Version 2.4.0

Merge commit 'f0240e91c93629cfb9f02b6307c11d787ae0b94b' into stable
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index d8c2687..ee25f1b 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,6 +1,26 @@
 Thank you for taking the time to file an issue!
 
-In order to route, prioritize, and act on this, please include:
+This tracker is for issues related to:
+
+* Analyzer
+* Common Front End (CFE) and kernel
+* Dart core libraries ("dart:async", "dart:io", etc.)
+* Dart VM
+* dart2js
+* dartfix
+* dev_compiler
+
+Some other pieces of the Dart ecosystem are maintained elsewhere. Please
+file issues in their repository:
+
+* Dart language: https://github.com/dart-lang/language
+* Dart website: https://github.com/dart-lang/site-www
+* Flutter: https://github.com/flutter/flutter
+* Linter: https://github.com/dart-lang/linter
+* dartfmt: https://github.com/dart-lang/dart_style
+
+If you aren't sure, file the issue here and we'll find the right home for it.
+In your issue, please include:
 
 * Dart SDK Version (`dart --version`)
 * Whether you are using Windows, MacOSX, or Linux (if applicable)
@@ -9,13 +29,10 @@
 Missing some or all of the above might make the issue take longer or be
 impossible to act on.
 
-----
+If you simply have a question, consider starting with Stack Overflow:
 
-Is it really an issue? For general questions consider starting with Stack
-Overflow:
 https://stackoverflow.com/questions/tagged/dart
 
-Also consider our Gitter channel for light-weight/quick discussions:
-https://gitter.im/dart-lang/sdk
+For a real-time response, consider our Gitter channel:
 
------
+https://gitter.im/dart-lang/sdk
diff --git a/.packages b/.packages
index c5944a1..37c475e 100644
--- a/.packages
+++ b/.packages
@@ -59,7 +59,9 @@
 meta:pkg/meta/lib
 mime:third_party/pkg/mime/lib
 mockito:third_party/pkg/mockito/lib
+modular_test:pkg/modular_test/lib
 mustache:third_party/pkg/mustache/lib
+nnbd_migration:pkg/nnbd_migration/lib
 oauth2:third_party/pkg/oauth2/lib
 observatory:runtime/observatory/lib
 observatory_test_package:runtime/observatory/tests/service/observatory_test_package
diff --git a/AUTHORS b/AUTHORS
index 27c9033..c61ecfc 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -4,6 +4,7 @@
 #   Name/Organization <email address>
 
 Google Inc.
+The V8 project authors
 
 Ola Martin Bini <ola.bini@gmail.com>
 Michael Haubenwallner <michael.haubenwallner@gmail.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 931efb2..b9554f5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,121 @@
-## 2.3.2
+## 2.4.0 - 2019-06-24
 
-* Cherry-pick 3972f738ca4e91104e2d6dad9bb1f36147879e98 to stable
+### Core libraries
+
+#### `dart:isolate`
+
+* `TransferableTypedData` class was added to facilitate faster cross-isolate
+communication of `Uint8List` data.
+
+* **Breaking change**: `Isolate.resolvePackageUri` will always throw an
+  `UnsupportedError` when compiled with dart2js or DDC. This was the only
+  remaining API in `dart:isolate` that didn't automatically throw since we
+  dropped support for this library in [Dart 2.0.0][1]. Note that the API already
+  throws in dart2js if the API is used directly without manually setting up a
+  `defaultPackagesBase` hook.
+
+[1]: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#200---2018-08-07
+
+
+#### `dart:developer`
+* Exposed `result`, `errorCode` and `errorDetail` getters in
+  `ServiceExtensionResponse` to allow for better debugging of VM service
+  extension RPC results.
+
+#### `dart:io`
+
+* Fixed `Cookie` class interoperability with certain websites by allowing the
+  cookie values to be the empty string (Issue [35804][]) and not stripping
+  double quotes from the value (Issue [33327][]) in accordance with RFC 6265.
+
+  [33327]: https://github.com/dart-lang/sdk/issues/33327
+  [35804]: https://github.com/dart-lang/sdk/issues/35804
+
+* The `HttpClientResponse` interface has been extended with the addition of a
+  new `compressionState` getter, which specifies whether the body of a
+  response was compressed when it was received and whether it has been
+  automatically uncompressed via `HttpClient.autoUncompress` (Issue [36971][]).
+
+  As part of this change, a corresponding new enum was added to `dart:io`:
+  `HttpClientResponseCompressionState`.
+
+  [36971]: https://github.com/dart-lang/sdk/issues/36971
+
+  * **Breaking change**: For those implementing the `HttpClientResponse`
+    interface, this is a breaking change, as implementing classes will need to
+    implement the new getter.
+
+#### `dart:async`
+
+* **Breaking change:** The `await for` allowed `null` as a stream due to a bug
+  in `StreamIterator` class. This bug has now been fixed.
+
+#### `dart:core`
+
+* **Breaking change:** The `RegExp` interface has been extended with two new
+  constructor named parameters:
+
+  * `unicode:` (`bool`, default: `false`), for Unicode patterns
+  * `dotAll:` (`bool`, default: `false`), to change the matching behavior of
+    '.' to also match line terminating characters.
+
+  Appropriate properties for these named parameters have also been added so
+  their use can be detected after construction.
+
+  In addition, `RegExp` methods that originally returned `Match` objects
+  now return a more specific subtype, `RegExpMatch`, which adds two features:
+
+  * `Iterable<String> groupNames`, a property that contains the names of all
+    named capture groups
+  * `String namedGroup(String name)`, a method that retrieves the match for
+    the given named capture group
+
+  This change only affects implementers of the `RegExp` interface; current
+  code using Dart regular expressions will not be affected.
+
+### Language
+
+*   **Breaking change:** Covariance of type variables used in super-interfaces
+    is now enforced (issue [35097][]).  For example, the following code was
+    previously accepted and will now be rejected:
+
+```dart
+class A<X> {};
+class B<X> extends A<void Function(X)> {};
+```
+
+* The identifier `async` can now be used in asynchronous and generator
+  functions.
+
+[35097]: https://github.com/dart-lang/sdk/issues/35097
+
+### Tools
+
+#### Linter
+
+The Linter was updated to `0.1.91`, which includes the following changes:
+
+* Fixed missed cases in `prefer_const_constructors`
+* Fixed `prefer_initializing_formals` to no longer suggest API breaking changes
+* Updated `omit_local_variable_types` to allow explicit `dynamic`s
+* Fixed null-reference in `unrelated_type_equality_checks`
+* New lint: `unsafe_html`
+* Broadened `prefer_null_aware_operators` to work beyond local variables.
+* Added `prefer_if_null_operators`.
+* Fixed `prefer_contains` false positives.
+* Fixed `unnecessary_parenthesis` false positives.
+* New lint: `prefer_double_quotes`
+* Fixed `prefer_asserts_in_initializer_lists` false positives
+* Fixed `curly_braces_in_flow_control_structures` to handle more cases
+* New lint: `prefer_double_quotes`
+* New lint: `sort_child_properties_last`
+* Fixed `type_annotate_public_apis` false positive for `static const` initializers
+
+#### Pub
+
+* `pub publish` will no longer warn about missing dependencies for import
+   statements in `example/`.
+* OAuth2 authentication will explicitely ask for the `openid` scope.
 
 ## 2.3.2 - 2019-06-11
 
@@ -270,7 +385,7 @@
   `.g.dart`, etc.).
 *   Fixed false positives in `unnecessary_parenthesis`.
 
-#### Pub client
+#### Pub
 
 *   Added a CHANGELOG validator that complains if you `pub publish` without
     mentioning the current version.
diff --git a/DEPS b/DEPS
index 0ad497f..81897b0 100644
--- a/DEPS
+++ b/DEPS
@@ -36,7 +36,7 @@
   "chromium_git": "https://chromium.googlesource.com",
   "fuchsia_git": "https://fuchsia.googlesource.com",
 
-  "co19_2_rev": "a0a24a4bd5e4d913264fccfd600139af5b20c8e9",
+  "co19_2_rev": "c4a8862775188ecb25991b815e2f1f700b19d0cc",
 
   # As Flutter does, we use Fuchsia's GN and Clang toolchain. These revision
   # should be kept up to date with the revisions pulled by the Flutter engine.
@@ -79,7 +79,7 @@
   #     and land the review.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-  "dart_style_tag": "1.2.7",  # Please see the note above before updating.
+  "dart_style_tag": "1.2.8",  # Please see the note above before updating.
 
   "dartdoc_tag" : "v0.28.2",
   "fixnum_tag": "0.10.9",
@@ -91,11 +91,12 @@
   "http_retry_tag": "0.1.1",
   "http_tag" : "0.12.0+2",
   "http_throttle_tag" : "1.0.2",
+  "icu_rev" : "c56c671998902fcc4fc9ace88c83daa99f980793",
   "idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
   "intl_tag": "0.15.7",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "2.0.9",
-  "linter_tag": "0.1.86",
+  "linter_tag": "0.1.91",
   "logging_tag": "0.11.3+2",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_tag": "2.0.3",
@@ -111,10 +112,10 @@
   "pedantic_tag": "v1.5.0",
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "1.3.6",
-  "protobuf_rev": "0c77167b16d00b561a6055bfe26690af7f26ae88",
-  "pub_rev": "8c363fe26f059c3063f1129adbb3c4e22a8ce954",
+  "protobuf_rev": "7d34c9e4e552a4f66acce32e4344ae27756a1949",
+  "pub_rev": "ecd5b413271f2699f8cd9e23aa4eebb5030c964f",
   "pub_semver_tag": "1.4.2",
-  "quiver_tag": "2.0.0+1",
+  "quiver-dart_tag": "2.0.0+1",
   "resource_rev": "2.1.5",
   "root_certificates_rev": "16ef64be64c7dfdff2b9f4b910726e635ccc519e",
   "shelf_static_rev": "v0.2.8",
@@ -132,7 +133,7 @@
   "test_process_tag": "1.0.3",
   "term_glyph_tag": "1.0.1",
   "test_reflective_loader_tag": "0.1.8",
-  "test_tag": "test-v1.6.1",
+  "test_tag": "test-v1.6.4",
   "typed_data_tag": "1.1.6",
   "unittest_rev": "2b8375bc98bb9dc81c539c91aaea6adce12e1072",
   "usage_tag": "3.4.0",
@@ -156,7 +157,7 @@
   Var("dart_root") + "/tools/sdks": {
       "packages": [{
           "package": "dart/dart-sdk/${{platform}}",
-          "version": "version:2.2.1-dev.3.1",
+          "version": "version:2.3.0",
       }],
       "dep_type": "cipd",
   },
@@ -167,7 +168,6 @@
       }],
       "dep_type": "cipd",
   },
-
   Var("dart_root") + "/tests/co19_2/src": {
       "packages": [{
           "package": "dart/third_party/co19",
@@ -175,11 +175,16 @@
       }],
       "dep_type": "cipd",
   },
-
   Var("dart_root") + "/third_party/markupsafe":
       Var("chromium_git") + "/chromium/src/third_party/markupsafe.git" +
       "@" + Var("markupsafe_rev"),
-
+  Var("dart_root") + "/third_party/babel": {
+      "packages": [{
+          "package": "dart/third_party/babel",
+          "version": "version:7.4.5",
+      }],
+      "dep_type": "cipd",
+  },
   Var("dart_root") + "/third_party/zlib":
       Var("chromium_git") + "/chromium/src/third_party/zlib.git" +
       "@" + Var("zlib_rev"),
@@ -210,6 +215,10 @@
       Var("chromium_git") + "/chromium/src/third_party/ply.git" +
       "@" + Var("ply_rev"),
 
+  Var("dart_root") + "/third_party/icu":
+      Var("chromium_git") + "/chromium/deps/icu.git" +
+      "@" + Var("icu_rev"),
+
   Var("dart_root") + "/tools/idl_parser":
       Var("chromium_git") + "/chromium/src/tools/idl_parser.git" +
       "@" + Var("idl_parser_rev"),
@@ -315,7 +324,7 @@
   Var("dart_root") + "/third_party/pkg/quiver":
       Var("chromium_git")
       + "/external/github.com/google/quiver-dart.git"
-      + "@" + Var("quiver_tag"),
+      + "@" + Var("quiver-dart_tag"),
   Var("dart_root") + "/third_party/pkg/resource":
       Var("dart_git") + "resource.git" + "@" + Var("resource_rev"),
   Var("dart_root") + "/third_party/pkg/shelf":
diff --git a/README.md b/README.md
index 51f129a..195667d 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,43 @@
 # Dart
 
-[Dart][website] is an open-source, scalable programming language, with robust
-libraries and runtimes, for building web, server, and mobile apps.
+## A client-optimized language for fast apps on any platform
+
+Dart is:
+
+  * **Optimized for UI**:
+  Develop with a programming language specialized around the needs of user interface creation
+  
+  * **Productive**:
+  Make changes iteratively: use hot reload to see the result instantly in your running app
+  
+  * **Fast on all platforms**:
+  Compile to ARM & x64 machine code for mobile,  desktop, and backend. Or compile to JavaScript for the web
+
+Dart has flexible compiler technology lets you run Dart code in different ways,
+depending on your target platform and goals:
+
+  * **Dart Native**: For programs targeting devices (mobile, desktop, server, and more),
+  Dart Native includes both a Dart VM with JIT (just-in-time) compilation and an
+  AOT (ahead-of-time) compiler for producing machine code.
+  
+  * **Dart Web**: For programs targeting the web, Dart Web includes both a development time
+  compiler (dartdevc) and a production time compiler (dart2js).  
+
+![Dart platforms illustration](https://dart.dev/assets/platforms-7f4d540acf9fe801b456ad74f9f855230a385014d05d9f5997c878b889a67a0f.svg)
+
+## License & patents
+
+Dart is free and open source.
+
+See [LICENSE][license] and [PATENTS][patents].
 
 ## Using Dart
 
-Visit the [dartlang.org][website] to learn more about the
+Visit the [dart.dev][website] to learn more about the
 [language][lang], [tools][tools],
 [getting started][codelab], and more.
 
-Browse [pub.dartlang.org][pubsite] for more packages and libraries contributed
+Browse [pub.dev][pubsite] for more packages and libraries contributed
 by the community and the Dart team.
 
 ## Building Dart
@@ -26,11 +54,7 @@
 
 You can also contribute patches, as described in [Contributing][contrib].
 
-## License & patents
-
-See [LICENSE][license] and [PATENTS][patents].
-
-[website]: https://www.dartlang.org
+[website]: https://dart.dev
 [license]: https://github.com/dart-lang/sdk/blob/master/LICENSE
 [repo]: https://github.com/dart-lang/sdk
 [lang]: https://www.dartlang.org/docs/dart-up-and-running/ch02.html
@@ -38,6 +62,5 @@
 [codelab]: https://www.dartlang.org/codelabs/darrrt/
 [dartbug]: http://dartbug.com
 [contrib]: https://github.com/dart-lang/sdk/wiki/Contributing
-[pubsite]: https://pub.dartlang.org
+[pubsite]: https://pub.dev
 [patents]: https://github.com/dart-lang/sdk/blob/master/PATENTS
-
diff --git a/WATCHLISTS b/WATCHLISTS
index 538f457..ea5b5d0 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -21,9 +21,6 @@
     'front_end': {
       'filepath': '^pkg/front_end',
     },
-    'http': {
-      'filepath': '^sdk/lib/_http',
-    },
     'kernel': {
       'filepath': '^pkg/kernel',
     },
@@ -68,11 +65,10 @@
   },
 
   'WATCHLISTS': {
-    'build': [ 'zra@google.com', 'keertip@google.com' ],
+    'build': [ 'keertip@google.com' ],
     'dart2js': [ 'johnniwinther@google.com', 'sigmund@google.com',
                  'sra@google.com'],
     'front_end': [ 'dart-fe-team+reviews@google.com' ],
-    'http': [ 'zra@google.com' ],
     'kernel': [ 'karlklose@google.com', 'jensj@google.com', 'kmillikin@google.com',
                 'alexmarkov@google.com' ],
     'messages_review': [ 'dart-uxr+reviews@google.com' ],
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index 38e3f8e..c61d41a 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -15,6 +15,9 @@
     android_sdk_root = default_android_sdk_root
     android_sdk_version = default_android_sdk_version
     android_sdk_build_tools_version = default_android_sdk_build_tools_version
+
+    # Unused by Dart. Required for GN files in the third_party package ICU.
+    enable_java_templates = false
   }
 
   # Host stuff -----------------------------------------------------------------
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
new file mode 100644
index 0000000..f22ba84
--- /dev/null
+++ b/build/config/android/rules.gni
@@ -0,0 +1,10 @@
+# Copyright (c) 2019, 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.
+
+# A trivial rules file that allows for the Chromium third_party ICU to
+# be built successfully.
+
+import("//build/config/android/config.gni")
+
+assert(is_android)
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 0a6a259..f073da1 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -433,8 +433,10 @@
     ]
   }
 
-  # Android standard library setup.
-  if (is_android) {
+  if (is_linux) {
+    libs += [ "dl" ]
+  } else if (is_android) {
+    # Android standard library setup.
     if (is_clang) {
       # Work around incompatibilities between bionic and clang headers.
       defines += [ "__compiler_offsetof=__builtin_offsetof" ]
@@ -594,7 +596,7 @@
     ]
 
     defines = []
-    if (!using_sanitizer && (!is_linux || !is_clang)) {
+    if (!using_sanitizer && !is_clang) {
       # _FORTIFY_SOURCE isn't really supported by Clang now, see
       # http://llvm.org/bugs/show_bug.cgi?id=16821.
       # It seems to work fine with Ubuntu 12 headers though, so use it in
diff --git a/build/config/host_byteorder.gni b/build/config/host_byteorder.gni
new file mode 100644
index 0000000..50ea94b
--- /dev/null
+++ b/build/config/host_byteorder.gni
@@ -0,0 +1,30 @@
+# Copyright (c) 2017 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.
+
+# Originally from v8, included in our repository as the ICU third party
+# import depends on it for building.
+
+# This header file defines the "host_byteorder" variable.
+# Not that this is currently used only for building v8.
+# The chromium code generally assumes little-endianness.
+declare_args() {
+  host_byteorder = "undefined"
+}
+
+# Detect host byteorder
+# ppc64 can be either BE or LE
+if (host_cpu == "ppc64") {
+  if (current_os == "aix") {
+    host_byteorder = "big"
+  } else {
+    # Only use the script when absolutely necessary
+    host_byteorder =
+        exec_script("//build/config/get_host_byteorder.py", [], "trim string")
+  }
+} else if (host_cpu == "ppc" || host_cpu == "s390" || host_cpu == "s390x" ||
+           host_cpu == "mips" || host_cpu == "mips64") {
+  host_byteorder = "big"
+} else {
+  host_byteorder = "little"
+}
diff --git a/build/executable_suffix.gni b/build/executable_suffix.gni
index e2b0dd8..ca69d39 100644
--- a/build/executable_suffix.gni
+++ b/build/executable_suffix.gni
@@ -2,7 +2,7 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-if (defined(is_win) && is_win) {
+if (host_os == "win") {
   executable_suffix = ".exe"
 } else {
   executable_suffix = ""
diff --git a/build/gn_run_binary.py b/build/gn_run_binary.py
index f6f9bac..718bf24 100755
--- a/build/gn_run_binary.py
+++ b/build/gn_run_binary.py
@@ -48,7 +48,7 @@
     path = './' + argv[2]
 
   if not os.path.isfile(path):
-    print "Binary not found: " + path
+    print ("Binary not found: " + path)
     return error_exit
 
   # The rest of the arguments are passed directly to the executable.
@@ -56,7 +56,7 @@
 
   result = run_command(args)
   if result != 0:
-    print result
+    print (result)
     return error_exit
   return 0
 
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 204d162..2635ca1 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  1.26.0
+  1.27.1
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -1455,6 +1455,7 @@
   
   
   
+  
 <h3>Requests</h3><dl><dt class="request"><a name="request_completion.getSuggestions">completion.getSuggestions</a></dt><dd><div class="box"><pre>request: {
   "id": String
   "method": "completion.getSuggestions"
@@ -1612,6 +1613,7 @@
     "<b>replacementLength</b>": int
     "<b>results</b>": List&lt;<a href="#type_CompletionSuggestion">CompletionSuggestion</a>&gt;
     "<b>isLast</b>": bool
+    "<b>libraryFile</b>": <span style="color:#999999">optional</span> <a href="#type_FilePath">FilePath</a>
     "<b>includedSuggestionSets</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>&gt;
     "<b>includedElementKinds</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_ElementKind">ElementKind</a>&gt;
     "<b>includedSuggestionRelevanceTags</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a>&gt;
@@ -1663,6 +1665,16 @@
           True if this is that last set of results that will be
           returned for the indicated completion.
         </p>
+      </dd><dt class="field"><b>libraryFile: <a href="#type_FilePath">FilePath</a><span style="color:#999999"> (optional)</span></b></dt><dd>
+        
+        <p>
+          The library file that contains the file where completion was
+          requested. The client might use it for example together with the
+          <tt>existingImports</tt> notification to filter out available
+          suggestions. If there were changes to existing imports in the library,
+          the corresponding <tt>existingImports</tt> notification will be sent
+          before the completion notification.
+        </p>
       </dd><dt class="field"><b>includedSuggestionSets: List&lt;<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>&gt;<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
@@ -1720,6 +1732,29 @@
         <p>
           A list of library ids that no longer apply.
         </p>
+      </dd></dl></dd><dt class="notification"><a name="notification_completion.existingImports">completion.existingImports</a></dt><dd><div class="box"><pre>notification: {
+  "event": "completion.existingImports"
+  "params": {
+    "<b>file</b>": <a href="#type_FilePath">FilePath</a>
+    "<b>imports</b>": <a href="#type_ExistingImports">ExistingImports</a>
+  }
+}</pre></div>
+    <p>
+      Reports existing imports in a library. This notification may be sent
+      multiple times for a library. When a notification is processed, clients
+      should replace any previous information for the library.
+    </p>
+    
+  <h4>parameters:</h4><dl><dt class="field"><b>file: <a href="#type_FilePath">FilePath</a></b></dt><dd>
+        
+        <p>
+          The defining file of the library.
+        </p>
+      </dd><dt class="field"><b>imports: <a href="#type_ExistingImports">ExistingImports</a></b></dt><dd>
+        
+        <p>
+          The existing imports in the library.
+        </p>
       </dd></dl></dd></dl>
 <h2 class="domain"><a name="domain_search">search domain</a></h2>
   <p>
@@ -2833,6 +2868,9 @@
   
   
   
+  
+  
+  
 <dl><dt class="typeDefinition"><a name="type_AddContentOverlay">AddContentOverlay: object</a></dt><dd>
     <p>
       A directive to begin overlaying the contents of a file. The supplied
@@ -2896,6 +2934,12 @@
         <p>
           The URL of a page containing documentation associated with this error.
         </p>
+      </dd><dt class="field"><b>contextMessages: List&lt;<a href="#type_DiagnosticMessage">DiagnosticMessage</a>&gt;<span style="color:#999999"> (optional)</span></b></dt><dd>
+        
+        <p>
+          Additional messages associated with this diagnostic that provide
+          context to help the user understand the diagnostic.
+        </p>
       </dd><dt class="field"><b>hasFix: bool<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
@@ -3033,6 +3077,13 @@
         <p>
           The identifier to present to the user for code completion.
         </p>
+      </dd><dt class="field"><b>declaringLibraryUri: String</b></dt><dd>
+        
+        <p>
+          The URI of the library that declares the element being suggested,
+          not the URI of the library associated with the enclosing
+          <tt>AvailableSuggestionSet</tt>.
+        </p>
       </dd><dt class="field"><b>element: <a href="#type_Element">Element</a></b></dt><dd>
         
         <p>
@@ -3176,11 +3227,15 @@
   <dl><dt class="value">AVAILABLE_SUGGESTION_SETS</dt><dd>
         
         <p>
-          The client will receive notifications once subscribed with completion suggestion sets from
-          the libraries of interest. The client should keep an up-to-date record of these in
+          The client will receive <tt>availableSuggestions</tt> notifications
+          once subscribed with completion suggestion sets from the libraries of
+          interest. The client should keep an up-to-date record of these in
           memory so that it will be able to union these candidates with other
           completion suggestions when applicable at completion time.
         </p>
+        <p>
+          The client will also receive <tt>existingImports</tt> notifications.
+        </p>
       </dd></dl></dd><dt class="typeDefinition"><a name="type_CompletionSuggestion">CompletionSuggestion: object</a></dt><dd>
     <p>
       A suggestion for how to complete partially entered text. Many of the
@@ -3402,6 +3457,27 @@
         <p>
           Exceptions associated with cache entries.
         </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_DiagnosticMessage">DiagnosticMessage: object</a></dt><dd>
+    <p>
+      A message associated with a diagnostic.
+    </p>
+    <p>
+      For example, if the diagnostic is reporting that a variable has been
+      referenced before it was declared, it might have a diagnostic message that
+      indicates where the variable is declared.
+    </p>
+    
+  <dl><dt class="field"><b>message: String</b></dt><dd>
+        
+        <p>
+          The message to be displayed to the user.
+        </p>
+      </dd><dt class="field"><b>location: <a href="#type_Location">Location</a></b></dt><dd>
+        
+        <p>
+          The location associated with or referenced by the message. Clients
+          should provide the ability to navigate to the location.
+        </p>
       </dd></dl></dd><dt class="typeDefinition"><a name="type_Element">Element: object</a></dt><dd>
     <p>
       Information about an element (something that can be declared in code).
@@ -3575,7 +3651,40 @@
       domain.
     </p>
     
-  <dl><dt class="value">LAUNCH_DATA</dt></dl></dd><dt class="typeDefinition"><a name="type_FileKind">FileKind: String</a></dt><dd>
+  <dl><dt class="value">LAUNCH_DATA</dt></dl></dd><dt class="typeDefinition"><a name="type_ExistingImport">ExistingImport: object</a></dt><dd>
+    <p>
+      Information about an existing import, with elements that it provides.
+    </p>
+    
+  <dl><dt class="field"><b>uri: int</b></dt><dd>
+        
+        <p>
+          The URI of the imported library.
+          It is an index in the <tt>strings</tt> field, in the enclosing
+          <tt>ExistingImports</tt> and its <tt>ImportedElementSet</tt> object.
+        </p>
+      </dd><dt class="field"><b>elements: List&lt;int&gt;</b></dt><dd>
+        
+        <p>
+          The list of indexes of elements, in the enclosing
+          <tt>ExistingImports</tt> object.
+        </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_ExistingImports">ExistingImports: object</a></dt><dd>
+    <p>
+      Information about all existing imports in a library.
+    </p>
+    
+  <dl><dt class="field"><b>elements: <a href="#type_ImportedElementSet">ImportedElementSet</a></b></dt><dd>
+        
+        <p>
+          The set of all unique imported elements for all imports.
+        </p>
+      </dd><dt class="field"><b>imports: List&lt;<a href="#type_ExistingImport">ExistingImport</a>&gt;</b></dt><dd>
+        
+        <p>
+          The list of imports in the library.
+        </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_FileKind">FileKind: String</a></dt><dd>
     <p>
       An enumeration of the kinds of files.
     </p>
@@ -3824,10 +3933,10 @@
       </dd><dt class="field"><b>containingLibraryName: String<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
-          The name of the library in which the referenced element is
-          declared. This data is omitted if there is no referenced
-          element, or if the element is declared inside an HTML
-          file.
+          The URI of the containing library, examples here include
+          "dart:core", "package:.." and file uris represented by the
+          path on disk, "/..". The data is omitted if the element is
+          declared inside an HTML file.
         </p>
       </dd><dt class="field"><b>containingClassDescription: String<span style="color:#999999"> (optional)</span></b></dt><dd>
         
@@ -3918,6 +4027,30 @@
         <p>
           The length of the name of the implemented member.
         </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_ImportedElementSet">ImportedElementSet: object</a></dt><dd>
+    <p>
+      The set of top-level elements encoded as pairs of the defining library
+      URI and the name, and stored in the parallel lists <tt>elementUris</tt>
+      and <tt>elementNames</tt>.
+    </p>
+    
+  <dl><dt class="field"><b>strings: List&lt;String&gt;</b></dt><dd>
+        
+        <p>
+          The list of unique strings in this object.
+        </p>
+      </dd><dt class="field"><b>uris: List&lt;int&gt;</b></dt><dd>
+        
+        <p>
+          The library URI part of the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
+      </dd><dt class="field"><b>names: List&lt;int&gt;</b></dt><dd>
+        
+        <p>
+          The name part of a the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
       </dd></dl></dd><dt class="typeDefinition"><a name="type_ImportedElements">ImportedElements: object</a></dt><dd>
     <p>
       A description of the elements that are referenced in a region of a file
@@ -5403,7 +5536,7 @@
   TODO: TBD
 </p>
 <h2 class="domain"><a name="index">Index</a></h2>
-<h3>Domains</h3><h4>server (<a href="#domain_server">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_server.getVersion">getVersion</a></li><li><a href="#request_server.shutdown">shutdown</a></li><li><a href="#request_server.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_server.connected">connected</a></li><li><a href="#notification_server.error">error</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li><li><a href="#request_completion.setSubscriptions">setSubscriptions</a></li><li><a href="#request_completion.registerLibraryPaths">registerLibraryPaths</a></li><li><a href="#request_completion.getSuggestionDetails">getSuggestionDetails</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li><li><a href="#notification_completion.availableSuggestions">availableSuggestions</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getRefactoring">getRefactoring</a></li><li><a href="#request_edit.sortMembers">sortMembers</a></li><li><a href="#request_edit.organizeDirectives">organizeDirectives</a></li></ul></div><h4>execution (<a href="#domain_execution">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_execution.createContext">createContext</a></li><li><a href="#request_execution.deleteContext">deleteContext</a></li><li><a href="#request_execution.getSuggestions">getSuggestions</a></li><li><a href="#request_execution.mapUri">mapUri</a></li><li><a href="#request_execution.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_execution.launchData">launchData</a></li></ul></div></div><h4>diagnostic (<a href="#domain_diagnostic">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_diagnostic.getDiagnostics">getDiagnostics</a></li><li><a href="#request_diagnostic.getServerPort">getServerPort</a></li></ul></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_AvailableSuggestion">AvailableSuggestion</a></li><li><a href="#type_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag</a></li><li><a href="#type_AvailableSuggestionSet">AvailableSuggestionSet</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</a></li><li><a href="#type_CompletionService">CompletionService</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a></li><li><a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LibraryPathSet">LibraryPathSet</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_RuntimeCompletionExpression">RuntimeCompletionExpression</a></li><li><a href="#type_RuntimeCompletionExpressionType">RuntimeCompletionExpressionType</a></li><li><a href="#type_RuntimeCompletionExpressionTypeKind">RuntimeCompletionExpressionTypeKind</a></li><li><a href="#type_RuntimeCompletionVariable">RuntimeCompletionVariable</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_EXTRACT_WIDGET">EXTRACT_WIDGET</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
+<h3>Domains</h3><h4>server (<a href="#domain_server">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_server.getVersion">getVersion</a></li><li><a href="#request_server.shutdown">shutdown</a></li><li><a href="#request_server.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_server.connected">connected</a></li><li><a href="#notification_server.error">error</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li><li><a href="#request_completion.setSubscriptions">setSubscriptions</a></li><li><a href="#request_completion.registerLibraryPaths">registerLibraryPaths</a></li><li><a href="#request_completion.getSuggestionDetails">getSuggestionDetails</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li><li><a href="#notification_completion.availableSuggestions">availableSuggestions</a></li><li><a href="#notification_completion.existingImports">existingImports</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getRefactoring">getRefactoring</a></li><li><a href="#request_edit.sortMembers">sortMembers</a></li><li><a href="#request_edit.organizeDirectives">organizeDirectives</a></li></ul></div><h4>execution (<a href="#domain_execution">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_execution.createContext">createContext</a></li><li><a href="#request_execution.deleteContext">deleteContext</a></li><li><a href="#request_execution.getSuggestions">getSuggestions</a></li><li><a href="#request_execution.mapUri">mapUri</a></li><li><a href="#request_execution.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_execution.launchData">launchData</a></li></ul></div></div><h4>diagnostic (<a href="#domain_diagnostic">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_diagnostic.getDiagnostics">getDiagnostics</a></li><li><a href="#request_diagnostic.getServerPort">getServerPort</a></li></ul></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_AvailableSuggestion">AvailableSuggestion</a></li><li><a href="#type_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag</a></li><li><a href="#type_AvailableSuggestionSet">AvailableSuggestionSet</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</a></li><li><a href="#type_CompletionService">CompletionService</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_ExistingImport">ExistingImport</a></li><li><a href="#type_ExistingImports">ExistingImports</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElementSet">ImportedElementSet</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a></li><li><a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LibraryPathSet">LibraryPathSet</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_RuntimeCompletionExpression">RuntimeCompletionExpression</a></li><li><a href="#type_RuntimeCompletionExpressionType">RuntimeCompletionExpressionType</a></li><li><a href="#type_RuntimeCompletionExpressionTypeKind">RuntimeCompletionExpressionTypeKind</a></li><li><a href="#type_RuntimeCompletionVariable">RuntimeCompletionVariable</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_EXTRACT_WIDGET">EXTRACT_WIDGET</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
 
 
 </body></html>
\ No newline at end of file
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
index dc8817d..deb8901 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
@@ -10,10 +10,12 @@
 // ignore_for_file: deprecated_member_use_from_same_package
 // ignore_for_file: unnecessary_brace_in_string_interps
 // ignore_for_file: unused_import
+// ignore_for_file: unused_shown_name
 
 import 'dart:core' hide deprecated;
 import 'dart:core' as core show deprecated;
 import 'dart:convert' show JsonEncoder;
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/protocol/protocol_internal.dart'
     show listEqual, mapEqual;
@@ -21,7 +23,218 @@
 
 const jsonEncoder = const JsonEncoder.withIndent('    ');
 
+class AnalyzerStatusParams implements ToJsonable {
+  static const jsonHandler = const LspJsonHandler(
+      AnalyzerStatusParams.canParse, AnalyzerStatusParams.fromJson);
+
+  AnalyzerStatusParams(this.isAnalyzing) {
+    if (isAnalyzing == null) {
+      throw 'isAnalyzing is required but was not provided';
+    }
+  }
+  static AnalyzerStatusParams fromJson(Map<String, dynamic> json) {
+    final isAnalyzing = json['isAnalyzing'];
+    return new AnalyzerStatusParams(isAnalyzing);
+  }
+
+  final bool isAnalyzing;
+
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> __result = {};
+    __result['isAnalyzing'] =
+        isAnalyzing ?? (throw 'isAnalyzing is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj) {
+    return obj is Map<String, dynamic> &&
+        obj.containsKey('isAnalyzing') &&
+        obj['isAnalyzing'] is bool;
+  }
+
+  @override
+  bool operator ==(other) {
+    if (other is AnalyzerStatusParams) {
+      return isAnalyzing == other.isAnalyzing && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, isAnalyzing.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class ClosingLabel implements ToJsonable {
+  static const jsonHandler =
+      const LspJsonHandler(ClosingLabel.canParse, ClosingLabel.fromJson);
+
+  ClosingLabel(this.range, this.label) {
+    if (range == null) {
+      throw 'range is required but was not provided';
+    }
+    if (label == null) {
+      throw 'label is required but was not provided';
+    }
+  }
+  static ClosingLabel fromJson(Map<String, dynamic> json) {
+    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
+    final label = json['label'];
+    return new ClosingLabel(range, label);
+  }
+
+  final String label;
+  final Range range;
+
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> __result = {};
+    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['label'] = label ?? (throw 'label is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj) {
+    return obj is Map<String, dynamic> &&
+        obj.containsKey('range') &&
+        Range.canParse(obj['range']) &&
+        obj.containsKey('label') &&
+        obj['label'] is String;
+  }
+
+  @override
+  bool operator ==(other) {
+    if (other is ClosingLabel) {
+      return range == other.range && label == other.label && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, range.hashCode);
+    hash = JenkinsSmiHash.combine(hash, label.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class CompletionItemResolutionInfo implements ToJsonable {
+  static const jsonHandler = const LspJsonHandler(
+      CompletionItemResolutionInfo.canParse,
+      CompletionItemResolutionInfo.fromJson);
+
+  CompletionItemResolutionInfo(this.file, this.offset, this.libId,
+      this.displayUri, this.rOffset, this.rLength) {
+    if (file == null) {
+      throw 'file is required but was not provided';
+    }
+    if (offset == null) {
+      throw 'offset is required but was not provided';
+    }
+    if (libId == null) {
+      throw 'libId is required but was not provided';
+    }
+    if (displayUri == null) {
+      throw 'displayUri is required but was not provided';
+    }
+    if (rOffset == null) {
+      throw 'rOffset is required but was not provided';
+    }
+    if (rLength == null) {
+      throw 'rLength is required but was not provided';
+    }
+  }
+  static CompletionItemResolutionInfo fromJson(Map<String, dynamic> json) {
+    final file = json['file'];
+    final offset = json['offset'];
+    final libId = json['libId'];
+    final displayUri = json['displayUri'];
+    final rOffset = json['rOffset'];
+    final rLength = json['rLength'];
+    return new CompletionItemResolutionInfo(
+        file, offset, libId, displayUri, rOffset, rLength);
+  }
+
+  final String displayUri;
+  final String file;
+  final num libId;
+  final num offset;
+  final num rLength;
+  final num rOffset;
+
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> __result = {};
+    __result['file'] = file ?? (throw 'file is required but was not set');
+    __result['offset'] = offset ?? (throw 'offset is required but was not set');
+    __result['libId'] = libId ?? (throw 'libId is required but was not set');
+    __result['displayUri'] =
+        displayUri ?? (throw 'displayUri is required but was not set');
+    __result['rOffset'] =
+        rOffset ?? (throw 'rOffset is required but was not set');
+    __result['rLength'] =
+        rLength ?? (throw 'rLength is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj) {
+    return obj is Map<String, dynamic> &&
+        obj.containsKey('file') &&
+        obj['file'] is String &&
+        obj.containsKey('offset') &&
+        obj['offset'] is num &&
+        obj.containsKey('libId') &&
+        obj['libId'] is num &&
+        obj.containsKey('displayUri') &&
+        obj['displayUri'] is String &&
+        obj.containsKey('rOffset') &&
+        obj['rOffset'] is num &&
+        obj.containsKey('rLength') &&
+        obj['rLength'] is num;
+  }
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionItemResolutionInfo) {
+      return file == other.file &&
+          offset == other.offset &&
+          libId == other.libId &&
+          displayUri == other.displayUri &&
+          rOffset == other.rOffset &&
+          rLength == other.rLength &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, file.hashCode);
+    hash = JenkinsSmiHash.combine(hash, offset.hashCode);
+    hash = JenkinsSmiHash.combine(hash, libId.hashCode);
+    hash = JenkinsSmiHash.combine(hash, displayUri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, rOffset.hashCode);
+    hash = JenkinsSmiHash.combine(hash, rLength.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class DartDiagnosticServer implements ToJsonable {
+  static const jsonHandler = const LspJsonHandler(
+      DartDiagnosticServer.canParse, DartDiagnosticServer.fromJson);
+
   DartDiagnosticServer(this.port) {
     if (port == null) {
       throw 'port is required but was not provided';
@@ -64,3 +277,66 @@
   @override
   String toString() => jsonEncoder.convert(toJson());
 }
+
+class PublishClosingLabelsParams implements ToJsonable {
+  static const jsonHandler = const LspJsonHandler(
+      PublishClosingLabelsParams.canParse, PublishClosingLabelsParams.fromJson);
+
+  PublishClosingLabelsParams(this.uri, this.labels) {
+    if (uri == null) {
+      throw 'uri is required but was not provided';
+    }
+    if (labels == null) {
+      throw 'labels is required but was not provided';
+    }
+  }
+  static PublishClosingLabelsParams fromJson(Map<String, dynamic> json) {
+    final uri = json['uri'];
+    final labels = json['labels']
+        ?.map((item) => item != null ? ClosingLabel.fromJson(item) : null)
+        ?.cast<ClosingLabel>()
+        ?.toList();
+    return new PublishClosingLabelsParams(uri, labels);
+  }
+
+  final List<ClosingLabel> labels;
+  final String uri;
+
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> __result = {};
+    __result['uri'] = uri ?? (throw 'uri is required but was not set');
+    __result['labels'] = labels ?? (throw 'labels is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj) {
+    return obj is Map<String, dynamic> &&
+        obj.containsKey('uri') &&
+        obj['uri'] is String &&
+        obj.containsKey('labels') &&
+        (obj['labels'] is List &&
+            (obj['labels'].every((item) => ClosingLabel.canParse(item))));
+  }
+
+  @override
+  bool operator ==(other) {
+    if (other is PublishClosingLabelsParams) {
+      return uri == other.uri &&
+          listEqual(labels, other.labels,
+              (ClosingLabel a, ClosingLabel b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, labels.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index 116d1e3..af4a262 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -10,10 +10,12 @@
 // ignore_for_file: deprecated_member_use_from_same_package
 // ignore_for_file: unnecessary_brace_in_string_interps
 // ignore_for_file: unused_import
+// ignore_for_file: unused_shown_name
 
 import 'dart:core' hide deprecated;
 import 'dart:core' as core show deprecated;
 import 'dart:convert' show JsonEncoder;
+import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/protocol/protocol_internal.dart'
     show listEqual, mapEqual;
@@ -84,36 +86,48 @@
   static const jsonHandler = const LspJsonHandler(
       ApplyWorkspaceEditResponse.canParse, ApplyWorkspaceEditResponse.fromJson);
 
-  ApplyWorkspaceEditResponse(this.applied) {
+  ApplyWorkspaceEditResponse(this.applied, this.failureReason) {
     if (applied == null) {
       throw 'applied is required but was not provided';
     }
   }
   static ApplyWorkspaceEditResponse fromJson(Map<String, dynamic> json) {
     final applied = json['applied'];
-    return new ApplyWorkspaceEditResponse(applied);
+    final failureReason = json['failureReason'];
+    return new ApplyWorkspaceEditResponse(applied, failureReason);
   }
 
   /// Indicates whether the edit was applied or not.
   final bool applied;
 
+  /// An optional textual description for why the edit was not applied. This may
+  /// be used may be used by the server for diagnostic logging or to provide a
+  /// suitable error for a request that triggered the edit.
+  final String failureReason;
+
   Map<String, dynamic> toJson() {
     Map<String, dynamic> __result = {};
     __result['applied'] =
         applied ?? (throw 'applied is required but was not set');
+    if (failureReason != null) {
+      __result['failureReason'] = failureReason;
+    }
     return __result;
   }
 
   static bool canParse(Object obj) {
     return obj is Map<String, dynamic> &&
         obj.containsKey('applied') &&
-        obj['applied'] is bool;
+        obj['applied'] is bool &&
+        (obj['failureReason'] == null || obj['failureReason'] is String);
   }
 
   @override
   bool operator ==(other) {
     if (other is ApplyWorkspaceEditResponse) {
-      return applied == other.applied && true;
+      return applied == other.applied &&
+          failureReason == other.failureReason &&
+          true;
     }
     return false;
   }
@@ -122,6 +136,7 @@
   int get hashCode {
     int hash = 0;
     hash = JenkinsSmiHash.combine(hash, applied.hashCode);
+    hash = JenkinsSmiHash.combine(hash, failureReason.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -1497,7 +1512,9 @@
         json['commitCharacters']?.map((item) => item)?.cast<String>()?.toList();
     final command =
         json['command'] != null ? Command.fromJson(json['command']) : null;
-    final data = json['data'];
+    final data = json['data'] != null
+        ? CompletionItemResolutionInfo.fromJson(json['data'])
+        : null;
     return new CompletionItem(
         label,
         kind,
@@ -1536,9 +1553,9 @@
   /// will be ignored.
   final List<String> commitCharacters;
 
-  /// An data entry field that is preserved on a completion item between a
+  /// A data entry field that is preserved on a completion item between a
   /// completion and a completion resolve request.
-  final dynamic data;
+  final CompletionItemResolutionInfo data;
 
   /// Indicates if this item is deprecated.
   final bool deprecated;
@@ -1572,7 +1589,8 @@
   final InsertTextFormat insertTextFormat;
 
   /// The kind of this completion item. Based of the kind an icon is chosen by
-  /// the editor.
+  /// the editor. The standardized set of available values is defined in
+  /// `CompletionItemKind`.
   final CompletionItemKind kind;
 
   /// The label of this completion item. By default also the text that is
@@ -1670,7 +1688,8 @@
             (obj['commitCharacters'] is List &&
                 (obj['commitCharacters'].every((item) => item is String)))) &&
         (obj['command'] == null || Command.canParse(obj['command'])) &&
-        (obj['data'] == null || true);
+        (obj['data'] == null ||
+            CompletionItemResolutionInfo.canParse(obj['data']));
   }
 
   @override
@@ -1992,22 +2011,34 @@
       CompletionRegistrationOptions.canParse,
       CompletionRegistrationOptions.fromJson);
 
-  CompletionRegistrationOptions(
-      this.triggerCharacters, this.resolveProvider, this.documentSelector);
+  CompletionRegistrationOptions(this.triggerCharacters,
+      this.allCommitCharacters, this.resolveProvider, this.documentSelector);
   static CompletionRegistrationOptions fromJson(Map<String, dynamic> json) {
     final triggerCharacters = json['triggerCharacters']
         ?.map((item) => item)
         ?.cast<String>()
         ?.toList();
+    final allCommitCharacters = json['allCommitCharacters']
+        ?.map((item) => item)
+        ?.cast<String>()
+        ?.toList();
     final resolveProvider = json['resolveProvider'];
     final documentSelector = json['documentSelector']
         ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
         ?.cast<DocumentFilter>()
         ?.toList();
-    return new CompletionRegistrationOptions(
-        triggerCharacters, resolveProvider, documentSelector);
+    return new CompletionRegistrationOptions(triggerCharacters,
+        allCommitCharacters, resolveProvider, documentSelector);
   }
 
+  /// The list of all possible characters that commit a completion. This field
+  /// can be used if clients don't support individual commmit characters per
+  /// completion item. See
+  /// `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport`
+  ///
+  /// Since 3.2.0
+  final List<String> allCommitCharacters;
+
   /// A document selector to identify the scope of the registration. If set to
   /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
@@ -2033,6 +2064,9 @@
     if (triggerCharacters != null) {
       __result['triggerCharacters'] = triggerCharacters;
     }
+    if (allCommitCharacters != null) {
+      __result['allCommitCharacters'] = allCommitCharacters;
+    }
     if (resolveProvider != null) {
       __result['resolveProvider'] = resolveProvider;
     }
@@ -2045,6 +2079,10 @@
         (obj['triggerCharacters'] == null ||
             (obj['triggerCharacters'] is List &&
                 (obj['triggerCharacters'].every((item) => item is String)))) &&
+        (obj['allCommitCharacters'] == null ||
+            (obj['allCommitCharacters'] is List &&
+                (obj['allCommitCharacters']
+                    .every((item) => item is String)))) &&
         (obj['resolveProvider'] == null || obj['resolveProvider'] is bool) &&
         obj.containsKey('documentSelector') &&
         (obj['documentSelector'] == null ||
@@ -2058,6 +2096,8 @@
     if (other is CompletionRegistrationOptions) {
       return listEqual(triggerCharacters, other.triggerCharacters,
               (String a, String b) => a == b) &&
+          listEqual(allCommitCharacters, other.allCommitCharacters,
+              (String a, String b) => a == b) &&
           resolveProvider == other.resolveProvider &&
           documentSelector == other.documentSelector &&
           true;
@@ -2069,6 +2109,7 @@
   int get hashCode {
     int hash = 0;
     hash = JenkinsSmiHash.combine(hash, triggerCharacters.hashCode);
+    hash = JenkinsSmiHash.combine(hash, allCommitCharacters.hashCode);
     hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode);
     hash = JenkinsSmiHash.combine(hash, documentSelector.hashCode);
     return JenkinsSmiHash.finish(hash);
@@ -2889,8 +2930,7 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
-/// Describe options to be used when registering for text document change
-/// events.
+/// Describe options to be used when registering for file system change events.
 class DidChangeWatchedFilesRegistrationOptions implements ToJsonable {
   static const jsonHandler = const LspJsonHandler(
       DidChangeWatchedFilesRegistrationOptions.canParse,
@@ -7077,7 +7117,8 @@
   final Either2<num, String> id;
   final String jsonrpc;
 
-  /// The result of a request. This can be omitted in the case of an error.
+  /// The result of a request. This member is REQUIRED on success. This member
+  /// MUST NOT exist if there was an error invoking the method.
   final dynamic result;
 
   Map<String, dynamic> toJson() {
@@ -7202,6 +7243,7 @@
       this.documentLinkProvider,
       this.colorProvider,
       this.foldingRangeProvider,
+      this.declarationProvider,
       this.executeCommandProvider,
       this.workspace,
       this.experimental);
@@ -7226,12 +7268,8 @@
         ? SignatureHelpOptions.fromJson(json['signatureHelpProvider'])
         : null;
     final definitionProvider = json['definitionProvider'];
-    final typeDefinitionProvider = json['typeDefinitionProvider'] is bool
-        ? new Either2<bool, dynamic>.t1(json['typeDefinitionProvider'])
-        : (new Either2<bool, dynamic>.t2(json['typeDefinitionProvider']));
-    final implementationProvider = json['implementationProvider'] is bool
-        ? new Either2<bool, dynamic>.t1(json['implementationProvider'])
-        : (new Either2<bool, dynamic>.t2(json['implementationProvider']));
+    final typeDefinitionProvider = json['typeDefinitionProvider'];
+    final implementationProvider = json['implementationProvider'];
     final referencesProvider = json['referencesProvider'];
     final documentHighlightProvider = json['documentHighlightProvider'];
     final documentSymbolProvider = json['documentSymbolProvider'];
@@ -7269,27 +7307,9 @@
     final documentLinkProvider = json['documentLinkProvider'] != null
         ? DocumentLinkOptions.fromJson(json['documentLinkProvider'])
         : null;
-    final colorProvider = json['colorProvider'] is bool
-        ? new Either3<bool, ColorProviderOptions, dynamic>.t1(
-            json['colorProvider'])
-        : (ColorProviderOptions.canParse(json['colorProvider'])
-            ? new Either3<bool, ColorProviderOptions, dynamic>.t2(
-                json['colorProvider'] != null
-                    ? ColorProviderOptions.fromJson(json['colorProvider'])
-                    : null)
-            : (new Either3<bool, ColorProviderOptions, dynamic>.t3(
-                json['colorProvider'])));
-    final foldingRangeProvider = json['foldingRangeProvider'] is bool
-        ? new Either3<bool, FoldingRangeProviderOptions, dynamic>.t1(
-            json['foldingRangeProvider'])
-        : (FoldingRangeProviderOptions.canParse(json['foldingRangeProvider'])
-            ? new Either3<bool, FoldingRangeProviderOptions, dynamic>.t2(
-                json['foldingRangeProvider'] != null
-                    ? FoldingRangeProviderOptions.fromJson(
-                        json['foldingRangeProvider'])
-                    : null)
-            : (new Either3<bool, FoldingRangeProviderOptions, dynamic>.t3(
-                json['foldingRangeProvider'])));
+    final colorProvider = json['colorProvider'];
+    final foldingRangeProvider = json['foldingRangeProvider'];
+    final declarationProvider = json['declarationProvider'];
     final executeCommandProvider = json['executeCommandProvider'] != null
         ? ExecuteCommandOptions.fromJson(json['executeCommandProvider'])
         : null;
@@ -7318,6 +7338,7 @@
         documentLinkProvider,
         colorProvider,
         foldingRangeProvider,
+        declarationProvider,
         executeCommandProvider,
         workspace,
         experimental);
@@ -7334,11 +7355,16 @@
   /// The server provides color provider support.
   ///
   /// Since 3.6.0
-  final Either3<bool, ColorProviderOptions, dynamic> colorProvider;
+  final dynamic colorProvider;
 
   /// The server provides completion support.
   final CompletionOptions completionProvider;
 
+  /// The server provides go to declaration support.
+  ///
+  /// Since 3.14.0
+  final dynamic declarationProvider;
+
   /// The server provides goto definition support.
   final bool definitionProvider;
 
@@ -7369,8 +7395,7 @@
   /// The server provides folding provider support.
   ///
   /// Since 3.10.0
-  final Either3<bool, FoldingRangeProviderOptions, dynamic>
-      foldingRangeProvider;
+  final dynamic foldingRangeProvider;
 
   /// The server provides hover support.
   final bool hoverProvider;
@@ -7378,7 +7403,7 @@
   /// The server provides Goto Implementation support.
   ///
   /// Since 3.6.0
-  final Either2<bool, dynamic> implementationProvider;
+  final dynamic implementationProvider;
 
   /// The server provides find references support.
   final bool referencesProvider;
@@ -7400,7 +7425,7 @@
   /// The server provides Goto Type Definition support.
   ///
   /// Since 3.6.0
-  final Either2<bool, dynamic> typeDefinitionProvider;
+  final dynamic typeDefinitionProvider;
 
   /// Workspace specific server capabilities
   final ServerCapabilitiesWorkspace workspace;
@@ -7472,6 +7497,9 @@
     if (foldingRangeProvider != null) {
       __result['foldingRangeProvider'] = foldingRangeProvider;
     }
+    if (declarationProvider != null) {
+      __result['declarationProvider'] = declarationProvider;
+    }
     if (executeCommandProvider != null) {
       __result['executeCommandProvider'] = executeCommandProvider;
     }
@@ -7496,10 +7524,8 @@
             SignatureHelpOptions.canParse(obj['signatureHelpProvider'])) &&
         (obj['definitionProvider'] == null ||
             obj['definitionProvider'] is bool) &&
-        (obj['typeDefinitionProvider'] == null ||
-            (obj['typeDefinitionProvider'] is bool || true)) &&
-        (obj['implementationProvider'] == null ||
-            (obj['implementationProvider'] is bool || true)) &&
+        (obj['typeDefinitionProvider'] == null || true) &&
+        (obj['implementationProvider'] == null || true) &&
         (obj['referencesProvider'] == null ||
             obj['referencesProvider'] is bool) &&
         (obj['documentHighlightProvider'] == null ||
@@ -7525,15 +7551,9 @@
                 RenameOptions.canParse(obj['renameProvider']))) &&
         (obj['documentLinkProvider'] == null ||
             DocumentLinkOptions.canParse(obj['documentLinkProvider'])) &&
-        (obj['colorProvider'] == null ||
-            (obj['colorProvider'] is bool ||
-                ColorProviderOptions.canParse(obj['colorProvider']) ||
-                true)) &&
-        (obj['foldingRangeProvider'] == null ||
-            (obj['foldingRangeProvider'] is bool ||
-                FoldingRangeProviderOptions.canParse(
-                    obj['foldingRangeProvider']) ||
-                true)) &&
+        (obj['colorProvider'] == null || true) &&
+        (obj['foldingRangeProvider'] == null || true) &&
+        (obj['declarationProvider'] == null || true) &&
         (obj['executeCommandProvider'] == null ||
             ExecuteCommandOptions.canParse(obj['executeCommandProvider'])) &&
         (obj['workspace'] == null ||
@@ -7566,6 +7586,7 @@
           documentLinkProvider == other.documentLinkProvider &&
           colorProvider == other.colorProvider &&
           foldingRangeProvider == other.foldingRangeProvider &&
+          declarationProvider == other.declarationProvider &&
           executeCommandProvider == other.executeCommandProvider &&
           workspace == other.workspace &&
           experimental == other.experimental &&
@@ -7599,6 +7620,7 @@
     hash = JenkinsSmiHash.combine(hash, documentLinkProvider.hashCode);
     hash = JenkinsSmiHash.combine(hash, colorProvider.hashCode);
     hash = JenkinsSmiHash.combine(hash, foldingRangeProvider.hashCode);
+    hash = JenkinsSmiHash.combine(hash, declarationProvider.hashCode);
     hash = JenkinsSmiHash.combine(hash, executeCommandProvider.hashCode);
     hash = JenkinsSmiHash.combine(hash, workspace.hashCode);
     hash = JenkinsSmiHash.combine(hash, experimental.hashCode);
@@ -8394,7 +8416,9 @@
   }
   static TextDocumentChangeRegistrationOptions fromJson(
       Map<String, dynamic> json) {
-    final syncKind = json['syncKind'];
+    final syncKind = json['syncKind'] != null
+        ? TextDocumentSyncKind.fromJson(json['syncKind'])
+        : null;
     final documentSelector = json['documentSelector']
         ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
         ?.cast<DocumentFilter>()
@@ -8409,7 +8433,7 @@
 
   /// How documents are synced to the server. See TextDocumentSyncKind.Full and
   /// TextDocumentSyncKind.Incremental.
-  final num syncKind;
+  final TextDocumentSyncKind syncKind;
 
   Map<String, dynamic> toJson() {
     Map<String, dynamic> __result = {};
@@ -8422,7 +8446,7 @@
   static bool canParse(Object obj) {
     return obj is Map<String, dynamic> &&
         obj.containsKey('syncKind') &&
-        obj['syncKind'] is num &&
+        TextDocumentSyncKind.canParse(obj['syncKind']) &&
         obj.containsKey('documentSelector') &&
         (obj['documentSelector'] == null ||
             (obj['documentSelector'] is List &&
@@ -11205,16 +11229,20 @@
   /// TextDocumentSyncKind.None.
   final TextDocumentSyncKind change;
 
-  /// Open and close notifications are sent to the server.
+  /// Open and close notifications are sent to the server. If omitted open close
+  /// notification should not be sent.
   final bool openClose;
 
-  /// Save notifications are sent to the server.
+  /// If present save notifications are sent to the server. If omitted the
+  /// notification should not be sent.
   final SaveOptions save;
 
-  /// Will save notifications are sent to the server.
+  /// If present will save notifications are sent to the server. If omitted the
+  /// notification should not be sent.
   final bool willSave;
 
-  /// Will save wait until requests are sent to the server.
+  /// If present will save wait until requests are sent to the server. If
+  /// omitted the request should not be sent.
   final bool willSaveWaitUntil;
 
   Map<String, dynamic> toJson() {
@@ -12258,7 +12286,8 @@
     return new WorkspaceFolder(uri, name);
   }
 
-  /// The name of the workspace folder. Defaults to the uri's basename.
+  /// The name of the workspace folder. Used to refer to this workspace folder
+  /// in the user interface.
   final String name;
 
   /// The associated URI for this workspace folder.
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart
index 7093987..ca304eb 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart
@@ -8,6 +8,17 @@
 
 const jsonRpcVersion = '2.0';
 
+const NullJsonHandler = const LspJsonHandler<Null>(_alwaysTrue, _alwaysNull);
+
+ErrorOr<R> cancelled<R>([R t]) =>
+    error(ErrorCodes.RequestCancelled, 'Request was cancelled', null);
+
+ErrorOr<R> error<R>(ErrorCodes code, String message, [String data]) =>
+    new ErrorOr<R>.error(new ResponseError(code, message, data));
+
+ErrorOr<R> failure<R>(ErrorOr<dynamic> error) =>
+    new ErrorOr<R>.error(error.error);
+
 Object specToJson(Object obj) {
   if (obj is ToJsonable) {
     return obj.toJson();
@@ -16,6 +27,12 @@
   }
 }
 
+ErrorOr<R> success<R>([R t]) => new ErrorOr<R>.success(t);
+
+Null _alwaysNull(_) => null;
+
+bool _alwaysTrue(_) => true;
+
 class Either2<T1, T2> {
   final int _which;
   final T1 _t1;
@@ -39,6 +56,9 @@
 
   Object toJson() => map(specToJson, specToJson);
 
+  @override
+  String toString() => map((t) => t.toString(), (t) => t.toString());
+
   /// Checks whether the value of the union equals the supplied value.
   bool valueEquals(o) => map((t) => t == o, (t) => t == o);
 }
@@ -83,6 +103,13 @@
 
   Object toJson() => map(specToJson, specToJson, specToJson);
 
+  @override
+  String toString() => map(
+        (t) => t.toString(),
+        (t) => t.toString(),
+        (t) => t.toString(),
+      );
+
   /// Checks whether the value of the union equals the supplied value.
   bool valueEquals(o) => map((t) => t == o, (t) => t == o, (t) => t == o);
 }
@@ -144,6 +171,14 @@
 
   Object toJson() => map(specToJson, specToJson, specToJson, specToJson);
 
+  @override
+  String toString() => map(
+        (t) => t.toString(),
+        (t) => t.toString(),
+        (t) => t.toString(),
+        (t) => t.toString(),
+      );
+
   /// Checks whether the value of the union equals the supplied value.
   bool valueEquals(o) =>
       map((t) => t == o, (t) => t == o, (t) => t == o, (t) => t == o);
@@ -198,10 +233,6 @@
   const LspJsonHandler(this.validateParams, this.convertParams);
 }
 
-bool _alwaysTrue(_) => true;
-Null _alwaysNull(_) => null;
-const NullJsonHandler = const LspJsonHandler<Null>(_alwaysTrue, _alwaysNull);
-
 abstract class ToJsonable {
   Object toJson();
 }
diff --git a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
index fb3c5ec..499c925 100644
--- a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
+++ b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
 
@@ -21,4 +22,10 @@
    * The workspace in which the fix contributor operates.
    */
   ChangeWorkspace get workspace;
+
+  /**
+   * Return top-level declarations with the [name] in libraries that are
+   * available to this context.
+   */
+  List<TopLevelDeclaration> getTopLevelDeclarations(String name);
 }
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
index aaecbef..85b9e43 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -239,7 +239,7 @@
 // Sort @required named parameters before optional ones.
 int _preferRequiredParams(
     engine.ParameterElement e1, engine.ParameterElement e2) {
-  int rank1 = e1.hasRequired ? 0 : !e1.isNamed ? -1 : 1;
-  int rank2 = e2.hasRequired ? 0 : !e2.isNamed ? -1 : 1;
+  int rank1 = (e1.isRequiredNamed || e1.hasRequired) ? 0 : !e1.isNamed ? -1 : 1;
+  int rank2 = (e2.isRequiredNamed || e2.hasRequired) ? 0 : !e2.isNamed ? -1 : 1;
   return rank1 - rank2;
 }
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 35174b9..2d93ddb 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.26.0';
+const String PROTOCOL_VERSION = '1.27.1';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -116,6 +116,10 @@
     'changedLibraries';
 const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_REMOVED_LIBRARIES =
     'removedLibraries';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS =
+    'completion.existingImports';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_FILE = 'file';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_IMPORTS = 'imports';
 const String COMPLETION_NOTIFICATION_RESULTS = 'completion.results';
 const String COMPLETION_NOTIFICATION_RESULTS_ID = 'id';
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_ELEMENT_KINDS =
@@ -126,6 +130,7 @@
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_SETS =
     'includedSuggestionSets';
 const String COMPLETION_NOTIFICATION_RESULTS_IS_LAST = 'isLast';
+const String COMPLETION_NOTIFICATION_RESULTS_LIBRARY_FILE = 'libraryFile';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_LENGTH =
     'replacementLength';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_OFFSET =
@@ -213,6 +218,7 @@
 const String EDIT_REQUEST_ORGANIZE_DIRECTIVES_FILE = 'file';
 const String EDIT_REQUEST_SORT_MEMBERS = 'edit.sortMembers';
 const String EDIT_REQUEST_SORT_MEMBERS_FILE = 'file';
+const String EDIT_RESPONSE_DARTFIX_DETAILS = 'details';
 const String EDIT_RESPONSE_DARTFIX_EDITS = 'edits';
 const String EDIT_RESPONSE_DARTFIX_HAS_ERRORS = 'hasErrors';
 const String EDIT_RESPONSE_DARTFIX_OTHER_SUGGESTIONS = 'otherSuggestions';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 6e7da59..45a219f 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -5075,6 +5075,7 @@
  *
  * {
  *   "label": String
+ *   "declaringLibraryUri": String
  *   "element": Element
  *   "defaultArgumentListString": optional String
  *   "defaultArgumentListTextRanges": optional List<int>
@@ -5091,6 +5092,8 @@
 class AvailableSuggestion implements HasToJson {
   String _label;
 
+  String _declaringLibraryUri;
+
   Element _element;
 
   String _defaultArgumentListString;
@@ -5123,6 +5126,21 @@
   }
 
   /**
+   * The URI of the library that declares the element being suggested, not the
+   * URI of the library associated with the enclosing AvailableSuggestionSet.
+   */
+  String get declaringLibraryUri => _declaringLibraryUri;
+
+  /**
+   * The URI of the library that declares the element being suggested, not the
+   * URI of the library associated with the enclosing AvailableSuggestionSet.
+   */
+  void set declaringLibraryUri(String value) {
+    assert(value != null);
+    this._declaringLibraryUri = value;
+  }
+
+  /**
    * Information about the element reference being suggested.
    */
   Element get element => _element;
@@ -5255,7 +5273,7 @@
     this._requiredParameterCount = value;
   }
 
-  AvailableSuggestion(String label, Element element,
+  AvailableSuggestion(String label, String declaringLibraryUri, Element element,
       {String defaultArgumentListString,
       List<int> defaultArgumentListTextRanges,
       String docComplete,
@@ -5265,6 +5283,7 @@
       List<String> relevanceTags,
       int requiredParameterCount}) {
     this.label = label;
+    this.declaringLibraryUri = declaringLibraryUri;
     this.element = element;
     this.defaultArgumentListString = defaultArgumentListString;
     this.defaultArgumentListTextRanges = defaultArgumentListTextRanges;
@@ -5288,6 +5307,13 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "label");
       }
+      String declaringLibraryUri;
+      if (json.containsKey("declaringLibraryUri")) {
+        declaringLibraryUri = jsonDecoder.decodeString(
+            jsonPath + ".declaringLibraryUri", json["declaringLibraryUri"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "declaringLibraryUri");
+      }
       Element element;
       if (json.containsKey("element")) {
         element = new Element.fromJson(
@@ -5339,7 +5365,7 @@
             jsonPath + ".requiredParameterCount",
             json["requiredParameterCount"]);
       }
-      return new AvailableSuggestion(label, element,
+      return new AvailableSuggestion(label, declaringLibraryUri, element,
           defaultArgumentListString: defaultArgumentListString,
           defaultArgumentListTextRanges: defaultArgumentListTextRanges,
           docComplete: docComplete,
@@ -5357,6 +5383,7 @@
   Map<String, dynamic> toJson() {
     Map<String, dynamic> result = {};
     result["label"] = label;
+    result["declaringLibraryUri"] = declaringLibraryUri;
     result["element"] = element.toJson();
     if (defaultArgumentListString != null) {
       result["defaultArgumentListString"] = defaultArgumentListString;
@@ -5392,6 +5419,7 @@
   bool operator ==(other) {
     if (other is AvailableSuggestion) {
       return label == other.label &&
+          declaringLibraryUri == other.declaringLibraryUri &&
           element == other.element &&
           defaultArgumentListString == other.defaultArgumentListString &&
           listEqual(defaultArgumentListTextRanges,
@@ -5413,6 +5441,7 @@
   int get hashCode {
     int hash = 0;
     hash = JenkinsSmiHash.combine(hash, label.hashCode);
+    hash = JenkinsSmiHash.combine(hash, declaringLibraryUri.hashCode);
     hash = JenkinsSmiHash.combine(hash, element.hashCode);
     hash = JenkinsSmiHash.combine(hash, defaultArgumentListString.hashCode);
     hash = JenkinsSmiHash.combine(hash, defaultArgumentListTextRanges.hashCode);
@@ -5803,6 +5832,116 @@
 }
 
 /**
+ * completion.existingImports params
+ *
+ * {
+ *   "file": FilePath
+ *   "imports": ExistingImports
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionExistingImportsParams implements HasToJson {
+  String _file;
+
+  ExistingImports _imports;
+
+  /**
+   * The defining file of the library.
+   */
+  String get file => _file;
+
+  /**
+   * The defining file of the library.
+   */
+  void set file(String value) {
+    assert(value != null);
+    this._file = value;
+  }
+
+  /**
+   * The existing imports in the library.
+   */
+  ExistingImports get imports => _imports;
+
+  /**
+   * The existing imports in the library.
+   */
+  void set imports(ExistingImports value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  CompletionExistingImportsParams(String file, ExistingImports imports) {
+    this.file = file;
+    this.imports = imports;
+  }
+
+  factory CompletionExistingImportsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String file;
+      if (json.containsKey("file")) {
+        file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "file");
+      }
+      ExistingImports imports;
+      if (json.containsKey("imports")) {
+        imports = new ExistingImports.fromJson(
+            jsonDecoder, jsonPath + ".imports", json["imports"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new CompletionExistingImportsParams(file, imports);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.existingImports params", json);
+    }
+  }
+
+  factory CompletionExistingImportsParams.fromNotification(
+      Notification notification) {
+    return new CompletionExistingImportsParams.fromJson(
+        new ResponseDecoder(null), "params", notification.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["file"] = file;
+    result["imports"] = imports.toJson();
+    return result;
+  }
+
+  Notification toNotification() {
+    return new Notification("completion.existingImports", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionExistingImportsParams) {
+      return file == other.file && imports == other.imports;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, file.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * completion.getSuggestionDetails params
  *
  * {
@@ -6593,6 +6732,7 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "libraryFile": optional FilePath
  *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
  *   "includedElementKinds": optional List<ElementKind>
  *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -6611,6 +6751,8 @@
 
   bool _isLast;
 
+  String _libraryFile;
+
   List<IncludedSuggestionSet> _includedSuggestionSets;
 
   List<ElementKind> _includedElementKinds;
@@ -6703,6 +6845,26 @@
   }
 
   /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  String get libraryFile => _libraryFile;
+
+  /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  void set libraryFile(String value) {
+    this._libraryFile = value;
+  }
+
+  /**
    * References to AvailableSuggestionSet objects previously sent to the
    * client. The client can include applicable names from the referenced
    * library in code completion suggestions.
@@ -6765,7 +6927,8 @@
 
   CompletionResultsParams(String id, int replacementOffset,
       int replacementLength, List<CompletionSuggestion> results, bool isLast,
-      {List<IncludedSuggestionSet> includedSuggestionSets,
+      {String libraryFile,
+      List<IncludedSuggestionSet> includedSuggestionSets,
       List<ElementKind> includedElementKinds,
       List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags}) {
     this.id = id;
@@ -6773,6 +6936,7 @@
     this.replacementLength = replacementLength;
     this.results = results;
     this.isLast = isLast;
+    this.libraryFile = libraryFile;
     this.includedSuggestionSets = includedSuggestionSets;
     this.includedElementKinds = includedElementKinds;
     this.includedSuggestionRelevanceTags = includedSuggestionRelevanceTags;
@@ -6820,6 +6984,11 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "isLast");
       }
+      String libraryFile;
+      if (json.containsKey("libraryFile")) {
+        libraryFile = jsonDecoder.decodeString(
+            jsonPath + ".libraryFile", json["libraryFile"]);
+      }
       List<IncludedSuggestionSet> includedSuggestionSets;
       if (json.containsKey("includedSuggestionSets")) {
         includedSuggestionSets = jsonDecoder.decodeList(
@@ -6848,6 +7017,7 @@
       }
       return new CompletionResultsParams(
           id, replacementOffset, replacementLength, results, isLast,
+          libraryFile: libraryFile,
           includedSuggestionSets: includedSuggestionSets,
           includedElementKinds: includedElementKinds,
           includedSuggestionRelevanceTags: includedSuggestionRelevanceTags);
@@ -6870,6 +7040,9 @@
     result["results"] =
         results.map((CompletionSuggestion value) => value.toJson()).toList();
     result["isLast"] = isLast;
+    if (libraryFile != null) {
+      result["libraryFile"] = libraryFile;
+    }
     if (includedSuggestionSets != null) {
       result["includedSuggestionSets"] = includedSuggestionSets
           .map((IncludedSuggestionSet value) => value.toJson())
@@ -6905,6 +7078,7 @@
           listEqual(results, other.results,
               (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
           isLast == other.isLast &&
+          libraryFile == other.libraryFile &&
           listEqual(includedSuggestionSets, other.includedSuggestionSets,
               (IncludedSuggestionSet a, IncludedSuggestionSet b) => a == b) &&
           listEqual(includedElementKinds, other.includedElementKinds,
@@ -6927,6 +7101,7 @@
     hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
     hash = JenkinsSmiHash.combine(hash, results.hashCode);
     hash = JenkinsSmiHash.combine(hash, isLast.hashCode);
+    hash = JenkinsSmiHash.combine(hash, libraryFile.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedSuggestionSets.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedElementKinds.hashCode);
     hash =
@@ -6946,11 +7121,13 @@
  */
 class CompletionService implements Enum {
   /**
-   * The client will receive notifications once subscribed with completion
-   * suggestion sets from the libraries of interest. The client should keep an
-   * up-to-date record of these in memory so that it will be able to union
-   * these candidates with other completion suggestions when applicable at
-   * completion time.
+   * The client will receive availableSuggestions notifications once subscribed
+   * with completion suggestion sets from the libraries of interest. The client
+   * should keep an up-to-date record of these in memory so that it will be
+   * able to union these candidates with other completion suggestions when
+   * applicable at completion time.
+   *
+   * The client will also receive existingImports notifications.
    */
   static const CompletionService AVAILABLE_SUGGESTION_SETS =
       const CompletionService._("AVAILABLE_SUGGESTION_SETS");
@@ -8045,6 +8222,7 @@
  *   "otherSuggestions": List<DartFixSuggestion>
  *   "hasErrors": bool
  *   "edits": List<SourceFileEdit>
+ *   "details": optional List<String>
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -8058,6 +8236,8 @@
 
   List<SourceFileEdit> _edits;
 
+  List<String> _details;
+
   /**
    * A list of recommended changes that can be automatically made by applying
    * the 'edits' included in this response.
@@ -8114,15 +8294,37 @@
     this._edits = value;
   }
 
+  /**
+   * Messages that should be displayed to the user that describe details of the
+   * fix generation. For example, the messages might (a) point out details that
+   * users might want to explore before committing the changes or (b) describe
+   * exceptions that were thrown but that did not stop the fixes from being
+   * produced. The list will be omitted if it is empty.
+   */
+  List<String> get details => _details;
+
+  /**
+   * Messages that should be displayed to the user that describe details of the
+   * fix generation. For example, the messages might (a) point out details that
+   * users might want to explore before committing the changes or (b) describe
+   * exceptions that were thrown but that did not stop the fixes from being
+   * produced. The list will be omitted if it is empty.
+   */
+  void set details(List<String> value) {
+    this._details = value;
+  }
+
   EditDartfixResult(
       List<DartFixSuggestion> suggestions,
       List<DartFixSuggestion> otherSuggestions,
       bool hasErrors,
-      List<SourceFileEdit> edits) {
+      List<SourceFileEdit> edits,
+      {List<String> details}) {
     this.suggestions = suggestions;
     this.otherSuggestions = otherSuggestions;
     this.hasErrors = hasErrors;
     this.edits = edits;
+    this.details = details;
   }
 
   factory EditDartfixResult.fromJson(
@@ -8168,8 +8370,14 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "edits");
       }
+      List<String> details;
+      if (json.containsKey("details")) {
+        details = jsonDecoder.decodeList(
+            jsonPath + ".details", json["details"], jsonDecoder.decodeString);
+      }
       return new EditDartfixResult(
-          suggestions, otherSuggestions, hasErrors, edits);
+          suggestions, otherSuggestions, hasErrors, edits,
+          details: details);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "edit.dartfix result", json);
     }
@@ -8193,6 +8401,9 @@
     result["hasErrors"] = hasErrors;
     result["edits"] =
         edits.map((SourceFileEdit value) => value.toJson()).toList();
+    if (details != null) {
+      result["details"] = details;
+    }
     return result;
   }
 
@@ -8213,7 +8424,8 @@
               (DartFixSuggestion a, DartFixSuggestion b) => a == b) &&
           hasErrors == other.hasErrors &&
           listEqual(edits, other.edits,
-              (SourceFileEdit a, SourceFileEdit b) => a == b);
+              (SourceFileEdit a, SourceFileEdit b) => a == b) &&
+          listEqual(details, other.details, (String a, String b) => a == b);
     }
     return false;
   }
@@ -8225,6 +8437,7 @@
     hash = JenkinsSmiHash.combine(hash, otherSuggestions.hashCode);
     hash = JenkinsSmiHash.combine(hash, hasErrors.hashCode);
     hash = JenkinsSmiHash.combine(hash, edits.hashCode);
+    hash = JenkinsSmiHash.combine(hash, details.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
@@ -13011,6 +13224,214 @@
 }
 
 /**
+ * ExistingImport
+ *
+ * {
+ *   "uri": int
+ *   "elements": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImport implements HasToJson {
+  int _uri;
+
+  List<int> _elements;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  int get uri => _uri;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  void set uri(int value) {
+    assert(value != null);
+    this._uri = value;
+  }
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  List<int> get elements => _elements;
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  void set elements(List<int> value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  ExistingImport(int uri, List<int> elements) {
+    this.uri = uri;
+    this.elements = elements;
+  }
+
+  factory ExistingImport.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      int uri;
+      if (json.containsKey("uri")) {
+        uri = jsonDecoder.decodeInt(jsonPath + ".uri", json["uri"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uri");
+      }
+      List<int> elements;
+      if (json.containsKey("elements")) {
+        elements = jsonDecoder.decodeList(
+            jsonPath + ".elements", json["elements"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      return new ExistingImport(uri, elements);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImport", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["uri"] = uri;
+    result["elements"] = elements;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImport) {
+      return uri == other.uri &&
+          listEqual(elements, other.elements, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * ExistingImports
+ *
+ * {
+ *   "elements": ImportedElementSet
+ *   "imports": List<ExistingImport>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImports implements HasToJson {
+  ImportedElementSet _elements;
+
+  List<ExistingImport> _imports;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  ImportedElementSet get elements => _elements;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  void set elements(ImportedElementSet value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  /**
+   * The list of imports in the library.
+   */
+  List<ExistingImport> get imports => _imports;
+
+  /**
+   * The list of imports in the library.
+   */
+  void set imports(List<ExistingImport> value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+    this.elements = elements;
+    this.imports = imports;
+  }
+
+  factory ExistingImports.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      ImportedElementSet elements;
+      if (json.containsKey("elements")) {
+        elements = new ImportedElementSet.fromJson(
+            jsonDecoder, jsonPath + ".elements", json["elements"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      List<ExistingImport> imports;
+      if (json.containsKey("imports")) {
+        imports = jsonDecoder.decodeList(
+            jsonPath + ".imports",
+            json["imports"],
+            (String jsonPath, Object json) =>
+                new ExistingImport.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new ExistingImports(elements, imports);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImports", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["elements"] = elements.toJson();
+    result["imports"] =
+        imports.map((ExistingImport value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImports) {
+      return elements == other.elements &&
+          listEqual(imports, other.imports,
+              (ExistingImport a, ExistingImport b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * extractLocalVariable feedback
  *
  * {
@@ -15586,16 +16007,16 @@
   }
 
   /**
-   * The name of the library in which the referenced element is declared. This
-   * data is omitted if there is no referenced element, or if the element is
-   * declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core",
+   * "package:.." and file uris represented by the path on disk, "/..". The
+   * data is omitted if the element is declared inside an HTML file.
    */
   String get containingLibraryName => _containingLibraryName;
 
   /**
-   * The name of the library in which the referenced element is declared. This
-   * data is omitted if there is no referenced element, or if the element is
-   * declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core",
+   * "package:.." and file uris represented by the path on disk, "/..". The
+   * data is omitted if the element is declared inside an HTML file.
    */
   void set containingLibraryName(String value) {
     this._containingLibraryName = value;
@@ -16109,6 +16530,135 @@
 }
 
 /**
+ * ImportedElementSet
+ *
+ * {
+ *   "strings": List<String>
+ *   "uris": List<int>
+ *   "names": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ImportedElementSet implements HasToJson {
+  List<String> _strings;
+
+  List<int> _uris;
+
+  List<int> _names;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  List<String> get strings => _strings;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  void set strings(List<String> value) {
+    assert(value != null);
+    this._strings = value;
+  }
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  List<int> get uris => _uris;
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  void set uris(List<int> value) {
+    assert(value != null);
+    this._uris = value;
+  }
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  List<int> get names => _names;
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  void set names(List<int> value) {
+    assert(value != null);
+    this._names = value;
+  }
+
+  ImportedElementSet(List<String> strings, List<int> uris, List<int> names) {
+    this.strings = strings;
+    this.uris = uris;
+    this.names = names;
+  }
+
+  factory ImportedElementSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<String> strings;
+      if (json.containsKey("strings")) {
+        strings = jsonDecoder.decodeList(
+            jsonPath + ".strings", json["strings"], jsonDecoder.decodeString);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "strings");
+      }
+      List<int> uris;
+      if (json.containsKey("uris")) {
+        uris = jsonDecoder.decodeList(
+            jsonPath + ".uris", json["uris"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uris");
+      }
+      List<int> names;
+      if (json.containsKey("names")) {
+        names = jsonDecoder.decodeList(
+            jsonPath + ".names", json["names"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "names");
+      }
+      return new ImportedElementSet(strings, uris, names);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ImportedElementSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["strings"] = strings;
+    result["uris"] = uris;
+    result["names"] = names;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ImportedElementSet) {
+      return listEqual(
+              strings, other.strings, (String a, String b) => a == b) &&
+          listEqual(uris, other.uris, (int a, int b) => a == b) &&
+          listEqual(names, other.names, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, strings.hashCode);
+    hash = JenkinsSmiHash.combine(hash, uris.hashCode);
+    hash = JenkinsSmiHash.combine(hash, names.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * ImportedElements
  *
  * {
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index c60be02..587adc4 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -42,6 +42,7 @@
 import 'package:analysis_server/src/search/search_domain.dart';
 import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
 import 'package:analysis_server/src/server/diagnostic_server.dart';
+import 'package:analysis_server/src/server/features.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
 import 'package:analysis_server/src/utilities/null_string_sink.dart';
@@ -54,7 +55,6 @@
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/context/context_root.dart';
-import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' as nd;
 import 'package:analyzer/src/dart/analysis/file_state.dart' as nd;
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
@@ -147,10 +147,6 @@
 
   PerformanceLog _analysisPerformanceLogger;
 
-  ByteStore byteStore;
-  nd.AnalysisDriverScheduler analysisDriverScheduler;
-  DeclarationsTracker declarationsTracker;
-
   /// The controller for [onAnalysisSetChanged].
   final StreamController _onAnalysisSetChangedController =
       new StreamController.broadcast(sync: true);
@@ -202,13 +198,22 @@
       }
       _analysisPerformanceLogger = new PerformanceLog(sink);
     }
+
     byteStore = createByteStore(resourceProvider);
+
     analysisDriverScheduler = new nd.AnalysisDriverScheduler(
         _analysisPerformanceLogger,
         driverWatcher: pluginWatcher);
     analysisDriverScheduler.status.listen(sendStatusNotificationNew);
     analysisDriverScheduler.start();
 
+    if (options.featureSet.completion) {
+      declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
+      declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
+      analysisDriverScheduler.outOfBandWorker =
+          CompletionLibrariesWorker(declarationsTracker);
+    }
+
     contextManager = new ContextManagerImpl(
         resourceProvider,
         sdkManager,
@@ -276,27 +281,6 @@
     return _onAnalysisStartedController.stream;
   }
 
-  void createDeclarationsTracker(void Function(LibraryChange) listener) {
-    if (declarationsTracker != null) return;
-
-    declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
-    declarationsTracker.changes.listen(listener);
-
-    _addContextsToDeclarationsTracker();
-
-    // Configure the scheduler to run the tracker.
-    analysisDriverScheduler.outOfBandWorker =
-        CompletionLibrariesWorker(declarationsTracker);
-
-    // We might have done running drivers work, so ask the scheduler to check.
-    analysisDriverScheduler.notify(null);
-  }
-
-  void disposeDeclarationsTracker() {
-    declarationsTracker = null;
-    analysisDriverScheduler.outOfBandWorker = null;
-  }
-
   /// The socket from which requests are being read has been closed.
   void done() {}
 
@@ -386,15 +370,6 @@
         resourceProvider.pathContext.normalize(path) == path;
   }
 
-  /// Notify the declarations tracker that the file with the given [path] was
-  /// changed - added, updated, or removed.  Schedule processing of the file.
-  void notifyDeclarationsTracker(String path) {
-    if (declarationsTracker != null) {
-      declarationsTracker.changeFile(path);
-      analysisDriverScheduler.notify(null);
-    }
-  }
-
   /// Read all files, resolve all URIs, and perform required analysis in
   /// all current analysis drivers.
   void reanalyze() {
@@ -523,7 +498,7 @@
       throw new RequestFailure(
           new Response.unsupportedFeature(requestId, e.message));
     }
-    _addContextsToDeclarationsTracker();
+    addContextsToDeclarationsTracker();
   }
 
   /// Implementation for `analysis.setSubscriptions`.
@@ -590,7 +565,11 @@
   /// Returns `true` if errors should be reported for [file] with the given
   /// absolute path.
   bool shouldSendErrorsNotificationFor(String file) {
-    return contextManager.isInAnalysisRoot(file);
+    // Errors should not be reported for things that are explicitly skipped
+    // during normal analysis (for example dot folders are skipped over in
+    // _handleWatchEventImpl).
+    return contextManager.isInAnalysisRoot(file) &&
+        !contextManager.isContainedInDotFolder(file);
   }
 
   Future<void> shutdown() {
@@ -701,15 +680,6 @@
 //    });
   }
 
-  void _addContextsToDeclarationsTracker() {
-    if (declarationsTracker != null) {
-      for (var driver in driverMap.values) {
-        declarationsTracker.addContext(driver.analysisContext);
-        driver.resetUriResolution();
-      }
-    }
-  }
-
   /// Return the path to the location of the byte store on disk, or `null` if
   /// there is no on-disk byte store.
   String _getByteStorePath() {
@@ -772,6 +742,9 @@
 
   /// Whether to enable parsing via the Fasta parser.
   bool useFastaParser = true;
+
+  /// The set of enabled features.
+  FeatureSet featureSet = FeatureSet();
 }
 
 class ServerContextManagerCallbacks extends ContextManagerCallbacks {
@@ -919,6 +892,11 @@
   }
 
   @override
+  void analysisOptionsUpdated(nd.AnalysisDriver driver) {
+    analysisServer.updateContextInDeclarationsTracker(driver);
+  }
+
+  @override
   void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
     nd.AnalysisDriver analysisDriver = analysisServer.driverMap[contextFolder];
     if (analysisDriver != null) {
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index 3ed2774..d1aa497d 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -8,6 +8,7 @@
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/collections.dart';
 import 'package:analysis_server/src/context_manager.dart';
+import 'package:analysis_server/src/domains/completion/available_suggestions.dart';
 import 'package:analysis_server/src/server/diagnostic_server.dart';
 import 'package:analysis_server/src/services/correction/namespace.dart';
 import 'package:analysis_server/src/services/search/element_visitors.dart';
@@ -27,7 +28,9 @@
 import 'package:analyzer/src/dart/analysis/status.dart' as nd;
 import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/services/available_declarations.dart';
 import 'package:analyzer/src/util/glob.dart';
 
 /// Implementations of [AbstractAnalysisServer] implement a server that listens
@@ -40,6 +43,13 @@
   /// context directories.
   ContextManager contextManager;
 
+  ByteStore byteStore;
+
+  nd.AnalysisDriverScheduler analysisDriverScheduler;
+
+  DeclarationsTracker declarationsTracker;
+  DeclarationsTrackerData declarationsTrackerData;
+
   /// The DiagnosticServer for this AnalysisServer. If available, it can be used
   /// to start an http diagnostics server or return the port for an existing
   /// server.
@@ -124,6 +134,13 @@
     return new DateTime.now().difference(start);
   }
 
+  void addContextsToDeclarationsTracker() {
+    for (var driver in driverMap.values) {
+      declarationsTracker?.addContext(driver.analysisContext);
+      driver.resetUriResolution();
+    }
+  }
+
   /// If the state location can be accessed, return the file byte store,
   /// otherwise return the memory byte store.
   ByteStore createByteStore(ResourceProvider resourceProvider) {
@@ -170,6 +187,13 @@
     return null;
   }
 
+  DartdocDirectiveInfo getDartdocDirectiveInfoFor(ResolvedUnitResult result) {
+    return declarationsTracker
+            ?.getContext(result.session.analysisContext)
+            ?.dartdocDirectiveInfo ??
+        new DartdocDirectiveInfo();
+  }
+
   /// Return a [Future] that completes with the [Element] at the given
   /// [offset] of the given [file], or with `null` if there is no node at the
   /// [offset] or the node does not have an element.
@@ -260,4 +284,16 @@
         .getResult(path, sendCachedToStream: sendCachedToStream)
         .catchError((_) => null);
   }
+
+  /// Notify the declarations tracker that the file with the given [path] was
+  /// changed - added, updated, or removed.  Schedule processing of the file.
+  void notifyDeclarationsTracker(String path) {
+    declarationsTracker?.changeFile(path);
+    analysisDriverScheduler.notify(null);
+  }
+
+  void updateContextInDeclarationsTracker(nd.AnalysisDriver driver) {
+    declarationsTracker?.discardContext(driver.analysisContext);
+    declarationsTracker?.addContext(driver.analysisContext);
+  }
 }
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index 7c150bab..233da3c 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -431,6 +431,13 @@
   }
 
   @override
+  void visitDefaultFormalParameter(DefaultFormalParameter node) {
+    computer._addRegion_token(
+        node.requiredKeyword, HighlightRegionType.KEYWORD);
+    super.visitDefaultFormalParameter(node);
+  }
+
+  @override
   void visitDoStatement(DoStatement node) {
     computer._addRegion_token(node.doKeyword, HighlightRegionType.KEYWORD);
     computer._addRegion_token(node.whileKeyword, HighlightRegionType.KEYWORD);
@@ -475,6 +482,13 @@
   }
 
   @override
+  void visitFieldFormalParameter(FieldFormalParameter node) {
+    computer._addRegion_token(
+        node.requiredKeyword, HighlightRegionType.KEYWORD);
+    super.visitFieldFormalParameter(node);
+  }
+
+  @override
   void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
     computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD);
     super.visitForEachPartsWithDeclaration(node);
@@ -517,6 +531,13 @@
   }
 
   @override
+  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    computer._addRegion_token(
+        node.requiredKeyword, HighlightRegionType.KEYWORD);
+    super.visitFunctionTypedFormalParameter(node);
+  }
+
+  @override
   void visitGenericFunctionType(GenericFunctionType node) {
     computer._addRegion_token(
         node.functionKeyword, HighlightRegionType.KEYWORD);
@@ -685,6 +706,13 @@
   }
 
   @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    computer._addRegion_token(
+        node.requiredKeyword, HighlightRegionType.KEYWORD);
+    super.visitSimpleFormalParameter(node);
+  }
+
+  @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
     computer._addIdentifierRegion(node);
     super.visitSimpleIdentifier(node);
@@ -747,6 +775,7 @@
 
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
+    computer._addRegion_token(node.lateKeyword, HighlightRegionType.KEYWORD);
     computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD);
     super.visitVariableDeclarationList(node);
   }
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
index fe52ab6..21fd783 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
@@ -522,6 +522,13 @@
   }
 
   @override
+  void visitDefaultFormalParameter(DefaultFormalParameter node) {
+    computer._addRegion_token(
+        node.requiredKeyword, HighlightRegionType.KEYWORD);
+    super.visitDefaultFormalParameter(node);
+  }
+
+  @override
   void visitDoStatement(DoStatement node) {
     computer._addRegion_token(node.doKeyword, HighlightRegionType.KEYWORD);
     computer._addRegion_token(node.whileKeyword, HighlightRegionType.KEYWORD);
@@ -566,6 +573,13 @@
   }
 
   @override
+  void visitFieldFormalParameter(FieldFormalParameter node) {
+    computer._addRegion_token(
+        node.requiredKeyword, HighlightRegionType.KEYWORD);
+    super.visitFieldFormalParameter(node);
+  }
+
+  @override
   void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
     computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD);
     super.visitForEachPartsWithDeclaration(node);
@@ -608,6 +622,13 @@
   }
 
   @override
+  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    computer._addRegion_token(
+        node.requiredKeyword, HighlightRegionType.KEYWORD);
+    super.visitFunctionTypedFormalParameter(node);
+  }
+
+  @override
   void visitGenericFunctionType(GenericFunctionType node) {
     computer._addRegion_token(
         node.functionKeyword, HighlightRegionType.KEYWORD);
@@ -782,6 +803,13 @@
   }
 
   @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    computer._addRegion_token(
+        node.requiredKeyword, HighlightRegionType.KEYWORD);
+    super.visitSimpleFormalParameter(node);
+  }
+
+  @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
     computer._addIdentifierRegion(node);
     super.visitSimpleIdentifier(node);
@@ -844,6 +872,7 @@
 
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
+    computer._addRegion_token(node.lateKeyword, HighlightRegionType.KEYWORD);
     computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD);
     super.visitVariableDeclarationList(node);
   }
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index 4229e9c..102a46f 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -5,12 +5,14 @@
 import 'package:analysis_server/protocol/protocol_generated.dart'
     show HoverInformation;
 import 'package:analysis_server/src/computer/computer_overrides.dart';
+import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
+import 'package:path/path.dart' as path;
 
 /**
  * A computer for the hover at the specified offset of a Dart [CompilationUnit].
@@ -72,7 +74,25 @@
           // containing library
           LibraryElement library = element.library;
           if (library != null) {
-            hover.containingLibraryName = library.name;
+            Uri uri = library.source.uri;
+            if (uri.scheme != '' && uri.scheme == 'file') {
+              // for 'file:' URIs, use the path after the project root
+              AnalysisSession analysisSession = _unit.declaredElement.session;
+              path.Context context =
+                  analysisSession.resourceProvider.pathContext;
+              String projectRootDir =
+                  analysisSession.analysisContext.contextRoot.root.path;
+              String relativePath =
+                  context.relative(context.fromUri(uri), from: projectRootDir);
+              if (context.style == path.Style.windows) {
+                List<String> pathList = context.split(relativePath);
+                hover.containingLibraryName = pathList.join('/');
+              } else {
+                hover.containingLibraryName = relativePath;
+              }
+            } else {
+              hover.containingLibraryName = uri.toString();
+            }
             hover.containingLibraryPath = library.source.fullName;
           }
         }
@@ -107,7 +127,8 @@
 
   static String computeDocumentation(
       DartdocDirectiveInfo dartdocInfo, Element element) {
-    // TODO(dantup) We're reusing this in parameter information - move it somewhere shared?
+    // TODO(dantup) We're reusing this in parameter information - move it
+    // somewhere shared?
     if (element is FieldFormalParameterElement) {
       element = (element as FieldFormalParameterElement).field;
     }
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index 7b32719..e1b0c0e 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -21,7 +21,7 @@
   final Flutter flutter;
 
   DartUnitOutlineComputer(this.resolvedUnit, {this.withBasicFlutter: false})
-      : flutter = Flutter.of(resolvedUnit.session);
+      : flutter = Flutter.of(resolvedUnit);
 
   /**
    * Returns the computed outline, not `null`.
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 5066368..dfb5db4 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -287,6 +287,12 @@
   List<AnalysisDriver> getDriversInAnalysisRoot(Folder analysisRoot);
 
   /**
+   * Determine whether the given [path], when interpreted relative to innermost
+   * context root, contains a folder whose name starts with '.'.
+   */
+  bool isContainedInDotFolder(String path);
+
+  /**
    * Return `true` if the given [path] is ignored by a [ContextInfo] whose
    * folder contains it.
    */
@@ -349,6 +355,11 @@
   void afterWatchEvent(WatchEvent event);
 
   /**
+   * Called when analysis options or URI resolution in the [driver] are changed.
+   */
+  void analysisOptionsUpdated(AnalysisDriver driver);
+
+  /**
    * Called when the set of files associated with a context have changed (or
    * some of those files have been modified).  [changeSet] is the set of
    * changes that need to be applied to the context.
@@ -556,6 +567,15 @@
     return drivers;
   }
 
+  /**
+   * Determine whether the given [path], when interpreted relative to innermost
+   * context root, contains a folder whose name starts with '.'.
+   */
+  bool isContainedInDotFolder(String path) {
+    ContextInfo info = _getInnermostContextInfoFor(path);
+    return info != null && _isContainedInDotFolder(info.folder.path, path);
+  }
+
   @override
   bool isIgnored(String path) {
     ContextInfo info = rootInfo;
@@ -870,7 +890,7 @@
   }
 
   /**
-   * Use the given analysis [driver] to analyze the content of the 
+   * Use the given analysis [driver] to analyze the content of the
    * AndroidManifest file at the given [path].
    */
   void _analyzeManifestFile(AnalysisDriver driver, String path) {
@@ -1615,6 +1635,7 @@
         contextRoot: driver.contextRoot);
     SourceFactory factory = builder.createSourceFactory(contextRoot, options);
     driver.configure(analysisOptions: options, sourceFactory: factory);
+    callbacks.analysisOptionsUpdated(driver);
   }
 
   void _updateContextPackageUriResolver(Folder contextFolder) {
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 53a2d7f..78f7301 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -21,7 +21,6 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart' as engine;
 import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 import 'package:analyzer/src/generated/engine.dart' as engine;
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -89,7 +88,7 @@
     List<HoverInformation> hovers = <HoverInformation>[];
     if (unit != null) {
       HoverInformation hoverInformation = new DartUnitHoverComputer(
-              _getDartdocDirectiveInfoFor(result), unit, params.offset)
+              server.getDartdocDirectiveInfoFor(result), unit, params.offset)
           .compute();
       if (hoverInformation != null) {
         hovers.add(hoverInformation);
@@ -279,7 +278,7 @@
     // Ensure the offset provided is a valid location in the file.
     final unit = result.unit;
     final computer = new DartUnitSignatureComputer(
-        _getDartdocDirectiveInfoFor(result), unit, params.offset);
+        server.getDartdocDirectiveInfoFor(result), unit, params.offset);
     if (!computer.offsetIsValid) {
       server.sendResponse(new Response.getSignatureInvalidOffset(request));
       return;
@@ -509,12 +508,4 @@
     server.updateOptions(updaters);
     return new AnalysisUpdateOptionsResult().toResponse(request.id);
   }
-
-  DartdocDirectiveInfo _getDartdocDirectiveInfoFor(ResolvedUnitResult result) {
-    // TODO(brianwilkerson) Consider moving this to AnalysisServer.
-    return server.declarationsTracker
-            ?.getContext(result.session.analysisContext)
-            ?.dartdocDirectiveInfo ??
-        new DartdocDirectiveInfo();
-  }
 }
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 3951541..4f91833 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -19,6 +19,7 @@
 import 'package:analysis_server/src/services/completion/token_details/token_detail_builder.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/element/element.dart' as analyzer;
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -202,9 +203,20 @@
         var libraryPath = fileElement.element.librarySource.fullName;
 
         var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
-        var requestedLibraryElement = await session.getLibraryByUri(
-          library.uriStr,
-        );
+
+        analyzer.LibraryElement requestedLibraryElement;
+        try {
+          requestedLibraryElement = await session.getLibraryByUri(
+            library.uriStr,
+          );
+        } on ArgumentError catch (e) {
+          server.sendResponse(Response.invalidParameter(
+            request,
+            'uri',
+            'Invalid URI: ${library.uriStr}\n$e',
+          ));
+          return;
+        }
 
         var requestedElement =
             requestedLibraryElement.exportNamespace.get(requestedName);
@@ -252,6 +264,14 @@
 
   @override
   Response handleRequest(Request request) {
+    if (!server.options.featureSet.completion) {
+      return Response.invalidParameter(
+        request,
+        'request',
+        'The completion feature is not enabled',
+      );
+    }
+
     return runZoned(() {
       String requestName = request.method;
 
@@ -323,8 +343,6 @@
    * Process a `completion.getSuggestions` request.
    */
   Future<void> processRequest(Request request) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     performance = new CompletionPerformance();
 
     // extract and validate params
@@ -344,7 +362,7 @@
             request,
             'params.offset',
             'Expected offset between 0 and source length inclusive,'
-            ' but found $offset'));
+                ' but found $offset'));
         return;
       }
 
@@ -377,8 +395,13 @@
       includedElementKinds,
       includedSuggestionRelevanceTags,
     ).then((CompletionResult result) {
+      String libraryFile;
       List<IncludedSuggestionSet> includedSuggestionSets;
       if (includedElementKinds != null && resolvedUnit != null) {
+        libraryFile = resolvedUnit.libraryElement.source.fullName;
+        server.sendNotification(
+          createExistingImportsNotification(resolvedUnit),
+        );
         includedSuggestionSets = computeIncludedSetList(
           server.declarationsTracker,
           resolvedUnit,
@@ -394,6 +417,7 @@
         result.replacementOffset,
         result.replacementLength,
         result.suggestions,
+        libraryFile,
         includedSuggestionSets,
         includedElementKinds?.toList(),
         includedSuggestionRelevanceTags,
@@ -432,6 +456,7 @@
     int replacementOffset,
     int replacementLength,
     Iterable<CompletionSuggestion> results,
+    String libraryFile,
     List<IncludedSuggestionSet> includedSuggestionSets,
     List<ElementKind> includedElementKinds,
     List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags,
@@ -443,6 +468,7 @@
         replacementLength,
         results,
         true,
+        libraryFile: libraryFile,
         includedSuggestionSets: includedSuggestionSets,
         includedElementKinds: includedElementKinds,
         includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
@@ -465,13 +491,23 @@
     subscriptions.addAll(params.subscriptions);
 
     if (subscriptions.contains(CompletionService.AVAILABLE_SUGGESTION_SETS)) {
-      server.createDeclarationsTracker((change) {
+      var data = server.declarationsTrackerData;
+      var soFarLibraries = data.startListening((change) {
         server.sendNotification(
-          createCompletionAvailableSuggestionsNotification(change),
+          createCompletionAvailableSuggestionsNotification(
+            change.changed,
+            change.removed,
+          ),
         );
       });
+      server.sendNotification(
+        createCompletionAvailableSuggestionsNotification(
+          soFarLibraries,
+          [],
+        ),
+      );
     } else {
-      server.disposeDeclarationsTracker();
+      server.declarationsTrackerData.stopListening();
     }
 
     return CompletionSetSubscriptionsResult().toResponse(request.id);
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index bbe879f..0d1e4df 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -4,7 +4,9 @@
 
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/generated/utilities_general.dart';
 import 'package:analyzer/src/services/available_declarations.dart';
 
 /// Compute which suggestion sets should be included into completion inside
@@ -68,16 +70,92 @@
 
 /// Convert the [LibraryChange] into the corresponding protocol notification.
 protocol.Notification createCompletionAvailableSuggestionsNotification(
-  LibraryChange change,
+  List<Library> changed,
+  List<int> removed,
 ) {
   return protocol.CompletionAvailableSuggestionsParams(
-    changedLibraries: change.changed.map((library) {
+    changedLibraries: changed.map((library) {
       return _protocolAvailableSuggestionSet(library);
     }).toList(),
-    removedLibraries: change.removed,
+    removedLibraries: removed,
   ).toNotification();
 }
 
+/// Compute existing imports and elements that they provide.
+protocol.Notification createExistingImportsNotification(
+  ResolvedUnitResult resolvedUnit,
+) {
+  var uniqueStrings = _UniqueImportedStrings();
+  var uniqueElements = _UniqueImportedElements();
+  var existingImports = <protocol.ExistingImport>[];
+
+  var importElementList = resolvedUnit.libraryElement.imports;
+  for (var import in importElementList) {
+    var importedLibrary = import.importedLibrary;
+    if (importedLibrary == null) continue;
+
+    var importedUriStr = '${importedLibrary.librarySource.uri}';
+
+    var existingImportElements = <int>[];
+    for (var element in import.namespace.definedNames.values) {
+      if (element.librarySource != null) {
+        var index = uniqueElements.indexOf(uniqueStrings, element);
+        existingImportElements.add(index);
+      }
+    }
+
+    existingImports.add(protocol.ExistingImport(
+      uniqueStrings.indexOf(importedUriStr),
+      existingImportElements,
+    ));
+  }
+
+  return protocol.CompletionExistingImportsParams(
+    resolvedUnit.libraryElement.source.fullName,
+    protocol.ExistingImports(
+      protocol.ImportedElementSet(
+        uniqueStrings.values,
+        uniqueElements.uriList,
+        uniqueElements.nameList,
+      ),
+      existingImports,
+    ),
+  ).toNotification();
+}
+
+/// TODO(dantup): We need to expose this because the Declarations code currently
+/// returns declarations with DeclarationKinds but the DartCompletionManager
+/// gives us a list of "included ElementKinds". Maybe it would be better to expose
+/// includedDeclarationKinds and then just map that list to ElementKinds once in
+/// domain_completion for the original protocol?
+protocol.ElementKind protocolElementKind(DeclarationKind kind) {
+  switch (kind) {
+    case DeclarationKind.CLASS:
+      return protocol.ElementKind.CLASS;
+    case DeclarationKind.CLASS_TYPE_ALIAS:
+      return protocol.ElementKind.CLASS_TYPE_ALIAS;
+    case DeclarationKind.CONSTRUCTOR:
+      return protocol.ElementKind.CONSTRUCTOR;
+    case DeclarationKind.ENUM:
+      return protocol.ElementKind.ENUM;
+    case DeclarationKind.ENUM_CONSTANT:
+      return protocol.ElementKind.ENUM_CONSTANT;
+    case DeclarationKind.FUNCTION:
+      return protocol.ElementKind.FUNCTION;
+    case DeclarationKind.FUNCTION_TYPE_ALIAS:
+      return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
+    case DeclarationKind.GETTER:
+      return protocol.ElementKind.GETTER;
+    case DeclarationKind.MIXIN:
+      return protocol.ElementKind.MIXIN;
+    case DeclarationKind.SETTER:
+      return protocol.ElementKind.SETTER;
+    case DeclarationKind.VARIABLE:
+      return protocol.ElementKind.TOP_LEVEL_VARIABLE;
+  }
+  return protocol.ElementKind.UNKNOWN;
+}
+
 /// Computes the best URI to import [what] into the [unit] library.
 String _getRelativeFileUri(ResolvedUnitResult unit, Uri what) {
   if (what.scheme == 'file') {
@@ -106,6 +184,13 @@
     label = '${declaration.parent.name}.${declaration.name}';
   }
 
+  String declaringLibraryUri;
+  if (declaration.parent == null) {
+    declaringLibraryUri = '${declaration.locationLibraryUri}';
+  } else {
+    declaringLibraryUri = '${declaration.parent.locationLibraryUri}';
+  }
+
   List<String> relevanceTags;
   if (declaration.relevanceTags == null) {
     relevanceTags = null;
@@ -116,6 +201,7 @@
 
   return protocol.AvailableSuggestion(
     label,
+    declaringLibraryUri,
     _protocolElement(declaration),
     defaultArgumentListString: declaration.defaultArgumentListString,
     defaultArgumentListTextRanges: declaration.defaultArgumentListTextRanges,
@@ -147,7 +233,7 @@
 
 protocol.Element _protocolElement(Declaration declaration) {
   return protocol.Element(
-    _protocolElementKind(declaration.kind),
+    protocolElementKind(declaration.kind),
     declaration.name,
     _protocolElementFlags(declaration),
     location: protocol.Location(
@@ -172,34 +258,6 @@
   );
 }
 
-protocol.ElementKind _protocolElementKind(DeclarationKind kind) {
-  switch (kind) {
-    case DeclarationKind.CLASS:
-      return protocol.ElementKind.CLASS;
-    case DeclarationKind.CLASS_TYPE_ALIAS:
-      return protocol.ElementKind.CLASS_TYPE_ALIAS;
-    case DeclarationKind.CONSTRUCTOR:
-      return protocol.ElementKind.CONSTRUCTOR;
-    case DeclarationKind.ENUM:
-      return protocol.ElementKind.ENUM;
-    case DeclarationKind.ENUM_CONSTANT:
-      return protocol.ElementKind.ENUM_CONSTANT;
-    case DeclarationKind.FUNCTION:
-      return protocol.ElementKind.FUNCTION;
-    case DeclarationKind.FUNCTION_TYPE_ALIAS:
-      return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
-    case DeclarationKind.GETTER:
-      return protocol.ElementKind.GETTER;
-    case DeclarationKind.MIXIN:
-      return protocol.ElementKind.MIXIN;
-    case DeclarationKind.SETTER:
-      return protocol.ElementKind.SETTER;
-    case DeclarationKind.VARIABLE:
-      return protocol.ElementKind.TOP_LEVEL_VARIABLE;
-  }
-  return protocol.ElementKind.UNKNOWN;
-}
-
 class CompletionLibrariesWorker implements SchedulerWorker {
   final DeclarationsTracker tracker;
 
@@ -219,3 +277,108 @@
     tracker.doWork();
   }
 }
+
+class DeclarationsTrackerData {
+  final DeclarationsTracker _tracker;
+
+  /// The set of libraries reported by [_tracker] so far.
+  ///
+  /// We create [_tracker] at the server start, but the completion domain
+  /// should send available declarations only when the corresponding
+  /// subscription is done. OTOH, we don't want the changes stream grow
+  /// infinitely as the same libraries are changed multiple times. So, we drain
+  /// the changes stream in this map, and send it at subscription.
+  final Map<int, Library> _idToLibrary = {};
+
+  /// When the completion domain subscribes for changes, we start redirecting
+  /// changes to this listener.
+  void Function(LibraryChange) _listener = null;
+
+  DeclarationsTrackerData(this._tracker) {
+    _tracker.changes.listen((change) {
+      if (_listener != null) {
+        _listener(change);
+      } else {
+        for (var library in change.changed) {
+          _idToLibrary[library.id] = library;
+        }
+        for (var id in change.removed) {
+          _idToLibrary.remove(id);
+        }
+      }
+    });
+  }
+
+  /// Start listening for available libraries, and return the libraries that
+  /// were accumulated so far.
+  List<Library> startListening(void Function(LibraryChange) listener) {
+    if (_listener != null) {
+      throw StateError('Already listening.');
+    }
+    _listener = listener;
+
+    var accumulatedLibraries = _idToLibrary.values.toList();
+    _idToLibrary.clear();
+    return accumulatedLibraries;
+  }
+
+  void stopListening() {
+    if (_listener == null) {
+      throw StateError('Not listening.');
+    }
+    _listener = null;
+  }
+}
+
+class _ImportedElement {
+  final int uri;
+  final int name;
+
+  @override
+  final int hashCode;
+
+  _ImportedElement(this.uri, this.name)
+      : hashCode = JenkinsSmiHash.hash2(uri, name);
+
+  @override
+  bool operator ==(other) {
+    return other is _ImportedElement && other.uri == uri && other.name == name;
+  }
+}
+
+class _UniqueImportedElements {
+  final map = <_ImportedElement, int>{};
+
+  List<int> get nameList => map.keys.map((e) => e.name).toList();
+
+  List<int> get uriList => map.keys.map((e) => e.uri).toList();
+
+  int indexOf(_UniqueImportedStrings strings, Element element) {
+    var uriStr = '${element.librarySource.uri}';
+    var wrapper = _ImportedElement(
+      strings.indexOf(uriStr),
+      strings.indexOf(element.name),
+    );
+    var index = map[wrapper];
+    if (index == null) {
+      index = map.length;
+      map[wrapper] = index;
+    }
+    return index;
+  }
+}
+
+class _UniqueImportedStrings {
+  final map = <String, int>{};
+
+  List<String> get values => map.keys.toList();
+
+  int indexOf(String str) {
+    var index = map[str];
+    if (index == null) {
+      index = map.length;
+      map[str] = index;
+    }
+    return index;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
index 0525b77..d14c29a 100644
--- a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
@@ -132,6 +132,7 @@
         listener.otherSuggestions,
         hasErrors,
         listener.sourceChange.edits,
+        details: listener.details,
       ).toResponse(request.id);
     } finally {
       server.contextManager.driverMap.values
@@ -143,6 +144,7 @@
       listener.otherSuggestions,
       hasErrors,
       listener.sourceChange.edits,
+      details: listener.details,
     ).toResponse(request.id);
   }
 
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index dbbd2d4..5941656 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -23,6 +23,7 @@
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/services/correction/fix/analysis_options/fix_generator.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/fix/manifest/fix_generator.dart';
 import 'package:analysis_server/src/services/correction/fix/pubspec/fix_generator.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
@@ -634,7 +635,16 @@
         int errorLine = lineInfo.getLocation(error.offset).lineNumber;
         if (errorLine == requestLine) {
           var workspace = DartChangeWorkspace(server.currentSessions);
-          var context = new DartFixContextImpl(workspace, result, error);
+          var context =
+              new DartFixContextImpl(workspace, result, error, (name) {
+            var tracker = server.declarationsTracker;
+            var provider = TopLevelDeclarationsProvider(tracker);
+            return provider.get(
+              result.session.analysisContext,
+              result.path,
+              name,
+            );
+          });
           List<Fix> fixes =
               await new DartFixContributor().computeFixes(context);
           if (fixes.isNotEmpty) {
@@ -810,7 +820,7 @@
           // try RENAME
           {
             RenameRefactoring renameRefactoring = new RenameRefactoring(
-                refactoringWorkspace, resolvedUnit.session, element);
+                refactoringWorkspace, resolvedUnit, element);
             if (renameRefactoring != null) {
               kinds.add(RefactoringKind.RENAME);
             }
@@ -1148,13 +1158,11 @@
       }
     }
     if (kind == RefactoringKind.MOVE_FILE) {
-      // TODO(brianwilkerson) Re-implement this refactoring under the new analysis driver
-//      _resetOnAnalysisStarted();
-//      ContextSourcePair contextSource = server.getContextSourcePair(file);
-//      engine.AnalysisContext context = contextSource.context;
-//      Source source = contextSource.source;
-//      refactoring = new MoveFileRefactoring(
-//          server.resourceProvider, searchEngine, context, source, file);
+      var resolvedUnit = await server.getResolvedUnit(file);
+      if (resolvedUnit != null) {
+        refactoring = new MoveFileRefactoring(
+            server.resourceProvider, refactoringWorkspace, resolvedUnit, file);
+      }
     }
     if (kind == RefactoringKind.RENAME) {
       var resolvedUnit = await server.getResolvedUnit(file);
@@ -1166,8 +1174,8 @@
               RenameRefactoring.getElementToRename(node, element);
 
           // do create the refactoring
-          refactoring = new RenameRefactoring(refactoringWorkspace,
-              resolvedUnit.session, renameElement.element);
+          refactoring = new RenameRefactoring(
+              refactoringWorkspace, resolvedUnit, renameElement.element);
           feedback = new RenameFeedback(
               renameElement.offset, renameElement.length, 'kind', 'oldName');
         }
diff --git a/pkg/analysis_server/lib/src/edit/fix/dartfix_info.dart b/pkg/analysis_server/lib/src/edit/fix/dartfix_info.dart
index 728bb580..421b8cc 100644
--- a/pkg/analysis_server/lib/src/edit/fix/dartfix_info.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/dartfix_info.dart
@@ -16,29 +16,97 @@
 
 const allFixes = <DartFixInfo>[
   //
-  // Required fixes
+  // Fixes enabled by default
   //
   const DartFixInfo(
     'fix-named-constructor-type-arguments',
-    'Move named constructor type arguments from the name to the type.',
+    '''
+Move named constructor type arguments from the name to the type.
+
+For example, this
+  new List.filled<String>(20, 'value');
+
+will be converted to
+  new List<String>.filled(20, 'value');''',
     FixErrorTask.fixNamedConstructorTypeArgs,
     isRequired: true,
   ),
   const DartFixInfo(
     'use-mixin',
-    'Convert classes used as a mixin to the new mixin syntax.',
+    '''
+Convert classes used as a mixin to the new mixin syntax.
+
+For example, this
+  class C with M { }
+  class M { }
+
+will be converted to
+  class C with M { }
+  mixin M { }
+
+There are several situations where a class cannot be automatically converted
+to a mixin such as when the class contains a constructor. In that situation
+a message is displayed and the class is not converted to a mixin.''',
     PreferMixinFix.task,
     isRequired: true,
   ),
   //
-  // Suggested fixes
+  // Fixes that may be explicitly enabled
   //
   const DartFixInfo(
     'double-to-int',
-    'Find double literals ending in .0 and remove the .0\n'
-    'wherever double context can be inferred.',
+    '''
+Find double literals ending in .0 and remove the .0
+wherever double context can be inferred.
+
+For example, this
+  const double myDouble = 8.0;
+
+will be converted to
+  const double myDouble = 8;''',
     PreferIntLiteralsFix.task,
   ),
+  const DartFixInfo(
+    'use-spread-collections',
+    '''
+Convert to using collection spread operators.
+
+For example, this
+  var l1 = ['b'];
+  var l2 = ['a']..addAll(l1);
+
+will be converted to
+  var l1 = ['b'];
+  var l2 = ['a', ...l1];''',
+    PreferSpreadCollectionsFix.task,
+    isDefault: false,
+  ),
+  const DartFixInfo(
+    'collection-if-elements',
+    '''
+Convert to using if elements when building collections.
+
+For example, this
+  f(bool b) => ['a', b ? 'c' : 'd', 'e'];
+
+will be converted to
+  f(bool b) => ['a', if (b) 'c' else 'd', 'e'];''',
+    PreferIfElementsToConditionalExpressionsFix.task,
+    isDefault: false,
+  ),
+  const DartFixInfo(
+    'map-for-elements',
+    '''
+Convert to for elements when building maps from iterables.
+
+For example, this
+  Map<int, int>.fromIterable([1, 2, 3], key: (i) => i, value: (i) => i * 2)
+
+will be converted to
+  <int, int>{ for(int i in [1, 2, 3]) i : i * 2, }''',
+    PreferForElementsToMapFromIterableFix.task,
+    isDefault: false,
+  ),
   //
   // Experimental fixes
   //
@@ -46,30 +114,13 @@
     'non-nullable',
     // TODO(danrubel) update description and make default/required
     // when NNBD fix is ready
-    'Experimental: Update sources to be non-nullable by default.\n'
-    'Requires the experimental non-nullable flag to be enabled.\n'
-    'This is not applied unless explicitly included.',
+    '''
+EXPERIMENTAL: Update sources to be non-nullable by default.
+This requires the experimental non-nullable flag to be enabled
+when running the updated application.''',
     NonNullableFix.task,
     isDefault: false,
   ),
-  const DartFixInfo(
-    'use-spread-collections',
-    'Convert to using collection spread operators.',
-    PreferSpreadCollectionsFix.task,
-    isDefault: false,
-  ),
-  const DartFixInfo(
-    'collection-if-elements',
-    'Convert to using if elements when building collections.',
-    PreferIfElementsToConditionalExpressionsFix.task,
-    isDefault: false,
-  ),
-  const DartFixInfo(
-    'map-for-elements',
-    'Convert to for elements when building maps from iterables.',
-    PreferForElementsToMapFromIterableFix.task,
-    isDefault: false,
-  ),
 ];
 
 /// [DartFixInfo] represents a fix that can be applied by [EditDartFix].
diff --git a/pkg/analysis_server/lib/src/edit/fix/dartfix_listener.dart b/pkg/analysis_server/lib/src/edit/fix/dartfix_listener.dart
index c1e9639..58657c0 100644
--- a/pkg/analysis_server/lib/src/edit/fix/dartfix_listener.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/dartfix_listener.dart
@@ -17,8 +17,19 @@
   final List<DartFixSuggestion> otherSuggestions = <DartFixSuggestion>[];
   final SourceChange sourceChange = new SourceChange('dartfix');
 
+  /// The details to be returned to the client.
+  List<String> details = [];
+
   DartFixListener(this.server);
 
+  /// Add the given [detail] to the list of details to be returned to the
+  /// client.
+  void addDetail(String detail) {
+    if (details.length < 200) {
+      details.add(detail);
+    }
+  }
+
   /// Record an edit to be sent to the client.
   ///
   /// The associated suggestion should be separately added by calling
diff --git a/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart b/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
index e71fd1d..378b3b1 100644
--- a/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
@@ -28,7 +28,12 @@
 
   Future<void> fixError(ResolvedUnitResult result, AnalysisError error) async {
     final workspace = DartChangeWorkspace(listener.server.currentSessions);
-    final dartContext = new DartFixContextImpl(workspace, result, error);
+    final dartContext = new DartFixContextImpl(
+      workspace,
+      result,
+      error,
+      (name) => [],
+    );
     final processor = new FixProcessor(dartContext);
     Fix fix = await processor.computeFix();
     final location = listener.locationFor(result, error.offset, error.length);
diff --git a/pkg/analysis_server/lib/src/edit/fix/fix_lint_task.dart b/pkg/analysis_server/lib/src/edit/fix/fix_lint_task.dart
index 0885046..0a68bcf 100644
--- a/pkg/analysis_server/lib/src/edit/fix/fix_lint_task.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/fix_lint_task.dart
@@ -18,71 +18,6 @@
 import 'package:front_end/src/scanner/token.dart';
 import 'package:source_span/src/span.dart';
 
-/// A task for fixing a particular lint.
-/// Subclasses should implement [applyLocalFixes] and [applyRemainingFixes]
-/// and may override any of the reportSomething() methods as needed.
-abstract class FixLintTask implements ErrorReporter {
-  final DartFixListener listener;
-
-  @override
-  Source source;
-
-  FixLintTask(this.listener);
-
-  /// Apply fixes for the current compilation unit.
-  Future<void> applyLocalFixes(ResolvedUnitResult result);
-
-  /// Apply any fixes remaining after all local changes have been applied.
-  Future<void> applyRemainingFixes();
-
-  @override
-  void reportError(AnalysisError error) {
-    // ignored
-  }
-
-  @override
-  void reportErrorForElement(ErrorCode errorCode, Element element,
-      [List<Object> arguments]) {
-    // ignored
-  }
-
-  @override
-  void reportErrorForNode(ErrorCode errorCode, AstNode node,
-      [List<Object> arguments]) {
-    // ignored
-  }
-
-  @override
-  void reportErrorForOffset(ErrorCode errorCode, int offset, int length,
-      [List<Object> arguments]) {
-    // ignored
-  }
-
-  @override
-  void reportErrorForSpan(ErrorCode errorCode, SourceSpan span,
-      [List<Object> arguments]) {
-    // ignored
-  }
-
-  @override
-  void reportErrorForToken(ErrorCode errorCode, Token token,
-      [List<Object> arguments]) {
-    // ignored
-  }
-
-  @override
-  void reportErrorMessage(
-      ErrorCode errorCode, int offset, int length, Message message) {
-    // ignored
-  }
-
-  @override
-  void reportTypeErrorForNode(
-      ErrorCode errorCode, AstNode node, List<Object> arguments) {
-    // ignored
-  }
-}
-
 /// A processor used by [EditDartFix] to manage [FixLintTask]s.
 mixin FixLintProcessor {
   final linters = <Linter>[];
@@ -168,3 +103,68 @@
     lint.reporter = task;
   }
 }
+
+/// A task for fixing a particular lint.
+/// Subclasses should implement [applyLocalFixes] and [applyRemainingFixes]
+/// and may override any of the reportSomething() methods as needed.
+abstract class FixLintTask implements ErrorReporter {
+  final DartFixListener listener;
+
+  @override
+  Source source;
+
+  FixLintTask(this.listener);
+
+  /// Apply fixes for the current compilation unit.
+  Future<void> applyLocalFixes(ResolvedUnitResult result);
+
+  /// Apply any fixes remaining after all local changes have been applied.
+  Future<void> applyRemainingFixes();
+
+  @override
+  void reportError(AnalysisError error) {
+    // ignored
+  }
+
+  @override
+  void reportErrorForElement(ErrorCode errorCode, Element element,
+      [List<Object> arguments]) {
+    // ignored
+  }
+
+  @override
+  void reportErrorForNode(ErrorCode errorCode, AstNode node,
+      [List<Object> arguments]) {
+    // ignored
+  }
+
+  @override
+  void reportErrorForOffset(ErrorCode errorCode, int offset, int length,
+      [List<Object> arguments]) {
+    // ignored
+  }
+
+  @override
+  void reportErrorForSpan(ErrorCode errorCode, SourceSpan span,
+      [List<Object> arguments]) {
+    // ignored
+  }
+
+  @override
+  void reportErrorForToken(ErrorCode errorCode, Token token,
+      [List<Object> arguments]) {
+    // ignored
+  }
+
+  @override
+  void reportErrorMessage(
+      ErrorCode errorCode, int offset, int length, Message message) {
+    // ignored
+  }
+
+  @override
+  void reportTypeErrorForNode(
+      ErrorCode errorCode, AstNode node, List<Object> arguments) {
+    // ignored
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
index 61d3984..ae1db3e 100644
--- a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
@@ -5,14 +5,14 @@
 import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
 import 'package:analysis_server/src/edit/fix/fix_code_task.dart';
-import 'package:analysis_server/src/nullability/provisional_api.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
-import 'package:yaml/yaml.dart';
 import 'package:source_span/source_span.dart';
+import 'package:yaml/yaml.dart';
 
 /// [NonNullableFix] visits each named type in a resolved compilation unit
 /// and determines whether the associated variable or parameter can be null
@@ -105,6 +105,7 @@
             content = '''
 
     - non-nullable''';
+            return null;
           },
         );
       }
@@ -142,20 +143,6 @@
     }
   }
 
-  void processYamlException(String action, String optionsFilePath, error) {
-    listener.addRecommendation('''Failed to $action options file
-  $optionsFilePath
-  $error
-
-  Manually update this file to enable non-nullable by adding:
-
-    analyzer:
-      enable-experiment:
-        - non-nullable
-''');
-    _packageIsNNBD = false;
-  }
-
   @override
   Future<void> processUnit(int phase, ResolvedUnitResult result) async {
     if (!_packageIsNNBD) {
@@ -173,6 +160,20 @@
     }
   }
 
+  void processYamlException(String action, String optionsFilePath, error) {
+    listener.addRecommendation('''Failed to $action options file
+  $optionsFilePath
+  $error
+
+  Manually update this file to enable non-nullable by adding:
+
+    analyzer:
+      enable-experiment:
+        - non-nullable
+''');
+    _packageIsNNBD = false;
+  }
+
   static void task(DartFixRegistrar registrar, DartFixListener listener) {
     registrar.registerCodeTask(new NonNullableFix(listener));
   }
@@ -184,6 +185,11 @@
   NullabilityMigrationAdapter(this.listener);
 
   @override
+  void addDetail(String detail) {
+    listener.addDetail(detail);
+  }
+
+  @override
   void addEdit(SingleNullabilityFix fix, SourceEdit edit) {
     listener.addEditWithoutSuggestion(fix.source, edit);
   }
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
index 2df986e..6330e82 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
@@ -50,7 +50,7 @@
       withBasicFlutter: false,
     ).compute();
 
-    flutter = Flutter.of(resolvedUnit.session);
+    flutter = Flutter.of(resolvedUnit);
 
     // Find widget classes.
     // IDEA plugin only supports rendering widgets in libraries.
@@ -63,7 +63,20 @@
     var flutterDartOutline = _convert(dartOutline);
 
     // Create outlines for widgets.
-    resolvedUnit.unit.accept(new _FlutterOutlineBuilder(this));
+    var visitor = new _FlutterOutlineBuilder(this);
+    resolvedUnit.unit.accept(visitor);
+
+    // Associate Flutter outlines with Dart outlines.
+    for (var outline in visitor.outlines) {
+      for (var parent in _depthFirstOrder) {
+        if (parent.offset < outline.offset &&
+            outline.offset + outline.length < parent.offset + parent.length) {
+          parent.children ??= <protocol.FlutterOutline>[];
+          parent.children.add(outline);
+          break;
+        }
+      }
+    }
 
     // Compute instrumented code.
     if (widgets.values.any((w) => w.hasDesignTimeConstructor)) {
@@ -224,8 +237,14 @@
             }
           }
         } else {
-          ParameterElement parameter = argument.staticParameterElement;
-          _addAttribute(attributes, argument, parameter);
+          var visitor = _FlutterOutlineBuilder(this);
+          argument.accept(visitor);
+          if (visitor.outlines.isNotEmpty) {
+            children.addAll(visitor.outlines);
+          } else {
+            ParameterElement parameter = argument.staticParameterElement;
+            _addAttribute(attributes, argument, parameter);
+          }
         }
       }
 
@@ -385,6 +404,7 @@
 
 class _FlutterOutlineBuilder extends GeneralizingAstVisitor<void> {
   final FlutterOutlineComputer computer;
+  final List<protocol.FlutterOutline> outlines = [];
 
   _FlutterOutlineBuilder(this.computer);
 
@@ -392,14 +412,7 @@
   void visitExpression(Expression node) {
     var outline = computer._createOutline(node, false);
     if (outline != null) {
-      for (var parent in computer._depthFirstOrder) {
-        if (parent.offset < outline.offset &&
-            outline.offset + outline.length < parent.offset + parent.length) {
-          parent.children ??= <protocol.FlutterOutline>[];
-          parent.children.add(outline);
-          return;
-        }
-      }
+      outlines.add(outline);
     } else {
       super.visitExpression(node);
     }
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index 2c4999c..1801317 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -4,14 +4,57 @@
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 
+/// Set the characters that will cause the editor to automatically
+/// trigger completion.
+/// TODO(dantup): There are several characters that we want to conditionally
+/// allow to trigger completion, but they can only be added when the completion
+/// provider is able to handle them in context:
+///
+///    {   trigger if being typed in a string immediately after a $
+///    '   trigger if the opening quote for an import/export
+///    "   trigger if the opening quote for an import/export
+///    /   trigger if as part of a path in an import/export
+///    \   trigger if as part of a path in an import/export
+///    :   don't trigger when typing case expressions (`case x:`)
+///
+/// Additionally, we need to prefix `filterText` on completion items
+/// with spaces for those that can follow whitespace (eg. `foo` in
+/// `myArg: foo`) to ensure they're not filtered away when the user
+/// types space.
+///
+/// See https://github.com/Dart-Code/Dart-Code/blob/68d1cd271e88a785570257d487adbdec17abd6a3/src/providers/dart_completion_item_provider.ts#L36-L64
+/// for the VS Code implementation of this.
+const dartCompletionTriggerCharacters = ['.', '=', '(', r'$'];
+
+/// TODO(dantup): Signature help triggering is even more sensitive to
+/// bad chars, so we'll need to implement the logic described here:
+/// https://github.com/dart-lang/sdk/issues/34241
+const dartSignatureHelpTriggerCharacters = <String>[];
+
+/// Characters to trigger formatting when format-on-type is enabled.
+const dartTypeFormattingCharacters = ['}', ';'];
+
 /// Constants for command IDs that are exchanged between LSP client/server.
 abstract class Commands {
   /// A list of all commands IDs that can be sent to the client to inform which
   /// commands should be sent to the server for execution (as opposed to being
   /// executed in the local plugin).
-  static const serverSupportedCommands = [sortMembers, organizeImports];
+  static const serverSupportedCommands = [
+    sortMembers,
+    organizeImports,
+    sendWorkspaceEdit,
+  ];
   static const sortMembers = 'edit.sortMembers';
   static const organizeImports = 'edit.organizeImports';
+  static const sendWorkspaceEdit = 'edit.sendWorkspaceEdit';
+}
+
+abstract class CustomMethods {
+  static const DiagnosticServer = const Method('dart/diagnosticServer');
+  static const PublishClosingLabels =
+      const Method('dart/textDocument/publishClosingLabels');
+  static const Super = const Method('dart/textDocument/super');
+  static const AnalyzerStatus = const Method(r'$/analyzerStatus');
 }
 
 /// CodeActionKinds supported by the server that are not declared in the LSP spec.
@@ -41,7 +84,6 @@
   static const FileHasErrors = const ErrorCodes(-32008);
   static const ClientFailedToApplyEdit = const ErrorCodes(-32009);
   static const RenameNotValid = const ErrorCodes(-32010);
-  static const ServerShuttingDown = const ErrorCodes(-32011);
 
   /// An error raised when the server detects that the server and client are out
   /// of sync and cannot recover. For example if a textDocument/didChange notification
@@ -57,7 +99,3 @@
   ///   if it crashes 5 times in the last 180 seconds."
   static const ClientServerInconsistentState = const ErrorCodes(-32010);
 }
-
-abstract class CustomMethods {
-  static const DiagnosticServer = const Method('dart/diagnosticServer');
-}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
index 674201f..9c4b4d6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
@@ -49,7 +49,7 @@
       final organizer = new DirectiveOrganizer(code, unit, result.errors);
       final edits = organizer.organize();
 
-      return sendEditsToClient(docIdentifier, unit, edits);
+      return sendSourceEditsToClient(docIdentifier, unit, edits);
     });
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/send_workspace_edit.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/send_workspace_edit.dart
new file mode 100644
index 0000000..99b061f
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/send_workspace_edit.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/handlers/commands/simple_edit_handler.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+
+/// This command allows a client to request the server send it a
+/// workspace/applyEdit command, simply passing through the edits provided
+/// by the client. This is to handle completion items that need to make edits
+/// in files other than those containing the completion (not natively supported
+/// by LSP). The edits are put into the [CompletionItem]s command field/
+/// args and when the client calls the server to execute that command, the server
+/// will call the client to execute workspace/applyEdit.
+class SendWorkspaceEditCommandHandler extends SimpleEditCommandHandler {
+  SendWorkspaceEditCommandHandler(LspAnalysisServer server) : super(server);
+
+  @override
+  String get commandName => 'Send Workspace Edit';
+
+  @override
+  Future<ErrorOr<void>> handle(List<dynamic> arguments) async {
+    if (arguments == null ||
+        arguments.length != 1 ||
+        arguments[0] is! Map<String, dynamic>) {
+      return ErrorOr.error(new ResponseError(
+        ServerErrorCodes.InvalidCommandArguments,
+        '$commandName requires a single List argument of WorkspaceEdit',
+        null,
+      ));
+    }
+
+    final workspaceEdit = WorkspaceEdit.fromJson(arguments[0]);
+
+    return await sendWorkspaceEditToClient(workspaceEdit);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
index 64c5877..0e60476 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
@@ -23,7 +23,7 @@
 
   String get commandName;
 
-  Future<ErrorOr<void>> sendEditsToClient(
+  Future<ErrorOr<void>> sendSourceEditsToClient(
       VersionedTextDocumentIdentifier docIdentifier,
       CompilationUnit unit,
       List<SourceEdit> edits) async {
@@ -38,6 +38,11 @@
       [new FileEditInformation(docIdentifier, unit.lineInfo, edits)],
     );
 
+    return sendWorkspaceEditToClient(workspaceEdit);
+  }
+
+  Future<ErrorOr<void>> sendWorkspaceEditToClient(
+      WorkspaceEdit workspaceEdit) async {
     // Send the edit to the client via a applyEdit request (this is a request
     // from server -> client and the client will provide a response).
     final editResponse = await server.sendRequest(Method.workspace_applyEdit,
@@ -63,7 +68,8 @@
     } else {
       return error(
         ServerErrorCodes.ClientFailedToApplyEdit,
-        'Client failed to apply workspace edit for $commandName',
+        'Client failed to apply workspace edit for $commandName '
+        '(reason: ${editResponseResult.failureReason ?? 'Client did not provide a reason'})',
         workspaceEdit.toString(),
       );
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
index 680d466..e1aba44 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
@@ -55,6 +55,6 @@
 
     final sorter = new MemberSorter(code, unit);
     final edits = sorter.sort();
-    return await sendEditsToClient(docIdentifier, unit, edits);
+    return await sendSourceEditsToClient(docIdentifier, unit, edits);
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
index 5d75dde..e4f255e 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
@@ -20,7 +20,8 @@
   LspJsonHandler<void> get jsonHandler => NullJsonHandler;
 
   @override
-  Future<ErrorOr<DartDiagnosticServer>> handle(void _) async {
+  Future<ErrorOr<DartDiagnosticServer>> handle(
+      void _, CancellationToken token) async {
     final port = await server.diagnosticServer.getServerPort();
     return success(new DartDiagnosticServer(port));
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart
new file mode 100644
index 0000000..ab45764
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/mapping.dart';
+import 'package:analysis_server/src/search/type_hierarchy.dart';
+
+class SuperHandler
+    extends MessageHandler<TextDocumentPositionParams, Location> {
+  SuperHandler(LspAnalysisServer server) : super(server);
+  Method get handlesMessage => CustomMethods.Super;
+
+  @override
+  LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
+      TextDocumentPositionParams.jsonHandler;
+
+  @override
+  Future<ErrorOr<Location>> handle(
+      TextDocumentPositionParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success(null);
+    }
+
+    final pos = params.position;
+    final path = pathOfDoc(params.textDocument);
+    final unit = await path.mapResult(requireResolvedUnit);
+    final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
+
+    return offset.mapResult((offset) async {
+      var node = await server.getNodeAtOffset(path.result, offset);
+      if (node == null) {
+        return success(null);
+      }
+
+      // Walk up the nodes until we find one that has an element so we can support
+      // finding supers even if the cursor location was inside a method or on its
+      // return type.
+      var element = server.getElementOfNode(node);
+      while (element == null && node.parent != null) {
+        node = node.parent;
+        element = server.getElementOfNode(node);
+      }
+      if (element == null) {
+        return success(null);
+      }
+
+      final computer = TypeHierarchyComputer(server.searchEngine, element);
+      final items = computer.computeSuper();
+
+      // We expect to get at least two items back - the first will be the input
+      // element so we start looking from the second.
+      if (items == null || items.length < 2) {
+        return success(null);
+      }
+
+      // The class will have a memberElement if we were searching for an element
+      // otherwise we're looking for a class.
+      final isMember = items.first.memberElement != null;
+      final superItem = items.skip(1).firstWhere(
+            (elm) =>
+                isMember ? elm.memberElement != null : elm.classElement != null,
+            orElse: () => null,
+          );
+
+      if (superItem == null) {
+        return success(null);
+      }
+
+      final location = isMember
+          ? superItem.memberElement.location
+          : superItem.classElement.location;
+
+      return success(toLocation(location, server.getLineInfo(location.file)));
+    });
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart
new file mode 100644
index 0000000..c21782c
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+
+class CancelRequestHandler extends MessageHandler<CancelParams, void> {
+  Map<String, CancelableToken> _tokens = {};
+
+  CancelRequestHandler(LspAnalysisServer server) : super(server);
+
+  Method get handlesMessage => Method.cancelRequest;
+
+  @override
+  LspJsonHandler<CancelParams> get jsonHandler => CancelParams.jsonHandler;
+
+  void clearToken(RequestMessage message) {
+    _tokens.remove(message.id.toString());
+  }
+
+  CancelableToken createToken(RequestMessage message) {
+    final token = new CancelableToken();
+    _tokens[message.id.toString()] = token;
+    return token;
+  }
+
+  ErrorOr<void> handle(CancelParams params, CancellationToken token) {
+    // Don't assume this is in the map as it's possible the client sent a
+    // cancellation that we processed after already starting to send the response
+    // and cleared the token.
+    _tokens[params.id.toString()]?.cancel();
+    return success();
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
index c43057f..c518c93 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
@@ -21,7 +21,8 @@
   LspJsonHandler<DidChangeWorkspaceFoldersParams> get jsonHandler =>
       DidChangeWorkspaceFoldersParams.jsonHandler;
 
-  ErrorOr<void> handle(DidChangeWorkspaceFoldersParams params) {
+  ErrorOr<void> handle(
+      DidChangeWorkspaceFoldersParams params, CancellationToken token) {
     // Don't do anything if our analysis roots are not based on open workspaces.
     if (!updateAnalysisRoots) {
       return success();
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index c55a22e..326b25a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -17,6 +17,7 @@
 import 'package:analysis_server/src/services/correction/assist_internal.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart'
@@ -33,9 +34,16 @@
       CodeActionParams.jsonHandler;
 
   Future<ErrorOr<List<Either2<Command, CodeAction>>>> handle(
-      CodeActionParams params) async {
+      CodeActionParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success(const []);
+    }
+
     final capabilities = server?.clientCapabilities?.textDocument?.codeAction;
 
+    final clientSupportsWorkspaceApplyEdit =
+        server?.clientCapabilities?.workspace?.applyEdit == true;
+
     final clientSupportsLiteralCodeActions =
         capabilities?.codeActionLiteralSupport != null;
 
@@ -55,6 +63,7 @@
           return _getCodeActions(
               clientSupportedCodeActionKinds,
               clientSupportsLiteralCodeActions,
+              clientSupportsWorkspaceApplyEdit,
               path.result,
               params.range,
               offset,
@@ -88,7 +97,7 @@
       assist.change.message,
       CodeActionKind.Refactor,
       const [],
-      createWorkspaceEdit(server, assist.change),
+      createWorkspaceEdit(server, assist.change.edits),
       null,
     ));
   }
@@ -103,7 +112,7 @@
       fix.change.message,
       CodeActionKind.QuickFix,
       [diagnostic],
-      createWorkspaceEdit(server, fix.change),
+      createWorkspaceEdit(server, fix.change.edits),
       null,
     ));
   }
@@ -144,6 +153,7 @@
   Future<ErrorOr<List<Either2<Command, CodeAction>>>> _getCodeActions(
     HashSet<CodeActionKind> kinds,
     bool supportsLiterals,
+    bool supportsWorkspaceApplyEdit,
     String path,
     Range range,
     int offset,
@@ -151,7 +161,8 @@
     ResolvedUnitResult unit,
   ) async {
     final results = await Future.wait([
-      _getSourceActions(kinds, supportsLiterals, path),
+      _getSourceActions(
+          kinds, supportsLiterals, supportsWorkspaceApplyEdit, path),
       _getAssistActions(kinds, supportsLiterals, offset, length, unit),
       _getRefactorActions(kinds, supportsLiterals, path, range, unit),
       _getFixActions(kinds, supportsLiterals, range, unit),
@@ -182,7 +193,14 @@
         int errorLine = lineInfo.getLocation(error.offset).lineNumber - 1;
         if (errorLine >= range.start.line && errorLine <= range.end.line) {
           var workspace = DartChangeWorkspace(server.currentSessions);
-          var context = new DartFixContextImpl(workspace, unit, error);
+          var context = new DartFixContextImpl(workspace, unit, error, (name) {
+            var tracker = server.declarationsTracker;
+            return TopLevelDeclarationsProvider(tracker).get(
+              unit.session.analysisContext,
+              unit.path,
+              name,
+            );
+          });
           final fixes = await fixContributor.computeFixes(context);
           if (fixes.isNotEmpty) {
             fixes.sort(Fix.SORT_BY_RELEVANCE);
@@ -232,18 +250,25 @@
   Future<List<Either2<Command, CodeAction>>> _getSourceActions(
     HashSet<CodeActionKind> clientSupportedCodeActionKinds,
     bool clientSupportsLiteralCodeActions,
+    bool clientSupportsWorkspaceApplyEdit,
     String path,
   ) async {
     // The source actions supported are only valid for Dart files.
     if (!AnalysisEngine.isDartFileName(path)) {
-      return [];
+      return const [];
     }
 
     // If the client told us what kinds they support but it does not include
     // Source then don't return any.
     if (clientSupportsLiteralCodeActions &&
         !clientSupportedCodeActionKinds.contains(CodeActionKind.Source)) {
-      return [];
+      return const [];
+    }
+
+    // If the client does not support workspace/applyEdit, we won't be able to
+    // run any of these.
+    if (!clientSupportsWorkspaceApplyEdit) {
+      return const [];
     }
 
     return [
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 67a3fa8..0602df0 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -7,6 +7,8 @@
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/domains/completion/available_suggestions.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analysis_server/src/lsp/mapping.dart';
@@ -15,6 +17,7 @@
 import 'package:analysis_server/src/services/completion/completion_performance.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
 
 // If the client does not provide capabilities.completion.completionItemKind.valueSet
 // then we must never send a kind that's not in this list.
@@ -41,14 +44,23 @@
 
 class CompletionHandler
     extends MessageHandler<CompletionParams, List<CompletionItem>> {
-  CompletionHandler(LspAnalysisServer server) : super(server);
+  final bool suggestFromUnimportedLibraries;
+  CompletionHandler(
+      LspAnalysisServer server, this.suggestFromUnimportedLibraries)
+      : super(server);
+
   Method get handlesMessage => Method.textDocument_completion;
 
   @override
   LspJsonHandler<CompletionParams> get jsonHandler =>
       CompletionParams.jsonHandler;
 
-  Future<ErrorOr<List<CompletionItem>>> handle(CompletionParams params) async {
+  Future<ErrorOr<List<CompletionItem>>> handle(
+      CompletionParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success(const []);
+    }
+
     final completionCapabilities =
         server?.clientCapabilities?.textDocument?.completion;
 
@@ -58,6 +70,9 @@
                 completionCapabilities.completionItemKind.valueSet)
             : defaultSupportedCompletionKinds;
 
+    final includeSuggestionSets = suggestFromUnimportedLibraries &&
+        server?.clientCapabilities?.workspace?.applyEdit == true;
+
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
     final unit = await path.mapResult(requireResolvedUnit);
@@ -65,16 +80,20 @@
     return offset.mapResult((offset) => _getItems(
           completionCapabilities,
           clientSupportedCompletionKinds,
+          includeSuggestionSets,
           unit.result,
           offset,
+          token,
         ));
   }
 
   Future<ErrorOr<List<CompletionItem>>> _getItems(
     TextDocumentClientCapabilitiesCompletion completionCapabilities,
     HashSet<CompletionItemKind> clientSupportedCompletionKinds,
+    bool includeSuggestionSets,
     ResolvedUnitResult unit,
     int offset,
+    CancellationToken token,
   ) async {
     final performance = new CompletionPerformance();
     performance.path = unit.path;
@@ -84,16 +103,26 @@
     final completionRequest =
         new CompletionRequestImpl(unit, offset, performance);
 
+    Set<ElementKind> includedElementKinds;
+    List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags;
+    if (includeSuggestionSets) {
+      includedElementKinds = Set<ElementKind>();
+      includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
+    }
+
     try {
-      CompletionContributor contributor = new DartCompletionManager();
-      final items = await contributor.computeSuggestions(completionRequest);
+      CompletionContributor contributor = new DartCompletionManager(
+        includedElementKinds: includedElementKinds,
+        includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
+      );
+      final suggestions =
+          await contributor.computeSuggestions(completionRequest);
 
-      performance.notificationCount = 1;
-      performance.suggestionCountFirst = items.length;
-      performance.suggestionCountLast = items.length;
-      performance.complete();
+      if (token.isCancellationRequested) {
+        return cancelled();
+      }
 
-      return success(items
+      final results = suggestions
           .map((item) => toCompletionItem(
                 completionCapabilities,
                 clientSupportedCompletionKinds,
@@ -102,7 +131,54 @@
                 completionRequest.replacementOffset,
                 completionRequest.replacementLength,
               ))
-          .toList());
+          .toList();
+
+      // Now compute items in suggestion sets.
+      List<IncludedSuggestionSet> includedSuggestionSets =
+          includedElementKinds == null || unit == null
+              ? const []
+              : computeIncludedSetList(
+                  server.declarationsTracker,
+                  unit,
+                );
+
+      includedSuggestionSets.forEach((includedSet) {
+        final library = server.declarationsTracker.getLibrary(includedSet.id);
+        if (library == null) {
+          return;
+        }
+
+        // Make a fast lookup for tag relevance.
+        final tagBoosts = <String, int>{};
+        includedSuggestionRelevanceTags
+            .forEach((t) => tagBoosts[t.tag] = t.relevanceBoost);
+
+        final setResults = library.declarations
+            // Filter to only the kinds we should return.
+            .where((item) =>
+                includedElementKinds.contains(protocolElementKind(item.kind)))
+            .map((item) => declarationToCompletionItem(
+                  completionCapabilities,
+                  clientSupportedCompletionKinds,
+                  unit.path,
+                  offset,
+                  includedSet,
+                  library,
+                  tagBoosts,
+                  unit.lineInfo,
+                  item,
+                  completionRequest.replacementOffset,
+                  completionRequest.replacementLength,
+                ));
+        results.addAll(setResults);
+      });
+
+      performance.notificationCount = 1;
+      performance.suggestionCountFirst = results.length;
+      performance.suggestionCountLast = results.length;
+      performance.complete();
+
+      return success(results);
     } on AbortCompletion {
       return success([]);
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
new file mode 100644
index 0000000..aa54dae
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -0,0 +1,198 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/mapping.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/element/element.dart' as analyzer;
+import 'package:analyzer/src/util/comment.dart' as analyzer;
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+
+class CompletionResolveHandler
+    extends MessageHandler<CompletionItem, CompletionItem> {
+  ///
+  /// The latest completion item we were asked to resolve. We use it to abort
+  /// previous requests.
+  ///
+  CompletionItem _latestCompletionItem;
+
+  CompletionResolveHandler(LspAnalysisServer server) : super(server);
+
+  Method get handlesMessage => Method.completionItem_resolve;
+
+  @override
+  LspJsonHandler<CompletionItem> get jsonHandler => CompletionItem.jsonHandler;
+
+  Future<ErrorOr<CompletionItem>> handle(
+      CompletionItem item, CancellationToken token) async {
+    // If this isn't an item with resolution data, return the same item back.
+    if (item.data == null) {
+      return success(item);
+    }
+
+    final data = item.data;
+    final lineInfo = server.getLineInfo(data.file);
+    if (lineInfo == null) {
+      return error(
+        ErrorCodes.InternalError,
+        'Line info not available for ${data.file}',
+        null,
+      );
+    }
+
+    // TODO(dantup): This logic is all repeated from domain_completion and needs
+    // extracting (with support for the different types of responses between
+    // the servers). Where is an appropriate place to put it?
+
+    var library = server.declarationsTracker.getLibrary(data.libId);
+    if (library == null) {
+      return error(
+        ErrorCodes.InvalidParams,
+        'Library ID is not valid: ${data.libId}',
+        data.libId.toString(),
+      );
+    }
+
+    // The label might be `MyEnum.myValue`, but we import only `MyEnum`.
+    var requestedName = item.label;
+    if (requestedName.contains('.')) {
+      requestedName = requestedName.substring(
+        0,
+        requestedName.indexOf('.'),
+      );
+    }
+
+    const timeout = Duration(milliseconds: 1000);
+    var timer = Stopwatch()..start();
+    _latestCompletionItem = item;
+    while (item == _latestCompletionItem && timer.elapsed < timeout) {
+      try {
+        var analysisDriver = server.getAnalysisDriver(data.file);
+        var session = analysisDriver.currentSession;
+
+        var fileElement = await session.getUnitElement(data.file);
+        var libraryPath = fileElement.element.librarySource.fullName;
+
+        var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
+
+        if (token.isCancellationRequested) {
+          return cancelled();
+        }
+
+        analyzer.LibraryElement requestedLibraryElement;
+        try {
+          requestedLibraryElement = await session.getLibraryByUri(
+            library.uriStr,
+          );
+        } on ArgumentError catch (e) {
+          return error(
+            ErrorCodes.InvalidParams,
+            'Invalid library URI: ${library.uriStr}',
+            '$e',
+          );
+        }
+
+        if (token.isCancellationRequested) {
+          return cancelled();
+        }
+
+        var requestedElement =
+            requestedLibraryElement.exportNamespace.get(requestedName);
+        if (requestedElement == null) {
+          return error(
+            ErrorCodes.InvalidParams,
+            'No such element: $requestedName',
+            requestedName,
+          );
+        }
+
+        var newLabel = item.label;
+        final builder = DartChangeBuilder(session);
+        await builder.addFileEdit(libraryPath, (builder) {
+          final result = builder.importLibraryElement(
+            targetLibrary: resolvedLibrary,
+            targetPath: libraryPath,
+            targetOffset: data.offset,
+            requestedLibrary: requestedLibraryElement,
+            requestedElement: requestedElement,
+          );
+          if (result.prefix != null) {
+            newLabel = '${result.prefix}.$newLabel';
+          }
+        });
+
+        if (token.isCancellationRequested) {
+          return cancelled();
+        }
+
+        final changes = builder.sourceChange;
+        final thisFilesChanges =
+            changes.edits.where((e) => e.file == data.file).toList();
+        final otherFilesChanges =
+            changes.edits.where((e) => e.file != data.file).toList();
+
+        // If this completion involves editing other files, we'll need to build
+        // a command that the client will call to apply those edits later.
+        Command command;
+        if (otherFilesChanges.isNotEmpty) {
+          final workspaceEdit = createWorkspaceEdit(server, otherFilesChanges);
+          command = Command(
+              'Add import', Commands.sendWorkspaceEdit, [workspaceEdit]);
+        }
+
+        // Documentation is added on during resolve for LSP.
+        final formats = server.clientCapabilities?.textDocument?.completion
+            ?.completionItem?.documentationFormat;
+        final dartDoc =
+            analyzer.getDartDocPlainText(requestedElement.documentationComment);
+        final documentation = asStringOrMarkupContent(formats, dartDoc);
+
+        return success(CompletionItem(
+          newLabel,
+          item.kind,
+          data.displayUri != null
+              ? "Auto import from '${data.displayUri}'\n\n${item.detail ?? ''}"
+                  .trim()
+              : item.detail,
+          documentation,
+          item.deprecated,
+          item.preselect,
+          item.sortText,
+          item.filterText,
+          newLabel,
+          item.insertTextFormat,
+          new TextEdit(
+            // TODO(dantup): If `clientSupportsSnippets == true` then we should map
+            // `selection` in to a snippet (see how Dart Code does this).
+            toRange(lineInfo, item.data.rOffset, item.data.rLength),
+            newLabel,
+          ),
+          thisFilesChanges
+              .expand((change) =>
+                  change.edits.map((edit) => toTextEdit(lineInfo, edit)))
+              .toList(),
+          item.commitCharacters,
+          command ?? item.command,
+          item.data,
+        ));
+      } on InconsistentAnalysisException {
+        // Loop around to try again.
+      }
+    }
+
+    // Timeout or abort, send the empty response.
+
+    return error(
+      ErrorCodes.RequestCancelled,
+      'Request was cancelled for taking too long or another request being received',
+      null,
+    );
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
index 51f7b2f..c6df90c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
@@ -23,7 +23,11 @@
       TextDocumentPositionParams.jsonHandler;
 
   Future<ErrorOr<List<Location>>> handle(
-      TextDocumentPositionParams params) async {
+      TextDocumentPositionParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success(const []);
+    }
+
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
     final unit = await path.mapResult(requireResolvedUnit);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
index c2fabbd..6a59beb 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
@@ -22,7 +22,11 @@
       TextDocumentPositionParams.jsonHandler;
 
   Future<ErrorOr<List<DocumentHighlight>>> handle(
-      TextDocumentPositionParams params) async {
+      TextDocumentPositionParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success(const []);
+    }
+
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
     final unit = await path.mapResult(requireResolvedUnit);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
index 6c5b120..3de909c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
@@ -48,7 +48,13 @@
       DocumentSymbolParams.jsonHandler;
 
   Future<ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>>>
-      handle(DocumentSymbolParams params) async {
+      handle(DocumentSymbolParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success(
+        Either2<List<DocumentSymbol>, List<SymbolInformation>>.t2([]),
+      );
+    }
+
     final symbolCapabilities =
         server?.clientCapabilities?.textDocument?.documentSymbol;
 
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
index b40f4b4..f552cf6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
@@ -8,6 +8,7 @@
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/commands/organize_imports.dart';
+import 'package:analysis_server/src/lsp/handlers/commands/send_workspace_edit.dart';
 import 'package:analysis_server/src/lsp/handlers/commands/sort_members.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
@@ -21,6 +22,8 @@
       : commandHandlers = {
           Commands.sortMembers: new SortMembersCommandHandler(server),
           Commands.organizeImports: new OrganizeImportsCommandHandler(server),
+          Commands.sendWorkspaceEdit:
+              new SendWorkspaceEditCommandHandler(server),
         },
         super(server);
 
@@ -30,7 +33,8 @@
   LspJsonHandler<ExecuteCommandParams> get jsonHandler =>
       ExecuteCommandParams.jsonHandler;
 
-  Future<ErrorOr<Object>> handle(ExecuteCommandParams params) async {
+  Future<ErrorOr<Object>> handle(
+      ExecuteCommandParams params, CancellationToken token) async {
     final handler = commandHandlers[params.command];
     if (handler == null) {
       return error(ServerErrorCodes.UnknownCommand,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
index c301118..699931d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
@@ -24,7 +24,7 @@
   LspJsonHandler<void> get jsonHandler => NullJsonHandler;
 
   @override
-  Future<ErrorOr<void>> handle(void _) async {
+  Future<ErrorOr<void>> handle(void _, CancellationToken token) async {
     // Set a flag that the server shutdown is being controlled here to ensure
     // that the normal code that shuts down the server when the channel closes
     // does not fire.
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
index 50d8ca3..bfea14c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
@@ -20,7 +20,12 @@
   LspJsonHandler<FoldingRangeParams> get jsonHandler =>
       FoldingRangeParams.jsonHandler;
 
-  Future<ErrorOr<List<FoldingRange>>> handle(FoldingRangeParams params) async {
+  Future<ErrorOr<List<FoldingRange>>> handle(
+      FoldingRangeParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success(const []);
+    }
+
     final path = pathOfDoc(params.textDocument);
     final unit = await path.mapResult(requireUnresolvedUnit);
 
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
index 7426410..2760984 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
@@ -32,7 +32,7 @@
   }
 
   Future<ErrorOr<List<TextEdit>>> handle(
-      DocumentOnTypeFormattingParams params) async {
+      DocumentOnTypeFormattingParams params, CancellationToken token) async {
     final path = pathOfDoc(params.textDocument);
     return path.mapResult((path) => formatFile(path));
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
index effe549..a0587b7 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
@@ -32,7 +32,7 @@
   }
 
   Future<ErrorOr<List<TextEdit>>> handle(
-      DocumentFormattingParams params) async {
+      DocumentFormattingParams params, CancellationToken token) async {
     final path = pathOfDoc(params.textDocument);
     return path.mapResult((path) => formatFile(path));
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
index 7d0db4f..b724b1a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
@@ -14,7 +14,6 @@
 import 'package:analysis_server/src/lsp/mapping.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 
 class HoverHandler extends MessageHandler<TextDocumentPositionParams, Hover> {
   HoverHandler(LspAnalysisServer server) : super(server);
@@ -24,7 +23,12 @@
   LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
       TextDocumentPositionParams.jsonHandler;
 
-  Future<ErrorOr<Hover>> handle(TextDocumentPositionParams params) async {
+  Future<ErrorOr<Hover>> handle(
+      TextDocumentPositionParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success(null);
+    }
+
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
     final unit = await path.mapResult(requireResolvedUnit);
@@ -84,14 +88,7 @@
 
   ErrorOr<Hover> _getHover(ResolvedUnitResult unit, int offset) {
     final hover = new DartUnitHoverComputer(
-            // TODO(brianwilkerson) Add declarationsTracker to server in order to
-            //  enable dartdoc processing.
-//            server.declarationsTracker
-//                .getContext(unit.session.analysisContext)
-//                .dartdocDirectiveInfo,
-            new DartdocDirectiveInfo(),
-            unit.unit,
-            offset)
+            server.getDartdocDirectiveInfoFor(unit), unit.unit, offset)
         .compute();
     return success(toHover(unit.lineInfo, hover));
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart
new file mode 100644
index 0000000..d6e7643
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/mapping.dart';
+import 'package:analysis_server/src/search/type_hierarchy.dart';
+
+class ImplementationHandler
+    extends MessageHandler<TextDocumentPositionParams, List<Location>> {
+  ImplementationHandler(LspAnalysisServer server) : super(server);
+  Method get handlesMessage => Method.textDocument_implementation;
+
+  @override
+  LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
+      TextDocumentPositionParams.jsonHandler;
+
+  @override
+  Future<ErrorOr<List<Location>>> handle(
+      TextDocumentPositionParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success(const []);
+    }
+
+    final pos = params.position;
+    final path = pathOfDoc(params.textDocument);
+    final unit = await path.mapResult(requireResolvedUnit);
+    final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
+    return offset
+        .mapResult((offset) => _getImplementations(path.result, offset, token));
+  }
+
+  Future<ErrorOr<List<Location>>> _getImplementations(
+      String file, int offset, CancelableToken token) async {
+    final element = await server.getElementAtOffset(file, offset);
+    final computer = new TypeHierarchyComputer(server.searchEngine, element);
+    if (token.isCancellationRequested) {
+      return cancelled();
+    }
+    final items = await computer.compute();
+
+    if (items == null || items.isEmpty) {
+      return success([]);
+    }
+
+    Iterable<TypeHierarchyItem> getDescendants(TypeHierarchyItem item) => item
+        .subclasses
+        ?.map((i) => items[i])
+        ?.followedBy(item.subclasses.expand((i) => getDescendants(items[i])));
+
+    // [TypeHierarchyComputer] returns the whole tree, but we specifically only
+    // want implementations (sub-classes). Find the referenced element and then
+    // recursively add its children.
+    var currentItem = items.firstWhere(
+      (item) {
+        final location =
+            item.memberElement?.location ?? item.classElement?.location;
+        return location.offset <= offset &&
+            location.offset + location.length >= offset;
+      },
+      // If we didn't find an item spanning our offset, we must've been at a
+      // call site so start everything from the root item.
+      orElse: () => items.first,
+    );
+
+    final isClass = currentItem.memberElement == null;
+
+    final locations = getDescendants(currentItem).where((item) {
+      // Filter based on type, so when searching for members we don't include
+      // any intermediate classes that don't have implementations for the
+      // method.
+      return isClass ? item.classElement != null : item.memberElement != null;
+    }).map((item) {
+      final elementLocation =
+          item.memberElement?.location ?? item.classElement?.location;
+      final lineInfo = server.getLineInfo(elementLocation.file);
+      return Location(
+        Uri.file(elementLocation.file).toString(),
+        toRange(lineInfo, elementLocation.offset, elementLocation.length),
+      );
+    }).toList();
+
+    return success(locations);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
index 88423de..1aa7293 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
@@ -19,19 +19,18 @@
   LspJsonHandler<InitializeParams> get jsonHandler =>
       InitializeParams.jsonHandler;
 
-  ErrorOr<InitializeResult> handle(InitializeParams params) {
-    final openWorkspacePaths = <String>[];
+  ErrorOr<InitializeResult> handle(
+      InitializeParams params, CancellationToken token) {
+    server.handleClientConnection(
+      params.capabilities,
+      params.initializationOptions,
+    );
 
+    final openWorkspacePaths = <String>[];
     // The onlyAnalyzeProjectsWithOpenFiles flag allows opening huge folders
     // without setting them as analysis roots. Instead, analysis roots will be
     // based only on the open files.
-    final onlyAnalyzeProjectsWithOpenFiles = params.initializationOptions !=
-            null
-        ? params.initializationOptions['onlyAnalyzeProjectsWithOpenFiles'] ==
-            true
-        : false;
-
-    if (!onlyAnalyzeProjectsWithOpenFiles) {
+    if (!server.initializationOptions.onlyAnalyzeProjectsWithOpenFiles) {
       if (params.workspaceFolders != null) {
         params.workspaceFolders.forEach((wf) {
           openWorkspacePaths.add(Uri.parse(wf.uri).toFilePath());
@@ -48,9 +47,10 @@
       }
     }
 
-    server.handleClientConnection(params.capabilities);
     server.messageHandler = new InitializingStateMessageHandler(
-        server, openWorkspacePaths, onlyAnalyzeProjectsWithOpenFiles);
+      server,
+      openWorkspacePaths,
+    );
 
     final codeActionLiteralSupport =
         params.capabilities.textDocument?.codeAction?.codeActionLiteralSupport;
@@ -58,6 +58,12 @@
     final renameOptionsSupport =
         params.capabilities.textDocument?.rename?.prepareSupport ?? false;
 
+    // When adding new capabilities to the server that may apply to specific file
+    // types, it's important to update
+    // [IntializedMessageHandler._performDynamicRegistration()] to notify
+    // supporting clients of this. This avoids clients needing to hard-code the
+    // list of what files types we support (and allows them to avoid sending
+    // requests where we have only partial support for some types).
     server.capabilities = new ServerCapabilities(
         Either2<TextDocumentSyncOptions, num>.t1(new TextDocumentSyncOptions(
           true,
@@ -68,38 +74,15 @@
         )),
         true, // hoverProvider
         new CompletionOptions(
-          false,
-          // Set the characters that will cause the editor to automatically
-          // trigger completion.
-          // TODO(dantup): There are several characters that we want to conditionally
-          // allow to trigger completion, but they can only be added when the completion
-          // provider is able to handle them in context:
-          //
-          //    {   trigger if being typed in a string immediately after a $
-          //    '   trigger if the opening quote for an import/export
-          //    "   trigger if the opening quote for an import/export
-          //    /   trigger if as part of a path in an import/export
-          //    \   trigger if as part of a path in an import/export
-          //    :   don't trigger when typing case expressions (`case x:`)
-          //
-          // Additionally, we need to prefix `filterText` on completion items
-          // with spaces for those that can follow whitespace (eg. `foo` in
-          // `myArg: foo`) to ensure they're not filtered away when the user
-          // types space.
-          //
-          // See https://github.com/Dart-Code/Dart-Code/blob/68d1cd271e88a785570257d487adbdec17abd6a3/src/providers/dart_completion_item_provider.ts#L36-L64
-          // for the VS Code implementation of this.
-          r'''.=($'''.split(''),
+          true, // resolveProvider
+          dartCompletionTriggerCharacters,
         ),
         new SignatureHelpOptions(
-          // TODO(dantup): Signature help triggering is even more sensitive to
-          // bad chars, so we'll need to implement the logic described here:
-          // https://github.com/dart-lang/sdk/issues/34241
-          [],
+          dartSignatureHelpTriggerCharacters,
         ),
         true, // definitionProvider
         null,
-        null,
+        true, // implementationProvider
         true, // referencesProvider
         true, // documentHighlightProvider
         true, // documentSymbolProvider
@@ -114,14 +97,16 @@
         null,
         true, // documentFormattingProvider
         false, // documentRangeFormattingProvider
-        new DocumentOnTypeFormattingOptions('}', [';']),
+        new DocumentOnTypeFormattingOptions(dartTypeFormattingCharacters.first,
+            dartTypeFormattingCharacters.skip(1).toList()),
         renameOptionsSupport
             ? Either2<bool, RenameOptions>.t2(new RenameOptions(true))
             : Either2<bool, RenameOptions>.t1(true),
         null,
         null,
-        Either3<bool, FoldingRangeProviderOptions, dynamic>.t1(true),
+        true, // foldingRangeProvider
         new ExecuteCommandOptions(Commands.serverSupportedCommands),
+        null, // declarationProvider
         new ServerCapabilitiesWorkspace(
             new ServerCapabilitiesWorkspaceFolders(true, true)),
         null);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
index 463ac9e..eeb698c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
@@ -4,30 +4,176 @@
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_states.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 
 class IntializedMessageHandler extends MessageHandler<InitializedParams, void> {
   final List<String> openWorkspacePaths;
-  final bool onlyAnalyzeProjectsWithOpenFiles;
-  IntializedMessageHandler(LspAnalysisServer server, this.openWorkspacePaths,
-      this.onlyAnalyzeProjectsWithOpenFiles)
-      : super(server);
+  IntializedMessageHandler(
+    LspAnalysisServer server,
+    this.openWorkspacePaths,
+  ) : super(server);
   Method get handlesMessage => Method.initialized;
 
   @override
   LspJsonHandler<InitializedParams> get jsonHandler =>
       InitializedParams.jsonHandler;
 
-  ErrorOr<void> handle(InitializedParams params) {
+  ErrorOr<void> handle(InitializedParams params, CancellationToken token) {
     server.messageHandler = new InitializedStateMessageHandler(
-        server, onlyAnalyzeProjectsWithOpenFiles);
+      server,
+    );
 
-    if (!onlyAnalyzeProjectsWithOpenFiles) {
+    _performDynamicRegistration();
+
+    if (!server.initializationOptions.onlyAnalyzeProjectsWithOpenFiles) {
       server.setAnalysisRoots(openWorkspacePaths);
     }
 
     return success();
   }
+
+  /// If the client supports dynamic registrations we can tell it what methods
+  /// we support for which documents. For example, this allows us to ask for
+  /// file edits for .dart as well as pubspec.yaml but only get hover/completion
+  /// calls for .dart. This functionality may not be supported by the client, in
+  /// which case they will use the ServerCapabilities to know which methods we
+  /// support and it will be up to them to decide which file types they will
+  /// send requests for.
+  Future<void> _performDynamicRegistration() async {
+    final dartFiles = DocumentFilter('dart', 'file', null);
+    final pubspecFile = DocumentFilter('yaml', 'file', '**/pubspec.yaml');
+    final analysisOptionsFile =
+        DocumentFilter('yaml', 'file', '**/analysis_options.yaml');
+    final allTypes = [dartFiles, pubspecFile, analysisOptionsFile];
+
+    // TODO(dantup): When we support plugins, we will need to collect their
+    // requirements too. For example, the Angular plugin might wish to add HTML
+    // `DocumentFilter('html', 'file', null)` to many of these requests.
+
+    int _lastRegistrationId = 1;
+    final registrations = <Registration>[];
+
+    /// Helper for creating registrations with IDs.
+    void register(bool condition, Method method, [ToJsonable options]) {
+      if (condition == true) {
+        registrations.add(Registration(
+            (_lastRegistrationId++).toString(), method.toJson(), options));
+      }
+    }
+
+    final textCapabilities = server.clientCapabilities?.textDocument;
+
+    register(
+      textCapabilities?.synchronization?.dynamicRegistration,
+      Method.textDocument_didOpen,
+      TextDocumentRegistrationOptions(allTypes),
+    );
+    register(
+      textCapabilities?.synchronization?.dynamicRegistration,
+      Method.textDocument_didClose,
+      TextDocumentRegistrationOptions(allTypes),
+    );
+    register(
+      textCapabilities?.synchronization?.dynamicRegistration,
+      Method.textDocument_didChange,
+      TextDocumentChangeRegistrationOptions(
+          TextDocumentSyncKind.Incremental, allTypes),
+    );
+    register(
+      server.clientCapabilities?.textDocument?.completion?.dynamicRegistration,
+      Method.textDocument_completion,
+      CompletionRegistrationOptions(
+        dartCompletionTriggerCharacters,
+        null,
+        true,
+        [dartFiles],
+      ),
+    );
+    register(
+      textCapabilities?.hover?.dynamicRegistration,
+      Method.textDocument_hover,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      textCapabilities?.signatureHelp?.dynamicRegistration,
+      Method.textDocument_signatureHelp,
+      SignatureHelpRegistrationOptions(
+          dartSignatureHelpTriggerCharacters, [dartFiles]),
+    );
+    register(
+      server.clientCapabilities?.textDocument?.references?.dynamicRegistration,
+      Method.textDocument_references,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      textCapabilities?.documentHighlight?.dynamicRegistration,
+      Method.textDocument_documentHighlight,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      textCapabilities?.documentSymbol?.dynamicRegistration,
+      Method.textDocument_documentSymbol,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      server.clientCapabilities?.textDocument?.formatting?.dynamicRegistration,
+      Method.textDocument_formatting,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      textCapabilities?.onTypeFormatting?.dynamicRegistration,
+      Method.textDocument_onTypeFormatting,
+      DocumentOnTypeFormattingRegistrationOptions(
+        dartTypeFormattingCharacters.first,
+        dartTypeFormattingCharacters.skip(1).toList(),
+        [dartFiles],
+      ),
+    );
+    register(
+      server.clientCapabilities?.textDocument?.definition?.dynamicRegistration,
+      Method.textDocument_definition,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      textCapabilities?.implementation?.dynamicRegistration,
+      Method.textDocument_implementation,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      server.clientCapabilities?.textDocument?.codeAction?.dynamicRegistration,
+      Method.textDocument_codeAction,
+      CodeActionRegistrationOptions(
+          [dartFiles], DartCodeActionKind.serverSupportedKinds),
+    );
+    register(
+      textCapabilities?.rename?.dynamicRegistration,
+      Method.textDocument_rename,
+      RenameRegistrationOptions(true, [dartFiles]),
+    );
+    register(
+      textCapabilities?.foldingRange?.dynamicRegistration,
+      Method.textDocument_foldingRange,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+
+    // Only send the registration request if we have at least one (since
+    // otherwise we don't know that the client supports registerCapability).
+    if (registrations.isNotEmpty) {
+      final registrationResponse = await server.sendRequest(
+        Method.client_registerCapability,
+        RegistrationParams(registrations),
+      );
+
+      if (registrationResponse.error != null) {
+        server.logErrorToClient(
+          'Failed to register capabilities with client: '
+          '(${registrationResponse.error.code}) '
+          '${registrationResponse.error.message}',
+        );
+      }
+    }
+  }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
index c025819..c6660f4 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
@@ -28,7 +28,12 @@
       ReferenceParams.jsonHandler;
 
   @override
-  Future<ErrorOr<List<Location>>> handle(ReferenceParams params) async {
+  Future<ErrorOr<List<Location>>> handle(
+      ReferenceParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success(const []);
+    }
+
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
     final unit = await path.mapResult(requireResolvedUnit);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
index b006c00..37c7916 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
@@ -21,7 +21,7 @@
   LspJsonHandler<void> get jsonHandler => NullJsonHandler;
 
   @override
-  ErrorOr<void> handle(void _) {
+  ErrorOr<void> handle(void _, CancellationToken token) {
     return error(errorCode, errorMessage, null);
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
index 16ed7cd..799eab6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
@@ -21,7 +21,7 @@
 
   @override
   Future<ErrorOr<RangeAndPlaceholder>> handle(
-      TextDocumentPositionParams params) async {
+      TextDocumentPositionParams params, CancellationToken token) async {
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
     final unit = await path.mapResult(requireResolvedUnit);
@@ -36,8 +36,8 @@
 
       final refactorDetails =
           RenameRefactoring.getElementToRename(node, element);
-      final refactoring = new RenameRefactoring(server.refactoringWorkspace,
-          unit.result.session, refactorDetails.element);
+      final refactoring = new RenameRefactoring(
+          server.refactoringWorkspace, unit.result, refactorDetails.element);
 
       // Check the rename is valid here.
       final initStatus = await refactoring.checkInitialConditions();
@@ -71,7 +71,8 @@
   LspJsonHandler<RenameParams> get jsonHandler => RenameParams.jsonHandler;
 
   @override
-  Future<ErrorOr<WorkspaceEdit>> handle(RenameParams params) async {
+  Future<ErrorOr<WorkspaceEdit>> handle(
+      RenameParams params, CancellationToken token) async {
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
     // If the client provided us a version doc identifier, we'll use it to ensure
@@ -95,8 +96,8 @@
 
       final refactorDetails =
           RenameRefactoring.getElementToRename(node, element);
-      final refactoring = new RenameRefactoring(server.refactoringWorkspace,
-          unit.result.session, refactorDetails.element);
+      final refactoring = new RenameRefactoring(
+          server.refactoringWorkspace, unit.result, refactorDetails.element);
 
       // TODO(dantup): Consider using window/showMessageRequest to prompt
       // the user to see if they'd like to proceed with a rename if there
@@ -106,6 +107,9 @@
 
       // Check the rename is valid here.
       final initStatus = await refactoring.checkInitialConditions();
+      if (token.isCancellationRequested) {
+        return cancelled();
+      }
       if (initStatus.hasError) {
         return error(
             ServerErrorCodes.RenameNotValid, initStatus.problem.message, null);
@@ -121,6 +125,9 @@
 
       // Final validation.
       final finalStatus = await refactoring.checkFinalConditions();
+      if (token.isCancellationRequested) {
+        return cancelled();
+      }
       if (finalStatus.hasError) {
         return error(
             ServerErrorCodes.RenameNotValid, finalStatus.problem.message, null);
@@ -128,6 +135,9 @@
 
       // Compute the actual change.
       final change = await refactoring.createChange();
+      if (token.isCancellationRequested) {
+        return cancelled();
+      }
 
       // Before we send anything back, ensure the original file didn't change
       // while we were computing changes.
@@ -137,7 +147,7 @@
             'Document was modified while rename was being computed', null);
       }
 
-      final workspaceEdit = createWorkspaceEdit(server, change);
+      final workspaceEdit = createWorkspaceEdit(server, change.edits);
       return success(workspaceEdit);
     });
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
index c16a394..9349240 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
@@ -16,7 +16,7 @@
   LspJsonHandler<void> get jsonHandler => NullJsonHandler;
 
   @override
-  ErrorOr<void> handle(void _) {
+  ErrorOr<void> handle(void _, CancellationToken token) {
     // Move to the Shutting Down state so we won't process any more
     // requests and the Exit notification will know it was a clean shutdown.
     server.messageHandler = new ShuttingDownStateMessageHandler(server);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
index 7fa60a7..642e77f 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
@@ -10,7 +10,6 @@
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analysis_server/src/lsp/mapping.dart';
-import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 
 class SignatureHelpHandler
     extends MessageHandler<TextDocumentPositionParams, SignatureHelp> {
@@ -22,7 +21,11 @@
       TextDocumentPositionParams.jsonHandler;
 
   Future<ErrorOr<SignatureHelp>> handle(
-      TextDocumentPositionParams params) async {
+      TextDocumentPositionParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success(null);
+    }
+
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
     final unit = await path.mapResult(requireResolvedUnit);
@@ -30,12 +33,7 @@
 
     return offset.mapResult((offset) {
       final computer = new DartUnitSignatureComputer(
-          // TODO(brianwilkerson) Add declarationsTracker to server in order to
-          //  enable dartdoc processing.
-//          server.declarationsTracker
-//              .getContext(unit.result.session.analysisContext)
-//              .dartdocDirectiveInfo,
-          new DartdocDirectiveInfo(),
+          server.getDartdocDirectiveInfoFor(unit.result),
           unit.result.unit,
           offset);
       if (!computer.offsetIsValid) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
index cd79433..a0e1d15 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
@@ -8,8 +8,10 @@
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/custom/handler_diagnostic_server.dart';
+import 'package:analysis_server/src/lsp/handlers/custom/handler_super.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_code_actions.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_completion.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_completion_resolve.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_definition.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_document_highlights.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_document_symbols.dart';
@@ -19,6 +21,7 @@
 import 'package:analysis_server/src/lsp/handlers/handler_format_on_type.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_formatting.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_hover.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_implementation.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_initialize.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_initialized.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_references.dart';
@@ -39,7 +42,7 @@
 
   @override
   FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) {
-    return failure(
+    return error(
         ErrorCodes.InternalError,
         'An unrecoverable error occurred and the server cannot process messages',
         null);
@@ -49,7 +52,6 @@
 class InitializedStateMessageHandler extends ServerStateMessageHandler {
   InitializedStateMessageHandler(
     LspAnalysisServer server,
-    bool onlyAnalyzeProjectsWithOpenFiles,
   ) : super(server) {
     reject(Method.initialize, ServerErrorCodes.ServerAlreadyInitialized,
         'Server already initialized');
@@ -58,17 +60,29 @@
     registerHandler(new ShutdownMessageHandler(server));
     registerHandler(new ExitMessageHandler(server));
     registerHandler(
-      new TextDocumentOpenHandler(server, onlyAnalyzeProjectsWithOpenFiles),
+      new TextDocumentOpenHandler(
+        server,
+        server.initializationOptions.onlyAnalyzeProjectsWithOpenFiles,
+      ),
     );
     registerHandler(new TextDocumentChangeHandler(server));
     registerHandler(
-      new TextDocumentCloseHandler(server, onlyAnalyzeProjectsWithOpenFiles),
+      new TextDocumentCloseHandler(
+        server,
+        server.initializationOptions.onlyAnalyzeProjectsWithOpenFiles,
+      ),
     );
     registerHandler(new HoverHandler(server));
-    registerHandler(new CompletionHandler(server));
+    registerHandler(new CompletionHandler(
+      server,
+      server.initializationOptions.suggestFromUnimportedLibraries,
+    ));
+    registerHandler(new CompletionResolveHandler(server));
     registerHandler(new SignatureHelpHandler(server));
     registerHandler(new DefinitionHandler(server));
+    registerHandler(new SuperHandler(server));
     registerHandler(new ReferencesHandler(server));
+    registerHandler(new ImplementationHandler(server));
     registerHandler(new FormattingHandler(server));
     registerHandler(new FormatOnTypeHandler(server));
     registerHandler(new DocumentHighlightsHandler(server));
@@ -76,7 +90,10 @@
     registerHandler(new CodeActionHandler(server));
     registerHandler(new ExecuteCommandHandler(server));
     registerHandler(
-      new WorkspaceFoldersHandler(server, !onlyAnalyzeProjectsWithOpenFiles),
+      new WorkspaceFoldersHandler(
+        server,
+        !server.initializationOptions.onlyAnalyzeProjectsWithOpenFiles,
+      ),
     );
     registerHandler(new PrepareRenameHandler(server));
     registerHandler(new RenameHandler(server));
@@ -87,15 +104,18 @@
 }
 
 class InitializingStateMessageHandler extends ServerStateMessageHandler {
-  InitializingStateMessageHandler(LspAnalysisServer server,
-      List<String> openWorkspacePaths, bool onlyAnalyzeProjectsWithOpenFiles)
-      : super(server) {
+  InitializingStateMessageHandler(
+    LspAnalysisServer server,
+    List<String> openWorkspacePaths,
+  ) : super(server) {
     reject(Method.initialize, ServerErrorCodes.ServerAlreadyInitialized,
         'Server already initialized');
     registerHandler(new ShutdownMessageHandler(server));
     registerHandler(new ExitMessageHandler(server));
     registerHandler(new IntializedMessageHandler(
-        server, openWorkspacePaths, onlyAnalyzeProjectsWithOpenFiles));
+      server,
+      openWorkspacePaths,
+    ));
   }
 
   @override
@@ -104,7 +124,7 @@
     if (message is! RequestMessage) {
       return success();
     }
-    return failure(
+    return error(
         ErrorCodes.ServerNotInitialized,
         'Unable to handle ${message.method} before the server is initialized '
         'and the client has sent the initialized notification');
@@ -124,7 +144,7 @@
     if (message is! RequestMessage) {
       return success();
     }
-    return failure(ErrorCodes.ServerNotInitialized,
+    return error(ErrorCodes.ServerNotInitialized,
         'Unable to handle ${message.method} before client has sent initialize request');
   }
 }
@@ -141,7 +161,7 @@
     if (message is! RequestMessage) {
       return success();
     }
-    return failure(ServerErrorCodes.ServerShuttingDown,
+    return error(ErrorCodes.InvalidRequest,
         'Unable to handle ${message.method} after shutdown request');
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
index e083f5d..46ab686 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
@@ -23,7 +23,8 @@
   LspJsonHandler<DidChangeTextDocumentParams> get jsonHandler =>
       DidChangeTextDocumentParams.jsonHandler;
 
-  ErrorOr<void> handle(DidChangeTextDocumentParams params) {
+  ErrorOr<void> handle(
+      DidChangeTextDocumentParams params, CancellationToken token) {
     final path = pathOfDoc(params.textDocument);
     return path.mapResult((path) => _changeFile(path, params));
   }
@@ -66,7 +67,8 @@
   LspJsonHandler<DidCloseTextDocumentParams> get jsonHandler =>
       DidCloseTextDocumentParams.jsonHandler;
 
-  ErrorOr<void> handle(DidCloseTextDocumentParams params) {
+  ErrorOr<void> handle(
+      DidCloseTextDocumentParams params, CancellationToken token) {
     final path = pathOfDoc(params.textDocument);
     return path.mapResult((path) {
       server.removePriorityFile(path);
@@ -111,7 +113,8 @@
   LspJsonHandler<DidOpenTextDocumentParams> get jsonHandler =>
       DidOpenTextDocumentParams.jsonHandler;
 
-  ErrorOr<void> handle(DidOpenTextDocumentParams params) {
+  ErrorOr<void> handle(
+      DidOpenTextDocumentParams params, CancellationToken token) {
     final doc = params.textDocument;
     final path = pathOfDocItem(doc);
     return path.mapResult((path) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
index 0f748d5..c53327a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
@@ -24,7 +24,7 @@
       WorkspaceSymbolParams.jsonHandler;
 
   Future<ErrorOr<List<SymbolInformation>>> handle(
-      WorkspaceSymbolParams params) async {
+      WorkspaceSymbolParams params, CancellationToken token) async {
     // Respond to empty queries with an empty list. The spec says this should
     // be non-empty, however VS Code's client sends empty requests (but then
     // appears to not render the results we supply anyway).
@@ -55,6 +55,9 @@
     for (var driver in server.driverMap.values) {
       final driverResults = await driver.search
           .declarations(regex, remainingResults, filePathsHashSet);
+      if (token.isCancellationRequested) {
+        return cancelled();
+      }
       declarations.addAll(driverResults);
       remainingResults -= driverResults.length;
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
index 29d6800..89a8c1b 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
@@ -7,6 +7,7 @@
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_cancel_request.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_reject.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analyzer/dart/analysis/results.dart';
@@ -19,6 +20,22 @@
   return items.map(converter).where((item) => item != null);
 }
 
+class CancelableToken extends CancellationToken {
+  bool _isCancelled = false;
+
+  @override
+  bool get isCancellationRequested => _isCancelled;
+
+  void cancel() => _isCancelled = true;
+}
+
+/// A token used to signal cancellation of an operation. This allows computation
+/// to be skipped when a caller is no longer interested in the result, for example
+/// when a $/cancel request is recieved for an in-progress request.
+abstract class CancellationToken {
+  bool get isCancellationRequested;
+}
+
 abstract class CommandHandler<P, R> with Handler<P, R> {
   CommandHandler(LspAnalysisServer server) {
     this.server = server;
@@ -30,12 +47,6 @@
 mixin Handler<P, R> {
   LspAnalysisServer server;
 
-  ErrorOr<R> error<R>(ErrorCodes code, String message, String data) =>
-      new ErrorOr<R>.error(new ResponseError(code, message, data));
-
-  ErrorOr<R> failure<R>(ErrorOr<dynamic> error) =>
-      new ErrorOr<R>.error(error.error);
-
   Future<ErrorOr<ResolvedUnitResult>> requireResolvedUnit(String path) async {
     final result = await server.getResolvedUnit(path);
     if (result?.state != ResultState.VALID) {
@@ -51,8 +62,6 @@
     }
     return success(result);
   }
-
-  ErrorOr<R> success<R>([R t]) => new ErrorOr<R>.success(t);
 }
 
 /// An object that can handle messages and produce responses for requests.
@@ -69,41 +78,69 @@
   /// A handler that can parse and validate JSON params.
   LspJsonHandler<P> get jsonHandler;
 
-  FutureOr<ErrorOr<R>> handle(P params);
+  FutureOr<ErrorOr<R>> handle(P params, CancellationToken token);
 
   /// Handle the given [message]. If the [message] is a [RequestMessage], then the
   /// return value will be sent back in a [ResponseMessage].
   /// [NotificationMessage]s are not expected to return results.
-  FutureOr<ErrorOr<R>> handleMessage(IncomingMessage message) {
+  FutureOr<ErrorOr<R>> handleMessage(
+      IncomingMessage message, CancellationToken token) {
     if (!jsonHandler.validateParams(message.params)) {
       return error(ErrorCodes.InvalidParams,
           'Invalid params for ${message.method}', null);
     }
 
     final params = jsonHandler.convertParams(message.params);
-    return handle(params);
+    return handle(params, token);
   }
 }
 
+class NotCancelableToken extends CancellationToken {
+  @override
+  bool get isCancellationRequested => false;
+}
+
 /// A message handler that handles all messages for a given server state.
 abstract class ServerStateMessageHandler {
   final LspAnalysisServer server;
   final Map<Method, MessageHandler> _messageHandlers = {};
+  final CancelRequestHandler _cancelHandler;
+  final NotCancelableToken _notCancelableToken = NotCancelableToken();
 
-  ServerStateMessageHandler(this.server);
-
-  ErrorOr<Object> failure<Object>(ErrorCodes code, String message,
-          [String data]) =>
-      new ErrorOr<Object>.error(new ResponseError(code, message, data));
+  ServerStateMessageHandler(this.server)
+      : _cancelHandler = CancelRequestHandler(server) {
+    registerHandler(_cancelHandler);
+  }
 
   /// Handle the given [message]. If the [message] is a [RequestMessage], then the
   /// return value will be sent back in a [ResponseMessage].
   /// [NotificationMessage]s are not expected to return results.
   FutureOr<ErrorOr<Object>> handleMessage(IncomingMessage message) async {
     final handler = _messageHandlers[message.method];
-    return handler != null
-        ? handler.handleMessage(message)
-        : handleUnknownMessage(message);
+    if (handler == null) {
+      return handleUnknownMessage(message);
+    }
+
+    if (message is! RequestMessage) {
+      return handler.handleMessage(message, _notCancelableToken);
+    }
+
+    // Create a cancellation token that will allow us to cancel this request if
+    // requested to save processing (the handler will need to specifically
+    // check the token after `await` points).
+    final token = _cancelHandler.createToken(message);
+    try {
+      final result = await handler.handleMessage(message, token);
+      // Do a final check before returning the result, because if the request was
+      // cancelled we can save the overhead of serialising everything to JSON
+      // and the client to deserialising the same in order to read the ID to see
+      // that it was a request it didn't need (in the case of completions this
+      // can be quite large).
+      await Future.delayed(Duration.zero);
+      return token.isCancellationRequested ? cancelled() : result;
+    } finally {
+      _cancelHandler.clearToken(message);
+    }
   }
 
   FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) {
@@ -112,8 +149,7 @@
     // to so they don't leave open requests on the client.
     return _isOptionalNotification(message)
         ? success()
-        : failure(
-            ErrorCodes.MethodNotFound, 'Unknown method ${message.method}');
+        : error(ErrorCodes.MethodNotFound, 'Unknown method ${message.method}');
   }
 
   registerHandler(MessageHandler handler) {
@@ -129,8 +165,6 @@
     registerHandler(new RejectMessageHandler(server, method, code, message));
   }
 
-  ErrorOr<Object> success<Object>([Object t]) => new ErrorOr<Object>.success(t);
-
   bool _isOptionalNotification(IncomingMessage message) {
     // Not a notification.
     if (message is! NotificationMessage) {
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index a1c6cf2..301e631 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -6,15 +6,18 @@
 import 'dart:collection';
 import 'dart:io' as io;
 
+import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart' as protocol;
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/analysis_server_abstract.dart';
 import 'package:analysis_server/src/collections.dart';
+import 'package:analysis_server/src/computer/computer_closingLabels.dart';
 import 'package:analysis_server/src/context_manager.dart';
 import 'package:analysis_server/src/domain_completion.dart'
     show CompletionDomainHandler;
+import 'package:analysis_server/src/domains/completion/available_suggestions.dart';
 import 'package:analysis_server/src/lsp/channel/lsp_channel.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_states.dart';
@@ -35,7 +38,6 @@
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/context/context_root.dart';
-import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' as nd;
 import 'package:analyzer/src/dart/analysis/file_state.dart' as nd;
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
@@ -43,6 +45,7 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/plugin/resolver_provider.dart';
+import 'package:analyzer/src/services/available_declarations.dart';
 import 'package:watcher/watcher.dart';
 
 /**
@@ -53,6 +56,10 @@
   /// The capabilities of the LSP client. Will be null prior to initialization.
   ClientCapabilities _clientCapabilities;
 
+  /// Initialization options provided by the LSP client. Allows opting in/out of
+  /// specific server functionality. Will be null prior to initialization.
+  LspInitializationOptions _initializationOptions;
+
   /**
    * The channel from which messages are received and to which responses should
    * be sent.
@@ -86,9 +93,6 @@
    */
   RefactoringWorkspace _refactoringWorkspace;
 
-  RefactoringWorkspace get refactoringWorkspace => _refactoringWorkspace ??=
-      new RefactoringWorkspace(driverMap.values, searchEngine);
-
   /**
    * The versions of each document known to the server (keyed by path), used to
    * send back to the client for server-initiated edits so that the client can
@@ -114,10 +118,6 @@
 
   PerformanceLog _analysisPerformanceLogger;
 
-  ByteStore byteStore;
-
-  nd.AnalysisDriverScheduler analysisDriverScheduler;
-
   ServerStateMessageHandler messageHandler;
 
   int nextRequestId = 1;
@@ -150,6 +150,8 @@
     ResolverProvider packageResolverProvider: null,
   }) : super(options, diagnosticServer, baseResourceProvider) {
     messageHandler = new UninitializedStateMessageHandler(this);
+    // TODO(dantup): This code is almost identical to AnalysisServer, consider
+    // moving it the base class that already holds many of these fields.
     defaultContextOptions.generateImplicitErrors = false;
     defaultContextOptions.useFastaParser = options.useFastaParser;
 
@@ -169,8 +171,16 @@
     byteStore = createByteStore(resourceProvider);
     analysisDriverScheduler =
         new nd.AnalysisDriverScheduler(_analysisPerformanceLogger);
+    analysisDriverScheduler.status.listen(sendStatusNotification);
     analysisDriverScheduler.start();
 
+    if (options.featureSet.completion) {
+      declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
+      declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
+      analysisDriverScheduler.outOfBandWorker =
+          CompletionLibrariesWorker(declarationsTracker);
+    }
+
     contextManager = new ContextManagerImpl(
         resourceProvider,
         sdkManager,
@@ -191,6 +201,13 @@
 
   Future<void> get exited => channel.closed;
 
+  /// Initialization options provided by the LSP client. Allows opting in/out of
+  /// specific server functionality. Will be null prior to initialization.
+  LspInitializationOptions get initializationOptions => _initializationOptions;
+
+  RefactoringWorkspace get refactoringWorkspace => _refactoringWorkspace ??=
+      new RefactoringWorkspace(driverMap.values, searchEngine);
+
   addPriorityFile(String path) {
     final didAdd = priorityFiles.add(path);
     assert(didAdd);
@@ -232,8 +249,10 @@
             null, new Uri.file(path).toString());
   }
 
-  void handleClientConnection(ClientCapabilities capabilities) {
+  void handleClientConnection(
+      ClientCapabilities capabilities, dynamic initializationOptions) {
     _clientCapabilities = capabilities;
+    _initializationOptions = LspInitializationOptions(initializationOptions);
 
     performanceAfterStartup = new ServerPerformance();
     performance = performanceAfterStartup;
@@ -320,6 +339,42 @@
     ));
   }
 
+  /// Logs an exception by sending it to the client (window/logMessage) and
+  /// recording it in a buffer on the server for diagnostics.
+  void logException(String message, exception, stackTrace) {
+    if (exception is CaughtException) {
+      stackTrace ??= exception.stackTrace;
+      message = '$message: ${exception.exception}';
+    } else if (exception != null) {
+      message = '$message: $exception';
+    }
+
+    final fullError = stackTrace == null ? message : '$message\n$stackTrace';
+
+    // Log the full message since showMessage above may be truncated or formatted
+    // badly (eg. VS Code takes the newlines out).
+    logErrorToClient(fullError);
+
+    // remember the last few exceptions
+    exceptions.add(new ServerException(
+      message,
+      exception,
+      stackTrace is StackTrace ? stackTrace : null,
+      false,
+    ));
+  }
+
+  void publishClosingLabels(String path, List<ClosingLabel> labels) {
+    final params =
+        new PublishClosingLabelsParams(Uri.file(path).toString(), labels);
+    final message = new NotificationMessage(
+      CustomMethods.PublishClosingLabels,
+      params,
+      jsonRpcVersion,
+    );
+    sendNotification(message);
+  }
+
   void publishDiagnostics(String path, List<Diagnostic> errors) {
     final params =
         new PublishDiagnosticsParams(Uri.file(path).toString(), errors);
@@ -343,9 +398,6 @@
     if (message is RequestMessage) {
       channel.sendResponse(
           new ResponseMessage(message.id, null, error, jsonRpcVersion));
-      // Since the LSP client might not show the failed requests to the user,
-      // also ensure the error is logged to the client.
-      logErrorToClient(error.message);
     } else if (message is ResponseMessage) {
       // For bad response messages where we can't respond with an error, send it as
       // show instead of log.
@@ -411,31 +463,30 @@
     logException(message, exception, stackTrace);
   }
 
-  /// Logs an exception by sending it to the client (window/logMessage) and
-  /// recording it in a buffer on the server for diagnostics.
-  void logException(String message, exception, stackTrace) {
-    if (exception is CaughtException) {
-      stackTrace ??= exception.stackTrace;
-    }
-
-    final fullError = stackTrace == null ? message : '$message\n$stackTrace';
-
-    // Log the full message since showMessage above may be truncated or formatted
-    // badly (eg. VS Code takes the newlines out).
-    logErrorToClient(fullError);
-
-    // remember the last few exceptions
-    exceptions.add(new ServerException(
-      message,
-      exception,
-      stackTrace is StackTrace ? stackTrace : null,
-      false,
+  /// Send status notification to the client. The state of analysis is given by
+  /// the [status] information.
+  void sendStatusNotification(nd.AnalysisStatus status) {
+    channel.sendNotification(new NotificationMessage(
+      CustomMethods.AnalyzerStatus,
+      new AnalyzerStatusParams(status.isAnalyzing),
+      jsonRpcVersion,
     ));
   }
 
   void setAnalysisRoots(List<String> includedPaths) {
+    declarationsTracker?.discardContexts();
     final uniquePaths = HashSet<String>.of(includedPaths ?? const []);
     contextManager.setRoots(uniquePaths.toList(), [], {});
+    addContextsToDeclarationsTracker();
+  }
+
+  /// Returns `true` if closing labels should be sent for [file] with the given
+  /// absolute path.
+  bool shouldSendClosingLabelsFor(String file) {
+    // Closing labels should only be sent for open (priority) files in the workspace.
+    return initializationOptions.closingLabels &&
+        priorityFiles.contains(file) &&
+        contextManager.isInAnalysisRoot(file);
   }
 
   /**
@@ -443,7 +494,11 @@
    * absolute path.
    */
   bool shouldSendErrorsNotificationFor(String file) {
-    return contextManager.isInAnalysisRoot(file);
+    // Errors should not be reported for things that are explicitly skipped
+    // during normal analysis (for example dot folders are skipped over in
+    // _handleWatchEventImpl).
+    return contextManager.isInAnalysisRoot(file) &&
+        !contextManager.isContainedInDotFolder(file);
   }
 
   void showErrorMessageToUser(String message) {
@@ -475,7 +530,7 @@
           ..addAll(addedPaths ?? const [])
           ..removeAll(removedPaths ?? const []);
 
-    contextManager.setRoots(newPaths.toList(), [], {});
+    setAnalysisRoots(newPaths.toList());
   }
 
   void updateOverlay(String path, String contents) {
@@ -486,6 +541,8 @@
       resourceProvider.removeOverlay(path);
     }
     driverMap.values.forEach((driver) => driver.changeFile(path));
+
+    notifyDeclarationsTracker(path);
   }
 
   _updateDriversPriorityFiles() {
@@ -495,6 +552,20 @@
   }
 }
 
+class LspInitializationOptions {
+  final bool onlyAnalyzeProjectsWithOpenFiles;
+  final bool suggestFromUnimportedLibraries;
+  final bool closingLabels;
+  LspInitializationOptions(dynamic options)
+      : onlyAnalyzeProjectsWithOpenFiles = options != null &&
+            options['onlyAnalyzeProjectsWithOpenFiles'] == true,
+        // suggestFromUnimportedLibraries defaults to true, so must be
+        // explicitly passed as false to disable.
+        suggestFromUnimportedLibraries = options == null ||
+            options['suggestFromUnimportedLibraries'] != false,
+        closingLabels = options != null && options['closingLabels'] == true;
+}
+
 class LspPerformance {
   /// A list of code completion performance measurements for the latest
   /// completion operation up to [performanceListMaxLength] measurements.
@@ -535,6 +606,17 @@
 
         analysisServer.publishDiagnostics(result.path, serverErrors);
       }
+      if (result.unit != null) {
+        if (analysisServer.shouldSendClosingLabelsFor(path)) {
+          final labels =
+              new DartUnitClosingLabelsComputer(result.lineInfo, result.unit)
+                  .compute()
+                  .map((l) => toClosingLabel(result.lineInfo, l))
+                  .toList();
+
+          analysisServer.publishClosingLabels(result.path, labels);
+        }
+      }
     });
     analysisDriver.exceptions.listen((nd.ExceptionResult result) {
       String message = 'Analysis failed: ${result.path}';
@@ -553,6 +635,11 @@
   }
 
   @override
+  void analysisOptionsUpdated(nd.AnalysisDriver driver) {
+    // TODO: implement analysisOptionsUpdated
+  }
+
+  @override
   void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
     nd.AnalysisDriver analysisDriver = analysisServer.driverMap[contextFolder];
     if (analysisDriver != null) {
@@ -576,7 +663,8 @@
 
   @override
   void broadcastWatchEvent(WatchEvent event) {
-    // TODO: implement broadcastWatchEvent
+    analysisServer.notifyDeclarationsTracker(event.path);
+    // TODO: implement plugin broadcastWatchEvent
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 2f9dd65..469f150 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -1,11 +1,21 @@
-import 'dart:collection';
+// Copyright (c) 2019, 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:collection';
+import 'dart:math';
+
+import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart'
+    as lsp;
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart'
     show ResponseError;
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp;
 import 'package:analysis_server/lsp_protocol/protocol_special.dart'
     show ErrorOr, Either2, Either4;
+import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/lsp/constants.dart' as lsp;
 import 'package:analysis_server/src/lsp/dartdoc.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart' as lsp;
@@ -18,6 +28,8 @@
 import 'package:analyzer/src/dart/analysis/search.dart' as server
     show DeclarationKind;
 import 'package:analyzer/src/generated/source.dart' as server;
+import 'package:analyzer/src/services/available_declarations.dart';
+import 'package:analyzer/src/services/available_declarations.dart' as dec;
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart' as server;
 
 const languageSourceName = 'dart';
@@ -38,10 +50,10 @@
 /// it's important to call this immediately after computing edits to ensure
 /// the document is not modified before the version number is read.
 lsp.WorkspaceEdit createWorkspaceEdit(
-    lsp.LspAnalysisServer server, server.SourceChange change) {
+    lsp.LspAnalysisServer server, List<server.SourceFileEdit> edits) {
   return toWorkspaceEdit(
       server.clientCapabilities?.workspace,
-      change.edits
+      edits
           .map((e) => new FileEditInformation(
               server.getVersionedDocumentIdentifier(e.file),
               server.getLineInfo(e.file),
@@ -49,6 +61,42 @@
           .toList());
 }
 
+lsp.CompletionItemKind declarationKindToCompletionItemKind(
+  HashSet<lsp.CompletionItemKind> clientSupportedCompletionKinds,
+  dec.DeclarationKind kind,
+) {
+  bool isSupported(lsp.CompletionItemKind kind) =>
+      clientSupportedCompletionKinds.contains(kind);
+
+  List<lsp.CompletionItemKind> getKindPreferences() {
+    switch (kind) {
+      case dec.DeclarationKind.CLASS:
+      case dec.DeclarationKind.CLASS_TYPE_ALIAS:
+      case dec.DeclarationKind.MIXIN:
+        return const [lsp.CompletionItemKind.Class];
+      case dec.DeclarationKind.CONSTRUCTOR:
+        return const [lsp.CompletionItemKind.Constructor];
+      case dec.DeclarationKind.ENUM:
+      case dec.DeclarationKind.ENUM_CONSTANT:
+        return const [lsp.CompletionItemKind.Enum];
+      case dec.DeclarationKind.FUNCTION:
+        return const [lsp.CompletionItemKind.Function];
+      case dec.DeclarationKind.FUNCTION_TYPE_ALIAS:
+        return const [lsp.CompletionItemKind.Class];
+      case dec.DeclarationKind.GETTER:
+        return const [lsp.CompletionItemKind.Property];
+      case dec.DeclarationKind.SETTER:
+        return const [lsp.CompletionItemKind.Property];
+      case dec.DeclarationKind.VARIABLE:
+        return const [lsp.CompletionItemKind.Variable];
+      default:
+        return const [];
+    }
+  }
+
+  return getKindPreferences().firstWhere(isSupported, orElse: () => null);
+}
+
 lsp.SymbolKind declarationKindToSymbolKind(
   HashSet<lsp.SymbolKind> clientSupportedSymbolKinds,
   server.DeclarationKind kind,
@@ -84,13 +132,74 @@
         return const [lsp.SymbolKind.Variable];
       default:
         assert(false, 'Unexpected declaration kind $kind');
-        return null;
+        return const [];
     }
   }
 
   return getKindPreferences().firstWhere(isSupported, orElse: () => null);
 }
 
+lsp.CompletionItem declarationToCompletionItem(
+  lsp.TextDocumentClientCapabilitiesCompletion completionCapabilities,
+  HashSet<lsp.CompletionItemKind> supportedCompletionItemKinds,
+  String file,
+  int offset,
+  IncludedSuggestionSet includedSuggestionSet,
+  Library library,
+  Map<String, int> tagBoosts,
+  server.LineInfo lineInfo,
+  dec.Declaration declaration,
+  int replacementOffset,
+  int replacementLength,
+) {
+  final label = declaration.name;
+
+  final useDeprecated =
+      completionCapabilities?.completionItem?.deprecatedSupport == true;
+
+  final completionKind = declarationKindToCompletionItemKind(
+      supportedCompletionItemKinds, declaration.kind);
+
+  var relevanceBoost = 0;
+  if (declaration.relevanceTags != null)
+    declaration.relevanceTags.forEach(
+        (t) => relevanceBoost = max(relevanceBoost, tagBoosts[t] ?? 0));
+  final itemRelevance = includedSuggestionSet.relevance + relevanceBoost;
+
+  // Because we potentially send thousands of these items, we should minimise
+  // the generated JSON as much as possible - for example using nulls in place
+  // of empty lists/false where possible.
+  return new lsp.CompletionItem(
+    label,
+    completionKind,
+    getDeclarationCompletionDetail(declaration, completionKind, useDeprecated),
+    null, // documentation - will be added during resolve.
+    useDeprecated && declaration.isDeprecated ? true : null,
+    null, // preselect
+    // Relevance is a number, highest being best. LSP does text sort so subtract
+    // from a large number so that a text sort will result in the correct order.
+    // 555 -> 999455
+    //  10 -> 999990
+    //   1 -> 999999
+    (1000000 - itemRelevance).toString(),
+    null, // filterText uses label if not set
+    null, // insertText is deprecated, but also uses label if not set
+    null, // insertTextFormat (we always use plain text so can ommit this)
+    null, // textEdit - added on during resolve
+    null, // additionalTextEdits, used for adding imports, etc.
+    null, // commitCharacters
+    null, // command
+    // data, used for completionItem/resolve.
+    new lsp.CompletionItemResolutionInfo(
+        file,
+        offset,
+        includedSuggestionSet.id,
+        includedSuggestionSet.displayUri ?? library.uri?.toString(),
+        replacementOffset,
+        replacementLength),
+  );
+}
+
 lsp.CompletionItemKind elementKindToCompletionItemKind(
   HashSet<lsp.CompletionItemKind> clientSupportedCompletionKinds,
   server.ElementKind kind,
@@ -131,6 +240,8 @@
         return const [lsp.CompletionItemKind.Variable];
       case server.ElementKind.METHOD:
         return const [lsp.CompletionItemKind.Method];
+      case server.ElementKind.MIXIN:
+        return const [lsp.CompletionItemKind.Class];
       case server.ElementKind.PARAMETER:
       case server.ElementKind.PREFIX:
         return const [lsp.CompletionItemKind.Variable];
@@ -147,7 +258,7 @@
       case server.ElementKind.UNIT_TEST_TEST:
         return const [lsp.CompletionItemKind.Method];
       default:
-        return null;
+        return const [];
     }
   }
 
@@ -214,7 +325,7 @@
         return const [lsp.SymbolKind.Method];
       default:
         assert(false, 'Unexpected element kind $kind');
-        return null;
+        return const [];
     }
   }
 
@@ -263,10 +374,52 @@
   } else if (hasParameterType) {
     return '$prefix${suggestion.parameterType}';
   } else {
-    return prefix;
+    return prefix.isNotEmpty ? prefix : null;
   }
 }
 
+String getDeclarationCompletionDetail(
+  dec.Declaration declaration,
+  lsp.CompletionItemKind completionKind,
+  bool clientSupportsDeprecated,
+) {
+  final hasParameters =
+      declaration.parameters != null && declaration.parameters.isNotEmpty;
+  final hasReturnType =
+      declaration.returnType != null && declaration.returnType.isNotEmpty;
+
+  final prefix = clientSupportsDeprecated || !declaration.isDeprecated
+      ? ''
+      : '(Deprecated) ';
+
+  if (completionKind == lsp.CompletionItemKind.Property) {
+    // Setters appear as methods with one arg but they also cause getters to not
+    // appear in the completion list, so displaying them as setters is misleading.
+    // To avoid this, always show only the return type, whether it's a getter
+    // or a setter.
+    return prefix +
+        (declaration.kind == dec.DeclarationKind.GETTER
+            ? declaration.returnType
+            // Don't assume setters always have parameters
+            // See https://github.com/dart-lang/sdk/issues/27747
+            : declaration.parameters != null &&
+                    declaration.parameters.isNotEmpty
+                // Extract the type part from '(MyType value)`
+                ? declaration.parameters
+                    .substring(1, declaration.parameters.lastIndexOf(" "))
+                : '');
+  } else if (hasParameters && hasReturnType) {
+    return '$prefix${declaration.parameters} → ${declaration.returnType}';
+  } else if (hasReturnType) {
+    return '$prefix${declaration.returnType}';
+  } else {
+    return prefix.isNotEmpty ? prefix : null;
+  }
+}
+
+bool isDartDocument(lsp.TextDocumentIdentifier doc) =>
+    doc?.uri?.endsWith('.dart');
+
 lsp.Location navigationTargetToLocation(String targetFilePath,
     server.NavigationTarget target, server.LineInfo lineInfo) {
   if (lineInfo == null) {
@@ -367,13 +520,18 @@
       case server.CompletionSuggestionKind.PARAMETER:
         return const [lsp.CompletionItemKind.Value];
       default:
-        return null;
+        return const [];
     }
   }
 
   return getKindPreferences().firstWhere(isSupported, orElse: () => null);
 }
 
+lsp.ClosingLabel toClosingLabel(
+        server.LineInfo lineInfo, server.ClosingLabel label) =>
+    lsp.ClosingLabel(
+        toRange(lineInfo, label.offset, label.length), label.label);
+
 lsp.CompletionItem toCompletionItem(
   lsp.TextDocumentClientCapabilitiesCompletion completionCapabilities,
   HashSet<lsp.CompletionItemKind> supportedCompletionItemKinds,
@@ -396,13 +554,16 @@
       : suggestionKindToCompletionItemKind(
           supportedCompletionItemKinds, suggestion.kind, label);
 
+  // Because we potentially send thousands of these items, we should minimise
+  // the generated JSON as much as possible - for example using nulls in place
+  // of empty lists/false where possible.
   return new lsp.CompletionItem(
     label,
     completionKind,
     getCompletionDetail(suggestion, completionKind, useDeprecated),
     asStringOrMarkupContent(formats, cleanDartdoc(suggestion.docComplete)),
-    useDeprecated ? suggestion.isDeprecated : null,
-    false, // preselect
+    useDeprecated && suggestion.isDeprecated ? true : null,
+    null, // preselect
     // Relevance is a number, highest being best. LSP does text sort so subtract
     // from a large number so that a text sort will result in the correct order.
     // 555 -> 999455
@@ -411,16 +572,15 @@
     (1000000 - suggestion.relevance).toString(),
     null, // filterText uses label if not set
     null, // insertText is deprecated, but also uses label if not set
-    // We don't have completions that use snippets, so we always return PlainText.
-    lsp.InsertTextFormat.PlainText,
+    null, // insertTextFormat (we always use plain text so can ommit this)
     new lsp.TextEdit(
       // TODO(dantup): If `clientSupportsSnippets == true` then we should map
       // `selection` in to a snippet (see how Dart Code does this).
       toRange(lineInfo, replacementOffset, replacementLength),
       suggestion.completion,
     ),
-    [], // additionalTextEdits, used for adding imports, etc.
-    [], // commitCharacters
+    null, // additionalTextEdits, used for adding imports, etc.
+    null, // commitCharacters
     null, // command
     null, // data, useful for if using lazy resolve, this comes back to us
   );
@@ -491,6 +651,16 @@
       .toList();
 }
 
+lsp.Location toLocation(server.Location location, server.LineInfo lineInfo) =>
+    lsp.Location(
+      Uri.file(location.file).toString(),
+      toRange(
+        lineInfo,
+        location.offset,
+        location.length,
+      ),
+    );
+
 ErrorOr<int> toOffset(
   server.LineInfo lineInfo,
   lsp.Position pos, {
diff --git a/pkg/analysis_server/lib/src/nullability/conditional_discard.dart b/pkg/analysis_server/lib/src/nullability/conditional_discard.dart
deleted file mode 100644
index 3e09ed4..0000000
--- a/pkg/analysis_server/lib/src/nullability/conditional_discard.dart
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/nullability_node.dart';
-import 'package:analysis_server/src/nullability/unit_propagation.dart';
-
-/// Container for information gathered during nullability migration about a
-/// conditional check that might need to be discarded.
-///
-/// This information will be associated with an Expression in the input program
-/// whose boolean value influences control flow (e.g. the condition of an `if`
-/// statement).
-class ConditionalDiscard {
-  /// Nullability node that will be `nullable` if the code path that results
-  /// from the condition evaluating to `true` will be reachable after
-  /// nullability migration, and therefore should be kept.
-  ///
-  /// `null` if the code path should be kept regardless of the outcome of
-  /// migration.
-  final NullabilityNode trueGuard;
-
-  /// Nullability node that will be `nullable` if the code path that results
-  /// from the condition evaluating to `false` will be reachable after
-  /// nullability migration, and therefore should be kept.
-  ///
-  /// `null` if the code path should be kept regardless of the outcome of
-  /// migration.
-  final NullabilityNode falseGuard;
-
-  /// Indicates whether the condition is pure (free from side effects).
-  ///
-  /// For example, a condition like `x == null` is pure (assuming `x` is a local
-  /// variable or static variable), because evaluating it has no user-visible
-  /// effect other than returning a boolean value.
-  ///
-  /// If [pureCondition] is `false`, and either [trueGuard] or [falseGuard] is
-  /// `false`, that it is safe to delete the condition expression as well as the
-  /// dead code branch (e.g. it means that `if (x == null) f(); else g();` could
-  /// be changed to simply `g();`).
-  final bool pureCondition;
-
-  ConditionalDiscard(this.trueGuard, this.falseGuard, this.pureCondition);
-
-  /// Indicates whether the code path that results from the condition evaluating
-  /// to `false` is reachable after migration.
-  bool get keepFalse => falseGuard == null || falseGuard.isNullable;
-
-  /// Indicates whether the code path that results from the condition evaluating
-  /// to `true` is reachable after migration.
-  bool get keepTrue => trueGuard == null || trueGuard.isNullable;
-}
diff --git a/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart b/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart
deleted file mode 100644
index a723c9a..0000000
--- a/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart
+++ /dev/null
@@ -1,560 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/conditional_discard.dart';
-import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
-import 'package:analysis_server/src/nullability/decorated_type.dart';
-import 'package:analysis_server/src/nullability/expression_checks.dart';
-import 'package:analysis_server/src/nullability/nullability_node.dart';
-import 'package:analysis_server/src/nullability/transitional_api.dart';
-import 'package:analysis_server/src/nullability/unit_propagation.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:meta/meta.dart';
-
-/// Visitor that gathers nullability migration constraints from code to be
-/// migrated.
-///
-/// The return type of each `visit...` method is a [DecoratedType] indicating
-/// the static type of the visited expression, along with the constraint
-/// variables that will determine its nullability.  For `visit...` methods that
-/// don't visit expressions, `null` will be returned.
-class ConstraintGatherer extends GeneralizingAstVisitor<DecoratedType> {
-  /// The repository of constraint variables and decorated types (from a
-  /// previous pass over the source code).
-  final VariableRepository _variables;
-
-  final bool _permissive;
-
-  final NullabilityMigrationAssumptions assumptions;
-
-  /// Constraints gathered by the visitor are stored here.
-  final Constraints _constraints;
-
-  /// The file being analyzed.
-  final Source _source;
-
-  /// For convenience, a [DecoratedType] representing non-nullable `Object`.
-  final DecoratedType _notNullType;
-
-  /// For convenience, a [DecoratedType] representing non-nullable `bool`.
-  final DecoratedType _nonNullableBoolType;
-
-  /// For convenience, a [DecoratedType] representing non-nullable `Type`.
-  final DecoratedType _nonNullableTypeType;
-
-  /// For convenience, a [DecoratedType] representing `Null`.
-  final DecoratedType _nullType;
-
-  /// The [DecoratedType] of the innermost function or method being visited, or
-  /// `null` if the visitor is not inside any function or method.
-  ///
-  /// This is needed to construct the appropriate nullability constraints for
-  /// return statements.
-  DecoratedType _currentFunctionType;
-
-  /// Information about the most recently visited binary expression whose
-  /// boolean value could possibly affect nullability analysis.
-  _ConditionInfo _conditionInfo;
-
-  /// The set of nullability nodes that would have to be `nullable` for the code
-  /// currently being visited to be reachable.
-  ///
-  /// Guard variables are attached to the left hand side of any generated
-  /// constraints, so that constraints do not take effect if they come from
-  /// code that can be proven unreachable by the migration tool.
-  final _guards = <NullabilityNode>[];
-
-  /// Indicates whether the statement or expression being visited is within
-  /// conditional control flow.  If `true`, this means that the enclosing
-  /// function might complete normally without executing the current statement
-  /// or expression.
-  bool _inConditionalControlFlow = false;
-
-  ConstraintGatherer(TypeProvider typeProvider, this._variables,
-      this._constraints, this._source, this._permissive, this.assumptions)
-      : _notNullType =
-            DecoratedType(typeProvider.objectType, NullabilityNode.never),
-        _nonNullableBoolType =
-            DecoratedType(typeProvider.boolType, NullabilityNode.never),
-        _nonNullableTypeType =
-            DecoratedType(typeProvider.typeType, NullabilityNode.never),
-        _nullType =
-            DecoratedType(typeProvider.nullType, NullabilityNode.always);
-
-  /// Gets the decorated type of [element] from [_variables], performing any
-  /// necessary substitutions.
-  DecoratedType getOrComputeElementType(Element element,
-      {DecoratedType targetType}) {
-    Map<TypeParameterElement, DecoratedType> substitution;
-    Element baseElement;
-    if (element is Member) {
-      assert(targetType != null);
-      baseElement = element.baseElement;
-      var targetTypeType = targetType.type;
-      if (targetTypeType is InterfaceType &&
-          baseElement is ClassMemberElement) {
-        var enclosingClass = baseElement.enclosingElement;
-        assert(targetTypeType.element == enclosingClass); // TODO(paulberry)
-        substitution = <TypeParameterElement, DecoratedType>{};
-        assert(enclosingClass.typeParameters.length ==
-            targetTypeType.typeArguments.length); // TODO(paulberry)
-        for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
-          substitution[enclosingClass.typeParameters[i]] =
-              targetType.typeArguments[i];
-        }
-      }
-    } else {
-      baseElement = element;
-    }
-    var decoratedBaseType =
-        _variables.decoratedElementType(baseElement, create: true);
-    if (substitution != null) {
-      DartType elementType;
-      if (element is MethodElement) {
-        elementType = element.type;
-      } else {
-        throw element.runtimeType; // TODO(paulberry)
-      }
-      return decoratedBaseType.substitute(
-          _constraints, substitution, elementType);
-    } else {
-      return decoratedBaseType;
-    }
-  }
-
-  @override
-  DecoratedType visitAssertStatement(AssertStatement node) {
-    _handleAssignment(_notNullType, node.condition);
-    if (identical(_conditionInfo?.condition, node.condition)) {
-      if (!_inConditionalControlFlow &&
-          _conditionInfo.trueDemonstratesNonNullIntent != null) {
-        _conditionInfo.trueDemonstratesNonNullIntent
-            ?.recordNonNullIntent(_constraints, _guards);
-      }
-    }
-    node.message?.accept(this);
-    return null;
-  }
-
-  @override
-  DecoratedType visitBinaryExpression(BinaryExpression node) {
-    switch (node.operator.type) {
-      case TokenType.EQ_EQ:
-      case TokenType.BANG_EQ:
-        assert(node.leftOperand is! NullLiteral); // TODO(paulberry)
-        var leftType = node.leftOperand.accept(this);
-        node.rightOperand.accept(this);
-        if (node.rightOperand is NullLiteral) {
-          // TODO(paulberry): figure out what the rules for isPure should be.
-          // TODO(paulberry): only set falseChecksNonNull in unconditional
-          // control flow
-          bool isPure = node.leftOperand is SimpleIdentifier;
-          var conditionInfo = _ConditionInfo(node,
-              isPure: isPure,
-              trueGuard: leftType.node,
-              falseDemonstratesNonNullIntent: leftType.node);
-          _conditionInfo = node.operator.type == TokenType.EQ_EQ
-              ? conditionInfo
-              : conditionInfo.not(node);
-        }
-        return _nonNullableBoolType;
-      case TokenType.PLUS:
-        _handleAssignment(_notNullType, node.leftOperand);
-        var callee = node.staticElement;
-        assert(!(callee is ClassMemberElement &&
-            callee.enclosingElement.typeParameters
-                .isNotEmpty)); // TODO(paulberry)
-        assert(callee != null); // TODO(paulberry)
-        var calleeType = getOrComputeElementType(callee);
-        // TODO(paulberry): substitute if necessary
-        assert(calleeType.positionalParameters.length > 0); // TODO(paulberry)
-        _handleAssignment(
-            calleeType.positionalParameters[0], node.rightOperand);
-        return calleeType.returnType;
-      default:
-        assert(false); // TODO(paulberry)
-        return null;
-    }
-  }
-
-  @override
-  DecoratedType visitBooleanLiteral(BooleanLiteral node) {
-    return DecoratedType(node.staticType, NullabilityNode.never);
-  }
-
-  @override
-  DecoratedType visitClassDeclaration(ClassDeclaration node) {
-    node.members.accept(this);
-    return null;
-  }
-
-  @override
-  DecoratedType visitConditionalExpression(ConditionalExpression node) {
-    _handleAssignment(_notNullType, node.condition);
-    // TODO(paulberry): guard anything inside the true and false branches
-    var thenType = node.thenExpression.accept(this);
-    assert(_isSimple(thenType)); // TODO(paulberry)
-    var elseType = node.elseExpression.accept(this);
-    assert(_isSimple(elseType)); // TODO(paulberry)
-    var overallType = DecoratedType(
-        node.staticType,
-        NullabilityNode.forConditionalexpression(
-            node, thenType.node, elseType.node, _joinNullabilities));
-    _variables.recordDecoratedExpressionType(node, overallType);
-    return overallType;
-  }
-
-  @override
-  DecoratedType visitDefaultFormalParameter(DefaultFormalParameter node) {
-    var defaultValue = node.defaultValue;
-    if (defaultValue == null) {
-      if (node.declaredElement.hasRequired) {
-        // Nothing to do; the implicit default value of `null` will never be
-        // reached.
-      } else if (node.declaredElement.isOptionalPositional ||
-          assumptions.namedNoDefaultParameterHeuristic ==
-              NamedNoDefaultParameterHeuristic.assumeNullable) {
-        NullabilityNode.recordAssignment(
-            NullabilityNode.always,
-            getOrComputeElementType(node.declaredElement).node,
-            null,
-            _guards,
-            _constraints,
-            false);
-      } else {
-        assert(assumptions.namedNoDefaultParameterHeuristic ==
-            NamedNoDefaultParameterHeuristic.assumeRequired);
-      }
-    } else {
-      _handleAssignment(
-          getOrComputeElementType(node.declaredElement), defaultValue,
-          canInsertChecks: false);
-    }
-    return null;
-  }
-
-  @override
-  DecoratedType visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    _handleAssignment(_currentFunctionType.returnType, node.expression);
-    return null;
-  }
-
-  @override
-  DecoratedType visitFunctionDeclaration(FunctionDeclaration node) {
-    node.functionExpression.parameters.accept(this);
-    assert(_currentFunctionType == null);
-    _currentFunctionType =
-        _variables.decoratedElementType(node.declaredElement);
-    _inConditionalControlFlow = false;
-    try {
-      node.functionExpression.body.accept(this);
-    } finally {
-      _currentFunctionType = null;
-    }
-    return null;
-  }
-
-  @override
-  DecoratedType visitIfStatement(IfStatement node) {
-    // TODO(paulberry): should the use of a boolean in an if-statement be
-    // treated like an implicit `assert(b != null)`?  Probably.
-    _handleAssignment(_notNullType, node.condition);
-    _inConditionalControlFlow = true;
-    NullabilityNode trueGuard;
-    NullabilityNode falseGuard;
-    if (identical(_conditionInfo?.condition, node.condition)) {
-      trueGuard = _conditionInfo.trueGuard;
-      falseGuard = _conditionInfo.falseGuard;
-      _variables.recordConditionalDiscard(_source, node,
-          ConditionalDiscard(trueGuard, falseGuard, _conditionInfo.isPure));
-    }
-    if (trueGuard != null) {
-      _guards.add(trueGuard);
-    }
-    try {
-      node.thenStatement.accept(this);
-    } finally {
-      if (trueGuard != null) {
-        _guards.removeLast();
-      }
-    }
-    if (falseGuard != null) {
-      _guards.add(falseGuard);
-    }
-    try {
-      node.elseStatement?.accept(this);
-    } finally {
-      if (falseGuard != null) {
-        _guards.removeLast();
-      }
-    }
-    return null;
-  }
-
-  @override
-  DecoratedType visitIntegerLiteral(IntegerLiteral node) {
-    return DecoratedType(node.staticType, NullabilityNode.never);
-  }
-
-  @override
-  DecoratedType visitMethodDeclaration(MethodDeclaration node) {
-    node.parameters.accept(this);
-    assert(_currentFunctionType == null);
-    _currentFunctionType =
-        _variables.decoratedElementType(node.declaredElement);
-    _inConditionalControlFlow = false;
-    try {
-      node.body.accept(this);
-    } finally {
-      _currentFunctionType = null;
-    }
-    return null;
-  }
-
-  @override
-  DecoratedType visitMethodInvocation(MethodInvocation node) {
-    DecoratedType targetType;
-    if (node.target != null) {
-      assert(node.operator.type == TokenType.PERIOD);
-      _checkNonObjectMember(node.methodName.name); // TODO(paulberry)
-      targetType = _handleAssignment(_notNullType, node.target);
-    }
-    var callee = node.methodName.staticElement;
-    assert(callee != null); // TODO(paulberry)
-    var calleeType = getOrComputeElementType(callee, targetType: targetType);
-    // TODO(paulberry): substitute if necessary
-    var arguments = node.argumentList.arguments;
-    int i = 0;
-    var suppliedNamedParameters = Set<String>();
-    for (var expression in arguments) {
-      if (expression is NamedExpression) {
-        var name = expression.name.label.name;
-        var parameterType = calleeType.namedParameters[name];
-        assert(parameterType != null); // TODO(paulberry)
-        _handleAssignment(parameterType, expression.expression);
-        suppliedNamedParameters.add(name);
-      } else {
-        assert(calleeType.positionalParameters.length > i); // TODO(paulberry)
-        _handleAssignment(calleeType.positionalParameters[i++], expression);
-      }
-    }
-    // Any parameters not supplied must be optional.
-    for (var entry in calleeType.namedParameters.entries) {
-      if (suppliedNamedParameters.contains(entry.key)) continue;
-      entry.value.node.recordNamedParameterNotSupplied(_constraints, _guards);
-    }
-    return calleeType.returnType;
-  }
-
-  @override
-  DecoratedType visitNode(AstNode node) {
-    if (_permissive) {
-      try {
-        return super.visitNode(node);
-      } catch (_) {
-        return null;
-      }
-    } else {
-      return super.visitNode(node);
-    }
-  }
-
-  @override
-  DecoratedType visitNullLiteral(NullLiteral node) {
-    return _nullType;
-  }
-
-  @override
-  DecoratedType visitParenthesizedExpression(ParenthesizedExpression node) {
-    return node.expression.accept(this);
-  }
-
-  @override
-  DecoratedType visitReturnStatement(ReturnStatement node) {
-    if (node.expression == null) {
-      _checkAssignment(_currentFunctionType.returnType, _nullType, null);
-    } else {
-      _handleAssignment(_currentFunctionType.returnType, node.expression);
-    }
-    return null;
-  }
-
-  @override
-  DecoratedType visitSimpleIdentifier(SimpleIdentifier node) {
-    var staticElement = node.staticElement;
-    if (staticElement is ParameterElement) {
-      return getOrComputeElementType(staticElement);
-    } else if (staticElement is ClassElement) {
-      return _nonNullableTypeType;
-    } else {
-      // TODO(paulberry)
-      throw new UnimplementedError('${staticElement.runtimeType}');
-    }
-  }
-
-  @override
-  DecoratedType visitStringLiteral(StringLiteral node) {
-    return DecoratedType(node.staticType, NullabilityNode.never);
-  }
-
-  @override
-  DecoratedType visitThisExpression(ThisExpression node) {
-    return DecoratedType(node.staticType, NullabilityNode.never);
-  }
-
-  @override
-  DecoratedType visitThrowExpression(ThrowExpression node) {
-    node.expression.accept(this);
-    // TODO(paulberry): do we need to check the expression type?  I think not.
-    return DecoratedType(node.staticType, NullabilityNode.never);
-  }
-
-  @override
-  DecoratedType visitTypeName(TypeName typeName) {
-    return DecoratedType(typeName.type, NullabilityNode.never);
-  }
-
-  /// Creates the necessary constraint(s) for an assignment from [sourceType] to
-  /// [destinationType].  [expression] is the expression whose type is
-  /// [sourceType]; it is the expression we will have to null-check in the case
-  /// where a nullable source is assigned to a non-nullable destination.
-  void _checkAssignment(DecoratedType destinationType, DecoratedType sourceType,
-      Expression expression) {
-    CheckExpression checkNotNull;
-    if (expression != null) {
-      checkNotNull = CheckExpression(expression);
-      _variables.recordExpressionChecks(
-          _source, expression, ExpressionChecks(checkNotNull));
-    }
-    NullabilityNode.recordAssignment(sourceType.node, destinationType.node,
-        checkNotNull, _guards, _constraints, _inConditionalControlFlow);
-    // TODO(paulberry): it's a cheat to pass in expression=null for the
-    // recursive checks.  Really we want to unify all the checks in a single
-    // ExpressionChecks object.
-    expression = null;
-    // TODO(paulberry): generalize this.
-    if ((_isSimple(sourceType) || destinationType.type.isObject) &&
-        _isSimple(destinationType)) {
-      // Ok; nothing further to do.
-    } else if (sourceType.type is InterfaceType &&
-        destinationType.type is InterfaceType &&
-        sourceType.type.element == destinationType.type.element) {
-      assert(sourceType.typeArguments.length ==
-          destinationType.typeArguments.length);
-      for (int i = 0; i < sourceType.typeArguments.length; i++) {
-        _checkAssignment(destinationType.typeArguments[i],
-            sourceType.typeArguments[i], expression);
-      }
-    } else if (destinationType.type.isDynamic || sourceType.type.isDynamic) {
-      // ok; nothing further to do.
-    } else {
-      throw '$destinationType <= $sourceType'; // TODO(paulberry)
-    }
-  }
-
-  /// Double checks that [name] is not the name of a method or getter declared
-  /// on [Object].
-  ///
-  /// TODO(paulberry): get rid of this method and put the correct logic into the
-  /// call sites.
-  void _checkNonObjectMember(String name) {
-    assert(name != 'toString');
-    assert(name != 'hashCode');
-    assert(name != 'noSuchMethod');
-    assert(name != 'runtimeType');
-  }
-
-  /// Creates the necessary constraint(s) for an assignment of the given
-  /// [expression] to a destination whose type is [destinationType].
-  DecoratedType _handleAssignment(
-      DecoratedType destinationType, Expression expression,
-      {bool canInsertChecks = true}) {
-    var sourceType = expression.accept(this);
-    _checkAssignment(
-        destinationType, sourceType, canInsertChecks ? expression : null);
-    return sourceType;
-  }
-
-  /// Double checks that [type] is sufficiently simple for this naive prototype
-  /// implementation.
-  ///
-  /// TODO(paulberry): get rid of this method and put the correct logic into the
-  /// call sites.
-  bool _isSimple(DecoratedType type) {
-    if (type.type.isBottom) return true;
-    if (type.type.isVoid) return true;
-    if (type.type is! InterfaceType) return false;
-    if ((type.type as InterfaceType).typeParameters.isNotEmpty) return false;
-    return true;
-  }
-
-  /// Creates a constraint variable (if necessary) representing the nullability
-  /// of [node], which is the disjunction of the nullabilities [a] and [b].
-  ConstraintVariable _joinNullabilities(
-      ConditionalExpression node, ConstraintVariable a, ConstraintVariable b) {
-    if (a == null) return b;
-    if (b == null) return a;
-    if (identical(a, ConstraintVariable.always) ||
-        identical(b, ConstraintVariable.always)) {
-      return ConstraintVariable.always;
-    }
-    var result = TypeIsNullable(node.offset);
-    _constraints.record([a], result);
-    _constraints.record([b], result);
-    _constraints.record([result], ConstraintVariable.or(_constraints, a, b));
-    return result;
-  }
-}
-
-/// Information about a binary expression whose boolean value could possibly
-/// affect nullability analysis.
-class _ConditionInfo {
-  /// The [expression] of interest.
-  final Expression condition;
-
-  /// Indicates whether [condition] is pure (free from side effects).
-  ///
-  /// For example, a condition like `x == null` is pure (assuming `x` is a local
-  /// variable or static variable), because evaluating it has no user-visible
-  /// effect other than returning a boolean value.
-  final bool isPure;
-
-  /// If not `null`, the [NullabilityNode] that would need to be nullable in
-  /// order for [condition] to evaluate to `true`.
-  final NullabilityNode trueGuard;
-
-  /// If not `null`, the [NullabilityNode] that would need to be nullable in
-  /// order for [condition] to evaluate to `false`.
-  final NullabilityNode falseGuard;
-
-  /// If not `null`, the [NullabilityNode] that should be asserted to have
-  //  /// non-null intent if [condition] is asserted to be `true`.
-  final NullabilityNode trueDemonstratesNonNullIntent;
-
-  /// If not `null`, the [NullabilityNode] that should be asserted to have
-  /// non-null intent if [condition] is asserted to be `false`.
-  final NullabilityNode falseDemonstratesNonNullIntent;
-
-  _ConditionInfo(this.condition,
-      {@required this.isPure,
-      this.trueGuard,
-      this.falseGuard,
-      this.trueDemonstratesNonNullIntent,
-      this.falseDemonstratesNonNullIntent});
-
-  /// Returns a new [_ConditionInfo] describing the boolean "not" of `this`.
-  _ConditionInfo not(Expression condition) => _ConditionInfo(condition,
-      isPure: isPure,
-      trueGuard: falseGuard,
-      falseGuard: trueGuard,
-      trueDemonstratesNonNullIntent: falseDemonstratesNonNullIntent,
-      falseDemonstratesNonNullIntent: trueDemonstratesNonNullIntent);
-}
diff --git a/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart b/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
deleted file mode 100644
index 8f5f170..0000000
--- a/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/conditional_discard.dart';
-import 'package:analysis_server/src/nullability/decorated_type.dart';
-import 'package:analysis_server/src/nullability/expression_checks.dart';
-import 'package:analysis_server/src/nullability/nullability_node.dart';
-import 'package:analysis_server/src/nullability/transitional_api.dart';
-import 'package:analysis_server/src/nullability/unit_propagation.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/type.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-/// Visitor that gathers constraint variables for nullability migration from
-/// code to be migrated.
-///
-/// The return type of each `visit...` method is a [DecoratedType] indicating
-/// the static type of the element declared by the visited node, along with the
-/// constraint variables that will determine its nullability.  For `visit...`
-/// methods that don't visit declarations, `null` will be returned.
-class ConstraintVariableGatherer extends GeneralizingAstVisitor<DecoratedType> {
-  /// Constraint variables and decorated types are stored here.
-  final VariableRecorder _variables;
-
-  /// The file being analyzed.
-  final Source _source;
-
-  /// If the parameters of a function or method are being visited, the
-  /// [DecoratedType] of the corresponding function or method type.
-  ///
-  /// TODO(paulberry): should this be updated when we visit generic function
-  /// type syntax?  How about when we visit old-style function-typed formal
-  /// parameters?
-  DecoratedType _currentFunctionType;
-
-  final bool _permissive;
-
-  final NullabilityMigrationAssumptions assumptions;
-
-  ConstraintVariableGatherer(
-      this._variables, this._source, this._permissive, this.assumptions);
-
-  /// Creates and stores a [DecoratedType] object corresponding to the given
-  /// [type] AST, and returns it.
-  DecoratedType decorateType(TypeAnnotation type) {
-    return type == null
-        // TODO(danrubel): Return something other than this
-        // to indicate that we should insert a type for the declaration
-        // that is missing a type reference.
-        ? new DecoratedType(
-            DynamicTypeImpl.instance, NullabilityNode.forInferredDynamicType())
-        : type.accept(this);
-  }
-
-  @override
-  DecoratedType visitDefaultFormalParameter(DefaultFormalParameter node) {
-    var decoratedType = node.parameter.accept(this);
-    if (node.declaredElement.hasRequired || node.defaultValue != null) {
-      return null;
-    }
-    decoratedType.node.trackPossiblyOptional();
-    _variables.recordPossiblyOptional(_source, node, decoratedType.node);
-  }
-
-  @override
-  DecoratedType visitFormalParameter(FormalParameter node) {
-    // Do not visit children
-    // TODO(paulberry): handle all types of formal parameters
-    // - NormalFormalParameter
-    // - SimpleFormalParameter
-    // - FieldFormalParameter
-    // - FunctionTypedFormalParameter
-    // - DefaultFormalParameter
-    return null;
-  }
-
-  @override
-  DecoratedType visitFunctionDeclaration(FunctionDeclaration node) {
-    _handleExecutableDeclaration(node.declaredElement, node.returnType,
-        node.functionExpression.parameters);
-    return null;
-  }
-
-  @override
-  DecoratedType visitMethodDeclaration(MethodDeclaration node) {
-    _handleExecutableDeclaration(
-        node.declaredElement, node.returnType, node.parameters);
-    return null;
-  }
-
-  @override
-  DecoratedType visitNode(AstNode node) {
-    if (_permissive) {
-      try {
-        return super.visitNode(node);
-      } catch (_) {
-        return null;
-      }
-    } else {
-      return super.visitNode(node);
-    }
-  }
-
-  @override
-  DecoratedType visitSimpleFormalParameter(SimpleFormalParameter node) {
-    var type = decorateType(node.type);
-    var declaredElement = node.declaredElement;
-    type.node.trackNonNullIntent(node.offset);
-    _variables.recordDecoratedElementType(declaredElement, type);
-    if (declaredElement.isNamed) {
-      _currentFunctionType.namedParameters[declaredElement.name] = type;
-    } else {
-      _currentFunctionType.positionalParameters.add(type);
-    }
-    return type;
-  }
-
-  @override
-  DecoratedType visitTypeAnnotation(TypeAnnotation node) {
-    assert(node != null); // TODO(paulberry)
-    assert(node is NamedType); // TODO(paulberry)
-    var type = node.type;
-    if (type.isVoid) {
-      return DecoratedType(
-          type, NullabilityNode.forTypeAnnotation(node.end, always: true));
-    }
-    assert(
-        type is InterfaceType || type is TypeParameterType); // TODO(paulberry)
-    var typeArguments = const <DecoratedType>[];
-    if (type is InterfaceType && type.typeParameters.isNotEmpty) {
-      if (node is TypeName) {
-        assert(node.typeArguments != null);
-        typeArguments =
-            node.typeArguments.arguments.map((t) => t.accept(this)).toList();
-      } else {
-        assert(false); // TODO(paulberry): is this possible?
-      }
-    }
-    var decoratedType = DecoratedTypeAnnotation(
-        type,
-        NullabilityNode.forTypeAnnotation(node.end,
-            always: node.question != null),
-        node.end,
-        typeArguments: typeArguments);
-    _variables.recordDecoratedTypeAnnotation(_source, node, decoratedType);
-    return decoratedType;
-  }
-
-  @override
-  DecoratedType visitTypeName(TypeName node) => visitTypeAnnotation(node);
-
-  /// Common handling of function and method declarations.
-  void _handleExecutableDeclaration(ExecutableElement declaredElement,
-      TypeAnnotation returnType, FormalParameterList parameters) {
-    var decoratedReturnType = decorateType(returnType);
-    var previousFunctionType = _currentFunctionType;
-    // TODO(paulberry): test that it's correct to use `null` for the nullability
-    // of the function type
-    var functionType = DecoratedType(
-        declaredElement.type, NullabilityNode.never,
-        returnType: decoratedReturnType,
-        positionalParameters: [],
-        namedParameters: {});
-    _currentFunctionType = functionType;
-    try {
-      parameters.accept(this);
-    } finally {
-      _currentFunctionType = previousFunctionType;
-    }
-    _variables.recordDecoratedElementType(declaredElement, functionType);
-  }
-}
-
-/// Repository of constraint variables and decorated types corresponding to the
-/// code being migrated.
-///
-/// This data structure records the results of the first pass of migration
-/// ([ConstraintVariableGatherer], which finds all the variables that need to be
-/// constrained).
-abstract class VariableRecorder {
-  /// Associates decorated type information with the given [element].
-  void recordDecoratedElementType(Element element, DecoratedType type);
-
-  /// Associates decorated type information with the given [type] node.
-  void recordDecoratedTypeAnnotation(
-      Source source, TypeAnnotation node, DecoratedTypeAnnotation type);
-
-  /// Records that [node] is associated with the question of whether the named
-  /// [parameter] should be optional (should not have a `required`
-  /// annotation added to it).
-  void recordPossiblyOptional(
-      Source source, DefaultFormalParameter parameter, NullabilityNode node);
-}
-
-/// Repository of constraint variables and decorated types corresponding to the
-/// code being migrated.
-///
-/// This data structure allows the second pass of migration
-/// ([ConstraintGatherer], which builds all the constraints) to access the
-/// results of the first ([ConstraintVariableGatherer], which finds all the
-/// variables that need to be constrained).
-abstract class VariableRepository {
-  /// Retrieves the [DecoratedType] associated with the static type of the given
-  /// [element].
-  ///
-  /// If [create] is `true`, and no decorated type is found for the given
-  /// element, one is synthesized using [DecoratedType.forElement].
-  DecoratedType decoratedElementType(Element element, {bool create: false});
-
-  /// Records conditional discard information for the given AST node (which is
-  /// an `if` statement or a conditional (`?:`) expression).
-  void recordConditionalDiscard(
-      Source source, AstNode node, ConditionalDiscard conditionalDiscard);
-
-  /// Associates decorated type information with the given [element].
-  ///
-  /// TODO(paulberry): why is this in both [VariableRecorder] and
-  /// [VariableRepository]?
-  void recordDecoratedElementType(Element element, DecoratedType type);
-
-  /// Associates decorated type information with the given expression [node].
-  void recordDecoratedExpressionType(Expression node, DecoratedType type);
-
-  /// Associates a set of nullability checks with the given expression [node].
-  void recordExpressionChecks(
-      Source source, Expression expression, ExpressionChecks checks);
-}
diff --git a/pkg/analysis_server/lib/src/nullability/decorated_type.dart b/pkg/analysis_server/lib/src/nullability/decorated_type.dart
deleted file mode 100644
index c6b3256..0000000
--- a/pkg/analysis_server/lib/src/nullability/decorated_type.dart
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/nullability_node.dart';
-import 'package:analysis_server/src/nullability/transitional_api.dart';
-import 'package:analysis_server/src/nullability/unit_propagation.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceEdit;
-
-/// Representation of a type in the code to be migrated.  In addition to
-/// tracking the (unmigrated) [DartType], we track the [ConstraintVariable]s
-/// indicating whether the type, and the types that compose it, are nullable.
-class DecoratedType {
-  final DartType type;
-
-  final NullabilityNode node;
-
-  /// If `this` is a function type, the [DecoratedType] of its return type.
-  final DecoratedType returnType;
-
-  /// If `this` is a function type, the [DecoratedType] of each of its
-  /// positional parameters (including both required and optional positional
-  /// parameters).
-  final List<DecoratedType> positionalParameters;
-
-  /// If `this` is a function type, the [DecoratedType] of each of its named
-  /// parameters.
-  final Map<String, DecoratedType> namedParameters;
-
-  /// If `this` is a parameterized type, the [DecoratedType] of each of its
-  /// type parameters.
-  ///
-  /// TODO(paulberry): how should we handle generic typedefs?
-  final List<DecoratedType> typeArguments;
-
-  DecoratedType(this.type, this.node,
-      {this.returnType,
-      this.positionalParameters = const [],
-      this.namedParameters = const {},
-      this.typeArguments = const []}) {
-    assert(node != null);
-    // The type system doesn't have a non-nullable version of `dynamic`.  So if
-    // the type is `dynamic`, verify that `nullable` is `always`.
-    assert(!type.isDynamic || node.isAlwaysNullable);
-  }
-
-  /// Creates a [DecoratedType] corresponding to the given [element], which is
-  /// presumed to have come from code that is already migrated.
-  factory DecoratedType.forElement(Element element) {
-    DecoratedType decorate(DartType type) {
-      assert((type as TypeImpl).nullabilitySuffix ==
-          NullabilitySuffix.star); // TODO(paulberry)
-      if (type is FunctionType) {
-        var decoratedType = DecoratedType(type, NullabilityNode.never,
-            returnType: decorate(type.returnType), positionalParameters: []);
-        for (var parameter in type.parameters) {
-          assert(parameter.isPositional); // TODO(paulberry)
-          decoratedType.positionalParameters.add(decorate(parameter.type));
-        }
-        return decoratedType;
-      } else if (type is InterfaceType) {
-        assert(type.typeParameters.isEmpty); // TODO(paulberry)
-        return DecoratedType(type, NullabilityNode.never);
-      } else {
-        throw type.runtimeType; // TODO(paulberry)
-      }
-    }
-
-    DecoratedType decoratedType;
-    if (element is MethodElement) {
-      decoratedType = decorate(element.type);
-    } else {
-      throw element.runtimeType; // TODO(paulberry)
-    }
-    return decoratedType;
-  }
-
-  /// Apply the given [substitution] to this type.
-  ///
-  /// [undecoratedResult] is the result of the substitution, as determined by
-  /// the normal type system.
-  DecoratedType substitute(
-      Constraints constraints,
-      Map<TypeParameterElement, DecoratedType> substitution,
-      DartType undecoratedResult) {
-    if (substitution.isEmpty) return this;
-    return _substitute(constraints, substitution, undecoratedResult);
-  }
-
-  @override
-  String toString() {
-    var trailing = node.debugSuffix;
-    var type = this.type;
-    if (type is TypeParameterType || type is VoidType) {
-      return '$type$trailing';
-    } else if (type is InterfaceType) {
-      var name = type.element.name;
-      var args = '';
-      if (type.typeArguments.isNotEmpty) {
-        args = '<${type.typeArguments.join(', ')}>';
-      }
-      return '$name$args$trailing';
-    } else if (type is FunctionType) {
-      assert(type.typeFormals.isEmpty); // TODO(paulberry)
-      assert(type.namedParameterTypes.isEmpty &&
-          namedParameters.isEmpty); // TODO(paulberry)
-      var args = positionalParameters.map((p) => p.toString()).join(', ');
-      return '$returnType Function($args)$trailing';
-    } else if (type is DynamicTypeImpl) {
-      return 'dynamic';
-    } else {
-      throw '$type'; // TODO(paulberry)
-    }
-  }
-
-  /// Internal implementation of [_substitute], used as a recursion target.
-  DecoratedType _substitute(
-      Constraints constraints,
-      Map<TypeParameterElement, DecoratedType> substitution,
-      DartType undecoratedResult) {
-    var type = this.type;
-    if (type is FunctionType && undecoratedResult is FunctionType) {
-      assert(type.typeFormals.isEmpty); // TODO(paulberry)
-      var newPositionalParameters = <DecoratedType>[];
-      for (int i = 0; i < positionalParameters.length; i++) {
-        var numRequiredParameters =
-            undecoratedResult.normalParameterTypes.length;
-        var undecoratedParameterType = i < numRequiredParameters
-            ? undecoratedResult.normalParameterTypes[i]
-            : undecoratedResult
-                .optionalParameterTypes[i - numRequiredParameters];
-        newPositionalParameters.add(positionalParameters[i]
-            ._substitute(constraints, substitution, undecoratedParameterType));
-      }
-      return DecoratedType(undecoratedResult, node,
-          returnType: returnType._substitute(
-              constraints, substitution, undecoratedResult.returnType),
-          positionalParameters: newPositionalParameters);
-    } else if (type is TypeParameterType) {
-      var inner = substitution[type.element];
-      return DecoratedType(undecoratedResult,
-          NullabilityNode.forSubstitution(constraints, inner?.node, node));
-    } else if (type is VoidType) {
-      return this;
-    }
-    throw '$type.substitute($substitution)'; // TODO(paulberry)
-  }
-}
-
-/// A [DecoratedType] based on a type annotation appearing explicitly in the
-/// source code.
-///
-/// This class implements [PotentialModification] because it knows how to update
-/// the source code to reflect its nullability.
-class DecoratedTypeAnnotation extends DecoratedType
-    implements PotentialModification {
-  final int _offset;
-
-  DecoratedTypeAnnotation(
-      DartType type, NullabilityNode nullabilityNode, this._offset,
-      {List<DecoratedType> typeArguments = const []})
-      : super(type, nullabilityNode, typeArguments: typeArguments);
-
-  @override
-  bool get isEmpty => node.isAlwaysNullable || !node.isNullable;
-
-  @override
-  Iterable<SourceEdit> get modifications =>
-      isEmpty ? [] : [SourceEdit(_offset, 0, '?')];
-}
-
-/// Type of a [ConstraintVariable] representing the fact that a type is intended
-/// to be non-null.
-class NonNullIntent extends ConstraintVariable {
-  final int _offset;
-
-  NonNullIntent(this._offset);
-
-  @override
-  toString() => 'nonNullIntent($_offset)';
-}
-
-/// Type of a [ConstraintVariable] representing the fact that a type is
-/// nullable.
-class TypeIsNullable extends ConstraintVariable {
-  final int _offset;
-
-  TypeIsNullable(this._offset);
-
-  @override
-  toString() => 'nullable($_offset)';
-}
diff --git a/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart b/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart
deleted file mode 100644
index 59164ce..0000000
--- a/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/constraint_variable_gatherer.dart';
-import 'package:analysis_server/src/nullability/decorated_type.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type_system.dart';
-import 'package:analyzer/src/dart/resolver/flow_analysis.dart';
-
-/// [TypeOperations] that works with [DecoratedType]s.
-class DecoratedTypeOperations implements TypeOperations<DecoratedType> {
-  final TypeSystem _typeSystem;
-  final VariableRepository _variableRepository;
-
-  DecoratedTypeOperations(this._typeSystem, this._variableRepository);
-
-  @override
-  DecoratedType elementType(VariableElement element) {
-    return _variableRepository.decoratedElementType(element);
-  }
-
-  @override
-  bool isSubtypeOf(DecoratedType leftType, DecoratedType rightType) {
-    return _typeSystem.isSubtypeOf(leftType.type, rightType.type);
-  }
-}
diff --git a/pkg/analysis_server/lib/src/nullability/expression_checks.dart b/pkg/analysis_server/lib/src/nullability/expression_checks.dart
deleted file mode 100644
index 14f47db..0000000
--- a/pkg/analysis_server/lib/src/nullability/expression_checks.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/transitional_api.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
-
-/// Container for information gathered during nullability migration about the
-/// set of runtime checks that might need to be performed on the value of an
-/// expression.
-///
-/// TODO(paulberry): the only check we support now is [nullCheck], which checks
-/// that the expression is not null.  We need to add other checks, e.g. to check
-/// that a List<int?> is actually a List<int>.
-class ExpressionChecks extends PotentialModification {
-  /// Constraint variable whose value will be `true` if this expression requires
-  /// a null check.
-  final CheckExpression nullCheck;
-
-  ExpressionChecks(this.nullCheck);
-
-  @override
-  bool get isEmpty => !nullCheck.value;
-
-  @override
-  Iterable<SourceEdit> get modifications =>
-      nullCheck.value ? [SourceEdit(nullCheck.offset, 0, '!')] : [];
-}
diff --git a/pkg/analysis_server/lib/src/nullability/nullability_node.dart b/pkg/analysis_server/lib/src/nullability/nullability_node.dart
deleted file mode 100644
index fd7d82b..0000000
--- a/pkg/analysis_server/lib/src/nullability/nullability_node.dart
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/decorated_type.dart';
-import 'package:analysis_server/src/nullability/transitional_api.dart';
-import 'package:analysis_server/src/nullability/unit_propagation.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:meta/meta.dart';
-
-/// Representation of a single node in the nullability inference graph.
-///
-/// Initially, this is just a wrapper over constraint variables, and the
-/// nullability inference graph is encoded into the wrapped constraint
-/// variables.  Over time this will be replaced by a first class representation
-/// of the nullability inference graph.
-class NullabilityNode {
-  /// [NullabilityNode] used for types that are known a priori to be nullable
-  /// (e.g. the type of the `null` literal).
-  static final always = NullabilityNode._(ConstraintVariable.always);
-
-  /// [NullabilityNode] used for types that are known a priori to be
-  /// non-nullable (e.g. the type of an integer literal).
-  static final never = NullabilityNode._(null);
-
-  /// [ConstraintVariable] whose value will be set to `true` if this type needs
-  /// to be nullable.
-  ///
-  /// If `null`, that means that an external constraint (outside the code being
-  /// migrated) forces this type to be non-nullable.
-  final ConstraintVariable nullable;
-
-  ConstraintVariable _nonNullIntent;
-
-  bool _isPossiblyOptional = false;
-
-  /// Creates a [NullabilityNode] representing the nullability of a conditional
-  /// expression which is nullable iff both [a] and [b] are nullable.
-  ///
-  /// The constraint variable contained in the new node is created using the
-  /// [joinNullabilities] callback.  TODO(paulberry): this should become
-  /// unnecessary once constraint solving is performed directly using
-  /// [NullabilityNode] objects.
-  NullabilityNode.forConditionalexpression(
-      ConditionalExpression conditionalExpression,
-      NullabilityNode a,
-      NullabilityNode b,
-      ConstraintVariable Function(
-              ConditionalExpression, ConstraintVariable, ConstraintVariable)
-          joinNullabilities)
-      : this._(
-            joinNullabilities(conditionalExpression, a.nullable, b.nullable));
-
-  /// Creates a [NullabilityNode] representing the nullability of a variable
-  /// whose type is `dynamic` due to type inference.
-  ///
-  /// TODO(paulberry): this should go away; we should decorate the actual
-  /// inferred type rather than assuming `dynamic`.
-  NullabilityNode.forInferredDynamicType() : this._(ConstraintVariable.always);
-
-  /// Creates a [NullabilityNode] representing the nullability of a type
-  /// substitution where [outerNode] is the nullability node for the type
-  /// variable being eliminated by the substitution, and [innerNode] is the
-  /// nullability node for the type being substituted in its place.
-  ///
-  /// [innerNode] may be `null`.  TODO(paulberry): when?
-  ///
-  /// Additional constraints are recorded in [constraints] as necessary to make
-  /// the new nullability node behave consistently with the old nodes.
-  /// TODO(paulberry): this should become unnecessary once constraint solving is
-  /// performed directly using [NullabilityNode] objects.
-  NullabilityNode.forSubstitution(Constraints constraints,
-      NullabilityNode innerNode, NullabilityNode outerNode)
-      : this._(ConstraintVariable.or(
-            constraints, innerNode?.nullable, outerNode.nullable));
-
-  /// Creates a [NullabilityNode] representing the nullability of a type
-  /// annotation appearing explicitly in the user's program.
-  NullabilityNode.forTypeAnnotation(int endOffset, {@required bool always})
-      : this._(always ? ConstraintVariable.always : TypeIsNullable(endOffset));
-
-  NullabilityNode._(this.nullable);
-
-  /// Gets a string that can be appended to a type name during debugging to help
-  /// annotate the nullability of that type.
-  String get debugSuffix => nullable == null ? '' : '?($nullable)';
-
-  /// Indicates whether this node is always nullable, by construction.
-  bool get isAlwaysNullable => identical(nullable, ConstraintVariable.always);
-
-  /// After constraint solving, this getter can be used to query whether the
-  /// type associated with this node should be considered nullable.
-  bool get isNullable => nullable.value;
-
-  /// Indicates whether this node is associated with a named parameter for which
-  /// nullability migration needs to decide whether it is optional or required.
-  bool get isPossiblyOptional => _isPossiblyOptional;
-
-  /// [ConstraintVariable] whose value will be set to `true` if the usage of
-  /// this type suggests that it is intended to be non-null (because of the
-  /// presence of a statement or expression that would unconditionally lead to
-  /// an exception being thrown in the case of a `null` value at runtime).
-  ConstraintVariable get nonNullIntent => _nonNullIntent;
-
-  /// Records the fact that an invocation was made to a function with named
-  /// parameters, and the named parameter associated with this node was not
-  /// supplied.
-  void recordNamedParameterNotSupplied(
-      Constraints constraints, List<NullabilityNode> guards) {
-    if (isPossiblyOptional) {
-      _recordConstraints(constraints, guards, const [], nullable);
-    }
-  }
-
-  void recordNonNullIntent(
-      Constraints constraints, List<NullabilityNode> guards) {
-    _recordConstraints(constraints, guards, const [], nonNullIntent);
-  }
-
-  /// Tracks that the possibility that this nullability node might demonstrate
-  /// non-null intent, based on the fact that it corresponds to a formal
-  /// parameter declaration at location [offset].
-  ///
-  /// TODO(paulberry): consider eliminating this method altogether, and simply
-  /// allowing all nullability nodes to track non-null intent if necessary.
-  void trackNonNullIntent(int offset) {
-    assert(_nonNullIntent == null);
-    _nonNullIntent = NonNullIntent(offset);
-  }
-
-  /// Tracks the possibility that this node is associated with a named parameter
-  /// for which nullability migration needs to decide whether it is optional or
-  /// required.
-  void trackPossiblyOptional() {
-    _isPossiblyOptional = true;
-  }
-
-  /// Connect the nullability nodes [sourceNode] and [destinationNode]
-  /// appopriately to account for an assignment in the source code being
-  /// analyzed.  Any constraints generated are recorded in [constraints].
-  ///
-  /// If [checkNotNull] is non-null, then it tracks the expression that may
-  /// require null-checking.
-  ///
-  /// [inConditionalControlFlow] indicates whether the assignment being analyzed
-  /// is reachable conditionally or unconditionally from the entry point of the
-  /// function; this affects how non-null intent is back-propagated.
-  static void recordAssignment(
-      NullabilityNode sourceNode,
-      NullabilityNode destinationNode,
-      CheckExpression checkNotNull,
-      List<NullabilityNode> guards,
-      Constraints constraints,
-      bool inConditionalControlFlow) {
-    var additionalConditions = <ConstraintVariable>[];
-    if (sourceNode.nullable != null) {
-      additionalConditions.add(sourceNode.nullable);
-      var destinationNonNullIntent = destinationNode.nonNullIntent;
-      // nullable_src => nullable_dst | check_expr
-      _recordConstraints(
-          constraints,
-          guards,
-          additionalConditions,
-          ConstraintVariable.or(
-              constraints, destinationNode.nullable, checkNotNull));
-      if (checkNotNull != null) {
-        // nullable_src & nonNullIntent_dst => check_expr
-        if (destinationNonNullIntent != null) {
-          additionalConditions.add(destinationNonNullIntent);
-          _recordConstraints(
-              constraints, guards, additionalConditions, checkNotNull);
-        }
-      }
-      additionalConditions.clear();
-      var sourceNonNullIntent = sourceNode.nonNullIntent;
-      if (!inConditionalControlFlow && sourceNonNullIntent != null) {
-        if (destinationNode.nullable == null) {
-          // The destination type can never be nullable so this demonstrates
-          // non-null intent.
-          _recordConstraints(
-              constraints, guards, additionalConditions, sourceNonNullIntent);
-        } else if (destinationNonNullIntent != null) {
-          // Propagate non-null intent from the destination to the source.
-          additionalConditions.add(destinationNonNullIntent);
-          _recordConstraints(
-              constraints, guards, additionalConditions, sourceNonNullIntent);
-        }
-      }
-    }
-  }
-
-  static void _recordConstraints(
-      Constraints constraints,
-      List<NullabilityNode> guards,
-      List<ConstraintVariable> additionalConditions,
-      ConstraintVariable consequence) {
-    var conditions = guards.map((node) => node.nullable).toList();
-    conditions.addAll(additionalConditions);
-    constraints.record(conditions, consequence);
-  }
-}
diff --git a/pkg/analysis_server/lib/src/nullability/provisional_api.dart b/pkg/analysis_server/lib/src/nullability/provisional_api.dart
deleted file mode 100644
index 99080c9..0000000
--- a/pkg/analysis_server/lib/src/nullability/provisional_api.dart
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/decorated_type.dart'
-    as analyzer;
-import 'package:analysis_server/src/nullability/expression_checks.dart'
-    as analyzer;
-import 'package:analysis_server/src/nullability/transitional_api.dart'
-    as analyzer;
-import 'package:analysis_server/src/protocol_server.dart';
-import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:meta/meta.dart';
-
-export 'package:analysis_server/src/nullability/transitional_api.dart'
-    show NamedNoDefaultParameterHeuristic, NullabilityMigrationAssumptions;
-
-/// Kinds of fixes that might be performed by nullability migration.
-class NullabilityFixKind {
-  /// An import needs to be added.
-  static const addImport =
-      const NullabilityFixKind._(appliedMessage: 'Add an import');
-
-  /// A formal parameter needs to have a required annotation added.
-  static const addRequired =
-      const NullabilityFixKind._(appliedMessage: 'Add a required annotation');
-
-  /// An expression's value needs to be null-checked.
-  static const checkExpression = const NullabilityFixKind._(
-    appliedMessage: 'Added a null check to an expression',
-  );
-
-  /// An explicit type mentioned in the source program needs to be made
-  /// nullable.
-  static const makeTypeNullable = const NullabilityFixKind._(
-    appliedMessage: 'Changed a type to be nullable',
-  );
-
-  /// An if-test or conditional expression needs to have its "then" branch
-  /// discarded.
-  static const discardThen = const NullabilityFixKind._(
-    appliedMessage: 'Discarded an unreachable conditional then branch',
-  );
-
-  /// An if-test or conditional expression needs to have its "else" branch
-  /// discarded.
-  static const discardElse = const NullabilityFixKind._(
-    appliedMessage: 'Discarded an unreachable conditional else branch',
-  );
-
-  /// A message used by dartfix to indicate a fix has been applied.
-  final String appliedMessage;
-
-  const NullabilityFixKind._({@required this.appliedMessage});
-}
-
-/// Provisional API for DartFix to perform nullability migration.
-///
-/// Usage: pass each input source file to [prepareInput].  Then pass each input
-/// source file to [processInput].  Then call [finish] to obtain the
-/// modifications that need to be made to each source file.
-///
-/// TODO(paulberry): figure out whether this API is what we want, and figure out
-/// what file/folder it belongs in.
-class NullabilityMigration {
-  final analyzer.NullabilityMigration _analyzerMigration;
-  final NullabilityMigrationListener listener;
-
-  /// Prepares to perform nullability migration.
-  ///
-  /// If [permissive] is `true`, exception handling logic will try to proceed
-  /// as far as possible even though the migration algorithm is not yet
-  /// complete.  TODO(paulberry): remove this mode once the migration algorithm
-  /// is fully implemented.
-  NullabilityMigration(this.listener,
-      {bool permissive: false,
-      analyzer.NullabilityMigrationAssumptions assumptions:
-          const analyzer.NullabilityMigrationAssumptions()})
-      : _analyzerMigration = analyzer.NullabilityMigration(
-            permissive: permissive, assumptions: assumptions);
-
-  void finish() {
-    for (var entry in _analyzerMigration.finish().entries) {
-      var source = entry.key;
-      for (var potentialModification in entry.value) {
-        var fix = _SingleNullabilityFix(source, potentialModification);
-        listener.addFix(fix);
-        for (var edit in potentialModification.modifications) {
-          listener.addEdit(fix, edit);
-        }
-      }
-    }
-  }
-
-  void prepareInput(ResolvedUnitResult result) {
-    _analyzerMigration.prepareInput(result.unit);
-  }
-
-  void processInput(ResolvedUnitResult result) {
-    _analyzerMigration.processInput(result.unit, result.typeProvider);
-  }
-}
-
-/// [NullabilityMigrationListener] is used by [NullabilityMigration]
-/// to communicate source changes or "fixes" to the client.
-abstract class NullabilityMigrationListener {
-  /// [addEdit] is called once for each source edit, in the order in which they
-  /// appear in the source file.
-  void addEdit(SingleNullabilityFix fix, SourceEdit edit);
-
-  /// [addFix] is called once for each source change.
-  void addFix(SingleNullabilityFix fix);
-}
-
-/// Representation of a single conceptual change made by the nullability
-/// migration algorithm.  This change might require multiple source edits to
-/// achieve.
-abstract class SingleNullabilityFix {
-  /// What kind of fix this is.
-  NullabilityFixKind get kind;
-
-  /// Location of the change, for reporting to the user.
-  Location get location;
-
-  /// File to change.
-  Source get source;
-}
-
-/// Implementation of [SingleNullabilityFix] used internally by
-/// [NullabilityMigration].
-class _SingleNullabilityFix extends SingleNullabilityFix {
-  @override
-  final Source source;
-
-  @override
-  final NullabilityFixKind kind;
-
-  factory _SingleNullabilityFix(
-      Source source, analyzer.PotentialModification potentialModification) {
-    // TODO(paulberry): once everything is migrated into the analysis server,
-    // the migration engine can just create SingleNullabilityFix objects
-    // directly and set their kind appropriately; we won't need to translate the
-    // kinds using a bunch of `is` checks.
-    NullabilityFixKind kind;
-    if (potentialModification is analyzer.ExpressionChecks) {
-      kind = NullabilityFixKind.checkExpression;
-    } else if (potentialModification is analyzer.DecoratedTypeAnnotation) {
-      kind = NullabilityFixKind.makeTypeNullable;
-    } else if (potentialModification is analyzer.ConditionalModification) {
-      kind = potentialModification.discard.keepFalse
-          ? NullabilityFixKind.discardThen
-          : NullabilityFixKind.discardElse;
-    } else if (potentialModification is analyzer.PotentiallyAddImport) {
-      kind = NullabilityFixKind.addImport;
-    } else if (potentialModification is analyzer.PotentiallyAddRequired) {
-      kind = NullabilityFixKind.addRequired;
-    } else {
-      throw new UnimplementedError('TODO(paulberry)');
-    }
-    return _SingleNullabilityFix._(source, kind);
-  }
-
-  _SingleNullabilityFix._(this.source, this.kind);
-
-  /// TODO(paulberry): do something better
-  Location get location => null;
-}
diff --git a/pkg/analysis_server/lib/src/nullability/transitional_api.dart b/pkg/analysis_server/lib/src/nullability/transitional_api.dart
deleted file mode 100644
index 7a1b505..0000000
--- a/pkg/analysis_server/lib/src/nullability/transitional_api.dart
+++ /dev/null
@@ -1,382 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/conditional_discard.dart';
-import 'package:analysis_server/src/nullability/constraint_gatherer.dart';
-import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
-import 'package:analysis_server/src/nullability/decorated_type.dart';
-import 'package:analysis_server/src/nullability/expression_checks.dart';
-import 'package:analysis_server/src/nullability/nullability_node.dart';
-import 'package:analysis_server/src/nullability/unit_propagation.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceEdit;
-
-/// Type of a [ConstraintVariable] representing the addition of a null check.
-class CheckExpression extends ConstraintVariable {
-  final int offset;
-
-  CheckExpression(Expression expression) : offset = expression.end;
-
-  @override
-  toString() => 'checkNotNull($offset)';
-}
-
-/// Records information about how a conditional expression or statement might
-/// need to be modified.
-class ConditionalModification extends PotentialModification {
-  final int offset;
-
-  final int end;
-
-  final bool isStatement;
-
-  final ConditionalDiscard discard;
-
-  final _KeepNode condition;
-
-  final _KeepNode thenStatement;
-
-  final _KeepNode elseStatement;
-
-  factory ConditionalModification(AstNode node, ConditionalDiscard discard) {
-    if (node is IfStatement) {
-      return ConditionalModification._(
-          node.offset,
-          node.end,
-          node is Statement,
-          discard,
-          _KeepNode(node.condition),
-          _KeepNode(node.thenStatement),
-          _KeepNode(node.elseStatement));
-    } else {
-      throw new UnimplementedError('TODO(paulberry)');
-    }
-  }
-
-  ConditionalModification._(this.offset, this.end, this.isStatement,
-      this.discard, this.condition, this.thenStatement, this.elseStatement);
-
-  @override
-  bool get isEmpty => discard.keepTrue && discard.keepFalse;
-
-  @override
-  Iterable<SourceEdit> get modifications {
-    if (isEmpty) return const [];
-    // TODO(paulberry): move the following logic into DartEditBuilder (see
-    // dartbug.com/35872).
-    var result = <SourceEdit>[];
-    var keepNodes = <_KeepNode>[];
-    if (!discard.pureCondition) {
-      keepNodes.add(condition); // TODO(paulberry): test
-    }
-    if (discard.keepTrue) {
-      keepNodes.add(thenStatement); // TODO(paulberry): test
-    }
-    if (discard.keepFalse) {
-      keepNodes.add(elseStatement); // TODO(paulberry): test
-    }
-    // TODO(paulberry): test thoroughly
-    for (int i = 0; i < keepNodes.length; i++) {
-      var keepNode = keepNodes[i];
-      if (i == 0 && keepNode.offset != offset) {
-        result.add(SourceEdit(offset, 0, '/* '));
-      }
-      if (i != 0 || keepNode.offset != offset) {
-        result.add(SourceEdit(keepNode.offset, 0, '*/ '));
-      }
-      if (i != keepNodes.length - 1 || keepNode.end != end) {
-        result.add(SourceEdit(keepNode.end, 0,
-            keepNode.isExpression && isStatement ? '; /*' : ' /*'));
-      }
-      if (i == keepNodes.length - 1 && keepNode.end != end) {
-        result.add(SourceEdit(end, 0, ' */'));
-      }
-    }
-    return result;
-  }
-}
-
-/// Enum encapsulating the various options proposed at
-/// https://github.com/dart-lang/language/issues/156#issuecomment-460525075
-enum DefaultParameterHandling {
-  /// Option 2: Add required named parameters
-  ///
-  /// - `{int x}` implicitly means `x` is required
-  ///   - required-ness goes into the function type:
-  ///     `int Function({required int x})`
-  /// - `{required int? x}` is allowed
-  ///   - means that something must be passed
-  ///   - passing null is allowed
-  /// - `{int x = 3}` is allowed
-  ///   - `x` is optional
-  ///   - passing null to it is an error
-  ///   - passing nothing to it results in it getting the default value
-  /// - `[int x]` is an error
-  /// - `[int x = 3]` is allowed
-  option2_addRequiredNamedParameters,
-}
-
-/// Enum representing the possible heuristics for handling named parameters with
-/// no default value.
-enum NamedNoDefaultParameterHeuristic {
-  /// Assume that the parameter should be considered nullable, unless the user
-  /// has explicitly marked it as `@required`.
-  assumeNullable,
-
-  /// Assume that the parameter should be considered required, unless the user
-  /// has explicitly marked it as nullable.
-  assumeRequired,
-}
-
-/// Transitional migration API.
-///
-/// Usage: pass each input source file to [prepareInput].  Then pass each input
-/// source file to [processInput].  Then call [finish] to obtain the
-/// modifications that need to be made to each source file.
-///
-/// TODO(paulberry): this implementation keeps a lot of CompilationUnit objects
-/// around.  Can we do better?
-class NullabilityMigration {
-  final bool _permissive;
-
-  final NullabilityMigrationAssumptions assumptions;
-
-  final _variables = Variables();
-
-  final _constraints = Solver();
-
-  /// Prepares to perform nullability migration.
-  ///
-  /// If [permissive] is `true`, exception handling logic will try to proceed
-  /// as far as possible even though the migration algorithm is not yet
-  /// complete.  TODO(paulberry): remove this mode once the migration algorithm
-  /// is fully implemented.
-  NullabilityMigration(
-      {bool permissive: false,
-      this.assumptions: const NullabilityMigrationAssumptions()})
-      : _permissive = permissive;
-
-  Map<Source, List<PotentialModification>> finish() {
-    _constraints.applyHeuristics();
-    return _variables.getPotentialModifications();
-  }
-
-  void prepareInput(CompilationUnit unit) {
-    unit.accept(ConstraintVariableGatherer(
-        _variables, unit.declaredElement.source, _permissive, assumptions));
-  }
-
-  void processInput(CompilationUnit unit, TypeProvider typeProvider) {
-    unit.accept(ConstraintGatherer(typeProvider, _variables, _constraints,
-        unit.declaredElement.source, _permissive, assumptions));
-  }
-}
-
-/// Assumptions affecting the behavior of the nullability migration tool.
-///
-/// These options generally reflect design decisions that have not yet been
-/// made.  They don't reflect behavioral differences we would want to expose to
-/// the user.
-///
-/// TODO(paulberry): hardcode these assumptions once decisions have been made.
-class NullabilityMigrationAssumptions {
-  /// Handling of default parameters.
-  final DefaultParameterHandling defaultParameterHandling;
-
-  /// Heuristic for handling named parameters with no default value.
-  final NamedNoDefaultParameterHeuristic namedNoDefaultParameterHeuristic;
-
-  const NullabilityMigrationAssumptions(
-      {this.defaultParameterHandling:
-          DefaultParameterHandling.option2_addRequiredNamedParameters,
-      this.namedNoDefaultParameterHeuristic:
-          NamedNoDefaultParameterHeuristic.assumeNullable});
-}
-
-/// Records information about the possible addition of an import
-/// to the source code.
-class PotentiallyAddImport extends PotentialModification {
-  final _usages = <PotentialModification>[];
-
-  final int _offset;
-  final String _importPath;
-
-  PotentiallyAddImport(
-      AstNode beforeNode, this._importPath, PotentialModification usage)
-      : _offset = beforeNode.offset {
-    _usages.add(usage);
-  }
-
-  get importPath => _importPath;
-
-  @override
-  bool get isEmpty {
-    for (PotentialModification usage in _usages) {
-      if (!usage.isEmpty) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  // TODO(danrubel): change all of dartfix NNBD to use DartChangeBuilder
-  @override
-  Iterable<SourceEdit> get modifications =>
-      isEmpty ? const [] : [SourceEdit(_offset, 0, "import '$_importPath';\n")];
-
-  void addUsage(PotentialModification usage) {
-    _usages.add(usage);
-  }
-}
-
-/// Records information about the possible addition of a `@required` annotation
-/// to the source code.
-class PotentiallyAddRequired extends PotentialModification {
-  final NullabilityNode _node;
-
-  final int _offset;
-
-  PotentiallyAddRequired(DefaultFormalParameter parameter, this._node)
-      : _offset = parameter.offset;
-
-  @override
-  bool get isEmpty => _node.isNullable;
-
-  @override
-  Iterable<SourceEdit> get modifications =>
-      isEmpty ? const [] : [SourceEdit(_offset, 0, '@required ')];
-}
-
-/// Interface used by data structures representing potential modifications to
-/// the code being migrated.
-abstract class PotentialModification {
-  bool get isEmpty;
-
-  /// Gets the individual migrations that need to be done, considering the
-  /// solution to the constraint equations.
-  Iterable<SourceEdit> get modifications;
-}
-
-class Variables implements VariableRecorder, VariableRepository {
-  final _decoratedElementTypes = <Element, DecoratedType>{};
-
-  final _potentialModifications = <Source, List<PotentialModification>>{};
-
-  @override
-  DecoratedType decoratedElementType(Element element, {bool create: false}) =>
-      _decoratedElementTypes[element] ??= create
-          ? DecoratedType.forElement(element)
-          : throw StateError('No element found');
-
-  Map<Source, List<PotentialModification>> getPotentialModifications() =>
-      _potentialModifications;
-
-  @override
-  void recordConditionalDiscard(
-      Source source, AstNode node, ConditionalDiscard conditionalDiscard) {
-    _addPotentialModification(
-        source, ConditionalModification(node, conditionalDiscard));
-  }
-
-  void recordDecoratedElementType(Element element, DecoratedType type) {
-    _decoratedElementTypes[element] = type;
-  }
-
-  void recordDecoratedExpressionType(Expression node, DecoratedType type) {}
-
-  void recordDecoratedTypeAnnotation(
-      Source source, TypeAnnotation node, DecoratedTypeAnnotation type) {
-    _addPotentialModification(source, type);
-  }
-
-  @override
-  void recordExpressionChecks(
-      Source source, Expression expression, ExpressionChecks checks) {
-    _addPotentialModification(source, checks);
-  }
-
-  @override
-  void recordPossiblyOptional(
-      Source source, DefaultFormalParameter parameter, NullabilityNode node) {
-    var modification = PotentiallyAddRequired(parameter, node);
-    _addPotentialModification(source, modification);
-    _addPotentialImport(
-        source, parameter, modification, 'package:meta/meta.dart');
-  }
-
-  void _addPotentialImport(Source source, AstNode node,
-      PotentialModification usage, String importPath) {
-    // Get the compilation unit - assume not null
-    while (node is! CompilationUnit) {
-      node = node.parent;
-    }
-    var unit = node as CompilationUnit;
-
-    // Find an existing import
-    for (var directive in unit.directives) {
-      if (directive is ImportDirective) {
-        if (directive.uri.stringValue == importPath) {
-          return;
-        }
-      }
-    }
-
-    // Add the usage to an existing modification if possible
-    for (var modification in (_potentialModifications[source] ??= [])) {
-      if (modification is PotentiallyAddImport) {
-        if (modification.importPath == importPath) {
-          modification.addUsage(usage);
-          return;
-        }
-      }
-    }
-
-    // Create a new import modification
-    AstNode beforeNode;
-    for (var directive in unit.directives) {
-      if (directive is ImportDirective || directive is ExportDirective) {
-        beforeNode = directive;
-        break;
-      }
-    }
-    if (beforeNode == null) {
-      for (var declaration in unit.declarations) {
-        beforeNode = declaration;
-        break;
-      }
-    }
-    _addPotentialModification(
-        source, PotentiallyAddImport(beforeNode, importPath, usage));
-  }
-
-  void _addPotentialModification(
-      Source source, PotentialModification potentialModification) {
-    (_potentialModifications[source] ??= []).add(potentialModification);
-  }
-}
-
-/// Helper object used by [ConditionalModification] to keep track of AST nodes
-/// within the conditional expression.
-class _KeepNode {
-  final int offset;
-
-  final int end;
-
-  final bool isExpression;
-
-  factory _KeepNode(AstNode node) {
-    int offset = node.offset;
-    int end = node.end;
-    if (node is Block && node.statements.isNotEmpty) {
-      offset = node.statements.beginToken.offset;
-      end = node.statements.endToken.end;
-    }
-    return _KeepNode._(offset, end, node is Expression);
-  }
-
-  _KeepNode._(this.offset, this.end, this.isExpression);
-}
diff --git a/pkg/analysis_server/lib/src/nullability/unit_propagation.dart b/pkg/analysis_server/lib/src/nullability/unit_propagation.dart
deleted file mode 100644
index b587e33..0000000
--- a/pkg/analysis_server/lib/src/nullability/unit_propagation.dart
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright (c) 2019, 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.
-
-/// Repository of constraints corresponding to the code being migrated.
-///
-/// This data structure carries information from the second pass of migration
-/// ([ConstraintGatherer]) to the third (which creates individual code
-/// modifications from each constraint).
-abstract class Constraints {
-  /// Records a new constraint equation.
-  void record(
-      Iterable<ConstraintVariable> conditions, ConstraintVariable consequence);
-}
-
-/// Representation of a single boolean variable in the constraint solver.
-class ConstraintVariable {
-  /// A special boolean variable whose value is known to be `true`.
-  static final ConstraintVariable always = _Always();
-
-  /// A list of all constraints containing this variable on their left hand side
-  /// that may not have been satisfied yet.
-  final _dependencies = <_Clause>[];
-
-  /// The value assigned to this constraint variable by the solution currently
-  /// being computed.
-  bool _value = false;
-
-  /// If this variable represents a disjunction ("or") of several other
-  /// variables, the variables in the disjunction.  Otherwise a singleton list
-  /// containing `this`.
-  final List<ConstraintVariable> _disjunctionParts;
-
-  ConstraintVariable() : _disjunctionParts = List.filled(1, null) {
-    _disjunctionParts[0] = this;
-  }
-
-  /// Creates a [ConstraintVariable] representing a disjunction ("or") of
-  /// several other variables.
-  ///
-  /// Additional constraints will be recorded in [constraints] to ensure that
-  /// the solution will be consistent.
-  factory ConstraintVariable.or(
-      Constraints constraints, ConstraintVariable a, ConstraintVariable b) {
-    if (a == null) return b;
-    if (b == null) return a;
-    var parts = a.disjunctionParts.toList();
-    parts.addAll(b.disjunctionParts);
-    assert(parts.length > 1);
-    var result = ConstraintVariable._(parts);
-    constraints.record([a], result);
-    constraints.record([b], result);
-    return result;
-  }
-
-  ConstraintVariable._(this._disjunctionParts);
-
-  /// If this variable represents a disjunction ("or") of several other
-  /// variables, the variables in the disjunction.  Otherwise a singleton list
-  /// containing `this`.
-  Iterable<ConstraintVariable> get disjunctionParts => _disjunctionParts;
-
-  /// Indicates whether this variable represents a disjunction ("or") of several
-  /// other variables.
-  bool get isDisjunction => _disjunctionParts.length > 1;
-
-  /// The value assigned to this constraint variable by the solution currently
-  /// being computed.
-  bool get value => _value;
-
-  @override
-  String toString() =>
-      isDisjunction ? '(${_disjunctionParts.join(' | ')})' : super.toString();
-}
-
-/// The core of the migration tool's constraint solver.  This class implements
-/// unit propagation (see https://en.wikipedia.org/wiki/Unit_propagation),
-/// extended to support disjunctions.
-///
-/// The extension works approximately as follows: first we perform ordinary unit
-/// propagation, accumulating a list of any disjunction variables that need to
-/// be assigned a value of `true`.  Once this finishes, we heuristically choose
-/// one of these disjunction variables and ensure that it is assigned a value of
-/// `true` by setting one of its constituent variables to `true` and propagating
-/// again.  Once all disjunctions have been resolved, we have a final solution.
-class Solver extends Constraints {
-  /// Clauses that should be evaluated as part of ordinary unit propagation.
-  final _pending = <_Clause>[];
-
-  /// Disjunction variables that have been determined by unit propagation to be
-  /// `true`, but for which we have not yet propagated the `true` value to one
-  /// of the constituent variables.
-  final _pendingDisjunctions = <ConstraintVariable>[];
-
-  /// Heuristically resolves any pending disjunctions.
-  void applyHeuristics() {
-    while (_pendingDisjunctions.isNotEmpty) {
-      var disjunction = _pendingDisjunctions.removeLast();
-      if (disjunction.disjunctionParts.any((v) => v.value)) continue;
-      // TODO(paulberry): smarter heuristics
-      var choice = disjunction.disjunctionParts.first;
-      record([], choice);
-    }
-  }
-
-  @override
-  void record(Iterable<ConstraintVariable> conditions,
-      covariant ConstraintVariable consequence) {
-    var _conditions = List<ConstraintVariable>.from(conditions);
-    var clause = _Clause(_conditions, consequence);
-    int i = 0;
-    while (i < _conditions.length) {
-      ConstraintVariable variable = _conditions[i];
-      if (variable._value) {
-        int j = _conditions.length - 1;
-        _conditions[i] = _conditions[j];
-        _conditions.removeLast();
-        continue;
-      }
-      variable._dependencies.add(clause);
-      i++;
-    }
-    if (i == 0) {
-      if (!consequence._value) {
-        consequence._value = true;
-        if (consequence.isDisjunction) {
-          _pendingDisjunctions.add(consequence);
-        }
-        _pending.addAll(consequence._dependencies);
-        _propagate();
-      }
-    } else {
-      consequence._dependencies.add(clause);
-    }
-  }
-
-  /// Performs ordinary unit propagation, recording any disjunctions encountered
-  /// in [_pendingDisjunctions].
-  void _propagate() {
-    while (_pending.isNotEmpty) {
-      var clause = _pending.removeLast();
-      var conditions = clause.conditions;
-      int i = 0;
-      while (i < conditions.length) {
-        ConstraintVariable variable = conditions[i];
-        if (variable._value) {
-          int j = conditions.length - 1;
-          conditions[i] = conditions[j];
-          conditions.removeLast();
-          continue;
-        }
-        i++;
-      }
-      if (i == 0) {
-        var consequence = clause.consequence;
-        if (!consequence._value) {
-          consequence._value = true;
-          if (consequence.isDisjunction) {
-            _pendingDisjunctions.add(consequence);
-          }
-          _pending.addAll(consequence._dependencies);
-        }
-      }
-    }
-  }
-}
-
-/// The special singleton [ConstraintVariable] whose value is always `true`.
-class _Always extends ConstraintVariable {
-  _Always() {
-    _value = true;
-  }
-
-  @override
-  String toString() => 'always';
-}
-
-/// A single equation in a system of constraints.
-class _Clause {
-  /// The conditions on the left hand side of the equation.
-  final List<ConstraintVariable> conditions;
-
-  /// The single variable on the right hand side of the equation.
-  final ConstraintVariable consequence;
-
-  _Clause(this.conditions, this.consequence);
-}
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index e24d2db..07fcdd8 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -141,10 +141,6 @@
   String correction = error.correction;
   bool fix = hasFix(error.errorCode);
   String url = errorCode.url;
-  if (url == null && errorCode is engine.LintCode) {
-    String lintName = errorCode.name.toLowerCase();
-    url = 'https://dart-lang.github.io/linter/lints/$lintName.html';
-  }
   return new AnalysisError(severity, type, location, message, code,
       correction: correction, hasFix: fix, url: url);
 }
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
index 26a8028..18e26c5 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:analysis_server/src/provisional/completion/completion_core.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -49,6 +50,12 @@
   List<String> get enabledExperiments;
 
   /**
+   * Return the feature set that was used to analyze the compilation unit in
+   * which suggestions are being made.
+   */
+  FeatureSet get featureSet;
+
+  /**
    * Return `true` if free standing identifiers should be suggested
    */
   bool get includeIdentifiers;
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 70f98dc..af93a95 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -14,6 +14,7 @@
 import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
 import 'package:analysis_server/src/server/dev_server.dart';
 import 'package:analysis_server/src/server/diagnostic_server.dart';
+import 'package:analysis_server/src/server/features.dart';
 import 'package:analysis_server/src/server/http_server.dart';
 import 'package:analysis_server/src/server/lsp_stdio_server.dart';
 import 'package:analysis_server/src/server/stdio_server.dart';
@@ -24,11 +25,13 @@
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/file_instrumentation.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:args/args.dart';
+import 'package:front_end/src/fasta/compiler_context.dart';
 import 'package:linter/src/rules.dart' as linter;
 import 'package:telemetry/crash_reporting.dart';
 import 'package:telemetry/telemetry.dart' as telemetry;
@@ -195,6 +198,18 @@
   static const String DARTPAD_OPTION = "dartpad";
 
   /**
+   * The name of the option to disable the completion feature.
+   */
+  static const String DISABLE_SERVER_FEATURE_COMPLETION =
+      "disable-server-feature-completion";
+
+  /**
+   * The name of the option to disable the search feature.
+   */
+  static const String DISABLE_SERVER_FEATURE_SEARCH =
+      "disable-server-feature-search";
+
+  /**
    * The name of the option used to enable instrumentation.
    */
   static const String ENABLE_INSTRUMENTATION_OPTION = "enable-instrumentation";
@@ -270,6 +285,11 @@
   static const String USE_LSP = "lsp";
 
   /**
+   * The name of the flag to use summary2.
+   */
+  static const String USE_SUMMARY2 = "use-summary2";
+
+  /**
    * A directory to analyze in order to train an analysis server snapshot.
    */
   static const String TRAIN_USING = "train-using";
@@ -319,6 +339,7 @@
     analysisServerOptions.cacheFolder = results[CACHE_FOLDER];
     analysisServerOptions.useFastaParser = results[USE_FASTA_PARSER];
     analysisServerOptions.useLanguageServerProtocol = results[USE_LSP];
+    AnalysisDriver.useSummary2 = results[USE_SUMMARY2];
 
     bool disableAnalyticsForSession = results[SUPPRESS_ANALYTICS_FLAG];
     if (results.wasParsed(TRAIN_USING)) {
@@ -354,6 +375,17 @@
       UriContributor.suggestFilePaths = false;
     }
 
+    {
+      bool disableCompletion = results[DISABLE_SERVER_FEATURE_COMPLETION];
+      bool disableSearch = results[DISABLE_SERVER_FEATURE_SEARCH];
+      if (disableCompletion || disableSearch) {
+        analysisServerOptions.featureSet = FeatureSet(
+          completion: !disableCompletion,
+          search: !disableSearch,
+        );
+      }
+    }
+
     if (results[HELP_OPTION]) {
       _printUsage(parser.parser, analytics, fromHelp: true);
       return null;
@@ -404,19 +436,21 @@
       }
     }
 
-    if (analysisServerOptions.useLanguageServerProtocol) {
-      startLspServer(results, analysisServerOptions, dartSdkManager,
-          instrumentationService, diagnosticServerPort);
-    } else {
-      startAnalysisServer(
-          results,
-          analysisServerOptions,
-          parser,
-          dartSdkManager,
-          instrumentationService,
-          analytics,
-          diagnosticServerPort);
-    }
+    CompilerContext.runWithDefaultOptions((_) async {
+      if (analysisServerOptions.useLanguageServerProtocol) {
+        startLspServer(results, analysisServerOptions, dartSdkManager,
+            instrumentationService, diagnosticServerPort);
+      } else {
+        startAnalysisServer(
+            results,
+            analysisServerOptions,
+            parser,
+            dartSdkManager,
+            instrumentationService,
+            analytics,
+            diagnosticServerPort);
+      }
+    });
   }
 
   void startAnalysisServer(
@@ -532,6 +566,8 @@
   ) {
     final serve_http = diagnosticServerPort != null;
 
+    linter.registerLintRules();
+
     _DiagnosticServerImpl diagnosticServer = new _DiagnosticServerImpl();
 
     final socketServer = new LspSocketServer(
@@ -630,6 +666,10 @@
         help: 'enable DartPad specific functionality',
         defaultsTo: false,
         hide: true);
+    parser.addFlag(DISABLE_SERVER_FEATURE_COMPLETION,
+        help: 'disable all completion features', defaultsTo: false, hide: true);
+    parser.addFlag(DISABLE_SERVER_FEATURE_SEARCH,
+        help: 'disable all search features', defaultsTo: false, hide: true);
     parser.addFlag(ENABLE_INSTRUMENTATION_OPTION,
         help: "enable sending instrumentation information to a server",
         defaultsTo: false,
@@ -682,6 +722,8 @@
         help: "Whether to enable parsing via the Fasta parser");
     parser.addFlag(USE_LSP,
         defaultsTo: false, help: "Whether to use the Language Server Protocol");
+    parser.addFlag(USE_SUMMARY2,
+        defaultsTo: false, help: "Whether to use summary2");
     parser.addOption(TRAIN_USING,
         help: "Pass in a directory to analyze for purposes of training an "
             "analysis server snapshot.");
diff --git a/pkg/analysis_server/lib/src/server/features.dart b/pkg/analysis_server/lib/src/server/features.dart
new file mode 100644
index 0000000..fd02aa1
--- /dev/null
+++ b/pkg/analysis_server/lib/src/server/features.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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.
+
+/// The set of features enabled in a server session.
+///
+/// When some features are not enabled, the server might avoid doing work
+/// that is only required for these features.
+class FeatureSet {
+  final bool completion;
+  final bool search;
+
+  FeatureSet({
+    this.completion = true,
+    this.search = true,
+  });
+}
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 3558966..a18befb 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
@@ -182,7 +182,7 @@
       // Optionally add Flutter child widget details.
       Element element = parameter.enclosingElement;
       if (element is ConstructorElement) {
-        var flutter = Flutter.of(request.result.session);
+        var flutter = Flutter.of(request.result);
         if (flutter.isWidget(element.enclosingElement)) {
           String value = getDefaultStringParameterValue(parameter);
           if (value == '<Widget>[]') {
@@ -224,7 +224,7 @@
       return;
     }
     Iterable<ParameterElement> requiredParam =
-        parameters.where((ParameterElement p) => p.isNotOptional);
+        parameters.where((ParameterElement p) => p.isRequiredPositional);
     int requiredCount = requiredParam.length;
     // TODO (jwren) _isAppendingToArgList can be split into two cases (with and
     // without preceded), then _isAppendingToArgList,
@@ -260,7 +260,7 @@
   }
 
   bool _isInFlutterCreation(DartCompletionRequest request) {
-    var flutter = Flutter.of(request.result.session);
+    var flutter = Flutter.of(request.result);
     AstNode containingNode = request?.target?.containingNode;
     InstanceCreationExpression newExpr = containingNode != null
         ? flutter.identifyNewExpression(containingNode.parent)
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 942ace0..ff5c730 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -30,6 +30,7 @@
 import 'package:analysis_server/src/services/completion/dart/type_member_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/uri_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/variable_name_contributor.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -334,6 +335,10 @@
       result.session.analysisContext.analysisOptions.enabledExperiments;
 
   @override
+  FeatureSet get featureSet =>
+      result.session.analysisContext.analysisOptions.contextFeatures;
+
+  @override
   bool get includeIdentifiers {
     return opType.includeIdentifiers;
   }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
index 5a66b56..6a9d22b 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
@@ -134,8 +134,7 @@
     }
     if (element is MethodElement &&
         element.name == 'setState' &&
-        Flutter.of(request.result.session)
-            .isExactState(element.enclosingElement)) {
+        Flutter.of(request.result).isExactState(element.enclosingElement)) {
       // Find the line indentation.
       String content = request.result.content;
       int lineStartOffset = request.offset;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index 9da6534..b68e34a 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -6,10 +6,10 @@
 
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
@@ -295,6 +295,10 @@
     if (node.covariantKeyword == null) {
       _addSuggestion(Keyword.COVARIANT);
     }
+    if (node.fields.lateKeyword == null &&
+        request.featureSet.isEnabled(Feature.non_nullable)) {
+      _addSuggestion(Keyword.LATE);
+    }
     if (!node.isStatic) {
       _addSuggestion(Keyword.STATIC);
     }
@@ -343,10 +347,16 @@
     }
     if (entity is Token && (entity as Token).type == TokenType.CLOSE_PAREN) {
       _addSuggestion(Keyword.COVARIANT);
+      if (request.featureSet.isEnabled(Feature.non_nullable)) {
+        _addSuggestion(Keyword.REQUIRED);
+      }
     } else if (entity is FormalParameter) {
       Token beginToken = (entity as FormalParameter).beginToken;
       if (beginToken != null && request.target.offset == beginToken.end) {
         _addSuggestion(Keyword.COVARIANT);
+        if (request.featureSet.isEnabled(Feature.non_nullable)) {
+          _addSuggestion(Keyword.REQUIRED);
+        }
       }
     }
   }
@@ -645,6 +655,9 @@
       Keyword.VAR,
       Keyword.VOID
     ]);
+    if (request.featureSet.isEnabled(Feature.non_nullable)) {
+      _addSuggestion(Keyword.LATE);
+    }
   }
 
   void _addClassDeclarationKeywords(ClassDeclaration node) {
@@ -661,9 +674,7 @@
   }
 
   void _addCollectionElementKeywords() {
-    List<String> enabledExperiments = request.enabledExperiments;
-    if (enabledExperiments.contains(EnableString.control_flow_collections) ||
-        enabledExperiments.contains(EnableString.spread_collections)) {
+    if (request.featureSet.isEnabled(Feature.control_flow_collections)) {
       _addSuggestions([
         Keyword.FOR,
         Keyword.IF,
@@ -683,6 +694,9 @@
       Keyword.VAR,
       Keyword.VOID
     ], DART_RELEVANCE_HIGH);
+    if (request.featureSet.isEnabled(Feature.non_nullable)) {
+      _addSuggestion(Keyword.LATE, DART_RELEVANCE_HIGH);
+    }
   }
 
   void _addExpressionKeywords(AstNode node) {
@@ -769,6 +783,9 @@
       Keyword.VOID,
       Keyword.WHILE
     ]);
+    if (request.featureSet.isEnabled(Feature.non_nullable)) {
+      _addSuggestion(Keyword.LATE);
+    }
   }
 
   void _addSuggestion(Keyword keyword,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
index e4d6e0f..0588482 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
@@ -514,7 +514,7 @@
     }).toList();
 
     Iterable<ParameterElement> requiredParameters = paramList
-        .where((FormalParameter param) => param.isRequired)
+        .where((FormalParameter param) => param.isRequiredPositional)
         .map((p) => p.declaredElement);
     suggestion.requiredParameterCount = requiredParameters.length;
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index abce4e7..0300ad1 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -63,7 +63,7 @@
     }).toList();
 
     Iterable<ParameterElement> requiredParameters = element.parameters
-        .where((ParameterElement param) => param.isNotOptional);
+        .where((ParameterElement param) => param.isRequiredPositional);
     suggestion.requiredParameterCount = requiredParameters.length;
 
     Iterable<ParameterElement> namedParameters =
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index 409b979..a40613c 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -213,7 +213,7 @@
   }
 
   // If the type is unresolved, use the declared type.
-  if (type != null && type.isUndefined) {
+  if (type != null && type.isDynamic) {
     if (declaredType is TypeName) {
       Identifier id = declaredType.name;
       if (id != null) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
index 82555b4..1d86d94 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
@@ -11,6 +11,7 @@
     show DartCompletionRequestImpl;
 import 'package:analysis_server/src/services/correction/name_suggestion.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
 import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
 
 /**
@@ -59,17 +60,25 @@
       // Resolution not needed for this completion
 
       AstNode node = request.target.containingNode;
+      int offset = request.target.offset;
+
+      // Use the refined node.
+      if (node is FormalParameterList) {
+        node = CompletionTarget.findFormalParameter(node, offset);
+      }
 
       String strName = null;
       if (node is ExpressionStatement) {
-        if (node.expression is Identifier) {
-          strName = _getStringName(node.expression as Identifier);
+        var expression = node.expression;
+        if (expression is Identifier) {
+          strName = _getStringName(expression);
         }
+      } else if (node is SimpleFormalParameter) {
+        var identifier = _formalParameterTypeIdentifier(node);
+        strName = _getStringName(identifier);
       } else if (node is VariableDeclarationList) {
-        TypeAnnotation typeAnnotation = node.type;
-        if (typeAnnotation is TypeName) {
-          strName = _getStringName(typeAnnotation.name);
-        }
+        var identifier = _typeAnnotationIdentifier(node.type);
+        strName = _getStringName(identifier);
       } else if (node is TopLevelVariableDeclaration) {
         // The parser parses 'Foo ' and 'Foo ;' differently, resulting in the
         // following.
@@ -79,9 +88,8 @@
         VariableDeclarationList varDeclarationList = node.variables;
         TypeAnnotation typeAnnotation = varDeclarationList.type;
         if (typeAnnotation != null) {
-          if (typeAnnotation is TypeName) {
-            strName = _getStringName(typeAnnotation.name);
-          }
+          var identifier = _typeAnnotationIdentifier(typeAnnotation);
+          strName = _getStringName(identifier);
         } else {
           NodeList<VariableDeclaration> varDeclarations =
               varDeclarationList.variables;
@@ -95,9 +103,8 @@
         return const <CompletionSuggestion>[];
       }
 
-      var doIncludePrivateVersion = !optype.inMethodBody &&
-          !optype.inFunctionBody &&
-          !optype.inConstructorBody;
+      var doIncludePrivateVersion =
+          optype.inFieldDeclaration || optype.inTopLevelVariableDeclaration;
 
       List<String> variableNameSuggestions = getCamelWordCombinations(strName);
       variableNameSuggestions.remove(strName);
@@ -119,4 +126,22 @@
     }
     return const <CompletionSuggestion>[];
   }
+
+  static Identifier _formalParameterTypeIdentifier(FormalParameter node) {
+    if (node is SimpleFormalParameter) {
+      var type = node.type;
+      if (type != null) {
+        return _typeAnnotationIdentifier(type);
+      }
+      return node.identifier;
+    }
+    return null;
+  }
+
+  static Identifier _typeAnnotationIdentifier(TypeAnnotation type) {
+    if (type is TypeName) {
+      return type.name;
+    }
+    return null;
+  }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
index 6c73922..cf2f06f 100644
--- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -324,12 +324,6 @@
           }
           _removeError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "']'");
           _removeError(ScannerErrorCode.EXPECTED_TOKEN, partialMatch: "']'");
-          var ms =
-              _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "';'");
-          if (ms != null) {
-            // Ensure the semicolon gets inserted in the correct location.
-            ms.offset = loc - 1;
-          }
         }
       }
     }
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index b16b95c..e46f525 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -60,11 +60,6 @@
   static const CONVERT_INTO_FINAL_FIELD = const AssistKind(
       'dart.assist.convert.getterToFinalField', 30, "Convert to final field",
       associatedErrorCodes: <String>['prefer_final_fields']);
-  static const CONVERT_INTO_ABSOLUTE_IMPORT = const AssistKind(
-      'dart.assist.convert.relativeToAbsoluteImport',
-      30,
-      "Convert to absolute import",
-      associatedErrorCodes: <String>['avoid_relative_lib_imports']);
   static const CONVERT_INTO_FOR_INDEX = const AssistKind(
       'dart.assist.convert.forEachToForIndex', 30, "Convert to for-index loop");
   static const CONVERT_INTO_GENERIC_FUNCTION_SYNTAX = const AssistKind(
@@ -120,6 +115,11 @@
   static const CONVERT_TO_NULL_AWARE = const AssistKind(
       'dart.assist.convert.toNullAware', 30, "Convert to use '?.'",
       associatedErrorCodes: <String>['prefer_null_aware_operators']);
+  static const CONVERT_TO_PACKAGE_IMPORT = const AssistKind(
+      'dart.assist.convert.relativeToPackageImport',
+      30,
+      "Convert to 'package:' import",
+      associatedErrorCodes: <String>['avoid_relative_lib_imports']);
   static const CONVERT_TO_SET_LITERAL = const AssistKind(
       'dart.assist.convert.toSetLiteral', 30, "Convert to set literal",
       // todo (brianwilkerson): unify w/ fix
@@ -148,8 +148,10 @@
       const AssistKind('dart.assist.flutter.move.down', 30, "Move widget down");
   static const FLUTTER_MOVE_UP =
       const AssistKind('dart.assist.flutter.move.up', 30, "Move widget up");
-  static const FLUTTER_REMOVE_WIDGET =
-      const AssistKind('dart.assist.flutter.removeWidget', 30, "Remove widget");
+  static const FLUTTER_REMOVE_WIDGET = const AssistKind(
+      'dart.assist.flutter.removeWidget',
+      30,
+      "Replace widget with its children");
   static const FLUTTER_SWAP_WITH_CHILD = const AssistKind(
       'dart.assist.flutter.swap.withChild', 30, "Swap with child");
   static const FLUTTER_SWAP_WITH_PARENT = const AssistKind(
@@ -203,6 +205,13 @@
       'dart.assist.convert.ifElseToConditional',
       30,
       "Replace 'if-else' with conditional ('c ? x : y')");
+  static const SORT_CHILD_PROPERTY_LAST = const AssistKind(
+      'dart.assist.sort.child.properties.last',
+      30,
+      "Move child property to end of arguments",
+      associatedErrorCodes: <String>[
+        'sort_child_properties_last',
+      ]);
   static const SPLIT_AND_CONDITION = const AssistKind(
       'dart.assist.splitIfConjunction', 30, "Split && condition");
   static const SPLIT_VARIABLE_DECLARATION = 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 9a58459..b465c69 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -69,7 +69,7 @@
         typeProvider = context.resolveResult.typeProvider,
         file = context.resolveResult.path,
         utils = new CorrectionUtils(context.resolveResult),
-        flutter = Flutter.of(context.resolveResult.session);
+        flutter = Flutter.of(context.resolveResult);
 
   /**
    * Returns the EOL to use for this [CompilationUnit].
@@ -104,7 +104,6 @@
     await _addProposal_convertMapConstructorToMapLiteral();
     await _addProposal_convertPartOfToUri();
     await _addProposal_convertSetConstructorToSetLiteral();
-    await _addProposal_convertToAbsoluteImport();
     await _addProposal_convertToAsyncFunctionBody();
     await _addProposal_convertToBlockFunctionBody();
     await _addProposal_convertToDoubleQuotedString();
@@ -119,6 +118,7 @@
     await _addProposal_convertToMultilineString();
     await _addProposal_convertToNormalParameter();
     await _addProposal_convertToNullAware();
+    await _addProposal_convertToPackageImport();
     await _addProposal_convertToSingleQuotedString();
     await _addProposal_encapsulateField();
     await _addProposal_exchangeOperands();
@@ -145,6 +145,7 @@
     await _addProposal_reparentFlutterList();
     await _addProposal_replaceConditionalWithIfElse();
     await _addProposal_replaceIfElseWithConditional();
+    await _addProposal_sortChildPropertyLast();
     await _addProposal_splitAndCondition();
     await _addProposal_splitVariableDeclaration();
     await _addProposal_surroundWith();
@@ -1009,7 +1010,7 @@
         if (expression is FunctionExpression) {
           NodeList<FormalParameter> parameters =
               expression.parameters.parameters;
-          if (parameters.length == 1 && parameters[0].isRequired) {
+          if (parameters.length == 1 && parameters[0].isRequiredPositional) {
             if (extractBody(expression) != null) {
               return expression;
             }
@@ -1229,29 +1230,6 @@
     _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_TO_SET_LITERAL);
   }
 
-  Future<void> _addProposal_convertToAbsoluteImport() async {
-    var node = this.node;
-    if (node is StringLiteral) {
-      node = node.parent;
-    }
-    if (node is ImportDirective) {
-      var importDirective = node;
-      var importUri = node.uriSource?.uri;
-      if (importUri?.scheme != 'package') {
-        return;
-      }
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (builder) {
-        builder.addSimpleReplacement(
-            range.node(importDirective.uri), "'$importUri'");
-      });
-      _addAssistFromBuilder(
-        changeBuilder,
-        DartAssistKind.CONVERT_INTO_ABSOLUTE_IMPORT,
-      );
-    }
-  }
-
   Future<void> _addProposal_convertToAsyncFunctionBody() async {
     FunctionBody body = getEnclosingFunctionBody();
     if (body == null ||
@@ -1945,6 +1923,48 @@
     }
   }
 
+  Future<void> _addProposal_convertToPackageImport() async {
+    var node = this.node;
+    if (node is StringLiteral) {
+      node = node.parent;
+    }
+    if (node is ImportDirective) {
+      ImportDirective importDirective = node;
+      var uriSource = importDirective.uriSource;
+
+      // Ignore if invalid URI.
+      if (uriSource == null) {
+        return;
+      }
+
+      var importUri = uriSource.uri;
+      if (importUri.scheme != 'package') {
+        return;
+      }
+
+      // Don't offer to convert a 'package:' URI to itself.
+      try {
+        if (Uri.parse(importDirective.uriContent).scheme == 'package') {
+          return;
+        }
+      } on FormatException {
+        return;
+      }
+
+      var changeBuilder = _newDartChangeBuilder();
+      await changeBuilder.addFileEdit(file, (builder) {
+        builder.addSimpleReplacement(
+          range.node(importDirective.uri),
+          "'$importUri'",
+        );
+      });
+      _addAssistFromBuilder(
+        changeBuilder,
+        DartAssistKind.CONVERT_TO_PACKAGE_IMPORT,
+      );
+    }
+  }
+
   Future<void> _addProposal_convertToSingleQuotedString() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -3528,6 +3548,47 @@
     }
   }
 
+  Future<void> _addProposal_sortChildPropertyLast() async {
+    NamedExpression childProp = flutter.findNamedExpression(node, 'child');
+    if (childProp == null) {
+      childProp = flutter.findNamedExpression(node, 'children');
+    }
+    if (childProp == null) {
+      return;
+    }
+
+    var parent = childProp.parent?.parent;
+    if (parent is! InstanceCreationExpression ||
+        !flutter.isWidgetCreation(parent)) {
+      return;
+    }
+
+    InstanceCreationExpression creationExpression = parent;
+    var args = creationExpression.argumentList;
+
+    var last = args.arguments.last;
+    if (last == childProp) {
+      // Already sorted.
+      return;
+    }
+
+    var changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      var start = childProp.beginToken.previous.end;
+      var end = childProp.endToken.next.end;
+      var childRange = range.startOffsetEndOffset(start, end);
+
+      var childText = utils.getRangeText(childRange);
+      builder.addSimpleReplacement(childRange, '');
+      builder.addSimpleInsertion(last.end + 1, childText);
+
+      changeBuilder.setSelection(new Position(file, last.end + 1));
+    });
+
+    _addAssistFromBuilder(
+        changeBuilder, DartAssistKind.SORT_CHILD_PROPERTY_LAST);
+  }
+
   Future<void> _addProposal_splitAndCondition() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 7ca77e9..adfc446 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/error/error.dart';
@@ -119,7 +120,16 @@
   @override
   final AnalysisError error;
 
-  DartFixContextImpl(this.workspace, this.resolveResult, this.error);
+  final List<TopLevelDeclaration> Function(String name)
+      getTopLevelDeclarationsFunction;
+
+  DartFixContextImpl(this.workspace, this.resolveResult, this.error,
+      this.getTopLevelDeclarationsFunction);
+
+  @override
+  List<TopLevelDeclaration> getTopLevelDeclarations(String name) {
+    return getTopLevelDeclarationsFunction(name);
+  }
 }
 
 /// An enumeration of quick fix kinds found in a Dart file.
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/dart/top_level_declarations.dart b/pkg/analysis_server/lib/src/services/correction/fix/dart/top_level_declarations.dart
new file mode 100644
index 0000000..ef4b987
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/dart/top_level_declarations.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/src/services/available_declarations.dart';
+
+/// Information about a single top-level declaration.
+class TopLevelDeclaration {
+  /// The path of the library that exports this declaration.
+  final String path;
+
+  /// The URI of the library that exports this declaration.
+  final Uri uri;
+
+  final TopLevelDeclarationKind kind;
+
+  final String name;
+
+  /// Is `true` if the declaration is exported, not declared in the [path].
+  final bool isExported;
+
+  TopLevelDeclaration(
+    this.path,
+    this.uri,
+    this.kind,
+    this.name,
+    this.isExported,
+  );
+
+  @override
+  String toString() => '($path, $uri, $kind, $name, $isExported)';
+}
+
+/// Kind of a top-level declaration.
+///
+/// We don't need it to be precise, just enough to support quick fixes.
+enum TopLevelDeclarationKind { type, function, variable }
+
+class TopLevelDeclarationsProvider {
+  final DeclarationsTracker tracker;
+
+  TopLevelDeclarationsProvider(this.tracker);
+
+  void doTrackerWork() {
+    while (tracker.hasWork) {
+      tracker.doWork();
+    }
+  }
+
+  List<TopLevelDeclaration> get(
+    AnalysisContext analysisContext,
+    String path,
+    String name,
+  ) {
+    var declarations = <TopLevelDeclaration>[];
+
+    void addDeclarations(Library library) {
+      for (var declaration in library.declarations) {
+        if (declaration.name != name) continue;
+
+        var kind = _getTopKind(declaration.kind);
+        if (kind == null) continue;
+
+        declarations.add(
+          TopLevelDeclaration(
+            library.path,
+            library.uri,
+            kind,
+            name,
+            declaration.locationLibraryUri != library.uri,
+          ),
+        );
+      }
+    }
+
+    var declarationsContext = tracker.getContext(analysisContext);
+    var libraries = declarationsContext.getLibraries(path);
+    libraries.context.forEach(addDeclarations);
+    libraries.dependencies.forEach(addDeclarations);
+    libraries.sdk.forEach(addDeclarations);
+
+    return declarations;
+  }
+
+  TopLevelDeclarationKind _getTopKind(DeclarationKind kind) {
+    switch (kind) {
+      case DeclarationKind.CLASS:
+      case DeclarationKind.CLASS_TYPE_ALIAS:
+      case DeclarationKind.ENUM:
+      case DeclarationKind.FUNCTION_TYPE_ALIAS:
+      case DeclarationKind.MIXIN:
+        return TopLevelDeclarationKind.type;
+        break;
+      case DeclarationKind.FUNCTION:
+        return TopLevelDeclarationKind.function;
+        break;
+      case DeclarationKind.GETTER:
+      case DeclarationKind.SETTER:
+      case DeclarationKind.VARIABLE:
+        return TopLevelDeclarationKind.variable;
+        break;
+      default:
+        return null;
+    }
+  }
+}
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 e605378..4cd9e33 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -10,6 +10,7 @@
 import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/levenshtein.dart';
 import 'package:analysis_server/src/services/correction/namespace.dart';
 import 'package:analysis_server/src/services/correction/strings.dart';
@@ -26,7 +27,6 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/session_helper.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
@@ -105,7 +105,11 @@
     // For each fix, put the fix into the HashMap.
     for (int i = 0; i < allAnalysisErrors.length; i++) {
       final FixContext fixContextI = new DartFixContextImpl(
-          context.workspace, context.resolveResult, allAnalysisErrors[i]);
+        context.workspace,
+        context.resolveResult,
+        allAnalysisErrors[i],
+        (name) => [],
+      );
       final FixProcessor processorI = new FixProcessor(fixContextI);
       final List<Fix> fixesListI = await processorI.compute();
       for (Fix f in fixesListI) {
@@ -196,7 +200,7 @@
         unitLibraryElement = context.resolveResult.libraryElement,
         unit = context.resolveResult.unit,
         utils = CorrectionUtils(context.resolveResult),
-        flutter = Flutter.of(context.resolveResult.session),
+        flutter = Flutter.of(context.resolveResult),
         error = context.error,
         errorOffset = context.error.offset,
         errorLength = context.error.length;
@@ -1747,7 +1751,7 @@
       // prepare parameters and arguments
       Iterable<ParameterElement> requiredParameters = superConstructor
           .parameters
-          .where((parameter) => parameter.isNotOptional);
+          .where((parameter) => parameter.isRequiredPositional);
       // add proposal
       ClassMemberLocation targetLocation =
           utils.prepareNewConstructorLocation(targetClassNode);
@@ -2343,9 +2347,11 @@
     ClassDeclaration declaration =
         node.thisOrAncestorOfType<ClassDeclaration>();
     if (declaration != null && declaration.extendsClause == null) {
+      // TODO(brianwilkerson) Find a way to pass in the name of the class
+      //  without needing to parse the message.
       String message = error.message;
-      int startIndex = message.indexOf("'", message.indexOf("'") + 1) + 1;
-      int endIndex = message.indexOf("'", startIndex);
+      int endIndex = message.lastIndexOf("'");
+      int startIndex = message.lastIndexOf("'", endIndex - 1) + 1;
       String typeName = message.substring(startIndex, endIndex);
       var changeBuilder = _newDartChangeBuilder();
       await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
@@ -2410,7 +2416,7 @@
     }
     // may be there is an existing import,
     // but it is with prefix and we don't use this prefix
-    Set<Source> alreadyImportedWithPrefix = new Set<Source>();
+    var alreadyImportedWithPrefix = new Set<String>();
     for (ImportElement imp in unitLibraryElement.imports) {
       // prepare element
       LibraryElement libraryElement = imp.importedLibrary;
@@ -2452,7 +2458,7 @@
           libraryName = libraryElement.source.shortName;
         }
         // don't add this library again
-        alreadyImportedWithPrefix.add(libraryElement.source);
+        alreadyImportedWithPrefix.add(libraryElement.source.fullName);
         // update library
         String newShowCode = 'show ${showNames.join(', ')}';
         int offset = showCombinator.offset;
@@ -2471,25 +2477,21 @@
     }
     // Find new top-level declarations.
     {
-      var declarations = await session.getTopLevelDeclarations(name);
-      for (TopLevelDeclarationInSource declaration in declarations) {
+      var declarations = await context.getTopLevelDeclarations(name);
+      for (var declaration in declarations) {
         // Check the kind.
-        if (!kinds2.contains(declaration.declaration.kind)) {
+        if (!kinds2.contains(declaration.kind)) {
           continue;
         }
         // Check the source.
-        Source librarySource = declaration.source;
-        if (alreadyImportedWithPrefix.contains(librarySource)) {
-          continue;
-        }
-        if (!_isSourceVisibleToLibrary(librarySource)) {
+        if (alreadyImportedWithPrefix.contains(declaration.path)) {
           continue;
         }
         // Compute the fix kind.
         FixKind fixKind;
-        if (librarySource.isInSystemLibrary) {
+        if (declaration.uri.isScheme('dart')) {
           fixKind = DartFixKind.IMPORT_LIBRARY_SDK;
-        } else if (_isLibSrcPath(librarySource.fullName)) {
+        } else if (_isLibSrcPath(declaration.path)) {
           // Bad: non-API.
           fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT3;
         } else if (declaration.isExported) {
@@ -2501,8 +2503,8 @@
         }
         // Add the fix.
         var relativeURI =
-            _getRelativeURIFromLibrary(unitLibraryElement, librarySource);
-        await _addFix_importLibrary(fixKind, librarySource.uri, relativeURI);
+            _getRelativeURIFromLibrary(unitLibraryElement, declaration.path);
+        await _addFix_importLibrary(fixKind, declaration.uri, relativeURI);
       }
     }
   }
@@ -3908,7 +3910,7 @@
     // Prepare the last required parameter.
     FormalParameter lastRequiredParameter;
     for (FormalParameter parameter in parameters) {
-      if (parameter.isRequired) {
+      if (parameter.isRequiredPositional) {
         lastRequiredParameter = parameter;
       }
     }
@@ -4244,21 +4246,20 @@
   }
 
   /**
-   * Return the relative uri from the passed [library] to the passed
-   * [source]. If the [source] is not in the LibraryElement, `null` is returned.
+   * Return the relative uri from the passed [library] to the given [path].
+   * If the [path] is not in the LibraryElement, `null` is returned.
    */
-  String _getRelativeURIFromLibrary(LibraryElement library, Source source) {
+  String _getRelativeURIFromLibrary(LibraryElement library, String path) {
     var librarySource = library?.librarySource;
     if (librarySource == null) {
       return null;
     }
     var pathCtx = resourceProvider.pathContext;
     var libraryDirectory = pathCtx.dirname(librarySource.fullName);
-    var sourceDirectory = pathCtx.dirname(source.fullName);
-    if (pathCtx.isWithin(libraryDirectory, source.fullName) ||
+    var sourceDirectory = pathCtx.dirname(path);
+    if (pathCtx.isWithin(libraryDirectory, path) ||
         pathCtx.isWithin(sourceDirectory, libraryDirectory)) {
-      String relativeFile =
-          pathCtx.relative(source.fullName, from: libraryDirectory);
+      String relativeFile = pathCtx.relative(path, from: libraryDirectory);
       return pathCtx.split(relativeFile).join('/');
     }
     return null;
@@ -4467,30 +4468,6 @@
     return false;
   }
 
-  /**
-   * Return `true` if the [source] can be imported into current library.
-   */
-  bool _isSourceVisibleToLibrary(Source source) {
-    String path = source.fullName;
-
-    var contextRoot = context.resolveResult.session.analysisContext.contextRoot;
-    if (contextRoot == null) {
-      return true;
-    }
-
-    // We don't want to use private libraries of other packages.
-    if (source.uri.isScheme('package') && _isLibSrcPath(path)) {
-      return contextRoot.root.contains(path);
-    }
-
-    // We cannot use relative URIs to reference files outside of our package.
-    if (source.uri.isScheme('file')) {
-      return contextRoot.root.contains(path);
-    }
-
-    return true;
-  }
-
   bool _isToListMethodElement(MethodElement method) {
     if (method.name != 'toList') {
       return false;
@@ -4692,7 +4669,7 @@
 
   _ExecutableParameters._(this.sessionHelper, this.executable) {
     for (var parameter in executable.parameters) {
-      if (parameter.isNotOptional) {
+      if (parameter.isRequiredPositional) {
         required.add(parameter);
       } else if (parameter.isOptionalPositional) {
         optionalPositional.add(parameter);
diff --git a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
index dcba372..ae424d9 100644
--- a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
@@ -6,6 +6,7 @@
 import 'package:analysis_server/src/services/correction/selection_analyzer.dart';
 import 'package:analysis_server/src/services/correction/status.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -18,10 +19,11 @@
  * Returns [Token]s of the given Dart source, not `null`, may be empty if no
  * tokens or some exception happens.
  */
-List<Token> _getTokens(String text) {
+List<Token> _getTokens(String text, FeatureSet featureSet) {
   try {
     List<Token> tokens = <Token>[];
-    Scanner scanner = new Scanner(null, new CharSequenceReader(text), null);
+    Scanner scanner = new Scanner(null, new CharSequenceReader(text), null)
+      ..configureFeatures(featureSet);
     Token token = scanner.tokenize();
     while (token.type != TokenType.EOF) {
       tokens.add(token);
@@ -224,7 +226,7 @@
   bool _hasTokens(SourceRange range) {
     String fullText = resolveResult.content;
     String rangeText = fullText.substring(range.offset, range.end);
-    return _getTokens(rangeText).isNotEmpty;
+    return _getTokens(rangeText, resolveResult.unit.featureSet).isNotEmpty;
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index d4a4280..5fcc990 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -7,6 +7,7 @@
 import 'package:analysis_server/src/protocol_server.dart'
     show doSourceChange_addElementEdit;
 import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -1065,7 +1066,7 @@
       return true;
     }
     // may be comment
-    return TokenUtils.getTokens(trimmedText).isEmpty;
+    return TokenUtils.getTokens(trimmedText, unit.featureSet).isEmpty;
   }
 
   ClassMemberLocation prepareNewClassMemberLocation(
@@ -1138,7 +1139,7 @@
     // prepare STRING token ranges
     List<SourceRange> lineRanges = [];
     {
-      List<Token> tokens = TokenUtils.getTokens(source);
+      List<Token> tokens = TokenUtils.getTokens(source, unit.featureSet);
       for (Token token in tokens) {
         if (token.type == TokenType.STRING) {
           lineRanges.add(range.token(token));
@@ -1361,10 +1362,11 @@
    * @return [Token]s of the given Dart source, not <code>null</code>, may be empty if no
    *         tokens or some exception happens.
    */
-  static List<Token> getTokens(String s) {
+  static List<Token> getTokens(String s, FeatureSet featureSet) {
     try {
       List<Token> tokens = [];
-      Scanner scanner = new Scanner(null, new CharSequenceReader(s), null);
+      Scanner scanner = new Scanner(null, new CharSequenceReader(s), null)
+        ..configureFeatures(featureSet);
       Token token = scanner.tokenize();
       while (token.type != TokenType.EOF) {
         tokens.add(token);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
index d8e0c05..f850b80 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -14,6 +14,7 @@
 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -502,7 +503,8 @@
     String selectionSource;
     {
       String rawSelectionSource = utils.getRangeText(selectionRange);
-      List<Token> selectionTokens = TokenUtils.getTokens(rawSelectionSource);
+      List<Token> selectionTokens =
+          TokenUtils.getTokens(rawSelectionSource, unit.featureSet);
       selectionSource =
           _encodeExpressionTokens(rootExpression, selectionTokens);
     }
@@ -514,8 +516,8 @@
       enclosingFunction = getEnclosingExecutableNode(selectionNode);
     }
     // visit function
-    enclosingFunction
-        .accept(new _OccurrencesVisitor(this, occurrences, selectionSource));
+    enclosingFunction.accept(new _OccurrencesVisitor(
+        this, occurrences, selectionSource, unit.featureSet));
   }
 
   void _prepareOffsetsLengths() {
@@ -605,8 +607,10 @@
   final ExtractLocalRefactoringImpl ref;
   final List<SourceRange> occurrences;
   final String selectionSource;
+  final FeatureSet featureSet;
 
-  _OccurrencesVisitor(this.ref, this.occurrences, this.selectionSource);
+  _OccurrencesVisitor(
+      this.ref, this.occurrences, this.selectionSource, this.featureSet);
 
   @override
   void visitBinaryExpression(BinaryExpression node) {
@@ -662,7 +666,7 @@
 
   void _tryToFindOccurrence(Expression node) {
     String nodeSource = ref.utils.getNodeText(node);
-    List<Token> nodeTokens = TokenUtils.getTokens(nodeSource);
+    List<Token> nodeTokens = TokenUtils.getTokens(nodeSource, featureSet);
     nodeSource = ref._encodeExpressionTokens(node, nodeTokens);
     if (nodeSource == selectionSource) {
       _addOccurrence(range.node(node));
@@ -672,7 +676,7 @@
   void _tryToFindOccurrenceFragments(Expression node) {
     int nodeOffset = node.offset;
     String nodeSource = ref.utils.getNodeText(node);
-    List<Token> nodeTokens = TokenUtils.getTokens(nodeSource);
+    List<Token> nodeTokens = TokenUtils.getTokens(nodeSource, featureSet);
     nodeSource = ref._encodeExpressionTokens(node, nodeTokens);
     // find "selection" in "node" tokens
     int lastIndex = 0;
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index 2c14f1f..c340e13 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -16,6 +16,7 @@
 import 'package:analysis_server/src/services/refactoring/rename_class_member.dart';
 import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
@@ -48,8 +49,8 @@
  * Returns the "normalized" version of the given source, which is reconstructed
  * from tokens, so ignores all the comments and spaces.
  */
-String _getNormalizedSource(String src) {
-  List<Token> selectionTokens = TokenUtils.getTokens(src);
+String _getNormalizedSource(String src, FeatureSet featureSet) {
+  List<Token> selectionTokens = TokenUtils.getTokens(src, featureSet);
   return selectionTokens.join(_TOKEN_SEPARATOR);
 }
 
@@ -674,7 +675,8 @@
         .accept(new _GetSourcePatternVisitor(range, pattern, replaceEdits));
     replaceEdits = replaceEdits.reversed.toList();
     String source = SourceEdit.applySequence(originalSource, replaceEdits);
-    pattern.normalizedSource = _getNormalizedSource(source);
+    pattern.normalizedSource =
+        _getNormalizedSource(source, resolveResult.unit.featureSet);
     return pattern;
   }
 
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
index 347c778..1cfca50 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -76,7 +76,7 @@
       this.searchEngine, this.resolveResult, this.offset, this.length)
       : sessionHelper = new AnalysisSessionHelper(resolveResult.session) {
     utils = new CorrectionUtils(resolveResult);
-    flutter = Flutter.of(resolveResult.session);
+    flutter = Flutter.of(resolveResult);
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
index c552695..fa26c42 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -74,7 +74,7 @@
       argumentSource = utils.getNodeText(argument);
     } else {
       // report about a missing required parameter
-      if (parameter.isNotOptional) {
+      if (parameter.isRequiredPositional) {
         status.addError('No argument for the parameter "${parameter.name}".',
             newLocation_fromNode(contextNode));
         return;
diff --git a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
index 0963233..164d553 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
@@ -10,6 +10,7 @@
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -25,8 +26,8 @@
     implements MoveFileRefactoring {
   final ResourceProvider resourceProvider;
   final pathos.Context pathContext;
-  final RefactoringWorkspace workspace;
-  final Source source;
+  final RefactoringWorkspace refactoringWorkspace;
+  final ResolvedUnitResult resolvedUnit;
   AnalysisDriver driver;
 
   String oldFile;
@@ -34,23 +35,18 @@
 
   final packagePrefixedStringPattern = new RegExp(r'''^r?['"]+package:''');
 
-  MoveFileRefactoringImpl(ResourceProvider resourceProvider, this.workspace,
-      this.source, this.oldFile)
-      : resourceProvider = resourceProvider,
-        pathContext = resourceProvider.pathContext {
-    if (source != null) {
-      oldFile = source.fullName;
-    }
-  }
+  MoveFileRefactoringImpl(this.resourceProvider, this.refactoringWorkspace,
+      this.resolvedUnit, this.oldFile)
+      : this.pathContext = resourceProvider.pathContext;
 
   @override
   String get refactoringName => 'Move File';
 
   @override
   Future<RefactoringStatus> checkFinalConditions() async {
-    final drivers = workspace.driversContaining(oldFile);
+    final drivers = refactoringWorkspace.driversContaining(oldFile);
     if (drivers.length != 1) {
-      if (workspace.drivers
+      if (refactoringWorkspace.drivers
           .any((d) => pathContext.equals(d.contextRoot.root, oldFile))) {
         return new RefactoringStatus.fatal(
             'Renaming an analysis root is not supported ($oldFile)');
@@ -74,8 +70,7 @@
   @override
   Future<SourceChange> createChange() async {
     var changeBuilder = new DartChangeBuilder(driver.currentSession);
-    final result = await driver.getUnitElement(oldFile);
-    final element = result?.element;
+    final element = resolvedUnit.unit.declaredElement;
     if (element == null) {
       return changeBuilder.sourceChange;
     }
@@ -92,8 +87,7 @@
       });
     } else {
       // Otherwise, we need to update any relative part-of references.
-      final result = await driver.currentSession.getResolvedUnit(oldFile);
-      Iterable<PartOfDirective> partOfs = result.unit.directives
+      Iterable<PartOfDirective> partOfs = resolvedUnit.unit.directives
           .whereType<PartOfDirective>()
           .where((po) => po.uri != null && _isRelativeUri(po.uri.stringValue));
 
@@ -113,7 +107,7 @@
 
     // Update incoming references to this file
     List<SearchMatch> matches =
-        await workspace.searchEngine.searchReferences(element);
+        await refactoringWorkspace.searchEngine.searchReferences(element);
     List<SourceReference> references = getSourceReferences(matches);
     for (SourceReference reference in references) {
       await changeBuilder.addFileEdit(reference.file, (builder) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
index 7bcbb7b..63a2193 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
@@ -27,7 +27,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     show RefactoringMethodParameter, SourceChange;
 
@@ -341,10 +340,13 @@
   /**
    * Returns a new [MoveFileRefactoring] instance.
    */
-  factory MoveFileRefactoring(ResourceProvider resourceProvider,
-      RefactoringWorkspace workspace, Source source, String oldFile) {
+  factory MoveFileRefactoring(
+      ResourceProvider resourceProvider,
+      RefactoringWorkspace workspace,
+      ResolvedUnitResult resolveResult,
+      String oldFilePath) {
     return new MoveFileRefactoringImpl(
-        resourceProvider, workspace, source, oldFile);
+        resourceProvider, workspace, resolveResult, oldFilePath);
   }
 
   /**
@@ -452,7 +454,8 @@
    * type.
    */
   factory RenameRefactoring(RefactoringWorkspace workspace,
-      AnalysisSession session, Element element) {
+      ResolvedUnitResult resolvedUnit, Element element) {
+    var session = resolvedUnit.session;
     if (element == null) {
       return null;
     }
@@ -460,7 +463,8 @@
       element = (element as PropertyAccessorElement).variable;
     }
     if (element.enclosingElement is CompilationUnitElement) {
-      return new RenameUnitMemberRefactoringImpl(workspace, element);
+      return new RenameUnitMemberRefactoringImpl(
+          workspace, resolvedUnit, element);
     }
     if (element is ConstructorElement) {
       return new RenameConstructorRefactoringImpl(workspace, session, element);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
index 26d14d3..9b8e268 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
@@ -14,6 +14,7 @@
 import 'package:analysis_server/src/services/search/element_visitors.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/utilities/flutter.dart';
+import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart' show Identifier;
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/java_core.dart';
@@ -43,6 +44,8 @@
  * A [Refactoring] for renaming compilation unit member [Element]s.
  */
 class RenameUnitMemberRefactoringImpl extends RenameRefactoringImpl {
+  final ResolvedUnitResult resolvedUnit;
+
   /// If the [element] is a Flutter `StatefulWidget` declaration, this is the
   /// corresponding `State` declaration.
   ClassElement _flutterWidgetState;
@@ -51,7 +54,7 @@
   String _flutterWidgetStateNewName;
 
   RenameUnitMemberRefactoringImpl(
-      RefactoringWorkspace workspace, Element element)
+      RefactoringWorkspace workspace, this.resolvedUnit, Element element)
       : super(workspace, element);
 
   @override
@@ -144,7 +147,7 @@
   }
 
   void _findFlutterStateClass() {
-    var flutter = Flutter.of(element.session);
+    var flutter = Flutter.of(resolvedUnit);
     if (flutter.isStatefulWidgetDeclaration(element)) {
       var oldStateName = oldName + 'State';
       _flutterWidgetState = element.library.getType(oldStateName) ??
diff --git a/pkg/analysis_server/lib/src/status/ast_writer.dart b/pkg/analysis_server/lib/src/status/ast_writer.dart
index 060cf6f..0d1562d 100644
--- a/pkg/analysis_server/lib/src/status/ast_writer.dart
+++ b/pkg/analysis_server/lib/src/status/ast_writer.dart
@@ -71,12 +71,16 @@
       properties['static keyword'] = node.staticKeyword;
     } else if (node is FormalParameter) {
       properties['declaredElement'] = node.declaredElement;
-      if (node.isNamed) {
-        properties['kind'] = 'named';
+      if (node.isRequiredPositional) {
+        properties['kind'] = 'required-positional';
+      } else if (node.isRequiredNamed) {
+        properties['kind'] = 'required-named';
       } else if (node.isOptionalPositional) {
-        properties['kind'] = 'positional';
+        properties['kind'] = 'optional-positional';
+      } else if (node.isOptionalNamed) {
+        properties['kind'] = 'optional-named';
       } else {
-        properties['kind'] = 'required';
+        properties['kind'] = 'unknown kind';
       }
     } else if (node is FunctionDeclaration) {
       properties['declaredElement'] = node.declaredElement;
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 2723c18..a03964c 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -551,9 +551,9 @@
     }
 
     h3('Dartdoc template info');
-    DartdocDirectiveInfo info = (server as AnalysisServer).declarationsTracker
-        ?.getContext(driver.analysisContext)
-        ?.dartdocDirectiveInfo ??
+    DartdocDirectiveInfo info = server.declarationsTracker
+            ?.getContext(driver.analysisContext)
+            ?.dartdocDirectiveInfo ??
         new DartdocDirectiveInfo();
     writeMap(info.templateMap);
   }
diff --git a/pkg/analysis_server/lib/src/status/element_writer.dart b/pkg/analysis_server/lib/src/status/element_writer.dart
index 4e8d3ec..a4a20c9 100644
--- a/pkg/analysis_server/lib/src/status/element_writer.dart
+++ b/pkg/analysis_server/lib/src/status/element_writer.dart
@@ -129,12 +129,16 @@
     if (element is ParameterElement) {
       properties['defaultValueCode'] = element.defaultValueCode;
       properties['isInitializingFormal'] = element.isInitializingFormal;
-      if (element.isNotOptional) {
-        properties['parameterKind'] = 'required';
+      if (element.isRequiredPositional) {
+        properties['parameterKind'] = 'required-positional';
+      } else if (element.isRequiredNamed) {
+        properties['parameterKind'] = 'required-named';
       } else if (element.isOptionalPositional) {
-        properties['parameterKind'] = 'positional';
-      } else if (element.isNamed) {
-        properties['parameterKind'] = 'named';
+        properties['parameterKind'] = 'optional-positional';
+      } else if (element.isOptionalNamed) {
+        properties['parameterKind'] = 'optional-named';
+      } else {
+        properties['parameterKind'] = 'unknown kind';
       }
     }
     if (element is PropertyAccessorElement) {
diff --git a/pkg/analysis_server/lib/src/utilities/flutter.dart b/pkg/analysis_server/lib/src/utilities/flutter.dart
index 71fcd4a..f18247a 100644
--- a/pkg/analysis_server/lib/src/utilities/flutter.dart
+++ b/pkg/analysis_server/lib/src/utilities/flutter.dart
@@ -3,8 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/strings.dart';
-import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/analysis/results.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/type.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -23,6 +24,9 @@
   static final mobile = Flutter._('flutter', 'package:flutter');
   static final web = Flutter._('flutter_web', 'package:flutter_web');
 
+  static final _uriFlutterMobileWidgets =
+      Uri.parse('package:flutter/widgets.dart');
+
   static final _uriFlutterWebWidgets =
       Uri.parse('package:flutter_web/widgets.dart');
 
@@ -36,10 +40,26 @@
   final Uri _uriWidgetsIcon;
   final Uri _uriWidgetsText;
 
-  factory Flutter.of(AnalysisSession session) {
-    if (session.uriConverter.uriToPath(_uriFlutterWebWidgets) != null) {
+  factory Flutter.of(ResolvedUnitResult resolvedUnit) {
+    var uriConverter = resolvedUnit.session.uriConverter;
+    var isMobile = uriConverter.uriToPath(_uriFlutterMobileWidgets) != null;
+    var isWeb = uriConverter.uriToPath(_uriFlutterWebWidgets) != null;
+
+    if (isMobile && isWeb) {
+      var visitor = _IdentifyMobileOrWeb();
+      resolvedUnit.unit.accept(visitor);
+      isMobile = visitor.isMobile;
+      isWeb = visitor.isWeb;
+    }
+
+    if (isMobile) {
+      return mobile;
+    }
+
+    if (isWeb) {
       return web;
     }
+
     return mobile;
   }
 
@@ -263,7 +283,19 @@
     for (; node != null; node = node.parent) {
       if (isWidgetExpression(node)) {
         var parent = node.parent;
+
+        if (node is AssignmentExpression) {
+          return null;
+        }
+        if (parent is AssignmentExpression) {
+          if (parent.rightHandSide == node) {
+            return node;
+          }
+          return null;
+        }
+
         if (parent is ArgumentList ||
+            parent is ExpressionFunctionBody && parent.expression == node ||
             parent is ListLiteral ||
             parent is NamedExpression && parent.expression == node ||
             parent is Statement) {
@@ -456,3 +488,27 @@
     return element != null && element.name == type && element.source.uri == uri;
   }
 }
+
+class _IdentifyMobileOrWeb extends GeneralizingAstVisitor<void> {
+  bool isMobile = false;
+  bool isWeb = false;
+
+  @override
+  void visitExpression(Expression node) {
+    if (isMobile || isWeb) {
+      return;
+    }
+
+    if (Flutter.mobile.isWidgetExpression(node)) {
+      isMobile = true;
+      return;
+    }
+
+    if (Flutter.web.isWidgetExpression(node)) {
+      isWeb = true;
+      return;
+    }
+
+    super.visitExpression(node);
+  }
+}
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index d9f2c93..c542415 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -15,6 +15,7 @@
   linter: any
   logging: any
   meta: any
+  nnbd_migration: any
   source_span: any
   package_config: any
   path: any
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart
index 798bedb..0dbadd0 100644
--- a/pkg/analysis_server/test/abstract_single_unit.dart
+++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/ast/element_locator.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
@@ -28,6 +29,7 @@
   CompilationUnit testUnit;
   CompilationUnitElement testUnitElement;
   LibraryElement testLibraryElement;
+  FindNode findNode;
 
   void addTestSource(String code, [Uri uri]) {
     testCode = code;
@@ -128,6 +130,7 @@
     }
     testUnitElement = testUnit.declaredElement;
     testLibraryElement = testUnitElement.library;
+    findNode = FindNode(code, testUnit);
   }
 
   @override
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index 7dc1119..3c1219a 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -87,7 +87,7 @@
       expect(hover.length, 'new A.named()'.length);
       // element
       expect(hover.dartdoc, 'my doc');
-      expect(hover.elementDescription, 'A.named() → A');
+      expect(hover.elementDescription, 'A A.named()');
       expect(hover.elementKind, 'constructor');
     }
 
@@ -116,10 +116,10 @@
     expect(hover.offset, findOffset('A(0)'));
     expect(hover.length, 'A(0)'.length);
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName, 'bin/test.dart');
     expect(hover.containingLibraryPath, testFile);
     expect(hover.dartdoc, isNull);
-    expect(hover.elementDescription, '(const) A(int i) → A');
+    expect(hover.elementDescription, '(const) A A(int i)');
     expect(hover.elementKind, 'constructor');
     // types
     expect(hover.staticType, isNull);
@@ -141,10 +141,10 @@
     expect(hover.offset, findOffset('A()'));
     expect(hover.length, 'A()'.length);
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName, 'bin/test.dart');
     expect(hover.containingLibraryPath, testFile);
     expect(hover.dartdoc, isNull);
-    expect(hover.elementDescription, '(new) A() → A');
+    expect(hover.elementDescription, '(new) A A()');
     expect(hover.elementKind, 'constructor');
     // types
     expect(hover.staticType, isNull);
@@ -167,10 +167,10 @@
     expect(hover.offset, findOffset('new A'));
     expect(hover.length, 'new A()'.length);
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName, 'bin/test.dart');
     expect(hover.containingLibraryPath, testFile);
     expect(hover.dartdoc, isNull);
-    expect(hover.elementDescription, 'A() → A');
+    expect(hover.elementDescription, 'A A()');
     expect(hover.elementKind, 'constructor');
     // types
     expect(hover.staticType, isNull);
@@ -192,10 +192,10 @@
       expect(hover.offset, findOffset('new A<String>'));
       expect(hover.length, 'new A<String>()'.length);
       // element
-      expect(hover.containingLibraryName, 'my.library');
+      expect(hover.containingLibraryName, 'bin/test.dart');
       expect(hover.containingLibraryPath, testFile);
       expect(hover.dartdoc, isNull);
-      expect(hover.elementDescription, 'A() → A<String>');
+      expect(hover.elementDescription, 'A<String> A()');
       expect(hover.elementKind, 'constructor');
       // types
       expect(hover.staticType, isNull);
@@ -214,6 +214,7 @@
     }
     {
       HoverInformation hover = await prepareHover('String>');
+      expect(hover.containingLibraryName, 'dart:core');
       expect(hover.offset, findOffset('String>'));
       expect(hover.length, 'String'.length);
       expect(hover.elementKind, 'class');
@@ -329,11 +330,11 @@
 ''');
     HoverInformation hover = await prepareHover('fff(int a');
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName, 'bin/test.dart');
     expect(hover.containingLibraryPath, testFile);
     expect(hover.containingClassDescription, isNull);
     expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
-    expect(hover.elementDescription, 'fff(int a, String b) → List<String>');
+    expect(hover.elementDescription, 'List<String> fff(int a, String b)');
     expect(hover.elementKind, 'function');
     // types
     expect(hover.staticType, isNull);
@@ -356,7 +357,7 @@
 ''');
     HoverInformation hover = await prepareHover('fff);');
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName, 'bin/test.dart');
     expect(hover.containingLibraryPath, testFile);
     expect(hover.containingClassDescription, 'A');
     expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
@@ -494,11 +495,11 @@
 ''');
     HoverInformation hover = await prepareHover('mmm(int a');
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName, 'bin/test.dart');
     expect(hover.containingLibraryPath, testFile);
     expect(hover.containingClassDescription, 'A');
     expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
-    expect(hover.elementDescription, 'mmm(int a, String b) → List<String>');
+    expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
     expect(hover.elementKind, 'method');
     // types
     expect(hover.staticType, isNull);
@@ -523,13 +524,13 @@
     expect(hover.offset, findOffset('mmm(42, '));
     expect(hover.length, 'mmm'.length);
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName, 'bin/test.dart');
     expect(hover.containingLibraryPath, testFile);
-    expect(hover.elementDescription, 'mmm(int a, String b) → List<String>');
+    expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
     expect(hover.elementKind, 'method');
     expect(hover.isDeprecated, isFalse);
     // types
-    expect(hover.staticType, '(int, String) → List<String>');
+    expect(hover.staticType, 'List<String> Function(int, String)');
     expect(hover.propagatedType, isNull);
     // no parameter
     expect(hover.parameter, isNull);
@@ -548,7 +549,7 @@
     HoverInformation hover = await prepareHover('test();');
     // element
     expect(hover.containingLibraryPath, testFile);
-    expect(hover.elementDescription, 'test() → void');
+    expect(hover.elementDescription, 'void test()');
     expect(hover.elementKind, 'method');
     expect(hover.isDeprecated, isTrue);
   }
@@ -571,15 +572,15 @@
     expect(hover.offset, findOffset('transform(n'));
     expect(hover.length, 'transform'.length);
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName, 'bin/test.dart');
     expect(hover.containingLibraryPath, testFile);
     expect(hover.elementDescription,
-        'Stream.transform<S>(StreamTransformer<int, S> streamTransformer) → Stream<S>');
+        'Stream<S> Stream.transform<S>(StreamTransformer<int, S> streamTransformer)');
     expect(hover.elementKind, 'method');
     expect(hover.isDeprecated, isFalse);
     // types
     expect(hover.staticType,
-        '(StreamTransformer<int, dynamic>) → Stream<dynamic>');
+        'Stream<dynamic> Function(StreamTransformer<int, dynamic>)');
     expect(hover.propagatedType, isNull);
     // no parameter
     expect(hover.parameter, isNull);
diff --git a/pkg/analysis_server/test/analysis/notification_errors_test.dart b/pkg/analysis_server/test/analysis/notification_errors_test.dart
index ffec72b..d344bc9 100644
--- a/pkg/analysis_server/test/analysis/notification_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_errors_test.dart
@@ -29,6 +29,12 @@
     if (notification.event == ANALYSIS_NOTIFICATION_ERRORS) {
       var decoded = new AnalysisErrorsParams.fromNotification(notification);
       filesErrors[decoded.file] = decoded.errors;
+    } else if (notification.event == ANALYSIS_NOTIFICATION_FLUSH_RESULTS) {
+      var decoded =
+          new AnalysisFlushResultsParams.fromNotification(notification);
+      for (var file in decoded.files) {
+        filesErrors[file] = null;
+      }
     }
   }
 
@@ -125,6 +131,55 @@
     expect(errors, isNull);
   }
 
+  test_dotFolder_priority() async {
+    // Files inside dotFolders should not generate error notifications even
+    // if they are added to priority (priority affects only priority, not what
+    // is analyzed).
+    createProject();
+    addTestFile('');
+    String brokenFile =
+        newFile(join(projectPath, '.dart_tool/broken.dart'), content: 'err')
+            .path;
+
+    await waitForTasksFinished();
+    await pumpEventQueue(times: 5000);
+    expect(filesErrors[brokenFile], isNull);
+
+    // Add to priority files and give chance for the file to be analyzed (if
+    // it would).
+    await setPriorityFiles([brokenFile]);
+    await waitForTasksFinished();
+    await pumpEventQueue(times: 5000);
+
+    // There should still be no errors.
+    expect(filesErrors[brokenFile], isNull);
+  }
+
+  test_dotFolder_unopenedFile() async {
+    // Files inside dotFolders are not analyzed. Sending requests that cause
+    // them to be opened (such as hovers) should not result in error notifications
+    // because there is no event that would flush them and they'd remain in the
+    // editor forever.
+    createProject();
+    addTestFile('');
+    String brokenFile =
+        newFile(join(projectPath, '.dart_tool/broken.dart'), content: 'err')
+            .path;
+
+    await waitForTasksFinished();
+    await pumpEventQueue(times: 5000);
+    expect(filesErrors[brokenFile], isNull);
+
+    // Send a getHover request for the file that will cause it to be read from disk.
+    await waitResponse(
+        new AnalysisGetHoverParams(brokenFile, 0).toRequest('0'));
+    await waitForTasksFinished();
+    await pumpEventQueue(times: 5000);
+
+    // There should be no errors because the file is not being analyzed.
+    expect(filesErrors[brokenFile], isNull);
+  }
+
   test_importError() async {
     createProject();
 
@@ -191,6 +246,108 @@
     expect(filesErrors[otherFile], isNull);
   }
 
+  test_overlay_dotFolder() async {
+    // Files inside dotFolders should not generate error notifications even
+    // if they have overlays added.
+    createProject();
+    addTestFile('');
+    String brokenFile =
+        newFile(join(projectPath, '.dart_tool/broken.dart'), content: 'err')
+            .path;
+
+    await waitForTasksFinished();
+    await pumpEventQueue(times: 5000);
+    expect(filesErrors[brokenFile], isNull);
+
+    // Add and overlay and give chance for the file to be analyzed (if
+    // it would).
+    await waitResponse(
+      new AnalysisUpdateContentParams({
+        brokenFile: new AddContentOverlay('err'),
+      }).toRequest('1'),
+    );
+    await waitForTasksFinished();
+    await pumpEventQueue(times: 5000);
+
+    // There should still be no errors.
+    expect(filesErrors[brokenFile], isNull);
+  }
+
+  test_overlay_newFile() async {
+    // Overlays added for files that don't exist on disk should still generate
+    // error notifications. Removing the overlay if the file is not on disk
+    // should clear the errors.
+    createProject();
+    addTestFile('');
+    String brokenFile = convertPath(join(projectPath, 'broken.dart'));
+
+    // Add and overlay and give chance for the file to be analyzed.
+    await waitResponse(
+      new AnalysisUpdateContentParams({
+        brokenFile: new AddContentOverlay('err'),
+      }).toRequest('0'),
+    );
+    await waitForTasksFinished();
+    await pumpEventQueue(times: 5000);
+
+    // There should now be errors.
+    expect(filesErrors[brokenFile], hasLength(greaterThan(0)));
+
+    // Remove the overlay (this file no longer exists anywhere).
+    await waitResponse(
+      new AnalysisUpdateContentParams({
+        brokenFile: new RemoveContentOverlay(),
+      }).toRequest('1'),
+    );
+    await waitForTasksFinished();
+    await pumpEventQueue(times: 5000);
+
+    // Unlike other tests here, removing an overlay for a file that doesn't exist
+    // on disk doesn't flush errors, but re-analyzes the missing file, which results
+    // in an error notification of 0 errors rather than a flush.
+    expect(filesErrors[brokenFile], isEmpty);
+  }
+
+  test_overlay_newFileSavedBeforeRemoving() async {
+    // Overlays added for files that don't exist on disk should still generate
+    // error notifications. If the file is subsequently saved to disk before the
+    // overlay is removed, the errors should not be flushed when the overlay is
+    // removed.
+    createProject();
+    addTestFile('');
+    String brokenFile = convertPath(join(projectPath, 'broken.dart'));
+
+    // Add and overlay and give chance for the file to be analyzed.
+    await waitResponse(
+      new AnalysisUpdateContentParams({
+        brokenFile: new AddContentOverlay('err'),
+      }).toRequest('0'),
+    );
+    await waitForTasksFinished();
+    await pumpEventQueue(times: 5000);
+
+    // There should now be errors.
+    expect(filesErrors[brokenFile], hasLength(greaterThan(0)));
+
+    // Write the file to disk.
+    newFile(brokenFile, content: 'err');
+    await waitForTasksFinished();
+    await pumpEventQueue(times: 5000);
+
+    // Remove the overlay.
+    await waitResponse(
+      new AnalysisUpdateContentParams({
+        brokenFile: new RemoveContentOverlay(),
+      }).toRequest('1'),
+    );
+    await waitForTasksFinished();
+    await pumpEventQueue(times: 5000);
+
+    // Errors should not have been flushed since the file still exists without
+    // the overlay.
+    expect(filesErrors[brokenFile], hasLength(greaterThan(0)));
+  }
+
   test_ParserError() async {
     createProject();
     addTestFile('library lib');
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index a7c001b..95bea0d 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -17,6 +17,7 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(AnalysisNotificationHighlightsTest);
     defineReflectiveTests(HighlightsWithControlFlowCollectionsTest);
+    defineReflectiveTests(HighlightsWithNnbdTest);
     defineReflectiveTests(HighlightTypeTest);
   });
 }
@@ -1303,6 +1304,37 @@
 }
 
 @reflectiveTest
+class HighlightsWithNnbdTest extends HighlightsTestSupport {
+  @override
+  void createProject({Map<String, String> packageRoots}) {
+    addAnalysisOptionsFile('''
+analyzer:
+  enable-experiment:
+    - non-nullable
+''');
+    super.createProject(packageRoots: packageRoots);
+  }
+
+  test_KEYWORD_late() async {
+    addTestFile('''
+class C {
+  late int x;
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'late');
+  }
+
+  test_KEYWORD_required() async {
+    addTestFile('''
+void f({required int x}) {}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'required');
+  }
+}
+
+@reflectiveTest
 class HighlightTypeTest {
   void test_constructor() {
     expect(HighlightRegionType.CLASS,
diff --git a/pkg/analysis_server/test/analysis/notification_highlights_test.dart b/pkg/analysis_server/test/analysis/notification_highlights_test.dart
index 78517c2..154bad5 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights_test.dart
@@ -17,6 +17,7 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(AnalysisNotificationHighlightsTest);
     defineReflectiveTests(HighlightsWithControlFlowCollectionsTest);
+    defineReflectiveTests(HighlightsWithNnbdTest);
     defineReflectiveTests(HighlightTypeTest);
   });
 }
@@ -1152,6 +1153,37 @@
 }
 
 @reflectiveTest
+class HighlightsWithNnbdTest extends HighlightsTestSupport {
+  @override
+  void createProject({Map<String, String> packageRoots}) {
+    addAnalysisOptionsFile('''
+analyzer:
+  enable-experiment:
+    - non-nullable
+''');
+    super.createProject(packageRoots: packageRoots);
+  }
+
+  test_KEYWORD_late() async {
+    addTestFile('''
+class C {
+  late int x;
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'late');
+  }
+
+  test_KEYWORD_required() async {
+    addTestFile('''
+void f({required int x}) {}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'required');
+  }
+}
+
+@reflectiveTest
 class HighlightTypeTest {
   void test_constructor() {
     expect(HighlightRegionType.CLASS,
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index f4593b4..22715a4 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -135,6 +135,12 @@
     handleSuccessfulRequest(request, handler: analysisHandler);
   }
 
+  void doAllDeclarationsTrackerWork() {
+    while (server.declarationsTracker.hasWork) {
+      server.declarationsTracker.doWork();
+    }
+  }
+
   /**
    * Returns the offset of [search] in [testCode].
    * Fails if not found.
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 88938f1..228ec3f 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -18,6 +18,7 @@
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
 import 'package:analyzer/src/generated/sdk.dart';
@@ -1978,8 +1979,9 @@
     String sdkExtPath = '$projPath/sdk_ext';
     newFile('$projPath/test', content: 'test.dart');
     newFile('$sdkExtPath/entry.dart');
+    var synchronousSession = SynchronousSession(analysisOptions, null);
     List<int> bytes = new SummaryBuilder(
-            [], RestrictedAnalysisContext(analysisOptions, null, null))
+            [], RestrictedAnalysisContext(synchronousSession, null))
         .build();
     newFileWithBytes('$projPath/sdk.ds', bytes);
     // Setup _embedder.yaml.
@@ -2517,6 +2519,9 @@
   void afterWatchEvent(WatchEvent event) {}
 
   @override
+  void analysisOptionsUpdated(AnalysisDriver driver) {}
+
+  @override
   void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
     AnalysisDriver driver = driverMap[contextFolder.path];
     if (driver != null) {
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index 2fa8a24..22a7245 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -40,6 +40,7 @@
 }
 ''');
     await waitForTasksFinished();
+    doAllDeclarationsTrackerWork();
     List<AnalysisErrorFixes> errorFixes =
         await _getFixesAt('Completer<String>');
     expect(errorFixes, hasLength(1));
@@ -133,17 +134,20 @@
   }
 
   test_suggestImportFromDifferentAnalysisRoot() async {
-    String asFileUri(String input) =>
-        new Uri.file(convertPath(input)).toString();
     newFolder('/aaa');
     newFile('/aaa/.packages', content: '''
-aaa:${asFileUri('/aaa/lib')}
-bbb:${asFileUri('/bbb/lib')}
+aaa:${toUri('/aaa/lib')}
+bbb:${toUri('/bbb/lib')}
 ''');
-    // Ensure that the target is analyzed as an implicit source.
-    newFile('/aaa/lib/foo.dart', content: 'import "package:bbb/target.dart";');
+    newFile('/aaa/pubspec.yaml', content: r'''
+dependencies:
+  bbb: any
+''');
 
     newFolder('/bbb');
+    newFile('/bbb/.packages', content: '''
+bbb:${toUri('/bbb/lib')}
+''');
     newFile('/bbb/lib/target.dart', content: 'class Foo() {}');
 
     handleSuccessfulRequest(
@@ -157,6 +161,7 @@
     _addOverlay(testFile, testCode);
 
     await waitForTasksFinished();
+    doAllDeclarationsTrackerWork();
 
     List<String> fixes = (await _getFixesAt('Foo()'))
         .single
diff --git a/pkg/analysis_server/test/edit/test_all.dart b/pkg/analysis_server/test/edit/test_all.dart
index 70251a6..62595d3 100644
--- a/pkg/analysis_server/test/edit/test_all.dart
+++ b/pkg/analysis_server/test/edit/test_all.dart
@@ -12,6 +12,7 @@
 import 'refactoring_test.dart' as refactoring;
 import 'sort_members_test.dart' as sort_members;
 import 'statement_completion_test.dart' as statement_completion;
+import 'token_details_test.dart' as token_details;
 
 main() {
   defineReflectiveSuite(() {
@@ -23,5 +24,6 @@
     refactoring.main();
     sort_members.main();
     statement_completion.main();
+    token_details.main();
   }, name: 'edit');
 }
diff --git a/pkg/analysis_server/test/edit/token_details_test.dart b/pkg/analysis_server/test/edit/token_details_test.dart
new file mode 100644
index 0000000..5d1be56
--- /dev/null
+++ b/pkg/analysis_server/test/edit/token_details_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2019, 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:analysis_server/protocol/protocol.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/domain_completion.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../analysis_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(CompletionListTokenDetailsTest);
+  });
+}
+
+@reflectiveTest
+class CompletionListTokenDetailsTest extends AbstractAnalysisTest {
+  CompletionDomainHandler completionHandler;
+
+  Future<CompletionListTokenDetailsResult> getTokenDetails() async {
+    CompletionListTokenDetailsParams params =
+        new CompletionListTokenDetailsParams(testFile);
+    await completionHandler.listTokenDetails(params.toRequest('0'));
+    Response response = await serverChannel.responseController.stream.first;
+    return CompletionListTokenDetailsResult.fromResponse(response);
+  }
+
+  @override
+  void setUp() {
+    super.setUp();
+    completionHandler = new CompletionDomainHandler(server);
+  }
+
+  test_packageUri() async {
+    newFile('/project/.packages', content: ''''
+project:lib/
+''');
+    newFile('/project/lib/c.dart', content: ''''
+class C {}
+''');
+    addTestFile('''
+import 'package:project/c.dart';
+
+C c;
+''');
+    createProject();
+    CompletionListTokenDetailsResult result = await getTokenDetails();
+    List<TokenDetails> tokens = result.tokens;
+    expect(tokens, hasLength(6));
+  }
+}
diff --git a/pkg/analysis_server/test/integration/analysis/error_test.dart b/pkg/analysis_server/test/integration/analysis/error_test.dart
index 0a7948b..7d5cd76 100644
--- a/pkg/analysis_server/test/integration/analysis/error_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/error_test.dart
@@ -18,6 +18,24 @@
 @reflectiveTest
 class AnalysisErrorIntegrationTest
     extends AbstractAnalysisServerIntegrationTest {
+  test_analysisRootDoesNotExist() async {
+    String packagePath = sourcePath('package');
+    String filePath = sourcePath('package/lib/test.dart');
+    String content = '''
+main() {
+  print(null) // parse error: missing ';'
+}''';
+    await sendServerSetSubscriptions([ServerService.STATUS]);
+    await sendAnalysisUpdateContent({filePath: AddContentOverlay(content)});
+    await sendAnalysisSetAnalysisRoots([packagePath], []);
+    await analysisFinished;
+
+    expect(currentAnalysisErrors[filePath], isList);
+    List<AnalysisError> errors = currentAnalysisErrors[filePath];
+    expect(errors, hasLength(1));
+    expect(errors[0].location.file, equals(filePath));
+  }
+
   test_detect_simple_error() {
     String pathname = sourcePath('test.dart');
     writeFile(pathname, '''
diff --git a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
index e2f25af..ae7e4db 100644
--- a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
@@ -81,13 +81,13 @@
       expect(info.length, equals(length));
       if (isCore) {
         expect(path.basename(info.containingLibraryPath), equals('core.dart'));
-        expect(info.containingLibraryName, equals('dart.core'));
+        expect(info.containingLibraryName, equals('dart:core'));
       } else if (isLocal || isLiteral) {
         expect(info.containingLibraryPath, isNull);
         expect(info.containingLibraryName, isNull);
       } else {
         expect(info.containingLibraryPath, equals(pathname));
-        expect(info.containingLibraryName, equals('lib.test'));
+        expect(info.containingLibraryName, isNotNull);
       }
       if (docRegexp == null) {
         expect(info.dartdoc, isNull);
diff --git a/pkg/analysis_server/test/integration/completion/list_token_details_test.dart b/pkg/analysis_server/test/integration/completion/list_token_details_test.dart
new file mode 100644
index 0000000..04df740
--- /dev/null
+++ b/pkg/analysis_server/test/integration/completion/list_token_details_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, 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:analysis_server/protocol/protocol_generated.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../support/integration_tests.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ListTokenDetailsTest);
+  });
+}
+
+@reflectiveTest
+class ListTokenDetailsTest extends AbstractAnalysisServerIntegrationTest {
+  String testPackagePath;
+
+  Future setUp() async {
+    await super.setUp();
+    testPackagePath = path.join(sourceDirectory.path, 'test_package');
+  }
+
+  @override
+  Future standardAnalysisSetup({bool subscribeStatus: true}) {
+    List<Future> futures = <Future>[];
+    if (subscribeStatus) {
+      futures.add(sendServerSetSubscriptions([ServerService.STATUS]));
+    }
+    futures.add(sendAnalysisSetAnalysisRoots([testPackagePath], []));
+    return Future.wait(futures);
+  }
+
+  test_getSuggestions() async {
+    String aPath = path.join(sourceDirectory.path, 'a');
+    String aLibPath = path.join(aPath, 'lib');
+    writeFile(path.join(aLibPath, 'a.dart'), '''
+class A {}
+''');
+    writeFile(path.join(testPackagePath, '.packages'), '''
+a:file://$aLibPath
+test_package:lib/
+''');
+    String testFilePath = path.join(testPackagePath, 'lib', 'test.dart');
+    writeFile(testFilePath, '''
+import 'package:a/a.dart';
+class B {}
+String f(A a, B b) => a.toString() + b.toString();
+''');
+    await standardAnalysisSetup();
+    await analysisFinished;
+
+    CompletionListTokenDetailsResult result =
+        await sendCompletionListTokenDetails(testFilePath);
+    expect(result, isNotNull);
+  }
+}
diff --git a/pkg/analysis_server/test/integration/completion/test_all.dart b/pkg/analysis_server/test/integration/completion/test_all.dart
index 1b5962b..11ed77f 100644
--- a/pkg/analysis_server/test/integration/completion/test_all.dart
+++ b/pkg/analysis_server/test/integration/completion/test_all.dart
@@ -4,13 +4,12 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'get_suggestions_test.dart' as get_suggestions_test;
+import 'get_suggestions_test.dart' as get_suggestions;
+import 'list_token_details_test.dart' as list_token_details;
 
-/**
- * Utility for manually running all integration tests.
- */
 main() {
   defineReflectiveSuite(() {
-    get_suggestions_test.main();
+    get_suggestions.main();
+    list_token_details.main();
   }, name: 'completion');
 }
diff --git a/pkg/analysis_server/test/integration/coverage.md b/pkg/analysis_server/test/integration/coverage.md
index 1728314..6df0629 100644
--- a/pkg/analysis_server/test/integration/coverage.md
+++ b/pkg/analysis_server/test/integration/coverage.md
@@ -31,9 +31,10 @@
 
 ## completion domain
 - [ ] completion.availableSuggestions
+- [ ] completion.existingImports
 - [ ] completion.getSuggestionDetails
 - [x] completion.getSuggestions
-- [ ] completion.listTokenDetails
+- [x] completion.listTokenDetails
 - [ ] completion.registerLibraryPaths
 - [ ] completion.results
 - [ ] completion.setSubscriptions
diff --git a/pkg/analysis_server/test/integration/linter/lint_names_test.dart b/pkg/analysis_server/test/integration/linter/lint_names_test.dart
index 1a515bf..929a9c0 100644
--- a/pkg/analysis_server/test/integration/linter/lint_names_test.dart
+++ b/pkg/analysis_server/test/integration/linter/lint_names_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:io';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/error/error.dart';
@@ -66,11 +67,14 @@
     var reader = new CharSequenceReader(contents);
     var stringSource = new StringSource(contents, name);
     var errorListener = new _ErrorListener();
-    var scanner = new Scanner(stringSource, reader, errorListener);
+    var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
+    var scanner = new Scanner(stringSource, reader, errorListener)
+      ..configureFeatures(featureSet);
     var startToken = scanner.tokenize();
     errorListener.throwIfErrors();
 
-    var parser = new Parser(stringSource, errorListener);
+    var parser =
+        new Parser(stringSource, errorListener, featureSet: featureSet);
     var cu = parser.parseCompilationUnit(startToken);
     errorListener.throwIfErrors();
 
diff --git a/pkg/analysis_server/test/integration/lsp_server/analyzer_status_test.dart b/pkg/analysis_server/test/integration/lsp_server/analyzer_status_test.dart
new file mode 100644
index 0000000..bff7062
--- /dev/null
+++ b/pkg/analysis_server/test/integration/lsp_server/analyzer_status_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2019, 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:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'integration_tests.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AnalyzerStatusTest);
+  });
+}
+
+@reflectiveTest
+class AnalyzerStatusTest extends AbstractLspAnalysisServerIntegrationTest {
+  test_afterInitialize() async {
+    const initialContents = 'int a = 1;';
+    newFile(mainFilePath, content: initialContents);
+
+    // To avoid races, set up listeners for the notifications before we initialise
+    // and track which event came first to ensure they arrived in the expected
+    // order.
+    bool firstNotificationWasAnalyzing = null;
+    final startNotification = waitForAnalysisStart()
+        .then((_) => firstNotificationWasAnalyzing ??= true);
+    final completeNotification = waitForAnalysisComplete()
+        .then((_) => firstNotificationWasAnalyzing ??= false);
+
+    await initialize();
+    await startNotification;
+    await completeNotification;
+
+    expect(firstNotificationWasAnalyzing, isTrue);
+  }
+
+  test_afterDocumentEdits() async {
+    const initialContents = 'int a = 1;';
+    newFile(mainFilePath, content: initialContents);
+
+    final initialAnalysis = waitForAnalysisComplete();
+
+    await initialize();
+    await initialAnalysis;
+
+    // Set up futures to wait for the new events.
+    final startNotification = waitForAnalysisStart();
+    final completeNotification = waitForAnalysisComplete();
+
+    // Send a modification
+    await openFile(mainFileUri, initialContents);
+    await replaceFile(222, mainFileUri, 'String a = 1;');
+
+    // Ensure the notifications come through again.
+    await startNotification;
+    await completeNotification;
+  }
+}
diff --git a/pkg/analysis_server/test/integration/lsp_server/diagnostic_test.dart b/pkg/analysis_server/test/integration/lsp_server/diagnostic_test.dart
new file mode 100644
index 0000000..40e2ff6
--- /dev/null
+++ b/pkg/analysis_server/test/integration/lsp_server/diagnostic_test.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2019, 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:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'integration_tests.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DiagnosticTest);
+  });
+}
+
+@reflectiveTest
+class DiagnosticTest extends AbstractLspAnalysisServerIntegrationTest {
+  test_initialAnalysis() async {
+    newFile(mainFilePath, content: 'String a = 1;');
+
+    final diagnosticsUpdate = waitForDiagnostics(mainFileUri);
+    await initialize();
+    final diagnostics = await diagnosticsUpdate;
+    expect(diagnostics, hasLength(1));
+    final diagnostic = diagnostics.first;
+    expect(diagnostic.code, equals('invalid_assignment'));
+    expect(diagnostic.range.start.line, equals(0));
+    expect(diagnostic.range.start.character, equals(11));
+    expect(diagnostic.range.end.line, equals(0));
+    expect(diagnostic.range.end.character, equals(12));
+  }
+
+  test_lints() async {
+    newFile(mainFilePath, content: '''main() async => await 1;''');
+    newFile(analysisOptionsPath, content: '''
+linter:
+  rules:
+    - await_only_futures
+    ''');
+
+    final diagnosticsUpdate = waitForDiagnostics(mainFileUri);
+    await initialize();
+    final diagnostics = await diagnosticsUpdate;
+    expect(diagnostics, hasLength(1));
+    final diagnostic = diagnostics.first;
+    expect(diagnostic.code, equals('await_only_futures'));
+    expect(diagnostic.range.start.line, equals(0));
+    expect(diagnostic.range.start.character, equals(16));
+    expect(diagnostic.range.end.line, equals(0));
+    expect(diagnostic.range.end.character, equals(21));
+  }
+}
diff --git a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
index f8a1713..aac6231 100644
--- a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
@@ -9,16 +9,12 @@
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/src/lsp/channel/lsp_byte_stream_channel.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:path/path.dart';
 
 import '../../lsp/server_abstract.dart';
 
 class AbstractLspAnalysisServerIntegrationTest
-    with
-        ResourceProviderMixin,
-        ClientCapabilitiesHelperMixin,
-        LspAnalysisServerTestMixin {
+    with ClientCapabilitiesHelperMixin, LspAnalysisServerTestMixin {
   LspServerClient client;
 
   final Map<int, Completer<ResponseMessage>> _completers = {};
@@ -49,6 +45,11 @@
     }
   }
 
+  newFile(String path, {String content}) =>
+      File(path).writeAsStringSync(content ?? '');
+
+  newFolder(String path) => Directory(path).createSync(recursive: true);
+
   @override
   void sendNotificationToServer(NotificationMessage notification) =>
       client.channel.sendNotification(notification);
@@ -74,7 +75,13 @@
     projectFolderPath = Directory.systemTemp
         .createTempSync('analysisServer')
         .resolveSymbolicLinksSync();
+    newFolder(projectFolderPath);
+    newFolder(join(projectFolderPath, 'lib'));
     projectFolderUri = Uri.file(projectFolderPath);
+    mainFilePath = join(projectFolderPath, 'lib', 'main.dart');
+    mainFileUri = Uri.file(mainFilePath);
+    analysisOptionsPath = join(projectFolderPath, 'analysis_options.yaml');
+    analysisOptionsUri = Uri.file(analysisOptionsPath);
 
     client = new LspServerClient();
     await client.start();
diff --git a/pkg/analysis_server/test/integration/lsp_server/test_all.dart b/pkg/analysis_server/test/integration/lsp_server/test_all.dart
index 7f67613..b171d0a 100644
--- a/pkg/analysis_server/test/integration/lsp_server/test_all.dart
+++ b/pkg/analysis_server/test/integration/lsp_server/test_all.dart
@@ -4,11 +4,15 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'analyzer_status_test.dart' as analyzer_status;
+import 'diagnostic_test.dart' as diagnostic_test;
 import 'initialization_test.dart' as initialization_test;
 import 'server_test.dart' as server_test;
 
 main() {
   defineReflectiveSuite(() {
+    analyzer_status.main();
+    diagnostic_test.main();
     initialization_test.main();
     server_test.main();
   }, name: 'lsp integration');
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index fe67037..cd4df3d 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -1219,6 +1219,14 @@
    *   True if this is that last set of results that will be returned for the
    *   indicated completion.
    *
+   * libraryFile: FilePath (optional)
+   *
+   *   The library file that contains the file where completion was requested.
+   *   The client might use it for example together with the existingImports
+   *   notification to filter out available suggestions. If there were changes
+   *   to existing imports in the library, the corresponding existingImports
+   *   notification will be sent before the completion notification.
+   *
    * includedSuggestionSets: List<IncludedSuggestionSet> (optional)
    *
    *   References to AvailableSuggestionSet objects previously sent to the
@@ -1279,6 +1287,29 @@
       _onCompletionAvailableSuggestions;
 
   /**
+   * Reports existing imports in a library. This notification may be sent
+   * multiple times for a library. When a notification is processed, clients
+   * should replace any previous information for the library.
+   *
+   * Parameters
+   *
+   * file: FilePath
+   *
+   *   The defining file of the library.
+   *
+   * imports: ExistingImports
+   *
+   *   The existing imports in the library.
+   */
+  Stream<CompletionExistingImportsParams> onCompletionExistingImports;
+
+  /**
+   * Stream controller for [onCompletionExistingImports].
+   */
+  StreamController<CompletionExistingImportsParams>
+      _onCompletionExistingImports;
+
+  /**
    * Perform a search for references to the element defined or referenced at
    * the given offset in the given file.
    *
@@ -1744,6 +1775,14 @@
    * edits: List<SourceFileEdit>
    *
    *   A list of source edits to apply the recommended changes.
+   *
+   * details: List<String> (optional)
+   *
+   *   Messages that should be displayed to the user that describe details of
+   *   the fix generation. For example, the messages might (a) point out
+   *   details that users might want to explore before committing the changes
+   *   or (b) describe exceptions that were thrown but that did not stop the
+   *   fixes from being produced. The list will be omitted if it is empty.
    */
   Future<EditDartfixResult> sendEditDartfix(List<String> included,
       {List<String> includedFixes,
@@ -2702,6 +2741,10 @@
         new StreamController<CompletionAvailableSuggestionsParams>(sync: true);
     onCompletionAvailableSuggestions =
         _onCompletionAvailableSuggestions.stream.asBroadcastStream();
+    _onCompletionExistingImports =
+        new StreamController<CompletionExistingImportsParams>(sync: true);
+    onCompletionExistingImports =
+        _onCompletionExistingImports.stream.asBroadcastStream();
     _onSearchResults = new StreamController<SearchResultsParams>(sync: true);
     onSearchResults = _onSearchResults.stream.asBroadcastStream();
     _onExecutionLaunchData =
@@ -2804,6 +2847,12 @@
             new CompletionAvailableSuggestionsParams.fromJson(
                 decoder, 'params', params));
         break;
+      case "completion.existingImports":
+        outOfTestExpect(params, isCompletionExistingImportsParams);
+        _onCompletionExistingImports.add(
+            new CompletionExistingImportsParams.fromJson(
+                decoder, 'params', params));
+        break;
       case "search.results":
         outOfTestExpect(params, isSearchResultsParams);
         _onSearchResults
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index ec50cf1..2dc3198 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -35,6 +35,7 @@
  *   "correction": optional String
  *   "code": String
  *   "url": optional String
+ *   "contextMessages": optional List<DiagnosticMessage>
  *   "hasFix": optional bool
  * }
  */
@@ -48,6 +49,7 @@
         }, optionalFields: {
           "correction": isString,
           "url": isString,
+          "contextMessages": isListOf(isDiagnosticMessage),
           "hasFix": isBool
         }));
 
@@ -170,6 +172,7 @@
  *
  * {
  *   "label": String
+ *   "declaringLibraryUri": String
  *   "element": Element
  *   "defaultArgumentListString": optional String
  *   "defaultArgumentListTextRanges": optional List<int>
@@ -184,6 +187,7 @@
 final Matcher isAvailableSuggestion =
     new LazyMatcher(() => new MatchesJsonObject("AvailableSuggestion", {
           "label": isString,
+          "declaringLibraryUri": isString,
           "element": isElement
         }, optionalFields: {
           "defaultArgumentListString": isString,
@@ -387,6 +391,17 @@
     optionalFields: {"location": isLocation}));
 
 /**
+ * DiagnosticMessage
+ *
+ * {
+ *   "message": String
+ *   "location": Location
+ * }
+ */
+final Matcher isDiagnosticMessage = new LazyMatcher(() => new MatchesJsonObject(
+    "DiagnosticMessage", {"message": isString, "location": isLocation}));
+
+/**
  * Element
  *
  * {
@@ -547,6 +562,29 @@
     new MatchesEnum("ExecutionService", ["LAUNCH_DATA"]);
 
 /**
+ * ExistingImport
+ *
+ * {
+ *   "uri": int
+ *   "elements": List<int>
+ * }
+ */
+final Matcher isExistingImport = new LazyMatcher(() => new MatchesJsonObject(
+    "ExistingImport", {"uri": isInt, "elements": isListOf(isInt)}));
+
+/**
+ * ExistingImports
+ *
+ * {
+ *   "elements": ImportedElementSet
+ *   "imports": List<ExistingImport>
+ * }
+ */
+final Matcher isExistingImports = new LazyMatcher(() => new MatchesJsonObject(
+    "ExistingImports",
+    {"elements": isImportedElementSet, "imports": isListOf(isExistingImport)}));
+
+/**
  * FileKind
  *
  * enum {
@@ -935,6 +973,22 @@
     "ImplementedMember", {"offset": isInt, "length": isInt}));
 
 /**
+ * ImportedElementSet
+ *
+ * {
+ *   "strings": List<String>
+ *   "uris": List<int>
+ *   "names": List<int>
+ * }
+ */
+final Matcher isImportedElementSet = new LazyMatcher(() =>
+    new MatchesJsonObject("ImportedElementSet", {
+      "strings": isListOf(isString),
+      "uris": isListOf(isInt),
+      "names": isListOf(isInt)
+    }));
+
+/**
  * ImportedElements
  *
  * {
@@ -2179,6 +2233,18 @@
         }));
 
 /**
+ * completion.existingImports params
+ *
+ * {
+ *   "file": FilePath
+ *   "imports": ExistingImports
+ * }
+ */
+final Matcher isCompletionExistingImportsParams = new LazyMatcher(() =>
+    new MatchesJsonObject("completion.existingImports params",
+        {"file": isFilePath, "imports": isExistingImports}));
+
+/**
  * completion.getSuggestionDetails params
  *
  * {
@@ -2275,6 +2341,7 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "libraryFile": optional FilePath
  *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
  *   "includedElementKinds": optional List<ElementKind>
  *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -2288,6 +2355,7 @@
           "results": isListOf(isCompletionSuggestion),
           "isLast": isBool
         }, optionalFields: {
+          "libraryFile": isFilePath,
           "includedSuggestionSets": isListOf(isIncludedSuggestionSet),
           "includedElementKinds": isListOf(isElementKind),
           "includedSuggestionRelevanceTags":
@@ -2388,6 +2456,7 @@
  *   "otherSuggestions": List<DartFixSuggestion>
  *   "hasErrors": bool
  *   "edits": List<SourceFileEdit>
+ *   "details": optional List<String>
  * }
  */
 final Matcher isEditDartfixResult =
@@ -2396,6 +2465,8 @@
           "otherSuggestions": isListOf(isDartFixSuggestion),
           "hasErrors": isBool,
           "edits": isListOf(isSourceFileEdit)
+        }, optionalFields: {
+          "details": isListOf(isString)
         }));
 
 /**
diff --git a/pkg/analysis_server/test/lsp/analyzer_status_test.dart b/pkg/analysis_server/test/lsp/analyzer_status_test.dart
new file mode 100644
index 0000000..1f5859c
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/analyzer_status_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2019, 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:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AnalyzerStatusTest);
+  });
+}
+
+@reflectiveTest
+class AnalyzerStatusTest extends AbstractLspAnalysisServerTest {
+  test_afterInitialize() async {
+    const initialContents = 'int a = 1;';
+    newFile(mainFilePath, content: initialContents);
+
+    // To avoid races, set up listeners for the notifications before we initialise
+    // and track which event came first to ensure they arrived in the expected
+    // order.
+    bool firstNotificationWasAnalyzing = null;
+    final startNotification = waitForAnalysisStart()
+        .then((_) => firstNotificationWasAnalyzing ??= true);
+    final completeNotification = waitForAnalysisComplete()
+        .then((_) => firstNotificationWasAnalyzing ??= false);
+
+    await initialize();
+    await startNotification;
+    await completeNotification;
+
+    expect(firstNotificationWasAnalyzing, isTrue);
+  }
+
+  test_afterDocumentEdits() async {
+    const initialContents = 'int a = 1;';
+    newFile(mainFilePath, content: initialContents);
+
+    final initialAnalysis = waitForAnalysisComplete();
+
+    await initialize();
+    await initialAnalysis;
+
+    // Set up futures to wait for the new events.
+    final startNotification = waitForAnalysisStart();
+    final completeNotification = waitForAnalysisComplete();
+
+    // Send a modification
+    await openFile(mainFileUri, initialContents);
+    await replaceFile(222, mainFileUri, 'String a = 1;');
+
+    // Ensure the notifications come through again.
+    await startNotification;
+    await completeNotification;
+  }
+}
diff --git a/pkg/analysis_server/test/lsp/cancel_request_test.dart b/pkg/analysis_server/test/lsp/cancel_request_test.dart
new file mode 100644
index 0000000..033f671
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/cancel_request_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../tool/lsp_spec/matchers.dart';
+import 'server_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(CancelRequestTest);
+  });
+}
+
+@reflectiveTest
+class CancelRequestTest extends AbstractLspAnalysisServerTest {
+  test_cancel() async {
+    final content = '''
+main() {
+  InOtherF^
+}
+    ''';
+
+    final initialAnalysis = waitForAnalysisComplete();
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    await initialAnalysis;
+
+    // Create a completion request that we'll cancel.
+    final completionRequest = makeRequest(
+      Method.textDocument_completion,
+      new CompletionParams(
+        null,
+        new TextDocumentIdentifier(mainFileUri.toString()),
+        positionFromMarker(content),
+      ),
+    );
+    // And a request to cancel it.
+    final cancelNotification = makeNotification(
+        Method.cancelRequest, new CancelParams(completionRequest.id));
+
+    // Send both (without waiting for the results of the first).
+    final completionRequestFuture = sendRequestToServer(completionRequest);
+    await sendNotificationToServer(cancelNotification);
+
+    final result = await completionRequestFuture;
+    expect(result.result, isNull);
+    expect(result.error, isNotNull);
+    expect(result.error, isResponseError(ErrorCodes.RequestCancelled));
+  }
+}
diff --git a/pkg/analysis_server/test/lsp/closing_labels_test.dart b/pkg/analysis_server/test/lsp/closing_labels_test.dart
new file mode 100644
index 0000000..0732276
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/closing_labels_test.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2019, 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:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ClosingLabelsTest);
+  });
+}
+
+@reflectiveTest
+class ClosingLabelsTest extends AbstractLspAnalysisServerTest {
+  test_afterChange() async {
+    final initialContent = 'main() {}';
+    final updatedContent = '''
+Widget build(BuildContext context) {
+  return new Row(         // Row       1:9
+    children: <Widget>[   // Widget[]  2:14
+      new Text('a'),
+      new Text('b'),
+    ],                    // /Widget[] 5:5
+  );                      // /Row      6:3
+}
+''';
+    await initialize(initializationOptions: {'closingLabels': true});
+
+    final labelsUpdateBeforeChange = waitForClosingLabels(mainFileUri);
+    openFile(mainFileUri, initialContent);
+    final labelsBeforeChange = await labelsUpdateBeforeChange;
+
+    final labelsUpdateAfterChange = waitForClosingLabels(mainFileUri);
+    replaceFile(1, mainFileUri, updatedContent);
+    final labelsAfterChange = await labelsUpdateAfterChange;
+
+    expect(labelsBeforeChange, isEmpty);
+    expect(labelsAfterChange, hasLength(2));
+
+    final first = labelsAfterChange.first;
+    final second = labelsAfterChange.last;
+
+    expect(first.label, equals('Row'));
+    expect(first.range.start.line, equals(1));
+    expect(first.range.start.character, equals(9));
+    expect(first.range.end.line, equals(6));
+    expect(first.range.end.character, equals(3));
+
+    expect(second.label, equals('<Widget>[]'));
+    expect(second.range.start.line, equals(2));
+    expect(second.range.start.character, equals(14));
+    expect(second.range.end.line, equals(5));
+    expect(second.range.end.character, equals(5));
+  }
+
+  test_initial() async {
+    final content = '''
+Widget build(BuildContext context) {
+  return new Row(         // Row       1:9
+    children: <Widget>[   // Widget[]  2:14
+      new Text('a'),
+      new Text('b'),
+    ],                    // /Widget[] 5:5
+  );                      // /Row      6:3
+}
+''';
+    await initialize(initializationOptions: {'closingLabels': true});
+
+    final closingLabelsUpdate = waitForClosingLabels(mainFileUri);
+    openFile(mainFileUri, content);
+    final labels = await closingLabelsUpdate;
+
+    expect(labels, hasLength(2));
+    final first = labels.first;
+    final second = labels.last;
+
+    expect(first.label, equals('Row'));
+    expect(first.range.start.line, equals(1));
+    expect(first.range.start.character, equals(9));
+    expect(first.range.end.line, equals(6));
+    expect(first.range.end.character, equals(3));
+
+    expect(second.label, equals('<Widget>[]'));
+    expect(second.range.start.line, equals(2));
+    expect(second.range.start.character, equals(14));
+    expect(second.range.end.line, equals(5));
+    expect(second.range.end.character, equals(5));
+  }
+}
diff --git a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
index a42d083..7c37bec 100644
--- a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
@@ -91,4 +91,16 @@
     applyChanges(contents, assistAction.edit.changes);
     expect(contents[mainFilePath], equals(expectedContent));
   }
+
+  test_nonDartFile() async {
+    await newFile(pubspecFilePath, content: simplePubspecContent);
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+    );
+
+    final codeActions =
+        await getCodeActions(pubspecFileUri.toString(), range: startOfDocRange);
+    expect(codeActions, isEmpty);
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
index 4d692a1..daadf31 100644
--- a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
@@ -93,4 +93,16 @@
     applyChanges(contents, fixAction.edit.changes);
     expect(contents[mainFilePath], equals(expectedContent));
   }
+
+  test_nonDartFile() async {
+    await newFile(pubspecFilePath, content: simplePubspecContent);
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+    );
+
+    final codeActions =
+        await getCodeActions(pubspecFileUri.toString(), range: startOfDocRange);
+    expect(codeActions, isEmpty);
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/code_actions_source_test.dart b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
index 3ea0d20..fb1daa5 100644
--- a/pkg/analysis_server/test/lsp/code_actions_source_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
@@ -37,8 +37,8 @@
     ''';
     await newFile(mainFilePath, content: content);
     await initialize(
-        workspaceCapabilities:
-            withDocumentChangesSupport(emptyWorkspaceClientCapabilities));
+        workspaceCapabilities: withApplyEditSupport(
+            withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -59,7 +59,7 @@
         // When the server sends the edit back, just keep a copy and say we
         // applied successfully (it'll be verified below).
         editParams = edit;
-        return new ApplyWorkspaceEditResponse(true);
+        return new ApplyWorkspaceEditResponse(true, null);
       },
     );
     // Successful edits return an empty success() response.
@@ -95,7 +95,9 @@
 int minified(int x, int y) => min(x, y);
     ''';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -116,7 +118,7 @@
         // When the server sends the edit back, just keep a copy and say we
         // applied successfully (it'll be verified below).
         editParams = edit;
-        return new ApplyWorkspaceEditResponse(true);
+        return new ApplyWorkspaceEditResponse(true, null);
       },
     );
     // Successful edits return an empty success() response.
@@ -138,9 +140,10 @@
   test_availableAsCodeActionLiteral() async {
     await newFile(mainFilePath);
     await initialize(
-      textDocumentCapabilities: withCodeActionKinds(
-          emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
-    );
+        textDocumentCapabilities: withCodeActionKinds(
+            emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     await checkCodeActionAvailable(
       mainFileUri,
@@ -152,7 +155,9 @@
 
   test_availableAsCommand() async {
     await newFile(mainFilePath);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     await checkCodeActionAvailable(
       mainFileUri,
@@ -165,7 +170,9 @@
   test_failsIfFileHasErrors() async {
     final content = 'invalid dart code';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -191,7 +198,9 @@
 int minified(int x, int y) => min(x, y);
     ''';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -212,9 +221,19 @@
   test_unavailableWhenNotRequested() async {
     await newFile(mainFilePath);
     await initialize(
-      textDocumentCapabilities: withCodeActionKinds(
-          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
-    );
+        textDocumentCapabilities: withCodeActionKinds(
+            emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
+
+    final codeActions = await getCodeActions(mainFileUri.toString());
+    final codeAction = findCommand(codeActions, Commands.organizeImports);
+    expect(codeAction, isNull);
+  }
+
+  test_unavailableWithoutApplyEditSupport() async {
+    await newFile(mainFilePath);
+    await initialize();
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -235,8 +254,8 @@
     ''';
     await newFile(mainFilePath, content: content);
     await initialize(
-        workspaceCapabilities:
-            withDocumentChangesSupport(emptyWorkspaceClientCapabilities));
+        workspaceCapabilities: withApplyEditSupport(
+            withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -257,7 +276,7 @@
         // When the server sends the edit back, just keep a copy and say we
         // applied successfully (it'll be verified below).
         editParams = edit;
-        return new ApplyWorkspaceEditResponse(true);
+        return new ApplyWorkspaceEditResponse(true, null);
       },
     );
     // Successful edits return an empty success() response.
@@ -286,7 +305,9 @@
     String b;
     ''';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -307,7 +328,7 @@
         // When the server sends the edit back, just keep a copy and say we
         // applied successfully (it'll be verified below).
         editParams = edit;
-        return new ApplyWorkspaceEditResponse(true);
+        return new ApplyWorkspaceEditResponse(true, null);
       },
     );
     // Successful edits return an empty success() response.
@@ -329,9 +350,10 @@
   test_availableAsCodeActionLiteral() async {
     await newFile(mainFilePath);
     await initialize(
-      textDocumentCapabilities: withCodeActionKinds(
-          emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
-    );
+        textDocumentCapabilities: withCodeActionKinds(
+            emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     await checkCodeActionAvailable(
       mainFileUri,
@@ -343,7 +365,9 @@
 
   test_availableAsCommand() async {
     await newFile(mainFilePath);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     await checkCodeActionAvailable(
       mainFileUri,
@@ -359,7 +383,9 @@
     String a;
     ''';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -377,7 +403,8 @@
       // Claim that we failed tpo apply the edits. This is what the client
       // would do if the edits provided were for an old version of the
       // document.
-      handler: (edit) => new ApplyWorkspaceEditResponse(false),
+      handler: (edit) =>
+          new ApplyWorkspaceEditResponse(false, 'Document changed'),
     );
 
     // Ensure the request returned an error (error repsonses are thrown by
@@ -389,7 +416,9 @@
   test_failsIfFileHasErrors() async {
     final content = 'invalid dart code';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -406,12 +435,35 @@
         throwsA(isResponseError(ServerErrorCodes.FileHasErrors)));
   }
 
+  test_nonDartFile() async {
+    await newFile(pubspecFilePath, content: simplePubspecContent);
+    await initialize(
+        textDocumentCapabilities: withCodeActionKinds(
+            emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
+
+    final codeActions =
+        await getCodeActions(pubspecFileUri.toString(), range: startOfDocRange);
+    expect(codeActions, isEmpty);
+  }
+
   test_unavailableWhenNotRequested() async {
     await newFile(mainFilePath);
     await initialize(
-      textDocumentCapabilities: withCodeActionKinds(
-          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
-    );
+        textDocumentCapabilities: withCodeActionKinds(
+            emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
+
+    final codeActions = await getCodeActions(mainFileUri.toString());
+    final codeAction = findCommand(codeActions, Commands.sortMembers);
+    expect(codeAction, isNull);
+  }
+
+  test_unavailableWithoutApplyEditSupport() async {
+    await newFile(mainFilePath);
+    await initialize();
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.sortMembers);
diff --git a/pkg/analysis_server/test/lsp/completion_test.dart b/pkg/analysis_server/test/lsp/completion_test.dart
index b3554c1..4e7b84b 100644
--- a/pkg/analysis_server/test/lsp/completion_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_test.dart
@@ -192,6 +192,14 @@
     expect(item.detail, isNot(contains('deprecated')));
   }
 
+  test_nonDartFile() async {
+    newFile(pubspecFilePath, content: simplePubspecContent);
+    await initialize();
+
+    final res = await getCompletion(pubspecFileUri, startOfDocPos);
+    expect(res, isEmpty);
+  }
+
   test_plainText() async {
     final content = '''
     class MyClass {
@@ -209,13 +217,234 @@
     final res = await getCompletion(mainFileUri, positionFromMarker(content));
     expect(res.any((c) => c.label == 'abcdefghij'), isTrue);
     final item = res.singleWhere((c) => c.label == 'abcdefghij');
-    expect(item.insertTextFormat, equals(InsertTextFormat.PlainText));
+    expect(item.insertTextFormat,
+        anyOf(equals(InsertTextFormat.PlainText), isNull));
     // ignore: deprecated_member_use_from_same_package
     expect(item.insertText, anyOf(equals('abcdefghij'), isNull));
     final updated = applyTextEdits(withoutMarkers(content), [item.textEdit]);
     expect(updated, contains('a.abcdefghij'));
   }
 
+  test_suggestionSets() async {
+    newFile(
+      join(projectFolderPath, 'other_file.dart'),
+      content: '''
+      /// This class is in another file.
+      class InOtherFile {}
+      ''',
+    );
+
+    final content = '''
+main() {
+  InOtherF^
+}
+    ''';
+
+    final initialAnalysis = waitForAnalysisComplete();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
+    await openFile(mainFileUri, withoutMarkers(content));
+    await initialAnalysis;
+    final res = await getCompletion(mainFileUri, positionFromMarker(content));
+
+    // Find the completion for the class in the other file.
+    final completion = res.singleWhere((c) => c.label == 'InOtherFile');
+    expect(completion, isNotNull);
+
+    // Expect no docs or text edit, since these are added during resolve.
+    expect(completion.documentation, isNull);
+    expect(completion.textEdit, isNull);
+
+    // Resolve the completion item (via server) to get its edits. This is the
+    // LSP's equiv of getSuggestionDetails() and is invoked by LSP clients to
+    // populate additional info (in our case, the additional edits for inserting
+    // the import).
+    final resolved = await resolveCompletion(completion);
+    expect(resolved, isNotNull);
+
+    // Ensure the detail field was update to show this will auto-import.
+    expect(
+        resolved.detail, startsWith("Auto import from '../other_file.dart'"));
+
+    // Ensure the doc comment was added.
+    expect(
+      resolved.documentation.valueEquals('This class is in another file.'),
+      isTrue,
+    );
+
+    // Ensure the edit was added on.
+    expect(resolved.textEdit, isNotNull);
+
+    // There should be no command for this item because it doesn't need imports
+    // in other files. Same-file completions are in additionalEdits.
+    expect(resolved.command, isNull);
+
+    // Apply both the main completion edit and the additionalTextEdits atomically.
+    final newContent = applyTextEdits(
+      withoutMarkers(content),
+      [resolved.textEdit].followedBy(resolved.additionalTextEdits).toList(),
+    );
+
+    // Ensure both edits were made - the completion, and the inserted import.
+    expect(newContent, equals('''
+import '../other_file.dart';
+
+main() {
+  InOtherFile
+}
+    '''));
+  }
+
+  test_suggestionSets_insertsIntoPartFiles() async {
+    // File we'll be adding an import for.
+    newFile(
+      join(projectFolderPath, 'other_file.dart'),
+      content: 'class InOtherFile {}',
+    );
+
+    // File that will have the import added.
+    final parentContent = '''part 'main.dart';''';
+    final parentFilePath = newFile(
+      join(projectFolderPath, 'lib', 'parent.dart'),
+      content: parentContent,
+    ).path;
+
+    // File that we're invoking completion in.
+    final content = '''
+part of 'parent.dart';
+main() {
+  InOtherF^
+}
+    ''';
+
+    final initialAnalysis = waitForAnalysisComplete();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
+    await openFile(mainFileUri, withoutMarkers(content));
+    await initialAnalysis;
+    final res = await getCompletion(mainFileUri, positionFromMarker(content));
+
+    final completion = res.singleWhere((c) => c.label == 'InOtherFile');
+    expect(completion, isNotNull);
+
+    // Resolve the completion item to get its edits.
+    final resolved = await resolveCompletion(completion);
+    expect(resolved, isNotNull);
+    // Ensure it has a command, since it will need to make edits in other files
+    // and that's done by telling the server to send a workspace/applyEdit. LSP
+    // doesn't currently support these other-file edits in the completion.
+    // See https://github.com/microsoft/language-server-protocol/issues/749
+    expect(resolved.command, isNotNull);
+
+    // Apply all current-document edits.
+    final newContent = applyTextEdits(
+      withoutMarkers(content),
+      [resolved.textEdit].followedBy(resolved.additionalTextEdits).toList(),
+    );
+    expect(newContent, equals('''
+part of 'parent.dart';
+main() {
+  InOtherFile
+}
+    '''));
+
+    // Execute the associated command (which will handle edits in other files).
+    ApplyWorkspaceEditParams editParams;
+    final commandResponse = await handleExpectedRequest<Object,
+        ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse>(
+      Method.workspace_applyEdit,
+      () => executeCommand(resolved.command),
+      handler: (edit) {
+        // When the server sends the edit back, just keep a copy and say we
+        // applied successfully (it'll be verified below).
+        editParams = edit;
+        return new ApplyWorkspaceEditResponse(true, null);
+      },
+    );
+    // Successful edits return an empty success() response.
+    expect(commandResponse, isNull);
+
+    // Ensure the edit came back.
+    expect(editParams, isNotNull);
+    expect(editParams.edit.changes, isNotNull);
+
+    // Ensure applying the changes will give us the expected content.
+    final contents = {
+      parentFilePath: withoutMarkers(parentContent),
+    };
+    applyChanges(contents, editParams.edit.changes);
+
+    // Check the parent file was modified to include the import by the edits
+    // that came from the server.
+    expect(contents[parentFilePath], equals('''
+import '../other_file.dart';
+
+part 'main.dart';'''));
+  }
+
+  test_suggestionSets_unavailableIfDisabled() async {
+    newFile(
+      join(projectFolderPath, 'other_file.dart'),
+      content: 'class InOtherFile {}',
+    );
+
+    final content = '''
+main() {
+  InOtherF^
+}
+    ''';
+
+    final initialAnalysis = waitForAnalysisComplete();
+    // Support applyEdit, but explicitly disable the suggestions.
+    await initialize(
+      initializationOptions: {'suggestFromUnimportedLibraries': false},
+      workspaceCapabilities:
+          withApplyEditSupport(emptyWorkspaceClientCapabilities),
+    );
+    await openFile(mainFileUri, withoutMarkers(content));
+    await initialAnalysis;
+    final res = await getCompletion(mainFileUri, positionFromMarker(content));
+
+    // Ensure the item doesn't appear in the results (because we might not
+    // be able to execute the import edits if they're in another file).
+    final completion = res.singleWhere(
+      (c) => c.label == 'InOtherFile',
+      orElse: () => null,
+    );
+    expect(completion, isNull);
+  }
+
+  test_suggestionSets_unavailableWithoutApplyEdit() async {
+    // If client doesn't advertise support for workspace/applyEdit, we won't
+    // include suggestion sets.
+    newFile(
+      join(projectFolderPath, 'other_file.dart'),
+      content: 'class InOtherFile {}',
+    );
+
+    final content = '''
+main() {
+  InOtherF^
+}
+    ''';
+
+    final initialAnalysis = waitForAnalysisComplete();
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    await initialAnalysis;
+    final res = await getCompletion(mainFileUri, positionFromMarker(content));
+
+    // Ensure the item doesn't appear in the results (because we might not
+    // be able to execute the import edits if they're in another file).
+    final completion = res.singleWhere(
+      (c) => c.label == 'InOtherFile',
+      orElse: () => null,
+    );
+    expect(completion, isNull);
+  }
+
   test_unopenFile() async {
     final content = '''
     class MyClass {
@@ -233,7 +462,8 @@
     final res = await getCompletion(mainFileUri, positionFromMarker(content));
     expect(res.any((c) => c.label == 'abcdefghij'), isTrue);
     final item = res.singleWhere((c) => c.label == 'abcdefghij');
-    expect(item.insertTextFormat, equals(InsertTextFormat.PlainText));
+    expect(item.insertTextFormat,
+        anyOf(equals(InsertTextFormat.PlainText), isNull));
     // ignore: deprecated_member_use_from_same_package
     expect(item.insertText, anyOf(equals('abcdefghij'), isNull));
     final updated = applyTextEdits(withoutMarkers(content), [item.textEdit]);
diff --git a/pkg/analysis_server/test/lsp/definition_test.dart b/pkg/analysis_server/test/lsp/definition_test.dart
index 4e99a7f..a7df3fe 100644
--- a/pkg/analysis_server/test/lsp/definition_test.dart
+++ b/pkg/analysis_server/test/lsp/definition_test.dart
@@ -53,6 +53,14 @@
     expect(loc.uri, equals(referencedFileUri.toString()));
   }
 
+  test_nonDartFile() async {
+    newFile(pubspecFilePath, content: simplePubspecContent);
+    await initialize();
+
+    final res = await getDefinition(pubspecFileUri, startOfDocPos);
+    expect(res, isEmpty);
+  }
+
   test_singleFile() async {
     final contents = '''
     [[foo]]() {
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart
index 802d3be..06ba649 100644
--- a/pkg/analysis_server/test/lsp/diagnostic_test.dart
+++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -61,4 +62,23 @@
     expect(diagnostic.range.end.line, equals(0));
     expect(diagnostic.range.end.character, equals(12));
   }
+
+  test_dotFilesExcluded() async {
+    var dotFolderFilePath =
+        join(projectFolderPath, '.dart_tool', 'tool_file.dart');
+    var dotFolderFileUri = Uri.file(dotFolderFilePath);
+
+    newFile(dotFolderFilePath, content: 'String a = 1;');
+
+    List<Diagnostic> diagnostics = null;
+    waitForDiagnostics(dotFolderFileUri).then((d) => diagnostics = d);
+
+    // Send a request for a hover.
+    await initialize();
+    await getHover(dotFolderFileUri, Position(0, 0));
+
+    // Ensure that as part of responding to getHover, diagnostics were not
+    // transmitted.
+    expect(diagnostics, isNull);
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/document_highlights_test.dart b/pkg/analysis_server/test/lsp/document_highlights_test.dart
index 7f002b4..374dd1d 100644
--- a/pkg/analysis_server/test/lsp/document_highlights_test.dart
+++ b/pkg/analysis_server/test/lsp/document_highlights_test.dart
@@ -29,6 +29,17 @@
     }
     ''');
 
+  test_nonDartFile() async {
+    await initialize();
+    await openFile(pubspecFileUri, simplePubspecContent);
+
+    final highlights =
+        await getDocumentHighlights(pubspecFileUri, startOfDocPos);
+
+    // Non-Dart files should return empty results, not errors.
+    expect(highlights, isEmpty);
+  }
+
   test_noResult() => _testMarkedContent('''
     main() {
       // This one is in a ^ comment!
diff --git a/pkg/analysis_server/test/lsp/document_symbols_test.dart b/pkg/analysis_server/test/lsp/document_symbols_test.dart
index b29ec7e..6d56201 100644
--- a/pkg/analysis_server/test/lsp/document_symbols_test.dart
+++ b/pkg/analysis_server/test/lsp/document_symbols_test.dart
@@ -104,4 +104,16 @@
     expect(method.kind, equals(SymbolKind.Method));
     expect(method.containerName, equals(myClass.name));
   }
+
+  test_nonDartFile() async {
+    newFile(pubspecFilePath, content: simplePubspecContent);
+    await initialize();
+
+    final result = await getDocumentSymbols(pubspecFileUri.toString());
+    final symbols = result.map(
+      (docsymbols) => throw 'Expected SymbolInformations, got DocumentSymbols',
+      (symbolInfos) => symbolInfos,
+    );
+    expect(symbols, isEmpty);
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/folding_test.dart b/pkg/analysis_server/test/lsp/folding_test.dart
index 0b41612..098010c 100644
--- a/pkg/analysis_server/test/lsp/folding_test.dart
+++ b/pkg/analysis_server/test/lsp/folding_test.dart
@@ -66,6 +66,14 @@
     expect(regions, unorderedEquals(expectedRegions));
   }
 
+  test_nonDartFile() async {
+    await initialize();
+    await openFile(pubspecFileUri, simplePubspecContent);
+
+    final regions = await getFoldingRegions(pubspecFileUri);
+    expect(regions, isEmpty);
+  }
+
   test_headersImportsComments() async {
     // TODO(dantup): Review why the file header and the method comment ranges
     // are different... one spans only the range to collapse, but the other
diff --git a/pkg/analysis_server/test/lsp/format_test.dart b/pkg/analysis_server/test/lsp/format_test.dart
index 17a34b0..52d944e 100644
--- a/pkg/analysis_server/test/lsp/format_test.dart
+++ b/pkg/analysis_server/test/lsp/format_test.dart
@@ -63,6 +63,15 @@
     expect(formatEdits, isNull);
   }
 
+  test_nonDartFile() async {
+    await initialize();
+    await openFile(pubspecFileUri, simplePubspecContent);
+
+    final formatEdits =
+        await formatOnType(pubspecFileUri.toString(), startOfDocPos, '}');
+    expect(formatEdits, isNull);
+  }
+
   test_path_doesNotExist() async {
     await initialize();
 
diff --git a/pkg/analysis_server/test/lsp/hover_test.dart b/pkg/analysis_server/test/lsp/hover_test.dart
index f1312e2..957b16f 100644
--- a/pkg/analysis_server/test/lsp/hover_test.dart
+++ b/pkg/analysis_server/test/lsp/hover_test.dart
@@ -18,6 +18,27 @@
 
 @reflectiveTest
 class HoverTest extends AbstractLspAnalysisServerTest {
+  test_dartDoc_macros() async {
+    final content = '''
+    /// {@template template_name}
+    /// This is shared content.
+    /// {@endtemplate}
+    const String foo = null;
+
+    /// {@macro template_name}
+    const String [[f^oo2]] = null;
+    ''';
+
+    final initialAnalysis = waitForAnalysisComplete();
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    await initialAnalysis;
+    var hover = await getHover(mainFileUri, positionFromMarker(content));
+    expect(hover, isNotNull);
+    expect(hover.range, equals(rangeFromMarkers(content)));
+    expect(_getStringContents(hover), endsWith('This is shared content.'));
+  }
+
   test_hover_bad_position() async {
     await initialize();
     await openFile(mainFileUri, '');
@@ -46,6 +67,8 @@
 ```dart
 String abc
 ```
+*lib/main.dart*
+
 ---
 This is a string.
 
@@ -107,6 +130,13 @@
     expect(hover, isNull);
   }
 
+  test_nonDartFile() async {
+    await initialize();
+    await openFile(pubspecFileUri, simplePubspecContent);
+    final hover = await getHover(pubspecFileUri, startOfDocPos);
+    expect(hover, isNull);
+  }
+
   test_plainText_simple() async {
     final content = '''
     /// This is a string.
@@ -137,6 +167,7 @@
 ```dart
 String abc
 ```
+*lib/main.dart*
     '''
         .trim();
 
diff --git a/pkg/analysis_server/test/lsp/implementation_test.dart b/pkg/analysis_server/test/lsp/implementation_test.dart
new file mode 100644
index 0000000..bde558e
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/implementation_test.dart
@@ -0,0 +1,183 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ImplementationTest);
+  });
+}
+
+@reflectiveTest
+class ImplementationTest extends AbstractLspAnalysisServerTest {
+  test_class_excludesSelf() => _testMarkedContent('''
+      abstract class ^[[A]] {}
+      class B extends A {}
+      class C extends A {}
+    ''', shouldMatch: false);
+
+  test_class_excludesSuper() => _testMarkedContent('''
+      abstract class [[A]] {}
+      class ^B extends A {}
+      class C extends A {}
+    ''', shouldMatch: false);
+
+  test_class_sub() => _testMarkedContent('''
+      abstract class ^A {}
+      class [[B]] extends A {}
+      class [[C]] extends A {}
+    ''');
+
+  test_class_subSub() => _testMarkedContent('''
+      abstract class ^A {}
+      class [[B]] extends A {}
+      class [[C]] extends A {}
+      class [[D]] extends B {}
+      class [[E]] extends B {}
+      class [[F]] extends E {}
+    ''');
+
+  test_emptyResults() async {
+    final content = '';
+
+    await initialize();
+    await openFile(mainFileUri, content);
+    final res = await getImplementations(
+      mainFileUri,
+      startOfDocPos,
+    );
+
+    expect(res, isEmpty);
+  }
+
+  test_method_excludesClassesWithoutImplementations() => _testMarkedContent('''
+      abstract class A {
+        void ^b();
+      }
+
+      class B extends A {}
+
+      class [[E]] extends B {}
+    ''', shouldMatch: false);
+
+  test_method_excludesSelf() => _testMarkedContent('''
+      abstract class A {
+        void ^[[b]]();
+      }
+
+      class B extends A {
+        void b() {}
+      }
+    ''', shouldMatch: false);
+
+  test_method_excludesSuper() => _testMarkedContent('''
+      abstract class A {
+        void [[b]]();
+      }
+
+      class B extends A {
+        void ^b() {}
+      }
+    ''', shouldMatch: false);
+
+  test_method_fromCallSite() => _testMarkedContent('''
+      abstract class A {
+        void b();
+      }
+
+      class B extends A {
+        void [[b]]() {}
+      }
+
+      class C extends A {
+        void [[b]]() {}
+      }
+
+      class D extends B {
+        void [[b]]() {}
+      }
+
+      class E extends B {}
+
+      class F extends E {
+        void [[b]]() {}
+      }
+
+      void fromCallSite() {
+        A e = new E();
+        e.^b();
+      }
+    ''');
+
+  test_method_sub() => _testMarkedContent('''
+      abstract class A {
+        void ^b();
+      }
+
+      class B extends A {
+        void [[b]]() {}
+      }
+
+      class C extends A {
+        void [[b]]() {}
+      }
+    ''');
+
+  test_method_subSub() => _testMarkedContent('''
+      abstract class A {
+        void ^b();
+      }
+
+      class B extends A {
+        void [[b]]() {}
+      }
+
+      class D extends B {
+        void [[b]]() {}
+      }
+
+      class E extends B {}
+
+      class F extends E {
+        void [[b]]() {}
+      }
+    ''');
+
+  test_nonDartFile() async {
+    newFile(pubspecFilePath, content: simplePubspecContent);
+    await initialize();
+
+    final res = await getImplementations(pubspecFileUri, startOfDocPos);
+    expect(res, isEmpty);
+  }
+
+  /// Takes an input string that contains ^ at the location to invoke the
+  /// textDocument/implementations command and has ranges marked with
+  /// `[[brackets]]` that are expected to be included (or not, if [shouldMatch]
+  /// is set to `false`) in the results.
+  Future<void> _testMarkedContent(String content,
+      {bool shouldMatch = true}) async {
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final res = await getImplementations(
+      mainFileUri,
+      positionFromMarker(content),
+    );
+
+    final expectedLocations = rangesFromMarkers(content)
+        .map((r) => Location(mainFileUri.toString(), r));
+
+    if (shouldMatch) {
+      expect(res, equals(expectedLocations));
+    } else {
+      expectedLocations.forEach((l) => expect(res, isNot(contains(res))));
+    }
+  }
+}
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index 26b7028..7b147df 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -170,6 +170,7 @@
       const Duration(seconds: 1),
       onTimeout: () {
         didTimeout = true;
+        return null;
       },
     );
 
@@ -179,13 +180,100 @@
 
   test_uninitialized_rejectsRequests() async {
     final request = makeRequest(new Method.fromJson('randomRequest'), null);
-    final logParams = await expectErrorNotification<LogMessageParams>(() async {
-      final response = await channel.sendRequestToServer(request);
-      expect(response.id, equals(request.id));
-      expect(response.result, isNull);
-      expect(response.error, isNotNull);
-      expect(response.error.code, ErrorCodes.ServerNotInitialized);
+    final response = await channel.sendRequestToServer(request);
+    expect(response.id, equals(request.id));
+    expect(response.result, isNull);
+    expect(response.error, isNotNull);
+    expect(response.error.code, ErrorCodes.ServerNotInitialized);
+  }
+
+  test_dynamicRegistration_notSupportedByClient() async {
+    // If the client doesn't send any dynamicRegistration settings then there
+    // should be no `client/registerCapability` calls.
+
+    // Set a flag if any registerCapability request comes through.
+    bool didGetRegisterCapabilityRequest = false;
+    requestsFromServer
+        .firstWhere((n) => n.method == Method.client_registerCapability)
+        .then((params) {
+      didGetRegisterCapabilityRequest = true;
     });
-    expect(logParams.type, equals(MessageType.Error));
+
+    // Initialize with no dynamic registrations advertised.
+    await initialize();
+    await pumpEventQueue();
+
+    expect(didGetRegisterCapabilityRequest, isFalse);
+  }
+
+  test_dynamicRegistration_onlyForClientSupportedMethods() async {
+    // Check that when the server calls client/registerCapability it only includes
+    // the items we advertised dynamic registration support for.
+    List<Registration> registrations;
+    await handleExpectedRequest<void, RegistrationParams, void>(
+      Method.client_registerCapability,
+      () => initialize(
+          textDocumentCapabilities: withHoverDynamicRegistration(
+              emptyTextDocumentClientCapabilities)),
+      handler: (registrationParams) =>
+          registrations = registrationParams.registrations,
+    );
+
+    expect(registrations, hasLength(1));
+    expect(registrations.single.method,
+        equals(Method.textDocument_hover.toJson()));
+  }
+
+  test_dynamicRegistration_containsAppropriateSettings() async {
+    // Basic check that the server responds with the capabilities we'd expect,
+    // for ex including analysis_options.yaml in text synchronization but not
+    // for hovers.
+    List<Registration> registrations;
+    await handleExpectedRequest<void, RegistrationParams, void>(
+      Method.client_registerCapability,
+      () => initialize(
+          // Support dynamic registration for both text sync + hovers.
+          textDocumentCapabilities: withTextSyncDynamicRegistration(
+              withHoverDynamicRegistration(
+                  emptyTextDocumentClientCapabilities))),
+      handler: (registrationParams) =>
+          registrations = registrationParams.registrations,
+    );
+
+    // Should container Hover, DidOpen, DidClose, DidChange.
+    expect(registrations, hasLength(4));
+    final hover =
+        registrationOptionsFor(registrations, Method.textDocument_hover);
+    final change =
+        registrationOptionsFor(registrations, Method.textDocument_didChange);
+    expect(registrationOptionsFor(registrations, Method.textDocument_didOpen),
+        isNotNull);
+    expect(registrationOptionsFor(registrations, Method.textDocument_didClose),
+        isNotNull);
+
+    // The hover capability should only specific Dart.
+    expect(hover, isNotNull);
+    expect(hover.documentSelector, hasLength(1));
+    expect(hover.documentSelector.single.language, equals('dart'));
+
+    // didChange should also include pubspec + analysis_options.
+    expect(change, isNotNull);
+    expect(change.documentSelector, hasLength(greaterThanOrEqualTo(3)));
+    expect(change.documentSelector.any((ds) => ds.language == 'dart'), isTrue);
+    expect(change.documentSelector.any((ds) => ds.pattern == '**/pubspec.yaml'),
+        isTrue);
+    expect(
+        change.documentSelector
+            .any((ds) => ds.pattern == '**/analysis_options.yaml'),
+        isTrue);
+  }
+
+  TextDocumentRegistrationOptions registrationOptionsFor(
+    List<Registration> registrations,
+    Method method,
+  ) {
+    return registrations
+        .singleWhere((r) => r.method == method.toJson(), orElse: () => null)
+        ?.registerOptions;
   }
 }
diff --git a/pkg/analysis_server/test/lsp/mapping_test.dart b/pkg/analysis_server/test/lsp/mapping_test.dart
new file mode 100644
index 0000000..d0d25b8
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/mapping_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2019, 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:collection';
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
+import 'package:analysis_server/src/lsp/mapping.dart' as lsp;
+import 'package:analysis_server/src/protocol_server.dart' as server;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MappingTest);
+  });
+}
+
+@reflectiveTest
+class MappingTest extends AbstractLspAnalysisServerTest {
+  test_completionItemKind_firstNotSupported() async {
+    // TYPE_PARAMETER maps to TypeParameter first, but since originally LSP
+    // did not support it, it'll map to Variable if the client doesn't support
+    // that.
+    var supportedKinds = new HashSet.of([
+      lsp.CompletionItemKind.TypeParameter,
+      lsp.CompletionItemKind.Variable,
+    ]);
+    var result = lsp.elementKindToCompletionItemKind(
+      supportedKinds,
+      server.ElementKind.TYPE_PARAMETER,
+    );
+    expect(result, equals(lsp.CompletionItemKind.TypeParameter));
+  }
+
+  test_completionItemKind_firstSupported() async {
+    // TYPE_PARAMETER maps to TypeParameter first, but since originally LSP
+    // did not support it, it'll map to Variable if the client doesn't support
+    // that.
+    var supportedKinds = new HashSet.of([lsp.CompletionItemKind.Variable]);
+    var result = lsp.elementKindToCompletionItemKind(
+      supportedKinds,
+      server.ElementKind.TYPE_PARAMETER,
+    );
+    expect(result, equals(lsp.CompletionItemKind.Variable));
+  }
+
+  test_completionItemKind_knownMapping() async {
+    final supportedKinds = new HashSet.of([lsp.CompletionItemKind.Class]);
+    final result = lsp.elementKindToCompletionItemKind(
+      supportedKinds,
+      server.ElementKind.CLASS,
+    );
+    expect(result, equals(lsp.CompletionItemKind.Class));
+  }
+
+  test_completionItemKind_notMapped() async {
+    var supportedKinds = new HashSet<lsp.CompletionItemKind>();
+    var result = lsp.elementKindToCompletionItemKind(
+      supportedKinds,
+      server.ElementKind.UNKNOWN, // Unknown is not mapped.
+    );
+    expect(result, isNull);
+  }
+
+  test_completionItemKind_notSupported() async {
+    var supportedKinds = new HashSet<lsp.CompletionItemKind>();
+    var result = lsp.elementKindToCompletionItemKind(
+      supportedKinds,
+      server.ElementKind.CLASS,
+    );
+    expect(result, isNull);
+  }
+}
diff --git a/pkg/analysis_server/test/lsp/references_test.dart b/pkg/analysis_server/test/lsp/references_test.dart
index bd36c11..0c69bca 100644
--- a/pkg/analysis_server/test/lsp/references_test.dart
+++ b/pkg/analysis_server/test/lsp/references_test.dart
@@ -99,6 +99,14 @@
     expect(loc.uri, equals(mainFileUri.toString()));
   }
 
+  test_nonDartFile() async {
+    newFile(pubspecFilePath, content: simplePubspecContent);
+    await initialize();
+
+    final res = await getReferences(pubspecFileUri, startOfDocPos);
+    expect(res, isEmpty);
+  }
+
   test_singleFile_withoutDeclaration() async {
     final contents = '''
     f^oo() {
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 108a850..a531618 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:convert';
 
 import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
@@ -30,8 +31,7 @@
 
 final beginningOfDocument = new Range(new Position(0, 0), new Position(0, 0));
 
-mixin LspAnalysisServerTestMixin
-    implements ResourceProviderMixin, ClientCapabilitiesHelperMixin {
+mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
   static const positionMarker = '^';
   static const rangeMarkerStart = '[[';
   static const rangeMarkerEnd = ']]';
@@ -40,8 +40,11 @@
       new RegExp(allMarkers.map(RegExp.escape).join('|'));
 
   int _id = 0;
-  String projectFolderPath, mainFilePath;
-  Uri projectFolderUri, mainFileUri;
+  String projectFolderPath, mainFilePath, pubspecFilePath, analysisOptionsPath;
+  Uri projectFolderUri, mainFileUri, pubspecFileUri, analysisOptionsUri;
+  final String simplePubspecContent = 'name: my_project';
+  final startOfDocPos = new Position(0, 0);
+  final startOfDocRange = new Range(new Position(0, 0), new Position(0, 0));
 
   Stream<Message> get serverToClient;
 
@@ -191,7 +194,7 @@
         changes,
       ),
     );
-    sendNotificationToServer(notification);
+    await sendNotificationToServer(notification);
   }
 
   Future changeWorkspaceFolders({List<Uri> add, List<Uri> remove}) async {
@@ -204,7 +207,7 @@
         ),
       ),
     );
-    sendNotificationToServer(notification);
+    await sendNotificationToServer(notification);
   }
 
   Future closeFile(Uri uri) async {
@@ -213,7 +216,7 @@
       new DidCloseTextDocumentParams(
           new TextDocumentIdentifier(uri.toString())),
     );
-    sendNotificationToServer(notification);
+    await sendNotificationToServer(notification);
   }
 
   Future<Object> executeCommand(Command command) async {
@@ -367,6 +370,14 @@
     return expectSuccessfulResponseTo<List<CompletionItem>>(request);
   }
 
+  Future<CompletionItem> resolveCompletion(CompletionItem item) {
+    final request = makeRequest(
+      Method.completionItem_resolve,
+      item,
+    );
+    return expectSuccessfulResponseTo<CompletionItem>(request);
+  }
+
   Future<List<Location>> getDefinition(Uri uri, Position pos) {
     final request = makeRequest(
       Method.textDocument_definition,
@@ -433,6 +444,21 @@
     return expectSuccessfulResponseTo<Hover>(request);
   }
 
+  Future<List<Location>> getImplementations(
+    Uri uri,
+    Position pos, {
+    includeDeclarations = false,
+  }) {
+    final request = makeRequest(
+      Method.textDocument_implementation,
+      new TextDocumentPositionParams(
+        new TextDocumentIdentifier(uri.toString()),
+        pos,
+      ),
+    );
+    return expectSuccessfulResponseTo<List<Location>>(request);
+  }
+
   Future<List<Location>> getReferences(
     Uri uri,
     Position pos, {
@@ -460,6 +486,20 @@
     return expectSuccessfulResponseTo<SignatureHelp>(request);
   }
 
+  Future<Location> getSuper(
+    Uri uri,
+    Position pos,
+  ) {
+    final request = makeRequest(
+      CustomMethods.Super,
+      new TextDocumentPositionParams(
+        new TextDocumentIdentifier(uri.toString()),
+        pos,
+      ),
+    );
+    return expectSuccessfulResponseTo<Location>(request);
+  }
+
   /// Executes [f] then waits for a request of type [method] from the server which
   /// is passed to [handler] to process, then waits for (and returns) the
   /// response to the original request.
@@ -542,7 +582,7 @@
     if (response.error == null) {
       final notification =
           makeNotification(Method.initialized, new InitializedParams());
-      sendNotificationToServer(notification);
+      await sendNotificationToServer(notification);
       await pumpEventQueue();
     } else if (throwOnFailure) {
       throw 'Error during initialize request: '
@@ -579,7 +619,7 @@
       new DidOpenTextDocumentParams(new TextDocumentItem(
           uri.toString(), dartLanguageId, version, content)),
     );
-    sendNotificationToServer(notification);
+    await sendNotificationToServer(notification);
     await pumpEventQueue();
   }
 
@@ -713,8 +753,8 @@
     await serverToClient.firstWhere((message) {
       if (message is NotificationMessage &&
           message.method == Method.textDocument_publishDiagnostics) {
-        diagnosticParams = message.params;
-
+        diagnosticParams =
+            _convertParams(message, PublishDiagnosticsParams.fromJson);
         return diagnosticParams.uri == uri.toString();
       }
       return false;
@@ -722,6 +762,50 @@
     return diagnosticParams.diagnostics;
   }
 
+  /// A helper to simplify processing of results for both in-process tests (where
+  /// we'll get the real type back), and out-of-process integration tests (where
+  /// params is `Map<String, dynamic>` and needs to be fromJson'd).
+  T _convertParams<T>(
+    IncomingMessage message,
+    T Function(Map<String, dynamic>) fromJson,
+  ) {
+    return message.params is T ? message.params : fromJson(message.params);
+  }
+
+  Future<List<ClosingLabel>> waitForClosingLabels(Uri uri) async {
+    PublishClosingLabelsParams closingLabelsParams;
+    await serverToClient.firstWhere((message) {
+      if (message is NotificationMessage &&
+          message.method == CustomMethods.PublishClosingLabels) {
+        closingLabelsParams =
+            _convertParams(message, PublishClosingLabelsParams.fromJson);
+
+        return closingLabelsParams.uri == uri.toString();
+      }
+      return false;
+    });
+    return closingLabelsParams.labels;
+  }
+
+  Future<AnalyzerStatusParams> waitForAnalysisStart() =>
+      waitForAnalysisStatus(true);
+
+  Future<AnalyzerStatusParams> waitForAnalysisComplete() =>
+      waitForAnalysisStatus(false);
+
+  Future<AnalyzerStatusParams> waitForAnalysisStatus(bool analyzing) async {
+    AnalyzerStatusParams params;
+    await serverToClient.firstWhere((message) {
+      if (message is NotificationMessage &&
+          message.method == CustomMethods.AnalyzerStatus) {
+        params = _convertParams(message, AnalyzerStatusParams.fromJson);
+        return params.isAnalyzing == analyzing;
+      }
+      return false;
+    });
+    return params;
+  }
+
   /// Removes markers like `[[` and `]]` and `^` that are used for marking
   /// positions/ranges in strings to avoid hard-coding positions in tests.
   String withoutMarkers(String contents) =>
@@ -786,6 +870,10 @@
     newFile(join(projectFolderPath, 'lib', 'file.dart'));
     mainFilePath = join(projectFolderPath, 'lib', 'main.dart');
     mainFileUri = Uri.file(mainFilePath);
+    pubspecFilePath = join(projectFolderPath, 'pubspec.yaml');
+    pubspecFileUri = Uri.file(pubspecFilePath);
+    analysisOptionsPath = join(projectFolderPath, 'analysis_options.yaml');
+    analysisOptionsUri = Uri.file(analysisOptionsPath);
   }
 
   Future tearDown() async {
@@ -826,7 +914,12 @@
     TextDocumentClientCapabilities source,
     Map<String, dynamic> textDocumentCapabilities,
   ) {
-    final json = source.toJson();
+    // TODO(dantup): Figure out why we need to do this to get a map...
+    // source.toJson() doesn't recursively called toJson() so we end up with
+    // objects (instead of maps) in child properties, which means multiple
+    // calls to this function do not work correctly. For now, calling jsonEncode
+    // then jsonDecode will force recursive serialisation.
+    final json = jsonDecode(jsonEncode(source));
     if (textDocumentCapabilities != null) {
       textDocumentCapabilities.keys.forEach((key) {
         json[key] = textDocumentCapabilities[key];
@@ -839,7 +932,9 @@
     WorkspaceClientCapabilities source,
     Map<String, dynamic> workspaceCapabilities,
   ) {
-    final json = source.toJson();
+    // TODO(dantup): As above - it seems like this round trip should be
+    // unnecessary.
+    final json = jsonDecode(jsonEncode(source));
     if (workspaceCapabilities != null) {
       workspaceCapabilities.keys.forEach((key) {
         json[key] = workspaceCapabilities[key];
@@ -903,6 +998,14 @@
     });
   }
 
+  TextDocumentClientCapabilities withHoverDynamicRegistration(
+    TextDocumentClientCapabilities source,
+  ) {
+    return extendTextDocumentCapabilities(source, {
+      'hover': {'dynamicRegistration': true}
+    });
+  }
+
   TextDocumentClientCapabilities withSignatureHelpContentFormat(
     TextDocumentClientCapabilities source,
     List<MarkupKind> formats,
@@ -916,6 +1019,14 @@
     });
   }
 
+  TextDocumentClientCapabilities withTextSyncDynamicRegistration(
+    TextDocumentClientCapabilities source,
+  ) {
+    return extendTextDocumentCapabilities(source, {
+      'synchronization': {'dynamicRegistration': true}
+    });
+  }
+
   TextDocumentClientCapabilities withHierarchicalDocumentSymbolSupport(
     TextDocumentClientCapabilities source,
   ) {
@@ -931,4 +1042,10 @@
       'workspaceEdit': {'documentChanges': true}
     });
   }
+
+  WorkspaceClientCapabilities withApplyEditSupport(
+    WorkspaceClientCapabilities source,
+  ) {
+    return extendWorkspaceCapabilities(source, {'applyEdit': true});
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/server_test.dart b/pkg/analysis_server/test/lsp/server_test.dart
index eb79236..17cea13 100644
--- a/pkg/analysis_server/test/lsp/server_test.dart
+++ b/pkg/analysis_server/test/lsp/server_test.dart
@@ -75,6 +75,7 @@
       const Duration(seconds: 1),
       onTimeout: () {
         didTimeout = true;
+        return null;
       },
     );
 
diff --git a/pkg/analysis_server/test/lsp/signature_help_test.dart b/pkg/analysis_server/test/lsp/signature_help_test.dart
index e22eec0..b791ddd 100644
--- a/pkg/analysis_server/test/lsp/signature_help_test.dart
+++ b/pkg/analysis_server/test/lsp/signature_help_test.dart
@@ -122,6 +122,15 @@
     );
   }
 
+  test_nonDartFile() async {
+    await initialize(
+        textDocumentCapabilities: withSignatureHelpContentFormat(
+            emptyTextDocumentClientCapabilities, [MarkupKind.PlainText]));
+    await openFile(pubspecFileUri, simplePubspecContent);
+    final res = await getSignatureHelp(pubspecFileUri, startOfDocPos);
+    expect(res, isNull);
+  }
+
   test_params_multipleNamed() async {
     final content = '''
     /// Does foo.
@@ -253,6 +262,37 @@
     );
   }
 
+  test_dartDocMacro() async {
+    final content = '''
+    /// {@template template_name}
+    /// This is shared content.
+    /// {@endtemplate}
+    const String bar = null;
+
+    /// {@macro template_name}
+    foo(String s, int i) {
+      foo(^);
+    }
+    ''';
+    final expectedLabel = 'foo(String s, int i)';
+    final expectedDoc = 'This is shared content.';
+
+    final initialAnalysis = waitForAnalysisComplete();
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    await initialAnalysis;
+    await testSignature(
+      content,
+      expectedLabel,
+      expectedDoc,
+      [
+        new ParameterInformation('String s', null),
+        new ParameterInformation('int i', null),
+      ],
+      expectedFormat: null,
+    );
+  }
+
   test_unopenFile() async {
     final content = '''
     /// Does foo.
diff --git a/pkg/analysis_server/test/lsp/super_test.dart b/pkg/analysis_server/test/lsp/super_test.dart
new file mode 100644
index 0000000..d1bc684
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/super_test.dart
@@ -0,0 +1,146 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SuperTest);
+  });
+}
+
+@reflectiveTest
+class SuperTest extends AbstractLspAnalysisServerTest {
+  test_className() async {
+    final content = '''
+class A {}
+
+class [[B]] extends A {}
+
+class C^ extends B {}
+''';
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    final res = await getSuper(
+      mainFileUri,
+      positionFromMarker(content),
+    );
+
+    expect(
+        res,
+        equals(
+            new Location(mainFileUri.toString(), rangeFromMarkers(content))));
+  }
+
+  test_insideClass() async {
+    final content = '''
+class A {}
+
+class [[B]] extends A {}
+
+class C extends B {
+  ^
+}
+''';
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    final res = await getSuper(
+      mainFileUri,
+      positionFromMarker(content),
+    );
+
+    expect(
+        res,
+        equals(
+            new Location(mainFileUri.toString(), rangeFromMarkers(content))));
+  }
+
+  test_insideMethod() async {
+    final content = '''
+class A {
+  void [[foo]]() {}
+}
+
+class B extends A {}
+
+class C extends B {
+  @override
+  void foo() {
+    // fo^oC
+  }
+}
+''';
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    final res = await getSuper(
+      mainFileUri,
+      positionFromMarker(content),
+    );
+
+    expect(
+        res,
+        equals(
+            new Location(mainFileUri.toString(), rangeFromMarkers(content))));
+  }
+
+  test_methodName() async {
+    final content = '''
+class A {
+  void [[foo]]() {}
+}
+
+class B extends A {}
+
+class C extends B {
+  @override
+  void fo^o() {
+    // fooC
+  }
+}
+''';
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    final res = await getSuper(
+      mainFileUri,
+      positionFromMarker(content),
+    );
+
+    expect(
+        res,
+        equals(
+            new Location(mainFileUri.toString(), rangeFromMarkers(content))));
+  }
+
+  test_methodReturnType() async {
+    final content = '''
+class A {
+  void [[foo]]() {}
+}
+
+class B extends A {}
+
+class C extends B {
+  @override
+  vo^id foo() {
+    // fooC
+  }
+}
+''';
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    final res = await getSuper(
+      mainFileUri,
+      positionFromMarker(content),
+    );
+
+    expect(
+        res,
+        equals(
+            new Location(mainFileUri.toString(), rangeFromMarkers(content))));
+  }
+}
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart
index 7c6ab34..f1cc08c 100644
--- a/pkg/analysis_server/test/lsp/test_all.dart
+++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -5,8 +5,11 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../src/lsp/lsp_packet_transformer_test.dart' as lsp_packet_transformer;
+import 'analyzer_status_test.dart' as analyzer_status;
+import 'cancel_request_test.dart' as cancel_request;
 import 'change_workspace_folders_test.dart' as change_workspace_folders;
 import 'code_actions_assists_test.dart' as code_actions_assists;
+import 'closing_labels_test.dart' as closing_labels;
 import 'code_actions_fixes_test.dart' as code_actions_fixes;
 import 'code_actions_source_test.dart' as code_actions_source;
 import 'completion_test.dart' as completion;
@@ -17,8 +20,11 @@
 import 'file_modification_test.dart' as file_modification;
 import 'folding_test.dart' as folding;
 import 'format_test.dart' as format;
+import 'super_test.dart' as get_super;
 import 'hover_test.dart' as hover;
+import 'implementation_test.dart' as implementation;
 import 'initialization_test.dart' as initialization;
+import 'mapping_test.dart' as mapping;
 import 'priority_files_test.dart' as priority_files;
 import 'references_test.dart' as references;
 import 'rename_test.dart' as rename;
@@ -28,7 +34,10 @@
 
 main() {
   defineReflectiveSuite(() {
+    analyzer_status.main();
+    cancel_request.main();
     change_workspace_folders.main();
+    closing_labels.main();
     code_actions_assists.main();
     code_actions_fixes.main();
     code_actions_source.main();
@@ -40,9 +49,12 @@
     file_modification.main();
     folding.main();
     format.main();
-    lsp_packet_transformer.main();
+    get_super.main();
     hover.main();
+    implementation.main();
     initialization.main();
+    lsp_packet_transformer.main();
+    mapping.main();
     priority_files.main();
     references.main();
     rename.main();
diff --git a/pkg/analysis_server/test/lsp/workspace_symbols_test.dart b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
index 72cad45..8bf1e30 100644
--- a/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
+++ b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -10,7 +11,9 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(WorkspaceSymbolsTest);
+    if (!AnalysisDriver.useSummary2) {
+      defineReflectiveTests(WorkspaceSymbolsTest);
+    }
   });
 }
 
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index 367e52e..6daf2ec 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -107,7 +107,8 @@
 
     notification = _convertJson(notification, lsp.NotificationMessage.fromJson);
 
-    _clientToServer.add(notification);
+    // Wrap send request in future to simulate WebSocket.
+    new Future(() => _clientToServer.add(notification));
   }
 
   @override
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 7b66304..07e7073 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -4,16 +4,17 @@
 
 import 'dart:mirrors';
 
-import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analysis_server/src/protocol_server.dart'
+    hide DiagnosticMessage;
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analyzer/dart/ast/ast.dart' as engine;
 import 'package:analyzer/dart/element/element.dart' as engine;
 import 'package:analyzer/dart/element/type.dart' as engine;
+import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/error.dart' as engine;
 import 'package:analyzer/src/dart/error/lint_codes.dart';
 import 'package:analyzer/src/error/codes.dart' as engine;
 import 'package:analyzer/src/generated/source.dart' as engine;
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -182,6 +183,7 @@
       engine.ElementKind.GENERIC_FUNCTION_TYPE: ElementKind.FUNCTION_TYPE_ALIAS,
       engine.ElementKind.IMPORT: ElementKind.UNKNOWN,
       engine.ElementKind.NAME: ElementKind.UNKNOWN,
+      engine.ElementKind.NEVER: ElementKind.UNKNOWN,
       engine.ElementKind.UNIVERSE: ElementKind.UNKNOWN
     });
   }
@@ -263,6 +265,18 @@
 
   MockAnalysisError(
       this.source, this.errorCode, this.offset, this.length, this.message);
+
+  @override
+  List<DiagnosticMessage> get contextMessages => null;
+
+  @override
+  String get correctionMessage => null;
+
+  @override
+  DiagnosticMessage get problemMessage => null;
+
+  @override
+  Severity get severity => null;
 }
 
 class MockErrorCode implements engine.ErrorCode {
@@ -290,6 +304,9 @@
   }
 
   @override
+  bool get hasPublishedDocs => false;
+
+  @override
   bool get isUnresolvedIdentifier => false;
 
   @override
diff --git a/pkg/analysis_server/test/search/declarations_test.dart b/pkg/analysis_server/test/search/declarations_test.dart
index 000ba70..3d505be 100644
--- a/pkg/analysis_server/test/search/declarations_test.dart
+++ b/pkg/analysis_server/test/search/declarations_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -14,7 +15,9 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(DeclarationsTest);
+    if (!AnalysisDriver.useSummary2) {
+      defineReflectiveTests(DeclarationsTest);
+    }
   });
 }
 
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 9d9a40d..dd6b22f 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
@@ -582,16 +582,20 @@
     //
     addTestSource('main() { int.parse("16", ^);}');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    });
   }
 
   test_ArgumentList_imported_function_named_param1() async {
     //
     addTestSource('main() { int.parse("16", r^);}');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    });
   }
 
   test_ArgumentList_imported_function_named_param2() async {
@@ -599,7 +603,7 @@
     addTestSource('main() { int.parse("16", radix: 7, ^);}');
     await computeSuggestions();
     assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'onError': '(String) → int'});
+        namedArgumentsWithTypes: {'onError': 'int Function(String)'});
   }
 
   test_ArgumentList_imported_function_named_param2a() async {
@@ -613,9 +617,10 @@
     //
     addTestSource('main() { int.parse("16", r^: 16);}');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'},
-        includeColon: false);
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    }, includeColon: false);
   }
 
   test_ArgumentList_imported_function_named_param_label2() async {
@@ -629,8 +634,10 @@
     //
     addTestSource('main() { int.parse("16", ^: 16);}');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    });
   }
 
   test_ArgumentList_local_constructor_named_fieldFormal_documentation() async {
@@ -886,8 +893,10 @@
 f(v,{int radix, int onError(String s)}){}
 main() { f("16", ^);}''');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    });
   }
 
   test_ArgumentList_local_function_named_param1() async {
@@ -896,8 +905,10 @@
 f(v,{int radix, int onError(String s)}){}
 main() { f("16", r^);}''');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    });
   }
 
   test_ArgumentList_local_function_named_param2() async {
@@ -907,7 +918,7 @@
 main() { f("16", radix: 7, ^);}''');
     await computeSuggestions();
     assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'onError': '(String) → int'});
+        namedArgumentsWithTypes: {'onError': 'int Function(String)'});
   }
 
   test_ArgumentList_local_function_named_param2a() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
index 49d5f95..8fccde1 100644
--- a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
@@ -2591,7 +2591,7 @@
     expect(suggestion.hasNamedParameters, false);
 
     suggestion = assertSuggestConstructor('C.bar');
-    expect(suggestion.element.parameters, "({dynamic boo: 'hoo', int z: 0})");
+    expect(suggestion.element.parameters, "({dynamic boo = 'hoo', int z = 0})");
     expect(suggestion.parameterNames, hasLength(2));
     expect(suggestion.parameterNames[0], 'boo');
     expect(suggestion.parameterTypes[0], 'dynamic');
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 2955d79..0bd591f 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -15,190 +15,24 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(KeywordContributorTest);
-    defineReflectiveTests(KeywordContributorWithUiAsCodeTest);
+    defineReflectiveTests(KeywordContributorWithNnbdTest);
   });
 }
 
 @reflectiveTest
 class KeywordContributorTest extends DartCompletionContributorTest {
-  static const List<Keyword> CLASS_BODY_KEYWORDS = const [
+  static const List<Keyword> COLLECTION_ELEMENT_START = const [
     Keyword.CONST,
-    Keyword.COVARIANT,
-    Keyword.DYNAMIC,
-    Keyword.FACTORY,
-    Keyword.FINAL,
-    Keyword.GET,
-    Keyword.OPERATOR,
-    Keyword.SET,
-    Keyword.STATIC,
-    Keyword.VAR,
-    Keyword.VOID
-  ];
-
-  static const List<Keyword> DECLARATION_KEYWORDS = const [
-    Keyword.ABSTRACT,
-    Keyword.CLASS,
-    Keyword.CONST,
-    Keyword.COVARIANT,
-    Keyword.DYNAMIC,
-    Keyword.FINAL,
-    Keyword.TYPEDEF,
-    Keyword.VAR,
-    Keyword.VOID
-  ];
-
-  static const List<Keyword> DIRECTIVE_AND_DECLARATION_KEYWORDS = const [
-    Keyword.ABSTRACT,
-    Keyword.CLASS,
-    Keyword.CONST,
-    Keyword.COVARIANT,
-    Keyword.DYNAMIC,
-    Keyword.EXPORT,
-    Keyword.FINAL,
-    Keyword.IMPORT,
-    Keyword.PART,
-    Keyword.TYPEDEF,
-    Keyword.VAR,
-    Keyword.VOID
-  ];
-
-  static const List<Keyword> DIRECTIVE_DECLARATION_AND_LIBRARY_KEYWORDS =
-      const [
-    Keyword.ABSTRACT,
-    Keyword.CLASS,
-    Keyword.CONST,
-    Keyword.COVARIANT,
-    Keyword.DYNAMIC,
-    Keyword.EXPORT,
-    Keyword.FINAL,
-    Keyword.IMPORT,
-    Keyword.LIBRARY,
-    Keyword.PART,
-    Keyword.TYPEDEF,
-    Keyword.VAR,
-    Keyword.VOID
+    Keyword.FALSE,
+    Keyword.FOR,
+    Keyword.IF,
+    Keyword.NEW,
+    Keyword.NULL,
+    Keyword.TRUE,
   ];
 
   static const List<String> NO_PSEUDO_KEYWORDS = const [];
 
-  static const List<Keyword> STMT_START_IN_CLASS = const [
-    Keyword.ASSERT,
-    Keyword.CONST,
-    Keyword.DO,
-    Keyword.FINAL,
-    Keyword.FOR,
-    Keyword.IF,
-    Keyword.NEW,
-    Keyword.RETURN,
-    Keyword.SUPER,
-    Keyword.SWITCH,
-    Keyword.THIS,
-    Keyword.THROW,
-    Keyword.TRY,
-    Keyword.VAR,
-    Keyword.VOID,
-    Keyword.WHILE
-  ];
-
-  static const List<Keyword> STMT_START_IN_LOOP_IN_CLASS = const [
-    Keyword.ASSERT,
-    Keyword.BREAK,
-    Keyword.CONST,
-    Keyword.CONTINUE,
-    Keyword.DO,
-    Keyword.FINAL,
-    Keyword.FOR,
-    Keyword.IF,
-    Keyword.NEW,
-    Keyword.RETURN,
-    Keyword.SUPER,
-    Keyword.SWITCH,
-    Keyword.THIS,
-    Keyword.THROW,
-    Keyword.TRY,
-    Keyword.VAR,
-    Keyword.VOID,
-    Keyword.WHILE
-  ];
-
-  static const List<Keyword> STMT_START_IN_SWITCH_IN_CLASS = const [
-    Keyword.ASSERT,
-    Keyword.BREAK,
-    Keyword.CASE,
-    Keyword.CONST,
-    Keyword.DEFAULT,
-    Keyword.DO,
-    Keyword.FINAL,
-    Keyword.FOR,
-    Keyword.IF,
-    Keyword.NEW,
-    Keyword.RETURN,
-    Keyword.SUPER,
-    Keyword.SWITCH,
-    Keyword.THIS,
-    Keyword.THROW,
-    Keyword.TRY,
-    Keyword.VAR,
-    Keyword.VOID,
-    Keyword.WHILE
-  ];
-
-  static const List<Keyword> STMT_START_IN_SWITCH_OUTSIDE_CLASS = const [
-    Keyword.ASSERT,
-    Keyword.BREAK,
-    Keyword.CASE,
-    Keyword.CONST,
-    Keyword.DEFAULT,
-    Keyword.DO,
-    Keyword.FINAL,
-    Keyword.FOR,
-    Keyword.IF,
-    Keyword.NEW,
-    Keyword.RETURN,
-    Keyword.SWITCH,
-    Keyword.THROW,
-    Keyword.TRY,
-    Keyword.VAR,
-    Keyword.VOID,
-    Keyword.WHILE
-  ];
-
-  static const List<Keyword> STMT_START_OUTSIDE_CLASS = const [
-    Keyword.ASSERT,
-    Keyword.CONST,
-    Keyword.DO,
-    Keyword.FINAL,
-    Keyword.FOR,
-    Keyword.IF,
-    Keyword.NEW,
-    Keyword.RETURN,
-    Keyword.SWITCH,
-    Keyword.THROW,
-    Keyword.TRY,
-    Keyword.VAR,
-    Keyword.VOID,
-    Keyword.WHILE
-  ];
-
-  static const List<Keyword> STMT_START_IN_LOOP_OUTSIDE_CLASS = const [
-    Keyword.ASSERT,
-    Keyword.BREAK,
-    Keyword.CONST,
-    Keyword.CONTINUE,
-    Keyword.DO,
-    Keyword.FINAL,
-    Keyword.FOR,
-    Keyword.IF,
-    Keyword.NEW,
-    Keyword.RETURN,
-    Keyword.SWITCH,
-    Keyword.THROW,
-    Keyword.TRY,
-    Keyword.VAR,
-    Keyword.VOID,
-    Keyword.WHILE
-  ];
-
   static const List<Keyword> EXPRESSION_START_INSTANCE = const [
     Keyword.CONST,
     Keyword.FALSE,
@@ -217,6 +51,190 @@
     Keyword.TRUE,
   ];
 
+  List<Keyword> get classBodyKeywords => [
+        Keyword.CONST,
+        Keyword.COVARIANT,
+        Keyword.DYNAMIC,
+        Keyword.FACTORY,
+        Keyword.FINAL,
+        Keyword.GET,
+        Keyword.OPERATOR,
+        Keyword.SET,
+        Keyword.STATIC,
+        Keyword.VAR,
+        Keyword.VOID
+      ];
+
+  List<Keyword> get constructorParameter => [Keyword.COVARIANT, Keyword.THIS];
+
+  List<Keyword> get declarationKeywords => [
+        Keyword.ABSTRACT,
+        Keyword.CLASS,
+        Keyword.CONST,
+        Keyword.COVARIANT,
+        Keyword.DYNAMIC,
+        Keyword.FINAL,
+        Keyword.TYPEDEF,
+        Keyword.VAR,
+        Keyword.VOID
+      ];
+
+  List<Keyword> get directiveAndDeclarationKeywords => [
+        Keyword.ABSTRACT,
+        Keyword.CLASS,
+        Keyword.CONST,
+        Keyword.COVARIANT,
+        Keyword.DYNAMIC,
+        Keyword.EXPORT,
+        Keyword.FINAL,
+        Keyword.IMPORT,
+        Keyword.PART,
+        Keyword.TYPEDEF,
+        Keyword.VAR,
+        Keyword.VOID
+      ];
+
+  List<Keyword> get directiveDeclarationAndLibraryKeywords =>
+      directiveDeclarationKeywords..add(Keyword.LIBRARY);
+
+  List<Keyword> get directiveDeclarationKeywords => [
+        Keyword.ABSTRACT,
+        Keyword.CLASS,
+        Keyword.CONST,
+        Keyword.COVARIANT,
+        Keyword.DYNAMIC,
+        Keyword.EXPORT,
+        Keyword.FINAL,
+        Keyword.IMPORT,
+        Keyword.PART,
+        Keyword.TYPEDEF,
+        Keyword.VAR,
+        Keyword.VOID
+      ];
+
+  List<Keyword> get methodParameter => [Keyword.COVARIANT];
+
+  List<Keyword> get statementStartInClass => [
+        Keyword.ASSERT,
+        Keyword.CONST,
+        Keyword.DO,
+        Keyword.FINAL,
+        Keyword.FOR,
+        Keyword.IF,
+        Keyword.NEW,
+        Keyword.RETURN,
+        Keyword.SUPER,
+        Keyword.SWITCH,
+        Keyword.THIS,
+        Keyword.THROW,
+        Keyword.TRY,
+        Keyword.VAR,
+        Keyword.VOID,
+        Keyword.WHILE
+      ];
+
+  List<Keyword> get statementStartInLoopInClass => [
+        Keyword.ASSERT,
+        Keyword.BREAK,
+        Keyword.CONST,
+        Keyword.CONTINUE,
+        Keyword.DO,
+        Keyword.FINAL,
+        Keyword.FOR,
+        Keyword.IF,
+        Keyword.NEW,
+        Keyword.RETURN,
+        Keyword.SUPER,
+        Keyword.SWITCH,
+        Keyword.THIS,
+        Keyword.THROW,
+        Keyword.TRY,
+        Keyword.VAR,
+        Keyword.VOID,
+        Keyword.WHILE
+      ];
+
+  List<Keyword> get statementStartInLoopOutsideClass => [
+        Keyword.ASSERT,
+        Keyword.BREAK,
+        Keyword.CONST,
+        Keyword.CONTINUE,
+        Keyword.DO,
+        Keyword.FINAL,
+        Keyword.FOR,
+        Keyword.IF,
+        Keyword.NEW,
+        Keyword.RETURN,
+        Keyword.SWITCH,
+        Keyword.THROW,
+        Keyword.TRY,
+        Keyword.VAR,
+        Keyword.VOID,
+        Keyword.WHILE
+      ];
+
+  List<Keyword> get statementStartInSwitchInClass => [
+        Keyword.ASSERT,
+        Keyword.BREAK,
+        Keyword.CASE,
+        Keyword.CONST,
+        Keyword.DEFAULT,
+        Keyword.DO,
+        Keyword.FINAL,
+        Keyword.FOR,
+        Keyword.IF,
+        Keyword.NEW,
+        Keyword.RETURN,
+        Keyword.SUPER,
+        Keyword.SWITCH,
+        Keyword.THIS,
+        Keyword.THROW,
+        Keyword.TRY,
+        Keyword.VAR,
+        Keyword.VOID,
+        Keyword.WHILE
+      ];
+
+  List<Keyword> get statementStartInSwitchOutsideClass => [
+        Keyword.ASSERT,
+        Keyword.BREAK,
+        Keyword.CASE,
+        Keyword.CONST,
+        Keyword.DEFAULT,
+        Keyword.DO,
+        Keyword.FINAL,
+        Keyword.FOR,
+        Keyword.IF,
+        Keyword.NEW,
+        Keyword.RETURN,
+        Keyword.SWITCH,
+        Keyword.THROW,
+        Keyword.TRY,
+        Keyword.VAR,
+        Keyword.VOID,
+        Keyword.WHILE
+      ];
+
+  List<Keyword> get statementStartOutsideClass => [
+        Keyword.ASSERT,
+        Keyword.CONST,
+        Keyword.DO,
+        Keyword.FINAL,
+        Keyword.FOR,
+        Keyword.IF,
+        Keyword.NEW,
+        Keyword.RETURN,
+        Keyword.SWITCH,
+        Keyword.THROW,
+        Keyword.TRY,
+        Keyword.VAR,
+        Keyword.VOID,
+        Keyword.WHILE
+      ];
+
+  List<Keyword> get staticMember =>
+      [Keyword.CONST, Keyword.COVARIANT, Keyword.FINAL];
+
   void assertSuggestKeywords(Iterable<Keyword> expectedKeywords,
       {List<String> pseudoKeywords: NO_PSEUDO_KEYWORDS,
       int relevance: DART_RELEVANCE_KEYWORD}) {
@@ -287,29 +305,29 @@
     return new KeywordContributor();
   }
 
-  test_after_class() async {
+  test_after_class_noPrefix() async {
     addTestSource('class A {} ^');
     await computeSuggestions();
-    assertSuggestKeywords(DECLARATION_KEYWORDS, relevance: DART_RELEVANCE_HIGH);
+    assertSuggestKeywords(declarationKeywords, relevance: DART_RELEVANCE_HIGH);
   }
 
-  test_after_class2() async {
+  test_after_class_prefix() async {
     addTestSource('class A {} c^');
     await computeSuggestions();
-    assertSuggestKeywords(DECLARATION_KEYWORDS, relevance: DART_RELEVANCE_HIGH);
+    assertSuggestKeywords(declarationKeywords, relevance: DART_RELEVANCE_HIGH);
   }
 
-  test_after_import() async {
+  test_after_import_noPrefix() async {
     addTestSource('import "foo"; ^');
     await computeSuggestions();
-    assertSuggestKeywords(DIRECTIVE_AND_DECLARATION_KEYWORDS,
+    assertSuggestKeywords(directiveAndDeclarationKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
-  test_after_import2() async {
+  test_after_import_prefix() async {
     addTestSource('import "foo"; c^');
     await computeSuggestions();
-    assertSuggestKeywords(DIRECTIVE_AND_DECLARATION_KEYWORDS,
+    assertSuggestKeywords(directiveAndDeclarationKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
@@ -328,14 +346,9 @@
     // and reports a single function expression argument
     // while analyzer adds the closing paren before the `a`
     // and adds synthetic `;`s making `a` a statement.
-    if (usingFastaParser) {
-      assertSuggestKeywords([],
-          pseudoKeywords: ['async', 'async*', 'sync*'],
-          relevance: DART_RELEVANCE_HIGH);
-    } else {
-      assertSuggestKeywords(STMT_START_OUTSIDE_CLASS,
-          pseudoKeywords: ['async', 'async*', 'sync*']);
-    }
+    assertSuggestKeywords([],
+        pseudoKeywords: ['async', 'async*', 'sync*'],
+        relevance: DART_RELEVANCE_HIGH);
   }
 
   test_anonymous_function_async3() async {
@@ -388,14 +401,9 @@
     await computeSuggestions();
     // Fasta interprets the argument as a function expression
     // while analyzer adds synthetic `;`s making `a` a statement.
-    if (usingFastaParser) {
-      assertSuggestKeywords([],
-          pseudoKeywords: ['async', 'async*', 'sync*'],
-          relevance: DART_RELEVANCE_HIGH);
-    } else {
-      assertSuggestKeywords(STMT_START_OUTSIDE_CLASS,
-          pseudoKeywords: ['async', 'async*', 'sync*']);
-    }
+    assertSuggestKeywords([],
+        pseudoKeywords: ['async', 'async*', 'sync*'],
+        relevance: DART_RELEVANCE_HIGH);
   }
 
   test_argument() async {
@@ -527,7 +535,7 @@
     var keywords = <Keyword>[];
     keywords.add(Keyword.CATCH);
     keywords.add(Keyword.FINALLY);
-    keywords.addAll(STMT_START_OUTSIDE_CLASS);
+    keywords.addAll(statementStartOutsideClass);
     assertSuggestKeywords(keywords, pseudoKeywords: ['on']);
   }
 
@@ -538,7 +546,7 @@
     var keywords = <Keyword>[];
     keywords.add(Keyword.CATCH);
     keywords.add(Keyword.FINALLY);
-    keywords.addAll(STMT_START_OUTSIDE_CLASS);
+    keywords.addAll(statementStartOutsideClass);
     assertSuggestKeywords(keywords, pseudoKeywords: ['on']);
   }
 
@@ -549,7 +557,7 @@
     var keywords = <Keyword>[];
     keywords.add(Keyword.CATCH);
     keywords.add(Keyword.FINALLY);
-    keywords.addAll(STMT_START_OUTSIDE_CLASS);
+    keywords.addAll(statementStartOutsideClass);
     assertSuggestKeywords(keywords, pseudoKeywords: ['on']);
   }
 
@@ -560,7 +568,7 @@
     var keywords = <Keyword>[];
     keywords.add(Keyword.CATCH);
     keywords.add(Keyword.FINALLY);
-    keywords.addAll(STMT_START_OUTSIDE_CLASS);
+    keywords.addAll(statementStartOutsideClass);
     assertSuggestKeywords(keywords, pseudoKeywords: ['on']);
   }
 
@@ -571,7 +579,7 @@
     var keywords = <Keyword>[];
     keywords.add(Keyword.CATCH);
     keywords.add(Keyword.FINALLY);
-    keywords.addAll(STMT_START_OUTSIDE_CLASS);
+    keywords.addAll(statementStartOutsideClass);
     assertSuggestKeywords(keywords, pseudoKeywords: ['on']);
   }
 
@@ -582,7 +590,7 @@
     var keywords = <Keyword>[];
     keywords.add(Keyword.CATCH);
     keywords.add(Keyword.FINALLY);
-    keywords.addAll(STMT_START_OUTSIDE_CLASS);
+    keywords.addAll(statementStartOutsideClass);
     assertSuggestKeywords(keywords, pseudoKeywords: ['on']);
   }
 
@@ -593,7 +601,7 @@
     var keywords = <Keyword>[];
     keywords.add(Keyword.CATCH);
     keywords.add(Keyword.FINALLY);
-    keywords.addAll(STMT_START_OUTSIDE_CLASS);
+    keywords.addAll(statementStartOutsideClass);
     assertSuggestKeywords(keywords, pseudoKeywords: ['on']);
   }
 
@@ -604,7 +612,7 @@
     var keywords = <Keyword>[];
     keywords.add(Keyword.CATCH);
     keywords.add(Keyword.FINALLY);
-    keywords.addAll(STMT_START_OUTSIDE_CLASS);
+    keywords.addAll(statementStartOutsideClass);
     assertSuggestKeywords(keywords, pseudoKeywords: ['on']);
   }
 
@@ -673,7 +681,7 @@
     addTestSource('main() {try {} catch (e) {^}}}');
     await computeSuggestions();
     var keywords = <Keyword>[];
-    keywords.addAll(STMT_START_OUTSIDE_CLASS);
+    keywords.addAll(statementStartOutsideClass);
     keywords.add(Keyword.RETHROW);
     assertSuggestKeywords(keywords);
   }
@@ -688,25 +696,25 @@
   test_class_body() async {
     addTestSource('class A {^}');
     await computeSuggestions();
-    assertSuggestKeywords(CLASS_BODY_KEYWORDS);
+    assertSuggestKeywords(classBodyKeywords);
   }
 
   test_class_body_beginning() async {
     addTestSource('class A {^ var foo;}');
     await computeSuggestions();
-    assertSuggestKeywords(CLASS_BODY_KEYWORDS);
+    assertSuggestKeywords(classBodyKeywords);
   }
 
   test_class_body_between() async {
     addTestSource('class A {var bar; ^ var foo;}');
     await computeSuggestions();
-    assertSuggestKeywords(CLASS_BODY_KEYWORDS);
+    assertSuggestKeywords(classBodyKeywords);
   }
 
   test_class_body_end() async {
     addTestSource('class A {var foo; ^}');
     await computeSuggestions();
-    assertSuggestKeywords(CLASS_BODY_KEYWORDS);
+    assertSuggestKeywords(classBodyKeywords);
   }
 
   test_class_extends() async {
@@ -775,7 +783,7 @@
 }
 ''');
     await computeSuggestions();
-    assertSuggestKeywords([Keyword.CONST, Keyword.COVARIANT, Keyword.FINAL]);
+    assertSuggestKeywords(staticMember);
   }
 
   test_class_member_final_afterStatic() async {
@@ -785,7 +793,7 @@
 }
 ''');
     await computeSuggestions();
-    assertSuggestKeywords([Keyword.CONST, Keyword.COVARIANT, Keyword.FINAL]);
+    assertSuggestKeywords(staticMember);
   }
 
   test_class_name() async {
@@ -851,50 +859,50 @@
     assertSuggestKeywords([Keyword.ASSERT, Keyword.SUPER, Keyword.THIS]);
   }
 
-  test_constructor_param() async {
+  test_constructor_param_noPrefix() async {
     addTestSource('class A { A(^) {});}');
     await computeSuggestions();
-    assertSuggestKeywords([Keyword.COVARIANT, Keyword.THIS]);
+    assertSuggestKeywords(constructorParameter);
   }
 
-  test_constructor_param2() async {
+  test_constructor_param_prefix() async {
     addTestSource('class A { A(t^) {});}');
     await computeSuggestions();
-    assertSuggestKeywords([Keyword.COVARIANT, Keyword.THIS]);
+    assertSuggestKeywords(constructorParameter);
   }
 
-  test_do_break_continue() async {
-    addTestSource('main() {do {^} while (true);}');
+  test_do_break_continue_insideClass() async {
+    addTestSource('class A {foo() {do {^} while (true);}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_LOOP_OUTSIDE_CLASS,
+    assertSuggestKeywords(statementStartInLoopInClass,
         relevance: DART_RELEVANCE_KEYWORD);
   }
 
-  test_do_break_continue2() async {
-    addTestSource('class A {foo() {do {^} while (true);}}');
+  test_do_break_continue_outsideClass() async {
+    addTestSource('main() {do {^} while (true);}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_LOOP_IN_CLASS,
+    assertSuggestKeywords(statementStartInLoopOutsideClass,
         relevance: DART_RELEVANCE_KEYWORD);
   }
 
   test_empty() async {
     addTestSource('^');
     await computeSuggestions();
-    assertSuggestKeywords(DIRECTIVE_DECLARATION_AND_LIBRARY_KEYWORDS,
+    assertSuggestKeywords(directiveDeclarationAndLibraryKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
-  test_for_break_continue() async {
-    addTestSource('main() {for (int x in myList) {^}}');
+  test_for_break_continue_insideClass() async {
+    addTestSource('class A {foo() {for (int x in myList) {^}}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_LOOP_OUTSIDE_CLASS,
+    assertSuggestKeywords(statementStartInLoopInClass,
         relevance: DART_RELEVANCE_KEYWORD);
   }
 
-  test_for_break_continue2() async {
-    addTestSource('class A {foo() {for (int x in myList) {^}}}');
+  test_for_break_continue_outsideClass() async {
+    addTestSource('main() {for (int x in myList) {^}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_LOOP_IN_CLASS,
+    assertSuggestKeywords(statementStartInLoopOutsideClass,
         relevance: DART_RELEVANCE_KEYWORD);
   }
 
@@ -937,7 +945,7 @@
   test_function_async() async {
     addTestSource('main()^');
     await computeSuggestions();
-    assertSuggestKeywords(usingFastaParser ? [] : DECLARATION_KEYWORDS,
+    assertSuggestKeywords([],
         pseudoKeywords: ['async', 'async*', 'sync*'],
         relevance: DART_RELEVANCE_HIGH);
   }
@@ -953,7 +961,7 @@
   test_function_async3() async {
     addTestSource('main()a^');
     await computeSuggestions();
-    assertSuggestKeywords(DECLARATION_KEYWORDS,
+    assertSuggestKeywords(declarationKeywords,
         pseudoKeywords: ['async', 'async*', 'sync*'],
         relevance: DART_RELEVANCE_HIGH);
   }
@@ -961,7 +969,7 @@
   test_function_async4() async {
     addTestSource('main()a^{}');
     await computeSuggestions();
-    assertSuggestKeywords(usingFastaParser ? [] : DECLARATION_KEYWORDS,
+    assertSuggestKeywords([],
         pseudoKeywords: ['async', 'async*', 'sync*'],
         relevance: DART_RELEVANCE_HIGH);
   }
@@ -969,7 +977,7 @@
   test_function_async5() async {
     addTestSource('main()a^ Foo foo;');
     await computeSuggestions();
-    assertSuggestKeywords(DECLARATION_KEYWORDS,
+    assertSuggestKeywords(declarationKeywords,
         pseudoKeywords: ['async', 'async*', 'sync*'],
         relevance: DART_RELEVANCE_HIGH);
   }
@@ -983,7 +991,7 @@
 }
 ''');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS);
+    assertSuggestKeywords(statementStartOutsideClass);
   }
 
   test_function_body_inClass_constructorInitializer_async() async {
@@ -995,7 +1003,8 @@
 }
 ''');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS, pseudoKeywords: ['await']);
+    assertSuggestKeywords(statementStartOutsideClass,
+        pseudoKeywords: ['await']);
   }
 
   test_function_body_inClass_constructorInitializer_async_star() async {
@@ -1007,7 +1016,7 @@
   }
   ''');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS,
+    assertSuggestKeywords(statementStartOutsideClass,
         pseudoKeywords: ['await', 'yield', 'yield*']);
   }
 
@@ -1018,7 +1027,7 @@
 }
 ''');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS);
+    assertSuggestKeywords(statementStartOutsideClass);
   }
 
   test_function_body_inClass_methodBody() async {
@@ -1030,7 +1039,7 @@
 }
 ''');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS);
+    assertSuggestKeywords(statementStartInClass);
   }
 
   test_function_body_inClass_methodBody_inFunction() async {
@@ -1044,7 +1053,7 @@
 }
 ''');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS);
+    assertSuggestKeywords(statementStartInClass);
   }
 
   test_function_body_inClass_methodBody_inFunction_async() async {
@@ -1058,7 +1067,7 @@
 }
 ''');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS, pseudoKeywords: ['await']);
+    assertSuggestKeywords(statementStartInClass, pseudoKeywords: ['await']);
   }
 
   test_function_body_inClass_methodBody_inFunction_async_star() async {
@@ -1072,82 +1081,89 @@
   }
   ''');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS,
+    assertSuggestKeywords(statementStartInClass,
         pseudoKeywords: ['await', 'yield', 'yield*']);
   }
 
   test_function_body_inUnit() async {
     addTestSource('main() {^}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS);
+    assertSuggestKeywords(statementStartOutsideClass);
   }
 
   test_function_body_inUnit_afterBlock() async {
     addTestSource('main() {{}^}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS);
+    assertSuggestKeywords(statementStartOutsideClass);
   }
 
   test_function_body_inUnit_async() async {
     addTestSource('main() async {^}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS, pseudoKeywords: ['await']);
+    assertSuggestKeywords(statementStartOutsideClass,
+        pseudoKeywords: ['await']);
   }
 
   test_function_body_inUnit_async_star() async {
     addTestSource('main() async* {n^}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS,
+    assertSuggestKeywords(statementStartOutsideClass,
         pseudoKeywords: ['await', 'yield', 'yield*']);
   }
 
   test_function_body_inUnit_async_star2() async {
     addTestSource('main() async* {n^ foo}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS,
+    assertSuggestKeywords(statementStartOutsideClass,
         pseudoKeywords: ['await', 'yield', 'yield*']);
   }
 
   test_function_body_inUnit_sync_star() async {
     addTestSource('main() sync* {n^}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS,
+    assertSuggestKeywords(statementStartOutsideClass,
         pseudoKeywords: ['await', 'yield', 'yield*']);
   }
 
   test_function_body_inUnit_sync_star2() async {
     addTestSource('main() sync* {n^ foo}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS,
+    assertSuggestKeywords(statementStartOutsideClass,
         pseudoKeywords: ['await', 'yield', 'yield*']);
   }
 
   test_if_after_else() async {
     addTestSource('main() { if (true) {} else ^ }');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS,
+    assertSuggestKeywords(statementStartOutsideClass,
         relevance: DART_RELEVANCE_KEYWORD);
   }
 
   test_if_afterThen_nextCloseCurlyBrace0() async {
     addTestSource('main() { if (true) {} ^ }');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS.toList()..add(Keyword.ELSE),
-        relevance: DART_RELEVANCE_KEYWORD);
+    List<Keyword> keywords = [];
+    keywords.addAll(statementStartOutsideClass);
+    keywords.add(Keyword.ELSE);
+    assertSuggestKeywords(keywords, relevance: DART_RELEVANCE_KEYWORD);
   }
 
   test_if_afterThen_nextCloseCurlyBrace1() async {
     addTestSource('main() { if (true) {} e^ }');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS.toList()..add(Keyword.ELSE),
-        relevance: DART_RELEVANCE_KEYWORD);
+    List<Keyword> keywords = [];
+    keywords.addAll(statementStartOutsideClass);
+    keywords.add(Keyword.ELSE);
+    assertSuggestKeywords(keywords, relevance: DART_RELEVANCE_KEYWORD);
   }
 
   test_if_afterThen_nextStatement0() async {
     addTestSource('main() { if (true) {} ^ print(0); }');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS.toList()..add(Keyword.ELSE),
-        relevance: DART_RELEVANCE_KEYWORD);
+    List<Keyword> keywords = [];
+    keywords.addAll(statementStartOutsideClass);
+    keywords.add(Keyword.ELSE);
+    assertSuggestKeywords(keywords, relevance: DART_RELEVANCE_KEYWORD);
   }
 
   test_if_condition_isKeyword() async {
@@ -1189,49 +1205,169 @@
   test_if_in_class() async {
     addTestSource('class A {foo() {if (true) ^}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS);
+    assertSuggestKeywords(statementStartInClass);
   }
 
   test_if_in_class2() async {
     addTestSource('class A {foo() {if (true) ^;}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS);
+    assertSuggestKeywords(statementStartInClass);
   }
 
   test_if_in_class3() async {
     addTestSource('class A {foo() {if (true) r^;}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS);
+    assertSuggestKeywords(statementStartInClass);
   }
 
   test_if_in_class4() async {
     addTestSource('class A {foo() {if (true) ^ go();}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS);
+    assertSuggestKeywords(statementStartInClass);
   }
 
   test_if_outside_class() async {
     addTestSource('foo() {if (true) ^}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS);
+    assertSuggestKeywords(statementStartOutsideClass);
   }
 
   test_if_outside_class2() async {
     addTestSource('foo() {if (true) ^;}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS);
+    assertSuggestKeywords(statementStartOutsideClass);
   }
 
   test_if_outside_class3() async {
     addTestSource('foo() {if (true) r^;}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS);
+    assertSuggestKeywords(statementStartOutsideClass);
   }
 
   test_if_outside_class4() async {
     addTestSource('foo() {if (true) ^ go();}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_OUTSIDE_CLASS);
+    assertSuggestKeywords(statementStartOutsideClass);
+  }
+
+  test_ifOrForElement_forElement() async {
+    addTestSource('''
+f() => [for (var e in c) ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_ifElement_else() async {
+    addTestSource('''
+f() => [if (true) 1 else ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_ifElement_then() async {
+    addTestSource('''
+f() => [if (true) ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_empty() async {
+    addTestSource('''
+f() => [^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_first() async {
+    addTestSource('''
+f() => [^1, 2];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_last() async {
+    addTestSource('''
+f() => [1, 2, ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_middle() async {
+    addTestSource('''
+f() => [1, ^, 2];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_empty() async {
+    addTestSource('''
+f() => <String, int>{^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_first() async {
+    addTestSource('''
+f() => <String, int>{^'a' : 1};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_last() async {
+    addTestSource('''
+f() => <String, int>{'a' : 1, 'b' : 2, ^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_middle() async {
+    addTestSource('''
+f() => <String, int>{'a' : 1, ^, 'b' : 2];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_empty() async {
+    addTestSource('''
+f() => <int>{^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_first() async {
+    addTestSource('''
+f() => <int>{^1, 2};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_last() async {
+    addTestSource('''
+f() => <int>{1, 2, ^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_middle() async {
+    addTestSource('''
+f() => <int>{1, ^, 2};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
   }
 
   test_import() async {
@@ -1370,7 +1506,7 @@
     expect(replacementOffset, 0);
     expect(replacementLength, 3);
     // TODO(danrubel) should not suggest declaration keywords
-    assertSuggestKeywords(DIRECTIVE_DECLARATION_AND_LIBRARY_KEYWORDS,
+    assertSuggestKeywords(directiveDeclarationAndLibraryKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
@@ -1380,7 +1516,7 @@
     expect(replacementOffset, 0);
     expect(replacementLength, 3);
     // TODO(danrubel) should not suggest declaration keywords
-    assertSuggestKeywords(DIRECTIVE_DECLARATION_AND_LIBRARY_KEYWORDS,
+    assertSuggestKeywords(directiveDeclarationAndLibraryKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
@@ -1390,7 +1526,7 @@
     expect(replacementOffset, 1);
     expect(replacementLength, 3);
     // TODO(danrubel) should not suggest declaration keywords
-    assertSuggestKeywords(DIRECTIVE_DECLARATION_AND_LIBRARY_KEYWORDS,
+    assertSuggestKeywords(directiveDeclarationAndLibraryKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
@@ -1400,7 +1536,7 @@
     expect(replacementOffset, 0);
     expect(replacementLength, 0);
     // TODO(danrubel) should not suggest declaration keywords
-    assertSuggestKeywords(DIRECTIVE_DECLARATION_AND_LIBRARY_KEYWORDS,
+    assertSuggestKeywords(directiveDeclarationAndLibraryKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
@@ -1410,7 +1546,7 @@
     expect(replacementOffset, 14);
     expect(replacementLength, 3);
     // TODO(danrubel) should not suggest declaration keywords
-    assertSuggestKeywords(DIRECTIVE_AND_DECLARATION_KEYWORDS,
+    assertSuggestKeywords(directiveDeclarationKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
@@ -1421,7 +1557,7 @@
     expect(replacementOffset, 32);
     expect(replacementLength, 3);
     // TODO(danrubel) should not suggest declaration keywords
-    assertSuggestKeywords(DIRECTIVE_AND_DECLARATION_KEYWORDS,
+    assertSuggestKeywords(directiveDeclarationKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
@@ -1452,7 +1588,7 @@
   test_library() async {
     addTestSource('library foo;^');
     await computeSuggestions();
-    assertSuggestKeywords(DIRECTIVE_AND_DECLARATION_KEYWORDS,
+    assertSuggestKeywords(directiveAndDeclarationKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
@@ -1483,7 +1619,7 @@
   test_method_async() async {
     addTestSource('class A { foo() ^}');
     await computeSuggestions();
-    assertSuggestKeywords(CLASS_BODY_KEYWORDS,
+    assertSuggestKeywords(classBodyKeywords,
         pseudoKeywords: ['async', 'async*', 'sync*']);
   }
 
@@ -1498,34 +1634,29 @@
   test_method_async3() async {
     addTestSource('class A { foo() a^}');
     await computeSuggestions();
-    assertSuggestKeywords(CLASS_BODY_KEYWORDS,
+    assertSuggestKeywords(classBodyKeywords,
         pseudoKeywords: ['async', 'async*', 'sync*']);
   }
 
   test_method_async4() async {
     addTestSource('class A { foo() a^{}}');
     await computeSuggestions();
-    if (usingFastaParser) {
-      assertSuggestKeywords([],
-          pseudoKeywords: ['async', 'async*', 'sync*'],
-          relevance: DART_RELEVANCE_HIGH);
-    } else {
-      assertSuggestKeywords(CLASS_BODY_KEYWORDS,
-          pseudoKeywords: ['async', 'async*', 'sync*']);
-    }
+    assertSuggestKeywords([],
+        pseudoKeywords: ['async', 'async*', 'sync*'],
+        relevance: DART_RELEVANCE_HIGH);
   }
 
   test_method_async5() async {
     addTestSource('class A { foo() ^ Foo foo;}');
     await computeSuggestions();
-    assertSuggestKeywords(CLASS_BODY_KEYWORDS,
+    assertSuggestKeywords(classBodyKeywords,
         pseudoKeywords: ['async', 'async*', 'sync*']);
   }
 
   test_method_async6() async {
     addTestSource('class A { foo() a^ Foo foo;}');
     await computeSuggestions();
-    assertSuggestKeywords(CLASS_BODY_KEYWORDS,
+    assertSuggestKeywords(classBodyKeywords,
         pseudoKeywords: ['async', 'async*', 'sync*']);
   }
 
@@ -1539,14 +1670,14 @@
   test_method_async8() async {
     addTestSource('class A { foo() a^ Foo foo;}');
     await computeSuggestions();
-    assertSuggestKeywords(CLASS_BODY_KEYWORDS,
+    assertSuggestKeywords(classBodyKeywords,
         pseudoKeywords: ['async', 'async*', 'sync*']);
   }
 
   test_method_body() async {
     addTestSource('class A { foo() {^}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS);
+    assertSuggestKeywords(statementStartInClass);
   }
 
   test_method_body2() async {
@@ -1570,7 +1701,7 @@
   test_method_body_async() async {
     addTestSource('class A { foo() async {^}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS, pseudoKeywords: ['await']);
+    assertSuggestKeywords(statementStartInClass, pseudoKeywords: ['await']);
   }
 
   test_method_body_async2() async {
@@ -1594,7 +1725,7 @@
   test_method_body_async_star() async {
     addTestSource('class A { foo() async* {^}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS,
+    assertSuggestKeywords(statementStartInClass,
         pseudoKeywords: ['await', 'yield', 'yield*']);
   }
 
@@ -1628,20 +1759,6 @@
     assertNoSuggestions();
   }
 
-  test_method_param() async {
-    addTestSource('class A { foo(^) {});}');
-    await computeSuggestions();
-    expect(suggestions, isNotEmpty);
-    assertSuggestKeywords([Keyword.COVARIANT]);
-  }
-
-  test_method_param2() async {
-    addTestSource('class A { foo(t^) {});}');
-    await computeSuggestions();
-    expect(suggestions, isNotEmpty);
-    assertSuggestKeywords([Keyword.COVARIANT]);
-  }
-
   test_method_param_named_init() async {
     addTestSource('class A { foo({bool bar: ^}) {}}');
     await computeSuggestions();
@@ -1656,6 +1773,13 @@
     assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
   }
 
+  test_method_param_noPrefix() async {
+    addTestSource('class A { foo(^) {});}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(methodParameter);
+  }
+
   test_method_param_positional_init() async {
     addTestSource('class A { foo([bool bar = ^]) {}}');
     await computeSuggestions();
@@ -1670,6 +1794,13 @@
     assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
   }
 
+  test_method_param_prefix() async {
+    addTestSource('class A { foo(t^) {});}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(methodParameter);
+  }
+
   test_mixin() async {
     addTestSource('mixin M o^ { }');
     await computeSuggestions();
@@ -1716,21 +1847,21 @@
   test_part_of() async {
     addTestSource('part of foo;^');
     await computeSuggestions();
-    assertSuggestKeywords(DIRECTIVE_AND_DECLARATION_KEYWORDS,
+    assertSuggestKeywords(directiveAndDeclarationKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
   test_partial_class() async {
     addTestSource('cl^');
     await computeSuggestions();
-    assertSuggestKeywords(DIRECTIVE_DECLARATION_AND_LIBRARY_KEYWORDS,
+    assertSuggestKeywords(directiveDeclarationAndLibraryKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
   test_partial_class2() async {
     addTestSource('library a; cl^');
     await computeSuggestions();
-    assertSuggestKeywords(DIRECTIVE_AND_DECLARATION_KEYWORDS,
+    assertSuggestKeywords(directiveAndDeclarationKeywords,
         relevance: DART_RELEVANCE_HIGH);
   }
 
@@ -1770,6 +1901,14 @@
     assertSuggestKeywords([]);
   }
 
+  test_spreadElement() async {
+    addTestSource('''
+f() => [...^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(KeywordContributorTest.EXPRESSION_START_NO_INSTANCE);
+  }
+
   test_switch_expression() async {
     addTestSource('main() {switch(^) {}}');
     await computeSuggestions();
@@ -1843,29 +1982,29 @@
         relevance: DART_RELEVANCE_HIGH);
   }
 
-  test_switch_statement() async {
-    addTestSource('main() {switch(1) {case 1:^}}');
-    await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_SWITCH_OUTSIDE_CLASS);
-  }
-
-  test_switch_statement2() async {
+  test_switch_statement_insideClass() async {
     addTestSource('class A{foo() {switch(1) {case 1:^}}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_SWITCH_IN_CLASS);
+    assertSuggestKeywords(statementStartInSwitchInClass);
+  }
+
+  test_switch_statement_outsideClass() async {
+    addTestSource('main() {switch(1) {case 1:^}}');
+    await computeSuggestions();
+    assertSuggestKeywords(statementStartInSwitchOutsideClass);
   }
 
   test_while_break_continue() async {
     addTestSource('main() {while (true) {^}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_LOOP_OUTSIDE_CLASS,
+    assertSuggestKeywords(statementStartInLoopOutsideClass,
         relevance: DART_RELEVANCE_KEYWORD);
   }
 
   test_while_break_continue2() async {
     addTestSource('class A {foo() {while (true) {^}}}');
     await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_LOOP_IN_CLASS,
+    assertSuggestKeywords(statementStartInLoopInClass,
         relevance: DART_RELEVANCE_KEYWORD);
   }
 
@@ -1886,151 +2025,65 @@
 }
 
 @reflectiveTest
-class KeywordContributorWithUiAsCodeTest extends KeywordContributorTest {
-  static const List<Keyword> COLLECTION_ELEMENT_START = const [
-    Keyword.CONST,
-    Keyword.FALSE,
-    Keyword.FOR,
-    Keyword.IF,
-    Keyword.NEW,
-    Keyword.NULL,
-    Keyword.TRUE,
-  ];
+class KeywordContributorWithNnbdTest extends KeywordContributorTest {
+  @override
+  List<Keyword> get classBodyKeywords =>
+      super.classBodyKeywords..add(Keyword.LATE);
+
+  @override
+  List<Keyword> get constructorParameter =>
+      super.constructorParameter..add(Keyword.REQUIRED);
+
+  @override
+  List<Keyword> get declarationKeywords =>
+      super.declarationKeywords..add(Keyword.LATE);
+
+  @override
+  List<Keyword> get directiveAndDeclarationKeywords =>
+      super.directiveAndDeclarationKeywords..add(Keyword.LATE);
+
+  @override
+  List<Keyword> get directiveDeclarationAndLibraryKeywords =>
+      super.directiveDeclarationAndLibraryKeywords..add(Keyword.LATE);
+
+  @override
+  List<Keyword> get directiveDeclarationKeywords =>
+      super.directiveDeclarationKeywords..add(Keyword.LATE);
+
+  @override
+  List<Keyword> get methodParameter =>
+      super.methodParameter..add(Keyword.REQUIRED);
+
+  @override
+  List<Keyword> get statementStartInClass =>
+      super.statementStartInClass..add(Keyword.LATE);
+
+  @override
+  List<Keyword> get statementStartInLoopInClass =>
+      super.statementStartInLoopInClass..add(Keyword.LATE);
+
+  @override
+  List<Keyword> get statementStartInLoopOutsideClass =>
+      super.statementStartInLoopOutsideClass..add(Keyword.LATE);
+
+  @override
+  List<Keyword> get statementStartInSwitchInClass =>
+      super.statementStartInSwitchInClass..add(Keyword.LATE);
+
+  @override
+  List<Keyword> get statementStartInSwitchOutsideClass =>
+      super.statementStartInSwitchOutsideClass..add(Keyword.LATE);
+
+  @override
+  List<Keyword> get statementStartOutsideClass =>
+      super.statementStartOutsideClass..add(Keyword.LATE);
+
+  @override
+  List<Keyword> get staticMember => super.staticMember..add(Keyword.LATE);
 
   @override
   void setupResourceProvider() {
     super.setupResourceProvider();
-    createAnalysisOptionsFile(experiments: [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ]);
-  }
-
-  test_ifOrForElement_forElement() async {
-    addTestSource('''
-f() => [for (var e in c) ^];
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_ifElement_else() async {
-    addTestSource('''
-f() => [if (true) 1 else ^];
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_ifElement_then() async {
-    addTestSource('''
-f() => [if (true) ^];
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_list_empty() async {
-    addTestSource('''
-f() => [^];
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_list_first() async {
-    addTestSource('''
-f() => [^1, 2];
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_list_last() async {
-    addTestSource('''
-f() => [1, 2, ^];
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_list_middle() async {
-    addTestSource('''
-f() => [1, ^, 2];
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_map_empty() async {
-    addTestSource('''
-f() => <String, int>{^};
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_map_first() async {
-    addTestSource('''
-f() => <String, int>{^'a' : 1};
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_map_last() async {
-    addTestSource('''
-f() => <String, int>{'a' : 1, 'b' : 2, ^};
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_map_middle() async {
-    addTestSource('''
-f() => <String, int>{'a' : 1, ^, 'b' : 2];
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_set_empty() async {
-    addTestSource('''
-f() => <int>{^};
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_set_first() async {
-    addTestSource('''
-f() => <int>{^1, 2};
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_set_last() async {
-    addTestSource('''
-f() => <int>{1, 2, ^};
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_ifOrForElement_set_middle() async {
-    addTestSource('''
-f() => <int>{1, ^, 2};
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(COLLECTION_ELEMENT_START);
-  }
-
-  test_spreadElement() async {
-    addTestSource('''
-f() => [...^];
-''');
-    await computeSuggestions();
-    assertSuggestKeywords(KeywordContributorTest.EXPRESSION_START_NO_INSTANCE);
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
   }
 }
diff --git a/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
index b0e10ba..237946b 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
@@ -2368,7 +2368,8 @@
     expect(suggestion.hasNamedParameters, false);
 
     suggestion = assertSuggestConstructor('C.bar');
-    expect(suggestion.element.parameters, '({dynamic boo: \'hoo\', int z: 0})');
+    expect(
+        suggestion.element.parameters, '({dynamic boo = \'hoo\', int z = 0})');
     expect(suggestion.element.returnType, 'C');
     expect(suggestion.declaringType, 'C');
     expect(suggestion.parameterNames, hasLength(2));
diff --git a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
index 2d776e06..49a2d65 100644
--- a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
@@ -42,7 +42,28 @@
     assertNotSuggested('a');
   }
 
-  test_ExpressionStatement_long() async {
+  test_ExpressionStatement_inConstructorBody() async {
+    addTestSource('''
+    class A { A() { AbstractCrazyNonsenseClassName ^ } }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+    // private versions aren't provided as this completion is in a constructor
+    // body
+    assertNotSuggested('_abstractCrazyNonsenseClassName');
+    assertNotSuggested('_crazyNonsenseClassName');
+    assertNotSuggested('_nonsenseClassName');
+    assertNotSuggested('_className');
+    assertNotSuggested('_name');
+  }
+
+  test_ExpressionStatement_inFunctionBody() async {
     addTestSource('''
     f() { AbstractCrazyNonsenseClassName ^ }
     ''');
@@ -54,7 +75,27 @@
     assertSuggestName('nonsenseClassName');
     assertSuggestName('className');
     assertSuggestName('name');
-    // private versions
+    // private versions aren't provided as this completion is in a function body
+    assertNotSuggested('_abstractCrazyNonsenseClassName');
+    assertNotSuggested('_crazyNonsenseClassName');
+    assertNotSuggested('_nonsenseClassName');
+    assertNotSuggested('_className');
+    assertNotSuggested('_name');
+  }
+
+  test_ExpressionStatement_inMethodBody() async {
+    addTestSource('''
+    class A { f() { AbstractCrazyNonsenseClassName ^ } }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+    // private versions aren't provided as this completion is in a method body
     assertNotSuggested('_abstractCrazyNonsenseClassName');
     assertNotSuggested('_crazyNonsenseClassName');
     assertNotSuggested('_nonsenseClassName');
@@ -146,6 +187,112 @@
     assertNotSuggested('_a');
   }
 
+  @failingTest
+  test_ForStatement() async {
+    addTestSource('''
+    f() { for(AbstractCrazyNonsenseClassName ^) {} }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+    // private versions
+    assertNotSuggested('_abstractCrazyNonsenseClassName');
+    assertNotSuggested('_crazyNonsenseClassName');
+    assertNotSuggested('_nonsenseClassName');
+    assertNotSuggested('_className');
+    assertNotSuggested('_name');
+  }
+
+  test_ForStatement_partial() async {
+    addTestSource('''
+    f() { for(AbstractCrazyNonsenseClassName a^) {} }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset - 1);
+    expect(replacementLength, 1);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+    // private versions
+    assertNotSuggested('_abstractCrazyNonsenseClassName');
+    assertNotSuggested('_crazyNonsenseClassName');
+    assertNotSuggested('_nonsenseClassName');
+    assertNotSuggested('_className');
+    assertNotSuggested('_name');
+  }
+
+  @failingTest
+  test_ForStatement_prefixed() async {
+    addTestSource('''
+    f() { for(prefix.AbstractCrazyNonsenseClassName ^) {} }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset - 1);
+    expect(replacementLength, 1);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+    // private versions
+    assertNotSuggested('_abstractCrazyNonsenseClassName');
+    assertNotSuggested('_crazyNonsenseClassName');
+    assertNotSuggested('_nonsenseClassName');
+    assertNotSuggested('_className');
+    assertNotSuggested('_name');
+  }
+
+  test_ForStatement_prefixed_partial() async {
+    addTestSource('''
+    f() { for(prefix.AbstractCrazyNonsenseClassName a^) {} }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset - 1);
+    expect(replacementLength, 1);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+    // private versions
+    assertNotSuggested('_abstractCrazyNonsenseClassName');
+    assertNotSuggested('_crazyNonsenseClassName');
+    assertNotSuggested('_nonsenseClassName');
+    assertNotSuggested('_className');
+    assertNotSuggested('_name');
+  }
+
+  test_SimpleFormalParameter_FormalParameterList() async {
+    addTestSource('''
+f(A ^) {}
+''');
+    await computeSuggestions();
+    expect(replacementOffset, 4);
+    expect(replacementLength, 0);
+    assertSuggestName('a');
+    // private version
+    assertNotSuggested('_a');
+  }
+
+  test_SimpleFormalParameter_itself() async {
+    addTestSource('''
+f(A n^) {}
+''');
+    await computeSuggestions();
+    expect(replacementOffset, 4);
+    expect(replacementLength, 1);
+    assertSuggestName('a');
+    // private version
+    assertNotSuggested('_a');
+  }
+
   test_TopLevelVariableDeclaration_dont_suggest_type() async {
     addTestSource('''
     a ^
diff --git a/pkg/analysis_server/test/services/linter/linter_test.dart b/pkg/analysis_server/test/services/linter/linter_test.dart
index 3965bba..14b0054 100644
--- a/pkg/analysis_server/test/services/linter/linter_test.dart
+++ b/pkg/analysis_server/test/services/linter/linter_test.dart
@@ -76,5 +76,8 @@
 
 class _TestSource implements Source {
   @override
+  String get fullName => '/package/lib/test.dart';
+
+  @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/analysis_server/test/services/refactoring/abstract_rename.dart b/pkg/analysis_server/test/services/refactoring/abstract_rename.dart
index 80308ef..3bbe0fa 100644
--- a/pkg/analysis_server/test/services/refactoring/abstract_rename.dart
+++ b/pkg/analysis_server/test/services/refactoring/abstract_rename.dart
@@ -56,8 +56,7 @@
    */
   void createRenameRefactoringForElement(Element element) {
     var workspace = new RefactoringWorkspace([driver], searchEngine);
-    var session = testAnalysisResult.session;
-    refactoring = new RenameRefactoring(workspace, session, element);
+    refactoring = new RenameRefactoring(workspace, testAnalysisResult, element);
     expect(refactoring, isNotNull, reason: "No refactoring for '$element'.");
   }
 
diff --git a/pkg/analysis_server/test/services/refactoring/move_file_test.dart b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
index 59f07b6..6f6fe1f 100644
--- a/pkg/analysis_server/test/services/refactoring/move_file_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
@@ -23,15 +23,16 @@
   MoveFileRefactoring refactoring;
 
   test_file_containing_imports_exports_parts() async {
-    String pathA = '/home/test/000/1111/a.dart';
-    String pathB = '/home/test/000/1111/b.dart';
-    String pathC = '/home/test/000/1111/22/c.dart';
-    testFile = '/home/test/000/1111/test.dart';
+    String pathA = convertPath('/home/test/000/1111/a.dart');
+    String pathB = convertPath('/home/test/000/1111/b.dart');
+    String pathC = convertPath('/home/test/000/1111/22/c.dart');
+    testFile = convertPath('/home/test/000/1111/test.dart');
     addSource('/absolute/uri.dart', '');
     addSource(pathA, 'part of lib;');
     addSource(pathB, "import 'test.dart';");
     addSource(pathC, '');
-    addTestSource('''
+    verifyNoTestUnitErrors = false;
+    await resolveTestUnit('''
 library lib;
 import 'dart:math';
 import '22/c.dart';
@@ -55,14 +56,18 @@
 ''');
   }
 
-  test_file_imported_with_package_uri() async {
-    newFile('/home/test/lib/old_name.dart', content: '');
+  test_file_imported_with_package_uri_down() async {
+    var file = newFile('/home/test/lib/old_name.dart', content: '');
     addTestSource(r'''
 import 'package:test/old_name.dart';
 ''');
 
-    _createRefactoring('/home/test/lib/222/new_name.dart',
-        oldName: '/home/test/lib/old_name.dart');
+    // Since the file being refactored isn't the test source, we set the
+    // testAnalysisResult manually here, the path is referenced through the
+    // referenced File object to run on Windows:
+    testAnalysisResult = await session.getResolvedUnit(file.path);
+
+    _createRefactoring('/home/test/lib/222/new_name.dart', oldFile: file.path);
     await _assertSuccessfulRefactoring();
 
     assertFileChangeResult(testFile, '''
@@ -70,29 +75,138 @@
 ''');
   }
 
-  test_file_importedLibrary_down() async {
-    String pathA = '/home/test/000/1111/a.dart';
-    testFile = '/home/test/000/1111/test.dart';
+  @failingTest
+  test_file_imported_with_package_uri_lib_change() async {
+    // The current testing stack does not support creating such bazel roots
+    var file =
+        newFile('/home/test0/test1/test2/lib/111/name.dart', content: '');
+    addTestSource(r'''
+import 'package:test0.test1.test2/111/name.dart';
+''');
+
+    // Since the file being refactored isn't the test source, we set the
+    // testAnalysisResult manually here, the path is referenced through the
+    // referenced File object to run on Windows:
+    testAnalysisResult = await session.getResolvedUnit(file.path);
+
+    _createRefactoring('/home/test0/test1/test3/lib/111/name.dart',
+        oldFile: file.path);
+    await _assertSuccessfulRefactoring();
+
+    assertFileChangeResult(testFile, '''
+import 'package:test0.test1.test3/111/name.dart';
+''');
+  }
+
+  @failingTest
+  test_file_imported_with_package_uri_lib_change_down() async {
+    // The current testing stack does not support creating such bazel roots
+    var file =
+        newFile('/home/test0/test1/test2/lib/111/name.dart', content: '');
+    addTestSource(r'''
+import 'package:test0.test1.test2/111/name.dart';
+''');
+
+    // Since the file being refactored isn't the test source, we set the
+    // testAnalysisResult manually here, the path is referenced through the
+    // referenced File object to run on Windows:
+    testAnalysisResult = await session.getResolvedUnit(file.path);
+
+    _createRefactoring('/home/test0/test1/test2/test3/lib/111/name.dart',
+        oldFile: file.path);
+    await _assertSuccessfulRefactoring();
+
+    assertFileChangeResult(testFile, '''
+import 'package:test0.test1.test2.test3/111/name.dart';
+''');
+  }
+
+  @failingTest
+  test_file_imported_with_package_uri_lib_change_up() async {
+    // The current testing stack does not support creating such bazel roots
+    var file =
+        newFile('/home/test0/test1/test2/lib/111/name.dart', content: '');
+    addTestSource(r'''
+import 'package:test0.test1.test2/111/name.dart';
+''');
+
+    // Since the file being refactored isn't the test source, we set the
+    // testAnalysisResult manually here, the path is referenced through the
+    // referenced File object to run on Windows:
+    testAnalysisResult = await session.getResolvedUnit(file.path);
+
+    _createRefactoring('/home/test0/test1/lib/111/name.dart',
+        oldFile: file.path);
+    await _assertSuccessfulRefactoring();
+
+    assertFileChangeResult(testFile, '''
+import 'package:test0.test1/111/name.dart';
+''');
+  }
+
+  test_file_imported_with_package_uri_sideways() async {
+    var file = newFile('/home/test/lib/111/old_name.dart', content: '');
+    addTestSource(r'''
+import 'package:test/111/old_name.dart';
+''');
+
+    // Since the file being refactored isn't the test source, we set the
+    // testAnalysisResult manually here, the path is referenced through the
+    // referenced File object to run on Windows:
+    testAnalysisResult = await session.getResolvedUnit(file.path);
+
+    _createRefactoring('/home/test/lib/222/new_name.dart', oldFile: file.path);
+    await _assertSuccessfulRefactoring();
+
+    assertFileChangeResult(testFile, '''
+import 'package:test/222/new_name.dart';
+''');
+  }
+
+  test_file_imported_with_package_uri_up() async {
+    var file = newFile('/home/test/lib/222/old_name.dart', content: '');
+    addTestSource(r'''
+import 'package:test/222/old_name.dart';
+''');
+
+    // Since the file being refactored isn't the test source, we set the
+    // testAnalysisResult manually here, the path is referenced through the
+    // referenced File object to run on Windows:
+    testAnalysisResult = await session.getResolvedUnit(file.path);
+
+    _createRefactoring('/home/test/lib/new_name.dart', oldFile: file.path);
+    await _assertSuccessfulRefactoring();
+
+    assertFileChangeResult(testFile, '''
+import 'package:test/new_name.dart';
+''');
+  }
+
+  test_file_imported_with_relative_uri_down() async {
+    String pathA = convertPath('/home/test/000/1111/a.dart');
+    testFile = convertPath('/home/test/000/1111/test.dart');
     addSource(pathA, '''
 import 'test.dart';
 ''');
-    addTestSource('');
+    await resolveTestUnit('');
+
     // perform refactoring
     _createRefactoring('/home/test/000/1111/22/new_name.dart');
     await _assertSuccessfulRefactoring();
+
     assertFileChangeResult(pathA, '''
 import '22/new_name.dart';
 ''');
     assertNoFileChange(testFile);
   }
 
-  test_file_importedLibrary_sideways() async {
-    String pathA = '/home/test/000/1111/a.dart';
-    testFile = '/home/test/000/1111/sub/folder/test.dart';
+  test_file_imported_with_relative_uri_sideways() async {
+    String pathA = convertPath('/home/test/000/1111/a.dart');
+    testFile = convertPath('/home/test/000/1111/sub/folder/test.dart');
     addSource(pathA, '''
 import 'sub/folder/test.dart';
 ''');
-    addTestSource('');
+    await resolveTestUnit('');
     // perform refactoring
     _createRefactoring('/home/test/000/new/folder/name/new_name.dart');
     await _assertSuccessfulRefactoring();
@@ -102,13 +216,13 @@
     assertNoFileChange(testFile);
   }
 
-  test_file_importedLibrary_up() async {
-    String pathA = '/home/test/000/1111/a.dart';
-    testFile = '/home/test/000/1111/22/test.dart';
+  test_file_imported_with_relative_uri_up() async {
+    String pathA = convertPath('/home/test/000/1111/a.dart');
+    testFile = convertPath('/home/test/000/1111/22/test.dart');
     addSource(pathA, '''
 import '22/test.dart';
 ''');
-    addTestSource('');
+    await resolveTestUnit('');
     // perform refactoring
     _createRefactoring('/home/test/000/1111/new_name.dart');
     await _assertSuccessfulRefactoring();
@@ -122,9 +236,9 @@
   test_file_referenced_by_multiple_libraries() async {
     // This test fails because the search index doesn't support multiple uris for
     // a library, so only one of them is updated.
-    String pathA = '/home/test/000/1111/a.dart';
-    String pathB = '/home/test/000/b.dart';
-    testFile = '/home/test/000/1111/22/test.dart';
+    String pathA = convertPath('/home/test/000/1111/a.dart');
+    String pathB = convertPath('/home/test/000/b.dart');
+    testFile = convertPath('/home/test/000/1111/22/test.dart');
     addSource(pathA, '''
 library lib;
 part '22/test.dart';
@@ -133,7 +247,7 @@
 library lib;
 part '1111/22/test.dart';
 ''');
-    addTestSource('''
+    await resolveTestUnit('''
 part of lib;
 ''');
     // perform refactoring
@@ -151,13 +265,13 @@
   }
 
   test_file_referenced_by_part() async {
-    String pathA = '/home/test/000/1111/a.dart';
-    testFile = '/home/test/000/1111/22/test.dart';
+    String pathA = convertPath('/home/test/000/1111/a.dart');
+    testFile = convertPath('/home/test/000/1111/22/test.dart');
     addSource(pathA, '''
 library lib;
 part '22/test.dart';
 ''');
-    addTestSource('''
+    await resolveTestUnit('''
 part of lib;
 ''');
     // perform refactoring
@@ -176,7 +290,7 @@
   }
 
   test_folder_outside_workspace_returns_failure() async {
-    _createRefactoring('/tmp-new', oldName: '/tmp');
+    _createRefactoring('/tmp-new', oldFile: '/tmp');
     // TODO(dantup): These paths should all use convertPath so they're as expected
     // on Windows.
     await _assertFailedRefactoring(RefactoringProblemSeverity.FATAL,
@@ -186,7 +300,7 @@
 
   test_nonexistent_file_returns_failure() async {
     _createRefactoring(convertPath('/home/test/test_missing_new.dart'),
-        oldName: convertPath('/home/test/test_missing.dart'));
+        oldFile: convertPath('/home/test/test_missing.dart'));
     await _assertFailedRefactoring(RefactoringProblemSeverity.FATAL,
         expectedMessage:
             '${convertPath('/home/test/test_missing.dart')} does not exist.');
@@ -200,7 +314,7 @@
   }
 
   test_projectFolder() async {
-    _createRefactoring('/home/test2', oldName: '/home/test');
+    _createRefactoring('/home/test2', oldFile: '/home/test');
     await _assertFailedRefactoring(RefactoringProblemSeverity.FATAL,
         expectedMessage: 'Renaming an analysis root is not supported '
             '(${convertPath('/home/test')})');
@@ -210,13 +324,13 @@
     // If the file is a part in a library, and the part-of directive uses a URI
     // rather than a library name, that will need updating too (if the relative
     // path to the parent changes).
-    String pathA = '/home/test/000/1111/a.dart';
-    testFile = '/home/test/000/1111/22/test.dart';
+    String pathA = convertPath('/home/test/000/1111/a.dart');
+    testFile = convertPath('/home/test/000/1111/22/test.dart');
     addSource(pathA, '''
 library lib;
 part '22/test.dart';
 ''');
-    addTestSource('''
+    await resolveTestUnit('''
 part of '../a.dart';
 ''');
     // perform refactoring
@@ -246,17 +360,13 @@
     refactoringChange = await refactoring.createChange();
   }
 
-  void _createRefactoring(String newName, {String oldName}) {
-    var workspace = new RefactoringWorkspace([driver], searchEngine);
+  void _createRefactoring(String newFile, {String oldFile}) {
+    var refactoringWorkspace = new RefactoringWorkspace([driver], searchEngine);
     // Allow passing an oldName for when we don't want to rename testSource,
-    // but otherwise fall back to that.
-    if (oldName != null) {
-      refactoring = new MoveFileRefactoring(
-          resourceProvider, workspace, null, convertPath(oldName));
-    } else {
-      refactoring = new MoveFileRefactoring(
-          resourceProvider, workspace, testSource, null);
-    }
-    refactoring.newFile = convertPath(newName);
+    // but otherwise fall back to testSource.fullname
+    oldFile = convertPath(oldFile != null ? oldFile : testSource.fullName);
+    refactoring = new MoveFileRefactoring(
+        resourceProvider, refactoringWorkspace, testAnalysisResult, oldFile);
+    refactoring.newFile = convertPath(newFile);
   }
 }
diff --git a/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart b/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
index 884c04a..0321fa9 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
@@ -230,8 +230,9 @@
   }
 
   test_newInstance_nullElement() async {
+    await indexTestUnit('');
     var workspace = new RefactoringWorkspace([driver], searchEngine);
-    var refactoring = new RenameRefactoring(workspace, null, null);
+    var refactoring = RenameRefactoring(workspace, testAnalysisResult, null);
     expect(refactoring, isNull);
   }
 
diff --git a/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart b/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart
index d94ac33..a6f62cf 100644
--- a/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart
@@ -61,6 +61,7 @@
     assertJsonText(_getSuggestion(set, 'A'), '''
 {
   "label": "A",
+  "declaringLibraryUri": "package:test/a.dart",
   "element": {
     "kind": "CLASS",
     "name": "A",
@@ -82,6 +83,7 @@
     assertJsonText(_getSuggestion(set, 'A.a'), '''
 {
   "label": "A.a",
+  "declaringLibraryUri": "package:test/a.dart",
   "element": {
     "kind": "CONSTRUCTOR",
     "name": "a",
@@ -118,6 +120,7 @@
     assertJsonText(_getSuggestion(set, 'MyEnum'), '''
 {
   "label": "MyEnum",
+  "declaringLibraryUri": "package:test/a.dart",
   "element": {
     "kind": "ENUM",
     "name": "MyEnum",
@@ -139,6 +142,7 @@
     assertJsonText(_getSuggestion(set, 'MyEnum.aaa'), '''
 {
   "label": "MyEnum.aaa",
+  "declaringLibraryUri": "package:test/a.dart",
   "element": {
     "kind": "ENUM_CONSTANT",
     "name": "aaa",
@@ -160,6 +164,7 @@
     assertJsonText(_getSuggestion(set, 'MyEnum.bbb'), '''
 {
   "label": "MyEnum.bbb",
+  "declaringLibraryUri": "package:test/a.dart",
   "element": {
     "kind": "ENUM_CONSTANT",
     "name": "bbb",
@@ -195,6 +200,7 @@
     assertJsonText(_getSuggestion(set, 'boolV'), '''
 {
   "label": "boolV",
+  "declaringLibraryUri": "package:test/a.dart",
   "element": {
     "kind": "TOP_LEVEL_VARIABLE",
     "name": "boolV",
@@ -217,6 +223,7 @@
     assertJsonText(_getSuggestion(set, 'intV'), '''
 {
   "label": "intV",
+  "declaringLibraryUri": "package:test/a.dart",
   "element": {
     "kind": "TOP_LEVEL_VARIABLE",
     "name": "intV",
@@ -239,6 +246,7 @@
     assertJsonText(_getSuggestion(set, 'doubleV'), '''
 {
   "label": "doubleV",
+  "declaringLibraryUri": "package:test/a.dart",
   "element": {
     "kind": "TOP_LEVEL_VARIABLE",
     "name": "doubleV",
@@ -261,6 +269,7 @@
     assertJsonText(_getSuggestion(set, 'stringV'), '''
 {
   "label": "stringV",
+  "declaringLibraryUri": "package:test/a.dart",
   "element": {
     "kind": "TOP_LEVEL_VARIABLE",
     "name": "stringV",
diff --git a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
index 97064f5..469ba02 100644
--- a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
+++ b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
@@ -21,6 +21,7 @@
   final Map<int, AvailableSuggestionSet> idToSetMap = {};
   final Map<String, AvailableSuggestionSet> uriToSetMap = {};
   final Map<String, CompletionResultsParams> idToSuggestions = {};
+  final Map<String, ExistingImports> fileToExistingImports = {};
 
   void assertJsonText(Object object, String expected) {
     expected = expected.trimRight();
@@ -56,6 +57,13 @@
     } else if (notification.event == COMPLETION_RESULTS) {
       var params = CompletionResultsParams.fromNotification(notification);
       idToSuggestions[params.id] = params;
+    } else if (notification.event == COMPLETION_NOTIFICATION_EXISTING_IMPORTS) {
+      var params = CompletionExistingImportsParams.fromNotification(
+        notification,
+      );
+      fileToExistingImports[params.file] = params.imports;
+    } else if (notification.event == SERVER_NOTIFICATION_ERROR) {
+      fail('${notification.toJson()}');
     }
   }
 
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
index 600a33a..47c59ec 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
@@ -10,12 +10,50 @@
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(ExistingImportsNotification);
     defineReflectiveTests(GetSuggestionAvailableTest);
   });
 }
 
 @reflectiveTest
-class GetSuggestionAvailableTest extends AvailableSuggestionsBase {
+class ExistingImportsNotification extends GetSuggestionsBase {
+  test_dart() async {
+    addTestFile(r'''
+import 'dart:math';
+''');
+    await _getSuggestions(testFile, 0);
+    _assertHasImport('dart:math', 'dart:math', 'Random');
+  }
+
+  test_invalidUri() async {
+    addTestFile(r'''
+import 'ht:';
+''');
+    await _getSuggestions(testFile, 0);
+    // We should not get 'server.error' notification.
+  }
+
+  void _assertHasImport(String exportingUri, String declaringUri, String name) {
+    var existingImports = fileToExistingImports[testFile];
+    expect(existingImports, isNotNull);
+
+    var existingImport = existingImports.imports.singleWhere((import) =>
+        existingImports.elements.strings[import.uri] == exportingUri);
+
+    var elements = existingImport.elements.map((index) {
+      var uriIndex = existingImports.elements.uris[index];
+      var nameIndex = existingImports.elements.names[index];
+      var uri = existingImports.elements.strings[uriIndex];
+      var name = existingImports.elements.strings[nameIndex];
+      return '$uri::$name';
+    }).toList();
+
+    expect(elements, contains('$declaringUri::$name'));
+  }
+}
+
+@reflectiveTest
+class GetSuggestionAvailableTest extends GetSuggestionsBase {
   test_dart() async {
     addTestFile('');
     var mathSet = await waitForSetWithUri('dart:math');
@@ -284,7 +322,9 @@
 ]
 ''');
   }
+}
 
+abstract class GetSuggestionsBase extends AvailableSuggestionsBase {
   Future<CompletionResultsParams> _getSuggestions(
     String path,
     int offset,
diff --git a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
index fe6ebd6..2ab09bd 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
@@ -205,6 +205,73 @@
     }
   }
 
+  test_children_closure_blockBody() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+import 'package:flutter/widgets.dart';
+
+class WidgetA extends StatelessWidget {
+  final Widget Function(bool) factory;
+
+  WidgetA(this.factory);
+}
+''');
+    FlutterOutline unitOutline = await _computeOutline('''
+import 'package:flutter/widgets.dart';
+import 'a.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new WidgetA((b) {
+      if (b) {
+        return const Text('aaa'),
+      } else {
+        return const Container(),
+      }
+    }); // WidgetA
+  }
+}
+''');
+    expect(_toText(unitOutline), r'''
+(D) MyWidget
+  (D) build
+    WidgetA
+      Text
+      Container
+''');
+  }
+
+  test_children_closure_expressionBody() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+import 'package:flutter/widgets.dart';
+
+class WidgetA extends StatelessWidget {
+  final Widget Function() factory;
+
+  WidgetA(this.factory);
+}
+''');
+    FlutterOutline unitOutline = await _computeOutline('''
+import 'package:flutter/widgets.dart';
+import 'a.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new WidgetA(
+      () => const Text('aaa'),
+    ); // WidgetA
+  }
+}
+''');
+    expect(_toText(unitOutline), r'''
+(D) MyWidget
+  (D) build
+    WidgetA
+      Text
+''');
+  }
+
   test_children_withCollectionElements() async {
     FlutterOutline unitOutline = await _computeOutline('''
 import 'package:flutter/widgets.dart';
diff --git a/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart b/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
deleted file mode 100644
index c3b1915..0000000
--- a/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
+++ /dev/null
@@ -1,1065 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/conditional_discard.dart';
-import 'package:analysis_server/src/nullability/constraint_gatherer.dart';
-import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
-import 'package:analysis_server/src/nullability/decorated_type.dart';
-import 'package:analysis_server/src/nullability/expression_checks.dart';
-import 'package:analysis_server/src/nullability/nullability_node.dart';
-import 'package:analysis_server/src/nullability/transitional_api.dart';
-import 'package:analysis_server/src/nullability/unit_propagation.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/test_utilities/find_node.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../abstract_single_unit.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(ConstraintGathererTest);
-    defineReflectiveTests(ConstraintVariableGathererTest);
-  });
-}
-
-@reflectiveTest
-class ConstraintGathererTest extends ConstraintsTestBase {
-  @override
-  final _Constraints constraints = _Constraints();
-
-  /// Checks that a constraint was recorded with a left hand side of
-  /// [conditions] and a right hand side of [consequence].
-  void assertConstraint(
-      Iterable<ConstraintVariable> conditions, ConstraintVariable consequence) {
-    expect(constraints._clauses,
-        contains(_Clause(conditions.toSet(), consequence)));
-  }
-
-  /// Checks that no constraint was recorded with a right hand side of
-  /// [consequence].
-  void assertNoConstraints(ConstraintVariable consequence) {
-    expect(
-        constraints._clauses,
-        isNot(contains(
-            predicate((_Clause clause) => clause.consequence == consequence))));
-  }
-
-  void assertNonNullIntent(NullabilityNode node, bool expected) {
-    if (expected) {
-      assertConstraint([], node.nonNullIntent);
-    } else {
-      assertNoConstraints(node.nonNullIntent);
-    }
-  }
-
-  /// Gets the [ExpressionChecks] associated with the expression whose text
-  /// representation is [text], or `null` if the expression has no
-  /// [ExpressionChecks] associated with it.
-  ExpressionChecks checkExpression(String text) {
-    return _variables.checkExpression(findNode.expression(text));
-  }
-
-  /// Gets the [DecoratedType] associated with the expression whose text
-  /// representation is [text], or `null` if the expression has no
-  /// [DecoratedType] associated with it.
-  DecoratedType decoratedExpressionType(String text) {
-    return _variables.decoratedExpressionType(findNode.expression(text));
-  }
-
-  test_always() async {
-    await analyze('');
-
-    // No clause is needed for `always`; it is assigned the value `true` before
-    // solving begins.
-    assertNoConstraints(ConstraintVariable.always);
-    assert(ConstraintVariable.always.value, isTrue);
-  }
-
-  test_assert_demonstrates_non_null_intent() async {
-    await analyze('''
-void f(int i) {
-  assert(i != null);
-}
-''');
-
-    assertNonNullIntent(decoratedTypeAnnotation('int i').node, true);
-  }
-
-  test_binaryExpression_add_left_check() async {
-    await analyze('''
-int f(int i, int j) => i + j;
-''');
-
-    assertConstraint([decoratedTypeAnnotation('int i').node.nullable],
-        checkExpression('i +').nullCheck);
-  }
-
-  test_binaryExpression_add_left_check_custom() async {
-    await analyze('''
-class Int {
-  Int operator+(Int other) => this;
-}
-Int f(Int i, Int j) => i + j;
-''');
-
-    assertConstraint([decoratedTypeAnnotation('Int i').node.nullable],
-        checkExpression('i +').nullCheck);
-  }
-
-  test_binaryExpression_add_result_custom() async {
-    await analyze('''
-class Int {
-  Int operator+(Int other) => this;
-}
-Int f(Int i, Int j) => (i + j);
-''');
-
-    assertConstraint(
-        [decoratedTypeAnnotation('Int operator+').node.nullable],
-        _either(decoratedTypeAnnotation('Int f').node.nullable,
-            checkExpression('(i + j)').nullCheck));
-  }
-
-  test_binaryExpression_add_result_not_null() async {
-    await analyze('''
-int f(int i, int j) => i + j;
-''');
-
-    assertNoConstraints(decoratedTypeAnnotation('int f').node.nullable);
-  }
-
-  test_binaryExpression_add_right_check() async {
-    await analyze('''
-int f(int i, int j) => i + j;
-''');
-
-    assertConstraint([decoratedTypeAnnotation('int j').node.nullable],
-        checkExpression('j;').nullCheck);
-  }
-
-  test_binaryExpression_add_right_check_custom() async {
-    await analyze('''
-class Int {
-  Int operator+(Int other) => this;
-}
-Int f(Int i, Int j) => i + j/*check*/;
-''');
-
-    assertConstraint(
-        [decoratedTypeAnnotation('Int j').node.nullable],
-        _either(decoratedTypeAnnotation('Int other').node.nullable,
-            checkExpression('j/*check*/').nullCheck));
-  }
-
-  test_binaryExpression_equal() async {
-    await analyze('''
-bool f(int i, int j) => i == j;
-''');
-
-    assertNoConstraints(decoratedTypeAnnotation('bool f').node.nullable);
-  }
-
-  test_boolLiteral() async {
-    await analyze('''
-bool f() {
-  return true;
-}
-''');
-    assertNoConstraints(decoratedTypeAnnotation('bool').node.nullable);
-  }
-
-  test_conditionalExpression_condition_check() async {
-    await analyze('''
-int f(bool b, int i, int j) {
-  return (b ? i : j);
-}
-''');
-
-    var nullable_b = decoratedTypeAnnotation('bool b').node.nullable;
-    var check_b = checkExpression('b ?').nullCheck;
-    assertConstraint([nullable_b], check_b);
-  }
-
-  test_conditionalExpression_general() async {
-    await analyze('''
-int f(bool b, int i, int j) {
-  return (b ? i : j);
-}
-''');
-
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    var nullable_j = decoratedTypeAnnotation('int j').node.nullable;
-    var nullable_i_or_nullable_j = _either(nullable_i, nullable_j);
-    var nullable_conditional = decoratedExpressionType('(b ?').node.nullable;
-    var nullable_return = decoratedTypeAnnotation('int f').node.nullable;
-    assertConstraint([nullable_i], nullable_conditional);
-    assertConstraint([nullable_j], nullable_conditional);
-    assertConstraint([nullable_conditional], nullable_i_or_nullable_j);
-    assertConstraint([nullable_conditional],
-        _either(nullable_return, checkExpression('(b ? i : j)').nullCheck));
-  }
-
-  test_conditionalExpression_left_non_null() async {
-    await analyze('''
-int f(bool b, int i) {
-  return (b ? (throw i) : i);
-}
-''');
-
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    var nullable_conditional = decoratedExpressionType('(b ?').node.nullable;
-    expect(nullable_conditional, same(nullable_i));
-  }
-
-  test_conditionalExpression_left_null() async {
-    await analyze('''
-int f(bool b, int i) {
-  return (b ? null : i);
-}
-''');
-
-    var nullable_conditional = decoratedExpressionType('(b ?').node.nullable;
-    expect(nullable_conditional, same(ConstraintVariable.always));
-  }
-
-  test_conditionalExpression_right_non_null() async {
-    await analyze('''
-int f(bool b, int i) {
-  return (b ? i : (throw i));
-}
-''');
-
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    var nullable_conditional = decoratedExpressionType('(b ?').node.nullable;
-    expect(nullable_conditional, same(nullable_i));
-  }
-
-  test_conditionalExpression_right_null() async {
-    await analyze('''
-int f(bool b, int i) {
-  return (b ? i : null);
-}
-''');
-
-    var nullable_conditional = decoratedExpressionType('(b ?').node.nullable;
-    expect(nullable_conditional, same(ConstraintVariable.always));
-  }
-
-  test_functionDeclaration_expression_body() async {
-    await analyze('''
-int/*1*/ f(int/*2*/ i) => i/*3*/;
-''');
-
-    assertConstraint(
-        [decoratedTypeAnnotation('int/*2*/').node.nullable],
-        _either(decoratedTypeAnnotation('int/*1*/').node.nullable,
-            checkExpression('i/*3*/').nullCheck));
-  }
-
-  test_functionDeclaration_parameter_named_default_notNull() async {
-    await analyze('''
-void f({int i = 1}) {}
-''');
-
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_functionDeclaration_parameter_named_default_null() async {
-    await analyze('''
-void f({int i = null}) {}
-''');
-
-    assertConstraint([ConstraintVariable.always],
-        decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_functionDeclaration_parameter_named_no_default_assume_nullable() async {
-    await analyze('''
-void f({int i}) {}
-''',
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
-
-    assertConstraint([ConstraintVariable.always],
-        decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_functionDeclaration_parameter_named_no_default_assume_required() async {
-    await analyze('''
-void f({int i}) {}
-''',
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_functionDeclaration_parameter_named_no_default_required_assume_nullable() async {
-    addMetaPackage();
-    await analyze('''
-import 'package:meta/meta.dart';
-void f({@required int i}) {}
-''',
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
-
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_functionDeclaration_parameter_named_no_default_required_assume_required() async {
-    addMetaPackage();
-    await analyze('''
-import 'package:meta/meta.dart';
-void f({@required int i}) {}
-''',
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_functionDeclaration_parameter_positionalOptional_default_notNull() async {
-    await analyze('''
-void f([int i = 1]) {}
-''');
-
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_functionDeclaration_parameter_positionalOptional_default_null() async {
-    await analyze('''
-void f([int i = null]) {}
-''');
-
-    assertConstraint([ConstraintVariable.always],
-        decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_functionDeclaration_parameter_positionalOptional_no_default() async {
-    await analyze('''
-void f([int i]) {}
-''');
-
-    assertConstraint([ConstraintVariable.always],
-        decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_functionDeclaration_parameter_positionalOptional_no_default_assume_required() async {
-    // Note: the `assumeRequired` behavior shouldn't affect the behavior here
-    // because it only affects named parameters.
-    await analyze('''
-void f([int i]) {}
-''',
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-
-    assertConstraint([ConstraintVariable.always],
-        decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_functionDeclaration_resets_unconditional_control_flow() async {
-    await analyze('''
-void f(bool b, int i, int j) {
-  assert(i != null);
-  if (b) return;
-  assert(j != null);
-}
-void g(int k) {
-  assert(k != null);
-}
-''');
-    assertNonNullIntent(decoratedTypeAnnotation('int i').node, true);
-    assertNonNullIntent(decoratedTypeAnnotation('int j').node, false);
-    assertNonNullIntent(decoratedTypeAnnotation('int k').node, true);
-  }
-
-  test_functionInvocation_parameter_fromLocalParameter() async {
-    await analyze('''
-void f(int/*1*/ i) {}
-void test(int/*2*/ i) {
-  f(i/*3*/);
-}
-''');
-
-    var int_1 = decoratedTypeAnnotation('int/*1*/');
-    var int_2 = decoratedTypeAnnotation('int/*2*/');
-    var i_3 = checkExpression('i/*3*/');
-    assertConstraint(
-        [int_2.node.nullable], _either(int_1.node.nullable, i_3.nullCheck));
-    assertConstraint(
-        [int_2.node.nullable, int_1.node.nonNullIntent], i_3.nullCheck);
-    assertConstraint([int_1.node.nonNullIntent], int_2.node.nonNullIntent);
-  }
-
-  test_functionInvocation_parameter_named() async {
-    await analyze('''
-void f({int i: 0}) {}
-void g(int j) {
-  f(i: j/*check*/);
-}
-''');
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    var nullable_j = decoratedTypeAnnotation('int j').node.nullable;
-    assertConstraint([nullable_j],
-        _either(nullable_i, checkExpression('j/*check*/').nullCheck));
-  }
-
-  test_functionInvocation_parameter_named_missing() async {
-    await analyze('''
-void f({int i}) {}
-void g() {
-  f();
-}
-''');
-    var optional_i = possiblyOptionalParameter('int i');
-    assertConstraint([], optional_i.nullable);
-  }
-
-  test_functionInvocation_parameter_named_missing_required() async {
-    addMetaPackage();
-    verifyNoTestUnitErrors = false;
-    await analyze('''
-import 'package:meta/meta.dart';
-void f({@required int i}) {}
-void g() {
-  f();
-}
-''');
-    // The call at `f()` is presumed to be in error; no constraint is recorded.
-    var optional_i = possiblyOptionalParameter('int i');
-    expect(optional_i, isNull);
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    assertNoConstraints(nullable_i);
-  }
-
-  test_functionInvocation_parameter_null() async {
-    await analyze('''
-void f(int i) {}
-void test() {
-  f(null);
-}
-''');
-
-    assertConstraint(
-        [ConstraintVariable.always],
-        _either(decoratedTypeAnnotation('int').node.nullable,
-            checkExpression('null').nullCheck));
-  }
-
-  test_functionInvocation_return() async {
-    await analyze('''
-int/*1*/ f() => 0;
-int/*2*/ g() {
-  return (f());
-}
-''');
-
-    assertConstraint(
-        [decoratedTypeAnnotation('int/*1*/').node.nullable],
-        _either(decoratedTypeAnnotation('int/*2*/').node.nullable,
-            checkExpression('(f())').nullCheck));
-  }
-
-  test_if_condition() async {
-    await analyze('''
-void f(bool b) {
-  if (b) {}
-}
-''');
-
-    assertConstraint([(decoratedTypeAnnotation('bool b').node.nullable)],
-        checkExpression('b) {}').nullCheck);
-  }
-
-  test_if_conditional_control_flow_after() async {
-    // Asserts after ifs don't demonstrate non-null intent.
-    // TODO(paulberry): if both branches complete normally, they should.
-    await analyze('''
-void f(bool b, int i) {
-  if (b) return;
-  assert(i != null);
-}
-''');
-
-    assertNonNullIntent(decoratedTypeAnnotation('int i').node, false);
-  }
-
-  test_if_conditional_control_flow_within() async {
-    // Asserts inside ifs don't demonstrate non-null intent.
-    await analyze('''
-void f(bool b, int i) {
-  if (b) {
-    assert(i != null);
-  } else {
-    assert(i != null);
-  }
-}
-''');
-
-    assertNonNullIntent(decoratedTypeAnnotation('int i').node, false);
-  }
-
-  test_if_guard_equals_null() async {
-    await analyze('''
-int f(int i, int j, int k) {
-  if (i == null) {
-    return j/*check*/;
-  } else {
-    return k/*check*/;
-  }
-}
-''');
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    var nullable_j = decoratedTypeAnnotation('int j').node.nullable;
-    var nullable_k = decoratedTypeAnnotation('int k').node.nullable;
-    var nullable_return = decoratedTypeAnnotation('int f').node.nullable;
-    assertConstraint([nullable_i, nullable_j],
-        _either(nullable_return, checkExpression('j/*check*/').nullCheck));
-    assertConstraint([nullable_k],
-        _either(nullable_return, checkExpression('k/*check*/').nullCheck));
-    var discard = statementDiscard('if (i == null)');
-    expect(discard.trueGuard.nullable, same(nullable_i));
-    expect(discard.falseGuard, null);
-    expect(discard.pureCondition, true);
-  }
-
-  test_if_simple() async {
-    await analyze('''
-int f(bool b, int i, int j) {
-  if (b) {
-    return i/*check*/;
-  } else {
-    return j/*check*/;
-  }
-}
-''');
-
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    var nullable_j = decoratedTypeAnnotation('int j').node.nullable;
-    var nullable_return = decoratedTypeAnnotation('int f').node.nullable;
-    assertConstraint([nullable_i],
-        _either(nullable_return, checkExpression('i/*check*/').nullCheck));
-    assertConstraint([nullable_j],
-        _either(nullable_return, checkExpression('j/*check*/').nullCheck));
-  }
-
-  test_if_without_else() async {
-    await analyze('''
-int f(bool b, int i) {
-  if (b) {
-    return i/*check*/;
-  }
-  return 0;
-}
-''');
-
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    var nullable_return = decoratedTypeAnnotation('int f').node.nullable;
-    assertConstraint([nullable_i],
-        _either(nullable_return, checkExpression('i/*check*/').nullCheck));
-  }
-
-  test_intLiteral() async {
-    await analyze('''
-int f() {
-  return 0;
-}
-''');
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_methodDeclaration_resets_unconditional_control_flow() async {
-    await analyze('''
-class C {
-  void f(bool b, int i, int j) {
-    assert(i != null);
-    if (b) return;
-    assert(j != null);
-  }
-  void g(int k) {
-    assert(k != null);
-  }
-}
-''');
-    assertNonNullIntent(decoratedTypeAnnotation('int i').node, true);
-    assertNonNullIntent(decoratedTypeAnnotation('int j').node, false);
-    assertNonNullIntent(decoratedTypeAnnotation('int k').node, true);
-  }
-
-  test_methodInvocation_parameter_contravariant() async {
-    await analyze('''
-class C<T> {
-  void f(T t) {}
-}
-void g(C<int> c, int i) {
-  c.f(i/*check*/);
-}
-''');
-
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    var nullable_c_t =
-        decoratedTypeAnnotation('C<int>').typeArguments[0].node.nullable;
-    var nullable_t = decoratedTypeAnnotation('T t').node.nullable;
-    var nullable_c_t_or_nullable_t = _either(nullable_c_t, nullable_t);
-    assertConstraint(
-        [nullable_i],
-        _either(nullable_c_t_or_nullable_t,
-            checkExpression('i/*check*/').nullCheck));
-  }
-
-  test_methodInvocation_parameter_generic() async {
-    await analyze('''
-class C<T> {}
-void f(C<int/*1*/>/*2*/ c) {}
-void g(C<int/*3*/>/*4*/ c) {
-  f(c/*check*/);
-}
-''');
-
-    assertConstraint([decoratedTypeAnnotation('int/*3*/').node.nullable],
-        decoratedTypeAnnotation('int/*1*/').node.nullable);
-    assertConstraint(
-        [decoratedTypeAnnotation('C<int/*3*/>/*4*/').node.nullable],
-        _either(decoratedTypeAnnotation('C<int/*1*/>/*2*/').node.nullable,
-            checkExpression('c/*check*/').nullCheck));
-  }
-
-  test_methodInvocation_parameter_named() async {
-    await analyze('''
-class C {
-  void f({int i: 0}) {}
-}
-void g(C c, int j) {
-  c.f(i: j/*check*/);
-}
-''');
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    var nullable_j = decoratedTypeAnnotation('int j').node.nullable;
-    assertConstraint([nullable_j],
-        _either(nullable_i, checkExpression('j/*check*/').nullCheck));
-  }
-
-  test_methodInvocation_target_check() async {
-    await analyze('''
-class C {
-  void m() {}
-}
-void test(C c) {
-  c.m();
-}
-''');
-
-    assertConstraint([decoratedTypeAnnotation('C c').node.nullable],
-        checkExpression('c.m').nullCheck);
-  }
-
-  test_methodInvocation_target_demonstrates_non_null_intent() async {
-    await analyze('''
-class C {
-  void m() {}
-}
-void test(C c) {
-  c.m();
-}
-''');
-
-    assertNonNullIntent(decoratedTypeAnnotation('C c').node, true);
-  }
-
-  test_parenthesizedExpression() async {
-    await analyze('''
-int f() {
-  return (null);
-}
-''');
-
-    assertConstraint(
-        [ConstraintVariable.always],
-        _either(decoratedTypeAnnotation('int').node.nullable,
-            checkExpression('(null)').nullCheck));
-  }
-
-  test_return_implicit_null() async {
-    verifyNoTestUnitErrors = false;
-    await analyze('''
-int f() {
-  return;
-}
-''');
-
-    assertConstraint([ConstraintVariable.always],
-        decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_return_null() async {
-    await analyze('''
-int f() {
-  return null;
-}
-''');
-
-    assertConstraint(
-        [ConstraintVariable.always],
-        _either(decoratedTypeAnnotation('int').node.nullable,
-            checkExpression('null').nullCheck));
-  }
-
-  test_stringLiteral() async {
-    // TODO(paulberry): also test string interpolations
-    await analyze('''
-String f() {
-  return 'x';
-}
-''');
-    assertNoConstraints(decoratedTypeAnnotation('String').node.nullable);
-  }
-
-  test_thisExpression() async {
-    await analyze('''
-class C {
-  C f() => this;
-}
-''');
-
-    assertNoConstraints(decoratedTypeAnnotation('C f').node.nullable);
-  }
-
-  test_throwExpression() async {
-    await analyze('''
-int f() {
-  return throw null;
-}
-''');
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
-  }
-
-  test_typeName() async {
-    await analyze('''
-Type f() {
-  return int;
-}
-''');
-    assertNoConstraints(decoratedTypeAnnotation('Type').node.nullable);
-  }
-
-  /// Creates a variable representing the disjunction of [a] and [b] solely for
-  /// the purpose of inspecting constraint equations in unit tests.  No
-  /// additional constraints will be recorded in [_constraints] as a consequence
-  /// of creating this variable.
-  ConstraintVariable _either(ConstraintVariable a, ConstraintVariable b) =>
-      ConstraintVariable.or(_MockConstraints(), a, b);
-}
-
-abstract class ConstraintsTestBase extends MigrationVisitorTestBase {
-  Constraints get constraints;
-
-  /// Analyzes the given source code, producing constraint variables and
-  /// constraints for it.
-  @override
-  Future<CompilationUnit> analyze(String code,
-      {NullabilityMigrationAssumptions assumptions:
-          const NullabilityMigrationAssumptions()}) async {
-    var unit = await super.analyze(code);
-    unit.accept(ConstraintGatherer(
-        typeProvider, _variables, constraints, testSource, false, assumptions));
-    return unit;
-  }
-}
-
-@reflectiveTest
-class ConstraintVariableGathererTest extends MigrationVisitorTestBase {
-  /// Gets the [DecoratedType] associated with the function declaration whose
-  /// name matches [search].
-  DecoratedType decoratedFunctionType(String search) =>
-      _variables.decoratedElementType(
-          findNode.functionDeclaration(search).declaredElement);
-
-  test_interfaceType_nullable() async {
-    await analyze('''
-void f(int? x) {}
-''');
-    var decoratedType = decoratedTypeAnnotation('int?');
-    expect(decoratedFunctionType('f').positionalParameters[0],
-        same(decoratedType));
-    expect(decoratedType.node.nullable, same(ConstraintVariable.always));
-  }
-
-  test_interfaceType_typeParameter() async {
-    await analyze('''
-void f(List<int> x) {}
-''');
-    var decoratedListType = decoratedTypeAnnotation('List<int>');
-    expect(decoratedFunctionType('f').positionalParameters[0],
-        same(decoratedListType));
-    expect(decoratedListType.node.nullable, isNotNull);
-    var decoratedIntType = decoratedTypeAnnotation('int');
-    expect(decoratedListType.typeArguments[0], same(decoratedIntType));
-    expect(decoratedIntType.node.nullable, isNotNull);
-  }
-
-  test_topLevelFunction_parameterType_implicit_dynamic() async {
-    await analyze('''
-void f(x) {}
-''');
-    var decoratedType =
-        _variables.decoratedElementType(findNode.simple('x').staticElement);
-    expect(decoratedFunctionType('f').positionalParameters[0],
-        same(decoratedType));
-    expect(decoratedType.type.isDynamic, isTrue);
-    expect(decoratedType.node.nullable, same(ConstraintVariable.always));
-  }
-
-  test_topLevelFunction_parameterType_named_no_default() async {
-    await analyze('''
-void f({String s}) {}
-''');
-    var decoratedType = decoratedTypeAnnotation('String');
-    var functionType = decoratedFunctionType('f');
-    expect(functionType.namedParameters['s'], same(decoratedType));
-    expect(decoratedType.node.nullable, isNotNull);
-    expect(decoratedType.node.nullable, isNot(same(ConstraintVariable.always)));
-    expect(functionType.namedParameters['s'].node.isPossiblyOptional, true);
-  }
-
-  test_topLevelFunction_parameterType_named_no_default_required() async {
-    addMetaPackage();
-    await analyze('''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-''');
-    var decoratedType = decoratedTypeAnnotation('String');
-    var functionType = decoratedFunctionType('f');
-    expect(functionType.namedParameters['s'], same(decoratedType));
-    expect(decoratedType.node.nullable, isNotNull);
-    expect(decoratedType.node.nullable, isNot(same(ConstraintVariable.always)));
-    expect(functionType.namedParameters['s'].node.isPossiblyOptional, false);
-  }
-
-  test_topLevelFunction_parameterType_named_with_default() async {
-    await analyze('''
-void f({String s: 'x'}) {}
-''');
-    var decoratedType = decoratedTypeAnnotation('String');
-    var functionType = decoratedFunctionType('f');
-    expect(functionType.namedParameters['s'], same(decoratedType));
-    expect(decoratedType.node.nullable, isNotNull);
-    expect(functionType.namedParameters['s'].node.isPossiblyOptional, false);
-  }
-
-  test_topLevelFunction_parameterType_positionalOptional() async {
-    await analyze('''
-void f([int i]) {}
-''');
-    var decoratedType = decoratedTypeAnnotation('int');
-    expect(decoratedFunctionType('f').positionalParameters[0],
-        same(decoratedType));
-    expect(decoratedType.node.nullable, isNotNull);
-  }
-
-  test_topLevelFunction_parameterType_simple() async {
-    await analyze('''
-void f(int i) {}
-''');
-    var decoratedType = decoratedTypeAnnotation('int');
-    expect(decoratedFunctionType('f').positionalParameters[0],
-        same(decoratedType));
-    expect(decoratedType.node.nullable, isNotNull);
-    expect(decoratedType.node.nonNullIntent, isNotNull);
-  }
-
-  test_topLevelFunction_returnType_implicit_dynamic() async {
-    await analyze('''
-f() {}
-''');
-    var decoratedType = decoratedFunctionType('f').returnType;
-    expect(decoratedType.type.isDynamic, isTrue);
-    expect(decoratedType.node.nullable, same(ConstraintVariable.always));
-  }
-
-  test_topLevelFunction_returnType_simple() async {
-    await analyze('''
-int f() => 0;
-''');
-    var decoratedType = decoratedTypeAnnotation('int');
-    expect(decoratedFunctionType('f').returnType, same(decoratedType));
-    expect(decoratedType.node.nullable, isNotNull);
-  }
-}
-
-class MigrationVisitorTestBase extends AbstractSingleUnitTest {
-  final _variables = _Variables();
-
-  FindNode findNode;
-
-  TypeProvider get typeProvider => testAnalysisResult.typeProvider;
-
-  Future<CompilationUnit> analyze(String code,
-      {NullabilityMigrationAssumptions assumptions:
-          const NullabilityMigrationAssumptions()}) async {
-    await resolveTestUnit(code);
-    testUnit.accept(
-        ConstraintVariableGatherer(_variables, testSource, false, assumptions));
-    findNode = FindNode(code, testUnit);
-    return testUnit;
-  }
-
-  /// Gets the [DecoratedType] associated with the type annotation whose text
-  /// is [text].
-  DecoratedType decoratedTypeAnnotation(String text) {
-    return _variables.decoratedTypeAnnotation(findNode.typeAnnotation(text));
-  }
-
-  NullabilityNode possiblyOptionalParameter(String text) {
-    return _variables
-        .possiblyOptionalParameter(findNode.defaultParameter(text));
-  }
-
-  @override
-  void setUp() {
-    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
-    super.setUp();
-  }
-
-  /// Gets the [ConditionalDiscard] information associated with the statement
-  /// whose text is [text].
-  ConditionalDiscard statementDiscard(String text) {
-    return _variables.conditionalDiscard(findNode.statement(text));
-  }
-}
-
-/// Mock representation of a constraint equation that is not connected to a
-/// constraint solver.  We use this to confirm that analysis produces the
-/// correct constraint equations.
-///
-/// [hashCode] and equality are implemented using [toString] for simplicity.
-class _Clause {
-  final Set<ConstraintVariable> conditions;
-  final ConstraintVariable consequence;
-
-  _Clause(this.conditions, this.consequence);
-
-  @override
-  int get hashCode => toString().hashCode;
-
-  @override
-  bool operator ==(Object other) =>
-      other is _Clause && toString() == other.toString();
-
-  @override
-  String toString() {
-    String lhs;
-    if (conditions.isNotEmpty) {
-      var sortedConditionStrings = conditions.map((v) => v.toString()).toList()
-        ..sort();
-      lhs = sortedConditionStrings.join(' & ') + ' => ';
-    } else {
-      lhs = '';
-    }
-    String rhs = consequence.toString();
-    return lhs + rhs;
-  }
-}
-
-/// Mock representation of a constraint solver that does not actually do any
-/// solving.  We use this to confirm that analysis produced the correct
-/// constraint equations.
-class _Constraints extends Constraints {
-  final _clauses = <_Clause>[];
-
-  @override
-  void record(
-      Iterable<ConstraintVariable> conditions, ConstraintVariable consequence) {
-    _clauses.add(_Clause(conditions.toSet(), consequence));
-  }
-}
-
-/// Mock implementation of [Constraints] that doesn't record any constraints.
-class _MockConstraints implements Constraints {
-  @override
-  void record(Iterable<ConstraintVariable> conditions,
-      ConstraintVariable consequence) {}
-}
-
-/// Mock representation of constraint variables.
-class _Variables extends Variables {
-  final _conditionalDiscard = <AstNode, ConditionalDiscard>{};
-
-  final _decoratedExpressionTypes = <Expression, DecoratedType>{};
-
-  final _decoratedTypeAnnotations = <TypeAnnotation, DecoratedType>{};
-
-  final _expressionChecks = <Expression, ExpressionChecks>{};
-
-  final _possiblyOptional = <DefaultFormalParameter, NullabilityNode>{};
-
-  /// Gets the [ExpressionChecks] associated with the given [expression].
-  ExpressionChecks checkExpression(Expression expression) =>
-      _expressionChecks[_normalizeExpression(expression)];
-
-  /// Gets the [conditionalDiscard] associated with the given [expression].
-  ConditionalDiscard conditionalDiscard(AstNode node) =>
-      _conditionalDiscard[node];
-
-  /// Gets the [DecoratedType] associated with the given [expression].
-  DecoratedType decoratedExpressionType(Expression expression) =>
-      _decoratedExpressionTypes[_normalizeExpression(expression)];
-
-  /// Gets the [DecoratedType] associated with the given [typeAnnotation].
-  DecoratedType decoratedTypeAnnotation(TypeAnnotation typeAnnotation) =>
-      _decoratedTypeAnnotations[typeAnnotation];
-
-  /// Gets the [NullabilityNode] associated with the possibility that
-  /// [parameter] may be optional.
-  NullabilityNode possiblyOptionalParameter(DefaultFormalParameter parameter) =>
-      _possiblyOptional[parameter];
-
-  @override
-  void recordConditionalDiscard(
-      Source source, AstNode node, ConditionalDiscard conditionalDiscard) {
-    _conditionalDiscard[node] = conditionalDiscard;
-    super.recordConditionalDiscard(source, node, conditionalDiscard);
-  }
-
-  void recordDecoratedExpressionType(Expression node, DecoratedType type) {
-    super.recordDecoratedExpressionType(node, type);
-    _decoratedExpressionTypes[_normalizeExpression(node)] = type;
-  }
-
-  void recordDecoratedTypeAnnotation(
-      Source source, TypeAnnotation node, DecoratedType type) {
-    super.recordDecoratedTypeAnnotation(source, node, type);
-    _decoratedTypeAnnotations[node] = type;
-  }
-
-  @override
-  void recordExpressionChecks(
-      Source source, Expression expression, ExpressionChecks checks) {
-    super.recordExpressionChecks(source, expression, checks);
-    _expressionChecks[_normalizeExpression(expression)] = checks;
-  }
-
-  @override
-  void recordPossiblyOptional(
-      Source source, DefaultFormalParameter parameter, NullabilityNode node) {
-    _possiblyOptional[parameter] = node;
-    super.recordPossiblyOptional(source, parameter, node);
-  }
-
-  /// Unwraps any parentheses surrounding [expression].
-  Expression _normalizeExpression(Expression expression) {
-    while (expression is ParenthesizedExpression) {
-      expression = (expression as ParenthesizedExpression).expression;
-    }
-    return expression;
-  }
-}
diff --git a/pkg/analysis_server/test/src/nullability/provisional_api_test.dart b/pkg/analysis_server/test/src/nullability/provisional_api_test.dart
deleted file mode 100644
index d96f84d..0000000
--- a/pkg/analysis_server/test/src/nullability/provisional_api_test.dart
+++ /dev/null
@@ -1,939 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/provisional_api.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../abstract_context.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(_ProvisionalApiTest);
-    defineReflectiveTests(_ProvisionalApiTestPermissive);
-    defineReflectiveTests(_ProvisionalApiTestWithReset);
-  });
-}
-
-/// Tests of the provisional API.
-@reflectiveTest
-class _ProvisionalApiTest extends _ProvisionalApiTestBase
-    with _ProvisionalApiTestCases {
-  @override
-  bool get _usePermissiveMode => false;
-}
-
-/// Base class for provisional API tests.
-abstract class _ProvisionalApiTestBase extends AbstractContextTest {
-  bool get _usePermissiveMode;
-
-  /// Hook invoked after calling `prepareInput` on each input.
-  void _afterPrepare() {}
-
-  /// Verifies that migration of the files in [input] produces the output in
-  /// [expectedOutput].
-  Future<void> _checkMultipleFileChanges(
-      Map<String, String> input, Map<String, String> expectedOutput,
-      {NullabilityMigrationAssumptions assumptions:
-          const NullabilityMigrationAssumptions()}) async {
-    for (var path in input.keys) {
-      newFile(path, content: input[path]);
-    }
-    var listener = new _TestMigrationListener();
-    var migration = NullabilityMigration(listener,
-        permissive: _usePermissiveMode, assumptions: assumptions);
-    for (var path in input.keys) {
-      migration.prepareInput(await session.getResolvedUnit(path));
-    }
-    _afterPrepare();
-    for (var path in input.keys) {
-      migration.processInput(await session.getResolvedUnit(path));
-    }
-    migration.finish();
-    var sourceEdits = <String, List<SourceEdit>>{};
-    for (var entry in listener._edits.entries) {
-      var path = entry.key.fullName;
-      expect(expectedOutput.keys, contains(path));
-      sourceEdits[path] = entry.value;
-    }
-    for (var path in expectedOutput.keys) {
-      var sourceEditsForPath = sourceEdits[path] ?? [];
-      sourceEditsForPath.sort((a, b) => b.offset.compareTo(a.offset));
-      expect(SourceEdit.applySequence(input[path], sourceEditsForPath),
-          expectedOutput[path]);
-    }
-  }
-
-  /// Verifies that migraiton of the single file with the given [content]
-  /// produces the [expected] output.
-  Future<void> _checkSingleFileChanges(String content, String expected,
-      {NullabilityMigrationAssumptions assumptions:
-          const NullabilityMigrationAssumptions()}) async {
-    var sourcePath = convertPath('/home/test/lib/test.dart');
-    await _checkMultipleFileChanges(
-        {sourcePath: content}, {sourcePath: expected},
-        assumptions: assumptions);
-  }
-}
-
-/// Mixin containing test cases for the provisional API.
-mixin _ProvisionalApiTestCases on _ProvisionalApiTestBase {
-  test_conditional_assert_statement_does_not_imply_non_null_intent() async {
-    var content = '''
-void f(bool b, int i) {
-  if (b) return;
-  assert(i != null);
-}
-void g(bool b, int i) {
-  if (b) f(b, i);
-}
-main() {
-  g(true, null);
-}
-''';
-    var expected = '''
-void f(bool b, int? i) {
-  if (b) return;
-  assert(i != null);
-}
-void g(bool b, int? i) {
-  if (b) f(b, i);
-}
-main() {
-  g(true, null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_conditional_dereference_does_not_imply_non_null_intent() async {
-    var content = '''
-void f(bool b, int i) {
-  if (b) i.abs();
-}
-void g(bool b, int i) {
-  if (b) f(b, i);
-}
-main() {
-  g(false, null);
-}
-''';
-    var expected = '''
-void f(bool b, int? i) {
-  if (b) i!.abs();
-}
-void g(bool b, int? i) {
-  if (b) f(b, i);
-}
-main() {
-  g(false, null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_conditional_non_null_usage_does_not_imply_non_null_intent() async {
-    var content = '''
-void f(bool b, int i, int j) {
-  if (b) i.gcd(j);
-}
-void g(bool b, int i, int j) {
-  if (b) f(b, i, j);
-}
-main() {
-  g(false, 0, null);
-}
-''';
-    var expected = '''
-void f(bool b, int i, int? j) {
-  if (b) i.gcd(j!);
-}
-void g(bool b, int i, int? j) {
-  if (b) f(b, i, j);
-}
-main() {
-  g(false, 0, null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_conditional_usage_does_not_propagate_non_null_intent() async {
-    var content = '''
-void f(int i) {
-  assert(i != null);
-}
-void g(bool b, int i) {
-  if (b) f(i);
-}
-void h(bool b1, bool b2, int i) {
-  if (b1) g(b2, i);
-}
-main() {
-  h(true, false, null);
-}
-''';
-    var expected = '''
-void f(int i) {
-  assert(i != null);
-}
-void g(bool b, int? i) {
-  if (b) f(i!);
-}
-void h(bool b1, bool b2, int? i) {
-  if (b1) g(b2, i);
-}
-main() {
-  h(true, false, null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_data_flow_generic_inward() async {
-    var content = '''
-class C<T> {
-  void f(T t) {}
-}
-void g(C<int> c, int i) {
-  c.f(i);
-}
-void test(C<int> c) {
-  g(c, null);
-}
-''';
-
-    // Default behavior is to add nullability at the call site.  Rationale: this
-    // is correct in the common case where the generic parameter represents the
-    // type of an item in a container.  Also, if there are many callers that are
-    // largely independent, adding nullability to the callee would likely
-    // propagate to a field in the class, and thence (via return values of other
-    // methods) to most users of the class.  Whereas if we add nullability at
-    // the call site it's possible that other call sites won't need it.
-    //
-    // TODO(paulberry): possible improvement: detect that since C uses T in a
-    // contravariant way, and deduce that test should change to
-    // `void test(C<int?> c)`
-    var expected = '''
-class C<T> {
-  void f(T t) {}
-}
-void g(C<int?> c, int? i) {
-  c.f(i);
-}
-void test(C<int> c) {
-  g(c, null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_data_flow_generic_inward_hint() async {
-    var content = '''
-class C<T> {
-  void f(T? t) {}
-}
-void g(C<int> c, int i) {
-  c.f(i);
-}
-void test(C<int> c) {
-  g(c, null);
-}
-''';
-
-    // The user may override the behavior shown in test_data_flow_generic_inward
-    // by explicitly marking f's use of T as nullable.  Since this makes g's
-    // call to f valid regardless of the type of c, c's type will remain
-    // C<int>.
-    var expected = '''
-class C<T> {
-  void f(T? t) {}
-}
-void g(C<int> c, int? i) {
-  c.f(i);
-}
-void test(C<int> c) {
-  g(c, null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_data_flow_inward() async {
-    var content = '''
-int f(int i) => 0;
-int g(int i) => f(i);
-void test() {
-  g(null);
-}
-''';
-
-    var expected = '''
-int f(int? i) => 0;
-int g(int? i) => f(i);
-void test() {
-  g(null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_data_flow_inward_missing_type() async {
-    var content = '''
-int f(int i) => 0;
-int g(i) => f(i); // TODO(danrubel): suggest type
-void test() {
-  g(null);
-}
-''';
-
-    var expected = '''
-int f(int? i) => 0;
-int g(i) => f(i); // TODO(danrubel): suggest type
-void test() {
-  g(null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_data_flow_outward() async {
-    var content = '''
-int f(int i) => null;
-int g(int i) => f(i);
-''';
-
-    var expected = '''
-int? f(int i) => null;
-int? g(int i) => f(i);
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_data_flow_outward_missing_type() async {
-    var content = '''
-f(int i) => null; // TODO(danrubel): suggest type
-int g(int i) => f(i);
-''';
-
-    var expected = '''
-f(int i) => null; // TODO(danrubel): suggest type
-int? g(int i) => f(i);
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_discard_simple_condition() async {
-    var content = '''
-int f(int i) {
-  if (i == null) {
-    return null;
-  } else {
-    return i + 1;
-  }
-}
-''';
-
-    var expected = '''
-int f(int i) {
-  /* if (i == null) {
-    return null;
-  } else {
-    */ return i + 1; /*
-  } */
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_named_parameter_no_default_unused_option2_assume_nullable() async {
-    var content = '''
-void f({String s}) {}
-main() {
-  f();
-}
-''';
-    var expected = '''
-void f({String? s}) {}
-main() {
-  f();
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
-  }
-
-  test_named_parameter_no_default_unused_option2_assume_nullable_propagate() async {
-    var content = '''
-void f(String s) {}
-void g({String s}) {
-  f(s);
-}
-main() {
-  g();
-}
-''';
-    var expected = '''
-void f(String? s) {}
-void g({String? s}) {
-  f(s);
-}
-main() {
-  g();
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
-  }
-
-  test_named_parameter_no_default_unused_option2_assume_required() async {
-    var content = '''
-void f({String s}) {}
-main() {
-  f();
-}
-''';
-    var expected = '''
-void f({String? s}) {}
-main() {
-  f();
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_no_default_unused_option2_assume_required_propagate() async {
-    var content = '''
-void f(String s) {}
-void g({String s}) {
-  f(s);
-}
-main() {
-  g();
-}
-''';
-    var expected = '''
-void f(String? s) {}
-void g({String? s}) {
-  f(s);
-}
-main() {
-  g();
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_no_default_unused_required_option2_assume_nullable() async {
-    // The `@required` annotation overrides the assumption of nullability.
-    // The call at `f()` is presumed to be in error.
-    addMetaPackage();
-    var content = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f();
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f();
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
-  }
-
-  test_named_parameter_no_default_unused_required_option2_assume_required() async {
-    // Since the `@required` annotation is already present, it is not added
-    // again.
-    // The call at `f()` is presumed to be in error.
-    addMetaPackage();
-    var content = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f();
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f();
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_no_default_used_non_null_option2_assume_nullable() async {
-    var content = '''
-void f({String s}) {}
-main() {
-  f(s: 'x');
-}
-''';
-    var expected = '''
-void f({String? s}) {}
-main() {
-  f(s: 'x');
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
-  }
-
-  test_named_parameter_no_default_used_non_null_option2_assume_nullable_propagate() async {
-    var content = '''
-void f(String s) {}
-void g({String s}) {
-  f(s);
-}
-main() {
-  g(s: 'x');
-}
-''';
-    var expected = '''
-void f(String? s) {}
-void g({String? s}) {
-  f(s);
-}
-main() {
-  g(s: 'x');
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
-  }
-
-  test_named_parameter_no_default_used_non_null_option2_assume_required() async {
-    var content = '''
-void f({String s}) {}
-main() {
-  f(s: 'x');
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f(s: 'x');
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_no_default_used_non_null_option2_assume_required_propagate() async {
-    var content = '''
-void f(String s) {}
-void g({String s}) {
-  f(s);
-}
-main() {
-  g(s: 'x');
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f(String s) {}
-void g({@required String s}) {
-  f(s);
-}
-main() {
-  g(s: 'x');
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_no_default_used_non_null_required_option2_assume_required() async {
-    // Even if we are using the "assumeRequired" heuristic, we should not add a
-    // duplicate `@required` annotation.
-    addMetaPackage();
-    var content = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f(s: 'x');
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f(s: 'x');
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_no_default_used_null_option2() async {
-    var content = '''
-void f({String s}) {}
-main() {
-  f(s: null);
-}
-''';
-    var expected = '''
-void f({String? s}) {}
-main() {
-  f(s: null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_named_parameter_no_default_used_null_required_option2_assume_nullable() async {
-    // Explicitly passing `null` forces the parameter to be nullable even though
-    // it is required.
-    addMetaPackage();
-    var content = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f(s: null);
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String? s}) {}
-main() {
-  f(s: null);
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
-  }
-
-  test_named_parameter_no_default_used_null_required_option2_assume_required() async {
-    // Explicitly passing `null` forces the parameter to be nullable even though
-    // it is required.
-    addMetaPackage();
-    var content = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f(s: null);
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String? s}) {}
-main() {
-  f(s: null);
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_with_non_null_default_unused_option2() async {
-    var content = '''
-void f({String s: 'foo'}) {}
-main() {
-  f();
-}
-''';
-    var expected = '''
-void f({String s: 'foo'}) {}
-main() {
-  f();
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_named_parameter_with_non_null_default_used_non_null_option2() async {
-    var content = '''
-void f({String s: 'foo'}) {}
-main() {
-  f(s: 'bar');
-}
-''';
-    var expected = '''
-void f({String s: 'foo'}) {}
-main() {
-  f(s: 'bar');
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_named_parameter_with_non_null_default_used_null_option2() async {
-    var content = '''
-void f({String s: 'foo'}) {}
-main() {
-  f(s: null);
-}
-''';
-    var expected = '''
-void f({String? s: 'foo'}) {}
-main() {
-  f(s: null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_named_parameter_with_null_default_unused_option2() async {
-    var content = '''
-void f({String s: null}) {}
-main() {
-  f();
-}
-''';
-    var expected = '''
-void f({String? s: null}) {}
-main() {
-  f();
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_non_null_assertion() async {
-    var content = '''
-int f(int i, [int j]) {
-  if (i == 0) return i;
-  return i + j;
-}
-''';
-
-    var expected = '''
-int f(int i, [int? j]) {
-  if (i == 0) return i;
-  return i + j!;
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_single_file_multiple_changes() async {
-    var content = '''
-int f() => null;
-int g() => null;
-''';
-    var expected = '''
-int? f() => null;
-int? g() => null;
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_single_file_single_change() async {
-    var content = '''
-int f() => null;
-''';
-    var expected = '''
-int? f() => null;
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_two_files() async {
-    var root = '/home/test/lib';
-    var path1 = convertPath('$root/file1.dart');
-    var file1 = '''
-import 'file2.dart';
-int f() => null;
-int h() => g();
-''';
-    var expected1 = '''
-import 'file2.dart';
-int? f() => null;
-int? h() => g();
-''';
-    var path2 = convertPath('$root/file2.dart');
-    var file2 = '''
-import 'file1.dart';
-int g() => f();
-''';
-    var expected2 = '''
-import 'file1.dart';
-int? g() => f();
-''';
-    await _checkMultipleFileChanges(
-        {path1: file1, path2: file2}, {path1: expected1, path2: expected2});
-  }
-
-  test_unconditional_assert_statement_implies_non_null_intent() async {
-    var content = '''
-void f(int i) {
-  assert(i != null);
-}
-void g(bool b, int i) {
-  if (b) f(i);
-}
-main() {
-  g(false, null);
-}
-''';
-    var expected = '''
-void f(int i) {
-  assert(i != null);
-}
-void g(bool b, int? i) {
-  if (b) f(i!);
-}
-main() {
-  g(false, null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_unconditional_dereference_implies_non_null_intent() async {
-    var content = '''
-void f(int i) {
-  i.abs();
-}
-void g(bool b, int i) {
-  if (b) f(i);
-}
-main() {
-  g(false, null);
-}
-''';
-    var expected = '''
-void f(int i) {
-  i.abs();
-}
-void g(bool b, int? i) {
-  if (b) f(i!);
-}
-main() {
-  g(false, null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_unconditional_non_null_usage_implies_non_null_intent() async {
-    var content = '''
-void f(int i, int j) {
-  i.gcd(j);
-}
-void g(bool b, int i, int j) {
-  if (b) f(i, j);
-}
-main() {
-  g(false, 0, null);
-}
-''';
-    var expected = '''
-void f(int i, int j) {
-  i.gcd(j);
-}
-void g(bool b, int i, int? j) {
-  if (b) f(i, j!);
-}
-main() {
-  g(false, 0, null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  test_unconditional_usage_propagates_non_null_intent() async {
-    var content = '''
-void f(int i) {
-  assert(i != null);
-}
-void g(int i) {
-  f(i);
-}
-void h(bool b, int i) {
-  if (b) g(i);
-}
-main() {
-  h(false, null);
-}
-''';
-    var expected = '''
-void f(int i) {
-  assert(i != null);
-}
-void g(int i) {
-  f(i);
-}
-void h(bool b, int? i) {
-  if (b) g(i!);
-}
-main() {
-  h(false, null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-}
-
-@reflectiveTest
-class _ProvisionalApiTestPermissive extends _ProvisionalApiTestBase
-    with _ProvisionalApiTestCases {
-  @override
-  bool get _usePermissiveMode => true;
-}
-
-/// Tests of the provisional API, where the driver is reset between calls to
-/// `prepareInput` and `processInput`, ensuring that the migration algorithm
-/// sees different AST and element objects during different phases.
-@reflectiveTest
-class _ProvisionalApiTestWithReset extends _ProvisionalApiTestBase
-    with _ProvisionalApiTestCases {
-  @override
-  bool get _usePermissiveMode => false;
-
-  @override
-  void _afterPrepare() {
-    driver.resetUriResolution();
-  }
-}
-
-class _TestMigrationListener implements NullabilityMigrationListener {
-  final _edits = <Source, List<SourceEdit>>{};
-
-  @override
-  void addEdit(SingleNullabilityFix fix, SourceEdit edit) {
-    (_edits[fix.source] ??= []).add(edit);
-  }
-
-  @override
-  void addFix(SingleNullabilityFix fix) {}
-}
diff --git a/pkg/analysis_server/test/src/nullability/test_all.dart b/pkg/analysis_server/test/src/nullability/test_all.dart
deleted file mode 100644
index 77b5187..0000000
--- a/pkg/analysis_server/test/src/nullability/test_all.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2019, 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:test_reflective_loader/test_reflective_loader.dart';
-
-import 'migration_visitor_test.dart' as migration_visitor_test;
-import 'provisional_api_test.dart' as provisional_api_test;
-import 'unit_propagation_test.dart' as unit_propagation_test;
-
-main() {
-  defineReflectiveSuite(() {
-    migration_visitor_test.main();
-    provisional_api_test.main();
-    unit_propagation_test.main();
-  });
-}
diff --git a/pkg/analysis_server/test/src/nullability/unit_propagation_test.dart b/pkg/analysis_server/test/src/nullability/unit_propagation_test.dart
deleted file mode 100644
index d2fcf89..0000000
--- a/pkg/analysis_server/test/src/nullability/unit_propagation_test.dart
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/nullability/unit_propagation.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(UnitPropagationTest);
-  });
-}
-
-/// TODO(paulberry): write more tests
-@reflectiveTest
-class UnitPropagationTest {
-  var solver = Solver();
-
-  ConstraintVariable newVar(String name) => _NamedConstraintVariable(name);
-
-  test_record_copies_conditions() {
-    var a = newVar('a');
-    var b = newVar('b');
-    var conditions = [a];
-    solver.record(conditions, b);
-    conditions.removeLast();
-    expect(a.value, false);
-    expect(b.value, false);
-    solver.record([], a);
-    expect(a.value, true);
-    expect(b.value, true);
-  }
-
-  test_record_propagates_true_variables_immediately() {
-    var a = newVar('a');
-    expect(a.value, false);
-    solver.record([], a);
-    expect(a.value, true);
-    var b = newVar('b');
-    expect(b.value, false);
-    solver.record([a], b);
-    expect(b.value, true);
-  }
-}
-
-/// Representation of a constraint variable with a specified name.
-///
-/// This makes test failures easier to comprehend.
-class _NamedConstraintVariable extends ConstraintVariable {
-  final String _name;
-
-  _NamedConstraintVariable(this._name);
-
-  @override
-  String toString() => _name;
-}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart
deleted file mode 100644
index 36e3fab..0000000
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2019, 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:analysis_server/src/services/correction/assist.dart';
-import 'package:analyzer_plugin/utilities/assist/assist.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'assist_processor.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(ConvertIntoAbsoluteImportTest);
-  });
-}
-
-@reflectiveTest
-class ConvertIntoAbsoluteImportTest extends AssistProcessorTest {
-  @override
-  AssistKind get kind => DartAssistKind.CONVERT_INTO_ABSOLUTE_IMPORT;
-
-  test_fileName_onUri() async {
-    addSource('/home/test/lib/foo.dart', '');
-
-    await resolveTestUnit('''
-import 'foo.dart';
-''');
-    await assertHasAssistAt('foo.dart', '''
-import 'package:test/foo.dart';
-''');
-  }
-
-  test_fileName_onImport() async {
-    addSource('/home/test/lib/foo.dart', '');
-
-    await resolveTestUnit('''
-import 'foo.dart';
-''');
-    // Validate assist is on import keyword too.
-    await assertHasAssistAt('import', '''
-import 'package:test/foo.dart';
-''');
-  }
-
-  test_nonPackage_Uri() async {
-    addSource('/home/test/lib/foo.dart', '');
-
-    await resolveTestUnit('''
-import 'dart:core';
-''');
-
-    await assertNoAssistAt('dart:core');
-    await assertNoAssistAt('import');
-  }
-
-  test_path() async {
-    addSource('/home/test/lib/foo/bar.dart', '');
-
-    testFile = convertPath('/home/test/lib/src/test.dart');
-
-    await resolveTestUnit('''
-import '../foo/bar.dart';
-''');
-    await assertHasAssistAt('bar.dart', '''
-import 'package:test/foo/bar.dart';
-''');
-  }
-}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_package_import_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_package_import_test.dart
new file mode 100644
index 0000000..84df167
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_package_import_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2019, 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:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToPackageImportTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToPackageImportTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.CONVERT_TO_PACKAGE_IMPORT;
+
+  test_fileName_onImport() async {
+    addSource('/home/test/lib/foo.dart', '');
+
+    await resolveTestUnit('''
+import 'foo.dart';
+''');
+    // Validate assist is on import keyword too.
+    await assertHasAssistAt('import', '''
+import 'package:test/foo.dart';
+''');
+  }
+
+  test_fileName_onUri() async {
+    addSource('/home/test/lib/foo.dart', '');
+
+    await resolveTestUnit('''
+import 'foo.dart';
+''');
+    await assertHasAssistAt('foo.dart', '''
+import 'package:test/foo.dart';
+''');
+  }
+
+  test_invalidUri() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestUnit('''
+import ':[invalidUri]';
+''');
+    await assertNoAssistAt('invalid');
+  }
+
+  test_nonPackage_Uri() async {
+    addSource('/home/test/lib/foo.dart', '');
+
+    await resolveTestUnit('''
+import 'dart:core';
+''');
+
+    await assertNoAssistAt('dart:core');
+    await assertNoAssistAt('import');
+  }
+
+  test_packageUri() async {
+    addSource('/home/test/lib/foo.dart', '');
+
+    await resolveTestUnit('''
+import 'package:test/foo.dart';
+''');
+    await assertNoAssistAt('foo.dart');
+    await assertNoAssistAt('import');
+  }
+
+  test_path() async {
+    addSource('/home/test/lib/foo/bar.dart', '');
+
+    testFile = convertPath('/home/test/lib/src/test.dart');
+
+    await resolveTestUnit('''
+import '../foo/bar.dart';
+''');
+    await assertHasAssistAt('bar.dart', '''
+import 'package:test/foo/bar.dart';
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
index f51ffa7..caca61e 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
@@ -81,4 +81,40 @@
 }
 ''');
   }
+
+  test_assignment() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/widgets.dart';
+
+main() {
+  Widget w;
+  w = /*caret*/Container();
+}
+''');
+    await assertHasAssist('''
+import 'package:flutter/widgets.dart';
+
+main() {
+  Widget w;
+  w = Center(child: Container());
+}
+''');
+  }
+
+  test_expressionFunctionBody() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/widgets.dart';
+class FakeFlutter {
+  main() => /*caret*/Container();
+}
+''');
+    await assertHasAssist('''
+import 'package:flutter/widgets.dart';
+class FakeFlutter {
+  main() => Center(child: Container());
+}
+''');
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart b/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart
new file mode 100644
index 0000000..4cc5973
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2019, 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:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SortChildPropertyLastTest);
+  });
+}
+
+@reflectiveTest
+class SortChildPropertyLastTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.SORT_CHILD_PROPERTY_LAST;
+
+  test_already_sorted() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    crossAxisAlignment: CrossAxisAlignment.center,
+    children: <Widget>[
+      Text('aaa'),
+      Text('bbbbbb'),
+      Text('ccccccccc'),
+    ],
+  );
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_already_sorted_one_prop() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    children: <Widget>[
+      Text('aaa'),
+      Text('bbbbbb'),
+      Text('ccccccccc'),
+    ],
+  );
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_no_children() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    crossAxisAlignment: CrossAxisAlignment.center,
+  );
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_sort() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    /*caret*/children: <Widget>[
+      Text('aaa'),
+      Text('bbbbbb'),
+      Text('ccccccccc'),
+    ],
+    crossAxisAlignment: CrossAxisAlignment.center,
+  );
+}
+''');
+    await assertHasAssist('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    crossAxisAlignment: CrossAxisAlignment.center,
+    children: <Widget>[
+      Text('aaa'),
+      Text('bbbbbb'),
+      Text('ccccccccc'),
+    ],
+  );
+}
+''');
+    assertExitPosition(after: "],");
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
index bc906ab..7a7f079 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -11,7 +11,6 @@
     as convert_documentation_into_block;
 import 'convert_documentation_into_line_test.dart'
     as convert_documentation_into_line;
-import 'convert_into_absolute_import_test.dart' as convert_into_absolute_import;
 import 'convert_into_async_body_test.dart' as convert_into_async_body;
 import 'convert_into_block_body_test.dart' as convert_into_block_body;
 import 'convert_into_expression_body_test.dart' as convert_into_expression_body;
@@ -34,6 +33,7 @@
 import 'convert_to_multiline_string_test.dart' as convert_to_multiline_string;
 import 'convert_to_normal_parameter_test.dart' as convert_to_normal_parameter;
 import 'convert_to_null_aware_test.dart' as convert_to_null_aware;
+import 'convert_to_package_import_test.dart' as convert_to_package_import;
 import 'convert_to_set_literal_test.dart' as convert_to_set_literal;
 import 'convert_to_single_quoted_string_test.dart'
     as convert_to_single_quoted_string;
@@ -67,6 +67,7 @@
     as replace_conditional_with_if_else;
 import 'replace_if_else_with_conditional_test.dart'
     as replace_if_else_with_conditional;
+import 'sort_child_property_last_test.dart' as sort_child_property_last;
 import 'split_and_condition_test.dart' as split_and_condition;
 import 'split_variable_declaration_test.dart' as split_variable_declaration;
 import 'surround_with_block_test.dart' as surround_with_block;
@@ -85,7 +86,6 @@
     convert_class_to_mixin.main();
     convert_documentation_into_block.main();
     convert_documentation_into_line.main();
-    convert_into_absolute_import.main();
     convert_into_async_body.main();
     convert_into_block_body.main();
     convert_into_expression_body.main();
@@ -106,6 +106,7 @@
     convert_to_multiline_string.main();
     convert_to_normal_parameter.main();
     convert_to_null_aware.main();
+    convert_to_package_import.main();
     convert_to_set_literal.main();
     convert_to_single_quoted_string.main();
     convert_to_spread.main();
@@ -135,6 +136,7 @@
     remove_type_annotation.main();
     replace_conditional_with_if_else.main();
     replace_if_else_with_conditional.main();
+    sort_child_property_last.main();
     split_and_condition.main();
     split_variable_declaration.main();
     surround_with_block.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_support.dart b/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_support.dart
index 23d6dc3..5e8b477 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_support.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_support.dart
@@ -7,7 +7,6 @@
 import 'package:analysis_server/src/services/correction/fix/analysis_options/fix_generator.dart';
 import 'package:analyzer/error/error.dart' as engine;
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index beb7025..4dbfa14 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -7,9 +7,12 @@
 import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/error/lint_codes.dart';
+import 'package:analyzer/src/services/available_declarations.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     hide AnalysisError;
 import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
@@ -250,7 +253,19 @@
 
   /// Computes fixes for the given [error] in [testUnit].
   Future<List<Fix>> _computeFixes(AnalysisError error) async {
-    var context = new DartFixContextImpl(workspace, testAnalysisResult, error);
+    var tracker = DeclarationsTracker(MemoryByteStore(), resourceProvider);
+    tracker.addContext(driver.analysisContext);
+
+    var context = new DartFixContextImpl(
+      workspace,
+      testAnalysisResult,
+      error,
+      (name) {
+        var provider = TopLevelDeclarationsProvider(tracker);
+        provider.doTrackerWork();
+        return provider.get(driver.analysisContext, testFile, name);
+      },
+    );
     return await new DartFixContributor().computeFixes(context);
   }
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
index f1d1710..6c11ac8 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
@@ -18,8 +18,7 @@
 }
 
 @reflectiveTest
-class ImportLibraryProject1Test extends FixProcessorTest
-    with ImportLibraryTestMixin {
+class ImportLibraryProject1Test extends FixProcessorTest {
   @override
   FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT1;
 
@@ -39,6 +38,45 @@
     await assertNoFix();
   }
 
+  test_lib() async {
+    addPackageFile('my_pkg', 'a.dart', 'class Test {}');
+    newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+  my_pkg: any
+''');
+
+    await resolveTestUnit('''
+main() {
+  Test test = null;
+  print(test);
+}
+''');
+
+    await assertHasFix('''
+import 'package:my_pkg/a.dart';
+
+main() {
+  Test test = null;
+  print(test);
+}
+''', expectedNumberOfFixesForKind: 1);
+  }
+
+  test_lib_src() async {
+    addPackageFile('my_pkg', 'src/a.dart', 'class Test {}');
+    newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+  my_pkg: any
+''');
+    await resolveTestUnit('''
+main() {
+  Test test = null;
+  print(test);
+}
+''');
+    await assertNoFix();
+  }
+
   test_notInLib() async {
     addSource('/home/other/test/lib.dart', 'class Test {}');
     await resolveTestUnit('''
@@ -50,66 +88,40 @@
     await assertNoFix();
   }
 
-  test_preferDirectOverExport() async {
-    _configureMyPkg({'b.dart': 'class Test {}', 'a.dart': "export 'b.dart';"});
-    await resolveTestUnit('''
-main() {
-  Test test = null;
-  print(test);
-}
-''');
-    await assertHasFix('''
-import 'package:my_pkg/b.dart';
-
-main() {
-  Test test = null;
-  print(test);
-}
-''', expectedNumberOfFixesForKind: 1);
-  }
-
-  test_preferDirectOverExport_src() async {
-    _configureMyPkg({'b.dart': 'class Test {}', 'a.dart': "export 'b.dart';"});
-    await resolveTestUnit('''
-main() {
-  Test test = null;
-  print(test);
-}
-''');
-    await assertHasFix('''
-import 'package:my_pkg/b.dart';
-
-main() {
-  Test test = null;
-  print(test);
-}
-''', expectedNumberOfFixesForKind: 1);
-  }
-
   test_relativeDirective() async {
     addSource('/home/test/lib/a.dart', '''
-import "b.dart";
-''');
-    addSource('/home/test/lib/b.dart', '''
 class Foo {}
 ''');
     await resolveTestUnit('''
 main() { new Foo(); }
 ''');
     await assertHasFix('''
-import 'b.dart';
+import 'a.dart';
 
 main() { new Foo(); }
 ''',
         expectedNumberOfFixesForKind: 2,
-        matchFixMessage: "Import library 'b.dart'");
+        matchFixMessage: "Import library 'a.dart'");
+  }
+
+  test_relativeDirective_downOneDirectory() async {
+    addSource('/home/test/lib/dir/a.dart', '''
+class Foo {}
+''');
+    await resolveTestUnit('''
+main() { new Foo(); }
+''');
+    await assertHasFix('''
+import 'dir/a.dart';
+
+main() { new Foo(); }
+''',
+        expectedNumberOfFixesForKind: 2,
+        matchFixMessage: "Import library 'dir/a.dart'");
   }
 
   test_relativeDirective_upOneDirectory() async {
     addSource('/home/test/lib/a.dart', '''
-import "b.dart";
-''');
-    addSource('/home/test/lib/b.dart', '''
 class Foo {}
 ''');
     testFile = convertPath('/home/test/lib/dir/test.dart');
@@ -117,31 +129,12 @@
 main() { new Foo(); }
 ''');
     await assertHasFix('''
-import '../b.dart';
+import '../a.dart';
 
 main() { new Foo(); }
 ''',
         expectedNumberOfFixesForKind: 2,
-        matchFixMessage: "Import library '../b.dart'");
-  }
-
-  test_relativeDirective_downOneDirectory() async {
-    addSource('/home/test/lib/dir/a.dart', '''
-import "b.dart";
-''');
-    addSource('/home/test/lib/dir/b.dart', '''
-class Foo {}
-''');
-    await resolveTestUnit('''
-main() { new Foo(); }
-''');
-    await assertHasFix('''
-import 'dir/b.dart';
-
-main() { new Foo(); }
-''',
-        expectedNumberOfFixesForKind: 2,
-        matchFixMessage: "Import library 'dir/b.dart'");
+        matchFixMessage: "Import library '../a.dart'");
   }
 
   test_withClass_annotation() async {
@@ -395,7 +388,6 @@
 
   @failingTest
   test_withFunction_nonFunctionType() async {
-    // TODO Remove preferFunctionOverTopLevelVariable test once this is passing
     addSource('/home/test/lib/lib.dart', 'int zero = 0;');
     await resolveTestUnit('''
 main() {
@@ -405,25 +397,6 @@
     await assertNoFix();
   }
 
-  test_withFunction_preferFunctionOverTopLevelVariable() async {
-    _configureMyPkg({
-      'b.dart': 'var myFunction = () {};',
-      'a.dart': 'myFunction() {}',
-    });
-    await resolveTestUnit('''
-main() {
-  myFunction();
-}
-''');
-    await assertHasFix('''
-import 'package:my_pkg/a.dart';
-
-main() {
-  myFunction();
-}
-''');
-  }
-
   test_withFunction_unresolvedMethod() async {
     addSource('/home/test/lib/lib.dart', '''
 library lib;
@@ -505,16 +478,17 @@
 }
 
 @reflectiveTest
-class ImportLibraryProject2Test extends FixProcessorTest
-    with ImportLibraryTestMixin {
+class ImportLibraryProject2Test extends FixProcessorTest {
   @override
   FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT2;
 
-  test_preferDirectOverExport() async {
-    _configureMyPkg({
-      'b.dart': 'class Test {}',
-      'a.dart': "export 'b.dart';",
-    });
+  test_lib() async {
+    addPackageFile('my_pkg', 'a.dart', "export 'b.dart';");
+    addPackageFile('my_pkg', 'b.dart', 'class Test {}');
+    newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+  my_pkg: any
+''');
     await resolveTestUnit('''
 main() {
   Test test = null;
@@ -531,11 +505,13 @@
 ''');
   }
 
-  test_preferDirectOverExport_src() async {
-    _configureMyPkg({
-      'b.dart': 'class Test {}',
-      'a.dart': "export 'b.dart';",
-    });
+  test_lib_src() async {
+    addPackageFile('my_pkg', 'a.dart', "export 'src/b.dart';");
+    addPackageFile('my_pkg', 'src/b.dart', 'class Test {}');
+    newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+  my_pkg: any
+''');
     await resolveTestUnit('''
 main() {
   Test test = null;
@@ -593,15 +569,3 @@
 ''');
   }
 }
-
-mixin ImportLibraryTestMixin on FixProcessorTest {
-  /// Configures the source factory to have a package named 'my_pkg' and for
-  /// the package to contain all of the files described by the [pathToCode] map.
-  /// The keys in the map are paths relative to the root of the package, and the
-  /// values are the contents of the files at those paths.
-  void _configureMyPkg(Map<String, String> pathToCode) {
-    pathToCode.forEach((path, code) {
-      addPackageFile('my_pkg', path, code);
-    });
-  }
-}
diff --git a/pkg/analysis_server/test/src/test_all.dart b/pkg/analysis_server/test/src/test_all.dart
index 86eb450..a45add5 100644
--- a/pkg/analysis_server/test/src/test_all.dart
+++ b/pkg/analysis_server/test/src/test_all.dart
@@ -9,7 +9,6 @@
 import 'domains/test_all.dart' as domains;
 import 'flutter/test_all.dart' as flutter;
 import 'lsp/test_all.dart' as lsp;
-import 'nullability/test_all.dart' as nullability;
 import 'plugin/test_all.dart' as plugin;
 import 'services/test_all.dart' as services;
 import 'utilities/test_all.dart' as utilities;
@@ -25,7 +24,6 @@
     domains.main();
     flutter.main();
     lsp.main();
-    nullability.main();
     plugin.main();
     services.main();
     utilities.main();
diff --git a/pkg/analysis_server/test/src/utilities/flutter_test.dart b/pkg/analysis_server/test/src/utilities/flutter_test.dart
index 6bb17e3..cad467a 100644
--- a/pkg/analysis_server/test/src/utilities/flutter_test.dart
+++ b/pkg/analysis_server/test/src/utilities/flutter_test.dart
@@ -279,6 +279,46 @@
     expect(flutter.identifyWidgetExpression(expression), expression);
   }
 
+  test_identifyWidgetExpression_parent_assignmentExpression() async {
+    await resolveTestUnit('''
+import 'package:flutter/widgets.dart';
+
+main() {
+  Widget text;
+  text = Text('abc');
+}
+
+void useWidget(Widget w) {}
+''');
+    // Assignment itself.
+    {
+      var expression = findNode.simple('text =');
+      expect(flutter.identifyWidgetExpression(expression), isNull);
+    }
+
+    // Left hand side.
+    {
+      var expression = findNode.assignment('text =');
+      expect(flutter.identifyWidgetExpression(expression), isNull);
+    }
+
+    // Right hand side.
+    {
+      var expression = findNode.instanceCreation('Text(');
+      expect(flutter.identifyWidgetExpression(expression), expression);
+    }
+  }
+
+  test_identifyWidgetExpression_parent_expressionFunctionBody() async {
+    await resolveTestUnit('''
+import 'package:flutter/widgets.dart';
+
+main(Widget widget) => widget; // ref
+''');
+    Expression expression = findNodeAtString("widget; // ref");
+    expect(flutter.identifyWidgetExpression(expression), expression);
+  }
+
   test_identifyWidgetExpression_parent_expressionStatement() async {
     await resolveTestUnit('''
 import 'package:flutter/widgets.dart';
diff --git a/pkg/analysis_server/test/stress/replay/replay.dart b/pkg/analysis_server/test/stress/replay/replay.dart
index 60397de..f842c5d 100644
--- a/pkg/analysis_server/test/stress/replay/replay.dart
+++ b/pkg/analysis_server/test/stress/replay/replay.dart
@@ -10,6 +10,7 @@
 import 'dart:math' as math;
 
 import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart' as error;
 import 'package:analyzer/src/dart/scanner/reader.dart';
@@ -273,7 +274,8 @@
   List<int> _getBreakOffsets(String text) {
     List<int> breakOffsets = <int>[];
     Scanner scanner = new Scanner(null, new CharSequenceReader(text),
-        error.AnalysisErrorListener.NULL_LISTENER);
+        error.AnalysisErrorListener.NULL_LISTENER)
+      ..configureFeatures(FeatureSet.forTesting(sdkVersion: '2.2.2'));
     Token token = scanner.tokenize();
     // TODO(brianwilkerson) Randomize. Sometimes add zero (0) as a break point.
     while (token.type != TokenType.EOF) {
diff --git a/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart b/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart
index f100429..e3e874e 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart
@@ -125,7 +125,7 @@
 	/**
 	 * The method's params.
 	 */
-	params?: Array<any> | object;
+	params?: Array<any> | string;
 }
     ''';
       final List<AstNode> output = parseString(input);
@@ -143,7 +143,7 @@
       UnionType union = field.type;
       expect(union.types, hasLength(2));
       expect(union.types[0], isArrayOf(isSimpleType('any')));
-      expect(union.types[1], isSimpleType('object'));
+      expect(union.types[1], isSimpleType('string'));
     });
 
     test('parses an interface with a map into a MapType', () {
@@ -304,5 +304,22 @@
       expect(union.types[0], isSimpleType('string'));
       expect(union.types[1], isArrayOf(isSimpleType('number')));
     });
+
+    test('parses an union including Object into a single type', () {
+      final String input = '''
+interface SomeInformation {
+	label: string | object;
+}
+    ''';
+      final List<AstNode> output = parseString(input);
+      expect(output, hasLength(1));
+      expect(output[0], const TypeMatcher<Interface>());
+      final Interface interface = output[0];
+      expect(interface.members, hasLength(1));
+      final Field field = interface.members.first;
+      expect(field, const TypeMatcher<Field>());
+      expect(field.name, equals('label'));
+      expect(field.type, isSimpleType('object'));
+    });
   });
 }
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index f5420ac..d0cd4be 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -16,7 +16,13 @@
 
 Note: In LSP the client makes the first request so there is no obvious confirmation that the server is working correctly until the client sends an `initialize` request. Unlike standard JSON RPC, [LSP requires that headers are sent](https://microsoft.github.io/language-server-protocol/specification).
 
-## Message Status
+## Initialization Options
+
+- `onlyAnalyzeProjectsWithOpenFiles`: When set to `true`, analysis will only be performed for projects that have open files rather than the root workspace folder. Defaults to `false`.
+- `suggestFromUnimportedLibraries`: When set to `false`, completion will not include synbols that are not already imported into the current file. Defaults to `true`, though the client must additionally support `workspace/applyEdit` for these completions to be included.
+- `closingLabels`: When set to `true`, `dart/textDocument/publishClosingLabels` notifications will be sent with information to render editor closing labels.
+
+## Method Status
 
 Below is a list of LSP methods and their implementation status.
 
@@ -31,14 +37,14 @@
 | initialize | ✅ | ✅ | ✅ | ✅ | trace and other options NYI
 | initialized | ✅ | ✅ | ✅ | ✅ |
 | shutdown | ✅ | ✅ | ✅ | ✅ | supported but does nothing |
-| exit | | | | | |
-| $/cancelRequest | | | | | ignored (unsupported) |
+| exit | ✅ | ✅ | ✅ | ✅ |
+| $/cancelRequest | ✅ | ✅ | ✅ | ✅ |
 | window/showMessage | ✅ | | | |
 | window/showMessageRequest | | | | |
 | window/logMessage | ✅ | | | |
 | telemetry/event | | | | |
-| client/registerCapability | | | | | unused, but should be used for DocumentSelector at least
-| client/unregisterCapability | | | | |
+| client/registerCapability | ✅ | ✅ | ✅ | ✅ |
+| client/unregisterCapability | | | | | (unused, capabilities don't change currently)
 | workspace/workspaceFolders | | | | |
 | workspace/didChangeWorkspaceFolders | ✅ | ✅ | ✅ | ✅ |
 | workspace/configuration | | | | |
@@ -59,7 +65,7 @@
 | textDocument/declaration | | | | |
 | textDocument/definition | ✅ | ✅ | ✅ | ✅ |
 | textDocument/typeDefinition | | | | |
-| textDocument/implementation | | | | |
+| textDocument/implementation | ✅ | ✅ | ✅ | ✅ |
 | textDocument/references | ✅ | ✅ | ✅ | ✅ |
 | textDocument/documentHighlight | ✅ | ✅ | ✅ | ✅ |
 | textDocument/documentSymbol | ✅ | ✅ | ✅ | ✅ |
@@ -81,4 +87,36 @@
 | textDocument/prepareRename | | | | |
 | textDocument/foldingRange | ✅ | ✅ | ✅ | ✅ |
 
+## Custom Methods
 
+The following custom methods are also provided by the Dart LSP server:
+
+### dart/diagnosticServer Method
+
+Direction: Client -> Server
+Params: None
+Returns: `{ port: number }`
+
+Starts the analzyer diagnostics server (if not already running) and returns the port number it's listening on.
+
+### dart/textDocument/super Method
+
+Direction: Client -> Server
+Params: `TextDocumentPositionParams`
+Returns: `Location | null`
+
+Returns the location of the super definition of the class or method at the provided position or `null` if there isn't one.
+
+### $/analyzerStatus Notification
+
+Direction: Server -> Client
+Params: `{ isAnalyzing: boolean }`
+
+Notifies the client when analysis starts/completes.
+
+### dart/textDocument/publishClosingLabels Notification
+
+Direction: Server -> Client
+Params: `{ uri: string, abels: { label: string, range: Range }[] }`
+
+Notifies the client when closing label information is available (or updated) for a file.
diff --git a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
index 2967651..cbaec69 100644
--- a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
+++ b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
@@ -34,8 +34,7 @@
       name != 'ResourceOperationKind';
 }
 
-String generateDartForTypes(List<AstNode> types) {
-  // Keep maps of items we may need to look up quickly later.
+void recordTypes(List<AstNode> types) {
   types
       .whereType<TypeAlias>()
       .forEach((alias) => _typeAliases[alias.name] = alias);
@@ -51,6 +50,9 @@
   types
       .whereType<Namespace>()
       .forEach((namespace) => _namespaces[namespace.name] = namespace);
+}
+
+String generateDartForTypes(List<AstNode> types) {
   final buffer = new IndentableStringBuffer();
   _getSorted(types).forEach((t) => _writeType(buffer, t));
   final formattedCode = _formatCode(buffer.toString());
diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
index 23fb23f..08a111d 100644
--- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart
+++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
@@ -6,9 +6,8 @@
 import 'dart:io';
 
 import 'package:analysis_server/src/services/correction/strings.dart';
-import 'package:http/http.dart' as http;
-
 import 'package:args/args.dart';
+import 'package:http/http.dart' as http;
 import 'package:path/path.dart' as path;
 
 import 'codegen_dart.dart';
@@ -40,11 +39,27 @@
   final String outFolder = path.join(packageFolder, 'lib', 'lsp_protocol');
   new Directory(outFolder).createSync();
 
-  await writeSpecClasses(args, outFolder);
-  await writeCustomClasses(args, outFolder);
+  // Collect definitions for types in the spec and our custom extensions.
+  final specTypes = await getSpecClasses(args);
+  final customTypes = getCustomClasses();
+
+  // Record both sets of types in dictionaries for faster lookups, but also so
+  // they can reference each other and we can find the definitions during
+  // codegen.
+  recordTypes(specTypes);
+  recordTypes(customTypes);
+
+  // Generate formatted Dart code (as a string) for each set of types.
+  final String specTypesOutput = generateDartForTypes(specTypes);
+  final String customTypesOutput = generateDartForTypes(customTypes);
+
+  new File(path.join(outFolder, 'protocol_generated.dart')).writeAsStringSync(
+      generatedFileHeader(2018, importCustom: true) + specTypesOutput);
+  new File(path.join(outFolder, 'protocol_custom_generated.dart'))
+      .writeAsStringSync(generatedFileHeader(2019) + customTypesOutput);
 }
 
-Future writeSpecClasses(ArgResults args, String outFolder) async {
+Future<List<AstNode>> getSpecClasses(ArgResults args) async {
   if (args[argDownload]) {
     await downloadSpec();
   }
@@ -63,32 +78,45 @@
   // Extract additional inline types that are specificed online in the `results`
   // section of the doc.
   types.addAll(extractResultsInlineTypes(spec));
-
-  final String output = generateDartForTypes(types);
-
-  new File(path.join(outFolder, 'protocol_generated.dart'))
-      .writeAsStringSync(generatedFileHeader(2018) + output);
+  return types;
 }
 
-/// Writes classes used by Dart's custom LSP methods.
-Future writeCustomClasses(ArgResults args, String outFolder) async {
+List<AstNode> getCustomClasses() {
   interface(String name, List<Member> fields) {
     return new Interface(null, Token.identifier(name), [], [], fields);
   }
 
-  field(String name, {String type, canBeNull: false, canBeUndefined: false}) {
-    return new Field(null, Token.identifier(name), Type.identifier(type),
-        canBeNull, canBeUndefined);
+  field(String name,
+      {String type, array: false, canBeNull: false, canBeUndefined: false}) {
+    var fieldType =
+        array ? ArrayType(Type.identifier(type)) : Type.identifier(type);
+
+    return new Field(
+        null, Token.identifier(name), fieldType, canBeNull, canBeUndefined);
   }
 
   final List<AstNode> customTypes = [
     interface('DartDiagnosticServer', [field('port', type: 'number')]),
+    interface('AnalyzerStatusParams', [field('isAnalyzing', type: 'boolean')]),
+    interface('PublishClosingLabelsParams', [
+      field('uri', type: 'string'),
+      field('labels', type: 'ClosingLabel', array: true)
+    ]),
+    interface('ClosingLabel',
+        [field('range', type: 'Range'), field('label', type: 'string')]),
+    interface(
+      'CompletionItemResolutionInfo',
+      [
+        field('file', type: 'string'),
+        field('offset', type: 'number'),
+        field('libId', type: 'number'),
+        field('displayUri', type: 'string'),
+        field('rOffset', type: 'number'),
+        field('rLength', type: 'number')
+      ],
+    ),
   ];
-
-  final String output = generateDartForTypes(customTypes);
-
-  new File(path.join(outFolder, 'protocol_custom_generated.dart'))
-      .writeAsStringSync(generatedFileHeader(2019) + output);
+  return customTypes;
 }
 
 Namespace extractMethodsEnum(String spec) {
@@ -117,7 +145,7 @@
       comment, new Token.identifier('Method'), methodConstants);
 }
 
-String generatedFileHeader(int year) => '''
+String generatedFileHeader(int year, {bool importCustom = false}) => '''
 // Copyright (c) $year, 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.
@@ -130,10 +158,12 @@
 // ignore_for_file: deprecated_member_use_from_same_package
 // ignore_for_file: unnecessary_brace_in_string_interps
 // ignore_for_file: unused_import
+// ignore_for_file: unused_shown_name
 
 import 'dart:core' hide deprecated;
 import 'dart:core' as core show deprecated;
 import 'dart:convert' show JsonEncoder;
+import 'package:analysis_server/lsp_protocol/protocol${importCustom ? '_custom' : ''}_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/protocol/protocol_internal.dart'
     show listEqual, mapEqual;
diff --git a/pkg/analysis_server/tool/lsp_spec/lsp_specification.md b/pkg/analysis_server/tool/lsp_spec/lsp_specification.md
index 2bb235d..38c8f2e 100644
--- a/pkg/analysis_server/tool/lsp_spec/lsp_specification.md
+++ b/pkg/analysis_server/tool/lsp_spec/lsp_specification.md
@@ -7,7 +7,6 @@
 download the latest version of the specification before regenerating the
 code, run the same script with an argument of "--download".
 
-
 ---
 
 Copyright (c) Microsoft Corporation.
@@ -129,10 +128,10 @@
 	id: number | string | null;
 
 	/**
-	 * The result of a request. This can be omitted in
-	 * the case of an error.
+	 * The result of a request. This member is REQUIRED on success.
+	 * This member MUST NOT exist if there was an error invoking the method.
 	 */
-	result?: any;
+	result?: string | number | boolean | object | null;
 
 	/**
 	 * The error object in case a request fails.
@@ -260,7 +259,7 @@
 
 #### Position
 
-Position in a text document expressed as zero-based line and zero-based character offset. A position is between two characters like an 'insert' cursor in a editor.
+Position in a text document expressed as zero-based line and zero-based character offset. A position is between two characters like an 'insert' cursor in a editor. Special values like for example `-1` to denote the end of a line are not supported.
 
 ```typescript
 interface Position {
@@ -608,7 +607,7 @@
 
 #### WorkspaceEdit
 
-A workspace edit represents changes to many resources managed in the workspace. The edit should either provide `changes` or `documentChanges`. If the client can handle versioned document edits and if `documentChange`s are present, the latter are preferred over `changes`.
+A workspace edit represents changes to many resources managed in the workspace. The edit should either provide `changes` or `documentChanges`. If the client can handle versioned document edits and if `documentChanges` are present, the latter are preferred over `changes`.
 
 ```typescript
 export interface WorkspaceEdit {
@@ -678,6 +677,7 @@
 
 Language | Identifier
 -------- | ----------
+ABAP | `abap`
 Windows Bat | `bat`
 BibTeX | `bibtex`
 Clojure | `clojure`
@@ -698,6 +698,7 @@
 Ini | `ini`
 Java | `java`
 JavaScript | `javascript`
+JavaScript React | `javascriptreact`
 JSON | `json`
 LaTeX | `latex`
 Less | `less`
@@ -706,7 +707,8 @@
 Markdown | `markdown`
 Objective-C | `objective-c`
 Objective-C++ | `objective-cpp`
-Perl | `perl` and `perl6`
+Perl | `perl`
+Perl 6 | `perl6`
 PHP | `php`
 Powershell | `powershell`
 Pug | `jade`
@@ -715,13 +717,14 @@
 Razor (cshtml) | `razor`
 Ruby | `ruby`
 Rust | `rust`
-Sass | `scss` (syntax using curly brackets), `sass` (indented syntax)
+SCSS | `scss` (syntax using curly brackets), `sass` (indented syntax)
 Scala | `scala`
 ShaderLab | `shaderlab`
 Shell Script (Bash) | `shellscript`
 SQL | `sql`
 Swift | `swift`
 TypeScript | `typescript`
+TypeScript React| `typescriptreact`
 TeX | `tex`
 Visual Basic | `vb`
 XML | `xml`
@@ -1760,7 +1763,8 @@
 
 export interface TextDocumentSyncOptions {
 	/**
-	 * Open and close notifications are sent to the server.
+	 * Open and close notifications are sent to the server. If omitted open close notification should not
+	 * be sent.
 	 */
 	openClose?: boolean;
 	/**
@@ -1769,15 +1773,18 @@
 	 */
 	change?: number;
 	/**
-	 * Will save notifications are sent to the server.
+	 * If present will save notifications are sent to the server. If omitted the notification should not be
+	 * sent.
 	 */
 	willSave?: boolean;
 	/**
-	 * Will save wait until requests are sent to the server.
+	 * If present will save wait until requests are sent to the server. If omitted the request should not be
+	 * sent.
 	 */
 	willSaveWaitUntil?: boolean;
 	/**
-	 * Save notifications are sent to the server.
+	 * If present save notifications are sent to the server. If omitted the notification should not be
+	 * sent.
 	 */
 	save?: SaveOptions;
 }
@@ -1888,6 +1895,12 @@
 	 */
 	foldingRangeProvider?: boolean | FoldingRangeProviderOptions | (FoldingRangeProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions);
 	/**
+	 * The server provides go to declaration support.
+	 *
+	 * Since 3.14.0
+	 */
+	declarationProvider?: boolean | (TextDocumentRegistrationOptions & StaticRegistrationOptions);
+	/**
 	 * The server provides execute command support.
 	 */
 	executeCommandProvider?: ExecuteCommandOptions;
@@ -1939,7 +1952,7 @@
 
 #### <a href="#shutdown" name="shutdown" class="anchor">Shutdown Request (:leftwards_arrow_with_hook:)</a>
 
-The shutdown request is sent from the client to the server. It asks the server to shut down, but to not exit (otherwise the response might not be delivered correctly to the client). There is a separate exit notification that asks the server to exit.
+The shutdown request is sent from the client to the server. It asks the server to shut down, but to not exit (otherwise the response might not be delivered correctly to the client). There is a separate exit notification that asks the server to exit. Clients must not sent any notifications other than `exit` or requests to a server to which they have sent a shutdown requests. If a server receives requests after a shutdown request those requests should be errored with `InvalidRequest`.
 
 _Request_:
 * method: 'shutdown'
@@ -2229,8 +2242,8 @@
 	uri: string;
 
 	/**
-	 * The name of the workspace folder. Defaults to the
-	 * uri's basename.
+	 * The name of the workspace folder. Used to refer to this
+	 * workspace folder in the user interface.
 	 */
 	name: string;
 }
@@ -2395,7 +2408,7 @@
 
 ```typescript
 /**
- * Describe options to be used when registering for text document change events.
+ * Describe options to be used when registering for file system change events.
  */
 export interface DidChangeWatchedFilesRegistrationOptions {
 	/**
@@ -2549,6 +2562,14 @@
 	 * Indicates whether the edit was applied or not.
 	 */
 	applied: boolean;
+
+	/**
+	 * An optional textual description for why the edit was not applied.
+	 * This may be used may be used by the server for diagnostic
+	 * logging or to provide a suitable error for a request that
+	 * triggered the edit.
+	 */
+	failureReason?: string;
 }
 ```
 * error: code and message set in case an exception happens during the request.
@@ -2898,7 +2919,8 @@
 
 	/**
 	 * The kind of this completion item. Based of the kind
-	 * an icon is chosen by the editor.
+	 * an icon is chosen by the editor. The standardized set
+	 * of available values is defined in `CompletionItemKind`.
 	 */
 	kind?: number;
 
@@ -2995,7 +3017,7 @@
 	command?: Command;
 
 	/**
-	 * An data entry field that is preserved on a completion item between
+	 * A data entry field that is preserved on a completion item between
 	 * a completion and a completion resolve request.
 	 */
 	data?: any
@@ -3051,6 +3073,15 @@
 	triggerCharacters?: string[];
 
 	/**
+	 * The list of all possible characters that commit a completion. This field can be used
+	 * if clients don't support individual commmit characters per completion item. See
+	 * `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport`
+	 *
+   * Since 3.2.0
+	 */
+	allCommitCharacters?: string[];
+
+	/**
 	 * The server provides support to resolve additional
 	 * information for a completion item.
 	 */
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript.dart b/pkg/analysis_server/tool/lsp_spec/typescript.dart
index afa5b76..f80733d 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript.dart
@@ -50,11 +50,15 @@
     "TextDocumentSyncOptions": {
       "change": "TextDocumentSyncKind",
     },
+    "TextDocumentChangeRegistrationOptions": {
+      "syncKind": "TextDocumentSyncKind",
+    },
     "FileSystemWatcher": {
       "kind": "WatchKind",
     },
     "CompletionItem": {
       "kind": "CompletionItemKind",
+      "data": "CompletionItemResolutionInfo",
     },
     "DocumentHighlight": {
       "kind": "DocumentHighlightKind",
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
index 2412309..3b06fd1 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
@@ -12,7 +12,8 @@
 
 final _validIdentifierCharacters = RegExp('[a-zA-Z0-9_]');
 
-bool isAnyType(TypeBase t) => t is Type && t.name == 'any';
+bool isAnyType(TypeBase t) =>
+    t is Type && (t.name == 'any' || t.name == 'object');
 
 bool isNullType(TypeBase t) => t is Type && t.name == 'null';
 
@@ -596,6 +597,15 @@
     final uniqueTypes = new Map.fromEntries(
       types.map((t) => new MapEntry(t.dartTypeWithTypeArgs, t)),
     ).values.toList();
+
+    // If our list includes something that maps to dynamic as well as other
+    // types, we should just treat the whole thing as dynamic as we get no value
+    // typing Either4<bool, String, num, dynamic> but it becomes much more
+    // difficult to use.
+    if (uniqueTypes.any(isAnyType)) {
+      return [uniqueTypes.firstWhere(isAnyType)];
+    }
+
     return uniqueTypes;
   }
 
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisError.java b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisError.java
index 24a3fdc..d635b12 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisError.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisError.java
@@ -74,6 +74,12 @@
   private final String url;
 
   /**
+   * Additional messages associated with this diagnostic that provide context to help the user
+   * understand the diagnostic.
+   */
+  private final List<DiagnosticMessage> contextMessages;
+
+  /**
    * A hint to indicate to interested clients that this error has an associated fix (or fixes). The
    * absence of this field implies there are not known to be fixes. Note that since the operation to
    * calculate whether fixes apply needs to be performant it is possible that complicated tests will
@@ -87,7 +93,7 @@
   /**
    * Constructor for {@link AnalysisError}.
    */
-  public AnalysisError(String severity, String type, Location location, String message, String correction, String code, String url, Boolean hasFix) {
+  public AnalysisError(String severity, String type, Location location, String message, String correction, String code, String url, List<DiagnosticMessage> contextMessages, Boolean hasFix) {
     this.severity = severity;
     this.type = type;
     this.location = location;
@@ -95,6 +101,7 @@
     this.correction = correction;
     this.code = code;
     this.url = url;
+    this.contextMessages = contextMessages;
     this.hasFix = hasFix;
   }
 
@@ -110,6 +117,7 @@
         ObjectUtilities.equals(other.correction, correction) &&
         ObjectUtilities.equals(other.code, code) &&
         ObjectUtilities.equals(other.url, url) &&
+        ObjectUtilities.equals(other.contextMessages, contextMessages) &&
         ObjectUtilities.equals(other.hasFix, hasFix);
     }
     return false;
@@ -123,8 +131,9 @@
     String correction = jsonObject.get("correction") == null ? null : jsonObject.get("correction").getAsString();
     String code = jsonObject.get("code").getAsString();
     String url = jsonObject.get("url") == null ? null : jsonObject.get("url").getAsString();
+    List<DiagnosticMessage> contextMessages = jsonObject.get("contextMessages") == null ? null : DiagnosticMessage.fromJsonArray(jsonObject.get("contextMessages").getAsJsonArray());
     Boolean hasFix = jsonObject.get("hasFix") == null ? null : jsonObject.get("hasFix").getAsBoolean();
-    return new AnalysisError(severity, type, location, message, correction, code, url, hasFix);
+    return new AnalysisError(severity, type, location, message, correction, code, url, contextMessages, hasFix);
   }
 
   public static List<AnalysisError> fromJsonArray(JsonArray jsonArray) {
@@ -147,6 +156,14 @@
   }
 
   /**
+   * Additional messages associated with this diagnostic that provide context to help the user
+   * understand the diagnostic.
+   */
+  public List<DiagnosticMessage> getContextMessages() {
+    return contextMessages;
+  }
+
+  /**
    * The correction message to be displayed for this error. The correction message should indicate
    * how the user can fix the error. The field is omitted if there is no correction message
    * associated with the error code.
@@ -214,6 +231,7 @@
     builder.append(correction);
     builder.append(code);
     builder.append(url);
+    builder.append(contextMessages);
     builder.append(hasFix);
     return builder.toHashCode();
   }
@@ -231,6 +249,13 @@
     if (url != null) {
       jsonObject.addProperty("url", url);
     }
+    if (contextMessages != null) {
+      JsonArray jsonArrayContextMessages = new JsonArray();
+      for (DiagnosticMessage elt : contextMessages) {
+        jsonArrayContextMessages.add(elt.toJson());
+      }
+      jsonObject.add("contextMessages", jsonArrayContextMessages);
+    }
     if (hasFix != null) {
       jsonObject.addProperty("hasFix", hasFix);
     }
@@ -255,6 +280,8 @@
     builder.append(code + ", ");
     builder.append("url=");
     builder.append(url + ", ");
+    builder.append("contextMessages=");
+    builder.append(StringUtils.join(contextMessages, ", ") + ", ");
     builder.append("hasFix=");
     builder.append(hasFix);
     builder.append("]");
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AvailableSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/AvailableSuggestion.java
index 488d3c9..fb4704b 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/AvailableSuggestion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AvailableSuggestion.java
@@ -42,6 +42,12 @@
   private final String label;
 
   /**
+   * The URI of the library that declares the element being suggested, not the URI of the library
+   * associated with the enclosing AvailableSuggestionSet.
+   */
+  private final String declaringLibraryUri;
+
+  /**
    * Information about the element reference being suggested.
    */
   private final Element element;
@@ -96,8 +102,9 @@
   /**
    * Constructor for {@link AvailableSuggestion}.
    */
-  public AvailableSuggestion(String label, Element element, String defaultArgumentListString, int[] defaultArgumentListTextRanges, String docComplete, String docSummary, List<String> parameterNames, List<String> parameterTypes, List<String> relevanceTags, Integer requiredParameterCount) {
+  public AvailableSuggestion(String label, String declaringLibraryUri, Element element, String defaultArgumentListString, int[] defaultArgumentListTextRanges, String docComplete, String docSummary, List<String> parameterNames, List<String> parameterTypes, List<String> relevanceTags, Integer requiredParameterCount) {
     this.label = label;
+    this.declaringLibraryUri = declaringLibraryUri;
     this.element = element;
     this.defaultArgumentListString = defaultArgumentListString;
     this.defaultArgumentListTextRanges = defaultArgumentListTextRanges;
@@ -115,6 +122,7 @@
       AvailableSuggestion other = (AvailableSuggestion) obj;
       return
         ObjectUtilities.equals(other.label, label) &&
+        ObjectUtilities.equals(other.declaringLibraryUri, declaringLibraryUri) &&
         ObjectUtilities.equals(other.element, element) &&
         ObjectUtilities.equals(other.defaultArgumentListString, defaultArgumentListString) &&
         Arrays.equals(other.defaultArgumentListTextRanges, defaultArgumentListTextRanges) &&
@@ -130,6 +138,7 @@
 
   public static AvailableSuggestion fromJson(JsonObject jsonObject) {
     String label = jsonObject.get("label").getAsString();
+    String declaringLibraryUri = jsonObject.get("declaringLibraryUri").getAsString();
     Element element = Element.fromJson(jsonObject.get("element").getAsJsonObject());
     String defaultArgumentListString = jsonObject.get("defaultArgumentListString") == null ? null : jsonObject.get("defaultArgumentListString").getAsString();
     int[] defaultArgumentListTextRanges = jsonObject.get("defaultArgumentListTextRanges") == null ? null : JsonUtilities.decodeIntArray(jsonObject.get("defaultArgumentListTextRanges").getAsJsonArray());
@@ -139,7 +148,7 @@
     List<String> parameterTypes = jsonObject.get("parameterTypes") == null ? null : JsonUtilities.decodeStringList(jsonObject.get("parameterTypes").getAsJsonArray());
     List<String> relevanceTags = jsonObject.get("relevanceTags") == null ? null : JsonUtilities.decodeStringList(jsonObject.get("relevanceTags").getAsJsonArray());
     Integer requiredParameterCount = jsonObject.get("requiredParameterCount") == null ? null : jsonObject.get("requiredParameterCount").getAsInt();
-    return new AvailableSuggestion(label, element, defaultArgumentListString, defaultArgumentListTextRanges, docComplete, docSummary, parameterNames, parameterTypes, relevanceTags, requiredParameterCount);
+    return new AvailableSuggestion(label, declaringLibraryUri, element, defaultArgumentListString, defaultArgumentListTextRanges, docComplete, docSummary, parameterNames, parameterTypes, relevanceTags, requiredParameterCount);
   }
 
   public static List<AvailableSuggestion> fromJsonArray(JsonArray jsonArray) {
@@ -155,6 +164,14 @@
   }
 
   /**
+   * The URI of the library that declares the element being suggested, not the URI of the library
+   * associated with the enclosing AvailableSuggestionSet.
+   */
+  public String getDeclaringLibraryUri() {
+    return declaringLibraryUri;
+  }
+
+  /**
    * A default String for use in generating argument list source contents on the client side.
    */
   public String getDefaultArgumentListString() {
@@ -235,6 +252,7 @@
   public int hashCode() {
     HashCodeBuilder builder = new HashCodeBuilder();
     builder.append(label);
+    builder.append(declaringLibraryUri);
     builder.append(element);
     builder.append(defaultArgumentListString);
     builder.append(defaultArgumentListTextRanges);
@@ -250,6 +268,7 @@
   public JsonObject toJson() {
     JsonObject jsonObject = new JsonObject();
     jsonObject.addProperty("label", label);
+    jsonObject.addProperty("declaringLibraryUri", declaringLibraryUri);
     jsonObject.add("element", element.toJson());
     if (defaultArgumentListString != null) {
       jsonObject.addProperty("defaultArgumentListString", defaultArgumentListString);
@@ -300,6 +319,8 @@
     builder.append("[");
     builder.append("label=");
     builder.append(label + ", ");
+    builder.append("declaringLibraryUri=");
+    builder.append(declaringLibraryUri + ", ");
     builder.append("element=");
     builder.append(element + ", ");
     builder.append("defaultArgumentListString=");
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java
index 5007ebd..8de0a91 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java
@@ -16,10 +16,12 @@
 public class CompletionService {
 
   /**
-   * The client will receive notifications once subscribed with completion suggestion sets from the
-   * libraries of interest. The client should keep an up-to-date record of these in memory so that it
-   * will be able to union these candidates with other completion suggestions when applicable at
-   * completion time.
+   * The client will receive availableSuggestions notifications once subscribed with completion
+   * suggestion sets from the libraries of interest. The client should keep an up-to-date record of
+   * these in memory so that it will be able to union these candidates with other completion
+   * suggestions when applicable at completion time.
+   *
+   * The client will also receive existingImports notifications.
    */
   public static final String AVAILABLE_SUGGESTION_SETS = "AVAILABLE_SUGGESTION_SETS";
 
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/DiagnosticMessage.java b/pkg/analysis_server/tool/spec/generated/java/types/DiagnosticMessage.java
new file mode 100644
index 0000000..6fdafcd
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/DiagnosticMessage.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * A message associated with a diagnostic.
+ *
+ * For example, if the diagnostic is reporting that a variable has been referenced before it was
+ * declared, it might have a diagnostic message that indicates where the variable is declared.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class DiagnosticMessage {
+
+  public static final DiagnosticMessage[] EMPTY_ARRAY = new DiagnosticMessage[0];
+
+  public static final List<DiagnosticMessage> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The message to be displayed to the user.
+   */
+  private final String message;
+
+  /**
+   * The location associated with or referenced by the message. Clients should provide the ability to
+   * navigate to the location.
+   */
+  private final Location location;
+
+  /**
+   * Constructor for {@link DiagnosticMessage}.
+   */
+  public DiagnosticMessage(String message, Location location) {
+    this.message = message;
+    this.location = location;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof DiagnosticMessage) {
+      DiagnosticMessage other = (DiagnosticMessage) obj;
+      return
+        ObjectUtilities.equals(other.message, message) &&
+        ObjectUtilities.equals(other.location, location);
+    }
+    return false;
+  }
+
+  public static DiagnosticMessage fromJson(JsonObject jsonObject) {
+    String message = jsonObject.get("message").getAsString();
+    Location location = Location.fromJson(jsonObject.get("location").getAsJsonObject());
+    return new DiagnosticMessage(message, location);
+  }
+
+  public static List<DiagnosticMessage> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<DiagnosticMessage> list = new ArrayList<DiagnosticMessage>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The location associated with or referenced by the message. Clients should provide the ability to
+   * navigate to the location.
+   */
+  public Location getLocation() {
+    return location;
+  }
+
+  /**
+   * The message to be displayed to the user.
+   */
+  public String getMessage() {
+    return message;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(message);
+    builder.append(location);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("message", message);
+    jsonObject.add("location", location.toJson());
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("message=");
+    builder.append(message + ", ");
+    builder.append("location=");
+    builder.append(location);
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java
new file mode 100644
index 0000000..a9055d0
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Information about an existing import, with elements that it provides.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExistingImport {
+
+  public static final ExistingImport[] EMPTY_ARRAY = new ExistingImport[0];
+
+  public static final List<ExistingImport> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in the enclosing
+   * ExistingImports and its ImportedElementSet object.
+   */
+  private final int uri;
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  private final int[] elements;
+
+  /**
+   * Constructor for {@link ExistingImport}.
+   */
+  public ExistingImport(int uri, int[] elements) {
+    this.uri = uri;
+    this.elements = elements;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ExistingImport) {
+      ExistingImport other = (ExistingImport) obj;
+      return
+        other.uri == uri &&
+        Arrays.equals(other.elements, elements);
+    }
+    return false;
+  }
+
+  public static ExistingImport fromJson(JsonObject jsonObject) {
+    int uri = jsonObject.get("uri").getAsInt();
+    int[] elements = JsonUtilities.decodeIntArray(jsonObject.get("elements").getAsJsonArray());
+    return new ExistingImport(uri, elements);
+  }
+
+  public static List<ExistingImport> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<ExistingImport> list = new ArrayList<ExistingImport>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  public int[] getElements() {
+    return elements;
+  }
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in the enclosing
+   * ExistingImports and its ImportedElementSet object.
+   */
+  public int getUri() {
+    return uri;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(uri);
+    builder.append(elements);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("uri", uri);
+    JsonArray jsonArrayElements = new JsonArray();
+    for (int elt : elements) {
+      jsonArrayElements.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("elements", jsonArrayElements);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("uri=");
+    builder.append(uri + ", ");
+    builder.append("elements=");
+    builder.append(StringUtils.join(elements, ", "));
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java
new file mode 100644
index 0000000..7473d829
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Information about all existing imports in a library.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExistingImports {
+
+  public static final ExistingImports[] EMPTY_ARRAY = new ExistingImports[0];
+
+  public static final List<ExistingImports> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  private final ImportedElementSet elements;
+
+  /**
+   * The list of imports in the library.
+   */
+  private final List<ExistingImport> imports;
+
+  /**
+   * Constructor for {@link ExistingImports}.
+   */
+  public ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+    this.elements = elements;
+    this.imports = imports;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ExistingImports) {
+      ExistingImports other = (ExistingImports) obj;
+      return
+        ObjectUtilities.equals(other.elements, elements) &&
+        ObjectUtilities.equals(other.imports, imports);
+    }
+    return false;
+  }
+
+  public static ExistingImports fromJson(JsonObject jsonObject) {
+    ImportedElementSet elements = ImportedElementSet.fromJson(jsonObject.get("elements").getAsJsonObject());
+    List<ExistingImport> imports = ExistingImport.fromJsonArray(jsonObject.get("imports").getAsJsonArray());
+    return new ExistingImports(elements, imports);
+  }
+
+  public static List<ExistingImports> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<ExistingImports> list = new ArrayList<ExistingImports>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  public ImportedElementSet getElements() {
+    return elements;
+  }
+
+  /**
+   * The list of imports in the library.
+   */
+  public List<ExistingImport> getImports() {
+    return imports;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(elements);
+    builder.append(imports);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.add("elements", elements.toJson());
+    JsonArray jsonArrayImports = new JsonArray();
+    for (ExistingImport elt : imports) {
+      jsonArrayImports.add(elt.toJson());
+    }
+    jsonObject.add("imports", jsonArrayImports);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("elements=");
+    builder.append(elements + ", ");
+    builder.append("imports=");
+    builder.append(StringUtils.join(imports, ", "));
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java b/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
index 463b420..88e6f0b 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
@@ -55,8 +55,9 @@
   private final String containingLibraryPath;
 
   /**
-   * The name of the library in which the referenced element is declared. This data is omitted if
-   * there is no referenced element, or if the element is declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core", "package:.." and file uris
+   * represented by the path on disk, "/..". The data is omitted if the element is declared inside an
+   * HTML file.
    */
   private final String containingLibraryName;
 
@@ -185,8 +186,9 @@
   }
 
   /**
-   * The name of the library in which the referenced element is declared. This data is omitted if
-   * there is no referenced element, or if the element is declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core", "package:.." and file uris
+   * represented by the path on disk, "/..". The data is omitted if the element is declared inside an
+   * HTML file.
    */
   public String getContainingLibraryName() {
     return containingLibraryName;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java b/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java
new file mode 100644
index 0000000..50ca031
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * The set of top-level elements encoded as pairs of the defining library URI and the name, and
+ * stored in the parallel lists elementUris and elementNames.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ImportedElementSet {
+
+  public static final ImportedElementSet[] EMPTY_ARRAY = new ImportedElementSet[0];
+
+  public static final List<ImportedElementSet> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The list of unique strings in this object.
+   */
+  private final List<String> strings;
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  private final int[] uris;
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  private final int[] names;
+
+  /**
+   * Constructor for {@link ImportedElementSet}.
+   */
+  public ImportedElementSet(List<String> strings, int[] uris, int[] names) {
+    this.strings = strings;
+    this.uris = uris;
+    this.names = names;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ImportedElementSet) {
+      ImportedElementSet other = (ImportedElementSet) obj;
+      return
+        ObjectUtilities.equals(other.strings, strings) &&
+        Arrays.equals(other.uris, uris) &&
+        Arrays.equals(other.names, names);
+    }
+    return false;
+  }
+
+  public static ImportedElementSet fromJson(JsonObject jsonObject) {
+    List<String> strings = JsonUtilities.decodeStringList(jsonObject.get("strings").getAsJsonArray());
+    int[] uris = JsonUtilities.decodeIntArray(jsonObject.get("uris").getAsJsonArray());
+    int[] names = JsonUtilities.decodeIntArray(jsonObject.get("names").getAsJsonArray());
+    return new ImportedElementSet(strings, uris, names);
+  }
+
+  public static List<ImportedElementSet> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<ImportedElementSet> list = new ArrayList<ImportedElementSet>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  public int[] getNames() {
+    return names;
+  }
+
+  /**
+   * The list of unique strings in this object.
+   */
+  public List<String> getStrings() {
+    return strings;
+  }
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  public int[] getUris() {
+    return uris;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(strings);
+    builder.append(uris);
+    builder.append(names);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    JsonArray jsonArrayStrings = new JsonArray();
+    for (String elt : strings) {
+      jsonArrayStrings.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("strings", jsonArrayStrings);
+    JsonArray jsonArrayUris = new JsonArray();
+    for (int elt : uris) {
+      jsonArrayUris.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("uris", jsonArrayUris);
+    JsonArray jsonArrayNames = new JsonArray();
+    for (int elt : names) {
+      jsonArrayNames.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("names", jsonArrayNames);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("strings=");
+    builder.append(StringUtils.join(strings, ", ") + ", ");
+    builder.append("uris=");
+    builder.append(StringUtils.join(uris, ", ") + ", ");
+    builder.append("names=");
+    builder.append(StringUtils.join(names, ", "));
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 56f1243..14ed664 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  <version>1.26.0</version>
+  <version>1.27.1</version>
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -1588,6 +1588,17 @@
           returned for the indicated completion.
         </p>
       </field>
+      <field name="libraryFile" optional="true">
+        <ref>FilePath</ref>
+        <p>
+          The library file that contains the file where completion was
+          requested. The client might use it for example together with the
+          <tt>existingImports</tt> notification to filter out available
+          suggestions. If there were changes to existing imports in the library,
+          the corresponding <tt>existingImports</tt> notification will be sent
+          before the completion notification.
+        </p>
+      </field>
       <field name="includedSuggestionSets" optional="true">
         <list>
           <ref>IncludedSuggestionSet</ref>
@@ -1658,6 +1669,27 @@
       </field>
     </params>
   </notification>
+  <notification event="existingImports">
+    <p>
+      Reports existing imports in a library. This notification may be sent
+      multiple times for a library. When a notification is processed, clients
+      should replace any previous information for the library.
+    </p>
+    <params>
+      <field name="file">
+        <ref>FilePath</ref>
+        <p>
+          The defining file of the library.
+        </p>
+      </field>
+      <field name="imports">
+        <ref>ExistingImports</ref>
+        <p>
+          The existing imports in the library.
+        </p>
+      </field>
+    </params>
+  </notification>
 </domain>
 <domain name="search">
   <p>
@@ -2221,6 +2253,18 @@
           A list of source edits to apply the recommended changes.
         </p>
       </field>
+      <field name="details" optional="true">
+        <list>
+          <ref>String</ref>
+        </list>
+        <p>
+          Messages that should be displayed to the user that describe details of
+          the fix generation. For example, the messages might (a) point out
+          details that users might want to explore before committing the changes
+          or (b) describe exceptions that were thrown but that did not stop the
+          fixes from being produced. The list will be omitted if it is empty.
+        </p>
+      </field>
     </result>
   </request>
   <request method="getFixes">
@@ -3566,6 +3610,14 @@
           The identifier to present to the user for code completion.
         </p>
       </field>
+      <field name="declaringLibraryUri">
+        <ref>String</ref>
+        <p>
+          The URI of the library that declares the element being suggested,
+          not the URI of the library associated with the enclosing
+          <tt>AvailableSuggestionSet</tt>.
+        </p>
+      </field>
       <field name="element">
         <ref>Element</ref>
         <p>
@@ -3669,6 +3721,86 @@
       </field>
     </object>
   </type>
+  <type name="ExistingImport">
+    <p>
+      Information about an existing import, with elements that it provides.
+    </p>
+    <object>
+      <field name="uri">
+        <ref>int</ref>
+        <p>
+          The URI of the imported library.
+          It is an index in the <tt>strings</tt> field, in the enclosing
+          <tt>ExistingImports</tt> and its <tt>ImportedElementSet</tt> object.
+        </p>
+      </field>
+      <field name="elements">
+        <list>
+          <ref>int</ref>
+        </list>
+        <p>
+          The list of indexes of elements, in the enclosing
+          <tt>ExistingImports</tt> object.
+        </p>
+      </field>
+    </object>
+  </type>
+  <type name="ExistingImports">
+    <p>
+      Information about all existing imports in a library.
+    </p>
+    <object>
+      <field name="elements">
+        <ref>ImportedElementSet</ref>
+        <p>
+          The set of all unique imported elements for all imports.
+        </p>
+      </field>
+      <field name="imports">
+        <list>
+          <ref>ExistingImport</ref>
+        </list>
+        <p>
+          The list of imports in the library.
+        </p>
+      </field>
+    </object>
+  </type>
+  <type name="ImportedElementSet">
+    <p>
+      The set of top-level elements encoded as pairs of the defining library
+      URI and the name, and stored in the parallel lists <tt>elementUris</tt>
+      and <tt>elementNames</tt>.
+    </p>
+    <object>
+      <field name="strings">
+        <list>
+          <ref>String</ref>
+        </list>
+        <p>
+          The list of unique strings in this object.
+        </p>
+      </field>
+      <field name="uris">
+        <list>
+          <ref>int</ref>
+        </list>
+        <p>
+          The library URI part of the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
+      </field>
+      <field name="names">
+        <list>
+          <ref>int</ref>
+        </list>
+        <p>
+          The name part of a the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
+      </field>
+    </object>
+  </type>
   <type name="IncludedSuggestionSet">
     <p>
       A reference to an <tt>AvailableSuggestionSet</tt> noting
@@ -3737,11 +3869,15 @@
       <value>
         <code>AVAILABLE_SUGGESTION_SETS</code>
         <p>
-          The client will receive notifications once subscribed with completion suggestion sets from
-          the libraries of interest. The client should keep an up-to-date record of these in
+          The client will receive <tt>availableSuggestions</tt> notifications
+          once subscribed with completion suggestion sets from the libraries of
+          interest. The client should keep an up-to-date record of these in
           memory so that it will be able to union these candidates with other
           completion suggestions when applicable at completion time.
         </p>
+        <p>
+          The client will also receive <tt>existingImports</tt> notifications.
+        </p>
       </value>
     </enum>
   </type>
@@ -4212,10 +4348,10 @@
       <field name="containingLibraryName" optional="true">
         <ref>String</ref>
         <p>
-          The name of the library in which the referenced element is
-          declared. This data is omitted if there is no referenced
-          element, or if the element is declared inside an HTML
-          file.
+          The URI of the containing library, examples here include
+          "dart:core", "package:.." and file uris represented by the
+          path on disk, "/..". The data is omitted if the element is
+          declared inside an HTML file.
         </p>
       </field>
       <field name="containingClassDescription" optional="true">
diff --git a/pkg/analysis_server_client/lib/handler/notification_handler.dart b/pkg/analysis_server_client/lib/handler/notification_handler.dart
index 97ec840..b85aa31 100644
--- a/pkg/analysis_server_client/lib/handler/notification_handler.dart
+++ b/pkg/analysis_server_client/lib/handler/notification_handler.dart
@@ -72,6 +72,11 @@
             new CompletionAvailableSuggestionsParams.fromJson(
                 decoder, 'params', params));
         break;
+      case COMPLETION_NOTIFICATION_EXISTING_IMPORTS:
+        onCompletionExistingImports(
+            new CompletionExistingImportsParams.fromJson(
+                decoder, 'params', params));
+        break;
       case COMPLETION_NOTIFICATION_RESULTS:
         onCompletionResults(
             new CompletionResultsParams.fromJson(decoder, 'params', params));
@@ -221,6 +226,11 @@
   void onCompletionAvailableSuggestions(
       CompletionAvailableSuggestionsParams params) {}
 
+  /// Reports existing imports in a library. This notification may be sent
+  /// multiple times for a library. When a notification is processed, clients
+  /// should replace any previous information for the library.
+  void onCompletionExistingImports(CompletionExistingImportsParams params) {}
+
   /// Reports the completion suggestions that should be presented
   /// to the user. The set of suggestions included in the
   /// notification is always a complete list that supersedes any
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index 35174b9..2d93ddb 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.26.0';
+const String PROTOCOL_VERSION = '1.27.1';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -116,6 +116,10 @@
     'changedLibraries';
 const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_REMOVED_LIBRARIES =
     'removedLibraries';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS =
+    'completion.existingImports';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_FILE = 'file';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_IMPORTS = 'imports';
 const String COMPLETION_NOTIFICATION_RESULTS = 'completion.results';
 const String COMPLETION_NOTIFICATION_RESULTS_ID = 'id';
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_ELEMENT_KINDS =
@@ -126,6 +130,7 @@
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_SETS =
     'includedSuggestionSets';
 const String COMPLETION_NOTIFICATION_RESULTS_IS_LAST = 'isLast';
+const String COMPLETION_NOTIFICATION_RESULTS_LIBRARY_FILE = 'libraryFile';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_LENGTH =
     'replacementLength';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_OFFSET =
@@ -213,6 +218,7 @@
 const String EDIT_REQUEST_ORGANIZE_DIRECTIVES_FILE = 'file';
 const String EDIT_REQUEST_SORT_MEMBERS = 'edit.sortMembers';
 const String EDIT_REQUEST_SORT_MEMBERS_FILE = 'file';
+const String EDIT_RESPONSE_DARTFIX_DETAILS = 'details';
 const String EDIT_RESPONSE_DARTFIX_EDITS = 'edits';
 const String EDIT_RESPONSE_DARTFIX_HAS_ERRORS = 'hasErrors';
 const String EDIT_RESPONSE_DARTFIX_OTHER_SUGGESTIONS = 'otherSuggestions';
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index 5d1b076..23f7303 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -5075,6 +5075,7 @@
  *
  * {
  *   "label": String
+ *   "declaringLibraryUri": String
  *   "element": Element
  *   "defaultArgumentListString": optional String
  *   "defaultArgumentListTextRanges": optional List<int>
@@ -5091,6 +5092,8 @@
 class AvailableSuggestion implements HasToJson {
   String _label;
 
+  String _declaringLibraryUri;
+
   Element _element;
 
   String _defaultArgumentListString;
@@ -5123,6 +5126,21 @@
   }
 
   /**
+   * The URI of the library that declares the element being suggested, not the
+   * URI of the library associated with the enclosing AvailableSuggestionSet.
+   */
+  String get declaringLibraryUri => _declaringLibraryUri;
+
+  /**
+   * The URI of the library that declares the element being suggested, not the
+   * URI of the library associated with the enclosing AvailableSuggestionSet.
+   */
+  void set declaringLibraryUri(String value) {
+    assert(value != null);
+    this._declaringLibraryUri = value;
+  }
+
+  /**
    * Information about the element reference being suggested.
    */
   Element get element => _element;
@@ -5255,7 +5273,7 @@
     this._requiredParameterCount = value;
   }
 
-  AvailableSuggestion(String label, Element element,
+  AvailableSuggestion(String label, String declaringLibraryUri, Element element,
       {String defaultArgumentListString,
       List<int> defaultArgumentListTextRanges,
       String docComplete,
@@ -5265,6 +5283,7 @@
       List<String> relevanceTags,
       int requiredParameterCount}) {
     this.label = label;
+    this.declaringLibraryUri = declaringLibraryUri;
     this.element = element;
     this.defaultArgumentListString = defaultArgumentListString;
     this.defaultArgumentListTextRanges = defaultArgumentListTextRanges;
@@ -5288,6 +5307,13 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "label");
       }
+      String declaringLibraryUri;
+      if (json.containsKey("declaringLibraryUri")) {
+        declaringLibraryUri = jsonDecoder.decodeString(
+            jsonPath + ".declaringLibraryUri", json["declaringLibraryUri"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "declaringLibraryUri");
+      }
       Element element;
       if (json.containsKey("element")) {
         element = new Element.fromJson(
@@ -5339,7 +5365,7 @@
             jsonPath + ".requiredParameterCount",
             json["requiredParameterCount"]);
       }
-      return new AvailableSuggestion(label, element,
+      return new AvailableSuggestion(label, declaringLibraryUri, element,
           defaultArgumentListString: defaultArgumentListString,
           defaultArgumentListTextRanges: defaultArgumentListTextRanges,
           docComplete: docComplete,
@@ -5357,6 +5383,7 @@
   Map<String, dynamic> toJson() {
     Map<String, dynamic> result = {};
     result["label"] = label;
+    result["declaringLibraryUri"] = declaringLibraryUri;
     result["element"] = element.toJson();
     if (defaultArgumentListString != null) {
       result["defaultArgumentListString"] = defaultArgumentListString;
@@ -5392,6 +5419,7 @@
   bool operator ==(other) {
     if (other is AvailableSuggestion) {
       return label == other.label &&
+          declaringLibraryUri == other.declaringLibraryUri &&
           element == other.element &&
           defaultArgumentListString == other.defaultArgumentListString &&
           listEqual(defaultArgumentListTextRanges,
@@ -5413,6 +5441,7 @@
   int get hashCode {
     int hash = 0;
     hash = JenkinsSmiHash.combine(hash, label.hashCode);
+    hash = JenkinsSmiHash.combine(hash, declaringLibraryUri.hashCode);
     hash = JenkinsSmiHash.combine(hash, element.hashCode);
     hash = JenkinsSmiHash.combine(hash, defaultArgumentListString.hashCode);
     hash = JenkinsSmiHash.combine(hash, defaultArgumentListTextRanges.hashCode);
@@ -5803,6 +5832,116 @@
 }
 
 /**
+ * completion.existingImports params
+ *
+ * {
+ *   "file": FilePath
+ *   "imports": ExistingImports
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionExistingImportsParams implements HasToJson {
+  String _file;
+
+  ExistingImports _imports;
+
+  /**
+   * The defining file of the library.
+   */
+  String get file => _file;
+
+  /**
+   * The defining file of the library.
+   */
+  void set file(String value) {
+    assert(value != null);
+    this._file = value;
+  }
+
+  /**
+   * The existing imports in the library.
+   */
+  ExistingImports get imports => _imports;
+
+  /**
+   * The existing imports in the library.
+   */
+  void set imports(ExistingImports value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  CompletionExistingImportsParams(String file, ExistingImports imports) {
+    this.file = file;
+    this.imports = imports;
+  }
+
+  factory CompletionExistingImportsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String file;
+      if (json.containsKey("file")) {
+        file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "file");
+      }
+      ExistingImports imports;
+      if (json.containsKey("imports")) {
+        imports = new ExistingImports.fromJson(
+            jsonDecoder, jsonPath + ".imports", json["imports"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new CompletionExistingImportsParams(file, imports);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.existingImports params", json);
+    }
+  }
+
+  factory CompletionExistingImportsParams.fromNotification(
+      Notification notification) {
+    return new CompletionExistingImportsParams.fromJson(
+        new ResponseDecoder(null), "params", notification.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["file"] = file;
+    result["imports"] = imports.toJson();
+    return result;
+  }
+
+  Notification toNotification() {
+    return new Notification("completion.existingImports", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionExistingImportsParams) {
+      return file == other.file && imports == other.imports;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, file.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * completion.getSuggestionDetails params
  *
  * {
@@ -6593,6 +6732,7 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "libraryFile": optional FilePath
  *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
  *   "includedElementKinds": optional List<ElementKind>
  *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -6611,6 +6751,8 @@
 
   bool _isLast;
 
+  String _libraryFile;
+
   List<IncludedSuggestionSet> _includedSuggestionSets;
 
   List<ElementKind> _includedElementKinds;
@@ -6703,6 +6845,26 @@
   }
 
   /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  String get libraryFile => _libraryFile;
+
+  /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  void set libraryFile(String value) {
+    this._libraryFile = value;
+  }
+
+  /**
    * References to AvailableSuggestionSet objects previously sent to the
    * client. The client can include applicable names from the referenced
    * library in code completion suggestions.
@@ -6765,7 +6927,8 @@
 
   CompletionResultsParams(String id, int replacementOffset,
       int replacementLength, List<CompletionSuggestion> results, bool isLast,
-      {List<IncludedSuggestionSet> includedSuggestionSets,
+      {String libraryFile,
+      List<IncludedSuggestionSet> includedSuggestionSets,
       List<ElementKind> includedElementKinds,
       List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags}) {
     this.id = id;
@@ -6773,6 +6936,7 @@
     this.replacementLength = replacementLength;
     this.results = results;
     this.isLast = isLast;
+    this.libraryFile = libraryFile;
     this.includedSuggestionSets = includedSuggestionSets;
     this.includedElementKinds = includedElementKinds;
     this.includedSuggestionRelevanceTags = includedSuggestionRelevanceTags;
@@ -6820,6 +6984,11 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "isLast");
       }
+      String libraryFile;
+      if (json.containsKey("libraryFile")) {
+        libraryFile = jsonDecoder.decodeString(
+            jsonPath + ".libraryFile", json["libraryFile"]);
+      }
       List<IncludedSuggestionSet> includedSuggestionSets;
       if (json.containsKey("includedSuggestionSets")) {
         includedSuggestionSets = jsonDecoder.decodeList(
@@ -6848,6 +7017,7 @@
       }
       return new CompletionResultsParams(
           id, replacementOffset, replacementLength, results, isLast,
+          libraryFile: libraryFile,
           includedSuggestionSets: includedSuggestionSets,
           includedElementKinds: includedElementKinds,
           includedSuggestionRelevanceTags: includedSuggestionRelevanceTags);
@@ -6870,6 +7040,9 @@
     result["results"] =
         results.map((CompletionSuggestion value) => value.toJson()).toList();
     result["isLast"] = isLast;
+    if (libraryFile != null) {
+      result["libraryFile"] = libraryFile;
+    }
     if (includedSuggestionSets != null) {
       result["includedSuggestionSets"] = includedSuggestionSets
           .map((IncludedSuggestionSet value) => value.toJson())
@@ -6905,6 +7078,7 @@
           listEqual(results, other.results,
               (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
           isLast == other.isLast &&
+          libraryFile == other.libraryFile &&
           listEqual(includedSuggestionSets, other.includedSuggestionSets,
               (IncludedSuggestionSet a, IncludedSuggestionSet b) => a == b) &&
           listEqual(includedElementKinds, other.includedElementKinds,
@@ -6927,6 +7101,7 @@
     hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
     hash = JenkinsSmiHash.combine(hash, results.hashCode);
     hash = JenkinsSmiHash.combine(hash, isLast.hashCode);
+    hash = JenkinsSmiHash.combine(hash, libraryFile.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedSuggestionSets.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedElementKinds.hashCode);
     hash =
@@ -6946,11 +7121,13 @@
  */
 class CompletionService implements Enum {
   /**
-   * The client will receive notifications once subscribed with completion
-   * suggestion sets from the libraries of interest. The client should keep an
-   * up-to-date record of these in memory so that it will be able to union
-   * these candidates with other completion suggestions when applicable at
-   * completion time.
+   * The client will receive availableSuggestions notifications once subscribed
+   * with completion suggestion sets from the libraries of interest. The client
+   * should keep an up-to-date record of these in memory so that it will be
+   * able to union these candidates with other completion suggestions when
+   * applicable at completion time.
+   *
+   * The client will also receive existingImports notifications.
    */
   static const CompletionService AVAILABLE_SUGGESTION_SETS =
       const CompletionService._("AVAILABLE_SUGGESTION_SETS");
@@ -8045,6 +8222,7 @@
  *   "otherSuggestions": List<DartFixSuggestion>
  *   "hasErrors": bool
  *   "edits": List<SourceFileEdit>
+ *   "details": optional List<String>
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -8058,6 +8236,8 @@
 
   List<SourceFileEdit> _edits;
 
+  List<String> _details;
+
   /**
    * A list of recommended changes that can be automatically made by applying
    * the 'edits' included in this response.
@@ -8114,15 +8294,37 @@
     this._edits = value;
   }
 
+  /**
+   * Messages that should be displayed to the user that describe details of the
+   * fix generation. For example, the messages might (a) point out details that
+   * users might want to explore before committing the changes or (b) describe
+   * exceptions that were thrown but that did not stop the fixes from being
+   * produced. The list will be omitted if it is empty.
+   */
+  List<String> get details => _details;
+
+  /**
+   * Messages that should be displayed to the user that describe details of the
+   * fix generation. For example, the messages might (a) point out details that
+   * users might want to explore before committing the changes or (b) describe
+   * exceptions that were thrown but that did not stop the fixes from being
+   * produced. The list will be omitted if it is empty.
+   */
+  void set details(List<String> value) {
+    this._details = value;
+  }
+
   EditDartfixResult(
       List<DartFixSuggestion> suggestions,
       List<DartFixSuggestion> otherSuggestions,
       bool hasErrors,
-      List<SourceFileEdit> edits) {
+      List<SourceFileEdit> edits,
+      {List<String> details}) {
     this.suggestions = suggestions;
     this.otherSuggestions = otherSuggestions;
     this.hasErrors = hasErrors;
     this.edits = edits;
+    this.details = details;
   }
 
   factory EditDartfixResult.fromJson(
@@ -8168,8 +8370,14 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "edits");
       }
+      List<String> details;
+      if (json.containsKey("details")) {
+        details = jsonDecoder.decodeList(
+            jsonPath + ".details", json["details"], jsonDecoder.decodeString);
+      }
       return new EditDartfixResult(
-          suggestions, otherSuggestions, hasErrors, edits);
+          suggestions, otherSuggestions, hasErrors, edits,
+          details: details);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "edit.dartfix result", json);
     }
@@ -8193,6 +8401,9 @@
     result["hasErrors"] = hasErrors;
     result["edits"] =
         edits.map((SourceFileEdit value) => value.toJson()).toList();
+    if (details != null) {
+      result["details"] = details;
+    }
     return result;
   }
 
@@ -8213,7 +8424,8 @@
               (DartFixSuggestion a, DartFixSuggestion b) => a == b) &&
           hasErrors == other.hasErrors &&
           listEqual(edits, other.edits,
-              (SourceFileEdit a, SourceFileEdit b) => a == b);
+              (SourceFileEdit a, SourceFileEdit b) => a == b) &&
+          listEqual(details, other.details, (String a, String b) => a == b);
     }
     return false;
   }
@@ -8225,6 +8437,7 @@
     hash = JenkinsSmiHash.combine(hash, otherSuggestions.hashCode);
     hash = JenkinsSmiHash.combine(hash, hasErrors.hashCode);
     hash = JenkinsSmiHash.combine(hash, edits.hashCode);
+    hash = JenkinsSmiHash.combine(hash, details.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
@@ -13011,6 +13224,214 @@
 }
 
 /**
+ * ExistingImport
+ *
+ * {
+ *   "uri": int
+ *   "elements": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImport implements HasToJson {
+  int _uri;
+
+  List<int> _elements;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  int get uri => _uri;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  void set uri(int value) {
+    assert(value != null);
+    this._uri = value;
+  }
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  List<int> get elements => _elements;
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  void set elements(List<int> value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  ExistingImport(int uri, List<int> elements) {
+    this.uri = uri;
+    this.elements = elements;
+  }
+
+  factory ExistingImport.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      int uri;
+      if (json.containsKey("uri")) {
+        uri = jsonDecoder.decodeInt(jsonPath + ".uri", json["uri"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uri");
+      }
+      List<int> elements;
+      if (json.containsKey("elements")) {
+        elements = jsonDecoder.decodeList(
+            jsonPath + ".elements", json["elements"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      return new ExistingImport(uri, elements);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImport", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["uri"] = uri;
+    result["elements"] = elements;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImport) {
+      return uri == other.uri &&
+          listEqual(elements, other.elements, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * ExistingImports
+ *
+ * {
+ *   "elements": ImportedElementSet
+ *   "imports": List<ExistingImport>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImports implements HasToJson {
+  ImportedElementSet _elements;
+
+  List<ExistingImport> _imports;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  ImportedElementSet get elements => _elements;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  void set elements(ImportedElementSet value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  /**
+   * The list of imports in the library.
+   */
+  List<ExistingImport> get imports => _imports;
+
+  /**
+   * The list of imports in the library.
+   */
+  void set imports(List<ExistingImport> value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+    this.elements = elements;
+    this.imports = imports;
+  }
+
+  factory ExistingImports.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      ImportedElementSet elements;
+      if (json.containsKey("elements")) {
+        elements = new ImportedElementSet.fromJson(
+            jsonDecoder, jsonPath + ".elements", json["elements"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      List<ExistingImport> imports;
+      if (json.containsKey("imports")) {
+        imports = jsonDecoder.decodeList(
+            jsonPath + ".imports",
+            json["imports"],
+            (String jsonPath, Object json) =>
+                new ExistingImport.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new ExistingImports(elements, imports);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImports", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["elements"] = elements.toJson();
+    result["imports"] =
+        imports.map((ExistingImport value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImports) {
+      return elements == other.elements &&
+          listEqual(imports, other.imports,
+              (ExistingImport a, ExistingImport b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * extractLocalVariable feedback
  *
  * {
@@ -15586,16 +16007,16 @@
   }
 
   /**
-   * The name of the library in which the referenced element is declared. This
-   * data is omitted if there is no referenced element, or if the element is
-   * declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core",
+   * "package:.." and file uris represented by the path on disk, "/..". The
+   * data is omitted if the element is declared inside an HTML file.
    */
   String get containingLibraryName => _containingLibraryName;
 
   /**
-   * The name of the library in which the referenced element is declared. This
-   * data is omitted if there is no referenced element, or if the element is
-   * declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core",
+   * "package:.." and file uris represented by the path on disk, "/..". The
+   * data is omitted if the element is declared inside an HTML file.
    */
   void set containingLibraryName(String value) {
     this._containingLibraryName = value;
@@ -16109,6 +16530,135 @@
 }
 
 /**
+ * ImportedElementSet
+ *
+ * {
+ *   "strings": List<String>
+ *   "uris": List<int>
+ *   "names": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ImportedElementSet implements HasToJson {
+  List<String> _strings;
+
+  List<int> _uris;
+
+  List<int> _names;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  List<String> get strings => _strings;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  void set strings(List<String> value) {
+    assert(value != null);
+    this._strings = value;
+  }
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  List<int> get uris => _uris;
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  void set uris(List<int> value) {
+    assert(value != null);
+    this._uris = value;
+  }
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  List<int> get names => _names;
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  void set names(List<int> value) {
+    assert(value != null);
+    this._names = value;
+  }
+
+  ImportedElementSet(List<String> strings, List<int> uris, List<int> names) {
+    this.strings = strings;
+    this.uris = uris;
+    this.names = names;
+  }
+
+  factory ImportedElementSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<String> strings;
+      if (json.containsKey("strings")) {
+        strings = jsonDecoder.decodeList(
+            jsonPath + ".strings", json["strings"], jsonDecoder.decodeString);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "strings");
+      }
+      List<int> uris;
+      if (json.containsKey("uris")) {
+        uris = jsonDecoder.decodeList(
+            jsonPath + ".uris", json["uris"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uris");
+      }
+      List<int> names;
+      if (json.containsKey("names")) {
+        names = jsonDecoder.decodeList(
+            jsonPath + ".names", json["names"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "names");
+      }
+      return new ImportedElementSet(strings, uris, names);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ImportedElementSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["strings"] = strings;
+    result["uris"] = uris;
+    result["names"] = names;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ImportedElementSet) {
+      return listEqual(
+              strings, other.strings, (String a, String b) => a == b) &&
+          listEqual(uris, other.uris, (int a, int b) => a == b) &&
+          listEqual(names, other.names, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, strings.hashCode);
+    hash = JenkinsSmiHash.combine(hash, uris.hashCode);
+    hash = JenkinsSmiHash.combine(hash, names.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * ImportedElements
  *
  * {
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index e30b6cf..37ac0ad 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,43 @@
+## 0.36.4-dev (not yet published)
+* Deprecated the `isNonNullableUnit` parameter of the `TypeResolverVisitor`
+  constructor.  TypeResolverVisitor should now be configured using the
+  `featureSet` parameter.
+* Refined the return type of the getter `TypeParameter.declaredElement`.  It is
+  always guaranteed to return a `TypeParameterElement`.
+* Deprecated the `abstract` setter in `ClassElementImpl`, `EnumElementImpl`,
+  `MethodElementImpl`, and `PropertyAccessorElementImpl`.  `isAbstract` should
+  be used instead.
+* Changed the way function types are displayed from e.g. `(int) -> void` to
+  `void Function(int)`. This is more consistent with the syntax of Dart, and it
+  will avoid ambiguities when nullability is added to the type system. This
+  impacts to value returned by `FunctionType.displayName` and
+  `FunctionType.toString` and `ExecutableElement.toString`. Client code might be
+  broken if it depends on the content of the returned value.
+
+## 0.36.3
+* Deprecated `AstFactory.compilationUnit`.  In a future analyzer release, this
+  method will be changed so that all its parameters are named parameters.
+  Clients wishing to prepare for this should switch to using
+  `AstFactory.compilationUnit2`.
+* Deprecated Parser setters `enableControlFlowCollections`, `enableNonNullable`,
+  `enableSpreadCollections`, and `enableTripleShift`, as well as the
+  recently-introduced method `configureFeatures`.  Parsers should now be
+  configured by passing a FeatureSet object to the Parser constructor.
+* Deprecated `AnalysisError.isStaticOnly`.
+* Deprecated `AnalysisError.offset` setter.
+* Added method `LinterContext.canBeConstConstructor`.
+* Bug fixes: #36732, #36775.
+
+## 0.36.2
+* Bug fixes: #36724.
+
+## 0.36.1
+* Deprecated `DartType.isUndefined`, and now it always returns `false`.
+* The "UI as code" features (control_flow_collections and spread_collections)
+  are now enabled.
+* Bug fixes: #32918, #36262, #36380, #36439, #36492, #36529, #36576, #36667,
+  #36678, #36691.
+
 ## 0.36.0
 * Changed the return type of `Expression.precendence` to `Precedence`.  Clients
   that prepared for this change by switching to `Expression.precedence2` should
diff --git a/pkg/analyzer/doc/tutorial/analysis.md b/pkg/analyzer/doc/tutorial/analysis.md
index a44d6a5..e71d245 100644
--- a/pkg/analyzer/doc/tutorial/analysis.md
+++ b/pkg/analyzer/doc/tutorial/analysis.md
@@ -24,9 +24,14 @@
 main() {
   List<String> includedPaths = <String>[/* ... */];
   AnalysisContextCollection collection =
-      new AnalysisContextCollection(includedPaths);
+      new AnalysisContextCollection(includedPaths: includedPaths);
   analyzeSomeFiles(collection, includedPaths);
 }
+
+analyzeSomeFiles(
+    AnalysisContextCollection collection, List<String> includedPaths) {
+  // See below.
+}
 ```
 
 The collection will create one or more analysis contexts that can be used to
@@ -52,6 +57,10 @@
     analyzeSingleFile(context, path);
   }
 }
+
+analyzeSingleFile(AnalysisContext context, String path) {
+  // See below.
+}
 ```
 
 ## Analyzing Multiple Files
@@ -68,6 +77,10 @@
     }
   }
 }
+
+analyzeSingleFile(AnalysisContext context, String path) {
+  // See below.
+}
 ```
 
 The files returned this way will include _all_ of the files in all of the
diff --git a/pkg/analyzer/doc/tutorial/ast.md b/pkg/analyzer/doc/tutorial/ast.md
index fd41d31..57af577 100644
--- a/pkg/analyzer/doc/tutorial/ast.md
+++ b/pkg/analyzer/doc/tutorial/ast.md
@@ -50,21 +50,12 @@
 to get the compilation unit for a file at a known `path`, then you can ask the
 analysis session for an AST.
 
-If you need an unresolved AST, then you can use either a synchronous or
-asynchronous method to access the AST:
+If you need an unresolved AST, then you can use the following method to access
+the AST:
 
 ```dart
-main() async {
-  ParseResult result = await session.getParsedAst(path);
-  CompilationUnit unit = result.unit;
-}
-```
-
-or
-
-```dart
-main() {
-  ParseResult result = session.getParsedAstSync(path);
+processFile(AnalysisSession session, String path) {
+  ParsedUnitResult result = session.getParsedUnit(path);
   CompilationUnit unit = result.unit;
 }
 ```
@@ -73,8 +64,8 @@
 method to access it:
 
 ```dart
-main() async {
-  ResolveResult result = await session.getResolvedAst(path);
+processFile(AnalysisSession session, String path) async {
+  ResolvedUnitResult result = await session.getResolvedUnit(path);
   CompilationUnit unit = result.unit;
 }
 ```
diff --git a/pkg/analyzer/lib/analyzer.dart b/pkg/analyzer/lib/analyzer.dart
index 3806ad9..0e8a271 100644
--- a/pkg/analyzer/lib/analyzer.dart
+++ b/pkg/analyzer/lib/analyzer.dart
@@ -7,6 +7,7 @@
 
 import 'dart:io';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
@@ -40,9 +41,14 @@
 /// If [parseFunctionBodies] is [false] then only function signatures will be
 /// parsed.
 CompilationUnit parseCompilationUnit(String contents,
-    {String name, bool suppressErrors: false, bool parseFunctionBodies: true}) {
+    {String name,
+    bool suppressErrors: false,
+    bool parseFunctionBodies: true,
+    FeatureSet featureSet}) {
+  // TODO(paulberry): make featureSet a required parameter
+  featureSet ??= FeatureSet.fromEnableFlags([]);
   Source source = new StringSource(contents, name);
-  return _parseSource(contents, source,
+  return _parseSource(contents, source, featureSet,
       suppressErrors: suppressErrors, parseFunctionBodies: parseFunctionBodies);
 }
 
@@ -54,7 +60,11 @@
 /// If [parseFunctionBodies] is [false] then only function signatures will be
 /// parsed.
 CompilationUnit parseDartFile(String path,
-    {bool suppressErrors: false, bool parseFunctionBodies: true}) {
+    {bool suppressErrors: false,
+    bool parseFunctionBodies: true,
+    FeatureSet featureSet}) {
+  // TODO(paulberry): Make featureSet a required parameter
+  featureSet ??= FeatureSet.fromEnableFlags([]);
   String contents = new File(path).readAsStringSync();
   var sourceFactory = new SourceFactory(
       [new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)]);
@@ -68,7 +78,7 @@
     throw new ArgumentError("Source $source doesn't exist");
   }
 
-  return _parseSource(contents, source,
+  return _parseSource(contents, source, featureSet,
       suppressErrors: suppressErrors, parseFunctionBodies: parseFunctionBodies);
 }
 
@@ -83,13 +93,16 @@
 /// Throws an [AnalyzerErrorGroup] if any errors occurred, unless
 /// [suppressErrors] is `true`, in which case any errors are discarded.
 CompilationUnit parseDirectives(String contents,
-    {String name, bool suppressErrors: false}) {
+    {String name, bool suppressErrors: false, FeatureSet featureSet}) {
+  // TODO(paulberry): make featureSet a required parameter.
+  featureSet ??= FeatureSet.fromEnableFlags([]);
   var source = new StringSource(contents, name);
   var errorCollector = new _ErrorCollector();
   var reader = new CharSequenceReader(contents);
-  var scanner = new Scanner(source, reader, errorCollector);
+  var scanner = new Scanner(source, reader, errorCollector)
+    ..configureFeatures(featureSet);
   var token = scanner.tokenize();
-  var parser = new Parser(source, errorCollector);
+  var parser = new Parser(source, errorCollector, featureSet: featureSet);
   var unit = parser.parseDirectives(token);
   unit.lineInfo = new LineInfo(scanner.lineStarts);
 
@@ -103,13 +116,15 @@
   return literal.stringValue;
 }
 
-CompilationUnit _parseSource(String contents, Source source,
+CompilationUnit _parseSource(
+    String contents, Source source, FeatureSet featureSet,
     {bool suppressErrors: false, bool parseFunctionBodies: true}) {
   var reader = new CharSequenceReader(contents);
   var errorCollector = new _ErrorCollector();
-  var scanner = new Scanner(source, reader, errorCollector);
+  var scanner = new Scanner(source, reader, errorCollector)
+    ..configureFeatures(featureSet);
   var token = scanner.tokenize();
-  var parser = new Parser(source, errorCollector)
+  var parser = new Parser(source, errorCollector, featureSet: featureSet)
     ..parseFunctionBodies = parseFunctionBodies;
   var unit = parser.parseCompilationUnit(token)
     ..lineInfo = new LineInfo(scanner.lineStarts);
diff --git a/pkg/analyzer/lib/dart/analysis/features.dart b/pkg/analyzer/lib/dart/analysis/features.dart
new file mode 100644
index 0000000..575c7de
--- /dev/null
+++ b/pkg/analyzer/lib/dart/analysis/features.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2019, 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:analyzer/src/dart/analysis/experiments.dart';
+import 'package:meta/meta.dart';
+import 'package:pub_semver/pub_semver.dart';
+
+/// Information about a single language feature whose presence or absence
+/// depends on the supported Dart SDK version, and possibly on the presence of
+/// experimental flags.
+abstract class Feature {
+  /// Feature information for the 2018 constant update.
+  static const constant_update_2018 = ExperimentalFeatures.constant_update_2018;
+
+  /// Feature information for non-nullability by default.
+  static const non_nullable = ExperimentalFeatures.non_nullable;
+
+  /// Feature information for control flow collections.
+  static const control_flow_collections =
+      ExperimentalFeatures.control_flow_collections;
+
+  /// Feature information for extension methods.
+  static const extension_methods = ExperimentalFeatures.extension_methods;
+
+  /// Feature information for spread collections.
+  static const spread_collections = ExperimentalFeatures.spread_collections;
+
+  /// Feature information for set literals.
+  static const set_literals = ExperimentalFeatures.set_literals;
+
+  /// Feature information for the triple-shift operator.
+  static const triple_shift = ExperimentalFeatures.triple_shift;
+
+  /// If the feature may be enabled or disabled on the command line, the
+  /// experimental flag that may be used to enable it.  Otherwise `null`.
+  ///
+  /// Should be `null` if [status] is `current` or `abandoned`.
+  String get experimentalFlag;
+
+  /// If [status] is not `future`, the first version of the Dart SDK in which
+  /// the given feature was supported.  Otherwise `null`.
+  Version get firstSupportedVersion;
+
+  /// The status of the feature.
+  FeatureStatus get status;
+}
+
+/// An unordered collection of [Feature] objects.
+abstract class FeatureSet {
+  /// Computes a set of features for use in a unit test.  Computes the set of
+  /// features enabled in [sdkVersion], plus any specified [additionalFeatures].
+  ///
+  /// If [sdkVersion] is not supplied (or is `null`), then the current set of
+  /// enabled features is used as the starting point.
+  @visibleForTesting
+  factory FeatureSet.forTesting(
+          {String sdkVersion, List<Feature> additionalFeatures}) =
+      // ignore: invalid_use_of_visible_for_testing_member
+      ExperimentStatus.forTesting;
+
+  /// Computes the set of features implied by the given set of experimental
+  /// enable flags.
+  factory FeatureSet.fromEnableFlags(List<String> flags) =
+      ExperimentStatus.fromStrings;
+
+  /// Queries whether the given [feature] is contained in this feature set.
+  bool isEnabled(Feature feature);
+
+  /// Computes a subset of this FeatureSet by removing any features that weren't
+  /// available in the given Dart SDK version.
+  FeatureSet restrictToVersion(Version version);
+}
+
+/// Information about the status of a language feature.
+enum FeatureStatus {
+  /// The language feature has not yet shipped.  It may not be used unless an
+  /// experimental flag is used to enable it.
+  future,
+
+  /// The language feature has not yet shipped, but we are testing the effect of
+  /// enabling it by default.  It may be used in any library with an appopriate
+  /// version constraint, unless an experimental flag is used to disable it.
+  provisional,
+
+  /// The language feature has been shipped.  It may be used in any library with
+  /// an appropriate version constraint.
+  current,
+
+  /// The language feature is no longer planned.  It may not be used.
+  abandoned,
+}
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index 6f31a7b..542661b 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -11,7 +11,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 
@@ -122,11 +121,6 @@
   /// complete with [SourceKind.UNKNOWN].
   Future<SourceKind> getSourceKind(String path);
 
-  /// Return a future that will complete with a list of the top-level
-  /// declarations with the given [name] in all known libraries.
-  Future<List<TopLevelDeclarationInSource>> getTopLevelDeclarations(
-      String name);
-
   /// Return a future that will complete with information about the results of
   /// building the element model for the file with the given absolute,
   /// normalized[path].
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index bce36d6..14df41a 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/precedence.dart';
 
 /// Defines the AST model. The AST (Abstract Syntax Tree) model describes the
@@ -499,6 +500,8 @@
 
   R visitExtendsClause(ExtendsClause node);
 
+  R visitExtensionDeclaration(ExtensionDeclaration node);
+
   R visitFieldDeclaration(FieldDeclaration node);
 
   R visitFieldFormalParameter(FieldFormalParameter node);
@@ -1223,6 +1226,17 @@
   /// [token].
   void set endToken(Token token);
 
+  /// The set of features available to this compilation unit, or `null` if
+  /// unknown.
+  ///
+  /// Determined by some combination of the .packages file, the enclosing
+  /// package's SDK version constraint, and/or the presence of a `@dart`
+  /// directive in a comment at the top of the file.
+  ///
+  /// Might be `null` if, for example, this [CompilationUnit] has been
+  /// resynthesized from a summary,
+  FeatureSet get featureSet;
+
   /// Return the line information for this compilation unit.
   LineInfo get lineInfo;
 
@@ -2096,6 +2110,37 @@
   void set superclass(TypeName name);
 }
 
+/// The declaration of an extension of a type.
+///
+///    extension ::=
+///        'extension' [SimpleIdentifier] [TypeParameterList]?
+///        'on' [TypeAnnotation] '{' [ClassMember]* '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ExtensionDeclaration implements NamedCompilationUnitMember {
+  /// Return the type that is being extended.
+  TypeAnnotation get extendedType;
+
+  /// Return the token representing the 'extension' keyword.
+  Token get extensionKeyword;
+
+  /// Return the left curly bracket.
+  Token get leftBracket;
+
+  /// Return the members being added to the extended class.
+  NodeList<ClassMember> get members;
+
+  /// Return the token representing the 'on' keyword.
+  Token get onKeyword;
+
+  /// Return the right curly bracket.
+  Token get rightBracket;
+
+  /// Return the type parameters for the extension, or `null` if the extension
+  /// does not have any type parameters.
+  TypeParameterList get typeParameters;
+}
+
 /// The declaration of one or more fields of the same type.
 ///
 ///    fieldDeclaration ::=
@@ -2289,15 +2334,17 @@
   /// even though they are implicitly final.
   bool get isFinal;
 
-  /// Return `true` if this parameter is a named parameter. Named parameters are
-  /// always optional, even when they are annotated with the `@required`
-  /// annotation.
+  /// Return `true` if this parameter is a named parameter. Named parameters can
+  /// either be required or optional.
   bool get isNamed;
 
   /// Return `true` if this parameter is an optional parameter. Optional
   /// parameters can either be positional or named.
   bool get isOptional;
 
+  /// Return `true` if this parameter is both an optional and named parameter.
+  bool get isOptionalNamed;
+
   /// Return `true` if this parameter is both an optional and positional
   /// parameter.
   bool get isOptionalPositional;
@@ -2307,12 +2354,22 @@
   bool get isPositional;
 
   /// Return `true` if this parameter is a required parameter. Required
-  /// parameters are always positional.
+  /// parameters can either be positional or named.
   ///
   /// Note: this will return `false` for a named parameter that is annotated
   /// with the `@required` annotation.
   bool get isRequired;
 
+  /// Return `true` if this parameter is both a required and named parameter.
+  ///
+  /// Note: this will return `false` for a named parameter that is annotated
+  /// with the `@required` annotation.
+  bool get isRequiredNamed;
+
+  /// Return `true` if this parameter is both a required and positional
+  /// parameter.
+  bool get isRequiredPositional;
+
   /// Return the kind of this parameter.
   @deprecated
   ParameterKind get kind;
@@ -2637,7 +2694,8 @@
   /// Set the element associated with the function to the given [element].
   void set element(ExecutableElement element);
 
-  /// Return the parameters associated with the function.
+  /// Return the parameters associated with the function, or `null` if the
+  /// function is part of a top-level getter.
   FormalParameterList get parameters;
 
   /// Set the parameters associated with the function to the given list of
@@ -2753,7 +2811,8 @@
 /// A function-typed formal parameter.
 ///
 ///    functionSignature ::=
-///        [TypeAnnotation]? [SimpleIdentifier] [TypeParameterList]? [FormalParameterList]
+///        [TypeAnnotation]? [SimpleIdentifier] [TypeParameterList]?
+///        [FormalParameterList] '?'?
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class FunctionTypedFormalParameter implements NormalFormalParameter {
@@ -2764,6 +2823,11 @@
   /// [parameters].
   void set parameters(FormalParameterList parameters);
 
+  /// Return the question mark indicating that the function type is nullable, or
+  /// `null` if there is no question mark. Having a nullable function type means
+  /// that the parameter can be null.
+  Token get question;
+
   /// Return the return type of the function, or `null` if the function does not
   /// have a return type.
   TypeAnnotation get returnType;
@@ -3447,6 +3511,15 @@
   /// Return the type arguments to be applied to the method being invoked, or
   /// `null` if no type arguments were provided.
   TypeArgumentList get typeArguments;
+
+  /// Return the actual type arguments of the invocation, either explicitly
+  /// specified in [typeArguments], or inferred.
+  ///
+  /// If the AST has been resolved, never returns `null`, returns an empty list
+  /// if the [function] does not have type parameters.
+  ///
+  /// Return `null` if the AST structure has not been resolved.
+  List<DartType> get typeArgumentTypes;
 }
 
 /// An is expression.
@@ -5110,6 +5183,9 @@
   /// Set the upper bound for legal arguments to the given [type].
   void set bound(TypeAnnotation type);
 
+  @override
+  TypeParameterElement get declaredElement;
+
   /// Return the token representing the 'extends' keyword, or `null` if there is
   /// no explicit upper bound.
   Token get extendsKeyword;
@@ -5227,6 +5303,9 @@
   /// even though they are implicitly final.
   bool get isFinal;
 
+  /// Return `true` if this variable was declared with the 'late' modifier.
+  bool get isLate;
+
   /// Return the name of the variable being declared.
   SimpleIdentifier get name;
 
@@ -5240,10 +5319,10 @@
 ///        finalConstVarOrType [VariableDeclaration] (',' [VariableDeclaration])*
 ///
 ///    finalConstVarOrType ::=
-///      | 'final' [TypeAnnotation]?
+///      'final' 'late'? [TypeAnnotation]?
 ///      | 'const' [TypeAnnotation]?
 ///      | 'var'
-///      | [TypeAnnotation]
+///      | 'late'? [TypeAnnotation]
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class VariableDeclarationList implements AnnotatedNode {
@@ -5257,6 +5336,10 @@
   /// this is a syntactic check rather than a semantic check.)
   bool get isFinal;
 
+  /// Return `true` if the variables in this list were declared with the 'late'
+  /// modifier.
+  bool get isLate;
+
   /// Return the token representing the 'final', 'const' or 'var' keyword, or
   /// `null` if no keyword was included.
   Token get keyword;
@@ -5265,6 +5348,10 @@
   /// given [token].
   void set keyword(Token token);
 
+  /// Return the token representing the 'late' keyword, or `null` if the late
+  /// modifier was not included.
+  Token get lateKeyword;
+
   /// Return the type of the variables being declared, or `null` if no type was
   /// provided.
   TypeAnnotation get type;
diff --git a/pkg/analyzer/lib/dart/ast/ast_factory.dart b/pkg/analyzer/lib/dart/ast/ast_factory.dart
index f934c92..2796e1a 100644
--- a/pkg/analyzer/lib/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/dart/ast/ast_factory.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:front_end/src/scanner/token.dart';
@@ -155,12 +156,30 @@
   /// in the compilation unit. The list of [directives] can be `null` if there
   /// are no directives in the compilation unit. The list of [declarations] can
   /// be `null` if there are no declarations in the compilation unit.
+  @Deprecated('Use compilationUnit2')
   CompilationUnit compilationUnit(
       Token beginToken,
       ScriptTag scriptTag,
       List<Directive> directives,
       List<CompilationUnitMember> declarations,
-      Token endToken);
+      Token endToken,
+      [FeatureSet featureSet]);
+
+  /// Returns a newly created compilation unit to have the given directives and
+  /// declarations.  The [scriptTag] can be `null` (or omitted) if there is no
+  /// script tag in the compilation unit.  The list of [declarations] can be
+  /// `null` (or omitted) if there are no directives in the compilation unit.
+  /// The list of `declarations` can be `null` (or omitted) if there are no
+  /// declarations in the compilation unit.  The [featureSet] can be `null` if
+  /// the set of features for this compilation unit is not known (this
+  /// restricts what analysis can be done of the compilation unit).
+  CompilationUnit compilationUnit2(
+      {@required Token beginToken,
+      ScriptTag scriptTag,
+      List<Directive> directives,
+      List<CompilationUnitMember> declarations,
+      @required Token endToken,
+      @required FeatureSet featureSet});
 
   /// Returns a newly created conditional expression.
   ConditionalExpression conditionalExpression(
@@ -320,6 +339,20 @@
   /// Returns a newly created extends clause.
   ExtendsClause extendsClause(Token extendsKeyword, TypeName superclass);
 
+  /// Return a newly created extention declaration. The list of [typeParameters]
+  /// can be `null` if there are no type parameters.
+  ExtensionDeclaration extensionDeclaration(
+      {Comment comment,
+      List<Annotation> metadata,
+      Token extensionKeyword,
+      @required SimpleIdentifier name,
+      TypeParameterList typeParameters,
+      Token onKeyword,
+      @required TypeAnnotation extendedType,
+      Token leftBracket,
+      List<ClassMember> members,
+      Token rightBracket});
+
   /// Returns a newly created field declaration. Either or both of the [comment]
   /// and [metadata] can be `null` if the declaration does not have the
   /// corresponding attribute. The [staticKeyword] can be `null` if the field is
@@ -516,7 +549,8 @@
       TypeAnnotation returnType,
       @required SimpleIdentifier identifier,
       TypeParameterList typeParameters,
-      @required FormalParameterList parameters});
+      @required FormalParameterList parameters,
+      Token question});
 
   /// Initialize a newly created generic function type.
   GenericFunctionType genericFunctionType(
@@ -907,6 +941,8 @@
   /// [comment] and [metadata] can be `null` if the variable list does not have
   /// the corresponding attribute. The [keyword] can be `null` if a type was
   /// specified. The [type] must be `null` if the keyword is 'var'.
+  ///
+  /// Use [variableDeclarationList2] instead.
   VariableDeclarationList variableDeclarationList(
       Comment comment,
       List<Annotation> metadata,
@@ -914,6 +950,18 @@
       TypeAnnotation type,
       List<VariableDeclaration> variables);
 
+  /// Returns a newly created variable declaration list. Either or both of the
+  /// [comment] and [metadata] can be `null` if the variable list does not have
+  /// the corresponding attribute. The [keyword] can be `null` if a type was
+  /// specified. The [type] must be `null` if the keyword is 'var'.
+  VariableDeclarationList variableDeclarationList2(
+      {Comment comment,
+      List<Annotation> metadata,
+      Token lateKeyword,
+      Token keyword,
+      TypeAnnotation type,
+      List<VariableDeclaration> variables});
+
   /// Returns a newly created variable declaration statement.
   VariableDeclarationStatement variableDeclarationStatement(
       VariableDeclarationList variableList, Token semicolon);
diff --git a/pkg/analyzer/lib/dart/ast/resolution_map.dart b/pkg/analyzer/lib/dart/ast/resolution_map.dart
index 83a4820..a0cc7e4 100644
--- a/pkg/analyzer/lib/dart/ast/resolution_map.dart
+++ b/pkg/analyzer/lib/dart/ast/resolution_map.dart
@@ -10,6 +10,8 @@
 /// AST to elements and types in the element model.
 ///
 /// Clients should not extend, implement or mix-in this class.
+// TODO(brianwilkerson) This was added for unifying with the front_end, and is
+//  no longer needed. It should be removed.
 abstract class ResolutionMap {
   /// Return the best element available for the function being invoked at
   /// [node]. If resolution was able to find a better element based on type
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart
index 6646631..68f4621 100644
--- a/pkg/analyzer/lib/dart/ast/visitor.dart
+++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -277,6 +277,10 @@
   R visitExtendsClause(ExtendsClause node) => visitNode(node);
 
   @override
+  R visitExtensionDeclaration(ExtensionDeclaration node) =>
+      visitNamedCompilationUnitMember(node);
+
+  @override
   R visitFieldDeclaration(FieldDeclaration node) => visitClassMember(node);
 
   @override
@@ -839,6 +843,12 @@
   }
 
   @override
+  R visitExtensionDeclaration(ExtensionDeclaration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
   R visitFieldDeclaration(FieldDeclaration node) {
     node.visitChildren(this);
     return null;
@@ -1447,6 +1457,9 @@
   R visitExtendsClause(ExtendsClause node) => null;
 
   @override
+  R visitExtensionDeclaration(ExtensionDeclaration node) => null;
+
+  @override
   R visitFieldDeclaration(FieldDeclaration node) => null;
 
   @override
@@ -1822,6 +1835,9 @@
   R visitExtendsClause(ExtendsClause node) => _throw(node);
 
   @override
+  R visitExtensionDeclaration(ExtensionDeclaration node) => _throw(node);
+
+  @override
   R visitFieldDeclaration(FieldDeclaration node) => _throw(node);
 
   @override
@@ -2406,6 +2422,14 @@
   }
 
   @override
+  T visitExtensionDeclaration(ExtensionDeclaration node) {
+    stopwatch.start();
+    T result = _baseVisitor.visitExtensionDeclaration(node);
+    stopwatch.stop();
+    return result;
+  }
+
+  @override
   T visitFieldDeclaration(FieldDeclaration node) {
     stopwatch.start();
     T result = _baseVisitor.visitFieldDeclaration(node);
@@ -3181,6 +3205,9 @@
   R visitExtendsClause(ExtendsClause node) => visitNode(node);
 
   @override
+  R visitExtensionDeclaration(ExtensionDeclaration node) => visitNode(node);
+
+  @override
   R visitFieldDeclaration(FieldDeclaration node) => visitNode(node);
 
   @override
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 20b425d..ba10def 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -521,9 +521,12 @@
   /// Return `true` if this element has an annotation of the form `@JS(..)`.
   bool get hasJS;
 
-  /// Return `true` if this element has an annotation of the form '@literal'.
+  /// Return `true` if this element has an annotation of the form `@literal`.
   bool get hasLiteral;
 
+  /// Return  `true` if this element has an annotation of the form `@mustCallSuper`.
+  bool get hasMustCallSuper;
+
   /// Return `true` if this element has an annotation of the form
   /// `@optionalTypeArgs`.
   bool get hasOptionalTypeArgs;
@@ -534,10 +537,10 @@
   /// Return `true` if this element has an annotation of the form `@protected`.
   bool get hasProtected;
 
-  /// Return `true` if this element has an annotation of the form '@required'.
+  /// Return `true` if this element has an annotation of the form `@required`.
   bool get hasRequired;
 
-  /// Return `true` if this element has an annotation of the form '@sealed'.
+  /// Return `true` if this element has an annotation of the form `@sealed`.
   bool get hasSealed;
 
   /// Return `true` if this element has an annotation of the form
@@ -840,25 +843,27 @@
 
   static const ElementKind NAME = const ElementKind('NAME', 15, "<name>");
 
+  static const ElementKind NEVER = const ElementKind('NEVER', 16, "<never>");
+
   static const ElementKind PARAMETER =
-      const ElementKind('PARAMETER', 16, "parameter");
+      const ElementKind('PARAMETER', 17, "parameter");
 
   static const ElementKind PREFIX =
-      const ElementKind('PREFIX', 17, "import prefix");
+      const ElementKind('PREFIX', 18, "import prefix");
 
-  static const ElementKind SETTER = const ElementKind('SETTER', 18, "setter");
+  static const ElementKind SETTER = const ElementKind('SETTER', 19, "setter");
 
   static const ElementKind TOP_LEVEL_VARIABLE =
-      const ElementKind('TOP_LEVEL_VARIABLE', 19, "top level variable");
+      const ElementKind('TOP_LEVEL_VARIABLE', 20, "top level variable");
 
   static const ElementKind FUNCTION_TYPE_ALIAS =
-      const ElementKind('FUNCTION_TYPE_ALIAS', 20, "function type alias");
+      const ElementKind('FUNCTION_TYPE_ALIAS', 21, "function type alias");
 
   static const ElementKind TYPE_PARAMETER =
-      const ElementKind('TYPE_PARAMETER', 21, "type parameter");
+      const ElementKind('TYPE_PARAMETER', 22, "type parameter");
 
   static const ElementKind UNIVERSE =
-      const ElementKind('UNIVERSE', 22, "<universe>");
+      const ElementKind('UNIVERSE', 23, "<universe>");
 
   static const List<ElementKind> values = const [
     CLASS,
@@ -877,6 +882,7 @@
     LOCAL_VARIABLE,
     METHOD,
     NAME,
+    NEVER,
     PARAMETER,
     PREFIX,
     SETTER,
@@ -935,7 +941,7 @@
 ///
 /// Clients may not extend, implement or mix-in this class. There are classes
 /// that implement this interface that provide useful default behaviors in
-/// `package:analyzer/dart/ast/visitor.dart`. A couple of the most useful
+/// `package:analyzer/dart/element/visitor.dart`. A couple of the most useful
 /// include
 /// * SimpleElementVisitor which implements every visit method by doing nothing,
 /// * RecursiveElementVisitor which will cause every node in a structure to be
@@ -1051,13 +1057,6 @@
   /// Return `true` if this element is an enum constant.
   bool get isEnumConstant;
 
-  /// Return `true` if this field uses lazy evaluation semantics.
-  ///
-  /// This will always return `false` unless the experiment 'non-nullable' is
-  /// enabled.
-  @experimental
-  bool get isLazy;
-
   /// Returns `true` if this field can be overridden in strong mode.
   @deprecated
   bool get isVirtual;
@@ -1300,6 +1299,8 @@
   /// included using the `part` directive.
   List<CompilationUnitElement> get units;
 
+  bool get isNonNullableByDefault;
+
   /// Return a list containing all of the imports that share the given [prefix],
   /// or an empty array if there are no such imports.
   List<ImportElement> getImportsWithPrefix(PrefixElement prefix);
@@ -1333,12 +1334,12 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class LocalVariableElement implements LocalElement, VariableElement {
-  /// Return `true` if this local variable uses lazy evaluation semantics.
+  /// Return `true` if this local variable uses late evaluation semantics.
   ///
   /// This will always return `false` unless the experiment 'non-nullable' is
   /// enabled.
   @experimental
-  bool get isLazy;
+  bool get isLate;
 }
 
 /// An element that represents a method defined within a type.
@@ -1404,9 +1405,10 @@
   /// Return `true` if this parameter is an initializing formal parameter.
   bool get isInitializingFormal;
 
-  /// Return `true` if this parameter is a named parameter. Named parameters are
-  /// always optional, even when they are annotated with the `@required`
-  /// annotation.
+  /// Return `true` if this parameter is a named parameter. Named parameters
+  /// that are annotated with the `@required` annotation are considered
+  /// optional.  Named parameters that are annotated with the `required` syntax
+  /// are considered required.
   bool get isNamed;
 
   /// Return `true` if this parameter is a required parameter. Required
@@ -1420,9 +1422,18 @@
   bool get isNotOptional;
 
   /// Return `true` if this parameter is an optional parameter. Optional
-  /// parameters can either be positional or named.
+  /// parameters can either be positional or named.  Named parameters that are
+  /// annotated with the `@required` annotation are considered optional.  Named
+  /// parameters that are annotated with the `required` syntax are considered
+  /// required.
   bool get isOptional;
 
+  /// Return `true` if this parameter is both an optional and named parameter.
+  /// Named parameters that are annotated with the `@required` annotation are
+  /// considered optional.  Named parameters that are annotated with the
+  /// `required` syntax are considered required.
+  bool get isOptionalNamed;
+
   /// Return `true` if this parameter is both an optional and positional
   /// parameter.
   bool get isOptionalPositional;
@@ -1431,6 +1442,16 @@
   /// parameters can either be required or optional.
   bool get isPositional;
 
+  /// Return `true` if this parameter is both a required and named parameter.
+  /// Named parameters that are annotated with the `@required` annotation are
+  /// considered optional.  Named parameters that are annotated with the
+  /// `required` syntax are considered required.
+  bool get isRequiredNamed;
+
+  /// Return `true` if this parameter is both a required and positional
+  /// parameter.
+  bool get isRequiredPositional;
+
   /// Return the kind of this parameter.
   @deprecated
   ParameterKind get parameterKind;
@@ -1529,6 +1550,13 @@
   /// will be synthetic.
   PropertyAccessorElement get getter;
 
+  /// Return `true` if this variable uses late evaluation semantics.
+  ///
+  /// This will always return `false` unless the experiment 'non-nullable' is
+  /// enabled.
+  @experimental
+  bool get isLate;
+
   /// Return the propagated type of this variable, or `null` if type propagation
   /// has not been performed, for example because the variable is not final.
   @deprecated
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index 7c752c2..7c2812a 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -29,6 +29,9 @@
 abstract class DartType {
   /// Return the name of this type as it should appear when presented to users
   /// in contexts such as error messages.
+  ///
+  /// Clients should not depend on the content of the returned value as it will
+  /// be changed if doing so would improve the UX.
   String get displayName;
 
   /// Return the element representing the declaration of this type, or `null` if
@@ -80,6 +83,7 @@
 
   /// Return `true` if this type represents a typename that couldn't be
   /// resolved.
+  @deprecated
   bool get isUndefined;
 
   /// Return `true` if this type represents the type 'void'.
diff --git a/pkg/analyzer/lib/diagnostic/diagnostic.dart b/pkg/analyzer/lib/diagnostic/diagnostic.dart
new file mode 100644
index 0000000..43b099a
--- /dev/null
+++ b/pkg/analyzer/lib/diagnostic/diagnostic.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2019, 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.
+
+/// A diagnostic, as defined by the [Diagnostic Design Guidelines][guidelines]:
+///
+/// > An indication of a specific problem at a specific location within the
+/// > source code being processed by a development tool.
+///
+/// Clients may not extend, implement or mix-in this class.
+///
+/// [guidelines]: ../doc/diagnostics.md
+abstract class Diagnostic {
+  /// A list of messages that provide context for understanding the problem
+  /// being reported. The list will be empty if there are no such messages.
+  List<DiagnosticMessage> get contextMessages;
+
+  /// A description of how to fix the problem, or `null` if there is no such
+  /// description.
+  String get correctionMessage;
+
+  /// A message describing what is wrong and why.
+  DiagnosticMessage get problemMessage;
+
+  /// The severity associated with the diagnostic.
+  Severity get severity;
+}
+
+/// A single message associated with a [Diagnostic], consisting of the text of
+/// the message and the location associated with it.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class DiagnosticMessage {
+  /// The absolute and normalized path of the file associated with this message.
+  String get filePath;
+
+  /// The length of the source range associated with this message.
+  int get length;
+
+  /// The text of the message.
+  String get message;
+
+  /// The zero-based offset from the start of the file to the beginning of the
+  /// source range associated with this message.
+  int get offset;
+}
+
+/// An indication of the severity of a [Diagnostic].
+enum Severity { error, warning, info }
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 0e565ab..ed09816 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -4,8 +4,10 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart' show ScannerErrorCode;
+import 'package:analyzer/src/diagnostic/diagnostic.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
@@ -115,9 +117,11 @@
   CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS,
   CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR,
   CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT,
+  CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR_MISMATCH,
   CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER,
   CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS,
   CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR,
+  CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER,
   CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT,
   CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME,
   CompileTimeErrorCode.DUPLICATE_DEFINITION,
@@ -172,6 +176,7 @@
   CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR,
   CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
   CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE,
+  CompileTimeErrorCode.INVALID_OPTIONAL_PARAMETER_TYPE,
   CompileTimeErrorCode.INVALID_OVERRIDE,
   CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS,
   CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST,
@@ -187,6 +192,8 @@
   CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL,
   CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL,
   CompileTimeErrorCode.MISSING_DART_LIBRARY,
+  CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER,
+  CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT,
   CompileTimeErrorCode.MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE,
   CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
   CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
@@ -283,6 +290,7 @@
   CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR,
   CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS,
   CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
+  CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
   CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR,
   CompileTimeErrorCode.YIELD_IN_NON_GENERATOR,
   HintCode.CAN_BE_NULL_AFTER_NULL_AWARE,
@@ -343,9 +351,12 @@
   HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT,
   HintCode.SDK_VERSION_GT_GT_GT_OPERATOR,
   HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT,
+  HintCode.SDK_VERSION_NEVER,
   HintCode.SDK_VERSION_SET_LITERAL,
   HintCode.SDK_VERSION_UI_AS_CODE,
   HintCode.STRICT_RAW_TYPE,
+  HintCode.STRICT_RAW_TYPE_IN_AS,
+  HintCode.STRICT_RAW_TYPE_IN_IS,
   HintCode.SUBTYPE_OF_SEALED_CLASS,
   HintCode.TYPE_CHECK_IS_NOT_NULL,
   HintCode.TYPE_CHECK_IS_NULL,
@@ -383,6 +394,7 @@
   ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS,
   ParserErrorCode.CLASS_IN_CLASS,
   ParserErrorCode.COLON_IN_PLACE_OF_IN,
+  ParserErrorCode.CONFLICTING_MODIFIERS,
   ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE,
   ParserErrorCode.CONST_AFTER_FACTORY,
   ParserErrorCode.CONST_AND_COVARIANT,
@@ -412,6 +424,7 @@
   ParserErrorCode.EMPTY_ENUM_BODY,
   ParserErrorCode.ENUM_IN_CLASS,
   ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
+  ParserErrorCode.EXPECTED_BODY,
   ParserErrorCode.EXPECTED_CASE_OR_DEFAULT,
   ParserErrorCode.EXPECTED_CLASS_MEMBER,
   ParserErrorCode.EXPECTED_ELSE_OR_COMMA,
@@ -743,7 +756,7 @@
  *
  * See [AnalysisErrorListener].
  */
-class AnalysisError {
+class AnalysisError implements Diagnostic {
   /**
    * An empty array of errors used when no errors are expected.
    */
@@ -781,10 +794,9 @@
    */
   final ErrorCode errorCode;
 
-  /**
-   * The localized error message.
-   */
-  String _message;
+  DiagnosticMessage _problemMessage;
+
+  List<DiagnosticMessage> _contextMessages;
 
   /**
    * The correction to be displayed for this error, or `null` if there is no
@@ -798,43 +810,40 @@
   final Source source;
 
   /**
-   * The character offset from the beginning of the source (zero based) where
-   * the error occurred.
-   */
-  int offset = 0;
-
-  /**
-   * The number of characters from the offset to the end of the source which
-   * encompasses the compilation error.
-   */
-  int length = 0;
-
-  /**
-   * A flag indicating whether this error can be shown to be a non-issue because
-   * of the result of type propagation.
-   */
-  bool isStaticOnly = false;
-
-  /**
    * Initialize a newly created analysis error. The error is associated with the
    * given [source] and is located at the given [offset] with the given
    * [length]. The error will have the given [errorCode] and the list of
-   * [arguments] will be used to complete the message.
+   * [arguments] will be used to complete the message and correction. If any
+   * [contextMessages] are provided, they will be recorded with the error.
    */
-  AnalysisError(this.source, this.offset, this.length, this.errorCode,
-      [List<Object> arguments]) {
-    this._message = formatList(errorCode.message, arguments);
+  AnalysisError(this.source, int offset, int length, this.errorCode,
+      [List<Object> arguments, List<DiagnosticMessage> contextMessages]) {
+    String message = formatList(errorCode.message, arguments);
     String correctionTemplate = errorCode.correction;
     if (correctionTemplate != null) {
       this._correction = formatList(correctionTemplate, arguments);
     }
+    _problemMessage = new DiagnosticMessageImpl(
+        filePath: source?.fullName,
+        length: length,
+        message: message,
+        offset: offset);
+    _contextMessages = contextMessages;
   }
 
   /**
    * Initialize a newly created analysis error with given values.
    */
-  AnalysisError.forValues(this.source, this.offset, this.length, this.errorCode,
-      this._message, this._correction);
+  AnalysisError.forValues(this.source, int offset, int length, this.errorCode,
+      String message, this._correction) {
+    _problemMessage = new DiagnosticMessageImpl(
+        filePath: source?.fullName,
+        length: length,
+        message: message,
+        offset: offset);
+  }
+
+  List<DiagnosticMessage> get contextMessages => _contextMessages ?? const [];
 
   /**
    * Return the template used to create the correction to be displayed for this
@@ -844,18 +853,70 @@
   String get correction => _correction;
 
   @override
+  String get correctionMessage => _correction;
+
+  @override
   int get hashCode {
     int hashCode = offset;
-    hashCode ^= (_message != null) ? _message.hashCode : 0;
+    hashCode ^= (message != null) ? message.hashCode : 0;
     hashCode ^= (source != null) ? source.hashCode : 0;
     return hashCode;
   }
 
   /**
+   * Return `true` if this error can be shown to be a non-issue because of the
+   * result of type propagation.
+   */
+  @Deprecated(
+      'Type propagation is no longer performed, so this will never be true')
+  bool get isStaticOnly => false;
+
+  @Deprecated(
+      'Type propagation is no longer performed, so this can never be true')
+  void set isStaticOnly(bool value) {}
+
+  /**
+   * The number of characters from the offset to the end of the source which
+   * encompasses the compilation error.
+   */
+  int get length => _problemMessage.length;
+
+  /**
    * Return the message to be displayed for this error. The message should
    * indicate what is wrong and why it is wrong.
    */
-  String get message => _message;
+  String get message => _problemMessage.message;
+
+  /**
+   * The character offset from the beginning of the source (zero based) where
+   * the error occurred.
+   */
+  int get offset => _problemMessage.offset;
+
+  /**
+   * The character offset from the beginning of the source (zero based) where
+   * the error occurred.
+   */
+  @Deprecated('Set the offset when the error is created')
+  set offset(int offset) {}
+
+  @override
+  DiagnosticMessage get problemMessage => _problemMessage;
+
+  @override
+  Severity get severity {
+    switch (errorCode.errorSeverity) {
+      case ErrorSeverity.ERROR:
+        return Severity.error;
+      case ErrorSeverity.WARNING:
+        return Severity.warning;
+      case ErrorSeverity.INFO:
+        return Severity.info;
+      default:
+        throw new StateError(
+            'Invalid error severity: ${errorCode.errorSeverity}');
+    }
+  }
 
   @override
   bool operator ==(Object other) {
@@ -871,11 +932,8 @@
       if (offset != other.offset || length != other.length) {
         return false;
       }
-      if (isStaticOnly != other.isStaticOnly) {
-        return false;
-      }
       // Deep checks.
-      if (_message != other._message) {
+      if (message != other.message) {
         return false;
       }
       if (source != other.source) {
@@ -897,7 +955,7 @@
     buffer.write(offset + length - 1);
     buffer.write("): ");
     //buffer.write("(" + lineNumber + ":" + columnNumber + "): ");
-    buffer.write(_message);
+    buffer.write(message);
     return buffer.toString();
   }
 
diff --git a/pkg/analyzer/lib/error/listener.dart b/pkg/analyzer/lib/error/listener.dart
index 5f7e149..9cceca8 100644
--- a/pkg/analyzer/lib/error/listener.dart
+++ b/pkg/analyzer/lib/error/listener.dart
@@ -235,23 +235,28 @@
           }
         }
         for (_TypeToConvert typeToConvert in typeGroup) {
-          Element element = typeToConvert.type.element;
-          if (element == null) {
-            arguments[typeToConvert.index] = typeToConvert.displayName;
-          } else {
-            // TODO(brianwilkerson) When analyzer supports info or context
-            //  messages, expose the additional information that way (rather
-            //  than being poorly inserted into the problem message).
-            StringBuffer buffer = new StringBuffer();
-            for (Element element in typeToConvert.allElements()) {
-              String name = element.name;
-              if (nameToElementMap[name].length > 1) {
-                buffer.write(buffer.isEmpty ? 'where ' : ', ');
-                buffer.write('$name is defined in ${element.source.fullName}');
+          // TODO(brianwilkerson) When analyzer supports info or context
+          //  messages, expose the additional information that way (rather
+          //  than being poorly inserted into the problem message).
+          StringBuffer buffer;
+          for (Element element in typeToConvert.allElements()) {
+            String name = element.name;
+            if (nameToElementMap[name].length > 1) {
+              if (buffer == null) {
+                buffer = new StringBuffer();
+                buffer.write('where ');
+              } else {
+                buffer.write(', ');
               }
+              buffer.write('$name is defined in ${element.source.fullName}');
             }
+          }
+
+          if (buffer != null) {
             arguments[typeToConvert.index] =
                 '${typeToConvert.displayName} ($buffer)';
+          } else {
+            arguments[typeToConvert.index] = typeToConvert.displayName;
           }
         }
       }
@@ -321,20 +326,16 @@
       Set<Element> elements = new Set<Element>();
 
       void addElementsFrom(DartType type) {
-        Element element = type?.element;
-        if (element != null) {
-          if (type is InterfaceType && elements.add(element)) {
+        if (type is FunctionType) {
+          addElementsFrom(type.returnType);
+          for (ParameterElement parameter in type.parameters) {
+            addElementsFrom(parameter.type);
+          }
+        } else if (type is InterfaceType) {
+          if (elements.add(type.element)) {
             for (DartType typeArgument in type.typeArguments) {
               addElementsFrom(typeArgument);
             }
-          } else if (type is FunctionType && elements.add(element)) {
-            addElementsFrom(type.returnType);
-            for (DartType typeArgument in type.typeArguments) {
-              addElementsFrom(typeArgument);
-            }
-            for (ParameterElement parameter in type.parameters) {
-              addElementsFrom(parameter.type);
-            }
           }
         }
       }
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index e179115..414ab6c 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 import 'dart:collection';
 import 'dart:convert';
+import 'dart:typed_data';
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source_io.dart';
@@ -19,7 +20,7 @@
 class MemoryResourceProvider implements ResourceProvider {
   final Map<String, _MemoryResource> _pathToResource =
       new HashMap<String, _MemoryResource>();
-  final Map<String, List<int>> _pathToBytes = new HashMap<String, List<int>>();
+  final Map<String, Uint8List> _pathToBytes = new HashMap<String, Uint8List>();
   final Map<String, int> _pathToTimestamp = new HashMap<String, int>();
   final Map<String, List<StreamController<WatchEvent>>> _pathToWatchers =
       new HashMap<String, List<StreamController<WatchEvent>>>();
@@ -128,7 +129,7 @@
 
   void modifyFile(String path, String content) {
     _checkFileAtPath(path);
-    _pathToBytes[path] = utf8.encode(content);
+    _pathToBytes[path] = utf8.encode(content) as Uint8List;
     _pathToTimestamp[path] = nextStamp++;
     _notifyWatchers(path, ChangeType.MODIFY);
   }
@@ -150,7 +151,7 @@
   File newFile(String path, String content, [int stamp]) {
     _ensureAbsoluteAndNormalized(path);
     _MemoryFile file = _newFile(path);
-    _pathToBytes[path] = utf8.encode(content);
+    _pathToBytes[path] = utf8.encode(content) as Uint8List;
     _pathToTimestamp[path] = stamp ?? nextStamp++;
     _notifyWatchers(path, ChangeType.ADD);
     return file;
@@ -159,7 +160,7 @@
   File newFileWithBytes(String path, List<int> bytes, [int stamp]) {
     _ensureAbsoluteAndNormalized(path);
     _MemoryFile file = _newFile(path);
-    _pathToBytes[path] = bytes;
+    _pathToBytes[path] = Uint8List.fromList(bytes);
     _pathToTimestamp[path] = stamp ?? nextStamp++;
     _notifyWatchers(path, ChangeType.ADD);
     return file;
@@ -196,7 +197,7 @@
     newFolder(pathContext.dirname(path));
     _MemoryFile file = new _MemoryFile(this, path);
     _pathToResource[path] = file;
-    _pathToBytes[path] = utf8.encode(content);
+    _pathToBytes[path] = utf8.encode(content) as Uint8List;
     _pathToTimestamp[path] = stamp ?? nextStamp++;
     _notifyWatchers(path, ChangeType.MODIFY);
     return file;
@@ -300,7 +301,7 @@
   void _setFileContent(_MemoryFile file, List<int> bytes) {
     String path = file.path;
     _pathToResource[path] = file;
-    _pathToBytes[path] = bytes;
+    _pathToBytes[path] = Uint8List.fromList(bytes);
     _pathToTimestamp[path] = nextStamp++;
     _notifyWatchers(path, ChangeType.MODIFY);
   }
@@ -357,7 +358,7 @@
   }
 
   @override
-  List<int> readAsBytesSync() {
+  Uint8List readAsBytesSync() {
     throw new FileSystemException(path, 'File could not be read');
   }
 
@@ -436,8 +437,8 @@
   }
 
   @override
-  List<int> readAsBytesSync() {
-    List<int> content = _provider._pathToBytes[path];
+  Uint8List readAsBytesSync() {
+    Uint8List content = _provider._pathToBytes[path];
     if (content == null) {
       throw new FileSystemException(path, 'File "$path" does not exist.');
     }
@@ -446,7 +447,7 @@
 
   @override
   String readAsStringSync() {
-    List<int> content = _provider._pathToBytes[path];
+    Uint8List content = _provider._pathToBytes[path];
     if (content == null) {
       throw new FileSystemException(path, 'File "$path" does not exist.');
     }
diff --git a/pkg/analyzer/lib/file_system/overlay_file_system.dart b/pkg/analyzer/lib/file_system/overlay_file_system.dart
index 76879be..3628b8f 100644
--- a/pkg/analyzer/lib/file_system/overlay_file_system.dart
+++ b/pkg/analyzer/lib/file_system/overlay_file_system.dart
@@ -3,7 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:convert';
 import 'dart:core';
+import 'dart:typed_data';
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source_io.dart';
@@ -70,6 +72,11 @@
 
   @override
   Resource getResource(String path) {
+    if (hasOverlay(path)) {
+      return new _OverlayResource._from(this, baseProvider.getFile(path));
+    } else if (_hasOverlayIn(path)) {
+      return new _OverlayResource._from(this, baseProvider.getFolder(path));
+    }
     return new _OverlayResource._from(this, baseProvider.getResource(path));
   }
 
@@ -140,14 +147,18 @@
   }
 
   /**
-   * Return the paths of all of the overlaid files that are immediate children
-   * of the given [folder].
+   * Return `true` if there is an overlay associated with at least one file
+   * contained inside the folder with the given [folderPath].
    */
-  Iterable<String> _overlaysInFolder(Folder folder) {
-    String folderPath = folder.path;
-    return _overlayContent.keys
-        .where((path) => pathContext.dirname(path) == folderPath);
-  }
+  bool _hasOverlayIn(String folderPath) => _overlayContent.keys
+      .any((filePath) => pathContext.isWithin(folderPath, filePath));
+
+  /**
+   * Return the paths of all of the overlaid files that are children of the
+   * given [folder], either directly or indirectly.
+   */
+  Iterable<String> _overlaysInFolder(String folderPath) => _overlayContent.keys
+      .where((filePath) => pathContext.isWithin(folderPath, filePath));
 }
 
 /**
@@ -221,10 +232,10 @@
   }
 
   @override
-  List<int> readAsBytesSync() {
+  Uint8List readAsBytesSync() {
     String content = _provider._getOverlayContent(path);
     if (content != null) {
-      return content.codeUnits;
+      return utf8.encode(content) as Uint8List;
     }
     return _file.readAsBytesSync();
   }
@@ -281,7 +292,7 @@
   Stream<WatchEvent> get changes => _folder.changes;
 
   @override
-  bool get exists => _resource.exists;
+  bool get exists => _provider._hasOverlayIn(path) || _resource.exists;
 
   /**
    * Return the folder from the base resource provider that corresponds to this
@@ -330,12 +341,24 @@
 
   @override
   List<Resource> getChildren() {
-    List<Resource> children = _folder
-        .getChildren()
-        .map((child) => new _OverlayResource._from(_provider, child))
-        .toList();
-    for (String overlayPath in _provider._overlaysInFolder(this)) {
-      children.add(_provider.getFile(overlayPath));
+    List<Resource> children;
+    try {
+      children = _folder
+          .getChildren()
+          .map((child) => new _OverlayResource._from(_provider, child))
+          .toList();
+    } on FileSystemException {
+      children = [];
+    }
+    for (String overlayPath in _provider._overlaysInFolder(path)) {
+      pathos.Context context = _provider.pathContext;
+      if (context.dirname(overlayPath) == path) {
+        children.add(_provider.getFile(overlayPath));
+      } else {
+        String relativePath = context.relative(overlayPath, from: path);
+        String folderName = context.split(relativePath)[0];
+        children.add(_provider.getFolder(context.join(path, folderName)));
+      }
     }
     return children;
   }
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index eb28314..83a34de 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 import 'dart:io' as io;
+import 'dart:typed_data';
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source_io.dart';
@@ -193,7 +194,7 @@
   }
 
   @override
-  List<int> readAsBytesSync() {
+  Uint8List readAsBytesSync() {
     _throwIfWindowsDeviceDriver();
     try {
       return _file.readAsBytesSync();
diff --git a/pkg/analyzer/lib/src/command_line/arguments.dart b/pkg/analyzer/lib/src/command_line/arguments.dart
index c39ec25..91a13f0 100644
--- a/pkg/analyzer/lib/src/command_line/arguments.dart
+++ b/pkg/analyzer/lib/src/command_line/arguments.dart
@@ -128,7 +128,7 @@
         return !context.isWithin(sdkPath, sourcePath);
       });
   return new DartSdkManager(
-      sdkPath ?? FolderBasedDartSdk.defaultSdkDirectory(resourceProvider),
+      sdkPath ?? FolderBasedDartSdk.defaultSdkDirectory(resourceProvider)?.path,
       canUseSummaries);
 }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart b/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart
index 20859c2..9b9a320 100644
--- a/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart
@@ -678,11 +678,13 @@
     if (parameters == null) return;
 
     for (var parameter in parameters.parameters) {
-      if (parameter.isRequired) {
+      if (parameter.isRequiredPositional) {
         signature.addInt(1);
+      } else if (parameter.isRequiredNamed) {
+        signature.addInt(4);
       } else if (parameter.isOptionalPositional) {
         signature.addInt(2);
-      } else {
+      } else if (parameter.isOptionalNamed) {
         signature.addInt(3);
       }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart b/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart
index 5f16104..01b5ac3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart
@@ -631,7 +631,10 @@
     if (node.isSynthetic) return;
 
     var name = node.name;
-    if (_localScopes.contains(name) || name == 'void' || name == 'dynamic') {
+    if (_localScopes.contains(name) ||
+        name == 'void' ||
+        name == 'dynamic' ||
+        name == 'Never') {
       return;
     }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 463a9db..0620474 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -28,7 +28,6 @@
 import 'package:analyzer/src/dart/analysis/search.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/analysis/status.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show
@@ -94,7 +93,7 @@
   /**
    * The version of data format, should be incremented on every format change.
    */
-  static const int DATA_VERSION = 79;
+  static const int DATA_VERSION = 81;
 
   /**
    * The number of exception contexts allowed to write. Once this field is
@@ -103,6 +102,11 @@
   static int allowedNumberOfContextsToWrite = 10;
 
   /**
+   * Whether summary2 should be used to resynthesize elements.
+   */
+  static bool useSummary2 = false;
+
+  /**
    * The scheduler that schedules analysis work in this, and possibly other
    * analysis drivers.
    */
@@ -168,13 +172,13 @@
    * The salt to mix into all hashes used as keys for unlinked data.
    */
   final Uint32List _unlinkedSalt =
-      new Uint32List(2 + AnalysisOptionsImpl.unlinkedSignatureLength);
+      new Uint32List(3 + AnalysisOptionsImpl.unlinkedSignatureLength);
 
   /**
    * The salt to mix into all hashes used as keys for linked data.
    */
   final Uint32List _linkedSalt =
-      new Uint32List(2 + AnalysisOptions.signatureLength);
+      new Uint32List(3 + AnalysisOptions.signatureLength);
 
   /**
    * The set of priority files, that should be analyzed sooner.
@@ -212,11 +216,6 @@
   final _referencingNameTasks = <_FilesReferencingNameTask>[];
 
   /**
-   * The list of tasks to compute top-level declarations of a name.
-   */
-  final _topLevelNameDeclarationsTasks = <_TopLevelNameDeclarationsTask>[];
-
-  /**
    * The mapping from the files for which the index was requested using
    * [getIndex] to the [Completer]s to report the result.
    */
@@ -514,9 +513,6 @@
     if (_unitElementRequestedFiles.isNotEmpty) {
       return AnalysisDriverPriority.interactive;
     }
-    if (_topLevelNameDeclarationsTasks.isNotEmpty) {
-      return AnalysisDriverPriority.interactive;
-    }
     if (_priorityFiles.isNotEmpty) {
       for (String path in _priorityFiles) {
         if (_fileTracker.isFilePending(path)) {
@@ -740,12 +736,18 @@
    * [uri], which is either resynthesized from the provided external summary
    * store, or built for a file to which the given [uri] is resolved.
    *
+   * Throw [ArgumentError] if the [uri] does not correspond to a file.
+   *
    * Throw [ArgumentError] if the [uri] corresponds to a part.
    */
   Future<LibraryElement> getLibraryByUri(String uri) async {
     var uriObj = Uri.parse(uri);
     var file = _fsState.getFileForUri(uriObj);
 
+    if (file.isUnresolved) {
+      throw ArgumentError('$uri cannot be resolved to a file.');
+    }
+
     if (file.isExternalLibrary) {
       return _createLibraryContext(file).getLibraryElement(file);
     }
@@ -960,19 +962,6 @@
   }
 
   /**
-   * Return a [Future] that completes with top-level declarations with the
-   * given [name] in all known libraries.
-   */
-  Future<List<TopLevelDeclarationInSource>> getTopLevelNameDeclarations(
-      String name) {
-    _discoverAvailableFiles();
-    var task = new _TopLevelNameDeclarationsTask(this, name);
-    _topLevelNameDeclarationsTasks.add(task);
-    _scheduler.notify(this);
-    return task.completer.future;
-  }
-
-  /**
    * Return a [Future] that completes with the [UnitElementResult] for the
    * file with the given [path], or with `null` if the file cannot be analyzed.
    */
@@ -1197,16 +1186,6 @@
       return;
     }
 
-    // Compute top-level declarations.
-    if (_topLevelNameDeclarationsTasks.isNotEmpty) {
-      _TopLevelNameDeclarationsTask task = _topLevelNameDeclarationsTasks.first;
-      bool isDone = task.perform();
-      if (isDone) {
-        _topLevelNameDeclarationsTasks.remove(task);
-      }
-      return;
-    }
-
     // Analyze a priority file.
     if (_priorityFiles.isNotEmpty) {
       for (String path in _priorityFiles) {
@@ -1432,6 +1411,7 @@
             libraryContext.isLibraryUri,
             libraryContext.analysisContext,
             libraryContext.resynthesizer,
+            libraryContext.elementFactory,
             libraryContext.inheritanceManager,
             library,
             _resourceProvider);
@@ -1500,6 +1480,7 @@
           libraryContext.isLibraryUri,
           libraryContext.analysisContext,
           libraryContext.resynthesizer,
+          libraryContext.elementFactory,
           libraryContext.inheritanceManager,
           library,
           _resourceProvider);
@@ -1594,6 +1575,7 @@
       _unlinkedSalt,
       _linkedSalt,
       externalSummaries: _externalSummaries,
+      useSummary2: useSummary2,
     );
     _fileTracker = new FileTracker(_logger, _fsState, _changeHook);
   }
@@ -1619,7 +1601,10 @@
         sourceFactory: _sourceFactory,
         externalSummaries: _externalSummaries,
         targetLibrary: library,
+        useSummary2: useSummary2,
       );
+    } else if (useSummary2) {
+      _libraryContext.load2(library);
     } else {
       _libraryContext.load(library);
     }
@@ -1650,11 +1635,13 @@
   void _fillSalt() {
     _unlinkedSalt[0] = DATA_VERSION;
     _unlinkedSalt[1] = enableIndex ? 1 : 0;
-    _unlinkedSalt.setAll(2, _analysisOptions.unlinkedSignature);
+    _unlinkedSalt[2] = useSummary2 ? 1 : 0;
+    _unlinkedSalt.setAll(3, _analysisOptions.unlinkedSignature);
 
     _linkedSalt[0] = DATA_VERSION;
     _linkedSalt[1] = enableIndex ? 1 : 0;
-    _linkedSalt.setAll(2, _analysisOptions.signature);
+    _linkedSalt[2] = useSummary2 ? 1 : 0;
+    _linkedSalt.setAll(3, _analysisOptions.signature);
   }
 
   /**
@@ -2529,66 +2516,3 @@
     return true;
   }
 }
-
-/**
- * Task that computes top-level declarations for a certain name in all
- * known libraries.
- */
-class _TopLevelNameDeclarationsTask {
-  final AnalysisDriver driver;
-  final String name;
-  final Completer<List<TopLevelDeclarationInSource>> completer =
-      new Completer<List<TopLevelDeclarationInSource>>();
-
-  final List<TopLevelDeclarationInSource> libraryDeclarations =
-      <TopLevelDeclarationInSource>[];
-  final Set<String> checkedFiles = new Set<String>();
-  final List<String> filesToCheck = <String>[];
-
-  _TopLevelNameDeclarationsTask(this.driver, this.name);
-
-  /**
-   * Perform a single piece of work, and either complete the [completer] and
-   * return `true` to indicate that the task is done, return `false` to indicate
-   * that the task should continue to be run.
-   */
-  bool perform() {
-    // Prepare files to check.
-    if (filesToCheck.isEmpty) {
-      filesToCheck.addAll(driver.addedFiles.difference(checkedFiles));
-      filesToCheck.addAll(driver.knownFiles.difference(checkedFiles));
-    }
-
-    // If no more files to check, complete and done.
-    if (filesToCheck.isEmpty) {
-      completer.complete(libraryDeclarations);
-      return true;
-    }
-
-    // Check the next file.
-    String path = filesToCheck.removeLast();
-    if (checkedFiles.add(path)) {
-      FileState file = driver._fsState.getFileForPath(path);
-      if (!file.isPart) {
-        bool isExported = false;
-
-        TopLevelDeclaration declaration;
-        for (FileState part in file.libraryFiles) {
-          declaration ??= part.topLevelDeclarations[name];
-        }
-
-        if (declaration == null) {
-          declaration = file.exportedTopLevelDeclarations[name];
-          isExported = true;
-        }
-        if (declaration != null) {
-          libraryDeclarations.add(new TopLevelDeclarationInSource(
-              file.source, declaration, isExported));
-        }
-      }
-    }
-
-    // We're not done yet.
-    return false;
-  }
-}
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
index 54978bd..cb17efa 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
@@ -2,21 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Note: the plan is to generate this file from a YAML representation somewhere
-// in the SDK repo.  Please do not add any code to this file that can't be
-// easily code generated based on a knowledge of the current set of experimental
-// flags and their status.
-// TODO(paulberry,kmillikin): once code generation is implemented, replace this
-// notice with a notice that this file is generated and a pointer to the source
-// YAML file and the regeneration tool.
-
-// Note: to demonstrate how code is supposed to be generated for expired flags,
-// this file contains bogus expired flags called "bogus-enabled" and
-// "bogus-disabled".  They are not used and can be removed at the time that code
-// generation is implemented.
-
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/src/dart/analysis/experiments_impl.dart';
+import 'package:analyzer/src/generated/utilities_general.dart';
 import 'package:meta/meta.dart';
+import 'package:pub_semver/src/version.dart';
 
 export 'package:analyzer/src/dart/analysis/experiments_impl.dart'
     show
@@ -28,111 +18,36 @@
         validateFlags,
         ValidationResult;
 
+part 'experiments.g.dart';
+
 /// Gets access to the private list of boolean flags in an [Experiments] object.
 /// For testing use only.
 @visibleForTesting
 List<bool> getExperimentalFlags_forTesting(ExperimentStatus status) =>
     status._enableFlags;
 
-/// Constant strings for enabling each of the currently known experimental
-/// flags.
-class EnableString {
-  /// String to enable the experiment "constant-update"
-  static const String constant_update_2018 = 'constant-update-2018';
-
-  /// String to enable the experiment "control-flow-collections"
-  static const String control_flow_collections = 'control-flow-collections';
-
-  /// String to enable the experiment "non-nullable"
-  static const String non_nullable = 'non-nullable';
-
-  /// String to enable the experiment "set-literals"
-  static const String set_literals = 'set-literals';
-
-  /// String to enable the experiment "spread-collections"
-  static const String spread_collections = 'spread-collections';
-
-  /// String to enable the experiment "triple-shift"
-  static const String triple_shift = 'triple-shift';
-
-  /// String to enable the experiment "bogus-disabled"
-  static const String bogus_disabled = 'bogus-disabled';
-
-  /// String to enable the experiment "bogus-enabled"
-  static const String bogus_enabled = 'bogus-enabled';
-}
-
 /// A representation of the set of experiments that are active and whether they
 /// are enabled.
-class ExperimentStatus {
+class ExperimentStatus with _CurrentState implements FeatureSet {
   /// A map containing information about all known experimental flags.
-  static const knownFeatures = <String, ExperimentalFeature>{
-    EnableString.constant_update_2018: const ExperimentalFeature(
-        0,
-        EnableString.constant_update_2018,
-        IsEnabledByDefault.constant_update_2018,
-        IsExpired.constant_update_2018,
-        'Q4 2018 Constant Update'),
-    EnableString.non_nullable: const ExperimentalFeature(
-        1,
-        EnableString.non_nullable,
-        IsEnabledByDefault.non_nullable,
-        IsExpired.non_nullable,
-        'Non Nullable'),
-    EnableString.control_flow_collections: const ExperimentalFeature(
-        null,
-        EnableString.control_flow_collections,
-        IsEnabledByDefault.control_flow_collections,
-        IsExpired.control_flow_collections,
-        'Control Flow Collections'),
-    EnableString.spread_collections: const ExperimentalFeature(
-        null,
-        EnableString.spread_collections,
-        IsEnabledByDefault.spread_collections,
-        IsExpired.spread_collections,
-        'Spread Collections'),
-    EnableString.set_literals: const ExperimentalFeature(
-        null,
-        EnableString.set_literals,
-        IsEnabledByDefault.set_literals,
-        IsExpired.set_literals,
-        'Set Literals'),
-    EnableString.triple_shift: const ExperimentalFeature(
-        2,
-        EnableString.triple_shift,
-        IsEnabledByDefault.triple_shift,
-        IsExpired.triple_shift,
-        'Triple-shift operator'),
-    EnableString.bogus_disabled: const ExperimentalFeature(
-        null,
-        EnableString.bogus_disabled,
-        IsEnabledByDefault.bogus_disabled,
-        IsExpired.bogus_disabled,
-        null),
-    EnableString.bogus_enabled: const ExperimentalFeature(
-        null,
-        EnableString.bogus_enabled,
-        IsEnabledByDefault.bogus_enabled,
-        IsExpired.bogus_enabled,
-        null),
-  };
+  static const knownFeatures = _knownFeatures;
 
   final List<bool> _enableFlags;
 
   /// Initializes a newly created set of experiments based on optional
   /// arguments.
-  ExperimentStatus(
-      {bool constant_update_2018,
-      bool control_flow_collections,
-      bool non_nullable,
-      bool set_literals,
-      bool spread_collections,
-      bool triple_shift})
-      : _enableFlags = <bool>[
-          constant_update_2018 ?? IsEnabledByDefault.constant_update_2018,
-          non_nullable ?? IsEnabledByDefault.non_nullable,
-          triple_shift ?? IsEnabledByDefault.triple_shift,
-        ];
+  ExperimentStatus() : _enableFlags = _buildExperimentalFlagsArray();
+
+  /// Computes a set of features for use in a unit test.  Computes the set of
+  /// features enabled in [sdkVersion], plus any specified [additionalFeatures].
+  ///
+  /// If [sdkVersion] is not supplied (or is `null`), then the current set of
+  /// enabled features is used as the starting point.
+  @visibleForTesting
+  ExperimentStatus.forTesting(
+      {String sdkVersion, List<Feature> additionalFeatures: const []})
+      : this._(enableFlagsForTesting(
+            sdkVersion: sdkVersion, additionalFeatures: additionalFeatures));
 
   /// Decodes the strings given in [flags] into a representation of the set of
   /// experiments that should be enabled.
@@ -144,93 +59,40 @@
 
   ExperimentStatus._(this._enableFlags);
 
-  /// Hardcoded state for the expired flag "bogus_disabled"
-  bool get bogus_disabled => false;
+  @override
+  int get hashCode {
+    int hash = 0;
+    for (var flag in _enableFlags) {
+      hash = JenkinsSmiHash.combine(hash, flag.hashCode);
+    }
+    return JenkinsSmiHash.finish(hash);
+  }
 
-  /// Hardcoded state for the expired flag "bogus_enabled"
-  bool get bogus_enabled => true;
-
-  /// Current state for the flag "constant-update-2018"
-  bool get constant_update_2018 => _enableFlags[0];
-
-  /// Current state for the flag "control_flow_collections"
-  bool get control_flow_collections => true;
-
-  /// Current state for the flag "non-nullable"
-  bool get non_nullable => _enableFlags[1];
-
-  /// Current state for the flag "set-literals"
-  bool get set_literals => true;
-
-  /// Current state for the flag "spread_collections"
-  bool get spread_collections => true;
-
-  /// Current state for the flag "triple_shift"
-  bool get triple_shift => _enableFlags[2];
+  @override
+  operator ==(Object other) {
+    if (other is ExperimentStatus) {
+      if (_enableFlags.length != other._enableFlags.length) return false;
+      for (int i = 0; i < _enableFlags.length; i++) {
+        if (_enableFlags[i] != other._enableFlags[i]) return false;
+      }
+      return true;
+    }
+    return false;
+  }
 
   /// Queries whether the given [feature] is enabled or disabled.
-  bool isEnabled(ExperimentalFeature feature) => feature.isExpired
-      ? feature.isEnabledByDefault
-      : _enableFlags[feature.index];
+  @override
+  bool isEnabled(covariant ExperimentalFeature feature) =>
+      _enableFlags[feature.index];
+
+  @override
+  FeatureSet restrictToVersion(Version version) =>
+      ExperimentStatus._(restrictEnableFlagsToVersion(_enableFlags, version));
+
+  @override
+  String toString() => experimentStatusToString(_enableFlags);
 
   /// Returns a list of strings suitable for passing to
   /// [ExperimentStatus.fromStrings].
   List<String> toStringList() => experimentStatusToStringList(this);
 }
-
-/// Constant bools indicating whether each experimental flag is currently
-/// enabled by default.
-class IsEnabledByDefault {
-  /// Default state of the experiment "constant-update"
-  static const bool constant_update_2018 = false;
-
-  /// Default state of the experiment "control-flow-collections"
-  static const bool control_flow_collections = true;
-
-  /// Default state of the experiment "non-nullable"
-  static const bool non_nullable = false;
-
-  /// Default state of the experiment "set-literals"
-  static const bool set_literals = true;
-
-  /// Default state of the experiment "spread-collections"
-  static const bool spread_collections = true;
-
-  /// Default state of the experiment "triple-shift"
-  static const bool triple_shift = false;
-
-  /// Default state of the experiment "bogus-disabled"
-  static const bool bogus_disabled = false;
-
-  /// Default state of the experiment "bogus-enabled"
-  static const bool bogus_enabled = true;
-}
-
-/// Constant bools indicating whether each experimental flag is currently
-/// expired (meaning its enable/disable status can no longer be altered from the
-/// value in [IsEnabledByDefault]).
-class IsExpired {
-  /// Expiration status of the experiment "constant-update"
-  static const bool constant_update_2018 = false;
-
-  /// Expiration status of the experiment "control-flow-collections"
-  static const bool control_flow_collections = true;
-
-  /// Expiration status of the experiment "non-nullable"
-  static const bool non_nullable = false;
-
-  /// Expiration status of the experiment "set-literals"
-  static const bool set_literals = true;
-
-  /// Expiration status of the experiment "spread-collections"
-  static const bool spread_collections = true;
-
-  /// Expiration status of the experiment "triple-shift"
-  static const bool triple_shift = false;
-
-  /// Expiration status of the experiment "bogus-disabled"
-  static const bool bogus_disabled = true;
-
-  /// Expiration status of the experiment "bogus-enabled"
-  static const bool bogus_enabled = true;
-}
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
new file mode 100644
index 0000000..3d782f0
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -0,0 +1,231 @@
+//
+// THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Instead modify 'tools/experimental_features.yaml' and run
+// 'dart pkg/analyzer/tool/experiments/generate.dart' to update.
+
+part of 'experiments.dart';
+
+/// A map containing information about all known experimental flags.
+const _knownFeatures = <String, ExperimentalFeature>{
+  EnableString.constant_update_2018: ExperimentalFeatures.constant_update_2018,
+  EnableString.control_flow_collections:
+      ExperimentalFeatures.control_flow_collections,
+  EnableString.extension_methods: ExperimentalFeatures.extension_methods,
+  EnableString.non_nullable: ExperimentalFeatures.non_nullable,
+  EnableString.set_literals: ExperimentalFeatures.set_literals,
+  EnableString.spread_collections: ExperimentalFeatures.spread_collections,
+  EnableString.triple_shift: ExperimentalFeatures.triple_shift,
+  EnableString.bogus_disabled: ExperimentalFeatures.bogus_disabled,
+  EnableString.bogus_enabled: ExperimentalFeatures.bogus_enabled,
+};
+
+List<bool> _buildExperimentalFlagsArray() => <bool>[
+      IsEnabledByDefault.constant_update_2018,
+      true, // control-flow-collections
+      IsEnabledByDefault.extension_methods,
+      IsEnabledByDefault.non_nullable,
+      true, // set-literals
+      true, // spread-collections
+      IsEnabledByDefault.triple_shift,
+      false, // bogus-disabled
+      true, // bogus-enabled
+    ];
+
+/// Constant strings for enabling each of the currently known experimental
+/// flags.
+class EnableString {
+  /// String to enable the experiment "constant-update-2018"
+  static const String constant_update_2018 = 'constant-update-2018';
+
+  /// String to enable the experiment "control-flow-collections"
+  static const String control_flow_collections = 'control-flow-collections';
+
+  /// String to enable the experiment "extension-methods"
+  static const String extension_methods = 'extension-methods';
+
+  /// String to enable the experiment "non-nullable"
+  static const String non_nullable = 'non-nullable';
+
+  /// String to enable the experiment "set-literals"
+  static const String set_literals = 'set-literals';
+
+  /// String to enable the experiment "spread-collections"
+  static const String spread_collections = 'spread-collections';
+
+  /// String to enable the experiment "triple-shift"
+  static const String triple_shift = 'triple-shift';
+
+  /// String to enable the experiment "bogus-disabled"
+  static const String bogus_disabled = 'bogus-disabled';
+
+  /// String to enable the experiment "bogus-enabled"
+  static const String bogus_enabled = 'bogus-enabled';
+}
+
+class ExperimentalFeatures {
+  static const constant_update_2018 = const ExperimentalFeature(
+      0,
+      EnableString.constant_update_2018,
+      IsEnabledByDefault.constant_update_2018,
+      IsExpired.constant_update_2018,
+      'Enhanced constant expressions');
+
+  static const control_flow_collections = const ExperimentalFeature(
+      1,
+      EnableString.control_flow_collections,
+      IsEnabledByDefault.control_flow_collections,
+      IsExpired.control_flow_collections,
+      'Control Flow Collections',
+      firstSupportedVersion: '2.2.2');
+
+  static const extension_methods = const ExperimentalFeature(
+      2,
+      EnableString.extension_methods,
+      IsEnabledByDefault.extension_methods,
+      IsExpired.extension_methods,
+      'Extension Methods');
+
+  static const non_nullable = const ExperimentalFeature(
+      3,
+      EnableString.non_nullable,
+      IsEnabledByDefault.non_nullable,
+      IsExpired.non_nullable,
+      'Non Nullable by default');
+
+  static const set_literals = const ExperimentalFeature(
+      4,
+      EnableString.set_literals,
+      IsEnabledByDefault.set_literals,
+      IsExpired.set_literals,
+      'Set Literals',
+      firstSupportedVersion: '2.2.0');
+
+  static const spread_collections = const ExperimentalFeature(
+      5,
+      EnableString.spread_collections,
+      IsEnabledByDefault.spread_collections,
+      IsExpired.spread_collections,
+      'Spread Collections',
+      firstSupportedVersion: '2.2.2');
+
+  static const triple_shift = const ExperimentalFeature(
+      6,
+      EnableString.triple_shift,
+      IsEnabledByDefault.triple_shift,
+      IsExpired.triple_shift,
+      'Triple-shift operator');
+
+  static const bogus_disabled = const ExperimentalFeature(
+      7,
+      EnableString.bogus_disabled,
+      IsEnabledByDefault.bogus_disabled,
+      IsExpired.bogus_disabled,
+      null);
+
+  static const bogus_enabled = const ExperimentalFeature(
+      8,
+      EnableString.bogus_enabled,
+      IsEnabledByDefault.bogus_enabled,
+      IsExpired.bogus_enabled,
+      null,
+      firstSupportedVersion: '1.0.0');
+}
+
+/// Constant bools indicating whether each experimental flag is currently
+/// enabled by default.
+class IsEnabledByDefault {
+  /// Default state of the experiment "constant-update-2018"
+  static const bool constant_update_2018 = false;
+
+  /// Default state of the experiment "control-flow-collections"
+  static const bool control_flow_collections = true;
+
+  /// Default state of the experiment "extension-methods"
+  static const bool extension_methods = false;
+
+  /// Default state of the experiment "non-nullable"
+  static const bool non_nullable = false;
+
+  /// Default state of the experiment "set-literals"
+  static const bool set_literals = true;
+
+  /// Default state of the experiment "spread-collections"
+  static const bool spread_collections = true;
+
+  /// Default state of the experiment "triple-shift"
+  static const bool triple_shift = false;
+
+  /// Default state of the experiment "bogus-disabled"
+  static const bool bogus_disabled = false;
+
+  /// Default state of the experiment "bogus-enabled"
+  static const bool bogus_enabled = true;
+}
+
+/// Constant bools indicating whether each experimental flag is currently
+/// expired (meaning its enable/disable status can no longer be altered from the
+/// value in [IsEnabledByDefault]).
+class IsExpired {
+  /// Expiration status of the experiment "constant-update-2018"
+  static const bool constant_update_2018 = false;
+
+  /// Expiration status of the experiment "control-flow-collections"
+  static const bool control_flow_collections = true;
+
+  /// Expiration status of the experiment "extension-methods"
+  static const bool extension_methods = false;
+
+  /// Expiration status of the experiment "non-nullable"
+  static const bool non_nullable = false;
+
+  /// Expiration status of the experiment "set-literals"
+  static const bool set_literals = true;
+
+  /// Expiration status of the experiment "spread-collections"
+  static const bool spread_collections = true;
+
+  /// Expiration status of the experiment "triple-shift"
+  static const bool triple_shift = false;
+
+  /// Expiration status of the experiment "bogus-disabled"
+  static const bool bogus_disabled = true;
+
+  /// Expiration status of the experiment "bogus-enabled"
+  static const bool bogus_enabled = true;
+}
+
+mixin _CurrentState {
+  /// Current state for the flag "bogus-disabled"
+  bool get bogus_disabled => isEnabled(ExperimentalFeatures.bogus_disabled);
+
+  /// Current state for the flag "bogus-enabled"
+  bool get bogus_enabled => isEnabled(ExperimentalFeatures.bogus_enabled);
+
+  /// Current state for the flag "constant-update-2018"
+  bool get constant_update_2018 =>
+      isEnabled(ExperimentalFeatures.constant_update_2018);
+
+  /// Current state for the flag "control-flow-collections"
+  bool get control_flow_collections =>
+      isEnabled(ExperimentalFeatures.control_flow_collections);
+
+  /// Current state for the flag "extension-methods"
+  bool get extension_methods =>
+      isEnabled(ExperimentalFeatures.extension_methods);
+
+  /// Current state for the flag "non-nullable"
+  bool get non_nullable => isEnabled(ExperimentalFeatures.non_nullable);
+
+  /// Current state for the flag "set-literals"
+  bool get set_literals => isEnabled(ExperimentalFeatures.set_literals);
+
+  /// Current state for the flag "spread-collections"
+  bool get spread_collections =>
+      isEnabled(ExperimentalFeatures.spread_collections);
+
+  /// Current state for the flag "triple-shift"
+  bool get triple_shift => isEnabled(ExperimentalFeatures.triple_shift);
+
+  bool isEnabled(covariant ExperimentalFeature feature);
+}
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments_impl.dart b/pkg/analyzer/lib/src/dart/analysis/experiments_impl.dart
index 64d4b7e..81a437b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments_impl.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments_impl.dart
@@ -2,8 +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.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:meta/meta.dart';
+import 'package:pub_semver/pub_semver.dart';
 
 /// The same as [ExperimentStatus.knownFeatures], except when a call to
 /// [overrideKnownFeatures] is in progress.
@@ -17,14 +19,9 @@
 /// unrecognized flags are ignored, conflicting flags are resolved in favor of
 /// the flag appearing last.
 List<bool> decodeFlags(List<String> flags) {
-  var decodedFlags = <bool>[];
+  var decodedFlags = List<bool>.filled(_knownFeatures.length, false);
   for (var feature in _knownFeatures.values) {
-    if (feature.isExpired) continue;
-    var index = feature.index;
-    while (decodedFlags.length <= index) {
-      decodedFlags.add(false);
-    }
-    decodedFlags[index] = feature.isEnabledByDefault;
+    decodedFlags[feature.index] = feature.isEnabledByDefault;
   }
   for (var entry in _flagStringsToMap(flags).entries) {
     decodedFlags[entry.key] = entry.value;
@@ -32,6 +29,34 @@
   return decodedFlags;
 }
 
+/// Computes a set of features for use in a unit test.  Computes the set of
+/// features enabled in [sdkVersion], plus any specified [additionalFeatures].
+///
+/// If [sdkVersion] is not supplied (or is `null`), then the current set of
+/// enabled features is used as the starting point.
+List<bool> enableFlagsForTesting(
+    {String sdkVersion, List<Feature> additionalFeatures: const []}) {
+  var flags = decodeFlags([]);
+  if (sdkVersion != null) {
+    flags = restrictEnableFlagsToVersion(flags, Version.parse(sdkVersion));
+  }
+  for (ExperimentalFeature feature in additionalFeatures) {
+    flags[feature.index] = true;
+  }
+  return flags;
+}
+
+/// Pretty-prints the given set of enable flags as a set of feature names.
+String experimentStatusToString(List<bool> enableFlags) {
+  var featuresInSet = <String>[];
+  for (var feature in _knownFeatures.values) {
+    if (enableFlags[feature.index]) {
+      featuresInSet.add(feature.enableString);
+    }
+  }
+  return 'FeatureSet{${featuresInSet.join(', ')}}';
+}
+
 /// Converts the flags in [status] to a list of strings suitable for
 /// passing to [_decodeFlags].
 List<String> experimentStatusToStringList(ExperimentStatus status) {
@@ -64,6 +89,19 @@
   }
 }
 
+/// Computes a new set of enable flags based on [flags], but with any features
+/// that were not present in [version] set to `false`.
+List<bool> restrictEnableFlagsToVersion(List<bool> flags, Version version) {
+  flags = List.from(flags);
+  for (var feature in _knownFeatures.values) {
+    if (!feature.isEnabledByDefault ||
+        feature.firstSupportedVersion > version) {
+      flags[feature.index] = false;
+    }
+  }
+  return flags;
+}
+
 /// Validates whether there are any disagreements between the strings given in
 /// [flags1] and the strings given in [flags2].
 ///
@@ -205,13 +243,10 @@
 
 /// Information about a single experimental flag that the user might use to
 /// request that a feature be enabled (or disabled).
-class ExperimentalFeature {
+class ExperimentalFeature implements Feature {
   /// Index of the flag in the private data structure maintained by
   /// [ExperimentStatus].
   ///
-  /// For expired features, the index should be null, since no enable/disable
-  /// state needs to be stored.
-  ///
   /// This index should not be relied upon to be stable over time.  For instance
   /// it should not be used to serialize the state of experiments to long term
   /// storage if there is any expectation of compatibility between analyzer
@@ -231,13 +266,50 @@
   /// Documentation for the feature, if known.  `null` for expired flags.
   final String documentation;
 
+  final String _firstSupportedVersion;
+
   const ExperimentalFeature(this.index, this.enableString,
-      this.isEnabledByDefault, this.isExpired, this.documentation)
-      : assert(isExpired ? index == null : index != null);
+      this.isEnabledByDefault, this.isExpired, this.documentation,
+      {String firstSupportedVersion})
+      : _firstSupportedVersion = firstSupportedVersion,
+        assert(index != null),
+        assert(isEnabledByDefault
+            ? firstSupportedVersion != null
+            : firstSupportedVersion == null),
+        assert(enableString != null);
 
   /// The string to disable the feature.
   String get disableString => 'no-$enableString';
 
+  @override
+  String get experimentalFlag => isExpired ? null : enableString;
+
+  @override
+  Version get firstSupportedVersion {
+    if (_firstSupportedVersion == null) {
+      return null;
+    } else {
+      return Version.parse(_firstSupportedVersion);
+    }
+  }
+
+  @override
+  FeatureStatus get status {
+    if (isExpired) {
+      if (isEnabledByDefault) {
+        return FeatureStatus.current;
+      } else {
+        return FeatureStatus.abandoned;
+      }
+    } else {
+      if (isEnabledByDefault) {
+        return FeatureStatus.provisional;
+      } else {
+        return FeatureStatus.future;
+      }
+    }
+  }
+
   /// Retrieves the string to enable or disable the feature, depending on
   /// [value].
   String stringForValue(bool value) => value ? enableString : disableString;
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 536e53d..252c1e4 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -5,6 +5,7 @@
 import 'dart:convert';
 import 'dart:typed_data';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -12,11 +13,10 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/defined_names.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/library_graph.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/referenced_names.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
+import 'package:analyzer/src/dart/analysis/unlinked_api_signature.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -30,11 +30,16 @@
 import 'package:analyzer/src/summary/name_filter.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/summary/summarize_ast.dart';
+import 'package:analyzer/src/summary2/informative_data.dart';
 import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
 import 'package:front_end/src/fasta/scanner/token.dart';
 import 'package:meta/meta.dart';
 
+var counterFileStateRefresh = 0;
+var counterUnlinkedLinkedBytes = 0;
+var timerFileStateRefresh = Stopwatch();
+
 /**
  * [FileContentOverlay] is used to temporary override content of files.
  */
@@ -78,11 +83,6 @@
  * should be called.
  */
 class FileState {
-  /**
-   * The next value for [_exportDeclarationsId].
-   */
-  static int _exportDeclarationsNextId = 0;
-
   final FileSystemState _fsState;
 
   /**
@@ -120,6 +120,8 @@
   UnlinkedUnit _unlinked;
   List<int> _apiSignature;
 
+  UnlinkedUnit2 _unlinked2;
+
   List<FileState> _importedFiles;
   List<FileState> _exportedFiles;
   List<FileState> _partedFiles;
@@ -133,10 +135,6 @@
   String _transitiveSignature;
   String _transitiveSignatureLinked;
 
-  Map<String, TopLevelDeclaration> _topLevelDeclarations;
-  Map<String, TopLevelDeclaration> _exportedTopLevelDeclarations;
-  int _exportDeclarationsId = 0;
-
   /**
    * The flag that shows whether the file has an error or warning that
    * might be fixed by a change to another file.
@@ -207,15 +205,6 @@
    */
   List<FileState> get exportedFiles => _exportedFiles;
 
-  /**
-   * Return [TopLevelDeclaration]s exported from the this library file. The
-   * keys to the map are names of declarations.
-   */
-  Map<String, TopLevelDeclaration> get exportedTopLevelDeclarations {
-    _exportDeclarationsNextId = 1;
-    return _computeExportedDeclarations().declarations;
-  }
-
   @override
   int get hashCode => uri.hashCode;
 
@@ -244,6 +233,9 @@
         _fsState.externalSummaries.unlinkedMap.containsKey(uriStr)) {
       return !_fsState.externalSummaries.linkedMap.containsKey(uriStr);
     }
+    if (_unlinked2 != null) {
+      return !_unlinked2.hasLibraryDirective && _unlinked2.hasPartOfDirective;
+    }
     return _unlinked.libraryNameOffset == 0 && _unlinked.isPartOf;
   }
 
@@ -311,59 +303,6 @@
   FileStateTestView get test => new FileStateTestView(this);
 
   /**
-   * Return public top-level declarations declared in the file. The keys to the
-   * map are names of declarations.
-   */
-  Map<String, TopLevelDeclaration> get topLevelDeclarations {
-    if (_topLevelDeclarations == null) {
-      _topLevelDeclarations = <String, TopLevelDeclaration>{};
-
-      void addDeclaration(TopLevelDeclarationKind kind, String name) {
-        if (!name.startsWith('_')) {
-          _topLevelDeclarations[name] = new TopLevelDeclaration(kind, name);
-        }
-      }
-
-      // Add types.
-      for (UnlinkedClass type in unlinked.classes) {
-        addDeclaration(TopLevelDeclarationKind.type, type.name);
-      }
-      for (UnlinkedEnum type in unlinked.enums) {
-        addDeclaration(TopLevelDeclarationKind.type, type.name);
-      }
-      for (UnlinkedClass type in unlinked.mixins) {
-        addDeclaration(TopLevelDeclarationKind.type, type.name);
-      }
-      for (UnlinkedTypedef type in unlinked.typedefs) {
-        addDeclaration(TopLevelDeclarationKind.type, type.name);
-      }
-      // Add functions and variables.
-      Set<String> addedVariableNames = new Set<String>();
-      for (UnlinkedExecutable executable in unlinked.executables) {
-        String name = executable.name;
-        if (executable.kind == UnlinkedExecutableKind.functionOrMethod) {
-          addDeclaration(TopLevelDeclarationKind.function, name);
-        } else if (executable.kind == UnlinkedExecutableKind.getter ||
-            executable.kind == UnlinkedExecutableKind.setter) {
-          if (executable.kind == UnlinkedExecutableKind.setter) {
-            name = name.substring(0, name.length - 1);
-          }
-          if (addedVariableNames.add(name)) {
-            addDeclaration(TopLevelDeclarationKind.variable, name);
-          }
-        }
-      }
-      for (UnlinkedVariable variable in unlinked.variables) {
-        String name = variable.name;
-        if (addedVariableNames.add(name)) {
-          addDeclaration(TopLevelDeclarationKind.variable, name);
-        }
-      }
-    }
-    return _topLevelDeclarations;
-  }
-
-  /**
    * Return the set of transitive files - the file itself and all of the
    * directly or indirectly referenced files.
    */
@@ -402,6 +341,11 @@
   UnlinkedUnit get unlinked => _unlinked;
 
   /**
+   * The [UnlinkedUnit2] of the file.
+   */
+  UnlinkedUnit2 get unlinked2 => _unlinked2;
+
+  /**
    * Return the [uri] string.
    */
   String get uriStr => uri.toString();
@@ -434,7 +378,8 @@
         return _parse(errorListener);
       });
     } catch (_) {
-      return _createEmptyCompilationUnit();
+      AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
+      return _createEmptyCompilationUnit(analysisOptions.contextFeatures);
     }
   }
 
@@ -449,6 +394,17 @@
    * Return `true` if the API signature changed since the last refresh.
    */
   bool refresh({bool allowCached: false}) {
+    counterFileStateRefresh++;
+
+    if (_fsState.useSummary2) {
+      return _refresh2(allowCached: allowCached);
+    }
+
+    var timerWasRunning = timerFileStateRefresh.isRunning;
+    if (!timerWasRunning) {
+      timerFileStateRefresh.start();
+    }
+
     _invalidateCurrentUnresolvedData();
 
     {
@@ -485,6 +441,7 @@
                   referencedNames: referencedNames,
                   subtypedNames: subtypedNames)
               .toBuffer();
+          counterUnlinkedLinkedBytes += bytes.length;
           _fsState._byteStore.put(_unlinkedKey, bytes);
         });
       }
@@ -514,10 +471,6 @@
           library.libraryCycle?.invalidate();
         }
       }
-
-      for (FileState file in _fsState._uriToFile.values) {
-        file._exportedTopLevelDeclarations = null;
-      }
     }
 
     // This file is potentially not a library for its previous parts anymore.
@@ -573,79 +526,21 @@
       files.add(this);
     }
 
+    if (!timerWasRunning) {
+      timerFileStateRefresh.stop();
+    }
+
     // Return whether the API signature changed.
     return apiSignatureChanged;
   }
 
   @override
-  String toString() => path;
+  String toString() => path ?? '<unresolved>';
 
-  /**
-   * Compute the full or partial map of exported declarations for this library.
-   */
-  _ExportedDeclarations _computeExportedDeclarations() {
-    // If we know exported declarations, return them.
-    if (_exportedTopLevelDeclarations != null) {
-      return new _ExportedDeclarations(0, _exportedTopLevelDeclarations);
-    }
-
-    // If we are already computing exported declarations for this library,
-    // report that we found a cycle.
-    if (_exportDeclarationsId != 0) {
-      return new _ExportedDeclarations(_exportDeclarationsId, null);
-    }
-
-    var declarations = <String, TopLevelDeclaration>{};
-
-    // Give each library a unique identifier.
-    _exportDeclarationsId = _exportDeclarationsNextId++;
-
-    // Append the exported declarations.
-    int firstCycleId = 0;
-    for (int i = 0; i < _exportedFiles.length; i++) {
-      var exported = _exportedFiles[i]._computeExportedDeclarations();
-      if (exported.declarations != null) {
-        for (TopLevelDeclaration t in exported.declarations.values) {
-          if (_exportFilters[i].accepts(t.name)) {
-            declarations[t.name] = t;
-          }
-        }
-      }
-      if (exported.firstCycleId > 0) {
-        if (firstCycleId == 0 || firstCycleId > exported.firstCycleId) {
-          firstCycleId = exported.firstCycleId;
-        }
-      }
-    }
-
-    // If this library is the first component of the cycle, then we are at
-    // the beginning of this cycle, and combination of partial export
-    // namespaces of other exported libraries and declarations of this library
-    // is the full export namespace of this library.
-    if (firstCycleId != 0 && firstCycleId == _exportDeclarationsId) {
-      firstCycleId = 0;
-    }
-
-    // We're done with this library, successfully or not.
-    _exportDeclarationsId = 0;
-
-    // Append the library declarations.
-    for (FileState file in libraryFiles) {
-      declarations.addAll(file.topLevelDeclarations);
-    }
-
-    // Record the declarations only if it is the full result.
-    if (firstCycleId == 0) {
-      _exportedTopLevelDeclarations = declarations;
-    }
-
-    // Return the full or partial result.
-    return new _ExportedDeclarations(firstCycleId, declarations);
-  }
-
-  CompilationUnit _createEmptyCompilationUnit() {
+  CompilationUnit _createEmptyCompilationUnit(FeatureSet featureSet) {
     var token = new Token.eof(0);
-    return astFactory.compilationUnit(token, null, [], [], token)
+    return astFactory.compilationUnit2(
+        beginToken: token, endToken: token, featureSet: featureSet)
       ..lineInfo = new LineInfo(const <int>[0]);
   }
 
@@ -677,7 +572,6 @@
     _definedTopLevelNames = null;
     _definedClassMemberNames = null;
     _referencedNames = null;
-    _topLevelDeclarations = null;
 
     if (_driverUnlinkedUnit != null) {
       for (var name in _driverUnlinkedUnit.subtypedNames) {
@@ -688,28 +582,27 @@
   }
 
   CompilationUnit _parse(AnalysisErrorListener errorListener) {
+    AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
+    FeatureSet featureSet = analysisOptions.contextFeatures;
     if (source == null) {
-      return _createEmptyCompilationUnit();
+      return _createEmptyCompilationUnit(featureSet);
     }
 
-    AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
-    ExperimentStatus experimentStatus = analysisOptions.experimentStatus;
     CharSequenceReader reader = new CharSequenceReader(content);
-    Scanner scanner = new Scanner(source, reader, errorListener);
-    scanner.enableGtGtGt = experimentStatus.triple_shift;
+    Scanner scanner = new Scanner(source, reader, errorListener)
+      ..configureFeatures(featureSet);
     Token token = PerformanceStatistics.scan.makeCurrentWhile(() {
-      return scanner.tokenize();
+      return scanner.tokenize(reportScannerErrors: false);
     });
     LineInfo lineInfo = new LineInfo(scanner.lineStarts);
 
     bool useFasta = analysisOptions.useFastaParser;
-    Parser parser = new Parser(source, errorListener, useFasta: useFasta);
+    // Pass the feature set from the scanner to the parser
+    // because the scanner may have detected a language version comment
+    // and downgraded the feature set it holds.
+    Parser parser = new Parser(source, errorListener,
+        featureSet: scanner.featureSet, useFasta: useFasta);
     parser.enableOptionalNewAndConst = true;
-    parser.enableNonNullable = experimentStatus.non_nullable;
-    parser.enableSpreadCollections = experimentStatus.spread_collections;
-    parser.enableControlFlowCollections =
-        experimentStatus.control_flow_collections;
-    parser.enableTripleShift = experimentStatus.triple_shift;
     CompilationUnit unit = parser.parseCompilationUnit(token);
     unit.lineInfo = lineInfo;
 
@@ -720,6 +613,174 @@
     return unit;
   }
 
+  bool _refresh2({bool allowCached: false}) {
+    var timerWasRunning = timerFileStateRefresh.isRunning;
+    if (!timerWasRunning) {
+      timerFileStateRefresh.start();
+    }
+
+    _invalidateCurrentUnresolvedData();
+
+    {
+      var rawFileState = _fsState._fileContentCache.get(path, allowCached);
+      _content = rawFileState.content;
+      _exists = rawFileState.exists;
+      _contentHash = rawFileState.contentHash;
+    }
+
+    // Prepare the unlinked bundle key.
+    List<int> contentSignature;
+    {
+      var signature = new ApiSignature();
+      signature.addUint32List(_fsState._unlinkedSalt);
+      signature.addString(_contentHash);
+      signature.addBool(_exists);
+      contentSignature = signature.toByteList();
+      _unlinkedKey = '${hex.encode(contentSignature)}.unlinked2';
+    }
+
+    // Prepare bytes of the unlinked bundle - existing or new.
+    List<int> bytes;
+    {
+      bytes = _fsState._byteStore.get(_unlinkedKey);
+      if (bytes == null || bytes.isEmpty) {
+        CompilationUnit unit = parse();
+        _fsState._logger.run('Create unlinked for $path', () {
+          var unlinkedUnit = serializeAstUnlinked2(unit);
+          var definedNames = computeDefinedNames(unit);
+          var referencedNames = computeReferencedNames(unit).toList();
+          var subtypedNames = computeSubtypedNames(unit).toList();
+          bytes = new AnalysisDriverUnlinkedUnitBuilder(
+            unit2: unlinkedUnit,
+            definedTopLevelNames: definedNames.topLevelNames.toList(),
+            definedClassMemberNames: definedNames.classMemberNames.toList(),
+            referencedNames: referencedNames,
+            subtypedNames: subtypedNames,
+          ).toBuffer();
+          _fsState._byteStore.put(_unlinkedKey, bytes);
+        });
+      }
+    }
+
+    // Read the unlinked bundle.
+    _driverUnlinkedUnit = new AnalysisDriverUnlinkedUnit.fromBuffer(bytes);
+    _unlinked2 = _driverUnlinkedUnit.unit2;
+    _lineInfo = new LineInfo(_unlinked2.lineStarts);
+
+    // Prepare API signature.
+    var newApiSignature = new Uint8List.fromList(_unlinked2.apiSignature);
+    bool apiSignatureChanged = _apiSignature != null &&
+        !_equalByteLists(_apiSignature, newApiSignature);
+    _apiSignature = newApiSignature;
+
+    // The API signature changed.
+    //   Flush affected library cycles.
+    //   Flush exported top-level declarations of all files.
+    if (apiSignatureChanged) {
+      _libraryCycle?.invalidate();
+
+      // If this is a part, invalidate the libraries.
+      var libraries = _fsState._partToLibraries[this];
+      if (libraries != null) {
+        for (var library in libraries) {
+          library.libraryCycle?.invalidate();
+        }
+      }
+    }
+
+    // This file is potentially not a library for its previous parts anymore.
+    if (_partedFiles != null) {
+      for (FileState part in _partedFiles) {
+        _fsState._partToLibraries[part]?.remove(this);
+      }
+    }
+
+    // Build the graph.
+    _importedFiles = <FileState>[];
+    _exportedFiles = <FileState>[];
+    _partedFiles = <FileState>[];
+    _exportFilters = <NameFilter>[];
+    for (var uri in _unlinked2.imports) {
+      var file = _fileForRelativeUri(uri);
+      _importedFiles.add(file);
+    }
+    for (var uri in _unlinked2.exports) {
+      var file = _fileForRelativeUri(uri);
+      _exportedFiles.add(file);
+      // TODO(scheglov) implement
+      _exportFilters.add(NameFilter.identity);
+    }
+    for (var uri in _unlinked2.parts) {
+      var file = _fileForRelativeUri(uri);
+      _partedFiles.add(file);
+      _fsState._partToLibraries
+          .putIfAbsent(file, () => <FileState>[])
+          .add(this);
+    }
+    _libraryFiles = [this]..addAll(_partedFiles);
+
+    // Compute referenced files.
+    _directReferencedFiles = new Set<FileState>()
+      ..addAll(_importedFiles)
+      ..addAll(_exportedFiles)
+      ..addAll(_partedFiles);
+    _directReferencedLibraries = Set<FileState>()
+      ..addAll(_importedFiles)
+      ..addAll(_exportedFiles);
+
+    // Update mapping from subtyped names to files.
+    for (var name in _driverUnlinkedUnit.subtypedNames) {
+      var files = _fsState._subtypedNameToFiles[name];
+      if (files == null) {
+        files = new Set<FileState>();
+        _fsState._subtypedNameToFiles[name] = files;
+      }
+      files.add(this);
+    }
+
+    if (!timerWasRunning) {
+      timerFileStateRefresh.stop();
+    }
+
+    // Return whether the API signature changed.
+    return apiSignatureChanged;
+  }
+
+  static UnlinkedUnit2Builder serializeAstUnlinked2(CompilationUnit unit) {
+    var exports = <String>[];
+    var imports = <String>['dart:core'];
+    var parts = <String>[];
+    var hasLibraryDirective = false;
+    var hasPartOfDirective = false;
+    for (var directive in unit.directives) {
+      if (directive is ExportDirective) {
+        var uriStr = directive.uri.stringValue;
+        exports.add(uriStr ?? '');
+      } else if (directive is ImportDirective) {
+        var uriStr = directive.uri.stringValue;
+        imports.add(uriStr ?? '');
+      } else if (directive is LibraryDirective) {
+        hasLibraryDirective = true;
+      } else if (directive is PartDirective) {
+        var uriStr = directive.uri.stringValue;
+        parts.add(uriStr ?? '');
+      } else if (directive is PartOfDirective) {
+        hasPartOfDirective = true;
+      }
+    }
+    var informativeData = createInformativeData(unit);
+    return UnlinkedUnit2Builder(
+      apiSignature: computeUnlinkedApiSignature(unit),
+      exports: exports,
+      imports: imports,
+      parts: parts,
+      hasLibraryDirective: hasLibraryDirective,
+      hasPartOfDirective: hasPartOfDirective,
+      lineStarts: unit.lineInfo.lineStarts,
+      informativeData: informativeData,
+    );
+  }
+
   /**
    * Return `true` if the given byte lists are equal.
    */
@@ -762,6 +823,7 @@
   final AnalysisOptions _analysisOptions;
   final Uint32List _unlinkedSalt;
   final Uint32List _linkedSalt;
+  final bool useSummary2;
 
   /**
    * The optional store with externally provided unlinked and corresponding
@@ -842,6 +904,7 @@
     this._unlinkedSalt,
     this._linkedSalt, {
     this.externalSummaries,
+    this.useSummary2 = false,
   }) {
     _fileContentCache = _FileContentCache.getInstance(
       _resourceProvider,
@@ -1040,23 +1103,6 @@
         .where((f) => f._libraryCycle == null)
         .toSet();
   }
-
-  Set<FileState> get librariesWithComputedExportedDeclarations {
-    return state._uriToFile.values
-        .where((f) => !f.isPart && f._exportedTopLevelDeclarations != null)
-        .toSet();
-  }
-}
-
-/**
- * The result of computing exported top-level declarations.
- * It can be full (when [firstCycleId] is zero), or partial (when a cycle)
- */
-class _ExportedDeclarations {
-  final int firstCycleId;
-  final Map<String, TopLevelDeclaration> declarations;
-
-  _ExportedDeclarations(this.firstCycleId, this.declarations);
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 61b116e..1c23029 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -487,6 +487,14 @@
             element.enclosingElement.isSynthetic)) {
       return;
     }
+    // Elements for generic function types are enclosed by the compilation
+    // units, but don't have names. So, we cannot index references to their
+    // named parameters. Ignore them.
+    if (elementKind == ElementKind.PARAMETER &&
+        element is ParameterElement &&
+        element.enclosingElement is GenericFunctionTypeElement) {
+      return;
+    }
     // Add the relation.
     assembler.addElementRelation(element, kind, offset, length, isQualified);
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index abea6f05..f3b0f77 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -32,9 +33,17 @@
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:analyzer/src/lint/linter_visitor.dart';
 import 'package:analyzer/src/services/lint.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:pub_semver/pub_semver.dart';
 
+var timerLibraryAnalyzer = Stopwatch();
+var timerLibraryAnalyzerConst = Stopwatch();
+var timerLibraryAnalyzerFreshUnit = Stopwatch();
+var timerLibraryAnalyzerResolve = Stopwatch();
+var timerLibraryAnalyzerSplicer = Stopwatch();
+var timerLibraryAnalyzerVerify = Stopwatch();
+
 /**
  * Analyzer of a single library.
  */
@@ -53,10 +62,10 @@
   final bool Function(Uri) _isLibraryUri;
   final AnalysisContext _context;
   final ElementResynthesizer _resynthesizer;
-  final TypeProvider _typeProvider;
+  final LinkedElementFactory _elementFactory;
+  TypeProvider _typeProvider;
 
   final TypeSystem _typeSystem;
-  bool isNonNullableLibrary = false;
   LibraryElement _libraryElement;
 
   LibraryScope _libraryScope;
@@ -85,11 +94,11 @@
       this._isLibraryUri,
       this._context,
       this._resynthesizer,
+      this._elementFactory,
       this._inheritance,
       this._library,
       this._resourceProvider)
-      : _typeProvider = _context.typeProvider,
-        _typeSystem = _context.typeSystem;
+      : _typeSystem = _context.typeSystem;
 
   /**
    * Compute analysis results for all units of the library.
@@ -104,36 +113,57 @@
    * Compute analysis results for all units of the library.
    */
   Map<FileState, UnitAnalysisResult> analyzeSync() {
+    timerLibraryAnalyzer.start();
     Map<FileState, CompilationUnit> units = {};
 
     // Parse all files.
+    timerLibraryAnalyzerFreshUnit.start();
     for (FileState file in _library.libraryFiles) {
       units[file] = _parse(file);
     }
-    // TODO(danrubel): Verify that all units are either nullable or non-nullable
-    isNonNullableLibrary =
-        (units.values.first as CompilationUnitImpl).isNonNullable;
+    timerLibraryAnalyzerFreshUnit.stop();
 
     // Resolve URIs in directives to corresponding sources.
+    FeatureSet featureSet = units[_library].featureSet;
+    _typeProvider = _context.typeProvider;
+    if (featureSet.isEnabled(Feature.non_nullable)) {
+      if (_typeProvider is! NonNullableTypeProvider) {
+        _typeProvider = NonNullableTypeProvider.from(_typeProvider);
+      }
+    } else {
+      if (_typeProvider is NonNullableTypeProvider) {
+        _typeProvider = TypeProviderImpl.from(_typeProvider);
+      }
+    }
     units.forEach((file, unit) {
+      _validateFeatureSet(unit, featureSet);
       _resolveUriBasedDirectives(file, unit);
     });
 
-    _libraryElement = _resynthesizer
-        .getElement(new ElementLocationImpl.con3([_library.uriStr]));
+    if (_elementFactory != null) {
+      _libraryElement = _elementFactory.libraryOfUri(_library.uriStr);
+    } else {
+      _libraryElement = _resynthesizer
+          .getElement(new ElementLocationImpl.con3([_library.uriStr]));
+    }
     _libraryScope = new LibraryScope(_libraryElement);
 
+    timerLibraryAnalyzerResolve.start();
     _resolveDirectives(units);
 
     units.forEach((file, unit) {
       _resolveFile(file, unit);
       _computePendingMissingRequiredParameters(file, unit);
     });
+    timerLibraryAnalyzerResolve.stop();
 
+    timerLibraryAnalyzerConst.start();
     units.values.forEach(_findConstants);
     _clearConstantEvaluationResults();
     _computeConstants();
+    timerLibraryAnalyzerConst.stop();
 
+    timerLibraryAnalyzerVerify.start();
     PerformanceStatistics.errors.makeCurrentWhile(() {
       units.forEach((file, unit) {
         _computeVerifyErrors(file, unit);
@@ -171,6 +201,7 @@
         }
       });
     }
+    timerLibraryAnalyzerVerify.stop();
 
     // Return full results.
     Map<FileState, UnitAnalysisResult> results = {};
@@ -179,6 +210,7 @@
       errors = _filterIgnoredErrors(file, errors);
       results[file] = new UnitAnalysisResult(file, unit, errors);
     });
+    timerLibraryAnalyzer.stop();
     return results;
   }
 
@@ -204,7 +236,7 @@
       ErrorReporter errorReporter, CompilationUnit unit) {
     ConstantVerifier constantVerifier = new ConstantVerifier(
         errorReporter, _libraryElement, _typeProvider, _declaredVariables,
-        forAnalysisDriver: true);
+        featureSet: unit.featureSet, forAnalysisDriver: true);
     unit.accept(constantVerifier);
   }
 
@@ -231,7 +263,7 @@
       errorListener.onError(pendingError.toAnalysisError());
     }
 
-    unit.accept(new DeadCodeVerifier(errorReporter, isNonNullableLibrary,
+    unit.accept(new DeadCodeVerifier(errorReporter, unit.featureSet,
         typeSystem: _context.typeSystem));
 
     // Dart2js analysis.
@@ -240,7 +272,7 @@
     }
 
     unit.accept(new BestPracticesVerifier(
-        errorReporter, _typeProvider, _libraryElement,
+        errorReporter, _typeProvider, _libraryElement, unit, file.content,
         typeSystem: _context.typeSystem,
         resourceProvider: _resourceProvider,
         analysisOptions: _context.analysisOptions));
@@ -623,7 +655,9 @@
       }
     }
 
+    timerLibraryAnalyzerSplicer.start();
     new DeclarationResolver().resolve(unit, unitElement);
+    timerLibraryAnalyzerSplicer.stop();
 
     unit.accept(new AstRewriteVisitor(_context.typeSystem, _libraryElement,
         source, _typeProvider, errorListener,
@@ -631,28 +665,33 @@
 
     // TODO(scheglov) remove EnumMemberBuilder class
 
-    new TypeParameterBoundsResolver(
-            _context.typeSystem, _libraryElement, source, errorListener,
-            isNonNullableUnit: isNonNullableLibrary)
+    new TypeParameterBoundsResolver(_context.typeSystem, _libraryElement,
+            source, errorListener, unit.featureSet)
         .resolveTypeBounds(unit);
 
     unit.accept(new TypeResolverVisitor(
         _libraryElement, source, _typeProvider, errorListener,
-        isNonNullableUnit: isNonNullableLibrary));
+        featureSet: unit.featureSet));
 
     unit.accept(new VariableResolverVisitor(
         _libraryElement, source, _typeProvider, errorListener,
         nameScope: _libraryScope));
 
-    unit.accept(new PartialResolverVisitor(_inheritance, _libraryElement,
-        source, _typeProvider, AnalysisErrorListener.NULL_LISTENER));
+    unit.accept(new PartialResolverVisitor(
+        _inheritance,
+        _libraryElement,
+        source,
+        _typeProvider,
+        AnalysisErrorListener.NULL_LISTENER,
+        unit.featureSet));
 
     // Nothing for RESOLVED_UNIT8?
     // Nothing for RESOLVED_UNIT9?
     // Nothing for RESOLVED_UNIT10?
 
     unit.accept(new ResolverVisitor(
-        _inheritance, _libraryElement, source, _typeProvider, errorListener));
+        _inheritance, _libraryElement, source, _typeProvider, errorListener,
+        featureSet: unit.featureSet));
   }
 
   /**
@@ -697,6 +736,15 @@
     }
   }
 
+  /// Validate that the feature set associated with the compilation [unit] is
+  /// the same as the [expectedSet] of features supported by the library.
+  void _validateFeatureSet(CompilationUnit unit, FeatureSet expectedSet) {
+    FeatureSet actualSet = unit.featureSet;
+    if (actualSet != expectedSet) {
+      // TODO(brianwilkerson) Generate a diagnostic.
+    }
+  }
+
   /**
    * Check the given [directive] to see if the referenced source exists and
    * report an error if it does not.
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 0be1dab..8f90231 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -9,8 +9,10 @@
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
+import 'package:analyzer/src/dart/analysis/library_graph.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/generated/engine.dart'
@@ -22,8 +24,20 @@
 import 'package:analyzer/src/summary/link.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
+import 'package:analyzer/src/summary2/link.dart' as link2;
+import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
+import 'package:analyzer/src/summary2/reference.dart';
 import 'package:meta/meta.dart';
 
+var counterLinkedLibraries = 0;
+var counterLoadedLibraries = 0;
+var timerBundleToBytes = Stopwatch();
+var timerInputLibraries = Stopwatch();
+var timerLinking = Stopwatch();
+var timerLoad2 = Stopwatch();
+
 /**
  * Context information necessary to analyze one or more libraries within an
  * [AnalysisDriver].
@@ -35,6 +49,8 @@
 
   final PerformanceLog logger;
   final ByteStore byteStore;
+  final AnalysisSession analysisSession;
+  final SummaryDataStore externalSummaries;
   final SummaryDataStore store = new SummaryDataStore([]);
 
   /// The size of the linked data that is loaded by this context.
@@ -44,8 +60,11 @@
 
   RestrictedAnalysisContext analysisContext;
   SummaryResynthesizer resynthesizer;
+  LinkedElementFactory elementFactory;
   InheritanceManager2 inheritanceManager;
 
+  var loadedBundles = Set<LibraryCycle>.identity();
+
   LibraryContext({
     @required AnalysisSession session,
     @required PerformanceLog logger,
@@ -54,27 +73,35 @@
     @required AnalysisOptions analysisOptions,
     @required DeclaredVariables declaredVariables,
     @required SourceFactory sourceFactory,
-    @required SummaryDataStore externalSummaries,
+    @required this.externalSummaries,
     @required FileState targetLibrary,
+    @required bool useSummary2,
   })  : this.logger = logger,
-        this.byteStore = byteStore {
+        this.byteStore = byteStore,
+        this.analysisSession = session {
     if (externalSummaries != null) {
       store.addStore(externalSummaries);
     }
 
+    var synchronousSession =
+        SynchronousSession(analysisOptions, declaredVariables);
     analysisContext = new RestrictedAnalysisContext(
-      analysisOptions,
-      declaredVariables,
+      synchronousSession,
       sourceFactory,
     );
 
-    // Fill the store with summaries required for the initial library.
-    load(targetLibrary);
+    if (useSummary2) {
+      _createElementFactory();
+      load2(targetLibrary);
+    } else {
+      // Fill the store with summaries required for the initial library.
+      load(targetLibrary);
 
-    resynthesizer = new StoreBasedSummaryResynthesizer(
-        analysisContext, session, sourceFactory, true, store);
-    analysisContext.typeProvider = resynthesizer.typeProvider;
-    resynthesizer.finishCoreAsyncLibraries();
+      resynthesizer = new StoreBasedSummaryResynthesizer(
+          analysisContext, session, sourceFactory, true, store);
+      analysisContext.typeProvider = resynthesizer.typeProvider;
+      resynthesizer.finishCoreAsyncLibraries();
+    }
 
     inheritanceManager = new InheritanceManager2(analysisContext.typeSystem);
   }
@@ -88,10 +115,18 @@
    * Computes a [CompilationUnitElement] for the given library/unit pair.
    */
   CompilationUnitElement computeUnitElement(FileState library, FileState unit) {
-    return resynthesizer.getElement(new ElementLocationImpl.con3(<String>[
-      library.uriStr,
-      unit.uriStr,
-    ]));
+    if (elementFactory != null) {
+      var reference = elementFactory.rootReference
+          .getChild(library.uriStr)
+          .getChild('@unit')
+          .getChild(unit.uriStr);
+      return elementFactory.elementOfReference(reference);
+    } else {
+      return resynthesizer.getElement(new ElementLocationImpl.con3(<String>[
+        library.uriStr,
+        unit.uriStr,
+      ]));
+    }
   }
 
   /**
@@ -106,16 +141,26 @@
    */
   bool isLibraryUri(Uri uri) {
     String uriStr = uri.toString();
-    return store.unlinkedMap[uriStr]?.isPartOf == false;
+    if (elementFactory != null) {
+      return elementFactory.isLibraryUri(uriStr);
+    } else {
+      return store.unlinkedMap[uriStr]?.isPartOf == false;
+    }
   }
 
   /// Load data required to access elements of the given [targetLibrary].
   void load(FileState targetLibrary) {
+    if (AnalysisDriver.useSummary2) {
+      throw StateError('Unexpected with summary2.');
+    }
+
     // The library is already a part of the context, nothing to do.
     if (store.linkedMap.containsKey(targetLibrary.uriStr)) {
       return;
     }
 
+    timerLoad2.start();
+
     var libraries = <String, FileState>{};
     void appendLibraryFiles(FileState library) {
       // Stop if this library is already a part of the context.
@@ -163,8 +208,10 @@
       }
       int numOfLoaded = libraries.length - libraryUrisToLink.length;
       logger.writeln('Loaded $numOfLoaded linked bundles.');
+      counterLoadedLibraries += numOfLoaded;
     });
 
+    timerLinking.start();
     var linkedLibraries = <String, LinkedLibraryBuilder>{};
     logger.run('Link libraries', () {
       linkedLibraries = link(libraryUrisToLink, (String uri) {
@@ -176,21 +223,149 @@
       }, DeclaredVariables(), analysisContext.analysisOptions);
       logger.writeln('Linked ${linkedLibraries.length} libraries.');
     });
+    timerLinking.stop();
+    counterLinkedLibraries += linkedLibraries.length;
 
     // Store freshly linked libraries into the byte store.
     // Append them to the context.
+    timerBundleToBytes.start();
     for (String uri in linkedLibraries.keys) {
+      counterLoadedLibraries++;
       FileState library = libraries[uri];
       String key = library.transitiveSignatureLinked;
 
+      timerBundleToBytes.start();
       LinkedLibraryBuilder linkedBuilder = linkedLibraries[uri];
       List<int> bytes = linkedBuilder.toBuffer();
+      timerBundleToBytes.stop();
       byteStore.put(key, bytes);
+      counterUnlinkedLinkedBytes += bytes.length;
 
       LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes);
       store.addLinkedLibrary(uri, linked);
       _linkedDataInBytes += bytes.length;
     }
+    timerBundleToBytes.stop();
+    timerLoad2.stop();
+  }
+
+  /// Load data required to access elements of the given [targetLibrary].
+  void load2(FileState targetLibrary) {
+    timerLoad2.start();
+    var inputBundles = <LinkedNodeBundle>[];
+
+    var librariesTotal = 0;
+    var librariesLoaded = 0;
+    var librariesLinked = 0;
+    var librariesLinkedTimer = Stopwatch();
+    var inputsTimer = Stopwatch();
+    var bytesGet = 0;
+    var bytesPut = 0;
+
+    void loadBundle(LibraryCycle cycle) {
+      if (!loadedBundles.add(cycle)) return;
+
+      librariesTotal += cycle.libraries.length;
+
+      cycle.directDependencies.forEach(loadBundle);
+
+      var key = cycle.transitiveSignature + '.linked_bundle';
+      var bytes = byteStore.get(key);
+
+      if (bytes == null) {
+        librariesLinkedTimer.start();
+
+        timerInputLibraries.start();
+        inputsTimer.start();
+        var inputLibraries = <link2.LinkInputLibrary>[];
+        for (var libraryFile in cycle.libraries) {
+          var librarySource = libraryFile.source;
+          if (librarySource == null) continue;
+
+          var inputUnits = <link2.LinkInputUnit>[];
+          for (var file in libraryFile.libraryFiles) {
+            var isSynthetic = !file.exists;
+            var unit = file.parse();
+            inputUnits.add(
+              link2.LinkInputUnit(file.source, isSynthetic, unit),
+            );
+          }
+
+          inputLibraries.add(
+            link2.LinkInputLibrary(librarySource, inputUnits),
+          );
+        }
+        inputsTimer.stop();
+        timerInputLibraries.stop();
+
+        timerLinking.start();
+        var linkResult = link2.link(elementFactory, inputLibraries);
+        librariesLinked += cycle.libraries.length;
+        counterLinkedLibraries += linkResult.bundle.libraries.length;
+        timerLinking.stop();
+
+        timerBundleToBytes.start();
+        bytes = linkResult.bundle.toBuffer();
+        timerBundleToBytes.stop();
+
+        byteStore.put(key, bytes);
+        bytesPut += bytes.length;
+        counterUnlinkedLinkedBytes += bytes.length;
+
+        librariesLinkedTimer.stop();
+      } else {
+        // TODO(scheglov) Take / clear parsed units in files.
+        bytesGet += bytes.length;
+        librariesLoaded += cycle.libraries.length;
+      }
+
+      // We are about to load dart:core, but if we have just linked it, the
+      // linker might have set the type provider. So, clear it, and recreate
+      // the element factory - it is empty anyway.
+      var hasDartCoreBeforeBundle = elementFactory.hasDartCore;
+      if (!hasDartCoreBeforeBundle) {
+        analysisContext.clearTypeProvider();
+        _createElementFactory();
+      }
+
+      var bundle = LinkedNodeBundle.fromBuffer(bytes);
+      inputBundles.add(bundle);
+      elementFactory.addBundle(
+        LinkedBundleContext(elementFactory, bundle),
+      );
+      counterLoadedLibraries += bundle.libraries.length;
+
+      // Set informative data.
+      for (var libraryFile in cycle.libraries) {
+        for (var unitFile in libraryFile.libraryFiles) {
+          elementFactory.setInformativeData(
+            libraryFile.uriStr,
+            unitFile.uriStr,
+            unitFile.unlinked2.informativeData,
+          );
+        }
+      }
+
+      // If the first bundle, with dart:core, create the type provider.
+      if (!hasDartCoreBeforeBundle && elementFactory.hasDartCore) {
+        _createElementFactoryTypeProvider();
+      }
+    }
+
+    logger.run('Prepare linked bundles', () {
+      var libraryCycle = targetLibrary.libraryCycle;
+      loadBundle(libraryCycle);
+      logger.writeln(
+        '[librariesTotal: $librariesTotal]'
+        '[librariesLoaded: $librariesLoaded]'
+        '[inputsTimer: ${inputsTimer.elapsedMilliseconds} ms]'
+        '[librariesLinked: $librariesLinked]'
+        '[librariesLinkedTimer: ${librariesLinkedTimer.elapsedMilliseconds} ms]'
+        '[bytesGet: $bytesGet][bytesPut: $bytesPut]',
+      );
+    });
+
+    timerLoad2.stop();
   }
 
   /// Return `true` if this context grew too large, and should be recreated.
@@ -201,4 +376,31 @@
   bool pack() {
     return _linkedDataInBytes > _maxLinkedDataInBytes;
   }
+
+  void _createElementFactory() {
+    elementFactory = LinkedElementFactory(
+      analysisContext,
+      analysisSession,
+      Reference.root(),
+    );
+    if (externalSummaries != null) {
+      for (var bundle in externalSummaries.bundles) {
+        elementFactory.addBundle(
+          LinkedBundleContext(elementFactory, bundle.bundle2),
+        );
+      }
+    }
+  }
+
+  void _createElementFactoryTypeProvider() {
+    var dartCore = elementFactory.libraryOfUri('dart:core');
+    var dartAsync = elementFactory.libraryOfUri('dart:async');
+    var typeProvider = SummaryTypeProvider()
+      ..initializeCore(dartCore)
+      ..initializeAsync(dartAsync);
+    analysisContext.typeProvider = typeProvider;
+
+    dartCore.createLoadLibraryFunction(typeProvider);
+    dartAsync.createLoadLibraryFunction(typeProvider);
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
index 7b0bcaf..3e79078 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/src/summary/api_signature.dart';
 import 'package:analyzer/src/summary/link.dart' as graph
     show DependencyWalker, Node;
-import 'package:meta/meta.dart';
 
 /// Ensure that the [FileState.libraryCycle] for the [file] and anything it
 /// depends on is computed.
@@ -23,7 +22,6 @@
   final List<FileState> libraries = [];
 
   /// The library cycles that this cycle references directly.
-  @visibleForTesting
   final Set<LibraryCycle> directDependencies = new Set<LibraryCycle>();
 
   /// The cycles that use this cycle, used to [invalidate] transitively.
@@ -35,11 +33,11 @@
   /// transitive signatures of the cycles that the [libraries] reference
   /// directly.  So, indirectly it is based on the transitive closure of all
   /// files that [libraries] reference (but we don't compute these files).
-  String _transitiveSignature;
+  String transitiveSignature;
 
   /// The map from a library in [libraries] to its transitive signature.
   ///
-  /// It is almost the same as [_transitiveSignature], but is also based on
+  /// It is almost the same as [transitiveSignature], but is also based on
   /// the URI of this specific library.  Currently we store each linked library
   /// with its own key, so we need unique keys.  However practically we never
   /// can use just *one* library of a cycle, we always use the whole cycle.
@@ -49,7 +47,7 @@
 
   LibraryCycle();
 
-  LibraryCycle.external() : _transitiveSignature = '<external>';
+  LibraryCycle.external() : transitiveSignature = '<external>';
 
   /// Invalidate this cycle and any cycles that directly or indirectly use it.
   ///
@@ -125,6 +123,8 @@
     for (var node in scc) {
       cycle.libraries.add(node.file);
 
+      signature.addString(node.file.uriStr);
+
       signature.addInt(node.file.libraryFiles.length);
       for (var file in node.file.libraryFiles) {
         signature.addBytes(file.apiSignature);
@@ -132,13 +132,13 @@
     }
 
     // Compute the general library cycle signature.
-    cycle._transitiveSignature = signature.toHex();
+    cycle.transitiveSignature = signature.toHex();
 
     // Compute library specific signatures.
     for (var node in scc) {
       var librarySignatureBuilder = new ApiSignature()
         ..addString(node.file.uriStr)
-        ..addString(cycle._transitiveSignature);
+        ..addString(cycle.transitiveSignature);
       var librarySignature = librarySignatureBuilder.toHex();
 
       node.file.internal_setLibraryCycle(
@@ -166,7 +166,7 @@
 
       if (cycle.directDependencies.add(referencedCycle)) {
         referencedCycle._directUsers.add(cycle);
-        signature.addString(referencedCycle._transitiveSignature);
+        signature.addString(referencedCycle.transitiveSignature);
       }
     }
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/restricted_analysis_context.dart b/pkg/analyzer/lib/src/dart/analysis/restricted_analysis_context.dart
index a68cdcd..60b7db7 100644
--- a/pkg/analyzer/lib/src/dart/analysis/restricted_analysis_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/restricted_analysis_context.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -14,42 +15,36 @@
 /// functionality (which is task based), except what we intend to expose
 /// through the new API.
 class RestrictedAnalysisContext implements AnalysisContextImpl {
-  @override
-  final AnalysisOptionsImpl analysisOptions;
-
-  @override
-  final DeclaredVariables declaredVariables;
+  final SynchronousSession synchronousSession;
 
   @override
   final SourceFactory sourceFactory;
 
-  TypeProvider _typeProvider;
-
-  TypeSystem _typeSystem;
-
-  RestrictedAnalysisContext(
-      this.analysisOptions, this.declaredVariables, this.sourceFactory);
+  RestrictedAnalysisContext(this.synchronousSession, this.sourceFactory);
 
   @override
-  TypeProvider get typeProvider => _typeProvider;
+  AnalysisOptionsImpl get analysisOptions => synchronousSession.analysisOptions;
+
+  @override
+  DeclaredVariables get declaredVariables =>
+      synchronousSession.declaredVariables;
+
+  @override
+  TypeProvider get typeProvider => synchronousSession.typeProvider;
 
   @override
   set typeProvider(TypeProvider typeProvider) {
-    if (_typeProvider != null) {
-      throw StateError('TypeProvider can be set only once.');
-    }
-    _typeProvider = typeProvider;
+    synchronousSession.typeProvider = typeProvider;
   }
 
   @override
-  TypeSystem get typeSystem {
-    return _typeSystem ??= Dart2TypeSystem(
-      typeProvider,
-      implicitCasts: analysisOptions.implicitCasts,
-    );
-  }
+  TypeSystem get typeSystem => synchronousSession.typeSystem;
 
   noSuchMethod(Invocation invocation) {
     return super.noSuchMethod(invocation);
   }
+
+  void clearTypeProvider() {
+    synchronousSession.clearTypeProvider();
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 908cc96..dd29d9d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -133,10 +133,13 @@
   Future<List<Declaration>> declarations(
       RegExp regExp, int maxResults, LinkedHashSet<String> files,
       {String onlyForFile}) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     List<Declaration> declarations = <Declaration>[];
 
+    // TODO(scheglov) Not implemented.
+    if (AnalysisDriver.useSummary2) {
+      return declarations;
+    }
+
     DeclarationKind getExecutableKind(
         UnlinkedExecutable executable, bool topLevel) {
       switch (executable.kind) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 6ff7f8f..376e315 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -12,43 +12,29 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' as driver;
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/dart/analysis/uri_converter.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 
-/**
- * A concrete implementation of an analysis session.
- */
+/// A concrete implementation of an analysis session.
 class AnalysisSessionImpl implements AnalysisSession {
-  /**
-   * The analysis driver performing analysis for this session.
-   */
+  /// The analysis driver performing analysis for this session.
   final driver.AnalysisDriver _driver;
 
-  /**
-   * The type provider being used by the analysis driver.
-   */
+  /// The type provider being used by the analysis driver.
   TypeProvider _typeProvider;
 
-  /**
-   * The type system being used by the analysis driver.
-   */
+  /// The type system being used by the analysis driver.
   TypeSystem _typeSystem;
 
-  /**
-   * The URI converter used to convert between URI's and file paths.
-   */
+  /// The URI converter used to convert between URI's and file paths.
   UriConverter _uriConverter;
 
-  /**
-   * The cache of libraries for URIs.
-   */
+  /// The cache of libraries for URIs.
   final Map<String, LibraryElement> _uriToLibraryCache = {};
 
-  /**
-   * Initialize a newly created analysis session.
-   */
+  /// Initialize a newly created analysis session.
   AnalysisSessionImpl(this._driver);
 
   @override
@@ -172,13 +158,6 @@
   }
 
   @override
-  Future<List<TopLevelDeclarationInSource>> getTopLevelDeclarations(
-      String name) {
-    _checkConsistency();
-    return _driver.getTopLevelNameDeclarations(name);
-  }
-
-  @override
   Future<UnitElementResult> getUnitElement(String path) {
     _checkConsistency();
     return _driver.getUnitElement(path);
@@ -190,10 +169,8 @@
     return _driver.getUnitElementSignature(path);
   }
 
-  /**
-   * Check to see that results from this session will be consistent, and throw
-   * an [InconsistentAnalysisException] if they might not be.
-   */
+  /// Check to see that results from this session will be consistent, and throw
+  /// an [InconsistentAnalysisException] if they might not be.
   void _checkConsistency() {
     if (_driver.currentSession != this) {
       throw new InconsistentAnalysisException();
@@ -208,3 +185,38 @@
     }
   }
 }
+
+/// Data structure containing information about the analysis session that is
+/// available synchronously.
+class SynchronousSession {
+  final AnalysisOptionsImpl analysisOptions;
+
+  final DeclaredVariables declaredVariables;
+
+  TypeProvider _typeProvider;
+
+  TypeSystem _typeSystem;
+
+  SynchronousSession(this.analysisOptions, this.declaredVariables);
+
+  TypeProvider get typeProvider => _typeProvider;
+
+  set typeProvider(TypeProvider typeProvider) {
+    if (_typeProvider != null) {
+      throw StateError('TypeProvider can be set only once.');
+    }
+    _typeProvider = typeProvider;
+  }
+
+  TypeSystem get typeSystem {
+    return _typeSystem ??= Dart2TypeSystem(
+      typeProvider,
+      implicitCasts: analysisOptions.implicitCasts,
+    );
+  }
+
+  void clearTypeProvider() {
+    _typeProvider = null;
+    _typeSystem = null;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/analysis/top_level_declaration.dart b/pkg/analyzer/lib/src/dart/analysis/top_level_declaration.dart
deleted file mode 100644
index 1658aad..0000000
--- a/pkg/analyzer/lib/src/dart/analysis/top_level_declaration.dart
+++ /dev/null
@@ -1,50 +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.
-
-import 'package:analyzer/src/generated/source.dart';
-
-/**
- * Information about a single top-level declaration.
- */
-class TopLevelDeclaration {
-  final TopLevelDeclarationKind kind;
-  final String name;
-
-  TopLevelDeclaration(this.kind, this.name);
-
-  @override
-  String toString() => '($kind, $name)';
-}
-
-/**
- * A declaration in a source.
- */
-class TopLevelDeclarationInSource {
-  /**
-   * The declaring source.
-   */
-  final Source source;
-
-  /**
-   * The declaration.
-   */
-  final TopLevelDeclaration declaration;
-
-  /**
-   * Is `true` if the [declaration] is exported, not declared in the [source].
-   */
-  final bool isExported;
-
-  TopLevelDeclarationInSource(this.source, this.declaration, this.isExported);
-
-  @override
-  String toString() => '($source, $declaration, $isExported)';
-}
-
-/**
- * Kind of a top-level declaration.
- *
- * We don't need it to be precise, just enough to support quick fixes.
- */
-enum TopLevelDeclarationKind { type, function, variable }
diff --git a/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart b/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
new file mode 100644
index 0000000..dfbaf6a
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
@@ -0,0 +1,134 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/summary/api_signature.dart';
+
+/// Return the bytes of the unlinked API signature of the given [unit].
+///
+/// If API signatures of two units are different, they may have different APIs.
+List<int> computeUnlinkedApiSignature(CompilationUnit unit) {
+  var computer = new _UnitApiSignatureComputer();
+  computer.compute(unit);
+  return computer.signature.toByteList();
+}
+
+class _UnitApiSignatureComputer {
+  final signature = new ApiSignature();
+
+  void addClassOrMixin(ClassOrMixinDeclaration node) {
+    addTokens(node.beginToken, node.leftBracket);
+
+    bool hasConstConstructor = node.members
+        .any((m) => m is ConstructorDeclaration && m.constKeyword != null);
+
+    signature.addInt(node.members.length);
+    for (var member in node.members) {
+      if (member is ConstructorDeclaration) {
+        var lastInitializer = member.constKeyword != null &&
+                member.initializers != null &&
+                member.initializers.isNotEmpty
+            ? member.initializers.last
+            : null;
+        addTokens(
+          member.beginToken,
+          (lastInitializer ?? member.parameters ?? member.name).endToken,
+        );
+      } else if (member is FieldDeclaration) {
+        var variableList = member.fields;
+        addVariables(
+          member,
+          variableList,
+          !member.isStatic && variableList.isFinal && hasConstConstructor,
+        );
+      } else if (member is MethodDeclaration) {
+        addTokens(
+          member.beginToken,
+          (member.parameters ?? member.name).endToken,
+        );
+      } else {
+        addNode(member);
+      }
+    }
+
+    addToken(node.rightBracket);
+  }
+
+  void addNode(AstNode node) {
+    addTokens(node.beginToken, node.endToken);
+  }
+
+  void addToken(Token token) {
+    signature.addString(token.lexeme);
+  }
+
+  /// Appends tokens from [begin] (including), to [end] (also including).
+  void addTokens(Token begin, Token end) {
+    if (begin is CommentToken) {
+      begin = (begin as CommentToken).parent;
+    }
+
+    Token token = begin;
+    while (token != null) {
+      addToken(token);
+
+      if (token == end) {
+        break;
+      }
+
+      var nextToken = token.next;
+
+      // Stop if EOF.
+      if (nextToken == token) {
+        break;
+      }
+
+      token = nextToken;
+    }
+  }
+
+  void addVariables(
+    AstNode node,
+    VariableDeclarationList variableList,
+    bool includeInitializers,
+  ) {
+    if (variableList.type == null ||
+        variableList.isConst ||
+        includeInitializers) {
+      addTokens(node.beginToken, node.endToken);
+    } else {
+      addTokens(node.beginToken, variableList.type.endToken);
+
+      signature.addInt(variableList.variables.length);
+      for (var variable in variableList.variables) {
+        addTokens(variable.beginToken, variable.name.endToken);
+        addToken(variable.endToken.next); // `,` or `;`
+      }
+    }
+  }
+
+  void compute(CompilationUnit unit) {
+    signature.addInt(unit.directives.length);
+    unit.directives.forEach(addNode);
+
+    signature.addInt(unit.declarations.length);
+    for (var declaration in unit.declarations) {
+      if (declaration is ClassOrMixinDeclaration) {
+        addClassOrMixin(declaration);
+      } else if (declaration is FunctionDeclaration) {
+        var parameters = declaration.functionExpression.parameters;
+        addTokens(
+          declaration.beginToken,
+          (parameters ?? declaration.name).endToken,
+        );
+      } else if (declaration is TopLevelVariableDeclaration) {
+        addVariables(declaration, declaration.variables, false);
+      } else {
+        addNode(declaration);
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 676b8dc..1d17498 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -5,6 +5,7 @@
 import 'dart:collection';
 import 'dart:math' as math;
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/precedence.dart';
 import 'package:analyzer/dart/ast/syntactic_entity.dart';
@@ -27,7 +28,6 @@
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
 import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:pub_semver/src/version.dart';
 
 /// Two or more string literals that are implicitly concatenated because of
 /// being adjacent (separated only by whitespace).
@@ -2044,8 +2044,6 @@
   @override
   CompilationUnitElement declaredElement;
 
-  Version languageVersion;
-
   /// The line information for this compilation unit.
   @override
   LineInfo lineInfo;
@@ -2059,8 +2057,8 @@
   /// has not yet been performed.
   LocalVariableInfo localVariableInfo = new LocalVariableInfo();
 
-  /// Is `true` if this unit has been parsed as non-nullable.
-  bool isNonNullable = false;
+  @override
+  final FeatureSet featureSet;
 
   /// Initialize a newly created compilation unit to have the given directives
   /// and declarations. The [scriptTag] can be `null` if there is no script tag
@@ -2072,7 +2070,8 @@
       ScriptTagImpl scriptTag,
       List<Directive> directives,
       List<CompilationUnitMember> declarations,
-      this.endToken) {
+      this.endToken,
+      this.featureSet) {
     _scriptTag = _becomeParentOf(scriptTag);
     _directives = new NodeListImpl<Directive>(this, directives);
     _declarations = new NodeListImpl<CompilationUnitMember>(this, declarations);
@@ -3822,6 +3821,109 @@
   }
 }
 
+/// The declaration of an extension of a type.
+///
+///    extension ::=
+///        'extension' [SimpleIdentifier] [TypeParameterList]?
+///        'on' [TypeAnnotation] '{' [ClassMember]* '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+class ExtensionDeclarationImpl extends NamedCompilationUnitMemberImpl
+    implements ExtensionDeclaration {
+  @override
+  Token extensionKeyword;
+
+  /// The type parameters for the extension, or `null` if the extension
+  /// does not have any type parameters.
+  TypeParameterListImpl _typeParameters;
+
+  @override
+  Token onKeyword;
+
+  /// The type that is being extended.
+  TypeAnnotationImpl _extendedType;
+
+  @override
+  Token leftBracket;
+
+  /// The members being added to the extended class.
+  NodeList<ClassMember> _members;
+
+  @override
+  Token rightBracket;
+
+  ExtensionDeclarationImpl(
+      CommentImpl comment,
+      List<Annotation> metadata,
+      this.extensionKeyword,
+      SimpleIdentifierImpl name,
+      TypeParameterListImpl typeParameters,
+      this.onKeyword,
+      TypeAnnotationImpl extendedType,
+      this.leftBracket,
+      List<ClassMember> members,
+      this.rightBracket)
+      : super(comment, metadata, name) {
+    _typeParameters = _becomeParentOf(typeParameters);
+    _extendedType = _becomeParentOf(extendedType);
+    _members = new NodeListImpl<ClassMember>(this, members);
+  }
+
+  @override
+  Token get beginToken => extensionKeyword;
+
+  @override
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
+    ..add(extensionKeyword)
+    ..add(name)
+    ..add(typeParameters)
+    ..add(onKeyword)
+    ..add(extendedType)
+    ..add(leftBracket)
+    ..addAll(members)
+    ..add(rightBracket);
+
+  @override
+  Element get declaredElement => name.staticElement;
+
+  @override
+  Element get element => name.staticElement;
+
+  @override
+  Token get endToken => rightBracket;
+
+  @override
+  TypeAnnotation get extendedType => _extendedType;
+
+  void set extendedType(TypeAnnotation extendedClass) {
+    _extendedType = _becomeParentOf(extendedClass as TypeAnnotationImpl);
+  }
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => name.beginToken;
+
+  @override
+  NodeList<ClassMember> get members => _members;
+
+  @override
+  TypeParameterList get typeParameters => _typeParameters;
+
+  void set typeParameters(TypeParameterList typeParameters) {
+    _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl);
+  }
+
+  @override
+  E accept<E>(AstVisitor<E> visitor) => visitor.visitExtensionDeclaration(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    name?.accept(visitor);
+    _typeParameters?.accept(visitor);
+    _extendedType?.accept(visitor);
+    _members.accept(visitor);
+  }
+}
+
 /// The declaration of one or more fields of the same type.
 ///
 ///    fieldDeclaration ::=
@@ -4223,13 +4325,17 @@
   ParameterElement get element => declaredElement;
 
   @override
-  bool get isNamed => kind == ParameterKind.NAMED;
+  bool get isNamed =>
+      kind == ParameterKind.NAMED || kind == ParameterKind.NAMED_REQUIRED;
 
   @override
   bool get isOptional =>
       kind == ParameterKind.NAMED || kind == ParameterKind.POSITIONAL;
 
   @override
+  bool get isOptionalNamed => kind == ParameterKind.NAMED;
+
+  @override
   bool get isOptionalPositional => kind == ParameterKind.POSITIONAL;
 
   @override
@@ -4237,7 +4343,14 @@
       kind == ParameterKind.POSITIONAL || kind == ParameterKind.REQUIRED;
 
   @override
-  bool get isRequired => kind == ParameterKind.REQUIRED;
+  bool get isRequired =>
+      kind == ParameterKind.REQUIRED || kind == ParameterKind.NAMED_REQUIRED;
+
+  @override
+  bool get isRequiredNamed => kind == ParameterKind.NAMED_REQUIRED;
+
+  @override
+  bool get isRequiredPositional => kind == ParameterKind.REQUIRED;
 
   @override
   // Overridden to remove the 'deprecated' annotation.
@@ -4797,7 +4910,8 @@
   /// not a generic method.
   TypeParameterListImpl _typeParameters;
 
-  /// The parameters associated with the function.
+  /// The parameters associated with the function, or `null` if the function is
+  /// part of a top-level getter.
   FormalParameterListImpl _parameters;
 
   /// The body of the function, or `null` if this is an external function.
@@ -5059,7 +5173,7 @@
 ///
 ///    functionSignature ::=
 ///        [TypeName]? [SimpleIdentifier] [TypeParameterList]?
-///        [FormalParameterList]
+///        [FormalParameterList] '?'?
 class FunctionTypedFormalParameterImpl extends NormalFormalParameterImpl
     implements FunctionTypedFormalParameter {
   /// The return type of the function, or `null` if the function does not have a
@@ -5073,6 +5187,9 @@
   /// The parameters of the function-typed parameter.
   FormalParameterListImpl _parameters;
 
+  @override
+  Token question;
+
   /// Initialize a newly created formal parameter. Either or both of the
   /// [comment] and [metadata] can be `null` if the parameter does not have the
   /// corresponding attribute. The [returnType] can be `null` if no return type
@@ -5085,7 +5202,8 @@
       TypeAnnotationImpl returnType,
       SimpleIdentifierImpl identifier,
       TypeParameterListImpl typeParameters,
-      FormalParameterListImpl parameters)
+      FormalParameterListImpl parameters,
+      this.question)
       : super(
             comment, metadata, covariantKeyword, requiredKeyword, identifier) {
     _returnType = _becomeParentOf(returnType);
@@ -5201,6 +5319,10 @@
   @override
   DartType type;
 
+  /// Return the element associated with the function type, or `null` if the
+  /// AST structure has not been resolved.
+  GenericFunctionTypeElement declaredElement;
+
   /// Initialize a newly created generic function type.
   GenericFunctionTypeImpl(TypeAnnotationImpl returnType, this.functionKeyword,
       TypeParameterListImpl typeParameters, FormalParameterListImpl parameters,
@@ -6051,7 +6173,8 @@
       AnalysisContext context = library.context;
       ErrorReporter errorReporter = new ErrorReporter(listener, element.source);
       accept(new ConstantVerifier(errorReporter, library, context.typeProvider,
-          context.declaredVariables));
+          context.declaredVariables,
+          featureSet: FeatureSet.fromEnableFlags([])));
     } finally {
       keyword = oldKeyword;
     }
@@ -6304,6 +6427,9 @@
   TypeArgumentListImpl _typeArguments;
 
   @override
+  List<DartType> typeArgumentTypes;
+
+  @override
   DartType staticInvokeType;
 
   /// Initialize a newly created invocation.
@@ -10381,6 +10507,12 @@
   }
 
   @override
+  bool get isLate {
+    AstNode parent = this.parent;
+    return parent is VariableDeclarationList && parent.isLate;
+  }
+
+  @override
   SimpleIdentifier get name => _name;
 
   @override
@@ -10406,16 +10538,20 @@
 ///        (',' [VariableDeclaration])*
 ///
 ///    finalConstVarOrType ::=
-///      | 'final' [TypeName]?
-///      | 'const' [TypeName]?
+///      'final' 'late'? [TypeAnnotation]?
+///      | 'const' [TypeAnnotation]?
 ///      | 'var'
-///      | [TypeName]
+///      | 'late'? [TypeAnnotation]
 class VariableDeclarationListImpl extends AnnotatedNodeImpl
     implements VariableDeclarationList {
   /// The token representing the 'final', 'const' or 'var' keyword, or `null` if
   /// no keyword was included.
   Token keyword;
 
+  /// The token representing the 'late' keyword, or `null` if the late modifier
+  /// was not included.
+  Token lateKeyword;
+
   /// The type of the variables being declared, or `null` if no type was
   /// provided.
   TypeAnnotationImpl _type;
@@ -10430,6 +10566,7 @@
   VariableDeclarationListImpl(
       CommentImpl comment,
       List<Annotation> metadata,
+      this.lateKeyword,
       this.keyword,
       TypeAnnotationImpl type,
       List<VariableDeclaration> variables)
@@ -10465,6 +10602,9 @@
   bool get isFinal => keyword?.keyword == Keyword.FINAL;
 
   @override
+  bool get isLate => lateKeyword != null;
+
+  @override
   TypeAnnotation get type => _type;
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index deeded8..1cd13f3 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/ast_factory.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
@@ -178,14 +179,27 @@
       new CommentReferenceImpl(newKeyword, identifier);
 
   @override
+  @deprecated
   CompilationUnit compilationUnit(
           Token beginToken,
           ScriptTag scriptTag,
           List<Directive> directives,
           List<CompilationUnitMember> declarations,
-          Token endToken) =>
-      new CompilationUnitImpl(
-          beginToken, scriptTag, directives, declarations, endToken);
+          Token endToken,
+          [FeatureSet featureSet]) =>
+      new CompilationUnitImpl(beginToken, scriptTag, directives, declarations,
+          endToken, featureSet);
+
+  @override
+  CompilationUnit compilationUnit2(
+          {Token beginToken,
+          ScriptTag scriptTag,
+          List<Directive> directives,
+          List<CompilationUnitMember> declarations,
+          Token endToken,
+          FeatureSet featureSet}) =>
+      new CompilationUnitImpl(beginToken, scriptTag, directives, declarations,
+          endToken, featureSet);
 
   @override
   ConditionalExpression conditionalExpression(
@@ -356,6 +370,30 @@
       new ExtendsClauseImpl(extendsKeyword, superclass);
 
   @override
+  ExtensionDeclaration extensionDeclaration(
+          {Comment comment,
+          List<Annotation> metadata,
+          Token extensionKeyword,
+          @required SimpleIdentifier name,
+          TypeParameterList typeParameters,
+          Token onKeyword,
+          @required TypeAnnotation extendedType,
+          Token leftBracket,
+          List<ClassMember> members,
+          Token rightBracket}) =>
+      new ExtensionDeclarationImpl(
+          comment,
+          metadata,
+          extensionKeyword,
+          name,
+          typeParameters,
+          onKeyword,
+          extendedType,
+          leftBracket,
+          members,
+          rightBracket);
+
+  @override
   FieldDeclaration fieldDeclaration(
           Comment comment,
           List<Annotation> metadata,
@@ -550,7 +588,7 @@
           TypeParameterList typeParameters,
           FormalParameterList parameters) =>
       new FunctionTypedFormalParameterImpl(comment, metadata, null, null,
-          returnType, identifier, typeParameters, parameters);
+          returnType, identifier, typeParameters, parameters, null);
 
   @override
   FunctionTypedFormalParameter functionTypedFormalParameter2(
@@ -561,9 +599,18 @@
           TypeAnnotation returnType,
           @required SimpleIdentifier identifier,
           TypeParameterList typeParameters,
-          @required FormalParameterList parameters}) =>
-      new FunctionTypedFormalParameterImpl(comment, metadata, covariantKeyword,
-          requiredKeyword, returnType, identifier, typeParameters, parameters);
+          @required FormalParameterList parameters,
+          Token question}) =>
+      new FunctionTypedFormalParameterImpl(
+          comment,
+          metadata,
+          covariantKeyword,
+          requiredKeyword,
+          returnType,
+          identifier,
+          typeParameters,
+          parameters,
+          question);
 
   @override
   GenericFunctionType genericFunctionType(
@@ -1021,7 +1068,19 @@
           TypeAnnotation type,
           List<VariableDeclaration> variables) =>
       new VariableDeclarationListImpl(
-          comment, metadata, keyword, type, variables);
+          comment, metadata, null, keyword, type, variables);
+
+  @override
+  VariableDeclarationList variableDeclarationList2(
+      {Comment comment,
+      List<Annotation> metadata,
+      Token lateKeyword,
+      Token keyword,
+      TypeAnnotation type,
+      List<VariableDeclaration> variables}) {
+    return new VariableDeclarationListImpl(
+        comment, metadata, lateKeyword, keyword, type, variables);
+  }
 
   @override
   VariableDeclarationStatement variableDeclarationStatement(
diff --git a/pkg/analyzer/lib/src/dart/ast/token.dart b/pkg/analyzer/lib/src/dart/ast/token.dart
index eea8be3..9939121 100644
--- a/pkg/analyzer/lib/src/dart/ast/token.dart
+++ b/pkg/analyzer/lib/src/dart/ast/token.dart
@@ -32,6 +32,8 @@
     return TokenType.CARET;
   } else if (operator == TokenType.GT_GT_EQ) {
     return TokenType.GT_GT;
+  } else if (operator == TokenType.GT_GT_GT_EQ) {
+    return TokenType.GT_GT_GT;
   } else if (operator == TokenType.LT_LT_EQ) {
     return TokenType.LT_LT;
   } else if (operator == TokenType.MINUS_EQ) {
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index b5fde2b..807d3c6 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -285,12 +285,13 @@
 
   @override
   CompilationUnit visitCompilationUnit(CompilationUnit node) {
-    CompilationUnit clone = astFactory.compilationUnit(
-        cloneToken(node.beginToken),
-        cloneNode(node.scriptTag),
-        cloneNodeList(node.directives),
-        cloneNodeList(node.declarations),
-        cloneToken(node.endToken));
+    CompilationUnit clone = astFactory.compilationUnit2(
+        beginToken: cloneToken(node.beginToken),
+        scriptTag: cloneNode(node.scriptTag),
+        directives: cloneNodeList(node.directives),
+        declarations: cloneNodeList(node.declarations),
+        endToken: cloneToken(node.endToken),
+        featureSet: node.featureSet);
     clone.lineInfo = node.lineInfo;
     return clone;
   }
@@ -449,6 +450,20 @@
           cloneToken(node.extendsKeyword), cloneNode(node.superclass));
 
   @override
+  ExtensionDeclaration visitExtensionDeclaration(ExtensionDeclaration node) =>
+      astFactory.extensionDeclaration(
+          comment: cloneNode(node.documentationComment),
+          metadata: cloneNodeList(node.metadata),
+          extensionKeyword: cloneToken(node.extensionKeyword),
+          name: cloneNode(node.name),
+          typeParameters: cloneNode(node.typeParameters),
+          onKeyword: cloneToken(node.onKeyword),
+          extendedType: cloneNode(node.extendedType),
+          leftBracket: cloneToken(node.leftBracket),
+          members: cloneNodeList(node.members),
+          rightBracket: cloneToken(node.rightBracket));
+
+  @override
   FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
       astFactory.fieldDeclaration2(
           comment: cloneNode(node.documentationComment),
@@ -585,7 +600,8 @@
           returnType: cloneNode(node.returnType),
           identifier: cloneNode(node.identifier),
           typeParameters: cloneNode(node.typeParameters),
-          parameters: cloneNode(node.parameters));
+          parameters: cloneNode(node.parameters),
+          question: cloneToken(node.question));
 
   @override
   AstNode visitGenericFunctionType(GenericFunctionType node) =>
@@ -1576,6 +1592,22 @@
   }
 
   @override
+  bool visitExtensionDeclaration(ExtensionDeclaration node) {
+    ExtensionDeclaration other = _other as ExtensionDeclaration;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.extensionKeyword, other.extensionKeyword) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualNodes(node.typeParameters, other.typeParameters) &&
+        isEqualTokens(node.onKeyword, other.onKeyword) &&
+        isEqualNodes(node.extendedType, other.extendedType) &&
+        isEqualTokens(node.leftBracket, other.leftBracket) &&
+        _isEqualNodeLists(node.members, other.members) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
   bool visitFieldDeclaration(FieldDeclaration node) {
     FieldDeclaration other = _other as FieldDeclaration;
     return isEqualNodes(
@@ -2642,12 +2674,13 @@
 
   @override
   CompilationUnit visitCompilationUnit(CompilationUnit node) {
-    CompilationUnitImpl copy = astFactory.compilationUnit(
-        _mapToken(node.beginToken),
-        _cloneNode(node.scriptTag),
-        _cloneNodeList(node.directives),
-        _cloneNodeList(node.declarations),
-        _mapToken(node.endToken));
+    CompilationUnitImpl copy = astFactory.compilationUnit2(
+        beginToken: _mapToken(node.beginToken),
+        scriptTag: _cloneNode(node.scriptTag),
+        directives: _cloneNodeList(node.directives),
+        declarations: _cloneNodeList(node.declarations),
+        endToken: _mapToken(node.endToken),
+        featureSet: node.featureSet);
     copy.lineInfo = node.lineInfo;
     copy.declaredElement = node.declaredElement;
     return copy;
@@ -2815,6 +2848,20 @@
           _mapToken(node.extendsKeyword), _cloneNode(node.superclass));
 
   @override
+  ExtensionDeclaration visitExtensionDeclaration(ExtensionDeclaration node) =>
+      astFactory.extensionDeclaration(
+          comment: _cloneNode(node.documentationComment),
+          metadata: _cloneNodeList(node.metadata),
+          extensionKeyword: _mapToken(node.extensionKeyword),
+          name: _cloneNode(node.name),
+          typeParameters: _cloneNode(node.typeParameters),
+          onKeyword: _mapToken(node.onKeyword),
+          extendedType: _cloneNode(node.extendedType),
+          leftBracket: _mapToken(node.leftBracket),
+          members: _cloneNodeList(node.members),
+          rightBracket: _mapToken(node.rightBracket));
+
+  @override
   FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
       astFactory.fieldDeclaration2(
           comment: _cloneNode(node.documentationComment),
@@ -2963,7 +3010,8 @@
           returnType: _cloneNode(node.returnType),
           identifier: _cloneNode(node.identifier),
           typeParameters: _cloneNode(node.typeParameters),
-          parameters: _cloneNode(node.parameters));
+          parameters: _cloneNode(node.parameters),
+          question: _mapToken(node.question));
 
   @override
   AstNode visitGenericFunctionType(GenericFunctionType node) =>
@@ -4228,6 +4276,29 @@
     return visitNode(node);
   }
 
+  bool visitExtensionDeclaration(ExtensionDeclaration node) {
+    if (identical(node.documentationComment, _oldNode)) {
+      node.documentationComment = _newNode as Comment;
+      return true;
+    } else if (_replaceInList(node.metadata)) {
+      return true;
+    } else if (identical(node.name, _oldNode)) {
+      (node as ExtensionDeclarationImpl).name = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.typeParameters, _oldNode)) {
+      (node as ExtensionDeclarationImpl).typeParameters =
+          _newNode as TypeParameterList;
+      return true;
+    } else if (identical(node.extendedType, _oldNode)) {
+      (node as ExtensionDeclarationImpl).extendedType =
+          _newNode as TypeAnnotation;
+      return true;
+    } else if (_replaceInList(node.members)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
   @override
   bool visitFieldDeclaration(FieldDeclaration node) {
     if (identical(node.fields, _oldNode)) {
@@ -5583,6 +5654,25 @@
   }
 
   @override
+  bool visitExtensionDeclaration(ExtensionDeclaration node) {
+    ExtensionDeclaration toNode = this._toNode as ExtensionDeclaration;
+    if (_and(
+        _isEqualNodes(node.documentationComment, toNode.documentationComment),
+        _isEqualNodeLists(node.metadata, toNode.metadata),
+        _isEqualTokens(node.extensionKeyword, toNode.extensionKeyword),
+        _isEqualNodes(node.name, toNode.name),
+        _isEqualNodes(node.typeParameters, toNode.typeParameters),
+        _isEqualTokens(node.onKeyword, toNode.onKeyword),
+        _isEqualNodes(node.extendedType, toNode.extendedType),
+        _isEqualTokens(node.leftBracket, toNode.leftBracket),
+        _isEqualNodeLists(node.members, toNode.members),
+        _isEqualTokens(node.rightBracket, toNode.rightBracket))) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
   bool visitFieldDeclaration(FieldDeclaration node) {
     FieldDeclaration toNode = this._toNode as FieldDeclaration;
     return _and(
@@ -7059,6 +7149,9 @@
 
   @override
   void visitDefaultFormalParameter(DefaultFormalParameter node) {
+    if (node.isRequiredNamed) {
+      _writer.print('required ');
+    }
     _visitNode(node.parameter);
     if (node.separator != null) {
       if (node.separator.lexeme != ":") {
@@ -7150,6 +7243,21 @@
   }
 
   @override
+  void visitExtensionDeclaration(ExtensionDeclaration node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+    _visitTokenWithSuffix(node.extensionKeyword, ' ');
+    _visitNode(node.name);
+    _visitNode(node.typeParameters);
+    _writer.print(' ');
+    _visitToken(node.onKeyword);
+    _writer.print(' ');
+    _visitNodeWithSuffix(node.extendedType, ' ');
+    _visitToken(node.leftBracket);
+    _visitNodeListWithSeparator(node.members, ' ');
+    _visitToken(node.rightBracket);
+  }
+
+  @override
   void visitFieldDeclaration(FieldDeclaration node) {
     _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
     _visitTokenWithSuffix(node.staticKeyword, " ");
@@ -7300,6 +7408,9 @@
     _visitNode(node.identifier);
     _visitNode(node.typeParameters);
     _visitNode(node.parameters);
+    if (node.question != null) {
+      _writer.print('?');
+    }
   }
 
   @override
@@ -7780,6 +7891,7 @@
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
     _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitTokenWithSuffix(node.lateKeyword, " ");
     _visitTokenWithSuffix(node.keyword, " ");
     _visitNodeWithSuffix(node.type, " ");
     _visitNodeListWithSeparator(node.variables, ", ");
@@ -7921,6 +8033,15 @@
   }
 
   /**
+   * Safely visit the given [token].
+   */
+  void _visitToken(Token token) {
+    if (token != null) {
+      _writer.print(token.lexeme);
+    }
+  }
+
+  /**
    * Safely visit the given [token], printing the [suffix] after the token if it
    * is non-`null`.
    */
@@ -8070,6 +8191,16 @@
   }
 
   /**
+   * Safely visit the given [token].
+   */
+  @protected
+  void safelyVisitToken(Token token) {
+    if (token != null) {
+      sink.write(token.lexeme);
+    }
+  }
+
+  /**
    * Safely visit the given [token], printing the [suffix] after the token if it
    * is non-`null`.
    */
@@ -8320,6 +8451,9 @@
 
   @override
   void visitDefaultFormalParameter(DefaultFormalParameter node) {
+    if (node.isRequiredNamed) {
+      sink.write('required ');
+    }
     safelyVisitNode(node.parameter);
     if (node.separator != null) {
       if (node.separator.lexeme != ":") {
@@ -8411,6 +8545,21 @@
   }
 
   @override
+  void visitExtensionDeclaration(ExtensionDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+    safelyVisitTokenWithSuffix(node.extensionKeyword, ' ');
+    safelyVisitNode(node.name);
+    safelyVisitNode(node.typeParameters);
+    sink.write(' ');
+    safelyVisitToken(node.onKeyword);
+    sink.write(' ');
+    safelyVisitNodeWithSuffix(node.extendedType, ' ');
+    safelyVisitToken(node.leftBracket);
+    safelyVisitNodeListWithSeparator(node.members, ' ');
+    safelyVisitToken(node.rightBracket);
+  }
+
+  @override
   void visitFieldDeclaration(FieldDeclaration node) {
     safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
     safelyVisitTokenWithSuffix(node.staticKeyword, " ");
@@ -8561,6 +8710,9 @@
     safelyVisitNode(node.identifier);
     safelyVisitNode(node.typeParameters);
     safelyVisitNode(node.parameters);
+    if (node.question != null) {
+      sink.write('?');
+    }
   }
 
   @override
@@ -9038,6 +9190,7 @@
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
     safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    safelyVisitTokenWithSuffix(node.lateKeyword, " ");
     safelyVisitTokenWithSuffix(node.keyword, " ");
     safelyVisitNodeWithSuffix(node.type, " ");
     safelyVisitNodeListWithSeparator(node.variables, ", ");
diff --git a/pkg/analyzer/lib/src/dart/constant/compute.dart b/pkg/analyzer/lib/src/dart/constant/compute.dart
index 712d4b6..3fc6ca9 100644
--- a/pkg/analyzer/lib/src/dart/constant/compute.dart
+++ b/pkg/analyzer/lib/src/dart/constant/compute.dart
@@ -20,9 +20,7 @@
     ExperimentStatus experimentStatus) {
   var evaluationEngine = ConstantEvaluationEngine(
       typeProvider, declaredVariables,
-      forAnalysisDriver: true,
-      typeSystem: typeSystem,
-      experimentStatus: experimentStatus);
+      typeSystem: typeSystem, experimentStatus: experimentStatus);
 
   var nodes = <_ConstantNode>[];
   var nodeMap = <ConstantEvaluationTarget, _ConstantNode>{};
@@ -39,9 +37,7 @@
   }
 }
 
-/**
- * [graph.Node] that is used to compute constants in dependency order.
- */
+/// [graph.Node] that is used to compute constants in dependency order.
 class _ConstantNode extends graph.Node<_ConstantNode> {
   final ConstantEvaluationEngine evaluationEngine;
   final Map<ConstantEvaluationTarget, _ConstantNode> nodeMap;
@@ -67,9 +63,7 @@
   }
 }
 
-/**
- * [graph.DependencyWalker] for computing constants and detecting cycles.
- */
+/// [graph.DependencyWalker] for computing constants and detecting cycles.
 class _ConstantWalker extends graph.DependencyWalker<_ConstantNode> {
   final ConstantEvaluationEngine evaluationEngine;
 
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 97fac61..26fc896 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -31,43 +32,49 @@
   /// The type provider used to access the known types.
   final TypeProvider _typeProvider;
 
-  /// The type system in use.
-  final TypeSystem _typeSystem;
-
   /// The set of variables declared using '-D' on the command line.
   final DeclaredVariables declaredVariables;
 
   /// The type representing the type 'int'.
-  InterfaceType _intType;
+  final InterfaceType _intType;
 
   /// The current library that is being analyzed.
   final LibraryElement _currentLibrary;
 
   final bool _constantUpdate2018Enabled;
 
-  ConstantEvaluationEngine _evaluationEngine;
+  final ConstantEvaluationEngine _evaluationEngine;
 
   /// Initialize a newly created constant verifier.
-  ///
-  /// @param errorReporter the error reporter by which errors will be reported
-  ConstantVerifier(this._errorReporter, LibraryElement currentLibrary,
-      this._typeProvider, this.declaredVariables,
-      {bool forAnalysisDriver: false})
-      : _currentLibrary = currentLibrary,
-        _typeSystem = currentLibrary.context.typeSystem,
-        _constantUpdate2018Enabled =
-            (currentLibrary.context.analysisOptions as AnalysisOptionsImpl)
-                .experimentStatus
-                .constant_update_2018 {
-    this._intType = _typeProvider.intType;
-    this._evaluationEngine = new ConstantEvaluationEngine(
-        _typeProvider, declaredVariables,
-        forAnalysisDriver: forAnalysisDriver,
-        typeSystem: _typeSystem,
-        experimentStatus:
-            (currentLibrary.context.analysisOptions as AnalysisOptionsImpl)
-                .experimentStatus);
-  }
+  ConstantVerifier(ErrorReporter errorReporter, LibraryElement currentLibrary,
+      TypeProvider typeProvider, DeclaredVariables declaredVariables,
+      // TODO(brianwilkerson) Remove the unused parameter `forAnalysisDriver`.
+      {bool forAnalysisDriver,
+      // TODO(paulberry): make [featureSet] a required parameter.
+      FeatureSet featureSet})
+      : this._(
+            errorReporter,
+            currentLibrary,
+            typeProvider,
+            declaredVariables,
+            currentLibrary.context.typeSystem,
+            featureSet ??
+                (currentLibrary.context.analysisOptions as AnalysisOptionsImpl)
+                    .contextFeatures);
+
+  ConstantVerifier._(
+      this._errorReporter,
+      this._currentLibrary,
+      this._typeProvider,
+      this.declaredVariables,
+      TypeSystem typeSystem,
+      FeatureSet featureSet)
+      : _constantUpdate2018Enabled =
+            featureSet.isEnabled(Feature.constant_update_2018),
+        _intType = _typeProvider.intType,
+        _evaluationEngine = new ConstantEvaluationEngine(
+            _typeProvider, declaredVariables,
+            typeSystem: typeSystem, experimentStatus: featureSet);
 
   @override
   void visitAnnotation(Annotation node) {
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 112dce6..53e8356 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -29,106 +29,76 @@
     show Dart2TypeSystem, TypeSystem;
 import 'package:analyzer/src/task/api/model.dart';
 
-/**
- * Helper class encapsulating the methods for evaluating constants and
- * constant instance creation expressions.
- */
+/// Helper class encapsulating the methods for evaluating constants and
+/// constant instance creation expressions.
 class ConstantEvaluationEngine {
-  /**
-   * Parameter to "fromEnvironment" methods that denotes the default value.
-   */
+  /// Parameter to "fromEnvironment" methods that denotes the default value.
   static String _DEFAULT_VALUE_PARAM = "defaultValue";
 
-  /**
-   * Source of RegExp matching declarable operator names.
-   * From sdk/lib/internal/symbol.dart.
-   */
+  /// Source of RegExp matching declarable operator names.
+  /// From sdk/lib/internal/symbol.dart.
   static String _OPERATOR_RE =
       "(?:[\\-+*/%&|^]|\\[\\]=?|==|~/?|<[<=]?|>[>=]?|unary-)";
 
-  /**
-   * Source of RegExp matching Dart reserved words.
-   * From sdk/lib/internal/symbol.dart.
-   */
+  /// Source of RegExp matching Dart reserved words.
+  /// From sdk/lib/internal/symbol.dart.
   static String _RESERVED_WORD_RE =
       "(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|"
       "d(?:efault|o)|e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|"
       "i[fns]|n(?:ew|ull)|ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|"
       "r(?:ue|y))|v(?:ar|oid)|w(?:hile|ith))";
 
-  /**
-   * Source of RegExp matching any public identifier.
-   * From sdk/lib/internal/symbol.dart.
-   */
+  /// Source of RegExp matching any public identifier.
+  /// From sdk/lib/internal/symbol.dart.
   static String _PUBLIC_IDENTIFIER_RE =
       "(?!$_RESERVED_WORD_RE\\b(?!\\\$))[a-zA-Z\$][\\w\$]*";
 
-  /**
-   * RegExp that validates a non-empty non-private symbol.
-   * From sdk/lib/internal/symbol.dart.
-   */
+  /// RegExp that validates a non-empty non-private symbol.
+  /// From sdk/lib/internal/symbol.dart.
   static RegExp _PUBLIC_SYMBOL_PATTERN = new RegExp(
       "^(?:$_OPERATOR_RE\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$|[.](?!\$)))+?\$");
 
-  /**
-   * The type provider used to access the known types.
-   */
+  /// The type provider used to access the known types.
   final TypeProvider typeProvider;
 
-  /**
-   * The type system.  This is used to guess the types of constants when their
-   * exact value is unknown.
-   */
+  /// The type system.  This is used to guess the types of constants when their
+  /// exact value is unknown.
   final TypeSystem typeSystem;
 
-  /**
-   * The set of variables declared on the command line using '-D'.
-   */
+  /// The set of variables declared on the command line using '-D'.
   final DeclaredVariables _declaredVariables;
 
-  /**
-   * Return the object representing the state of active experiments.
-   */
+  /// Return the object representing the state of active experiments.
   final ExperimentStatus experimentStatus;
 
-  /**
-   * Validator used to verify correct dependency analysis when running unit
-   * tests.
-   */
+  /// Validator used to verify correct dependency analysis when running unit
+  /// tests.
   final ConstantEvaluationValidator validator;
 
-  /**
-   * Whether this engine is used inside Analysis Driver.
-   */
-  final bool forAnalysisDriver;
-
-  /**
-   * Initialize a newly created [ConstantEvaluationEngine].  The [typeProvider]
-   * is used to access known types.  [_declaredVariables] is the set of
-   * variables declared on the command line using '-D'.  The [validator], if
-   * given, is used to verify correct dependency analysis when running unit
-   * tests.
-   */
+  /// Initialize a newly created [ConstantEvaluationEngine].  The [typeProvider]
+  /// is used to access known types.  [_declaredVariables] is the set of
+  /// variables declared on the command line using '-D'.  The [validator], if
+  /// given, is used to verify correct dependency analysis when running unit
+  /// tests.
   ConstantEvaluationEngine(TypeProvider typeProvider, this._declaredVariables,
       {ConstantEvaluationValidator validator,
       ExperimentStatus experimentStatus,
       TypeSystem typeSystem,
-      this.forAnalysisDriver: false})
+      // TODO(brianwilkerson) Remove the unused parameter `forAnalysisDriver`.
+      @deprecated bool forAnalysisDriver})
       : typeProvider = typeProvider,
         validator =
             validator ?? new ConstantEvaluationValidator_ForProduction(),
         typeSystem = typeSystem ?? new Dart2TypeSystem(typeProvider),
         experimentStatus = experimentStatus ?? new ExperimentStatus();
 
-  /**
-   * Check that the arguments to a call to fromEnvironment() are correct. The
-   * [arguments] are the AST nodes of the arguments. The [argumentValues] are
-   * the values of the unnamed arguments. The [namedArgumentValues] are the
-   * values of the named arguments. The [expectedDefaultValueType] is the
-   * allowed type of the "defaultValue" parameter (if present). Note:
-   * "defaultValue" is always allowed to be null. Return `true` if the arguments
-   * are correct, `false` if there is an error.
-   */
+  /// Check that the arguments to a call to fromEnvironment() are correct. The
+  /// [arguments] are the AST nodes of the arguments. The [argumentValues] are
+  /// the values of the unnamed arguments. The [namedArgumentValues] are the
+  /// values of the named arguments. The [expectedDefaultValueType] is the
+  /// allowed type of the "defaultValue" parameter (if present). Note:
+  /// "defaultValue" is always allowed to be null. Return `true` if the
+  /// arguments are correct, `false` if there is an error.
   bool checkFromEnvironmentArguments(
       NodeList<Expression> arguments,
       List<DartObjectImpl> argumentValues,
@@ -163,13 +133,11 @@
     return true;
   }
 
-  /**
-   * Check that the arguments to a call to Symbol() are correct. The [arguments]
-   * are the AST nodes of the arguments. The [argumentValues] are the values of
-   * the unnamed arguments. The [namedArgumentValues] are the values of the
-   * named arguments. Return `true` if the arguments are correct, `false` if
-   * there is an error.
-   */
+  /// Check that the arguments to a call to Symbol() are correct. The
+  /// [arguments] are the AST nodes of the arguments. The [argumentValues] are
+  /// the values of the unnamed arguments. The [namedArgumentValues] are the
+  /// values of the named arguments. Return `true` if the arguments are correct,
+  /// `false` if there is an error.
   bool checkSymbolArguments(
       NodeList<Expression> arguments,
       List<DartObjectImpl> argumentValues,
@@ -187,9 +155,7 @@
     return isValidPublicSymbol(name);
   }
 
-  /**
-   * Compute the constant value associated with the given [constant].
-   */
+  /// Compute the constant value associated with the given [constant].
   void computeConstantValue(ConstantEvaluationTarget constant) {
     validator.beforeComputeValue(constant);
     if (constant is ParameterElementImpl) {
@@ -287,17 +253,16 @@
     } else {
       // Should not happen.
       assert(false);
-      AnalysisEngine.instance.logger.logError(
-          "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}");
+      AnalysisEngine.instance.logger
+          .logError("Constant value computer trying to compute "
+              "the value of a node of type ${constant.runtimeType}");
       return;
     }
   }
 
-  /**
-   * Determine which constant elements need to have their values computed
-   * prior to computing the value of [constant], and report them using
-   * [callback].
-   */
+  /// Determine which constant elements need to have their values computed
+  /// prior to computing the value of [constant], and report them using
+  /// [callback].
   void computeDependencies(
       ConstantEvaluationTarget constant, ReferenceFinderCallback callback) {
     ReferenceFinder referenceFinder = new ReferenceFinder(callback);
@@ -320,12 +285,13 @@
           return;
         } else if (constant.isFactory) {
           // Factory constructor, but getConstRedirectedConstructor returned
-          // null.  This can happen if we're visiting one of the special external
-          // const factory constructors in the SDK, or if the code contains
-          // errors (such as delegating to a non-const constructor, or delegating
-          // to a constructor that can't be resolved).  In any of these cases,
-          // we'll evaluate calls to this constructor without having to refer to
-          // any other constants.  So we don't need to report any dependencies.
+          // null.  This can happen if we're visiting one of the special
+          // external const factory constructors in the SDK, or if the code
+          // contains errors (such as delegating to a non-const constructor, or
+          // delegating to a constructor that can't be resolved).  In any of
+          // these cases, we'll evaluate calls to this constructor without
+          // having to refer to any other constants.  So we don't need to report
+          // any dependencies.
           return;
         }
         bool defaultSuperInvocationNeeded = true;
@@ -401,20 +367,19 @@
     } else {
       // Should not happen.
       assert(false);
-      AnalysisEngine.instance.logger.logError(
-          "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}");
+      AnalysisEngine.instance.logger
+          .logError("Constant value computer trying to compute "
+              "the value of a node of type ${constant.runtimeType}");
     }
   }
 
-  /**
-   * Evaluate a call to fromEnvironment() on the bool, int, or String class. The
-   * [environmentValue] is the value fetched from the environment. The
-   * [builtInDefaultValue] is the value that should be used as the default if no
-   * "defaultValue" argument appears in [namedArgumentValues]. The
-   * [namedArgumentValues] are the values of the named parameters passed to
-   * fromEnvironment(). Return a [DartObjectImpl] object corresponding to the
-   * evaluated result.
-   */
+  /// Evaluate a call to fromEnvironment() on the bool, int, or String class.
+  /// The [environmentValue] is the value fetched from the environment. The
+  /// [builtInDefaultValue] is the value that should be used as the default if
+  /// no "defaultValue" argument appears in [namedArgumentValues]. The
+  /// [namedArgumentValues] are the values of the named parameters passed to
+  /// fromEnvironment(). Return a [DartObjectImpl] object corresponding to the
+  /// evaluated result.
   DartObjectImpl computeValueFromEnvironment(
       DartObject environmentValue,
       DartObjectImpl builtInDefaultValue,
@@ -752,7 +717,7 @@
         DartObjectImpl evaluationResult = condition.accept(initializerVisitor);
         if (evaluationResult == null ||
             !evaluationResult.isBool ||
-            evaluationResult.toBoolValue() != true) {
+            evaluationResult.toBoolValue() == false) {
           errorReporter.reportErrorForNode(
               CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
           return null;
@@ -797,14 +762,12 @@
     }
   }
 
-  /**
-   * Attempt to follow the chain of factory redirections until a constructor is
-   * reached which is not a const factory constructor. Return the constant
-   * constructor which terminates the chain of factory redirections, if the
-   * chain terminates. If there is a problem (e.g. a redirection can't be found,
-   * or a cycle is encountered), the chain will be followed as far as possible
-   * and then a const factory constructor will be returned.
-   */
+  /// Attempt to follow the chain of factory redirections until a constructor is
+  /// reached which is not a const factory constructor. Return the constant
+  /// constructor which terminates the chain of factory redirections, if the
+  /// chain terminates. If there is a problem (e.g. a redirection can't be
+  /// found, or a cycle is encountered), the chain will be followed as far as
+  /// possible and then a const factory constructor will be returned.
   ConstructorElement followConstantRedirectionChain(
       ConstructorElement constructor) {
     HashSet<ConstructorElement> constructorsVisited =
@@ -831,12 +794,10 @@
     return constructor;
   }
 
-  /**
-   * Generate an error indicating that the given [constant] is not a valid
-   * compile-time constant because it references at least one of the constants
-   * in the given [cycle], each of which directly or indirectly references the
-   * constant.
-   */
+  /// Generate an error indicating that the given [constant] is not a valid
+  /// compile-time constant because it references at least one of the constants
+  /// in the given [cycle], each of which directly or indirectly references the
+  /// constant.
   void generateCycleError(Iterable<ConstantEvaluationTarget> cycle,
       ConstantEvaluationTarget constant) {
     if (constant is VariableElement) {
@@ -857,15 +818,14 @@
       // Should not happen.  Formal parameter defaults and annotations should
       // never appear as part of a cycle because they can't be referred to.
       assert(false);
-      AnalysisEngine.instance.logger.logError(
-          "Constant value computer trying to report a cycle error for a node of type ${constant.runtimeType}");
+      AnalysisEngine.instance.logger
+          .logError("Constant value computer trying to report a cycle error "
+              "for a node of type ${constant.runtimeType}");
     }
   }
 
-  /**
-   * If [constructor] redirects to another const constructor, return the
-   * const constructor it redirects to.  Otherwise return `null`.
-   */
+  /// If [constructor] redirects to another const constructor, return the
+  /// const constructor it redirects to.  Otherwise return `null`.
   ConstructorElement getConstRedirectedConstructor(
       ConstructorElement constructor) {
     if (!constructor.isFactory) {
@@ -894,17 +854,12 @@
     return redirectedConstructor;
   }
 
-  /**
-   * Check if the object [obj] matches the type [type] according to runtime type
-   * checking rules.
-   */
+  /// Check if the object [obj] matches the type [type] according to runtime
+  /// type checking rules.
   bool runtimeTypeMatch(DartObjectImpl obj, DartType type) {
     if (obj.isNull) {
       return true;
     }
-    if (type.isUndefined) {
-      return false;
-    }
     var objType = obj.type;
     if (objType.isDartCoreInt && type.isDartCoreDouble) {
       // Work around dartbug.com/35993 by allowing `int` to be used in a place
@@ -926,75 +881,54 @@
     return objType.isSubtypeOf(type);
   }
 
-  /**
-   * Determine whether the given string is a valid name for a public symbol
-   * (i.e. whether it is allowed for a call to the Symbol constructor).
-   */
+  /// Determine whether the given string is a valid name for a public symbol
+  /// (i.e. whether it is allowed for a call to the Symbol constructor).
   static bool isValidPublicSymbol(String name) =>
       name.isEmpty || name == "void" || _PUBLIC_SYMBOL_PATTERN.hasMatch(name);
 }
 
-/**
- * Interface for [AnalysisTarget]s for which constant evaluation can be
- * performed.
- */
+/// Interface for [AnalysisTarget]s for which constant evaluation can be
+/// performed.
 abstract class ConstantEvaluationTarget extends AnalysisTarget {
-  /**
-   * Return the [AnalysisContext] which should be used to evaluate this
-   * constant.
-   */
+  /// Return the [AnalysisContext] which should be used to evaluate this
+  /// constant.
   AnalysisContext get context;
 
-  /**
-   * Return whether this constant is evaluated.
-   */
+  /// Return whether this constant is evaluated.
   bool get isConstantEvaluated;
 }
 
-/**
- * Interface used by unit tests to verify correct dependency analysis during
- * constant evaluation.
- */
+/// Interface used by unit tests to verify correct dependency analysis during
+/// constant evaluation.
 abstract class ConstantEvaluationValidator {
-  /**
-   * This method is called just before computing the constant value associated
-   * with [constant]. Unit tests will override this method to introduce
-   * additional error checking.
-   */
+  /// This method is called just before computing the constant value associated
+  /// with [constant]. Unit tests will override this method to introduce
+  /// additional error checking.
   void beforeComputeValue(ConstantEvaluationTarget constant);
 
-  /**
-   * This method is called just before getting the constant initializers
-   * associated with the [constructor]. Unit tests will override this method to
-   * introduce additional error checking.
-   */
+  /// This method is called just before getting the constant initializers
+  /// associated with the [constructor]. Unit tests will override this method to
+  /// introduce additional error checking.
   void beforeGetConstantInitializers(ConstructorElement constructor);
 
-  /**
-   * This method is called just before retrieving an evaluation result from an
-   * element. Unit tests will override it to introduce additional error
-   * checking.
-   */
+  /// This method is called just before retrieving an evaluation result from an
+  /// element. Unit tests will override it to introduce additional error
+  /// checking.
   void beforeGetEvaluationResult(ConstantEvaluationTarget constant);
 
-  /**
-   * This method is called just before getting the constant value of a field
-   * with an initializer.  Unit tests will override this method to introduce
-   * additional error checking.
-   */
+  /// This method is called just before getting the constant value of a field
+  /// with an initializer.  Unit tests will override this method to introduce
+  /// additional error checking.
   void beforeGetFieldEvaluationResult(FieldElementImpl field);
 
-  /**
-   * This method is called just before getting a parameter's default value. Unit
-   * tests will override this method to introduce additional error checking.
-   */
+  /// This method is called just before getting a parameter's default value.
+  /// Unit tests will override this method to introduce additional error
+  /// checking.
   void beforeGetParameterDefault(ParameterElement parameter);
 }
 
-/**
- * Implementation of [ConstantEvaluationValidator] used in production; does no
- * validation.
- */
+/// Implementation of [ConstantEvaluationValidator] used in production; does no
+/// validation.
 class ConstantEvaluationValidator_ForProduction
     implements ConstantEvaluationValidator {
   @override
@@ -1013,37 +947,28 @@
   void beforeGetParameterDefault(ParameterElement parameter) {}
 }
 
-/**
- * A visitor used to evaluate constant expressions to produce their compile-time
- * value.
- */
+/// A visitor used to evaluate constant expressions to produce their
+/// compile-time value.
 class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
-  /**
-   * The type provider used to access the known types.
-   */
+  /// The evaluation engine used to access the feature set, type system, and
+  /// type provider.
   final ConstantEvaluationEngine evaluationEngine;
 
   final Map<String, DartObjectImpl> _lexicalEnvironment;
 
-  /**
-   * Error reporter that we use to report errors accumulated while computing the
-   * constant.
-   */
+  /// Error reporter that we use to report errors accumulated while computing
+  /// the constant.
   final ErrorReporter _errorReporter;
 
-  /**
-   * Helper class used to compute constant values.
-   */
+  /// Helper class used to compute constant values.
   DartObjectComputer _dartObjectComputer;
 
-  /**
-   * Initialize a newly created constant visitor. The [evaluationEngine] is
-   * used to evaluate instance creation expressions. The [lexicalEnvironment]
-   * is a map containing values which should override identifiers, or `null` if
-   * no overriding is necessary. The [_errorReporter] is used to report errors
-   * found during evaluation.  The [validator] is used by unit tests to verify
-   * correct dependency analysis.
-   */
+  /// Initialize a newly created constant visitor. The [evaluationEngine] is
+  /// used to evaluate instance creation expressions. The [lexicalEnvironment]
+  /// is a map containing values which should override identifiers, or `null` if
+  /// no overriding is necessary. The [_errorReporter] is used to report errors
+  /// found during evaluation.  The [validator] is used by unit tests to verify
+  /// correct dependency analysis.
   ConstantVisitor(this.evaluationEngine, this._errorReporter,
       {Map<String, DartObjectImpl> lexicalEnvironment})
       : _lexicalEnvironment = lexicalEnvironment {
@@ -1051,26 +976,18 @@
         new DartObjectComputer(_errorReporter, evaluationEngine);
   }
 
-  /**
-   * Return the object representing the state of active experiments.
-   */
+  /// Return the object representing the state of active experiments.
   ExperimentStatus get experimentStatus => evaluationEngine.experimentStatus;
 
-  /**
-   * Convenience getter to gain access to the [evaluationEngine]'s type system.
-   */
+  /// Convenience getter to gain access to the [evaluationEngine]'s type system.
   TypeSystem get typeSystem => evaluationEngine.typeSystem;
 
-  /**
-   * Convenience getter to gain access to the [evaluationEngine]'s type
-   * provider.
-   */
+  /// Convenience getter to gain access to the [evaluationEngine]'s type
+  /// provider.
   TypeProvider get _typeProvider => evaluationEngine.typeProvider;
 
-  /**
-   * Given a [type] that may contain free type variables, evaluate them against
-   * the current lexical environment and return the substituted type.
-   */
+  /// Given a [type] that may contain free type variables, evaluate them against
+  /// the current lexical environment and return the substituted type.
   DartType evaluateType(DartType type) {
     if (type is TypeParameterType) {
       return null;
@@ -1093,9 +1010,7 @@
     return type;
   }
 
-  /**
-   * Given a [type], returns the constant value that contains that type value.
-   */
+  /// Given a [type], returns the constant value that contains that type value.
   DartObjectImpl typeConstant(DartType type) {
     return new DartObjectImpl(_typeProvider.typeType, new TypeState(type));
   }
@@ -1556,11 +1471,9 @@
   @override
   DartObjectImpl visitTypeName(TypeName node) => visitTypeAnnotation(node);
 
-  /**
-   * Add the entries produced by evaluating the given collection [element] to
-   * the given [list]. Return `true` if the evaluation of one or more of the
-   * elements failed.
-   */
+  /// Add the entries produced by evaluating the given collection [element] to
+  /// the given [list]. Return `true` if the evaluation of one or more of the
+  /// elements failed.
   bool _addElementsToList(List<DartObject> list, CollectionElement element) {
     if (element is IfElement) {
       bool conditionValue = _evaluateCondition(element.condition);
@@ -1592,11 +1505,9 @@
     return true;
   }
 
-  /**
-   * Add the entries produced by evaluating the given map [element] to the given
-   * [map]. Return `true` if the evaluation of one or more of the entries
-   * failed.
-   */
+  /// Add the entries produced by evaluating the given map [element] to the
+  /// given [map]. Return `true` if the evaluation of one or more of the entries
+  /// failed.
   bool _addElementsToMap(
       Map<DartObjectImpl, DartObjectImpl> map, CollectionElement element) {
     if (element is IfElement) {
@@ -1630,11 +1541,9 @@
     return true;
   }
 
-  /**
-   * Add the entries produced by evaluating the given collection [element] to
-   * the given [set]. Return `true` if the evaluation of one or more of the
-   * elements failed.
-   */
+  /// Add the entries produced by evaluating the given collection [element] to
+  /// the given [set]. Return `true` if the evaluation of one or more of the
+  /// elements failed.
   bool _addElementsToSet(Set<DartObject> set, CollectionElement element) {
     if (element is IfElement) {
       bool conditionValue = _evaluateCondition(element.condition);
@@ -1666,10 +1575,8 @@
     return true;
   }
 
-  /**
-   * Create an error associated with the given [node]. The error will have the
-   * given error [code].
-   */
+  /// Create an error associated with the given [node]. The error will have the
+  /// given error [code].
   void _error(AstNode node, ErrorCode code) {
     if (code == null) {
       var parent = node?.parent;
@@ -1686,54 +1593,43 @@
         code ?? CompileTimeErrorCode.INVALID_CONSTANT, node);
   }
 
-  /**
-   * Evaluate the given [condition] with the assumption that it must be a
-   * `bool`.
-   */
+  /// Evaluate the given [condition] with the assumption that it must be a
+  /// `bool`.
   bool _evaluateCondition(Expression condition) {
     DartObjectImpl conditionResult = condition.accept(this);
     bool conditionValue = conditionResult?.toBoolValue();
     if (conditionValue == null) {
-      // TODO(brianwilkerson) Figure out why the static type is sometimes null.
-      DartType staticType = condition.staticType;
-      if (staticType == null ||
-          typeSystem.isAssignableTo(staticType, _typeProvider.boolType)) {
-        // If the static type is not assignable, then we will have already
-        // reported this error.
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, condition);
+      if (conditionResult?.type != _typeProvider.boolType) {
+        // TODO(brianwilkerson) Figure out why the static type is sometimes null.
+        DartType staticType = condition.staticType;
+        if (staticType == null ||
+            typeSystem.isAssignableTo(staticType, _typeProvider.boolType)) {
+          // If the static type is not assignable, then we will have already
+          // reported this error.
+          // TODO(mfairhurst) get the FeatureSet to suppress this for nnbd too.
+          _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, condition);
+        }
       }
     }
     return conditionValue;
   }
 
-  /**
-   * Return the constant value of the static constant represented by the given
-   * [element]. The [node] is the node to be used if an error needs to be
-   * reported.
-   */
+  /// Return the constant value of the static constant represented by the given
+  /// [element]. The [node] is the node to be used if an error needs to be
+  /// reported.
   DartObjectImpl _getConstantValue(AstNode node, Element element) {
     Element variableElement =
         element is PropertyAccessorElement ? element.variable : element;
     if (variableElement is VariableElementImpl) {
       // We access values of constant variables here in two cases: when we
-      // compute values of other constant  variables, or when we compute values
-      // and errors for other constant expressions. In any case, with Analysis
-      // Driver, we compute values of all dependencies first (or detect  cycle).
-      // So, the value has already been computed. Just return it.
-      if (evaluationEngine.forAnalysisDriver) {
-        EvaluationResultImpl value = variableElement.evaluationResult;
-        if (variableElement.isConst && value != null) {
-          return value.value;
-        }
-      } else {
-        // TODO(scheglov) Once we remove task model, we can remove this code.
-        evaluationEngine.validator.beforeGetEvaluationResult(variableElement);
-        variableElement.computeConstantValue();
-        EvaluationResultImpl value = variableElement.evaluationResult;
-        if (variableElement.isConst && value != null) {
-          return value.value;
-        }
+      // compute values of other constant variables, or when we compute values
+      // and errors for other constant expressions. In either case we have
+      // already computed values of all dependencies first (or detect a cycle),
+      // so the value has already been computed and we can just return it.
+      EvaluationResultImpl value = variableElement.evaluationResult;
+      if (variableElement.isConst && value != null) {
+        return value.value;
       }
     } else if (variableElement is ExecutableElement) {
       ExecutableElement function = element;
@@ -1756,10 +1652,8 @@
     return null;
   }
 
-  /**
-   * Return `true` if the given [targetResult] represents a string and the
-   * [identifier] is "length".
-   */
+  /// Return `true` if the given [targetResult] represents a string and the
+  /// [identifier] is "length".
   bool _isStringLength(
       DartObjectImpl targetResult, SimpleIdentifier identifier) {
     if (targetResult == null || targetResult.type != _typeProvider.stringType) {
@@ -1780,10 +1674,8 @@
     }
   }
 
-  /**
-   * Return the value of the given [expression], or a representation of 'null'
-   * if the expression cannot be evaluated.
-   */
+  /// Return the value of the given [expression], or a representation of 'null'
+  /// if the expression cannot be evaluated.
   DartObjectImpl _valueOf(Expression expression) {
     DartObjectImpl expressionValue = expression.accept(this);
     if (expressionValue != null) {
@@ -1793,32 +1685,22 @@
   }
 }
 
-/**
- * A utility class that contains methods for manipulating instances of a Dart
- * class and for collecting errors during evaluation.
- */
+/// A utility class that contains methods for manipulating instances of a Dart
+/// class and for collecting errors during evaluation.
 class DartObjectComputer {
-  /**
-   * The error reporter that we are using to collect errors.
-   */
+  /// The error reporter that we are using to collect errors.
   final ErrorReporter _errorReporter;
 
-  /**
-   * The type provider used to access the known types.
-   */
+  /// The evaluation engine used to access the type system, and type provider.
   final ConstantEvaluationEngine _evaluationEngine;
 
   DartObjectComputer(this._errorReporter, this._evaluationEngine);
 
-  /**
-   * Convenience getter to gain access to the [evaluationEngine]'s type
-   * provider.
-   */
+  /// Convenience getter to gain access to the [evaluationEngine]'s type
+  /// provider.
   TypeProvider get _typeProvider => _evaluationEngine.typeProvider;
 
-  /**
-   * Convenience getter to gain access to the [evaluationEngine]'s type system.
-   */
+  /// Convenience getter to gain access to the [evaluationEngine]'s type system.
   TypeSystem get _typeSystem => _evaluationEngine.typeSystem;
 
   DartObjectImpl add(BinaryExpression node, DartObjectImpl leftOperand,
@@ -1834,10 +1716,9 @@
     return null;
   }
 
-  /**
-   * Return the result of applying boolean conversion to the [evaluationResult].
-   * The [node] is the node against which errors should be reported.
-   */
+  /// Return the result of applying boolean conversion to the
+  /// [evaluationResult]. The [node] is the node against which errors should be
+  /// reported.
   DartObjectImpl applyBooleanConversion(
       AstNode node, DartObjectImpl evaluationResult) {
     if (evaluationResult != null) {
@@ -2181,11 +2062,9 @@
     return null;
   }
 
-  /**
-   * Return the result of invoking the 'length' getter on the
-   * [evaluationResult]. The [node] is the node against which errors should be
-   * reported.
-   */
+  /// Return the result of invoking the 'length' getter on the
+  /// [evaluationResult]. The [node] is the node against which errors should be
+  /// reported.
   EvaluationResultImpl stringLength(
       Expression node, EvaluationResultImpl evaluationResult) {
     if (evaluationResult.value != null) {
@@ -2229,76 +2108,54 @@
   }
 }
 
-/**
- * The result of attempting to evaluate an expression.
- */
+/// The result of attempting to evaluate an expression.
 class EvaluationResult {
   // TODO(brianwilkerson) Merge with EvaluationResultImpl
-  /**
-   * The value of the expression.
-   */
+  /// The value of the expression.
   final DartObject value;
 
-  /**
-   * The errors that should be reported for the expression(s) that were
-   * evaluated.
-   */
+  /// The errors that should be reported for the expression(s) that were
+  /// evaluated.
   final List<AnalysisError> _errors;
 
-  /**
-   * Initialize a newly created result object with the given [value] and set of
-   * [_errors]. Clients should use one of the factory methods: [forErrors] and
-   * [forValue].
-   */
+  /// Initialize a newly created result object with the given [value] and set of
+  /// [_errors]. Clients should use one of the factory methods: [forErrors] and
+  /// [forValue].
   EvaluationResult(this.value, this._errors);
 
-  /**
-   * Return a list containing the errors that should be reported for the
-   * expression(s) that were evaluated. If there are no such errors, the list
-   * will be empty. The list can be empty even if the expression is not a valid
-   * compile time constant if the errors would have been reported by other parts
-   * of the analysis engine.
-   */
+  /// Return a list containing the errors that should be reported for the
+  /// expression(s) that were evaluated. If there are no such errors, the list
+  /// will be empty. The list can be empty even if the expression is not a valid
+  /// compile time constant if the errors would have been reported by other
+  /// parts of the analysis engine.
   List<AnalysisError> get errors => _errors ?? AnalysisError.NO_ERRORS;
 
-  /**
-   * Return `true` if the expression is a compile-time constant expression that
-   * would not throw an exception when evaluated.
-   */
+  /// Return `true` if the expression is a compile-time constant expression that
+  /// would not throw an exception when evaluated.
   bool get isValid => _errors == null;
 
-  /**
-   * Return an evaluation result representing the result of evaluating an
-   * expression that is not a compile-time constant because of the given
-   * [errors].
-   */
+  /// Return an evaluation result representing the result of evaluating an
+  /// expression that is not a compile-time constant because of the given
+  /// [errors].
   static EvaluationResult forErrors(List<AnalysisError> errors) =>
       new EvaluationResult(null, errors);
 
-  /**
-   * Return an evaluation result representing the result of evaluating an
-   * expression that is a compile-time constant that evaluates to the given
-   * [value].
-   */
+  /// Return an evaluation result representing the result of evaluating an
+  /// expression that is a compile-time constant that evaluates to the given
+  /// [value].
   static EvaluationResult forValue(DartObject value) =>
       new EvaluationResult(value, null);
 }
 
-/**
- * The result of attempting to evaluate a expression.
- */
+/// The result of attempting to evaluate a expression.
 class EvaluationResultImpl {
-  /**
-   * The errors encountered while trying to evaluate the compile time constant.
-   * These errors may or may not have prevented the expression from being a
-   * valid compile time constant.
-   */
+  /// The errors encountered while trying to evaluate the compile time constant.
+  /// These errors may or may not have prevented the expression from being a
+  /// valid compile time constant.
   List<AnalysisError> _errors;
 
-  /**
-   * The value of the expression, or `null` if the value couldn't be computed
-   * due to errors.
-   */
+  /// The value of the expression, or `null` if the value couldn't be computed
+  /// due to errors.
   final DartObjectImpl value;
 
   EvaluationResultImpl(this.value, [List<AnalysisError> errors]) {
diff --git a/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
index 3d091bd..65e2023 100644
--- a/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
+++ b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
@@ -7,6 +7,10 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 
+/// Some [ConstructorElement]s can be temporary marked as "const" to check
+/// if doing this is valid.
+final temporaryConstConstructorElements = new Expando<bool>();
+
 /// Check if the [node] and all its sub-nodes are potentially constant.
 ///
 /// Return the list of nodes that are not potentially constant.
@@ -234,7 +238,8 @@
 
     if (element is ParameterElement) {
       var enclosing = element.enclosingElement;
-      if (enclosing is ConstructorElement && enclosing.isConst) {
+      if (enclosing is ConstructorElement &&
+          isConstConstructorElement(enclosing)) {
         if (node.thisOrAncestorOfType<ConstructorInitializer>() != null) {
           return;
         }
@@ -353,4 +358,9 @@
       }
     }
   }
+
+  static bool isConstConstructorElement(ConstructorElement element) {
+    if (element.isConst) return true;
+    return temporaryConstConstructorElements[element] ?? false;
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index 60cecdd..e99b3c5 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -28,15 +28,11 @@
   return constructor;
 }
 
-/**
- * Callback used by [ReferenceFinder] to report that a dependency was found.
- */
+/// Callback used by [ReferenceFinder] to report that a dependency was found.
 typedef void ReferenceFinderCallback(ConstantEvaluationTarget dependency);
 
-/**
- * An [AstCloner] that copies the necessary information from the AST to allow
- * constants to be evaluated.
- */
+/// An [AstCloner] that copies the necessary information from the AST to allow
+/// constants to be evaluated.
 class ConstantAstCloner extends AstCloner {
   ConstantAstCloner() : super(true);
 
@@ -137,15 +133,11 @@
   }
 }
 
-/**
- * A visitor used to traverse the AST structures of all of the compilation units
- * being resolved and build the full set of dependencies for all constant
- * expressions.
- */
+/// A visitor used to traverse the AST structures of all of the compilation
+/// units being resolved and build the full set of dependencies for all constant
+/// expressions.
 class ConstantExpressionsDependenciesFinder extends RecursiveAstVisitor {
-  /**
-   * The constants whose values need to be computed.
-   */
+  /// The constants whose values need to be computed.
   HashSet<ConstantEvaluationTarget> dependencies =
       new HashSet<ConstantEvaluationTarget>();
 
@@ -204,23 +196,17 @@
   }
 }
 
-/**
- * A visitor used to traverse the AST structures of all of the compilation units
- * being resolved and build tables of the constant variables, constant
- * constructors, constant constructor invocations, and annotations found in
- * those compilation units.
- */
+/// A visitor used to traverse the AST structures of all of the compilation
+/// units being resolved and build tables of the constant variables, constant
+/// constructors, constant constructor invocations, and annotations found in
+/// those compilation units.
 class ConstantFinder extends RecursiveAstVisitor<void> {
-  /**
-   * The elements and AST nodes whose constant values need to be computed.
-   */
+  /// The elements and AST nodes whose constant values need to be computed.
   List<ConstantEvaluationTarget> constantsToCompute =
       <ConstantEvaluationTarget>[];
 
-  /**
-   * A flag indicating whether instance variables marked as "final" should be
-   * treated as "const".
-   */
+  /// A flag indicating whether instance variables marked as "final" should be
+  /// treated as "const".
   bool treatFinalInstanceVarAsConst = false;
 
   @override
@@ -296,22 +282,16 @@
   }
 }
 
-/**
- * An object used to add reference information for a given variable to the
- * bi-directional mapping used to order the evaluation of constants.
- */
+/// An object used to add reference information for a given variable to the
+/// bi-directional mapping used to order the evaluation of constants.
 class ReferenceFinder extends RecursiveAstVisitor<void> {
-  /**
-   * The callback which should be used to report any dependencies that were
-   * found.
-   */
+  /// The callback which should be used to report any dependencies that were
+  /// found.
   final ReferenceFinderCallback _callback;
 
-  /**
-   * Initialize a newly created reference finder to find references from a given
-   * variable to other variables and to add those references to the given graph.
-   * The [_callback] will be invoked for every dependency found.
-   */
+  /// Initialize a newly created reference finder to find references from a
+  /// given variable to other variables and to add those references to the given
+  /// graph. The [_callback] will be invoked for every dependency found.
   ReferenceFinder(this._callback);
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index 1b93859..db0ed6f 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -2,9 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- * The implementation of the class [DartObject].
- */
+/// The implementation of the class [DartObject].
 import 'dart:collection';
 
 import 'package:analyzer/dart/constant/value.dart';
@@ -16,33 +14,21 @@
 import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
 
-/**
- * The state of an object representing a boolean value.
- */
+/// The state of an object representing a boolean value.
 class BoolState extends InstanceState {
-  /**
-   * An instance representing the boolean value 'false'.
-   */
+  /// An instance representing the boolean value 'false'.
   static BoolState FALSE_STATE = new BoolState(false);
 
-  /**
-   * An instance representing the boolean value 'true'.
-   */
+  /// An instance representing the boolean value 'true'.
   static BoolState TRUE_STATE = new BoolState(true);
 
-  /**
-   * A state that can be used to represent a boolean whose value is not known.
-   */
+  /// A state that can be used to represent a boolean whose value is not known.
   static BoolState UNKNOWN_VALUE = new BoolState(null);
 
-  /**
-   * The value of this instance.
-   */
+  /// The value of this instance.
   final bool value;
 
-  /**
-   * Initialize a newly created state to represent the given [value].
-   */
+  /// Initialize a newly created state to represent the given [value].
   BoolState(this.value);
 
   @override
@@ -92,8 +78,6 @@
         return UNKNOWN_VALUE;
       }
       return BoolState.from(identical(value, rightValue));
-    } else if (rightOperand is DynamicState) {
-      return UNKNOWN_VALUE;
     }
     return FALSE_STATE;
   }
@@ -134,70 +118,50 @@
   @override
   String toString() => value == null ? "-unknown-" : (value ? "true" : "false");
 
-  /**
-   * Return the boolean state representing the given boolean [value].
-   */
+  /// Return the boolean state representing the given boolean [value].
   static BoolState from(bool value) =>
       value ? BoolState.TRUE_STATE : BoolState.FALSE_STATE;
 }
 
-/**
- * Information about a const constructor invocation.
- */
+/// Information about a const constructor invocation.
 class ConstructorInvocation {
-  /**
-   * The constructor that was called.
-   */
+  /// The constructor that was called.
   final ConstructorElement constructor;
 
-  /**
-   * Values of specified arguments, actual values for positional, and `null`
-   * for named (which are provided as [namedArguments]).
-   */
+  /// Values of specified arguments, actual values for positional, and `null`
+  /// for named (which are provided as [namedArguments]).
   final List<DartObjectImpl> _argumentValues;
 
-  /**
-   * The named arguments passed to the constructor.
-   */
+  /// The named arguments passed to the constructor.
   final Map<String, DartObjectImpl> namedArguments;
 
   ConstructorInvocation(
       this.constructor, this._argumentValues, this.namedArguments);
 
-  /**
-   * The positional arguments passed to the constructor.
-   */
+  /// The positional arguments passed to the constructor.
   List<DartObjectImpl> get positionalArguments {
     return _argumentValues.takeWhile((v) => v != null).toList();
   }
 }
 
-/**
- * A representation of an instance of a Dart class.
- */
+/// A representation of an instance of a Dart class.
 class DartObjectImpl implements DartObject {
   /// When `true`, `operator==` only compares constant values, ignoring types.
   ///
   /// This is a temporary hack to work around dartbug.com/35908.
-  /// TODO(paulberry): when #35908 is fixed, remove this hack.
+  // TODO(paulberry): when #35908 is fixed, remove this hack.
   static bool _ignoreTypesInEqualityComparison = false;
 
   @override
   final ParameterizedType type;
 
-  /**
-   * The state of the object.
-   */
+  /// The state of the object.
   final InstanceState _state;
 
-  /**
-   * Initialize a newly created object to have the given [type] and [_state].
-   */
+  /// Initialize a newly created object to have the given [type] and [_state].
   DartObjectImpl(this.type, this._state);
 
-  /**
-   * Create an object to represent an unknown value.
-   */
+  /// Create an object to represent an unknown value.
   factory DartObjectImpl.validWithUnknownValue(ParameterizedType type) {
     if (type.element.library.isDartCore) {
       String typeName = type.name;
@@ -222,34 +186,24 @@
   @override
   bool get hasKnownValue => !_state.isUnknown;
 
-  /**
-   * Return `true` if this object represents an object whose type is 'bool'.
-   */
+  /// Return `true` if this object represents an object whose type is 'bool'.
   bool get isBool => _state.isBool;
 
-  /**
-   * Return `true` if this object represents an object whose type is either
-   * 'bool', 'num', 'String', or 'Null'.
-   */
+  /// Return `true` if this object represents an object whose type is either
+  /// 'bool', 'num', 'String', or 'Null'.
   bool get isBoolNumStringOrNull => _state.isBoolNumStringOrNull;
 
-  /**
-   * Return `true` if this object represents an object whose type is 'int'.
-   */
+  /// Return `true` if this object represents an object whose type is 'int'.
   bool get isInt => _state.isInt;
 
   @override
   bool get isNull => _state is NullState;
 
-  /**
-   * Return `true` if this object represents an unknown value.
-   */
+  /// Return `true` if this object represents an unknown value.
   bool get isUnknown => _state.isUnknown;
 
-  /**
-   * Return `true` if this object represents an instance of a user-defined
-   * class.
-   */
+  /// Return `true` if this object represents an instance of a user-defined
+  /// class.
   bool get isUserDefinedObject => _state is GenericState;
 
   @override
@@ -261,22 +215,18 @@
     return false;
   }
 
-  /**
-   * Return the result of invoking the '+' operator on this object with the
-   * given [rightOperand]. The [typeProvider] is the type provider used to find
-   * known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '+' operator on this object with the
+  /// given [rightOperand]. The [typeProvider] is the type provider used to find
+  /// known types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl add(TypeProvider typeProvider, DartObjectImpl rightOperand) {
     InstanceState result = _state.add(rightOperand._state);
     if (result is IntState) {
       return new DartObjectImpl(typeProvider.intType, result);
     } else if (result is DoubleState) {
       return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
     } else if (result is StringState) {
       return new DartObjectImpl(typeProvider.stringType, result);
     }
@@ -284,19 +234,15 @@
     throw new StateError("add returned a ${result.runtimeType}");
   }
 
-  /**
-   * Return the result of invoking the '~' operator on this object. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '~' operator on this object. The
+  /// [typeProvider] is the type provider used to find known types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl bitNot(TypeProvider typeProvider) =>
       new DartObjectImpl(typeProvider.intType, _state.bitNot());
 
-  /**
-   * Return the result of casting this object to the given [castType].
-   */
+  /// Return the result of casting this object to the given [castType].
   DartObjectImpl castToType(TypeProvider typeProvider, TypeSystem typeSystem,
       DartObjectImpl castType) {
     _assertType(castType);
@@ -310,26 +256,22 @@
     return this;
   }
 
-  /**
-   * Return the result of invoking the ' ' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the ' ' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl concatenate(
           TypeProvider typeProvider, DartObjectImpl rightOperand) =>
       new DartObjectImpl(
           typeProvider.stringType, _state.concatenate(rightOperand._state));
 
-  /**
-   * Return the result of applying boolean conversion to this object. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of applying boolean conversion to this object. The
+  /// [typeProvider] is the type provider used to find known types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl convertToBool(TypeProvider typeProvider) {
     InterfaceType boolType = typeProvider.boolType;
     if (identical(type, boolType)) {
@@ -338,14 +280,12 @@
     return new DartObjectImpl(boolType, _state.convertToBool());
   }
 
-  /**
-   * Return the result of invoking the '/' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for
-   * an object of this kind.
-   */
+  /// Return the result of invoking the '/' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for
+  /// an object of this kind.
   DartObjectImpl divide(
       TypeProvider typeProvider, DartObjectImpl rightOperand) {
     InstanceState result = _state.divide(rightOperand._state);
@@ -353,21 +293,17 @@
       return new DartObjectImpl(typeProvider.intType, result);
     } else if (result is DoubleState) {
       return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
     }
     // We should never get here.
     throw new StateError("divide returned a ${result.runtimeType}");
   }
 
-  /**
-   * Return the result of invoking the '&' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl eagerAnd(
       TypeProvider typeProvider, DartObjectImpl rightOperand, bool allowBool) {
     if (allowBool && isBool && rightOperand.isBool) {
@@ -381,14 +317,12 @@
         CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT);
   }
 
-  /**
-   * Return the result of invoking the '|' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '|' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl eagerOr(
       TypeProvider typeProvider, DartObjectImpl rightOperand, bool allowBool) {
     if (allowBool && isBool && rightOperand.isBool) {
@@ -402,14 +336,12 @@
         CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT);
   }
 
-  /**
-   * Return the result of invoking the '^' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '^' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl eagerXor(
       TypeProvider typeProvider, DartObjectImpl rightOperand, bool allowBool) {
     if (allowBool && isBool && rightOperand.isBool) {
@@ -423,14 +355,12 @@
         CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT);
   }
 
-  /**
-   * Return the result of invoking the '==' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '==' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl equalEqual(
       TypeProvider typeProvider, DartObjectImpl rightOperand) {
     if (isNull || rightOperand.isNull) {
@@ -467,35 +397,30 @@
     return null;
   }
 
-  /**
-   * Return the result of invoking the '&gt;' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&gt;' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl greaterThan(
           TypeProvider typeProvider, DartObjectImpl rightOperand) =>
       new DartObjectImpl(
           typeProvider.boolType, _state.greaterThan(rightOperand._state));
 
-  /**
-   * Return the result of invoking the '&gt;=' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&gt;=' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl greaterThanOrEqual(
           TypeProvider typeProvider, DartObjectImpl rightOperand) =>
       new DartObjectImpl(typeProvider.boolType,
           _state.greaterThanOrEqual(rightOperand._state));
 
-  /**
-   * Return the result of testing whether this object has the given [testedType].
-   */
+  /// Return the result of testing whether this object has the given
+  /// [testedType].
   DartObjectImpl hasType(TypeProvider typeProvider, TypeSystem typeSystem,
       DartObjectImpl testedType) {
     _assertType(testedType);
@@ -515,14 +440,12 @@
     return new DartObjectImpl(typeProvider.boolType, state);
   }
 
-  /**
-   * Return the result of invoking the '~/' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '~/' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl integerDivide(
           TypeProvider typeProvider, DartObjectImpl rightOperand) =>
       new DartObjectImpl(
@@ -532,7 +455,7 @@
   /// object and sub-objects.
   ///
   /// This is a temporary hack to work around dartbug.com/35908.
-  /// TODO(paulberry): when #35908 is fixed, remove this hack.
+  // TODO(paulberry): when #35908 is fixed, remove this hack.
   bool isEqualIgnoringTypesRecursively(Object other) {
     bool oldIgnoreTypesInEqualityComparison = _ignoreTypesInEqualityComparison;
     _ignoreTypesInEqualityComparison = true;
@@ -543,38 +466,32 @@
     }
   }
 
-  /**
-   * Return the result of invoking the identical function on this object with
-   * the [rightOperand]. The [typeProvider] is the type provider used to find
-   * known types.
-   */
+  /// Return the result of invoking the identical function on this object with
+  /// the [rightOperand]. The [typeProvider] is the type provider used to find
+  /// known types.
   DartObjectImpl isIdentical(
       TypeProvider typeProvider, DartObjectImpl rightOperand) {
     return new DartObjectImpl(
         typeProvider.boolType, _state.isIdentical(rightOperand._state));
   }
 
-  /**
-   * Return the result of invoking the '&&' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&&' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl lazyAnd(
           TypeProvider typeProvider, DartObjectImpl rightOperandComputer()) =>
       new DartObjectImpl(typeProvider.boolType,
           _state.lazyAnd(() => rightOperandComputer()?._state));
 
-  /**
-   * Return the result of invoking the '==' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '==' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl lazyEqualEqual(
       TypeProvider typeProvider, DartObjectImpl rightOperand) {
     if (isNull || rightOperand.isNull) {
@@ -592,129 +509,107 @@
         CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
   }
 
-  /**
-   * Return the result of invoking the '||' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '||' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl lazyOr(
           TypeProvider typeProvider, DartObjectImpl rightOperandComputer()) =>
       new DartObjectImpl(typeProvider.boolType,
           _state.lazyOr(() => rightOperandComputer()?._state));
 
-  /**
-   * Return the result of invoking the '&lt;' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&lt;' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl lessThan(
           TypeProvider typeProvider, DartObjectImpl rightOperand) =>
       new DartObjectImpl(
           typeProvider.boolType, _state.lessThan(rightOperand._state));
 
-  /**
-   * Return the result of invoking the '&lt;=' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&lt;=' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl lessThanOrEqual(
           TypeProvider typeProvider, DartObjectImpl rightOperand) =>
       new DartObjectImpl(
           typeProvider.boolType, _state.lessThanOrEqual(rightOperand._state));
 
-  /**
-   * Return the result of invoking the '!' operator on this object. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '!' operator on this object. The
+  /// [typeProvider] is the type provider used to find known types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl logicalNot(TypeProvider typeProvider) =>
       new DartObjectImpl(typeProvider.boolType, _state.logicalNot());
 
-  /**
-   * Return the result of invoking the '&gt;&gt;&gt;' operator on this object
-   * with the [rightOperand]. The [typeProvider] is the type provider used to
-   * find known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&gt;&gt;&gt;' operator on this object
+  /// with the [rightOperand]. The [typeProvider] is the type provider used to
+  /// find known types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl logicalShiftRight(
           TypeProvider typeProvider, DartObjectImpl rightOperand) =>
       new DartObjectImpl(
           typeProvider.intType, _state.logicalShiftRight(rightOperand._state));
 
-  /**
-   * Return the result of invoking the '-' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '-' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl minus(TypeProvider typeProvider, DartObjectImpl rightOperand) {
     InstanceState result = _state.minus(rightOperand._state);
     if (result is IntState) {
       return new DartObjectImpl(typeProvider.intType, result);
     } else if (result is DoubleState) {
       return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
     }
     // We should never get here.
     throw new StateError("minus returned a ${result.runtimeType}");
   }
 
-  /**
-   * Return the result of invoking the '-' operator on this object. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '-' operator on this object. The
+  /// [typeProvider] is the type provider used to find known types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl negated(TypeProvider typeProvider) {
     InstanceState result = _state.negated();
     if (result is IntState) {
       return new DartObjectImpl(typeProvider.intType, result);
     } else if (result is DoubleState) {
       return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
     }
     // We should never get here.
     throw new StateError("negated returned a ${result.runtimeType}");
   }
 
-  /**
-   * Return the result of invoking the '!=' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '!=' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl notEqual(
       TypeProvider typeProvider, DartObjectImpl rightOperand) {
     return equalEqual(typeProvider, rightOperand).logicalNot(typeProvider);
   }
 
-  /**
-   * Return the result of converting this object to a 'String'. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the object cannot be converted to a
-   * 'String'.
-   */
+  /// Return the result of converting this object to a 'String'. The
+  /// [typeProvider] is the type provider used to find known types.
+  ///
+  /// Throws an [EvaluationException] if the object cannot be converted to a
+  /// 'String'.
   DartObjectImpl performToString(TypeProvider typeProvider) {
     InterfaceType stringType = typeProvider.stringType;
     if (identical(type, stringType)) {
@@ -723,14 +618,12 @@
     return new DartObjectImpl(stringType, _state.convertToString());
   }
 
-  /**
-   * Return the result of invoking the '%' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '%' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl remainder(
       TypeProvider typeProvider, DartObjectImpl rightOperand) {
     InstanceState result = _state.remainder(rightOperand._state);
@@ -738,65 +631,53 @@
       return new DartObjectImpl(typeProvider.intType, result);
     } else if (result is DoubleState) {
       return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
     }
     // We should never get here.
     throw new StateError("remainder returned a ${result.runtimeType}");
   }
 
-  /**
-   * Return the result of invoking the '&lt;&lt;' operator on this object with
-   * the [rightOperand]. The [typeProvider] is the type provider used to find
-   * known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&lt;&lt;' operator on this object with
+  /// the [rightOperand]. The [typeProvider] is the type provider used to find
+  /// known types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl shiftLeft(
           TypeProvider typeProvider, DartObjectImpl rightOperand) =>
       new DartObjectImpl(
           typeProvider.intType, _state.shiftLeft(rightOperand._state));
 
-  /**
-   * Return the result of invoking the '&gt;&gt;' operator on this object with
-   * the [rightOperand]. The [typeProvider] is the type provider used to find
-   * known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&gt;&gt;' operator on this object with
+  /// the [rightOperand]. The [typeProvider] is the type provider used to find
+  /// known types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl shiftRight(
           TypeProvider typeProvider, DartObjectImpl rightOperand) =>
       new DartObjectImpl(
           typeProvider.intType, _state.shiftRight(rightOperand._state));
 
-  /**
-   * Return the result of invoking the 'length' getter on this object. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the 'length' getter on this object. The
+  /// [typeProvider] is the type provider used to find known types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl stringLength(TypeProvider typeProvider) =>
       new DartObjectImpl(typeProvider.intType, _state.stringLength());
 
-  /**
-   * Return the result of invoking the '*' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '*' operator on this object with the
+  /// [rightOperand]. The [typeProvider] is the type provider used to find known
+  /// types.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   DartObjectImpl times(TypeProvider typeProvider, DartObjectImpl rightOperand) {
     InstanceState result = _state.times(rightOperand._state);
     if (result is IntState) {
       return new DartObjectImpl(typeProvider.intType, result);
     } else if (result is DoubleState) {
       return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
     }
     // We should never get here.
     throw new StateError("times returned a ${result.runtimeType}");
@@ -820,10 +701,8 @@
     return null;
   }
 
-  /**
-   * If this constant represents a library function or static method, returns
-   * it, otherwise returns `null`.
-   */
+  /// If this constant represents a library function or static method, returns
+  /// it, otherwise returns `null`.
   ExecutableElement toFunctionValue() {
     InstanceState state = _state;
     return state is FunctionState ? state._element : null;
@@ -895,10 +774,8 @@
     return null;
   }
 
-  /**
-   * Throw an exception if the given [object]'s state does not represent a Type
-   * value.
-   */
+  /// Throw an exception if the given [object]'s state does not represent a Type
+  /// value.
   void _assertType(DartObjectImpl object) {
     if (object._state is! TypeState) {
       throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_TYPE);
@@ -906,33 +783,22 @@
   }
 }
 
-/**
- * The state of an object representing a double.
- */
+/// The state of an object representing a double.
 class DoubleState extends NumState {
-  /**
-   * A state that can be used to represent a double whose value is not known.
-   */
+  /// A state that can be used to represent a double whose value is not known.
   static DoubleState UNKNOWN_VALUE = new DoubleState(null);
 
-  /**
-   * The value of this instance.
-   */
+  /// The value of this instance.
   final double value;
 
-  /**
-   * Initialize a newly created state to represent a double with the given
-   * [value].
-   */
+  /// Initialize a newly created state to represent a double with the given
+  /// [value].
   DoubleState(this.value);
 
   @override
   int get hashCode => value == null ? 0 : value.hashCode;
 
   @override
-  bool get isBoolNumStringOrNull => true;
-
-  @override
   bool get isUnknown => value == null;
 
   @override
@@ -960,8 +826,6 @@
         return UNKNOWN_VALUE;
       }
       return new DoubleState(value + rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -993,20 +857,12 @@
         return UNKNOWN_VALUE;
       }
       return new DoubleState(value / rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
   BoolState greaterThan(InstanceState rightOperand) {
     assertNumOrNull(rightOperand);
     if (value == null) {
@@ -1024,8 +880,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(value > rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -1049,8 +903,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(value >= rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -1076,8 +928,6 @@
       }
       double result = value / rightValue;
       return new IntState(result.toInt());
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return IntState.UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -1100,8 +950,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(value == rightValue.toDouble());
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     return BoolState.FALSE_STATE;
   }
@@ -1129,8 +977,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(value < rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -1154,8 +1000,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(value <= rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -1179,8 +1023,6 @@
         return UNKNOWN_VALUE;
       }
       return new DoubleState(value - rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -1212,8 +1054,6 @@
         return UNKNOWN_VALUE;
       }
       return new DoubleState(value % rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -1237,8 +1077,6 @@
         return UNKNOWN_VALUE;
       }
       return new DoubleState(value * rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -1248,207 +1086,22 @@
   String toString() => value == null ? "-unknown-" : value.toString();
 }
 
-/**
- * The state of an object representing a Dart object for which there is no type
- * information.
- */
-class DynamicState extends InstanceState {
-  /**
-   * The unique instance of this class.
-   */
-  static DynamicState DYNAMIC_STATE = new DynamicState();
-
-  @override
-  bool get isBool => true;
-
-  @override
-  bool get isBoolNumStringOrNull => true;
-
-  @override
-  String get typeName => "dynamic";
-
-  @override
-  NumState add(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return _unknownNum(rightOperand);
-  }
-
-  @override
-  IntState bitAnd(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  IntState bitNot() => IntState.UNKNOWN_VALUE;
-
-  @override
-  IntState bitOr(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  IntState bitXor(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  StringState concatenate(InstanceState rightOperand) {
-    assertString(rightOperand);
-    return StringState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState convertToBool() => BoolState.UNKNOWN_VALUE;
-
-  @override
-  StringState convertToString() => StringState.UNKNOWN_VALUE;
-
-  @override
-  NumState divide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return _unknownNum(rightOperand);
-  }
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState greaterThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState greaterThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  IntState integerDivide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState lazyAnd(InstanceState rightOperandComputer()) {
-    assertBool(rightOperandComputer());
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState lazyOr(InstanceState rightOperandComputer()) {
-    InstanceState rightOperand = rightOperandComputer();
-    assertBool(rightOperand);
-    return rightOperand.convertToBool();
-  }
-
-  @override
-  BoolState lessThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState lessThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState logicalNot() => BoolState.UNKNOWN_VALUE;
-
-  @override
-  NumState minus(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return _unknownNum(rightOperand);
-  }
-
-  @override
-  NumState negated() => NumState.UNKNOWN_VALUE;
-
-  @override
-  NumState remainder(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return _unknownNum(rightOperand);
-  }
-
-  @override
-  IntState shiftLeft(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  IntState shiftRight(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  NumState times(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return _unknownNum(rightOperand);
-  }
-
-  /**
-   * Return an object representing an unknown numeric value whose type is based
-   * on the type of the [rightOperand].
-   */
-  NumState _unknownNum(InstanceState rightOperand) {
-    if (rightOperand is IntState) {
-      return IntState.UNKNOWN_VALUE;
-    } else if (rightOperand is DoubleState) {
-      return DoubleState.UNKNOWN_VALUE;
-    }
-    return NumState.UNKNOWN_VALUE;
-  }
-}
-
-/**
- * Exception that would be thrown during the evaluation of Dart code.
- */
+/// Exception that would be thrown during the evaluation of Dart code.
 class EvaluationException {
-  /**
-   * The error code associated with the exception.
-   */
+  /// The error code associated with the exception.
   final ErrorCode errorCode;
 
-  /**
-   * Initialize a newly created exception to have the given [errorCode].
-   */
+  /// Initialize a newly created exception to have the given [errorCode].
   EvaluationException(this.errorCode);
 }
 
-/**
- * The state of an object representing a function.
- */
+/// The state of an object representing a function.
 class FunctionState extends InstanceState {
-  /**
-   * The element representing the function being modeled.
-   */
+  /// The element representing the function being modeled.
   final ExecutableElement _element;
 
-  /**
-   * Initialize a newly created state to represent the function with the given
-   * [element].
-   */
+  /// Initialize a newly created state to represent the function with the given
+  /// [element].
   FunctionState(this._element);
 
   @override
@@ -1485,8 +1138,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(_element == rightElement);
-    } else if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     return BoolState.FALSE_STATE;
   }
@@ -1500,36 +1151,24 @@
   String toString() => _element == null ? "-unknown-" : _element.name;
 }
 
-/**
- * The state of an object representing a Dart object for which there is no more
- * specific state.
- */
+/// The state of an object representing a Dart object for which there is no more
+/// specific state.
 class GenericState extends InstanceState {
-  /**
-   * Pseudo-field that we use to represent fields in the superclass.
-   */
+  /// Pseudo-field that we use to represent fields in the superclass.
   static String SUPERCLASS_FIELD = "(super)";
 
-  /**
-   * A state that can be used to represent an object whose state is not known.
-   */
+  /// A state that can be used to represent an object whose state is not known.
   static GenericState UNKNOWN_VALUE =
       new GenericState(new HashMap<String, DartObjectImpl>());
 
-  /**
-   * The values of the fields of this instance.
-   */
+  /// The values of the fields of this instance.
   final Map<String, DartObjectImpl> _fieldMap;
 
-  /**
-   * Information about the constructor invoked to generate this instance.
-   */
+  /// Information about the constructor invoked to generate this instance.
   final ConstructorInvocation invocation;
 
-  /**
-   * Initialize a newly created state to represent a newly created object. The
-   * [fieldMap] contains the values of the fields of the instance.
-   */
+  /// Initialize a newly created state to represent a newly created object. The
+  /// [fieldMap] contains the values of the fields of the instance.
   GenericState(this._fieldMap, {this.invocation});
 
   @override
@@ -1582,9 +1221,6 @@
 
   @override
   BoolState isIdentical(InstanceState rightOperand) {
-    if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
     return BoolState.from(this == rightOperand);
   }
 
@@ -1613,54 +1249,36 @@
   }
 }
 
-/**
- * The state of an object representing a Dart object.
- */
+/// The state of an object representing a Dart object.
 abstract class InstanceState {
-  /**
-   * If this represents a generic dart object, return a map from its field names
-   * to their values. Otherwise return null.
-   */
+  /// If this represents a generic dart object, return a map from its field
+  /// names to their values. Otherwise return null.
   Map<String, DartObjectImpl> get fields => null;
 
-  /**
-   * Return `true` if this object represents an object whose type is 'bool'.
-   */
+  /// Return `true` if this object represents an object whose type is 'bool'.
   bool get isBool => false;
 
-  /**
-   * Return `true` if this object represents an object whose type is either
-   * 'bool', 'num', 'String', or 'Null'.
-   */
+  /// Return `true` if this object represents an object whose type is either
+  /// 'bool', 'num', 'String', or 'Null'.
   bool get isBoolNumStringOrNull => false;
 
-  /**
-   * Return `true` if this object represents an object whose type is 'int'.
-   */
+  /// Return `true` if this object represents an object whose type is 'int'.
   bool get isInt => false;
 
-  /**
-   * Return `true` if this object represents the value 'null'.
-   */
+  /// Return `true` if this object represents the value 'null'.
   bool get isNull => false;
 
-  /**
-   * Return `true` if this object represents an unknown value.
-   */
+  /// Return `true` if this object represents an unknown value.
   bool get isUnknown => false;
 
-  /**
-   * Return the name of the type of this value.
-   */
+  /// Return the name of the type of this value.
   String get typeName;
 
-  /**
-   * Return the result of invoking the '+' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '+' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   InstanceState add(InstanceState rightOperand) {
     if (this is StringState && rightOperand is StringState) {
       return concatenate(rightOperand);
@@ -1671,75 +1289,53 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Throw an exception if the given [state] does not represent a boolean value.
-   */
+  /// Throw an exception if the given [state] does not represent a boolean value.
   void assertBool(InstanceState state) {
-    if (!(state is BoolState || state is DynamicState)) {
+    if (state is! BoolState) {
       throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
     }
   }
 
-  /**
-   * Throw an exception if the given [state] does not represent a boolean,
-   * numeric, string or null value.
-   */
+  /// Throw an exception if the given [state] does not represent a boolean,
+  /// numeric, string or null value.
   void assertBoolNumStringOrNull(InstanceState state) {
     if (!(state is BoolState ||
-        state is DoubleState ||
-        state is IntState ||
         state is NumState ||
         state is StringState ||
-        state is NullState ||
-        state is DynamicState)) {
+        state is NullState)) {
       throw new EvaluationException(
           CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
     }
   }
 
-  /**
-   * Throw an exception if the given [state] does not represent an integer or
-   * null value.
-   */
+  /// Throw an exception if the given [state] does not represent an integer or
+  /// null value.
   void assertIntOrNull(InstanceState state) {
-    if (!(state is IntState ||
-        state is NumState ||
-        state is NullState ||
-        state is DynamicState)) {
+    if (!(state is IntState || state is NullState)) {
       throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
     }
   }
 
-  /**
-   * Throw an exception if the given [state] does not represent a boolean,
-   * numeric, string or null value.
-   */
+  /// Throw an exception if the given [state] does not represent a boolean,
+  /// numeric, string or null value.
   void assertNumOrNull(InstanceState state) {
-    if (!(state is DoubleState ||
-        state is IntState ||
-        state is NumState ||
-        state is NullState ||
-        state is DynamicState)) {
+    if (!(state is NumState || state is NullState)) {
       throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
     }
   }
 
-  /**
-   * Throw an exception if the given [state] does not represent a String value.
-   */
+  /// Throw an exception if the given [state] does not represent a String value.
   void assertString(InstanceState state) {
-    if (!(state is StringState || state is DynamicState)) {
+    if (state is! StringState) {
       throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
     }
   }
 
-  /**
-   * Return the result of invoking the '&' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   IntState bitAnd(InstanceState rightOperand) {
     assertIntOrNull(this);
     assertIntOrNull(rightOperand);
@@ -1747,25 +1343,21 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '~' operator on this object.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '~' operator on this object.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   IntState bitNot() {
     assertIntOrNull(this);
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '|' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '|' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   IntState bitOr(InstanceState rightOperand) {
     assertIntOrNull(this);
     assertIntOrNull(rightOperand);
@@ -1773,13 +1365,11 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '^' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '^' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   IntState bitXor(InstanceState rightOperand) {
     assertIntOrNull(this);
     assertIntOrNull(rightOperand);
@@ -1787,42 +1377,34 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the ' ' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the ' ' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   StringState concatenate(InstanceState rightOperand) {
     assertString(rightOperand);
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of applying boolean conversion to this object.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of applying boolean conversion to this object.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState convertToBool() => BoolState.FALSE_STATE;
 
-  /**
-   * Return the result of converting this object to a String.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of converting this object to a String.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   StringState convertToString();
 
-  /**
-   * Return the result of invoking the '/' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '/' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   NumState divide(InstanceState rightOperand) {
     assertNumOrNull(this);
     assertNumOrNull(rightOperand);
@@ -1830,22 +1412,18 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '==' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '==' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState equalEqual(InstanceState rightOperand);
 
-  /**
-   * Return the result of invoking the '&gt;' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&gt;' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState greaterThan(InstanceState rightOperand) {
     assertNumOrNull(this);
     assertNumOrNull(rightOperand);
@@ -1853,13 +1431,11 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '&gt;=' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&gt;=' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState greaterThanOrEqual(InstanceState rightOperand) {
     assertNumOrNull(this);
     assertNumOrNull(rightOperand);
@@ -1867,13 +1443,11 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '~/' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '~/' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   IntState integerDivide(InstanceState rightOperand) {
     assertNumOrNull(this);
     assertNumOrNull(rightOperand);
@@ -1881,19 +1455,15 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the identical function on this object with
-   * the [rightOperand].
-   */
+  /// Return the result of invoking the identical function on this object with
+  /// the [rightOperand].
   BoolState isIdentical(InstanceState rightOperand);
 
-  /**
-   * Return the result of invoking the '&&' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&&' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState lazyAnd(InstanceState rightOperandComputer()) {
     assertBool(this);
     if (convertToBool() == BoolState.FALSE_STATE) {
@@ -1904,22 +1474,18 @@
     return rightOperand.convertToBool();
   }
 
-  /**
-   * Return the result of invoking the '==' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '==' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState lazyEqualEqual(InstanceState rightOperand);
 
-  /**
-   * Return the result of invoking the '||' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '||' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState lazyOr(InstanceState rightOperandComputer()) {
     assertBool(this);
     if (convertToBool() == BoolState.TRUE_STATE) {
@@ -1930,13 +1496,11 @@
     return rightOperand.convertToBool();
   }
 
-  /**
-   * Return the result of invoking the '&lt;' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&lt;' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState lessThan(InstanceState rightOperand) {
     assertNumOrNull(this);
     assertNumOrNull(rightOperand);
@@ -1944,13 +1508,11 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '&lt;=' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&lt;=' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState lessThanOrEqual(InstanceState rightOperand) {
     assertNumOrNull(this);
     assertNumOrNull(rightOperand);
@@ -1958,13 +1520,11 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '&' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState logicalAnd(InstanceState rightOperand) {
     assertBool(this);
     assertBool(rightOperand);
@@ -1976,24 +1536,20 @@
     return BoolState.from(leftValue & rightValue);
   }
 
-  /**
-   * Return the result of invoking the '!' operator on this object.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '!' operator on this object.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState logicalNot() {
     assertBool(this);
     return BoolState.TRUE_STATE;
   }
 
-  /**
-   * Return the result of invoking the '|' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '|' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState logicalOr(InstanceState rightOperand) {
     assertBool(this);
     assertBool(rightOperand);
@@ -2005,13 +1561,11 @@
     return BoolState.from(leftValue | rightValue);
   }
 
-  /**
-   * Return the result of invoking the '&gt;&gt;' operator on this object with
-   * the [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&gt;&gt;' operator on this object with
+  /// the [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   IntState logicalShiftRight(InstanceState rightOperand) {
     assertIntOrNull(this);
     assertIntOrNull(rightOperand);
@@ -2019,13 +1573,11 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '^' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '^' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   BoolState logicalXor(InstanceState rightOperand) {
     assertBool(this);
     assertBool(rightOperand);
@@ -2037,13 +1589,11 @@
     return BoolState.from(leftValue ^ rightValue);
   }
 
-  /**
-   * Return the result of invoking the '-' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '-' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   NumState minus(InstanceState rightOperand) {
     assertNumOrNull(this);
     assertNumOrNull(rightOperand);
@@ -2051,25 +1601,21 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '-' operator on this object.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '-' operator on this object.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   NumState negated() {
     assertNumOrNull(this);
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '%' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '%' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   NumState remainder(InstanceState rightOperand) {
     assertNumOrNull(this);
     assertNumOrNull(rightOperand);
@@ -2077,13 +1623,11 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '&lt;&lt;' operator on this object with
-   * the [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&lt;&lt;' operator on this object with
+  /// the [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   IntState shiftLeft(InstanceState rightOperand) {
     assertIntOrNull(this);
     assertIntOrNull(rightOperand);
@@ -2091,13 +1635,11 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '&gt;&gt;' operator on this object with
-   * the [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '&gt;&gt;' operator on this object with
+  /// the [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   IntState shiftRight(InstanceState rightOperand) {
     assertIntOrNull(this);
     assertIntOrNull(rightOperand);
@@ -2105,25 +1647,21 @@
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the 'length' getter on this object.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the 'length' getter on this object.
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   IntState stringLength() {
     assertString(this);
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
-  /**
-   * Return the result of invoking the '*' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
+  /// Return the result of invoking the '*' operator on this object with the
+  /// [rightOperand].
+  ///
+  /// Throws an [EvaluationException] if the operator is not appropriate for an
+  /// object of this kind.
   NumState times(InstanceState rightOperand) {
     assertNumOrNull(this);
     assertNumOrNull(rightOperand);
@@ -2132,33 +1670,22 @@
   }
 }
 
-/**
- * The state of an object representing an int.
- */
+/// The state of an object representing an int.
 class IntState extends NumState {
-  /**
-   * A state that can be used to represent an int whose value is not known.
-   */
+  /// A state that can be used to represent an int whose value is not known.
   static IntState UNKNOWN_VALUE = new IntState(null);
 
-  /**
-   * The value of this instance.
-   */
+  /// The value of this instance.
   final int value;
 
-  /**
-   * Initialize a newly created state to represent an int with the given
-   * [value].
-   */
+  /// Initialize a newly created state to represent an int with the given
+  /// [value].
   IntState(this.value);
 
   @override
   int get hashCode => value == null ? 0 : value.hashCode;
 
   @override
-  bool get isBoolNumStringOrNull => true;
-
-  @override
   bool get isInt => true;
 
   @override
@@ -2192,8 +1719,6 @@
         return DoubleState.UNKNOWN_VALUE;
       }
       return new DoubleState(value.toDouble() + rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2211,8 +1736,6 @@
         return UNKNOWN_VALUE;
       }
       return new IntState(value & rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2238,8 +1761,6 @@
         return UNKNOWN_VALUE;
       }
       return new IntState(value | rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2257,8 +1778,6 @@
         return UNKNOWN_VALUE;
       }
       return new IntState(value ^ rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2291,20 +1810,12 @@
         return DoubleState.UNKNOWN_VALUE;
       }
       return new DoubleState(value.toDouble() / rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return DoubleState.UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
   BoolState greaterThan(InstanceState rightOperand) {
     assertNumOrNull(rightOperand);
     if (value == null) {
@@ -2322,8 +1833,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(value.toDouble() > rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2347,8 +1856,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(value.toDouble() >= rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2376,8 +1883,6 @@
       }
       double result = value.toDouble() / rightValue;
       return new IntState(result.toInt());
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2400,8 +1905,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(rightValue == value.toDouble());
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     return BoolState.FALSE_STATE;
   }
@@ -2429,8 +1932,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(value.toDouble() < rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2454,8 +1955,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(value.toDouble() <= rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2487,8 +1986,6 @@
         }
         return new IntState(value ~/ divisor);
       }
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2515,8 +2012,6 @@
         return DoubleState.UNKNOWN_VALUE;
       }
       return new DoubleState(value.toDouble() - rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2553,8 +2048,6 @@
         return DoubleState.UNKNOWN_VALUE;
       }
       return new DoubleState(value.toDouble() % rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2576,8 +2069,6 @@
       if (rightValue >= 0) {
         return new IntState(value << rightValue);
       }
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2599,8 +2090,6 @@
       if (rightValue >= 0) {
         return new IntState(value >> rightValue);
       }
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2627,8 +2116,6 @@
         return DoubleState.UNKNOWN_VALUE;
       }
       return new DoubleState(value.toDouble() * rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
     }
     throw new EvaluationException(
         CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -2638,19 +2125,13 @@
   String toString() => value == null ? "-unknown-" : value.toString();
 }
 
-/**
- * The state of an object representing a list.
- */
+/// The state of an object representing a list.
 class ListState extends InstanceState {
-  /**
-   * The elements of the list.
-   */
+  /// The elements of the list.
   final List<DartObjectImpl> _elements;
 
-  /**
-   * Initialize a newly created state to represent a list with the given
-   * [elements].
-   */
+  /// Initialize a newly created state to represent a list with the given
+  /// [elements].
   ListState(this._elements);
 
   @override
@@ -2697,9 +2178,6 @@
 
   @override
   BoolState isIdentical(InstanceState rightOperand) {
-    if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
     return BoolState.from(this == rightOperand);
   }
 
@@ -2726,19 +2204,13 @@
   }
 }
 
-/**
- * The state of an object representing a map.
- */
+/// The state of an object representing a map.
 class MapState extends InstanceState {
-  /**
-   * The entries in the map.
-   */
+  /// The entries in the map.
   final Map<DartObjectImpl, DartObjectImpl> _entries;
 
-  /**
-   * Initialize a newly created state to represent a map with the given
-   * [entries].
-   */
+  /// Initialize a newly created state to represent a map with the given
+  /// [entries].
   MapState(this._entries);
 
   @override
@@ -2786,9 +2258,6 @@
 
   @override
   BoolState isIdentical(InstanceState rightOperand) {
-    if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
     return BoolState.from(this == rightOperand);
   }
 
@@ -2817,13 +2286,9 @@
   }
 }
 
-/**
- * The state of an object representing the value 'null'.
- */
+/// The state of an object representing the value 'null'.
 class NullState extends InstanceState {
-  /**
-   * An instance representing the boolean value 'null'.
-   */
+  /// An instance representing the boolean value 'null'.
   static NullState NULL_STATE = new NullState();
 
   @override
@@ -2858,9 +2323,6 @@
 
   @override
   BoolState isIdentical(InstanceState rightOperand) {
-    if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
     return BoolState.from(rightOperand is NullState);
   }
 
@@ -2879,140 +2341,25 @@
   String toString() => "null";
 }
 
-/**
- * The state of an object representing a number of an unknown type (a 'num').
- */
-class NumState extends InstanceState {
-  /**
-   * A state that can be used to represent a number whose value is not known.
-   */
-  static NumState UNKNOWN_VALUE = new NumState();
-
-  @override
-  int get hashCode => 7;
-
+/// The state of an object representing a number.
+abstract class NumState extends InstanceState {
   @override
   bool get isBoolNumStringOrNull => true;
 
   @override
-  bool get isUnknown => identical(this, UNKNOWN_VALUE);
-
-  @override
-  String get typeName => "num";
-
-  @override
-  bool operator ==(Object object) => object is NumState;
-
-  @override
-  NumState add(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return UNKNOWN_VALUE;
-  }
-
-  @override
-  StringState convertToString() => StringState.UNKNOWN_VALUE;
-
-  @override
-  NumState divide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return DoubleState.UNKNOWN_VALUE;
-  }
-
-  @override
   BoolState equalEqual(InstanceState rightOperand) {
     assertBoolNumStringOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
+    return isIdentical(rightOperand);
   }
-
-  @override
-  BoolState greaterThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState greaterThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  IntState integerDivide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return IntState.UNKNOWN_VALUE;
-      } else if (rightValue == 0) {
-        throw new EvaluationException(
-            CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
-      }
-    } else if (rightOperand is DynamicState) {
-      return IntState.UNKNOWN_VALUE;
-    }
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState lessThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState lessThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  NumState minus(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return UNKNOWN_VALUE;
-  }
-
-  @override
-  NumState negated() => UNKNOWN_VALUE;
-
-  @override
-  NumState remainder(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return UNKNOWN_VALUE;
-  }
-
-  @override
-  NumState times(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return UNKNOWN_VALUE;
-  }
-
-  @override
-  String toString() => "-unknown-";
 }
 
-/**
- * The state of an object representing a set.
- */
+/// The state of an object representing a set.
 class SetState extends InstanceState {
-  /**
-   * The elements of the set.
-   */
+  /// The elements of the set.
   final Set<DartObjectImpl> _elements;
 
-  /**
-   * Initialize a newly created state to represent a set with the given
-   * [elements].
-   */
+  /// Initialize a newly created state to represent a set with the given
+  /// [elements].
   SetState(this._elements);
 
   @override
@@ -3059,9 +2406,6 @@
 
   @override
   BoolState isIdentical(InstanceState rightOperand) {
-    if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
     return BoolState.from(this == rightOperand);
   }
 
@@ -3088,23 +2432,15 @@
   }
 }
 
-/**
- * The state of an object representing a string.
- */
+/// The state of an object representing a string.
 class StringState extends InstanceState {
-  /**
-   * A state that can be used to represent a double whose value is not known.
-   */
+  /// A state that can be used to represent a double whose value is not known.
   static StringState UNKNOWN_VALUE = new StringState(null);
 
-  /**
-   * The value of this instance.
-   */
+  /// The value of this instance.
   final String value;
 
-  /**
-   * Initialize a newly created state to represent the given [value].
-   */
+  /// Initialize a newly created state to represent the given [value].
   StringState(this.value);
 
   @override
@@ -3134,8 +2470,6 @@
         return UNKNOWN_VALUE;
       }
       return new StringState("$value$rightValue");
-    } else if (rightOperand is DynamicState) {
-      return UNKNOWN_VALUE;
     }
     return super.concatenate(rightOperand);
   }
@@ -3160,8 +2494,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(value == rightValue);
-    } else if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     return BoolState.FALSE_STATE;
   }
@@ -3183,18 +2515,12 @@
   String toString() => value == null ? "-unknown-" : "'$value'";
 }
 
-/**
- * The state of an object representing a symbol.
- */
+/// The state of an object representing a symbol.
 class SymbolState extends InstanceState {
-  /**
-   * The value of this instance.
-   */
+  /// The value of this instance.
   final String value;
 
-  /**
-   * Initialize a newly created state to represent the given [value].
-   */
+  /// Initialize a newly created state to represent the given [value].
   SymbolState(this.value);
 
   @override
@@ -3232,8 +2558,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(value == rightValue);
-    } else if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     return BoolState.FALSE_STATE;
   }
@@ -3247,18 +2571,12 @@
   String toString() => value == null ? "-unknown-" : "#$value";
 }
 
-/**
- * The state of an object representing a type.
- */
+/// The state of an object representing a type.
 class TypeState extends InstanceState {
-  /**
-   * The element representing the type being modeled.
-   */
+  /// The element representing the type being modeled.
   final DartType _type;
 
-  /**
-   * Initialize a newly created state to represent the given [value].
-   */
+  /// Initialize a newly created state to represent the given [value].
   TypeState(this._type);
 
   @override
@@ -3296,8 +2614,6 @@
         return BoolState.UNKNOWN_VALUE;
       }
       return BoolState.from(_type == rightType);
-    } else if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
     }
     return BoolState.FALSE_STATE;
   }
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index 0997e08..8086e2c 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -83,7 +83,7 @@
     SimpleIdentifier className = node.name;
     ClassElementImpl element = new ClassElementImpl.forNode(className);
     className.staticElement = element;
-    element.abstract = node.isAbstract;
+    element.isAbstract = node.isAbstract;
     _fillClassElement(node, element, holder);
 
     _currentHolder.addType(element);
@@ -97,7 +97,7 @@
     ClassElementImpl element = new ClassElementImpl.forNode(className);
     _setCodeRange(element, node);
     element.metadata = _createElementAnnotations(node.metadata);
-    element.abstract = node.abstractKeyword != null;
+    element.isAbstract = node.abstractKeyword != null;
     element.mixinApplication = true;
     element.typeParameters = holder.typeParameters;
     setElementDocumentationComment(element, node);
@@ -430,7 +430,7 @@
         _setCodeRange(element, node);
         element.metadata = _createElementAnnotations(node.metadata);
         setElementDocumentationComment(element, node);
-        element.abstract = node.isAbstract;
+        element.isAbstract = node.isAbstract;
         if (node.externalKeyword != null || body is NativeFunctionBody) {
           element.external = true;
         }
@@ -482,7 +482,7 @@
             getter.generator = true;
           }
           getter.variable = field;
-          getter.abstract = node.isAbstract;
+          getter.isAbstract = node.isAbstract;
           getter.getter = true;
           getter.isStatic = isStatic;
           field.getter = getter;
@@ -511,7 +511,7 @@
             setter.generator = true;
           }
           setter.variable = field;
-          setter.abstract = node.isAbstract;
+          setter.isAbstract = node.isAbstract;
           setter.setter = true;
           setter.isStatic = isStatic;
           if (node.returnType == null) {
@@ -1523,6 +1523,7 @@
     FunctionType type = new FunctionTypeImpl(element);
     element.type = type;
     (node as GenericFunctionTypeImpl).type = type;
+    (node as GenericFunctionTypeImpl).declaredElement = element;
     holder.validate();
   }
 
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index f2db8f0..cf5423c 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -18,6 +18,7 @@
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisEngine, AnalysisOptionsImpl;
@@ -454,6 +455,9 @@
   /// methods might be different.
   int version = 0;
 
+  /// This callback is set during mixins inference to handle reentrant calls.
+  List<InterfaceType> Function(ClassElementImpl) linkedMixinInferenceCallback;
+
   /// 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.
   ClassElementImpl(String name, int offset)
@@ -476,9 +480,9 @@
       : super.forSerialized(enclosingUnit);
 
   /// Set whether this class is abstract.
+  @Deprecated('Use isAbstract instead')
   void set abstract(bool isAbstract) {
-    _assertNotResynthesized(_unlinkedClass);
-    setModifier(Modifier.ABSTRACT, isAbstract);
+    this.isAbstract = isAbstract;
   }
 
   @override
@@ -555,12 +559,24 @@
       _constructors = context.getConstructors(linkedNode).map((node) {
         var name = node.name?.name ?? '';
         var reference = containerRef.getChild(name);
-        if (reference.element == null) {
-          reference.node2 = node;
-          ConstructorElementImpl.forLinkedNode(this, reference, node);
+        if (reference.hasElementFor(node)) {
+          return reference.element as ConstructorElement;
         }
-        return reference.element as ConstructorElement;
+        return ConstructorElementImpl.forLinkedNode(this, reference, node);
       }).toList();
+
+      if (_constructors.isEmpty) {
+        return _constructors = [
+          ConstructorElementImpl.forLinkedNode(
+            this,
+            containerRef.getChild(''),
+            null,
+          )
+            ..isSynthetic = true
+            ..name = ''
+            ..nameOffset = -1,
+        ];
+      }
     }
 
     if (_unlinkedClass != null) {
@@ -809,6 +825,12 @@
     return hasModifier(Modifier.ABSTRACT);
   }
 
+  /// Set whether this class is abstract.
+  void set isAbstract(bool isAbstract) {
+    _assertNotResynthesized(_unlinkedClass);
+    setModifier(Modifier.ABSTRACT, isAbstract);
+  }
+
   @override
   bool get isMixinApplication {
     if (linkedNode != null) {
@@ -882,11 +904,10 @@
           .map((node) {
         var name = node.name.name;
         var reference = containerRef.getChild(name);
-        if (reference.element == null) {
-          reference.node2 = node;
-          MethodElementImpl.forLinkedNode(this, reference, node);
+        if (reference.hasElementFor(node)) {
+          return reference.element as MethodElement;
         }
-        return reference.element as MethodElement;
+        return MethodElementImpl.forLinkedNode(this, reference, node);
       }).toList();
     }
 
@@ -939,6 +960,10 @@
 
   @override
   List<InterfaceType> get mixins {
+    if (linkedMixinInferenceCallback != null) {
+      _mixins = linkedMixinInferenceCallback(this);
+    }
+
     if (_mixins != null) {
       return _mixins;
     }
@@ -1009,6 +1034,10 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getNameOffset(linkedNode);
+    }
+
     int offset = super.nameOffset;
     if (offset == 0 && _unlinkedClass != null) {
       return _unlinkedClass.nameOffset;
@@ -1632,7 +1661,9 @@
       : resynthesizerContext = null,
         _unlinkedUnit = null,
         _unlinkedPart = null,
-        super.forLinkedNode(enclosingLibrary, reference, linkedNode);
+        super.forLinkedNode(enclosingLibrary, reference, linkedNode) {
+    _nameOffset = -1;
+  }
 
   /// Initialize using the given serialized information.
   CompilationUnitElementImpl.forSerialized(LibraryElementImpl enclosingLibrary,
@@ -1679,6 +1710,9 @@
 
   @override
   int get codeLength {
+    if (linkedNode != null) {
+      return linkedContext.getCodeLength(linkedNode);
+    }
     if (_unlinkedUnit != null) {
       return _unlinkedUnit.codeRange?.length;
     }
@@ -1687,6 +1721,9 @@
 
   @override
   int get codeOffset {
+    if (linkedNode != null) {
+      return linkedContext.getCodeOffset(linkedNode);
+    }
     if (_unlinkedUnit != null) {
       return _unlinkedUnit.codeRange?.offset;
     }
@@ -1712,11 +1749,10 @@
       _enums = linkedNode.declarations.whereType<EnumDeclaration>().map((node) {
         var name = node.name.name;
         var reference = containerRef.getChild(name);
-        if (reference.element == null) {
-          reference.node2 = node;
-          EnumElementImpl.forLinkedNode(this, reference, node);
+        if (reference.hasElementFor(node)) {
+          return reference.element as EnumElementImpl;
         }
-        return reference.element as EnumElementImpl;
+        return EnumElementImpl.forLinkedNode(this, reference, node);
       }).toList();
     }
 
@@ -1750,11 +1786,10 @@
           .map((node) {
         var name = node.name.name;
         var reference = containerRef.getChild(name);
-        if (reference.element == null) {
-          reference.node2 = node;
-          FunctionElementImpl.forLinkedNode(this, reference, node);
+        if (reference.hasElementFor(node)) {
+          return reference.element as FunctionElementImpl;
         }
-        return reference.element as FunctionElementImpl;
+        return FunctionElementImpl.forLinkedNode(this, reference, node);
       }).toList();
     } else if (_unlinkedUnit != null) {
       _functions = _unlinkedUnit.executables
@@ -1792,11 +1827,10 @@
         }
 
         var reference = containerRef.getChild(name);
-        if (reference.element == null) {
-          reference.node2 = node;
-          GenericTypeAliasElementImpl.forLinkedNode(this, reference, node);
+        if (reference.hasElementFor(node)) {
+          return reference.element as GenericTypeAliasElementImpl;
         }
-        return reference.element as GenericTypeAliasElement;
+        return GenericTypeAliasElementImpl.forLinkedNode(this, reference, node);
       }).toList();
     }
 
@@ -1846,16 +1880,15 @@
 
     if (linkedNode != null) {
       CompilationUnit linkedNode = this.linkedNode;
-      var containerRef = reference.getChild('@class');
+      var containerRef = reference.getChild('@mixin');
       var declarations = linkedNode.declarations;
       return _mixins = declarations.whereType<MixinDeclaration>().map((node) {
         var name = node.name.name;
         var reference = containerRef.getChild(name);
-        if (reference.element == null) {
-          reference.node2 = node;
-          MixinElementImpl.forLinkedNode(this, reference, node);
+        if (reference.hasElementFor(node)) {
+          return reference.element as MixinElementImpl;
         }
-        return reference.element as MixinElementImpl;
+        return MixinElementImpl.forLinkedNode(this, reference, node);
       }).toList();
     }
 
@@ -1954,11 +1987,13 @@
           continue;
         }
         var reference = containerRef.getChild(name);
-        if (reference.element == null) {
-          reference.node2 = node;
-          ClassElementImpl.forLinkedNode(this, reference, node);
+        if (reference.hasElementFor(node)) {
+          _types.add(reference.element);
+        } else {
+          _types.add(
+            ClassElementImpl.forLinkedNode(this, reference, node),
+          );
         }
-        _types.add(reference.element);
       }
       return _types;
     }
@@ -2580,6 +2615,15 @@
 
   @override
   int get nameEnd {
+    if (linkedNode != null) {
+      var node = linkedNode as ConstructorDeclaration;
+      if (node.name != null) {
+        return node.name.end;
+      } else {
+        return node.returnType.end;
+      }
+    }
+
     if (serializedExecutable != null) {
       if (serializedExecutable.name.isNotEmpty) {
         return serializedExecutable.nameEnd;
@@ -2597,6 +2641,11 @@
 
   @override
   int get periodOffset {
+    if (linkedNode != null) {
+      var node = linkedNode as ConstructorDeclaration;
+      return node.period?.offset;
+    }
+
     if (serializedExecutable != null) {
       if (serializedExecutable.name.isNotEmpty) {
         return serializedExecutable.periodOffset;
@@ -2675,26 +2724,25 @@
 
   @override
   void appendTo(StringBuffer buffer) {
+    String name;
+    String constructorName = displayName;
     if (enclosingElement == null) {
       String message;
-      String name = displayName;
-      if (name != null && !name.isEmpty) {
+      if (constructorName != null && !constructorName.isEmpty) {
         message =
-            'Found constructor element named $name with no enclosing element';
+            'Found constructor element named $constructorName with no enclosing element';
       } else {
         message = 'Found unnamed constructor element with no enclosing element';
       }
       AnalysisEngine.instance.logger.logError(message);
-      buffer.write('<unknown class>');
+      name = '<unknown class>';
     } else {
-      buffer.write(enclosingElement.displayName);
+      name = enclosingElement.displayName;
     }
-    String name = displayName;
-    if (name != null && !name.isEmpty) {
-      buffer.write(".");
-      buffer.write(name);
+    if (constructorName != null && !constructorName.isEmpty) {
+      name = '$name.$constructorName';
     }
-    super.appendTo(buffer);
+    appendToWithName(buffer, name);
   }
 
   @deprecated
@@ -2811,7 +2859,7 @@
 
     if (linkedNode != null) {
       var context = enclosingUnit.linkedContext;
-      return _constantInitializer = context.readInitializer(this, linkedNode);
+      return _constantInitializer = context.readInitializer(linkedNode);
     }
 
     if (_unlinkedConst != null) {
@@ -3179,6 +3227,7 @@
 /// A base class for concrete implementations of an [Element].
 abstract class ElementImpl implements Element {
   /// An Unicode right arrow.
+  @deprecated
   static final String RIGHT_ARROW = " \u2192 ";
 
   static int _NEXT_ID = 0;
@@ -3232,7 +3281,7 @@
   /// Initialize from linked node.
   ElementImpl.forLinkedNode(
       this._enclosingElement, this.reference, this.linkedNode) {
-    reference?.element = this;
+    reference?.element ??= this;
   }
 
   /// Initialize a newly created element to have the given [name].
@@ -3380,6 +3429,18 @@
   }
 
   @override
+  bool get hasMustCallSuper {
+    var metadata = this.metadata;
+    for (var i = 0; i < metadata.length; i++) {
+      var annotation = metadata[i];
+      if (annotation.isMustCallSuper) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
   bool get hasOptionalTypeArgs {
     var metadata = this.metadata;
     for (var i = 0; i < metadata.length; i++) {
@@ -3767,8 +3828,9 @@
     var annotations = new List<ElementAnnotation>(length);
     for (int i = 0; i < length; i++) {
       var ast = nodeList[i];
-      annotations[i] = ElementAnnotationImpl(enclosingUnit)
-        ..annotationAst = ast;
+      annotations[i] = ElementAnnotationImpl(unit)
+        ..annotationAst = ast
+        ..element = ast.element;
     }
     return annotations;
   }
@@ -3975,6 +4037,7 @@
       : super.forSerialized(enclosingUnit);
 
   /// Set whether this class is abstract.
+  @Deprecated('This setter will be removed')
   void set abstract(bool isAbstract) {
     _assertNotResynthesized(_unlinkedEnum);
   }
@@ -4135,6 +4198,10 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getNameOffset(linkedNode);
+    }
+
     int offset = super.nameOffset;
     if (offset == 0 && _unlinkedEnum != null && _unlinkedEnum.nameOffset != 0) {
       return _unlinkedEnum.nameOffset;
@@ -4295,9 +4362,7 @@
   ExecutableElementImpl.forLinkedNode(
       ElementImpl enclosing, Reference reference, AstNode linkedNode)
       : serializedExecutable = null,
-        super.forLinkedNode(enclosing, reference, linkedNode) {
-    reference.element = this;
-  }
+        super.forLinkedNode(enclosing, reference, linkedNode);
 
   /// Initialize a newly created executable element to have the given [name].
   ExecutableElementImpl.forNode(Identifier name)
@@ -4574,25 +4639,42 @@
 
   @override
   void appendTo(StringBuffer buffer) {
+    appendToWithName(buffer, displayName);
+  }
+
+  /// Append a textual representation of this element to the given [buffer]. The
+  /// [name] is the name of the executable element or `null` if the element has
+  /// no name. If [includeType] is `true` then the return type will be included.
+  void appendToWithName(StringBuffer buffer, String name) {
+    FunctionType functionType = type;
+    if (functionType != null) {
+      buffer.write(functionType.returnType);
+      if (name != null) {
+        buffer.write(' ');
+        buffer.write(name);
+      }
+    } else if (name != null) {
+      buffer.write(name);
+    }
     if (this.kind != ElementKind.GETTER) {
       int typeParameterCount = typeParameters.length;
       if (typeParameterCount > 0) {
         buffer.write('<');
         for (int i = 0; i < typeParameterCount; i++) {
           if (i > 0) {
-            buffer.write(", ");
+            buffer.write(', ');
           }
           (typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
         }
         buffer.write('>');
       }
-      buffer.write("(");
+      buffer.write('(');
       String closing = null;
       ParameterKind kind = ParameterKind.REQUIRED;
       int parameterCount = parameters.length;
       for (int i = 0; i < parameterCount; i++) {
         if (i > 0) {
-          buffer.write(", ");
+          buffer.write(', ');
         }
         ParameterElement parameter = parameters[i];
         // ignore: deprecated_member_use_from_same_package
@@ -4601,12 +4683,15 @@
           if (closing != null) {
             buffer.write(closing);
           }
-          if (parameterKind == ParameterKind.POSITIONAL) {
-            buffer.write("[");
-            closing = "]";
-          } else if (parameterKind == ParameterKind.NAMED) {
-            buffer.write("{");
-            closing = "}";
+          if (parameter.isOptionalPositional) {
+            buffer.write('[');
+            closing = ']';
+          } else if (parameter.isNamed) {
+            buffer.write('{');
+            if (parameter.isRequiredNamed) {
+              buffer.write('required ');
+            }
+            closing = '}';
           } else {
             closing = null;
           }
@@ -4617,11 +4702,7 @@
       if (closing != null) {
         buffer.write(closing);
       }
-      buffer.write(")");
-    }
-    if (type != null) {
-      buffer.write(ElementImpl.RIGHT_ARROW);
-      buffer.write(type.returnType);
+      buffer.write(')');
     }
   }
 
@@ -4757,6 +4838,10 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return linkedContext.getDirectiveOffset(linkedNode);
+    }
+
     int offset = super.nameOffset;
     if (offset == 0 && _unlinkedExportNonPublic != null) {
       return _unlinkedExportNonPublic.offset;
@@ -4887,7 +4972,7 @@
   @override
   bool get isCovariant {
     if (linkedNode != null) {
-      return linkedContext.isCovariant(linkedNode);
+      return linkedContext.isExplicitlyCovariant(linkedNode);
     }
 
     if (_unlinkedVariable != null) {
@@ -4908,17 +4993,6 @@
       enclosingElement != null && enclosingElement.isEnum && !isSynthetic;
 
   @override
-  bool get isLazy {
-//    if (linkedNode != null) {
-//      return enclosingUnit.linkedContext.isLazy(linkedNode);
-//    }
-//    if (_unlinkedVariable != null) {
-//      return _unlinkedVariable.isLazy;
-//    }
-    return hasModifier(Modifier.LAZY);
-  }
-
-  @override
   bool get isStatic {
     if (linkedNode != null) {
       return enclosingUnit.linkedContext.isStatic(linkedNode);
@@ -4985,6 +5059,9 @@
   FieldElement get field {
     if (_field == null) {
       String fieldName;
+      if (linkedNode != null) {
+        fieldName = linkedContext.getFieldFormalParameterName(linkedNode);
+      }
       if (unlinkedParam != null) {
         fieldName = unlinkedParam.name;
       }
@@ -5136,15 +5213,6 @@
   @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitFunctionElement(this);
 
-  @override
-  void appendTo(StringBuffer buffer) {
-    String name = displayName;
-    if (name != null) {
-      buffer.write(name);
-    }
-    super.appendTo(buffer);
-  }
-
   @deprecated
   @override
   FunctionDeclaration computeNode() =>
@@ -5540,11 +5608,13 @@
     if (linkedNode != null) {
       if (linkedNode is GenericTypeAlias) {
         var context = enclosingUnit.linkedContext;
-        return _function = GenericFunctionTypeElementImpl.forLinkedNode(
-          this,
-          reference.getChild('@function'),
-          context.getGeneticTypeAliasFunction(linkedNode),
-        );
+        var function = context.getGeneticTypeAliasFunction(linkedNode);
+        if (function != null) {
+          var reference = context.getGenericFunctionTypeReference(function);
+          return _function = reference.element;
+        } else {
+          return null;
+        }
       } else {
         return _function = GenericFunctionTypeElementImpl.forLinkedNode(
           this,
@@ -5590,6 +5660,13 @@
     _function = function;
   }
 
+  bool get hasSelfReference {
+    if (linkedNode != null) {
+      return linkedContext.getHasTypedefSelfReference(linkedNode);
+    }
+    return false;
+  }
+
   @override
   bool get isSimplyBounded {
     if (linkedNode != null) {
@@ -5623,6 +5700,10 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getNameOffset(linkedNode);
+    }
+
     int offset = super.nameOffset;
     if (offset == 0 && _unlinkedTypedef != null) {
       return _unlinkedTypedef.nameOffset;
@@ -5740,15 +5821,23 @@
       return null;
     }
     FunctionType functionType = function.type;
+
     List<TypeParameterElement> parameterElements = element.typeParameters;
-    List<DartType> parameterTypes =
-        TypeParameterTypeImpl.getTypes(parameterElements);
-    int parameterCount = parameterTypes.length;
+    int parameterCount = parameterElements.length;
+
     if (typeArguments == null ||
         parameterElements.length != typeArguments.length) {
       DartType dynamicType = DynamicElementImpl.instance.type;
       typeArguments = new List<DartType>.filled(parameterCount, dynamicType);
     }
+
+    if (element is GenericTypeAliasElementImpl && element.linkedNode != null) {
+      return Substitution.fromPairs(parameterElements, typeArguments)
+          .substituteType(functionType);
+    }
+
+    List<DartType> parameterTypes =
+        TypeParameterTypeImpl.getTypes(parameterElements);
     return functionType.substitute2(typeArguments, parameterTypes);
   }
 }
@@ -5969,6 +6058,10 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return linkedContext.getDirectiveOffset(linkedNode);
+    }
+
     int offset = super.nameOffset;
     if (offset == 0 && _unlinkedImport != null) {
       if (_unlinkedImport.isImplicit) {
@@ -6191,6 +6284,9 @@
   /// The context of the defining unit.
   final LinkedUnitContext linkedContext;
 
+  @override
+  final bool isNonNullableByDefault;
+
   /// The compilation unit that defines this library.
   CompilationUnitElement _definingCompilationUnit;
 
@@ -6241,8 +6337,8 @@
 
   /// Initialize a newly created library element in the given [context] to have
   /// the given [name] and [offset].
-  LibraryElementImpl(
-      this.context, this.session, String name, int offset, this.nameLength)
+  LibraryElementImpl(this.context, this.session, String name, int offset,
+      this.nameLength, this.isNonNullableByDefault)
       : resynthesizerContext = null,
         unlinkedDefiningUnit = null,
         linkedContext = null,
@@ -6259,14 +6355,20 @@
       CompilationUnit linkedNode)
       : resynthesizerContext = null,
         unlinkedDefiningUnit = null,
+        isNonNullableByDefault = linkedContext.isNNBD,
         super.forLinkedNode(null, reference, linkedNode) {
     _name = name;
     _nameOffset = offset;
+    setResolutionCapability(
+        LibraryResolutionCapability.resolvedTypeNames, true);
+    setResolutionCapability(
+        LibraryResolutionCapability.constantExpressions, true);
   }
 
   /// Initialize a newly created library element in the given [context] to have
   /// the given [name].
-  LibraryElementImpl.forNode(this.context, this.session, LibraryIdentifier name)
+  LibraryElementImpl.forNode(this.context, this.session, LibraryIdentifier name,
+      this.isNonNullableByDefault)
       : nameLength = name != null ? name.length : 0,
         resynthesizerContext = null,
         unlinkedDefiningUnit = null,
@@ -6283,6 +6385,7 @@
       this.resynthesizerContext,
       this.unlinkedDefiningUnit)
       : linkedContext = null,
+        isNonNullableByDefault = unlinkedDefiningUnit.isNNBD,
         super.forSerialized(null) {
     _name = name;
     _nameOffset = offset;
@@ -6335,9 +6438,21 @@
   }
 
   FunctionElement get entryPoint {
-    if (resynthesizerContext != null) {
-      _entryPoint ??= resynthesizerContext.findEntryPoint();
+    if (_entryPoint != null) return _entryPoint;
+
+    if (linkedContext != null) {
+      var namespace = library.exportNamespace;
+      var entryPoint = namespace.get(FunctionElement.MAIN_FUNCTION_NAME);
+      if (entryPoint is FunctionElement) {
+        return _entryPoint = entryPoint;
+      }
+      return null;
     }
+
+    if (resynthesizerContext != null) {
+      return _entryPoint = resynthesizerContext.findEntryPoint();
+    }
+
     return _entryPoint;
   }
 
@@ -6429,6 +6544,19 @@
 
   @override
   bool get hasExtUri {
+    if (linkedNode != null) {
+      var unit = linkedContext.unit_withDirectives;
+      for (var import in unit.directives) {
+        if (import is ImportDirective) {
+          var uriStr = linkedContext.getSelectedUri(import);
+          if (DartUriResolver.isDartExtUri(uriStr)) {
+            return true;
+          }
+        }
+      }
+      return false;
+    }
+
     if (unlinkedDefiningUnit != null) {
       List<UnlinkedImport> unlinkedImports = unlinkedDefiningUnit.imports;
       for (UnlinkedImport import in unlinkedImports) {
@@ -6570,6 +6698,14 @@
   }
 
   @override
+  bool get isSynthetic {
+    if (linkedNode != null) {
+      return linkedContext.isSynthetic;
+    }
+    return super.isSynthetic;
+  }
+
+  @override
   ElementKind get kind => ElementKind.LIBRARY;
 
   @override
@@ -6667,7 +6803,7 @@
 
     if (linkedNode != null) {
       var metadata = linkedContext.getLibraryMetadata(linkedNode);
-      return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+      return _metadata = _buildAnnotations2(definingCompilationUnit, metadata);
     }
 
     if (unlinkedDefiningUnit != null) {
@@ -7013,14 +7149,14 @@
   }
 
   @override
-  bool get isLazy {
-//    if (linkedNode != null) {
-//      return enclosingUnit.linkedContext.isLazy(linkedNode);
-//    }
-//    if (_unlinkedVariable != null) {
-//      return _unlinkedVariable.isLazy;
-//    }
-    return hasModifier(Modifier.LAZY);
+  bool get isLate {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isLate(linkedNode);
+    }
+    if (_unlinkedVariable != null) {
+      return _unlinkedVariable.isLate;
+    }
+    return hasModifier(Modifier.LATE);
   }
 
   @override
@@ -7083,9 +7219,9 @@
       : super.forSerialized(serializedExecutable, enclosingClass);
 
   /// Set whether this method is abstract.
+  @Deprecated('Use isAbstract instead')
   void set abstract(bool isAbstract) {
-    _assertNotResynthesized(serializedExecutable);
-    setModifier(Modifier.ABSTRACT, isAbstract);
+    this.isAbstract = isAbstract;
   }
 
   @override
@@ -7104,6 +7240,12 @@
   TypeParameterizedElementMixin get enclosingTypeParameterContext =>
       super.enclosingElement as ClassElementImpl;
 
+  /// Set whether this class is abstract.
+  void set isAbstract(bool isAbstract) {
+    _assertNotResynthesized(serializedExecutable);
+    setModifier(Modifier.ABSTRACT, isAbstract);
+  }
+
   @override
   bool get isOperator {
     String name = displayName;
@@ -7149,12 +7291,6 @@
   @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitMethodElement(this);
 
-  @override
-  void appendTo(StringBuffer buffer) {
-    buffer.write(displayName);
-    super.appendTo(buffer);
-  }
-
   @deprecated
   @override
   MethodDeclaration computeNode() =>
@@ -7244,6 +7380,7 @@
         constraints = onClause.superclassConstraints
             .map((node) => node.type)
             .whereType<InterfaceType>()
+            .where(_isInterfaceTypeInterface)
             .toList();
       }
       if (constraints == null || constraints.isEmpty) {
@@ -7283,11 +7420,17 @@
 
   @override
   List<String> get superInvokedNames {
-    if (_superInvokedNames == null) {
-      if (_unlinkedClass != null) {
-        _superInvokedNames = _unlinkedClass.superInvokedNames;
-      }
+    if (_superInvokedNames != null) return _superInvokedNames;
+
+    if (linkedNode != null) {
+      return _superInvokedNames =
+          linkedContext.getMixinSuperInvokedNames(linkedNode);
     }
+
+    if (_unlinkedClass != null) {
+      return _superInvokedNames = _unlinkedClass.superInvokedNames;
+    }
+
     return _superInvokedNames ?? const <String>[];
   }
 
@@ -7389,7 +7532,7 @@
   static const Modifier IMPLICIT_TYPE = const Modifier('IMPLICIT_TYPE', 12);
 
   /// Indicates that modifier 'lazy' was applied to the element.
-  static const Modifier LAZY = const Modifier('LAZY', 13);
+  static const Modifier LATE = const Modifier('LATE', 13);
 
   /// Indicates that a class is a mixin application.
   static const Modifier MIXIN_APPLICATION =
@@ -7425,7 +7568,7 @@
     GETTER,
     HAS_EXT_URI,
     IMPLICIT_TYPE,
-    LAZY,
+    LATE,
     MIXIN_APPLICATION,
     REFERENCES_SUPER,
     SETTER,
@@ -7506,6 +7649,9 @@
   bool get hasLiteral => false;
 
   @override
+  bool get hasMustCallSuper => false;
+
+  @override
   bool get hasOptionalTypeArgs => false;
 
   @override
@@ -7705,6 +7851,30 @@
   }
 }
 
+/// The synthetic element representing the declaration of the type `Never`.
+class NeverElementImpl extends ElementImpl implements TypeDefiningElement {
+  /// Return the unique instance of this class.
+  static NeverElementImpl get instance =>
+      BottomTypeImpl.instance.element as NeverElementImpl;
+
+  @override
+  BottomTypeImpl type;
+
+  /// Initialize a newly created instance of this class. Instances of this class
+  /// should <b>not</b> be created except as part of creating the type
+  /// associated with this element. The single instance of this class should be
+  /// accessed through the method [instance].
+  NeverElementImpl() : super('Never', -1) {
+    setModifier(Modifier.SYNTHETIC, true);
+  }
+
+  @override
+  ElementKind get kind => ElementKind.NEVER;
+
+  @override
+  T accept<T>(ElementVisitor<T> visitor) => null;
+}
+
 /// A [VariableElementImpl], which is not a parameter.
 abstract class NonParameterVariableElementImpl extends VariableElementImpl {
   /// The unlinked representation of the variable in the summary.
@@ -7786,6 +7956,14 @@
   @override
   FunctionElement get initializer {
     if (_initializer == null) {
+      if (linkedNode != null) {
+        if (linkedContext.hasInitializer(linkedNode)) {
+          _initializer = new FunctionElementImpl('', -1)
+            ..isSynthetic = true
+            .._type = FunctionTypeImpl.synthetic(type, [], [])
+            ..enclosingElement = this;
+        }
+      }
       if (_unlinkedVariable != null) {
         UnlinkedExecutable unlinkedInitializer = _unlinkedVariable.initializer;
         if (unlinkedInitializer != null) {
@@ -7892,6 +8070,10 @@
 
   @override
   TopLevelInferenceError get typeInferenceError {
+    if (linkedNode != null) {
+      return linkedContext.getTypeInferenceError(linkedNode);
+    }
+
     if (_unlinkedVariable != null) {
       return enclosingUnit.resynthesizerContext
           .getTypeInferenceError(_unlinkedVariable.inferredTypeSlot);
@@ -7911,6 +8093,16 @@
   /// The unlinked representation of the parameter in the summary.
   final UnlinkedParam unlinkedParam;
 
+  /// A list containing all of the parameters defined by this parameter element.
+  /// There will only be parameters if this parameter is a function typed
+  /// parameter.
+  List<ParameterElement> _parameters;
+
+  /// A list containing all of the type parameters defined for this parameter
+  /// element. There will only be parameters if this parameter is a function
+  /// typed parameter.
+  List<TypeParameterElement> _typeParameters;
+
   /// The kind of this parameter.
   ParameterKind _parameterKind;
 
@@ -7969,7 +8161,7 @@
       {bool synthetic: false}) {
     ParameterElementImpl element;
     if (unlinkedParameter.isInitializingFormal) {
-      if (unlinkedParameter.kind == UnlinkedParamKind.required) {
+      if (unlinkedParameter.kind == UnlinkedParamKind.requiredPositional) {
         element = new FieldFormalParameterElementImpl.forSerialized(
             unlinkedParameter, enclosingElement);
       } else {
@@ -7977,7 +8169,7 @@
             unlinkedParameter, enclosingElement);
       }
     } else {
-      if (unlinkedParameter.kind == UnlinkedParamKind.required) {
+      if (unlinkedParameter.kind == UnlinkedParamKind.requiredPositional) {
         element = new ParameterElementImpl.forSerialized(
             unlinkedParameter, enclosingElement);
       } else {
@@ -8023,6 +8215,10 @@
 
   @override
   String get defaultValueCode {
+    if (linkedNode != null) {
+      return linkedContext.getDefaultValueCode(linkedNode);
+    }
+
     if (unlinkedParam != null) {
       if (unlinkedParam.initializer?.bodyExpr == null) {
         return null;
@@ -8059,6 +8255,9 @@
   /// when it overrides a method in a supertype that has a corresponding
   /// covariant parameter.
   bool get inheritsCovariant {
+    if (linkedNode != null) {
+      return linkedContext.getInheritsCovariant(linkedNode);
+    }
     if (unlinkedParam != null) {
       return enclosingUnit.resynthesizerContext
           .inheritsCovariant(unlinkedParam.inheritsCovariantSlot);
@@ -8069,6 +8268,11 @@
 
   /// Record whether or not this parameter inherits from a covariant parameter.
   void set inheritsCovariant(bool value) {
+    if (linkedNode != null) {
+      linkedContext.setInheritsCovariant(linkedNode, value);
+      return;
+    }
+
     _assertNotResynthesized(unlinkedParam);
     _inheritsCovariant = value;
   }
@@ -8076,6 +8280,11 @@
   @override
   FunctionElement get initializer {
     if (_initializer == null) {
+      if (linkedNode != null) {
+        if (linkedContext.hasDefaultValue(linkedNode)) {
+          _initializer = new FunctionElementImpl('', -1)..isSynthetic = true;
+        }
+      }
       if (unlinkedParam != null) {
         UnlinkedExecutable unlinkedInitializer = unlinkedParam.initializer;
         if (unlinkedInitializer != null) {
@@ -8113,9 +8322,6 @@
 
   @override
   bool get isCovariant {
-    if (linkedNode != null) {
-      return linkedContext.isCovariant(linkedNode);
-    }
     if (isExplicitlyCovariant || inheritsCovariant) {
       return true;
     }
@@ -8124,6 +8330,9 @@
 
   /// Return true if this parameter is explicitly marked as being covariant.
   bool get isExplicitlyCovariant {
+    if (linkedNode != null) {
+      return linkedContext.isExplicitlyCovariant(linkedNode);
+    }
     if (unlinkedParam != null) {
       return unlinkedParam.isExplicitlyCovariant;
     }
@@ -8198,7 +8407,8 @@
       if (unlinkedParam != null) {
         if (isSynthetic ||
             (unlinkedParam.name.isEmpty &&
-                unlinkedParam.kind != UnlinkedParamKind.named &&
+                unlinkedParam.kind != UnlinkedParamKind.requiredNamed &&
+                unlinkedParam.kind != UnlinkedParamKind.optionalNamed &&
                 enclosingElement is GenericFunctionTypeElement)) {
           return -1;
         }
@@ -8219,15 +8429,18 @@
     }
     if (unlinkedParam != null) {
       switch (unlinkedParam.kind) {
-        case UnlinkedParamKind.named:
+        case UnlinkedParamKind.optionalNamed:
           _parameterKind = ParameterKind.NAMED;
           break;
-        case UnlinkedParamKind.positional:
+        case UnlinkedParamKind.optionalPositional:
           _parameterKind = ParameterKind.POSITIONAL;
           break;
-        case UnlinkedParamKind.required:
+        case UnlinkedParamKind.requiredPositional:
           _parameterKind = ParameterKind.REQUIRED;
           break;
+        case UnlinkedParamKind.requiredNamed:
+          _parameterKind = ParameterKind.NAMED_REQUIRED;
+          break;
       }
     }
     return _parameterKind;
@@ -8240,7 +8453,39 @@
 
   @override
   List<ParameterElement> get parameters {
-    return const <ParameterElement>[];
+    if (_parameters != null) return _parameters;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var formalParameters = context.getFormalParameters(linkedNode);
+      if (formalParameters != null) {
+        var containerRef = reference.getChild('@parameter');
+        return _parameters = ParameterElementImpl.forLinkedNodeList(
+          this,
+          context,
+          containerRef,
+          formalParameters,
+        );
+      } else {
+        return _parameters ??= const <ParameterElement>[];
+      }
+    }
+
+    if (unlinkedParam != null) {
+      _resynthesizeTypeAndParameters();
+      return _parameters ??= const <ParameterElement>[];
+    }
+
+    return _parameters ??= const <ParameterElement>[];
+  }
+
+  /// Set the parameters defined by this executable element to the given
+  /// [parameters].
+  void set parameters(List<ParameterElement> parameters) {
+    for (ParameterElement parameter in parameters) {
+      (parameter as ParameterElementImpl).enclosingElement = this;
+    }
+    this._parameters = parameters;
   }
 
   @override
@@ -8256,6 +8501,10 @@
 
   @override
   TopLevelInferenceError get typeInferenceError {
+    if (linkedNode != null) {
+      return linkedContext.getTypeInferenceError(linkedNode);
+    }
+
     if (unlinkedParam != null) {
       return enclosingUnit.resynthesizerContext
           .getTypeInferenceError(unlinkedParam.inferredTypeSlot);
@@ -8266,7 +8515,34 @@
 
   @override
   List<TypeParameterElement> get typeParameters {
-    return const <TypeParameterElement>[];
+    if (_typeParameters != null) return _typeParameters;
+
+    if (linkedNode != null) {
+      var typeParameters = linkedContext.getTypeParameters2(linkedNode);
+      if (typeParameters == null) {
+        return _typeParameters = const [];
+      }
+      var containerRef = reference.getChild('@typeParameter');
+      return _typeParameters =
+          typeParameters.typeParameters.map<TypeParameterElement>((node) {
+        var reference = containerRef.getChild(node.name.name);
+        if (reference.hasElementFor(node)) {
+          return reference.element as TypeParameterElement;
+        }
+        return TypeParameterElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    }
+
+    return _typeParameters ??= const <TypeParameterElement>[];
+  }
+
+  /// Set the type parameters defined by this parameter element to the given
+  /// [typeParameters].
+  void set typeParameters(List<TypeParameterElement> typeParameters) {
+    for (TypeParameterElement parameter in typeParameters) {
+      (parameter as TypeParameterElementImpl).enclosingElement = this;
+    }
+    this._typeParameters = typeParameters;
   }
 
   @override
@@ -8292,21 +8568,20 @@
 
   @override
   void appendTo(StringBuffer buffer) {
-    String left = "";
-    String right = "";
-    while (true) {
-      if (parameterKind == ParameterKind.NAMED) {
-        left = "{";
-        right = "}";
-      } else if (parameterKind == ParameterKind.POSITIONAL) {
-        left = "[";
-        right = "]";
-      } else if (parameterKind == ParameterKind.REQUIRED) {}
-      break;
+    if (isNamed) {
+      buffer.write('{');
+      if (isRequiredNamed) {
+        buffer.write('required ');
+      }
+      appendToWithoutDelimiters(buffer);
+      buffer.write('}');
+    } else if (isOptionalPositional) {
+      buffer.write('[');
+      appendToWithoutDelimiters(buffer);
+      buffer.write(']');
+    } else {
+      appendToWithoutDelimiters(buffer);
     }
-    buffer.write(left);
-    appendToWithoutDelimiters(buffer);
-    buffer.write(right);
   }
 
   @deprecated
@@ -8338,9 +8613,10 @@
         var typeElement = new GenericFunctionTypeElementImpl.forOffset(-1);
         typeElement.enclosingElement = this;
 
-        typeElement.parameters = ParameterElementImpl.resynthesizeList(
+        _parameters = ParameterElementImpl.resynthesizeList(
             unlinkedParam.parameters, typeElement,
             synthetic: isSynthetic);
+        typeElement.parameters = _parameters;
 
         typeElement.returnType = enclosingUnit.resynthesizerContext
             .resolveTypeRef(this, unlinkedParam.type);
@@ -8370,7 +8646,7 @@
     return formalParameters.map((node) {
       if (node is DefaultFormalParameter) {
         NormalFormalParameter parameterNode = node.parameter;
-        var name = parameterNode.identifier.name;
+        var name = parameterNode.identifier?.name ?? '';
         var reference = containerRef.getChild(name);
         reference.node2 = node;
         if (parameterNode is FieldFormalParameter) {
@@ -8396,15 +8672,14 @@
         } else {
           var name = node.identifier.name;
           var reference = containerRef.getChild(name);
-          if (reference.element == null) {
-            reference.node2 = node;
-            ParameterElementImpl.forLinkedNodeFactory(
-              enclosing,
-              reference,
-              node,
-            );
+          if (reference.hasElementFor(node)) {
+            return reference.element as ParameterElement;
           }
-          return reference.element as ParameterElement;
+          return ParameterElementImpl.forLinkedNodeFactory(
+            enclosing,
+            reference,
+            node,
+          );
         }
       }
     }).toList();
@@ -8445,11 +8720,28 @@
   @override
   bool get inheritsCovariant {
     PropertyInducingElement variable = setter.variable;
-    if (variable is FieldElementImpl && variable._unlinkedVariable != null) {
-      return enclosingUnit.resynthesizerContext
-          .inheritsCovariant(variable._unlinkedVariable.inheritsCovariantSlot);
+    if (variable is FieldElementImpl) {
+      if (variable.linkedNode != null) {
+        var context = variable.linkedContext;
+        return context.getInheritsCovariant(variable.linkedNode);
+      }
+      if (variable._unlinkedVariable != null) {
+        return enclosingUnit.resynthesizerContext.inheritsCovariant(
+            variable._unlinkedVariable.inheritsCovariantSlot);
+      }
     }
-    return super.inheritsCovariant;
+    return false;
+  }
+
+  @override
+  void set inheritsCovariant(bool value) {
+    PropertyInducingElement variable = setter.variable;
+    if (variable is FieldElementImpl) {
+      if (variable.linkedNode != null) {
+        var context = variable.linkedContext;
+        return context.setInheritsCovariant(variable.linkedNode, value);
+      }
+    }
   }
 
   @override
@@ -8482,10 +8774,14 @@
 /// [ParameterElement].
 mixin ParameterElementMixin implements ParameterElement {
   @override
-  bool get isNamed => parameterKind == ParameterKind.NAMED;
+  bool get isNamed =>
+      parameterKind == ParameterKind.NAMED ||
+      parameterKind == ParameterKind.NAMED_REQUIRED;
 
   @override
-  bool get isNotOptional => parameterKind == ParameterKind.REQUIRED;
+  bool get isNotOptional =>
+      parameterKind == ParameterKind.REQUIRED ||
+      parameterKind == ParameterKind.NAMED_REQUIRED;
 
   @override
   bool get isOptional =>
@@ -8493,6 +8789,9 @@
       parameterKind == ParameterKind.POSITIONAL;
 
   @override
+  bool get isOptionalNamed => parameterKind == ParameterKind.NAMED;
+
+  @override
   bool get isOptionalPositional => parameterKind == ParameterKind.POSITIONAL;
 
   @override
@@ -8501,21 +8800,22 @@
       parameterKind == ParameterKind.REQUIRED;
 
   @override
+  bool get isRequiredNamed => parameterKind == ParameterKind.NAMED_REQUIRED;
+
+  @override
+  bool get isRequiredPositional => parameterKind == ParameterKind.REQUIRED;
+
+  @override
   // Overridden to remove the 'deprecated' annotation.
   ParameterKind get parameterKind;
 
   @override
   void appendToWithoutDelimiters(StringBuffer buffer) {
     buffer.write(type);
-    buffer.write(" ");
+    buffer.write(' ');
     buffer.write(displayName);
     if (defaultValueCode != null) {
-      if (parameterKind == ParameterKind.NAMED) {
-        buffer.write(": ");
-      }
-      if (parameterKind == ParameterKind.POSITIONAL) {
-        buffer.write(" = ");
-      }
+      buffer.write(' = ');
       buffer.write(defaultValueCode);
     }
   }
@@ -8631,9 +8931,9 @@
   }
 
   /// Set whether this accessor is abstract.
+  @Deprecated('Use isAbstract instead')
   void set abstract(bool isAbstract) {
-    _assertNotResynthesized(serializedExecutable);
-    setModifier(Modifier.ABSTRACT, isAbstract);
+    this.isAbstract = isAbstract;
   }
 
   @override
@@ -8680,6 +8980,12 @@
     return "$name$suffix";
   }
 
+  /// Set whether this class is abstract.
+  void set isAbstract(bool isAbstract) {
+    _assertNotResynthesized(serializedExecutable);
+    setModifier(Modifier.ABSTRACT, isAbstract);
+  }
+
   @override
   bool get isGetter {
     if (linkedNode != null) {
@@ -8758,9 +9064,8 @@
 
   @override
   void appendTo(StringBuffer buffer) {
-    buffer.write(isGetter ? "get " : "set ");
-    buffer.write(variable.displayName);
-    super.appendTo(buffer);
+    super.appendToWithName(
+        buffer, (isGetter ? 'get ' : 'set ') + variable.displayName);
   }
 
   @deprecated
@@ -8886,6 +9191,17 @@
   @override
   bool get isConstantEvaluated => true;
 
+  @override
+  bool get isLate {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isLate(linkedNode);
+    }
+    if (_unlinkedVariable != null) {
+      return _unlinkedVariable.isLate;
+    }
+    return hasModifier(Modifier.LATE);
+  }
+
   @deprecated
   @override
   DartType get propagatedType => null;
@@ -9174,9 +9490,7 @@
         super(name, offset);
 
   TypeParameterElementImpl.forLinkedNode(
-      TypeParameterizedElementMixin enclosing,
-      Reference reference,
-      TypeParameter linkedNode)
+      ElementImpl enclosing, Reference reference, TypeParameter linkedNode)
       : _unlinkedTypeParam = null,
         super.forLinkedNode(enclosing, reference, linkedNode);
 
@@ -9246,6 +9560,16 @@
     return super.codeOffset;
   }
 
+  /// The default value of the type parameter. It is used to provide the
+  /// corresponding missing type argument in type annotations and as the
+  /// fall-back type value in type inference.
+  DartType get defaultType {
+    if (linkedNode != null) {
+      return linkedContext.getDefaultType(linkedNode);
+    }
+    return null;
+  }
+
   @override
   String get displayName => name;
 
@@ -9275,6 +9599,10 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getNameOffset(linkedNode);
+    }
+
     int offset = super.nameOffset;
     if (offset == 0 && _unlinkedTypeParam != null) {
       return _unlinkedTypeParam.nameOffset;
@@ -9283,13 +9611,11 @@
   }
 
   TypeParameterType get type {
-    if (linkedNode != null) {
-      _type ??= new TypeParameterTypeImpl(this);
-    }
-    if (_unlinkedTypeParam != null) {
-      _type ??= new TypeParameterTypeImpl(this);
-    }
-    return _type;
+    // Note: TypeParameterElement.type has nullability suffix `star` regardless
+    // of whether it appears in a migrated library.  This is because for type
+    // parameters of synthetic function types, the ancestor chain is broken and
+    // we can't find the enclosing library to tell whether it is migrated.
+    return _type ??= new TypeParameterTypeImpl(this);
   }
 
   void set type(TypeParameterType type) {
@@ -9343,10 +9669,14 @@
       if (typeParameters == null) {
         return _typeParameterElements = const [];
       }
-      return _typeParameterElements = typeParameters.typeParameters.map((node) {
-        TypeParameterElementImpl element = node.declaredElement;
-        element.enclosingElement = this;
-        return element;
+      var containerRef = reference.getChild('@typeParameter');
+      return _typeParameterElements =
+          typeParameters.typeParameters.map<TypeParameterElement>((node) {
+        var reference = containerRef.getChild(node.name.name);
+        if (reference.hasElementFor(node)) {
+          return reference.element as TypeParameterElement;
+        }
+        return TypeParameterElementImpl.forLinkedNode(this, reference, node);
       }).toList();
     }
 
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
index 7a4a1e7..67f745c 100644
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -395,6 +395,9 @@
   bool get hasLiteral => actualElement.hasLiteral;
 
   @override
+  bool get hasMustCallSuper => actualElement.hasMustCallSuper;
+
+  @override
   bool get hasOptionalTypeArgs => actualElement.hasOptionalTypeArgs;
 
   @override
@@ -664,9 +667,6 @@
   @override
   bool get isEnumConstant => actualElement.isEnumConstant;
 
-  @override
-  bool get isLazy => actualElement.isLazy;
-
   @deprecated
   @override
   bool get isVirtual => actualElement.isVirtual;
@@ -894,6 +894,9 @@
   LibraryElement get actualElement => super.actualElement as LibraryElement;
 
   @override
+  bool get isNonNullableByDefault => actualElement.isNonNullableByDefault;
+
+  @override
   CompilationUnitElement get definingCompilationUnit =>
       actualElement.definingCompilationUnit;
 
@@ -987,7 +990,7 @@
       super.actualElement as LocalVariableElement;
 
   @override
-  bool get isLazy => actualElement.isLazy;
+  bool get isLate => actualElement.isLate;
 
   @override
   ElementKind get kind => ElementKind.LOCAL_VARIABLE;
@@ -1180,6 +1183,9 @@
   @override
   bool get isConstantEvaluated => actualElement.isConstantEvaluated;
 
+  @override
+  bool get isLate => actualElement.isLate;
+
   @deprecated
   @override
   DartType get propagatedType => null;
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 12fd38f..f818145 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -73,26 +73,27 @@
     ConstructorElement baseElement = this.baseElement;
     List<ParameterElement> parameters = this.parameters;
     FunctionType type = this.type;
+
     StringBuffer buffer = new StringBuffer();
+    if (type != null) {
+      buffer.write(type.returnType);
+      buffer.write(' ');
+    }
     buffer.write(baseElement.enclosingElement.displayName);
     String name = displayName;
     if (name != null && !name.isEmpty) {
-      buffer.write(".");
+      buffer.write('.');
       buffer.write(name);
     }
-    buffer.write("(");
+    buffer.write('(');
     int parameterCount = parameters.length;
     for (int i = 0; i < parameterCount; i++) {
       if (i > 0) {
-        buffer.write(", ");
+        buffer.write(', ');
       }
       buffer.write(parameters[i]);
     }
-    buffer.write(")");
-    if (type != null) {
-      buffer.write(ElementImpl.RIGHT_ARROW);
-      buffer.write(type.returnType);
-    }
+    buffer.write(')');
     return buffer.toString();
   }
 
@@ -256,7 +257,7 @@
   bool get isEnumConstant => baseElement.isEnumConstant;
 
   @override
-  bool get isLazy => baseElement.isLazy;
+  bool get isLate => baseElement.isLate;
 
   @deprecated
   @override
@@ -428,6 +429,9 @@
   bool get hasLiteral => _baseElement.hasLiteral;
 
   @override
+  bool get hasMustCallSuper => _baseElement.hasMustCallSuper;
+
+  @override
   bool get hasOptionalTypeArgs => _baseElement.hasOptionalTypeArgs;
 
   @override
@@ -618,28 +622,33 @@
     MethodElement baseElement = this.baseElement;
     List<ParameterElement> parameters = this.parameters;
     FunctionType type = this.type;
+
     StringBuffer buffer = new StringBuffer();
+    if (type != null) {
+      buffer.write(type.returnType);
+      buffer.write(' ');
+    }
     buffer.write(baseElement.enclosingElement.displayName);
-    buffer.write(".");
+    buffer.write('.');
     buffer.write(baseElement.displayName);
     int typeParameterCount = typeParameters.length;
     if (typeParameterCount > 0) {
       buffer.write('<');
       for (int i = 0; i < typeParameterCount; i++) {
         if (i > 0) {
-          buffer.write(", ");
+          buffer.write(', ');
         }
         (typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
       }
       buffer.write('>');
     }
-    buffer.write("(");
+    buffer.write('(');
     String closing = null;
     ParameterKind kind = ParameterKind.REQUIRED;
     int parameterCount = parameters.length;
     for (int i = 0; i < parameterCount; i++) {
       if (i > 0) {
-        buffer.write(", ");
+        buffer.write(', ');
       }
       ParameterElement parameter = parameters[i];
       // ignore: deprecated_member_use_from_same_package
@@ -648,12 +657,12 @@
         if (closing != null) {
           buffer.write(closing);
         }
-        if (parameterKind == ParameterKind.POSITIONAL) {
-          buffer.write("[");
-          closing = "]";
-        } else if (parameterKind == ParameterKind.NAMED) {
-          buffer.write("{");
-          closing = "}";
+        if (parameter.isOptionalPositional) {
+          buffer.write('[');
+          closing = ']';
+        } else if (parameter.isNamed) {
+          buffer.write('{');
+          closing = '}';
         } else {
           closing = null;
         }
@@ -664,11 +673,7 @@
     if (closing != null) {
       buffer.write(closing);
     }
-    buffer.write(")");
-    if (type != null) {
-      buffer.write(ElementImpl.RIGHT_ARROW);
-      buffer.write(type.returnType);
-    }
+    buffer.write(')');
     return buffer.toString();
   }
 
@@ -849,28 +854,29 @@
     PropertyAccessorElement baseElement = this.baseElement;
     List<ParameterElement> parameters = this.parameters;
     FunctionType type = this.type;
+
     StringBuffer builder = new StringBuffer();
+    if (type != null) {
+      builder.write(type.returnType);
+      builder.write(' ');
+    }
     if (isGetter) {
-      builder.write("get ");
+      builder.write('get ');
     } else {
-      builder.write("set ");
+      builder.write('set ');
     }
     builder.write(baseElement.enclosingElement.displayName);
-    builder.write(".");
+    builder.write('.');
     builder.write(baseElement.displayName);
-    builder.write("(");
+    builder.write('(');
     int parameterCount = parameters.length;
     for (int i = 0; i < parameterCount; i++) {
       if (i > 0) {
-        builder.write(", ");
+        builder.write(', ');
       }
       builder.write(parameters[i]);
     }
-    builder.write(")");
-    if (type != null) {
-      builder.write(ElementImpl.RIGHT_ARROW);
-      builder.write(type.returnType);
-    }
+    builder.write(')');
     return builder.toString();
   }
 
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 267f338..8da95fd 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -56,14 +56,47 @@
  */
 class BottomTypeImpl extends TypeImpl {
   /**
-   * The unique instance of this class.
+   * The unique instance of this class, nullable.
+   *
+   * This behaves equivalently to the `Null` type, but we distinguish it for two
+   * reasons: (1) there are circumstances where we need access to this type, but
+   * we don't have access to the type provider, so using `Never?` is a
+   * convenient solution.  (2) we may decide that the distinction is convenient
+   * in diagnostic messages (this is TBD).
    */
-  static final BottomTypeImpl instance = new BottomTypeImpl._();
+  static final BottomTypeImpl instanceNullable =
+      new BottomTypeImpl._(NullabilitySuffix.question);
+
+  /**
+   * The unique instance of this class, starred.
+   *
+   * This behaves like a version of the Null* type that could be conceivably
+   * migrated to be of type Never. Therefore, it's the bottom of all legacy
+   * types, and also assignable to the true bottom. Note that Never? and Never*
+   * are not the same type, as Never* is a subtype of Never, while Never? is
+   * not.
+   */
+  static final BottomTypeImpl instanceLegacy =
+      new BottomTypeImpl._(NullabilitySuffix.star);
+
+  /**
+   * The unique instance of this class, non-nullable.
+   */
+  static final BottomTypeImpl instance =
+      new BottomTypeImpl._(NullabilitySuffix.none);
+
+  @override
+  final NullabilitySuffix nullabilitySuffix;
 
   /**
    * Prevent the creation of instances of this class.
    */
-  BottomTypeImpl._() : super(null, "<bottom>");
+  BottomTypeImpl._(this.nullabilitySuffix)
+      : super(new NeverElementImpl(), "Never") {
+    if (nullabilitySuffix == NullabilitySuffix.none) {
+      (element as NeverElementImpl).type = this;
+    }
+  }
 
   @override
   int get hashCode => 0;
@@ -72,7 +105,10 @@
   bool get isBottom => true;
 
   @override
-  NullabilitySuffix get nullabilitySuffix => NullabilitySuffix.none;
+  bool get isDartCoreNull {
+    // `Never?` is equivalent to `Null`, so make sure it behaves the same.
+    return nullabilitySuffix == NullabilitySuffix.question;
+  }
 
   @override
   bool operator ==(Object object) => identical(object, this);
@@ -117,8 +153,15 @@
 
   @override
   TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
-    // The bottom type is always non-nullable.
-    return this;
+    switch (nullabilitySuffix) {
+      case NullabilitySuffix.question:
+        return instanceNullable;
+      case NullabilitySuffix.star:
+        return instanceLegacy;
+      case NullabilitySuffix.none:
+        return instance;
+    }
+    throw StateError('Unexpected nullabilitySuffix: $nullabilitySuffix');
   }
 }
 
@@ -240,6 +283,12 @@
   TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) => this;
 
   @override
+  void _appendToWithTypeParameters(StringBuffer buffer,
+      Set<TypeImpl> visitedTypes, bool withNullability, String typeParameters) {
+    throw StateError('We should never get here.');
+  }
+
+  @override
   void _forEachParameterType(
       ParameterKind kind, callback(String name, DartType type)) {
     // There are no parameters.
@@ -307,8 +356,10 @@
 
   DeferredFunctionTypeImpl(this._computeElement, String name,
       List<DartType> typeArguments, bool isInstantiated,
-      {NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star})
-      : super._(null, name, null, typeArguments, null, null, isInstantiated,
+      {NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+      FunctionTypedElement computedElement})
+      : _computedElement = computedElement,
+        super._(null, name, null, typeArguments, null, null, isInstantiated,
             nullabilitySuffix: nullabilitySuffix);
 
   @override
@@ -325,6 +376,7 @@
     if (this.nullabilitySuffix == nullabilitySuffix) return this;
     return DeferredFunctionTypeImpl(
         _computeElement, name, typeArguments, isInstantiated,
+        computedElement: _computedElement,
         nullabilitySuffix: nullabilitySuffix);
   }
 }
@@ -502,7 +554,7 @@
     var name = original.name ?? "";
     var element = original.element;
     var function = new FunctionElementImpl(name, -1);
-    function.enclosingElement = element.enclosingElement;
+    function.enclosingElement = element?.enclosingElement;
     function.isSynthetic = true;
     function.returnType = newType.returnType;
     function.typeParameters = freshVarElements;
@@ -602,10 +654,16 @@
 
   @override
   Map<String, DartType> get namedParameterTypes {
+    // TODO(brianwilkerson) This implementation breaks the contract because the
+    //  parameters will not necessarily be returned in the order in which they
+    //  were declared.
     Map<String, DartType> types = <String, DartType>{};
     _forEachParameterType(ParameterKind.NAMED, (name, type) {
       types[name] = type;
     });
+    _forEachParameterType(ParameterKind.NAMED_REQUIRED, (name, type) {
+      types[name] = type;
+    });
     return types;
   }
 
@@ -672,8 +730,11 @@
   @override
   void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
       {bool withNullability = false}) {
+    // TODO(paulberry): eliminate code duplication with
+    // _ElementWriter.writeType.  See issue #35818.
     if (visitedTypes.add(this)) {
       if (typeFormals.isNotEmpty) {
+        StringBuffer typeParametersBuffer = StringBuffer();
         // To print a type with type variables, first make sure we have unique
         // variable names to print.
         Set<TypeParameterType> freeVariables = new HashSet<TypeParameterType>();
@@ -688,10 +749,10 @@
 
         List<DartType> instantiateTypeArgs = <DartType>[];
         List<DartType> variables = <DartType>[];
-        buffer.write("<");
+        typeParametersBuffer.write('<');
         for (TypeParameterElement e in typeFormals) {
           if (e != typeFormals[0]) {
-            buffer.write(",");
+            typeParametersBuffer.write(',');
           }
           String name = e.name;
           int counter = 0;
@@ -706,89 +767,27 @@
           }
           TypeParameterTypeImpl t =
               new TypeParameterTypeImpl(new TypeParameterElementImpl(name, -1));
-          t.appendTo(buffer, visitedTypes, withNullability: withNullability);
+          t.appendTo(typeParametersBuffer, visitedTypes,
+              withNullability: withNullability);
           instantiateTypeArgs.add(t);
           variables.add(e.type);
           if (e.bound != null) {
-            buffer.write(" extends ");
+            typeParametersBuffer.write(' extends ');
             TypeImpl renamed =
                 e.bound.substitute2(instantiateTypeArgs, variables);
-            renamed.appendTo(buffer, visitedTypes);
+            renamed.appendTo(typeParametersBuffer, visitedTypes);
           }
         }
-        buffer.write(">");
+        typeParametersBuffer.write('>');
 
-        // Instantiate it and print the resulting type. After instantiation, it
-        // will no longer have typeFormals, so we will continue below.
-        this
-            .instantiate(instantiateTypeArgs)
-            .appendTo(buffer, visitedTypes, withNullability: withNullability);
-        return;
-      }
-
-      List<DartType> normalParameterTypes = this.normalParameterTypes;
-      List<DartType> optionalParameterTypes = this.optionalParameterTypes;
-      Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
-      DartType returnType = this.returnType;
-
-      bool needsComma = false;
-      void writeSeparator() {
-        if (needsComma) {
-          buffer.write(", ");
-        } else {
-          needsComma = true;
-        }
-      }
-
-      void startOptionalParameters() {
-        if (needsComma) {
-          buffer.write(", ");
-          needsComma = false;
-        }
-      }
-
-      buffer.write("(");
-      if (normalParameterTypes.isNotEmpty) {
-        for (DartType type in normalParameterTypes) {
-          writeSeparator();
-          (type as TypeImpl)
-              .appendTo(buffer, visitedTypes, withNullability: withNullability);
-        }
-      }
-      if (optionalParameterTypes.isNotEmpty) {
-        startOptionalParameters();
-        buffer.write("[");
-        for (DartType type in optionalParameterTypes) {
-          writeSeparator();
-          (type as TypeImpl)
-              .appendTo(buffer, visitedTypes, withNullability: withNullability);
-        }
-        buffer.write("]");
-        needsComma = true;
-      }
-      if (namedParameterTypes.isNotEmpty) {
-        startOptionalParameters();
-        buffer.write("{");
-        namedParameterTypes.forEach((String name, DartType type) {
-          writeSeparator();
-          buffer.write(name);
-          buffer.write(": ");
-          (type as TypeImpl)
-              .appendTo(buffer, visitedTypes, withNullability: withNullability);
-        });
-        buffer.write("}");
-        needsComma = true;
-      }
-      buffer.write(")");
-      buffer.write(ElementImpl.RIGHT_ARROW);
-      if (returnType == null) {
-        buffer.write("null");
+        // Instantiate it and print the resulting type.
+        this.instantiate(instantiateTypeArgs)._appendToWithTypeParameters(
+            buffer,
+            visitedTypes,
+            withNullability,
+            typeParametersBuffer.toString());
       } else {
-        (returnType as TypeImpl)
-            .appendTo(buffer, visitedTypes, withNullability: withNullability);
-      }
-      if (withNullability) {
-        _appendNullability(buffer);
+        _appendToWithTypeParameters(buffer, visitedTypes, withNullability, '');
       }
       visitedTypes.remove(this);
     } else {
@@ -891,6 +890,76 @@
   FunctionTypeImpl substitute3(List<DartType> argumentTypes) =>
       substitute2(argumentTypes, typeArguments);
 
+  void _appendToWithTypeParameters(StringBuffer buffer,
+      Set<TypeImpl> visitedTypes, bool withNullability, String typeParameters) {
+    List<DartType> normalParameterTypes = this.normalParameterTypes;
+    List<DartType> optionalParameterTypes = this.optionalParameterTypes;
+    Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
+    DartType returnType = this.returnType;
+
+    if (returnType == null) {
+      buffer.write('null');
+    } else {
+      (returnType as TypeImpl)
+          .appendTo(buffer, visitedTypes, withNullability: withNullability);
+    }
+    buffer.write(' Function');
+    buffer.write(typeParameters);
+    bool needsComma = false;
+
+    void writeSeparator() {
+      if (needsComma) {
+        buffer.write(', ');
+      } else {
+        needsComma = true;
+      }
+    }
+
+    void startOptionalParameters() {
+      if (needsComma) {
+        buffer.write(', ');
+        needsComma = false;
+      }
+    }
+
+    buffer.write('(');
+    if (normalParameterTypes.isNotEmpty) {
+      for (DartType type in normalParameterTypes) {
+        writeSeparator();
+        (type as TypeImpl)
+            .appendTo(buffer, visitedTypes, withNullability: withNullability);
+      }
+    }
+    if (optionalParameterTypes.isNotEmpty) {
+      startOptionalParameters();
+      buffer.write('[');
+      for (DartType type in optionalParameterTypes) {
+        writeSeparator();
+        (type as TypeImpl)
+            .appendTo(buffer, visitedTypes, withNullability: withNullability);
+      }
+      buffer.write(']');
+      needsComma = true;
+    }
+    if (namedParameterTypes.isNotEmpty) {
+      startOptionalParameters();
+      buffer.write('{');
+      namedParameterTypes.forEach((String name, DartType type) {
+        writeSeparator();
+        buffer.write(name);
+        buffer.write(': ');
+        (type as TypeImpl)
+            .appendTo(buffer, visitedTypes, withNullability: withNullability);
+      });
+      buffer.write('}');
+      needsComma = true;
+    }
+    buffer.write(')');
+    if (withNullability) {
+      _appendNullability(buffer);
+    }
+  }
+
   /**
    * Invokes [callback] for each parameter of [kind] with the parameter's [name]
    * and type after any type parameters have been applied.
@@ -936,43 +1005,6 @@
   }
 
   /**
-   * Given a generic function type [g] and an instantiated function type [f],
-   * find a list of type arguments TArgs such that `g<TArgs> == f`,
-   * and return TArgs.
-   *
-   * This function must be called with type [f] that was instantiated from [g].
-   *
-   * If [g] is not generic, returns an empty list.
-   */
-  static Iterable<DartType> recoverTypeArguments(
-      FunctionType g, FunctionType f) {
-    // TODO(jmesserly): perhaps a better design here would be: instead of
-    // recording staticInvokeType on InvocationExpression, we could record the
-    // instantiated type arguments, that way we wouldn't need to recover them.
-    //
-    // For now though, this is a pretty quick operation.
-    if (g.typeFormals.isEmpty) {
-      assert(g == f);
-      return const <DartType>[];
-    }
-    assert(f.typeFormals.isEmpty);
-    assert(g.typeFormals.length <= f.typeArguments.length);
-
-    // Instantiation in Analyzer works like this:
-    // Given:
-    //     {U/T} <S> T -> S
-    // Where {U/T} represents the typeArguments (U) and typeParameters (T) list,
-    // and <S> represents the typeFormals.
-    //
-    // Now instantiate([V]), and the result should be:
-    //     {U/T, V/S} T -> S.
-    //
-    // Therefore, we can recover the typeArguments from our instantiated
-    // function.
-    return f.typeArguments.skip(f.typeArguments.length - g.typeFormals.length);
-  }
-
-  /**
    * Compares two function types [t] and [s] to see if their corresponding
    * parameter types match [parameterRelation], return types match
    * [returnRelation], and type parameter bounds match [boundsRelation].
@@ -1055,7 +1087,7 @@
     var tOptional = <ParameterElement>[];
     var tNamed = <String, ParameterElement>{};
     for (var p in tParams) {
-      if (p.isNotOptional) {
+      if (p.isRequiredPositional) {
         tRequired.add(p);
       } else if (p.isOptionalPositional) {
         tOptional.add(p);
@@ -1069,7 +1101,7 @@
     var sOptional = <ParameterElement>[];
     var sNamed = <String, ParameterElement>{};
     for (var p in sParams) {
-      if (p.isNotOptional) {
+      if (p.isRequiredPositional) {
         sRequired.add(p);
       } else if (p.isOptionalPositional) {
         sOptional.add(p);
@@ -2947,11 +2979,20 @@
 
   /**
    * Return the same type, but with the given [nullabilitySuffix].
+   *
+   * If the nullability of `this` already matches [nullabilitySuffix], `this`
+   * is returned.
+   *
+   * Note: this method just does low-level manipulations of the underlying type,
+   * so it is what you want if you are constructing a fresh type and want it to
+   * have the correct nullability suffix, but it is generally *not* what you
+   * want if you're manipulating existing types.  For manipulating existing
+   * types, please use the methods in [TypeSystem].
    */
   TypeImpl withNullability(NullabilitySuffix nullabilitySuffix);
 
   void _appendNullability(StringBuffer buffer) {
-    if (isDynamic || isBottom || isVoid) {
+    if (isDynamic || isVoid) {
       // These types don't have nullability variations, so don't append
       // anything.
       return;
@@ -3204,7 +3245,21 @@
       return objectType;
     }
 
-    return element.bound.resolveToBound(objectType);
+    NullabilitySuffix newNullabilitySuffix;
+    if (nullabilitySuffix == NullabilitySuffix.question ||
+        (element.bound as TypeImpl).nullabilitySuffix ==
+            NullabilitySuffix.question) {
+      newNullabilitySuffix = NullabilitySuffix.question;
+    } else if (nullabilitySuffix == NullabilitySuffix.star ||
+        (element.bound as TypeImpl).nullabilitySuffix ==
+            NullabilitySuffix.star) {
+      newNullabilitySuffix = NullabilitySuffix.star;
+    } else {
+      newNullabilitySuffix = NullabilitySuffix.none;
+    }
+
+    return (element.bound.resolveToBound(objectType) as TypeImpl)
+        .withNullability(newNullabilitySuffix);
   }
 
   @override
@@ -3213,7 +3268,8 @@
       [List<FunctionTypeAliasElement> prune]) {
     int length = parameterTypes.length;
     for (int i = 0; i < length; i++) {
-      if (parameterTypes[i] == this) {
+      var parameterType = parameterTypes[i];
+      if (parameterType is TypeParameterTypeImpl && parameterType == this) {
         TypeImpl argumentType = argumentTypes[i];
 
         // TODO(scheglov) It should not happen, but sometimes arguments are null.
@@ -3223,15 +3279,29 @@
 
         // TODO(scheglov) Proposed substitution rules for nullability.
         NullabilitySuffix resultNullability;
+        NullabilitySuffix parameterNullability =
+            parameterType.nullabilitySuffix;
         NullabilitySuffix argumentNullability = argumentType.nullabilitySuffix;
-        if (argumentNullability == NullabilitySuffix.question ||
-            nullabilitySuffix == NullabilitySuffix.question) {
-          resultNullability = NullabilitySuffix.question;
-        } else if (argumentNullability == NullabilitySuffix.star ||
-            nullabilitySuffix == NullabilitySuffix.star) {
-          resultNullability = NullabilitySuffix.star;
+        if (parameterNullability == NullabilitySuffix.none) {
+          if (argumentNullability == NullabilitySuffix.question ||
+              nullabilitySuffix == NullabilitySuffix.question) {
+            resultNullability = NullabilitySuffix.question;
+          } else if (argumentNullability == NullabilitySuffix.star ||
+              nullabilitySuffix == NullabilitySuffix.star) {
+            resultNullability = NullabilitySuffix.star;
+          } else {
+            resultNullability = NullabilitySuffix.none;
+          }
+        } else if (parameterNullability == NullabilitySuffix.star) {
+          if (argumentNullability == NullabilitySuffix.question ||
+              nullabilitySuffix == NullabilitySuffix.question) {
+            resultNullability = NullabilitySuffix.question;
+          } else {
+            resultNullability = argumentNullability;
+          }
         } else {
-          resultNullability = NullabilitySuffix.none;
+          // We should never be substituting for `T?`.
+          throw new StateError('Tried to substitute for T?');
         }
 
         return argumentType.withNullability(resultNullability);
@@ -3265,87 +3335,6 @@
 }
 
 /**
- * The unique instance of the class `UndefinedTypeImpl` implements the type of
- * type names that couldn't be resolved.
- *
- * This class behaves like DynamicTypeImpl in almost every respect, to reduce
- * cascading errors.
- */
-class UndefinedTypeImpl extends TypeImpl {
-  /**
-   * The unique instance of this class.
-   */
-  static final UndefinedTypeImpl instance = new UndefinedTypeImpl._();
-
-  /**
-   * Prevent the creation of instances of this class.
-   */
-  UndefinedTypeImpl._()
-      : super(DynamicElementImpl.instance, Keyword.DYNAMIC.lexeme);
-
-  @override
-  int get hashCode => 1;
-
-  @override
-  bool get isDynamic => true;
-
-  @override
-  bool get isUndefined => true;
-
-  @override
-  NullabilitySuffix get nullabilitySuffix => NullabilitySuffix.star;
-
-  @override
-  bool operator ==(Object object) => identical(object, this);
-
-  @override
-  bool isMoreSpecificThan(DartType type,
-      [bool withDynamic = false, Set<Element> visitedElements]) {
-    // T is S
-    if (identical(this, type)) {
-      return true;
-    }
-    // else
-    return withDynamic;
-  }
-
-  @override
-  bool isSubtypeOf(DartType type) => true;
-
-  @override
-  bool isSupertypeOf(DartType type) => true;
-
-  @override
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
-
-  @override
-  DartType replaceTopAndBottom(TypeProvider typeProvider,
-      {bool isCovariant = true}) {
-    if (isCovariant) {
-      return typeProvider.nullType;
-    } else {
-      return this;
-    }
-  }
-
-  @override
-  DartType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) {
-    int length = parameterTypes.length;
-    for (int i = 0; i < length; i++) {
-      if (parameterTypes[i] == this) {
-        return argumentTypes[i];
-      }
-    }
-    return this;
-  }
-
-  @override
-  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) => this;
-}
-
-/**
  * The type `void`.
  */
 abstract class VoidType implements DartType {
@@ -3511,7 +3500,7 @@
   @override
   List<String> get normalParameterNames {
     return baseParameters
-        .where((parameter) => parameter.isNotOptional)
+        .where((parameter) => parameter.isRequiredPositional)
         .map((parameter) => parameter.name)
         .toList();
   }
@@ -3798,8 +3787,10 @@
   List<FunctionTypeAliasElement> get newPrune => const [];
 
   @override
-  List<String> get normalParameterNames =>
-      parameters.where((p) => p.isNotOptional).map((p) => p.name).toList();
+  List<String> get normalParameterNames => parameters
+      .where((p) => p.isRequiredPositional)
+      .map((p) => p.name)
+      .toList();
 
   @override
   List<String> get optionalParameterNames => parameters
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index dbf57f9..d73ab28 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -7,6 +7,8 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_visitor.dart';
+import 'package:analyzer/src/summary2/function_type_builder.dart';
+import 'package:analyzer/src/summary2/named_type_builder.dart';
 
 /// Generates a fresh copy of the given type parameters, with their bounds
 /// substituted to reference the new parameters.
@@ -323,6 +325,51 @@
   }
 
   @override
+  DartType visitFunctionTypeBuilder(FunctionTypeBuilder type) {
+    // This is a bit tricky because we have to generate fresh type parameters
+    // in order to change the bounds.  At the same time, if the function type
+    // was unaltered, we have to return the [type] object (not a copy!).
+    // Substituting a type for a fresh type variable should not be confused
+    // with a "real" substitution.
+    //
+    // Create an inner environment to generate fresh type parameters.  The use
+    // counter on the inner environment tells if the fresh type parameters have
+    // any uses, but does not tell if the resulting function type is distinct.
+    // Our own use counter will get incremented if something from our
+    // environment has been used inside the function.
+    var inner = type.typeFormals.isEmpty ? this : newInnerEnvironment();
+    int before = this.useCounter;
+
+    // Invert the variance when translating parameters.
+    inner.invertVariance();
+
+    var typeFormals = inner.freshTypeParameters(type.typeFormals);
+
+    var parameters = type.parameters.map((parameter) {
+      var type = inner.visit(parameter.type);
+      return ParameterElementImpl.synthetic(
+        parameter.name,
+        type,
+        // ignore: deprecated_member_use_from_same_package
+        parameter.parameterKind,
+      );
+    }).toList();
+
+    inner.invertVariance();
+
+    var returnType = inner.visit(type.returnType);
+
+    if (this.useCounter == before) return type;
+
+    return FunctionTypeBuilder(
+      typeFormals,
+      parameters,
+      returnType,
+      type.nullabilitySuffix,
+    );
+  }
+
+  @override
   DartType visitInterfaceType(InterfaceType type) {
     if (type.typeArguments.isEmpty) {
       return type;
@@ -338,6 +385,25 @@
   }
 
   @override
+  DartType visitNamedType(NamedTypeBuilder type) {
+    if (type.arguments.isEmpty) {
+      return type;
+    }
+
+    int before = useCounter;
+    var arguments = type.arguments.map(visit).toList();
+    if (useCounter == before) {
+      return type;
+    }
+
+    return new NamedTypeBuilder(
+      type.element,
+      arguments,
+      type.nullabilitySuffix,
+    );
+  }
+
+  @override
   DartType visitTypeParameterType(TypeParameterType type) {
     return getSubstitute(type.element) ?? type;
   }
diff --git a/pkg/analyzer/lib/src/dart/element/type_visitor.dart b/pkg/analyzer/lib/src/dart/element/type_visitor.dart
index 6b0ffbe..08b8de6 100644
--- a/pkg/analyzer/lib/src/dart/element/type_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_visitor.dart
@@ -4,6 +4,8 @@
 
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/summary2/function_type_builder.dart';
+import 'package:analyzer/src/summary2/named_type_builder.dart';
 
 class DartTypeVisitor<R> {
   const DartTypeVisitor();
@@ -16,8 +18,12 @@
 
   R visitFunctionType(FunctionType type) => defaultDartType(type);
 
+  R visitFunctionTypeBuilder(FunctionTypeBuilder type) => defaultDartType(type);
+
   R visitInterfaceType(InterfaceType type) => defaultDartType(type);
 
+  R visitNamedType(NamedTypeBuilder type) => defaultDartType(type);
+
   R visitTypeParameterType(TypeParameterType type) => defaultDartType(type);
 
   R visitVoidType(VoidType type) => defaultDartType(type);
@@ -32,9 +38,15 @@
     if (type is FunctionType) {
       return visitor.visitFunctionType(type);
     }
+    if (type is FunctionTypeBuilder) {
+      return visitor.visitFunctionTypeBuilder(type);
+    }
     if (type is InterfaceType) {
       return visitor.visitInterfaceType(type);
     }
+    if (type is NamedTypeBuilder) {
+      return visitor.visitNamedType(type);
+    }
     if (type is TypeParameterType) {
       return visitor.visitTypeParameterType(type);
     }
diff --git a/pkg/analyzer/lib/src/dart/element/wrapped.dart b/pkg/analyzer/lib/src/dart/element/wrapped.dart
index 5aebd1d..ab41831 100644
--- a/pkg/analyzer/lib/src/dart/element/wrapped.dart
+++ b/pkg/analyzer/lib/src/dart/element/wrapped.dart
@@ -71,6 +71,9 @@
   bool get hasLoadLibraryFunction => wrappedUnit.hasLoadLibraryFunction;
 
   @override
+  bool get hasMustCallSuper => wrappedUnit.hasMustCallSuper;
+
+  @override
   bool get hasOptionalTypeArgs => wrappedUnit.hasOptionalTypeArgs;
 
   @override
@@ -264,6 +267,9 @@
   bool get hasLiteral => wrappedImport.hasLiteral;
 
   @override
+  bool get hasMustCallSuper => wrappedImport.hasMustCallSuper;
+
+  @override
   bool get hasOptionalTypeArgs => wrappedImport.hasOptionalTypeArgs;
 
   @override
@@ -420,6 +426,9 @@
   AnalysisContext get context => wrappedLib.context;
 
   @override
+  bool get isNonNullableByDefault => wrappedLib.isNonNullableByDefault;
+
+  @override
   CompilationUnitElement get definingCompilationUnit =>
       wrappedLib.definingCompilationUnit;
 
@@ -472,6 +481,9 @@
   bool get hasLoadLibraryFunction => wrappedLib.hasLoadLibraryFunction;
 
   @override
+  bool get hasMustCallSuper => wrappedLib.hasMustCallSuper;
+
+  @override
   bool get hasOptionalTypeArgs => wrappedLib.hasOptionalTypeArgs;
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index ef261f3..651d581 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -34,7 +34,7 @@
   static const HintCode DEAD_CODE_CATCH_FOLLOWING_CATCH = const HintCode(
       'DEAD_CODE_CATCH_FOLLOWING_CATCH',
       "Dead code: catch clauses after a 'catch (e)' or "
-      "an 'on Object catch (e)' are never reached.",
+          "an 'on Object catch (e)' are never reached.",
       correction:
           "Try reordering the catch clauses so that they can be reached, or "
           "removing the unreachable catch clauses.");
@@ -51,17 +51,36 @@
   static const HintCode DEAD_CODE_ON_CATCH_SUBTYPE = const HintCode(
       'DEAD_CODE_ON_CATCH_SUBTYPE',
       "Dead code: this on-catch block will never be executed because '{0}' is "
-      "a subtype of '{1}' and hence will have been caught above.",
+          "a subtype of '{1}' and hence will have been caught above.",
       correction:
           "Try reordering the catch clauses so that this block can be reached, or "
           "removing the unreachable catch clause.");
 
   /**
-   * Deprecated members should not be invoked or used.
-   *
    * Parameters:
    * 0: the name of the member
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a deprecated library or class
+  // member is used in a different package.
+  //
+  // #### Example
+  //
+  // If the method `m` in the class `C` is annotated with `@deprecated`, then
+  // the following code produces this diagnostic:
+  //
+  // ```dart
+  // void f(C c) {
+  //   c.!m!();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // The documentation for declarations that are annotated with `@deprecated`
+  // should have documentation to indicate what code to use in place of the
+  // deprecated code.
   static const HintCode DEPRECATED_MEMBER_USE = const HintCode(
       'DEPRECATED_MEMBER_USE', "'{0}' is deprecated and shouldn't be used.",
       correction:
@@ -148,7 +167,7 @@
       const HintCode(
           'FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE',
           "A file in the 'lib' directory shouldn't import a file outside the "
-          "'lib' directory.",
+              "'lib' directory.",
           correction: "Try removing the import, or "
               "moving the imported file inside the 'lib' directory.");
 
@@ -163,7 +182,7 @@
       const HintCode(
           'FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE',
           "A file outside the 'lib' directory shouldn't reference a file "
-          "inside the 'lib' directory using a relative path.",
+              "inside the 'lib' directory using a relative path.",
           correction: "Try using a package: URI instead.");
 
   /**
@@ -173,7 +192,7 @@
       const HintCode(
           'IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION',
           "The library '{0}' defines a top-level function named 'loadLibrary' "
-          "which is hidden by deferring this library.",
+              "which is hidden by deferring this library.",
           correction: "Try changing the import to not be deferred, or "
               "rename the function in the imported library.");
 
@@ -204,7 +223,7 @@
       const HintCode(
           'INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE',
           "The type of {0} cannot be inferred without either a type or "
-          "initializer.",
+              "initializer.",
           correction: "Try specifying the type of the variable.");
 
   /**
@@ -244,12 +263,32 @@
       "Only classes can be annotated as being immutable.");
 
   /**
-   * This hint is generated anywhere a @literal annotation is associated with
-   * anything other than a const constructor.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The meaning of the `@literal` annotation is only defined when it's applied
+  // to a const constructor.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // !@literal!
+  // var x;
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the annotation:
+  //
+  // ```dart
+  // var x;
+  // ```
   static const HintCode INVALID_LITERAL_ANNOTATION = const HintCode(
       'INVALID_LITERAL_ANNOTATION',
-      "Only const constructors can be annotated as being literal.");
+      "Only const constructors can have the `@literal` annotation.");
 
   /**
    * This hint is generated anywhere where `@required` annotates a non named
@@ -261,7 +300,7 @@
   static const HintCode INVALID_REQUIRED_PARAM = const HintCode(
       'INVALID_REQUIRED_PARAM',
       "The type parameter '{0}' is annotated with @required but only named "
-      "parameters without default value can be annotated with it.",
+          "parameters without default value can be annotated with it.",
       correction: "Remove @required.");
 
   /**
@@ -274,7 +313,7 @@
   static const HintCode INVALID_SEALED_ANNOTATION = const HintCode(
       'INVALID_SEALED_ANNOTATION',
       "The member '{0}' is annotated with '@sealed' but only classes can be "
-      "annotated with it.",
+          "annotated with it.",
       correction: "Remove @sealed.");
 
   /**
@@ -288,7 +327,7 @@
   static const HintCode INVALID_USE_OF_PROTECTED_MEMBER = const HintCode(
       'INVALID_USE_OF_PROTECTED_MEMBER',
       "The member '{0}' can only be used within instance members of subclasses "
-      "of '{1}'.");
+          "of '{1}'.");
 
   /// This hint is generated anywhere where a member annotated with
   /// `@visibleForTemplate` is used outside of a "template" Dart file.
@@ -319,7 +358,7 @@
   static const HintCode INVALID_VISIBILITY_ANNOTATION = const HintCode(
       'INVALID_VISIBILITY_ANNOTATION',
       "The member '{0}' is annotated with '{1}', but this annotation is only "
-      "meaningful on declarations of public members.");
+          "meaningful on declarations of public members.");
 
   /**
    * Hint for the `x is double` type checks.
@@ -327,7 +366,7 @@
   static const HintCode IS_DOUBLE = const HintCode(
       'IS_DOUBLE',
       "When compiled to JS, this test might return true when the left hand "
-      "side is an int.",
+          "side is an int.",
       correction: "Try testing for 'num' instead.");
 
   /**
@@ -338,7 +377,7 @@
   static const HintCode IS_INT = const HintCode(
       'IS_INT',
       "When compiled to JS, this test might return true when the left hand "
-      "side is a double.",
+          "side is a double.",
       correction: "Try testing for 'num' instead.");
 
   /**
@@ -347,7 +386,7 @@
   static const HintCode IS_NOT_DOUBLE = const HintCode(
       'IS_NOT_DOUBLE',
       "When compiled to JS, this test might return false when the left hand "
-      "side is an int.",
+          "side is an int.",
       correction: "Try testing for 'num' instead.");
 
   /**
@@ -358,7 +397,7 @@
   static const HintCode IS_NOT_INT = const HintCode(
       'IS_NOT_INT',
       "When compiled to JS, this test might return false when the left hand "
-      "side is a double.",
+          "side is a double.",
       correction: "Try testing for 'num' instead.");
 
   /**
@@ -368,7 +407,7 @@
   static const HintCode MISSING_JS_LIB_ANNOTATION = const HintCode(
       'MISSING_JS_LIB_ANNOTATION',
       "The @JS() annotation can only be used if it is also declared on the "
-      "library directive.",
+          "library directive.",
       correction: "Try adding the annotation to the library directive.");
 
   /**
@@ -405,7 +444,7 @@
   static const HintCode MISSING_RETURN = const HintCode(
       'MISSING_RETURN',
       "This function has a return type of '{0}', but doesn't end with a "
-      "return statement.",
+          "return statement.",
       correction: "Try adding a return statement, "
           "or changing the return type to 'void'.");
 
@@ -416,7 +455,7 @@
   static const HintCode MIXIN_ON_SEALED_CLASS = const HintCode(
       'MIXIN_ON_SEALED_CLASS',
       "The class '{0}' should not be used as a mixin constraint because it is "
-      "sealed, and any class mixing in this mixin has '{0}' as a superclass.",
+          "sealed, and any class mixing in this mixin has '{0}' as a superclass.",
       correction:
           "Try composing with this class, or refer to its documentation for "
           "more information.");
@@ -428,8 +467,8 @@
   static const HintCode MUST_BE_IMMUTABLE = const HintCode(
       'MUST_BE_IMMUTABLE',
       "This class (or a class which this class inherits from) is marked as "
-      "'@immutable', but one or more of its instance fields are not final: "
-      "{0}");
+          "'@immutable', but one or more of its instance fields are not final: "
+          "{0}");
 
   /**
    * Generate a hint for methods that override methods annotated `@mustCallSuper`
@@ -441,7 +480,7 @@
   static const HintCode MUST_CALL_SUPER = const HintCode(
       'MUST_CALL_SUPER',
       "This method overrides a method annotated as @mustCallSuper in '{0}', "
-      "but does not invoke the overridden method.");
+          "but does not invoke the overridden method.");
 
   /**
    * Generate a hint for non-const instance creation using a constructor
@@ -450,7 +489,7 @@
   static const HintCode NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR = const HintCode(
       'NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR',
       "This instance creation must be 'const', because the {0} constructor is "
-      "marked as '@literal'.",
+          "marked as '@literal'.",
       correction: "Try adding a 'const' keyword.");
 
   /**
@@ -461,7 +500,7 @@
       const HintCode(
           'NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW',
           "This instance creation must be 'const', because the {0} constructor is "
-          "marked as '@literal'.",
+              "marked as '@literal'.",
           correction: "Try replacing the 'new' keyword with 'const'.");
 
   /**
@@ -479,7 +518,7 @@
   static const HintCode NULL_AWARE_IN_CONDITION = const HintCode(
       'NULL_AWARE_IN_CONDITION',
       "The value of the '?.' operator can be 'null', which isn't appropriate "
-      "in a condition.",
+          "in a condition.",
       correction:
           "Try replacing the '?.' with a '.', testing the left-hand side for null if "
           "necessary.");
@@ -491,7 +530,7 @@
   static const HintCode NULL_AWARE_IN_LOGICAL_OPERATOR = const HintCode(
       'NULL_AWARE_IN_LOGICAL_OPERATOR',
       "The value of the '?.' operator can be 'null', which isn't appropriate "
-      "as an operand of a logical operator.");
+          "as an operand of a logical operator.");
 
   /**
    * Hint for classes that override equals, but not hashCode.
@@ -560,7 +599,7 @@
   static const HintCode SDK_VERSION_ASYNC_EXPORTED_FROM_CORE = const HintCode(
       'SDK_VERSION_ASYNC_EXPORTED_FROM_CORE',
       "The class '{0}' was not exported from 'dart:core' until version 2.1, "
-      "but this code is required to be able to run on earlier versions.",
+          "but this code is required to be able to run on earlier versions.",
       correction:
           "Try either importing 'dart:async' or updating the SDK constraints.");
 
@@ -568,13 +607,12 @@
    * An as expression being used in a const context is expected to run on
    * versions of the SDK that did not support them.
    */
-  static const HintCode SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT =
-      const HintCode(
-          'SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT',
-          "The use of an as expression in a constant expression wasn't "
-          "supported until version 2.2.2, but this code is required to be able "
+  static const HintCode SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT = const HintCode(
+      'SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT',
+      "The use of an as expression in a constant expression wasn't "
+          "supported until version 2.3.2, but this code is required to be able "
           "to run on earlier versions.",
-          correction: "Try updating the SDK constraints.");
+      correction: "Try updating the SDK constraints.");
 
   /**
    * The operator '&', '|' or '^' is being used on boolean values in code that
@@ -583,7 +621,7 @@
   static const HintCode SDK_VERSION_BOOL_OPERATOR = const HintCode(
       'SDK_VERSION_BOOL_OPERATOR',
       "Using the operator '{0}' for 'bool's was not supported until version "
-      "2.2.2, but this code is required to be able to run on earlier versions.",
+          "2.3.2, but this code is required to be able to run on earlier versions.",
       correction: "Try updating the SDK constraints.");
 
   /**
@@ -593,8 +631,8 @@
   static const HintCode SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT = const HintCode(
       'SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT',
       "Using the operator '==' for non-primitive types was not supported until "
-      "version 2.2.2, but this code is required to be able to run on earlier "
-      "versions.",
+          "version 2.3.2, but this code is required to be able to run on earlier "
+          "versions.",
       correction: "Try updating the SDK constraints.");
 
   /**
@@ -603,40 +641,84 @@
    */
   static const HintCode SDK_VERSION_GT_GT_GT_OPERATOR = const HintCode(
       'SDK_VERSION_GT_GT_GT_OPERATOR',
-      "The operator '>>>' was not supported until version 2.2.2, but this code "
-      "is required to be able to run on earlier versions.",
+      "The operator '>>>' was not supported until version 2.3.2, but this code "
+          "is required to be able to run on earlier versions.",
       correction: "Try updating the SDK constraints.");
 
   /**
    * An is expression being used in a const context is expected to run on
    * versions of the SDK that did not support them.
    */
-  static const HintCode SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT =
-      const HintCode(
-          'SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT',
-          "The use of an is expression in a constant expression wasn't "
-          "supported until version 2.2.2, but this code is required to be able "
+  static const HintCode SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT = const HintCode(
+      'SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT',
+      "The use of an is expression in a constant expression wasn't "
+          "supported until version 2.3.2, but this code is required to be able "
           "to run on earlier versions.",
-          correction: "Try updating the SDK constraints.");
+      correction: "Try updating the SDK constraints.");
 
   /**
-   * A set literal is being used in code that is expected to run on versions of
-   * the SDK that did not support them.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a set literal is found in code
+  // that has an SDK constraint whose lower bound is less than 2.2. Set literals
+  // were not supported in earlier versions, so this code won't be able to run
+  // against earlier versions of the SDK.
+  //
+  // #### Example
+  //
+  // In a package that defines SDK constraints in the `pubspec.yaml` file that
+  // have a lower bound that's less than 2.2:
+  //
+  // ```yaml
+  // environment:
+  //   sdk: '>=2.1.0 <2.4.0'
+  // ```
+  //
+  // The following code generates this diagnostic:
+  //
+  // ```dart
+  // var s = !<int>{}!;
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need to support older versions of the SDK, then you can
+  // increase the SDK constraint to allow the syntax to be used:
+  //
+  // ```yaml
+  // environment:
+  //   sdk: '>=2.2.0 <2.4.0'
+  // ```
+  //
+  // If you do need to support older versions of the SDK, then replace the set
+  // literal with code that creates the set without the use of a literal:
+  //
+  // ```dart
+  // var s = new Set<int>();
+  // ```
   static const HintCode SDK_VERSION_SET_LITERAL = const HintCode(
       'SDK_VERSION_SET_LITERAL',
-      "Set literals were not supported until version 2.2, "
-      "but this code is required to be able to run on earlier versions.",
+      "Set literals weren't supported until version 2.2, "
+          "but this code must be able to run on earlier versions.",
       correction: "Try updating the SDK constraints.");
 
   /**
+   * The type Never is being used in code that is expected to run on versions of
+   * the SDK that did not support it.
+   */
+  static const HintCode SDK_VERSION_NEVER = const HintCode(
+      'SDK_VERSION_NEVER', "The type Never is not yet supported.");
+
+  /**
    * The for, if or spread element is being used in code that is expected to run
    * on versions of the SDK that did not support them.
    */
   static const HintCode SDK_VERSION_UI_AS_CODE = const HintCode(
       'SDK_VERSION_UI_AS_CODE',
       "The for, if and spread elements were not supported until version 2.2.2, "
-      "but this code is required to be able to run on earlier versions.",
+          "but this code is required to be able to run on earlier versions.",
       correction: "Try updating the SDK constraints.");
 
   /**
@@ -648,13 +730,31 @@
       correction: "Use explicit type arguments for '{0}'.");
 
   /**
+   * When "strict-raw-types" is enabled, raw types must be inferred via the
+   * context type, or have type arguments.
+   */
+  static const HintCode STRICT_RAW_TYPE_IN_AS = HintCode(
+      'STRICT_RAW_TYPE_IN_AS',
+      "The generic type '{0}' should have explicit type arguments but doesn't.",
+      correction: "Use explicit type arguments for '{0}'.");
+
+  /**
+   * When "strict-raw-types" is enabled, raw types must be inferred via the
+   * context type, or have type arguments.
+   */
+  static const HintCode STRICT_RAW_TYPE_IN_IS = HintCode(
+      'STRICT_RAW_TYPE_IN_IS',
+      "The generic type '{0}' should have explicit type arguments but doesn't.",
+      correction: "Use explicit type arguments for '{0}'.");
+
+  /**
    * This hint is generated anywhere where a `@sealed` class or mixin is used as
    * a super-type of a class.
    */
   static const HintCode SUBTYPE_OF_SEALED_CLASS = const HintCode(
       'SUBTYPE_OF_SEALED_CLASS',
       "The class '{0}' should not be extended, mixed in, or implemented "
-      "because it is sealed.",
+          "because it is sealed.",
       correction:
           "Try composing instead of inheriting, or refer to its documentation "
           "for more information.");
@@ -801,8 +901,10 @@
    * template. The correction associated with the error will be created from the
    * given [correction] template.
    */
-  const HintCode(String name, String message, {String correction})
-      : super.temporary(name, message, correction: correction);
+  const HintCode(String name, String message,
+      {String correction, bool hasPublishedDocs})
+      : super.temporary(name, message,
+            correction: correction, hasPublishedDocs: hasPublishedDocs);
 
   @override
   ErrorSeverity get errorSeverity => ErrorType.HINT.severity;
diff --git a/pkg/analyzer/lib/src/dart/error/lint_codes.dart b/pkg/analyzer/lib/src/dart/error/lint_codes.dart
index d83e4a9..8d61ae3 100644
--- a/pkg/analyzer/lib/src/dart/error/lint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/lint_codes.dart
@@ -27,4 +27,8 @@
    * subclass the lint's code is defined in.
    */
   String get uniqueName => "LintCode.$name";
+
+  @override
+  String get url =>
+      'https://dart-lang.github.io/linter/lints/${name.toLowerCase()}.html';
 }
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index de2684c..cec3fe1 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -51,8 +51,8 @@
   static const ParserErrorCode ASYNC_KEYWORD_USED_AS_IDENTIFIER =
       const ParserErrorCode(
           'ASYNC_KEYWORD_USED_AS_IDENTIFIER',
-          "The keywords 'async', 'await', and 'yield' can't be used as "
-          "identifiers in an asynchronous or generator function.");
+          "The keywords 'await' and 'yield' can't be used as "
+              "identifiers in an asynchronous or generator function.");
 
   static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = _BREAK_OUTSIDE_OF_LOOP;
 
@@ -65,14 +65,18 @@
 
   static const ParserErrorCode COLON_IN_PLACE_OF_IN = _COLON_IN_PLACE_OF_IN;
 
+  static const ParserErrorCode CONFLICTING_MODIFIERS = _CONFLICTING_MODIFIERS;
+
   // TODO(danrubel): Remove this unused error code
   static const ParserErrorCode CONST_AFTER_FACTORY = _MODIFIER_OUT_OF_ORDER;
 
-  static const ParserErrorCode CONST_AND_COVARIANT = _CONST_AND_COVARIANT;
+  // TODO(danrubel): Remove this unused error code
+  static const ParserErrorCode CONST_AND_COVARIANT = _CONFLICTING_MODIFIERS;
 
   static const ParserErrorCode CONST_AND_FINAL = _CONST_AND_FINAL;
 
-  static const ParserErrorCode CONST_AND_VAR = _CONST_AND_VAR;
+  // TODO(danrubel): Remove this unused error code
+  static const ParserErrorCode CONST_AND_VAR = _CONFLICTING_MODIFIERS;
 
   static const ParserErrorCode CONST_CLASS = _CONST_CLASS;
 
@@ -102,9 +106,10 @@
   static const ParserErrorCode CONTINUE_WITHOUT_LABEL_IN_CASE =
       _CONTINUE_WITHOUT_LABEL_IN_CASE;
 
-  static const ParserErrorCode COVARIANT_AFTER_FINAL = _COVARIANT_AFTER_FINAL;
+  // TODO(danrubel): Remove this unused error code
+  static const ParserErrorCode COVARIANT_AFTER_FINAL = _MODIFIER_OUT_OF_ORDER;
 
-  static const ParserErrorCode COVARIANT_AFTER_VAR = _COVARIANT_AFTER_VAR;
+  static const ParserErrorCode COVARIANT_AFTER_VAR = _MODIFIER_OUT_OF_ORDER;
 
   static const ParserErrorCode COVARIANT_AND_STATIC = _COVARIANT_AND_STATIC;
 
@@ -156,6 +161,8 @@
   static const ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND =
       _EQUALITY_CANNOT_BE_EQUALITY_OPERAND;
 
+  static const ParserErrorCode EXPECTED_BODY = _EXPECTED_BODY;
+
   static const ParserErrorCode EXPECTED_CASE_OR_DEFAULT = const ParserErrorCode(
       'EXPECTED_CASE_OR_DEFAULT', "Expected 'case' or 'default'.",
       correction: "Try placing this code inside a case clause.");
@@ -197,11 +204,11 @@
   static const ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE =
       _EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE;
 
-  static const ParserErrorCode EXTERNAL_AFTER_CONST = _EXTERNAL_AFTER_CONST;
+  static const ParserErrorCode EXTERNAL_AFTER_CONST = _MODIFIER_OUT_OF_ORDER;
 
-  static const ParserErrorCode EXTERNAL_AFTER_FACTORY = _EXTERNAL_AFTER_FACTORY;
+  static const ParserErrorCode EXTERNAL_AFTER_FACTORY = _MODIFIER_OUT_OF_ORDER;
 
-  static const ParserErrorCode EXTERNAL_AFTER_STATIC = _EXTERNAL_AFTER_STATIC;
+  static const ParserErrorCode EXTERNAL_AFTER_STATIC = _MODIFIER_OUT_OF_ORDER;
 
   static const ParserErrorCode EXTERNAL_CLASS = _EXTERNAL_CLASS;
 
@@ -335,7 +342,7 @@
   static const ParserErrorCode INVALID_COMMENT_REFERENCE = const ParserErrorCode(
       'INVALID_COMMENT_REFERENCE',
       "Comment references should contain a possibly prefixed identifier and "
-      "can start with 'new', but shouldn't contain anything else.");
+          "can start with 'new', but shouldn't contain anything else.");
 
   static const ParserErrorCode INVALID_CONSTRUCTOR_NAME = const ParserErrorCode(
       'INVALID_CONSTRUCTOR_NAME',
@@ -410,11 +417,7 @@
   static const ParserErrorCode MISSING_CATCH_OR_FINALLY =
       _MISSING_CATCH_OR_FINALLY;
 
-  /// TODO(danrubel): Consider splitting this into two separate error messages.
-  static const ParserErrorCode MISSING_CLASS_BODY = const ParserErrorCode(
-      'MISSING_CLASS_BODY',
-      "A class or mixin definition must have a body, even if it is empty.",
-      correction: "Try adding a body to your class or mixin.");
+  static const ParserErrorCode MISSING_CLASS_BODY = _EXPECTED_BODY;
 
   static const ParserErrorCode MISSING_CLOSING_PARENTHESIS =
       const ParserErrorCode(
@@ -559,7 +562,7 @@
       const ParserErrorCode(
           'MULTIPLE_VARIABLES_IN_FOR_EACH',
           "A single loop variable must be declared in a for-each loop before "
-          "the 'in', but {0} were found.",
+              "the 'in', but {0} were found.",
           correction:
               "Try moving all but one of the declarations inside the loop body.");
 
@@ -583,14 +586,14 @@
       const ParserErrorCode(
           'NATIVE_CLAUSE_IN_NON_SDK_CODE',
           "Native clause can only be used in the SDK and code that is loaded "
-          "through native extensions.",
+              "through native extensions.",
           correction: "Try removing the native clause.");
 
   static const ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE =
       const ParserErrorCode(
           'NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE',
           "Native functions can only be declared in the SDK and code that is "
-          "loaded through native extensions.",
+              "loaded through native extensions.",
           correction: "Try removing the word 'native'.");
 
   static const ParserErrorCode NATIVE_CLAUSE_SHOULD_BE_ANNOTATION =
@@ -660,11 +663,11 @@
 
   static const ParserErrorCode STACK_OVERFLOW = _STACK_OVERFLOW;
 
-  static const ParserErrorCode STATIC_AFTER_CONST = _STATIC_AFTER_CONST;
+  static const ParserErrorCode STATIC_AFTER_CONST = _MODIFIER_OUT_OF_ORDER;
 
-  static const ParserErrorCode STATIC_AFTER_FINAL = _STATIC_AFTER_FINAL;
+  static const ParserErrorCode STATIC_AFTER_FINAL = _MODIFIER_OUT_OF_ORDER;
 
-  static const ParserErrorCode STATIC_AFTER_VAR = _STATIC_AFTER_VAR;
+  static const ParserErrorCode STATIC_AFTER_VAR = _MODIFIER_OUT_OF_ORDER;
 
   static const ParserErrorCode STATIC_CONSTRUCTOR = _STATIC_CONSTRUCTOR;
 
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index c02bde2..80d4ee8b 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -15,7 +15,7 @@
   _EXTERNAL_ENUM,
   _PREFIX_AFTER_COMBINATOR,
   _TYPEDEF_IN_CLASS,
-  _COVARIANT_AFTER_VAR,
+  _EXPECTED_BODY,
   _INVALID_AWAIT_IN_FOR,
   _IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
   _WITH_BEFORE_EXTENDS,
@@ -25,9 +25,9 @@
   _SWITCH_HAS_MULTIPLE_DEFAULT_CASES,
   _SWITCH_HAS_CASE_AFTER_DEFAULT_CASE,
   _STATIC_OPERATOR,
-  _STATIC_AFTER_VAR,
-  _STATIC_AFTER_FINAL,
-  _STATIC_AFTER_CONST,
+  _INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER,
+  _STACK_OVERFLOW,
+  _MISSING_CATCH_OR_FINALLY,
   _REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
   _REDIRECTING_CONSTRUCTOR_WITH_BODY,
   _NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
@@ -53,9 +53,9 @@
   _IMPLEMENTS_BEFORE_ON,
   _IMPLEMENTS_BEFORE_EXTENDS,
   _ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE,
-  _EXTERNAL_AFTER_CONST,
-  _EXTERNAL_AFTER_FACTORY,
-  _EXTERNAL_AFTER_STATIC,
+  _EXPECTED_ELSE_OR_COMMA,
+  _INVALID_SUPER_IN_INITIALIZER,
+  _EXPERIMENT_NOT_ENABLED,
   _EXTERNAL_METHOD_WITH_BODY,
   _EXTERNAL_FIELD,
   _ABSTRACT_CLASS_MEMBER,
@@ -64,15 +64,15 @@
   _COLON_IN_PLACE_OF_IN,
   _CONSTRUCTOR_WITH_RETURN_TYPE,
   _MODIFIER_OUT_OF_ORDER,
-  _CONST_AND_COVARIANT,
+  _TYPE_BEFORE_FACTORY,
   _CONST_AND_FINAL,
-  _CONST_AND_VAR,
+  _CONFLICTING_MODIFIERS,
   _CONST_CLASS,
   _VAR_AS_TYPE_NAME,
   _CONST_FACTORY,
   _CONST_METHOD,
   _CONTINUE_WITHOUT_LABEL_IN_CASE,
-  _COVARIANT_AFTER_FINAL,
+  _INVALID_THIS_IN_INITIALIZER,
   _COVARIANT_AND_STATIC,
   _COVARIANT_MEMBER,
   _DEFERRED_AFTER_PREFIX,
@@ -97,14 +97,6 @@
   _EXTERNAL_CONSTRUCTOR_WITH_BODY,
   _FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS,
   _VAR_AND_TYPE,
-  _INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER,
-  _STACK_OVERFLOW,
-  _MISSING_CATCH_OR_FINALLY,
-  _EXPERIMENT_NOT_ENABLED,
-  _EXPECTED_ELSE_OR_COMMA,
-  _INVALID_SUPER_IN_INITIALIZER,
-  _INVALID_THIS_IN_INITIALIZER,
-  _TYPE_BEFORE_FACTORY,
 ];
 
 const ParserErrorCode _ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
@@ -137,24 +129,20 @@
     'COLON_IN_PLACE_OF_IN', r"For-in loops use 'in' rather than a colon.",
     correction: "Try replacing the colon with the keyword 'in'.");
 
+const ParserErrorCode _CONFLICTING_MODIFIERS = const ParserErrorCode(
+    'CONFLICTING_MODIFIERS',
+    r"Members can't be declared to be both '#string' and '#string2'.",
+    correction: "Try removing one of the keywords.");
+
 const ParserErrorCode _CONSTRUCTOR_WITH_RETURN_TYPE = const ParserErrorCode(
     'CONSTRUCTOR_WITH_RETURN_TYPE', r"Constructors can't have a return type.",
     correction: "Try removing the return type.");
 
-const ParserErrorCode _CONST_AND_COVARIANT = const ParserErrorCode(
-    'CONST_AND_COVARIANT',
-    r"Members can't be declared to be both 'const' and 'covariant'.",
-    correction: "Try removing either the 'const' or 'covariant' keyword.");
-
 const ParserErrorCode _CONST_AND_FINAL = const ParserErrorCode(
     'CONST_AND_FINAL',
     r"Members can't be declared to be both 'const' and 'final'.",
     correction: "Try removing either the 'const' or 'final' keyword.");
 
-const ParserErrorCode _CONST_AND_VAR = const ParserErrorCode(
-    'CONST_AND_VAR', r"Members can't be declared to be both 'const' and 'var'.",
-    correction: "Try removing either the 'const' or 'var' keyword.");
-
 const ParserErrorCode _CONST_CLASS = const ParserErrorCode(
     'CONST_CLASS', r"Classes can't be declared to be 'const'.",
     correction:
@@ -180,16 +168,6 @@
     correction:
         "Try adding a label associated with one of the case clauses to the continue statement.");
 
-const ParserErrorCode _COVARIANT_AFTER_FINAL = const ParserErrorCode(
-    'COVARIANT_AFTER_FINAL',
-    r"The modifier 'covariant' should be before the modifier 'final'.",
-    correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _COVARIANT_AFTER_VAR = const ParserErrorCode(
-    'COVARIANT_AFTER_VAR',
-    r"The modifier 'covariant' should be before the modifier 'var'.",
-    correction: "Try re-ordering the modifiers.");
-
 const ParserErrorCode _COVARIANT_AND_STATIC = const ParserErrorCode(
     'COVARIANT_AND_STATIC',
     r"Members can't be declared to be both 'covariant' and 'static'.",
@@ -238,6 +216,10 @@
     r"An equality expression can't be an operand of another equality expression.",
     correction: "Try re-writing the expression.");
 
+const ParserErrorCode _EXPECTED_BODY = const ParserErrorCode(
+    'EXPECTED_BODY', r"A #string must have a body, even if it is empty.",
+    correction: "Try adding an empty body.");
+
 const ParserErrorCode _EXPECTED_ELSE_OR_COMMA = const ParserErrorCode(
     'EXPECTED_ELSE_OR_COMMA', r"Expected 'else' or comma.");
 
@@ -256,21 +238,6 @@
         correction:
             "Try moving the export directives before the part directives.");
 
-const ParserErrorCode _EXTERNAL_AFTER_CONST = const ParserErrorCode(
-    'EXTERNAL_AFTER_CONST',
-    r"The modifier 'external' should be before the modifier 'const'.",
-    correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _EXTERNAL_AFTER_FACTORY = const ParserErrorCode(
-    'EXTERNAL_AFTER_FACTORY',
-    r"The modifier 'external' should be before the modifier 'factory'.",
-    correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _EXTERNAL_AFTER_STATIC = const ParserErrorCode(
-    'EXTERNAL_AFTER_STATIC',
-    r"The modifier 'external' should be before the modifier 'static'.",
-    correction: "Try re-ordering the modifiers.");
-
 const ParserErrorCode _EXTERNAL_CLASS = const ParserErrorCode(
     'EXTERNAL_CLASS', r"Classes can't be declared to be 'external'.",
     correction: "Try removing the keyword 'external'.");
@@ -503,21 +470,6 @@
     r"The file has too many nested expressions or statements.",
     correction: "Try simplifying the code.");
 
-const ParserErrorCode _STATIC_AFTER_CONST = const ParserErrorCode(
-    'STATIC_AFTER_CONST',
-    r"The modifier 'static' should be before the modifier 'const'.",
-    correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _STATIC_AFTER_FINAL = const ParserErrorCode(
-    'STATIC_AFTER_FINAL',
-    r"The modifier 'static' should be before the modifier 'final'.",
-    correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _STATIC_AFTER_VAR = const ParserErrorCode(
-    'STATIC_AFTER_VAR',
-    r"The modifier 'static' should be before the modifier 'var'.",
-    correction: "Try re-ordering the modifiers.");
-
 const ParserErrorCode _STATIC_CONSTRUCTOR = const ParserErrorCode(
     'STATIC_CONSTRUCTOR', r"Constructors can't be static.",
     correction: "Try removing the keyword 'static'.");
diff --git a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
index 0184c06..b1781ea 100644
--- a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
@@ -359,6 +359,8 @@
       if (r > numOfRequiredParams) {
         r = numOfRequiredParams;
       }
+      // TODO(brianwilkerson) Handle the fact that named parameters can now be
+      //  required.
       namedParametersList.addAll(_getNamedParameterNames(element));
     }
     return _createSyntheticExecutableElement(
@@ -426,6 +428,8 @@
       parameter.parameterKind = ParameterKind.POSITIONAL;
       parameters[i] = parameter;
     }
+    // TODO(brianwilkerson) Handle the fact that named parameters can now be
+    //  required.
     for (int m = 0; m < namedParameters.length; m++, i++) {
       ParameterElementImpl parameter =
           new ParameterElementImpl(namedParameters[m], 0);
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index 844dfd9..184d379 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -38,6 +38,9 @@
   /// The object keeping track of which elements have had their types promoted.
   final TypePromotionManager _promoteManager;
 
+  /// The invocation being resolved.
+  MethodInvocationImpl _invocation;
+
   /// The [Name] object of the invocation being resolved by [resolve].
   Name _currentName;
 
@@ -52,6 +55,8 @@
   Scope get nameScope => _resolver.nameScope;
 
   void resolve(MethodInvocation node) {
+    _invocation = node;
+
     SimpleIdentifier nameNode = node.methodName;
     String name = nameNode.name;
     _currentName = Name(_definingLibraryUri, name);
@@ -167,10 +172,17 @@
 
     if (typeFormals.isNotEmpty) {
       if (arguments == null) {
-        return _resolver.typeSystem.instantiateToBounds(invokeType);
+        var typeArguments =
+            _resolver.typeSystem.instantiateTypeFormalsToBounds(typeFormals);
+        _invocation.typeArgumentTypes = typeArguments;
+        return invokeType.instantiate(typeArguments);
       } else {
-        return invokeType.instantiate(arguments.map((n) => n.type).toList());
+        var typeArguments = arguments.map((n) => n.type).toList();
+        _invocation.typeArgumentTypes = typeArguments;
+        return invokeType.instantiate(typeArguments);
       }
+    } else {
+      _invocation.typeArgumentTypes = const <DartType>[];
     }
 
     return invokeType;
@@ -442,6 +454,7 @@
         nameNode.staticElement = loadLibraryFunction;
         node.staticInvokeType = loadLibraryFunction?.type;
         node.staticType = loadLibraryFunction?.returnType;
+        _setExplicitTypeArgumentTypes();
         return;
       }
     }
@@ -547,18 +560,32 @@
     }
     node.staticInvokeType = _dynamicType;
     node.staticType = _dynamicType;
+    _setExplicitTypeArgumentTypes();
+  }
+
+  /// Set explicitly specified type argument types, or empty if not specified.
+  /// Inference is done in type analyzer, so inferred type arguments might be
+  /// set later.
+  void _setExplicitTypeArgumentTypes() {
+    var typeArgumentList = _invocation.typeArguments;
+    if (typeArgumentList != null) {
+      var arguments = typeArgumentList.arguments;
+      _invocation.typeArgumentTypes = arguments.map((n) => n.type).toList();
+    } else {
+      _invocation.typeArgumentTypes = [];
+    }
   }
 
   void _setResolution(MethodInvocation node, DartType type) {
-    if (type == _dynamicType || _isCoreFunction(type)) {
-      _setDynamicResolution(node);
-      return;
-    }
-
     // TODO(scheglov) We need this for StaticTypeAnalyzer to run inference.
     // But it seems weird. Do we need to know the raw type of a function?!
     node.methodName.staticType = type;
 
+    if (type == _dynamicType || _isCoreFunction(type)) {
+      _setDynamicResolution(node, setNameTypeToDynamic: false);
+      return;
+    }
+
     if (type is InterfaceType) {
       var call = _inheritance.getMember(type, _nameCall);
       if (call != null && call.element.kind == ElementKind.METHOD) {
@@ -573,6 +600,7 @@
         node.typeArguments,
         node.methodName,
       );
+      instantiatedType = _toSyntheticFunctionType(instantiatedType);
       node.staticInvokeType = instantiatedType;
       node.staticType = instantiatedType.returnType;
       // TODO(scheglov) too much magic
@@ -619,4 +647,30 @@
     }
     return false;
   }
+
+  /// As an experiment for using synthetic [FunctionType]s, we replace some
+  /// function types with the equivalent synthetic function type instance.
+  /// The assumption that we try to prove is that only the set of parameters,
+  /// with their names, types and kinds is important, but the element that
+  /// encloses them is not (`null` for synthetic function types).
+  static FunctionType _toSyntheticFunctionType(FunctionType type) {
+//    if (type.element is GenericFunctionTypeElement) {
+//      var synthetic = FunctionTypeImpl.synthetic(
+//        type.returnType,
+//        type.typeFormals.map((e) {
+//          return TypeParameterElementImpl.synthetic(e.name)..bound = e.bound;
+//        }).toList(),
+//        type.parameters.map((p) {
+//          return ParameterElementImpl.synthetic(
+//            p.name,
+//            p.type,
+//            // ignore: deprecated_member_use_from_same_package
+//            p.parameterKind,
+//          );
+//        }).toList(),
+//      );
+//      return synthetic;
+//    }
+    return type;
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index f1fb360..e2194c6 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -526,7 +527,7 @@
       for (int i = 0; i < _importedNamespaces.length; i++) {
         Element element = lookup(_importedNamespaces[i]);
         if (element != null) {
-          if (element.library.isInSdk) {
+          if (element is NeverElementImpl || element.library.isInSdk) {
             sdkElements.add(element);
           } else {
             nonSdkElements.add(element);
@@ -725,6 +726,7 @@
     // which is not possible for `dynamic`.
     if (library.isDartCore) {
       definedNames['dynamic'] = DynamicElementImpl.instance;
+      definedNames['Never'] = BottomTypeImpl.instance.element;
     }
 
     return new Namespace(definedNames);
diff --git a/pkg/analyzer/lib/src/dart/resolver/variance.dart b/pkg/analyzer/lib/src/dart/resolver/variance.dart
new file mode 100644
index 0000000..69bc580
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/variance.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2019, 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:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+
+/// Computes the variance of the [typeParameter] in the [type].
+int computeVariance(TypeParameterElement typeParameter, DartType type) {
+  if (type is TypeParameterType) {
+    if (type.element == typeParameter) {
+      return Variance.covariant;
+    } else {
+      return Variance.unrelated;
+    }
+  } else if (type is InterfaceType) {
+    var result = Variance.unrelated;
+    for (var argument in type.typeArguments) {
+      result = Variance.meet(
+        result,
+        computeVariance(typeParameter, argument),
+      );
+    }
+    return result;
+  } else if (type is FunctionType) {
+    var result = computeVariance(typeParameter, type.returnType);
+
+    for (var parameter in type.typeFormals) {
+      // If [parameter] is referenced in the bound at all, it makes the
+      // variance of [parameter] in the entire type invariant.  The invocation
+      // of [computeVariance] below is made to simply figure out if [variable]
+      // occurs in the bound.
+      var bound = parameter.bound;
+      if (bound != null &&
+          computeVariance(typeParameter, bound) != Variance.unrelated) {
+        result = Variance.invariant;
+      }
+    }
+
+    for (var parameter in type.parameters) {
+      result = Variance.meet(
+        result,
+        Variance.combine(
+          Variance.contravariant,
+          computeVariance(typeParameter, parameter.type),
+        ),
+      );
+    }
+    return result;
+  }
+  return Variance.unrelated;
+}
+
+/// Value set for variance of a type parameter `X` in a type `T`.
+class Variance {
+  /// Used when `X` does not occur free in `T`.
+  static const int unrelated = 0;
+
+  /// Used when `X` occurs free in `T`, and `U <: V` implies `[U/X]T <: [V/X]T`.
+  static const int covariant = 1;
+
+  /// Used when `X` occurs free in `T`, and `U <: V` implies `[V/X]T <: [U/X]T`.
+  static const int contravariant = 2;
+
+  /// Used when there exists a pair `U` and `V` such that `U <: V`, but
+  /// `[U/X]T` and `[V/X]T` are incomparable.
+  static const int invariant = 3;
+
+  /// Combines variances of `X` in `T` and `Y` in `S` into variance of `X` in
+  /// `[Y/T]S`.
+  ///
+  /// Consider the following examples:
+  ///
+  /// * variance of `X` in `Function(X)` is [contravariant], variance of `Y`
+  /// in `List<Y>` is [covariant], so variance of `X` in `List<Function(X)>` is
+  /// [contravariant];
+  ///
+  /// * variance of `X` in `List<X>` is [covariant], variance of `Y` in
+  /// `Function(Y)` is [contravariant], so variance of `X` in
+  /// `Function(List<X>)` is [contravariant];
+  ///
+  /// * variance of `X` in `Function(X)` is [contravariant], variance of `Y` in
+  /// `Function(Y)` is [contravariant], so variance of `X` in
+  /// `Function(Function(X))` is [covariant];
+  ///
+  /// * let the following be declared:
+  ///
+  ///     typedef F<Z> = Function();
+  ///
+  /// then variance of `X` in `F<X>` is [unrelated], variance of `Y` in
+  /// `List<Y>` is [covariant], so variance of `X` in `List<F<X>>` is
+  /// [unrelated];
+  ///
+  /// * let the following be declared:
+  ///
+  ///     typedef G<Z> = Z Function(Z);
+  ///
+  /// then variance of `X` in `List<X>` is [covariant], variance of `Y` in
+  /// `G<Y>` is [invariant], so variance of `X` in `G<List<X>>` is [invariant].
+  static int combine(int a, int b) {
+    if (a == unrelated || b == unrelated) return unrelated;
+    if (a == invariant || b == invariant) return invariant;
+    return a == b ? covariant : contravariant;
+  }
+
+  /// Variance values form a lattice where [unrelated] is the top, [invariant]
+  /// is the bottom, and [covariant] and [contravariant] are incomparable.
+  /// [meet] calculates the meet of two elements of such lattice.  It can be
+  /// used, for example, to calculate the variance of a typedef type parameter
+  /// if it's encountered on the RHS of the typedef multiple times.
+  static int meet(int a, int b) => a | b;
+}
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
index ab852cf..b446a32 100644
--- a/pkg/analyzer/lib/src/dart/scanner/scanner.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
@@ -10,6 +11,7 @@
 import 'package:front_end/src/fasta/scanner.dart' as fasta;
 import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
 import 'package:front_end/src/scanner/token.dart' show Token, TokenType;
+import 'package:pub_semver/pub_semver.dart';
 
 export 'package:analyzer/src/dart/error/syntactic_errors.dart';
 
@@ -51,14 +53,25 @@
 
   Token firstToken;
 
-  bool scanLazyAssignmentOperators = false;
-
   /**
-   * A flag indicating whether the scanner should recognize the `>>>` operator.
+   * A flag indicating whether the scanner should recognize the `>>>` operator
+   * and the `>>>=` operator.
+   *
+   * Use [configureFeatures] rather than this field.
    */
   bool enableGtGtGt = false;
 
   /**
+   * A flag indicating whether the scanner should recognize the `late` and
+   * `required` keywords.
+   *
+   * Use [configureFeatures] rather than this field.
+   */
+  bool enableNonNullable = false;
+
+  FeatureSet _featureSet;
+
+  /**
    * Initialize a newly created scanner to scan characters from the given
    * [source]. The given character [reader] will be used to read the characters
    * in the source. The given [_errorListener] will be informed of any errors
@@ -80,10 +93,33 @@
     lineStarts.add(0);
   }
 
+  /**
+   * The features associated with this scanner.
+   *
+   * If a language version comment (e.g. '// @dart = 2.3') is detected
+   * when calling [tokenize] and this field is non-null, then this field
+   * will be updated to contain a downgraded feature set based upon the
+   * language version specified.
+   *
+   * Use [configureFeatures] to set the features.
+   */
+  FeatureSet get featureSet => _featureSet;
+
   set preserveComments(bool preserveComments) {
     this._preserveComments = preserveComments;
   }
 
+  /// Configures the scanner appropriately for the given [featureSet].
+  ///
+  /// TODO(paulberry): stop exposing `enableGtGtGt` and `enableNonNullable` so
+  /// that callers are forced to use this API.  Note that this would be a
+  /// breaking change.
+  void configureFeatures(FeatureSet featureSet) {
+    this._featureSet = featureSet;
+    enableGtGtGt = featureSet.isEnabled(Feature.triple_shift);
+    enableNonNullable = featureSet.isEnabled(Feature.non_nullable);
+  }
+
   void reportError(
       ScannerErrorCode errorCode, int offset, List<Object> arguments) {
     _errorListener
@@ -102,11 +138,19 @@
     lineStarts.add(offset - column + 1);
   }
 
-  Token tokenize() {
+  /// The fasta parser handles error tokens produced by the scanner
+  /// but the old parser used by angular does not
+  /// and expects that scanner errors to be reported by this method.
+  /// Set [reportScannerErrors] `true` when using the old parser.
+  Token tokenize({bool reportScannerErrors = true}) {
     fasta.ScannerResult result = fasta.scanString(_contents,
-        enableGtGtGt: enableGtGtGt,
+        configuration: _featureSet != null
+            ? buildConfig(_featureSet)
+            : fasta.ScannerConfiguration(
+                enableTripleShift: enableGtGtGt,
+                enableNonNullable: enableNonNullable),
         includeComments: _preserveComments,
-        scanLazyAssignmentOperators: scanLazyAssignmentOperators);
+        languageVersionChanged: _languageVersionChanged);
 
     // fasta pretends there is an additional line at EOF
     result.lineStarts.removeLast();
@@ -116,12 +160,19 @@
 
     lineStarts.addAll(result.lineStarts);
     fasta.Token token = result.tokens;
-    // The default recovery strategy used by scanString
-    // places all error tokens at the head of the stream.
-    while (token.type == TokenType.BAD_INPUT) {
-      translateErrorToken(token, reportError);
-      token = token.next;
+
+    // The fasta parser handles error tokens produced by the scanner
+    // but the old parser used by angular does not
+    // and expects that scanner errors to be reported here
+    if (reportScannerErrors) {
+      // The default recovery strategy used by scanString
+      // places all error tokens at the head of the stream.
+      while (token.type == TokenType.BAD_INPUT) {
+        translateErrorToken(token, reportError);
+        token = token.next;
+      }
     }
+
     firstToken = token;
     // Update all token offsets based upon the reader's starting offset
     if (_readerOffset != -1) {
@@ -133,4 +184,23 @@
     }
     return firstToken;
   }
+
+  void _languageVersionChanged(
+      fasta.Scanner scanner, fasta.LanguageVersionToken languageVersion) {
+    if (_featureSet != null) {
+      _featureSet = _featureSet.restrictToVersion(
+          Version(languageVersion.major, languageVersion.minor, 0));
+      scanner.configuration = buildConfig(_featureSet);
+    }
+  }
+
+  /// Return a ScannerConfiguration based upon the specified feature set.
+  static fasta.ScannerConfiguration buildConfig(FeatureSet featureSet) =>
+      featureSet == null
+          ? fasta.ScannerConfiguration()
+          : fasta.ScannerConfiguration(
+              enableExtensionMethods:
+                  featureSet.isEnabled(Feature.extension_methods),
+              enableTripleShift: featureSet.isEnabled(Feature.triple_shift),
+              enableNonNullable: featureSet.isEnabled(Feature.non_nullable));
 }
diff --git a/pkg/analyzer/lib/src/dart/sdk/patch.dart b/pkg/analyzer/lib/src/dart/sdk/patch.dart
index d2f8f1e..72c191f 100644
--- a/pkg/analyzer/lib/src/dart/sdk/patch.dart
+++ b/pkg/analyzer/lib/src/dart/sdk/patch.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
@@ -58,7 +59,8 @@
             'The patch file ${patchFile.path} for $source does not exist.');
       }
       Source patchSource = patchFile.createSource();
-      CompilationUnit patchUnit = parse(patchSource, errorListener);
+      CompilationUnit patchUnit =
+          parse(patchSource, errorListener, unit.featureSet);
 
       // Prepare for reporting errors.
       _baseDesc = source.toString();
@@ -405,16 +407,17 @@
    * Parse the given [source] into AST.
    */
   @visibleForTesting
-  static CompilationUnit parse(
-      Source source, AnalysisErrorListener errorListener) {
+  static CompilationUnit parse(Source source,
+      AnalysisErrorListener errorListener, FeatureSet featureSet) {
     String code = source.contents.data;
 
     CharSequenceReader reader = new CharSequenceReader(code);
-    Scanner scanner = new Scanner(source, reader, errorListener);
+    Scanner scanner = new Scanner(source, reader, errorListener)
+      ..configureFeatures(featureSet);
     Token token = scanner.tokenize();
     LineInfo lineInfo = new LineInfo(scanner.lineStarts);
 
-    Parser parser = new Parser(source, errorListener);
+    Parser parser = new Parser(source, errorListener, featureSet: featureSet);
     CompilationUnit unit = parser.parseCompilationUnit(token);
     unit.lineInfo = lineInfo;
     return unit;
diff --git a/pkg/analyzer/lib/src/dart/sdk/sdk.dart b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
index 41e4bfe..22ab2f2 100644
--- a/pkg/analyzer/lib/src/dart/sdk/sdk.dart
+++ b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
@@ -6,6 +6,7 @@
 import 'dart:convert';
 import 'dart:io' as io;
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/exception/exception.dart';
@@ -129,6 +130,16 @@
     });
   }
 
+  /**
+   * Return info for debugging https://github.com/dart-lang/sdk/issues/35226.
+   */
+  Map<String, Object> debugInfo() {
+    return <String, Object>{
+      'runtimeType': '$runtimeType',
+      'libraryMap': libraryMap.debugInfo(),
+    };
+  }
+
   @override
   Source fromFileUri(Uri uri) {
     File file =
@@ -219,16 +230,6 @@
     return source;
   }
 
-  /**
-   * Return info for debugging https://github.com/dart-lang/sdk/issues/35226.
-   */
-  Map<String, Object> debugInfo() {
-    return <String, Object>{
-      'runtimeType': '$runtimeType',
-      'libraryMap': libraryMap.debugInfo(),
-    };
-  }
-
   String _getPath(File file) {
     List<SdkLibrary> libraries = libraryMap.sdkLibraries;
     int length = libraries.length;
@@ -551,16 +552,6 @@
   }
 
   /**
-   * Return info for debugging https://github.com/dart-lang/sdk/issues/35226.
-   */
-  @override
-  Map<String, Object> debugInfo() {
-    var result = super.debugInfo();
-    result['directory'] = _sdkDirectory.path;
-    return result;
-  }
-
-  /**
    * Determine the search order for trying to locate the [_LIBRARIES_FILE].
    */
   Iterable<File> get _libraryMapLocations sync* {
@@ -574,6 +565,16 @@
         .getChildAssumingFile(_LIBRARIES_FILE);
   }
 
+  /**
+   * Return info for debugging https://github.com/dart-lang/sdk/issues/35226.
+   */
+  @override
+  Map<String, Object> debugInfo() {
+    var result = super.debugInfo();
+    result['directory'] = _sdkDirectory.path;
+    return result;
+  }
+
   @override
   String getRelativePathFromFile(File file) {
     String filePath = file.path;
@@ -897,9 +898,13 @@
    */
   LibraryMap readFromSource(Source source, String libraryFileContents) {
     BooleanErrorListener errorListener = new BooleanErrorListener();
+    // TODO(paulberry): initialize the feature set appropriately based on the
+    // version of the SDK we are reading, and enable flags.
+    var featureSet = FeatureSet.fromEnableFlags([]);
     Scanner scanner = new Scanner(
-        source, new CharSequenceReader(libraryFileContents), errorListener);
-    Parser parser = new Parser(source, errorListener);
+        source, new CharSequenceReader(libraryFileContents), errorListener)
+      ..configureFeatures(featureSet);
+    Parser parser = new Parser(source, errorListener, featureSet: featureSet);
     CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
     SdkLibrariesReader_LibraryBuilder libraryBuilder =
         new SdkLibrariesReader_LibraryBuilder(_useDart2jsPaths);
diff --git a/pkg/analyzer/lib/src/dartdoc/dartdoc_directive_info.dart b/pkg/analyzer/lib/src/dartdoc/dartdoc_directive_info.dart
index ca9c241..1449906 100644
--- a/pkg/analyzer/lib/src/dartdoc/dartdoc_directive_info.dart
+++ b/pkg/analyzer/lib/src/dartdoc/dartdoc_directive_info.dart
@@ -18,6 +18,13 @@
       r'[ ]*{@template\s+(.+?)}([\s\S]+?){@endtemplate}[ ]*\n?',
       multiLine: true);
 
+  /// A regular expression used to match a youtube or animation directive.
+  ///
+  /// These are in the form:
+  /// `{@youtube 560 315 https://www.youtube.com/watch?v=2uaoEDOgk_I}`.
+  static final videoRegExp =
+      new RegExp(r'{@(youtube|animation)\s+[^}]+\s+[^}]+\s+([^}]+)}');
+
   /// A table mapping the names of templates to the unprocessed bodies of the
   /// templates.
   final Map<String, String> templateMap = {};
@@ -45,8 +52,12 @@
     }
   }
 
-  /// Process the given Dartdoc [comment], replacing any macro directives with
-  /// the body of the corresponding template.
+  /// Process the given Dartdoc [comment], replacing any known dartdoc
+  /// directives with the associated content.
+  ///
+  /// Macro directives are replaced with the body of the corresponding template.
+  ///
+  /// Youtube and animation directives are replaced with markdown hyperlinks.
   String processDartdoc(String comment) {
     List<String> lines = _stripDelimiters(comment);
     for (int i = lines.length - 1; i >= 0; i--) {
@@ -58,6 +69,20 @@
         if (value != null) {
           lines[i] = value;
         }
+        continue;
+      }
+
+      match = videoRegExp.firstMatch(line);
+      if (match != null) {
+        String uri = match.group(2);
+        if (uri != null && uri.isNotEmpty) {
+          String label = uri;
+          if (label.startsWith('https://')) {
+            label = label.substring('https://'.length);
+          }
+          lines[i] = '[$label]($uri)';
+        }
+        continue;
       }
     }
     return lines.join('\n');
diff --git a/pkg/analyzer/lib/src/diagnostic/diagnostic.dart b/pkg/analyzer/lib/src/diagnostic/diagnostic.dart
new file mode 100644
index 0000000..d45ad279
--- /dev/null
+++ b/pkg/analyzer/lib/src/diagnostic/diagnostic.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2019, 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:analyzer/diagnostic/diagnostic.dart';
+import 'package:meta/meta.dart';
+
+/// A concrete implementation of a diagnostic message.
+class DiagnosticMessageImpl implements DiagnosticMessage {
+  @override
+  final String filePath;
+
+  @override
+  final int length;
+
+  @override
+  final String message;
+
+  @override
+  final int offset;
+
+  /// Initialize a newly created message to represent a [message] reported in
+  /// the file at the given [filePath] at the given [offset] and with the given
+  /// [length].
+  DiagnosticMessageImpl(
+      {@required this.filePath,
+      @required this.length,
+      @required this.message,
+      @required this.offset});
+}
diff --git a/pkg/analyzer/lib/src/diagnostic/diagnostic_factory.dart b/pkg/analyzer/lib/src/diagnostic/diagnostic_factory.dart
new file mode 100644
index 0000000..7b359dd
--- /dev/null
+++ b/pkg/analyzer/lib/src/diagnostic/diagnostic_factory.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/diagnostic/diagnostic.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/diagnostic/diagnostic.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+/// A factory used to create diagnostics.
+class DiagnosticFactory {
+  /// Initialize a newly created diagnostic factory.
+  DiagnosticFactory();
+
+  /// Return a diagnostic indicating that the given [identifier] was referenced
+  /// before it was declared.
+  AnalysisError referencedBeforeDeclaration(
+      Source source, Identifier identifier,
+      {Element element}) {
+    String name = identifier.name;
+    Element staticElement = element ?? identifier.staticElement;
+    List<DiagnosticMessage> contextMessages;
+    int declarationOffset = staticElement.nameOffset;
+    if (declarationOffset >= 0 && staticElement != null) {
+      CompilationUnitElement unit = staticElement
+          .getAncestor((element) => element is CompilationUnitElement);
+      CharacterLocation location = unit.lineInfo.getLocation(declarationOffset);
+      contextMessages = [
+        new DiagnosticMessageImpl(
+            filePath: source.fullName,
+            message:
+                "The declaration of '$name' is on line ${location.lineNumber}.",
+            offset: declarationOffset,
+            length: staticElement.nameLength)
+      ];
+    }
+    return new AnalysisError(
+        source,
+        identifier.offset,
+        identifier.length,
+        CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION,
+        [name],
+        contextMessages);
+  }
+}
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 5eda88c4..1b304fd 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -83,8 +83,9 @@
    * given [correction] template.
    */
   const CheckedModeCompileTimeErrorCode(String name, String message,
-      {String correction})
-      : super.temporary(name, message, correction: correction);
+      {String correction, bool hasPublishedDocs})
+      : super.temporary(name, message,
+            correction: correction, hasPublishedDocs: hasPublishedDocs);
 
   @override
   ErrorSeverity get errorSeverity =>
@@ -141,22 +142,142 @@
           correction: "Try removing the export of one of the libraries, or "
               "explicitly hiding the name in one of the export directives.");
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // Because map and set literals use the same delimiters (`{` and `}`), the
+  // analyzer looks at the type arguments and the elements to determine which
+  // kind of literal you meant. When there are no type arguments and all of the
+  // elements are spread elements (which are allowed in both kinds of literals),
+  // then the analyzer uses the types of the expressions that are being spread.
+  // If all of the expressions have the type `Iterable`, then it's a set
+  // literal; if they all have the type `Map`, then it's a map literal.
+  //
+  // The analyzer produces this diagnostic when some of the expressions being
+  // spread have the type `Iterable` and others have the type `Map`, making it
+  // impossible for the analyzer to determine whether you are writing a map
+  // literal or a set literal.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // union(Map<String, String> a, List<String> b, Map<String, String> c) =>
+  //     {...a, ...b, ...c};
+  // ```
+  //
+  // The list `b` can only be spread into a set, and the maps `a` and `c` can
+  // only be spread into a map, and the literal can't be both.
+  //
+  // #### Common fixes
+  //
+  // There are two common ways to fix this problem. The first is to remove all
+  // of the spread elements of one kind or the other, so that the elements are
+  // consistent. In this case, that likely means removing the list (and
+  // deciding what to do about the now unused parameter):
+  //
+  // ```dart
+  // union(Map<String, String> a, List<String> b, Map<String, String> c) =>
+  //     {...a, ...c};
+  // ```
+  //
+  // The second fix is to change the elements of one kind into elements that are
+  // consistent with the other elements. For example, you could add the elements
+  // of the list as keys that map to themselves:
+  //
+  // ```dart
+  // union(Map<String, String> a, List<String> b, Map<String, String> c) =>
+  //     {...a, for (String s in b) s: s, ...c};
+  // ```
   static const CompileTimeErrorCode AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH =
       const CompileTimeErrorCode(
           'AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH',
-          "This literal must be both a map and a set, because some elements "
-              "spread a 'Map' and others spread an 'Iterable', but that isn't "
-              "allowed.",
+          "This literal contains both 'Map' and 'Iterable' spreads, "
+              "which makes it impossible to determine whether the literal is "
+              "a map or a set.",
           correction:
               "Try removing or changing some of the elements so that all of "
               "the elements are consistent.");
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // Because map and set literals use the same delimiters (`‘{` and `}`), the
+  // analyzer looks at the type arguments and the elements to determine which
+  // kind of literal you meant. When there are no type arguments and all of the
+  // elements are spread elements (which are allowed in both kinds of literals)
+  // then the analyzer uses the types of the expressions that are being spread
+  // to decide. If all of the expressions have the type `Iterable`, then it's a
+  // set literal, if they all have the type `Map`, then it's a map literal.
+  //
+  // This diagnostic is produced when none of the expressions being spread has a
+  // type that allows the analyzer to decide whether you were writing a map
+  // literal or a set literal.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // union(a, b) => !{...a, ...b}!;
+  // ```
+  //
+  // The problem occurs because there are no type arguments, and there is no
+  // information about the type of either `a` or `b`.
+  //
+  // #### Common fixes
+  //
+  // There are three common ways to fix this problem. The first is to add type
+  // arguments to the literal. For example, if the literal is intended to be a
+  // map literal, you might write something like this:
+  //
+  // ```dart
+  // union(a, b) => <String, String>{...a, ...b};
+  // ```
+  //
+  // The second fix is to add type information so that the expressions have
+  // either the type `Iterable` or the type `Map`. You could add an explicit
+  // cast or, in this case, add types to the declarations of the two parameters:
+  //
+  // ```dart
+  // union(List<int> a, List<int> b) => {...a, ...b};
+  // ```
+  //
+  // The third fix is to add context information. In this case, that means
+  // adding a return type to the function:
+  //
+  // ```dart
+  // Set<String> union(a, b) => {...a, ...b};
+  // ```
+  //
+  // In other cases, you might add a type somewhere else. For example, say the
+  // original code looks like this:
+  //
+  // ```dart
+  // union(a, b) {
+  //   var x = {...a, ...b};
+  //   return x;
+  // }
+  // ```
+  //
+  // You might add a type annotation on `x`, like this:
+  //
+  // ```dart
+  // union(a, b) {
+  //   Map<String, String> x = {...a, ...b};
+  //   return x;
+  // }
+  // ```
   static const CompileTimeErrorCode AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER =
       const CompileTimeErrorCode(
           'AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER',
-          "This literal must be either a map or a set, but none of the "
-              "elements have enough type information to know which, and that isn't "
-              "allowed.",
+          "This literal must be either a map or a set, but the elements don't "
+              "have enough type information for type inference to work.",
           correction:
               "Try adding type arguments to the literal (one for sets, two "
               "for maps).");
@@ -785,6 +906,17 @@
           correction: "Try removing the default value.");
 
   /**
+   * It is an error to call the default List constructor with a length argument
+   * and a type argument which is potentially non-nullable.
+   */
+  static const CompileTimeErrorCode DEFAULT_LIST_CONSTRUCTOR_MISMATCH =
+      const CompileTimeErrorCode(
+          'DEFAULT_LIST_CONSTRUCTOR_MISMATCH',
+          "A list whose values cannot be 'null' cannot be given an initial length "
+              "because the initial values would all be 'null'.",
+          correction: "Try removing the argument.");
+
+  /**
    * 6.2.1 Required Formals: By means of a function signature that names the
    * parameter and describes its type as a function type. It is a compile-time
    * error if any default values are specified in the signature of such a
@@ -808,6 +940,44 @@
           correction: "Try removing the default value.");
 
   /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a named parameter has both the
+  // `required` modifier and a default value. If the parameter is required, then
+  // a value for the parameter is always provided at the call sites, so the
+  // default value can never be used.
+  //
+  // #### Example
+  //
+  // The following code generates this diagnostic:
+  //
+  // ```dart
+  // void log({required String !message! = 'no message'}) {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the parameter is really required, then remove the default value:
+  //
+  // ```dart
+  // void log({required String message}) {}
+  // ```
+  //
+  // If the parameter isn't always required, then remove the `required`
+  // modifier:
+  //
+  // ```dart
+  // void log({String message = 'no message'}) {}
+  // ```
+  static const CompileTimeErrorCode DEFAULT_VALUE_ON_REQUIRED_PARAMETER =
+      const CompileTimeErrorCode('DEFAULT_VALUE_ON_REQUIRED_PARAMETER',
+          "Required named parameters can't have a default value.",
+          correction: "Try removing either the default value or the 'required' "
+              "modifier.");
+
+  /**
    * 3.1 Scoping: It is a compile-time error if there is more than one entity
    * with the same name declared in the same scope.
    */
@@ -911,9 +1081,33 @@
           "The exported library '{0}' can't have a part-of directive.",
           correction: "Try exporting the library that the part is a part of.");
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the analyzer finds an
+  // expression, rather than a map entry, in what appears to be a map literal.
+  //
+  // #### Example
+  //
+  // The following code generates this diagnostic:
+  //
+  // ```dart
+  // var map = <String, int>{'a': 0, 'b': 1, !'c'!};
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the expression is intended to compute either a key or a value in an
+  // entry, fix the issue by completing the code:
+  //
+  // ```dart
+  // var map = <String, int>{'a': 0, 'b': 1, 'c': 2};
+  // ```
   static const CompileTimeErrorCode EXPRESSION_IN_MAP =
       const CompileTimeErrorCode(
-          'EXPRESSION_IN_MAP', "Expressions cannot be used in a map literal.",
+          'EXPRESSION_IN_MAP', "Expressions can't be used in a map literal.",
           correction:
               "Try removing the expression or converting it to be a map entry.");
 
@@ -1493,6 +1687,20 @@
               "Try using a generic function type (returnType 'Function(' parameters ')').");
 
   /**
+   * It is an error if an optional parameter (named or otherwise) with no
+   * default value has a potentially non-nullable type. This is produced in
+   * cases where there is no valid default value.
+   */
+  static const CompileTimeErrorCode INVALID_OPTIONAL_PARAMETER_TYPE =
+      const CompileTimeErrorCode(
+          'INVALID_OPTIONAL_PARAMETER_TYPE',
+          "The parameter '{0}' cannot have a value of 'null' because of its "
+              "type, but no default value it valid, so it must be a required "
+              "parameter.",
+          correction: "Try making this nullable (by adding a '?') or "
+              "making this a required parameter.");
+
+  /**
    * If a class declaration has a member declaration, the signature of that
    * member declaration becomes the signature in the interface. It's a
    * compile-time error if that signature is not a valid override of all
@@ -1672,6 +1880,70 @@
           correction: "Check your Dart SDK installation for completeness.");
 
   /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an optional parameter doesn't
+  // have a default value, but has a
+  // <a href=”#potentially-non-nullable”>potentially non-nullable</a> type.
+  // Optional parameters that have no explicit default value have an implicit
+  // default value of `null`. If the type of the parameter doesn't allow the
+  // parameter to have a value of null, then the implicit default value is not
+  // valid.
+  //
+  // #### Example
+  //
+  // The following code generates this diagnostic:
+  //
+  // ```dart
+  // void log({String !message!}) {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the parameter can have the value `null`, then add a question mark after
+  // the type annotation:
+  //
+  // ```dart
+  // void log({String? message}) {}
+  // ```
+  //
+  // If the parameter can't be null, then either provide a default value:
+  //
+  // ```dart
+  // void log({String message = ''}) {}
+  // ```
+  //
+  // or add the `required` modifier to the parameter:
+  //
+  // ```dart
+  // void log({required String message}) {}
+  // ```
+  static const CompileTimeErrorCode MISSING_DEFAULT_VALUE_FOR_PARAMETER =
+      const CompileTimeErrorCode(
+          'MISSING_DEFAULT_VALUE_FOR_PARAMETER',
+          "The parameter '{0}' can't have a value of 'null' because of its "
+              "type, so it must either be a required parameter or have a "
+              "default value.",
+          correction:
+              "Try adding either a default value or the 'required' modifier.");
+
+  /**
+   * It is an error if a named parameter that is marked as being required is
+   * not bound to an argument at a call site.
+   *
+   * Parameters:
+   * 0: the name of the parameter
+   */
+  static const CompileTimeErrorCode MISSING_REQUIRED_ARGUMENT =
+      const CompileTimeErrorCode(
+          'MISSING_REQUIRED_ARGUMENT',
+          "The named parameter '{0}' is required so "
+              "there needs to be a corresponding argument.",
+          correction: "Try adding the required argument.");
+
+  /**
    * It's a compile-time error to apply a mixin containing super-invocations to
    * a class that doesn't have a concrete implementation of the super-invoked
    * members compatible with the super-constraint interface.
@@ -1695,15 +1967,18 @@
 
   /**
    * It's a compile-time error to apply a mixin to a class that doesn't
-   * implement all the on type requirements of the mixin declaration.
+   * implement all the `on` type requirements of the mixin declaration.
    *
    * Parameters:
-   * 0: the display name of the not implemented type
+   * 0: the display name of the mixin
+   * 1: the display name of the superclass
+   * 2: the display name of the type that is not implemented
    */
   static const CompileTimeErrorCode
       MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE = const CompileTimeErrorCode(
           'MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE',
-          "The class doesn't implement the required class '{0}'.",
+          "'{0}' cannot be mixed onto '{1}' "
+              "because '{1}' does not implement '{2}'.",
           correction: "Try extending the class '{0}'.");
 
   /**
@@ -2176,6 +2451,33 @@
           "{0} required argument(s) expected, but {1} found.",
           correction: "Try adding the missing arguments.");
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the static type of the
+  // expression of a spread element that appears in either a list literal or a
+  // set literal doesn't implement the type `Iterable`.
+  //
+  // #### Example
+  //
+  // The following code generates this diagnostic:
+  //
+  // ```dart
+  // var m = <String, int>{'a': 0, 'b': 1};
+  // var s = <String>{...m};
+  // ```
+  //
+  // #### Common fixes
+  //
+  // The most common fix is to replace the expression with one that produces an
+  // iterable object:
+  //
+  // ```dart
+  // var m = <String, int>{'a': 0, 'b': 1};
+  // var s = <String>{...m.keys};
+  // ```
   static const CompileTimeErrorCode NOT_ITERABLE_SPREAD =
       const CompileTimeErrorCode('NOT_ITERABLE_SPREAD',
           "Spread elements in list or set literals must implement 'Iterable'.");
@@ -2214,12 +2516,39 @@
           correction: "Try removing the question mark.");
 
   /**
-   * It is a compile-time error for a class to extend, implement, or mixin a
-   * type of the form T? for any T.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a class declaration uses an
+  // extends clause to specify a superclass, and the type that's specified is a
+  // nullable type.
+  //
+  // The reason the supertype is a _type_ rather than a class name is to allow
+  // you to control the signatures of the members to be inherited from the
+  // supertype, such as by specifying type arguments. However, the nullability
+  // of a type doesn't change the signatures of any members, so there isn't any
+  // reason to allow the nullability to be specified when used in the extends
+  // clause.
+  //
+  // #### Example
+  //
+  // The following code generates this diagnostic:
+  //
+  // ```dart
+  // class Invalid extends !Duration?! {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // The most common fix is to remove the question mark:
+  //
+  // ```dart
+  // class Invalid extends Duration {}
+  // ```
   static const CompileTimeErrorCode NULLABLE_TYPE_IN_EXTENDS_CLAUSE =
       const CompileTimeErrorCode('NULLABLE_TYPE_IN_EXTENDS_CLAUSE',
-          "A class cannot extend a nullable type.",
+          "A class can't extend a nullable type.",
           correction: "Try removing the question mark.");
 
   /**
@@ -2816,6 +3145,20 @@
           "Setters should declare exactly one required parameter.");
 
   /**
+   * Let `C` be a generic class that declares a formal type parameter `X`, and
+   * assume that `T` is a direct superinterface of `C`. It is a compile-time
+   * error if `X` occurs contravariantly or invariantly in `T`.
+   */
+  static const CompileTimeErrorCode
+      WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE =
+      const CompileTimeErrorCode(
+    'WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE',
+    "'{0}' can't be used contravariantly or invariantly in '{1}'.",
+    correction: "Try not using class type parameters in types of formal "
+        "parameters of function types.",
+  );
+
+  /**
    * ?? Yield: It is a compile-time error if a yield statement appears in a
    * function that is not a generator function.
    */
@@ -2846,9 +3189,12 @@
    * given [correction] template.
    */
   const CompileTimeErrorCode(String name, String message,
-      {String correction, bool isUnresolvedIdentifier: false})
+      {String correction,
+      bool hasPublishedDocs,
+      bool isUnresolvedIdentifier: false})
       : super.temporary(name, message,
             correction: correction,
+            hasPublishedDocs: hasPublishedDocs,
             isUnresolvedIdentifier: isUnresolvedIdentifier);
 
   @override
@@ -3478,9 +3824,12 @@
    * given [correction] template.
    */
   const StaticTypeWarningCode(String name, String message,
-      {String correction, bool isUnresolvedIdentifier: false})
+      {String correction,
+      bool hasPublishedDocs,
+      bool isUnresolvedIdentifier: false})
       : super.temporary(name, message,
             correction: correction,
+            hasPublishedDocs: hasPublishedDocs,
             isUnresolvedIdentifier: isUnresolvedIdentifier);
 
   @override
@@ -4554,10 +4903,12 @@
    */
   const StaticWarningCode(String name, String message,
       {String correction,
-      this.errorSeverity: ErrorSeverity.ERROR,
+      this.errorSeverity = ErrorSeverity.ERROR,
+      bool hasPublishedDocs,
       bool isUnresolvedIdentifier: false})
       : super.temporary(name, message,
             correction: correction,
+            hasPublishedDocs: hasPublishedDocs,
             isUnresolvedIdentifier: isUnresolvedIdentifier);
 
   @override
@@ -4826,9 +5177,10 @@
    * created from the optional [correction] template.
    */
   const StrongModeCode(ErrorType type, String name, String message,
-      {String correction})
+      {String correction, bool hasPublishedDocs})
       : type = type,
-        super.temporary('STRONG_MODE_$name', message, correction: correction);
+        super.temporary('STRONG_MODE_$name', message,
+            correction: correction, hasPublishedDocs: hasPublishedDocs);
 
   @override
   ErrorSeverity get errorSeverity => type.severity;
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index d120057..4edfcba 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -37,6 +38,7 @@
           typeProvider: _typeProvider,
           inheritance: _inheritance,
           reporter: _reporter,
+          featureSet: unit.featureSet,
           library: library,
           classNameNode: declaration.name,
           implementsClause: declaration.implementsClause,
@@ -50,6 +52,7 @@
           typeProvider: _typeProvider,
           inheritance: _inheritance,
           reporter: _reporter,
+          featureSet: unit.featureSet,
           library: library,
           classNameNode: declaration.name,
           implementsClause: declaration.implementsClause,
@@ -62,6 +65,7 @@
           typeProvider: _typeProvider,
           inheritance: _inheritance,
           reporter: _reporter,
+          featureSet: unit.featureSet,
           library: library,
           classNameNode: declaration.name,
           implementsClause: declaration.implementsClause,
@@ -85,6 +89,7 @@
   final InheritanceManager2 inheritance;
   final ErrorReporter reporter;
 
+  final FeatureSet featureSet;
   final LibraryElement library;
   final Uri libraryUri;
   final ClassElementImpl classElement;
@@ -108,6 +113,7 @@
     this.typeProvider,
     this.inheritance,
     this.reporter,
+    this.featureSet,
     this.library,
     this.classNameNode,
     this.implementsClause,
@@ -382,7 +388,8 @@
         if (setter != null && setter.parameters.length == 1) {
           var getterType = getter.returnType;
           var setterType = setter.parameters[0].type;
-          if (!typeSystem.isAssignableTo(getterType, setterType)) {
+          if (!typeSystem.isAssignableTo(getterType, setterType,
+              featureSet: featureSet)) {
             var getterElement = getter.element;
             var setterElement = setter.element;
 
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
index 89dcdce..ba32987 100644
--- a/pkg/analyzer/lib/src/error/literal_element_verifier.dart
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -15,6 +16,7 @@
   final TypeProvider typeProvider;
   final TypeSystem typeSystem;
   final ErrorReporter errorReporter;
+  final FeatureSet featureSet;
   final bool Function(Expression) checkForUseOfVoidResult;
 
   final bool forList;
@@ -36,6 +38,7 @@
     this.forMap = false,
     this.mapKeyType,
     this.mapValueType,
+    this.featureSet,
   });
 
   void verify(CollectionElement element) {
@@ -45,7 +48,7 @@
   /// Check that the given [type] is assignable to the [elementType], otherwise
   /// report the list or set error on the [errorNode].
   void _checkAssignableToElementType(DartType type, AstNode errorNode) {
-    if (!typeSystem.isAssignableTo(type, elementType)) {
+    if (!typeSystem.isAssignableTo(type, elementType, featureSet: featureSet)) {
       var errorCode = forList
           ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
           : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
@@ -106,7 +109,8 @@
     }
 
     var keyType = entry.key.staticType;
-    if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+    if (!typeSystem.isAssignableTo(keyType, mapKeyType,
+        featureSet: featureSet)) {
       errorReporter.reportTypeErrorForNode(
         StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
         entry.key,
@@ -115,7 +119,8 @@
     }
 
     var valueType = entry.value.staticType;
-    if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+    if (!typeSystem.isAssignableTo(valueType, mapValueType,
+        featureSet: featureSet)) {
       errorReporter.reportTypeErrorForNode(
         StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
         entry.value,
@@ -157,7 +162,8 @@
     }
 
     var iterableElementType = iterableType.typeArguments[0];
-    if (!typeSystem.isAssignableTo(iterableElementType, elementType)) {
+    if (!typeSystem.isAssignableTo(iterableElementType, elementType,
+        featureSet: featureSet)) {
       var errorCode = forList
           ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
           : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
@@ -200,7 +206,8 @@
     }
 
     var keyType = mapType.typeArguments[0];
-    if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+    if (!typeSystem.isAssignableTo(keyType, mapKeyType,
+        featureSet: featureSet)) {
       errorReporter.reportTypeErrorForNode(
         StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
         expression,
@@ -209,7 +216,8 @@
     }
 
     var valueType = mapType.typeArguments[1];
-    if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+    if (!typeSystem.isAssignableTo(valueType, mapValueType,
+        featureSet: featureSet)) {
       errorReporter.reportTypeErrorForNode(
         StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
         expression,
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 22634cd..73b6a7c 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/ast_factory.dart' show AstFactory;
 import 'package:analyzer/dart/ast/standard_ast_factory.dart' as standard;
@@ -11,8 +12,8 @@
 import 'package:analyzer/src/dart/ast/ast.dart'
     show
         ClassDeclarationImpl,
-        ClassOrMixinDeclarationImpl,
         CompilationUnitImpl,
+        ExtensionDeclarationImpl,
         MixinDeclarationImpl;
 import 'package:analyzer/src/fasta/error_converter.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -56,9 +57,8 @@
     show NullValue, StackListener;
 import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
 import 'package:front_end/src/scanner/token.dart'
-    show CommentToken, SyntheticStringToken, SyntheticToken;
+    show SyntheticStringToken, SyntheticToken;
 import 'package:kernel/ast.dart' show AsyncMarker;
-import 'package:pub_semver/pub_semver.dart';
 
 const _invalidCollectionElement = const _InvalidCollectionElement._();
 
@@ -69,7 +69,6 @@
   final FastaErrorReporter errorReporter;
   final Uri fileUri;
   ScriptTag scriptTag;
-  Version languageVersion;
   final List<Directive> directives = <Directive>[];
   final List<CompilationUnitMember> declarations = <CompilationUnitMember>[];
   final localDeclarations = <int, AstNode>{};
@@ -87,6 +86,9 @@
   /// The mixin currently being parsed, or `null` if no mixin is being parsed.
   MixinDeclarationImpl mixinDeclaration;
 
+  /// The extension currently being parsed, or `null` if none.
+  ExtensionDeclarationImpl extensionDeclaration;
+
   /// If true, this is building a full AST. Otherwise, only create method
   /// bodies.
   final bool isFullAst;
@@ -106,7 +108,10 @@
 
   bool parseFunctionBodies = true;
 
-  /// `true` if non-nullable behavior is enabled
+  /// `true` if non-nullable behavior is enabled.
+  ///
+  /// When setting this field, be sure to set `scanner.enableNonNullable`
+  /// to the same value.
   bool enableNonNullable = false;
 
   /// `true` if spread-collections behavior is enabled
@@ -118,11 +123,33 @@
   /// `true` if triple-shift behavior is enabled
   bool enableTripleShift = false;
 
+  FeatureSet _featureSet;
+
   AstBuilder(ErrorReporter errorReporter, this.fileUri, this.isFullAst,
       [Uri uri])
       : this.errorReporter = new FastaErrorReporter(errorReporter),
         uri = uri ?? fileUri;
 
+  NodeList<ClassMember> get currentDeclarationMembers {
+    if (classDeclaration != null) {
+      return classDeclaration.members;
+    } else if (mixinDeclaration != null) {
+      return mixinDeclaration.members;
+    } else {
+      return extensionDeclaration.members;
+    }
+  }
+
+  SimpleIdentifier get currentDeclarationName {
+    if (classDeclaration != null) {
+      return classDeclaration.name;
+    } else if (mixinDeclaration != null) {
+      return mixinDeclaration.name;
+    } else {
+      return extensionDeclaration.name;
+    }
+  }
+
   @override
   void addProblem(Message message, int charOffset, int length,
       {bool wasHandled: false, List<LocatedMessage> context}) {
@@ -151,7 +178,9 @@
 
   @override
   void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
-    assert(classDeclaration == null && mixinDeclaration == null);
+    assert(classDeclaration == null &&
+        mixinDeclaration == null &&
+        extensionDeclaration == null);
     push(new _Modifiers()..abstractKeyword = abstractToken);
   }
 
@@ -161,6 +190,30 @@
   }
 
   @override
+  void beginExtensionDeclaration(Token extensionKeyword, Token nameToken) {
+    assert(optional('extension', extensionKeyword));
+    assert(classDeclaration == null &&
+        mixinDeclaration == null &&
+        extensionDeclaration == null);
+    debugEvent("ExtensionHeader");
+
+    TypeParameterList typeParameters = pop();
+    SimpleIdentifier name = pop();
+    List<Annotation> metadata = pop();
+    Comment comment = _findComment(metadata, extensionKeyword);
+
+    extensionDeclaration = ast.extensionDeclaration(
+      comment: comment,
+      metadata: metadata,
+      name: name,
+      typeParameters: typeParameters,
+      extendedType: null, // extendedType is set in [endExtensionDeclaration]
+    ) as ExtensionDeclarationImpl;
+
+    declarations.add(extensionDeclaration);
+  }
+
+  @override
   void beginFactoryMethod(
       Token lastConsumed, Token externalToken, Token constToken) {
     push(new _Modifiers()
@@ -169,11 +222,12 @@
   }
 
   @override
-  void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
-      Token varFinalOrConst) {
+  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+      Token covariantToken, Token varFinalOrConst) {
     push(new _Modifiers()
       ..covariantKeyword = covariantToken
-      ..finalConstOrVarKeyword = varFinalOrConst);
+      ..finalConstOrVarKeyword = varFinalOrConst
+      ..requiredToken = requiredToken);
   }
 
   @override
@@ -229,7 +283,9 @@
 
   @override
   void beginMixinDeclaration(Token mixinKeyword, Token name) {
-    assert(classDeclaration == null && mixinDeclaration == null);
+    assert(classDeclaration == null &&
+        mixinDeclaration == null &&
+        extensionDeclaration == null);
   }
 
   @override
@@ -255,10 +311,13 @@
   }
 
   @override
-  void beginVariablesDeclaration(Token token, Token varFinalOrConst) {
+  void beginVariablesDeclaration(
+      Token token, Token lateToken, Token varFinalOrConst) {
     debugEvent("beginVariablesDeclaration");
-    if (varFinalOrConst != null) {
-      push(new _Modifiers()..finalConstOrVarKeyword = varFinalOrConst);
+    if (varFinalOrConst != null || lateToken != null) {
+      push(new _Modifiers()
+        ..finalConstOrVarKeyword = varFinalOrConst
+        ..lateToken = lateToken);
     } else {
       push(NullValue.Modifiers);
     }
@@ -276,6 +335,21 @@
     }
   }
 
+  /// Configures the parser appropriately for the given [featureSet].
+  ///
+  /// TODO(paulberry): stop exposing `enableNonNullable`,
+  /// `enableSpreadCollections`, `enableControlFlowCollections`, and
+  /// `enableTripleShift` so that callers are forced to use this API.  Note that
+  /// this will not be a breaking change, because this code is in `lib/src`.
+  void configureFeatures(FeatureSet featureSet) {
+    enableNonNullable = featureSet.isEnabled(Feature.non_nullable);
+    enableSpreadCollections = featureSet.isEnabled(Feature.spread_collections);
+    enableControlFlowCollections =
+        featureSet.isEnabled(Feature.control_flow_collections);
+    enableTripleShift = featureSet.isEnabled(Feature.triple_shift);
+    _featureSet = featureSet;
+  }
+
   @override
   void debugEvent(String name) {
     // printEvent('AstBuilder: $name');
@@ -458,14 +532,25 @@
   @override
   void endClassOrMixinBody(
       int memberCount, Token leftBracket, Token rightBracket) {
+    // TODO(danrubel): consider renaming endClassOrMixinBody
+    // to endClassOrMixinOrExtensionBody
     assert(optional('{', leftBracket));
     assert(optional('}', rightBracket));
     debugEvent("ClassOrMixinBody");
 
-    ClassOrMixinDeclarationImpl declaration =
-        classDeclaration ?? mixinDeclaration;
-    declaration.leftBracket = leftBracket;
-    declaration.rightBracket = rightBracket;
+    if (classDeclaration != null) {
+      classDeclaration
+        ..leftBracket = leftBracket
+        ..rightBracket = rightBracket;
+    } else if (mixinDeclaration != null) {
+      mixinDeclaration
+        ..leftBracket = leftBracket
+        ..rightBracket = rightBracket;
+    } else {
+      extensionDeclaration
+        ..leftBracket = leftBracket
+        ..rightBracket = rightBracket;
+    }
   }
 
   @override
@@ -481,11 +566,13 @@
     Token beginToken = pop();
     checkEmpty(endToken.charOffset);
 
-    CompilationUnitImpl unit = ast.compilationUnit(
-            beginToken, scriptTag, directives, declarations, endToken)
-        as CompilationUnitImpl;
-    unit.languageVersion = languageVersion;
-    unit.isNonNullable = enableNonNullable;
+    CompilationUnitImpl unit = ast.compilationUnit2(
+        beginToken: beginToken,
+        scriptTag: scriptTag,
+        directives: directives,
+        declarations: declarations,
+        endToken: endToken,
+        featureSet: _featureSet) as CompilationUnitImpl;
     push(unit);
   }
 
@@ -618,6 +705,15 @@
   }
 
   @override
+  void endExtensionDeclaration(Token onKeyword, Token token) {
+    TypeAnnotation type = pop();
+    extensionDeclaration
+      ..extendedType = type
+      ..onKeyword = onKeyword;
+    extensionDeclaration = null;
+  }
+
+  @override
   void endFactoryMethod(
       Token beginToken, Token factoryKeyword, Token endToken) {
     assert(optional('factory', factoryKeyword));
@@ -669,21 +765,20 @@
           ast.simpleIdentifier(typeName.identifier.token, isDeclaration: true);
     }
 
-    (classDeclaration ?? mixinDeclaration).members.add(
-        ast.constructorDeclaration(
-            comment,
-            metadata,
-            modifiers?.externalKeyword,
-            modifiers?.finalConstOrVarKeyword,
-            factoryKeyword,
-            ast.simpleIdentifier(returnType.token),
-            period,
-            name,
-            parameters,
-            separator,
-            null,
-            redirectedConstructor,
-            body));
+    currentDeclarationMembers.add(ast.constructorDeclaration(
+        comment,
+        metadata,
+        modifiers?.externalKeyword,
+        modifiers?.finalConstOrVarKeyword,
+        factoryKeyword,
+        ast.simpleIdentifier(returnType.token),
+        period,
+        name,
+        parameters,
+        separator,
+        null,
+        redirectedConstructor,
+        body));
   }
 
   void endFieldInitializer(Token assignment, Token token) {
@@ -696,27 +791,27 @@
   }
 
   @override
-  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
-      int count, Token beginToken, Token semicolon) {
+  void endFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token semicolon) {
     assert(optional(';', semicolon));
     debugEvent("Fields");
 
     List<VariableDeclaration> variables = popTypedList(count);
     TypeAnnotation type = pop();
-    _Modifiers modifiers = new _Modifiers()
-      ..staticKeyword = staticToken
-      ..covariantKeyword = covariantToken
-      ..finalConstOrVarKeyword = varFinalOrConst;
-    var variableList = ast.variableDeclarationList(
-        null, null, modifiers?.finalConstOrVarKeyword, type, variables);
-    Token covariantKeyword = modifiers?.covariantKeyword;
+    var variableList = ast.variableDeclarationList2(
+      lateKeyword: lateToken,
+      keyword: varFinalOrConst,
+      type: type,
+      variables: variables,
+    );
+    Token covariantKeyword = covariantToken;
     List<Annotation> metadata = pop();
     Comment comment = _findComment(metadata, beginToken);
-    (classDeclaration ?? mixinDeclaration).members.add(ast.fieldDeclaration2(
+    currentDeclarationMembers.add(ast.fieldDeclaration2(
         comment: comment,
         metadata: metadata,
         covariantKeyword: covariantKeyword,
-        staticKeyword: modifiers?.staticKeyword,
+        staticKeyword: staticToken,
         fieldList: variableList,
         semicolon: semicolon));
   }
@@ -791,6 +886,10 @@
     _Modifiers modifiers = pop();
     Token keyword = modifiers?.finalConstOrVarKeyword;
     Token covariantKeyword = modifiers?.covariantKeyword;
+    Token requiredKeyword = modifiers?.requiredToken;
+    if (!enableNonNullable) {
+      reportNonNullableModifierError(requiredKeyword);
+    }
     List<Annotation> metadata = pop();
     Comment comment = _findComment(metadata,
         thisKeyword ?? typeOrFunctionTypedParameter?.beginToken ?? nameToken);
@@ -806,15 +905,18 @@
             comment: comment,
             metadata: metadata,
             covariantKeyword: covariantKeyword,
+            requiredKeyword: requiredKeyword,
             returnType: typeOrFunctionTypedParameter.returnType,
             typeParameters: typeOrFunctionTypedParameter.typeParameters,
-            parameters: typeOrFunctionTypedParameter.parameters);
+            parameters: typeOrFunctionTypedParameter.parameters,
+            question: typeOrFunctionTypedParameter.question);
       } else {
         node = ast.fieldFormalParameter2(
             identifier: name,
             comment: comment,
             metadata: metadata,
             covariantKeyword: covariantKeyword,
+            requiredKeyword: requiredKeyword,
             type: typeOrFunctionTypedParameter.returnType,
             thisKeyword: thisKeyword,
             period: periodAfterThis,
@@ -828,6 +930,7 @@
             comment: comment,
             metadata: metadata,
             covariantKeyword: covariantKeyword,
+            requiredKeyword: requiredKeyword,
             keyword: keyword,
             type: type,
             identifier: name);
@@ -836,6 +939,7 @@
             comment: comment,
             metadata: metadata,
             covariantKeyword: covariantKeyword,
+            requiredKeyword: requiredKeyword,
             keyword: keyword,
             type: type,
             thisKeyword: thisKeyword,
@@ -844,7 +948,8 @@
       }
     }
 
-    ParameterKind analyzerKind = _toAnalyzerParameterKind(kind);
+    ParameterKind analyzerKind =
+        _toAnalyzerParameterKind(kind, requiredKeyword);
     FormalParameter parameter = node;
     if (analyzerKind != ParameterKind.REQUIRED) {
       parameter = ast.defaultFormalParameter(
@@ -985,7 +1090,7 @@
   }
 
   @override
-  void endFunctionTypedFormalParameter(Token nameToken) {
+  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
     debugEvent("FunctionTypedFormalParameter");
 
     FormalParameterList formalParameters = pop();
@@ -998,7 +1103,8 @@
         identifier: null,
         returnType: returnType,
         typeParameters: typeParameters,
-        parameters: formalParameters));
+        parameters: formalParameters,
+        question: question));
   }
 
   @override
@@ -1381,9 +1487,6 @@
           beginToken.charOffset, uri);
     }
 
-    ClassOrMixinDeclarationImpl declaration =
-        classDeclaration ?? mixinDeclaration;
-
     void constructor(
         SimpleIdentifier prefixOrName, Token period, SimpleIdentifier name) {
       if (typeParameters != null) {
@@ -1419,22 +1522,20 @@
           initializers,
           redirectedConstructor,
           body);
-      declaration.members.add(constructor);
+      currentDeclarationMembers.add(constructor);
       if (mixinDeclaration != null) {
         // TODO (danrubel): Report an error if this is a mixin declaration.
       }
     }
 
     void method(Token operatorKeyword, SimpleIdentifier name) {
-      if (modifiers?.constKeyword != null &&
-          body != null &&
-          (body.length > 1 || body.beginToken?.lexeme != ';')) {
+      if (modifiers?.constKeyword != null) {
         // This error is also reported in OutlineBuilder.endMethod
         handleRecoverableError(
             messageConstMethod, modifiers.constKeyword, modifiers.constKeyword);
       }
       checkFieldFormalParameters(parameters);
-      declaration.members.add(ast.methodDeclaration(
+      currentDeclarationMembers.add(ast.methodDeclaration(
           comment,
           metadata,
           modifiers?.externalKeyword,
@@ -1449,9 +1550,9 @@
     }
 
     if (name is SimpleIdentifier) {
-      if (name.name == declaration.name.name && getOrSet == null) {
+      if (name.name == currentDeclarationName.name && getOrSet == null) {
         constructor(name, null, null);
-      } else if (initializers.isNotEmpty) {
+      } else if (initializers.isNotEmpty && getOrSet == null) {
         constructor(name, null, null);
       } else {
         method(null, name);
@@ -1725,20 +1826,25 @@
     debugEvent("TopLevelDeclaration");
   }
 
-  void endTopLevelFields(Token staticToken, Token covariantToken,
-      Token varFinalOrConst, int count, Token beginToken, Token semicolon) {
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token semicolon) {
     assert(optional(';', semicolon));
     debugEvent("TopLevelFields");
 
     List<VariableDeclaration> variables = popTypedList(count);
     TypeAnnotation type = pop();
-    _Modifiers modifiers = new _Modifiers()
-      ..staticKeyword = staticToken
-      ..covariantKeyword = covariantToken
-      ..finalConstOrVarKeyword = varFinalOrConst;
-    Token keyword = modifiers?.finalConstOrVarKeyword;
-    var variableList =
-        ast.variableDeclarationList(null, null, keyword, type, variables);
+    var variableList = ast.variableDeclarationList2(
+      lateKeyword: lateToken,
+      keyword: varFinalOrConst,
+      type: type,
+      variables: variables,
+    );
     List<Annotation> metadata = pop();
     Comment comment = _findComment(metadata, beginToken);
     declarations.add(ast.topLevelVariableDeclaration(
@@ -1848,8 +1954,14 @@
     Comment comment = _findComment(metadata,
         variables[0].beginToken ?? type?.beginToken ?? modifiers.beginToken);
     push(ast.variableDeclarationStatement(
-        ast.variableDeclarationList(
-            comment, metadata, keyword, type, variables),
+        ast.variableDeclarationList2(
+          comment: comment,
+          metadata: metadata,
+          lateKeyword: modifiers?.lateToken,
+          keyword: keyword,
+          type: type,
+          variables: variables,
+        ),
         semicolon));
   }
 
@@ -1898,8 +2010,7 @@
     }
   }
 
-  void finishFunction(
-      List annotations, formals, AsyncMarker asyncModifier, FunctionBody body) {
+  void finishFunction(formals, AsyncMarker asyncModifier, FunctionBody body) {
     debugEvent("finishFunction");
 
     Statement bodyStatement;
@@ -2248,10 +2359,7 @@
       if (variableOrDeclaration is! SimpleIdentifier) {
         // Parser has already reported the error.
         if (!leftParenthesis.next.isIdentifier) {
-          parser.rewriter.insertToken(
-              leftParenthesis,
-              new SyntheticStringToken(
-                  TokenType.IDENTIFIER, '', leftParenthesis.next.charOffset));
+          parser.rewriter.insertSyntheticIdentifier(leftParenthesis);
         }
         variableOrDeclaration = ast.simpleIdentifier(leftParenthesis.next);
       }
@@ -2473,16 +2581,6 @@
     push(ast.label(name, colon));
   }
 
-  @override
-  void handleLanguageVersion(Token commentToken, int major, int minor) {
-    debugEvent('LanguageVersion');
-    assert(commentToken is CommentToken);
-    assert(major != null);
-    assert(minor != null);
-
-    languageVersion = Version(major, minor, 0);
-  }
-
   void handleLiteralBool(Token token) {
     bool value = identical(token.stringValue, "true");
     assert(value || identical(token.stringValue, "false"));
@@ -2653,7 +2751,9 @@
   @override
   void handleMixinHeader(Token mixinKeyword) {
     assert(optional('mixin', mixinKeyword));
-    assert(classDeclaration == null && mixinDeclaration == null);
+    assert(classDeclaration == null &&
+        mixinDeclaration == null &&
+        extensionDeclaration == null);
     debugEvent("MixinHeader");
 
     ImplementsClause implementsClause = pop(NullValue.IdentifierList);
@@ -3253,10 +3353,14 @@
     return variableDeclaration;
   }
 
-  ParameterKind _toAnalyzerParameterKind(FormalParameterKind type) {
+  ParameterKind _toAnalyzerParameterKind(
+      FormalParameterKind type, Token requiredKeyword) {
     if (type == FormalParameterKind.optionalPositional) {
       return ParameterKind.POSITIONAL;
     } else if (type == FormalParameterKind.optionalNamed) {
+      if (requiredKeyword != null) {
+        return ParameterKind.NAMED_REQUIRED;
+      }
       return ParameterKind.NAMED;
     } else {
       return ParameterKind.REQUIRED;
@@ -3291,34 +3395,8 @@
   Token finalConstOrVarKeyword;
   Token staticKeyword;
   Token covariantKeyword;
-
-  _Modifiers([List<Token> modifierTokens]) {
-    // No need to check the order and uniqueness of the modifiers, or that
-    // disallowed modifiers are not used; the parser should do that.
-    // TODO(paulberry,ahe): implement the necessary logic in the parser.
-    if (modifierTokens != null) {
-      for (var token in modifierTokens) {
-        var s = token.lexeme;
-        if (identical('abstract', s)) {
-          abstractKeyword = token;
-        } else if (identical('const', s)) {
-          finalConstOrVarKeyword = token;
-        } else if (identical('external', s)) {
-          externalKeyword = token;
-        } else if (identical('final', s)) {
-          finalConstOrVarKeyword = token;
-        } else if (identical('static', s)) {
-          staticKeyword = token;
-        } else if (identical('var', s)) {
-          finalConstOrVarKeyword = token;
-        } else if (identical('covariant', s)) {
-          covariantKeyword = token;
-        } else {
-          unhandled("$s", "modifier", token.charOffset, null);
-        }
-      }
-    }
-  }
+  Token requiredToken;
+  Token lateToken;
 
   /// Return the token that is lexically first.
   Token get beginToken {
@@ -3328,7 +3406,9 @@
       externalKeyword,
       finalConstOrVarKeyword,
       staticKeyword,
-      covariantKeyword
+      covariantKeyword,
+      requiredToken,
+      lateToken,
     ]) {
       if (firstToken == null) {
         firstToken = token;
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index 16f6f09..132cb54 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -205,10 +205,6 @@
         errorReporter?.reportErrorForOffset(
             StrongModeCode.INVALID_SUPER_INVOCATION, offset, length);
         return;
-      case "MISSING_CLASS_BODY":
-        errorReporter?.reportErrorForOffset(
-            ParserErrorCode.MISSING_CLASS_BODY, offset, length);
-        return;
       case "MISSING_DIGIT":
         errorReporter?.reportErrorForOffset(
             ScannerErrorCode.MISSING_DIGIT, offset, length);
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index 7175395..d8abec8 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -27,9 +28,6 @@
   /// The compilation unit containing the AST nodes being visited.
   CompilationUnitElementImpl _enclosingUnit;
 
-  /// The type provider used to access the known types.
-  TypeProvider _typeProvider;
-
   /// The [ElementWalker] we are using to keep track of progress through the
   /// element model.
   ElementWalker _walker;
@@ -42,7 +40,6 @@
   /// not match each other.
   void resolve(CompilationUnit unit, CompilationUnitElement element) {
     _enclosingUnit = element;
-    _typeProvider = _enclosingUnit.context?.typeProvider;
     _walker = new ElementWalker.forCompilationUnit(element);
     unit.element = element;
     try {
@@ -137,10 +134,7 @@
       });
     }
 
-    bool isFunctionTyped = normalParameter is FunctionTypedFormalParameter ||
-        normalParameter is FieldFormalParameter &&
-            normalParameter.parameters != null;
-    _walk(new ElementWalker.forParameter(element, isFunctionTyped), () {
+    _walk(new ElementWalker.forParameter(element), () {
       normalParameter.accept(this);
     });
 
@@ -150,7 +144,6 @@
   @override
   void visitEnumDeclaration(EnumDeclaration node) {
     ClassElement element = _match(node.name, _walker.getEnum());
-    node.name.staticType = _typeProvider.typeType;
     resolveMetadata(node, node.metadata, element);
     _walk(new ElementWalker.forClass(element), () {
       for (EnumConstantDeclaration constant in node.constants) {
@@ -202,8 +195,7 @@
     if (node.parent is! DefaultFormalParameter) {
       ParameterElement element =
           _match(node.identifier, _walker.getParameter());
-      bool isFunctionTyped = node.parameters != null;
-      _walk(new ElementWalker.forParameter(element, isFunctionTyped), () {
+      _walk(new ElementWalker.forParameter(element), () {
         super.visitFieldFormalParameter(node);
       });
       resolveMetadata(node, node.metadata, element);
@@ -234,6 +226,9 @@
     _setGenericFunctionType(node.returnType, element.returnType);
     (node.functionExpression as FunctionExpressionImpl).declaredElement =
         element;
+    if (AnalysisDriver.useSummary2 && _enclosingUnit.linkedContext != null) {
+      node.returnType?.accept(this);
+    }
     _walker._elementHolder?.addFunction(element);
     _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
       super.visitFunctionDeclaration(node);
@@ -264,7 +259,7 @@
     if (node.parent is! DefaultFormalParameter) {
       ParameterElement element =
           _match(node.identifier, _walker.getParameter());
-      _walk(new ElementWalker.forParameter(element, true), () {
+      _walk(new ElementWalker.forParameter(element), () {
         super.visitFunctionTypedFormalParameter(node);
       });
       resolveMetadata(node, node.metadata, element);
@@ -275,18 +270,25 @@
 
   @override
   void visitGenericFunctionType(GenericFunctionType node) {
+    if (AnalysisDriver.useSummary2 && _enclosingUnit.linkedContext != null) {
+      var builder = new LocalElementBuilder(ElementHolder(), _enclosingUnit);
+      node.accept(builder);
+
+      var nodeImpl = node as GenericFunctionTypeImpl;
+      _enclosingUnit.encloseElement(
+        nodeImpl.declaredElement as GenericFunctionTypeElementImpl,
+      );
+      return;
+    }
     if (_walker.elementBuilder != null) {
       _walker.elementBuilder.visitGenericFunctionType(node);
     } else {
-      DartType type = node.type;
-      if (type != null) {
-        Element element = type.element;
-        if (element is GenericFunctionTypeElement) {
-          _setGenericFunctionType(node.returnType, element.returnType);
-          _walk(new ElementWalker.forGenericFunctionType(element), () {
-            super.visitGenericFunctionType(node);
-          });
-        }
+      var element = node.type?.element;
+      if (element is GenericFunctionTypeElement) {
+        _setGenericFunctionType(node.returnType, element.returnType);
+        _walk(new ElementWalker.forGenericFunctionType(element), () {
+          super.visitGenericFunctionType(node);
+        });
       }
     }
   }
@@ -361,6 +363,9 @@
       }
     }
     _setGenericFunctionType(node.returnType, element.returnType);
+    if (AnalysisDriver.useSummary2 && _enclosingUnit.linkedContext != null) {
+      node.returnType?.accept(this);
+    }
     _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
       super.visitMethodDeclaration(node);
     });
@@ -405,7 +410,7 @@
           _match(node.identifier, _walker.getParameter());
       (node as SimpleFormalParameterImpl).declaredElement = element;
       _setGenericFunctionType(node.type, element.type);
-      _walk(new ElementWalker.forParameter(element, false), () {
+      _walk(new ElementWalker.forParameter(element), () {
         super.visitSimpleFormalParameter(node);
       });
       resolveMetadata(node, node.metadata, element);
@@ -435,7 +440,8 @@
 
   @override
   void visitTypeParameter(TypeParameter node) {
-    if (node.parent.parent is FunctionTypedFormalParameter) {
+    if (node.parent.parent is FunctionTypedFormalParameter &&
+        !AnalysisDriver.useSummary2) {
       // Work around dartbug.com/28515.
       // TODO(paulberry): remove this once dartbug.com/28515 is fixed.
       var element = new TypeParameterElementImpl.forNode(node.name);
@@ -514,6 +520,7 @@
   void _setGenericFunctionType(TypeAnnotation typeNode, DartType type) {
     if (typeNode is GenericFunctionTypeImpl) {
       typeNode.type = type;
+      typeNode.declaredElement = type.element;
     } else if (typeNode is NamedType) {
       typeNode.type = type;
       if (type is ParameterizedType) {
@@ -739,7 +746,7 @@
   /// corresponding type arguments of the [typeArguments].
   static void _applyTypeArgumentsToList(LibraryElement enclosingLibraryElement,
       DartType type, List<TypeAnnotation> typeArguments) {
-    if (type != null && type.isUndefined) {
+    if (type != null && type.isDynamic) {
       for (TypeAnnotation argument in typeArguments) {
         applyToTypeAnnotation(enclosingLibraryElement, type, argument);
       }
@@ -851,18 +858,10 @@
 
   /// Creates an [ElementWalker] which walks the child elements of a parameter
   /// element.
-  ElementWalker.forParameter(ParameterElement element, bool functionTyped)
+  ElementWalker.forParameter(ParameterElement element)
       : element = element,
         _parameters = element.parameters,
-        _typeParameters = element.typeParameters {
-    // If the parameter node is function typed, extract type parameters and
-    // formal parameters from its generic function type element.
-    if (functionTyped) {
-      GenericFunctionTypeElement typeElement = element.type.element;
-      _typeParameters = typeElement.typeParameters;
-      _parameters = typeElement.parameters;
-    }
-  }
+        _typeParameters = element.typeParameters;
 
   /// Creates an [ElementWalker] which walks the child elements of a typedef
   /// element.
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index c37d478..8f4c1b3 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -6,6 +6,7 @@
 import 'dart:collection';
 import 'dart:typed_data';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -28,7 +29,6 @@
 import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/summary/api_signature.dart';
-import 'package:analyzer/src/task/api/dart.dart';
 import 'package:analyzer/src/task/api/model.dart';
 import 'package:analyzer/src/task/manager.dart';
 import 'package:front_end/src/fasta/scanner/token.dart';
@@ -39,605 +39,473 @@
 export 'package:analyzer/src/generated/timestamped_data.dart'
     show TimestampedData;
 
-/**
- * Used by [AnalysisOptions] to allow function bodies to be analyzed in some
- * sources but not others.
- */
+/// Used by [AnalysisOptions] to allow function bodies to be analyzed in some
+/// sources but not others.
 typedef bool AnalyzeFunctionBodiesPredicate(Source source);
 
-/**
- * A context in which a single analysis can be performed and incrementally
- * maintained. The context includes such information as the version of the SDK
- * being analyzed against as well as the package-root used to resolve 'package:'
- * URI's. (Both of which are known indirectly through the [SourceFactory].)
- *
- * An analysis context also represents the state of the analysis, which includes
- * knowing which sources have been included in the analysis (either directly or
- * indirectly) and the results of the analysis. Sources must be added and
- * removed from the context using the method [applyChanges], which is also used
- * to notify the context when sources have been modified and, consequently,
- * previously known results might have been invalidated.
- *
- * There are two ways to access the results of the analysis. The most common is
- * to use one of the 'get' methods to access the results. The 'get' methods have
- * the advantage that they will always return quickly, but have the disadvantage
- * that if the results are not currently available they will return either
- * nothing or in some cases an incomplete result. The second way to access
- * results is by using one of the 'compute' methods. The 'compute' methods will
- * always attempt to compute the requested results but might block the caller
- * for a significant period of time.
- *
- * When results have been invalidated, have never been computed (as is the case
- * for newly added sources), or have been removed from the cache, they are
- * <b>not</b> automatically recreated. They will only be recreated if one of the
- * 'compute' methods is invoked.
- *
- * However, this is not always acceptable. Some clients need to keep the
- * analysis results up-to-date. For such clients there is a mechanism that
- * allows them to incrementally perform needed analysis and get notified of the
- * consequent changes to the analysis results. This mechanism is realized by the
- * method [performAnalysisTask].
- *
- * Analysis engine allows for having more than one context. This can be used,
- * for example, to perform one analysis based on the state of files on disk and
- * a separate analysis based on the state of those files in open editors. It can
- * also be used to perform an analysis based on a proposed future state, such as
- * the state after a refactoring.
- */
+/// A context in which a single analysis can be performed and incrementally
+/// maintained. The context includes such information as the version of the SDK
+/// being analyzed against as well as the package-root used to resolve 'package:'
+/// URI's. (Both of which are known indirectly through the [SourceFactory].)
+///
+/// An analysis context also represents the state of the analysis, which includes
+/// knowing which sources have been included in the analysis (either directly or
+/// indirectly) and the results of the analysis. Sources must be added and
+/// removed from the context using the method [applyChanges], which is also used
+/// to notify the context when sources have been modified and, consequently,
+/// previously known results might have been invalidated.
+///
+/// There are two ways to access the results of the analysis. The most common is
+/// to use one of the 'get' methods to access the results. The 'get' methods have
+/// the advantage that they will always return quickly, but have the disadvantage
+/// that if the results are not currently available they will return either
+/// nothing or in some cases an incomplete result. The second way to access
+/// results is by using one of the 'compute' methods. The 'compute' methods will
+/// always attempt to compute the requested results but might block the caller
+/// for a significant period of time.
+///
+/// When results have been invalidated, have never been computed (as is the case
+/// for newly added sources), or have been removed from the cache, they are
+/// <b>not</b> automatically recreated. They will only be recreated if one of the
+/// 'compute' methods is invoked.
+///
+/// However, this is not always acceptable. Some clients need to keep the
+/// analysis results up-to-date. For such clients there is a mechanism that
+/// allows them to incrementally perform needed analysis and get notified of the
+/// consequent changes to the analysis results. This mechanism is realized by the
+/// method [performAnalysisTask].
+///
+/// Analysis engine allows for having more than one context. This can be used,
+/// for example, to perform one analysis based on the state of files on disk and
+/// a separate analysis based on the state of those files in open editors. It can
+/// also be used to perform an analysis based on a proposed future state, such as
+/// the state after a refactoring.
 abstract class AnalysisContext {
-  /**
-   * The file resolver provider used to override the way file URI's are
-   * resolved in some contexts.
-   */
+  /// The file resolver provider used to override the way file URI's are
+  /// resolved in some contexts.
   ResolverProvider fileResolverProvider;
 
-  /**
-   * Return the set of analysis options controlling the behavior of this
-   * context. Clients should not modify the returned set of options.
-   */
+  /// Return the set of analysis options controlling the behavior of this
+  /// context. Clients should not modify the returned set of options.
   AnalysisOptions get analysisOptions;
 
-  /**
-   * Set the set of analysis options controlling the behavior of this context to
-   * the given [options]. Clients can safely assume that all necessary analysis
-   * results have been invalidated.
-   */
+  /// Set the set of analysis options controlling the behavior of this context to
+  /// the given [options]. Clients can safely assume that all necessary analysis
+  /// results have been invalidated.
   void set analysisOptions(AnalysisOptions options);
 
-  /**
-   * Set the order in which sources will be analyzed by [performAnalysisTask] to
-   * match the order of the sources in the given list of [sources]. If a source
-   * that needs to be analyzed is not contained in the list, then it will be
-   * treated as if it were at the end of the list. If the list is empty (or
-   * `null`) then no sources will be given priority over other sources.
-   *
-   * Changes made to the list after this method returns will <b>not</b> be
-   * reflected in the priority order.
-   */
+  /// Set the order in which sources will be analyzed by [performAnalysisTask] to
+  /// match the order of the sources in the given list of [sources]. If a source
+  /// that needs to be analyzed is not contained in the list, then it will be
+  /// treated as if it were at the end of the list. If the list is empty (or
+  /// `null`) then no sources will be given priority over other sources.
+  ///
+  /// Changes made to the list after this method returns will <b>not</b> be
+  /// reflected in the priority order.
   void set analysisPriorityOrder(List<Source> sources);
 
-  /**
-   * Return the set of declared variables used when computing constant values.
-   */
+  /// Return the set of declared variables used when computing constant values.
   DeclaredVariables get declaredVariables;
 
-  /**
-   * Return a list containing all of the sources known to this context that
-   * represent HTML files. The contents of the list can be incomplete.
-   */
+  /// Return a list containing all of the sources known to this context that
+  /// represent HTML files. The contents of the list can be incomplete.
   List<Source> get htmlSources;
 
-  /**
-   * The stream that is notified when a source either starts or stops being
-   * analyzed implicitly.
-   */
+  /// The stream that is notified when a source either starts or stops being
+  /// analyzed implicitly.
   Stream<ImplicitAnalysisEvent> get implicitAnalysisEvents;
 
-  /**
-   * Returns `true` if this context was disposed using [dispose].
-   */
+  /// Returns `true` if this context was disposed using [dispose].
   bool get isDisposed;
 
-  /**
-   * Return a list containing all of the sources known to this context that
-   * represent the defining compilation unit of a library that can be run within
-   * a browser. The sources that are returned represent libraries that have a
-   * 'main' method and are either referenced by an HTML file or import, directly
-   * or indirectly, a client-only library. The contents of the list can be
-   * incomplete.
-   */
+  /// Return a list containing all of the sources known to this context that
+  /// represent the defining compilation unit of a library that can be run within
+  /// a browser. The sources that are returned represent libraries that have a
+  /// 'main' method and are either referenced by an HTML file or import, directly
+  /// or indirectly, a client-only library. The contents of the list can be
+  /// incomplete.
   List<Source> get launchableClientLibrarySources;
 
-  /**
-   * Return a list containing all of the sources known to this context that
-   * represent the defining compilation unit of a library that can be run
-   * outside of a browser. The contents of the list can be incomplete.
-   */
+  /// Return a list containing all of the sources known to this context that
+  /// represent the defining compilation unit of a library that can be run
+  /// outside of a browser. The contents of the list can be incomplete.
   List<Source> get launchableServerLibrarySources;
 
-  /**
-   * Return a list containing all of the sources known to this context that
-   * represent the defining compilation unit of a library. The contents of the
-   * list can be incomplete.
-   */
+  /// Return a list containing all of the sources known to this context that
+  /// represent the defining compilation unit of a library. The contents of the
+  /// list can be incomplete.
   List<Source> get librarySources;
 
-  /**
-   * Return a client-provided name used to identify this context, or `null` if
-   * the client has not provided a name.
-   */
+  /// Return a client-provided name used to identify this context, or `null` if
+  /// the client has not provided a name.
   String get name;
 
-  /**
-   * Set the client-provided name used to identify this context to the given
-   * [name].
-   */
+  /// Set the client-provided name used to identify this context to the given
+  /// [name].
   set name(String name);
 
-  /**
-   * The stream that is notified when sources have been added or removed,
-   * or the source's content has changed.
-   */
+  /// The stream that is notified when sources have been added or removed,
+  /// or the source's content has changed.
   Stream<SourcesChangedEvent> get onSourcesChanged;
 
-  /**
-   * Return the source factory used to create the sources that can be analyzed
-   * in this context.
-   */
+  /// Return the source factory used to create the sources that can be analyzed
+  /// in this context.
   SourceFactory get sourceFactory;
 
-  /**
-   * Set the source factory used to create the sources that can be analyzed in
-   * this context to the given source [factory]. Clients can safely assume that
-   * all analysis results have been invalidated.
-   */
+  /// Set the source factory used to create the sources that can be analyzed in
+  /// this context to the given source [factory]. Clients can safely assume that
+  /// all analysis results have been invalidated.
   void set sourceFactory(SourceFactory factory);
 
-  /**
-   * Return a list containing all of the sources known to this context.
-   */
+  /// Return a list containing all of the sources known to this context.
   List<Source> get sources;
 
-  /**
-   * Return a type provider for this context or throw [AnalysisException] if
-   * either `dart:core` or `dart:async` cannot be resolved.
-   */
+  /// Return a type provider for this context or throw [AnalysisException] if
+  /// either `dart:core` or `dart:async` cannot be resolved.
   TypeProvider get typeProvider;
 
-  /**
-   * Return a type system for this context.
-   */
+  /// Return a type system for this context.
   TypeSystem get typeSystem;
 
-  /**
-   * Add the given [listener] to the list of objects that are to be notified
-   * when various analysis results are produced in this context.
-   */
+  /// Add the given [listener] to the list of objects that are to be notified
+  /// when various analysis results are produced in this context.
   void addListener(AnalysisListener listener);
 
-  /**
-   * Apply the given [delta] to change the level of analysis that will be
-   * performed for the sources known to this context.
-   */
+  /// Apply the given [delta] to change the level of analysis that will be
+  /// performed for the sources known to this context.
   void applyAnalysisDelta(AnalysisDelta delta);
 
-  /**
-   * Apply the changes specified by the given [changeSet] to this context. Any
-   * analysis results that have been invalidated by these changes will be
-   * removed.
-   */
+  /// Apply the changes specified by the given [changeSet] to this context. Any
+  /// analysis results that have been invalidated by these changes will be
+  /// removed.
   void applyChanges(ChangeSet changeSet);
 
-  /**
-   * Return the documentation comment for the given [element] as it appears in
-   * the original source (complete with the beginning and ending delimiters) for
-   * block documentation comments, or lines starting with `"///"` and separated
-   * with `"\n"` characters for end-of-line documentation comments, or `null` if
-   * the element does not have a documentation comment associated with it. This
-   * can be a long-running operation if the information needed to access the
-   * comment is not cached.
-   *
-   * Throws an [AnalysisException] if the documentation comment could not be
-   * determined because the analysis could not be performed.
-   *
-   * <b>Note:</b> This method cannot be used in an async environment.
-   */
+  /// Return the documentation comment for the given [element] as it appears in
+  /// the original source (complete with the beginning and ending delimiters) for
+  /// block documentation comments, or lines starting with `"///"` and separated
+  /// with `"\n"` characters for end-of-line documentation comments, or `null` if
+  /// the element does not have a documentation comment associated with it. This
+  /// can be a long-running operation if the information needed to access the
+  /// comment is not cached.
+  ///
+  /// Throws an [AnalysisException] if the documentation comment could not be
+  /// determined because the analysis could not be performed.
+  ///
+  /// <b>Note:</b> This method cannot be used in an async environment.
   String computeDocumentationComment(Element element);
 
-  /**
-   * Return a list containing all of the errors associated with the given
-   * [source]. If the errors are not already known then the source will be
-   * analyzed in order to determine the errors associated with it.
-   *
-   * Throws an [AnalysisException] if the errors could not be determined because
-   * the analysis could not be performed.
-   *
-   * <b>Note:</b> This method cannot be used in an async environment.
-   *
-   * See [getErrors].
-   */
+  /// Return a list containing all of the errors associated with the given
+  /// [source]. If the errors are not already known then the source will be
+  /// analyzed in order to determine the errors associated with it.
+  ///
+  /// Throws an [AnalysisException] if the errors could not be determined because
+  /// the analysis could not be performed.
+  ///
+  /// <b>Note:</b> This method cannot be used in an async environment.
+  ///
+  /// See [getErrors].
   List<AnalysisError> computeErrors(Source source);
 
-  /**
-   * Return the kind of the given [source], computing it's kind if it is not
-   * already known. Return [SourceKind.UNKNOWN] if the source is not contained
-   * in this context.
-   *
-   * <b>Note:</b> This method cannot be used in an async environment.
-   *
-   * See [getKindOf].
-   */
+  /// Return the kind of the given [source], computing it's kind if it is not
+  /// already known. Return [SourceKind.UNKNOWN] if the source is not contained
+  /// in this context.
+  ///
+  /// <b>Note:</b> This method cannot be used in an async environment.
+  ///
+  /// See [getKindOf].
   SourceKind computeKindOf(Source source);
 
-  /**
-   * Return the element model corresponding to the library defined by the given
-   * [source]. If the element model does not yet exist it will be created. The
-   * process of creating an element model for a library can long-running,
-   * depending on the size of the library and the number of libraries that are
-   * imported into it that also need to have a model built for them.
-   *
-   * Throws an [AnalysisException] if the element model could not be determined
-   * because the analysis could not be performed.
-   *
-   * <b>Note:</b> This method cannot be used in an async environment.
-   *
-   * See [getLibraryElement].
-   */
+  /// Return the element model corresponding to the library defined by the given
+  /// [source]. If the element model does not yet exist it will be created. The
+  /// process of creating an element model for a library can long-running,
+  /// depending on the size of the library and the number of libraries that are
+  /// imported into it that also need to have a model built for them.
+  ///
+  /// Throws an [AnalysisException] if the element model could not be determined
+  /// because the analysis could not be performed.
+  ///
+  /// <b>Note:</b> This method cannot be used in an async environment.
+  ///
+  /// See [getLibraryElement].
   LibraryElement computeLibraryElement(Source source);
 
-  /**
-   * Return the line information for the given [source], or `null` if the source
-   * is not of a recognized kind (neither a Dart nor HTML file). If the line
-   * information was not previously known it will be created. The line
-   * information is used to map offsets from the beginning of the source to line
-   * and column pairs.
-   *
-   * Throws an [AnalysisException] if the line information could not be
-   * determined because the analysis could not be performed.
-   *
-   * <b>Note:</b> This method cannot be used in an async environment.
-   *
-   * See [getLineInfo].
-   */
+  /// Return the line information for the given [source], or `null` if the source
+  /// is not of a recognized kind (neither a Dart nor HTML file). If the line
+  /// information was not previously known it will be created. The line
+  /// information is used to map offsets from the beginning of the source to line
+  /// and column pairs.
+  ///
+  /// Throws an [AnalysisException] if the line information could not be
+  /// determined because the analysis could not be performed.
+  ///
+  /// <b>Note:</b> This method cannot be used in an async environment.
+  ///
+  /// See [getLineInfo].
   LineInfo computeLineInfo(Source source);
 
-  /**
-   * Return a future which will be completed with the fully resolved AST for a
-   * single compilation unit within the given library, once that AST is up to
-   * date.
-   *
-   * If the resolved AST can't be computed for some reason, the future will be
-   * completed with an error.  One possible error is AnalysisNotScheduledError,
-   * which means that the resolved AST can't be computed because the given
-   * source file is not scheduled to be analyzed within the context of the
-   * given library.
-   */
+  /// Return a future which will be completed with the fully resolved AST for a
+  /// single compilation unit within the given library, once that AST is up to
+  /// date.
+  ///
+  /// If the resolved AST can't be computed for some reason, the future will be
+  /// completed with an error.  One possible error is AnalysisNotScheduledError,
+  /// which means that the resolved AST can't be computed because the given
+  /// source file is not scheduled to be analyzed within the context of the
+  /// given library.
   CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync(
       Source source, Source librarySource);
 
-  /**
-   * Perform work until the given [result] has been computed for the given
-   * [target]. Return the computed value.
-   */
+  /// Perform work until the given [result] has been computed for the given
+  /// [target]. Return the computed value.
   V computeResult<V>(AnalysisTarget target, ResultDescriptor<V> result);
 
-  /**
-   * Notifies the context that the client is going to stop using this context.
-   */
+  /// Notifies the context that the client is going to stop using this context.
   void dispose();
 
-  /**
-   * Return `true` if the given [source] exists.
-   *
-   * This method should be used rather than the method [Source.exists] because
-   * contexts can have local overrides of the content of a source that the
-   * source is not aware of and a source with local content is considered to
-   * exist even if there is no file on disk.
-   */
+  /// Return `true` if the given [source] exists.
+  ///
+  /// This method should be used rather than the method [Source.exists] because
+  /// contexts can have local overrides of the content of a source that the
+  /// source is not aware of and a source with local content is considered to
+  /// exist even if there is no file on disk.
   bool exists(Source source);
 
-  /**
-   * Return the element model corresponding to the compilation unit defined by
-   * the given [unitSource] in the library defined by the given [librarySource],
-   * or `null` if the element model does not currently exist or if the library
-   * cannot be analyzed for some reason.
-   */
+  /// Return the element model corresponding to the compilation unit defined by
+  /// the given [unitSource] in the library defined by the given [librarySource],
+  /// or `null` if the element model does not currently exist or if the library
+  /// cannot be analyzed for some reason.
   CompilationUnitElement getCompilationUnitElement(
       Source unitSource, Source librarySource);
 
-  /**
-   * Return configuration data associated with the given key or the [key]'s
-   * default value if no state has been associated.
-   *
-   * See [setConfigurationData].
-   */
+  /// Return configuration data associated with the given key or the [key]'s
+  /// default value if no state has been associated.
+  ///
+  /// See [setConfigurationData].
   @deprecated
   V getConfigurationData<V>(ResultDescriptor<V> key);
 
-  /**
-   * Return the contents and timestamp of the given [source].
-   *
-   * This method should be used rather than the method [Source.getContents]
-   * because contexts can have local overrides of the content of a source that
-   * the source is not aware of.
-   */
+  /// Return the contents and timestamp of the given [source].
+  ///
+  /// This method should be used rather than the method [Source.getContents]
+  /// because contexts can have local overrides of the content of a source that
+  /// the source is not aware of.
   TimestampedData<String> getContents(Source source);
 
-  /**
-   * Return the element referenced by the given [location], or `null` if the
-   * element is not immediately available or if there is no element with the
-   * given location. The latter condition can occur, for example, if the
-   * location describes an element from a different context or if the element
-   * has been removed from this context as a result of some change since it was
-   * originally obtained.
-   */
+  /// Return the element referenced by the given [location], or `null` if the
+  /// element is not immediately available or if there is no element with the
+  /// given location. The latter condition can occur, for example, if the
+  /// location describes an element from a different context or if the element
+  /// has been removed from this context as a result of some change since it was
+  /// originally obtained.
   Element getElement(ElementLocation location);
 
-  /**
-   * Return an analysis error info containing the list of all of the errors and
-   * the line info associated with the given [source]. The list of errors will
-   * be empty if the source is not known to this context or if there are no
-   * errors in the source. The errors contained in the list can be incomplete.
-   *
-   * See [computeErrors].
-   */
+  /// Return an analysis error info containing the list of all of the errors and
+  /// the line info associated with the given [source]. The list of errors will
+  /// be empty if the source is not known to this context or if there are no
+  /// errors in the source. The errors contained in the list can be incomplete.
+  ///
+  /// See [computeErrors].
   AnalysisErrorInfo getErrors(Source source);
 
-  /**
-   * Return the sources for the HTML files that reference the compilation unit
-   * with the given [source]. If the source does not represent a Dart source or
-   * is not known to this context, the returned list will be empty. The contents
-   * of the list can be incomplete.
-   */
+  /// Return the sources for the HTML files that reference the compilation unit
+  /// with the given [source]. If the source does not represent a Dart source or
+  /// is not known to this context, the returned list will be empty. The contents
+  /// of the list can be incomplete.
   List<Source> getHtmlFilesReferencing(Source source);
 
-  /**
-   * Return the kind of the given [source], or `null` if the kind is not known
-   * to this context.
-   *
-   * See [computeKindOf].
-   */
+  /// Return the kind of the given [source], or `null` if the kind is not known
+  /// to this context.
+  ///
+  /// See [computeKindOf].
   SourceKind getKindOf(Source source);
 
-  /**
-   * Return the sources for the defining compilation units of any libraries of
-   * which the given [source] is a part. The list will normally contain a single
-   * library because most Dart sources are only included in a single library,
-   * but it is possible to have a part that is contained in multiple identically
-   * named libraries. If the source represents the defining compilation unit of
-   * a library, then the returned list will contain the given source as its only
-   * element. If the source does not represent a Dart source or is not known to
-   * this context, the returned list will be empty. The contents of the list can
-   * be incomplete.
-   */
+  /// Return the sources for the defining compilation units of any libraries of
+  /// which the given [source] is a part. The list will normally contain a single
+  /// library because most Dart sources are only included in a single library,
+  /// but it is possible to have a part that is contained in multiple identically
+  /// named libraries. If the source represents the defining compilation unit of
+  /// a library, then the returned list will contain the given source as its only
+  /// element. If the source does not represent a Dart source or is not known to
+  /// this context, the returned list will be empty. The contents of the list can
+  /// be incomplete.
   List<Source> getLibrariesContaining(Source source);
 
-  /**
-   * Return the sources for the defining compilation units of any libraries that
-   * depend on the library defined by the given [librarySource]. One library
-   * depends on another if it either imports or exports that library.
-   */
+  /// Return the sources for the defining compilation units of any libraries that
+  /// depend on the library defined by the given [librarySource]. One library
+  /// depends on another if it either imports or exports that library.
   List<Source> getLibrariesDependingOn(Source librarySource);
 
-  /**
-   * Return the sources for the defining compilation units of any libraries that
-   * are referenced from the HTML file defined by the given [htmlSource].
-   */
+  /// Return the sources for the defining compilation units of any libraries that
+  /// are referenced from the HTML file defined by the given [htmlSource].
   List<Source> getLibrariesReferencedFromHtml(Source htmlSource);
 
-  /**
-   * Return the element model corresponding to the library defined by the given
-   * [source], or `null` if the element model does not currently exist or if the
-   * library cannot be analyzed for some reason.
-   */
+  /// Return the element model corresponding to the library defined by the given
+  /// [source], or `null` if the element model does not currently exist or if the
+  /// library cannot be analyzed for some reason.
   LibraryElement getLibraryElement(Source source);
 
-  /**
-   * Return the line information for the given [source], or `null` if the line
-   * information is not known. The line information is used to map offsets from
-   * the beginning of the source to line and column pairs.
-   *
-   * See [computeLineInfo].
-   */
+  /// Return the line information for the given [source], or `null` if the line
+  /// information is not known. The line information is used to map offsets from
+  /// the beginning of the source to line and column pairs.
+  ///
+  /// See [computeLineInfo].
   LineInfo getLineInfo(Source source);
 
-  /**
-   * Return the modification stamp for the [source], or a negative value if the
-   * source does not exist. A modification stamp is a non-negative integer with
-   * the property that if the contents of the source have not been modified
-   * since the last time the modification stamp was accessed then the same value
-   * will be returned, but if the contents of the source have been modified one
-   * or more times (even if the net change is zero) the stamps will be different.
-   *
-   * This method should be used rather than the method
-   * [Source.getModificationStamp] because contexts can have local overrides of
-   * the content of a source that the source is not aware of.
-   */
+  /// Return the modification stamp for the [source], or a negative value if the
+  /// source does not exist. A modification stamp is a non-negative integer with
+  /// the property that if the contents of the source have not been modified
+  /// since the last time the modification stamp was accessed then the same value
+  /// will be returned, but if the contents of the source have been modified one
+  /// or more times (even if the net change is zero) the stamps will be different.
+  ///
+  /// This method should be used rather than the method
+  /// [Source.getModificationStamp] because contexts can have local overrides of
+  /// the content of a source that the source is not aware of.
   int getModificationStamp(Source source);
 
-  /**
-   * Return a fully resolved AST for the compilation unit defined by the given
-   * [unitSource] within the given [library], or `null` if the resolved AST is
-   * not already computed.
-   *
-   * See [resolveCompilationUnit].
-   */
+  /// Return a fully resolved AST for the compilation unit defined by the given
+  /// [unitSource] within the given [library], or `null` if the resolved AST is
+  /// not already computed.
+  ///
+  /// See [resolveCompilationUnit].
   CompilationUnit getResolvedCompilationUnit(
       Source unitSource, LibraryElement library);
 
-  /**
-   * Return a fully resolved AST for the compilation unit defined by the given
-   * [unitSource] within the library defined by the given [librarySource], or
-   * `null` if the resolved AST is not already computed.
-   *
-   * See [resolveCompilationUnit2].
-   */
+  /// Return a fully resolved AST for the compilation unit defined by the given
+  /// [unitSource] within the library defined by the given [librarySource], or
+  /// `null` if the resolved AST is not already computed.
+  ///
+  /// See [resolveCompilationUnit2].
   CompilationUnit getResolvedCompilationUnit2(
       Source unitSource, Source librarySource);
 
-  /**
-   * Return the value of the given [result] for the given [target].
-   *
-   * If the corresponding [target] does not exist, or the [result] is not
-   * computed yet, then the default value is returned.
-   */
+  /// Return the value of the given [result] for the given [target].
+  ///
+  /// If the corresponding [target] does not exist, or the [result] is not
+  /// computed yet, then the default value is returned.
   V getResult<V>(AnalysisTarget target, ResultDescriptor<V> result);
 
-  /**
-   * Return a list of the sources being analyzed in this context whose full path
-   * is equal to the given [path].
-   */
+  /// Return a list of the sources being analyzed in this context whose full path
+  /// is equal to the given [path].
   List<Source> getSourcesWithFullName(String path);
 
-  /**
-   * Invalidates hints in the given [librarySource] and included parts.
-   */
+  /// Invalidates hints in the given [librarySource] and included parts.
   void invalidateLibraryHints(Source librarySource);
 
-  /**
-   * Return `true` if the given [librarySource] is known to be the defining
-   * compilation unit of a library that can be run on a client (references
-   * 'dart:html', either directly or indirectly).
-   *
-   * <b>Note:</b> In addition to the expected case of returning `false` if the
-   * source is known to be a library that cannot be run on a client, this method
-   * will also return `false` if the source is not known to be a library or if
-   * we do not know whether it can be run on a client.
-   */
+  /// Return `true` if the given [librarySource] is known to be the defining
+  /// compilation unit of a library that can be run on a client (references
+  /// 'dart:html', either directly or indirectly).
+  ///
+  /// <b>Note:</b> In addition to the expected case of returning `false` if the
+  /// source is known to be a library that cannot be run on a client, this method
+  /// will also return `false` if the source is not known to be a library or if
+  /// we do not know whether it can be run on a client.
   bool isClientLibrary(Source librarySource);
 
-  /**
-   * Return `true` if the given [librarySource] is known to be the defining
-   * compilation unit of a library that can be run on the server (does not
-   * reference 'dart:html', either directly or indirectly).
-   *
-   * <b>Note:</b> In addition to the expected case of returning `false` if the
-   * source is known to be a library that cannot be run on the server, this
-   * method will also return `false` if the source is not known to be a library
-   * or if we do not know whether it can be run on the server.
-   */
+  /// Return `true` if the given [librarySource] is known to be the defining
+  /// compilation unit of a library that can be run on the server (does not
+  /// reference 'dart:html', either directly or indirectly).
+  ///
+  /// <b>Note:</b> In addition to the expected case of returning `false` if the
+  /// source is known to be a library that cannot be run on the server, this
+  /// method will also return `false` if the source is not known to be a library
+  /// or if we do not know whether it can be run on the server.
   bool isServerLibrary(Source librarySource);
 
-  /**
-   * Return the stream that is notified when a result with the given
-   * [descriptor] is changed, e.g. computed or invalidated.
-   */
+  /// Return the stream that is notified when a result with the given
+  /// [descriptor] is changed, e.g. computed or invalidated.
   Stream<ResultChangedEvent> onResultChanged(ResultDescriptor descriptor);
 
-  /**
-   * Return the stream that is notified when a new value for the given
-   * [descriptor] is computed.
-   */
+  /// Return the stream that is notified when a new value for the given
+  /// [descriptor] is computed.
   @deprecated
   Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor);
 
-  /**
-   * Parse the content of the given [source] to produce an AST structure. The
-   * resulting AST structure may or may not be resolved, and may have a slightly
-   * different structure depending upon whether it is resolved.
-   *
-   * Throws an [AnalysisException] if the analysis could not be performed
-   *
-   * <b>Note:</b> This method cannot be used in an async environment.
-   */
+  /// Parse the content of the given [source] to produce an AST structure. The
+  /// resulting AST structure may or may not be resolved, and may have a slightly
+  /// different structure depending upon whether it is resolved.
+  ///
+  /// Throws an [AnalysisException] if the analysis could not be performed
+  ///
+  /// <b>Note:</b> This method cannot be used in an async environment.
   CompilationUnit parseCompilationUnit(Source source);
 
-  /**
-   * Perform the next unit of work required to keep the analysis results
-   * up-to-date and return information about the consequent changes to the
-   * analysis results. This method can be long running.
-   *
-   * The implementation that uses the task model notifies subscribers of
-   * [onResultChanged] about computed results.
-   *
-   * The following results are computed for Dart sources.
-   *
-   * 1. For explicit and implicit sources:
-   *    [PARSED_UNIT]
-   *    [RESOLVED_UNIT]
-   *
-   * 2. For explicit sources:
-   *    [DART_ERRORS].
-   *
-   * 3. For explicit and implicit library sources:
-   *    [LIBRARY_ELEMENT].
-   */
+  /// Perform the next unit of work required to keep the analysis results
+  /// up-to-date and return information about the consequent changes to the
+  /// analysis results. This method can be long running.
+  ///
+  /// The implementation that uses the task model notifies subscribers of
+  /// [onResultChanged] about computed results.
+  ///
+  /// The following results are computed for Dart sources.
+  ///
+  /// 1. For explicit and implicit sources:
+  ///    [PARSED_UNIT]
+  ///    [RESOLVED_UNIT]
+  ///
+  /// 2. For explicit sources:
+  ///    [DART_ERRORS].
+  ///
+  /// 3. For explicit and implicit library sources:
+  ///    [LIBRARY_ELEMENT].
   AnalysisResult performAnalysisTask();
 
-  /**
-   * Remove the given [listener] from the list of objects that are to be
-   * notified when various analysis results are produced in this context.
-   */
+  /// Remove the given [listener] from the list of objects that are to be
+  /// notified when various analysis results are produced in this context.
   void removeListener(AnalysisListener listener);
 
-  /**
-   * Return a fully resolved AST for the compilation unit defined by the given
-   * [unitSource] within the given [library].
-   *
-   * Throws an [AnalysisException] if the analysis could not be performed.
-   *
-   * <b>Note:</b> This method cannot be used in an async environment.
-   *
-   * See [getResolvedCompilationUnit].
-   */
+  /// Return a fully resolved AST for the compilation unit defined by the given
+  /// [unitSource] within the given [library].
+  ///
+  /// Throws an [AnalysisException] if the analysis could not be performed.
+  ///
+  /// <b>Note:</b> This method cannot be used in an async environment.
+  ///
+  /// See [getResolvedCompilationUnit].
   CompilationUnit resolveCompilationUnit(
       Source unitSource, LibraryElement library);
 
-  /**
-   * Return a fully resolved AST for the compilation unit defined by the given
-   * [unitSource] within the library defined by the given [librarySource].
-   *
-   * Throws an [AnalysisException] if the analysis could not be performed.
-   *
-   * <b>Note:</b> This method cannot be used in an async environment.
-   *
-   * See [getResolvedCompilationUnit2].
-   */
+  /// Return a fully resolved AST for the compilation unit defined by the given
+  /// [unitSource] within the library defined by the given [librarySource].
+  ///
+  /// Throws an [AnalysisException] if the analysis could not be performed.
+  ///
+  /// <b>Note:</b> This method cannot be used in an async environment.
+  ///
+  /// See [getResolvedCompilationUnit2].
   CompilationUnit resolveCompilationUnit2(
       Source unitSource, Source librarySource);
 
-  /**
-   * Set the contents of the given [source] to the given [contents] and mark the
-   * source as having changed. The additional [offset] and [length] information
-   * is used by the context to determine what reanalysis is necessary.
-   */
+  /// Set the contents of the given [source] to the given [contents] and mark the
+  /// source as having changed. The additional [offset] and [length] information
+  /// is used by the context to determine what reanalysis is necessary.
   void setChangedContents(
       Source source, String contents, int offset, int oldLength, int newLength);
 
-  /**
-   * Associate this configuration [data] object with the given descriptor [key].
-   *
-   * See [getConfigurationData].
-   */
+  /// Associate this configuration [data] object with the given descriptor [key].
+  ///
+  /// See [getConfigurationData].
   @deprecated
   void setConfigurationData(ResultDescriptor key, Object data);
 
-  /**
-   * Set the contents of the given [source] to the given [contents] and mark the
-   * source as having changed. This has the effect of overriding the default
-   * contents of the source. If the contents are `null` the override is removed
-   * so that the default contents will be returned.
-   */
+  /// Set the contents of the given [source] to the given [contents] and mark the
+  /// source as having changed. This has the effect of overriding the default
+  /// contents of the source. If the contents are `null` the override is removed
+  /// so that the default contents will be returned.
   void setContents(Source source, String contents);
 }
 
-/**
- * A representation of changes to the types of analysis that should be
- * performed.
- */
+/// A representation of changes to the types of analysis that should be
+/// performed.
 class AnalysisDelta {
-  /**
-   * A mapping from source to what type of analysis should be performed on that
-   * source.
-   */
+  /// A mapping from source to what type of analysis should be performed on that
+  /// source.
   Map<Source, AnalysisLevel> _analysisMap =
       new HashMap<Source, AnalysisLevel>();
 
-  /**
-   * Return a collection of the sources that have been added. This is equivalent
-   * to calling [getAnalysisLevels] and collecting all sources that do not have
-   * an analysis level of [AnalysisLevel.NONE].
-   */
+  /// Return a collection of the sources that have been added. This is equivalent
+  /// to calling [getAnalysisLevels] and collecting all sources that do not have
+  /// an analysis level of [AnalysisLevel.NONE].
   List<Source> get addedSources {
     List<Source> result = new List<Source>();
     _analysisMap.forEach((Source source, AnalysisLevel level) {
@@ -648,15 +516,11 @@
     return result;
   }
 
-  /**
-   * Return a mapping of sources to the level of analysis that should be
-   * performed.
-   */
+  /// Return a mapping of sources to the level of analysis that should be
+  /// performed.
   Map<Source, AnalysisLevel> get analysisLevels => _analysisMap;
 
-  /**
-   * Record that the given [source] should be analyzed at the given [level].
-   */
+  /// Record that the given [source] should be analyzed at the given [level].
   void setAnalysisLevel(Source source, AnalysisLevel level) {
     _analysisMap[source] = level;
   }
@@ -671,10 +535,8 @@
     return buffer.toString();
   }
 
-  /**
-   * Append to the given [buffer] all sources with the given analysis [level],
-   * prefixed with a label and a separator if [needsSeparator] is `true`.
-   */
+  /// Append to the given [buffer] all sources with the given analysis [level],
+  /// prefixed with a label and a separator if [needsSeparator] is `true`.
   bool _appendSources(
       StringBuffer buffer, bool needsSeparator, AnalysisLevel level) {
     bool first = true;
@@ -697,85 +559,55 @@
   }
 }
 
-/**
- * The entry point for the functionality provided by the analysis engine. There
- * is a single instance of this class.
- */
+/// The entry point for the functionality provided by the analysis engine. There
+/// is a single instance of this class.
 class AnalysisEngine {
-  /**
-   * The suffix used for Dart source files.
-   */
+  /// The suffix used for Dart source files.
   static const String SUFFIX_DART = "dart";
 
-  /**
-   * The short suffix used for HTML files.
-   */
+  /// The short suffix used for HTML files.
   static const String SUFFIX_HTM = "htm";
 
-  /**
-   * The long suffix used for HTML files.
-   */
+  /// The long suffix used for HTML files.
   static const String SUFFIX_HTML = "html";
 
-  /**
-   * The deprecated file name used for analysis options files.
-   */
+  /// The deprecated file name used for analysis options files.
   static const String ANALYSIS_OPTIONS_FILE = '.analysis_options';
 
-  /**
-   * The file name used for analysis options files.
-   */
+  /// The file name used for analysis options files.
   static const String ANALYSIS_OPTIONS_YAML_FILE = 'analysis_options.yaml';
 
-  /**
-   * The file name used for pubspec files.
-   */
+  /// The file name used for pubspec files.
   static const String PUBSPEC_YAML_FILE = 'pubspec.yaml';
 
-  /**
-   * The file name used for Android manifest files.
-   */
+  /// The file name used for Android manifest files.
   static const String ANDROID_MANIFEST_FILE = 'AndroidManifest.xml';
 
-  /**
-   * The unique instance of this class.
-   */
+  /// The unique instance of this class.
   static final AnalysisEngine instance = new AnalysisEngine._();
 
-  /**
-   * The logger that should receive information about errors within the analysis
-   * engine.
-   */
+  /// The logger that should receive information about errors within the analysis
+  /// engine.
   Logger _logger = Logger.NULL;
 
-  /**
-   * The instrumentation service that is to be used by this analysis engine.
-   */
+  /// The instrumentation service that is to be used by this analysis engine.
   InstrumentationService _instrumentationService =
       InstrumentationService.NULL_SERVICE;
 
-  /**
-   * The partition manager being used to manage the shared partitions.
-   */
+  /// The partition manager being used to manage the shared partitions.
   final PartitionManager partitionManager = new PartitionManager();
 
-  /**
-   * The task manager used to manage the tasks used to analyze code.
-   */
+  /// The task manager used to manage the tasks used to analyze code.
   TaskManager _taskManager;
 
   AnalysisEngine._();
 
-  /**
-   * Return the instrumentation service that is to be used by this analysis
-   * engine.
-   */
+  /// Return the instrumentation service that is to be used by this analysis
+  /// engine.
   InstrumentationService get instrumentationService => _instrumentationService;
 
-  /**
-   * Set the instrumentation service that is to be used by this analysis engine
-   * to the given [service].
-   */
+  /// Set the instrumentation service that is to be used by this analysis engine
+  /// to the given [service].
   void set instrumentationService(InstrumentationService service) {
     if (service == null) {
       _instrumentationService = InstrumentationService.NULL_SERVICE;
@@ -784,23 +616,17 @@
     }
   }
 
-  /**
-   * Return the logger that should receive information about errors within the
-   * analysis engine.
-   */
+  /// Return the logger that should receive information about errors within the
+  /// analysis engine.
   Logger get logger => _logger;
 
-  /**
-   * Set the logger that should receive information about errors within the
-   * analysis engine to the given [logger].
-   */
+  /// Set the logger that should receive information about errors within the
+  /// analysis engine to the given [logger].
   void set logger(Logger logger) {
     this._logger = logger ?? Logger.NULL;
   }
 
-  /**
-   * Return the task manager used to manage the tasks used to analyze code.
-   */
+  /// Return the task manager used to manage the tasks used to analyze code.
   TaskManager get taskManager {
     if (_taskManager == null) {
       _taskManager = new TaskManager();
@@ -808,34 +634,26 @@
     return _taskManager;
   }
 
-  /**
-   * Clear any caches holding on to analysis results so that a full re-analysis
-   * will be performed the next time an analysis context is created.
-   */
+  /// Clear any caches holding on to analysis results so that a full re-analysis
+  /// will be performed the next time an analysis context is created.
   void clearCaches() {
     partitionManager.clearCache();
     // See https://github.com/dart-lang/sdk/issues/30314.
     StringToken.canonicalizer.clear();
   }
 
-  /**
-   * Create and return a new context in which analysis can be performed.
-   */
+  /// Create and return a new context in which analysis can be performed.
   AnalysisContext createAnalysisContext() {
     return new AnalysisContextImpl();
   }
 
-  /**
-   * A utility method that clients can use to process all of the required
-   * plugins. This method can only be used by clients that do not need to
-   * process any other plugins.
-   */
+  /// A utility method that clients can use to process all of the required
+  /// plugins. This method can only be used by clients that do not need to
+  /// process any other plugins.
   @deprecated
   void processRequiredPlugins() {}
 
-  /**
-   * Return `true` if the given [fileName] is an analysis options file.
-   */
+  /// Return `true` if the given [fileName] is an analysis options file.
   static bool isAnalysisOptionsFileName(String fileName,
       [pathos.Context context]) {
     if (fileName == null) {
@@ -846,10 +664,8 @@
         basename == ANALYSIS_OPTIONS_YAML_FILE;
   }
 
-  /**
-   * Return `true` if the given [fileName] is assumed to contain Dart source
-   * code.
-   */
+  /// Return `true` if the given [fileName] is assumed to contain Dart source
+  /// code.
   static bool isDartFileName(String fileName) {
     if (fileName == null) {
       return false;
@@ -858,9 +674,7 @@
     return extension == SUFFIX_DART;
   }
 
-  /**
-   * Return `true` if the given [fileName] is AndroidManifest.xml
-   */
+  /// Return `true` if the given [fileName] is AndroidManifest.xml
   static bool isManifestFileName(String fileName) {
     if (fileName == null) {
       return false;
@@ -869,83 +683,55 @@
   }
 }
 
-/**
- * The analysis errors and line information for the errors.
- */
+/// The analysis errors and line information for the errors.
 abstract class AnalysisErrorInfo {
-  /**
-   * Return the errors that as a result of the analysis, or `null` if there were
-   * no errors.
-   */
+  /// Return the errors that as a result of the analysis, or `null` if there were
+  /// no errors.
   List<AnalysisError> get errors;
 
-  /**
-   * Return the line information associated with the errors, or `null` if there
-   * were no errors.
-   */
+  /// Return the line information associated with the errors, or `null` if there
+  /// were no errors.
   LineInfo get lineInfo;
 }
 
-/**
- * The analysis errors and line info associated with a source.
- */
+/// The analysis errors and line info associated with a source.
 class AnalysisErrorInfoImpl implements AnalysisErrorInfo {
-  /**
-   * The analysis errors associated with a source, or `null` if there are no
-   * errors.
-   */
+  /// The analysis errors associated with a source, or `null` if there are no
+  /// errors.
   @override
   final List<AnalysisError> errors;
 
-  /**
-   * The line information associated with the errors, or `null` if there are no
-   * errors.
-   */
+  /// The line information associated with the errors, or `null` if there are no
+  /// errors.
   final LineInfo lineInfo;
 
-  /**
-   * Initialize an newly created error info with the given [errors] and
-   * [lineInfo].
-   */
+  /// Initialize an newly created error info with the given [errors] and
+  /// [lineInfo].
   AnalysisErrorInfoImpl(this.errors, this.lineInfo);
 }
 
-/**
- * The levels at which a source can be analyzed.
- */
+/// The levels at which a source can be analyzed.
 class AnalysisLevel implements Comparable<AnalysisLevel> {
-  /**
-   * Indicates a source should be fully analyzed.
-   */
+  /// Indicates a source should be fully analyzed.
   static const AnalysisLevel ALL = const AnalysisLevel('ALL', 0);
 
-  /**
-   * Indicates a source should be resolved and that errors, warnings and hints
-   * are needed.
-   */
+  /// Indicates a source should be resolved and that errors, warnings and hints
+  /// are needed.
   static const AnalysisLevel ERRORS = const AnalysisLevel('ERRORS', 1);
 
-  /**
-   * Indicates a source should be resolved, but that errors, warnings and hints
-   * are not needed.
-   */
+  /// Indicates a source should be resolved, but that errors, warnings and hints
+  /// are not needed.
   static const AnalysisLevel RESOLVED = const AnalysisLevel('RESOLVED', 2);
 
-  /**
-   * Indicates a source is not of interest to the client.
-   */
+  /// Indicates a source is not of interest to the client.
   static const AnalysisLevel NONE = const AnalysisLevel('NONE', 3);
 
   static const List<AnalysisLevel> values = const [ALL, ERRORS, RESOLVED, NONE];
 
-  /**
-   * The name of this analysis level.
-   */
+  /// The name of this analysis level.
   final String name;
 
-  /**
-   * The ordinal value of the analysis level.
-   */
+  /// The ordinal value of the analysis level.
   final int ordinal;
 
   const AnalysisLevel(this.name, this.ordinal);
@@ -960,294 +746,207 @@
   String toString() => name;
 }
 
-/**
- * An object that is listening for results being produced by an analysis
- * context.
- */
+/// An object that is listening for results being produced by an analysis
+/// context.
 abstract class AnalysisListener {
-  /**
-   * Reports that a task, described by the given [taskDescription] is about to
-   * be performed by the given [context].
-   */
+  /// Reports that a task, described by the given [taskDescription] is about to
+  /// be performed by the given [context].
   void aboutToPerformTask(AnalysisContext context, String taskDescription);
 
-  /**
-   * Reports that the [errors] associated with the given [source] in the given
-   * [context] has been updated to the given errors. The [lineInfo] is the line
-   * information associated with the source.
-   */
+  /// Reports that the [errors] associated with the given [source] in the given
+  /// [context] has been updated to the given errors. The [lineInfo] is the line
+  /// information associated with the source.
   void computedErrors(AnalysisContext context, Source source,
       List<AnalysisError> errors, LineInfo lineInfo);
 
-  /**
-   * Reports that the given [source] is no longer included in the set of sources
-   * that are being analyzed by the given analysis [context].
-   */
+  /// Reports that the given [source] is no longer included in the set of sources
+  /// that are being analyzed by the given analysis [context].
   void excludedSource(AnalysisContext context, Source source);
 
-  /**
-   * Reports that the given [source] is now included in the set of sources that
-   * are being analyzed by the given analysis [context].
-   */
+  /// Reports that the given [source] is now included in the set of sources that
+  /// are being analyzed by the given analysis [context].
   void includedSource(AnalysisContext context, Source source);
 
-  /**
-   * Reports that the given Dart [source] was parsed in the given [context],
-   * producing the given [unit].
-   */
+  /// Reports that the given Dart [source] was parsed in the given [context],
+  /// producing the given [unit].
   void parsedDart(AnalysisContext context, Source source, CompilationUnit unit);
 
-  /**
-   * Reports that the given Dart [source] was resolved in the given [context].
-   */
+  /// Reports that the given Dart [source] was resolved in the given [context].
   void resolvedDart(
       AnalysisContext context, Source source, CompilationUnit unit);
 }
 
-/**
- * Futures returned by [AnalysisContext] for pending analysis results will
- * complete with this error if it is determined that analysis results will
- * never become available (e.g. because the requested source is not subject to
- * analysis, or because the requested source is a part file which is not a part
- * of any known library).
- */
+/// Futures returned by [AnalysisContext] for pending analysis results will
+/// complete with this error if it is determined that analysis results will
+/// never become available (e.g. because the requested source is not subject to
+/// analysis, or because the requested source is a part file which is not a part
+/// of any known library).
 class AnalysisNotScheduledError implements Exception {}
 
-/**
- * A set of analysis options used to control the behavior of an analysis
- * context.
- */
+/// A set of analysis options used to control the behavior of an analysis
+/// context.
 abstract class AnalysisOptions {
-  /**
-   * The length of the list returned by [signature].
-   */
+  /// The length of the list returned by [signature].
   static const int signatureLength = 4;
 
-  /**
-   * Function that returns `true` if analysis is to parse and analyze function
-   * bodies for a given source.
-   */
+  /// Function that returns `true` if analysis is to parse and analyze function
+  /// bodies for a given source.
   AnalyzeFunctionBodiesPredicate get analyzeFunctionBodiesPredicate;
 
-  /**
-   * Return the maximum number of sources for which AST structures should be
-   * kept in the cache.
-   *
-   * DEPRECATED: This setting no longer has any effect.
-   */
+  /// Return the maximum number of sources for which AST structures should be
+  /// kept in the cache.
+  ///
+  /// DEPRECATED: This setting no longer has any effect.
   @deprecated
   int get cacheSize;
 
-  /*
-   * A flag indicating whether to run checks on AndroidManifest.xml file to
-   * see if it is complaint with Chrome OS.
-   */
+  /// A flag indicating whether to run checks on AndroidManifest.xml file to
+  /// see if it is complaint with Chrome OS.
   bool get chromeOsManifestChecks;
 
-  /**
-   * Return `true` if analysis is to generate dart2js related hint results.
-   */
+  /// The set of features that are globally enabled for this context.
+  FeatureSet get contextFeatures;
+
+  /// Return `true` if analysis is to generate dart2js related hint results.
   bool get dart2jsHint;
 
-  /**
-   * Return `true` if cache flushing should be disabled.  Setting this option to
-   * `true` can improve analysis speed at the expense of memory usage.  It may
-   * also be useful for working around bugs.
-   *
-   * This option should not be used when the analyzer is part of a long running
-   * process (such as the analysis server) because it has the potential to
-   * prevent memory from being reclaimed.
-   */
+  /// Return `true` if cache flushing should be disabled.  Setting this option to
+  /// `true` can improve analysis speed at the expense of memory usage.  It may
+  /// also be useful for working around bugs.
+  ///
+  /// This option should not be used when the analyzer is part of a long running
+  /// process (such as the analysis server) because it has the potential to
+  /// prevent memory from being reclaimed.
   bool get disableCacheFlushing;
 
-  /**
-   * Return `true` if the parser is to parse asserts in the initializer list of
-   * a constructor.
-   */
+  /// Return `true` if the parser is to parse asserts in the initializer list of
+  /// a constructor.
   @deprecated
   bool get enableAssertInitializer;
 
-  /**
-   * Return `true` to enable custom assert messages (DEP 37).
-   */
+  /// Return `true` to enable custom assert messages (DEP 37).
   @deprecated
   bool get enableAssertMessage;
 
-  /**
-   * Return `true` to if analysis is to enable async support.
-   */
+  /// Return `true` to if analysis is to enable async support.
   @deprecated
   bool get enableAsync;
 
-  /**
-   * Return `true` to enable interface libraries (DEP 40).
-   */
+  /// Return `true` to enable interface libraries (DEP 40).
   @deprecated
   bool get enableConditionalDirectives;
 
-  /**
-   * Return a list containing the names of the experiments that are enabled in
-   * the context associated with these options.
-   *
-   * The process around these experiments is described in this
-   * [doc](https://github.com/dart-lang/sdk/blob/master/docs/process/experimental-flags.md).
-   */
+  /// Return a list containing the names of the experiments that are enabled in
+  /// the context associated with these options.
+  ///
+  /// The process around these experiments is described in this
+  /// [doc](https://github.com/dart-lang/sdk/blob/master/docs/process/experimental-flags.md).
   List<String> get enabledExperiments;
 
-  /**
-   * Return a list of the names of the packages for which, if they define a
-   * plugin, the plugin should be enabled.
-   */
+  /// Return a list of the names of the packages for which, if they define a
+  /// plugin, the plugin should be enabled.
   List<String> get enabledPluginNames;
 
-  /**
-   * Return `true` to enable generic methods (DEP 22).
-   */
+  /// Return `true` to enable generic methods (DEP 22).
   @deprecated
   bool get enableGenericMethods => null;
 
-  /**
-   * Return `true` if access to field formal parameters should be allowed in a
-   * constructor's initializer list.
-   */
+  /// Return `true` if access to field formal parameters should be allowed in a
+  /// constructor's initializer list.
   @deprecated
   bool get enableInitializingFormalAccess;
 
-  /**
-   * Return `true` to enable the lazy compound assignment operators '&&=' and
-   * '||='.
-   */
+  /// Return `true` to enable the lazy compound assignment operators '&&=' and
+  /// '||='.
   bool get enableLazyAssignmentOperators;
 
-  /**
-   * Return `true` if mixins are allowed to inherit from types other than
-   * Object, and are allowed to reference `super`.
-   */
+  /// Return `true` if mixins are allowed to inherit from types other than
+  /// Object, and are allowed to reference `super`.
   @deprecated
   bool get enableSuperMixins;
 
-  /**
-   * Return `true` if timing data should be gathered during execution.
-   */
+  /// Return `true` if timing data should be gathered during execution.
   bool get enableTiming;
 
-  /**
-   * Return `true` to enable the use of URIs in part-of directives.
-   */
+  /// Return `true` to enable the use of URIs in part-of directives.
   @deprecated
   bool get enableUriInPartOf;
 
-  /**
-   * Return a list of error processors that are to be used when reporting
-   * errors in some analysis context.
-   */
+  /// Return a list of error processors that are to be used when reporting
+  /// errors in some analysis context.
   List<ErrorProcessor> get errorProcessors;
 
-  /**
-   * Return a list of exclude patterns used to exclude some sources from
-   * analysis.
-   */
+  /// Return a list of exclude patterns used to exclude some sources from
+  /// analysis.
   List<String> get excludePatterns;
 
-  /**
-   * Return `true` if errors, warnings and hints should be generated for sources
-   * that are implicitly being analyzed. The default value is `true`.
-   */
+  /// Return `true` if errors, warnings and hints should be generated for sources
+  /// that are implicitly being analyzed. The default value is `true`.
   bool get generateImplicitErrors;
 
-  /**
-   * Return `true` if errors, warnings and hints should be generated for sources
-   * in the SDK. The default value is `false`.
-   */
+  /// Return `true` if errors, warnings and hints should be generated for sources
+  /// in the SDK. The default value is `false`.
   bool get generateSdkErrors;
 
-  /**
-   * Return `true` if analysis is to generate hint results (e.g. type inference
-   * based information and pub best practices).
-   */
+  /// Return `true` if analysis is to generate hint results (e.g. type inference
+  /// based information and pub best practices).
   bool get hint;
 
-  /**
-   * Return `true` if analysis is to generate lint warnings.
-   */
+  /// Return `true` if analysis is to generate lint warnings.
   bool get lint;
 
-  /**
-   * Return a list of the lint rules that are to be run in an analysis context
-   * if [lint] returns `true`.
-   */
+  /// Return a list of the lint rules that are to be run in an analysis context
+  /// if [lint] returns `true`.
   List<Linter> get lintRules;
 
-  /**
-   * A mapping from Dart SDK library name (e.g. "dart:core") to a list of paths
-   * to patch files that should be applied to the library.
-   */
+  /// A mapping from Dart SDK library name (e.g. "dart:core") to a list of paths
+  /// to patch files that should be applied to the library.
   Map<String, List<String>> get patchPaths;
 
-  /**
-   * Return `true` if analysis is to parse comments.
-   */
+  /// Return `true` if analysis is to parse comments.
   bool get preserveComments;
 
-  /**
-   * Return `true` if analyzer should enable the use of Dart 2.0 features.
-   *
-   * This getter is deprecated, and is hard-coded to always return true.
-   */
+  /// Return `true` if analyzer should enable the use of Dart 2.0 features.
+  ///
+  /// This getter is deprecated, and is hard-coded to always return true.
   @Deprecated(
       'This getter is deprecated and is hard-coded to always return true.')
   bool get previewDart2;
 
-  /**
-   * The version range for the SDK specified in `pubspec.yaml`, or `null` if
-   * there is no `pubspec.yaml` or if it does not contain an SDK range.
-   */
+  /// The version range for the SDK specified in `pubspec.yaml`, or `null` if
+  /// there is no `pubspec.yaml` or if it does not contain an SDK range.
   VersionConstraint get sdkVersionConstraint;
 
-  /**
-   * Return the opaque signature of the options.
-   *
-   * The length of the list is guaranteed to equal [signatureLength].
-   */
+  /// Return the opaque signature of the options.
+  ///
+  /// The length of the list is guaranteed to equal [signatureLength].
   Uint32List get signature;
 
-  /**
-   * Return `true` if strong mode analysis should be used.
-   *
-   * This getter is deprecated, and is hard-coded to always return true.
-   */
+  /// Return `true` if strong mode analysis should be used.
+  ///
+  /// This getter is deprecated, and is hard-coded to always return true.
   @Deprecated(
       'This getter is deprecated and is hard-coded to always return true.')
   bool get strongMode;
 
-  /**
-   * Return `true` if dependencies between computed results should be tracked
-   * by analysis cache.  This option should only be set to `false` if analysis
-   * is performed in such a way that none of the inputs is ever changed
-   * during the life time of the context.
-   */
+  /// Return `true` if dependencies between computed results should be tracked
+  /// by analysis cache.  This option should only be set to `false` if analysis
+  /// is performed in such a way that none of the inputs is ever changed
+  /// during the life time of the context.
   bool get trackCacheDependencies;
 
-  /**
-   * Return `true` if analyzer should use the Dart 2.0 Front End parser.
-   */
+  /// Return `true` if analyzer should use the Dart 2.0 Front End parser.
   bool get useFastaParser;
 
-  /**
-   * Reset the state of this set of analysis options to its original state.
-   */
+  /// Reset the state of this set of analysis options to its original state.
   void resetToDefaults();
 
-  /**
-   * Set the values of the cross-context options to match those in the given set
-   * of [options].
-   */
+  /// Set the values of the cross-context options to match those in the given set
+  /// of [options].
   @deprecated
   void setCrossContextOptionsFrom(AnalysisOptions options);
 
-  /**
-   * Determine whether two signatures returned by [signature] are equal.
-   */
+  /// Determine whether two signatures returned by [signature] are equal.
   static bool signaturesEqual(Uint32List a, Uint32List b) {
     assert(a.length == signatureLength);
     assert(b.length == signatureLength);
@@ -1263,40 +962,28 @@
   }
 }
 
-/**
- * A set of analysis options used to control the behavior of an analysis
- * context.
- */
+/// A set of analysis options used to control the behavior of an analysis
+/// context.
 class AnalysisOptionsImpl implements AnalysisOptions {
-  /**
-   * DEPRECATED: The maximum number of sources for which data should be kept in
-   * the cache.
-   *
-   * This constant no longer has any effect.
-   */
+  /// DEPRECATED: The maximum number of sources for which data should be kept in
+  /// the cache.
+  ///
+  /// This constant no longer has any effect.
   @deprecated
   static const int DEFAULT_CACHE_SIZE = 64;
 
-  /**
-   * The length of the list returned by [unlinkedSignature].
-   */
+  /// The length of the list returned by [unlinkedSignature].
   static const int unlinkedSignatureLength = 4;
 
-  /**
-   * A predicate indicating whether analysis is to parse and analyze function
-   * bodies.
-   */
+  /// A predicate indicating whether analysis is to parse and analyze function
+  /// bodies.
   AnalyzeFunctionBodiesPredicate _analyzeFunctionBodiesPredicate =
       _analyzeAllFunctionBodies;
 
-  /**
-   * The cached [unlinkedSignature].
-   */
+  /// The cached [unlinkedSignature].
   Uint32List _unlinkedSignature;
 
-  /**
-   * The cached [signature].
-   */
+  /// The cached [signature].
   Uint32List _signature;
 
   @override
@@ -1311,10 +998,7 @@
 
   List<String> _enabledExperiments = const <String>[];
 
-  /**
-   * Parsed [enabledExperiments].
-   */
-  ExperimentStatus _experimentStatus = ExperimentStatus();
+  ExperimentStatus _contextFeatures = ExperimentStatus();
 
   @override
   List<String> enabledPluginNames = const <String>[];
@@ -1325,15 +1009,11 @@
   @override
   bool enableTiming = false;
 
-  /**
-   * A list of error processors that are to be used when reporting errors in
-   * some analysis context.
-   */
+  /// A list of error processors that are to be used when reporting errors in
+  /// some analysis context.
   List<ErrorProcessor> _errorProcessors;
 
-  /**
-   * A list of exclude patterns used to exclude some sources from analysis.
-   */
+  /// A list of exclude patterns used to exclude some sources from analysis.
   List<String> _excludePatterns;
 
   @override
@@ -1348,10 +1028,8 @@
   @override
   bool lint = false;
 
-  /**
-   * The lint rules that are to be run in an analysis context if [lint] returns
-   * `true`.
-   */
+  /// The lint rules that are to be run in an analysis context if [lint] returns
+  /// `true`.
   List<Linter> _lintRules;
 
   Map<String, List<String>> patchPaths = {};
@@ -1359,11 +1037,9 @@
   @override
   bool preserveComments = true;
 
-  /**
-   * A flag indicating whether strong-mode inference hints should be
-   * used.  This flag is not exposed in the interface, and should be
-   * replaced by something more general.
-   */
+  /// A flag indicating whether strong-mode inference hints should be
+  /// used.  This flag is not exposed in the interface, and should be
+  /// replaced by something more general.
   // TODO(leafp): replace this with something more general
   bool strongModeHints = false;
 
@@ -1376,55 +1052,43 @@
   @override
   bool disableCacheFlushing = false;
 
-  /**
-   * A flag indicating whether implicit casts are allowed in [strongMode]
-   * (they are always allowed in Dart 1.0 mode).
-   *
-   * This option is experimental and subject to change.
-   */
+  /// A flag indicating whether implicit casts are allowed in [strongMode]
+  /// (they are always allowed in Dart 1.0 mode).
+  ///
+  /// This option is experimental and subject to change.
   bool implicitCasts = true;
 
-  /**
-   * A flag indicating whether implicit dynamic type is allowed, on by default.
-   *
-   * This flag can be used without necessarily enabling [strongMode], but it is
-   * designed with strong mode's type inference in mind. Without type inference,
-   * it will raise many errors. Also it does not provide type safety without
-   * strong mode.
-   *
-   * This option is experimental and subject to change.
-   */
+  /// A flag indicating whether implicit dynamic type is allowed, on by default.
+  ///
+  /// This flag can be used without necessarily enabling [strongMode], but it is
+  /// designed with strong mode's type inference in mind. Without type inference,
+  /// it will raise many errors. Also it does not provide type safety without
+  /// strong mode.
+  ///
+  /// This option is experimental and subject to change.
   bool implicitDynamic = true;
 
-  /**
-   * A flag indicating whether inference failures are allowed, off by default.
-   *
-   * This option is experimental and subject to change.
-   */
+  /// A flag indicating whether inference failures are allowed, off by default.
+  ///
+  /// This option is experimental and subject to change.
   bool strictInference = false;
 
-  /**
-   * Whether raw types (types without explicit type arguments, such as `List`)
-   * should be reported as potential problems.
-   * 
-   * Raw types are a common source of `dynamic` being introduced implicitly.
-   * This often leads to cast failures later on in the program.
-   */
+  /// Whether raw types (types without explicit type arguments, such as `List`)
+  /// should be reported as potential problems.
+  ///
+  /// Raw types are a common source of `dynamic` being introduced implicitly.
+  /// This often leads to cast failures later on in the program.
   bool strictRawTypes = false;
 
   @override
   bool chromeOsManifestChecks = false;
 
-  /**
-   * Initialize a newly created set of analysis options to have their default
-   * values.
-   */
+  /// Initialize a newly created set of analysis options to have their default
+  /// values.
   AnalysisOptionsImpl();
 
-  /**
-   * Initialize a newly created set of analysis options to have the same values
-   * as those in the given set of analysis [options].
-   */
+  /// Initialize a newly created set of analysis options to have the same values
+  /// as those in the given set of analysis [options].
   AnalysisOptionsImpl.from(AnalysisOptions options) {
     analyzeFunctionBodiesPredicate = options.analyzeFunctionBodiesPredicate;
     dart2jsHint = options.dart2jsHint;
@@ -1484,6 +1148,14 @@
     _analyzeFunctionBodiesPredicate = value;
   }
 
+  @override
+  FeatureSet get contextFeatures => _contextFeatures;
+
+  set contextFeatures(FeatureSet featureSet) {
+    _contextFeatures = featureSet;
+    _enabledExperiments = _contextFeatures.toStringList();
+  }
+
   @deprecated
   @override
   bool get enableAssertInitializer => true;
@@ -1505,9 +1177,7 @@
   @deprecated
   void set enableAsync(bool enable) {}
 
-  /**
-   * A flag indicating whether interface libraries are to be supported (DEP 40).
-   */
+  /// A flag indicating whether interface libraries are to be supported (DEP 40).
   bool get enableConditionalDirectives => true;
 
   @deprecated
@@ -1518,7 +1188,7 @@
 
   set enabledExperiments(List<String> enabledExperiments) {
     _enabledExperiments = enabledExperiments;
-    _experimentStatus = ExperimentStatus.fromStrings(enabledExperiments);
+    _contextFeatures = ExperimentStatus.fromStrings(enabledExperiments);
   }
 
   @override
@@ -1555,10 +1225,8 @@
   List<ErrorProcessor> get errorProcessors =>
       _errorProcessors ??= const <ErrorProcessor>[];
 
-  /**
-   * Set the list of error [processors] that are to be used when reporting
-   * errors in some analysis context.
-   */
+  /// Set the list of error [processors] that are to be used when reporting
+  /// errors in some analysis context.
   void set errorProcessors(List<ErrorProcessor> processors) {
     _errorProcessors = processors;
   }
@@ -1566,23 +1234,17 @@
   @override
   List<String> get excludePatterns => _excludePatterns ??= const <String>[];
 
-  /**
-   * Set the exclude patterns used to exclude some sources from analysis to
-   * those in the given list of [patterns].
-   */
+  /// Set the exclude patterns used to exclude some sources from analysis to
+  /// those in the given list of [patterns].
   void set excludePatterns(List<String> patterns) {
     _excludePatterns = patterns;
   }
 
-  /**
-   * The set of enabled experiments.
-   */
-  ExperimentStatus get experimentStatus => _experimentStatus;
+  /// The set of enabled experiments.
+  ExperimentStatus get experimentStatus => _contextFeatures;
 
-  /**
-   * Return `true` to enable mixin declarations.
-   * https://github.com/dart-lang/language/issues/12
-   */
+  /// Return `true` to enable mixin declarations.
+  /// https://github.com/dart-lang/language/issues/12
   @deprecated
   bool get isMixinSupportEnabled => true;
 
@@ -1592,10 +1254,8 @@
   @override
   List<Linter> get lintRules => _lintRules ??= const <Linter>[];
 
-  /**
-   * Set the lint rules that are to be run in an analysis context if [lint]
-   * returns `true`.
-   */
+  /// Set the lint rules that are to be run in an analysis context if [lint]
+  /// returns `true`.
   void set lintRules(List<Linter> rules) {
     _lintRules = rules;
   }
@@ -1665,11 +1325,9 @@
       "The strongMode field is deprecated, and shouldn't be assigned to")
   set strongMode(bool value) {}
 
-  /**
-   * Return the opaque signature of the options that affect unlinked data.
-   *
-   * The length of the list is guaranteed to equal [unlinkedSignatureLength].
-   */
+  /// Return the opaque signature of the options that affect unlinked data.
+  ///
+  /// The length of the list is guaranteed to equal [unlinkedSignatureLength].
   Uint32List get unlinkedSignature {
     if (_unlinkedSignature == null) {
       ApiSignature buffer = new ApiSignature();
@@ -1726,9 +1384,7 @@
     }
   }
 
-  /**
-   * Return whether the given lists of lints are equal.
-   */
+  /// Return whether the given lists of lints are equal.
   static bool compareLints(List<Linter> a, List<Linter> b) {
     if (a.length != b.length) {
       return false;
@@ -1741,175 +1397,129 @@
     return true;
   }
 
-  /**
-   * Predicate used for [analyzeFunctionBodiesPredicate] when
-   * [analyzeFunctionBodies] is set to `true`.
-   */
+  /// Predicate used for [analyzeFunctionBodiesPredicate] when
+  /// [analyzeFunctionBodies] is set to `true`.
   static bool _analyzeAllFunctionBodies(Source _) => true;
 
-  /**
-   * Predicate used for [analyzeFunctionBodiesPredicate] when
-   * [analyzeFunctionBodies] is set to `false`.
-   */
+  /// Predicate used for [analyzeFunctionBodiesPredicate] when
+  /// [analyzeFunctionBodies] is set to `false`.
   static bool _analyzeNoFunctionBodies(Source _) => false;
 }
 
-/**
- *
- */
+///
 class AnalysisResult {
-  /**
-   * The change notices associated with this result, or `null` if there were no
-   * changes and there is no more work to be done.
-   */
+  /// The change notices associated with this result, or `null` if there were no
+  /// changes and there is no more work to be done.
   final List<ChangeNotice> _notices;
 
-  /**
-   * The number of milliseconds required to determine which task was to be
-   * performed.
-   */
+  /// The number of milliseconds required to determine which task was to be
+  /// performed.
   final int getTime;
 
-  /**
-   * The name of the class of the task that was performed.
-   */
+  /// The name of the class of the task that was performed.
   final String taskClassName;
 
-  /**
-   * The number of milliseconds required to perform the task.
-   */
+  /// The number of milliseconds required to perform the task.
   final int performTime;
 
-  /**
-   * Initialize a newly created analysis result to have the given values. The
-   * [notices] is the change notices associated with this result. The [getTime]
-   * is the number of milliseconds required to determine which task was to be
-   * performed. The [taskClassName] is the name of the class of the task that
-   * was performed. The [performTime] is the number of milliseconds required to
-   * perform the task.
-   */
+  /// Initialize a newly created analysis result to have the given values. The
+  /// [notices] is the change notices associated with this result. The [getTime]
+  /// is the number of milliseconds required to determine which task was to be
+  /// performed. The [taskClassName] is the name of the class of the task that
+  /// was performed. The [performTime] is the number of milliseconds required to
+  /// perform the task.
   AnalysisResult(
       this._notices, this.getTime, this.taskClassName, this.performTime);
 
-  /**
-   * Return the change notices associated with this result, or `null` if there
-   * were no changes and there is no more work to be done.
-   */
+  /// Return the change notices associated with this result, or `null` if there
+  /// were no changes and there is no more work to be done.
   List<ChangeNotice> get changeNotices => _notices;
 
-  /**
-   * Return `true` if there is more to be performed after the task that was
-   * performed.
-   */
+  /// Return `true` if there is more to be performed after the task that was
+  /// performed.
   bool get hasMoreWork => _notices != null;
 }
 
-/**
- * Statistics about cache consistency validation.
- */
+/// Statistics about cache consistency validation.
 class CacheConsistencyValidationStatistics {
-  /**
-   * Number of sources which were changed, but the context was not notified
-   * about it, so this fact was detected only during cache consistency
-   * validation.
-   */
+  /// Number of sources which were changed, but the context was not notified
+  /// about it, so this fact was detected only during cache consistency
+  /// validation.
   int numOfChanged = 0;
 
-  /**
-   * Number of sources which stopped existing, but the context was not notified
-   * about it, so this fact was detected only during cache consistency
-   * validation.
-   */
+  /// Number of sources which stopped existing, but the context was not notified
+  /// about it, so this fact was detected only during cache consistency
+  /// validation.
   int numOfRemoved = 0;
 
-  /**
-   * Reset all counters.
-   */
+  /// Reset all counters.
   void reset() {
     numOfChanged = 0;
     numOfRemoved = 0;
   }
 }
 
-/**
- * Interface for cache consistency validation in an [InternalAnalysisContext].
- */
+/// Interface for cache consistency validation in an [InternalAnalysisContext].
 abstract class CacheConsistencyValidator {
-  /**
-   * Return sources for which the contexts needs to know modification times.
-   */
+  /// 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.
-   */
+  /// 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.
- */
+/// The possible states of cached data.
 class CacheState implements Comparable<CacheState> {
-  /**
-   * The data is not in the cache and the last time an attempt was made to
-   * compute the data an exception occurred, making it pointless to attempt to
-   * compute the data again.
-   *
-   * Valid Transitions:
-   * * [INVALID] if a source was modified that might cause the data to be
-   *   computable
-   */
+  /// The data is not in the cache and the last time an attempt was made to
+  /// compute the data an exception occurred, making it pointless to attempt to
+  /// compute the data again.
+  ///
+  /// Valid Transitions:
+  /// * [INVALID] if a source was modified that might cause the data to be
+  ///   computable
   static const CacheState ERROR = const CacheState('ERROR', 0);
 
-  /**
-   * The data is not in the cache because it was flushed from the cache in order
-   * to control memory usage. If the data is recomputed, results do not need to
-   * be reported.
-   *
-   * Valid Transitions:
-   * * [IN_PROCESS] if the data is being recomputed
-   * * [INVALID] if a source was modified that causes the data to need to be
-   *   recomputed
-   */
+  /// The data is not in the cache because it was flushed from the cache in order
+  /// to control memory usage. If the data is recomputed, results do not need to
+  /// be reported.
+  ///
+  /// Valid Transitions:
+  /// * [IN_PROCESS] if the data is being recomputed
+  /// * [INVALID] if a source was modified that causes the data to need to be
+  ///   recomputed
   static const CacheState FLUSHED = const CacheState('FLUSHED', 1);
 
-  /**
-   * The data might or might not be in the cache but is in the process of being
-   * recomputed.
-   *
-   * Valid Transitions:
-   * * [ERROR] if an exception occurred while trying to compute the data
-   * * [VALID] if the data was successfully computed and stored in the cache
-   */
+  /// The data might or might not be in the cache but is in the process of being
+  /// recomputed.
+  ///
+  /// Valid Transitions:
+  /// * [ERROR] if an exception occurred while trying to compute the data
+  /// * [VALID] if the data was successfully computed and stored in the cache
   static const CacheState IN_PROCESS = const CacheState('IN_PROCESS', 2);
 
-  /**
-   * The data is not in the cache and needs to be recomputed so that results can
-   * be reported.
-   *
-   * Valid Transitions:
-   * * [IN_PROCESS] if an attempt is being made to recompute the data
-   */
+  /// The data is not in the cache and needs to be recomputed so that results can
+  /// be reported.
+  ///
+  /// Valid Transitions:
+  /// * [IN_PROCESS] if an attempt is being made to recompute the data
   static const CacheState INVALID = const CacheState('INVALID', 3);
 
-  /**
-   * The data is in the cache and up-to-date.
-   *
-   * Valid Transitions:
-   * * [FLUSHED] if the data is removed in order to manage memory usage
-   * * [INVALID] if a source was modified in such a way as to invalidate the
-   *   previous data
-   */
+  /// The data is in the cache and up-to-date.
+  ///
+  /// Valid Transitions:
+  /// * [FLUSHED] if the data is removed in order to manage memory usage
+  /// * [INVALID] if a source was modified in such a way as to invalidate the
+  ///   previous data
   static const CacheState VALID = const CacheState('VALID', 4);
 
   static const List<CacheState> values = const [
@@ -1920,14 +1530,10 @@
     VALID
   ];
 
-  /**
-   * The name of this cache state.
-   */
+  /// The name of this cache state.
   final String name;
 
-  /**
-   * The ordinal value of the cache state.
-   */
+  /// The ordinal value of the cache state.
   final int ordinal;
 
   const CacheState(this.name, this.ordinal);
@@ -1942,70 +1548,48 @@
   String toString() => name;
 }
 
-/**
- * An object that represents a change to the analysis results associated with a
- * given source.
- */
+/// An object that represents a change to the analysis results associated with a
+/// given source.
 abstract class ChangeNotice implements AnalysisErrorInfo {
-  /**
-   * The parsed, but maybe not resolved Dart AST that changed as a result of
-   * the analysis, or `null` if the AST was not changed.
-   */
+  /// The parsed, but maybe not resolved Dart AST that changed as a result of
+  /// the analysis, or `null` if the AST was not changed.
   CompilationUnit get parsedDartUnit;
 
-  /**
-   * The fully resolved Dart AST that changed as a result of the analysis, or
-   * `null` if the AST was not changed.
-   */
+  /// The fully resolved Dart AST that changed as a result of the analysis, or
+  /// `null` if the AST was not changed.
   CompilationUnit get resolvedDartUnit;
 
-  /**
-   * Return the source for which the result is being reported.
-   */
+  /// Return the source for which the result is being reported.
   Source get source;
 }
 
-/**
- * An implementation of a [ChangeNotice].
- */
+/// An implementation of a [ChangeNotice].
 class ChangeNoticeImpl implements ChangeNotice {
-  /**
-   * The source for which the result is being reported.
-   */
+  /// The source for which the result is being reported.
   @override
   final Source source;
 
-  /**
-   * The parsed, but maybe not resolved Dart AST that changed as a result of
-   * the analysis, or `null` if the AST was not changed.
-   */
+  /// The parsed, but maybe not resolved Dart AST that changed as a result of
+  /// the analysis, or `null` if the AST was not changed.
   @override
   CompilationUnit parsedDartUnit;
 
-  /**
-   * The fully resolved Dart AST that changed as a result of the analysis, or
-   * `null` if the AST was not changed.
-   */
+  /// The fully resolved Dart AST that changed as a result of the analysis, or
+  /// `null` if the AST was not changed.
   @override
   CompilationUnit resolvedDartUnit;
 
-  /**
-   * The errors that changed as a result of the analysis, or `null` if errors
-   * were not changed.
-   */
+  /// The errors that changed as a result of the analysis, or `null` if errors
+  /// were not changed.
   List<AnalysisError> _errors;
 
-  /**
-   * The line information associated with the source, or `null` if errors were
-   * not changed.
-   */
+  /// The line information associated with the source, or `null` if errors were
+  /// not changed.
   LineInfo _lineInfo;
 
-  /**
-   * Initialize a newly created notice associated with the given source.
-   *
-   * @param source the source for which the change is being reported
-   */
+  /// Initialize a newly created notice associated with the given source.
+  ///
+  /// @param source the source for which the change is being reported
   ChangeNoticeImpl(this.source);
 
   @override
@@ -2014,10 +1598,8 @@
   @override
   LineInfo get lineInfo => _lineInfo;
 
-  /**
-   * Set the errors that changed as a result of the analysis to the given
-   * [errors] and set the line information to the given [lineInfo].
-   */
+  /// Set the errors that changed as a result of the analysis to the given
+  /// [errors] and set the line information to the given [lineInfo].
   void setErrors(List<AnalysisError> errors, LineInfo lineInfo) {
     this._errors = errors;
     this._lineInfo = lineInfo;
@@ -2031,61 +1613,43 @@
   String toString() => "Changes for ${source.fullName}";
 }
 
-/**
- * An indication of which sources have been added, changed, removed, or deleted.
- * In the case of a changed source, there are multiple ways of indicating the
- * nature of the change.
- *
- * No source should be added to the change set more than once, either with the
- * same or a different kind of change. It does not make sense, for example, for
- * a source to be both added and removed, and it is redundant for a source to be
- * marked as changed in its entirety and changed in some specific range.
- */
+/// An indication of which sources have been added, changed, removed, or deleted.
+/// In the case of a changed source, there are multiple ways of indicating the
+/// nature of the change.
+///
+/// No source should be added to the change set more than once, either with the
+/// same or a different kind of change. It does not make sense, for example, for
+/// a source to be both added and removed, and it is redundant for a source to be
+/// marked as changed in its entirety and changed in some specific range.
 class ChangeSet {
-  /**
-   * A list containing the sources that have been added.
-   */
+  /// A list containing the sources that have been added.
   final List<Source> addedSources = new List<Source>();
 
-  /**
-   * A list containing the sources that have been changed.
-   */
+  /// A list containing the sources that have been changed.
   final List<Source> changedSources = new List<Source>();
 
-  /**
-   * A table mapping the sources whose content has been changed to the current
-   * content of those sources.
-   */
+  /// A table mapping the sources whose content has been changed to the current
+  /// content of those sources.
   Map<Source, String> _changedContent = new HashMap<Source, String>();
 
-  /**
-   * A table mapping the sources whose content has been changed within a single
-   * range to the current content of those sources and information about the
-   * affected range.
-   */
+  /// A table mapping the sources whose content has been changed within a single
+  /// range to the current content of those sources and information about the
+  /// affected range.
   final HashMap<Source, ChangeSet_ContentChange> changedRanges =
       new HashMap<Source, ChangeSet_ContentChange>();
 
-  /**
-   * A list containing the sources that have been removed.
-   */
+  /// A list containing the sources that have been removed.
   final List<Source> removedSources = new List<Source>();
 
-  /**
-   * A list containing the source containers specifying additional sources that
-   * have been removed.
-   */
+  /// A list containing the source containers specifying additional sources that
+  /// have been removed.
   final List<SourceContainer> removedContainers = new List<SourceContainer>();
 
-  /**
-   * Return a table mapping the sources whose content has been changed to the
-   * current content of those sources.
-   */
+  /// Return a table mapping the sources whose content has been changed to the
+  /// current content of those sources.
   Map<Source, String> get changedContents => _changedContent;
 
-  /**
-   * Return `true` if this change set does not contain any changes.
-   */
+  /// Return `true` if this change set does not contain any changes.
   bool get isEmpty =>
       addedSources.isEmpty &&
       changedSources.isEmpty &&
@@ -2094,57 +1658,45 @@
       removedSources.isEmpty &&
       removedContainers.isEmpty;
 
-  /**
-   * Record that the specified [source] has been added and that its content is
-   * the default contents of the source.
-   */
+  /// Record that the specified [source] has been added and that its content is
+  /// the default contents of the source.
   void addedSource(Source source) {
     addedSources.add(source);
   }
 
-  /**
-   * Record that the specified [source] has been changed and that its content is
-   * the given [contents].
-   */
+  /// Record that the specified [source] has been changed and that its content is
+  /// the given [contents].
   void changedContent(Source source, String contents) {
     _changedContent[source] = contents;
   }
 
-  /**
-   * Record that the specified [source] has been changed and that its content is
-   * the given [contents]. The [offset] is the offset into the current contents.
-   * The [oldLength] is the number of characters in the original contents that
-   * were replaced. The [newLength] is the number of characters in the
-   * replacement text.
-   */
+  /// Record that the specified [source] has been changed and that its content is
+  /// the given [contents]. The [offset] is the offset into the current contents.
+  /// The [oldLength] is the number of characters in the original contents that
+  /// were replaced. The [newLength] is the number of characters in the
+  /// replacement text.
   void changedRange(Source source, String contents, int offset, int oldLength,
       int newLength) {
     changedRanges[source] =
         new ChangeSet_ContentChange(contents, offset, oldLength, newLength);
   }
 
-  /**
-   * Record that the specified [source] has been changed. If the content of the
-   * source was previously overridden, this has no effect (the content remains
-   * overridden). To cancel (or change) the override, use [changedContent]
-   * instead.
-   */
+  /// Record that the specified [source] has been changed. If the content of the
+  /// source was previously overridden, this has no effect (the content remains
+  /// overridden). To cancel (or change) the override, use [changedContent]
+  /// instead.
   void changedSource(Source source) {
     changedSources.add(source);
   }
 
-  /**
-   * Record that the specified source [container] has been removed.
-   */
+  /// Record that the specified source [container] has been removed.
   void removedContainer(SourceContainer container) {
     if (container != null) {
       removedContainers.add(container);
     }
   }
 
-  /**
-   * Record that the specified [source] has been removed.
-   */
+  /// Record that the specified [source] has been removed.
   void removedSource(Source source) {
     if (source != null) {
       removedSources.add(source);
@@ -2182,11 +1734,9 @@
     return buffer.toString();
   }
 
-  /**
-   * Append the given [sources] to the given [buffer], prefixed with the given
-   * [label] and a separator if [needsSeparator] is `true`. Return `true` if
-   * future lists of sources will need a separator.
-   */
+  /// Append the given [sources] to the given [buffer], prefixed with the given
+  /// [label] and a separator if [needsSeparator] is `true`. Return `true` if
+  /// future lists of sources will need a separator.
   bool _appendSources(StringBuffer buffer, List<Source> sources,
       bool needsSeparator, String label) {
     if (sources.isEmpty) {
@@ -2205,11 +1755,9 @@
     return true;
   }
 
-  /**
-   * Append the given [sources] to the given [builder], prefixed with the given
-   * [label] and a separator if [needsSeparator] is `true`. Return `true` if
-   * future lists of sources will need a separator.
-   */
+  /// Append the given [sources] to the given [builder], prefixed with the given
+  /// [label] and a separator if [needsSeparator] is `true`. Return `true` if
+  /// future lists of sources will need a separator.
   bool _appendSources2(StringBuffer buffer, Map<Source, dynamic> sources,
       bool needsSeparator, String label) {
     if (sources.isEmpty) {
@@ -2229,64 +1777,42 @@
   }
 }
 
-/**
- * A change to the content of a source.
- */
+/// A change to the content of a source.
 class ChangeSet_ContentChange {
-  /**
-   * The new contents of the source.
-   */
+  /// The new contents of the source.
   final String contents;
 
-  /**
-   * The offset into the current contents.
-   */
+  /// The offset into the current contents.
   final int offset;
 
-  /**
-   * The number of characters in the original contents that were replaced
-   */
+  /// The number of characters in the original contents that were replaced
   final int oldLength;
 
-  /**
-   * The number of characters in the replacement text.
-   */
+  /// The number of characters in the replacement text.
   final int newLength;
 
-  /**
-   * Initialize a newly created change object to represent a change to the
-   * content of a source. The [contents] is the new contents of the source. The
-   * [offset] is the offset into the current contents. The [oldLength] is the
-   * number of characters in the original contents that were replaced. The
-   * [newLength] is the number of characters in the replacement text.
-   */
+  /// Initialize a newly created change object to represent a change to the
+  /// content of a source. The [contents] is the new contents of the source. The
+  /// [offset] is the offset into the current contents. The [oldLength] is the
+  /// number of characters in the original contents that were replaced. The
+  /// [newLength] is the number of characters in the replacement text.
   ChangeSet_ContentChange(
       this.contents, this.offset, this.oldLength, this.newLength);
 }
 
-/**
- * [ComputedResult] describes a value computed for a [ResultDescriptor].
- */
+/// [ComputedResult] describes a value computed for a [ResultDescriptor].
 @deprecated
 class ComputedResult<V> {
-  /**
-   * The context in which the value was computed.
-   */
+  /// The context in which the value was computed.
   final AnalysisContext context;
 
-  /**
-   * The descriptor of the result which was computed.
-   */
+  /// The descriptor of the result which was computed.
   final ResultDescriptor<V> descriptor;
 
-  /**
-   * The target for which the result was computed.
-   */
+  /// The target for which the result was computed.
   final AnalysisTarget target;
 
-  /**
-   * The computed value.
-   */
+  /// The computed value.
   final V value;
 
   ComputedResult(this.context, this.descriptor, this.target, this.value);
@@ -2295,25 +1821,17 @@
   String toString() => 'Computed $descriptor of $target in $context';
 }
 
-/**
- * An event indicating when a source either starts or stops being implicitly
- * analyzed.
- */
+/// An event indicating when a source either starts or stops being implicitly
+/// analyzed.
 class ImplicitAnalysisEvent {
-  /**
-   * The source whose status has changed.
-   */
+  /// The source whose status has changed.
   final Source source;
 
-  /**
-   * A flag indicating whether the source is now being analyzed.
-   */
+  /// A flag indicating whether the source is now being analyzed.
   final bool isAnalyzed;
 
-  /**
-   * Initialize a newly created event to indicate that the given [source] has
-   * changed it status to match the [isAnalyzed] flag.
-   */
+  /// Initialize a newly created event to indicate that the given [source] has
+  /// changed it status to match the [isAnalyzed] flag.
   ImplicitAnalysisEvent(this.source, this.isAnalyzed);
 
   @override
@@ -2321,220 +1839,156 @@
       '${isAnalyzed ? '' : 'not '}analyzing ${source.fullName}';
 }
 
-/**
- * Additional behavior for an analysis context that is required by internal
- * users of the context.
- */
+/// Additional behavior for an analysis context that is required by internal
+/// users of the context.
 abstract class InternalAnalysisContext implements AnalysisContext {
-  /**
-   * A table mapping the sources known to the context to the information known
-   * about the source.
-   */
+  /// A table mapping the sources known to the context to the information known
+  /// about the source.
   AnalysisCache get analysisCache;
 
-  /**
-   * The cache consistency validator for this context.
-   */
+  /// 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.
-   */
+  /// 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.
   set contentCache(ContentCache value);
 
-  /**
-   * Get the [EmbedderYamlLocator] for this context.
-   */
+  /// Get the [EmbedderYamlLocator] for this context.
   @deprecated
   EmbedderYamlLocator get embedderYamlLocator;
 
-  /**
-   * Return a list of the explicit targets being analyzed by this context.
-   */
+  /// Return a list of the explicit targets being analyzed by this context.
   List<AnalysisTarget> get explicitTargets;
 
-  /**
-   * Return `true` if the context is active, i.e. is being analyzed now.
-   */
+  /// Return `true` if the context is active, i.e. is being analyzed now.
   bool get isActive;
 
-  /**
-   * Specify whether the context is active, i.e. is being analyzed now.
-   */
+  /// Specify whether the context is active, i.e. is being analyzed now.
   set isActive(bool value);
 
-  /**
-   * Return the [StreamController] reporting [InvalidatedResult]s for everything
-   * in this context's cache.
-   */
+  /// Return the [StreamController] reporting [InvalidatedResult]s for everything
+  /// in this context's cache.
   ReentrantSynchronousStream<InvalidatedResult> get onResultInvalidated;
 
-  /**
-   * Return a list containing all of the sources that have been marked as
-   * priority sources. Clients must not modify the returned list.
-   */
+  /// Return a list containing all of the sources that have been marked as
+  /// priority sources. Clients must not modify the returned list.
   List<Source> get prioritySources;
 
-  /**
-   * Return a list of the priority targets being analyzed by this context.
-   */
+  /// Return a list of the priority targets being analyzed by this context.
   List<AnalysisTarget> get priorityTargets;
 
-  /**
-   * The partition that contains analysis results that are not shared with other
-   * contexts.
-   */
+  /// The partition that contains analysis results that are not shared with other
+  /// contexts.
   CachePartition get privateAnalysisCachePartition;
 
-  /**
-   * Sets the [TypeProvider] for this context.
-   */
+  /// Sets the [TypeProvider] for this context.
   void set typeProvider(TypeProvider typeProvider);
 
-  /**
-   * A list of all [WorkManager]s used by this context.
-   */
+  /// A list of all [WorkManager]s used by this context.
   List<WorkManager> get workManagers;
 
-  /**
-   * This method is invoked when the state of the [result] of the [entry] is
-   * [CacheState.INVALID], so it is about to be computed.
-   *
-   * If the context knows how to provide the value, it sets the value into
-   * the [entry] with all required dependencies, and returns `true`.
-   *
-   * Otherwise, it returns `false` to indicate that the result should be
-   * computed as usually.
-   */
+  /// This method is invoked when the state of the [result] of the [entry] is
+  /// [CacheState.INVALID], so it is about to be computed.
+  ///
+  /// If the context knows how to provide the value, it sets the value into
+  /// the [entry] with all required dependencies, and returns `true`.
+  ///
+  /// Otherwise, it returns `false` to indicate that the result should be
+  /// computed as usually.
   bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result);
 
-  /**
-   * Return a list containing the sources of the libraries that are exported by
-   * the library with the given [source]. The list will be empty if the given
-   * source is invalid, if the given source does not represent a library, or if
-   * the library does not export any other libraries.
-   *
-   * Throws an [AnalysisException] if the exported libraries could not be
-   * computed.
-   */
+  /// Return a list containing the sources of the libraries that are exported by
+  /// the library with the given [source]. The list will be empty if the given
+  /// source is invalid, if the given source does not represent a library, or if
+  /// the library does not export any other libraries.
+  ///
+  /// Throws an [AnalysisException] if the exported libraries could not be
+  /// computed.
   List<Source> computeExportedLibraries(Source source);
 
-  /**
-   * Return a list containing the sources of the libraries that are imported by
-   * the library with the given [source]. The list will be empty if the given
-   * source is invalid, if the given source does not represent a library, or if
-   * the library does not import any other libraries.
-   *
-   * Throws an [AnalysisException] if the imported libraries could not be
-   * computed.
-   */
+  /// Return a list containing the sources of the libraries that are imported by
+  /// the library with the given [source]. The list will be empty if the given
+  /// source is invalid, if the given source does not represent a library, or if
+  /// the library does not import any other libraries.
+  ///
+  /// Throws an [AnalysisException] if the imported libraries could not be
+  /// computed.
   List<Source> computeImportedLibraries(Source source);
 
-  /**
-   * Return all the resolved [CompilationUnit]s for the given [source] if not
-   * flushed, otherwise return `null` and ensures that the [CompilationUnit]s
-   * will be eventually returned to the client from [performAnalysisTask].
-   */
+  /// Return all the resolved [CompilationUnit]s for the given [source] if not
+  /// flushed, otherwise return `null` and ensures that the [CompilationUnit]s
+  /// will be eventually returned to the client from [performAnalysisTask].
   List<CompilationUnit> ensureResolvedDartUnits(Source source);
 
-  /**
-   * Return the cache entry associated with the given [target].
-   */
+  /// Return the cache entry associated with the given [target].
   CacheEntry getCacheEntry(AnalysisTarget target);
 
-  /**
-   * Return context that owns the given [source].
-   */
+  /// Return context that owns the given [source].
   InternalAnalysisContext getContextFor(Source source);
 
-  /**
-   * Return a change notice for the given [source], creating one if one does not
-   * already exist.
-   */
+  /// Return a change notice for the given [source], creating one if one does not
+  /// already exist.
   ChangeNoticeImpl getNotice(Source source);
 
-  /**
-   * Return a namespace containing mappings for all of the public names defined
-   * by the given [library].
-   */
+  /// Return a namespace containing mappings for all of the public names defined
+  /// by the given [library].
   Namespace getPublicNamespace(LibraryElement library);
 
-  /**
-   * Respond to a change which has been made to the given [source] file.
-   * [originalContents] is the former contents of the file, and [newContents]
-   * is the updated contents.  If [notify] is true, a source changed event is
-   * triggered.
-   *
-   * Normally it should not be necessary for clients to call this function,
-   * since it will be automatically invoked in response to a call to
-   * [applyChanges] or [setContents].  However, if this analysis context is
-   * sharing its content cache with other contexts, then the client must
-   * manually update the content cache and call this function for each context.
-   *
-   * Return `true` if the change was significant to this context (i.e. [source]
-   * is either implicitly or explicitly analyzed by this context, and a change
-   * actually occurred).
-   */
+  /// Respond to a change which has been made to the given [source] file.
+  /// [originalContents] is the former contents of the file, and [newContents]
+  /// is the updated contents.  If [notify] is true, a source changed event is
+  /// triggered.
+  ///
+  /// Normally it should not be necessary for clients to call this function,
+  /// since it will be automatically invoked in response to a call to
+  /// [applyChanges] or [setContents].  However, if this analysis context is
+  /// sharing its content cache with other contexts, then the client must
+  /// manually update the content cache and call this function for each context.
+  ///
+  /// Return `true` if the change was significant to this context (i.e. [source]
+  /// is either implicitly or explicitly analyzed by this context, and a change
+  /// actually occurred).
   bool handleContentsChanged(
       Source source, String originalContents, String newContents, bool notify);
 
-  /**
-   * Given an [elementMap] mapping the source for the libraries represented by
-   * the corresponding elements to the elements representing the libraries,
-   * record those mappings.
-   */
+  /// Given an [elementMap] mapping the source for the libraries represented by
+  /// the corresponding elements to the elements representing the libraries,
+  /// record those mappings.
   void recordLibraryElements(Map<Source, LibraryElement> elementMap);
 
-  /**
-   * Return `true` if errors should be produced for the given [source].
-   */
+  /// Return `true` if errors should be produced for the given [source].
   bool shouldErrorsBeAnalyzed(Source source);
 
-  /**
-   * For testing only: flush all representations of the AST (both resolved and
-   * unresolved) for the given [source] out of the cache.
-   */
+  /// For testing only: flush all representations of the AST (both resolved and
+  /// unresolved) for the given [source] out of the cache.
   void test_flushAstStructures(Source source);
 
-  /**
-   * Visit all entries of the content cache.
-   */
+  /// Visit all entries of the content cache.
   void visitContentCache(ContentCacheVisitor visitor);
 }
 
-/**
- * An object that can be used to receive information about errors within the
- * analysis engine. Implementations usually write this information to a file,
- * but can also record the information for later use (such as during testing) or
- * even ignore the information.
- */
+/// An object that can be used to receive information about errors within the
+/// analysis engine. Implementations usually write this information to a file,
+/// but can also record the information for later use (such as during testing) or
+/// even ignore the information.
 abstract class Logger {
-  /**
-   * A logger that ignores all logging.
-   */
+  /// A logger that ignores all logging.
   static final Logger NULL = new NullLogger();
 
-  /**
-   * Log the given message as an error. The [message] is expected to be an
-   * explanation of why the error occurred or what it means. The [exception] is
-   * expected to be the reason for the error. At least one argument must be
-   * provided.
-   */
+  /// Log the given message as an error. The [message] is expected to be an
+  /// explanation of why the error occurred or what it means. The [exception] is
+  /// expected to be the reason for the error. At least one argument must be
+  /// provided.
   void logError(String message, [CaughtException exception]);
 
-  /**
-   * Log the given informational message. The [message] is expected to be an
-   * explanation of why the error occurred or what it means. The [exception] is
-   * expected to be the reason for the error.
-   */
+  /// Log the given informational message. The [message] is expected to be an
+  /// explanation of why the error occurred or what it means. The [exception] is
+  /// expected to be the reason for the error.
   void logInformation(String message, [CaughtException exception]);
 }
 
-/**
- * An implementation of [Logger] that does nothing.
- */
+/// An implementation of [Logger] that does nothing.
 class NullLogger implements Logger {
   @override
   void logError(String message, [CaughtException exception]) {}
@@ -2543,109 +1997,71 @@
   void logInformation(String message, [CaughtException exception]) {}
 }
 
-/**
- * An exception created when an analysis attempt fails because a source was
- * deleted between the time the analysis started and the time the results of the
- * analysis were ready to be recorded.
- */
+/// An exception created when an analysis attempt fails because a source was
+/// deleted between the time the analysis started and the time the results of the
+/// analysis were ready to be recorded.
 class ObsoleteSourceAnalysisException extends AnalysisException {
-  /**
-   * The source that was removed while it was being analyzed.
-   */
+  /// The source that was removed while it was being analyzed.
   Source _source;
 
-  /**
-   * Initialize a newly created exception to represent the removal of the given
-   * [source].
-   */
+  /// Initialize a newly created exception to represent the removal of the given
+  /// [source].
   ObsoleteSourceAnalysisException(Source source)
       : super(
             "The source '${source.fullName}' was removed while it was being analyzed") {
     this._source = source;
   }
 
-  /**
-   * Return the source that was removed while it was being analyzed.
-   */
+  /// Return the source that was removed while it was being analyzed.
   Source get source => _source;
 }
 
-/**
- * Container with global [AnalysisContext] performance statistics.
- */
+/// Container with global [AnalysisContext] performance statistics.
 class PerformanceStatistics {
-  /**
-   * The [PerformanceTag] for `package:analyzer`.
-   */
+  /// The [PerformanceTag] for `package:analyzer`.
   static PerformanceTag analyzer = new PerformanceTag('analyzer');
 
-  /**
-   * The [PerformanceTag] for time spent in reading files.
-   */
+  /// The [PerformanceTag] for time spent in reading files.
   static PerformanceTag io = analyzer.createChild('io');
 
-  /**
-   * The [PerformanceTag] for general phases of analysis.
-   */
+  /// The [PerformanceTag] for general phases of analysis.
   static PerformanceTag analysis = analyzer.createChild('analysis');
 
-  /**
-   * The [PerformanceTag] for time spent in scanning.
-   */
+  /// The [PerformanceTag] for time spent in scanning.
   static PerformanceTag scan = analyzer.createChild('scan');
 
-  /**
-   * The [PerformanceTag] for time spent in parsing.
-   */
+  /// The [PerformanceTag] for time spent in parsing.
   static PerformanceTag parse = analyzer.createChild('parse');
 
-  /**
-   * The [PerformanceTag] for time spent in resolving.
-   */
+  /// The [PerformanceTag] for time spent in resolving.
   static PerformanceTag resolve = new PerformanceTag('resolve');
 
-  /**
-   * The [PerformanceTag] for time spent in error verifier.
-   */
+  /// The [PerformanceTag] for time spent in error verifier.
   static PerformanceTag errors = analysis.createChild('errors');
 
-  /**
-   * The [PerformanceTag] for time spent in hints generator.
-   */
+  /// The [PerformanceTag] for time spent in hints generator.
   static PerformanceTag hints = analysis.createChild('hints');
 
-  /**
-   * The [PerformanceTag] for time spent in linting.
-   */
+  /// The [PerformanceTag] for time spent in linting.
   static PerformanceTag lints = analysis.createChild('lints');
 
-  /**
-   * The [PerformanceTag] for time spent computing cycles.
-   */
+  /// The [PerformanceTag] for time spent computing cycles.
   static PerformanceTag cycles = new PerformanceTag('cycles');
 
-  /**
-   * The [PerformanceTag] for time spent in summaries support.
-   */
+  /// The [PerformanceTag] for time spent in summaries support.
   static PerformanceTag summary = analyzer.createChild('summary');
 
-  /**
-   * Statistics about cache consistency validation.
-   */
+  /// Statistics about cache consistency validation.
   static final CacheConsistencyValidationStatistics
       cacheConsistencyValidationStatistics =
       new CacheConsistencyValidationStatistics();
 }
 
-/**
- * An visitor that removes any resolution information from an AST structure when
- * used to visit that structure.
- */
+/// An visitor that removes any resolution information from an AST structure when
+/// used to visit that structure.
 class ResolutionEraser extends GeneralizingAstVisitor<void> {
-  /**
-   * A flag indicating whether the elements associated with declarations should
-   * be erased.
-   */
+  /// A flag indicating whether the elements associated with declarations should
+  /// be erased.
   bool eraseDeclarations = true;
 
   @override
@@ -2767,9 +2183,7 @@
     super.visitSuperConstructorInvocation(node);
   }
 
-  /**
-   * Remove any resolution information from the given AST structure.
-   */
+  /// Remove any resolution information from the given AST structure.
   static void erase(AstNode node, {bool eraseDeclarations: true}) {
     ResolutionEraser eraser = new ResolutionEraser();
     eraser.eraseDeclarations = eraseDeclarations;
@@ -2777,48 +2191,32 @@
   }
 }
 
-/**
- * [ResultChangedEvent] describes a change to an analysis result.
- */
+/// [ResultChangedEvent] describes a change to an analysis result.
 class ResultChangedEvent<V> {
-  /**
-   * The context in which the result was changed.
-   */
+  /// The context in which the result was changed.
   final AnalysisContext context;
 
-  /**
-   * The target for which the result was changed.
-   */
+  /// The target for which the result was changed.
   final AnalysisTarget target;
 
-  /**
-   * The descriptor of the result which was changed.
-   */
+  /// The descriptor of the result which was changed.
   final ResultDescriptor<V> descriptor;
 
-  /**
-   * If the result [wasComputed], the new value of the result. If the result
-   * [wasInvalidated], the value of before it was invalidated, may be the
-   * default value if the result was flushed.
-   */
+  /// If the result [wasComputed], the new value of the result. If the result
+  /// [wasInvalidated], the value of before it was invalidated, may be the
+  /// default value if the result was flushed.
   final V value;
 
-  /**
-   * Is `true` if the result was computed, or `false` is is was invalidated.
-   */
+  /// Is `true` if the result was computed, or `false` is is was invalidated.
   final bool _wasComputed;
 
   ResultChangedEvent(this.context, this.target, this.descriptor, this.value,
       this._wasComputed);
 
-  /**
-   * Returns `true` if the result was computed.
-   */
+  /// Returns `true` if the result was computed.
   bool get wasComputed => _wasComputed;
 
-  /**
-   * Returns `true` if the result was invalidated.
-   */
+  /// Returns `true` if the result was invalidated.
   bool get wasInvalidated => !_wasComputed;
 
   @override
@@ -2828,34 +2226,24 @@
   }
 }
 
-/**
- * [SourcesChangedEvent] indicates which sources have been added, removed,
- * or whose contents have changed.
- */
+/// [SourcesChangedEvent] indicates which sources have been added, removed,
+/// or whose contents have changed.
 class SourcesChangedEvent {
-  /**
-   * The internal representation of what has changed. Clients should not access
-   * this field directly.
-   */
+  /// The internal representation of what has changed. Clients should not access
+  /// this field directly.
   final ChangeSet _changeSet;
 
-  /**
-   * Construct an instance representing the given changes.
-   */
+  /// Construct an instance representing the given changes.
   SourcesChangedEvent(ChangeSet changeSet) : _changeSet = changeSet;
 
-  /**
-   * Construct an instance representing a source content change.
-   */
+  /// Construct an instance representing a source content change.
   factory SourcesChangedEvent.changedContent(Source source, String contents) {
     ChangeSet changeSet = new ChangeSet();
     changeSet.changedContent(source, contents);
     return new SourcesChangedEvent(changeSet);
   }
 
-  /**
-   * Construct an instance representing a source content change.
-   */
+  /// Construct an instance representing a source content change.
   factory SourcesChangedEvent.changedRange(Source source, String contents,
       int offset, int oldLength, int newLength) {
     ChangeSet changeSet = new ChangeSet();
@@ -2863,9 +2251,7 @@
     return new SourcesChangedEvent(changeSet);
   }
 
-  /**
-   * Return the collection of sources for which content has changed.
-   */
+  /// Return the collection of sources for which content has changed.
   Iterable<Source> get changedSources {
     List<Source> changedSources = new List.from(_changeSet.changedSources);
     changedSources.addAll(_changeSet.changedContents.keys);
@@ -2873,14 +2259,10 @@
     return changedSources;
   }
 
-  /**
-   * Return `true` if any sources were added.
-   */
+  /// Return `true` if any sources were added.
   bool get wereSourcesAdded => _changeSet.addedSources.length > 0;
 
-  /**
-   * Return `true` if any sources were removed or deleted.
-   */
+  /// Return `true` if any sources were removed or deleted.
   bool get wereSourcesRemoved =>
       _changeSet.removedSources.length > 0 ||
       _changeSet.removedContainers.length > 0;
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 7f2f741..93bc24d 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -5,6 +5,7 @@
 import 'dart:collection';
 import "dart:math" as math;
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -14,12 +15,15 @@
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
+import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/error/literal_element_verifier.dart';
 import 'package:analyzer/src/error/pending_error.dart';
@@ -37,6 +41,16 @@
  */
 class ErrorVerifier extends RecursiveAstVisitor<void> {
   /**
+   * Properties on the object class which are safe to call on nullable types.
+   * 
+   * Note that this must include tear-offs.
+   *
+   * TODO(mfairhurst): Calculate these fields rather than hard-code them.
+   */
+  static final _objectPropertyNames =
+      Set.from(['hashCode', 'runtimeType', 'noSuchMethod', 'toString']);
+
+  /**
    * The error reporter by which errors will be reported.
    */
   final ErrorReporter _errorReporter;
@@ -278,7 +292,8 @@
   /// fixed.
   final bool disableConflictingGenericsCheck;
 
-  bool _isNonNullable = false;
+  /// The features enabled in the unit currently being checked for errors.
+  FeatureSet _featureSet;
 
   /**
    * Initialize a newly created error verifier.
@@ -330,6 +345,9 @@
     _enclosingClass = classElement;
   }
 
+  bool get _isNonNullable =>
+      _featureSet?.isEnabled(Feature.non_nullable) ?? false;
+
   @override
   void visitAnnotation(Annotation node) {
     _checkForInvalidAnnotationFromDeferredLibrary(node);
@@ -352,12 +370,14 @@
   @override
   void visitAssertInitializer(AssertInitializer node) {
     _checkForNonBoolExpression(node);
+    _checkForNullableDereference(node.condition);
     super.visitAssertInitializer(node);
   }
 
   @override
   void visitAssertStatement(AssertStatement node) {
     _checkForNonBoolExpression(node);
+    _checkForNullableDereference(node.condition);
     super.visitAssertStatement(node);
   }
 
@@ -400,9 +420,10 @@
       _checkForUseOfVoidResult(node.rightOperand);
       _checkForNullableDereference(node.leftOperand);
       _checkForNullableDereference(node.rightOperand);
-    } else if (type != TokenType.EQ_EQ &&
-        type != TokenType.BANG_EQ &&
-        type != TokenType.QUESTION_QUESTION) {
+    } else if (type == TokenType.EQ_EQ || type == TokenType.BANG_EQ) {
+      _checkForArgumentTypeNotAssignableForArgument(node.rightOperand,
+          promoteParameterToNullable: true);
+    } else if (type != TokenType.QUESTION_QUESTION) {
       _checkForArgumentTypeNotAssignableForArgument(node.rightOperand);
       _checkForNullableDereference(node.leftOperand);
     } else {
@@ -508,6 +529,7 @@
       _initializeInitialFieldElementsMap(_enclosingClass.fields);
       _checkForFinalNotInitializedInClass(members);
       _checkForBadFunctionUse(node);
+      _checkForWrongTypeParameterVarianceInSuperinterfaces();
       super.visitClassDeclaration(node);
     } finally {
       _isInNativeClass = false;
@@ -525,6 +547,7 @@
       _enclosingClass = AbstractClassElementImpl.getImpl(node.declaredElement);
       _checkClassInheritance(
           node, node.superclass, node.withClause, node.implementsClause);
+      _checkForWrongTypeParameterVarianceInSuperinterfaces();
     } finally {
       _enclosingClass = outerClassElement;
     }
@@ -543,11 +566,11 @@
 
   @override
   void visitCompilationUnit(CompilationUnit node) {
-    _isNonNullable = (node as CompilationUnitImpl).isNonNullable;
+    _featureSet = node.featureSet;
     _checkDuplicateUnitMembers(node);
     _checkForDeferredPrefixCollisions(node);
     super.visitCompilationUnit(node);
-    _isNonNullable = false;
+    _featureSet = null;
   }
 
   @override
@@ -745,6 +768,7 @@
   void visitFormalParameterList(FormalParameterList node) {
     _checkDuplicateDefinitionInParameterList(node);
     _checkUseOfCovariantInParameters(node);
+    _checkUseOfDefaultValuesInParameters(node);
     super.visitFormalParameterList(node);
   }
 
@@ -839,6 +863,8 @@
     }
     _checkForImplicitDynamicInvoke(node);
     _checkForNullableDereference(node.function);
+    _checkForMissingRequiredParam(
+        node.staticInvokeType, node.argumentList, node);
     super.visitFunctionExpressionInvocation(node);
   }
 
@@ -874,7 +900,7 @@
       }
 
       // TODO(paulberry): remove this once dartbug.com/28515 is fixed.
-      if (node.typeParameters != null) {
+      if (node.typeParameters != null && !AnalysisDriver.useSummary2) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.GENERIC_FUNCTION_TYPED_PARAM_UNSUPPORTED,
             node);
@@ -946,6 +972,8 @@
         _checkForConstOrNewWithAbstractClass(node, typeName, type);
         _checkForConstOrNewWithEnum(node, typeName, type);
         _checkForConstOrNewWithMixin(node, typeName, type);
+        _checkForMissingRequiredParam(
+            node.staticElement?.type, node.argumentList, node.constructorName);
         if (_isInConstInstanceCreation) {
           _checkForConstWithNonConst(node);
           _checkForConstWithUndefinedConstructor(
@@ -954,6 +982,7 @@
         } else {
           _checkForNewWithUndefinedConstructor(node, constructorName, typeName);
         }
+        _checkForListConstructor(node, type);
       }
       _checkForImplicitDynamicType(typeName);
       super.visitInstanceCreationExpression(node);
@@ -1045,6 +1074,9 @@
     }
     _checkTypeArguments(node);
     _checkForImplicitDynamicInvoke(node);
+    _checkForNullableDereference(methodName);
+    _checkForMissingRequiredParam(
+        node.staticInvokeType, node.argumentList, node.methodName);
     if (node.operator?.type != TokenType.QUESTION_PERIOD &&
         methodName.name != 'toString' &&
         methodName.name != 'noSuchMethod') {
@@ -1077,6 +1109,7 @@
 
       _initializeInitialFieldElementsMap(_enclosingClass.fields);
       _checkForFinalNotInitializedInClass(members);
+      _checkForWrongTypeParameterVarianceInSuperinterfaces();
       //      _checkForBadFunctionUse(node);
       super.visitMixinDeclaration(node);
     } finally {
@@ -1123,8 +1156,7 @@
     }
     String property = node.identifier.name;
     if (node.staticElement is ExecutableElement &&
-        property != 'hashCode' &&
-        property != 'runtimeType') {
+        !_objectPropertyNames.contains(property)) {
       _checkForNullableDereference(node.prefix);
     }
     super.visitPrefixedIdentifier(node);
@@ -1153,8 +1185,7 @@
     _checkForStaticAccessToInstanceMember(typeReference, propertyName);
     _checkForInstanceAccessToStaticMember(typeReference, propertyName);
     if (node.operator?.type != TokenType.QUESTION_PERIOD &&
-        propertyName.name != 'hashCode' &&
-        propertyName.name != 'runtimeType') {
+        !_objectPropertyNames.contains(propertyName.name)) {
       _checkForNullableDereference(node.target);
     }
     _checkForUnnecessaryNullAware(node.target, node.operator);
@@ -1164,6 +1195,11 @@
   @override
   void visitRedirectingConstructorInvocation(
       RedirectingConstructorInvocation node) {
+    DartType type =
+        resolutionMap.staticElementForConstructorReference(node)?.type;
+    if (type != null) {
+      _checkForMissingRequiredParam(type, node.argumentList, node);
+    }
     _isInConstructorInitializer = true;
     try {
       super.visitRedirectingConstructorInvocation(node);
@@ -1258,6 +1294,11 @@
 
   @override
   void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    DartType type =
+        resolutionMap.staticElementForConstructorReference(node)?.type;
+    if (type != null) {
+      _checkForMissingRequiredParam(type, node.argumentList, node);
+    }
     _isInConstructorInitializer = true;
     try {
       super.visitSuperConstructorInvocation(node);
@@ -1931,7 +1972,7 @@
     List<FieldElement> notInitFinalFields = <FieldElement>[];
     fieldElementsMap.forEach((FieldElement fieldElement, INIT_STATE state) {
       if (state == INIT_STATE.NOT_INIT) {
-        if (fieldElement.isFinal) {
+        if (fieldElement.isFinal && !fieldElement.isLate) {
           notInitFinalFields.add(fieldElement);
         }
       }
@@ -2071,8 +2112,8 @@
     FunctionType constructorType =
         resolutionMap.elementDeclaredByConstructorDeclaration(declaration).type;
     DartType constructorReturnType = constructorType.returnType;
-    if (!_typeSystem.isAssignableTo(
-        redirectedReturnType, constructorReturnType)) {
+    if (!_typeSystem.isAssignableTo(redirectedReturnType, constructorReturnType,
+        featureSet: _featureSet)) {
       _errorReporter.reportErrorForNode(
           StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE,
           redirectedConstructor,
@@ -2224,13 +2265,17 @@
    *
    * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
    */
-  void _checkForArgumentTypeNotAssignableForArgument(Expression argument) {
+  void _checkForArgumentTypeNotAssignableForArgument(Expression argument,
+      {bool promoteParameterToNullable = false}) {
     if (argument == null) {
       return;
     }
 
     ParameterElement staticParameterElement = argument.staticParameterElement;
     DartType staticParameterType = staticParameterElement?.type;
+    if (promoteParameterToNullable && staticParameterType != null) {
+      staticParameterType = _typeSystem.makeNullable(staticParameterType);
+    }
     _checkForArgumentTypeNotAssignableWithExpectedTypes(argument,
         staticParameterType, StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
   }
@@ -2291,10 +2336,16 @@
     if (expressionType == null) {
       return;
     }
-    if (_typeSystem.isAssignableTo(expressionType, type)) {
+    if (_typeSystem.isAssignableTo(expressionType, type,
+        featureSet: _featureSet)) {
       return;
     }
-    _errorReporter.reportErrorForNode(errorCode, expression, arguments);
+    if (expressionType.element == type.element) {
+      _errorReporter.reportErrorForNode(
+          StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, expression);
+    } else {
+      _errorReporter.reportErrorForNode(errorCode, expression, arguments);
+    }
   }
 
   bool _checkForAssignableExpression(
@@ -2310,7 +2361,8 @@
       DartType actualStaticType,
       DartType expectedStaticType,
       ErrorCode errorCode) {
-    if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) {
+    if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType,
+        featureSet: _featureSet)) {
       _errorReporter.reportTypeErrorForNode(
           errorCode, expression, [actualStaticType, expectedStaticType]);
       return false;
@@ -2531,8 +2583,8 @@
         _errorReporter.reportErrorForElement(
             CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, method, [
           _enclosingClass.displayName,
-          inherited.enclosingElement.displayName,
-          name
+          name,
+          inherited.enclosingElement.displayName
         ]);
       }
     }
@@ -3017,7 +3069,8 @@
           StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
           node.iterable,
           [iterableType, loopTypeName]);
-    } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) {
+    } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType,
+        featureSet: _featureSet)) {
       _errorReporter.reportTypeErrorForNode(
           StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
           node.iterable,
@@ -3191,7 +3244,8 @@
     if (staticType == null) {
       return;
     }
-    if (_typeSystem.isAssignableTo(staticType, fieldType)) {
+    if (_typeSystem.isAssignableTo(staticType, fieldType,
+        featureSet: _featureSet)) {
       return;
     }
     // report problem
@@ -3294,7 +3348,7 @@
               CompileTimeErrorCode.CONST_NOT_INITIALIZED,
               variable.name,
               [variable.name.name]);
-        } else {
+        } else if (!_isNonNullable || !variable.isLate) {
           _errorReporter.reportErrorForNode(
               StaticWarningCode.FINAL_NOT_INITIALIZED,
               variable.name,
@@ -3459,8 +3513,7 @@
     if (invokeType is FunctionType &&
         declaredType is FunctionType &&
         declaredType.typeFormals.isNotEmpty) {
-      Iterable<DartType> typeArgs =
-          FunctionTypeImpl.recoverTypeArguments(declaredType, invokeType);
+      List<DartType> typeArgs = node.typeArgumentTypes;
       if (typeArgs.any((t) => t.isDynamic)) {
         // Issue an error depending on what we're trying to call.
         Expression function = node.function;
@@ -3816,7 +3869,8 @@
     }
     DartType leftType = getStaticType(lhs);
     DartType rightType = getStaticType(assignment);
-    if (!_typeSystem.isAssignableTo(rightType, leftType)) {
+    if (!_typeSystem.isAssignableTo(rightType, leftType,
+        featureSet: _featureSet)) {
       _errorReporter.reportTypeErrorForNode(
           StaticTypeWarningCode.INVALID_ASSIGNMENT, rhs, [rightType, leftType]);
     }
@@ -3890,6 +3944,17 @@
     }
   }
 
+  void _checkForListConstructor(
+      InstanceCreationExpression node, InterfaceType type) {
+    if (node.argumentList.arguments.length == 1 &&
+        _isDartCoreList(type) &&
+        _typeSystem.isPotentiallyNonNullable(type.typeArguments[0])) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR_MISMATCH,
+          node.constructorName);
+    }
+  }
+
   /**
    * Verify that the elements of the given list [literal] are subtypes of the
    * list's static type.
@@ -3918,6 +3983,7 @@
       _checkForUseOfVoidResult,
       forList: true,
       elementType: listElementType,
+      featureSet: _featureSet,
     );
     for (CollectionElement element in literal.elements) {
       verifier.verify(element);
@@ -3953,6 +4019,7 @@
         forMap: true,
         mapKeyType: keyType,
         mapValueType: valueType,
+        featureSet: _featureSet,
       );
       for (CollectionElement element in literal.elements) {
         verifier.verify(element);
@@ -4027,7 +4094,8 @@
       // (if the getter is null, it is dynamic which is assignable to everything).
       if (setterType != null &&
           getterType != null &&
-          !_typeSystem.isAssignableTo(getterType, setterType)) {
+          !_typeSystem.isAssignableTo(getterType, setterType,
+              featureSet: _featureSet)) {
         _errorReporter.reportTypeErrorForNode(
             StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
             accessorDeclaration,
@@ -4100,6 +4168,24 @@
     }
   }
 
+  void _checkForMissingRequiredParam(
+      DartType type, ArgumentList argumentList, AstNode node) {
+    if (type is FunctionType) {
+      for (ParameterElement parameter in type.parameters) {
+        if (parameter.isRequiredNamed) {
+          String parameterName = parameter.name;
+          if (!RequiredConstantsComputer._containsNamedExpression(
+              argumentList, parameterName)) {
+            _errorReporter.reportErrorForNode(
+                CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT,
+                node,
+                [parameterName]);
+          }
+        }
+      }
+    }
+  }
+
   /**
    * Verify that the given function [body] does not contain return statements
    * that both have and do not have return values.
@@ -4210,8 +4296,11 @@
       if (!isSatisfied) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
-            mixinName.name,
-            [constraint.displayName]);
+            mixinName.name, [
+          mixinName.type.displayName,
+          _enclosingClass.supertype,
+          constraint.displayName
+        ]);
         return true;
       }
     }
@@ -4354,11 +4443,11 @@
   }
 
   void _checkForMustCallSuper(MethodDeclaration node) {
-    if (node.isStatic) {
+    if (node.isStatic || node.isAbstract) {
       return;
     }
     MethodElement element = _findOverriddenMemberThatMustCallSuper(node);
-    if (element != null) {
+    if (element != null && _hasConcreteSuperMethod(node)) {
       _InvocationCollector collector = new _InvocationCollector();
       node.accept(collector);
       if (!collector.superCalls.contains(element.name)) {
@@ -4476,7 +4565,8 @@
     if (!_checkForNullableDereference(condition) &&
         !_checkForUseOfVoidResult(condition) &&
         conditionType != null &&
-        !_typeSystem.isAssignableTo(conditionType, _boolType)) {
+        !_typeSystem.isAssignableTo(conditionType, _boolType,
+            featureSet: _featureSet)) {
       _errorReporter.reportErrorForNode(
           StaticTypeWarningCode.NON_BOOL_CONDITION, condition);
     }
@@ -4485,16 +4575,20 @@
   /**
    * Verify that the given [assertion] has either a 'bool' or '() -> bool'
    * condition.
-   *
-   * See [StaticTypeWarningCode.NON_BOOL_EXPRESSION].
    */
   void _checkForNonBoolExpression(Assertion assertion) {
     Expression expression = assertion.condition;
     DartType type = getStaticType(expression);
     if (type is InterfaceType) {
-      if (!_typeSystem.isAssignableTo(type, _boolType)) {
-        _errorReporter.reportErrorForNode(
-            StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression);
+      if (!_typeSystem.isAssignableTo(type, _boolType,
+          featureSet: _featureSet)) {
+        if (type.element == _boolType.element) {
+          _errorReporter.reportErrorForNode(
+              StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, expression);
+        } else {
+          _errorReporter.reportErrorForNode(
+              StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression);
+        }
       }
     } else if (type is FunctionType) {
       _errorReporter.reportErrorForNode(
@@ -4504,15 +4598,19 @@
 
   /**
    * Checks to ensure that the given [expression] is assignable to bool.
-   *
-   * See [StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION].
    */
   void _checkForNonBoolNegationExpression(Expression expression) {
     DartType conditionType = getStaticType(expression);
     if (conditionType != null &&
-        !_typeSystem.isAssignableTo(conditionType, _boolType)) {
-      _errorReporter.reportErrorForNode(
-          StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION, expression);
+        !_typeSystem.isAssignableTo(conditionType, _boolType,
+            featureSet: _featureSet)) {
+      if (conditionType.element == _boolType.element) {
+        _errorReporter.reportErrorForNode(
+            StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, expression);
+      } else {
+        _errorReporter.reportErrorForNode(
+            StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION, expression);
+      }
     }
   }
 
@@ -4590,15 +4688,13 @@
    * Check for illegal derefences of nullables, ie, "unchecked" usages of
    * nullable values. Note that *any* usage of a null value is an "unchecked"
    * usage, because proper checks will promote the type to a non-nullable value.
-   *
-   * See [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]
    */
   bool _checkForNullableDereference(Expression expression) {
     if (expression == null ||
         !_isNonNullable ||
         expression.staticType == null ||
-        (expression.staticType as TypeImpl).nullabilitySuffix !=
-            NullabilitySuffix.question) {
+        expression.staticType.isDynamic ||
+        !_typeSystem.isPotentiallyNullable(expression.staticType)) {
       return false;
     }
 
@@ -4759,6 +4855,17 @@
   /// or inferred type arguments. When that happens, it reports error code
   /// [StrongModeCode.STRICT_RAW_TYPE].
   void _checkForRawTypeName(TypeName node) {
+    AstNode parentEscapingTypeArguments(TypeName node) {
+      AstNode parent = node.parent;
+      while (parent is TypeArgumentList || parent is TypeName) {
+        if (parent.parent == null) {
+          return parent;
+        }
+        parent = parent.parent;
+      }
+      return parent;
+    }
+
     if (!_options.strictRawTypes || node == null) return;
     if (node.typeArguments != null) {
       // Type has explicit type arguments.
@@ -4766,8 +4873,17 @@
     }
     if (_isMissingTypeArguments(
         node, node.type, node.name.staticElement, null)) {
-      _errorReporter
-          .reportErrorForNode(HintCode.STRICT_RAW_TYPE, node, [node.type]);
+      AstNode unwrappedParent = parentEscapingTypeArguments(node);
+      if (unwrappedParent is AsExpression) {
+        _errorReporter.reportErrorForNode(
+            HintCode.STRICT_RAW_TYPE_IN_AS, node, [node.type]);
+      } else if (unwrappedParent is IsExpression) {
+        _errorReporter.reportErrorForNode(
+            HintCode.STRICT_RAW_TYPE_IN_IS, node, [node.type]);
+      } else {
+        _errorReporter
+            .reportErrorForNode(HintCode.STRICT_RAW_TYPE, node, [node.type]);
+      }
     }
   }
 
@@ -4943,10 +5059,8 @@
         _hiddenElements != null &&
         _hiddenElements.contains(node.staticElement) &&
         node.parent is! CommentReference) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION,
-          node,
-          [node.name]);
+      _errorReporter.reportError(new DiagnosticFactory()
+          .referencedBeforeDeclaration(_errorReporter.source, node));
     }
   }
 
@@ -5081,7 +5195,8 @@
       var checkWithType = (!_inAsync)
           ? fromType
           : _typeProvider.futureType.instantiate(<DartType>[fromType]);
-      if (_typeSystem.isAssignableTo(checkWithType, expectedType)) {
+      if (_typeSystem.isAssignableTo(checkWithType, expectedType,
+          featureSet: _featureSet)) {
         return;
       }
     }
@@ -5119,6 +5234,7 @@
         _checkForUseOfVoidResult,
         forSet: true,
         elementType: setElementType,
+        featureSet: _featureSet,
       );
       for (CollectionElement element in literal.elements) {
         verifier.verify(element);
@@ -5185,7 +5301,8 @@
     DartType caseType = getStaticType(caseExpression);
 
     // check types
-    if (!_typeSystem.isAssignableTo(expressionType, caseType)) {
+    if (!_typeSystem.isAssignableTo(expressionType, caseType,
+        featureSet: _featureSet)) {
       _errorReporter.reportErrorForNode(
           StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE,
           expression,
@@ -5234,7 +5351,7 @@
       return;
     }
     if (type is ParameterizedType) {
-      var element = type.element;
+      var element = typeName.name.staticElement;
       // prepare type parameters
       List<TypeParameterElement> parameterElements;
       if (element is ClassElement) {
@@ -5246,6 +5363,8 @@
         // should be unnecessary.
         FunctionTypeAliasElement typedefElement = element.enclosingElement;
         parameterElements = typedefElement.typeParameters;
+      } else if (type is FunctionType) {
+        parameterElements = type.typeFormals;
       } else {
         // There are no other kinds of parameterized types.
         throw new UnimplementedError(
@@ -5509,7 +5628,8 @@
                 [parameter.identifier.name]);
           } else if (declaredType != null &&
               fieldType != null &&
-              !_typeSystem.isAssignableTo(declaredType, fieldType)) {
+              !_typeSystem.isAssignableTo(declaredType, fieldType,
+                  featureSet: _featureSet)) {
             _errorReporter.reportTypeErrorForNode(
                 StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE,
                 parameter,
@@ -5613,13 +5733,37 @@
     }
 
     NodeList<FormalParameter> parameters = parameterList.parameters;
-    if (parameters.length != 1 || !parameters[0].isRequired) {
+    if (parameters.length != 1 || !parameters[0].isRequiredPositional) {
       _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
           setterName);
     }
   }
 
+  void _checkForWrongTypeParameterVarianceInSuperinterfaces() {
+    void checkOne(DartType superInterface) {
+      if (superInterface != null) {
+        for (var typeParameter in _enclosingClass.typeParameters) {
+          var variance = computeVariance(typeParameter, superInterface);
+          if (variance == Variance.contravariant ||
+              variance == Variance.invariant) {
+            _errorReporter.reportErrorForElement(
+              CompileTimeErrorCode
+                  .WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+              typeParameter,
+              [typeParameter.name, superInterface],
+            );
+          }
+        }
+      }
+    }
+
+    checkOne(_enclosingClass.supertype);
+    _enclosingClass.interfaces.forEach(checkOne);
+    _enclosingClass.mixins.forEach(checkOne);
+    _enclosingClass.superclassConstraints.forEach(checkOne);
+  }
+
   /**
    * Check for a type mis-match between the yielded type and the declared
    * return type of a generator function.
@@ -5658,7 +5802,8 @@
       } else {
         requiredReturnType = _typeProvider.iterableDynamicType;
       }
-      if (!_typeSystem.isAssignableTo(impliedReturnType, requiredReturnType)) {
+      if (!_typeSystem.isAssignableTo(impliedReturnType, requiredReturnType,
+          featureSet: _featureSet)) {
         _errorReporter.reportTypeErrorForNode(
             StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
             yieldExpression,
@@ -5856,6 +6001,59 @@
     }
   }
 
+  void _checkUseOfDefaultValuesInParameters(FormalParameterList node) {
+    AstNode parent = node.parent;
+    if (parent is FieldFormalParameter ||
+        parent is FunctionTypeAlias ||
+        parent is FunctionTypedFormalParameter ||
+        parent is GenericFunctionType) {
+      // These locations are not allowed to have default values.
+      return;
+    }
+    NodeList<FormalParameter> parameters = node.parameters;
+    int length = parameters.length;
+    for (int i = 0; i < length; i++) {
+      FormalParameter parameter = parameters[i];
+      if (parameter.isOptional) {
+        DartType type = parameter.declaredElement.type;
+        if (type.isDartAsyncFutureOr) {
+          type = (type as ParameterizedType).typeArguments[0];
+        }
+        if ((parameter as DefaultFormalParameter).defaultValue == null) {
+          if (_typeSystem.isPotentiallyNonNullable(type)) {
+            SimpleIdentifier parameterName = _parameterName(parameter);
+            if (type is TypeParameterType) {
+              _errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode.INVALID_OPTIONAL_PARAMETER_TYPE,
+                  parameterName ?? parameter,
+                  [parameterName?.name ?? '?']);
+            } else {
+              _errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER,
+                  parameterName ?? parameter,
+                  [parameterName?.name ?? '?']);
+            }
+          }
+        } else if (!_typeSystem.isNonNullable(type) &&
+            _typeSystem.isPotentiallyNonNullable(type)) {
+          // If the type is both potentially non-nullable and not
+          // non-nullable, then it cannot be used for an optional parameter.
+          SimpleIdentifier parameterName = _parameterName(parameter);
+          _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.INVALID_OPTIONAL_PARAMETER_TYPE,
+              parameterName ?? parameter,
+              [parameterName?.name ?? '?']);
+        }
+      } else if (parameter.isRequiredNamed) {
+        if ((parameter as DefaultFormalParameter).defaultValue != null) {
+          _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER,
+              _parameterName(parameter) ?? parameter);
+        }
+      }
+    }
+  }
+
   InterfaceType _findInterfaceTypeForMixin(TypeName mixin,
       InterfaceType supertypeConstraint, List<InterfaceType> interfaceTypes) {
     var element = supertypeConstraint.element;
@@ -5901,20 +6099,40 @@
     return result;
   }
 
+  /// Find a method which is overridden by [node] and which is annotated with
+  /// `@mustCallSuper`.
+  ///
+  /// As per the definition of `mustCallSuper` [1], every method which overrides
+  /// a method annotated with `@mustCallSuper` is implicitly annotated with
+  /// `@mustCallSuper`.
+  ///
+  /// [1] https://pub.dartlang.org/documentation/meta/latest/meta/mustCallSuper-constant.html
   MethodElement _findOverriddenMemberThatMustCallSuper(MethodDeclaration node) {
-    ExecutableElement overriddenMember =
-        _getOverriddenMember(node.declaredElement);
-    List<ExecutableElement> seen = <ExecutableElement>[];
-    while (
-        overriddenMember is MethodElement && !seen.contains(overriddenMember)) {
-      for (ElementAnnotation annotation in overriddenMember.metadata) {
-        if (annotation.isMustCallSuper) {
-          return overriddenMember;
-        }
+    Element member = node.declaredElement;
+    ClassElement classElement = member.enclosingElement;
+    String name = member.name;
+
+    // Walk up the type hierarchy from [classElement], ignoring direct interfaces.
+    Queue<ClassElement> superclasses =
+        Queue.of(classElement.mixins.map((i) => i.element))
+          ..addAll(classElement.superclassConstraints.map((i) => i.element))
+          ..add(classElement.supertype?.element);
+    Set<ClassElement> visitedClasses = new Set<ClassElement>();
+    while (superclasses.isNotEmpty) {
+      ClassElement ancestor = superclasses.removeFirst();
+      if (ancestor == null || !visitedClasses.add(ancestor)) {
+        continue;
       }
-      seen.add(overriddenMember);
-      // Keep looking up the chain.
-      overriddenMember = _getOverriddenMember(overriddenMember);
+      ExecutableElement member = ancestor.getMethod(name) ??
+          ancestor.getGetter(name) ??
+          ancestor.getSetter(name);
+      if (member is MethodElement && member.hasMustCallSuper) {
+        return member;
+      }
+      superclasses
+        ..addAll(ancestor.mixins.map((i) => i.element))
+        ..addAll(ancestor.superclassConstraints.map((i) => i.element))
+        ..add(ancestor.supertype?.element);
     }
     return null;
   }
@@ -6021,23 +6239,6 @@
     return buffer.toString();
   }
 
-  ExecutableElement _getOverriddenMember(Element member) {
-    ClassElement classElement = member.enclosingElement;
-    String name = member.name;
-    ClassElement superclass = classElement.supertype?.element;
-    Set<ClassElement> visitedClasses = new Set<ClassElement>();
-    while (superclass != null && visitedClasses.add(superclass)) {
-      ExecutableElement member = superclass.getMethod(name) ??
-          superclass.getGetter(name) ??
-          superclass.getSetter(name);
-      if (member != null) {
-        return member;
-      }
-      superclass = superclass.supertype?.element;
-    }
-    return null;
-  }
-
   /**
    * Return the type of the first and only parameter of the given [setter].
    */
@@ -6051,6 +6252,19 @@
     return setterParameters[0].type;
   }
 
+  /// Returns whether [node] overrides a concrete method.
+  bool _hasConcreteSuperMethod(MethodDeclaration node) {
+    ClassElement classElement = node.declaredElement.enclosingElement;
+    String name = node.declaredElement.name;
+
+    Queue<ClassElement> superclasses =
+        Queue.of(classElement.mixins.map((i) => i.element))
+          ..addAll(classElement.superclassConstraints.map((i) => i.element))
+          ..add(classElement.supertype?.element);
+    return superclasses.any(
+        (parent) => parent.lookUpConcreteMethod(name, parent.library) != null);
+  }
+
   /**
    * Return `true` if the given [constructor] redirects to itself, directly or
    * indirectly.
@@ -6082,6 +6296,9 @@
     if (element == null) {
       return false;
     }
+    if (element is GenericTypeAliasElementImpl && element.linkedNode != null) {
+      return element.hasSelfReference;
+    }
     var visitor = new _HasTypedefSelfReferenceVisitor(element.function);
     element.accept(visitor);
     return visitor.hasSelfReference;
@@ -6099,6 +6316,14 @@
     }
   }
 
+  bool _isDartCoreList(InterfaceType type) {
+    ClassElement element = type.element;
+    if (element == null) {
+      return false;
+    }
+    return element.name == "List" && element.library.isDartCore;
+  }
+
   bool _isFunctionType(DartType type) {
     if (type.isDynamic || type.isDartCoreNull) {
       return true;
@@ -6204,6 +6429,17 @@
     return false;
   }
 
+  /// Return the name of the [parameter], or `null` if the parameter does not
+  /// have a name.
+  SimpleIdentifier _parameterName(FormalParameter parameter) {
+    if (parameter is NormalFormalParameter) {
+      return parameter.identifier;
+    } else if (parameter is DefaultFormalParameter) {
+      return parameter.parameter.identifier;
+    }
+    return null;
+  }
+
   /// Determines if the given [typeName] occurs in a context where super-bounded
   /// types are allowed.
   bool _shouldAllowSuperBoundedTypes(TypeName typeName) {
@@ -6418,7 +6654,7 @@
       DartType type, ArgumentList argumentList, AstNode node) {
     if (type is FunctionType) {
       for (ParameterElement parameter in type.parameters) {
-        if (parameter.isNamed) {
+        if (parameter.isOptionalNamed) {
           ElementAnnotationImpl annotation = _getRequiredAnnotation(parameter);
           if (annotation != null) {
             String parameterName = parameter.name;
@@ -6433,7 +6669,11 @@
     }
   }
 
-  bool _containsNamedExpression(ArgumentList args, String name) {
+  ElementAnnotationImpl _getRequiredAnnotation(ParameterElement param) => param
+      .metadata
+      .firstWhere((ElementAnnotation e) => e.isRequired, orElse: () => null);
+
+  static bool _containsNamedExpression(ArgumentList args, String name) {
     NodeList<Expression> arguments = args.arguments;
     for (int i = arguments.length - 1; i >= 0; i--) {
       Expression expression = arguments[i];
@@ -6445,10 +6685,6 @@
     }
     return false;
   }
-
-  ElementAnnotationImpl _getRequiredAnnotation(ParameterElement param) => param
-      .metadata
-      .firstWhere((ElementAnnotation e) => e.isRequired, orElse: () => null);
 }
 
 class _HasTypedefSelfReferenceVisitor extends GeneralizingElementVisitor<void> {
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 2055493..d494c4e 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 import "dart:math" as math;
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -194,18 +195,37 @@
 
   bool allowNativeClause;
 
+  FeatureSet _featureSet;
+
   /// Initialize a newly created parser to parse tokens in the given [_source]
   /// and to report any errors that are found to the given [_errorListener].
+  ///
+  /// In a future major version release of the analyzer, the [featureSet]
+  /// argument will be required.
   factory Parser(Source source, AnalysisErrorListener errorListener,
-      {bool useFasta}) {
+      {bool useFasta, FeatureSet featureSet}) {
     if (useFasta ?? Parser.useFasta) {
-      return new _Parser2(source, errorListener, allowNativeClause: true);
+      var parser = new _Parser2(source, errorListener, allowNativeClause: true);
+      if (featureSet != null) {
+        parser.configureFeatures(featureSet);
+      }
+      return parser;
     } else {
-      return new Parser.withoutFasta(source, errorListener);
+      return new Parser.withoutFasta(source, errorListener,
+          featureSet: featureSet);
     }
   }
 
-  Parser.withoutFasta(this._source, this._errorListener);
+  /// Creates a parser using the old (legacy) analyzer parsing logic.
+  ///
+  /// In a future major version release of the analyzer, the [featureSet]
+  /// argument will be required.
+  Parser.withoutFasta(this._source, this._errorListener,
+      {FeatureSet featureSet}) {
+    if (featureSet != null) {
+      _configureFeatures(featureSet);
+    }
+  }
 
   /// Return the current token.
   Token get currentToken => _currentToken;
@@ -226,6 +246,7 @@
   void set enableAssertInitializer(bool enable) {}
 
   /// Enables or disables parsing of control flow collections.
+  @Deprecated('Pass a FeatureSet to the constructor instead')
   void set enableControlFlowCollections(bool value) {
     if (value) {
       throw new UnimplementedError('control_flow_collections experiment'
@@ -234,6 +255,7 @@
   }
 
   /// Enables or disables non-nullable by default.
+  @Deprecated('Pass a FeatureSet to the constructor instead')
   void set enableNonNullable(bool value) {
     if (value) {
       throw new UnimplementedError(
@@ -258,6 +280,7 @@
   }
 
   /// Enables or disables parsing of spread collections.
+  @Deprecated('Pass a FeatureSet to the constructor instead')
   void set enableSpreadCollections(bool value) {
     if (value) {
       throw new UnimplementedError(
@@ -266,6 +289,7 @@
   }
 
   /// Enables or disables parsing of the triple shift operators.
+  @Deprecated('Pass a FeatureSet to the constructor instead')
   void set enableTripleShift(bool value) {
     if (value) {
       throw new UnimplementedError('triple_shift experiment'
@@ -339,6 +363,12 @@
     return buffer.toString();
   }
 
+  /// Configures the parser appropriately for the given [featureSet].
+  @Deprecated('Pass a FeatureSet to the constructor instead')
+  void configureFeatures(FeatureSet featureSet) {
+    _configureFeatures(featureSet);
+  }
+
   /// Return a synthetic identifier.
   SimpleIdentifier createSyntheticIdentifier({bool isDeclaration: false}) {
     Token syntheticToken;
@@ -1620,7 +1650,8 @@
     try {
       BooleanErrorListener listener = new BooleanErrorListener();
       Scanner scanner = new Scanner(
-          null, new SubSequenceReader(referenceSource, sourceOffset), listener);
+          null, new SubSequenceReader(referenceSource, sourceOffset), listener)
+        ..configureFeatures(_featureSet);
       scanner.setSourceStart(1, 1);
       Token firstToken = scanner.tokenize();
       if (listener.errorReported) {
@@ -1906,7 +1937,8 @@
         } on _TooDeepTreeError {
           _reportErrorForToken(ParserErrorCode.STACK_OVERFLOW, _currentToken);
           Token eof = new Token.eof(0);
-          return astFactory.compilationUnit(eof, null, null, null, eof);
+          return astFactory.compilationUnit2(
+              beginToken: eof, endToken: eof, featureSet: _featureSet);
         }
         if (member != null) {
           declarations.add(member);
@@ -1955,8 +1987,13 @@
 //        }
       }
     }
-    return astFactory.compilationUnit(
-        firstToken, scriptTag, directives, declarations, _currentToken);
+    return astFactory.compilationUnit2(
+        beginToken: firstToken,
+        scriptTag: scriptTag,
+        directives: directives,
+        declarations: declarations,
+        endToken: _currentToken,
+        featureSet: _featureSet);
   }
 
   /// Parse a compilation unit member. The [commentAndMetadata] is the metadata
@@ -2406,12 +2443,20 @@
         while (!_matches(TokenType.EOF)) {
           _advance();
         }
-        return astFactory.compilationUnit(
-            firstToken, scriptTag, directives, null, _currentToken);
+        return astFactory.compilationUnit2(
+            beginToken: firstToken,
+            scriptTag: scriptTag,
+            directives: directives,
+            endToken: _currentToken,
+            featureSet: _featureSet);
       }
     }
-    return astFactory.compilationUnit(
-        firstToken, scriptTag, directives, null, _currentToken);
+    return astFactory.compilationUnit2(
+        beginToken: firstToken,
+        scriptTag: scriptTag,
+        directives: directives,
+        endToken: _currentToken,
+        featureSet: _featureSet);
   }
 
   /// Parse a documentation comment based on the given list of documentation
@@ -5551,6 +5596,26 @@
     return false;
   }
 
+  void _configureFeatures(FeatureSet featureSet) {
+    if (featureSet.isEnabled(Feature.control_flow_collections)) {
+      throw new UnimplementedError('control_flow_collections experiment'
+          ' not supported by analyzer parser');
+    }
+    if (featureSet.isEnabled(Feature.non_nullable)) {
+      throw new UnimplementedError(
+          'non-nullable experiment not supported by analyzer parser');
+    }
+    if (featureSet.isEnabled(Feature.spread_collections)) {
+      throw new UnimplementedError(
+          'spread_collections experiment not supported by analyzer parser');
+    }
+    if (featureSet.isEnabled(Feature.triple_shift)) {
+      throw new UnimplementedError('triple_shift experiment'
+          ' not supported by analyzer parser');
+    }
+    _featureSet = featureSet;
+  }
+
   /// Convert the given [method] declaration into the nearest valid top-level
   /// function declaration (that is, the function declaration that most closely
   /// captures the components of the given method declaration).
@@ -6911,8 +6976,7 @@
   SimpleIdentifier _parseSimpleIdentifierUnchecked(
       {bool isDeclaration: false}) {
     String lexeme = _currentToken.lexeme;
-    if ((_inAsync || _inGenerator) &&
-        (lexeme == ASYNC || lexeme == _AWAIT || lexeme == _YIELD)) {
+    if ((_inAsync || _inGenerator) && (lexeme == _AWAIT || lexeme == _YIELD)) {
       _reportErrorForCurrentToken(
           ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER);
     }
diff --git a/pkg/analyzer/lib/src/generated/parser_fasta.dart b/pkg/analyzer/lib/src/generated/parser_fasta.dart
index d08aa89..f7c72e0 100644
--- a/pkg/analyzer/lib/src/generated/parser_fasta.dart
+++ b/pkg/analyzer/lib/src/generated/parser_fasta.dart
@@ -24,12 +24,15 @@
   final AstBuilder astBuilder;
 
   ParserAdapter(this.currentToken, ErrorReporter errorReporter, Uri fileUri,
-      {bool allowNativeClause: false})
+      {bool allowNativeClause: false, FeatureSet featureSet})
       : fastaParser = new fasta.Parser(null),
         astBuilder = new AstBuilder(errorReporter, fileUri, true) {
     fastaParser.listener = astBuilder;
     astBuilder.parser = fastaParser;
     astBuilder.allowNativeClause = allowNativeClause;
+    if (featureSet != null) {
+      astBuilder.configureFeatures(featureSet);
+    }
   }
 
   @override
@@ -108,6 +111,11 @@
   }
 
   @override
+  void configureFeatures(FeatureSet featureSet) {
+    astBuilder.configureFeatures(featureSet);
+  }
+
+  @override
   Expression parseAdditiveExpression() => parseExpression2();
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 9295e4f..b5b6b72 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -4,6 +4,7 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/ast_factory.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
@@ -26,6 +27,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/exit_detector.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/element_resolver.dart';
@@ -90,15 +92,6 @@
         InstanceCreationExpression instanceCreationExpression =
             astFactory.instanceCreationExpression(
                 _getKeyword(node), constructorName, node.argumentList);
-        InterfaceType type = getType(typeSystem, element, node.typeArguments);
-        ConstructorElement constructorElement =
-            type.lookUpConstructor(null, definingLibrary);
-        methodName.staticElement = element;
-        methodName.staticType = type;
-        typeName.type = type;
-        constructorName.staticElement = constructorElement;
-        instanceCreationExpression.staticType = type;
-        instanceCreationExpression.staticElement = constructorElement;
         NodeReplacer.replace(node, instanceCreationExpression);
       }
     } else if (target is SimpleIdentifier) {
@@ -128,17 +121,6 @@
               astFactory.instanceCreationExpression(
                   _getKeyword(node), constructorName, node.argumentList,
                   typeArguments: typeArguments);
-          InterfaceType type = getType(typeSystem, element, null);
-          constructorElement =
-              type.lookUpConstructor(methodName.name, definingLibrary);
-          methodName.staticElement = element;
-          methodName.staticType = type;
-          target.staticElement = element;
-          target.staticType = type; // TODO(scheglov) remove this
-          typeName.type = type;
-          constructorName.staticElement = constructorElement;
-          instanceCreationExpression.staticType = type;
-          instanceCreationExpression.staticElement = constructorElement;
           NodeReplacer.replace(node, instanceCreationExpression);
         }
       } else if (element is PrefixElement) {
@@ -158,16 +140,6 @@
           InstanceCreationExpression instanceCreationExpression =
               astFactory.instanceCreationExpression(
                   _getKeyword(node), constructorName, node.argumentList);
-          InterfaceType type =
-              getType(typeSystem, prefixedElement, node.typeArguments);
-          ConstructorElement constructorElement =
-              type.lookUpConstructor(null, definingLibrary);
-          methodName.staticElement = element;
-          methodName.staticType = type;
-          typeName.type = type;
-          constructorName.staticElement = constructorElement;
-          instanceCreationExpression.staticType = type;
-          instanceCreationExpression.staticElement = constructorElement;
           NodeReplacer.replace(node, instanceCreationExpression);
         }
       }
@@ -195,16 +167,6 @@
             InstanceCreationExpression instanceCreationExpression =
                 astFactory.instanceCreationExpression(
                     _getKeyword(node), constructorName, node.argumentList);
-            InterfaceType type = getType(typeSystem, element, typeArguments);
-            constructorElement =
-                type.lookUpConstructor(methodName.name, definingLibrary);
-            methodName.staticElement = element;
-            methodName.staticType = type;
-            target.identifier.staticElement = element;
-            typeName.type = type;
-            constructorName.staticElement = constructorElement;
-            instanceCreationExpression.staticType = type;
-            instanceCreationExpression.staticElement = constructorElement;
             NodeReplacer.replace(node, instanceCreationExpression);
           }
         }
@@ -298,7 +260,9 @@
   BestPracticesVerifier(
     this._errorReporter,
     TypeProvider typeProvider,
-    this._currentLibrary, {
+    this._currentLibrary,
+    CompilationUnit unit,
+    String content, {
     TypeSystem typeSystem,
     ResourceProvider resourceProvider,
     DeclaredVariables declaredVariables,
@@ -317,7 +281,7 @@
     _workspacePackage = workspace.findPackageFor(libraryPath);
     _linterContext = LinterContextImpl(
         null /* allUnits */,
-        null /* currentUnit */,
+        new LinterContextUnit(content, unit),
         declaredVariables,
         typeProvider,
         _typeSystem,
@@ -509,6 +473,14 @@
   }
 
   @override
+  void visitFunctionExpression(FunctionExpression node) {
+    if (node.parent is! FunctionDeclaration) {
+      _checkForMissingReturn(null, node.body, node.declaredElement, node);
+    }
+    super.visitFunctionExpression(node);
+  }
+
+  @override
   void visitImportDirective(ImportDirective node) {
     _checkForDeprecatedMemberUse(node.uriElement, node);
     ImportElement importElement = node.element;
@@ -743,15 +715,6 @@
       return false;
     }
 
-    bool isLibraryInWorkspacePackage(LibraryElement library) {
-      if (_workspacePackage == null || library == null) {
-        // Better to not make a big claim that they _are_ in the same package,
-        // if we were unable to determine what package [_currentLibrary] is in.
-        return false;
-      }
-      return _workspacePackage.contains(library.source.fullName);
-    }
-
     if (!_inDeprecatedMember &&
         element != null &&
         isDeprecated(element) &&
@@ -776,7 +739,7 @@
       }
       LibraryElement library =
           element is LibraryElement ? element : element.library;
-      HintCode hintCode = isLibraryInWorkspacePackage(library)
+      HintCode hintCode = _isLibraryInWorkspacePackage(library)
           ? HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
           : HintCode.DEPRECATED_MEMBER_USE;
       _errorReporter.reportErrorForNode(hintCode, node, [displayName]);
@@ -972,8 +935,7 @@
 
   void _checkForInvalidSealedSuperclass(NamedCompilationUnitMember node) {
     bool currentPackageContains(Element element) {
-      String elementLibraryPath = element.library.source.fullName;
-      return _workspacePackage.contains(elementLibraryPath);
+      return _isLibraryInWorkspacePackage(element.library);
     }
 
     // [NamedCompilationUnitMember.declaredElement] is not necessarily a
@@ -1080,7 +1042,27 @@
       var flattenedType =
           body.isAsynchronous ? _typeSystem.flatten(returnType) : returnType;
 
-      // dynamic/Null/void are allowed to omit a return.
+      // Function expressions without a return will have their return type set
+      // to `Null` regardless of their context type. So we need to figure out
+      // if a return type was expected from the original downwards context.
+      //
+      // This helps detect hint cases like `int Function() f = () {}`.
+      // See https://github.com/dart-lang/sdk/issues/28233 for context.
+      if (flattenedType.isDartCoreNull && functionNode is FunctionExpression) {
+        var contextType = InferenceContext.getContext(functionNode);
+        if (contextType is FunctionType) {
+          returnType = contextType.returnType;
+          flattenedType = body.isAsynchronous
+              ? returnType.flattenFutures(_typeSystem)
+              : returnType;
+        }
+      }
+
+      // dynamic, Null, void, and FutureOr<T> where T is (dynamic, Null, void)
+      // are allowed to omit a return.
+      if (flattenedType.isDartAsyncFutureOr) {
+        flattenedType = (flattenedType as InterfaceType).typeArguments[0];
+      }
       if (flattenedType.isDynamic ||
           flattenedType.isDartCoreNull ||
           flattenedType.isVoid) {
@@ -1278,6 +1260,15 @@
     }
   }
 
+  bool _isLibraryInWorkspacePackage(LibraryElement library) {
+    if (_workspacePackage == null || library == null) {
+      // Better to not make a big claim that they _are_ in the same package,
+      // if we were unable to determine what package [_currentLibrary] is in.
+      return false;
+    }
+    return _workspacePackage.contains(library.source);
+  }
+
   /// Check for the passed class declaration for the
   /// [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE] hint code.
   ///
@@ -1482,9 +1473,10 @@
   /// Initialize a newly created dead code verifier that will report dead code
   /// to the given [errorReporter] and will use the given [typeSystem] if one is
   /// provided.
-  DeadCodeVerifier(this._errorReporter, this._isNonNullableUnit,
+  DeadCodeVerifier(this._errorReporter, FeatureSet featureSet,
       {TypeSystem typeSystem})
-      : this._typeSystem = typeSystem ?? new Dart2TypeSystem(null);
+      : this._typeSystem = typeSystem ?? new Dart2TypeSystem(null),
+        _isNonNullableUnit = featureSet.isEnabled(Feature.non_nullable);
 
   @override
   void visitAssignmentExpression(AssignmentExpression node) {
@@ -3331,9 +3323,10 @@
       Source source,
       TypeProvider typeProvider,
       AnalysisErrorListener errorListener,
+      FeatureSet featureSet,
       {Scope nameScope})
       : super(inheritance, definingLibrary, source, typeProvider, errorListener,
-            nameScope: nameScope);
+            featureSet: featureSet, nameScope: nameScope);
 
   /// Resolve the instance fields in the given compilation unit [node].
   void resolveCompilationUnit(CompilationUnit node) {
@@ -3397,6 +3390,33 @@
   }
 }
 
+/// A type provider that returns non-nullable versions of the SDK types.
+class NonNullableTypeProvider extends TypeProviderImpl {
+  NonNullableTypeProvider(
+      LibraryElement coreLibrary, LibraryElement asyncLibrary)
+      : super(coreLibrary, asyncLibrary);
+
+  /// Return a type provider initialized from the same library elements as the
+  /// [baseProvider].
+  factory NonNullableTypeProvider.from(TypeProvider baseProvider) {
+    return NonNullableTypeProvider(baseProvider.boolType.element.library,
+        baseProvider.streamType.element.library);
+  }
+
+  @override
+  DartType get bottomType => BottomTypeImpl.instance;
+
+  @override
+  InterfaceType _getType(Namespace namespace, String typeName) {
+    InterfaceType type = super._getType(namespace, typeName);
+    if (type == null) {
+      return null;
+    }
+    return (type as TypeImpl).withNullability(NullabilitySuffix.none)
+        as InterfaceType;
+  }
+}
+
 /// 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.
@@ -3509,9 +3529,10 @@
       Source source,
       TypeProvider typeProvider,
       AnalysisErrorListener errorListener,
+      FeatureSet featureSet,
       {Scope nameScope})
       : super(inheritance, definingLibrary, source, typeProvider, errorListener,
-            nameScope: nameScope);
+            featureSet: featureSet, nameScope: nameScope);
 
   @override
   void visitBlockFunctionBody(BlockFunctionBody node) {
@@ -3641,8 +3662,10 @@
   /// message associated with the error will be created from the given [message]
   /// template. The correction associated with the error will be created from
   /// the given [correction] template.
-  const ResolverErrorCode(String name, String message, {String correction})
-      : super.temporary(name, message, correction: correction);
+  const ResolverErrorCode(String name, String message,
+      {String correction, bool hasPublishedDocs})
+      : super.temporary(name, message,
+            correction: correction, hasPublishedDocs: hasPublishedDocs);
 
   @override
   ErrorSeverity get errorSeverity => type.severity;
@@ -3661,6 +3684,8 @@
 
   final AnalysisOptionsImpl _analysisOptions;
 
+  final bool _uiAsCodeEnabled;
+
   /// The object used to resolve the element associated with the current node.
   ElementResolver elementResolver;
 
@@ -3718,16 +3743,45 @@
   /// the node that will first be visited.  If `null` or unspecified, a new
   /// [LibraryScope] will be created based on [definingLibrary] and
   /// [typeProvider].
+  ///
+  /// TODO(paulberry): make [featureSet] a required parameter (this will be a
+  /// breaking change).
   ResolverVisitor(
+      InheritanceManager2 inheritance,
+      LibraryElement definingLibrary,
+      Source source,
+      TypeProvider typeProvider,
+      AnalysisErrorListener errorListener,
+      {FeatureSet featureSet,
+      Scope nameScope,
+      bool propagateTypes: true,
+      reportConstEvaluationErrors: true})
+      : this._(
+            inheritance,
+            definingLibrary,
+            source,
+            typeProvider,
+            errorListener,
+            featureSet ??
+                definingLibrary.context.analysisOptions.contextFeatures,
+            nameScope,
+            propagateTypes,
+            reportConstEvaluationErrors);
+
+  ResolverVisitor._(
       this.inheritance,
       LibraryElement definingLibrary,
       Source source,
       TypeProvider typeProvider,
       AnalysisErrorListener errorListener,
-      {Scope nameScope,
-      bool propagateTypes: true,
-      reportConstEvaluationErrors: true})
+      FeatureSet featureSet,
+      Scope nameScope,
+      bool propagateTypes,
+      reportConstEvaluationErrors)
       : _analysisOptions = definingLibrary.context.analysisOptions,
+        _uiAsCodeEnabled =
+            featureSet.isEnabled(Feature.control_flow_collections) ||
+                featureSet.isEnabled(Feature.spread_collections),
         super(definingLibrary, source, typeProvider, errorListener,
             nameScope: nameScope) {
     this.elementResolver = new ElementResolver(this,
@@ -3740,7 +3794,7 @@
     }
     this.inferenceContext = new InferenceContext._(
         typeProvider, typeSystem, strongModeHints, errorReporter);
-    this.typeAnalyzer = new StaticTypeAnalyzer(this);
+    this.typeAnalyzer = new StaticTypeAnalyzer(this, featureSet);
   }
 
   /// Return the element representing the function containing the current node,
@@ -3851,6 +3905,11 @@
     // TODO(brianwilkerson) Remove this method.
   }
 
+  /// Set the enclosing function body when partial AST is resolved.
+  void prepareCurrentFunctionBody(FunctionBody body) {
+    _currentFunctionBody = body;
+  }
+
   /// Set information about enclosing declarations.
   void prepareEnclosingDeclarations({
     ClassElement enclosingClassElement,
@@ -4806,8 +4865,7 @@
             typeProvider.iterableType.instantiate([elementType]);
         _pushCollectionTypesDownToAll(node.elements,
             elementType: elementType, iterableType: iterableType);
-        if (!_analysisOptions.experimentStatus.spread_collections &&
-            !_analysisOptions.experimentStatus.control_flow_collections &&
+        if (!_uiAsCodeEnabled &&
             node.elements.isEmpty &&
             node.typeArguments == null &&
             node.isMap) {
@@ -5429,7 +5487,7 @@
     int length = parameters.length;
     for (int i = 0; i < length; i++) {
       ParameterElement parameter = parameters[i];
-      if (parameter.isNotOptional) {
+      if (parameter.isRequiredPositional) {
         unnamedParameters.add(parameter);
         unnamedParameterCount++;
         requiredParameterCount++;
@@ -5948,8 +6006,7 @@
             new CaughtException(new AnalysisException(), null));
       } else {
         nameScope = new EnclosedScope(nameScope);
-        GenericFunctionTypeElement typeElement = parameterElement.type.element;
-        List<TypeParameterElement> typeParameters = typeElement.typeParameters;
+        var typeParameters = parameterElement.typeParameters;
         int length = typeParameters.length;
         for (int i = 0; i < length; i++) {
           nameScope.define(typeParameters[i]);
@@ -5970,7 +6027,8 @@
       super.visitGenericFunctionType(node);
       return;
     }
-    GenericFunctionTypeElement element = type.element;
+    GenericFunctionTypeElement element =
+        (node as GenericFunctionTypeImpl).declaredElement;
     Scope outerScope = nameScope;
     try {
       if (element == null) {
@@ -6256,7 +6314,6 @@
 class TypeNameResolver {
   final TypeSystem typeSystem;
   final DartType dynamicType;
-  final DartType undefinedType;
   final bool isNonNullableUnit;
   final AnalysisOptionsImpl analysisOptions;
   final LibraryElement definingLibrary;
@@ -6281,7 +6338,6 @@
       this.errorListener,
       {this.shouldUseWithClauseInferredTypes: true})
       : dynamicType = typeProvider.dynamicType,
-        undefinedType = typeProvider.undefinedType,
         analysisOptions = definingLibrary.context.analysisOptions;
 
   /// Report an error with the given error code and arguments.
@@ -6323,8 +6379,8 @@
         return;
       }
       if (nameScope.shouldIgnoreUndefined(typeName)) {
-        typeName.staticType = undefinedType;
-        node.type = undefinedType;
+        typeName.staticType = dynamicType;
+        node.type = dynamicType;
         return;
       }
       //
@@ -6344,8 +6400,8 @@
           element = nameScope.lookup(prefix, definingLibrary);
           if (element is PrefixElement) {
             if (nameScope.shouldIgnoreUndefined(typeName)) {
-              typeName.staticType = undefinedType;
-              node.type = undefinedType;
+              typeName.staticType = dynamicType;
+              node.type = dynamicType;
               return;
             }
             AstNode grandParent = parent.parent;
@@ -6383,8 +6439,8 @@
         }
       }
       if (nameScope.shouldIgnoreUndefined(typeName)) {
-        typeName.staticType = undefinedType;
-        node.type = undefinedType;
+        typeName.staticType = dynamicType;
+        node.type = dynamicType;
         return;
       }
     }
@@ -6501,8 +6557,8 @@
       if (element is MultiplyDefinedElement) {
         _setElement(typeName, element);
       }
-      typeName.staticType = undefinedType;
-      node.type = undefinedType;
+      typeName.staticType = dynamicType;
+      node.type = dynamicType;
       return;
     }
 
@@ -6515,6 +6571,9 @@
     if (element == DynamicElementImpl.instance) {
       _setElement(typeName, element);
       type = DynamicTypeImpl.instance;
+    } else if (element is NeverElementImpl) {
+      _setElement(typeName, element);
+      type = element.type;
     } else if (element is FunctionTypeAliasElement) {
       _setElement(typeName, element);
       type = element.type as TypeImpl;
@@ -6560,8 +6619,8 @@
         } else if (element is LocalVariableElement ||
             (element is FunctionElement &&
                 element.enclosingElement is ExecutableElement)) {
-          reportErrorForNode(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION,
-              typeName, [typeName.name]);
+          errorListener.onError(new DiagnosticFactory()
+              .referencedBeforeDeclaration(source, typeName, element: element));
         } else {
           reportErrorForNode(
               StaticWarningCode.NOT_A_TYPE, typeName, [typeName.name]);
@@ -6675,7 +6734,7 @@
   DartType _getType(TypeAnnotation annotation) {
     DartType type = annotation.type;
     if (type == null) {
-      return undefinedType;
+      return dynamicType;
     }
     return type;
   }
@@ -6860,7 +6919,11 @@
       if (node.question != null) {
         _reportInvalidNullableType(node);
       }
-      nullabilitySuffix = NullabilitySuffix.none;
+      if (isNonNullableUnit) {
+        nullabilitySuffix = NullabilitySuffix.none;
+      } else {
+        nullabilitySuffix = NullabilitySuffix.star;
+      }
     } else {
       nullabilitySuffix = _getNullability(node.question != null);
     }
@@ -6933,14 +6996,13 @@
   Scope libraryScope = null;
   TypeNameResolver typeNameResolver = null;
 
-  TypeParameterBoundsResolver(
-      this.typeSystem, this.library, this.source, this.errorListener,
-      {bool isNonNullableUnit = false})
+  TypeParameterBoundsResolver(this.typeSystem, this.library, this.source,
+      this.errorListener, FeatureSet featureSet)
       : libraryScope = new LibraryScope(library),
         typeNameResolver = new TypeNameResolver(
             typeSystem,
             typeSystem.typeProvider,
-            isNonNullableUnit,
+            featureSet.isEnabled(Feature.non_nullable),
             library,
             source,
             errorListener);
@@ -7193,7 +7255,7 @@
   InterfaceType get mapType;
 
   /// Return the type representing the built-in type 'Never'.
-  InterfaceType get neverType;
+  DartType get neverType;
 
   /// Return a list containing all of the types that cannot be either extended
   /// or implemented.
@@ -7232,9 +7294,6 @@
   /// Return the type representing the built-in type 'Type'.
   InterfaceType get typeType;
 
-  /// Return the type representing typenames that can't be resolved.
-  DartType get undefinedType;
-
   /// Return 'true' if [id] is the name of a getter on
   /// the Object type.
   bool isObjectGetter(String id);
@@ -7253,11 +7312,11 @@
 abstract class TypeProviderBase implements TypeProvider {
   @override
   List<InterfaceType> get nonSubtypableTypes => <InterfaceType>[
+        boolType,
+        doubleType,
+        intType,
         nullType,
         numType,
-        intType,
-        doubleType,
-        boolType,
         stringType
       ];
 
@@ -7286,18 +7345,12 @@
   /// The type representing the built-in type 'bool'.
   InterfaceType _boolType;
 
-  /// The type representing the type 'bottom'.
-  DartType _bottomType;
-
   /// The type representing the built-in type 'double'.
   InterfaceType _doubleType;
 
   /// The type representing the built-in type 'Deprecated'.
   InterfaceType _deprecatedType;
 
-  /// The type representing the built-in type 'dynamic'.
-  DartType _dynamicType;
-
   /// The type representing the built-in type 'Function'.
   InterfaceType _functionType;
 
@@ -7340,9 +7393,6 @@
   /// An shared object representing the value 'null'.
   DartObjectImpl _nullObject;
 
-  /// The type representing the type 'Never'.
-  InterfaceType _neverType;
-
   /// The type representing the type 'Null'.
   InterfaceType _nullType;
 
@@ -7373,20 +7423,24 @@
   /// The type representing the built-in type 'Type'.
   InterfaceType _typeType;
 
-  /// The type representing typenames that can't be resolved.
-  DartType _undefinedType;
-
   /// Initialize a newly created type provider to provide the types defined in
   /// the given [coreLibrary] and [asyncLibrary].
   TypeProviderImpl(LibraryElement coreLibrary, LibraryElement asyncLibrary) {
     _initializeFrom(coreLibrary, asyncLibrary);
   }
 
+  /// Return a type provider initialized from the same library elements as the
+  /// [baseProvider].
+  factory TypeProviderImpl.from(TypeProvider baseProvider) {
+    return TypeProviderImpl(baseProvider.boolType.element.library,
+        baseProvider.streamType.element.library);
+  }
+
   @override
   InterfaceType get boolType => _boolType;
 
   @override
-  DartType get bottomType => _bottomType;
+  DartType get bottomType => BottomTypeImpl.instanceLegacy;
 
   @override
   InterfaceType get deprecatedType => _deprecatedType;
@@ -7395,7 +7449,7 @@
   InterfaceType get doubleType => _doubleType;
 
   @override
-  DartType get dynamicType => _dynamicType;
+  DartType get dynamicType => DynamicTypeImpl.instance;
 
   @override
   InterfaceType get functionType => _functionType;
@@ -7437,7 +7491,7 @@
   InterfaceType get mapType => _mapType;
 
   @override
-  InterfaceType get neverType => _neverType;
+  DartType get neverType => BottomTypeImpl.instance;
 
   @override
   DartObjectImpl get nullObject {
@@ -7477,19 +7531,6 @@
   @override
   InterfaceType get typeType => _typeType;
 
-  @override
-  DartType get undefinedType => _undefinedType;
-
-  InterfaceType _createNever(Namespace namespace) {
-    // TODO(brianwilkerson) Remove this method when the class is defined in the
-    //  SDK.
-    CompilationUnitElement compilationUnit =
-        boolType.element.getAncestor((e) => e is CompilationUnitElement);
-    ClassElementImpl element = ElementFactory.classElement('Never', objectType);
-    element.enclosingElement = compilationUnit;
-    return element.type;
-  }
-
   /// Return the type with the given [typeName] from the given [namespace], or
   /// `null` if there is no class with the given name.
   InterfaceType _getType(Namespace namespace, String typeName) {
@@ -7512,10 +7553,8 @@
         new NamespaceBuilder().createPublicNamespaceForLibrary(asyncLibrary);
 
     _boolType = _getType(coreNamespace, 'bool');
-    _bottomType = BottomTypeImpl.instance;
     _deprecatedType = _getType(coreNamespace, 'Deprecated');
     _doubleType = _getType(coreNamespace, 'double');
-    _dynamicType = DynamicTypeImpl.instance;
     _functionType = _getType(coreNamespace, 'Function');
     _futureOrType = _getType(asyncNamespace, 'FutureOr');
     _futureType = _getType(asyncNamespace, 'Future');
@@ -7523,8 +7562,6 @@
     _iterableType = _getType(coreNamespace, 'Iterable');
     _listType = _getType(coreNamespace, 'List');
     _mapType = _getType(coreNamespace, 'Map');
-    _neverType =
-        _getType(coreNamespace, 'Never') ?? _createNever(coreNamespace);
     _nullType = _getType(coreNamespace, 'Null');
     _numType = _getType(coreNamespace, 'num');
     _objectType = _getType(coreNamespace, 'Object');
@@ -7534,14 +7571,13 @@
     _stringType = _getType(coreNamespace, 'String');
     _symbolType = _getType(coreNamespace, 'Symbol');
     _typeType = _getType(coreNamespace, 'Type');
-    _undefinedType = UndefinedTypeImpl.instance;
-    _futureDynamicType = _futureType.instantiate(<DartType>[_dynamicType]);
+    _futureDynamicType = _futureType.instantiate(<DartType>[dynamicType]);
     _futureNullType = _futureType.instantiate(<DartType>[_nullType]);
-    _iterableDynamicType = _iterableType.instantiate(<DartType>[_dynamicType]);
+    _iterableDynamicType = _iterableType.instantiate(<DartType>[dynamicType]);
     _iterableObjectType = _iterableType.instantiate(<DartType>[_objectType]);
     _mapObjectObjectType =
         _mapType.instantiate(<DartType>[_objectType, _objectType]);
-    _streamDynamicType = _streamType.instantiate(<DartType>[_dynamicType]);
+    _streamDynamicType = _streamType.instantiate(<DartType>[dynamicType]);
     // FutureOr<T> is still fairly new, so if we're analyzing an SDK that
     // doesn't have it yet, create an element for it.
     _futureOrType ??= createPlaceholderFutureOr(_futureType, _objectType);
@@ -7588,9 +7624,6 @@
   /// The type representing the type 'dynamic'.
   DartType _dynamicType;
 
-  /// The type representing typenames that can't be resolved.
-  DartType _undefinedType;
-
   /// The flag specifying if currently visited class references 'super'
   /// expression.
   bool _hasReferenceToSuper = false;
@@ -7636,20 +7669,26 @@
   /// [nameScope] is the scope used to resolve identifiers in the node that will
   /// first be visited.  If `null` or unspecified, a new [LibraryScope] will be
   /// created based on [definingLibrary] and [typeProvider].
+  ///
+  /// Note: in a future release of the analyzer, the [featureSet] parameter will
+  /// be required.
   TypeResolverVisitor(LibraryElement definingLibrary, Source source,
       TypeProvider typeProvider, AnalysisErrorListener errorListener,
       {Scope nameScope,
-      this.isNonNullableUnit: false,
+      @Deprecated('Use featureSet instead') bool isNonNullableUnit: false,
+      FeatureSet featureSet,
       this.mode: TypeResolverMode.everything,
       bool shouldUseWithClauseInferredTypes: true,
       this.shouldSetElementSupertypes: false})
-      : super(definingLibrary, source, typeProvider, errorListener,
+      : isNonNullableUnit = featureSet?.isEnabled(Feature.non_nullable) ??
+            // ignore: deprecated_member_use_from_same_package
+            isNonNullableUnit,
+        super(definingLibrary, source, typeProvider, errorListener,
             nameScope: nameScope) {
     _dynamicType = typeProvider.dynamicType;
-    _undefinedType = typeProvider.undefinedType;
     _typeSystem = TypeSystem.create(definingLibrary.context);
     _typeNameResolver = new TypeNameResolver(_typeSystem, typeProvider,
-        isNonNullableUnit, definingLibrary, source, errorListener,
+        this.isNonNullableUnit, definingLibrary, source, errorListener,
         shouldUseWithClauseInferredTypes: shouldUseWithClauseInferredTypes);
   }
 
@@ -7904,7 +7943,14 @@
 
   @override
   void visitGenericFunctionType(GenericFunctionType node) {
-    GenericFunctionTypeElementImpl element = node.type?.element;
+    GenericFunctionTypeElementImpl element =
+        (node as GenericFunctionTypeImpl).declaredElement;
+    if (node.type != null) {
+      var nullability =
+          _typeNameResolver._getNullability(node.question != null);
+      (node as GenericFunctionTypeImpl).type =
+          (node.type as TypeImpl).withNullability(nullability);
+    }
     if (element != null) {
       super.visitGenericFunctionType(node);
       element.returnType =
@@ -8316,7 +8362,10 @@
       TypeAnnotation returnType, FormalParameterList parameterList) {
     DartType type = parameter.type;
     GenericFunctionTypeElementImpl typeElement = type.element;
-    typeElement.returnType = _computeReturnType(returnType);
+    // With summary2 we use synthetic FunctionType(s).
+    if (typeElement != null) {
+      typeElement.returnType = _computeReturnType(returnType);
+    }
   }
 }
 
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index 9f8c00a..86ef733 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -7,6 +7,7 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/src/context/context.dart';
@@ -277,9 +278,13 @@
    */
   LibraryMap readFromSource(Source source, String libraryFileContents) {
     BooleanErrorListener errorListener = new BooleanErrorListener();
+    // TODO(paulberry): initialize the feature set appropriately based on the
+    // version of the SDK we are reading, and enable flags.
+    var featureSet = FeatureSet.fromEnableFlags([]);
     Scanner scanner = new Scanner(
-        source, new CharSequenceReader(libraryFileContents), errorListener);
-    Parser parser = new Parser(source, errorListener);
+        source, new CharSequenceReader(libraryFileContents), errorListener)
+      ..configureFeatures(featureSet);
+    Parser parser = new Parser(source, errorListener, featureSet: featureSet);
     CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
     SdkLibrariesReader_LibraryBuilder libraryBuilder =
         new SdkLibrariesReader_LibraryBuilder(_useDart2jsPaths);
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 285df36..1ce52ef 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -4,22 +4,26 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/ast/ast.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/dart/element/type_algebra.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/task/strong/checker.dart'
     show getExpressionType, getReadType;
+import 'package:meta/meta.dart';
 
 /**
  * Instances of the class `StaticTypeAnalyzer` perform two type-related tasks. First, they
@@ -37,6 +41,11 @@
   final ResolverVisitor _resolver;
 
   /**
+   * The feature set that should be used to resolve types.
+   */
+  final FeatureSet _featureSet;
+
+  /**
    * The object providing access to the types defined by the language.
    */
   TypeProvider _typeProvider;
@@ -68,11 +77,12 @@
   TypePromotionManager _promoteManager;
 
   /**
-   * Initialize a newly created type analyzer.
+   * Initialize a newly created static type analyzer to analyze types for the
+   * [_resolver] based on the
    *
    * @param resolver the resolver driving this participant
    */
-  StaticTypeAnalyzer(this._resolver) {
+  StaticTypeAnalyzer(this._resolver, this._featureSet) {
     _typeProvider = _resolver.typeProvider;
     _typeSystem = _resolver.typeSystem;
     _dynamicType = _typeProvider.dynamicType;
@@ -83,6 +93,11 @@
   }
 
   /**
+   * Return `true` if NNBD is enabled for this compilation unit.
+   */
+  bool get _nonNullableEnabled => _featureSet.isEnabled(Feature.non_nullable);
+
+  /**
    * Given a constructor name [node] and a type [type], record an inferred type
    * for the constructor if in strong mode. This is used to fill in any
    * inferred type parameters found by the resolver.
@@ -123,9 +138,9 @@
       List<ParameterElement> parameters = node.parameterElements;
       {
         Iterator<ParameterElement> positional =
-            parameters.where((p) => !p.isNamed).iterator;
+            parameters.where((p) => p.isPositional).iterator;
         Iterator<ParameterElement> fnPositional =
-            functionType.parameters.where((p) => !p.isNamed).iterator;
+            functionType.parameters.where((p) => p.isPositional).iterator;
         while (positional.moveNext() && fnPositional.moveNext()) {
           inferType(positional.current, fnPositional.current.type);
         }
@@ -218,7 +233,7 @@
    */
   @override
   void visitAdjacentStrings(AdjacentStrings node) {
-    _recordStaticType(node, _typeProvider.stringType);
+    _recordStaticType(node, _nonNullable(_typeProvider.stringType));
   }
 
   /**
@@ -281,14 +296,26 @@
       DartType staticType = _getStaticType(rightHandSide);
       _recordStaticType(node, staticType);
     } else if (operator == TokenType.QUESTION_QUESTION_EQ) {
-      // The static type of a compound assignment using ??= is the least upper
-      // bound of the static types of the LHS and RHS.
-      _analyzeLeastUpperBound(node, node.leftHandSide, node.rightHandSide,
-          read: true);
+      if (_nonNullableEnabled) {
+        // The static type of a compound assignment using ??= with NNBD is the
+        // least upper bound of the static types of the LHS and RHS after
+        // promoting the LHS/ to non-null (as we know its value will not be used
+        // if null)
+        _analyzeLeastUpperBoundTypes(
+            node,
+            _typeSystem.promoteToNonNull(
+                _getExpressionType(node.leftHandSide, read: true)),
+            _getExpressionType(node.rightHandSide, read: true));
+      } else {
+        // The static type of a compound assignment using ??= before NNBD is the
+        // least upper bound of the static types of the LHS and RHS.
+        _analyzeLeastUpperBound(node, node.leftHandSide, node.rightHandSide,
+            read: true);
+      }
       return;
     } else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ ||
         operator == TokenType.BAR_BAR_EQ) {
-      _recordStaticType(node, _typeProvider.boolType);
+      _recordStaticType(node, _nonNullable(_typeProvider.boolType));
     } else {
       ExecutableElement staticMethodElement = node.staticElement;
       DartType staticType = _computeStaticReturnType(staticMethodElement);
@@ -296,7 +323,8 @@
           _getStaticType(node.leftHandSide, read: true),
           operator,
           node.rightHandSide.staticType,
-          staticType);
+          staticType,
+          _featureSet);
       _recordStaticType(node, staticType);
     }
   }
@@ -363,11 +391,23 @@
   @override
   void visitBinaryExpression(BinaryExpression node) {
     if (node.operator.type == TokenType.QUESTION_QUESTION) {
-      // Evaluation of an if-null expression e of the form e1 ?? e2 is
-      // equivalent to the evaluation of the expression
-      // ((x) => x == null ? e2 : x)(e1).  The static type of e is the least
-      // upper bound of the static type of e1 and the static type of e2.
-      _analyzeLeastUpperBound(node, node.leftOperand, node.rightOperand);
+      if (_nonNullableEnabled) {
+        // The static type of a compound assignment using ??= with NNBD is the
+        // least upper bound of the static types of the LHS and RHS after
+        // promoting the LHS/ to non-null (as we know its value will not be used
+        // if null)
+        _analyzeLeastUpperBoundTypes(
+            node,
+            _typeSystem.promoteToNonNull(
+                _getExpressionType(node.leftOperand, read: true)),
+            _getExpressionType(node.rightOperand, read: true));
+      } else {
+        // Without NNBD, evaluation of an if-null expression e of the form
+        // e1 ?? e2 is equivalent to the evaluation of the expression
+        // ((x) => x == null ? e2 : x)(e1).  The static type of e is the least
+        // upper bound of the static type of e1 and the static type of e2.
+        _analyzeLeastUpperBound(node, node.leftOperand, node.rightOperand);
+      }
       return;
     }
     DartType staticType = node.staticInvokeType?.returnType ?? _dynamicType;
@@ -375,7 +415,8 @@
         node.leftOperand.staticType,
         node.operator.type,
         node.rightOperand.staticType,
-        staticType);
+        staticType,
+        _featureSet);
     _recordStaticType(node, staticType);
   }
 
@@ -385,7 +426,7 @@
    */
   @override
   void visitBooleanLiteral(BooleanLiteral node) {
-    _recordStaticType(node, _typeProvider.boolType);
+    _recordStaticType(node, _nonNullable(_typeProvider.boolType));
   }
 
   /**
@@ -424,7 +465,7 @@
    */
   @override
   void visitDoubleLiteral(DoubleLiteral node) {
-    _recordStaticType(node, _typeProvider.doubleType);
+    _recordStaticType(node, _nonNullable(_typeProvider.doubleType));
   }
 
   @override
@@ -500,7 +541,8 @@
   @override
   void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     _inferGenericInvocationExpression(node);
-    DartType staticType = _computeInvokeReturnType(node.staticInvokeType);
+    DartType staticType = _computeInvokeReturnType(node.staticInvokeType,
+        isNullableInvoke: false);
     _recordStaticType(node, staticType);
   }
 
@@ -560,11 +602,13 @@
     var context = InferenceContext.getContext(
         (node as IntegerLiteralImpl).immediatelyNegated ? node.parent : node);
     if (context == null ||
-        _typeSystem.isAssignableTo(_typeProvider.intType, context) ||
-        !_typeSystem.isAssignableTo(_typeProvider.doubleType, context)) {
-      _recordStaticType(node, _typeProvider.intType);
+        _typeSystem.isAssignableTo(_typeProvider.intType, context,
+            featureSet: _featureSet) ||
+        !_typeSystem.isAssignableTo(_typeProvider.doubleType, context,
+            featureSet: _featureSet)) {
+      _recordStaticType(node, _nonNullable(_typeProvider.intType));
     } else {
-      _recordStaticType(node, _typeProvider.doubleType);
+      _recordStaticType(node, _nonNullable(_typeProvider.doubleType));
     }
   }
 
@@ -576,7 +620,7 @@
    */
   @override
   void visitIsExpression(IsExpression node) {
-    _recordStaticType(node, _typeProvider.boolType);
+    _recordStaticType(node, _nonNullable(_typeProvider.boolType));
   }
 
   /**
@@ -602,7 +646,9 @@
         }
       }
       _recordStaticType(
-          node, _typeProvider.listType.instantiate(<DartType>[staticType]));
+          node,
+          _nonNullable(
+              _typeProvider.listType.instantiate(<DartType>[staticType])));
       return;
     }
 
@@ -617,6 +663,8 @@
       // in fact had an error above, because it will still attempt to return
       // a type. Perhaps we should record inference from TypeSystem if
       // everything was successful?
+      // TODO(brianwilkerson) Determine whether we need to make the inferred
+      //  type non-nullable here or whether it will already be non-nullable.
       _resolver.inferenceContext.recordInference(node, inferred);
       _recordStaticType(node, inferred);
       return;
@@ -670,8 +718,9 @@
         _inferMethodInvocationInlineJS(node);
 
     if (!inferredStaticType) {
-      DartType staticStaticType =
-          _computeInvokeReturnType(node.staticInvokeType);
+      DartType staticStaticType = _computeInvokeReturnType(
+          node.staticInvokeType,
+          isNullableInvoke: node.operator?.type == TokenType.QUESTION_PERIOD);
       _recordStaticType(node, staticStaticType);
     }
   }
@@ -729,9 +778,7 @@
     TypeImpl staticType = _getStaticType(operand, read: true);
 
     if (node.operator.type == TokenType.BANG) {
-      // TODO(paulberry): This does the wrong thing if staticType is a type
-      // parameter type.
-      staticType = staticType.withNullability(NullabilitySuffix.none);
+      staticType = _typeSystem.promoteToNonNull(staticType);
     } else {
       // No need to check for `intVar++`, the result is `int`.
       if (!staticType.isDartCoreInt) {
@@ -756,13 +803,13 @@
       if (_isNotTypeLiteral(node)) {
         staticType = staticElement.type;
       } else {
-        staticType = _typeProvider.typeType;
+        staticType = _nonNullable(_typeProvider.typeType);
       }
     } else if (staticElement is FunctionTypeAliasElement) {
       if (_isNotTypeLiteral(node)) {
         staticType = staticElement.type;
       } else {
-        staticType = _typeProvider.typeType;
+        staticType = _nonNullable(_typeProvider.typeType);
       }
     } else if (staticElement is MethodElement) {
       staticType = staticElement.type;
@@ -775,6 +822,7 @@
     } else if (staticElement is VariableElement) {
       staticType = staticElement.type;
     }
+
     staticType = _inferGenericInstantiationFromContext(node, staticType);
     if (!_inferObjectAccess(node, staticType, prefixedIdentifier)) {
       _recordStaticType(prefixedIdentifier, staticType);
@@ -791,7 +839,7 @@
   void visitPrefixExpression(PrefixExpression node) {
     TokenType operator = node.operator.type;
     if (operator == TokenType.BANG) {
-      _recordStaticType(node, _typeProvider.boolType);
+      _recordStaticType(node, _nonNullable(_typeProvider.boolType));
     } else {
       // The other cases are equivalent to invoking a method.
       ExecutableElement staticMethodElement = node.staticElement;
@@ -801,7 +849,7 @@
         Expression operand = node.operand;
         var operandReadType = _getStaticType(operand, read: true);
         if (operandReadType.isDartCoreInt) {
-          staticType = _typeProvider.intType;
+          staticType = _nonNullable(_typeProvider.intType);
         } else {
           _checkForInvalidAssignmentIncDec(node, operand, staticType);
         }
@@ -863,7 +911,13 @@
     } else {
       // TODO(brianwilkerson) Report this internal error.
     }
+
+    if (node.operator.type == TokenType.QUESTION_PERIOD &&
+        _nonNullableEnabled) {
+      staticType = _typeSystem.makeNullable(staticType);
+    }
     staticType = _inferGenericInstantiationFromContext(node, staticType);
+
     if (!_inferObjectAccess(node, staticType, propertyName)) {
       _recordStaticType(propertyName, staticType);
       _recordStaticType(node, staticType);
@@ -891,14 +945,18 @@
         (node as SetOrMapLiteralImpl).becomeSet();
         var elementType = _getType(typeArguments[0]) ?? _dynamicType;
         _recordStaticType(
-            node, _typeProvider.setType.instantiate(<DartType>[elementType]));
+            node,
+            _nonNullable(
+                _typeProvider.setType.instantiate(<DartType>[elementType])));
         return;
       } else if (typeArguments.length == 2) {
         (node as SetOrMapLiteralImpl).becomeMap();
         var keyType = _getType(typeArguments[0]) ?? _dynamicType;
         var valueType = _getType(typeArguments[1]) ?? _dynamicType;
-        _recordStaticType(node,
-            _typeProvider.mapType.instantiate(<DartType>[keyType, valueType]));
+        _recordStaticType(
+            node,
+            _nonNullable(_typeProvider.mapType
+                .instantiate(<DartType>[keyType, valueType])));
         return;
       }
       // If we get here, then a nonsense number of type arguments were provided,
@@ -914,6 +972,9 @@
       assert(literalType.element == _typeProvider.setType.element);
       (node as SetOrMapLiteralImpl).becomeSet();
     }
+    // TODO(brianwilkerson) Decide whether the literalType needs to be made
+    //  non-nullable here or whether that will have happened in
+    //  _inferSetOrMapLiteralType.
     _resolver.inferenceContext.recordInference(node, literalType);
     _recordStaticType(node, literalType);
   }
@@ -964,13 +1025,13 @@
       if (_isNotTypeLiteral(node)) {
         staticType = element.type;
       } else {
-        staticType = _typeProvider.typeType;
+        staticType = _nonNullable(_typeProvider.typeType);
       }
     } else if (element is FunctionTypeAliasElement) {
       if (_isNotTypeLiteral(node)) {
         staticType = element.type;
       } else {
-        staticType = _typeProvider.typeType;
+        staticType = _nonNullable(_typeProvider.typeType);
       }
     } else if (element is MethodElement) {
       staticType = element.type;
@@ -979,7 +1040,7 @@
     } else if (element is ExecutableElement) {
       staticType = element.type;
     } else if (element is TypeParameterElement) {
-      staticType = _typeProvider.typeType;
+      staticType = _nonNullable(_typeProvider.typeType);
     } else if (element is VariableElement) {
       VariableElement variable = element;
       staticType = _promoteManager.getStaticType(variable);
@@ -991,7 +1052,7 @@
       }
       staticType = _typeProvider.dynamicType;
     } else if (element is DynamicElementImpl) {
-      staticType = _typeProvider.typeType;
+      staticType = _nonNullable(_typeProvider.typeType);
     } else {
       staticType = _dynamicType;
     }
@@ -1005,7 +1066,7 @@
    */
   @override
   void visitSimpleStringLiteral(SimpleStringLiteral node) {
-    _recordStaticType(node, _typeProvider.stringType);
+    _recordStaticType(node, _nonNullable(_typeProvider.stringType));
   }
 
   /**
@@ -1014,7 +1075,7 @@
    */
   @override
   void visitStringInterpolation(StringInterpolation node) {
-    _recordStaticType(node, _typeProvider.stringType);
+    _recordStaticType(node, _nonNullable(_typeProvider.stringType));
   }
 
   @override
@@ -1030,7 +1091,7 @@
 
   @override
   void visitSymbolLiteral(SymbolLiteral node) {
-    _recordStaticType(node, _typeProvider.symbolType);
+    _recordStaticType(node, _nonNullable(_typeProvider.symbolType));
   }
 
   /**
@@ -1071,10 +1132,21 @@
       {bool read: false}) {
     DartType staticType1 = _getExpressionType(expr1, read: read);
     DartType staticType2 = _getExpressionType(expr2, read: read);
+
+    _analyzeLeastUpperBoundTypes(node, staticType1, staticType2);
+  }
+
+  /**
+   * Set the static type of [node] to be the least upper bound of the static
+   * types [staticType1] and [staticType2].
+   */
+  void _analyzeLeastUpperBoundTypes(
+      Expression node, DartType staticType1, DartType staticType2) {
     if (staticType1 == null) {
       // TODO(brianwilkerson) Determine whether this can still happen.
       staticType1 = _dynamicType;
     }
+
     if (staticType2 == null) {
       // TODO(brianwilkerson) Determine whether this can still happen.
       staticType2 = _dynamicType;
@@ -1092,7 +1164,8 @@
   void _checkForInvalidAssignmentIncDec(
       AstNode node, Expression operand, DartType type) {
     var operandWriteType = _getStaticType(operand);
-    if (!_typeSystem.isAssignableTo(type, operandWriteType)) {
+    if (!_typeSystem.isAssignableTo(type, operandWriteType,
+        featureSet: _featureSet)) {
       _resolver.errorReporter.reportTypeErrorForNode(
         StaticTypeWarningCode.INVALID_ASSIGNMENT,
         node,
@@ -1159,15 +1232,24 @@
    * Compute the return type of the method or function represented by the given
    * type that is being invoked.
    */
-  DartType _computeInvokeReturnType(DartType type) {
+  DartType /*!*/ _computeInvokeReturnType(DartType type,
+      {@required bool isNullableInvoke}) {
+    TypeImpl /*!*/ returnType;
     if (type is InterfaceType) {
       MethodElement callMethod = type.lookUpMethod(
           FunctionElement.CALL_METHOD_NAME, _resolver.definingLibrary);
-      return callMethod?.type?.returnType ?? _dynamicType;
+      returnType = callMethod?.type?.returnType ?? _dynamicType;
     } else if (type is FunctionType) {
-      return type.returnType ?? _dynamicType;
+      returnType = type.returnType ?? _dynamicType;
+    } else {
+      returnType = _dynamicType;
     }
-    return _dynamicType;
+
+    if (isNullableInvoke && _nonNullableEnabled) {
+      returnType = _typeSystem.makeNullable(returnType);
+    }
+
+    return returnType;
   }
 
   /**
@@ -1182,13 +1264,14 @@
       InterfaceType genericType = body.isAsynchronous
           ? _typeProvider.streamType
           : _typeProvider.iterableType;
-      return genericType.instantiate(<DartType>[type]);
+      return _nonNullable(genericType.instantiate(<DartType>[type]));
     } else if (body.isAsynchronous) {
       if (type.isDartAsyncFutureOr) {
         type = (type as InterfaceType).typeArguments[0];
       }
-      return _typeProvider.futureType
+      DartType futureType = _typeProvider.futureType
           .instantiate(<DartType>[_typeSystem.flatten(type)]);
+      return _nonNullable(futureType);
     } else {
       return type;
     }
@@ -1208,13 +1291,14 @@
       //
       FunctionType propertyType = element.type;
       if (propertyType != null) {
-        return _computeInvokeReturnType(propertyType.returnType);
+        return _computeInvokeReturnType(propertyType.returnType,
+            isNullableInvoke: false);
       }
     } else if (element is ExecutableElement) {
-      return _computeInvokeReturnType(element.type);
+      return _computeInvokeReturnType(element.type, isNullableInvoke: false);
     } else if (element is VariableElement) {
       DartType variableType = _promoteManager.getStaticType(element);
-      return _computeInvokeReturnType(variableType);
+      return _computeInvokeReturnType(variableType, isNullableInvoke: false);
     }
     return _dynamicType;
   }
@@ -1512,6 +1596,7 @@
     if (context is FunctionType &&
         type is FunctionType &&
         ts is Dart2TypeSystem) {
+      // TODO(scheglov) Also store type arguments for identifiers.
       return ts.inferFunctionTypeInstantiation(context, type,
           errorReporter: _resolver.errorReporter, errorNode: node);
     }
@@ -1528,8 +1613,7 @@
   void _inferGenericInvocationExpression(InvocationExpression node) {
     ArgumentList arguments = node.argumentList;
     var type = node.function.staticType;
-    var freshType =
-        type is FunctionType ? new FunctionTypeImpl.fresh(type) : type;
+    var freshType = _getFreshType(type);
 
     FunctionType inferred = _inferGenericInvoke(
         node, freshType, node.typeArguments, arguments, node.function);
@@ -1576,12 +1660,31 @@
           argTypes.add(argumentList.arguments[i].staticType);
         }
       }
-      return ts.inferGenericFunctionOrType(
+      var typeArgs = ts.inferGenericFunctionOrType2<FunctionType>(
           fnType, params, argTypes, InferenceContext.getContext(node),
           isConst: isConst,
           errorReporter: _resolver.errorReporter,
           errorNode: errorNode);
+      if (node is InvocationExpressionImpl) {
+        node.typeArgumentTypes = typeArgs;
+      }
+      if (typeArgs != null) {
+        return fnType.instantiate(typeArgs);
+      }
+      return fnType;
     }
+
+    // There is currently no other place where we set type arguments
+    // for FunctionExpressionInvocation(s), so set it here, if not inferred.
+    if (node is FunctionExpressionInvocationImpl) {
+      if (typeArguments != null) {
+        var typeArgs = typeArguments.arguments.map((n) => n.type).toList();
+        node.typeArgumentTypes = typeArgs;
+      } else {
+        node.typeArgumentTypes = const <DartType>[];
+      }
+    }
+
     return null;
   }
 
@@ -1862,6 +1965,17 @@
   }
 
   /**
+   * Return the non-nullable variant of the [type] if NNBD is enabled, otherwise
+   * return the type itself.
+   */
+  DartType _nonNullable(DartType type) {
+    if (_nonNullableEnabled) {
+      return _typeSystem.promoteToNonNull(type);
+    }
+    return type;
+  }
+
+  /**
    * Record that the static type of the given node is the given type.
    *
    * @param expression the node whose type is to be recorded
@@ -1962,6 +2076,19 @@
     function.type = new FunctionTypeImpl(function);
     return new FunctionTypeImpl.fresh(function.type);
   }
+
+  static DartType _getFreshType(DartType type) {
+    if (type is FunctionType) {
+      if (AnalysisDriver.useSummary2) {
+        var parameters = getFreshTypeParameters(type.typeFormals);
+        return parameters.applyToFunctionType(type);
+      } else {
+        return new FunctionTypeImpl.fresh(type);
+      }
+    } else {
+      return type;
+    }
+  }
 }
 
 class _InferredCollectionElementTypeInformation {
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index c62b040..469e29c 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:meta/meta.dart';
 
 /**
  * The class `AstTestFactory` defines utility methods that can be used to create AST nodes. The
@@ -275,14 +276,16 @@
           String scriptTag,
           List<Directive> directives,
           List<CompilationUnitMember> declarations) =>
-      astFactory.compilationUnit(
-          TokenFactory.tokenFromType(TokenType.EOF),
-          scriptTag == null ? null : AstTestFactory.scriptTag(scriptTag),
-          directives == null ? new List<Directive>() : directives,
-          declarations == null
+      astFactory.compilationUnit2(
+          beginToken: TokenFactory.tokenFromType(TokenType.EOF),
+          scriptTag:
+              scriptTag == null ? null : AstTestFactory.scriptTag(scriptTag),
+          directives: directives == null ? new List<Directive>() : directives,
+          declarations: declarations == null
               ? new List<CompilationUnitMember>()
               : declarations,
-          TokenFactory.tokenFromType(TokenType.EOF));
+          endToken: TokenFactory.tokenFromType(TokenType.EOF),
+          featureSet: null);
 
   static ConditionalExpression conditionalExpression(Expression condition,
           Expression thenExpression, Expression elseExpression) =>
@@ -467,6 +470,24 @@
   static ExtendsClause extendsClause(TypeName type) => astFactory.extendsClause(
       TokenFactory.tokenFromKeyword(Keyword.EXTENDS), type);
 
+  static ExtensionDeclaration extensionDeclaration(
+          {@required String name,
+          TypeParameterList typeParameters,
+          @required TypeAnnotation extendedType,
+          List<ClassMember> members}) =>
+      astFactory.extensionDeclaration(
+          comment: null,
+          metadata: null,
+          extensionKeyword: TokenFactory.tokenFromKeyword(Keyword.EXTENSION),
+          name: identifier3(name),
+          typeParameters: typeParameters,
+          onKeyword: TokenFactory.tokenFromKeyword(Keyword.ON),
+          extendedType: extendedType,
+          leftBracket: TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET),
+          members: members,
+          rightBracket:
+              TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET));
+
   static FieldDeclaration fieldDeclaration(bool isStatic, Keyword keyword,
           TypeAnnotation type, List<VariableDeclaration> variables) =>
       astFactory.fieldDeclaration2(
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 8dfa63d..e54a06c 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -412,12 +412,12 @@
     return spec;
   }
 
-  static LibraryElementImpl library(
-      AnalysisContext context, String libraryName) {
+  static LibraryElementImpl library(AnalysisContext context, String libraryName,
+      {bool isNonNullableByDefault: true}) {
     String fileName = "/$libraryName.dart";
     CompilationUnitElementImpl unit = compilationUnit(fileName);
-    LibraryElementImpl library = new LibraryElementImpl(
-        context, null, libraryName, 0, libraryName.length);
+    LibraryElementImpl library = new LibraryElementImpl(context, null,
+        libraryName, 0, libraryName.length, isNonNullableByDefault);
     library.definingCompilationUnit = unit;
     return library;
   }
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index bb052ad..8ea7304 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -23,6 +23,8 @@
  * for the core library.
  */
 class TestTypeProvider extends TypeProviderBase {
+  final bool _isNonNullableByDefault;
+
   /**
    * The type representing the built-in type 'bool'.
    */
@@ -179,11 +181,6 @@
   InterfaceType _typeType;
 
   /**
-   * The type representing type names that can't be resolved.
-   */
-  DartType _undefinedType;
-
-  /**
    * The analysis context, if any. Used to create an appropriate 'dart:async'
    * library to back `Future<T>`.
    */
@@ -195,7 +192,9 @@
    */
   AnalysisDriver _driver;
 
-  TestTypeProvider([this._context, this._driver]);
+  /// TODO(paulberry): rework API and make _isNonNullableByDefault required.
+  TestTypeProvider(
+      [this._context, this._driver, this._isNonNullableByDefault = false]);
 
   @override
   InterfaceType get boolType {
@@ -476,10 +475,14 @@
       // Create a library element for "dart:core"
       // This enables the "isDartCoreNull" getter.
       var library = new LibraryElementImpl.forNode(
-          _context, null, AstTestFactory.libraryIdentifier2(["dart.core"]));
+          _context,
+          null,
+          AstTestFactory.libraryIdentifier2(["dart.core"]),
+          _isNonNullableByDefault);
       var unit = new CompilationUnitElementImpl();
       library.definingCompilationUnit = unit;
-      unit.librarySource = unit.source = new StringSource('', null);
+      unit.librarySource =
+          unit.source = new StringSource('', null, uri: Uri.parse('dart:core'));
 
       nullElement.enclosingElement = library;
       _nullType = nullElement.type;
@@ -612,14 +615,6 @@
     return _typeType;
   }
 
-  @override
-  DartType get undefinedType {
-    if (_undefinedType == null) {
-      _undefinedType = UndefinedTypeImpl.instance;
-    }
-    return _undefinedType;
-  }
-
   void _initDartAsync() {
     Source asyncSource;
     if (_driver != null) {
@@ -632,7 +627,10 @@
     }
     CompilationUnitElementImpl asyncUnit = new CompilationUnitElementImpl();
     LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
-        _context, null, AstTestFactory.libraryIdentifier2(["dart.async"]));
+        _context,
+        null,
+        AstTestFactory.libraryIdentifier2(["dart.async"]),
+        _isNonNullableByDefault);
     asyncLibrary.definingCompilationUnit = asyncUnit;
     asyncUnit.librarySource = asyncUnit.source = asyncSource;
 
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index b2fa6c8..7b41701 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -5,12 +5,14 @@
 import 'dart:collection';
 import 'dart:math' as math;
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart' show AstNode;
 import 'package:analyzer/dart/ast/token.dart' show Keyword, TokenType;
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_system.dart' as public;
 import 'package:analyzer/error/listener.dart' show ErrorReporter;
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart' show TypeParameterMember;
 import 'package:analyzer/src/dart/element/type.dart';
@@ -49,7 +51,9 @@
 
 bool _isBottom(DartType t) {
   return t.isBottom ||
-      t.isDartCoreNull ||
+      // TODO(mfairhurst): Remove the exception treating Null* as Top.
+      t.isDartCoreNull &&
+          (t as TypeImpl).nullabilitySuffix == NullabilitySuffix.star ||
       identical(t, UnknownInferredType.instance);
 }
 
@@ -58,7 +62,8 @@
     return _isTop((t as InterfaceType).typeArguments[0]);
   }
   return t.isDynamic ||
-      t.isObject ||
+      (t.isObject &&
+          (t as TypeImpl).nullabilitySuffix != NullabilitySuffix.none) ||
       t.isVoid ||
       identical(t, UnknownInferredType.instance);
 }
@@ -73,7 +78,8 @@
       new HashSet<TypeComparison>();
 
   /**
-   * True if implicit casts should be allowed, otherwise false.
+   * False if implicit casts should always be disallowed, otherwise the
+   * [FeatureSet] will be used.
    *
    * This affects the behavior of [isAssignableTo].
    */
@@ -164,7 +170,8 @@
     }
 
     // No subtype relation, so no known GLB.
-    return typeProvider.bottomType;
+    // TODO(mfairhurst): implement fully NNBD GLB, and return Never (non-legacy)
+    return BottomTypeImpl.instanceLegacy;
   }
 
   /**
@@ -193,8 +200,12 @@
     inferrer.constrainGenericFunctionInContext(fnType, contextType);
 
     // Infer and instantiate the resulting type.
-    return inferrer.infer(fnType, fnType.typeFormals,
-        errorReporter: errorReporter, errorNode: errorNode);
+    var inferredTypes = inferrer.infer(
+      fnType.typeFormals,
+      errorReporter: errorReporter,
+      errorNode: errorNode,
+    );
+    return fnType.instantiate(inferredTypes);
   }
 
   /// Infers a generic type, function, method, or list/map literal
@@ -227,10 +238,53 @@
       AstNode errorNode,
       bool downwards: false,
       bool isConst: false}) {
+    var inferredTypes = inferGenericFunctionOrType2(
+      genericType,
+      parameters,
+      argumentTypes,
+      returnContextType,
+      errorReporter: errorReporter,
+      errorNode: errorNode,
+      downwards: downwards,
+      isConst: isConst,
+    );
+    return genericType.instantiate(inferredTypes);
+  }
+
+  /// Infers type arguments for a generic type, function, method, or
+  /// list/map literal, using the downward context type as well as the
+  /// argument types if available.
+  ///
+  /// For example, given a function type with generic type parameters, this
+  /// infers the type parameters from the actual argument types, and returns the
+  /// instantiated function type.
+  ///
+  /// Concretely, given a function type with parameter types P0, P1, ... Pn,
+  /// result type R, and generic type parameters T0, T1, ... Tm, use the
+  /// argument types A0, A1, ... An to solve for the type parameters.
+  ///
+  /// For each parameter Pi, we want to ensure that Ai <: Pi. We can do this by
+  /// running the subtype algorithm, and when we reach a type parameter Tj,
+  /// recording the lower or upper bound it must satisfy. At the end, all
+  /// constraints can be combined to determine the type.
+  ///
+  /// All constraints on each type parameter Tj are tracked, as well as where
+  /// they originated, so we can issue an error message tracing back to the
+  /// argument values, type parameter "extends" clause, or the return type
+  /// context.
+  List<DartType> inferGenericFunctionOrType2<T extends ParameterizedType>(
+      T genericType,
+      List<ParameterElement> parameters,
+      List<DartType> argumentTypes,
+      DartType returnContextType,
+      {ErrorReporter errorReporter,
+      AstNode errorNode,
+      bool downwards: false,
+      bool isConst: false}) {
     // TODO(jmesserly): expose typeFormals on ParameterizedType.
     List<TypeParameterElement> typeFormals = typeFormalsAsElements(genericType);
     if (typeFormals.isEmpty) {
-      return genericType;
+      return null;
     }
 
     // Create a TypeSystem that will allow certain type parameters to be
@@ -257,7 +311,7 @@
           genericType: genericType);
     }
 
-    return inferrer.infer(genericType, typeFormals,
+    return inferrer.infer(typeFormals,
         errorReporter: errorReporter,
         errorNode: errorNode,
         downwardsInferPhase: downwards);
@@ -297,7 +351,7 @@
       Map<TypeParameterType, DartType> knownTypes}) {
     int count = typeFormals.length;
     if (count == 0) {
-      return null;
+      return const <DartType>[];
     }
 
     Set<TypeParameterType> all = new Set<TypeParameterType>();
@@ -323,6 +377,9 @@
       Set<DartType> visitedTypes = new HashSet<DartType>();
 
       void appendParameters(DartType type) {
+        if (type == null) {
+          return;
+        }
         if (visitedTypes.contains(type)) {
           return;
         }
@@ -330,6 +387,13 @@
         if (type is TypeParameterType && all.contains(type)) {
           parameters ??= <TypeParameterType>[];
           parameters.add(type);
+        } else if (AnalysisDriver.useSummary2) {
+          if (type is FunctionType) {
+            appendParameters(type.returnType);
+            type.parameters.map((p) => p.type).forEach(appendParameters);
+          } else if (type is InterfaceType) {
+            type.typeArguments.forEach(appendParameters);
+          }
         } else if (type is ParameterizedType) {
           type.typeArguments.forEach(appendParameters);
         }
@@ -389,7 +453,8 @@
   }
 
   @override
-  bool isAssignableTo(DartType fromType, DartType toType) {
+  bool isAssignableTo(DartType fromType, DartType toType,
+      {FeatureSet featureSet}) {
     // An actual subtype
     if (isSubtypeOf(fromType, toType)) {
       return true;
@@ -398,15 +463,23 @@
     // A call method tearoff
     if (fromType is InterfaceType && acceptsFunctionType(toType)) {
       var callMethodType = getCallMethodType(fromType);
-      if (callMethodType != null && isAssignableTo(callMethodType, toType)) {
+      if (callMethodType != null &&
+          isAssignableTo(callMethodType, toType, featureSet: featureSet)) {
         return true;
       }
     }
 
+    // First make sure --no-implicit-casts disables all downcasts, including
+    // dynamic casts.
     if (!implicitCasts) {
       return false;
     }
 
+    // Now handle NNBD default behavior, where we disable non-dynamic downcasts.
+    if (featureSet != null && featureSet.isEnabled(Feature.non_nullable)) {
+      return fromType.isDynamic;
+    }
+
     // Don't allow implicit downcasts between function types
     // and call method objects, as these will almost always fail.
     if (fromType is FunctionType && getCallMethodType(toType) != null) {
@@ -425,8 +498,7 @@
       return false;
     }
 
-    // If the subtype relation goes the other way, allow the implicit
-    // downcast.
+    // If the subtype relation goes the other way, allow the implicit downcast.
     if (isSubtypeOf(toType, fromType)) {
       // TODO(leafp,jmesserly): we emit warnings/hints for these in
       // src/task/strong/checker.dart, which is a bit inconsistent. That
@@ -491,12 +563,23 @@
         p1.isCovariant && isSubtypeOf(p1.type, p2.type);
   }
 
+  /// Check if [_t1] is a subtype of [_t2].
+  ///
+  /// Partially updated to reflect
+  /// https://github.com/dart-lang/language/blob/da5adf7eb5f2d479069d8660ed7ca7b230098510/resources/type-system/subtyping.md
+  ///
+  /// However, it does not correllate 1:1 and does not specialize Null vs Never
+  /// cases. It also is not guaranteed to be exactly accurate vs the "spec"
+  /// because it has slightly different order of operations. These should be
+  /// brought in line or proven equivalent.
   @override
-  bool isSubtypeOf(DartType t1, DartType t2) {
+  bool isSubtypeOf(DartType _t1, DartType _t2) {
+    var t1 = _t1 as TypeImpl;
+    var t2 = _t2 as TypeImpl;
+
     if (identical(t1, t2)) {
       return true;
     }
-
     // The types are void, dynamic, bottom, interface types, function types,
     // FutureOr<T> and type parameters.
     //
@@ -515,10 +598,36 @@
       return false;
     }
 
+    // TODO(mfairhurst): Convert Null to Never?, to simplify the algorithm, and
+    // remove this check.
+    if (t1.isDartCoreNull) {
+      if (t2.nullabilitySuffix != NullabilitySuffix.none) {
+        return true;
+      }
+    }
+
+    // Handle T1? <: T2
+    if (t1.nullabilitySuffix == NullabilitySuffix.question) {
+      if (t2.nullabilitySuffix == NullabilitySuffix.none) {
+        // If T2 is not FutureOr<S2>, then subtype is false.
+        if (!t2.isDartAsyncFutureOr) {
+          return false;
+        }
+
+        // T1? <: FutureOr<T2> is true if T2 is S2?.
+        // TODO(mfairhurst): handle T1? <: FutureOr<dynamic>, etc.
+        if (t2 is InterfaceTypeImpl &&
+            (t2.typeArguments[0] as TypeImpl).nullabilitySuffix ==
+                NullabilitySuffix.none) {
+          return false;
+        }
+      }
+    }
+
     // Handle FutureOr<T> union type.
-    if (t1 is InterfaceType && t1.isDartAsyncFutureOr) {
+    if (t1 is InterfaceTypeImpl && t1.isDartAsyncFutureOr) {
       var t1TypeArg = t1.typeArguments[0];
-      if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
+      if (t2 is InterfaceTypeImpl && t2.isDartAsyncFutureOr) {
         var t2TypeArg = t2.typeArguments[0];
         // FutureOr<A> <: FutureOr<B> iff A <: B
         return isSubtypeOf(t1TypeArg, t2TypeArg);
@@ -530,7 +639,7 @@
       return isSubtypeOf(t1Future, t2) && isSubtypeOf(t1TypeArg, t2);
     }
 
-    if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
+    if (t2 is InterfaceTypeImpl && t2.isDartAsyncFutureOr) {
       // given t2 is Future<A> | A, then:
       // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
       var t2TypeArg = t2.typeArguments[0];
@@ -542,23 +651,26 @@
     //  T is not dynamic or object (handled above)
     //  True if T == S
     //  Or true if bound of S is S' and S' <: T
-    if (t1 is TypeParameterType) {
-      if (t2 is TypeParameterType &&
+    if (t1 is TypeParameterTypeImpl) {
+      if (t2 is TypeParameterTypeImpl &&
           t1.definition == t2.definition &&
           _typeParameterBoundsSubtype(t1.bound, t2.bound, true)) {
         return true;
       }
+
       DartType bound = t1.element.bound;
       return bound == null
           ? false
           : _typeParameterBoundsSubtype(bound, t2, false);
     }
+
     if (t2 is TypeParameterType) {
       return false;
     }
 
-    // We've eliminated void, dynamic, bottom, type parameters, and FutureOr.
-    // The only cases are the combinations of interface type and function type.
+    // We've eliminated void, dynamic, bottom, type parameters, FutureOr,
+    // nullable, and legacy nullable types. The only cases are the combinations
+    // of interface type and function type.
 
     // A function type can only subtype an interface type if
     // the interface type is Function
@@ -569,11 +681,11 @@
     if (t1 is InterfaceType && t2 is FunctionType) return false;
 
     // Two interface types
-    if (t1 is InterfaceType && t2 is InterfaceType) {
+    if (t1 is InterfaceTypeImpl && t2 is InterfaceTypeImpl) {
       return _isInterfaceSubtypeOf(t1, t2, null);
     }
 
-    return _isFunctionSubtypeOf(t1, t2);
+    return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType);
   }
 
   /// Given a [type] T that may have an unknown type `?`, returns a type
@@ -590,7 +702,7 @@
 
   @override
   DartType refineBinaryExpressionType(DartType leftType, TokenType operator,
-      DartType rightType, DartType currentType) {
+      DartType rightType, DartType currentType, FeatureSet featureSet) {
     if (leftType is TypeParameterType &&
         leftType.element.bound == typeProvider.numType) {
       if (rightType == leftType || rightType == typeProvider.intType) {
@@ -600,6 +712,9 @@
             operator == TokenType.PLUS_EQ ||
             operator == TokenType.MINUS_EQ ||
             operator == TokenType.STAR_EQ) {
+          if (featureSet.isEnabled(Feature.non_nullable)) {
+            return promoteToNonNull(leftType as TypeImpl);
+          }
           return leftType;
         }
       }
@@ -608,13 +723,16 @@
             operator == TokenType.MINUS ||
             operator == TokenType.STAR ||
             operator == TokenType.SLASH) {
+          if (featureSet.isEnabled(Feature.non_nullable)) {
+            return promoteToNonNull(typeProvider.doubleType as TypeImpl);
+          }
           return typeProvider.doubleType;
         }
       }
       return currentType;
     }
-    return super
-        .refineBinaryExpressionType(leftType, operator, rightType, currentType);
+    return super.refineBinaryExpressionType(
+        leftType, operator, rightType, currentType, featureSet);
   }
 
   @override
@@ -771,6 +889,8 @@
     }
 
     // Union the named parameters together.
+    // TODO(brianwilkerson) Handle the fact that named parameters can now be
+    //  required.
     Map<String, DartType> fNamed = f.namedParameterTypes;
     Map<String, DartType> gNamed = g.namedParameterTypes;
     for (String name in fNamed.keys.toSet()..addAll(gNamed.keys)) {
@@ -1145,16 +1265,16 @@
     tryMatchSubtypeOf(declaredType, contextType, origin, covariant: true);
   }
 
-  /// Given the constraints that were given by calling [isSubtypeOf], find the
-  /// instantiation of the generic function that satisfies these constraints.
+  /// Given the constraints that were given by calling [constrainArgument] and
+  /// [constrainReturnType], find the type arguments for the [typeFormals] that
+  /// satisfies these constraints.
   ///
   /// If [downwardsInferPhase] is set, we are in the first pass of inference,
   /// pushing context types down. At that point we are allowed to push down
   /// `?` to precisely represent an unknown type. If [downwardsInferPhase] is
   /// false, we are on our final inference pass, have all available information
   /// including argument types, and must not conclude `?` for any type formal.
-  T infer<T extends ParameterizedType>(
-      T genericType, List<TypeParameterElement> typeFormals,
+  List<DartType> infer(List<TypeParameterElement> typeFormals,
       {bool considerExtendsClause: true,
       ErrorReporter errorReporter,
       AstNode errorNode,
@@ -1188,7 +1308,7 @@
     // If the downwards infer phase has failed, we'll catch this in the upwards
     // phase later on.
     if (downwardsInferPhase) {
-      return genericType.instantiate(inferredTypes) as T;
+      return inferredTypes;
     }
 
     // Check the inferred types against all of the constraints.
@@ -1247,8 +1367,8 @@
 
     // Use instantiate to bounds to finish things off.
     var hasError = new List<bool>.filled(fnTypeParams.length, false);
-    var result = _typeSystem.instantiateToBounds(genericType,
-        hasError: hasError, knownTypes: knownTypes) as T;
+    var result = _typeSystem.instantiateTypeFormalsToBounds(typeFormals,
+        hasError: hasError, knownTypes: knownTypes);
 
     // Report any errors from instantiateToBounds.
     for (int i = 0; i < hasError.length; i++) {
@@ -1266,6 +1386,7 @@
         ]);
       }
     }
+
     return result;
   }
 
@@ -1910,9 +2031,11 @@
 
   /**
    * Return `true` if the [leftType] is assignable to the [rightType] (that is,
-   * if leftType <==> rightType).
+   * if leftType <==> rightType). Accepts a [FeatureSet] to correctly handle
+   * NNBD implicit downcasts.
    */
-  bool isAssignableTo(DartType leftType, DartType rightType);
+  bool isAssignableTo(DartType leftType, DartType rightType,
+      {FeatureSet featureSet});
 
   /**
    * Return `true` if the [leftType] is more specific than the [rightType]
@@ -1967,6 +2090,13 @@
     return getLeastUpperBound(leftType, rightType);
   }
 
+  /// Returns a nullable version of [type].  The result would be equivalent to
+  /// the union `type | Null` (if we supported union types).
+  DartType makeNullable(TypeImpl type) {
+    // TODO(paulberry): handle type parameter types
+    return type.withNullability(NullabilitySuffix.question);
+  }
+
   /// Attempts to find the appropriate substitution for [typeParameters] that can
   /// be applied to [src] to make it equal to [dest].  If no such substitution can
   /// be found, `null` is returned.
@@ -1978,8 +2108,13 @@
       inferrer.constrainReturnType(srcs[i], dests[i]);
       inferrer.constrainReturnType(dests[i], srcs[i]);
     }
-    var result = inferrer.infer(mixinElement.type, typeParameters,
-        considerExtendsClause: false);
+
+    var inferredTypes = inferrer.infer(
+      typeParameters,
+      considerExtendsClause: false,
+    );
+    var result = mixinElement.type.instantiate(inferredTypes);
+
     for (int i = 0; i < srcs.length; i++) {
       if (!srcs[i]
           .substitute2(result.typeArguments, mixinElement.type.typeArguments)
@@ -2016,17 +2151,31 @@
     return null;
   }
 
+  /// Returns a non-nullable version of [type].  This is equivalent to the
+  /// operation `NonNull` defined in the spec.
+  DartType promoteToNonNull(TypeImpl type) {
+    if (type.isDartCoreNull) return BottomTypeImpl.instance;
+    // TODO(mfairhurst): handle type parameter types
+    return type.withNullability(NullabilitySuffix.none);
+  }
+
   /**
-   * Attempts to make a better guess for the type of a binary with the given
-   * [operator], given that resolution has so far produced the [currentType].
+   * Determine the type of a binary expression with the given [operator] whose
+   * left operand has the type [leftType] and whose right operand has the type
+   * [rightType], given that resolution has so far produced the [currentType].
+   * The [featureSet] is used to determine whether any features that effect the
+   * computation have been enabled.
    */
   DartType refineBinaryExpressionType(DartType leftType, TokenType operator,
-      DartType rightType, DartType currentType) {
+      DartType rightType, DartType currentType, FeatureSet featureSet) {
     // bool
     if (operator == TokenType.AMPERSAND_AMPERSAND ||
         operator == TokenType.BAR_BAR ||
         operator == TokenType.EQ_EQ ||
         operator == TokenType.BANG_EQ) {
+      if (featureSet.isEnabled(Feature.non_nullable)) {
+        return promoteToNonNull(typeProvider.boolType as TypeImpl);
+      }
       return typeProvider.boolType;
     }
     DartType intType = typeProvider.intType;
@@ -2042,6 +2191,9 @@
           operator == TokenType.STAR_EQ) {
         DartType doubleType = typeProvider.doubleType;
         if (rightType == doubleType) {
+          if (featureSet.isEnabled(Feature.non_nullable)) {
+            return promoteToNonNull(doubleType as TypeImpl);
+          }
           return doubleType;
         }
       }
@@ -2057,6 +2209,9 @@
           operator == TokenType.STAR_EQ ||
           operator == TokenType.TILDE_SLASH_EQ) {
         if (rightType == intType) {
+          if (featureSet.isEnabled(Feature.non_nullable)) {
+            return promoteToNonNull(intType as TypeImpl);
+          }
           return intType;
         }
       }
@@ -2166,6 +2321,8 @@
           ParameterKind.POSITIONAL));
     }
 
+    // TODO(brianwilkerson) Handle the fact that named parameters can now be
+    //  required.
     Map<String, DartType> fNamed = f.namedParameterTypes;
     Map<String, DartType> gNamed = g.namedParameterTypes;
     for (String name in fNamed.keys.toSet()..retainAll(gNamed.keys)) {
diff --git a/pkg/analyzer/lib/src/generated/utilities_dart.dart b/pkg/analyzer/lib/src/generated/utilities_dart.dart
index d1904a0..160c47a 100644
--- a/pkg/analyzer/lib/src/generated/utilities_dart.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_dart.dart
@@ -50,20 +50,32 @@
 }
 
 /**
- * The kinds of a parameter. There are two basic kinds of parameters: required
- * and optional. Optional parameters are further divided into two kinds:
- * positional optional and named optional.
+ * The kind of a parameter. A parameter can be either positional or named, and
+ * can be either required or optional. 
  */
 class ParameterKind implements Comparable<ParameterKind> {
+  /// A positional required parameter.
   static const ParameterKind REQUIRED =
-      const ParameterKind('REQUIRED', 0, false);
+      const ParameterKind('REQUIRED', 0, false, false);
 
+  /// A positional optional parameter.
   static const ParameterKind POSITIONAL =
-      const ParameterKind('POSITIONAL', 1, true);
+      const ParameterKind('POSITIONAL', 1, false, true);
 
-  static const ParameterKind NAMED = const ParameterKind('NAMED', 2, true);
+  /// A named required parameter.
+  static const ParameterKind NAMED_REQUIRED =
+      const ParameterKind('NAMED_REQUIRED', 2, true, false);
 
-  static const List<ParameterKind> values = const [REQUIRED, POSITIONAL, NAMED];
+  /// A named optional parameter.
+  static const ParameterKind NAMED =
+      const ParameterKind('NAMED', 2, true, true);
+
+  static const List<ParameterKind> values = const [
+    REQUIRED,
+    POSITIONAL,
+    NAMED_REQUIRED,
+    NAMED
+  ];
 
   /**
    * The name of this parameter.
@@ -76,14 +88,19 @@
   final int ordinal;
 
   /**
-   * A flag indicating whether this is an optional parameter.
+   * A flag indicating whether this is a named or positional parameter.
+   */
+  final bool isNamed;
+
+  /**
+   * A flag indicating whether this is an optional or required parameter.
    */
   final bool isOptional;
 
   /**
    * Initialize a newly created kind with the given state.
    */
-  const ParameterKind(this.name, this.ordinal, this.isOptional);
+  const ParameterKind(this.name, this.ordinal, this.isNamed, this.isOptional);
 
   @override
   int get hashCode => ordinal;
diff --git a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
index 1087abd..98a39ae 100644
--- a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
+++ b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
@@ -72,15 +72,25 @@
   VersionRange get before_2_2_2 =>
       new VersionRange(max: Version.parse('2.2.2'), includeMax: false);
 
+  /// Return a range covering every version up to, but not including, 2.3.2.
+  VersionRange get before_2_3_2 =>
+      new VersionRange(max: Version.parse('2.3.2'), includeMax: false);
+
   /// Return `true` if references to the constant-update-2018 features need to
   /// be checked.
   bool get checkConstantUpdate2018 => _checkConstantUpdate2018 ??=
-      !before_2_2_2.intersect(_versionConstraint).isEmpty;
+      !before_2_3_2.intersect(_versionConstraint).isEmpty;
 
   /// Return `true` if references to Future and Stream need to be checked.
   bool get checkFutureAndStream => _checkFutureAndStream ??=
       !before_2_1_0.intersect(_versionConstraint).isEmpty;
 
+  /// Return `true` if references to the non-nullable features need to be
+  /// checked.
+  // TODO(brianwilkerson) Implement this as a version check when a version has
+  //  been selected.
+  bool get checkNnbd => true;
+
   /// Return `true` if references to set literals need to be checked.
   bool get checkSetLiterals =>
       _checkSetLiterals ??= !before_2_2_0.intersect(_versionConstraint).isEmpty;
@@ -214,6 +224,8 @@
       }
       _errorReporter.reportErrorForNode(
           HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE, node, [element.name]);
+    } else if (checkNnbd && element == _typeProvider.neverType.element) {
+      _errorReporter.reportErrorForNode(HintCode.SDK_VERSION_NEVER, node);
     }
   }
 
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index d62aaa0..e3dae80 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -10,7 +10,7 @@
 import 'package:analyzer/file_system/file_system.dart'
     show File, Folder, ResourceProvider, ResourceUriResolver;
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/source/analysis_options_provider.dart';
+import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index c60b97d1..51a2b46 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/file_system/file_system.dart' as file_system;
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/constant/potentially_constant.dart';
 import 'package:analyzer/src/dart/error/lint_codes.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisErrorInfo, AnalysisErrorInfoImpl, AnalysisOptions, Logger;
@@ -43,6 +44,7 @@
   static final _camelCaseTester = new RegExp(r'^([_$]*)([A-Z?$]+[a-z0-9]*)+$');
 
   final String value;
+
   CamelCaseString(this.value) {
     if (!isCamelCase(value)) {
       throw new ArgumentError('$value is not CamelCase');
@@ -189,8 +191,11 @@
   final String label;
   final String href;
   final bool bold;
+
   const Hyperlink(this.label, this.href, {this.bold: false});
+
   String get html => '<a href="$href">${_emph(label)}</a>';
+
   String _emph(msg) => bold ? '<strong>$msg</strong>' : msg;
 }
 
@@ -218,6 +223,16 @@
   /// Note that this method can cause constant evaluation to occur, which can be
   /// computationally expensive.
   bool canBeConst(InstanceCreationExpression expression);
+
+  /// Return `true` if it would be valid for the given constructor declaration
+  /// [node] to have a keyword of `const`.
+  ///
+  /// The [node] is expected to be a node within one of the compilation
+  /// units in [allUnits].
+  ///
+  /// Note that this method can cause constant evaluation to occur, which can be
+  /// computationally expensive.
+  bool canBeConstConstructor(ConstructorDeclaration node);
 }
 
 /// Implementation of [LinterContext]
@@ -257,18 +272,50 @@
     // exception.
     //
     Token oldKeyword = expression.keyword;
-    ConstantAnalysisErrorListener listener =
-        new ConstantAnalysisErrorListener();
     try {
       expression.keyword = new KeywordToken(Keyword.CONST, expression.offset);
-      LibraryElement library = element.library;
-      ErrorReporter errorReporter = new ErrorReporter(listener, element.source);
-      expression.accept(new ConstantVerifier(
-          errorReporter, library, typeProvider, declaredVariables));
+      return !_hasConstantVerifierError(expression);
     } finally {
       expression.keyword = oldKeyword;
     }
-    return !listener.hasConstError;
+  }
+
+  @override
+  bool canBeConstConstructor(ConstructorDeclaration node) {
+    ConstructorElement element = node.declaredElement;
+
+    ClassElement classElement = element.enclosingElement;
+    if (classElement.hasNonFinalField) return false;
+
+    var oldKeyword = node.constKeyword;
+    try {
+      temporaryConstConstructorElements[element] = true;
+      node.constKeyword = KeywordToken(Keyword.CONST, node.offset);
+      return !_hasConstantVerifierError(node);
+    } finally {
+      temporaryConstConstructorElements[element] = null;
+      node.constKeyword = oldKeyword;
+    }
+  }
+
+  /// Return `true` if [ConstantVerifier] reports an error for the [node].
+  bool _hasConstantVerifierError(AstNode node) {
+    var unitElement = currentUnit.unit.declaredElement;
+    var libraryElement = unitElement.library;
+
+    var listener = ConstantAnalysisErrorListener();
+    var errorReporter = ErrorReporter(listener, unitElement.source);
+
+    node.accept(
+      ConstantVerifier(
+        errorReporter,
+        libraryElement,
+        typeProvider,
+        declaredVariables,
+        featureSet: currentUnit.unit.featureSet,
+      ),
+    );
+    return listener.hasConstError;
   }
 }
 
@@ -299,10 +346,12 @@
   String analysisOptions;
   LintFilter filter;
   file_system.ResourceProvider resourceProvider;
+
   // todo (pq): consider migrating to named params (but note Linter dep).
   LinterOptions([this.enabledLints, this.analysisOptions]) {
     enabledLints ??= Registry.ruleRegistry;
   }
+
   void configure(LintConfig config) {
     enabledLints = Registry.ruleRegistry.where((LintRule rule) =>
         !config.ruleConfigs.any((rc) => rc.disables(rule.name)));
@@ -374,7 +423,7 @@
       ErrorCode errorCode,
       bool ignoreSyntheticNodes: true}) {
     if (node != null && (!node.isSynthetic || !ignoreSyntheticNodes)) {
-      reporter.reportErrorForNode(lintCode, node, arguments);
+      reporter.reportErrorForNode(errorCode ?? lintCode, node, arguments);
     }
   }
 
@@ -383,7 +432,7 @@
       ErrorCode errorCode,
       bool ignoreSyntheticTokens: true}) {
     if (token != null && (!token.isSynthetic || !ignoreSyntheticTokens)) {
-      reporter.reportErrorForToken(lintCode, token, arguments);
+      reporter.reportErrorForToken(errorCode ?? lintCode, token, arguments);
     }
   }
 
@@ -478,6 +527,7 @@
 
 abstract class Reporter {
   void exception(LinterException exception);
+
   void warn(String message);
 }
 
diff --git a/pkg/analyzer/lib/src/lint/util.dart b/pkg/analyzer/lib/src/lint/util.dart
index 2e12794..57e33be 100644
--- a/pkg/analyzer/lib/src/lint/util.dart
+++ b/pkg/analyzer/lib/src/lint/util.dart
@@ -4,6 +4,7 @@
 
 import 'dart:io';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -89,6 +90,7 @@
 class Spelunker {
   final String path;
   final IOSink sink;
+
   Spelunker(this.path, {IOSink sink}) : this.sink = sink ?? stdout;
 
   void spelunk() {
@@ -98,12 +100,16 @@
 
     var reader = new CharSequenceReader(contents);
     var stringSource = new StringSource(contents, path);
-    var scanner = new Scanner(stringSource, reader, errorListener);
+    // TODO(paulberry): figure out the appropriate featureSet to use here
+    var featureSet = FeatureSet.fromEnableFlags([]);
+    var scanner = new Scanner(stringSource, reader, errorListener)
+      ..configureFeatures(featureSet);
     var startToken = scanner.tokenize();
 
     errorListener.throwIfErrors();
 
-    var parser = new Parser(stringSource, errorListener);
+    var parser =
+        new Parser(stringSource, errorListener, featureSet: featureSet);
     var node = parser.parseCompilationUnit(startToken);
 
     errorListener.throwIfErrors();
@@ -132,6 +138,7 @@
   int indent = 0;
 
   final IOSink sink;
+
   _SourceVisitor(this.sink);
 
   String asString(AstNode node) =>
diff --git a/pkg/analyzer/lib/src/manifest/manifest_validator.dart b/pkg/analyzer/lib/src/manifest/manifest_validator.dart
index 3f2c5aa..a79c84e 100644
--- a/pkg/analyzer/lib/src/manifest/manifest_validator.dart
+++ b/pkg/analyzer/lib/src/manifest/manifest_validator.dart
@@ -61,11 +61,19 @@
         orElse: () => null);
     if (feature != null) {
       if (!feature.attributes.containsKey(ANDROID_REQUIRED)) {
-        _reportErrorForNode(reporter, feature, ANDROID_NAME,
-            ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE);
+        _reportErrorForNode(
+            reporter,
+            feature,
+            ANDROID_NAME,
+            ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE,
+            [HARDWARE_FEATURE_TOUCHSCREEN]);
       } else if (feature.attributes[ANDROID_REQUIRED] == 'true') {
-        _reportErrorForNode(reporter, feature, ANDROID_NAME,
-            ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE);
+        _reportErrorForNode(
+            reporter,
+            feature,
+            ANDROID_NAME,
+            ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE,
+            [HARDWARE_FEATURE_TOUCHSCREEN]);
       }
     } else {
       _reportErrorForNode(
@@ -83,11 +91,19 @@
         .toList();
     unsupported.forEach((element) {
       if (!element.attributes.containsKey(ANDROID_REQUIRED)) {
-        _reportErrorForNode(reporter, element, ANDROID_NAME,
-            ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE);
+        _reportErrorForNode(
+            reporter,
+            element,
+            ANDROID_NAME,
+            ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE,
+            [element.attributes[ANDROID_NAME]]);
       } else if (element.attributes[ANDROID_REQUIRED] == 'true') {
-        _reportErrorForNode(reporter, element, ANDROID_NAME,
-            ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE);
+        _reportErrorForNode(
+            reporter,
+            element,
+            ANDROID_NAME,
+            ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE,
+            [element.attributes[ANDROID_NAME]]);
       }
     });
   }
@@ -126,7 +142,6 @@
     activites.forEach((activity) {
       var attributes = activity.attributes;
       if (attributes.containsKey(ATTRIBUTE_SCREEN_ORIENTATION)) {
-        var value = attributes[ATTRIBUTE_SCREEN_ORIENTATION];
         if (UNSUPPORTED_ORIENTATIONS
             .contains(attributes[ATTRIBUTE_SCREEN_ORIENTATION])) {
           _reportErrorForNode(reporter, activity, ATTRIBUTE_SCREEN_ORIENTATION,
diff --git a/pkg/analyzer/lib/src/manifest/manifest_warning_code.dart b/pkg/analyzer/lib/src/manifest/manifest_warning_code.dart
index c7c1504..cfecf97 100644
--- a/pkg/analyzer/lib/src/manifest/manifest_warning_code.dart
+++ b/pkg/analyzer/lib/src/manifest/manifest_warning_code.dart
@@ -15,10 +15,8 @@
    * A code indicating that a specified hardware feature is not supported on Chrome OS.
    */
   static const ManifestWarningCode UNSUPPORTED_CHROME_OS_HARDWARE =
-      const ManifestWarningCode(
-          'UNSUPPORTED_CHROME_OS_HARDWARE',
-          "This feature is not supported on Chrome OS. Try adding " +
-              "`android:required=\"false\"` for this feature.",
+      const ManifestWarningCode('UNSUPPORTED_CHROME_OS_HARDWARE',
+          "The feature {0} is not supported on Chrome OS, consider making it optional.",
           correction:
               "Try adding `android:required=\"false\"` for this " + "feature.");
 
@@ -26,10 +24,8 @@
    * A code indicating that a specified feature is not supported on Chrome OS.
    */
   static const ManifestWarningCode UNSUPPORTED_CHROME_OS_FEATURE =
-      const ManifestWarningCode(
-          'UNSUPPORTED_CHROME_OS_FEATURE',
-          "This feature is not supported on Chrome OS. Try changing " +
-              "`android:required to \"false\"` for this feature.",
+      const ManifestWarningCode('UNSUPPORTED_CHROME_OS_FEATURE',
+          'The feature {0} is not supported on Chrome OS, consider making it optional.',
           correction: "Try changing to `android:required=\"false\"` for this " +
               "feature.");
 
@@ -39,10 +35,7 @@
    */
   static const ManifestWarningCode NO_TOUCHSCREEN_FEATURE = const ManifestWarningCode(
       'NO_TOUCHSCREEN_FEATURE',
-      "Explicitly set \"android.hardware.touchscreen\" to not required for Chrome OS. " +
-          "Consider adding " +
-          "<uses-feature android:name=\"android.hardware.touchscreen\" android:required=\"false\" />" +
-          " to the manifest.",
+      "The default \"android.hardware.touchscreen\" needs to be optional for Chrome OS. ",
       correction: "Consider adding " +
           "<uses-feature android:name=\"android.hardware.touchscreen\" android:required=\"false\" />" +
           " to the manifest.");
@@ -51,25 +44,22 @@
    * A code indicating that a specified permission is not supported on Chrome OS.
    */
   static const ManifestWarningCode PERMISSION_IMPLIES_UNSUPPORTED_HARDWARE =
-      const ManifestWarningCode(
-          'PERMISSION_IMPLIES_UNSUPPORTED_HARDWARE',
-          "Permission exists without corresponding hardware tag `<uses-feature " +
-              "android:name=\"{0}\"  android:required=\"false\">`.",
-          correction:
-              "Try adding the uses-feature with required=\"false\" attribute value.");
+      const ManifestWarningCode('PERMISSION_IMPLIES_UNSUPPORTED_HARDWARE',
+          "Permission makes app incompatible for Chrome OS, consider adding optional {0} feature tag, ",
+          correction: " Try adding `<uses-feature " +
+              "android:name=\"{0}\"  android:required=\"false\">`.");
 
   /**
    * A code indicating that the camera permissions is not supported on Chrome OS.
    */
-  static const ManifestWarningCode CAMERA_PERMISSIONS_INCOMPATIBLE =
-      const ManifestWarningCode(
-          'CAMERA_PERMISSIONS_INCOMPATIBLE',
-          "Permission exists without corresponding hardware `<uses-feature " +
-              "android:name=\"android.hardware.camera\"  android:required=\"false\">` " +
-              "`<uses-feature " +
-              "android:name=\"android.hardware.camera.autofocus\"  android:required=\"false\">`.",
-          correction:
-              "Try adding the uses-feature with required=\"false\" attribute value.");
+  static const ManifestWarningCode CAMERA_PERMISSIONS_INCOMPATIBLE = const ManifestWarningCode(
+      'CAMERA_PERMISSIONS_INCOMPATIBLE',
+      "Camera permissions make app incompatible for Chrome OS, consider adding " +
+          "optional features \"android.hardware.camera\" and \"android.hardware.camera.autofocus\".",
+      correction: "Try adding `<uses-feature " +
+          "android:name=\"android.hardware.camera\"  android:required=\"false\">` " +
+          "`<uses-feature " +
+          "android:name=\"android.hardware.camera.autofocus\"  android:required=\"false\">`.");
 
   /**
    * A code indicating that the activity is set to be non resizable.
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index 431ccb0..6de334c 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -6,6 +6,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
@@ -56,6 +57,7 @@
   final String typeParameters;
 
   List<String> _relevanceTags;
+  Uri _locationLibraryUri;
 
   Declaration({
     @required this.children,
@@ -83,6 +85,8 @@
     @required this.typeParameters,
   }) : _relevanceTags = relevanceTags;
 
+  Uri get locationLibraryUri => _locationLibraryUri;
+
   List<String> get relevanceTags => _relevanceTags;
 
   @override
@@ -473,6 +477,12 @@
     _changedPaths.add(path);
   }
 
+  /// Discard the [analysisContext], but don't discard any libraries that it
+  /// might have in its dependencies.
+  void discardContext(AnalysisContext analysisContext) {
+    _contexts.remove(analysisContext);
+  }
+
   /// Discard all contexts and libraries, notify the [changes] stream that
   /// these libraries are removed.
   void discardContexts() {
@@ -626,19 +636,35 @@
     var file = _getFileByPath(containingContext, path);
     if (file == null) return;
 
-    var isLibrary = file.isLibrary;
-    var library = isLibrary ? file : file.library;
-    if (library == null) return;
+    var wasLibrary = file.isLibrary;
+    var oldLibrary = wasLibrary ? file : file.library;
 
-    if (isLibrary) {
-      file.refresh(containingContext);
-    } else {
-      file.refresh(containingContext);
-      library.refresh(containingContext);
-    }
+    file.refresh(containingContext);
+    var isLibrary = file.isLibrary;
+    var newLibrary = isLibrary ? file : file.library;
 
     var invalidatedLibraries = Set<_File>();
-    _invalidateExportedDeclarations(invalidatedLibraries, library);
+    var notLibraries = <_File>[];
+    if (wasLibrary) {
+      if (isLibrary) {
+        _invalidateExportedDeclarations(invalidatedLibraries, file);
+      } else {
+        notLibraries.add(file);
+        if (newLibrary != null) {
+          newLibrary.refresh(containingContext);
+          _invalidateExportedDeclarations(invalidatedLibraries, newLibrary);
+        }
+      }
+    } else {
+      if (oldLibrary != null) {
+        oldLibrary.refresh(containingContext);
+        _invalidateExportedDeclarations(invalidatedLibraries, oldLibrary);
+      }
+      if (newLibrary != null && newLibrary != oldLibrary) {
+        newLibrary.refresh(containingContext);
+        _invalidateExportedDeclarations(invalidatedLibraries, newLibrary);
+      }
+    }
     _computeExportedDeclarations(invalidatedLibraries);
 
     var changedLibraries = <Library>[];
@@ -659,6 +685,10 @@
         removedLibraries.add(libraryFile.id);
       }
     }
+    for (var file in notLibraries) {
+      _idToLibrary.remove(file.id);
+      removedLibraries.add(file.id);
+    }
     _changesController.add(
       LibraryChange._(changedLibraries, removedLibraries),
     );
@@ -1065,7 +1095,10 @@
 
     // Set back pointers.
     for (var export in exports) {
-      export.file.directExporters.add(this);
+      var directExporters = export.file.directExporters;
+      if (!directExporters.contains(this)) {
+        directExporters.add(this);
+      }
     }
     for (var part in parts) {
       part.file.library = this;
@@ -1080,6 +1113,7 @@
         libraryDeclarations.addAll(part.file.fileDeclarations);
       }
       _computeRelevanceTags(libraryDeclarations);
+      _setLocationLibraryUri();
     }
   }
 
@@ -1353,6 +1387,19 @@
           returnType: _getTypeAnnotationString(functionType.returnType),
           typeParameters: functionType.typeParameters?.toSource(),
         );
+      } else if (node is FunctionTypeAlias) {
+        var parameters = node.parameters;
+        addDeclaration(
+          isDeprecated: isDeprecated,
+          kind: DeclarationKind.FUNCTION_TYPE_ALIAS,
+          name: node.name,
+          parameters: parameters.toSource(),
+          parameterNames: _getFormalParameterNames(parameters),
+          parameterTypes: _getFormalParameterTypes(parameters),
+          requiredParameterCount: _getFormalParameterRequiredCount(parameters),
+          returnType: _getTypeAnnotationString(node.returnType),
+          typeParameters: node.typeParameters?.toSource(),
+        );
       } else if (node is MixinDeclaration) {
         addDeclaration(
           isDeprecated: isDeprecated,
@@ -1479,6 +1526,12 @@
     templateValues = idlFile.directiveInfo.templateValues.toList();
   }
 
+  void _setLocationLibraryUri() {
+    for (var declaration in libraryDeclarations) {
+      declaration._locationLibraryUri = uri;
+    }
+  }
+
   static _DefaultArguments _computeDefaultArguments(
       FormalParameterList parameters) {
     var buffer = StringBuffer();
@@ -1488,6 +1541,10 @@
         if (buffer.isNotEmpty) {
           buffer.write(', ');
         }
+        if (parameter.isNamed) {
+          buffer.write(parameter.identifier.name);
+          buffer.write(': ');
+        }
         var valueOffset = buffer.length;
         buffer.write(parameter.identifier.name);
         var valueLength = buffer.length - valueOffset;
@@ -1527,7 +1584,7 @@
     if (parameters == null) return null;
 
     return parameters.parameters
-        .takeWhile((parameter) => parameter.isRequired)
+        .takeWhile((parameter) => parameter.isRequiredPositional)
         .length;
   }
 
@@ -1588,10 +1645,14 @@
     var source = StringSource(content, '');
 
     var reader = new CharSequenceReader(content);
-    var scanner = new Scanner(null, reader, errorListener);
+    // TODO(paulberry): figure out the appropriate FeatureSet to use here
+    var featureSet = FeatureSet.fromEnableFlags([]);
+    var scanner = new Scanner(null, reader, errorListener)
+      ..configureFeatures(featureSet);
     var token = scanner.tokenize();
 
-    var parser = new Parser(source, errorListener, useFasta: true);
+    var parser = new Parser(source, errorListener,
+        featureSet: featureSet, useFasta: true);
     var unit = parser.parseCompilationUnit(token);
     unit.lineInfo = LineInfo(scanner.lineStarts);
 
@@ -1629,7 +1690,11 @@
 
   @override
   List<_LibraryNode> computeDependencies() {
-    return file.exports.map((e) => e.file).map(walker.getNode).toList();
+    return file.exports
+        .map((export) => export.file)
+        .where((file) => file.isLibrary)
+        .map(walker.getNode)
+        .toList();
   }
 }
 
@@ -1643,8 +1708,11 @@
     resultSet.addAll(file.libraryDeclarations);
 
     for (var export in file.exports) {
-      var exportedDeclarations = export.file.exportedDeclarations;
-      resultSet.addAll(export.filter(exportedDeclarations));
+      var file = export.file;
+      if (file.isLibrary) {
+        var exportedDeclarations = file.exportedDeclarations;
+        resultSet.addAll(export.filter(exportedDeclarations));
+      }
     }
 
     file.exportedDeclarations = resultSet.toList();
diff --git a/pkg/analyzer/lib/src/string_source.dart b/pkg/analyzer/lib/src/string_source.dart
index c2f5f1f..7663db4 100644
--- a/pkg/analyzer/lib/src/string_source.dart
+++ b/pkg/analyzer/lib/src/string_source.dart
@@ -23,9 +23,9 @@
   @override
   final int modificationStamp;
 
-  StringSource(this._contents, String fullName)
+  StringSource(this._contents, String fullName, {Uri uri})
       : this.fullName = fullName,
-        uri = fullName == null ? null : new Uri.file(fullName),
+        uri = uri ?? (fullName == null ? null : new Uri.file(fullName)),
         modificationStamp = new DateTime.now().millisecondsSinceEpoch;
 
   @override
diff --git a/pkg/analyzer/lib/src/summary/expr_builder.dart b/pkg/analyzer/lib/src/summary/expr_builder.dart
index 77bcdd9..7f07f7e 100644
--- a/pkg/analyzer/lib/src/summary/expr_builder.dart
+++ b/pkg/analyzer/lib/src/summary/expr_builder.dart
@@ -673,9 +673,10 @@
     simpleParam.identifier.staticElement = param;
     simpleParam.declaredElement = param;
     var unlinkedParam = (param as ParameterElementImpl).unlinkedParam;
-    if (unlinkedParam.kind == UnlinkedParamKind.positional) {
+    if (unlinkedParam.kind == UnlinkedParamKind.optionalPositional) {
       return AstTestFactory.positionalFormalParameter(simpleParam, null);
-    } else if (unlinkedParam.kind == UnlinkedParamKind.named) {
+    } else if (unlinkedParam.kind == UnlinkedParamKind.requiredNamed ||
+        unlinkedParam.kind == UnlinkedParamKind.optionalNamed) {
       return AstTestFactory.namedFormalParameter(simpleParam, null);
     } else {
       return simpleParam;
diff --git a/pkg/analyzer/lib/src/summary/flat_buffers.dart b/pkg/analyzer/lib/src/summary/flat_buffers.dart
index da60445..96d0719 100644
--- a/pkg/analyzer/lib/src/summary/flat_buffers.dart
+++ b/pkg/analyzer/lib/src/summary/flat_buffers.dart
@@ -89,6 +89,16 @@
   final int initialSize;
 
   /**
+   * The list of field tails, reused by [_VTable] instances.
+   */
+  final Int32List _reusedFieldTails = Int32List(1024);
+
+  /**
+   * The list of field offsets, reused by [_VTable] instances.
+   */
+  final Int32List _reusedFieldOffsets = Int32List(1024);
+
+  /**
    * The list of existing VTable(s).
    */
   final List<_VTable> _vTables = <_VTable>[];
@@ -248,6 +258,7 @@
       }
       // Write a new VTable.
       if (vTableTail == null) {
+        _currentVTable.takeFieldOffsets();
         _prepare(2, _currentVTable.numOfUint16);
         vTableTail = _tail;
         _currentVTable.tail = vTableTail;
@@ -332,7 +343,7 @@
     if (_currentVTable != null) {
       throw new StateError('Inline tables are not supported.');
     }
-    _currentVTable = new _VTable();
+    _currentVTable = new _VTable(_reusedFieldTails, _reusedFieldOffsets);
     _currentTableEndTail = _tail;
   }
 
@@ -570,6 +581,19 @@
 }
 
 /**
+ * The reader of 64-bit floats.
+ */
+class Float64Reader extends Reader<double> {
+  const Float64Reader() : super();
+
+  @override
+  int get size => 8;
+
+  @override
+  double read(BufferContext bc, int offset) => bc._getFloat64(offset);
+}
+
+/**
  * The reader of signed 32-bit integers.
  */
 class Int32Reader extends Reader<int> {
@@ -768,19 +792,6 @@
 }
 
 /**
- * The reader of 64-bit floats.
- */
-class Float64Reader extends Reader<double> {
-  const Float64Reader() : super();
-
-  @override
-  int get size => 8;
-
-  @override
-  double read(BufferContext bc, int offset) => bc._getFloat64(offset);
-}
-
-/**
  * List of booleans backed by 8-bit unsigned integers.
  */
 class _FbBoolList with ListMixin<bool> implements List<bool> {
@@ -905,8 +916,19 @@
  * Class that describes the structure of a table.
  */
 class _VTable {
-  final List<int> fieldTails = <int>[];
-  List<int> fieldOffsets;
+  final Int32List _reusedFieldTails;
+  final Int32List _reusedFieldOffsets;
+
+  /**
+   * The number of fields in [_reusedFieldTails].
+   */
+  int _fieldCount = 0;
+
+  /**
+   * The private copy of [_reusedFieldOffsets], which is made only when we
+   * find that this table is unique.
+   */
+  Int32List _fieldOffsets;
 
   /**
    * The size of the table that uses this VTable.
@@ -919,13 +941,15 @@
    */
   int tail;
 
-  int get numOfUint16 => 1 + 1 + fieldTails.length;
+  _VTable(this._reusedFieldTails, this._reusedFieldOffsets);
+
+  int get numOfUint16 => 1 + 1 + _fieldCount;
 
   void addField(int field, int offset) {
-    while (fieldTails.length <= field) {
-      fieldTails.add(null);
+    while (_fieldCount <= field) {
+      _reusedFieldTails[_fieldCount++] = -1;
     }
-    fieldTails[field] = offset;
+    _reusedFieldTails[field] = offset;
   }
 
   /**
@@ -935,9 +959,9 @@
     assert(tail == null);
     assert(existing.tail != null);
     if (tableSize == existing.tableSize &&
-        fieldOffsets.length == existing.fieldOffsets.length) {
-      for (int i = 0; i < fieldOffsets.length; i++) {
-        if (fieldOffsets[i] != existing.fieldOffsets[i]) {
+        _fieldCount == existing._fieldCount) {
+      for (int i = 0; i < _fieldCount; i++) {
+        if (_reusedFieldOffsets[i] != existing._fieldOffsets[i]) {
           return false;
         }
       }
@@ -947,14 +971,12 @@
   }
 
   /**
-   * Fill the [fieldOffsets] field.
+   * Fill the [_reusedFieldOffsets] field.
    */
   void computeFieldOffsets(int tableTail) {
-    assert(fieldOffsets == null);
-    fieldOffsets = List<int>(fieldTails.length);
-    for (int i = 0; i < fieldTails.length; ++i) {
-      int fieldTail = fieldTails[i];
-      fieldOffsets[i] = fieldTail == null ? 0 : tableTail - fieldTail;
+    for (int i = 0; i < _fieldCount; ++i) {
+      int fieldTail = _reusedFieldTails[i];
+      _reusedFieldOffsets[i] = fieldTail == -1 ? 0 : tableTail - fieldTail;
     }
   }
 
@@ -970,9 +992,20 @@
     buf.setUint16(bufOffset, tableSize, Endian.little);
     bufOffset += 2;
     // Field offsets.
-    for (int fieldOffset in fieldOffsets) {
+    for (int fieldOffset in _fieldOffsets) {
       buf.setUint16(bufOffset, fieldOffset, Endian.little);
       bufOffset += 2;
     }
   }
+
+  /**
+   * Fill the [_fieldOffsets] field.
+   */
+  void takeFieldOffsets() {
+    assert(_fieldOffsets == null);
+    _fieldOffsets = Int32List(_fieldCount);
+    for (int i = 0; i < _fieldCount; ++i) {
+      _fieldOffsets[i] = _reusedFieldOffsets[i];
+    }
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 7b27b6c..c9f3506 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -47,6 +47,22 @@
   }
 }
 
+class _EntityRefNullabilitySuffixReader
+    extends fb.Reader<idl.EntityRefNullabilitySuffix> {
+  const _EntityRefNullabilitySuffixReader() : super();
+
+  @override
+  int get size => 1;
+
+  @override
+  idl.EntityRefNullabilitySuffix read(fb.BufferContext bc, int offset) {
+    int index = const fb.Uint8Reader().read(bc, offset);
+    return index < idl.EntityRefNullabilitySuffix.values.length
+        ? idl.EntityRefNullabilitySuffix.values[index]
+        : idl.EntityRefNullabilitySuffix.starOrIrrelevant;
+  }
+}
+
 class _IndexNameKindReader extends fb.Reader<idl.IndexNameKind> {
   const _IndexNameKindReader() : super();
 
@@ -121,7 +137,7 @@
     int index = const fb.Uint8Reader().read(bc, offset);
     return index < idl.LinkedNodeFormalParameterKind.values.length
         ? idl.LinkedNodeFormalParameterKind.values[index]
-        : idl.LinkedNodeFormalParameterKind.required;
+        : idl.LinkedNodeFormalParameterKind.requiredPositional;
   }
 }
 
@@ -276,7 +292,7 @@
     int index = const fb.Uint8Reader().read(bc, offset);
     return index < idl.UnlinkedParamKind.values.length
         ? idl.UnlinkedParamKind.values[index]
-        : idl.UnlinkedParamKind.required;
+        : idl.UnlinkedParamKind.requiredPositional;
   }
 }
 
@@ -1930,6 +1946,7 @@
   List<String> _referencedNames;
   List<String> _subtypedNames;
   UnlinkedUnitBuilder _unit;
+  UnlinkedUnit2Builder _unit2;
 
   @override
   List<String> get definedClassMemberNames =>
@@ -1973,21 +1990,32 @@
     this._unit = value;
   }
 
+  @override
+  UnlinkedUnit2Builder get unit2 => _unit2;
+
+  /// Unlinked information for the unit.
+  set unit2(UnlinkedUnit2Builder value) {
+    this._unit2 = value;
+  }
+
   AnalysisDriverUnlinkedUnitBuilder(
       {List<String> definedClassMemberNames,
       List<String> definedTopLevelNames,
       List<String> referencedNames,
       List<String> subtypedNames,
-      UnlinkedUnitBuilder unit})
+      UnlinkedUnitBuilder unit,
+      UnlinkedUnit2Builder unit2})
       : _definedClassMemberNames = definedClassMemberNames,
         _definedTopLevelNames = definedTopLevelNames,
         _referencedNames = referencedNames,
         _subtypedNames = subtypedNames,
-        _unit = unit;
+        _unit = unit,
+        _unit2 = unit2;
 
   /// Flush [informative] data recursively.
   void flushInformative() {
     _unit?.flushInformative();
+    _unit2?.flushInformative();
   }
 
   /// Accumulate non-[informative] data into [signature].
@@ -2026,6 +2054,8 @@
         signature.addString(x);
       }
     }
+    signature.addBool(this._unit2 != null);
+    this._unit2?.collectApiSignature(signature);
   }
 
   List<int> toBuffer() {
@@ -2039,6 +2069,7 @@
     fb.Offset offset_referencedNames;
     fb.Offset offset_subtypedNames;
     fb.Offset offset_unit;
+    fb.Offset offset_unit2;
     if (!(_definedClassMemberNames == null ||
         _definedClassMemberNames.isEmpty)) {
       offset_definedClassMemberNames = fbBuilder.writeList(
@@ -2061,6 +2092,9 @@
     if (_unit != null) {
       offset_unit = _unit.finish(fbBuilder);
     }
+    if (_unit2 != null) {
+      offset_unit2 = _unit2.finish(fbBuilder);
+    }
     fbBuilder.startTable();
     if (offset_definedClassMemberNames != null) {
       fbBuilder.addOffset(3, offset_definedClassMemberNames);
@@ -2077,6 +2111,9 @@
     if (offset_unit != null) {
       fbBuilder.addOffset(1, offset_unit);
     }
+    if (offset_unit2 != null) {
+      fbBuilder.addOffset(5, offset_unit2);
+    }
     return fbBuilder.endTable();
   }
 }
@@ -2110,6 +2147,7 @@
   List<String> _referencedNames;
   List<String> _subtypedNames;
   idl.UnlinkedUnit _unit;
+  idl.UnlinkedUnit2 _unit2;
 
   @override
   List<String> get definedClassMemberNames {
@@ -2146,6 +2184,12 @@
     _unit ??= const _UnlinkedUnitReader().vTableGet(_bc, _bcOffset, 1, null);
     return _unit;
   }
+
+  @override
+  idl.UnlinkedUnit2 get unit2 {
+    _unit2 ??= const _UnlinkedUnit2Reader().vTableGet(_bc, _bcOffset, 5, null);
+    return _unit2;
+  }
 }
 
 abstract class _AnalysisDriverUnlinkedUnitMixin
@@ -2161,6 +2205,7 @@
       _result["referencedNames"] = referencedNames;
     if (subtypedNames.isNotEmpty) _result["subtypedNames"] = subtypedNames;
     if (unit != null) _result["unit"] = unit.toJson();
+    if (unit2 != null) _result["unit2"] = unit2.toJson();
     return _result;
   }
 
@@ -2171,6 +2216,7 @@
         "referencedNames": referencedNames,
         "subtypedNames": subtypedNames,
         "unit": unit,
+        "unit2": unit2,
       };
 
   @override
@@ -3610,6 +3656,7 @@
     implements idl.EntityRef {
   idl.EntityRefKind _entityKind;
   List<int> _implicitFunctionTypeIndices;
+  idl.EntityRefNullabilitySuffix _nullabilitySuffix;
   int _paramReference;
   int _reference;
   int _refinedSlot;
@@ -3663,6 +3710,15 @@
   }
 
   @override
+  idl.EntityRefNullabilitySuffix get nullabilitySuffix =>
+      _nullabilitySuffix ??= idl.EntityRefNullabilitySuffix.starOrIrrelevant;
+
+  /// If the reference represents a type, the nullability of the type.
+  set nullabilitySuffix(idl.EntityRefNullabilitySuffix value) {
+    this._nullabilitySuffix = value;
+  }
+
+  @override
   int get paramReference => _paramReference ??= 0;
 
   /// If this is a reference to a type parameter, one-based index into the list
@@ -3774,6 +3830,7 @@
   EntityRefBuilder(
       {idl.EntityRefKind entityKind,
       List<int> implicitFunctionTypeIndices,
+      idl.EntityRefNullabilitySuffix nullabilitySuffix,
       int paramReference,
       int reference,
       int refinedSlot,
@@ -3784,6 +3841,7 @@
       List<UnlinkedTypeParamBuilder> typeParameters})
       : _entityKind = entityKind,
         _implicitFunctionTypeIndices = implicitFunctionTypeIndices,
+        _nullabilitySuffix = nullabilitySuffix,
         _paramReference = paramReference,
         _reference = reference,
         _refinedSlot = refinedSlot,
@@ -3842,6 +3900,8 @@
     }
     signature.addInt(this._entityKind == null ? 0 : this._entityKind.index);
     signature.addInt(this._refinedSlot ?? 0);
+    signature.addInt(
+        this._nullabilitySuffix == null ? 0 : this._nullabilitySuffix.index);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -3877,6 +3937,10 @@
     if (offset_implicitFunctionTypeIndices != null) {
       fbBuilder.addOffset(4, offset_implicitFunctionTypeIndices);
     }
+    if (_nullabilitySuffix != null &&
+        _nullabilitySuffix != idl.EntityRefNullabilitySuffix.starOrIrrelevant) {
+      fbBuilder.addUint8(10, _nullabilitySuffix.index);
+    }
     if (_paramReference != null && _paramReference != 0) {
       fbBuilder.addUint32(3, _paramReference);
     }
@@ -3923,6 +3987,7 @@
 
   idl.EntityRefKind _entityKind;
   List<int> _implicitFunctionTypeIndices;
+  idl.EntityRefNullabilitySuffix _nullabilitySuffix;
   int _paramReference;
   int _reference;
   int _refinedSlot;
@@ -3947,6 +4012,13 @@
   }
 
   @override
+  idl.EntityRefNullabilitySuffix get nullabilitySuffix {
+    _nullabilitySuffix ??= const _EntityRefNullabilitySuffixReader().vTableGet(
+        _bc, _bcOffset, 10, idl.EntityRefNullabilitySuffix.starOrIrrelevant);
+    return _nullabilitySuffix;
+  }
+
+  @override
   int get paramReference {
     _paramReference ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
     return _paramReference;
@@ -4010,6 +4082,8 @@
       _result["entityKind"] = entityKind.toString().split('.')[1];
     if (implicitFunctionTypeIndices.isNotEmpty)
       _result["implicitFunctionTypeIndices"] = implicitFunctionTypeIndices;
+    if (nullabilitySuffix != idl.EntityRefNullabilitySuffix.starOrIrrelevant)
+      _result["nullabilitySuffix"] = nullabilitySuffix.toString().split('.')[1];
     if (paramReference != 0) _result["paramReference"] = paramReference;
     if (reference != 0) _result["reference"] = reference;
     if (refinedSlot != 0) _result["refinedSlot"] = refinedSlot;
@@ -4032,6 +4106,7 @@
   Map<String, Object> toMap() => {
         "entityKind": entityKind,
         "implicitFunctionTypeIndices": implicitFunctionTypeIndices,
+        "nullabilitySuffix": nullabilitySuffix,
         "paramReference": paramReference,
         "reference": reference,
         "refinedSlot": refinedSlot,
@@ -4648,39 +4723,42 @@
     implements idl.LinkedNode {
   LinkedNodeTypeBuilder _variantField_24;
   List<LinkedNodeBuilder> _variantField_2;
-  LinkedNodeBuilder _variantField_11;
   List<LinkedNodeBuilder> _variantField_4;
   LinkedNodeBuilder _variantField_6;
-  int _variantField_15;
   LinkedNodeBuilder _variantField_7;
-  LinkedNodeBuilder _variantField_8;
-  int _variantField_16;
   int _variantField_17;
-  int _variantField_18;
-  int _variantField_19;
   LinkedNodeTypeBuilder _variantField_23;
+  LinkedNodeBuilder _variantField_8;
+  int _variantField_15;
+  idl.UnlinkedTokenType _variantField_28;
   bool _variantField_27;
   LinkedNodeBuilder _variantField_9;
   LinkedNodeBuilder _variantField_12;
   List<LinkedNodeBuilder> _variantField_5;
   LinkedNodeBuilder _variantField_13;
-  int _variantField_34;
-  int _variantField_33;
-  List<int> _variantField_28;
+  List<String> _variantField_33;
   idl.LinkedNodeCommentType _variantField_29;
   List<LinkedNodeBuilder> _variantField_3;
   LinkedNodeBuilder _variantField_10;
+  idl.LinkedNodeFormalParameterKind _variantField_26;
   double _variantField_21;
   LinkedNodeTypeBuilder _variantField_25;
-  idl.LinkedNodeFormalParameterKind _variantField_26;
+  int _flags;
+  String _variantField_1;
+  int _variantField_36;
+  int _variantField_16;
   String _variantField_30;
   LinkedNodeBuilder _variantField_14;
-  bool _isSynthetic;
   idl.LinkedNodeKind _kind;
+  List<String> _variantField_34;
+  String _name;
   String _variantField_20;
   bool _variantField_31;
+  idl.UnlinkedTokenType _variantField_35;
+  TopLevelInferenceErrorBuilder _variantField_32;
+  LinkedNodeBuilder _variantField_11;
   String _variantField_22;
-  LinkedNodeVariablesDeclarationBuilder _variantField_32;
+  int _variantField_19;
 
   @override
   LinkedNodeTypeBuilder get actualReturnType {
@@ -4768,6 +4846,12 @@
   }
 
   @override
+  List<LinkedNodeBuilder> get comment_references {
+    assert(kind == idl.LinkedNodeKind.comment);
+    return _variantField_2 ??= <LinkedNodeBuilder>[];
+  }
+
+  @override
   List<LinkedNodeBuilder> get compilationUnit_declarations {
     assert(kind == idl.LinkedNodeKind.compilationUnit);
     return _variantField_2 ??= <LinkedNodeBuilder>[];
@@ -4798,14 +4882,14 @@
   }
 
   @override
-  List<LinkedNodeBuilder> get hideCombinator_hiddenNames {
-    assert(kind == idl.LinkedNodeKind.hideCombinator);
+  List<LinkedNodeBuilder> get implementsClause_interfaces {
+    assert(kind == idl.LinkedNodeKind.implementsClause);
     return _variantField_2 ??= <LinkedNodeBuilder>[];
   }
 
   @override
-  List<LinkedNodeBuilder> get implementsClause_interfaces {
-    assert(kind == idl.LinkedNodeKind.implementsClause);
+  List<LinkedNodeBuilder> get instanceCreationExpression_arguments {
+    assert(kind == idl.LinkedNodeKind.instanceCreationExpression);
     return _variantField_2 ??= <LinkedNodeBuilder>[];
   }
 
@@ -4822,12 +4906,6 @@
   }
 
   @override
-  List<LinkedNodeBuilder> get listLiteral_elements {
-    assert(kind == idl.LinkedNodeKind.listLiteral);
-    return _variantField_2 ??= <LinkedNodeBuilder>[];
-  }
-
-  @override
   List<LinkedNodeBuilder> get namespaceDirective_combinators {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective);
@@ -4841,18 +4919,6 @@
   }
 
   @override
-  List<LinkedNodeBuilder> get setOrMapLiteral_elements {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    return _variantField_2 ??= <LinkedNodeBuilder>[];
-  }
-
-  @override
-  List<LinkedNodeBuilder> get showCombinator_shownNames {
-    assert(kind == idl.LinkedNodeKind.showCombinator);
-    return _variantField_2 ??= <LinkedNodeBuilder>[];
-  }
-
-  @override
   List<LinkedNodeBuilder> get stringInterpolation_elements {
     assert(kind == idl.LinkedNodeKind.stringInterpolation);
     return _variantField_2 ??= <LinkedNodeBuilder>[];
@@ -4877,6 +4943,19 @@
   }
 
   @override
+  List<LinkedNodeBuilder> get typedLiteral_typeArguments {
+    assert(kind == idl.LinkedNodeKind.listLiteral ||
+        kind == idl.LinkedNodeKind.setOrMapLiteral);
+    return _variantField_2 ??= <LinkedNodeBuilder>[];
+  }
+
+  @override
+  List<LinkedNodeBuilder> get typeName_typeArguments {
+    assert(kind == idl.LinkedNodeKind.typeName);
+    return _variantField_2 ??= <LinkedNodeBuilder>[];
+  }
+
+  @override
   List<LinkedNodeBuilder> get typeParameterList_typeParameters {
     assert(kind == idl.LinkedNodeKind.typeParameterList);
     return _variantField_2 ??= <LinkedNodeBuilder>[];
@@ -4914,6 +4993,11 @@
     _variantField_2 = value;
   }
 
+  set comment_references(List<LinkedNodeBuilder> value) {
+    assert(kind == idl.LinkedNodeKind.comment);
+    _variantField_2 = value;
+  }
+
   set compilationUnit_declarations(List<LinkedNodeBuilder> value) {
     assert(kind == idl.LinkedNodeKind.compilationUnit);
     _variantField_2 = value;
@@ -4939,13 +5023,13 @@
     _variantField_2 = value;
   }
 
-  set hideCombinator_hiddenNames(List<LinkedNodeBuilder> value) {
-    assert(kind == idl.LinkedNodeKind.hideCombinator);
+  set implementsClause_interfaces(List<LinkedNodeBuilder> value) {
+    assert(kind == idl.LinkedNodeKind.implementsClause);
     _variantField_2 = value;
   }
 
-  set implementsClause_interfaces(List<LinkedNodeBuilder> value) {
-    assert(kind == idl.LinkedNodeKind.implementsClause);
+  set instanceCreationExpression_arguments(List<LinkedNodeBuilder> value) {
+    assert(kind == idl.LinkedNodeKind.instanceCreationExpression);
     _variantField_2 = value;
   }
 
@@ -4959,11 +5043,6 @@
     _variantField_2 = value;
   }
 
-  set listLiteral_elements(List<LinkedNodeBuilder> value) {
-    assert(kind == idl.LinkedNodeKind.listLiteral);
-    _variantField_2 = value;
-  }
-
   set namespaceDirective_combinators(List<LinkedNodeBuilder> value) {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective);
@@ -4975,16 +5054,6 @@
     _variantField_2 = value;
   }
 
-  set setOrMapLiteral_elements(List<LinkedNodeBuilder> value) {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    _variantField_2 = value;
-  }
-
-  set showCombinator_shownNames(List<LinkedNodeBuilder> value) {
-    assert(kind == idl.LinkedNodeKind.showCombinator);
-    _variantField_2 = value;
-  }
-
   set stringInterpolation_elements(List<LinkedNodeBuilder> value) {
     assert(kind == idl.LinkedNodeKind.stringInterpolation);
     _variantField_2 = value;
@@ -5005,6 +5074,17 @@
     _variantField_2 = value;
   }
 
+  set typedLiteral_typeArguments(List<LinkedNodeBuilder> value) {
+    assert(kind == idl.LinkedNodeKind.listLiteral ||
+        kind == idl.LinkedNodeKind.setOrMapLiteral);
+    _variantField_2 = value;
+  }
+
+  set typeName_typeArguments(List<LinkedNodeBuilder> value) {
+    assert(kind == idl.LinkedNodeKind.typeName);
+    _variantField_2 = value;
+  }
+
   set typeParameterList_typeParameters(List<LinkedNodeBuilder> value) {
     assert(kind == idl.LinkedNodeKind.typeParameterList);
     _variantField_2 = value;
@@ -5021,57 +5101,6 @@
   }
 
   @override
-  LinkedNodeBuilder get annotatedNode_comment {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.declaredIdentifier ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
-        kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.fieldDeclaration ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.libraryDirective ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.partOfDirective ||
-        kind == idl.LinkedNodeKind.topLevelVariableDeclaration ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration ||
-        kind == idl.LinkedNodeKind.variableDeclarationList);
-    return _variantField_11;
-  }
-
-  set annotatedNode_comment(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.declaredIdentifier ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
-        kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.fieldDeclaration ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.libraryDirective ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.partOfDirective ||
-        kind == idl.LinkedNodeKind.topLevelVariableDeclaration ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration ||
-        kind == idl.LinkedNodeKind.variableDeclarationList);
-    _variantField_11 = value;
-  }
-
-  @override
   List<LinkedNodeBuilder> get annotatedNode_metadata {
     assert(kind == idl.LinkedNodeKind.classDeclaration ||
         kind == idl.LinkedNodeKind.classTypeAlias ||
@@ -5229,6 +5258,12 @@
   }
 
   @override
+  LinkedNodeBuilder get commentReference_identifier {
+    assert(kind == idl.LinkedNodeKind.commentReference);
+    return _variantField_6;
+  }
+
+  @override
   LinkedNodeBuilder get compilationUnit_scriptTag {
     assert(kind == idl.LinkedNodeKind.compilationUnit);
     return _variantField_6;
@@ -5289,12 +5324,6 @@
   }
 
   @override
-  LinkedNodeBuilder get enumConstantDeclaration_name {
-    assert(kind == idl.LinkedNodeKind.enumConstantDeclaration);
-    return _variantField_6;
-  }
-
-  @override
   LinkedNodeBuilder get expressionFunctionBody_expression {
     assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
     return _variantField_6;
@@ -5401,24 +5430,12 @@
   }
 
   @override
-  LinkedNodeBuilder get importDirective_prefix {
-    assert(kind == idl.LinkedNodeKind.importDirective);
-    return _variantField_6;
-  }
-
-  @override
   LinkedNodeBuilder get indexExpression_index {
     assert(kind == idl.LinkedNodeKind.indexExpression);
     return _variantField_6;
   }
 
   @override
-  LinkedNodeBuilder get instanceCreationExpression_arguments {
-    assert(kind == idl.LinkedNodeKind.instanceCreationExpression);
-    return _variantField_6;
-  }
-
-  @override
   LinkedNodeBuilder get interpolationExpression_expression {
     assert(kind == idl.LinkedNodeKind.interpolationExpression);
     return _variantField_6;
@@ -5687,6 +5704,11 @@
     _variantField_6 = value;
   }
 
+  set commentReference_identifier(LinkedNodeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.commentReference);
+    _variantField_6 = value;
+  }
+
   set compilationUnit_scriptTag(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.compilationUnit);
     _variantField_6 = value;
@@ -5737,11 +5759,6 @@
     _variantField_6 = value;
   }
 
-  set enumConstantDeclaration_name(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.enumConstantDeclaration);
-    _variantField_6 = value;
-  }
-
   set expressionFunctionBody_expression(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
     _variantField_6 = value;
@@ -5832,21 +5849,11 @@
     _variantField_6 = value;
   }
 
-  set importDirective_prefix(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.importDirective);
-    _variantField_6 = value;
-  }
-
   set indexExpression_index(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.indexExpression);
     _variantField_6 = value;
   }
 
-  set instanceCreationExpression_arguments(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.instanceCreationExpression);
-    _variantField_6 = value;
-  }
-
   set interpolationExpression_expression(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.interpolationExpression);
     _variantField_6 = value;
@@ -6018,1120 +6025,6 @@
   }
 
   @override
-  int get annotation_atSign {
-    assert(kind == idl.LinkedNodeKind.annotation);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get argumentList_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.argumentList);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get asExpression_asOperator {
-    assert(kind == idl.LinkedNodeKind.asExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get assertInitializer_assertKeyword {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get assertStatement_assertKeyword {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get assignmentExpression_element {
-    assert(kind == idl.LinkedNodeKind.assignmentExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get awaitExpression_awaitKeyword {
-    assert(kind == idl.LinkedNodeKind.awaitExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get binaryExpression_element {
-    assert(kind == idl.LinkedNodeKind.binaryExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get block_leftBracket {
-    assert(kind == idl.LinkedNodeKind.block);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get blockFunctionBody_keyword {
-    assert(kind == idl.LinkedNodeKind.blockFunctionBody);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get booleanLiteral_literal {
-    assert(kind == idl.LinkedNodeKind.booleanLiteral);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get breakStatement_breakKeyword {
-    assert(kind == idl.LinkedNodeKind.breakStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get catchClause_catchKeyword {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get classDeclaration_abstractKeyword {
-    assert(kind == idl.LinkedNodeKind.classDeclaration);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get classTypeAlias_abstractKeyword {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get compilationUnit_beginToken {
-    assert(kind == idl.LinkedNodeKind.compilationUnit);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get conditionalExpression_colon {
-    assert(kind == idl.LinkedNodeKind.conditionalExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get configuration_ifKeyword {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get constructorDeclaration_constKeyword {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get constructorFieldInitializer_equals {
-    assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get constructorName_element {
-    assert(kind == idl.LinkedNodeKind.constructorName);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get continueStatement_continueKeyword {
-    assert(kind == idl.LinkedNodeKind.continueStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get declaredIdentifier_keyword {
-    assert(kind == idl.LinkedNodeKind.declaredIdentifier);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get defaultFormalParameter_separator {
-    assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get doStatement_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get doubleLiteral_literal {
-    assert(kind == idl.LinkedNodeKind.doubleLiteral);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get emptyFunctionBody_semicolon {
-    assert(kind == idl.LinkedNodeKind.emptyFunctionBody);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get emptyStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.emptyStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get enumDeclaration_enumKeyword {
-    assert(kind == idl.LinkedNodeKind.enumDeclaration);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get expressionFunctionBody_arrow {
-    assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get expressionStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.expressionStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get extendsClause_extendsKeyword {
-    assert(kind == idl.LinkedNodeKind.extendsClause);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get fieldDeclaration_covariantKeyword {
-    assert(kind == idl.LinkedNodeKind.fieldDeclaration);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get fieldFormalParameter_keyword {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get forEachParts_inKeyword {
-    assert(kind == idl.LinkedNodeKind.forEachPartsWithDeclaration ||
-        kind == idl.LinkedNodeKind.forEachPartsWithIdentifier);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get formalParameterList_leftDelimiter {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get forMixin_awaitKeyword {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get forParts_leftSeparator {
-    assert(kind == idl.LinkedNodeKind.forPartsWithDeclarations ||
-        kind == idl.LinkedNodeKind.forPartsWithExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get functionDeclaration_externalKeyword {
-    assert(kind == idl.LinkedNodeKind.functionDeclaration);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get genericFunctionType_functionKeyword {
-    assert(kind == idl.LinkedNodeKind.genericFunctionType);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get ifMixin_elseKeyword {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get implementsClause_implementsKeyword {
-    assert(kind == idl.LinkedNodeKind.implementsClause);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get importDirective_asKeyword {
-    assert(kind == idl.LinkedNodeKind.importDirective);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get indexExpression_element {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get instanceCreationExpression_keyword {
-    assert(kind == idl.LinkedNodeKind.instanceCreationExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get integerLiteral_literal {
-    assert(kind == idl.LinkedNodeKind.integerLiteral);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get interpolationExpression_leftBracket {
-    assert(kind == idl.LinkedNodeKind.interpolationExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get interpolationString_token {
-    assert(kind == idl.LinkedNodeKind.interpolationString);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get isExpression_isOperator {
-    assert(kind == idl.LinkedNodeKind.isExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get label_colon {
-    assert(kind == idl.LinkedNodeKind.label);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get listLiteral_leftBracket {
-    assert(kind == idl.LinkedNodeKind.listLiteral);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get mapLiteralEntry_separator {
-    assert(kind == idl.LinkedNodeKind.mapLiteralEntry);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get methodDeclaration_externalKeyword {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get methodInvocation_operator {
-    assert(kind == idl.LinkedNodeKind.methodInvocation);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get mixinDeclaration_mixinKeyword {
-    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get nativeClause_nativeKeyword {
-    assert(kind == idl.LinkedNodeKind.nativeClause);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get nativeFunctionBody_nativeKeyword {
-    assert(kind == idl.LinkedNodeKind.nativeFunctionBody);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get nullLiteral_literal {
-    assert(kind == idl.LinkedNodeKind.nullLiteral);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get onClause_onKeyword {
-    assert(kind == idl.LinkedNodeKind.onClause);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get parenthesizedExpression_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.parenthesizedExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get postfixExpression_element {
-    assert(kind == idl.LinkedNodeKind.postfixExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get prefixedIdentifier_period {
-    assert(kind == idl.LinkedNodeKind.prefixedIdentifier);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get prefixExpression_element {
-    assert(kind == idl.LinkedNodeKind.prefixExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get propertyAccess_operator {
-    assert(kind == idl.LinkedNodeKind.propertyAccess);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get redirectingConstructorInvocation_element {
-    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get rethrowExpression_rethrowKeyword {
-    assert(kind == idl.LinkedNodeKind.rethrowExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get returnStatement_returnKeyword {
-    assert(kind == idl.LinkedNodeKind.returnStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get scriptTag_scriptTag {
-    assert(kind == idl.LinkedNodeKind.scriptTag);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get setOrMapLiteral_leftBracket {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get simpleFormalParameter_keyword {
-    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get simpleIdentifier_element {
-    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get simpleStringLiteral_token {
-    assert(kind == idl.LinkedNodeKind.simpleStringLiteral);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get spreadElement_spreadOperator {
-    assert(kind == idl.LinkedNodeKind.spreadElement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get superConstructorInvocation_element {
-    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get superExpression_superKeyword {
-    assert(kind == idl.LinkedNodeKind.superExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get switchMember_keyword {
-    assert(kind == idl.LinkedNodeKind.switchCase ||
-        kind == idl.LinkedNodeKind.switchDefault);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get switchStatement_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get symbolLiteral_poundSign {
-    assert(kind == idl.LinkedNodeKind.symbolLiteral);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get thisExpression_thisKeyword {
-    assert(kind == idl.LinkedNodeKind.thisExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get throwExpression_throwKeyword {
-    assert(kind == idl.LinkedNodeKind.throwExpression);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get topLevelVariableDeclaration_semicolon {
-    assert(kind == idl.LinkedNodeKind.topLevelVariableDeclaration);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get tryStatement_finallyKeyword {
-    assert(kind == idl.LinkedNodeKind.tryStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get typeArgumentList_leftBracket {
-    assert(kind == idl.LinkedNodeKind.typeArgumentList);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get typeName_question {
-    assert(kind == idl.LinkedNodeKind.typeName);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get typeParameter_extendsKeyword {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get typeParameterList_leftBracket {
-    assert(kind == idl.LinkedNodeKind.typeParameterList);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get variableDeclaration_equals {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get variableDeclarationList_keyword {
-    assert(kind == idl.LinkedNodeKind.variableDeclarationList);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get variableDeclarationStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.variableDeclarationStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get whileStatement_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.whileStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get withClause_withKeyword {
-    assert(kind == idl.LinkedNodeKind.withClause);
-    return _variantField_15 ??= 0;
-  }
-
-  @override
-  int get yieldStatement_yieldKeyword {
-    assert(kind == idl.LinkedNodeKind.yieldStatement);
-    return _variantField_15 ??= 0;
-  }
-
-  set annotation_atSign(int value) {
-    assert(kind == idl.LinkedNodeKind.annotation);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set argumentList_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.argumentList);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set asExpression_asOperator(int value) {
-    assert(kind == idl.LinkedNodeKind.asExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set assertInitializer_assertKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set assertStatement_assertKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set assignmentExpression_element(int value) {
-    assert(kind == idl.LinkedNodeKind.assignmentExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set awaitExpression_awaitKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.awaitExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set binaryExpression_element(int value) {
-    assert(kind == idl.LinkedNodeKind.binaryExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set block_leftBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.block);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set blockFunctionBody_keyword(int value) {
-    assert(kind == idl.LinkedNodeKind.blockFunctionBody);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set booleanLiteral_literal(int value) {
-    assert(kind == idl.LinkedNodeKind.booleanLiteral);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set breakStatement_breakKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.breakStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set catchClause_catchKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set classDeclaration_abstractKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.classDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set classTypeAlias_abstractKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set compilationUnit_beginToken(int value) {
-    assert(kind == idl.LinkedNodeKind.compilationUnit);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set conditionalExpression_colon(int value) {
-    assert(kind == idl.LinkedNodeKind.conditionalExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set configuration_ifKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set constructorDeclaration_constKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set constructorFieldInitializer_equals(int value) {
-    assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set constructorName_element(int value) {
-    assert(kind == idl.LinkedNodeKind.constructorName);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set continueStatement_continueKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.continueStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set declaredIdentifier_keyword(int value) {
-    assert(kind == idl.LinkedNodeKind.declaredIdentifier);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set defaultFormalParameter_separator(int value) {
-    assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set doStatement_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set doubleLiteral_literal(int value) {
-    assert(kind == idl.LinkedNodeKind.doubleLiteral);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set emptyFunctionBody_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.emptyFunctionBody);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set emptyStatement_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.emptyStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set enumDeclaration_enumKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.enumDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set expressionFunctionBody_arrow(int value) {
-    assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set expressionStatement_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.expressionStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set extendsClause_extendsKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.extendsClause);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set fieldDeclaration_covariantKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.fieldDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set fieldFormalParameter_keyword(int value) {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set forEachParts_inKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.forEachPartsWithDeclaration ||
-        kind == idl.LinkedNodeKind.forEachPartsWithIdentifier);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set formalParameterList_leftDelimiter(int value) {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set forMixin_awaitKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set forParts_leftSeparator(int value) {
-    assert(kind == idl.LinkedNodeKind.forPartsWithDeclarations ||
-        kind == idl.LinkedNodeKind.forPartsWithExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set functionDeclaration_externalKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.functionDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set genericFunctionType_functionKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.genericFunctionType);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set ifMixin_elseKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set implementsClause_implementsKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.implementsClause);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set importDirective_asKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.importDirective);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set indexExpression_element(int value) {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set instanceCreationExpression_keyword(int value) {
-    assert(kind == idl.LinkedNodeKind.instanceCreationExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set integerLiteral_literal(int value) {
-    assert(kind == idl.LinkedNodeKind.integerLiteral);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set interpolationExpression_leftBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.interpolationExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set interpolationString_token(int value) {
-    assert(kind == idl.LinkedNodeKind.interpolationString);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set isExpression_isOperator(int value) {
-    assert(kind == idl.LinkedNodeKind.isExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set label_colon(int value) {
-    assert(kind == idl.LinkedNodeKind.label);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set listLiteral_leftBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.listLiteral);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set mapLiteralEntry_separator(int value) {
-    assert(kind == idl.LinkedNodeKind.mapLiteralEntry);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set methodDeclaration_externalKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set methodInvocation_operator(int value) {
-    assert(kind == idl.LinkedNodeKind.methodInvocation);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set mixinDeclaration_mixinKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set nativeClause_nativeKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.nativeClause);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set nativeFunctionBody_nativeKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.nativeFunctionBody);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set nullLiteral_literal(int value) {
-    assert(kind == idl.LinkedNodeKind.nullLiteral);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set onClause_onKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.onClause);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set parenthesizedExpression_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.parenthesizedExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set postfixExpression_element(int value) {
-    assert(kind == idl.LinkedNodeKind.postfixExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set prefixedIdentifier_period(int value) {
-    assert(kind == idl.LinkedNodeKind.prefixedIdentifier);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set prefixExpression_element(int value) {
-    assert(kind == idl.LinkedNodeKind.prefixExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set propertyAccess_operator(int value) {
-    assert(kind == idl.LinkedNodeKind.propertyAccess);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set redirectingConstructorInvocation_element(int value) {
-    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set rethrowExpression_rethrowKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.rethrowExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set returnStatement_returnKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.returnStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set scriptTag_scriptTag(int value) {
-    assert(kind == idl.LinkedNodeKind.scriptTag);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set setOrMapLiteral_leftBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set simpleFormalParameter_keyword(int value) {
-    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set simpleIdentifier_element(int value) {
-    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set simpleStringLiteral_token(int value) {
-    assert(kind == idl.LinkedNodeKind.simpleStringLiteral);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set spreadElement_spreadOperator(int value) {
-    assert(kind == idl.LinkedNodeKind.spreadElement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set superConstructorInvocation_element(int value) {
-    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set superExpression_superKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.superExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set switchMember_keyword(int value) {
-    assert(kind == idl.LinkedNodeKind.switchCase ||
-        kind == idl.LinkedNodeKind.switchDefault);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set switchStatement_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set symbolLiteral_poundSign(int value) {
-    assert(kind == idl.LinkedNodeKind.symbolLiteral);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set thisExpression_thisKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.thisExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set throwExpression_throwKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.throwExpression);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set topLevelVariableDeclaration_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.topLevelVariableDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set tryStatement_finallyKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.tryStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set typeArgumentList_leftBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.typeArgumentList);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set typeName_question(int value) {
-    assert(kind == idl.LinkedNodeKind.typeName);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set typeParameter_extendsKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set typeParameterList_leftBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.typeParameterList);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set variableDeclaration_equals(int value) {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set variableDeclarationList_keyword(int value) {
-    assert(kind == idl.LinkedNodeKind.variableDeclarationList);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set variableDeclarationStatement_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.variableDeclarationStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set whileStatement_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.whileStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set withClause_withKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.withClause);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  set yieldStatement_yieldKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.yieldStatement);
-    assert(value == null || value >= 0);
-    _variantField_15 = value;
-  }
-
-  @override
   LinkedNodeBuilder get annotation_constructorName {
     assert(kind == idl.LinkedNodeKind.annotation);
     return _variantField_7;
@@ -7198,12 +6091,6 @@
   }
 
   @override
-  LinkedNodeBuilder get constructorDeclaration_name {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    return _variantField_7;
-  }
-
-  @override
   LinkedNodeBuilder get constructorFieldInitializer_fieldName {
     assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
     return _variantField_7;
@@ -7402,24 +6289,6 @@
   }
 
   @override
-  LinkedNodeBuilder get typeName_typeArguments {
-    assert(kind == idl.LinkedNodeKind.typeName);
-    return _variantField_7;
-  }
-
-  @override
-  LinkedNodeBuilder get typeParameter_name {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    return _variantField_7;
-  }
-
-  @override
-  LinkedNodeBuilder get variableDeclaration_name {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    return _variantField_7;
-  }
-
-  @override
   LinkedNodeBuilder get whileStatement_condition {
     assert(kind == idl.LinkedNodeKind.whileStatement);
     return _variantField_7;
@@ -7480,11 +6349,6 @@
     _variantField_7 = value;
   }
 
-  set constructorDeclaration_name(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    _variantField_7 = value;
-  }
-
   set constructorFieldInitializer_fieldName(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
     _variantField_7 = value;
@@ -7651,27 +6515,169 @@
     _variantField_7 = value;
   }
 
-  set typeName_typeArguments(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.typeName);
-    _variantField_7 = value;
-  }
-
-  set typeParameter_name(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    _variantField_7 = value;
-  }
-
-  set variableDeclaration_name(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_7 = value;
-  }
-
   set whileStatement_condition(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.whileStatement);
     _variantField_7 = value;
   }
 
   @override
+  int get annotation_element {
+    assert(kind == idl.LinkedNodeKind.annotation);
+    return _variantField_17 ??= 0;
+  }
+
+  @override
+  int get genericFunctionType_id {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    return _variantField_17 ??= 0;
+  }
+
+  set annotation_element(int value) {
+    assert(kind == idl.LinkedNodeKind.annotation);
+    assert(value == null || value >= 0);
+    _variantField_17 = value;
+  }
+
+  set genericFunctionType_id(int value) {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    assert(value == null || value >= 0);
+    _variantField_17 = value;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get annotation_elementType {
+    assert(kind == idl.LinkedNodeKind.annotation);
+    return _variantField_23;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get assignmentExpression_elementType {
+    assert(kind == idl.LinkedNodeKind.assignmentExpression);
+    return _variantField_23;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get binaryExpression_elementType {
+    assert(kind == idl.LinkedNodeKind.binaryExpression);
+    return _variantField_23;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get constructorName_elementType {
+    assert(kind == idl.LinkedNodeKind.constructorName);
+    return _variantField_23;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get indexExpression_elementType {
+    assert(kind == idl.LinkedNodeKind.indexExpression);
+    return _variantField_23;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get postfixExpression_elementType {
+    assert(kind == idl.LinkedNodeKind.postfixExpression);
+    return _variantField_23;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get prefixExpression_elementType {
+    assert(kind == idl.LinkedNodeKind.prefixExpression);
+    return _variantField_23;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get redirectingConstructorInvocation_elementType {
+    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
+    return _variantField_23;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get simpleIdentifier_elementType {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+    return _variantField_23;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get superConstructorInvocation_elementType {
+    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
+    return _variantField_23;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get typeName_type {
+    assert(kind == idl.LinkedNodeKind.typeName);
+    return _variantField_23;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get typeParameter_defaultType {
+    assert(kind == idl.LinkedNodeKind.typeParameter);
+    return _variantField_23;
+  }
+
+  set annotation_elementType(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.annotation);
+    _variantField_23 = value;
+  }
+
+  set assignmentExpression_elementType(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.assignmentExpression);
+    _variantField_23 = value;
+  }
+
+  set binaryExpression_elementType(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.binaryExpression);
+    _variantField_23 = value;
+  }
+
+  set constructorName_elementType(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.constructorName);
+    _variantField_23 = value;
+  }
+
+  set indexExpression_elementType(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.indexExpression);
+    _variantField_23 = value;
+  }
+
+  set postfixExpression_elementType(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.postfixExpression);
+    _variantField_23 = value;
+  }
+
+  set prefixExpression_elementType(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.prefixExpression);
+    _variantField_23 = value;
+  }
+
+  set redirectingConstructorInvocation_elementType(
+      LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
+    _variantField_23 = value;
+  }
+
+  set simpleIdentifier_elementType(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+    _variantField_23 = value;
+  }
+
+  set superConstructorInvocation_elementType(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
+    _variantField_23 = value;
+  }
+
+  set typeName_type(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.typeName);
+    _variantField_23 = value;
+  }
+
+  set typeParameter_defaultType(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.typeParameter);
+    _variantField_23 = value;
+  }
+
+  @override
   LinkedNodeBuilder get annotation_name {
     assert(kind == idl.LinkedNodeKind.annotation);
     return _variantField_8;
@@ -7848,1410 +6854,214 @@
   }
 
   @override
-  int get annotation_period {
-    assert(kind == idl.LinkedNodeKind.annotation);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get argumentList_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.argumentList);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get assertInitializer_comma {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get assertStatement_comma {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get assignmentExpression_operator {
+  int get assignmentExpression_element {
     assert(kind == idl.LinkedNodeKind.assignmentExpression);
-    return _variantField_16 ??= 0;
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get binaryExpression_operator {
+  int get binaryExpression_element {
     assert(kind == idl.LinkedNodeKind.binaryExpression);
-    return _variantField_16 ??= 0;
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get block_rightBracket {
-    assert(kind == idl.LinkedNodeKind.block);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get blockFunctionBody_star {
-    assert(kind == idl.LinkedNodeKind.blockFunctionBody);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get breakStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.breakStatement);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get catchClause_comma {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get classDeclaration_classKeyword {
-    assert(kind == idl.LinkedNodeKind.classDeclaration);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get classTypeAlias_equals {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get compilationUnit_endToken {
-    assert(kind == idl.LinkedNodeKind.compilationUnit);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get conditionalExpression_question {
-    assert(kind == idl.LinkedNodeKind.conditionalExpression);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get configuration_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get constructorDeclaration_externalKeyword {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get constructorFieldInitializer_period {
-    assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get constructorName_period {
+  int get constructorName_element {
     assert(kind == idl.LinkedNodeKind.constructorName);
-    return _variantField_16 ??= 0;
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get continueStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.continueStatement);
-    return _variantField_16 ??= 0;
+  int get emptyFunctionBody_fake {
+    assert(kind == idl.LinkedNodeKind.emptyFunctionBody);
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get doStatement_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    return _variantField_16 ??= 0;
+  int get emptyStatement_fake {
+    assert(kind == idl.LinkedNodeKind.emptyStatement);
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get enumDeclaration_leftBracket {
-    assert(kind == idl.LinkedNodeKind.enumDeclaration);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get expressionFunctionBody_keyword {
-    assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get fieldDeclaration_semicolon {
-    assert(kind == idl.LinkedNodeKind.fieldDeclaration);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get fieldFormalParameter_period {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get formalParameterList_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get forMixin_forKeyword {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get forParts_rightSeparator {
-    assert(kind == idl.LinkedNodeKind.forPartsWithDeclarations ||
-        kind == idl.LinkedNodeKind.forPartsWithExpression);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get functionDeclaration_propertyKeyword {
-    assert(kind == idl.LinkedNodeKind.functionDeclaration);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get genericFunctionType_question {
-    assert(kind == idl.LinkedNodeKind.genericFunctionType);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get genericTypeAlias_equals {
-    assert(kind == idl.LinkedNodeKind.genericTypeAlias);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get ifMixin_ifKeyword {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get importDirective_deferredKeyword {
+  int get importDirective_prefixOffset {
     assert(kind == idl.LinkedNodeKind.importDirective);
-    return _variantField_16 ??= 0;
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get indexExpression_period {
+  int get indexExpression_element {
     assert(kind == idl.LinkedNodeKind.indexExpression);
-    return _variantField_16 ??= 0;
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get integerLiteral_value {
-    assert(kind == idl.LinkedNodeKind.integerLiteral);
-    return _variantField_16 ??= 0;
+  int get nullLiteral_fake {
+    assert(kind == idl.LinkedNodeKind.nullLiteral);
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get interpolationExpression_rightBracket {
-    assert(kind == idl.LinkedNodeKind.interpolationExpression);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get isExpression_notOperator {
-    assert(kind == idl.LinkedNodeKind.isExpression);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get listLiteral_rightBracket {
-    assert(kind == idl.LinkedNodeKind.listLiteral);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get methodDeclaration_modifierKeyword {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get nativeFunctionBody_semicolon {
-    assert(kind == idl.LinkedNodeKind.nativeFunctionBody);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get parenthesizedExpression_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.parenthesizedExpression);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get partOfDirective_ofKeyword {
-    assert(kind == idl.LinkedNodeKind.partOfDirective);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get postfixExpression_operator {
+  int get postfixExpression_element {
     assert(kind == idl.LinkedNodeKind.postfixExpression);
-    return _variantField_16 ??= 0;
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get prefixExpression_operator {
+  int get prefixExpression_element {
     assert(kind == idl.LinkedNodeKind.prefixExpression);
-    return _variantField_16 ??= 0;
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get redirectingConstructorInvocation_period {
+  int get redirectingConstructorInvocation_element {
     assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
-    return _variantField_16 ??= 0;
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get returnStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.returnStatement);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get setOrMapLiteral_rightBracket {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get simpleIdentifier_token {
+  int get simpleIdentifier_element {
     assert(kind == idl.LinkedNodeKind.simpleIdentifier);
-    return _variantField_16 ??= 0;
+    return _variantField_15 ??= 0;
   }
 
   @override
-  int get superConstructorInvocation_period {
+  int get superConstructorInvocation_element {
     assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
-    return _variantField_16 ??= 0;
+    return _variantField_15 ??= 0;
   }
 
-  @override
-  int get switchMember_colon {
-    assert(kind == idl.LinkedNodeKind.switchCase ||
-        kind == idl.LinkedNodeKind.switchDefault);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get switchStatement_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get tryStatement_tryKeyword {
-    assert(kind == idl.LinkedNodeKind.tryStatement);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get typeArgumentList_rightBracket {
-    assert(kind == idl.LinkedNodeKind.typeArgumentList);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get typeParameter_id {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get typeParameterList_rightBracket {
-    assert(kind == idl.LinkedNodeKind.typeParameterList);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get whileStatement_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.whileStatement);
-    return _variantField_16 ??= 0;
-  }
-
-  @override
-  int get yieldStatement_star {
-    assert(kind == idl.LinkedNodeKind.yieldStatement);
-    return _variantField_16 ??= 0;
-  }
-
-  set annotation_period(int value) {
-    assert(kind == idl.LinkedNodeKind.annotation);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set argumentList_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.argumentList);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set assertInitializer_comma(int value) {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set assertStatement_comma(int value) {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set assignmentExpression_operator(int value) {
+  set assignmentExpression_element(int value) {
     assert(kind == idl.LinkedNodeKind.assignmentExpression);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set binaryExpression_operator(int value) {
+  set binaryExpression_element(int value) {
     assert(kind == idl.LinkedNodeKind.binaryExpression);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set block_rightBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.block);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set blockFunctionBody_star(int value) {
-    assert(kind == idl.LinkedNodeKind.blockFunctionBody);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set breakStatement_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.breakStatement);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set catchClause_comma(int value) {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set classDeclaration_classKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.classDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set classTypeAlias_equals(int value) {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set compilationUnit_endToken(int value) {
-    assert(kind == idl.LinkedNodeKind.compilationUnit);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set conditionalExpression_question(int value) {
-    assert(kind == idl.LinkedNodeKind.conditionalExpression);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set configuration_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set constructorDeclaration_externalKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set constructorFieldInitializer_period(int value) {
-    assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set constructorName_period(int value) {
+  set constructorName_element(int value) {
     assert(kind == idl.LinkedNodeKind.constructorName);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set continueStatement_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.continueStatement);
+  set emptyFunctionBody_fake(int value) {
+    assert(kind == idl.LinkedNodeKind.emptyFunctionBody);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set doStatement_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.doStatement);
+  set emptyStatement_fake(int value) {
+    assert(kind == idl.LinkedNodeKind.emptyStatement);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set enumDeclaration_leftBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.enumDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set expressionFunctionBody_keyword(int value) {
-    assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set fieldDeclaration_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.fieldDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set fieldFormalParameter_period(int value) {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set formalParameterList_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set forMixin_forKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set forParts_rightSeparator(int value) {
-    assert(kind == idl.LinkedNodeKind.forPartsWithDeclarations ||
-        kind == idl.LinkedNodeKind.forPartsWithExpression);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set functionDeclaration_propertyKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.functionDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set genericFunctionType_question(int value) {
-    assert(kind == idl.LinkedNodeKind.genericFunctionType);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set genericTypeAlias_equals(int value) {
-    assert(kind == idl.LinkedNodeKind.genericTypeAlias);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set ifMixin_ifKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set importDirective_deferredKeyword(int value) {
+  set importDirective_prefixOffset(int value) {
     assert(kind == idl.LinkedNodeKind.importDirective);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set indexExpression_period(int value) {
+  set indexExpression_element(int value) {
     assert(kind == idl.LinkedNodeKind.indexExpression);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set integerLiteral_value(int value) {
-    assert(kind == idl.LinkedNodeKind.integerLiteral);
+  set nullLiteral_fake(int value) {
+    assert(kind == idl.LinkedNodeKind.nullLiteral);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set interpolationExpression_rightBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.interpolationExpression);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set isExpression_notOperator(int value) {
-    assert(kind == idl.LinkedNodeKind.isExpression);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set listLiteral_rightBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.listLiteral);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set methodDeclaration_modifierKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set nativeFunctionBody_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.nativeFunctionBody);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set parenthesizedExpression_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.parenthesizedExpression);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set partOfDirective_ofKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.partOfDirective);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set postfixExpression_operator(int value) {
+  set postfixExpression_element(int value) {
     assert(kind == idl.LinkedNodeKind.postfixExpression);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set prefixExpression_operator(int value) {
+  set prefixExpression_element(int value) {
     assert(kind == idl.LinkedNodeKind.prefixExpression);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set redirectingConstructorInvocation_period(int value) {
+  set redirectingConstructorInvocation_element(int value) {
     assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set returnStatement_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.returnStatement);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set setOrMapLiteral_rightBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set simpleIdentifier_token(int value) {
+  set simpleIdentifier_element(int value) {
     assert(kind == idl.LinkedNodeKind.simpleIdentifier);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
-  set superConstructorInvocation_period(int value) {
+  set superConstructorInvocation_element(int value) {
     assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
     assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set switchMember_colon(int value) {
-    assert(kind == idl.LinkedNodeKind.switchCase ||
-        kind == idl.LinkedNodeKind.switchDefault);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set switchStatement_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set tryStatement_tryKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.tryStatement);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set typeArgumentList_rightBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.typeArgumentList);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set typeParameter_id(int value) {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set typeParameterList_rightBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.typeParameterList);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set whileStatement_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.whileStatement);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
-  }
-
-  set yieldStatement_star(int value) {
-    assert(kind == idl.LinkedNodeKind.yieldStatement);
-    assert(value == null || value >= 0);
-    _variantField_16 = value;
+    _variantField_15 = value;
   }
 
   @override
-  int get assertInitializer_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get assertStatement_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get catchClause_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get configuration_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get constructorDeclaration_factoryKeyword {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get constructorFieldInitializer_thisKeyword {
-    assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get doStatement_doKeyword {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get enumDeclaration_rightBracket {
-    assert(kind == idl.LinkedNodeKind.enumDeclaration);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get expressionFunctionBody_semicolon {
-    assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get fieldDeclaration_staticKeyword {
-    assert(kind == idl.LinkedNodeKind.fieldDeclaration);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get fieldFormalParameter_thisKeyword {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get formalParameterList_rightDelimiter {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get forMixin_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get ifMixin_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get indexExpression_leftBracket {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get methodDeclaration_operatorKeyword {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get redirectingConstructorInvocation_thisKeyword {
-    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get superConstructorInvocation_superKeyword {
-    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get switchStatement_switchKeyword {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get whileStatement_whileKeyword {
-    assert(kind == idl.LinkedNodeKind.whileStatement);
-    return _variantField_17 ??= 0;
-  }
-
-  @override
-  int get yieldStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.yieldStatement);
-    return _variantField_17 ??= 0;
-  }
-
-  set assertInitializer_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set assertStatement_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set catchClause_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set configuration_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set constructorDeclaration_factoryKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set constructorFieldInitializer_thisKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set doStatement_doKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set enumDeclaration_rightBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.enumDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set expressionFunctionBody_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set fieldDeclaration_staticKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.fieldDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set fieldFormalParameter_thisKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set formalParameterList_rightDelimiter(int value) {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set forMixin_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set ifMixin_leftParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set indexExpression_leftBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set methodDeclaration_operatorKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set redirectingConstructorInvocation_thisKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set superConstructorInvocation_superKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set switchStatement_switchKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set whileStatement_whileKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.whileStatement);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  set yieldStatement_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.yieldStatement);
-    assert(value == null || value >= 0);
-    _variantField_17 = value;
-  }
-
-  @override
-  int get assertInitializer_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get assertStatement_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get catchClause_onKeyword {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get classOrMixinDeclaration_rightBracket {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get configuration_equalToken {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get constructorDeclaration_period {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get directive_keyword {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.libraryDirective ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.partOfDirective);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get doStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get formalParameterList_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get ifMixin_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get indexExpression_rightBracket {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get methodDeclaration_propertyKeyword {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get switchStatement_leftBracket {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    return _variantField_18 ??= 0;
-  }
-
-  @override
-  int get typeAlias_typedefKeyword {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias);
-    return _variantField_18 ??= 0;
-  }
-
-  set assertInitializer_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set assertStatement_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set catchClause_onKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set classOrMixinDeclaration_rightBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set configuration_equalToken(int value) {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set constructorDeclaration_period(int value) {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set directive_keyword(int value) {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.libraryDirective ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.partOfDirective);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set doStatement_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set formalParameterList_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set ifMixin_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set indexExpression_rightBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set methodDeclaration_propertyKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set switchStatement_leftBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  set typeAlias_typedefKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias);
-    assert(value == null || value >= 0);
-    _variantField_18 = value;
-  }
-
-  @override
-  int get assertStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get catchClause_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get classOrMixinDeclaration_leftBracket {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get combinator_keyword {
-    assert(kind == idl.LinkedNodeKind.hideCombinator ||
-        kind == idl.LinkedNodeKind.showCombinator);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get constructorDeclaration_separator {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get doStatement_whileKeyword {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get forMixin_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get methodDeclaration_actualProperty {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get normalFormalParameter_covariantKeyword {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get switchStatement_rightBracket {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get typeAlias_semicolon {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get typedLiteral_constKeyword {
-    assert(kind == idl.LinkedNodeKind.listLiteral ||
-        kind == idl.LinkedNodeKind.setOrMapLiteral);
-    return _variantField_19 ??= 0;
-  }
-
-  @override
-  int get uriBasedDirective_uriElement {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.partDirective);
-    return _variantField_19 ??= 0;
-  }
-
-  set assertStatement_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set catchClause_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set classOrMixinDeclaration_leftBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set combinator_keyword(int value) {
-    assert(kind == idl.LinkedNodeKind.hideCombinator ||
-        kind == idl.LinkedNodeKind.showCombinator);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set constructorDeclaration_separator(int value) {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set doStatement_whileKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set forMixin_rightParenthesis(int value) {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set methodDeclaration_actualProperty(int value) {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set normalFormalParameter_covariantKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set switchStatement_rightBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set typeAlias_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set typedLiteral_constKeyword(int value) {
-    assert(kind == idl.LinkedNodeKind.listLiteral ||
-        kind == idl.LinkedNodeKind.setOrMapLiteral);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  set uriBasedDirective_uriElement(int value) {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.partDirective);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  @override
-  LinkedNodeTypeBuilder get assignmentExpression_elementType {
+  idl.UnlinkedTokenType get assignmentExpression_operator {
     assert(kind == idl.LinkedNodeKind.assignmentExpression);
-    return _variantField_23;
+    return _variantField_28 ??= idl.UnlinkedTokenType.NOTHING;
   }
 
   @override
-  LinkedNodeTypeBuilder get binaryExpression_elementType {
+  idl.UnlinkedTokenType get binaryExpression_operator {
     assert(kind == idl.LinkedNodeKind.binaryExpression);
-    return _variantField_23;
+    return _variantField_28 ??= idl.UnlinkedTokenType.NOTHING;
   }
 
   @override
-  LinkedNodeTypeBuilder get constructorName_elementType {
-    assert(kind == idl.LinkedNodeKind.constructorName);
-    return _variantField_23;
-  }
-
-  @override
-  LinkedNodeTypeBuilder get indexExpression_elementType {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    return _variantField_23;
-  }
-
-  @override
-  LinkedNodeTypeBuilder get postfixExpression_elementType {
+  idl.UnlinkedTokenType get postfixExpression_operator {
     assert(kind == idl.LinkedNodeKind.postfixExpression);
-    return _variantField_23;
+    return _variantField_28 ??= idl.UnlinkedTokenType.NOTHING;
   }
 
   @override
-  LinkedNodeTypeBuilder get prefixExpression_elementType {
+  idl.UnlinkedTokenType get prefixExpression_operator {
     assert(kind == idl.LinkedNodeKind.prefixExpression);
-    return _variantField_23;
+    return _variantField_28 ??= idl.UnlinkedTokenType.NOTHING;
   }
 
   @override
-  LinkedNodeTypeBuilder get redirectingConstructorInvocation_elementType {
-    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
-    return _variantField_23;
+  idl.UnlinkedTokenType get propertyAccess_operator {
+    assert(kind == idl.LinkedNodeKind.propertyAccess);
+    return _variantField_28 ??= idl.UnlinkedTokenType.NOTHING;
   }
 
-  @override
-  LinkedNodeTypeBuilder get simpleIdentifier_elementType {
-    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
-    return _variantField_23;
-  }
-
-  @override
-  LinkedNodeTypeBuilder get superConstructorInvocation_elementType {
-    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
-    return _variantField_23;
-  }
-
-  @override
-  LinkedNodeTypeBuilder get typeName_type {
-    assert(kind == idl.LinkedNodeKind.typeName);
-    return _variantField_23;
-  }
-
-  set assignmentExpression_elementType(LinkedNodeTypeBuilder value) {
+  set assignmentExpression_operator(idl.UnlinkedTokenType value) {
     assert(kind == idl.LinkedNodeKind.assignmentExpression);
-    _variantField_23 = value;
+    _variantField_28 = value;
   }
 
-  set binaryExpression_elementType(LinkedNodeTypeBuilder value) {
+  set binaryExpression_operator(idl.UnlinkedTokenType value) {
     assert(kind == idl.LinkedNodeKind.binaryExpression);
-    _variantField_23 = value;
+    _variantField_28 = value;
   }
 
-  set constructorName_elementType(LinkedNodeTypeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.constructorName);
-    _variantField_23 = value;
-  }
-
-  set indexExpression_elementType(LinkedNodeTypeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    _variantField_23 = value;
-  }
-
-  set postfixExpression_elementType(LinkedNodeTypeBuilder value) {
+  set postfixExpression_operator(idl.UnlinkedTokenType value) {
     assert(kind == idl.LinkedNodeKind.postfixExpression);
-    _variantField_23 = value;
+    _variantField_28 = value;
   }
 
-  set prefixExpression_elementType(LinkedNodeTypeBuilder value) {
+  set prefixExpression_operator(idl.UnlinkedTokenType value) {
     assert(kind == idl.LinkedNodeKind.prefixExpression);
-    _variantField_23 = value;
+    _variantField_28 = value;
   }
 
-  set redirectingConstructorInvocation_elementType(
-      LinkedNodeTypeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
-    _variantField_23 = value;
-  }
-
-  set simpleIdentifier_elementType(LinkedNodeTypeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
-    _variantField_23 = value;
-  }
-
-  set superConstructorInvocation_elementType(LinkedNodeTypeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
-    _variantField_23 = value;
-  }
-
-  set typeName_type(LinkedNodeTypeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.typeName);
-    _variantField_23 = value;
+  set propertyAccess_operator(idl.UnlinkedTokenType value) {
+    assert(kind == idl.LinkedNodeKind.propertyAccess);
+    _variantField_28 = value;
   }
 
   @override
@@ -9267,22 +7077,18 @@
   }
 
   @override
-  bool get defaultFormalParameter_isNamed {
-    assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
-    return _variantField_27 ??= false;
-  }
-
-  @override
-  bool get normalFormalParameter_isCovariant {
+  bool get inheritsCovariant {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
     return _variantField_27 ??= false;
   }
 
   @override
-  bool get setOrMapLiteral_isMap {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
+  bool get typeAlias_hasSelfReference {
+    assert(kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias);
     return _variantField_27 ??= false;
   }
 
@@ -9296,20 +7102,17 @@
     _variantField_27 = value;
   }
 
-  set defaultFormalParameter_isNamed(bool value) {
-    assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
-    _variantField_27 = value;
-  }
-
-  set normalFormalParameter_isCovariant(bool value) {
+  set inheritsCovariant(bool value) {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
     _variantField_27 = value;
   }
 
-  set setOrMapLiteral_isMap(bool value) {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
+  set typeAlias_hasSelfReference(bool value) {
+    assert(kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias);
     _variantField_27 = value;
   }
 
@@ -9382,14 +7185,6 @@
     return _variantField_12;
   }
 
-  @override
-  LinkedNodeBuilder get normalFormalParameter_identifier {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    return _variantField_12;
-  }
-
   set classOrMixinDeclaration_implementsClause(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.classDeclaration ||
         kind == idl.LinkedNodeKind.mixinDeclaration);
@@ -9402,13 +7197,6 @@
     _variantField_12 = value;
   }
 
-  set normalFormalParameter_identifier(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    _variantField_12 = value;
-  }
-
   @override
   List<LinkedNodeBuilder> get classOrMixinDeclaration_members {
     assert(kind == idl.LinkedNodeKind.classDeclaration ||
@@ -9449,127 +7237,14 @@
   }
 
   @override
-  int get codeLength {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.defaultFormalParameter ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration);
-    return _variantField_34 ??= 0;
-  }
-
-  set codeLength(int value) {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.defaultFormalParameter ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_34 = value;
-  }
-
-  @override
-  int get codeOffset {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.defaultFormalParameter ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration);
-    return _variantField_33 ??= 0;
-  }
-
-  @override
-  int get directive_semicolon {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.libraryDirective ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.partOfDirective);
-    return _variantField_33 ??= 0;
-  }
-
-  set codeOffset(int value) {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.defaultFormalParameter ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_33 = value;
-  }
-
-  set directive_semicolon(int value) {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.libraryDirective ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.partOfDirective);
-    assert(value == null || value >= 0);
-    _variantField_33 = value;
-  }
-
-  @override
-  List<int> get comment_tokens {
+  List<String> get comment_tokens {
     assert(kind == idl.LinkedNodeKind.comment);
-    return _variantField_28 ??= <int>[];
+    return _variantField_33 ??= <String>[];
   }
 
-  @override
-  List<int> get symbolLiteral_components {
-    assert(kind == idl.LinkedNodeKind.symbolLiteral);
-    return _variantField_28 ??= <int>[];
-  }
-
-  set comment_tokens(List<int> value) {
+  set comment_tokens(List<String> value) {
     assert(kind == idl.LinkedNodeKind.comment);
-    assert(value == null || value.every((e) => e >= 0));
-    _variantField_28 = value;
-  }
-
-  set symbolLiteral_components(List<int> value) {
-    assert(kind == idl.LinkedNodeKind.symbolLiteral);
-    assert(value == null || value.every((e) => e >= 0));
-    _variantField_28 = value;
+    _variantField_33 = value;
   }
 
   @override
@@ -9590,6 +7265,12 @@
   }
 
   @override
+  List<LinkedNodeBuilder> get listLiteral_elements {
+    assert(kind == idl.LinkedNodeKind.listLiteral);
+    return _variantField_3 ??= <LinkedNodeBuilder>[];
+  }
+
+  @override
   List<LinkedNodeBuilder> get namespaceDirective_configurations {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective);
@@ -9597,6 +7278,12 @@
   }
 
   @override
+  List<LinkedNodeBuilder> get setOrMapLiteral_elements {
+    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
+    return _variantField_3 ??= <LinkedNodeBuilder>[];
+  }
+
+  @override
   List<LinkedNodeBuilder> get switchMember_labels {
     assert(kind == idl.LinkedNodeKind.switchCase ||
         kind == idl.LinkedNodeKind.switchDefault);
@@ -9608,12 +7295,22 @@
     _variantField_3 = value;
   }
 
+  set listLiteral_elements(List<LinkedNodeBuilder> value) {
+    assert(kind == idl.LinkedNodeKind.listLiteral);
+    _variantField_3 = value;
+  }
+
   set namespaceDirective_configurations(List<LinkedNodeBuilder> value) {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective);
     _variantField_3 = value;
   }
 
+  set setOrMapLiteral_elements(List<LinkedNodeBuilder> value) {
+    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
+    _variantField_3 = value;
+  }
+
   set switchMember_labels(List<LinkedNodeBuilder> value) {
     assert(kind == idl.LinkedNodeKind.switchCase ||
         kind == idl.LinkedNodeKind.switchDefault);
@@ -9626,20 +7323,21 @@
     return _variantField_10;
   }
 
-  @override
-  LinkedNodeBuilder get methodDeclaration_name {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    return _variantField_10;
-  }
-
   set constructorDeclaration_returnType(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.constructorDeclaration);
     _variantField_10 = value;
   }
 
-  set methodDeclaration_name(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    _variantField_10 = value;
+  @override
+  idl.LinkedNodeFormalParameterKind get defaultFormalParameter_kind {
+    assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
+    return _variantField_26 ??=
+        idl.LinkedNodeFormalParameterKind.requiredPositional;
+  }
+
+  set defaultFormalParameter_kind(idl.LinkedNodeFormalParameterKind value) {
+    assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
+    _variantField_26 = value;
   }
 
   @override
@@ -9655,23 +7353,17 @@
 
   @override
   LinkedNodeTypeBuilder get expression_type {
-    assert(kind == idl.LinkedNodeKind.adjacentStrings ||
-        kind == idl.LinkedNodeKind.assignmentExpression ||
+    assert(kind == idl.LinkedNodeKind.assignmentExpression ||
         kind == idl.LinkedNodeKind.asExpression ||
         kind == idl.LinkedNodeKind.awaitExpression ||
         kind == idl.LinkedNodeKind.binaryExpression ||
-        kind == idl.LinkedNodeKind.booleanLiteral ||
         kind == idl.LinkedNodeKind.cascadeExpression ||
         kind == idl.LinkedNodeKind.conditionalExpression ||
-        kind == idl.LinkedNodeKind.doubleLiteral ||
         kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.indexExpression ||
         kind == idl.LinkedNodeKind.instanceCreationExpression ||
-        kind == idl.LinkedNodeKind.integerLiteral ||
-        kind == idl.LinkedNodeKind.isExpression ||
         kind == idl.LinkedNodeKind.listLiteral ||
         kind == idl.LinkedNodeKind.methodInvocation ||
-        kind == idl.LinkedNodeKind.namedExpression ||
         kind == idl.LinkedNodeKind.nullLiteral ||
         kind == idl.LinkedNodeKind.parenthesizedExpression ||
         kind == idl.LinkedNodeKind.prefixExpression ||
@@ -9681,8 +7373,6 @@
         kind == idl.LinkedNodeKind.rethrowExpression ||
         kind == idl.LinkedNodeKind.setOrMapLiteral ||
         kind == idl.LinkedNodeKind.simpleIdentifier ||
-        kind == idl.LinkedNodeKind.simpleStringLiteral ||
-        kind == idl.LinkedNodeKind.stringInterpolation ||
         kind == idl.LinkedNodeKind.superExpression ||
         kind == idl.LinkedNodeKind.symbolLiteral ||
         kind == idl.LinkedNodeKind.thisExpression ||
@@ -9697,23 +7387,17 @@
   }
 
   set expression_type(LinkedNodeTypeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.adjacentStrings ||
-        kind == idl.LinkedNodeKind.assignmentExpression ||
+    assert(kind == idl.LinkedNodeKind.assignmentExpression ||
         kind == idl.LinkedNodeKind.asExpression ||
         kind == idl.LinkedNodeKind.awaitExpression ||
         kind == idl.LinkedNodeKind.binaryExpression ||
-        kind == idl.LinkedNodeKind.booleanLiteral ||
         kind == idl.LinkedNodeKind.cascadeExpression ||
         kind == idl.LinkedNodeKind.conditionalExpression ||
-        kind == idl.LinkedNodeKind.doubleLiteral ||
         kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.indexExpression ||
         kind == idl.LinkedNodeKind.instanceCreationExpression ||
-        kind == idl.LinkedNodeKind.integerLiteral ||
-        kind == idl.LinkedNodeKind.isExpression ||
         kind == idl.LinkedNodeKind.listLiteral ||
         kind == idl.LinkedNodeKind.methodInvocation ||
-        kind == idl.LinkedNodeKind.namedExpression ||
         kind == idl.LinkedNodeKind.nullLiteral ||
         kind == idl.LinkedNodeKind.parenthesizedExpression ||
         kind == idl.LinkedNodeKind.prefixExpression ||
@@ -9723,8 +7407,6 @@
         kind == idl.LinkedNodeKind.rethrowExpression ||
         kind == idl.LinkedNodeKind.setOrMapLiteral ||
         kind == idl.LinkedNodeKind.simpleIdentifier ||
-        kind == idl.LinkedNodeKind.simpleStringLiteral ||
-        kind == idl.LinkedNodeKind.stringInterpolation ||
         kind == idl.LinkedNodeKind.superExpression ||
         kind == idl.LinkedNodeKind.symbolLiteral ||
         kind == idl.LinkedNodeKind.thisExpression ||
@@ -9738,18 +7420,96 @@
   }
 
   @override
-  idl.LinkedNodeFormalParameterKind get formalParameter_kind {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    return _variantField_26 ??= idl.LinkedNodeFormalParameterKind.required;
+  int get flags => _flags ??= 0;
+
+  set flags(int value) {
+    assert(value == null || value >= 0);
+    this._flags = value;
   }
 
-  set formalParameter_kind(idl.LinkedNodeFormalParameterKind value) {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+  @override
+  String get importDirective_prefix {
+    assert(kind == idl.LinkedNodeKind.importDirective);
+    return _variantField_1 ??= '';
+  }
+
+  set importDirective_prefix(String value) {
+    assert(kind == idl.LinkedNodeKind.importDirective);
+    _variantField_1 = value;
+  }
+
+  @override
+  int get informativeId {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.defaultFormalParameter ||
+        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.fieldDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    _variantField_26 = value;
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.partDirective ||
+        kind == idl.LinkedNodeKind.partOfDirective ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.topLevelVariableDeclaration ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration ||
+        kind == idl.LinkedNodeKind.variableDeclarationList);
+    return _variantField_36 ??= 0;
+  }
+
+  set informativeId(int value) {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.defaultFormalParameter ||
+        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.fieldDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.partDirective ||
+        kind == idl.LinkedNodeKind.partOfDirective ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.topLevelVariableDeclaration ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration ||
+        kind == idl.LinkedNodeKind.variableDeclarationList);
+    assert(value == null || value >= 0);
+    _variantField_36 = value;
+  }
+
+  @override
+  int get integerLiteral_value {
+    assert(kind == idl.LinkedNodeKind.integerLiteral);
+    return _variantField_16 ??= 0;
+  }
+
+  set integerLiteral_value(int value) {
+    assert(kind == idl.LinkedNodeKind.integerLiteral);
+    assert(value == null || value >= 0);
+    _variantField_16 = value;
   }
 
   @override
@@ -9771,33 +7531,6 @@
   }
 
   @override
-  LinkedNodeBuilder get namedCompilationUnitMember_name {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    return _variantField_14;
-  }
-
-  @override
-  LinkedNodeBuilder get normalFormalParameter_comment {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    return _variantField_14;
-  }
-
-  @override
-  LinkedNodeBuilder get typedLiteral_typeArguments {
-    assert(kind == idl.LinkedNodeKind.listLiteral ||
-        kind == idl.LinkedNodeKind.setOrMapLiteral);
-    return _variantField_14;
-  }
-
-  @override
   LinkedNodeBuilder get uriBasedDirective_uri {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective ||
@@ -9811,30 +7544,6 @@
     _variantField_14 = value;
   }
 
-  set namedCompilationUnitMember_name(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    _variantField_14 = value;
-  }
-
-  set normalFormalParameter_comment(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    _variantField_14 = value;
-  }
-
-  set typedLiteral_typeArguments(LinkedNodeBuilder value) {
-    assert(kind == idl.LinkedNodeKind.listLiteral ||
-        kind == idl.LinkedNodeKind.setOrMapLiteral);
-    _variantField_14 = value;
-  }
-
   set uriBasedDirective_uri(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective ||
@@ -9843,13 +7552,6 @@
   }
 
   @override
-  bool get isSynthetic => _isSynthetic ??= false;
-
-  set isSynthetic(bool value) {
-    this._isSynthetic = value;
-  }
-
-  @override
   idl.LinkedNodeKind get kind => _kind ??= idl.LinkedNodeKind.adjacentStrings;
 
   set kind(idl.LinkedNodeKind value) {
@@ -9857,6 +7559,39 @@
   }
 
   @override
+  List<String> get mixinDeclaration_superInvokedNames {
+    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+    return _variantField_34 ??= <String>[];
+  }
+
+  @override
+  List<String> get names {
+    assert(kind == idl.LinkedNodeKind.hideCombinator ||
+        kind == idl.LinkedNodeKind.showCombinator ||
+        kind == idl.LinkedNodeKind.symbolLiteral);
+    return _variantField_34 ??= <String>[];
+  }
+
+  set mixinDeclaration_superInvokedNames(List<String> value) {
+    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+    _variantField_34 = value;
+  }
+
+  set names(List<String> value) {
+    assert(kind == idl.LinkedNodeKind.hideCombinator ||
+        kind == idl.LinkedNodeKind.showCombinator ||
+        kind == idl.LinkedNodeKind.symbolLiteral);
+    _variantField_34 = value;
+  }
+
+  @override
+  String get name => _name ??= '';
+
+  set name(String value) {
+    this._name = value;
+  }
+
+  @override
   String get namespaceDirective_selectedUri {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective);
@@ -9881,12 +7616,6 @@
   }
 
   @override
-  bool get setOrMapLiteral_isSet {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    return _variantField_31 ??= false;
-  }
-
-  @override
   bool get simplyBoundable_isSimplyBounded {
     assert(kind == idl.LinkedNodeKind.classDeclaration ||
         kind == idl.LinkedNodeKind.classTypeAlias ||
@@ -9896,11 +7625,6 @@
     return _variantField_31 ??= false;
   }
 
-  set setOrMapLiteral_isSet(bool value) {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    _variantField_31 = value;
-  }
-
   set simplyBoundable_isSimplyBounded(bool value) {
     assert(kind == idl.LinkedNodeKind.classDeclaration ||
         kind == idl.LinkedNodeKind.classTypeAlias ||
@@ -9911,6 +7635,41 @@
   }
 
   @override
+  idl.UnlinkedTokenType get spreadElement_spreadOperator {
+    assert(kind == idl.LinkedNodeKind.spreadElement);
+    return _variantField_35 ??= idl.UnlinkedTokenType.NOTHING;
+  }
+
+  set spreadElement_spreadOperator(idl.UnlinkedTokenType value) {
+    assert(kind == idl.LinkedNodeKind.spreadElement);
+    _variantField_35 = value;
+  }
+
+  @override
+  TopLevelInferenceErrorBuilder get topLevelTypeInferenceError {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_32;
+  }
+
+  set topLevelTypeInferenceError(TopLevelInferenceErrorBuilder value) {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_32 = value;
+  }
+
+  @override
+  LinkedNodeBuilder get unused11 {
+    assert(kind == idl.LinkedNodeKind.classDeclaration);
+    return _variantField_11;
+  }
+
+  set unused11(LinkedNodeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.classDeclaration);
+    _variantField_11 = value;
+  }
+
+  @override
   String get uriBasedDirective_uriContent {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective ||
@@ -9926,39 +7685,464 @@
   }
 
   @override
-  LinkedNodeVariablesDeclarationBuilder get variableDeclaration_declaration {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    return _variantField_32;
+  int get uriBasedDirective_uriElement {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.partDirective);
+    return _variantField_19 ??= 0;
   }
 
-  set variableDeclaration_declaration(
-      LinkedNodeVariablesDeclarationBuilder value) {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_32 = value;
+  set uriBasedDirective_uriElement(int value) {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.partDirective);
+    assert(value == null || value >= 0);
+    _variantField_19 = value;
   }
 
+  LinkedNodeBuilder.adjacentStrings({
+    List<LinkedNodeBuilder> adjacentStrings_strings,
+  })  : _kind = idl.LinkedNodeKind.adjacentStrings,
+        _variantField_2 = adjacentStrings_strings;
+
+  LinkedNodeBuilder.annotation({
+    LinkedNodeBuilder annotation_arguments,
+    LinkedNodeBuilder annotation_constructorName,
+    int annotation_element,
+    LinkedNodeTypeBuilder annotation_elementType,
+    LinkedNodeBuilder annotation_name,
+  })  : _kind = idl.LinkedNodeKind.annotation,
+        _variantField_6 = annotation_arguments,
+        _variantField_7 = annotation_constructorName,
+        _variantField_17 = annotation_element,
+        _variantField_23 = annotation_elementType,
+        _variantField_8 = annotation_name;
+
+  LinkedNodeBuilder.argumentList({
+    List<LinkedNodeBuilder> argumentList_arguments,
+  })  : _kind = idl.LinkedNodeKind.argumentList,
+        _variantField_2 = argumentList_arguments;
+
+  LinkedNodeBuilder.asExpression({
+    LinkedNodeBuilder asExpression_expression,
+    LinkedNodeBuilder asExpression_type,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.asExpression,
+        _variantField_6 = asExpression_expression,
+        _variantField_7 = asExpression_type,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.assertInitializer({
+    LinkedNodeBuilder assertInitializer_condition,
+    LinkedNodeBuilder assertInitializer_message,
+  })  : _kind = idl.LinkedNodeKind.assertInitializer,
+        _variantField_6 = assertInitializer_condition,
+        _variantField_7 = assertInitializer_message;
+
+  LinkedNodeBuilder.assertStatement({
+    LinkedNodeBuilder assertStatement_condition,
+    LinkedNodeBuilder assertStatement_message,
+  })  : _kind = idl.LinkedNodeKind.assertStatement,
+        _variantField_6 = assertStatement_condition,
+        _variantField_7 = assertStatement_message;
+
+  LinkedNodeBuilder.assignmentExpression({
+    LinkedNodeBuilder assignmentExpression_leftHandSide,
+    LinkedNodeBuilder assignmentExpression_rightHandSide,
+    LinkedNodeTypeBuilder assignmentExpression_elementType,
+    int assignmentExpression_element,
+    idl.UnlinkedTokenType assignmentExpression_operator,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.assignmentExpression,
+        _variantField_6 = assignmentExpression_leftHandSide,
+        _variantField_7 = assignmentExpression_rightHandSide,
+        _variantField_23 = assignmentExpression_elementType,
+        _variantField_15 = assignmentExpression_element,
+        _variantField_28 = assignmentExpression_operator,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.awaitExpression({
+    LinkedNodeBuilder awaitExpression_expression,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.awaitExpression,
+        _variantField_6 = awaitExpression_expression,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.binaryExpression({
+    LinkedNodeTypeBuilder binaryExpression_invokeType,
+    LinkedNodeBuilder binaryExpression_leftOperand,
+    LinkedNodeBuilder binaryExpression_rightOperand,
+    LinkedNodeTypeBuilder binaryExpression_elementType,
+    int binaryExpression_element,
+    idl.UnlinkedTokenType binaryExpression_operator,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.binaryExpression,
+        _variantField_24 = binaryExpression_invokeType,
+        _variantField_6 = binaryExpression_leftOperand,
+        _variantField_7 = binaryExpression_rightOperand,
+        _variantField_23 = binaryExpression_elementType,
+        _variantField_15 = binaryExpression_element,
+        _variantField_28 = binaryExpression_operator,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.block({
+    List<LinkedNodeBuilder> block_statements,
+  })  : _kind = idl.LinkedNodeKind.block,
+        _variantField_2 = block_statements;
+
+  LinkedNodeBuilder.blockFunctionBody({
+    LinkedNodeBuilder blockFunctionBody_block,
+  })  : _kind = idl.LinkedNodeKind.blockFunctionBody,
+        _variantField_6 = blockFunctionBody_block;
+
+  LinkedNodeBuilder.booleanLiteral({
+    bool booleanLiteral_value,
+  })  : _kind = idl.LinkedNodeKind.booleanLiteral,
+        _variantField_27 = booleanLiteral_value;
+
+  LinkedNodeBuilder.breakStatement({
+    LinkedNodeBuilder breakStatement_label,
+  })  : _kind = idl.LinkedNodeKind.breakStatement,
+        _variantField_6 = breakStatement_label;
+
+  LinkedNodeBuilder.cascadeExpression({
+    List<LinkedNodeBuilder> cascadeExpression_sections,
+    LinkedNodeBuilder cascadeExpression_target,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.cascadeExpression,
+        _variantField_2 = cascadeExpression_sections,
+        _variantField_6 = cascadeExpression_target,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.catchClause({
+    LinkedNodeBuilder catchClause_body,
+    LinkedNodeBuilder catchClause_exceptionParameter,
+    LinkedNodeBuilder catchClause_exceptionType,
+    LinkedNodeBuilder catchClause_stackTraceParameter,
+  })  : _kind = idl.LinkedNodeKind.catchClause,
+        _variantField_6 = catchClause_body,
+        _variantField_7 = catchClause_exceptionParameter,
+        _variantField_8 = catchClause_exceptionType,
+        _variantField_9 = catchClause_stackTraceParameter;
+
+  LinkedNodeBuilder.classDeclaration({
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder classDeclaration_extendsClause,
+    LinkedNodeBuilder classDeclaration_withClause,
+    LinkedNodeBuilder classDeclaration_nativeClause,
+    bool classDeclaration_isDartObject,
+    LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
+    List<LinkedNodeBuilder> classOrMixinDeclaration_members,
+    LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
+    int informativeId,
+    bool simplyBoundable_isSimplyBounded,
+    LinkedNodeBuilder unused11,
+  })  : _kind = idl.LinkedNodeKind.classDeclaration,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = classDeclaration_extendsClause,
+        _variantField_7 = classDeclaration_withClause,
+        _variantField_8 = classDeclaration_nativeClause,
+        _variantField_27 = classDeclaration_isDartObject,
+        _variantField_12 = classOrMixinDeclaration_implementsClause,
+        _variantField_5 = classOrMixinDeclaration_members,
+        _variantField_13 = classOrMixinDeclaration_typeParameters,
+        _variantField_36 = informativeId,
+        _variantField_31 = simplyBoundable_isSimplyBounded,
+        _variantField_11 = unused11;
+
+  LinkedNodeBuilder.classTypeAlias({
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder classTypeAlias_typeParameters,
+    LinkedNodeBuilder classTypeAlias_superclass,
+    LinkedNodeBuilder classTypeAlias_withClause,
+    LinkedNodeBuilder classTypeAlias_implementsClause,
+    int informativeId,
+    bool simplyBoundable_isSimplyBounded,
+  })  : _kind = idl.LinkedNodeKind.classTypeAlias,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = classTypeAlias_typeParameters,
+        _variantField_7 = classTypeAlias_superclass,
+        _variantField_8 = classTypeAlias_withClause,
+        _variantField_9 = classTypeAlias_implementsClause,
+        _variantField_36 = informativeId,
+        _variantField_31 = simplyBoundable_isSimplyBounded;
+
+  LinkedNodeBuilder.comment({
+    List<LinkedNodeBuilder> comment_references,
+    List<String> comment_tokens,
+    idl.LinkedNodeCommentType comment_type,
+  })  : _kind = idl.LinkedNodeKind.comment,
+        _variantField_2 = comment_references,
+        _variantField_33 = comment_tokens,
+        _variantField_29 = comment_type;
+
+  LinkedNodeBuilder.commentReference({
+    LinkedNodeBuilder commentReference_identifier,
+  })  : _kind = idl.LinkedNodeKind.commentReference,
+        _variantField_6 = commentReference_identifier;
+
+  LinkedNodeBuilder.compilationUnit({
+    List<LinkedNodeBuilder> compilationUnit_declarations,
+    LinkedNodeBuilder compilationUnit_scriptTag,
+    List<LinkedNodeBuilder> compilationUnit_directives,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.compilationUnit,
+        _variantField_2 = compilationUnit_declarations,
+        _variantField_6 = compilationUnit_scriptTag,
+        _variantField_3 = compilationUnit_directives,
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.conditionalExpression({
+    LinkedNodeBuilder conditionalExpression_condition,
+    LinkedNodeBuilder conditionalExpression_elseExpression,
+    LinkedNodeBuilder conditionalExpression_thenExpression,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.conditionalExpression,
+        _variantField_6 = conditionalExpression_condition,
+        _variantField_7 = conditionalExpression_elseExpression,
+        _variantField_8 = conditionalExpression_thenExpression,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.configuration({
+    LinkedNodeBuilder configuration_name,
+    LinkedNodeBuilder configuration_value,
+    LinkedNodeBuilder configuration_uri,
+  })  : _kind = idl.LinkedNodeKind.configuration,
+        _variantField_6 = configuration_name,
+        _variantField_7 = configuration_value,
+        _variantField_8 = configuration_uri;
+
+  LinkedNodeBuilder.constructorDeclaration({
+    List<LinkedNodeBuilder> constructorDeclaration_initializers,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder constructorDeclaration_body,
+    LinkedNodeBuilder constructorDeclaration_parameters,
+    LinkedNodeBuilder constructorDeclaration_redirectedConstructor,
+    LinkedNodeBuilder constructorDeclaration_returnType,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.constructorDeclaration,
+        _variantField_2 = constructorDeclaration_initializers,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = constructorDeclaration_body,
+        _variantField_8 = constructorDeclaration_parameters,
+        _variantField_9 = constructorDeclaration_redirectedConstructor,
+        _variantField_10 = constructorDeclaration_returnType,
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.constructorFieldInitializer({
+    LinkedNodeBuilder constructorFieldInitializer_expression,
+    LinkedNodeBuilder constructorFieldInitializer_fieldName,
+  })  : _kind = idl.LinkedNodeKind.constructorFieldInitializer,
+        _variantField_6 = constructorFieldInitializer_expression,
+        _variantField_7 = constructorFieldInitializer_fieldName;
+
+  LinkedNodeBuilder.constructorName({
+    LinkedNodeBuilder constructorName_name,
+    LinkedNodeBuilder constructorName_type,
+    LinkedNodeTypeBuilder constructorName_elementType,
+    int constructorName_element,
+  })  : _kind = idl.LinkedNodeKind.constructorName,
+        _variantField_6 = constructorName_name,
+        _variantField_7 = constructorName_type,
+        _variantField_23 = constructorName_elementType,
+        _variantField_15 = constructorName_element;
+
+  LinkedNodeBuilder.continueStatement({
+    LinkedNodeBuilder continueStatement_label,
+  })  : _kind = idl.LinkedNodeKind.continueStatement,
+        _variantField_6 = continueStatement_label;
+
+  LinkedNodeBuilder.declaredIdentifier({
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder declaredIdentifier_identifier,
+    LinkedNodeBuilder declaredIdentifier_type,
+  })  : _kind = idl.LinkedNodeKind.declaredIdentifier,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = declaredIdentifier_identifier,
+        _variantField_7 = declaredIdentifier_type;
+
+  LinkedNodeBuilder.defaultFormalParameter({
+    LinkedNodeBuilder defaultFormalParameter_defaultValue,
+    LinkedNodeBuilder defaultFormalParameter_parameter,
+    idl.LinkedNodeFormalParameterKind defaultFormalParameter_kind,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.defaultFormalParameter,
+        _variantField_6 = defaultFormalParameter_defaultValue,
+        _variantField_7 = defaultFormalParameter_parameter,
+        _variantField_26 = defaultFormalParameter_kind,
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.doStatement({
+    LinkedNodeBuilder doStatement_body,
+    LinkedNodeBuilder doStatement_condition,
+  })  : _kind = idl.LinkedNodeKind.doStatement,
+        _variantField_6 = doStatement_body,
+        _variantField_7 = doStatement_condition;
+
+  LinkedNodeBuilder.dottedName({
+    List<LinkedNodeBuilder> dottedName_components,
+  })  : _kind = idl.LinkedNodeKind.dottedName,
+        _variantField_2 = dottedName_components;
+
+  LinkedNodeBuilder.doubleLiteral({
+    double doubleLiteral_value,
+  })  : _kind = idl.LinkedNodeKind.doubleLiteral,
+        _variantField_21 = doubleLiteral_value;
+
+  LinkedNodeBuilder.emptyFunctionBody({
+    int emptyFunctionBody_fake,
+  })  : _kind = idl.LinkedNodeKind.emptyFunctionBody,
+        _variantField_15 = emptyFunctionBody_fake;
+
+  LinkedNodeBuilder.emptyStatement({
+    int emptyStatement_fake,
+  })  : _kind = idl.LinkedNodeKind.emptyStatement,
+        _variantField_15 = emptyStatement_fake;
+
+  LinkedNodeBuilder.enumConstantDeclaration({
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.enumConstantDeclaration,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.enumDeclaration({
+    List<LinkedNodeBuilder> enumDeclaration_constants,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.enumDeclaration,
+        _variantField_2 = enumDeclaration_constants,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.exportDirective({
+    List<LinkedNodeBuilder> namespaceDirective_combinators,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    List<LinkedNodeBuilder> namespaceDirective_configurations,
+    int informativeId,
+    LinkedNodeBuilder uriBasedDirective_uri,
+    String namespaceDirective_selectedUri,
+    String uriBasedDirective_uriContent,
+    int uriBasedDirective_uriElement,
+  })  : _kind = idl.LinkedNodeKind.exportDirective,
+        _variantField_2 = namespaceDirective_combinators,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_3 = namespaceDirective_configurations,
+        _variantField_36 = informativeId,
+        _variantField_14 = uriBasedDirective_uri,
+        _variantField_20 = namespaceDirective_selectedUri,
+        _variantField_22 = uriBasedDirective_uriContent,
+        _variantField_19 = uriBasedDirective_uriElement;
+
+  LinkedNodeBuilder.expressionFunctionBody({
+    LinkedNodeBuilder expressionFunctionBody_expression,
+  })  : _kind = idl.LinkedNodeKind.expressionFunctionBody,
+        _variantField_6 = expressionFunctionBody_expression;
+
+  LinkedNodeBuilder.expressionStatement({
+    LinkedNodeBuilder expressionStatement_expression,
+  })  : _kind = idl.LinkedNodeKind.expressionStatement,
+        _variantField_6 = expressionStatement_expression;
+
+  LinkedNodeBuilder.extendsClause({
+    LinkedNodeBuilder extendsClause_superclass,
+  })  : _kind = idl.LinkedNodeKind.extendsClause,
+        _variantField_6 = extendsClause_superclass;
+
+  LinkedNodeBuilder.fieldDeclaration({
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder fieldDeclaration_fields,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.fieldDeclaration,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = fieldDeclaration_fields,
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.fieldFormalParameter({
+    LinkedNodeTypeBuilder actualType,
+    List<LinkedNodeBuilder> normalFormalParameter_metadata,
+    LinkedNodeBuilder fieldFormalParameter_type,
+    LinkedNodeBuilder fieldFormalParameter_typeParameters,
+    LinkedNodeBuilder fieldFormalParameter_formalParameters,
+    bool inheritsCovariant,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.fieldFormalParameter,
+        _variantField_24 = actualType,
+        _variantField_4 = normalFormalParameter_metadata,
+        _variantField_6 = fieldFormalParameter_type,
+        _variantField_7 = fieldFormalParameter_typeParameters,
+        _variantField_8 = fieldFormalParameter_formalParameters,
+        _variantField_27 = inheritsCovariant,
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.forEachPartsWithDeclaration({
+    LinkedNodeBuilder forEachParts_iterable,
+    LinkedNodeBuilder forEachPartsWithDeclaration_loopVariable,
+  })  : _kind = idl.LinkedNodeKind.forEachPartsWithDeclaration,
+        _variantField_6 = forEachParts_iterable,
+        _variantField_7 = forEachPartsWithDeclaration_loopVariable;
+
+  LinkedNodeBuilder.forEachPartsWithIdentifier({
+    LinkedNodeBuilder forEachParts_iterable,
+    LinkedNodeBuilder forEachPartsWithIdentifier_identifier,
+  })  : _kind = idl.LinkedNodeKind.forEachPartsWithIdentifier,
+        _variantField_6 = forEachParts_iterable,
+        _variantField_7 = forEachPartsWithIdentifier_identifier;
+
+  LinkedNodeBuilder.forElement({
+    LinkedNodeBuilder forMixin_forLoopParts,
+    LinkedNodeBuilder forElement_body,
+  })  : _kind = idl.LinkedNodeKind.forElement,
+        _variantField_6 = forMixin_forLoopParts,
+        _variantField_7 = forElement_body;
+
+  LinkedNodeBuilder.forPartsWithDeclarations({
+    LinkedNodeBuilder forParts_condition,
+    LinkedNodeBuilder forPartsWithDeclarations_variables,
+    List<LinkedNodeBuilder> forParts_updaters,
+  })  : _kind = idl.LinkedNodeKind.forPartsWithDeclarations,
+        _variantField_6 = forParts_condition,
+        _variantField_7 = forPartsWithDeclarations_variables,
+        _variantField_5 = forParts_updaters;
+
+  LinkedNodeBuilder.forPartsWithExpression({
+    LinkedNodeBuilder forParts_condition,
+    LinkedNodeBuilder forPartsWithExpression_initialization,
+    List<LinkedNodeBuilder> forParts_updaters,
+  })  : _kind = idl.LinkedNodeKind.forPartsWithExpression,
+        _variantField_6 = forParts_condition,
+        _variantField_7 = forPartsWithExpression_initialization,
+        _variantField_5 = forParts_updaters;
+
+  LinkedNodeBuilder.forStatement({
+    LinkedNodeBuilder forMixin_forLoopParts,
+    LinkedNodeBuilder forStatement_body,
+  })  : _kind = idl.LinkedNodeKind.forStatement,
+        _variantField_6 = forMixin_forLoopParts,
+        _variantField_7 = forStatement_body;
+
+  LinkedNodeBuilder.formalParameterList({
+    List<LinkedNodeBuilder> formalParameterList_parameters,
+  })  : _kind = idl.LinkedNodeKind.formalParameterList,
+        _variantField_2 = formalParameterList_parameters;
+
   LinkedNodeBuilder.functionDeclaration({
     LinkedNodeTypeBuilder actualReturnType,
-    LinkedNodeBuilder annotatedNode_comment,
     List<LinkedNodeBuilder> annotatedNode_metadata,
     LinkedNodeBuilder functionDeclaration_functionExpression,
-    int functionDeclaration_externalKeyword,
     LinkedNodeBuilder functionDeclaration_returnType,
-    int functionDeclaration_propertyKeyword,
-    int codeLength,
-    int codeOffset,
-    LinkedNodeBuilder namedCompilationUnitMember_name,
+    int informativeId,
   })  : _kind = idl.LinkedNodeKind.functionDeclaration,
         _variantField_24 = actualReturnType,
-        _variantField_11 = annotatedNode_comment,
         _variantField_4 = annotatedNode_metadata,
         _variantField_6 = functionDeclaration_functionExpression,
-        _variantField_15 = functionDeclaration_externalKeyword,
         _variantField_7 = functionDeclaration_returnType,
-        _variantField_16 = functionDeclaration_propertyKeyword,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_14 = namedCompilationUnitMember_name;
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.functionDeclarationStatement({
+    LinkedNodeBuilder functionDeclarationStatement_functionDeclaration,
+  })  : _kind = idl.LinkedNodeKind.functionDeclarationStatement,
+        _variantField_6 = functionDeclarationStatement_functionDeclaration;
 
   LinkedNodeBuilder.functionExpression({
     LinkedNodeTypeBuilder actualReturnType,
@@ -9971,206 +8155,6 @@
         _variantField_7 = functionExpression_formalParameters,
         _variantField_8 = functionExpression_typeParameters;
 
-  LinkedNodeBuilder.functionTypeAlias({
-    LinkedNodeTypeBuilder actualReturnType,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder functionTypeAlias_formalParameters,
-    LinkedNodeBuilder functionTypeAlias_returnType,
-    LinkedNodeBuilder functionTypeAlias_typeParameters,
-    int typeAlias_typedefKeyword,
-    int typeAlias_semicolon,
-    int codeLength,
-    int codeOffset,
-    LinkedNodeBuilder namedCompilationUnitMember_name,
-    bool simplyBoundable_isSimplyBounded,
-  })  : _kind = idl.LinkedNodeKind.functionTypeAlias,
-        _variantField_24 = actualReturnType,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = functionTypeAlias_formalParameters,
-        _variantField_7 = functionTypeAlias_returnType,
-        _variantField_8 = functionTypeAlias_typeParameters,
-        _variantField_18 = typeAlias_typedefKeyword,
-        _variantField_19 = typeAlias_semicolon,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_14 = namedCompilationUnitMember_name,
-        _variantField_31 = simplyBoundable_isSimplyBounded;
-
-  LinkedNodeBuilder.genericFunctionType({
-    LinkedNodeTypeBuilder actualReturnType,
-    LinkedNodeBuilder genericFunctionType_typeParameters,
-    int genericFunctionType_functionKeyword,
-    LinkedNodeBuilder genericFunctionType_returnType,
-    LinkedNodeBuilder genericFunctionType_formalParameters,
-    int genericFunctionType_question,
-    LinkedNodeTypeBuilder genericFunctionType_type,
-  })  : _kind = idl.LinkedNodeKind.genericFunctionType,
-        _variantField_24 = actualReturnType,
-        _variantField_6 = genericFunctionType_typeParameters,
-        _variantField_15 = genericFunctionType_functionKeyword,
-        _variantField_7 = genericFunctionType_returnType,
-        _variantField_8 = genericFunctionType_formalParameters,
-        _variantField_16 = genericFunctionType_question,
-        _variantField_25 = genericFunctionType_type;
-
-  LinkedNodeBuilder.methodDeclaration({
-    LinkedNodeTypeBuilder actualReturnType,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder methodDeclaration_body,
-    int methodDeclaration_externalKeyword,
-    LinkedNodeBuilder methodDeclaration_formalParameters,
-    LinkedNodeBuilder methodDeclaration_returnType,
-    int methodDeclaration_modifierKeyword,
-    int methodDeclaration_operatorKeyword,
-    int methodDeclaration_propertyKeyword,
-    int methodDeclaration_actualProperty,
-    LinkedNodeBuilder methodDeclaration_typeParameters,
-    int codeLength,
-    int codeOffset,
-    LinkedNodeBuilder methodDeclaration_name,
-  })  : _kind = idl.LinkedNodeKind.methodDeclaration,
-        _variantField_24 = actualReturnType,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = methodDeclaration_body,
-        _variantField_15 = methodDeclaration_externalKeyword,
-        _variantField_7 = methodDeclaration_formalParameters,
-        _variantField_8 = methodDeclaration_returnType,
-        _variantField_16 = methodDeclaration_modifierKeyword,
-        _variantField_17 = methodDeclaration_operatorKeyword,
-        _variantField_18 = methodDeclaration_propertyKeyword,
-        _variantField_19 = methodDeclaration_actualProperty,
-        _variantField_9 = methodDeclaration_typeParameters,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_10 = methodDeclaration_name;
-
-  LinkedNodeBuilder.fieldFormalParameter({
-    LinkedNodeTypeBuilder actualType,
-    List<LinkedNodeBuilder> normalFormalParameter_metadata,
-    LinkedNodeBuilder fieldFormalParameter_type,
-    int fieldFormalParameter_keyword,
-    LinkedNodeBuilder fieldFormalParameter_typeParameters,
-    LinkedNodeBuilder fieldFormalParameter_formalParameters,
-    int fieldFormalParameter_period,
-    int fieldFormalParameter_thisKeyword,
-    int normalFormalParameter_covariantKeyword,
-    bool normalFormalParameter_isCovariant,
-    LinkedNodeBuilder normalFormalParameter_identifier,
-    int codeLength,
-    int codeOffset,
-    idl.LinkedNodeFormalParameterKind formalParameter_kind,
-    LinkedNodeBuilder normalFormalParameter_comment,
-  })  : _kind = idl.LinkedNodeKind.fieldFormalParameter,
-        _variantField_24 = actualType,
-        _variantField_4 = normalFormalParameter_metadata,
-        _variantField_6 = fieldFormalParameter_type,
-        _variantField_15 = fieldFormalParameter_keyword,
-        _variantField_7 = fieldFormalParameter_typeParameters,
-        _variantField_8 = fieldFormalParameter_formalParameters,
-        _variantField_16 = fieldFormalParameter_period,
-        _variantField_17 = fieldFormalParameter_thisKeyword,
-        _variantField_19 = normalFormalParameter_covariantKeyword,
-        _variantField_27 = normalFormalParameter_isCovariant,
-        _variantField_12 = normalFormalParameter_identifier,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_26 = formalParameter_kind,
-        _variantField_14 = normalFormalParameter_comment;
-
-  LinkedNodeBuilder.functionTypedFormalParameter({
-    LinkedNodeTypeBuilder actualType,
-    List<LinkedNodeBuilder> normalFormalParameter_metadata,
-    LinkedNodeBuilder functionTypedFormalParameter_formalParameters,
-    LinkedNodeBuilder functionTypedFormalParameter_returnType,
-    LinkedNodeBuilder functionTypedFormalParameter_typeParameters,
-    int normalFormalParameter_covariantKeyword,
-    bool normalFormalParameter_isCovariant,
-    LinkedNodeBuilder normalFormalParameter_identifier,
-    int codeLength,
-    int codeOffset,
-    idl.LinkedNodeFormalParameterKind formalParameter_kind,
-    LinkedNodeBuilder normalFormalParameter_comment,
-  })  : _kind = idl.LinkedNodeKind.functionTypedFormalParameter,
-        _variantField_24 = actualType,
-        _variantField_4 = normalFormalParameter_metadata,
-        _variantField_6 = functionTypedFormalParameter_formalParameters,
-        _variantField_7 = functionTypedFormalParameter_returnType,
-        _variantField_8 = functionTypedFormalParameter_typeParameters,
-        _variantField_19 = normalFormalParameter_covariantKeyword,
-        _variantField_27 = normalFormalParameter_isCovariant,
-        _variantField_12 = normalFormalParameter_identifier,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_26 = formalParameter_kind,
-        _variantField_14 = normalFormalParameter_comment;
-
-  LinkedNodeBuilder.simpleFormalParameter({
-    LinkedNodeTypeBuilder actualType,
-    List<LinkedNodeBuilder> normalFormalParameter_metadata,
-    LinkedNodeBuilder simpleFormalParameter_type,
-    int simpleFormalParameter_keyword,
-    int normalFormalParameter_covariantKeyword,
-    bool normalFormalParameter_isCovariant,
-    LinkedNodeBuilder normalFormalParameter_identifier,
-    int codeLength,
-    int codeOffset,
-    idl.LinkedNodeFormalParameterKind formalParameter_kind,
-    LinkedNodeBuilder normalFormalParameter_comment,
-  })  : _kind = idl.LinkedNodeKind.simpleFormalParameter,
-        _variantField_24 = actualType,
-        _variantField_4 = normalFormalParameter_metadata,
-        _variantField_6 = simpleFormalParameter_type,
-        _variantField_15 = simpleFormalParameter_keyword,
-        _variantField_19 = normalFormalParameter_covariantKeyword,
-        _variantField_27 = normalFormalParameter_isCovariant,
-        _variantField_12 = normalFormalParameter_identifier,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_26 = formalParameter_kind,
-        _variantField_14 = normalFormalParameter_comment;
-
-  LinkedNodeBuilder.variableDeclaration({
-    LinkedNodeTypeBuilder actualType,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder variableDeclaration_initializer,
-    int variableDeclaration_equals,
-    LinkedNodeBuilder variableDeclaration_name,
-    int codeLength,
-    int codeOffset,
-    LinkedNodeVariablesDeclarationBuilder variableDeclaration_declaration,
-  })  : _kind = idl.LinkedNodeKind.variableDeclaration,
-        _variantField_24 = actualType,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = variableDeclaration_initializer,
-        _variantField_15 = variableDeclaration_equals,
-        _variantField_7 = variableDeclaration_name,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_32 = variableDeclaration_declaration;
-
-  LinkedNodeBuilder.binaryExpression({
-    LinkedNodeTypeBuilder binaryExpression_invokeType,
-    LinkedNodeBuilder binaryExpression_leftOperand,
-    int binaryExpression_element,
-    LinkedNodeBuilder binaryExpression_rightOperand,
-    int binaryExpression_operator,
-    LinkedNodeTypeBuilder binaryExpression_elementType,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.binaryExpression,
-        _variantField_24 = binaryExpression_invokeType,
-        _variantField_6 = binaryExpression_leftOperand,
-        _variantField_15 = binaryExpression_element,
-        _variantField_7 = binaryExpression_rightOperand,
-        _variantField_16 = binaryExpression_operator,
-        _variantField_23 = binaryExpression_elementType,
-        _variantField_25 = expression_type;
-
   LinkedNodeBuilder.functionExpressionInvocation({
     LinkedNodeTypeBuilder invocationExpression_invokeType,
     LinkedNodeBuilder functionExpressionInvocation_function,
@@ -10184,155 +8168,173 @@
         _variantField_25 = expression_type,
         _variantField_14 = invocationExpression_arguments;
 
-  LinkedNodeBuilder.methodInvocation({
-    LinkedNodeTypeBuilder invocationExpression_invokeType,
-    LinkedNodeBuilder methodInvocation_methodName,
-    int methodInvocation_operator,
-    LinkedNodeBuilder methodInvocation_target,
-    LinkedNodeBuilder invocationExpression_typeArguments,
-    LinkedNodeTypeBuilder expression_type,
-    LinkedNodeBuilder invocationExpression_arguments,
-  })  : _kind = idl.LinkedNodeKind.methodInvocation,
-        _variantField_24 = invocationExpression_invokeType,
-        _variantField_6 = methodInvocation_methodName,
-        _variantField_15 = methodInvocation_operator,
-        _variantField_7 = methodInvocation_target,
-        _variantField_12 = invocationExpression_typeArguments,
-        _variantField_25 = expression_type,
-        _variantField_14 = invocationExpression_arguments;
-
-  LinkedNodeBuilder.adjacentStrings({
-    List<LinkedNodeBuilder> adjacentStrings_strings,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.adjacentStrings,
-        _variantField_2 = adjacentStrings_strings,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.argumentList({
-    List<LinkedNodeBuilder> argumentList_arguments,
-    int argumentList_leftParenthesis,
-    int argumentList_rightParenthesis,
-  })  : _kind = idl.LinkedNodeKind.argumentList,
-        _variantField_2 = argumentList_arguments,
-        _variantField_15 = argumentList_leftParenthesis,
-        _variantField_16 = argumentList_rightParenthesis;
-
-  LinkedNodeBuilder.block({
-    List<LinkedNodeBuilder> block_statements,
-    int block_leftBracket,
-    int block_rightBracket,
-  })  : _kind = idl.LinkedNodeKind.block,
-        _variantField_2 = block_statements,
-        _variantField_15 = block_leftBracket,
-        _variantField_16 = block_rightBracket;
-
-  LinkedNodeBuilder.cascadeExpression({
-    List<LinkedNodeBuilder> cascadeExpression_sections,
-    LinkedNodeBuilder cascadeExpression_target,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.cascadeExpression,
-        _variantField_2 = cascadeExpression_sections,
-        _variantField_6 = cascadeExpression_target,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.compilationUnit({
-    List<LinkedNodeBuilder> compilationUnit_declarations,
-    LinkedNodeBuilder compilationUnit_scriptTag,
-    int compilationUnit_beginToken,
-    int compilationUnit_endToken,
-    List<LinkedNodeBuilder> compilationUnit_directives,
-  })  : _kind = idl.LinkedNodeKind.compilationUnit,
-        _variantField_2 = compilationUnit_declarations,
-        _variantField_6 = compilationUnit_scriptTag,
-        _variantField_15 = compilationUnit_beginToken,
-        _variantField_16 = compilationUnit_endToken,
-        _variantField_3 = compilationUnit_directives;
-
-  LinkedNodeBuilder.constructorDeclaration({
-    List<LinkedNodeBuilder> constructorDeclaration_initializers,
-    LinkedNodeBuilder annotatedNode_comment,
+  LinkedNodeBuilder.functionTypeAlias({
+    LinkedNodeTypeBuilder actualReturnType,
     List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder constructorDeclaration_body,
-    int constructorDeclaration_constKeyword,
-    LinkedNodeBuilder constructorDeclaration_name,
-    LinkedNodeBuilder constructorDeclaration_parameters,
-    int constructorDeclaration_externalKeyword,
-    int constructorDeclaration_factoryKeyword,
-    int constructorDeclaration_period,
-    int constructorDeclaration_separator,
-    LinkedNodeBuilder constructorDeclaration_redirectedConstructor,
-    int codeLength,
-    int codeOffset,
-    LinkedNodeBuilder constructorDeclaration_returnType,
-  })  : _kind = idl.LinkedNodeKind.constructorDeclaration,
-        _variantField_2 = constructorDeclaration_initializers,
-        _variantField_11 = annotatedNode_comment,
+    LinkedNodeBuilder functionTypeAlias_formalParameters,
+    LinkedNodeBuilder functionTypeAlias_returnType,
+    LinkedNodeBuilder functionTypeAlias_typeParameters,
+    bool typeAlias_hasSelfReference,
+    int informativeId,
+    bool simplyBoundable_isSimplyBounded,
+  })  : _kind = idl.LinkedNodeKind.functionTypeAlias,
+        _variantField_24 = actualReturnType,
         _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = constructorDeclaration_body,
-        _variantField_15 = constructorDeclaration_constKeyword,
-        _variantField_7 = constructorDeclaration_name,
-        _variantField_8 = constructorDeclaration_parameters,
-        _variantField_16 = constructorDeclaration_externalKeyword,
-        _variantField_17 = constructorDeclaration_factoryKeyword,
-        _variantField_18 = constructorDeclaration_period,
-        _variantField_19 = constructorDeclaration_separator,
-        _variantField_9 = constructorDeclaration_redirectedConstructor,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_10 = constructorDeclaration_returnType;
+        _variantField_6 = functionTypeAlias_formalParameters,
+        _variantField_7 = functionTypeAlias_returnType,
+        _variantField_8 = functionTypeAlias_typeParameters,
+        _variantField_27 = typeAlias_hasSelfReference,
+        _variantField_36 = informativeId,
+        _variantField_31 = simplyBoundable_isSimplyBounded;
 
-  LinkedNodeBuilder.dottedName({
-    List<LinkedNodeBuilder> dottedName_components,
-  })  : _kind = idl.LinkedNodeKind.dottedName,
-        _variantField_2 = dottedName_components;
+  LinkedNodeBuilder.functionTypedFormalParameter({
+    LinkedNodeTypeBuilder actualType,
+    List<LinkedNodeBuilder> normalFormalParameter_metadata,
+    LinkedNodeBuilder functionTypedFormalParameter_formalParameters,
+    LinkedNodeBuilder functionTypedFormalParameter_returnType,
+    LinkedNodeBuilder functionTypedFormalParameter_typeParameters,
+    bool inheritsCovariant,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.functionTypedFormalParameter,
+        _variantField_24 = actualType,
+        _variantField_4 = normalFormalParameter_metadata,
+        _variantField_6 = functionTypedFormalParameter_formalParameters,
+        _variantField_7 = functionTypedFormalParameter_returnType,
+        _variantField_8 = functionTypedFormalParameter_typeParameters,
+        _variantField_27 = inheritsCovariant,
+        _variantField_36 = informativeId;
 
-  LinkedNodeBuilder.enumDeclaration({
-    List<LinkedNodeBuilder> enumDeclaration_constants,
-    LinkedNodeBuilder annotatedNode_comment,
+  LinkedNodeBuilder.genericFunctionType({
+    LinkedNodeTypeBuilder actualReturnType,
+    LinkedNodeBuilder genericFunctionType_typeParameters,
+    LinkedNodeBuilder genericFunctionType_returnType,
+    int genericFunctionType_id,
+    LinkedNodeBuilder genericFunctionType_formalParameters,
+    LinkedNodeTypeBuilder genericFunctionType_type,
+  })  : _kind = idl.LinkedNodeKind.genericFunctionType,
+        _variantField_24 = actualReturnType,
+        _variantField_6 = genericFunctionType_typeParameters,
+        _variantField_7 = genericFunctionType_returnType,
+        _variantField_17 = genericFunctionType_id,
+        _variantField_8 = genericFunctionType_formalParameters,
+        _variantField_25 = genericFunctionType_type;
+
+  LinkedNodeBuilder.genericTypeAlias({
     List<LinkedNodeBuilder> annotatedNode_metadata,
-    int enumDeclaration_enumKeyword,
-    int enumDeclaration_leftBracket,
-    int enumDeclaration_rightBracket,
-    int codeLength,
-    int codeOffset,
-    LinkedNodeBuilder namedCompilationUnitMember_name,
-  })  : _kind = idl.LinkedNodeKind.enumDeclaration,
-        _variantField_2 = enumDeclaration_constants,
-        _variantField_11 = annotatedNode_comment,
+    LinkedNodeBuilder genericTypeAlias_typeParameters,
+    LinkedNodeBuilder genericTypeAlias_functionType,
+    bool typeAlias_hasSelfReference,
+    int informativeId,
+    bool simplyBoundable_isSimplyBounded,
+  })  : _kind = idl.LinkedNodeKind.genericTypeAlias,
         _variantField_4 = annotatedNode_metadata,
-        _variantField_15 = enumDeclaration_enumKeyword,
-        _variantField_16 = enumDeclaration_leftBracket,
-        _variantField_17 = enumDeclaration_rightBracket,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_14 = namedCompilationUnitMember_name;
-
-  LinkedNodeBuilder.formalParameterList({
-    List<LinkedNodeBuilder> formalParameterList_parameters,
-    int formalParameterList_leftDelimiter,
-    int formalParameterList_leftParenthesis,
-    int formalParameterList_rightDelimiter,
-    int formalParameterList_rightParenthesis,
-  })  : _kind = idl.LinkedNodeKind.formalParameterList,
-        _variantField_2 = formalParameterList_parameters,
-        _variantField_15 = formalParameterList_leftDelimiter,
-        _variantField_16 = formalParameterList_leftParenthesis,
-        _variantField_17 = formalParameterList_rightDelimiter,
-        _variantField_18 = formalParameterList_rightParenthesis;
+        _variantField_6 = genericTypeAlias_typeParameters,
+        _variantField_7 = genericTypeAlias_functionType,
+        _variantField_27 = typeAlias_hasSelfReference,
+        _variantField_36 = informativeId,
+        _variantField_31 = simplyBoundable_isSimplyBounded;
 
   LinkedNodeBuilder.hideCombinator({
-    List<LinkedNodeBuilder> hideCombinator_hiddenNames,
-    int combinator_keyword,
+    List<String> names,
   })  : _kind = idl.LinkedNodeKind.hideCombinator,
-        _variantField_2 = hideCombinator_hiddenNames,
-        _variantField_19 = combinator_keyword;
+        _variantField_34 = names;
+
+  LinkedNodeBuilder.ifElement({
+    LinkedNodeBuilder ifMixin_condition,
+    LinkedNodeBuilder ifElement_thenElement,
+    LinkedNodeBuilder ifElement_elseElement,
+  })  : _kind = idl.LinkedNodeKind.ifElement,
+        _variantField_6 = ifMixin_condition,
+        _variantField_8 = ifElement_thenElement,
+        _variantField_9 = ifElement_elseElement;
+
+  LinkedNodeBuilder.ifStatement({
+    LinkedNodeBuilder ifMixin_condition,
+    LinkedNodeBuilder ifStatement_elseStatement,
+    LinkedNodeBuilder ifStatement_thenStatement,
+  })  : _kind = idl.LinkedNodeKind.ifStatement,
+        _variantField_6 = ifMixin_condition,
+        _variantField_7 = ifStatement_elseStatement,
+        _variantField_8 = ifStatement_thenStatement;
 
   LinkedNodeBuilder.implementsClause({
     List<LinkedNodeBuilder> implementsClause_interfaces,
-    int implementsClause_implementsKeyword,
   })  : _kind = idl.LinkedNodeKind.implementsClause,
-        _variantField_2 = implementsClause_interfaces,
-        _variantField_15 = implementsClause_implementsKeyword;
+        _variantField_2 = implementsClause_interfaces;
+
+  LinkedNodeBuilder.importDirective({
+    List<LinkedNodeBuilder> namespaceDirective_combinators,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    int importDirective_prefixOffset,
+    List<LinkedNodeBuilder> namespaceDirective_configurations,
+    String importDirective_prefix,
+    int informativeId,
+    LinkedNodeBuilder uriBasedDirective_uri,
+    String namespaceDirective_selectedUri,
+    String uriBasedDirective_uriContent,
+    int uriBasedDirective_uriElement,
+  })  : _kind = idl.LinkedNodeKind.importDirective,
+        _variantField_2 = namespaceDirective_combinators,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_15 = importDirective_prefixOffset,
+        _variantField_3 = namespaceDirective_configurations,
+        _variantField_1 = importDirective_prefix,
+        _variantField_36 = informativeId,
+        _variantField_14 = uriBasedDirective_uri,
+        _variantField_20 = namespaceDirective_selectedUri,
+        _variantField_22 = uriBasedDirective_uriContent,
+        _variantField_19 = uriBasedDirective_uriElement;
+
+  LinkedNodeBuilder.indexExpression({
+    LinkedNodeBuilder indexExpression_index,
+    LinkedNodeBuilder indexExpression_target,
+    LinkedNodeTypeBuilder indexExpression_elementType,
+    int indexExpression_element,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.indexExpression,
+        _variantField_6 = indexExpression_index,
+        _variantField_7 = indexExpression_target,
+        _variantField_23 = indexExpression_elementType,
+        _variantField_15 = indexExpression_element,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.instanceCreationExpression({
+    List<LinkedNodeBuilder> instanceCreationExpression_arguments,
+    LinkedNodeBuilder instanceCreationExpression_constructorName,
+    LinkedNodeBuilder instanceCreationExpression_typeArguments,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.instanceCreationExpression,
+        _variantField_2 = instanceCreationExpression_arguments,
+        _variantField_7 = instanceCreationExpression_constructorName,
+        _variantField_8 = instanceCreationExpression_typeArguments,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.integerLiteral({
+    int integerLiteral_value,
+  })  : _kind = idl.LinkedNodeKind.integerLiteral,
+        _variantField_16 = integerLiteral_value;
+
+  LinkedNodeBuilder.interpolationExpression({
+    LinkedNodeBuilder interpolationExpression_expression,
+  })  : _kind = idl.LinkedNodeKind.interpolationExpression,
+        _variantField_6 = interpolationExpression_expression;
+
+  LinkedNodeBuilder.interpolationString({
+    String interpolationString_value,
+  })  : _kind = idl.LinkedNodeKind.interpolationString,
+        _variantField_30 = interpolationString_value;
+
+  LinkedNodeBuilder.isExpression({
+    LinkedNodeBuilder isExpression_expression,
+    LinkedNodeBuilder isExpression_type,
+  })  : _kind = idl.LinkedNodeKind.isExpression,
+        _variantField_6 = isExpression_expression,
+        _variantField_7 = isExpression_type;
+
+  LinkedNodeBuilder.label({
+    LinkedNodeBuilder label_label,
+  })  : _kind = idl.LinkedNodeKind.label,
+        _variantField_6 = label_label;
 
   LinkedNodeBuilder.labeledStatement({
     List<LinkedNodeBuilder> labeledStatement_labels,
@@ -10341,1298 +8343,2444 @@
         _variantField_2 = labeledStatement_labels,
         _variantField_6 = labeledStatement_statement;
 
+  LinkedNodeBuilder.libraryDirective({
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder libraryDirective_name,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.libraryDirective,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = libraryDirective_name,
+        _variantField_36 = informativeId;
+
   LinkedNodeBuilder.libraryIdentifier({
     List<LinkedNodeBuilder> libraryIdentifier_components,
   })  : _kind = idl.LinkedNodeKind.libraryIdentifier,
         _variantField_2 = libraryIdentifier_components;
 
   LinkedNodeBuilder.listLiteral({
+    List<LinkedNodeBuilder> typedLiteral_typeArguments,
     List<LinkedNodeBuilder> listLiteral_elements,
-    int listLiteral_leftBracket,
-    int listLiteral_rightBracket,
-    int typedLiteral_constKeyword,
     LinkedNodeTypeBuilder expression_type,
-    LinkedNodeBuilder typedLiteral_typeArguments,
   })  : _kind = idl.LinkedNodeKind.listLiteral,
-        _variantField_2 = listLiteral_elements,
-        _variantField_15 = listLiteral_leftBracket,
-        _variantField_16 = listLiteral_rightBracket,
-        _variantField_19 = typedLiteral_constKeyword,
-        _variantField_25 = expression_type,
-        _variantField_14 = typedLiteral_typeArguments;
-
-  LinkedNodeBuilder.exportDirective({
-    List<LinkedNodeBuilder> namespaceDirective_combinators,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    int directive_keyword,
-    int uriBasedDirective_uriElement,
-    int directive_semicolon,
-    List<LinkedNodeBuilder> namespaceDirective_configurations,
-    LinkedNodeBuilder uriBasedDirective_uri,
-    String namespaceDirective_selectedUri,
-    String uriBasedDirective_uriContent,
-  })  : _kind = idl.LinkedNodeKind.exportDirective,
-        _variantField_2 = namespaceDirective_combinators,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_18 = directive_keyword,
-        _variantField_19 = uriBasedDirective_uriElement,
-        _variantField_33 = directive_semicolon,
-        _variantField_3 = namespaceDirective_configurations,
-        _variantField_14 = uriBasedDirective_uri,
-        _variantField_20 = namespaceDirective_selectedUri,
-        _variantField_22 = uriBasedDirective_uriContent;
-
-  LinkedNodeBuilder.importDirective({
-    List<LinkedNodeBuilder> namespaceDirective_combinators,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder importDirective_prefix,
-    int importDirective_asKeyword,
-    int importDirective_deferredKeyword,
-    int directive_keyword,
-    int uriBasedDirective_uriElement,
-    int directive_semicolon,
-    List<LinkedNodeBuilder> namespaceDirective_configurations,
-    LinkedNodeBuilder uriBasedDirective_uri,
-    String namespaceDirective_selectedUri,
-    String uriBasedDirective_uriContent,
-  })  : _kind = idl.LinkedNodeKind.importDirective,
-        _variantField_2 = namespaceDirective_combinators,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = importDirective_prefix,
-        _variantField_15 = importDirective_asKeyword,
-        _variantField_16 = importDirective_deferredKeyword,
-        _variantField_18 = directive_keyword,
-        _variantField_19 = uriBasedDirective_uriElement,
-        _variantField_33 = directive_semicolon,
-        _variantField_3 = namespaceDirective_configurations,
-        _variantField_14 = uriBasedDirective_uri,
-        _variantField_20 = namespaceDirective_selectedUri,
-        _variantField_22 = uriBasedDirective_uriContent;
-
-  LinkedNodeBuilder.onClause({
-    List<LinkedNodeBuilder> onClause_superclassConstraints,
-    int onClause_onKeyword,
-  })  : _kind = idl.LinkedNodeKind.onClause,
-        _variantField_2 = onClause_superclassConstraints,
-        _variantField_15 = onClause_onKeyword;
-
-  LinkedNodeBuilder.setOrMapLiteral({
-    List<LinkedNodeBuilder> setOrMapLiteral_elements,
-    int setOrMapLiteral_leftBracket,
-    int setOrMapLiteral_rightBracket,
-    int typedLiteral_constKeyword,
-    bool setOrMapLiteral_isMap,
-    LinkedNodeTypeBuilder expression_type,
-    LinkedNodeBuilder typedLiteral_typeArguments,
-    bool setOrMapLiteral_isSet,
-  })  : _kind = idl.LinkedNodeKind.setOrMapLiteral,
-        _variantField_2 = setOrMapLiteral_elements,
-        _variantField_15 = setOrMapLiteral_leftBracket,
-        _variantField_16 = setOrMapLiteral_rightBracket,
-        _variantField_19 = typedLiteral_constKeyword,
-        _variantField_27 = setOrMapLiteral_isMap,
-        _variantField_25 = expression_type,
-        _variantField_14 = typedLiteral_typeArguments,
-        _variantField_31 = setOrMapLiteral_isSet;
-
-  LinkedNodeBuilder.showCombinator({
-    List<LinkedNodeBuilder> showCombinator_shownNames,
-    int combinator_keyword,
-  })  : _kind = idl.LinkedNodeKind.showCombinator,
-        _variantField_2 = showCombinator_shownNames,
-        _variantField_19 = combinator_keyword;
-
-  LinkedNodeBuilder.stringInterpolation({
-    List<LinkedNodeBuilder> stringInterpolation_elements,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.stringInterpolation,
-        _variantField_2 = stringInterpolation_elements,
+        _variantField_2 = typedLiteral_typeArguments,
+        _variantField_3 = listLiteral_elements,
         _variantField_25 = expression_type;
 
-  LinkedNodeBuilder.switchStatement({
-    List<LinkedNodeBuilder> switchStatement_members,
-    int switchStatement_leftParenthesis,
-    LinkedNodeBuilder switchStatement_expression,
-    int switchStatement_rightParenthesis,
-    int switchStatement_switchKeyword,
-    int switchStatement_leftBracket,
-    int switchStatement_rightBracket,
-  })  : _kind = idl.LinkedNodeKind.switchStatement,
-        _variantField_2 = switchStatement_members,
-        _variantField_15 = switchStatement_leftParenthesis,
-        _variantField_7 = switchStatement_expression,
-        _variantField_16 = switchStatement_rightParenthesis,
-        _variantField_17 = switchStatement_switchKeyword,
-        _variantField_18 = switchStatement_leftBracket,
-        _variantField_19 = switchStatement_rightBracket;
-
-  LinkedNodeBuilder.tryStatement({
-    List<LinkedNodeBuilder> tryStatement_catchClauses,
-    LinkedNodeBuilder tryStatement_body,
-    int tryStatement_finallyKeyword,
-    LinkedNodeBuilder tryStatement_finallyBlock,
-    int tryStatement_tryKeyword,
-  })  : _kind = idl.LinkedNodeKind.tryStatement,
-        _variantField_2 = tryStatement_catchClauses,
-        _variantField_6 = tryStatement_body,
-        _variantField_15 = tryStatement_finallyKeyword,
-        _variantField_7 = tryStatement_finallyBlock,
-        _variantField_16 = tryStatement_tryKeyword;
-
-  LinkedNodeBuilder.typeArgumentList({
-    List<LinkedNodeBuilder> typeArgumentList_arguments,
-    int typeArgumentList_leftBracket,
-    int typeArgumentList_rightBracket,
-  })  : _kind = idl.LinkedNodeKind.typeArgumentList,
-        _variantField_2 = typeArgumentList_arguments,
-        _variantField_15 = typeArgumentList_leftBracket,
-        _variantField_16 = typeArgumentList_rightBracket;
-
-  LinkedNodeBuilder.typeParameterList({
-    List<LinkedNodeBuilder> typeParameterList_typeParameters,
-    int typeParameterList_leftBracket,
-    int typeParameterList_rightBracket,
-  })  : _kind = idl.LinkedNodeKind.typeParameterList,
-        _variantField_2 = typeParameterList_typeParameters,
-        _variantField_15 = typeParameterList_leftBracket,
-        _variantField_16 = typeParameterList_rightBracket;
-
-  LinkedNodeBuilder.variableDeclarationList({
-    List<LinkedNodeBuilder> variableDeclarationList_variables,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder variableDeclarationList_type,
-    int variableDeclarationList_keyword,
-  })  : _kind = idl.LinkedNodeKind.variableDeclarationList,
-        _variantField_2 = variableDeclarationList_variables,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = variableDeclarationList_type,
-        _variantField_15 = variableDeclarationList_keyword;
-
-  LinkedNodeBuilder.withClause({
-    List<LinkedNodeBuilder> withClause_mixinTypes,
-    int withClause_withKeyword,
-  })  : _kind = idl.LinkedNodeKind.withClause,
-        _variantField_2 = withClause_mixinTypes,
-        _variantField_15 = withClause_withKeyword;
-
-  LinkedNodeBuilder.classDeclaration({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder classDeclaration_extendsClause,
-    int classDeclaration_abstractKeyword,
-    LinkedNodeBuilder classDeclaration_withClause,
-    LinkedNodeBuilder classDeclaration_nativeClause,
-    int classDeclaration_classKeyword,
-    int classOrMixinDeclaration_rightBracket,
-    int classOrMixinDeclaration_leftBracket,
-    bool classDeclaration_isDartObject,
-    LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
-    List<LinkedNodeBuilder> classOrMixinDeclaration_members,
-    LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
-    int codeLength,
-    int codeOffset,
-    LinkedNodeBuilder namedCompilationUnitMember_name,
-    bool simplyBoundable_isSimplyBounded,
-  })  : _kind = idl.LinkedNodeKind.classDeclaration,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = classDeclaration_extendsClause,
-        _variantField_15 = classDeclaration_abstractKeyword,
-        _variantField_7 = classDeclaration_withClause,
-        _variantField_8 = classDeclaration_nativeClause,
-        _variantField_16 = classDeclaration_classKeyword,
-        _variantField_18 = classOrMixinDeclaration_rightBracket,
-        _variantField_19 = classOrMixinDeclaration_leftBracket,
-        _variantField_27 = classDeclaration_isDartObject,
-        _variantField_12 = classOrMixinDeclaration_implementsClause,
-        _variantField_5 = classOrMixinDeclaration_members,
-        _variantField_13 = classOrMixinDeclaration_typeParameters,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_14 = namedCompilationUnitMember_name,
-        _variantField_31 = simplyBoundable_isSimplyBounded;
-
-  LinkedNodeBuilder.classTypeAlias({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder classTypeAlias_typeParameters,
-    int classTypeAlias_abstractKeyword,
-    LinkedNodeBuilder classTypeAlias_superclass,
-    LinkedNodeBuilder classTypeAlias_withClause,
-    int classTypeAlias_equals,
-    int typeAlias_typedefKeyword,
-    int typeAlias_semicolon,
-    LinkedNodeBuilder classTypeAlias_implementsClause,
-    int codeLength,
-    int codeOffset,
-    LinkedNodeBuilder namedCompilationUnitMember_name,
-    bool simplyBoundable_isSimplyBounded,
-  })  : _kind = idl.LinkedNodeKind.classTypeAlias,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = classTypeAlias_typeParameters,
-        _variantField_15 = classTypeAlias_abstractKeyword,
-        _variantField_7 = classTypeAlias_superclass,
-        _variantField_8 = classTypeAlias_withClause,
-        _variantField_16 = classTypeAlias_equals,
-        _variantField_18 = typeAlias_typedefKeyword,
-        _variantField_19 = typeAlias_semicolon,
-        _variantField_9 = classTypeAlias_implementsClause,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_14 = namedCompilationUnitMember_name,
-        _variantField_31 = simplyBoundable_isSimplyBounded;
-
-  LinkedNodeBuilder.declaredIdentifier({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder declaredIdentifier_identifier,
-    int declaredIdentifier_keyword,
-    LinkedNodeBuilder declaredIdentifier_type,
-  })  : _kind = idl.LinkedNodeKind.declaredIdentifier,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = declaredIdentifier_identifier,
-        _variantField_15 = declaredIdentifier_keyword,
-        _variantField_7 = declaredIdentifier_type;
-
-  LinkedNodeBuilder.enumConstantDeclaration({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder enumConstantDeclaration_name,
-  })  : _kind = idl.LinkedNodeKind.enumConstantDeclaration,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = enumConstantDeclaration_name;
-
-  LinkedNodeBuilder.fieldDeclaration({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder fieldDeclaration_fields,
-    int fieldDeclaration_covariantKeyword,
-    int fieldDeclaration_semicolon,
-    int fieldDeclaration_staticKeyword,
-  })  : _kind = idl.LinkedNodeKind.fieldDeclaration,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = fieldDeclaration_fields,
-        _variantField_15 = fieldDeclaration_covariantKeyword,
-        _variantField_16 = fieldDeclaration_semicolon,
-        _variantField_17 = fieldDeclaration_staticKeyword;
-
-  LinkedNodeBuilder.genericTypeAlias({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder genericTypeAlias_typeParameters,
-    LinkedNodeBuilder genericTypeAlias_functionType,
-    int genericTypeAlias_equals,
-    int typeAlias_typedefKeyword,
-    int typeAlias_semicolon,
-    int codeLength,
-    int codeOffset,
-    LinkedNodeBuilder namedCompilationUnitMember_name,
-    bool simplyBoundable_isSimplyBounded,
-  })  : _kind = idl.LinkedNodeKind.genericTypeAlias,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = genericTypeAlias_typeParameters,
-        _variantField_7 = genericTypeAlias_functionType,
-        _variantField_16 = genericTypeAlias_equals,
-        _variantField_18 = typeAlias_typedefKeyword,
-        _variantField_19 = typeAlias_semicolon,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_14 = namedCompilationUnitMember_name,
-        _variantField_31 = simplyBoundable_isSimplyBounded;
-
-  LinkedNodeBuilder.libraryDirective({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder libraryDirective_name,
-    int directive_keyword,
-    int directive_semicolon,
-  })  : _kind = idl.LinkedNodeKind.libraryDirective,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = libraryDirective_name,
-        _variantField_18 = directive_keyword,
-        _variantField_33 = directive_semicolon;
-
-  LinkedNodeBuilder.mixinDeclaration({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder mixinDeclaration_onClause,
-    int mixinDeclaration_mixinKeyword,
-    int classOrMixinDeclaration_rightBracket,
-    int classOrMixinDeclaration_leftBracket,
-    LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
-    List<LinkedNodeBuilder> classOrMixinDeclaration_members,
-    LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
-    int codeLength,
-    int codeOffset,
-    LinkedNodeBuilder namedCompilationUnitMember_name,
-    bool simplyBoundable_isSimplyBounded,
-  })  : _kind = idl.LinkedNodeKind.mixinDeclaration,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = mixinDeclaration_onClause,
-        _variantField_15 = mixinDeclaration_mixinKeyword,
-        _variantField_18 = classOrMixinDeclaration_rightBracket,
-        _variantField_19 = classOrMixinDeclaration_leftBracket,
-        _variantField_12 = classOrMixinDeclaration_implementsClause,
-        _variantField_5 = classOrMixinDeclaration_members,
-        _variantField_13 = classOrMixinDeclaration_typeParameters,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_14 = namedCompilationUnitMember_name,
-        _variantField_31 = simplyBoundable_isSimplyBounded;
-
-  LinkedNodeBuilder.partDirective({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    int directive_keyword,
-    int uriBasedDirective_uriElement,
-    int directive_semicolon,
-    LinkedNodeBuilder uriBasedDirective_uri,
-    String uriBasedDirective_uriContent,
-  })  : _kind = idl.LinkedNodeKind.partDirective,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_18 = directive_keyword,
-        _variantField_19 = uriBasedDirective_uriElement,
-        _variantField_33 = directive_semicolon,
-        _variantField_14 = uriBasedDirective_uri,
-        _variantField_22 = uriBasedDirective_uriContent;
-
-  LinkedNodeBuilder.partOfDirective({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder partOfDirective_libraryName,
-    LinkedNodeBuilder partOfDirective_uri,
-    int partOfDirective_ofKeyword,
-    int directive_keyword,
-    int directive_semicolon,
-  })  : _kind = idl.LinkedNodeKind.partOfDirective,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = partOfDirective_libraryName,
-        _variantField_7 = partOfDirective_uri,
-        _variantField_16 = partOfDirective_ofKeyword,
-        _variantField_18 = directive_keyword,
-        _variantField_33 = directive_semicolon;
-
-  LinkedNodeBuilder.topLevelVariableDeclaration({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder topLevelVariableDeclaration_variableList,
-    int topLevelVariableDeclaration_semicolon,
-  })  : _kind = idl.LinkedNodeKind.topLevelVariableDeclaration,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = topLevelVariableDeclaration_variableList,
-        _variantField_15 = topLevelVariableDeclaration_semicolon;
-
-  LinkedNodeBuilder.typeParameter({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder typeParameter_bound,
-    int typeParameter_extendsKeyword,
-    LinkedNodeBuilder typeParameter_name,
-    int typeParameter_id,
-    int codeLength,
-    int codeOffset,
-  })  : _kind = idl.LinkedNodeKind.typeParameter,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = typeParameter_bound,
-        _variantField_15 = typeParameter_extendsKeyword,
-        _variantField_7 = typeParameter_name,
-        _variantField_16 = typeParameter_id,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset;
-
-  LinkedNodeBuilder.switchCase({
-    List<LinkedNodeBuilder> switchMember_statements,
-    LinkedNodeBuilder switchCase_expression,
-    int switchMember_keyword,
-    int switchMember_colon,
-    List<LinkedNodeBuilder> switchMember_labels,
-  })  : _kind = idl.LinkedNodeKind.switchCase,
-        _variantField_4 = switchMember_statements,
-        _variantField_6 = switchCase_expression,
-        _variantField_15 = switchMember_keyword,
-        _variantField_16 = switchMember_colon,
-        _variantField_3 = switchMember_labels;
-
-  LinkedNodeBuilder.switchDefault({
-    List<LinkedNodeBuilder> switchMember_statements,
-    int switchMember_keyword,
-    int switchMember_colon,
-    List<LinkedNodeBuilder> switchMember_labels,
-  })  : _kind = idl.LinkedNodeKind.switchDefault,
-        _variantField_4 = switchMember_statements,
-        _variantField_15 = switchMember_keyword,
-        _variantField_16 = switchMember_colon,
-        _variantField_3 = switchMember_labels;
-
-  LinkedNodeBuilder.annotation({
-    LinkedNodeBuilder annotation_arguments,
-    int annotation_atSign,
-    LinkedNodeBuilder annotation_constructorName,
-    LinkedNodeBuilder annotation_name,
-    int annotation_period,
-  })  : _kind = idl.LinkedNodeKind.annotation,
-        _variantField_6 = annotation_arguments,
-        _variantField_15 = annotation_atSign,
-        _variantField_7 = annotation_constructorName,
-        _variantField_8 = annotation_name,
-        _variantField_16 = annotation_period;
-
-  LinkedNodeBuilder.asExpression({
-    LinkedNodeBuilder asExpression_expression,
-    int asExpression_asOperator,
-    LinkedNodeBuilder asExpression_type,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.asExpression,
-        _variantField_6 = asExpression_expression,
-        _variantField_15 = asExpression_asOperator,
-        _variantField_7 = asExpression_type,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.assertInitializer({
-    LinkedNodeBuilder assertInitializer_condition,
-    int assertInitializer_assertKeyword,
-    LinkedNodeBuilder assertInitializer_message,
-    int assertInitializer_comma,
-    int assertInitializer_leftParenthesis,
-    int assertInitializer_rightParenthesis,
-  })  : _kind = idl.LinkedNodeKind.assertInitializer,
-        _variantField_6 = assertInitializer_condition,
-        _variantField_15 = assertInitializer_assertKeyword,
-        _variantField_7 = assertInitializer_message,
-        _variantField_16 = assertInitializer_comma,
-        _variantField_17 = assertInitializer_leftParenthesis,
-        _variantField_18 = assertInitializer_rightParenthesis;
-
-  LinkedNodeBuilder.assertStatement({
-    LinkedNodeBuilder assertStatement_condition,
-    int assertStatement_assertKeyword,
-    LinkedNodeBuilder assertStatement_message,
-    int assertStatement_comma,
-    int assertStatement_leftParenthesis,
-    int assertStatement_rightParenthesis,
-    int assertStatement_semicolon,
-  })  : _kind = idl.LinkedNodeKind.assertStatement,
-        _variantField_6 = assertStatement_condition,
-        _variantField_15 = assertStatement_assertKeyword,
-        _variantField_7 = assertStatement_message,
-        _variantField_16 = assertStatement_comma,
-        _variantField_17 = assertStatement_leftParenthesis,
-        _variantField_18 = assertStatement_rightParenthesis,
-        _variantField_19 = assertStatement_semicolon;
-
-  LinkedNodeBuilder.assignmentExpression({
-    LinkedNodeBuilder assignmentExpression_leftHandSide,
-    int assignmentExpression_element,
-    LinkedNodeBuilder assignmentExpression_rightHandSide,
-    int assignmentExpression_operator,
-    LinkedNodeTypeBuilder assignmentExpression_elementType,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.assignmentExpression,
-        _variantField_6 = assignmentExpression_leftHandSide,
-        _variantField_15 = assignmentExpression_element,
-        _variantField_7 = assignmentExpression_rightHandSide,
-        _variantField_16 = assignmentExpression_operator,
-        _variantField_23 = assignmentExpression_elementType,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.awaitExpression({
-    LinkedNodeBuilder awaitExpression_expression,
-    int awaitExpression_awaitKeyword,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.awaitExpression,
-        _variantField_6 = awaitExpression_expression,
-        _variantField_15 = awaitExpression_awaitKeyword,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.blockFunctionBody({
-    LinkedNodeBuilder blockFunctionBody_block,
-    int blockFunctionBody_keyword,
-    int blockFunctionBody_star,
-  })  : _kind = idl.LinkedNodeKind.blockFunctionBody,
-        _variantField_6 = blockFunctionBody_block,
-        _variantField_15 = blockFunctionBody_keyword,
-        _variantField_16 = blockFunctionBody_star;
-
-  LinkedNodeBuilder.breakStatement({
-    LinkedNodeBuilder breakStatement_label,
-    int breakStatement_breakKeyword,
-    int breakStatement_semicolon,
-  })  : _kind = idl.LinkedNodeKind.breakStatement,
-        _variantField_6 = breakStatement_label,
-        _variantField_15 = breakStatement_breakKeyword,
-        _variantField_16 = breakStatement_semicolon;
-
-  LinkedNodeBuilder.catchClause({
-    LinkedNodeBuilder catchClause_body,
-    int catchClause_catchKeyword,
-    LinkedNodeBuilder catchClause_exceptionParameter,
-    LinkedNodeBuilder catchClause_exceptionType,
-    int catchClause_comma,
-    int catchClause_leftParenthesis,
-    int catchClause_onKeyword,
-    int catchClause_rightParenthesis,
-    LinkedNodeBuilder catchClause_stackTraceParameter,
-  })  : _kind = idl.LinkedNodeKind.catchClause,
-        _variantField_6 = catchClause_body,
-        _variantField_15 = catchClause_catchKeyword,
-        _variantField_7 = catchClause_exceptionParameter,
-        _variantField_8 = catchClause_exceptionType,
-        _variantField_16 = catchClause_comma,
-        _variantField_17 = catchClause_leftParenthesis,
-        _variantField_18 = catchClause_onKeyword,
-        _variantField_19 = catchClause_rightParenthesis,
-        _variantField_9 = catchClause_stackTraceParameter;
-
-  LinkedNodeBuilder.conditionalExpression({
-    LinkedNodeBuilder conditionalExpression_condition,
-    int conditionalExpression_colon,
-    LinkedNodeBuilder conditionalExpression_elseExpression,
-    LinkedNodeBuilder conditionalExpression_thenExpression,
-    int conditionalExpression_question,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.conditionalExpression,
-        _variantField_6 = conditionalExpression_condition,
-        _variantField_15 = conditionalExpression_colon,
-        _variantField_7 = conditionalExpression_elseExpression,
-        _variantField_8 = conditionalExpression_thenExpression,
-        _variantField_16 = conditionalExpression_question,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.configuration({
-    LinkedNodeBuilder configuration_name,
-    int configuration_ifKeyword,
-    LinkedNodeBuilder configuration_value,
-    LinkedNodeBuilder configuration_uri,
-    int configuration_leftParenthesis,
-    int configuration_rightParenthesis,
-    int configuration_equalToken,
-  })  : _kind = idl.LinkedNodeKind.configuration,
-        _variantField_6 = configuration_name,
-        _variantField_15 = configuration_ifKeyword,
-        _variantField_7 = configuration_value,
-        _variantField_8 = configuration_uri,
-        _variantField_16 = configuration_leftParenthesis,
-        _variantField_17 = configuration_rightParenthesis,
-        _variantField_18 = configuration_equalToken;
-
-  LinkedNodeBuilder.constructorFieldInitializer({
-    LinkedNodeBuilder constructorFieldInitializer_expression,
-    int constructorFieldInitializer_equals,
-    LinkedNodeBuilder constructorFieldInitializer_fieldName,
-    int constructorFieldInitializer_period,
-    int constructorFieldInitializer_thisKeyword,
-  })  : _kind = idl.LinkedNodeKind.constructorFieldInitializer,
-        _variantField_6 = constructorFieldInitializer_expression,
-        _variantField_15 = constructorFieldInitializer_equals,
-        _variantField_7 = constructorFieldInitializer_fieldName,
-        _variantField_16 = constructorFieldInitializer_period,
-        _variantField_17 = constructorFieldInitializer_thisKeyword;
-
-  LinkedNodeBuilder.constructorName({
-    LinkedNodeBuilder constructorName_name,
-    int constructorName_element,
-    LinkedNodeBuilder constructorName_type,
-    int constructorName_period,
-    LinkedNodeTypeBuilder constructorName_elementType,
-  })  : _kind = idl.LinkedNodeKind.constructorName,
-        _variantField_6 = constructorName_name,
-        _variantField_15 = constructorName_element,
-        _variantField_7 = constructorName_type,
-        _variantField_16 = constructorName_period,
-        _variantField_23 = constructorName_elementType;
-
-  LinkedNodeBuilder.continueStatement({
-    LinkedNodeBuilder continueStatement_label,
-    int continueStatement_continueKeyword,
-    int continueStatement_semicolon,
-  })  : _kind = idl.LinkedNodeKind.continueStatement,
-        _variantField_6 = continueStatement_label,
-        _variantField_15 = continueStatement_continueKeyword,
-        _variantField_16 = continueStatement_semicolon;
-
-  LinkedNodeBuilder.defaultFormalParameter({
-    LinkedNodeBuilder defaultFormalParameter_defaultValue,
-    int defaultFormalParameter_separator,
-    LinkedNodeBuilder defaultFormalParameter_parameter,
-    bool defaultFormalParameter_isNamed,
-    int codeLength,
-    int codeOffset,
-  })  : _kind = idl.LinkedNodeKind.defaultFormalParameter,
-        _variantField_6 = defaultFormalParameter_defaultValue,
-        _variantField_15 = defaultFormalParameter_separator,
-        _variantField_7 = defaultFormalParameter_parameter,
-        _variantField_27 = defaultFormalParameter_isNamed,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset;
-
-  LinkedNodeBuilder.doStatement({
-    LinkedNodeBuilder doStatement_body,
-    int doStatement_leftParenthesis,
-    LinkedNodeBuilder doStatement_condition,
-    int doStatement_rightParenthesis,
-    int doStatement_doKeyword,
-    int doStatement_semicolon,
-    int doStatement_whileKeyword,
-  })  : _kind = idl.LinkedNodeKind.doStatement,
-        _variantField_6 = doStatement_body,
-        _variantField_15 = doStatement_leftParenthesis,
-        _variantField_7 = doStatement_condition,
-        _variantField_16 = doStatement_rightParenthesis,
-        _variantField_17 = doStatement_doKeyword,
-        _variantField_18 = doStatement_semicolon,
-        _variantField_19 = doStatement_whileKeyword;
-
-  LinkedNodeBuilder.expressionFunctionBody({
-    LinkedNodeBuilder expressionFunctionBody_expression,
-    int expressionFunctionBody_arrow,
-    int expressionFunctionBody_keyword,
-    int expressionFunctionBody_semicolon,
-  })  : _kind = idl.LinkedNodeKind.expressionFunctionBody,
-        _variantField_6 = expressionFunctionBody_expression,
-        _variantField_15 = expressionFunctionBody_arrow,
-        _variantField_16 = expressionFunctionBody_keyword,
-        _variantField_17 = expressionFunctionBody_semicolon;
-
-  LinkedNodeBuilder.expressionStatement({
-    LinkedNodeBuilder expressionStatement_expression,
-    int expressionStatement_semicolon,
-  })  : _kind = idl.LinkedNodeKind.expressionStatement,
-        _variantField_6 = expressionStatement_expression,
-        _variantField_15 = expressionStatement_semicolon;
-
-  LinkedNodeBuilder.extendsClause({
-    LinkedNodeBuilder extendsClause_superclass,
-    int extendsClause_extendsKeyword,
-  })  : _kind = idl.LinkedNodeKind.extendsClause,
-        _variantField_6 = extendsClause_superclass,
-        _variantField_15 = extendsClause_extendsKeyword;
-
-  LinkedNodeBuilder.forEachPartsWithDeclaration({
-    LinkedNodeBuilder forEachParts_iterable,
-    int forEachParts_inKeyword,
-    LinkedNodeBuilder forEachPartsWithDeclaration_loopVariable,
-  })  : _kind = idl.LinkedNodeKind.forEachPartsWithDeclaration,
-        _variantField_6 = forEachParts_iterable,
-        _variantField_15 = forEachParts_inKeyword,
-        _variantField_7 = forEachPartsWithDeclaration_loopVariable;
-
-  LinkedNodeBuilder.forEachPartsWithIdentifier({
-    LinkedNodeBuilder forEachParts_iterable,
-    int forEachParts_inKeyword,
-    LinkedNodeBuilder forEachPartsWithIdentifier_identifier,
-  })  : _kind = idl.LinkedNodeKind.forEachPartsWithIdentifier,
-        _variantField_6 = forEachParts_iterable,
-        _variantField_15 = forEachParts_inKeyword,
-        _variantField_7 = forEachPartsWithIdentifier_identifier;
-
-  LinkedNodeBuilder.forElement({
-    LinkedNodeBuilder forMixin_forLoopParts,
-    int forMixin_awaitKeyword,
-    LinkedNodeBuilder forElement_body,
-    int forMixin_forKeyword,
-    int forMixin_leftParenthesis,
-    int forMixin_rightParenthesis,
-  })  : _kind = idl.LinkedNodeKind.forElement,
-        _variantField_6 = forMixin_forLoopParts,
-        _variantField_15 = forMixin_awaitKeyword,
-        _variantField_7 = forElement_body,
-        _variantField_16 = forMixin_forKeyword,
-        _variantField_17 = forMixin_leftParenthesis,
-        _variantField_19 = forMixin_rightParenthesis;
-
-  LinkedNodeBuilder.forStatement({
-    LinkedNodeBuilder forMixin_forLoopParts,
-    int forMixin_awaitKeyword,
-    LinkedNodeBuilder forStatement_body,
-    int forMixin_forKeyword,
-    int forMixin_leftParenthesis,
-    int forMixin_rightParenthesis,
-  })  : _kind = idl.LinkedNodeKind.forStatement,
-        _variantField_6 = forMixin_forLoopParts,
-        _variantField_15 = forMixin_awaitKeyword,
-        _variantField_7 = forStatement_body,
-        _variantField_16 = forMixin_forKeyword,
-        _variantField_17 = forMixin_leftParenthesis,
-        _variantField_19 = forMixin_rightParenthesis;
-
-  LinkedNodeBuilder.forPartsWithDeclarations({
-    LinkedNodeBuilder forParts_condition,
-    int forParts_leftSeparator,
-    LinkedNodeBuilder forPartsWithDeclarations_variables,
-    int forParts_rightSeparator,
-    List<LinkedNodeBuilder> forParts_updaters,
-  })  : _kind = idl.LinkedNodeKind.forPartsWithDeclarations,
-        _variantField_6 = forParts_condition,
-        _variantField_15 = forParts_leftSeparator,
-        _variantField_7 = forPartsWithDeclarations_variables,
-        _variantField_16 = forParts_rightSeparator,
-        _variantField_5 = forParts_updaters;
-
-  LinkedNodeBuilder.forPartsWithExpression({
-    LinkedNodeBuilder forParts_condition,
-    int forParts_leftSeparator,
-    LinkedNodeBuilder forPartsWithExpression_initialization,
-    int forParts_rightSeparator,
-    List<LinkedNodeBuilder> forParts_updaters,
-  })  : _kind = idl.LinkedNodeKind.forPartsWithExpression,
-        _variantField_6 = forParts_condition,
-        _variantField_15 = forParts_leftSeparator,
-        _variantField_7 = forPartsWithExpression_initialization,
-        _variantField_16 = forParts_rightSeparator,
-        _variantField_5 = forParts_updaters;
-
-  LinkedNodeBuilder.functionDeclarationStatement({
-    LinkedNodeBuilder functionDeclarationStatement_functionDeclaration,
-  })  : _kind = idl.LinkedNodeKind.functionDeclarationStatement,
-        _variantField_6 = functionDeclarationStatement_functionDeclaration;
-
-  LinkedNodeBuilder.ifElement({
-    LinkedNodeBuilder ifMixin_condition,
-    int ifMixin_elseKeyword,
-    LinkedNodeBuilder ifElement_thenElement,
-    int ifMixin_ifKeyword,
-    int ifMixin_leftParenthesis,
-    int ifMixin_rightParenthesis,
-    LinkedNodeBuilder ifElement_elseElement,
-  })  : _kind = idl.LinkedNodeKind.ifElement,
-        _variantField_6 = ifMixin_condition,
-        _variantField_15 = ifMixin_elseKeyword,
-        _variantField_8 = ifElement_thenElement,
-        _variantField_16 = ifMixin_ifKeyword,
-        _variantField_17 = ifMixin_leftParenthesis,
-        _variantField_18 = ifMixin_rightParenthesis,
-        _variantField_9 = ifElement_elseElement;
-
-  LinkedNodeBuilder.ifStatement({
-    LinkedNodeBuilder ifMixin_condition,
-    int ifMixin_elseKeyword,
-    LinkedNodeBuilder ifStatement_elseStatement,
-    LinkedNodeBuilder ifStatement_thenStatement,
-    int ifMixin_ifKeyword,
-    int ifMixin_leftParenthesis,
-    int ifMixin_rightParenthesis,
-  })  : _kind = idl.LinkedNodeKind.ifStatement,
-        _variantField_6 = ifMixin_condition,
-        _variantField_15 = ifMixin_elseKeyword,
-        _variantField_7 = ifStatement_elseStatement,
-        _variantField_8 = ifStatement_thenStatement,
-        _variantField_16 = ifMixin_ifKeyword,
-        _variantField_17 = ifMixin_leftParenthesis,
-        _variantField_18 = ifMixin_rightParenthesis;
-
-  LinkedNodeBuilder.indexExpression({
-    LinkedNodeBuilder indexExpression_index,
-    int indexExpression_element,
-    LinkedNodeBuilder indexExpression_target,
-    int indexExpression_period,
-    int indexExpression_leftBracket,
-    int indexExpression_rightBracket,
-    LinkedNodeTypeBuilder indexExpression_elementType,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.indexExpression,
-        _variantField_6 = indexExpression_index,
-        _variantField_15 = indexExpression_element,
-        _variantField_7 = indexExpression_target,
-        _variantField_16 = indexExpression_period,
-        _variantField_17 = indexExpression_leftBracket,
-        _variantField_18 = indexExpression_rightBracket,
-        _variantField_23 = indexExpression_elementType,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.instanceCreationExpression({
-    LinkedNodeBuilder instanceCreationExpression_arguments,
-    int instanceCreationExpression_keyword,
-    LinkedNodeBuilder instanceCreationExpression_constructorName,
-    LinkedNodeBuilder instanceCreationExpression_typeArguments,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.instanceCreationExpression,
-        _variantField_6 = instanceCreationExpression_arguments,
-        _variantField_15 = instanceCreationExpression_keyword,
-        _variantField_7 = instanceCreationExpression_constructorName,
-        _variantField_8 = instanceCreationExpression_typeArguments,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.interpolationExpression({
-    LinkedNodeBuilder interpolationExpression_expression,
-    int interpolationExpression_leftBracket,
-    int interpolationExpression_rightBracket,
-  })  : _kind = idl.LinkedNodeKind.interpolationExpression,
-        _variantField_6 = interpolationExpression_expression,
-        _variantField_15 = interpolationExpression_leftBracket,
-        _variantField_16 = interpolationExpression_rightBracket;
-
-  LinkedNodeBuilder.isExpression({
-    LinkedNodeBuilder isExpression_expression,
-    int isExpression_isOperator,
-    LinkedNodeBuilder isExpression_type,
-    int isExpression_notOperator,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.isExpression,
-        _variantField_6 = isExpression_expression,
-        _variantField_15 = isExpression_isOperator,
-        _variantField_7 = isExpression_type,
-        _variantField_16 = isExpression_notOperator,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.label({
-    LinkedNodeBuilder label_label,
-    int label_colon,
-  })  : _kind = idl.LinkedNodeKind.label,
-        _variantField_6 = label_label,
-        _variantField_15 = label_colon;
-
   LinkedNodeBuilder.mapLiteralEntry({
     LinkedNodeBuilder mapLiteralEntry_key,
-    int mapLiteralEntry_separator,
     LinkedNodeBuilder mapLiteralEntry_value,
   })  : _kind = idl.LinkedNodeKind.mapLiteralEntry,
         _variantField_6 = mapLiteralEntry_key,
-        _variantField_15 = mapLiteralEntry_separator,
         _variantField_7 = mapLiteralEntry_value;
 
+  LinkedNodeBuilder.methodDeclaration({
+    LinkedNodeTypeBuilder actualReturnType,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder methodDeclaration_body,
+    LinkedNodeBuilder methodDeclaration_formalParameters,
+    LinkedNodeBuilder methodDeclaration_returnType,
+    LinkedNodeBuilder methodDeclaration_typeParameters,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.methodDeclaration,
+        _variantField_24 = actualReturnType,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = methodDeclaration_body,
+        _variantField_7 = methodDeclaration_formalParameters,
+        _variantField_8 = methodDeclaration_returnType,
+        _variantField_9 = methodDeclaration_typeParameters,
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.methodInvocation({
+    LinkedNodeTypeBuilder invocationExpression_invokeType,
+    LinkedNodeBuilder methodInvocation_methodName,
+    LinkedNodeBuilder methodInvocation_target,
+    LinkedNodeBuilder invocationExpression_typeArguments,
+    LinkedNodeTypeBuilder expression_type,
+    LinkedNodeBuilder invocationExpression_arguments,
+  })  : _kind = idl.LinkedNodeKind.methodInvocation,
+        _variantField_24 = invocationExpression_invokeType,
+        _variantField_6 = methodInvocation_methodName,
+        _variantField_7 = methodInvocation_target,
+        _variantField_12 = invocationExpression_typeArguments,
+        _variantField_25 = expression_type,
+        _variantField_14 = invocationExpression_arguments;
+
+  LinkedNodeBuilder.mixinDeclaration({
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder mixinDeclaration_onClause,
+    LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
+    List<LinkedNodeBuilder> classOrMixinDeclaration_members,
+    LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
+    int informativeId,
+    List<String> mixinDeclaration_superInvokedNames,
+    bool simplyBoundable_isSimplyBounded,
+  })  : _kind = idl.LinkedNodeKind.mixinDeclaration,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = mixinDeclaration_onClause,
+        _variantField_12 = classOrMixinDeclaration_implementsClause,
+        _variantField_5 = classOrMixinDeclaration_members,
+        _variantField_13 = classOrMixinDeclaration_typeParameters,
+        _variantField_36 = informativeId,
+        _variantField_34 = mixinDeclaration_superInvokedNames,
+        _variantField_31 = simplyBoundable_isSimplyBounded;
+
   LinkedNodeBuilder.namedExpression({
     LinkedNodeBuilder namedExpression_expression,
     LinkedNodeBuilder namedExpression_name,
-    LinkedNodeTypeBuilder expression_type,
   })  : _kind = idl.LinkedNodeKind.namedExpression,
         _variantField_6 = namedExpression_expression,
-        _variantField_7 = namedExpression_name,
-        _variantField_25 = expression_type;
+        _variantField_7 = namedExpression_name;
 
   LinkedNodeBuilder.nativeClause({
     LinkedNodeBuilder nativeClause_name,
-    int nativeClause_nativeKeyword,
   })  : _kind = idl.LinkedNodeKind.nativeClause,
-        _variantField_6 = nativeClause_name,
-        _variantField_15 = nativeClause_nativeKeyword;
+        _variantField_6 = nativeClause_name;
 
   LinkedNodeBuilder.nativeFunctionBody({
     LinkedNodeBuilder nativeFunctionBody_stringLiteral,
-    int nativeFunctionBody_nativeKeyword,
-    int nativeFunctionBody_semicolon,
   })  : _kind = idl.LinkedNodeKind.nativeFunctionBody,
-        _variantField_6 = nativeFunctionBody_stringLiteral,
-        _variantField_15 = nativeFunctionBody_nativeKeyword,
-        _variantField_16 = nativeFunctionBody_semicolon;
+        _variantField_6 = nativeFunctionBody_stringLiteral;
+
+  LinkedNodeBuilder.nullLiteral({
+    int nullLiteral_fake,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.nullLiteral,
+        _variantField_15 = nullLiteral_fake,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.onClause({
+    List<LinkedNodeBuilder> onClause_superclassConstraints,
+  })  : _kind = idl.LinkedNodeKind.onClause,
+        _variantField_2 = onClause_superclassConstraints;
 
   LinkedNodeBuilder.parenthesizedExpression({
     LinkedNodeBuilder parenthesizedExpression_expression,
-    int parenthesizedExpression_leftParenthesis,
-    int parenthesizedExpression_rightParenthesis,
     LinkedNodeTypeBuilder expression_type,
   })  : _kind = idl.LinkedNodeKind.parenthesizedExpression,
         _variantField_6 = parenthesizedExpression_expression,
-        _variantField_15 = parenthesizedExpression_leftParenthesis,
-        _variantField_16 = parenthesizedExpression_rightParenthesis,
         _variantField_25 = expression_type;
 
+  LinkedNodeBuilder.partDirective({
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    int informativeId,
+    LinkedNodeBuilder uriBasedDirective_uri,
+    String uriBasedDirective_uriContent,
+    int uriBasedDirective_uriElement,
+  })  : _kind = idl.LinkedNodeKind.partDirective,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_36 = informativeId,
+        _variantField_14 = uriBasedDirective_uri,
+        _variantField_22 = uriBasedDirective_uriContent,
+        _variantField_19 = uriBasedDirective_uriElement;
+
+  LinkedNodeBuilder.partOfDirective({
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder partOfDirective_libraryName,
+    LinkedNodeBuilder partOfDirective_uri,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.partOfDirective,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = partOfDirective_libraryName,
+        _variantField_7 = partOfDirective_uri,
+        _variantField_36 = informativeId;
+
   LinkedNodeBuilder.postfixExpression({
     LinkedNodeBuilder postfixExpression_operand,
-    int postfixExpression_element,
-    int postfixExpression_operator,
     LinkedNodeTypeBuilder postfixExpression_elementType,
+    int postfixExpression_element,
+    idl.UnlinkedTokenType postfixExpression_operator,
     LinkedNodeTypeBuilder expression_type,
   })  : _kind = idl.LinkedNodeKind.postfixExpression,
         _variantField_6 = postfixExpression_operand,
-        _variantField_15 = postfixExpression_element,
-        _variantField_16 = postfixExpression_operator,
         _variantField_23 = postfixExpression_elementType,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.prefixedIdentifier({
-    LinkedNodeBuilder prefixedIdentifier_identifier,
-    int prefixedIdentifier_period,
-    LinkedNodeBuilder prefixedIdentifier_prefix,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.prefixedIdentifier,
-        _variantField_6 = prefixedIdentifier_identifier,
-        _variantField_15 = prefixedIdentifier_period,
-        _variantField_7 = prefixedIdentifier_prefix,
+        _variantField_15 = postfixExpression_element,
+        _variantField_28 = postfixExpression_operator,
         _variantField_25 = expression_type;
 
   LinkedNodeBuilder.prefixExpression({
     LinkedNodeBuilder prefixExpression_operand,
-    int prefixExpression_element,
-    int prefixExpression_operator,
     LinkedNodeTypeBuilder prefixExpression_elementType,
+    int prefixExpression_element,
+    idl.UnlinkedTokenType prefixExpression_operator,
     LinkedNodeTypeBuilder expression_type,
   })  : _kind = idl.LinkedNodeKind.prefixExpression,
         _variantField_6 = prefixExpression_operand,
-        _variantField_15 = prefixExpression_element,
-        _variantField_16 = prefixExpression_operator,
         _variantField_23 = prefixExpression_elementType,
+        _variantField_15 = prefixExpression_element,
+        _variantField_28 = prefixExpression_operator,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.prefixedIdentifier({
+    LinkedNodeBuilder prefixedIdentifier_identifier,
+    LinkedNodeBuilder prefixedIdentifier_prefix,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.prefixedIdentifier,
+        _variantField_6 = prefixedIdentifier_identifier,
+        _variantField_7 = prefixedIdentifier_prefix,
         _variantField_25 = expression_type;
 
   LinkedNodeBuilder.propertyAccess({
     LinkedNodeBuilder propertyAccess_propertyName,
-    int propertyAccess_operator,
     LinkedNodeBuilder propertyAccess_target,
+    idl.UnlinkedTokenType propertyAccess_operator,
     LinkedNodeTypeBuilder expression_type,
   })  : _kind = idl.LinkedNodeKind.propertyAccess,
         _variantField_6 = propertyAccess_propertyName,
-        _variantField_15 = propertyAccess_operator,
         _variantField_7 = propertyAccess_target,
+        _variantField_28 = propertyAccess_operator,
         _variantField_25 = expression_type;
 
   LinkedNodeBuilder.redirectingConstructorInvocation({
     LinkedNodeBuilder redirectingConstructorInvocation_arguments,
-    int redirectingConstructorInvocation_element,
     LinkedNodeBuilder redirectingConstructorInvocation_constructorName,
-    int redirectingConstructorInvocation_period,
-    int redirectingConstructorInvocation_thisKeyword,
     LinkedNodeTypeBuilder redirectingConstructorInvocation_elementType,
+    int redirectingConstructorInvocation_element,
   })  : _kind = idl.LinkedNodeKind.redirectingConstructorInvocation,
         _variantField_6 = redirectingConstructorInvocation_arguments,
-        _variantField_15 = redirectingConstructorInvocation_element,
         _variantField_7 = redirectingConstructorInvocation_constructorName,
-        _variantField_16 = redirectingConstructorInvocation_period,
-        _variantField_17 = redirectingConstructorInvocation_thisKeyword,
-        _variantField_23 = redirectingConstructorInvocation_elementType;
+        _variantField_23 = redirectingConstructorInvocation_elementType,
+        _variantField_15 = redirectingConstructorInvocation_element;
+
+  LinkedNodeBuilder.rethrowExpression({
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.rethrowExpression,
+        _variantField_25 = expression_type;
 
   LinkedNodeBuilder.returnStatement({
     LinkedNodeBuilder returnStatement_expression,
-    int returnStatement_returnKeyword,
-    int returnStatement_semicolon,
   })  : _kind = idl.LinkedNodeKind.returnStatement,
-        _variantField_6 = returnStatement_expression,
-        _variantField_15 = returnStatement_returnKeyword,
-        _variantField_16 = returnStatement_semicolon;
+        _variantField_6 = returnStatement_expression;
 
-  LinkedNodeBuilder.spreadElement({
-    LinkedNodeBuilder spreadElement_expression,
-    int spreadElement_spreadOperator,
-  })  : _kind = idl.LinkedNodeKind.spreadElement,
-        _variantField_6 = spreadElement_expression,
-        _variantField_15 = spreadElement_spreadOperator;
-
-  LinkedNodeBuilder.superConstructorInvocation({
-    LinkedNodeBuilder superConstructorInvocation_arguments,
-    int superConstructorInvocation_element,
-    LinkedNodeBuilder superConstructorInvocation_constructorName,
-    int superConstructorInvocation_period,
-    int superConstructorInvocation_superKeyword,
-    LinkedNodeTypeBuilder superConstructorInvocation_elementType,
-  })  : _kind = idl.LinkedNodeKind.superConstructorInvocation,
-        _variantField_6 = superConstructorInvocation_arguments,
-        _variantField_15 = superConstructorInvocation_element,
-        _variantField_7 = superConstructorInvocation_constructorName,
-        _variantField_16 = superConstructorInvocation_period,
-        _variantField_17 = superConstructorInvocation_superKeyword,
-        _variantField_23 = superConstructorInvocation_elementType;
-
-  LinkedNodeBuilder.throwExpression({
-    LinkedNodeBuilder throwExpression_expression,
-    int throwExpression_throwKeyword,
+  LinkedNodeBuilder.setOrMapLiteral({
+    List<LinkedNodeBuilder> typedLiteral_typeArguments,
+    List<LinkedNodeBuilder> setOrMapLiteral_elements,
     LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.throwExpression,
-        _variantField_6 = throwExpression_expression,
-        _variantField_15 = throwExpression_throwKeyword,
+  })  : _kind = idl.LinkedNodeKind.setOrMapLiteral,
+        _variantField_2 = typedLiteral_typeArguments,
+        _variantField_3 = setOrMapLiteral_elements,
         _variantField_25 = expression_type;
 
-  LinkedNodeBuilder.typeName({
-    LinkedNodeBuilder typeName_name,
-    int typeName_question,
-    LinkedNodeBuilder typeName_typeArguments,
-    LinkedNodeTypeBuilder typeName_type,
-  })  : _kind = idl.LinkedNodeKind.typeName,
-        _variantField_6 = typeName_name,
-        _variantField_15 = typeName_question,
-        _variantField_7 = typeName_typeArguments,
-        _variantField_23 = typeName_type;
+  LinkedNodeBuilder.showCombinator({
+    List<String> names,
+  })  : _kind = idl.LinkedNodeKind.showCombinator,
+        _variantField_34 = names;
 
-  LinkedNodeBuilder.variableDeclarationStatement({
-    LinkedNodeBuilder variableDeclarationStatement_variables,
-    int variableDeclarationStatement_semicolon,
-  })  : _kind = idl.LinkedNodeKind.variableDeclarationStatement,
-        _variantField_6 = variableDeclarationStatement_variables,
-        _variantField_15 = variableDeclarationStatement_semicolon;
-
-  LinkedNodeBuilder.whileStatement({
-    LinkedNodeBuilder whileStatement_body,
-    int whileStatement_leftParenthesis,
-    LinkedNodeBuilder whileStatement_condition,
-    int whileStatement_rightParenthesis,
-    int whileStatement_whileKeyword,
-  })  : _kind = idl.LinkedNodeKind.whileStatement,
-        _variantField_6 = whileStatement_body,
-        _variantField_15 = whileStatement_leftParenthesis,
-        _variantField_7 = whileStatement_condition,
-        _variantField_16 = whileStatement_rightParenthesis,
-        _variantField_17 = whileStatement_whileKeyword;
-
-  LinkedNodeBuilder.yieldStatement({
-    LinkedNodeBuilder yieldStatement_expression,
-    int yieldStatement_yieldKeyword,
-    int yieldStatement_star,
-    int yieldStatement_semicolon,
-  })  : _kind = idl.LinkedNodeKind.yieldStatement,
-        _variantField_6 = yieldStatement_expression,
-        _variantField_15 = yieldStatement_yieldKeyword,
-        _variantField_16 = yieldStatement_star,
-        _variantField_17 = yieldStatement_semicolon;
-
-  LinkedNodeBuilder.booleanLiteral({
-    int booleanLiteral_literal,
-    bool booleanLiteral_value,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.booleanLiteral,
-        _variantField_15 = booleanLiteral_literal,
-        _variantField_27 = booleanLiteral_value,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.doubleLiteral({
-    int doubleLiteral_literal,
-    double doubleLiteral_value,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.doubleLiteral,
-        _variantField_15 = doubleLiteral_literal,
-        _variantField_21 = doubleLiteral_value,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.emptyFunctionBody({
-    int emptyFunctionBody_semicolon,
-  })  : _kind = idl.LinkedNodeKind.emptyFunctionBody,
-        _variantField_15 = emptyFunctionBody_semicolon;
-
-  LinkedNodeBuilder.emptyStatement({
-    int emptyStatement_semicolon,
-  })  : _kind = idl.LinkedNodeKind.emptyStatement,
-        _variantField_15 = emptyStatement_semicolon;
-
-  LinkedNodeBuilder.integerLiteral({
-    int integerLiteral_literal,
-    int integerLiteral_value,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.integerLiteral,
-        _variantField_15 = integerLiteral_literal,
-        _variantField_16 = integerLiteral_value,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.interpolationString({
-    int interpolationString_token,
-    String interpolationString_value,
-  })  : _kind = idl.LinkedNodeKind.interpolationString,
-        _variantField_15 = interpolationString_token,
-        _variantField_30 = interpolationString_value;
-
-  LinkedNodeBuilder.nullLiteral({
-    int nullLiteral_literal,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.nullLiteral,
-        _variantField_15 = nullLiteral_literal,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.rethrowExpression({
-    int rethrowExpression_rethrowKeyword,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.rethrowExpression,
-        _variantField_15 = rethrowExpression_rethrowKeyword,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.scriptTag({
-    int scriptTag_scriptTag,
-  })  : _kind = idl.LinkedNodeKind.scriptTag,
-        _variantField_15 = scriptTag_scriptTag;
+  LinkedNodeBuilder.simpleFormalParameter({
+    LinkedNodeTypeBuilder actualType,
+    List<LinkedNodeBuilder> normalFormalParameter_metadata,
+    LinkedNodeBuilder simpleFormalParameter_type,
+    bool inheritsCovariant,
+    int informativeId,
+    TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
+  })  : _kind = idl.LinkedNodeKind.simpleFormalParameter,
+        _variantField_24 = actualType,
+        _variantField_4 = normalFormalParameter_metadata,
+        _variantField_6 = simpleFormalParameter_type,
+        _variantField_27 = inheritsCovariant,
+        _variantField_36 = informativeId,
+        _variantField_32 = topLevelTypeInferenceError;
 
   LinkedNodeBuilder.simpleIdentifier({
-    int simpleIdentifier_element,
-    int simpleIdentifier_token,
     LinkedNodeTypeBuilder simpleIdentifier_elementType,
+    int simpleIdentifier_element,
     LinkedNodeTypeBuilder expression_type,
   })  : _kind = idl.LinkedNodeKind.simpleIdentifier,
-        _variantField_15 = simpleIdentifier_element,
-        _variantField_16 = simpleIdentifier_token,
         _variantField_23 = simpleIdentifier_elementType,
+        _variantField_15 = simpleIdentifier_element,
         _variantField_25 = expression_type;
 
   LinkedNodeBuilder.simpleStringLiteral({
-    int simpleStringLiteral_token,
-    LinkedNodeTypeBuilder expression_type,
     String simpleStringLiteral_value,
   })  : _kind = idl.LinkedNodeKind.simpleStringLiteral,
-        _variantField_15 = simpleStringLiteral_token,
-        _variantField_25 = expression_type,
         _variantField_20 = simpleStringLiteral_value;
 
+  LinkedNodeBuilder.spreadElement({
+    LinkedNodeBuilder spreadElement_expression,
+    idl.UnlinkedTokenType spreadElement_spreadOperator,
+  })  : _kind = idl.LinkedNodeKind.spreadElement,
+        _variantField_6 = spreadElement_expression,
+        _variantField_35 = spreadElement_spreadOperator;
+
+  LinkedNodeBuilder.stringInterpolation({
+    List<LinkedNodeBuilder> stringInterpolation_elements,
+  })  : _kind = idl.LinkedNodeKind.stringInterpolation,
+        _variantField_2 = stringInterpolation_elements;
+
+  LinkedNodeBuilder.superConstructorInvocation({
+    LinkedNodeBuilder superConstructorInvocation_arguments,
+    LinkedNodeBuilder superConstructorInvocation_constructorName,
+    LinkedNodeTypeBuilder superConstructorInvocation_elementType,
+    int superConstructorInvocation_element,
+  })  : _kind = idl.LinkedNodeKind.superConstructorInvocation,
+        _variantField_6 = superConstructorInvocation_arguments,
+        _variantField_7 = superConstructorInvocation_constructorName,
+        _variantField_23 = superConstructorInvocation_elementType,
+        _variantField_15 = superConstructorInvocation_element;
+
   LinkedNodeBuilder.superExpression({
-    int superExpression_superKeyword,
     LinkedNodeTypeBuilder expression_type,
   })  : _kind = idl.LinkedNodeKind.superExpression,
-        _variantField_15 = superExpression_superKeyword,
         _variantField_25 = expression_type;
 
+  LinkedNodeBuilder.switchCase({
+    List<LinkedNodeBuilder> switchMember_statements,
+    LinkedNodeBuilder switchCase_expression,
+    List<LinkedNodeBuilder> switchMember_labels,
+  })  : _kind = idl.LinkedNodeKind.switchCase,
+        _variantField_4 = switchMember_statements,
+        _variantField_6 = switchCase_expression,
+        _variantField_3 = switchMember_labels;
+
+  LinkedNodeBuilder.switchDefault({
+    List<LinkedNodeBuilder> switchMember_statements,
+    List<LinkedNodeBuilder> switchMember_labels,
+  })  : _kind = idl.LinkedNodeKind.switchDefault,
+        _variantField_4 = switchMember_statements,
+        _variantField_3 = switchMember_labels;
+
+  LinkedNodeBuilder.switchStatement({
+    List<LinkedNodeBuilder> switchStatement_members,
+    LinkedNodeBuilder switchStatement_expression,
+  })  : _kind = idl.LinkedNodeKind.switchStatement,
+        _variantField_2 = switchStatement_members,
+        _variantField_7 = switchStatement_expression;
+
   LinkedNodeBuilder.symbolLiteral({
-    int symbolLiteral_poundSign,
-    List<int> symbolLiteral_components,
     LinkedNodeTypeBuilder expression_type,
+    List<String> names,
   })  : _kind = idl.LinkedNodeKind.symbolLiteral,
-        _variantField_15 = symbolLiteral_poundSign,
-        _variantField_28 = symbolLiteral_components,
-        _variantField_25 = expression_type;
+        _variantField_25 = expression_type,
+        _variantField_34 = names;
 
   LinkedNodeBuilder.thisExpression({
-    int thisExpression_thisKeyword,
     LinkedNodeTypeBuilder expression_type,
   })  : _kind = idl.LinkedNodeKind.thisExpression,
-        _variantField_15 = thisExpression_thisKeyword,
         _variantField_25 = expression_type;
 
-  LinkedNodeBuilder.comment({
-    List<int> comment_tokens,
-    idl.LinkedNodeCommentType comment_type,
-  })  : _kind = idl.LinkedNodeKind.comment,
-        _variantField_28 = comment_tokens,
-        _variantField_29 = comment_type;
+  LinkedNodeBuilder.throwExpression({
+    LinkedNodeBuilder throwExpression_expression,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.throwExpression,
+        _variantField_6 = throwExpression_expression,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.topLevelVariableDeclaration({
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder topLevelVariableDeclaration_variableList,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.topLevelVariableDeclaration,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = topLevelVariableDeclaration_variableList,
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.tryStatement({
+    List<LinkedNodeBuilder> tryStatement_catchClauses,
+    LinkedNodeBuilder tryStatement_body,
+    LinkedNodeBuilder tryStatement_finallyBlock,
+  })  : _kind = idl.LinkedNodeKind.tryStatement,
+        _variantField_2 = tryStatement_catchClauses,
+        _variantField_6 = tryStatement_body,
+        _variantField_7 = tryStatement_finallyBlock;
+
+  LinkedNodeBuilder.typeArgumentList({
+    List<LinkedNodeBuilder> typeArgumentList_arguments,
+  })  : _kind = idl.LinkedNodeKind.typeArgumentList,
+        _variantField_2 = typeArgumentList_arguments;
+
+  LinkedNodeBuilder.typeName({
+    List<LinkedNodeBuilder> typeName_typeArguments,
+    LinkedNodeBuilder typeName_name,
+    LinkedNodeTypeBuilder typeName_type,
+  })  : _kind = idl.LinkedNodeKind.typeName,
+        _variantField_2 = typeName_typeArguments,
+        _variantField_6 = typeName_name,
+        _variantField_23 = typeName_type;
+
+  LinkedNodeBuilder.typeParameter({
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder typeParameter_bound,
+    LinkedNodeTypeBuilder typeParameter_defaultType,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.typeParameter,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = typeParameter_bound,
+        _variantField_23 = typeParameter_defaultType,
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.typeParameterList({
+    List<LinkedNodeBuilder> typeParameterList_typeParameters,
+  })  : _kind = idl.LinkedNodeKind.typeParameterList,
+        _variantField_2 = typeParameterList_typeParameters;
+
+  LinkedNodeBuilder.variableDeclaration({
+    LinkedNodeTypeBuilder actualType,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder variableDeclaration_initializer,
+    bool inheritsCovariant,
+    int informativeId,
+    TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
+  })  : _kind = idl.LinkedNodeKind.variableDeclaration,
+        _variantField_24 = actualType,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = variableDeclaration_initializer,
+        _variantField_27 = inheritsCovariant,
+        _variantField_36 = informativeId,
+        _variantField_32 = topLevelTypeInferenceError;
+
+  LinkedNodeBuilder.variableDeclarationList({
+    List<LinkedNodeBuilder> variableDeclarationList_variables,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder variableDeclarationList_type,
+    int informativeId,
+  })  : _kind = idl.LinkedNodeKind.variableDeclarationList,
+        _variantField_2 = variableDeclarationList_variables,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = variableDeclarationList_type,
+        _variantField_36 = informativeId;
+
+  LinkedNodeBuilder.variableDeclarationStatement({
+    LinkedNodeBuilder variableDeclarationStatement_variables,
+  })  : _kind = idl.LinkedNodeKind.variableDeclarationStatement,
+        _variantField_6 = variableDeclarationStatement_variables;
+
+  LinkedNodeBuilder.whileStatement({
+    LinkedNodeBuilder whileStatement_body,
+    LinkedNodeBuilder whileStatement_condition,
+  })  : _kind = idl.LinkedNodeKind.whileStatement,
+        _variantField_6 = whileStatement_body,
+        _variantField_7 = whileStatement_condition;
+
+  LinkedNodeBuilder.withClause({
+    List<LinkedNodeBuilder> withClause_mixinTypes,
+  })  : _kind = idl.LinkedNodeKind.withClause,
+        _variantField_2 = withClause_mixinTypes;
+
+  LinkedNodeBuilder.yieldStatement({
+    LinkedNodeBuilder yieldStatement_expression,
+  })  : _kind = idl.LinkedNodeKind.yieldStatement,
+        _variantField_6 = yieldStatement_expression;
 
   /// Flush [informative] data recursively.
   void flushInformative() {
-    _variantField_24?.flushInformative();
-    _variantField_2?.forEach((b) => b.flushInformative());
-    _variantField_11?.flushInformative();
-    _variantField_4?.forEach((b) => b.flushInformative());
-    _variantField_6?.flushInformative();
-    _variantField_7?.flushInformative();
-    _variantField_8?.flushInformative();
-    _variantField_23?.flushInformative();
-    _variantField_9?.flushInformative();
-    _variantField_12?.flushInformative();
-    _variantField_5?.forEach((b) => b.flushInformative());
-    _variantField_13?.flushInformative();
-    _variantField_3?.forEach((b) => b.flushInformative());
-    _variantField_10?.flushInformative();
-    _variantField_25?.flushInformative();
-    _variantField_14?.flushInformative();
-    _variantField_32?.flushInformative();
+    if (kind == idl.LinkedNodeKind.adjacentStrings) {
+      adjacentStrings_strings?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.annotation) {
+      annotation_arguments?.flushInformative();
+      annotation_constructorName?.flushInformative();
+      annotation_elementType?.flushInformative();
+      annotation_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.argumentList) {
+      argumentList_arguments?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.asExpression) {
+      asExpression_expression?.flushInformative();
+      asExpression_type?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.assertInitializer) {
+      assertInitializer_condition?.flushInformative();
+      assertInitializer_message?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.assertStatement) {
+      assertStatement_condition?.flushInformative();
+      assertStatement_message?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.assignmentExpression) {
+      assignmentExpression_leftHandSide?.flushInformative();
+      assignmentExpression_rightHandSide?.flushInformative();
+      assignmentExpression_elementType?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.awaitExpression) {
+      awaitExpression_expression?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.binaryExpression) {
+      binaryExpression_invokeType?.flushInformative();
+      binaryExpression_leftOperand?.flushInformative();
+      binaryExpression_rightOperand?.flushInformative();
+      binaryExpression_elementType?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.block) {
+      block_statements?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.blockFunctionBody) {
+      blockFunctionBody_block?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.booleanLiteral) {
+    } else if (kind == idl.LinkedNodeKind.breakStatement) {
+      breakStatement_label?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.cascadeExpression) {
+      cascadeExpression_sections?.forEach((b) => b.flushInformative());
+      cascadeExpression_target?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.catchClause) {
+      catchClause_body?.flushInformative();
+      catchClause_exceptionParameter?.flushInformative();
+      catchClause_exceptionType?.flushInformative();
+      catchClause_stackTraceParameter?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.classDeclaration) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      classDeclaration_extendsClause?.flushInformative();
+      classDeclaration_withClause?.flushInformative();
+      classDeclaration_nativeClause?.flushInformative();
+      classOrMixinDeclaration_implementsClause?.flushInformative();
+      classOrMixinDeclaration_members?.forEach((b) => b.flushInformative());
+      classOrMixinDeclaration_typeParameters?.flushInformative();
+      informativeId = null;
+      unused11?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.classTypeAlias) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      classTypeAlias_typeParameters?.flushInformative();
+      classTypeAlias_superclass?.flushInformative();
+      classTypeAlias_withClause?.flushInformative();
+      classTypeAlias_implementsClause?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.comment) {
+      comment_references?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.commentReference) {
+      commentReference_identifier?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.compilationUnit) {
+      compilationUnit_declarations?.forEach((b) => b.flushInformative());
+      compilationUnit_scriptTag?.flushInformative();
+      compilationUnit_directives?.forEach((b) => b.flushInformative());
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.conditionalExpression) {
+      conditionalExpression_condition?.flushInformative();
+      conditionalExpression_elseExpression?.flushInformative();
+      conditionalExpression_thenExpression?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.configuration) {
+      configuration_name?.flushInformative();
+      configuration_value?.flushInformative();
+      configuration_uri?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+      constructorDeclaration_initializers?.forEach((b) => b.flushInformative());
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      constructorDeclaration_body?.flushInformative();
+      constructorDeclaration_parameters?.flushInformative();
+      constructorDeclaration_redirectedConstructor?.flushInformative();
+      constructorDeclaration_returnType?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
+      constructorFieldInitializer_expression?.flushInformative();
+      constructorFieldInitializer_fieldName?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.constructorName) {
+      constructorName_name?.flushInformative();
+      constructorName_type?.flushInformative();
+      constructorName_elementType?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.continueStatement) {
+      continueStatement_label?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.declaredIdentifier) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      declaredIdentifier_identifier?.flushInformative();
+      declaredIdentifier_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+      defaultFormalParameter_defaultValue?.flushInformative();
+      defaultFormalParameter_parameter?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.doStatement) {
+      doStatement_body?.flushInformative();
+      doStatement_condition?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.dottedName) {
+      dottedName_components?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.doubleLiteral) {
+    } else if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+    } else if (kind == idl.LinkedNodeKind.emptyStatement) {
+    } else if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.enumDeclaration) {
+      enumDeclaration_constants?.forEach((b) => b.flushInformative());
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.exportDirective) {
+      namespaceDirective_combinators?.forEach((b) => b.flushInformative());
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      namespaceDirective_configurations?.forEach((b) => b.flushInformative());
+      informativeId = null;
+      uriBasedDirective_uri?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
+      expressionFunctionBody_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.expressionStatement) {
+      expressionStatement_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.extendsClause) {
+      extendsClause_superclass?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      fieldDeclaration_fields?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+      actualType?.flushInformative();
+      normalFormalParameter_metadata?.forEach((b) => b.flushInformative());
+      fieldFormalParameter_type?.flushInformative();
+      fieldFormalParameter_typeParameters?.flushInformative();
+      fieldFormalParameter_formalParameters?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
+      forEachParts_iterable?.flushInformative();
+      forEachPartsWithDeclaration_loopVariable?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
+      forEachParts_iterable?.flushInformative();
+      forEachPartsWithIdentifier_identifier?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.forElement) {
+      forMixin_forLoopParts?.flushInformative();
+      forElement_body?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
+      forParts_condition?.flushInformative();
+      forPartsWithDeclarations_variables?.flushInformative();
+      forParts_updaters?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
+      forParts_condition?.flushInformative();
+      forPartsWithExpression_initialization?.flushInformative();
+      forParts_updaters?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.forStatement) {
+      forMixin_forLoopParts?.flushInformative();
+      forStatement_body?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.formalParameterList) {
+      formalParameterList_parameters?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.functionDeclaration) {
+      actualReturnType?.flushInformative();
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      functionDeclaration_functionExpression?.flushInformative();
+      functionDeclaration_returnType?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
+      functionDeclarationStatement_functionDeclaration?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.functionExpression) {
+      actualReturnType?.flushInformative();
+      functionExpression_body?.flushInformative();
+      functionExpression_formalParameters?.flushInformative();
+      functionExpression_typeParameters?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+      invocationExpression_invokeType?.flushInformative();
+      functionExpressionInvocation_function?.flushInformative();
+      invocationExpression_typeArguments?.flushInformative();
+      expression_type?.flushInformative();
+      invocationExpression_arguments?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+      actualReturnType?.flushInformative();
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      functionTypeAlias_formalParameters?.flushInformative();
+      functionTypeAlias_returnType?.flushInformative();
+      functionTypeAlias_typeParameters?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+      actualType?.flushInformative();
+      normalFormalParameter_metadata?.forEach((b) => b.flushInformative());
+      functionTypedFormalParameter_formalParameters?.flushInformative();
+      functionTypedFormalParameter_returnType?.flushInformative();
+      functionTypedFormalParameter_typeParameters?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.genericFunctionType) {
+      actualReturnType?.flushInformative();
+      genericFunctionType_typeParameters?.flushInformative();
+      genericFunctionType_returnType?.flushInformative();
+      genericFunctionType_formalParameters?.flushInformative();
+      genericFunctionType_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      genericTypeAlias_typeParameters?.flushInformative();
+      genericTypeAlias_functionType?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.hideCombinator) {
+    } else if (kind == idl.LinkedNodeKind.ifElement) {
+      ifMixin_condition?.flushInformative();
+      ifElement_thenElement?.flushInformative();
+      ifElement_elseElement?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.ifStatement) {
+      ifMixin_condition?.flushInformative();
+      ifStatement_elseStatement?.flushInformative();
+      ifStatement_thenStatement?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.implementsClause) {
+      implementsClause_interfaces?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.importDirective) {
+      namespaceDirective_combinators?.forEach((b) => b.flushInformative());
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      namespaceDirective_configurations?.forEach((b) => b.flushInformative());
+      informativeId = null;
+      uriBasedDirective_uri?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.indexExpression) {
+      indexExpression_index?.flushInformative();
+      indexExpression_target?.flushInformative();
+      indexExpression_elementType?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+      instanceCreationExpression_arguments
+          ?.forEach((b) => b.flushInformative());
+      instanceCreationExpression_constructorName?.flushInformative();
+      instanceCreationExpression_typeArguments?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.integerLiteral) {
+    } else if (kind == idl.LinkedNodeKind.interpolationExpression) {
+      interpolationExpression_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.interpolationString) {
+    } else if (kind == idl.LinkedNodeKind.isExpression) {
+      isExpression_expression?.flushInformative();
+      isExpression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.label) {
+      label_label?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.labeledStatement) {
+      labeledStatement_labels?.forEach((b) => b.flushInformative());
+      labeledStatement_statement?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.libraryDirective) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      libraryDirective_name?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+      libraryIdentifier_components?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.listLiteral) {
+      typedLiteral_typeArguments?.forEach((b) => b.flushInformative());
+      listLiteral_elements?.forEach((b) => b.flushInformative());
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
+      mapLiteralEntry_key?.flushInformative();
+      mapLiteralEntry_value?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.methodDeclaration) {
+      actualReturnType?.flushInformative();
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      methodDeclaration_body?.flushInformative();
+      methodDeclaration_formalParameters?.flushInformative();
+      methodDeclaration_returnType?.flushInformative();
+      methodDeclaration_typeParameters?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.methodInvocation) {
+      invocationExpression_invokeType?.flushInformative();
+      methodInvocation_methodName?.flushInformative();
+      methodInvocation_target?.flushInformative();
+      invocationExpression_typeArguments?.flushInformative();
+      expression_type?.flushInformative();
+      invocationExpression_arguments?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      mixinDeclaration_onClause?.flushInformative();
+      classOrMixinDeclaration_implementsClause?.flushInformative();
+      classOrMixinDeclaration_members?.forEach((b) => b.flushInformative());
+      classOrMixinDeclaration_typeParameters?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.namedExpression) {
+      namedExpression_expression?.flushInformative();
+      namedExpression_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.nativeClause) {
+      nativeClause_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
+      nativeFunctionBody_stringLiteral?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.nullLiteral) {
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.onClause) {
+      onClause_superclassConstraints?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
+      parenthesizedExpression_expression?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.partDirective) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      informativeId = null;
+      uriBasedDirective_uri?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.partOfDirective) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      partOfDirective_libraryName?.flushInformative();
+      partOfDirective_uri?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.postfixExpression) {
+      postfixExpression_operand?.flushInformative();
+      postfixExpression_elementType?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.prefixExpression) {
+      prefixExpression_operand?.flushInformative();
+      prefixExpression_elementType?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+      prefixedIdentifier_identifier?.flushInformative();
+      prefixedIdentifier_prefix?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.propertyAccess) {
+      propertyAccess_propertyName?.flushInformative();
+      propertyAccess_target?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
+      redirectingConstructorInvocation_arguments?.flushInformative();
+      redirectingConstructorInvocation_constructorName?.flushInformative();
+      redirectingConstructorInvocation_elementType?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.rethrowExpression) {
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.returnStatement) {
+      returnStatement_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+      typedLiteral_typeArguments?.forEach((b) => b.flushInformative());
+      setOrMapLiteral_elements?.forEach((b) => b.flushInformative());
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.showCombinator) {
+    } else if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+      actualType?.flushInformative();
+      normalFormalParameter_metadata?.forEach((b) => b.flushInformative());
+      simpleFormalParameter_type?.flushInformative();
+      informativeId = null;
+      topLevelTypeInferenceError?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.simpleIdentifier) {
+      simpleIdentifier_elementType?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
+    } else if (kind == idl.LinkedNodeKind.spreadElement) {
+      spreadElement_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.stringInterpolation) {
+      stringInterpolation_elements?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
+      superConstructorInvocation_arguments?.flushInformative();
+      superConstructorInvocation_constructorName?.flushInformative();
+      superConstructorInvocation_elementType?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.superExpression) {
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.switchCase) {
+      switchMember_statements?.forEach((b) => b.flushInformative());
+      switchCase_expression?.flushInformative();
+      switchMember_labels?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.switchDefault) {
+      switchMember_statements?.forEach((b) => b.flushInformative());
+      switchMember_labels?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.switchStatement) {
+      switchStatement_members?.forEach((b) => b.flushInformative());
+      switchStatement_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.symbolLiteral) {
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.thisExpression) {
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.throwExpression) {
+      throwExpression_expression?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      topLevelVariableDeclaration_variableList?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.tryStatement) {
+      tryStatement_catchClauses?.forEach((b) => b.flushInformative());
+      tryStatement_body?.flushInformative();
+      tryStatement_finallyBlock?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.typeArgumentList) {
+      typeArgumentList_arguments?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.typeName) {
+      typeName_typeArguments?.forEach((b) => b.flushInformative());
+      typeName_name?.flushInformative();
+      typeName_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.typeParameter) {
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      typeParameter_bound?.flushInformative();
+      typeParameter_defaultType?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.typeParameterList) {
+      typeParameterList_typeParameters?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.variableDeclaration) {
+      actualType?.flushInformative();
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      variableDeclaration_initializer?.flushInformative();
+      informativeId = null;
+      topLevelTypeInferenceError?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+      variableDeclarationList_variables?.forEach((b) => b.flushInformative());
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      variableDeclarationList_type?.flushInformative();
+      informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
+      variableDeclarationStatement_variables?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.whileStatement) {
+      whileStatement_body?.flushInformative();
+      whileStatement_condition?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.withClause) {
+      withClause_mixinTypes?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.yieldStatement) {
+      yieldStatement_expression?.flushInformative();
+    }
   }
 
   /// Accumulate non-[informative] data into [signature].
   void collectApiSignature(api_sig.ApiSignature signature) {
-    signature.addInt(this._kind == null ? 0 : this._kind.index);
-    signature.addBool(this._isSynthetic == true);
-    if (this._variantField_2 == null) {
-      signature.addInt(0);
-    } else {
-      signature.addInt(this._variantField_2.length);
-      for (var x in this._variantField_2) {
-        x?.collectApiSignature(signature);
+    if (kind == idl.LinkedNodeKind.adjacentStrings) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.adjacentStrings_strings == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.adjacentStrings_strings.length);
+        for (var x in this.adjacentStrings_strings) {
+          x?.collectApiSignature(signature);
+        }
       }
-    }
-    if (this._variantField_3 == null) {
-      signature.addInt(0);
-    } else {
-      signature.addInt(this._variantField_3.length);
-      for (var x in this._variantField_3) {
-        x?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.annotation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.annotation_arguments != null);
+      this.annotation_arguments?.collectApiSignature(signature);
+      signature.addBool(this.annotation_constructorName != null);
+      this.annotation_constructorName?.collectApiSignature(signature);
+      signature.addBool(this.annotation_name != null);
+      this.annotation_name?.collectApiSignature(signature);
+      signature.addInt(this.annotation_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.annotation_elementType != null);
+      this.annotation_elementType?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.argumentList) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.argumentList_arguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.argumentList_arguments.length);
+        for (var x in this.argumentList_arguments) {
+          x?.collectApiSignature(signature);
+        }
       }
-    }
-    if (this._variantField_4 == null) {
-      signature.addInt(0);
-    } else {
-      signature.addInt(this._variantField_4.length);
-      for (var x in this._variantField_4) {
-        x?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.asExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.asExpression_expression != null);
+      this.asExpression_expression?.collectApiSignature(signature);
+      signature.addBool(this.asExpression_type != null);
+      this.asExpression_type?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.assertInitializer) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.assertInitializer_condition != null);
+      this.assertInitializer_condition?.collectApiSignature(signature);
+      signature.addBool(this.assertInitializer_message != null);
+      this.assertInitializer_message?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.assertStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.assertStatement_condition != null);
+      this.assertStatement_condition?.collectApiSignature(signature);
+      signature.addBool(this.assertStatement_message != null);
+      this.assertStatement_message?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.assignmentExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.assignmentExpression_leftHandSide != null);
+      this.assignmentExpression_leftHandSide?.collectApiSignature(signature);
+      signature.addBool(this.assignmentExpression_rightHandSide != null);
+      this.assignmentExpression_rightHandSide?.collectApiSignature(signature);
+      signature.addInt(this.assignmentExpression_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.assignmentExpression_elementType != null);
+      this.assignmentExpression_elementType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addInt(this.assignmentExpression_operator == null
+          ? 0
+          : this.assignmentExpression_operator.index);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.awaitExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.awaitExpression_expression != null);
+      this.awaitExpression_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.binaryExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.binaryExpression_leftOperand != null);
+      this.binaryExpression_leftOperand?.collectApiSignature(signature);
+      signature.addBool(this.binaryExpression_rightOperand != null);
+      this.binaryExpression_rightOperand?.collectApiSignature(signature);
+      signature.addInt(this.binaryExpression_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.binaryExpression_elementType != null);
+      this.binaryExpression_elementType?.collectApiSignature(signature);
+      signature.addBool(this.binaryExpression_invokeType != null);
+      this.binaryExpression_invokeType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addInt(this.binaryExpression_operator == null
+          ? 0
+          : this.binaryExpression_operator.index);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.block) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.block_statements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.block_statements.length);
+        for (var x in this.block_statements) {
+          x?.collectApiSignature(signature);
+        }
       }
-    }
-    if (this._variantField_5 == null) {
-      signature.addInt(0);
-    } else {
-      signature.addInt(this._variantField_5.length);
-      for (var x in this._variantField_5) {
-        x?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.blockFunctionBody) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.blockFunctionBody_block != null);
+      this.blockFunctionBody_block?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.booleanLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.booleanLiteral_value == true);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.breakStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.breakStatement_label != null);
+      this.breakStatement_label?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.cascadeExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.cascadeExpression_sections == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.cascadeExpression_sections.length);
+        for (var x in this.cascadeExpression_sections) {
+          x?.collectApiSignature(signature);
+        }
       }
-    }
-    signature.addBool(this._variantField_6 != null);
-    this._variantField_6?.collectApiSignature(signature);
-    signature.addBool(this._variantField_7 != null);
-    this._variantField_7?.collectApiSignature(signature);
-    signature.addBool(this._variantField_8 != null);
-    this._variantField_8?.collectApiSignature(signature);
-    signature.addBool(this._variantField_9 != null);
-    this._variantField_9?.collectApiSignature(signature);
-    signature.addBool(this._variantField_10 != null);
-    this._variantField_10?.collectApiSignature(signature);
-    signature.addBool(this._variantField_11 != null);
-    this._variantField_11?.collectApiSignature(signature);
-    signature.addBool(this._variantField_12 != null);
-    this._variantField_12?.collectApiSignature(signature);
-    signature.addBool(this._variantField_13 != null);
-    this._variantField_13?.collectApiSignature(signature);
-    signature.addBool(this._variantField_14 != null);
-    this._variantField_14?.collectApiSignature(signature);
-    signature.addInt(this._variantField_15 ?? 0);
-    signature.addInt(this._variantField_16 ?? 0);
-    signature.addInt(this._variantField_17 ?? 0);
-    signature.addInt(this._variantField_18 ?? 0);
-    signature.addInt(this._variantField_19 ?? 0);
-    signature.addString(this._variantField_20 ?? '');
-    signature.addDouble(this._variantField_21 ?? 0.0);
-    signature.addString(this._variantField_22 ?? '');
-    signature.addBool(this._variantField_23 != null);
-    this._variantField_23?.collectApiSignature(signature);
-    signature.addBool(this._variantField_24 != null);
-    this._variantField_24?.collectApiSignature(signature);
-    signature.addBool(this._variantField_25 != null);
-    this._variantField_25?.collectApiSignature(signature);
-    signature.addInt(
-        this._variantField_26 == null ? 0 : this._variantField_26.index);
-    signature.addBool(this._variantField_27 == true);
-    if (this._variantField_28 == null) {
-      signature.addInt(0);
-    } else {
-      signature.addInt(this._variantField_28.length);
-      for (var x in this._variantField_28) {
-        signature.addInt(x);
+      signature.addBool(this.cascadeExpression_target != null);
+      this.cascadeExpression_target?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.catchClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.catchClause_body != null);
+      this.catchClause_body?.collectApiSignature(signature);
+      signature.addBool(this.catchClause_exceptionParameter != null);
+      this.catchClause_exceptionParameter?.collectApiSignature(signature);
+      signature.addBool(this.catchClause_exceptionType != null);
+      this.catchClause_exceptionType?.collectApiSignature(signature);
+      signature.addBool(this.catchClause_stackTraceParameter != null);
+      this.catchClause_stackTraceParameter?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.classDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
       }
+      if (this.classOrMixinDeclaration_members == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.classOrMixinDeclaration_members.length);
+        for (var x in this.classOrMixinDeclaration_members) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.classDeclaration_extendsClause != null);
+      this.classDeclaration_extendsClause?.collectApiSignature(signature);
+      signature.addBool(this.classDeclaration_withClause != null);
+      this.classDeclaration_withClause?.collectApiSignature(signature);
+      signature.addBool(this.classDeclaration_nativeClause != null);
+      this.classDeclaration_nativeClause?.collectApiSignature(signature);
+      signature.addBool(this.unused11 != null);
+      this.unused11?.collectApiSignature(signature);
+      signature.addBool(this.classOrMixinDeclaration_implementsClause != null);
+      this
+          .classOrMixinDeclaration_implementsClause
+          ?.collectApiSignature(signature);
+      signature.addBool(this.classOrMixinDeclaration_typeParameters != null);
+      this
+          .classOrMixinDeclaration_typeParameters
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.classDeclaration_isDartObject == true);
+      signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.classTypeAlias) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.classTypeAlias_typeParameters != null);
+      this.classTypeAlias_typeParameters?.collectApiSignature(signature);
+      signature.addBool(this.classTypeAlias_superclass != null);
+      this.classTypeAlias_superclass?.collectApiSignature(signature);
+      signature.addBool(this.classTypeAlias_withClause != null);
+      this.classTypeAlias_withClause?.collectApiSignature(signature);
+      signature.addBool(this.classTypeAlias_implementsClause != null);
+      this.classTypeAlias_implementsClause?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.comment) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.comment_references == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.comment_references.length);
+        for (var x in this.comment_references) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.comment_type == null ? 0 : this.comment_type.index);
+      if (this.comment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.comment_tokens.length);
+        for (var x in this.comment_tokens) {
+          signature.addString(x);
+        }
+      }
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.commentReference) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.commentReference_identifier != null);
+      this.commentReference_identifier?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.compilationUnit) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.compilationUnit_declarations == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.compilationUnit_declarations.length);
+        for (var x in this.compilationUnit_declarations) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.compilationUnit_directives == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.compilationUnit_directives.length);
+        for (var x in this.compilationUnit_directives) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.compilationUnit_scriptTag != null);
+      this.compilationUnit_scriptTag?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.conditionalExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.conditionalExpression_condition != null);
+      this.conditionalExpression_condition?.collectApiSignature(signature);
+      signature.addBool(this.conditionalExpression_elseExpression != null);
+      this.conditionalExpression_elseExpression?.collectApiSignature(signature);
+      signature.addBool(this.conditionalExpression_thenExpression != null);
+      this.conditionalExpression_thenExpression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.configuration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.configuration_name != null);
+      this.configuration_name?.collectApiSignature(signature);
+      signature.addBool(this.configuration_value != null);
+      this.configuration_value?.collectApiSignature(signature);
+      signature.addBool(this.configuration_uri != null);
+      this.configuration_uri?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.constructorDeclaration_initializers == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.constructorDeclaration_initializers.length);
+        for (var x in this.constructorDeclaration_initializers) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.constructorDeclaration_body != null);
+      this.constructorDeclaration_body?.collectApiSignature(signature);
+      signature.addBool(this.constructorDeclaration_parameters != null);
+      this.constructorDeclaration_parameters?.collectApiSignature(signature);
+      signature
+          .addBool(this.constructorDeclaration_redirectedConstructor != null);
+      this
+          .constructorDeclaration_redirectedConstructor
+          ?.collectApiSignature(signature);
+      signature.addBool(this.constructorDeclaration_returnType != null);
+      this.constructorDeclaration_returnType?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.constructorFieldInitializer_expression != null);
+      this
+          .constructorFieldInitializer_expression
+          ?.collectApiSignature(signature);
+      signature.addBool(this.constructorFieldInitializer_fieldName != null);
+      this
+          .constructorFieldInitializer_fieldName
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.constructorName) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.constructorName_name != null);
+      this.constructorName_name?.collectApiSignature(signature);
+      signature.addBool(this.constructorName_type != null);
+      this.constructorName_type?.collectApiSignature(signature);
+      signature.addInt(this.constructorName_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.constructorName_elementType != null);
+      this.constructorName_elementType?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.continueStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.continueStatement_label != null);
+      this.continueStatement_label?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.declaredIdentifier) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.declaredIdentifier_identifier != null);
+      this.declaredIdentifier_identifier?.collectApiSignature(signature);
+      signature.addBool(this.declaredIdentifier_type != null);
+      this.declaredIdentifier_type?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.defaultFormalParameter_defaultValue != null);
+      this.defaultFormalParameter_defaultValue?.collectApiSignature(signature);
+      signature.addBool(this.defaultFormalParameter_parameter != null);
+      this.defaultFormalParameter_parameter?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.defaultFormalParameter_kind == null
+          ? 0
+          : this.defaultFormalParameter_kind.index);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.doStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.doStatement_body != null);
+      this.doStatement_body?.collectApiSignature(signature);
+      signature.addBool(this.doStatement_condition != null);
+      this.doStatement_condition?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.dottedName) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.dottedName_components == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.dottedName_components.length);
+        for (var x in this.dottedName_components) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.doubleLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addDouble(this.doubleLiteral_value ?? 0.0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.emptyFunctionBody_fake ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.emptyStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.emptyStatement_fake ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.enumDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.enumDeclaration_constants == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.enumDeclaration_constants.length);
+        for (var x in this.enumDeclaration_constants) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.exportDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.namespaceDirective_combinators == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.namespaceDirective_combinators.length);
+        for (var x in this.namespaceDirective_combinators) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.namespaceDirective_configurations == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.namespaceDirective_configurations.length);
+        for (var x in this.namespaceDirective_configurations) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.uriBasedDirective_uri != null);
+      this.uriBasedDirective_uri?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.uriBasedDirective_uriElement ?? 0);
+      signature.addString(this.namespaceDirective_selectedUri ?? '');
+      signature.addString(this.uriBasedDirective_uriContent ?? '');
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.expressionFunctionBody_expression != null);
+      this.expressionFunctionBody_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.expressionStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.expressionStatement_expression != null);
+      this.expressionStatement_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.extendsClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.extendsClause_superclass != null);
+      this.extendsClause_superclass?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.fieldDeclaration_fields != null);
+      this.fieldDeclaration_fields?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.normalFormalParameter_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.normalFormalParameter_metadata.length);
+        for (var x in this.normalFormalParameter_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.fieldFormalParameter_type != null);
+      this.fieldFormalParameter_type?.collectApiSignature(signature);
+      signature.addBool(this.fieldFormalParameter_typeParameters != null);
+      this.fieldFormalParameter_typeParameters?.collectApiSignature(signature);
+      signature.addBool(this.fieldFormalParameter_formalParameters != null);
+      this
+          .fieldFormalParameter_formalParameters
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualType != null);
+      this.actualType?.collectApiSignature(signature);
+      signature.addBool(this.inheritsCovariant == true);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.forEachParts_iterable != null);
+      this.forEachParts_iterable?.collectApiSignature(signature);
+      signature.addBool(this.forEachPartsWithDeclaration_loopVariable != null);
+      this
+          .forEachPartsWithDeclaration_loopVariable
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.forEachParts_iterable != null);
+      this.forEachParts_iterable?.collectApiSignature(signature);
+      signature.addBool(this.forEachPartsWithIdentifier_identifier != null);
+      this
+          .forEachPartsWithIdentifier_identifier
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.forElement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.forMixin_forLoopParts != null);
+      this.forMixin_forLoopParts?.collectApiSignature(signature);
+      signature.addBool(this.forElement_body != null);
+      this.forElement_body?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.forParts_updaters == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.forParts_updaters.length);
+        for (var x in this.forParts_updaters) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.forParts_condition != null);
+      this.forParts_condition?.collectApiSignature(signature);
+      signature.addBool(this.forPartsWithDeclarations_variables != null);
+      this.forPartsWithDeclarations_variables?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.forParts_updaters == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.forParts_updaters.length);
+        for (var x in this.forParts_updaters) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.forParts_condition != null);
+      this.forParts_condition?.collectApiSignature(signature);
+      signature.addBool(this.forPartsWithExpression_initialization != null);
+      this
+          .forPartsWithExpression_initialization
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.forStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.forMixin_forLoopParts != null);
+      this.forMixin_forLoopParts?.collectApiSignature(signature);
+      signature.addBool(this.forStatement_body != null);
+      this.forStatement_body?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.formalParameterList) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.formalParameterList_parameters == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.formalParameterList_parameters.length);
+        for (var x in this.formalParameterList_parameters) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.functionDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.functionDeclaration_functionExpression != null);
+      this
+          .functionDeclaration_functionExpression
+          ?.collectApiSignature(signature);
+      signature.addBool(this.functionDeclaration_returnType != null);
+      this.functionDeclaration_returnType?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualReturnType != null);
+      this.actualReturnType?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(
+          this.functionDeclarationStatement_functionDeclaration != null);
+      this
+          .functionDeclarationStatement_functionDeclaration
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.functionExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.functionExpression_body != null);
+      this.functionExpression_body?.collectApiSignature(signature);
+      signature.addBool(this.functionExpression_formalParameters != null);
+      this.functionExpression_formalParameters?.collectApiSignature(signature);
+      signature.addBool(this.functionExpression_typeParameters != null);
+      this.functionExpression_typeParameters?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualReturnType != null);
+      this.actualReturnType?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.functionExpressionInvocation_function != null);
+      this
+          .functionExpressionInvocation_function
+          ?.collectApiSignature(signature);
+      signature.addBool(this.invocationExpression_typeArguments != null);
+      this.invocationExpression_typeArguments?.collectApiSignature(signature);
+      signature.addBool(this.invocationExpression_arguments != null);
+      this.invocationExpression_arguments?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.invocationExpression_invokeType != null);
+      this.invocationExpression_invokeType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.functionTypeAlias_formalParameters != null);
+      this.functionTypeAlias_formalParameters?.collectApiSignature(signature);
+      signature.addBool(this.functionTypeAlias_returnType != null);
+      this.functionTypeAlias_returnType?.collectApiSignature(signature);
+      signature.addBool(this.functionTypeAlias_typeParameters != null);
+      this.functionTypeAlias_typeParameters?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualReturnType != null);
+      this.actualReturnType?.collectApiSignature(signature);
+      signature.addBool(this.typeAlias_hasSelfReference == true);
+      signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.normalFormalParameter_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.normalFormalParameter_metadata.length);
+        for (var x in this.normalFormalParameter_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature
+          .addBool(this.functionTypedFormalParameter_formalParameters != null);
+      this
+          .functionTypedFormalParameter_formalParameters
+          ?.collectApiSignature(signature);
+      signature.addBool(this.functionTypedFormalParameter_returnType != null);
+      this
+          .functionTypedFormalParameter_returnType
+          ?.collectApiSignature(signature);
+      signature
+          .addBool(this.functionTypedFormalParameter_typeParameters != null);
+      this
+          .functionTypedFormalParameter_typeParameters
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualType != null);
+      this.actualType?.collectApiSignature(signature);
+      signature.addBool(this.inheritsCovariant == true);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.genericFunctionType) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.genericFunctionType_typeParameters != null);
+      this.genericFunctionType_typeParameters?.collectApiSignature(signature);
+      signature.addBool(this.genericFunctionType_returnType != null);
+      this.genericFunctionType_returnType?.collectApiSignature(signature);
+      signature.addBool(this.genericFunctionType_formalParameters != null);
+      this.genericFunctionType_formalParameters?.collectApiSignature(signature);
+      signature.addInt(this.genericFunctionType_id ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualReturnType != null);
+      this.actualReturnType?.collectApiSignature(signature);
+      signature.addBool(this.genericFunctionType_type != null);
+      this.genericFunctionType_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.genericTypeAlias_typeParameters != null);
+      this.genericTypeAlias_typeParameters?.collectApiSignature(signature);
+      signature.addBool(this.genericTypeAlias_functionType != null);
+      this.genericTypeAlias_functionType?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.typeAlias_hasSelfReference == true);
+      signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.hideCombinator) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      if (this.names == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.names.length);
+        for (var x in this.names) {
+          signature.addString(x);
+        }
+      }
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.ifElement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.ifMixin_condition != null);
+      this.ifMixin_condition?.collectApiSignature(signature);
+      signature.addBool(this.ifElement_thenElement != null);
+      this.ifElement_thenElement?.collectApiSignature(signature);
+      signature.addBool(this.ifElement_elseElement != null);
+      this.ifElement_elseElement?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.ifStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.ifMixin_condition != null);
+      this.ifMixin_condition?.collectApiSignature(signature);
+      signature.addBool(this.ifStatement_elseStatement != null);
+      this.ifStatement_elseStatement?.collectApiSignature(signature);
+      signature.addBool(this.ifStatement_thenStatement != null);
+      this.ifStatement_thenStatement?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.implementsClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.implementsClause_interfaces == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.implementsClause_interfaces.length);
+        for (var x in this.implementsClause_interfaces) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.importDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addString(this.importDirective_prefix ?? '');
+      if (this.namespaceDirective_combinators == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.namespaceDirective_combinators.length);
+        for (var x in this.namespaceDirective_combinators) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.namespaceDirective_configurations == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.namespaceDirective_configurations.length);
+        for (var x in this.namespaceDirective_configurations) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.uriBasedDirective_uri != null);
+      this.uriBasedDirective_uri?.collectApiSignature(signature);
+      signature.addInt(this.importDirective_prefixOffset ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.uriBasedDirective_uriElement ?? 0);
+      signature.addString(this.namespaceDirective_selectedUri ?? '');
+      signature.addString(this.uriBasedDirective_uriContent ?? '');
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.indexExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.indexExpression_index != null);
+      this.indexExpression_index?.collectApiSignature(signature);
+      signature.addBool(this.indexExpression_target != null);
+      this.indexExpression_target?.collectApiSignature(signature);
+      signature.addInt(this.indexExpression_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.indexExpression_elementType != null);
+      this.indexExpression_elementType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.instanceCreationExpression_arguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.instanceCreationExpression_arguments.length);
+        for (var x in this.instanceCreationExpression_arguments) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature
+          .addBool(this.instanceCreationExpression_constructorName != null);
+      this
+          .instanceCreationExpression_constructorName
+          ?.collectApiSignature(signature);
+      signature.addBool(this.instanceCreationExpression_typeArguments != null);
+      this
+          .instanceCreationExpression_typeArguments
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.integerLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.integerLiteral_value ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.interpolationExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.interpolationExpression_expression != null);
+      this.interpolationExpression_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.interpolationString) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.interpolationString_value ?? '');
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.isExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.isExpression_expression != null);
+      this.isExpression_expression?.collectApiSignature(signature);
+      signature.addBool(this.isExpression_type != null);
+      this.isExpression_type?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.label) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.label_label != null);
+      this.label_label?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.labeledStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.labeledStatement_labels == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.labeledStatement_labels.length);
+        for (var x in this.labeledStatement_labels) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.labeledStatement_statement != null);
+      this.labeledStatement_statement?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.libraryDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.libraryDirective_name != null);
+      this.libraryDirective_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.libraryIdentifier_components == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.libraryIdentifier_components.length);
+        for (var x in this.libraryIdentifier_components) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.listLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.typedLiteral_typeArguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.typedLiteral_typeArguments.length);
+        for (var x in this.typedLiteral_typeArguments) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.listLiteral_elements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.listLiteral_elements.length);
+        for (var x in this.listLiteral_elements) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.mapLiteralEntry_key != null);
+      this.mapLiteralEntry_key?.collectApiSignature(signature);
+      signature.addBool(this.mapLiteralEntry_value != null);
+      this.mapLiteralEntry_value?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.methodDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.methodDeclaration_body != null);
+      this.methodDeclaration_body?.collectApiSignature(signature);
+      signature.addBool(this.methodDeclaration_formalParameters != null);
+      this.methodDeclaration_formalParameters?.collectApiSignature(signature);
+      signature.addBool(this.methodDeclaration_returnType != null);
+      this.methodDeclaration_returnType?.collectApiSignature(signature);
+      signature.addBool(this.methodDeclaration_typeParameters != null);
+      this.methodDeclaration_typeParameters?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualReturnType != null);
+      this.actualReturnType?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.methodInvocation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.methodInvocation_methodName != null);
+      this.methodInvocation_methodName?.collectApiSignature(signature);
+      signature.addBool(this.methodInvocation_target != null);
+      this.methodInvocation_target?.collectApiSignature(signature);
+      signature.addBool(this.invocationExpression_typeArguments != null);
+      this.invocationExpression_typeArguments?.collectApiSignature(signature);
+      signature.addBool(this.invocationExpression_arguments != null);
+      this.invocationExpression_arguments?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.invocationExpression_invokeType != null);
+      this.invocationExpression_invokeType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.classOrMixinDeclaration_members == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.classOrMixinDeclaration_members.length);
+        for (var x in this.classOrMixinDeclaration_members) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.mixinDeclaration_onClause != null);
+      this.mixinDeclaration_onClause?.collectApiSignature(signature);
+      signature.addBool(this.classOrMixinDeclaration_implementsClause != null);
+      this
+          .classOrMixinDeclaration_implementsClause
+          ?.collectApiSignature(signature);
+      signature.addBool(this.classOrMixinDeclaration_typeParameters != null);
+      this
+          .classOrMixinDeclaration_typeParameters
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+      if (this.mixinDeclaration_superInvokedNames == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.mixinDeclaration_superInvokedNames.length);
+        for (var x in this.mixinDeclaration_superInvokedNames) {
+          signature.addString(x);
+        }
+      }
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.namedExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.namedExpression_expression != null);
+      this.namedExpression_expression?.collectApiSignature(signature);
+      signature.addBool(this.namedExpression_name != null);
+      this.namedExpression_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.nativeClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.nativeClause_name != null);
+      this.nativeClause_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.nativeFunctionBody_stringLiteral != null);
+      this.nativeFunctionBody_stringLiteral?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.nullLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nullLiteral_fake ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.onClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.onClause_superclassConstraints == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.onClause_superclassConstraints.length);
+        for (var x in this.onClause_superclassConstraints) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.parenthesizedExpression_expression != null);
+      this.parenthesizedExpression_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.partDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.uriBasedDirective_uri != null);
+      this.uriBasedDirective_uri?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.uriBasedDirective_uriElement ?? 0);
+      signature.addString(this.uriBasedDirective_uriContent ?? '');
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.partOfDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.partOfDirective_libraryName != null);
+      this.partOfDirective_libraryName?.collectApiSignature(signature);
+      signature.addBool(this.partOfDirective_uri != null);
+      this.partOfDirective_uri?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.postfixExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.postfixExpression_operand != null);
+      this.postfixExpression_operand?.collectApiSignature(signature);
+      signature.addInt(this.postfixExpression_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.postfixExpression_elementType != null);
+      this.postfixExpression_elementType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addInt(this.postfixExpression_operator == null
+          ? 0
+          : this.postfixExpression_operator.index);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.prefixExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.prefixExpression_operand != null);
+      this.prefixExpression_operand?.collectApiSignature(signature);
+      signature.addInt(this.prefixExpression_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.prefixExpression_elementType != null);
+      this.prefixExpression_elementType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addInt(this.prefixExpression_operator == null
+          ? 0
+          : this.prefixExpression_operator.index);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.prefixedIdentifier_identifier != null);
+      this.prefixedIdentifier_identifier?.collectApiSignature(signature);
+      signature.addBool(this.prefixedIdentifier_prefix != null);
+      this.prefixedIdentifier_prefix?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.propertyAccess) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.propertyAccess_propertyName != null);
+      this.propertyAccess_propertyName?.collectApiSignature(signature);
+      signature.addBool(this.propertyAccess_target != null);
+      this.propertyAccess_target?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addInt(this.propertyAccess_operator == null
+          ? 0
+          : this.propertyAccess_operator.index);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature
+          .addBool(this.redirectingConstructorInvocation_arguments != null);
+      this
+          .redirectingConstructorInvocation_arguments
+          ?.collectApiSignature(signature);
+      signature.addBool(
+          this.redirectingConstructorInvocation_constructorName != null);
+      this
+          .redirectingConstructorInvocation_constructorName
+          ?.collectApiSignature(signature);
+      signature.addInt(this.redirectingConstructorInvocation_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature
+          .addBool(this.redirectingConstructorInvocation_elementType != null);
+      this
+          .redirectingConstructorInvocation_elementType
+          ?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.rethrowExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.returnStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.returnStatement_expression != null);
+      this.returnStatement_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.typedLiteral_typeArguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.typedLiteral_typeArguments.length);
+        for (var x in this.typedLiteral_typeArguments) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.setOrMapLiteral_elements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.setOrMapLiteral_elements.length);
+        for (var x in this.setOrMapLiteral_elements) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.showCombinator) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      if (this.names == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.names.length);
+        for (var x in this.names) {
+          signature.addString(x);
+        }
+      }
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.normalFormalParameter_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.normalFormalParameter_metadata.length);
+        for (var x in this.normalFormalParameter_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.simpleFormalParameter_type != null);
+      this.simpleFormalParameter_type?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualType != null);
+      this.actualType?.collectApiSignature(signature);
+      signature.addBool(this.inheritsCovariant == true);
+      signature.addBool(this.topLevelTypeInferenceError != null);
+      this.topLevelTypeInferenceError?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.simpleIdentifier) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.simpleIdentifier_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.simpleIdentifier_elementType != null);
+      this.simpleIdentifier_elementType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.simpleStringLiteral_value ?? '');
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.spreadElement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.spreadElement_expression != null);
+      this.spreadElement_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.spreadElement_spreadOperator == null
+          ? 0
+          : this.spreadElement_spreadOperator.index);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.stringInterpolation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.stringInterpolation_elements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.stringInterpolation_elements.length);
+        for (var x in this.stringInterpolation_elements) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.superConstructorInvocation_arguments != null);
+      this.superConstructorInvocation_arguments?.collectApiSignature(signature);
+      signature
+          .addBool(this.superConstructorInvocation_constructorName != null);
+      this
+          .superConstructorInvocation_constructorName
+          ?.collectApiSignature(signature);
+      signature.addInt(this.superConstructorInvocation_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.superConstructorInvocation_elementType != null);
+      this
+          .superConstructorInvocation_elementType
+          ?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.superExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.switchCase) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.switchMember_labels == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.switchMember_labels.length);
+        for (var x in this.switchMember_labels) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.switchMember_statements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.switchMember_statements.length);
+        for (var x in this.switchMember_statements) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.switchCase_expression != null);
+      this.switchCase_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.switchDefault) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.switchMember_labels == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.switchMember_labels.length);
+        for (var x in this.switchMember_labels) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.switchMember_statements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.switchMember_statements.length);
+        for (var x in this.switchMember_statements) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.switchStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.switchStatement_members == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.switchStatement_members.length);
+        for (var x in this.switchStatement_members) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.switchStatement_expression != null);
+      this.switchStatement_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.symbolLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      if (this.names == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.names.length);
+        for (var x in this.names) {
+          signature.addString(x);
+        }
+      }
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.thisExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.throwExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.throwExpression_expression != null);
+      this.throwExpression_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.topLevelVariableDeclaration_variableList != null);
+      this
+          .topLevelVariableDeclaration_variableList
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.tryStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.tryStatement_catchClauses == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.tryStatement_catchClauses.length);
+        for (var x in this.tryStatement_catchClauses) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.tryStatement_body != null);
+      this.tryStatement_body?.collectApiSignature(signature);
+      signature.addBool(this.tryStatement_finallyBlock != null);
+      this.tryStatement_finallyBlock?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.typeArgumentList) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.typeArgumentList_arguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.typeArgumentList_arguments.length);
+        for (var x in this.typeArgumentList_arguments) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.typeName) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.typeName_typeArguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.typeName_typeArguments.length);
+        for (var x in this.typeName_typeArguments) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.typeName_name != null);
+      this.typeName_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.typeName_type != null);
+      this.typeName_type?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.typeParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.typeParameter_bound != null);
+      this.typeParameter_bound?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.typeParameter_defaultType != null);
+      this.typeParameter_defaultType?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.typeParameterList) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.typeParameterList_typeParameters == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.typeParameterList_typeParameters.length);
+        for (var x in this.typeParameterList_typeParameters) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.variableDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.variableDeclaration_initializer != null);
+      this.variableDeclaration_initializer?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualType != null);
+      this.actualType?.collectApiSignature(signature);
+      signature.addBool(this.inheritsCovariant == true);
+      signature.addBool(this.topLevelTypeInferenceError != null);
+      this.topLevelTypeInferenceError?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.variableDeclarationList_variables == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.variableDeclarationList_variables.length);
+        for (var x in this.variableDeclarationList_variables) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.variableDeclarationList_type != null);
+      this.variableDeclarationList_type?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.variableDeclarationStatement_variables != null);
+      this
+          .variableDeclarationStatement_variables
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.whileStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.whileStatement_body != null);
+      this.whileStatement_body?.collectApiSignature(signature);
+      signature.addBool(this.whileStatement_condition != null);
+      this.whileStatement_condition?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.withClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.withClause_mixinTypes == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.withClause_mixinTypes.length);
+        for (var x in this.withClause_mixinTypes) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.yieldStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.yieldStatement_expression != null);
+      this.yieldStatement_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.name ?? '');
     }
-    signature.addInt(
-        this._variantField_29 == null ? 0 : this._variantField_29.index);
-    signature.addString(this._variantField_30 ?? '');
-    signature.addBool(this._variantField_31 == true);
-    signature.addBool(this._variantField_32 != null);
-    this._variantField_32?.collectApiSignature(signature);
-    signature.addInt(this._variantField_33 ?? 0);
-    signature.addInt(this._variantField_34 ?? 0);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
     fb.Offset offset_variantField_24;
     fb.Offset offset_variantField_2;
-    fb.Offset offset_variantField_11;
     fb.Offset offset_variantField_4;
     fb.Offset offset_variantField_6;
     fb.Offset offset_variantField_7;
-    fb.Offset offset_variantField_8;
     fb.Offset offset_variantField_23;
+    fb.Offset offset_variantField_8;
     fb.Offset offset_variantField_9;
     fb.Offset offset_variantField_12;
     fb.Offset offset_variantField_5;
     fb.Offset offset_variantField_13;
-    fb.Offset offset_variantField_28;
+    fb.Offset offset_variantField_33;
     fb.Offset offset_variantField_3;
     fb.Offset offset_variantField_10;
     fb.Offset offset_variantField_25;
+    fb.Offset offset_variantField_1;
     fb.Offset offset_variantField_30;
     fb.Offset offset_variantField_14;
+    fb.Offset offset_variantField_34;
+    fb.Offset offset_name;
     fb.Offset offset_variantField_20;
-    fb.Offset offset_variantField_22;
     fb.Offset offset_variantField_32;
+    fb.Offset offset_variantField_11;
+    fb.Offset offset_variantField_22;
     if (_variantField_24 != null) {
       offset_variantField_24 = _variantField_24.finish(fbBuilder);
     }
@@ -11640,9 +10788,6 @@
       offset_variantField_2 = fbBuilder
           .writeList(_variantField_2.map((b) => b.finish(fbBuilder)).toList());
     }
-    if (_variantField_11 != null) {
-      offset_variantField_11 = _variantField_11.finish(fbBuilder);
-    }
     if (!(_variantField_4 == null || _variantField_4.isEmpty)) {
       offset_variantField_4 = fbBuilder
           .writeList(_variantField_4.map((b) => b.finish(fbBuilder)).toList());
@@ -11653,12 +10798,12 @@
     if (_variantField_7 != null) {
       offset_variantField_7 = _variantField_7.finish(fbBuilder);
     }
-    if (_variantField_8 != null) {
-      offset_variantField_8 = _variantField_8.finish(fbBuilder);
-    }
     if (_variantField_23 != null) {
       offset_variantField_23 = _variantField_23.finish(fbBuilder);
     }
+    if (_variantField_8 != null) {
+      offset_variantField_8 = _variantField_8.finish(fbBuilder);
+    }
     if (_variantField_9 != null) {
       offset_variantField_9 = _variantField_9.finish(fbBuilder);
     }
@@ -11672,8 +10817,9 @@
     if (_variantField_13 != null) {
       offset_variantField_13 = _variantField_13.finish(fbBuilder);
     }
-    if (!(_variantField_28 == null || _variantField_28.isEmpty)) {
-      offset_variantField_28 = fbBuilder.writeListUint32(_variantField_28);
+    if (!(_variantField_33 == null || _variantField_33.isEmpty)) {
+      offset_variantField_33 = fbBuilder.writeList(
+          _variantField_33.map((b) => fbBuilder.writeString(b)).toList());
     }
     if (!(_variantField_3 == null || _variantField_3.isEmpty)) {
       offset_variantField_3 = fbBuilder
@@ -11685,21 +10831,34 @@
     if (_variantField_25 != null) {
       offset_variantField_25 = _variantField_25.finish(fbBuilder);
     }
+    if (_variantField_1 != null) {
+      offset_variantField_1 = fbBuilder.writeString(_variantField_1);
+    }
     if (_variantField_30 != null) {
       offset_variantField_30 = fbBuilder.writeString(_variantField_30);
     }
     if (_variantField_14 != null) {
       offset_variantField_14 = _variantField_14.finish(fbBuilder);
     }
+    if (!(_variantField_34 == null || _variantField_34.isEmpty)) {
+      offset_variantField_34 = fbBuilder.writeList(
+          _variantField_34.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    if (_name != null) {
+      offset_name = fbBuilder.writeString(_name);
+    }
     if (_variantField_20 != null) {
       offset_variantField_20 = fbBuilder.writeString(_variantField_20);
     }
-    if (_variantField_22 != null) {
-      offset_variantField_22 = fbBuilder.writeString(_variantField_22);
-    }
     if (_variantField_32 != null) {
       offset_variantField_32 = _variantField_32.finish(fbBuilder);
     }
+    if (_variantField_11 != null) {
+      offset_variantField_11 = _variantField_11.finish(fbBuilder);
+    }
+    if (_variantField_22 != null) {
+      offset_variantField_22 = fbBuilder.writeString(_variantField_22);
+    }
     fbBuilder.startTable();
     if (offset_variantField_24 != null) {
       fbBuilder.addOffset(24, offset_variantField_24);
@@ -11707,39 +10866,31 @@
     if (offset_variantField_2 != null) {
       fbBuilder.addOffset(2, offset_variantField_2);
     }
-    if (offset_variantField_11 != null) {
-      fbBuilder.addOffset(11, offset_variantField_11);
-    }
     if (offset_variantField_4 != null) {
       fbBuilder.addOffset(4, offset_variantField_4);
     }
     if (offset_variantField_6 != null) {
       fbBuilder.addOffset(6, offset_variantField_6);
     }
-    if (_variantField_15 != null && _variantField_15 != 0) {
-      fbBuilder.addUint32(15, _variantField_15);
-    }
     if (offset_variantField_7 != null) {
       fbBuilder.addOffset(7, offset_variantField_7);
     }
-    if (offset_variantField_8 != null) {
-      fbBuilder.addOffset(8, offset_variantField_8);
-    }
-    if (_variantField_16 != null && _variantField_16 != 0) {
-      fbBuilder.addUint32(16, _variantField_16);
-    }
     if (_variantField_17 != null && _variantField_17 != 0) {
       fbBuilder.addUint32(17, _variantField_17);
     }
-    if (_variantField_18 != null && _variantField_18 != 0) {
-      fbBuilder.addUint32(18, _variantField_18);
-    }
-    if (_variantField_19 != null && _variantField_19 != 0) {
-      fbBuilder.addUint32(19, _variantField_19);
-    }
     if (offset_variantField_23 != null) {
       fbBuilder.addOffset(23, offset_variantField_23);
     }
+    if (offset_variantField_8 != null) {
+      fbBuilder.addOffset(8, offset_variantField_8);
+    }
+    if (_variantField_15 != null && _variantField_15 != 0) {
+      fbBuilder.addUint32(15, _variantField_15);
+    }
+    if (_variantField_28 != null &&
+        _variantField_28 != idl.UnlinkedTokenType.NOTHING) {
+      fbBuilder.addUint8(28, _variantField_28.index);
+    }
     if (_variantField_27 == true) {
       fbBuilder.addBool(27, true);
     }
@@ -11755,14 +10906,8 @@
     if (offset_variantField_13 != null) {
       fbBuilder.addOffset(13, offset_variantField_13);
     }
-    if (_variantField_34 != null && _variantField_34 != 0) {
-      fbBuilder.addUint32(34, _variantField_34);
-    }
-    if (_variantField_33 != null && _variantField_33 != 0) {
-      fbBuilder.addUint32(33, _variantField_33);
-    }
-    if (offset_variantField_28 != null) {
-      fbBuilder.addOffset(28, offset_variantField_28);
+    if (offset_variantField_33 != null) {
+      fbBuilder.addOffset(33, offset_variantField_33);
     }
     if (_variantField_29 != null &&
         _variantField_29 != idl.LinkedNodeCommentType.block) {
@@ -11774,15 +10919,28 @@
     if (offset_variantField_10 != null) {
       fbBuilder.addOffset(10, offset_variantField_10);
     }
+    if (_variantField_26 != null &&
+        _variantField_26 !=
+            idl.LinkedNodeFormalParameterKind.requiredPositional) {
+      fbBuilder.addUint8(26, _variantField_26.index);
+    }
     if (_variantField_21 != null && _variantField_21 != 0.0) {
       fbBuilder.addFloat64(21, _variantField_21);
     }
     if (offset_variantField_25 != null) {
       fbBuilder.addOffset(25, offset_variantField_25);
     }
-    if (_variantField_26 != null &&
-        _variantField_26 != idl.LinkedNodeFormalParameterKind.required) {
-      fbBuilder.addUint8(26, _variantField_26.index);
+    if (_flags != null && _flags != 0) {
+      fbBuilder.addUint32(18, _flags);
+    }
+    if (offset_variantField_1 != null) {
+      fbBuilder.addOffset(1, offset_variantField_1);
+    }
+    if (_variantField_36 != null && _variantField_36 != 0) {
+      fbBuilder.addUint32(36, _variantField_36);
+    }
+    if (_variantField_16 != null && _variantField_16 != 0) {
+      fbBuilder.addUint32(16, _variantField_16);
     }
     if (offset_variantField_30 != null) {
       fbBuilder.addOffset(30, offset_variantField_30);
@@ -11790,24 +10948,37 @@
     if (offset_variantField_14 != null) {
       fbBuilder.addOffset(14, offset_variantField_14);
     }
-    if (_isSynthetic == true) {
-      fbBuilder.addBool(1, true);
-    }
     if (_kind != null && _kind != idl.LinkedNodeKind.adjacentStrings) {
       fbBuilder.addUint8(0, _kind.index);
     }
+    if (offset_variantField_34 != null) {
+      fbBuilder.addOffset(34, offset_variantField_34);
+    }
+    if (offset_name != null) {
+      fbBuilder.addOffset(37, offset_name);
+    }
     if (offset_variantField_20 != null) {
       fbBuilder.addOffset(20, offset_variantField_20);
     }
     if (_variantField_31 == true) {
       fbBuilder.addBool(31, true);
     }
-    if (offset_variantField_22 != null) {
-      fbBuilder.addOffset(22, offset_variantField_22);
+    if (_variantField_35 != null &&
+        _variantField_35 != idl.UnlinkedTokenType.NOTHING) {
+      fbBuilder.addUint8(35, _variantField_35.index);
     }
     if (offset_variantField_32 != null) {
       fbBuilder.addOffset(32, offset_variantField_32);
     }
+    if (offset_variantField_11 != null) {
+      fbBuilder.addOffset(11, offset_variantField_11);
+    }
+    if (offset_variantField_22 != null) {
+      fbBuilder.addOffset(22, offset_variantField_22);
+    }
+    if (_variantField_19 != null && _variantField_19 != 0) {
+      fbBuilder.addUint32(19, _variantField_19);
+    }
     return fbBuilder.endTable();
   }
 }
@@ -11830,39 +11001,42 @@
 
   idl.LinkedNodeType _variantField_24;
   List<idl.LinkedNode> _variantField_2;
-  idl.LinkedNode _variantField_11;
   List<idl.LinkedNode> _variantField_4;
   idl.LinkedNode _variantField_6;
-  int _variantField_15;
   idl.LinkedNode _variantField_7;
-  idl.LinkedNode _variantField_8;
-  int _variantField_16;
   int _variantField_17;
-  int _variantField_18;
-  int _variantField_19;
   idl.LinkedNodeType _variantField_23;
+  idl.LinkedNode _variantField_8;
+  int _variantField_15;
+  idl.UnlinkedTokenType _variantField_28;
   bool _variantField_27;
   idl.LinkedNode _variantField_9;
   idl.LinkedNode _variantField_12;
   List<idl.LinkedNode> _variantField_5;
   idl.LinkedNode _variantField_13;
-  int _variantField_34;
-  int _variantField_33;
-  List<int> _variantField_28;
+  List<String> _variantField_33;
   idl.LinkedNodeCommentType _variantField_29;
   List<idl.LinkedNode> _variantField_3;
   idl.LinkedNode _variantField_10;
+  idl.LinkedNodeFormalParameterKind _variantField_26;
   double _variantField_21;
   idl.LinkedNodeType _variantField_25;
-  idl.LinkedNodeFormalParameterKind _variantField_26;
+  int _flags;
+  String _variantField_1;
+  int _variantField_36;
+  int _variantField_16;
   String _variantField_30;
   idl.LinkedNode _variantField_14;
-  bool _isSynthetic;
   idl.LinkedNodeKind _kind;
+  List<String> _variantField_34;
+  String _name;
   String _variantField_20;
   bool _variantField_31;
+  idl.UnlinkedTokenType _variantField_35;
+  idl.TopLevelInferenceError _variantField_32;
+  idl.LinkedNode _variantField_11;
   String _variantField_22;
-  idl.LinkedNodeVariablesDeclaration _variantField_32;
+  int _variantField_19;
 
   @override
   idl.LinkedNodeType get actualReturnType {
@@ -11941,6 +11115,15 @@
   }
 
   @override
+  List<idl.LinkedNode> get comment_references {
+    assert(kind == idl.LinkedNodeKind.comment);
+    _variantField_2 ??=
+        const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
+            .vTableGet(_bc, _bcOffset, 2, const <idl.LinkedNode>[]);
+    return _variantField_2;
+  }
+
+  @override
   List<idl.LinkedNode> get compilationUnit_declarations {
     assert(kind == idl.LinkedNodeKind.compilationUnit);
     _variantField_2 ??=
@@ -11986,8 +11169,8 @@
   }
 
   @override
-  List<idl.LinkedNode> get hideCombinator_hiddenNames {
-    assert(kind == idl.LinkedNodeKind.hideCombinator);
+  List<idl.LinkedNode> get implementsClause_interfaces {
+    assert(kind == idl.LinkedNodeKind.implementsClause);
     _variantField_2 ??=
         const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
             .vTableGet(_bc, _bcOffset, 2, const <idl.LinkedNode>[]);
@@ -11995,8 +11178,8 @@
   }
 
   @override
-  List<idl.LinkedNode> get implementsClause_interfaces {
-    assert(kind == idl.LinkedNodeKind.implementsClause);
+  List<idl.LinkedNode> get instanceCreationExpression_arguments {
+    assert(kind == idl.LinkedNodeKind.instanceCreationExpression);
     _variantField_2 ??=
         const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
             .vTableGet(_bc, _bcOffset, 2, const <idl.LinkedNode>[]);
@@ -12022,15 +11205,6 @@
   }
 
   @override
-  List<idl.LinkedNode> get listLiteral_elements {
-    assert(kind == idl.LinkedNodeKind.listLiteral);
-    _variantField_2 ??=
-        const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
-            .vTableGet(_bc, _bcOffset, 2, const <idl.LinkedNode>[]);
-    return _variantField_2;
-  }
-
-  @override
   List<idl.LinkedNode> get namespaceDirective_combinators {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective);
@@ -12050,24 +11224,6 @@
   }
 
   @override
-  List<idl.LinkedNode> get setOrMapLiteral_elements {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    _variantField_2 ??=
-        const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
-            .vTableGet(_bc, _bcOffset, 2, const <idl.LinkedNode>[]);
-    return _variantField_2;
-  }
-
-  @override
-  List<idl.LinkedNode> get showCombinator_shownNames {
-    assert(kind == idl.LinkedNodeKind.showCombinator);
-    _variantField_2 ??=
-        const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
-            .vTableGet(_bc, _bcOffset, 2, const <idl.LinkedNode>[]);
-    return _variantField_2;
-  }
-
-  @override
   List<idl.LinkedNode> get stringInterpolation_elements {
     assert(kind == idl.LinkedNodeKind.stringInterpolation);
     _variantField_2 ??=
@@ -12104,6 +11260,25 @@
   }
 
   @override
+  List<idl.LinkedNode> get typedLiteral_typeArguments {
+    assert(kind == idl.LinkedNodeKind.listLiteral ||
+        kind == idl.LinkedNodeKind.setOrMapLiteral);
+    _variantField_2 ??=
+        const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
+            .vTableGet(_bc, _bcOffset, 2, const <idl.LinkedNode>[]);
+    return _variantField_2;
+  }
+
+  @override
+  List<idl.LinkedNode> get typeName_typeArguments {
+    assert(kind == idl.LinkedNodeKind.typeName);
+    _variantField_2 ??=
+        const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
+            .vTableGet(_bc, _bcOffset, 2, const <idl.LinkedNode>[]);
+    return _variantField_2;
+  }
+
+  @override
   List<idl.LinkedNode> get typeParameterList_typeParameters {
     assert(kind == idl.LinkedNodeKind.typeParameterList);
     _variantField_2 ??=
@@ -12131,34 +11306,6 @@
   }
 
   @override
-  idl.LinkedNode get annotatedNode_comment {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.declaredIdentifier ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
-        kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.fieldDeclaration ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.libraryDirective ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.partOfDirective ||
-        kind == idl.LinkedNodeKind.topLevelVariableDeclaration ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration ||
-        kind == idl.LinkedNodeKind.variableDeclarationList);
-    _variantField_11 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 11, null);
-    return _variantField_11;
-  }
-
-  @override
   List<idl.LinkedNode> get annotatedNode_metadata {
     assert(kind == idl.LinkedNodeKind.classDeclaration ||
         kind == idl.LinkedNodeKind.classTypeAlias ||
@@ -12313,6 +11460,14 @@
   }
 
   @override
+  idl.LinkedNode get commentReference_identifier {
+    assert(kind == idl.LinkedNodeKind.commentReference);
+    _variantField_6 ??=
+        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 6, null);
+    return _variantField_6;
+  }
+
+  @override
   idl.LinkedNode get compilationUnit_scriptTag {
     assert(kind == idl.LinkedNodeKind.compilationUnit);
     _variantField_6 ??=
@@ -12393,14 +11548,6 @@
   }
 
   @override
-  idl.LinkedNode get enumConstantDeclaration_name {
-    assert(kind == idl.LinkedNodeKind.enumConstantDeclaration);
-    _variantField_6 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 6, null);
-    return _variantField_6;
-  }
-
-  @override
   idl.LinkedNode get expressionFunctionBody_expression {
     assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
     _variantField_6 ??=
@@ -12541,14 +11688,6 @@
   }
 
   @override
-  idl.LinkedNode get importDirective_prefix {
-    assert(kind == idl.LinkedNodeKind.importDirective);
-    _variantField_6 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 6, null);
-    return _variantField_6;
-  }
-
-  @override
   idl.LinkedNode get indexExpression_index {
     assert(kind == idl.LinkedNodeKind.indexExpression);
     _variantField_6 ??=
@@ -12557,14 +11696,6 @@
   }
 
   @override
-  idl.LinkedNode get instanceCreationExpression_arguments {
-    assert(kind == idl.LinkedNodeKind.instanceCreationExpression);
-    _variantField_6 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 6, null);
-    return _variantField_6;
-  }
-
-  @override
   idl.LinkedNode get interpolationExpression_expression {
     assert(kind == idl.LinkedNodeKind.interpolationExpression);
     _variantField_6 ??=
@@ -12837,747 +11968,6 @@
   }
 
   @override
-  int get annotation_atSign {
-    assert(kind == idl.LinkedNodeKind.annotation);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get argumentList_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.argumentList);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get asExpression_asOperator {
-    assert(kind == idl.LinkedNodeKind.asExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get assertInitializer_assertKeyword {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get assertStatement_assertKeyword {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get assignmentExpression_element {
-    assert(kind == idl.LinkedNodeKind.assignmentExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get awaitExpression_awaitKeyword {
-    assert(kind == idl.LinkedNodeKind.awaitExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get binaryExpression_element {
-    assert(kind == idl.LinkedNodeKind.binaryExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get block_leftBracket {
-    assert(kind == idl.LinkedNodeKind.block);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get blockFunctionBody_keyword {
-    assert(kind == idl.LinkedNodeKind.blockFunctionBody);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get booleanLiteral_literal {
-    assert(kind == idl.LinkedNodeKind.booleanLiteral);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get breakStatement_breakKeyword {
-    assert(kind == idl.LinkedNodeKind.breakStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get catchClause_catchKeyword {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get classDeclaration_abstractKeyword {
-    assert(kind == idl.LinkedNodeKind.classDeclaration);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get classTypeAlias_abstractKeyword {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get compilationUnit_beginToken {
-    assert(kind == idl.LinkedNodeKind.compilationUnit);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get conditionalExpression_colon {
-    assert(kind == idl.LinkedNodeKind.conditionalExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get configuration_ifKeyword {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get constructorDeclaration_constKeyword {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get constructorFieldInitializer_equals {
-    assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get constructorName_element {
-    assert(kind == idl.LinkedNodeKind.constructorName);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get continueStatement_continueKeyword {
-    assert(kind == idl.LinkedNodeKind.continueStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get declaredIdentifier_keyword {
-    assert(kind == idl.LinkedNodeKind.declaredIdentifier);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get defaultFormalParameter_separator {
-    assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get doStatement_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get doubleLiteral_literal {
-    assert(kind == idl.LinkedNodeKind.doubleLiteral);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get emptyFunctionBody_semicolon {
-    assert(kind == idl.LinkedNodeKind.emptyFunctionBody);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get emptyStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.emptyStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get enumDeclaration_enumKeyword {
-    assert(kind == idl.LinkedNodeKind.enumDeclaration);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get expressionFunctionBody_arrow {
-    assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get expressionStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.expressionStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get extendsClause_extendsKeyword {
-    assert(kind == idl.LinkedNodeKind.extendsClause);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get fieldDeclaration_covariantKeyword {
-    assert(kind == idl.LinkedNodeKind.fieldDeclaration);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get fieldFormalParameter_keyword {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get forEachParts_inKeyword {
-    assert(kind == idl.LinkedNodeKind.forEachPartsWithDeclaration ||
-        kind == idl.LinkedNodeKind.forEachPartsWithIdentifier);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get formalParameterList_leftDelimiter {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get forMixin_awaitKeyword {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get forParts_leftSeparator {
-    assert(kind == idl.LinkedNodeKind.forPartsWithDeclarations ||
-        kind == idl.LinkedNodeKind.forPartsWithExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get functionDeclaration_externalKeyword {
-    assert(kind == idl.LinkedNodeKind.functionDeclaration);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get genericFunctionType_functionKeyword {
-    assert(kind == idl.LinkedNodeKind.genericFunctionType);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get ifMixin_elseKeyword {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get implementsClause_implementsKeyword {
-    assert(kind == idl.LinkedNodeKind.implementsClause);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get importDirective_asKeyword {
-    assert(kind == idl.LinkedNodeKind.importDirective);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get indexExpression_element {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get instanceCreationExpression_keyword {
-    assert(kind == idl.LinkedNodeKind.instanceCreationExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get integerLiteral_literal {
-    assert(kind == idl.LinkedNodeKind.integerLiteral);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get interpolationExpression_leftBracket {
-    assert(kind == idl.LinkedNodeKind.interpolationExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get interpolationString_token {
-    assert(kind == idl.LinkedNodeKind.interpolationString);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get isExpression_isOperator {
-    assert(kind == idl.LinkedNodeKind.isExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get label_colon {
-    assert(kind == idl.LinkedNodeKind.label);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get listLiteral_leftBracket {
-    assert(kind == idl.LinkedNodeKind.listLiteral);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get mapLiteralEntry_separator {
-    assert(kind == idl.LinkedNodeKind.mapLiteralEntry);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get methodDeclaration_externalKeyword {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get methodInvocation_operator {
-    assert(kind == idl.LinkedNodeKind.methodInvocation);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get mixinDeclaration_mixinKeyword {
-    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get nativeClause_nativeKeyword {
-    assert(kind == idl.LinkedNodeKind.nativeClause);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get nativeFunctionBody_nativeKeyword {
-    assert(kind == idl.LinkedNodeKind.nativeFunctionBody);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get nullLiteral_literal {
-    assert(kind == idl.LinkedNodeKind.nullLiteral);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get onClause_onKeyword {
-    assert(kind == idl.LinkedNodeKind.onClause);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get parenthesizedExpression_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.parenthesizedExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get postfixExpression_element {
-    assert(kind == idl.LinkedNodeKind.postfixExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get prefixedIdentifier_period {
-    assert(kind == idl.LinkedNodeKind.prefixedIdentifier);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get prefixExpression_element {
-    assert(kind == idl.LinkedNodeKind.prefixExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get propertyAccess_operator {
-    assert(kind == idl.LinkedNodeKind.propertyAccess);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get redirectingConstructorInvocation_element {
-    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get rethrowExpression_rethrowKeyword {
-    assert(kind == idl.LinkedNodeKind.rethrowExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get returnStatement_returnKeyword {
-    assert(kind == idl.LinkedNodeKind.returnStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get scriptTag_scriptTag {
-    assert(kind == idl.LinkedNodeKind.scriptTag);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get setOrMapLiteral_leftBracket {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get simpleFormalParameter_keyword {
-    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get simpleIdentifier_element {
-    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get simpleStringLiteral_token {
-    assert(kind == idl.LinkedNodeKind.simpleStringLiteral);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get spreadElement_spreadOperator {
-    assert(kind == idl.LinkedNodeKind.spreadElement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get superConstructorInvocation_element {
-    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get superExpression_superKeyword {
-    assert(kind == idl.LinkedNodeKind.superExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get switchMember_keyword {
-    assert(kind == idl.LinkedNodeKind.switchCase ||
-        kind == idl.LinkedNodeKind.switchDefault);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get switchStatement_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get symbolLiteral_poundSign {
-    assert(kind == idl.LinkedNodeKind.symbolLiteral);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get thisExpression_thisKeyword {
-    assert(kind == idl.LinkedNodeKind.thisExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get throwExpression_throwKeyword {
-    assert(kind == idl.LinkedNodeKind.throwExpression);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get topLevelVariableDeclaration_semicolon {
-    assert(kind == idl.LinkedNodeKind.topLevelVariableDeclaration);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get tryStatement_finallyKeyword {
-    assert(kind == idl.LinkedNodeKind.tryStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get typeArgumentList_leftBracket {
-    assert(kind == idl.LinkedNodeKind.typeArgumentList);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get typeName_question {
-    assert(kind == idl.LinkedNodeKind.typeName);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get typeParameter_extendsKeyword {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get typeParameterList_leftBracket {
-    assert(kind == idl.LinkedNodeKind.typeParameterList);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get variableDeclaration_equals {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get variableDeclarationList_keyword {
-    assert(kind == idl.LinkedNodeKind.variableDeclarationList);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get variableDeclarationStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.variableDeclarationStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get whileStatement_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.whileStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get withClause_withKeyword {
-    assert(kind == idl.LinkedNodeKind.withClause);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
-  int get yieldStatement_yieldKeyword {
-    assert(kind == idl.LinkedNodeKind.yieldStatement);
-    _variantField_15 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
-    return _variantField_15;
-  }
-
-  @override
   idl.LinkedNode get annotation_constructorName {
     assert(kind == idl.LinkedNodeKind.annotation);
     _variantField_7 ??=
@@ -13666,14 +12056,6 @@
   }
 
   @override
-  idl.LinkedNode get constructorDeclaration_name {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    _variantField_7 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 7, null);
-    return _variantField_7;
-  }
-
-  @override
   idl.LinkedNode get constructorFieldInitializer_fieldName {
     assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
     _variantField_7 ??=
@@ -13938,30 +12320,6 @@
   }
 
   @override
-  idl.LinkedNode get typeName_typeArguments {
-    assert(kind == idl.LinkedNodeKind.typeName);
-    _variantField_7 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 7, null);
-    return _variantField_7;
-  }
-
-  @override
-  idl.LinkedNode get typeParameter_name {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    _variantField_7 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 7, null);
-    return _variantField_7;
-  }
-
-  @override
-  idl.LinkedNode get variableDeclaration_name {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_7 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 7, null);
-    return _variantField_7;
-  }
-
-  @override
   idl.LinkedNode get whileStatement_condition {
     assert(kind == idl.LinkedNodeKind.whileStatement);
     _variantField_7 ??=
@@ -13970,6 +12328,118 @@
   }
 
   @override
+  int get annotation_element {
+    assert(kind == idl.LinkedNodeKind.annotation);
+    _variantField_17 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
+    return _variantField_17;
+  }
+
+  @override
+  int get genericFunctionType_id {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    _variantField_17 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
+    return _variantField_17;
+  }
+
+  @override
+  idl.LinkedNodeType get annotation_elementType {
+    assert(kind == idl.LinkedNodeKind.annotation);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
+  idl.LinkedNodeType get assignmentExpression_elementType {
+    assert(kind == idl.LinkedNodeKind.assignmentExpression);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
+  idl.LinkedNodeType get binaryExpression_elementType {
+    assert(kind == idl.LinkedNodeKind.binaryExpression);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
+  idl.LinkedNodeType get constructorName_elementType {
+    assert(kind == idl.LinkedNodeKind.constructorName);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
+  idl.LinkedNodeType get indexExpression_elementType {
+    assert(kind == idl.LinkedNodeKind.indexExpression);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
+  idl.LinkedNodeType get postfixExpression_elementType {
+    assert(kind == idl.LinkedNodeKind.postfixExpression);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
+  idl.LinkedNodeType get prefixExpression_elementType {
+    assert(kind == idl.LinkedNodeKind.prefixExpression);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
+  idl.LinkedNodeType get redirectingConstructorInvocation_elementType {
+    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
+  idl.LinkedNodeType get simpleIdentifier_elementType {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
+  idl.LinkedNodeType get superConstructorInvocation_elementType {
+    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
+  idl.LinkedNodeType get typeName_type {
+    assert(kind == idl.LinkedNodeKind.typeName);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
+  idl.LinkedNodeType get typeParameter_defaultType {
+    assert(kind == idl.LinkedNodeKind.typeParameter);
+    _variantField_23 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
+    return _variantField_23;
+  }
+
+  @override
   idl.LinkedNode get annotation_name {
     assert(kind == idl.LinkedNodeKind.annotation);
     _variantField_8 ??=
@@ -14098,939 +12568,147 @@
   }
 
   @override
-  int get annotation_period {
-    assert(kind == idl.LinkedNodeKind.annotation);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get argumentList_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.argumentList);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get assertInitializer_comma {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get assertStatement_comma {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get assignmentExpression_operator {
+  int get assignmentExpression_element {
     assert(kind == idl.LinkedNodeKind.assignmentExpression);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get binaryExpression_operator {
+  int get binaryExpression_element {
     assert(kind == idl.LinkedNodeKind.binaryExpression);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get block_rightBracket {
-    assert(kind == idl.LinkedNodeKind.block);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get blockFunctionBody_star {
-    assert(kind == idl.LinkedNodeKind.blockFunctionBody);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get breakStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.breakStatement);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get catchClause_comma {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get classDeclaration_classKeyword {
-    assert(kind == idl.LinkedNodeKind.classDeclaration);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get classTypeAlias_equals {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get compilationUnit_endToken {
-    assert(kind == idl.LinkedNodeKind.compilationUnit);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get conditionalExpression_question {
-    assert(kind == idl.LinkedNodeKind.conditionalExpression);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get configuration_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get constructorDeclaration_externalKeyword {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get constructorFieldInitializer_period {
-    assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get constructorName_period {
+  int get constructorName_element {
     assert(kind == idl.LinkedNodeKind.constructorName);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get continueStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.continueStatement);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+  int get emptyFunctionBody_fake {
+    assert(kind == idl.LinkedNodeKind.emptyFunctionBody);
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get doStatement_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+  int get emptyStatement_fake {
+    assert(kind == idl.LinkedNodeKind.emptyStatement);
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get enumDeclaration_leftBracket {
-    assert(kind == idl.LinkedNodeKind.enumDeclaration);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get expressionFunctionBody_keyword {
-    assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get fieldDeclaration_semicolon {
-    assert(kind == idl.LinkedNodeKind.fieldDeclaration);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get fieldFormalParameter_period {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get formalParameterList_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get forMixin_forKeyword {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get forParts_rightSeparator {
-    assert(kind == idl.LinkedNodeKind.forPartsWithDeclarations ||
-        kind == idl.LinkedNodeKind.forPartsWithExpression);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get functionDeclaration_propertyKeyword {
-    assert(kind == idl.LinkedNodeKind.functionDeclaration);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get genericFunctionType_question {
-    assert(kind == idl.LinkedNodeKind.genericFunctionType);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get genericTypeAlias_equals {
-    assert(kind == idl.LinkedNodeKind.genericTypeAlias);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get ifMixin_ifKeyword {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get importDirective_deferredKeyword {
+  int get importDirective_prefixOffset {
     assert(kind == idl.LinkedNodeKind.importDirective);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get indexExpression_period {
+  int get indexExpression_element {
     assert(kind == idl.LinkedNodeKind.indexExpression);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get integerLiteral_value {
-    assert(kind == idl.LinkedNodeKind.integerLiteral);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+  int get nullLiteral_fake {
+    assert(kind == idl.LinkedNodeKind.nullLiteral);
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get interpolationExpression_rightBracket {
-    assert(kind == idl.LinkedNodeKind.interpolationExpression);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get isExpression_notOperator {
-    assert(kind == idl.LinkedNodeKind.isExpression);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get listLiteral_rightBracket {
-    assert(kind == idl.LinkedNodeKind.listLiteral);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get methodDeclaration_modifierKeyword {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get nativeFunctionBody_semicolon {
-    assert(kind == idl.LinkedNodeKind.nativeFunctionBody);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get parenthesizedExpression_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.parenthesizedExpression);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get partOfDirective_ofKeyword {
-    assert(kind == idl.LinkedNodeKind.partOfDirective);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get postfixExpression_operator {
+  int get postfixExpression_element {
     assert(kind == idl.LinkedNodeKind.postfixExpression);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get prefixExpression_operator {
+  int get prefixExpression_element {
     assert(kind == idl.LinkedNodeKind.prefixExpression);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get redirectingConstructorInvocation_period {
+  int get redirectingConstructorInvocation_element {
     assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get returnStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.returnStatement);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get setOrMapLiteral_rightBracket {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get simpleIdentifier_token {
+  int get simpleIdentifier_element {
     assert(kind == idl.LinkedNodeKind.simpleIdentifier);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get superConstructorInvocation_period {
+  int get superConstructorInvocation_element {
     assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
   }
 
   @override
-  int get switchMember_colon {
-    assert(kind == idl.LinkedNodeKind.switchCase ||
-        kind == idl.LinkedNodeKind.switchDefault);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get switchStatement_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get tryStatement_tryKeyword {
-    assert(kind == idl.LinkedNodeKind.tryStatement);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get typeArgumentList_rightBracket {
-    assert(kind == idl.LinkedNodeKind.typeArgumentList);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get typeParameter_id {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get typeParameterList_rightBracket {
-    assert(kind == idl.LinkedNodeKind.typeParameterList);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get whileStatement_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.whileStatement);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get yieldStatement_star {
-    assert(kind == idl.LinkedNodeKind.yieldStatement);
-    _variantField_16 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
-    return _variantField_16;
-  }
-
-  @override
-  int get assertInitializer_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get assertStatement_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get catchClause_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get configuration_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get constructorDeclaration_factoryKeyword {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get constructorFieldInitializer_thisKeyword {
-    assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get doStatement_doKeyword {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get enumDeclaration_rightBracket {
-    assert(kind == idl.LinkedNodeKind.enumDeclaration);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get expressionFunctionBody_semicolon {
-    assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get fieldDeclaration_staticKeyword {
-    assert(kind == idl.LinkedNodeKind.fieldDeclaration);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get fieldFormalParameter_thisKeyword {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get formalParameterList_rightDelimiter {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get forMixin_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get ifMixin_leftParenthesis {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get indexExpression_leftBracket {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get methodDeclaration_operatorKeyword {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get redirectingConstructorInvocation_thisKeyword {
-    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get superConstructorInvocation_superKeyword {
-    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get switchStatement_switchKeyword {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get whileStatement_whileKeyword {
-    assert(kind == idl.LinkedNodeKind.whileStatement);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get yieldStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.yieldStatement);
-    _variantField_17 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
-    return _variantField_17;
-  }
-
-  @override
-  int get assertInitializer_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.assertInitializer);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get assertStatement_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get catchClause_onKeyword {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get classOrMixinDeclaration_rightBracket {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get configuration_equalToken {
-    assert(kind == idl.LinkedNodeKind.configuration);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get constructorDeclaration_period {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get directive_keyword {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.libraryDirective ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.partOfDirective);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get doStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get formalParameterList_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.formalParameterList);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get ifMixin_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.ifElement ||
-        kind == idl.LinkedNodeKind.ifStatement);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get indexExpression_rightBracket {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get methodDeclaration_propertyKeyword {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get switchStatement_leftBracket {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get typeAlias_typedefKeyword {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias);
-    _variantField_18 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
-    return _variantField_18;
-  }
-
-  @override
-  int get assertStatement_semicolon {
-    assert(kind == idl.LinkedNodeKind.assertStatement);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get catchClause_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.catchClause);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get classOrMixinDeclaration_leftBracket {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get combinator_keyword {
-    assert(kind == idl.LinkedNodeKind.hideCombinator ||
-        kind == idl.LinkedNodeKind.showCombinator);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get constructorDeclaration_separator {
-    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get doStatement_whileKeyword {
-    assert(kind == idl.LinkedNodeKind.doStatement);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get forMixin_rightParenthesis {
-    assert(kind == idl.LinkedNodeKind.forElement ||
-        kind == idl.LinkedNodeKind.forStatement);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get methodDeclaration_actualProperty {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get normalFormalParameter_covariantKeyword {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get switchStatement_rightBracket {
-    assert(kind == idl.LinkedNodeKind.switchStatement);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get typeAlias_semicolon {
-    assert(kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get typedLiteral_constKeyword {
-    assert(kind == idl.LinkedNodeKind.listLiteral ||
-        kind == idl.LinkedNodeKind.setOrMapLiteral);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  int get uriBasedDirective_uriElement {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.partDirective);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  idl.LinkedNodeType get assignmentExpression_elementType {
+  idl.UnlinkedTokenType get assignmentExpression_operator {
     assert(kind == idl.LinkedNodeKind.assignmentExpression);
-    _variantField_23 ??=
-        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
-    return _variantField_23;
+    _variantField_28 ??= const _UnlinkedTokenTypeReader()
+        .vTableGet(_bc, _bcOffset, 28, idl.UnlinkedTokenType.NOTHING);
+    return _variantField_28;
   }
 
   @override
-  idl.LinkedNodeType get binaryExpression_elementType {
+  idl.UnlinkedTokenType get binaryExpression_operator {
     assert(kind == idl.LinkedNodeKind.binaryExpression);
-    _variantField_23 ??=
-        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
-    return _variantField_23;
+    _variantField_28 ??= const _UnlinkedTokenTypeReader()
+        .vTableGet(_bc, _bcOffset, 28, idl.UnlinkedTokenType.NOTHING);
+    return _variantField_28;
   }
 
   @override
-  idl.LinkedNodeType get constructorName_elementType {
-    assert(kind == idl.LinkedNodeKind.constructorName);
-    _variantField_23 ??=
-        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
-    return _variantField_23;
-  }
-
-  @override
-  idl.LinkedNodeType get indexExpression_elementType {
-    assert(kind == idl.LinkedNodeKind.indexExpression);
-    _variantField_23 ??=
-        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
-    return _variantField_23;
-  }
-
-  @override
-  idl.LinkedNodeType get postfixExpression_elementType {
+  idl.UnlinkedTokenType get postfixExpression_operator {
     assert(kind == idl.LinkedNodeKind.postfixExpression);
-    _variantField_23 ??=
-        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
-    return _variantField_23;
+    _variantField_28 ??= const _UnlinkedTokenTypeReader()
+        .vTableGet(_bc, _bcOffset, 28, idl.UnlinkedTokenType.NOTHING);
+    return _variantField_28;
   }
 
   @override
-  idl.LinkedNodeType get prefixExpression_elementType {
+  idl.UnlinkedTokenType get prefixExpression_operator {
     assert(kind == idl.LinkedNodeKind.prefixExpression);
-    _variantField_23 ??=
-        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
-    return _variantField_23;
+    _variantField_28 ??= const _UnlinkedTokenTypeReader()
+        .vTableGet(_bc, _bcOffset, 28, idl.UnlinkedTokenType.NOTHING);
+    return _variantField_28;
   }
 
   @override
-  idl.LinkedNodeType get redirectingConstructorInvocation_elementType {
-    assert(kind == idl.LinkedNodeKind.redirectingConstructorInvocation);
-    _variantField_23 ??=
-        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
-    return _variantField_23;
-  }
-
-  @override
-  idl.LinkedNodeType get simpleIdentifier_elementType {
-    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
-    _variantField_23 ??=
-        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
-    return _variantField_23;
-  }
-
-  @override
-  idl.LinkedNodeType get superConstructorInvocation_elementType {
-    assert(kind == idl.LinkedNodeKind.superConstructorInvocation);
-    _variantField_23 ??=
-        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
-    return _variantField_23;
-  }
-
-  @override
-  idl.LinkedNodeType get typeName_type {
-    assert(kind == idl.LinkedNodeKind.typeName);
-    _variantField_23 ??=
-        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
-    return _variantField_23;
+  idl.UnlinkedTokenType get propertyAccess_operator {
+    assert(kind == idl.LinkedNodeKind.propertyAccess);
+    _variantField_28 ??= const _UnlinkedTokenTypeReader()
+        .vTableGet(_bc, _bcOffset, 28, idl.UnlinkedTokenType.NOTHING);
+    return _variantField_28;
   }
 
   @override
@@ -15050,26 +12728,20 @@
   }
 
   @override
-  bool get defaultFormalParameter_isNamed {
-    assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
-    _variantField_27 ??=
-        const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
-    return _variantField_27;
-  }
-
-  @override
-  bool get normalFormalParameter_isCovariant {
+  bool get inheritsCovariant {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
     _variantField_27 ??=
         const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
     return _variantField_27;
   }
 
   @override
-  bool get setOrMapLiteral_isMap {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
+  bool get typeAlias_hasSelfReference {
+    assert(kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias);
     _variantField_27 ??=
         const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
     return _variantField_27;
@@ -15134,16 +12806,6 @@
   }
 
   @override
-  idl.LinkedNode get normalFormalParameter_identifier {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    _variantField_12 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 12, null);
-    return _variantField_12;
-  }
-
-  @override
   List<idl.LinkedNode> get classOrMixinDeclaration_members {
     assert(kind == idl.LinkedNodeKind.classDeclaration ||
         kind == idl.LinkedNodeKind.mixinDeclaration);
@@ -15173,75 +12835,11 @@
   }
 
   @override
-  int get codeLength {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.defaultFormalParameter ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_34 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 34, 0);
-    return _variantField_34;
-  }
-
-  @override
-  int get codeOffset {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.defaultFormalParameter ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_33 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 33, 0);
-    return _variantField_33;
-  }
-
-  @override
-  int get directive_semicolon {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.libraryDirective ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.partOfDirective);
-    _variantField_33 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 33, 0);
-    return _variantField_33;
-  }
-
-  @override
-  List<int> get comment_tokens {
+  List<String> get comment_tokens {
     assert(kind == idl.LinkedNodeKind.comment);
-    _variantField_28 ??= const fb.Uint32ListReader()
-        .vTableGet(_bc, _bcOffset, 28, const <int>[]);
-    return _variantField_28;
-  }
-
-  @override
-  List<int> get symbolLiteral_components {
-    assert(kind == idl.LinkedNodeKind.symbolLiteral);
-    _variantField_28 ??= const fb.Uint32ListReader()
-        .vTableGet(_bc, _bcOffset, 28, const <int>[]);
-    return _variantField_28;
+    _variantField_33 ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 33, const <String>[]);
+    return _variantField_33;
   }
 
   @override
@@ -15262,6 +12860,15 @@
   }
 
   @override
+  List<idl.LinkedNode> get listLiteral_elements {
+    assert(kind == idl.LinkedNodeKind.listLiteral);
+    _variantField_3 ??=
+        const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
+            .vTableGet(_bc, _bcOffset, 3, const <idl.LinkedNode>[]);
+    return _variantField_3;
+  }
+
+  @override
   List<idl.LinkedNode> get namespaceDirective_configurations {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective);
@@ -15272,6 +12879,15 @@
   }
 
   @override
+  List<idl.LinkedNode> get setOrMapLiteral_elements {
+    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
+    _variantField_3 ??=
+        const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
+            .vTableGet(_bc, _bcOffset, 3, const <idl.LinkedNode>[]);
+    return _variantField_3;
+  }
+
+  @override
   List<idl.LinkedNode> get switchMember_labels {
     assert(kind == idl.LinkedNodeKind.switchCase ||
         kind == idl.LinkedNodeKind.switchDefault);
@@ -15290,11 +12906,14 @@
   }
 
   @override
-  idl.LinkedNode get methodDeclaration_name {
-    assert(kind == idl.LinkedNodeKind.methodDeclaration);
-    _variantField_10 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 10, null);
-    return _variantField_10;
+  idl.LinkedNodeFormalParameterKind get defaultFormalParameter_kind {
+    assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
+    _variantField_26 ??= const _LinkedNodeFormalParameterKindReader().vTableGet(
+        _bc,
+        _bcOffset,
+        26,
+        idl.LinkedNodeFormalParameterKind.requiredPositional);
+    return _variantField_26;
   }
 
   @override
@@ -15307,23 +12926,17 @@
 
   @override
   idl.LinkedNodeType get expression_type {
-    assert(kind == idl.LinkedNodeKind.adjacentStrings ||
-        kind == idl.LinkedNodeKind.assignmentExpression ||
+    assert(kind == idl.LinkedNodeKind.assignmentExpression ||
         kind == idl.LinkedNodeKind.asExpression ||
         kind == idl.LinkedNodeKind.awaitExpression ||
         kind == idl.LinkedNodeKind.binaryExpression ||
-        kind == idl.LinkedNodeKind.booleanLiteral ||
         kind == idl.LinkedNodeKind.cascadeExpression ||
         kind == idl.LinkedNodeKind.conditionalExpression ||
-        kind == idl.LinkedNodeKind.doubleLiteral ||
         kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.indexExpression ||
         kind == idl.LinkedNodeKind.instanceCreationExpression ||
-        kind == idl.LinkedNodeKind.integerLiteral ||
-        kind == idl.LinkedNodeKind.isExpression ||
         kind == idl.LinkedNodeKind.listLiteral ||
         kind == idl.LinkedNodeKind.methodInvocation ||
-        kind == idl.LinkedNodeKind.namedExpression ||
         kind == idl.LinkedNodeKind.nullLiteral ||
         kind == idl.LinkedNodeKind.parenthesizedExpression ||
         kind == idl.LinkedNodeKind.prefixExpression ||
@@ -15333,8 +12946,6 @@
         kind == idl.LinkedNodeKind.rethrowExpression ||
         kind == idl.LinkedNodeKind.setOrMapLiteral ||
         kind == idl.LinkedNodeKind.simpleIdentifier ||
-        kind == idl.LinkedNodeKind.simpleStringLiteral ||
-        kind == idl.LinkedNodeKind.stringInterpolation ||
         kind == idl.LinkedNodeKind.superExpression ||
         kind == idl.LinkedNodeKind.symbolLiteral ||
         kind == idl.LinkedNodeKind.thisExpression ||
@@ -15353,13 +12964,58 @@
   }
 
   @override
-  idl.LinkedNodeFormalParameterKind get formalParameter_kind {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+  int get flags {
+    _flags ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
+    return _flags;
+  }
+
+  @override
+  String get importDirective_prefix {
+    assert(kind == idl.LinkedNodeKind.importDirective);
+    _variantField_1 ??=
+        const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
+    return _variantField_1;
+  }
+
+  @override
+  int get informativeId {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.defaultFormalParameter ||
+        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.fieldDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    _variantField_26 ??= const _LinkedNodeFormalParameterKindReader().vTableGet(
-        _bc, _bcOffset, 26, idl.LinkedNodeFormalParameterKind.required);
-    return _variantField_26;
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.partDirective ||
+        kind == idl.LinkedNodeKind.partOfDirective ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.topLevelVariableDeclaration ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration ||
+        kind == idl.LinkedNodeKind.variableDeclarationList);
+    _variantField_36 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 36, 0);
+    return _variantField_36;
+  }
+
+  @override
+  int get integerLiteral_value {
+    assert(kind == idl.LinkedNodeKind.integerLiteral);
+    _variantField_16 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
+    return _variantField_16;
   }
 
   @override
@@ -15380,39 +13036,6 @@
   }
 
   @override
-  idl.LinkedNode get namedCompilationUnitMember_name {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.mixinDeclaration);
-    _variantField_14 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 14, null);
-    return _variantField_14;
-  }
-
-  @override
-  idl.LinkedNode get normalFormalParameter_comment {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    _variantField_14 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 14, null);
-    return _variantField_14;
-  }
-
-  @override
-  idl.LinkedNode get typedLiteral_typeArguments {
-    assert(kind == idl.LinkedNodeKind.listLiteral ||
-        kind == idl.LinkedNodeKind.setOrMapLiteral);
-    _variantField_14 ??=
-        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 14, null);
-    return _variantField_14;
-  }
-
-  @override
   idl.LinkedNode get uriBasedDirective_uri {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective ||
@@ -15423,12 +13046,6 @@
   }
 
   @override
-  bool get isSynthetic {
-    _isSynthetic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 1, false);
-    return _isSynthetic;
-  }
-
-  @override
   idl.LinkedNodeKind get kind {
     _kind ??= const _LinkedNodeKindReader()
         .vTableGet(_bc, _bcOffset, 0, idl.LinkedNodeKind.adjacentStrings);
@@ -15436,6 +13053,30 @@
   }
 
   @override
+  List<String> get mixinDeclaration_superInvokedNames {
+    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+    _variantField_34 ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 34, const <String>[]);
+    return _variantField_34;
+  }
+
+  @override
+  List<String> get names {
+    assert(kind == idl.LinkedNodeKind.hideCombinator ||
+        kind == idl.LinkedNodeKind.showCombinator ||
+        kind == idl.LinkedNodeKind.symbolLiteral);
+    _variantField_34 ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 34, const <String>[]);
+    return _variantField_34;
+  }
+
+  @override
+  String get name {
+    _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 37, '');
+    return _name;
+  }
+
+  @override
   String get namespaceDirective_selectedUri {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective);
@@ -15453,14 +13094,6 @@
   }
 
   @override
-  bool get setOrMapLiteral_isSet {
-    assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
-    _variantField_31 ??=
-        const fb.BoolReader().vTableGet(_bc, _bcOffset, 31, false);
-    return _variantField_31;
-  }
-
-  @override
   bool get simplyBoundable_isSimplyBounded {
     assert(kind == idl.LinkedNodeKind.classDeclaration ||
         kind == idl.LinkedNodeKind.classTypeAlias ||
@@ -15473,6 +13106,31 @@
   }
 
   @override
+  idl.UnlinkedTokenType get spreadElement_spreadOperator {
+    assert(kind == idl.LinkedNodeKind.spreadElement);
+    _variantField_35 ??= const _UnlinkedTokenTypeReader()
+        .vTableGet(_bc, _bcOffset, 35, idl.UnlinkedTokenType.NOTHING);
+    return _variantField_35;
+  }
+
+  @override
+  idl.TopLevelInferenceError get topLevelTypeInferenceError {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_32 ??= const _TopLevelInferenceErrorReader()
+        .vTableGet(_bc, _bcOffset, 32, null);
+    return _variantField_32;
+  }
+
+  @override
+  idl.LinkedNode get unused11 {
+    assert(kind == idl.LinkedNodeKind.classDeclaration);
+    _variantField_11 ??=
+        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 11, null);
+    return _variantField_11;
+  }
+
+  @override
   String get uriBasedDirective_uriContent {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective ||
@@ -15483,11 +13141,13 @@
   }
 
   @override
-  idl.LinkedNodeVariablesDeclaration get variableDeclaration_declaration {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_32 ??= const _LinkedNodeVariablesDeclarationReader()
-        .vTableGet(_bc, _bcOffset, 32, null);
-    return _variantField_32;
+  int get uriBasedDirective_uriElement {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.partDirective);
+    _variantField_19 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
+    return _variantField_19;
   }
 }
 
@@ -15495,34 +13155,491 @@
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
-    if (isSynthetic != false) _result["isSynthetic"] = isSynthetic;
+    if (flags != 0) _result["flags"] = flags;
     if (kind != idl.LinkedNodeKind.adjacentStrings)
       _result["kind"] = kind.toString().split('.')[1];
+    if (name != '') _result["name"] = name;
+    if (kind == idl.LinkedNodeKind.adjacentStrings) {
+      if (adjacentStrings_strings.isNotEmpty)
+        _result["adjacentStrings_strings"] =
+            adjacentStrings_strings.map((_value) => _value.toJson()).toList();
+    }
+    if (kind == idl.LinkedNodeKind.annotation) {
+      if (annotation_arguments != null)
+        _result["annotation_arguments"] = annotation_arguments.toJson();
+      if (annotation_constructorName != null)
+        _result["annotation_constructorName"] =
+            annotation_constructorName.toJson();
+      if (annotation_element != 0)
+        _result["annotation_element"] = annotation_element;
+      if (annotation_elementType != null)
+        _result["annotation_elementType"] = annotation_elementType.toJson();
+      if (annotation_name != null)
+        _result["annotation_name"] = annotation_name.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.argumentList) {
+      if (argumentList_arguments.isNotEmpty)
+        _result["argumentList_arguments"] =
+            argumentList_arguments.map((_value) => _value.toJson()).toList();
+    }
+    if (kind == idl.LinkedNodeKind.asExpression) {
+      if (asExpression_expression != null)
+        _result["asExpression_expression"] = asExpression_expression.toJson();
+      if (asExpression_type != null)
+        _result["asExpression_type"] = asExpression_type.toJson();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.assertInitializer) {
+      if (assertInitializer_condition != null)
+        _result["assertInitializer_condition"] =
+            assertInitializer_condition.toJson();
+      if (assertInitializer_message != null)
+        _result["assertInitializer_message"] =
+            assertInitializer_message.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.assertStatement) {
+      if (assertStatement_condition != null)
+        _result["assertStatement_condition"] =
+            assertStatement_condition.toJson();
+      if (assertStatement_message != null)
+        _result["assertStatement_message"] = assertStatement_message.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.assignmentExpression) {
+      if (assignmentExpression_leftHandSide != null)
+        _result["assignmentExpression_leftHandSide"] =
+            assignmentExpression_leftHandSide.toJson();
+      if (assignmentExpression_rightHandSide != null)
+        _result["assignmentExpression_rightHandSide"] =
+            assignmentExpression_rightHandSide.toJson();
+      if (assignmentExpression_elementType != null)
+        _result["assignmentExpression_elementType"] =
+            assignmentExpression_elementType.toJson();
+      if (assignmentExpression_element != 0)
+        _result["assignmentExpression_element"] = assignmentExpression_element;
+      if (assignmentExpression_operator != idl.UnlinkedTokenType.NOTHING)
+        _result["assignmentExpression_operator"] =
+            assignmentExpression_operator.toString().split('.')[1];
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.awaitExpression) {
+      if (awaitExpression_expression != null)
+        _result["awaitExpression_expression"] =
+            awaitExpression_expression.toJson();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.binaryExpression) {
+      if (binaryExpression_invokeType != null)
+        _result["binaryExpression_invokeType"] =
+            binaryExpression_invokeType.toJson();
+      if (binaryExpression_leftOperand != null)
+        _result["binaryExpression_leftOperand"] =
+            binaryExpression_leftOperand.toJson();
+      if (binaryExpression_rightOperand != null)
+        _result["binaryExpression_rightOperand"] =
+            binaryExpression_rightOperand.toJson();
+      if (binaryExpression_elementType != null)
+        _result["binaryExpression_elementType"] =
+            binaryExpression_elementType.toJson();
+      if (binaryExpression_element != 0)
+        _result["binaryExpression_element"] = binaryExpression_element;
+      if (binaryExpression_operator != idl.UnlinkedTokenType.NOTHING)
+        _result["binaryExpression_operator"] =
+            binaryExpression_operator.toString().split('.')[1];
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.block) {
+      if (block_statements.isNotEmpty)
+        _result["block_statements"] =
+            block_statements.map((_value) => _value.toJson()).toList();
+    }
+    if (kind == idl.LinkedNodeKind.blockFunctionBody) {
+      if (blockFunctionBody_block != null)
+        _result["blockFunctionBody_block"] = blockFunctionBody_block.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.booleanLiteral) {
+      if (booleanLiteral_value != false)
+        _result["booleanLiteral_value"] = booleanLiteral_value;
+    }
+    if (kind == idl.LinkedNodeKind.breakStatement) {
+      if (breakStatement_label != null)
+        _result["breakStatement_label"] = breakStatement_label.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.cascadeExpression) {
+      if (cascadeExpression_sections.isNotEmpty)
+        _result["cascadeExpression_sections"] = cascadeExpression_sections
+            .map((_value) => _value.toJson())
+            .toList();
+      if (cascadeExpression_target != null)
+        _result["cascadeExpression_target"] = cascadeExpression_target.toJson();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.catchClause) {
+      if (catchClause_body != null)
+        _result["catchClause_body"] = catchClause_body.toJson();
+      if (catchClause_exceptionParameter != null)
+        _result["catchClause_exceptionParameter"] =
+            catchClause_exceptionParameter.toJson();
+      if (catchClause_exceptionType != null)
+        _result["catchClause_exceptionType"] =
+            catchClause_exceptionType.toJson();
+      if (catchClause_stackTraceParameter != null)
+        _result["catchClause_stackTraceParameter"] =
+            catchClause_stackTraceParameter.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.classDeclaration) {
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (classDeclaration_extendsClause != null)
+        _result["classDeclaration_extendsClause"] =
+            classDeclaration_extendsClause.toJson();
+      if (classDeclaration_withClause != null)
+        _result["classDeclaration_withClause"] =
+            classDeclaration_withClause.toJson();
+      if (classDeclaration_nativeClause != null)
+        _result["classDeclaration_nativeClause"] =
+            classDeclaration_nativeClause.toJson();
+      if (classDeclaration_isDartObject != false)
+        _result["classDeclaration_isDartObject"] =
+            classDeclaration_isDartObject;
+      if (classOrMixinDeclaration_implementsClause != null)
+        _result["classOrMixinDeclaration_implementsClause"] =
+            classOrMixinDeclaration_implementsClause.toJson();
+      if (classOrMixinDeclaration_members.isNotEmpty)
+        _result["classOrMixinDeclaration_members"] =
+            classOrMixinDeclaration_members
+                .map((_value) => _value.toJson())
+                .toList();
+      if (classOrMixinDeclaration_typeParameters != null)
+        _result["classOrMixinDeclaration_typeParameters"] =
+            classOrMixinDeclaration_typeParameters.toJson();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+      if (simplyBoundable_isSimplyBounded != false)
+        _result["simplyBoundable_isSimplyBounded"] =
+            simplyBoundable_isSimplyBounded;
+      if (unused11 != null) _result["unused11"] = unused11.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.classTypeAlias) {
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (classTypeAlias_typeParameters != null)
+        _result["classTypeAlias_typeParameters"] =
+            classTypeAlias_typeParameters.toJson();
+      if (classTypeAlias_superclass != null)
+        _result["classTypeAlias_superclass"] =
+            classTypeAlias_superclass.toJson();
+      if (classTypeAlias_withClause != null)
+        _result["classTypeAlias_withClause"] =
+            classTypeAlias_withClause.toJson();
+      if (classTypeAlias_implementsClause != null)
+        _result["classTypeAlias_implementsClause"] =
+            classTypeAlias_implementsClause.toJson();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+      if (simplyBoundable_isSimplyBounded != false)
+        _result["simplyBoundable_isSimplyBounded"] =
+            simplyBoundable_isSimplyBounded;
+    }
+    if (kind == idl.LinkedNodeKind.comment) {
+      if (comment_references.isNotEmpty)
+        _result["comment_references"] =
+            comment_references.map((_value) => _value.toJson()).toList();
+      if (comment_tokens.isNotEmpty) _result["comment_tokens"] = comment_tokens;
+      if (comment_type != idl.LinkedNodeCommentType.block)
+        _result["comment_type"] = comment_type.toString().split('.')[1];
+    }
+    if (kind == idl.LinkedNodeKind.commentReference) {
+      if (commentReference_identifier != null)
+        _result["commentReference_identifier"] =
+            commentReference_identifier.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.compilationUnit) {
+      if (compilationUnit_declarations.isNotEmpty)
+        _result["compilationUnit_declarations"] = compilationUnit_declarations
+            .map((_value) => _value.toJson())
+            .toList();
+      if (compilationUnit_scriptTag != null)
+        _result["compilationUnit_scriptTag"] =
+            compilationUnit_scriptTag.toJson();
+      if (compilationUnit_directives.isNotEmpty)
+        _result["compilationUnit_directives"] = compilationUnit_directives
+            .map((_value) => _value.toJson())
+            .toList();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.conditionalExpression) {
+      if (conditionalExpression_condition != null)
+        _result["conditionalExpression_condition"] =
+            conditionalExpression_condition.toJson();
+      if (conditionalExpression_elseExpression != null)
+        _result["conditionalExpression_elseExpression"] =
+            conditionalExpression_elseExpression.toJson();
+      if (conditionalExpression_thenExpression != null)
+        _result["conditionalExpression_thenExpression"] =
+            conditionalExpression_thenExpression.toJson();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.configuration) {
+      if (configuration_name != null)
+        _result["configuration_name"] = configuration_name.toJson();
+      if (configuration_value != null)
+        _result["configuration_value"] = configuration_value.toJson();
+      if (configuration_uri != null)
+        _result["configuration_uri"] = configuration_uri.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+      if (constructorDeclaration_initializers.isNotEmpty)
+        _result["constructorDeclaration_initializers"] =
+            constructorDeclaration_initializers
+                .map((_value) => _value.toJson())
+                .toList();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (constructorDeclaration_body != null)
+        _result["constructorDeclaration_body"] =
+            constructorDeclaration_body.toJson();
+      if (constructorDeclaration_parameters != null)
+        _result["constructorDeclaration_parameters"] =
+            constructorDeclaration_parameters.toJson();
+      if (constructorDeclaration_redirectedConstructor != null)
+        _result["constructorDeclaration_redirectedConstructor"] =
+            constructorDeclaration_redirectedConstructor.toJson();
+      if (constructorDeclaration_returnType != null)
+        _result["constructorDeclaration_returnType"] =
+            constructorDeclaration_returnType.toJson();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
+      if (constructorFieldInitializer_expression != null)
+        _result["constructorFieldInitializer_expression"] =
+            constructorFieldInitializer_expression.toJson();
+      if (constructorFieldInitializer_fieldName != null)
+        _result["constructorFieldInitializer_fieldName"] =
+            constructorFieldInitializer_fieldName.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.constructorName) {
+      if (constructorName_name != null)
+        _result["constructorName_name"] = constructorName_name.toJson();
+      if (constructorName_type != null)
+        _result["constructorName_type"] = constructorName_type.toJson();
+      if (constructorName_elementType != null)
+        _result["constructorName_elementType"] =
+            constructorName_elementType.toJson();
+      if (constructorName_element != 0)
+        _result["constructorName_element"] = constructorName_element;
+    }
+    if (kind == idl.LinkedNodeKind.continueStatement) {
+      if (continueStatement_label != null)
+        _result["continueStatement_label"] = continueStatement_label.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.declaredIdentifier) {
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (declaredIdentifier_identifier != null)
+        _result["declaredIdentifier_identifier"] =
+            declaredIdentifier_identifier.toJson();
+      if (declaredIdentifier_type != null)
+        _result["declaredIdentifier_type"] = declaredIdentifier_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+      if (defaultFormalParameter_defaultValue != null)
+        _result["defaultFormalParameter_defaultValue"] =
+            defaultFormalParameter_defaultValue.toJson();
+      if (defaultFormalParameter_parameter != null)
+        _result["defaultFormalParameter_parameter"] =
+            defaultFormalParameter_parameter.toJson();
+      if (defaultFormalParameter_kind !=
+          idl.LinkedNodeFormalParameterKind.requiredPositional)
+        _result["defaultFormalParameter_kind"] =
+            defaultFormalParameter_kind.toString().split('.')[1];
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.doStatement) {
+      if (doStatement_body != null)
+        _result["doStatement_body"] = doStatement_body.toJson();
+      if (doStatement_condition != null)
+        _result["doStatement_condition"] = doStatement_condition.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.dottedName) {
+      if (dottedName_components.isNotEmpty)
+        _result["dottedName_components"] =
+            dottedName_components.map((_value) => _value.toJson()).toList();
+    }
+    if (kind == idl.LinkedNodeKind.doubleLiteral) {
+      if (doubleLiteral_value != 0.0)
+        _result["doubleLiteral_value"] = doubleLiteral_value.isFinite
+            ? doubleLiteral_value
+            : doubleLiteral_value.toString();
+    }
+    if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+      if (emptyFunctionBody_fake != 0)
+        _result["emptyFunctionBody_fake"] = emptyFunctionBody_fake;
+    }
+    if (kind == idl.LinkedNodeKind.emptyStatement) {
+      if (emptyStatement_fake != 0)
+        _result["emptyStatement_fake"] = emptyStatement_fake;
+    }
+    if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.enumDeclaration) {
+      if (enumDeclaration_constants.isNotEmpty)
+        _result["enumDeclaration_constants"] =
+            enumDeclaration_constants.map((_value) => _value.toJson()).toList();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.exportDirective) {
+      if (namespaceDirective_combinators.isNotEmpty)
+        _result["namespaceDirective_combinators"] =
+            namespaceDirective_combinators
+                .map((_value) => _value.toJson())
+                .toList();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (namespaceDirective_configurations.isNotEmpty)
+        _result["namespaceDirective_configurations"] =
+            namespaceDirective_configurations
+                .map((_value) => _value.toJson())
+                .toList();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+      if (uriBasedDirective_uri != null)
+        _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
+      if (namespaceDirective_selectedUri != '')
+        _result["namespaceDirective_selectedUri"] =
+            namespaceDirective_selectedUri;
+      if (uriBasedDirective_uriContent != '')
+        _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
+      if (uriBasedDirective_uriElement != 0)
+        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
+    }
+    if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
+      if (expressionFunctionBody_expression != null)
+        _result["expressionFunctionBody_expression"] =
+            expressionFunctionBody_expression.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.expressionStatement) {
+      if (expressionStatement_expression != null)
+        _result["expressionStatement_expression"] =
+            expressionStatement_expression.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.extendsClause) {
+      if (extendsClause_superclass != null)
+        _result["extendsClause_superclass"] = extendsClause_superclass.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (fieldDeclaration_fields != null)
+        _result["fieldDeclaration_fields"] = fieldDeclaration_fields.toJson();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+      if (actualType != null) _result["actualType"] = actualType.toJson();
+      if (normalFormalParameter_metadata.isNotEmpty)
+        _result["normalFormalParameter_metadata"] =
+            normalFormalParameter_metadata
+                .map((_value) => _value.toJson())
+                .toList();
+      if (fieldFormalParameter_type != null)
+        _result["fieldFormalParameter_type"] =
+            fieldFormalParameter_type.toJson();
+      if (fieldFormalParameter_typeParameters != null)
+        _result["fieldFormalParameter_typeParameters"] =
+            fieldFormalParameter_typeParameters.toJson();
+      if (fieldFormalParameter_formalParameters != null)
+        _result["fieldFormalParameter_formalParameters"] =
+            fieldFormalParameter_formalParameters.toJson();
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
+      if (forEachParts_iterable != null)
+        _result["forEachParts_iterable"] = forEachParts_iterable.toJson();
+      if (forEachPartsWithDeclaration_loopVariable != null)
+        _result["forEachPartsWithDeclaration_loopVariable"] =
+            forEachPartsWithDeclaration_loopVariable.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
+      if (forEachParts_iterable != null)
+        _result["forEachParts_iterable"] = forEachParts_iterable.toJson();
+      if (forEachPartsWithIdentifier_identifier != null)
+        _result["forEachPartsWithIdentifier_identifier"] =
+            forEachPartsWithIdentifier_identifier.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.forElement) {
+      if (forMixin_forLoopParts != null)
+        _result["forMixin_forLoopParts"] = forMixin_forLoopParts.toJson();
+      if (forElement_body != null)
+        _result["forElement_body"] = forElement_body.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
+      if (forParts_condition != null)
+        _result["forParts_condition"] = forParts_condition.toJson();
+      if (forPartsWithDeclarations_variables != null)
+        _result["forPartsWithDeclarations_variables"] =
+            forPartsWithDeclarations_variables.toJson();
+      if (forParts_updaters.isNotEmpty)
+        _result["forParts_updaters"] =
+            forParts_updaters.map((_value) => _value.toJson()).toList();
+    }
+    if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
+      if (forParts_condition != null)
+        _result["forParts_condition"] = forParts_condition.toJson();
+      if (forPartsWithExpression_initialization != null)
+        _result["forPartsWithExpression_initialization"] =
+            forPartsWithExpression_initialization.toJson();
+      if (forParts_updaters.isNotEmpty)
+        _result["forParts_updaters"] =
+            forParts_updaters.map((_value) => _value.toJson()).toList();
+    }
+    if (kind == idl.LinkedNodeKind.forStatement) {
+      if (forMixin_forLoopParts != null)
+        _result["forMixin_forLoopParts"] = forMixin_forLoopParts.toJson();
+      if (forStatement_body != null)
+        _result["forStatement_body"] = forStatement_body.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.formalParameterList) {
+      if (formalParameterList_parameters.isNotEmpty)
+        _result["formalParameterList_parameters"] =
+            formalParameterList_parameters
+                .map((_value) => _value.toJson())
+                .toList();
+    }
     if (kind == idl.LinkedNodeKind.functionDeclaration) {
       if (actualReturnType != null)
         _result["actualReturnType"] = actualReturnType.toJson();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
       if (annotatedNode_metadata.isNotEmpty)
         _result["annotatedNode_metadata"] =
             annotatedNode_metadata.map((_value) => _value.toJson()).toList();
       if (functionDeclaration_functionExpression != null)
         _result["functionDeclaration_functionExpression"] =
             functionDeclaration_functionExpression.toJson();
-      if (functionDeclaration_externalKeyword != 0)
-        _result["functionDeclaration_externalKeyword"] =
-            functionDeclaration_externalKeyword;
       if (functionDeclaration_returnType != null)
         _result["functionDeclaration_returnType"] =
             functionDeclaration_returnType.toJson();
-      if (functionDeclaration_propertyKeyword != 0)
-        _result["functionDeclaration_propertyKeyword"] =
-            functionDeclaration_propertyKeyword;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (namedCompilationUnitMember_name != null)
-        _result["namedCompilationUnitMember_name"] =
-            namedCompilationUnitMember_name.toJson();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
+      if (functionDeclarationStatement_functionDeclaration != null)
+        _result["functionDeclarationStatement_functionDeclaration"] =
+            functionDeclarationStatement_functionDeclaration.toJson();
     }
     if (kind == idl.LinkedNodeKind.functionExpression) {
       if (actualReturnType != null)
@@ -15536,241 +13653,6 @@
         _result["functionExpression_typeParameters"] =
             functionExpression_typeParameters.toJson();
     }
-    if (kind == idl.LinkedNodeKind.functionTypeAlias) {
-      if (actualReturnType != null)
-        _result["actualReturnType"] = actualReturnType.toJson();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (functionTypeAlias_formalParameters != null)
-        _result["functionTypeAlias_formalParameters"] =
-            functionTypeAlias_formalParameters.toJson();
-      if (functionTypeAlias_returnType != null)
-        _result["functionTypeAlias_returnType"] =
-            functionTypeAlias_returnType.toJson();
-      if (functionTypeAlias_typeParameters != null)
-        _result["functionTypeAlias_typeParameters"] =
-            functionTypeAlias_typeParameters.toJson();
-      if (typeAlias_typedefKeyword != 0)
-        _result["typeAlias_typedefKeyword"] = typeAlias_typedefKeyword;
-      if (typeAlias_semicolon != 0)
-        _result["typeAlias_semicolon"] = typeAlias_semicolon;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (namedCompilationUnitMember_name != null)
-        _result["namedCompilationUnitMember_name"] =
-            namedCompilationUnitMember_name.toJson();
-      if (simplyBoundable_isSimplyBounded != false)
-        _result["simplyBoundable_isSimplyBounded"] =
-            simplyBoundable_isSimplyBounded;
-    }
-    if (kind == idl.LinkedNodeKind.genericFunctionType) {
-      if (actualReturnType != null)
-        _result["actualReturnType"] = actualReturnType.toJson();
-      if (genericFunctionType_typeParameters != null)
-        _result["genericFunctionType_typeParameters"] =
-            genericFunctionType_typeParameters.toJson();
-      if (genericFunctionType_functionKeyword != 0)
-        _result["genericFunctionType_functionKeyword"] =
-            genericFunctionType_functionKeyword;
-      if (genericFunctionType_returnType != null)
-        _result["genericFunctionType_returnType"] =
-            genericFunctionType_returnType.toJson();
-      if (genericFunctionType_formalParameters != null)
-        _result["genericFunctionType_formalParameters"] =
-            genericFunctionType_formalParameters.toJson();
-      if (genericFunctionType_question != 0)
-        _result["genericFunctionType_question"] = genericFunctionType_question;
-      if (genericFunctionType_type != null)
-        _result["genericFunctionType_type"] = genericFunctionType_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.methodDeclaration) {
-      if (actualReturnType != null)
-        _result["actualReturnType"] = actualReturnType.toJson();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (methodDeclaration_body != null)
-        _result["methodDeclaration_body"] = methodDeclaration_body.toJson();
-      if (methodDeclaration_externalKeyword != 0)
-        _result["methodDeclaration_externalKeyword"] =
-            methodDeclaration_externalKeyword;
-      if (methodDeclaration_formalParameters != null)
-        _result["methodDeclaration_formalParameters"] =
-            methodDeclaration_formalParameters.toJson();
-      if (methodDeclaration_returnType != null)
-        _result["methodDeclaration_returnType"] =
-            methodDeclaration_returnType.toJson();
-      if (methodDeclaration_modifierKeyword != 0)
-        _result["methodDeclaration_modifierKeyword"] =
-            methodDeclaration_modifierKeyword;
-      if (methodDeclaration_operatorKeyword != 0)
-        _result["methodDeclaration_operatorKeyword"] =
-            methodDeclaration_operatorKeyword;
-      if (methodDeclaration_propertyKeyword != 0)
-        _result["methodDeclaration_propertyKeyword"] =
-            methodDeclaration_propertyKeyword;
-      if (methodDeclaration_actualProperty != 0)
-        _result["methodDeclaration_actualProperty"] =
-            methodDeclaration_actualProperty;
-      if (methodDeclaration_typeParameters != null)
-        _result["methodDeclaration_typeParameters"] =
-            methodDeclaration_typeParameters.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (methodDeclaration_name != null)
-        _result["methodDeclaration_name"] = methodDeclaration_name.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
-      if (actualType != null) _result["actualType"] = actualType.toJson();
-      if (normalFormalParameter_metadata.isNotEmpty)
-        _result["normalFormalParameter_metadata"] =
-            normalFormalParameter_metadata
-                .map((_value) => _value.toJson())
-                .toList();
-      if (fieldFormalParameter_type != null)
-        _result["fieldFormalParameter_type"] =
-            fieldFormalParameter_type.toJson();
-      if (fieldFormalParameter_keyword != 0)
-        _result["fieldFormalParameter_keyword"] = fieldFormalParameter_keyword;
-      if (fieldFormalParameter_typeParameters != null)
-        _result["fieldFormalParameter_typeParameters"] =
-            fieldFormalParameter_typeParameters.toJson();
-      if (fieldFormalParameter_formalParameters != null)
-        _result["fieldFormalParameter_formalParameters"] =
-            fieldFormalParameter_formalParameters.toJson();
-      if (fieldFormalParameter_period != 0)
-        _result["fieldFormalParameter_period"] = fieldFormalParameter_period;
-      if (fieldFormalParameter_thisKeyword != 0)
-        _result["fieldFormalParameter_thisKeyword"] =
-            fieldFormalParameter_thisKeyword;
-      if (normalFormalParameter_covariantKeyword != 0)
-        _result["normalFormalParameter_covariantKeyword"] =
-            normalFormalParameter_covariantKeyword;
-      if (normalFormalParameter_isCovariant != false)
-        _result["normalFormalParameter_isCovariant"] =
-            normalFormalParameter_isCovariant;
-      if (normalFormalParameter_identifier != null)
-        _result["normalFormalParameter_identifier"] =
-            normalFormalParameter_identifier.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (formalParameter_kind != idl.LinkedNodeFormalParameterKind.required)
-        _result["formalParameter_kind"] =
-            formalParameter_kind.toString().split('.')[1];
-      if (normalFormalParameter_comment != null)
-        _result["normalFormalParameter_comment"] =
-            normalFormalParameter_comment.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
-      if (actualType != null) _result["actualType"] = actualType.toJson();
-      if (normalFormalParameter_metadata.isNotEmpty)
-        _result["normalFormalParameter_metadata"] =
-            normalFormalParameter_metadata
-                .map((_value) => _value.toJson())
-                .toList();
-      if (functionTypedFormalParameter_formalParameters != null)
-        _result["functionTypedFormalParameter_formalParameters"] =
-            functionTypedFormalParameter_formalParameters.toJson();
-      if (functionTypedFormalParameter_returnType != null)
-        _result["functionTypedFormalParameter_returnType"] =
-            functionTypedFormalParameter_returnType.toJson();
-      if (functionTypedFormalParameter_typeParameters != null)
-        _result["functionTypedFormalParameter_typeParameters"] =
-            functionTypedFormalParameter_typeParameters.toJson();
-      if (normalFormalParameter_covariantKeyword != 0)
-        _result["normalFormalParameter_covariantKeyword"] =
-            normalFormalParameter_covariantKeyword;
-      if (normalFormalParameter_isCovariant != false)
-        _result["normalFormalParameter_isCovariant"] =
-            normalFormalParameter_isCovariant;
-      if (normalFormalParameter_identifier != null)
-        _result["normalFormalParameter_identifier"] =
-            normalFormalParameter_identifier.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (formalParameter_kind != idl.LinkedNodeFormalParameterKind.required)
-        _result["formalParameter_kind"] =
-            formalParameter_kind.toString().split('.')[1];
-      if (normalFormalParameter_comment != null)
-        _result["normalFormalParameter_comment"] =
-            normalFormalParameter_comment.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
-      if (actualType != null) _result["actualType"] = actualType.toJson();
-      if (normalFormalParameter_metadata.isNotEmpty)
-        _result["normalFormalParameter_metadata"] =
-            normalFormalParameter_metadata
-                .map((_value) => _value.toJson())
-                .toList();
-      if (simpleFormalParameter_type != null)
-        _result["simpleFormalParameter_type"] =
-            simpleFormalParameter_type.toJson();
-      if (simpleFormalParameter_keyword != 0)
-        _result["simpleFormalParameter_keyword"] =
-            simpleFormalParameter_keyword;
-      if (normalFormalParameter_covariantKeyword != 0)
-        _result["normalFormalParameter_covariantKeyword"] =
-            normalFormalParameter_covariantKeyword;
-      if (normalFormalParameter_isCovariant != false)
-        _result["normalFormalParameter_isCovariant"] =
-            normalFormalParameter_isCovariant;
-      if (normalFormalParameter_identifier != null)
-        _result["normalFormalParameter_identifier"] =
-            normalFormalParameter_identifier.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (formalParameter_kind != idl.LinkedNodeFormalParameterKind.required)
-        _result["formalParameter_kind"] =
-            formalParameter_kind.toString().split('.')[1];
-      if (normalFormalParameter_comment != null)
-        _result["normalFormalParameter_comment"] =
-            normalFormalParameter_comment.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.variableDeclaration) {
-      if (actualType != null) _result["actualType"] = actualType.toJson();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (variableDeclaration_initializer != null)
-        _result["variableDeclaration_initializer"] =
-            variableDeclaration_initializer.toJson();
-      if (variableDeclaration_equals != 0)
-        _result["variableDeclaration_equals"] = variableDeclaration_equals;
-      if (variableDeclaration_name != null)
-        _result["variableDeclaration_name"] = variableDeclaration_name.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (variableDeclaration_declaration != null)
-        _result["variableDeclaration_declaration"] =
-            variableDeclaration_declaration.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.binaryExpression) {
-      if (binaryExpression_invokeType != null)
-        _result["binaryExpression_invokeType"] =
-            binaryExpression_invokeType.toJson();
-      if (binaryExpression_leftOperand != null)
-        _result["binaryExpression_leftOperand"] =
-            binaryExpression_leftOperand.toJson();
-      if (binaryExpression_element != 0)
-        _result["binaryExpression_element"] = binaryExpression_element;
-      if (binaryExpression_rightOperand != null)
-        _result["binaryExpression_rightOperand"] =
-            binaryExpression_rightOperand.toJson();
-      if (binaryExpression_operator != 0)
-        _result["binaryExpression_operator"] = binaryExpression_operator;
-      if (binaryExpression_elementType != null)
-        _result["binaryExpression_elementType"] =
-            binaryExpression_elementType.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
     if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
       if (invocationExpression_invokeType != null)
         _result["invocationExpression_invokeType"] =
@@ -15787,6 +13669,246 @@
         _result["invocationExpression_arguments"] =
             invocationExpression_arguments.toJson();
     }
+    if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+      if (actualReturnType != null)
+        _result["actualReturnType"] = actualReturnType.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (functionTypeAlias_formalParameters != null)
+        _result["functionTypeAlias_formalParameters"] =
+            functionTypeAlias_formalParameters.toJson();
+      if (functionTypeAlias_returnType != null)
+        _result["functionTypeAlias_returnType"] =
+            functionTypeAlias_returnType.toJson();
+      if (functionTypeAlias_typeParameters != null)
+        _result["functionTypeAlias_typeParameters"] =
+            functionTypeAlias_typeParameters.toJson();
+      if (typeAlias_hasSelfReference != false)
+        _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+      if (simplyBoundable_isSimplyBounded != false)
+        _result["simplyBoundable_isSimplyBounded"] =
+            simplyBoundable_isSimplyBounded;
+    }
+    if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+      if (actualType != null) _result["actualType"] = actualType.toJson();
+      if (normalFormalParameter_metadata.isNotEmpty)
+        _result["normalFormalParameter_metadata"] =
+            normalFormalParameter_metadata
+                .map((_value) => _value.toJson())
+                .toList();
+      if (functionTypedFormalParameter_formalParameters != null)
+        _result["functionTypedFormalParameter_formalParameters"] =
+            functionTypedFormalParameter_formalParameters.toJson();
+      if (functionTypedFormalParameter_returnType != null)
+        _result["functionTypedFormalParameter_returnType"] =
+            functionTypedFormalParameter_returnType.toJson();
+      if (functionTypedFormalParameter_typeParameters != null)
+        _result["functionTypedFormalParameter_typeParameters"] =
+            functionTypedFormalParameter_typeParameters.toJson();
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.genericFunctionType) {
+      if (actualReturnType != null)
+        _result["actualReturnType"] = actualReturnType.toJson();
+      if (genericFunctionType_typeParameters != null)
+        _result["genericFunctionType_typeParameters"] =
+            genericFunctionType_typeParameters.toJson();
+      if (genericFunctionType_returnType != null)
+        _result["genericFunctionType_returnType"] =
+            genericFunctionType_returnType.toJson();
+      if (genericFunctionType_id != 0)
+        _result["genericFunctionType_id"] = genericFunctionType_id;
+      if (genericFunctionType_formalParameters != null)
+        _result["genericFunctionType_formalParameters"] =
+            genericFunctionType_formalParameters.toJson();
+      if (genericFunctionType_type != null)
+        _result["genericFunctionType_type"] = genericFunctionType_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (genericTypeAlias_typeParameters != null)
+        _result["genericTypeAlias_typeParameters"] =
+            genericTypeAlias_typeParameters.toJson();
+      if (genericTypeAlias_functionType != null)
+        _result["genericTypeAlias_functionType"] =
+            genericTypeAlias_functionType.toJson();
+      if (typeAlias_hasSelfReference != false)
+        _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+      if (simplyBoundable_isSimplyBounded != false)
+        _result["simplyBoundable_isSimplyBounded"] =
+            simplyBoundable_isSimplyBounded;
+    }
+    if (kind == idl.LinkedNodeKind.hideCombinator) {
+      if (names.isNotEmpty) _result["names"] = names;
+    }
+    if (kind == idl.LinkedNodeKind.ifElement) {
+      if (ifMixin_condition != null)
+        _result["ifMixin_condition"] = ifMixin_condition.toJson();
+      if (ifElement_thenElement != null)
+        _result["ifElement_thenElement"] = ifElement_thenElement.toJson();
+      if (ifElement_elseElement != null)
+        _result["ifElement_elseElement"] = ifElement_elseElement.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.ifStatement) {
+      if (ifMixin_condition != null)
+        _result["ifMixin_condition"] = ifMixin_condition.toJson();
+      if (ifStatement_elseStatement != null)
+        _result["ifStatement_elseStatement"] =
+            ifStatement_elseStatement.toJson();
+      if (ifStatement_thenStatement != null)
+        _result["ifStatement_thenStatement"] =
+            ifStatement_thenStatement.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.implementsClause) {
+      if (implementsClause_interfaces.isNotEmpty)
+        _result["implementsClause_interfaces"] = implementsClause_interfaces
+            .map((_value) => _value.toJson())
+            .toList();
+    }
+    if (kind == idl.LinkedNodeKind.importDirective) {
+      if (namespaceDirective_combinators.isNotEmpty)
+        _result["namespaceDirective_combinators"] =
+            namespaceDirective_combinators
+                .map((_value) => _value.toJson())
+                .toList();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (importDirective_prefixOffset != 0)
+        _result["importDirective_prefixOffset"] = importDirective_prefixOffset;
+      if (namespaceDirective_configurations.isNotEmpty)
+        _result["namespaceDirective_configurations"] =
+            namespaceDirective_configurations
+                .map((_value) => _value.toJson())
+                .toList();
+      if (importDirective_prefix != '')
+        _result["importDirective_prefix"] = importDirective_prefix;
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+      if (uriBasedDirective_uri != null)
+        _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
+      if (namespaceDirective_selectedUri != '')
+        _result["namespaceDirective_selectedUri"] =
+            namespaceDirective_selectedUri;
+      if (uriBasedDirective_uriContent != '')
+        _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
+      if (uriBasedDirective_uriElement != 0)
+        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
+    }
+    if (kind == idl.LinkedNodeKind.indexExpression) {
+      if (indexExpression_index != null)
+        _result["indexExpression_index"] = indexExpression_index.toJson();
+      if (indexExpression_target != null)
+        _result["indexExpression_target"] = indexExpression_target.toJson();
+      if (indexExpression_elementType != null)
+        _result["indexExpression_elementType"] =
+            indexExpression_elementType.toJson();
+      if (indexExpression_element != 0)
+        _result["indexExpression_element"] = indexExpression_element;
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+      if (instanceCreationExpression_arguments.isNotEmpty)
+        _result["instanceCreationExpression_arguments"] =
+            instanceCreationExpression_arguments
+                .map((_value) => _value.toJson())
+                .toList();
+      if (instanceCreationExpression_constructorName != null)
+        _result["instanceCreationExpression_constructorName"] =
+            instanceCreationExpression_constructorName.toJson();
+      if (instanceCreationExpression_typeArguments != null)
+        _result["instanceCreationExpression_typeArguments"] =
+            instanceCreationExpression_typeArguments.toJson();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.integerLiteral) {
+      if (integerLiteral_value != 0)
+        _result["integerLiteral_value"] = integerLiteral_value;
+    }
+    if (kind == idl.LinkedNodeKind.interpolationExpression) {
+      if (interpolationExpression_expression != null)
+        _result["interpolationExpression_expression"] =
+            interpolationExpression_expression.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.interpolationString) {
+      if (interpolationString_value != '')
+        _result["interpolationString_value"] = interpolationString_value;
+    }
+    if (kind == idl.LinkedNodeKind.isExpression) {
+      if (isExpression_expression != null)
+        _result["isExpression_expression"] = isExpression_expression.toJson();
+      if (isExpression_type != null)
+        _result["isExpression_type"] = isExpression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.label) {
+      if (label_label != null) _result["label_label"] = label_label.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.labeledStatement) {
+      if (labeledStatement_labels.isNotEmpty)
+        _result["labeledStatement_labels"] =
+            labeledStatement_labels.map((_value) => _value.toJson()).toList();
+      if (labeledStatement_statement != null)
+        _result["labeledStatement_statement"] =
+            labeledStatement_statement.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.libraryDirective) {
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (libraryDirective_name != null)
+        _result["libraryDirective_name"] = libraryDirective_name.toJson();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+      if (libraryIdentifier_components.isNotEmpty)
+        _result["libraryIdentifier_components"] = libraryIdentifier_components
+            .map((_value) => _value.toJson())
+            .toList();
+    }
+    if (kind == idl.LinkedNodeKind.listLiteral) {
+      if (typedLiteral_typeArguments.isNotEmpty)
+        _result["typedLiteral_typeArguments"] = typedLiteral_typeArguments
+            .map((_value) => _value.toJson())
+            .toList();
+      if (listLiteral_elements.isNotEmpty)
+        _result["listLiteral_elements"] =
+            listLiteral_elements.map((_value) => _value.toJson()).toList();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
+      if (mapLiteralEntry_key != null)
+        _result["mapLiteralEntry_key"] = mapLiteralEntry_key.toJson();
+      if (mapLiteralEntry_value != null)
+        _result["mapLiteralEntry_value"] = mapLiteralEntry_value.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.methodDeclaration) {
+      if (actualReturnType != null)
+        _result["actualReturnType"] = actualReturnType.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (methodDeclaration_body != null)
+        _result["methodDeclaration_body"] = methodDeclaration_body.toJson();
+      if (methodDeclaration_formalParameters != null)
+        _result["methodDeclaration_formalParameters"] =
+            methodDeclaration_formalParameters.toJson();
+      if (methodDeclaration_returnType != null)
+        _result["methodDeclaration_returnType"] =
+            methodDeclaration_returnType.toJson();
+      if (methodDeclaration_typeParameters != null)
+        _result["methodDeclaration_typeParameters"] =
+            methodDeclaration_typeParameters.toJson();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
     if (kind == idl.LinkedNodeKind.methodInvocation) {
       if (invocationExpression_invokeType != null)
         _result["invocationExpression_invokeType"] =
@@ -15794,8 +13916,6 @@
       if (methodInvocation_methodName != null)
         _result["methodInvocation_methodName"] =
             methodInvocation_methodName.toJson();
-      if (methodInvocation_operator != 0)
-        _result["methodInvocation_operator"] = methodInvocation_operator;
       if (methodInvocation_target != null)
         _result["methodInvocation_target"] = methodInvocation_target.toJson();
       if (invocationExpression_typeArguments != null)
@@ -15807,615 +13927,80 @@
         _result["invocationExpression_arguments"] =
             invocationExpression_arguments.toJson();
     }
-    if (kind == idl.LinkedNodeKind.adjacentStrings) {
-      if (adjacentStrings_strings.isNotEmpty)
-        _result["adjacentStrings_strings"] =
-            adjacentStrings_strings.map((_value) => _value.toJson()).toList();
+    if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (mixinDeclaration_onClause != null)
+        _result["mixinDeclaration_onClause"] =
+            mixinDeclaration_onClause.toJson();
+      if (classOrMixinDeclaration_implementsClause != null)
+        _result["classOrMixinDeclaration_implementsClause"] =
+            classOrMixinDeclaration_implementsClause.toJson();
+      if (classOrMixinDeclaration_members.isNotEmpty)
+        _result["classOrMixinDeclaration_members"] =
+            classOrMixinDeclaration_members
+                .map((_value) => _value.toJson())
+                .toList();
+      if (classOrMixinDeclaration_typeParameters != null)
+        _result["classOrMixinDeclaration_typeParameters"] =
+            classOrMixinDeclaration_typeParameters.toJson();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+      if (mixinDeclaration_superInvokedNames.isNotEmpty)
+        _result["mixinDeclaration_superInvokedNames"] =
+            mixinDeclaration_superInvokedNames;
+      if (simplyBoundable_isSimplyBounded != false)
+        _result["simplyBoundable_isSimplyBounded"] =
+            simplyBoundable_isSimplyBounded;
+    }
+    if (kind == idl.LinkedNodeKind.namedExpression) {
+      if (namedExpression_expression != null)
+        _result["namedExpression_expression"] =
+            namedExpression_expression.toJson();
+      if (namedExpression_name != null)
+        _result["namedExpression_name"] = namedExpression_name.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.nativeClause) {
+      if (nativeClause_name != null)
+        _result["nativeClause_name"] = nativeClause_name.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
+      if (nativeFunctionBody_stringLiteral != null)
+        _result["nativeFunctionBody_stringLiteral"] =
+            nativeFunctionBody_stringLiteral.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.nullLiteral) {
+      if (nullLiteral_fake != 0) _result["nullLiteral_fake"] = nullLiteral_fake;
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
-    if (kind == idl.LinkedNodeKind.argumentList) {
-      if (argumentList_arguments.isNotEmpty)
-        _result["argumentList_arguments"] =
-            argumentList_arguments.map((_value) => _value.toJson()).toList();
-      if (argumentList_leftParenthesis != 0)
-        _result["argumentList_leftParenthesis"] = argumentList_leftParenthesis;
-      if (argumentList_rightParenthesis != 0)
-        _result["argumentList_rightParenthesis"] =
-            argumentList_rightParenthesis;
-    }
-    if (kind == idl.LinkedNodeKind.block) {
-      if (block_statements.isNotEmpty)
-        _result["block_statements"] =
-            block_statements.map((_value) => _value.toJson()).toList();
-      if (block_leftBracket != 0)
-        _result["block_leftBracket"] = block_leftBracket;
-      if (block_rightBracket != 0)
-        _result["block_rightBracket"] = block_rightBracket;
-    }
-    if (kind == idl.LinkedNodeKind.cascadeExpression) {
-      if (cascadeExpression_sections.isNotEmpty)
-        _result["cascadeExpression_sections"] = cascadeExpression_sections
-            .map((_value) => _value.toJson())
-            .toList();
-      if (cascadeExpression_target != null)
-        _result["cascadeExpression_target"] = cascadeExpression_target.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.compilationUnit) {
-      if (compilationUnit_declarations.isNotEmpty)
-        _result["compilationUnit_declarations"] = compilationUnit_declarations
-            .map((_value) => _value.toJson())
-            .toList();
-      if (compilationUnit_scriptTag != null)
-        _result["compilationUnit_scriptTag"] =
-            compilationUnit_scriptTag.toJson();
-      if (compilationUnit_beginToken != 0)
-        _result["compilationUnit_beginToken"] = compilationUnit_beginToken;
-      if (compilationUnit_endToken != 0)
-        _result["compilationUnit_endToken"] = compilationUnit_endToken;
-      if (compilationUnit_directives.isNotEmpty)
-        _result["compilationUnit_directives"] = compilationUnit_directives
-            .map((_value) => _value.toJson())
-            .toList();
-    }
-    if (kind == idl.LinkedNodeKind.constructorDeclaration) {
-      if (constructorDeclaration_initializers.isNotEmpty)
-        _result["constructorDeclaration_initializers"] =
-            constructorDeclaration_initializers
-                .map((_value) => _value.toJson())
-                .toList();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (constructorDeclaration_body != null)
-        _result["constructorDeclaration_body"] =
-            constructorDeclaration_body.toJson();
-      if (constructorDeclaration_constKeyword != 0)
-        _result["constructorDeclaration_constKeyword"] =
-            constructorDeclaration_constKeyword;
-      if (constructorDeclaration_name != null)
-        _result["constructorDeclaration_name"] =
-            constructorDeclaration_name.toJson();
-      if (constructorDeclaration_parameters != null)
-        _result["constructorDeclaration_parameters"] =
-            constructorDeclaration_parameters.toJson();
-      if (constructorDeclaration_externalKeyword != 0)
-        _result["constructorDeclaration_externalKeyword"] =
-            constructorDeclaration_externalKeyword;
-      if (constructorDeclaration_factoryKeyword != 0)
-        _result["constructorDeclaration_factoryKeyword"] =
-            constructorDeclaration_factoryKeyword;
-      if (constructorDeclaration_period != 0)
-        _result["constructorDeclaration_period"] =
-            constructorDeclaration_period;
-      if (constructorDeclaration_separator != 0)
-        _result["constructorDeclaration_separator"] =
-            constructorDeclaration_separator;
-      if (constructorDeclaration_redirectedConstructor != null)
-        _result["constructorDeclaration_redirectedConstructor"] =
-            constructorDeclaration_redirectedConstructor.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (constructorDeclaration_returnType != null)
-        _result["constructorDeclaration_returnType"] =
-            constructorDeclaration_returnType.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.dottedName) {
-      if (dottedName_components.isNotEmpty)
-        _result["dottedName_components"] =
-            dottedName_components.map((_value) => _value.toJson()).toList();
-    }
-    if (kind == idl.LinkedNodeKind.enumDeclaration) {
-      if (enumDeclaration_constants.isNotEmpty)
-        _result["enumDeclaration_constants"] =
-            enumDeclaration_constants.map((_value) => _value.toJson()).toList();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (enumDeclaration_enumKeyword != 0)
-        _result["enumDeclaration_enumKeyword"] = enumDeclaration_enumKeyword;
-      if (enumDeclaration_leftBracket != 0)
-        _result["enumDeclaration_leftBracket"] = enumDeclaration_leftBracket;
-      if (enumDeclaration_rightBracket != 0)
-        _result["enumDeclaration_rightBracket"] = enumDeclaration_rightBracket;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (namedCompilationUnitMember_name != null)
-        _result["namedCompilationUnitMember_name"] =
-            namedCompilationUnitMember_name.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.formalParameterList) {
-      if (formalParameterList_parameters.isNotEmpty)
-        _result["formalParameterList_parameters"] =
-            formalParameterList_parameters
-                .map((_value) => _value.toJson())
-                .toList();
-      if (formalParameterList_leftDelimiter != 0)
-        _result["formalParameterList_leftDelimiter"] =
-            formalParameterList_leftDelimiter;
-      if (formalParameterList_leftParenthesis != 0)
-        _result["formalParameterList_leftParenthesis"] =
-            formalParameterList_leftParenthesis;
-      if (formalParameterList_rightDelimiter != 0)
-        _result["formalParameterList_rightDelimiter"] =
-            formalParameterList_rightDelimiter;
-      if (formalParameterList_rightParenthesis != 0)
-        _result["formalParameterList_rightParenthesis"] =
-            formalParameterList_rightParenthesis;
-    }
-    if (kind == idl.LinkedNodeKind.hideCombinator) {
-      if (hideCombinator_hiddenNames.isNotEmpty)
-        _result["hideCombinator_hiddenNames"] = hideCombinator_hiddenNames
-            .map((_value) => _value.toJson())
-            .toList();
-      if (combinator_keyword != 0)
-        _result["combinator_keyword"] = combinator_keyword;
-    }
-    if (kind == idl.LinkedNodeKind.implementsClause) {
-      if (implementsClause_interfaces.isNotEmpty)
-        _result["implementsClause_interfaces"] = implementsClause_interfaces
-            .map((_value) => _value.toJson())
-            .toList();
-      if (implementsClause_implementsKeyword != 0)
-        _result["implementsClause_implementsKeyword"] =
-            implementsClause_implementsKeyword;
-    }
-    if (kind == idl.LinkedNodeKind.labeledStatement) {
-      if (labeledStatement_labels.isNotEmpty)
-        _result["labeledStatement_labels"] =
-            labeledStatement_labels.map((_value) => _value.toJson()).toList();
-      if (labeledStatement_statement != null)
-        _result["labeledStatement_statement"] =
-            labeledStatement_statement.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.libraryIdentifier) {
-      if (libraryIdentifier_components.isNotEmpty)
-        _result["libraryIdentifier_components"] = libraryIdentifier_components
-            .map((_value) => _value.toJson())
-            .toList();
-    }
-    if (kind == idl.LinkedNodeKind.listLiteral) {
-      if (listLiteral_elements.isNotEmpty)
-        _result["listLiteral_elements"] =
-            listLiteral_elements.map((_value) => _value.toJson()).toList();
-      if (listLiteral_leftBracket != 0)
-        _result["listLiteral_leftBracket"] = listLiteral_leftBracket;
-      if (listLiteral_rightBracket != 0)
-        _result["listLiteral_rightBracket"] = listLiteral_rightBracket;
-      if (typedLiteral_constKeyword != 0)
-        _result["typedLiteral_constKeyword"] = typedLiteral_constKeyword;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-      if (typedLiteral_typeArguments != null)
-        _result["typedLiteral_typeArguments"] =
-            typedLiteral_typeArguments.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.exportDirective) {
-      if (namespaceDirective_combinators.isNotEmpty)
-        _result["namespaceDirective_combinators"] =
-            namespaceDirective_combinators
-                .map((_value) => _value.toJson())
-                .toList();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (directive_keyword != 0)
-        _result["directive_keyword"] = directive_keyword;
-      if (uriBasedDirective_uriElement != 0)
-        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
-      if (directive_semicolon != 0)
-        _result["directive_semicolon"] = directive_semicolon;
-      if (namespaceDirective_configurations.isNotEmpty)
-        _result["namespaceDirective_configurations"] =
-            namespaceDirective_configurations
-                .map((_value) => _value.toJson())
-                .toList();
-      if (uriBasedDirective_uri != null)
-        _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
-      if (namespaceDirective_selectedUri != '')
-        _result["namespaceDirective_selectedUri"] =
-            namespaceDirective_selectedUri;
-      if (uriBasedDirective_uriContent != '')
-        _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
-    }
-    if (kind == idl.LinkedNodeKind.importDirective) {
-      if (namespaceDirective_combinators.isNotEmpty)
-        _result["namespaceDirective_combinators"] =
-            namespaceDirective_combinators
-                .map((_value) => _value.toJson())
-                .toList();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (importDirective_prefix != null)
-        _result["importDirective_prefix"] = importDirective_prefix.toJson();
-      if (importDirective_asKeyword != 0)
-        _result["importDirective_asKeyword"] = importDirective_asKeyword;
-      if (importDirective_deferredKeyword != 0)
-        _result["importDirective_deferredKeyword"] =
-            importDirective_deferredKeyword;
-      if (directive_keyword != 0)
-        _result["directive_keyword"] = directive_keyword;
-      if (uriBasedDirective_uriElement != 0)
-        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
-      if (directive_semicolon != 0)
-        _result["directive_semicolon"] = directive_semicolon;
-      if (namespaceDirective_configurations.isNotEmpty)
-        _result["namespaceDirective_configurations"] =
-            namespaceDirective_configurations
-                .map((_value) => _value.toJson())
-                .toList();
-      if (uriBasedDirective_uri != null)
-        _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
-      if (namespaceDirective_selectedUri != '')
-        _result["namespaceDirective_selectedUri"] =
-            namespaceDirective_selectedUri;
-      if (uriBasedDirective_uriContent != '')
-        _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
-    }
     if (kind == idl.LinkedNodeKind.onClause) {
       if (onClause_superclassConstraints.isNotEmpty)
         _result["onClause_superclassConstraints"] =
             onClause_superclassConstraints
                 .map((_value) => _value.toJson())
                 .toList();
-      if (onClause_onKeyword != 0)
-        _result["onClause_onKeyword"] = onClause_onKeyword;
     }
-    if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
-      if (setOrMapLiteral_elements.isNotEmpty)
-        _result["setOrMapLiteral_elements"] =
-            setOrMapLiteral_elements.map((_value) => _value.toJson()).toList();
-      if (setOrMapLiteral_leftBracket != 0)
-        _result["setOrMapLiteral_leftBracket"] = setOrMapLiteral_leftBracket;
-      if (setOrMapLiteral_rightBracket != 0)
-        _result["setOrMapLiteral_rightBracket"] = setOrMapLiteral_rightBracket;
-      if (typedLiteral_constKeyword != 0)
-        _result["typedLiteral_constKeyword"] = typedLiteral_constKeyword;
-      if (setOrMapLiteral_isMap != false)
-        _result["setOrMapLiteral_isMap"] = setOrMapLiteral_isMap;
+    if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
+      if (parenthesizedExpression_expression != null)
+        _result["parenthesizedExpression_expression"] =
+            parenthesizedExpression_expression.toJson();
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
-      if (typedLiteral_typeArguments != null)
-        _result["typedLiteral_typeArguments"] =
-            typedLiteral_typeArguments.toJson();
-      if (setOrMapLiteral_isSet != false)
-        _result["setOrMapLiteral_isSet"] = setOrMapLiteral_isSet;
-    }
-    if (kind == idl.LinkedNodeKind.showCombinator) {
-      if (showCombinator_shownNames.isNotEmpty)
-        _result["showCombinator_shownNames"] =
-            showCombinator_shownNames.map((_value) => _value.toJson()).toList();
-      if (combinator_keyword != 0)
-        _result["combinator_keyword"] = combinator_keyword;
-    }
-    if (kind == idl.LinkedNodeKind.stringInterpolation) {
-      if (stringInterpolation_elements.isNotEmpty)
-        _result["stringInterpolation_elements"] = stringInterpolation_elements
-            .map((_value) => _value.toJson())
-            .toList();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.switchStatement) {
-      if (switchStatement_members.isNotEmpty)
-        _result["switchStatement_members"] =
-            switchStatement_members.map((_value) => _value.toJson()).toList();
-      if (switchStatement_leftParenthesis != 0)
-        _result["switchStatement_leftParenthesis"] =
-            switchStatement_leftParenthesis;
-      if (switchStatement_expression != null)
-        _result["switchStatement_expression"] =
-            switchStatement_expression.toJson();
-      if (switchStatement_rightParenthesis != 0)
-        _result["switchStatement_rightParenthesis"] =
-            switchStatement_rightParenthesis;
-      if (switchStatement_switchKeyword != 0)
-        _result["switchStatement_switchKeyword"] =
-            switchStatement_switchKeyword;
-      if (switchStatement_leftBracket != 0)
-        _result["switchStatement_leftBracket"] = switchStatement_leftBracket;
-      if (switchStatement_rightBracket != 0)
-        _result["switchStatement_rightBracket"] = switchStatement_rightBracket;
-    }
-    if (kind == idl.LinkedNodeKind.tryStatement) {
-      if (tryStatement_catchClauses.isNotEmpty)
-        _result["tryStatement_catchClauses"] =
-            tryStatement_catchClauses.map((_value) => _value.toJson()).toList();
-      if (tryStatement_body != null)
-        _result["tryStatement_body"] = tryStatement_body.toJson();
-      if (tryStatement_finallyKeyword != 0)
-        _result["tryStatement_finallyKeyword"] = tryStatement_finallyKeyword;
-      if (tryStatement_finallyBlock != null)
-        _result["tryStatement_finallyBlock"] =
-            tryStatement_finallyBlock.toJson();
-      if (tryStatement_tryKeyword != 0)
-        _result["tryStatement_tryKeyword"] = tryStatement_tryKeyword;
-    }
-    if (kind == idl.LinkedNodeKind.typeArgumentList) {
-      if (typeArgumentList_arguments.isNotEmpty)
-        _result["typeArgumentList_arguments"] = typeArgumentList_arguments
-            .map((_value) => _value.toJson())
-            .toList();
-      if (typeArgumentList_leftBracket != 0)
-        _result["typeArgumentList_leftBracket"] = typeArgumentList_leftBracket;
-      if (typeArgumentList_rightBracket != 0)
-        _result["typeArgumentList_rightBracket"] =
-            typeArgumentList_rightBracket;
-    }
-    if (kind == idl.LinkedNodeKind.typeParameterList) {
-      if (typeParameterList_typeParameters.isNotEmpty)
-        _result["typeParameterList_typeParameters"] =
-            typeParameterList_typeParameters
-                .map((_value) => _value.toJson())
-                .toList();
-      if (typeParameterList_leftBracket != 0)
-        _result["typeParameterList_leftBracket"] =
-            typeParameterList_leftBracket;
-      if (typeParameterList_rightBracket != 0)
-        _result["typeParameterList_rightBracket"] =
-            typeParameterList_rightBracket;
-    }
-    if (kind == idl.LinkedNodeKind.variableDeclarationList) {
-      if (variableDeclarationList_variables.isNotEmpty)
-        _result["variableDeclarationList_variables"] =
-            variableDeclarationList_variables
-                .map((_value) => _value.toJson())
-                .toList();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (variableDeclarationList_type != null)
-        _result["variableDeclarationList_type"] =
-            variableDeclarationList_type.toJson();
-      if (variableDeclarationList_keyword != 0)
-        _result["variableDeclarationList_keyword"] =
-            variableDeclarationList_keyword;
-    }
-    if (kind == idl.LinkedNodeKind.withClause) {
-      if (withClause_mixinTypes.isNotEmpty)
-        _result["withClause_mixinTypes"] =
-            withClause_mixinTypes.map((_value) => _value.toJson()).toList();
-      if (withClause_withKeyword != 0)
-        _result["withClause_withKeyword"] = withClause_withKeyword;
-    }
-    if (kind == idl.LinkedNodeKind.classDeclaration) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (classDeclaration_extendsClause != null)
-        _result["classDeclaration_extendsClause"] =
-            classDeclaration_extendsClause.toJson();
-      if (classDeclaration_abstractKeyword != 0)
-        _result["classDeclaration_abstractKeyword"] =
-            classDeclaration_abstractKeyword;
-      if (classDeclaration_withClause != null)
-        _result["classDeclaration_withClause"] =
-            classDeclaration_withClause.toJson();
-      if (classDeclaration_nativeClause != null)
-        _result["classDeclaration_nativeClause"] =
-            classDeclaration_nativeClause.toJson();
-      if (classDeclaration_classKeyword != 0)
-        _result["classDeclaration_classKeyword"] =
-            classDeclaration_classKeyword;
-      if (classOrMixinDeclaration_rightBracket != 0)
-        _result["classOrMixinDeclaration_rightBracket"] =
-            classOrMixinDeclaration_rightBracket;
-      if (classOrMixinDeclaration_leftBracket != 0)
-        _result["classOrMixinDeclaration_leftBracket"] =
-            classOrMixinDeclaration_leftBracket;
-      if (classDeclaration_isDartObject != false)
-        _result["classDeclaration_isDartObject"] =
-            classDeclaration_isDartObject;
-      if (classOrMixinDeclaration_implementsClause != null)
-        _result["classOrMixinDeclaration_implementsClause"] =
-            classOrMixinDeclaration_implementsClause.toJson();
-      if (classOrMixinDeclaration_members.isNotEmpty)
-        _result["classOrMixinDeclaration_members"] =
-            classOrMixinDeclaration_members
-                .map((_value) => _value.toJson())
-                .toList();
-      if (classOrMixinDeclaration_typeParameters != null)
-        _result["classOrMixinDeclaration_typeParameters"] =
-            classOrMixinDeclaration_typeParameters.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (namedCompilationUnitMember_name != null)
-        _result["namedCompilationUnitMember_name"] =
-            namedCompilationUnitMember_name.toJson();
-      if (simplyBoundable_isSimplyBounded != false)
-        _result["simplyBoundable_isSimplyBounded"] =
-            simplyBoundable_isSimplyBounded;
-    }
-    if (kind == idl.LinkedNodeKind.classTypeAlias) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (classTypeAlias_typeParameters != null)
-        _result["classTypeAlias_typeParameters"] =
-            classTypeAlias_typeParameters.toJson();
-      if (classTypeAlias_abstractKeyword != 0)
-        _result["classTypeAlias_abstractKeyword"] =
-            classTypeAlias_abstractKeyword;
-      if (classTypeAlias_superclass != null)
-        _result["classTypeAlias_superclass"] =
-            classTypeAlias_superclass.toJson();
-      if (classTypeAlias_withClause != null)
-        _result["classTypeAlias_withClause"] =
-            classTypeAlias_withClause.toJson();
-      if (classTypeAlias_equals != 0)
-        _result["classTypeAlias_equals"] = classTypeAlias_equals;
-      if (typeAlias_typedefKeyword != 0)
-        _result["typeAlias_typedefKeyword"] = typeAlias_typedefKeyword;
-      if (typeAlias_semicolon != 0)
-        _result["typeAlias_semicolon"] = typeAlias_semicolon;
-      if (classTypeAlias_implementsClause != null)
-        _result["classTypeAlias_implementsClause"] =
-            classTypeAlias_implementsClause.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (namedCompilationUnitMember_name != null)
-        _result["namedCompilationUnitMember_name"] =
-            namedCompilationUnitMember_name.toJson();
-      if (simplyBoundable_isSimplyBounded != false)
-        _result["simplyBoundable_isSimplyBounded"] =
-            simplyBoundable_isSimplyBounded;
-    }
-    if (kind == idl.LinkedNodeKind.declaredIdentifier) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (declaredIdentifier_identifier != null)
-        _result["declaredIdentifier_identifier"] =
-            declaredIdentifier_identifier.toJson();
-      if (declaredIdentifier_keyword != 0)
-        _result["declaredIdentifier_keyword"] = declaredIdentifier_keyword;
-      if (declaredIdentifier_type != null)
-        _result["declaredIdentifier_type"] = declaredIdentifier_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (enumConstantDeclaration_name != null)
-        _result["enumConstantDeclaration_name"] =
-            enumConstantDeclaration_name.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.fieldDeclaration) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (fieldDeclaration_fields != null)
-        _result["fieldDeclaration_fields"] = fieldDeclaration_fields.toJson();
-      if (fieldDeclaration_covariantKeyword != 0)
-        _result["fieldDeclaration_covariantKeyword"] =
-            fieldDeclaration_covariantKeyword;
-      if (fieldDeclaration_semicolon != 0)
-        _result["fieldDeclaration_semicolon"] = fieldDeclaration_semicolon;
-      if (fieldDeclaration_staticKeyword != 0)
-        _result["fieldDeclaration_staticKeyword"] =
-            fieldDeclaration_staticKeyword;
-    }
-    if (kind == idl.LinkedNodeKind.genericTypeAlias) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (genericTypeAlias_typeParameters != null)
-        _result["genericTypeAlias_typeParameters"] =
-            genericTypeAlias_typeParameters.toJson();
-      if (genericTypeAlias_functionType != null)
-        _result["genericTypeAlias_functionType"] =
-            genericTypeAlias_functionType.toJson();
-      if (genericTypeAlias_equals != 0)
-        _result["genericTypeAlias_equals"] = genericTypeAlias_equals;
-      if (typeAlias_typedefKeyword != 0)
-        _result["typeAlias_typedefKeyword"] = typeAlias_typedefKeyword;
-      if (typeAlias_semicolon != 0)
-        _result["typeAlias_semicolon"] = typeAlias_semicolon;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (namedCompilationUnitMember_name != null)
-        _result["namedCompilationUnitMember_name"] =
-            namedCompilationUnitMember_name.toJson();
-      if (simplyBoundable_isSimplyBounded != false)
-        _result["simplyBoundable_isSimplyBounded"] =
-            simplyBoundable_isSimplyBounded;
-    }
-    if (kind == idl.LinkedNodeKind.libraryDirective) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (libraryDirective_name != null)
-        _result["libraryDirective_name"] = libraryDirective_name.toJson();
-      if (directive_keyword != 0)
-        _result["directive_keyword"] = directive_keyword;
-      if (directive_semicolon != 0)
-        _result["directive_semicolon"] = directive_semicolon;
-    }
-    if (kind == idl.LinkedNodeKind.mixinDeclaration) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (mixinDeclaration_onClause != null)
-        _result["mixinDeclaration_onClause"] =
-            mixinDeclaration_onClause.toJson();
-      if (mixinDeclaration_mixinKeyword != 0)
-        _result["mixinDeclaration_mixinKeyword"] =
-            mixinDeclaration_mixinKeyword;
-      if (classOrMixinDeclaration_rightBracket != 0)
-        _result["classOrMixinDeclaration_rightBracket"] =
-            classOrMixinDeclaration_rightBracket;
-      if (classOrMixinDeclaration_leftBracket != 0)
-        _result["classOrMixinDeclaration_leftBracket"] =
-            classOrMixinDeclaration_leftBracket;
-      if (classOrMixinDeclaration_implementsClause != null)
-        _result["classOrMixinDeclaration_implementsClause"] =
-            classOrMixinDeclaration_implementsClause.toJson();
-      if (classOrMixinDeclaration_members.isNotEmpty)
-        _result["classOrMixinDeclaration_members"] =
-            classOrMixinDeclaration_members
-                .map((_value) => _value.toJson())
-                .toList();
-      if (classOrMixinDeclaration_typeParameters != null)
-        _result["classOrMixinDeclaration_typeParameters"] =
-            classOrMixinDeclaration_typeParameters.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (namedCompilationUnitMember_name != null)
-        _result["namedCompilationUnitMember_name"] =
-            namedCompilationUnitMember_name.toJson();
-      if (simplyBoundable_isSimplyBounded != false)
-        _result["simplyBoundable_isSimplyBounded"] =
-            simplyBoundable_isSimplyBounded;
     }
     if (kind == idl.LinkedNodeKind.partDirective) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
       if (annotatedNode_metadata.isNotEmpty)
         _result["annotatedNode_metadata"] =
             annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (directive_keyword != 0)
-        _result["directive_keyword"] = directive_keyword;
-      if (uriBasedDirective_uriElement != 0)
-        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
-      if (directive_semicolon != 0)
-        _result["directive_semicolon"] = directive_semicolon;
+      if (informativeId != 0) _result["informativeId"] = informativeId;
       if (uriBasedDirective_uri != null)
         _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
       if (uriBasedDirective_uriContent != '')
         _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
+      if (uriBasedDirective_uriElement != 0)
+        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
     }
     if (kind == idl.LinkedNodeKind.partOfDirective) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
       if (annotatedNode_metadata.isNotEmpty)
         _result["annotatedNode_metadata"] =
             annotatedNode_metadata.map((_value) => _value.toJson()).toList();
@@ -16424,41 +14009,156 @@
             partOfDirective_libraryName.toJson();
       if (partOfDirective_uri != null)
         _result["partOfDirective_uri"] = partOfDirective_uri.toJson();
-      if (partOfDirective_ofKeyword != 0)
-        _result["partOfDirective_ofKeyword"] = partOfDirective_ofKeyword;
-      if (directive_keyword != 0)
-        _result["directive_keyword"] = directive_keyword;
-      if (directive_semicolon != 0)
-        _result["directive_semicolon"] = directive_semicolon;
+      if (informativeId != 0) _result["informativeId"] = informativeId;
     }
-    if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (topLevelVariableDeclaration_variableList != null)
-        _result["topLevelVariableDeclaration_variableList"] =
-            topLevelVariableDeclaration_variableList.toJson();
-      if (topLevelVariableDeclaration_semicolon != 0)
-        _result["topLevelVariableDeclaration_semicolon"] =
-            topLevelVariableDeclaration_semicolon;
+    if (kind == idl.LinkedNodeKind.postfixExpression) {
+      if (postfixExpression_operand != null)
+        _result["postfixExpression_operand"] =
+            postfixExpression_operand.toJson();
+      if (postfixExpression_elementType != null)
+        _result["postfixExpression_elementType"] =
+            postfixExpression_elementType.toJson();
+      if (postfixExpression_element != 0)
+        _result["postfixExpression_element"] = postfixExpression_element;
+      if (postfixExpression_operator != idl.UnlinkedTokenType.NOTHING)
+        _result["postfixExpression_operator"] =
+            postfixExpression_operator.toString().split('.')[1];
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
     }
-    if (kind == idl.LinkedNodeKind.typeParameter) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (typeParameter_bound != null)
-        _result["typeParameter_bound"] = typeParameter_bound.toJson();
-      if (typeParameter_extendsKeyword != 0)
-        _result["typeParameter_extendsKeyword"] = typeParameter_extendsKeyword;
-      if (typeParameter_name != null)
-        _result["typeParameter_name"] = typeParameter_name.toJson();
-      if (typeParameter_id != 0) _result["typeParameter_id"] = typeParameter_id;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+    if (kind == idl.LinkedNodeKind.prefixExpression) {
+      if (prefixExpression_operand != null)
+        _result["prefixExpression_operand"] = prefixExpression_operand.toJson();
+      if (prefixExpression_elementType != null)
+        _result["prefixExpression_elementType"] =
+            prefixExpression_elementType.toJson();
+      if (prefixExpression_element != 0)
+        _result["prefixExpression_element"] = prefixExpression_element;
+      if (prefixExpression_operator != idl.UnlinkedTokenType.NOTHING)
+        _result["prefixExpression_operator"] =
+            prefixExpression_operator.toString().split('.')[1];
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+      if (prefixedIdentifier_identifier != null)
+        _result["prefixedIdentifier_identifier"] =
+            prefixedIdentifier_identifier.toJson();
+      if (prefixedIdentifier_prefix != null)
+        _result["prefixedIdentifier_prefix"] =
+            prefixedIdentifier_prefix.toJson();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.propertyAccess) {
+      if (propertyAccess_propertyName != null)
+        _result["propertyAccess_propertyName"] =
+            propertyAccess_propertyName.toJson();
+      if (propertyAccess_target != null)
+        _result["propertyAccess_target"] = propertyAccess_target.toJson();
+      if (propertyAccess_operator != idl.UnlinkedTokenType.NOTHING)
+        _result["propertyAccess_operator"] =
+            propertyAccess_operator.toString().split('.')[1];
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
+      if (redirectingConstructorInvocation_arguments != null)
+        _result["redirectingConstructorInvocation_arguments"] =
+            redirectingConstructorInvocation_arguments.toJson();
+      if (redirectingConstructorInvocation_constructorName != null)
+        _result["redirectingConstructorInvocation_constructorName"] =
+            redirectingConstructorInvocation_constructorName.toJson();
+      if (redirectingConstructorInvocation_elementType != null)
+        _result["redirectingConstructorInvocation_elementType"] =
+            redirectingConstructorInvocation_elementType.toJson();
+      if (redirectingConstructorInvocation_element != 0)
+        _result["redirectingConstructorInvocation_element"] =
+            redirectingConstructorInvocation_element;
+    }
+    if (kind == idl.LinkedNodeKind.rethrowExpression) {
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.returnStatement) {
+      if (returnStatement_expression != null)
+        _result["returnStatement_expression"] =
+            returnStatement_expression.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+      if (typedLiteral_typeArguments.isNotEmpty)
+        _result["typedLiteral_typeArguments"] = typedLiteral_typeArguments
+            .map((_value) => _value.toJson())
+            .toList();
+      if (setOrMapLiteral_elements.isNotEmpty)
+        _result["setOrMapLiteral_elements"] =
+            setOrMapLiteral_elements.map((_value) => _value.toJson()).toList();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.showCombinator) {
+      if (names.isNotEmpty) _result["names"] = names;
+    }
+    if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+      if (actualType != null) _result["actualType"] = actualType.toJson();
+      if (normalFormalParameter_metadata.isNotEmpty)
+        _result["normalFormalParameter_metadata"] =
+            normalFormalParameter_metadata
+                .map((_value) => _value.toJson())
+                .toList();
+      if (simpleFormalParameter_type != null)
+        _result["simpleFormalParameter_type"] =
+            simpleFormalParameter_type.toJson();
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+      if (topLevelTypeInferenceError != null)
+        _result["topLevelTypeInferenceError"] =
+            topLevelTypeInferenceError.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.simpleIdentifier) {
+      if (simpleIdentifier_elementType != null)
+        _result["simpleIdentifier_elementType"] =
+            simpleIdentifier_elementType.toJson();
+      if (simpleIdentifier_element != 0)
+        _result["simpleIdentifier_element"] = simpleIdentifier_element;
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
+      if (simpleStringLiteral_value != '')
+        _result["simpleStringLiteral_value"] = simpleStringLiteral_value;
+    }
+    if (kind == idl.LinkedNodeKind.spreadElement) {
+      if (spreadElement_expression != null)
+        _result["spreadElement_expression"] = spreadElement_expression.toJson();
+      if (spreadElement_spreadOperator != idl.UnlinkedTokenType.NOTHING)
+        _result["spreadElement_spreadOperator"] =
+            spreadElement_spreadOperator.toString().split('.')[1];
+    }
+    if (kind == idl.LinkedNodeKind.stringInterpolation) {
+      if (stringInterpolation_elements.isNotEmpty)
+        _result["stringInterpolation_elements"] = stringInterpolation_elements
+            .map((_value) => _value.toJson())
+            .toList();
+    }
+    if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
+      if (superConstructorInvocation_arguments != null)
+        _result["superConstructorInvocation_arguments"] =
+            superConstructorInvocation_arguments.toJson();
+      if (superConstructorInvocation_constructorName != null)
+        _result["superConstructorInvocation_constructorName"] =
+            superConstructorInvocation_constructorName.toJson();
+      if (superConstructorInvocation_elementType != null)
+        _result["superConstructorInvocation_elementType"] =
+            superConstructorInvocation_elementType.toJson();
+      if (superConstructorInvocation_element != 0)
+        _result["superConstructorInvocation_element"] =
+            superConstructorInvocation_element;
+    }
+    if (kind == idl.LinkedNodeKind.superExpression) {
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
     }
     if (kind == idl.LinkedNodeKind.switchCase) {
       if (switchMember_statements.isNotEmpty)
@@ -16466,10 +14166,6 @@
             switchMember_statements.map((_value) => _value.toJson()).toList();
       if (switchCase_expression != null)
         _result["switchCase_expression"] = switchCase_expression.toJson();
-      if (switchMember_keyword != 0)
-        _result["switchMember_keyword"] = switchMember_keyword;
-      if (switchMember_colon != 0)
-        _result["switchMember_colon"] = switchMember_colon;
       if (switchMember_labels.isNotEmpty)
         _result["switchMember_labels"] =
             switchMember_labels.map((_value) => _value.toJson()).toList();
@@ -16478,778 +14174,654 @@
       if (switchMember_statements.isNotEmpty)
         _result["switchMember_statements"] =
             switchMember_statements.map((_value) => _value.toJson()).toList();
-      if (switchMember_keyword != 0)
-        _result["switchMember_keyword"] = switchMember_keyword;
-      if (switchMember_colon != 0)
-        _result["switchMember_colon"] = switchMember_colon;
       if (switchMember_labels.isNotEmpty)
         _result["switchMember_labels"] =
             switchMember_labels.map((_value) => _value.toJson()).toList();
     }
-    if (kind == idl.LinkedNodeKind.annotation) {
-      if (annotation_arguments != null)
-        _result["annotation_arguments"] = annotation_arguments.toJson();
-      if (annotation_atSign != 0)
-        _result["annotation_atSign"] = annotation_atSign;
-      if (annotation_constructorName != null)
-        _result["annotation_constructorName"] =
-            annotation_constructorName.toJson();
-      if (annotation_name != null)
-        _result["annotation_name"] = annotation_name.toJson();
-      if (annotation_period != 0)
-        _result["annotation_period"] = annotation_period;
+    if (kind == idl.LinkedNodeKind.switchStatement) {
+      if (switchStatement_members.isNotEmpty)
+        _result["switchStatement_members"] =
+            switchStatement_members.map((_value) => _value.toJson()).toList();
+      if (switchStatement_expression != null)
+        _result["switchStatement_expression"] =
+            switchStatement_expression.toJson();
     }
-    if (kind == idl.LinkedNodeKind.asExpression) {
-      if (asExpression_expression != null)
-        _result["asExpression_expression"] = asExpression_expression.toJson();
-      if (asExpression_asOperator != 0)
-        _result["asExpression_asOperator"] = asExpression_asOperator;
-      if (asExpression_type != null)
-        _result["asExpression_type"] = asExpression_type.toJson();
+    if (kind == idl.LinkedNodeKind.symbolLiteral) {
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
+      if (names.isNotEmpty) _result["names"] = names;
     }
-    if (kind == idl.LinkedNodeKind.assertInitializer) {
-      if (assertInitializer_condition != null)
-        _result["assertInitializer_condition"] =
-            assertInitializer_condition.toJson();
-      if (assertInitializer_assertKeyword != 0)
-        _result["assertInitializer_assertKeyword"] =
-            assertInitializer_assertKeyword;
-      if (assertInitializer_message != null)
-        _result["assertInitializer_message"] =
-            assertInitializer_message.toJson();
-      if (assertInitializer_comma != 0)
-        _result["assertInitializer_comma"] = assertInitializer_comma;
-      if (assertInitializer_leftParenthesis != 0)
-        _result["assertInitializer_leftParenthesis"] =
-            assertInitializer_leftParenthesis;
-      if (assertInitializer_rightParenthesis != 0)
-        _result["assertInitializer_rightParenthesis"] =
-            assertInitializer_rightParenthesis;
-    }
-    if (kind == idl.LinkedNodeKind.assertStatement) {
-      if (assertStatement_condition != null)
-        _result["assertStatement_condition"] =
-            assertStatement_condition.toJson();
-      if (assertStatement_assertKeyword != 0)
-        _result["assertStatement_assertKeyword"] =
-            assertStatement_assertKeyword;
-      if (assertStatement_message != null)
-        _result["assertStatement_message"] = assertStatement_message.toJson();
-      if (assertStatement_comma != 0)
-        _result["assertStatement_comma"] = assertStatement_comma;
-      if (assertStatement_leftParenthesis != 0)
-        _result["assertStatement_leftParenthesis"] =
-            assertStatement_leftParenthesis;
-      if (assertStatement_rightParenthesis != 0)
-        _result["assertStatement_rightParenthesis"] =
-            assertStatement_rightParenthesis;
-      if (assertStatement_semicolon != 0)
-        _result["assertStatement_semicolon"] = assertStatement_semicolon;
-    }
-    if (kind == idl.LinkedNodeKind.assignmentExpression) {
-      if (assignmentExpression_leftHandSide != null)
-        _result["assignmentExpression_leftHandSide"] =
-            assignmentExpression_leftHandSide.toJson();
-      if (assignmentExpression_element != 0)
-        _result["assignmentExpression_element"] = assignmentExpression_element;
-      if (assignmentExpression_rightHandSide != null)
-        _result["assignmentExpression_rightHandSide"] =
-            assignmentExpression_rightHandSide.toJson();
-      if (assignmentExpression_operator != 0)
-        _result["assignmentExpression_operator"] =
-            assignmentExpression_operator;
-      if (assignmentExpression_elementType != null)
-        _result["assignmentExpression_elementType"] =
-            assignmentExpression_elementType.toJson();
+    if (kind == idl.LinkedNodeKind.thisExpression) {
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
-    if (kind == idl.LinkedNodeKind.awaitExpression) {
-      if (awaitExpression_expression != null)
-        _result["awaitExpression_expression"] =
-            awaitExpression_expression.toJson();
-      if (awaitExpression_awaitKeyword != 0)
-        _result["awaitExpression_awaitKeyword"] = awaitExpression_awaitKeyword;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.blockFunctionBody) {
-      if (blockFunctionBody_block != null)
-        _result["blockFunctionBody_block"] = blockFunctionBody_block.toJson();
-      if (blockFunctionBody_keyword != 0)
-        _result["blockFunctionBody_keyword"] = blockFunctionBody_keyword;
-      if (blockFunctionBody_star != 0)
-        _result["blockFunctionBody_star"] = blockFunctionBody_star;
-    }
-    if (kind == idl.LinkedNodeKind.breakStatement) {
-      if (breakStatement_label != null)
-        _result["breakStatement_label"] = breakStatement_label.toJson();
-      if (breakStatement_breakKeyword != 0)
-        _result["breakStatement_breakKeyword"] = breakStatement_breakKeyword;
-      if (breakStatement_semicolon != 0)
-        _result["breakStatement_semicolon"] = breakStatement_semicolon;
-    }
-    if (kind == idl.LinkedNodeKind.catchClause) {
-      if (catchClause_body != null)
-        _result["catchClause_body"] = catchClause_body.toJson();
-      if (catchClause_catchKeyword != 0)
-        _result["catchClause_catchKeyword"] = catchClause_catchKeyword;
-      if (catchClause_exceptionParameter != null)
-        _result["catchClause_exceptionParameter"] =
-            catchClause_exceptionParameter.toJson();
-      if (catchClause_exceptionType != null)
-        _result["catchClause_exceptionType"] =
-            catchClause_exceptionType.toJson();
-      if (catchClause_comma != 0)
-        _result["catchClause_comma"] = catchClause_comma;
-      if (catchClause_leftParenthesis != 0)
-        _result["catchClause_leftParenthesis"] = catchClause_leftParenthesis;
-      if (catchClause_onKeyword != 0)
-        _result["catchClause_onKeyword"] = catchClause_onKeyword;
-      if (catchClause_rightParenthesis != 0)
-        _result["catchClause_rightParenthesis"] = catchClause_rightParenthesis;
-      if (catchClause_stackTraceParameter != null)
-        _result["catchClause_stackTraceParameter"] =
-            catchClause_stackTraceParameter.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.conditionalExpression) {
-      if (conditionalExpression_condition != null)
-        _result["conditionalExpression_condition"] =
-            conditionalExpression_condition.toJson();
-      if (conditionalExpression_colon != 0)
-        _result["conditionalExpression_colon"] = conditionalExpression_colon;
-      if (conditionalExpression_elseExpression != null)
-        _result["conditionalExpression_elseExpression"] =
-            conditionalExpression_elseExpression.toJson();
-      if (conditionalExpression_thenExpression != null)
-        _result["conditionalExpression_thenExpression"] =
-            conditionalExpression_thenExpression.toJson();
-      if (conditionalExpression_question != 0)
-        _result["conditionalExpression_question"] =
-            conditionalExpression_question;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.configuration) {
-      if (configuration_name != null)
-        _result["configuration_name"] = configuration_name.toJson();
-      if (configuration_ifKeyword != 0)
-        _result["configuration_ifKeyword"] = configuration_ifKeyword;
-      if (configuration_value != null)
-        _result["configuration_value"] = configuration_value.toJson();
-      if (configuration_uri != null)
-        _result["configuration_uri"] = configuration_uri.toJson();
-      if (configuration_leftParenthesis != 0)
-        _result["configuration_leftParenthesis"] =
-            configuration_leftParenthesis;
-      if (configuration_rightParenthesis != 0)
-        _result["configuration_rightParenthesis"] =
-            configuration_rightParenthesis;
-      if (configuration_equalToken != 0)
-        _result["configuration_equalToken"] = configuration_equalToken;
-    }
-    if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
-      if (constructorFieldInitializer_expression != null)
-        _result["constructorFieldInitializer_expression"] =
-            constructorFieldInitializer_expression.toJson();
-      if (constructorFieldInitializer_equals != 0)
-        _result["constructorFieldInitializer_equals"] =
-            constructorFieldInitializer_equals;
-      if (constructorFieldInitializer_fieldName != null)
-        _result["constructorFieldInitializer_fieldName"] =
-            constructorFieldInitializer_fieldName.toJson();
-      if (constructorFieldInitializer_period != 0)
-        _result["constructorFieldInitializer_period"] =
-            constructorFieldInitializer_period;
-      if (constructorFieldInitializer_thisKeyword != 0)
-        _result["constructorFieldInitializer_thisKeyword"] =
-            constructorFieldInitializer_thisKeyword;
-    }
-    if (kind == idl.LinkedNodeKind.constructorName) {
-      if (constructorName_name != null)
-        _result["constructorName_name"] = constructorName_name.toJson();
-      if (constructorName_element != 0)
-        _result["constructorName_element"] = constructorName_element;
-      if (constructorName_type != null)
-        _result["constructorName_type"] = constructorName_type.toJson();
-      if (constructorName_period != 0)
-        _result["constructorName_period"] = constructorName_period;
-      if (constructorName_elementType != null)
-        _result["constructorName_elementType"] =
-            constructorName_elementType.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.continueStatement) {
-      if (continueStatement_label != null)
-        _result["continueStatement_label"] = continueStatement_label.toJson();
-      if (continueStatement_continueKeyword != 0)
-        _result["continueStatement_continueKeyword"] =
-            continueStatement_continueKeyword;
-      if (continueStatement_semicolon != 0)
-        _result["continueStatement_semicolon"] = continueStatement_semicolon;
-    }
-    if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
-      if (defaultFormalParameter_defaultValue != null)
-        _result["defaultFormalParameter_defaultValue"] =
-            defaultFormalParameter_defaultValue.toJson();
-      if (defaultFormalParameter_separator != 0)
-        _result["defaultFormalParameter_separator"] =
-            defaultFormalParameter_separator;
-      if (defaultFormalParameter_parameter != null)
-        _result["defaultFormalParameter_parameter"] =
-            defaultFormalParameter_parameter.toJson();
-      if (defaultFormalParameter_isNamed != false)
-        _result["defaultFormalParameter_isNamed"] =
-            defaultFormalParameter_isNamed;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-    }
-    if (kind == idl.LinkedNodeKind.doStatement) {
-      if (doStatement_body != null)
-        _result["doStatement_body"] = doStatement_body.toJson();
-      if (doStatement_leftParenthesis != 0)
-        _result["doStatement_leftParenthesis"] = doStatement_leftParenthesis;
-      if (doStatement_condition != null)
-        _result["doStatement_condition"] = doStatement_condition.toJson();
-      if (doStatement_rightParenthesis != 0)
-        _result["doStatement_rightParenthesis"] = doStatement_rightParenthesis;
-      if (doStatement_doKeyword != 0)
-        _result["doStatement_doKeyword"] = doStatement_doKeyword;
-      if (doStatement_semicolon != 0)
-        _result["doStatement_semicolon"] = doStatement_semicolon;
-      if (doStatement_whileKeyword != 0)
-        _result["doStatement_whileKeyword"] = doStatement_whileKeyword;
-    }
-    if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
-      if (expressionFunctionBody_expression != null)
-        _result["expressionFunctionBody_expression"] =
-            expressionFunctionBody_expression.toJson();
-      if (expressionFunctionBody_arrow != 0)
-        _result["expressionFunctionBody_arrow"] = expressionFunctionBody_arrow;
-      if (expressionFunctionBody_keyword != 0)
-        _result["expressionFunctionBody_keyword"] =
-            expressionFunctionBody_keyword;
-      if (expressionFunctionBody_semicolon != 0)
-        _result["expressionFunctionBody_semicolon"] =
-            expressionFunctionBody_semicolon;
-    }
-    if (kind == idl.LinkedNodeKind.expressionStatement) {
-      if (expressionStatement_expression != null)
-        _result["expressionStatement_expression"] =
-            expressionStatement_expression.toJson();
-      if (expressionStatement_semicolon != 0)
-        _result["expressionStatement_semicolon"] =
-            expressionStatement_semicolon;
-    }
-    if (kind == idl.LinkedNodeKind.extendsClause) {
-      if (extendsClause_superclass != null)
-        _result["extendsClause_superclass"] = extendsClause_superclass.toJson();
-      if (extendsClause_extendsKeyword != 0)
-        _result["extendsClause_extendsKeyword"] = extendsClause_extendsKeyword;
-    }
-    if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
-      if (forEachParts_iterable != null)
-        _result["forEachParts_iterable"] = forEachParts_iterable.toJson();
-      if (forEachParts_inKeyword != 0)
-        _result["forEachParts_inKeyword"] = forEachParts_inKeyword;
-      if (forEachPartsWithDeclaration_loopVariable != null)
-        _result["forEachPartsWithDeclaration_loopVariable"] =
-            forEachPartsWithDeclaration_loopVariable.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
-      if (forEachParts_iterable != null)
-        _result["forEachParts_iterable"] = forEachParts_iterable.toJson();
-      if (forEachParts_inKeyword != 0)
-        _result["forEachParts_inKeyword"] = forEachParts_inKeyword;
-      if (forEachPartsWithIdentifier_identifier != null)
-        _result["forEachPartsWithIdentifier_identifier"] =
-            forEachPartsWithIdentifier_identifier.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.forElement) {
-      if (forMixin_forLoopParts != null)
-        _result["forMixin_forLoopParts"] = forMixin_forLoopParts.toJson();
-      if (forMixin_awaitKeyword != 0)
-        _result["forMixin_awaitKeyword"] = forMixin_awaitKeyword;
-      if (forElement_body != null)
-        _result["forElement_body"] = forElement_body.toJson();
-      if (forMixin_forKeyword != 0)
-        _result["forMixin_forKeyword"] = forMixin_forKeyword;
-      if (forMixin_leftParenthesis != 0)
-        _result["forMixin_leftParenthesis"] = forMixin_leftParenthesis;
-      if (forMixin_rightParenthesis != 0)
-        _result["forMixin_rightParenthesis"] = forMixin_rightParenthesis;
-    }
-    if (kind == idl.LinkedNodeKind.forStatement) {
-      if (forMixin_forLoopParts != null)
-        _result["forMixin_forLoopParts"] = forMixin_forLoopParts.toJson();
-      if (forMixin_awaitKeyword != 0)
-        _result["forMixin_awaitKeyword"] = forMixin_awaitKeyword;
-      if (forStatement_body != null)
-        _result["forStatement_body"] = forStatement_body.toJson();
-      if (forMixin_forKeyword != 0)
-        _result["forMixin_forKeyword"] = forMixin_forKeyword;
-      if (forMixin_leftParenthesis != 0)
-        _result["forMixin_leftParenthesis"] = forMixin_leftParenthesis;
-      if (forMixin_rightParenthesis != 0)
-        _result["forMixin_rightParenthesis"] = forMixin_rightParenthesis;
-    }
-    if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
-      if (forParts_condition != null)
-        _result["forParts_condition"] = forParts_condition.toJson();
-      if (forParts_leftSeparator != 0)
-        _result["forParts_leftSeparator"] = forParts_leftSeparator;
-      if (forPartsWithDeclarations_variables != null)
-        _result["forPartsWithDeclarations_variables"] =
-            forPartsWithDeclarations_variables.toJson();
-      if (forParts_rightSeparator != 0)
-        _result["forParts_rightSeparator"] = forParts_rightSeparator;
-      if (forParts_updaters.isNotEmpty)
-        _result["forParts_updaters"] =
-            forParts_updaters.map((_value) => _value.toJson()).toList();
-    }
-    if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
-      if (forParts_condition != null)
-        _result["forParts_condition"] = forParts_condition.toJson();
-      if (forParts_leftSeparator != 0)
-        _result["forParts_leftSeparator"] = forParts_leftSeparator;
-      if (forPartsWithExpression_initialization != null)
-        _result["forPartsWithExpression_initialization"] =
-            forPartsWithExpression_initialization.toJson();
-      if (forParts_rightSeparator != 0)
-        _result["forParts_rightSeparator"] = forParts_rightSeparator;
-      if (forParts_updaters.isNotEmpty)
-        _result["forParts_updaters"] =
-            forParts_updaters.map((_value) => _value.toJson()).toList();
-    }
-    if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
-      if (functionDeclarationStatement_functionDeclaration != null)
-        _result["functionDeclarationStatement_functionDeclaration"] =
-            functionDeclarationStatement_functionDeclaration.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.ifElement) {
-      if (ifMixin_condition != null)
-        _result["ifMixin_condition"] = ifMixin_condition.toJson();
-      if (ifMixin_elseKeyword != 0)
-        _result["ifMixin_elseKeyword"] = ifMixin_elseKeyword;
-      if (ifElement_thenElement != null)
-        _result["ifElement_thenElement"] = ifElement_thenElement.toJson();
-      if (ifMixin_ifKeyword != 0)
-        _result["ifMixin_ifKeyword"] = ifMixin_ifKeyword;
-      if (ifMixin_leftParenthesis != 0)
-        _result["ifMixin_leftParenthesis"] = ifMixin_leftParenthesis;
-      if (ifMixin_rightParenthesis != 0)
-        _result["ifMixin_rightParenthesis"] = ifMixin_rightParenthesis;
-      if (ifElement_elseElement != null)
-        _result["ifElement_elseElement"] = ifElement_elseElement.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.ifStatement) {
-      if (ifMixin_condition != null)
-        _result["ifMixin_condition"] = ifMixin_condition.toJson();
-      if (ifMixin_elseKeyword != 0)
-        _result["ifMixin_elseKeyword"] = ifMixin_elseKeyword;
-      if (ifStatement_elseStatement != null)
-        _result["ifStatement_elseStatement"] =
-            ifStatement_elseStatement.toJson();
-      if (ifStatement_thenStatement != null)
-        _result["ifStatement_thenStatement"] =
-            ifStatement_thenStatement.toJson();
-      if (ifMixin_ifKeyword != 0)
-        _result["ifMixin_ifKeyword"] = ifMixin_ifKeyword;
-      if (ifMixin_leftParenthesis != 0)
-        _result["ifMixin_leftParenthesis"] = ifMixin_leftParenthesis;
-      if (ifMixin_rightParenthesis != 0)
-        _result["ifMixin_rightParenthesis"] = ifMixin_rightParenthesis;
-    }
-    if (kind == idl.LinkedNodeKind.indexExpression) {
-      if (indexExpression_index != null)
-        _result["indexExpression_index"] = indexExpression_index.toJson();
-      if (indexExpression_element != 0)
-        _result["indexExpression_element"] = indexExpression_element;
-      if (indexExpression_target != null)
-        _result["indexExpression_target"] = indexExpression_target.toJson();
-      if (indexExpression_period != 0)
-        _result["indexExpression_period"] = indexExpression_period;
-      if (indexExpression_leftBracket != 0)
-        _result["indexExpression_leftBracket"] = indexExpression_leftBracket;
-      if (indexExpression_rightBracket != 0)
-        _result["indexExpression_rightBracket"] = indexExpression_rightBracket;
-      if (indexExpression_elementType != null)
-        _result["indexExpression_elementType"] =
-            indexExpression_elementType.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
-      if (instanceCreationExpression_arguments != null)
-        _result["instanceCreationExpression_arguments"] =
-            instanceCreationExpression_arguments.toJson();
-      if (instanceCreationExpression_keyword != 0)
-        _result["instanceCreationExpression_keyword"] =
-            instanceCreationExpression_keyword;
-      if (instanceCreationExpression_constructorName != null)
-        _result["instanceCreationExpression_constructorName"] =
-            instanceCreationExpression_constructorName.toJson();
-      if (instanceCreationExpression_typeArguments != null)
-        _result["instanceCreationExpression_typeArguments"] =
-            instanceCreationExpression_typeArguments.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.interpolationExpression) {
-      if (interpolationExpression_expression != null)
-        _result["interpolationExpression_expression"] =
-            interpolationExpression_expression.toJson();
-      if (interpolationExpression_leftBracket != 0)
-        _result["interpolationExpression_leftBracket"] =
-            interpolationExpression_leftBracket;
-      if (interpolationExpression_rightBracket != 0)
-        _result["interpolationExpression_rightBracket"] =
-            interpolationExpression_rightBracket;
-    }
-    if (kind == idl.LinkedNodeKind.isExpression) {
-      if (isExpression_expression != null)
-        _result["isExpression_expression"] = isExpression_expression.toJson();
-      if (isExpression_isOperator != 0)
-        _result["isExpression_isOperator"] = isExpression_isOperator;
-      if (isExpression_type != null)
-        _result["isExpression_type"] = isExpression_type.toJson();
-      if (isExpression_notOperator != 0)
-        _result["isExpression_notOperator"] = isExpression_notOperator;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.label) {
-      if (label_label != null) _result["label_label"] = label_label.toJson();
-      if (label_colon != 0) _result["label_colon"] = label_colon;
-    }
-    if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
-      if (mapLiteralEntry_key != null)
-        _result["mapLiteralEntry_key"] = mapLiteralEntry_key.toJson();
-      if (mapLiteralEntry_separator != 0)
-        _result["mapLiteralEntry_separator"] = mapLiteralEntry_separator;
-      if (mapLiteralEntry_value != null)
-        _result["mapLiteralEntry_value"] = mapLiteralEntry_value.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.namedExpression) {
-      if (namedExpression_expression != null)
-        _result["namedExpression_expression"] =
-            namedExpression_expression.toJson();
-      if (namedExpression_name != null)
-        _result["namedExpression_name"] = namedExpression_name.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.nativeClause) {
-      if (nativeClause_name != null)
-        _result["nativeClause_name"] = nativeClause_name.toJson();
-      if (nativeClause_nativeKeyword != 0)
-        _result["nativeClause_nativeKeyword"] = nativeClause_nativeKeyword;
-    }
-    if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
-      if (nativeFunctionBody_stringLiteral != null)
-        _result["nativeFunctionBody_stringLiteral"] =
-            nativeFunctionBody_stringLiteral.toJson();
-      if (nativeFunctionBody_nativeKeyword != 0)
-        _result["nativeFunctionBody_nativeKeyword"] =
-            nativeFunctionBody_nativeKeyword;
-      if (nativeFunctionBody_semicolon != 0)
-        _result["nativeFunctionBody_semicolon"] = nativeFunctionBody_semicolon;
-    }
-    if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
-      if (parenthesizedExpression_expression != null)
-        _result["parenthesizedExpression_expression"] =
-            parenthesizedExpression_expression.toJson();
-      if (parenthesizedExpression_leftParenthesis != 0)
-        _result["parenthesizedExpression_leftParenthesis"] =
-            parenthesizedExpression_leftParenthesis;
-      if (parenthesizedExpression_rightParenthesis != 0)
-        _result["parenthesizedExpression_rightParenthesis"] =
-            parenthesizedExpression_rightParenthesis;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.postfixExpression) {
-      if (postfixExpression_operand != null)
-        _result["postfixExpression_operand"] =
-            postfixExpression_operand.toJson();
-      if (postfixExpression_element != 0)
-        _result["postfixExpression_element"] = postfixExpression_element;
-      if (postfixExpression_operator != 0)
-        _result["postfixExpression_operator"] = postfixExpression_operator;
-      if (postfixExpression_elementType != null)
-        _result["postfixExpression_elementType"] =
-            postfixExpression_elementType.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
-      if (prefixedIdentifier_identifier != null)
-        _result["prefixedIdentifier_identifier"] =
-            prefixedIdentifier_identifier.toJson();
-      if (prefixedIdentifier_period != 0)
-        _result["prefixedIdentifier_period"] = prefixedIdentifier_period;
-      if (prefixedIdentifier_prefix != null)
-        _result["prefixedIdentifier_prefix"] =
-            prefixedIdentifier_prefix.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.prefixExpression) {
-      if (prefixExpression_operand != null)
-        _result["prefixExpression_operand"] = prefixExpression_operand.toJson();
-      if (prefixExpression_element != 0)
-        _result["prefixExpression_element"] = prefixExpression_element;
-      if (prefixExpression_operator != 0)
-        _result["prefixExpression_operator"] = prefixExpression_operator;
-      if (prefixExpression_elementType != null)
-        _result["prefixExpression_elementType"] =
-            prefixExpression_elementType.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.propertyAccess) {
-      if (propertyAccess_propertyName != null)
-        _result["propertyAccess_propertyName"] =
-            propertyAccess_propertyName.toJson();
-      if (propertyAccess_operator != 0)
-        _result["propertyAccess_operator"] = propertyAccess_operator;
-      if (propertyAccess_target != null)
-        _result["propertyAccess_target"] = propertyAccess_target.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
-      if (redirectingConstructorInvocation_arguments != null)
-        _result["redirectingConstructorInvocation_arguments"] =
-            redirectingConstructorInvocation_arguments.toJson();
-      if (redirectingConstructorInvocation_element != 0)
-        _result["redirectingConstructorInvocation_element"] =
-            redirectingConstructorInvocation_element;
-      if (redirectingConstructorInvocation_constructorName != null)
-        _result["redirectingConstructorInvocation_constructorName"] =
-            redirectingConstructorInvocation_constructorName.toJson();
-      if (redirectingConstructorInvocation_period != 0)
-        _result["redirectingConstructorInvocation_period"] =
-            redirectingConstructorInvocation_period;
-      if (redirectingConstructorInvocation_thisKeyword != 0)
-        _result["redirectingConstructorInvocation_thisKeyword"] =
-            redirectingConstructorInvocation_thisKeyword;
-      if (redirectingConstructorInvocation_elementType != null)
-        _result["redirectingConstructorInvocation_elementType"] =
-            redirectingConstructorInvocation_elementType.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.returnStatement) {
-      if (returnStatement_expression != null)
-        _result["returnStatement_expression"] =
-            returnStatement_expression.toJson();
-      if (returnStatement_returnKeyword != 0)
-        _result["returnStatement_returnKeyword"] =
-            returnStatement_returnKeyword;
-      if (returnStatement_semicolon != 0)
-        _result["returnStatement_semicolon"] = returnStatement_semicolon;
-    }
-    if (kind == idl.LinkedNodeKind.spreadElement) {
-      if (spreadElement_expression != null)
-        _result["spreadElement_expression"] = spreadElement_expression.toJson();
-      if (spreadElement_spreadOperator != 0)
-        _result["spreadElement_spreadOperator"] = spreadElement_spreadOperator;
-    }
-    if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
-      if (superConstructorInvocation_arguments != null)
-        _result["superConstructorInvocation_arguments"] =
-            superConstructorInvocation_arguments.toJson();
-      if (superConstructorInvocation_element != 0)
-        _result["superConstructorInvocation_element"] =
-            superConstructorInvocation_element;
-      if (superConstructorInvocation_constructorName != null)
-        _result["superConstructorInvocation_constructorName"] =
-            superConstructorInvocation_constructorName.toJson();
-      if (superConstructorInvocation_period != 0)
-        _result["superConstructorInvocation_period"] =
-            superConstructorInvocation_period;
-      if (superConstructorInvocation_superKeyword != 0)
-        _result["superConstructorInvocation_superKeyword"] =
-            superConstructorInvocation_superKeyword;
-      if (superConstructorInvocation_elementType != null)
-        _result["superConstructorInvocation_elementType"] =
-            superConstructorInvocation_elementType.toJson();
-    }
     if (kind == idl.LinkedNodeKind.throwExpression) {
       if (throwExpression_expression != null)
         _result["throwExpression_expression"] =
             throwExpression_expression.toJson();
-      if (throwExpression_throwKeyword != 0)
-        _result["throwExpression_throwKeyword"] = throwExpression_throwKeyword;
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
+    if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (topLevelVariableDeclaration_variableList != null)
+        _result["topLevelVariableDeclaration_variableList"] =
+            topLevelVariableDeclaration_variableList.toJson();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.tryStatement) {
+      if (tryStatement_catchClauses.isNotEmpty)
+        _result["tryStatement_catchClauses"] =
+            tryStatement_catchClauses.map((_value) => _value.toJson()).toList();
+      if (tryStatement_body != null)
+        _result["tryStatement_body"] = tryStatement_body.toJson();
+      if (tryStatement_finallyBlock != null)
+        _result["tryStatement_finallyBlock"] =
+            tryStatement_finallyBlock.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.typeArgumentList) {
+      if (typeArgumentList_arguments.isNotEmpty)
+        _result["typeArgumentList_arguments"] = typeArgumentList_arguments
+            .map((_value) => _value.toJson())
+            .toList();
+    }
     if (kind == idl.LinkedNodeKind.typeName) {
+      if (typeName_typeArguments.isNotEmpty)
+        _result["typeName_typeArguments"] =
+            typeName_typeArguments.map((_value) => _value.toJson()).toList();
       if (typeName_name != null)
         _result["typeName_name"] = typeName_name.toJson();
-      if (typeName_question != 0)
-        _result["typeName_question"] = typeName_question;
-      if (typeName_typeArguments != null)
-        _result["typeName_typeArguments"] = typeName_typeArguments.toJson();
       if (typeName_type != null)
         _result["typeName_type"] = typeName_type.toJson();
     }
+    if (kind == idl.LinkedNodeKind.typeParameter) {
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (typeParameter_bound != null)
+        _result["typeParameter_bound"] = typeParameter_bound.toJson();
+      if (typeParameter_defaultType != null)
+        _result["typeParameter_defaultType"] =
+            typeParameter_defaultType.toJson();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
+    if (kind == idl.LinkedNodeKind.typeParameterList) {
+      if (typeParameterList_typeParameters.isNotEmpty)
+        _result["typeParameterList_typeParameters"] =
+            typeParameterList_typeParameters
+                .map((_value) => _value.toJson())
+                .toList();
+    }
+    if (kind == idl.LinkedNodeKind.variableDeclaration) {
+      if (actualType != null) _result["actualType"] = actualType.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (variableDeclaration_initializer != null)
+        _result["variableDeclaration_initializer"] =
+            variableDeclaration_initializer.toJson();
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+      if (topLevelTypeInferenceError != null)
+        _result["topLevelTypeInferenceError"] =
+            topLevelTypeInferenceError.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+      if (variableDeclarationList_variables.isNotEmpty)
+        _result["variableDeclarationList_variables"] =
+            variableDeclarationList_variables
+                .map((_value) => _value.toJson())
+                .toList();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (variableDeclarationList_type != null)
+        _result["variableDeclarationList_type"] =
+            variableDeclarationList_type.toJson();
+      if (informativeId != 0) _result["informativeId"] = informativeId;
+    }
     if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
       if (variableDeclarationStatement_variables != null)
         _result["variableDeclarationStatement_variables"] =
             variableDeclarationStatement_variables.toJson();
-      if (variableDeclarationStatement_semicolon != 0)
-        _result["variableDeclarationStatement_semicolon"] =
-            variableDeclarationStatement_semicolon;
     }
     if (kind == idl.LinkedNodeKind.whileStatement) {
       if (whileStatement_body != null)
         _result["whileStatement_body"] = whileStatement_body.toJson();
-      if (whileStatement_leftParenthesis != 0)
-        _result["whileStatement_leftParenthesis"] =
-            whileStatement_leftParenthesis;
       if (whileStatement_condition != null)
         _result["whileStatement_condition"] = whileStatement_condition.toJson();
-      if (whileStatement_rightParenthesis != 0)
-        _result["whileStatement_rightParenthesis"] =
-            whileStatement_rightParenthesis;
-      if (whileStatement_whileKeyword != 0)
-        _result["whileStatement_whileKeyword"] = whileStatement_whileKeyword;
+    }
+    if (kind == idl.LinkedNodeKind.withClause) {
+      if (withClause_mixinTypes.isNotEmpty)
+        _result["withClause_mixinTypes"] =
+            withClause_mixinTypes.map((_value) => _value.toJson()).toList();
     }
     if (kind == idl.LinkedNodeKind.yieldStatement) {
       if (yieldStatement_expression != null)
         _result["yieldStatement_expression"] =
             yieldStatement_expression.toJson();
-      if (yieldStatement_yieldKeyword != 0)
-        _result["yieldStatement_yieldKeyword"] = yieldStatement_yieldKeyword;
-      if (yieldStatement_star != 0)
-        _result["yieldStatement_star"] = yieldStatement_star;
-      if (yieldStatement_semicolon != 0)
-        _result["yieldStatement_semicolon"] = yieldStatement_semicolon;
-    }
-    if (kind == idl.LinkedNodeKind.booleanLiteral) {
-      if (booleanLiteral_literal != 0)
-        _result["booleanLiteral_literal"] = booleanLiteral_literal;
-      if (booleanLiteral_value != false)
-        _result["booleanLiteral_value"] = booleanLiteral_value;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.doubleLiteral) {
-      if (doubleLiteral_literal != 0)
-        _result["doubleLiteral_literal"] = doubleLiteral_literal;
-      if (doubleLiteral_value != 0.0)
-        _result["doubleLiteral_value"] = doubleLiteral_value.isFinite
-            ? doubleLiteral_value
-            : doubleLiteral_value.toString();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
-      if (emptyFunctionBody_semicolon != 0)
-        _result["emptyFunctionBody_semicolon"] = emptyFunctionBody_semicolon;
-    }
-    if (kind == idl.LinkedNodeKind.emptyStatement) {
-      if (emptyStatement_semicolon != 0)
-        _result["emptyStatement_semicolon"] = emptyStatement_semicolon;
-    }
-    if (kind == idl.LinkedNodeKind.integerLiteral) {
-      if (integerLiteral_literal != 0)
-        _result["integerLiteral_literal"] = integerLiteral_literal;
-      if (integerLiteral_value != 0)
-        _result["integerLiteral_value"] = integerLiteral_value;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.interpolationString) {
-      if (interpolationString_token != 0)
-        _result["interpolationString_token"] = interpolationString_token;
-      if (interpolationString_value != '')
-        _result["interpolationString_value"] = interpolationString_value;
-    }
-    if (kind == idl.LinkedNodeKind.nullLiteral) {
-      if (nullLiteral_literal != 0)
-        _result["nullLiteral_literal"] = nullLiteral_literal;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.rethrowExpression) {
-      if (rethrowExpression_rethrowKeyword != 0)
-        _result["rethrowExpression_rethrowKeyword"] =
-            rethrowExpression_rethrowKeyword;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.scriptTag) {
-      if (scriptTag_scriptTag != 0)
-        _result["scriptTag_scriptTag"] = scriptTag_scriptTag;
-    }
-    if (kind == idl.LinkedNodeKind.simpleIdentifier) {
-      if (simpleIdentifier_element != 0)
-        _result["simpleIdentifier_element"] = simpleIdentifier_element;
-      if (simpleIdentifier_token != 0)
-        _result["simpleIdentifier_token"] = simpleIdentifier_token;
-      if (simpleIdentifier_elementType != null)
-        _result["simpleIdentifier_elementType"] =
-            simpleIdentifier_elementType.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
-      if (simpleStringLiteral_token != 0)
-        _result["simpleStringLiteral_token"] = simpleStringLiteral_token;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-      if (simpleStringLiteral_value != '')
-        _result["simpleStringLiteral_value"] = simpleStringLiteral_value;
-    }
-    if (kind == idl.LinkedNodeKind.superExpression) {
-      if (superExpression_superKeyword != 0)
-        _result["superExpression_superKeyword"] = superExpression_superKeyword;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.symbolLiteral) {
-      if (symbolLiteral_poundSign != 0)
-        _result["symbolLiteral_poundSign"] = symbolLiteral_poundSign;
-      if (symbolLiteral_components.isNotEmpty)
-        _result["symbolLiteral_components"] = symbolLiteral_components;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.thisExpression) {
-      if (thisExpression_thisKeyword != 0)
-        _result["thisExpression_thisKeyword"] = thisExpression_thisKeyword;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.comment) {
-      if (comment_tokens.isNotEmpty) _result["comment_tokens"] = comment_tokens;
-      if (comment_type != idl.LinkedNodeCommentType.block)
-        _result["comment_type"] = comment_type.toString().split('.')[1];
     }
     return _result;
   }
 
   @override
   Map<String, Object> toMap() {
+    if (kind == idl.LinkedNodeKind.adjacentStrings) {
+      return {
+        "adjacentStrings_strings": adjacentStrings_strings,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.annotation) {
+      return {
+        "annotation_arguments": annotation_arguments,
+        "annotation_constructorName": annotation_constructorName,
+        "annotation_element": annotation_element,
+        "annotation_elementType": annotation_elementType,
+        "annotation_name": annotation_name,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.argumentList) {
+      return {
+        "argumentList_arguments": argumentList_arguments,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.asExpression) {
+      return {
+        "asExpression_expression": asExpression_expression,
+        "asExpression_type": asExpression_type,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.assertInitializer) {
+      return {
+        "assertInitializer_condition": assertInitializer_condition,
+        "assertInitializer_message": assertInitializer_message,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.assertStatement) {
+      return {
+        "assertStatement_condition": assertStatement_condition,
+        "assertStatement_message": assertStatement_message,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.assignmentExpression) {
+      return {
+        "assignmentExpression_leftHandSide": assignmentExpression_leftHandSide,
+        "assignmentExpression_rightHandSide":
+            assignmentExpression_rightHandSide,
+        "assignmentExpression_elementType": assignmentExpression_elementType,
+        "assignmentExpression_element": assignmentExpression_element,
+        "assignmentExpression_operator": assignmentExpression_operator,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.awaitExpression) {
+      return {
+        "awaitExpression_expression": awaitExpression_expression,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.binaryExpression) {
+      return {
+        "binaryExpression_invokeType": binaryExpression_invokeType,
+        "binaryExpression_leftOperand": binaryExpression_leftOperand,
+        "binaryExpression_rightOperand": binaryExpression_rightOperand,
+        "binaryExpression_elementType": binaryExpression_elementType,
+        "binaryExpression_element": binaryExpression_element,
+        "binaryExpression_operator": binaryExpression_operator,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.block) {
+      return {
+        "block_statements": block_statements,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.blockFunctionBody) {
+      return {
+        "blockFunctionBody_block": blockFunctionBody_block,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.booleanLiteral) {
+      return {
+        "booleanLiteral_value": booleanLiteral_value,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.breakStatement) {
+      return {
+        "breakStatement_label": breakStatement_label,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.cascadeExpression) {
+      return {
+        "cascadeExpression_sections": cascadeExpression_sections,
+        "cascadeExpression_target": cascadeExpression_target,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.catchClause) {
+      return {
+        "catchClause_body": catchClause_body,
+        "catchClause_exceptionParameter": catchClause_exceptionParameter,
+        "catchClause_exceptionType": catchClause_exceptionType,
+        "catchClause_stackTraceParameter": catchClause_stackTraceParameter,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.classDeclaration) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "classDeclaration_extendsClause": classDeclaration_extendsClause,
+        "classDeclaration_withClause": classDeclaration_withClause,
+        "classDeclaration_nativeClause": classDeclaration_nativeClause,
+        "classDeclaration_isDartObject": classDeclaration_isDartObject,
+        "classOrMixinDeclaration_implementsClause":
+            classOrMixinDeclaration_implementsClause,
+        "classOrMixinDeclaration_members": classOrMixinDeclaration_members,
+        "classOrMixinDeclaration_typeParameters":
+            classOrMixinDeclaration_typeParameters,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
+        "unused11": unused11,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.classTypeAlias) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "classTypeAlias_typeParameters": classTypeAlias_typeParameters,
+        "classTypeAlias_superclass": classTypeAlias_superclass,
+        "classTypeAlias_withClause": classTypeAlias_withClause,
+        "classTypeAlias_implementsClause": classTypeAlias_implementsClause,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.comment) {
+      return {
+        "comment_references": comment_references,
+        "comment_tokens": comment_tokens,
+        "comment_type": comment_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.commentReference) {
+      return {
+        "commentReference_identifier": commentReference_identifier,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.compilationUnit) {
+      return {
+        "compilationUnit_declarations": compilationUnit_declarations,
+        "compilationUnit_scriptTag": compilationUnit_scriptTag,
+        "compilationUnit_directives": compilationUnit_directives,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.conditionalExpression) {
+      return {
+        "conditionalExpression_condition": conditionalExpression_condition,
+        "conditionalExpression_elseExpression":
+            conditionalExpression_elseExpression,
+        "conditionalExpression_thenExpression":
+            conditionalExpression_thenExpression,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.configuration) {
+      return {
+        "configuration_name": configuration_name,
+        "configuration_value": configuration_value,
+        "configuration_uri": configuration_uri,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+      return {
+        "constructorDeclaration_initializers":
+            constructorDeclaration_initializers,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "constructorDeclaration_body": constructorDeclaration_body,
+        "constructorDeclaration_parameters": constructorDeclaration_parameters,
+        "constructorDeclaration_redirectedConstructor":
+            constructorDeclaration_redirectedConstructor,
+        "constructorDeclaration_returnType": constructorDeclaration_returnType,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
+      return {
+        "constructorFieldInitializer_expression":
+            constructorFieldInitializer_expression,
+        "constructorFieldInitializer_fieldName":
+            constructorFieldInitializer_fieldName,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.constructorName) {
+      return {
+        "constructorName_name": constructorName_name,
+        "constructorName_type": constructorName_type,
+        "constructorName_elementType": constructorName_elementType,
+        "constructorName_element": constructorName_element,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.continueStatement) {
+      return {
+        "continueStatement_label": continueStatement_label,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.declaredIdentifier) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "declaredIdentifier_identifier": declaredIdentifier_identifier,
+        "declaredIdentifier_type": declaredIdentifier_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+      return {
+        "defaultFormalParameter_defaultValue":
+            defaultFormalParameter_defaultValue,
+        "defaultFormalParameter_parameter": defaultFormalParameter_parameter,
+        "defaultFormalParameter_kind": defaultFormalParameter_kind,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.doStatement) {
+      return {
+        "doStatement_body": doStatement_body,
+        "doStatement_condition": doStatement_condition,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.dottedName) {
+      return {
+        "dottedName_components": dottedName_components,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.doubleLiteral) {
+      return {
+        "doubleLiteral_value": doubleLiteral_value,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+      return {
+        "emptyFunctionBody_fake": emptyFunctionBody_fake,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.emptyStatement) {
+      return {
+        "emptyStatement_fake": emptyStatement_fake,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.enumDeclaration) {
+      return {
+        "enumDeclaration_constants": enumDeclaration_constants,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.exportDirective) {
+      return {
+        "namespaceDirective_combinators": namespaceDirective_combinators,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "namespaceDirective_configurations": namespaceDirective_configurations,
+        "flags": flags,
+        "informativeId": informativeId,
+        "uriBasedDirective_uri": uriBasedDirective_uri,
+        "kind": kind,
+        "name": name,
+        "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
+        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
+        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
+      return {
+        "expressionFunctionBody_expression": expressionFunctionBody_expression,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.expressionStatement) {
+      return {
+        "expressionStatement_expression": expressionStatement_expression,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.extendsClause) {
+      return {
+        "extendsClause_superclass": extendsClause_superclass,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "fieldDeclaration_fields": fieldDeclaration_fields,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+      return {
+        "actualType": actualType,
+        "normalFormalParameter_metadata": normalFormalParameter_metadata,
+        "fieldFormalParameter_type": fieldFormalParameter_type,
+        "fieldFormalParameter_typeParameters":
+            fieldFormalParameter_typeParameters,
+        "fieldFormalParameter_formalParameters":
+            fieldFormalParameter_formalParameters,
+        "inheritsCovariant": inheritsCovariant,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
+      return {
+        "forEachParts_iterable": forEachParts_iterable,
+        "forEachPartsWithDeclaration_loopVariable":
+            forEachPartsWithDeclaration_loopVariable,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
+      return {
+        "forEachParts_iterable": forEachParts_iterable,
+        "forEachPartsWithIdentifier_identifier":
+            forEachPartsWithIdentifier_identifier,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forElement) {
+      return {
+        "forMixin_forLoopParts": forMixin_forLoopParts,
+        "forElement_body": forElement_body,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
+      return {
+        "forParts_condition": forParts_condition,
+        "forPartsWithDeclarations_variables":
+            forPartsWithDeclarations_variables,
+        "forParts_updaters": forParts_updaters,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
+      return {
+        "forParts_condition": forParts_condition,
+        "forPartsWithExpression_initialization":
+            forPartsWithExpression_initialization,
+        "forParts_updaters": forParts_updaters,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forStatement) {
+      return {
+        "forMixin_forLoopParts": forMixin_forLoopParts,
+        "forStatement_body": forStatement_body,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.formalParameterList) {
+      return {
+        "formalParameterList_parameters": formalParameterList_parameters,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
     if (kind == idl.LinkedNodeKind.functionDeclaration) {
       return {
         "actualReturnType": actualReturnType,
-        "annotatedNode_comment": annotatedNode_comment,
         "annotatedNode_metadata": annotatedNode_metadata,
         "functionDeclaration_functionExpression":
             functionDeclaration_functionExpression,
-        "functionDeclaration_externalKeyword":
-            functionDeclaration_externalKeyword,
         "functionDeclaration_returnType": functionDeclaration_returnType,
-        "functionDeclaration_propertyKeyword":
-            functionDeclaration_propertyKeyword,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
-        "isSynthetic": isSynthetic,
+        "flags": flags,
+        "informativeId": informativeId,
         "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
+      return {
+        "functionDeclarationStatement_functionDeclaration":
+            functionDeclarationStatement_functionDeclaration,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.functionExpression) {
@@ -17259,91 +14831,41 @@
         "functionExpression_formalParameters":
             functionExpression_formalParameters,
         "functionExpression_typeParameters": functionExpression_typeParameters,
-        "isSynthetic": isSynthetic,
+        "flags": flags,
         "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+      return {
+        "invocationExpression_invokeType": invocationExpression_invokeType,
+        "functionExpressionInvocation_function":
+            functionExpressionInvocation_function,
+        "invocationExpression_typeArguments":
+            invocationExpression_typeArguments,
+        "expression_type": expression_type,
+        "flags": flags,
+        "invocationExpression_arguments": invocationExpression_arguments,
+        "kind": kind,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.functionTypeAlias) {
       return {
         "actualReturnType": actualReturnType,
-        "annotatedNode_comment": annotatedNode_comment,
         "annotatedNode_metadata": annotatedNode_metadata,
         "functionTypeAlias_formalParameters":
             functionTypeAlias_formalParameters,
         "functionTypeAlias_returnType": functionTypeAlias_returnType,
         "functionTypeAlias_typeParameters": functionTypeAlias_typeParameters,
-        "typeAlias_typedefKeyword": typeAlias_typedefKeyword,
-        "typeAlias_semicolon": typeAlias_semicolon,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
-        "isSynthetic": isSynthetic,
+        "typeAlias_hasSelfReference": typeAlias_hasSelfReference,
+        "flags": flags,
+        "informativeId": informativeId,
         "kind": kind,
+        "name": name,
         "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
       };
     }
-    if (kind == idl.LinkedNodeKind.genericFunctionType) {
-      return {
-        "actualReturnType": actualReturnType,
-        "genericFunctionType_typeParameters":
-            genericFunctionType_typeParameters,
-        "genericFunctionType_functionKeyword":
-            genericFunctionType_functionKeyword,
-        "genericFunctionType_returnType": genericFunctionType_returnType,
-        "genericFunctionType_formalParameters":
-            genericFunctionType_formalParameters,
-        "genericFunctionType_question": genericFunctionType_question,
-        "genericFunctionType_type": genericFunctionType_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.methodDeclaration) {
-      return {
-        "actualReturnType": actualReturnType,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "methodDeclaration_body": methodDeclaration_body,
-        "methodDeclaration_externalKeyword": methodDeclaration_externalKeyword,
-        "methodDeclaration_formalParameters":
-            methodDeclaration_formalParameters,
-        "methodDeclaration_returnType": methodDeclaration_returnType,
-        "methodDeclaration_modifierKeyword": methodDeclaration_modifierKeyword,
-        "methodDeclaration_operatorKeyword": methodDeclaration_operatorKeyword,
-        "methodDeclaration_propertyKeyword": methodDeclaration_propertyKeyword,
-        "methodDeclaration_actualProperty": methodDeclaration_actualProperty,
-        "methodDeclaration_typeParameters": methodDeclaration_typeParameters,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "methodDeclaration_name": methodDeclaration_name,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
-      return {
-        "actualType": actualType,
-        "normalFormalParameter_metadata": normalFormalParameter_metadata,
-        "fieldFormalParameter_type": fieldFormalParameter_type,
-        "fieldFormalParameter_keyword": fieldFormalParameter_keyword,
-        "fieldFormalParameter_typeParameters":
-            fieldFormalParameter_typeParameters,
-        "fieldFormalParameter_formalParameters":
-            fieldFormalParameter_formalParameters,
-        "fieldFormalParameter_period": fieldFormalParameter_period,
-        "fieldFormalParameter_thisKeyword": fieldFormalParameter_thisKeyword,
-        "normalFormalParameter_covariantKeyword":
-            normalFormalParameter_covariantKeyword,
-        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
-        "normalFormalParameter_identifier": normalFormalParameter_identifier,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "formalParameter_kind": formalParameter_kind,
-        "normalFormalParameter_comment": normalFormalParameter_comment,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
     if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
       return {
         "actualType": actualType,
@@ -17354,16 +14876,422 @@
             functionTypedFormalParameter_returnType,
         "functionTypedFormalParameter_typeParameters":
             functionTypedFormalParameter_typeParameters,
-        "normalFormalParameter_covariantKeyword":
-            normalFormalParameter_covariantKeyword,
-        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
-        "normalFormalParameter_identifier": normalFormalParameter_identifier,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "formalParameter_kind": formalParameter_kind,
-        "normalFormalParameter_comment": normalFormalParameter_comment,
-        "isSynthetic": isSynthetic,
+        "inheritsCovariant": inheritsCovariant,
+        "flags": flags,
+        "informativeId": informativeId,
         "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.genericFunctionType) {
+      return {
+        "actualReturnType": actualReturnType,
+        "genericFunctionType_typeParameters":
+            genericFunctionType_typeParameters,
+        "genericFunctionType_returnType": genericFunctionType_returnType,
+        "genericFunctionType_id": genericFunctionType_id,
+        "genericFunctionType_formalParameters":
+            genericFunctionType_formalParameters,
+        "genericFunctionType_type": genericFunctionType_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "genericTypeAlias_typeParameters": genericTypeAlias_typeParameters,
+        "genericTypeAlias_functionType": genericTypeAlias_functionType,
+        "typeAlias_hasSelfReference": typeAlias_hasSelfReference,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.hideCombinator) {
+      return {
+        "flags": flags,
+        "kind": kind,
+        "names": names,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.ifElement) {
+      return {
+        "ifMixin_condition": ifMixin_condition,
+        "ifElement_thenElement": ifElement_thenElement,
+        "ifElement_elseElement": ifElement_elseElement,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.ifStatement) {
+      return {
+        "ifMixin_condition": ifMixin_condition,
+        "ifStatement_elseStatement": ifStatement_elseStatement,
+        "ifStatement_thenStatement": ifStatement_thenStatement,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.implementsClause) {
+      return {
+        "implementsClause_interfaces": implementsClause_interfaces,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.importDirective) {
+      return {
+        "namespaceDirective_combinators": namespaceDirective_combinators,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "importDirective_prefixOffset": importDirective_prefixOffset,
+        "namespaceDirective_configurations": namespaceDirective_configurations,
+        "flags": flags,
+        "importDirective_prefix": importDirective_prefix,
+        "informativeId": informativeId,
+        "uriBasedDirective_uri": uriBasedDirective_uri,
+        "kind": kind,
+        "name": name,
+        "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
+        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
+        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.indexExpression) {
+      return {
+        "indexExpression_index": indexExpression_index,
+        "indexExpression_target": indexExpression_target,
+        "indexExpression_elementType": indexExpression_elementType,
+        "indexExpression_element": indexExpression_element,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+      return {
+        "instanceCreationExpression_arguments":
+            instanceCreationExpression_arguments,
+        "instanceCreationExpression_constructorName":
+            instanceCreationExpression_constructorName,
+        "instanceCreationExpression_typeArguments":
+            instanceCreationExpression_typeArguments,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.integerLiteral) {
+      return {
+        "flags": flags,
+        "integerLiteral_value": integerLiteral_value,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.interpolationExpression) {
+      return {
+        "interpolationExpression_expression":
+            interpolationExpression_expression,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.interpolationString) {
+      return {
+        "flags": flags,
+        "interpolationString_value": interpolationString_value,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.isExpression) {
+      return {
+        "isExpression_expression": isExpression_expression,
+        "isExpression_type": isExpression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.label) {
+      return {
+        "label_label": label_label,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.labeledStatement) {
+      return {
+        "labeledStatement_labels": labeledStatement_labels,
+        "labeledStatement_statement": labeledStatement_statement,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.libraryDirective) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "libraryDirective_name": libraryDirective_name,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+      return {
+        "libraryIdentifier_components": libraryIdentifier_components,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.listLiteral) {
+      return {
+        "typedLiteral_typeArguments": typedLiteral_typeArguments,
+        "listLiteral_elements": listLiteral_elements,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
+      return {
+        "mapLiteralEntry_key": mapLiteralEntry_key,
+        "mapLiteralEntry_value": mapLiteralEntry_value,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.methodDeclaration) {
+      return {
+        "actualReturnType": actualReturnType,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "methodDeclaration_body": methodDeclaration_body,
+        "methodDeclaration_formalParameters":
+            methodDeclaration_formalParameters,
+        "methodDeclaration_returnType": methodDeclaration_returnType,
+        "methodDeclaration_typeParameters": methodDeclaration_typeParameters,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.methodInvocation) {
+      return {
+        "invocationExpression_invokeType": invocationExpression_invokeType,
+        "methodInvocation_methodName": methodInvocation_methodName,
+        "methodInvocation_target": methodInvocation_target,
+        "invocationExpression_typeArguments":
+            invocationExpression_typeArguments,
+        "expression_type": expression_type,
+        "flags": flags,
+        "invocationExpression_arguments": invocationExpression_arguments,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "mixinDeclaration_onClause": mixinDeclaration_onClause,
+        "classOrMixinDeclaration_implementsClause":
+            classOrMixinDeclaration_implementsClause,
+        "classOrMixinDeclaration_members": classOrMixinDeclaration_members,
+        "classOrMixinDeclaration_typeParameters":
+            classOrMixinDeclaration_typeParameters,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "mixinDeclaration_superInvokedNames":
+            mixinDeclaration_superInvokedNames,
+        "name": name,
+        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.namedExpression) {
+      return {
+        "namedExpression_expression": namedExpression_expression,
+        "namedExpression_name": namedExpression_name,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.nativeClause) {
+      return {
+        "nativeClause_name": nativeClause_name,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
+      return {
+        "nativeFunctionBody_stringLiteral": nativeFunctionBody_stringLiteral,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.nullLiteral) {
+      return {
+        "nullLiteral_fake": nullLiteral_fake,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.onClause) {
+      return {
+        "onClause_superclassConstraints": onClause_superclassConstraints,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
+      return {
+        "parenthesizedExpression_expression":
+            parenthesizedExpression_expression,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.partDirective) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "flags": flags,
+        "informativeId": informativeId,
+        "uriBasedDirective_uri": uriBasedDirective_uri,
+        "kind": kind,
+        "name": name,
+        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
+        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.partOfDirective) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "partOfDirective_libraryName": partOfDirective_libraryName,
+        "partOfDirective_uri": partOfDirective_uri,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.postfixExpression) {
+      return {
+        "postfixExpression_operand": postfixExpression_operand,
+        "postfixExpression_elementType": postfixExpression_elementType,
+        "postfixExpression_element": postfixExpression_element,
+        "postfixExpression_operator": postfixExpression_operator,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.prefixExpression) {
+      return {
+        "prefixExpression_operand": prefixExpression_operand,
+        "prefixExpression_elementType": prefixExpression_elementType,
+        "prefixExpression_element": prefixExpression_element,
+        "prefixExpression_operator": prefixExpression_operator,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+      return {
+        "prefixedIdentifier_identifier": prefixedIdentifier_identifier,
+        "prefixedIdentifier_prefix": prefixedIdentifier_prefix,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.propertyAccess) {
+      return {
+        "propertyAccess_propertyName": propertyAccess_propertyName,
+        "propertyAccess_target": propertyAccess_target,
+        "propertyAccess_operator": propertyAccess_operator,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
+      return {
+        "redirectingConstructorInvocation_arguments":
+            redirectingConstructorInvocation_arguments,
+        "redirectingConstructorInvocation_constructorName":
+            redirectingConstructorInvocation_constructorName,
+        "redirectingConstructorInvocation_elementType":
+            redirectingConstructorInvocation_elementType,
+        "redirectingConstructorInvocation_element":
+            redirectingConstructorInvocation_element,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.rethrowExpression) {
+      return {
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.returnStatement) {
+      return {
+        "returnStatement_expression": returnStatement_expression,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+      return {
+        "typedLiteral_typeArguments": typedLiteral_typeArguments,
+        "setOrMapLiteral_elements": setOrMapLiteral_elements,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.showCombinator) {
+      return {
+        "flags": flags,
+        "kind": kind,
+        "names": names,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
@@ -17371,1256 +15299,240 @@
         "actualType": actualType,
         "normalFormalParameter_metadata": normalFormalParameter_metadata,
         "simpleFormalParameter_type": simpleFormalParameter_type,
-        "simpleFormalParameter_keyword": simpleFormalParameter_keyword,
-        "normalFormalParameter_covariantKeyword":
-            normalFormalParameter_covariantKeyword,
-        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
-        "normalFormalParameter_identifier": normalFormalParameter_identifier,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "formalParameter_kind": formalParameter_kind,
-        "normalFormalParameter_comment": normalFormalParameter_comment,
-        "isSynthetic": isSynthetic,
+        "inheritsCovariant": inheritsCovariant,
+        "flags": flags,
+        "informativeId": informativeId,
         "kind": kind,
+        "name": name,
+        "topLevelTypeInferenceError": topLevelTypeInferenceError,
       };
     }
-    if (kind == idl.LinkedNodeKind.variableDeclaration) {
+    if (kind == idl.LinkedNodeKind.simpleIdentifier) {
       return {
-        "actualType": actualType,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "variableDeclaration_initializer": variableDeclaration_initializer,
-        "variableDeclaration_equals": variableDeclaration_equals,
-        "variableDeclaration_name": variableDeclaration_name,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-        "variableDeclaration_declaration": variableDeclaration_declaration,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.binaryExpression) {
-      return {
-        "binaryExpression_invokeType": binaryExpression_invokeType,
-        "binaryExpression_leftOperand": binaryExpression_leftOperand,
-        "binaryExpression_element": binaryExpression_element,
-        "binaryExpression_rightOperand": binaryExpression_rightOperand,
-        "binaryExpression_operator": binaryExpression_operator,
-        "binaryExpression_elementType": binaryExpression_elementType,
+        "simpleIdentifier_elementType": simpleIdentifier_elementType,
+        "simpleIdentifier_element": simpleIdentifier_element,
         "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
+        "flags": flags,
         "kind": kind,
+        "name": name,
       };
     }
-    if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+    if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
       return {
-        "invocationExpression_invokeType": invocationExpression_invokeType,
-        "functionExpressionInvocation_function":
-            functionExpressionInvocation_function,
-        "invocationExpression_typeArguments":
-            invocationExpression_typeArguments,
-        "expression_type": expression_type,
-        "invocationExpression_arguments": invocationExpression_arguments,
-        "isSynthetic": isSynthetic,
+        "flags": flags,
         "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.methodInvocation) {
-      return {
-        "invocationExpression_invokeType": invocationExpression_invokeType,
-        "methodInvocation_methodName": methodInvocation_methodName,
-        "methodInvocation_operator": methodInvocation_operator,
-        "methodInvocation_target": methodInvocation_target,
-        "invocationExpression_typeArguments":
-            invocationExpression_typeArguments,
-        "expression_type": expression_type,
-        "invocationExpression_arguments": invocationExpression_arguments,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.adjacentStrings) {
-      return {
-        "adjacentStrings_strings": adjacentStrings_strings,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.argumentList) {
-      return {
-        "argumentList_arguments": argumentList_arguments,
-        "argumentList_leftParenthesis": argumentList_leftParenthesis,
-        "argumentList_rightParenthesis": argumentList_rightParenthesis,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.block) {
-      return {
-        "block_statements": block_statements,
-        "block_leftBracket": block_leftBracket,
-        "block_rightBracket": block_rightBracket,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.cascadeExpression) {
-      return {
-        "cascadeExpression_sections": cascadeExpression_sections,
-        "cascadeExpression_target": cascadeExpression_target,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.compilationUnit) {
-      return {
-        "compilationUnit_declarations": compilationUnit_declarations,
-        "compilationUnit_scriptTag": compilationUnit_scriptTag,
-        "compilationUnit_beginToken": compilationUnit_beginToken,
-        "compilationUnit_endToken": compilationUnit_endToken,
-        "compilationUnit_directives": compilationUnit_directives,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.constructorDeclaration) {
-      return {
-        "constructorDeclaration_initializers":
-            constructorDeclaration_initializers,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "constructorDeclaration_body": constructorDeclaration_body,
-        "constructorDeclaration_constKeyword":
-            constructorDeclaration_constKeyword,
-        "constructorDeclaration_name": constructorDeclaration_name,
-        "constructorDeclaration_parameters": constructorDeclaration_parameters,
-        "constructorDeclaration_externalKeyword":
-            constructorDeclaration_externalKeyword,
-        "constructorDeclaration_factoryKeyword":
-            constructorDeclaration_factoryKeyword,
-        "constructorDeclaration_period": constructorDeclaration_period,
-        "constructorDeclaration_separator": constructorDeclaration_separator,
-        "constructorDeclaration_redirectedConstructor":
-            constructorDeclaration_redirectedConstructor,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "constructorDeclaration_returnType": constructorDeclaration_returnType,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.dottedName) {
-      return {
-        "dottedName_components": dottedName_components,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.enumDeclaration) {
-      return {
-        "enumDeclaration_constants": enumDeclaration_constants,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "enumDeclaration_enumKeyword": enumDeclaration_enumKeyword,
-        "enumDeclaration_leftBracket": enumDeclaration_leftBracket,
-        "enumDeclaration_rightBracket": enumDeclaration_rightBracket,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.formalParameterList) {
-      return {
-        "formalParameterList_parameters": formalParameterList_parameters,
-        "formalParameterList_leftDelimiter": formalParameterList_leftDelimiter,
-        "formalParameterList_leftParenthesis":
-            formalParameterList_leftParenthesis,
-        "formalParameterList_rightDelimiter":
-            formalParameterList_rightDelimiter,
-        "formalParameterList_rightParenthesis":
-            formalParameterList_rightParenthesis,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.hideCombinator) {
-      return {
-        "hideCombinator_hiddenNames": hideCombinator_hiddenNames,
-        "combinator_keyword": combinator_keyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.implementsClause) {
-      return {
-        "implementsClause_interfaces": implementsClause_interfaces,
-        "implementsClause_implementsKeyword":
-            implementsClause_implementsKeyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.labeledStatement) {
-      return {
-        "labeledStatement_labels": labeledStatement_labels,
-        "labeledStatement_statement": labeledStatement_statement,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.libraryIdentifier) {
-      return {
-        "libraryIdentifier_components": libraryIdentifier_components,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.listLiteral) {
-      return {
-        "listLiteral_elements": listLiteral_elements,
-        "listLiteral_leftBracket": listLiteral_leftBracket,
-        "listLiteral_rightBracket": listLiteral_rightBracket,
-        "typedLiteral_constKeyword": typedLiteral_constKeyword,
-        "expression_type": expression_type,
-        "typedLiteral_typeArguments": typedLiteral_typeArguments,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.exportDirective) {
-      return {
-        "namespaceDirective_combinators": namespaceDirective_combinators,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "directive_keyword": directive_keyword,
-        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
-        "directive_semicolon": directive_semicolon,
-        "namespaceDirective_configurations": namespaceDirective_configurations,
-        "uriBasedDirective_uri": uriBasedDirective_uri,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-        "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
-        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.importDirective) {
-      return {
-        "namespaceDirective_combinators": namespaceDirective_combinators,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "importDirective_prefix": importDirective_prefix,
-        "importDirective_asKeyword": importDirective_asKeyword,
-        "importDirective_deferredKeyword": importDirective_deferredKeyword,
-        "directive_keyword": directive_keyword,
-        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
-        "directive_semicolon": directive_semicolon,
-        "namespaceDirective_configurations": namespaceDirective_configurations,
-        "uriBasedDirective_uri": uriBasedDirective_uri,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-        "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
-        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.onClause) {
-      return {
-        "onClause_superclassConstraints": onClause_superclassConstraints,
-        "onClause_onKeyword": onClause_onKeyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
-      return {
-        "setOrMapLiteral_elements": setOrMapLiteral_elements,
-        "setOrMapLiteral_leftBracket": setOrMapLiteral_leftBracket,
-        "setOrMapLiteral_rightBracket": setOrMapLiteral_rightBracket,
-        "typedLiteral_constKeyword": typedLiteral_constKeyword,
-        "setOrMapLiteral_isMap": setOrMapLiteral_isMap,
-        "expression_type": expression_type,
-        "typedLiteral_typeArguments": typedLiteral_typeArguments,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-        "setOrMapLiteral_isSet": setOrMapLiteral_isSet,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.showCombinator) {
-      return {
-        "showCombinator_shownNames": showCombinator_shownNames,
-        "combinator_keyword": combinator_keyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.stringInterpolation) {
-      return {
-        "stringInterpolation_elements": stringInterpolation_elements,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.switchStatement) {
-      return {
-        "switchStatement_members": switchStatement_members,
-        "switchStatement_leftParenthesis": switchStatement_leftParenthesis,
-        "switchStatement_expression": switchStatement_expression,
-        "switchStatement_rightParenthesis": switchStatement_rightParenthesis,
-        "switchStatement_switchKeyword": switchStatement_switchKeyword,
-        "switchStatement_leftBracket": switchStatement_leftBracket,
-        "switchStatement_rightBracket": switchStatement_rightBracket,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.tryStatement) {
-      return {
-        "tryStatement_catchClauses": tryStatement_catchClauses,
-        "tryStatement_body": tryStatement_body,
-        "tryStatement_finallyKeyword": tryStatement_finallyKeyword,
-        "tryStatement_finallyBlock": tryStatement_finallyBlock,
-        "tryStatement_tryKeyword": tryStatement_tryKeyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.typeArgumentList) {
-      return {
-        "typeArgumentList_arguments": typeArgumentList_arguments,
-        "typeArgumentList_leftBracket": typeArgumentList_leftBracket,
-        "typeArgumentList_rightBracket": typeArgumentList_rightBracket,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.typeParameterList) {
-      return {
-        "typeParameterList_typeParameters": typeParameterList_typeParameters,
-        "typeParameterList_leftBracket": typeParameterList_leftBracket,
-        "typeParameterList_rightBracket": typeParameterList_rightBracket,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.variableDeclarationList) {
-      return {
-        "variableDeclarationList_variables": variableDeclarationList_variables,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "variableDeclarationList_type": variableDeclarationList_type,
-        "variableDeclarationList_keyword": variableDeclarationList_keyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.withClause) {
-      return {
-        "withClause_mixinTypes": withClause_mixinTypes,
-        "withClause_withKeyword": withClause_withKeyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.classDeclaration) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "classDeclaration_extendsClause": classDeclaration_extendsClause,
-        "classDeclaration_abstractKeyword": classDeclaration_abstractKeyword,
-        "classDeclaration_withClause": classDeclaration_withClause,
-        "classDeclaration_nativeClause": classDeclaration_nativeClause,
-        "classDeclaration_classKeyword": classDeclaration_classKeyword,
-        "classOrMixinDeclaration_rightBracket":
-            classOrMixinDeclaration_rightBracket,
-        "classOrMixinDeclaration_leftBracket":
-            classOrMixinDeclaration_leftBracket,
-        "classDeclaration_isDartObject": classDeclaration_isDartObject,
-        "classOrMixinDeclaration_implementsClause":
-            classOrMixinDeclaration_implementsClause,
-        "classOrMixinDeclaration_members": classOrMixinDeclaration_members,
-        "classOrMixinDeclaration_typeParameters":
-            classOrMixinDeclaration_typeParameters,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.classTypeAlias) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "classTypeAlias_typeParameters": classTypeAlias_typeParameters,
-        "classTypeAlias_abstractKeyword": classTypeAlias_abstractKeyword,
-        "classTypeAlias_superclass": classTypeAlias_superclass,
-        "classTypeAlias_withClause": classTypeAlias_withClause,
-        "classTypeAlias_equals": classTypeAlias_equals,
-        "typeAlias_typedefKeyword": typeAlias_typedefKeyword,
-        "typeAlias_semicolon": typeAlias_semicolon,
-        "classTypeAlias_implementsClause": classTypeAlias_implementsClause,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.declaredIdentifier) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "declaredIdentifier_identifier": declaredIdentifier_identifier,
-        "declaredIdentifier_keyword": declaredIdentifier_keyword,
-        "declaredIdentifier_type": declaredIdentifier_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "enumConstantDeclaration_name": enumConstantDeclaration_name,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.fieldDeclaration) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "fieldDeclaration_fields": fieldDeclaration_fields,
-        "fieldDeclaration_covariantKeyword": fieldDeclaration_covariantKeyword,
-        "fieldDeclaration_semicolon": fieldDeclaration_semicolon,
-        "fieldDeclaration_staticKeyword": fieldDeclaration_staticKeyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.genericTypeAlias) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "genericTypeAlias_typeParameters": genericTypeAlias_typeParameters,
-        "genericTypeAlias_functionType": genericTypeAlias_functionType,
-        "genericTypeAlias_equals": genericTypeAlias_equals,
-        "typeAlias_typedefKeyword": typeAlias_typedefKeyword,
-        "typeAlias_semicolon": typeAlias_semicolon,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.libraryDirective) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "libraryDirective_name": libraryDirective_name,
-        "directive_keyword": directive_keyword,
-        "directive_semicolon": directive_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.mixinDeclaration) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "mixinDeclaration_onClause": mixinDeclaration_onClause,
-        "mixinDeclaration_mixinKeyword": mixinDeclaration_mixinKeyword,
-        "classOrMixinDeclaration_rightBracket":
-            classOrMixinDeclaration_rightBracket,
-        "classOrMixinDeclaration_leftBracket":
-            classOrMixinDeclaration_leftBracket,
-        "classOrMixinDeclaration_implementsClause":
-            classOrMixinDeclaration_implementsClause,
-        "classOrMixinDeclaration_members": classOrMixinDeclaration_members,
-        "classOrMixinDeclaration_typeParameters":
-            classOrMixinDeclaration_typeParameters,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.partDirective) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "directive_keyword": directive_keyword,
-        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
-        "directive_semicolon": directive_semicolon,
-        "uriBasedDirective_uri": uriBasedDirective_uri,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.partOfDirective) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "partOfDirective_libraryName": partOfDirective_libraryName,
-        "partOfDirective_uri": partOfDirective_uri,
-        "partOfDirective_ofKeyword": partOfDirective_ofKeyword,
-        "directive_keyword": directive_keyword,
-        "directive_semicolon": directive_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "topLevelVariableDeclaration_variableList":
-            topLevelVariableDeclaration_variableList,
-        "topLevelVariableDeclaration_semicolon":
-            topLevelVariableDeclaration_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.typeParameter) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "typeParameter_bound": typeParameter_bound,
-        "typeParameter_extendsKeyword": typeParameter_extendsKeyword,
-        "typeParameter_name": typeParameter_name,
-        "typeParameter_id": typeParameter_id,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.switchCase) {
-      return {
-        "switchMember_statements": switchMember_statements,
-        "switchCase_expression": switchCase_expression,
-        "switchMember_keyword": switchMember_keyword,
-        "switchMember_colon": switchMember_colon,
-        "switchMember_labels": switchMember_labels,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.switchDefault) {
-      return {
-        "switchMember_statements": switchMember_statements,
-        "switchMember_keyword": switchMember_keyword,
-        "switchMember_colon": switchMember_colon,
-        "switchMember_labels": switchMember_labels,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.annotation) {
-      return {
-        "annotation_arguments": annotation_arguments,
-        "annotation_atSign": annotation_atSign,
-        "annotation_constructorName": annotation_constructorName,
-        "annotation_name": annotation_name,
-        "annotation_period": annotation_period,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.asExpression) {
-      return {
-        "asExpression_expression": asExpression_expression,
-        "asExpression_asOperator": asExpression_asOperator,
-        "asExpression_type": asExpression_type,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.assertInitializer) {
-      return {
-        "assertInitializer_condition": assertInitializer_condition,
-        "assertInitializer_assertKeyword": assertInitializer_assertKeyword,
-        "assertInitializer_message": assertInitializer_message,
-        "assertInitializer_comma": assertInitializer_comma,
-        "assertInitializer_leftParenthesis": assertInitializer_leftParenthesis,
-        "assertInitializer_rightParenthesis":
-            assertInitializer_rightParenthesis,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.assertStatement) {
-      return {
-        "assertStatement_condition": assertStatement_condition,
-        "assertStatement_assertKeyword": assertStatement_assertKeyword,
-        "assertStatement_message": assertStatement_message,
-        "assertStatement_comma": assertStatement_comma,
-        "assertStatement_leftParenthesis": assertStatement_leftParenthesis,
-        "assertStatement_rightParenthesis": assertStatement_rightParenthesis,
-        "assertStatement_semicolon": assertStatement_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.assignmentExpression) {
-      return {
-        "assignmentExpression_leftHandSide": assignmentExpression_leftHandSide,
-        "assignmentExpression_element": assignmentExpression_element,
-        "assignmentExpression_rightHandSide":
-            assignmentExpression_rightHandSide,
-        "assignmentExpression_operator": assignmentExpression_operator,
-        "assignmentExpression_elementType": assignmentExpression_elementType,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.awaitExpression) {
-      return {
-        "awaitExpression_expression": awaitExpression_expression,
-        "awaitExpression_awaitKeyword": awaitExpression_awaitKeyword,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.blockFunctionBody) {
-      return {
-        "blockFunctionBody_block": blockFunctionBody_block,
-        "blockFunctionBody_keyword": blockFunctionBody_keyword,
-        "blockFunctionBody_star": blockFunctionBody_star,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.breakStatement) {
-      return {
-        "breakStatement_label": breakStatement_label,
-        "breakStatement_breakKeyword": breakStatement_breakKeyword,
-        "breakStatement_semicolon": breakStatement_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.catchClause) {
-      return {
-        "catchClause_body": catchClause_body,
-        "catchClause_catchKeyword": catchClause_catchKeyword,
-        "catchClause_exceptionParameter": catchClause_exceptionParameter,
-        "catchClause_exceptionType": catchClause_exceptionType,
-        "catchClause_comma": catchClause_comma,
-        "catchClause_leftParenthesis": catchClause_leftParenthesis,
-        "catchClause_onKeyword": catchClause_onKeyword,
-        "catchClause_rightParenthesis": catchClause_rightParenthesis,
-        "catchClause_stackTraceParameter": catchClause_stackTraceParameter,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.conditionalExpression) {
-      return {
-        "conditionalExpression_condition": conditionalExpression_condition,
-        "conditionalExpression_colon": conditionalExpression_colon,
-        "conditionalExpression_elseExpression":
-            conditionalExpression_elseExpression,
-        "conditionalExpression_thenExpression":
-            conditionalExpression_thenExpression,
-        "conditionalExpression_question": conditionalExpression_question,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.configuration) {
-      return {
-        "configuration_name": configuration_name,
-        "configuration_ifKeyword": configuration_ifKeyword,
-        "configuration_value": configuration_value,
-        "configuration_uri": configuration_uri,
-        "configuration_leftParenthesis": configuration_leftParenthesis,
-        "configuration_rightParenthesis": configuration_rightParenthesis,
-        "configuration_equalToken": configuration_equalToken,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
-      return {
-        "constructorFieldInitializer_expression":
-            constructorFieldInitializer_expression,
-        "constructorFieldInitializer_equals":
-            constructorFieldInitializer_equals,
-        "constructorFieldInitializer_fieldName":
-            constructorFieldInitializer_fieldName,
-        "constructorFieldInitializer_period":
-            constructorFieldInitializer_period,
-        "constructorFieldInitializer_thisKeyword":
-            constructorFieldInitializer_thisKeyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.constructorName) {
-      return {
-        "constructorName_name": constructorName_name,
-        "constructorName_element": constructorName_element,
-        "constructorName_type": constructorName_type,
-        "constructorName_period": constructorName_period,
-        "constructorName_elementType": constructorName_elementType,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.continueStatement) {
-      return {
-        "continueStatement_label": continueStatement_label,
-        "continueStatement_continueKeyword": continueStatement_continueKeyword,
-        "continueStatement_semicolon": continueStatement_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
-      return {
-        "defaultFormalParameter_defaultValue":
-            defaultFormalParameter_defaultValue,
-        "defaultFormalParameter_separator": defaultFormalParameter_separator,
-        "defaultFormalParameter_parameter": defaultFormalParameter_parameter,
-        "defaultFormalParameter_isNamed": defaultFormalParameter_isNamed,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.doStatement) {
-      return {
-        "doStatement_body": doStatement_body,
-        "doStatement_leftParenthesis": doStatement_leftParenthesis,
-        "doStatement_condition": doStatement_condition,
-        "doStatement_rightParenthesis": doStatement_rightParenthesis,
-        "doStatement_doKeyword": doStatement_doKeyword,
-        "doStatement_semicolon": doStatement_semicolon,
-        "doStatement_whileKeyword": doStatement_whileKeyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
-      return {
-        "expressionFunctionBody_expression": expressionFunctionBody_expression,
-        "expressionFunctionBody_arrow": expressionFunctionBody_arrow,
-        "expressionFunctionBody_keyword": expressionFunctionBody_keyword,
-        "expressionFunctionBody_semicolon": expressionFunctionBody_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.expressionStatement) {
-      return {
-        "expressionStatement_expression": expressionStatement_expression,
-        "expressionStatement_semicolon": expressionStatement_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.extendsClause) {
-      return {
-        "extendsClause_superclass": extendsClause_superclass,
-        "extendsClause_extendsKeyword": extendsClause_extendsKeyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
-      return {
-        "forEachParts_iterable": forEachParts_iterable,
-        "forEachParts_inKeyword": forEachParts_inKeyword,
-        "forEachPartsWithDeclaration_loopVariable":
-            forEachPartsWithDeclaration_loopVariable,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
-      return {
-        "forEachParts_iterable": forEachParts_iterable,
-        "forEachParts_inKeyword": forEachParts_inKeyword,
-        "forEachPartsWithIdentifier_identifier":
-            forEachPartsWithIdentifier_identifier,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forElement) {
-      return {
-        "forMixin_forLoopParts": forMixin_forLoopParts,
-        "forMixin_awaitKeyword": forMixin_awaitKeyword,
-        "forElement_body": forElement_body,
-        "forMixin_forKeyword": forMixin_forKeyword,
-        "forMixin_leftParenthesis": forMixin_leftParenthesis,
-        "forMixin_rightParenthesis": forMixin_rightParenthesis,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forStatement) {
-      return {
-        "forMixin_forLoopParts": forMixin_forLoopParts,
-        "forMixin_awaitKeyword": forMixin_awaitKeyword,
-        "forStatement_body": forStatement_body,
-        "forMixin_forKeyword": forMixin_forKeyword,
-        "forMixin_leftParenthesis": forMixin_leftParenthesis,
-        "forMixin_rightParenthesis": forMixin_rightParenthesis,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
-      return {
-        "forParts_condition": forParts_condition,
-        "forParts_leftSeparator": forParts_leftSeparator,
-        "forPartsWithDeclarations_variables":
-            forPartsWithDeclarations_variables,
-        "forParts_rightSeparator": forParts_rightSeparator,
-        "forParts_updaters": forParts_updaters,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
-      return {
-        "forParts_condition": forParts_condition,
-        "forParts_leftSeparator": forParts_leftSeparator,
-        "forPartsWithExpression_initialization":
-            forPartsWithExpression_initialization,
-        "forParts_rightSeparator": forParts_rightSeparator,
-        "forParts_updaters": forParts_updaters,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
-      return {
-        "functionDeclarationStatement_functionDeclaration":
-            functionDeclarationStatement_functionDeclaration,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.ifElement) {
-      return {
-        "ifMixin_condition": ifMixin_condition,
-        "ifMixin_elseKeyword": ifMixin_elseKeyword,
-        "ifElement_thenElement": ifElement_thenElement,
-        "ifMixin_ifKeyword": ifMixin_ifKeyword,
-        "ifMixin_leftParenthesis": ifMixin_leftParenthesis,
-        "ifMixin_rightParenthesis": ifMixin_rightParenthesis,
-        "ifElement_elseElement": ifElement_elseElement,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.ifStatement) {
-      return {
-        "ifMixin_condition": ifMixin_condition,
-        "ifMixin_elseKeyword": ifMixin_elseKeyword,
-        "ifStatement_elseStatement": ifStatement_elseStatement,
-        "ifStatement_thenStatement": ifStatement_thenStatement,
-        "ifMixin_ifKeyword": ifMixin_ifKeyword,
-        "ifMixin_leftParenthesis": ifMixin_leftParenthesis,
-        "ifMixin_rightParenthesis": ifMixin_rightParenthesis,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.indexExpression) {
-      return {
-        "indexExpression_index": indexExpression_index,
-        "indexExpression_element": indexExpression_element,
-        "indexExpression_target": indexExpression_target,
-        "indexExpression_period": indexExpression_period,
-        "indexExpression_leftBracket": indexExpression_leftBracket,
-        "indexExpression_rightBracket": indexExpression_rightBracket,
-        "indexExpression_elementType": indexExpression_elementType,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
-      return {
-        "instanceCreationExpression_arguments":
-            instanceCreationExpression_arguments,
-        "instanceCreationExpression_keyword":
-            instanceCreationExpression_keyword,
-        "instanceCreationExpression_constructorName":
-            instanceCreationExpression_constructorName,
-        "instanceCreationExpression_typeArguments":
-            instanceCreationExpression_typeArguments,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.interpolationExpression) {
-      return {
-        "interpolationExpression_expression":
-            interpolationExpression_expression,
-        "interpolationExpression_leftBracket":
-            interpolationExpression_leftBracket,
-        "interpolationExpression_rightBracket":
-            interpolationExpression_rightBracket,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.isExpression) {
-      return {
-        "isExpression_expression": isExpression_expression,
-        "isExpression_isOperator": isExpression_isOperator,
-        "isExpression_type": isExpression_type,
-        "isExpression_notOperator": isExpression_notOperator,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.label) {
-      return {
-        "label_label": label_label,
-        "label_colon": label_colon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
-      return {
-        "mapLiteralEntry_key": mapLiteralEntry_key,
-        "mapLiteralEntry_separator": mapLiteralEntry_separator,
-        "mapLiteralEntry_value": mapLiteralEntry_value,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.namedExpression) {
-      return {
-        "namedExpression_expression": namedExpression_expression,
-        "namedExpression_name": namedExpression_name,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.nativeClause) {
-      return {
-        "nativeClause_name": nativeClause_name,
-        "nativeClause_nativeKeyword": nativeClause_nativeKeyword,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
-      return {
-        "nativeFunctionBody_stringLiteral": nativeFunctionBody_stringLiteral,
-        "nativeFunctionBody_nativeKeyword": nativeFunctionBody_nativeKeyword,
-        "nativeFunctionBody_semicolon": nativeFunctionBody_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
-      return {
-        "parenthesizedExpression_expression":
-            parenthesizedExpression_expression,
-        "parenthesizedExpression_leftParenthesis":
-            parenthesizedExpression_leftParenthesis,
-        "parenthesizedExpression_rightParenthesis":
-            parenthesizedExpression_rightParenthesis,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.postfixExpression) {
-      return {
-        "postfixExpression_operand": postfixExpression_operand,
-        "postfixExpression_element": postfixExpression_element,
-        "postfixExpression_operator": postfixExpression_operator,
-        "postfixExpression_elementType": postfixExpression_elementType,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
-      return {
-        "prefixedIdentifier_identifier": prefixedIdentifier_identifier,
-        "prefixedIdentifier_period": prefixedIdentifier_period,
-        "prefixedIdentifier_prefix": prefixedIdentifier_prefix,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.prefixExpression) {
-      return {
-        "prefixExpression_operand": prefixExpression_operand,
-        "prefixExpression_element": prefixExpression_element,
-        "prefixExpression_operator": prefixExpression_operator,
-        "prefixExpression_elementType": prefixExpression_elementType,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.propertyAccess) {
-      return {
-        "propertyAccess_propertyName": propertyAccess_propertyName,
-        "propertyAccess_operator": propertyAccess_operator,
-        "propertyAccess_target": propertyAccess_target,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
-      return {
-        "redirectingConstructorInvocation_arguments":
-            redirectingConstructorInvocation_arguments,
-        "redirectingConstructorInvocation_element":
-            redirectingConstructorInvocation_element,
-        "redirectingConstructorInvocation_constructorName":
-            redirectingConstructorInvocation_constructorName,
-        "redirectingConstructorInvocation_period":
-            redirectingConstructorInvocation_period,
-        "redirectingConstructorInvocation_thisKeyword":
-            redirectingConstructorInvocation_thisKeyword,
-        "redirectingConstructorInvocation_elementType":
-            redirectingConstructorInvocation_elementType,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.returnStatement) {
-      return {
-        "returnStatement_expression": returnStatement_expression,
-        "returnStatement_returnKeyword": returnStatement_returnKeyword,
-        "returnStatement_semicolon": returnStatement_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
+        "name": name,
+        "simpleStringLiteral_value": simpleStringLiteral_value,
       };
     }
     if (kind == idl.LinkedNodeKind.spreadElement) {
       return {
         "spreadElement_expression": spreadElement_expression,
-        "spreadElement_spreadOperator": spreadElement_spreadOperator,
-        "isSynthetic": isSynthetic,
+        "flags": flags,
         "kind": kind,
+        "name": name,
+        "spreadElement_spreadOperator": spreadElement_spreadOperator,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.stringInterpolation) {
+      return {
+        "stringInterpolation_elements": stringInterpolation_elements,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
       return {
         "superConstructorInvocation_arguments":
             superConstructorInvocation_arguments,
-        "superConstructorInvocation_element":
-            superConstructorInvocation_element,
         "superConstructorInvocation_constructorName":
             superConstructorInvocation_constructorName,
-        "superConstructorInvocation_period": superConstructorInvocation_period,
-        "superConstructorInvocation_superKeyword":
-            superConstructorInvocation_superKeyword,
         "superConstructorInvocation_elementType":
             superConstructorInvocation_elementType,
-        "isSynthetic": isSynthetic,
+        "superConstructorInvocation_element":
+            superConstructorInvocation_element,
+        "flags": flags,
         "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.superExpression) {
+      return {
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.switchCase) {
+      return {
+        "switchMember_statements": switchMember_statements,
+        "switchCase_expression": switchCase_expression,
+        "switchMember_labels": switchMember_labels,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.switchDefault) {
+      return {
+        "switchMember_statements": switchMember_statements,
+        "switchMember_labels": switchMember_labels,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.switchStatement) {
+      return {
+        "switchStatement_members": switchStatement_members,
+        "switchStatement_expression": switchStatement_expression,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.symbolLiteral) {
+      return {
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "names": names,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.thisExpression) {
+      return {
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.throwExpression) {
       return {
         "throwExpression_expression": throwExpression_expression,
-        "throwExpression_throwKeyword": throwExpression_throwKeyword,
         "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
+        "flags": flags,
         "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "topLevelVariableDeclaration_variableList":
+            topLevelVariableDeclaration_variableList,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.tryStatement) {
+      return {
+        "tryStatement_catchClauses": tryStatement_catchClauses,
+        "tryStatement_body": tryStatement_body,
+        "tryStatement_finallyBlock": tryStatement_finallyBlock,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.typeArgumentList) {
+      return {
+        "typeArgumentList_arguments": typeArgumentList_arguments,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.typeName) {
       return {
-        "typeName_name": typeName_name,
-        "typeName_question": typeName_question,
         "typeName_typeArguments": typeName_typeArguments,
+        "typeName_name": typeName_name,
         "typeName_type": typeName_type,
-        "isSynthetic": isSynthetic,
+        "flags": flags,
         "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.typeParameter) {
+      return {
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "typeParameter_bound": typeParameter_bound,
+        "typeParameter_defaultType": typeParameter_defaultType,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.typeParameterList) {
+      return {
+        "typeParameterList_typeParameters": typeParameterList_typeParameters,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.variableDeclaration) {
+      return {
+        "actualType": actualType,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "variableDeclaration_initializer": variableDeclaration_initializer,
+        "inheritsCovariant": inheritsCovariant,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
+        "topLevelTypeInferenceError": topLevelTypeInferenceError,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+      return {
+        "variableDeclarationList_variables": variableDeclarationList_variables,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "variableDeclarationList_type": variableDeclarationList_type,
+        "flags": flags,
+        "informativeId": informativeId,
+        "kind": kind,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
       return {
         "variableDeclarationStatement_variables":
             variableDeclarationStatement_variables,
-        "variableDeclarationStatement_semicolon":
-            variableDeclarationStatement_semicolon,
-        "isSynthetic": isSynthetic,
+        "flags": flags,
         "kind": kind,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.whileStatement) {
       return {
         "whileStatement_body": whileStatement_body,
-        "whileStatement_leftParenthesis": whileStatement_leftParenthesis,
         "whileStatement_condition": whileStatement_condition,
-        "whileStatement_rightParenthesis": whileStatement_rightParenthesis,
-        "whileStatement_whileKeyword": whileStatement_whileKeyword,
-        "isSynthetic": isSynthetic,
+        "flags": flags,
         "kind": kind,
+        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.withClause) {
+      return {
+        "withClause_mixinTypes": withClause_mixinTypes,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.yieldStatement) {
       return {
         "yieldStatement_expression": yieldStatement_expression,
-        "yieldStatement_yieldKeyword": yieldStatement_yieldKeyword,
-        "yieldStatement_star": yieldStatement_star,
-        "yieldStatement_semicolon": yieldStatement_semicolon,
-        "isSynthetic": isSynthetic,
+        "flags": flags,
         "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.booleanLiteral) {
-      return {
-        "booleanLiteral_literal": booleanLiteral_literal,
-        "booleanLiteral_value": booleanLiteral_value,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.doubleLiteral) {
-      return {
-        "doubleLiteral_literal": doubleLiteral_literal,
-        "doubleLiteral_value": doubleLiteral_value,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
-      return {
-        "emptyFunctionBody_semicolon": emptyFunctionBody_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.emptyStatement) {
-      return {
-        "emptyStatement_semicolon": emptyStatement_semicolon,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.integerLiteral) {
-      return {
-        "integerLiteral_literal": integerLiteral_literal,
-        "integerLiteral_value": integerLiteral_value,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.interpolationString) {
-      return {
-        "interpolationString_token": interpolationString_token,
-        "interpolationString_value": interpolationString_value,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.nullLiteral) {
-      return {
-        "nullLiteral_literal": nullLiteral_literal,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.rethrowExpression) {
-      return {
-        "rethrowExpression_rethrowKeyword": rethrowExpression_rethrowKeyword,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.scriptTag) {
-      return {
-        "scriptTag_scriptTag": scriptTag_scriptTag,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.simpleIdentifier) {
-      return {
-        "simpleIdentifier_element": simpleIdentifier_element,
-        "simpleIdentifier_token": simpleIdentifier_token,
-        "simpleIdentifier_elementType": simpleIdentifier_elementType,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
-      return {
-        "simpleStringLiteral_token": simpleStringLiteral_token,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-        "simpleStringLiteral_value": simpleStringLiteral_value,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.superExpression) {
-      return {
-        "superExpression_superKeyword": superExpression_superKeyword,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.symbolLiteral) {
-      return {
-        "symbolLiteral_poundSign": symbolLiteral_poundSign,
-        "symbolLiteral_components": symbolLiteral_components,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.thisExpression) {
-      return {
-        "thisExpression_thisKeyword": thisExpression_thisKeyword,
-        "expression_type": expression_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.comment) {
-      return {
-        "comment_tokens": comment_tokens,
-        "comment_type": comment_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
+        "name": name,
       };
     }
     throw StateError("Unexpected $kind");
@@ -19129,6 +16041,8 @@
   int _interfaceClass;
   List<LinkedNodeTypeBuilder> _interfaceTypeArguments;
   idl.LinkedNodeTypeKind _kind;
+  idl.EntityRefNullabilitySuffix _nullabilitySuffix;
+  int _typeParameterElement;
   int _typeParameterId;
 
   @override
@@ -19196,6 +16110,22 @@
   }
 
   @override
+  idl.EntityRefNullabilitySuffix get nullabilitySuffix =>
+      _nullabilitySuffix ??= idl.EntityRefNullabilitySuffix.starOrIrrelevant;
+
+  set nullabilitySuffix(idl.EntityRefNullabilitySuffix value) {
+    this._nullabilitySuffix = value;
+  }
+
+  @override
+  int get typeParameterElement => _typeParameterElement ??= 0;
+
+  set typeParameterElement(int value) {
+    assert(value == null || value >= 0);
+    this._typeParameterElement = value;
+  }
+
+  @override
   int get typeParameterId => _typeParameterId ??= 0;
 
   set typeParameterId(int value) {
@@ -19212,6 +16142,8 @@
       int interfaceClass,
       List<LinkedNodeTypeBuilder> interfaceTypeArguments,
       idl.LinkedNodeTypeKind kind,
+      idl.EntityRefNullabilitySuffix nullabilitySuffix,
+      int typeParameterElement,
       int typeParameterId})
       : _functionFormalParameters = functionFormalParameters,
         _functionReturnType = functionReturnType,
@@ -19221,6 +16153,8 @@
         _interfaceClass = interfaceClass,
         _interfaceTypeArguments = interfaceTypeArguments,
         _kind = kind,
+        _nullabilitySuffix = nullabilitySuffix,
+        _typeParameterElement = typeParameterElement,
         _typeParameterId = typeParameterId;
 
   /// Flush [informative] data recursively.
@@ -19262,6 +16196,7 @@
       }
     }
     signature.addInt(this._kind == null ? 0 : this._kind.index);
+    signature.addInt(this._typeParameterElement ?? 0);
     signature.addInt(this._typeParameterId ?? 0);
     signature.addInt(this._genericTypeAliasReference ?? 0);
     if (this._genericTypeAliasTypeArguments == null) {
@@ -19272,6 +16207,8 @@
         x?.collectApiSignature(signature);
       }
     }
+    signature.addInt(
+        this._nullabilitySuffix == null ? 0 : this._nullabilitySuffix.index);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -19314,10 +16251,10 @@
       fbBuilder.addOffset(2, offset_functionTypeParameters);
     }
     if (_genericTypeAliasReference != null && _genericTypeAliasReference != 0) {
-      fbBuilder.addUint32(7, _genericTypeAliasReference);
+      fbBuilder.addUint32(8, _genericTypeAliasReference);
     }
     if (offset_genericTypeAliasTypeArguments != null) {
-      fbBuilder.addOffset(8, offset_genericTypeAliasTypeArguments);
+      fbBuilder.addOffset(9, offset_genericTypeAliasTypeArguments);
     }
     if (_interfaceClass != null && _interfaceClass != 0) {
       fbBuilder.addUint32(3, _interfaceClass);
@@ -19328,8 +16265,15 @@
     if (_kind != null && _kind != idl.LinkedNodeTypeKind.bottom) {
       fbBuilder.addUint8(5, _kind.index);
     }
+    if (_nullabilitySuffix != null &&
+        _nullabilitySuffix != idl.EntityRefNullabilitySuffix.starOrIrrelevant) {
+      fbBuilder.addUint8(10, _nullabilitySuffix.index);
+    }
+    if (_typeParameterElement != null && _typeParameterElement != 0) {
+      fbBuilder.addUint32(6, _typeParameterElement);
+    }
     if (_typeParameterId != null && _typeParameterId != 0) {
-      fbBuilder.addUint32(6, _typeParameterId);
+      fbBuilder.addUint32(7, _typeParameterId);
     }
     return fbBuilder.endTable();
   }
@@ -19359,6 +16303,8 @@
   int _interfaceClass;
   List<idl.LinkedNodeType> _interfaceTypeArguments;
   idl.LinkedNodeTypeKind _kind;
+  idl.EntityRefNullabilitySuffix _nullabilitySuffix;
+  int _typeParameterElement;
   int _typeParameterId;
 
   @override
@@ -19391,7 +16337,7 @@
   @override
   int get genericTypeAliasReference {
     _genericTypeAliasReference ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 7, 0);
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 8, 0);
     return _genericTypeAliasReference;
   }
 
@@ -19399,7 +16345,7 @@
   List<idl.LinkedNodeType> get genericTypeAliasTypeArguments {
     _genericTypeAliasTypeArguments ??=
         const fb.ListReader<idl.LinkedNodeType>(const _LinkedNodeTypeReader())
-            .vTableGet(_bc, _bcOffset, 8, const <idl.LinkedNodeType>[]);
+            .vTableGet(_bc, _bcOffset, 9, const <idl.LinkedNodeType>[]);
     return _genericTypeAliasTypeArguments;
   }
 
@@ -19425,9 +16371,23 @@
   }
 
   @override
+  idl.EntityRefNullabilitySuffix get nullabilitySuffix {
+    _nullabilitySuffix ??= const _EntityRefNullabilitySuffixReader().vTableGet(
+        _bc, _bcOffset, 10, idl.EntityRefNullabilitySuffix.starOrIrrelevant);
+    return _nullabilitySuffix;
+  }
+
+  @override
+  int get typeParameterElement {
+    _typeParameterElement ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 6, 0);
+    return _typeParameterElement;
+  }
+
+  @override
   int get typeParameterId {
     _typeParameterId ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 6, 0);
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 7, 0);
     return _typeParameterId;
   }
 }
@@ -19456,6 +16416,10 @@
           interfaceTypeArguments.map((_value) => _value.toJson()).toList();
     if (kind != idl.LinkedNodeTypeKind.bottom)
       _result["kind"] = kind.toString().split('.')[1];
+    if (nullabilitySuffix != idl.EntityRefNullabilitySuffix.starOrIrrelevant)
+      _result["nullabilitySuffix"] = nullabilitySuffix.toString().split('.')[1];
+    if (typeParameterElement != 0)
+      _result["typeParameterElement"] = typeParameterElement;
     if (typeParameterId != 0) _result["typeParameterId"] = typeParameterId;
     return _result;
   }
@@ -19470,6 +16434,8 @@
         "interfaceClass": interfaceClass,
         "interfaceTypeArguments": interfaceTypeArguments,
         "kind": kind,
+        "nullabilitySuffix": nullabilitySuffix,
+        "typeParameterElement": typeParameterElement,
         "typeParameterId": typeParameterId,
       };
 
@@ -19486,7 +16452,7 @@
 
   @override
   idl.LinkedNodeFormalParameterKind get kind =>
-      _kind ??= idl.LinkedNodeFormalParameterKind.required;
+      _kind ??= idl.LinkedNodeFormalParameterKind.requiredPositional;
 
   set kind(idl.LinkedNodeFormalParameterKind value) {
     this._kind = value;
@@ -19537,7 +16503,8 @@
       offset_type = _type.finish(fbBuilder);
     }
     fbBuilder.startTable();
-    if (_kind != null && _kind != idl.LinkedNodeFormalParameterKind.required) {
+    if (_kind != null &&
+        _kind != idl.LinkedNodeFormalParameterKind.requiredPositional) {
       fbBuilder.addUint8(0, _kind.index);
     }
     if (offset_name != null) {
@@ -19574,8 +16541,8 @@
 
   @override
   idl.LinkedNodeFormalParameterKind get kind {
-    _kind ??= const _LinkedNodeFormalParameterKindReader().vTableGet(
-        _bc, _bcOffset, 0, idl.LinkedNodeFormalParameterKind.required);
+    _kind ??= const _LinkedNodeFormalParameterKindReader().vTableGet(_bc,
+        _bcOffset, 0, idl.LinkedNodeFormalParameterKind.requiredPositional);
     return _kind;
   }
 
@@ -19597,7 +16564,7 @@
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
-    if (kind != idl.LinkedNodeFormalParameterKind.required)
+    if (kind != idl.LinkedNodeFormalParameterKind.requiredPositional)
       _result["kind"] = kind.toString().split('.')[1];
     if (name != '') _result["name"] = name;
     if (type != null) _result["type"] = type.toJson();
@@ -19728,11 +16695,27 @@
 class LinkedNodeUnitBuilder extends Object
     with _LinkedNodeUnitMixin
     implements idl.LinkedNodeUnit {
+  bool _isNNBD;
+  bool _isSynthetic;
   LinkedNodeBuilder _node;
   UnlinkedTokensBuilder _tokens;
   String _uriStr;
 
   @override
+  bool get isNNBD => _isNNBD ??= false;
+
+  set isNNBD(bool value) {
+    this._isNNBD = value;
+  }
+
+  @override
+  bool get isSynthetic => _isSynthetic ??= false;
+
+  set isSynthetic(bool value) {
+    this._isSynthetic = value;
+  }
+
+  @override
   LinkedNodeBuilder get node => _node;
 
   set node(LinkedNodeBuilder value) {
@@ -19754,8 +16737,14 @@
   }
 
   LinkedNodeUnitBuilder(
-      {LinkedNodeBuilder node, UnlinkedTokensBuilder tokens, String uriStr})
-      : _node = node,
+      {bool isNNBD,
+      bool isSynthetic,
+      LinkedNodeBuilder node,
+      UnlinkedTokensBuilder tokens,
+      String uriStr})
+      : _isNNBD = isNNBD,
+        _isSynthetic = isSynthetic,
+        _node = node,
         _tokens = tokens,
         _uriStr = uriStr;
 
@@ -19772,6 +16761,8 @@
     this._tokens?.collectApiSignature(signature);
     signature.addBool(this._node != null);
     this._node?.collectApiSignature(signature);
+    signature.addBool(this._isSynthetic == true);
+    signature.addBool(this._isNNBD == true);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -19788,6 +16779,12 @@
       offset_uriStr = fbBuilder.writeString(_uriStr);
     }
     fbBuilder.startTable();
+    if (_isNNBD == true) {
+      fbBuilder.addBool(4, true);
+    }
+    if (_isSynthetic == true) {
+      fbBuilder.addBool(3, true);
+    }
     if (offset_node != null) {
       fbBuilder.addOffset(2, offset_node);
     }
@@ -19817,11 +16814,25 @@
 
   _LinkedNodeUnitImpl(this._bc, this._bcOffset);
 
+  bool _isNNBD;
+  bool _isSynthetic;
   idl.LinkedNode _node;
   idl.UnlinkedTokens _tokens;
   String _uriStr;
 
   @override
+  bool get isNNBD {
+    _isNNBD ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 4, false);
+    return _isNNBD;
+  }
+
+  @override
+  bool get isSynthetic {
+    _isSynthetic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
+    return _isSynthetic;
+  }
+
+  @override
   idl.LinkedNode get node {
     _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 2, null);
     return _node;
@@ -19845,6 +16856,8 @@
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
+    if (isNNBD != false) _result["isNNBD"] = isNNBD;
+    if (isSynthetic != false) _result["isSynthetic"] = isSynthetic;
     if (node != null) _result["node"] = node.toJson();
     if (tokens != null) _result["tokens"] = tokens.toJson();
     if (uriStr != '') _result["uriStr"] = uriStr;
@@ -19853,6 +16866,8 @@
 
   @override
   Map<String, Object> toMap() => {
+        "isNNBD": isNNBD,
+        "isSynthetic": isSynthetic,
         "node": node,
         "tokens": tokens,
         "uriStr": uriStr,
@@ -19862,183 +16877,6 @@
   String toString() => convert.json.encode(toJson());
 }
 
-class LinkedNodeVariablesDeclarationBuilder extends Object
-    with _LinkedNodeVariablesDeclarationMixin
-    implements idl.LinkedNodeVariablesDeclaration {
-  LinkedNodeBuilder _comment;
-  bool _isConst;
-  bool _isCovariant;
-  bool _isFinal;
-  bool _isStatic;
-
-  @override
-  LinkedNodeBuilder get comment => _comment;
-
-  set comment(LinkedNodeBuilder value) {
-    this._comment = value;
-  }
-
-  @override
-  bool get isConst => _isConst ??= false;
-
-  set isConst(bool value) {
-    this._isConst = value;
-  }
-
-  @override
-  bool get isCovariant => _isCovariant ??= false;
-
-  set isCovariant(bool value) {
-    this._isCovariant = value;
-  }
-
-  @override
-  bool get isFinal => _isFinal ??= false;
-
-  set isFinal(bool value) {
-    this._isFinal = value;
-  }
-
-  @override
-  bool get isStatic => _isStatic ??= false;
-
-  set isStatic(bool value) {
-    this._isStatic = value;
-  }
-
-  LinkedNodeVariablesDeclarationBuilder(
-      {LinkedNodeBuilder comment,
-      bool isConst,
-      bool isCovariant,
-      bool isFinal,
-      bool isStatic})
-      : _comment = comment,
-        _isConst = isConst,
-        _isCovariant = isCovariant,
-        _isFinal = isFinal,
-        _isStatic = isStatic;
-
-  /// Flush [informative] data recursively.
-  void flushInformative() {
-    _comment?.flushInformative();
-  }
-
-  /// Accumulate non-[informative] data into [signature].
-  void collectApiSignature(api_sig.ApiSignature signature) {
-    signature.addBool(this._comment != null);
-    this._comment?.collectApiSignature(signature);
-    signature.addBool(this._isConst == true);
-    signature.addBool(this._isCovariant == true);
-    signature.addBool(this._isFinal == true);
-    signature.addBool(this._isStatic == true);
-  }
-
-  fb.Offset finish(fb.Builder fbBuilder) {
-    fb.Offset offset_comment;
-    if (_comment != null) {
-      offset_comment = _comment.finish(fbBuilder);
-    }
-    fbBuilder.startTable();
-    if (offset_comment != null) {
-      fbBuilder.addOffset(0, offset_comment);
-    }
-    if (_isConst == true) {
-      fbBuilder.addBool(1, true);
-    }
-    if (_isCovariant == true) {
-      fbBuilder.addBool(2, true);
-    }
-    if (_isFinal == true) {
-      fbBuilder.addBool(3, true);
-    }
-    if (_isStatic == true) {
-      fbBuilder.addBool(4, true);
-    }
-    return fbBuilder.endTable();
-  }
-}
-
-class _LinkedNodeVariablesDeclarationReader
-    extends fb.TableReader<_LinkedNodeVariablesDeclarationImpl> {
-  const _LinkedNodeVariablesDeclarationReader();
-
-  @override
-  _LinkedNodeVariablesDeclarationImpl createObject(
-          fb.BufferContext bc, int offset) =>
-      new _LinkedNodeVariablesDeclarationImpl(bc, offset);
-}
-
-class _LinkedNodeVariablesDeclarationImpl extends Object
-    with _LinkedNodeVariablesDeclarationMixin
-    implements idl.LinkedNodeVariablesDeclaration {
-  final fb.BufferContext _bc;
-  final int _bcOffset;
-
-  _LinkedNodeVariablesDeclarationImpl(this._bc, this._bcOffset);
-
-  idl.LinkedNode _comment;
-  bool _isConst;
-  bool _isCovariant;
-  bool _isFinal;
-  bool _isStatic;
-
-  @override
-  idl.LinkedNode get comment {
-    _comment ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 0, null);
-    return _comment;
-  }
-
-  @override
-  bool get isConst {
-    _isConst ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 1, false);
-    return _isConst;
-  }
-
-  @override
-  bool get isCovariant {
-    _isCovariant ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 2, false);
-    return _isCovariant;
-  }
-
-  @override
-  bool get isFinal {
-    _isFinal ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
-    return _isFinal;
-  }
-
-  @override
-  bool get isStatic {
-    _isStatic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 4, false);
-    return _isStatic;
-  }
-}
-
-abstract class _LinkedNodeVariablesDeclarationMixin
-    implements idl.LinkedNodeVariablesDeclaration {
-  @override
-  Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
-    if (comment != null) _result["comment"] = comment.toJson();
-    if (isConst != false) _result["isConst"] = isConst;
-    if (isCovariant != false) _result["isCovariant"] = isCovariant;
-    if (isFinal != false) _result["isFinal"] = isFinal;
-    if (isStatic != false) _result["isStatic"] = isStatic;
-    return _result;
-  }
-
-  @override
-  Map<String, Object> toMap() => {
-        "comment": comment,
-        "isConst": isConst,
-        "isCovariant": isCovariant,
-        "isFinal": isFinal,
-        "isStatic": isStatic,
-      };
-
-  @override
-  String toString() => convert.json.encode(toJson());
-}
-
 class LinkedReferenceBuilder extends Object
     with _LinkedReferenceMixin
     implements idl.LinkedReference {
@@ -20588,6 +17426,7 @@
 class PackageBundleBuilder extends Object
     with _PackageBundleMixin
     implements idl.PackageBundle {
+  LinkedNodeBundleBuilder _bundle2;
   List<LinkedLibraryBuilder> _linkedLibraries;
   List<String> _linkedLibraryUris;
   int _majorVersion;
@@ -20600,6 +17439,14 @@
       throw new UnimplementedError('attempt to access deprecated field');
 
   @override
+  LinkedNodeBundleBuilder get bundle2 => _bundle2;
+
+  /// The version 2 of the summary.
+  set bundle2(LinkedNodeBundleBuilder value) {
+    this._bundle2 = value;
+  }
+
+  @override
   Null get dependencies =>
       throw new UnimplementedError('attempt to access deprecated field');
 
@@ -20663,13 +17510,15 @@
   }
 
   PackageBundleBuilder(
-      {List<LinkedLibraryBuilder> linkedLibraries,
+      {LinkedNodeBundleBuilder bundle2,
+      List<LinkedLibraryBuilder> linkedLibraries,
       List<String> linkedLibraryUris,
       int majorVersion,
       int minorVersion,
       List<UnlinkedUnitBuilder> unlinkedUnits,
       List<String> unlinkedUnitUris})
-      : _linkedLibraries = linkedLibraries,
+      : _bundle2 = bundle2,
+        _linkedLibraries = linkedLibraries,
         _linkedLibraryUris = linkedLibraryUris,
         _majorVersion = majorVersion,
         _minorVersion = minorVersion,
@@ -20678,6 +17527,7 @@
 
   /// Flush [informative] data recursively.
   void flushInformative() {
+    _bundle2?.flushInformative();
     _linkedLibraries?.forEach((b) => b.flushInformative());
     _unlinkedUnits?.forEach((b) => b.flushInformative());
   }
@@ -20718,6 +17568,8 @@
     }
     signature.addInt(this._majorVersion ?? 0);
     signature.addInt(this._minorVersion ?? 0);
+    signature.addBool(this._bundle2 != null);
+    this._bundle2?.collectApiSignature(signature);
   }
 
   List<int> toBuffer() {
@@ -20726,10 +17578,14 @@
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_bundle2;
     fb.Offset offset_linkedLibraries;
     fb.Offset offset_linkedLibraryUris;
     fb.Offset offset_unlinkedUnits;
     fb.Offset offset_unlinkedUnitUris;
+    if (_bundle2 != null) {
+      offset_bundle2 = _bundle2.finish(fbBuilder);
+    }
     if (!(_linkedLibraries == null || _linkedLibraries.isEmpty)) {
       offset_linkedLibraries = fbBuilder
           .writeList(_linkedLibraries.map((b) => b.finish(fbBuilder)).toList());
@@ -20747,6 +17603,9 @@
           _unlinkedUnitUris.map((b) => fbBuilder.writeString(b)).toList());
     }
     fbBuilder.startTable();
+    if (offset_bundle2 != null) {
+      fbBuilder.addOffset(9, offset_bundle2);
+    }
     if (offset_linkedLibraries != null) {
       fbBuilder.addOffset(0, offset_linkedLibraries);
     }
@@ -20790,6 +17649,7 @@
 
   _PackageBundleImpl(this._bc, this._bcOffset);
 
+  idl.LinkedNodeBundle _bundle2;
   List<idl.LinkedLibrary> _linkedLibraries;
   List<String> _linkedLibraryUris;
   int _majorVersion;
@@ -20802,6 +17662,13 @@
       throw new UnimplementedError('attempt to access deprecated field');
 
   @override
+  idl.LinkedNodeBundle get bundle2 {
+    _bundle2 ??=
+        const _LinkedNodeBundleReader().vTableGet(_bc, _bcOffset, 9, null);
+    return _bundle2;
+  }
+
+  @override
   Null get dependencies =>
       throw new UnimplementedError('attempt to access deprecated field');
 
@@ -20856,6 +17723,7 @@
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
+    if (bundle2 != null) _result["bundle2"] = bundle2.toJson();
     if (linkedLibraries.isNotEmpty)
       _result["linkedLibraries"] =
           linkedLibraries.map((_value) => _value.toJson()).toList();
@@ -20873,6 +17741,7 @@
 
   @override
   Map<String, Object> toMap() => {
+        "bundle2": bundle2,
         "linkedLibraries": linkedLibraries,
         "linkedLibraryUris": linkedLibraryUris,
         "majorVersion": majorVersion,
@@ -25747,6 +22616,1236 @@
   String toString() => convert.json.encode(toJson());
 }
 
+class UnlinkedInformativeDataBuilder extends Object
+    with _UnlinkedInformativeDataMixin
+    implements idl.UnlinkedInformativeData {
+  int _variantField_2;
+  int _variantField_3;
+  int _variantField_1;
+  List<String> _variantField_4;
+  idl.LinkedNodeKind _kind;
+  int _variantField_5;
+  int _variantField_6;
+  List<int> _variantField_7;
+
+  @override
+  int get codeLength {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.defaultFormalParameter ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_2 ??= 0;
+  }
+
+  set codeLength(int value) {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.defaultFormalParameter ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    assert(value == null || value >= 0);
+    _variantField_2 = value;
+  }
+
+  @override
+  int get codeOffset {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.defaultFormalParameter ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_3 ??= 0;
+  }
+
+  set codeOffset(int value) {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.defaultFormalParameter ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    assert(value == null || value >= 0);
+    _variantField_3 = value;
+  }
+
+  @override
+  int get directiveKeywordOffset {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.partDirective ||
+        kind == idl.LinkedNodeKind.partOfDirective);
+    return _variantField_1 ??= 0;
+  }
+
+  @override
+  int get nameOffset {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_1 ??= 0;
+  }
+
+  set directiveKeywordOffset(int value) {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.partDirective ||
+        kind == idl.LinkedNodeKind.partOfDirective);
+    assert(value == null || value >= 0);
+    _variantField_1 = value;
+  }
+
+  set nameOffset(int value) {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    assert(value == null || value >= 0);
+    _variantField_1 = value;
+  }
+
+  @override
+  List<String> get documentationComment_tokens {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
+        kind == idl.LinkedNodeKind.fieldDeclaration ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.topLevelVariableDeclaration);
+    return _variantField_4 ??= <String>[];
+  }
+
+  set documentationComment_tokens(List<String> value) {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
+        kind == idl.LinkedNodeKind.fieldDeclaration ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.topLevelVariableDeclaration);
+    _variantField_4 = value;
+  }
+
+  @override
+  idl.LinkedNodeKind get kind => _kind ??= idl.LinkedNodeKind.adjacentStrings;
+
+  /// The kind of the node.
+  set kind(idl.LinkedNodeKind value) {
+    this._kind = value;
+  }
+
+  @override
+  int get constructorDeclaration_returnTypeOffset {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    return _variantField_5 ??= 0;
+  }
+
+  set constructorDeclaration_returnTypeOffset(int value) {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    assert(value == null || value >= 0);
+    _variantField_5 = value;
+  }
+
+  @override
+  int get constructorDeclaration_periodOffset {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    return _variantField_6 ??= 0;
+  }
+
+  set constructorDeclaration_periodOffset(int value) {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    assert(value == null || value >= 0);
+    _variantField_6 = value;
+  }
+
+  @override
+  List<int> get compilationUnit_lineStarts {
+    assert(kind == idl.LinkedNodeKind.compilationUnit);
+    return _variantField_7 ??= <int>[];
+  }
+
+  /// Offsets of the first character of each line in the source code.
+  set compilationUnit_lineStarts(List<int> value) {
+    assert(kind == idl.LinkedNodeKind.compilationUnit);
+    assert(value == null || value.every((e) => e >= 0));
+    _variantField_7 = value;
+  }
+
+  UnlinkedInformativeDataBuilder.classDeclaration({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.classDeclaration,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.classTypeAlias({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.classTypeAlias,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.compilationUnit({
+    int codeLength,
+    int codeOffset,
+    List<int> compilationUnit_lineStarts,
+  })  : _kind = idl.LinkedNodeKind.compilationUnit,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_7 = compilationUnit_lineStarts;
+
+  UnlinkedInformativeDataBuilder.constructorDeclaration({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+    List<String> documentationComment_tokens,
+    int constructorDeclaration_returnTypeOffset,
+    int constructorDeclaration_periodOffset,
+  })  : _kind = idl.LinkedNodeKind.constructorDeclaration,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset,
+        _variantField_4 = documentationComment_tokens,
+        _variantField_5 = constructorDeclaration_returnTypeOffset,
+        _variantField_6 = constructorDeclaration_periodOffset;
+
+  UnlinkedInformativeDataBuilder.defaultFormalParameter({
+    int codeLength,
+    int codeOffset,
+  })  : _kind = idl.LinkedNodeKind.defaultFormalParameter,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset;
+
+  UnlinkedInformativeDataBuilder.enumConstantDeclaration({
+    int nameOffset,
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.enumConstantDeclaration,
+        _variantField_1 = nameOffset,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.enumDeclaration({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.enumDeclaration,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.exportDirective({
+    int directiveKeywordOffset,
+  })  : _kind = idl.LinkedNodeKind.exportDirective,
+        _variantField_1 = directiveKeywordOffset;
+
+  UnlinkedInformativeDataBuilder.fieldDeclaration({
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.fieldDeclaration,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.fieldFormalParameter({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+  })  : _kind = idl.LinkedNodeKind.fieldFormalParameter,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset;
+
+  UnlinkedInformativeDataBuilder.functionDeclaration({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.functionDeclaration,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.functionTypeAlias({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.functionTypeAlias,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.functionTypedFormalParameter({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+  })  : _kind = idl.LinkedNodeKind.functionTypedFormalParameter,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset;
+
+  UnlinkedInformativeDataBuilder.genericTypeAlias({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.genericTypeAlias,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.importDirective({
+    int directiveKeywordOffset,
+  })  : _kind = idl.LinkedNodeKind.importDirective,
+        _variantField_1 = directiveKeywordOffset;
+
+  UnlinkedInformativeDataBuilder.libraryDirective({
+    int directiveKeywordOffset,
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.libraryDirective,
+        _variantField_1 = directiveKeywordOffset,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.methodDeclaration({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.methodDeclaration,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.mixinDeclaration({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.mixinDeclaration,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.partDirective({
+    int directiveKeywordOffset,
+  })  : _kind = idl.LinkedNodeKind.partDirective,
+        _variantField_1 = directiveKeywordOffset;
+
+  UnlinkedInformativeDataBuilder.partOfDirective({
+    int directiveKeywordOffset,
+  })  : _kind = idl.LinkedNodeKind.partOfDirective,
+        _variantField_1 = directiveKeywordOffset;
+
+  UnlinkedInformativeDataBuilder.simpleFormalParameter({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+  })  : _kind = idl.LinkedNodeKind.simpleFormalParameter,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset;
+
+  UnlinkedInformativeDataBuilder.topLevelVariableDeclaration({
+    List<String> documentationComment_tokens,
+  })  : _kind = idl.LinkedNodeKind.topLevelVariableDeclaration,
+        _variantField_4 = documentationComment_tokens;
+
+  UnlinkedInformativeDataBuilder.typeParameter({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+  })  : _kind = idl.LinkedNodeKind.typeParameter,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset;
+
+  UnlinkedInformativeDataBuilder.variableDeclaration({
+    int codeLength,
+    int codeOffset,
+    int nameOffset,
+  })  : _kind = idl.LinkedNodeKind.variableDeclaration,
+        _variantField_2 = codeLength,
+        _variantField_3 = codeOffset,
+        _variantField_1 = nameOffset;
+
+  /// Flush [informative] data recursively.
+  void flushInformative() {
+    if (kind == idl.LinkedNodeKind.classDeclaration) {
+    } else if (kind == idl.LinkedNodeKind.classTypeAlias) {
+    } else if (kind == idl.LinkedNodeKind.compilationUnit) {
+    } else if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+    } else if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+    } else if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+    } else if (kind == idl.LinkedNodeKind.enumDeclaration) {
+    } else if (kind == idl.LinkedNodeKind.exportDirective) {
+    } else if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+    } else if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+    } else if (kind == idl.LinkedNodeKind.functionDeclaration) {
+    } else if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+    } else if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+    } else if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+    } else if (kind == idl.LinkedNodeKind.importDirective) {
+    } else if (kind == idl.LinkedNodeKind.libraryDirective) {
+    } else if (kind == idl.LinkedNodeKind.methodDeclaration) {
+    } else if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+    } else if (kind == idl.LinkedNodeKind.partDirective) {
+    } else if (kind == idl.LinkedNodeKind.partOfDirective) {
+    } else if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+    } else if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+    } else if (kind == idl.LinkedNodeKind.typeParameter) {
+    } else if (kind == idl.LinkedNodeKind.variableDeclaration) {}
+  }
+
+  /// Accumulate non-[informative] data into [signature].
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    if (kind == idl.LinkedNodeKind.classDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.classTypeAlias) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.compilationUnit) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+      if (this.compilationUnit_lineStarts == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.compilationUnit_lineStarts.length);
+        for (var x in this.compilationUnit_lineStarts) {
+          signature.addInt(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+      signature.addInt(this.constructorDeclaration_returnTypeOffset ?? 0);
+      signature.addInt(this.constructorDeclaration_periodOffset ?? 0);
+    } else if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+    } else if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.enumDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.exportDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.directiveKeywordOffset ?? 0);
+    } else if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+    } else if (kind == idl.LinkedNodeKind.functionDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+    } else if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.importDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.directiveKeywordOffset ?? 0);
+    } else if (kind == idl.LinkedNodeKind.libraryDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.directiveKeywordOffset ?? 0);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.methodDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.partDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.directiveKeywordOffset ?? 0);
+    } else if (kind == idl.LinkedNodeKind.partOfDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.directiveKeywordOffset ?? 0);
+    } else if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+    } else if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.documentationComment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.documentationComment_tokens.length);
+        for (var x in this.documentationComment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.typeParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+    } else if (kind == idl.LinkedNodeKind.variableDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nameOffset ?? 0);
+      signature.addInt(this.codeLength ?? 0);
+      signature.addInt(this.codeOffset ?? 0);
+    }
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_variantField_4;
+    fb.Offset offset_variantField_7;
+    if (!(_variantField_4 == null || _variantField_4.isEmpty)) {
+      offset_variantField_4 = fbBuilder.writeList(
+          _variantField_4.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    if (!(_variantField_7 == null || _variantField_7.isEmpty)) {
+      offset_variantField_7 = fbBuilder.writeListUint32(_variantField_7);
+    }
+    fbBuilder.startTable();
+    if (_variantField_2 != null && _variantField_2 != 0) {
+      fbBuilder.addUint32(2, _variantField_2);
+    }
+    if (_variantField_3 != null && _variantField_3 != 0) {
+      fbBuilder.addUint32(3, _variantField_3);
+    }
+    if (_variantField_1 != null && _variantField_1 != 0) {
+      fbBuilder.addUint32(1, _variantField_1);
+    }
+    if (offset_variantField_4 != null) {
+      fbBuilder.addOffset(4, offset_variantField_4);
+    }
+    if (_kind != null && _kind != idl.LinkedNodeKind.adjacentStrings) {
+      fbBuilder.addUint8(0, _kind.index);
+    }
+    if (_variantField_5 != null && _variantField_5 != 0) {
+      fbBuilder.addUint32(5, _variantField_5);
+    }
+    if (_variantField_6 != null && _variantField_6 != 0) {
+      fbBuilder.addUint32(6, _variantField_6);
+    }
+    if (offset_variantField_7 != null) {
+      fbBuilder.addOffset(7, offset_variantField_7);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _UnlinkedInformativeDataReader
+    extends fb.TableReader<_UnlinkedInformativeDataImpl> {
+  const _UnlinkedInformativeDataReader();
+
+  @override
+  _UnlinkedInformativeDataImpl createObject(fb.BufferContext bc, int offset) =>
+      new _UnlinkedInformativeDataImpl(bc, offset);
+}
+
+class _UnlinkedInformativeDataImpl extends Object
+    with _UnlinkedInformativeDataMixin
+    implements idl.UnlinkedInformativeData {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _UnlinkedInformativeDataImpl(this._bc, this._bcOffset);
+
+  int _variantField_2;
+  int _variantField_3;
+  int _variantField_1;
+  List<String> _variantField_4;
+  idl.LinkedNodeKind _kind;
+  int _variantField_5;
+  int _variantField_6;
+  List<int> _variantField_7;
+
+  @override
+  int get codeLength {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.defaultFormalParameter ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_2 ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 2, 0);
+    return _variantField_2;
+  }
+
+  @override
+  int get codeOffset {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.defaultFormalParameter ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_3 ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
+    return _variantField_3;
+  }
+
+  @override
+  int get directiveKeywordOffset {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.partDirective ||
+        kind == idl.LinkedNodeKind.partOfDirective);
+    _variantField_1 ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
+    return _variantField_1;
+  }
+
+  @override
+  int get nameOffset {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_1 ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
+    return _variantField_1;
+  }
+
+  @override
+  List<String> get documentationComment_tokens {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
+        kind == idl.LinkedNodeKind.fieldDeclaration ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.topLevelVariableDeclaration);
+    _variantField_4 ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 4, const <String>[]);
+    return _variantField_4;
+  }
+
+  @override
+  idl.LinkedNodeKind get kind {
+    _kind ??= const _LinkedNodeKindReader()
+        .vTableGet(_bc, _bcOffset, 0, idl.LinkedNodeKind.adjacentStrings);
+    return _kind;
+  }
+
+  @override
+  int get constructorDeclaration_returnTypeOffset {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    _variantField_5 ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 5, 0);
+    return _variantField_5;
+  }
+
+  @override
+  int get constructorDeclaration_periodOffset {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    _variantField_6 ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 6, 0);
+    return _variantField_6;
+  }
+
+  @override
+  List<int> get compilationUnit_lineStarts {
+    assert(kind == idl.LinkedNodeKind.compilationUnit);
+    _variantField_7 ??=
+        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 7, const <int>[]);
+    return _variantField_7;
+  }
+}
+
+abstract class _UnlinkedInformativeDataMixin
+    implements idl.UnlinkedInformativeData {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (kind != idl.LinkedNodeKind.adjacentStrings)
+      _result["kind"] = kind.toString().split('.')[1];
+    if (kind == idl.LinkedNodeKind.classDeclaration) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.classTypeAlias) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.compilationUnit) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (compilationUnit_lineStarts.isNotEmpty)
+        _result["compilationUnit_lineStarts"] = compilationUnit_lineStarts;
+    }
+    if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+      if (constructorDeclaration_returnTypeOffset != 0)
+        _result["constructorDeclaration_returnTypeOffset"] =
+            constructorDeclaration_returnTypeOffset;
+      if (constructorDeclaration_periodOffset != 0)
+        _result["constructorDeclaration_periodOffset"] =
+            constructorDeclaration_periodOffset;
+    }
+    if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+    }
+    if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.enumDeclaration) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.exportDirective) {
+      if (directiveKeywordOffset != 0)
+        _result["directiveKeywordOffset"] = directiveKeywordOffset;
+    }
+    if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    }
+    if (kind == idl.LinkedNodeKind.functionDeclaration) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    }
+    if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.importDirective) {
+      if (directiveKeywordOffset != 0)
+        _result["directiveKeywordOffset"] = directiveKeywordOffset;
+    }
+    if (kind == idl.LinkedNodeKind.libraryDirective) {
+      if (directiveKeywordOffset != 0)
+        _result["directiveKeywordOffset"] = directiveKeywordOffset;
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.methodDeclaration) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.partDirective) {
+      if (directiveKeywordOffset != 0)
+        _result["directiveKeywordOffset"] = directiveKeywordOffset;
+    }
+    if (kind == idl.LinkedNodeKind.partOfDirective) {
+      if (directiveKeywordOffset != 0)
+        _result["directiveKeywordOffset"] = directiveKeywordOffset;
+    }
+    if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    }
+    if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+      if (documentationComment_tokens.isNotEmpty)
+        _result["documentationComment_tokens"] = documentationComment_tokens;
+    }
+    if (kind == idl.LinkedNodeKind.typeParameter) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    }
+    if (kind == idl.LinkedNodeKind.variableDeclaration) {
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    }
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() {
+    if (kind == idl.LinkedNodeKind.classDeclaration) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.classTypeAlias) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.compilationUnit) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "kind": kind,
+        "compilationUnit_lineStarts": compilationUnit_lineStarts,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+        "constructorDeclaration_returnTypeOffset":
+            constructorDeclaration_returnTypeOffset,
+        "constructorDeclaration_periodOffset":
+            constructorDeclaration_periodOffset,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+      return {
+        "nameOffset": nameOffset,
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.enumDeclaration) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.exportDirective) {
+      return {
+        "directiveKeywordOffset": directiveKeywordOffset,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+      return {
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.functionDeclaration) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.importDirective) {
+      return {
+        "directiveKeywordOffset": directiveKeywordOffset,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.libraryDirective) {
+      return {
+        "directiveKeywordOffset": directiveKeywordOffset,
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.methodDeclaration) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.partDirective) {
+      return {
+        "directiveKeywordOffset": directiveKeywordOffset,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.partOfDirective) {
+      return {
+        "directiveKeywordOffset": directiveKeywordOffset,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+      return {
+        "documentationComment_tokens": documentationComment_tokens,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.typeParameter) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.variableDeclaration) {
+      return {
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "nameOffset": nameOffset,
+        "kind": kind,
+      };
+    }
+    throw StateError("Unexpected $kind");
+  }
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
 class UnlinkedParamBuilder extends Object
     with _UnlinkedParamMixin
     implements idl.UnlinkedParam {
@@ -25875,7 +23974,8 @@
   }
 
   @override
-  idl.UnlinkedParamKind get kind => _kind ??= idl.UnlinkedParamKind.required;
+  idl.UnlinkedParamKind get kind =>
+      _kind ??= idl.UnlinkedParamKind.requiredPositional;
 
   /// Kind of the parameter.
   set kind(idl.UnlinkedParamKind value) {
@@ -26079,7 +24179,7 @@
     if (_isInitializingFormal == true) {
       fbBuilder.addBool(6, true);
     }
-    if (_kind != null && _kind != idl.UnlinkedParamKind.required) {
+    if (_kind != null && _kind != idl.UnlinkedParamKind.requiredPositional) {
       fbBuilder.addUint8(4, _kind.index);
     }
     if (offset_name != null) {
@@ -26210,7 +24310,7 @@
   @override
   idl.UnlinkedParamKind get kind {
     _kind ??= const _UnlinkedParamKindReader()
-        .vTableGet(_bc, _bcOffset, 4, idl.UnlinkedParamKind.required);
+        .vTableGet(_bc, _bcOffset, 4, idl.UnlinkedParamKind.requiredPositional);
     return _kind;
   }
 
@@ -26272,7 +24372,7 @@
     if (isFunctionTyped != false) _result["isFunctionTyped"] = isFunctionTyped;
     if (isInitializingFormal != false)
       _result["isInitializingFormal"] = isInitializingFormal;
-    if (kind != idl.UnlinkedParamKind.required)
+    if (kind != idl.UnlinkedParamKind.requiredPositional)
       _result["kind"] = kind.toString().split('.')[1];
     if (name != '') _result["name"] = name;
     if (nameOffset != 0) _result["nameOffset"] = nameOffset;
@@ -27928,6 +26028,7 @@
   List<UnlinkedExecutableBuilder> _executables;
   List<UnlinkedExportNonPublicBuilder> _exports;
   List<UnlinkedImportBuilder> _imports;
+  bool _isNNBD;
   bool _isPartOf;
   List<UnlinkedExprBuilder> _libraryAnnotations;
   UnlinkedDocumentationCommentBuilder _libraryDocumentationComment;
@@ -28011,6 +26112,14 @@
   }
 
   @override
+  bool get isNNBD => _isNNBD ??= false;
+
+  /// Indicates whether this compilation unit is opted into NNBD.
+  set isNNBD(bool value) {
+    this._isNNBD = value;
+  }
+
+  @override
   bool get isPartOf => _isPartOf ??= false;
 
   /// Indicates whether the unit contains a "part of" declaration.
@@ -28138,6 +26247,7 @@
       List<UnlinkedExecutableBuilder> executables,
       List<UnlinkedExportNonPublicBuilder> exports,
       List<UnlinkedImportBuilder> imports,
+      bool isNNBD,
       bool isPartOf,
       List<UnlinkedExprBuilder> libraryAnnotations,
       UnlinkedDocumentationCommentBuilder libraryDocumentationComment,
@@ -28158,6 +26268,7 @@
         _executables = executables,
         _exports = exports,
         _imports = imports,
+        _isNNBD = isNNBD,
         _isPartOf = isPartOf,
         _libraryAnnotations = libraryAnnotations,
         _libraryDocumentationComment = libraryDocumentationComment,
@@ -28295,6 +26406,7 @@
         x?.collectApiSignature(signature);
       }
     }
+    signature.addBool(this._isNNBD == true);
   }
 
   List<int> toBuffer() {
@@ -28405,6 +26517,9 @@
     if (offset_imports != null) {
       fbBuilder.addOffset(5, offset_imports);
     }
+    if (_isNNBD == true) {
+      fbBuilder.addBool(21, true);
+    }
     if (_isPartOf == true) {
       fbBuilder.addBool(18, true);
     }
@@ -28476,6 +26591,7 @@
   List<idl.UnlinkedExecutable> _executables;
   List<idl.UnlinkedExportNonPublic> _exports;
   List<idl.UnlinkedImport> _imports;
+  bool _isNNBD;
   bool _isPartOf;
   List<idl.UnlinkedExpr> _libraryAnnotations;
   idl.UnlinkedDocumentationComment _libraryDocumentationComment;
@@ -28548,6 +26664,12 @@
   }
 
   @override
+  bool get isNNBD {
+    _isNNBD ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 21, false);
+    return _isNNBD;
+  }
+
+  @override
   bool get isPartOf {
     _isPartOf ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 18, false);
     return _isPartOf;
@@ -28660,6 +26782,7 @@
       _result["exports"] = exports.map((_value) => _value.toJson()).toList();
     if (imports.isNotEmpty)
       _result["imports"] = imports.map((_value) => _value.toJson()).toList();
+    if (isNNBD != false) _result["isNNBD"] = isNNBD;
     if (isPartOf != false) _result["isPartOf"] = isPartOf;
     if (libraryAnnotations.isNotEmpty)
       _result["libraryAnnotations"] =
@@ -28699,6 +26822,7 @@
         "executables": executables,
         "exports": exports,
         "imports": imports,
+        "isNNBD": isNNBD,
         "isPartOf": isPartOf,
         "libraryAnnotations": libraryAnnotations,
         "libraryDocumentationComment": libraryDocumentationComment,
@@ -28718,6 +26842,341 @@
   String toString() => convert.json.encode(toJson());
 }
 
+class UnlinkedUnit2Builder extends Object
+    with _UnlinkedUnit2Mixin
+    implements idl.UnlinkedUnit2 {
+  List<int> _apiSignature;
+  List<String> _exports;
+  bool _hasLibraryDirective;
+  bool _hasPartOfDirective;
+  List<String> _imports;
+  List<UnlinkedInformativeDataBuilder> _informativeData;
+  List<int> _lineStarts;
+  List<String> _parts;
+
+  @override
+  List<int> get apiSignature => _apiSignature ??= <int>[];
+
+  /// The MD5 hash signature of the API portion of this unit. It depends on all
+  /// tokens that might affect APIs of declarations in the unit.
+  set apiSignature(List<int> value) {
+    assert(value == null || value.every((e) => e >= 0));
+    this._apiSignature = value;
+  }
+
+  @override
+  List<String> get exports => _exports ??= <String>[];
+
+  /// URIs of `export` directives.
+  set exports(List<String> value) {
+    this._exports = value;
+  }
+
+  @override
+  bool get hasLibraryDirective => _hasLibraryDirective ??= false;
+
+  /// Is `true` if the unit contains a `library` directive.
+  set hasLibraryDirective(bool value) {
+    this._hasLibraryDirective = value;
+  }
+
+  @override
+  bool get hasPartOfDirective => _hasPartOfDirective ??= false;
+
+  /// Is `true` if the unit contains a `part of` directive.
+  set hasPartOfDirective(bool value) {
+    this._hasPartOfDirective = value;
+  }
+
+  @override
+  List<String> get imports => _imports ??= <String>[];
+
+  /// URIs of `import` directives.
+  set imports(List<String> value) {
+    this._imports = value;
+  }
+
+  @override
+  List<UnlinkedInformativeDataBuilder> get informativeData =>
+      _informativeData ??= <UnlinkedInformativeDataBuilder>[];
+
+  set informativeData(List<UnlinkedInformativeDataBuilder> value) {
+    this._informativeData = value;
+  }
+
+  @override
+  List<int> get lineStarts => _lineStarts ??= <int>[];
+
+  /// Offsets of the first character of each line in the source code.
+  set lineStarts(List<int> value) {
+    assert(value == null || value.every((e) => e >= 0));
+    this._lineStarts = value;
+  }
+
+  @override
+  List<String> get parts => _parts ??= <String>[];
+
+  /// URIs of `part` directives.
+  set parts(List<String> value) {
+    this._parts = value;
+  }
+
+  UnlinkedUnit2Builder(
+      {List<int> apiSignature,
+      List<String> exports,
+      bool hasLibraryDirective,
+      bool hasPartOfDirective,
+      List<String> imports,
+      List<UnlinkedInformativeDataBuilder> informativeData,
+      List<int> lineStarts,
+      List<String> parts})
+      : _apiSignature = apiSignature,
+        _exports = exports,
+        _hasLibraryDirective = hasLibraryDirective,
+        _hasPartOfDirective = hasPartOfDirective,
+        _imports = imports,
+        _informativeData = informativeData,
+        _lineStarts = lineStarts,
+        _parts = parts;
+
+  /// Flush [informative] data recursively.
+  void flushInformative() {
+    _informativeData?.forEach((b) => b.flushInformative());
+    _lineStarts = null;
+  }
+
+  /// Accumulate non-[informative] data into [signature].
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    if (this._apiSignature == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._apiSignature.length);
+      for (var x in this._apiSignature) {
+        signature.addInt(x);
+      }
+    }
+    if (this._exports == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._exports.length);
+      for (var x in this._exports) {
+        signature.addString(x);
+      }
+    }
+    if (this._imports == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._imports.length);
+      for (var x in this._imports) {
+        signature.addString(x);
+      }
+    }
+    signature.addBool(this._hasPartOfDirective == true);
+    if (this._parts == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._parts.length);
+      for (var x in this._parts) {
+        signature.addString(x);
+      }
+    }
+    signature.addBool(this._hasLibraryDirective == true);
+    if (this._informativeData == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._informativeData.length);
+      for (var x in this._informativeData) {
+        x?.collectApiSignature(signature);
+      }
+    }
+  }
+
+  List<int> toBuffer() {
+    fb.Builder fbBuilder = new fb.Builder();
+    return fbBuilder.finish(finish(fbBuilder), "UUN2");
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_apiSignature;
+    fb.Offset offset_exports;
+    fb.Offset offset_imports;
+    fb.Offset offset_informativeData;
+    fb.Offset offset_lineStarts;
+    fb.Offset offset_parts;
+    if (!(_apiSignature == null || _apiSignature.isEmpty)) {
+      offset_apiSignature = fbBuilder.writeListUint32(_apiSignature);
+    }
+    if (!(_exports == null || _exports.isEmpty)) {
+      offset_exports = fbBuilder
+          .writeList(_exports.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    if (!(_imports == null || _imports.isEmpty)) {
+      offset_imports = fbBuilder
+          .writeList(_imports.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    if (!(_informativeData == null || _informativeData.isEmpty)) {
+      offset_informativeData = fbBuilder
+          .writeList(_informativeData.map((b) => b.finish(fbBuilder)).toList());
+    }
+    if (!(_lineStarts == null || _lineStarts.isEmpty)) {
+      offset_lineStarts = fbBuilder.writeListUint32(_lineStarts);
+    }
+    if (!(_parts == null || _parts.isEmpty)) {
+      offset_parts = fbBuilder
+          .writeList(_parts.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    fbBuilder.startTable();
+    if (offset_apiSignature != null) {
+      fbBuilder.addOffset(0, offset_apiSignature);
+    }
+    if (offset_exports != null) {
+      fbBuilder.addOffset(1, offset_exports);
+    }
+    if (_hasLibraryDirective == true) {
+      fbBuilder.addBool(6, true);
+    }
+    if (_hasPartOfDirective == true) {
+      fbBuilder.addBool(3, true);
+    }
+    if (offset_imports != null) {
+      fbBuilder.addOffset(2, offset_imports);
+    }
+    if (offset_informativeData != null) {
+      fbBuilder.addOffset(7, offset_informativeData);
+    }
+    if (offset_lineStarts != null) {
+      fbBuilder.addOffset(5, offset_lineStarts);
+    }
+    if (offset_parts != null) {
+      fbBuilder.addOffset(4, offset_parts);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+idl.UnlinkedUnit2 readUnlinkedUnit2(List<int> buffer) {
+  fb.BufferContext rootRef = new fb.BufferContext.fromBytes(buffer);
+  return const _UnlinkedUnit2Reader().read(rootRef, 0);
+}
+
+class _UnlinkedUnit2Reader extends fb.TableReader<_UnlinkedUnit2Impl> {
+  const _UnlinkedUnit2Reader();
+
+  @override
+  _UnlinkedUnit2Impl createObject(fb.BufferContext bc, int offset) =>
+      new _UnlinkedUnit2Impl(bc, offset);
+}
+
+class _UnlinkedUnit2Impl extends Object
+    with _UnlinkedUnit2Mixin
+    implements idl.UnlinkedUnit2 {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _UnlinkedUnit2Impl(this._bc, this._bcOffset);
+
+  List<int> _apiSignature;
+  List<String> _exports;
+  bool _hasLibraryDirective;
+  bool _hasPartOfDirective;
+  List<String> _imports;
+  List<idl.UnlinkedInformativeData> _informativeData;
+  List<int> _lineStarts;
+  List<String> _parts;
+
+  @override
+  List<int> get apiSignature {
+    _apiSignature ??=
+        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 0, const <int>[]);
+    return _apiSignature;
+  }
+
+  @override
+  List<String> get exports {
+    _exports ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 1, const <String>[]);
+    return _exports;
+  }
+
+  @override
+  bool get hasLibraryDirective {
+    _hasLibraryDirective ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 6, false);
+    return _hasLibraryDirective;
+  }
+
+  @override
+  bool get hasPartOfDirective {
+    _hasPartOfDirective ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
+    return _hasPartOfDirective;
+  }
+
+  @override
+  List<String> get imports {
+    _imports ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 2, const <String>[]);
+    return _imports;
+  }
+
+  @override
+  List<idl.UnlinkedInformativeData> get informativeData {
+    _informativeData ??= const fb.ListReader<idl.UnlinkedInformativeData>(
+            const _UnlinkedInformativeDataReader())
+        .vTableGet(_bc, _bcOffset, 7, const <idl.UnlinkedInformativeData>[]);
+    return _informativeData;
+  }
+
+  @override
+  List<int> get lineStarts {
+    _lineStarts ??=
+        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 5, const <int>[]);
+    return _lineStarts;
+  }
+
+  @override
+  List<String> get parts {
+    _parts ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 4, const <String>[]);
+    return _parts;
+  }
+}
+
+abstract class _UnlinkedUnit2Mixin implements idl.UnlinkedUnit2 {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (apiSignature.isNotEmpty) _result["apiSignature"] = apiSignature;
+    if (exports.isNotEmpty) _result["exports"] = exports;
+    if (hasLibraryDirective != false)
+      _result["hasLibraryDirective"] = hasLibraryDirective;
+    if (hasPartOfDirective != false)
+      _result["hasPartOfDirective"] = hasPartOfDirective;
+    if (imports.isNotEmpty) _result["imports"] = imports;
+    if (informativeData.isNotEmpty)
+      _result["informativeData"] =
+          informativeData.map((_value) => _value.toJson()).toList();
+    if (lineStarts.isNotEmpty) _result["lineStarts"] = lineStarts;
+    if (parts.isNotEmpty) _result["parts"] = parts;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "apiSignature": apiSignature,
+        "exports": exports,
+        "hasLibraryDirective": hasLibraryDirective,
+        "hasPartOfDirective": hasPartOfDirective,
+        "imports": imports,
+        "informativeData": informativeData,
+        "lineStarts": lineStarts,
+        "parts": parts,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
 class UnlinkedVariableBuilder extends Object
     with _UnlinkedVariableMixin
     implements idl.UnlinkedVariable {
@@ -28730,6 +27189,7 @@
   bool _isConst;
   bool _isCovariant;
   bool _isFinal;
+  bool _isLate;
   bool _isStatic;
   String _name;
   int _nameOffset;
@@ -28824,6 +27284,14 @@
   }
 
   @override
+  bool get isLate => _isLate ??= false;
+
+  /// Indicates whether the variable is declared using the `late` keyword.
+  set isLate(bool value) {
+    this._isLate = value;
+  }
+
+  @override
   bool get isStatic => _isStatic ??= false;
 
   /// Indicates whether the variable is declared using the `static` keyword.
@@ -28892,6 +27360,7 @@
       bool isConst,
       bool isCovariant,
       bool isFinal,
+      bool isLate,
       bool isStatic,
       String name,
       int nameOffset,
@@ -28906,6 +27375,7 @@
         _isConst = isConst,
         _isCovariant = isCovariant,
         _isFinal = isFinal,
+        _isLate = isLate,
         _isStatic = isStatic,
         _name = name,
         _nameOffset = nameOffset,
@@ -28944,6 +27414,7 @@
     this._initializer?.collectApiSignature(signature);
     signature.addBool(this._isCovariant == true);
     signature.addInt(this._inheritsCovariantSlot ?? 0);
+    signature.addBool(this._isLate == true);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -29000,6 +27471,9 @@
     if (_isFinal == true) {
       fbBuilder.addBool(7, true);
     }
+    if (_isLate == true) {
+      fbBuilder.addBool(16, true);
+    }
     if (_isStatic == true) {
       fbBuilder.addBool(4, true);
     }
@@ -29044,6 +27518,7 @@
   bool _isConst;
   bool _isCovariant;
   bool _isFinal;
+  bool _isLate;
   bool _isStatic;
   String _name;
   int _nameOffset;
@@ -29111,6 +27586,12 @@
   }
 
   @override
+  bool get isLate {
+    _isLate ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 16, false);
+    return _isLate;
+  }
+
+  @override
   bool get isStatic {
     _isStatic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 4, false);
     return _isStatic;
@@ -29167,6 +27648,7 @@
     if (isConst != false) _result["isConst"] = isConst;
     if (isCovariant != false) _result["isCovariant"] = isCovariant;
     if (isFinal != false) _result["isFinal"] = isFinal;
+    if (isLate != false) _result["isLate"] = isLate;
     if (isStatic != false) _result["isStatic"] = isStatic;
     if (name != '') _result["name"] = name;
     if (nameOffset != 0) _result["nameOffset"] = nameOffset;
@@ -29187,6 +27669,7 @@
         "isConst": isConst,
         "isCovariant": isCovariant,
         "isFinal": isFinal,
+        "isLate": isLate,
         "isStatic": isStatic,
         "name": name,
         "nameOffset": nameOffset,
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 25f838b..d68ae09 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -46,6 +46,30 @@
   syntheticFunction
 }
 
+/// Enum representing nullability suffixes in summaries.
+///
+/// This enum is similar to [NullabilitySuffix], but the order is different so
+/// that [EntityRefNullabilitySuffix.starOrIrrelevant] can be the default.
+enum EntityRefNullabilitySuffix : byte {
+  /// An indication that the canonical representation of the type under
+  /// consideration ends with `*`.  Types having this nullability suffix are
+  /// called "legacy types"; it has not yet been determined whether they should
+  /// be unioned with the Null type.
+  ///
+  /// Also used in circumstances where no nullability suffix information is
+  /// needed.
+  starOrIrrelevant,
+
+  /// An indication that the canonical representation of the type under
+  /// consideration ends with `?`.  Types having this nullability suffix should
+  /// be interpreted as being unioned with the Null type.
+  question,
+
+  /// An indication that the canonical representation of the type under
+  /// consideration does not end with either `?` or `*`.
+  none
+}
+
 /// Enum used to indicate the kind of a name in index.
 enum IndexNameKind : byte {
   /// A top-level element.
@@ -152,11 +176,13 @@
 
 /// Kinds of formal parameters.
 enum LinkedNodeFormalParameterKind : byte {
-  required,
+  requiredPositional,
 
   optionalPositional,
 
-  optionalNamed
+  optionalNamed,
+
+  requiredNamed
 }
 
 /// Kinds of [LinkedNode].
@@ -197,6 +223,8 @@
 
   comment,
 
+  commentReference,
+
   compilationUnit,
 
   conditionalExpression,
@@ -341,8 +369,6 @@
 
   returnStatement,
 
-  scriptTag,
-
   setOrMapLiteral,
 
   showCombinator,
@@ -1071,14 +1097,17 @@
 
 /// Enum used to indicate the kind of a parameter.
 enum UnlinkedParamKind : byte {
-  /// Parameter is required.
-  required,
+  /// Parameter is required and positional.
+  requiredPositional,
 
-  /// Parameter is positional optional (enclosed in `[]`)
-  positional,
+  /// Parameter is optional and positional (enclosed in `[]`)
+  optionalPositional,
 
-  /// Parameter is named optional (enclosed in `{}`)
-  named
+  /// Parameter is optional and named (enclosed in `{}`)
+  optionalNamed,
+
+  /// Parameter is required and named (enclosed in `{}`).
+  requiredNamed
 }
 
 /// TODO(scheglov) document
@@ -1124,6 +1153,8 @@
 
   BANG_EQ,
 
+  BANG_EQ_EQ,
+
   BAR,
 
   BAR_BAR,
@@ -1178,6 +1209,8 @@
 
   EQ_EQ,
 
+  EQ_EQ_EQ,
+
   EXPORT,
 
   EXTENDS,
@@ -1208,6 +1241,10 @@
 
   GT_GT_EQ,
 
+  GT_GT_GT,
+
+  GT_GT_GT_EQ,
+
   HASH,
 
   HEXADECIMAL,
@@ -1234,6 +1271,8 @@
 
   IS,
 
+  LATE,
+
   LIBRARY,
 
   LT,
@@ -1302,6 +1341,8 @@
 
   QUESTION_QUESTION_EQ,
 
+  REQUIRED,
+
   RETHROW,
 
   RETURN,
@@ -1541,6 +1582,9 @@
 
   /// Unlinked information for the unit.
   unit:UnlinkedUnit (id: 1);
+
+  /// Unlinked information for the unit.
+  unit2:UnlinkedUnit2 (id: 5);
 }
 
 /// Information about a single declaration.
@@ -1688,6 +1732,9 @@
   /// first to the class and then to the method.
   implicitFunctionTypeIndices:[uint] (id: 4);
 
+  /// If the reference represents a type, the nullability of the type.
+  nullabilitySuffix:EntityRefNullabilitySuffix (id: 10);
+
   /// If this is a reference to a type parameter, one-based index into the list
   /// of [UnlinkedTypeParam]s currently in effect.  Indexing is done using De
   /// Bruijn index conventions; that is, innermost parameters come first, and
@@ -1839,28 +1886,22 @@
 
   variantField_2:[LinkedNode] (id: 2);
 
-  variantField_11:LinkedNode (id: 11);
-
   variantField_4:[LinkedNode] (id: 4);
 
   variantField_6:LinkedNode (id: 6);
 
-  variantField_15:uint (id: 15);
-
   variantField_7:LinkedNode (id: 7);
 
-  variantField_8:LinkedNode (id: 8);
-
-  variantField_16:uint (id: 16);
-
   variantField_17:uint (id: 17);
 
-  variantField_18:uint (id: 18);
-
-  variantField_19:uint (id: 19);
-
   variantField_23:LinkedNodeType (id: 23);
 
+  variantField_8:LinkedNode (id: 8);
+
+  variantField_15:uint (id: 15);
+
+  variantField_28:UnlinkedTokenType (id: 28);
+
   variantField_27:bool (id: 27);
 
   variantField_9:LinkedNode (id: 9);
@@ -1871,11 +1912,7 @@
 
   variantField_13:LinkedNode (id: 13);
 
-  variantField_34:uint (id: 34);
-
-  variantField_33:uint (id: 33);
-
-  variantField_28:[uint] (id: 28);
+  variantField_33:[string] (id: 33);
 
   variantField_29:LinkedNodeCommentType (id: 29);
 
@@ -1883,27 +1920,43 @@
 
   variantField_10:LinkedNode (id: 10);
 
+  variantField_26:LinkedNodeFormalParameterKind (id: 26);
+
   variantField_21:double (id: 21);
 
   variantField_25:LinkedNodeType (id: 25);
 
-  variantField_26:LinkedNodeFormalParameterKind (id: 26);
+  flags:uint (id: 18);
+
+  variantField_1:string (id: 1);
+
+  variantField_36:uint (id: 36);
+
+  variantField_16:uint (id: 16);
 
   variantField_30:string (id: 30);
 
   variantField_14:LinkedNode (id: 14);
 
-  isSynthetic:bool (id: 1);
-
   kind:LinkedNodeKind (id: 0);
 
+  variantField_34:[string] (id: 34);
+
+  name:string (id: 37);
+
   variantField_20:string (id: 20);
 
   variantField_31:bool (id: 31);
 
+  variantField_35:UnlinkedTokenType (id: 35);
+
+  variantField_32:TopLevelInferenceError (id: 32);
+
+  variantField_11:LinkedNode (id: 11);
+
   variantField_22:string (id: 22);
 
-  variantField_32:LinkedNodeVariablesDeclaration (id: 32);
+  variantField_19:uint (id: 19);
 }
 
 /// Information about a group of libraries linked together, for example because
@@ -1945,9 +1998,9 @@
 
   functionTypeParameters:[LinkedNodeTypeTypeParameter] (id: 2);
 
-  genericTypeAliasReference:uint (id: 7);
+  genericTypeAliasReference:uint (id: 8);
 
-  genericTypeAliasTypeArguments:[LinkedNodeType] (id: 8);
+  genericTypeAliasTypeArguments:[LinkedNodeType] (id: 9);
 
   /// Reference to a [LinkedNodeReferences].
   interfaceClass:uint (id: 3);
@@ -1956,7 +2009,11 @@
 
   kind:LinkedNodeTypeKind (id: 5);
 
-  typeParameterId:uint (id: 6);
+  nullabilitySuffix:EntityRefNullabilitySuffix (id: 10);
+
+  typeParameterElement:uint (id: 6);
+
+  typeParameterId:uint (id: 7);
 }
 
 /// Information about a formal parameter in a function type.
@@ -1977,6 +2034,10 @@
 
 /// Information about a single library in a [LinkedNodeLibrary].
 table LinkedNodeUnit {
+  isNNBD:bool (id: 4);
+
+  isSynthetic:bool (id: 3);
+
   node:LinkedNode (id: 2);
 
   tokens:UnlinkedTokens (id: 1);
@@ -1984,20 +2045,6 @@
   uriStr:string (id: 0);
 }
 
-/// Information about a top-level declaration, or a field declaration that
-/// contributes information to [LinkedNodeKind.variableDeclaration].
-table LinkedNodeVariablesDeclaration {
-  comment:LinkedNode (id: 0);
-
-  isConst:bool (id: 1);
-
-  isCovariant:bool (id: 2);
-
-  isFinal:bool (id: 3);
-
-  isStatic:bool (id: 4);
-}
-
 /// Information about the resolution of an [UnlinkedReference].
 table LinkedReference {
   /// If this [LinkedReference] doesn't have an associated [UnlinkedReference],
@@ -2086,6 +2133,9 @@
   /// package may have changed.
   apiSignature:string (id: 7, deprecated);
 
+  /// The version 2 of the summary.
+  bundle2:LinkedNodeBundle (id: 9);
+
   /// Information about the packages this package depends on, if known.
   dependencies:[PackageDependencyInfo] (id: 8, deprecated);
 
@@ -2690,6 +2740,26 @@
   uriOffset:uint (id: 3);
 }
 
+table UnlinkedInformativeData {
+  variantField_2:uint (id: 2);
+
+  variantField_3:uint (id: 3);
+
+  variantField_1:uint (id: 1);
+
+  variantField_4:[string] (id: 4);
+
+  /// The kind of the node.
+  kind:LinkedNodeKind (id: 0);
+
+  variantField_5:uint (id: 5);
+
+  variantField_6:uint (id: 6);
+
+  /// Offsets of the first character of each line in the source code.
+  variantField_7:[uint] (id: 7);
+}
+
 /// Unlinked summary information about a function parameter.
 table UnlinkedParam {
   /// Annotations for this parameter.
@@ -2969,6 +3039,9 @@
   /// Import declarations in the compilation unit.
   imports:[UnlinkedImport] (id: 5);
 
+  /// Indicates whether this compilation unit is opted into NNBD.
+  isNNBD:bool (id: 21);
+
   /// Indicates whether the unit contains a "part of" declaration.
   isPartOf:bool (id: 18);
 
@@ -3017,6 +3090,33 @@
   variables:[UnlinkedVariable] (id: 3);
 }
 
+/// Unlinked summary information about a compilation unit.
+table UnlinkedUnit2 {
+  /// The MD5 hash signature of the API portion of this unit. It depends on all
+  /// tokens that might affect APIs of declarations in the unit.
+  apiSignature:[uint] (id: 0);
+
+  /// URIs of `export` directives.
+  exports:[string] (id: 1);
+
+  /// Is `true` if the unit contains a `library` directive.
+  hasLibraryDirective:bool (id: 6);
+
+  /// Is `true` if the unit contains a `part of` directive.
+  hasPartOfDirective:bool (id: 3);
+
+  /// URIs of `import` directives.
+  imports:[string] (id: 2);
+
+  informativeData:[UnlinkedInformativeData] (id: 7);
+
+  /// Offsets of the first character of each line in the source code.
+  lineStarts:[uint] (id: 5);
+
+  /// URIs of `part` directives.
+  parts:[string] (id: 4);
+}
+
 /// Unlinked summary information about a top level variable, local variable, or
 /// a field.
 table UnlinkedVariable {
@@ -3058,6 +3158,9 @@
   /// Indicates whether the variable is declared using the `final` keyword.
   isFinal:bool (id: 7);
 
+  /// Indicates whether the variable is declared using the `late` keyword.
+  isLate:bool (id: 16);
+
   /// Indicates whether the variable is declared using the `static` keyword.
   ///
   /// Note that for top level variables, this flag is false, since they are not
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 0bf34e0..6590b07 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -283,6 +283,10 @@
   /// Unlinked information for the unit.
   @Id(1)
   UnlinkedUnit get unit;
+
+  /// Unlinked information for the unit.
+  @Id(5)
+  UnlinkedUnit2 get unit2;
 }
 
 /// Information about a single declaration.
@@ -487,6 +491,10 @@
   @Id(4)
   List<int> get implicitFunctionTypeIndices;
 
+  /// If the reference represents a type, the nullability of the type.
+  @Id(10)
+  EntityRefNullabilitySuffix get nullabilitySuffix;
+
   /// If this is a reference to a type parameter, one-based index into the list
   /// of [UnlinkedTypeParam]s currently in effect.  Indexing is done using De
   /// Bruijn index conventions; that is, innermost parameters come first, and
@@ -571,6 +579,30 @@
   syntheticFunction
 }
 
+/// Enum representing nullability suffixes in summaries.
+///
+/// This enum is similar to [NullabilitySuffix], but the order is different so
+/// that [EntityRefNullabilitySuffix.starOrIrrelevant] can be the default.
+enum EntityRefNullabilitySuffix {
+  /// An indication that the canonical representation of the type under
+  /// consideration ends with `*`.  Types having this nullability suffix are
+  /// called "legacy types"; it has not yet been determined whether they should
+  /// be unioned with the Null type.
+  ///
+  /// Also used in circumstances where no nullability suffix information is
+  /// needed.
+  starOrIrrelevant,
+
+  /// An indication that the canonical representation of the type under
+  /// consideration ends with `?`.  Types having this nullability suffix should
+  /// be interpreted as being unioned with the Null type.
+  question,
+
+  /// An indication that the canonical representation of the type under
+  /// consideration does not end with either `?` or `*`.
+  none,
+}
+
 /// Enum used to indicate the kind of a name in index.
 enum IndexNameKind {
   /// A top-level element.
@@ -790,31 +822,6 @@
   @VariantId(2, variant: LinkedNodeKind.adjacentStrings)
   List<LinkedNode> get adjacentStrings_strings;
 
-  @VariantId(11, variantList: [
-    LinkedNodeKind.classDeclaration,
-    LinkedNodeKind.classTypeAlias,
-    LinkedNodeKind.constructorDeclaration,
-    LinkedNodeKind.declaredIdentifier,
-    LinkedNodeKind.enumDeclaration,
-    LinkedNodeKind.enumConstantDeclaration,
-    LinkedNodeKind.exportDirective,
-    LinkedNodeKind.fieldDeclaration,
-    LinkedNodeKind.functionDeclaration,
-    LinkedNodeKind.functionTypeAlias,
-    LinkedNodeKind.genericTypeAlias,
-    LinkedNodeKind.importDirective,
-    LinkedNodeKind.libraryDirective,
-    LinkedNodeKind.methodDeclaration,
-    LinkedNodeKind.mixinDeclaration,
-    LinkedNodeKind.partDirective,
-    LinkedNodeKind.partOfDirective,
-    LinkedNodeKind.topLevelVariableDeclaration,
-    LinkedNodeKind.typeParameter,
-    LinkedNodeKind.variableDeclaration,
-    LinkedNodeKind.variableDeclarationList,
-  ])
-  LinkedNode get annotatedNode_comment;
-
   @VariantId(4, variantList: [
     LinkedNodeKind.classDeclaration,
     LinkedNodeKind.classTypeAlias,
@@ -843,75 +850,39 @@
   @VariantId(6, variant: LinkedNodeKind.annotation)
   LinkedNode get annotation_arguments;
 
-  @VariantId(15, variant: LinkedNodeKind.annotation)
-  int get annotation_atSign;
-
   @VariantId(7, variant: LinkedNodeKind.annotation)
   LinkedNode get annotation_constructorName;
 
+  @VariantId(17, variant: LinkedNodeKind.annotation)
+  int get annotation_element;
+
+  @VariantId(23, variant: LinkedNodeKind.annotation)
+  LinkedNodeType get annotation_elementType;
+
   @VariantId(8, variant: LinkedNodeKind.annotation)
   LinkedNode get annotation_name;
 
-  @VariantId(16, variant: LinkedNodeKind.annotation)
-  int get annotation_period;
-
   @VariantId(2, variant: LinkedNodeKind.argumentList)
   List<LinkedNode> get argumentList_arguments;
 
-  @VariantId(15, variant: LinkedNodeKind.argumentList)
-  int get argumentList_leftParenthesis;
-
-  @VariantId(16, variant: LinkedNodeKind.argumentList)
-  int get argumentList_rightParenthesis;
-
-  @VariantId(15, variant: LinkedNodeKind.asExpression)
-  int get asExpression_asOperator;
-
   @VariantId(6, variant: LinkedNodeKind.asExpression)
   LinkedNode get asExpression_expression;
 
   @VariantId(7, variant: LinkedNodeKind.asExpression)
   LinkedNode get asExpression_type;
 
-  @VariantId(15, variant: LinkedNodeKind.assertInitializer)
-  int get assertInitializer_assertKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.assertInitializer)
-  int get assertInitializer_comma;
-
   @VariantId(6, variant: LinkedNodeKind.assertInitializer)
   LinkedNode get assertInitializer_condition;
 
-  @VariantId(17, variant: LinkedNodeKind.assertInitializer)
-  int get assertInitializer_leftParenthesis;
-
   @VariantId(7, variant: LinkedNodeKind.assertInitializer)
   LinkedNode get assertInitializer_message;
 
-  @VariantId(18, variant: LinkedNodeKind.assertInitializer)
-  int get assertInitializer_rightParenthesis;
-
-  @VariantId(15, variant: LinkedNodeKind.assertStatement)
-  int get assertStatement_assertKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.assertStatement)
-  int get assertStatement_comma;
-
   @VariantId(6, variant: LinkedNodeKind.assertStatement)
   LinkedNode get assertStatement_condition;
 
-  @VariantId(17, variant: LinkedNodeKind.assertStatement)
-  int get assertStatement_leftParenthesis;
-
   @VariantId(7, variant: LinkedNodeKind.assertStatement)
   LinkedNode get assertStatement_message;
 
-  @VariantId(18, variant: LinkedNodeKind.assertStatement)
-  int get assertStatement_rightParenthesis;
-
-  @VariantId(19, variant: LinkedNodeKind.assertStatement)
-  int get assertStatement_semicolon;
-
   @VariantId(15, variant: LinkedNodeKind.assignmentExpression)
   int get assignmentExpression_element;
 
@@ -921,15 +892,12 @@
   @VariantId(6, variant: LinkedNodeKind.assignmentExpression)
   LinkedNode get assignmentExpression_leftHandSide;
 
-  @VariantId(16, variant: LinkedNodeKind.assignmentExpression)
-  int get assignmentExpression_operator;
+  @VariantId(28, variant: LinkedNodeKind.assignmentExpression)
+  UnlinkedTokenType get assignmentExpression_operator;
 
   @VariantId(7, variant: LinkedNodeKind.assignmentExpression)
   LinkedNode get assignmentExpression_rightHandSide;
 
-  @VariantId(15, variant: LinkedNodeKind.awaitExpression)
-  int get awaitExpression_awaitKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.awaitExpression)
   LinkedNode get awaitExpression_expression;
 
@@ -945,45 +913,24 @@
   @VariantId(6, variant: LinkedNodeKind.binaryExpression)
   LinkedNode get binaryExpression_leftOperand;
 
-  @VariantId(16, variant: LinkedNodeKind.binaryExpression)
-  int get binaryExpression_operator;
+  @VariantId(28, variant: LinkedNodeKind.binaryExpression)
+  UnlinkedTokenType get binaryExpression_operator;
 
   @VariantId(7, variant: LinkedNodeKind.binaryExpression)
   LinkedNode get binaryExpression_rightOperand;
 
-  @VariantId(15, variant: LinkedNodeKind.block)
-  int get block_leftBracket;
-
-  @VariantId(16, variant: LinkedNodeKind.block)
-  int get block_rightBracket;
-
   @VariantId(2, variant: LinkedNodeKind.block)
   List<LinkedNode> get block_statements;
 
   @VariantId(6, variant: LinkedNodeKind.blockFunctionBody)
   LinkedNode get blockFunctionBody_block;
 
-  @VariantId(15, variant: LinkedNodeKind.blockFunctionBody)
-  int get blockFunctionBody_keyword;
-
-  @VariantId(16, variant: LinkedNodeKind.blockFunctionBody)
-  int get blockFunctionBody_star;
-
-  @VariantId(15, variant: LinkedNodeKind.booleanLiteral)
-  int get booleanLiteral_literal;
-
   @VariantId(27, variant: LinkedNodeKind.booleanLiteral)
   bool get booleanLiteral_value;
 
-  @VariantId(15, variant: LinkedNodeKind.breakStatement)
-  int get breakStatement_breakKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.breakStatement)
   LinkedNode get breakStatement_label;
 
-  @VariantId(16, variant: LinkedNodeKind.breakStatement)
-  int get breakStatement_semicolon;
-
   @VariantId(2, variant: LinkedNodeKind.cascadeExpression)
   List<LinkedNode> get cascadeExpression_sections;
 
@@ -993,36 +940,15 @@
   @VariantId(6, variant: LinkedNodeKind.catchClause)
   LinkedNode get catchClause_body;
 
-  @VariantId(15, variant: LinkedNodeKind.catchClause)
-  int get catchClause_catchKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.catchClause)
-  int get catchClause_comma;
-
   @VariantId(7, variant: LinkedNodeKind.catchClause)
   LinkedNode get catchClause_exceptionParameter;
 
   @VariantId(8, variant: LinkedNodeKind.catchClause)
   LinkedNode get catchClause_exceptionType;
 
-  @VariantId(17, variant: LinkedNodeKind.catchClause)
-  int get catchClause_leftParenthesis;
-
-  @VariantId(18, variant: LinkedNodeKind.catchClause)
-  int get catchClause_onKeyword;
-
-  @VariantId(19, variant: LinkedNodeKind.catchClause)
-  int get catchClause_rightParenthesis;
-
   @VariantId(9, variant: LinkedNodeKind.catchClause)
   LinkedNode get catchClause_stackTraceParameter;
 
-  @VariantId(15, variant: LinkedNodeKind.classDeclaration)
-  int get classDeclaration_abstractKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.classDeclaration)
-  int get classDeclaration_classKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.classDeclaration)
   LinkedNode get classDeclaration_extendsClause;
 
@@ -1041,36 +967,18 @@
   ])
   LinkedNode get classOrMixinDeclaration_implementsClause;
 
-  @VariantId(19, variantList: [
-    LinkedNodeKind.classDeclaration,
-    LinkedNodeKind.mixinDeclaration,
-  ])
-  int get classOrMixinDeclaration_leftBracket;
-
   @VariantId(5, variantList: [
     LinkedNodeKind.classDeclaration,
     LinkedNodeKind.mixinDeclaration,
   ])
   List<LinkedNode> get classOrMixinDeclaration_members;
 
-  @VariantId(18, variantList: [
-    LinkedNodeKind.classDeclaration,
-    LinkedNodeKind.mixinDeclaration,
-  ])
-  int get classOrMixinDeclaration_rightBracket;
-
   @VariantId(13, variantList: [
     LinkedNodeKind.classDeclaration,
     LinkedNodeKind.mixinDeclaration,
   ])
   LinkedNode get classOrMixinDeclaration_typeParameters;
 
-  @VariantId(15, variant: LinkedNodeKind.classTypeAlias)
-  int get classTypeAlias_abstractKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.classTypeAlias)
-  int get classTypeAlias_equals;
-
   @VariantId(9, variant: LinkedNodeKind.classTypeAlias)
   LinkedNode get classTypeAlias_implementsClause;
 
@@ -1083,58 +991,17 @@
   @VariantId(8, variant: LinkedNodeKind.classTypeAlias)
   LinkedNode get classTypeAlias_withClause;
 
-  @VariantId(34, variantList: [
-    LinkedNodeKind.classDeclaration,
-    LinkedNodeKind.classTypeAlias,
-    LinkedNodeKind.constructorDeclaration,
-    LinkedNodeKind.defaultFormalParameter,
-    LinkedNodeKind.enumDeclaration,
-    LinkedNodeKind.fieldFormalParameter,
-    LinkedNodeKind.functionDeclaration,
-    LinkedNodeKind.functionTypeAlias,
-    LinkedNodeKind.functionTypedFormalParameter,
-    LinkedNodeKind.genericTypeAlias,
-    LinkedNodeKind.methodDeclaration,
-    LinkedNodeKind.mixinDeclaration,
-    LinkedNodeKind.simpleFormalParameter,
-    LinkedNodeKind.typeParameter,
-    LinkedNodeKind.variableDeclaration,
-  ])
-  int get codeLength;
+  @VariantId(2, variant: LinkedNodeKind.comment)
+  List<LinkedNode> get comment_references;
 
-  @VariantId(33, variantList: [
-    LinkedNodeKind.classDeclaration,
-    LinkedNodeKind.classTypeAlias,
-    LinkedNodeKind.constructorDeclaration,
-    LinkedNodeKind.defaultFormalParameter,
-    LinkedNodeKind.enumDeclaration,
-    LinkedNodeKind.fieldFormalParameter,
-    LinkedNodeKind.functionDeclaration,
-    LinkedNodeKind.functionTypeAlias,
-    LinkedNodeKind.functionTypedFormalParameter,
-    LinkedNodeKind.genericTypeAlias,
-    LinkedNodeKind.methodDeclaration,
-    LinkedNodeKind.mixinDeclaration,
-    LinkedNodeKind.simpleFormalParameter,
-    LinkedNodeKind.typeParameter,
-    LinkedNodeKind.variableDeclaration,
-  ])
-  int get codeOffset;
-
-  @VariantId(19, variantList: [
-    LinkedNodeKind.hideCombinator,
-    LinkedNodeKind.showCombinator,
-  ])
-  int get combinator_keyword;
-
-  @VariantId(28, variant: LinkedNodeKind.comment)
-  List<int> get comment_tokens;
+  @VariantId(33, variant: LinkedNodeKind.comment)
+  List<String> get comment_tokens;
 
   @VariantId(29, variant: LinkedNodeKind.comment)
   LinkedNodeCommentType get comment_type;
 
-  @VariantId(15, variant: LinkedNodeKind.compilationUnit)
-  int get compilationUnit_beginToken;
+  @VariantId(6, variant: LinkedNodeKind.commentReference)
+  LinkedNode get commentReference_identifier;
 
   @VariantId(2, variant: LinkedNodeKind.compilationUnit)
   List<LinkedNode> get compilationUnit_declarations;
@@ -1142,42 +1009,21 @@
   @VariantId(3, variant: LinkedNodeKind.compilationUnit)
   List<LinkedNode> get compilationUnit_directives;
 
-  @VariantId(16, variant: LinkedNodeKind.compilationUnit)
-  int get compilationUnit_endToken;
-
   @VariantId(6, variant: LinkedNodeKind.compilationUnit)
   LinkedNode get compilationUnit_scriptTag;
 
-  @VariantId(15, variant: LinkedNodeKind.conditionalExpression)
-  int get conditionalExpression_colon;
-
   @VariantId(6, variant: LinkedNodeKind.conditionalExpression)
   LinkedNode get conditionalExpression_condition;
 
   @VariantId(7, variant: LinkedNodeKind.conditionalExpression)
   LinkedNode get conditionalExpression_elseExpression;
 
-  @VariantId(16, variant: LinkedNodeKind.conditionalExpression)
-  int get conditionalExpression_question;
-
   @VariantId(8, variant: LinkedNodeKind.conditionalExpression)
   LinkedNode get conditionalExpression_thenExpression;
 
-  @VariantId(18, variant: LinkedNodeKind.configuration)
-  int get configuration_equalToken;
-
-  @VariantId(15, variant: LinkedNodeKind.configuration)
-  int get configuration_ifKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.configuration)
-  int get configuration_leftParenthesis;
-
   @VariantId(6, variant: LinkedNodeKind.configuration)
   LinkedNode get configuration_name;
 
-  @VariantId(17, variant: LinkedNodeKind.configuration)
-  int get configuration_rightParenthesis;
-
   @VariantId(8, variant: LinkedNodeKind.configuration)
   LinkedNode get configuration_uri;
 
@@ -1187,51 +1033,24 @@
   @VariantId(6, variant: LinkedNodeKind.constructorDeclaration)
   LinkedNode get constructorDeclaration_body;
 
-  @VariantId(15, variant: LinkedNodeKind.constructorDeclaration)
-  int get constructorDeclaration_constKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.constructorDeclaration)
-  int get constructorDeclaration_externalKeyword;
-
-  @VariantId(17, variant: LinkedNodeKind.constructorDeclaration)
-  int get constructorDeclaration_factoryKeyword;
-
   @VariantId(2, variant: LinkedNodeKind.constructorDeclaration)
   List<LinkedNode> get constructorDeclaration_initializers;
 
-  @VariantId(7, variant: LinkedNodeKind.constructorDeclaration)
-  LinkedNode get constructorDeclaration_name;
-
   @VariantId(8, variant: LinkedNodeKind.constructorDeclaration)
   LinkedNode get constructorDeclaration_parameters;
 
-  @VariantId(18, variant: LinkedNodeKind.constructorDeclaration)
-  int get constructorDeclaration_period;
-
   @VariantId(9, variant: LinkedNodeKind.constructorDeclaration)
   LinkedNode get constructorDeclaration_redirectedConstructor;
 
   @VariantId(10, variant: LinkedNodeKind.constructorDeclaration)
   LinkedNode get constructorDeclaration_returnType;
 
-  @VariantId(19, variant: LinkedNodeKind.constructorDeclaration)
-  int get constructorDeclaration_separator;
-
-  @VariantId(15, variant: LinkedNodeKind.constructorFieldInitializer)
-  int get constructorFieldInitializer_equals;
-
   @VariantId(6, variant: LinkedNodeKind.constructorFieldInitializer)
   LinkedNode get constructorFieldInitializer_expression;
 
   @VariantId(7, variant: LinkedNodeKind.constructorFieldInitializer)
   LinkedNode get constructorFieldInitializer_fieldName;
 
-  @VariantId(16, variant: LinkedNodeKind.constructorFieldInitializer)
-  int get constructorFieldInitializer_period;
-
-  @VariantId(17, variant: LinkedNodeKind.constructorFieldInitializer)
-  int get constructorFieldInitializer_thisKeyword;
-
   @VariantId(15, variant: LinkedNodeKind.constructorName)
   int get constructorName_element;
 
@@ -1241,129 +1060,60 @@
   @VariantId(6, variant: LinkedNodeKind.constructorName)
   LinkedNode get constructorName_name;
 
-  @VariantId(16, variant: LinkedNodeKind.constructorName)
-  int get constructorName_period;
-
   @VariantId(7, variant: LinkedNodeKind.constructorName)
   LinkedNode get constructorName_type;
 
-  @VariantId(15, variant: LinkedNodeKind.continueStatement)
-  int get continueStatement_continueKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.continueStatement)
   LinkedNode get continueStatement_label;
 
-  @VariantId(16, variant: LinkedNodeKind.continueStatement)
-  int get continueStatement_semicolon;
-
   @VariantId(6, variant: LinkedNodeKind.declaredIdentifier)
   LinkedNode get declaredIdentifier_identifier;
 
-  @VariantId(15, variant: LinkedNodeKind.declaredIdentifier)
-  int get declaredIdentifier_keyword;
-
   @VariantId(7, variant: LinkedNodeKind.declaredIdentifier)
   LinkedNode get declaredIdentifier_type;
 
   @VariantId(6, variant: LinkedNodeKind.defaultFormalParameter)
   LinkedNode get defaultFormalParameter_defaultValue;
 
-  @VariantId(27, variant: LinkedNodeKind.defaultFormalParameter)
-  bool get defaultFormalParameter_isNamed;
+  @VariantId(26, variant: LinkedNodeKind.defaultFormalParameter)
+  LinkedNodeFormalParameterKind get defaultFormalParameter_kind;
 
   @VariantId(7, variant: LinkedNodeKind.defaultFormalParameter)
   LinkedNode get defaultFormalParameter_parameter;
 
-  @VariantId(15, variant: LinkedNodeKind.defaultFormalParameter)
-  int get defaultFormalParameter_separator;
-
-  @VariantId(18, variantList: [
-    LinkedNodeKind.exportDirective,
-    LinkedNodeKind.importDirective,
-    LinkedNodeKind.libraryDirective,
-    LinkedNodeKind.partDirective,
-    LinkedNodeKind.partOfDirective,
-  ])
-  int get directive_keyword;
-
-  @VariantId(33, variantList: [
-    LinkedNodeKind.exportDirective,
-    LinkedNodeKind.importDirective,
-    LinkedNodeKind.libraryDirective,
-    LinkedNodeKind.partDirective,
-    LinkedNodeKind.partOfDirective,
-  ])
-  int get directive_semicolon;
-
   @VariantId(6, variant: LinkedNodeKind.doStatement)
   LinkedNode get doStatement_body;
 
   @VariantId(7, variant: LinkedNodeKind.doStatement)
   LinkedNode get doStatement_condition;
 
-  @VariantId(17, variant: LinkedNodeKind.doStatement)
-  int get doStatement_doKeyword;
-
-  @VariantId(15, variant: LinkedNodeKind.doStatement)
-  int get doStatement_leftParenthesis;
-
-  @VariantId(16, variant: LinkedNodeKind.doStatement)
-  int get doStatement_rightParenthesis;
-
-  @VariantId(18, variant: LinkedNodeKind.doStatement)
-  int get doStatement_semicolon;
-
-  @VariantId(19, variant: LinkedNodeKind.doStatement)
-  int get doStatement_whileKeyword;
-
   @VariantId(2, variant: LinkedNodeKind.dottedName)
   List<LinkedNode> get dottedName_components;
 
-  @VariantId(15, variant: LinkedNodeKind.doubleLiteral)
-  int get doubleLiteral_literal;
-
   @VariantId(21, variant: LinkedNodeKind.doubleLiteral)
   double get doubleLiteral_value;
 
   @VariantId(15, variant: LinkedNodeKind.emptyFunctionBody)
-  int get emptyFunctionBody_semicolon;
+  int get emptyFunctionBody_fake;
 
   @VariantId(15, variant: LinkedNodeKind.emptyStatement)
-  int get emptyStatement_semicolon;
-
-  @VariantId(6, variant: LinkedNodeKind.enumConstantDeclaration)
-  LinkedNode get enumConstantDeclaration_name;
+  int get emptyStatement_fake;
 
   @VariantId(2, variant: LinkedNodeKind.enumDeclaration)
   List<LinkedNode> get enumDeclaration_constants;
 
-  @VariantId(15, variant: LinkedNodeKind.enumDeclaration)
-  int get enumDeclaration_enumKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.enumDeclaration)
-  int get enumDeclaration_leftBracket;
-
-  @VariantId(17, variant: LinkedNodeKind.enumDeclaration)
-  int get enumDeclaration_rightBracket;
-
   @VariantId(25, variantList: [
-    LinkedNodeKind.adjacentStrings,
     LinkedNodeKind.assignmentExpression,
     LinkedNodeKind.asExpression,
     LinkedNodeKind.awaitExpression,
     LinkedNodeKind.binaryExpression,
-    LinkedNodeKind.booleanLiteral,
     LinkedNodeKind.cascadeExpression,
     LinkedNodeKind.conditionalExpression,
-    LinkedNodeKind.doubleLiteral,
     LinkedNodeKind.functionExpressionInvocation,
     LinkedNodeKind.indexExpression,
     LinkedNodeKind.instanceCreationExpression,
-    LinkedNodeKind.integerLiteral,
-    LinkedNodeKind.isExpression,
     LinkedNodeKind.listLiteral,
     LinkedNodeKind.methodInvocation,
-    LinkedNodeKind.namedExpression,
     LinkedNodeKind.nullLiteral,
     LinkedNodeKind.parenthesizedExpression,
     LinkedNodeKind.prefixExpression,
@@ -1373,8 +1123,6 @@
     LinkedNodeKind.rethrowExpression,
     LinkedNodeKind.setOrMapLiteral,
     LinkedNodeKind.simpleIdentifier,
-    LinkedNodeKind.simpleStringLiteral,
-    LinkedNodeKind.stringInterpolation,
     LinkedNodeKind.superExpression,
     LinkedNodeKind.symbolLiteral,
     LinkedNodeKind.thisExpression,
@@ -1382,65 +1130,29 @@
   ])
   LinkedNodeType get expression_type;
 
-  @VariantId(15, variant: LinkedNodeKind.expressionFunctionBody)
-  int get expressionFunctionBody_arrow;
-
   @VariantId(6, variant: LinkedNodeKind.expressionFunctionBody)
   LinkedNode get expressionFunctionBody_expression;
 
-  @VariantId(16, variant: LinkedNodeKind.expressionFunctionBody)
-  int get expressionFunctionBody_keyword;
-
-  @VariantId(17, variant: LinkedNodeKind.expressionFunctionBody)
-  int get expressionFunctionBody_semicolon;
-
   @VariantId(6, variant: LinkedNodeKind.expressionStatement)
   LinkedNode get expressionStatement_expression;
 
-  @VariantId(15, variant: LinkedNodeKind.expressionStatement)
-  int get expressionStatement_semicolon;
-
-  @VariantId(15, variant: LinkedNodeKind.extendsClause)
-  int get extendsClause_extendsKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.extendsClause)
   LinkedNode get extendsClause_superclass;
 
-  @VariantId(15, variant: LinkedNodeKind.fieldDeclaration)
-  int get fieldDeclaration_covariantKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.fieldDeclaration)
   LinkedNode get fieldDeclaration_fields;
 
-  @VariantId(16, variant: LinkedNodeKind.fieldDeclaration)
-  int get fieldDeclaration_semicolon;
-
-  @VariantId(17, variant: LinkedNodeKind.fieldDeclaration)
-  int get fieldDeclaration_staticKeyword;
-
   @VariantId(8, variant: LinkedNodeKind.fieldFormalParameter)
   LinkedNode get fieldFormalParameter_formalParameters;
 
-  @VariantId(15, variant: LinkedNodeKind.fieldFormalParameter)
-  int get fieldFormalParameter_keyword;
-
-  @VariantId(16, variant: LinkedNodeKind.fieldFormalParameter)
-  int get fieldFormalParameter_period;
-
-  @VariantId(17, variant: LinkedNodeKind.fieldFormalParameter)
-  int get fieldFormalParameter_thisKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.fieldFormalParameter)
   LinkedNode get fieldFormalParameter_type;
 
   @VariantId(7, variant: LinkedNodeKind.fieldFormalParameter)
   LinkedNode get fieldFormalParameter_typeParameters;
 
-  @VariantId(15, variantList: [
-    LinkedNodeKind.forEachPartsWithDeclaration,
-    LinkedNodeKind.forEachPartsWithIdentifier,
-  ])
-  int get forEachParts_inKeyword;
+  @Id(18)
+  int get flags;
 
   @VariantId(6, variantList: [
     LinkedNodeKind.forEachPartsWithDeclaration,
@@ -1457,76 +1169,21 @@
   @VariantId(7, variant: LinkedNodeKind.forElement)
   LinkedNode get forElement_body;
 
-  @VariantId(26, variantList: [
-    LinkedNodeKind.fieldFormalParameter,
-    LinkedNodeKind.functionTypedFormalParameter,
-    LinkedNodeKind.simpleFormalParameter,
-  ])
-  LinkedNodeFormalParameterKind get formalParameter_kind;
-
-  @VariantId(15, variant: LinkedNodeKind.formalParameterList)
-  int get formalParameterList_leftDelimiter;
-
-  @VariantId(16, variant: LinkedNodeKind.formalParameterList)
-  int get formalParameterList_leftParenthesis;
-
   @VariantId(2, variant: LinkedNodeKind.formalParameterList)
   List<LinkedNode> get formalParameterList_parameters;
 
-  @VariantId(17, variant: LinkedNodeKind.formalParameterList)
-  int get formalParameterList_rightDelimiter;
-
-  @VariantId(18, variant: LinkedNodeKind.formalParameterList)
-  int get formalParameterList_rightParenthesis;
-
-  @VariantId(15, variantList: [
-    LinkedNodeKind.forElement,
-    LinkedNodeKind.forStatement,
-  ])
-  int get forMixin_awaitKeyword;
-
-  @VariantId(16, variantList: [
-    LinkedNodeKind.forElement,
-    LinkedNodeKind.forStatement,
-  ])
-  int get forMixin_forKeyword;
-
   @VariantId(6, variantList: [
     LinkedNodeKind.forElement,
     LinkedNodeKind.forStatement,
   ])
   LinkedNode get forMixin_forLoopParts;
 
-  @VariantId(17, variantList: [
-    LinkedNodeKind.forElement,
-    LinkedNodeKind.forStatement,
-  ])
-  int get forMixin_leftParenthesis;
-
-  @VariantId(19, variantList: [
-    LinkedNodeKind.forElement,
-    LinkedNodeKind.forStatement,
-  ])
-  int get forMixin_rightParenthesis;
-
   @VariantId(6, variantList: [
     LinkedNodeKind.forPartsWithDeclarations,
     LinkedNodeKind.forPartsWithExpression,
   ])
   LinkedNode get forParts_condition;
 
-  @VariantId(15, variantList: [
-    LinkedNodeKind.forPartsWithDeclarations,
-    LinkedNodeKind.forPartsWithExpression,
-  ])
-  int get forParts_leftSeparator;
-
-  @VariantId(16, variantList: [
-    LinkedNodeKind.forPartsWithDeclarations,
-    LinkedNodeKind.forPartsWithExpression,
-  ])
-  int get forParts_rightSeparator;
-
   @VariantId(5, variantList: [
     LinkedNodeKind.forPartsWithDeclarations,
     LinkedNodeKind.forPartsWithExpression,
@@ -1542,15 +1199,9 @@
   @VariantId(7, variant: LinkedNodeKind.forStatement)
   LinkedNode get forStatement_body;
 
-  @VariantId(15, variant: LinkedNodeKind.functionDeclaration)
-  int get functionDeclaration_externalKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.functionDeclaration)
   LinkedNode get functionDeclaration_functionExpression;
 
-  @VariantId(16, variant: LinkedNodeKind.functionDeclaration)
-  int get functionDeclaration_propertyKeyword;
-
   @VariantId(7, variant: LinkedNodeKind.functionDeclaration)
   LinkedNode get functionDeclaration_returnType;
 
@@ -1590,11 +1241,8 @@
   @VariantId(8, variant: LinkedNodeKind.genericFunctionType)
   LinkedNode get genericFunctionType_formalParameters;
 
-  @VariantId(15, variant: LinkedNodeKind.genericFunctionType)
-  int get genericFunctionType_functionKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.genericFunctionType)
-  int get genericFunctionType_question;
+  @VariantId(17, variant: LinkedNodeKind.genericFunctionType)
+  int get genericFunctionType_id;
 
   @VariantId(7, variant: LinkedNodeKind.genericFunctionType)
   LinkedNode get genericFunctionType_returnType;
@@ -1605,18 +1253,12 @@
   @VariantId(6, variant: LinkedNodeKind.genericFunctionType)
   LinkedNode get genericFunctionType_typeParameters;
 
-  @VariantId(16, variant: LinkedNodeKind.genericTypeAlias)
-  int get genericTypeAlias_equals;
-
   @VariantId(7, variant: LinkedNodeKind.genericTypeAlias)
   LinkedNode get genericTypeAlias_functionType;
 
   @VariantId(6, variant: LinkedNodeKind.genericTypeAlias)
   LinkedNode get genericTypeAlias_typeParameters;
 
-  @VariantId(2, variant: LinkedNodeKind.hideCombinator)
-  List<LinkedNode> get hideCombinator_hiddenNames;
-
   @VariantId(9, variant: LinkedNodeKind.ifElement)
   LinkedNode get ifElement_elseElement;
 
@@ -1629,50 +1271,20 @@
   ])
   LinkedNode get ifMixin_condition;
 
-  @VariantId(15, variantList: [
-    LinkedNodeKind.ifElement,
-    LinkedNodeKind.ifStatement,
-  ])
-  int get ifMixin_elseKeyword;
-
-  @VariantId(16, variantList: [
-    LinkedNodeKind.ifElement,
-    LinkedNodeKind.ifStatement,
-  ])
-  int get ifMixin_ifKeyword;
-
-  @VariantId(17, variantList: [
-    LinkedNodeKind.ifElement,
-    LinkedNodeKind.ifStatement,
-  ])
-  int get ifMixin_leftParenthesis;
-
-  @VariantId(18, variantList: [
-    LinkedNodeKind.ifElement,
-    LinkedNodeKind.ifStatement,
-  ])
-  int get ifMixin_rightParenthesis;
-
   @VariantId(7, variant: LinkedNodeKind.ifStatement)
   LinkedNode get ifStatement_elseStatement;
 
   @VariantId(8, variant: LinkedNodeKind.ifStatement)
   LinkedNode get ifStatement_thenStatement;
 
-  @VariantId(15, variant: LinkedNodeKind.implementsClause)
-  int get implementsClause_implementsKeyword;
-
   @VariantId(2, variant: LinkedNodeKind.implementsClause)
   List<LinkedNode> get implementsClause_interfaces;
 
+  @VariantId(1, variant: LinkedNodeKind.importDirective)
+  String get importDirective_prefix;
+
   @VariantId(15, variant: LinkedNodeKind.importDirective)
-  int get importDirective_asKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.importDirective)
-  int get importDirective_deferredKeyword;
-
-  @VariantId(6, variant: LinkedNodeKind.importDirective)
-  LinkedNode get importDirective_prefix;
+  int get importDirective_prefixOffset;
 
   @VariantId(15, variant: LinkedNodeKind.indexExpression)
   int get indexExpression_element;
@@ -1683,48 +1295,63 @@
   @VariantId(6, variant: LinkedNodeKind.indexExpression)
   LinkedNode get indexExpression_index;
 
-  @VariantId(17, variant: LinkedNodeKind.indexExpression)
-  int get indexExpression_leftBracket;
-
-  @VariantId(16, variant: LinkedNodeKind.indexExpression)
-  int get indexExpression_period;
-
-  @VariantId(18, variant: LinkedNodeKind.indexExpression)
-  int get indexExpression_rightBracket;
-
   @VariantId(7, variant: LinkedNodeKind.indexExpression)
   LinkedNode get indexExpression_target;
 
-  @VariantId(6, variant: LinkedNodeKind.instanceCreationExpression)
-  LinkedNode get instanceCreationExpression_arguments;
+  @VariantId(36, variantList: [
+    LinkedNodeKind.classDeclaration,
+    LinkedNodeKind.classTypeAlias,
+    LinkedNodeKind.compilationUnit,
+    LinkedNodeKind.compilationUnit,
+    LinkedNodeKind.constructorDeclaration,
+    LinkedNodeKind.defaultFormalParameter,
+    LinkedNodeKind.enumConstantDeclaration,
+    LinkedNodeKind.enumDeclaration,
+    LinkedNodeKind.exportDirective,
+    LinkedNodeKind.fieldDeclaration,
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionDeclaration,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.functionTypeAlias,
+    LinkedNodeKind.genericTypeAlias,
+    LinkedNodeKind.importDirective,
+    LinkedNodeKind.libraryDirective,
+    LinkedNodeKind.methodDeclaration,
+    LinkedNodeKind.mixinDeclaration,
+    LinkedNodeKind.partDirective,
+    LinkedNodeKind.partOfDirective,
+    LinkedNodeKind.simpleFormalParameter,
+    LinkedNodeKind.topLevelVariableDeclaration,
+    LinkedNodeKind.typeParameter,
+    LinkedNodeKind.variableDeclaration,
+    LinkedNodeKind.variableDeclarationList,
+  ])
+  @informative
+  int get informativeId;
+
+  @VariantId(27, variantList: [
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.simpleFormalParameter,
+    LinkedNodeKind.variableDeclaration,
+  ])
+  bool get inheritsCovariant;
+
+  @VariantId(2, variant: LinkedNodeKind.instanceCreationExpression)
+  List<LinkedNode> get instanceCreationExpression_arguments;
 
   @VariantId(7, variant: LinkedNodeKind.instanceCreationExpression)
   LinkedNode get instanceCreationExpression_constructorName;
 
-  @VariantId(15, variant: LinkedNodeKind.instanceCreationExpression)
-  int get instanceCreationExpression_keyword;
-
   @VariantId(8, variant: LinkedNodeKind.instanceCreationExpression)
   LinkedNode get instanceCreationExpression_typeArguments;
 
-  @VariantId(15, variant: LinkedNodeKind.integerLiteral)
-  int get integerLiteral_literal;
-
   @VariantId(16, variant: LinkedNodeKind.integerLiteral)
   int get integerLiteral_value;
 
   @VariantId(6, variant: LinkedNodeKind.interpolationExpression)
   LinkedNode get interpolationExpression_expression;
 
-  @VariantId(15, variant: LinkedNodeKind.interpolationExpression)
-  int get interpolationExpression_leftBracket;
-
-  @VariantId(16, variant: LinkedNodeKind.interpolationExpression)
-  int get interpolationExpression_rightBracket;
-
-  @VariantId(15, variant: LinkedNodeKind.interpolationString)
-  int get interpolationString_token;
-
   @VariantId(30, variant: LinkedNodeKind.interpolationString)
   String get interpolationString_value;
 
@@ -1749,24 +1376,12 @@
   @VariantId(6, variant: LinkedNodeKind.isExpression)
   LinkedNode get isExpression_expression;
 
-  @VariantId(15, variant: LinkedNodeKind.isExpression)
-  int get isExpression_isOperator;
-
-  @VariantId(16, variant: LinkedNodeKind.isExpression)
-  int get isExpression_notOperator;
-
   @VariantId(7, variant: LinkedNodeKind.isExpression)
   LinkedNode get isExpression_type;
 
-  @Id(1)
-  bool get isSynthetic;
-
   @Id(0)
   LinkedNodeKind get kind;
 
-  @VariantId(15, variant: LinkedNodeKind.label)
-  int get label_colon;
-
   @VariantId(6, variant: LinkedNodeKind.label)
   LinkedNode get label_label;
 
@@ -1782,48 +1397,21 @@
   @VariantId(2, variant: LinkedNodeKind.libraryIdentifier)
   List<LinkedNode> get libraryIdentifier_components;
 
-  @VariantId(2, variant: LinkedNodeKind.listLiteral)
+  @VariantId(3, variant: LinkedNodeKind.listLiteral)
   List<LinkedNode> get listLiteral_elements;
 
-  @VariantId(15, variant: LinkedNodeKind.listLiteral)
-  int get listLiteral_leftBracket;
-
-  @VariantId(16, variant: LinkedNodeKind.listLiteral)
-  int get listLiteral_rightBracket;
-
   @VariantId(6, variant: LinkedNodeKind.mapLiteralEntry)
   LinkedNode get mapLiteralEntry_key;
 
-  @VariantId(15, variant: LinkedNodeKind.mapLiteralEntry)
-  int get mapLiteralEntry_separator;
-
   @VariantId(7, variant: LinkedNodeKind.mapLiteralEntry)
   LinkedNode get mapLiteralEntry_value;
 
-  @VariantId(19, variant: LinkedNodeKind.methodDeclaration)
-  int get methodDeclaration_actualProperty;
-
   @VariantId(6, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_body;
 
-  @VariantId(15, variant: LinkedNodeKind.methodDeclaration)
-  int get methodDeclaration_externalKeyword;
-
   @VariantId(7, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_formalParameters;
 
-  @VariantId(16, variant: LinkedNodeKind.methodDeclaration)
-  int get methodDeclaration_modifierKeyword;
-
-  @VariantId(10, variant: LinkedNodeKind.methodDeclaration)
-  LinkedNode get methodDeclaration_name;
-
-  @VariantId(17, variant: LinkedNodeKind.methodDeclaration)
-  int get methodDeclaration_operatorKeyword;
-
-  @VariantId(18, variant: LinkedNodeKind.methodDeclaration)
-  int get methodDeclaration_propertyKeyword;
-
   @VariantId(8, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_returnType;
 
@@ -1833,28 +1421,17 @@
   @VariantId(6, variant: LinkedNodeKind.methodInvocation)
   LinkedNode get methodInvocation_methodName;
 
-  @VariantId(15, variant: LinkedNodeKind.methodInvocation)
-  int get methodInvocation_operator;
-
   @VariantId(7, variant: LinkedNodeKind.methodInvocation)
   LinkedNode get methodInvocation_target;
 
-  @VariantId(15, variant: LinkedNodeKind.mixinDeclaration)
-  int get mixinDeclaration_mixinKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.mixinDeclaration)
   LinkedNode get mixinDeclaration_onClause;
 
-  @VariantId(14, variantList: [
-    LinkedNodeKind.classDeclaration,
-    LinkedNodeKind.classTypeAlias,
-    LinkedNodeKind.enumDeclaration,
-    LinkedNodeKind.functionDeclaration,
-    LinkedNodeKind.functionTypeAlias,
-    LinkedNodeKind.genericTypeAlias,
-    LinkedNodeKind.mixinDeclaration,
-  ])
-  LinkedNode get namedCompilationUnitMember_name;
+  @VariantId(34, variant: LinkedNodeKind.mixinDeclaration)
+  List<String> get mixinDeclaration_superInvokedNames;
+
+  @Id(37)
+  String get name;
 
   @VariantId(6, variant: LinkedNodeKind.namedExpression)
   LinkedNode get namedExpression_expression;
@@ -1862,6 +1439,13 @@
   @VariantId(7, variant: LinkedNodeKind.namedExpression)
   LinkedNode get namedExpression_name;
 
+  @VariantId(34, variantList: [
+    LinkedNodeKind.hideCombinator,
+    LinkedNodeKind.showCombinator,
+    LinkedNodeKind.symbolLiteral,
+  ])
+  List<String> get names;
+
   @VariantId(2, variantList: [
     LinkedNodeKind.exportDirective,
     LinkedNodeKind.importDirective,
@@ -1883,46 +1467,9 @@
   @VariantId(6, variant: LinkedNodeKind.nativeClause)
   LinkedNode get nativeClause_name;
 
-  @VariantId(15, variant: LinkedNodeKind.nativeClause)
-  int get nativeClause_nativeKeyword;
-
-  @VariantId(15, variant: LinkedNodeKind.nativeFunctionBody)
-  int get nativeFunctionBody_nativeKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.nativeFunctionBody)
-  int get nativeFunctionBody_semicolon;
-
   @VariantId(6, variant: LinkedNodeKind.nativeFunctionBody)
   LinkedNode get nativeFunctionBody_stringLiteral;
 
-  @VariantId(14, variantList: [
-    LinkedNodeKind.fieldFormalParameter,
-    LinkedNodeKind.functionTypedFormalParameter,
-    LinkedNodeKind.simpleFormalParameter,
-  ])
-  LinkedNode get normalFormalParameter_comment;
-
-  @VariantId(19, variantList: [
-    LinkedNodeKind.fieldFormalParameter,
-    LinkedNodeKind.functionTypedFormalParameter,
-    LinkedNodeKind.simpleFormalParameter,
-  ])
-  int get normalFormalParameter_covariantKeyword;
-
-  @VariantId(12, variantList: [
-    LinkedNodeKind.fieldFormalParameter,
-    LinkedNodeKind.functionTypedFormalParameter,
-    LinkedNodeKind.simpleFormalParameter,
-  ])
-  LinkedNode get normalFormalParameter_identifier;
-
-  @VariantId(27, variantList: [
-    LinkedNodeKind.fieldFormalParameter,
-    LinkedNodeKind.functionTypedFormalParameter,
-    LinkedNodeKind.simpleFormalParameter,
-  ])
-  bool get normalFormalParameter_isCovariant;
-
   @VariantId(4, variantList: [
     LinkedNodeKind.fieldFormalParameter,
     LinkedNodeKind.functionTypedFormalParameter,
@@ -1931,10 +1478,7 @@
   List<LinkedNode> get normalFormalParameter_metadata;
 
   @VariantId(15, variant: LinkedNodeKind.nullLiteral)
-  int get nullLiteral_literal;
-
-  @VariantId(15, variant: LinkedNodeKind.onClause)
-  int get onClause_onKeyword;
+  int get nullLiteral_fake;
 
   @VariantId(2, variant: LinkedNodeKind.onClause)
   List<LinkedNode> get onClause_superclassConstraints;
@@ -1942,18 +1486,9 @@
   @VariantId(6, variant: LinkedNodeKind.parenthesizedExpression)
   LinkedNode get parenthesizedExpression_expression;
 
-  @VariantId(15, variant: LinkedNodeKind.parenthesizedExpression)
-  int get parenthesizedExpression_leftParenthesis;
-
-  @VariantId(16, variant: LinkedNodeKind.parenthesizedExpression)
-  int get parenthesizedExpression_rightParenthesis;
-
   @VariantId(6, variant: LinkedNodeKind.partOfDirective)
   LinkedNode get partOfDirective_libraryName;
 
-  @VariantId(16, variant: LinkedNodeKind.partOfDirective)
-  int get partOfDirective_ofKeyword;
-
   @VariantId(7, variant: LinkedNodeKind.partOfDirective)
   LinkedNode get partOfDirective_uri;
 
@@ -1966,15 +1501,12 @@
   @VariantId(6, variant: LinkedNodeKind.postfixExpression)
   LinkedNode get postfixExpression_operand;
 
-  @VariantId(16, variant: LinkedNodeKind.postfixExpression)
-  int get postfixExpression_operator;
+  @VariantId(28, variant: LinkedNodeKind.postfixExpression)
+  UnlinkedTokenType get postfixExpression_operator;
 
   @VariantId(6, variant: LinkedNodeKind.prefixedIdentifier)
   LinkedNode get prefixedIdentifier_identifier;
 
-  @VariantId(15, variant: LinkedNodeKind.prefixedIdentifier)
-  int get prefixedIdentifier_period;
-
   @VariantId(7, variant: LinkedNodeKind.prefixedIdentifier)
   LinkedNode get prefixedIdentifier_prefix;
 
@@ -1987,11 +1519,11 @@
   @VariantId(6, variant: LinkedNodeKind.prefixExpression)
   LinkedNode get prefixExpression_operand;
 
-  @VariantId(16, variant: LinkedNodeKind.prefixExpression)
-  int get prefixExpression_operator;
+  @VariantId(28, variant: LinkedNodeKind.prefixExpression)
+  UnlinkedTokenType get prefixExpression_operator;
 
-  @VariantId(15, variant: LinkedNodeKind.propertyAccess)
-  int get propertyAccess_operator;
+  @VariantId(28, variant: LinkedNodeKind.propertyAccess)
+  UnlinkedTokenType get propertyAccess_operator;
 
   @VariantId(6, variant: LinkedNodeKind.propertyAccess)
   LinkedNode get propertyAccess_propertyName;
@@ -2011,48 +1543,12 @@
   @VariantId(23, variant: LinkedNodeKind.redirectingConstructorInvocation)
   LinkedNodeType get redirectingConstructorInvocation_elementType;
 
-  @VariantId(16, variant: LinkedNodeKind.redirectingConstructorInvocation)
-  int get redirectingConstructorInvocation_period;
-
-  @VariantId(17, variant: LinkedNodeKind.redirectingConstructorInvocation)
-  int get redirectingConstructorInvocation_thisKeyword;
-
-  @VariantId(15, variant: LinkedNodeKind.rethrowExpression)
-  int get rethrowExpression_rethrowKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.returnStatement)
   LinkedNode get returnStatement_expression;
 
-  @VariantId(15, variant: LinkedNodeKind.returnStatement)
-  int get returnStatement_returnKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.returnStatement)
-  int get returnStatement_semicolon;
-
-  @VariantId(15, variant: LinkedNodeKind.scriptTag)
-  int get scriptTag_scriptTag;
-
-  @VariantId(2, variant: LinkedNodeKind.setOrMapLiteral)
+  @VariantId(3, variant: LinkedNodeKind.setOrMapLiteral)
   List<LinkedNode> get setOrMapLiteral_elements;
 
-  @VariantId(27, variant: LinkedNodeKind.setOrMapLiteral)
-  bool get setOrMapLiteral_isMap;
-
-  @VariantId(31, variant: LinkedNodeKind.setOrMapLiteral)
-  bool get setOrMapLiteral_isSet;
-
-  @VariantId(15, variant: LinkedNodeKind.setOrMapLiteral)
-  int get setOrMapLiteral_leftBracket;
-
-  @VariantId(16, variant: LinkedNodeKind.setOrMapLiteral)
-  int get setOrMapLiteral_rightBracket;
-
-  @VariantId(2, variant: LinkedNodeKind.showCombinator)
-  List<LinkedNode> get showCombinator_shownNames;
-
-  @VariantId(15, variant: LinkedNodeKind.simpleFormalParameter)
-  int get simpleFormalParameter_keyword;
-
   @VariantId(6, variant: LinkedNodeKind.simpleFormalParameter)
   LinkedNode get simpleFormalParameter_type;
 
@@ -2062,12 +1558,6 @@
   @VariantId(23, variant: LinkedNodeKind.simpleIdentifier)
   LinkedNodeType get simpleIdentifier_elementType;
 
-  @VariantId(16, variant: LinkedNodeKind.simpleIdentifier)
-  int get simpleIdentifier_token;
-
-  @VariantId(15, variant: LinkedNodeKind.simpleStringLiteral)
-  int get simpleStringLiteral_token;
-
   @VariantId(20, variant: LinkedNodeKind.simpleStringLiteral)
   String get simpleStringLiteral_value;
 
@@ -2083,8 +1573,8 @@
   @VariantId(6, variant: LinkedNodeKind.spreadElement)
   LinkedNode get spreadElement_expression;
 
-  @VariantId(15, variant: LinkedNodeKind.spreadElement)
-  int get spreadElement_spreadOperator;
+  @VariantId(35, variant: LinkedNodeKind.spreadElement)
+  UnlinkedTokenType get spreadElement_spreadOperator;
 
   @VariantId(2, variant: LinkedNodeKind.stringInterpolation)
   List<LinkedNode> get stringInterpolation_elements;
@@ -2101,30 +1591,9 @@
   @VariantId(23, variant: LinkedNodeKind.superConstructorInvocation)
   LinkedNodeType get superConstructorInvocation_elementType;
 
-  @VariantId(16, variant: LinkedNodeKind.superConstructorInvocation)
-  int get superConstructorInvocation_period;
-
-  @VariantId(17, variant: LinkedNodeKind.superConstructorInvocation)
-  int get superConstructorInvocation_superKeyword;
-
-  @VariantId(15, variant: LinkedNodeKind.superExpression)
-  int get superExpression_superKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.switchCase)
   LinkedNode get switchCase_expression;
 
-  @VariantId(16, variantList: [
-    LinkedNodeKind.switchCase,
-    LinkedNodeKind.switchDefault,
-  ])
-  int get switchMember_colon;
-
-  @VariantId(15, variantList: [
-    LinkedNodeKind.switchCase,
-    LinkedNodeKind.switchDefault,
-  ])
-  int get switchMember_keyword;
-
   @VariantId(3, variantList: [
     LinkedNodeKind.switchCase,
     LinkedNodeKind.switchDefault,
@@ -2140,41 +1609,17 @@
   @VariantId(7, variant: LinkedNodeKind.switchStatement)
   LinkedNode get switchStatement_expression;
 
-  @VariantId(18, variant: LinkedNodeKind.switchStatement)
-  int get switchStatement_leftBracket;
-
-  @VariantId(15, variant: LinkedNodeKind.switchStatement)
-  int get switchStatement_leftParenthesis;
-
   @VariantId(2, variant: LinkedNodeKind.switchStatement)
   List<LinkedNode> get switchStatement_members;
 
-  @VariantId(19, variant: LinkedNodeKind.switchStatement)
-  int get switchStatement_rightBracket;
-
-  @VariantId(16, variant: LinkedNodeKind.switchStatement)
-  int get switchStatement_rightParenthesis;
-
-  @VariantId(17, variant: LinkedNodeKind.switchStatement)
-  int get switchStatement_switchKeyword;
-
-  @VariantId(28, variant: LinkedNodeKind.symbolLiteral)
-  List<int> get symbolLiteral_components;
-
-  @VariantId(15, variant: LinkedNodeKind.symbolLiteral)
-  int get symbolLiteral_poundSign;
-
-  @VariantId(15, variant: LinkedNodeKind.thisExpression)
-  int get thisExpression_thisKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.throwExpression)
   LinkedNode get throwExpression_expression;
 
-  @VariantId(15, variant: LinkedNodeKind.throwExpression)
-  int get throwExpression_throwKeyword;
-
-  @VariantId(15, variant: LinkedNodeKind.topLevelVariableDeclaration)
-  int get topLevelVariableDeclaration_semicolon;
+  @VariantId(32, variantList: [
+    LinkedNodeKind.simpleFormalParameter,
+    LinkedNodeKind.variableDeclaration,
+  ])
+  TopLevelInferenceError get topLevelTypeInferenceError;
 
   @VariantId(6, variant: LinkedNodeKind.topLevelVariableDeclaration)
   LinkedNode get topLevelVariableDeclaration_variableList;
@@ -2188,80 +1633,44 @@
   @VariantId(7, variant: LinkedNodeKind.tryStatement)
   LinkedNode get tryStatement_finallyBlock;
 
-  @VariantId(15, variant: LinkedNodeKind.tryStatement)
-  int get tryStatement_finallyKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.tryStatement)
-  int get tryStatement_tryKeyword;
-
-  @VariantId(19, variantList: [
-    LinkedNodeKind.classTypeAlias,
+  @VariantId(27, variantList: [
     LinkedNodeKind.functionTypeAlias,
     LinkedNodeKind.genericTypeAlias,
   ])
-  int get typeAlias_semicolon;
-
-  @VariantId(18, variantList: [
-    LinkedNodeKind.classTypeAlias,
-    LinkedNodeKind.functionTypeAlias,
-    LinkedNodeKind.genericTypeAlias,
-  ])
-  int get typeAlias_typedefKeyword;
+  bool get typeAlias_hasSelfReference;
 
   @VariantId(2, variant: LinkedNodeKind.typeArgumentList)
   List<LinkedNode> get typeArgumentList_arguments;
 
-  @VariantId(15, variant: LinkedNodeKind.typeArgumentList)
-  int get typeArgumentList_leftBracket;
-
-  @VariantId(16, variant: LinkedNodeKind.typeArgumentList)
-  int get typeArgumentList_rightBracket;
-
-  @VariantId(19, variantList: [
+  @VariantId(2, variantList: [
     LinkedNodeKind.listLiteral,
     LinkedNodeKind.setOrMapLiteral,
   ])
-  int get typedLiteral_constKeyword;
-
-  @VariantId(14, variantList: [
-    LinkedNodeKind.listLiteral,
-    LinkedNodeKind.setOrMapLiteral,
-  ])
-  LinkedNode get typedLiteral_typeArguments;
+  List<LinkedNode> get typedLiteral_typeArguments;
 
   @VariantId(6, variant: LinkedNodeKind.typeName)
   LinkedNode get typeName_name;
 
-  @VariantId(15, variant: LinkedNodeKind.typeName)
-  int get typeName_question;
-
   @VariantId(23, variant: LinkedNodeKind.typeName)
   LinkedNodeType get typeName_type;
 
-  @VariantId(7, variant: LinkedNodeKind.typeName)
-  LinkedNode get typeName_typeArguments;
+  @VariantId(2, variant: LinkedNodeKind.typeName)
+  List<LinkedNode> get typeName_typeArguments;
 
   @VariantId(6, variant: LinkedNodeKind.typeParameter)
   LinkedNode get typeParameter_bound;
 
-  @VariantId(15, variant: LinkedNodeKind.typeParameter)
-  int get typeParameter_extendsKeyword;
-
-  @VariantId(16, variant: LinkedNodeKind.typeParameter)
-  int get typeParameter_id;
-
-  @VariantId(7, variant: LinkedNodeKind.typeParameter)
-  LinkedNode get typeParameter_name;
-
-  @VariantId(15, variant: LinkedNodeKind.typeParameterList)
-  int get typeParameterList_leftBracket;
-
-  @VariantId(16, variant: LinkedNodeKind.typeParameterList)
-  int get typeParameterList_rightBracket;
+  @VariantId(23, variant: LinkedNodeKind.typeParameter)
+  LinkedNodeType get typeParameter_defaultType;
 
   @VariantId(2, variant: LinkedNodeKind.typeParameterList)
   List<LinkedNode> get typeParameterList_typeParameters;
 
+  @VariantId(11, variantList: [
+    LinkedNodeKind.classDeclaration,
+  ])
+  LinkedNode get unused11;
+
   @VariantId(14, variantList: [
     LinkedNodeKind.exportDirective,
     LinkedNodeKind.importDirective,
@@ -2283,30 +1692,15 @@
   ])
   int get uriBasedDirective_uriElement;
 
-  @VariantId(32, variant: LinkedNodeKind.variableDeclaration)
-  LinkedNodeVariablesDeclaration get variableDeclaration_declaration;
-
-  @VariantId(15, variant: LinkedNodeKind.variableDeclaration)
-  int get variableDeclaration_equals;
-
   @VariantId(6, variant: LinkedNodeKind.variableDeclaration)
   LinkedNode get variableDeclaration_initializer;
 
-  @VariantId(7, variant: LinkedNodeKind.variableDeclaration)
-  LinkedNode get variableDeclaration_name;
-
-  @VariantId(15, variant: LinkedNodeKind.variableDeclarationList)
-  int get variableDeclarationList_keyword;
-
   @VariantId(6, variant: LinkedNodeKind.variableDeclarationList)
   LinkedNode get variableDeclarationList_type;
 
   @VariantId(2, variant: LinkedNodeKind.variableDeclarationList)
   List<LinkedNode> get variableDeclarationList_variables;
 
-  @VariantId(15, variant: LinkedNodeKind.variableDeclarationStatement)
-  int get variableDeclarationStatement_semicolon;
-
   @VariantId(6, variant: LinkedNodeKind.variableDeclarationStatement)
   LinkedNode get variableDeclarationStatement_variables;
 
@@ -2316,32 +1710,11 @@
   @VariantId(7, variant: LinkedNodeKind.whileStatement)
   LinkedNode get whileStatement_condition;
 
-  @VariantId(15, variant: LinkedNodeKind.whileStatement)
-  int get whileStatement_leftParenthesis;
-
-  @VariantId(16, variant: LinkedNodeKind.whileStatement)
-  int get whileStatement_rightParenthesis;
-
-  @VariantId(17, variant: LinkedNodeKind.whileStatement)
-  int get whileStatement_whileKeyword;
-
   @VariantId(2, variant: LinkedNodeKind.withClause)
   List<LinkedNode> get withClause_mixinTypes;
 
-  @VariantId(15, variant: LinkedNodeKind.withClause)
-  int get withClause_withKeyword;
-
   @VariantId(6, variant: LinkedNodeKind.yieldStatement)
   LinkedNode get yieldStatement_expression;
-
-  @VariantId(17, variant: LinkedNodeKind.yieldStatement)
-  int get yieldStatement_semicolon;
-
-  @VariantId(16, variant: LinkedNodeKind.yieldStatement)
-  int get yieldStatement_star;
-
-  @VariantId(15, variant: LinkedNodeKind.yieldStatement)
-  int get yieldStatement_yieldKeyword;
 }
 
 /// Information about a group of libraries linked together, for example because
@@ -2364,9 +1737,10 @@
 
 /// Kinds of formal parameters.
 enum LinkedNodeFormalParameterKind {
-  required,
+  requiredPositional,
   optionalPositional,
-  optionalNamed
+  optionalNamed,
+  requiredNamed
 }
 
 /// Kinds of [LinkedNode].
@@ -2389,6 +1763,7 @@
   classDeclaration,
   classTypeAlias,
   comment,
+  commentReference,
   compilationUnit,
   conditionalExpression,
   configuration,
@@ -2461,7 +1836,6 @@
   redirectingConstructorInvocation,
   rethrowExpression,
   returnStatement,
-  scriptTag,
   setOrMapLiteral,
   showCombinator,
   simpleFormalParameter,
@@ -2532,10 +1906,10 @@
   @Id(2)
   List<LinkedNodeTypeTypeParameter> get functionTypeParameters;
 
-  @Id(7)
+  @Id(8)
   int get genericTypeAliasReference;
 
-  @Id(8)
+  @Id(9)
   List<LinkedNodeType> get genericTypeAliasTypeArguments;
 
   /// Reference to a [LinkedNodeReferences].
@@ -2548,7 +1922,13 @@
   @Id(5)
   LinkedNodeTypeKind get kind;
 
+  @Id(10)
+  EntityRefNullabilitySuffix get nullabilitySuffix;
+
   @Id(6)
+  int get typeParameterElement;
+
+  @Id(7)
   int get typeParameterId;
 }
 
@@ -2585,6 +1965,12 @@
 
 /// Information about a single library in a [LinkedNodeLibrary].
 abstract class LinkedNodeUnit extends base.SummaryClass {
+  @Id(4)
+  bool get isNNBD;
+
+  @Id(3)
+  bool get isSynthetic;
+
   @Id(2)
   LinkedNode get node;
 
@@ -2595,25 +1981,6 @@
   String get uriStr;
 }
 
-/// Information about a top-level declaration, or a field declaration that
-/// contributes information to [LinkedNodeKind.variableDeclaration].
-abstract class LinkedNodeVariablesDeclaration extends base.SummaryClass {
-  @Id(0)
-  LinkedNode get comment;
-
-  @Id(1)
-  bool get isConst;
-
-  @Id(2)
-  bool get isCovariant;
-
-  @Id(3)
-  bool get isFinal;
-
-  @Id(4)
-  bool get isStatic;
-}
-
 /// Information about the resolution of an [UnlinkedReference].
 abstract class LinkedReference extends base.SummaryClass {
   /// If this [LinkedReference] doesn't have an associated [UnlinkedReference],
@@ -2722,6 +2089,10 @@
   @deprecated
   String get apiSignature;
 
+  /// The version 2 of the summary.
+  @Id(9)
+  LinkedNodeBundle get bundle2;
+
   /// Information about the packages this package depends on, if known.
   @Id(8)
   @informative
@@ -4154,6 +3525,108 @@
   int get uriOffset;
 }
 
+@Variant('kind')
+abstract class UnlinkedInformativeData extends base.SummaryClass {
+  @VariantId(2, variantList: [
+    LinkedNodeKind.classDeclaration,
+    LinkedNodeKind.classTypeAlias,
+    LinkedNodeKind.compilationUnit,
+    LinkedNodeKind.constructorDeclaration,
+    LinkedNodeKind.defaultFormalParameter,
+    LinkedNodeKind.enumDeclaration,
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionDeclaration,
+    LinkedNodeKind.functionTypeAlias,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.genericTypeAlias,
+    LinkedNodeKind.methodDeclaration,
+    LinkedNodeKind.mixinDeclaration,
+    LinkedNodeKind.simpleFormalParameter,
+    LinkedNodeKind.typeParameter,
+    LinkedNodeKind.variableDeclaration,
+  ])
+  int get codeLength;
+
+  @VariantId(3, variantList: [
+    LinkedNodeKind.classDeclaration,
+    LinkedNodeKind.classTypeAlias,
+    LinkedNodeKind.compilationUnit,
+    LinkedNodeKind.constructorDeclaration,
+    LinkedNodeKind.defaultFormalParameter,
+    LinkedNodeKind.enumDeclaration,
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionDeclaration,
+    LinkedNodeKind.functionTypeAlias,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.genericTypeAlias,
+    LinkedNodeKind.methodDeclaration,
+    LinkedNodeKind.mixinDeclaration,
+    LinkedNodeKind.simpleFormalParameter,
+    LinkedNodeKind.typeParameter,
+    LinkedNodeKind.variableDeclaration,
+  ])
+  int get codeOffset;
+
+  @VariantId(1, variantList: [
+    LinkedNodeKind.exportDirective,
+    LinkedNodeKind.importDirective,
+    LinkedNodeKind.libraryDirective,
+    LinkedNodeKind.partDirective,
+    LinkedNodeKind.partOfDirective,
+  ])
+  int get directiveKeywordOffset;
+
+  @VariantId(4, variantList: [
+    LinkedNodeKind.classDeclaration,
+    LinkedNodeKind.classTypeAlias,
+    LinkedNodeKind.constructorDeclaration,
+    LinkedNodeKind.enumDeclaration,
+    LinkedNodeKind.enumConstantDeclaration,
+    LinkedNodeKind.fieldDeclaration,
+    LinkedNodeKind.functionDeclaration,
+    LinkedNodeKind.functionTypeAlias,
+    LinkedNodeKind.genericTypeAlias,
+    LinkedNodeKind.libraryDirective,
+    LinkedNodeKind.methodDeclaration,
+    LinkedNodeKind.mixinDeclaration,
+    LinkedNodeKind.topLevelVariableDeclaration,
+  ])
+  List<String> get documentationComment_tokens;
+
+  /// The kind of the node.
+  @Id(0)
+  LinkedNodeKind get kind;
+
+  @VariantId(1, variantList: [
+    LinkedNodeKind.classDeclaration,
+    LinkedNodeKind.classTypeAlias,
+    LinkedNodeKind.constructorDeclaration,
+    LinkedNodeKind.enumConstantDeclaration,
+    LinkedNodeKind.enumDeclaration,
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionDeclaration,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.functionTypeAlias,
+    LinkedNodeKind.genericTypeAlias,
+    LinkedNodeKind.methodDeclaration,
+    LinkedNodeKind.mixinDeclaration,
+    LinkedNodeKind.simpleFormalParameter,
+    LinkedNodeKind.typeParameter,
+    LinkedNodeKind.variableDeclaration,
+  ])
+  int get nameOffset;
+
+  @VariantId(5, variant: LinkedNodeKind.constructorDeclaration)
+  int get constructorDeclaration_returnTypeOffset;
+
+  @VariantId(6, variant: LinkedNodeKind.constructorDeclaration)
+  int get constructorDeclaration_periodOffset;
+
+  /// Offsets of the first character of each line in the source code.
+  @VariantId(7, variant: LinkedNodeKind.compilationUnit)
+  List<int> get compilationUnit_lineStarts;
+}
+
 /// Unlinked summary information about a function parameter.
 abstract class UnlinkedParam extends base.SummaryClass {
   /// Annotations for this parameter.
@@ -4257,14 +3730,17 @@
 
 /// Enum used to indicate the kind of a parameter.
 enum UnlinkedParamKind {
-  /// Parameter is required.
-  required,
+  /// Parameter is required and positional.
+  requiredPositional,
 
-  /// Parameter is positional optional (enclosed in `[]`)
-  positional,
+  /// Parameter is optional and positional (enclosed in `[]`)
+  optionalPositional,
 
-  /// Parameter is named optional (enclosed in `{}`)
-  named
+  /// Parameter is optional and named (enclosed in `{}`)
+  optionalNamed,
+
+  /// Parameter is required and named (enclosed in `{}`).
+  requiredNamed
 }
 
 /// Unlinked summary information about a part declaration.
@@ -4419,6 +3895,7 @@
   BACKSLASH,
   BANG,
   BANG_EQ,
+  BANG_EQ_EQ,
   BAR,
   BAR_BAR,
   BAR_EQ,
@@ -4446,6 +3923,7 @@
   EOF,
   EQ,
   EQ_EQ,
+  EQ_EQ_EQ,
   EXPORT,
   EXTENDS,
   EXTERNAL,
@@ -4461,6 +3939,8 @@
   GT_EQ,
   GT_GT,
   GT_GT_EQ,
+  GT_GT_GT,
+  GT_GT_GT_EQ,
   HASH,
   HEXADECIMAL,
   HIDE,
@@ -4474,6 +3954,7 @@
   INT,
   INTERFACE,
   IS,
+  LATE,
   LIBRARY,
   LT,
   LT_EQ,
@@ -4508,6 +3989,7 @@
   QUESTION_PERIOD,
   QUESTION_QUESTION,
   QUESTION_QUESTION_EQ,
+  REQUIRED,
   RETHROW,
   RETURN,
   SCRIPT_TAG,
@@ -4670,6 +4152,10 @@
   @Id(5)
   List<UnlinkedImport> get imports;
 
+  /// Indicates whether this compilation unit is opted into NNBD.
+  @Id(21)
+  bool get isNNBD;
+
   /// Indicates whether the unit contains a "part of" declaration.
   @Id(18)
   bool get isPartOf;
@@ -4735,6 +4221,46 @@
   List<UnlinkedVariable> get variables;
 }
 
+/// Unlinked summary information about a compilation unit.
+@TopLevel('UUN2')
+abstract class UnlinkedUnit2 extends base.SummaryClass {
+  factory UnlinkedUnit2.fromBuffer(List<int> buffer) =>
+      generated.readUnlinkedUnit2(buffer);
+
+  /// The MD5 hash signature of the API portion of this unit. It depends on all
+  /// tokens that might affect APIs of declarations in the unit.
+  @Id(0)
+  List<int> get apiSignature;
+
+  /// URIs of `export` directives.
+  @Id(1)
+  List<String> get exports;
+
+  /// Is `true` if the unit contains a `library` directive.
+  @Id(6)
+  bool get hasLibraryDirective;
+
+  /// Is `true` if the unit contains a `part of` directive.
+  @Id(3)
+  bool get hasPartOfDirective;
+
+  /// URIs of `import` directives.
+  @Id(2)
+  List<String> get imports;
+
+  @Id(7)
+  List<UnlinkedInformativeData> get informativeData;
+
+  /// Offsets of the first character of each line in the source code.
+  @informative
+  @Id(5)
+  List<int> get lineStarts;
+
+  /// URIs of `part` directives.
+  @Id(4)
+  List<String> get parts;
+}
+
 /// Unlinked summary information about a top level variable, local variable, or
 /// a field.
 abstract class UnlinkedVariable extends base.SummaryClass {
@@ -4787,6 +4313,10 @@
   @Id(7)
   bool get isFinal;
 
+  /// Indicates whether the variable is declared using the `late` keyword.
+  @Id(16)
+  bool get isLate;
+
   /// Indicates whether the variable is declared using the `static` keyword.
   ///
   /// Note that for top level variables, this flag is false, since they are not
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 012a2ac..5bc3580 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -56,6 +56,7 @@
 /// - Where possible, we favor method dispatch instead of "is" and "as"
 ///   checks.  E.g. see [ReferenceableElementForLink.asConstructor].
 import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
@@ -186,7 +187,10 @@
     CompilationUnitElementInBuildUnit compilationUnit,
     TypeParameterSerializationContext typeParameterContext,
     {int slot}) {
-  EntityRefBuilder result = new EntityRefBuilder(slot: slot);
+  EntityRefBuilder result = new EntityRefBuilder(
+      slot: slot,
+      nullabilitySuffix:
+          encodeNullabilitySuffix((type as TypeImpl).nullabilitySuffix));
   if (type is InterfaceType) {
     ClassElementForLink element = type.element;
     result.reference = compilationUnit.addReference(element);
@@ -317,12 +321,14 @@
     TypeParameterSerializationContext typeParameterContext) {
   UnlinkedParamBuilder b = new UnlinkedParamBuilder();
   b.name = parameter.name;
-  if (parameter.isNotOptional) {
-    b.kind = UnlinkedParamKind.required;
+  if (parameter.isRequiredPositional) {
+    b.kind = UnlinkedParamKind.requiredPositional;
+  } else if (parameter.isRequiredNamed) {
+    b.kind = UnlinkedParamKind.requiredNamed;
   } else if (parameter.isOptionalPositional) {
-    b.kind = UnlinkedParamKind.positional;
-  } else if (parameter.isNamed) {
-    b.kind = UnlinkedParamKind.named;
+    b.kind = UnlinkedParamKind.optionalPositional;
+  } else if (parameter.isOptionalNamed) {
+    b.kind = UnlinkedParamKind.optionalNamed;
   }
   DartType type = parameter.type;
   if (!parameter.hasImplicitType) {
@@ -1410,11 +1416,12 @@
         return DynamicTypeImpl.instance;
       }
     }
+    DartType result;
     if (entity.paramReference != 0) {
-      return context.typeParameterContext
+      result = context.typeParameterContext
           .getTypeParameterType(entity.paramReference);
     } else if (entity.entityKind == EntityRefKind.genericFunctionType) {
-      return new GenericFunctionTypeElementForLink(
+      result = new GenericFunctionTypeElementForLink(
               this,
               context,
               entity.typeParameters,
@@ -1424,13 +1431,13 @@
     } else if (entity.syntheticReturnType != null) {
       FunctionElementImpl element =
           new FunctionElementForLink_Synthetic(this, context, entity);
-      return element.type;
+      result = element.type;
     } else if (entity.implicitFunctionTypeIndices.isNotEmpty) {
       DartType type = resolveRef(entity.reference).asStaticType;
       for (int index in entity.implicitFunctionTypeIndices) {
         type = (type as FunctionType).parameters[index].type;
       }
-      return type;
+      result = type;
     } else {
       ReferenceableElementForLink element = resolveRef(entity.reference);
       bool implicitTypeArgumentsInUse = false;
@@ -1449,13 +1456,14 @@
         }
       }
 
-      var type = element.buildType(
+      result = element.buildType(
           getTypeArgument, entity.implicitFunctionTypeIndices);
       if (implicitTypeArgumentsInUse) {
-        _typesWithImplicitArguments[type] = true;
+        _typesWithImplicitArguments[result] = true;
       }
-      return type;
     }
+    var nullabilitySuffix = decodeNullabilitySuffix(entity.nullabilitySuffix);
+    return (result as TypeImpl).withNullability(nullabilitySuffix);
   }
 
   @override
@@ -2455,19 +2463,25 @@
           new TypeParameterScope(nameScope, enclosingClass), enclosingClass);
     }
     var inheritance = new InheritanceManager2(linker.typeSystem);
+    // Note: this is a bit of a hack; we ought to use the feature set for the
+    // compilation unit being analyzed, but that's not feasible because sumaries
+    // don't record the feature set.  This should be resolved when we switch to
+    // the "summary2" mechanism.
+    var featureSet = FeatureSet.fromEnableFlags([]);
     var resolverVisitor = new ResolverVisitor(
         inheritance, library, source, typeProvider, errorListener,
+        featureSet: featureSet,
         nameScope: nameScope,
         propagateTypes: false,
         reportConstEvaluationErrors: false);
     var typeResolverVisitor = new TypeResolverVisitor(
         library, source, typeProvider, errorListener,
-        nameScope: nameScope);
+        featureSet: featureSet, nameScope: nameScope);
     var variableResolverVisitor = new VariableResolverVisitor(
         library, source, typeProvider, errorListener,
         nameScope: nameScope, localVariableInfo: LocalVariableInfo());
     var partialResolverVisitor = new PartialResolverVisitor(
-        inheritance, library, source, typeProvider, errorListener,
+        inheritance, library, source, typeProvider, errorListener, featureSet,
         nameScope: nameScope);
     return new ExprTypeComputer._(
         unit._unitResynthesizer,
@@ -2568,6 +2582,9 @@
             initializerForInference);
 
   @override
+  bool get isLate => unlinkedVariable.isLate;
+
+  @override
   bool get isStatic => unlinkedVariable.isStatic;
 
   @override
@@ -3588,6 +3605,9 @@
   }
 
   @override
+  bool get isNonNullableByDefault => _unlinkedDefiningUnit.isNNBD;
+
+  @override
   ContextForLink get context => _linker.context;
 
   @override
@@ -4290,10 +4310,14 @@
   bool get isInitializingFormal => unlinkedParam.isInitializingFormal;
 
   @override
-  bool get isNamed => parameterKind == ParameterKind.NAMED;
+  bool get isNamed =>
+      parameterKind == ParameterKind.NAMED ||
+      parameterKind == ParameterKind.NAMED_REQUIRED;
 
   @override
-  bool get isNotOptional => parameterKind == ParameterKind.REQUIRED;
+  bool get isNotOptional =>
+      parameterKind == ParameterKind.REQUIRED ||
+      parameterKind == ParameterKind.NAMED_REQUIRED;
 
   @override
   bool get isOptional =>
@@ -4301,6 +4325,9 @@
       parameterKind == ParameterKind.POSITIONAL;
 
   @override
+  bool get isOptionalNamed => parameterKind == ParameterKind.NAMED;
+
+  @override
   bool get isOptionalPositional => parameterKind == ParameterKind.POSITIONAL;
 
   @override
@@ -4309,16 +4336,27 @@
       parameterKind == ParameterKind.REQUIRED;
 
   @override
+  bool get isRequiredNamed => parameterKind == ParameterKind.NAMED_REQUIRED;
+
+  @override
+  bool get isRequiredPositional => parameterKind == ParameterKind.REQUIRED;
+
+  @override
+  get linkedNode => null;
+
+  @override
   String get name => unlinkedParam.name;
 
   @override
   ParameterKind get parameterKind {
     switch (unlinkedParam.kind) {
-      case UnlinkedParamKind.required:
+      case UnlinkedParamKind.requiredPositional:
         return ParameterKind.REQUIRED;
-      case UnlinkedParamKind.positional:
+      case UnlinkedParamKind.requiredNamed:
+        return ParameterKind.NAMED_REQUIRED;
+      case UnlinkedParamKind.optionalPositional:
         return ParameterKind.POSITIONAL;
-      case UnlinkedParamKind.named:
+      case UnlinkedParamKind.optionalNamed:
         return ParameterKind.NAMED;
     }
     return null;
@@ -4402,10 +4440,14 @@
   bool get isInitializingFormal => unlinkedParam.isInitializingFormal;
 
   @override
-  bool get isNamed => parameterKind == ParameterKind.NAMED;
+  bool get isNamed =>
+      parameterKind == ParameterKind.NAMED ||
+      parameterKind == ParameterKind.NAMED_REQUIRED;
 
   @override
-  bool get isNotOptional => parameterKind == ParameterKind.REQUIRED;
+  bool get isNotOptional =>
+      parameterKind == ParameterKind.REQUIRED ||
+      parameterKind == ParameterKind.NAMED_REQUIRED;
 
   @override
   bool get isOptional =>
@@ -4413,6 +4455,9 @@
       parameterKind == ParameterKind.POSITIONAL;
 
   @override
+  bool get isOptionalNamed => parameterKind == ParameterKind.NAMED;
+
+  @override
   bool get isOptionalPositional => parameterKind == ParameterKind.POSITIONAL;
 
   @override
@@ -4421,6 +4466,12 @@
       parameterKind == ParameterKind.REQUIRED;
 
   @override
+  bool get isRequiredNamed => parameterKind == ParameterKind.NAMED_REQUIRED;
+
+  @override
+  bool get isRequiredPositional => parameterKind == ParameterKind.REQUIRED;
+
+  @override
   bool get isSynthetic => true;
 
   @override
@@ -5347,7 +5398,6 @@
   InterfaceType _listType;
   InterfaceType _mapType;
   InterfaceType _mapObjectObjectType;
-  InterfaceType _neverType;
   InterfaceType _nullType;
   InterfaceType _numType;
   InterfaceType _objectType;
@@ -5432,8 +5482,7 @@
       _mapType ??= _buildInterfaceType(_linker.coreLibrary, 'Map');
 
   @override
-  InterfaceType get neverType =>
-      _neverType ??= _buildInterfaceType(_linker.coreLibrary, 'Never');
+  DartType get neverType => BottomTypeImpl.instance;
 
   @override
   DartObjectImpl get nullObject {
@@ -5481,9 +5530,6 @@
   InterfaceType get typeType =>
       _typeType ??= _buildInterfaceType(_linker.coreLibrary, 'Type');
 
-  @override
-  DartType get undefinedType => UndefinedTypeImpl.instance;
-
   InterfaceType _buildInterfaceType(
       LibraryElementForLink library, String name) {
     return library.getContainedName(name).buildType((int i) {
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 3c6b194..fbe8c41 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -31,6 +31,30 @@
  */
 final _typesWithImplicitTypeArguments = new Expando();
 
+NullabilitySuffix decodeNullabilitySuffix(EntityRefNullabilitySuffix suffix) {
+  switch (suffix) {
+    case EntityRefNullabilitySuffix.none:
+      return NullabilitySuffix.none;
+    case EntityRefNullabilitySuffix.question:
+      return NullabilitySuffix.question;
+    case EntityRefNullabilitySuffix.starOrIrrelevant:
+      return NullabilitySuffix.star;
+  }
+  throw new StateError('Unrecognized nullability suffix');
+}
+
+EntityRefNullabilitySuffix encodeNullabilitySuffix(NullabilitySuffix suffix) {
+  switch (suffix) {
+    case NullabilitySuffix.none:
+      return EntityRefNullabilitySuffix.none;
+    case NullabilitySuffix.question:
+      return EntityRefNullabilitySuffix.question;
+    case NullabilitySuffix.star:
+      return EntityRefNullabilitySuffix.starOrIrrelevant;
+  }
+  throw new StateError('Unrecognized nullability suffix');
+}
+
 /// An instance of [LibraryResynthesizer] is responsible for resynthesizing the
 /// elements in a single library from that library's summary.
 abstract class LibraryResynthesizer {
@@ -329,7 +353,7 @@
       Source librarySource = _getSource(uri);
       if (serializedLibrary == null) {
         LibraryElementImpl libraryElement =
-            new LibraryElementImpl(context, session, '', -1, 0);
+            new LibraryElementImpl(context, session, '', -1, 0, true);
         libraryElement.isSynthetic = true;
         CompilationUnitElementImpl unitElement =
             new CompilationUnitElementImpl();
@@ -1343,17 +1367,18 @@
         type = refinedType;
       }
     }
+    DartType result;
     if (type.paramReference != 0) {
-      return context.typeParameterContext
+      result = context.typeParameterContext
           .getTypeParameterType(type.paramReference);
     } else if (type.entityKind == EntityRefKind.genericFunctionType) {
       GenericFunctionTypeElement element =
           new GenericFunctionTypeElementImpl.forSerialized(context, type);
-      return element.type;
+      result = element.type;
     } else if (type.syntheticReturnType != null) {
       FunctionElementImpl element =
           new FunctionElementImpl_forLUB(context, type);
-      return element.type;
+      result = element.type;
     } else {
       DartType getTypeArgument(int i) {
         if (i < type.typeArguments.length) {
@@ -1369,12 +1394,14 @@
         return DynamicTypeImpl.instance;
       }
 
-      return referenceInfo.buildType(
+      result = referenceInfo.buildType(
           instantiateToBoundsAllowed,
           type.typeArguments.length,
           getTypeArgument,
           type.implicitFunctionTypeIndices);
     }
+    var nullabilitySuffix = decodeNullabilitySuffix(type.nullabilitySuffix);
+    return (result as TypeImpl).withNullability(nullabilitySuffix);
   }
 
   @override
@@ -1491,7 +1518,7 @@
       bool isDeclarableType = false;
       int numTypeParameters = linkedReference.numTypeParameters;
       if (linkedReference.kind == ReferenceKind.unresolved) {
-        type = UndefinedTypeImpl.instance;
+        type = DynamicTypeImpl.instance;
         element = null;
         isDeclarableType = true;
       } else if (name == 'dynamic') {
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index 895d564..3608b07 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -18,7 +19,8 @@
 /// bodies should be serialized to facilitate type inference.
 UnlinkedUnitBuilder serializeAstUnlinked(CompilationUnit compilationUnit,
     {bool serializeInferrableFields: true}) {
-  return new _SummarizeAstVisitor(serializeInferrableFields)
+  return new _SummarizeAstVisitor(serializeInferrableFields,
+          compilationUnit.featureSet.isEnabled(Feature.non_nullable))
       .serializeCompilationUnit(compilationUnit);
 }
 
@@ -44,6 +46,10 @@
         super(forConst);
 
   @override
+  EntityRefNullabilitySuffix computeNullabilitySuffix(Token question) =>
+      visitor.computeNullabilitySuffix(question);
+
+  @override
   bool isParameterName(String name) {
     return variableNames?.contains(name) ?? false;
   }
@@ -86,7 +92,8 @@
   @override
   EntityRefBuilder serializeConstructorRef(Identifier typeName,
       TypeArgumentList typeArguments, SimpleIdentifier name) {
-    EntityRefBuilder typeBuilder = serializeTypeName(typeName, typeArguments);
+    EntityRefBuilder typeBuilder = serializeTypeName(
+        typeName, typeArguments, EntityRefNullabilitySuffix.starOrIrrelevant);
     if (name == null) {
       return typeBuilder;
     } else {
@@ -114,7 +121,8 @@
       visitor.serializeGenericFunctionType(node);
 
   EntityRefBuilder serializeIdentifier(Identifier identifier) {
-    EntityRefBuilder b = new EntityRefBuilder();
+    EntityRefBuilder b =
+        new EntityRefBuilder(nullabilitySuffix: computeNullabilitySuffix(null));
     if (identifier is SimpleIdentifier) {
       int index = visitor.serializeSimpleReference(identifier.name);
       if (index < 0) {
@@ -160,8 +168,10 @@
 
   @override
   EntityRefBuilder serializeTypeName(
-      Identifier name, TypeArgumentList arguments) {
-    return visitor.serializeTypeName(name, arguments);
+      Identifier name,
+      TypeArgumentList arguments,
+      EntityRefNullabilitySuffix nullabilitySuffix) {
+    return visitor.serializeTypeName(name, arguments, nullabilitySuffix);
   }
 }
 
@@ -216,6 +226,8 @@
   /// performed using the AST representation.
   final bool _serializeInferrableFields;
 
+  final bool _nnbd;
+
   /// List of objects which should be written to [UnlinkedUnit.classes].
   final List<UnlinkedClassBuilder> classes = <UnlinkedClassBuilder>[];
 
@@ -324,7 +336,7 @@
   /// covariance.
   bool _parametersMayInheritCovariance = false;
 
-  _SummarizeAstVisitor(this._serializeInferrableFields);
+  _SummarizeAstVisitor(this._serializeInferrableFields, this._nnbd);
 
   /// Create a slot id for storing a propagated or inferred type or const cycle
   /// info.
@@ -355,6 +367,12 @@
     return scope;
   }
 
+  EntityRefNullabilitySuffix computeNullabilitySuffix(Token question) {
+    if (!_nnbd) return EntityRefNullabilitySuffix.starOrIrrelevant;
+    if (question != null) return EntityRefNullabilitySuffix.question;
+    return EntityRefNullabilitySuffix.none;
+  }
+
   /// Serialize the given list of [annotations].  If there are no annotations,
   /// the empty list is returned.
   List<UnlinkedExprBuilder> serializeAnnotations(
@@ -473,7 +491,8 @@
       unlinkedImports.add(new UnlinkedImportBuilder(isImplicit: true));
     }
     compilationUnit.declarations.accept(this);
-    UnlinkedUnitBuilder b = new UnlinkedUnitBuilder();
+    UnlinkedUnitBuilder b = new UnlinkedUnitBuilder(
+        isNNBD: compilationUnit.featureSet.isEnabled(Feature.non_nullable));
     b.lineStarts = compilationUnit.lineInfo?.lineStarts;
     b.isPartOf = isPartOf;
     b.libraryName = libraryName;
@@ -711,7 +730,8 @@
   EntityRefBuilder serializeGenericFunctionType(GenericFunctionType node) {
     _TypeParameterScope typeParameterScope = new _TypeParameterScope();
     scopes.add(typeParameterScope);
-    EntityRefBuilder b = new EntityRefBuilder();
+    EntityRefBuilder b = new EntityRefBuilder(
+        nullabilitySuffix: computeNullabilitySuffix(node?.question));
     b.entityKind = EntityRefKind.genericFunctionType;
     b.typeParameters =
         serializeTypeParameters(node.typeParameters, typeParameterScope);
@@ -826,12 +846,14 @@
     if (_parametersMayInheritCovariance) {
       b.inheritsCovariantSlot = assignSlot();
     }
-    if (node.isRequired) {
-      b.kind = UnlinkedParamKind.required;
+    if (node.isRequiredPositional) {
+      b.kind = UnlinkedParamKind.requiredPositional;
+    } else if (node.isRequiredNamed) {
+      b.kind = UnlinkedParamKind.requiredNamed;
     } else if (node.isOptionalPositional) {
-      b.kind = UnlinkedParamKind.positional;
-    } else if (node.isNamed) {
-      b.kind = UnlinkedParamKind.named;
+      b.kind = UnlinkedParamKind.optionalPositional;
+    } else if (node.isOptionalNamed) {
+      b.kind = UnlinkedParamKind.optionalNamed;
     } else {
       // ignore: deprecated_member_use_from_same_package
       throw new StateError('Unexpected parameter kind: ${node.kind}');
@@ -882,8 +904,10 @@
   /// a [EntityRef].  Note that this method does the right thing if the
   /// name doesn't refer to an entity other than a type (e.g. a class member).
   EntityRefBuilder serializeType(TypeAnnotation node) {
+    var nullabilitySuffix = computeNullabilitySuffix(node?.question);
     if (node is TypeName) {
-      return serializeTypeName(node?.name, node?.typeArguments);
+      return serializeTypeName(
+          node?.name, node?.typeArguments, nullabilitySuffix);
     } else if (node is GenericFunctionType) {
       return serializeGenericFunctionType(node);
     } else if (node != null) {
@@ -897,11 +921,14 @@
   /// a [EntityRef].  Note that this method does the right thing if the
   /// name doesn't refer to an entity other than a type (e.g. a class member).
   EntityRefBuilder serializeTypeName(
-      Identifier identifier, TypeArgumentList typeArguments) {
+      Identifier identifier,
+      TypeArgumentList typeArguments,
+      EntityRefNullabilitySuffix nullabilitySuffix) {
     if (identifier == null) {
       return null;
     } else {
-      EntityRefBuilder b = new EntityRefBuilder();
+      EntityRefBuilder b =
+          new EntityRefBuilder(nullabilitySuffix: nullabilitySuffix);
       if (identifier is SimpleIdentifier) {
         String name = identifier.name;
         int indexOffset = 0;
@@ -980,6 +1007,7 @@
       b.isConst = variables.isConst;
       b.isCovariant = isCovariant;
       b.isFinal = variables.isFinal;
+      b.isLate = variable.isLate;
       b.isStatic = isDeclaredStatic;
       b.name = variable.name.name;
       b.nameOffset = variable.name.offset;
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
index 79f9c9a..6a931fa 100644
--- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -194,7 +194,8 @@
   /// Return [EntityRefBuilder] that corresponds to the given [type].
   EntityRefBuilder serializeType(TypeAnnotation type) {
     if (type is TypeName) {
-      return serializeTypeName(type?.name, type?.typeArguments);
+      return serializeTypeName(type?.name, type?.typeArguments,
+          computeNullabilitySuffix(type.question));
     }
     if (type is GenericFunctionType) {
       return serializeGenericFunctionType(type);
@@ -205,8 +206,8 @@
 
   /// Return [EntityRefBuilder] that corresponds to the type with the given
   /// [name] and [arguments].
-  EntityRefBuilder serializeTypeName(
-      Identifier name, TypeArgumentList arguments);
+  EntityRefBuilder serializeTypeName(Identifier name,
+      TypeArgumentList arguments, EntityRefNullabilitySuffix nullabilitySuffix);
 
   /// Return the [UnlinkedExprBuilder] that corresponds to the state of this
   /// serializer.
@@ -802,4 +803,6 @@
       }
     }
   }
+
+  EntityRefNullabilitySuffix computeNullabilitySuffix(Token question);
 }
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index ba4cc40..08732d5 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -35,6 +35,8 @@
   final Map<String, UnlinkedUnitBuilder> _unlinkedUnitMap =
       <String, UnlinkedUnitBuilder>{};
 
+  LinkedNodeBundleBuilder _bundle2;
+
   void addLinkedLibrary(String uri, LinkedLibraryBuilder library) {
     _linkedLibraries.add(library);
     _linkedLibraryUris.add(uri);
@@ -60,6 +62,14 @@
         unlinkedUnitUris: _unlinkedUnitUris,
         unlinkedUnits: _unlinkedUnits,
         majorVersion: currentMajorVersion,
-        minorVersion: currentMinorVersion);
+        minorVersion: currentMinorVersion,
+        bundle2: _bundle2);
+  }
+
+  void setBundle2(LinkedNodeBundleBuilder bundle2) {
+    if (this._bundle2 != null) {
+      throw StateError('Bundle2 may be set only once.');
+    }
+    _bundle2 = bundle2;
   }
 }
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index f774d2a..cf9c22f 100644
--- a/pkg/analyzer/lib/src/summary/summary_file_builder.dart
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -5,6 +5,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
@@ -22,6 +23,9 @@
 import 'package:analyzer/src/summary/link.dart';
 import 'package:analyzer/src/summary/summarize_ast.dart';
 import 'package:analyzer/src/summary/summarize_elements.dart';
+import 'package:analyzer/src/summary2/link.dart' as summary2;
+import 'package:analyzer/src/summary2/linked_element_factory.dart' as summary2;
+import 'package:analyzer/src/summary2/reference.dart' as summary2;
 
 class SummaryBuilder {
   final Iterable<Source> librarySources;
@@ -72,6 +76,7 @@
 
   final Set<String> libraryUris = new Set<String>();
   final Map<String, UnlinkedUnit> unlinkedMap = <String, UnlinkedUnit>{};
+  final List<summary2.LinkInputLibrary> inputLibraries = [];
 
   final PackageBundleAssembler bundleAssembler = new PackageBundleAssembler();
 
@@ -94,6 +99,8 @@
     }, DeclaredVariables(), context.analysisOptions);
     map.forEach(bundleAssembler.addLinkedLibrary);
 
+    _link2();
+
     return bundleAssembler.assemble().toBuffer();
   }
 
@@ -102,8 +109,16 @@
     if (!libraryUris.add(uriStr)) {
       return;
     }
-    CompilationUnit unit = _addUnlinked(source);
-    for (Directive directive in unit.directives) {
+
+    var inputUnits = <summary2.LinkInputUnit>[];
+
+    CompilationUnit definingUnit = _parse(source);
+    _addUnlinked(source, definingUnit);
+    inputUnits.add(
+      summary2.LinkInputUnit(source, false, definingUnit),
+    );
+
+    for (Directive directive in definingUnit.directives) {
       if (directive is NamespaceDirective) {
         String libUri = directive.uri.stringValue;
         Source libSource = context.sourceFactory.resolveUri(source, libUri);
@@ -111,28 +126,49 @@
       } else if (directive is PartDirective) {
         String partUri = directive.uri.stringValue;
         Source partSource = context.sourceFactory.resolveUri(source, partUri);
-        _addUnlinked(partSource);
+        CompilationUnit partUnit = _parse(partSource);
+        _addUnlinked(partSource, partUnit);
+        inputUnits.add(
+          summary2.LinkInputUnit(partSource, false, partUnit),
+        );
       }
     }
+
+    inputLibraries.add(
+      summary2.LinkInputLibrary(source, inputUnits),
+    );
   }
 
-  CompilationUnit _addUnlinked(Source source) {
+  void _addUnlinked(Source source, CompilationUnit unit) {
     String uriStr = source.uri.toString();
-    CompilationUnit unit = _parse(source);
     UnlinkedUnitBuilder unlinked = serializeAstUnlinked(unit);
     unlinkedMap[uriStr] = unlinked;
     bundleAssembler.addUnlinkedUnit(source, unlinked);
-    return unit;
+  }
+
+  void _link2() {
+    var elementFactory = summary2.LinkedElementFactory(
+      context,
+      null,
+      summary2.Reference.root(),
+    );
+
+    var linkResult = summary2.link(elementFactory, inputLibraries);
+    bundleAssembler.setBundle2(linkResult.bundle);
   }
 
   CompilationUnit _parse(Source source) {
     AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER;
     String code = source.contents.data;
     CharSequenceReader reader = new CharSequenceReader(code);
-    Scanner scanner = new Scanner(source, reader, errorListener);
+    // TODO(paulberry): figure out the appropriate featureSet to use here
+    var featureSet = FeatureSet.fromEnableFlags([]);
+    Scanner scanner = new Scanner(source, reader, errorListener)
+      ..configureFeatures(featureSet);
     Token token = scanner.tokenize();
     LineInfo lineInfo = new LineInfo(scanner.lineStarts);
     Parser parser = new Parser(source, errorListener,
+        featureSet: featureSet,
         useFasta: context.analysisOptions.useFastaParser);
     parser.enableOptionalNewAndConst = true;
     CompilationUnit unit = parser.parseCompilationUnit(token);
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index f31b076..e54f587 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -128,7 +128,6 @@
   InterfaceType _listType;
   InterfaceType _mapType;
   InterfaceType _mapObjectObjectType;
-  InterfaceType _neverType;
   DartObjectImpl _nullObject;
   InterfaceType _nullType;
   InterfaceType _numType;
@@ -149,7 +148,7 @@
   }
 
   @override
-  DartType get bottomType => BottomTypeImpl.instance;
+  DartType get bottomType => BottomTypeImpl.instanceLegacy;
 
   @override
   InterfaceType get deprecatedType {
@@ -267,10 +266,7 @@
   }
 
   @override
-  InterfaceType get neverType {
-    assert(_coreLibrary != null);
-    return _neverType ??= _getType(_coreLibrary, 'Never');
-  }
+  DartType get neverType => BottomTypeImpl.instance;
 
   @override
   DartObjectImpl get nullObject {
@@ -349,9 +345,6 @@
     return _typeType;
   }
 
-  @override
-  DartType get undefinedType => UndefinedTypeImpl.instance;
-
   /**
    * Initialize the `dart:async` types provided by this type provider.
    */
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart b/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart
new file mode 100644
index 0000000..5f973e1
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart
@@ -0,0 +1,525 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+
+class AstBinaryFlags {
+  static final Map<Type, int> _typeBits = {};
+
+  static final _hasAwait = _checkBit(
+    0,
+    ForElement,
+    ForStatement,
+  );
+
+  static final _hasEqual = _checkBit(
+    0,
+    Configuration,
+  );
+
+  static final _hasInitializer = _checkBit(
+    0,
+    DefaultFormalParameter,
+    VariableDeclaration,
+  );
+
+  static final _hasNot = _checkBit(
+    0,
+    IsExpression,
+  );
+
+  static final _hasPeriod = _checkBit(
+    0,
+    IndexExpression,
+    MethodInvocation,
+  );
+
+  static final _hasPeriod2 = _checkBit(
+    1,
+    MethodInvocation,
+  );
+
+  static final _hasQuestion = _checkBit(
+    1,
+    GenericFunctionType,
+    TypeName,
+  );
+
+  static final _hasSeparatorColon = _checkBit(
+    0,
+    ConstructorDeclaration,
+  );
+
+  static final _hasSeparatorEquals = _checkBit(
+    2,
+    ConstructorDeclaration,
+  );
+
+  static final _hasThis = _checkBit(
+    0,
+    ConstructorFieldInitializer,
+    RedirectingConstructorInvocation,
+  );
+
+  static final _hasTypeArguments = _checkBit(
+    0,
+    TypedLiteral,
+    TypeName,
+  );
+
+  static final _isAbstract = _checkBit(
+    1,
+    ClassDeclaration,
+    ClassTypeAlias,
+    ConstructorDeclaration,
+    MethodDeclaration,
+  );
+
+  static final _isAsync = _checkBit(
+    2,
+    BlockFunctionBody,
+    EmptyFunctionBody,
+    FunctionExpression,
+    MethodDeclaration,
+  );
+
+  static final _isConst = _checkBit(
+    3,
+    ConstructorDeclaration,
+    DeclaredIdentifier,
+    InstanceCreationExpression,
+    NormalFormalParameter,
+    TypedLiteral,
+    VariableDeclarationList,
+  );
+
+  static final _isCovariant = _checkBit(
+    2,
+    FieldDeclaration,
+    NormalFormalParameter,
+  );
+
+  static final _isDeclaration = _checkBit(
+    0,
+    SimpleIdentifier,
+  );
+
+  static final _isDeferred = _checkBit(
+    0,
+    ImportDirective,
+  );
+
+  static final _isDelimiterCurly = _checkBit(
+    0,
+    FormalParameterList,
+  );
+
+  static final _isDelimiterSquare = _checkBit(
+    1,
+    FormalParameterList,
+  );
+
+  static final _isExternal = _checkBit(
+    7,
+    ConstructorDeclaration,
+    FunctionDeclaration,
+    MethodDeclaration,
+  );
+
+  static final _isFactory = _checkBit(
+    4,
+    ConstructorDeclaration,
+  );
+
+  static final _isFinal = _checkBit(
+    4,
+    DeclaredIdentifier,
+    NormalFormalParameter,
+    VariableDeclarationList,
+  );
+
+  static final _isGenerator = _checkBit(
+    3,
+    FunctionExpression,
+    MethodDeclaration,
+  );
+
+  static final _isGet = _checkBit(
+    4,
+    FunctionDeclaration,
+    MethodDeclaration,
+  );
+
+  static final _isLate = _checkBit(
+    0,
+    VariableDeclarationList,
+  );
+
+  static final _isMap = _checkBit(
+    1,
+    TypedLiteral,
+  );
+
+  static final _isNew = _checkBit(
+    0,
+    InstanceCreationExpression,
+  );
+
+  static final _isOperator = _checkBit(
+    0,
+    MethodDeclaration,
+  );
+
+  static final _isRequired = _checkBit(
+    0,
+    NormalFormalParameter,
+  );
+
+  static final _isSet = _checkBit(
+    5,
+    FunctionDeclaration,
+    MethodDeclaration,
+    TypedLiteral,
+  );
+
+  static final _isStar = _checkBit(
+    0,
+    BlockFunctionBody,
+    YieldStatement,
+  );
+
+  static final _isStatic = _checkBit(
+    6,
+    FieldDeclaration,
+    MethodDeclaration,
+  );
+
+  static final _isStringInterpolationIdentifier = _checkBit(
+    0,
+    InterpolationExpression,
+  );
+
+  static final _isSync = _checkBit(
+    3,
+    BlockFunctionBody,
+    ExpressionFunctionBody,
+  );
+
+  static final _isVar = _checkBit(
+    1,
+    DeclaredIdentifier,
+    NormalFormalParameter,
+    VariableDeclarationList,
+  );
+
+  static int encode({
+    bool hasAwait: false,
+    bool hasEqual: false,
+    bool hasInitializer: false,
+    bool hasNot: false,
+    bool hasPeriod: false,
+    bool hasPeriod2: false,
+    bool hasQuestion: false,
+    bool hasSeparatorColon: false,
+    bool hasSeparatorEquals: false,
+    bool hasThis: false,
+    bool hasTypeArguments: false,
+    bool isAbstract: false,
+    bool isAsync: false,
+    bool isConst: false,
+    bool isCovariant: false,
+    bool isDeclaration: false,
+    bool isDeferred: false,
+    bool isDelimiterCurly: false,
+    bool isDelimiterSquare: false,
+    bool isExternal: false,
+    bool isFactory: false,
+    bool isFinal: false,
+    bool isGenerator: false,
+    bool isGet: false,
+    bool isLate: false,
+    bool isMap: false,
+    bool isNew: false,
+    bool isOperator: false,
+    bool isRequired: false,
+    bool isSet: false,
+    bool isStar: false,
+    bool isStatic: false,
+    bool isStringInterpolationIdentifier: false,
+    bool isSync: false,
+    bool isVar: false,
+  }) {
+    var result = 0;
+    if (hasAwait) {
+      result |= _hasAwait;
+    }
+    if (hasEqual) {
+      result |= _hasEqual;
+    }
+    if (hasInitializer) {
+      result |= _hasInitializer;
+    }
+    if (hasNot) {
+      result |= _hasNot;
+    }
+    if (hasPeriod) {
+      result |= _hasPeriod;
+    }
+    if (hasPeriod2) {
+      result |= _hasPeriod2;
+    }
+    if (hasQuestion) {
+      result |= _hasQuestion;
+    }
+    if (hasSeparatorColon) {
+      result |= _hasSeparatorColon;
+    }
+    if (hasSeparatorEquals) {
+      result |= _hasSeparatorEquals;
+    }
+    if (hasThis) {
+      result |= _hasThis;
+    }
+    if (hasTypeArguments) {
+      result |= _hasTypeArguments;
+    }
+    if (isAbstract) {
+      result |= _isAbstract;
+    }
+    if (isAsync) {
+      result |= _isAsync;
+    }
+    if (isCovariant) {
+      result |= _isCovariant;
+    }
+    if (isDeclaration) {
+      result |= _isDeclaration;
+    }
+    if (isDeferred) {
+      result |= _isDeferred;
+    }
+    if (isDelimiterCurly) {
+      result |= _isDelimiterCurly;
+    }
+    if (isDelimiterSquare) {
+      result |= _isDelimiterSquare;
+    }
+    if (isConst) {
+      result |= _isConst;
+    }
+    if (isExternal) {
+      result |= _isExternal;
+    }
+    if (isFactory) {
+      result |= _isFactory;
+    }
+    if (isFinal) {
+      result |= _isFinal;
+    }
+    if (isGenerator) {
+      result |= _isGenerator;
+    }
+    if (isGet) {
+      result |= _isGet;
+    }
+    if (isLate) {
+      result |= _isLate;
+    }
+    if (isMap) {
+      result |= _isMap;
+    }
+    if (isNew) {
+      result |= _isNew;
+    }
+    if (isOperator) {
+      result |= _isOperator;
+    }
+    if (isRequired) {
+      result |= _isRequired;
+    }
+    if (isSet) {
+      result |= _isSet;
+    }
+    if (isStar) {
+      result |= _isStar;
+    }
+    if (isStatic) {
+      result |= _isStatic;
+    }
+    if (isStringInterpolationIdentifier) {
+      result |= _isStringInterpolationIdentifier;
+    }
+    if (isSync) {
+      result |= _isSync;
+    }
+    if (isVar) {
+      result |= _isVar;
+    }
+    return result;
+  }
+
+  static bool hasAwait(int flags) {
+    return (flags & _hasAwait) != 0;
+  }
+
+  static bool hasEqual(int flags) {
+    return (flags & _hasEqual) != 0;
+  }
+
+  static bool hasInitializer(int flags) {
+    return (flags & _hasInitializer) != 0;
+  }
+
+  static bool hasNot(int flags) {
+    return (flags & _hasNot) != 0;
+  }
+
+  static bool hasPeriod(int flags) {
+    return (flags & _hasPeriod) != 0;
+  }
+
+  static bool hasPeriod2(int flags) {
+    return (flags & _hasPeriod2) != 0;
+  }
+
+  static bool hasQuestion(int flags) {
+    return (flags & _isStringInterpolationIdentifier) != 0;
+  }
+
+  static bool hasSeparatorColon(int flags) {
+    return (flags & _hasSeparatorColon) != 0;
+  }
+
+  static bool hasSeparatorEquals(int flags) {
+    return (flags & _hasSeparatorEquals) != 0;
+  }
+
+  static bool hasThis(int flags) {
+    return (flags & _hasThis) != 0;
+  }
+
+  static bool hasTypeArguments(int flags) {
+    return (flags & _hasTypeArguments) != 0;
+  }
+
+  static bool isAbstract(int flags) {
+    return (flags & _isAbstract) != 0;
+  }
+
+  static bool isAsync(int flags) {
+    return (flags & _isAsync) != 0;
+  }
+
+  static bool isConst(int flags) {
+    return (flags & _isConst) != 0;
+  }
+
+  static bool isCovariant(int flags) {
+    return (flags & _isCovariant) != 0;
+  }
+
+  static bool isDeclaration(int flags) {
+    return (flags & _isDeclaration) != 0;
+  }
+
+  static bool isDeferred(int flags) {
+    return (flags & _isDeferred) != 0;
+  }
+
+  static bool isDelimiterCurly(int flags) {
+    return (flags & _isDelimiterCurly) != 0;
+  }
+
+  static bool isDelimiterSquare(int flags) {
+    return (flags & _isDelimiterSquare) != 0;
+  }
+
+  static bool isExternal(int flags) {
+    return (flags & _isExternal) != 0;
+  }
+
+  static bool isFactory(int flags) {
+    return (flags & _isFactory) != 0;
+  }
+
+  static bool isFinal(int flags) {
+    return (flags & _isFinal) != 0;
+  }
+
+  static bool isGenerator(int flags) {
+    return (flags & _isGenerator) != 0;
+  }
+
+  static bool isGet(int flags) {
+    return (flags & _isGet) != 0;
+  }
+
+  static bool isLate(int flags) {
+    return (flags & _isLate) != 0;
+  }
+
+  static bool isMap(int flags) {
+    return (flags & _isMap) != 0;
+  }
+
+  static bool isNew(int flags) {
+    return (flags & _isNew) != 0;
+  }
+
+  static bool isOperator(int flags) {
+    return (flags & _isOperator) != 0;
+  }
+
+  static bool isRequired(int flags) {
+    return (flags & _isRequired) != 0;
+  }
+
+  static bool isSet(int flags) {
+    return (flags & _isSet) != 0;
+  }
+
+  static bool isStar(int flags) {
+    return (flags & _isStar) != 0;
+  }
+
+  static bool isStatic(int flags) {
+    return (flags & _isStatic) != 0;
+  }
+
+  static bool isStringInterpolationIdentifier(int flags) {
+    return (flags & _isStringInterpolationIdentifier) != 0;
+  }
+
+  static bool isSync(int flags) {
+    return (flags & _isSync) != 0;
+  }
+
+  static bool isVar(int flags) {
+    return (flags & _isVar) != 0;
+  }
+
+  /// Check the bit for its uniqueness for the given types.
+  static int _checkBit(int shift, Type type1,
+      [Type type2, Type type3, Type type4, Type type5, Type type6]) {
+    _checkBit0(shift, type1);
+    _checkBit0(shift, type2);
+    _checkBit0(shift, type3);
+    _checkBit0(shift, type4);
+    _checkBit0(shift, type5);
+    _checkBit0(shift, type6);
+    return 1 << shift;
+  }
+
+  /// Check the bit for its uniqueness for the [type].
+  static void _checkBit0(int shift, Type type) {
+    if (type != null) {
+      var currentBits = _typeBits[type] ?? 0;
+      var bit = 1 << shift;
+      if ((currentBits & bit) != 0) {
+        throw StateError('1 << $shift is already used for $type');
+      }
+      _typeBits[type] = currentBits | bit;
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 15cab36..44b9e83 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -9,10 +9,22 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
+import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_flags.dart';
 import 'package:analyzer/src/summary2/lazy_ast.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/tokens_context.dart';
+
+var timerAstBinaryReader = Stopwatch();
+var timerAstBinaryReaderClass = Stopwatch();
+var timerAstBinaryReaderDirective = Stopwatch();
+var timerAstBinaryReaderFunctionBody = Stopwatch();
+var timerAstBinaryReaderFunctionDeclaration = Stopwatch();
+var timerAstBinaryReaderMixin = Stopwatch();
+var timerAstBinaryReaderTopLevelVar = Stopwatch();
 
 /// Deserializer of fully resolved ASTs from flat buffers.
 class AstBinaryReader {
@@ -21,23 +33,56 @@
   /// Set to `true` when this reader is used to lazily read its unit.
   bool isLazy = false;
 
+  /// Whether we are reading a directive.
+  ///
+  /// [StringLiteral]s in directives are not actual expressions, and don't need
+  /// a type. Moreover, when we are reading `dart:core` imports, the type
+  /// provider is not ready yet, so we cannot access type `String`.
+  bool _isReadingDirective = false;
+
   AstBinaryReader(this._unitContext);
 
+  InterfaceType get _boolType => _unitContext.typeProvider.boolType;
+
+  InterfaceType get _doubleType => _unitContext.typeProvider.doubleType;
+
+  InterfaceType get _intType => _unitContext.typeProvider.intType;
+
+  DartType get _nullType => _unitContext.typeProvider.nullType;
+
+  InterfaceType get _stringType => _unitContext.typeProvider.stringType;
+
   AstNode readNode(LinkedNode data) {
-    var node = _readNode(data);
-    if (node == null) return null;
-
-    if (!isLazy) {
-      _unitContext.tokensContext.linkTokens(node.beginToken, node.endToken);
+    timerAstBinaryReader.start();
+    try {
+      return _readNode(data);
+    } finally {
+      timerAstBinaryReader.stop();
     }
-
-    return node;
   }
 
   DartType readType(LinkedNodeType data) {
     return _readType(data);
   }
 
+  SimpleIdentifier _declaredIdentifier(LinkedNode data) {
+    var informativeData = _unitContext.getInformativeData(data);
+    var offset = informativeData?.nameOffset ?? 0;
+    return astFactory.simpleIdentifier(
+      TokenFactory.tokenFromString(data.name)..offset = offset,
+      isDeclaration: true,
+    );
+  }
+
+  Token _directiveKeyword(LinkedNode data, Keyword keyword, Token def) {
+    var informativeData = _unitContext.getInformativeData(data);
+    if (informativeData != null) {
+      return TokenFactory.tokenFromKeyword(keyword)
+        ..offset = informativeData.directiveKeywordOffset;
+    }
+    return def;
+  }
+
   Element _elementOfComponents(
     int rawElementIndex,
     LinkedNodeType definingTypeNode,
@@ -48,6 +93,10 @@
     var definingType = _readType(definingTypeNode);
     if (element is ConstructorElement) {
       return ConstructorMember.from(element, definingType);
+    } else if (element is MethodElement) {
+      return MethodMember.from(element, definingType);
+    } else if (element is PropertyAccessorElement) {
+      return PropertyAccessorMember.from(element, definingType);
     } else {
       throw UnimplementedError('(${element.runtimeType}) $element');
     }
@@ -58,78 +107,72 @@
     return bundleContext.elementOfIndex(index);
   }
 
-  Token _getToken(int index) {
-    return _unitContext.tokensContext.tokenOfIndex(index);
-  }
-
-  List<Token> _getTokens(List<int> indexList) {
-    var result = List<Token>(indexList.length);
-    for (var i = 0; i < indexList.length; ++i) {
-      var index = indexList[i];
-      result[i] = _getToken(index);
-    }
-    return result;
-  }
-
   AdjacentStrings _read_adjacentStrings(LinkedNode data) {
-    return astFactory.adjacentStrings(
+    var node = astFactory.adjacentStrings(
       _readNodeList(data.adjacentStrings_strings),
-    )..staticType = _readType(data.expression_type);
+    );
+    if (!_isReadingDirective) {
+      node.staticType = _stringType;
+    }
+    return node;
   }
 
   Annotation _read_annotation(LinkedNode data) {
     return astFactory.annotation(
-      _getToken(data.annotation_atSign),
+      _Tokens.AT,
       _readNode(data.annotation_name),
-      _getToken(data.annotation_period),
+      _Tokens.PERIOD,
       _readNode(data.annotation_constructorName),
       _readNode(data.annotation_arguments),
-    );
+    )..element = _elementOfComponents(
+        data.annotation_element,
+        data.annotation_elementType,
+      );
   }
 
   ArgumentList _read_argumentList(LinkedNode data) {
     return astFactory.argumentList(
-      _getToken(data.argumentList_leftParenthesis),
+      _Tokens.OPEN_PAREN,
       _readNodeList(data.argumentList_arguments),
-      _getToken(data.argumentList_rightParenthesis),
+      _Tokens.CLOSE_PAREN,
     );
   }
 
   AsExpression _read_asExpression(LinkedNode data) {
     return astFactory.asExpression(
       _readNode(data.asExpression_expression),
-      _getToken(data.asExpression_asOperator),
+      _Tokens.AS,
       _readNode(data.asExpression_type),
     )..staticType = _readType(data.expression_type);
   }
 
   AssertInitializer _read_assertInitializer(LinkedNode data) {
     return astFactory.assertInitializer(
-      _getToken(data.assertInitializer_assertKeyword),
-      _getToken(data.assertInitializer_leftParenthesis),
+      _Tokens.ASSERT,
+      _Tokens.OPEN_PAREN,
       _readNode(data.assertInitializer_condition),
-      _getToken(data.assertInitializer_comma),
+      _Tokens.COMMA,
       _readNode(data.assertInitializer_message),
-      _getToken(data.assertInitializer_rightParenthesis),
+      _Tokens.CLOSE_PAREN,
     );
   }
 
   AssertStatement _read_assertStatement(LinkedNode data) {
     return astFactory.assertStatement(
-      _getToken(data.assertStatement_assertKeyword),
-      _getToken(data.assertStatement_leftParenthesis),
+      _Tokens.AS,
+      _Tokens.OPEN_PAREN,
       _readNode(data.assertStatement_condition),
-      _getToken(data.assertStatement_comma),
+      _Tokens.COMMA,
       _readNode(data.assertStatement_message),
-      _getToken(data.assertStatement_rightParenthesis),
-      _getToken(data.assertStatement_semicolon),
+      _Tokens.CLOSE_PAREN,
+      _Tokens.SEMICOLON,
     );
   }
 
   AssignmentExpression _read_assignmentExpression(LinkedNode data) {
     return astFactory.assignmentExpression(
       _readNode(data.assignmentExpression_leftHandSide),
-      _getToken(data.assignmentExpression_operator),
+      _Tokens.fromType(data.assignmentExpression_operator),
       _readNode(data.assignmentExpression_rightHandSide),
     )
       ..staticElement = _elementOfComponents(
@@ -141,7 +184,7 @@
 
   AwaitExpression _read_awaitExpression(LinkedNode data) {
     return astFactory.awaitExpression(
-      _getToken(data.awaitExpression_awaitKeyword),
+      _Tokens.AWAIT,
       _readNode(data.awaitExpression_expression),
     )..staticType = _readType(data.expression_type);
   }
@@ -149,7 +192,7 @@
   BinaryExpression _read_binaryExpression(LinkedNode data) {
     return astFactory.binaryExpression(
       _readNode(data.binaryExpression_leftOperand),
-      _getToken(data.binaryExpression_operator),
+      _Tokens.fromType(data.binaryExpression_operator),
       _readNode(data.binaryExpression_rightOperand),
     )
       ..staticElement = _elementOfComponents(
@@ -161,32 +204,40 @@
 
   Block _read_block(LinkedNode data) {
     return astFactory.block(
-      _getToken(data.block_leftBracket),
+      _Tokens.OPEN_CURLY_BRACKET,
       _readNodeList(data.block_statements),
-      _getToken(data.block_rightBracket),
+      _Tokens.CLOSE_CURLY_BRACKET,
     );
   }
 
   BlockFunctionBody _read_blockFunctionBody(LinkedNode data) {
-    return astFactory.blockFunctionBody(
-      _getToken(data.blockFunctionBody_keyword),
-      _getToken(data.blockFunctionBody_star),
-      _readNode(data.blockFunctionBody_block),
-    );
+    timerAstBinaryReaderFunctionBody.start();
+    try {
+      return astFactory.blockFunctionBody(
+        _Tokens.choose(
+          AstBinaryFlags.isAsync(data.flags),
+          _Tokens.ASYNC,
+          AstBinaryFlags.isSync(data.flags),
+          _Tokens.SYNC,
+        ),
+        AstBinaryFlags.isStar(data.flags) ? _Tokens.STAR : null,
+        _readNode(data.blockFunctionBody_block),
+      );
+    } finally {
+      timerAstBinaryReaderFunctionBody.stop();
+    }
   }
 
   BooleanLiteral _read_booleanLiteral(LinkedNode data) {
-    return astFactory.booleanLiteral(
-      _getToken(data.booleanLiteral_literal),
-      data.booleanLiteral_value,
-    )..staticType = _readType(data.expression_type);
+    return AstTestFactory.booleanLiteral(data.booleanLiteral_value)
+      ..staticType = _boolType;
   }
 
   BreakStatement _read_breakStatement(LinkedNode data) {
     return astFactory.breakStatement(
-      _getToken(data.breakStatement_breakKeyword),
+      _Tokens.BREAK,
       _readNode(data.breakStatement_label),
-      _getToken(data.breakStatement_semicolon),
+      _Tokens.SEMICOLON,
     );
   }
 
@@ -198,59 +249,74 @@
   }
 
   CatchClause _read_catchClause(LinkedNode data) {
+    var exceptionType = _readNode(data.catchClause_exceptionType);
+    var exceptionParameter = _readNode(data.catchClause_exceptionParameter);
+    var stackTraceParameter = _readNode(data.catchClause_stackTraceParameter);
     return astFactory.catchClause(
-      _getToken(data.catchClause_onKeyword),
-      _readNode(data.catchClause_exceptionType),
-      _getToken(data.catchClause_catchKeyword),
-      _getToken(data.catchClause_leftParenthesis),
-      _readNode(data.catchClause_exceptionParameter),
-      _getToken(data.catchClause_comma),
-      _readNode(data.catchClause_stackTraceParameter),
-      _getToken(data.catchClause_rightParenthesis),
+      exceptionType != null ? _Tokens.ON : null,
+      exceptionType,
+      exceptionParameter != null ? _Tokens.CATCH : null,
+      exceptionParameter != null ? _Tokens.OPEN_PAREN : null,
+      exceptionParameter,
+      stackTraceParameter != null ? _Tokens.COMMA : null,
+      stackTraceParameter,
+      exceptionParameter != null ? _Tokens.CLOSE_PAREN : null,
       _readNode(data.catchClause_body),
     );
   }
 
   ClassDeclaration _read_classDeclaration(LinkedNode data) {
-    var node = astFactory.classDeclaration(
-      _readNodeLazy(data.annotatedNode_comment),
-      _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.classDeclaration_abstractKeyword),
-      _getToken(data.classDeclaration_classKeyword),
-      _readNode(data.namedCompilationUnitMember_name),
-      _readNode(data.classOrMixinDeclaration_typeParameters),
-      _readNodeLazy(data.classDeclaration_extendsClause),
-      _readNodeLazy(data.classDeclaration_withClause),
-      _readNodeLazy(data.classOrMixinDeclaration_implementsClause),
-      _getToken(data.classOrMixinDeclaration_leftBracket),
-      _readNodeListLazy(data.classOrMixinDeclaration_members),
-      _getToken(data.classOrMixinDeclaration_rightBracket),
-    );
-    node.nativeClause = _readNodeLazy(data.classDeclaration_nativeClause);
-    LazyClassDeclaration.setData(node, data);
-    return node;
+    timerAstBinaryReaderClass.start();
+    try {
+      var node = astFactory.classDeclaration(
+        _readDocumentationComment(data),
+        _readNodeListLazy(data.annotatedNode_metadata),
+        AstBinaryFlags.isAbstract(data.flags) ? _Tokens.ABSTRACT : null,
+        _Tokens.CLASS,
+        _declaredIdentifier(data),
+        _readNode(data.classOrMixinDeclaration_typeParameters),
+        _readNodeLazy(data.classDeclaration_extendsClause),
+        _readNodeLazy(data.classDeclaration_withClause),
+        _readNodeLazy(data.classOrMixinDeclaration_implementsClause),
+        _Tokens.OPEN_CURLY_BRACKET,
+        _readNodeListLazy(data.classOrMixinDeclaration_members),
+        _Tokens.CLOSE_CURLY_BRACKET,
+      );
+      node.nativeClause = _readNodeLazy(data.classDeclaration_nativeClause);
+      LazyClassDeclaration.setData(node, data);
+      return node;
+    } finally {
+      timerAstBinaryReaderClass.stop();
+    }
   }
 
   ClassTypeAlias _read_classTypeAlias(LinkedNode data) {
-    var node = astFactory.classTypeAlias(
-      _readNodeLazy(data.annotatedNode_comment),
-      _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.typeAlias_typedefKeyword),
-      _readNode(data.namedCompilationUnitMember_name),
-      _readNode(data.classTypeAlias_typeParameters),
-      _getToken(data.classTypeAlias_equals),
-      _getToken(data.classTypeAlias_abstractKeyword),
-      _readNodeLazy(data.classTypeAlias_superclass),
-      _readNodeLazy(data.classTypeAlias_withClause),
-      _readNodeLazy(data.classTypeAlias_implementsClause),
-      _getToken(data.typeAlias_semicolon),
-    );
-    LazyClassTypeAlias.setData(node, data);
-    return node;
+    timerAstBinaryReaderClass.start();
+    try {
+      var node = astFactory.classTypeAlias(
+        _readDocumentationComment(data),
+        _readNodeListLazy(data.annotatedNode_metadata),
+        _Tokens.CLASS,
+        _declaredIdentifier(data),
+        _readNode(data.classTypeAlias_typeParameters),
+        _Tokens.EQ,
+        AstBinaryFlags.isAbstract(data.flags) ? _Tokens.ABSTRACT : null,
+        _readNodeLazy(data.classTypeAlias_superclass),
+        _readNodeLazy(data.classTypeAlias_withClause),
+        _readNodeLazy(data.classTypeAlias_implementsClause),
+        _Tokens.SEMICOLON,
+      );
+      LazyClassTypeAlias.setData(node, data);
+      return node;
+    } finally {
+      timerAstBinaryReaderClass.stop();
+    }
   }
 
   Comment _read_comment(LinkedNode data) {
-    var tokens = _getTokens(data.comment_tokens);
+    var tokens = data.comment_tokens
+        .map((lexeme) => TokenFactory.tokenFromString(lexeme))
+        .toList();
     switch (data.comment_type) {
       case LinkedNodeCommentType.block:
         return astFactory.endOfLineComment(
@@ -259,7 +325,7 @@
       case LinkedNodeCommentType.documentation:
         return astFactory.documentationComment(
           tokens,
-          // TODO(scheglov) references
+          _readNodeList(data.comment_references),
         );
       case LinkedNodeCommentType.endOfLine:
         return astFactory.endOfLineComment(
@@ -270,50 +336,75 @@
     }
   }
 
-  CompilationUnit _read_compilationUnit(LinkedNode data) {
-    return astFactory.compilationUnit(
-      _getToken(data.compilationUnit_beginToken),
-      _readNode(data.compilationUnit_scriptTag),
-      _readNodeList(data.compilationUnit_directives),
-      _readNodeList(data.compilationUnit_declarations),
-      _getToken(data.compilationUnit_endToken),
+  CommentReference _read_commentReference(LinkedNode data) {
+    return astFactory.commentReference(
+      AstBinaryFlags.isNew(data.flags) ? _Tokens.NEW : null,
+      _readNode(data.commentReference_identifier),
     );
   }
 
+  CompilationUnit _read_compilationUnit(LinkedNode data) {
+    return astFactory.compilationUnit2(
+        beginToken: null,
+        scriptTag: _readNode(data.compilationUnit_scriptTag),
+        directives: _readNodeList(data.compilationUnit_directives),
+        declarations: _readNodeList(data.compilationUnit_declarations),
+        endToken: null,
+        featureSet: null);
+  }
+
   ConditionalExpression _read_conditionalExpression(LinkedNode data) {
     return astFactory.conditionalExpression(
       _readNode(data.conditionalExpression_condition),
-      _getToken(data.conditionalExpression_question),
+      _Tokens.QUESTION,
       _readNode(data.conditionalExpression_thenExpression),
-      _getToken(data.conditionalExpression_colon),
+      _Tokens.COLON,
       _readNode(data.conditionalExpression_elseExpression),
     )..staticType = _readType(data.expression_type);
   }
 
   Configuration _read_configuration(LinkedNode data) {
     return astFactory.configuration(
-      _getToken(data.configuration_ifKeyword),
-      _getToken(data.configuration_leftParenthesis),
+      _Tokens.IF,
+      _Tokens.OPEN_PAREN,
       _readNode(data.configuration_name),
-      _getToken(data.configuration_equalToken),
+      AstBinaryFlags.hasEqual(data.flags) ? _Tokens.EQ : null,
       _readNode(data.configuration_value),
-      _getToken(data.configuration_rightParenthesis),
+      _Tokens.CLOSE_PAREN,
       _readNode(data.configuration_uri),
     );
   }
 
   ConstructorDeclaration _read_constructorDeclaration(LinkedNode data) {
+    SimpleIdentifier returnType = _readNode(
+      data.constructorDeclaration_returnType,
+    );
+
+    var informativeData = _unitContext.getInformativeData(data);
+    returnType.token.offset =
+        informativeData?.constructorDeclaration_returnTypeOffset ?? 0;
+
     var node = astFactory.constructorDeclaration(
-      _readNodeLazy(data.annotatedNode_comment),
+      _readDocumentationComment(data),
       _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.constructorDeclaration_externalKeyword),
-      _getToken(data.constructorDeclaration_constKeyword),
-      _getToken(data.constructorDeclaration_factoryKeyword),
-      _readNode(data.constructorDeclaration_returnType),
-      _getToken(data.constructorDeclaration_period),
-      _readNode(data.constructorDeclaration_name),
+      AstBinaryFlags.isExternal(data.flags) ? _Tokens.EXTERNAL : null,
+      AstBinaryFlags.isConst(data.flags) ? _Tokens.CONST : null,
+      AstBinaryFlags.isFactory(data.flags) ? _Tokens.FACTORY : null,
+      returnType,
+      data.name.isNotEmpty
+          ? Token(
+              TokenType.PERIOD,
+              informativeData?.constructorDeclaration_periodOffset ?? 0,
+            )
+          : null,
+      data.name.isNotEmpty ? _declaredIdentifier(data) : null,
       _readNodeLazy(data.constructorDeclaration_parameters),
-      _getToken(data.constructorDeclaration_separator),
+      _Tokens.choose(
+        AstBinaryFlags.hasSeparatorColon(data.flags),
+        _Tokens.COLON,
+        AstBinaryFlags.hasSeparatorEquals(data.flags),
+        _Tokens.EQ,
+      ),
       _readNodeListLazy(data.constructorDeclaration_initializers),
       _readNodeLazy(data.constructorDeclaration_redirectedConstructor),
       _readNodeLazy(data.constructorDeclaration_body),
@@ -324,11 +415,12 @@
 
   ConstructorFieldInitializer _read_constructorFieldInitializer(
       LinkedNode data) {
+    var hasThis = AstBinaryFlags.hasThis(data.flags);
     return astFactory.constructorFieldInitializer(
-      _getToken(data.constructorFieldInitializer_thisKeyword),
-      _getToken(data.constructorFieldInitializer_period),
+      hasThis ? _Tokens.THIS : null,
+      hasThis ? _Tokens.PERIOD : null,
       _readNode(data.constructorFieldInitializer_fieldName),
-      _getToken(data.constructorFieldInitializer_equals),
+      _Tokens.EQ,
       _readNode(data.constructorFieldInitializer_expression),
     );
   }
@@ -336,7 +428,7 @@
   ConstructorName _read_constructorName(LinkedNode data) {
     return astFactory.constructorName(
       _readNode(data.constructorName_type),
-      _getToken(data.constructorName_period),
+      data.constructorName_name != null ? _Tokens.PERIOD : null,
       _readNode(data.constructorName_name),
     )..staticElement = _elementOfComponents(
         data.constructorName_element,
@@ -346,17 +438,24 @@
 
   ContinueStatement _read_continueStatement(LinkedNode data) {
     return astFactory.continueStatement(
-      _getToken(data.continueStatement_continueKeyword),
+      _Tokens.CONTINUE,
       _readNode(data.continueStatement_label),
-      _getToken(data.continueStatement_semicolon),
+      _Tokens.SEMICOLON,
     );
   }
 
   DeclaredIdentifier _read_declaredIdentifier(LinkedNode data) {
     return astFactory.declaredIdentifier(
-      _readNode(data.annotatedNode_comment),
+      _readDocumentationComment(data),
       _readNodeList(data.annotatedNode_metadata),
-      _getToken(data.declaredIdentifier_keyword),
+      _Tokens.choose(
+        AstBinaryFlags.isConst(data.flags),
+        _Tokens.CONST,
+        AstBinaryFlags.isFinal(data.flags),
+        _Tokens.FINAL,
+        AstBinaryFlags.isVar(data.flags),
+        _Tokens.VAR,
+      ),
       _readNode(data.declaredIdentifier_type),
       _readNode(data.declaredIdentifier_identifier),
     );
@@ -365,10 +464,8 @@
   DefaultFormalParameter _read_defaultFormalParameter(LinkedNode data) {
     var node = astFactory.defaultFormalParameter(
       _readNode(data.defaultFormalParameter_parameter),
-      data.defaultFormalParameter_isNamed
-          ? ParameterKind.NAMED
-          : ParameterKind.POSITIONAL,
-      _getToken(data.defaultFormalParameter_separator),
+      _toParameterKind(data.defaultFormalParameter_kind),
+      data.defaultFormalParameter_defaultValue != null ? _Tokens.COLON : null,
       _readNodeLazy(data.defaultFormalParameter_defaultValue),
     );
     LazyFormalParameter.setData(node, data);
@@ -377,13 +474,13 @@
 
   DoStatement _read_doStatement(LinkedNode data) {
     return astFactory.doStatement(
-      _getToken(data.doStatement_doKeyword),
+      _Tokens.DO,
       _readNode(data.doStatement_body),
-      _getToken(data.doStatement_whileKeyword),
-      _getToken(data.doStatement_leftParenthesis),
+      _Tokens.WHILE,
+      _Tokens.OPEN_PAREN,
       _readNode(data.doStatement_condition),
-      _getToken(data.doStatement_rightParenthesis),
-      _getToken(data.doStatement_semicolon),
+      _Tokens.CLOSE_PAREN,
+      _Tokens.SEMICOLON,
     );
   }
 
@@ -394,29 +491,27 @@
   }
 
   DoubleLiteral _read_doubleLiteral(LinkedNode data) {
-    return astFactory.doubleLiteral(
-      _getToken(data.doubleLiteral_literal),
-      data.doubleLiteral_value,
-    )..staticType = _readType(data.expression_type);
+    return AstTestFactory.doubleLiteral(data.doubleLiteral_value)
+      ..staticType = _doubleType;
   }
 
   EmptyFunctionBody _read_emptyFunctionBody(LinkedNode data) {
     return astFactory.emptyFunctionBody(
-      _getToken(data.emptyFunctionBody_semicolon),
+      _Tokens.SEMICOLON,
     );
   }
 
   EmptyStatement _read_emptyStatement(LinkedNode data) {
     return astFactory.emptyStatement(
-      _getToken(data.emptyStatement_semicolon),
+      _Tokens.SEMICOLON,
     );
   }
 
   EnumConstantDeclaration _read_enumConstantDeclaration(LinkedNode data) {
     var node = astFactory.enumConstantDeclaration(
-      _readNodeLazy(data.annotatedNode_comment),
+      _readDocumentationComment(data),
       _readNodeListLazy(data.annotatedNode_metadata),
-      _readNode(data.enumConstantDeclaration_name),
+      _declaredIdentifier(data),
     );
     LazyEnumConstantDeclaration.setData(node, data);
     return node;
@@ -424,63 +519,82 @@
 
   EnumDeclaration _read_enumDeclaration(LinkedNode data) {
     var node = astFactory.enumDeclaration(
-      _readNodeLazy(data.annotatedNode_comment),
+      _readDocumentationComment(data),
       _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.enumDeclaration_enumKeyword),
-      _readNode(data.namedCompilationUnitMember_name),
-      _getToken(data.enumDeclaration_leftBracket),
+      _Tokens.ENUM,
+      _declaredIdentifier(data),
+      _Tokens.OPEN_CURLY_BRACKET,
       _readNodeListLazy(data.enumDeclaration_constants),
-      _getToken(data.enumDeclaration_rightBracket),
+      _Tokens.CLOSE_CURLY_BRACKET,
     );
     LazyEnumDeclaration.setData(node, data);
     return node;
   }
 
   ExportDirective _read_exportDirective(LinkedNode data) {
-    var node = astFactory.exportDirective(
-      _readNode(data.annotatedNode_comment),
-      _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.directive_keyword),
-      _readNode(data.uriBasedDirective_uri),
-      _readNodeList(data.namespaceDirective_configurations),
-      _readNodeList(data.namespaceDirective_combinators),
-      _getToken(data.directive_semicolon),
-    );
-    LazyDirective.setData(node, data);
-    return node;
+    timerAstBinaryReaderDirective.start();
+    _isReadingDirective = true;
+    try {
+      var node = astFactory.exportDirective(
+        _readDocumentationComment(data),
+        _readNodeListLazy(data.annotatedNode_metadata),
+        _directiveKeyword(data, Keyword.EXPORT, _Tokens.EXPORT),
+        _readNode(data.uriBasedDirective_uri),
+        _readNodeList(data.namespaceDirective_configurations),
+        _readNodeList(data.namespaceDirective_combinators),
+        _Tokens.SEMICOLON,
+      );
+      LazyDirective.setData(node, data);
+      return node;
+    } finally {
+      _isReadingDirective = false;
+      timerAstBinaryReaderDirective.stop();
+    }
   }
 
   ExpressionFunctionBody _read_expressionFunctionBody(LinkedNode data) {
-    return astFactory.expressionFunctionBody(
-      _getToken(data.expressionFunctionBody_keyword),
-      _getToken(data.expressionFunctionBody_arrow),
-      _readNode(data.expressionFunctionBody_expression),
-      _getToken(data.expressionFunctionBody_semicolon),
-    );
+    timerAstBinaryReaderFunctionBody.start();
+    try {
+      return astFactory.expressionFunctionBody(
+        _Tokens.choose(
+          AstBinaryFlags.isAsync(data.flags),
+          _Tokens.ASYNC,
+          AstBinaryFlags.isSync(data.flags),
+          _Tokens.SYNC,
+        ),
+        _Tokens.ARROW,
+        _readNode(data.expressionFunctionBody_expression),
+        _Tokens.SEMICOLON,
+      );
+    } finally {
+      timerAstBinaryReaderFunctionBody.stop();
+    }
   }
 
   ExpressionStatement _read_expressionStatement(LinkedNode data) {
     return astFactory.expressionStatement(
       _readNode(data.expressionStatement_expression),
-      _getToken(data.expressionStatement_semicolon),
+      _Tokens.SEMICOLON,
     );
   }
 
   ExtendsClause _read_extendsClause(LinkedNode data) {
     return astFactory.extendsClause(
-      _getToken(data.extendsClause_extendsKeyword),
+      _Tokens.EXTENDS,
       _readNode(data.extendsClause_superclass),
     );
   }
 
   FieldDeclaration _read_fieldDeclaration(LinkedNode data) {
     var node = astFactory.fieldDeclaration2(
-      comment: _readNodeLazy(data.annotatedNode_comment),
-      covariantKeyword: _getToken(data.fieldDeclaration_covariantKeyword),
+      comment: _readDocumentationComment(data),
+      covariantKeyword:
+          AstBinaryFlags.isCovariant(data.flags) ? _Tokens.COVARIANT : null,
       fieldList: _readNode(data.fieldDeclaration_fields),
       metadata: _readNodeListLazy(data.annotatedNode_metadata),
-      semicolon: _getToken(data.fieldDeclaration_semicolon),
-      staticKeyword: _getToken(data.fieldDeclaration_staticKeyword),
+      semicolon: _Tokens.SEMICOLON,
+      staticKeyword:
+          AstBinaryFlags.isStatic(data.flags) ? _Tokens.STATIC : null,
     );
     LazyFieldDeclaration.setData(node, data);
     return node;
@@ -488,16 +602,26 @@
 
   FieldFormalParameter _read_fieldFormalParameter(LinkedNode data) {
     var node = astFactory.fieldFormalParameter2(
-      identifier: _readNode(data.normalFormalParameter_identifier),
-      period: _getToken(data.fieldFormalParameter_period),
-      thisKeyword: _getToken(data.fieldFormalParameter_thisKeyword),
-      covariantKeyword: _getToken(data.normalFormalParameter_covariantKeyword),
+      identifier: _declaredIdentifier(data),
+      period: _Tokens.PERIOD,
+      thisKeyword: _Tokens.THIS,
+      covariantKeyword:
+          AstBinaryFlags.isCovariant(data.flags) ? _Tokens.COVARIANT : null,
       typeParameters: _readNode(data.fieldFormalParameter_typeParameters),
-      keyword: _getToken(data.fieldFormalParameter_keyword),
+      keyword: _Tokens.choose(
+        AstBinaryFlags.isConst(data.flags),
+        _Tokens.CONST,
+        AstBinaryFlags.isFinal(data.flags),
+        _Tokens.FINAL,
+        AstBinaryFlags.isVar(data.flags),
+        _Tokens.VAR,
+      ),
       metadata: _readNodeList(data.normalFormalParameter_metadata),
-      comment: _readNode(data.normalFormalParameter_comment),
+      comment: _readDocumentationComment(data),
       type: _readNode(data.fieldFormalParameter_type),
       parameters: _readNode(data.fieldFormalParameter_formalParameters),
+      requiredKeyword:
+          AstBinaryFlags.isRequired(data.flags) ? _Tokens.REQUIRED : null,
     );
     LazyFormalParameter.setData(node, data);
     return node;
@@ -506,7 +630,7 @@
   ForEachPartsWithDeclaration _read_forEachPartsWithDeclaration(
       LinkedNode data) {
     return astFactory.forEachPartsWithDeclaration(
-      inKeyword: _getToken(data.forEachParts_inKeyword),
+      inKeyword: _Tokens.IN,
       iterable: _readNode(data.forEachParts_iterable),
       loopVariable: _readNode(data.forEachPartsWithDeclaration_loopVariable),
     );
@@ -514,7 +638,7 @@
 
   ForEachPartsWithIdentifier _read_forEachPartsWithIdentifier(LinkedNode data) {
     return astFactory.forEachPartsWithIdentifier(
-      inKeyword: _getToken(data.forEachParts_inKeyword),
+      inKeyword: _Tokens.IN,
       iterable: _readNode(data.forEachParts_iterable),
       identifier: _readNode(data.forEachPartsWithIdentifier_identifier),
     );
@@ -522,30 +646,40 @@
 
   ForElement _read_forElement(LinkedNode data) {
     return astFactory.forElement(
-      awaitKeyword: _getToken(data.forMixin_awaitKeyword),
+      awaitKeyword: AstBinaryFlags.hasAwait(data.flags) ? _Tokens.AWAIT : null,
       body: _readNode(data.forElement_body),
-      forKeyword: _getToken(data.forMixin_forKeyword),
+      forKeyword: _Tokens.FOR,
       forLoopParts: _readNode(data.forMixin_forLoopParts),
-      leftParenthesis: _getToken(data.forMixin_leftParenthesis),
-      rightParenthesis: _getToken(data.forMixin_rightParenthesis),
+      leftParenthesis: _Tokens.OPEN_PAREN,
+      rightParenthesis: _Tokens.CLOSE_PAREN,
     );
   }
 
   FormalParameterList _read_formalParameterList(LinkedNode data) {
     return astFactory.formalParameterList(
-      _getToken(data.formalParameterList_leftParenthesis),
+      _Tokens.OPEN_PAREN,
       _readNodeList(data.formalParameterList_parameters),
-      _getToken(data.formalParameterList_leftDelimiter),
-      _getToken(data.formalParameterList_rightDelimiter),
-      _getToken(data.formalParameterList_rightParenthesis),
+      _Tokens.choose(
+        AstBinaryFlags.isDelimiterCurly(data.flags),
+        _Tokens.OPEN_CURLY_BRACKET,
+        AstBinaryFlags.isDelimiterSquare(data.flags),
+        _Tokens.OPEN_SQUARE_BRACKET,
+      ),
+      _Tokens.choose(
+        AstBinaryFlags.isDelimiterCurly(data.flags),
+        _Tokens.CLOSE_CURLY_BRACKET,
+        AstBinaryFlags.isDelimiterSquare(data.flags),
+        _Tokens.CLOSE_SQUARE_BRACKET,
+      ),
+      _Tokens.CLOSE_PAREN,
     );
   }
 
   ForPartsWithDeclarations _read_forPartsWithDeclarations(LinkedNode data) {
     return astFactory.forPartsWithDeclarations(
       condition: _readNode(data.forParts_condition),
-      leftSeparator: _getToken(data.forParts_leftSeparator),
-      rightSeparator: _getToken(data.forParts_rightSeparator),
+      leftSeparator: _Tokens.SEMICOLON,
+      rightSeparator: _Tokens.SEMICOLON,
       updaters: _readNodeList(data.forParts_updaters),
       variables: _readNode(data.forPartsWithDeclarations_variables),
     );
@@ -555,35 +689,45 @@
     return astFactory.forPartsWithExpression(
       condition: _readNode(data.forParts_condition),
       initialization: _readNode(data.forPartsWithExpression_initialization),
-      leftSeparator: _getToken(data.forParts_leftSeparator),
-      rightSeparator: _getToken(data.forParts_rightSeparator),
+      leftSeparator: _Tokens.SEMICOLON,
+      rightSeparator: _Tokens.SEMICOLON,
       updaters: _readNodeList(data.forParts_updaters),
     );
   }
 
   ForStatement _read_forStatement(LinkedNode data) {
     return astFactory.forStatement(
-      awaitKeyword: _getToken(data.forMixin_awaitKeyword),
-      forKeyword: _getToken(data.forMixin_forKeyword),
-      leftParenthesis: _getToken(data.forMixin_leftParenthesis),
+      awaitKeyword: AstBinaryFlags.hasAwait(data.flags) ? _Tokens.AWAIT : null,
+      forKeyword: _Tokens.FOR,
+      leftParenthesis: _Tokens.OPEN_PAREN,
       forLoopParts: _readNode(data.forMixin_forLoopParts),
-      rightParenthesis: _getToken(data.forMixin_rightParenthesis),
+      rightParenthesis: _Tokens.CLOSE_PAREN,
       body: _readNode(data.forStatement_body),
     );
   }
 
   FunctionDeclaration _read_functionDeclaration(LinkedNode data) {
-    var node = astFactory.functionDeclaration(
-      _readNodeLazy(data.annotatedNode_comment),
-      _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.functionDeclaration_externalKeyword),
-      _readNodeLazy(data.functionDeclaration_returnType),
-      _getToken(data.functionDeclaration_propertyKeyword),
-      _readNode(data.namedCompilationUnitMember_name),
-      _readNodeLazy(data.functionDeclaration_functionExpression),
-    );
-    LazyFunctionDeclaration.setData(node, data);
-    return node;
+    timerAstBinaryReaderFunctionDeclaration.start();
+    try {
+      var node = astFactory.functionDeclaration(
+        _readDocumentationComment(data),
+        _readNodeListLazy(data.annotatedNode_metadata),
+        AstBinaryFlags.isExternal(data.flags) ? _Tokens.EXTERNAL : null,
+        _readNodeLazy(data.functionDeclaration_returnType),
+        _Tokens.choose(
+          AstBinaryFlags.isGet(data.flags),
+          _Tokens.GET,
+          AstBinaryFlags.isSet(data.flags),
+          _Tokens.SET,
+        ),
+        _declaredIdentifier(data),
+        _readNodeLazy(data.functionDeclaration_functionExpression),
+      );
+      LazyFunctionDeclaration.setData(node, data);
+      return node;
+    } finally {
+      timerAstBinaryReaderFunctionDeclaration.stop();
+    }
   }
 
   FunctionDeclarationStatement _read_functionDeclarationStatement(
@@ -614,126 +758,201 @@
 
   FunctionTypeAlias _read_functionTypeAlias(LinkedNode data) {
     var node = astFactory.functionTypeAlias(
-      _readNodeLazy(data.annotatedNode_comment),
+      _readDocumentationComment(data),
       _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.typeAlias_typedefKeyword),
+      _Tokens.TYPEDEF,
       _readNodeLazy(data.functionTypeAlias_returnType),
-      _readNode(data.namedCompilationUnitMember_name),
+      _declaredIdentifier(data),
       _readNode(data.functionTypeAlias_typeParameters),
       _readNodeLazy(data.functionTypeAlias_formalParameters),
-      _getToken(data.typeAlias_semicolon),
+      _Tokens.SEMICOLON,
     );
     LazyFunctionTypeAlias.setData(node, data);
+    LazyFunctionTypeAlias.setHasSelfReference(
+      node,
+      data.typeAlias_hasSelfReference,
+    );
     return node;
   }
 
   FunctionTypedFormalParameter _read_functionTypedFormalParameter(
       LinkedNode data) {
     var node = astFactory.functionTypedFormalParameter2(
-      identifier: _readNode(data.normalFormalParameter_identifier),
-      parameters: _readNode(data.functionTypedFormalParameter_formalParameters),
-      returnType: _readNode(data.functionTypedFormalParameter_returnType),
-      covariantKeyword: _getToken(data.normalFormalParameter_covariantKeyword),
-      comment: _readNode(data.normalFormalParameter_comment),
-      metadata: _readNodeList(data.normalFormalParameter_metadata),
-      typeParameters:
-          _readNode(data.functionTypedFormalParameter_typeParameters),
+      comment: _readDocumentationComment(data),
+      covariantKeyword:
+          AstBinaryFlags.isCovariant(data.flags) ? _Tokens.COVARIANT : null,
+      identifier: _declaredIdentifier(data),
+      metadata: _readNodeListLazy(data.normalFormalParameter_metadata),
+      parameters: _readNodeLazy(
+        data.functionTypedFormalParameter_formalParameters,
+      ),
+      requiredKeyword:
+          AstBinaryFlags.isRequired(data.flags) ? _Tokens.REQUIRED : null,
+      returnType: _readNodeLazy(data.functionTypedFormalParameter_returnType),
+      typeParameters: _readNode(
+        data.functionTypedFormalParameter_typeParameters,
+      ),
     );
     LazyFormalParameter.setData(node, data);
     return node;
   }
 
   GenericFunctionType _read_genericFunctionType(LinkedNode data) {
+    var id = data.genericFunctionType_id;
+
+    // Read type parameters, without bounds, to avoid forward references.
+    TypeParameterList typeParameterList;
+    var typeParameterListData = data.genericFunctionType_typeParameters;
+    if (typeParameterListData != null) {
+      var dataList = typeParameterListData.typeParameterList_typeParameters;
+      var typeParameters = List<TypeParameter>(dataList.length);
+      for (var i = 0; i < dataList.length; ++i) {
+        var data = dataList[i];
+        typeParameters[i] = astFactory.typeParameter(
+          _readDocumentationComment(data),
+          _readNodeList(data.annotatedNode_metadata),
+          _declaredIdentifier(data),
+          data.typeParameter_bound != null ? _Tokens.EXTENDS : null,
+          null,
+        );
+      }
+      typeParameterList = astFactory.typeParameterList(
+        _Tokens.LT,
+        typeParameters,
+        _Tokens.GT,
+      );
+    }
+
     GenericFunctionTypeImpl node = astFactory.genericFunctionType(
-      _readNodeLazy(data.genericFunctionType_returnType),
-      _getToken(data.genericFunctionType_functionKeyword),
-      _readNode(data.genericFunctionType_typeParameters),
-      _readNodeLazy(data.genericFunctionType_formalParameters),
-      question: _getToken(data.genericFunctionType_question),
+      null,
+      _Tokens.FUNCTION,
+      typeParameterList,
+      null,
+      question:
+          AstBinaryFlags.hasQuestion(data.flags) ? _Tokens.QUESTION : null,
     );
     node.type = _readType(data.genericFunctionType_type);
-    LazyGenericFunctionType.setData(node, data);
+
+    // Create the node element, so now type parameter elements are available.
+    LazyAst.setGenericFunctionTypeId(node, id);
+    _unitContext.createGenericFunctionTypeElement(id, node);
+
+    // Finish reading.
+    if (typeParameterListData != null) {
+      var dataList = typeParameterListData.typeParameterList_typeParameters;
+      var typeParameters = typeParameterList.typeParameters;
+      for (var i = 0; i < dataList.length; ++i) {
+        var data = dataList[i];
+        var node = typeParameters[i];
+        node.bound = _readNode(data.typeParameter_bound);
+      }
+    }
+    node.returnType = readNode(data.genericFunctionType_returnType);
+    node.parameters = _readNode(data.genericFunctionType_formalParameters);
+
     return node;
   }
 
   GenericTypeAlias _read_genericTypeAlias(LinkedNode data) {
     var node = astFactory.genericTypeAlias(
-      _readNodeLazy(data.annotatedNode_comment),
-      _readNodeList(data.annotatedNode_metadata),
-      _getToken(data.typeAlias_typedefKeyword),
-      _readNode(data.namedCompilationUnitMember_name),
+      _readDocumentationComment(data),
+      _readNodeListLazy(data.annotatedNode_metadata),
+      _Tokens.TYPEDEF,
+      _declaredIdentifier(data),
       _readNode(data.genericTypeAlias_typeParameters),
-      _getToken(data.genericTypeAlias_equals),
+      _Tokens.EQ,
       _readNodeLazy(data.genericTypeAlias_functionType),
-      _getToken(data.typeAlias_semicolon),
+      _Tokens.SEMICOLON,
     );
     LazyGenericTypeAlias.setData(node, data);
+    LazyGenericTypeAlias.setHasSelfReference(
+      node,
+      data.typeAlias_hasSelfReference,
+    );
     return node;
   }
 
   HideCombinator _read_hideCombinator(LinkedNode data) {
     return astFactory.hideCombinator(
-      _getToken(data.combinator_keyword),
-      _readNodeList(data.hideCombinator_hiddenNames),
+      _Tokens.HIDE,
+      data.names.map((name) => AstTestFactory.identifier3(name)).toList(),
     );
   }
 
   IfElement _read_ifElement(LinkedNode data) {
+    var elseElement = _readNode(data.ifElement_elseElement);
     return astFactory.ifElement(
       condition: _readNode(data.ifMixin_condition),
-      elseElement: _readNode(data.ifElement_elseElement),
-      elseKeyword: _getToken(data.ifMixin_elseKeyword),
-      ifKeyword: _getToken(data.ifMixin_ifKeyword),
-      leftParenthesis: _getToken(data.ifMixin_leftParenthesis),
-      rightParenthesis: _getToken(data.ifMixin_rightParenthesis),
+      elseElement: elseElement,
+      elseKeyword: elseElement != null ? _Tokens.ELSE : null,
+      ifKeyword: _Tokens.IF,
+      leftParenthesis: _Tokens.OPEN_PAREN,
+      rightParenthesis: _Tokens.CLOSE_PAREN,
       thenElement: _readNode(data.ifElement_thenElement),
     );
   }
 
   IfStatement _read_ifStatement(LinkedNode data) {
+    var elseStatement = _readNode(data.ifStatement_elseStatement);
     return astFactory.ifStatement(
-      _getToken(data.ifMixin_ifKeyword),
-      _getToken(data.ifMixin_leftParenthesis),
+      _Tokens.IF,
+      _Tokens.OPEN_PAREN,
       _readNode(data.ifMixin_condition),
-      _getToken(data.ifMixin_rightParenthesis),
+      _Tokens.CLOSE_PAREN,
       _readNode(data.ifStatement_thenStatement),
-      _getToken(data.ifMixin_elseKeyword),
-      _readNode(data.ifStatement_elseStatement),
+      elseStatement != null ? _Tokens.ELSE : null,
+      elseStatement,
     );
   }
 
   ImplementsClause _read_implementsClause(LinkedNode data) {
     return astFactory.implementsClause(
-      _getToken(data.implementsClause_implementsKeyword),
+      _Tokens.IMPLEMENTS,
       _readNodeList(data.implementsClause_interfaces),
     );
   }
 
   ImportDirective _read_importDirective(LinkedNode data) {
-    var node = astFactory.importDirective(
-      _readNode(data.annotatedNode_comment),
-      _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.directive_keyword),
-      _readNode(data.uriBasedDirective_uri),
-      _readNodeList(data.namespaceDirective_configurations),
-      _getToken(data.importDirective_deferredKeyword),
-      _getToken(data.importDirective_asKeyword),
-      _readNode(data.importDirective_prefix),
-      _readNodeList(data.namespaceDirective_combinators),
-      _getToken(data.directive_semicolon),
-    );
-    LazyDirective.setData(node, data);
-    return node;
+    timerAstBinaryReaderDirective.start();
+    _isReadingDirective = true;
+    try {
+      SimpleIdentifier prefix;
+      if (data.importDirective_prefix.isNotEmpty) {
+        prefix = astFactory.simpleIdentifier(
+          TokenFactory.tokenFromString(data.importDirective_prefix)
+            ..offset = data.importDirective_prefixOffset,
+        );
+      }
+
+      var node = astFactory.importDirective(
+        _readDocumentationComment(data),
+        _readNodeListLazy(data.annotatedNode_metadata),
+        _directiveKeyword(data, Keyword.IMPORT, _Tokens.IMPORT),
+        _readNode(data.uriBasedDirective_uri),
+        _readNodeList(data.namespaceDirective_configurations),
+        AstBinaryFlags.isDeferred(data.flags) ? _Tokens.DEFERRED : null,
+        _Tokens.AS,
+        prefix,
+        _readNodeList(data.namespaceDirective_combinators),
+        _Tokens.SEMICOLON,
+      );
+      LazyDirective.setData(node, data);
+      return node;
+    } finally {
+      _isReadingDirective = false;
+      timerAstBinaryReaderDirective.stop();
+    }
   }
 
   IndexExpression _read_indexExpression(LinkedNode data) {
     return astFactory.indexExpressionForTarget(
       _readNode(data.indexExpression_target),
-      _getToken(data.indexExpression_leftBracket),
+      _Tokens.OPEN_SQUARE_BRACKET,
       _readNode(data.indexExpression_index),
-      _getToken(data.indexExpression_rightBracket),
+      _Tokens.CLOSE_SQUARE_BRACKET,
     )
-      ..period = _getToken(data.indexExpression_period)
+      ..period =
+          AstBinaryFlags.hasPeriod(data.flags) ? _Tokens.PERIOD_PERIOD : null
       ..staticElement = _elementOfComponents(
         data.indexExpression_element,
         data.indexExpression_elementType,
@@ -742,32 +961,48 @@
   }
 
   InstanceCreationExpression _read_instanceCreationExpression(LinkedNode data) {
-    return astFactory.instanceCreationExpression(
-      _getToken(data.instanceCreationExpression_keyword),
+    var node = astFactory.instanceCreationExpression(
+      _Tokens.choose(
+        AstBinaryFlags.isConst(data.flags),
+        _Tokens.CONST,
+        AstBinaryFlags.isNew(data.flags),
+        _Tokens.NEW,
+      ),
       _readNode(data.instanceCreationExpression_constructorName),
-      _readNode(data.instanceCreationExpression_arguments),
+      astFactory.argumentList(
+        _Tokens.OPEN_PAREN,
+        _readNodeList(
+          data.instanceCreationExpression_arguments,
+        ),
+        _Tokens.CLOSE_PAREN,
+      ),
       typeArguments: _readNode(data.instanceCreationExpression_typeArguments),
-    )..staticType = _readType(data.expression_type);
+    );
+    node.staticElement = node.constructorName.staticElement;
+    node.staticType = _readType(data.expression_type);
+    return node;
   }
 
   IntegerLiteral _read_integerLiteral(LinkedNode data) {
-    return astFactory.integerLiteral(
-      _getToken(data.integerLiteral_literal),
-      data.integerLiteral_value,
-    )..staticType = _readType(data.expression_type);
+    return AstTestFactory.integer(data.integerLiteral_value)
+      ..staticType = _intType;
   }
 
   InterpolationExpression _read_interpolationExpression(LinkedNode data) {
+    var isIdentifier =
+        AstBinaryFlags.isStringInterpolationIdentifier(data.flags);
     return astFactory.interpolationExpression(
-      _getToken(data.interpolationExpression_leftBracket),
+      isIdentifier
+          ? _Tokens.OPEN_CURLY_BRACKET
+          : _Tokens.STRING_INTERPOLATION_EXPRESSION,
       _readNode(data.interpolationExpression_expression),
-      _getToken(data.interpolationExpression_rightBracket),
+      isIdentifier ? null : _Tokens.CLOSE_CURLY_BRACKET,
     );
   }
 
   InterpolationString _read_interpolationString(LinkedNode data) {
     return astFactory.interpolationString(
-      _getToken(data.interpolationString_token),
+      TokenFactory.tokenFromString(data.interpolationString_value),
       data.interpolationString_value,
     );
   }
@@ -775,16 +1010,16 @@
   IsExpression _read_isExpression(LinkedNode data) {
     return astFactory.isExpression(
       _readNode(data.isExpression_expression),
-      _getToken(data.isExpression_isOperator),
-      _getToken(data.isExpression_notOperator),
+      _Tokens.IS,
+      AstBinaryFlags.hasNot(data.flags) ? _Tokens.BANG : null,
       _readNode(data.isExpression_type),
-    )..staticType = _readType(data.expression_type);
+    )..staticType = _boolType;
   }
 
   Label _read_label(LinkedNode data) {
     return astFactory.label(
       _readNode(data.label_label),
-      _getToken(data.label_colon),
+      _Tokens.COLON,
     );
   }
 
@@ -796,15 +1031,22 @@
   }
 
   LibraryDirective _read_libraryDirective(LinkedNode data) {
-    var node = astFactory.libraryDirective(
-      _readNode(data.annotatedNode_comment),
-      _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.directive_keyword),
-      _readNode(data.libraryDirective_name),
-      _getToken(data.directive_semicolon),
-    );
-    LazyDirective.setData(node, data);
-    return node;
+    timerAstBinaryReaderDirective.start();
+    _isReadingDirective = true;
+    try {
+      var node = astFactory.libraryDirective(
+        _unitContext.createComment(data),
+        _readNodeListLazy(data.annotatedNode_metadata),
+        _Tokens.LIBRARY,
+        _readNode(data.libraryDirective_name),
+        _Tokens.SEMICOLON,
+      );
+      LazyDirective.setData(node, data);
+      return node;
+    } finally {
+      _isReadingDirective = false;
+      timerAstBinaryReaderDirective.stop();
+    }
   }
 
   LibraryIdentifier _read_libraryIdentifier(LinkedNode data) {
@@ -815,35 +1057,48 @@
 
   ListLiteral _read_listLiteral(LinkedNode data) {
     return astFactory.listLiteral(
-      _getToken(data.typedLiteral_constKeyword),
-      _readNode(data.typedLiteral_typeArguments),
-      _getToken(data.listLiteral_leftBracket),
+      AstBinaryFlags.isConst(data.flags) ? _Tokens.CONST : null,
+      AstBinaryFlags.hasTypeArguments(data.flags)
+          ? astFactory.typeArgumentList(
+              _Tokens.LT,
+              _readNodeList(data.typedLiteral_typeArguments),
+              _Tokens.GT,
+            )
+          : null,
+      _Tokens.OPEN_SQUARE_BRACKET,
       _readNodeList(data.listLiteral_elements),
-      _getToken(data.listLiteral_rightBracket),
+      _Tokens.CLOSE_SQUARE_BRACKET,
     )..staticType = _readType(data.expression_type);
   }
 
   MapLiteralEntry _read_mapLiteralEntry(LinkedNode data) {
     return astFactory.mapLiteralEntry(
       _readNode(data.mapLiteralEntry_key),
-      _getToken(data.mapLiteralEntry_separator),
+      _Tokens.COLON,
       _readNode(data.mapLiteralEntry_value),
     );
   }
 
   MethodDeclaration _read_methodDeclaration(LinkedNode data) {
     var node = astFactory.methodDeclaration(
-      _readNodeLazy(data.annotatedNode_comment),
+      _readDocumentationComment(data),
       _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.methodDeclaration_externalKeyword),
-      _getToken(data.methodDeclaration_modifierKeyword),
+      AstBinaryFlags.isExternal(data.flags) ? _Tokens.EXTERNAL : null,
+      AstBinaryFlags.isStatic(data.flags) ? _Tokens.STATIC : null,
       _readNodeLazy(data.methodDeclaration_returnType),
-      _getToken(data.methodDeclaration_propertyKeyword),
-      _getToken(data.methodDeclaration_operatorKeyword),
-      _readNode(data.methodDeclaration_name),
+      _Tokens.choose(
+        AstBinaryFlags.isGet(data.flags),
+        _Tokens.GET,
+        AstBinaryFlags.isSet(data.flags),
+        _Tokens.SET,
+      ),
+      AstBinaryFlags.isOperator(data.flags) ? _Tokens.OPERATOR : null,
+      _declaredIdentifier(data),
       _readNode(data.methodDeclaration_typeParameters),
       _readNodeLazy(data.methodDeclaration_formalParameters),
-      _readNodeLazy(data.methodDeclaration_body),
+      AstBinaryFlags.isAbstract(data.flags)
+          ? AstTestFactory.emptyFunctionBody()
+          : AstTestFactory.blockFunctionBody(AstTestFactory.block()),
     );
     LazyMethodDeclaration.setData(node, data);
     return node;
@@ -852,7 +1107,12 @@
   MethodInvocation _read_methodInvocation(LinkedNode data) {
     return astFactory.methodInvocation(
       _readNode(data.methodInvocation_target),
-      _getToken(data.methodInvocation_operator),
+      _Tokens.choose(
+        AstBinaryFlags.hasPeriod(data.flags),
+        _Tokens.PERIOD,
+        AstBinaryFlags.hasPeriod2(data.flags),
+        _Tokens.PERIOD_PERIOD,
+      ),
       _readNode(data.methodInvocation_methodName),
       _readNode(data.invocationExpression_typeArguments),
       _readNode(data.invocationExpression_arguments),
@@ -860,95 +1120,115 @@
   }
 
   MixinDeclaration _read_mixinDeclaration(LinkedNode data) {
-    var node = astFactory.mixinDeclaration(
-      _readNodeLazy(data.annotatedNode_comment),
-      _readNodeList(data.annotatedNode_metadata),
-      _getToken(data.mixinDeclaration_mixinKeyword),
-      _readNode(data.namedCompilationUnitMember_name),
-      _readNode(data.classOrMixinDeclaration_typeParameters),
-      _readNodeLazy(data.mixinDeclaration_onClause),
-      _readNodeLazy(data.classOrMixinDeclaration_implementsClause),
-      _getToken(data.classOrMixinDeclaration_leftBracket),
-      _readNodeListLazy(data.classOrMixinDeclaration_members),
-      _getToken(data.classOrMixinDeclaration_rightBracket),
-    );
-    LazyMixinDeclaration.setData(node, data);
-    return node;
+    timerAstBinaryReaderMixin.start();
+    try {
+      var node = astFactory.mixinDeclaration(
+        _readDocumentationComment(data),
+        _readNodeListLazy(data.annotatedNode_metadata),
+        _Tokens.MIXIN,
+        _declaredIdentifier(data),
+        _readNode(data.classOrMixinDeclaration_typeParameters),
+        _readNodeLazy(data.mixinDeclaration_onClause),
+        _readNodeLazy(data.classOrMixinDeclaration_implementsClause),
+        _Tokens.OPEN_CURLY_BRACKET,
+        _readNodeListLazy(data.classOrMixinDeclaration_members),
+        _Tokens.CLOSE_CURLY_BRACKET,
+      );
+      LazyMixinDeclaration(node, data);
+      return node;
+    } finally {
+      timerAstBinaryReaderMixin.stop();
+    }
   }
 
   NamedExpression _read_namedExpression(LinkedNode data) {
+    Expression expression = _readNode(data.namedExpression_expression);
     return astFactory.namedExpression(
       _readNode(data.namedExpression_name),
-      _readNode(data.namedExpression_expression),
-    )..staticType = _readType(data.expression_type);
+      expression,
+    )..staticType = expression.staticType;
   }
 
   NativeClause _read_nativeClause(LinkedNode data) {
     return astFactory.nativeClause(
-      _getToken(data.nativeClause_nativeKeyword),
+      _Tokens.NATIVE,
       _readNode(data.nativeClause_name),
     );
   }
 
   NativeFunctionBody _read_nativeFunctionBody(LinkedNode data) {
     return astFactory.nativeFunctionBody(
-      _getToken(data.nativeFunctionBody_nativeKeyword),
+      _Tokens.NATIVE,
       _readNode(data.nativeFunctionBody_stringLiteral),
-      _getToken(data.nativeFunctionBody_semicolon),
+      _Tokens.SEMICOLON,
     );
   }
 
   NullLiteral _read_nullLiteral(LinkedNode data) {
     return astFactory.nullLiteral(
-      _getToken(data.nullLiteral_literal),
-    )..staticType = _readType(data.expression_type);
+      _Tokens.NULL,
+    )..staticType = _nullType;
   }
 
   OnClause _read_onClause(LinkedNode data) {
     return astFactory.onClause(
-      _getToken(data.onClause_onKeyword),
+      _Tokens.ON,
       _readNodeList(data.onClause_superclassConstraints),
     );
   }
 
   ParenthesizedExpression _read_parenthesizedExpression(LinkedNode data) {
     return astFactory.parenthesizedExpression(
-      _getToken(data.parenthesizedExpression_leftParenthesis),
+      _Tokens.OPEN_PAREN,
       _readNode(data.parenthesizedExpression_expression),
-      _getToken(data.parenthesizedExpression_rightParenthesis),
+      _Tokens.CLOSE_PAREN,
     )..staticType = _readType(data.expression_type);
   }
 
   PartDirective _read_partDirective(LinkedNode data) {
-    var node = astFactory.partDirective(
-      _readNode(data.annotatedNode_comment),
-      _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.directive_keyword),
-      _readNode(data.uriBasedDirective_uri),
-      _getToken(data.directive_semicolon),
-    );
-    LazyDirective.setData(node, data);
-    return node;
+    timerAstBinaryReaderDirective.start();
+    _isReadingDirective = true;
+    try {
+      var node = astFactory.partDirective(
+        _readDocumentationComment(data),
+        _readNodeListLazy(data.annotatedNode_metadata),
+        _Tokens.PART,
+        _readNode(data.uriBasedDirective_uri),
+        _Tokens.SEMICOLON,
+      );
+      LazyDirective.setData(node, data);
+      return node;
+    } finally {
+      _isReadingDirective = false;
+      timerAstBinaryReaderDirective.stop();
+    }
   }
 
   PartOfDirective _read_partOfDirective(LinkedNode data) {
-    var node = astFactory.partOfDirective(
-      _readNode(data.annotatedNode_comment),
-      _readNodeList(data.annotatedNode_metadata),
-      _getToken(data.directive_keyword),
-      _getToken(data.partOfDirective_ofKeyword),
-      _readNode(data.partOfDirective_uri),
-      _readNode(data.partOfDirective_libraryName),
-      _getToken(data.directive_semicolon),
-    );
-    LazyDirective.setData(node, data);
-    return node;
+    timerAstBinaryReaderDirective.start();
+    _isReadingDirective = true;
+    try {
+      var node = astFactory.partOfDirective(
+        _readDocumentationComment(data),
+        _readNodeListLazy(data.annotatedNode_metadata),
+        _Tokens.PART,
+        _Tokens.OF,
+        _readNode(data.partOfDirective_uri),
+        _readNode(data.partOfDirective_libraryName),
+        _Tokens.SEMICOLON,
+      );
+      LazyDirective.setData(node, data);
+      return node;
+    } finally {
+      _isReadingDirective = false;
+      timerAstBinaryReaderDirective.stop();
+    }
   }
 
   PostfixExpression _read_postfixExpression(LinkedNode data) {
     return astFactory.postfixExpression(
       _readNode(data.postfixExpression_operand),
-      _getToken(data.postfixExpression_operator),
+      _Tokens.fromType(data.postfixExpression_operator),
     )
       ..staticElement = _elementOfComponents(
         data.postfixExpression_element,
@@ -960,14 +1240,14 @@
   PrefixedIdentifier _read_prefixedIdentifier(LinkedNode data) {
     return astFactory.prefixedIdentifier(
       _readNode(data.prefixedIdentifier_prefix),
-      _getToken(data.prefixedIdentifier_period),
+      _Tokens.PERIOD,
       _readNode(data.prefixedIdentifier_identifier),
     )..staticType = _readType(data.expression_type);
   }
 
   PrefixExpression _read_prefixExpression(LinkedNode data) {
     return astFactory.prefixExpression(
-      _getToken(data.prefixExpression_operator),
+      _Tokens.fromType(data.prefixExpression_operator),
       _readNode(data.prefixExpression_operand),
     )
       ..staticElement = _elementOfComponents(
@@ -980,16 +1260,17 @@
   PropertyAccess _read_propertyAccess(LinkedNode data) {
     return astFactory.propertyAccess(
       _readNode(data.propertyAccess_target),
-      _getToken(data.propertyAccess_operator),
+      _Tokens.fromType(data.propertyAccess_operator),
       _readNode(data.propertyAccess_propertyName),
     )..staticType = _readType(data.expression_type);
   }
 
   RedirectingConstructorInvocation _read_redirectingConstructorInvocation(
       LinkedNode data) {
+    var hasThis = AstBinaryFlags.hasThis(data.flags);
     return astFactory.redirectingConstructorInvocation(
-      _getToken(data.redirectingConstructorInvocation_thisKeyword),
-      _getToken(data.redirectingConstructorInvocation_period),
+      hasThis ? _Tokens.THIS : null,
+      hasThis ? _Tokens.PERIOD : null,
       _readNode(data.redirectingConstructorInvocation_constructorName),
       _readNode(data.redirectingConstructorInvocation_arguments),
     )..staticElement = _elementOfComponents(
@@ -1000,35 +1281,35 @@
 
   RethrowExpression _read_rethrowExpression(LinkedNode data) {
     return astFactory.rethrowExpression(
-      _getToken(data.rethrowExpression_rethrowKeyword),
+      _Tokens.RETHROW,
     )..staticType = _readType(data.expression_type);
   }
 
   ReturnStatement _read_returnStatement(LinkedNode data) {
     return astFactory.returnStatement(
-      _getToken(data.returnStatement_returnKeyword),
+      _Tokens.RETURN,
       _readNode(data.returnStatement_expression),
-      _getToken(data.returnStatement_semicolon),
-    );
-  }
-
-  ScriptTag _read_scriptTag(LinkedNode data) {
-    return astFactory.scriptTag(
-      _getToken(data.scriptTag_scriptTag),
+      _Tokens.SEMICOLON,
     );
   }
 
   SetOrMapLiteral _read_setOrMapLiteral(LinkedNode data) {
     SetOrMapLiteralImpl node = astFactory.setOrMapLiteral(
-      constKeyword: _getToken(data.typedLiteral_constKeyword),
+      constKeyword: AstBinaryFlags.isConst(data.flags) ? _Tokens.CONST : null,
       elements: _readNodeList(data.setOrMapLiteral_elements),
-      leftBracket: _getToken(data.setOrMapLiteral_leftBracket),
-      typeArguments: _readNode(data.typedLiteral_typeArguments),
-      rightBracket: _getToken(data.setOrMapLiteral_rightBracket),
+      leftBracket: _Tokens.OPEN_CURLY_BRACKET,
+      typeArguments: AstBinaryFlags.hasTypeArguments(data.flags)
+          ? astFactory.typeArgumentList(
+              _Tokens.LT,
+              _readNodeList(data.typedLiteral_typeArguments),
+              _Tokens.GT,
+            )
+          : null,
+      rightBracket: _Tokens.CLOSE_CURLY_BRACKET,
     )..staticType = _readType(data.expression_type);
-    if (data.setOrMapLiteral_isMap) {
+    if (AstBinaryFlags.isMap(data.flags)) {
       node.becomeMap();
-    } else if (data.setOrMapLiteral_isSet) {
+    } else if (AstBinaryFlags.isSet(data.flags)) {
       node.becomeSet();
     }
     return node;
@@ -1036,27 +1317,39 @@
 
   ShowCombinator _read_showCombinator(LinkedNode data) {
     return astFactory.showCombinator(
-      _getToken(data.combinator_keyword),
-      _readNodeList(data.showCombinator_shownNames),
+      _Tokens.SHOW,
+      data.names.map((name) => AstTestFactory.identifier3(name)).toList(),
     );
   }
 
   SimpleFormalParameter _read_simpleFormalParameter(LinkedNode data) {
     SimpleFormalParameterImpl node = astFactory.simpleFormalParameter2(
-      identifier: _readNode(data.normalFormalParameter_identifier),
+      identifier: _declaredIdentifier(data),
       type: _readNode(data.simpleFormalParameter_type),
-      covariantKeyword: _getToken(data.normalFormalParameter_covariantKeyword),
-      comment: _readNode(data.normalFormalParameter_comment),
+      covariantKeyword:
+          AstBinaryFlags.isCovariant(data.flags) ? _Tokens.COVARIANT : null,
+      comment: _readDocumentationComment(data),
       metadata: _readNodeList(data.normalFormalParameter_metadata),
-      keyword: _getToken(data.simpleFormalParameter_keyword),
+      keyword: _Tokens.choose(
+        AstBinaryFlags.isConst(data.flags),
+        _Tokens.CONST,
+        AstBinaryFlags.isFinal(data.flags),
+        _Tokens.FINAL,
+        AstBinaryFlags.isVar(data.flags),
+        _Tokens.VAR,
+      ),
+      requiredKeyword:
+          AstBinaryFlags.isRequired(data.flags) ? _Tokens.REQUIRED : null,
     );
     LazyFormalParameter.setData(node, data);
+    LazyAst.setInheritsCovariant(node, data.inheritsCovariant);
     return node;
   }
 
   SimpleIdentifier _read_simpleIdentifier(LinkedNode data) {
     return astFactory.simpleIdentifier(
-      _getToken(data.simpleIdentifier_token),
+      TokenFactory.tokenFromString(data.name),
+      isDeclaration: AstBinaryFlags.isDeclaration(data.flags),
     )
       ..staticElement = _elementOfComponents(
         data.simpleIdentifier_element,
@@ -1066,15 +1359,16 @@
   }
 
   SimpleStringLiteral _read_simpleStringLiteral(LinkedNode data) {
-    return astFactory.simpleStringLiteral(
-      _getToken(data.simpleStringLiteral_token),
-      data.simpleStringLiteral_value,
-    )..staticType = _readType(data.expression_type);
+    var node = AstTestFactory.string2(data.simpleStringLiteral_value);
+    if (!_isReadingDirective) {
+      node.staticType = _stringType;
+    }
+    return node;
   }
 
   SpreadElement _read_spreadElement(LinkedNode data) {
     return astFactory.spreadElement(
-      spreadOperator: _getToken(data.spreadElement_spreadOperator),
+      spreadOperator: _Tokens.fromType(data.spreadElement_spreadOperator),
       expression: _readNode(data.spreadElement_expression),
     );
   }
@@ -1082,13 +1376,13 @@
   StringInterpolation _read_stringInterpolation(LinkedNode data) {
     return astFactory.stringInterpolation(
       _readNodeList(data.stringInterpolation_elements),
-    )..staticType = _readType(data.expression_type);
+    )..staticType = _stringType;
   }
 
   SuperConstructorInvocation _read_superConstructorInvocation(LinkedNode data) {
     return astFactory.superConstructorInvocation(
-      _getToken(data.superConstructorInvocation_superKeyword),
-      _getToken(data.superConstructorInvocation_period),
+      _Tokens.SUPER,
+      _Tokens.PERIOD,
       _readNode(data.superConstructorInvocation_constructorName),
       _readNode(data.superConstructorInvocation_arguments),
     )..staticElement = _elementOfComponents(
@@ -1099,16 +1393,16 @@
 
   SuperExpression _read_superExpression(LinkedNode data) {
     return astFactory.superExpression(
-      _getToken(data.superExpression_superKeyword),
+      _Tokens.SUPER,
     )..staticType = _readType(data.expression_type);
   }
 
   SwitchCase _read_switchCase(LinkedNode data) {
     return astFactory.switchCase(
       _readNodeList(data.switchMember_labels),
-      _getToken(data.switchMember_keyword),
+      _Tokens.CASE,
       _readNode(data.switchCase_expression),
-      _getToken(data.switchMember_colon),
+      _Tokens.COLON,
       _readNodeList(data.switchMember_statements),
     );
   }
@@ -1116,157 +1410,183 @@
   SwitchDefault _read_switchDefault(LinkedNode data) {
     return astFactory.switchDefault(
       _readNodeList(data.switchMember_labels),
-      _getToken(data.switchMember_keyword),
-      _getToken(data.switchMember_colon),
+      _Tokens.DEFAULT,
+      _Tokens.COLON,
       _readNodeList(data.switchMember_statements),
     );
   }
 
   SwitchStatement _read_switchStatement(LinkedNode data) {
     return astFactory.switchStatement(
-      _getToken(data.switchStatement_switchKeyword),
-      _getToken(data.switchStatement_leftParenthesis),
+      _Tokens.SWITCH,
+      _Tokens.OPEN_PAREN,
       _readNode(data.switchStatement_expression),
-      _getToken(data.switchStatement_rightParenthesis),
-      _getToken(data.switchStatement_leftBracket),
+      _Tokens.CLOSE_PAREN,
+      _Tokens.OPEN_CURLY_BRACKET,
       _readNodeList(data.switchStatement_members),
-      _getToken(data.switchStatement_rightBracket),
+      _Tokens.CLOSE_CURLY_BRACKET,
     );
   }
 
   SymbolLiteral _read_symbolLiteral(LinkedNode data) {
     return astFactory.symbolLiteral(
-      _getToken(data.symbolLiteral_poundSign),
-      _getTokens(data.symbolLiteral_components),
+      _Tokens.HASH,
+      data.names.map((lexeme) => TokenFactory.tokenFromString(lexeme)).toList(),
     )..staticType = _readType(data.expression_type);
   }
 
   ThisExpression _read_thisExpression(LinkedNode data) {
     return astFactory.thisExpression(
-      _getToken(data.thisExpression_thisKeyword),
+      _Tokens.THIS,
     )..staticType = _readType(data.expression_type);
   }
 
   ThrowExpression _read_throwExpression(LinkedNode data) {
     return astFactory.throwExpression(
-      _getToken(data.throwExpression_throwKeyword),
+      _Tokens.THROW,
       _readNode(data.throwExpression_expression),
     )..staticType = _readType(data.expression_type);
   }
 
   TopLevelVariableDeclaration _read_topLevelVariableDeclaration(
       LinkedNode data) {
-    var node = astFactory.topLevelVariableDeclaration(
-      _readNodeLazy(data.annotatedNode_comment),
-      _readNodeListLazy(data.annotatedNode_metadata),
-      _readNode(data.topLevelVariableDeclaration_variableList),
-      _getToken(data.topLevelVariableDeclaration_semicolon),
-    );
-    LazyTopLevelVariableDeclaration.setData(node, data);
-    return node;
+    timerAstBinaryReaderTopLevelVar.start();
+    try {
+      var node = astFactory.topLevelVariableDeclaration(
+        _readDocumentationComment(data),
+        _readNodeListLazy(data.annotatedNode_metadata),
+        _readNode(data.topLevelVariableDeclaration_variableList),
+        _Tokens.SEMICOLON,
+      );
+      LazyTopLevelVariableDeclaration.setData(node, data);
+      return node;
+    } finally {
+      timerAstBinaryReaderTopLevelVar.stop();
+    }
   }
 
   TryStatement _read_tryStatement(LinkedNode data) {
     return astFactory.tryStatement(
-      _getToken(data.tryStatement_tryKeyword),
+      _Tokens.TRY,
       _readNode(data.tryStatement_body),
       _readNodeList(data.tryStatement_catchClauses),
-      _getToken(data.tryStatement_finallyKeyword),
+      _Tokens.FINALLY,
       _readNode(data.tryStatement_finallyBlock),
     );
   }
 
   TypeArgumentList _read_typeArgumentList(LinkedNode data) {
     return astFactory.typeArgumentList(
-      _getToken(data.typeArgumentList_leftBracket),
+      _Tokens.LT,
       _readNodeList(data.typeArgumentList_arguments),
-      _getToken(data.typeArgumentList_rightBracket),
+      _Tokens.GT,
     );
   }
 
   TypeName _read_typeName(LinkedNode data) {
     return astFactory.typeName(
       _readNode(data.typeName_name),
-      _readNode(data.typeName_typeArguments),
-      question: _getToken(data.typeName_question),
+      AstBinaryFlags.hasTypeArguments(data.flags)
+          ? astFactory.typeArgumentList(
+              _Tokens.LT,
+              _readNodeList(data.typeName_typeArguments),
+              _Tokens.GT,
+            )
+          : null,
+      question:
+          AstBinaryFlags.hasQuestion(data.flags) ? _Tokens.QUESTION : null,
     )..type = _readType(data.typeName_type);
   }
 
   TypeParameter _read_typeParameter(LinkedNode data) {
     var node = astFactory.typeParameter(
-      _readNodeLazy(data.annotatedNode_comment),
+      _readDocumentationComment(data),
       _readNodeListLazy(data.annotatedNode_metadata),
-      _readNode(data.typeParameter_name),
-      _getToken(data.typeParameter_extendsKeyword),
+      _declaredIdentifier(data),
+      _Tokens.EXTENDS,
       _readNodeLazy(data.typeParameter_bound),
     );
     LazyTypeParameter.setData(node, data);
-    _unitContext.addTypeParameter(data.typeParameter_id, node);
     return node;
   }
 
   TypeParameterList _read_typeParameterList(LinkedNode data) {
     return astFactory.typeParameterList(
-      _getToken(data.typeParameterList_leftBracket),
+      _Tokens.LT,
       _readNodeList(data.typeParameterList_typeParameters),
-      _getToken(data.typeParameterList_rightBracket),
+      _Tokens.GT,
     );
   }
 
   VariableDeclaration _read_variableDeclaration(LinkedNode data) {
     var node = astFactory.variableDeclaration(
-      _readNode(data.variableDeclaration_name),
-      _getToken(data.variableDeclaration_equals),
+      _declaredIdentifier(data),
+      _Tokens.EQ,
       _readNodeLazy(data.variableDeclaration_initializer),
     );
     LazyVariableDeclaration.setData(node, data);
+    LazyAst.setInheritsCovariant(node, data.inheritsCovariant);
     return node;
   }
 
   VariableDeclarationList _read_variableDeclarationList(LinkedNode data) {
-    return astFactory.variableDeclarationList(
-      _readNodeLazy(data.annotatedNode_comment),
-      _readNodeListLazy(data.annotatedNode_metadata),
-      _getToken(data.variableDeclarationList_keyword),
-      _readNodeLazy(data.variableDeclarationList_type),
-      _readNodeList(data.variableDeclarationList_variables),
+    var node = astFactory.variableDeclarationList2(
+      comment: _readDocumentationComment(data),
+      keyword: _Tokens.choose(
+        AstBinaryFlags.isConst(data.flags),
+        _Tokens.CONST,
+        AstBinaryFlags.isFinal(data.flags),
+        _Tokens.FINAL,
+        AstBinaryFlags.isVar(data.flags),
+        _Tokens.VAR,
+      ),
+      lateKeyword: AstBinaryFlags.isLate(data.flags) ? _Tokens.LATE : null,
+      metadata: _readNodeListLazy(data.annotatedNode_metadata),
+      type: _readNodeLazy(data.variableDeclarationList_type),
+      variables: _readNodeList(data.variableDeclarationList_variables),
     );
+    LazyVariableDeclarationList.setData(node, data);
+    return node;
   }
 
   VariableDeclarationStatement _read_variableDeclarationStatement(
       LinkedNode data) {
     return astFactory.variableDeclarationStatement(
       _readNode(data.variableDeclarationStatement_variables),
-      _getToken(data.variableDeclarationStatement_semicolon),
+      _Tokens.SEMICOLON,
     );
   }
 
   WhileStatement _read_whileStatement(LinkedNode data) {
     return astFactory.whileStatement(
-      _getToken(data.whileStatement_whileKeyword),
-      _getToken(data.whileStatement_leftParenthesis),
+      _Tokens.WHILE,
+      _Tokens.OPEN_PAREN,
       _readNode(data.whileStatement_condition),
-      _getToken(data.whileStatement_rightParenthesis),
+      _Tokens.CLOSE_PAREN,
       _readNode(data.whileStatement_body),
     );
   }
 
   WithClause _read_withClause(LinkedNode data) {
     return astFactory.withClause(
-      _getToken(data.withClause_withKeyword),
+      _Tokens.WITH,
       _readNodeList(data.withClause_mixinTypes),
     );
   }
 
   YieldStatement _read_yieldStatement(LinkedNode data) {
     return astFactory.yieldStatement(
-      _getToken(data.yieldStatement_yieldKeyword),
-      _getToken(data.yieldStatement_star),
+      _Tokens.YIELD,
+      AstBinaryFlags.isStar(data.flags) ? _Tokens.STAR : null,
       _readNode(data.yieldStatement_expression),
-      _getToken(data.yieldStatement_semicolon),
+      _Tokens.SEMICOLON,
     );
   }
 
+  Comment _readDocumentationComment(LinkedNode data) {
+    return null;
+  }
+
   AstNode _readNode(LinkedNode data) {
     if (data == null) return null;
 
@@ -1307,6 +1627,8 @@
         return _read_classTypeAlias(data);
       case LinkedNodeKind.comment:
         return _read_comment(data);
+      case LinkedNodeKind.commentReference:
+        return _read_commentReference(data);
       case LinkedNodeKind.compilationUnit:
         return _read_compilationUnit(data);
       case LinkedNodeKind.conditionalExpression:
@@ -1451,8 +1773,6 @@
         return _read_rethrowExpression(data);
       case LinkedNodeKind.returnStatement:
         return _read_returnStatement(data);
-      case LinkedNodeKind.scriptTag:
-        return _read_scriptTag(data);
       case LinkedNodeKind.setOrMapLiteral:
         return _read_setOrMapLiteral(data);
       case LinkedNodeKind.showCombinator:
@@ -1536,4 +1856,124 @@
   DartType _readType(LinkedNodeType data) {
     return _unitContext.readType(data);
   }
+
+  static ParameterKind _toParameterKind(LinkedNodeFormalParameterKind kind) {
+    switch (kind) {
+      case LinkedNodeFormalParameterKind.requiredPositional:
+        return ParameterKind.REQUIRED;
+      case LinkedNodeFormalParameterKind.requiredNamed:
+        return ParameterKind.NAMED_REQUIRED;
+        break;
+      case LinkedNodeFormalParameterKind.optionalPositional:
+        return ParameterKind.POSITIONAL;
+        break;
+      case LinkedNodeFormalParameterKind.optionalNamed:
+        return ParameterKind.NAMED;
+      default:
+        throw StateError('Unexpected: $kind');
+    }
+  }
+}
+
+class _Tokens {
+  static final ABSTRACT = TokenFactory.tokenFromKeyword(Keyword.ABSTRACT);
+  static final ARROW = TokenFactory.tokenFromType(TokenType.FUNCTION);
+  static final AS = TokenFactory.tokenFromKeyword(Keyword.AS);
+  static final ASSERT = TokenFactory.tokenFromKeyword(Keyword.ASSERT);
+  static final AT = TokenFactory.tokenFromType(TokenType.AT);
+  static final ASYNC = TokenFactory.tokenFromKeyword(Keyword.ASYNC);
+  static final AWAIT = TokenFactory.tokenFromKeyword(Keyword.AWAIT);
+  static final BANG = TokenFactory.tokenFromType(TokenType.BANG);
+  static final BREAK = TokenFactory.tokenFromKeyword(Keyword.BREAK);
+  static final CASE = TokenFactory.tokenFromKeyword(Keyword.CASE);
+  static final CATCH = TokenFactory.tokenFromKeyword(Keyword.CATCH);
+  static final CLASS = TokenFactory.tokenFromKeyword(Keyword.CLASS);
+  static final CLOSE_CURLY_BRACKET =
+      TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET);
+  static final CLOSE_PAREN = TokenFactory.tokenFromType(TokenType.CLOSE_PAREN);
+  static final CLOSE_SQUARE_BRACKET =
+      TokenFactory.tokenFromType(TokenType.CLOSE_SQUARE_BRACKET);
+  static final COLON = TokenFactory.tokenFromType(TokenType.COLON);
+  static final COMMA = TokenFactory.tokenFromType(TokenType.COMMA);
+  static final CONST = TokenFactory.tokenFromKeyword(Keyword.CONST);
+  static final CONTINUE = TokenFactory.tokenFromKeyword(Keyword.CONTINUE);
+  static final COVARIANT = TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
+  static final DEFERRED = TokenFactory.tokenFromKeyword(Keyword.DEFERRED);
+  static final ELSE = TokenFactory.tokenFromKeyword(Keyword.ELSE);
+  static final EXTERNAL = TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
+  static final FACTORY = TokenFactory.tokenFromKeyword(Keyword.FACTORY);
+  static final DEFAULT = TokenFactory.tokenFromKeyword(Keyword.DEFAULT);
+  static final DO = TokenFactory.tokenFromKeyword(Keyword.DO);
+  static final ENUM = TokenFactory.tokenFromKeyword(Keyword.ENUM);
+  static final EQ = TokenFactory.tokenFromType(TokenType.EQ);
+  static final EXPORT = TokenFactory.tokenFromKeyword(Keyword.EXPORT);
+  static final EXTENDS = TokenFactory.tokenFromKeyword(Keyword.EXTENDS);
+  static final FINAL = TokenFactory.tokenFromKeyword(Keyword.FINAL);
+  static final FINALLY = TokenFactory.tokenFromKeyword(Keyword.FINALLY);
+  static final FOR = TokenFactory.tokenFromKeyword(Keyword.FOR);
+  static final FUNCTION = TokenFactory.tokenFromKeyword(Keyword.FUNCTION);
+  static final GET = TokenFactory.tokenFromKeyword(Keyword.GET);
+  static final GT = TokenFactory.tokenFromType(TokenType.GT);
+  static final HASH = TokenFactory.tokenFromType(TokenType.HASH);
+  static final HIDE = TokenFactory.tokenFromKeyword(Keyword.HIDE);
+  static final IF = TokenFactory.tokenFromKeyword(Keyword.IF);
+  static final IMPLEMENTS = TokenFactory.tokenFromKeyword(Keyword.IMPORT);
+  static final IMPORT = TokenFactory.tokenFromKeyword(Keyword.IMPLEMENTS);
+  static final IN = TokenFactory.tokenFromKeyword(Keyword.IN);
+  static final IS = TokenFactory.tokenFromKeyword(Keyword.IS);
+  static final LATE = TokenFactory.tokenFromKeyword(Keyword.LATE);
+  static final LIBRARY = TokenFactory.tokenFromKeyword(Keyword.LIBRARY);
+  static final LT = TokenFactory.tokenFromType(TokenType.LT);
+  static final MIXIN = TokenFactory.tokenFromKeyword(Keyword.MIXIN);
+  static final NATIVE = TokenFactory.tokenFromKeyword(Keyword.NATIVE);
+  static final NEW = TokenFactory.tokenFromKeyword(Keyword.NEW);
+  static final NULL = TokenFactory.tokenFromKeyword(Keyword.NULL);
+  static final OF = TokenFactory.tokenFromKeyword(Keyword.OF);
+  static final ON = TokenFactory.tokenFromKeyword(Keyword.ON);
+  static final OPEN_CURLY_BRACKET =
+      TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET);
+  static final OPEN_PAREN = TokenFactory.tokenFromType(TokenType.OPEN_PAREN);
+  static final OPEN_SQUARE_BRACKET =
+      TokenFactory.tokenFromType(TokenType.OPEN_SQUARE_BRACKET);
+  static final OPERATOR = TokenFactory.tokenFromKeyword(Keyword.OPERATOR);
+  static final PART = TokenFactory.tokenFromKeyword(Keyword.PART);
+  static final PERIOD = TokenFactory.tokenFromType(TokenType.PERIOD);
+  static final PERIOD_PERIOD =
+      TokenFactory.tokenFromType(TokenType.PERIOD_PERIOD);
+  static final QUESTION = TokenFactory.tokenFromType(TokenType.QUESTION);
+  static final REQUIRED = TokenFactory.tokenFromKeyword(Keyword.REQUIRED);
+  static final RETHROW = TokenFactory.tokenFromKeyword(Keyword.RETHROW);
+  static final RETURN = TokenFactory.tokenFromKeyword(Keyword.RETURN);
+  static final SEMICOLON = TokenFactory.tokenFromType(TokenType.SEMICOLON);
+  static final SET = TokenFactory.tokenFromKeyword(Keyword.SET);
+  static final SHOW = TokenFactory.tokenFromKeyword(Keyword.SHOW);
+  static final STAR = TokenFactory.tokenFromType(TokenType.STAR);
+  static final STATIC = TokenFactory.tokenFromKeyword(Keyword.STATIC);
+  static final STRING_INTERPOLATION_EXPRESSION =
+      TokenFactory.tokenFromType(TokenType.STRING_INTERPOLATION_EXPRESSION);
+  static final SUPER = TokenFactory.tokenFromKeyword(Keyword.SUPER);
+  static final SWITCH = TokenFactory.tokenFromKeyword(Keyword.SWITCH);
+  static final SYNC = TokenFactory.tokenFromKeyword(Keyword.SYNC);
+  static final THIS = TokenFactory.tokenFromKeyword(Keyword.THIS);
+  static final THROW = TokenFactory.tokenFromKeyword(Keyword.THROW);
+  static final TRY = TokenFactory.tokenFromKeyword(Keyword.TRY);
+  static final TYPEDEF = TokenFactory.tokenFromKeyword(Keyword.TYPEDEF);
+  static final VAR = TokenFactory.tokenFromKeyword(Keyword.VAR);
+  static final WITH = TokenFactory.tokenFromKeyword(Keyword.WITH);
+  static final WHILE = TokenFactory.tokenFromKeyword(Keyword.WHILE);
+  static final YIELD = TokenFactory.tokenFromKeyword(Keyword.YIELD);
+
+  static Token choose(bool if1, Token then1, bool if2, Token then2,
+      [bool if3, Token then3]) {
+    if (if1) return then1;
+    if (if2) return then2;
+    if (if2 == true) return then3;
+    return null;
+  }
+
+  static Token fromType(UnlinkedTokenType type) {
+    return TokenFactory.tokenFromType(
+      TokensContext.binaryToAstTokenType(type),
+    );
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 76a97c7..5d3ce26 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -11,21 +11,29 @@
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_flags.dart';
+import 'package:analyzer/src/summary2/informative_data.dart';
 import 'package:analyzer/src/summary2/lazy_ast.dart';
 import 'package:analyzer/src/summary2/linking_bundle_context.dart';
-import 'package:analyzer/src/summary2/tokens_context.dart';
+import 'package:analyzer/src/summary2/tokens_writer.dart';
+
+var timerAstBinaryWriter = Stopwatch();
+var timerAstBinaryWriterClass = Stopwatch();
+var timerAstBinaryWriterDirective = Stopwatch();
+var timerAstBinaryWriterFunctionBody = Stopwatch();
+var timerAstBinaryWriterMixin = Stopwatch();
+var timerAstBinaryWriterTopVar = Stopwatch();
+var timerAstBinaryWriterTypedef = Stopwatch();
 
 /// Serializer of fully resolved ASTs into flat buffers.
 class AstBinaryWriter extends ThrowingAstVisitor<LinkedNodeBuilder> {
   final LinkingBundleContext _linkingContext;
-  final TokensContext _tokensContext;
 
-  /// This field is set temporary while visiting [FieldDeclaration] or
-  /// [TopLevelVariableDeclaration] to store data shared among all variables
-  /// in these declarations.
-  LinkedNodeVariablesDeclarationBuilder _variablesDeclaration;
+  /// Is `true` if the current [ClassDeclaration] has a const constructor,
+  /// so initializers of final fields should be written.
+  bool _hasConstConstructor = false;
 
-  AstBinaryWriter(this._linkingContext, this._tokensContext);
+  AstBinaryWriter(this._linkingContext);
 
   @override
   LinkedNodeBuilder visitAdjacentStrings(AdjacentStrings node) {
@@ -36,12 +44,13 @@
 
   @override
   LinkedNodeBuilder visitAnnotation(Annotation node) {
+    var elementComponents = _componentsOfElement(node.element);
     return LinkedNodeBuilder.annotation(
       annotation_arguments: node.arguments?.accept(this),
-      annotation_atSign: _getToken(node.atSign),
       annotation_constructorName: node.constructorName?.accept(this),
+      annotation_element: elementComponents.rawElement,
+      annotation_elementType: elementComponents.definingType,
       annotation_name: node.name?.accept(this),
-      annotation_period: _getToken(node.period),
     );
   }
 
@@ -49,15 +58,12 @@
   LinkedNodeBuilder visitArgumentList(ArgumentList node) {
     return LinkedNodeBuilder.argumentList(
       argumentList_arguments: _writeNodeList(node.arguments),
-      argumentList_leftParenthesis: _getToken(node.leftParenthesis),
-      argumentList_rightParenthesis: _getToken(node.rightParenthesis),
     );
   }
 
   @override
   LinkedNodeBuilder visitAsExpression(AsExpression node) {
     return LinkedNodeBuilder.asExpression(
-      asExpression_asOperator: _getToken(node.asOperator),
       asExpression_expression: node.expression.accept(this),
       asExpression_type: node.type.accept(this),
     );
@@ -66,25 +72,16 @@
   @override
   LinkedNodeBuilder visitAssertInitializer(AssertInitializer node) {
     return LinkedNodeBuilder.assertInitializer(
-      assertInitializer_assertKeyword: _getToken(node.assertKeyword),
-      assertInitializer_comma: _getToken(node.comma),
       assertInitializer_condition: node.condition.accept(this),
-      assertInitializer_leftParenthesis: _getToken(node.leftParenthesis),
       assertInitializer_message: node.message?.accept(this),
-      assertInitializer_rightParenthesis: _getToken(node.rightParenthesis),
     );
   }
 
   @override
   LinkedNodeBuilder visitAssertStatement(AssertStatement node) {
     var builder = LinkedNodeBuilder.assertStatement(
-      assertStatement_assertKeyword: _getToken(node.assertKeyword),
-      assertStatement_comma: _getToken(node.comma),
       assertStatement_condition: node.condition.accept(this),
-      assertStatement_leftParenthesis: _getToken(node.leftParenthesis),
       assertStatement_message: node.message?.accept(this),
-      assertStatement_rightParenthesis: _getToken(node.rightParenthesis),
-      assertStatement_semicolon: _getToken(node.semicolon),
     );
     _storeStatement(builder, node);
     return builder;
@@ -97,7 +94,9 @@
       assignmentExpression_element: elementComponents.rawElement,
       assignmentExpression_elementType: elementComponents.definingType,
       assignmentExpression_leftHandSide: node.leftHandSide.accept(this),
-      assignmentExpression_operator: _getToken(node.operator),
+      assignmentExpression_operator: TokensWriter.astToBinaryTokenType(
+        node.operator.type,
+      ),
       assignmentExpression_rightHandSide: node.rightHandSide.accept(this),
       expression_type: _writeType(node.staticType),
     );
@@ -106,7 +105,6 @@
   @override
   LinkedNodeBuilder visitAwaitExpression(AwaitExpression node) {
     return LinkedNodeBuilder.awaitExpression(
-      awaitExpression_awaitKeyword: _getToken(node.awaitKeyword),
       awaitExpression_expression: node.expression.accept(this),
       expression_type: _writeType(node.staticType),
     );
@@ -119,7 +117,9 @@
       binaryExpression_element: elementComponents.rawElement,
       binaryExpression_elementType: elementComponents.definingType,
       binaryExpression_leftOperand: node.leftOperand.accept(this),
-      binaryExpression_operator: _getToken(node.operator),
+      binaryExpression_operator: TokensWriter.astToBinaryTokenType(
+        node.operator.type,
+      ),
       binaryExpression_rightOperand: node.rightOperand.accept(this),
       expression_type: _writeType(node.staticType),
     );
@@ -128,25 +128,31 @@
   @override
   LinkedNodeBuilder visitBlock(Block node) {
     return LinkedNodeBuilder.block(
-      block_leftBracket: _getToken(node.leftBracket),
-      block_rightBracket: _getToken(node.rightBracket),
       block_statements: _writeNodeList(node.statements),
     );
   }
 
   @override
   LinkedNodeBuilder visitBlockFunctionBody(BlockFunctionBody node) {
-    return LinkedNodeBuilder.blockFunctionBody(
-      blockFunctionBody_block: node.block.accept(this),
-      blockFunctionBody_keyword: _getToken(node.keyword),
-      blockFunctionBody_star: _getToken(node.star),
-    );
+    timerAstBinaryWriterFunctionBody.start();
+    try {
+      var builder = LinkedNodeBuilder.blockFunctionBody(
+        blockFunctionBody_block: node.block.accept(this),
+      );
+      builder.flags = AstBinaryFlags.encode(
+        isAsync: node.keyword?.keyword == Keyword.ASYNC,
+        isStar: node.star != null,
+        isSync: node.keyword?.keyword == Keyword.SYNC,
+      );
+      return builder;
+    } finally {
+      timerAstBinaryWriterFunctionBody.stop();
+    }
   }
 
   @override
   LinkedNodeBuilder visitBooleanLiteral(BooleanLiteral node) {
     return LinkedNodeBuilder.booleanLiteral(
-      booleanLiteral_literal: _getToken(node.literal),
       booleanLiteral_value: node.value,
     );
   }
@@ -154,9 +160,7 @@
   @override
   LinkedNodeBuilder visitBreakStatement(BreakStatement node) {
     var builder = LinkedNodeBuilder.breakStatement(
-      breakStatement_breakKeyword: _getToken(node.breakKeyword),
       breakStatement_label: node.label?.accept(this),
-      breakStatement_semicolon: _getToken(node.semicolon),
     );
     _storeStatement(builder, node);
     return builder;
@@ -176,43 +180,59 @@
   LinkedNodeBuilder visitCatchClause(CatchClause node) {
     return LinkedNodeBuilder.catchClause(
       catchClause_body: node.body.accept(this),
-      catchClause_catchKeyword: _getToken(node.catchKeyword),
-      catchClause_comma: _getToken(node.comma),
       catchClause_exceptionParameter: node.exceptionParameter?.accept(this),
       catchClause_exceptionType: node.exceptionType?.accept(this),
-      catchClause_leftParenthesis: _getToken(node.leftParenthesis),
-      catchClause_onKeyword: _getToken(node.onKeyword),
-      catchClause_rightParenthesis: _getToken(node.rightParenthesis),
       catchClause_stackTraceParameter: node.stackTraceParameter?.accept(this),
     );
   }
 
   @override
   LinkedNodeBuilder visitClassDeclaration(ClassDeclaration node) {
-    var builder = LinkedNodeBuilder.classDeclaration(
-      classDeclaration_abstractKeyword: _getToken(node.abstractKeyword),
-      classDeclaration_classKeyword: _getToken(node.classKeyword),
-      classDeclaration_extendsClause: node.extendsClause?.accept(this),
-      classDeclaration_nativeClause: node.nativeClause?.accept(this),
-      classDeclaration_withClause: node.withClause?.accept(this),
-    );
-    _storeClassOrMixinDeclaration(builder, node);
-    return builder;
+    try {
+      timerAstBinaryWriterClass.start();
+
+      _hasConstConstructor = false;
+      for (var member in node.members) {
+        if (member is ConstructorDeclaration && member.constKeyword != null) {
+          _hasConstConstructor = true;
+          break;
+        }
+      }
+
+      var builder = LinkedNodeBuilder.classDeclaration(
+        classDeclaration_extendsClause: node.extendsClause?.accept(this),
+        classDeclaration_nativeClause: node.nativeClause?.accept(this),
+        classDeclaration_withClause: node.withClause?.accept(this),
+      );
+      builder.flags = AstBinaryFlags.encode(
+        isAbstract: node.abstractKeyword != null,
+      );
+      _storeClassOrMixinDeclaration(builder, node);
+      return builder;
+    } finally {
+      timerAstBinaryWriterClass.stop();
+    }
   }
 
   @override
   LinkedNodeBuilder visitClassTypeAlias(ClassTypeAlias node) {
-    var builder = LinkedNodeBuilder.classTypeAlias(
-      classTypeAlias_abstractKeyword: _getToken(node.abstractKeyword),
-      classTypeAlias_equals: _getToken(node.equals),
-      classTypeAlias_implementsClause: node.implementsClause?.accept(this),
-      classTypeAlias_superclass: node.superclass.accept(this),
-      classTypeAlias_typeParameters: node.typeParameters?.accept(this),
-      classTypeAlias_withClause: node.withClause.accept(this),
-    );
-    _storeTypeAlias(builder, node);
-    _storeIsSimpleBounded(builder, node);
-    return builder;
+    timerAstBinaryWriterClass.start();
+    try {
+      var builder = LinkedNodeBuilder.classTypeAlias(
+        classTypeAlias_implementsClause: node.implementsClause?.accept(this),
+        classTypeAlias_superclass: node.superclass.accept(this),
+        classTypeAlias_typeParameters: node.typeParameters?.accept(this),
+        classTypeAlias_withClause: node.withClause.accept(this),
+      );
+      builder.flags = AstBinaryFlags.encode(
+        isAbstract: node.abstractKeyword != null,
+      );
+      _storeTypeAlias(builder, node);
+      _storeIsSimpleBounded(builder, node);
+      return builder;
+    } finally {
+      timerAstBinaryWriterClass.stop();
+    }
   }
 
   @override
@@ -227,29 +247,44 @@
     }
 
     return LinkedNodeBuilder.comment(
-      comment_tokens: _getTokens(node.tokens),
+      comment_tokens: node.tokens.map((t) => t.lexeme).toList(),
       comment_type: type,
+      // TODO(scheglov) restore
+//      comment_references: _writeNodeList(node.references),
     );
   }
 
   @override
+  LinkedNodeBuilder visitCommentReference(CommentReference node) {
+//    var identifier = node.identifier;
+//    _tokensWriter.writeTokens(
+//      node.newKeyword ?? identifier.beginToken,
+//      identifier.endToken,
+//    );
+//
+//    return LinkedNodeBuilder.commentReference(
+//      commentReference_identifier: identifier.accept(this),
+//      commentReference_newKeyword: _getToken(node.newKeyword),
+//    );
+    return null;
+  }
+
+  @override
   LinkedNodeBuilder visitCompilationUnit(CompilationUnit node) {
-    return LinkedNodeBuilder.compilationUnit(
-      compilationUnit_beginToken: _getToken(node.beginToken),
+    var builder = LinkedNodeBuilder.compilationUnit(
       compilationUnit_declarations: _writeNodeList(node.declarations),
       compilationUnit_directives: _writeNodeList(node.directives),
-      compilationUnit_endToken: _getToken(node.endToken),
       compilationUnit_scriptTag: node.scriptTag?.accept(this),
+      informativeId: getInformativeId(node),
     );
+    return builder;
   }
 
   @override
   LinkedNodeBuilder visitConditionalExpression(ConditionalExpression node) {
     var builder = LinkedNodeBuilder.conditionalExpression(
-      conditionalExpression_colon: _getToken(node.colon),
       conditionalExpression_condition: node.condition.accept(this),
       conditionalExpression_elseExpression: node.elseExpression.accept(this),
-      conditionalExpression_question: _getToken(node.question),
       conditionalExpression_thenExpression: node.thenExpression.accept(this),
     );
     _storeExpression(builder, node);
@@ -258,35 +293,37 @@
 
   @override
   LinkedNodeBuilder visitConfiguration(Configuration node) {
-    return LinkedNodeBuilder.configuration(
-      configuration_equalToken: _getToken(node.equalToken),
-      configuration_ifKeyword: _getToken(node.ifKeyword),
-      configuration_leftParenthesis: _getToken(node.leftParenthesis),
+    var builder = LinkedNodeBuilder.configuration(
       configuration_name: node.name?.accept(this),
-      configuration_rightParenthesis: _getToken(node.rightParenthesis),
       configuration_value: node.value?.accept(this),
       configuration_uri: node.uri?.accept(this),
     );
+    builder.flags = AstBinaryFlags.encode(
+      hasEqual: node.equalToken != null,
+    );
+    return builder;
   }
 
   @override
   LinkedNodeBuilder visitConstructorDeclaration(ConstructorDeclaration node) {
     var builder = LinkedNodeBuilder.constructorDeclaration(
-      constructorDeclaration_body: node.body?.accept(this),
-      constructorDeclaration_constKeyword: _getToken(node.constKeyword),
-      constructorDeclaration_externalKeyword: _getToken(node.externalKeyword),
-      constructorDeclaration_factoryKeyword: _getToken(node.factoryKeyword),
       constructorDeclaration_initializers: _writeNodeList(node.initializers),
-      constructorDeclaration_name: node.name?.accept(this),
       constructorDeclaration_parameters: node.parameters.accept(this),
-      constructorDeclaration_period: _getToken(node.period),
       constructorDeclaration_redirectedConstructor:
           node.redirectedConstructor?.accept(this),
       constructorDeclaration_returnType: node.returnType.accept(this),
-      constructorDeclaration_separator: _getToken(node.separator),
+      informativeId: getInformativeId(node),
     );
+    builder.flags = AstBinaryFlags.encode(
+      hasSeparatorColon: node.separator?.type == TokenType.COLON,
+      hasSeparatorEquals: node.separator?.type == TokenType.EQ,
+      isAbstract: node.body is EmptyFunctionBody,
+      isConst: node.constKeyword != null,
+      isExternal: node.externalKeyword != null,
+      isFactory: node.factoryKeyword != null,
+    );
+    builder.name = node.name?.name;
     _storeClassMember(builder, node);
-    _storeCodeOffsetLength(builder, node);
     return builder;
   }
 
@@ -294,11 +331,11 @@
   LinkedNodeBuilder visitConstructorFieldInitializer(
       ConstructorFieldInitializer node) {
     var builder = LinkedNodeBuilder.constructorFieldInitializer(
-      constructorFieldInitializer_equals: _getToken(node.equals),
       constructorFieldInitializer_expression: node.expression.accept(this),
       constructorFieldInitializer_fieldName: node.fieldName.accept(this),
-      constructorFieldInitializer_period: _getToken(node.period),
-      constructorFieldInitializer_thisKeyword: _getToken(node.thisKeyword),
+    );
+    builder.flags = AstBinaryFlags.encode(
+      hasThis: node.thisKeyword != null,
     );
     _storeConstructorInitializer(builder, node);
     return builder;
@@ -311,7 +348,6 @@
       constructorName_element: elementComponents.rawElement,
       constructorName_elementType: elementComponents.definingType,
       constructorName_name: node.name?.accept(this),
-      constructorName_period: _getToken(node.period),
       constructorName_type: node.type.accept(this),
     );
   }
@@ -319,9 +355,7 @@
   @override
   LinkedNodeBuilder visitContinueStatement(ContinueStatement node) {
     var builder = LinkedNodeBuilder.continueStatement(
-      continueStatement_continueKeyword: _getToken(node.continueKeyword),
       continueStatement_label: node.label?.accept(this),
-      continueStatement_semicolon: _getToken(node.semicolon),
     );
     _storeStatement(builder, node);
     return builder;
@@ -331,22 +365,33 @@
   LinkedNodeBuilder visitDeclaredIdentifier(DeclaredIdentifier node) {
     var builder = LinkedNodeBuilder.declaredIdentifier(
       declaredIdentifier_identifier: node.identifier.accept(this),
-      declaredIdentifier_keyword: _getToken(node.keyword),
       declaredIdentifier_type: node.type?.accept(this),
     );
+    builder.flags = AstBinaryFlags.encode(
+      isConst: node.keyword?.keyword == Keyword.CONST,
+      isFinal: node.keyword?.keyword == Keyword.FINAL,
+      isVar: node.keyword?.keyword == Keyword.VAR,
+    );
     _storeDeclaration(builder, node);
     return builder;
   }
 
   @override
   LinkedNodeBuilder visitDefaultFormalParameter(DefaultFormalParameter node) {
+    var defaultValue = node.defaultValue;
+    if (!_isSerializableExpression(defaultValue)) {
+      defaultValue = null;
+    }
+
     var builder = LinkedNodeBuilder.defaultFormalParameter(
-      defaultFormalParameter_defaultValue: node.defaultValue?.accept(this),
-      defaultFormalParameter_isNamed: node.isNamed,
+      defaultFormalParameter_defaultValue: defaultValue?.accept(this),
+      defaultFormalParameter_kind: _toParameterKind(node),
       defaultFormalParameter_parameter: node.parameter.accept(this),
-      defaultFormalParameter_separator: _getToken(node.separator),
+      informativeId: getInformativeId(node),
     );
-    _storeCodeOffsetLength(builder, node);
+    builder.flags = AstBinaryFlags.encode(
+      hasInitializer: node.defaultValue != null,
+    );
     return builder;
   }
 
@@ -355,11 +400,6 @@
     return LinkedNodeBuilder.doStatement(
       doStatement_body: node.body.accept(this),
       doStatement_condition: node.condition.accept(this),
-      doStatement_doKeyword: _getToken(node.doKeyword),
-      doStatement_leftParenthesis: _getToken(node.leftParenthesis),
-      doStatement_rightParenthesis: _getToken(node.rightParenthesis),
-      doStatement_semicolon: _getToken(node.semicolon),
-      doStatement_whileKeyword: _getToken(node.whileKeyword),
     );
   }
 
@@ -373,33 +413,28 @@
   @override
   LinkedNodeBuilder visitDoubleLiteral(DoubleLiteral node) {
     return LinkedNodeBuilder.doubleLiteral(
-      doubleLiteral_literal: _getToken(node.literal),
       doubleLiteral_value: node.value,
-      expression_type: _writeType(node.staticType),
     );
   }
 
   @override
   LinkedNodeBuilder visitEmptyFunctionBody(EmptyFunctionBody node) {
-    var builder = LinkedNodeBuilder.emptyFunctionBody(
-      emptyFunctionBody_semicolon: _getToken(node.semicolon),
-    );
+    var builder = LinkedNodeBuilder.emptyFunctionBody();
     _storeFunctionBody(builder, node);
     return builder;
   }
 
   @override
   LinkedNodeBuilder visitEmptyStatement(EmptyStatement node) {
-    return LinkedNodeBuilder.emptyStatement(
-      emptyStatement_semicolon: _getToken(node.semicolon),
-    );
+    return LinkedNodeBuilder.emptyStatement();
   }
 
   @override
   LinkedNodeBuilder visitEnumConstantDeclaration(EnumConstantDeclaration node) {
     var builder = LinkedNodeBuilder.enumConstantDeclaration(
-      enumConstantDeclaration_name: node.name.accept(this),
+      informativeId: getInformativeId(node),
     );
+    builder..name = node.name.name;
     _storeDeclaration(builder, node);
     return builder;
   }
@@ -408,9 +443,6 @@
   LinkedNodeBuilder visitEnumDeclaration(EnumDeclaration node) {
     var builder = LinkedNodeBuilder.enumDeclaration(
       enumDeclaration_constants: _writeNodeList(node.constants),
-      enumDeclaration_enumKeyword: _getToken(node.enumKeyword),
-      enumDeclaration_leftBracket: _getToken(node.leftBracket),
-      enumDeclaration_rightBracket: _getToken(node.rightBracket),
     );
     _storeNamedCompilationUnitMember(builder, node);
     return builder;
@@ -418,55 +450,59 @@
 
   @override
   LinkedNodeBuilder visitExportDirective(ExportDirective node) {
-    var builder = LinkedNodeBuilder.exportDirective();
-    _storeNamespaceDirective(builder, node);
-    return builder;
+    timerAstBinaryWriterDirective.start();
+    try {
+      var builder = LinkedNodeBuilder.exportDirective();
+      _storeNamespaceDirective(builder, node);
+      return builder;
+    } finally {
+      timerAstBinaryWriterDirective.stop();
+    }
   }
 
   @override
   LinkedNodeBuilder visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    return LinkedNodeBuilder.expressionFunctionBody(
-      expressionFunctionBody_arrow: _getToken(node.functionDefinition),
-      expressionFunctionBody_expression: node.expression.accept(this),
-      expressionFunctionBody_keyword: _getToken(node.keyword),
-      expressionFunctionBody_semicolon: _getToken(node.semicolon),
-    );
+    timerAstBinaryWriterFunctionBody.start();
+    try {
+      var builder = LinkedNodeBuilder.expressionFunctionBody(
+        expressionFunctionBody_expression: node.expression.accept(this),
+      );
+      builder.flags = AstBinaryFlags.encode(
+        isAsync: node.keyword?.keyword == Keyword.ASYNC,
+        isSync: node.keyword?.keyword == Keyword.SYNC,
+      );
+      return builder;
+    } finally {
+      timerAstBinaryWriterFunctionBody.stop();
+    }
   }
 
   @override
   LinkedNodeBuilder visitExpressionStatement(ExpressionStatement node) {
     return LinkedNodeBuilder.expressionStatement(
       expressionStatement_expression: node.expression.accept(this),
-      expressionStatement_semicolon: _getToken(node.semicolon),
     );
   }
 
   @override
   LinkedNodeBuilder visitExtendsClause(ExtendsClause node) {
     return LinkedNodeBuilder.extendsClause(
-      extendsClause_extendsKeyword: _getToken(node.extendsKeyword),
       extendsClause_superclass: node.superclass.accept(this),
     );
   }
 
   @override
   LinkedNodeBuilder visitFieldDeclaration(FieldDeclaration node) {
-    _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder(
-      isCovariant: node.covariantKeyword != null,
-      isStatic: node.isStatic,
-    );
-
     var builder = LinkedNodeBuilder.fieldDeclaration(
-      fieldDeclaration_covariantKeyword: _getToken(node.covariantKeyword),
       fieldDeclaration_fields: node.fields.accept(this),
-      fieldDeclaration_semicolon: _getToken(node.semicolon),
-      fieldDeclaration_staticKeyword: _getToken(node.staticKeyword),
+      informativeId: getInformativeId(node),
+    );
+    builder.flags = AstBinaryFlags.encode(
+      isCovariant: node.covariantKeyword != null,
+      isStatic: node.staticKeyword != null,
     );
     _storeClassMember(builder, node);
 
-    _variablesDeclaration.comment = builder.annotatedNode_comment;
-    _variablesDeclaration = null;
-
     return builder;
   }
 
@@ -474,13 +510,10 @@
   LinkedNodeBuilder visitFieldFormalParameter(FieldFormalParameter node) {
     var builder = LinkedNodeBuilder.fieldFormalParameter(
       fieldFormalParameter_formalParameters: node.parameters?.accept(this),
-      fieldFormalParameter_keyword: _getToken(node.keyword),
-      fieldFormalParameter_period: _getToken(node.period),
-      fieldFormalParameter_thisKeyword: _getToken(node.thisKeyword),
       fieldFormalParameter_type: node.type?.accept(this),
       fieldFormalParameter_typeParameters: node.typeParameters?.accept(this),
     );
-    _storeNormalFormalParameter(builder, node);
+    _storeNormalFormalParameter(builder, node, node.keyword);
     return builder;
   }
 
@@ -515,13 +548,16 @@
 
   @override
   LinkedNodeBuilder visitFormalParameterList(FormalParameterList node) {
-    return LinkedNodeBuilder.formalParameterList(
-      formalParameterList_leftDelimiter: _getToken(node.leftDelimiter),
-      formalParameterList_leftParenthesis: _getToken(node.leftParenthesis),
+    var builder = LinkedNodeBuilder.formalParameterList(
       formalParameterList_parameters: _writeNodeList(node.parameters),
-      formalParameterList_rightDelimiter: _getToken(node.rightDelimiter),
-      formalParameterList_rightParenthesis: _getToken(node.rightParenthesis),
     );
+    builder.flags = AstBinaryFlags.encode(
+      isDelimiterCurly:
+          node.leftDelimiter?.type == TokenType.OPEN_CURLY_BRACKET,
+      isDelimiterSquare:
+          node.leftDelimiter?.type == TokenType.OPEN_SQUARE_BRACKET,
+    );
+    return builder;
   }
 
   @override
@@ -555,11 +591,14 @@
   @override
   LinkedNodeBuilder visitFunctionDeclaration(FunctionDeclaration node) {
     var builder = LinkedNodeBuilder.functionDeclaration(
-      functionDeclaration_externalKeyword: _getToken(node.externalKeyword),
+      functionDeclaration_returnType: node.returnType?.accept(this),
       functionDeclaration_functionExpression:
           node.functionExpression?.accept(this),
-      functionDeclaration_propertyKeyword: _getToken(node.propertyKeyword),
-      functionDeclaration_returnType: node.returnType?.accept(this),
+    );
+    builder.flags = AstBinaryFlags.encode(
+      isExternal: node.externalKeyword != null,
+      isGet: node.isGetter,
+      isSet: node.isSetter,
     );
     _storeNamedCompilationUnitMember(builder, node);
     _writeActualReturnType(builder, node);
@@ -577,11 +616,20 @@
 
   @override
   LinkedNodeBuilder visitFunctionExpression(FunctionExpression node) {
-    return LinkedNodeBuilder.functionExpression(
-      functionExpression_body: node.body?.accept(this),
-      functionExpression_formalParameters: node.parameters?.accept(this),
+    var bodyToStore = node.body;
+    if (node.parent.parent is CompilationUnit) {
+      bodyToStore = null;
+    }
+    var builder = LinkedNodeBuilder.functionExpression(
       functionExpression_typeParameters: node.typeParameters?.accept(this),
+      functionExpression_formalParameters: node.parameters?.accept(this),
+      functionExpression_body: bodyToStore?.accept(this),
     );
+    builder.flags = AstBinaryFlags.encode(
+      isAsync: node.body?.isAsynchronous ?? false,
+      isGenerator: node.body?.isGenerator ?? false,
+    );
+    return builder;
   }
 
   @override
@@ -596,15 +644,22 @@
 
   @override
   LinkedNodeBuilder visitFunctionTypeAlias(FunctionTypeAlias node) {
-    var builder = LinkedNodeBuilder.functionTypeAlias(
-      functionTypeAlias_formalParameters: node.parameters.accept(this),
-      functionTypeAlias_returnType: node.returnType?.accept(this),
-      functionTypeAlias_typeParameters: node.typeParameters?.accept(this),
-    );
-    _storeTypeAlias(builder, node);
-    _writeActualReturnType(builder, node);
-    _storeIsSimpleBounded(builder, node);
-    return builder;
+    timerAstBinaryWriterTypedef.start();
+    try {
+      var builder = LinkedNodeBuilder.functionTypeAlias(
+        functionTypeAlias_formalParameters: node.parameters.accept(this),
+        functionTypeAlias_returnType: node.returnType?.accept(this),
+        functionTypeAlias_typeParameters: node.typeParameters?.accept(this),
+        typeAlias_hasSelfReference:
+            LazyFunctionTypeAlias.getHasSelfReference(node),
+      );
+      _storeTypeAlias(builder, node);
+      _writeActualReturnType(builder, node);
+      _storeIsSimpleBounded(builder, node);
+      return builder;
+    } finally {
+      timerAstBinaryWriterTypedef.stop();
+    }
   }
 
   @override
@@ -617,52 +672,63 @@
       functionTypedFormalParameter_typeParameters:
           node.typeParameters?.accept(this),
     );
-    _storeNormalFormalParameter(builder, node);
+    _storeNormalFormalParameter(builder, node, null);
     return builder;
   }
 
   @override
   LinkedNodeBuilder visitGenericFunctionType(GenericFunctionType node) {
+    var id = LazyAst.getGenericFunctionTypeId(node);
+    assert(id != null);
+
     var builder = LinkedNodeBuilder.genericFunctionType(
-      genericFunctionType_formalParameters: node.parameters.accept(this),
-      genericFunctionType_functionKeyword: _getToken(node.functionKeyword),
-      genericFunctionType_question: _getToken(node.question),
+      genericFunctionType_id: id,
       genericFunctionType_returnType: node.returnType?.accept(this),
-      genericFunctionType_type: _writeType(node.type),
       genericFunctionType_typeParameters: node.typeParameters?.accept(this),
+      genericFunctionType_formalParameters: node.parameters.accept(this),
+      genericFunctionType_type: _writeType(node.type),
+    );
+    builder.flags = AstBinaryFlags.encode(
+      hasQuestion: node.question != null,
     );
     _writeActualReturnType(builder, node);
+
     return builder;
   }
 
   @override
   LinkedNodeBuilder visitGenericTypeAlias(GenericTypeAlias node) {
-    var builder = LinkedNodeBuilder.genericTypeAlias(
-      genericTypeAlias_equals: _getToken(node.equals),
-      genericTypeAlias_functionType: node.functionType.accept(this),
-      genericTypeAlias_typeParameters: node.typeParameters?.accept(this),
-    );
-    _storeTypeAlias(builder, node);
-    _storeIsSimpleBounded(builder, node);
-    return builder;
+    timerAstBinaryWriterTypedef.start();
+    try {
+      var builder = LinkedNodeBuilder.genericTypeAlias(
+        genericTypeAlias_typeParameters: node.typeParameters?.accept(this),
+        genericTypeAlias_functionType: node.functionType?.accept(this),
+        typeAlias_hasSelfReference:
+            LazyGenericTypeAlias.getHasSelfReference(node),
+      );
+      _storeTypeAlias(builder, node);
+      _storeIsSimpleBounded(builder, node);
+      return builder;
+    } finally {
+      timerAstBinaryWriterTypedef.stop();
+    }
   }
 
   @override
   LinkedNodeBuilder visitHideCombinator(HideCombinator node) {
     var builder = LinkedNodeBuilder.hideCombinator(
-      hideCombinator_hiddenNames: _writeNodeList(node.hiddenNames),
+      names: node.hiddenNames.map((id) => id.name).toList(),
     );
-    _storeCombinator(builder, node);
     return builder;
   }
 
   @override
   LinkedNodeBuilder visitIfElement(IfElement node) {
     var builder = LinkedNodeBuilder.ifElement(
+      ifMixin_condition: node.condition.accept(this),
       ifElement_elseElement: node.elseElement?.accept(this),
       ifElement_thenElement: node.thenElement.accept(this),
     );
-    _storeIfMixin(builder, node as IfElementImpl);
     return builder;
   }
 
@@ -670,72 +736,78 @@
   LinkedNodeBuilder visitIfStatement(IfStatement node) {
     var builder = LinkedNodeBuilder.ifStatement(
       ifMixin_condition: node.condition.accept(this),
-      ifMixin_elseKeyword: _getToken(node.elseKeyword),
       ifStatement_elseStatement: node.elseStatement?.accept(this),
-      ifMixin_ifKeyword: _getToken(node.ifKeyword),
-      ifMixin_leftParenthesis: _getToken(node.leftParenthesis),
-      ifMixin_rightParenthesis: _getToken(node.rightParenthesis),
       ifStatement_thenStatement: node.thenStatement.accept(this),
     );
-    _storeIfMixin(builder, node as IfStatementImpl);
     return builder;
   }
 
   @override
   LinkedNodeBuilder visitImplementsClause(ImplementsClause node) {
     return LinkedNodeBuilder.implementsClause(
-      implementsClause_implementsKeyword: _getToken(node.implementsKeyword),
       implementsClause_interfaces: _writeNodeList(node.interfaces),
     );
   }
 
   @override
   LinkedNodeBuilder visitImportDirective(ImportDirective node) {
-    var builder = LinkedNodeBuilder.importDirective(
-      importDirective_asKeyword: _getToken(node.asKeyword),
-      importDirective_deferredKeyword: _getToken(node.deferredKeyword),
-      importDirective_prefix: node.prefix?.accept(this),
-    );
-    _storeNamespaceDirective(builder, node);
-    return builder;
+    timerAstBinaryWriterDirective.start();
+    try {
+      var builder = LinkedNodeBuilder.importDirective(
+        importDirective_prefix: node.prefix?.name,
+        importDirective_prefixOffset: node.prefix?.offset ?? 0,
+      );
+      builder.flags = AstBinaryFlags.encode(
+        isDeferred: node.deferredKeyword != null,
+      );
+      _storeNamespaceDirective(builder, node);
+      return builder;
+    } finally {
+      timerAstBinaryWriterDirective.stop();
+    }
   }
 
   @override
   LinkedNodeBuilder visitIndexExpression(IndexExpression node) {
     var elementComponents = _componentsOfElement(node.staticElement);
-    return LinkedNodeBuilder.indexExpression(
+    var builder = LinkedNodeBuilder.indexExpression(
       indexExpression_element: elementComponents.rawElement,
       indexExpression_elementType: elementComponents.definingType,
       indexExpression_index: node.index.accept(this),
-      indexExpression_leftBracket: _getToken(node.leftBracket),
-      indexExpression_period: _getToken(node.period),
-      indexExpression_rightBracket: _getToken(node.rightBracket),
       indexExpression_target: node.target?.accept(this),
       expression_type: _writeType(node.staticType),
     );
+    builder.flags = AstBinaryFlags.encode(
+      hasPeriod: node.period != null,
+    );
+    return builder;
   }
 
   @override
   LinkedNodeBuilder visitInstanceCreationExpression(
       InstanceCreationExpression node) {
     InstanceCreationExpressionImpl nodeImpl = node;
-    return LinkedNodeBuilder.instanceCreationExpression(
-      instanceCreationExpression_arguments: node.argumentList.accept(this),
+    var builder = LinkedNodeBuilder.instanceCreationExpression(
+      instanceCreationExpression_arguments: _writeNodeList(
+        node.argumentList.arguments,
+      ),
       instanceCreationExpression_constructorName:
           node.constructorName.accept(this),
-      instanceCreationExpression_keyword: _getToken(node.keyword),
       instanceCreationExpression_typeArguments:
           nodeImpl.typeArguments?.accept(this),
       expression_type: _writeType(node.staticType),
     );
+    builder.flags = AstBinaryFlags.encode(
+      isConst: node.keyword?.type == Keyword.CONST,
+      isNew: node.keyword?.type == Keyword.NEW,
+    );
+    return builder;
   }
 
   @override
   LinkedNodeBuilder visitIntegerLiteral(IntegerLiteral node) {
     return LinkedNodeBuilder.integerLiteral(
-      integerLiteral_literal: _getToken(node.literal),
       integerLiteral_value: node.value,
-      expression_type: _writeType(node.staticType),
     );
   }
 
@@ -743,15 +815,15 @@
   LinkedNodeBuilder visitInterpolationExpression(InterpolationExpression node) {
     return LinkedNodeBuilder.interpolationExpression(
       interpolationExpression_expression: node.expression.accept(this),
-      interpolationExpression_leftBracket: _getToken(node.leftBracket),
-      interpolationExpression_rightBracket: _getToken(node.rightBracket),
-    );
+    )..flags = AstBinaryFlags.encode(
+        isStringInterpolationIdentifier:
+            node.leftBracket.type == TokenType.STRING_INTERPOLATION_IDENTIFIER,
+      );
   }
 
   @override
   LinkedNodeBuilder visitInterpolationString(InterpolationString node) {
     return LinkedNodeBuilder.interpolationString(
-      interpolationString_token: _getToken(node.contents),
       interpolationString_value: node.value,
     );
   }
@@ -760,11 +832,11 @@
   LinkedNodeBuilder visitIsExpression(IsExpression node) {
     var builder = LinkedNodeBuilder.isExpression(
       isExpression_expression: node.expression.accept(this),
-      isExpression_isOperator: _getToken(node.isOperator),
-      isExpression_notOperator: _getToken(node.notOperator),
       isExpression_type: node.type.accept(this),
     );
-    _storeExpression(builder, node);
+    builder.flags = AstBinaryFlags.encode(
+      hasNot: node.notOperator != null,
+    );
     return builder;
   }
 
@@ -772,7 +844,6 @@
   LinkedNodeBuilder visitLabel(Label node) {
     return LinkedNodeBuilder.label(
       label_label: node.label.accept(this),
-      label_colon: _getToken(node.colon),
     );
   }
 
@@ -786,12 +857,17 @@
 
   @override
   LinkedNodeBuilder visitLibraryDirective(LibraryDirective node) {
-    var builder = LinkedNodeBuilder.libraryDirective(
-      libraryDirective_name: node.name.accept(this),
-      directive_semicolon: _getToken(node.semicolon),
-    );
-    _storeDirective(builder, node);
-    return builder;
+    timerAstBinaryWriterDirective.start();
+    try {
+      var builder = LinkedNodeBuilder.libraryDirective(
+        informativeId: getInformativeId(node),
+        libraryDirective_name: node.name.accept(this),
+      );
+      _storeDirective(builder, node);
+      return builder;
+    } finally {
+      timerAstBinaryWriterDirective.stop();
+    }
   }
 
   @override
@@ -805,8 +881,6 @@
   LinkedNodeBuilder visitListLiteral(ListLiteral node) {
     var builder = LinkedNodeBuilder.listLiteral(
       listLiteral_elements: _writeNodeList(node.elements),
-      listLiteral_leftBracket: _getToken(node.leftBracket),
-      listLiteral_rightBracket: _getToken(node.rightBracket),
     );
     _storeTypedLiteral(builder, node);
     return builder;
@@ -816,7 +890,6 @@
   LinkedNodeBuilder visitMapLiteralEntry(MapLiteralEntry node) {
     return LinkedNodeBuilder.mapLiteralEntry(
       mapLiteralEntry_key: node.key.accept(this),
-      mapLiteralEntry_separator: _getToken(node.separator),
       mapLiteralEntry_value: node.value.accept(this),
     );
   }
@@ -824,18 +897,23 @@
   @override
   LinkedNodeBuilder visitMethodDeclaration(MethodDeclaration node) {
     var builder = LinkedNodeBuilder.methodDeclaration(
-      methodDeclaration_body: node.body?.accept(this),
-      methodDeclaration_externalKeyword: _getToken(node.externalKeyword),
-      methodDeclaration_formalParameters: node.parameters?.accept(this),
-      methodDeclaration_modifierKeyword: _getToken(node.modifierKeyword),
-      methodDeclaration_name: node.name.accept(this),
-      methodDeclaration_operatorKeyword: _getToken(node.operatorKeyword),
-      methodDeclaration_propertyKeyword: _getToken(node.propertyKeyword),
       methodDeclaration_returnType: node.returnType?.accept(this),
       methodDeclaration_typeParameters: node.typeParameters?.accept(this),
+      methodDeclaration_formalParameters: node.parameters?.accept(this),
+    );
+    builder.name = node.name.name;
+    builder.flags = AstBinaryFlags.encode(
+      isAbstract: node.body is EmptyFunctionBody,
+      isAsync: node.body?.isAsynchronous ?? false,
+      isExternal: node.externalKeyword != null,
+      isGenerator: node.body?.isGenerator ?? false,
+      isGet: node.isGetter,
+      isOperator: node.operatorKeyword != null,
+      isSet: node.isSetter,
+      isStatic: node.isStatic,
     );
     _storeClassMember(builder, node);
-    _storeCodeOffsetLength(builder, node);
+    _storeInformativeId(builder, node);
     _writeActualReturnType(builder, node);
     return builder;
   }
@@ -844,21 +922,29 @@
   LinkedNodeBuilder visitMethodInvocation(MethodInvocation node) {
     var builder = LinkedNodeBuilder.methodInvocation(
       methodInvocation_methodName: node.methodName?.accept(this),
-      methodInvocation_operator: _getToken(node.operator),
       methodInvocation_target: node.target?.accept(this),
     );
+    builder.flags = AstBinaryFlags.encode(
+      hasPeriod: node.operator?.type == TokenType.PERIOD,
+      hasPeriod2: node.operator?.type == TokenType.PERIOD_PERIOD,
+    );
     _storeInvocationExpression(builder, node);
     return builder;
   }
 
   @override
   LinkedNodeBuilder visitMixinDeclaration(MixinDeclaration node) {
-    var builder = LinkedNodeBuilder.mixinDeclaration(
-      mixinDeclaration_mixinKeyword: _getToken(node.mixinKeyword),
-      mixinDeclaration_onClause: node.onClause?.accept(this),
-    );
-    _storeClassOrMixinDeclaration(builder, node);
-    return builder;
+    timerAstBinaryWriterMixin.start();
+    try {
+      var builder = LinkedNodeBuilder.mixinDeclaration(
+        mixinDeclaration_onClause: node.onClause?.accept(this),
+      );
+      _storeClassOrMixinDeclaration(builder, node);
+      LazyMixinDeclaration.get(node).put(builder);
+      return builder;
+    } finally {
+      timerAstBinaryWriterMixin.stop();
+    }
   }
 
   @override
@@ -872,7 +958,6 @@
   @override
   LinkedNodeBuilder visitNativeClause(NativeClause node) {
     return LinkedNodeBuilder.nativeClause(
-      nativeClause_nativeKeyword: _getToken(node.nativeKeyword),
       nativeClause_name: node.name.accept(this),
     );
   }
@@ -880,25 +965,18 @@
   @override
   LinkedNodeBuilder visitNativeFunctionBody(NativeFunctionBody node) {
     return LinkedNodeBuilder.nativeFunctionBody(
-      nativeFunctionBody_nativeKeyword: _getToken(node.nativeKeyword),
-      nativeFunctionBody_semicolon: _getToken(node.semicolon),
       nativeFunctionBody_stringLiteral: node.stringLiteral?.accept(this),
     );
   }
 
   @override
   LinkedNodeBuilder visitNullLiteral(NullLiteral node) {
-    var builder = LinkedNodeBuilder.nullLiteral(
-      nullLiteral_literal: _getToken(node.literal),
-    );
-    _storeExpression(builder, node);
-    return builder;
+    return LinkedNodeBuilder.nullLiteral();
   }
 
   @override
   LinkedNodeBuilder visitOnClause(OnClause node) {
     return LinkedNodeBuilder.onClause(
-      onClause_onKeyword: _getToken(node.onKeyword),
       onClause_superclassConstraints:
           _writeNodeList(node.superclassConstraints),
     );
@@ -908,9 +986,6 @@
   LinkedNodeBuilder visitParenthesizedExpression(ParenthesizedExpression node) {
     var builder = LinkedNodeBuilder.parenthesizedExpression(
       parenthesizedExpression_expression: node.expression.accept(this),
-      parenthesizedExpression_leftParenthesis: _getToken(node.leftParenthesis),
-      parenthesizedExpression_rightParenthesis:
-          _getToken(node.rightParenthesis),
     );
     _storeExpression(builder, node);
     return builder;
@@ -918,23 +993,29 @@
 
   @override
   LinkedNodeBuilder visitPartDirective(PartDirective node) {
-    var builder = LinkedNodeBuilder.partDirective(
-      directive_semicolon: _getToken(node.semicolon),
-    );
-    _storeUriBasedDirective(builder, node);
-    return builder;
+    timerAstBinaryWriterDirective.start();
+    try {
+      var builder = LinkedNodeBuilder.partDirective();
+      _storeUriBasedDirective(builder, node);
+      return builder;
+    } finally {
+      timerAstBinaryWriterDirective.stop();
+    }
   }
 
   @override
   LinkedNodeBuilder visitPartOfDirective(PartOfDirective node) {
-    var builder = LinkedNodeBuilder.partOfDirective(
-      partOfDirective_libraryName: node.libraryName?.accept(this),
-      partOfDirective_ofKeyword: _getToken(node.ofKeyword),
-      directive_semicolon: _getToken(node.semicolon),
-      partOfDirective_uri: node.uri?.accept(this),
-    );
-    _storeDirective(builder, node);
-    return builder;
+    timerAstBinaryWriterDirective.start();
+    try {
+      var builder = LinkedNodeBuilder.partOfDirective(
+        partOfDirective_libraryName: node.libraryName?.accept(this),
+        partOfDirective_uri: node.uri?.accept(this),
+      );
+      _storeDirective(builder, node);
+      return builder;
+    } finally {
+      timerAstBinaryWriterDirective.stop();
+    }
   }
 
   @override
@@ -945,7 +1026,9 @@
       postfixExpression_element: elementComponents.rawElement,
       postfixExpression_elementType: elementComponents.definingType,
       postfixExpression_operand: node.operand.accept(this),
-      postfixExpression_operator: _getToken(node.operator),
+      postfixExpression_operator: TokensWriter.astToBinaryTokenType(
+        node.operator.type,
+      ),
     );
   }
 
@@ -953,7 +1036,6 @@
   LinkedNodeBuilder visitPrefixedIdentifier(PrefixedIdentifier node) {
     return LinkedNodeBuilder.prefixedIdentifier(
       prefixedIdentifier_identifier: node.identifier.accept(this),
-      prefixedIdentifier_period: _getToken(node.period),
       prefixedIdentifier_prefix: node.prefix.accept(this),
       expression_type: _writeType(node.staticType),
     );
@@ -967,14 +1049,18 @@
       prefixExpression_element: elementComponents.rawElement,
       prefixExpression_elementType: elementComponents.definingType,
       prefixExpression_operand: node.operand.accept(this),
-      prefixExpression_operator: _getToken(node.operator),
+      prefixExpression_operator: TokensWriter.astToBinaryTokenType(
+        node.operator.type,
+      ),
     );
   }
 
   @override
   LinkedNodeBuilder visitPropertyAccess(PropertyAccess node) {
     var builder = LinkedNodeBuilder.propertyAccess(
-      propertyAccess_operator: _getToken(node.operator),
+      propertyAccess_operator: TokensWriter.astToBinaryTokenType(
+        node.operator.type,
+      ),
       propertyAccess_propertyName: node.propertyName.accept(this),
       propertyAccess_target: node.target?.accept(this),
     );
@@ -994,8 +1080,9 @@
       redirectingConstructorInvocation_element: elementComponents.rawElement,
       redirectingConstructorInvocation_elementType:
           elementComponents.definingType,
-      redirectingConstructorInvocation_period: _getToken(node.period),
-      redirectingConstructorInvocation_thisKeyword: _getToken(node.thisKeyword),
+    );
+    builder.flags = AstBinaryFlags.encode(
+      hasThis: node.thisKeyword != null,
     );
     _storeConstructorInitializer(builder, node);
     return builder;
@@ -1003,58 +1090,48 @@
 
   @override
   LinkedNodeBuilder visitRethrowExpression(RethrowExpression node) {
-    var builder = LinkedNodeBuilder.rethrowExpression(
-      rethrowExpression_rethrowKeyword: _getToken(node.rethrowKeyword),
+    return LinkedNodeBuilder.rethrowExpression(
+      expression_type: _writeType(node.staticType),
     );
-    _storeExpression(builder, node);
-    return builder;
   }
 
   @override
   LinkedNodeBuilder visitReturnStatement(ReturnStatement node) {
     return LinkedNodeBuilder.returnStatement(
       returnStatement_expression: node.expression?.accept(this),
-      returnStatement_returnKeyword: _getToken(node.returnKeyword),
-      returnStatement_semicolon: _getToken(node.semicolon),
     );
   }
 
   @override
   LinkedNodeBuilder visitScriptTag(ScriptTag node) {
-    return LinkedNodeBuilder.scriptTag(
-      scriptTag_scriptTag: _getToken(node.scriptTag),
-    );
+    return null;
   }
 
   @override
   LinkedNodeBuilder visitSetOrMapLiteral(SetOrMapLiteral node) {
     var builder = LinkedNodeBuilder.setOrMapLiteral(
       setOrMapLiteral_elements: _writeNodeList(node.elements),
-      setOrMapLiteral_isMap: node.isMap,
-      setOrMapLiteral_isSet: node.isSet,
-      setOrMapLiteral_leftBracket: _getToken(node.leftBracket),
-      setOrMapLiteral_rightBracket: _getToken(node.rightBracket),
     );
-    _storeTypedLiteral(builder, node);
+    _storeTypedLiteral(builder, node, isMap: node.isMap, isSet: node.isSet);
     return builder;
   }
 
   @override
   LinkedNodeBuilder visitShowCombinator(ShowCombinator node) {
     var builder = LinkedNodeBuilder.showCombinator(
-      showCombinator_shownNames: _writeNodeList(node.shownNames),
+      names: node.shownNames.map((id) => id.name).toList(),
     );
-    _storeCombinator(builder, node);
     return builder;
   }
 
   @override
   LinkedNodeBuilder visitSimpleFormalParameter(SimpleFormalParameter node) {
     var builder = LinkedNodeBuilder.simpleFormalParameter(
-      simpleFormalParameter_keyword: _getToken(node.keyword),
       simpleFormalParameter_type: node.type?.accept(this),
     );
-    _storeNormalFormalParameter(builder, node);
+    builder.topLevelTypeInferenceError = LazyAst.getTypeInferenceError(node);
+    _storeNormalFormalParameter(builder, node, node.keyword);
+    _storeInheritsCovariant(builder, node);
     return builder;
   }
 
@@ -1069,21 +1146,23 @@
     }
 
     var elementComponents = _componentsOfElement(element);
-    return LinkedNodeBuilder.simpleIdentifier(
+    var builder = LinkedNodeBuilder.simpleIdentifier(
       simpleIdentifier_element: elementComponents.rawElement,
       simpleIdentifier_elementType: elementComponents.definingType,
-      simpleIdentifier_token: _getToken(node.token),
       expression_type: _writeType(node.staticType),
     );
+    builder.flags = AstBinaryFlags.encode(
+      isDeclaration: node is DeclaredSimpleIdentifier,
+    );
+    builder.name = node.name;
+    return builder;
   }
 
   @override
   LinkedNodeBuilder visitSimpleStringLiteral(SimpleStringLiteral node) {
     var builder = LinkedNodeBuilder.simpleStringLiteral(
-      simpleStringLiteral_token: _getToken(node.literal),
       simpleStringLiteral_value: node.value,
     );
-    _storeExpression(builder, node);
     return builder;
   }
 
@@ -1091,7 +1170,9 @@
   LinkedNodeBuilder visitSpreadElement(SpreadElement node) {
     return LinkedNodeBuilder.spreadElement(
       spreadElement_expression: node.expression.accept(this),
-      spreadElement_spreadOperator: _getToken(node.spreadOperator),
+      spreadElement_spreadOperator: TokensWriter.astToBinaryTokenType(
+        node.spreadOperator.type,
+      ),
     );
   }
 
@@ -1099,7 +1180,6 @@
   LinkedNodeBuilder visitStringInterpolation(StringInterpolation node) {
     return LinkedNodeBuilder.stringInterpolation(
       stringInterpolation_elements: _writeNodeList(node.elements),
-      expression_type: _writeType(node.staticType),
     );
   }
 
@@ -1113,8 +1193,6 @@
           node.constructorName?.accept(this),
       superConstructorInvocation_element: elementComponents.rawElement,
       superConstructorInvocation_elementType: elementComponents.definingType,
-      superConstructorInvocation_period: _getToken(node.period),
-      superConstructorInvocation_superKeyword: _getToken(node.superKeyword),
     );
     _storeConstructorInitializer(builder, node);
     return builder;
@@ -1122,9 +1200,7 @@
 
   @override
   LinkedNodeBuilder visitSuperExpression(SuperExpression node) {
-    var builder = LinkedNodeBuilder.superExpression(
-      superExpression_superKeyword: _getToken(node.superKeyword),
-    );
+    var builder = LinkedNodeBuilder.superExpression();
     _storeExpression(builder, node);
     return builder;
   }
@@ -1149,20 +1225,14 @@
   LinkedNodeBuilder visitSwitchStatement(SwitchStatement node) {
     return LinkedNodeBuilder.switchStatement(
       switchStatement_expression: node.expression.accept(this),
-      switchStatement_leftBracket: _getToken(node.leftBracket),
-      switchStatement_leftParenthesis: _getToken(node.leftParenthesis),
       switchStatement_members: _writeNodeList(node.members),
-      switchStatement_rightBracket: _getToken(node.rightBracket),
-      switchStatement_rightParenthesis: _getToken(node.rightParenthesis),
-      switchStatement_switchKeyword: _getToken(node.switchKeyword),
     );
   }
 
   @override
   LinkedNodeBuilder visitSymbolLiteral(SymbolLiteral node) {
     var builder = LinkedNodeBuilder.symbolLiteral(
-      symbolLiteral_poundSign: _getToken(node.poundSign),
-      symbolLiteral_components: _getTokens(node.components),
+      names: node.components.map((t) => t.lexeme).toList(),
     );
     _storeExpression(builder, node);
     return builder;
@@ -1170,9 +1240,7 @@
 
   @override
   LinkedNodeBuilder visitThisExpression(ThisExpression node) {
-    var builder = LinkedNodeBuilder.thisExpression(
-      thisExpression_thisKeyword: _getToken(node.thisKeyword),
-    );
+    var builder = LinkedNodeBuilder.thisExpression();
     _storeExpression(builder, node);
     return builder;
   }
@@ -1181,7 +1249,6 @@
   LinkedNodeBuilder visitThrowExpression(ThrowExpression node) {
     return LinkedNodeBuilder.throwExpression(
       throwExpression_expression: node.expression.accept(this),
-      throwExpression_throwKeyword: _getToken(node.throwKeyword),
       expression_type: _writeType(node.staticType),
     );
   }
@@ -1189,18 +1256,18 @@
   @override
   LinkedNodeBuilder visitTopLevelVariableDeclaration(
       TopLevelVariableDeclaration node) {
-    _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder();
+    timerAstBinaryWriterTopVar.start();
+    try {
+      var builder = LinkedNodeBuilder.topLevelVariableDeclaration(
+        informativeId: getInformativeId(node),
+        topLevelVariableDeclaration_variableList: node.variables?.accept(this),
+      );
+      _storeCompilationUnitMember(builder, node);
 
-    var builder = LinkedNodeBuilder.topLevelVariableDeclaration(
-      topLevelVariableDeclaration_semicolon: _getToken(node.semicolon),
-      topLevelVariableDeclaration_variableList: node.variables?.accept(this),
-    );
-    _storeCompilationUnitMember(builder, node);
-
-    _variablesDeclaration.comment = builder.annotatedNode_comment;
-    _variablesDeclaration = null;
-
-    return builder;
+      return builder;
+    } finally {
+      timerAstBinaryWriterTopVar.stop();
+    }
   }
 
   @override
@@ -1209,8 +1276,6 @@
       tryStatement_body: node.body.accept(this),
       tryStatement_catchClauses: _writeNodeList(node.catchClauses),
       tryStatement_finallyBlock: node.finallyBlock?.accept(this),
-      tryStatement_finallyKeyword: _getToken(node.finallyKeyword),
-      tryStatement_tryKeyword: _getToken(node.tryKeyword),
     );
   }
 
@@ -1218,8 +1283,6 @@
   LinkedNodeBuilder visitTypeArgumentList(TypeArgumentList node) {
     return LinkedNodeBuilder.typeArgumentList(
       typeArgumentList_arguments: _writeNodeList(node.arguments),
-      typeArgumentList_leftBracket: _getToken(node.leftBracket),
-      typeArgumentList_rightBracket: _getToken(node.rightBracket),
     );
   }
 
@@ -1227,61 +1290,80 @@
   LinkedNodeBuilder visitTypeName(TypeName node) {
     return LinkedNodeBuilder.typeName(
       typeName_name: node.name.accept(this),
-      typeName_question: _getToken(node.question),
       typeName_type: _writeType(node.type),
-      typeName_typeArguments: node.typeArguments?.accept(this),
-    );
+      typeName_typeArguments: _writeNodeList(
+        node.typeArguments?.arguments,
+      ),
+    )..flags = AstBinaryFlags.encode(
+        hasQuestion: node.question != null,
+        hasTypeArguments: node.typeArguments != null,
+      );
   }
 
   @override
   LinkedNodeBuilder visitTypeParameter(TypeParameter node) {
     var builder = LinkedNodeBuilder.typeParameter(
-        typeParameter_bound: node.bound?.accept(this),
-        typeParameter_extendsKeyword: _getToken(node.extendsKeyword),
-        typeParameter_name: node.name.accept(this));
-    _storeDeclaration(builder, node);
-    _storeCodeOffsetLength(builder, node);
-    builder.typeParameter_id = _linkingContext.idOfTypeParameter(
-      node.declaredElement,
+      typeParameter_bound: node.bound?.accept(this),
+      typeParameter_defaultType: _writeType(LazyAst.getDefaultType(node)),
+      informativeId: getInformativeId(node),
     );
+    builder.name = node.name.name;
+    _storeDeclaration(builder, node);
     return builder;
   }
 
   @override
   LinkedNodeBuilder visitTypeParameterList(TypeParameterList node) {
     return LinkedNodeBuilder.typeParameterList(
-      typeParameterList_leftBracket: _getToken(node.leftBracket),
-      typeParameterList_rightBracket: _getToken(node.rightBracket),
       typeParameterList_typeParameters: _writeNodeList(node.typeParameters),
     );
   }
 
   @override
   LinkedNodeBuilder visitVariableDeclaration(VariableDeclaration node) {
+    var initializer = node.initializer;
+    var declarationList = node.parent as VariableDeclarationList;
+    var declaration = declarationList.parent;
+    if (declaration is TopLevelVariableDeclaration) {
+      if (!declarationList.isConst) {
+        initializer = null;
+      }
+    } else if (declaration is FieldDeclaration) {
+      if (!(declarationList.isConst ||
+          !declaration.isStatic &&
+              declarationList.isFinal &&
+              _hasConstConstructor)) {
+        initializer = null;
+      }
+    }
+
     var builder = LinkedNodeBuilder.variableDeclaration(
-      variableDeclaration_equals: _getToken(node.equals),
-      variableDeclaration_initializer: node.initializer?.accept(this),
-      variableDeclaration_name: node.name.accept(this),
-      variableDeclaration_declaration: _variablesDeclaration,
+      informativeId: getInformativeId(node),
+      variableDeclaration_initializer: initializer?.accept(this),
     );
+    builder.flags = AstBinaryFlags.encode(
+      hasInitializer: node.initializer != null,
+    );
+    builder.name = node.name.name;
+    builder.topLevelTypeInferenceError = LazyAst.getTypeInferenceError(node);
     _writeActualType(builder, node);
+    _storeInheritsCovariant(builder, node);
     return builder;
   }
 
   @override
   LinkedNodeBuilder visitVariableDeclarationList(VariableDeclarationList node) {
-    if (_variablesDeclaration != null) {
-      _variablesDeclaration.isConst = node.isConst;
-      _variablesDeclaration.isFinal = node.isFinal;
-    }
-
     var builder = LinkedNodeBuilder.variableDeclarationList(
-      variableDeclarationList_keyword: _getToken(node.keyword),
       variableDeclarationList_type: node.type?.accept(this),
       variableDeclarationList_variables: _writeNodeList(node.variables),
     );
+    builder.flags = AstBinaryFlags.encode(
+      isConst: node.isConst,
+      isFinal: node.isFinal,
+      isLate: node.lateKeyword != null,
+      isVar: node.keyword?.keyword == Keyword.VAR,
+    );
     _storeAnnotatedNode(builder, node);
-    _storeCodeOffsetLengthVariables(builder, node);
     return builder;
   }
 
@@ -1289,7 +1371,6 @@
   LinkedNodeBuilder visitVariableDeclarationStatement(
       VariableDeclarationStatement node) {
     return LinkedNodeBuilder.variableDeclarationStatement(
-      variableDeclarationStatement_semicolon: _getToken(node.semicolon),
       variableDeclarationStatement_variables: node.variables.accept(this),
     );
   }
@@ -1299,9 +1380,6 @@
     return LinkedNodeBuilder.whileStatement(
       whileStatement_body: node.body.accept(this),
       whileStatement_condition: node.condition.accept(this),
-      whileStatement_leftParenthesis: _getToken(node.leftParenthesis),
-      whileStatement_rightParenthesis: _getToken(node.rightParenthesis),
-      whileStatement_whileKeyword: _getToken(node.whileKeyword),
     );
   }
 
@@ -1309,27 +1387,35 @@
   LinkedNodeBuilder visitWithClause(WithClause node) {
     return LinkedNodeBuilder.withClause(
       withClause_mixinTypes: _writeNodeList(node.mixinTypes),
-      withClause_withKeyword: _getToken(node.withKeyword),
     );
   }
 
   @override
   LinkedNodeBuilder visitYieldStatement(YieldStatement node) {
     var builder = LinkedNodeBuilder.yieldStatement(
-      yieldStatement_yieldKeyword: _getToken(node.yieldKeyword),
       yieldStatement_expression: node.expression.accept(this),
-      yieldStatement_semicolon: _getToken(node.semicolon),
-      yieldStatement_star: _getToken(node.star),
+    );
+    builder.flags = AstBinaryFlags.encode(
+      isStar: node.star != null,
     );
     _storeStatement(builder, node);
     return builder;
   }
 
-  LinkedNodeBuilder writeNode(AstNode node) {
-    return node.accept(this);
+  LinkedNodeBuilder writeUnit(CompilationUnit unit) {
+    timerAstBinaryWriter.start();
+    try {
+      return unit.accept(this);
+    } finally {
+      timerAstBinaryWriter.stop();
+    }
   }
 
   _ElementComponents _componentsOfElement(Element element) {
+    while (element is ParameterMember) {
+      element = (element as ParameterMember).baseElement;
+    }
+
     if (element is Member) {
       var elementIndex = _indexOfElement(element.baseElement);
       var definingTypeNode = _writeType(element.definingType);
@@ -1340,27 +1426,12 @@
     return _ElementComponents(elementIndex, null);
   }
 
-  int _getToken(Token token) {
-    return _tokensContext.indexOfToken(token);
-  }
-
-  List<int> _getTokens(List<Token> tokenList) {
-    var result = List<int>(tokenList.length);
-    for (var i = 0; i < tokenList.length; ++i) {
-      var token = tokenList[i];
-      result[i] = _getToken(token);
-    }
-    return result;
-  }
-
   int _indexOfElement(Element element) {
     return _linkingContext.indexOfElement(element);
   }
 
   void _storeAnnotatedNode(LinkedNodeBuilder builder, AnnotatedNode node) {
-    builder
-      ..annotatedNode_comment = node.documentationComment?.accept(this)
-      ..annotatedNode_metadata = _writeNodeList(node.metadata);
+    builder.annotatedNode_metadata = _writeNodeList(node.metadata);
   }
 
   void _storeClassMember(LinkedNodeBuilder builder, ClassMember node) {
@@ -1372,36 +1443,13 @@
     builder
       ..classOrMixinDeclaration_implementsClause =
           node.implementsClause?.accept(this)
-      ..classOrMixinDeclaration_leftBracket = _getToken(node.leftBracket)
       ..classOrMixinDeclaration_members = _writeNodeList(node.members)
-      ..classOrMixinDeclaration_rightBracket = _getToken(node.rightBracket)
       ..classOrMixinDeclaration_typeParameters =
           node.typeParameters?.accept(this);
     _storeNamedCompilationUnitMember(builder, node);
     _storeIsSimpleBounded(builder, node);
   }
 
-  void _storeCodeOffsetLength(LinkedNodeBuilder builder, AstNode node) {
-    builder.codeOffset = node.offset;
-    builder.codeLength = node.length;
-  }
-
-  void _storeCodeOffsetLengthVariables(
-      LinkedNodeBuilder builder, VariableDeclarationList node) {
-    var builders = builder.variableDeclarationList_variables;
-    for (var i = 0; i < builders.length; ++i) {
-      var variableBuilder = builders[i];
-      var variableNode = node.variables[i];
-      var offset = (i == 0 ? node.parent : variableNode).offset;
-      variableBuilder.codeOffset = offset;
-      variableBuilder.codeLength = variableNode.end - offset;
-    }
-  }
-
-  void _storeCombinator(LinkedNodeBuilder builder, Combinator node) {
-    builder.combinator_keyword = _getToken(node.keyword);
-  }
-
   void _storeCompilationUnitMember(
       LinkedNodeBuilder builder, CompilationUnitMember node) {
     _storeDeclaration(builder, node);
@@ -1416,7 +1464,7 @@
 
   void _storeDirective(LinkedNodeBuilder builder, Directive node) {
     _storeAnnotatedNode(builder, node);
-    builder..directive_keyword = _getToken(node.keyword);
+    _storeInformativeId(builder, node);
   }
 
   void _storeExpression(LinkedNodeBuilder builder, Expression node) {
@@ -1425,53 +1473,38 @@
 
   void _storeForEachParts(LinkedNodeBuilder builder, ForEachParts node) {
     _storeForLoopParts(builder, node);
-    builder
-      ..forEachParts_inKeyword = _getToken(node.inKeyword)
-      ..forEachParts_iterable = node.iterable?.accept(this);
+    builder..forEachParts_iterable = node.iterable?.accept(this);
   }
 
   void _storeForLoopParts(LinkedNodeBuilder builder, ForLoopParts node) {}
 
   void _storeFormalParameter(LinkedNodeBuilder builder, FormalParameter node) {
-    var kind = LinkedNodeFormalParameterKind.required;
-    if (node.isNamed) {
-      kind = LinkedNodeFormalParameterKind.optionalNamed;
-    } else if (node.isOptionalPositional) {
-      kind = LinkedNodeFormalParameterKind.optionalPositional;
-    }
-    builder.formalParameter_kind = kind;
-
-    _storeCodeOffsetLength(builder, node);
     _writeActualType(builder, node);
   }
 
   void _storeForMixin(LinkedNodeBuilder builder, ForMixin node) {
-    builder
-      ..forMixin_awaitKeyword = _getToken(node.awaitKeyword)
-      ..forMixin_forKeyword = _getToken(node.forKeyword)
-      ..forMixin_forLoopParts = node.forLoopParts.accept(this)
-      ..forMixin_leftParenthesis = _getToken(node.leftParenthesis)
-      ..forMixin_rightParenthesis = _getToken(node.rightParenthesis);
+    builder.flags = AstBinaryFlags.encode(
+      hasAwait: node.awaitKeyword != null,
+    );
+    builder..forMixin_forLoopParts = node.forLoopParts.accept(this);
   }
 
   void _storeForParts(LinkedNodeBuilder builder, ForParts node) {
     _storeForLoopParts(builder, node);
     builder
-      ..forParts_leftSeparator = _getToken(node.leftSeparator)
       ..forParts_condition = node.condition?.accept(this)
-      ..forParts_rightSeparator = _getToken(node.rightSeparator)
       ..forParts_updaters = _writeNodeList(node.updaters);
   }
 
   void _storeFunctionBody(LinkedNodeBuilder builder, FunctionBody node) {}
 
-  void _storeIfMixin(LinkedNodeBuilder builder, IfMixin node) {
-    builder
-      ..ifMixin_condition = node.condition.accept(this)
-      ..ifMixin_elseKeyword = _getToken(node.elseKeyword)
-      ..ifMixin_ifKeyword = _getToken(node.ifKeyword)
-      ..ifMixin_leftParenthesis = _getToken(node.leftParenthesis)
-      ..ifMixin_rightParenthesis = _getToken(node.rightParenthesis);
+  void _storeInformativeId(LinkedNodeBuilder builder, AstNode node) {
+    builder.informativeId = getInformativeId(node);
+  }
+
+  void _storeInheritsCovariant(LinkedNodeBuilder builder, AstNode node) {
+    var value = LazyAst.getInheritsCovariant(node);
+    builder.inheritsCovariant = value;
   }
 
   void _storeInvocationExpression(
@@ -1492,8 +1525,8 @@
   void _storeNamedCompilationUnitMember(
       LinkedNodeBuilder builder, NamedCompilationUnitMember node) {
     _storeCompilationUnitMember(builder, node);
-    _storeCodeOffsetLength(builder, node);
-    builder..namedCompilationUnitMember_name = node.name.accept(this);
+    _storeInformativeId(builder, node);
+    builder.name = node.name.name;
   }
 
   void _storeNamespaceDirective(
@@ -1502,42 +1535,49 @@
     builder
       ..namespaceDirective_combinators = _writeNodeList(node.combinators)
       ..namespaceDirective_configurations = _writeNodeList(node.configurations)
-      ..namespaceDirective_selectedUri = LazyDirective.getSelectedUri(node)
-      ..directive_semicolon = _getToken(node.semicolon);
+      ..namespaceDirective_selectedUri = LazyDirective.getSelectedUri(node);
   }
 
   void _storeNormalFormalParameter(
-      LinkedNodeBuilder builder, NormalFormalParameter node) {
+      LinkedNodeBuilder builder, NormalFormalParameter node, Token keyword) {
     _storeFormalParameter(builder, node);
     builder
-      ..normalFormalParameter_comment = node.documentationComment?.accept(this)
-      ..normalFormalParameter_covariantKeyword =
-          _getToken(node.covariantKeyword)
-      ..normalFormalParameter_identifier = node.identifier?.accept(this)
+      ..flags = AstBinaryFlags.encode(
+        isConst: keyword?.type == Keyword.CONST,
+        isCovariant: node.covariantKeyword != null,
+        isFinal: keyword?.type == Keyword.FINAL,
+        isRequired: node.requiredKeyword != null,
+        isVar: keyword?.type == Keyword.VAR,
+      )
+      ..informativeId = getInformativeId(node)
+      ..name = node.identifier?.name
       ..normalFormalParameter_metadata = _writeNodeList(node.metadata);
   }
 
   void _storeStatement(LinkedNodeBuilder builder, Statement node) {}
 
   void _storeSwitchMember(LinkedNodeBuilder builder, SwitchMember node) {
-    builder.switchMember_colon = _getToken(node.colon);
-    builder.switchMember_keyword = _getToken(node.keyword);
     builder.switchMember_labels = _writeNodeList(node.labels);
     builder.switchMember_statements = _writeNodeList(node.statements);
   }
 
   void _storeTypeAlias(LinkedNodeBuilder builder, TypeAlias node) {
     _storeNamedCompilationUnitMember(builder, node);
-    builder
-      ..typeAlias_semicolon = _getToken(node.semicolon)
-      ..typeAlias_typedefKeyword = _getToken(node.typedefKeyword);
   }
 
-  void _storeTypedLiteral(LinkedNodeBuilder builder, TypedLiteral node) {
+  void _storeTypedLiteral(LinkedNodeBuilder builder, TypedLiteral node,
+      {bool isMap: false, bool isSet: false}) {
     _storeExpression(builder, node);
     builder
-      ..typedLiteral_constKeyword = _getToken(node.constKeyword)
-      ..typedLiteral_typeArguments = node.typeArguments?.accept(this);
+      ..flags = AstBinaryFlags.encode(
+        hasTypeArguments: node.typeArguments != null,
+        isConst: node.constKeyword != null,
+        isMap: isMap,
+        isSet: isSet,
+      )
+      ..typedLiteral_typeArguments = _writeNodeList(
+        node.typeArguments?.arguments,
+      );
   }
 
   void _storeUriBasedDirective(
@@ -1562,6 +1602,10 @@
   }
 
   List<LinkedNodeBuilder> _writeNodeList(List<AstNode> nodeList) {
+    if (nodeList == null) {
+      return const <LinkedNodeBuilder>[];
+    }
+
     var result = List<LinkedNodeBuilder>.filled(
       nodeList.length,
       null,
@@ -1576,6 +1620,34 @@
   LinkedNodeTypeBuilder _writeType(DartType type) {
     return _linkingContext.writeType(type);
   }
+
+  /// Return `true` if the expression might be successfully serialized.
+  ///
+  /// This does not mean that the expression is constant, it just means that
+  /// we know that it might be serialized and deserialized. For example
+  /// function expressions are problematic, and are not necessary to
+  /// deserialize, so we choose not to do this.
+  static bool _isSerializableExpression(Expression node) {
+    if (node == null) return false;
+
+    var visitor = _IsSerializableExpressionVisitor();
+    node.accept(visitor);
+    return visitor.result;
+  }
+
+  static LinkedNodeFormalParameterKind _toParameterKind(FormalParameter node) {
+    if (node.isRequiredPositional) {
+      return LinkedNodeFormalParameterKind.requiredPositional;
+    } else if (node.isRequiredNamed) {
+      return LinkedNodeFormalParameterKind.requiredNamed;
+    } else if (node.isOptionalPositional) {
+      return LinkedNodeFormalParameterKind.optionalPositional;
+    } else if (node.isOptionalNamed) {
+      return LinkedNodeFormalParameterKind.optionalNamed;
+    } else {
+      throw new StateError('Unknown kind of parameter');
+    }
+  }
 }
 
 /// Components of a [Member] - the raw element, and the defining type.
@@ -1585,3 +1657,12 @@
 
   _ElementComponents(this.rawElement, this.definingType);
 }
+
+class _IsSerializableExpressionVisitor extends RecursiveAstVisitor<void> {
+  bool result = true;
+
+  @override
+  void visitFunctionExpression(FunctionExpression node) {
+    result = false;
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
index a8a0d5a..1812c3e 100644
--- a/pkg/analyzer/lib/src/summary2/ast_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary2/link.dart';
@@ -21,30 +22,29 @@
     AstNode node, {
     ClassElement enclosingClassElement,
     ExecutableElement enclosingExecutableElement,
-    bool doAstRewrite = false,
+    FunctionBody enclosingFunctionBody,
   }) {
+    var featureSet = node.thisOrAncestorOfType<CompilationUnit>().featureSet;
     var source = _FakeSource();
     var errorListener = AnalysisErrorListener.NULL_LISTENER;
 
     var typeResolverVisitor = new TypeResolverVisitor(
         _library, source, _linker.typeProvider, errorListener,
-        nameScope: _nameScope);
+        featureSet: featureSet, nameScope: _nameScope);
     node.accept(typeResolverVisitor);
 
-    if (doAstRewrite) {
-      var astRewriteVisitor = new AstRewriteVisitor(_linker.typeSystem,
-          _library, source, _linker.typeProvider, errorListener,
-          nameScope: _nameScope);
-      node.accept(astRewriteVisitor);
-    }
+    var variableResolverVisitor = new VariableResolverVisitor(
+        _library, source, _linker.typeProvider, errorListener,
+        nameScope: _nameScope, localVariableInfo: LocalVariableInfo());
+    node.accept(variableResolverVisitor);
 
-//    expression.accept(_variableResolverVisitor);
 //    if (_linker.getAst != null) {
 //      expression.accept(_partialResolverVisitor);
 //    }
 
     var resolverVisitor = new ResolverVisitor(_linker.inheritance, _library,
         source, _linker.typeProvider, errorListener,
+        featureSet: featureSet,
         nameScope: _nameScope,
         propagateTypes: false,
         reportConstEvaluationErrors: false);
@@ -52,11 +52,28 @@
       enclosingClassElement: enclosingClassElement,
       enclosingExecutableElement: enclosingExecutableElement,
     );
+    if (enclosingFunctionBody != null) {
+      resolverVisitor.prepareCurrentFunctionBody(enclosingFunctionBody);
+    }
 
     node.accept(resolverVisitor);
   }
+
+  void rewriteAst(AstNode node) {
+    var source = _FakeSource();
+    var errorListener = AnalysisErrorListener.NULL_LISTENER;
+
+    var astRewriteVisitor = new AstRewriteVisitor(_linker.typeSystem, _library,
+        source, _linker.typeProvider, errorListener,
+        nameScope: _nameScope);
+    node.accept(astRewriteVisitor);
+  }
 }
 
 class _FakeSource implements Source {
+  @override
+  String get fullName => '/package/lib/test.dart';
+
+  @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
index eefebe8..586123a 100644
--- a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
@@ -478,6 +478,7 @@
     node.identifier.accept(this);
     node.typeParameters?.accept(this);
     node.parameters.accept(this);
+    _token(node.question);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
index dab6481..2845328 100644
--- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
@@ -2,7 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart' show LibraryScope;
 import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -20,6 +22,7 @@
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/summary2/reference_resolver.dart';
 import 'package:analyzer/src/summary2/scope.dart';
+import 'package:analyzer/src/summary2/types_builder.dart';
 
 class SourceLibraryBuilder {
   final Linker linker;
@@ -30,7 +33,7 @@
   LinkedLibraryContext context;
 
   LibraryElementImpl element;
-  LibraryScope libraryScope;
+  LibraryScope scope;
 
   /// Local declarations.
   final Scope localScope = Scope.top();
@@ -62,6 +65,7 @@
             var nameList = node.hiddenNames.map((i) => i.name).toList();
             return Combinator.hide(nameList);
           }
+          return null;
         }).toList();
 
         var exported = linker.builders[uri];
@@ -71,7 +75,12 @@
         } else {
           var references = linker.elementFactory.exportsOfLibrary('$uri');
           for (var reference in references) {
-            export.addToExportScope(reference.name, reference);
+            var name = reference.name;
+            if (reference.isSetter) {
+              export.addToExportScope('$name=', reference);
+            } else {
+              export.addToExportScope(name, reference);
+            }
           }
         }
       }
@@ -85,6 +94,7 @@
       var classRef = unitRef.getChild('@class');
       var enumRef = unitRef.getChild('@enum');
       var functionRef = unitRef.getChild('@function');
+      var mixinRef = unitRef.getChild('@mixin');
       var typeAliasRef = unitRef.getChild('@typeAlias');
       var getterRef = unitRef.getChild('@getter');
       var setterRef = unitRef.getChild('@setter');
@@ -119,7 +129,12 @@
 
           var reference = containerRef.getChild(name);
           reference.node2 = node;
-          localScope.declare(name, reference);
+
+          if (node.isSetter) {
+            localScope.declare('$name=', reference);
+          } else {
+            localScope.declare(name, reference);
+          }
         } else if (node is ast.FunctionTypeAlias) {
           var name = node.name.name;
           var reference = typeAliasRef.getChild(name);
@@ -134,7 +149,7 @@
           localScope.declare(name, reference);
         } else if (node is ast.MixinDeclaration) {
           var name = node.name.name;
-          var reference = classRef.getChild(name);
+          var reference = mixinRef.getChild(name);
           reference.node2 = node;
           localScope.declare(name, reference);
         } else if (node is ast.TopLevelVariableDeclaration) {
@@ -158,103 +173,9 @@
         }
       }
     }
-//    for (var unit in units) {
-//      var unitRef = reference.getChild('@unit').getChild('${unit.uri}');
-//      var classRef = unitRef.getChild('@class');
-//      var enumRef = unitRef.getChild('@enum');
-//      var functionRef = unitRef.getChild('@function');
-//      var typeAliasRef = unitRef.getChild('@typeAlias');
-//      var getterRef = unitRef.getChild('@getter');
-//      var setterRef = unitRef.getChild('@setter');
-//      var variableRef = unitRef.getChild('@variable');
-//      for (var node in unit.node.compilationUnit_declarations) {
-//        if (node.kind == LinkedNodeKind.classDeclaration ||
-//            node.kind == LinkedNodeKind.classTypeAlias ||
-//            node.kind == LinkedNodeKind.mixinDeclaration) {
-//          var name = unit.context.getUnitMemberName(node);
-//          var reference = classRef.getChild(name);
-//          reference.node = node;
-//          scope.declare(name, reference);
-//        } else if (node.kind == LinkedNodeKind.enumDeclaration) {
-//          var name = unit.context.getUnitMemberName(node);
-//          var reference = enumRef.getChild(name);
-//          reference.node = node;
-//          scope.declare(name, reference);
-//        } else if (node.kind == LinkedNodeKind.functionDeclaration) {
-//          var name = unit.context.getUnitMemberName(node);
-//
-//          Reference containerRef;
-//          if (unit.context.isGetterFunction(node)) {
-//            containerRef = getterRef;
-//          } else if (unit.context.isSetterFunction(node)) {
-//            containerRef = setterRef;
-//          } else {
-//            containerRef = functionRef;
-//          }
-//
-//          var reference = containerRef.getChild(name);
-//          reference.node = node;
-//
-//          scope.declare(name, reference);
-//        } else if (node.kind == LinkedNodeKind.functionTypeAlias) {
-//          var name = unit.context.getUnitMemberName(node);
-//          var reference = typeAliasRef.getChild(name);
-//          reference.node = node;
-//
-//          scope.declare(name, reference);
-//        } else if (node.kind == LinkedNodeKind.genericTypeAlias) {
-//          var name = unit.context.getUnitMemberName(node);
-//          var reference = typeAliasRef.getChild(name);
-//          reference.node = node;
-//
-//          scope.declare(name, reference);
-//        } else if (node.kind == LinkedNodeKind.topLevelVariableDeclaration) {
-//          var variableList = node.topLevelVariableDeclaration_variableList;
-//          for (var variable in variableList.variableDeclarationList_variables) {
-//            var name = unit.context.getVariableName(variable);
-//
-//            var reference = variableRef.getChild(name);
-//            reference.node = node;
-//
-//            var getter = getterRef.getChild(name);
-//            scope.declare(name, getter);
-//
-//            if (!unit.context.isConst(variable) &&
-//                !unit.context.isFinal(variable)) {
-//              var setter = setterRef.getChild(name);
-//              scope.declare('$name=', setter);
-//            }
-//          }
-//        } else {
-//          // TODO(scheglov) implement
-//          throw UnimplementedError('${node.kind}');
-//        }
-//      }
-//    }
     if ('$uri' == 'dart:core') {
       localScope.declare('dynamic', reference.getChild('dynamic'));
-    }
-  }
-
-  void addSyntheticConstructors() {
-    for (var reference in localScope.map.values) {
-      var node = reference.node;
-      if (node == null) continue;
-      if (node.kind != LinkedNodeKind.classDeclaration) continue;
-
-      // Skip the class if it already has a constructor.
-      if (node.classOrMixinDeclaration_members
-          .any((n) => n.kind == LinkedNodeKind.constructorDeclaration)) {
-        continue;
-      }
-
-      node.classOrMixinDeclaration_members.add(
-        LinkedNodeBuilder.constructorDeclaration(
-          constructorDeclaration_parameters:
-              LinkedNodeBuilder.formalParameterList(),
-          constructorDeclaration_body: LinkedNodeBuilder.emptyFunctionBody(),
-        )..isSynthetic = true,
-      );
+      localScope.declare('Never', reference.getChild('Never'));
     }
   }
 
@@ -275,7 +196,7 @@
 
   void buildElement() {
     element = linker.elementFactory.libraryOfUri('$uri');
-    libraryScope = LibraryScope(element);
+    scope = LibraryScope(element);
   }
 
   void buildInitialExportScope() {
@@ -284,6 +205,24 @@
     });
   }
 
+  void collectMixinSuperInvokedNames() {
+    for (var unitContext in context.units) {
+      for (var declaration in unitContext.unit.declarations) {
+        if (declaration is ast.MixinDeclaration) {
+          var names = Set<String>();
+          var collector = MixinSuperInvokedNamesCollector(names);
+          for (var executable in declaration.members) {
+            if (executable is ast.MethodDeclaration) {
+              executable.body.accept(collector);
+            }
+          }
+          var lazy = LazyMixinDeclaration.get(declaration);
+          lazy.setSuperInvokedNames(names.toList());
+        }
+      }
+    }
+  }
+
   void resolveConstructors() {
     ConstructorInitializerResolver(linker, element).resolve();
   }
@@ -293,23 +232,23 @@
   }
 
   void resolveMetadata() {
-    var metadataResolver = MetadataResolver(linker, element);
-    for (var unitContext in context.units) {
-      unitContext.unit.accept(metadataResolver);
+    for (CompilationUnitElementImpl unit in element.units) {
+      var resolver = MetadataResolver(linker, element, scope, unit);
+      unit.linkedNode.accept(resolver);
     }
   }
 
-  void resolveTypes(List<ast.AstNode> nodesToBuildType) {
+  void resolveTypes(NodesToBuildType nodesToBuildType) {
     for (var unitContext in context.units) {
       var unitRef = reference.getChild('@unit');
       var unitReference = unitRef.getChild(unitContext.uriStr);
       var resolver = ReferenceResolver(
-        linker.linkingBundleContext,
         nodesToBuildType,
         linker.elementFactory,
         element,
         unitReference,
-        libraryScope,
+        linker.contextFeatures.isEnabled(Feature.non_nullable),
+        scope,
       );
       unitContext.unit.accept(resolver);
     }
@@ -342,7 +281,9 @@
       directive.configurations,
       directive.uri.stringValue,
     );
-    if (relativeUriStr.isEmpty) return null;
+    if (relativeUriStr == null || relativeUriStr.isEmpty) {
+      return null;
+    }
     var relativeUri = Uri.parse(relativeUriStr);
     return resolveRelativeUri(this.uri, relativeUri);
   }
diff --git a/pkg/analyzer/lib/src/summary2/combinator.dart b/pkg/analyzer/lib/src/summary2/combinator.dart
index 5d7b20e..96f1152 100644
--- a/pkg/analyzer/lib/src/summary2/combinator.dart
+++ b/pkg/analyzer/lib/src/summary2/combinator.dart
@@ -8,9 +8,16 @@
 
   Combinator(this.isShow, this.names);
 
-  Combinator.show(Iterable<String> names) : this(true, names.toSet());
-
   Combinator.hide(Iterable<String> names) : this(false, names.toSet());
 
+  Combinator.show(Iterable<String> names) : this(true, names.toSet());
+
   bool get isHide => !isShow;
+
+  bool matches(String name) {
+    if (name.endsWith('=')) {
+      name = name.substring(0, name.length - 1);
+    }
+    return names.contains(name);
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart b/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart
index fbb7919..4a6d796 100644
--- a/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart
@@ -4,8 +4,10 @@
 
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/summary2/ast_resolver.dart';
 import 'package:analyzer/src/summary2/link.dart';
 import 'package:analyzer/src/summary2/linking_node_scope.dart';
@@ -14,6 +16,7 @@
   final Linker _linker;
   final LibraryElementImpl _libraryElement;
 
+  CompilationUnitElement _unitElement;
   ClassElement _classElement;
   ConstructorElement _constructorElement;
   ConstructorDeclarationImpl _constructorNode;
@@ -23,6 +26,7 @@
 
   void resolve() {
     for (var unit in _libraryElement.units) {
+      _unitElement = unit;
       for (var classElement in unit.types) {
         _classElement = classElement;
         for (var constructorElement in classElement.constructors) {
@@ -46,6 +50,9 @@
 
     _astResolver = AstResolver(_linker, _libraryElement, initializerScope);
 
+    FunctionBodyImpl body = _constructorNode.body;
+    body.localVariableInfo = LocalVariableInfo();
+
     _initializers();
     _redirectedConstructor();
   }
@@ -59,11 +66,16 @@
       return;
     }
 
+    var holder = ElementHolder();
+    var elementBuilder = LocalElementBuilder(holder, _unitElement);
+    initializers.accept(elementBuilder);
+
     for (var initializer in initializers) {
       _astResolver.resolve(
         initializer,
         enclosingClassElement: _classElement,
         enclosingExecutableElement: _constructorElement,
+        enclosingFunctionBody: _constructorNode.body,
       );
     }
   }
diff --git a/pkg/analyzer/lib/src/summary2/default_types_builder.dart b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
new file mode 100644
index 0000000..18a4fcb3
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
@@ -0,0 +1,308 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+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/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/summary2/function_type_builder.dart';
+import 'package:analyzer/src/summary2/lazy_ast.dart';
+import 'package:analyzer/src/summary2/named_type_builder.dart';
+import 'package:analyzer/src/summary2/type_builder.dart';
+import 'package:kernel/util/graph.dart' show Graph, computeStrongComponents;
+
+class DefaultTypesBuilder {
+  final Dart2TypeSystem typeSystem;
+
+  DefaultTypesBuilder(this.typeSystem);
+
+  void build(List<AstNode> nodes) {
+    for (var node in nodes) {
+      if (node is ClassDeclaration) {
+        _breakRawTypeCycles(node.declaredElement, node.typeParameters);
+        _computeBounds(node.typeParameters);
+      } else if (node is ClassTypeAlias) {
+        _breakRawTypeCycles(node.declaredElement, node.typeParameters);
+        _computeBounds(node.typeParameters);
+      } else if (node is FunctionTypeAlias) {
+        _breakRawTypeCycles(node.declaredElement, node.typeParameters);
+        _computeBounds(node.typeParameters);
+      } else if (node is GenericTypeAlias) {
+        _breakRawTypeCycles(node.declaredElement, node.typeParameters);
+        _computeBounds(node.typeParameters);
+      } else if (node is MixinDeclaration) {
+        _breakRawTypeCycles(node.declaredElement, node.typeParameters);
+        _computeBounds(node.typeParameters);
+      }
+    }
+    for (var node in nodes) {
+      if (node is ClassDeclaration) {
+        _build(node.typeParameters);
+      } else if (node is ClassTypeAlias) {
+        _build(node.typeParameters);
+      } else if (node is FunctionTypeAlias) {
+        _build(node.typeParameters);
+      } else if (node is GenericTypeAlias) {
+        _build(node.typeParameters);
+      } else if (node is MixinDeclaration) {
+        _build(node.typeParameters);
+      }
+    }
+  }
+
+  void _breakRawTypeCycles(
+    Element declarationElement,
+    TypeParameterList parameterList,
+  ) {
+    if (parameterList == null) return;
+
+    var allCycles = <List<_CycleElement>>[];
+    for (var parameter in parameterList.typeParameters) {
+      var boundNode = parameter.bound;
+      if (boundNode == null) continue;
+
+      var cycles = _findRawTypePathsToDeclaration(
+        parameter,
+        boundNode.type,
+        declarationElement,
+        Set<Element>.identity(),
+      );
+      allCycles.addAll(cycles);
+    }
+
+    for (var cycle in allCycles) {
+      for (var element in cycle) {
+        var boundNode = element.parameter.bound;
+        if (boundNode is TypeName) {
+          boundNode.type = DynamicTypeImpl.instance;
+        } else {
+          throw UnimplementedError('(${boundNode.runtimeType}) $boundNode');
+        }
+      }
+    }
+  }
+
+  /// Build actual default type [DartType]s from computed [TypeBuilder]s.
+  void _build(TypeParameterList parameterList) {
+    if (parameterList == null) return;
+
+    for (var parameter in parameterList.typeParameters) {
+      var defaultType = LazyAst.getDefaultType(parameter);
+      if (defaultType is TypeBuilder) {
+        var builtType = defaultType.build();
+        LazyAst.setDefaultType(parameter, builtType);
+      }
+    }
+  }
+
+  /// Compute bounds to be provided as type arguments in place of missing type
+  /// arguments on raw types with the given type parameters.
+  void _computeBounds(TypeParameterList parameterList) {
+    if (parameterList == null) return;
+
+    var dynamicType = typeSystem.typeProvider.dynamicType;
+    var nullType = typeSystem.typeProvider.nullType;
+
+    var nodes = parameterList.typeParameters;
+    var length = nodes.length;
+    var elements = List<TypeParameterElement>(length);
+    var bounds = List<DartType>(length);
+    for (int i = 0; i < length; i++) {
+      var node = nodes[i];
+      elements[i] = node.declaredElement;
+      bounds[i] = node.bound?.type ?? dynamicType;
+    }
+
+    var graph = _TypeParametersGraph(elements, bounds);
+    var stronglyConnected = computeStrongComponents(graph);
+    for (var component in stronglyConnected) {
+      var dynamicSubstitution = <TypeParameterElement, DartType>{};
+      var nullSubstitution = <TypeParameterElement, DartType>{};
+      for (var i in component) {
+        var element = elements[i];
+        dynamicSubstitution[element] = dynamicType;
+        nullSubstitution[element] = nullType;
+      }
+
+      var substitution = Substitution.fromUpperAndLowerBounds(
+        dynamicSubstitution,
+        nullSubstitution,
+      );
+      for (var i in component) {
+        bounds[i] = substitution.substituteType(bounds[i]);
+      }
+    }
+
+    for (var i = 0; i < length; i++) {
+      var thisSubstitution = <TypeParameterElement, DartType>{};
+      var nullSubstitution = <TypeParameterElement, DartType>{};
+      var element = elements[i];
+      thisSubstitution[element] = bounds[i];
+      nullSubstitution[element] = nullType;
+
+      var substitution = Substitution.fromUpperAndLowerBounds(
+        thisSubstitution,
+        nullSubstitution,
+      );
+      for (var j = 0; j < length; j++) {
+        bounds[j] = substitution.substituteType(bounds[j]);
+      }
+    }
+
+    // Set computed TypeBuilder(s) as default types.
+    for (var i = 0; i < length; i++) {
+      LazyAst.setDefaultType(nodes[i], bounds[i]);
+    }
+  }
+
+  /// Finds raw type paths starting with the [startParameter] and a
+  /// [startType] that is used in its bound, and ending with [end].
+  List<List<_CycleElement>> _findRawTypePathsToDeclaration(
+    TypeParameter startParameter,
+    DartType startType,
+    Element end,
+    Set<Element> visited,
+  ) {
+    var paths = <List<_CycleElement>>[];
+    if (startType is NamedTypeBuilder) {
+      var declaration = startType.element;
+      if (startType.arguments.isEmpty) {
+        if (startType.element == end) {
+          paths.add([
+            _CycleElement(startParameter, startType),
+          ]);
+        } else if (visited.add(startType.element)) {
+          void recurseParameters(List<TypeParameterElement> parameters) {
+            for (TypeParameterElementImpl parameter in parameters) {
+              TypeParameter parameterNode = parameter.linkedNode;
+              var bound = parameterNode.bound;
+              if (bound != null) {
+                var tails = _findRawTypePathsToDeclaration(
+                  parameterNode,
+                  bound.type,
+                  end,
+                  visited,
+                );
+                for (var tail in tails) {
+                  paths.add(<_CycleElement>[
+                    _CycleElement(startParameter, startType),
+                  ]..addAll(tail));
+                }
+              }
+            }
+          }
+
+          if (declaration is ClassElement) {
+            recurseParameters(declaration.typeParameters);
+          } else if (declaration is GenericTypeAliasElement) {
+            recurseParameters(declaration.typeParameters);
+          }
+          visited.remove(startType.element);
+        }
+      } else {
+        for (var argument in startType.arguments) {
+          paths.addAll(
+            _findRawTypePathsToDeclaration(
+              startParameter,
+              argument,
+              end,
+              visited,
+            ),
+          );
+        }
+      }
+    } else if (startType is FunctionTypeBuilder) {
+      paths.addAll(
+        _findRawTypePathsToDeclaration(
+          startParameter,
+          startType.returnType,
+          end,
+          visited,
+        ),
+      );
+      for (var formalParameter in startType.parameters) {
+        paths.addAll(
+          _findRawTypePathsToDeclaration(
+            startParameter,
+            formalParameter.type,
+            end,
+            visited,
+          ),
+        );
+      }
+    }
+    return paths;
+  }
+}
+
+class _CycleElement {
+  final TypeParameter parameter;
+  final DartType type;
+
+  _CycleElement(this.parameter, this.type);
+}
+
+/// Graph of mutual dependencies of type parameters from the same declaration.
+/// Type parameters are represented by their indices in the corresponding
+/// declaration.
+class _TypeParametersGraph implements Graph<int> {
+  @override
+  List<int> vertices;
+
+  // Each `edges[i]` is the list of indices of type parameters that reference
+  // the type parameter with the index `i` in their bounds.
+  List<List<int>> _edges;
+
+  Map<TypeParameterElement, int> _parameterToIndex = Map.identity();
+
+  _TypeParametersGraph(
+    List<TypeParameterElement> parameters,
+    List<DartType> bounds,
+  ) {
+    assert(parameters.length == bounds.length);
+
+    vertices = List<int>(parameters.length);
+    _edges = List<List<int>>(parameters.length);
+    for (int i = 0; i < vertices.length; i++) {
+      vertices[i] = i;
+      _edges[i] = <int>[];
+      _parameterToIndex[parameters[i]] = i;
+    }
+
+    for (int i = 0; i < vertices.length; i++) {
+      _collectReferencesFrom(i, bounds[i]);
+    }
+  }
+
+  /// Return type parameters that depend on the [index]th type parameter.
+  @override
+  Iterable<int> neighborsOf(int index) {
+    return _edges[index];
+  }
+
+  /// Collect references to the [index]th type parameter from the [type].
+  void _collectReferencesFrom(int index, DartType type) {
+    if (type is FunctionTypeBuilder) {
+      for (var parameter in type.typeFormals) {
+        _collectReferencesFrom(index, parameter.bound);
+      }
+      for (var parameter in type.parameters) {
+        _collectReferencesFrom(index, parameter.type);
+      }
+      _collectReferencesFrom(index, type.returnType);
+    } else if (type is NamedTypeBuilder) {
+      for (var argument in type.arguments) {
+        _collectReferencesFrom(index, argument);
+      }
+    } else if (type is TypeParameterType) {
+      var typeIndex = _parameterToIndex[type.element];
+      if (typeIndex != null) {
+        _edges[typeIndex].add(index);
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/default_value_resolver.dart b/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
index f531465..fbdeaea 100644
--- a/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
@@ -27,19 +28,12 @@
 
   void resolve() {
     for (CompilationUnitElementImpl unit in _libraryElement.units) {
+      for (var classElement in unit.mixins) {
+        _class(classElement);
+      }
+
       for (var classElement in unit.types) {
-        _classElement = classElement;
-
-        for (var element in classElement.constructors) {
-          _constructor(element);
-        }
-
-        for (var element in classElement.methods) {
-          _setScopeFromElement(element);
-          _method(element);
-        }
-
-        _classElement = null;
+        _class(classElement);
       }
 
       for (var element in unit.functions) {
@@ -48,6 +42,21 @@
     }
   }
 
+  void _class(ClassElement classElement) {
+    _classElement = classElement;
+
+    for (var element in classElement.constructors) {
+      _constructor(element);
+    }
+
+    for (var element in classElement.methods) {
+      _setScopeFromElement(element);
+      _method(element);
+    }
+
+    _classElement = null;
+  }
+
   void _constructor(ConstructorElementImpl element) {
     if (element.isSynthetic) return;
 
@@ -82,6 +91,8 @@
     }
     if (defaultValue == null) return;
 
+    defaultValue.accept(LocalElementBuilder(ElementHolder(), null));
+
     var contextType = TypeVariableEliminator(_linker.typeProvider)
         .substituteType(parameter.type);
     InferenceContext.setType(defaultValue, contextType);
diff --git a/pkg/analyzer/lib/src/summary2/export.dart b/pkg/analyzer/lib/src/summary2/export.dart
index 63a1365..18247c3 100644
--- a/pkg/analyzer/lib/src/summary2/export.dart
+++ b/pkg/analyzer/lib/src/summary2/export.dart
@@ -16,8 +16,8 @@
   bool addToExportScope(String name, Reference reference) {
     if (combinators != null) {
       for (Combinator combinator in combinators) {
-        if (combinator.isShow && !combinator.names.contains(name)) return false;
-        if (combinator.isHide && combinator.names.contains(name)) return false;
+        if (combinator.isShow && !combinator.matches(name)) return false;
+        if (combinator.isHide && combinator.matches(name)) return false;
       }
     }
     return exporter.addToExportScope(name, reference);
diff --git a/pkg/analyzer/lib/src/summary2/function_type_builder.dart b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
new file mode 100644
index 0000000..2cec063
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/summary2/lazy_ast.dart';
+import 'package:analyzer/src/summary2/type_builder.dart';
+
+/// The type builder for a [GenericFunctionType].
+class FunctionTypeBuilder extends TypeBuilder {
+  static DynamicTypeImpl get _dynamicType => DynamicTypeImpl.instance;
+
+  final List<TypeParameterElement> typeFormals;
+  final List<ParameterElement> parameters;
+  final DartType returnType;
+  final NullabilitySuffix nullabilitySuffix;
+
+  /// The node for which this builder is created, or `null` if the builder
+  /// was detached from its node, e.g. during computing default types for
+  /// type parameters.
+  final GenericFunctionTypeImpl node;
+
+  /// The actual built type, not a [TypeBuilder] anymore.
+  ///
+  /// When [build] is called, the type is built, stored into this field,
+  /// and set for the [node].
+  DartType _type;
+
+  FunctionTypeBuilder(
+    this.typeFormals,
+    this.parameters,
+    this.returnType,
+    this.nullabilitySuffix, {
+    this.node,
+  });
+
+  factory FunctionTypeBuilder.of(
+    GenericFunctionType node,
+    NullabilitySuffix nullabilitySuffix,
+  ) {
+    return FunctionTypeBuilder(
+      node.typeParameters?.typeParameters
+              ?.map((n) => n.declaredElement)
+              ?.toList() ??
+          [],
+      node.parameters.parameters.map((n) {
+        return ParameterElementImpl.synthetic(
+          n.identifier?.name ?? '',
+          _getParameterType(n),
+          // ignore: deprecated_member_use_from_same_package
+          n.kind,
+        );
+      }).toList(),
+      _getNodeType(node.returnType),
+      nullabilitySuffix,
+      node: node,
+    );
+  }
+
+  @override
+  Element get element => null;
+
+  @override
+  DartType build() {
+    if (_type != null) {
+      return _type;
+    }
+
+    var builtReturnType = _buildType(returnType);
+    _type = FunctionTypeImpl.synthetic(
+      builtReturnType,
+      typeFormals,
+      parameters.map((e) {
+        return ParameterElementImpl.synthetic(
+          e.name,
+          _buildType(e.type),
+          // ignore: deprecated_member_use_from_same_package
+          e.parameterKind,
+        );
+      }).toList(),
+      nullabilitySuffix: nullabilitySuffix,
+    );
+
+    if (node != null) {
+      node.type = _type;
+      LazyAst.setReturnType(node, builtReturnType ?? _dynamicType);
+    }
+
+    return _type;
+  }
+
+  @override
+  String toString() {
+    var buffer = StringBuffer();
+
+    if (typeFormals.isNotEmpty) {
+      buffer.write('<');
+      buffer.write(typeFormals.join(', '));
+      buffer.write('>');
+    }
+
+    buffer.write('(');
+    buffer.write(parameters.join(', '));
+    buffer.write(')');
+
+    buffer.write(' → ');
+    buffer.write(returnType);
+
+    return buffer.toString();
+  }
+
+  /// If the [type] is a [TypeBuilder], build it; otherwise return as is.
+  static DartType _buildType(DartType type) {
+    if (type is TypeBuilder) {
+      return type.build();
+    } else {
+      return type;
+    }
+  }
+
+  /// Return the type of the [node] as is, possibly a [TypeBuilder].
+  static DartType _getNodeType(TypeAnnotation node) {
+    if (node == null) {
+      return _dynamicType;
+    } else {
+      return node.type;
+    }
+  }
+
+  /// Return the type of the [node] as is, possibly a [TypeBuilder].
+  static DartType _getParameterType(FormalParameter node) {
+    if (node is DefaultFormalParameter) {
+      return _getParameterType(node.parameter);
+    } else if (node is SimpleFormalParameter) {
+      return _getNodeType(node.type);
+    } else {
+      throw UnimplementedError('(${node.runtimeType}) $node');
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
new file mode 100644
index 0000000..a09494f
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -0,0 +1,391 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/summary/format.dart';
+
+/// Create informative data for nodes that need it, and set IDs of this
+/// data to the nodes.
+List<UnlinkedInformativeDataBuilder> createInformativeData(
+    CompilationUnit unit) {
+  var visitor = _SetInformativeId();
+  unit.accept(visitor);
+  return visitor.dataList;
+}
+
+/// If [createInformativeData] set the informative data identifier for the
+/// [node], return it, otherwise return zero.
+int getInformativeId(AstNode node) {
+  int id = node.getProperty(_SetInformativeId.ID);
+  return id ?? 0;
+}
+
+class _SetInformativeId extends SimpleAstVisitor<void> {
+  static final String ID = 'informativeId';
+
+  final List<UnlinkedInformativeDataBuilder> dataList = [];
+
+  void setData(AstNode node, UnlinkedInformativeDataBuilder data) {
+    var id = 1 + dataList.length;
+    node.setProperty(ID, id);
+    dataList.add(data);
+  }
+
+  @override
+  void visitClassDeclaration(ClassDeclaration node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.classDeclaration(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        documentationComment_tokens: _nodeCommentTokens(node),
+        nameOffset: node.name.offset,
+      ),
+    );
+
+    node.typeParameters?.accept(this);
+    node.members.accept(this);
+  }
+
+  @override
+  void visitClassTypeAlias(ClassTypeAlias node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.classTypeAlias(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        documentationComment_tokens: _nodeCommentTokens(node),
+        nameOffset: node.name.offset,
+      ),
+    );
+
+    node.typeParameters?.accept(this);
+  }
+
+  @override
+  void visitCompilationUnit(CompilationUnit node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.compilationUnit(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        compilationUnit_lineStarts: node.lineInfo.lineStarts,
+      ),
+    );
+
+    node.directives.accept(this);
+    node.declarations.accept(this);
+  }
+
+  @override
+  void visitConstructorDeclaration(ConstructorDeclaration node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.constructorDeclaration(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        documentationComment_tokens: _nodeCommentTokens(node),
+        nameOffset: node.name?.offset ?? 0,
+        constructorDeclaration_periodOffset: node.period?.offset ?? 0,
+        constructorDeclaration_returnTypeOffset: node.returnType.offset,
+      ),
+    );
+
+    node.parameters?.accept(this);
+  }
+
+  @override
+  void visitDefaultFormalParameter(DefaultFormalParameter node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.defaultFormalParameter(
+        codeOffset: node.offset,
+        codeLength: node.length,
+      ),
+    );
+
+    node.parameter.accept(this);
+  }
+
+  @override
+  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.enumConstantDeclaration(
+        documentationComment_tokens: _nodeCommentTokens(node),
+        nameOffset: node.name.offset,
+      ),
+    );
+  }
+
+  @override
+  void visitEnumDeclaration(EnumDeclaration node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.enumDeclaration(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        documentationComment_tokens: _nodeCommentTokens(node),
+        nameOffset: node.name.offset,
+      ),
+    );
+
+    node.constants.accept(this);
+  }
+
+  @override
+  void visitExportDirective(ExportDirective node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.exportDirective(
+        directiveKeywordOffset: node.keyword.offset,
+      ),
+    );
+  }
+
+  @override
+  void visitFieldDeclaration(FieldDeclaration node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.fieldDeclaration(
+        documentationComment_tokens: _nodeCommentTokens(node),
+      ),
+    );
+
+    node.fields.accept(this);
+  }
+
+  @override
+  void visitFieldFormalParameter(FieldFormalParameter node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.fieldFormalParameter(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        nameOffset: node.identifier.offset,
+      ),
+    );
+  }
+
+  @override
+  void visitFormalParameterList(FormalParameterList node) {
+    node.parameters.accept(this);
+  }
+
+  @override
+  void visitFunctionDeclaration(FunctionDeclaration node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.functionDeclaration(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        documentationComment_tokens: _nodeCommentTokens(node),
+        nameOffset: node.name.offset,
+      ),
+    );
+
+    node.functionExpression.accept(this);
+  }
+
+  @override
+  void visitFunctionExpression(FunctionExpression node) {
+    node.typeParameters?.accept(this);
+    node.parameters?.accept(this);
+  }
+
+  @override
+  void visitFunctionTypeAlias(FunctionTypeAlias node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.functionTypeAlias(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        documentationComment_tokens: _nodeCommentTokens(node),
+        nameOffset: node.name.offset,
+      ),
+    );
+
+    node.typeParameters?.accept(this);
+    node.parameters.accept(this);
+  }
+
+  @override
+  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.functionTypedFormalParameter(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        nameOffset: node.identifier.offset,
+      ),
+    );
+  }
+
+  @override
+  void visitGenericFunctionType(GenericFunctionType node) {
+    node.typeParameters?.accept(this);
+    node.parameters.accept(this);
+  }
+
+  @override
+  void visitGenericTypeAlias(GenericTypeAlias node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.genericTypeAlias(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        documentationComment_tokens: _nodeCommentTokens(node),
+        nameOffset: node.name.offset,
+      ),
+    );
+
+    node.typeParameters?.accept(this);
+    node.functionType?.accept(this);
+  }
+
+  @override
+  void visitImportDirective(ImportDirective node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.importDirective(
+        directiveKeywordOffset: node.keyword.offset,
+      ),
+    );
+  }
+
+  @override
+  void visitLibraryDirective(LibraryDirective node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.libraryDirective(
+        documentationComment_tokens: _nodeCommentTokens(node),
+      ),
+    );
+  }
+
+  @override
+  void visitMethodDeclaration(MethodDeclaration node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.methodDeclaration(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        documentationComment_tokens: _nodeCommentTokens(node),
+        nameOffset: node.name.offset,
+      ),
+    );
+
+    node.typeParameters?.accept(this);
+    node.parameters?.accept(this);
+  }
+
+  @override
+  void visitMixinDeclaration(MixinDeclaration node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.mixinDeclaration(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        documentationComment_tokens: _nodeCommentTokens(node),
+        nameOffset: node.name.offset,
+      ),
+    );
+
+    node.typeParameters?.accept(this);
+    node.members.accept(this);
+  }
+
+  @override
+  void visitPartDirective(PartDirective node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.partDirective(
+        directiveKeywordOffset: node.keyword.offset,
+      ),
+    );
+  }
+
+  @override
+  void visitPartOfDirective(PartOfDirective node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.partDirective(
+        directiveKeywordOffset: node.keyword.offset,
+      ),
+    );
+  }
+
+  @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.simpleFormalParameter(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        nameOffset: node.identifier?.offset ?? 0,
+      ),
+    );
+  }
+
+  @override
+  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.topLevelVariableDeclaration(
+        documentationComment_tokens: _nodeCommentTokens(node),
+      ),
+    );
+
+    node.variables.accept(this);
+  }
+
+  @override
+  void visitTypeParameter(TypeParameter node) {
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.typeParameter(
+        codeOffset: node.offset,
+        codeLength: node.length,
+        nameOffset: node.name.offset,
+      ),
+    );
+  }
+
+  @override
+  void visitTypeParameterList(TypeParameterList node) {
+    node.typeParameters.accept(this);
+  }
+
+  @override
+  void visitVariableDeclaration(VariableDeclaration node) {
+    var variableList = node.parent as VariableDeclarationList;
+    var isFirst = identical(variableList.variables[0], node);
+    var codeOffset = (isFirst ? variableList.parent : node).offset;
+    var codeLength = node.end - codeOffset;
+
+    setData(
+      node,
+      UnlinkedInformativeDataBuilder.variableDeclaration(
+        codeOffset: codeOffset,
+        codeLength: codeLength,
+        nameOffset: node.name.offset,
+      ),
+    );
+  }
+
+  @override
+  void visitVariableDeclarationList(VariableDeclarationList node) {
+    node.variables.accept(this);
+  }
+
+  static List<String> _commentTokens(Comment comment) {
+    if (comment == null) return null;
+    return comment.tokens.map((token) => token.lexeme).toList();
+  }
+
+  static List<String> _nodeCommentTokens(AnnotatedNode node) {
+    return _commentTokens(node.documentationComment);
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/lazy_ast.dart b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
index 77b9527..9537838 100644
--- a/pkg/analyzer/lib/src/summary2/lazy_ast.dart
+++ b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
@@ -5,21 +5,40 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_flags.dart';
 import 'package:analyzer/src/summary2/ast_binary_reader.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
 
 /// Accessor for reading AST lazily, or read data that is stored in IDL, but
 /// cannot be stored in AST, like inferred types.
 class LazyAst {
+  static const _defaultTypedKey = 'lazyAst_defaultType';
+  static const _genericFunctionTypeIdKey = 'lazyAst_genericFunctionTypeId';
   static const _hasOverrideInferenceKey = 'lazyAst_hasOverrideInference';
+  static const _inheritsCovariantKey = 'lazyAst_isCovariant';
   static const _isSimplyBoundedKey = 'lazyAst_simplyBounded';
   static const _returnTypeKey = 'lazyAst_returnType';
+  static const _typeInferenceErrorKey = 'lazyAst_typeInferenceError';
   static const _typeKey = 'lazyAst_type';
 
   final LinkedNode data;
 
   LazyAst(this.data);
 
+  static DartType getDefaultType(TypeParameter node) {
+    return node.getProperty(_defaultTypedKey);
+  }
+
+  static int getGenericFunctionTypeId(GenericFunctionType node) {
+    return node.getProperty(_genericFunctionTypeIdKey);
+  }
+
+  static bool getInheritsCovariant(AstNode node) {
+    return node.getProperty(_inheritsCovariantKey) ?? false;
+  }
+
   static DartType getReturnType(AstNode node) {
     return node.getProperty(_returnTypeKey);
   }
@@ -28,6 +47,10 @@
     return node.getProperty(_typeKey);
   }
 
+  static TopLevelInferenceError getTypeInferenceError(AstNode node) {
+    return node.getProperty(_typeInferenceErrorKey);
+  }
+
   static bool hasOverrideInferenceDone(AstNode node) {
     return node.getProperty(_hasOverrideInferenceKey) ?? false;
   }
@@ -36,6 +59,18 @@
     return node.getProperty(_isSimplyBoundedKey);
   }
 
+  static void setDefaultType(TypeParameter node, DartType type) {
+    node.setProperty(_defaultTypedKey, type);
+  }
+
+  static void setGenericFunctionTypeId(GenericFunctionType node, int id) {
+    node.setProperty(_genericFunctionTypeIdKey, id);
+  }
+
+  static void setInheritsCovariant(AstNode node, bool value) {
+    node.setProperty(_inheritsCovariantKey, value);
+  }
+
   static void setOverrideInferenceDone(AstNode node) {
     node.setProperty(_hasOverrideInferenceKey, true);
   }
@@ -51,6 +86,11 @@
   static void setType(AstNode node, DartType type) {
     node.setProperty(_typeKey, type);
   }
+
+  static void setTypeInferenceError(
+      AstNode node, TopLevelInferenceError error) {
+    node.setProperty(_typeInferenceErrorKey, error);
+  }
 }
 
 class LazyClassDeclaration {
@@ -71,15 +111,35 @@
     return node.getProperty(_key);
   }
 
-  static void readDocumentationComment(
-    AstBinaryReader reader,
+  static int getCodeLength(
+    LinkedUnitContext context,
     ClassDeclaration node,
   ) {
-    var lazy = LazyClassDeclaration.get(node);
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    ClassDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
+  static void readDocumentationComment(
+    LinkedUnitContext context,
+    ClassDeclaration node,
+  ) {
+    var lazy = get(node);
     if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -101,7 +161,7 @@
     AstBinaryReader reader,
     ClassDeclaration node,
   ) {
-    var lazy = LazyClassDeclaration.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasImplementsClause) {
       node.implementsClause = reader.readNode(
         lazy.data.classOrMixinDeclaration_implementsClause,
@@ -114,7 +174,7 @@
     AstBinaryReader reader,
     ClassDeclaration node,
   ) {
-    var lazy = LazyClassDeclaration.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasMembers) {
       var dataList = lazy.data.classOrMixinDeclaration_members;
       for (var i = 0; i < dataList.length; ++i) {
@@ -129,7 +189,7 @@
     AstBinaryReader reader,
     ClassDeclaration node,
   ) {
-    var lazy = LazyClassDeclaration.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasMetadata) {
       var dataList = lazy.data.annotatedNode_metadata;
       for (var i = 0; i < dataList.length; ++i) {
@@ -144,7 +204,7 @@
     AstBinaryReader reader,
     ClassDeclaration node,
   ) {
-    var lazy = LazyClassDeclaration.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasWithClause) {
       node.withClause = reader.readNode(
         lazy.data.classDeclaration_withClause,
@@ -176,15 +236,35 @@
     return node.getProperty(_key);
   }
 
-  static void readDocumentationComment(
-    AstBinaryReader reader,
+  static int getCodeLength(
+    LinkedUnitContext context,
     ClassTypeAlias node,
   ) {
-    var lazy = LazyClassTypeAlias.get(node);
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    ClassTypeAlias node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
+  static void readDocumentationComment(
+    LinkedUnitContext context,
+    ClassTypeAlias node,
+  ) {
+    var lazy = get(node);
     if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -193,7 +273,7 @@
     AstBinaryReader reader,
     ClassTypeAlias node,
   ) {
-    var lazy = LazyClassTypeAlias.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasImplementsClause) {
       node.implementsClause = reader.readNode(
         lazy.data.classTypeAlias_implementsClause,
@@ -221,14 +301,12 @@
     AstBinaryReader reader,
     ClassTypeAlias node,
   ) {
-    if (reader.isLazy) {
-      var lazy = get(node);
-      if (!lazy._hasSuperclass) {
-        node.superclass = reader.readNode(
-          lazy.data.classTypeAlias_superclass,
-        );
-        lazy._hasSuperclass = true;
-      }
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasSuperclass) {
+      node.superclass = reader.readNode(
+        lazy.data.classTypeAlias_superclass,
+      );
+      lazy._hasSuperclass = true;
     }
   }
 
@@ -236,7 +314,7 @@
     AstBinaryReader reader,
     ClassTypeAlias node,
   ) {
-    var lazy = LazyClassTypeAlias.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasWithClause) {
       node.withClause = reader.readNode(
         lazy.data.classTypeAlias_withClause,
@@ -251,6 +329,44 @@
   }
 }
 
+class LazyCompilationUnit {
+  static const _key = 'lazyAst';
+
+  final LinkedNode data;
+
+  LazyCompilationUnit(this.data);
+
+  static LazyCompilationUnit get(CompilationUnit node) {
+    return node.getProperty(_key);
+  }
+
+  static int getCodeLength(
+    LinkedUnitContext context,
+    CompilationUnit node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    CompilationUnit node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
+  static void setData(CompilationUnit node, LinkedNode data) {
+    node.setProperty(_key, LazyCompilationUnit(data));
+  }
+}
+
 class LazyConstructorDeclaration {
   static const _key = 'lazyAst';
 
@@ -269,6 +385,28 @@
     return node.getProperty(_key);
   }
 
+  static int getCodeLength(
+    LinkedUnitContext context,
+    ConstructorDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    ConstructorDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
   static void readBody(
     AstBinaryReader reader,
     ConstructorDeclaration node,
@@ -283,14 +421,12 @@
   }
 
   static void readDocumentationComment(
-    AstBinaryReader reader,
+    LinkedUnitContext context,
     ConstructorDeclaration node,
   ) {
-    var lazy = LazyConstructorDeclaration.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -299,7 +435,7 @@
     AstBinaryReader reader,
     ConstructorDeclaration node,
   ) {
-    var lazy = LazyConstructorDeclaration.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasFormalParameters) {
       node.parameters = reader.readNode(
         lazy.data.constructorDeclaration_parameters,
@@ -413,14 +549,12 @@
   }
 
   static void readDocumentationComment(
-    AstBinaryReader reader,
+    LinkedUnitContext context,
     EnumConstantDeclaration node,
   ) {
     var lazy = get(node);
     if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -460,6 +594,28 @@
     return node.getProperty(_key);
   }
 
+  static int getCodeLength(
+    LinkedUnitContext context,
+    EnumDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    EnumDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
   static void readConstants(
     AstBinaryReader reader,
     EnumDeclaration node,
@@ -476,14 +632,12 @@
   }
 
   static void readDocumentationComment(
-    AstBinaryReader reader,
+    LinkedUnitContext context,
     EnumDeclaration node,
   ) {
     var lazy = get(node);
     if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -523,14 +677,12 @@
   }
 
   static void readDocumentationComment(
-    AstBinaryReader reader,
+    LinkedUnitContext context,
     FieldDeclaration node,
   ) {
     var lazy = get(node);
     if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -561,8 +713,11 @@
   final LinkedNode data;
 
   bool _hasDefaultValue = false;
+  bool _hasFormalParameters = false;
   bool _hasMetadata = false;
   bool _hasType = false;
+  bool _hasTypeInferenceError = false;
+  bool _hasTypeNode = false;
 
   LazyFormalParameter(this.data);
 
@@ -570,33 +725,89 @@
     return node.getProperty(_key);
   }
 
+  static int getCodeLength(
+    LinkedUnitContext context,
+    FormalParameter node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    FormalParameter node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
   static DartType getType(
     AstBinaryReader reader,
     FormalParameter node,
   ) {
-    if (reader.isLazy) {
-      var lazy = get(node);
-      if (!lazy._hasType) {
-        var type = reader.readType(lazy.data.actualType);
-        LazyAst.setType(node, type);
-        lazy._hasType = true;
-      }
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasType) {
+      var type = reader.readType(lazy.data.actualType);
+      LazyAst.setType(node, type);
+      lazy._hasType = true;
     }
     return LazyAst.getType(node);
   }
 
+  static TopLevelInferenceError getTypeInferenceError(FormalParameter node) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasTypeInferenceError) {
+      var error = lazy.data.topLevelTypeInferenceError;
+      LazyAst.setTypeInferenceError(node, error);
+      lazy._hasTypeInferenceError = true;
+    }
+    return LazyAst.getTypeInferenceError(node);
+  }
+
+  static bool hasDefaultValue(DefaultFormalParameter node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return AstBinaryFlags.hasInitializer(lazy.data.flags);
+    } else {
+      return node.defaultValue != null;
+    }
+  }
+
   static void readDefaultValue(
     AstBinaryReader reader,
     DefaultFormalParameter node,
   ) {
-    if (reader.isLazy) {
-      var lazy = LazyFormalParameter.get(node);
-      if (lazy != null && !lazy._hasDefaultValue) {
-        node.defaultValue = reader.readNode(
-          lazy.data.defaultFormalParameter_defaultValue,
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasDefaultValue) {
+      node.defaultValue = reader.readNode(
+        lazy.data.defaultFormalParameter_defaultValue,
+      );
+      lazy._hasDefaultValue = true;
+    }
+  }
+
+  static void readFormalParameters(
+    AstBinaryReader reader,
+    FormalParameter node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasFormalParameters) {
+      if (node is FunctionTypedFormalParameter) {
+        node.parameters = reader.readNode(
+          lazy.data.functionTypedFormalParameter_formalParameters,
         );
-        lazy._hasDefaultValue = true;
+      } else if (node is FieldFormalParameter) {
+        node.parameters = reader.readNode(
+          lazy.data.fieldFormalParameter_formalParameters,
+        );
       }
+      lazy._hasFormalParameters = true;
     }
   }
 
@@ -615,6 +826,21 @@
     }
   }
 
+  static void readTypeNode(
+    AstBinaryReader reader,
+    FormalParameter node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasTypeNode) {
+      if (node is SimpleFormalParameter) {
+        node.type = reader.readNode(
+          lazy.data.simpleFormalParameter_type,
+        );
+      }
+      lazy._hasTypeNode = true;
+    }
+  }
+
   static void setData(FormalParameter node, LinkedNode data) {
     node.setProperty(_key, LazyFormalParameter(data));
   }
@@ -628,6 +854,7 @@
   bool _hasDocumentationComment = false;
   bool _hasMetadata = false;
   bool _hasReturnType = false;
+  bool _hasReturnTypeNode = false;
 
   LazyFunctionDeclaration(this.data);
 
@@ -635,31 +862,51 @@
     return node.getProperty(_key);
   }
 
+  static int getCodeLength(
+    LinkedUnitContext context,
+    FunctionDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    FunctionDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
   static DartType getReturnType(
     AstBinaryReader reader,
     FunctionDeclaration node,
   ) {
     readFunctionExpression(reader, node);
-    if (reader.isLazy) {
-      var lazy = get(node);
-      if (!lazy._hasReturnType) {
-        var type = reader.readType(lazy.data.actualReturnType);
-        LazyAst.setReturnType(node, type);
-        lazy._hasReturnType = true;
-      }
+
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasReturnType) {
+      var type = reader.readType(lazy.data.actualReturnType);
+      LazyAst.setReturnType(node, type);
+      lazy._hasReturnType = true;
     }
+
     return LazyAst.getReturnType(node);
   }
 
   static void readDocumentationComment(
-    AstBinaryReader reader,
+    LinkedUnitContext context,
     FunctionDeclaration node,
   ) {
-    var lazy = LazyFunctionDeclaration.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -669,7 +916,7 @@
     FunctionDeclaration node,
   ) {
     if (node.functionExpression == null) {
-      var lazy = LazyFunctionDeclaration.get(node);
+      var lazy = get(node);
       node.functionExpression = reader.readNode(
         lazy.data.functionDeclaration_functionExpression,
       );
@@ -691,6 +938,19 @@
     }
   }
 
+  static void readReturnTypeNode(
+    AstBinaryReader reader,
+    FunctionDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasReturnTypeNode) {
+      node.returnType = reader.readNode(
+        lazy.data.functionDeclaration_returnType,
+      );
+      lazy._hasReturnTypeNode = true;
+    }
+  }
+
   static void setData(FunctionDeclaration node, LinkedNode data) {
     node.setProperty(_key, LazyFunctionDeclaration(data));
   }
@@ -710,6 +970,24 @@
     return node.getProperty(_key);
   }
 
+  static bool isAsynchronous(FunctionExpression node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return AstBinaryFlags.isAsync(lazy.data.flags);
+    } else {
+      return node.body.isAsynchronous;
+    }
+  }
+
+  static bool isGenerator(FunctionExpression node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return AstBinaryFlags.isGenerator(lazy.data.flags);
+    } else {
+      return node.body.isGenerator;
+    }
+  }
+
   static void readBody(
     AstBinaryReader reader,
     FunctionExpression node,
@@ -743,6 +1021,7 @@
 
 class LazyFunctionTypeAlias {
   static const _key = 'lazyAst';
+  static const _hasSelfReferenceKey = 'lazyAst_hasSelfReferenceKey';
 
   final LinkedNode data;
 
@@ -750,6 +1029,7 @@
   bool _hasFormalParameters = false;
   bool _hasMetadata = false;
   bool _hasReturnType = false;
+  bool _hasReturnTypeNode = false;
 
   LazyFunctionTypeAlias(this.data);
 
@@ -757,30 +1037,52 @@
     return node.getProperty(_key);
   }
 
+  static int getCodeLength(
+    LinkedUnitContext context,
+    FunctionTypeAlias node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    FunctionTypeAlias node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
+  static bool getHasSelfReference(FunctionTypeAlias node) {
+    return node.getProperty(_hasSelfReferenceKey);
+  }
+
   static DartType getReturnType(
     AstBinaryReader reader,
     FunctionTypeAlias node,
   ) {
-    if (reader.isLazy) {
-      var lazy = get(node);
-      if (!lazy._hasReturnType) {
-        var type = reader.readType(lazy.data.actualReturnType);
-        LazyAst.setReturnType(node, type);
-        lazy._hasReturnType = true;
-      }
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasReturnType) {
+      var type = reader.readType(lazy.data.actualReturnType);
+      LazyAst.setReturnType(node, type);
+      lazy._hasReturnType = true;
     }
     return LazyAst.getReturnType(node);
   }
 
   static void readDocumentationComment(
-    AstBinaryReader reader,
+    LinkedUnitContext context,
     FunctionTypeAlias node,
   ) {
     var lazy = get(node);
     if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -789,7 +1091,7 @@
     AstBinaryReader reader,
     FunctionTypeAlias node,
   ) {
-    var lazy = LazyFunctionTypeAlias.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasFormalParameters) {
       node.parameters = reader.readNode(
         lazy.data.functionTypeAlias_formalParameters,
@@ -813,66 +1115,38 @@
     }
   }
 
+  static void readReturnTypeNode(
+    AstBinaryReader reader,
+    FunctionTypeAlias node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasReturnTypeNode) {
+      node.returnType = reader.readNode(
+        lazy.data.functionTypeAlias_returnType,
+      );
+      lazy._hasReturnTypeNode = true;
+    }
+  }
+
   static void setData(FunctionTypeAlias node, LinkedNode data) {
     node.setProperty(_key, LazyFunctionTypeAlias(data));
     LazyAst.setSimplyBounded(node, data.simplyBoundable_isSimplyBounded);
   }
-}
 
-class LazyGenericFunctionType {
-  static const _key = 'lazyAst';
-
-  final LinkedNode data;
-
-  bool _hasFormalParameters = false;
-  bool _hasReturnType = false;
-
-  LazyGenericFunctionType(this.data);
-
-  static LazyGenericFunctionType get(GenericFunctionType node) {
-    return node.getProperty(_key);
-  }
-
-  static DartType getReturnType(
-    AstBinaryReader reader,
-    GenericFunctionType node,
-  ) {
-    if (reader.isLazy) {
-      var lazy = get(node);
-      if (!lazy._hasReturnType) {
-        var type = reader.readType(lazy.data.actualReturnType);
-        LazyAst.setReturnType(node, type);
-        lazy._hasReturnType = true;
-      }
-    }
-    return LazyAst.getReturnType(node);
-  }
-
-  static void readFormalParameters(
-    AstBinaryReader reader,
-    GenericFunctionType node,
-  ) {
-    var lazy = get(node);
-    if (lazy != null && !lazy._hasFormalParameters) {
-      node.parameters = reader.readNode(
-        lazy.data.genericFunctionType_formalParameters,
-      );
-      lazy._hasFormalParameters = true;
-    }
-  }
-
-  static void setData(GenericFunctionType node, LinkedNode data) {
-    node.setProperty(_key, LazyGenericFunctionType(data));
+  static void setHasSelfReference(FunctionTypeAlias node, bool value) {
+    node.setProperty(_hasSelfReferenceKey, value);
   }
 }
 
 class LazyGenericTypeAlias {
   static const _key = 'lazyAst';
+  static const _hasSelfReferenceKey = 'lazyAst_hasSelfReferenceKey';
 
   final LinkedNode data;
 
   bool _hasDocumentationComment = false;
   bool _hasFunction = false;
+  bool _hasMetadata = false;
 
   LazyGenericTypeAlias(this.data);
 
@@ -880,15 +1154,39 @@
     return node.getProperty(_key);
   }
 
+  static int getCodeLength(
+    LinkedUnitContext context,
+    GenericTypeAlias node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    GenericTypeAlias node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
+  static bool getHasSelfReference(GenericTypeAlias node) {
+    return node.getProperty(_hasSelfReferenceKey);
+  }
+
   static void readDocumentationComment(
-    AstBinaryReader reader,
+    LinkedUnitContext context,
     GenericTypeAlias node,
   ) {
     var lazy = get(node);
     if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -906,10 +1204,29 @@
     }
   }
 
+  static void readMetadata(
+    AstBinaryReader reader,
+    GenericTypeAlias node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasMetadata) {
+      var dataList = lazy.data.annotatedNode_metadata;
+      for (var i = 0; i < dataList.length; ++i) {
+        var data = dataList[i];
+        node.metadata[i] = reader.readNode(data);
+      }
+      lazy._hasMetadata = true;
+    }
+  }
+
   static void setData(GenericTypeAlias node, LinkedNode data) {
     node.setProperty(_key, LazyGenericTypeAlias(data));
     LazyAst.setSimplyBounded(node, data.simplyBoundable_isSimplyBounded);
   }
+
+  static void setHasSelfReference(GenericTypeAlias node, bool value) {
+    node.setProperty(_hasSelfReferenceKey, value);
+  }
 }
 
 class LazyMethodDeclaration {
@@ -922,6 +1239,7 @@
   bool _hasFormalParameters = false;
   bool _hasMetadata = false;
   bool _hasReturnType = false;
+  bool _hasReturnTypeNode = false;
 
   LazyMethodDeclaration(this.data);
 
@@ -929,21 +1247,68 @@
     return node.getProperty(_key);
   }
 
+  static int getCodeLength(
+    LinkedUnitContext context,
+    MethodDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    MethodDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
   static DartType getReturnType(
     AstBinaryReader reader,
     MethodDeclaration node,
   ) {
-    if (reader.isLazy) {
-      var lazy = get(node);
-      if (!lazy._hasReturnType) {
-        var type = reader.readType(lazy.data.actualReturnType);
-        LazyAst.setReturnType(node, type);
-        lazy._hasReturnType = true;
-      }
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasReturnType) {
+      var type = reader.readType(lazy.data.actualReturnType);
+      LazyAst.setReturnType(node, type);
+      lazy._hasReturnType = true;
     }
     return LazyAst.getReturnType(node);
   }
 
+  static bool isAbstract(MethodDeclaration node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return AstBinaryFlags.isAbstract(lazy.data.flags);
+    } else {
+      return node.isAbstract;
+    }
+  }
+
+  static bool isAsynchronous(MethodDeclaration node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return AstBinaryFlags.isAsync(lazy.data.flags);
+    } else {
+      return node.body.isAsynchronous;
+    }
+  }
+
+  static bool isGenerator(MethodDeclaration node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return AstBinaryFlags.isGenerator(lazy.data.flags);
+    } else {
+      return node.body.isGenerator;
+    }
+  }
+
   static void readBody(
     AstBinaryReader reader,
     MethodDeclaration node,
@@ -958,14 +1323,12 @@
   }
 
   static void readDocumentationComment(
-    AstBinaryReader reader,
+    LinkedUnitContext context,
     MethodDeclaration node,
   ) {
-    var lazy = LazyMethodDeclaration.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -974,7 +1337,7 @@
     AstBinaryReader reader,
     MethodDeclaration node,
   ) {
-    var lazy = LazyMethodDeclaration.get(node);
+    var lazy = get(node);
     if (lazy != null && !lazy._hasFormalParameters) {
       node.parameters = reader.readNode(
         lazy.data.methodDeclaration_formalParameters,
@@ -998,6 +1361,19 @@
     }
   }
 
+  static void readReturnTypeNode(
+    AstBinaryReader reader,
+    MethodDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasReturnTypeNode) {
+      node.returnType = reader.readNode(
+        lazy.data.methodDeclaration_returnType,
+      );
+      lazy._hasReturnTypeNode = true;
+    }
+  }
+
   static void setData(MethodDeclaration node, LinkedNode data) {
     node.setProperty(_key, LazyMethodDeclaration(data));
   }
@@ -1012,22 +1388,66 @@
   bool _hasOnClause = false;
   bool _hasImplementsClause = false;
   bool _hasMembers = false;
+  bool _hasMetadata = false;
 
-  LazyMixinDeclaration(this.data);
+  List<String> _superInvokedNames;
 
-  static LazyMixinDeclaration get(MixinDeclaration node) {
-    return node.getProperty(_key);
+  LazyMixinDeclaration(MixinDeclaration node, this.data) {
+    node.setProperty(_key, this);
+    if (data != null) {
+      LazyAst.setSimplyBounded(node, data.simplyBoundable_isSimplyBounded);
+    }
   }
 
-  static void readDocumentationComment(
-    AstBinaryReader reader,
+  List<String> getSuperInvokedNames() {
+    return _superInvokedNames ??= data.mixinDeclaration_superInvokedNames;
+  }
+
+  void put(LinkedNodeBuilder builder) {
+    builder.mixinDeclaration_superInvokedNames = _superInvokedNames ?? [];
+  }
+
+  void setSuperInvokedNames(List<String> value) {
+    _superInvokedNames = value;
+  }
+
+  static LazyMixinDeclaration get(MixinDeclaration node) {
+    LazyMixinDeclaration lazy = node.getProperty(_key);
+    if (lazy == null) {
+      return LazyMixinDeclaration(node, null);
+    }
+    return lazy;
+  }
+
+  static int getCodeLength(
+    LinkedUnitContext context,
     MixinDeclaration node,
   ) {
     var lazy = get(node);
-    if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    MixinDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
+  static void readDocumentationComment(
+    LinkedUnitContext context,
+    MixinDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy.data != null && !lazy._hasDocumentationComment) {
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -1037,7 +1457,7 @@
     MixinDeclarationImpl node,
   ) {
     var lazy = get(node);
-    if (lazy != null && !lazy._hasImplementsClause) {
+    if (lazy.data != null && !lazy._hasImplementsClause) {
       node.implementsClause = reader.readNode(
         lazy.data.classOrMixinDeclaration_implementsClause,
       );
@@ -1050,7 +1470,7 @@
     MixinDeclaration node,
   ) {
     var lazy = get(node);
-    if (lazy != null && !lazy._hasMembers) {
+    if (lazy.data != null && !lazy._hasMembers) {
       var dataList = lazy.data.classOrMixinDeclaration_members;
       for (var i = 0; i < dataList.length; ++i) {
         var data = dataList[i];
@@ -1060,23 +1480,33 @@
     }
   }
 
+  static void readMetadata(
+    AstBinaryReader reader,
+    MixinDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy.data != null && !lazy._hasMetadata) {
+      var dataList = lazy.data.annotatedNode_metadata;
+      for (var i = 0; i < dataList.length; ++i) {
+        var data = dataList[i];
+        node.metadata[i] = reader.readNode(data);
+      }
+      lazy._hasMetadata = true;
+    }
+  }
+
   static void readOnClause(
     AstBinaryReader reader,
     MixinDeclarationImpl node,
   ) {
     var lazy = get(node);
-    if (lazy != null && !lazy._hasOnClause) {
+    if (lazy.data != null && !lazy._hasOnClause) {
       node.onClause = reader.readNode(
         lazy.data.mixinDeclaration_onClause,
       );
       lazy._hasOnClause = true;
     }
   }
-
-  static void setData(MixinDeclaration node, LinkedNode data) {
-    node.setProperty(_key, LazyMixinDeclaration(data));
-    LazyAst.setSimplyBounded(node, data.simplyBoundable_isSimplyBounded);
-  }
 }
 
 class LazyTopLevelVariableDeclaration {
@@ -1094,14 +1524,12 @@
   }
 
   static void readDocumentationComment(
-    AstBinaryReader reader,
+    LinkedUnitContext context,
     TopLevelVariableDeclaration node,
   ) {
     var lazy = get(node);
     if (lazy != null && !lazy._hasDocumentationComment) {
-      node.documentationComment = reader.readNode(
-        lazy.data.annotatedNode_comment,
-      );
+      node.documentationComment = context.createComment(lazy.data);
       lazy._hasDocumentationComment = true;
     }
   }
@@ -1132,6 +1560,8 @@
   final LinkedNode data;
 
   bool _hasBound = false;
+  bool _hasDefaultType = false;
+  bool _hasMetadata = false;
 
   LazyTypeParameter(this.data);
 
@@ -1139,6 +1569,39 @@
     return node.getProperty(_key);
   }
 
+  static int getCodeLength(
+    LinkedUnitContext context,
+    TypeParameter node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    return node.length;
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    TypeParameter node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    return node.offset;
+  }
+
+  static DartType getDefaultType(AstBinaryReader reader, TypeParameter node) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasDefaultType) {
+      lazy._hasDefaultType = true;
+      var type = reader.readType(lazy.data.typeParameter_defaultType);
+      LazyAst.setDefaultType(node, type);
+      return type;
+    }
+    return LazyAst.getDefaultType(node);
+  }
+
   static void readBound(AstBinaryReader reader, TypeParameter node) {
     var lazy = get(node);
     if (lazy != null && !lazy._hasBound) {
@@ -1147,6 +1610,21 @@
     }
   }
 
+  static void readMetadata(
+    AstBinaryReader reader,
+    TypeParameter node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasMetadata) {
+      var dataList = lazy.data.annotatedNode_metadata;
+      for (var i = 0; i < dataList.length; ++i) {
+        var data = dataList[i];
+        node.metadata[i] = reader.readNode(data);
+      }
+      lazy._hasMetadata = true;
+    }
+  }
+
   static void setData(TypeParameter node, LinkedNode data) {
     node.setProperty(_key, LazyTypeParameter(data));
   }
@@ -1159,6 +1637,7 @@
 
   bool _hasInitializer = false;
   bool _hasType = false;
+  bool _hasTypeInferenceError = false;
 
   LazyVariableDeclaration(this.data);
 
@@ -1166,33 +1645,81 @@
     return node.getProperty(_key);
   }
 
+  static int getCodeLength(
+    LinkedUnitContext context,
+    VariableDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeLength ?? 0;
+    }
+    VariableDeclarationList parent = node.parent;
+    if (parent.variables[0] == node) {
+      return node.end - parent.offset;
+    } else {
+      return node.end - node.offset;
+    }
+  }
+
+  static int getCodeOffset(
+    LinkedUnitContext context,
+    VariableDeclaration node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return context.getInformativeData(lazy.data)?.codeOffset ?? 0;
+    }
+    VariableDeclarationList parent = node.parent;
+    if (parent.variables[0] == node) {
+      return parent.offset;
+    } else {
+      return node.offset;
+    }
+  }
+
   static DartType getType(
     AstBinaryReader reader,
     VariableDeclaration node,
   ) {
-    if (reader.isLazy) {
-      var lazy = get(node);
-      if (!lazy._hasType) {
-        var type = reader.readType(lazy.data.actualType);
-        LazyAst.setType(node, type);
-        lazy._hasType = true;
-      }
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasType) {
+      var type = reader.readType(lazy.data.actualType);
+      LazyAst.setType(node, type);
+      lazy._hasType = true;
     }
     return LazyAst.getType(node);
   }
 
+  static TopLevelInferenceError getTypeInferenceError(
+      VariableDeclaration node) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasTypeInferenceError) {
+      var error = lazy.data.topLevelTypeInferenceError;
+      LazyAst.setTypeInferenceError(node, error);
+      lazy._hasTypeInferenceError = true;
+    }
+    return LazyAst.getTypeInferenceError(node);
+  }
+
+  static bool hasInitializer(VariableDeclaration node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return AstBinaryFlags.hasInitializer(lazy.data.flags);
+    } else {
+      return node.initializer != null;
+    }
+  }
+
   static void readInitializer(
     AstBinaryReader reader,
     VariableDeclaration node,
   ) {
-    if (reader.isLazy) {
-      var lazy = get(node);
-      if (lazy != null && !lazy._hasInitializer) {
-        node.initializer = reader.readNode(
-          lazy.data.variableDeclaration_initializer,
-        );
-        lazy._hasInitializer = true;
-      }
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasInitializer) {
+      node.initializer = reader.readNode(
+        lazy.data.variableDeclaration_initializer,
+      );
+      lazy._hasInitializer = true;
     }
   }
 
@@ -1200,3 +1727,34 @@
     node.setProperty(_key, LazyVariableDeclaration(data));
   }
 }
+
+class LazyVariableDeclarationList {
+  static const _key = 'lazyAst';
+
+  final LinkedNode data;
+
+  bool _hasTypeNode = false;
+
+  LazyVariableDeclarationList(this.data);
+
+  static LazyVariableDeclarationList get(VariableDeclarationList node) {
+    return node.getProperty(_key);
+  }
+
+  static void readTypeNode(
+    AstBinaryReader reader,
+    VariableDeclarationList node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasTypeNode) {
+      node.type = reader.readNode(
+        lazy.data.variableDeclarationList_type,
+      );
+      lazy._hasTypeNode = true;
+    }
+  }
+
+  static void setData(VariableDeclarationList node, LinkedNode data) {
+    node.setProperty(_key, LazyVariableDeclarationList(data));
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index 77430ea..af4948d 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -2,10 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/ast/ast.dart' show AstNode, CompilationUnit;
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -13,7 +12,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/summary_sdk.dart';
 import 'package:analyzer/src/summary2/ast_binary_writer.dart';
 import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
@@ -22,27 +20,24 @@
 import 'package:analyzer/src/summary2/linking_bundle_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/summary2/simply_bounded.dart';
-import 'package:analyzer/src/summary2/tokens_writer.dart';
 import 'package:analyzer/src/summary2/top_level_inference.dart';
-import 'package:analyzer/src/summary2/type_builder.dart';
+import 'package:analyzer/src/summary2/type_alias.dart';
+import 'package:analyzer/src/summary2/types_builder.dart';
+
+var timerLinkingLinkingBundle = Stopwatch();
+var timerLinkingRemoveBundle = Stopwatch();
 
 LinkResult link(
-  AnalysisOptions analysisOptions,
-  SourceFactory sourceFactory,
-  DeclaredVariables declaredVariables,
-  List<LinkedNodeBundle> inputBundles,
+  LinkedElementFactory elementFactory,
   List<LinkInputLibrary> inputLibraries,
 ) {
-  var linker = Linker(analysisOptions, sourceFactory, declaredVariables);
-  linker.link(inputBundles, inputLibraries);
+  var linker = Linker(elementFactory);
+  linker.link(inputLibraries);
   return LinkResult(linker.linkingBundle);
 }
 
 class Linker {
-  final DeclaredVariables declaredVariables;
-
-  final Reference rootReference = Reference.root();
-  LinkedElementFactory elementFactory;
+  final LinkedElementFactory elementFactory;
 
   LinkedNodeBundleBuilder linkingBundle;
   LinkedBundleContext bundleContext;
@@ -51,30 +46,11 @@
   /// Libraries that are being linked.
   final Map<Uri, SourceLibraryBuilder> builders = {};
 
-  _AnalysisContextForLinking analysisContext;
-  TypeProvider typeProvider;
-  Dart2TypeSystem typeSystem;
-  InheritanceManager2 inheritance;
+  InheritanceManager2 inheritance; // TODO(scheglov) cache it
 
-  Linker(
-    AnalysisOptions analysisOptions,
-    SourceFactory sourceFactory,
-    this.declaredVariables,
-  ) {
-    var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
-    dynamicRef.element = DynamicElementImpl.instance;
-
-    linkingBundleContext = LinkingBundleContext(dynamicRef);
-
-    analysisContext = _AnalysisContextForLinking(
-      analysisOptions,
-      sourceFactory,
-    );
-
-    elementFactory = LinkedElementFactory(
-      analysisContext,
-      _AnalysisSessionForLinking(),
-      rootReference,
+  Linker(this.elementFactory) {
+    linkingBundleContext = LinkingBundleContext(
+      elementFactory.dynamicRef,
     );
 
     bundleContext = LinkedBundleContext.forAst(
@@ -83,13 +59,25 @@
     );
   }
 
-  void link(List<LinkedNodeBundle> inputBundles,
-      List<LinkInputLibrary> inputLibraries) {
-    for (var input in inputBundles) {
-      var inputBundleContext = LinkedBundleContext(elementFactory, input);
-      elementFactory.addBundle(inputBundleContext);
-    }
+  InternalAnalysisContext get analysisContext {
+    return elementFactory.analysisContext;
+  }
 
+  FeatureSet get contextFeatures {
+    return analysisContext.analysisOptions.contextFeatures;
+  }
+
+  DeclaredVariables get declaredVariables {
+    return analysisContext.declaredVariables;
+  }
+
+  Reference get rootReference => elementFactory.rootReference;
+
+  TypeProvider get typeProvider => analysisContext.typeProvider;
+
+  Dart2TypeSystem get typeSystem => analysisContext.typeSystem;
+
+  void link(List<LinkInputLibrary> inputLibraries) {
     for (var inputLibrary in inputLibraries) {
       SourceLibraryBuilder.build(this, inputLibrary);
     }
@@ -98,41 +86,54 @@
 
     _buildOutlines();
 
+    timerLinkingLinkingBundle.start();
     _createLinkingBundle();
-  }
+    timerLinkingLinkingBundle.stop();
 
-  void _addExporters() {
-    for (var library in builders.values) {
-      library.addExporters();
-    }
-  }
-
-  void _addSyntheticConstructors() {
-    for (var library in builders.values) {
-      library.addSyntheticConstructors();
-    }
+    timerLinkingRemoveBundle.start();
+    linkingBundleContext.clearIndexes();
+    elementFactory.removeBundle(bundleContext);
+    timerLinkingRemoveBundle.stop();
   }
 
   void _buildOutlines() {
     _resolveUriDirectives();
-    _addExporters();
     _computeLibraryScopes();
-    _addSyntheticConstructors();
     _createTypeSystem();
     _resolveTypes();
+    TypeAliasSelfReferenceFinder().perform(this);
     _createLoadLibraryFunctions();
     _performTopLevelInference();
     _resolveConstructors();
+    _resolveConstantInitializers();
     _resolveDefaultValues();
     _resolveMetadata();
+    _collectMixinSuperInvokedNames();
+  }
+
+  void _collectMixinSuperInvokedNames() {
+    for (var library in builders.values) {
+      library.collectMixinSuperInvokedNames();
+    }
   }
 
   void _computeLibraryScopes() {
+    for (var library in builders.values) {
+      library.addLocalDeclarations();
+    }
+
+    for (var library in builders.values) {
+      library.buildInitialExportScope();
+    }
+
     var exporters = new Set<SourceLibraryBuilder>();
     var exportees = new Set<SourceLibraryBuilder>();
 
     for (var library in builders.values) {
-      library.addLocalDeclarations();
+      library.addExporters();
+    }
+
+    for (var library in builders.values) {
       if (library.exporters.isNotEmpty) {
         exportees.add(library);
         for (var exporter in library.exporters) {
@@ -141,10 +142,6 @@
       }
     }
 
-    for (var library in builders.values) {
-      library.buildInitialExportScope();
-    }
-
     var both = new Set<SourceLibraryBuilder>();
     for (var exported in exportees) {
       if (exporters.contains(exported)) {
@@ -183,21 +180,17 @@
     for (var builder in builders.values) {
       linkingLibraries.add(builder.node);
 
-      for (var unit2 in builder.context.units) {
-        var unit = unit2.unit;
-        var tokensResult = TokensWriter().writeTokens(
-          unit.beginToken,
-          unit.endToken,
-        );
-        var tokensContext = tokensResult.toContext();
+      for (var unitContext in builder.context.units) {
+        var unit = unitContext.unit;
 
-        var writer = new AstBinaryWriter(linkingBundleContext, tokensContext);
-        var unitLinkedNode = writer.writeNode(unit);
+        var writer = AstBinaryWriter(linkingBundleContext);
+        var unitLinkedNode = writer.writeUnit(unit);
         builder.node.units.add(
           LinkedNodeUnitBuilder(
-            uriStr: unit2.uriStr,
-            tokens: tokensResult.tokens,
+            isSynthetic: unitContext.isSynthetic,
+            uriStr: unitContext.uriStr,
             node: unitLinkedNode,
+            isNNBD: unit.featureSet.isEnabled(Feature.non_nullable),
           ),
         );
       }
@@ -215,19 +208,17 @@
   }
 
   void _createTypeSystem() {
-    var coreRef = rootReference.getChild('dart:core');
-    var coreLib = elementFactory.elementOfReference(coreRef);
+    if (typeProvider != null) {
+      inheritance = InheritanceManager2(typeSystem);
+      return;
+    }
 
-    var asyncRef = rootReference.getChild('dart:async');
-    var asyncLib = elementFactory.elementOfReference(asyncRef);
+    var coreLib = elementFactory.libraryOfUri('dart:core');
+    var asyncLib = elementFactory.libraryOfUri('dart:async');
 
-    typeProvider = SummaryTypeProvider()
+    analysisContext.typeProvider = SummaryTypeProvider()
       ..initializeCore(coreLib)
       ..initializeAsync(asyncLib);
-    analysisContext.typeProvider = typeProvider;
-
-    typeSystem = Dart2TypeSystem(typeProvider);
-    analysisContext.typeSystem = typeSystem;
 
     inheritance = InheritanceManager2(typeSystem);
   }
@@ -236,6 +227,10 @@
     TopLevelInference(this).infer();
   }
 
+  void _resolveConstantInitializers() {
+    ConstantInitializersResolver(this).perform();
+  }
+
   void _resolveConstructors() {
     for (var library in builders.values) {
       library.resolveConstructors();
@@ -255,12 +250,12 @@
   }
 
   void _resolveTypes() {
-    var nodesToBuildType = <AstNode>[];
+    var nodesToBuildType = NodesToBuildType();
     for (var library in builders.values) {
       library.resolveTypes(nodesToBuildType);
     }
     computeSimplyBounded(bundleContext, builders.values);
-    TypeBuilder(typeSystem).build(nodesToBuildType);
+    TypesBuilder(typeSystem).build(nodesToBuildType);
   }
 
   void _resolveUriDirectives() {
@@ -279,9 +274,10 @@
 
 class LinkInputUnit {
   final Source source;
+  final bool isSynthetic;
   final CompilationUnit unit;
 
-  LinkInputUnit(this.source, this.unit);
+  LinkInputUnit(this.source, this.isSynthetic, this.unit);
 }
 
 class LinkResult {
@@ -289,32 +285,3 @@
 
   LinkResult(this.bundle);
 }
-
-class _AnalysisContextForLinking implements InternalAnalysisContext {
-  @override
-  final AnalysisOptions analysisOptions;
-
-  @override
-  final SourceFactory sourceFactory;
-
-  @override
-  TypeProvider typeProvider;
-
-  @override
-  TypeSystem typeSystem;
-
-  _AnalysisContextForLinking(this.analysisOptions, this.sourceFactory);
-
-  @override
-  Namespace getPublicNamespace(LibraryElement library) {
-    // TODO(scheglov) Not sure if this method of AnalysisContext is useful.
-    var builder = new NamespaceBuilder();
-    return builder.createPublicNamespaceForLibrary(library);
-  }
-
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-class _AnalysisSessionForLinking implements AnalysisSession {
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
diff --git a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
index bb079ee..4c218be 100644
--- a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/informative_data.dart';
 import 'package:analyzer/src/summary2/link.dart';
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
@@ -20,17 +21,29 @@
   LinkedBundleContext(this.elementFactory, this._bundle)
       : _references = List<Reference>(_bundle.references.name.length) {
     for (var library in _bundle.libraries) {
-      var libraryContext = LinkedLibraryContext(library.uriStr, this, library);
-      libraryMap[library.uriStr] = libraryContext;
+      var uriStr = library.uriStr;
+      var reference = elementFactory.rootReference.getChild(uriStr);
+      var libraryContext = LinkedLibraryContext(
+        this,
+        uriStr,
+        reference,
+        library,
+      );
+      libraryMap[uriStr] = libraryContext;
 
+      var unitRef = reference.getChild('@unit');
       var units = library.units;
       for (var unitIndex = 0; unitIndex < units.length; ++unitIndex) {
         var unit = units[unitIndex];
+        var uriStr = unit.uriStr;
+        var reference = unitRef.getChild(uriStr);
         var unitContext = LinkedUnitContext(
           this,
           libraryContext,
           unitIndex,
-          unit.uriStr,
+          uriStr,
+          reference,
+          unit.isSynthetic,
           unit,
         );
         libraryContext.units.add(unitContext);
@@ -41,25 +54,34 @@
   LinkedBundleContext.forAst(this.elementFactory, this._references)
       : _bundle = null;
 
+  /// Return `true` if this bundle is being linked.
+  bool get isLinking => _bundle == null;
+
   LinkedLibraryContext addLinkingLibrary(
     String uriStr,
     LinkedNodeLibraryBuilder data,
     LinkInputLibrary inputLibrary,
   ) {
     var uriStr = data.uriStr;
-    var libraryContext = LinkedLibraryContext(uriStr, this, data);
+    var reference = elementFactory.rootReference.getChild(uriStr);
+    var libraryContext = LinkedLibraryContext(this, uriStr, reference, data);
     libraryMap[uriStr] = libraryContext;
 
+    var unitRef = reference.getChild('@unit');
     var unitIndex = 0;
     for (var inputUnit in inputLibrary.units) {
       var source = inputUnit.source;
-      var unitUriStr = source != null ? '${source.uri}' : '';
+      var uriStr = source != null ? '${source.uri}' : '';
+      var reference = unitRef.getChild(uriStr);
+      createInformativeData(inputUnit.unit);
       libraryContext.units.add(
         LinkedUnitContext(
           this,
           libraryContext,
           unitIndex++,
-          unitUriStr,
+          uriStr,
+          reference,
+          inputUnit.isSynthetic,
           null,
           unit: inputUnit.unit,
         ),
@@ -104,12 +126,13 @@
 }
 
 class LinkedLibraryContext {
-  final String uriStr;
   final LinkedBundleContext context;
+  final String uriStr;
+  final Reference reference;
   final LinkedNodeLibrary node;
   final List<LinkedUnitContext> units = [];
 
-  LinkedLibraryContext(this.uriStr, this.context, this.node);
+  LinkedLibraryContext(this.context, this.uriStr, this.reference, this.node);
 
   LinkedUnitContext get definingUnit => units.first;
 }
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 41b8880..e1561c0 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -23,12 +23,27 @@
   CoreTypes _coreTypes;
 
   LinkedElementFactory(
-      this.analysisContext, this.analysisSession, this.rootReference);
+    this.analysisContext,
+    this.analysisSession,
+    this.rootReference,
+  ) {
+    var dartCoreRef = rootReference.getChild('dart:core');
+    dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
+    dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
+  }
 
   CoreTypes get coreTypes {
     return _coreTypes ??= CoreTypes(this);
   }
 
+  Reference get dynamicRef {
+    return rootReference.getChild('dart:core').getChild('dynamic');
+  }
+
+  bool get hasDartCore {
+    return libraryMap.containsKey('dart:core');
+  }
+
   void addBundle(LinkedBundleContext context) {
     libraryMap.addAll(context.libraryMap);
   }
@@ -58,6 +73,8 @@
 
   List<Reference> exportsOfLibrary(String uriStr) {
     var library = libraryMap[uriStr];
+    if (library == null) return const [];
+
     var exportIndexList = library.node.exports;
     var exportReferences = List<Reference>(exportIndexList.length);
     for (var i = 0; i < exportIndexList.length; ++i) {
@@ -68,36 +85,40 @@
     return exportReferences;
   }
 
+  bool isLibraryUri(String uriStr) {
+    var libraryContext = libraryMap[uriStr];
+    return !libraryContext.definingUnit.hasPartOfDirective;
+  }
+
   LibraryElementImpl libraryOfUri(String uriStr) {
     var reference = rootReference.getChild(uriStr);
     return elementOfReference(reference);
   }
 
-  LinkedNode nodeOfReference(Reference reference) {
-//    if (reference.node != null) {
-//      return reference.node;
-//    }
-//
-//    var unitRef = reference.parent?.parent;
-//    var unitContainer = unitRef?.parent;
-//    if (unitContainer?.name == '@unit') {
-//      var libraryUriStr = unitContainer.parent.name;
-//      var libraryData = libraryMap[libraryUriStr];
-//      for (var unitData in libraryData.node.units) {
-//        var definingUnitContext = LinkedUnitContext(
-//          libraryData.context,
-//          TokensContext(unitData.tokens),
-//        );
-//        _ElementRequest._indexUnitDeclarations(
-//          definingUnitContext,
-//          unitRef,
-//          unitData.node,
-//        );
-//        return reference.node;
-//      }
-//    }
+  /// We have linked the bundle, and need to disconnect its libraries, so
+  /// that the client can re-add the bundle, this time read from bytes.
+  void removeBundle(LinkedBundleContext context) {
+    for (var uriStr in context.libraryMap.keys) {
+      libraryMap.remove(uriStr);
+      rootReference.removeChild(uriStr);
+    }
+  }
 
-    throw UnimplementedError('$reference');
+  /// Set optional informative data for the unit.
+  void setInformativeData(
+    String libraryUriStr,
+    String unitUriStr,
+    List<UnlinkedInformativeData> informativeData,
+  ) {
+    var libraryContext = libraryMap[libraryUriStr];
+    if (libraryContext != null) {
+      for (var unitContext in libraryContext.units) {
+        if (unitContext.uriStr == unitUriStr) {
+          unitContext.informativeData = informativeData;
+          return;
+        }
+      }
+    }
   }
 }
 
@@ -134,6 +155,11 @@
       return _enum(unit, reference);
     }
 
+    if (parentName == '@field') {
+      var enclosing = elementOfReference(parent2);
+      return _field(enclosing, reference);
+    }
+
     if (parentName == '@function') {
       CompilationUnitElementImpl enclosing = elementOfReference(parent2);
       return _function(enclosing, reference);
@@ -149,16 +175,37 @@
       return _method(enclosing, reference);
     }
 
+    if (parentName == '@mixin') {
+      var unit = elementOfReference(parent2);
+      return _mixin(unit, reference);
+    }
+
     if (parentName == '@parameter') {
       ExecutableElementImpl enclosing = elementOfReference(parent2);
       return _parameter(enclosing, reference);
     }
 
+    if (parentName == '@prefix') {
+      LibraryElementImpl enclosing = elementOfReference(parent2);
+      return _prefix(enclosing, reference);
+    }
+
     if (parentName == '@typeAlias') {
       var unit = elementOfReference(parent2);
       return _typeAlias(unit, reference);
     }
 
+    if (parentName == '@typeParameter') {
+      var enclosing = elementOfReference(parent2);
+      if (enclosing is ParameterElement) {
+        (enclosing as ParameterElement).typeParameters;
+      } else {
+        (enclosing as TypeParameterizedElement).typeParameters;
+      }
+      assert(reference.element != null);
+      return reference.element;
+    }
+
     if (parentName == '@unit') {
       elementOfReference(parent2);
       // Creating a library fills all its units.
@@ -166,7 +213,6 @@
       return reference.element;
     }
 
-    // TODO(scheglov) support other elements
     throw StateError('Not found: $input');
   }
 
@@ -184,6 +230,12 @@
       assert(reference.element != null);
       return reference.element;
     }
+    if (enclosing is EnumElementImpl) {
+      enclosing.accessors;
+      // Requesting accessors sets elements for accessors and variables.
+      assert(reference.element != null);
+      return reference.element;
+    }
     // Only classes and units have accessors.
     throw StateError('${enclosing.runtimeType}');
   }
@@ -212,19 +264,24 @@
     var sourceFactory = elementFactory.analysisContext.sourceFactory;
     var librarySource = sourceFactory.forUri(uriStr);
 
+    // The URI cannot be resolved, we don't know the library.
+    if (librarySource == null) return null;
+
     var libraryContext = elementFactory.libraryMap[uriStr];
-    // TODO(scheglov) don't use node
-    var node2 = libraryContext.node;
-    var hasName = node2.name.isNotEmpty;
+    if (libraryContext == null) {
+      throw ArgumentError('Missing library: $uriStr');
+    }
+    var libraryNode = libraryContext.node;
+    var hasName = libraryNode.name.isNotEmpty;
 
     var definingUnitContext = libraryContext.definingUnit;
 
     var libraryElement = LibraryElementImpl.forLinkedNode(
       elementFactory.analysisContext,
       elementFactory.analysisSession,
-      node2.name,
-      hasName ? node2.nameOffset : -1,
-      node2.name.length,
+      libraryNode.name,
+      hasName ? libraryNode.nameOffset : -1,
+      libraryNode.name.length,
       definingUnitContext,
       reference,
       definingUnitContext.unit_withDeclarations,
@@ -239,9 +296,10 @@
       var unitElement = CompilationUnitElementImpl.forLinkedNode(
         libraryElement,
         unitContext,
-        unitContainerRef.getChild(unitContext.uriStr),
+        unitContext.reference,
         unitNode,
       );
+      unitElement.lineInfo = unitNode.lineInfo;
       unitElement.source = unitSource;
       unitElement.librarySource = librarySource;
       units.add(unitElement);
@@ -269,6 +327,13 @@
     return reference.element;
   }
 
+  FieldElementImpl _field(ClassElementImpl enclosing, Reference reference) {
+    enclosing.fields;
+    // Requesting fields sets elements for all fields.
+    assert(reference.element != null);
+    return reference.element;
+  }
+
   Element _function(CompilationUnitElementImpl enclosing, Reference reference) {
     enclosing.functions;
     assert(reference.element != null);
@@ -289,12 +354,30 @@
     return reference.element;
   }
 
+  MixinElementImpl _mixin(
+      CompilationUnitElementImpl unit, Reference reference) {
+    if (reference.node2 == null) {
+      _indexUnitElementDeclarations(unit);
+      assert(reference.node2 != null, '$reference');
+    }
+    MixinElementImpl.forLinkedNode(unit, reference, reference.node2);
+    return reference.element;
+  }
+
   Element _parameter(ExecutableElementImpl enclosing, Reference reference) {
     enclosing.parameters;
     assert(reference.element != null);
     return reference.element;
   }
 
+  PrefixElementImpl _prefix(LibraryElementImpl library, Reference reference) {
+    for (var import in library.imports) {
+      import.prefix;
+    }
+    assert(reference.element != null);
+    return reference.element;
+  }
+
   GenericTypeAliasElementImpl _typeAlias(
       CompilationUnitElementImpl unit, Reference reference) {
     if (reference.node2 == null) {
@@ -316,6 +399,7 @@
     var classRef = unitRef.getChild('@class');
     var enumRef = unitRef.getChild('@enum');
     var functionRef = unitRef.getChild('@function');
+    var mixinRef = unitRef.getChild('@mixin');
     var typeAliasRef = unitRef.getChild('@typeAlias');
     var variableRef = unitRef.getChild('@variable');
     for (var declaration in unitNode.declarations) {
@@ -337,6 +421,9 @@
       } else if (declaration is GenericTypeAlias) {
         var name = declaration.name.name;
         typeAliasRef.getChild(name).node2 = declaration;
+      } else if (declaration is MixinDeclaration) {
+        var name = declaration.name.name;
+        mixinRef.getChild(name).node2 = declaration;
       } else if (declaration is TopLevelVariableDeclaration) {
         for (var variable in declaration.variables.variables) {
           var name = variable.name.name;
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 7c044db..2f285f7 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -2,17 +2,23 @@
 // 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:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/ast_binary_reader.dart';
 import 'package:analyzer/src/summary2/lazy_ast.dart';
 import 'package:analyzer/src/summary2/linked_bundle_context.dart';
-import 'package:analyzer/src/summary2/tokens_context.dart';
+import 'package:analyzer/src/summary2/reference.dart';
 
 /// The context of a unit - the context of the bundle, and the unit tokens.
 class LinkedUnitContext {
@@ -20,29 +26,35 @@
   final LinkedLibraryContext libraryContext;
   final int indexInLibrary;
   final String uriStr;
+  final Reference reference;
+  final bool isSynthetic;
   final LinkedNodeUnit data;
-  final TokensContext tokensContext;
+
+  /// Optional informative data for the unit.
+  List<UnlinkedInformativeData> informativeData;
 
   AstBinaryReader _astReader;
 
   CompilationUnit _unit;
   bool _hasDirectivesRead = false;
 
-  /// Mapping from identifiers to real or synthetic type parameters.
-  ///
-  /// Real type parameters have corresponding [TypeParameter] nodes, and are
-  /// referenced from other AST nodes.
+  /// Mapping from identifiers to synthetic type parameters.
   ///
   /// Synthetic type parameters are added when [readType] begins reading a
   /// [FunctionType], and removed when reading is done.
-  final Map<int, TypeParameterElement> _typeParameters = {};
+  final Map<int, TypeParameterElementImpl> _typeParameters = {};
 
   int _nextSyntheticTypeParameterId = 0x10000;
 
-  LinkedUnitContext(this.bundleContext, this.libraryContext,
-      this.indexInLibrary, this.uriStr, this.data,
-      {CompilationUnit unit})
-      : tokensContext = data != null ? TokensContext(data.tokens) : null {
+  LinkedUnitContext(
+      this.bundleContext,
+      this.libraryContext,
+      this.indexInLibrary,
+      this.uriStr,
+      this.reference,
+      this.isSynthetic,
+      this.data,
+      {CompilationUnit unit}) {
     _astReader = AstBinaryReader(this);
     _astReader.isLazy = unit == null;
 
@@ -50,11 +62,38 @@
     _hasDirectivesRead = _unit != null;
   }
 
+  bool get hasPartOfDirective {
+    for (var directive in unit_withDirectives.directives) {
+      if (directive is PartOfDirective) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// Return `true` if this unit is a part of a bundle that is being linked.
+  bool get isLinking => bundleContext.isLinking;
+
+  bool get isNNBD {
+    if (data != null) return data.isNNBD;
+    return _unit.featureSet.isEnabled(Feature.non_nullable);
+  }
+
+  TypeProvider get typeProvider =>
+      bundleContext.elementFactory.analysisContext.typeProvider;
+
   CompilationUnit get unit => _unit;
 
   CompilationUnit get unit_withDeclarations {
     if (_unit == null) {
       _unit = _astReader.readNode(data.node);
+
+      var informativeData = getInformativeData(data.node);
+      var lineStarts = informativeData?.compilationUnit_lineStarts ?? [];
+      if (lineStarts.isEmpty) {
+        lineStarts = [0];
+      }
+      _unit.lineInfo = LineInfo(lineStarts);
     }
     return _unit;
   }
@@ -71,13 +110,28 @@
     return _unit;
   }
 
-  /// Every [TypeParameter] node has [TypeParameterElement], which is created
-  /// during reading of this node. All type parameter nodes are read before
-  /// any nodes that reference them (bounds are read lazily later).
-  void addTypeParameter(int id, TypeParameter node) {
-    var element = TypeParameterElementImpl.forLinkedNode(null, null, node);
-    _typeParameters[id] = element;
-    node.name.staticElement = element;
+  void createGenericFunctionTypeElement(int id, GenericFunctionTypeImpl node) {
+    var containerRef = this.reference.getChild('@genericFunctionType');
+    var reference = containerRef.getChild('$id');
+    var element = GenericFunctionTypeElementImpl.forLinkedNode(
+      this.reference.element,
+      reference,
+      node,
+    );
+    node.declaredElement = element;
+  }
+
+  Comment createComment(LinkedNode data) {
+    var informativeData = getInformativeData(data);
+    var tokenStringList = informativeData?.documentationComment_tokens;
+    if (tokenStringList == null || tokenStringList.isEmpty) {
+      return null;
+    }
+
+    var tokens = tokenStringList
+        .map((lexeme) => TokenFactory.tokenFromString(lexeme))
+        .toList();
+    return astFactory.documentationComment(tokens);
   }
 
   /// Return the [LibraryElement] referenced in the [node].
@@ -89,54 +143,70 @@
 
   int getCodeLength(AstNode node) {
     if (node is ClassDeclaration) {
-      return LazyClassDeclaration.get(node).data.codeLength;
+      return LazyClassDeclaration.getCodeLength(this, node);
     } else if (node is ClassTypeAlias) {
-      return LazyClassTypeAlias.get(node).data.codeLength;
+      return LazyClassTypeAlias.getCodeLength(this, node);
+    } else if (node is CompilationUnit) {
+      if (data != null) {
+        return getInformativeData(data.node)?.codeLength ?? 0;
+      } else {
+        return node.length;
+      }
     } else if (node is ConstructorDeclaration) {
-      return LazyConstructorDeclaration.get(node).data.codeLength;
+      return LazyConstructorDeclaration.getCodeLength(this, node);
+    } else if (node is EnumDeclaration) {
+      return LazyEnumDeclaration.getCodeLength(this, node);
     } else if (node is FormalParameter) {
-      return LazyFormalParameter.get(node).data.codeLength;
+      return LazyFormalParameter.getCodeLength(this, node);
     } else if (node is FunctionDeclaration) {
-      return LazyFunctionDeclaration.get(node).data.codeLength;
+      return LazyFunctionDeclaration.getCodeLength(this, node);
+    } else if (node is FunctionTypeAliasImpl) {
+      return LazyFunctionTypeAlias.getCodeLength(this, node);
+    } else if (node is GenericTypeAlias) {
+      return LazyGenericTypeAlias.getCodeLength(this, node);
     } else if (node is MethodDeclaration) {
-      return LazyMethodDeclaration.get(node).data.codeLength;
+      return LazyMethodDeclaration.getCodeLength(this, node);
+    } else if (node is MixinDeclaration) {
+      return LazyMixinDeclaration.getCodeLength(this, node);
     } else if (node is TypeParameter) {
-      return LazyTypeParameter.get(node).data.codeLength;
+      return LazyTypeParameter.getCodeLength(this, node);
     } else if (node is VariableDeclaration) {
-      return LazyVariableDeclaration.get(node).data.codeLength;
+      return LazyVariableDeclaration.getCodeLength(this, node);
     }
     throw UnimplementedError('${node.runtimeType}');
   }
 
   int getCodeOffset(AstNode node) {
     if (node is ClassDeclaration) {
-      return LazyClassDeclaration.get(node).data.codeOffset;
+      return LazyClassDeclaration.getCodeOffset(this, node);
     } else if (node is ClassTypeAlias) {
-      return LazyClassTypeAlias.get(node).data.codeOffset;
+      return LazyClassTypeAlias.getCodeOffset(this, node);
+    } else if (node is CompilationUnit) {
+      return 0;
     } else if (node is ConstructorDeclaration) {
-      return LazyConstructorDeclaration.get(node).data.codeOffset;
+      return LazyConstructorDeclaration.getCodeOffset(this, node);
+    } else if (node is EnumDeclaration) {
+      return LazyEnumDeclaration.getCodeOffset(this, node);
     } else if (node is FormalParameter) {
-      return LazyFormalParameter.get(node).data.codeOffset;
+      return LazyFormalParameter.getCodeOffset(this, node);
     } else if (node is FunctionDeclaration) {
-      return LazyFunctionDeclaration.get(node).data.codeOffset;
+      return LazyFunctionDeclaration.getCodeOffset(this, node);
+    } else if (node is FunctionTypeAliasImpl) {
+      return LazyFunctionTypeAlias.getCodeOffset(this, node);
+    } else if (node is GenericTypeAlias) {
+      return LazyGenericTypeAlias.getCodeOffset(this, node);
     } else if (node is MethodDeclaration) {
-      return LazyMethodDeclaration.get(node).data.codeOffset;
+      return LazyMethodDeclaration.getCodeOffset(this, node);
+    } else if (node is MixinDeclaration) {
+      return LazyMixinDeclaration.getCodeOffset(this, node);
     } else if (node is TypeParameter) {
-      return LazyTypeParameter.get(node).data.codeOffset;
+      return LazyTypeParameter.getCodeOffset(this, node);
     } else if (node is VariableDeclaration) {
-      return LazyVariableDeclaration.get(node).data.codeOffset;
+      return LazyVariableDeclaration.getCodeOffset(this, node);
     }
     throw UnimplementedError('${node.runtimeType}');
   }
 
-  String getConstructorDeclarationName(LinkedNode node) {
-    var name = node.constructorDeclaration_name;
-    if (name != null) {
-      return getSimpleName(name);
-    }
-    return '';
-  }
-
   List<ConstructorInitializer> getConstructorInitializers(
     ConstructorDeclaration node,
   ) {
@@ -160,45 +230,61 @@
     }
   }
 
+  DartType getDefaultType(TypeParameter node) {
+    return LazyTypeParameter.getDefaultType(_astReader, node);
+  }
+
+  String getDefaultValueCode(AstNode node) {
+    if (node is DefaultFormalParameter) {
+      LazyFormalParameter.readDefaultValue(_astReader, node);
+      return node.defaultValue?.toString();
+    }
+    return null;
+  }
+
+  int getDirectiveOffset(Directive node) {
+    return node.keyword.offset;
+  }
+
   Comment getDocumentationComment(AstNode node) {
     if (node is ClassDeclaration) {
-      LazyClassDeclaration.readDocumentationComment(_astReader, node);
+      LazyClassDeclaration.readDocumentationComment(this, node);
       return node.documentationComment;
     } else if (node is ClassTypeAlias) {
-      LazyClassTypeAlias.readDocumentationComment(_astReader, node);
+      LazyClassTypeAlias.readDocumentationComment(this, node);
       return node.documentationComment;
     } else if (node is ConstructorDeclaration) {
-      LazyConstructorDeclaration.readDocumentationComment(_astReader, node);
+      LazyConstructorDeclaration.readDocumentationComment(this, node);
       return node.documentationComment;
     } else if (node is EnumConstantDeclaration) {
-      LazyEnumConstantDeclaration.readDocumentationComment(_astReader, node);
+      LazyEnumConstantDeclaration.readDocumentationComment(this, node);
       return node.documentationComment;
     } else if (node is EnumDeclaration) {
-      LazyEnumDeclaration.readDocumentationComment(_astReader, node);
+      LazyEnumDeclaration.readDocumentationComment(this, node);
       return node.documentationComment;
     } else if (node is FunctionDeclaration) {
-      LazyFunctionDeclaration.readDocumentationComment(_astReader, node);
+      LazyFunctionDeclaration.readDocumentationComment(this, node);
       return node.documentationComment;
     } else if (node is FunctionTypeAlias) {
-      LazyFunctionTypeAlias.readDocumentationComment(_astReader, node);
+      LazyFunctionTypeAlias.readDocumentationComment(this, node);
       return node.documentationComment;
     } else if (node is GenericTypeAlias) {
-      LazyGenericTypeAlias.readDocumentationComment(_astReader, node);
+      LazyGenericTypeAlias.readDocumentationComment(this, node);
       return node.documentationComment;
     } else if (node is MethodDeclaration) {
-      LazyMethodDeclaration.readDocumentationComment(_astReader, node);
+      LazyMethodDeclaration.readDocumentationComment(this, node);
       return node.documentationComment;
     } else if (node is MixinDeclaration) {
-      LazyMixinDeclaration.readDocumentationComment(_astReader, node);
+      LazyMixinDeclaration.readDocumentationComment(this, node);
       return node.documentationComment;
     } else if (node is VariableDeclaration) {
       var parent2 = node.parent.parent;
       if (parent2 is FieldDeclaration) {
-        LazyFieldDeclaration.readDocumentationComment(_astReader, parent2);
+        LazyFieldDeclaration.readDocumentationComment(this, parent2);
         return parent2.documentationComment;
       } else if (parent2 is TopLevelVariableDeclaration) {
         LazyTopLevelVariableDeclaration.readDocumentationComment(
-          _astReader,
+          this,
           parent2,
         );
         return parent2.documentationComment;
@@ -215,6 +301,16 @@
     return node.constants;
   }
 
+  String getFieldFormalParameterName(AstNode node) {
+    if (node is DefaultFormalParameter) {
+      return getFieldFormalParameterName(node.parameter);
+    } else if (node is FieldFormalParameter) {
+      return node.identifier.name;
+    } else {
+      throw StateError('${node.runtimeType}');
+    }
+  }
+
   Iterable<VariableDeclaration> getFields(ClassOrMixinDeclaration node) sync* {
     var members = _getClassOrMixinMembers(node);
     for (var member in members) {
@@ -226,10 +322,6 @@
     }
   }
 
-  String getFormalParameterName(LinkedNode node) {
-    return getSimpleName(node.normalFormalParameter_identifier);
-  }
-
   List<FormalParameter> getFormalParameters(AstNode node) {
     if (node is ConstructorDeclaration) {
       LazyConstructorDeclaration.readFormalParameters(_astReader, node);
@@ -240,11 +332,22 @@
     } else if (node is FunctionExpression) {
       LazyFunctionExpression.readFormalParameters(_astReader, node);
       return node.parameters?.parameters;
+    } else if (node is FormalParameter) {
+      if (node is DefaultFormalParameter) {
+        return getFormalParameters(node.parameter);
+      } else if (node is FieldFormalParameter) {
+        LazyFormalParameter.readFormalParameters(_astReader, node);
+        return node.parameters?.parameters;
+      } else if (node is FunctionTypedFormalParameter) {
+        LazyFormalParameter.readFormalParameters(_astReader, node);
+        return node.parameters.parameters;
+      } else {
+        return null;
+      }
     } else if (node is FunctionTypeAlias) {
       LazyFunctionTypeAlias.readFormalParameters(_astReader, node);
       return node.parameters.parameters;
     } else if (node is GenericFunctionType) {
-      LazyGenericFunctionType.readFormalParameters(_astReader, node);
       return node.parameters.parameters;
     } else if (node is MethodDeclaration) {
       LazyMethodDeclaration.readFormalParameters(_astReader, node);
@@ -252,21 +355,12 @@
     } else {
       throw UnimplementedError('${node.runtimeType}');
     }
-//    if (kind == LinkedNodeKind.constructorDeclaration) {
-//      parameterList = node.constructorDeclaration_parameters;
-//    } else if (kind == LinkedNodeKind.functionDeclaration) {
-//      return getFormalParameters(node.functionDeclaration_functionExpression);
-//    } else if (kind == LinkedNodeKind.functionExpression) {
-//      parameterList = node.functionExpression_formalParameters;
-//    } else if (kind == LinkedNodeKind.functionTypeAlias) {
-//      parameterList = node.functionTypeAlias_formalParameters;
-//    } else if (kind == LinkedNodeKind.genericFunctionType) {
-//      parameterList = node.genericFunctionType_formalParameters;
-//    } else if (kind == LinkedNodeKind.methodDeclaration) {
-//      parameterList = node.methodDeclaration_formalParameters;
-//    } else {
-//      throw UnimplementedError('$kind');
-//    }
+  }
+
+  Reference getGenericFunctionTypeReference(GenericFunctionType node) {
+    var containerRef = reference.getChild('@genericFunctionType');
+    var id = LazyAst.getGenericFunctionTypeId(node);
+    return containerRef.getChild('$id');
   }
 
   GenericFunctionType getGeneticTypeAliasFunction(GenericTypeAlias node) {
@@ -274,6 +368,15 @@
     return node.functionType;
   }
 
+  bool getHasTypedefSelfReference(AstNode node) {
+    if (node is FunctionTypeAlias) {
+      return LazyFunctionTypeAlias.getHasSelfReference(node);
+    } else if (node is GenericTypeAlias) {
+      return LazyGenericTypeAlias.getHasSelfReference(node);
+    }
+    return false;
+  }
+
   ImplementsClause getImplementsClause(AstNode node) {
     if (node is ClassDeclaration) {
       LazyClassDeclaration.readImplementsClause(_astReader, node);
@@ -289,12 +392,25 @@
     }
   }
 
-  InterfaceType getInterfaceType(LinkedNodeType linkedType) {
-    var type = readType(linkedType);
-    if (type is InterfaceType && !type.element.isEnum) {
-      return type;
+  UnlinkedInformativeData getInformativeData(LinkedNode data) {
+    if (informativeData == null) return null;
+
+    var id = data.informativeId;
+    if (id == 0) return null;
+
+    return informativeData[id - 1];
+  }
+
+  bool getInheritsCovariant(AstNode node) {
+    if (node is DefaultFormalParameter) {
+      return getInheritsCovariant(node.parameter);
+    } else if (node is FormalParameter) {
+      return LazyAst.getInheritsCovariant(node);
+    } else if (node is VariableDeclaration) {
+      return LazyAst.getInheritsCovariant(node);
+    } else {
+      throw StateError('${node.runtimeType}');
     }
-    return null;
   }
 
   Comment getLibraryDocumentationComment(CompilationUnit unit) {
@@ -324,7 +440,11 @@
       return node.metadata;
     } else if (node is CompilationUnit) {
       assert(node == _unit);
-      return _getPartDirectiveAnnotation();
+      if (indexInLibrary != 0) {
+        return _getPartDirectiveAnnotation();
+      } else {
+        return const <Annotation>[];
+      }
     } else if (node is ConstructorDeclaration) {
       LazyConstructorDeclaration.readMetadata(_astReader, node);
       return node.metadata;
@@ -348,9 +468,18 @@
     } else if (node is FunctionTypeAlias) {
       LazyFunctionTypeAlias.readMetadata(_astReader, node);
       return node.metadata;
+    } else if (node is GenericTypeAlias) {
+      LazyGenericTypeAlias.readMetadata(_astReader, node);
+      return node.metadata;
     } else if (node is MethodDeclaration) {
       LazyMethodDeclaration.readMetadata(_astReader, node);
       return node.metadata;
+    } else if (node is MixinDeclaration) {
+      LazyMixinDeclaration.readMetadata(_astReader, node);
+      return node.metadata;
+    } else if (node is TypeParameter) {
+      LazyTypeParameter.readMetadata(_astReader, node);
+      return node.metadata;
     } else if (node is VariableDeclaration) {
       var parent2 = node.parent.parent;
       if (parent2 is FieldDeclaration) {
@@ -361,39 +490,9 @@
         return parent2.metadata;
       }
     }
-//    var kind = node.kind;
-//    if (kind == LinkedNodeKind.classDeclaration ||
-//        kind == LinkedNodeKind.classTypeAlias ||
-//        kind == LinkedNodeKind.constructorDeclaration ||
-//        kind == LinkedNodeKind.enumConstantDeclaration ||
-//        kind == LinkedNodeKind.enumDeclaration ||
-//        kind == LinkedNodeKind.exportDirective ||
-//        kind == LinkedNodeKind.functionDeclaration ||
-//        kind == LinkedNodeKind.functionTypeAlias ||
-//        kind == LinkedNodeKind.libraryDirective ||
-//        kind == LinkedNodeKind.importDirective ||
-//        kind == LinkedNodeKind.methodDeclaration ||
-//        kind == LinkedNodeKind.mixinDeclaration ||
-//        kind == LinkedNodeKind.partDirective ||
-//        kind == LinkedNodeKind.partOfDirective ||
-//        kind == LinkedNodeKind.variableDeclaration) {
-//      return node.annotatedNode_metadata;
-//    }
-//    if (kind == LinkedNodeKind.defaultFormalParameter) {
-//      return getMetadataOrEmpty(node.defaultFormalParameter_parameter);
-//    }
-//    if (kind == LinkedNodeKind.fieldFormalParameter ||
-//        kind == LinkedNodeKind.functionTypedFormalParameter ||
-//        kind == LinkedNodeKind.simpleFormalParameter) {
-//      return node.normalFormalParameter_metadata;
-//    }
     return const <Annotation>[];
   }
 
-  String getMethodName(LinkedNode node) {
-    return getSimpleName(node.methodDeclaration_name);
-  }
-
   Iterable<MethodDeclaration> getMethods(AstNode node) sync* {
     if (node is ClassOrMixinDeclaration) {
       var members = _getClassOrMixinMembers(node);
@@ -405,13 +504,27 @@
     }
   }
 
+  List<String> getMixinSuperInvokedNames(MixinDeclaration node) {
+    return LazyMixinDeclaration.get(node).getSuperInvokedNames();
+  }
+
   int getNameOffset(AstNode node) {
-    if (node is NamedCompilationUnitMember) {
-      return node.name.offset;
+    if (node is ConstructorDeclaration) {
+      if (node.name != null) {
+        return node.name.offset;
+      } else {
+        return node.returnType.offset;
+      }
     } else if (node is EnumConstantDeclaration) {
       return node.name.offset;
     } else if (node is FormalParameter) {
-      return node.identifier.offset;
+      return node.identifier?.offset ?? -1;
+    } else if (node is MethodDeclaration) {
+      return node.name.offset;
+    } else if (node is NamedCompilationUnitMember) {
+      return node.name.offset;
+    } else if (node is TypeParameter) {
+      return node.name.offset;
     } else if (node is VariableDeclaration) {
       return node.name.offset;
     }
@@ -430,7 +543,7 @@
     } else if (node is FunctionTypeAlias) {
       return LazyFunctionTypeAlias.getReturnType(_astReader, node);
     } else if (node is GenericFunctionType) {
-      return LazyGenericFunctionType.getReturnType(_astReader, node);
+      return node.returnType?.type ?? DynamicTypeImpl.instance;
     } else if (node is MethodDeclaration) {
       return LazyMethodDeclaration.getReturnType(_astReader, node);
     } else {
@@ -438,20 +551,25 @@
     }
   }
 
-  String getSimpleName(LinkedNode node) {
-    return getTokenLexeme(node.simpleIdentifier_token);
+  TypeAnnotation getReturnTypeNode(AstNode node) {
+    if (node is FunctionTypeAlias) {
+      LazyFunctionTypeAlias.readReturnTypeNode(_astReader, node);
+      return node.returnType;
+    } else if (node is GenericFunctionType) {
+      return node.returnType;
+    } else if (node is FunctionDeclaration) {
+      LazyFunctionDeclaration.readReturnTypeNode(_astReader, node);
+      return node.returnType;
+    } else if (node is MethodDeclaration) {
+      LazyMethodDeclaration.readReturnTypeNode(_astReader, node);
+      return node.returnType;
+    } else {
+      throw UnimplementedError('${node.runtimeType}');
+    }
   }
 
-  List<String> getSimpleNameList(List<LinkedNode> nodeList) {
-    return nodeList.map(getSimpleName).toList();
-  }
-
-  int getSimpleOffset(LinkedNode node) {
-    return getTokenOffset(node.simpleIdentifier_token);
-  }
-
-  String getStringContent(LinkedNode node) {
-    return node.simpleStringLiteral_value;
+  String getSelectedUri(UriBasedDirective node) {
+    return LazyDirective.getSelectedUri(node);
   }
 
   TypeName getSuperclass(AstNode node) {
@@ -466,14 +584,6 @@
     }
   }
 
-  String getTokenLexeme(int token) {
-    return tokensContext.lexeme(token);
-  }
-
-  int getTokenOffset(int token) {
-    return tokensContext.offset(token);
-  }
-
   /// Return the actual type for the [node] - explicit or inferred.
   DartType getType(AstNode node) {
     if (node is DefaultFormalParameter) {
@@ -487,6 +597,18 @@
     }
   }
 
+  TopLevelInferenceError getTypeInferenceError(AstNode node) {
+    if (node is DefaultFormalParameter) {
+      return getTypeInferenceError(node.parameter);
+    } else if (node is SimpleFormalParameter) {
+      return LazyFormalParameter.getTypeInferenceError(node);
+    } else if (node is VariableDeclaration) {
+      return LazyVariableDeclaration.getTypeInferenceError(node);
+    } else {
+      return null;
+    }
+  }
+
   TypeAnnotation getTypeParameterBound(TypeParameter node) {
     LazyTypeParameter.readBound(_astReader, node);
     return node.bound;
@@ -499,11 +621,17 @@
       return node.typeParameters;
     } else if (node is ConstructorDeclaration) {
       return null;
+    } else if (node is DefaultFormalParameter) {
+      return getTypeParameters2(node.parameter);
+    } else if (node is FieldFormalParameter) {
+      return null;
     } else if (node is FunctionDeclaration) {
       LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
       return getTypeParameters2(node.functionExpression);
     } else if (node is FunctionExpression) {
       return node.typeParameters;
+    } else if (node is FunctionTypedFormalParameter) {
+      return node.typeParameters;
     } else if (node is FunctionTypeAlias) {
       return node.typeParameters;
     } else if (node is GenericFunctionType) {
@@ -514,19 +642,13 @@
       return node.typeParameters;
     } else if (node is MixinDeclaration) {
       return node.typeParameters;
+    } else if (node is SimpleFormalParameter) {
+      return null;
     } else {
       throw UnimplementedError('${node.runtimeType}');
     }
   }
 
-  String getUnitMemberName(LinkedNode node) {
-    return getSimpleName(node.namedCompilationUnitMember_name);
-  }
-
-  String getVariableName(LinkedNode node) {
-    return getSimpleName(node.variableDeclaration_name);
-  }
-
   WithClause getWithClause(AstNode node) {
     if (node is ClassDeclaration) {
       LazyClassDeclaration.readWithClause(_astReader, node);
@@ -539,23 +661,42 @@
     }
   }
 
+  bool hasDefaultValue(FormalParameter node) {
+    if (node is DefaultFormalParameter) {
+      return LazyFormalParameter.hasDefaultValue(node);
+    }
+    return false;
+  }
+
   bool hasImplicitReturnType(AstNode node) {
+    if (node is FunctionDeclaration) {
+      LazyFunctionDeclaration.readReturnTypeNode(_astReader, node);
+      return node.returnType == null;
+    }
     if (node is MethodDeclaration) {
+      LazyMethodDeclaration.readReturnTypeNode(_astReader, node);
       return node.returnType == null;
     }
     return false;
   }
 
   bool hasImplicitType(AstNode node) {
-    if (node is VariableDeclaration) {
-      VariableDeclarationList parent = node.parent;
-      return parent.type == null;
+    if (node is DefaultFormalParameter) {
+      return hasImplicitType(node.parameter);
     } else if (node is SimpleFormalParameter) {
       return node.type == null;
+    } else if (node is VariableDeclaration) {
+      VariableDeclarationList parent = node.parent;
+      LazyVariableDeclarationList.readTypeNode(_astReader, parent);
+      return parent.type == null;
     }
     return false;
   }
 
+  bool hasInitializer(VariableDeclaration node) {
+    return LazyVariableDeclaration.hasInitializer(node);
+  }
+
   bool hasOverrideInferenceDone(AstNode node) {
     // Only nodes in the libraries being linked might be not inferred yet.
     if (_astReader.isLazy) return true;
@@ -571,18 +712,24 @@
     } else if (node is FunctionDeclaration) {
       return false;
     } else if (node is MethodDeclaration) {
-      return node.isAbstract;
+      return LazyMethodDeclaration.isAbstract(node);
     }
     throw UnimplementedError('${node.runtimeType}');
   }
 
   bool isAsynchronous(AstNode node) {
-    var body = _getFunctionBody(node);
-    return body.isAsynchronous;
-  }
-
-  bool isAsyncKeyword(int token) {
-    return tokensContext.type(token) == UnlinkedTokenType.ASYNC;
+    if (node is ConstructorDeclaration) {
+      return false;
+    } else if (node is FunctionDeclaration) {
+      LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
+      return isAsynchronous(node.functionExpression);
+    } else if (node is FunctionExpression) {
+      return LazyFunctionExpression.isAsynchronous(node);
+    } else if (node is MethodDeclaration) {
+      return LazyMethodDeclaration.isAsynchronous(node);
+    } else {
+      throw UnimplementedError('${node.runtimeType}');
+    }
   }
 
   bool isConst(AstNode node) {
@@ -593,35 +740,22 @@
       VariableDeclarationList parent = node.parent;
       return parent.isConst;
     }
-//    var kind = node.kind;
-//    if (kind == LinkedNodeKind.defaultFormalParameter) {
-//      return isConst(node.defaultFormalParameter_parameter);
-//    }
-//    if (kind == LinkedNodeKind.simpleFormalParameter) {
-//      return isConstKeyword(node.simpleFormalParameter_keyword);
-//    }
-//    if (kind == LinkedNodeKind.variableDeclaration) {
-//      return node.variableDeclaration_declaration.isConst;
-//    }
     throw UnimplementedError('${node.runtimeType}');
   }
 
-  bool isConstKeyword(int token) {
-    return tokensContext.type(token) == UnlinkedTokenType.CONST;
-  }
-
-  bool isConstVariableList(LinkedNode node) {
-    return isConstKeyword(node.variableDeclarationList_keyword);
-  }
-
-  bool isCovariant(AstNode node) {
-    if (node is FormalParameter) {
+  bool isExplicitlyCovariant(AstNode node) {
+    if (node is DefaultFormalParameter) {
+      return isExplicitlyCovariant(node.parameter);
+    } else if (node is EnumConstantDeclaration) {
+      return false;
+    } else if (node is FormalParameter) {
       return node.covariantKeyword != null;
     } else if (node is VariableDeclaration) {
       var parent2 = node.parent.parent;
       return parent2 is FieldDeclaration && parent2.covariantKeyword != null;
+    } else {
+      throw StateError('${node.runtimeType}');
     }
-    return false;
   }
 
   bool isExternal(AstNode node) {
@@ -647,21 +781,19 @@
     throw UnimplementedError('${node.runtimeType}');
   }
 
-  bool isFinalKeyword(int token) {
-    return tokensContext.type(token) == UnlinkedTokenType.FINAL;
-  }
-
-  bool isFinalVariableList(LinkedNode node) {
-    return isFinalKeyword(node.variableDeclarationList_keyword);
-  }
-
-  bool isFunction(LinkedNode node) {
-    return node.kind == LinkedNodeKind.functionDeclaration;
-  }
-
   bool isGenerator(AstNode node) {
-    var body = _getFunctionBody(node);
-    return body.isGenerator;
+    if (node is ConstructorDeclaration) {
+      return false;
+    } else if (node is FunctionDeclaration) {
+      LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
+      return isGenerator(node.functionExpression);
+    } else if (node is FunctionExpression) {
+      return LazyFunctionExpression.isGenerator(node);
+    } else if (node is MethodDeclaration) {
+      return LazyMethodDeclaration.isGenerator(node);
+    } else {
+      throw UnimplementedError('${node.runtimeType}');
+    }
   }
 
   bool isGetter(AstNode node) {
@@ -674,12 +806,17 @@
     }
   }
 
-  bool isLibraryKeyword(int token) {
-    return tokensContext.type(token) == UnlinkedTokenType.LIBRARY;
-  }
-
-  bool isMethod(LinkedNode node) {
-    return node.kind == LinkedNodeKind.methodDeclaration;
+  bool isLate(AstNode node) {
+    if (node is VariableDeclaration) {
+      return node.isLate;
+    }
+    if (node is VariableDeclarationList) {
+      return node.isLate;
+    }
+    if (node is EnumConstantDeclaration) {
+      return false;
+    }
+    throw UnimplementedError('${node.runtimeType}');
   }
 
   bool isSetter(AstNode node) {
@@ -708,11 +845,7 @@
     throw UnimplementedError('${node.runtimeType}');
   }
 
-  bool isSyncKeyword(int token) {
-    return tokensContext.type(token) == UnlinkedTokenType.SYNC;
-  }
-
-  Expression readInitializer(ElementImpl enclosing, AstNode node) {
+  Expression readInitializer(AstNode node) {
     if (node is DefaultFormalParameter) {
       LazyFormalParameter.readDefaultValue(_astReader, node);
       return node.defaultValue;
@@ -724,10 +857,6 @@
     }
   }
 
-  AstNode readNode(LinkedNode linkedNode) {
-    return _astReader.readNode(linkedNode);
-  }
-
   DartType readType(LinkedNodeType linkedType) {
     if (linkedType == null) return null;
 
@@ -739,13 +868,23 @@
     } else if (kind == LinkedNodeTypeKind.function) {
       var typeParameterDataList = linkedType.functionTypeParameters;
 
-      var typeParameters = <TypeParameterElement>[];
-      for (var typeParameterData in typeParameterDataList) {
+      var typeParametersLength = typeParameterDataList.length;
+      var typeParameters = List<TypeParameterElement>(typeParametersLength);
+      for (var i = 0; i < typeParametersLength; ++i) {
+        var typeParameterData = typeParameterDataList[i];
         var element = TypeParameterElementImpl(typeParameterData.name, -1);
-        typeParameters.add(element);
+        typeParameters[i] = element;
         _typeParameters[_nextSyntheticTypeParameterId++] = element;
       }
 
+      // Type parameters might use each other in bounds, including forward
+      // references. So, we read bounds after reading all type parameters.
+      for (var i = 0; i < typeParametersLength; ++i) {
+        var typeParameterData = typeParameterDataList[i];
+        TypeParameterElementImpl element = typeParameters[i];
+        element.bound = readType(typeParameterData.bound);
+      }
+
       var returnType = readType(linkedType.functionReturnType);
       var formalParameters = linkedType.functionFormalParameters.map((p) {
         var type = readType(p.type);
@@ -753,26 +892,37 @@
         return ParameterElementImpl.synthetic(p.name, type, kind);
       }).toList();
 
-      for (var i = 0; i < typeParameterDataList.length; ++i) {
+      for (var i = 0; i < typeParametersLength; ++i) {
         _typeParameters.remove(--_nextSyntheticTypeParameterId);
       }
 
+      var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
+
       return FunctionTypeImpl.synthetic(
         returnType,
         typeParameters,
         formalParameters,
-      );
+      ).withNullability(nullabilitySuffix);
     } else if (kind == LinkedNodeTypeKind.interface) {
       var element = bundleContext.elementOfIndex(linkedType.interfaceClass);
+      var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
       return InterfaceTypeImpl.explicit(
         element,
         linkedType.interfaceTypeArguments.map(readType).toList(),
+        nullabilitySuffix: nullabilitySuffix,
       );
     } else if (kind == LinkedNodeTypeKind.typeParameter) {
+      TypeParameterElement element;
       var id = linkedType.typeParameterId;
-      var element = _typeParameters[id];
-      assert(element != null);
-      return TypeParameterTypeImpl(element);
+      if (id != 0) {
+        element = _typeParameters[id];
+        assert(element != null);
+      } else {
+        var index = linkedType.typeParameterElement;
+        element = bundleContext.elementOfIndex(index);
+      }
+      var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
+      return TypeParameterTypeImpl(element).withNullability(nullabilitySuffix);
     } else if (kind == LinkedNodeTypeKind.void_) {
       return VoidTypeImpl.instance;
     } else {
@@ -780,8 +930,21 @@
     }
   }
 
+  void setInheritsCovariant(AstNode node, bool value) {
+    if (node is DefaultFormalParameter) {
+      setInheritsCovariant(node.parameter, value);
+    } else if (node is FormalParameter) {
+      LazyAst.setInheritsCovariant(node, value);
+    } else if (node is VariableDeclaration) {
+      LazyAst.setInheritsCovariant(node, value);
+    } else {
+      throw StateError('${node.runtimeType}');
+    }
+  }
+
   void setOverrideInferenceDone(AstNode node) {
-    assert(!_astReader.isLazy);
+    // TODO(scheglov) This assert fails, check how to avoid this.
+//    assert(!_astReader.isLazy);
     LazyAst.setOverrideInferenceDone(node);
   }
 
@@ -790,7 +953,11 @@
   }
 
   void setVariableType(AstNode node, DartType type) {
-    LazyAst.setType(node, type);
+    if (node is DefaultFormalParameter) {
+      setVariableType(node.parameter, type);
+    } else {
+      LazyAst.setType(node, type);
+    }
   }
 
   bool shouldBeConstFieldElement(AstNode node) {
@@ -799,8 +966,8 @@
       if (variableList.isConst) return true;
 
       if (variableList.isFinal) {
-        ClassDeclaration classDeclaration = variableList.parent.parent;
-        for (var member in classDeclaration.members) {
+        ClassOrMixinDeclaration class_ = variableList.parent.parent;
+        for (var member in class_.members) {
           if (member is ConstructorDeclaration && member.constKeyword != null) {
             return true;
           }
@@ -823,9 +990,10 @@
   ParameterKind _formalParameterKind(LinkedNodeFormalParameterKind kind) {
     if (kind == LinkedNodeFormalParameterKind.optionalNamed) {
       return ParameterKind.NAMED;
-    }
-    if (kind == LinkedNodeFormalParameterKind.optionalPositional) {
+    } else if (kind == LinkedNodeFormalParameterKind.optionalPositional) {
       return ParameterKind.POSITIONAL;
+    } else if (kind == LinkedNodeFormalParameterKind.requiredNamed) {
+      return ParameterKind.NAMED_REQUIRED;
     }
     return ParameterKind.REQUIRED;
   }
@@ -841,67 +1009,32 @@
     return node.members;
   }
 
-  FunctionBody _getFunctionBody(AstNode node) {
-    if (node is ConstructorDeclaration) {
-      LazyConstructorDeclaration.readBody(_astReader, node);
-      return node.body;
-    } else if (node is FunctionDeclaration) {
-      LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
-      return _getFunctionBody(node.functionExpression);
-    } else if (node is FunctionExpression) {
-      LazyFunctionExpression.readBody(_astReader, node);
-      return node.body;
-    } else if (node is MethodDeclaration) {
-      LazyMethodDeclaration.readBody(_astReader, node);
-      return node.body;
-    } else {
-      throw UnimplementedError('${node.runtimeType}');
-    }
-  }
-
   NodeList<Annotation> _getPartDirectiveAnnotation() {
-    if (indexInLibrary != 0) {
-      var definingContext = libraryContext.definingUnit;
-      var unit = definingContext.unit;
-      var partDirectiveIndex = 0;
-      for (var directive in unit.directives) {
-        if (directive is PartDirective) {
-          partDirectiveIndex++;
-          if (partDirectiveIndex == indexInLibrary) {
-            LazyDirective.readMetadata(definingContext._astReader, directive);
-            return directive.metadata;
-          }
+    var definingContext = libraryContext.definingUnit;
+    var unit = definingContext.unit;
+    var partDirectiveIndex = 0;
+    for (var directive in unit.directives) {
+      if (directive is PartDirective) {
+        partDirectiveIndex++;
+        if (partDirectiveIndex == indexInLibrary) {
+          LazyDirective.readMetadata(definingContext._astReader, directive);
+          return directive.metadata;
         }
       }
     }
     throw StateError('Expected to find $indexInLibrary part directive.');
   }
 
-  static List<LinkedNode> getTypeParameters(LinkedNode node) {
-    LinkedNode typeParameterList;
-    var kind = node.kind;
-    if (kind == LinkedNodeKind.classTypeAlias) {
-      typeParameterList = node.classTypeAlias_typeParameters;
-    } else if (kind == LinkedNodeKind.classDeclaration ||
-        kind == LinkedNodeKind.mixinDeclaration) {
-      typeParameterList = node.classOrMixinDeclaration_typeParameters;
-    } else if (kind == LinkedNodeKind.constructorDeclaration) {
-      return const [];
-    } else if (kind == LinkedNodeKind.functionDeclaration) {
-      return getTypeParameters(node.functionDeclaration_functionExpression);
-    } else if (kind == LinkedNodeKind.functionExpression) {
-      typeParameterList = node.functionExpression_typeParameters;
-    } else if (kind == LinkedNodeKind.functionTypeAlias) {
-      typeParameterList = node.functionTypeAlias_typeParameters;
-    } else if (kind == LinkedNodeKind.genericFunctionType) {
-      typeParameterList = node.genericFunctionType_typeParameters;
-    } else if (kind == LinkedNodeKind.genericTypeAlias) {
-      typeParameterList = node.genericTypeAlias_typeParameters;
-    } else if (kind == LinkedNodeKind.methodDeclaration) {
-      typeParameterList = node.methodDeclaration_typeParameters;
-    } else {
-      throw UnimplementedError('$kind');
+  static NullabilitySuffix _nullabilitySuffix(EntityRefNullabilitySuffix data) {
+    switch (data) {
+      case EntityRefNullabilitySuffix.starOrIrrelevant:
+        return NullabilitySuffix.star;
+      case EntityRefNullabilitySuffix.question:
+        return NullabilitySuffix.question;
+      case EntityRefNullabilitySuffix.none:
+        return NullabilitySuffix.none;
+      default:
+        throw StateError('$data');
     }
-    return typeParameterList?.typeParameterList_typeParameters;
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
index 06d86ce..7a7c22d 100644
--- a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/reference.dart';
@@ -31,13 +30,18 @@
   );
 
   final Map<TypeParameterElement, int> _typeParameters = Map.identity();
-  int _nextTypeParameterId = 1;
   int _nextSyntheticTypeParameterId = 0x10000;
 
   LinkingBundleContext(this.dynamicReference);
 
-  void addTypeParameter(TypeParameterElement element) {
-    _typeParameters[element] = _nextTypeParameterId++;
+  /// We need indexes for references during linking, but once we are done,
+  /// we must clear indexes to make references ready for linking a next bundle.
+  void clearIndexes() {
+    for (var reference in references) {
+      if (reference != null) {
+        reference.index = null;
+      }
+    }
   }
 
   int idOfTypeParameter(TypeParameterElement element) {
@@ -46,15 +50,12 @@
 
   int indexOfElement(Element element) {
     if (element == null) return 0;
+    assert(element is! Member);
 
     if (identical(element, DynamicElementImpl.instance)) {
       return indexOfReference(dynamicReference);
     }
 
-    if (element is Member) {
-      element = (element as Member).baseElement;
-    }
-
     var reference = (element as ElementImpl).reference;
     return indexOfReference(reference);
   }
@@ -91,13 +92,25 @@
         kind: LinkedNodeTypeKind.interface,
         interfaceClass: indexOfElement(type.element),
         interfaceTypeArguments: type.typeArguments.map(writeType).toList(),
+        nullabilitySuffix: _nullabilitySuffix(type),
       );
     } else if (type is TypeParameterType) {
       TypeParameterElementImpl element = type.element;
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.typeParameter,
-        typeParameterId: _typeParameters[element],
-      );
+      var id = _typeParameters[element];
+      if (id != null) {
+        return LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.typeParameter,
+          nullabilitySuffix: _nullabilitySuffix(type),
+          typeParameterId: id,
+        );
+      } else {
+        var index = indexOfElement(element);
+        return LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.typeParameter,
+          nullabilitySuffix: _nullabilitySuffix(type),
+          typeParameterElement: index,
+        );
+      }
     } else if (type is VoidType) {
       return LinkedNodeTypeBuilder(
         kind: LinkedNodeTypeKind.void_,
@@ -108,15 +121,17 @@
   }
 
   LinkedNodeFormalParameterKind _formalParameterKind(ParameterElement p) {
-    // ignore: deprecated_member_use_from_same_package
-    var kind = p.parameterKind;
-    if (kind == ParameterKind.NAMED) {
-      return LinkedNodeFormalParameterKind.optionalNamed;
-    }
-    if (kind == ParameterKind.POSITIONAL) {
+    if (p.isRequiredPositional) {
+      return LinkedNodeFormalParameterKind.requiredPositional;
+    } else if (p.isRequiredNamed) {
+      return LinkedNodeFormalParameterKind.requiredNamed;
+    } else if (p.isOptionalPositional) {
       return LinkedNodeFormalParameterKind.optionalPositional;
+    } else if (p.isOptionalNamed) {
+      return LinkedNodeFormalParameterKind.optionalNamed;
+    } else {
+      throw StateError('Unexpected parameter kind: $p');
     }
-    return LinkedNodeFormalParameterKind.required;
   }
 
   FunctionType _toSyntheticFunctionType(FunctionType type) {
@@ -163,6 +178,7 @@
           .toList(),
       functionReturnType: writeType(type.returnType),
       functionTypeParameters: typeParameterBuilders,
+      nullabilitySuffix: _nullabilitySuffix(type),
     );
 
     for (var typeParameter in typeParameters) {
@@ -172,4 +188,18 @@
 
     return result;
   }
+
+  static EntityRefNullabilitySuffix _nullabilitySuffix(DartType type) {
+    var nullabilitySuffix = (type as TypeImpl).nullabilitySuffix;
+    switch (nullabilitySuffix) {
+      case NullabilitySuffix.question:
+        return EntityRefNullabilitySuffix.question;
+      case NullabilitySuffix.star:
+        return EntityRefNullabilitySuffix.starOrIrrelevant;
+      case NullabilitySuffix.none:
+        return EntityRefNullabilitySuffix.none;
+      default:
+        throw StateError('$nullabilitySuffix');
+    }
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
index e089151..a9265e1 100644
--- a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.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/summary2/ast_resolver.dart';
@@ -13,18 +14,20 @@
 class MetadataResolver extends ThrowingAstVisitor<void> {
   final Linker _linker;
   final LibraryElement _libraryElement;
+  final Scope _libraryScope;
+  final CompilationUnitElement _unitElement;
 
-  Scope scope;
-
-  MetadataResolver(this._linker, this._libraryElement);
+  MetadataResolver(this._linker, this._libraryElement, this._libraryScope,
+      this._unitElement);
 
   @override
   void visitAnnotation(Annotation node) {
-    // TODO(scheglov) get rid of?
-    node.elementAnnotation = ElementAnnotationImpl(null);
+    node.elementAnnotation = ElementAnnotationImpl(_unitElement);
 
-    var astResolver = AstResolver(_linker, _libraryElement, scope);
-    // TODO(scheglov) enclosing elements?
+    var holder = ElementHolder();
+    node.accept(LocalElementBuilder(holder, null));
+
+    var astResolver = AstResolver(_linker, _libraryElement, _libraryScope);
     astResolver.resolve(node);
   }
 
@@ -117,9 +120,16 @@
   }
 
   @override
+  void visitGenericFunctionType(GenericFunctionType node) {
+    node.typeParameters?.accept(this);
+    node.parameters.accept(this);
+  }
+
+  @override
   void visitGenericTypeAlias(GenericTypeAlias node) {
-    // TODO: implement visitGenericTypeAlias
-//    super.visitGenericTypeAlias(node);
+    node.metadata.accept(this);
+    node.typeParameters?.accept(this);
+    node.functionType?.accept(this);
   }
 
   @override
@@ -141,8 +151,9 @@
 
   @override
   void visitMixinDeclaration(MixinDeclaration node) {
-    // TODO: implement visitMixinDeclaration
-//    super.visitMixinDeclaration(node);
+    node.metadata.accept(this);
+    node.typeParameters?.accept(this);
+    node.members.accept(this);
   }
 
   @override
@@ -166,8 +177,12 @@
   }
 
   @override
+  void visitTypeParameter(TypeParameter node) {
+    node.metadata.accept(this);
+  }
+
+  @override
   void visitTypeParameterList(TypeParameterList node) {
-    // TODO: implement visitTypeParameterList
-//    super.visitTypeParameterList(node);
+    node.typeParameters.accept(this);
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/named_type_builder.dart b/pkg/analyzer/lib/src/summary2/named_type_builder.dart
new file mode 100644
index 0000000..003f614
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/named_type_builder.dart
@@ -0,0 +1,236 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+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/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/summary2/type_builder.dart';
+
+/// The type builder for a [TypeName].
+class NamedTypeBuilder extends TypeBuilder {
+  static DynamicTypeImpl get _dynamicType => DynamicTypeImpl.instance;
+
+  final Element element;
+  final List<DartType> arguments;
+  final NullabilitySuffix nullabilitySuffix;
+
+  /// The node for which this builder is created, or `null` if the builder
+  /// was detached from its node, e.g. during computing default types for
+  /// type parameters.
+  final TypeName node;
+
+  /// The actual built type, not a [TypeBuilder] anymore.
+  ///
+  /// When [build] is called, the type is built, stored into this field,
+  /// and set for the [node].
+  DartType _type;
+
+  NamedTypeBuilder(this.element, this.arguments, this.nullabilitySuffix,
+      {this.node});
+
+  factory NamedTypeBuilder.of(
+    TypeName node,
+    Element element,
+    NullabilitySuffix nullabilitySuffix,
+  ) {
+    List<DartType> arguments;
+    var argumentList = node.typeArguments;
+    if (argumentList != null) {
+      arguments = argumentList.arguments.map((n) => n.type).toList();
+    } else {
+      arguments = <DartType>[];
+    }
+
+    return NamedTypeBuilder(element, arguments, nullabilitySuffix, node: node);
+  }
+
+  @override
+  DartType build() {
+    if (_type != null) {
+      return _type;
+    }
+
+    var element = this.element;
+    if (element is ClassElement) {
+      var parameters = element.typeParameters;
+      if (parameters.isEmpty) {
+        var rawType = element.type;
+        _type = (rawType as TypeImpl).withNullability(nullabilitySuffix);
+      } else {
+        var arguments = _buildArguments(parameters);
+        _type = InterfaceTypeImpl.explicit(
+          element,
+          arguments,
+          nullabilitySuffix: nullabilitySuffix,
+        );
+      }
+    } else if (element is GenericTypeAliasElement) {
+      // Break a possible recursion.
+      _type = _dynamicType;
+
+      var rawType = _getRawFunctionType(element);
+
+      var parameters = element.typeParameters;
+      if (parameters.isEmpty) {
+        _type = rawType;
+      } else {
+        var arguments = _buildArguments(parameters);
+        var substitution = Substitution.fromPairs(parameters, arguments);
+        _type = substitution.substituteType(rawType);
+      }
+    } else if (element is TypeParameterElement) {
+      _type = TypeParameterTypeImpl(element);
+    } else {
+      _type = _dynamicType;
+    }
+
+    node?.type = _type;
+    return _type;
+  }
+
+  @override
+  String toString() {
+    var buffer = StringBuffer();
+    buffer.write(element.displayName);
+    if (arguments.isNotEmpty) {
+      buffer.write('<');
+      buffer.write(arguments.join(', '));
+      buffer.write('>');
+    }
+    return buffer.toString();
+  }
+
+  /// Build arguments that correspond to the type [parameters].
+  List<DartType> _buildArguments(List<TypeParameterElement> parameters) {
+    if (arguments.isNotEmpty) {
+      if (arguments.length == parameters.length) {
+        var result = List<DartType>(parameters.length);
+        for (int i = 0; i < result.length; ++i) {
+          var type = arguments[i];
+          result[i] = _buildType(type);
+        }
+        return result;
+      } else {
+        return _listOfDynamic(parameters.length);
+      }
+    } else {
+      var result = List<DartType>(parameters.length);
+      for (int i = 0; i < result.length; ++i) {
+        TypeParameterElementImpl parameter = parameters[i];
+        var defaultType = parameter.defaultType;
+        defaultType = _buildType(defaultType);
+        result[i] = defaultType;
+      }
+      return result;
+    }
+  }
+
+  DartType _buildFormalParameterType(FormalParameter node) {
+    if (node is DefaultFormalParameter) {
+      return _buildFormalParameterType(node.parameter);
+    } else if (node is FunctionTypedFormalParameter) {
+      return _buildFunctionType(
+        node.typeParameters,
+        node.returnType,
+        node.parameters,
+      );
+    } else if (node is SimpleFormalParameter) {
+      return _buildNodeType(node.type);
+    } else {
+      throw UnimplementedError('(${node.runtimeType}) $node');
+    }
+  }
+
+  FunctionType _buildFunctionType(
+    TypeParameterList typeParameterList,
+    TypeAnnotation returnTypeNode,
+    FormalParameterList parameterList,
+  ) {
+    var returnType = _buildNodeType(returnTypeNode);
+
+    List<TypeParameterElement> typeParameters;
+    if (typeParameterList != null) {
+      typeParameters = typeParameterList.typeParameters
+          .map<TypeParameterElement>((p) => p.declaredElement)
+          .toList();
+    } else {
+      typeParameters = const <TypeParameterElement>[];
+    }
+
+    var formalParameters = parameterList.parameters.map((parameter) {
+      return ParameterElementImpl.synthetic(
+        parameter.identifier?.name ?? '',
+        _buildFormalParameterType(parameter),
+        // ignore: deprecated_member_use_from_same_package
+        parameter.kind,
+      );
+    }).toList();
+
+    return FunctionTypeImpl.synthetic(
+      returnType,
+      typeParameters,
+      formalParameters,
+    );
+  }
+
+  DartType _buildNodeType(TypeAnnotation node) {
+    if (node == null) {
+      return _dynamicType;
+    } else {
+      return _buildType(node.type);
+    }
+  }
+
+  /// If the [type] is a [TypeBuilder], build it; otherwise return as is.
+  DartType _buildType(DartType type) {
+    if (type is TypeBuilder) {
+      return type.build();
+    } else {
+      return type;
+    }
+  }
+
+  DartType _getRawFunctionType(GenericTypeAliasElementImpl element) {
+    // If the element is not being linked, there is no reason (or a way,
+    // because the linked node might be read only partially) to go through
+    // its node - all its types have already been built.
+    if (!element.linkedContext.isLinking) {
+      var function = element.function;
+      if (function != null) {
+        return function.type;
+      } else {
+        return _dynamicType;
+      }
+    }
+
+    var typedefNode = element.linkedNode;
+    if (typedefNode is FunctionTypeAlias) {
+      return _buildFunctionType(
+        null,
+        typedefNode.returnType,
+        typedefNode.parameters,
+      );
+    } else if (typedefNode is GenericTypeAlias) {
+      var functionNode = typedefNode.functionType;
+      if (functionNode != null) {
+        return _buildFunctionType(
+          functionNode.typeParameters,
+          functionNode.returnType,
+          functionNode.parameters,
+        );
+      } else {
+        return _dynamicType;
+      }
+    } else {
+      throw StateError('(${element.runtimeType}) $element');
+    }
+  }
+
+  static List<DartType> _listOfDynamic(int length) {
+    return List<DartType>.filled(length, _dynamicType);
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/reference.dart b/pkg/analyzer/lib/src/summary2/reference.dart
index 989ab17..626fdc8 100644
--- a/pkg/analyzer/lib/src/summary2/reference.dart
+++ b/pkg/analyzer/lib/src/summary2/reference.dart
@@ -69,9 +69,9 @@
 
   bool get isPrefix => parent != null && parent.name == '@prefix';
 
-  bool get isTypeAlias => parent != null && parent.name == '@typeAlias';
+  bool get isSetter => parent != null && parent.name == '@setter';
 
-  int get numOfChildren => _children != null ? _children.length : 0;
+  bool get isTypeAlias => parent != null && parent.name == '@typeAlias';
 
   /// Return the child with the given name, or `null` if does not exist.
   Reference operator [](String name) {
@@ -84,5 +84,24 @@
     return map[name] ??= new Reference._(this, name);
   }
 
+  /// If the reference has element, and it is for the [node], return `true`.
+  ///
+  /// The element might be not `null`, but the node is different in case of
+  /// duplicate declarations.
+  bool hasElementFor(AstNode node) {
+    if (element != null && node2 == node) {
+      return true;
+    } else {
+      if (node2 == null) {
+        node2 = node;
+      }
+      return false;
+    }
+  }
+
+  void removeChild(String name) {
+    _children.remove(name);
+  }
+
   String toString() => parent == null ? 'root' : '$parent::$name';
 }
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index 8601a46..e9efbb0 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -3,502 +3,21 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/function_type_builder.dart';
+import 'package:analyzer/src/summary2/lazy_ast.dart';
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
-import 'package:analyzer/src/summary2/linking_bundle_context.dart';
 import 'package:analyzer/src/summary2/linking_node_scope.dart';
+import 'package:analyzer/src/summary2/named_type_builder.dart';
 import 'package:analyzer/src/summary2/reference.dart';
-
-//class ReferenceResolver {
-//  final LinkingBundleContext linkingBundleContext;
-//  final TypesToBuild typesToBuild;
-//  final UnitBuilder unit;
-//
-//  /// TODO(scheglov) Update scope with local scopes (formal / type parameters).
-//  Scope scope;
-//
-//  Reference reference;
-//
-//  ReferenceResolver(
-//    this.linkingBundleContext,
-//    this.typesToBuild,
-//    this.unit,
-//    this.scope,
-//    this.reference,
-//  );
-//
-//  LinkedNodeTypeBuilder get _dynamicType {
-//    return LinkedNodeTypeBuilder(
-//      kind: LinkedNodeTypeKind.dynamic_,
-//    );
-//  }
-//
-//  void resolve() {
-//    _node(unit.node);
-//  }
-//
-//  void _classDeclaration(LinkedNodeBuilder node) {
-//    var name = unit.context.getUnitMemberName(node);
-//    reference = reference.getChild('@class').getChild(name);
-//
-//    var typeParameters = node.classOrMixinDeclaration_typeParameters;
-//    _withTypeParameters(typeParameters, () {
-//      _extendsClause(node.classDeclaration_extendsClause);
-//      _withClause(node.classDeclaration_withClause);
-//      _implementsClause(node.classOrMixinDeclaration_implementsClause);
-//
-//      for (var member in node.classOrMixinDeclaration_members) {
-//        if (member.kind != LinkedNodeKind.constructorDeclaration) {
-//          _node(member);
-//        }
-//      }
-//      for (var member in node.classOrMixinDeclaration_members) {
-//        if (member.kind == LinkedNodeKind.constructorDeclaration) {
-//          _node(member);
-//        }
-//      }
-//    });
-//
-//    reference = reference.parent.parent;
-//  }
-//
-//  void _classTypeAlias(LinkedNodeBuilder node) {
-//    var name = unit.context.getUnitMemberName(node);
-//    reference = reference.getChild('@class').getChild(name);
-//
-//    var typeParameters = node.classTypeAlias_typeParameters;
-//    _withTypeParameters(typeParameters, () {
-//      _typeName(node.classTypeAlias_superclass);
-//      _withClause(node.classTypeAlias_withClause);
-//      _implementsClause(node.classTypeAlias_implementsClause);
-//    });
-//
-//    reference = reference.parent.parent;
-//  }
-//
-//  void _compilationUnit(LinkedNodeBuilder node) {
-//    _nodeList(node.compilationUnit_directives);
-//    _nodeList(node.compilationUnit_declarations);
-//  }
-//
-//  void _constructorDeclaration(LinkedNodeBuilder node) {
-//    _node(node.constructorDeclaration_parameters);
-//  }
-//
-//  void _enumConstantDeclaration(LinkedNodeBuilder node) {}
-//
-//  void _enumDeclaration(LinkedNodeBuilder node) {
-//    _nodeList(node.enumDeclaration_constants);
-//  }
-//
-//  void _exportDirective(LinkedNodeBuilder node) {}
-//
-//  void _extendsClause(LinkedNodeBuilder node) {
-//    if (node == null) return;
-//
-//    _typeName(node.extendsClause_superclass);
-//  }
-//
-//  void _fieldDeclaration(LinkedNodeBuilder node) {
-//    _node(node.fieldDeclaration_fields);
-//  }
-//
-//  void _fieldFormalParameter(LinkedNodeBuilder node) {
-//    var typeNode = node.fieldFormalParameter_type;
-//    if (typeNode != null) {
-//      _node(typeNode);
-//    }
-//
-//    var formalParameters = node.fieldFormalParameter_formalParameters;
-//    if (formalParameters != null) {
-//      _formalParameters(formalParameters);
-//    }
-//
-//    if (typeNode != null || formalParameters != null) {
-//      typesToBuild.declarations.add(node);
-//    }
-//  }
-//
-//  void _formalParameters(LinkedNodeBuilder node) {
-//    for (var parameter in node.formalParameterList_parameters) {
-//      _node(parameter);
-//    }
-//  }
-//
-//  void _functionDeclaration(LinkedNodeBuilder node) {
-//    var name = unit.context.getUnitMemberName(node);
-//    reference = reference.getChild('@function').getChild(name);
-//
-//    var function = node.functionDeclaration_functionExpression;
-//    var typeParameters = function.functionExpression_typeParameters;
-//    _withTypeParameters(typeParameters, () {
-//      var returnType = node.functionDeclaration_returnType;
-//      if (returnType != null) {
-//        _node(returnType);
-//        typesToBuild.declarations.add(node);
-//      } else {
-//        node.functionDeclaration_returnType2 = _dynamicType;
-//      }
-//
-//      _node(function.functionExpression_formalParameters);
-//    });
-//
-//    reference = reference.parent.parent;
-//  }
-//
-//  void _functionExpression(LinkedNodeBuilder node) {
-//    var typeParameters = node.functionExpression_typeParameters;
-//    _withTypeParameters(typeParameters, () {
-//      _node(node.functionExpression_formalParameters);
-//    });
-//  }
-//
-//  void _functionTypeAlias(LinkedNodeBuilder node) {
-//    var name = unit.context.getUnitMemberName(node);
-//    reference = reference.getChild('@typeAlias').getChild(name);
-//
-//    var typeParameters = node.functionTypeAlias_typeParameters;
-//    _withTypeParameters(typeParameters, () {
-//      var returnType = node.functionTypeAlias_returnType;
-//      if (returnType != null) {
-//        _node(returnType);
-//        typesToBuild.declarations.add(node);
-//      } else {
-//        node.functionTypeAlias_returnType2 = _dynamicType;
-//      }
-//
-//      _node(node.functionTypeAlias_formalParameters);
-//    });
-//
-//    reference = reference.parent.parent;
-//  }
-//
-//  void _functionTypedFormalParameter(LinkedNodeBuilder node) {
-//    var typeParameters = node.functionTypedFormalParameter_typeParameters;
-//    _withTypeParameters(typeParameters, () {
-//      var typeNode = node.functionTypedFormalParameter_returnType;
-//      if (typeNode != null) {
-//        _node(typeNode);
-//      }
-//
-//      _formalParameters(node.functionTypedFormalParameter_formalParameters);
-//      typesToBuild.declarations.add(node);
-//    });
-//  }
-//
-//  void _genericFunctionType(LinkedNodeBuilder node) {
-//    reference = reference.getChild('@function');
-//
-//    var name = '${reference.numOfChildren}';
-//    reference = reference.getChild(name);
-//
-//    var typeParameters = node.genericFunctionType_typeParameters;
-//    _withTypeParameters(typeParameters, () {
-//      var returnType = node.genericFunctionType_returnType;
-//      if (returnType != null) {
-//        _node(returnType);
-//        typesToBuild.declarations.add(node);
-//      }
-//
-//      _formalParameters(node.genericFunctionType_formalParameters);
-//
-//      typesToBuild.typeAnnotations.add(node);
-//    });
-//
-//    reference = reference.parent.parent;
-//  }
-//
-//  void _genericTypeAlias(LinkedNodeBuilder node) {
-//    var name = unit.context.getSimpleName(
-//      node.namedCompilationUnitMember_name,
-//    );
-//    reference = reference.getChild('@typeAlias').getChild(name);
-//
-//    var typeParameters = node.genericTypeAlias_typeParameters;
-//    _withTypeParameters(typeParameters, () {
-//      _node(node.genericTypeAlias_functionType);
-//    });
-//
-//    reference = reference.parent.parent;
-//  }
-//
-//  void _implementsClause(LinkedNodeBuilder node) {
-//    if (node == null) return;
-//
-//    _typeNameList(node.implementsClause_interfaces);
-//  }
-//
-//  void _importDirective(LinkedNodeBuilder node) {}
-//
-//  void _libraryDirective(LinkedNodeBuilder node) {}
-//
-//  void _methodDeclaration(LinkedNodeBuilder node) {
-//    var name = unit.context.getMethodName(node);
-//    reference = reference.getChild('@method').getChild(name);
-//
-//    var typeParameters = node.methodDeclaration_typeParameters;
-//    _withTypeParameters(typeParameters, () {
-//      var returnType = node.methodDeclaration_returnType;
-//      if (returnType != null) {
-//        _node(returnType);
-//        typesToBuild.declarations.add(node);
-//      }
-//
-//      _node(node.methodDeclaration_formalParameters);
-//    });
-//
-//    reference = reference.parent.parent;
-//  }
-//
-//  void _mixinDeclaration(LinkedNodeBuilder node) {
-//    var name = unit.context.getUnitMemberName(node);
-//    reference = reference.getChild('@class').getChild(name);
-//
-//    var typeParameters = node.classOrMixinDeclaration_typeParameters;
-//    _withTypeParameters(typeParameters, () {
-//      _onClause(node.mixinDeclaration_onClause);
-//      _implementsClause(node.classOrMixinDeclaration_implementsClause);
-//      _nodeList(node.classOrMixinDeclaration_members);
-//    });
-//
-//    reference = reference.parent.parent;
-//  }
-//
-//  void _node(LinkedNodeBuilder node) {
-//    if (node == null) return;
-//
-//    if (node.kind == LinkedNodeKind.classDeclaration) {
-//      _classDeclaration(node);
-//    } else if (node.kind == LinkedNodeKind.classTypeAlias) {
-//      _classTypeAlias(node);
-//    } else if (node.kind == LinkedNodeKind.compilationUnit) {
-//      _compilationUnit(node);
-//    } else if (node.kind == LinkedNodeKind.constructorDeclaration) {
-//      _constructorDeclaration(node);
-//    } else if (node.kind == LinkedNodeKind.defaultFormalParameter) {
-//      _node(node.defaultFormalParameter_parameter);
-//    } else if (node.kind == LinkedNodeKind.enumDeclaration) {
-//      _enumDeclaration(node);
-//    } else if (node.kind == LinkedNodeKind.enumConstantDeclaration) {
-//      _enumConstantDeclaration(node);
-//    } else if (node.kind == LinkedNodeKind.exportDirective) {
-//      _exportDirective(node);
-//    } else if (node.kind == LinkedNodeKind.fieldDeclaration) {
-//      _fieldDeclaration(node);
-//    } else if (node.kind == LinkedNodeKind.fieldFormalParameter) {
-//      _fieldFormalParameter(node);
-//    } else if (node.kind == LinkedNodeKind.formalParameterList) {
-//      _formalParameters(node);
-//    } else if (node.kind == LinkedNodeKind.functionDeclaration) {
-//      _functionDeclaration(node);
-//    } else if (node.kind == LinkedNodeKind.functionExpression) {
-//      _functionExpression(node);
-//    } else if (node.kind == LinkedNodeKind.functionTypeAlias) {
-//      _functionTypeAlias(node);
-//    } else if (node.kind == LinkedNodeKind.functionTypedFormalParameter) {
-//      _functionTypedFormalParameter(node);
-//    } else if (node.kind == LinkedNodeKind.genericFunctionType) {
-//      _genericFunctionType(node);
-//    } else if (node.kind == LinkedNodeKind.genericTypeAlias) {
-//      _genericTypeAlias(node);
-//    } else if (node.kind == LinkedNodeKind.importDirective) {
-//      _importDirective(node);
-//    } else if (node.kind == LinkedNodeKind.libraryDirective) {
-//      _libraryDirective(node);
-//    } else if (node.kind == LinkedNodeKind.methodDeclaration) {
-//      _methodDeclaration(node);
-//    } else if (node.kind == LinkedNodeKind.mixinDeclaration) {
-//      _mixinDeclaration(node);
-//    } else if (node.kind == LinkedNodeKind.partDirective) {
-//      _partDirective(node);
-//    } else if (node.kind == LinkedNodeKind.partOfDirective) {
-//      _partOfDirective(node);
-//    } else if (node.kind == LinkedNodeKind.simpleFormalParameter) {
-//      _simpleFormalParameter(node);
-//    } else if (node.kind == LinkedNodeKind.topLevelVariableDeclaration) {
-//      _topLevelVariableDeclaration(node);
-//    } else if (node.kind == LinkedNodeKind.typeArgumentList) {
-//      _typeArgumentList(node);
-//    } else if (node.kind == LinkedNodeKind.typeName) {
-//      _typeName(node);
-//    } else if (node.kind == LinkedNodeKind.typeParameter) {
-//      _typeParameter(node);
-//    } else if (node.kind == LinkedNodeKind.typeParameterList) {
-//      _typeParameterList(node);
-//    } else if (node.kind == LinkedNodeKind.variableDeclarationList) {
-//      _variableDeclarationList(node);
-//    } else {
-//      // TODO(scheglov) implement
-//      throw UnimplementedError('${node.kind}');
-//    }
-//  }
-//
-//  void _nodeList(List<LinkedNode> nodeList) {
-//    if (nodeList == null) return;
-//
-//    for (var i = 0; i < nodeList.length; ++i) {
-//      var node = nodeList[i];
-//      _node(node);
-//    }
-//  }
-//
-//  void _onClause(LinkedNodeBuilder node) {
-//    if (node == null) return;
-//
-//    _typeNameList(node.onClause_superclassConstraints);
-//  }
-//
-//  void _partDirective(LinkedNodeBuilder node) {}
-//
-//  void _partOfDirective(LinkedNodeBuilder node) {}
-//
-//  void _setSimpleElement(LinkedNodeBuilder identifier, Reference reference) {
-//    var referenceIndex = linkingBundleContext.indexOfReference(reference);
-//    identifier.simpleIdentifier_element = referenceIndex;
-//  }
-//
-//  void _simpleFormalParameter(LinkedNodeBuilder node) {
-//    var typeNode = node.simpleFormalParameter_type;
-//    if (typeNode != null) {
-//      _node(typeNode);
-//      typesToBuild.declarations.add(node);
-//    } else {
-//      // TODO(scheglov) might be inferred
-//      node.simpleFormalParameter_type2 = _dynamicType;
-//    }
-//
-//    if (node.normalFormalParameter_covariantKeyword != 0) {
-//      node.normalFormalParameter_isCovariant = true;
-//    } else {
-//      // TODO(scheglov) might be inferred
-//    }
-//  }
-//
-//  void _topLevelVariableDeclaration(LinkedNodeBuilder node) {
-//    _node(node.topLevelVariableDeclaration_variableList);
-//  }
-//
-//  void _typeArgumentList(LinkedNodeBuilder node) {
-//    for (var typeArgument in node.typeArgumentList_arguments) {
-//      _typeName(typeArgument);
-//    }
-//  }
-//
-//  void _typeName(LinkedNodeBuilder node) {
-//    if (node == null) return;
-//
-//    var identifier = node.typeName_name;
-//    Reference reference;
-//
-//    if (identifier.kind == LinkedNodeKind.simpleIdentifier) {
-//      var name = unit.context.getSimpleName(identifier);
-//
-//      if (name == 'void') {
-//        node.typeName_type = LinkedNodeTypeBuilder(
-//          kind: LinkedNodeTypeKind.void_,
-//        );
-//        return;
-//      }
-//
-//      reference = scope.lookup(name);
-//    } else {
-//      var prefixNode = identifier.prefixedIdentifier_prefix;
-//      var prefixName = unit.context.getSimpleName(prefixNode);
-//      var prefixReference = scope.lookup(prefixName);
-//      _setSimpleElement(prefixNode, prefixReference);
-//
-//      identifier = identifier.prefixedIdentifier_identifier;
-//      var name = unit.context.getSimpleName(identifier);
-//
-//      if (prefixReference != null && prefixReference.isPrefix) {
-//        var prefixScope = prefixReference.prefixScope;
-//        reference = prefixScope.lookup(name);
-//      } else {
-//        identifier.simpleIdentifier_element = 0;
-//        node.typeName_type = _dynamicType;
-//        return;
-//      }
-//    }
-//
-//    if (reference == null) {
-//      identifier.simpleIdentifier_element = 0;
-//      node.typeName_type = _dynamicType;
-//      return;
-//    }
-//
-//    _setSimpleElement(identifier, reference);
-//
-//    var typeArgumentList = node.typeName_typeArguments;
-//    if (typeArgumentList != null) {
-//      _node(typeArgumentList);
-//    }
-//
-//    typesToBuild.typeAnnotations.add(node);
-//  }
-//
-//  void _typeNameList(List<LinkedNode> nodeList) {
-//    for (var i = 0; i < nodeList.length; ++i) {
-//      var node = nodeList[i];
-//      _typeName(node);
-//    }
-//  }
-//
-//  void _typeParameter(LinkedNodeBuilder node) {
-//    _node(node.typeParameter_bound);
-//    // TODO(scheglov) set Object bound if no explicit?
-//  }
-//
-//  void _typeParameterList(LinkedNodeBuilder node) {
-//    for (var typeParameter in node.typeParameterList_typeParameters) {
-//      _node(typeParameter);
-//    }
-//  }
-//
-//  void _variableDeclarationList(LinkedNodeBuilder node) {
-//    var typeNode = node.variableDeclarationList_type;
-//    if (typeNode != null) {
-//      _node(typeNode);
-//      typesToBuild.declarations.add(node);
-//    }
-//  }
-//
-//  void _withClause(LinkedNodeBuilder node) {
-//    if (node == null) return;
-//
-//    _typeNameList(node.withClause_mixinTypes);
-//  }
-//
-//  /// Enter the type parameters scope, visit them, and run [f].
-//  void _withTypeParameters(LinkedNode typeParameterList, void f()) {
-//    if (typeParameterList == null) {
-//      f();
-//      return;
-//    }
-//
-//    scope = Scope(this.scope, {});
-//
-//    var containerRef = this.reference.getChild('@typeParameter');
-//    var typeParameters = typeParameterList.typeParameterList_typeParameters;
-//    for (var typeParameter in typeParameters) {
-//      var name = unit.context.getSimpleName(typeParameter.typeParameter_name);
-//      var reference = containerRef.getChild(name);
-//      reference.node = typeParameter;
-//      scope.declare(name, reference);
-//    }
-//
-//    _node(typeParameterList);
-//    f();
-//
-//    if (typeParameterList != null) {
-//      scope = scope.parent;
-//    }
-//  }
-//}
+import 'package:analyzer/src/summary2/types_builder.dart';
 
 /// Recursive visitor of [LinkedNode]s that resolves explicit type annotations
 /// in outlines.  This includes resolving element references in identifiers
@@ -510,22 +29,29 @@
 /// the type is set, otherwise we keep it empty, so we will attempt to infer
 /// it later).
 class ReferenceResolver extends ThrowingAstVisitor<void> {
-  final LinkingBundleContext linkingContext;
-  final List<AstNode> nodesToBuildType;
+  final NodesToBuildType nodesToBuildType;
   final LinkedElementFactory elementFactory;
   final LibraryElement _libraryElement;
+  final Reference unitReference;
+  final bool nnbd;
+
+  /// The depth-first number of the next [GenericFunctionType] node.
+  int _nextGenericFunctionTypeId = 0;
 
   Reference reference;
   Scope scope;
 
+  /// Is `true` if the current [ClassDeclaration] has a const constructor.
+  bool _hasConstConstructor = false;
+
   ReferenceResolver(
-    this.linkingContext,
     this.nodesToBuildType,
     this.elementFactory,
     this._libraryElement,
-    this.reference,
+    this.unitReference,
+    this.nnbd,
     this.scope,
-  );
+  ) : reference = unitReference;
 
   @override
   void visitBlockFunctionBody(BlockFunctionBody node) {}
@@ -538,22 +64,30 @@
     var name = node.name.name;
     reference = reference.getChild('@class').getChild(name);
 
-    _createTypeParameterElements(node.typeParameters);
-    var element = ClassElementImpl.forLinkedNode(
-      outerReference.element,
-      reference,
-      node,
-    );
+    ClassElementImpl element = reference.element;
     node.name.staticElement = element;
+
+    _createTypeParameterElements(node.typeParameters);
     scope = new TypeParameterScope(scope, element);
-    scope = new ClassScope(scope, element);
-    LinkingNodeContext(node, scope);
 
     node.typeParameters?.accept(this);
     node.extendsClause?.accept(this);
     node.implementsClause?.accept(this);
     node.withClause?.accept(this);
+
+    scope = new ClassScope(scope, element);
+    LinkingNodeContext(node, scope);
+
+    _hasConstConstructor = false;
+    for (var member in node.members) {
+      if (member is ConstructorDeclaration && member.constKeyword != null) {
+        _hasConstConstructor = true;
+        break;
+      }
+    }
+
     node.members.accept(this);
+    nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -567,13 +101,9 @@
     var name = node.name.name;
     reference = reference.getChild('@class').getChild(name);
 
-    _createTypeParameterElements(node.typeParameters);
-    var element = ClassElementImpl.forLinkedNode(
-      outerReference.element,
-      reference,
-      node,
-    );
+    ClassElementImpl element = reference.element;
     node.name.staticElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = new TypeParameterScope(scope, element);
     scope = new ClassScope(scope, element);
     LinkingNodeContext(node, scope);
@@ -582,6 +112,7 @@
     node.superclass?.accept(this);
     node.withClause?.accept(this);
     node.implementsClause?.accept(this);
+    nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -636,13 +167,19 @@
   @override
   void visitFieldDeclaration(FieldDeclaration node) {
     node.fields.accept(this);
+
+    if (node.fields.isConst ||
+        !node.isStatic && node.fields.isFinal && _hasConstConstructor) {
+      var visitor = _SetGenericFunctionTypeIdVisitor(this);
+      node.fields.variables.accept(visitor);
+    }
   }
 
   @override
   void visitFieldFormalParameter(FieldFormalParameter node) {
     node.type?.accept(this);
     node.parameters?.accept(this);
-    nodesToBuildType.add(node);
+    nodesToBuildType.addDeclaration(node);
   }
 
   @override
@@ -655,22 +192,26 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = node.name.name;
-    reference = reference.getChild('@function').getChild(name);
+    var container = '@function';
+    var propertyKeyword = node.propertyKeyword?.keyword;
+    if (propertyKeyword == Keyword.GET) {
+      container = '@getter';
+    } else if (propertyKeyword == Keyword.SET) {
+      container = '@setter';
+    }
 
-    _createTypeParameterElements(node.functionExpression.typeParameters);
-    var element = FunctionElementImpl.forLinkedNode(
-      outerReference.element,
-      reference,
-      node,
-    );
+    var name = node.name.name;
+    reference = reference.getChild(container).getChild(name);
+
+    ExecutableElementImpl element = reference.element;
     node.name.staticElement = element;
+    _createTypeParameterElements(node.functionExpression.typeParameters);
     scope = new FunctionScope(scope, element);
     LinkingNodeContext(node, scope);
 
     node.returnType?.accept(this);
     node.functionExpression.accept(this);
-    nodesToBuildType.add(node);
+    nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -690,19 +231,15 @@
     var name = node.name.name;
     reference = reference.getChild('@typeAlias').getChild(name);
 
-    _createTypeParameterElements(node.typeParameters);
-    var element = GenericTypeAliasElementImpl.forLinkedNode(
-      outerReference.element,
-      reference,
-      node,
-    );
+    GenericTypeAliasElementImpl element = reference.element;
     node.name.staticElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = FunctionTypeScope(outerScope, element);
 
     node.returnType?.accept(this);
     node.typeParameters?.accept(this);
     node.parameters.accept(this);
-    nodesToBuildType.add(node);
+    nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -710,11 +247,33 @@
 
   @override
   void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    var outerScope = scope;
+    var outerReference = reference;
+
+    var name = node.identifier.name;
+    reference = reference.getChild('@parameter').getChild(name);
+    reference.node2 = node;
+
+    var element = ParameterElementImpl.forLinkedNode(
+      outerReference.element,
+      reference,
+      node,
+    );
+    node.identifier.staticElement = element;
+    _createTypeParameterElements(node.typeParameters);
+
+    scope = new EnclosedScope(scope);
+    for (var typeParameter in element.typeParameters) {
+      scope.define(typeParameter);
+    }
+
     node.returnType?.accept(this);
     node.typeParameters?.accept(this);
     node.parameters.accept(this);
+    nodesToBuildType.addDeclaration(node);
 
-    nodesToBuildType.add(node);
+    scope = outerScope;
+    reference = outerReference;
   }
 
   @override
@@ -722,22 +281,29 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = '${outerReference.numOfChildren}';
-    reference = reference.getChild(name);
+    var id = _nextGenericFunctionTypeId++;
+    LazyAst.setGenericFunctionTypeId(node, id);
 
-    _createTypeParameterElements(node.typeParameters);
+    var containerRef = unitReference.getChild('@genericFunctionType');
+    reference = containerRef.getChild('$id');
+
     var element = GenericFunctionTypeElementImpl.forLinkedNode(
-      outerReference.element,
+      unitReference.element,
       reference,
       node,
     );
+    (node as GenericFunctionTypeImpl).declaredElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(outerScope, element);
 
     node.returnType?.accept(this);
     node.typeParameters?.accept(this);
     node.parameters.accept(this);
-    nodesToBuildType.add(node);
-    nodesToBuildType.add(node);
+
+    var nullabilitySuffix = _getNullabilitySuffix(node.question != null);
+    var builder = FunctionTypeBuilder.of(node, nullabilitySuffix);
+    (node as GenericFunctionTypeImpl).type = builder;
+    nodesToBuildType.addTypeBuilder(builder);
 
     scope = outerScope;
     reference = outerReference;
@@ -751,17 +317,14 @@
     var name = node.name.name;
     reference = reference.getChild('@typeAlias').getChild(name);
 
-    _createTypeParameterElements(node.typeParameters);
-    var element = GenericTypeAliasElementImpl.forLinkedNode(
-      outerReference.element,
-      reference,
-      node,
-    );
+    GenericTypeAliasElementImpl element = reference.element;
     node.name.staticElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(outerScope, element);
 
     node.typeParameters?.accept(this);
-    node.functionType.accept(this);
+    node.functionType?.accept(this);
+    nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -777,23 +340,31 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = node.name.name;
-    reference = reference.getChild('@method').getChild(name);
+    var container = '@method';
+    var propertyKeyword = node.propertyKeyword?.keyword;
+    if (propertyKeyword == Keyword.GET) {
+      container = '@getter';
+    } else if (propertyKeyword == Keyword.SET) {
+      container = '@setter';
+    }
 
-    _createTypeParameterElements(node.typeParameters);
+    var name = node.name.name;
+    reference = reference.getChild(container).getChild(name);
+
     var element = MethodElementImpl.forLinkedNode(
       outerReference.element,
       reference,
       node,
     );
     node.name.staticElement = element;
+    _createTypeParameterElements(node.typeParameters);
     scope = new FunctionScope(scope, element);
     LinkingNodeContext(node, scope);
 
     node.returnType?.accept(this);
-    node.parameters?.accept(this);
     node.typeParameters?.accept(this);
-    nodesToBuildType.add(node);
+    node.parameters?.accept(this);
+    nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -805,22 +376,23 @@
     var outerReference = reference;
 
     var name = node.name.name;
-    reference = reference.getChild('@class').getChild(name);
+    reference = reference.getChild('@mixin').getChild(name);
+
+    MixinElementImpl element = reference.element;
+    node.name.staticElement = element;
 
     _createTypeParameterElements(node.typeParameters);
-    var element = ClassElementImpl.forLinkedNode(
-      outerReference.element,
-      reference,
-      node,
-    );
-    node.name.staticElement = element;
     scope = new TypeParameterScope(scope, element);
-    scope = new ClassScope(scope, element);
 
     node.typeParameters?.accept(this);
     node.onClause?.accept(this);
     node.implementsClause?.accept(this);
+
+    scope = new ClassScope(scope, element);
+    LinkingNodeContext(node, scope);
+
     node.members.accept(this);
+    nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -834,12 +406,16 @@
   @override
   void visitSimpleFormalParameter(SimpleFormalParameter node) {
     node.type?.accept(this);
-    nodesToBuildType.add(node);
+    nodesToBuildType.addDeclaration(node);
   }
 
   @override
   void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
     node.variables.accept(this);
+    if (node.variables.isConst) {
+      var visitor = _SetGenericFunctionTypeIdVisitor(this);
+      node.variables.variables.accept(visitor);
+    }
   }
 
   @override
@@ -866,7 +442,21 @@
 
     node.typeArguments?.accept(this);
 
-    nodesToBuildType.add(node);
+    var nullabilitySuffix = _getNullabilitySuffix(node.question != null);
+    if (element is TypeParameterElement) {
+      node.type = TypeParameterTypeImpl(
+        element,
+        nullabilitySuffix: nullabilitySuffix,
+      );
+    } else {
+      var builder = NamedTypeBuilder.of(
+        node,
+        element,
+        nullabilitySuffix,
+      );
+      node.type = builder;
+      nodesToBuildType.addTypeBuilder(builder);
+    }
   }
 
   @override
@@ -882,7 +472,7 @@
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
     node.type?.accept(this);
-    nodesToBuildType.add(node);
+    nodesToBuildType.addDeclaration(node);
   }
 
   @override
@@ -891,9 +481,17 @@
   }
 
   void _createTypeParameterElement(TypeParameter node) {
-    var element = TypeParameterElementImpl.forLinkedNode(null, null, node);
+    var outerReference = this.reference;
+    var containerRef = outerReference.getChild('@typeParameter');
+    var reference = containerRef.getChild(node.name.name);
+    reference.node2 = node;
+
+    var element = TypeParameterElementImpl.forLinkedNode(
+      outerReference.element,
+      reference,
+      node,
+    );
     node.name.staticElement = element;
-    linkingContext.addTypeParameter(element);
   }
 
   void _createTypeParameterElements(TypeParameterList typeParameterList) {
@@ -903,4 +501,33 @@
       _createTypeParameterElement(typeParameter);
     }
   }
+
+  NullabilitySuffix _getNullabilitySuffix(bool hasQuestion) {
+    if (nnbd) {
+      if (hasQuestion) {
+        return NullabilitySuffix.question;
+      } else {
+        return NullabilitySuffix.none;
+      }
+    } else {
+      return NullabilitySuffix.star;
+    }
+  }
+}
+
+/// For consistency we set identifiers for [GenericFunctionType]s in constant
+/// variable initializers, and instance final fields of classes with constant
+/// constructors.
+class _SetGenericFunctionTypeIdVisitor extends RecursiveAstVisitor<void> {
+  final ReferenceResolver resolver;
+
+  _SetGenericFunctionTypeIdVisitor(this.resolver);
+
+  @override
+  void visitGenericFunctionType(GenericFunctionType node) {
+    var id = resolver._nextGenericFunctionTypeId++;
+    LazyAst.setGenericFunctionTypeId(node, id);
+
+    super.visitGenericFunctionType(node);
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/simply_bounded.dart b/pkg/analyzer/lib/src/summary2/simply_bounded.dart
index cac5831..e1bbe8a 100644
--- a/pkg/analyzer/lib/src/summary2/simply_bounded.dart
+++ b/pkg/analyzer/lib/src/summary2/simply_bounded.dart
@@ -132,10 +132,15 @@
       collector.visitParameters(node.parameters);
       return collector.types;
     } else if (node is GenericTypeAlias) {
-      var collector = _TypeCollector();
-      collector.addType(node.functionType.returnType);
-      collector.visitParameters(node.functionType.parameters);
-      return collector.types;
+      var functionType = node.functionType;
+      if (functionType != null) {
+        var collector = _TypeCollector();
+        collector.addType(functionType.returnType);
+        collector.visitParameters(functionType.parameters);
+        return collector.types;
+      } else {
+        return const <TypeAnnotation>[];
+      }
     } else {
       throw StateError('(${node.runtimeType}) $node');
     }
diff --git a/pkg/analyzer/lib/src/summary2/tokens_context.dart b/pkg/analyzer/lib/src/summary2/tokens_context.dart
index 3b68f79..bae4d3bc 100644
--- a/pkg/analyzer/lib/src/summary2/tokens_context.dart
+++ b/pkg/analyzer/lib/src/summary2/tokens_context.dart
@@ -3,143 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/tokens_writer.dart';
 
-/// The context for reading or writing tokens.
-///
-/// Tokens cannot be compared, so tokens for [indexOfToken] must be previously
-/// received from [tokenOfIndex], or the context must be created from a
-/// [TokensResult] (the result of writing previously parsed tokens).
+/// The context for reading tokens.
 class TokensContext {
-  final UnlinkedTokens _tokens;
-  final List<Token> _indexToToken;
-  final Map<Token, int> _tokenToIndex;
-
-  TokensContext(this._tokens)
-      : _indexToToken = List<Token>(_tokens.type.length),
-        _tokenToIndex = Map.identity();
-
-  TokensContext.fromResult(
-      this._tokens, this._indexToToken, this._tokenToIndex);
-
-  /// TODO(scheglov) Not used yet, maybe remove.
-  int addSyntheticToken(
-      UnlinkedTokenKind kind, UnlinkedTokenType type, String lexeme) {
-    var index = _tokens.kind.length;
-    UnlinkedTokensBuilder tokens = _tokens;
-    tokens.kind.add(kind);
-    tokens.lexeme.add(lexeme);
-    tokens.offset.add(0);
-    tokens.length.add(0);
-    tokens.type.add(type);
-    tokens.next.add(0);
-    tokens.endGroup.add(0);
-    tokens.precedingComment.add(0);
-    tokens.isSynthetic.add(true);
-    return index;
-  }
-
-  int indexOfToken(Token token) {
-    if (token == null) return 0;
-
-    var index = _tokenToIndex[token];
-    if (index == null) {
-      throw StateError('Unexpected token: $token');
-    }
-    return index;
-  }
-
-  String lexeme(int index) {
-    return _tokens.lexeme[index];
-  }
-
-  void linkTokens(Token from, Token to) {
-    var fromIndex = _tokenToIndex[from];
-    var toIndex = _tokenToIndex[to];
-    Token prevToken = null;
-    for (var index = fromIndex; index <= toIndex && index != 0;) {
-      var token = _indexToToken[index];
-      token ??= tokenOfIndex(index);
-
-      prevToken?.next = token;
-
-      prevToken = token;
-      index = _tokens.next[index];
-    }
-  }
-
-  int offset(int index) {
-    return _tokens.offset[index];
-  }
-
-  Token tokenOfIndex(int index) {
-    if (index == 0) return null;
-
-    var token = _indexToToken[index];
-    if (token == null) {
-      var kind = _tokens.kind[index];
-      switch (kind) {
-        case UnlinkedTokenKind.nothing:
-          return null;
-        case UnlinkedTokenKind.comment:
-          token = CommentToken(
-            _binaryToAstTokenType(_tokens.type[index]),
-            _tokens.lexeme[index],
-            _tokens.offset[index],
-          );
-          break;
-        case UnlinkedTokenKind.keyword:
-          token = KeywordToken(
-            _binaryToAstTokenType(_tokens.type[index]),
-            _tokens.offset[index],
-            _getCommentToken(_tokens.precedingComment[index]),
-          );
-          break;
-        case UnlinkedTokenKind.simple:
-          token = SimpleToken(
-            _binaryToAstTokenType(_tokens.type[index]),
-            _tokens.offset[index],
-            _getCommentToken(_tokens.precedingComment[index]),
-          );
-          break;
-        case UnlinkedTokenKind.string:
-          token = StringToken(
-            _binaryToAstTokenType(_tokens.type[index]),
-            _tokens.lexeme[index],
-            _tokens.offset[index],
-            _getCommentToken(_tokens.precedingComment[index]),
-          );
-          break;
-        default:
-          throw UnimplementedError('Token kind: $kind');
-      }
-      _indexToToken[index] = token;
-      _tokenToIndex[token] = index;
-    }
-    return token;
-  }
-
-  UnlinkedTokenType type(int index) {
-    return _tokens.type[index];
-  }
-
-  CommentToken _getCommentToken(int index) {
-    var result = tokenOfIndex(index);
-    var token = result;
-    while (true) {
-      index = _tokens.next[index];
-      if (index == 0) return result;
-
-      var nextToken = tokenOfIndex(index);
-      token.next = nextToken;
-      token = nextToken;
-    }
-  }
-
-  static TokenType _binaryToAstTokenType(UnlinkedTokenType type) {
+  static TokenType binaryToAstTokenType(UnlinkedTokenType type) {
     switch (type) {
       case UnlinkedTokenType.ABSTRACT:
         return Keyword.ABSTRACT;
@@ -167,6 +35,8 @@
         return TokenType.BANG;
       case UnlinkedTokenType.BANG_EQ:
         return TokenType.BANG_EQ;
+      case UnlinkedTokenType.BANG_EQ_EQ:
+        return TokenType.BANG_EQ_EQ;
       case UnlinkedTokenType.BAR:
         return TokenType.BAR;
       case UnlinkedTokenType.BAR_BAR:
@@ -221,6 +91,8 @@
         return TokenType.EQ;
       case UnlinkedTokenType.EQ_EQ:
         return TokenType.EQ_EQ;
+      case UnlinkedTokenType.EQ_EQ_EQ:
+        return TokenType.EQ_EQ_EQ;
       case UnlinkedTokenType.EXPORT:
         return Keyword.EXPORT;
       case UnlinkedTokenType.EXTENDS:
@@ -251,6 +123,10 @@
         return TokenType.GT_GT;
       case UnlinkedTokenType.GT_GT_EQ:
         return TokenType.GT_GT_EQ;
+      case UnlinkedTokenType.GT_GT_GT:
+        return TokenType.GT_GT_GT;
+      case UnlinkedTokenType.GT_GT_GT_EQ:
+        return TokenType.GT_GT_GT_EQ;
       case UnlinkedTokenType.HASH:
         return TokenType.HASH;
       case UnlinkedTokenType.HEXADECIMAL:
@@ -277,6 +153,8 @@
         return Keyword.INTERFACE;
       case UnlinkedTokenType.IS:
         return TokenType.IS;
+      case UnlinkedTokenType.LATE:
+        return Keyword.LATE;
       case UnlinkedTokenType.LIBRARY:
         return Keyword.LIBRARY;
       case UnlinkedTokenType.LT:
@@ -345,6 +223,8 @@
         return TokenType.QUESTION_QUESTION;
       case UnlinkedTokenType.QUESTION_QUESTION_EQ:
         return TokenType.QUESTION_QUESTION_EQ;
+      case UnlinkedTokenType.REQUIRED:
+        return Keyword.REQUIRED;
       case UnlinkedTokenType.RETHROW:
         return Keyword.RETHROW;
       case UnlinkedTokenType.RETURN:
diff --git a/pkg/analyzer/lib/src/summary2/tokens_writer.dart b/pkg/analyzer/lib/src/summary2/tokens_writer.dart
index 59dae23..859e2ef 100644
--- a/pkg/analyzer/lib/src/summary2/tokens_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/tokens_writer.dart
@@ -3,173 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/tokens_context.dart';
-import 'package:meta/meta.dart';
-
-/// The result of writing a sequence of tokens.
-class TokensResult {
-  final UnlinkedTokensBuilder tokens;
-  final List<Token> _indexToToken;
-  final Map<Token, int> _tokenToIndex;
-
-  TokensResult(this.tokens, this._indexToToken, this._tokenToIndex);
-
-  TokensContext toContext() {
-    return TokensContext.fromResult(tokens, _indexToToken, _tokenToIndex);
-  }
-}
 
 class TokensWriter {
-  final UnlinkedTokensBuilder _tokens = UnlinkedTokensBuilder();
-  final List<Token> _indexToToken = [];
-  final Map<Token, int> _tokenToIndex = Map.identity();
-
-  TokensWriter() {
-    _addToken(
-      null,
-      isSynthetic: true,
-      kind: UnlinkedTokenKind.nothing,
-      length: 0,
-      lexeme: '',
-      offset: 0,
-      precedingComment: 0,
-      type: UnlinkedTokenType.NOTHING,
-    );
-  }
-
-  /// Write all the tokens from the [first] to the [last] inclusively.
-  TokensResult writeTokens(Token first, Token last) {
-    if (first is CommentToken) {
-      first = (first as CommentToken).parent;
-    }
-
-    var endGroupToBeginIndexMap = <Token, int>{};
-    var previousIndex = 0;
-    for (var token = first;; token = token.next) {
-      var index = _writeToken(token);
-
-      if (previousIndex != 0) {
-        _tokens.next[previousIndex] = index;
-      }
-      previousIndex = index;
-
-      if (token.endGroup != null) {
-        endGroupToBeginIndexMap[token.endGroup] = index;
-      }
-
-      var beginIndex = endGroupToBeginIndexMap[token];
-      if (beginIndex != null) {
-        _tokens.endGroup[beginIndex] = index;
-      }
-
-      if (token == last) break;
-    }
-
-    return TokensResult(_tokens, _indexToToken, _tokenToIndex);
-  }
-
-  int _addToken(
-    Token token, {
-    @required bool isSynthetic,
-    @required UnlinkedTokenKind kind,
-    @required int length,
-    @required String lexeme,
-    @required int offset,
-    @required int precedingComment,
-    @required UnlinkedTokenType type,
-  }) {
-    _tokens.endGroup.add(0);
-    _tokens.isSynthetic.add(isSynthetic);
-    _tokens.kind.add(kind);
-    _tokens.length.add(length);
-    _tokens.lexeme.add(lexeme);
-    _tokens.next.add(0);
-    _tokens.offset.add(offset);
-    _tokens.precedingComment.add(precedingComment);
-    _tokens.type.add(type);
-
-    var index = _indexToToken.length;
-    _indexToToken.add(token);
-    _tokenToIndex[token] = index;
-    return index;
-  }
-
-  int _writeCommentToken(CommentToken token) {
-    if (token == null) return 0;
-
-    int firstIndex = null;
-    var previousIndex = 0;
-    while (token != null) {
-      var index = _addToken(
-        token,
-        isSynthetic: false,
-        kind: UnlinkedTokenKind.comment,
-        length: token.length,
-        lexeme: token.lexeme,
-        offset: token.offset,
-        precedingComment: 0,
-        type: _astToBinaryTokenType(token.type),
-      );
-      firstIndex ??= index;
-
-      if (previousIndex != 0) {
-        _tokens.next[previousIndex] = index;
-      }
-      previousIndex = index;
-
-      token = token.next;
-    }
-
-    return firstIndex;
-  }
-
-  int _writeToken(Token token) {
-    assert(_tokenToIndex[token] == null);
-
-    var commentIndex = _writeCommentToken(token.precedingComments);
-
-    if (token is KeywordToken) {
-      return _addToken(
-        token,
-        isSynthetic: token.isSynthetic,
-        kind: UnlinkedTokenKind.keyword,
-        lexeme: token.lexeme,
-        offset: token.offset,
-        length: token.length,
-        precedingComment: commentIndex,
-        type: _astToBinaryTokenType(token.type),
-      );
-    } else if (token is StringToken) {
-      return _addToken(
-        token,
-        isSynthetic: token.isSynthetic,
-        kind: UnlinkedTokenKind.string,
-        lexeme: token.lexeme,
-        offset: token.offset,
-        length: token.length,
-        precedingComment: commentIndex,
-        type: _astToBinaryTokenType(token.type),
-      );
-    } else if (token is SimpleToken) {
-      return _addToken(
-        token,
-        isSynthetic: token.isSynthetic,
-        kind: UnlinkedTokenKind.simple,
-        lexeme: token.lexeme,
-        offset: token.offset,
-        length: token.length,
-        precedingComment: commentIndex,
-        type: _astToBinaryTokenType(token.type),
-      );
-    } else {
-      throw UnimplementedError('(${token.runtimeType}) $token');
-    }
-  }
-
-  static UnlinkedTokenType _astToBinaryTokenType(TokenType type) {
+  static UnlinkedTokenType astToBinaryTokenType(TokenType type) {
     if (type == Keyword.ABSTRACT) {
       return UnlinkedTokenType.ABSTRACT;
     } else if (type == TokenType.AMPERSAND) {
@@ -196,6 +33,8 @@
       return UnlinkedTokenType.BANG;
     } else if (type == TokenType.BANG_EQ) {
       return UnlinkedTokenType.BANG_EQ;
+    } else if (type == TokenType.BANG_EQ_EQ) {
+      return UnlinkedTokenType.BANG_EQ_EQ;
     } else if (type == TokenType.BAR) {
       return UnlinkedTokenType.BAR;
     } else if (type == TokenType.BAR_BAR) {
@@ -250,6 +89,8 @@
       return UnlinkedTokenType.EQ;
     } else if (type == TokenType.EQ_EQ) {
       return UnlinkedTokenType.EQ_EQ;
+    } else if (type == TokenType.EQ_EQ_EQ) {
+      return UnlinkedTokenType.EQ_EQ_EQ;
     } else if (type == Keyword.EXPORT) {
       return UnlinkedTokenType.EXPORT;
     } else if (type == Keyword.EXTENDS) {
@@ -280,6 +121,10 @@
       return UnlinkedTokenType.GT_GT;
     } else if (type == TokenType.GT_GT_EQ) {
       return UnlinkedTokenType.GT_GT_EQ;
+    } else if (type == TokenType.GT_GT_GT) {
+      return UnlinkedTokenType.GT_GT_GT;
+    } else if (type == TokenType.GT_GT_GT_EQ) {
+      return UnlinkedTokenType.GT_GT_GT_EQ;
     } else if (type == TokenType.HASH) {
       return UnlinkedTokenType.HASH;
     } else if (type == TokenType.HEXADECIMAL) {
@@ -306,6 +151,8 @@
       return UnlinkedTokenType.INTERFACE;
     } else if (type == TokenType.IS) {
       return UnlinkedTokenType.IS;
+    } else if (type == Keyword.LATE) {
+      return UnlinkedTokenType.LATE;
     } else if (type == Keyword.LIBRARY) {
       return UnlinkedTokenType.LIBRARY;
     } else if (type == TokenType.LT) {
@@ -374,6 +221,8 @@
       return UnlinkedTokenType.QUESTION_QUESTION;
     } else if (type == TokenType.QUESTION_QUESTION_EQ) {
       return UnlinkedTokenType.QUESTION_QUESTION_EQ;
+    } else if (type == Keyword.REQUIRED) {
+      return UnlinkedTokenType.REQUIRED;
     } else if (type == Keyword.RETHROW) {
       return UnlinkedTokenType.RETHROW;
     } else if (type == Keyword.RETURN) {
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index 60b10d9..ac469fd 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -11,6 +11,8 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/link.dart' as graph
     show DependencyWalker, Node;
 import 'package:analyzer/src/summary2/ast_resolver.dart';
@@ -30,6 +32,55 @@
   return (element as ElementImpl).linkedNode;
 }
 
+/// Resolver for typed constant top-level variables and fields initializers.
+///
+/// Initializers of untyped variables are resolved during [TopLevelInference].
+class ConstantInitializersResolver {
+  final Linker linker;
+
+  LibraryElement _library;
+  Scope _scope;
+
+  ConstantInitializersResolver(this.linker);
+
+  DynamicTypeImpl get _dynamicType => DynamicTypeImpl.instance;
+
+  void perform() {
+    for (var builder in linker.builders.values) {
+      _library = builder.element;
+      for (var unitContext in builder.context.units) {
+        for (var unitMember in unitContext.unit.declarations) {
+          _scope = builder.scope;
+          if (unitMember is TopLevelVariableDeclaration) {
+            _variableDeclarationList(unitMember.variables);
+          } else if (unitMember is ClassOrMixinDeclaration) {
+            _scope = LinkingNodeContext.get(unitMember).scope;
+            for (var classMember in unitMember.members) {
+              if (classMember is FieldDeclaration) {
+                _variableDeclarationList(classMember.fields);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  void _variableDeclarationList(VariableDeclarationList node) {
+    var typeNode = node.type;
+    if (node.isConst && typeNode != null) {
+      for (var variable in node.variables) {
+        if (variable.initializer != null) {
+          InferenceContext.setType(variable.initializer, typeNode.type);
+          var astResolver = AstResolver(linker, _library, _scope);
+          astResolver.rewriteAst(variable.initializer);
+          astResolver.resolve(variable.initializer);
+        }
+      }
+    }
+  }
+}
+
 class TopLevelInference {
   final Linker linker;
 
@@ -38,8 +89,11 @@
   DynamicTypeImpl get _dynamicType => DynamicTypeImpl.instance;
 
   void infer() {
+    var initializerInference = _InitializerInference(linker);
+    initializerInference.createNodes();
+
     _performOverrideInference();
-    _InitializerInference(linker).perform();
+    initializerInference.perform();
     _inferConstructorFieldFormals();
   }
 
@@ -84,17 +138,37 @@
   }
 
   void _performOverrideInference() {
+    var inferrer = new InstanceMemberInferrer(
+      linker.typeProvider,
+      linker.inheritance,
+    );
     for (var builder in linker.builders.values) {
       for (var unit in builder.element.units) {
-        new InstanceMemberInferrer(
-          linker.typeProvider,
-          linker.inheritance,
-        ).inferCompilationUnit(unit);
+        inferrer.inferCompilationUnit(unit);
       }
     }
   }
 }
 
+class _FunctionElementForLink_Initializer implements FunctionElementImpl {
+  final _InferenceNode _node;
+
+  @override
+  Element enclosingElement;
+
+  _FunctionElementForLink_Initializer(this._node);
+
+  @override
+  DartType get returnType {
+    if (!_node.isEvaluated) {
+      _node._walker.walk(_node);
+    }
+    return LazyAst.getType(_node._node);
+  }
+
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
 class _InferenceDependenciesCollector extends RecursiveAstVisitor<void> {
   final Set<PropertyInducingElement> _set = Set.identity();
 
@@ -111,17 +185,32 @@
   final _InferenceWalker _walker;
   final LibraryElement _library;
   final Scope _scope;
+  final PropertyInducingElementImpl _element;
   final VariableDeclaration _node;
 
   @override
   bool isEvaluated = false;
 
-  _InferenceNode(this._walker, this._library, this._scope, this._node);
+  _InferenceNode(
+    this._walker,
+    this._library,
+    this._scope,
+    this._element,
+    this._node,
+  );
+
+  bool get isImplicitlyTypedInstanceField {
+    VariableDeclarationList variables = _node.parent;
+    if (variables.type == null) {
+      var parent = variables.parent;
+      return parent is FieldDeclaration && !parent.isStatic;
+    }
+    return false;
+  }
 
   @override
   List<_InferenceNode> computeDependencies() {
-    _node.initializer.accept(LocalElementBuilder(ElementHolder(), null));
-
+    _buildLocalElements();
     _resolveInitializer();
 
     var collector = _InferenceDependenciesCollector();
@@ -131,17 +220,26 @@
       return const <_InferenceNode>[];
     }
 
-    return collector._set
+    var dependencies = collector._set
         .map(_walker.getNode)
         .where((node) => node != null)
         .toList();
+
+    for (var node in dependencies) {
+      if (node.isImplicitlyTypedInstanceField) {
+        LazyAst.setType(_node, DynamicTypeImpl.instance);
+        isEvaluated = true;
+        return const <_InferenceNode>[];
+      }
+    }
+
+    return dependencies;
   }
 
   void evaluate() {
     _resolveInitializer();
 
-    VariableDeclarationList parent = _node.parent;
-    if (parent.type == null) {
+    if (LazyAst.getType(_node) == null) {
       var initializerType = _node.initializer.staticType;
       initializerType = _dynamicIfNull(initializerType);
       LazyAst.setType(_node, initializerType);
@@ -150,14 +248,40 @@
     isEvaluated = true;
   }
 
-  void markCircular() {
+  void markCircular(List<_InferenceNode> cycle) {
     LazyAst.setType(_node, DynamicTypeImpl.instance);
+
+    var cycleNames = Set<String>();
+    for (var inferenceNode in cycle) {
+      var node = inferenceNode._node;
+      if (node is VariableDeclaration) {
+        cycleNames.add(node.name.name);
+      } else {
+        cycleNames.add('<unknown>');
+      }
+    }
+
+    LazyAst.setTypeInferenceError(
+      _node,
+      TopLevelInferenceErrorBuilder(
+        kind: TopLevelInferenceErrorKind.dependencyCycle,
+        arguments: cycleNames.toList(),
+      ),
+    );
+
     isEvaluated = true;
   }
 
+  void _buildLocalElements() {
+    var holder = ElementHolder();
+    _node.initializer.accept(LocalElementBuilder(holder, null));
+    _element.encloseElements(holder.functions);
+  }
+
   void _resolveInitializer() {
     var astResolver = AstResolver(_walker._linker, _library, _scope);
-    astResolver.resolve(_node.initializer, doAstRewrite: true);
+    astResolver.rewriteAst(_node.initializer);
+    astResolver.resolve(_node.initializer);
   }
 }
 
@@ -167,11 +291,6 @@
 
   _InferenceWalker(this._linker);
 
-  void addNode(Element element, LibraryElement library, Scope scope,
-      VariableDeclaration node) {
-    _nodes[element] = _InferenceNode(this, library, scope, node);
-  }
-
   @override
   void evaluate(_InferenceNode v) {
     v.evaluate();
@@ -180,7 +299,7 @@
   @override
   void evaluateScc(List<_InferenceNode> scc) {
     for (var node in scc) {
-      node.markCircular();
+      node.markCircular(scc);
     }
   }
 
@@ -206,40 +325,47 @@
 
   _InitializerInference(this._linker) : _walker = _InferenceWalker(_linker);
 
-  void perform() {
+  void createNodes() {
     for (var builder in _linker.builders.values) {
       _library = builder.element;
       for (var unit in _library.units) {
-        for (var class_ in unit.types) {
-          var node = _getLinkedNode(class_);
-          _scope = LinkingNodeContext.get(node).scope;
-          for (var element in class_.fields) {
-            _addNode(element);
-          }
-        }
+        unit.types.forEach(_addClassElementFields);
+        unit.mixins.forEach(_addClassElementFields);
 
-        _scope = builder.libraryScope;
+        _scope = builder.scope;
         for (var element in unit.topLevelVariables) {
           _addNode(element);
         }
       }
     }
+  }
+
+  void perform() {
     _walker.walkNodes();
   }
 
+  void _addClassElementFields(ClassElement class_) {
+    var node = _getLinkedNode(class_);
+    _scope = LinkingNodeContext.get(node).scope;
+    for (var element in class_.fields) {
+      _addNode(element);
+    }
+  }
+
   void _addNode(PropertyInducingElement element) {
     if (element.isSynthetic) return;
 
     VariableDeclaration node = _getLinkedNode(element);
-    VariableDeclarationList variableList = node.parent;
-    if (variableList.type == null || element.isConst) {
-      if (node.initializer != null) {
-        _walker.addNode(element, _library, _scope, node);
-      } else {
-        if (LazyAst.getType(node) == null) {
-          LazyAst.setType(node, DynamicTypeImpl.instance);
-        }
-      }
+    if (LazyAst.getType(node) != null) return;
+
+    if (node.initializer != null) {
+      var inferenceNode =
+          _InferenceNode(_walker, _library, _scope, element, node);
+      _walker._nodes[element] = inferenceNode;
+      (element as PropertyInducingElementImpl).initializer =
+          _FunctionElementForLink_Initializer(inferenceNode);
+    } else {
+      LazyAst.setType(node, DynamicTypeImpl.instance);
     }
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/type_alias.dart b/pkg/analyzer/lib/src/summary2/type_alias.dart
new file mode 100644
index 0000000..79e8ba8
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/type_alias.dart
@@ -0,0 +1,137 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/summary2/lazy_ast.dart';
+import 'package:analyzer/src/summary2/link.dart';
+
+class TypeAliasSelfReferenceFinder {
+  /// Check typedefs and mark the ones having self references.
+  void perform(Linker linker) {
+    for (var builder in linker.builders.values) {
+      for (var unitContext in builder.context.units) {
+        for (var node in unitContext.unit.declarations) {
+          if (node is FunctionTypeAlias) {
+            var finder = _Finder(node);
+            finder.functionTypeAlias(node);
+            LazyFunctionTypeAlias.setHasSelfReference(
+              node,
+              finder.hasSelfReference,
+            );
+          } else if (node is GenericTypeAlias) {
+            var finder = _Finder(node);
+            finder.genericTypeAlias(node);
+            LazyGenericTypeAlias.setHasSelfReference(
+              node,
+              finder.hasSelfReference,
+            );
+          }
+        }
+      }
+    }
+  }
+}
+
+class _Finder {
+  final AstNode self;
+  final Set<AstNode> visited = Set.identity();
+  bool hasSelfReference = false;
+
+  _Finder(this.self);
+
+  void functionTypeAlias(FunctionTypeAlias node) {
+    _typeParameterList(node.typeParameters);
+    _formalParameterList(node.parameters);
+    _visit(node.returnType);
+  }
+
+  void genericTypeAlias(GenericTypeAlias node) {
+    var functionType = node.functionType;
+    if (functionType != null) {
+      _typeParameterList(functionType.typeParameters);
+      _formalParameterList(functionType.parameters);
+      _visit(functionType.returnType);
+    }
+  }
+
+  void _argumentList(TypeArgumentList node) {
+    if (node != null) {
+      for (var argument in node.arguments) {
+        _visit(argument);
+      }
+    }
+  }
+
+  void _formalParameter(FormalParameter node) {
+    if (node is DefaultFormalParameter) {
+      _formalParameter(node.parameter);
+    } else if (node is FunctionTypedFormalParameter) {
+      _visit(node.returnType);
+      _formalParameterList(node.parameters);
+    } else if (node is SimpleFormalParameter) {
+      _visit(node.type);
+    }
+  }
+
+  void _formalParameterList(FormalParameterList node) {
+    for (var parameter in node.parameters) {
+      _formalParameter(parameter);
+    }
+  }
+
+  void _typeParameterList(TypeParameterList node) {
+    if (node != null) {
+      for (var parameter in node.typeParameters) {
+        _visit(parameter.bound);
+      }
+    }
+  }
+
+  void _visit(TypeAnnotation node) {
+    if (hasSelfReference) return;
+    if (node == null) return;
+
+    if (node is TypeName) {
+      var element = node.name.staticElement;
+      if (element is ElementImpl &&
+          element.enclosingElement != null &&
+          element.linkedContext.isLinking) {
+        var typeNode = element.linkedNode;
+        if (typeNode == self) {
+          hasSelfReference = true;
+          return;
+        }
+        if (typeNode is ClassDeclaration) {
+          if (visited.add(typeNode)) {
+            _typeParameterList(typeNode.typeParameters);
+          }
+        } else if (typeNode is ClassTypeAlias) {
+          if (visited.add(typeNode)) {
+            _typeParameterList(typeNode.typeParameters);
+          }
+        } else if (typeNode is FunctionTypeAlias) {
+          if (visited.add(typeNode)) {
+            functionTypeAlias(typeNode);
+          }
+        } else if (typeNode is GenericTypeAlias) {
+          if (visited.add(typeNode)) {
+            genericTypeAlias(typeNode);
+          }
+        } else if (typeNode is MixinDeclaration) {
+          if (visited.add(typeNode)) {
+            _typeParameterList(typeNode.typeParameters);
+          }
+        }
+      }
+      _argumentList(node.typeArguments);
+    } else if (node is GenericFunctionType) {
+      _typeParameterList(node.typeParameters);
+      _formalParameterList(node.parameters);
+      _visit(node.returnType);
+    } else {
+      throw UnimplementedError('(${node.runtimeType}) $node');
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/type_builder.dart b/pkg/analyzer/lib/src/summary2/type_builder.dart
index 9a677ee..ffa1d14 100644
--- a/pkg/analyzer/lib/src/summary2/type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/type_builder.dart
@@ -2,259 +2,17 @@
 // 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:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_algebra.dart';
-import 'package:analyzer/src/generated/type_system.dart';
-import 'package:analyzer/src/summary2/lazy_ast.dart';
 
-class TypeBuilder {
-  final Dart2TypeSystem typeSystem;
+/// The builder for a [DartType] represented by a node.
+abstract class TypeBuilder implements DartType {
+  /// Build the type, and set it for the corresponding node.
+  /// Does nothing if the type has been already built.
+  ///
+  /// Return the built type.
+  DartType build();
 
-  /// The set of type annotations, and declaration in the build unit, for which
-  /// we need to build types, but have not built yet.
-  final Set<AstNode> _nodesToBuildType = Set.identity();
-
-  TypeBuilder(this.typeSystem);
-
-  DynamicTypeImpl get _dynamicType => DynamicTypeImpl.instance;
-
-  VoidTypeImpl get _voidType => VoidTypeImpl.instance;
-
-  /// The [nodes] list is a mix of [TypeAnnotation]s and declarations, where
-  /// usually type annotations come before declarations that use them, but this
-  /// is not guaranteed, and not even always possible. For example references
-  /// to typedefs declared in another unit being built - we need to build types
-  /// for this typedef, which might reference another unit (encountered before
-  /// or after the one defining the typedef).
-  void build(List<AstNode> nodes) {
-    _nodesToBuildType.addAll(nodes);
-    for (var item in nodes) {
-      _build(item);
-    }
-  }
-
-  void _build(AstNode node) {
-    if (node == null) return;
-    if (!_nodesToBuildType.remove(node)) return;
-
-    if (node is TypeAnnotation) {
-      _typeAnnotation(node);
-    } else {
-      _declaration(node);
-    }
-  }
-
-  FunctionType _buildFunctionType(
-    TypeParameterList typeParameterList,
-    TypeAnnotation returnTypeNode,
-    FormalParameterList parameterList,
-  ) {
-    var returnType = returnTypeNode?.type ?? _dynamicType;
-
-    List<TypeParameterElement> typeParameters;
-    if (typeParameterList != null) {
-      typeParameters = typeParameterList.typeParameters
-          .map<TypeParameterElement>((p) => p.declaredElement)
-          .toList();
-    } else {
-      typeParameters = const <TypeParameterElement>[];
-    }
-
-    var formalParameters = parameterList.parameters.map((parameter) {
-      return ParameterElementImpl.synthetic(
-        parameter.identifier?.name ?? '',
-        LazyAst.getType(parameter),
-        // ignore: deprecated_member_use_from_same_package
-        parameter.kind,
-      );
-    }).toList();
-
-    return FunctionTypeImpl.synthetic(
-      returnType,
-      typeParameters,
-      formalParameters,
-    );
-  }
-
-  void _declaration(AstNode node) {
-    if (node is FieldFormalParameter) {
-      _fieldFormalParameter(node);
-    } else if (node is FunctionDeclaration) {
-      var defaultReturnType = node.isSetter ? _voidType : _dynamicType;
-      var returnType = node.returnType?.type ?? defaultReturnType;
-      LazyAst.setReturnType(node, returnType);
-    } else if (node is FunctionTypeAlias) {
-      _functionTypeAlias(node);
-    } else if (node is FunctionTypedFormalParameter) {
-      _functionTypedFormalParameter(node);
-    } else if (node is GenericFunctionType) {
-      _genericFunctionType(node);
-    } else if (node is MethodDeclaration) {
-      var defaultReturnType = node.isSetter ? _voidType : _dynamicType;
-      var returnType = node.returnType?.type ?? defaultReturnType;
-      LazyAst.setReturnType(node, returnType);
-    } else if (node is SimpleFormalParameter) {
-      _build(node.type);
-      LazyAst.setType(node, node.type?.type ?? _dynamicType);
-    } else if (node is VariableDeclarationList) {
-      var type = node.type?.type;
-      if (type != null) {
-        for (var variable in node.variables) {
-          LazyAst.setType(variable, type);
-        }
-      }
-    } else {
-      throw UnimplementedError('${node.runtimeType}');
-    }
-  }
-
-  void _fieldFormalParameter(FieldFormalParameter node) {
-    var parameterList = node.parameters;
-    if (parameterList != null) {
-      var type = _buildFunctionType(
-        node.typeParameters,
-        node.type,
-        parameterList,
-      );
-      LazyAst.setType(node, type);
-    } else {
-      LazyAst.setType(node, node.type?.type ?? _dynamicType);
-    }
-  }
-
-  void _formalParameterList(FormalParameterList node) {
-    for (var formalParameter in node.parameters) {
-      if (formalParameter is SimpleFormalParameter) {
-        _build(formalParameter);
-      }
-    }
-  }
-
-  void _functionTypeAlias(FunctionTypeAlias node) {
-    var returnTypeNode = node.returnType;
-    _build(returnTypeNode);
-    LazyAst.setReturnType(node, returnTypeNode?.type ?? _dynamicType);
-
-    _typeParameterList(node.typeParameters);
-    _formalParameterList(node.parameters);
-  }
-
-  void _functionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    var type = _buildFunctionType(
-      node.typeParameters,
-      node.returnType,
-      node.parameters,
-    );
-    LazyAst.setType(node, type);
-  }
-
-  void _genericFunctionType(GenericFunctionTypeImpl node) {
-    var returnTypeNode = node.returnType;
-    _build(returnTypeNode);
-    LazyAst.setReturnType(node, returnTypeNode?.type ?? _dynamicType);
-
-    _typeParameterList(node.typeParameters);
-    _formalParameterList(node.parameters);
-
-    node.type = _buildFunctionType(
-      node.typeParameters,
-      node.returnType,
-      node.parameters,
-    );
-  }
-
-  List<DartType> _listOfDynamic(int typeParametersLength) {
-    return List<DartType>.filled(typeParametersLength, _dynamicType);
-  }
-
-  void _typeAnnotation(TypeAnnotation node) {
-    if (node is GenericFunctionType) {
-      _genericFunctionType(node);
-    } else if (node is TypeName) {
-      node.type = _dynamicType;
-      _typeName(node);
-    } else {
-      throw StateError('${node.runtimeType}');
-    }
-  }
-
-  void _typeName(TypeName node) {
-    var element = node.name.staticElement;
-
-    List<DartType> typeArguments;
-    var typeArgumentList = node.typeArguments;
-    if (typeArgumentList != null) {
-      typeArguments = typeArgumentList.arguments.map((a) => a.type).toList();
-    }
-
-    if (element is ClassElement) {
-      if (element.isEnum) {
-        node.type = InterfaceTypeImpl.explicit(element, const []);
-      } else {
-        var rawType = element.type;
-
-        var typeParametersLength = element.typeParameters.length;
-        if (typeParametersLength == 0) {
-          node.type = rawType;
-          return;
-        }
-
-        if (typeArguments == null) {
-          node.type = typeSystem.instantiateToBounds(rawType);
-          return;
-        }
-
-        if (typeArguments.length != typeParametersLength) {
-          typeArguments = _listOfDynamic(typeParametersLength);
-        }
-
-        node.type = InterfaceTypeImpl.explicit(element, typeArguments);
-      }
-    } else if (element is GenericTypeAliasElement) {
-      _build((element as ElementImpl).linkedNode);
-
-      var rawType = element.function.type;
-
-      var typeParameters = element.typeParameters;
-      var typeParametersLength = typeParameters.length;
-      if (typeParametersLength == 0) {
-        node.type = rawType;
-        return;
-      }
-
-      if (typeArguments == null) {
-        typeArguments = typeSystem.instantiateTypeFormalsToBounds(
-          typeParameters,
-        );
-      } else if (typeArguments.length != typeParametersLength) {
-        typeArguments = _listOfDynamic(typeParametersLength);
-      }
-
-      var substitution = Substitution.fromPairs(
-        typeParameters,
-        typeArguments,
-      );
-      node.type = substitution.substituteType(rawType);
-    } else if (element is TypeParameterElement) {
-      node.type = TypeParameterTypeImpl(element);
-    } else {
-      // We might get all kinds of elements, including not type at all.
-      // For example a PrefixElement, or a getter, etc.
-      // In all these cases the type is dynamic.
-      node.type = _dynamicType;
-    }
-  }
-
-  void _typeParameterList(TypeParameterList node) {
-    if (node == null) return;
-
-    for (var typeParameter in node.typeParameters) {
-      _build(typeParameter.bound);
-    }
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart
new file mode 100644
index 0000000..0fa8a2b
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/types_builder.dart
@@ -0,0 +1,352 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+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/type.dart';
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/summary2/default_types_builder.dart';
+import 'package:analyzer/src/summary2/lazy_ast.dart';
+import 'package:analyzer/src/summary2/type_builder.dart';
+
+class NodesToBuildType {
+  final List<AstNode> declarations = [];
+  final List<TypeBuilder> typeBuilders = [];
+
+  void addDeclaration(AstNode node) {
+    declarations.add(node);
+  }
+
+  void addTypeBuilder(TypeBuilder builder) {
+    typeBuilders.add(builder);
+  }
+}
+
+class TypesBuilder {
+  final Dart2TypeSystem typeSystem;
+
+  TypesBuilder(this.typeSystem);
+
+  DynamicTypeImpl get _dynamicType => DynamicTypeImpl.instance;
+
+  VoidTypeImpl get _voidType => VoidTypeImpl.instance;
+
+  /// Build types for all type annotations, and set types for declarations.
+  void build(NodesToBuildType nodes) {
+    DefaultTypesBuilder(typeSystem).build(nodes.declarations);
+
+    for (var builder in nodes.typeBuilders) {
+      builder.build();
+    }
+
+    _MixinsInference(typeSystem).perform(nodes.declarations);
+
+    for (var declaration in nodes.declarations) {
+      _declaration(declaration);
+    }
+  }
+
+  FunctionType _buildFunctionType(
+    TypeParameterList typeParameterList,
+    TypeAnnotation returnTypeNode,
+    FormalParameterList parameterList,
+  ) {
+    var returnType = returnTypeNode?.type ?? _dynamicType;
+
+    List<TypeParameterElement> typeParameters;
+    if (typeParameterList != null) {
+      typeParameters = typeParameterList.typeParameters
+          .map<TypeParameterElement>((p) => p.declaredElement)
+          .toList();
+    } else {
+      typeParameters = const <TypeParameterElement>[];
+    }
+
+    var formalParameters = parameterList.parameters.map((parameter) {
+      return ParameterElementImpl.synthetic(
+        parameter.identifier?.name ?? '',
+        _getType(parameter),
+        // ignore: deprecated_member_use_from_same_package
+        parameter.kind,
+      );
+    }).toList();
+
+    return FunctionTypeImpl.synthetic(
+      returnType,
+      typeParameters,
+      formalParameters,
+    );
+  }
+
+  void _classDeclaration(ClassDeclaration node) {}
+
+  void _declaration(AstNode node) {
+    if (node is ClassDeclaration) {
+      _classDeclaration(node);
+    } else if (node is ClassTypeAlias) {
+      // TODO(scheglov) ???
+    } else if (node is FieldFormalParameter) {
+      _fieldFormalParameter(node);
+    } else if (node is FunctionDeclaration) {
+      var returnType = node.returnType?.type;
+      if (returnType == null) {
+        if (node.isSetter) {
+          returnType = _voidType;
+        } else {
+          returnType = _dynamicType;
+        }
+      }
+      LazyAst.setReturnType(node, returnType);
+    } else if (node is FunctionTypeAlias) {
+      _functionTypeAlias(node);
+    } else if (node is FunctionTypedFormalParameter) {
+      _functionTypedFormalParameter(node);
+    } else if (node is GenericTypeAlias) {
+      // TODO(scheglov) ???
+    } else if (node is MethodDeclaration) {
+      var returnType = node.returnType?.type;
+      if (returnType == null) {
+        if (node.isSetter) {
+          returnType = _voidType;
+        } else if (node.isOperator && node.name.name == '[]=') {
+          returnType = _voidType;
+        } else {
+          returnType = _dynamicType;
+        }
+      }
+      LazyAst.setReturnType(node, returnType);
+    } else if (node is MixinDeclaration) {
+      // TODO(scheglov) ???
+    } else if (node is SimpleFormalParameter) {
+      LazyAst.setType(node, node.type?.type ?? _dynamicType);
+    } else if (node is VariableDeclarationList) {
+      var type = node.type?.type;
+      if (type != null) {
+        for (var variable in node.variables) {
+          LazyAst.setType(variable, type);
+        }
+      }
+    } else {
+      throw UnimplementedError('${node.runtimeType}');
+    }
+  }
+
+  void _fieldFormalParameter(FieldFormalParameter node) {
+    var parameterList = node.parameters;
+    if (parameterList != null) {
+      var type = _buildFunctionType(
+        node.typeParameters,
+        node.type,
+        parameterList,
+      );
+      LazyAst.setType(node, type);
+    } else {
+      LazyAst.setType(node, node.type?.type ?? _dynamicType);
+    }
+  }
+
+  void _functionTypeAlias(FunctionTypeAlias node) {
+    var returnTypeNode = node.returnType;
+    LazyAst.setReturnType(node, returnTypeNode?.type ?? _dynamicType);
+  }
+
+  void _functionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    var type = _buildFunctionType(
+      node.typeParameters,
+      node.returnType,
+      node.parameters,
+    );
+    LazyAst.setType(node, type);
+  }
+
+  static DartType _getType(FormalParameter node) {
+    if (node is DefaultFormalParameter) {
+      return _getType(node.parameter);
+    }
+    return LazyAst.getType(node);
+  }
+}
+
+/// Performs mixins inference in a [ClassDeclaration].
+class _MixinInference {
+  final Dart2TypeSystem typeSystem;
+
+  InterfaceType classType;
+  List<InterfaceType> mixinTypes = [];
+  List<InterfaceType> supertypesForMixinInference;
+
+  _MixinInference(this.typeSystem, this.classType);
+
+  void perform(WithClause withClause) {
+    if (withClause == null) return;
+
+    for (var mixinNode in withClause.mixinTypes) {
+      var mixinType = _inferSingle(mixinNode);
+      mixinTypes.add(mixinType);
+
+      _addSupertypes(mixinType);
+    }
+  }
+
+  void _addSupertypes(InterfaceType type) {
+    if (supertypesForMixinInference != null) {
+      ClassElementImpl.collectAllSupertypes(
+        supertypesForMixinInference,
+        type,
+        classType,
+      );
+    }
+  }
+
+  InterfaceType _findInterfaceTypeForElement(
+    ClassElement element,
+    List<InterfaceType> interfaceTypes,
+  ) {
+    for (var interfaceType in interfaceTypes) {
+      if (interfaceType.element == element) return interfaceType;
+    }
+    return null;
+  }
+
+  List<InterfaceType> _findInterfaceTypesForConstraints(
+    List<InterfaceType> constraints,
+    List<InterfaceType> interfaceTypes,
+  ) {
+    var result = <InterfaceType>[];
+    for (var constraint in constraints) {
+      var interfaceType = _findInterfaceTypeForElement(
+        constraint.element,
+        interfaceTypes,
+      );
+
+      // No matching interface type found, so inference fails.
+      if (interfaceType == null) {
+        return null;
+      }
+
+      result.add(interfaceType);
+    }
+    return result;
+  }
+
+  InterfaceType _inferSingle(TypeName mixinNode) {
+    var mixinType = _interfaceType(mixinNode.type);
+
+    if (mixinNode.typeArguments != null) {
+      return mixinType;
+    }
+
+    var mixinElement = mixinType.element;
+    if (mixinElement.typeParameters.isEmpty) {
+      return mixinType;
+    }
+
+    var mixinSupertypeConstraints =
+        typeSystem.gatherMixinSupertypeConstraintsForInference(mixinElement);
+    if (mixinSupertypeConstraints.isEmpty) {
+      return mixinType;
+    }
+
+    if (supertypesForMixinInference == null) {
+      supertypesForMixinInference = <InterfaceType>[];
+      _addSupertypes(classType.superclass);
+      for (var previousMixinType in mixinTypes) {
+        _addSupertypes(previousMixinType);
+      }
+    }
+
+    var matchingInterfaceTypes = _findInterfaceTypesForConstraints(
+      mixinSupertypeConstraints,
+      supertypesForMixinInference,
+    );
+
+    // Note: if matchingInterfaceType is null, that's an error.  Also,
+    // if there are multiple matching interface types that use
+    // different type parameters, that's also an error.  But we can't
+    // report errors from the linker, so we just use the
+    // first matching interface type (if there is one).  The error
+    // detection logic is implemented in the ErrorVerifier.
+    if (matchingInterfaceTypes == null) {
+      return mixinType;
+    }
+
+    // Try to pattern match matchingInterfaceTypes against
+    // mixinSupertypeConstraints to find the correct set of type
+    // parameters to apply to the mixin.
+    var inferredMixin = typeSystem.matchSupertypeConstraints(
+      mixinElement,
+      mixinSupertypeConstraints,
+      matchingInterfaceTypes,
+    );
+    if (inferredMixin != null) {
+      mixinType = inferredMixin;
+      mixinNode.type = inferredMixin;
+    }
+
+    return mixinType;
+  }
+
+  InterfaceType _interfaceType(DartType type) {
+    if (type is InterfaceType && !type.element.isEnum) {
+      return type;
+    }
+    return typeSystem.typeProvider.objectType;
+  }
+}
+
+/// Performs mixin inference for all declarations.
+class _MixinsInference {
+  final Dart2TypeSystem typeSystem;
+
+  _MixinsInference(this.typeSystem);
+
+  void perform(List<AstNode> declarations) {
+    for (var node in declarations) {
+      if (node is ClassDeclaration || node is ClassTypeAlias) {
+        ClassElementImpl element = (node as Declaration).declaredElement;
+        element.linkedMixinInferenceCallback = _callbackWhenRecursion;
+      }
+    }
+
+    for (var declaration in declarations) {
+      _inferDeclaration(declaration);
+    }
+  }
+
+  /// This method is invoked when mixins are asked from the [element], and
+  /// we are inferring the [element] now, i.e. there is a loop.
+  ///
+  /// This is an error. So, we return the empty list, and break the loop.
+  List<InterfaceType> _callbackWhenLoop(ClassElementImpl element) {
+    element.linkedMixinInferenceCallback = null;
+    return <InterfaceType>[];
+  }
+
+  /// This method is invoked when mixins are asked from the [element], and
+  /// we are not inferring the [element] now, i.e. there is no loop.
+  List<InterfaceType> _callbackWhenRecursion(ClassElementImpl element) {
+    _inferDeclaration(element.linkedNode);
+    // The inference was successful, let the element return actual mixins.
+    return null;
+  }
+
+  void _infer(ClassElementImpl element, WithClause withClause) {
+    element.linkedMixinInferenceCallback = _callbackWhenLoop;
+    try {
+      _MixinInference(typeSystem, element.type).perform(withClause);
+    } finally {
+      element.linkedMixinInferenceCallback = null;
+    }
+  }
+
+  void _inferDeclaration(AstNode node) {
+    if (node is ClassDeclaration) {
+      _infer(node.declaredElement, node.withClause);
+    } else if (node is ClassTypeAlias) {
+      _infer(node.declaredElement, node.withClause);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 0708ecf..7725c55 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -6,6 +6,7 @@
 // refactored to fit into analyzer.
 import 'dart:collection';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/ast/token.dart' show TokenType;
@@ -123,6 +124,8 @@
   final AnalysisOptionsImpl _options;
   _OverrideChecker _overrideChecker;
 
+  FeatureSet _featureSet;
+
   bool _failure = false;
   bool _hasImplicitCasts;
   HashSet<ExecutableElement> _covariantPrivateMembers;
@@ -334,6 +337,7 @@
 
   @override
   void visitCompilationUnit(CompilationUnit node) {
+    _featureSet = node.featureSet;
     _hasImplicitCasts = false;
     _covariantPrivateMembers = new HashSet();
     node.visitChildren(this);
@@ -733,7 +737,7 @@
       var rhsType = _getExpressionType(expr.rightHandSide);
       var lhsType = _getExpressionType(expr.leftHandSide);
       var returnType = rules.refineBinaryExpressionType(
-          lhsType, op, rhsType, functionType.returnType);
+          lhsType, op, rhsType, functionType.returnType, _featureSet);
 
       // Check the argument for an implicit cast.
       _checkImplicitCast(expr.rightHandSide, paramTypes[0], from: rhsType);
@@ -958,8 +962,8 @@
         var functionType = element.type;
         var rhsType = typeProvider.intType;
         var lhsType = _getExpressionType(operand);
-        var returnType = rules.refineBinaryExpressionType(
-            lhsType, TokenType.PLUS, rhsType, functionType.returnType);
+        var returnType = rules.refineBinaryExpressionType(lhsType,
+            TokenType.PLUS, rhsType, functionType.returnType, _featureSet);
 
         // Skip the argument check - `int` cannot be downcast.
         //
@@ -1114,7 +1118,7 @@
     }
 
     // Down cast or legal sideways cast, coercion needed.
-    if (rules.isAssignableTo(from, to)) {
+    if (rules.isAssignableTo(from, to, featureSet: _featureSet)) {
       return true;
     }
 
@@ -1180,11 +1184,12 @@
           if (expr.isMap) {
             _recordMessage(
                 expr, StrongModeCode.INVALID_CAST_LITERAL_MAP, [from, to]);
-          } else {
-            // Ambiguity should be resolved by now
-            assert(expr.isSet);
+          } else if (expr.isSet) {
             _recordMessage(
                 expr, StrongModeCode.INVALID_CAST_LITERAL_SET, [from, to]);
+          } else {
+            // This should only happen when the code is invalid, in which case
+            // the error should have been reported elsewhere.
           }
         } else {
           _recordMessage(
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index 35a6337..ed2c5c3 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -16,6 +16,7 @@
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/link.dart'
     show FieldElementForLink_ClassField, ParameterElementForLink;
+import 'package:analyzer/src/summary2/lazy_ast.dart';
 
 /**
  * Sets the type of the field. The types in implicit accessors are updated
@@ -169,7 +170,14 @@
           parameterType = type;
         }
       } else if (parameterType != type) {
-        if (parameter is ParameterElementForLink) {
+        if (parameter is ParameterElementImpl && parameter.linkedNode != null) {
+          LazyAst.setTypeInferenceError(
+            parameter.linkedNode,
+            TopLevelInferenceErrorBuilder(
+              kind: TopLevelInferenceErrorKind.overrideConflictParameterType,
+            ),
+          );
+        } else if (parameter is ParameterElementForLink) {
           parameter.setInferenceError(new TopLevelInferenceErrorBuilder(
               kind: TopLevelInferenceErrorKind.overrideConflictParameterType));
         }
@@ -411,7 +419,14 @@
     _FieldOverrideInferenceResult typeResult =
         _computeFieldOverrideType(field.getter);
     if (typeResult.isError) {
-      if (field is FieldElementForLink_ClassField) {
+      if (field is FieldElementImpl && field.linkedNode != null) {
+        LazyAst.setTypeInferenceError(
+          field.linkedNode,
+          TopLevelInferenceErrorBuilder(
+            kind: TopLevelInferenceErrorKind.overrideConflictFieldType,
+          ),
+        );
+      } else if (field is FieldElementForLink_ClassField) {
         field.setInferenceError(new TopLevelInferenceErrorBuilder(
             kind: TopLevelInferenceErrorKind.overrideConflictFieldType));
       }
@@ -420,8 +435,12 @@
 
     if (field.hasImplicitType) {
       DartType newType = typeResult.type;
-      if (newType == null && field.initializer != null) {
-        newType = field.initializer.returnType;
+
+      if (newType == null) {
+        var initializer = field.initializer;
+        if (initializer != null) {
+          newType = initializer.returnType;
+        }
       }
 
       if (newType == null || newType.isBottom || newType.isDartCoreNull) {
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index f8ff22c..bf87a5f 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -498,4 +498,13 @@
     }
     throw StateError('Not found: $name');
   }
+
+  TopLevelVariableElement topVar(String name) {
+    for (var variable in definingUnit.topLevelVariables) {
+      if (variable.name == name) {
+        return variable;
+      }
+    }
+    throw StateError('Not found: $name');
+  }
 }
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index ced02d0..7a1f121 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -87,6 +87,10 @@
     return _node(search, (n) => n is ExpressionStatement);
   }
 
+  FieldDeclaration fieldDeclaration(String search) {
+    return _node(search, (n) => n is FieldDeclaration);
+  }
+
   FieldFormalParameter fieldFormalParameter(String search) {
     return _node(search, (n) => n is FieldFormalParameter);
   }
@@ -107,6 +111,10 @@
     return _node(search, (n) => n is FunctionExpression);
   }
 
+  FunctionExpressionInvocation functionExpressionInvocation(String search) {
+    return _node(search, (n) => n is FunctionExpressionInvocation);
+  }
+
   FunctionTypeAlias functionTypeAlias(String search) {
     return _node(search, (n) => n is FunctionTypeAlias);
   }
diff --git a/pkg/analyzer/lib/src/workspace/basic.dart b/pkg/analyzer/lib/src/workspace/basic.dart
index 0b177f0..59ff9e1 100644
--- a/pkg/analyzer/lib/src/workspace/basic.dart
+++ b/pkg/analyzer/lib/src/workspace/basic.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/workspace/simple.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:package_config/packages.dart';
@@ -68,10 +69,13 @@
   BasicWorkspacePackage(this.root, this.workspace);
 
   @override
-  bool contains(String path) {
+  bool contains(Source source) {
+    // When dealing with a BasicWorkspace, [source] will always have a valid
+    // fullName.
+    String filePath = source.fullName;
     // There is a 1-1 relationship between [BasicWorkspace]s and
     // [BasicWorkspacePackage]s. If a file is in a package's workspace, then it
     // is in the package as well.
-    return workspace.provider.pathContext.isWithin(root, path);
+    return workspace.provider.pathContext.isWithin(root, filePath);
   }
 }
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index 9151e23..d66c851 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -97,34 +97,8 @@
 
   @override
   Uri restoreAbsolute(Source source) {
-    path.Context context = _workspace.provider.pathContext;
     String filePath = source.fullName;
 
-    Uri restore(String root, String filePath) {
-      if (root != null && context.isWithin(root, filePath)) {
-        String relative = context.relative(filePath, from: root);
-        List<String> components = context.split(relative);
-        if (components.length > 4 &&
-            components[0] == 'third_party' &&
-            components[1] == 'dart' &&
-            components[3] == 'lib') {
-          String packageName = components[2];
-          String pathInLib = components.skip(4).join('/');
-          return Uri.parse('package:$packageName/$pathInLib');
-        } else {
-          for (int i = 2; i < components.length - 1; i++) {
-            String component = components[i];
-            if (component == 'lib') {
-              String packageName = components.getRange(0, i).join('.');
-              String pathInLib = components.skip(i + 1).join('/');
-              return Uri.parse('package:$packageName/$pathInLib');
-            }
-          }
-        }
-      }
-      return null;
-    }
-
     // Search in each root.
     for (String root in [
       _workspace.bin,
@@ -132,14 +106,43 @@
       _workspace.readonly,
       _workspace.root
     ]) {
-      Uri uri = restore(root, filePath);
-      if (uri != null) {
-        return uri;
+      List<String> uriParts = _restoreUriParts(root, filePath);
+      if (uriParts != null) {
+        return Uri.parse('package:${uriParts[0]}/${uriParts[1]}');
       }
     }
 
     return null;
   }
+
+  /// Restore [filePath] to its 'package:' URI parts.
+  ///
+  /// Returns `null` if [root] is null or if [filePath] is not within [root].
+  List<String> _restoreUriParts(String root, String filePath) {
+    path.Context context = _workspace.provider.pathContext;
+    if (root != null && context.isWithin(root, filePath)) {
+      String relative = context.relative(filePath, from: root);
+      List<String> components = context.split(relative);
+      if (components.length > 4 &&
+          components[0] == 'third_party' &&
+          components[1] == 'dart' &&
+          components[3] == 'lib') {
+        String packageName = components[2];
+        String pathInLib = components.skip(4).join('/');
+        return [packageName, pathInLib];
+      } else {
+        for (int i = 2; i < components.length - 1; i++) {
+          String component = components[i];
+          if (component == 'lib') {
+            String packageName = components.getRange(0, i).join('.');
+            String pathInLib = components.skip(i + 1).join('/');
+            return [packageName, pathInLib];
+          }
+        }
+      }
+    }
+    return null;
+  }
 }
 
 /**
@@ -276,7 +279,13 @@
 
       if (folder.getChildAssumingFile(_buildFileName).exists) {
         // Found the BUILD file, denoting a Dart package.
-        return BazelWorkspacePackage(folder.path, this);
+        List<String> uriParts = (packageUriResolver as BazelPackageUriResolver)
+            ._restoreUriParts(root, '${folder.path}/lib/__fake__.dart');
+        if (uriParts == null || uriParts.isEmpty) {
+          return BazelWorkspacePackage(null, folder.path, this);
+        } else {
+          return BazelWorkspacePackage(uriParts[0], folder.path, this);
+        }
       }
 
       // Go up a folder.
@@ -299,6 +308,10 @@
    * corresponding readonly workspace root.
    */
   static BazelWorkspace find(ResourceProvider provider, String filePath) {
+    Resource resource = provider.getResource(filePath);
+    if (resource is File && resource.parent != null) {
+      filePath = resource.parent.path;
+    }
     path.Context context = provider.pathContext;
     Folder folder = provider.getFolder(filePath);
     while (true) {
@@ -373,24 +386,33 @@
  * a given package in a BazelWorkspace.
  */
 class BazelWorkspacePackage extends WorkspacePackage {
+  /// A prefix for any URI of a path in this package.
+  final String _uriPrefix;
+
   final String root;
 
   final BazelWorkspace workspace;
 
-  BazelWorkspacePackage(this.root, this.workspace);
+  BazelWorkspacePackage(String packageName, this.root, this.workspace)
+      : this._uriPrefix = 'package:$packageName/';
 
   @override
-  bool contains(String path) {
-    if (workspace.findFile(path) == null) {
+  bool contains(Source source) {
+    if (source.uri.isScheme('package')) {
+      return source.uri.toString().startsWith(_uriPrefix);
+    }
+    String filePath = source.fullName;
+    if (filePath == null) return false;
+    if (workspace.findFile(filePath) == null) {
       return false;
     }
-    if (!workspace.provider.pathContext.isWithin(root, path)) {
+    if (!workspace.provider.pathContext.isWithin(root, filePath)) {
       return false;
     }
 
-    // Just because [path] is within [root] does not mean it is in this
+    // Just because [filePath] is within [root] does not mean it is in this
     // package; it could be in a "subpackage." Must go through the work of
-    // learning exactly which package [path] is contained in.
-    return workspace.findPackageFor(path).root == root;
+    // learning exactly which package [filePath] is contained in.
+    return workspace.findPackageFor(filePath).root == root;
   }
 }
diff --git a/pkg/analyzer/lib/src/workspace/gn.dart b/pkg/analyzer/lib/src/workspace/gn.dart
index 1f2a608..7244b90 100644
--- a/pkg/analyzer/lib/src/workspace/gn.dart
+++ b/pkg/analyzer/lib/src/workspace/gn.dart
@@ -313,17 +313,19 @@
   GnWorkspacePackage(this.root, this.workspace);
 
   @override
-  bool contains(String path) {
-    if (workspace.findFile(path) == null) {
+  bool contains(Source source) {
+    String filePath = filePathFromSource(source);
+    if (filePath == null) return false;
+    if (workspace.findFile(filePath) == null) {
       return false;
     }
-    if (!workspace.provider.pathContext.isWithin(root, path)) {
+    if (!workspace.provider.pathContext.isWithin(root, filePath)) {
       return false;
     }
 
-    // Just because [path] is within [root] does not mean it is in this
+    // Just because [filePath] is within [root] does not mean it is in this
     // package; it could be in a "subpackage." Must go through the work of
-    // learning exactly which package [path] is contained in.
-    return workspace.findPackageFor(path).root == root;
+    // learning exactly which package [filePath] is contained in.
+    return workspace.findPackageFor(filePath).root == root;
   }
 }
diff --git a/pkg/analyzer/lib/src/workspace/package_build.dart b/pkg/analyzer/lib/src/workspace/package_build.dart
index 4e6bee0..4459dd5 100644
--- a/pkg/analyzer/lib/src/workspace/package_build.dart
+++ b/pkg/analyzer/lib/src/workspace/package_build.dart
@@ -106,19 +106,27 @@
     String filePath = source.fullName;
 
     if (_context.isWithin(_workspace.root, filePath)) {
-      String relative = _context.relative(filePath, from: _workspace.root);
-      List<String> components = _context.split(relative);
-      if (components.length > 4 &&
-          components[0] == 'build' &&
-          components[1] == 'generated' &&
-          components[3] == 'lib') {
-        String packageName = components[2];
-        String pathInLib = components.skip(4).join('/');
-        return Uri.parse('package:$packageName/$pathInLib');
+      List<String> uriParts = _restoreUriParts(filePath);
+      if (uriParts != null) {
+        return Uri.parse('package:${uriParts[0]}/${uriParts[1]}');
       }
     }
     return source.uri;
   }
+
+  List<String> _restoreUriParts(String filePath) {
+    String relative = _context.relative(filePath, from: _workspace.root);
+    List<String> components = _context.split(relative);
+    if (components.length > 4 &&
+        components[0] == 'build' &&
+        components[1] == 'generated' &&
+        components[3] == 'lib') {
+      String packageName = components[2];
+      String pathInLib = components.skip(4).join('/');
+      return [packageName, pathInLib];
+    }
+    return null;
+  }
 }
 
 /**
@@ -277,8 +285,9 @@
 
   @override
   WorkspacePackage findPackageFor(String filePath) {
-    final Folder folder = provider.getFolder(filePath);
-    if (provider.pathContext.isWithin(root, folder.path)) {
+    path.Context context = provider.pathContext;
+    final folder = provider.getFolder(context.dirname(filePath));
+    if (context.isWithin(root, folder.path)) {
       _theOnlyPackage ??= new PackageBuildWorkspacePackage(root, this);
       return _theOnlyPackage;
     } else {
@@ -337,7 +346,9 @@
   PackageBuildWorkspacePackage(this.root, this.workspace);
 
   @override
-  bool contains(String filePath) {
+  bool contains(Source source) {
+    String filePath = filePathFromSource(source);
+    if (filePath == null) return false;
     // There is a 1-1 relationship between PackageBuildWorkspaces and
     // PackageBuildWorkspacePackages. If a file is in a package's workspace,
     // then it is in the package as well.
diff --git a/pkg/analyzer/lib/src/workspace/pub.dart b/pkg/analyzer/lib/src/workspace/pub.dart
index 3cfbe59..65347eb 100644
--- a/pkg/analyzer/lib/src/workspace/pub.dart
+++ b/pkg/analyzer/lib/src/workspace/pub.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/workspace/simple.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:package_config/packages.dart';
@@ -71,10 +72,12 @@
   PubWorkspacePackage(this.root, this.workspace);
 
   @override
-  bool contains(String path) {
+  bool contains(Source source) {
+    String filePath = filePathFromSource(source);
+    if (filePath == null) return false;
     // There is a 1-1 relationship between [PubWorkspace]s and
     // [PubWorkspacePackage]s. If a file is in a package's workspace, then it
     // is in the package as well.
-    return workspace.provider.pathContext.isWithin(root, path);
+    return workspace.provider.pathContext.isWithin(root, filePath);
   }
 }
diff --git a/pkg/analyzer/lib/src/workspace/workspace.dart b/pkg/analyzer/lib/src/workspace/workspace.dart
index be58cdb..7b74cb5 100644
--- a/pkg/analyzer/lib/src/workspace/workspace.dart
+++ b/pkg/analyzer/lib/src/workspace/workspace.dart
@@ -62,5 +62,18 @@
 
   Workspace get workspace;
 
-  bool contains(String path);
+  bool contains(Source source);
+
+  /// Return a file path for the location of [source].
+  ///
+  /// If [source]'s URI scheme is package, it's fullName might be unusable (for
+  /// example, the case of a [InSummarySource]). In this case, use
+  /// [workspace]'s package URI resolver to fetch the file path.
+  String filePathFromSource(Source source) {
+    if (source.uri.scheme == 'package') {
+      return workspace.packageUriResolver.resolveAbsolute(source.uri)?.fullName;
+    } else {
+      return source.fullName;
+    }
+  }
 }
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index cf9777b..29b6585 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,20 +1,20 @@
 name: analyzer
-version: 0.36.1-dev
+version: 0.36.4-dev
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
 environment:
-  sdk: '>=2.1.0-dev.5.0 <3.0.0'
+  sdk: '>=2.2.2 <3.0.0'
 dependencies:
   args: '>=0.12.1 <2.0.0'
   charcode: ^1.1.0
   collection: ^1.10.1
   convert: ^2.0.0
   crypto: '>=1.1.1 <3.0.0'
-  front_end: 0.1.15
+  front_end: 0.1.18
   glob: ^1.0.3
   html: '>=0.13.4+1 <0.15.0'
-  kernel: 0.3.15
+  kernel: 0.3.18
   meta: ^1.0.2
   package_config: '>=0.1.5 <2.0.0'
   path: '>=0.9.0 <2.0.0'
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index 4468d47..585da6a 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -615,6 +616,8 @@
 E f() => g;
 ''';
 
+  final featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
+
   CompilationUnit _unit;
 
   CompilationUnit get unit {
@@ -623,9 +626,12 @@
           new GatheringErrorListener(checkRanges: true);
       var source =
           new StringSource(contents, 'PreviousTokenTest_findPrevious.dart');
-      Token tokens = new Scanner.fasta(source, listener).tokenize();
-      _unit = new Parser(source, listener, useFasta: true)
-          .parseCompilationUnit(tokens);
+      var scanner = new Scanner.fasta(source, listener)
+        ..configureFeatures(featureSet);
+      Token tokens = scanner.tokenize();
+      _unit =
+          new Parser(source, listener, featureSet: featureSet, useFasta: true)
+              .parseCompilationUnit(tokens);
     }
     return _unit;
   }
@@ -670,7 +676,9 @@
     GatheringErrorListener listener =
         new GatheringErrorListener(checkRanges: true);
     var source = new StringSource('missing', 'PreviousTokenTest_missing.dart');
-    Token missing = new Scanner.fasta(source, listener).tokenize();
+    var scanner = new Scanner.fasta(source, listener)
+      ..configureFeatures(featureSet);
+    Token missing = scanner.tokenize();
 
     expect(statement.findPrevious(missing), null);
     expect(statement.findPrevious(null), null);
@@ -690,16 +698,16 @@
     expect(statement.findPrevious(findToken('return')).lexeme, '{');
   }
 
+  void test_findPrevious_sibling_class() {
+    CompilationUnitMember declaration = unit.declarations[1];
+    expect(declaration.findPrevious(findToken('E')).lexeme, '}');
+  }
+
   void test_findPrevious_sibling_method() {
     ClassDeclaration clazz = unit.declarations[0];
     MethodDeclaration method = clazz.members[1];
     expect(method.findPrevious(findToken('D')).lexeme, '}');
   }
-
-  void test_findPrevious_sibling_class() {
-    CompilationUnitMember declaration = unit.declarations[1];
-    expect(declaration.findPrevious(findToken('E')).lexeme, '}');
-  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/dart/element/builder_test.dart b/pkg/analyzer/test/dart/element/builder_test.dart
index 25ba692..a7de7ad 100644
--- a/pkg/analyzer/test/dart/element/builder_test.dart
+++ b/pkg/analyzer/test/dart/element/builder_test.dart
@@ -274,12 +274,11 @@
             null,
             AstTestFactory.typeName4('int'),
             [AstTestFactory.variableDeclaration('V')]);
-    CompilationUnit unit = astFactory.compilationUnit(
-        topLevelVariableDeclaration.beginToken,
-        null,
-        [],
-        [topLevelVariableDeclaration],
-        topLevelVariableDeclaration.endToken);
+    CompilationUnit unit = astFactory.compilationUnit2(
+        beginToken: topLevelVariableDeclaration.beginToken,
+        declarations: [topLevelVariableDeclaration],
+        endToken: topLevelVariableDeclaration.endToken,
+        featureSet: null);
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = _makeBuilder(holder);
     unit.beginToken.offset = 10;
@@ -466,7 +465,7 @@
     expect(parameter.isConst, isFalse);
     expect(parameter.isFinal, isFalse);
     expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isNotOptional, isTrue);
+    expect(parameter.isRequiredPositional, isTrue);
     _assertVisibleRange(parameter, 100, 110);
   }
 
@@ -490,7 +489,7 @@
     expect(parameter.isExplicitlyCovariant, isTrue);
     expect(parameter.isFinal, isFalse);
     expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isNotOptional, isTrue);
+    expect(parameter.isRequiredPositional, isTrue);
     _assertVisibleRange(parameter, 100, 110);
   }
 
@@ -514,7 +513,7 @@
     expect(parameter.isConst, isFalse);
     expect(parameter.isFinal, isFalse);
     expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isNotOptional, isTrue);
+    expect(parameter.isRequiredPositional, isTrue);
     expect(typeElement.typeParameters, hasLength(1));
     _assertVisibleRange(parameter, 100, 110);
   }
@@ -641,7 +640,7 @@
     expect(parameter.isFinal, isFalse);
     expect(parameter.isSynthetic, isFalse);
     expect(parameter.name, parameterName);
-    expect(parameter.isNotOptional, isTrue);
+    expect(parameter.isRequiredPositional, isTrue);
     _assertVisibleRange(parameter, 100, 110);
   }
 
@@ -667,7 +666,7 @@
     expect(parameter.isFinal, isFalse);
     expect(parameter.isSynthetic, isFalse);
     expect(parameter.name, parameterName);
-    expect(parameter.isNotOptional, isTrue);
+    expect(parameter.isRequiredPositional, isTrue);
     _assertVisibleRange(parameter, 100, 110);
   }
 
@@ -691,7 +690,7 @@
     expect(parameter.isFinal, isFalse);
     expect(parameter.isSynthetic, isFalse);
     expect(parameter.name, parameterName);
-    expect(parameter.isNotOptional, isTrue);
+    expect(parameter.isRequiredPositional, isTrue);
     _assertVisibleRange(parameter, 100, 110);
   }
 
@@ -718,7 +717,7 @@
     expect(parameter.isFinal, isFalse);
     expect(parameter.isSynthetic, isFalse);
     expect(parameter.name, parameterName);
-    expect(parameter.isNotOptional, isTrue);
+    expect(parameter.isRequiredPositional, isTrue);
     _assertVisibleRange(parameter, 100, 110);
   }
 
@@ -1855,7 +1854,7 @@
     expect(parameter.isConst, isFalse);
     expect(parameter.isFinal, isFalse);
     expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isNotOptional, isTrue);
+    expect(parameter.isRequiredPositional, isTrue);
     expect(parameter.parameters, hasLength(0));
   }
 
@@ -1879,7 +1878,7 @@
     expect(parameter.isConst, isFalse);
     expect(parameter.isFinal, isFalse);
     expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isNotOptional, isTrue);
+    expect(parameter.isRequiredPositional, isTrue);
     expect(typeElement.parameters, hasLength(1));
   }
 
diff --git a/pkg/analyzer/test/file_system/overlay_file_system_test.dart b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
index c422ade..7ee7052 100644
--- a/pkg/analyzer/test/file_system/overlay_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
@@ -179,6 +179,15 @@
     expect(file.readAsBytesSync(), <int>[98, 98, 98]);
   }
 
+  test_readAsBytesSync_existing_withOverlay_utf8() {
+    // Strings should be encoded as UTF8 when they're written, so when we read
+    // them back as bytes we should see the UTF8-encoded version of the string.
+    String overlayContent = '\u00e5'; // latin small letter a with ring above
+    File file =
+        _file(exists: true, withOverlay: true, overlayContent: overlayContent);
+    expect(file.readAsBytesSync(), <int>[0xc3, 0xa5]);
+  }
+
   test_readAsBytesSync_notExisting_withoutOverlay() {
     File file = _file(exists: false);
     expect(() => file.readAsBytesSync(), throwsA(_isFileSystemException));
@@ -506,7 +515,7 @@
     expect(child, isNotNull);
   }
 
-  test_getChildren() {
+  test_getChildren_existing() {
     Folder folder = _folder(exists: true);
     Folder child1 = _folder(
         exists: true, path: provider.pathContext.join(folder.path, 'lib'));
@@ -523,6 +532,13 @@
         unorderedEquals([child1.path, child2.path, child3.path]));
   }
 
+  test_getChildren_nonExisting_withOverlay() {
+    File file = _file(exists: false, withOverlay: true);
+    List<Resource> children = file.parent.parent.getChildren();
+    expect(children, hasLength(1));
+    expect(children[0], _isFolder);
+  }
+
   test_isOrContains_false() {
     Folder folder = _folder(exists: true);
     expect(folder.isOrContains(baseProvider.convertPath('/foo/baz')), isFalse);
@@ -662,20 +678,28 @@
     expect(file.exists, isTrue);
   }
 
-  test_getFolder_existing() {
+  test_getFolder_existing_withoutOverlay() {
     Folder folder = _folder(exists: true);
     expect(folder, isNotNull);
     expect(folder.path, defaultFolderPath);
     expect(folder.exists, isTrue);
   }
 
-  test_getFolder_notExisting() {
+  test_getFolder_notExisting_withoutOverlay() {
     Folder folder = _folder(exists: false);
     expect(folder, isNotNull);
     expect(folder.path, defaultFolderPath);
     expect(folder.exists, isFalse);
   }
 
+  test_getFolder_notExisting_withOverlay() {
+    File file = _file(exists: false, withOverlay: true);
+    Folder folder = file.parent;
+    expect(folder, isNotNull);
+    expect(folder.path, defaultFolderPath);
+    expect(folder.exists, isTrue);
+  }
+
   test_getModificationTimes_withoutOverlay() async {
     Source source = _file(exists: true).createSource();
     List<int> times = await provider.getModificationTimes([source]);
@@ -688,36 +712,43 @@
     expect(times, [42]);
   }
 
-  test_getResource_existingFile_withoutOverlay() {
+  test_getResource_file_existing_withoutOverlay() {
     String path = _file(exists: true).path;
     Resource resource = provider.getResource(path);
     expect(resource, _isFile);
   }
 
-  test_getResource_existingFile_withOverlay() {
+  test_getResource_file_existing_withOverlay() {
     String path = _file(exists: true, withOverlay: true).path;
     Resource resource = provider.getResource(path);
     expect(resource, _isFile);
   }
 
-  test_getResource_existingFolder() {
-    String path = _folder(exists: true).path;
-    Resource resource = provider.getResource(path);
-    expect(resource, _isFolder);
-  }
-
-  test_getResource_notExisting_withoutOverlay() {
+  test_getResource_file_notExisting_withoutOverlay() {
     String path = _file(exists: false).path;
     Resource resource = provider.getResource(path);
     expect(resource, _isFile);
   }
 
-  test_getResource_notExisting_withOverlay() {
+  test_getResource_file_notExisting_withOverlay() {
     String path = _file(exists: false, withOverlay: true).path;
     Resource resource = provider.getResource(path);
     expect(resource, _isFile);
   }
 
+  test_getResource_folder_existing() {
+    String path = _folder(exists: true).path;
+    Resource resource = provider.getResource(path);
+    expect(resource, _isFolder);
+  }
+
+  test_getResource_folder_nonExisting_withOverlay() {
+    String filePath = _file(exists: false, withOverlay: true).path;
+    String folderPath = provider.pathContext.dirname(filePath);
+    Resource resource = provider.getResource(folderPath);
+    expect(resource, _isFolder);
+  }
+
   test_getStateLocation_uniqueness() {
     String idOne = 'one';
     Folder folderOne = provider.getStateLocation(idOne);
@@ -763,7 +794,8 @@
       {@required bool exists,
       String content,
       String path,
-      bool withOverlay = false}) {
+      bool withOverlay = false,
+      String overlayContent = 'bbb'}) {
     if (path == null) {
       path = defaultFilePath;
     } else {
@@ -773,7 +805,7 @@
       baseProvider.newFile(path, content ?? 'a');
     }
     if (withOverlay) {
-      provider.setOverlay(path, content: 'bbb', modificationStamp: 42);
+      provider.setOverlay(path, content: overlayContent, modificationStamp: 42);
     }
     return provider.getFile(path);
   }
diff --git a/pkg/analyzer/test/generated/analysis_context_factory.dart b/pkg/analyzer/test/generated/analysis_context_factory.dart
index e2aef27..b7ae647 100644
--- a/pkg/analyzer/test/generated/analysis_context_factory.dart
+++ b/pkg/analyzer/test/generated/analysis_context_factory.dart
@@ -4,6 +4,7 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -47,7 +48,8 @@
       {UriResolver contributedResolver,
       MemoryResourceProvider resourceProvider}) {
     AnalysisContextForTests context = new AnalysisContextForTests();
-    return initContextWithCore(context, contributedResolver, resourceProvider);
+    return initContextWithCore(context, FeatureSet.forTesting(),
+        contributedResolver, resourceProvider);
   }
 
   /**
@@ -60,7 +62,8 @@
       {MemoryResourceProvider resourceProvider}) {
     AnalysisContextForTests context = new AnalysisContextForTests();
     context._internalSetAnalysisOptions(options);
-    return initContextWithCore(context, null, resourceProvider);
+    return initContextWithCore(
+        context, options.contextFeatures, null, resourceProvider);
   }
 
   /**
@@ -73,8 +76,8 @@
       Map<String, String> packages,
       {MemoryResourceProvider resourceProvider}) {
     AnalysisContextForTests context = new AnalysisContextForTests();
-    return initContextWithCore(
-        context, new TestPackageUriResolver(packages), resourceProvider);
+    return initContextWithCore(context, FeatureSet.forTesting(),
+        new TestPackageUriResolver(packages), resourceProvider);
   }
 
   /**
@@ -84,7 +87,7 @@
    * be used when accessing the file system.
    */
   static InternalAnalysisContext initContextWithCore(
-      InternalAnalysisContext context,
+      InternalAnalysisContext context, FeatureSet featureSet,
       [UriResolver contributedResolver,
       MemoryResourceProvider resourceProvider]) {
     DartSdk sdk = new _AnalysisContextFactory_initContextWithCore(
@@ -174,7 +177,10 @@
       proxyTopLevelVariableElt
     ];
     LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
-        coreContext, null, AstTestFactory.libraryIdentifier2(["dart", "core"]));
+        coreContext,
+        null,
+        AstTestFactory.libraryIdentifier2(["dart", "core"]),
+        featureSet.isEnabled(Feature.non_nullable));
     coreLibrary.definingCompilationUnit = coreUnit;
     //
     // dart:async
@@ -182,7 +188,8 @@
     LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
         coreContext,
         null,
-        AstTestFactory.libraryIdentifier2(["dart", "async"]));
+        AstTestFactory.libraryIdentifier2(["dart", "async"]),
+        featureSet.isEnabled(Feature.non_nullable));
     CompilationUnitElementImpl asyncUnit = new CompilationUnitElementImpl();
     Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
     asyncUnit.librarySource = asyncUnit.source = asyncSource;
@@ -238,7 +245,7 @@
     // Stream
     ClassElementImpl streamElement =
         ElementFactory.classElement2("Stream", ["T"]);
-    streamElement.abstract = true;
+    streamElement.isAbstract = true;
     streamElement.constructors = <ConstructorElement>[
       ElementFactory.constructorElement2(streamElement, null)
     ];
@@ -329,8 +336,11 @@
             "document", false, true, htmlDocumentElement.type);
     htmlUnit.topLevelVariables = <TopLevelVariableElement>[document];
     htmlUnit.accessors = <PropertyAccessorElement>[document.getter];
-    LibraryElementImpl htmlLibrary = new LibraryElementImpl.forNode(coreContext,
-        null, AstTestFactory.libraryIdentifier2(["dart", "dom", "html"]));
+    LibraryElementImpl htmlLibrary = new LibraryElementImpl.forNode(
+        coreContext,
+        null,
+        AstTestFactory.libraryIdentifier2(["dart", "dom", "html"]),
+        featureSet.isEnabled(Feature.non_nullable));
     htmlLibrary.definingCompilationUnit = htmlUnit;
     //
     // dart:math
@@ -355,7 +365,7 @@
     TopLevelVariableElement piElement = ElementFactory.topLevelVariableElement3(
         "PI", true, false, provider.doubleType);
     ClassElementImpl randomElement = ElementFactory.classElement2("Random");
-    randomElement.abstract = true;
+    randomElement.isAbstract = true;
     ConstructorElementImpl randomConstructor =
         ElementFactory.constructorElement2(randomElement, null);
     randomConstructor.factory = true;
@@ -390,7 +400,10 @@
     ];
     mathUnit.types = <ClassElement>[randomElement];
     LibraryElementImpl mathLibrary = new LibraryElementImpl.forNode(
-        coreContext, null, AstTestFactory.libraryIdentifier2(["dart", "math"]));
+        coreContext,
+        null,
+        AstTestFactory.libraryIdentifier2(["dart", "math"]),
+        featureSet.isEnabled(Feature.non_nullable));
     mathLibrary.definingCompilationUnit = mathUnit;
     //
     // Record the elements.
diff --git a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
index 46f7960..f92a108 100644
--- a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
@@ -16,12 +16,14 @@
 @reflectiveTest
 class CheckedModeCompileTimeErrorCodeTest extends DriverResolutionTest {
   test_assertion_throws() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(int x, int y) : assert(x < y);
 }
 var v = const A(3, 2);
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 61, 13),
+    ]);
   }
 
   test_fieldFormalParameterAssignableToField_extends() async {
@@ -46,13 +48,15 @@
   test_fieldFormalParameterAssignableToField_fieldType_unresolved_null() async {
     // Null always passes runtime type checks, even when the type is
     // unresolved.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final Unresolved x;
   const A(String this.x);
 }
 var v = const A(null);
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 18, 10),
+    ]);
   }
 
   test_fieldFormalParameterAssignableToField_implements() async {
@@ -151,7 +155,7 @@
   test_fieldFormalParameterAssignableToField_typedef() async {
     // foo has the runtime type dynamic -> dynamic, so it is not assignable
     // to A.f.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 typedef String Int2String(int x);
 class A {
   final Int2String f;
@@ -159,7 +163,9 @@
 }
 foo(x) => 1;
 var v = const A(foo);
-''', [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 116, 3),
+    ]);
   }
 
   test_fieldFormalParameterAssignableToField_typeSubstitution() async {
@@ -175,15 +181,18 @@
   }
 
   test_fieldFormalParameterNotAssignableToField() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final int x;
   const A(this.x);
 }
 var v = const A('foo');
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          62,
+          5),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 62, 5),
     ]);
   }
 
@@ -191,7 +200,7 @@
     // According to checked-mode type checking rules, a value of type A is not
     // assignable to a field of type B, because B extends A (the subtyping
     // relationship is in the wrong direction).
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A();
 }
@@ -204,32 +213,39 @@
 }
 const A u = const A();
 var v = const C(u);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          143,
+          1),
+    ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_fieldType() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final int x;
   const A(this.x);
 }
 var v = const A('foo');
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          62,
+          5),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 62, 5),
     ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_fieldType_unresolved() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final Unresolved x;
   const A(String this.x);
 }
 var v = const A('foo');
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.UNDEFINED_CLASS
+      error(StaticWarningCode.UNDEFINED_CLASS, 18, 10),
     ]);
   }
 
@@ -237,7 +253,7 @@
     // According to checked-mode type checking rules, a value of type A is not
     // assignable to a field of type B, because B implements A (the subtyping
     // relationship is in the wrong direction).
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A();
 }
@@ -248,61 +264,84 @@
 }
 const A u = const A();
 var v = const C(u);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          132,
+          1),
+    ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_list() async {
     // <num>[1, 2, 3] has type List<num>, which is not a subtype of List<int>.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(List<int> x);
 }
 const dynamic w = const <num>[1, 2, 3];
 var x = const A(w);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          92,
+          1),
+    ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_map_keyMismatch() async {
     // <num, int>{1: 2} has type Map<num, int>, which is not a subtype of
     // Map<int, int>.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(Map<int, int> x);
 }
 const dynamic w = const <num, int>{1: 2};
 var x = const A(w);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          98,
+          1),
+    ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_map_valueMismatch() async {
     // <int, num>{1: 2} has type Map<int, num>, which is not a subtype of
     // Map<int, int>.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(Map<int, int> x);
 }
 const dynamic w = const <int, num>{1: 2};
 var x = const A(w);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          98,
+          1),
+    ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_optional() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final int x;
   const A([this.x = 'foo']);
 }
 var v = const A();
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticTypeWarningCode.INVALID_ASSIGNMENT
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 45, 5),
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          64,
+          9),
     ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_typedef() async {
     // foo has the runtime type String -> int, so it should not be assignable
     // to A.f (A.f requires it to be int -> String).
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 typedef String Int2String(int x);
 class A {
   final Int2String f;
@@ -311,35 +350,47 @@
 int foo(String x) => 1;
 var v = const A(foo);
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 127, 3),
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          127,
+          3),
     ]);
   }
 
   test_fieldInitializerNotAssignable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final int x;
   const A() : x = '';
 }
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE,
-      StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE
+      error(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, 43, 2),
+      error(
+          CheckedModeCompileTimeErrorCode
+              .CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE,
+          43,
+          2),
     ]);
   }
 
   test_fieldTypeMismatch() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(x) : y = x;
   final int y;
 }
 var v = const A('foo');
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+          57,
+          14),
+    ]);
   }
 
   test_fieldTypeMismatch_generic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
       r'''
 class C<T> {
   final T x = y;
@@ -349,27 +400,30 @@
 var v = const C<String>();
 ''',
       [
-        CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
-        StaticTypeWarningCode.INVALID_ASSIGNMENT
+        error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 27, 1),
+        error(
+            CheckedModeCompileTimeErrorCode
+                .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+            70,
+            17),
       ],
     );
   }
 
   test_fieldTypeMismatch_unresolved() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(x) : y = x;
   final Unresolved y;
 }
 var v = const A('foo');
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
-      StaticWarningCode.UNDEFINED_CLASS
+      error(StaticWarningCode.UNDEFINED_CLASS, 40, 10),
     ]);
   }
 
   test_fieldTypeOk_generic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
       r'''
 class C<T> {
   final T x = y;
@@ -378,7 +432,9 @@
 const int y = 1;
 var v = const C<int>();
 ''',
-      [StaticTypeWarningCode.INVALID_ASSIGNMENT],
+      [
+        error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 27, 1),
+      ],
     );
   }
 
@@ -395,40 +451,50 @@
   test_fieldTypeOk_unresolved_null() async {
     // Null always passes runtime type checks, even when the type is
     // unresolved.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(x) : y = x;
   final Unresolved y;
 }
 var v = const A(null);
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 40, 10),
+    ]);
   }
 
   test_listElementTypeNotAssignable() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <String> [42];
-''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 24, 2),
+    ]);
   }
 
   test_listLiteral_inferredElementType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const Object x = [1];
 const List<String> y = x;
-''', [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+''', [
+      error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 41, 1),
+    ]);
   }
 
   test_mapLiteral_inferredKeyType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const Object x = {1: 1};
 const Map<String, dynamic> y = x;
-''', [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+''', [
+      error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 52, 1),
+    ]);
   }
 
   test_mapLiteral_inferredValueType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const Object x = {1: 1};
 const Map<dynamic, String> y = x;
-''', [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+''', [
+      error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 52, 1),
+    ]);
   }
 
   test_parameterAssignable_null() async {
@@ -451,62 +517,71 @@
   test_parameterAssignable_undefined_null() async {
     // Null always passes runtime type checks, even when the type is
     // unresolved.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(Unresolved x);
 }
 var v = const A(null);
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 20, 10),
+    ]);
   }
 
   test_parameterNotAssignable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(int x);
 }
 var v = const A('foo');
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          46,
+          5),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 46, 5),
     ]);
   }
 
   test_parameterNotAssignable_typeSubstitution() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<T> {
   const A(T x);
 }
 var v = const A<int>('foo');
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 52, 5),
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          52,
+          5),
     ]);
   }
 
   test_parameterNotAssignable_undefined() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(Unresolved x);
 }
 var v = const A('foo');
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.UNDEFINED_CLASS
+      error(StaticWarningCode.UNDEFINED_CLASS, 20, 10),
     ]);
   }
 
   test_redirectingConstructor_paramTypeMismatch() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A.a1(x) : this.a2(x);
   const A.a2(String x);
 }
 var v = const A.a1(0);
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 74, 13),
+    ]);
   }
 
   test_superConstructor_paramTypeMismatch() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class C {
   final double d;
   const C(this.d);
@@ -515,7 +590,9 @@
   const D(d) : super(d);
 }
 const f = const D('0.0');
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 106, 14),
+    ]);
   }
 
   test_topLevelVarAssignable_null() async {
@@ -527,26 +604,27 @@
   test_topLevelVarAssignable_undefined_null() async {
     // Null always passes runtime type checks, even when the type is
     // unresolved.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const Unresolved x = null;
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 6, 10),
+    ]);
   }
 
   test_topLevelVarNotAssignable() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const int x = 'foo';
 ''', [
-      CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
-      StaticTypeWarningCode.INVALID_ASSIGNMENT
+      error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 10, 1),
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 14, 5),
     ]);
   }
 
   test_topLevelVarNotAssignable_undefined() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const Unresolved x = 'foo';
 ''', [
-      CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
-      StaticWarningCode.UNDEFINED_CLASS
+      error(StaticWarningCode.UNDEFINED_CLASS, 6, 10),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index 2daae3d..e1db296 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -6,15 +6,17 @@
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
-import 'package:analyzer/src/generated/source_io.dart';
 import 'package:test/test.dart' show expect;
+import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'resolver_test_case.dart';
+import '../src/dart/resolution/driver_resolution.dart';
+import 'test_support.dart';
 
-class CompileTimeErrorCodeTestBase extends ResolverTestCase {
+class CompileTimeErrorCodeTestBase extends DriverResolutionTest {
   disabled_test_conflictingGenericInterfaces_hierarchyLoop_infinite() async {
     // There is an interface conflict here due to a loop in the class
     // hierarchy leading to an infinite set of implemented types; this loop
@@ -25,7 +27,9 @@
     await assertErrorsInCode('''
 class A<T> implements B<List<T>> {}
 class B<T> implements A<List<T>> {}
-''', [CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 0, 0),
+    ]);
   }
 
   test_accessPrivateEnumField() async {
@@ -34,15 +38,17 @@
 String name(E e) {
   return e._name;
 }
-''', [CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD], verify: false);
+''', [
+      error(CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD, 45, 5),
+    ]);
   }
 
   test_ambiguousExport() async {
-    newFile("/lib1.dart", content: r'''
+    newFile("/test/lib/lib1.dart", content: r'''
 library lib1;
 class N {}
 ''');
-    newFile("/lib2.dart", content: r'''
+    newFile("/test/lib/lib2.dart", content: r'''
 library lib2;
 class N {}
 ''');
@@ -50,7 +56,9 @@
 library L;
 export 'lib1.dart';
 export 'lib2.dart';
-''', [CompileTimeErrorCode.AMBIGUOUS_EXPORT]);
+''', [
+      error(CompileTimeErrorCode.AMBIGUOUS_EXPORT, 31, 19),
+    ]);
   }
 
   test_annotationWithNotClass() async {
@@ -65,11 +73,13 @@
 @property(123)
 main() {
 }
-''', [CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS, 117, 8),
+    ]);
   }
 
   test_annotationWithNotClass_prefixed() async {
-    newFile("/annotations.dart", content: r'''
+    newFile("/test/lib/annotations.dart", content: r'''
 class Property {
   final int value;
   const Property(this.value);
@@ -82,7 +92,9 @@
 @pref.property(123)
 main() {
 }
-''', [CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS, 36, 13),
+    ]);
   }
 
   test_asyncForInWrongContext() async {
@@ -91,7 +103,10 @@
   await for (var e in list) {
   }
 }
-''', [CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 27, 1),
+      error(CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT, 29, 2),
+    ]);
   }
 
   test_awaitInWrongContext_sync() async {
@@ -102,7 +117,9 @@
 f(x) {
   return await x;
 }
-''', [CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT]);
+''', [
+      error(CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, 16, 5),
+    ]);
   }
 
   test_awaitInWrongContext_syncStar() async {
@@ -113,7 +130,9 @@
 f(x) sync* {
   yield await x;
 }
-''', [CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT]);
+''', [
+      error(CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, 21, 5),
+    ]);
   }
 
   test_bug_23176() async {
@@ -125,9 +144,9 @@
   dynamic @A(const A()) x;
 }
 ''', [
-      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
-      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
-      ParserErrorCode.EXPECTED_TOKEN
+      error(ParserErrorCode.EXPECTED_TOKEN, 40, 7),
+      error(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 40, 7),
+      error(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 62, 1),
     ]);
   }
 
@@ -136,15 +155,17 @@
 class A {}
 class B {}
 class as = A with B;
-''', [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME]);
+''', [
+      error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME, 28, 2),
+    ]);
   }
 
   test_builtInIdentifierAsPrefixName() async {
     await assertErrorsInCode('''
 import 'dart:async' as abstract;
 ''', [
-      CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_PREFIX_NAME,
-      HintCode.UNUSED_IMPORT
+      error(HintCode.UNUSED_IMPORT, 7, 12),
+      error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_PREFIX_NAME, 23, 8),
     ]);
   }
 
@@ -153,7 +174,9 @@
 import 'dart:core' as core;
 
 dynamic x;
-''', [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
+''', [
+      error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 29, 7),
+    ]);
   }
 
   test_builtInIdentifierAsType_formalParameter_field() async {
@@ -162,14 +185,18 @@
   var x;
   A(static this.x);
 }
-''', [ParserErrorCode.EXTRANEOUS_MODIFIER]);
+''', [
+      error(ParserErrorCode.EXTRANEOUS_MODIFIER, 23, 6),
+    ]);
   }
 
   test_builtInIdentifierAsType_formalParameter_simple() async {
     await assertErrorsInCode(r'''
 f(static x) {
 }
-''', [ParserErrorCode.EXTRANEOUS_MODIFIER]);
+''', [
+      error(ParserErrorCode.EXTRANEOUS_MODIFIER, 2, 6),
+    ]);
   }
 
   test_builtInIdentifierAsType_variableDeclaration() async {
@@ -178,28 +205,35 @@
   typedef x;
 }
 ''', [
-      StaticWarningCode.UNDEFINED_IDENTIFIER,
-      StaticWarningCode.UNDEFINED_IDENTIFIER,
-      ParserErrorCode.EXPECTED_TOKEN
+      error(ParserErrorCode.EXPECTED_TOKEN, 8, 7),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 8, 7),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 16, 1),
     ]);
   }
 
   test_builtInIdentifierAsTypedefName_functionTypeAlias() async {
     await assertErrorsInCode('''
 typedef bool as();
-''', [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME]);
+''', [
+      error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME, 13, 2),
+    ]);
   }
 
   test_builtInIdentifierAsTypeName() async {
     await assertErrorsInCode('''
 class as {}
-''', [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME]);
+''', [
+      error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME, 6, 2),
+    ]);
   }
 
   test_builtInIdentifierAsTypeParameterName() async {
     await assertErrorsInCode('''
 class A<as> {}
-''', [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME]);
+''', [
+      error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME, 8,
+          2),
+    ]);
   }
 
   test_caseExpressionTypeImplementsEquals() async {
@@ -219,7 +253,10 @@
     default: return 0;
   }
 }
-''', [CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+''', [
+      error(
+          CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, 194, 6),
+    ]);
   }
 
   test_conflictingGenericInterfaces_hierarchyLoop() async {
@@ -230,8 +267,8 @@
 class A<T> implements B<T> {}
 class B<T> implements A<T> {}
 ''', [
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 36, 1),
     ]);
   }
 
@@ -248,7 +285,9 @@
     await assertErrorsInCode(r'''
 class T<T> {
 }
-''', [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS, 8, 1),
+    ]);
   }
 
   test_conflictingTypeVariableAndMember_field() async {
@@ -256,7 +295,9 @@
 class A<T> {
   var T;
 }
-''', [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, 8, 1),
+    ]);
   }
 
   test_conflictingTypeVariableAndMember_getter() async {
@@ -264,7 +305,9 @@
 class A<T> {
   get T => null;
 }
-''', [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, 8, 1),
+    ]);
   }
 
   test_conflictingTypeVariableAndMember_method() async {
@@ -272,7 +315,9 @@
 class A<T> {
   T() {}
 }
-''', [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, 8, 1),
+    ]);
   }
 
   test_conflictingTypeVariableAndMember_method_static() async {
@@ -280,7 +325,9 @@
 class A<T> {
   static T() {}
 }
-''', [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, 8, 1),
+    ]);
   }
 
   test_conflictingTypeVariableAndMember_setter() async {
@@ -288,7 +335,9 @@
 class A<T> {
   set T(x) {}
 }
-''', [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, 8, 1),
+    ]);
   }
 
   test_consistentCaseExpressionTypes_dynamic() async {
@@ -315,7 +364,7 @@
   }
 
   test_const_invalid_constructorFieldInitializer_fromLibrary() async {
-    newFile('/lib.dart', content: r'''
+    newFile('/test/lib/lib.dart', content: r'''
 class A<T> {
   final int f;
   const A() : f = T.foo;
@@ -324,7 +373,9 @@
     await assertErrorsInCode(r'''
 import 'lib.dart';
 const a = const A();
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 29, 9),
+    ]);
   }
 
   test_constConstructor_redirect_generic() async {
@@ -353,9 +404,13 @@
   return 3;
 }
 ''', [
-      CompileTimeErrorCode
-          .CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST,
-      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 26,
+          3),
+      error(
+          CompileTimeErrorCode
+              .CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST,
+          33,
+          10),
     ]);
   }
 
@@ -379,7 +434,9 @@
 class B extends A {
   const B(): super();
 }
-''', [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER]);
+''', [
+      error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, 52, 7),
+    ]);
   }
 
   test_constConstructorWithNonConstSuper_implicit() async {
@@ -390,7 +447,9 @@
 class B extends A {
   const B();
 }
-''', [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER]);
+''', [
+      error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, 47, 1),
+    ]);
   }
 
   test_constConstructorWithNonFinalField_mixin() async {
@@ -402,8 +461,10 @@
   const B();
 }
 ''', [
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
+      error(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 55, 10),
+      error(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 61, 1),
     ]);
   }
 
@@ -416,8 +477,9 @@
   const B();
 }
 ''', [
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER
+      error(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 43, 10),
+      error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, 49, 1),
     ]);
   }
 
@@ -427,44 +489,43 @@
   int x;
   const A();
 }
-''', [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD]);
+''', [
+      error(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 21, 10),
+    ]);
   }
 
   test_constDeferredClass() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 class A {
   const A();
 }
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 main() {
   const a.A();
 }
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.CONST_DEFERRED_CLASS
+''', [
+      error(CompileTimeErrorCode.CONST_DEFERRED_CLASS, 65, 3),
     ]);
   }
 
   test_constDeferredClass_namedConstructor() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 class A {
   const A.b();
-}''',
-      r'''
+}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 main() {
   const a.A.b();
-}'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.CONST_DEFERRED_CLASS
+}''', [
+      error(CompileTimeErrorCode.CONST_DEFERRED_CLASS, 65, 5),
     ]);
   }
 
@@ -474,7 +535,10 @@
   const A();
 }
 const a = new A();
-''', [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
+''', [
+      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 35,
+          7),
+    ]);
   }
 
   test_constEval_newInstance_externalFactoryConstConstructor() async {
@@ -496,7 +560,10 @@
 }
 
 const x = const C().t;
-''', [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
+''', [
+      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 58,
+          11),
+    ]);
   }
 
   test_constEval_propertyExtraction_targetNotConst() async {
@@ -507,7 +574,10 @@
 }
 final a = const A();
 const C = a.m;
-''', [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
+''', [
+      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 72,
+          1),
+    ]);
   }
 
   test_constEvalThrowsException() async {
@@ -516,7 +586,9 @@
   const C();
 }
 f() { return const C(); }
-''', [CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION]);
+''', [
+      error(CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION, 0, 0),
+    ]);
   }
 
   test_constEvalThrowsException_binaryMinus_null() async {
@@ -532,7 +604,9 @@
   test_constEvalThrowsException_divisionByZero() async {
     await assertErrorsInCode('''
 const C = 1 ~/ 0;
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE, 10, 6),
+    ]);
   }
 
   test_constEvalThrowsException_finalAlreadySet_initializer() async {
@@ -547,8 +621,9 @@
 }
 var x = const C();
 ''', [
-      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
-      StaticWarningCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION
+      error(StaticWarningCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION,
+          39, 1),
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 56, 9),
     ]);
   }
 
@@ -565,50 +640,62 @@
 }
 var x = const C(2);
 ''', [
-      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
-      StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR
+      error(StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR,
+          40, 1),
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 54, 10),
     ]);
   }
 
   test_constEvalThrowsException_unaryBitNot_null() async {
     await assertErrorsInCode('''
 const C = ~null;
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION], verify: false);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 10, 5),
+    ]);
   }
 
   test_constEvalThrowsException_unaryNegated_null() async {
     await assertErrorsInCode('''
 const C = -null;
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION], verify: false);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 10, 5),
+    ]);
   }
 
   test_constEvalThrowsException_unaryNot_null() async {
     await assertErrorsInCode('''
 const C = !null;
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 10, 5),
+    ]);
   }
 
   test_constEvalTypeBool_binary_and() async {
     await assertErrorsInCode('''
 const _ = true && '';
 ''', [
-      CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL,
-      StaticTypeWarningCode.NON_BOOL_OPERAND,
+      error(HintCode.UNUSED_ELEMENT, 6, 1),
+      error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, 10, 10),
+      error(StaticTypeWarningCode.NON_BOOL_OPERAND, 18, 2),
     ]);
   }
 
   test_constEvalTypeBool_binary_leftTrue() async {
     await assertErrorsInCode('''
 const C = (true || 0);
-''', [StaticTypeWarningCode.NON_BOOL_OPERAND, HintCode.DEAD_CODE]);
+''', [
+      error(HintCode.DEAD_CODE, 19, 1),
+      error(StaticTypeWarningCode.NON_BOOL_OPERAND, 19, 1),
+    ]);
   }
 
   test_constEvalTypeBool_binary_or() async {
     await assertErrorsInCode(r'''
 const _ = false || '';
 ''', [
-      CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL,
-      StaticTypeWarningCode.NON_BOOL_OPERAND,
+      error(HintCode.UNUSED_ELEMENT, 6, 1),
+      error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, 10, 11),
+      error(StaticTypeWarningCode.NON_BOOL_OPERAND, 19, 2),
     ]);
   }
 
@@ -634,7 +721,11 @@
 ''',
         IsEnabledByDefault.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING]);
+            : [
+                error(HintCode.UNUSED_ELEMENT, 49, 1),
+                error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING, 53,
+                    14),
+              ]);
   }
 
   test_constEvalTypeBoolNumString_notEqual() async {
@@ -645,7 +736,10 @@
 
 const num a = 0;
 const _ = a != const A();
-''', [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 49, 1),
+      error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING, 53, 14),
+    ]);
   }
 
   test_constEvalTypeInt_binary() async {
@@ -676,8 +770,8 @@
   A(const this.x) {}
 }
 ''', [
-      CompileTimeErrorCode.CONST_FORMAL_PARAMETER,
-      ParserErrorCode.EXTRANEOUS_MODIFIER
+      error(CompileTimeErrorCode.CONST_FORMAL_PARAMETER, 23, 12),
+      error(ParserErrorCode.EXTRANEOUS_MODIFIER, 23, 5),
     ]);
   }
 
@@ -685,8 +779,8 @@
     await assertErrorsInCode('''
 f(const x) {}
 ''', [
-      CompileTimeErrorCode.CONST_FORMAL_PARAMETER,
-      ParserErrorCode.EXTRANEOUS_MODIFIER
+      error(CompileTimeErrorCode.CONST_FORMAL_PARAMETER, 2, 7),
+      error(ParserErrorCode.EXTRANEOUS_MODIFIER, 2, 5),
     ]);
   }
 
@@ -695,7 +789,11 @@
 f(p) {
   const C = p;
 }
-''', [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
+      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 19,
+          1),
+    ]);
   }
 
   test_constInitializedWithNonConstValue_finalField() async {
@@ -706,7 +804,9 @@
   final field = 0;
   foo([int x = field]) {}
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 46, 5),
+    ]);
   }
 
   test_constInitializedWithNonConstValue_missingConstInListLiteral() async {
@@ -722,36 +822,38 @@
   }
 
   test_constInitializedWithNonConstValueFromDeferredClass() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 const V = 1;
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 const B = a.V;
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode
-          .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY
+''', [
+      error(
+          CompileTimeErrorCode
+              .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY,
+          58,
+          3),
     ]);
   }
 
   test_constInitializedWithNonConstValueFromDeferredClass_nested() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 const V = 1;
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 const B = a.V + 1;
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode
-          .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY
+''', [
+      error(
+          CompileTimeErrorCode
+              .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY,
+          58,
+          7),
     ]);
   }
 
@@ -760,7 +862,9 @@
 class C {
   const int f = 0;
 }
-''', [CompileTimeErrorCode.CONST_INSTANCE_FIELD]);
+''', [
+      error(CompileTimeErrorCode.CONST_INSTANCE_FIELD, 12, 5),
+    ]);
   }
 
   test_constWithInvalidTypeParameters() async {
@@ -769,7 +873,9 @@
   const A();
 }
 f() { return const A<A>(); }
-''', [CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS]);
+''', [
+      error(CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS, 44, 4),
+    ]);
   }
 
   test_constWithInvalidTypeParameters_tooFew() async {
@@ -781,7 +887,9 @@
 f(p) {
   return const C<A>();
 }
-''', [CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS]);
+''', [
+      error(CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS, 64, 4),
+    ]);
   }
 
   test_constWithInvalidTypeParameters_tooMany() async {
@@ -793,7 +901,9 @@
 f(p) {
   return const C<A, A>();
 }
-''', [CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS]);
+''', [
+      error(CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS, 61, 7),
+    ]);
   }
 
   test_constWithNonConst() async {
@@ -802,7 +912,9 @@
   T(a, b, {c, d}) {}
 }
 f() { return const T(0, 1, c: 2, d: 3); }
-''', [CompileTimeErrorCode.CONST_WITH_NON_CONST]);
+''', [
+      error(CompileTimeErrorCode.CONST_WITH_NON_CONST, 46, 25),
+    ]);
   }
 
   test_constWithNonConst_in_const_context() async {
@@ -815,7 +927,9 @@
 main() {
   const A(B());
 }
-''', [CompileTimeErrorCode.CONST_WITH_NON_CONST]);
+''', [
+      error(CompileTimeErrorCode.CONST_WITH_NON_CONST, 57, 3),
+    ]);
   }
 
   test_constWithNonConstantArgument_annotation() async {
@@ -827,7 +941,9 @@
 @A(v)
 main() {
 }
-''', [CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT]);
+''', [
+      error(CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT, 45, 1),
+    ]);
   }
 
   test_constWithNonConstantArgument_instanceCreation() async {
@@ -837,7 +953,7 @@
 }
 f(p) { return const A(p); }
 ''', [
-      CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT,
+      error(CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT, 48, 1),
     ]);
   }
 
@@ -847,21 +963,21 @@
 f() {
   return const A();
 }
-''', [CompileTimeErrorCode.CONST_WITH_NON_TYPE]);
+''', [
+      error(CompileTimeErrorCode.CONST_WITH_NON_TYPE, 28, 1),
+    ]);
   }
 
   test_constWithNonType_fromLibrary() async {
-    Source source1 = addNamedSource("/lib.dart", '');
-    Source source2 = addNamedSource("/lib2.dart", r'''
-import 'lib.dart' as lib;
+    newFile('/test/lib/lib1.dart');
+    await assertErrorsInCode('''
+import 'lib1.dart' as lib;
 void f() {
   const lib.A();
 }
-''');
-    await computeAnalysisResult(source1);
-    await computeAnalysisResult(source2);
-    assertErrors(source2, [CompileTimeErrorCode.CONST_WITH_NON_TYPE]);
-    verify([source1]);
+''', [
+      error(CompileTimeErrorCode.CONST_WITH_NON_TYPE, 50, 1),
+    ]);
   }
 
   test_constWithTypeParameters_direct() async {
@@ -871,8 +987,8 @@
   const A();
 }
 ''', [
-      CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS,
-      StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 40, 1),
+      error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS, 40, 1),
     ]);
   }
 
@@ -883,8 +999,8 @@
   const A();
 }
 ''', [
-      CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS,
-      StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC
+      error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS, 45, 1),
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 45, 1),
     ]);
   }
 
@@ -896,7 +1012,9 @@
 f() {
   return const A.noSuchConstructor();
 }
-''', [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR], verify: false);
+''', [
+      error(CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR, 48, 17),
+    ]);
   }
 
   test_constWithUndefinedConstructorDefault() async {
@@ -907,14 +1025,17 @@
 f() {
   return const A();
 }
-''', [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT]);
+''', [
+      error(
+          CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, 51, 1),
+    ]);
   }
 
   test_defaultValueInFunctionTypeAlias_new_named() async {
     await assertErrorsInCode('''
 typedef F = int Function({Map<String, String> m: const {}});
 ''', [
-      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
+      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 47, 1),
     ]);
   }
 
@@ -922,7 +1043,7 @@
     await assertErrorsInCode('''
 typedef F = int Function([Map<String, String> m = const {}]);
 ''', [
-      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
+      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 48, 1),
     ]);
   }
 
@@ -930,8 +1051,8 @@
     await assertErrorsInCode('''
 typedef F([x = 0]);
 ''', [
-      CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS,
-      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
+      error(CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, 0, 19),
+      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 13, 1),
     ]);
   }
 
@@ -939,8 +1060,8 @@
     await assertErrorsInCode('''
 typedef F([x = 0]);
 ''', [
-      CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS,
-      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
+      error(CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, 0, 19),
+      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 13, 1),
     ]);
   }
 
@@ -948,8 +1069,9 @@
     await assertErrorsInCode('''
 f(g({p: null})) {}
 ''', [
-      CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER,
-      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
+      error(
+          CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER, 5, 7),
+      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 6, 1),
     ]);
   }
 
@@ -957,8 +1079,9 @@
     await assertErrorsInCode('''
 f(g([p = null])) {}
 ''', [
-      CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER,
-      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
+      error(
+          CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER, 5, 8),
+      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 7, 1),
     ]);
   }
 
@@ -971,7 +1094,12 @@
 class B implements A {
   B([int x = 1]) {}
 }
-''', [CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR]);
+''', [
+      error(
+          CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR,
+          27,
+          1),
+    ]);
   }
 
   test_deferredImportWithInvalidUri() async {
@@ -980,56 +1108,60 @@
 main() {
   p.loadLibrary();
 }
-''', [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+''', [
+      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 15),
+    ]);
   }
 
   test_duplicateDefinition_acrossLibraries() async {
-    Source librarySource = addNamedSource("/lib.dart", r'''
+    var libFile = newFile('/test/lib/lib.dart', content: '''
 library lib;
 
 part 'a.dart';
-part 'b.dart';
+part 'test.dart';
 ''');
-    Source sourceA = addNamedSource("/a.dart", r'''
+    newFile('/test/lib/a.dart', content: '''
 part of lib;
 
 class A {}
 ''');
-    Source sourceB = addNamedSource("/b.dart", r'''
+    String partContent = '''
 part of lib;
 
 class A {}
-''');
-    await computeAnalysisResult(librarySource);
-    await computeAnalysisResult(sourceA);
-    await computeAnalysisResult(sourceB);
-    assertNoErrors(librarySource);
-    assertErrors(sourceB, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
-    verify([librarySource, sourceA, sourceB]);
+''';
+    newFile('/test/lib/test.dart', content: partContent);
+    await resolveFile(libFile.path);
+    await assertErrorsInCode(partContent, [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 20, 1),
+    ]);
   }
 
   test_duplicateDefinition_catch() async {
     await assertErrorsInCode(r'''
 main() {
   try {} catch (e, e) {}
-}''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+}''', [
+      error(HintCode.UNUSED_CATCH_STACK, 28, 1),
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 28, 1),
+    ]);
   }
 
   test_duplicateDefinition_inPart() async {
-    Source librarySource = addNamedSource("/lib.dart", r'''
+    var libFile = newFile('/test/lib/lib1.dart', content: '''
 library test;
-part 'a.dart';
+part 'test.dart';
 class A {}
 ''');
-    Source sourceA = addNamedSource("/a.dart", r'''
+    String partContent = '''
 part of test;
 class A {}
-''');
-    await computeAnalysisResult(librarySource);
-    await computeAnalysisResult(sourceA);
-    assertNoErrors(librarySource);
-    assertErrors(sourceA, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
-    verify([librarySource, sourceA]);
+''';
+    newFile('/test/lib/test.dart', content: partContent);
+    await resolveFile(libFile.path);
+    await assertErrorsInCode(partContent, [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 20, 1),
+    ]);
   }
 
   test_duplicateDefinition_locals_inCase() async {
@@ -1041,7 +1173,11 @@
       var a;
   }
 }
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 45, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 58, 1),
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 58, 1),
+    ]);
   }
 
   test_duplicateDefinition_locals_inFunctionBlock() async {
@@ -1050,7 +1186,11 @@
   int m = 0;
   m(a) {}
 }
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 24, 1),
+      error(HintCode.UNUSED_ELEMENT, 24, 1),
+    ]);
   }
 
   test_duplicateDefinition_locals_inIf() async {
@@ -1061,7 +1201,11 @@
     var a;
   }
 }
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 38, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 49, 1),
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 49, 1),
+    ]);
   }
 
   test_duplicateDefinition_locals_inMethodBlock() async {
@@ -1072,7 +1216,23 @@
     int a;
   }
 }
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 26, 1),
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 37, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 37, 1),
+    ]);
+  }
+
+  test_duplicateDefinition_notInDefiningUnit() async {
+    newFile('/test/lib/a.dart', content: '''
+part of test;
+class A {}
+''');
+    await assertNoErrorsInCode('''
+library test;
+part 'a.dart';
+class A {}
+''');
   }
 
   test_duplicateDefinition_parameters_inConstructor() async {
@@ -1081,13 +1241,17 @@
   int a;
   A(int a, this.a);
 }
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 35, 1),
+    ]);
   }
 
   test_duplicateDefinition_parameters_inFunctionTypeAlias() async {
     await assertErrorsInCode(r'''
 typedef F(int a, double a);
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 24, 1),
+    ]);
   }
 
   test_duplicateDefinition_parameters_inLocalFunction() async {
@@ -1096,7 +1260,10 @@
   f(int a, double a) {
   };
 }
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 11, 1),
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 27, 1),
+    ]);
   }
 
   test_duplicateDefinition_parameters_inMethod() async {
@@ -1105,19 +1272,25 @@
   m(int a, double a) {
   }
 }
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 28, 1),
+    ]);
   }
 
   test_duplicateDefinition_parameters_inTopLevelFunction() async {
     await assertErrorsInCode(r'''
 f(int a, double a) {}
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 16, 1),
+    ]);
   }
 
   test_duplicateDefinition_typeParameters() async {
     await assertErrorsInCode(r'''
 class A<T, T> {}
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 11, 1),
+    ]);
   }
 
   test_duplicateNamedArgument() async {
@@ -1126,73 +1299,79 @@
 main() {
   f(a: 1, a: 2);
 }
-''', [CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, 32, 1),
+    ]);
   }
 
   test_duplicatePart_sameSource() async {
-    newFile('/part.dart', content: 'part of lib;');
+    newFile('/test/lib/part.dart', content: 'part of lib;');
     await assertErrorsInCode(r'''
 library lib;
 part 'part.dart';
 part 'foo/../part.dart';
-''', [CompileTimeErrorCode.DUPLICATE_PART]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_PART, 36, 18),
+    ]);
   }
 
   test_duplicatePart_sameUri() async {
-    newFile('/part.dart', content: 'part of lib;');
+    newFile('/test/lib/part.dart', content: 'part of lib;');
     await assertErrorsInCode(r'''
 library lib;
 part 'part.dart';
 part 'part.dart';
-''', [CompileTimeErrorCode.DUPLICATE_PART]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_PART, 36, 11),
+    ]);
   }
 
   test_exportInternalLibrary() async {
     await assertErrorsInCode('''
 export 'dart:_interceptors';
-''', [CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY]);
+''', [
+      error(CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, 0, 28),
+    ]);
   }
 
   test_exportOfNonLibrary() async {
-    newFile("/lib1.dart", content: '''
+    newFile("/test/lib/lib1.dart", content: '''
 part of lib;
 ''');
     await assertErrorsInCode(r'''
 library L;
 export 'lib1.dart';
-''', [CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY]);
+''', [
+      error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 18, 11),
+    ]);
   }
 
   test_extendsDeferredClass() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 class A {}
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class B extends a.A {}
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS, 64, 3),
     ]);
   }
 
   test_extendsDeferredClass_classTypeAlias() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 class A {}
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class M {}
 class C = a.A with M;
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS, 69, 3),
     ]);
   }
 
@@ -1200,23 +1379,25 @@
     await assertErrorsInCode('''
 class A extends bool {}
 ''', [
-      CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
-      CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 4),
     ]);
   }
 
   test_extendsDisallowedClass_class_double() async {
     await assertErrorsInCode('''
 class A extends double {}
-''', [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 6),
+    ]);
   }
 
   test_extendsDisallowedClass_class_int() async {
     await assertErrorsInCode('''
 class A extends int {}
 ''', [
-      CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
-      CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 3),
     ]);
   }
 
@@ -1224,23 +1405,25 @@
     await assertErrorsInCode('''
 class A extends Null {}
 ''', [
-      CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
-      CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 4),
     ]);
   }
 
   test_extendsDisallowedClass_class_num() async {
     await assertErrorsInCode('''
 class A extends num {}
-''', [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 3),
+    ]);
   }
 
   test_extendsDisallowedClass_class_String() async {
     await assertErrorsInCode('''
 class A extends String {}
 ''', [
-      CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
-      CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 6, 1),
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 6),
     ]);
   }
 
@@ -1248,42 +1431,54 @@
     await assertErrorsInCode(r'''
 class M {}
 class C = bool with M;
-''', [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 4),
+    ]);
   }
 
   test_extendsDisallowedClass_classTypeAlias_double() async {
     await assertErrorsInCode(r'''
 class M {}
 class C = double with M;
-''', [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 6),
+    ]);
   }
 
   test_extendsDisallowedClass_classTypeAlias_int() async {
     await assertErrorsInCode(r'''
 class M {}
 class C = int with M;
-''', [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 3),
+    ]);
   }
 
   test_extendsDisallowedClass_classTypeAlias_Null() async {
     await assertErrorsInCode(r'''
 class M {}
 class C = Null with M;
-''', [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 4),
+    ]);
   }
 
   test_extendsDisallowedClass_classTypeAlias_num() async {
     await assertErrorsInCode(r'''
 class M {}
 class C = num with M;
-''', [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 3),
+    ]);
   }
 
   test_extendsDisallowedClass_classTypeAlias_String() async {
     await assertErrorsInCode(r'''
 class M {}
 class C = String with M;
-''', [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 21, 6),
+    ]);
   }
 
   test_extraPositionalArguments_const() async {
@@ -1294,7 +1489,9 @@
 main() {
   const A(0);
 }
-''', [CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS]);
+''', [
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 43, 3),
+    ]);
   }
 
   test_extraPositionalArguments_const_super() async {
@@ -1305,7 +1502,9 @@
 class B extends A {
   const B() : super(0);
 }
-''', [CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS]);
+''', [
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 64, 3),
+    ]);
   }
 
   test_extraPositionalArgumentsCouldBeNamed_const() async {
@@ -1316,7 +1515,10 @@
 main() {
   const A(0);
 }
-''', [CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED]);
+''', [
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 50,
+          3),
+    ]);
   }
 
   test_extraPositionalArgumentsCouldBeNamed_const_super() async {
@@ -1327,7 +1529,10 @@
 class B extends A {
   const B() : super(0);
 }
-''', [CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED]);
+''', [
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 71,
+          3),
+    ]);
   }
 
   test_fieldFormalParameter_assignedInInitializer() async {
@@ -1336,7 +1541,10 @@
   int x;
   A(this.x) : x = 3 {}
 }
-''', [CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER,
+          33, 1),
+    ]);
   }
 
   test_fieldInitializedByMultipleInitializers() async {
@@ -1345,7 +1553,10 @@
   int x;
   A() : x = 0, x = 1 {}
 }
-''', [CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, 34,
+          1),
+    ]);
   }
 
   test_fieldInitializedByMultipleInitializers_multipleInits() async {
@@ -1355,8 +1566,10 @@
   A() : x = 0, x = 1, x = 2 {}
 }
 ''', [
-      CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS,
-      CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS
+      error(CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, 34,
+          1),
+      error(CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, 41,
+          1),
     ]);
   }
 
@@ -1368,8 +1581,10 @@
   A() : x = 0, x = 1, y = 0, y = 1 {}
 }
 ''', [
-      CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS,
-      CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS
+      error(CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, 43,
+          1),
+      error(CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, 57,
+          1),
     ]);
   }
 
@@ -1379,7 +1594,10 @@
   int x;
   A(this.x) : x = 1 {}
 }
-''', [CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER,
+          33, 1),
+    ]);
   }
 
   test_fieldInitializerFactoryConstructor() async {
@@ -1388,7 +1606,9 @@
   int x;
   factory A(this.x) => null;
 }
-''', [CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR, 31, 6),
+    ]);
   }
 
   test_fieldInitializerOutsideConstructor() async {
@@ -1399,8 +1619,8 @@
   m(this.x) {}
 }
 ''', [
-      ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
-      CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
+      error(ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, 23, 4),
+      error(CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, 23, 6),
     ]);
   }
 
@@ -1410,7 +1630,9 @@
   int x;
   m([this.x]) {}
 }
-''', [CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, 24, 6),
+    ]);
   }
 
   test_fieldInitializerOutsideConstructor_inFunctionTypeParameter() async {
@@ -1419,7 +1641,9 @@
   int x;
   A(int p(this.x));
 }
-''', [CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, 29, 6),
+    ]);
   }
 
   test_fieldInitializerRedirectingConstructor_afterRedirection() async {
@@ -1429,7 +1653,10 @@
   A.named() {}
   A() : this.named(), x = 42;
 }
-''', [CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, 56,
+          6),
+    ]);
   }
 
   test_fieldInitializerRedirectingConstructor_beforeRedirection() async {
@@ -1439,7 +1666,10 @@
   A.named() {}
   A() : x = 42, this.named();
 }
-''', [CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, 42,
+          6),
+    ]);
   }
 
   test_fieldInitializingFormalRedirectingConstructor() async {
@@ -1449,7 +1679,10 @@
   A.named() {}
   A(this.x) : this.named();
 }
-''', [CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, 38,
+          6),
+    ]);
   }
 
   test_finalInitializedMultipleTimes_initializers() async {
@@ -1458,7 +1691,10 @@
   final x;
   A() : x = 0, x = 0 {}
 }
-''', [CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, 36,
+          1),
+    ]);
   }
 
   /**
@@ -1475,7 +1711,10 @@
   final x;
   A(this.x) : x = 0 {}
 }
-''', [CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER,
+          35, 1),
+    ]);
   }
 
   test_finalInitializedMultipleTimes_initializingFormals() async {
@@ -1486,8 +1725,8 @@
   A(this.x, this.x) {}
 }
 ''', [
-      CompileTimeErrorCode.DUPLICATE_DEFINITION,
-      CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES
+      error(CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES, 38, 1),
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 38, 1),
     ]);
   }
 
@@ -1496,13 +1735,17 @@
 class A {
   static const F;
 }
-''', [CompileTimeErrorCode.CONST_NOT_INITIALIZED]);
+''', [
+      error(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 25, 1),
+    ]);
   }
 
   test_finalNotInitialized_library_const() async {
     await assertErrorsInCode('''
 const F;
-''', [CompileTimeErrorCode.CONST_NOT_INITIALIZED]);
+''', [
+      error(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 6, 1),
+    ]);
   }
 
   test_finalNotInitialized_local_const() async {
@@ -1510,7 +1753,10 @@
 f() {
   const int x;
 }
-''', [CompileTimeErrorCode.CONST_NOT_INITIALIZED]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 18, 1),
+      error(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 18, 1),
+    ]);
   }
 
   test_forInWithConstVariable_forEach_identifier() async {
@@ -1519,7 +1765,10 @@
   const x = 0;
   for (x in [0, 1, 2]) {}
 }
-''', [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, 28, 1),
+    ]);
   }
 
   test_forInWithConstVariable_forEach_loopVariable() async {
@@ -1527,7 +1776,10 @@
 f() {
   for (const x in [0, 1, 2]) {}
 }
-''', [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+''', [
+      error(CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, 13, 7),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 19, 1),
+    ]);
   }
 
   test_fromEnvironment_bool_badArgs() async {
@@ -1535,10 +1787,10 @@
 var b1 = const bool.fromEnvironment(1);
 var b2 = const bool.fromEnvironment('x', defaultValue: 1);
 ''', [
-      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
-      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 9, 29),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 36, 1),
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 49, 48),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 81, 15),
     ]);
   }
 
@@ -1546,13 +1798,11 @@
     // The type of the defaultValue needs to be correct even when the default
     // value isn't used (because the variable is defined in the environment).
     driver.declaredVariables = new DeclaredVariables.fromMap({'x': 'true'});
-    Source source = addSource('''
+    assertErrorsInCode('''
 var b = const bool.fromEnvironment('x', defaultValue: 1);
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 8, 48),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 40, 15),
     ]);
   }
 
@@ -1560,14 +1810,18 @@
     await assertErrorsInCode(r'''
 T f<T>(T t) => null;
 main() { f(<S>(S s) => s); }
-''', [StrongModeCode.COULD_NOT_INFER]);
+''', [
+      error(StrongModeCode.COULD_NOT_INFER, 30, 1),
+    ]);
   }
 
   test_genericFunctionTypeArgument_inference_functionType() async {
     await assertErrorsInCode(r'''
 T Function<T>(T) f;
 main() { f(<S>(S s) => s); }
-''', [StrongModeCode.COULD_NOT_INFER]);
+''', [
+      error(StrongModeCode.COULD_NOT_INFER, 29, 1),
+    ]);
   }
 
   test_genericFunctionTypeArgument_inference_method() async {
@@ -1576,26 +1830,34 @@
   T f<T>(T t) => null;
 }
 main() { new C().f(<S>(S s) => s); }
-''', [StrongModeCode.COULD_NOT_INFER]);
+''', [
+      error(StrongModeCode.COULD_NOT_INFER, 52, 1),
+    ]);
   }
 
   test_genericFunctionTypeAsBound_class() async {
     await assertErrorsInCode(r'''
 class C<T extends S Function<S>(S)> {
 }
-''', [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND]);
+''', [
+      error(CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND, 18, 16),
+    ]);
   }
 
   test_genericFunctionTypeAsBound_genericFunction() async {
     await assertErrorsInCode(r'''
 T Function<T extends S Function<S>(S)>(T) fun;
-''', [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND]);
+''', [
+      error(CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND, 21, 16),
+    ]);
   }
 
   test_genericFunctionTypeAsBound_genericFunctionTypedef() async {
     await assertErrorsInCode(r'''
 typedef foo = T Function<T extends S Function<S>(S)>(T t);
-''', [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND]);
+''', [
+      error(CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND, 35, 16),
+    ]);
   }
 
   test_genericFunctionTypeAsBound_parameterOfFunction() async {
@@ -1607,100 +1869,115 @@
   test_genericFunctionTypeAsBound_typedef() async {
     await assertErrorsInCode(r'''
 typedef T foo<T extends S Function<S>(S)>(T t);
-''', [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND]);
-  }
-
-  test_genericFunctionTypedParameter() async {
-    // Once dartbug.com/28515 is fixed, this syntax should no longer generate an
-    // error.
-    // TODO(paulberry): When dartbug.com/28515 is fixed, convert this into a
-    // NonErrorResolverTest.
-    await assertErrorsInCode('''
-void g(T f<T>(T x)) {}
 ''', [
-      CompileTimeErrorCode.GENERIC_FUNCTION_TYPED_PARAM_UNSUPPORTED,
-      // Due to dartbug.com/28515, some additional errors appear when using the
-      // new analysis driver.
-      StaticWarningCode.UNDEFINED_CLASS, StaticWarningCode.UNDEFINED_CLASS
+      error(CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND, 24, 16),
     ]);
   }
 
+  test_genericFunctionTypedParameter() async {
+    var code = '''
+void g(T f<T>(T x)) {}
+''';
+    if (AnalysisDriver.useSummary2) {
+      await assertNoErrorsInCode(code);
+    } else {
+      // Once dartbug.com/28515 is fixed, this syntax should no longer generate an
+      // error.
+      await assertErrorsInCode(code, [
+        // Due to dartbug.com/28515, some additional errors appear when using the
+        // new analysis driver.
+        error(StaticWarningCode.UNDEFINED_CLASS, 7, 1),
+        error(CompileTimeErrorCode.GENERIC_FUNCTION_TYPED_PARAM_UNSUPPORTED, 7,
+            11),
+        error(StaticWarningCode.UNDEFINED_CLASS, 14, 1),
+      ]);
+    }
+  }
+
   test_implementsDeferredClass() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 class A {}
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class B implements a.A {}
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS, 67, 3),
     ]);
   }
 
   test_implementsDeferredClass_classTypeAlias() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 class A {}
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class B {}
 class M {}
 class C = B with M implements a.A;
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS, 100, 3),
     ]);
   }
 
   test_implementsDisallowedClass_class_bool() async {
     await assertErrorsInCode('''
 class A implements bool {}
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 4),
+    ]);
   }
 
   test_implementsDisallowedClass_class_double() async {
     await assertErrorsInCode('''
 class A implements double {}
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
+    ]);
   }
 
   test_implementsDisallowedClass_class_int() async {
     await assertErrorsInCode('''
 class A implements int {}
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 3),
+    ]);
   }
 
   test_implementsDisallowedClass_class_Null() async {
     await assertErrorsInCode('''
 class A implements Null {}
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 4),
+    ]);
   }
 
   test_implementsDisallowedClass_class_num() async {
     await assertErrorsInCode('''
 class A implements num {}
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 3),
+    ]);
   }
 
   test_implementsDisallowedClass_class_String() async {
     await assertErrorsInCode('''
 class A implements String {}
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
+    ]);
   }
 
   test_implementsDisallowedClass_class_String_num() async {
     await assertErrorsInCode('''
 class A implements String, num {}
 ''', [
-      CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
-      CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 27, 3),
     ]);
   }
 
@@ -1709,7 +1986,9 @@
 class A {}
 class M {}
 class C = A with M implements bool;
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 4),
+    ]);
   }
 
   test_implementsDisallowedClass_classTypeAlias_double() async {
@@ -1717,7 +1996,9 @@
 class A {}
 class M {}
 class C = A with M implements double;
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 6),
+    ]);
   }
 
   test_implementsDisallowedClass_classTypeAlias_int() async {
@@ -1725,7 +2006,9 @@
 class A {}
 class M {}
 class C = A with M implements int;
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 3),
+    ]);
   }
 
   test_implementsDisallowedClass_classTypeAlias_Null() async {
@@ -1733,7 +2016,9 @@
 class A {}
 class M {}
 class C = A with M implements Null;
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 4),
+    ]);
   }
 
   test_implementsDisallowedClass_classTypeAlias_num() async {
@@ -1741,7 +2026,9 @@
 class A {}
 class M {}
 class C = A with M implements num;
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 3),
+    ]);
   }
 
   test_implementsDisallowedClass_classTypeAlias_String() async {
@@ -1749,7 +2036,9 @@
 class A {}
 class M {}
 class C = A with M implements String;
-''', [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 6),
+    ]);
   }
 
   test_implementsDisallowedClass_classTypeAlias_String_num() async {
@@ -1758,8 +2047,8 @@
 class M {}
 class C = A with M implements String, num;
 ''', [
-      CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
-      CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 52, 6),
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 60, 3),
     ]);
   }
 
@@ -1767,20 +2056,26 @@
     await assertErrorsInCode(r'''
 int A;
 class B implements A {}
-''', [CompileTimeErrorCode.IMPLEMENTS_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_NON_CLASS, 26, 1),
+    ]);
   }
 
   test_implementsNonClass_dynamic() async {
     await assertErrorsInCode('''
 class A implements dynamic {}
-''', [CompileTimeErrorCode.IMPLEMENTS_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_NON_CLASS, 19, 7),
+    ]);
   }
 
   test_implementsNonClass_enum() async {
     await assertErrorsInCode(r'''
 enum E { ONE }
 class A implements E {}
-''', [CompileTimeErrorCode.IMPLEMENTS_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_NON_CLASS, 34, 1),
+    ]);
   }
 
   test_implementsNonClass_typeAlias() async {
@@ -1789,27 +2084,35 @@
 class M {}
 int B;
 class C = A with M implements B;
-''', [CompileTimeErrorCode.IMPLEMENTS_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_NON_CLASS, 59, 1),
+    ]);
   }
 
   test_implementsSuperClass() async {
     await assertErrorsInCode(r'''
 class A {}
 class B extends A implements A {}
-''', [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, 40, 1),
+    ]);
   }
 
   test_implementsSuperClass_Object() async {
     await assertErrorsInCode('''
 class A implements Object {}
-''', [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, 19, 6),
+    ]);
   }
 
   test_implementsSuperClass_Object_typeAlias() async {
     await assertErrorsInCode(r'''
 class M {}
 class A = Object with M implements Object;
-''', [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, 46, 6),
+    ]);
   }
 
   test_implementsSuperClass_typeAlias() async {
@@ -1817,7 +2120,9 @@
 class A {}
 class M {}
 class B = A with M implements A;
-''', [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, 52, 1),
+    ]);
   }
 
   test_implicitThisReferenceInInitializer_field() async {
@@ -1827,7 +2132,9 @@
   A() : v = f;
   var f;
 }
-''', [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 31, 1),
+    ]);
   }
 
   test_implicitThisReferenceInInitializer_field2() async {
@@ -1837,8 +2144,8 @@
   final y = x;
 }
 ''', [
-      CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER,
-      StrongModeCode.TOP_LEVEL_INSTANCE_GETTER
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 37, 1),
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 37, 1),
     ]);
   }
 
@@ -1849,7 +2156,9 @@
   A() : v = f();
   f() {}
 }
-''', [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 31, 1),
+    ]);
   }
 
   test_implicitThisReferenceInInitializer_invocationInStatic() async {
@@ -1858,7 +2167,9 @@
   static var F = m();
   int m() => 0;
 }
-''', [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 27, 1),
+    ]);
   }
 
   test_implicitThisReferenceInInitializer_redirectingConstructorInvocation() async {
@@ -1868,7 +2179,9 @@
   A.named() : this(f);
   var f;
 }
-''', [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 39, 1),
+    ]);
   }
 
   test_implicitThisReferenceInInitializer_superConstructorInvocation() async {
@@ -1880,7 +2193,9 @@
   B() : super(f);
   var f;
 }
-''', [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 56, 1),
+    ]);
   }
 
   test_importInternalLibrary() async {
@@ -1891,11 +2206,14 @@
     // cases.
     await assertErrorsInCode('''
 import 'dart:_interceptors';
-''', [CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY, HintCode.UNUSED_IMPORT]);
+''', [
+      error(CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY, 7, 20),
+      error(HintCode.UNUSED_IMPORT, 7, 20),
+    ]);
   }
 
   test_importOfNonLibrary() async {
-    newFile("/part.dart", content: r'''
+    newFile("/test/lib/part.dart", content: r'''
 part of lib;
 class A{}
 ''');
@@ -1903,7 +2221,9 @@
 library lib;
 import 'part.dart';
 A a;
-''', [CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY]);
+''', [
+      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 20, 11),
+    ]);
   }
 
   test_inconsistentCaseExpressionTypes() async {
@@ -1916,7 +2236,9 @@
       break;
   }
 }
-''', [CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES]);
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 60, 3),
+    ]);
   }
 
   test_inconsistentCaseExpressionTypes_dynamic() async {
@@ -1940,8 +2262,8 @@
   }
 }
 ''', [
-      CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES,
-      CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES
+      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 117, 1),
+      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 142, 3),
     ]);
   }
 
@@ -1958,8 +2280,8 @@
   }
 }
 ''', [
-      CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES,
-      CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES
+      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 60, 3),
+      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 87, 3),
     ]);
   }
 
@@ -1971,7 +2293,9 @@
   const A() : x = 'foo';
 }
 A a = const A();
-''', [CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD], verify: false);
+''', [
+      error(CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD, 24, 9),
+    ]);
   }
 
   test_initializerForNonExistent_initializer() async {
@@ -1979,7 +2303,9 @@
 class A {
   A() : x = 0 {}
 }
-''', [CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD], verify: false);
+''', [
+      error(CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD, 18, 5),
+    ]);
   }
 
   test_initializerForStaticField() async {
@@ -1988,7 +2314,9 @@
   static int x;
   A() : x = 0 {}
 }
-''', [CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD]);
+''', [
+      error(CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD, 34, 5),
+    ]);
   }
 
   test_initializingFormalForNonExistentField() async {
@@ -1996,7 +2324,10 @@
 class A {
   A(this.x) {}
 }
-''', [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
+''', [
+      error(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD, 14,
+          6),
+    ]);
   }
 
   test_initializingFormalForNonExistentField_notInEnclosingClass() async {
@@ -2007,7 +2338,10 @@
 class B extends A {
   B(this.x) {}
 }
-''', [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
+''', [
+      error(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD, 43,
+          6),
+    ]);
   }
 
   test_initializingFormalForNonExistentField_optional() async {
@@ -2015,7 +2349,10 @@
 class A {
   A([this.x]) {}
 }
-''', [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
+''', [
+      error(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD, 15,
+          6),
+    ]);
   }
 
   test_initializingFormalForNonExistentField_synthetic() async {
@@ -2024,7 +2361,10 @@
   int get x => 1;
   A(this.x) {}
 }
-''', [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
+''', [
+      error(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD, 32,
+          6),
+    ]);
   }
 
   test_initializingFormalForStaticField() async {
@@ -2033,7 +2373,9 @@
   static int x;
   A([this.x]) {}
 }
-''', [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD]);
+''', [
+      error(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD, 31, 6),
+    ]);
   }
 
   test_instanceMemberAccessFromFactory_named() async {
@@ -2046,7 +2388,9 @@
     return new A();
   }
 }
-''', [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY]);
+''', [
+      error(CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY, 51, 1),
+    ]);
   }
 
   test_instanceMemberAccessFromFactory_unnamed() async {
@@ -2059,7 +2403,9 @@
     return new A._();
   }
 }
-''', [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY]);
+''', [
+      error(CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY, 48, 1),
+    ]);
   }
 
   test_instanceMemberAccessFromStatic_field() async {
@@ -2070,7 +2416,9 @@
     f;
   }
 }
-''', [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC]);
+''', [
+      error(CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC, 40, 1),
+    ]);
   }
 
   test_instanceMemberAccessFromStatic_getter() async {
@@ -2081,7 +2429,9 @@
     g;
   }
 }
-''', [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC]);
+''', [
+      error(CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC, 48, 1),
+    ]);
   }
 
   test_instanceMemberAccessFromStatic_method() async {
@@ -2092,24 +2442,25 @@
     m();
   }
 }
-''', [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC]);
+''', [
+      error(CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC, 40, 1),
+    ]);
   }
 
   test_instantiate_to_bounds_not_matching_bounds() async {
-    Source source = addSource('''
+    // There should be an error, because Bar's type argument T is Foo, which
+    // doesn't extends Foo<T>.
+    await assertErrorsInCode('''
 class Foo<T> {}
 class Bar<T extends Foo<T>> {}
 class Baz extends Bar {}
 void main() {}
-''');
-    var result = await computeAnalysisResult(source);
-    // Instantiate-to-bounds should have instantiated "Bar" to "Bar<Foo>"
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 65, 3),
+    ]);
+    // Instantiate-to-bounds should have instantiated "Bar" to "Bar<Foo>".
     expect(result.unit.declaredElement.getType('Baz').supertype.toString(),
         'Bar<Foo<dynamic>>');
-    // Therefore there should be an error, since Bar's type argument T is Foo,
-    // which doesn't extends Foo<T>.
-    assertErrors(
-        source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
   }
 
   test_instantiateEnum_const() async {
@@ -2118,7 +2469,9 @@
 E e(String name) {
   return const E();
 }
-''', [CompileTimeErrorCode.INSTANTIATE_ENUM]);
+''', [
+      error(CompileTimeErrorCode.INSTANTIATE_ENUM, 49, 1),
+    ]);
   }
 
   test_instantiateEnum_new() async {
@@ -2127,24 +2480,27 @@
 E e(String name) {
   return new E();
 }
-''', [CompileTimeErrorCode.INSTANTIATE_ENUM]);
+''', [
+      error(CompileTimeErrorCode.INSTANTIATE_ENUM, 47, 1),
+    ]);
   }
 
   test_integerLiteralAsDoubleOutOfRange_excessiveExponent() async {
-    Source source = addSource(
+    await assertErrorsInCode(
         'double x = 0xfffffffffffff80000000000000000000000000000000000000000000'
         '0000000000000000000000000000000000000000000000000000000000000000000000'
         '0000000000000000000000000000000000000000000000000000000000000000000000'
-        '000000000000000000000000000000000000000000000000000000000000;');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [CompileTimeErrorCode.INTEGER_LITERAL_IMPRECISE_AS_DOUBLE]);
-    AnalysisError error = analysisResults[source].errors[0];
+        '000000000000000000000000000000000000000000000000000000000000;',
+        [
+          error(CompileTimeErrorCode.INTEGER_LITERAL_IMPRECISE_AS_DOUBLE, 11,
+              259),
+        ]);
+    AnalysisError firstError = result.errors[0];
 
     // Check that we suggest the max double instead.
     expect(
         true,
-        error.correction.contains(
+        firstError.correction.contains(
             '179769313486231570814527423731704356798070567525844996598917476803'
             '157260780028538760589558632766878171540458953514382464234321326889'
             '464182768467546703537516986049910576551282076245490090389328944075'
@@ -2153,31 +2509,34 @@
   }
 
   test_integerLiteralAsDoubleOutOfRange_excessiveMantissa() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 double x = 9223372036854775809;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [CompileTimeErrorCode.INTEGER_LITERAL_IMPRECISE_AS_DOUBLE]);
-    AnalysisError error = analysisResults[source].errors[0];
+''', [
+      error(CompileTimeErrorCode.INTEGER_LITERAL_IMPRECISE_AS_DOUBLE, 11, 19),
+    ]);
+    AnalysisError firstError = result.errors[0];
     // Check that we suggest a valid double instead.
-    expect(true, error.correction.contains('9223372036854775808'));
+    expect(true, firstError.correction.contains('9223372036854775808'));
   }
 
   test_integerLiteralOutOfRange_negative() async {
     await assertErrorsInCode('''
 int x = -9223372036854775809;
-''', [CompileTimeErrorCode.INTEGER_LITERAL_OUT_OF_RANGE]);
+''', [
+      error(CompileTimeErrorCode.INTEGER_LITERAL_OUT_OF_RANGE, 9, 19),
+    ]);
   }
 
   test_integerLiteralOutOfRange_positive() async {
     await assertErrorsInCode('''
 int x = 9223372036854775808;
-''', [CompileTimeErrorCode.INTEGER_LITERAL_OUT_OF_RANGE]);
+''', [
+      error(CompileTimeErrorCode.INTEGER_LITERAL_OUT_OF_RANGE, 8, 19),
+    ]);
   }
 
   test_invalidAnnotation_importWithPrefix_notConstantVariable() async {
-    newFile("/lib.dart", content: r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 final V = 0;
 ''');
@@ -2186,11 +2545,13 @@
 @p.V
 main() {
 }
-''', [CompileTimeErrorCode.INVALID_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.INVALID_ANNOTATION, 24, 4),
+    ]);
   }
 
   test_invalidAnnotation_importWithPrefix_notVariableOrConstructorInvocation() async {
-    newFile("/lib.dart", content: r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 typedef V();
 ''');
@@ -2199,7 +2560,9 @@
 @p.V
 main() {
 }
-''', [CompileTimeErrorCode.INVALID_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.INVALID_ANNOTATION, 24, 4),
+    ]);
   }
 
   test_invalidAnnotation_notConstantVariable() async {
@@ -2208,7 +2571,9 @@
 @V
 main() {
 }
-''', [CompileTimeErrorCode.INVALID_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.INVALID_ANNOTATION, 13, 2),
+    ]);
   }
 
   test_invalidAnnotation_notVariableOrConstructorInvocation() async {
@@ -2217,7 +2582,9 @@
 @V
 main() {
 }
-''', [CompileTimeErrorCode.INVALID_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.INVALID_ANNOTATION, 13, 2),
+    ]);
   }
 
   test_invalidAnnotation_staticMethodReference() async {
@@ -2228,58 +2595,57 @@
 @A.f
 main() {
 }
-''', [CompileTimeErrorCode.INVALID_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.INVALID_ANNOTATION, 28, 4),
+    ]);
   }
 
   test_invalidAnnotationFromDeferredLibrary() async {
     // See test_invalidAnnotation_notConstantVariable
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 class V { const V(); }
 const v = const V();
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 @a.v main () {}
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY
+''', [
+      error(
+          CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY, 49, 3),
     ]);
   }
 
   test_invalidAnnotationFromDeferredLibrary_constructor() async {
     // See test_invalidAnnotation_notConstantVariable
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 class C { const C(); }
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 @a.C() main () {}
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY
+''', [
+      error(
+          CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY, 49, 3),
     ]);
   }
 
   test_invalidAnnotationFromDeferredLibrary_namedConstructor() async {
     // See test_invalidAnnotation_notConstantVariable
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 class C { const C.name(); }
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 @a.C.name() main () {}
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY
+''', [
+      error(
+          CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY, 49, 3),
     ]);
   }
 
@@ -2289,11 +2655,13 @@
 @V
 main() {
 }
-''', [CompileTimeErrorCode.INVALID_ANNOTATION_GETTER]);
+''', [
+      error(CompileTimeErrorCode.INVALID_ANNOTATION_GETTER, 12, 2),
+    ]);
   }
 
   test_invalidAnnotationGetter_importWithPrefix_getter() async {
-    newFile("/lib.dart", content: r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 get V => 0;
 ''');
@@ -2302,7 +2670,9 @@
 @p.V
 main() {
 }
-''', [CompileTimeErrorCode.INVALID_ANNOTATION_GETTER]);
+''', [
+      error(CompileTimeErrorCode.INVALID_ANNOTATION_GETTER, 24, 4),
+    ]);
   }
 
   test_invalidConstructorName_notEnclosingClassName_defined() async {
@@ -2311,7 +2681,9 @@
   B() : super();
 }
 class B {}
-''', [CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME]);
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, 12, 1),
+    ]);
   }
 
   test_invalidConstructorName_notEnclosingClassName_undefined() async {
@@ -2319,7 +2691,9 @@
 class A {
   B() : super();
 }
-''', [CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME]);
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, 12, 1),
+    ]);
   }
 
   test_invalidFactoryNameNotAClass_notClassName() async {
@@ -2328,7 +2702,9 @@
 class A {
   factory B() => null;
 }
-''', [CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS]);
+''', [
+      error(CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS, 27, 1),
+    ]);
   }
 
   test_invalidFactoryNameNotAClass_notEnclosingClassName() async {
@@ -2336,7 +2712,9 @@
 class A {
   factory B() => null;
 }
-''', [CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS]);
+''', [
+      error(CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS, 20, 1),
+    ]);
   }
 
   test_invalidIdentifierInAsync_async() async {
@@ -2346,7 +2724,9 @@
     int async;
   }
 }
-''', [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 32, 5),
+    ]);
   }
 
   test_invalidIdentifierInAsync_await() async {
@@ -2356,7 +2736,10 @@
     int await;
   }
 }
-''', [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 32, 5),
+      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 32, 5),
+    ]);
   }
 
   test_invalidIdentifierInAsync_yield() async {
@@ -2366,7 +2749,10 @@
     int yield;
   }
 }
-''', [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+''', [
+      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 32, 5),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 32, 5),
+    ]);
   }
 
   test_invalidModifierOnConstructor_async() async {
@@ -2374,7 +2760,9 @@
 class A {
   A() async {}
 }
-''', [CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR, 16, 5),
+    ]);
   }
 
   test_invalidModifierOnConstructor_asyncStar() async {
@@ -2382,7 +2770,9 @@
 class A {
   A() async* {}
 }
-''', [CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR, 16, 5),
+    ]);
   }
 
   test_invalidModifierOnConstructor_syncStar() async {
@@ -2390,7 +2780,9 @@
 class A {
   A() sync* {}
 }
-''', [CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR, 16, 4),
+    ]);
   }
 
   test_invalidModifierOnSetter_member_async() async {
@@ -2401,8 +2793,8 @@
   set x(v) async {}
 }
 ''', [
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 21, 5),
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 21, 5),
     ]);
   }
 
@@ -2412,8 +2804,8 @@
   set x(v) async* {}
 }
 ''', [
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 21, 5),
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 21, 5),
     ]);
   }
 
@@ -2423,8 +2815,8 @@
   set x(v) sync* {}
 }
 ''', [
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 21, 4),
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 21, 4),
     ]);
   }
 
@@ -2432,8 +2824,8 @@
     await assertErrorsInCode('''
 set x(v) async {}
 ''', [
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 9, 5),
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 9, 5),
     ]);
   }
 
@@ -2441,8 +2833,8 @@
     await assertErrorsInCode('''
 set x(v) async* {}
 ''', [
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 9, 5),
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 9, 5),
     ]);
   }
 
@@ -2450,8 +2842,8 @@
     await assertErrorsInCode('''
 set x(v) sync* {}
 ''', [
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
-      CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 9, 4),
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER, 9, 4),
     ]);
   }
 
@@ -2460,7 +2852,9 @@
 class A {
   factory A() { return this; }
 }
-''', [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
+''', [
+      error(CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, 33, 4),
+    ]);
   }
 
   test_invalidReferenceToThis_instanceVariableInitializer_inConstructor() async {
@@ -2469,7 +2863,9 @@
   var f;
   A() : f = this;
 }
-''', [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
+''', [
+      error(CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, 31, 4),
+    ]);
   }
 
   test_invalidReferenceToThis_instanceVariableInitializer_inDeclaration() async {
@@ -2477,7 +2873,9 @@
 class A {
   var f = this;
 }
-''', [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
+''', [
+      error(CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, 20, 4),
+    ]);
   }
 
   test_invalidReferenceToThis_staticMethod() async {
@@ -2485,7 +2883,9 @@
 class A {
   static m() { return this; }
 }
-''', [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
+''', [
+      error(CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, 32, 4),
+    ]);
   }
 
   test_invalidReferenceToThis_staticVariableInitializer() async {
@@ -2493,7 +2893,9 @@
 class A {
   static A f = this;
 }
-''', [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
+''', [
+      error(CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, 25, 4),
+    ]);
   }
 
   test_invalidReferenceToThis_superInitializer() async {
@@ -2504,19 +2906,25 @@
 class B extends A {
   B() : super(this);
 }
-''', [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
+''', [
+      error(CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, 60, 4),
+    ]);
   }
 
   test_invalidReferenceToThis_topLevelFunction() async {
     await assertErrorsInCode('''
 f() { return this; }
-''', [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
+''', [
+      error(CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, 13, 4),
+    ]);
   }
 
   test_invalidReferenceToThis_variableInitializer() async {
     await assertErrorsInCode('''
 int x = this;
-''', [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
+''', [
+      error(CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, 8, 4),
+    ]);
   }
 
   test_invalidTypeArgumentInConstList() async {
@@ -2526,7 +2934,9 @@
     return const <E>[];
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST, 39, 1),
+    ]);
   }
 
   test_invalidTypeArgumentInConstMap() async {
@@ -2536,26 +2946,34 @@
     return const <String, E>{};
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP, 47, 1),
+    ]);
   }
 
   test_invalidUri_export() async {
     await assertErrorsInCode('''
 export 'ht:';
-''', [CompileTimeErrorCode.INVALID_URI]);
+''', [
+      error(CompileTimeErrorCode.INVALID_URI, 7, 5),
+    ]);
   }
 
   test_invalidUri_import() async {
     await assertErrorsInCode('''
 import 'ht:';
-''', [CompileTimeErrorCode.INVALID_URI]);
+''', [
+      error(CompileTimeErrorCode.INVALID_URI, 7, 5),
+    ]);
   }
 
   test_invalidUri_part() async {
     await assertErrorsInCode(r'''
 library lib;
 part 'ht:';
-''', [CompileTimeErrorCode.INVALID_URI]);
+''', [
+      error(CompileTimeErrorCode.INVALID_URI, 18, 5),
+    ]);
   }
 
   test_isInConstInstanceCreation_restored() async {
@@ -2568,7 +2986,9 @@
 }
 const x = const Foo<int>(const Foo<int>(0, 1),
     const <Foo<String>>[]); // (1)
-''', [CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 110, 6),
+    ]);
   }
 
   test_isInInstanceVariableInitializer_restored() async {
@@ -2587,7 +3007,10 @@
   _foo() {
   }
 }
-''', [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 65, 4),
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 89, 4),
+    ]);
   }
 
   test_labelInOuterScope() async {
@@ -2601,7 +3024,10 @@
     }
   }
 }
-''', [CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 62, 1),
+      error(CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE, 82, 1),
+    ]);
   }
 
   test_labelUndefined_break() async {
@@ -2611,8 +3037,10 @@
     break y;
   }
 }
-''', [CompileTimeErrorCode.LABEL_UNDEFINED, HintCode.UNUSED_LABEL],
-        verify: false);
+''', [
+      error(HintCode.UNUSED_LABEL, 8, 2),
+      error(CompileTimeErrorCode.LABEL_UNDEFINED, 36, 1),
+    ]);
   }
 
   test_labelUndefined_continue() async {
@@ -2622,8 +3050,10 @@
     continue y;
   }
 }
-''', [CompileTimeErrorCode.LABEL_UNDEFINED, HintCode.UNUSED_LABEL],
-        verify: false);
+''', [
+      error(HintCode.UNUSED_LABEL, 8, 2),
+      error(CompileTimeErrorCode.LABEL_UNDEFINED, 39, 1),
+    ]);
   }
 
   test_length_of_erroneous_constant() async {
@@ -2632,9 +3062,10 @@
     await assertErrorsInCode('''
 const int i = (1 ? 'alpha' : 'beta').length;
 ''', [
-      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE,
-      CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL,
-      StaticTypeWarningCode.NON_BOOL_CONDITION
+      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 14,
+          29),
+      error(StaticTypeWarningCode.NON_BOOL_CONDITION, 15, 1),
+      error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, 15, 1),
     ]);
   }
 
@@ -2643,7 +3074,9 @@
 class A {
   int A = 0;
 }
-''', [CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
+''', [
+      error(CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
+    ]);
   }
 
   test_memberWithClassName_field2() async {
@@ -2651,7 +3084,9 @@
 class A {
   int z, A, b = 0;
 }
-''', [CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
+''', [
+      error(CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, 19, 1),
+    ]);
   }
 
   test_memberWithClassName_getter() async {
@@ -2659,7 +3094,9 @@
 class A {
   get A => 0;
 }
-''', [CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
+''', [
+      error(CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
+    ]);
   }
 
   test_memberWithClassName_method() async {
@@ -2674,7 +3111,9 @@
 }
 class B extends Object with A {}
 ''',
-      [CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR],
+      [
+        error(CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR, 49, 1),
+      ],
     );
   }
 
@@ -2686,40 +3125,38 @@
 }
 class B = Object with A;
 ''',
-      [CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR],
+      [
+        error(CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR, 43, 1),
+      ],
     );
   }
 
   test_mixinDeferredClass() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 class A {}
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class B extends Object with a.A {}
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.MIXIN_DEFERRED_CLASS
+''', [
+      error(CompileTimeErrorCode.MIXIN_DEFERRED_CLASS, 76, 3),
     ]);
   }
 
   test_mixinDeferredClass_classTypeAlias() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 class A {}
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class B {}
 class C = B with a.A;
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.MIXIN_DEFERRED_CLASS
+''', [
+      error(CompileTimeErrorCode.MIXIN_DEFERRED_CLASS, 76, 3),
     ]);
   }
 
@@ -2748,7 +3185,10 @@
 class B {}
 mixin M<T> on A<T> {}
 class C = Object with M;
-''', [CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
+          78, 1),
+    ]);
   }
 
   test_mixinInference_noMatchingClass_new_syntax() async {
@@ -2757,7 +3197,10 @@
 class B {}
 mixin M<T> on A<T> {}
 class C extends Object with M {}
-''', [CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
+          84, 1),
+    ]);
   }
 
   test_mixinInference_noMatchingClass_noSuperclassConstraint_new_syntax() async {
@@ -2775,12 +3218,15 @@
 class B {}
 mixin M<T> on A<T> {}
 class C extends Object with M<int> {}
-''', [CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
+          84, 1),
+    ]);
   }
 
   test_mixinInference_recursiveSubtypeCheck_new_syntax() async {
     // See dartbug.com/32353 for a detailed explanation.
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class ioDirectory implements ioFileSystemEntity {}
 
 class ioFileSystemEntity {}
@@ -2806,10 +3252,7 @@
 
 mixin DirectoryAddOnsMixin implements Directory {}
 ''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    var mixins =
-        analysisResult.unit.declaredElement.getType('_LocalDirectory').mixins;
+    var mixins = result.unit.declaredElement.getType('_LocalDirectory').mixins;
     expect(mixins[0].toString(), 'ForwardingDirectory<_LocalDirectory>');
   }
 
@@ -2818,7 +3261,9 @@
 class A {}
 class B extends A {}
 class C extends Object with B {}
-''', [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 60, 1),
+    ]);
   }
 
   test_mixinInheritsFromNotObject_classDeclaration_with() async {
@@ -2826,7 +3271,9 @@
 class A {}
 class B extends Object with A {}
 class C extends Object with B {}
-''', [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 72, 1),
+    ]);
   }
 
   test_mixinInheritsFromNotObject_typeAlias_extends() async {
@@ -2834,7 +3281,9 @@
 class A {}
 class B extends A {}
 class C = Object with B;
-''', [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 54, 1),
+    ]);
   }
 
   test_mixinInheritsFromNotObject_typeAlias_with() async {
@@ -2842,85 +3291,111 @@
 class A {}
 class B extends Object with A {}
 class C = Object with B;
-''', [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 66, 1),
+    ]);
   }
 
   test_mixinOfDisallowedClass_class_bool() async {
     await assertErrorsInCode('''
 class A extends Object with bool {}
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
+    ]);
   }
 
   test_mixinOfDisallowedClass_class_double() async {
     await assertErrorsInCode('''
 class A extends Object with double {}
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
+    ]);
   }
 
   test_mixinOfDisallowedClass_class_int() async {
     await assertErrorsInCode('''
 class A extends Object with int {}
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
+    ]);
   }
 
   test_mixinOfDisallowedClass_class_Null() async {
     await assertErrorsInCode('''
 class A extends Object with Null {}
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
+    ]);
   }
 
   test_mixinOfDisallowedClass_class_num() async {
     await assertErrorsInCode('''
 class A extends Object with num {}
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
+    ]);
   }
 
   test_mixinOfDisallowedClass_class_String() async {
     await assertErrorsInCode('''
 class A extends Object with String {}
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
+    ]);
   }
 
   test_mixinOfDisallowedClass_classTypeAlias_bool() async {
     await assertErrorsInCode(r'''
 class A {}
 class C = A with bool;
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
+    ]);
   }
 
   test_mixinOfDisallowedClass_classTypeAlias_double() async {
     await assertErrorsInCode(r'''
 class A {}
 class C = A with double;
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
+    ]);
   }
 
   test_mixinOfDisallowedClass_classTypeAlias_int() async {
     await assertErrorsInCode(r'''
 class A {}
 class C = A with int;
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
+    ]);
   }
 
   test_mixinOfDisallowedClass_classTypeAlias_Null() async {
     await assertErrorsInCode(r'''
 class A {}
 class C = A with Null;
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
+    ]);
   }
 
   test_mixinOfDisallowedClass_classTypeAlias_num() async {
     await assertErrorsInCode(r'''
 class A {}
 class C = A with num;
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
+    ]);
   }
 
   test_mixinOfDisallowedClass_classTypeAlias_String() async {
     await assertErrorsInCode(r'''
 class A {}
 class C = A with String;
-''', [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
+    ]);
   }
 
   test_mixinOfDisallowedClass_classTypeAlias_String_num() async {
@@ -2928,31 +3403,38 @@
 class A {}
 class C = A with String, num;
 ''', [
-      CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS,
-      CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
+      error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 36, 3),
     ]);
   }
 
   test_mixinOfNonClass() async {
     // TODO(brianwilkerson) Compare with MIXIN_WITH_NON_CLASS_SUPERCLASS.
+    // TODO(brianwilkerson) Fix the offset and length.
     await assertErrorsInCode(r'''
 var A;
 class B extends Object mixin A {}
-''', [CompileTimeErrorCode.MIXIN_OF_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 0, 0),
+    ]);
   }
 
   test_mixinOfNonClass_class() async {
     await assertErrorsInCode(r'''
 int A;
 class B extends Object with A {}
-''', [CompileTimeErrorCode.MIXIN_OF_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 35, 1),
+    ]);
   }
 
   test_mixinOfNonClass_enum() async {
     await assertErrorsInCode(r'''
 enum E { ONE }
 class A extends Object with E {}
-''', [CompileTimeErrorCode.MIXIN_OF_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 43, 1),
+    ]);
   }
 
   test_mixinOfNonClass_typeAlias() async {
@@ -2960,7 +3442,9 @@
 class A {}
 int B;
 class C = A with B;
-''', [CompileTimeErrorCode.MIXIN_OF_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 35, 1),
+    ]);
   }
 
   test_mixinReferencesSuper() async {
@@ -2969,7 +3453,9 @@
   toString() => super.toString();
 }
 class B extends Object with A {}
-''', [CompileTimeErrorCode.MIXIN_REFERENCES_SUPER]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_REFERENCES_SUPER, 74, 1),
+    ]);
   }
 
   test_mixinWithNonClassSuperclass_class() async {
@@ -2977,7 +3463,9 @@
 int A;
 class B {}
 class C extends A with B {}
-''', [CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS, 34, 1),
+    ]);
   }
 
   test_mixinWithNonClassSuperclass_typeAlias() async {
@@ -2985,7 +3473,9 @@
 int A;
 class B {}
 class C = A with B;
-''', [CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS, 28, 1),
+    ]);
   }
 
   test_multipleRedirectingConstructorInvocations() async {
@@ -2995,7 +3485,10 @@
   A.a() {}
   A.b() {}
 }
-''', [CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS]);
+''', [
+      error(CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS,
+          28, 8),
+    ]);
   }
 
   test_multipleSuperInitializers() async {
@@ -3005,38 +3498,35 @@
   B() : super(), super() {}
 }
 ''', [
-      CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS,
-      StrongModeCode.INVALID_SUPER_INVOCATION
+      error(StrongModeCode.INVALID_SUPER_INVOCATION, 39, 7),
+      error(CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS, 48, 7),
     ]);
   }
 
   test_nativeClauseInNonSDKCode() async {
-    // TODO(jwren) Move this test somewhere else: This test verifies a parser
-    // error code is generated through the ErrorVerifier, it is not a
-    // CompileTimeErrorCode.
     await assertErrorsInCode('''
 class A native 'string' {}
-''', [ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE]);
+''', [
+      error(ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, 8, 15),
+    ]);
   }
 
   test_nativeFunctionBodyInNonSDKCode_function() async {
-    // TODO(jwren) Move this test somewhere else: This test verifies a parser
-    // error code is generated through the ErrorVerifier, it is not a
-    // CompileTimeErrorCode.
     await assertErrorsInCode('''
 int m(a) native 'string';
-''', [ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE]);
+''', [
+      error(ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE, 9, 16),
+    ]);
   }
 
   test_nativeFunctionBodyInNonSDKCode_method() async {
-    // TODO(jwren) Move this test somewhere else: This test verifies a parser
-    // error code is generated through the ErrorVerifier, it is not a
-    // CompileTimeErrorCode.
     await assertErrorsInCode(r'''
 class A{
   static int m(a) native 'string';
 }
-''', [ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE]);
+''', [
+      error(ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE, 27, 16),
+    ]);
   }
 
   test_noAnnotationConstructorArguments() async {
@@ -3047,7 +3537,9 @@
 @A
 main() {
 }
-''', [CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS]);
+''', [
+      error(CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS, 25, 2),
+    ]);
   }
 
   test_noDefaultSuperConstructorExplicit() async {
@@ -3058,7 +3550,9 @@
 class B extends A {
   B() {}
 }
-''', [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT]);
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT, 42, 1),
+    ]);
   }
 
   test_noDefaultSuperConstructorImplicit_superHasParameters() async {
@@ -3068,14 +3562,18 @@
 }
 class B extends A {
 }
-''', [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 26, 1),
+    ]);
   }
 
   test_noDefaultSuperConstructorImplicit_superOnlyNamed() async {
     await assertErrorsInCode(r'''
 class A { A.named() {} }
 class B extends A {}
-''', [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 31, 1),
+    ]);
   }
 
   test_nonConstantAnnotationConstructor_named() async {
@@ -3086,7 +3584,9 @@
 @A.fromInt()
 main() {
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR, 29, 12),
+    ]);
   }
 
   test_nonConstantAnnotationConstructor_unnamed() async {
@@ -3097,21 +3597,27 @@
 @A()
 main() {
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR, 21, 4),
+    ]);
   }
 
   test_nonConstantDefaultValue_function_named() async {
     await assertErrorsInCode(r'''
 int y;
 f({x : y}) {}
-''', [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 14, 1),
+    ]);
   }
 
   test_nonConstantDefaultValue_function_positional() async {
     await assertErrorsInCode(r'''
 int y;
 f([x = y]) {}
-''', [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 14, 1),
+    ]);
   }
 
   test_nonConstantDefaultValue_inConstructor_named() async {
@@ -3120,7 +3626,9 @@
   int y;
   A({x : y}) {}
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 28, 1),
+    ]);
   }
 
   test_nonConstantDefaultValue_inConstructor_positional() async {
@@ -3129,7 +3637,9 @@
   int y;
   A([x = y]) {}
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 28, 1),
+    ]);
   }
 
   test_nonConstantDefaultValue_method_named() async {
@@ -3138,7 +3648,9 @@
   int y;
   m({x : y}) {}
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 28, 1),
+    ]);
   }
 
   test_nonConstantDefaultValue_method_positional() async {
@@ -3147,38 +3659,42 @@
   int y;
   m([x = y]) {}
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 28, 1),
+    ]);
   }
 
   test_nonConstantDefaultValueFromDeferredLibrary() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 const V = 1;
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 f({x : a.V}) {}
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY
+''', [
+      error(
+          CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY,
+          55,
+          3),
     ]);
   }
 
   test_nonConstantDefaultValueFromDeferredLibrary_nested() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 const V = 1;
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 f({x : a.V + 1}) {}
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY
+''', [
+      error(
+          CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY,
+          55,
+          7),
     ]);
   }
 
@@ -3190,16 +3706,17 @@
       break;
   }
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION, 46, 1),
+    ]);
   }
 
   test_nonConstCaseExpressionFromDeferredLibrary() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 const int c = 1;
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 main (int p) {
@@ -3208,19 +3725,21 @@
       break;
   }
 }
-'''
-    ], [
-      CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY
+''', [
+      error(
+          CompileTimeErrorCode
+              .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
+          87,
+          3),
     ]);
   }
 
   test_nonConstCaseExpressionFromDeferredLibrary_nested() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 const int c = 1;
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 main (int p) {
@@ -3229,9 +3748,12 @@
       break;
   }
 }
-'''
-    ], [
-      CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY
+''', [
+      error(
+          CompileTimeErrorCode
+              .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
+          87,
+          7),
     ]);
   }
 
@@ -3242,20 +3764,20 @@
   {'a' : 0, 'b' : 1}.length;
 }
 ''', [
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
+      error(ParserErrorCode.EXPECTED_TOKEN, 9, 3),
+      error(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 18, 3),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 24, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
     ]);
   }
 
@@ -3266,28 +3788,30 @@
   {'a' : 0, 'b' : 1};
 }
 ''', [
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
+      error(ParserErrorCode.EXPECTED_TOKEN, 9, 3),
+      error(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 18, 3),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 24, 1),
     ]);
   }
 
   test_nonConstValueInInitializer_assert_condition() async {
-    await assertErrorsInCode(r'''
+    await assertErrorsInCode('''
 class A {
   const A(int i) : assert(i.isNegative);
 }
-''', [CompileTimeErrorCode.INVALID_CONSTANT]);
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 36, 12),
+    ]);
   }
 
   test_nonConstValueInInitializer_assert_message() async {
@@ -3295,7 +3819,9 @@
 class A {
   const A(int i) : assert(i < 0, 'isNegative = ${i.isNegative}');
 }
-''', [CompileTimeErrorCode.INVALID_CONSTANT]);
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 59, 12),
+    ]);
   }
 
   test_nonConstValueInInitializer_field() async {
@@ -3305,7 +3831,9 @@
   final int a;
   const A() : a = C;
 }
-''', [CompileTimeErrorCode.INVALID_CONSTANT]);
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 59, 1),
+    ]);
   }
 
   test_nonConstValueInInitializer_instanceCreation() async {
@@ -3321,27 +3849,23 @@
 }
 var b = const B();
 ''', [
-      CompileTimeErrorCode.INVALID_CONSTANT,
-      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 47, 7),
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 77, 9),
     ]);
   }
 
   test_nonConstValueInInitializer_instanceCreation_inDifferentFile() async {
-    Source sourceA = addNamedSource('/a.dart', r'''
+    newFile('/test/lib/a.dart', content: '''
 import 'b.dart';
 const v = const MyClass();
 ''');
-    Source sourceB = addNamedSource('/b.dart', r'''
+    await assertErrorsInCode('''
 class MyClass {
   const MyClass([p = foo]);
 }
-''');
-    await computeAnalysisResult(sourceA);
-    assertNoErrors(sourceA);
-    await computeAnalysisResult(sourceB);
-    assertErrors(sourceB, [
-      CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE,
-      StaticWarningCode.UNDEFINED_IDENTIFIER
+''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 37, 3),
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 37, 3),
     ]);
   }
 
@@ -3352,7 +3876,9 @@
   const A.named(p);
   const A() : this.named(C);
 }
-''', [CompileTimeErrorCode.INVALID_CONSTANT]);
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 71, 1),
+    ]);
   }
 
   test_nonConstValueInInitializer_super() async {
@@ -3364,72 +3890,67 @@
   static var C;
   const B() : super(C);
 }
-''', [CompileTimeErrorCode.INVALID_CONSTANT]);
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 82, 1),
+    ]);
   }
 
   test_nonConstValueInInitializerFromDeferredLibrary_field() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
-const int c = 1;''',
-      r'''
+const int c = 1;''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class A {
   final int x;
   const A() : x = a.c;
 }
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.INVALID_CONSTANT
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 91, 3),
     ]);
   }
 
   test_nonConstValueInInitializerFromDeferredLibrary_field_nested() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 const int c = 1;
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class A {
   final int x;
   const A() : x = a.c + 1;
 }
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.INVALID_CONSTANT
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 91, 3),
     ]);
   }
 
   test_nonConstValueInInitializerFromDeferredLibrary_redirecting() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 const int c = 1;
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class A {
   const A.named(p);
   const A() : this.named(a.c);
 }
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.INVALID_CONSTANT
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 103, 3),
     ]);
   }
 
   test_nonConstValueInInitializerFromDeferredLibrary_super() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 const int c = 1;
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class A {
@@ -3438,9 +3959,8 @@
 class B extends A {
   const B() : super(a.c);
 }
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.INVALID_CONSTANT
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 114, 3),
     ]);
   }
 
@@ -3452,7 +3972,9 @@
 class B extends A {
   B() : super.named();
 }
-''', [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, 69, 13),
+    ]);
   }
 
   test_nonGenerativeConstructor_implicit() async {
@@ -3463,7 +3985,9 @@
 class B extends A {
   B();
 }
-''', [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, 57, 1),
+    ]);
   }
 
   test_nonGenerativeConstructor_implicit2() async {
@@ -3473,7 +3997,9 @@
 }
 class B extends A {
 }
-''', [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, 41, 1),
+    ]);
   }
 
   test_notEnoughRequiredArguments_const() async {
@@ -3484,7 +4010,9 @@
 main() {
   const A();
 }
-''', [CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
+''', [
+      error(CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS, 48, 2),
+    ]);
   }
 
   test_notEnoughRequiredArguments_const_super() async {
@@ -3495,13 +4023,18 @@
 class B extends A {
   const B() : super();
 }
-''', [CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
+''', [
+      error(CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS, 69, 2),
+    ]);
   }
 
   test_objectCannotExtendAnotherClass() async {
+    // TODO(brianwilkerson) Fix the offset and length.
     await assertErrorsInCode(r'''
 class Object extends List {}
-''', [CompileTimeErrorCode.OBJECT_CANNOT_EXTEND_ANOTHER_CLASS]);
+''', [
+      error(CompileTimeErrorCode.OBJECT_CANNOT_EXTEND_ANOTHER_CLASS, 0, 0),
+    ]);
   }
 
   test_optionalParameterInOperator_named() async {
@@ -3509,7 +4042,9 @@
 class A {
   operator +({p}) {}
 }
-''', [CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR]);
+''', [
+      error(CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR, 24, 1),
+    ]);
   }
 
   test_optionalParameterInOperator_positional() async {
@@ -3517,28 +4052,34 @@
 class A {
   operator +([p]) {}
 }
-''', [CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR]);
+''', [
+      error(CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR, 24, 1),
+    ]);
   }
 
   test_partOfNonPart() async {
-    newFile("/l2.dart", content: '''
+    newFile("/test/lib/l2.dart", content: '''
 library l2;
 ''');
     await assertErrorsInCode(r'''
 library l1;
 part 'l2.dart';
-''', [CompileTimeErrorCode.PART_OF_NON_PART]);
+''', [
+      error(CompileTimeErrorCode.PART_OF_NON_PART, 17, 9),
+    ]);
   }
 
   test_partOfNonPart_self() async {
     await assertErrorsInCode(r'''
 library lib;
 part 'test.dart';
-''', [CompileTimeErrorCode.PART_OF_NON_PART]);
+''', [
+      error(CompileTimeErrorCode.PART_OF_NON_PART, 18, 11),
+    ]);
   }
 
   test_prefix_assignment_compound_in_method() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 ''');
     await assertErrorsInCode('''
@@ -3548,11 +4089,13 @@
     p += 1;
   }
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 46, 1),
+    ]);
   }
 
   test_prefix_assignment_compound_not_in_method() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 ''');
     await assertErrorsInCode('''
@@ -3560,11 +4103,13 @@
 f() {
   p += 1;
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 32, 1),
+    ]);
   }
 
   test_prefix_assignment_in_method() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 ''');
     await assertErrorsInCode('''
@@ -3574,11 +4119,13 @@
     p = 1;
   }
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 46, 1),
+    ]);
   }
 
   test_prefix_assignment_not_in_method() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 ''');
     await assertErrorsInCode('''
@@ -3586,11 +4133,13 @@
 f() {
   p = 1;
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 32, 1),
+    ]);
   }
 
   test_prefix_conditionalPropertyAccess_call_loadLibrary() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 ''');
     await assertErrorsInCode('''
@@ -3598,11 +4147,13 @@
 f() {
   p?.loadLibrary();
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 41, 1),
+    ]);
   }
 
   test_prefix_conditionalPropertyAccess_get() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 var x;
 ''');
@@ -3611,11 +4162,13 @@
 f() {
   return p?.x;
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 39, 1),
+    ]);
   }
 
   test_prefix_conditionalPropertyAccess_get_loadLibrary() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 ''');
     await assertErrorsInCode('''
@@ -3623,11 +4176,13 @@
 f() {
   return p?.loadLibrary;
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 48, 1),
+    ]);
   }
 
   test_prefix_conditionalPropertyAccess_set() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 var x;
 ''');
@@ -3636,11 +4191,13 @@
 f() {
   p?.x = null;
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 32, 1),
+    ]);
   }
 
   test_prefix_conditionalPropertyAccess_set_loadLibrary() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 ''');
     await assertErrorsInCode('''
@@ -3648,11 +4205,13 @@
 f() {
   p?.loadLibrary = null;
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 41, 1),
+    ]);
   }
 
   test_prefixCollidesWithTopLevelMembers_functionTypeAlias() async {
-    newFile("/lib.dart", content: r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 class A{}
 ''');
@@ -3660,11 +4219,13 @@
 import 'lib.dart' as p;
 typedef p();
 p.A a;
-''', [CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, 32, 1),
+    ]);
   }
 
   test_prefixCollidesWithTopLevelMembers_topLevelFunction() async {
-    newFile("/lib.dart", content: r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 class A{}
 ''');
@@ -3672,11 +4233,13 @@
 import 'lib.dart' as p;
 p() {}
 p.A a;
-''', [CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, 24, 1),
+    ]);
   }
 
   test_prefixCollidesWithTopLevelMembers_topLevelVariable() async {
-    newFile("/lib.dart", content: r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 class A{}
 ''');
@@ -3684,11 +4247,13 @@
 import 'lib.dart' as p;
 var p = null;
 p.A a;
-''', [CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, 28, 1),
+    ]);
   }
 
   test_prefixCollidesWithTopLevelMembers_type() async {
-    newFile("/lib.dart", content: r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 class A{}
 ''');
@@ -3696,11 +4261,13 @@
 import 'lib.dart' as p;
 class p {}
 p.A a;
-''', [CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, 30, 1),
+    ]);
   }
 
   test_prefixNotFollowedByDot() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 ''');
     await assertErrorsInCode('''
@@ -3708,11 +4275,13 @@
 f() {
   return p;
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 39, 1),
+    ]);
   }
 
   test_prefixNotFollowedByDot_compoundAssignment() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 ''');
     await assertErrorsInCode('''
@@ -3720,11 +4289,13 @@
 f() {
   p += 1;
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 32, 1),
+    ]);
   }
 
   test_prefixNotFollowedByDot_conditionalMethodInvocation() async {
-    newFile('/lib.dart', content: '''
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 g() {}
 ''');
@@ -3733,14 +4304,18 @@
 f() {
   p?.g();
 }
-''', [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+''', [
+      error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 32, 1),
+    ]);
   }
 
   test_privateCollisionInClassTypeAlias_mixinAndMixin() {
     return _privateCollisionInMixinApplicationTest('''
 import 'lib1.dart';
 class C = Object with A, B;
-''');
+''', [
+      error(CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION, 45, 1),
+    ]);
   }
 
   test_privateCollisionInClassTypeAlias_mixinAndMixin_indirect() {
@@ -3748,28 +4323,36 @@
 import 'lib1.dart';
 class C = Object with A;
 class D = C with B;
-''');
+''', [
+      error(CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION, 62, 1),
+    ]);
   }
 
   test_privateCollisionInClassTypeAlias_superclassAndMixin() {
     return _privateCollisionInMixinApplicationTest('''
 import 'lib1.dart';
 class C = A with B;
-''');
+''', [
+      error(CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION, 37, 1),
+    ]);
   }
 
   test_privateCollisionInClassTypeAlias_superclassAndMixin_same() {
     return _privateCollisionInMixinApplicationTest('''
 import 'lib1.dart';
 class C = A with A;
-''');
+''', [
+      error(CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION, 37, 1),
+    ]);
   }
 
   test_privateCollisionInMixinApplication_mixinAndMixin() {
     return _privateCollisionInMixinApplicationTest('''
 import 'lib1.dart';
 class C extends Object with A, B {}
-''');
+''', [
+      error(CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION, 51, 1),
+    ]);
   }
 
   test_privateCollisionInMixinApplication_mixinAndMixin_indirect() {
@@ -3777,27 +4360,35 @@
 import 'lib1.dart';
 class C extends Object with A {}
 class D extends C with B {}
-''');
+''', [
+      error(CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION, 76, 1),
+    ]);
   }
 
   test_privateCollisionInMixinApplication_superclassAndMixin() {
     return _privateCollisionInMixinApplicationTest('''
 import 'lib1.dart';
 class C extends A with B {}
-''');
+''', [
+      error(CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION, 43, 1),
+    ]);
   }
 
   test_privateCollisionInMixinApplication_superclassAndMixin_same() {
     return _privateCollisionInMixinApplicationTest('''
 import 'lib1.dart';
 class C extends A with A {}
-''');
+''', [
+      error(CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION, 43, 1),
+    ]);
   }
 
   test_privateOptionalParameter() async {
     await assertErrorsInCode('''
 f({var _p}) {}
-''', [CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER]);
+''', [
+      error(CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER, 3, 6),
+    ]);
   }
 
   test_privateOptionalParameter_fieldFormal() async {
@@ -3806,13 +4397,18 @@
   var _p;
   A({this._p: 0});
 }
-''', [CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER]);
+''', [
+      error(HintCode.UNUSED_FIELD, 16, 2),
+      error(CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER, 25, 7),
+    ]);
   }
 
   test_privateOptionalParameter_withDefaultValue() async {
     await assertErrorsInCode('''
 f({_p : 0}) {}
-''', [CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER]);
+''', [
+      error(CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER, 3, 2),
+    ]);
   }
 
   test_recursiveCompileTimeConstant() async {
@@ -3821,7 +4417,9 @@
   const A();
   final m = const A();
 }
-''', [CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT]);
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, 31, 1),
+    ]);
   }
 
   test_recursiveCompileTimeConstant_cycle() async {
@@ -3829,16 +4427,16 @@
 const x = y + 1;
 const y = x + 1;
 ''', [
-      CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT,
-      CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT,
-      StrongModeCode.TOP_LEVEL_CYCLE,
-      StrongModeCode.TOP_LEVEL_CYCLE,
+      error(CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, 6, 1),
+      error(StrongModeCode.TOP_LEVEL_CYCLE, 10, 1),
+      error(CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, 23, 1),
+      error(StrongModeCode.TOP_LEVEL_CYCLE, 27, 1),
     ]);
   }
 
   test_recursiveCompileTimeConstant_fromMapLiteral() async {
     newFile(
-      '/constants.dart',
+      '/test/lib/constants.dart',
       content: r'''
 const int x = y;
 const int y = x;
@@ -3858,15 +4456,17 @@
   const C() : x = y;
   final x;
 }
-''', [CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT]);
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, 6, 1),
+    ]);
   }
 
   test_recursiveCompileTimeConstant_singleVariable() async {
     await assertErrorsInCode(r'''
 const x = x;
 ''', [
-      CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT,
-      StrongModeCode.TOP_LEVEL_CYCLE
+      error(CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, 6, 1),
+      error(StrongModeCode.TOP_LEVEL_CYCLE, 10, 1),
     ]);
   }
 
@@ -3878,8 +4478,8 @@
   ],
 ];
 ''', [
-      CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT,
-      StrongModeCode.TOP_LEVEL_CYCLE,
+      error(CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, 6, 5),
+      error(StrongModeCode.TOP_LEVEL_CYCLE, 39, 5),
     ]);
   }
 
@@ -3890,8 +4490,8 @@
   A.b() : this.a();
 }
 ''', [
-      CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT
+      error(CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT, 20, 8),
+      error(CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT, 40, 8),
     ]);
   }
 
@@ -3900,7 +4500,9 @@
 class A {
   A() : this();
 }
-''', [CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT]);
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT, 18, 6),
+    ]);
   }
 
   test_recursiveFactoryRedirect() async {
@@ -3915,12 +4517,12 @@
   factory C() = B;
 }
 ''', [
-      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 39, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 50, 1),
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 83, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 94, 1),
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 127, 1),
     ]);
   }
 
@@ -3929,7 +4531,9 @@
 class A {
   factory A() = A;
 }
-''', [CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT]);
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 26, 1),
+    ]);
   }
 
   test_recursiveFactoryRedirect_diverging() async {
@@ -3943,7 +4547,9 @@
 main() {
   const C<int>();
 }
-''', [CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT]);
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 35, 7),
+    ]);
   }
 
   test_recursiveFactoryRedirect_generic() async {
@@ -3958,12 +4564,12 @@
   factory C() = B;
 }
 ''', [
-      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 45, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 56, 1),
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 95, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 106, 1),
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 145, 1),
     ]);
   }
 
@@ -3979,12 +4585,12 @@
   factory C.nameC() = B.nameB;
 }
 ''', [
-      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 45, 7),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 62, 1),
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 101, 7),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 118, 1),
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 157, 7),
     ]);
   }
 
@@ -4004,10 +4610,10 @@
   factory C() = B;
 }
 ''', [
-      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 37, 1),
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 70, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 81, 1),
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 117, 1),
     ]);
   }
 
@@ -4016,8 +4622,10 @@
 class A {
   A() : this.noSuchConstructor();
 }
-''', [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR],
-        verify: false);
+''', [
+      error(CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR, 18,
+          24),
+    ]);
   }
 
   test_redirectGenerativeToNonGenerativeConstructor() async {
@@ -4026,7 +4634,13 @@
   A() : this.x();
   factory A.x() => null;
 }
-''', [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR]);
+''', [
+      error(
+          CompileTimeErrorCode
+              .REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR,
+          18,
+          8),
+    ]);
   }
 
   test_redirectToMissingConstructor_named() async {
@@ -4037,7 +4651,9 @@
 class B {
   const factory B() = A.name;
 }
-''', [CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR], verify: false);
+''', [
+      error(CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR, 65, 6),
+    ]);
   }
 
   test_redirectToMissingConstructor_unnamed() async {
@@ -4048,7 +4664,9 @@
 class B {
   const factory B() = A;
 }
-''', [CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR, 70, 1),
+    ]);
   }
 
   test_redirectToNonClass_notAType() async {
@@ -4057,7 +4675,9 @@
 class B {
   const factory B() = A;
 }
-''', [CompileTimeErrorCode.REDIRECT_TO_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.REDIRECT_TO_NON_CLASS, 39, 1),
+    ]);
   }
 
   test_redirectToNonClass_undefinedIdentifier() async {
@@ -4065,7 +4685,9 @@
 class B {
   const factory B() = A;
 }
-''', [CompileTimeErrorCode.REDIRECT_TO_NON_CLASS]);
+''', [
+      error(CompileTimeErrorCode.REDIRECT_TO_NON_CLASS, 32, 1),
+    ]);
   }
 
   test_redirectToNonConstConstructor() async {
@@ -4074,7 +4696,9 @@
   A.a() {}
   const factory A.b() = A.a;
 }
-''', [CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR, 45, 3),
+    ]);
   }
 
   test_referencedBeforeDeclaration_hideInBlock_comment() async {
@@ -4095,7 +4719,9 @@
   v() {}
 }
 print(x) {}
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 28, 1),
+    ]);
   }
 
   test_referencedBeforeDeclaration_hideInBlock_local() async {
@@ -4106,7 +4732,9 @@
   var v = 2;
 }
 print(x) {}
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 28, 1),
+    ]);
   }
 
   test_referencedBeforeDeclaration_hideInBlock_subBlock() async {
@@ -4119,7 +4747,9 @@
   var v = 2;
 }
 print(x) {}
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 34, 1),
+    ]);
   }
 
   test_referencedBeforeDeclaration_inInitializer_closure() async {
@@ -4127,7 +4757,9 @@
 main() {
   var v = () => v;
 }
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 25, 1),
+    ]);
   }
 
   test_referencedBeforeDeclaration_inInitializer_directly() async {
@@ -4135,7 +4767,9 @@
 main() {
   var v = v;
 }
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 19, 1),
+    ]);
   }
 
   test_referencedBeforeDeclaration_type_localFunction() async {
@@ -4143,8 +4777,11 @@
 void testTypeRef() {
   String s = '';
   int String(int x) => x + 1;
+  print(s + String);
 }
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 23, 6),
+    ]);
   }
 
   test_referencedBeforeDeclaration_type_localVariable() async {
@@ -4152,8 +4789,11 @@
 void testTypeRef() {
   String s = '';
   var String = '';
+  print(s + String);
 }
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 23, 6),
+    ]);
   }
 
   test_rethrowOutsideCatch() async {
@@ -4161,7 +4801,9 @@
 f() {
   rethrow;
 }
-''', [CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH]);
+''', [
+      error(CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, 8, 7),
+    ]);
   }
 
   test_returnInGenerativeConstructor() async {
@@ -4169,7 +4811,9 @@
 class A {
   A() { return 0; }
 }
-''', [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR, 25, 1),
+    ]);
   }
 
   test_returnInGenerativeConstructor_expressionFunctionBody() async {
@@ -4177,7 +4821,9 @@
 class A {
   A() => null;
 }
-''', [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR, 16, 8),
+    ]);
   }
 
   test_returnInGenerator_asyncStar() async {
@@ -4186,8 +4832,8 @@
   return 0;
 }
 ''', [
-      CompileTimeErrorCode.RETURN_IN_GENERATOR,
-      CompileTimeErrorCode.RETURN_IN_GENERATOR
+      error(CompileTimeErrorCode.RETURN_IN_GENERATOR, 15, 9),
+      error(CompileTimeErrorCode.RETURN_IN_GENERATOR, 15, 6),
     ]);
   }
 
@@ -4197,36 +4843,36 @@
   return 0;
 }
 ''', [
-      CompileTimeErrorCode.RETURN_IN_GENERATOR,
-      CompileTimeErrorCode.RETURN_IN_GENERATOR
+      error(CompileTimeErrorCode.RETURN_IN_GENERATOR, 14, 9),
+      error(CompileTimeErrorCode.RETURN_IN_GENERATOR, 14, 6),
     ]);
   }
 
   test_sharedDeferredPrefix() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile('/test/lib/lib1.dart', content: '''
 library lib1;
 f1() {}
-''',
-      r'''
+''');
+    newFile('/test/lib/lib2.dart', content: '''
 library lib2;
 f2() {}
-''',
-      r'''
+''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as lib;
 import 'lib2.dart' as lib;
 main() { lib.f1(); lib.f2(); }
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.SHARED_DEFERRED_PREFIX
+''', [
+      error(CompileTimeErrorCode.SHARED_DEFERRED_PREFIX, 33, 8),
     ]);
   }
 
   test_superInInvalidContext_binaryExpression() async {
     await assertErrorsInCode('''
 var v = super + 0;
-''', [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
+''', [
+      error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 8, 5),
+    ]);
   }
 
   test_superInInvalidContext_constructorFieldInitializer() async {
@@ -4238,7 +4884,9 @@
   var f;
   B() : f = super.m();
 }
-''', [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT], verify: false);
+''', [
+      error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 62, 5),
+    ]);
   }
 
   test_superInInvalidContext_factoryConstructor() async {
@@ -4252,7 +4900,9 @@
     return null;
   }
 }
-''', [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT], verify: false);
+''', [
+      error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 61, 5),
+    ]);
   }
 
   test_superInInvalidContext_instanceVariableInitializer() async {
@@ -4263,7 +4913,9 @@
 class B extends A {
  var b = super.a;
 }
-''', [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
+''', [
+      error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 50, 5),
+    ]);
   }
 
   test_superInInvalidContext_staticMethod() async {
@@ -4274,7 +4926,9 @@
 class B extends A {
   static n() { return super.m(); }
 }
-''', [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT], verify: false);
+''', [
+      error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 70, 5),
+    ]);
   }
 
   test_superInInvalidContext_staticVariableInitializer() async {
@@ -4285,7 +4939,9 @@
 class B extends A {
   static int b = super.a;
 }
-''', [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
+''', [
+      error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 69, 5),
+    ]);
   }
 
   test_superInInvalidContext_topLevelFunction() async {
@@ -4293,13 +4949,17 @@
 f() {
   super.f();
 }
-''', [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
+''', [
+      error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 8, 5),
+    ]);
   }
 
   test_superInInvalidContext_topLevelVariableInitializer() async {
     await assertErrorsInCode('''
 var v = super.y;
-''', [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
+''', [
+      error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 8, 5),
+    ]);
   }
 
   test_superInitializerInObject() async {
@@ -4307,7 +4967,9 @@
 class Object {
   Object() : super();
 }
-''', [CompileTimeErrorCode.SUPER_INITIALIZER_IN_OBJECT]);
+''', [
+      error(CompileTimeErrorCode.SUPER_INITIALIZER_IN_OBJECT, 0, 0),
+    ]);
   }
 
   test_superInRedirectingConstructor_redirectionSuper() async {
@@ -4317,7 +4979,9 @@
   B() : this.name(), super();
   B.name() {}
 }
-''', [CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR, 42, 7),
+    ]);
   }
 
   test_superInRedirectingConstructor_superRedirection() async {
@@ -4328,8 +4992,8 @@
   B.name() {}
 }
 ''', [
-      CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR,
-      StrongModeCode.INVALID_SUPER_INVOCATION
+      error(StrongModeCode.INVALID_SUPER_INVOCATION, 29, 7),
+      error(CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR, 29, 7),
     ]);
   }
 
@@ -4341,19 +5005,21 @@
 var s4 = const Symbol('x', 'y');
 var s5 = const Symbol('x', foo: 'x');
 ''', [
-      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
-      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
-      CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS,
-      CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS,
-      CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 9, 17),
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 37, 15),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 50, 1),
+      error(CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS, 75, 2),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 100, 10),
+      error(CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, 139, 3),
     ]);
   }
 
   test_test_fieldInitializerOutsideConstructor_topLevelFunction() async {
     await assertErrorsInCode(r'''
 f(this.x(y)) {}
-''', [CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, 2, 9),
+    ]);
   }
 
   test_typeAliasCannotReferenceItself_11987() async {
@@ -4362,10 +5028,11 @@
 typedef void G(List<F> l);
 main() {
   F foo(G g) => g;
+  foo(null);
 }
 ''', [
-      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
-      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 26),
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 27, 26),
     ]);
   }
 
@@ -4385,7 +5052,9 @@
   test_typeAliasCannotReferenceItself_functionTypedParameter_returnType() async {
     await assertErrorsInCode('''
 typedef A(A b());
-''', [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 17),
+    ]);
   }
 
   test_typeAliasCannotReferenceItself_generic() async {
@@ -4394,35 +5063,44 @@
 typedef G = void Function(List<F> l);
 main() {
   F foo(G g) => g;
+  foo(null);
 }
 ''', [
-      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
-      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 37),
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 38, 37),
     ]);
   }
 
   test_typeAliasCannotReferenceItself_parameterType_named() async {
     await assertErrorsInCode('''
 typedef A({A a});
-''', [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 17),
+    ]);
   }
 
   test_typeAliasCannotReferenceItself_parameterType_positional() async {
     await assertErrorsInCode('''
 typedef A([A a]);
-''', [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 17),
+    ]);
   }
 
   test_typeAliasCannotReferenceItself_parameterType_required() async {
     await assertErrorsInCode('''
 typedef A(A a);
-''', [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 15),
+    ]);
   }
 
   test_typeAliasCannotReferenceItself_parameterType_typeArgument() async {
     await assertErrorsInCode('''
 typedef A(List<A> a);
-''', [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 21),
+    ]);
   }
 
   test_typeAliasCannotReferenceItself_returnClass_withTypeAlias() async {
@@ -4439,7 +5117,9 @@
   test_typeAliasCannotReferenceItself_returnType() async {
     await assertErrorsInCode('''
 typedef A A();
-''', [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 14),
+    ]);
   }
 
   test_typeAliasCannotReferenceItself_returnType_indirect() async {
@@ -4447,18 +5127,23 @@
 typedef B A();
 typedef A B();
 ''', [
-      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
-      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 14),
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 15, 14),
     ]);
   }
 
   test_typeAliasCannotReferenceItself_typeVariableBounds() async {
+    var errors = [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 30),
+    ];
+    if (!AnalysisDriver.useSummary2) {
+      errors.add(
+        error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 22, 3),
+      );
+    }
     await assertErrorsInCode('''
 typedef A<T extends A<int>>();
-''', [
-      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
-      StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
-    ]);
+''', errors);
   }
 
   test_typeArgumentNotMatchingBounds_const() async {
@@ -4469,15 +5154,17 @@
   const G();
 }
 f() { return const G<B>(); }
-''', [CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 81, 1),
+    ]);
   }
 
   test_typedef_infiniteParameterBoundCycle() async {
     await assertErrorsInCode(r'''
 typedef F<X extends F> = F Function();
 ''', [
-      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
-      StrongModeCode.NOT_INSTANTIATED_BOUND,
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 38),
+      error(StrongModeCode.NOT_INSTANTIATED_BOUND, 20, 1),
     ]);
   }
 
@@ -4486,7 +5173,9 @@
 @unresolved
 main() {
 }
-''', [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_ANNOTATION, 0, 11),
+    ]);
   }
 
   test_undefinedAnnotation_unresolved_invocation() async {
@@ -4494,7 +5183,9 @@
 @Unresolved()
 main() {
 }
-''', [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_ANNOTATION, 0, 13),
+    ]);
   }
 
   test_undefinedAnnotation_unresolved_prefixedIdentifier() async {
@@ -4503,7 +5194,9 @@
 @p.unresolved
 main() {
 }
-''', [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_ANNOTATION, 25, 13),
+    ]);
   }
 
   test_undefinedAnnotation_useLibraryScope() async {
@@ -4512,7 +5205,9 @@
 class A {
   static const foo = null;
 }
-''', [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_ANNOTATION, 0, 4),
+    ]);
   }
 
   test_undefinedClass_const() async {
@@ -4520,7 +5215,9 @@
 f() {
   return const A();
 }
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 21, 1),
+    ]);
   }
 
   test_undefinedConstructorInInitializer_explicit_named() async {
@@ -4529,8 +5226,9 @@
 class B extends A {
   B() : super.named();
 }
-''', [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER],
-        verify: false);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER, 39, 13),
+    ]);
   }
 
   test_undefinedConstructorInInitializer_explicit_unnamed() async {
@@ -4541,7 +5239,10 @@
 class B extends A {
   B() : super();
 }
-''', [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
+          55, 7),
+    ]);
   }
 
   test_undefinedConstructorInInitializer_implicit() async {
@@ -4552,7 +5253,10 @@
 class B extends A {
   B();
 }
-''', [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
+          49, 1),
+    ]);
   }
 
   test_undefinedNamedParameter() async {
@@ -4563,68 +5267,84 @@
 main() {
   const A(p: 0);
 }
-''', [CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER]);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, 44, 1),
+    ]);
   }
 
   test_uriDoesNotExist_export() async {
     await assertErrorsInCode('''
 export 'unknown.dart';
-''', [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+''', [
+      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 14),
+    ]);
   }
 
   test_uriDoesNotExist_import() async {
     await assertErrorsInCode('''
 import 'unknown.dart';
-''', [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+''', [
+      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 14),
+    ]);
   }
 
   test_uriDoesNotExist_import_appears_after_deleting_target() async {
-    Source target = addNamedSource("/target.dart", '''
-''');
-    Source test = addSource('''
+    String filePath = newFile('/test/lib/target.dart').path;
+
+    await assertErrorsInCode('''
 import 'target.dart';
-''');
-    await computeAnalysisResult(test);
-    assertErrors(test, [HintCode.UNUSED_IMPORT]);
+''', [
+      error(HintCode.UNUSED_IMPORT, 7, 13),
+    ]);
 
     // Remove the overlay in the same way as AnalysisServer.
-    deleteFile(target.fullName);
-    driver.removeFile(target.fullName);
+    deleteFile(filePath);
+    driver.removeFile(filePath);
 
-    await computeAnalysisResult(test);
-    assertErrors(test, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+    await resolveTestFile();
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    errorListener.addAll(result.errors);
+    errorListener.assertErrors([
+      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 13),
+    ]);
   }
 
+  @failingTest
   test_uriDoesNotExist_import_disappears_when_fixed() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 import 'target.dart';
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+''', [
+      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 13),
+    ]);
 
-    String targetPath = convertPath('/target.dart');
-    // Add an overlay in the same way as AnalysisServer.
-    fileContentOverlay[targetPath] = '';
-    driver.changeFile(targetPath);
+    newFile('/test/lib/target.dart');
 
     // Make sure the error goes away.
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_IMPORT]);
+    // TODO(brianwilkerson) The error does not go away, possibly because the
+    //  file is not being reanalyzed.
+    await resolveTestFile();
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    errorListener.addAll(result.errors);
+    errorListener.assertErrors([
+      error(HintCode.UNUSED_IMPORT, 0, 0),
+    ]);
   }
 
   test_uriDoesNotExist_part() async {
     await assertErrorsInCode(r'''
 library lib;
 part 'unknown.dart';
-''', [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+''', [
+      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 18, 14),
+    ]);
   }
 
   test_uriWithInterpolation_constant() async {
     await assertErrorsInCode('''
 import 'stuff_\$platform.dart';
 ''', [
-      CompileTimeErrorCode.URI_WITH_INTERPOLATION,
-      StaticWarningCode.UNDEFINED_IDENTIFIER
+      error(CompileTimeErrorCode.URI_WITH_INTERPOLATION, 7, 22),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 15, 8),
     ]);
   }
 
@@ -4632,7 +5352,9 @@
     await assertErrorsInCode(r'''
 library lib;
 part '${'a'}.dart';
-''', [CompileTimeErrorCode.URI_WITH_INTERPOLATION]);
+''', [
+      error(CompileTimeErrorCode.URI_WITH_INTERPOLATION, 18, 13),
+    ]);
   }
 
   test_wrongNumberOfParametersForOperator1() async {
@@ -4658,7 +5380,10 @@
 class A {
   operator -(a, b) {}
 }
-''', [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS]);
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS,
+          21, 1),
+    ]);
   }
 
   test_wrongNumberOfParametersForOperator_tilde() async {
@@ -4669,25 +5394,33 @@
   test_wrongNumberOfParametersForSetter_function_named() async {
     await assertErrorsInCode('''
 set x({p}) {}
-''', [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, 4, 1),
+    ]);
   }
 
   test_wrongNumberOfParametersForSetter_function_optional() async {
     await assertErrorsInCode('''
 set x([p]) {}
-''', [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, 4, 1),
+    ]);
   }
 
   test_wrongNumberOfParametersForSetter_function_tooFew() async {
     await assertErrorsInCode('''
 set x() {}
-''', [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, 4, 1),
+    ]);
   }
 
   test_wrongNumberOfParametersForSetter_function_tooMany() async {
     await assertErrorsInCode('''
 set x(a, b) {}
-''', [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, 4, 1),
+    ]);
   }
 
   test_wrongNumberOfParametersForSetter_method_named() async {
@@ -4695,7 +5428,9 @@
 class A {
   set x({p}) {}
 }
-''', [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, 16, 1),
+    ]);
   }
 
   test_wrongNumberOfParametersForSetter_method_optional() async {
@@ -4703,7 +5438,9 @@
 class A {
   set x([p]) {}
 }
-''', [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, 16, 1),
+    ]);
   }
 
   test_wrongNumberOfParametersForSetter_method_tooFew() async {
@@ -4711,7 +5448,9 @@
 class A {
   set x() {}
 }
-''', [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, 16, 1),
+    ]);
   }
 
   test_wrongNumberOfParametersForSetter_method_tooMany() async {
@@ -4719,7 +5458,9 @@
 class A {
   set x(a, b) {}
 }
-''', [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
+''', [
+      error(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, 16, 1),
+    ]);
   }
 
   test_yield_used_as_identifier_in_async_method() async {
@@ -4727,7 +5468,10 @@
 f() async {
   var yield = 1;
 }
-''', [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+''', [
+      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 18, 5),
+    ]);
   }
 
   test_yield_used_as_identifier_in_async_star_method() async {
@@ -4735,7 +5479,10 @@
 f() async* {
   var yield = 1;
 }
-''', [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+''', [
+      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 19, 5),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 19, 5),
+    ]);
   }
 
   test_yield_used_as_identifier_in_sync_star_method() async {
@@ -4743,7 +5490,10 @@
 f() sync* {
   var yield = 1;
 }
-''', [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+''', [
+      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 18, 5),
+    ]);
   }
 
   test_yieldEachInNonGenerator_async() async {
@@ -4753,7 +5503,9 @@
 f() async {
   yield* 0;
 }
-''', [CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR]);
+''', [
+      error(CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR, 0, 0),
+    ]);
   }
 
   test_yieldEachInNonGenerator_sync() async {
@@ -4763,7 +5515,9 @@
 f() {
   yield* 0;
 }
-''', [CompileTimeErrorCode.YIELD_IN_NON_GENERATOR]);
+''', [
+      error(CompileTimeErrorCode.YIELD_IN_NON_GENERATOR, 0, 0),
+    ]);
   }
 
   test_yieldInNonGenerator_async() async {
@@ -4773,7 +5527,9 @@
 f() async {
   yield 0;
 }
-''', [CompileTimeErrorCode.YIELD_IN_NON_GENERATOR]);
+''', [
+      error(CompileTimeErrorCode.YIELD_IN_NON_GENERATOR, 0, 0),
+    ]);
   }
 
   test_yieldInNonGenerator_sync() async {
@@ -4783,14 +5539,18 @@
 f() {
   yield 0;
 }
-''', [CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR]);
+''', [
+      error(CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR, 0, 0),
+    ]);
   }
 
   Future<void> _check_constEvalThrowsException_binary_null(
       String expr, bool resolved) async {
     await assertErrorsInCode('''
 const C = $expr;
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION], verify: false);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 10, 8),
+    ]);
   }
 
   Future<void> _check_constEvalTypeBoolOrInt_binary(String expr) async {
@@ -4798,8 +5558,9 @@
 const int a = 0;
 const _ = $expr;
 ''', [
-      CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(HintCode.UNUSED_ELEMENT, 23, 1),
+      error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT, 27, 6),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 31, 2),
     ]);
   }
 
@@ -4808,8 +5569,9 @@
 const int a = 0;
 const _ = $expr;
 ''', [
-      CompileTimeErrorCode.CONST_EVAL_TYPE_INT,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(HintCode.UNUSED_ELEMENT, 23, 1),
+      error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT, 27, 6),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 31, 2),
     ]);
   }
 
@@ -4818,8 +5580,9 @@
 const num a = 0;
 const _ = $expr;
 ''', [
-      CompileTimeErrorCode.CONST_EVAL_TYPE_NUM,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(HintCode.UNUSED_ELEMENT, 23, 1),
+      error(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM, 27, 6),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 31, 2),
     ]);
   }
 
@@ -4829,7 +5592,10 @@
 class A {
   operator $name($parameters) {}
 }
-''', [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR]);
+''', [
+      error(
+          CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR, 21, 1),
+    ]);
   }
 
   Future<void> _check_wrongNumberOfParametersForOperator1(String name) async {
@@ -4837,8 +5603,9 @@
     await _check_wrongNumberOfParametersForOperator(name, 'a, b');
   }
 
-  Future<void> _privateCollisionInMixinApplicationTest(String testCode) async {
-    newFile('/lib1.dart', content: '''
+  Future<void> _privateCollisionInMixinApplicationTest(
+      String testCode, List<ExpectedError> expectedErrors) async {
+    newFile('/test/lib/lib1.dart', content: '''
 class A {
   int _x;
 }
@@ -4847,7 +5614,6 @@
   int _x;
 }
 ''');
-    await assertErrorsInCode(testCode,
-        [CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION]);
+    await assertErrorsInCode(testCode, expectedErrors);
   }
 }
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 f8b7ac6..7346b25 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -2,10 +2,8 @@
 // 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:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../src/dart/resolution/driver_resolution.dart';
@@ -79,271 +77,322 @@
 
 @reflectiveTest
 class CompileTimeErrorCodeTest_WithUIAsCode extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_defaultValueInFunctionTypeAlias_new_named() async {
     // This test used to fail with UI as code enabled. Test the fix here.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 typedef F = int Function({Map<String, String> m: const {}});
 ''', [
-      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
+      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 47, 1),
     ]);
   }
 
   test_defaultValueInFunctionTypeAlias_new_named_ambiguous() async {
     // Test that the strong checker does not crash when given an ambiguous
     // set or map literal.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 typedef F = int Function({Object m: const {1, 2: 3}});
 ''', [
-      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
-      CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
+      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 34, 1),
+      error(CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH, 36, 15),
     ]);
   }
 }
 
 @reflectiveTest
 class ControlFlowCollectionsTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [EnableString.control_flow_collections];
-
   test_awaitForIn_declaredVariableWrongType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 import 'dart:async';
 f() async {
   Stream<String> stream;
   await for (int i in stream) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 75, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 80, 6),
+    ]);
   }
 
   test_awaitForIn_existingVariableWrongType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 import 'dart:async';
 f() async {
   Stream<String> stream;
   int i;
   await for (i in stream) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 64, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 85, 6),
+    ]);
   }
 
   test_awaitForIn_notStream() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 f() async {
   await for (var i in true) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 29, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, 34, 4),
+    ]);
   }
 
   test_duplicateDefinition_for_initializers() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   for (int i = 0, i = 0; i < 5;) {}
 }
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 24, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 24, 1),
+    ]);
   }
 
   test_expectedOneListTypeArgument() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   <int, int>[];
-}''', [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS]);
+}''', [
+      error(StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS, 11, 10),
+    ]);
   }
 
   test_expectedOneSetTypeArgument() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   <int, int, int>{2, 3};
-}''', [StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS]);
+}''', [
+      error(StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS, 11, 15),
+    ]);
   }
 
   test_expectedTwoMapTypeArguments_three_ambiguous() async {
     // TODO(brianwilkerson) We probably need a new error code for "expected
     //  either one or two type arguments" to handle the ambiguous case.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   <int, int, int>{};
-}''', [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
+}''', [
+      error(StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, 11, 15),
+    ]);
   }
 
   test_expectedTwoMapTypeArguments_three_map() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   <int, int, int>{1:2};
-}''', [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
+}''', [
+      error(StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, 11, 15),
+    ]);
   }
 
   test_forIn_declaredVariableWrongType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 f() {
   for (int i in <String>[]) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 22, 10),
+    ]);
   }
 
   test_forIn_existingVariableWrongType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 f() {
   int i;
   for (i in <String>[]) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 12, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 27, 10),
+    ]);
   }
 
   test_forIn_notIterable() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 f() {
   for (var i in true) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, 22, 4),
+    ]);
   }
 
   test_forIn_typeBoundBad() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class Foo<T extends Iterable<int>> {
   void method(T iterable) {
     for (String i in iterable) {}
   }
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 81, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 86, 8),
+    ]);
   }
 
   test_forInWithConstVariable_forEach_identifier() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   const x = 0;
   for (x in [0, 1, 2]) {}
 }
-''', [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, 28, 1),
+    ]);
   }
 
   test_forInWithConstVariable_forEach_loopVariable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   for (const x in [0, 1, 2]) {}
 }
-''', [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+''', [
+      error(CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, 13, 7),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 19, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfInForeachIterableError() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 void main() {
   void x;
   for (var v in x) {}
 }
-''', [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 35, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 40, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInForeachVariableError() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 void main() {
   void x;
   var y;
   for (y in x) {}
 }
-''', [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 30, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 45, 1),
+    ]);
   }
 
   test_invalidTypeArgumentInConstList() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<E> {
   m() {
     return const <E>[];
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST, 39, 1),
+    ]);
   }
 
   test_invalidTypeArgumentInConstMap_key() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<E> {
   m() {
     return const <E, String>{};
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP, 39, 1),
+    ]);
   }
 
   test_invalidTypeArgumentInConstMap_value() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<E> {
   m() {
     return const <String, E>{};
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP, 47, 1),
+    ]);
   }
 
   test_invalidTypeArgumentInConstSet_class() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<E> {
   m() {
     return const <E>{};
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET, 39, 1),
+    ]);
   }
 
   test_listElementTypeNotAssignable_const() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <String>[42];
-''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 23, 2),
+    ]);
   }
 
   test_mapValueTypeNotAssignable_const() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <String, String>{'a' : 2};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 37, 1),
+    ]);
   }
 
   test_nonBoolCondition_for_declaration() async {
     // https://github.com/dart-lang/sdk/issues/24713
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   for (int i = 0; 3;) {}
 }
-''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(StaticTypeWarningCode.NON_BOOL_CONDITION, 24, 1),
+    ]);
   }
 
   test_nonBoolCondition_for_expression() async {
     // https://github.com/dart-lang/sdk/issues/24713
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   int i;
   for (i = 0; 3;) {}
-}''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 12, 1),
+      error(StaticTypeWarningCode.NON_BOOL_CONDITION, 29, 1),
+    ]);
   }
 
   test_nonConstMapAsExpressionStatement_begin() async {
     // TODO(danrubel) Fasta is not recovering well.
     // Ideally we would produce a single diagnostic:
     // CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   {'a' : 0, 'b' : 1}.length;
 }
 ''', [
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
+      error(ParserErrorCode.EXPECTED_TOKEN, 9, 3),
+      error(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 18, 3),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 24, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
     ]);
   }
 
@@ -351,43 +400,47 @@
     // TODO(danrubel) Fasta is not recovering well.
     // Ideally we would produce a single diagnostic:
     // CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   {'a' : 0, 'b' : 1};
 }
 ''', [
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
+      error(ParserErrorCode.EXPECTED_TOKEN, 9, 3),
+      error(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 18, 3),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 24, 1),
     ]);
   }
 
   test_setElementTypeNotAssignable_const() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <String>{42};
-''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 23, 2),
+    ]);
   }
 }
 
 @reflectiveTest
 class InvalidTypeArgumentInConstSetTest extends DriverResolutionTest {
   test_class() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<E> {
   m() {
     return const <E>{};
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET, 39, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index 8cb223e..53c7e30 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
@@ -1146,6 +1147,7 @@
     _definingLibrary.definingCompilationUnit = unit;
     _visitor = new ResolverVisitor(
         inheritance, _definingLibrary, source, _typeProvider, _listener,
+        featureSet: FeatureSet.forTesting(),
         nameScope: new LibraryScope(_definingLibrary));
     _resolver = _visitor.elementResolver;
   }
diff --git a/pkg/analyzer/test/generated/invalid_code_test.dart b/pkg/analyzer/test/generated/invalid_code_test.dart
index 3d24f99..73fb3ef 100644
--- a/pkg/analyzer/test/generated/invalid_code_test.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -4,12 +4,9 @@
 
 import 'dart:async';
 
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'resolver_test_case.dart';
+import '../src/dart/resolution/driver_resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -17,22 +14,15 @@
   });
 }
 
-/**
- * Tests for various end-to-end cases when invalid code caused exceptions
- * in one or another Analyzer subsystem. We are not interested not in specific
- * errors generated, but we want to make sure that there is at least one,
- * and analysis finishes without exceptions.
- */
+/// Tests for various end-to-end cases when invalid code caused exceptions
+/// in one or another Analyzer subsystem. We are not interested not in specific
+/// errors generated, but we want to make sure that there is at least one,
+/// and analysis finishes without exceptions.
 @reflectiveTest
-class InvalidCodeTest extends ResolverTestCase {
-  @override
-  AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
-
-  /**
-   * This code results in a method with the empty name, and the default
-   * constructor, which also has the empty name. The `Map` in `f` initializer
-   * references the empty name.
-   */
+class InvalidCodeTest extends DriverResolutionTest {
+  /// This code results in a method with the empty name, and the default
+  /// constructor, which also has the empty name. The `Map` in `f` initializer
+  /// references the empty name.
   test_constructorAndMethodNameCollision() async {
     await _assertCanBeAnalyzed('''
 class C {
@@ -49,8 +39,8 @@
   }
 
   Future<void> _assertCanBeAnalyzed(String text) async {
-    Source source = addSource(text);
-    var analysisResult = await computeAnalysisResult(source);
-    expect(analysisResult.errors, isNotEmpty);
+    addTestFile(text);
+    await resolveTestFile();
+    assertHasTestErrors();
   }
 }
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index a033b5c..11fa1ce 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -4,36 +4,35 @@
 
 import 'dart:async';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/source_io.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'resolver_test_case.dart';
+import '../src/dart/resolution/driver_resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonErrorResolverTest);
-    defineReflectiveTests(NonErrorResolverWithUiAsCodeTest);
     defineReflectiveTests(NonConstantValueInInitializer);
   });
 }
 
 @reflectiveTest
-class NonConstantValueInInitializer extends ResolverTestCase {
+class NonConstantValueInInitializer extends DriverResolutionTest {
   @override
-  List<String> get enabledExperiments => [EnableString.constant_update_2018];
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0',
+        additionalFeatures: [Feature.constant_update_2018]);
 
   test_intLiteralInDoubleContext_const_exact() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 const double x = 0;
 class C {
   const C(double y) : assert(y is double), assert(x is double);
@@ -47,14 +46,12 @@
   const C(-0);
   const C(0x0);
   const C(-0x0);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_isCheckInConstAssert() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   const C() : assert(1 is int);
 }
@@ -63,101 +60,107 @@
   const C();
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 }
 
 @reflectiveTest
-class NonErrorResolverTest extends ResolverTestCase {
-  @override
-  AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
-
+class NonErrorResolverTest extends DriverResolutionTest {
   test_ambiguousExport() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: r'''
+library lib1;
+class M {}
+''');
+    newFile("/test/lib/lib2.dart", content: r'''
+library lib2;
+class N {}
+''');
+    await assertNoErrorsInCode(r'''
 library L;
 export 'lib1.dart';
-export 'lib2.dart';''');
-    addNamedSource("/lib1.dart", r'''
-library lib1;
-class M {}''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
-class N {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+export 'lib2.dart';
+''');
   }
 
   test_ambiguousExport_combinators_hide() async {
-    Source source = addSource(r'''
-library L;
-export 'lib1.dart';
-export 'lib2.dart' hide B;''');
-    addNamedSource("/lib1.dart", r'''
+    newFile("/test/lib/lib1.dart", content: r'''
 library L1;
 class A {}
-class B {}''');
-    addNamedSource("/lib2.dart", r'''
+class B {}
+''');
+    newFile("/test/lib/lib2.dart", content: r'''
 library L2;
 class B {}
-class C {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C {}
+''');
+    await assertNoErrorsInCode(r'''
+library L;
+export 'lib1.dart';
+export 'lib2.dart' hide B;
+''');
   }
 
   test_ambiguousExport_combinators_show() async {
-    Source source = addSource(r'''
-library L;
-export 'lib1.dart';
-export 'lib2.dart' show C;''');
-    addNamedSource("/lib1.dart", r'''
+    newFile("/test/lib/lib1.dart", content: r'''
 library L1;
 class A {}
-class B {}''');
-    addNamedSource("/lib2.dart", r'''
+class B {}
+''');
+    newFile("/test/lib/lib2.dart", content: r'''
 library L2;
 class B {}
-class C {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C {}
+''');
+    await assertNoErrorsInCode(r'''
+library L;
+export 'lib1.dart';
+export 'lib2.dart' show C;
+''');
   }
 
   test_ambiguousExport_sameDeclaration() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib.dart", content: r'''
+library lib;
+class N {}
+''');
+    await assertNoErrorsInCode(r'''
 library L;
 export 'lib.dart';
-export 'lib.dart';''');
-    addNamedSource("/lib.dart", r'''
-library lib;
-class N {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+export 'lib.dart';
+''');
   }
 
   test_ambiguousImport_dart_implicitHide() async {
-    Source source = addSource(r'''
+    newFile('/test/lib/lib.dart', content: r'''
+class Future {
+  static const zero = 0;
+}
+''');
+    await assertNoErrorsInCode(r'''
 import 'dart:async';
 import 'lib.dart';
 main() {
   print(Future.zero);
 }
 ''');
-    addNamedSource('/lib.dart', r'''
-class Future {
-  static const zero = 0;
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_ambiguousImport_hideCombinator() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: r'''
+library lib1;
+class N {}
+class N1 {}
+''');
+    newFile("/test/lib/lib2.dart", content: r'''
+library lib2;
+class N {}
+class N2 {}
+''');
+    newFile("/test/lib/lib3.dart", content: r'''
+library lib3;
+class N {}
+class N3 {}
+''');
+    await assertNoErrorsInCode(r'''
 import 'lib1.dart';
 import 'lib2.dart';
 import 'lib3.dart' hide N;
@@ -165,71 +168,60 @@
   new N1();
   new N2();
   new N3();
-}''');
-    addNamedSource("/lib1.dart", r'''
-library lib1;
-class N {}
-class N1 {}''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
-class N {}
-class N2 {}''');
-    addNamedSource("/lib3.dart", r'''
-library lib3;
-class N {}
-class N3 {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+}
+''');
   }
 
   test_ambiguousImport_showCombinator() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: r'''
+library lib1;
+class N {}
+class N1 {}
+''');
+    newFile("/test/lib/lib2.dart", content: r'''
+library lib2;
+class N {}
+class N2 {}
+''');
+    await assertErrorsInCode(r'''
 import 'lib1.dart';
 import 'lib2.dart' show N, N2;
 main() {
   new N1();
   new N2();
-}''');
-    addNamedSource("/lib1.dart", r'''
-library lib1;
-class N {}
-class N1 {}''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
-class N {}
-class N2 {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_SHOWN_NAME]);
+}
+''', [
+      error(HintCode.UNUSED_SHOWN_NAME, 44, 1),
+    ]);
   }
 
   test_annotated_partOfDeclaration() async {
-    Source source = addSource('library L; part "part.dart";');
-    addNamedSource('/part.dart', '@deprecated part of L;');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    newFile('/test/lib/part.dart', content: '''
+@deprecated part of L;
+''');
+    await assertNoErrorsInCode('''
+library L; part "part.dart";
+''');
   }
 
   test_argumentTypeNotAssignable_classWithCall_Function() async {
-    Source source = addSource(r'''
-  caller(Function callee) {
-    callee();
-  }
+    await assertNoErrorsInCode(r'''
+caller(Function callee) {
+  callee();
+}
 
-  class CallMeBack {
-    call() => 0;
-  }
+class CallMeBack {
+  call() => 0;
+}
 
-  main() {
-    caller(new CallMeBack());
-  }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+main() {
+  caller(new CallMeBack());
+}
+''');
   }
 
   test_argumentTypeNotAssignable_fieldFormalParameterElement_member() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class ObjectSink<T> {
   void sink(T object) {
     new TimestampedObject<T>(object);
@@ -238,49 +230,39 @@
 class TimestampedObject<E> {
   E object2;
   TimestampedObject(this.object2);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_argumentTypeNotAssignable_invocation_functionParameter_generic() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A<K> {
   m(f(K k), K v) {
     f(v);
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_argumentTypeNotAssignable_invocation_typedef_generic() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef A<T>(T p);
 f(A<int> a) {
   a(1);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_argumentTypeNotAssignable_Object_Function() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main() {
   process(() {});
 }
 process(Object x) {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_argumentTypeNotAssignable_optionalNew() async {
-    resetWith(options: new AnalysisOptionsImpl());
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class Widget { }
 
 class MaterialPageRoute {
@@ -294,110 +276,85 @@
   ));
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_argumentTypeNotAssignable_typedef_local() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef A(int p1, String p2);
 A getA() => null;
 f() {
   A a = getA();
   a(1, '2');
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_argumentTypeNotAssignable_typedef_parameter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef A(int p1, String p2);
 f(A a) {
   a(1, '2');
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_assert_with_message_await() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 f() async {
   assert(false, await g());
 }
 Future<String> g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_assert_with_message_dynamic() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() {
   assert(false, g());
 }
 g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_assert_with_message_non_string() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() {
   assert(false, 3);
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_assert_with_message_null() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() {
   assert(false, null);
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_assert_with_message_string() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() {
   assert(false, 'message');
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_assert_with_message_suppresses_unused_var_hint() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() {
   String message = 'msg';
   assert(true, message);
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_assignability_function_expr_rettype_from_typedef_cls() async {
     // In the code below, the type of (() => f()) has a return type which is
     // a class, and that class is inferred from the return type of the typedef
     // F.
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class C {}
 typedef C F();
 F f;
@@ -405,16 +362,13 @@
   F f2 = (() => f());
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_assignability_function_expr_rettype_from_typedef_typedef() async {
     // In the code below, the type of (() => f()) has a return type which is
     // a typedef, and that typedef is inferred from the return type of the
     // typedef F.
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 typedef G F();
 typedef G();
 F f;
@@ -422,24 +376,19 @@
   F f2 = (() => f());
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_assignmentToFinal_prefixNegate() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   final x = 0;
   -x;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_assignmentToFinalNoSetter_prefixedIdentifier() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int get x => 0;
   set x(v) {}
@@ -447,14 +396,12 @@
 main() {
   A a = new A();
   a.x = 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_assignmentToFinalNoSetter_propertyAccess() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int get x => 0;
   set x(v) {}
@@ -464,73 +411,57 @@
 }
 main() {
   B.a.x = 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_assignmentToFinals_importWithPrefix() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: r'''
+library lib1;
+bool x = false;''');
+    await assertNoErrorsInCode(r'''
 library lib;
 import 'lib1.dart' as foo;
 main() {
   foo.x = true;
-}''');
-    addNamedSource("/lib1.dart", r'''
-library lib1;
-bool x = false;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_async_dynamic_with_return() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 dynamic f() async {
   return;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_dynamic_with_return_value() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 dynamic f() async {
   return 5;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_dynamic_without_return() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 dynamic f() async {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_expression_function_type() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 typedef Future<int> F(int i);
 main() {
   F f = (int i) async => i;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_flattened() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 typedef Future<int> CreatesFutureInt();
 main() {
@@ -540,238 +471,179 @@
 }
 Future<int> f() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_future_dynamic_with_return() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future<dynamic> f() async {
   return;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_future_dynamic_with_return_value() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future<dynamic> f() async {
   return 5;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_future_dynamic_without_return() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future<dynamic> f() async {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_future_int_with_return_future_int() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future<int> f() async {
   return new Future<int>.value(5);
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_future_int_with_return_value() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future<int> f() async {
   return 5;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_future_null_with_return() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future<Null> f() async {
   return;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_future_null_without_return() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future<Null> f() async {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_future_object_with_return_value() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future<Object> f() async {
   return 5;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_future_with_return() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future f() async {
   return;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_future_with_return_value() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future f() async {
   return 5;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_future_without_return() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future f() async {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_with_return() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() async {
   return;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_with_return_value() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() async {
   return 5;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_async_without_return() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() async {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_asyncForInWrongContext_async() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(list) async {
   await for (var e in list) {
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_asyncForInWrongContext_asyncStar() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(list) async* {
   await for (var e in list) {
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_await_flattened() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future<Future<int>> ffi() => null;
 f() async {
   Future<int> b = await ffi();
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_await_simple() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Future<int> fi() => null;
 f() async {
   int a = await fi();
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_awaitInWrongContext_async() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(x, y) async {
   return await x + await y;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_awaitInWrongContext_asyncStar() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(x, y) async* {
   yield await x + await y;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_breakWithoutLabelInSwitch() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   void m(int i) {
     switch (i) {
@@ -779,50 +651,40 @@
         break;
     }
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_bug_24539_getter() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class C<T> {
   List<Foo> get x => null;
 }
 
 typedef Foo(param);
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_bug_24539_setter() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class C<T> {
   void set x(List<Foo> value) {}
 }
 
 typedef Foo(param);
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_builtInIdentifierAsType_dynamic() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   dynamic x;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_caseBlockNotTerminated() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(int p) {
   for (int i = 0; i < 10; i++) {
     switch (p) {
@@ -842,27 +704,23 @@
         return;
     }
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_caseBlockNotTerminated_lastCase() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(int p) {
   switch (p) {
     case 0:
       p = p + 1;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_caseExpressionTypeImplementsEquals() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 print(p) {}
 
 abstract class B {
@@ -882,27 +740,23 @@
   case const C(0): print('Switch: 0'); break;
   case const C(1): print('Switch: 1'); break;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_caseExpressionTypeImplementsEquals_int() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(int i) {
   switch(i) {
     case(1) : return 1;
     default: return 0;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_caseExpressionTypeImplementsEquals_Object() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class IntWrapper {
   final int value;
   const IntWrapper(this.value);
@@ -913,156 +767,128 @@
     case(const IntWrapper(1)) : return 1;
     default: return 0;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_caseExpressionTypeImplementsEquals_String() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(String s) {
   switch(s) {
     case('1') : return 1;
     default: return 0;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_class_type_alias_documentationComment() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 /**
  * Documentation
  */
 class C = D with E;
 
 class D {}
-class E {}''');
-    TestAnalysisResult analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-    CompilationUnit unit = analysisResult.unit;
+class E {}
+''');
+    CompilationUnit unit = result.unit;
     ClassElement classC =
         resolutionMap.elementDeclaredByCompilationUnit(unit).getType('C');
     expect(classC.documentationComment, isNotNull);
   }
 
   test_closure_in_type_inferred_variable_in_other_lib() async {
-    Source source = addSource('''
-import 'other.dart';
-var x = y;
-    ''');
-    addNamedSource('/other.dart', '''
+    newFile('/test/lib/other.dart', content: '''
 var y = (Object x) => x is int && x.isEven;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+import 'other.dart';
+var x = y;
+''');
   }
 
   test_concreteClassWithAbstractMember() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   m();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_concreteClassWithAbstractMember_inherited() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m() {}
 }
 class B extends A {
   m();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_conflictingConstructorNameAndMember_setter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
 A.x() {}
 set x(_) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_conflictingStaticGetterAndInstanceSetter_thisClass() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   static get x => 0;
   static set x(int p) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_const_constructor_with_named_generic_parameter() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class C<T> {
   const C({T t});
 }
 const c = const C(t: 1);
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_const_dynamic() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 const Type d = dynamic;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_const_imported_defaultParameterValue_withImportPrefix() async {
-    Source source = addNamedSource("/a.dart", r'''
-import 'b.dart';
-const b = const B();
-''');
-    addNamedSource("/b.dart", r'''
+    newFile('/test/lib/b.dart', content: r'''
 import 'c.dart' as ccc;
 class B {
   const B([p = ccc.value]);
 }
 ''');
-    addNamedSource("/c.dart", r'''
+    newFile('/test/lib/c.dart', content: r'''
 const int value = 12345;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode(r'''
+import 'b.dart';
+const b = const B();
+''');
   }
 
   test_constConstructorWithNonConstSuper_explicit() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   const A();
 }
 class B extends A {
   const B(): super();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constConstructorWithNonConstSuper_redirectingFactory() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A();
 }
@@ -1071,123 +897,107 @@
 }
 class C extends A {
   const factory C() = B;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constConstructorWithNonConstSuper_unresolved() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 class A {
   A.a();
 }
 class B extends A {
   const B(): super();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
-    verify([source]);
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
+          54, 7),
+    ]);
   }
 
   test_constConstructorWithNonFinalField_finalInstanceVar() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final int x = 0;
   const A();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constConstructorWithNonFinalField_static() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   static int x;
   const A();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constConstructorWithNonFinalField_syntheticField() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   const A();
   set x(value) {}
   get x {return 0;}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constDeferredClass_new() async {
-    await resolveWithErrors(<String>[
-      r'''
-library lib1;
+    newFile('/test/lib/lib.dart', content: r'''
 class A {
   const A.b();
-}''',
-      r'''
-library root;
-import 'lib1.dart' deferred as a;
+}
+''');
+    await assertNoErrorsInCode(r'''
+import 'lib.dart' deferred as a;
 main() {
   new a.A.b();
-}'''
-    ], <ErrorCode>[]);
+}
+''');
   }
 
   test_constEval_functionTypeLiteral() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef F();
-const C = F;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+const C = F;
+''');
   }
 
   test_constEval_propertyExtraction_fieldStatic_targetType() async {
-    addNamedSource("/math.dart", r'''
+    newFile("/test/lib/math.dart", content: r'''
 library math;
-const PI = 3.14;''');
-    Source source = addSource(r'''
+const PI = 3.14;
+''');
+    await assertNoErrorsInCode(r'''
 import 'math.dart' as math;
-const C = math.PI;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+const C = math.PI;
+''');
   }
 
   test_constEval_propertyExtraction_methodStatic_targetType() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   const A();
   static m() {}
 }
-const C = A.m;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+const C = A.m;
+''');
   }
 
   test_constEval_symbol() async {
-    addNamedSource("/math.dart", r'''
+    newFile("/test/lib/math.dart", content: r'''
 library math;
-const PI = 3.14;''');
-    Source source = addSource(r'''
+const PI = 3.14;
+''');
+    await assertNoErrorsInCode(r'''
 const C = #foo;
-foo() {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+foo() {}
+''');
   }
 
   test_constEvalTypeBoolNumString_equal() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class B {
   final v;
   const B.a1(bool p) : v = p == true;
@@ -1209,13 +1019,12 @@
   const B.n2(num p) : v = null == p;
   const B.n3(Object p) : v = p == null;
   const B.n4(Object p) : v = null == p;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+}
+''');
   }
 
   test_constEvalTypeBoolNumString_notEqual() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class B {
   final v;
   const B.a1(bool p) : v = p != true;
@@ -1237,46 +1046,37 @@
   const B.n2(num p) : v = null != p;
   const B.n3(Object p) : v = p != null;
   const B.n4(Object p) : v = null != p;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constEvAlTypeNum_String() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 const String A = 'a';
 const String B = A + 'b';
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_constNotInitialized_field() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   static const int x = 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constNotInitialized_local() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main() {
   const int x = 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constRedirectSkipsSupertype() async {
     // Since C redirects to C.named, it doesn't implicitly refer to B's
     // unnamed constructor.  Therefore there is no cycle.
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class B {
   final x;
   const B() : x = y;
@@ -1288,491 +1088,407 @@
 }
 const y = const C();
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_constructorDeclaration_scope_signature() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 const app = 0;
 class A {
   A(@app int app) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constWithNonConstantArgument_constField() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   const A(x);
 }
 main() {
   const A(double.INFINITY);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constWithNonConstantArgument_literals() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   const A(a, b, c, d);
 }
-f() { return const A(true, 0, 1.0, '2'); }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+f() { return const A(true, 0, 1.0, '2'); }
+''');
   }
 
   test_constWithTypeParameters_direct() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A<T> {
   static const V = const A<int>();
   const A();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constWithUndefinedConstructor() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   const A.name();
 }
 f() {
   return const A.name();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_constWithUndefinedConstructorDefault() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   const A();
 }
 f() {
   return const A();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_defaultValueInFunctionTypeAlias() async {
-    Source source = addSource("typedef F([x]);");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+typedef F([x]);
+''');
   }
 
   test_defaultValueInFunctionTypedParameter_named() async {
-    Source source = addSource("f(g({p})) {}");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+f(g({p})) {}
+''');
   }
 
   test_defaultValueInFunctionTypedParameter_optional() async {
-    Source source = addSource("f(g([p])) {}");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode("f(g([p])) {}");
   }
 
   test_deprecatedMemberUse_hide() async {
-    Source source = addSource(r'''
-library lib;
-import 'lib1.dart' hide B;
-A a = new A();''');
-    addNamedSource("/lib1.dart", r'''
+    newFile("/test/lib/lib1.dart", content: r'''
 library lib1;
 class A {}
 @deprecated
-class B {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class B {}
+''');
+    await assertNoErrorsInCode(r'''
+library lib;
+import 'lib1.dart' hide B;
+A a = new A();
+''');
   }
 
   test_duplicateDefinition_emptyName() async {
     // Note: This code has two FunctionElements '() {}' with an empty name,
     // this tests that the empty string is not put into the scope
     // (more than once).
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 Map _globalMap = {
   'a' : () {},
   'b' : () {}
-};''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+};
+''');
   }
 
   test_duplicateDefinition_getter() async {
-    Source source = addSource("bool get a => true;");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+bool get a => true;
+''');
   }
 
   test_duplicatePart() async {
-    addNamedSource('/part1.dart', 'part of lib;');
-    addNamedSource('/part2.dart', 'part of lib;');
-    Source source = addSource(r'''
+    newFile('/test/lib/part1.dart', content: '''
+part of lib;
+''');
+    newFile('/test/lib/part2.dart', content: '''
+part of lib;
+''');
+    await assertNoErrorsInCode(r'''
 library lib;
 part 'part1.dart';
 part 'part2.dart';
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_dynamicIdentifier() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main() {
   var v = dynamic;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_empty_generator_async() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Stream<int> f() async* {
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_empty_generator_sync() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 Iterable<int> f() sync* {
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_expectedOneListTypeArgument() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main() {
   <int> [];
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_expectedTwoMapTypeArguments() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main() {
   <int, int> {};
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_exportDuplicatedLibraryUnnamed() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart");
+    newFile("/test/lib/lib2.dart");
+    await assertNoErrorsInCode(r'''
 library test;
 export 'lib1.dart';
-export 'lib2.dart';''');
-    addNamedSource("/lib1.dart", "");
-    addNamedSource("/lib2.dart", "");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+export 'lib2.dart';
+''');
   }
 
   test_exportOfNonLibrary_libraryDeclared() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: "library lib1;");
+    await assertNoErrorsInCode(r'''
 library L;
-export 'lib1.dart';''');
-    addNamedSource("/lib1.dart", "library lib1;");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+export 'lib1.dart';
+''');
   }
 
   test_exportOfNonLibrary_libraryNotDeclared() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart");
+    await assertNoErrorsInCode(r'''
 library L;
-export 'lib1.dart';''');
-    addNamedSource("/lib1.dart", "");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+export 'lib1.dart';
+''');
   }
 
   test_extraPositionalArguments_function() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(p1, p2) {}
 main() {
   f(1, 2);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_extraPositionalArguments_Function() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(Function a) {
   a(1, 2);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_extraPositionalArguments_typedef_local() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef A(p1, p2);
 A getA() => null;
 f() {
   A a = getA();
   a(1, 2);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_extraPositionalArguments_typedef_parameter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef A(p1, p2);
 f(A a) {
   a(1, 2);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_fieldFormalParameter_functionTyped_named() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   final Function field;
 
   C({String this.field(int value)});
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_fieldFormalParameter_genericFunctionTyped() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   final Object Function(int, double) field;
 
   C(String Function(num, Object) this.field);
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_fieldFormalParameter_genericFunctionTyped_named() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   final Object Function(int, double) field;
 
   C({String Function(num, Object) this.field});
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_fieldInitializedByMultipleInitializers() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int x;
   int y;
   A() : x = 0, y = 0 {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_fieldInitializedInInitializerAndDeclaration_fieldNotFinal() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int x = 0;
   A() : x = 1 {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_fieldInitializedInInitializerAndDeclaration_finalFieldNotSet() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final int x;
   A() : x = 1 {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_fieldInitializerOutsideConstructor() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int x;
   A(this.x) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_fieldInitializerOutsideConstructor_defaultParameters() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int x;
   A([this.x]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_fieldInitializerRedirectingConstructor_super() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A() {}
 }
 class B extends A {
   int x;
   B(this.x) : super();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_finalInitializedInDeclarationAndConstructor_initializer() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final x;
   A() : x = 1 {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_finalInitializedInDeclarationAndConstructor_initializingFormal() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final x;
   A(this.x) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_finalNotInitialized_atDeclaration() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final int x = 0;
   A() {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_finalNotInitialized_fieldFormal() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final int x = 0;
   A() {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_finalNotInitialized_functionTypedFieldFormal() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final Function x;
   A(int this.x(int p)) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_finalNotInitialized_hasNativeClause_hasConstructor() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 class A native 'something' {
   final int x;
   A() {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE]);
-    verify([source]);
+}
+''', [
+      error(ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, 8, 18),
+    ]);
   }
 
   test_finalNotInitialized_hasNativeClause_noConstructor() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 class A native 'something' {
   final int x;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE]);
-    verify([source]);
+}
+''', [
+      error(ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, 8, 18),
+    ]);
   }
 
   test_finalNotInitialized_initializer() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final int x;
   A() : x = 0 {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_finalNotInitialized_redirectingConstructor() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final int x;
   A(this.x);
   A.named() : this (42);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_for_in_scope() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 main() {
   List<List<int>> x = [[1]];
   for (int x in x.first) {
@@ -1780,57 +1496,46 @@
   }
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_forEach_genericFunctionType() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main() {
   for (Null Function<T>(T, Null) e in <dynamic>[]) {
     e;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_functionDeclaration_scope_returnType() async {
-    Source source = addSource("int f(int) { return 0; }");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+int f(int) { return 0; }
+''');
   }
 
   test_functionDeclaration_scope_signature() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 const app = 0;
-f(@app int app) {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+f(@app int app) {}
+''');
   }
 
   test_functionTypeAlias_scope_returnType() async {
-    Source source = addSource("typedef int f(int);");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+typedef int f(int);
+''');
   }
 
   test_functionTypeAlias_scope_signature() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 const app = 0;
-typedef int f(@app int app);''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+typedef int f(@app int app);
+''');
   }
 
   test_functionWithoutCall() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A implements Function {
 }
 class B implements A {
@@ -1840,70 +1545,56 @@
   void call() {}
 }
 class D extends C {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_functionWithoutCall_doesNotImplementFunction() async {
-    Source source = addSource("class A {}");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode("class A {}");
   }
 
   test_functionWithoutCall_staticCallMethod() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A { }
 class B extends A {
   static call() { }
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_functionWithoutCall_withNoSuchMethod() async {
     // 16078
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A implements Function {
   noSuchMethod(inv) {
     return 42;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_functionWithoutCall_withNoSuchMethod_mixin() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   noSuchMethod(inv) {}
 }
 class B extends Object with A implements Function {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_functionWithoutCall_withNoSuchMethod_superclass() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   noSuchMethod(inv) {}
 }
 class B extends A implements Function {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_genericTypeAlias_castsAndTypeChecks_hasTypeParameters() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 typedef Foo<S> = S Function<T>(T x);
 
 main(Object p) {
@@ -1917,13 +1608,10 @@
   }
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_genericTypeAlias_castsAndTypeChecks_noTypeParameters() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 typedef Foo = T Function<T>(T x);
 
 main(Object p) {
@@ -1933,13 +1621,10 @@
   }
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_genericTypeAlias_fieldAndReturnType_noTypeParameters() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef Foo = int Function<T>(T x);
 int foo<T>(T x) => 3;
 Foo bar() => foo;
@@ -1954,13 +1639,10 @@
   }
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_genericTypeAlias_fieldAndReturnType_typeParameters_arguments() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef Foo<S> = S Function<T>(T x);
 int foo<T>(T x) => 3;
 Foo<int> bar() => foo;
@@ -1975,13 +1657,10 @@
   }
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_genericTypeAlias_fieldAndReturnType_typeParameters_noArguments() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef Foo<S> = S Function<T>(T x);
 int foo<T>(T x) => 3;
 Foo bar() => foo;
@@ -1996,26 +1675,22 @@
   }
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_genericTypeAlias_invalidGenericFunctionType() async {
-    Source source = addSource('''
+    // There is a parse error, but no crashes.
+    await assertErrorsInCode('''
 typedef F = int;
 main(p) {
   p is F;
 }
-''');
-    await computeAnalysisResult(source);
-    // There is a parse error, but no crashes.
-    assertErrors(source, [ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE]);
-    verify([source]);
+''', [
+      error(ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, 10, 1),
+    ]);
   }
 
   test_genericTypeAlias_noTypeParameters() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef Foo = int Function<T>(T x);
 int foo<T>(T x) => 3;
 void test1() {
@@ -2025,13 +1700,10 @@
   y<String>("hello");
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_genericTypeAlias_typeParameters() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef Foo<S> = S Function<T>(T x);
 int foo<T>(T x) => 3;
 void test1() {
@@ -2041,227 +1713,80 @@
   y<String>("hello");
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_implicitThisReferenceInInitializer_constructorName() async {
-    Source source = addSource(r'''
-class A {
-  A.named() {}
-}
-class B {
-  var v;
-  B() : v = new A.named();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_implicitThisReferenceInInitializer_prefixedIdentifier() async {
-    Source source = addSource(r'''
-class A {
-  var f;
-}
-class B {
-  var v;
-  B(A a) : v = a.f;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_implicitThisReferenceInInitializer_qualifiedMethodInvocation() async {
-    Source source = addSource(r'''
-class A {
-  f() {}
-}
-class B {
-  var v;
-  B() : v = new A().f();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_implicitThisReferenceInInitializer_qualifiedPropertyAccess() async {
-    Source source = addSource(r'''
-class A {
-  var f;
-}
-class B {
-  var v;
-  B() : v = new A().f;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_implicitThisReferenceInInitializer_staticField_thisClass() async {
-    Source source = addSource(r'''
-class A {
-  var v;
-  A() : v = f;
-  static var f;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_implicitThisReferenceInInitializer_staticGetter() async {
-    Source source = addSource(r'''
-class A {
-  var v;
-  A() : v = f;
-  static get f => 42;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_implicitThisReferenceInInitializer_staticMethod() async {
-    Source source = addSource(r'''
-class A {
-  var v;
-  A() : v = f();
-  static f() => 42;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_implicitThisReferenceInInitializer_topLevelField() async {
-    Source source = addSource(r'''
-class A {
-  var v;
-  A() : v = f;
-}
-var f = 42;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_implicitThisReferenceInInitializer_topLevelFunction() async {
-    Source source = addSource(r'''
-class A {
-  var v;
-  A() : v = f();
-}
-f() => 42;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_implicitThisReferenceInInitializer_topLevelGetter() async {
-    Source source = addSource(r'''
-class A {
-  var v;
-  A() : v = f;
-}
-get f => 42;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_implicitThisReferenceInInitializer_typeParameter() async {
-    Source source = addSource(r'''
-class A<T> {
-  var v;
-  A(p) : v = (p is T);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_importDuplicatedLibraryName() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib.dart", content: "library lib;");
+    await assertErrorsInCode(r'''
 library test;
 import 'lib.dart';
-import 'lib.dart';''');
-    addNamedSource("/lib.dart", "library lib;");
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      HintCode.UNUSED_IMPORT,
-      HintCode.UNUSED_IMPORT,
-      HintCode.DUPLICATE_IMPORT
+import 'lib.dart';
+''', [
+      error(HintCode.UNUSED_IMPORT, 21, 10),
+      error(HintCode.UNUSED_IMPORT, 40, 10),
+      error(HintCode.DUPLICATE_IMPORT, 40, 10),
     ]);
-    verify([source]);
   }
 
   test_importDuplicatedLibraryUnnamed() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart");
+    newFile("/test/lib/lib2.dart");
+    // No warning on duplicate import (https://github.com/dart-lang/sdk/issues/24156)
+    await assertErrorsInCode(r'''
 library test;
 import 'lib1.dart';
-import 'lib2.dart';''');
-    addNamedSource("/lib1.dart", "");
-    addNamedSource("/lib2.dart", "");
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      // No warning on duplicate import (https://github.com/dart-lang/sdk/issues/24156)
-      HintCode.UNUSED_IMPORT,
-      HintCode.UNUSED_IMPORT
+import 'lib2.dart';
+''', [
+      error(HintCode.UNUSED_IMPORT, 21, 11),
+      error(HintCode.UNUSED_IMPORT, 41, 11),
     ]);
-    verify([source]);
   }
 
   test_importOfNonLibrary_libraryDeclared() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/part.dart", content: r'''
+library lib1;
+class A {}
+''');
+    await assertNoErrorsInCode(r'''
 library lib;
 import 'part.dart';
-A a;''');
-    addNamedSource("/part.dart", r'''
-library lib1;
-class A {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+A a;
+''');
   }
 
   test_importOfNonLibrary_libraryNotDeclared() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/part.dart", content: '''
+class A {}
+''');
+    await assertNoErrorsInCode(r'''
 library lib;
 import 'part.dart';
-A a;''');
-    addNamedSource("/part.dart", "class A {}");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+A a;
+''');
   }
 
   test_importPrefixes_withFirstLetterDifference() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: r'''
+library lib1;
+test1() {}
+''');
+    newFile("/test/lib/lib2.dart", content: r'''
+library lib2;
+test2() {}
+''');
+    await assertNoErrorsInCode(r'''
 library L;
 import 'lib1.dart' as math;
 import 'lib2.dart' as path;
 main() {
   math.test1();
   path.test2();
-}''');
-    addNamedSource("/lib1.dart", r'''
-library lib1;
-test1() {}''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
-test2() {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_inconsistentCaseExpressionTypes() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(var p) {
   switch (p) {
     case 1:
@@ -2269,28 +1794,24 @@
     case 2:
       break;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_inconsistentMethodInheritance_accessors_typeParameter2() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A<E> {
   E get x {return null;}
 }
 class B<E> {
   E get x {return null;}
 }
-class C<E> extends A<E> implements B<E> {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C<E> extends A<E> implements B<E> {}
+''');
   }
 
   test_inconsistentMethodInheritance_accessors_typeParameters1() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A<E> {
   E get x;
 }
@@ -2299,14 +1820,12 @@
 }
 class C<E> implements A<E>, B<E> {
   E get x => null;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_inconsistentMethodInheritance_accessors_typeParameters_diamond() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class F<E> extends B<E> {}
 class D<E> extends F<E> {
   external E get g;
@@ -2318,14 +1837,12 @@
   E get g { return null; }
 }
 class A<E> extends B<E> implements D<E> {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_inconsistentMethodInheritance_methods_typeParameter2() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A<E> {
   x(E e) {}
 }
@@ -2334,14 +1851,12 @@
 }
 class C<E> extends A<E> implements B<E> {
   x(E e) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_inconsistentMethodInheritance_methods_typeParameters1() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A<E> {
   x(E e) {}
 }
@@ -2350,14 +1865,12 @@
 }
 class C<E> implements A<E>, B<E> {
   x(E e) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_inconsistentMethodInheritance_simple() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   x();
 }
@@ -2366,14 +1879,12 @@
 }
 class C implements A, B {
   x() {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_infer_mixin_new_syntax() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 abstract class A<T> {}
 
 class B {}
@@ -2382,10 +1893,7 @@
 
 class C extends A<B> with M {}
 ''');
-    TestAnalysisResult analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-    CompilationUnit unit = analysisResult.unit;
+    CompilationUnit unit = result.unit;
     ClassElement classC =
         resolutionMap.elementDeclaredByCompilationUnit(unit).getType('C');
     expect(classC.mixins, hasLength(1));
@@ -2393,7 +1901,7 @@
   }
 
   test_infer_mixin_with_substitution_functionType_new_syntax() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 abstract class A<T> {}
 
 class B {}
@@ -2401,10 +1909,14 @@
 mixin M<T, U> on A<T Function(U)> {}
 
 class C extends A<int Function(String)> with M {}
-''');
-    TestAnalysisResult analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    CompilationUnit unit = analysisResult.unit;
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        47,
+        1,
+      ),
+    ]);
+    CompilationUnit unit = result.unit;
     ClassElement classC =
         resolutionMap.elementDeclaredByCompilationUnit(unit).getType('C');
     expect(classC.mixins, hasLength(1));
@@ -2412,7 +1924,7 @@
   }
 
   test_infer_mixin_with_substitution_new_syntax() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 abstract class A<T> {}
 
 class B {}
@@ -2421,10 +1933,7 @@
 
 class C extends A<List<B>> with M {}
 ''');
-    TestAnalysisResult analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-    CompilationUnit unit = analysisResult.unit;
+    CompilationUnit unit = result.unit;
     ClassElement classC =
         resolutionMap.elementDeclaredByCompilationUnit(unit).getType('C');
     expect(classC.mixins, hasLength(1));
@@ -2432,18 +1941,16 @@
   }
 
   test_initializingFormalForNonExistentField() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int x;
   A(this.x) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_instance_creation_inside_annotation() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class C {
   const C();
 }
@@ -2454,132 +1961,119 @@
 @D(const C())
 f() {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_instanceAccessToStaticMember_fromComment() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   static m() {}
 }
 /// [A.m]
 main() {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_instanceAccessToStaticMember_topLevel() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 m() {}
 main() {
   m();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_instanceMemberAccessFromStatic_fromComment() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m() {}
   /// [m]
   static foo() {
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_instanceMethodNameCollidesWithSuperclassStatic_field() async {
-    Source source = addSource(r'''
-import 'lib.dart';
-class B extends A {
-  _m() {}
-}''');
-    addNamedSource("/lib.dart", r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library L;
 class A {
   static var _m;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_instanceMethodNameCollidesWithSuperclassStatic_method() async {
-    Source source = addSource(r'''
+}
+''');
+    await assertNoErrorsInCode(r'''
 import 'lib.dart';
 class B extends A {
   _m() {}
-}''');
-    addNamedSource("/lib.dart", r'''
+}
+''');
+  }
+
+  test_instanceMethodNameCollidesWithSuperclassStatic_method() async {
+    newFile("/test/lib/lib.dart", content: r'''
 library L;
 class A {
   static _m() {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
+    await assertNoErrorsInCode(r'''
+import 'lib.dart';
+class B extends A {
+  _m() {}
+}
+''');
   }
 
   test_integerLiteralOutOfRange_negative_leadingZeros() async {
-    Source source = addSource('int x = -000923372036854775809;');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+    await assertNoErrorsInCode('''
+int x = -000923372036854775809;
+''');
   }
 
   test_integerLiteralOutOfRange_negative_small() async {
-    Source source = addSource('int x = -42;');
-    await computeAnalysisResult(source);
-    assertErrors(source);
+    await assertNoErrorsInCode('''
+int x = -42;
+''');
   }
 
   test_integerLiteralOutOfRange_negative_valid() async {
-    Source source = addSource('int x = -9223372036854775808;');
-    await computeAnalysisResult(source);
-    assertErrors(source);
+    await assertNoErrorsInCode('''
+int x = -9223372036854775808;
+''');
   }
 
   test_integerLiteralOutOfRange_positive_leadingZeros() async {
-    Source source = addSource('int x = 000923372036854775808;');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+    await assertNoErrorsInCode('''
+int x = 000923372036854775808;
+''');
   }
 
   test_integerLiteralOutOfRange_positive_valid() async {
-    Source source = addSource('int x = 9223372036854775807;');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+    await assertNoErrorsInCode('''
+int x = 9223372036854775807;
+''');
   }
 
   test_integerLiteralOutOfRange_positive_zero() async {
-    Source source = addSource('int x = 0;');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+    await assertNoErrorsInCode('''
+int x = 0;
+''');
   }
 
   test_intLiteralInDoubleContext() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 void takeDouble(double x) {}
 void main() {
   takeDouble(0);
   takeDouble(-0);
   takeDouble(0x0);
   takeDouble(-0x0);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_intLiteralInDoubleContext_const() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   const C(double x)
     : assert((x + 3) / 2 == 1.5)
@@ -2594,110 +2088,98 @@
   const C(-0);
   const C(0x0);
   const C(-0x0);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidAnnotation_constantVariable_field() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 @A.C
 class A {
   static const C = 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidAnnotation_constantVariable_field_importWithPrefix() async {
-    addNamedSource("/lib.dart", r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 class A {
   static const C = 0;
-}''');
-    Source source = addSource(r'''
+}
+''');
+    await assertNoErrorsInCode(r'''
 import 'lib.dart' as p;
 @p.A.C
 main() {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidAnnotation_constantVariable_topLevel() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 const C = 0;
 @C
 main() {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidAnnotation_constantVariable_topLevel_importWithPrefix() async {
-    addNamedSource("/lib.dart", r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
-const C = 0;''');
-    Source source = addSource(r'''
+const C = 0;
+''');
+    await assertNoErrorsInCode(r'''
 import 'lib.dart' as p;
 @p.C
 main() {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidAnnotation_constConstructor_importWithPrefix() async {
-    addNamedSource("/lib.dart", r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 class A {
   const A(int p);
-}''');
-    Source source = addSource(r'''
+}
+''');
+    await assertNoErrorsInCode(r'''
 import 'lib.dart' as p;
 @p.A(42)
 main() {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidAnnotation_constConstructor_named_importWithPrefix() async {
-    addNamedSource("/lib.dart", r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 class A {
   const A.named(int p);
-}''');
-    Source source = addSource(r'''
+}
+''');
+    await assertNoErrorsInCode(r'''
 import 'lib.dart' as p;
 @p.A.named(42)
 main() {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidAssignment() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   var x;
   var y;
   x = y;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidAssignment_compoundAssignment() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class byte {
   int _value;
   byte(this._value);
@@ -2707,52 +2189,39 @@
 void main() {
   byte b = new byte(52);
   b += 3;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidAssignment_defaultValue_named() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f({String x: '0'}) {
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_invalidAssignment_defaultValue_optional() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f([String x = '0']) {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidAssignment_ifNullAssignment_compatibleType() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 void f(int i) {
   num n;
   n ??= i;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_invalidAssignment_ifNullAssignment_sameType() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 void f(int i) {
   int j;
   j ??= i;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_invalidAssignment_implicitlyImplementFunctionViaCall_1() async {
@@ -2762,7 +2231,7 @@
     // 'test_invalidAssignment_implicitlyImplementFunctionViaCall_2()'
     // are closely related: here we see that 'I' checks as a subtype of
     // 'IntToInt'.
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class I {
   int call(int x) => 0;
 }
@@ -2770,10 +2239,8 @@
   noSuchMethod(_) => null;
 }
 typedef int IntToInt(int x);
-IntToInt f = new I();''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+IntToInt f = new I();
+''');
   }
 
   test_invalidAssignment_implicitlyImplementFunctionViaCall_2() async {
@@ -2783,7 +2250,7 @@
     // check as a subtype of 'IntToInt'. Together with
     // 'test_invalidAssignment_implicitlyImplementFunctionViaCall_1()' we see
     // that subtyping is not transitive here.
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class I {
   int call(int x) => 0;
 }
@@ -2791,10 +2258,8 @@
   noSuchMethod(_) => null;
 }
 typedef int IntToInt(int x);
-IntToInt f = new C();''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+IntToInt f = new C();
+''');
   }
 
   test_invalidAssignment_implicitlyImplementFunctionViaCall_3() async {
@@ -2802,7 +2267,7 @@
     //
     // Like 'test_invalidAssignment_implicitlyImplementFunctionViaCall_2()',
     // but uses type 'Function' instead of more precise type 'IntToInt' for 'f'.
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class I {
   int call(int x) => 0;
 }
@@ -2810,10 +2275,8 @@
   noSuchMethod(_) => null;
 }
 typedef int IntToInt(int x);
-Function f = new C();''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+Function f = new C();
+''');
   }
 
   test_invalidAssignment_implicitlyImplementFunctionViaCall_4() async {
@@ -2828,7 +2291,7 @@
     // transitivity for 'JsBuilder' objects, assigning them to
     // '(String) -> dynamic'. The declared type of 'JsBuilder.call' is
     // '(String, [dynamic]) -> Expression'.
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class I {
   int call([int x]) => 0;
 }
@@ -2836,14 +2299,12 @@
   noSuchMethod(_) => null;
 }
 typedef int VoidToInt();
-VoidToInt f = new C();''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+VoidToInt f = new C();
+''');
   }
 
   test_invalidAssignment_postfixExpression_localVariable() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A operator+(_) => this;
 }
@@ -2852,13 +2313,10 @@
   a++;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_invalidAssignment_postfixExpression_property() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A operator+(_) => this;
 }
@@ -2871,13 +2329,10 @@
   c.a++;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_invalidAssignment_prefixExpression_localVariable() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A operator+(_) => this;
 }
@@ -2886,13 +2341,10 @@
   ++a;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_invalidAssignment_prefixExpression_property() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A operator+(_) => this;
 }
@@ -2905,113 +2357,94 @@
   ++c.a;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_invalidAssignment_toDynamic() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   var g;
   g = () => 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidFactoryNameNotAClass() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   factory A() => null;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidIdentifierInAsync() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m() {
     int async;
     int await;
     int yield;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidMethodOverrideNamedParamType() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m({int a}) {}
 }
 class B implements A {
   m({int a, int b}) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidOverrideNamed_unorderedNamedParameter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m({a, b}) {}
 }
 class B extends A {
   m({b, a}) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidOverrideRequired_less() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m(a, b) {}
 }
 class B extends A {
   m(a, [b]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidOverrideRequired_same() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m(a) {}
 }
 class B extends A {
   m(a) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidOverrideReturnType_returnType_interface() async {
-    Source source = addNamedSource("/test.dart", r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   num m();
 }
 class B implements A {
   int m() { return 1; }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidOverrideReturnType_returnType_interface2() async {
-    Source source = addNamedSource("/test.dart", r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   num m();
 }
@@ -3019,66 +2452,56 @@
 }
 class C implements B {
   int m() { return 1; }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidOverrideReturnType_returnType_mixin() async {
-    Source source = addNamedSource("/test.dart", r'''
+    await assertNoErrorsInCode(r'''
 class A {
   num m() { return 0; }
 }
 class B extends Object with A {
   int m() { return 1; }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidOverrideReturnType_returnType_parameterizedTypes() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A<E> {
   List<E> m();
 }
 class B extends A<dynamic> {
   List<dynamic> m() { return new List<dynamic>(); }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidOverrideReturnType_returnType_sameType() async {
-    Source source = addNamedSource("/test.dart", r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int m() { return 0; }
 }
 class B extends A {
   int m() { return 1; }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidOverrideReturnType_returnType_superclass() async {
-    Source source = addNamedSource("/test.dart", r'''
+    await assertNoErrorsInCode(r'''
 class A {
   num m() { return 0; }
 }
 class B extends A {
   int m() { return 1; }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidOverrideReturnType_returnType_superclass2() async {
-    Source source = addNamedSource("/test.dart", r'''
+    await assertNoErrorsInCode(r'''
 class A {
   num m() { return 0; }
 }
@@ -3086,92 +2509,78 @@
 }
 class C extends B {
   int m() { return 1; }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidOverrideReturnType_returnType_void() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   void m() {}
 }
 class B extends A {
   int m() { return 0; }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidReferenceToThis_constructor() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A() {
     var v = this;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidReferenceToThis_instanceMethod() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m() {
     var v = this;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidTypeArgumentForKey() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m() {
     return const <int, int>{};
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidTypeArgumentInConstList() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A<E> {
   m() {
     return <E>[];
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_invalidTypeArgumentInConstMap() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A<E> {
   m() {
     return <String, E>{};
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   Future test_issue32114() async {
-    addNamedSource('/a.dart', '''
+    newFile('/test/lib/a.dart', content: '''
 class O {}
 
 typedef T Func<T extends O>(T e);
 ''');
-    addNamedSource('/b.dart', '''
+    newFile('/test/lib/b.dart', content: '''
 import 'a.dart';
 export 'a.dart' show Func;
 
@@ -3179,20 +2588,17 @@
   Func<T> get func;
 }
 ''');
-    final Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'b.dart';
 
 class B extends A {
   Func get func => (x) => x;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_issue_24191() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 
 abstract class S extends Stream {}
@@ -3202,13 +2608,10 @@
   }
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_issue_32394() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 var x = y.map((a) => a.toString());
 var y = [3];
 var z = x.toList();
@@ -3216,21 +2619,21 @@
 void main() {
   String p = z;
 }
-''');
-    var result = await computeAnalysisResult(source);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 93, 1),
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 97, 1),
+    ]);
     var z = result.unit.declaredElement.topLevelVariables
         .where((e) => e.name == 'z')
         .single;
     expect(z.type.toString(), 'List<String>');
-    assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
-    verify([source]);
   }
 
   test_issue_35320_lists() async {
-    addNamedSource('/lib.dart', '''
+    newFile('/test/lib/lib.dart', content: '''
 const x = const <String>['a'];
 ''');
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'lib.dart';
 const y = const <String>['b'];
 int f(v) {
@@ -3244,16 +2647,13 @@
   }
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_issue_35320_maps() async {
-    addNamedSource('/lib.dart', '''
+    newFile('/test/lib/lib.dart', content: '''
 const x = const <String, String>{'a': 'b'};
 ''');
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'lib.dart';
 const y = const <String, String>{'c': 'd'};
 int f(v) {
@@ -3267,148 +2667,119 @@
   }
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_listElementTypeNotAssignable() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 var v1 = <int> [42];
-var v2 = const <int> [42];''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+var v2 = const <int> [42];
+''');
   }
 
   test_loadLibraryDefined() async {
-    await resolveWithErrors(<String>[
-      r'''
-library lib1;
-foo() => 22;''',
-      r'''
-import 'lib1.dart' deferred as other;
+    newFile('/test/lib/lib.dart', content: r'''
+library lib;
+foo() => 22;''');
+    await assertNoErrorsInCode(r'''
+import 'lib.dart' deferred as other;
 main() {
   other.loadLibrary().then((_) => other.foo());
-}'''
-    ], <ErrorCode>[]);
+}
+''');
   }
 
   test_local_generator_async() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() {
   return () async* { yield 0; };
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_local_generator_sync() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() {
   return () sync* { yield 0; };
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_mapKeyTypeNotAssignable() async {
-    Source source = addSource("var v = <String, int > {'a' : 1};");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+var v = <String, int > {'a' : 1};
+''');
   }
 
   test_metadata_enumConstantDeclaration() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 const x = 1;
 enum E {
   aaa,
   @x
   bbb
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_methodDeclaration_scope_signature() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 const app = 0;
 class A {
   foo(@app int app) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_misMatchedGetterAndSetterTypes_instance_sameTypes() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   int get x => 0;
   set x(int v) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_misMatchedGetterAndSetterTypes_instance_unspecifiedGetter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   get x => 0;
   set x(String v) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_misMatchedGetterAndSetterTypes_instance_unspecifiedSetter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   int get x => 0;
   set x(v) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_misMatchedGetterAndSetterTypes_topLevel_sameTypes() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 int get x => 0;
-set x(int v) {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+set x(int v) {}
+''');
   }
 
   test_misMatchedGetterAndSetterTypes_topLevel_unspecifiedGetter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 get x => 0;
-set x(String v) {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+set x(String v) {}
+''');
   }
 
   test_misMatchedGetterAndSetterTypes_topLevel_unspecifiedSetter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 int get x => 0;
-set x(v) {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+set x(v) {}
+''');
   }
 
   test_missingEnumConstantInSwitch_all() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 enum E { A, B, C }
 
 f(E e) {
@@ -3417,14 +2788,12 @@
     case E.B: break;
     case E.C: break;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_missingEnumConstantInSwitch_default() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 enum E { A, B, C }
 
 f(E e) {
@@ -3432,14 +2801,12 @@
     case E.B: break;
     default: break;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_mixedReturnTypes_differentScopes() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   m(int x) {
     f(int y) {
@@ -3448,25 +2815,21 @@
     f(x);
     return 0;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_mixedReturnTypes_ignoreImplicit() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(bool p) {
   if (p) return 42;
   // implicit 'return;' is ignored
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_mixedReturnTypes_ignoreImplicit2() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(bool p) {
   if (p) {
     return 42;
@@ -3474,14 +2837,12 @@
     return 42;
   }
   // implicit 'return;' is ignored
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_mixedReturnTypes_sameKind() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   m(int x) {
     if (x < 0) {
@@ -3489,10 +2850,8 @@
     }
     return 0;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_mixin_of_mixin_type_argument_inference() async {
@@ -3500,14 +2859,11 @@
     // superclass constraints are determined from the mixin's superclass, and
     // B's superclass is Object.  So no mixin type inference is attempted, and
     // "with B" is interpreted as "with B<dynamic>".
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class A<T> {}
 class B<T> = Object with A<T>;
 class C = Object with B;
 ''');
-    var result = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
     var bReference = result.unit.declaredElement.getType('C').mixins[0];
     expect(bReference.typeArguments[0].toString(), 'dynamic');
   }
@@ -3518,44 +2874,37 @@
     // B's superclass is "Object with A1<T>".  So mixin type inference succeeds
     // (since C's base class implements A1<int>), and "with B" is interpreted as
     // "with B<int>".
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class A1<T> {}
 class A2<T> {}
 class B<T> = Object with A1<T>, A2<T>;
 class Base implements A1<int> {}
 class C = Base with B;
 ''');
-    var result = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
     var bReference = result.unit.declaredElement.getType('C').mixins[0];
     expect(bReference.typeArguments[0].toString(), 'int');
   }
 
   test_mixinDeclaresConstructor() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m() {}
 }
-class B extends Object with A {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class B extends Object with A {}
+''');
   }
 
   test_mixinDeclaresConstructor_factory() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   factory A() => null;
 }
-class B extends Object with A {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class B extends Object with A {}
+''');
   }
 
   test_mixinInference_with_actual_mixins() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class I<X> {}
 
 mixin M0<T> on I<T> {}
@@ -3570,9 +2919,6 @@
   var x = new A().foo();
 }
 ''');
-    var result = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
     var main = result.unit.declarations.last as FunctionDeclaration;
     var mainBody = main.functionExpression.body as BlockFunctionBody;
     var xDecl = mainBody.block.statements[0] as VariableDeclarationStatement;
@@ -3581,101 +2927,85 @@
   }
 
   test_mixinInheritsFromNotObject_classDeclaration_extends_new_syntax() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 mixin B on A {}
-class C extends A with B {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C extends A with B {}
+''');
   }
 
   test_mixinInheritsFromNotObject_classDeclaration_mixTypeAlias() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B = Object with A;
-class C extends Object with B {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C extends Object with B {}
+''');
   }
 
   test_mixinInheritsFromNotObject_typeAlias_extends_new_syntax() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 mixin B on A {}
-class C = A with B;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C = A with B;
+''');
   }
 
   test_mixinInheritsFromNotObject_typedef_mixTypeAlias() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B = Object with A;
-class C = Object with B;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C = Object with B;
+''');
   }
 
   test_mixinReferencesSuper_new_syntax() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 mixin A {
   toString() => super.toString();
 }
-class B extends Object with A {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class B extends Object with A {}
+''');
   }
 
   test_multipleSuperInitializers_no() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B extends A {
   B() {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_multipleSuperInitializers_single() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B extends A {
   B() : super() {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nativeConstConstructor() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 import 'dart-ext:x';
 class Foo {
   const Foo() native 'Foo_Foo';
   const factory Foo.foo() native 'Foo_Foo_foo';
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY]);
-    // Cannot verify the AST because the import's URI cannot be resolved.
+}
+''', [
+      error(ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, 47, 6),
+    ]);
   }
 
   test_nativeFunctionBodyInNonSDKCode_function() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 import 'dart-ext:x';
-int m(a) native 'string';''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    // Cannot verify the AST because the import's URI cannot be resolved.
+int m(a) native 'string';
+''');
   }
 
   test_newWithAbstractClass_factory() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   factory A() { return new B(); }
 }
@@ -3684,123 +3014,105 @@
 }
 A f() {
   return new A();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_newWithUndefinedConstructor() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A.name() {}
 }
 f() {
   new A.name();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_newWithUndefinedConstructorDefault() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A() {}
 }
 f() {
   new A();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_abstractsDontOverrideConcretes_getter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int get g => 0;
 }
 abstract class B extends A {
   int get g;
 }
-class C extends B {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C extends B {}
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_abstractsDontOverrideConcretes_method() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m(p) {}
 }
 abstract class B extends A {
   m(p);
 }
-class C extends B {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C extends B {}
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_abstractsDontOverrideConcretes_setter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   set s(v) {}
 }
 abstract class B extends A {
   set s(v);
 }
-class C extends B {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C extends B {}
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_classTypeAlias_interface() async {
     // 15979
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class M {}
 abstract class A {}
 abstract class I {
   m();
 }
-abstract class B = A with M implements I;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+abstract class B = A with M implements I;
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_classTypeAlias_mixin() async {
     // 15979
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class M {
   m();
 }
 abstract class A {}
-abstract class B = A with M;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+abstract class B = A with M;
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_classTypeAlias_superclass() async {
     // 15979
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class M {}
 abstract class A {
   m();
 }
-abstract class B = A with M;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+abstract class B = A with M;
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_mixin_getter() async {
     // 17034
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   var a;
 }
@@ -3808,14 +3120,12 @@
   get a;
 }
 class B extends A with M {}
-class C extends B {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C extends B {}
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_mixin_method() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m() {}
 }
@@ -3823,14 +3133,12 @@
   m();
 }
 class B extends A with M {}
-class C extends B {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C extends B {}
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_mixin_setter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   var a;
 }
@@ -3838,101 +3146,85 @@
   set a(dynamic v);
 }
 class B extends A with M {}
-class C extends B {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class C extends B {}
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_noSuchMethod_accessor() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   int get g;
 }
 class B extends A {
   noSuchMethod(v) => '';
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_noSuchMethod_method() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   m(p);
 }
 class B extends A {
   noSuchMethod(v) => '';
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_noSuchMethod_mixin() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   noSuchMethod(v) => '';
 }
 class B extends Object with A {
   m(p);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_noSuchMethod_superclass() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   noSuchMethod(v) => '';
 }
 class B extends A {
   m(p);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_overridesMethodInObject() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   String toString([String prefix = '']) => '${prefix}Hello';
 }
 class C {}
-class B extends A with C {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class B extends A with C {}
+''');
   }
 
   test_nonBoolExpression_interfaceType() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   assert(true);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonBoolNegationExpression() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(bool pb, pd) {
   !true;
   !false;
   !pb;
   !pd;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonBoolNegationExpression_dynamic() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f1(bool dynamic) {
   !dynamic;
 }
@@ -3941,143 +3233,116 @@
   !dynamic;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_nonBoolOperand_and_bool() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 bool f(bool left, bool right) {
   return left && right;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonBoolOperand_and_dynamic() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 bool f(left, dynamic right) {
   return left && right;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonBoolOperand_or_bool() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 bool f(bool left, bool right) {
   return left || right;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonBoolOperand_or_dynamic() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 bool f(dynamic left, right) {
   return left || right;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstantDefaultValue_constField() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f([a = double.INFINITY]) {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstantDefaultValue_function_named() async {
-    Source source = addSource("f({x : 2 + 3}) {}");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+f({x : 2 + 3}) {}
+''');
   }
 
   test_nonConstantDefaultValue_function_positional() async {
-    Source source = addSource("f([x = 2 + 3]) {}");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+f([x = 2 + 3]) {}
+''');
   }
 
   test_nonConstantDefaultValue_inConstructor_named() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A({x : 2 + 3}) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstantDefaultValue_inConstructor_positional() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A([x = 2 + 3]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstantDefaultValue_method_named() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m({x : 2 + 3}) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstantDefaultValue_method_positional() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m([x = 2 + 3]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstantDefaultValue_typedConstList() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m([p111 = const <String>[]]) {}
 }
 class B extends A {
   m([p222 = const <String>[]]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstantValueInInitializer_namedArgument() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final a;
   const A({this.a});
 }
 class B extends A {
   const B({b}) : super(a: b);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstCaseExpression_constField() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 f(double p) {
   switch (p) {
     case double.INFINITY:
@@ -4085,15 +3350,14 @@
     default:
       return false;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
-    verify([source]);
+}
+''', [
+      error(CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, 16, 6),
+    ]);
   }
 
   test_nonConstCaseExpression_typeLiteral() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(Type t) {
   switch (t) {
     case bool:
@@ -4102,78 +3366,66 @@
     default:
       return false;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstListElement_constField() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main() {
   const [double.INFINITY];
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstMapAsExpressionStatement_const() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   const {'a' : 0, 'b' : 1};
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstMapAsExpressionStatement_notExpressionStatement() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   var m = {'a' : 0, 'b' : 1};
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstMapAsExpressionStatement_typeArguments() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   <String, int> {'a' : 0, 'b' : 1};
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstMapValue_constField() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main() {
   const {0: double.INFINITY};
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstValueInInitializer_binary_bool() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 class A {
   final v;
   const A.a1(bool p) : v = p && true;
   const A.a2(bool p) : v = true && p;
   const A.b1(bool p) : v = p || true;
   const A.b2(bool p) : v = true || p;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.DEAD_CODE]);
-    verify([source]);
+}
+''', [
+      error(HintCode.DEAD_CODE, 170, 1),
+    ]);
   }
 
   test_nonConstValueInInitializer_binary_dynamic() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final v;
   const A.a1(p) : v = p + 5;
@@ -4196,14 +3448,12 @@
   const A.i2(p) : v = 5 <= p;
   const A.j1(p) : v = p % 5;
   const A.j2(p) : v = 5 % p;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    // operations on "p" are not resolved
+}
+''');
   }
 
   test_nonConstValueInInitializer_binary_int() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final v;
   const A.a1(int p) : v = p ^ 5;
@@ -4216,14 +3466,12 @@
   const A.d2(int p) : v = 5 >> p;
   const A.e1(int p) : v = p << 5;
   const A.e2(int p) : v = 5 << p;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstValueInInitializer_binary_num() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final v;
   const A.a1(num p) : v = p + 5;
@@ -4246,212 +3494,171 @@
   const A.i2(num p) : v = 5 <= p;
   const A.j1(num p) : v = p % 5;
   const A.j2(num p) : v = 5 % p;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstValueInInitializer_field() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final int a;
   const A() : a = 5;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstValueInInitializer_redirecting() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   const A.named(p);
   const A() : this.named(42);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstValueInInitializer_super() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   const A(p);
 }
 class B extends A {
   const B() : super(42);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonConstValueInInitializer_unary() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   final v;
   const A.a(bool p) : v = !p;
   const A.b(int p) : v = ~p;
   const A.c(num p) : v = -p;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonGenerativeConstructor() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A.named() {}
   factory A() => null;
 }
 class B extends A {
   B() : super.named();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonTypeInCatchClause_isClass() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   try {
   } on String catch (e) {
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonTypeInCatchClause_isFunctionTypeAlias() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef F();
 f() {
   try {
   } on F catch (e) {
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonTypeInCatchClause_isTypeParameter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A<T> {
   f() {
     try {
     } on T catch (e) {
     }
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonTypeInCatchClause_noType() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   try {
   } catch (e) {
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonVoidReturnForOperator_no() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   operator []=(a, b) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonVoidReturnForOperator_void() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   void operator []=(a, b) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonVoidReturnForSetter_function_no() async {
-    Source source = addSource("set x(v) {}");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+set x(v) {}
+''');
   }
 
   test_nonVoidReturnForSetter_function_void() async {
-    Source source = addSource("void set x(v) {}");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+void set x(v) {}
+''');
   }
 
   test_nonVoidReturnForSetter_method_no() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   set x(v) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_nonVoidReturnForSetter_method_void() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   void set x(v) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   @failingTest
   test_null_callOperator() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 main() {
   null + 5;
   null == 5;
   null[0];
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticTypeWarningCode.UNDEFINED_METHOD,
-      StaticTypeWarningCode.UNDEFINED_METHOD
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_METHOD, 0, 0),
+      error(StaticTypeWarningCode.UNDEFINED_METHOD, 0, 0),
     ]);
   }
 
   test_optionalNew_rewrite() async {
-    resetWith(options: new AnalysisOptionsImpl());
-    Source source = addSource(r'''
-import 'b.dart';
-main() {
-  const B.named1();
-  const B.named2();
-  const B.named3();
-  const B.named4();
-}
-''');
-    addNamedSource("/a.dart", r'''
+    newFile("/test/lib/a.dart", content: r'''
 class A {
   const A();
   const A.named();
 }
 ''');
-    addNamedSource("/b.dart", r'''
+    newFile("/test/lib/b.dart", content: r'''
 import 'a.dart';
 import 'a.dart' as p;
 
@@ -4469,27 +3676,19 @@
   final A a;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode(r'''
+import 'b.dart';
+main() {
+  const B.named1();
+  const B.named2();
+  const B.named3();
+  const B.named4();
+}
+''');
   }
 
   test_optionalNew_rewrite_instantiatesToBounds() async {
-    resetWith(options: new AnalysisOptionsImpl());
-    Source source = addSource(r'''
-import 'b.dart';
-
-@B.named1()
-@B.named2()
-@B.named3()
-@B.named4()
-@B.named5()
-@B.named6()
-@B.named7()
-@B.named8()
-main() {}
-''');
-    addNamedSource("/a.dart", r'''
+    newFile("/test/lib/a.dart", content: r'''
 class Unbounded<T> {
   const Unbounded();
   const Unbounded.named();
@@ -4499,7 +3698,7 @@
   const Bounded.named();
 }
 ''');
-    addNamedSource("/b.dart", r'''
+    newFile("/test/lib/b.dart", content: r'''
 import 'a.dart';
 import 'a.dart' as p;
 
@@ -4526,7 +3725,19 @@
   final Bounded bounded;
 }
 ''');
-    final result = await computeAnalysisResult(source);
+    await assertNoErrorsInCode(r'''
+import 'b.dart';
+
+@B.named1()
+@B.named2()
+@B.named3()
+@B.named4()
+@B.named5()
+@B.named6()
+@B.named7()
+@B.named8()
+main() {}
+''');
     expect(result.unit.declarations, hasLength(1));
     final mainDecl = result.unit.declarations[0];
     expect(mainDecl.metadata, hasLength(8));
@@ -4548,24 +3759,20 @@
         expect(bounded.type.typeArguments[0].name, 'String');
       }
     });
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_optionalParameterInOperator_required() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   operator +(p) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_parameterScope_local() async {
     // Parameter names shouldn't conflict with the name of the function they
     // are enclosed in.
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   g(g) {
     h(g);
@@ -4573,15 +3780,12 @@
 }
 h(x) {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_parameterScope_method() async {
     // Parameter names shouldn't conflict with the name of the function they
     // are enclosed in.
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   g(g) {
     h(g);
@@ -4589,27 +3793,21 @@
 }
 h(x) {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_parameterScope_topLevel() async {
     // Parameter names shouldn't conflict with the name of the function they
     // are enclosed in.
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 g(g) {
   h(g);
 }
 h(x) {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_parametricCallFunction() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   var c = new C();
   c<String>().codeUnits;
@@ -4617,41 +3815,35 @@
 
 class C {
   T call<T>() => null;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_prefixCollidesWithTopLevelMembers() async {
-    addNamedSource("/lib.dart", r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 class A {}''');
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 import 'lib.dart' as p;
 typedef P();
 p2() {}
 var p3;
 class p4 {}
-p.A a;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+p.A a;
+''');
   }
 
   test_propagateTypeArgs_intoBounds() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A<E> {}
 abstract class B<F> implements A<F>{}
 abstract class C<G, H extends A<G>> {}
-class D<I> extends C<I, B<I>> {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+class D<I> extends C<I, B<I>> {}
+''');
   }
 
   test_propagateTypeArgs_intoSupertype() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A<T> {
   A(T p);
   A.named(T p);
@@ -4659,26 +3851,22 @@
 class B<S> extends A<S> {
   B(S p) : super(p);
   B.named(S p) : super.named(p);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_recursiveConstructorRedirect() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A.a() : this.b();
   A.b() : this.c();
   A.c() {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_recursiveFactoryRedirect() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   factory A() = B;
 }
@@ -4687,38 +3875,32 @@
 }
 class C implements B {
   factory C() => null;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_redirectToInvalidFunctionType() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A implements B {
   A(int p) {}
 }
 class B {
   factory B(int p) = A;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_redirectToNonConstConstructor() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   const A.a();
   const factory A.b() = A.a;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_referencedBeforeDeclaration_cascade() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 testRequestHandler() {}
 
 main() {
@@ -4727,141 +3909,114 @@
     ..stream(s1);
   var stream = 123;
   print(stream);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_referenceToDeclaredVariableInInitializer_constructorName() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A.x() {}
 }
 f() {
   var x = new A.x();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_referenceToDeclaredVariableInInitializer_methodName() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   x() {}
 }
 f(A a) {
   var x = a.x();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_referenceToDeclaredVariableInInitializer_propertyName() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   var x;
 }
 f(A a) {
   var x = a.x;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_regress34906() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef G<X, Y extends Function(X)> = X Function(Function(Y));
 G<dynamic, Function(Null)> superBoundedG;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_rethrowOutsideCatch() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   void m() {
     try {} catch (e) {rethrow;}
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_return_in_generator_async() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Stream<int> f() async* {
   return;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_return_in_generator_sync() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 Iterable<int> f() sync* {
   return;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_returnInGenerativeConstructor() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A() { return; }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_returnInGenerator_async() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() async {
   return 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_returnInGenerator_sync() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   return 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_returnOfInvalidType_async() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 import 'dart:async';
 class A {
   Future<int> m() async {
     return 0;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_returnOfInvalidType_dynamic() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class TypeError {}
 class A {
   static void testLogicalOp() {
@@ -4873,30 +4028,24 @@
       }
     }
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_returnOfInvalidType_subtype() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B extends A {}
-A f(B b) { return b; }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+A f(B b) { return b; }
+''');
   }
 
   test_returnOfInvalidType_supertype() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B extends A {}
-B f(A a) { return a; }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+B f(A a) { return a; }
+''');
   }
 
   test_returnOfInvalidType_typeParameter_18468() async {
@@ -4910,17 +4059,15 @@
     // returned out of the TestTypeProvider don't have a mock 'dart.core'
     // enclosing library element.
     // See TypeParameterTypeImpl.isMoreSpecificThan().
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class Foo<T> {
   Type get t => T;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_returnOfInvalidType_void() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 void f1() {}
 void f2() { return; }
 void f3() { return null; }
@@ -4930,101 +4077,86 @@
 g1() {}
 void g2() {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_returnWithoutValue_noReturnType() async {
-    Source source = addSource("f() { return; }");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+f() { return; }
+''');
   }
 
   test_returnWithoutValue_void() async {
-    Source source = addSource("void f() { return; }");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+void f() { return; }
+''');
   }
 
   test_reversedTypeArguments() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class Codec<S1, T1> {
   Codec<T1, S1> get inverted => new _InvertedCodec<T1, S1>(this);
 }
 class _InvertedCodec<T2, S2> extends Codec<T2, S2> {
   _InvertedCodec(Codec<S2, T2> codec);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_sharedDeferredPrefix() async {
-    await resolveWithErrors(<String>[
-      r'''
-library lib1;
-f1() {}''',
-      r'''
-library lib2;
-f2() {}''',
-      r'''
-library lib3;
-f3() {}''',
-      r'''
-library root;
+    newFile('/test/lib/lib1.dart', content: r'''
+f1() {}
+''');
+    newFile('/test/lib/lib2.dart', content: r'''
+f2() {}
+''');
+    newFile('/test/lib/lib3.dart', content: r'''
+f3() {}
+''');
+    await assertNoErrorsInCode(r'''
 import 'lib1.dart' deferred as lib1;
 import 'lib2.dart' as lib;
 import 'lib3.dart' as lib;
-main() { lib1.f1(); lib.f2(); lib.f3(); }'''
-    ], <ErrorCode>[]);
+main() { lib1.f1(); lib.f2(); lib.f3(); }
+''');
   }
 
   test_staticAccessToInstanceMember_annotation() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   const A.name();
 }
 @A.name()
 main() {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_staticAccessToInstanceMember_method() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   static m() {}
 }
 main() {
   A.m;
   A.m();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_staticAccessToInstanceMember_propertyAccess_field() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   static var f;
 }
 main() {
   A.f;
   A.f = 1;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_staticAccessToInstanceMember_propertyAccess_propertyAccessor() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   static get f => 42;
   static set f(x) {}
@@ -5032,14 +4164,12 @@
 main() {
   A.f;
   A.f = 1;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_superInInvalidContext() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m() {}
 }
@@ -5050,114 +4180,102 @@
   n() {
     var v = super.m();
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typeAliasCannotReferenceItself_returnClass_withTypeAlias() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef B A();
 class B {
   A a;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typeArgument_boundToFunctionType() async {
-    Source source = addSource("class A<T extends void Function(T)>{}");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await assertNoErrorsInCode('''
+class A<T extends void Function(T)>{}
+''');
   }
 
   test_typeArgumentNotMatchingBounds_const() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B extends A {}
 class G<E extends A> {
   const G();
 }
-f() { return const G<B>(); }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+f() { return const G<B>(); }
+''');
   }
 
   test_typeArgumentNotMatchingBounds_new() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B extends A {}
 class G<E extends A> {}
-f() { return new G<B>(); }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+f() { return new G<B>(); }
+''');
   }
 
   test_typeArgumentNotMatchingBounds_ofFunctionTypeAlias_hasBound() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B extends A {}
 typedef F<T extends A>();
 F<A> fa;
 F<B> fb;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_typeArgumentNotMatchingBounds_ofFunctionTypeAlias_hasBound2() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class MyClass<T> {}
 typedef MyFunction<T, P extends MyClass<T>>();
 class A<T, P extends MyClass<T>> {
   MyFunction<T, P> f;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_typeArgumentNotMatchingBounds_ofFunctionTypeAlias_noBound() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef F<T>();
 F<int> f1;
 F<String> f2;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+  }
+
+  test_typedef_not_function() async {
+    newFile('/test/lib/a.dart', content: '''
+typedef F = int;
+''');
+    await assertNoErrorsInCode('''
+import 'a.dart';
+F f;
+''');
   }
 
   test_typePromotion_booleanAnd_useInRight() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main(Object p) {
   p is String && p.length != 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_booleanAnd_useInRight_accessedInClosureRight_noAssignment() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 callMe(f()) { f(); }
 main(Object p) {
   (p is String) && callMe(() { p.length; });
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_conditional_issue14655() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B extends A {}
 class C extends B {
@@ -5166,35 +4284,28 @@
 print(_) {}
 main(A p) {
   (p is C) && (print(() => p) && (p is B)) ? p.mc() : p = null;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_conditional_useInThen() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main(Object p) {
   p is String ? p.length : 0;
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_typePromotion_conditional_useInThen_accessedInClosure_noAssignment() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 callMe(f()) { f(); }
 main(Object p) {
   p is String ? callMe(() { p.length; }) : 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_functionType_arg_ignoreIfNotMoreSpecific() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef FuncB(B b);
 typedef FuncA(A a);
 class A {}
@@ -5203,14 +4314,12 @@
   if (f is FuncB) {
     f(new A());
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_functionType_return_ignoreIfNotMoreSpecific() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 typedef FuncAtoDyn(A a);
 typedef FuncDynToDyn(x);
@@ -5218,14 +4327,12 @@
   if (f is FuncDynToDyn) {
     A a = f(new A());
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_functionType_return_voidToDynamic() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef FuncDynToDyn(x);
 typedef void FuncDynToVoid(x);
 class A {}
@@ -5233,14 +4340,12 @@
   if (f is FuncDynToDyn) {
     A a = f(null);
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_if_accessedInClosure_noAssignment() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 callMe(f()) { f(); }
 main(Object p) {
   if (p is String) {
@@ -5248,14 +4353,12 @@
       p.length;
     });
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_if_extends_moreSpecific() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class V {}
 class VP extends V {}
 class A<T> {}
@@ -5267,40 +4370,33 @@
   if (p is B<VP>) {
     p.b;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_if_hasAssignment_outsideAfter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main(Object p) {
   if (p is String) {
     p.length;
   }
   p = 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_if_hasAssignment_outsideBefore() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main(Object p, Object p2) {
   p = p2;
   if (p is String) {
     p.length;
   }
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_typePromotion_if_implements_moreSpecific() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class V {}
 class VP extends V {}
 class A<T> {}
@@ -5312,14 +4408,12 @@
   if (p is B<VP>) {
     p.b;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_if_inClosure_assignedAfter_inSameFunction() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main() {
   f(Object p) {
     if (p is String) {
@@ -5327,40 +4421,34 @@
     }
     p = 0;
   };
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_if_is_and_left() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 bool tt() => true;
 main(Object p) {
   if (p is String && tt()) {
     p.length;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_if_is_and_right() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 bool tt() => true;
 main(Object p) {
   if (tt() && p is String) {
     p.length;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_if_is_and_subThenSuper() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   var a;
 }
@@ -5372,197 +4460,166 @@
     p.a;
     p.b;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_if_is_parenthesized() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main(Object p) {
   if ((p is String)) {
     p.length;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_if_is_single() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main(Object p) {
   if (p is String) {
     p.length;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typePromotion_parentheses() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main(Object p) {
   (p is String) ? p.length : 0;
   (p) is String ? p.length : 0;
   ((p)) is String ? p.length : 0;
   ((p) is String) ? p.length : 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typeType_class() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class C {}
 f(Type t) {}
 main() {
   f(C);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typeType_class_prefixed() async {
-    addNamedSource("/lib.dart", r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 class C {}''');
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 import 'lib.dart' as p;
 f(Type t) {}
 main() {
   f(p.C);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typeType_functionTypeAlias() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef F();
 f(Type t) {}
 main() {
   f(F);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_typeType_functionTypeAlias_prefixed() async {
-    addNamedSource("/lib.dart", r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 typedef F();''');
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 import 'lib.dart' as p;
 f(Type t) {}
 main() {
   f(p.F);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_undefinedConstructorInInitializer_explicit_named() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A.named() {}
 }
 class B extends A {
   B() : super.named();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_undefinedConstructorInInitializer_explicit_unnamed() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A() {}
 }
 class B extends A {
   B() : super();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_undefinedConstructorInInitializer_hasOptionalParameters() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A([p]) {}
 }
 class B extends A {
   B();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_undefinedConstructorInInitializer_implicit() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   A() {}
 }
 class B extends A {
   B();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_undefinedConstructorInInitializer_redirecting() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class Foo {
   Foo.ctor();
 }
 class Bar extends Foo {
   Bar() : this.ctor();
   Bar.ctor() : super.ctor();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   @failingTest
   test_undefinedEnumConstant() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 enum E { ONE }
 E e() {
   return E.TWO;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_undefinedGetter_static_conditionalAccess() async {
     // The conditional access operator '?.' can be used to access static
     // fields.
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class A {
   static var x;
 }
 var a = A?.x;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_undefinedGetter_typeSubstitution() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A<E> {
   E element;
 }
@@ -5570,72 +4627,63 @@
   m() {
     element.last;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_undefinedIdentifier_synthetic_whenExpression() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 print(x) {}
 main() {
   print(is String);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [ParserErrorCode.MISSING_IDENTIFIER]);
+}
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 29, 2),
+    ]);
   }
 
   test_undefinedIdentifier_synthetic_whenMethodName() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 print(x) {}
 main(int p) {
   p.();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      StaticTypeWarningCode.UNDEFINED_GETTER
+}
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 30, 1),
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 30, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 31, 1),
     ]);
   }
 
   test_undefinedMethod_functionExpression_callMethod() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main() {
   (() => null).call();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    // A call to verify(source) fails as '.call()' isn't resolved.
+}
+''');
   }
 
   test_undefinedMethod_functionExpression_directCall() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 main() {
   (() => null)();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    // A call to verify(source) fails as '(() => null)()' isn't resolved.
+}
+''');
   }
 
   test_undefinedMethod_static_conditionalAccess() async {
     // The conditional access operator '?.' can be used to access static
     // methods.
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class A {
   static void m() {}
 }
 f() { A?.m(); }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_undefinedOperator_index() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   operator [](a) {}
   operator []=(a, b) {}
@@ -5643,51 +4691,42 @@
 f(A a) {
   a[0];
   a[0] = 1;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_undefinedOperator_tilde() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 const A = 3;
-const B = ~((1 << A) - 1);''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+const B = ~((1 << A) - 1);
+''');
   }
 
   test_undefinedSetter_importWithPrefix() async {
-    addNamedSource("/lib.dart", r'''
+    newFile("/test/lib/lib.dart", content: r'''
 library lib;
 set y(int value) {}''');
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 import 'lib.dart' as x;
 main() {
   x.y = 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_undefinedSetter_static_conditionalAccess() async {
     // The conditional access operator '?.' can be used to access static
     // fields.
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class A {
   static var x;
 }
 f() { A?.x = 1; }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_undefinedSuperMethod_field() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   var m;
 }
@@ -5695,14 +4734,12 @@
   f() {
     super.m();
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_undefinedSuperMethod_method() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   m() {}
 }
@@ -5710,53 +4747,48 @@
   f() {
     super.m();
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_unusedShownName_unresolved() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 import 'dart:math' show max, FooBar;
 main() {
   print(max(1, 2));
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNDEFINED_SHOWN_NAME]);
+''', [
+      error(HintCode.UNDEFINED_SHOWN_NAME, 29, 6),
+    ]);
   }
 
   test_uriDoesNotExist_dll() async {
-    addNamedSource("/lib.dll", "");
-    Source source = addSource("import 'dart-ext:lib';");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+    newFile("/test/lib/lib.dll");
+    await assertNoErrorsInCode('''
+import 'dart-ext:lib';
+''');
   }
 
   test_uriDoesNotExist_dylib() async {
-    addNamedSource("/lib.dylib", "");
-    Source source = addSource("import 'dart-ext:lib';");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+    newFile("/test/lib/lib.dylib");
+    await assertNoErrorsInCode('''
+import 'dart-ext:lib';
+''');
   }
 
   test_uriDoesNotExist_so() async {
-    addNamedSource("/lib.so", "");
-    Source source = addSource("import 'dart-ext:lib';");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+    newFile("/test/lib/lib.so");
+    await assertNoErrorsInCode('''
+import 'dart-ext:lib';
+''');
   }
 
   Future test_useDynamicWithPrefix() async {
-    final Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:core' as core;
 
 core.dynamic dynamicVariable;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_wrongNumberOfParametersForOperator1() async {
@@ -5778,13 +4810,11 @@
   }
 
   test_wrongNumberOfParametersForOperator_index() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   operator []=(a, b) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_wrongNumberOfParametersForOperator_minus() async {
@@ -5793,293 +4823,218 @@
   }
 
   test_wrongNumberOfParametersForSetter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   set x(a) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_yield_async_to_dynamic_type() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 dynamic f() async* {
   yield 3;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_async_to_generic_type() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Stream f() async* {
   yield 3;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_async_to_parameterized_type() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Stream<int> f() async* {
   yield 3;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_async_to_untyped() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() async* {
   yield 3;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_async_dynamic_to_dynamic() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() async* {
   yield* g();
 }
 g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_async_dynamic_to_stream() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Stream f() async* {
   yield* g();
 }
 g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_async_dynamic_to_typed_stream() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Stream<int> f() async* {
   yield* g();
 }
 g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_async_stream_to_dynamic() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 f() async* {
   yield* g();
 }
 Stream g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_async_typed_stream_to_dynamic() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 f() async* {
   yield* g();
 }
 Stream<int> g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_async_typed_stream_to_typed_stream() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 Stream<int> f() async* {
   yield* g();
 }
 Stream<int> g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_sync_dynamic_to_dynamic() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() sync* {
   yield* g();
 }
 g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_sync_dynamic_to_iterable() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 Iterable f() sync* {
   yield* g();
 }
 g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_sync_dynamic_to_typed_iterable() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 Iterable<int> f() sync* {
   yield* g();
 }
 g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_sync_iterable_to_dynamic() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() sync* {
   yield* g();
 }
 Iterable g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_sync_typed_iterable_to_dynamic() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() sync* {
   yield* g();
 }
 Iterable<int> g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_each_sync_typed_iterable_to_typed_iterable() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 Iterable<int> f() sync* {
   yield* g();
 }
 Iterable<int> g() => null;
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_sync_to_dynamic_type() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 dynamic f() sync* {
   yield 3;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_sync_to_generic_type() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 Iterable f() sync* {
   yield 3;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_sync_to_parameterized_type() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 Iterable<int> f() sync* {
   yield 3;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yield_sync_to_untyped() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 f() sync* {
   yield 3;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_yieldInNonGenerator_asyncStar() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() async* {
   yield 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_yieldInNonGenerator_syncStar() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() sync* {
   yield 0;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   Future<void> _check_wrongNumberOfParametersForOperator(
       String name, String parameters) async {
-    Source source = addSource("""
+    await assertNoErrorsInCode('''
 class A {
   operator $name($parameters) {}
-}""");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   Future<void> _check_wrongNumberOfParametersForOperator1(String name) async {
     await _check_wrongNumberOfParametersForOperator(name, "a");
   }
 }
-
-@reflectiveTest
-class NonErrorResolverWithUiAsCodeTest extends NonErrorResolverTest {
-  @override
-  List<String> get enabledExperiments =>
-      [EnableString.spread_collections, EnableString.control_flow_collections];
-}
diff --git a/pkg/analyzer/test/generated/non_hint_code_test.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
index 24c5811..eb33500 100644
--- a/pkg/analyzer/test/generated/non_hint_code_test.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../src/dart/resolution/driver_resolution.dart';
 import 'resolver_test_case.dart';
 
 main() {
@@ -15,34 +16,31 @@
 }
 
 @reflectiveTest
-class NonHintCodeTest extends ResolverTestCase {
+class NonHintCodeTest extends DriverResolutionTest {
   test_async_future_object_without_return() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 import 'dart:async';
 Future<Object> f() async {}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.MISSING_RETURN]);
-    verify([source]);
+''', [
+      error(HintCode.MISSING_RETURN, 21, 14),
+    ]);
   }
 
   test_issue20904BuggyTypePromotionAtIfJoin_1() async {
     // https://code.google.com/p/dart/issues/detail?id=20904
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(var message, var dynamic_) {
   if (message is Function) {
     message = dynamic_;
   }
   int s = message;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_issue20904BuggyTypePromotionAtIfJoin_3() async {
     // https://code.google.com/p/dart/issues/detail?id=20904
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(var message) {
   var dynamic_;
   if (message is Function) {
@@ -51,15 +49,13 @@
     return;
   }
   int s = message;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_issue20904BuggyTypePromotionAtIfJoin_4() async {
     // https://code.google.com/p/dart/issues/detail?id=20904
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f(var message) {
   if (message is Function) {
     message = '';
@@ -67,14 +63,12 @@
     return;
   }
   String s = message;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_propagatedFieldType() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A { }
 class X<T> {
   final x = new List<T>();
@@ -84,14 +78,12 @@
   foo() {
     y.x.add(new A());
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_proxy_annotation_prefixed() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 library L;
 @proxy
 class A {}
@@ -103,13 +95,12 @@
   var y = a + a;
   a++;
   ++a;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+}
+''');
   }
 
   test_proxy_annotation_prefixed2() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 library L;
 @proxy
 class A {}
@@ -123,13 +114,12 @@
     a++;
     ++a;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+}
+''');
   }
 
   test_proxy_annotation_prefixed3() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 library L;
 class B {
   f(var a) {
@@ -143,13 +133,12 @@
   }
 }
 @proxy
-class A {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+class A {}
+''');
   }
 
   test_undefinedMethod_assignmentExpression_inSubtype() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B extends A {
   operator +(B b) {return new B();}
@@ -158,23 +147,21 @@
   a = new A();
   a2 = new A();
   a += a2;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+}
+''');
   }
 
   test_undefinedMethod_dynamic() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class D<T extends dynamic> {
   fieldAccess(T t) => t.abc;
   methodAccess(T t) => t.xyz(1, 2, 'three');
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+}
+''');
   }
 
   test_undefinedMethod_unionType_all() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int m(int x) => 0;
 }
@@ -189,13 +176,12 @@
     ab = b;
   }
   ab.m();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+}
+''');
   }
 
   test_undefinedMethod_unionType_some() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int m(int x) => 0;
 }
@@ -208,9 +194,8 @@
     ab = b;
   }
   ab.m(0);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+}
+''');
   }
 }
 
@@ -219,24 +204,24 @@
   //  the first would fail. We should implement these checks and enable the
   //  tests.
   test_import_package() async {
-    Source source = addSource("import 'package:somepackage/other.dart';");
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+    await assertErrorsInCode('''
+import 'package:somepackage/other.dart';
+''', [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
   }
 
   test_import_packageWithDotDot() async {
-    Source source = addSource("import 'package:somepackage/../other.dart';");
-    await computeAnalysisResult(source);
-    assertErrors(source, [
+    await assertErrorsInCode('''
+import 'package:somepackage/../other.dart';
+''', [
       CompileTimeErrorCode.URI_DOES_NOT_EXIST,
       HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT
     ]);
   }
 
   test_import_packageWithLeadingDotDot() async {
-    Source source = addSource("import 'package:../other.dart';");
-    await computeAnalysisResult(source);
-    assertErrors(source, [
+    await assertErrorsInCode('''
+import 'package:../other.dart';
+''', [
       CompileTimeErrorCode.URI_DOES_NOT_EXIST,
       HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT
     ]);
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index 45b0b61..a8a660d 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -108,12 +108,6 @@
   }
 
   @override
-  void beginClassOrMixinBody(Token token) {
-    super.beginClassOrMixinBody(token);
-    begin('ClassOrMixinBody');
-  }
-
-  @override
   void beginClassDeclaration(
       Token beginToken, Token abstractToken, Token name) {
     super.beginClassDeclaration(beginToken, abstractToken, name);
@@ -121,6 +115,12 @@
   }
 
   @override
+  void beginClassOrMixinBody(Token token) {
+    super.beginClassOrMixinBody(token);
+    begin('ClassOrMixinBody');
+  }
+
+  @override
   void beginClassOrNamedMixinApplication(Token token) {
     super.beginClassOrNamedMixinApplication(token);
     begin('ClassOrNamedMixinApplication');
@@ -201,6 +201,12 @@
   }
 
   @override
+  void beginExtensionDeclaration(Token extensionKeyword, Token name) {
+    super.beginExtensionDeclaration(extensionKeyword, name);
+    begin('ExtensionDeclaration');
+  }
+
+  @override
   void beginFactoryMethod(
       Token lastConsumed, Token externalToken, Token constToken) {
     super.beginFactoryMethod(lastConsumed, externalToken, constToken);
@@ -232,21 +238,10 @@
   }
 
   @override
-  void beginForStatement(Token token) {
-    super.beginForStatement(token);
-    begin('ForStatement');
-  }
-
-  @override
-  void beginForStatementBody(Token token) {
-    super.beginForStatementBody(token);
-    begin('ForStatementBody');
-  }
-
-  @override
-  void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
-      Token varFinalOrConst) {
-    super.beginFormalParameter(token, kind, covariantToken, varFinalOrConst);
+  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+      Token covariantToken, Token varFinalOrConst) {
+    super.beginFormalParameter(
+        token, kind, requiredToken, covariantToken, varFinalOrConst);
     begin('FormalParameter');
   }
 
@@ -257,15 +252,15 @@
   }
 
   @override
-  void beginIfControlFlow(Token ifToken) {
-    super.beginIfControlFlow(ifToken);
-    begin('IfControlFlow');
+  void beginForStatement(Token token) {
+    super.beginForStatement(token);
+    begin('ForStatement');
   }
 
   @override
-  void beginLocalFunctionDeclaration(Token token) {
-    super.beginLocalFunctionDeclaration(token);
-    begin('LocalFunctionDeclaration');
+  void beginForStatementBody(Token token) {
+    super.beginForStatementBody(token);
+    begin('ForStatementBody');
   }
 
   @override
@@ -305,6 +300,12 @@
   }
 
   @override
+  void beginIfControlFlow(Token ifToken) {
+    super.beginIfControlFlow(ifToken);
+    begin('IfControlFlow');
+  }
+
+  @override
   void beginIfStatement(Token token) {
     super.beginIfStatement(token);
     begin('IfStatement');
@@ -359,6 +360,12 @@
   }
 
   @override
+  void beginLocalFunctionDeclaration(Token token) {
+    super.beginLocalFunctionDeclaration(token);
+    begin('LocalFunctionDeclaration');
+  }
+
+  @override
   void beginMember() {
     expectIn('ClassOrMixinBody');
     super.beginMember();
@@ -526,8 +533,9 @@
   }
 
   @override
-  void beginVariablesDeclaration(Token token, Token varFinalOrConst) {
-    super.beginVariablesDeclaration(token, varFinalOrConst);
+  void beginVariablesDeclaration(
+      Token token, Token lateToken, Token varFinalOrConst) {
+    super.beginVariablesDeclaration(token, lateToken, varFinalOrConst);
     begin('VariablesDeclaration');
   }
 
@@ -600,12 +608,6 @@
   }
 
   @override
-  void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
-    end('ClassOrMixinBody');
-    super.endClassOrMixinBody(memberCount, beginToken, endToken);
-  }
-
-  @override
   void endClassDeclaration(Token beginToken, Token endToken) {
     end('ClassDeclaration');
     end('ClassOrNamedMixinApplication');
@@ -613,6 +615,12 @@
   }
 
   @override
+  void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
+    end('ClassOrMixinBody');
+    super.endClassOrMixinBody(memberCount, beginToken, endToken);
+  }
+
+  @override
   void endCombinators(int count) {
     end('Combinators');
     super.endCombinators(count);
@@ -688,6 +696,12 @@
   }
 
   @override
+  void endExtensionDeclaration(Token onKeyword, Token token) {
+    super.endExtensionDeclaration(onKeyword, token);
+    end('ExtensionDeclaration');
+  }
+
+  @override
   void endFactoryMethod(
       Token beginToken, Token factoryKeyword, Token endToken) {
     end('FactoryMethod');
@@ -701,12 +715,12 @@
   }
 
   @override
-  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
-      int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     // beginMember --> endFields, endMember
     expectIn('Member');
-    super.endFields(staticToken, covariantToken, varFinalOrConst, count,
-        beginToken, endToken);
+    super.endFields(staticToken, covariantToken, lateToken, varFinalOrConst,
+        count, beginToken, endToken);
   }
 
   @override
@@ -716,12 +730,6 @@
   }
 
   @override
-  void endForInControlFlow(Token token) {
-    end('ForControlFlow');
-    super.endForInControlFlow(token);
-  }
-
-  @override
   void endForIn(Token endToken) {
     end('ForStatement');
     super.endForIn(endToken);
@@ -734,24 +742,18 @@
   }
 
   @override
+  void endForInControlFlow(Token token) {
+    end('ForControlFlow');
+    super.endForInControlFlow(token);
+  }
+
+  @override
   void endForInExpression(Token token) {
     end('ForInExpression');
     super.endForInExpression(token);
   }
 
   @override
-  void endForStatement(Token endToken) {
-    end('ForStatement');
-    super.endForStatement(endToken);
-  }
-
-  @override
-  void endForStatementBody(Token token) {
-    end('ForStatementBody');
-    super.endForStatementBody(token);
-  }
-
-  @override
   void endFormalParameter(Token thisKeyword, Token periodAfterThis,
       Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
     end('FormalParameter');
@@ -767,9 +769,15 @@
   }
 
   @override
-  void endLocalFunctionDeclaration(Token endToken) {
-    end('LocalFunctionDeclaration');
-    super.endLocalFunctionDeclaration(endToken);
+  void endForStatement(Token endToken) {
+    end('ForStatement');
+    super.endForStatement(endToken);
+  }
+
+  @override
+  void endForStatementBody(Token token) {
+    end('ForStatementBody');
+    super.endForStatementBody(token);
   }
 
   @override
@@ -798,9 +806,9 @@
   }
 
   @override
-  void endFunctionTypedFormalParameter(Token nameToken) {
+  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
     end('FunctionTypedFormalParameter');
-    super.endFunctionTypedFormalParameter(nameToken);
+    super.endFunctionTypedFormalParameter(nameToken, question);
   }
 
   @override
@@ -876,6 +884,12 @@
   }
 
   @override
+  void endLocalFunctionDeclaration(Token endToken) {
+    end('LocalFunctionDeclaration');
+    super.endLocalFunctionDeclaration(endToken);
+  }
+
+  @override
   void endMember() {
     end('Member');
     super.endMember();
@@ -1014,11 +1028,17 @@
   }
 
   @override
-  void endTopLevelFields(Token staticToken, Token covariantToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
     end('TopLevelMember');
-    super.endTopLevelFields(staticToken, covariantToken, varFinalOrConst, count,
-        beginToken, endToken);
+    super.endTopLevelFields(staticToken, covariantToken, lateToken,
+        varFinalOrConst, count, beginToken, endToken);
   }
 
   @override
@@ -1108,33 +1128,23 @@
   }
 
   @override
-  void handleIdentifierList(int count) {
-    expectInOneOf(['Hide', 'Show']);
-    super.handleIdentifierList(count);
-  }
-
-  @override
   void handleDottedName(int count, Token firstIdentifier) {
     expectIn('ConditionalUri');
     super.handleDottedName(count, firstIdentifier);
   }
 
   @override
-  void handleRecoverClassHeader() {
-    expectIn('ClassDeclaration');
-    listener.handleRecoverClassHeader();
+  void handleIdentifierList(int count) {
+    expectInOneOf(['Hide', 'Show']);
+    super.handleIdentifierList(count);
   }
 
   @override
-  void handleRecoverImport(Token semicolon) {
-    expectIn('CompilationUnit');
-    listener.handleRecoverImport(semicolon);
-  }
-
-  @override
-  void handleRecoverMixinHeader() {
-    expectIn('MixinDeclaration');
-    listener.handleRecoverMixinHeader();
+  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+    // This event normally happens within "Import",
+    // but happens within "CompilationUnit" during recovery.
+    expectInOneOf(const ['Import', 'CompilationUnit']);
+    listener.handleImportPrefix(deferredKeyword, asKeyword);
   }
 
   @override
@@ -1174,11 +1184,21 @@
   }
 
   @override
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
-    // This event normally happens within "Import",
-    // but happens within "CompilationUnit" during recovery.
-    expectInOneOf(const ['Import', 'CompilationUnit']);
-    listener.handleImportPrefix(deferredKeyword, asKeyword);
+  void handleRecoverClassHeader() {
+    expectIn('ClassDeclaration');
+    listener.handleRecoverClassHeader();
+  }
+
+  @override
+  void handleRecoverImport(Token semicolon) {
+    expectIn('CompilationUnit');
+    listener.handleRecoverImport(semicolon);
+  }
+
+  @override
+  void handleRecoverMixinHeader() {
+    expectIn('MixinDeclaration');
+    listener.handleRecoverMixinHeader();
   }
 
   @override
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index ef81da6..291c7ff 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart' as analyzer;
 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
@@ -18,11 +19,12 @@
 import 'package:front_end/src/fasta/parser/async_modifier.dart';
 import 'package:front_end/src/fasta/parser/forwarding_listener.dart' as fasta;
 import 'package:front_end/src/fasta/parser/parser.dart' as fasta;
+import 'package:front_end/src/fasta/scanner.dart' as fasta;
 import 'package:front_end/src/fasta/scanner.dart'
-    show ScannerResult, scanString;
+    show LanguageVersionToken, ScannerConfiguration, ScannerResult, scanString;
 import 'package:front_end/src/fasta/scanner/error_token.dart' show ErrorToken;
 import 'package:front_end/src/fasta/scanner/string_scanner.dart';
-import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
+import 'package:pub_semver/src/version.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -34,6 +36,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ClassMemberParserTest_Fasta);
+    defineReflectiveTests(ExtensionMethodsParserTest_Fasta);
     defineReflectiveTests(CollectionLiteralParserTest);
     defineReflectiveTests(ComplexParserTest_Fasta);
     defineReflectiveTests(ErrorParserTest_Fasta);
@@ -55,10 +58,13 @@
 @reflectiveTest
 class ClassMemberParserTest_Fasta extends FastaParserTestCase
     with ClassMemberParserTestMixin {
+  final tripleShift = FeatureSet.forTesting(
+      sdkVersion: '2.0.0', additionalFeatures: [Feature.triple_shift]);
+
   void test_parseClassMember_operator_gtgtgt() {
     CompilationUnitImpl unit = parseCompilationUnit(
         'class C { bool operator >>>(other) => false; }',
-        enableGtGtGt: true);
+        featureSet: tripleShift);
     ClassDeclaration declaration = unit.declarations[0];
     MethodDeclaration method = declaration.members[0];
 
@@ -77,7 +83,7 @@
   void test_parseClassMember_operator_gtgtgteq() {
     CompilationUnitImpl unit = parseCompilationUnit(
         'class C { foo(int value) { x >>>= value; } }',
-        enableGtGtGtEq: true);
+        featureSet: tripleShift);
     ClassDeclaration declaration = unit.declarations[0];
     MethodDeclaration method = declaration.members[0];
     BlockFunctionBody blockFunctionBody = method.body;
@@ -91,6 +97,184 @@
     SimpleIdentifier rightHandSide = assignment.rightHandSide;
     expect(rightHandSide.name, 'value');
   }
+
+  void test_parseField_const_late() {
+    createParser('const late T f = 0;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 6, 4),
+    ]);
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isTrue);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_final_late() {
+    createParser('final late T f;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4),
+    ]);
+    expect(member, isNotNull);
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isTrue);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_late() {
+    createParser('late T f;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_late_const() {
+    createParser('late const T f = 0;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 5, 5),
+    ]);
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isTrue);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_late_final() {
+    createParser('late final T f;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isTrue);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_late_var() {
+    createParser('late var f;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 5, 3),
+    ]);
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_var_late() {
+    createParser('var late f;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 4, 4),
+    ]);
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
 }
 
 /**
@@ -108,8 +292,12 @@
         errors: errors,
         expectedEndOffset: expectedEndOffset,
         inAsync: inAsync,
-        parseSpreadCollections: true,
-        parseControlFlowCollections: true);
+        featureSet: FeatureSet.forTesting(
+            sdkVersion: '2.0.0',
+            additionalFeatures: [
+              Feature.spread_collections,
+              Feature.control_flow_collections
+            ]));
   }
 
   void test_listLiteral_for() {
@@ -933,6 +1121,8 @@
 @reflectiveTest
 class ExpressionParserTest_Fasta extends FastaParserTestCase
     with ExpressionParserTestMixin {
+  final beforeUiAsCode = FeatureSet.forTesting(sdkVersion: '2.2.0');
+
   void test_binaryExpression_allOperators() {
     // https://github.com/dart-lang/sdk/issues/36255
     for (TokenType type in TokenType.all) {
@@ -948,9 +1138,9 @@
     }
   }
 
-  void test_listLiteral_spread() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
-    ListLiteral list = parseExpression('[1, ...[2]]', errors: [
+  void test_listLiteral_spread_disabled() {
+    ListLiteral list =
+        parseExpression('[1, ...[2]]', featureSet: beforeUiAsCode, errors: [
       expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 4, 3),
     ]);
     expect(list.elements, hasLength(1));
@@ -958,9 +1148,9 @@
     expect(first.value, 1);
   }
 
-  void test_listLiteral_spreadQ() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
-    ListLiteral list = parseExpression('[1, ...?[2]]', errors: [
+  void test_listLiteral_spreadQ_disabled() {
+    ListLiteral list =
+        parseExpression('[1, ...?[2]]', featureSet: beforeUiAsCode, errors: [
       expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 4, 4),
     ]);
     expect(list.elements, hasLength(1));
@@ -992,8 +1182,9 @@
     expect(value.value, 6);
   }
 
-  void test_mapLiteral_invalid_set_entry() {
-    SetOrMapLiteral map = parseExpression('<int, int>{1}', errors: [
+  void test_mapLiteral_invalid_set_entry_uiAsCodeDisabled() {
+    SetOrMapLiteral map =
+        parseExpression('<int, int>{1}', featureSet: beforeUiAsCode, errors: [
       expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 1),
       expectedError(ParserErrorCode.MISSING_IDENTIFIER, 12, 1),
     ]);
@@ -1032,63 +1223,67 @@
     expect(map.elements, hasLength(0));
   }
 
-  void test_mapLiteral_spread() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
-    SetOrMapLiteral map = parseExpression('{1: 2, ...{3: 4}}', errors: [
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 7, 3),
-    ]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_spread2_typed() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
-    SetOrMapLiteral map =
-        parseExpression('<int, int>{1: 2, ...{3: 4}}', errors: [
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 17, 3),
-    ]);
+  void test_mapLiteral_spread2_typed_disabled() {
+    SetOrMapLiteral map = parseExpression('<int, int>{1: 2, ...{3: 4}}',
+        featureSet: beforeUiAsCode,
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 17, 3),
+        ]);
     expect(map.constKeyword, isNull);
     expect(map.typeArguments.arguments, hasLength(2));
     expect(map.elements, hasLength(1));
   }
 
-  void test_mapLiteral_spread_typed() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
-    SetOrMapLiteral map = parseExpression('<int, int>{...{3: 4}}', errors: [
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 11, 3),
-    ]);
+  void test_mapLiteral_spread_disabled() {
+    SetOrMapLiteral map = parseExpression('{1: 2, ...{3: 4}}',
+        featureSet: beforeUiAsCode,
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 7, 3),
+        ]);
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments, isNull);
+    expect(map.elements, hasLength(1));
+  }
+
+  void test_mapLiteral_spread_typed_disabled() {
+    SetOrMapLiteral map = parseExpression('<int, int>{...{3: 4}}',
+        featureSet: beforeUiAsCode,
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 11, 3),
+        ]);
     expect(map.constKeyword, isNull);
     expect(map.typeArguments.arguments, hasLength(2));
     expect(map.elements, hasLength(0));
   }
 
-  void test_mapLiteral_spreadQ() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
-    SetOrMapLiteral map = parseExpression('{1: 2, ...?{3: 4}}', errors: [
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 7, 4),
-    ]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_spreadQ2_typed() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
-    SetOrMapLiteral map =
-        parseExpression('<int, int>{1: 2, ...?{3: 4}}', errors: [
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 17, 4),
-    ]);
+  void test_mapLiteral_spreadQ2_typed_disabled() {
+    SetOrMapLiteral map = parseExpression('<int, int>{1: 2, ...?{3: 4}}',
+        featureSet: beforeUiAsCode,
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 17, 4),
+        ]);
     expect(map.constKeyword, isNull);
     expect(map.typeArguments.arguments, hasLength(2));
     expect(map.elements, hasLength(1));
   }
 
-  void test_mapLiteral_spreadQ_typed() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
-    SetOrMapLiteral map = parseExpression('<int, int>{...?{3: 4}}', errors: [
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 11, 4),
-    ]);
+  void test_mapLiteral_spreadQ_disabled() {
+    SetOrMapLiteral map = parseExpression('{1: 2, ...?{3: 4}}',
+        featureSet: beforeUiAsCode,
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 7, 4),
+        ]);
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments, isNull);
+    expect(map.elements, hasLength(1));
+  }
+
+  void test_mapLiteral_spreadQ_typed_disabled() {
+    SetOrMapLiteral map = parseExpression('<int, int>{...?{3: 4}}',
+        featureSet: beforeUiAsCode,
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 11, 4),
+        ]);
     expect(map.constKeyword, isNull);
     expect(map.typeArguments.arguments, hasLength(2));
     expect(map.elements, hasLength(0));
@@ -1143,8 +1338,9 @@
     expect(value.value, 3);
   }
 
-  void test_setLiteral_invalid_map_entry() {
-    SetOrMapLiteral set = parseExpression('<int>{1: 1}', errors: [
+  void test_setLiteral_invalid_map_entry_beforeUiAsCode() {
+    SetOrMapLiteral set =
+        parseExpression('<int>{1: 1}', featureSet: beforeUiAsCode, errors: [
       expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 1),
     ]);
     expect(set.constKeyword, isNull);
@@ -1170,9 +1366,9 @@
     expect(value.value, 3);
   }
 
-  void test_setLiteral_spread2() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
+  void test_setLiteral_spread2_disabled() {
     SetOrMapLiteral set = parseExpression('{3, ...[4]}',
+        featureSet: beforeUiAsCode,
         errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 4, 3)]);
     expect(set.constKeyword, isNull);
     expect(set.typeArguments, isNull);
@@ -1181,9 +1377,9 @@
     expect(value.value, 3);
   }
 
-  void test_setLiteral_spread2Q() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
+  void test_setLiteral_spread2Q_disabled() {
     SetOrMapLiteral set = parseExpression('{3, ...?[4]}',
+        featureSet: beforeUiAsCode,
         errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 4, 4)]);
     expect(set.constKeyword, isNull);
     expect(set.typeArguments, isNull);
@@ -1192,18 +1388,18 @@
     expect(value.value, 3);
   }
 
-  void test_setLiteral_spread_typed() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
+  void test_setLiteral_spread_typed_disabled() {
     SetOrMapLiteral set = parseExpression('<int>{...[3]}',
+        featureSet: beforeUiAsCode,
         errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 6, 3)]);
     expect(set.constKeyword, isNull);
     expect(set.typeArguments, isNotNull);
     expect(set.elements, hasLength(0));
   }
 
-  void test_setLiteral_spreadQ_typed() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
+  void test_setLiteral_spreadQ_typed_disabled() {
     SetOrMapLiteral set = parseExpression('<int>{...?[3]}',
+        featureSet: beforeUiAsCode,
         errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 6, 4)]);
     expect(set.constKeyword, isNull);
     expect(set.typeArguments, isNotNull);
@@ -1221,18 +1417,18 @@
     expect(value.value, 3);
   }
 
-  void test_setOrMapLiteral_spread() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
+  void test_setOrMapLiteral_spread_disabled() {
     SetOrMapLiteral map = parseExpression('{...{3: 4}}',
+        featureSet: beforeUiAsCode,
         errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 1, 3)]);
     expect(map.constKeyword, isNull);
     expect(map.typeArguments, isNull);
     expect(map.elements, hasLength(0));
   }
 
-  void test_setOrMapLiteral_spreadQ() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
+  void test_setOrMapLiteral_spreadQ_disabled() {
     SetOrMapLiteral map = parseExpression('{...?{3: 4}}',
+        featureSet: beforeUiAsCode,
         errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 1, 4)]);
     expect(map.constKeyword, isNull);
     expect(map.typeArguments, isNull);
@@ -1240,6 +1436,163 @@
   }
 }
 
+@reflectiveTest
+class ExtensionMethodsParserTest_Fasta extends FastaParserTestCase {
+  @override
+  CompilationUnit parseCompilationUnit(String content,
+      {List<ErrorCode> codes,
+      List<ExpectedError> errors,
+      FeatureSet featureSet}) {
+    return super.parseCompilationUnit(content,
+        codes: codes,
+        errors: errors,
+        featureSet: featureSet ??
+            FeatureSet.forTesting(
+              sdkVersion: '2.3.0',
+              additionalFeatures: [Feature.extension_methods],
+            ));
+  }
+
+  void test_complex_extends() {
+    var unit = parseCompilationUnit(
+        'extension E extends A with B, C implements D { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 7),
+          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 4),
+          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 28, 1),
+          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 32, 10),
+        ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'extends');
+    expect((extension.extendedType as NamedType).name.name, 'A');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_complex_implements() {
+    var unit = parseCompilationUnit('extension E implements C, D { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 10),
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 24, 1),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'implements');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_complex_type() {
+    var unit = parseCompilationUnit('extension E on C<T> { }');
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    var namedType = (extension.extendedType as NamedType);
+    expect(namedType.name.name, 'C');
+    expect(namedType.typeArguments.arguments, hasLength(1));
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_missing_on() {
+    var unit = parseCompilationUnit('extension E', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 11, 0),
+      expectedError(ParserErrorCode.MISSING_CLASS_BODY, 11, 0),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, '');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_missing_on_withBlock() {
+    var unit = parseCompilationUnit('extension E {}', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 1),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, '');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_missing_on_withClassAndBlock() {
+    var unit = parseCompilationUnit('extension E C {}', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple() {
+    var unit = parseCompilationUnit('extension E on C { }');
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    var namedType = (extension.extendedType as NamedType);
+    expect(namedType.name.name, 'C');
+    expect(namedType.typeArguments, isNull);
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple_extends() {
+    var unit = parseCompilationUnit('extension E extends C { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 7),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'extends');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple_implements() {
+    var unit = parseCompilationUnit('extension E implements C { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 10),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'implements');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple_not_enabled() {
+    parseCompilationUnit('extension E on C { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 0, 9),
+          expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 15, 1)
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.3.0'));
+  }
+
+  void test_simple_with() {
+    var unit = parseCompilationUnit('extension E with C { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 4),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'with');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+}
+
 /**
  * Implementation of [AbstractParserTestCase] specialized for testing the
  * Fasta parser.
@@ -1248,6 +1601,19 @@
     with ParserTestHelpers
     implements AbstractParserTestCase {
   static final List<ErrorCode> NO_ERROR_COMPARISON = <ErrorCode>[];
+
+  final controlFlow = FeatureSet.forTesting(
+      sdkVersion: '2.0.0',
+      additionalFeatures: [Feature.control_flow_collections]);
+
+  final spread = FeatureSet.forTesting(
+      sdkVersion: '2.0.0', additionalFeatures: [Feature.spread_collections]);
+
+  final nonNullable = FeatureSet.forTesting(
+      sdkVersion: '2.2.2', additionalFeatures: [Feature.non_nullable]);
+
+  final preNonNullable = FeatureSet.forTesting(sdkVersion: '2.2.2');
+
   ParserProxy _parserProxy;
 
   analyzer.Token _fastaTokens;
@@ -1255,11 +1621,6 @@
   @override
   bool allowNativeClause = false;
 
-  @override
-  set enableLazyAssignmentOperators(bool value) {
-    // Lazy assignment operators are always enabled
-  }
-
   set enableOptionalNewAndConst(bool enable) {
     // ignored
   }
@@ -1305,10 +1666,13 @@
   }
 
   @override
-  void createParser(String content, {int expectedEndOffset}) {
-    var scanner = new StringScanner(content, includeComments: true);
+  void createParser(String content,
+      {int expectedEndOffset, FeatureSet featureSet}) {
+    featureSet ??= FeatureSet.forTesting();
+    var scanner = new StringScanner(content,
+        configuration: ScannerConfiguration.nonNullable, includeComments: true);
     _fastaTokens = scanner.tokenize();
-    _parserProxy = new ParserProxy(_fastaTokens,
+    _parserProxy = new ParserProxy(_fastaTokens, featureSet,
         allowNativeClause: allowNativeClause,
         expectedEndOffset: expectedEndOffset);
   }
@@ -1399,16 +1763,12 @@
   CompilationUnit parseCompilationUnit(String content,
       {List<ErrorCode> codes,
       List<ExpectedError> errors,
-      bool enableControlFlowCollections,
-      bool enableGtGtGt,
-      bool enableGtGtGtEq}) {
+      FeatureSet featureSet}) {
     GatheringErrorListener listener =
         new GatheringErrorListener(checkRanges: true);
 
-    CompilationUnit unit = parseCompilationUnit2(content, listener,
-        enableControlFlowCollections: enableControlFlowCollections,
-        enableGtGtGt: enableGtGtGt,
-        enableGtGtGtEq: enableGtGtGtEq);
+    CompilationUnit unit =
+        parseCompilationUnit2(content, listener, featureSet: featureSet);
 
     // Assert and return result
     if (codes != null) {
@@ -1424,45 +1784,33 @@
 
   CompilationUnit parseCompilationUnit2(
       String content, GatheringErrorListener listener,
-      {bool enableControlFlowCollections,
-      bool enableGtGtGt,
-      bool enableGtGtGtEq}) {
+      {FeatureSet featureSet}) {
+    featureSet ??= FeatureSet.forTesting();
     var source = new StringSource(content, 'parser_test_StringSource.dart');
 
-    void reportError(
-        ScannerErrorCode errorCode, int offset, List<Object> arguments) {
-      listener
-          .onError(new AnalysisError(source, offset, 1, errorCode, arguments));
+    // Adjust the feature set based on language version comment.
+    void languageVersionChanged(
+        fasta.Scanner scanner, LanguageVersionToken languageVersion) {
+      featureSet = featureSet.restrictToVersion(
+          Version(languageVersion.major, languageVersion.minor, 0));
+      scanner.configuration = Scanner.buildConfig(featureSet);
     }
 
     // Scan tokens
     ScannerResult result = scanString(content,
         includeComments: true,
-        enableGtGtGt: enableGtGtGt ?? enableGtGtGtEq ?? false,
-        enableGtGtGtEq: enableGtGtGtEq ?? false);
-    Token token = result.tokens;
-    if (result.hasErrors) {
-      // The default recovery strategy used by scanString
-      // places all error tokens at the head of the stream.
-      while (token.type == TokenType.BAD_INPUT) {
-        translateErrorToken(token, reportError);
-        token = token.next;
-      }
-    }
-    _fastaTokens = token;
+        configuration: Scanner.buildConfig(featureSet),
+        languageVersionChanged: languageVersionChanged);
+    _fastaTokens = result.tokens;
 
     // Run parser
     ErrorReporter errorReporter = new ErrorReporter(listener, source);
     fasta.Parser parser = new fasta.Parser(null);
-    AstBuilder astBuilder = new AstBuilder(errorReporter, source.uri, true);
+    AstBuilder astBuilder = new AstBuilder(errorReporter, source.uri, true)
+      ..configureFeatures(featureSet);
     parser.listener = astBuilder;
     astBuilder.parser = parser;
     astBuilder.allowNativeClause = allowNativeClause;
-    if (enableControlFlowCollections != null) {
-      astBuilder.enableControlFlowCollections = enableControlFlowCollections;
-    }
-    astBuilder.enableTripleShift =
-        enableGtGtGt == true || enableGtGtGtEq == true;
     parser.parseUnit(_fastaTokens);
     CompilationUnitImpl unit = astBuilder.pop();
     unit.localDeclarations = astBuilder.localDeclarations;
@@ -1514,12 +1862,9 @@
       List<ExpectedError> errors,
       int expectedEndOffset,
       bool inAsync = false,
-      bool parseSpreadCollections = false,
-      bool parseControlFlowCollections = false}) {
-    createParser(source, expectedEndOffset: expectedEndOffset);
-    _parserProxy.astBuilder.enableSpreadCollections = parseSpreadCollections;
-    _parserProxy.astBuilder.enableControlFlowCollections =
-        parseControlFlowCollections;
+      FeatureSet featureSet}) {
+    createParser(source,
+        expectedEndOffset: expectedEndOffset, featureSet: featureSet);
     if (inAsync) {
       _parserProxy.fastaParser.asyncState = AsyncModifier.Async;
     }
@@ -1702,16 +2047,9 @@
 
   @override
   Statement parseStatement(String source,
-      {bool enableLazyAssignmentOperators,
-      int expectedEndOffset,
-      bool parseSetLiterals = false,
-      bool parseSpreadCollections = false,
-      bool parseControlFlowCollections = false,
-      bool inAsync = false}) {
-    createParser(source, expectedEndOffset: expectedEndOffset);
-    _parserProxy.astBuilder.enableSpreadCollections = parseSpreadCollections;
-    _parserProxy.astBuilder.enableControlFlowCollections =
-        parseControlFlowCollections;
+      {int expectedEndOffset, FeatureSet featureSet, bool inAsync = false}) {
+    createParser(source,
+        expectedEndOffset: expectedEndOffset, featureSet: featureSet);
     if (inAsync) {
       _parserProxy.fastaParser.asyncState = AsyncModifier.Async;
     }
@@ -1782,32 +2120,225 @@
  */
 @reflectiveTest
 class FormalParameterParserTest_Fasta extends FastaParserTestCase
-    with FormalParameterParserTestMixin {}
+    with FormalParameterParserTestMixin {
+  FormalParameter parseNNBDFormalParameter(String code, ParameterKind kind,
+      {List<ExpectedError> errors}) {
+    String parametersCode;
+    if (kind == ParameterKind.REQUIRED) {
+      parametersCode = '($code)';
+    } else if (kind == ParameterKind.POSITIONAL) {
+      parametersCode = '([$code])';
+    } else if (kind == ParameterKind.NAMED) {
+      parametersCode = '({$code})';
+    } else {
+      fail('$kind');
+    }
+    createParser(parametersCode, featureSet: nonNullable);
+    FormalParameterList list =
+        _parserProxy.parseFormalParameterList(inFunctionType: false);
+    assertErrors(errors: errors);
+    return list.parameters.single;
+  }
+
+  void test_parseFormalParameter_covariant_required_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseNNBDFormalParameter(
+        'covariant required A a : null', kind,
+        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 12, 8)]);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_final_required_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseNNBDFormalParameter(
+        'final required a : null', kind,
+        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 8, 8)]);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_required_covariant_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseNNBDFormalParameter('required covariant A a : null', kind);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_required_final_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseNNBDFormalParameter('required final a : null', kind);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_required_type_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseNNBDFormalParameter('required A a : null', kind);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_required_var_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseNNBDFormalParameter('required var a : null', kind);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_var_required_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseNNBDFormalParameter(
+        'var required a : null', kind,
+        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 8)]);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseNormalFormalParameter_function_named_nullable() {
+    ParameterKind kind = ParameterKind.NAMED;
+    var defaultParameter =
+        parseFormalParameter('a()? : null', kind) as DefaultFormalParameter;
+    var functionParameter =
+        defaultParameter.parameter as FunctionTypedFormalParameter;
+    assertNoErrors();
+    expect(functionParameter.returnType, isNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.isNamed, isTrue);
+    expect(functionParameter.question, isNotNull);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseNormalFormalParameter_function_noType_nullable() {
+    NormalFormalParameter parameter =
+        parseNNBDFormalParameter('a()?', ParameterKind.REQUIRED);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFunctionTypedFormalParameter);
+    FunctionTypedFormalParameter functionParameter = parameter;
+    expect(functionParameter.returnType, isNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNotNull);
+  }
+}
 
 /**
  * Tests of the fasta parser based on [ComplexParserTestMixin].
  */
 @reflectiveTest
 class NNBDParserTest_Fasta extends FastaParserTestCase {
-  CompilationUnit parseNNBDCompilationUnit(String code,
-      {List<ExpectedError> errors}) {
-    createParser(code);
-    _parserProxy.astBuilder.enableNonNullable = true;
-    CompilationUnit unit = _parserProxy.parseCompilationUnit2();
-    assertErrors(errors: errors);
-    return unit;
-  }
+  @override
+  CompilationUnit parseCompilationUnit(String content,
+          {List<ErrorCode> codes,
+          List<ExpectedError> errors,
+          FeatureSet featureSet}) =>
+      super.parseCompilationUnit(content,
+          codes: codes, errors: errors, featureSet: featureSet ?? nonNullable);
 
   void test_assignment_complex() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x + bar(7); }');
+    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x + bar(7); }');
   }
 
   void test_assignment_simple() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
+    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
   }
 
   void test_binary_expression_statement() {
-    final unit = parseNNBDCompilationUnit('D? foo(X? x) { X ?? x2; }');
+    final unit = parseCompilationUnit('D? foo(X? x) { X ?? x2; }');
     FunctionDeclaration funct = unit.declarations[0];
     BlockFunctionBody body = funct.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -1820,15 +2351,15 @@
   }
 
   void test_conditional() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? 7 : y; }');
+    parseCompilationUnit('D? foo(X? x) { X ? 7 : y; }');
   }
 
   void test_conditional_complex() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }');
+    parseCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }');
   }
 
   void test_conditional_error() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? ? x2 = x + bar(7) : y; }',
+    parseCompilationUnit('D? foo(X? x) { X ? ? x2 = x + bar(7) : y; }',
         errors: [
           expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1),
           expectedError(ParserErrorCode.EXPECTED_TOKEN, 40, 1),
@@ -1837,58 +2368,58 @@
   }
 
   void test_conditional_simple() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }');
+    parseCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }');
   }
 
   void test_enableNonNullable_false() {
     parseCompilationUnit('main() { x is String? ? (x + y) : z; }',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 20, 1)]);
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 20, 1)],
+        featureSet: preNonNullable);
   }
 
   void test_for() {
-    parseNNBDCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }');
+    parseCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }');
   }
 
   void test_for_conditional() {
-    parseNNBDCompilationUnit(
-        'main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }');
+    parseCompilationUnit('main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }');
   }
 
   void test_for_nullable() {
-    parseNNBDCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }');
+    parseCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }');
   }
 
   void test_foreach() {
-    parseNNBDCompilationUnit('main() { for(int x in [7]) { } }');
+    parseCompilationUnit('main() { for(int x in [7]) { } }');
   }
 
   void test_foreach_nullable() {
-    parseNNBDCompilationUnit('main() { for(int? x in [7, null]) { } }');
+    parseCompilationUnit('main() { for(int? x in [7, null]) { } }');
   }
 
   void test_gft_nullable() {
-    parseNNBDCompilationUnit('main() { C? Function() x = 7; }');
+    parseCompilationUnit('main() { C? Function() x = 7; }');
   }
 
   void test_gft_nullable_1() {
-    parseNNBDCompilationUnit('main() { C Function()? x = 7; }');
+    parseCompilationUnit('main() { C Function()? x = 7; }');
   }
 
   void test_gft_nullable_2() {
-    parseNNBDCompilationUnit('main() { C? Function()? x = 7; }');
+    parseCompilationUnit('main() { C? Function()? x = 7; }');
   }
 
   void test_gft_nullable_3() {
-    parseNNBDCompilationUnit('main() { C? Function()? Function()? x = 7; }');
+    parseCompilationUnit('main() { C? Function()? Function()? x = 7; }');
   }
 
   void test_gft_nullable_prefixed() {
-    parseNNBDCompilationUnit('main() { C.a? Function()? x = 7; }');
+    parseCompilationUnit('main() { C.a? Function()? x = 7; }');
   }
 
   void test_is_nullable() {
     CompilationUnit unit =
-        parseNNBDCompilationUnit('main() { x is String? ? (x + y) : z; }');
+        parseCompilationUnit('main() { x is String? ? (x + y) : z; }');
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -1904,7 +2435,7 @@
 
   void test_is_nullable_parenthesis() {
     CompilationUnit unit =
-        parseNNBDCompilationUnit('main() { (x is String?) ? (x + y) : z; }');
+        parseCompilationUnit('main() { (x is String?) ? (x + y) : z; }');
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -1919,8 +2450,48 @@
     expect(elseExpression, isSimpleIdentifier);
   }
 
+  void test_is_nullable_parenthesis_optOut() {
+    parseCompilationUnit('''
+// @dart = 2.2
+main() { (x is String?) ? (x + y) : z; }
+''', errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 36, 1)]);
+  }
+
+  void test_late_as_identifier() {
+    parseCompilationUnit('''
+class C {
+  int late;
+}
+
+void f(C c) {
+  print(c.late);
+}
+
+main() {
+  f(new C());
+}
+''', featureSet: preNonNullable);
+  }
+
+  void test_late_as_identifier_optOut() {
+    parseCompilationUnit('''
+// @dart = 2.2
+class C {
+  int late;
+}
+
+void f(C c) {
+  print(c.late);
+}
+
+main() {
+  f(new C());
+}
+''');
+  }
+
   void test_nullCheck() {
-    var unit = parseNNBDCompilationUnit('f(int? y) { var x = y!; }');
+    var unit = parseCompilationUnit('f(int? y) { var x = y!; }');
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     VariableDeclarationStatement statement = body.block.statements[0];
@@ -1931,11 +2502,12 @@
   }
 
   void test_nullCheck_disabled() {
-    // TODO(danrubel): remove this once NNBD is enabled by default
-    var unit = parseCompilationUnit('f(int? y) { var x = y!; }', errors: [
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
-    ]);
+    var unit = parseCompilationUnit('f(int? y) { var x = y!; }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
+        ],
+        featureSet: preNonNullable);
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     VariableDeclarationStatement statement = body.block.statements[0];
@@ -1943,125 +2515,142 @@
     expect(identifier.name, 'y');
   }
 
+  void test_nullCheckAfterGetterAccess() {
+    parseCompilationUnit('f() { var x = g.x!.y + 7; }');
+  }
+
+  void test_nullCheckAfterMethodCall() {
+    parseCompilationUnit('f() { var x = g.m()!.y + 7; }');
+  }
+
+  void test_nullCheckBeforeGetterAccess() {
+    parseCompilationUnit('f() { var x = g!.x + 7; }');
+  }
+
+  void test_nullCheckBeforeMethodCall() {
+    parseCompilationUnit('f() { var x = g!.m() + 7; }');
+  }
+
   void test_nullCheckFunctionResult() {
-    parseNNBDCompilationUnit('f() { var x = g()! + 7; }');
+    parseCompilationUnit('f() { var x = g()! + 7; }');
   }
 
   void test_nullCheckIndexedValue() {
-    parseNNBDCompilationUnit('f(int? y) { var x = y[0]! + 7; }');
+    parseCompilationUnit('f(int? y) { var x = y[0]! + 7; }');
   }
 
   void test_nullCheckIndexedValue2() {
-    parseNNBDCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }');
+    parseCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }');
   }
 
   void test_nullCheckInExpression() {
-    parseNNBDCompilationUnit('f(int? y) { var x = y! + 7; }');
+    parseCompilationUnit('f(int? y) { var x = y! + 7; }');
   }
 
   void test_nullCheckInExpression_disabled() {
-    // TODO(danrubel): remove this once NNBD is enabled by default
-    parseCompilationUnit('f(int? y) { var x = y! + 7; }', errors: [
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
-    ]);
+    parseCompilationUnit('f(int? y) { var x = y! + 7; }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
+        ],
+        featureSet: preNonNullable);
   }
 
   void test_nullCheckMethodResult() {
-    parseNNBDCompilationUnit('f() { var x = g.m()! + 7; }');
+    parseCompilationUnit('f() { var x = g.m()! + 7; }');
   }
 
   void test_nullCheckMethodResult2() {
-    parseNNBDCompilationUnit('f() { var x = g?.m()! + 7; }');
+    parseCompilationUnit('f() { var x = g?.m()! + 7; }');
   }
 
   void test_nullCheckMethodResult3() {
-    parseNNBDCompilationUnit('f() { var x = super.m()! + 7; }');
+    parseCompilationUnit('f() { var x = super.m()! + 7; }');
   }
 
   void test_nullCheckOnConstConstructor() {
-    parseNNBDCompilationUnit('f() { var x = const Foo()!; }');
+    parseCompilationUnit('f() { var x = const Foo()!; }');
   }
 
   void test_nullCheckOnConstructor() {
-    parseNNBDCompilationUnit('f() { var x = new Foo()!; }');
+    parseCompilationUnit('f() { var x = new Foo()!; }');
   }
 
   void test_nullCheckOnLiteral_disabled() {
-    // TODO(danrubel): remove this once NNBD is enabled by default
     parseCompilationUnit('f() { var x = 0!; }',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 15, 1)]);
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 15, 1)],
+        featureSet: preNonNullable);
   }
 
   void test_nullCheckOnLiteralDouble() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = 1.2!; }');
+    parseCompilationUnit('f() { var x = 1.2!; }');
   }
 
   void test_nullCheckOnLiteralInt() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = 0!; }');
+    parseCompilationUnit('f() { var x = 0!; }');
   }
 
   void test_nullCheckOnLiteralList() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = [1,2]!; }');
+    parseCompilationUnit('f() { var x = [1,2]!; }');
   }
 
   void test_nullCheckOnLiteralMap() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = {1:2}!; }');
+    parseCompilationUnit('f() { var x = {1:2}!; }');
   }
 
   void test_nullCheckOnLiteralSet() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = {1,2}!; }');
+    parseCompilationUnit('f() { var x = {1,2}!; }');
   }
 
   void test_nullCheckOnLiteralString() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = "seven"!; }');
+    parseCompilationUnit('f() { var x = "seven"!; }');
   }
 
   void test_nullCheckOnNull() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = null!; }');
+    parseCompilationUnit('f() { var x = null!; }');
   }
 
   void test_nullCheckOnSymbol() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = #seven!; }');
+    parseCompilationUnit('f() { var x = #seven!; }');
   }
 
   void test_nullCheckOnValue() {
-    parseNNBDCompilationUnit('f(Point p) { var x = p.y! + 7; }');
+    parseCompilationUnit('f(Point p) { var x = p.y! + 7; }');
   }
 
   void test_nullCheckOnValue_disabled() {
-    // TODO(danrubel): remove this once NNBD is enabled by default
     parseCompilationUnit('f(Point p) { var x = p.y! + 7; }',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 24, 1)]);
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 24, 1)],
+        featureSet: preNonNullable);
   }
 
   void test_nullCheckParenthesizedExpression() {
-    parseNNBDCompilationUnit('f(int? y) { var x = (y)! + 7; }');
+    parseCompilationUnit('f(int? y) { var x = (y)! + 7; }');
   }
 
   void test_nullCheckPropertyAccess() {
-    parseNNBDCompilationUnit('f() { var x = g.p! + 7; }');
+    parseCompilationUnit('f() { var x = g.p! + 7; }');
   }
 
   void test_nullCheckPropertyAccess2() {
-    parseNNBDCompilationUnit('f() { var x = g?.p! + 7; }');
+    parseCompilationUnit('f() { var x = g?.p! + 7; }');
   }
 
   void test_nullCheckPropertyAccess3() {
-    parseNNBDCompilationUnit('f() { var x = super.p! + 7; }');
+    parseCompilationUnit('f() { var x = super.p! + 7; }');
   }
 
   void test_postfix_null_assertion_and_unary_prefix_operator_precedence() {
     // -x! is parsed as -(x!).
-    var unit = parseNNBDCompilationUnit('void main() { -x!; }');
+    var unit = parseCompilationUnit('void main() { -x!; }');
     var function = unit.declarations[0] as FunctionDeclaration;
     var body = function.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
@@ -2073,7 +2662,7 @@
 
   void test_postfix_null_assertion_of_postfix_expression() {
     // x++! is parsed as (x++)!.
-    var unit = parseNNBDCompilationUnit('void main() { x++!; }');
+    var unit = parseCompilationUnit('void main() { x++!; }');
     var function = unit.declarations[0] as FunctionDeclaration;
     var body = function.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
@@ -2105,21 +2694,23 @@
    * Creates a [ParserProxy] which is prepared to begin parsing at the given
    * Fasta token.
    */
-  factory ParserProxy(analyzer.Token firstToken,
+  factory ParserProxy(analyzer.Token firstToken, FeatureSet featureSet,
       {bool allowNativeClause: false, int expectedEndOffset}) {
     TestSource source = new TestSource();
     var errorListener = new GatheringErrorListener(checkRanges: true);
     var errorReporter = new ErrorReporter(errorListener, source);
-    return new ParserProxy._(firstToken, errorReporter, null, errorListener,
+    return new ParserProxy._(
+        firstToken, errorReporter, null, errorListener, featureSet,
         allowNativeClause: allowNativeClause,
         expectedEndOffset: expectedEndOffset);
   }
 
   ParserProxy._(analyzer.Token firstToken, ErrorReporter errorReporter,
-      Uri fileUri, this._errorListener,
+      Uri fileUri, this._errorListener, FeatureSet featureSet,
       {bool allowNativeClause: false, this.expectedEndOffset})
       : super(firstToken, errorReporter, fileUri,
             allowNativeClause: allowNativeClause) {
+    configureFeatures(featureSet);
     _eventListener = new ForwardingTestListener(astBuilder);
     fastaParser.listener = _eventListener;
   }
@@ -2269,8 +2860,16 @@
    */
   _run(String enclosingEvent, f()) {
     _eventListener.begin(enclosingEvent);
+
+    // Simulate error handling of parseUnit by skipping error tokens
+    // before parsing and reporting them after parsing is complete.
+    Token errorToken = currentToken;
+    currentToken = fastaParser.skipErrorTokens(currentToken);
     var result = f();
+    fastaParser.reportAllErrorTokens(errorToken);
+
     _eventListener.end(enclosingEvent);
+
     String lexeme = currentToken is ErrorToken
         ? currentToken.runtimeType.toString()
         : currentToken.lexeme;
@@ -2299,8 +2898,8 @@
   }
 
   void test_incompleteForEach2() {
-    ForStatement statement = parseStatement('for (String item i) {}',
-        parseControlFlowCollections: true);
+    ForStatement statement =
+        parseStatement('for (String item i) {}', featureSet: controlFlow);
     listener.assertErrors([
       expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 4),
       expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 1)
@@ -2373,6 +2972,58 @@
   @override
   void test_parseCommentReferences_skipLink_reference_multiLine() =>
       super.test_parseCommentReferences_skipLink_reference_multiLine();
+
+  void test_parseVariableDeclaration_final_late() {
+    var statement = parseStatement('final late a;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertErrors(
+        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4)]);
+    expect(declarationList.keyword.lexeme, 'final');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_late() {
+    var statement = parseStatement('late a;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertNoErrors();
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_late_final() {
+    var statement = parseStatement('late final a;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertNoErrors();
+    expect(declarationList.keyword.lexeme, 'final');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_late_init() {
+    var statement = parseStatement('late a = 0;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertNoErrors();
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_late_type() {
+    var statement = parseStatement('late A a;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertNoErrors();
+    expect(declarationList.lateKeyword, isNotNull);
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNotNull);
+    expect(declarationList.variables, hasLength(1));
+  }
 }
 
 /**
@@ -2420,7 +3071,7 @@
     ForStatement forStatement = parseStatement(
       'await for (element in list) {}',
       inAsync: true,
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.awaitKeyword, isNotNull);
@@ -2434,10 +3085,44 @@
     expect(forStatement.body, isNotNull);
   }
 
+  void test_parseForStatement_each_finalExternal() {
+    ForStatement forStatement = parseStatement(
+      'for (final external in list) {}',
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.loopVariable.identifier.name, 'external');
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_finalRequired() {
+    ForStatement forStatement = parseStatement(
+      'for (final required in list) {}',
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.loopVariable.identifier.name, 'required');
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
   void test_parseForStatement_each_genericFunctionType2() {
     ForStatement forStatement = parseStatement(
       'for (void Function<T>(T) element in list) {}',
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.awaitKeyword, isNull);
@@ -2454,7 +3139,7 @@
   void test_parseForStatement_each_identifier2() {
     ForStatement forStatement = parseStatement(
       'for (element in list) {}',
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.awaitKeyword, isNull);
@@ -2471,7 +3156,7 @@
   void test_parseForStatement_each_noType_metadata2() {
     ForStatement forStatement = parseStatement(
       'for (@A var element in list) {}',
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.awaitKeyword, isNull);
@@ -2489,7 +3174,7 @@
   void test_parseForStatement_each_type2() {
     ForStatement forStatement = parseStatement(
       'for (A element in list) {}',
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.awaitKeyword, isNull);
@@ -2506,7 +3191,7 @@
   void test_parseForStatement_each_var2() {
     ForStatement forStatement = parseStatement(
       'for (var element in list) {}',
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.awaitKeyword, isNull);
@@ -2523,7 +3208,7 @@
   void test_parseForStatement_loop_c2() {
     ForStatement forStatement = parseStatement(
       'for (; i < count;) {}',
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2541,7 +3226,7 @@
   void test_parseForStatement_loop_cu2() {
     ForStatement forStatement = parseStatement(
       'for (; i < count; i++) {}',
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2559,7 +3244,7 @@
   void test_parseForStatement_loop_ecu2() {
     ForStatement forStatement = parseStatement(
       'for (i--; i < count; i++) {}',
-      parseSpreadCollections: true,
+      featureSet: spread,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2577,7 +3262,7 @@
   void test_parseForStatement_loop_i2() {
     ForStatement forStatement = parseStatement(
       'for (var i = 0;;) {}',
-      parseSpreadCollections: true,
+      featureSet: spread,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2598,7 +3283,7 @@
   void test_parseForStatement_loop_i_withMetadata2() {
     ForStatement forStatement = parseStatement(
       'for (@A var i = 0;;) {}',
-      parseSpreadCollections: true,
+      featureSet: spread,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2619,7 +3304,7 @@
   void test_parseForStatement_loop_ic2() {
     ForStatement forStatement = parseStatement(
       'for (var i = 0; i < count;) {}',
-      parseSpreadCollections: true,
+      featureSet: spread,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2639,7 +3324,7 @@
   void test_parseForStatement_loop_icu2() {
     ForStatement forStatement = parseStatement(
       'for (var i = 0; i < count; i++) {}',
-      parseSpreadCollections: true,
+      featureSet: spread,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2659,7 +3344,7 @@
   void test_parseForStatement_loop_iicuu2() {
     ForStatement forStatement = parseStatement(
       'for (int i = 0, j = count; i < j; i++, j--) {}',
-      parseSpreadCollections: true,
+      featureSet: spread,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2679,7 +3364,7 @@
   void test_parseForStatement_loop_iu2() {
     ForStatement forStatement = parseStatement(
       'for (var i = 0;; i++) {}',
-      parseSpreadCollections: true,
+      featureSet: spread,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2699,7 +3384,7 @@
   void test_parseForStatement_loop_u2() {
     ForStatement forStatement = parseStatement(
       'for (;; i++) {}',
-      parseSpreadCollections: true,
+      featureSet: spread,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2754,101 +3439,6 @@
 @reflectiveTest
 class TopLevelParserTest_Fasta extends FastaParserTestCase
     with TopLevelParserTestMixin {
-  void test_languageVersion_afterImport() {
-    var unit = parseCompilationUnit('''
-import 'foo.dart';
-// @dart = 2.3
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion, isNull);
-  }
-
-  void test_languageVersion_beforeComment() {
-    var unit = parseCompilationUnit('''
-// some other comment
-// @dart = 2.3
-// yet another comment
-import 'foo.dart';
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion.major, 2);
-    expect(unit.languageVersion.minor, 3);
-  }
-
-  void test_languageVersion_beforeFunction() {
-    var unit = parseCompilationUnit('''
-// @dart = 2.3
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion.major, 2);
-    expect(unit.languageVersion.minor, 3);
-  }
-
-  void test_languageVersion_beforeImport() {
-    var unit = parseCompilationUnit('''
-// @dart = 2.3
-import 'foo.dart';
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion.major, 2);
-    expect(unit.languageVersion.minor, 3);
-  }
-
-  void test_languageVersion_beforeImport_afterScript() {
-    var unit = parseCompilationUnit('''
-#!/bin/dart
-// @dart = 2.3
-import 'foo.dart';
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion.major, 2);
-    expect(unit.languageVersion.minor, 3);
-  }
-
-  void test_languageVersion_beforeLibrary() {
-    var unit = parseCompilationUnit('''
-// @dart = 2.3
-library foo;
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion.major, 2);
-    expect(unit.languageVersion.minor, 3);
-  }
-
-  void test_languageVersion_incomplete_version() {
-    var unit = parseCompilationUnit('''
-// @dart = 2.
-library foo;
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion, isNull);
-  }
-
-  void test_languageVersion_invalid_identifier() {
-    var unit = parseCompilationUnit('''
-// @dart = blat
-library foo;
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion, isNull);
-  }
-
-  void test_languageVersion_invalid_version() {
-    var unit = parseCompilationUnit('''
-// @dart = 2.x
-library foo;
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion, isNull);
-  }
-
-  void test_languageVersion_unspecified() {
-    var unit = parseCompilationUnit('''
-main() {}
-''') as CompilationUnitImpl;
-    expect(unit.languageVersion, isNull);
-  }
-
   void test_parseClassDeclaration_native_allowed() {
     allowNativeClause = true;
     test_parseClassDeclaration_native();
@@ -3084,4 +3674,52 @@
     MixinDeclaration declaration = parseFullCompilationUnitMember();
     expectCommentText(declaration.documentationComment, '/// Doc');
   }
+
+  void test_parseTopLevelVariable_final_late() {
+    var unit = parseCompilationUnit('final late a;',
+        featureSet: nonNullable,
+        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4)]);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    var declarationList = declaration.variables;
+    expect(declarationList.keyword.lexeme, 'final');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseTopLevelVariable_late() {
+    var unit = parseCompilationUnit('late a;', featureSet: nonNullable);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    var declarationList = declaration.variables;
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseTopLevelVariable_late_final() {
+    var unit = parseCompilationUnit('late final a;', featureSet: nonNullable);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    var declarationList = declaration.variables;
+    expect(declarationList.keyword.lexeme, 'final');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseTopLevelVariable_late_init() {
+    var unit = parseCompilationUnit('late a = 0;', featureSet: nonNullable);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    var declarationList = declaration.variables;
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseTopLevelVariable_late_type() {
+    var unit = parseCompilationUnit('late A a;', featureSet: nonNullable);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    var declarationList = declaration.variables;
+    expect(declarationList.lateKeyword, isNotNull);
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNotNull);
+    expect(declarationList.variables, hasLength(1));
+  }
 }
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 13c908b..4de8709 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -57,8 +58,6 @@
 
   void set allowNativeClause(bool value);
 
-  void set enableLazyAssignmentOperators(bool value);
-
   /**
    * Set a flag indicating whether the parser should parse instance creation
    * expressions that lack either the `new` or `const` keyword.
@@ -232,8 +231,7 @@
 
   SimpleIdentifier parseSimpleIdentifier(String code);
 
-  Statement parseStatement(String source,
-      {bool enableLazyAssignmentOperators, int expectedEndOffset});
+  Statement parseStatement(String source, {int expectedEndOffset});
 
   Expression parseStringLiteral(String code);
 
@@ -437,6 +435,11 @@
     expect(field.staticKeyword, isNull);
     VariableDeclarationList list = field.fields;
     expect(list, isNotNull);
+    expect(list.keyword, isNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
     NodeList<VariableDeclaration> variables = list.variables;
     expect(variables, hasLength(1));
     VariableDeclaration variable = variables[0];
@@ -456,6 +459,12 @@
     expect(field.staticKeyword, isNull);
     VariableDeclarationList list = field.fields;
     expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
     TypeName type = list.type;
     expect(type.name.name, 'List');
     NodeList typeArguments = type.typeArguments.arguments;
@@ -507,6 +516,12 @@
     expect(field.staticKeyword, isNull);
     VariableDeclarationList list = field.fields;
     expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
     NodeList<VariableDeclaration> variables = list.variables;
     expect(variables, hasLength(1));
     VariableDeclaration variable = variables[0];
@@ -527,6 +542,12 @@
     expect(field.staticKeyword, isNull);
     VariableDeclarationList list = field.fields;
     expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
     NodeList<VariableDeclaration> variables = list.variables;
     expect(variables, hasLength(1));
     VariableDeclaration variable = variables[0];
@@ -546,6 +567,12 @@
     expect(field.staticKeyword, isNull);
     VariableDeclarationList list = field.fields;
     expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
     NodeList<VariableDeclaration> variables = list.variables;
     expect(variables, hasLength(1));
     VariableDeclaration variable = variables[0];
@@ -565,6 +592,12 @@
     expect(field.staticKeyword, isNull);
     VariableDeclarationList list = field.fields;
     expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
     NodeList<VariableDeclaration> variables = list.variables;
     expect(variables, hasLength(1));
     VariableDeclaration variable = variables[0];
@@ -585,6 +618,12 @@
     expect(field.staticKeyword, isNull);
     VariableDeclarationList list = field.fields;
     expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
     NodeList<VariableDeclaration> variables = list.variables;
     expect(variables, hasLength(1));
     VariableDeclaration variable = variables[0];
@@ -636,6 +675,12 @@
     expect(field.staticKeyword, isNotNull);
     VariableDeclarationList list = field.fields;
     expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
     NodeList<VariableDeclaration> variables = list.variables;
     expect(variables, hasLength(1));
     VariableDeclaration variable = variables[0];
@@ -1583,6 +1628,25 @@
     expect(initializer.period, isNull);
   }
 
+  void test_parseGetter_identifier_colon_issue_36961() {
+    createParser('get a:');
+    MethodDeclaration method = parser.parseClassMember('C');
+    expect(method, isNotNull);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_INITIALIZER, 5, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 6, 0),
+    ]);
+    expect(method.body, isNotNull);
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.parameters, isNull);
+    expect(method.propertyKeyword, isNotNull);
+    expect(method.returnType, isNull);
+  }
+
   void test_parseGetter_nonStatic() {
     createParser('/// Doc\nT get a;');
     MethodDeclaration method = parser.parseClassMember('C');
@@ -2467,6 +2531,20 @@
     listener.assertErrors([expectedError(ParserErrorCode.CONST_METHOD, 0, 5)]);
   }
 
+  void test_constMethod_noReturnType() {
+    createParser('const m() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([expectedError(ParserErrorCode.CONST_METHOD, 0, 5)]);
+  }
+
+  void test_constMethod_noReturnType2() {
+    createParser('const m();');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([expectedError(ParserErrorCode.CONST_METHOD, 0, 5)]);
+  }
+
   void test_constructorPartial() {
     createParser('class C { C< }');
     parser.parseCompilationUnit2();
@@ -3175,7 +3253,7 @@
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
     listener.assertErrors(
-        [expectedError(ParserErrorCode.EXTERNAL_AFTER_FACTORY, 8, 8)]);
+        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 8, 8)]);
   }
 
   void test_externalAfterStatic() {
@@ -4335,24 +4413,16 @@
 
   void test_missingClassBody() {
     parseCompilationUnit("class A class B {}",
-        errors: [expectedError(ParserErrorCode.MISSING_CLASS_BODY, 8, 5)]);
+        errors: [expectedError(ParserErrorCode.MISSING_CLASS_BODY, 6, 1)]);
   }
 
   void test_missingClosingParenthesis() {
-    // It is possible that it is not possible to generate this error (that it's
-    // being reported in code that cannot actually be reached), but that hasn't
-    // been proven yet.
     createParser('(int a, int b ;',
-        expectedEndOffset: 14 /* ErrorToken at end of token stream */);
+        expectedEndOffset: 14 /* parsing ends at synthetic ')' */);
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    if (usingFastaParser) {
-      // Fasta scanner reports missing `)` error
-      listener.assertNoErrors();
-    } else {
-      listener.errors
-          .contains(expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 1));
-    }
+    listener.errors
+        .contains(expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 1));
   }
 
   void test_missingConstFinalVarOrType_static() {
@@ -5259,7 +5329,7 @@
         parseStatement('switch (a) return;', expectedEndOffset: 11);
     expect(statement, isNotNull);
     listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 6)]
+        ? [expectedError(ParserErrorCode.EXPECTED_BODY, 9, 1)]
         : [
             expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 6),
             expectedError(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, 11, 6),
@@ -6375,7 +6445,6 @@
 
   void test_parseExpression_assign_compound() {
     if (usingFastaParser && AbstractScanner.LAZY_ASSIGNMENT_ENABLED) {
-      enableLazyAssignmentOperators = true;
       Expression expression = parseExpression('x ||= y');
       var assignmentExpression = expression as AssignmentExpression;
       expect(assignmentExpression.leftHandSide, isNotNull);
@@ -8150,6 +8219,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -8167,6 +8237,7 @@
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -8184,6 +8255,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -8204,6 +8276,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNotNull);
@@ -8222,6 +8295,7 @@
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNotNull);
@@ -8239,6 +8313,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNotNull);
@@ -8257,6 +8332,7 @@
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNull);
     expect(simpleParameter.type, isGenericFunctionType);
@@ -8274,6 +8350,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNull);
     expect(simpleParameter.type, isNotNull);
@@ -8292,6 +8369,7 @@
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNull);
     expect(simpleParameter.type, isNotNull);
@@ -8309,6 +8387,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNull);
     expect(simpleParameter.type, isNotNull);
@@ -8329,6 +8408,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -8346,6 +8426,7 @@
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -8363,6 +8444,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -8382,6 +8464,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -8399,6 +8482,7 @@
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -8415,6 +8499,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -8434,6 +8519,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNotNull);
@@ -8451,6 +8537,7 @@
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNotNull);
@@ -8467,6 +8554,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNotNull);
@@ -8485,6 +8573,7 @@
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNull);
     expect(simpleParameter.type, isGenericFunctionType);
@@ -8501,6 +8590,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNull);
     expect(simpleParameter.type, isNotNull);
@@ -8520,6 +8610,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNull);
     expect(simpleParameter.type, isNotNull);
@@ -8537,6 +8628,7 @@
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNull);
     expect(simpleParameter.type, isNotNull);
@@ -8553,6 +8645,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNull);
     expect(simpleParameter.type, isNotNull);
@@ -8572,6 +8665,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNull);
     expect(simpleParameter.type, isNotNull);
@@ -8591,6 +8685,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -8608,6 +8703,7 @@
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -8624,6 +8720,7 @@
     SimpleFormalParameter simpleParameter =
         defaultParameter.parameter as SimpleFormalParameter;
     expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
     expect(simpleParameter.identifier, isNotNull);
     expect(simpleParameter.keyword, isNotNull);
     expect(simpleParameter.type, isNull);
@@ -9021,6 +9118,7 @@
     expect(functionParameter.typeParameters, isNull);
     expect(functionParameter.parameters, isNotNull);
     expect(functionParameter.isNamed, isTrue);
+    expect(functionParameter.question, isNull);
     expect(defaultParameter.separator, isNotNull);
     expect(defaultParameter.defaultValue, isNotNull);
     expect(defaultParameter.isNamed, isTrue);
@@ -9036,6 +9134,7 @@
     expect(functionParameter.identifier, isNotNull);
     expect(functionParameter.typeParameters, isNull);
     expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
   }
 
   void test_parseNormalFormalParameter_function_noType_covariant() {
@@ -9050,6 +9149,7 @@
     expect(functionParameter.identifier, isNotNull);
     expect(functionParameter.typeParameters, isNull);
     expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
   }
 
   void test_parseNormalFormalParameter_function_noType_typeParameters() {
@@ -9062,6 +9162,7 @@
     expect(functionParameter.identifier, isNotNull);
     expect(functionParameter.typeParameters, isNotNull);
     expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
   }
 
   void test_parseNormalFormalParameter_function_type() {
@@ -9074,6 +9175,7 @@
     expect(functionParameter.identifier, isNotNull);
     expect(functionParameter.typeParameters, isNull);
     expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
   }
 
   void test_parseNormalFormalParameter_function_type_typeParameters() {
@@ -9086,6 +9188,7 @@
     expect(functionParameter.identifier, isNotNull);
     expect(functionParameter.typeParameters, isNotNull);
     expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
   }
 
   void test_parseNormalFormalParameter_function_typeVoid_covariant() {
@@ -9100,6 +9203,7 @@
     expect(functionParameter.identifier, isNotNull);
     expect(functionParameter.typeParameters, isNull);
     expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
   }
 
   void test_parseNormalFormalParameter_function_void() {
@@ -9112,6 +9216,7 @@
     expect(functionParameter.identifier, isNotNull);
     expect(functionParameter.typeParameters, isNull);
     expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
   }
 
   void test_parseNormalFormalParameter_function_void_typeParameters() {
@@ -9124,6 +9229,7 @@
     expect(functionParameter.identifier, isNotNull);
     expect(functionParameter.typeParameters, isNotNull);
     expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
   }
 
   void test_parseNormalFormalParameter_function_withDocComment() {
@@ -9275,12 +9381,6 @@
   bool parseAsync = true;
 
   /**
-   * A flag indicating whether lazy assignment operators should be enabled for
-   * the test.
-   */
-  bool enableLazyAssignmentOperators = false;
-
-  /**
    * A flag indicating whether the parser should parse instance creation
    * expressions that lack either the `new` or `const` keyword.
    */
@@ -9329,36 +9429,14 @@
     Source source = new TestSource();
     listener = new GatheringErrorListener();
 
-    void reportError(
-        ScannerErrorCode errorCode, int offset, List<Object> arguments) {
-      listener
-          .onError(new AnalysisError(source, offset, 1, errorCode, arguments));
-    }
-
-    //
-    // Scan the source.
-    //
-    ScannerResult result = scanString(content,
-        includeComments: true,
-        scanLazyAssignmentOperators: enableLazyAssignmentOperators);
-    Token token = result.tokens;
-    if (result.hasErrors) {
-      // The default recovery strategy used by scanString
-      // places all error tokens at the head of the stream.
-      while (token.type == TokenType.BAD_INPUT) {
-        translateErrorToken(token, reportError);
-        token = token.next;
-      }
-    }
+    ScannerResult result = scanString(content, includeComments: true);
     listener.setLineInfo(source, result.lineStarts);
-    //
-    // Create and initialize the parser.
-    //
-    parser = new Parser(source, listener);
+
+    parser = new Parser(source, listener, featureSet: FeatureSet.forTesting());
     parser.allowNativeClause = allowNativeClause;
     parser.parseFunctionBodies = parseFunctionBodies;
     parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
-    parser.currentToken = token;
+    parser.currentToken = result.tokens;
   }
 
   @override
@@ -9479,32 +9557,13 @@
     Source source = new TestSource();
     GatheringErrorListener listener = new GatheringErrorListener();
 
-    void reportError(
-        ScannerErrorCode errorCode, int offset, List<Object> arguments) {
-      listener
-          .onError(new AnalysisError(source, offset, 1, errorCode, arguments));
-    }
-
-    //
-    // Scan the source.
-    //
-    ScannerResult result = scanString(content,
-        includeComments: true,
-        scanLazyAssignmentOperators: enableLazyAssignmentOperators);
-    Token token = result.tokens;
-    if (result.hasErrors) {
-      // The default recovery strategy used by scanString
-      // places all error tokens at the head of the stream.
-      while (token.type == TokenType.BAD_INPUT) {
-        translateErrorToken(token, reportError);
-        token = token.next;
-      }
-    }
+    ScannerResult result = scanString(content, includeComments: true);
     listener.setLineInfo(source, result.lineStarts);
 
-    Parser parser = new Parser(source, listener);
+    Parser parser =
+        new Parser(source, listener, featureSet: FeatureSet.forTesting());
     parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
-    CompilationUnit unit = parser.parseCompilationUnit(token);
+    CompilationUnit unit = parser.parseCompilationUnit(result.tokens);
     expect(unit, isNotNull);
     if (codes != null) {
       listener.assertErrorsWithCodes(codes);
@@ -9524,31 +9583,12 @@
     Source source = NonExistingSource.unknown;
     listener ??= AnalysisErrorListener.NULL_LISTENER;
 
-    void reportError(
-        ScannerErrorCode errorCode, int offset, List<Object> arguments) {
-      listener
-          .onError(new AnalysisError(source, offset, 1, errorCode, arguments));
-    }
+    ScannerResult result = scanString(content, includeComments: true);
 
-    //
-    // Scan the source.
-    //
-    ScannerResult result = scanString(content,
-        includeComments: true,
-        scanLazyAssignmentOperators: enableLazyAssignmentOperators);
-    Token token = result.tokens;
-    if (result.hasErrors) {
-      // The default recovery strategy used by scanString
-      // places all error tokens at the head of the stream.
-      while (token.type == TokenType.BAD_INPUT) {
-        translateErrorToken(token, reportError);
-        token = token.next;
-      }
-    }
-
-    Parser parser = new Parser(source, listener);
+    Parser parser =
+        new Parser(source, listener, featureSet: FeatureSet.forTesting());
     parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
-    CompilationUnit unit = parser.parseCompilationUnit(token);
+    CompilationUnit unit = parser.parseCompilationUnit(result.tokens);
     unit.lineInfo = new LineInfo(result.lineStarts);
     return unit;
   }
@@ -9872,40 +9912,17 @@
    * Parse the given [content] as a statement. If [enableLazyAssignmentOperators]
    * is `true`, then lazy assignment operators should be enabled.
    */
-  Statement parseStatement(String content,
-      {bool enableLazyAssignmentOperators, int expectedEndOffset}) {
+  Statement parseStatement(String content, {int expectedEndOffset}) {
     Source source = new TestSource();
     listener = new GatheringErrorListener();
-    if (enableLazyAssignmentOperators != null) {
-      this.enableLazyAssignmentOperators = enableLazyAssignmentOperators;
-    }
 
-    void reportError(
-        ScannerErrorCode errorCode, int offset, List<Object> arguments) {
-      listener
-          .onError(new AnalysisError(source, offset, 1, errorCode, arguments));
-    }
-
-    //
-    // Scan the source.
-    //
-    ScannerResult result = scanString(content,
-        includeComments: true,
-        scanLazyAssignmentOperators: enableLazyAssignmentOperators);
-    Token token = result.tokens;
-    if (result.hasErrors) {
-      // The default recovery strategy used by scanString
-      // places all error tokens at the head of the stream.
-      while (token.type == TokenType.BAD_INPUT) {
-        translateErrorToken(token, reportError);
-        token = token.next;
-      }
-    }
+    ScannerResult result = scanString(content, includeComments: true);
     listener.setLineInfo(source, result.lineStarts);
 
-    Parser parser = new Parser(source, listener);
+    Parser parser =
+        new Parser(source, listener, featureSet: FeatureSet.forTesting());
     parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
-    Statement statement = parser.parseStatement(token);
+    Statement statement = parser.parseStatement(result.tokens);
     expect(statement, isNotNull);
     return statement;
   }
@@ -9926,31 +9943,13 @@
     Source source = new TestSource();
     GatheringErrorListener listener = new GatheringErrorListener();
 
-    void reportError(
-        ScannerErrorCode errorCode, int offset, List<Object> arguments) {
-      listener
-          .onError(new AnalysisError(source, offset, 1, errorCode, arguments));
-    }
-
-    //
-    // Scan the source.
-    //
-    ScannerResult result = scanString(content,
-        scanLazyAssignmentOperators: enableLazyAssignmentOperators);
-    Token token = result.tokens;
-    if (result.hasErrors) {
-      // The default recovery strategy used by scanString
-      // places all error tokens at the head of the stream.
-      while (token.type == TokenType.BAD_INPUT) {
-        translateErrorToken(token, reportError);
-        token = token.next;
-      }
-    }
+    ScannerResult result = scanString(content);
     listener.setLineInfo(source, result.lineStarts);
 
-    Parser parser = new Parser(source, listener);
+    Parser parser =
+        new Parser(source, listener, featureSet: FeatureSet.forTesting());
     parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
-    List<Statement> statements = parser.parseStatements(token);
+    List<Statement> statements = parser.parseStatements(result.tokens);
     expect(statements, hasLength(expectedCount));
     listener.assertErrorsWithCodes(errorCodes);
     return statements;
@@ -12345,7 +12344,10 @@
   }
 
   void test_Parser() {
-    expect(new Parser(NonExistingSource.unknown, null), isNotNull);
+    expect(
+        new Parser(NonExistingSource.unknown, null,
+            featureSet: FeatureSet.forTesting()),
+        isNotNull);
   }
 
   void test_skipPrefixedIdentifier_invalid() {
@@ -16403,6 +16405,18 @@
     expect(unit.declarations, hasLength(1));
   }
 
+  void test_parseCompilationUnit_pseudo_asTypeName() {
+    for (Keyword keyword in Keyword.values) {
+      if (keyword.isPseudo) {
+        String lexeme = keyword.lexeme;
+        parseCompilationUnit('$lexeme f;');
+        parseCompilationUnit('class C {$lexeme f;}');
+        parseCompilationUnit('f($lexeme g) {}');
+        parseCompilationUnit('f() {$lexeme g;}');
+      }
+    }
+  }
+
   void test_parseCompilationUnit_pseudo_prefixed() {
     for (Keyword keyword in Keyword.values) {
       if (keyword.isPseudo) {
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 3da22d1..b20c4b5 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 import 'dart:collection';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
@@ -25,6 +26,7 @@
 import 'package:analyzer/src/generated/testing/element_factory.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
 import 'package:analyzer/src/source/source_resource.dart';
+import 'package:analyzer/src/string_source.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -43,6 +45,7 @@
     defineReflectiveTests(ErrorResolverTest);
     defineReflectiveTests(LibraryImportScopeTest);
     defineReflectiveTests(LibraryScopeTest);
+    defineReflectiveTests(NonNullableTypeProviderTest);
     defineReflectiveTests(PrefixedNamespaceTest);
     defineReflectiveTests(ScopeTest);
     defineReflectiveTests(StrictModeTest);
@@ -152,7 +155,7 @@
 }
 
 @reflectiveTest
-class EnclosedScopeTest extends ResolverTestCase {
+class EnclosedScopeTest extends DriverResolutionTest {
   test_define_duplicate() async {
     Scope rootScope = new _RootScope();
     EnclosedScope scope = new EnclosedScope(rootScope);
@@ -168,7 +171,7 @@
 @reflectiveTest
 class ErrorResolverTest extends DriverResolutionTest {
   test_breakLabelOnSwitchMember() async {
-    assertErrorCodesInCode(r'''
+    assertErrorsInCode(r'''
 class A {
   void m(int i) {
     switch (i) {
@@ -178,11 +181,13 @@
         break l;
     }
   }
-}''', [ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER]);
+}''', [
+      error(ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER, 105, 1),
+    ]);
   }
 
   test_continueLabelOnSwitch() async {
-    assertErrorCodesInCode(r'''
+    assertErrorsInCode(r'''
 class A {
   void m(int i) {
     l: switch (i) {
@@ -190,7 +195,9 @@
         continue l;
     }
   }
-}''', [ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH]);
+}''', [
+      error(ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH, 79, 1),
+    ]);
   }
 
   test_enclosingElement_invalidLocalFunction() async {
@@ -332,7 +339,130 @@
 }
 
 @reflectiveTest
-class PrefixedNamespaceTest extends ResolverTestCase {
+class NonNullableTypeProviderTest extends EngineTestCase {
+  void assertNonNullable(InterfaceType type) {
+    expect((type as TypeImpl).nullabilitySuffix, NullabilitySuffix.none);
+  }
+
+  void test_creation() {
+    //
+    // Create a mock library element with the types expected to be in dart:core.
+    // We cannot use either ElementFactory or TestTypeProvider (which uses
+    // ElementFactory) because we side-effect the elements in ways that would
+    // break other tests.
+    //
+    InterfaceType objectType = _classElement("Object", null).type;
+    InterfaceType boolType = _classElement("bool", objectType).type;
+    InterfaceType numType = _classElement("num", objectType).type;
+    InterfaceType deprecatedType = _classElement('Deprecated', objectType).type;
+    InterfaceType doubleType = _classElement("double", numType).type;
+    InterfaceType functionType = _classElement("Function", objectType).type;
+    InterfaceType futureType = _classElement("Future", objectType, ["T"]).type;
+    InterfaceType futureOrType =
+        _classElement("FutureOr", objectType, ["T"]).type;
+    InterfaceType intType = _classElement("int", numType).type;
+    InterfaceType iterableType =
+        _classElement("Iterable", objectType, ["T"]).type;
+    InterfaceType listType = _classElement("List", objectType, ["E"]).type;
+    InterfaceType mapType = _classElement("Map", objectType, ["K", "V"]).type;
+    InterfaceType nullType = _classElement('Null', objectType).type;
+    InterfaceType setType = _classElement("Set", objectType, ["E"]).type;
+    InterfaceType stackTraceType = _classElement("StackTrace", objectType).type;
+    InterfaceType streamType = _classElement("Stream", objectType, ["T"]).type;
+    InterfaceType stringType = _classElement("String", objectType).type;
+    InterfaceType symbolType = _classElement("Symbol", objectType).type;
+    InterfaceType typeType = _classElement("Type", objectType).type;
+    CompilationUnitElementImpl coreUnit = new CompilationUnitElementImpl();
+    coreUnit.types = <ClassElement>[
+      boolType.element,
+      deprecatedType.element,
+      doubleType.element,
+      functionType.element,
+      intType.element,
+      iterableType.element,
+      listType.element,
+      mapType.element,
+      nullType.element,
+      numType.element,
+      setType.element,
+      objectType.element,
+      stackTraceType.element,
+      stringType.element,
+      symbolType.element,
+      typeType.element
+    ];
+    coreUnit.source = new TestSource('dart:core');
+    coreUnit.librarySource = coreUnit.source;
+    CompilationUnitElementImpl asyncUnit = new CompilationUnitElementImpl();
+    asyncUnit.types = <ClassElement>[
+      futureType.element,
+      futureOrType.element,
+      streamType.element
+    ];
+    asyncUnit.source = new TestSource('dart:async');
+    asyncUnit.librarySource = asyncUnit.source;
+    LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
+        null, null, AstTestFactory.libraryIdentifier2(["dart.core"]), true);
+    coreLibrary.definingCompilationUnit = coreUnit;
+    LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
+        null, null, AstTestFactory.libraryIdentifier2(["dart.async"]), true);
+    asyncLibrary.definingCompilationUnit = asyncUnit;
+    //
+    // Create a type provider and ensure that it can return the expected types.
+    //
+    TypeProvider provider =
+        new NonNullableTypeProvider(coreLibrary, asyncLibrary);
+    assertNonNullable(provider.boolType);
+    expect(provider.bottomType, isNotNull);
+    assertNonNullable(provider.deprecatedType);
+    assertNonNullable(provider.doubleType);
+    expect(provider.dynamicType, isNotNull);
+    assertNonNullable(provider.functionType);
+    assertNonNullable(provider.futureType);
+    assertNonNullable(provider.futureOrType);
+    assertNonNullable(provider.intType);
+    assertNonNullable(provider.listType);
+    assertNonNullable(provider.mapType);
+    expect(provider.neverType, isNotNull);
+    assertNonNullable(provider.nullType);
+    assertNonNullable(provider.numType);
+    assertNonNullable(provider.objectType);
+    assertNonNullable(provider.stackTraceType);
+    assertNonNullable(provider.streamType);
+    assertNonNullable(provider.stringType);
+    assertNonNullable(provider.symbolType);
+    assertNonNullable(provider.typeType);
+  }
+
+  ClassElement _classElement(String typeName, InterfaceType superclassType,
+      [List<String> parameterNames]) {
+    ClassElementImpl element =
+        new ClassElementImpl.forNode(AstTestFactory.identifier3(typeName));
+    element.supertype = superclassType;
+    if (parameterNames != null) {
+      int count = parameterNames.length;
+      if (count > 0) {
+        List<TypeParameterElementImpl> typeParameters =
+            new List<TypeParameterElementImpl>(count);
+        List<TypeParameterTypeImpl> typeArguments =
+            new List<TypeParameterTypeImpl>(count);
+        for (int i = 0; i < count; i++) {
+          TypeParameterElementImpl typeParameter =
+              new TypeParameterElementImpl.forNode(
+                  AstTestFactory.identifier3(parameterNames[i]));
+          typeParameters[i] = typeParameter;
+          typeArguments[i] = new TypeParameterTypeImpl(typeParameter);
+          typeParameter.type = typeArguments[i];
+        }
+        element.typeParameters = typeParameters;
+      }
+    }
+    return element;
+  }
+}
+
+@reflectiveTest
+class PrefixedNamespaceTest extends DriverResolutionTest {
   void test_lookup_missing() {
     ClassElement element = ElementFactory.classElement2('A');
     PrefixedNamespace namespace = new PrefixedNamespace('p', _toMap([element]));
@@ -361,7 +491,7 @@
 }
 
 @reflectiveTest
-class ScopeTest extends ResolverTestCase {
+class ScopeTest extends DriverResolutionTest {
   void test_define_duplicate() {
     Scope scope = new _RootScope();
     SimpleIdentifier identifier = AstTestFactory.identifier3('v');
@@ -574,155 +704,143 @@
  * and warnings are reported when the analysis engine is run in strict mode.
  */
 @reflectiveTest
-class StrictModeTest extends ResolverTestCase {
-  @override
-  void setUp() {
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    options.hint = false;
-    resetWith(options: options);
-  }
-
+class StrictModeTest extends DriverResolutionTest {
   test_assert_is() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 int f(num n) {
   assert (n is int);
   return n & 0x0F;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 47, 1),
+    ]);
   }
 
   test_conditional_and_is() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 int f(num n) {
   return (n is int && n > 0) ? n & 0x0F : 0;
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_conditional_is() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 int f(num n) {
   return (n is int) ? n & 0x0F : 0;
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_conditional_isNot() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 int f(num n) {
   return (n is! int) ? 0 : n & 0x0F;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 44, 1),
+    ]);
   }
 
   test_conditional_or_is() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 int f(num n) {
   return (n is! int || n < 0) ? 0 : n & 0x0F;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 53, 1),
+    ]);
   }
 
-  @failingTest
+//  @failingTest
   test_for() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 int f(List<int> list) {
   num sum = 0;
   for (num i = 0; i < list.length; i++) {
     sum += list[i];
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}''', [
+      error(HintCode.MISSING_RETURN, 0, 3),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 30, 3),
+    ]);
   }
 
   test_forEach() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 int f(List<int> list) {
   num sum = 0;
   for (num n in list) {
     sum += n & 0x0F;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}''', [
+      error(HintCode.MISSING_RETURN, 0, 3),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 30, 3),
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 76, 1),
+    ]);
   }
 
   test_if_and_is() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 int f(num n) {
   if (n is int && n > 0) {
     return n & 0x0F;
   }
   return 0;
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_if_is() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 int f(num n) {
   if (n is int) {
     return n & 0x0F;
   }
   return 0;
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_if_isNot() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 int f(num n) {
   if (n is! int) {
     return 0;
   } else {
     return n & 0x0F;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 72, 1),
+    ]);
   }
 
   test_if_isNot_abrupt() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 int f(num n) {
   if (n is! int) {
     return 0;
   }
   return n & 0x0F;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 63, 1),
+    ]);
   }
 
   test_if_or_is() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 int f(num n) {
   if (n is! int || n < 0) {
     return 0;
   } else {
     return n & 0x0F;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 81, 1),
+    ]);
   }
 
   test_localVar() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 int f() {
   num n = 1234;
   return n & 0x0F;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 37, 1),
+    ]);
   }
 }
 
@@ -1066,7 +1184,7 @@
       symbolType.element,
       typeType.element
     ];
-    coreUnit.source = new TestSource('dart:core');
+    coreUnit.source = new StringSource('', null, uri: Uri.parse('dart:core'));
     coreUnit.librarySource = coreUnit.source;
     CompilationUnitElementImpl asyncUnit = new CompilationUnitElementImpl();
     asyncUnit.types = <ClassElement>[
@@ -1074,13 +1192,14 @@
       futureOrType.element,
       streamType.element
     ];
-    asyncUnit.source = new TestSource('dart:async');
+
+    asyncUnit.source = new StringSource('', null, uri: Uri.parse('dart:async'));
     asyncUnit.librarySource = asyncUnit.source;
     LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
-        null, null, AstTestFactory.libraryIdentifier2(["dart.core"]));
+        null, null, AstTestFactory.libraryIdentifier2(["dart.core"]), true);
     coreLibrary.definingCompilationUnit = coreUnit;
     LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
-        null, null, AstTestFactory.libraryIdentifier2(["dart.async"]));
+        null, null, AstTestFactory.libraryIdentifier2(["dart.async"]), true);
     asyncLibrary.definingCompilationUnit = asyncUnit;
     //
     // Create a type provider and ensure that it can return the expected types.
@@ -1180,13 +1299,20 @@
     InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(
         resourceProvider: resourceProvider);
     Source librarySource = new FileSource(getFile("/lib.dart"));
+    // TODO(paulberry): make it possible to override the feature set so we can
+    // test NNBD features.
+    var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
     LibraryElementImpl element = new LibraryElementImpl.forNode(
-        context, null, AstTestFactory.libraryIdentifier2(["lib"]));
+        context,
+        null,
+        AstTestFactory.libraryIdentifier2(["lib"]),
+        featureSet.isEnabled(Feature.non_nullable));
     element.definingCompilationUnit = new CompilationUnitElementImpl();
     _typeProvider = new TestTypeProvider();
     libraryScope = new LibraryScope(element);
     _visitor = new TypeResolverVisitor(
         element, librarySource, _typeProvider, _listener,
+        featureSet: featureSet,
         nameScope: libraryScope,
         shouldSetElementSupertypes: shouldSetElementSupertypes);
   }
@@ -1218,12 +1344,18 @@
       InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(
           resourceProvider: resourceProvider);
       var source = getFile('/test.dart').createSource();
-      var libraryElement = new LibraryElementImpl.forNode(context, null, null)
+      // TODO(paulberry): make it possible to override the feature set so we can
+      // test NNBD features.
+      var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
+      var libraryElement = new LibraryElementImpl.forNode(
+          context, null, null, featureSet.isEnabled(Feature.non_nullable))
         ..definingCompilationUnit = unitElement;
       var libraryScope = new LibraryScope(libraryElement);
       var visitor = new TypeResolverVisitor(
           libraryElement, source, _typeProvider, _listener,
-          nameScope: libraryScope, mode: TypeResolverMode.api);
+          featureSet: featureSet,
+          nameScope: libraryScope,
+          mode: TypeResolverMode.api);
       libraryScope.define(A);
       unit.accept(visitor);
     }
@@ -1834,6 +1966,7 @@
         AstTestFactory.functionTypedFormalParameter(
             AstTestFactory.typeName4('R'), 'g', [eNode]);
     ParameterElementImpl gElement = ElementFactory.requiredParameter('g');
+    gElement.typeParameters = [elementE];
     gNode.identifier.staticElement = gElement;
 
     FunctionTypeImpl gType =
@@ -1952,7 +2085,7 @@
       ..staticElement = new _StaleElement();
     TypeName typeName = astFactory.typeName(id, null);
     _resolveNode(typeName, []);
-    expect(typeName.type, UndefinedTypeImpl.instance);
+    expect(typeName.type, DynamicTypeImpl.instance);
     expect(typeName.name.staticElement, null);
     _listener.assertErrorsWithCodes([StaticWarningCode.UNDEFINED_CLASS]);
   }
@@ -1993,7 +2126,7 @@
     TypeName typeName =
         astFactory.typeName(AstTestFactory.identifier(prefix, suffix), null);
     _resolveNode(typeName, []);
-    expect(typeName.type, UndefinedTypeImpl.instance);
+    expect(typeName.type, DynamicTypeImpl.instance);
     expect(prefix.staticElement, null);
     expect(suffix.staticElement, null);
     _listener.assertErrorsWithCodes([StaticWarningCode.UNDEFINED_CLASS]);
@@ -2088,12 +2221,18 @@
       InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(
           resourceProvider: resourceProvider);
       var source = getFile('/test.dart').createSource();
-      var libraryElement = new LibraryElementImpl.forNode(context, null, null)
+      // TODO(paulberry): make it possible to override the feature set so we can
+      // test NNBD features.
+      var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
+      var libraryElement = new LibraryElementImpl.forNode(
+          context, null, null, featureSet.isEnabled(Feature.non_nullable))
         ..definingCompilationUnit = unitElement;
       libraryScope = new LibraryScope(libraryElement);
       visitor = new TypeResolverVisitor(
           libraryElement, source, _typeProvider, _listener,
-          nameScope: libraryScope, mode: TypeResolverMode.local);
+          featureSet: featureSet,
+          nameScope: libraryScope,
+          mode: TypeResolverMode.local);
     }
 
     // Define top-level types.
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index 9f11907..b0bb6d4 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
@@ -567,10 +568,12 @@
         new CompilationUnitElementImpl();
     compilationUnit.librarySource =
         compilationUnit.source = definingCompilationUnitSource;
+    var featureSet = context.analysisOptions.contextFeatures;
     LibraryElementImpl library = new LibraryElementImpl.forNode(
         context,
         driver?.currentSession,
-        AstTestFactory.libraryIdentifier2([libraryName]));
+        AstTestFactory.libraryIdentifier2([libraryName]),
+        featureSet.isEnabled(Feature.non_nullable));
     library.definingCompilationUnit = compilationUnit;
     library.parts = sourcedCompilationUnits;
     return library;
@@ -795,6 +798,18 @@
   }
 
   /**
+   * Looks up the identifier with [name] and validates that its type type
+   * stringifies to [type] and that its generics match the given stringified
+   * output.
+   */
+  FunctionTypeImpl expectFunctionType2(String name, String type) {
+    SimpleIdentifier identifier = findIdentifier(name);
+    FunctionTypeImpl functionType = identifier.staticType;
+    expect('$functionType', type);
+    return functionType;
+  }
+
+  /**
    * Looks up the identifier with [name] and validates its static [type].
    *
    * If [type] is a string, validates that the identifier's static type
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index 79a88bf..5470859 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -2,12 +2,14 @@
 // 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:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/source/line_info.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/source.dart';
+import 'package:front_end/src/fasta/scanner/error_token.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -77,6 +79,8 @@
 
 @reflectiveTest
 class LineInfoTest extends EngineTestCase {
+  final featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
+
   void test_lineInfo_multilineComment() {
     String source = "/*\r\n *\r\n */";
     _assertLineInfo(source, [
@@ -126,7 +130,8 @@
     String source = "var\r\ni\n=\n1;\n";
     GatheringErrorListener listener = new GatheringErrorListener();
     Scanner scanner =
-        new Scanner(null, new CharSequenceReader(source), listener);
+        new Scanner(null, new CharSequenceReader(source), listener)
+          ..configureFeatures(featureSet);
     var token = scanner.tokenize();
     expect(token.lexeme, 'var');
     var lineStarts = scanner.lineStarts;
@@ -139,11 +144,15 @@
     // See https://github.com/dart-lang/sdk/issues/30320
     String source = '<!-- @Component(';
     GatheringErrorListener listener = new GatheringErrorListener();
-    _scanWithListener(source, listener);
-    listener.assertErrorsWithCodes(const [
-      ScannerErrorCode.EXPECTED_TOKEN,
-      ScannerErrorCode.EXPECTED_TOKEN,
-    ]);
+    Scanner scanner =
+        new Scanner(null, new CharSequenceReader(source), listener)
+          ..configureFeatures(featureSet);
+    Token token = scanner.tokenize(reportScannerErrors: false);
+    expect(token, TypeMatcher<UnmatchedToken>());
+    token = token.next;
+    expect(token, TypeMatcher<UnmatchedToken>());
+    token = token.next;
+    expect(token, isNot(TypeMatcher<ErrorToken>()));
   }
 
   void _assertLineInfo(
@@ -164,11 +173,13 @@
     }
   }
 
-  Token _scanWithListener(String source, GatheringErrorListener listener,
-      {bool lazyAssignmentOperators: false}) {
+  Token _scanWithListener(
+    String source,
+    GatheringErrorListener listener,
+  ) {
     Scanner scanner =
-        new Scanner(null, new CharSequenceReader(source), listener);
-    scanner.scanLazyAssignmentOperators = lazyAssignmentOperators;
+        new Scanner(null, new CharSequenceReader(source), listener)
+          ..configureFeatures(featureSet);
     Token result = scanner.tokenize();
     listener.setLineInfo(new TestSource(), scanner.lineStarts);
     return result;
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index 47bfbff..de35b72 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -993,7 +993,7 @@
     await resolveTestFile();
 
     var node = findNode.simple('myVar(42)');
-    assertType(node, '(int) → String');
+    assertType(node, 'String Function(int)');
   }
 
   test_metadata_class() async {
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index aebb310..36b6c24 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -137,7 +138,7 @@
 }
 """;
     await resolveTestUnit(code);
-    expectIdentifierType("p()", '() → dynamic');
+    expectIdentifierType("p()", 'dynamic Function()');
   }
 
   test_staticMethods_classTypeParameters() async {
@@ -150,7 +151,7 @@
 }
 ''';
     await resolveTestUnit(code);
-    expectFunctionType('m);', '() → void');
+    expectFunctionType('m);', 'void Function()');
   }
 
   test_staticMethods_classTypeParameters_genericMethod() async {
@@ -169,29 +170,30 @@
     // C - m
     TypeParameterType typeS;
     {
-      FunctionTypeImpl type = expectFunctionType('m);', '<S>(S) → void',
+      FunctionTypeImpl type = expectFunctionType('m);', 'void Function<S>(S)',
           elementTypeParams: '[S]',
           typeFormals: '[S]',
-          identifierType: '<S>(S) → void');
+          identifierType: 'void Function<S>(S)');
 
       typeS = type.typeFormals[0].type;
       type = type.instantiate([DynamicTypeImpl.instance]);
-      expect(type.toString(), '(dynamic) → void');
+      expect(type.toString(), 'void Function(dynamic)');
       expect(type.typeParameters.toString(), '[S]');
       expect(type.typeArguments, [DynamicTypeImpl.instance]);
       expect(type.typeFormals, isEmpty);
     }
     // C - m - f
     {
-      FunctionTypeImpl type = expectFunctionType('f);', '<U>(S, U) → void',
+      FunctionTypeImpl type = expectFunctionType(
+          'f);', 'void Function<U>(S, U)',
           elementTypeParams: '[U]',
           typeParams: '[S]',
           typeArgs: '[S]',
           typeFormals: '[U]',
-          identifierType: '<U>(S, U) → void');
+          identifierType: 'void Function<U>(S, U)');
 
       type = type.instantiate([DynamicTypeImpl.instance]);
-      expect(type.toString(), '(S, dynamic) → void');
+      expect(type.toString(), 'void Function(S, dynamic)');
       expect(type.typeParameters.toString(), '[S, U]');
       expect(type.typeArguments, [typeS, DynamicTypeImpl.instance]);
       expect(type.typeFormals, isEmpty);
@@ -1527,13 +1529,14 @@
         new CompilationUnitElementImpl();
     definingCompilationUnit.librarySource =
         definingCompilationUnit.source = source;
-    LibraryElementImpl definingLibrary =
-        new LibraryElementImpl.forNode(context, null, null);
+    var featureSet = FeatureSet.forTesting();
+    LibraryElementImpl definingLibrary = new LibraryElementImpl.forNode(
+        context, null, null, featureSet.isEnabled(Feature.non_nullable));
     definingLibrary.definingCompilationUnit = definingCompilationUnit;
     _typeProvider = context.typeProvider;
     _visitor = new ResolverVisitor(
         inheritance, definingLibrary, source, _typeProvider, _listener,
-        nameScope: new LibraryScope(definingLibrary));
+        featureSet: featureSet, nameScope: new LibraryScope(definingLibrary));
     return _visitor.typeAnalyzer;
   }
 
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index 23012b9..655d38e 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -3,11 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source_io.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'resolver_test_case.dart';
+import '../src/dart/resolution/driver_resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -17,7 +15,7 @@
 }
 
 @reflectiveTest
-class StaticTypeWarningCodeTest extends ResolverTestCase {
+class StaticTypeWarningCodeTest extends DriverResolutionTest {
   test_assert_message_suppresses_type_promotion() async {
     // If a variable is assigned to inside the expression for an assert
     // message, type promotion should be suppressed, just as it would be if the
@@ -35,8 +33,9 @@
     assert(true, () { x = new C(); return 'msg'; }());
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
-    // Do not verify since `x.foo()` fails to resolve.
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_METHOD, 65, 3),
+    ]);
   }
 
   test_await_flattened() async {
@@ -46,7 +45,9 @@
 f() async {
   Future<int> b = await ffi(); 
 }
-''', []);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 82, 1),
+    ]);
   }
 
   test_await_simple() async {
@@ -56,7 +57,10 @@
 f() async {
   String a = await fi(); // Warning: int not assignable to String
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 68, 1),
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 72, 10),
+    ]);
   }
 
   test_awaitForIn_declaredVariableRightType() async {
@@ -76,7 +80,10 @@
   Stream<String> stream;
   await for (int i in stream) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 75, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 80, 6),
+    ]);
   }
 
   test_awaitForIn_downcast() async {
@@ -127,7 +134,10 @@
   int i;
   await for (i in stream) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 64, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 85, 6),
+    ]);
   }
 
   test_awaitForIn_notStream() async {
@@ -135,7 +145,10 @@
 f() async {
   await for (var i in true) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 29, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, 34, 4),
+    ]);
   }
 
   test_awaitForIn_streamOfDynamic() async {
@@ -179,8 +192,9 @@
   }
 }
 ''', [
-      StaticTypeWarningCode.INVALID_ASSIGNMENT,
-      StaticTypeWarningCode.INVALID_ASSIGNMENT
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 271, 4),
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 289, 2),
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 304, 2),
     ]);
   }
 
@@ -188,22 +202,30 @@
     await assertErrorsInCode(r'''
 main() {
   <int, int> [];
-}''', [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS]);
+}
+''', [
+      error(StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS, 11, 10),
+    ]);
   }
 
-  @failingTest
   test_expectedOneSetTypeArgument() async {
     await assertErrorsInCode(r'''
 main() {
-  <int, int>{2, 3};
-}''', [StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS]);
+  <int, int, int>{2, 3};
+}
+''', [
+      error(StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS, 11, 15),
+    ]);
   }
 
   test_expectedTwoMapTypeArguments_three() async {
     await assertErrorsInCode(r'''
 main() {
   <int, int, int> {};
-}''', [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
+}
+''', [
+      error(StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, 11, 15),
+    ]);
   }
 
   test_forIn_declaredVariableRightType() async {
@@ -219,7 +241,10 @@
 f() {
   for (int i in <String>[]) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 22, 10),
+    ]);
   }
 
   test_forIn_downcast() async {
@@ -271,7 +296,10 @@
   int i;
   for (i in <String>[]) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 12, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 27, 10),
+    ]);
   }
 
   test_forIn_iterableOfDynamic() async {
@@ -287,7 +315,10 @@
 f() {
   for (var i in true) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, 22, 4),
+    ]);
   }
 
   test_forIn_object() async {
@@ -306,7 +337,10 @@
     for (String i in iterable) {}
   }
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 81, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 86, 8),
+    ]);
   }
 
   test_forIn_typeBoundGood() async {
@@ -330,7 +364,9 @@
   test_illegalAsyncGeneratorReturnType_function_nonStream() async {
     await assertErrorsInCode('''
 int f() async* {}
-''', [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+''', [
+      error(StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, 0, 3),
+    ]);
   }
 
   test_illegalAsyncGeneratorReturnType_function_subtypeOfStream() async {
@@ -338,7 +374,9 @@
 import 'dart:async';
 abstract class SubStream<T> implements Stream<T> {}
 SubStream<int> f() async* {}
-''', [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+''', [
+      error(StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, 73, 14),
+    ]);
   }
 
   test_illegalAsyncGeneratorReturnType_method_nonStream() async {
@@ -346,7 +384,9 @@
 class C {
   int f() async* {}
 }
-''', [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+''', [
+      error(StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, 12, 3),
+    ]);
   }
 
   test_illegalAsyncGeneratorReturnType_method_subtypeOfStream() async {
@@ -356,15 +396,17 @@
 class C {
   SubStream<int> f() async* {}
 }
-''', [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+''', [
+      error(StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, 85, 14),
+    ]);
   }
 
   test_illegalAsyncReturnType_function_nonFuture() async {
     await assertErrorsInCode('''
 int f() async {}
 ''', [
-      StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE,
-      HintCode.MISSING_RETURN
+      error(StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, 0, 3),
+      error(HintCode.MISSING_RETURN, 0, 3),
     ]);
   }
 
@@ -375,7 +417,9 @@
 SubFuture<int> f() async {
   return 0;
 }
-''', [StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE]);
+''', [
+      error(StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, 73, 14),
+    ]);
   }
 
   test_illegalAsyncReturnType_method_nonFuture() async {
@@ -384,8 +428,8 @@
   int m() async {}
 }
 ''', [
-      StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE,
-      HintCode.MISSING_RETURN
+      error(HintCode.MISSING_RETURN, 12, 3),
+      error(StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, 12, 3),
     ]);
   }
 
@@ -398,20 +442,26 @@
     return 0;
   }
 }
-''', [StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE]);
+''', [
+      error(StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, 85, 14),
+    ]);
   }
 
   test_illegalSyncGeneratorReturnType_function_nonIterator() async {
     await assertErrorsInCode('''
 int f() sync* {}
-''', [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
+''', [
+      error(StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, 0, 3),
+    ]);
   }
 
   test_illegalSyncGeneratorReturnType_function_subclassOfIterator() async {
     await assertErrorsInCode('''
 abstract class SubIterator<T> implements Iterator<T> {}
 SubIterator<int> f() sync* {}
-''', [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
+''', [
+      error(StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, 56, 16),
+    ]);
   }
 
   test_illegalSyncGeneratorReturnType_method_nonIterator() async {
@@ -419,7 +469,9 @@
 class C {
   int f() sync* {}
 }
-''', [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
+''', [
+      error(StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, 12, 3),
+    ]);
   }
 
   test_illegalSyncGeneratorReturnType_method_subclassOfIterator() async {
@@ -428,7 +480,9 @@
 class C {
   SubIterator<int> f() sync* {}
 }
-''', [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
+''', [
+      error(StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, 68, 16),
+    ]);
   }
 
   test_instanceAccessToStaticMember_method_reference() async {
@@ -438,7 +492,10 @@
 }
 main(A a) {
   a.m;
-}''', [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]);
+}
+''', [
+      error(StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 44, 1),
+    ]);
   }
 
   test_instanceAccessToStaticMember_propertyAccess_field() async {
@@ -448,7 +505,10 @@
 }
 main(A a) {
   a.f;
-}''', [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]);
+}
+''', [
+      error(StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 44, 1),
+    ]);
   }
 
   test_instanceAccessToStaticMember_propertyAccess_getter() async {
@@ -458,7 +518,10 @@
 }
 main(A a) {
   a.f;
-}''', [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]);
+}
+''', [
+      error(StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 50, 1),
+    ]);
   }
 
   test_instanceAccessToStaticMember_propertyAccess_setter() async {
@@ -468,7 +531,10 @@
 }
 main(A a) {
   a.f = 42;
-}''', [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]);
+}
+''', [
+      error(StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 49, 1),
+    ]);
   }
 
   test_invalidAssignment_compoundAssignment() async {
@@ -482,19 +548,29 @@
 void main() {
   byte b = new byte(52);
   b += 3;
-}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+}
+''', [
+      error(HintCode.UNUSED_FIELD, 19, 6),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 112, 1),
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 137, 1),
+    ]);
   }
 
   test_invalidAssignment_defaultValue_named() async {
     await assertErrorsInCode(r'''
 f({String x: 0}) {
-}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+}
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 13, 1),
+    ]);
   }
 
   test_invalidAssignment_defaultValue_optional() async {
     await assertErrorsInCode(r'''
 f([String x = 0]) {
-}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+}''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 14, 1),
+    ]);
   }
 
   test_invalidAssignment_dynamic() async {
@@ -502,14 +578,20 @@
 main() {
   dynamic = 1;
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 21, 1),
+    ]);
   }
 
   test_invalidAssignment_functionExpressionInvocation() async {
     await assertErrorsInCode('''
 main() {
   String x = (() => 5)();
-}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 18, 1),
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 22, 11),
+    ]);
   }
 
   test_invalidAssignment_ifNullAssignment() async {
@@ -518,7 +600,9 @@
   double d;
   d ??= i;
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 36, 1),
+    ]);
   }
 
   test_invalidAssignment_instanceVariable() async {
@@ -529,7 +613,10 @@
 f() {
   A a;
   a.x = '0';
-}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+}
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 42, 3),
+    ]);
   }
 
   test_invalidAssignment_localVariable() async {
@@ -537,7 +624,11 @@
 f() {
   int x;
   x = '0';
-}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 12, 1),
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 21, 3),
+    ]);
   }
 
   test_invalidAssignment_postfixExpression_localVariable() async {
@@ -551,7 +642,9 @@
 f(A a) {
   a++;
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 65, 3),
+    ]);
   }
 
   test_invalidAssignment_postfixExpression_property() async {
@@ -569,7 +662,9 @@
 f(C c) {
   c.a++;
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 85, 5),
+    ]);
   }
 
   test_invalidAssignment_prefixExpression_localVariable() async {
@@ -583,7 +678,9 @@
 f(A a) {
   ++a;
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 65, 3),
+    ]);
   }
 
   test_invalidAssignment_prefixExpression_property() async {
@@ -601,7 +698,9 @@
 f(C c) {
   ++c.a;
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 85, 5),
+    ]);
   }
 
   test_invalidAssignment_regressionInIssue18468Fix() async {
@@ -609,7 +708,10 @@
     await assertErrorsInCode(r'''
 class C<T> {
   T t = int;
-}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+}
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 21, 3),
+    ]);
   }
 
   test_invalidAssignment_staticVariable() async {
@@ -619,12 +721,18 @@
 }
 f() {
   A.x = '0';
-}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+}
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 42, 3),
+    ]);
   }
 
   test_invalidAssignment_topLevelVariableDeclaration() async {
-    await assertErrorsInCode(
-        "int x = 'string';", [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+    await assertErrorsInCode('''
+int x = 'string';
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 8, 8),
+    ]);
   }
 
   test_invalidAssignment_typeParameter() async {
@@ -635,33 +743,48 @@
   void test(num n) {
     value = n;
   }
-}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+}
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 57, 1),
+    ]);
   }
 
   test_invalidAssignment_variableDeclaration() async {
     await assertErrorsInCode(r'''
 class A {
   int x = 'string';
-}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+}
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 20, 8),
+    ]);
   }
 
   test_invocationOfNonFunctionExpression_literal() async {
     await assertErrorsInCode(r'''
 f() {
   3(5);
-}''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION]);
+}
+''', [
+      error(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, 8, 1),
+    ]);
   }
 
   test_nonBoolCondition_conditional() async {
-    await assertErrorsInCode("f() { return 3 ? 2 : 1; }",
-        [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+    await assertErrorsInCode('''
+f() { return 3 ? 2 : 1; }
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_CONDITION, 13, 1),
+    ]);
   }
 
   test_nonBoolCondition_do() async {
     await assertErrorsInCode(r'''
 f() {
   do {} while (3);
-}''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_CONDITION, 21, 1),
+    ]);
   }
 
   test_nonBoolCondition_for() async {
@@ -669,32 +792,41 @@
     await assertErrorsInCode(r'''
 f() {
   for (;3;) {}
-}''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_CONDITION, 14, 1),
+    ]);
   }
 
   test_nonBoolCondition_if() async {
     await assertErrorsInCode(r'''
 f() {
   if (3) return 2; else return 1;
-}''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_CONDITION, 12, 1),
+    ]);
   }
 
   test_nonBoolCondition_while() async {
     await assertErrorsInCode(r'''
 f() {
   while (3) {}
-}''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_CONDITION, 15, 1),
+    ]);
   }
 
   test_nonBoolExpression_functionType_bool() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 bool makeAssertion() => true;
 f() {
   assert(makeAssertion);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
-    verify([source]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_EXPRESSION, 45, 13),
+    ]);
   }
 
   test_nonBoolExpression_functionType_int() async {
@@ -702,62 +834,89 @@
 int makeAssertion() => 1;
 f() {
   assert(makeAssertion);
-}''', [StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_EXPRESSION, 41, 13),
+    ]);
   }
 
   test_nonBoolExpression_interfaceType() async {
     await assertErrorsInCode(r'''
 f() {
   assert(0);
-}''', [StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_EXPRESSION, 15, 1),
+    ]);
   }
 
   test_nonBoolNegationExpression() async {
     await assertErrorsInCode(r'''
 f() {
   !42;
-}''', [StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION, 9, 2),
+    ]);
   }
 
   test_nonBoolOperand_and_left() async {
     await assertErrorsInCode(r'''
 bool f(int left, bool right) {
   return left && right;
-}''', [StaticTypeWarningCode.NON_BOOL_OPERAND]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_OPERAND, 40, 4),
+    ]);
   }
 
   test_nonBoolOperand_and_right() async {
     await assertErrorsInCode(r'''
 bool f(bool left, String right) {
   return left && right;
-}''', [StaticTypeWarningCode.NON_BOOL_OPERAND]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_OPERAND, 51, 5),
+    ]);
   }
 
   test_nonBoolOperand_or_left() async {
     await assertErrorsInCode(r'''
 bool f(List<int> left, bool right) {
   return left || right;
-}''', [StaticTypeWarningCode.NON_BOOL_OPERAND]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_OPERAND, 46, 4),
+    ]);
   }
 
   test_nonBoolOperand_or_right() async {
     await assertErrorsInCode(r'''
 bool f(bool left, double right) {
   return left || right;
-}''', [StaticTypeWarningCode.NON_BOOL_OPERAND]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_BOOL_OPERAND, 51, 5),
+    ]);
   }
 
   test_nonTypeAsTypeArgument_notAType() async {
     await assertErrorsInCode(r'''
 int A;
 class B<E> {}
-f(B<A> b) {}''', [StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT]);
+f(B<A> b) {}
+''', [
+      error(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT, 25, 1),
+    ]);
   }
 
   test_nonTypeAsTypeArgument_undefinedIdentifier() async {
     await assertErrorsInCode(r'''
 class B<E> {}
-f(B<A> b) {}''', [StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT]);
+f(B<A> b) {}
+''', [
+      error(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT, 18, 1),
+    ]);
   }
 
   test_returnOfInvalidType_async_future_future_int_mismatches_future_int() async {
@@ -767,7 +926,9 @@
   return g();
 }
 Future<Future<int>> g() => null;
-''', [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+''', [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 54, 3),
+    ]);
   }
 
   test_returnOfInvalidType_async_future_int_mismatches_future_string() async {
@@ -776,7 +937,9 @@
 Future<String> f() async {
   return 5;
 }
-''', [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+''', [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 57, 1),
+    ]);
   }
 
   test_returnOfInvalidType_async_future_int_mismatches_int() async {
@@ -785,19 +948,25 @@
   return 5;
 }
 ''', [
-      StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
-      StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE
+      error(StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, 0, 3),
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 25, 1),
     ]);
   }
 
   test_returnOfInvalidType_expressionFunctionBody_function() async {
-    await assertErrorsInCode(
-        "int f() => '0';", [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+    await assertErrorsInCode('''
+int f() => '0';
+''', [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 11, 3),
+    ]);
   }
 
   test_returnOfInvalidType_expressionFunctionBody_getter() async {
-    await assertErrorsInCode(
-        "int get g => '0';", [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+    await assertErrorsInCode('''
+int get g => '0';
+''', [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 13, 3),
+    ]);
   }
 
   test_returnOfInvalidType_expressionFunctionBody_localFunction() async {
@@ -807,24 +976,37 @@
     int f() => '0';
     return '0';
   }
-}''', [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 33, 1),
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 40, 3),
+    ]);
   }
 
   test_returnOfInvalidType_expressionFunctionBody_method() async {
     await assertErrorsInCode(r'''
 class A {
   int f() => '0';
-}''', [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+}
+''', [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 23, 3),
+    ]);
   }
 
   test_returnOfInvalidType_function() async {
-    await assertErrorsInCode("int f() { return '0'; }",
-        [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+    await assertErrorsInCode('''
+int f() { return '0'; }
+''', [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 17, 3),
+    ]);
   }
 
   test_returnOfInvalidType_getter() async {
-    await assertErrorsInCode("int get g { return '0'; }",
-        [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+    await assertErrorsInCode('''
+int get g { return '0'; }
+''', [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 19, 3),
+    ]);
   }
 
   test_returnOfInvalidType_localFunction() async {
@@ -834,18 +1016,27 @@
     int f() { return '0'; }
     return '0';
   }
-}''', [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 33, 1),
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 46, 3),
+    ]);
   }
 
   test_returnOfInvalidType_method() async {
     await assertErrorsInCode(r'''
 class A {
   int f() { return '0'; }
-}''', [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+}
+''', [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 29, 3),
+    ]);
   }
 
   test_returnOfInvalidType_not_issued_for_expressionFunctionBody_void() async {
-    await assertNoErrorsInCode("void f() => 42;");
+    await assertNoErrorsInCode('''
+void f() => 42;
+''');
   }
 
   test_returnOfInvalidType_not_issued_for_valid_generic_return() async {
@@ -862,12 +1053,14 @@
   S test(F<int, S> arg) => arg.value;
 }
 
-void main() { }''');
+void main() { }
+''');
   }
 
   test_returnOfInvalidType_void() async {
-    await assertErrorsInCode("void f() { return 42; }",
-        [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+    await assertErrorsInCode("void f() { return 42; }", [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 18, 2),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_classTypeAlias() async {
@@ -877,7 +1070,9 @@
 class C {}
 class G<E extends A> {}
 class D = G<B> with C;
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 69, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_extends() async {
@@ -886,7 +1081,9 @@
 class B {}
 class G<E extends A> {}
 class C extends G<B>{}
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 64, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_extends_regressionInIssue18468Fix() async {
@@ -894,7 +1091,9 @@
     await assertErrorsInCode(r'''
 class X<T extends Type> {}
 class Y<U> extends X<U> {}
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_fieldFormalParameter() async {
@@ -905,7 +1104,10 @@
 class C {
   var f;
   C(G<B> this.f) {}
-}''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+}
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 71, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_functionReturnType() async {
@@ -914,7 +1116,9 @@
 class B {}
 class G<E extends A> {}
 G<B> f() { return null; }
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_functionTypeAlias() async {
@@ -923,7 +1127,9 @@
 class B {}
 class G<E extends A> {}
 typedef G<B> f();
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 56, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_functionTypedFormalParameter() async {
@@ -932,7 +1138,9 @@
 class B {}
 class G<E extends A> {}
 f(G<B> h()) {}
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 50, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_implements() async {
@@ -941,7 +1149,9 @@
 class B {}
 class G<E extends A> {}
 class C implements G<B>{}
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 67, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_is() async {
@@ -950,7 +1160,9 @@
 class B {}
 class G<E extends A> {}
 var b = 1 is G<B>;
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 61, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_methodInvocation_localFunction() async {
@@ -965,7 +1177,9 @@
   }
   print(f<String>('hello', 'world'));
 }
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 145, 6),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_methodInvocation_method() async {
@@ -983,7 +1197,9 @@
 f(PointFactory factory) {
   print(factory.point<String>('hello', 'world'));
 }
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 202, 6),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_methodInvocation_topLevelFunction() async {
@@ -999,7 +1215,9 @@
 main() {
   print(f<String>('hello', 'world'));
 }
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 140, 6),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_methodReturnType() async {
@@ -1009,7 +1227,10 @@
 class G<E extends A> {}
 class C {
   G<B> m() { return null; }
-}''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+}
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 60, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_new() async {
@@ -1018,7 +1239,9 @@
 class B {}
 class G<E extends A> {}
 f() { return new G<B>(); }
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 65, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_new_superTypeOfUpperBound() async {
@@ -1028,7 +1251,9 @@
 class C extends B {}
 class G<E extends B> {}
 f() { return new G<A>(); }
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 96, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_ofFunctionTypeAlias() async {
@@ -1037,7 +1262,9 @@
 class B {}
 typedef F<T extends A>();
 F<B> fff;
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 50, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_parameter() async {
@@ -1046,7 +1273,9 @@
 class B {}
 class G<E extends A> {}
 f(G<B> g) {}
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 50, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_redirectingConstructor() async {
@@ -1056,9 +1285,10 @@
 class X<T extends A> {
   X(int x, int y) {}
   factory X.name(int x, int y) = X<B>;
-}''', [
-      StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
-      StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE
+}
+''', [
+      error(StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE, 99, 4),
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 101, 1),
     ]);
   }
 
@@ -1069,7 +1299,9 @@
 class C<E> {}
 class D<E extends A> {}
 C<D<B>> Var;
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 64, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_typeParameter() async {
@@ -1079,7 +1311,9 @@
 class C {}
 class G<E extends A> {}
 class D<F extends G<B>> {}
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 77, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_variableDeclaration() async {
@@ -1088,7 +1322,9 @@
 class B {}
 class G<E extends A> {}
 G<B> g;
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1),
+    ]);
   }
 
   test_typeArgumentNotMatchingBounds_with() async {
@@ -1097,66 +1333,88 @@
 class B {}
 class G<E extends A> {}
 class C extends Object with G<B>{}
-''', [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+''', [
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 76, 1),
+    ]);
   }
 
   test_typeParameterSupertypeOfItsBound() async {
     await assertErrorsInCode(r'''
 class A<T extends T> {
 }
-''', [StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND]);
+''', [
+      error(StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND, 8, 11),
+    ]);
   }
 
   test_typePromotion_booleanAnd_useInRight_accessedInClosureRight_mutated() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 callMe(f()) { f(); }
 main(Object p) {
   (p is String) && callMe(() { p.length; });
   p = 0;
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 71, 6),
+    ]);
   }
 
   test_typePromotion_booleanAnd_useInRight_mutatedInLeft() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 main(Object p) {
   ((p is String) && ((p = 42) == 42)) && p.length != 0;
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 60, 6),
+    ]);
   }
 
   test_typePromotion_booleanAnd_useInRight_mutatedInRight() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 main(Object p) {
   (p is String) && (((p = 42) == 42) && p.length != 0);
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 59, 6),
+    ]);
   }
 
   test_typePromotion_conditional_useInThen_accessedInClosure_hasAssignment_after() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 callMe(f()) { f(); }
 main(Object p) {
   p is String ? callMe(() { p.length; }) : 0;
   p = 42;
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 68, 6),
+    ]);
   }
 
   test_typePromotion_conditional_useInThen_accessedInClosure_hasAssignment_before() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 callMe(f()) { f(); }
 main(Object p) {
   p = 42;
   p is String ? callMe(() { p.length; }) : 0;
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 78, 6),
+    ]);
   }
 
   test_typePromotion_conditional_useInThen_hasAssignment() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 main(Object p) {
   p is String ? (p.length + (p = 42)) : 0;
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 36, 6),
+    ]);
   }
 
   test_typePromotion_if_accessedInClosure_hasAssignment() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 callMe(f()) { f(); }
 main(Object p) {
   if (p is String) {
@@ -1165,20 +1423,26 @@
     });
   }
   p = 0;
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 83, 6),
+    ]);
   }
 
   test_typePromotion_if_and_right_hasAssignment() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 main(Object p) {
   if (p is String && (p = null) == null) {
     p.length;
   }
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 66, 6),
+    ]);
   }
 
   test_typePromotion_if_extends_notMoreSpecific_dynamic() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class V {}
 class A<T> {}
 class B<S> extends A<S> {
@@ -1189,11 +1453,14 @@
   if (p is B) {
     p.b;
   }
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 100, 1),
+    ]);
   }
 
   test_typePromotion_if_extends_notMoreSpecific_notMoreSpecificTypeArg() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class V {}
 class A<T> {}
 class B<S> extends A<S> {
@@ -1204,71 +1471,94 @@
   if (p is B<int>) {
     p.b;
   }
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 105, 1),
+    ]);
   }
 
   test_typePromotion_if_hasAssignment_after() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 main(Object p) {
   if (p is String) {
     p.length;
     p = 0;
   }
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 44, 6),
+    ]);
   }
 
   test_typePromotion_if_hasAssignment_before() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 main(Object p) {
   if (p is String) {
     p = 0;
     p.length;
   }
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 55, 6),
+    ]);
   }
 
   test_typePromotion_if_hasAssignment_inClosure_anonymous_after() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 main(Object p) {
   if (p is String) {
     p.length;
   }
   () {p = 0;};
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 44, 6),
+    ]);
   }
 
   test_typePromotion_if_hasAssignment_inClosure_anonymous_before() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 main(Object p) {
   () {p = 0;};
   if (p is String) {
     p.length;
   }
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 59, 6),
+    ]);
   }
 
   test_typePromotion_if_hasAssignment_inClosure_function_after() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 main(Object p) {
   if (p is String) {
     p.length;
   }
   f() {p = 0;};
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 44, 6),
+      error(HintCode.UNUSED_ELEMENT, 58, 1),
+    ]);
   }
 
   test_typePromotion_if_hasAssignment_inClosure_function_before() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 main(Object p) {
   f() {p = 0;};
   if (p is String) {
     p.length;
   }
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 19, 1),
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 60, 6),
+    ]);
   }
 
   test_typePromotion_if_implements_notMoreSpecific_dynamic() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class V {}
 class A<T> {}
 class B<S> implements A<S> {
@@ -1279,11 +1569,14 @@
   if (p is B) {
     p.b;
   }
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 103, 1),
+    ]);
   }
 
   test_typePromotion_if_with_notMoreSpecific_dynamic() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class V {}
 class A<T> {}
 class B<S> extends Object with A<S> {
@@ -1295,7 +1588,9 @@
     p.b;
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 112, 1),
+    ]);
   }
 
   test_undefinedEnumConstant() async {
@@ -1305,21 +1600,25 @@
 E e() {
   return E.TWO;
 }
-''', [StaticTypeWarningCode.UNDEFINED_GETTER], verify: false);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 34, 3),
+    ]);
   }
 
   test_undefinedGetter() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class T {}
 f(T e) { return e.m; }
-''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 29, 1),
+    ]);
   }
 
   test_undefinedGetter_generic_function_call() async {
     // Referencing `.call` on a `Function` type works similarly to referencing
     // it on `dynamic`--the reference is accepted at compile time, and all type
     // checking is deferred until runtime.
-    await assertErrorsInUnverifiedCode('''
+    await assertErrorsInCode('''
 f(Function f) {
   return f.call;
 }
@@ -1327,11 +1626,13 @@
   }
 
   test_undefinedGetter_object_call() async {
-    await assertErrorsInUnverifiedCode('''
+    await assertErrorsInCode('''
 f(Object o) {
   return o.call;
 }
-''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 25, 4),
+    ]);
   }
 
   test_undefinedGetter_proxy_annotation_fakeProxy() async {
@@ -1344,13 +1645,18 @@
 @proxy class PrefixProxy {}
 main() {
   new PrefixProxy().foo;
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 127, 3),
+    ]);
   }
 
   test_undefinedGetter_static() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
-var a = A.B;''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+var a = A.B;''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 21, 1),
+    ]);
   }
 
   test_undefinedGetter_typeLiteral_cascadeTarget() async {
@@ -1360,17 +1666,21 @@
 }
 main() {
   T..foo;
-}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 54, 3),
+    ]);
   }
 
   test_undefinedGetter_typeLiteral_conditionalAccess() async {
     // When applied to a type literal, the conditional access operator '?.'
     // cannot be used to access instance getters of Type.
-    // TODO(brianwilkerson) We cannot verify because hashCode isn't resolved.
     await assertErrorsInCode('''
 class A {}
 f() => A?.hashCode;
-''', [StaticTypeWarningCode.UNDEFINED_GETTER], verify: false);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 21, 8),
+    ]);
   }
 
   test_undefinedGetter_wrongNumberOfTypeArguments_tooLittle() async {
@@ -1380,7 +1690,10 @@
 }
 main(A<int> a) {
   a.element.anyGetterExistsInDynamic;
-}''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+}
+''', [
+      error(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 36, 6),
+    ]);
   }
 
   test_undefinedGetter_wrongNumberOfTypeArguments_tooMany() async {
@@ -1390,7 +1703,10 @@
 }
 main(A<int,int> a) {
   a.element.anyGetterExistsInDynamic;
-}''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+}
+''', [
+      error(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 33, 10),
+    ]);
   }
 
   test_undefinedGetter_wrongOfTypeArgument() async {
@@ -1400,7 +1716,10 @@
 }
 main(A<NoSuchType> a) {
   a.element.anyGetterExistsInDynamic;
-}''', [StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT]);
+}
+''', [
+      error(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT, 35, 10),
+    ]);
   }
 
   test_undefinedMethod_assignmentExpression() async {
@@ -1411,7 +1730,10 @@
     A a2 = new A();
     a += a2;
   }
-}''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_METHOD, 58, 2),
+    ]);
   }
 
   test_undefinedMethod_ignoreTypePropagation() async {
@@ -1425,12 +1747,18 @@
     A a = new B();
     a.m();
   }
-}''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_METHOD, 85, 1),
+    ]);
   }
 
   test_undefinedMethod_leastUpperBoundWithNull() async {
-    await assertErrorsInCode('f(bool b, int i) => (b ? null : i).foo();',
-        [StaticTypeWarningCode.UNDEFINED_METHOD]);
+    await assertErrorsInCode('''
+f(bool b, int i) => (b ? null : i).foo();
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_METHOD, 35, 3),
+    ]);
   }
 
   test_undefinedMethod_ofNull() async {
@@ -1441,53 +1769,65 @@
 main() {
   f(42).abs();
 }
-''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_METHOD, 40, 3),
+    ]);
   }
 
   test_undefinedMethodWithConstructor() async {
-    // TODO(brianwilkerson) We cannot verify because 'C' could not be resolved.
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   C.m();
 }
 f() {
   C c = C.m();
-}''', [], verify: false);
+}
+''');
   }
 
   test_undefinedOperator_indexBoth() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 f(A a) {
   a[0]++;
-}''', [
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 23, 3),
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 23, 3),
     ]);
   }
 
   test_undefinedOperator_indexGetter() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 f(A a) {
   a[0];
-}''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 23, 3),
+    ]);
   }
 
   test_undefinedOperator_indexSetter() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 f(A a) {
   a[0] = 1;
-}''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 23, 3),
+    ]);
   }
 
   test_undefinedOperator_plus() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 f(A a) {
   a + 1;
-}''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 24, 1),
+    ]);
   }
 
   test_undefinedOperator_postfixExpression() async {
@@ -1495,7 +1835,10 @@
 class A {}
 f(A a) {
   a++;
-}''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 23, 2),
+    ]);
   }
 
   test_undefinedOperator_prefixExpression() async {
@@ -1503,19 +1846,28 @@
 class A {}
 f(A a) {
   ++a;
-}''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 22, 2),
+    ]);
   }
 
   test_undefinedSetter() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class T {}
-f(T e1) { e1.m = 0; }''', [StaticTypeWarningCode.UNDEFINED_SETTER]);
+f(T e1) { e1.m = 0; }
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_SETTER, 24, 1),
+    ]);
   }
 
   test_undefinedSetter_static() async {
-    await assertErrorsInUnverifiedCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
-f() { A.B = 0;}''', [StaticTypeWarningCode.UNDEFINED_SETTER]);
+f() { A.B = 0;}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_SETTER, 19, 1),
+    ]);
   }
 
   test_undefinedSetter_typeLiteral_cascadeTarget() async {
@@ -1525,7 +1877,10 @@
 }
 main() {
   T..foo = 42;
-}''', [StaticTypeWarningCode.UNDEFINED_SETTER]);
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_SETTER, 54, 3),
+    ]);
   }
 
   test_unqualifiedReferenceToNonLocalStaticMember_getter() async {
@@ -1537,7 +1892,14 @@
   int b() {
     return a;
   }
-}''', [StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER]);
+}
+''', [
+      error(
+          StaticTypeWarningCode
+              .UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
+          80,
+          1),
+    ]);
   }
 
   test_unqualifiedReferenceToNonLocalStaticMember_getter_invokeTarget() async {
@@ -1551,7 +1913,13 @@
     foo.abs();
   }
 }
-''', [StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER]);
+''', [
+      error(
+          StaticTypeWarningCode
+              .UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
+          72,
+          3),
+    ]);
   }
 
   test_unqualifiedReferenceToNonLocalStaticMember_setter() async {
@@ -1563,33 +1931,50 @@
   b(y) {
     a = y;
   }
-}''', [StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER]);
+}
+''', [
+      error(
+          StaticTypeWarningCode
+              .UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
+          66,
+          1),
+    ]);
   }
 
   test_wrongNumberOfTypeArguments_class_tooFew() async {
     await assertErrorsInCode(r'''
 class A<E, F> {}
-A<A> a = null;''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+A<A> a = null;
+''', [
+      error(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 17, 4),
+    ]);
   }
 
   test_wrongNumberOfTypeArguments_class_tooMany() async {
     await assertErrorsInCode(r'''
 class A<E> {}
-A<A, A> a = null;''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+A<A, A> a = null;
+''', [
+      error(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 14, 7),
+    ]);
   }
 
   test_wrongNumberOfTypeArguments_classAlias() async {
     await assertErrorsInCode(r'''
 class A {}
 class M {}
-class B<F extends num> = A<F> with M;''',
-        [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+class B<F extends num> = A<F> with M;
+''', [
+      error(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 47, 4),
+    ]);
   }
 
   test_wrongNumberOfTypeArguments_dynamic() async {
     await assertErrorsInCode(r'''
 dynamic<int> v;
-''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+''', [
+      error(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 0, 12),
+    ]);
   }
 
   test_wrongNumberOfTypeArguments_typeParameter() async {
@@ -1597,7 +1982,9 @@
 class C<T> {
   T<int> f;
 }
-''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+''', [
+      error(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 15, 6),
+    ]);
   }
 
   test_wrongNumberOfTypeArguments_typeTest_tooFew() async {
@@ -1606,7 +1993,10 @@
 class C<K, V> {}
 f(p) {
   return p is C<A>;
-}''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+}
+''', [
+      error(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 49, 4),
+    ]);
   }
 
   test_wrongNumberOfTypeArguments_typeTest_tooMany() async {
@@ -1615,7 +2005,10 @@
 class C<E> {}
 f(p) {
   return p is C<A, A>;
-}''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+}
+''', [
+      error(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 46, 7),
+    ]);
   }
 
   test_yield_async_to_basic_type() async {
@@ -1624,8 +2017,8 @@
   yield 3;
 }
 ''', [
-      StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
-      StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE
+      error(StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, 0, 3),
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 25, 1),
     ]);
   }
 
@@ -1635,8 +2028,8 @@
   yield 3;
 }
 ''', [
-      StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
-      StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE
+      error(StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, 0, 13),
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 35, 1),
     ]);
   }
 
@@ -1646,7 +2039,9 @@
 Stream<int> f() async* {
   yield "foo";
 }
-''', [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+''', [
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 54, 5),
+    ]);
   }
 
   test_yield_each_async_non_stream() async {
@@ -1654,7 +2049,9 @@
 f() async* {
   yield* 0;
 }
-''', [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+''', [
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 22, 1),
+    ]);
   }
 
   test_yield_each_async_to_mistyped_stream() async {
@@ -1664,7 +2061,9 @@
   yield* g();
 }
 Stream<String> g() => null;
-''', [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+''', [
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 55, 3),
+    ]);
   }
 
   test_yield_each_sync_non_iterable() async {
@@ -1672,7 +2071,9 @@
 f() sync* {
   yield* 0;
 }
-''', [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+''', [
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 21, 1),
+    ]);
   }
 
   test_yield_each_sync_to_mistyped_iterable() async {
@@ -1681,7 +2082,9 @@
   yield* g();
 }
 Iterable<String> g() => null;
-''', [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+''', [
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 35, 3),
+    ]);
   }
 
   test_yield_sync_to_basic_type() async {
@@ -1690,8 +2093,8 @@
   yield 3;
 }
 ''', [
-      StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
-      StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE
+      error(StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, 0, 3),
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 24, 1),
     ]);
   }
 
@@ -1700,7 +2103,9 @@
 Iterable<int> f() sync* {
   yield "foo";
 }
-''', [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+''', [
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 34, 5),
+    ]);
   }
 
   test_yield_sync_to_stream() async {
@@ -1710,22 +2115,16 @@
   yield 3;
 }
 ''', [
-      StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
-      StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE
+      error(StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, 21, 11),
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 53, 1),
     ]);
   }
 }
 
 @reflectiveTest
-class StrongModeStaticTypeWarningCodeTest extends ResolverTestCase {
-  void setUp() {
-    super.setUp();
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    resetWith(options: options);
-  }
-
+class StrongModeStaticTypeWarningCodeTest extends DriverResolutionTest {
   test_legalAsyncGeneratorReturnType_function_supertypeOfStream() async {
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 f() async* { yield 42; }
 dynamic f2() async* { yield 42; }
@@ -1735,11 +2134,11 @@
 Stream<Object> f6() async* { yield 42; }
 Stream<num> f7() async* { yield 42; }
 Stream<int> f8() async* { yield 42; }
-''', []);
+''');
   }
 
   test_legalAsyncReturnType_function_supertypeOfFuture() async {
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 import 'dart:async';
 f() async { return 42; }
 dynamic f2() async { return 42; }
@@ -1749,11 +2148,11 @@
 Future<Object> f6() async { return 42; }
 Future<num> f7() async { return 42; }
 Future<int> f8() async { return 42; }
-''', []);
+''');
   }
 
   test_legalSyncGeneratorReturnType_function_supertypeOfIterable() async {
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 f() sync* { yield 42; }
 dynamic f2() sync* { yield 42; }
 Object f3() sync* { yield 42; }
@@ -1762,6 +2161,6 @@
 Iterable<Object> f6() sync* { yield 42; }
 Iterable<num> f7() sync* { yield 42; }
 Iterable<int> f8() sync* { yield 42; }
-''', []);
+''');
   }
 }
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index 463cae1..3ace484 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -2,14 +2,14 @@
 // 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:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/source_io.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'resolver_test_case.dart';
+import '../src/dart/resolution/driver_resolution.dart';
+import 'test_support.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -18,141 +18,151 @@
 }
 
 @reflectiveTest
-class StaticWarningCodeTest extends ResolverTestCase {
+class StaticWarningCodeTest extends DriverResolutionTest {
   test_ambiguousImport_as() async {
-    Source source = addSource(r'''
-import 'lib1.dart';
-import 'lib2.dart';
-f(p) {p as N;}''');
-    addNamedSource("/lib1.dart", r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
 class N {}''');
-    addNamedSource("/lib2.dart", r'''
+    newFile("/test/lib/lib2.dart", content: '''
 library lib2;
 class N {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
+    await assertErrorsInCode('''
+import 'lib1.dart';
+import 'lib2.dart';
+f(p) {p as N;}''', [
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 51, 1),
+    ]);
   }
 
   test_ambiguousImport_dart() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 import 'dart:async';
 import 'dart:async2';
 
 Future v;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
+''', [
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 44, 6),
+    ]);
   }
 
   test_ambiguousImport_extends() async {
-    Source source = addSource(r'''
-import 'lib1.dart';
-import 'lib2.dart';
-class A extends N {}''');
-    addNamedSource("/lib1.dart", r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
 class N {}''');
-    addNamedSource("/lib2.dart", r'''
+    newFile("/test/lib/lib2.dart", content: '''
 library lib2;
 class N {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.AMBIGUOUS_IMPORT,
-      CompileTimeErrorCode.EXTENDS_NON_CLASS
+    await assertErrorsInCode('''
+import 'lib1.dart';
+import 'lib2.dart';
+class A extends N {}''', [
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 56, 1),
+      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 56, 1),
     ]);
   }
 
   test_ambiguousImport_implements() async {
-    Source source = addSource(r'''
-import 'lib1.dart';
-import 'lib2.dart';
-class A implements N {}''');
-    addNamedSource("/lib1.dart", r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
 class N {}''');
-    addNamedSource("/lib2.dart", r'''
+    newFile("/test/lib/lib2.dart", content: '''
 library lib2;
 class N {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.AMBIGUOUS_IMPORT,
-      CompileTimeErrorCode.IMPLEMENTS_NON_CLASS
+    await assertErrorsInCode('''
+import 'lib1.dart';
+import 'lib2.dart';
+class A implements N {}''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_NON_CLASS, 59, 1),
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 59, 1),
     ]);
   }
 
   test_ambiguousImport_inPart() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class N {}
+''');
+    newFile("/test/lib/lib2.dart", content: '''
+library lib2;
+class N {}
+''');
+    newFile('/test/lib/part.dart', content: '''
+part of lib;
+class A extends N {}
+''');
+    newFile('/test/lib/lib.dart', content: '''
 library lib;
 import 'lib1.dart';
 import 'lib2.dart';
-part 'part.dart';''');
-    addNamedSource("/lib1.dart", r'''
-library lib1;
-class N {}''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
-class N {}''');
-    Source partSource = addNamedSource("/part.dart", r'''
-part of lib;
-class A extends N {}''');
-    await computeAnalysisResult(source);
-    await computeAnalysisResult(partSource);
-    assertNoErrors(source);
-    assertErrors(partSource, [
-      StaticWarningCode.AMBIGUOUS_IMPORT,
-      CompileTimeErrorCode.EXTENDS_NON_CLASS
-    ]);
+part 'part.dart';
+''');
+    ResolvedUnitResult libResult =
+        await resolveFile(convertPath('/test/lib/lib.dart'));
+    ResolvedUnitResult partResult =
+        await resolveFile(convertPath('/test/lib/part.dart'));
+    expect(libResult.errors, hasLength(0));
+    new GatheringErrorListener()
+      ..addAll(partResult.errors)
+      ..assertErrors([
+        error(StaticWarningCode.AMBIGUOUS_IMPORT, 29, 1),
+        error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 29, 1),
+      ]);
   }
 
   test_ambiguousImport_instanceCreation() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class N {}''');
+    newFile("/test/lib/lib2.dart", content: '''
+library lib2;
+class N {}''');
+    await assertErrorsInCode('''
 library L;
 import 'lib1.dart';
 import 'lib2.dart';
-f() {new N();}''');
-    addNamedSource("/lib1.dart", r'''
-library lib1;
-class N {}''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
-class N {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
+f() {new N();}''', [
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 60, 1),
+    ]);
   }
 
   test_ambiguousImport_is() async {
-    Source source = addSource(r'''
-import 'lib1.dart';
-import 'lib2.dart';
-f(p) {p is N;}''');
-    addNamedSource("/lib1.dart", r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
 class N {}''');
-    addNamedSource("/lib2.dart", r'''
+    newFile("/test/lib/lib2.dart", content: '''
 library lib2;
 class N {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
+    await assertErrorsInCode('''
+import 'lib1.dart';
+import 'lib2.dart';
+f(p) {p is N;}''', [
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 51, 1),
+    ]);
   }
 
   test_ambiguousImport_qualifier() async {
-    Source source = addSource(r'''
-import 'lib1.dart';
-import 'lib2.dart';
-g() { N.FOO; }''');
-    addNamedSource("/lib1.dart", r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
 class N {}''');
-    addNamedSource("/lib2.dart", r'''
+    newFile("/test/lib/lib2.dart", content: '''
 library lib2;
 class N {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
+    await assertErrorsInCode('''
+import 'lib1.dart';
+import 'lib2.dart';
+g() { N.FOO; }''', [
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 46, 1),
+    ]);
   }
 
   test_ambiguousImport_typeAnnotation() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class N {}''');
+    newFile("/test/lib/lib2.dart", content: '''
+library lib2;
+class N {}''');
+    await assertErrorsInCode('''
 import 'lib1.dart';
 import 'lib2.dart';
 typedef N FT(N p);
@@ -163,167 +173,152 @@
 class A {
   N m() { return null; }
 }
-class B<T extends N> {}''');
-    addNamedSource("/lib1.dart", r'''
-library lib1;
-class N {}''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
-class N {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.AMBIGUOUS_IMPORT,
-      StaticWarningCode.AMBIGUOUS_IMPORT,
-      StaticWarningCode.AMBIGUOUS_IMPORT,
-      StaticWarningCode.AMBIGUOUS_IMPORT,
-      StaticWarningCode.AMBIGUOUS_IMPORT,
-      StaticWarningCode.AMBIGUOUS_IMPORT,
-      StaticWarningCode.AMBIGUOUS_IMPORT
+class B<T extends N> {}''', [
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 48, 1),
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 53, 1),
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 59, 1),
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 63, 1),
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 72, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 74, 1),
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 106, 1),
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 149, 1),
     ]);
   }
 
   test_ambiguousImport_typeArgument_annotation() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class N {}''');
+    newFile("/test/lib/lib2.dart", content: '''
+library lib2;
+class N {}''');
+    await assertErrorsInCode('''
 import 'lib1.dart';
 import 'lib2.dart';
 class A<T> {}
-A<N> f() { return null; }''');
-    addNamedSource("/lib1.dart", r'''
-library lib1;
-class N {}''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
-class N {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
+A<N> f() { return null; }''', [
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 56, 1),
+    ]);
   }
 
   test_ambiguousImport_typeArgument_instanceCreation() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class N {}''');
+    newFile("/test/lib/lib2.dart", content: '''
+library lib2;
+class N {}''');
+    await assertErrorsInCode('''
 import 'lib1.dart';
 import 'lib2.dart';
 class A<T> {}
-f() {new A<N>();}''');
-    addNamedSource("/lib1.dart", r'''
-library lib1;
-class N {}''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
-class N {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
+f() {new A<N>();}''', [
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 65, 1),
+    ]);
   }
 
   test_ambiguousImport_varRead() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+var v;''');
+    newFile("/test/lib/lib2.dart", content: '''
+library lib2;
+var v;''');
+    await assertErrorsInCode('''
 import 'lib1.dart';
 import 'lib2.dart';
 f() { g(v); }
-g(p) {}''');
-    addNamedSource("/lib1.dart", r'''
-library lib1;
-var v;''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
-var v;''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
+g(p) {}''', [
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 48, 1),
+    ]);
   }
 
   test_ambiguousImport_varWrite() async {
-    Source source = addSource(r'''
-import 'lib1.dart';
-import 'lib2.dart';
-f() { v = 0; }''');
-    addNamedSource("/lib1.dart", r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
 var v;''');
-    addNamedSource("/lib2.dart", r'''
+    newFile("/test/lib/lib2.dart", content: '''
 library lib2;
 var v;''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
+    await assertErrorsInCode('''
+import 'lib1.dart';
+import 'lib2.dart';
+f() { v = 0; }''', [
+      error(StaticWarningCode.AMBIGUOUS_IMPORT, 46, 1),
+    ]);
   }
 
   test_argumentTypeNotAssignable_ambiguousClassName() async {
     // See dartbug.com/19624
-    Source source = addNamedSource("/lib1.dart", r'''
-library lib1;
+    newFile("/test/lib/lib2.dart", content: '''
+class _A {}
+g(h(_A a)) {}''');
+    await assertErrorsInCode('''
 import 'lib2.dart';
 class _A {}
 f() {
   g((_A a) {});
-}''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
-class _A {}
-g(h(_A a)) {}''');
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 42, 9),
+    ]);
     // The name _A is private to the library it's defined in, so this is a type
     // mismatch. Furthermore, the error message should mention both _A and the
     // filenames so the user can figure out what's going on.
-    TestAnalysisResult analysisResult = await computeAnalysisResult(source);
-    List<AnalysisError> errors = analysisResult.errors;
-    expect(errors, hasLength(1));
-    AnalysisError error = errors[0];
-    expect(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, error.errorCode);
-    String message = error.message;
-    expect(message.indexOf("_A") != -1, isTrue);
+    String message = result.errors[0].message;
+    expect(message.indexOf("_A") >= 0, isTrue);
   }
 
   test_argumentTypeNotAssignable_annotation_namedConstructor() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   const A.fromInt(int p);
 }
 @A.fromInt('0')
 main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 49, 3),
+    ]);
   }
 
   test_argumentTypeNotAssignable_annotation_unnamedConstructor() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   const A(int p);
 }
 @A('0')
 main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 33, 3),
+    ]);
   }
 
   test_argumentTypeNotAssignable_binary() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   operator +(int p) {}
 }
 f(A a) {
   a + '0';
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 50, 3),
+    ]);
   }
 
   test_argumentTypeNotAssignable_call() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 typedef bool Predicate<T>(T object);
 
 Predicate<String> f() => null;
 
 void main() {
   f().call(3);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 95, 1),
+    ]);
   }
 
   test_argumentTypeNotAssignable_cascadeSecond() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 // filler filler filler filler filler filler filler filler filler filler
 class A {
   B ma() { return new B(); }
@@ -335,248 +330,229 @@
 main() {
   A a = new A();
   a..  ma().mb(0);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 186, 1),
+    ]);
   }
 
   test_argumentTypeNotAssignable_const() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   const A(String p);
 }
 main() {
   const A(42);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
+}''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          52,
+          2),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 52, 2),
     ]);
-    verify([source]);
   }
 
   test_argumentTypeNotAssignable_const_super() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   const A(String p);
 }
 class B extends A {
   const B() : super(42);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 73, 2),
+    ]);
   }
 
   test_argumentTypeNotAssignable_functionExpressionInvocation_required() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 main() {
   (int x) {} ('');
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 23, 2),
+    ]);
   }
 
   test_argumentTypeNotAssignable_index() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   operator [](int index) {}
 }
 f(A a) {
   a['0'];
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 53, 3),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_callParameter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   call(int p) {}
 }
 f(A a) {
   a('0');
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 42, 3),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_callVariable() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   call(int p) {}
 }
 main() {
   A a = new A();
   a('0');
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 59, 3),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_functionParameter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 a(b(int p)) {
   b('0');
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 18, 3),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_functionParameter_generic() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A<K, V> {
   m(f(K k), V v) {
     f(v);
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 41, 1),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_functionTypes_optional() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void acceptFunNumOptBool(void funNumOptBool([bool b])) {}
 void funNumBool(bool b) {}
 main() {
   acceptFunNumOptBool(funNumBool);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.INVALID_CAST_FUNCTION]);
-    verify([source]);
+}''', [
+      error(StrongModeCode.INVALID_CAST_FUNCTION, 116, 10),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_generic() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A<T> {
   m(T t) {}
 }
 f(A<String> a) {
   a.m(1);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 50, 1),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_named() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f({String p}) {}
 main() {
   f(p: 42);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 30, 5),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_optional() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f([String p]) {}
 main() {
   f(42);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 30, 2),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_required() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f(String p) {}
 main() {
   f(42);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 28, 2),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_typedef_generic() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 typedef A<T>(T p);
 f(A<int> a) {
   a('1');
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 37, 3),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_typedef_local() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 typedef A(int p);
 A getA() => null;
 main() {
   A a = getA();
   a('1');
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 65, 3),
+    ]);
   }
 
   test_argumentTypeNotAssignable_invocation_typedef_parameter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 typedef A(int p);
 f(A a) {
   a('1');
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 31, 3),
+    ]);
   }
 
   test_argumentTypeNotAssignable_new_generic() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A<T> {
   A(T p) {}
 }
 main() {
   new A<String>(42);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 52, 2),
+    ]);
   }
 
   test_argumentTypeNotAssignable_new_optional() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   A([String p]) {}
 }
 main() {
   new A(42);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 48, 2),
+    ]);
   }
 
   test_argumentTypeNotAssignable_new_required() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   A(String p) {}
 }
 main() {
   new A(42);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 46, 2),
+    ]);
   }
 
   @failingTest
   test_argumentTypeNotAssignable_tearOff_required() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class C {
   Object/*=T*/ f/*<T>*/(Object/*=T*/ x) => x;
 }
@@ -584,233 +560,225 @@
   var h = c.f/*<int>*/;
   print(h('s'));
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
+''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 99, 1),
+    ]);
   }
 
   test_assignmentToClass() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 class C {}
 main() {
   C = null;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
+''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_TYPE, 22, 1),
+    ]);
   }
 
   test_assignmentToConst_instanceVariable() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   static const v = 0;
 }
 f() {
   A.v = 1;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_CONST]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_CONST, 42, 3),
+    ]);
   }
 
   test_assignmentToConst_instanceVariable_plusEq() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   static const v = 0;
 }
 f() {
   A.v += 1;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_CONST]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_CONST, 42, 3),
+    ]);
   }
 
   test_assignmentToConst_localVariable() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   const x = 0;
   x = 1;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_CONST]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(StaticWarningCode.ASSIGNMENT_TO_CONST, 23, 1),
+    ]);
   }
 
   test_assignmentToConst_localVariable_plusEq() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   const x = 0;
   x += 1;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_CONST]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(StaticWarningCode.ASSIGNMENT_TO_CONST, 23, 1),
+    ]);
   }
 
   test_assignmentToEnumType() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 enum E { e }
 main() {
   E = null;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
+''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_TYPE, 24, 1),
+    ]);
   }
 
   test_assignmentToFinal_instanceVariable() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   final v = 0;
 }
 f() {
   A a = new A();
   a.v = 1;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL, 54, 1),
+    ]);
   }
 
   test_assignmentToFinal_instanceVariable_plusEq() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   final v = 0;
 }
 f() {
   A a = new A();
   a.v += 1;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL, 54, 1),
+    ]);
   }
 
   test_assignmentToFinalLocal_localVariable() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   final x = 0;
   x = 1;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL, 23, 1),
+    ]);
   }
 
   test_assignmentToFinalLocal_localVariable_plusEq() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   final x = 0;
   x += 1;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL, 23, 1),
+    ]);
   }
 
   test_assignmentToFinalLocal_parameter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f(final x) {
   x = 1;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL, 15, 1),
+    ]);
   }
 
   test_assignmentToFinalLocal_postfixMinusMinus() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   final x = 0;
   x--;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL, 23, 1),
+    ]);
   }
 
   test_assignmentToFinalLocal_postfixPlusPlus() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   final x = 0;
   x++;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL, 23, 1),
+    ]);
   }
 
   test_assignmentToFinalLocal_prefixMinusMinus() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   final x = 0;
   --x;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL, 25, 1),
+    ]);
   }
 
   test_assignmentToFinalLocal_prefixPlusPlus() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   final x = 0;
   ++x;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL, 25, 1),
+    ]);
   }
 
   test_assignmentToFinalLocal_suffixMinusMinus() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   final x = 0;
   x--;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL, 23, 1),
+    ]);
   }
 
   test_assignmentToFinalLocal_suffixPlusPlus() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   final x = 0;
   x++;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL, 23, 1),
+    ]);
   }
 
   test_assignmentToFinalLocal_topLevelVariable() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 final x = 0;
-f() { x = 1; }''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
-    verify([source]);
+f() { x = 1; }''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL, 19, 1),
+    ]);
   }
 
   test_assignmentToFinalNoSetter_prefixedIdentifier() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int get x => 0;
 }
 main() {
   A a = new A();
   a.x = 0;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER, 60, 1),
+    ]);
   }
 
   test_assignmentToFinalNoSetter_propertyAccess() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int get x => 0;
 }
@@ -819,61 +787,58 @@
 }
 main() {
   B.a.x = 0;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER, 71, 1),
+    ]);
   }
 
   test_assignmentToFunction() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {}
 main() {
   f = null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FUNCTION]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_FUNCTION, 18, 1),
+    ]);
   }
 
   test_assignmentToMethod() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m() {}
 }
 f(A a) {
   a.m = () {};
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_METHOD]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_METHOD, 32, 3),
+    ]);
   }
 
   test_assignmentToTypedef() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 typedef void F();
 main() {
   F = null;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
+''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_TYPE, 29, 1),
+    ]);
   }
 
   test_assignmentToTypeParameter() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 class C<T> {
   f() {
     T = null;
   }
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
+''', [
+      error(StaticWarningCode.ASSIGNMENT_TO_TYPE, 25, 1),
+    ]);
   }
 
   test_caseBlockNotTerminated() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f(int p) {
   switch (p) {
     case 0:
@@ -881,70 +846,65 @@
     case 1:
       break;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.CASE_BLOCK_NOT_TERMINATED]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.CASE_BLOCK_NOT_TERMINATED, 30, 4),
+    ]);
   }
 
   test_castToNonType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 var A = 0;
-f(String s) { var x = s as A; }''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.CAST_TO_NON_TYPE]);
-    verify([source]);
+f(String s) { var x = s as A; }''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 29, 1),
+      error(StaticWarningCode.CAST_TO_NON_TYPE, 38, 1),
+    ]);
   }
 
   test_concreteClassWithAbstractMember() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER, 12, 4),
+    ]);
   }
 
   test_concreteClassWithAbstractMember_noSuchMethod_interface() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class I {
   noSuchMethod(v) => '';
 }
 class A implements I {
   m();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER, 62, 4),
+    ]);
   }
 
   test_constWithAbstractClass() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {
   const A();
 }
 void f() {
   A a = const A();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.CONST_WITH_ABSTRACT_CLASS]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 49, 1),
+      error(StaticWarningCode.CONST_WITH_ABSTRACT_CLASS, 59, 1),
+    ]);
   }
 
   test_constWithAbstractClass_generic() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A<E> {
   const A();
 }
 void f() {
   var a = const A<int>();
-}''');
-    TestAnalysisResult result = await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.CONST_WITH_ABSTRACT_CLASS]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 54, 1),
+      error(StaticWarningCode.CONST_WITH_ABSTRACT_CLASS, 64, 6),
+    ]);
 
     ClassDeclaration classA = result.unit.declarations[0];
     FunctionDeclaration f = result.unit.declarations[1];
@@ -956,96 +916,85 @@
   }
 
   test_exportDuplicatedLibraryNamed() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: "library lib;");
+    newFile("/test/lib/lib2.dart", content: "library lib;");
+    await assertErrorsInCode('''
 library test;
 export 'lib1.dart';
-export 'lib2.dart';''');
-    addNamedSource("/lib1.dart", "library lib;");
-    addNamedSource("/lib2.dart", "library lib;");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.EXPORT_DUPLICATED_LIBRARY_NAMED]);
-    verify([source]);
+export 'lib2.dart';''', [
+      error(StaticWarningCode.EXPORT_DUPLICATED_LIBRARY_NAMED, 34, 19),
+    ]);
   }
 
   test_extraPositionalArguments() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {}
 main() {
   f(0, 1, '2');
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS, 19, 11),
+    ]);
   }
 
   test_extraPositionalArguments_functionExpression() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 main() {
   (int x) {} (0, 1);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS, 22, 6),
+    ]);
   }
 
   test_extraPositionalArgumentsCouldBeNamed() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f({x, y}) {}
 main() {
   f(0, 1, '2');
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED]);
-    verify([source]);
+}''', [
+      error(
+          StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 25, 11),
+    ]);
   }
 
   test_extraPositionalArgumentsCouldBeNamed_functionExpression() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 main() {
   (int x, {int y}) {} (0, 1);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 31, 6),
+    ]);
   }
 
   test_fieldInitializedInInitializerAndDeclaration_final() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   final int x = 0;
   A() : x = 1 {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION,
+          37, 1),
+    ]);
   }
 
   test_fieldInitializerNotAssignable() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int x;
   A() : x = '';
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, 31, 2),
+    ]);
   }
 
   test_fieldInitializingFormalNotAssignable() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int x;
   A(String this.x) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE,
-      StrongModeCode.INVALID_PARAMETER_DECLARATION
+}''', [
+      error(StrongModeCode.INVALID_PARAMETER_DECLARATION, 23, 13),
+      error(StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE, 23, 13),
     ]);
-    verify([source]);
   }
 
   /**
@@ -1058,765 +1007,706 @@
    * the broader code
    */
   test_finalInitializedInDeclarationAndConstructor_initializers() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   final x = 0;
   A() : x = 0 {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION,
+          33, 1),
+    ]);
   }
 
   test_finalInitializedInDeclarationAndConstructor_initializingFormal() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   final x = 0;
   A(this.x) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR,
+          34, 1),
+    ]);
   }
 
   test_finalNotInitialized_inConstructor_1() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   final int x;
   A() {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1, 27, 1),
+    ]);
   }
 
   test_finalNotInitialized_inConstructor_2() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   final int a;
   final int b;
   A() {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2, 42, 1),
+    ]);
   }
 
   test_finalNotInitialized_inConstructor_3() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   final int a;
   final int b;
   final int c;
   A() {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS, 57, 1),
+    ]);
   }
 
   test_finalNotInitialized_instanceField_final() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   final F;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FINAL_NOT_INITIALIZED]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.FINAL_NOT_INITIALIZED, 18, 1),
+    ]);
   }
 
   test_finalNotInitialized_instanceField_final_static() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   static final F;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FINAL_NOT_INITIALIZED]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.FINAL_NOT_INITIALIZED, 25, 1),
+    ]);
   }
 
   test_finalNotInitialized_library_final() async {
-    Source source = addSource("final F;");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FINAL_NOT_INITIALIZED]);
-    verify([source]);
+    await assertErrorsInCode('''
+final F;
+''', [
+      error(StaticWarningCode.FINAL_NOT_INITIALIZED, 6, 1),
+    ]);
   }
 
   test_finalNotInitialized_local_final() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   final int x;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FINAL_NOT_INITIALIZED]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 18, 1),
+      error(StaticWarningCode.FINAL_NOT_INITIALIZED, 18, 1),
+    ]);
   }
 
   test_functionWithoutCall_direct() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 class A implements Function {
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_functionWithoutCall_direct_typeAlias() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 class M {}
 class A = Object with M implements Function;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_functionWithoutCall_indirect_extends() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 abstract class A implements Function {
 }
 class B extends A {
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_functionWithoutCall_indirect_extends_typeAlias() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 abstract class A implements Function {}
 class M {}
 class B = A with M;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_functionWithoutCall_indirect_implements() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 abstract class A implements Function {
 }
 class B implements A {
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_functionWithoutCall_indirect_implements_typeAlias() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 abstract class A implements Function {}
 class M {}
 class B = Object with M implements A;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_functionWithoutCall_mixin_implements() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 abstract class A implements Function {}
 class B extends Object with A {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_functionWithoutCall_mixin_implements_typeAlias() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 abstract class A implements Function {}
 class B = Object with A;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_generalizedVoid_andVoidLhsError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   x && true;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 26, 1),
+    ]);
   }
 
   test_generalizedVoid_andVoidRhsError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   true && x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 34, 1),
+    ]);
   }
 
   test_generalizedVoid_assignmentToVoidParameterOk() async {
     // Note: the spec may decide to disallow this, but at this point that seems
     // highly unlikely.
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void main() {
   void x;
   f(x);
 }
 void f(void x) {}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_generalizedVoid_assignToVoid_notStrong_error() async {
     // See StrongModeStaticTypeAnalyzer2Test.test_generalizedVoid_assignToVoidOk
     // for testing that this does not have errors in strong mode.
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void main() {
   void x;
   x = 42;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_generalizedVoid_interpolateVoidValueError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode(r'''
 void main() {
   void x;
   "$x";
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 28, 1),
+    ]);
   }
 
   test_generalizedVoid_negateVoidValueError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   !x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 21, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 27, 1),
+    ]);
   }
 
   test_generalizedVoid_orVoidLhsError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   x || true;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 26, 1),
+    ]);
   }
 
   test_generalizedVoid_orVoidRhsError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   false || x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 35, 1),
+    ]);
   }
 
   test_generalizedVoid_throwVoidValueError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   throw x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 32, 1),
+    ]);
   }
 
   test_generalizedVoid_unaryNegativeVoidValueError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   -x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.USE_OF_VOID_RESULT,
+''', [
       // TODO(mfairhurst) suppress UNDEFINED_OPERATOR
-      StaticTypeWarningCode.UNDEFINED_OPERATOR
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 21, 1),
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 26, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 27, 1),
     ]);
   }
 
   test_generalizedVoid_useOfInForeachIterableError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   for (var v in x) {}
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 35, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 40, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidAsIndexAssignError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main(List list) {
   void x;
   list[x] = null;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 40, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidAsIndexError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main(List list) {
   void x;
   list[x];
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 40, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidAssignedToDynamicError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   dynamic z = x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 34, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 38, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidByIndexingError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   x[0];
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 27, 3),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidCallSetterError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   x.foo = null;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 28, 3),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidCastsOk() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void use(dynamic x) { }
 void main() {
   void x;
   use(x as int);
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_generalizedVoid_useOfVoidInConditionalConditionError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   x ? null : null;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 26, 1),
+    ]);
   }
 
   @failingTest
   test_generalizedVoid_useOfVoidInConditionalLhsError() async {
     // TODO(mfairhurst) Enable this.
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main(bool c) {
   void x;
   c ? x : null;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 36, 1),
+    ]);
   }
 
   @failingTest
   test_generalizedVoid_useOfVoidInConditionalRhsError() async {
     // TODO(mfairhurst) Enable this.
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main(bool c) {
   void x;
   c ? null : x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 43, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInDoWhileConditionError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   do {} while (x);
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 39, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInExpStmtOk() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void main() {
   void x;
   x;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   @failingTest // This test may be completely invalid.
   test_generalizedVoid_useOfVoidInForeachVariableError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   for (x in [1, 2]) {}
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 31, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInForPartsOk() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void main() {
   void x;
   for (x; false; x) {}
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_generalizedVoid_useOfVoidInIsTestError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   x is int;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 26, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInListLiteralError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   <dynamic>[x];
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 36, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInListLiteralOk() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void main() {
   void x;
   <void>[x]; // not strong mode; we have to specify <void>.
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_generalizedVoid_useOfVoidInMapLiteralKeyError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   var m2 = <dynamic, int>{x : 4};
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 30, 2),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 50, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInMapLiteralKeyOk() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void main() {
   void x;
   var m2 = <void, int>{x : 4}; // not strong mode; we have to specify <void>.
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_generalizedVoid_useOfVoidInMapLiteralValueError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   var m1 = <int, dynamic>{4: x};
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 30, 2),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 53, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInMapLiteralValueOk() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void main() {
   void x;
   var m1 = <int, void>{4: x}; // not strong mode; we have to specify <void>.
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_generalizedVoid_useOfVoidInNullOperatorLhsError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   x ?? 499;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 26, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInNullOperatorRhsOk() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void main() {
   void x;
   null ?? x;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_generalizedVoid_useOfVoidInSpecialAssignmentError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   x += 1;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 21, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 28, 2),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInSwitchExpressionError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   switch(x) {}
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 33, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInWhileConditionError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   while (x) {};
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 33, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidNullPropertyAccessError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   x?.foo;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 29, 3),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidPropertyAccessError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void main() {
   void x;
   x.foo;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 28, 3),
+    ]);
   }
 
   @failingTest
   test_generalizedVoid_useOfVoidReturnInNonVoidFunctionError() async {
     // TODO(mfairhurst) Get this test to pass once codebase is compliant.
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 dynamic main() {
   void x;
   return x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+''', [
+      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 36, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidReturnInVoidFunctionOk() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void main() {
   void x;
   return x;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_generalizedVoid_useOfVoidWhenArgumentError() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void use(dynamic x) { }
 void main() {
   void x;
   use(x);
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 54, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidWithInitializerOk() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void main() {
   void x;
   void y = x;
 }
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_generalizedVoid_yieldStarVoid_asyncStar() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 main(void x) async* {
   yield* x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 31, 1),
+    ]);
   }
 
   test_generalizedVoid_yieldStarVoid_syncStar() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 main(void x) sync* {
   yield* x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 30, 1),
+    ]);
   }
 
   test_generalizedVoid_yieldVoid_asyncStar() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 main(void x) async* {
   yield x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 30, 1),
+    ]);
   }
 
   test_generalizedVoid_yieldVoid_syncStar() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 main(void x) sync* {
   yield x;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 29, 1),
+    ]);
   }
 
   test_importDuplicatedLibraryNamed() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/lib1.dart", content: "library lib;");
+    newFile("/test/lib/lib2.dart", content: "library lib;");
+    assertErrorsInCode('''
 library test;
 import 'lib1.dart';
-import 'lib2.dart';''');
-    addNamedSource("/lib1.dart", "library lib;");
-    addNamedSource("/lib2.dart", "library lib;");
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.IMPORT_DUPLICATED_LIBRARY_NAMED,
-      HintCode.UNUSED_IMPORT,
-      HintCode.UNUSED_IMPORT
+import 'lib2.dart';''', [
+      error(HintCode.UNUSED_IMPORT, 21, 11),
+      error(StaticWarningCode.IMPORT_DUPLICATED_LIBRARY_NAMED, 34, 19),
+      error(HintCode.UNUSED_IMPORT, 41, 11),
     ]);
-    verify([source]);
   }
 
   test_importOfNonLibrary() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 part of lib;
-class A {}''',
-      r'''
+class A {}''');
+    assertErrorsInCode('''
 library lib;
 import 'lib1.dart' deferred as p;
-var a = new p.A();'''
-    ], <ErrorCode>[
-      StaticWarningCode.IMPORT_OF_NON_LIBRARY
+var a = new p.A();''', [
+      error(StaticWarningCode.IMPORT_OF_NON_LIBRARY, 20, 11),
     ]);
   }
 
   test_invalidGetterOverrideReturnType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int get g { return 0; }
 }
 class B extends A {
   String get g { return 'a'; }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 60, 28),
+    ]);
   }
 
   test_invalidGetterOverrideReturnType_implicit() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   String f;
 }
 class B extends A {
   int f;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INVALID_OVERRIDE,
-      CompileTimeErrorCode.INVALID_OVERRIDE
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 46, 5),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 46, 5),
     ]);
-    verify([source]);
   }
 
   test_invalidGetterOverrideReturnType_twoInterfaces() async {
     // test from language/override_inheritance_field_test_11.dart
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class I {
   int get getter => null;
 }
@@ -1826,17 +1716,14 @@
 abstract class A implements I, J {}
 class B extends A {
   String get getter => null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INVALID_OVERRIDE,
-      CompileTimeErrorCode.INVALID_OVERRIDE,
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 152, 26),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 152, 26),
     ]);
-    verify([source]);
   }
 
   test_invalidGetterOverrideReturnType_twoInterfaces_conflicting() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class I<U> {
   U get g => null;
 }
@@ -1845,56 +1732,50 @@
 }
 class B implements I<int>, J<String> {
   double get g => null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INVALID_OVERRIDE,
-      CompileTimeErrorCode.INVALID_OVERRIDE
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 127, 21),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 127, 21),
     ]);
-    verify([source]);
   }
 
   test_invalidMethodOverrideNamedParamType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m({int a}) {}
 }
 class B implements A {
   m({String a}) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 16),
+    ]);
   }
 
   test_invalidMethodOverrideNormalParamType_interface() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m(int a) {}
 }
 class B implements A {
   m(String a) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 51, 14),
+    ]);
   }
 
   test_invalidMethodOverrideNormalParamType_superclass() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m(int a) {}
 }
 class B extends A {
   m(String a) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 48, 14),
+    ]);
   }
 
   test_invalidMethodOverrideNormalParamType_superclass_interface() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class I<U> {
   m(U u) => null;
 }
@@ -1903,17 +1784,14 @@
 }
 class B extends I<int> implements J<String> {
   m(double d) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INVALID_OVERRIDE,
-      CompileTimeErrorCode.INVALID_OVERRIDE
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 132, 14),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 132, 14),
     ]);
-    verify([source]);
   }
 
   test_invalidMethodOverrideNormalParamType_twoInterfaces() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class I {
   m(int n);
 }
@@ -1923,18 +1801,15 @@
 abstract class A implements I, J {}
 class B extends A {
   m(String n) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INVALID_OVERRIDE,
-      CompileTimeErrorCode.INVALID_OVERRIDE
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 14),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 14),
     ]);
-    verify([source]);
   }
 
   test_invalidMethodOverrideNormalParamType_twoInterfaces_conflicting() async {
     // language/override_inheritance_generic_test/08
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class I<U> {
   m(U u) => null;
 }
@@ -1943,30 +1818,26 @@
 }
 class B implements I<int>, J<String> {
   m(double d) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INVALID_OVERRIDE,
-      CompileTimeErrorCode.INVALID_OVERRIDE
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 14),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 14),
     ]);
-    verify([source]);
   }
 
   test_invalidMethodOverrideOptionalParamType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m([int a]) {}
 }
 class B implements A {
   m([String a]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 16),
+    ]);
   }
 
   test_invalidMethodOverrideOptionalParamType_twoInterfaces() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class I {
   m([int n]);
 }
@@ -1976,30 +1847,26 @@
 abstract class A implements I, J {}
 class B extends A {
   m([String n]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INVALID_OVERRIDE,
-      CompileTimeErrorCode.INVALID_OVERRIDE
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 128, 16),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 128, 16),
     ]);
-    verify([source]);
   }
 
   test_invalidMethodOverrideReturnType_interface() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int m() { return 0; }
 }
 class B implements A {
   String m() { return 'a'; }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 61, 26),
+    ]);
   }
 
   test_invalidMethodOverrideReturnType_interface_grandparent() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {
   int m();
 }
@@ -2007,40 +1874,37 @@
 }
 class C implements B {
   String m() { return 'a'; }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 91, 26),
+    ]);
   }
 
   test_invalidMethodOverrideReturnType_mixin() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int m() { return 0; }
 }
 class B extends Object with A {
   String m() { return 'a'; }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 70, 26),
+    ]);
   }
 
   test_invalidMethodOverrideReturnType_superclass() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int m() { return 0; }
 }
 class B extends A {
   String m() { return 'a'; }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 58, 26),
+    ]);
   }
 
   test_invalidMethodOverrideReturnType_superclass_grandparent() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int m() { return 0; }
 }
@@ -2048,14 +1912,13 @@
 }
 class C extends B {
   String m() { return 'a'; }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 80, 26),
+    ]);
   }
 
   test_invalidMethodOverrideReturnType_twoInterfaces() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class I {
   int m();
 }
@@ -2065,121 +1928,110 @@
 abstract class A implements I, J {}
 class B extends A {
   String m() => '';
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INVALID_OVERRIDE,
-      CompileTimeErrorCode.INVALID_OVERRIDE
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 122, 17),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 122, 17),
     ]);
-    verify([source]);
   }
 
   test_invalidMethodOverrideReturnType_void() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int m() { return 0; }
 }
 class B extends A {
   void m() {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 58, 11),
+    ]);
   }
 
   test_invalidOverrideNamed_fewerNamedParameters() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m({a, b}) {}
 }
 class B extends A {
   m({a}) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 9),
+    ]);
   }
 
   test_invalidOverrideNamed_missingNamedParameter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m({a, b}) {}
 }
 class B extends A {
   m({a, c}) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 12),
+    ]);
   }
 
   test_invalidOverridePositional_optional() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m([a, b]) {}
 }
 class B extends A {
   m([a]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 9),
+    ]);
   }
 
   test_invalidOverridePositional_optionalAndRequired() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m(a, b, [c, d]) {}
 }
 class B extends A {
   m(a, b, [c]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 55, 15),
+    ]);
   }
 
   test_invalidOverridePositional_optionalAndRequired2() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m(a, b, [c, d]) {}
 }
 class B extends A {
   m(a, [c, d]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 55, 15),
+    ]);
   }
 
   test_invalidOverrideRequired() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m(a) {}
 }
 class B extends A {
   m(a, b) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 44, 10),
+    ]);
   }
 
   test_invalidSetterOverrideNormalParamType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   void set s(int v) {}
 }
 class B extends A {
   void set s(String v) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 57, 23),
+    ]);
   }
 
   test_invalidSetterOverrideNormalParamType_superclass_interface() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class I {
   set setter14(int _) => null;
 }
@@ -2189,18 +2041,15 @@
 abstract class A extends I implements J {}
 class B extends A {
   set setter14(String _) => null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INVALID_OVERRIDE,
-      CompileTimeErrorCode.INVALID_OVERRIDE,
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 169, 31),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 169, 31),
     ]);
-    verify([source]);
   }
 
   test_invalidSetterOverrideNormalParamType_twoInterfaces() async {
     // test from language/override_inheritance_field_test_34.dart
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class I {
   set setter14(int _) => null;
 }
@@ -2210,17 +2059,14 @@
 abstract class A implements I, J {}
 class B extends A {
   set setter14(String _) => null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INVALID_OVERRIDE,
-      CompileTimeErrorCode.INVALID_OVERRIDE
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 162, 31),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 162, 31),
     ]);
-    verify([source]);
   }
 
   test_invalidSetterOverrideNormalParamType_twoInterfaces_conflicting() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class I<U> {
   set s(U u) {}
 }
@@ -2229,27 +2075,22 @@
 }
 class B implements I<int>, J<String> {
   set s(double d) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INVALID_OVERRIDE,
-      CompileTimeErrorCode.INVALID_OVERRIDE
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 121, 18),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 121, 18),
     ]);
-    verify([source]);
   }
 
   test_mismatchedAccessorTypes_topLevel() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 int get g { return 0; }
-set g(String v) {}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]);
-    verify([source]);
+set g(String v) {}''', [
+      error(StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES, 0, 23),
+    ]);
   }
 
   test_missingEnumConstantInSwitch() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 enum E { ONE, TWO, THREE, FOUR }
 bool odd(E e) {
   switch (e) {
@@ -2257,17 +2098,14 @@
     case E.THREE: return true;
   }
   return false;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
-      StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH
+}''', [
+      error(StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, 51, 10),
+      error(StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, 51, 10),
     ]);
-    verify([source]);
   }
 
   test_mixedReturnTypes_localFunction() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class C {
   m(int x) {
     return (int y) {
@@ -2277,14 +2115,13 @@
       return 0;
     };
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.RETURN_WITHOUT_VALUE, 71, 7),
+    ]);
   }
 
   test_mixedReturnTypes_method() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class C {
   m(int x) {
     if (x < 0) {
@@ -2292,51 +2129,45 @@
     }
     return 0;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.MIXED_RETURN_TYPES,
-      StaticWarningCode.MIXED_RETURN_TYPES
+}''', [
+      error(StaticWarningCode.MIXED_RETURN_TYPES, 46, 6),
+      error(StaticWarningCode.MIXED_RETURN_TYPES, 64, 6),
     ]);
-    verify([source]);
   }
 
   test_mixedReturnTypes_topLevelFunction() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f(int x) {
   if (x < 0) {
     return;
   }
   return 0;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.MIXED_RETURN_TYPES,
-      StaticWarningCode.MIXED_RETURN_TYPES
+}''', [
+      error(StaticWarningCode.MIXED_RETURN_TYPES, 30, 6),
+      error(StaticWarningCode.MIXED_RETURN_TYPES, 44, 6),
     ]);
-    verify([source]);
   }
 
   test_newWithAbstractClass() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {}
 void f() {
   A a = new A();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NEW_WITH_ABSTRACT_CLASS]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 35, 1),
+      error(StaticWarningCode.NEW_WITH_ABSTRACT_CLASS, 43, 1),
+    ]);
   }
 
   test_newWithAbstractClass_generic() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A<E> {}
 void f() {
   var a = new A<int>();
-}''');
-    TestAnalysisResult result = await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NEW_WITH_ABSTRACT_CLASS]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 40, 1),
+      error(StaticWarningCode.NEW_WITH_ABSTRACT_CLASS, 48, 6),
+    ]);
 
     ClassDeclaration classA = result.unit.declarations[0];
     FunctionDeclaration f = result.unit.declarations[1];
@@ -2348,92 +2179,85 @@
   }
 
   test_newWithInvalidTypeParameters() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {}
-f() { return new A<A>(); }''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS]);
-    verify([source]);
+f() { return new A<A>(); }''', [
+      error(StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS, 28, 4),
+    ]);
   }
 
   test_newWithInvalidTypeParameters_tooFew() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {}
 class C<K, V> {}
 f(p) {
   return new C<A>();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS, 48, 4),
+    ]);
   }
 
   test_newWithInvalidTypeParameters_tooMany() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {}
 class C<E> {}
 f(p) {
   return new C<A, A>();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS, 45, 7),
+    ]);
   }
 
   test_newWithNonType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 var A = 0;
 void f() {
   var a = new A();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NEW_WITH_NON_TYPE]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 28, 1),
+      error(StaticWarningCode.NEW_WITH_NON_TYPE, 36, 1),
+    ]);
   }
 
   test_newWithNonType_fromLibrary() async {
-    Source source1 = addNamedSource("/lib.dart", "class B {}");
-    Source source2 = addNamedSource("/lib2.dart", r'''
+    newFile("/test/lib/lib.dart", content: "class B {}");
+    await assertErrorsInCode('''
 import 'lib.dart' as lib;
 void f() {
   var a = new lib.A();
 }
-lib.B b;''');
-    await computeAnalysisResult(source1);
-    await computeAnalysisResult(source2);
-    assertErrors(source2, [StaticWarningCode.NEW_WITH_NON_TYPE]);
-    verify([source1]);
+lib.B b;''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 43, 1),
+      error(StaticWarningCode.NEW_WITH_NON_TYPE, 55, 1),
+    ]);
   }
 
   test_newWithUndefinedConstructor() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   A() {}
 }
 f() {
   new A.name();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR]);
-    // no verify(), 'name' is not resolved
+}''', [
+      error(StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR, 35, 4),
+    ]);
   }
 
   test_newWithUndefinedConstructorDefault() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   A.name() {}
 }
 f() {
   new A();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, 38, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberFivePlus() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {
   m();
   n();
@@ -2442,16 +2266,17 @@
   q();
 }
 class C extends A {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS
+}''', [
+      error(
+          StaticWarningCode
+              .NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS,
+          62,
+          1),
     ]);
-    verify([source]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberFour() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {
   m();
   n();
@@ -2459,126 +2284,117 @@
   p();
 }
 class C extends A {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR,
+          55, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_classTypeAlias_interface() async {
     // 15979
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class M {}
 abstract class A {}
 abstract class I {
   m();
 }
-class B = A with M implements I;''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+class B = A with M implements I;''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          74, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_classTypeAlias_mixin() async {
     // 15979
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class M {
   m();
 }
 abstract class A {}
-class B = A with M;''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+class B = A with M;''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          54, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_classTypeAlias_superclass() async {
     // 15979
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class M {}
 abstract class A {
   m();
 }
-class B = A with M;''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+class B = A with M;''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          45, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_ensureCorrectFunctionSubtypeIsUsedInImplementation() async {
     // 15028
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class C {
   foo(int x) => x;
 }
 abstract class D {
   foo(x, [y]);
 }
-class E extends C implements D {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]);
-    verify([source]);
+class E extends C implements D {}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 73, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_getter_fromInterface() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class I {
   int get g {return 1;}
 }
 class C implements I {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          42, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_getter_fromSuperclass() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {
   int get g;
 }
 class C extends A {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          40, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_method_fromInterface() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class I {
   m(p) {}
 }
 class C implements I {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          28, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_method_fromInterface_abstractNSM() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class I {
   m(p) {}
 }
 class C implements I {
   noSuchMethod(v);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          28, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_method_fromInterface_abstractOverrideNSM() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 class I {
   m(p) {}
 }
@@ -2588,41 +2404,36 @@
 class C extends B implements I {
   noSuchMethod(v);
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_method_fromInterface_ifcNSM() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class I {
   m(p) {}
   noSuchMethod(v) => null;
 }
 class C implements I {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          55, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_method_fromSuperclass() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {
   m(p);
 }
 class C extends A {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          35, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_method_optionalParamCount() async {
     // 7640
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {
   int x(int a);
 }
@@ -2630,49 +2441,48 @@
   int x(int a, [int b]);
 }
 class C implements A, B {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          89, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_mixinInherits_getter() async {
     // 15001
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A { get g1; get g2; }
 abstract class B implements A { get g1 => 1; }
-class C extends Object with B {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
+class C extends Object with B {}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          90, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_mixinInherits_method() async {
     // 15001
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A { m1(); m2(); }
 abstract class B implements A { m1() => 1; }
-class C extends Object with B {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
+class C extends Object with B {}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          84, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_mixinInherits_setter() async {
     // 15001
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A { set s1(v); set s2(v); }
 abstract class B implements A { set s1(v) {} }
-class C extends Object with B {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
+class C extends Object with B {}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          96, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_noSuchMethod_interface() async {
     // 15979
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class I {
   noSuchMethod(v) => '';
 }
@@ -2680,16 +2490,15 @@
   m();
 }
 class B extends A implements I {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          71, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_setter_and_implicitSetter() async {
     // test from language/override_inheritance_abstract_test_14.dart
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {
   set field(_);
 }
@@ -2698,42 +2507,39 @@
 }
 class B extends A implements I {
   get field => 0;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          77, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_setter_fromInterface() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class I {
   set s(int i) {}
 }
 class C implements I {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          36, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_setter_fromSuperclass() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {
   set s(int i);
 }
 class C extends A {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          43, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_superclasses_interface() async {
     // bug 11154
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   get a => 'a';
 }
@@ -2741,683 +2547,622 @@
   get b => 'b';
 }
 class C extends B {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          84, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_variable_fromInterface_missingGetter() async {
     // 16133
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class I {
   var v;
 }
 class C implements I {
   set v(_) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          27, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberOne_variable_fromInterface_missingSetter() async {
     // 16133
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class I {
   var v;
 }
 class C implements I {
   get v => 1;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
+          27, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberThree() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {
   m();
   n();
   o();
 }
 class C extends A {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE,
+          48, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberTwo() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 abstract class A {
   m();
   n();
 }
 class C extends A {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO,
+          41, 1),
+    ]);
   }
 
   test_nonAbstractClassInheritsAbstractMemberTwo_variable_fromInterface_missingBoth() async {
     // 16133
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class I {
   var v;
 }
 class C implements I {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO,
+          27, 1),
+    ]);
   }
 
   test_nonTypeInCatchClause_noElement() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {
   try {
   } on T catch (e) {
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, 21, 1),
+      error(HintCode.UNUSED_CATCH_CLAUSE, 30, 1),
+    ]);
   }
 
   test_nonTypeInCatchClause_notType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 var T = 0;
 f() {
   try {
   } on T catch (e) {
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, 32, 1),
+      error(HintCode.UNUSED_CATCH_CLAUSE, 41, 1),
+    ]);
   }
 
   test_nonVoidReturnForOperator() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int operator []=(a, b) { return a; }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NON_VOID_RETURN_FOR_OPERATOR]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_VOID_RETURN_FOR_OPERATOR, 12, 3),
+    ]);
   }
 
   test_nonVoidReturnForSetter_function() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 int set x(int v) {
   return 42;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NON_VOID_RETURN_FOR_SETTER]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, 0, 3),
+    ]);
   }
 
   test_nonVoidReturnForSetter_method() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   int set x(int v) {
     return 42;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NON_VOID_RETURN_FOR_SETTER]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, 12, 3),
+    ]);
   }
 
   test_notAType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f() {}
 main() {
   f v = null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NOT_A_TYPE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NOT_A_TYPE, 18, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 20, 1),
+    ]);
   }
 
   test_notEnoughRequiredArguments() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f(int a, String b) {}
 main() {
   f();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS, 34, 2),
+    ]);
   }
 
   test_notEnoughRequiredArguments_functionExpression() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 main() {
   (int x) {} ();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS, 22, 2),
+    ]);
   }
 
   test_notEnoughRequiredArguments_getterReturningFunction() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 typedef Getter(self);
 Getter getter = (x) => x;
 main() {
   getter();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS, 65, 2),
+    ]);
   }
 
   test_partOfDifferentLibrary() async {
-    Source source = addSource(r'''
+    newFile("/test/lib/part.dart", content: "part of lub;");
+    await assertErrorsInCode('''
 library lib;
-part 'part.dart';''');
-    addNamedSource("/part.dart", "part of lub;");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.PART_OF_DIFFERENT_LIBRARY]);
-    verify([source]);
+part 'part.dart';''', [
+      error(StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, 18, 11),
+    ]);
   }
 
   test_redirectToInvalidFunctionType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A implements B {
   A(int p) {}
 }
 class B {
   factory B() = A;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE, 65, 1),
+    ]);
   }
 
   test_redirectToInvalidReturnType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   A() {}
 }
 class B {
   factory B() = A;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE, 47, 1),
+    ]);
   }
 
   test_redirectToMissingConstructor_named() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A implements B{
   A() {}
 }
 class B {
   factory B() = A.name;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR]);
+}''', [
+      error(StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR, 59, 6),
+    ]);
   }
 
   test_redirectToMissingConstructor_unnamed() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A implements B{
   A.name() {}
 }
 class B {
   factory B() = A;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR]);
+}''', [
+      error(StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR, 64, 1),
+    ]);
   }
 
   test_redirectToNonClass_notAType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class B {
   int A;
   factory B() = A;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.REDIRECT_TO_NON_CLASS]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.REDIRECT_TO_NON_CLASS, 35, 1),
+    ]);
   }
 
   test_redirectToNonClass_undefinedIdentifier() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class B {
   factory B() = A;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.REDIRECT_TO_NON_CLASS]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.REDIRECT_TO_NON_CLASS, 26, 1),
+    ]);
   }
 
   test_returnWithoutValue_async() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 import 'dart:async';
 Future<int> f() async {
   return;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
-    verify([source]);
+''', [
+      error(StaticWarningCode.RETURN_WITHOUT_VALUE, 47, 7),
+    ]);
   }
 
   test_returnWithoutValue_async_future_object_with_return() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 import 'dart:async';
 Future<Object> f() async {
   return;
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
-    verify([source]);
+''', [
+      error(StaticWarningCode.RETURN_WITHOUT_VALUE, 50, 7),
+    ]);
   }
 
   test_returnWithoutValue_factoryConstructor() async {
-    Source source = addSource("class A { factory A() { return; } }");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
-    verify([source]);
+    await assertErrorsInCode('''
+class A { factory A() { return; } }
+''', [
+      error(StaticWarningCode.RETURN_WITHOUT_VALUE, 24, 7),
+    ]);
   }
 
   test_returnWithoutValue_function() async {
-    Source source = addSource("int f() { return; }");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
-    verify([source]);
+    await assertErrorsInCode('''
+int f() { return; }
+''', [
+      error(StaticWarningCode.RETURN_WITHOUT_VALUE, 10, 7),
+    ]);
   }
 
   test_returnWithoutValue_method() async {
-    Source source = addSource("class A { int m() { return; } }");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
-    verify([source]);
+    await assertErrorsInCode('''
+class A { int m() { return; } }
+''', [
+      error(StaticWarningCode.RETURN_WITHOUT_VALUE, 20, 7),
+    ]);
   }
 
   test_returnWithoutValue_mixedReturnTypes_function() async {
     // Tests that only the RETURN_WITHOUT_VALUE warning is created, and no
     // MIXED_RETURN_TYPES are created.
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 int f(int x) {
   if (x < 0) {
     return 1;
   }
   return;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.RETURN_WITHOUT_VALUE, 50, 7),
+    ]);
   }
 
   test_returnWithoutValue_Null() async {
     // Test that block bodied functions with return type Null and an empty
     // return cause a static warning.
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 Null f() {return;}
 ''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_staticAccessToInstanceMember_method_invocation() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m() {}
 }
 main() {
   A.m();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 34, 1),
+    ]);
   }
 
   test_staticAccessToInstanceMember_method_reference() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   m() {}
 }
 main() {
   A.m;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 34, 1),
+    ]);
   }
 
   test_staticAccessToInstanceMember_propertyAccess_field() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   var f;
 }
 main() {
   A.f;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 34, 1),
+    ]);
   }
 
   test_staticAccessToInstanceMember_propertyAccess_getter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   get f => 42;
 }
 main() {
   A.f;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 40, 1),
+    ]);
   }
 
   test_staticAccessToInstanceMember_propertyAccess_setter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   set f(x) {}
 }
 main() {
   A.f = 42;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 39, 1),
+    ]);
   }
 
   test_switchExpressionNotAssignable() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f(int p) {
   switch (p) {
     case 'a': break;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE, 21, 1),
+    ]);
   }
 
   test_typeAnnotationDeferredClass_asExpression() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 f(var v) {
   v as a.A;
-}'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 66, 3),
     ]);
   }
 
   test_typeAnnotationDeferredClass_catchClause() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 f(var v) {
   try {
   } on a.A {
   }
-}'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 74, 3),
     ]);
   }
 
   test_typeAnnotationDeferredClass_fieldFormalParameter() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class C {
   var v;
   C(a.A this.v);
-}'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 71, 3),
     ]);
   }
 
   test_typeAnnotationDeferredClass_functionDeclaration_returnType() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
-a.A f() { return null; }'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+a.A f() { return null; }''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 48, 3),
     ]);
   }
 
   test_typeAnnotationDeferredClass_functionTypedFormalParameter_returnType() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
-f(a.A g()) {}'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+f(a.A g()) {}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 50, 3),
     ]);
   }
 
   test_typeAnnotationDeferredClass_isExpression() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 f(var v) {
   bool b = v is a.A;
-}'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 66, 1),
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 75, 3),
     ]);
   }
 
   test_typeAnnotationDeferredClass_methodDeclaration_returnType() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class C {
   a.A m() { return null; }
-}'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 60, 3),
     ]);
   }
 
   test_typeAnnotationDeferredClass_simpleFormalParameter() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
-f(a.A v) {}'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+f(a.A v) {}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 50, 3),
     ]);
   }
 
   test_typeAnnotationDeferredClass_typeArgumentList() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class C<E> {}
-C<a.A> c;'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+C<a.A> c;''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 64, 3),
     ]);
   }
 
   test_typeAnnotationDeferredClass_typeArgumentList2() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
 class C<E, F> {}
-C<a.A, a.A> c;'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS,
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+C<a.A, a.A> c;''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 67, 3),
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 72, 3),
     ]);
   }
 
   test_typeAnnotationDeferredClass_typeParameter_bound() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
-class C<E extends a.A> {}'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+class C<E extends a.A> {}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 66, 3),
     ]);
   }
 
   test_typeAnnotationDeferredClass_variableDeclarationList() async {
-    await resolveWithErrors(<String>[
-      r'''
+    newFile("/test/lib/lib1.dart", content: '''
 library lib1;
-class A {}''',
-      r'''
+class A {}''');
+    await assertErrorsInCode('''
 library root;
 import 'lib1.dart' deferred as a;
-a.A v;'''
-    ], <ErrorCode>[
-      StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS
+a.A v;''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 48, 3),
     ]);
   }
 
   test_typeParameterReferencedByStatic_field() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A<K> {
   static K k;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 22, 1),
+    ]);
   }
 
   test_typeParameterReferencedByStatic_getter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A<K> {
   static K get k => null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 22, 1),
+    ]);
   }
 
   test_typeParameterReferencedByStatic_methodBodyReference() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A<K> {
   static m() {
     K k;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 32, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 34, 1),
+    ]);
   }
 
   test_typeParameterReferencedByStatic_methodParameter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A<K> {
   static m(K k) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 24, 1),
+    ]);
   }
 
   test_typeParameterReferencedByStatic_methodReturn() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A<K> {
   static K m() { return null; }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 22, 1),
+    ]);
   }
 
   test_typeParameterReferencedByStatic_setter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A<K> {
   static set s(K k) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 28, 1),
+    ]);
   }
 
   test_typeParameterReferencedByStatic_simpleIdentifier() async {
-    Source source = addSource('''
+    await assertErrorsInCode('''
 class A<T> {
   static foo() {
     T;
   }
 }
-''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
-    verify([source]);
+''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 34, 1),
+    ]);
   }
 
   test_typePromotion_functionType_arg_InterToDyn() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 typedef FuncDyn(x);
 typedef FuncA(A a);
 class A {}
@@ -3427,329 +3172,324 @@
     f(new B());
   }
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 
   test_typeTestNonType() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 var A = 0;
 f(var p) {
   if (p is A) {
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.TYPE_TEST_WITH_NON_TYPE]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.TYPE_TEST_WITH_NON_TYPE, 33, 1),
+    ]);
   }
 
   test_typeTestWithUndefinedName() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f(var p) {
   if (p is A) {
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.TYPE_TEST_WITH_UNDEFINED_NAME]);
-    verify([source]);
+}''', [
+      error(StaticWarningCode.TYPE_TEST_WITH_UNDEFINED_NAME, 22, 1),
+    ]);
   }
 
   test_undefinedClass_instanceCreation() async {
-    Source source = addSource("f() { new C(); }");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
+    await assertErrorsInCode('''
+f() { new C(); }
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 10, 1),
+    ]);
   }
 
   test_undefinedClass_variableDeclaration() async {
-    Source source = addSource("f() { C c; }");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
+    await assertErrorsInCode('''
+f() { C c; }
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 6, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 8, 1),
+    ]);
   }
 
   test_undefinedClassBoolean_variableDeclaration() async {
-    Source source = addSource("f() { boolean v; }");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS_BOOLEAN]);
+    await assertErrorsInCode('''
+f() { boolean v; }
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS_BOOLEAN, 6, 7),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+    ]);
   }
 
   @failingTest
   test_undefinedIdentifier_commentReference() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 /** [m] xxx [new B.c] */
 class A {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.UNDEFINED_IDENTIFIER,
-      StaticWarningCode.UNDEFINED_IDENTIFIER
+}''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 5, 1),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 17, 1),
     ]);
   }
 
   test_undefinedIdentifier_for() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f(var l) {
   for (e in l) {
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
+}''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 18, 1),
+    ]);
   }
 
   test_undefinedIdentifier_function() async {
-    Source source = addSource("int a() => b;");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
+    await assertErrorsInCode('''
+int a() => b;
+''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 11, 1),
+    ]);
   }
 
   test_undefinedIdentifier_importCore_withShow() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 import 'dart:core' show List;
 main() {
   List;
   String;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
+}''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 49, 6),
+    ]);
   }
 
   test_undefinedIdentifier_initializer() async {
-    Source source = addSource("var a = b;");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
+    await assertErrorsInCode('''
+var a = b;
+''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 8, 1),
+    ]);
   }
 
   test_undefinedIdentifier_methodInvocation() async {
-    Source source = addSource("f() { C.m(); }");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
+    await assertErrorsInCode('''
+f() { C.m(); }
+''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 6, 1),
+    ]);
   }
 
   test_undefinedIdentifier_private_getter() async {
-    addNamedSource("/lib.dart", r'''
+    newFile("/test/lib/lib.dart", content: '''
 library lib;
 class A {
   var _foo;
 }''');
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 import 'lib.dart';
 class B extends A {
   test() {
     var v = _foo;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 58, 1),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 62, 4),
+    ]);
   }
 
   test_undefinedIdentifier_private_setter() async {
-    addNamedSource("/lib.dart", r'''
+    newFile("/test/lib/lib.dart", content: '''
 library lib;
 class A {
   var _foo;
 }''');
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 import 'lib.dart';
 class B extends A {
   test() {
     _foo = 42;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
+}''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 54, 4),
+    ]);
   }
 
   test_undefinedIdentifierAwait_function() async {
-    Source source = addSource("void a() { await; }");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT]);
+    await assertErrorsInCode('''
+void a() { await; }
+''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT, 11, 5),
+    ]);
   }
 
   test_undefinedNamedParameter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 f({a, b}) {}
 main() {
   f(c: 1);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_NAMED_PARAMETER]);
-    // no verify(), 'c' is not resolved
+}''', [
+      error(StaticWarningCode.UNDEFINED_NAMED_PARAMETER, 26, 1),
+    ]);
   }
 
   test_undefinedStaticMethodOrGetter_getter() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class C {}
 f(var p) {
   f(C.m);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 28, 1),
+    ]);
   }
 
   test_undefinedStaticMethodOrGetter_getter_inSuperclass() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class S {
   static int get g => 0;
 }
 class C extends S {}
 f(var p) {
   f(C.g);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 75, 1),
+    ]);
   }
 
   test_undefinedStaticMethodOrGetter_setter_inSuperclass() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class S {
   static set s(int i) {}
 }
 class C extends S {}
 f(var p) {
   f(C.s = 1);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_SETTER, 75, 1),
+    ]);
   }
 
   test_useOfVoidResult_assignmentExpression_function() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void f() {}
 class A {
   n() {
     var a;
     a = f();
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 38, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 49, 1),
+    ]);
   }
 
   test_useOfVoidResult_assignmentExpression_method() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   void m() {}
   n() {
     var a;
     a = m();
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 40, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 51, 1),
+    ]);
   }
 
   test_useOfVoidResult_await() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 main() async {
   void x;
   await x;
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_useOfVoidResult_inForLoop_error() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   void m() {}
   n() {
     for(Object a = m();;) {}
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 47, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 51, 1),
+    ]);
   }
 
   test_useOfVoidResult_inForLoop_ok() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 class A {
   void m() {}
   n() {
     for(void a = m();;) {}
   }
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_useOfVoidResult_variableDeclaration_function_error() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 void f() {}
 class A {
   n() {
     Object a = f();
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 41, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 45, 1),
+    ]);
   }
 
   test_useOfVoidResult_variableDeclaration_function_ok() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 void f() {}
 class A {
   n() {
     void a = f();
   }
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_useOfVoidResult_variableDeclaration_method2() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   void m() {}
   n() {
     Object a = m(), b = m();
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.USE_OF_VOID_RESULT,
-      StaticWarningCode.USE_OF_VOID_RESULT
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 43, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 47, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 52, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 56, 1),
     ]);
-    verify([source]);
   }
 
   test_useOfVoidResult_variableDeclaration_method_error() async {
-    Source source = addSource(r'''
+    await assertErrorsInCode('''
 class A {
   void m() {}
   n() {
     Object a = m();
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
-    verify([source]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 43, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 47, 1),
+    ]);
   }
 
   test_useOfVoidResult_variableDeclaration_method_ok() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 class A {
   void m() {}
   n() {
     void a = m();
   }
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_voidReturnForGetter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode('''
 class S {
   void get value {}
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
   }
 }
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index ae7258d..1f4358e 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -8,7 +8,7 @@
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -24,19 +24,15 @@
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(StrongModeCastsTest);
     defineReflectiveTests(StrongModeLocalInferenceTest);
     defineReflectiveTests(StrongModeStaticTypeAnalyzer2Test);
     defineReflectiveTests(StrongModeTypePropagationTest);
-    defineReflectiveTests(StrongModeCastsWithUiAsCodeTest);
   });
 }
 
 @reflectiveTest
-class StrongModeCastsWithUiAsCodeTest extends ResolverTestCase {
-  @override
-  List<String> get enabledExperiments =>
-      [EnableString.spread_collections, EnableString.control_flow_collections];
-
+class StrongModeCastsTest extends ResolverTestCase {
   test_implicitCastMetadata_ifElement_condition() async {
     var source = addSource(r'''
 class C {
@@ -2532,8 +2528,8 @@
 Couldn't infer type parameter 'T'.
 
 Tried to infer 'double' for 'T' which doesn't work:
-  Parameter 'f' declared as     '(T) → T'
-                but argument is '(int) → double'.
+  Parameter 'f' declared as     'T Function(T)'
+                but argument is 'double Function(int)'.
 
 Consider passing explicit type argument(s) to the generic.
 
@@ -2559,10 +2555,10 @@
 Couldn't infer type parameter 'T'.
 
 Tried to infer 'num' for 'T' which doesn't work:
-  Parameter 'a' declared as     '(T) → T'
-                but argument is '(int) → double'.
-  Parameter 'b' declared as     '(T) → T'
-                but argument is '(double) → int'.
+  Parameter 'a' declared as     'T Function(T)'
+                but argument is 'double Function(int)'.
+  Parameter 'b' declared as     'T Function(T)'
+                but argument is 'int Function(double)'.
 
 Consider passing explicit type argument(s) to the generic.
 
@@ -2589,7 +2585,7 @@
         .variables
         .variables[0];
     var call = h.initializer as MethodInvocation;
-    expect(call.staticInvokeType.toString(), '(Null, Null) → Null');
+    expect(call.staticInvokeType.toString(), 'Null Function(Null, Null)');
   }
 
   test_inference_error_extendsFromReturn2() async {
@@ -2610,8 +2606,8 @@
 Tried to infer 'String' for 'T' which doesn't work:
   Type parameter 'T' declared to extend 'num'.
 The type 'String' was inferred from:
-  Return type declared as '(T) → T'
-              used where  '(String) → String' is required.
+  Return type declared as 'T Function(T)'
+              used where  'String Function(String)' is required.
 
 Consider passing explicit type argument(s) to the generic.
 
@@ -2637,8 +2633,8 @@
 Couldn't infer type parameter 'T'.
 
 Tried to infer 'dynamic' for 'T' which doesn't work:
-  Function type declared as '<T extends num>(T, T) → T'
-                used where  '(num, dynamic) → num' is required.
+  Function type declared as 'T Function<T extends num>(T, T)'
+                used where  'num Function(num, dynamic)' is required.
 
 Consider passing explicit type argument(s) to the generic.
 
@@ -2660,8 +2656,8 @@
 Couldn't infer type parameter 'T'.
 
 Tried to infer 'num' for 'T' which doesn't work:
-  Return type declared as '(T) → T'
-              used where  '(num) → int' is required.
+  Return type declared as 'T Function(T)'
+              used where  'int Function(num)' is required.
 
 Consider passing explicit type argument(s) to the generic.
 
@@ -2702,8 +2698,13 @@
     var stmts = body.block.statements;
     for (ExpressionStatement stmt in stmts) {
       MethodInvocation invoke = stmt.expression;
-      ParameterizedType fType = invoke.staticInvokeType;
-      expect(fType.typeArguments[0].toString(), 'T');
+      FunctionType fType = invoke.staticInvokeType;
+      if (AnalysisDriver.useSummary2) {
+        expect('$fType',
+            'void Function(T Function(T), int Function(T, T), T Function(T))');
+      } else {
+        expect(fType.typeArguments[0].toString(), 'T');
+      }
     }
   }
 
@@ -2729,8 +2730,12 @@
     var stmts = body.block.statements;
     for (ExpressionStatement stmt in stmts) {
       MethodInvocation invoke = stmt.expression;
-      ParameterizedType fType = invoke.staticInvokeType;
-      expect(fType.typeArguments[0].toString(), 'T');
+      FunctionType fType = invoke.staticInvokeType;
+      if (AnalysisDriver.useSummary2) {
+        expect('$fType', 'void Function(List<T>, int Function(T, T), List<T>)');
+      } else {
+        expect(fType.typeArguments[0].toString(), 'T');
+      }
     }
   }
 
@@ -2756,8 +2761,12 @@
     var stmts = body.block.statements;
     for (ExpressionStatement stmt in stmts) {
       MethodInvocation invoke = stmt.expression;
-      ParameterizedType fType = invoke.staticInvokeType;
-      expect(fType.typeArguments[0].toString(), 'T');
+      FunctionType fType = invoke.staticInvokeType;
+      if (AnalysisDriver.useSummary2) {
+        expect('$fType', 'void Function(T, int Function(T, T), T)');
+      } else {
+        expect(fType.typeArguments[0].toString(), 'T');
+      }
     }
   }
 
@@ -2780,10 +2789,10 @@
         .variables[0];
     _isDynamic(h.declaredElement.type);
     var fCall = h.initializer as MethodInvocation;
-    expect(
-        fCall.staticInvokeType.toString(), '((dynamic) → dynamic) → dynamic');
+    expect(fCall.staticInvokeType.toString(),
+        'dynamic Function(dynamic Function(dynamic))');
     var g = fCall.argumentList.arguments[0];
-    expect(g.staticType.toString(), '(dynamic) → dynamic');
+    expect(g.staticType.toString(), 'dynamic Function(dynamic)');
   }
 
   test_inferGenericInstantiation2() async {
@@ -2808,11 +2817,11 @@
             .functionExpression
             .body as ExpressionFunctionBody)
         .expression as MethodInvocation;
-    expect(
-        fold.staticInvokeType.toString(), '(num, (num, dynamic) → num) → num');
+    expect(fold.staticInvokeType.toString(),
+        'num Function(num, num Function(num, dynamic))');
     var max = fold.argumentList.arguments[1];
-    // TODO(jmesserly): arguably (num, num) → num is better here.
-    expect(max.staticType.toString(), '(dynamic, dynamic) → dynamic');
+    // TODO(jmesserly): arguably num Function(num, num) is better here.
+    expect(max.staticType.toString(), 'dynamic Function(dynamic, dynamic)');
   }
 
   test_inferredFieldDeclaration_propagation() async {
@@ -3600,7 +3609,7 @@
     expect(typeName.type.toString(), 'A<T2, U2>');
 
     var constructorMember = redirected.staticElement;
-    expect(constructorMember.toString(), 'A.named() → A<T2, U2>');
+    expect(constructorMember.toString(), 'A<T2, U2> A.named()');
     expect(redirected.name.staticElement, constructorMember);
   }
 
@@ -3637,7 +3646,7 @@
     expect(typeName.type.toString(), 'A<T2, U2>');
 
     expect(redirected.name, isNull);
-    expect(redirected.staticElement.toString(), 'A() → A<T2, U2>');
+    expect(redirected.staticElement.toString(), 'A<T2, U2> A()');
   }
 
   test_redirectingConstructor_propagation() async {
@@ -3898,76 +3907,18 @@
 }
 
 @reflectiveTest
-class StrongModeStaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared
-    with StrongModeStaticTypeAnalyzer2TestCases {
+class StrongModeStaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared {
+  void expectStaticInvokeType(String search, String type) {
+    var invocation = findIdentifier(search).parent as MethodInvocation;
+    expect(invocation.staticInvokeType.toString(), type);
+  }
+
   void setUp() {
     super.setUp();
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     resetWith(options: options);
   }
 
-  @failingTest
-  @override
-  test_genericFunction_parameter() {
-    return super.test_genericFunction_parameter();
-  }
-
-  @failingTest
-  @override
-  test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit() {
-    return super
-        .test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit();
-  }
-
-  @failingTest
-  @override
-  test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred() {
-    return super
-        .test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred();
-  }
-
-  @failingTest
-  @override
-  test_genericMethod_functionInvocation_functionTypedParameter_explicit() {
-    return super
-        .test_genericMethod_functionInvocation_functionTypedParameter_explicit();
-  }
-
-  @failingTest
-  @override
-  test_genericMethod_functionInvocation_functionTypedParameter_inferred() {
-    return super
-        .test_genericMethod_functionInvocation_functionTypedParameter_inferred();
-  }
-
-  @failingTest
-  @override
-  test_genericMethod_functionTypedParameter_tearoff() {
-    return super.test_genericMethod_functionTypedParameter_tearoff();
-  }
-
-  @override
-  @failingTest
-  test_genericMethod_nestedCaptureBounds() {
-    // https://github.com/dart-lang/sdk/issues/30236
-    return super.test_genericMethod_nestedCaptureBounds();
-  }
-
-  @override
-  @failingTest
-  test_genericMethod_tearoff_instantiated() {
-    return super.test_genericMethod_tearoff_instantiated();
-  }
-}
-
-/// Test cases for [StrongModeStaticTypeAnalyzer2Test]
-mixin StrongModeStaticTypeAnalyzer2TestCases
-    implements StaticTypeAnalyzer2TestShared {
-  void expectStaticInvokeType(String search, String type) {
-    var invocation = findIdentifier(search).parent as MethodInvocation;
-    expect(invocation.staticInvokeType.toString(), type);
-  }
-
   test_dynamicObjectGetter_hashCode() async {
     String code = r'''
 main() {
@@ -4034,32 +3985,30 @@
 
   test_genericFunction() async {
     await resolveTestUnit(r'T f<T>(T x) => null;');
-    expectFunctionType('f', '<T>(T) → T',
+    expectFunctionType('f', 'T Function<T>(T)',
         elementTypeParams: '[T]', typeFormals: '[T]');
     SimpleIdentifier f = findIdentifier('f');
     FunctionElementImpl e = f.staticElement;
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
-    expect(ft.toString(), '(String) → String');
+    expect(ft.toString(), 'String Function(String)');
   }
 
   test_genericFunction_bounds() async {
     await resolveTestUnit(r'T f<T extends num>(T x) => null;');
-    expectFunctionType('f', '<T extends num>(T) → T',
+    expectFunctionType('f', 'T Function<T extends num>(T)',
         elementTypeParams: '[T extends num]', typeFormals: '[T extends num]');
   }
 
   test_genericFunction_parameter() async {
+    // TODO(paulberry): remove when dartbug.com/28515 fixed.
+    if (!AnalysisDriver.useSummary2) return;
+
     await resolveTestUnit(r'''
 void g(T f<T>(T x)) {}
-''', noErrors: false // TODO(paulberry): remove when dartbug.com/28515 fixed.
-        );
-    expectFunctionType('f', '<T>(T) → T',
-        elementTypeParams: '[]', typeFormals: '[T]');
-    SimpleIdentifier f = findIdentifier('f');
-    ParameterElementImpl e = f.staticElement;
-    FunctionType type = e.type;
+''');
+    var type = expectFunctionType2('f', 'T Function<T>(T)');
     FunctionType ft = type.instantiate([typeProvider.stringType]);
-    expect(ft.toString(), '(String) → String');
+    expect(ft.toString(), 'String Function(String)');
   }
 
   test_genericFunction_static() async {
@@ -4068,12 +4017,12 @@
   static T f<T>(T x) => null;
 }
 ''');
-    expectFunctionType('f', '<T>(T) → T',
+    expectFunctionType('f', 'T Function<T>(T)',
         elementTypeParams: '[T]', typeFormals: '[T]');
     SimpleIdentifier f = findIdentifier('f');
     MethodElementImpl e = f.staticElement;
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
-    expect(ft.toString(), '(String) → String');
+    expect(ft.toString(), 'String Function(String)');
   }
 
   test_genericFunction_typedef() async {
@@ -4154,16 +4103,16 @@
   C<String> cOfString;
 }
 ''');
-    expectFunctionType('f', '<T>(E) → List<T>',
+    expectFunctionType('f', 'List<T> Function<T>(E)',
         elementTypeParams: '[T]',
         typeParams: '[E]',
         typeArgs: '[E]',
         typeFormals: '[T]');
     SimpleIdentifier c = findIdentifier('cOfString');
     FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
-    expect(ft.toString(), '<T>(String) → List<T>');
+    expect(ft.toString(), 'List<T> Function<T>(String)');
     ft = ft.instantiate([typeProvider.intType]);
-    expect(ft.toString(), '(String) → List<int>');
+    expect(ft.toString(), 'List<int> Function(String)');
     expect('${ft.typeArguments}/${ft.typeParameters}', '[String, int]/[E, T]');
   }
 
@@ -4179,7 +4128,7 @@
 ''');
     MethodInvocation f = findIdentifier('f<int>').parent;
     FunctionType ft = f.staticInvokeType;
-    expect(ft.toString(), '(String) → List<int>');
+    expect(ft.toString(), 'List<int> Function(String)');
     expect('${ft.typeArguments}/${ft.typeParameters}', '[String, int]/[E, T]');
 
     SimpleIdentifier x = findIdentifier('x');
@@ -4222,26 +4171,33 @@
   }
 
   test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit() async {
+    // TODO(paulberry): remove when dartbug.com/28515 fixed.
+    if (!AnalysisDriver.useSummary2) return;
+
     await resolveTestUnit(r'''
 void test<S>(T pf<T>(T e)) {
   var paramCall = (pf)<int>(3);
 }
-''', noErrors: false // TODO(paulberry): remove when dartbug.com/28515 fixed.
-        );
+''');
     expectIdentifierType('paramCall', "int");
   }
 
   test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred() async {
+    // TODO(paulberry): remove when dartbug.com/28515 fixed.
+    if (!AnalysisDriver.useSummary2) return;
+
     await resolveTestUnit(r'''
 void test<S>(T pf<T>(T e)) {
   var paramCall = (pf)(3);
 }
-''', noErrors: false // TODO(paulberry): remove when dartbug.com/28515 fixed.
-        );
+''');
     expectIdentifierType('paramCall', "int");
   }
 
   test_genericMethod_functionExpressionInvocation_inferred() async {
+    // TODO(paulberry): remove when dartbug.com/28515 fixed.
+    if (!AnalysisDriver.useSummary2) return;
+
     await resolveTestUnit(r'''
 class C<E> {
   T f<T>(T e) => null;
@@ -4264,8 +4220,7 @@
   var localCall = (lf)(3);
   var paramCall = (pf)(3);
 }
-''', noErrors: false // TODO(paulberry): remove when dartbug.com/28515 fixed.
-        );
+''');
     expectIdentifierType('methodCall', "int");
     expectIdentifierType('staticCall', "int");
     expectIdentifierType('staticFieldCall', "int");
@@ -4308,22 +4263,26 @@
   }
 
   test_genericMethod_functionInvocation_functionTypedParameter_explicit() async {
+    // TODO(paulberry): remove when dartbug.com/28515 fixed.
+    if (!AnalysisDriver.useSummary2) return;
+
     await resolveTestUnit(r'''
 void test<S>(T pf<T>(T e)) {
   var paramCall = pf<int>(3);
 }
-''', noErrors: false // TODO(paulberry): remove when dartbug.com/28515 fixed.
-        );
+''');
     expectIdentifierType('paramCall', "int");
   }
 
   test_genericMethod_functionInvocation_functionTypedParameter_inferred() async {
+    // TODO(paulberry): remove when dartbug.com/28515 fixed.
+    if (!AnalysisDriver.useSummary2) return;
+
     await resolveTestUnit(r'''
 void test<S>(T pf<T>(T e)) {
   var paramCall = pf(3);
 }
-''', noErrors: false // TODO(paulberry): remove when dartbug.com/28515 fixed.
-        );
+''');
     expectIdentifierType('paramCall', "int");
   }
 
@@ -4367,7 +4326,7 @@
   C<String> cOfString;
 }
 ''');
-    expectFunctionType('f', '<T>((E) → T) → List<T>',
+    expectFunctionType('f', 'List<T> Function<T>(T Function(E))',
         elementTypeParams: '[T]',
         typeParams: '[E]',
         typeArgs: '[E]',
@@ -4375,19 +4334,21 @@
 
     SimpleIdentifier c = findIdentifier('cOfString');
     FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
-    expect(ft.toString(), '<T>((String) → T) → List<T>');
+    expect(ft.toString(), 'List<T> Function<T>(T Function(String))');
     ft = ft.instantiate([typeProvider.intType]);
-    expect(ft.toString(), '((String) → int) → List<int>');
+    expect(ft.toString(), 'List<int> Function(int Function(String))');
   }
 
   test_genericMethod_functionTypedParameter_tearoff() async {
+    // TODO(paulberry): remove when dartbug.com/28515 fixed.
+    if (!AnalysisDriver.useSummary2) return;
+
     await resolveTestUnit(r'''
 void test<S>(T pf<T>(T e)) {
   var paramTearOff = pf;
 }
-''', noErrors: false // TODO(paulberry): remove when dartbug.com/28515 fixed.
-        );
-    expectIdentifierType('paramTearOff', "<T>(T) → T");
+''');
+    expectIdentifierType('paramTearOff', "T Function<T>(T)");
   }
 
   test_genericMethod_implicitDynamic() async {
@@ -4403,13 +4364,17 @@
   list.map((e) => e);
   list.map((e) => 3);
 }''');
-    expectIdentifierType('map((e) => e);', '<T>((dynamic) → T) → T');
-    expectIdentifierType('map((e) => 3);', '<T>((dynamic) → T) → T');
+    expectIdentifierType(
+        'map((e) => e);', 'T Function<T>(T Function(dynamic))');
+    expectIdentifierType(
+        'map((e) => 3);', 'T Function<T>(T Function(dynamic))');
 
     MethodInvocation m1 = findIdentifier('map((e) => e);').parent;
-    expect(m1.staticInvokeType.toString(), '((dynamic) → dynamic) → dynamic');
+    expect(m1.staticInvokeType.toString(),
+        'dynamic Function(dynamic Function(dynamic))');
     MethodInvocation m2 = findIdentifier('map((e) => 3);').parent;
-    expect(m2.staticInvokeType.toString(), '((dynamic) → int) → int');
+    expect(
+        m2.staticInvokeType.toString(), 'int Function(int Function(dynamic))');
   }
 
   test_genericMethod_max_doubleDouble() async {
@@ -4490,13 +4455,14 @@
 }
 ''');
     MethodInvocation f = findIdentifier('f<int>(3);').parent;
-    expect(f.staticInvokeType.toString(), '(int) → S');
+    expect(f.staticInvokeType.toString(), 'S Function(int)');
     FunctionType ft = f.staticInvokeType;
     expect('${ft.typeArguments}/${ft.typeParameters}', '[S, int]/[T, S]');
 
-    expectIdentifierType('f;', '<S₀>(S₀) → S');
+    expectIdentifierType('f;', 'S Function<S₀>(S₀)');
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/30236')
   test_genericMethod_nestedCaptureBounds() async {
     await resolveTestUnit(r'''
 class C<T> {
@@ -4508,12 +4474,12 @@
 }
 ''');
     MethodInvocation f = findIdentifier('f<int>(3);').parent;
-    expect(f.staticInvokeType.toString(), '(int) → S');
+    expect(f.staticInvokeType.toString(), 'S Function(int)');
     FunctionType ft = f.staticInvokeType;
     expect('${ft.typeArguments}/${ft.typeParameters}',
         '[S, int]/[T, S extends T]');
 
-    expectIdentifierType('f;', '<S₀ extends S>(S₀) → S');
+    expectIdentifierType('f;', 'S Function<S₀ extends S>(S₀)');
   }
 
   test_genericMethod_nestedFunctions() async {
@@ -4523,8 +4489,8 @@
   return null;
 }
 ''');
-    expectIdentifierType('f', '<S>(S) → S');
-    expectIdentifierType('g', '<S>(S) → <S>(S) → S');
+    expectIdentifierType('f', 'S Function<S>(S)');
+    expectIdentifierType('g', 'S Function<S>(S) Function<S>(S)');
   }
 
   test_genericMethod_override() async {
@@ -4536,12 +4502,12 @@
   T f<T>(T x) => null; // from D
 }
 ''');
-    expectFunctionType('f<T>(T x) => null; // from D', '<T>(T) → T',
+    expectFunctionType('f<T>(T x) => null; // from D', 'T Function<T>(T)',
         elementTypeParams: '[T]', typeFormals: '[T]');
     SimpleIdentifier f = findIdentifier('f<T>(T x) => null; // from D');
     MethodElementImpl e = f.staticElement;
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
-    expect(ft.toString(), '(String) → String');
+    expect(ft.toString(), 'String Function(String)');
   }
 
   test_genericMethod_override_bounds() async {
@@ -4697,15 +4663,16 @@
   var paramTearOff = pf;
 }
 ''');
-    expectIdentifierType('methodTearOff', "<T>(int) → T");
-    expectIdentifierType('staticTearOff', "<T>(T) → T");
-    expectIdentifierType('staticFieldTearOff', "<T>(T) → T");
-    expectIdentifierType('topFunTearOff', "<T>(T) → T");
-    expectIdentifierType('topFieldTearOff', "<T>(T) → T");
-    expectIdentifierType('localTearOff', "<T>(T) → T");
-    expectIdentifierType('paramTearOff', "<T>(T) → T");
+    expectIdentifierType('methodTearOff', "T Function<T>(int)");
+    expectIdentifierType('staticTearOff', "T Function<T>(T)");
+    expectIdentifierType('staticFieldTearOff', "T Function<T>(T)");
+    expectIdentifierType('topFunTearOff', "T Function<T>(T)");
+    expectIdentifierType('topFieldTearOff', "T Function<T>(T)");
+    expectIdentifierType('localTearOff', "T Function<T>(T)");
+    expectIdentifierType('paramTearOff', "T Function<T>(T)");
   }
 
+  @failingTest
   test_genericMethod_tearoff_instantiated() async {
     await resolveTestUnit(r'''
 class C<E> {
@@ -4728,13 +4695,13 @@
   var paramTearOffInst = pf<int>;
 }
 ''');
-    expectIdentifierType('methodTearOffInst', "(int) → int");
-    expectIdentifierType('staticTearOffInst', "(int) → int");
-    expectIdentifierType('staticFieldTearOffInst', "(int) → int");
-    expectIdentifierType('topFunTearOffInst', "(int) → int");
-    expectIdentifierType('topFieldTearOffInst', "(int) → int");
-    expectIdentifierType('localTearOffInst', "(int) → int");
-    expectIdentifierType('paramTearOffInst', "(int) → int");
+    expectIdentifierType('methodTearOffInst', "int Function(int)");
+    expectIdentifierType('staticTearOffInst', "int Function(int)");
+    expectIdentifierType('staticFieldTearOffInst', "int Function(int)");
+    expectIdentifierType('topFunTearOffInst', "int Function(int)");
+    expectIdentifierType('topFieldTearOffInst', "int Function(int)");
+    expectIdentifierType('localTearOffInst', "int Function(int)");
+    expectIdentifierType('paramTearOffInst', "int Function(int)");
   }
 
   test_genericMethod_then() async {
@@ -4792,7 +4759,7 @@
   var fieldRead = C.h;
 }
 ''');
-    expectIdentifierType('fieldRead', "<T>(T) → T");
+    expectIdentifierType('fieldRead', "T Function<T>(T)");
   }
 
   test_implicitBounds() async {
@@ -4914,7 +4881,7 @@
 ''';
     await resolveTestUnit(code, noErrors: false);
     assertNoErrors(testSource);
-    expectIdentifierType('c;', 'C<(dynamic) → dynamic>');
+    expectIdentifierType('c;', 'C<dynamic Function(dynamic)>');
   }
 
   test_instantiateToBounds_class_ok_implicitDynamic_multi() async {
@@ -5017,7 +4984,7 @@
 ''';
     await resolveTestUnit(code);
     assertNoErrors(testSource);
-    expectStaticInvokeType('m(null', '(Null, Null) → void');
+    expectStaticInvokeType('m(null', 'void Function(Null, Null)');
   }
 
   test_instantiateToBounds_method_ok_referenceOther_before2() async {
@@ -5032,7 +4999,7 @@
 ''';
     await resolveTestUnit(code);
     assertNoErrors(testSource);
-    expectStaticInvokeType('m();', '() → Map<T, List<T>>');
+    expectStaticInvokeType('m();', 'Map<T, List<T>> Function()');
   }
 
   test_instantiateToBounds_method_ok_simpleBounds() async {
@@ -5047,7 +5014,7 @@
 ''';
     await resolveTestUnit(code);
     assertNoErrors(testSource);
-    expectStaticInvokeType('m(null)', '(Null) → void');
+    expectStaticInvokeType('m(null)', 'void Function(Null)');
   }
 
   test_instantiateToBounds_method_ok_simpleBounds2() async {
@@ -5062,7 +5029,7 @@
 ''';
     await resolveTestUnit(code);
     assertNoErrors(testSource);
-    expectStaticInvokeType('m();', '() → T');
+    expectStaticInvokeType('m();', 'T Function()');
   }
 
   test_issue32396() async {
@@ -5468,10 +5435,10 @@
   Future<void> _objectMethodOnFunctions_helper2(String code) async {
     await resolveTestUnit(code);
     expectIdentifierType('t0', "String");
-    expectIdentifierType('t1', "() → String");
+    expectIdentifierType('t1', "String Function()");
     expectIdentifierType('t2', "int");
     expectIdentifierType('t3', "String");
-    expectIdentifierType('t4', "() → String");
+    expectIdentifierType('t4', "String Function()");
     expectIdentifierType('t5', "int");
   }
 }
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index 9084e64..964112f 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -4,6 +4,7 @@
 
 // Tests related to the [TypeSystem] class.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart' show astFactory;
 import 'package:analyzer/dart/ast/token.dart' show Keyword;
 import 'package:analyzer/dart/element/element.dart';
@@ -29,12 +30,14 @@
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(AssignabilityTest);
     defineReflectiveTests(ConstraintMatchingTest);
-    defineReflectiveTests(StrongAssignabilityTest);
-    defineReflectiveTests(StrongSubtypingTest);
-    defineReflectiveTests(StrongGenericFunctionInferenceTest);
-    defineReflectiveTests(StrongLeastUpperBoundTest);
-    defineReflectiveTests(StrongGreatestLowerBoundTest);
+    defineReflectiveTests(GenericFunctionInferenceTest);
+    defineReflectiveTests(GreatestLowerBoundTest);
+    defineReflectiveTests(LeastUpperBoundFunctionsTest);
+    defineReflectiveTests(LeastUpperBoundTest);
+    defineReflectiveTests(NonNullableSubtypingTest);
+    defineReflectiveTests(SubtypingTest);
     defineReflectiveTests(TypeSystemTest);
   });
 }
@@ -62,6 +65,272 @@
   }
 }
 
+@reflectiveTest
+class AssignabilityTest extends AbstractTypeSystemTest {
+  void test_isAssignableTo_bottom_isBottom() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    List<DartType> interassignable = <DartType>[
+      dynamicType,
+      objectType,
+      intType,
+      doubleType,
+      numType,
+      stringType,
+      interfaceType,
+      bottomType
+    ];
+
+    _checkGroups(bottomType, interassignable: interassignable);
+  }
+
+  void test_isAssignableTo_call_method() {
+    ClassElementImpl classBottom = ElementFactory.classElement2("B");
+    MethodElement methodBottom =
+        ElementFactory.methodElement("call", objectType, <DartType>[intType]);
+    classBottom.methods = <MethodElement>[methodBottom];
+
+    DartType top =
+        TypeBuilder.function(required: <DartType>[intType], result: objectType);
+    InterfaceType bottom = classBottom.type;
+
+    _checkIsStrictAssignableTo(bottom, top);
+  }
+
+  void test_isAssignableTo_classes() {
+    ClassElement classTop = ElementFactory.classElement2("A");
+    ClassElement classLeft = ElementFactory.classElement("B", classTop.type);
+    ClassElement classRight = ElementFactory.classElement("C", classTop.type);
+    ClassElement classBottom = ElementFactory.classElement("D", classLeft.type)
+      ..interfaces = <InterfaceType>[classRight.type];
+    InterfaceType top = classTop.type;
+    InterfaceType left = classLeft.type;
+    InterfaceType right = classRight.type;
+    InterfaceType bottom = classBottom.type;
+
+    _checkLattice(top, left, right, bottom);
+  }
+
+  void test_isAssignableTo_double() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    List<DartType> interassignable = <DartType>[
+      dynamicType,
+      objectType,
+      doubleType,
+      numType,
+      bottomType
+    ];
+    List<DartType> unrelated = <DartType>[
+      intType,
+      stringType,
+      interfaceType,
+    ];
+
+    _checkGroups(doubleType,
+        interassignable: interassignable, unrelated: unrelated);
+  }
+
+  void test_isAssignableTo_dynamic_isTop() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    List<DartType> interassignable = <DartType>[
+      dynamicType,
+      objectType,
+      intType,
+      doubleType,
+      numType,
+      stringType,
+      interfaceType,
+      bottomType
+    ];
+    _checkGroups(dynamicType, interassignable: interassignable);
+  }
+
+  void test_isAssignableTo_generics() {
+    ClassElementImpl LClass = ElementFactory.classElement2('L', ["T"]);
+    InterfaceType LType = LClass.type;
+    ClassElementImpl MClass = ElementFactory.classElement2('M', ["T"]);
+    DartType typeParam = MClass.typeParameters[0].type;
+    InterfaceType superType = LType.instantiate(<DartType>[typeParam]);
+    MClass.interfaces = <InterfaceType>[superType];
+    InterfaceType MType = MClass.type;
+
+    InterfaceType top = LType.instantiate(<DartType>[dynamicType]);
+    InterfaceType left = MType.instantiate(<DartType>[dynamicType]);
+    InterfaceType right = LType.instantiate(<DartType>[intType]);
+    InterfaceType bottom = MType.instantiate(<DartType>[intType]);
+
+    _checkCrossLattice(top, left, right, bottom);
+  }
+
+  void test_isAssignableTo_int() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    List<DartType> interassignable = <DartType>[
+      dynamicType,
+      objectType,
+      intType,
+      numType,
+      bottomType
+    ];
+    List<DartType> unrelated = <DartType>[
+      doubleType,
+      stringType,
+      interfaceType,
+    ];
+
+    _checkGroups(intType,
+        interassignable: interassignable, unrelated: unrelated);
+  }
+
+  void test_isAssignableTo_named_optional() {
+    DartType r =
+        TypeBuilder.function(required: <DartType>[intType], result: intType);
+    DartType o = TypeBuilder.function(
+        required: <DartType>[], optional: <DartType>[intType], result: intType);
+    DartType n = TypeBuilder.function(
+        required: <DartType>[],
+        named: <String, DartType>{'x': intType},
+        result: intType);
+    DartType rr = TypeBuilder.function(
+        required: <DartType>[intType, intType], result: intType);
+    DartType ro = TypeBuilder.function(
+        required: <DartType>[intType],
+        optional: <DartType>[intType],
+        result: intType);
+    DartType rn = TypeBuilder.function(
+        required: <DartType>[intType],
+        named: <String, DartType>{'x': intType},
+        result: intType);
+    DartType oo = TypeBuilder.function(
+        required: <DartType>[],
+        optional: <DartType>[intType, intType],
+        result: intType);
+    DartType nn = TypeBuilder.function(
+        required: <DartType>[],
+        named: <String, DartType>{'x': intType, 'y': intType},
+        result: intType);
+    DartType nnn = TypeBuilder.function(
+        required: <DartType>[],
+        named: <String, DartType>{'x': intType, 'y': intType, 'z': intType},
+        result: intType);
+
+    _checkGroups(r,
+        interassignable: [r, o, ro, rn, oo], unrelated: [n, rr, nn, nnn]);
+    _checkGroups(o,
+        interassignable: [o, oo], unrelated: [n, rr, ro, rn, nn, nnn]);
+    _checkGroups(n,
+        interassignable: [n, nn, nnn], unrelated: [r, o, rr, ro, rn, oo]);
+    _checkGroups(rr,
+        interassignable: [rr, ro, oo], unrelated: [r, o, n, rn, nn, nnn]);
+    _checkGroups(ro, interassignable: [ro, oo], unrelated: [o, n, rn, nn, nnn]);
+    _checkGroups(rn,
+        interassignable: [rn], unrelated: [o, n, rr, ro, oo, nn, nnn]);
+    _checkGroups(oo, interassignable: [oo], unrelated: [n, rn, nn, nnn]);
+    _checkGroups(nn,
+        interassignable: [nn, nnn], unrelated: [r, o, rr, ro, rn, oo]);
+    _checkGroups(nnn,
+        interassignable: [nnn], unrelated: [r, o, rr, ro, rn, oo]);
+  }
+
+  void test_isAssignableTo_num() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    List<DartType> interassignable = <DartType>[
+      dynamicType,
+      objectType,
+      numType,
+      intType,
+      doubleType,
+      bottomType
+    ];
+    List<DartType> unrelated = <DartType>[
+      stringType,
+      interfaceType,
+    ];
+
+    _checkGroups(numType,
+        interassignable: interassignable, unrelated: unrelated);
+  }
+
+  void test_isAssignableTo_simple_function() {
+    FunctionType top =
+        TypeBuilder.function(required: <DartType>[intType], result: objectType);
+    FunctionType left =
+        TypeBuilder.function(required: <DartType>[intType], result: intType);
+    FunctionType right = TypeBuilder.function(
+        required: <DartType>[objectType], result: objectType);
+    FunctionType bottom =
+        TypeBuilder.function(required: <DartType>[objectType], result: intType);
+
+    _checkCrossLattice(top, left, right, bottom);
+  }
+
+  void test_isAssignableTo_void_functions() {
+    FunctionType top =
+        TypeBuilder.function(required: <DartType>[intType], result: voidType);
+    FunctionType bottom =
+        TypeBuilder.function(required: <DartType>[objectType], result: intType);
+
+    _checkEquivalent(bottom, top);
+  }
+
+  void _checkCrossLattice(
+      DartType top, DartType left, DartType right, DartType bottom) {
+    _checkGroups(top, interassignable: [top, left, right, bottom]);
+    _checkGroups(left,
+        interassignable: [top, left, bottom], unrelated: [right]);
+    _checkGroups(right,
+        interassignable: [top, right, bottom], unrelated: [left]);
+    _checkGroups(bottom, interassignable: [top, left, right, bottom]);
+  }
+
+  void _checkEquivalent(DartType type1, DartType type2) {
+    _checkIsAssignableTo(type1, type2);
+    _checkIsAssignableTo(type2, type1);
+  }
+
+  void _checkGroups(DartType t1,
+      {List<DartType> interassignable, List<DartType> unrelated}) {
+    if (interassignable != null) {
+      for (DartType t2 in interassignable) {
+        _checkEquivalent(t1, t2);
+      }
+    }
+    if (unrelated != null) {
+      for (DartType t2 in unrelated) {
+        _checkUnrelated(t1, t2);
+      }
+    }
+  }
+
+  void _checkIsAssignableTo(DartType type1, DartType type2) {
+    expect(typeSystem.isAssignableTo(type1, type2), true);
+  }
+
+  void _checkIsNotAssignableTo(DartType type1, DartType type2) {
+    expect(typeSystem.isAssignableTo(type1, type2), false);
+  }
+
+  void _checkIsStrictAssignableTo(DartType type1, DartType type2) {
+    _checkIsAssignableTo(type1, type2);
+    _checkIsNotAssignableTo(type2, type1);
+  }
+
+  void _checkLattice(
+      DartType top, DartType left, DartType right, DartType bottom) {
+    _checkGroups(top, interassignable: <DartType>[top, left, right, bottom]);
+    _checkGroups(left,
+        interassignable: <DartType>[top, left, bottom],
+        unrelated: <DartType>[right]);
+    _checkGroups(right,
+        interassignable: <DartType>[top, right, bottom],
+        unrelated: <DartType>[left]);
+    _checkGroups(bottom, interassignable: <DartType>[top, left, right, bottom]);
+  }
+
+  void _checkUnrelated(DartType type1, DartType type2) {
+    _checkIsNotAssignableTo(type1, type2);
+    _checkIsNotAssignableTo(type2, type1);
+  }
+}
+
 /**
  * Base class for testing LUB and GLB in spec and strong mode.
  */
@@ -78,6 +347,7 @@
   InterfaceType get intType => typeProvider.intType;
   InterfaceType get iterableType => typeProvider.iterableType;
   InterfaceType get listType => typeProvider.listType;
+  InterfaceType get nullType => typeProvider.nullType;
   InterfaceType get numType => typeProvider.numType;
   InterfaceType get objectType => typeProvider.objectType;
   InterfaceType get stringType => typeProvider.stringType;
@@ -507,616 +777,8 @@
   }
 }
 
-/**
- * Base class for testing LUB in spec and strong mode.
- * Defines helper functions and tests. Tests here are ones whose behavior is
- * the same in strong and spec mode.
- */
-abstract class LeastUpperBoundTestBase extends BoundTestBase {
-  void test_bottom_function() {
-    _checkLeastUpperBound(bottomType, simpleFunctionType, simpleFunctionType);
-  }
-
-  void test_bottom_interface() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkLeastUpperBound(bottomType, interfaceType, interfaceType);
-  }
-
-  void test_bottom_typeParam() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    _checkLeastUpperBound(bottomType, typeParam, typeParam);
-  }
-
-  void test_directInterfaceCase() {
-    // class A
-    // class B implements A
-    // class C implements B
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    classB.interfaces = <InterfaceType>[typeA];
-    classC.interfaces = <InterfaceType>[typeB];
-    _checkLeastUpperBound(typeB, typeC, typeB);
-  }
-
-  void test_directSubclassCase() {
-    // class A
-    // class B extends A
-    // class C extends B
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    _checkLeastUpperBound(typeB, typeC, typeB);
-  }
-
-  void test_dynamic_bottom() {
-    _checkLeastUpperBound(dynamicType, bottomType, dynamicType);
-  }
-
-  void test_dynamic_function() {
-    _checkLeastUpperBound(dynamicType, simpleFunctionType, dynamicType);
-  }
-
-  void test_dynamic_interface() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkLeastUpperBound(dynamicType, interfaceType, dynamicType);
-  }
-
-  void test_dynamic_typeParam() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    _checkLeastUpperBound(dynamicType, typeParam, dynamicType);
-  }
-
-  void test_dynamic_void() {
-    // Note: _checkLeastUpperBound tests `LUB(x, y)` as well as `LUB(y, x)`
-    _checkLeastUpperBound(dynamicType, voidType, voidType);
-  }
-
-  void test_functionsDifferentRequiredArity() {
-    FunctionType type1 = _functionType([intType, intType]);
-    FunctionType type2 = _functionType([intType, intType, intType]);
-    _checkLeastUpperBound(type1, type2, functionType);
-  }
-
-  void test_functionsIgnoreExtraNamedParams() {
-    FunctionType type1 = _functionType([], named: {'a': intType, 'b': intType});
-    FunctionType type2 = _functionType([], named: {'a': intType, 'c': intType});
-    FunctionType expected = _functionType([], named: {'a': intType});
-    _checkLeastUpperBound(type1, type2, expected);
-  }
-
-  void test_functionsIgnoreExtraPositionalParams() {
-    FunctionType type1 =
-        _functionType([], optional: [intType, intType, stringType]);
-    FunctionType type2 = _functionType([], optional: [intType]);
-    FunctionType expected = _functionType([], optional: [intType]);
-    _checkLeastUpperBound(type1, type2, expected);
-  }
-
-  void test_functionsLubReturnType() {
-    FunctionType type1 = _functionType([], returns: intType);
-    FunctionType type2 = _functionType([], returns: doubleType);
-    FunctionType expected = _functionType([], returns: numType);
-    _checkLeastUpperBound(type1, type2, expected);
-  }
-
-  void test_functionsSameType() {
-    FunctionType type1 = _functionType([stringType, intType, numType],
-        optional: [doubleType], named: {'n': numType}, returns: intType);
-    FunctionType type2 = _functionType([stringType, intType, numType],
-        optional: [doubleType], named: {'n': numType}, returns: intType);
-    FunctionType expected = _functionType([stringType, intType, numType],
-        optional: [doubleType], named: {'n': numType}, returns: intType);
-    _checkLeastUpperBound(type1, type2, expected);
-  }
-
-  void test_interface_function() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkLeastUpperBound(interfaceType, simpleFunctionType, objectType);
-  }
-
-  void test_mixinCase() {
-    // class A
-    // class B extends A
-    // class C extends A
-    // class D extends B with M, N, O, P
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElement classC = ElementFactory.classElement("C", classA.type);
-    ClassElementImpl classD = ElementFactory.classElement("D", classB.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeC = classC.type;
-    InterfaceType typeD = classD.type;
-    classD.mixins = <InterfaceType>[
-      ElementFactory.classElement2("M").type,
-      ElementFactory.classElement2("N").type,
-      ElementFactory.classElement2("O").type,
-      ElementFactory.classElement2("P").type
-    ];
-    _checkLeastUpperBound(typeD, typeC, typeA);
-  }
-
-  void test_nestedFunctionsLubInnerParamTypes() {
-    FunctionType type1 = _functionType([
-      _functionType([stringType, intType, intType])
-    ]);
-    FunctionType type2 = _functionType([
-      _functionType([intType, doubleType, numType])
-    ]);
-    FunctionType expected = _functionType([
-      _functionType([objectType, numType, numType])
-    ]);
-    _checkLeastUpperBound(type1, type2, expected);
-  }
-
-  void test_object() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    DartType typeObject = typeA.element.supertype;
-    // assert that object does not have a super type
-    expect((typeObject.element as ClassElement).supertype, isNull);
-    // assert that both A and B have the same super type of Object
-    expect(typeB.element.supertype, typeObject);
-    // finally, assert that the only least upper bound of A and B is Object
-    _checkLeastUpperBound(typeA, typeB, typeObject);
-  }
-
-  void test_self() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-
-    List<DartType> types = [
-      dynamicType,
-      voidType,
-      bottomType,
-      typeParam,
-      interfaceType,
-      simpleFunctionType
-    ];
-
-    for (DartType type in types) {
-      _checkLeastUpperBound(type, type, type);
-    }
-  }
-
-  void test_sharedSuperclass1() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    _checkLeastUpperBound(typeB, typeC, typeA);
-  }
-
-  void test_sharedSuperclass2() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
-    ClassElementImpl classD = ElementFactory.classElement("D", classC.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeD = classD.type;
-    _checkLeastUpperBound(typeB, typeD, typeA);
-  }
-
-  void test_sharedSuperclass3() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
-    ClassElementImpl classD = ElementFactory.classElement("D", classB.type);
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    InterfaceType typeD = classD.type;
-    _checkLeastUpperBound(typeC, typeD, typeB);
-  }
-
-  void test_sharedSuperclass4() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classA2 = ElementFactory.classElement2("A2");
-    ClassElement classA3 = ElementFactory.classElement2("A3");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeA2 = classA2.type;
-    InterfaceType typeA3 = classA3.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    classB.interfaces = <InterfaceType>[typeA2];
-    classC.interfaces = <InterfaceType>[typeA3];
-    _checkLeastUpperBound(typeB, typeC, typeA);
-  }
-
-  void test_sharedSuperinterface1() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    classB.interfaces = <InterfaceType>[typeA];
-    classC.interfaces = <InterfaceType>[typeA];
-    _checkLeastUpperBound(typeB, typeC, typeA);
-  }
-
-  void test_sharedSuperinterface2() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    ClassElementImpl classD = ElementFactory.classElement2("D");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    InterfaceType typeD = classD.type;
-    classB.interfaces = <InterfaceType>[typeA];
-    classC.interfaces = <InterfaceType>[typeA];
-    classD.interfaces = <InterfaceType>[typeC];
-    _checkLeastUpperBound(typeB, typeD, typeA);
-  }
-
-  void test_sharedSuperinterface3() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    ClassElementImpl classD = ElementFactory.classElement2("D");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    InterfaceType typeD = classD.type;
-    classB.interfaces = <InterfaceType>[typeA];
-    classC.interfaces = <InterfaceType>[typeB];
-    classD.interfaces = <InterfaceType>[typeB];
-    _checkLeastUpperBound(typeC, typeD, typeB);
-  }
-
-  void test_sharedSuperinterface4() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classA2 = ElementFactory.classElement2("A2");
-    ClassElement classA3 = ElementFactory.classElement2("A3");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeA2 = classA2.type;
-    InterfaceType typeA3 = classA3.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    classB.interfaces = <InterfaceType>[typeA, typeA2];
-    classC.interfaces = <InterfaceType>[typeA, typeA3];
-    _checkLeastUpperBound(typeB, typeC, typeA);
-  }
-
-  void test_twoComparables() {
-    _checkLeastUpperBound(stringType, numType, objectType);
-  }
-
-  void test_typeParam_function_bounded() {
-    TypeParameterElementImpl typeParamElement =
-        ElementFactory.typeParameterElement('T');
-    typeParamElement.bound = functionType;
-    DartType typeParam = typeParamElement.type;
-    _checkLeastUpperBound(typeParam, simpleFunctionType, functionType);
-  }
-
-  void test_typeParam_function_noBound() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    _checkLeastUpperBound(typeParam, simpleFunctionType, objectType);
-  }
-
-  void test_typeParam_interface_bounded() {
-    DartType typeA = ElementFactory.classElement2('A', []).type;
-    DartType typeB = ElementFactory.classElement('B', typeA).type;
-    DartType typeC = ElementFactory.classElement('C', typeA).type;
-    TypeParameterElementImpl typeParamElement =
-        ElementFactory.typeParameterElement('T');
-    typeParamElement.bound = typeB;
-    DartType typeParam = typeParamElement.type;
-    _checkLeastUpperBound(typeParam, typeC, typeA);
-  }
-
-  void test_typeParam_interface_noBound() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkLeastUpperBound(typeParam, interfaceType, objectType);
-  }
-
-  void test_typeParameters_same() {
-    // List<int>
-    // List<int>
-    InterfaceType listOfIntType = listType.instantiate(<DartType>[intType]);
-    _checkLeastUpperBound(listOfIntType, listOfIntType, listOfIntType);
-  }
-
-  void test_void() {
-    List<DartType> types = [
-      bottomType,
-      simpleFunctionType,
-      ElementFactory.classElement2('A', []).type,
-      ElementFactory.typeParameterElement('T').type
-    ];
-    for (DartType type in types) {
-      _checkLeastUpperBound(
-          _functionType([], returns: voidType),
-          _functionType([], returns: type),
-          _functionType([], returns: voidType));
-    }
-  }
-}
-
 @reflectiveTest
-class StrongAssignabilityTest extends AbstractTypeSystemTest {
-  void test_isAssignableTo_bottom_isBottom() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    List<DartType> interassignable = <DartType>[
-      dynamicType,
-      objectType,
-      intType,
-      doubleType,
-      numType,
-      stringType,
-      interfaceType,
-      bottomType
-    ];
-
-    _checkGroups(bottomType, interassignable: interassignable);
-  }
-
-  void test_isAssignableTo_call_method() {
-    ClassElementImpl classBottom = ElementFactory.classElement2("B");
-    MethodElement methodBottom =
-        ElementFactory.methodElement("call", objectType, <DartType>[intType]);
-    classBottom.methods = <MethodElement>[methodBottom];
-
-    DartType top =
-        TypeBuilder.function(required: <DartType>[intType], result: objectType);
-    InterfaceType bottom = classBottom.type;
-
-    _checkIsStrictAssignableTo(bottom, top);
-  }
-
-  void test_isAssignableTo_classes() {
-    ClassElement classTop = ElementFactory.classElement2("A");
-    ClassElement classLeft = ElementFactory.classElement("B", classTop.type);
-    ClassElement classRight = ElementFactory.classElement("C", classTop.type);
-    ClassElement classBottom = ElementFactory.classElement("D", classLeft.type)
-      ..interfaces = <InterfaceType>[classRight.type];
-    InterfaceType top = classTop.type;
-    InterfaceType left = classLeft.type;
-    InterfaceType right = classRight.type;
-    InterfaceType bottom = classBottom.type;
-
-    _checkLattice(top, left, right, bottom);
-  }
-
-  void test_isAssignableTo_double() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    List<DartType> interassignable = <DartType>[
-      dynamicType,
-      objectType,
-      doubleType,
-      numType,
-      bottomType
-    ];
-    List<DartType> unrelated = <DartType>[
-      intType,
-      stringType,
-      interfaceType,
-    ];
-
-    _checkGroups(doubleType,
-        interassignable: interassignable, unrelated: unrelated);
-  }
-
-  void test_isAssignableTo_dynamic_isTop() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    List<DartType> interassignable = <DartType>[
-      dynamicType,
-      objectType,
-      intType,
-      doubleType,
-      numType,
-      stringType,
-      interfaceType,
-      bottomType
-    ];
-    _checkGroups(dynamicType, interassignable: interassignable);
-  }
-
-  void test_isAssignableTo_generics() {
-    ClassElementImpl LClass = ElementFactory.classElement2('L', ["T"]);
-    InterfaceType LType = LClass.type;
-    ClassElementImpl MClass = ElementFactory.classElement2('M', ["T"]);
-    DartType typeParam = MClass.typeParameters[0].type;
-    InterfaceType superType = LType.instantiate(<DartType>[typeParam]);
-    MClass.interfaces = <InterfaceType>[superType];
-    InterfaceType MType = MClass.type;
-
-    InterfaceType top = LType.instantiate(<DartType>[dynamicType]);
-    InterfaceType left = MType.instantiate(<DartType>[dynamicType]);
-    InterfaceType right = LType.instantiate(<DartType>[intType]);
-    InterfaceType bottom = MType.instantiate(<DartType>[intType]);
-
-    _checkCrossLattice(top, left, right, bottom);
-  }
-
-  void test_isAssignableTo_int() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    List<DartType> interassignable = <DartType>[
-      dynamicType,
-      objectType,
-      intType,
-      numType,
-      bottomType
-    ];
-    List<DartType> unrelated = <DartType>[
-      doubleType,
-      stringType,
-      interfaceType,
-    ];
-
-    _checkGroups(intType,
-        interassignable: interassignable, unrelated: unrelated);
-  }
-
-  void test_isAssignableTo_named_optional() {
-    DartType r =
-        TypeBuilder.function(required: <DartType>[intType], result: intType);
-    DartType o = TypeBuilder.function(
-        required: <DartType>[], optional: <DartType>[intType], result: intType);
-    DartType n = TypeBuilder.function(
-        required: <DartType>[],
-        named: <String, DartType>{'x': intType},
-        result: intType);
-    DartType rr = TypeBuilder.function(
-        required: <DartType>[intType, intType], result: intType);
-    DartType ro = TypeBuilder.function(
-        required: <DartType>[intType],
-        optional: <DartType>[intType],
-        result: intType);
-    DartType rn = TypeBuilder.function(
-        required: <DartType>[intType],
-        named: <String, DartType>{'x': intType},
-        result: intType);
-    DartType oo = TypeBuilder.function(
-        required: <DartType>[],
-        optional: <DartType>[intType, intType],
-        result: intType);
-    DartType nn = TypeBuilder.function(
-        required: <DartType>[],
-        named: <String, DartType>{'x': intType, 'y': intType},
-        result: intType);
-    DartType nnn = TypeBuilder.function(
-        required: <DartType>[],
-        named: <String, DartType>{'x': intType, 'y': intType, 'z': intType},
-        result: intType);
-
-    _checkGroups(r,
-        interassignable: [r, o, ro, rn, oo], unrelated: [n, rr, nn, nnn]);
-    _checkGroups(o,
-        interassignable: [o, oo], unrelated: [n, rr, ro, rn, nn, nnn]);
-    _checkGroups(n,
-        interassignable: [n, nn, nnn], unrelated: [r, o, rr, ro, rn, oo]);
-    _checkGroups(rr,
-        interassignable: [rr, ro, oo], unrelated: [r, o, n, rn, nn, nnn]);
-    _checkGroups(ro, interassignable: [ro, oo], unrelated: [o, n, rn, nn, nnn]);
-    _checkGroups(rn,
-        interassignable: [rn], unrelated: [o, n, rr, ro, oo, nn, nnn]);
-    _checkGroups(oo, interassignable: [oo], unrelated: [n, rn, nn, nnn]);
-    _checkGroups(nn,
-        interassignable: [nn, nnn], unrelated: [r, o, rr, ro, rn, oo]);
-    _checkGroups(nnn,
-        interassignable: [nnn], unrelated: [r, o, rr, ro, rn, oo]);
-  }
-
-  void test_isAssignableTo_num() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    List<DartType> interassignable = <DartType>[
-      dynamicType,
-      objectType,
-      numType,
-      intType,
-      doubleType,
-      bottomType
-    ];
-    List<DartType> unrelated = <DartType>[
-      stringType,
-      interfaceType,
-    ];
-
-    _checkGroups(numType,
-        interassignable: interassignable, unrelated: unrelated);
-  }
-
-  void test_isAssignableTo_simple_function() {
-    FunctionType top =
-        TypeBuilder.function(required: <DartType>[intType], result: objectType);
-    FunctionType left =
-        TypeBuilder.function(required: <DartType>[intType], result: intType);
-    FunctionType right = TypeBuilder.function(
-        required: <DartType>[objectType], result: objectType);
-    FunctionType bottom =
-        TypeBuilder.function(required: <DartType>[objectType], result: intType);
-
-    _checkCrossLattice(top, left, right, bottom);
-  }
-
-  void test_isAssignableTo_void_functions() {
-    FunctionType top =
-        TypeBuilder.function(required: <DartType>[intType], result: voidType);
-    FunctionType bottom =
-        TypeBuilder.function(required: <DartType>[objectType], result: intType);
-
-    _checkEquivalent(bottom, top);
-  }
-
-  void _checkCrossLattice(
-      DartType top, DartType left, DartType right, DartType bottom) {
-    _checkGroups(top, interassignable: [top, left, right, bottom]);
-    _checkGroups(left,
-        interassignable: [top, left, bottom], unrelated: [right]);
-    _checkGroups(right,
-        interassignable: [top, right, bottom], unrelated: [left]);
-    _checkGroups(bottom, interassignable: [top, left, right, bottom]);
-  }
-
-  void _checkEquivalent(DartType type1, DartType type2) {
-    _checkIsAssignableTo(type1, type2);
-    _checkIsAssignableTo(type2, type1);
-  }
-
-  void _checkGroups(DartType t1,
-      {List<DartType> interassignable, List<DartType> unrelated}) {
-    if (interassignable != null) {
-      for (DartType t2 in interassignable) {
-        _checkEquivalent(t1, t2);
-      }
-    }
-    if (unrelated != null) {
-      for (DartType t2 in unrelated) {
-        _checkUnrelated(t1, t2);
-      }
-    }
-  }
-
-  void _checkIsAssignableTo(DartType type1, DartType type2) {
-    expect(typeSystem.isAssignableTo(type1, type2), true);
-  }
-
-  void _checkIsNotAssignableTo(DartType type1, DartType type2) {
-    expect(typeSystem.isAssignableTo(type1, type2), false);
-  }
-
-  void _checkIsStrictAssignableTo(DartType type1, DartType type2) {
-    _checkIsAssignableTo(type1, type2);
-    _checkIsNotAssignableTo(type2, type1);
-  }
-
-  void _checkLattice(
-      DartType top, DartType left, DartType right, DartType bottom) {
-    _checkGroups(top, interassignable: <DartType>[top, left, right, bottom]);
-    _checkGroups(left,
-        interassignable: <DartType>[top, left, bottom],
-        unrelated: <DartType>[right]);
-    _checkGroups(right,
-        interassignable: <DartType>[top, right, bottom],
-        unrelated: <DartType>[left]);
-    _checkGroups(bottom, interassignable: <DartType>[top, left, right, bottom]);
-  }
-
-  void _checkUnrelated(DartType type1, DartType type2) {
-    _checkIsNotAssignableTo(type1, type2);
-    _checkIsNotAssignableTo(type2, type1);
-  }
-}
-
-@reflectiveTest
-class StrongGenericFunctionInferenceTest extends AbstractTypeSystemTest {
+class GenericFunctionInferenceTest extends AbstractTypeSystemTest {
   void test_boundedByAnotherTypeParameter() {
     // <TFrom, TTo extends Iterable<TFrom>>(TFrom) -> TTo
     var tFrom = TypeBuilder.variable('TFrom');
@@ -1412,11 +1074,8 @@
   }
 }
 
-/**
- * Tests GLB, which only exists in strong mode.
- */
 @reflectiveTest
-class StrongGreatestLowerBoundTest extends BoundTestBase {
+class GreatestLowerBoundTest extends BoundTestBase {
   void setUp() {
     super.setUp();
     typeSystem = new Dart2TypeSystem(typeProvider);
@@ -1732,20 +1391,19 @@
   }
 }
 
-/**
- * Tests LUB in strong mode.
- *
- * Tests defined in this class are ones whose behavior is spec mode-specific.
- * In particular, function parameters are compared using LUB in spec mode, but
- * GLB in strong mode.
- */
 @reflectiveTest
-class StrongLeastUpperBoundTest extends LeastUpperBoundTestBase {
+class LeastUpperBoundFunctionsTest extends BoundTestBase {
   void setUp() {
     super.setUp();
     typeSystem = new Dart2TypeSystem(typeProvider);
   }
 
+  void test_functionsDifferentRequiredArity() {
+    FunctionType type1 = _functionType([intType, intType]);
+    FunctionType type2 = _functionType([intType, intType, intType]);
+    _checkLeastUpperBound(type1, type2, functionType);
+  }
+
   void test_functionsFuzzyArrows() {
     FunctionType type1 = _functionType([dynamicType]);
     FunctionType type2 = _functionType([intType]);
@@ -1776,6 +1434,149 @@
     _checkLeastUpperBound(type1, type2, expected);
   }
 
+  void test_functionsIgnoreExtraNamedParams() {
+    FunctionType type1 = _functionType([], named: {'a': intType, 'b': intType});
+    FunctionType type2 = _functionType([], named: {'a': intType, 'c': intType});
+    FunctionType expected = _functionType([], named: {'a': intType});
+    _checkLeastUpperBound(type1, type2, expected);
+  }
+
+  void test_functionsIgnoreExtraPositionalParams() {
+    FunctionType type1 =
+        _functionType([], optional: [intType, intType, stringType]);
+    FunctionType type2 = _functionType([], optional: [intType]);
+    FunctionType expected = _functionType([], optional: [intType]);
+    _checkLeastUpperBound(type1, type2, expected);
+  }
+
+  void test_functionsLubReturnType() {
+    FunctionType type1 = _functionType([], returns: intType);
+    FunctionType type2 = _functionType([], returns: doubleType);
+    FunctionType expected = _functionType([], returns: numType);
+    _checkLeastUpperBound(type1, type2, expected);
+  }
+
+  void test_functionsSameType() {
+    FunctionType type1 = _functionType([stringType, intType, numType],
+        optional: [doubleType], named: {'n': numType}, returns: intType);
+    FunctionType type2 = _functionType([stringType, intType, numType],
+        optional: [doubleType], named: {'n': numType}, returns: intType);
+    FunctionType expected = _functionType([stringType, intType, numType],
+        optional: [doubleType], named: {'n': numType}, returns: intType);
+    _checkLeastUpperBound(type1, type2, expected);
+  }
+}
+
+@reflectiveTest
+class LeastUpperBoundTest extends BoundTestBase {
+  void setUp() {
+    super.setUp();
+    typeSystem = new Dart2TypeSystem(typeProvider);
+  }
+
+  void test_bottom_function() {
+    _checkLeastUpperBound(bottomType, simpleFunctionType, simpleFunctionType);
+  }
+
+  void test_bottom_interface() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    _checkLeastUpperBound(bottomType, interfaceType, interfaceType);
+  }
+
+  void test_bottom_typeParam() {
+    DartType typeParam = ElementFactory.typeParameterElement('T').type;
+    _checkLeastUpperBound(bottomType, typeParam, typeParam);
+  }
+
+  void test_directInterfaceCase() {
+    // class A
+    // class B implements A
+    // class C implements B
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    ClassElementImpl classC = ElementFactory.classElement2("C");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    classB.interfaces = <InterfaceType>[typeA];
+    classC.interfaces = <InterfaceType>[typeB];
+    _checkLeastUpperBound(typeB, typeC, typeB);
+  }
+
+  void test_directSubclassCase() {
+    // class A
+    // class B extends A
+    // class C extends B
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    _checkLeastUpperBound(typeB, typeC, typeB);
+  }
+
+  void test_dynamic_bottom() {
+    _checkLeastUpperBound(dynamicType, bottomType, dynamicType);
+  }
+
+  void test_dynamic_function() {
+    _checkLeastUpperBound(dynamicType, simpleFunctionType, dynamicType);
+  }
+
+  void test_dynamic_interface() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    _checkLeastUpperBound(dynamicType, interfaceType, dynamicType);
+  }
+
+  void test_dynamic_typeParam() {
+    DartType typeParam = ElementFactory.typeParameterElement('T').type;
+    _checkLeastUpperBound(dynamicType, typeParam, dynamicType);
+  }
+
+  void test_dynamic_void() {
+    // Note: _checkLeastUpperBound tests `LUB(x, y)` as well as `LUB(y, x)`
+    _checkLeastUpperBound(dynamicType, voidType, voidType);
+  }
+
+  void test_interface_function() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    _checkLeastUpperBound(interfaceType, simpleFunctionType, objectType);
+  }
+
+  void test_mixinCase() {
+    // class A
+    // class B extends A
+    // class C extends A
+    // class D extends B with M, N, O, P
+    ClassElement classA = ElementFactory.classElement2("A");
+    ClassElement classB = ElementFactory.classElement("B", classA.type);
+    ClassElement classC = ElementFactory.classElement("C", classA.type);
+    ClassElementImpl classD = ElementFactory.classElement("D", classB.type);
+    InterfaceType typeA = classA.type;
+    InterfaceType typeC = classC.type;
+    InterfaceType typeD = classD.type;
+    classD.mixins = <InterfaceType>[
+      ElementFactory.classElement2("M").type,
+      ElementFactory.classElement2("N").type,
+      ElementFactory.classElement2("O").type,
+      ElementFactory.classElement2("P").type
+    ];
+    _checkLeastUpperBound(typeD, typeC, typeA);
+  }
+
+  void test_nestedFunctionsLubInnerParamTypes() {
+    FunctionType type1 = _functionType([
+      _functionType([stringType, intType, intType])
+    ]);
+    FunctionType type2 = _functionType([
+      _functionType([intType, doubleType, numType])
+    ]);
+    FunctionType expected = _functionType([
+      _functionType([objectType, numType, numType])
+    ]);
+    _checkLeastUpperBound(type1, type2, expected);
+  }
+
   void test_nestedNestedFunctionsGlbInnermostParamTypes() {
     FunctionType type1 = _functionType([
       _functionType([
@@ -1795,6 +1596,148 @@
     _checkLeastUpperBound(type1, type2, expected);
   }
 
+  void test_object() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    DartType typeObject = typeA.element.supertype;
+    // assert that object does not have a super type
+    expect((typeObject.element as ClassElement).supertype, isNull);
+    // assert that both A and B have the same super type of Object
+    expect(typeB.element.supertype, typeObject);
+    // finally, assert that the only least upper bound of A and B is Object
+    _checkLeastUpperBound(typeA, typeB, typeObject);
+  }
+
+  void test_self() {
+    DartType typeParam = ElementFactory.typeParameterElement('T').type;
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+
+    List<DartType> types = [
+      dynamicType,
+      voidType,
+      bottomType,
+      typeParam,
+      interfaceType,
+      simpleFunctionType
+    ];
+
+    for (DartType type in types) {
+      _checkLeastUpperBound(type, type, type);
+    }
+  }
+
+  void test_sharedSuperclass1() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    _checkLeastUpperBound(typeB, typeC, typeA);
+  }
+
+  void test_sharedSuperclass2() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
+    ClassElementImpl classD = ElementFactory.classElement("D", classC.type);
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeD = classD.type;
+    _checkLeastUpperBound(typeB, typeD, typeA);
+  }
+
+  void test_sharedSuperclass3() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
+    ClassElementImpl classD = ElementFactory.classElement("D", classB.type);
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    InterfaceType typeD = classD.type;
+    _checkLeastUpperBound(typeC, typeD, typeB);
+  }
+
+  void test_sharedSuperclass4() {
+    ClassElement classA = ElementFactory.classElement2("A");
+    ClassElement classA2 = ElementFactory.classElement2("A2");
+    ClassElement classA3 = ElementFactory.classElement2("A3");
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
+    InterfaceType typeA = classA.type;
+    InterfaceType typeA2 = classA2.type;
+    InterfaceType typeA3 = classA3.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    classB.interfaces = <InterfaceType>[typeA2];
+    classC.interfaces = <InterfaceType>[typeA3];
+    _checkLeastUpperBound(typeB, typeC, typeA);
+  }
+
+  void test_sharedSuperinterface1() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    ClassElementImpl classC = ElementFactory.classElement2("C");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    classB.interfaces = <InterfaceType>[typeA];
+    classC.interfaces = <InterfaceType>[typeA];
+    _checkLeastUpperBound(typeB, typeC, typeA);
+  }
+
+  void test_sharedSuperinterface2() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    ClassElementImpl classC = ElementFactory.classElement2("C");
+    ClassElementImpl classD = ElementFactory.classElement2("D");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    InterfaceType typeD = classD.type;
+    classB.interfaces = <InterfaceType>[typeA];
+    classC.interfaces = <InterfaceType>[typeA];
+    classD.interfaces = <InterfaceType>[typeC];
+    _checkLeastUpperBound(typeB, typeD, typeA);
+  }
+
+  void test_sharedSuperinterface3() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    ClassElementImpl classC = ElementFactory.classElement2("C");
+    ClassElementImpl classD = ElementFactory.classElement2("D");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    InterfaceType typeD = classD.type;
+    classB.interfaces = <InterfaceType>[typeA];
+    classC.interfaces = <InterfaceType>[typeB];
+    classD.interfaces = <InterfaceType>[typeB];
+    _checkLeastUpperBound(typeC, typeD, typeB);
+  }
+
+  void test_sharedSuperinterface4() {
+    ClassElement classA = ElementFactory.classElement2("A");
+    ClassElement classA2 = ElementFactory.classElement2("A2");
+    ClassElement classA3 = ElementFactory.classElement2("A3");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    ClassElementImpl classC = ElementFactory.classElement2("C");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeA2 = classA2.type;
+    InterfaceType typeA3 = classA3.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    classB.interfaces = <InterfaceType>[typeA, typeA2];
+    classC.interfaces = <InterfaceType>[typeA, typeA3];
+    _checkLeastUpperBound(typeB, typeC, typeA);
+  }
+
+  void test_twoComparables() {
+    _checkLeastUpperBound(stringType, numType, objectType);
+  }
+
   void test_typeParam_boundedByParam() {
     TypeParameterElementImpl typeParamElementT =
         ElementFactory.typeParameterElement('T');
@@ -1827,6 +1770,36 @@
     _checkLeastUpperBound(s, u, AType.instantiate([objectType]));
   }
 
+  void test_typeParam_function_bounded() {
+    TypeParameterElementImpl typeParamElement =
+        ElementFactory.typeParameterElement('T');
+    typeParamElement.bound = functionType;
+    DartType typeParam = typeParamElement.type;
+    _checkLeastUpperBound(typeParam, simpleFunctionType, functionType);
+  }
+
+  void test_typeParam_function_noBound() {
+    DartType typeParam = ElementFactory.typeParameterElement('T').type;
+    _checkLeastUpperBound(typeParam, simpleFunctionType, objectType);
+  }
+
+  void test_typeParam_interface_bounded() {
+    DartType typeA = ElementFactory.classElement2('A', []).type;
+    DartType typeB = ElementFactory.classElement('B', typeA).type;
+    DartType typeC = ElementFactory.classElement('C', typeA).type;
+    TypeParameterElementImpl typeParamElement =
+        ElementFactory.typeParameterElement('T');
+    typeParamElement.bound = typeB;
+    DartType typeParam = typeParamElement.type;
+    _checkLeastUpperBound(typeParam, typeC, typeA);
+  }
+
+  void test_typeParam_interface_noBound() {
+    DartType typeParam = ElementFactory.typeParameterElement('T').type;
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    _checkLeastUpperBound(typeParam, interfaceType, objectType);
+  }
+
   /// Check least upper bound of the same class with different type parameters.
   void test_typeParameters_different() {
     // class List<int>
@@ -1838,6 +1811,13 @@
     _checkLeastUpperBound(listOfIntType, listOfDoubleType, listOfNum);
   }
 
+  void test_typeParameters_same() {
+    // List<int>
+    // List<int>
+    InterfaceType listOfIntType = listType.instantiate(<DartType>[intType]);
+    _checkLeastUpperBound(listOfIntType, listOfIntType, listOfIntType);
+  }
+
   /// Check least upper bound of two related classes with different
   /// type parameters.
   void test_typeParametersAndClass_different() {
@@ -1849,32 +1829,113 @@
     // TODO(leafp): this should be iterableOfNumType
     _checkLeastUpperBound(listOfIntType, iterableOfDoubleType, objectType);
   }
+
+  void test_void() {
+    List<DartType> types = [
+      bottomType,
+      simpleFunctionType,
+      ElementFactory.classElement2('A', []).type,
+      ElementFactory.typeParameterElement('T').type
+    ];
+    for (DartType type in types) {
+      _checkLeastUpperBound(
+          _functionType([], returns: voidType),
+          _functionType([], returns: type),
+          _functionType([], returns: voidType));
+    }
+  }
 }
 
 @reflectiveTest
-class StrongSubtypingTest {
-  TypeProvider typeProvider;
-  TypeSystem typeSystem;
-
-  DartType get bottomType => typeProvider.bottomType;
-  InterfaceType get doubleType => typeProvider.doubleType;
-  DartType get dynamicType => typeProvider.dynamicType;
-  InterfaceType get functionType => typeProvider.functionType;
-  InterfaceType get futureOrType => typeProvider.futureOrType;
-  InterfaceType get intType => typeProvider.intType;
-  InterfaceType get listType => typeProvider.listType;
-  InterfaceType get numType => typeProvider.numType;
-  InterfaceType get objectType => typeProvider.objectType;
-  InterfaceType get stringType => typeProvider.stringType;
-  DartType get voidType => VoidTypeImpl.instance;
-
+class NonNullableSubtypingTest extends SubtypingTestBase {
+  @override
   void setUp() {
-    typeProvider = AnalysisContextFactory.contextWithCore(
+    typeProvider = AnalysisContextFactory.contextWithCoreAndOptions(
+            new AnalysisOptionsImpl()
+              ..contextFeatures = FeatureSet.forTesting(
+                  additionalFeatures: [Feature.non_nullable]),
             resourceProvider: new MemoryResourceProvider())
         .typeProvider;
+
+    // TypeSystem should use the context type provider.
     typeSystem = new Dart2TypeSystem(typeProvider);
+
+    LibraryElement coreLibrary = typeProvider.objectType.element.library;
+    LibraryElement asyncLibrary = typeProvider.streamType.element.library;
+
+    // Get a non-nullable type provider for convience during the test.
+    typeProvider = new NonNullableTypeProvider(coreLibrary, asyncLibrary);
   }
 
+  void test_int_nullableTypes() {
+    List<DartType> equivalents = <DartType>[
+      intType,
+      _star(intType),
+    ];
+    List<DartType> supertypes = <DartType>[
+      _question(intType),
+      objectType,
+      _question(objectType),
+    ];
+    List<DartType> unrelated = <DartType>[doubleType, nullType];
+    _checkGroups(intType,
+        equivalents: equivalents, supertypes: supertypes, unrelated: unrelated);
+  }
+
+  void test_intQuestion_nullableTypes() {
+    List<DartType> equivalents = <DartType>[
+      _question(intType),
+      _star(intType),
+    ];
+    List<DartType> subtypes = <DartType>[
+      intType,
+      nullType,
+    ];
+    List<DartType> supertypes = <DartType>[
+      _question(numType),
+      _star(numType),
+      _question(objectType),
+      _star(objectType),
+    ];
+    List<DartType> unrelated = <DartType>[doubleType, numType, objectType];
+    _checkGroups(_question(intType),
+        equivalents: equivalents,
+        supertypes: supertypes,
+        unrelated: unrelated,
+        subtypes: subtypes);
+  }
+
+  void test_intStar_nullableTypes() {
+    List<DartType> equivalents = <DartType>[
+      intType,
+      _question(intType),
+      _star(intType),
+    ];
+    List<DartType> subtypes = <DartType>[nullType];
+    List<DartType> supertypes = <DartType>[
+      numType,
+      _question(numType),
+      _star(numType),
+      objectType,
+      _question(objectType),
+    ];
+    List<DartType> unrelated = <DartType>[doubleType];
+    _checkGroups(_star(intType),
+        equivalents: equivalents,
+        supertypes: supertypes,
+        unrelated: unrelated,
+        subtypes: subtypes);
+  }
+
+  DartType _question(DartType dartType) =>
+      (dartType as TypeImpl).withNullability(NullabilitySuffix.question);
+
+  DartType _star(DartType dartType) =>
+      (dartType as TypeImpl).withNullability(NullabilitySuffix.star);
+}
+
+@reflectiveTest
+class SubtypingTest extends SubtypingTestBase {
   void test_bottom_isBottom() {
     DartType interfaceType = ElementFactory.classElement2('A', []).type;
     List<DartType> equivalents = <DartType>[bottomType];
@@ -2184,6 +2245,31 @@
     ];
     _checkGroups(voidType, equivalents: equivalents, subtypes: subtypes);
   }
+}
+
+class SubtypingTestBase {
+  TypeProvider typeProvider;
+  TypeSystem typeSystem;
+
+  DartType get bottomType => typeProvider.bottomType;
+  InterfaceType get doubleType => typeProvider.doubleType;
+  DartType get dynamicType => typeProvider.dynamicType;
+  InterfaceType get functionType => typeProvider.functionType;
+  InterfaceType get futureOrType => typeProvider.futureOrType;
+  InterfaceType get intType => typeProvider.intType;
+  InterfaceType get listType => typeProvider.listType;
+  DartType get nullType => typeProvider.nullType;
+  InterfaceType get numType => typeProvider.numType;
+  InterfaceType get objectType => typeProvider.objectType;
+  InterfaceType get stringType => typeProvider.stringType;
+  DartType get voidType => VoidTypeImpl.instance;
+
+  void setUp() {
+    typeProvider = AnalysisContextFactory.contextWithCore(
+            resourceProvider: new MemoryResourceProvider())
+        .typeProvider;
+    typeSystem = new Dart2TypeSystem(typeProvider);
+  }
 
   void _checkEquivalent(DartType type1, DartType type2) {
     _checkIsSubtypeOf(type1, type2);
@@ -2218,7 +2304,8 @@
   }
 
   void _checkIsNotSubtypeOf(DartType type1, DartType type2) {
-    expect(typeSystem.isSubtypeOf(type1, type2), false);
+    expect(typeSystem.isSubtypeOf(type1, type2), false,
+        reason: '$type1 was not supposed to be a subtype of $type2');
   }
 
   void _checkIsStrictSubtypeOf(DartType type1, DartType type2) {
@@ -2227,7 +2314,8 @@
   }
 
   void _checkIsSubtypeOf(DartType type1, DartType type2) {
-    expect(typeSystem.isSubtypeOf(type1, type2), true);
+    expect(typeSystem.isSubtypeOf(type1, type2), true,
+        reason: '$type1 is not a subtype of $type2');
   }
 
   void _checkLattice(
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index 8463f41..858c95e 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -1185,9 +1186,12 @@
   CompilationUnit _parseUnit(String code) {
     GatheringErrorListener listener = new GatheringErrorListener();
     CharSequenceReader reader = new CharSequenceReader(code);
-    Scanner scanner = new Scanner(null, reader, listener);
+    var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
+    Scanner scanner = new Scanner(null, reader, listener)
+      ..configureFeatures(featureSet);
     Token token = scanner.tokenize();
-    Parser parser = new Parser(NonExistingSource.unknown, listener);
+    Parser parser =
+        new Parser(NonExistingSource.unknown, listener, featureSet: featureSet);
     CompilationUnit unit = parser.parseCompilationUnit(token);
     expect(unit, isNotNull);
     listener.assertNoErrors();
diff --git a/pkg/analyzer/test/parse_compilation_unit_test.dart b/pkg/analyzer/test/parse_compilation_unit_test.dart
index 899f832..3fec6a9 100644
--- a/pkg/analyzer/test/parse_compilation_unit_test.dart
+++ b/pkg/analyzer/test/parse_compilation_unit_test.dart
@@ -12,6 +12,46 @@
     expect(unit.toString(), equals("void main() => print('Hello, world!');"));
   });
 
+  group('Supports spread collections', () {
+    var contents = 'var x = [...[]];';
+    void checkCompilationUnit(CompilationUnit unit) {
+      var declaration = unit.declarations.single as TopLevelVariableDeclaration;
+      var listLiteral =
+          declaration.variables.variables.single.initializer as ListLiteral;
+      var spread = listLiteral.elements.single as SpreadElement;
+      expect(spread.expression, TypeMatcher<ListLiteral>());
+    }
+
+    test('with errors suppressed', () {
+      checkCompilationUnit(
+          parseCompilationUnit(contents, suppressErrors: true));
+    });
+    test('with errors enabled', () {
+      checkCompilationUnit(parseCompilationUnit(contents));
+    });
+  });
+
+  group('Supports control flow collections', () {
+    var contents = 'var x = [if (true) 0 else "foo"];';
+    void checkCompilationUnit(CompilationUnit unit) {
+      var declaration = unit.declarations.single as TopLevelVariableDeclaration;
+      var listLiteral =
+          declaration.variables.variables.single.initializer as ListLiteral;
+      var ifElement = listLiteral.elements.single as IfElement;
+      expect(ifElement.condition, TypeMatcher<BooleanLiteral>());
+      expect(ifElement.thenElement, TypeMatcher<IntegerLiteral>());
+      expect(ifElement.elseElement, TypeMatcher<StringLiteral>());
+    }
+
+    test('with errors suppressed', () {
+      checkCompilationUnit(
+          parseCompilationUnit(contents, suppressErrors: true));
+    });
+    test('with errors enabled', () {
+      checkCompilationUnit(parseCompilationUnit(contents));
+    });
+  });
+
   test("throws errors for an invalid compilation unit", () {
     expect(() {
       parseCompilationUnit("void main() => print('Hello, world!')",
diff --git a/pkg/analyzer/test/snippets/README.md b/pkg/analyzer/test/snippets/README.md
new file mode 100644
index 0000000..aab390e
--- /dev/null
+++ b/pkg/analyzer/test/snippets/README.md
@@ -0,0 +1 @@
+The 'snippets' directory exists to enable the test in 'verify_docs_test.dart'.
\ No newline at end of file
diff --git a/pkg/analyzer/test/src/command_line/arguments_test.dart b/pkg/analyzer/test/src/command_line/arguments_test.dart
index 3662f70..d9e2e10 100644
--- a/pkg/analyzer/test/src/command_line/arguments_test.dart
+++ b/pkg/analyzer/test/src/command_line/arguments_test.dart
@@ -84,7 +84,7 @@
         createDartSdkManager(resourceProvider, false, result);
     expect(manager, isNotNull);
     expect(manager.defaultSdkDirectory,
-        FolderBasedDartSdk.defaultSdkDirectory(resourceProvider));
+        FolderBasedDartSdk.defaultSdkDirectory(resourceProvider)?.path);
     expect(manager.canUseSummaries, false);
   }
 
@@ -96,8 +96,9 @@
     DartSdkManager manager =
         createDartSdkManager(resourceProvider, true, result);
     expect(manager, isNotNull);
+
     expect(manager.defaultSdkDirectory,
-        FolderBasedDartSdk.defaultSdkDirectory(resourceProvider));
+        FolderBasedDartSdk.defaultSdkDirectory(resourceProvider)?.path);
     expect(manager.canUseSummaries, true);
   }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/dependency/reference_collector_test.dart b/pkg/analyzer/test/src/dart/analysis/dependency/reference_collector_test.dart
index 36027c4..ff7cce5 100644
--- a/pkg/analyzer/test/src/dart/analysis/dependency/reference_collector_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/dependency/reference_collector_test.dart
@@ -5,8 +5,6 @@
 import 'package:analyzer/src/dart/analysis/dependency/library_builder.dart'
     hide buildLibrary;
 import 'package:analyzer/src/dart/analysis/dependency/node.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -20,7 +18,6 @@
     defineReflectiveTests(ImplReferenceCollectorTest);
     defineReflectiveTests(ShadowReferenceCollectorTest);
     defineReflectiveTests(StatementReferenceCollectorTest);
-    defineReflectiveTests(StatementReferenceCollectorTest_SpreadCollections);
     defineReflectiveTests(TypeReferenceCollectorTest);
   });
 }
@@ -2158,14 +2155,6 @@
 }
 
 @reflectiveTest
-class StatementReferenceCollectorTest_SpreadCollections
-    extends StatementReferenceCollectorTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [EnableString.spread_collections];
-}
-
-@reflectiveTest
 class TypeReferenceCollectorTest extends _Base {
   test_dynamic() async {
     var library = await buildTestLibrary(a, r'''
@@ -2213,7 +2202,7 @@
 
   test_function_shadow_typeParameters() async {
     var library = await buildTestLibrary(a, r'''
-A Function<T extends U, U>(B) test() {}
+A Function<T2 extends U2, U2>(B) test() {}
 ''');
     _assertApi(library, 'test', NodeKind.FUNCTION, unprefixed: ['A', 'B']);
   }
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index b116529..40d5bc6 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
@@ -35,8 +36,6 @@
 
 final isDynamicType = new TypeMatcher<DynamicTypeImpl>();
 
-final isUndefinedType = new TypeMatcher<UndefinedTypeImpl>();
-
 final isVoidType = new TypeMatcher<VoidTypeImpl>();
 
 /**
@@ -638,7 +637,7 @@
 
     SimpleIdentifier constructorName = annotation.constructorName;
     expect(constructorName.staticElement, same(constructor));
-    expect(constructorName.staticType.toString(), '(int, {b: int}) → A');
+    expect(constructorName.staticType.toString(), 'A Function(int, {b: int})');
 
     var arguments = annotation.arguments.arguments;
     var parameters = constructor.parameters;
@@ -765,7 +764,8 @@
     expect(prefixed.prefix.staticType, aClass.type);
 
     expect(prefixed.identifier.staticElement, same(constructor));
-    expect(prefixed.identifier.staticType.toString(), '(int, {b: int}) → A');
+    expect(
+        prefixed.identifier.staticType.toString(), 'A Function(int, {b: int})');
 
     expect(annotation.constructorName, isNull);
 
@@ -1081,7 +1081,7 @@
       SimpleIdentifier forTarget = forInvocation.target;
       expect(forTarget.staticElement, itemsElement);
 
-      var closureTypeStr = '(int) → Null';
+      var closureTypeStr = 'Null Function(int)';
       FunctionExpression closure = forInvocation.argumentList.arguments[0];
 
       FunctionElementImpl closureElement = closure.declaredElement;
@@ -1122,7 +1122,7 @@
       SimpleIdentifier forTarget = forInvocation.target;
       expect(forTarget.staticElement, itemsElement);
 
-      var closureTypeStr = '(int) → Null';
+      var closureTypeStr = 'Null Function(int)';
       FunctionExpression closure = forInvocation.argumentList.arguments[0];
 
       FunctionElementImpl closureElement = closure.declaredElement;
@@ -1167,7 +1167,7 @@
     await resolveTestFile();
 
     var closure = findNode.functionExpression('<T>() =>');
-    assertType(closure, '<T>() → List<T>');
+    assertType(closure, 'List<T> Function<T>()');
 
     FunctionElementImpl closureElement = closure.declaredElement;
     expect(closureElement.enclosingElement, findElement.function('main'));
@@ -1547,7 +1547,7 @@
 
     var invocation = findNode.methodInvocation('loadLibrary');
     assertType(invocation, 'Future<dynamic>');
-    assertInvokeType(invocation, '() → Future<dynamic>');
+    assertInvokeType(invocation, 'Future<dynamic> Function()');
 
     SimpleIdentifier target = invocation.target;
     assertElement(target, import.prefix);
@@ -1555,7 +1555,7 @@
 
     var name = invocation.methodName;
     assertElement(name, import.importedLibrary.loadLibraryFunction);
-    assertType(name, '() → Future<dynamic>');
+    assertType(name, 'Future<dynamic> Function()');
   }
 
   @failingTest
@@ -1574,7 +1574,7 @@
 
     var invocation = findNode.methodInvocation('loadLibrary');
     assertType(invocation, 'Future<dynamic>');
-    assertInvokeType(invocation, '() → Future<dynamic>');
+    assertInvokeType(invocation, 'Future<dynamic> Function()');
 
     SimpleIdentifier target = invocation.target;
     assertElement(target, import.prefix);
@@ -1582,7 +1582,7 @@
 
     var name = invocation.methodName;
     assertElement(name, import.importedLibrary.loadLibraryFunction);
-    assertType(name, '() → Future<dynamic>');
+    assertType(name, 'Future<dynamic> Function()');
 
     var bRef = invocation.argumentList.arguments[0];
     assertElement(bRef, findElement.topGet('b'));
@@ -1605,7 +1605,7 @@
     var import = findElement.import('package:test/a.dart');
 
     var prefixed = findNode.prefixed('a.loadLibrary');
-    assertType(prefixed, '() → Future<dynamic>');
+    assertType(prefixed, 'Future<dynamic> Function()');
 
     var prefix = prefixed.prefix;
     assertElement(prefix, import.prefix);
@@ -1613,7 +1613,7 @@
 
     var identifier = prefixed.identifier;
     assertElement(identifier, import.importedLibrary.loadLibraryFunction);
-    assertType(identifier, '() → Future<dynamic>');
+    assertType(identifier, 'Future<dynamic> Function()');
   }
 
   test_deferredImport_variable() async {
@@ -1816,7 +1816,7 @@
 
     ExpressionStatement statement = mainStatements[0];
     MethodInvocation invocation = statement.expression;
-    expect(invocation.staticInvokeType.toString(), '() → String');
+    expect(invocation.staticInvokeType.toString(), 'String Function()');
 
     MethodElement methodElement = invocation.methodName.staticElement;
     expect(methodElement.name, 'toString');
@@ -1837,12 +1837,12 @@
     VariableDeclarationStatement statement = statements[0];
 
     TypeName typeName = statement.variables.type;
-    expect(typeName.type, isUndefinedType);
+    expect(typeName.type, isDynamicType);
     expect(typeName.typeArguments.arguments[0].type, typeProvider.intType);
 
     VariableDeclaration vNode = statement.variables.variables[0];
-    expect(vNode.name.staticType, isUndefinedType);
-    expect(vNode.declaredElement.type, isUndefinedType);
+    expect(vNode.name.staticType, isDynamicType);
+    expect(vNode.declaredElement.type, isDynamicType);
   }
 
   test_field_context() async {
@@ -1946,7 +1946,7 @@
     expect(p.declaredElement, same(pElement));
 
     expect(p.identifier.staticElement, same(pElement));
-    expect(p.identifier.staticType.toString(), '(int) → String');
+    expect(p.identifier.staticType.toString(), 'String Function(int)');
 
     {
       FunctionType type = p.identifier.staticType;
@@ -2045,7 +2045,7 @@
 
     ExpressionStatement statement = mainStatements[0];
     MethodInvocation invocation = statement.expression;
-    expect(invocation.staticInvokeType.toString(), '(int) → void');
+    expect(invocation.staticInvokeType.toString(), 'void Function(int)');
     // TODO(scheglov) Check for MethodElement
 //    expect(invocation.methodName.staticElement, same(mElement));
   }
@@ -2081,7 +2081,7 @@
     FunctionExpressionInvocation invocation = statement.expression;
 
     expect(invocation.staticElement, isNull);
-    expect(invocation.staticInvokeType.toString(), '(String) → int');
+    expect(invocation.staticInvokeType.toString(), 'int Function(String)');
     expect(invocation.staticType, typeProvider.intType);
 
     List<TypeAnnotation> typeArguments = invocation.typeArguments.arguments;
@@ -2108,7 +2108,7 @@
 ''');
     await resolveTestFile();
     var f = findNode.simple('f;');
-    assertType(f, '<T>(T) → void');
+    assertType(f, 'void Function<T>(T)');
     var fType = f.staticType as FunctionType;
     var fTypeTypeParameter = fType.typeFormals[0];
     var fTypeParameter = fType.normalParameterTypes[0] as TypeParameterType;
@@ -2711,7 +2711,7 @@
 
     var invocation = findNode.methodInvocation('codeUnitAt');
     assertType(invocation, 'int');
-    assertInvokeType(invocation, '(int) → int');
+    assertInvokeType(invocation, 'int Function(int)');
     assertElement(invocation.methodName, stringElement.getMethod('codeUnitAt'));
 
     var aRef = invocation.target;
@@ -2735,7 +2735,7 @@
 
     var invocation = findNode.methodInvocation('m();');
     assertType(invocation, 'int');
-    assertInvokeType(invocation, '() → int');
+    assertInvokeType(invocation, 'int Function()');
     assertElement(invocation.methodName, findElement.method('m'));
   }
 
@@ -2751,7 +2751,7 @@
 
     var invocation = findNode.methodInvocation('id(');
     assertType(invocation, 'bool');
-    assertInvokeType(invocation, '(Object, Object) → bool');
+    assertInvokeType(invocation, 'bool Function(Object, Object)');
     assertElement(invocation.methodName, findElement.topGet('id'));
 
     var aRef = invocation.argumentList.arguments[0];
@@ -3043,7 +3043,7 @@
 
     var aRef = findNode.simple('a + 1');
     assertElement(aRef, findElement.method('a'));
-    assertType(aRef, '() → int');
+    assertType(aRef, 'int Function()');
   }
 
   test_invalid_fieldInitializer_this() async {
@@ -3356,7 +3356,7 @@
 
     var invocation = findNode.methodInvocation('m(a)');
     assertElement(invocation.methodName, m);
-    assertType(invocation.methodName, '() → void');
+    assertType(invocation.methodName, 'void Function()');
     assertType(invocation, 'void');
 
     var aRef = invocation.argumentList.arguments[0];
@@ -3378,7 +3378,7 @@
 
     var invocation = findNode.methodInvocation('f(p: a');
     assertElement(invocation.methodName, f);
-    assertType(invocation.methodName, '({p: dynamic}) → void');
+    assertType(invocation.methodName, 'void Function({p: dynamic})');
     assertType(invocation, 'void');
 
     NamedExpression arg0 = invocation.argumentList.arguments[0];
@@ -3404,7 +3404,7 @@
 
     var invocation = findNode.methodInvocation('f(p: a');
     assertElement(invocation.methodName, f);
-    assertType(invocation.methodName, '({p: dynamic}) → void');
+    assertType(invocation.methodName, 'void Function({p: dynamic})');
     assertType(invocation, 'void');
 
     NamedExpression arg0 = invocation.argumentList.arguments[0];
@@ -3451,7 +3451,7 @@
 
     var invocation = findNode.methodInvocation('m(a)');
     assertElement(invocation.methodName, m);
-    assertType(invocation.methodName, '() → void');
+    assertType(invocation.methodName, 'void Function()');
     assertType(invocation, 'void');
 
     var aRef = invocation.argumentList.arguments[0];
@@ -3497,7 +3497,7 @@
 
     var invocation = findNode.methodInvocation('f(a)');
     assertElement(invocation.methodName, f);
-    assertType(invocation.methodName, '() → void');
+    assertType(invocation.methodName, 'void Function()');
     assertType(invocation, 'void');
 
     var aRef = invocation.argumentList.arguments[0];
@@ -3519,7 +3519,7 @@
 
     var invocation = findNode.methodInvocation('f(a)');
     assertElement(invocation.methodName, f);
-    assertType(invocation.methodName, '() → void');
+    assertType(invocation.methodName, 'void Function()');
     assertType(invocation, 'void');
 
     var aRef = invocation.argumentList.arguments[0];
@@ -4033,7 +4033,7 @@
   var v = f(1, '2');
 }
 ''');
-    String fTypeString = '(int, String) → double';
+    String fTypeString = 'double Function(int, String)';
 
     await resolveTestFile();
     List<Statement> mainStatements = _getMainStatements(result);
@@ -4140,7 +4140,7 @@
     }
 
     expect(fElement, isNotNull);
-    expect(fElement.type.toString(), '<T,U>(T, U) → T');
+    expect(fElement.type.toString(), 'T Function<T,U>(T, U)');
 
     expect(fNode.name.staticElement, same(fElement));
     expect(fNode.name.staticType, fElement.type);
@@ -4188,7 +4188,8 @@
     expect(fInvocation.staticType, typeProvider.intType);
 
     assertTypeNull(fInvocation.methodName);
-    expect(fInvocation.staticInvokeType.toString(), '(int, String) → int');
+    expect(
+        fInvocation.staticInvokeType.toString(), 'int Function(int, String)');
   }
 
   test_local_function_generic_f_bounded() async {
@@ -4205,7 +4206,7 @@
     FunctionElement fElement = fNode.declaredElement;
 
     expect(fElement.type.toString(),
-        '<T extends U,U,V extends U>(T, U, V) → void');
+        'void Function<T extends U,U,V extends U>(T, U, V)');
     var tElement = fElement.typeParameters[0];
     var uElement = fElement.typeParameters[1];
     var vElement = fElement.typeParameters[2];
@@ -4226,7 +4227,7 @@
     FunctionDeclaration fNode = fStatement.functionDeclaration;
     FunctionElement fElement = fNode.declaredElement;
 
-    expect(fElement.type.toString(), '<T>({x: T}) → void');
+    expect(fElement.type.toString(), 'void Function<T>({x: T})');
     var tElement = fElement.typeParameters[0];
     expect(fElement.type.typeFormals[0], same(tElement));
     expect((fElement.type.parameters[0].type as TypeParameterType).element,
@@ -4246,7 +4247,7 @@
     FunctionDeclaration fNode = fStatement.functionDeclaration;
     FunctionElement fElement = fNode.declaredElement;
 
-    expect(fElement.type.toString(), '<T>([T]) → void');
+    expect(fElement.type.toString(), 'void Function<T>([T])');
     var tElement = fElement.typeParameters[0];
     expect(fElement.type.typeFormals[0], same(tElement));
     expect((fElement.type.parameters[0].type as TypeParameterType).element,
@@ -4260,7 +4261,7 @@
   f(1, b: '2', c: true);
 }
 ''');
-    String fTypeString = '(int, {b: String, c: bool}) → double';
+    String fTypeString = 'double Function(int, {b: String, c: bool})';
 
     await resolveTestFile();
     List<Statement> mainStatements = _getMainStatements(result);
@@ -4337,7 +4338,7 @@
 
     expect(fNode.returnType, isNull);
     expect(fElement, isNotNull);
-    expect(fElement.type.toString(), '() → Null');
+    expect(fElement.type.toString(), 'Null Function()');
 
     expect(fNode.name.staticElement, same(fElement));
     expect(fNode.name.staticType, fElement.type);
@@ -4352,7 +4353,7 @@
   var v = f(1, '2', true);
 }
 ''');
-    String fTypeString = '(int, [String, bool]) → double';
+    String fTypeString = 'double Function(int, [String, bool])';
 
     await resolveTestFile();
     List<Statement> mainStatements = _getMainStatements(result);
@@ -4430,7 +4431,7 @@
 ''');
     await resolveTestFile();
     var callback = findNode.simple('callback');
-    assertType(callback, '<T extends E>(D) → C');
+    assertType(callback, 'C Function<T extends E>(D)');
     var cReference = findNode.simple('C callback');
     var cElement = findElement.class_('C');
     assertType(cReference, 'C');
@@ -4749,20 +4750,20 @@
 ''');
     await resolveTestFile();
 
-    var mainStatements = _getMainStatements(result);
-    var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
-    var fElement = fDeclaration.functionDeclaration.declaredElement;
-    var tElement = fElement.typeParameters[0];
-    var body = fDeclaration.functionDeclaration.functionExpression.body
-        as BlockFunctionBody;
-    var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
-    var gType = gDeclaration.variables.type as TypeName;
+    var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+    var gType = findNode.typeName('Consumer<T>');
     var gTypeType = gType.type as FunctionType;
-    var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
-    expect(gTypeTypeArgument.element, same(tElement));
+
+    if (!AnalysisDriver.useSummary2) {
+      var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+      expect(gTypeTypeArgument.element, same(tElement));
+    }
+
     var gTypeParameterType =
         gTypeType.namedParameterTypes['u'] as TypeParameterType;
     expect(gTypeParameterType.element, same(tElement));
+
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
@@ -4782,20 +4783,20 @@
 ''');
     await resolveTestFile();
 
-    var mainStatements = _getMainStatements(result);
-    var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
-    var fElement = fDeclaration.functionDeclaration.declaredElement;
-    var tElement = fElement.typeParameters[0];
-    var body = fDeclaration.functionDeclaration.functionExpression.body
-        as BlockFunctionBody;
-    var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
-    var gType = gDeclaration.variables.type as TypeName;
+    var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+    var gType = findNode.typeName('Consumer<T>');
     var gTypeType = gType.type as FunctionType;
-    var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
-    expect(gTypeTypeArgument.element, same(tElement));
+
+    if (!AnalysisDriver.useSummary2) {
+      var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+      expect(gTypeTypeArgument.element, same(tElement));
+    }
+
     var gTypeParameterType =
         gTypeType.normalParameterTypes[0] as TypeParameterType;
     expect(gTypeParameterType.element, same(tElement));
+
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
@@ -4815,20 +4816,20 @@
 ''');
     await resolveTestFile();
 
-    var mainStatements = _getMainStatements(result);
-    var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
-    var fElement = fDeclaration.functionDeclaration.declaredElement;
-    var tElement = fElement.typeParameters[0];
-    var body = fDeclaration.functionDeclaration.functionExpression.body
-        as BlockFunctionBody;
-    var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
-    var gType = gDeclaration.variables.type as TypeName;
+    var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+    var gType = findNode.typeName('Consumer<T>');
     var gTypeType = gType.type as FunctionType;
-    var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
-    expect(gTypeTypeArgument.element, same(tElement));
+
+    if (!AnalysisDriver.useSummary2) {
+      var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+      expect(gTypeTypeArgument.element, same(tElement));
+    }
+
     var gTypeParameterType =
         gTypeType.optionalParameterTypes[0] as TypeParameterType;
     expect(gTypeParameterType.element, same(tElement));
+
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
@@ -4848,19 +4849,19 @@
 ''');
     await resolveTestFile();
 
-    var mainStatements = _getMainStatements(result);
-    var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
-    var fElement = fDeclaration.functionDeclaration.declaredElement;
-    var tElement = fElement.typeParameters[0];
-    var body = fDeclaration.functionDeclaration.functionExpression.body
-        as BlockFunctionBody;
-    var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
-    var gType = gDeclaration.variables.type as TypeName;
+    var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+    var gType = findNode.typeName('Producer<T>');
     var gTypeType = gType.type as FunctionType;
-    var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
-    expect(gTypeTypeArgument.element, same(tElement));
+
+    if (!AnalysisDriver.useSummary2) {
+      var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+      expect(gTypeTypeArgument.element, same(tElement));
+    }
+
     var gTypeReturnType = gTypeType.returnType as TypeParameterType;
     expect(gTypeReturnType.element, same(tElement));
+
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
@@ -4884,7 +4885,7 @@
     FunctionDeclaration main = result.unit.declarations[0];
     expect(main.declaredElement, isNotNull);
     expect(main.name.staticElement, isNotNull);
-    expect(main.name.staticType.toString(), '() → void');
+    expect(main.name.staticType.toString(), 'void Function()');
 
     BlockFunctionBody body = main.functionExpression.body;
     NodeList<Statement> statements = body.block.statements;
@@ -5244,7 +5245,7 @@
   c.f(1, b: '2', c: true);
 }
 ''');
-    String fTypeString = '(int, {b: String, c: bool}) → double';
+    String fTypeString = 'double Function(int, {b: String, c: bool})';
 
     await resolveTestFile();
     ClassDeclaration classDeclaration = result.unit.declarations[0];
@@ -5324,11 +5325,11 @@
     MethodInvocation invocation = statement.expression;
 
     expect(invocation.staticType, typeProvider.doubleType);
-    expect(invocation.staticInvokeType.toString(), '(int) → double');
+    expect(invocation.staticInvokeType.toString(), 'double Function(int)');
 
     SimpleIdentifier methodName = invocation.methodName;
     expect(methodName.staticElement, same(callElement));
-    expect(methodName.staticType.toString(), '(int) → double');
+    expect(methodName.staticType.toString(), 'double Function(int)');
   }
 
   test_methodInvocation_explicitCall_functionTarget() async {
@@ -5351,11 +5352,11 @@
     MethodInvocation invocation = statement.expression;
 
     expect(invocation.staticType, typeProvider.doubleType);
-    expect(invocation.staticInvokeType.toString(), '(int) → double');
+    expect(invocation.staticInvokeType.toString(), 'double Function(int)');
 
     SimpleIdentifier target = invocation.target;
     expect(target.staticElement, same(parameter));
-    expect(target.staticType.toString(), '(int) → double');
+    expect(target.staticType.toString(), 'double Function(int)');
 
     SimpleIdentifier methodName = invocation.methodName;
     expect(methodName.staticElement, isNull);
@@ -5386,7 +5387,7 @@
     MethodInvocation invocation = statement.expression;
     expect(invocation.methodName.staticElement, same(fooElement));
 
-    var invokeTypeStr = '(int) → void';
+    var invokeTypeStr = 'void Function(int)';
     expect(invocation.staticType.toString(), 'void');
     expect(invocation.staticInvokeType.toString(), invokeTypeStr);
   }
@@ -5407,7 +5408,7 @@
       var invocation = findNode.methodInvocation('m(1)');
       List<Expression> arguments = invocation.argumentList.arguments;
 
-      var invokeTypeStr = '(int) → void';
+      var invokeTypeStr = 'void Function(int)';
       assertType(invocation, 'void');
       assertInvokeType(invocation, invokeTypeStr);
 
@@ -5434,15 +5435,20 @@
       var invocation = findNode.methodInvocation('m(1, 2.3)');
       List<Expression> arguments = invocation.argumentList.arguments;
 
-      var invokeTypeStr = '(int, double) → Map<int, double>';
+      var invokeTypeStr = 'Map<int, double> Function(int, double)';
       assertType(invocation, 'Map<int, double>');
       assertInvokeType(invocation, invokeTypeStr);
 
       assertMember(invocation.methodName, 'C<int>', mElement);
-      assertType(invocation.methodName, '<U>(int, U) → Map<int, U>');
+      assertType(invocation.methodName, 'Map<int, U> Function<U>(int, U)');
 
-      _assertArgumentToParameter(arguments[0], mElement.parameters[0]);
-      _assertArgumentToParameter(arguments[1], mElement.parameters[1]);
+      if (AnalysisDriver.useSummary2) {
+        _assertArgumentToParameter2(arguments[0], 'int');
+        _assertArgumentToParameter2(arguments[1], 'double');
+      } else {
+        _assertArgumentToParameter(arguments[0], mElement.parameters[0]);
+        _assertArgumentToParameter(arguments[1], mElement.parameters[1]);
+      }
     }
   }
 
@@ -5558,12 +5564,18 @@
     ExpressionStatement statement = fooStatements[0];
     MethodInvocation invocation = statement.expression;
     expect(invocation.methodName.staticElement, same(fElement));
-    expect(invocation.staticInvokeType.toString(), '(int, {b: int}) → String');
+    expect(invocation.staticInvokeType.toString(),
+        'String Function(int, {b: int})');
     expect(invocation.staticType, typeProvider.stringType);
 
     List<Expression> arguments = invocation.argumentList.arguments;
-    _assertArgumentToParameter(arguments[0], funElement.parameters[0]);
-    _assertArgumentToParameter(arguments[1], funElement.parameters[1]);
+    if (AnalysisDriver.useSummary2) {
+      _assertArgumentToParameter2(arguments[0], 'int');
+      _assertArgumentToParameter2(arguments[1], 'int');
+    } else {
+      _assertArgumentToParameter(arguments[0], funElement.parameters[0]);
+      _assertArgumentToParameter(arguments[1], funElement.parameters[1]);
+    }
   }
 
   test_methodInvocation_notFunction_local_dynamic() async {
@@ -5613,7 +5625,7 @@
     ExpressionStatement statement = mainStatements[0];
     MethodInvocation invocation = statement.expression;
     expect(invocation.methodName.staticElement, same(fElement));
-    expect(invocation.staticInvokeType.toString(), '(int) → String');
+    expect(invocation.staticInvokeType.toString(), 'String Function(int)');
     expect(invocation.staticType, typeProvider.stringType);
 
     List<Expression> arguments = invocation.argumentList.arguments;
@@ -5677,7 +5689,7 @@
       expect(target.staticElement, same(cElement));
       expect(target.staticType, same(cElement.type));
 
-      var invokeTypeStr = '(int) → void';
+      var invokeTypeStr = 'void Function(int)';
       expect(invocation.staticType.toString(), 'void');
       expect(invocation.staticInvokeType.toString(), invokeTypeStr);
       expect(invocation.staticInvokeType.element, same(mElement));
@@ -5699,7 +5711,7 @@
 
       expect(invocation.target, isNull);
 
-      var invokeTypeStr = '(int) → void';
+      var invokeTypeStr = 'void Function(int)';
       expect(invocation.staticType.toString(), 'void');
       expect(invocation.staticInvokeType.toString(), invokeTypeStr);
       expect(invocation.staticInvokeType.element, same(mElement));
@@ -5729,7 +5741,7 @@
     BlockFunctionBody barBody = barNode.body;
     ExpressionStatement fooStatement = barBody.block.statements[0];
     MethodInvocation fooInvocation = fooStatement.expression;
-    expect(fooInvocation.staticInvokeType.toString(), '(C<T>) → T');
+    expect(fooInvocation.staticInvokeType.toString(), 'T Function(C<T>)');
     expect(fooInvocation.staticType.toString(), 'T');
     expect(fooInvocation.staticType.element, same(tElement));
   }
@@ -5741,7 +5753,7 @@
 }
 double f(int a, String b) {}
 ''');
-    String fTypeString = '(int, String) → double';
+    String fTypeString = 'double Function(int, String)';
 
     await resolveTestFile();
     List<Statement> mainStatements = _getMainStatements(result);
@@ -5782,7 +5794,7 @@
 
     // f<bool, String>(true, 'str');
     {
-      String fTypeString = '(bool, String) → void';
+      String fTypeString = 'void Function(bool, String)';
       ExpressionStatement statement = mainStatements[0];
       MethodInvocation invocation = statement.expression;
 
@@ -5818,7 +5830,7 @@
 
     // f(1, 2.3);
     {
-      String fTypeString = '(int, double) → void';
+      String fTypeString = 'void Function(int, double)';
       ExpressionStatement statement = mainStatements[1];
       MethodInvocation invocation = statement.expression;
       List<Expression> arguments = invocation.argumentList.arguments;
@@ -5867,7 +5879,6 @@
     }
   }
 
-  @failingTest
   test_optionalConst_prefixed() async {
     newFile('/test/lib/a.dart', content: r'''
 class C {
@@ -6122,7 +6133,7 @@
     assertTypeName(intRef, intElement, 'int');
 
     var functionRef = findNode.genericFunctionType('Function(double)');
-    assertType(functionRef, '(double) → int');
+    assertType(functionRef, 'int Function(double)');
 
     var doubleRef = findNode.typeName('double) g');
     assertTypeName(doubleRef, doubleElement, 'double');
@@ -6171,7 +6182,7 @@
     await resolveTestFile();
 
     var gRef = findNode.simple('g()++');
-    assertType(gRef, '() → int');
+    assertType(gRef, 'int Function()');
     assertElement(gRef, findElement.parameter('g'));
   }
 
@@ -6388,7 +6399,7 @@
     PrefixedIdentifier prefixed = statement.expression;
 
     expect(prefixed.prefix.staticElement, same(parameter));
-    expect(prefixed.prefix.staticType.toString(), '(int) → double');
+    expect(prefixed.prefix.staticType.toString(), 'double Function(int)');
 
     SimpleIdentifier methodName = prefixed.identifier;
     expect(methodName.staticElement, isNull);
@@ -6751,7 +6762,7 @@
     FunctionDeclaration main = result.unit.declarations[0];
     expect(main.declaredElement, isNotNull);
     expect(main.name.staticElement, isNotNull);
-    expect(main.name.staticType.toString(), '() → void');
+    expect(main.name.staticType.toString(), 'void Function()');
 
     BlockFunctionBody body = main.functionExpression.body;
     NodeList<Statement> statements = body.block.statements;
@@ -7219,7 +7230,7 @@
 
     SimpleIdentifier dName = enumNode.name;
     expect(dName.staticElement, same(enumElement));
-    expect(dName.staticType, typeProvider.typeType);
+    expect(dName.staticType, isNull);
 
     {
       var aElement = enumElement.getField('A');
@@ -7271,7 +7282,7 @@
     {
       ConstructorDeclaration node = cNode.members[0];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(int) → C');
+      expect(node.declaredElement.type.toString(), 'C Function(int)');
       expect(node.returnType.staticElement, same(cElement));
       expect(node.returnType.staticType, typeType);
       expect(node.name, isNull);
@@ -7281,18 +7292,18 @@
     {
       ConstructorDeclaration node = cNode.members[1];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(int) → C');
+      expect(node.declaredElement.type.toString(), 'C Function(int)');
       expect(node.returnType.staticElement, same(cElement));
       expect(node.returnType.staticType, typeType);
       expect(node.name.staticElement, same(node.declaredElement));
-      expect(node.name.staticType.toString(), '(int) → C');
+      expect(node.name.staticType.toString(), 'C Function(int)');
     }
 
     // publicMethod()
     {
       MethodDeclaration node = cNode.members[2];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(double) → int');
+      expect(node.declaredElement.type.toString(), 'int Function(double)');
 
       // method return type
       TypeName returnType = node.returnType;
@@ -7324,7 +7335,7 @@
     {
       MethodDeclaration node = cNode.members[3];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '() → int');
+      expect(node.declaredElement.type.toString(), 'int Function()');
 
       // getter return type
       TypeName returnType = node.returnType;
@@ -7342,7 +7353,7 @@
     {
       MethodDeclaration node = cNode.members[4];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(double) → void');
+      expect(node.declaredElement.type.toString(), 'void Function(double)');
 
       // setter return type
       TypeName returnType = node.returnType;
@@ -7391,7 +7402,7 @@
     {
       FunctionDeclaration node = result.unit.declarations[0];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(double) → int');
+      expect(node.declaredElement.type.toString(), 'int Function(double)');
 
       // function return type
       TypeName returnType = node.returnType;
@@ -7424,7 +7435,7 @@
     {
       FunctionDeclaration node = result.unit.declarations[1];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '() → int');
+      expect(node.declaredElement.type.toString(), 'int Function()');
 
       // getter return type
       TypeName returnType = node.returnType;
@@ -7442,7 +7453,7 @@
     {
       FunctionDeclaration node = result.unit.declarations[2];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(double) → void');
+      expect(node.declaredElement.type.toString(), 'void Function(double)');
 
       // setter return type
       TypeName returnType = node.returnType;
@@ -7660,7 +7671,7 @@
   f(1, b: '2', c: true);
 }
 ''');
-    String fTypeString = '(int, {b: String, c: bool}) → double';
+    String fTypeString = 'double Function(int, {b: String, c: bool})';
 
     await resolveTestFile();
     FunctionDeclaration fDeclaration = result.unit.declarations[0];
@@ -7960,26 +7971,18 @@
 ''');
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit;
-    CompilationUnitElement unitElement = unit.declaredElement;
-    var typeProvider = unitElement.context.typeProvider;
 
-    FunctionTypeAlias alias = unit.declarations[0];
+    FunctionTypeAlias alias = findNode.functionTypeAlias('F<T>');
     GenericTypeAliasElement aliasElement = alias.declaredElement;
-    FunctionType aliasType = aliasElement.type;
 
-    ClassDeclaration cNode = unit.declarations[1];
-
-    FieldDeclaration fDeclaration = cNode.members[0];
-    FunctionType instantiatedAliasType =
-        aliasType.instantiate([typeProvider.intType]);
+    FieldDeclaration fDeclaration = findNode.fieldDeclaration('F<int> f');
 
     TypeName typeName = fDeclaration.fields.type;
-    expect(typeName.type, instantiatedAliasType);
+    expect('${typeName.type}', 'int Function(bool)');
 
     SimpleIdentifier typeIdentifier = typeName.name;
     expect(typeIdentifier.staticElement, same(aliasElement));
-    expect(typeIdentifier.staticType, instantiatedAliasType);
+    expect('${typeIdentifier.staticType}', 'int Function(bool)');
 
     List<TypeAnnotation> typeArguments = typeName.typeArguments.arguments;
     expect(typeArguments, hasLength(1));
@@ -8095,7 +8098,6 @@
     assertType(identifier, 'Type');
   }
 
-  @failingTest
   test_unresolved_instanceCreation_name_11() async {
     addTestFile(r'''
 int arg1, arg2;
@@ -8226,12 +8228,12 @@
     ExpressionStatement statement = statements[0];
 
     InstanceCreationExpression creation = statement.expression;
-    expect(creation.staticType, isUndefinedType);
+    expect(creation.staticType, isDynamicType);
 
     ConstructorName constructorName = creation.constructorName;
 
     TypeName typeName = constructorName.type;
-    expect(typeName.type, isUndefinedType);
+    expect(typeName.type, isDynamicType);
 
     PrefixedIdentifier typePrefixed = typeName.name;
     assertElementNull(typePrefixed);
@@ -8273,12 +8275,12 @@
     ExpressionStatement statement = statements[0];
 
     InstanceCreationExpression creation = statement.expression;
-    expect(creation.staticType, isUndefinedType);
+    expect(creation.staticType, isDynamicType);
 
     ConstructorName constructorName = creation.constructorName;
 
     TypeName typeName = constructorName.type;
-    expect(typeName.type, isUndefinedType);
+    expect(typeName.type, isDynamicType);
 
     PrefixedIdentifier typePrefixed = typeName.name;
     assertElementNull(typePrefixed);
@@ -8750,6 +8752,21 @@
     }
   }
 
+  /// Assert that the [argument] has the [expectedType]. If the [argument] is
+  /// a [NamedExpression], the name must be resolved to the same parameter.
+  void _assertArgumentToParameter2(Expression argument, String expectedType,
+      {DartType memberType}) {
+    ParameterElement actual = argument.staticParameterElement;
+    var actualType = actual.type;
+    expect('$actualType', expectedType);
+
+    if (argument is NamedExpression) {
+      SimpleIdentifier name = argument.name.label;
+      expect(name.staticElement, same(actual));
+      expect(name.staticType, isNull);
+    }
+  }
+
   /// Assert that the given [creation] creates instance of the [classElement].
   /// Limitations: no import prefix, no type arguments, unnamed constructor.
   void _assertConstructorInvocation(
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 5cfbae5..dcc2fad 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -15,7 +15,6 @@
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/status.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -39,6 +38,9 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(AnalysisDriverSchedulerTest);
     defineReflectiveTests(AnalysisDriverTest);
+    if (!AnalysisDriver.useSummary2) {
+      defineReflectiveTests(AnalysisDriverSummary1Test);
+    }
     defineReflectiveTests(CacheAllAnalysisDriverTest);
   });
 }
@@ -344,6 +346,374 @@
 /// TODO(paulberry): migrate this test away from the task model.
 /// See dartbug.com/35734.
 @reflectiveTest
+class AnalysisDriverSummary1Test extends BaseAnalysisDriverTest {
+  test_externalSummaries() async {
+    var a = convertPath('/a.dart');
+    var b = convertPath('/b.dart');
+    newFile(a, content: r'''
+class A {}
+''');
+    newFile(b, content: r'''
+import 'a.dart';
+var a = new A();
+''');
+
+    // Prepare the store with a.dart and everything it needs.
+    SummaryDataStore summaryStore =
+        await createAnalysisDriver().test.getSummaryStore(a);
+
+    // There are at least a.dart and dart:core libraries.
+    String aUri = toUriStr(a);
+    expect(summaryStore.unlinkedMap.keys, contains(aUri));
+    expect(summaryStore.linkedMap.keys, contains(aUri));
+    expect(summaryStore.unlinkedMap.keys, contains('dart:core'));
+    expect(summaryStore.linkedMap.keys, contains('dart:core'));
+
+    // Remove a.dart from the file system.
+    deleteFile(a);
+
+    // We don't need a.dart file when we analyze with the summary store.
+    // Still no analysis errors.
+    AnalysisDriver driver =
+        createAnalysisDriver(externalSummaries: summaryStore);
+    ResolvedUnitResult result = await driver.getResult(b);
+    expect(result.errors, isEmpty);
+  }
+
+  test_externalSummaries_partReuse() async {
+    var a = convertPath('/a.dart');
+    var b = convertPath('/b.dart');
+    var c = convertPath('/c.dart');
+    newFile(a, content: r'''
+library a;
+part 'b.dart';
+class A {}
+''');
+    newFile(b, content: r'''
+part of a;
+class _B {}
+''');
+    newFile(c, content: r'''
+library a;
+import 'a.dart';
+part 'b.dart';
+var a = new A();
+var b = new _B();
+''');
+
+    // Prepare the store with a.dart and everything it needs.
+    SummaryDataStore summaryStore =
+        await createAnalysisDriver().test.getSummaryStore(a);
+
+    String aUri = toUriStr(a);
+    String bUri = toUriStr(b);
+    // There are unlinked units for a.dart and b.dart files.
+    expect(summaryStore.hasUnlinkedUnit(aUri), isTrue);
+    expect(summaryStore.hasUnlinkedUnit(bUri), isTrue);
+    // Only a.dart is linked, because b.dart is not a library.
+    expect(summaryStore.hasLinkedLibrary(aUri), isTrue);
+    expect(summaryStore.hasLinkedLibrary(bUri), isFalse);
+
+    // Remove a.dart from the file system.
+    // Keep b.dart, because we (re)use it as a part.
+    deleteFile(a);
+
+    // We don't need a.dart file when we analyze with the summary store.
+    // We can instantiate the class A the library a.dart.
+    // We can instantiate the class _A the part b.dart.
+    AnalysisDriver driver =
+        createAnalysisDriver(externalSummaries: summaryStore);
+    ResolvedUnitResult result = await driver.getResult(c);
+    expect(result.errors, isEmpty);
+  }
+
+  test_getLibraryByUri_external() async {
+    var a = convertPath('/test/lib/a.dart');
+    var b = convertPath('/test/lib/b.dart');
+
+    String aUriStr = 'package:test/a.dart';
+    String bUriStr = 'package:test/b.dart';
+
+    newFile(a, content: r'''
+part 'b.dart';
+
+class A {}
+''');
+
+    newFile(b, content: r'''
+part of 'a.dart';
+
+class B {}
+''');
+
+    // Prepare the store with package:test/test.dart URI.
+    var store = await createAnalysisDriver().test.getSummaryStore(a);
+
+    // package:test/test.dart is in the store.
+    expect(store.unlinkedMap.keys, contains(aUriStr));
+    expect(store.unlinkedMap.keys, contains(bUriStr));
+    expect(store.linkedMap.keys, contains(aUriStr));
+    expect(store.linkedMap.keys, isNot(contains(bUriStr)));
+
+    // Remove the files from the file system.
+    deleteFile(a);
+    deleteFile(b);
+
+    // We can resynthesize the library from the store.
+    var driver = createAnalysisDriver(externalSummaries: store);
+
+    // Ask by URI, so we get the "external" FileState.
+    var aUri = Uri.parse(aUriStr);
+    var aFile = driver.fsState.getFileForUri(aUri);
+    expect(aFile.uri, aUri);
+    expect(aFile.path, isNull);
+
+    // We still can resynthesize the library.
+    // The URI is known to be external, so we don't talk to the file.
+    var library = await driver.getLibraryByUri(aUriStr);
+    expect(library.getType('A'), isNotNull);
+    expect(library.getType('B'), isNotNull);
+
+    // It is an error to ask for a library when we know that it is a part.
+    expect(() async {
+      await driver.getLibraryByUri(bUriStr);
+    }, throwsArgumentError);
+  }
+
+  test_getLibraryByUri_sdk_analyze() async {
+    LibraryElement coreLibrary = await driver.getLibraryByUri('dart:core');
+    expect(coreLibrary, isNotNull);
+    expect(coreLibrary.getType('Object'), isNotNull);
+    expect(coreLibrary.getType('int'), isNotNull);
+  }
+
+  test_getLibraryByUri_sdk_resynthesize() async {
+    String corePath = sdk.mapDartUri('dart:core').fullName;
+    String asyncPath = sdk.mapDartUri('dart:async').fullName;
+    var sdkStore = await createAnalysisDriver().test.getSummaryStore(corePath);
+
+    // There are dart:core and dart:async in the store.
+    expect(sdkStore.unlinkedMap.keys, contains('dart:core'));
+    expect(sdkStore.unlinkedMap.keys, contains('dart:async'));
+    expect(sdkStore.linkedMap.keys, contains('dart:core'));
+    expect(sdkStore.linkedMap.keys, contains('dart:async'));
+
+    // Remove dart:core and dart:async.
+    // So, the new driver below cannot parse and summarize them.
+    deleteFile(corePath);
+    deleteFile(asyncPath);
+
+    // We still get get dart:core library element.
+    AnalysisDriver driver = createAnalysisDriver(externalSummaries: sdkStore);
+    LibraryElement coreLibrary = await driver.getLibraryByUri('dart:core');
+    expect(coreLibrary, isNotNull);
+    expect(coreLibrary.getType('Object'), isNotNull);
+  }
+
+  test_getParsedLibrary_external() async {
+    var a1 = convertPath('/aaa/lib/a1.dart');
+    var a2 = convertPath('/aaa/lib/a2.dart');
+
+    var a1UriStr = 'package:aaa/a1.dart';
+    var a2UriStr = 'package:aaa/a2.dart';
+
+    newFile(a1, content: "part 'a2.dart';  class A {}");
+    newFile(a2, content: "part of 'a1.dart';");
+
+    // Build the store with the library.
+    var store = await createAnalysisDriver().test.getSummaryStore(a1);
+    expect(store.unlinkedMap.keys, contains(a1UriStr));
+    expect(store.unlinkedMap.keys, contains(a2UriStr));
+    expect(store.linkedMap.keys, contains(a1UriStr));
+
+    var driver = createAnalysisDriver(externalSummaries: store);
+    var libraryElement = await driver.getLibraryByUri(a1UriStr);
+    var classA = libraryElement.library.getType('A');
+
+    var parsedLibrary = driver.getParsedLibrary(a1);
+    expect(parsedLibrary, isNotNull);
+    expect(parsedLibrary.state, ResultState.NOT_A_FILE);
+    expect(() {
+      parsedLibrary.getElementDeclaration(classA);
+    }, throwsStateError);
+
+    // It is an error to ask for a library when we know that it is a part.
+    expect(() {
+      driver.getParsedLibrary(a2);
+    }, throwsArgumentError);
+  }
+
+  test_getParsedLibraryByUri_external() async {
+    var a1 = convertPath('/aaa/lib/a1.dart');
+    var a2 = convertPath('/aaa/lib/a2.dart');
+
+    var a1UriStr = 'package:aaa/a1.dart';
+    var a2UriStr = 'package:aaa/a2.dart';
+
+    var a1Uri = Uri.parse(a1UriStr);
+    var a2Uri = Uri.parse(a2UriStr);
+
+    newFile(a1, content: "part 'a2.dart';  class A {}");
+    newFile(a2, content: "part of 'a1.dart';");
+
+    // Build the store with the library.
+    var store = await createAnalysisDriver().test.getSummaryStore(a1);
+    expect(store.unlinkedMap.keys, contains(a1UriStr));
+    expect(store.unlinkedMap.keys, contains(a2UriStr));
+    expect(store.linkedMap.keys, contains(a1UriStr));
+
+    var driver = createAnalysisDriver(externalSummaries: store);
+    var libraryElement = await driver.getLibraryByUri(a1UriStr);
+    var classA = libraryElement.library.getType('A');
+
+    {
+      var parsedLibrary = driver.getParsedLibraryByUri(a1Uri);
+      expect(parsedLibrary, isNotNull);
+      expect(parsedLibrary.state, ResultState.NOT_A_FILE);
+      expect(() {
+        parsedLibrary.getElementDeclaration(classA);
+      }, throwsStateError);
+    }
+
+    // We can also get the result from the session.
+    {
+      var session = driver.currentSession;
+      var parsedLibrary = session.getParsedLibraryByElement(libraryElement);
+      expect(parsedLibrary, isNotNull);
+      expect(parsedLibrary.state, ResultState.NOT_A_FILE);
+      expect(() {
+        parsedLibrary.getElementDeclaration(classA);
+      }, throwsStateError);
+    }
+
+    // It is an error to ask for a library when we know that it is a part.
+    expect(() {
+      driver.getParsedLibraryByUri(a2Uri);
+    }, throwsArgumentError);
+  }
+
+  test_getResolvedLibrary_external() async {
+    var a1 = convertPath('/aaa/lib/a1.dart');
+    var a2 = convertPath('/aaa/lib/a2.dart');
+
+    var a1UriStr = 'package:aaa/a1.dart';
+    var a2UriStr = 'package:aaa/a2.dart';
+
+    newFile(a1, content: "part 'a2.dart';  class A {}");
+    newFile(a2, content: "part of 'a1.dart';");
+
+    // Build the store with the library.
+    var store = await createAnalysisDriver().test.getSummaryStore(a1);
+    expect(store.unlinkedMap.keys, contains(a1UriStr));
+    expect(store.unlinkedMap.keys, contains(a2UriStr));
+    expect(store.linkedMap.keys, contains(a1UriStr));
+
+    var driver = createAnalysisDriver(externalSummaries: store);
+    var libraryElement = await driver.getLibraryByUri(a1UriStr);
+    var classA = libraryElement.library.getType('A');
+
+    var resolvedLibrary = await driver.getResolvedLibrary(a1);
+    expect(resolvedLibrary, isNotNull);
+    expect(resolvedLibrary.state, ResultState.NOT_A_FILE);
+    expect(() {
+      resolvedLibrary.getElementDeclaration(classA);
+    }, throwsStateError);
+
+    // It is an error to ask for a library when we know that it is a part.
+    expect(() async {
+      await driver.getResolvedLibrary(a2);
+    }, throwsArgumentError);
+  }
+
+  test_getResolvedLibraryByUri_external() async {
+    var a1 = convertPath('/aaa/lib/a1.dart');
+    var a2 = convertPath('/aaa/lib/a2.dart');
+
+    var a1UriStr = 'package:aaa/a1.dart';
+    var a2UriStr = 'package:aaa/a2.dart';
+
+    var a1Uri = Uri.parse(a1UriStr);
+    var a2Uri = Uri.parse(a2UriStr);
+
+    newFile(a1, content: "part 'a2.dart';  class A {}");
+    newFile(a2, content: "part of 'a1.dart';");
+
+    // Build the store with the library.
+    var store = await createAnalysisDriver().test.getSummaryStore(a1);
+    expect(store.unlinkedMap.keys, contains(a1UriStr));
+    expect(store.unlinkedMap.keys, contains(a2UriStr));
+    expect(store.linkedMap.keys, contains(a1UriStr));
+
+    var driver = createAnalysisDriver(externalSummaries: store);
+    var libraryElement = await driver.getLibraryByUri(a1UriStr);
+    var classA = libraryElement.library.getType('A');
+
+    {
+      var resolvedLibrary = await driver.getResolvedLibraryByUri(a1Uri);
+      expect(resolvedLibrary, isNotNull);
+      expect(resolvedLibrary.state, ResultState.NOT_A_FILE);
+      expect(() {
+        resolvedLibrary.getElementDeclaration(classA);
+      }, throwsStateError);
+    }
+
+    // We can also get the result from the session.
+    {
+      var session = driver.currentSession;
+      var resolvedLibrary =
+          await session.getResolvedLibraryByElement(libraryElement);
+      expect(resolvedLibrary, isNotNull);
+      expect(resolvedLibrary.state, ResultState.NOT_A_FILE);
+      expect(() {
+        resolvedLibrary.getElementDeclaration(classA);
+      }, throwsStateError);
+    }
+
+    // It is an error to ask for a library when we know that it is a part.
+    expect(() async {
+      await driver.getResolvedLibraryByUri(a2Uri);
+    }, throwsArgumentError);
+  }
+
+  test_isLibraryByUri() async {
+    var a1 = '/aaa/lib/a1.dart';
+    var a2 = '/aaa/lib/a2.dart';
+    var b1 = '/bbb/lib/b1.dart';
+    var b2 = '/bbb/lib/b2.dart';
+
+    String a1UriStr = 'package:aaa/a1.dart';
+    String a2UriStr = 'package:aaa/a2.dart';
+    String b1UriStr = 'package:bbb/b1.dart';
+    String b2UriStr = 'package:bbb/b2.dart';
+
+    newFile(a1, content: "part 'a2.dart';");
+    newFile(a2, content: "part of 'a1.dart';");
+    newFile(b1, content: "part 'b2.dart';");
+    newFile(b2, content: "part of 'b1.dart';");
+
+    // Build the store with the library.
+    var store =
+        await createAnalysisDriver().test.getSummaryStore(convertPath(a1));
+    expect(store.unlinkedMap.keys, contains(a1UriStr));
+    expect(store.unlinkedMap.keys, contains(a2UriStr));
+    expect(store.linkedMap.keys, contains(a1UriStr));
+
+    // Remove the stored files from the file system.
+    deleteFile(a1);
+    deleteFile(a2);
+
+    // We can ask isLibraryByUri() for both external and local units.
+    AnalysisDriver driver = createAnalysisDriver(externalSummaries: store);
+    expect(driver.isLibraryByUri(Uri.parse(a1UriStr)), isTrue);
+    expect(driver.isLibraryByUri(Uri.parse(a2UriStr)), isFalse);
+    expect(driver.isLibraryByUri(Uri.parse(b1UriStr)), isTrue);
+    expect(driver.isLibraryByUri(Uri.parse(b2UriStr)), isFalse);
+  }
+}
+
+/// TODO(paulberry): migrate this test away from the task model.
+/// See dartbug.com/35734.
+@reflectiveTest
 class AnalysisDriverTest extends BaseAnalysisDriverTest {
   void configurePreviewDart2() {
     driver.configure(
@@ -1101,86 +1471,6 @@
     expect(errors[0].errorCode, CompileTimeErrorCode.URI_DOES_NOT_EXIST);
   }
 
-  test_externalSummaries() async {
-    var a = convertPath('/a.dart');
-    var b = convertPath('/b.dart');
-    newFile(a, content: r'''
-class A {}
-''');
-    newFile(b, content: r'''
-import 'a.dart';
-var a = new A();
-''');
-
-    // Prepare the store with a.dart and everything it needs.
-    SummaryDataStore summaryStore =
-        await createAnalysisDriver().test.getSummaryStore(a);
-
-    // There are at least a.dart and dart:core libraries.
-    String aUri = toUriStr(a);
-    expect(summaryStore.unlinkedMap.keys, contains(aUri));
-    expect(summaryStore.linkedMap.keys, contains(aUri));
-    expect(summaryStore.unlinkedMap.keys, contains('dart:core'));
-    expect(summaryStore.linkedMap.keys, contains('dart:core'));
-
-    // Remove a.dart from the file system.
-    deleteFile(a);
-
-    // We don't need a.dart file when we analyze with the summary store.
-    // Still no analysis errors.
-    AnalysisDriver driver =
-        createAnalysisDriver(externalSummaries: summaryStore);
-    ResolvedUnitResult result = await driver.getResult(b);
-    expect(result.errors, isEmpty);
-  }
-
-  test_externalSummaries_partReuse() async {
-    var a = convertPath('/a.dart');
-    var b = convertPath('/b.dart');
-    var c = convertPath('/c.dart');
-    newFile(a, content: r'''
-library a;
-part 'b.dart';
-class A {}
-''');
-    newFile(b, content: r'''
-part of a;
-class _B {}
-''');
-    newFile(c, content: r'''
-library a;
-import 'a.dart';
-part 'b.dart';
-var a = new A();
-var b = new _B();
-''');
-
-    // Prepare the store with a.dart and everything it needs.
-    SummaryDataStore summaryStore =
-        await createAnalysisDriver().test.getSummaryStore(a);
-
-    String aUri = toUriStr(a);
-    String bUri = toUriStr(b);
-    // There are unlinked units for a.dart and b.dart files.
-    expect(summaryStore.hasUnlinkedUnit(aUri), isTrue);
-    expect(summaryStore.hasUnlinkedUnit(bUri), isTrue);
-    // Only a.dart is linked, because b.dart is not a library.
-    expect(summaryStore.hasLinkedLibrary(aUri), isTrue);
-    expect(summaryStore.hasLinkedLibrary(bUri), isFalse);
-
-    // Remove a.dart from the file system.
-    // Keep b.dart, because we (re)use it as a part.
-    deleteFile(a);
-
-    // We don't need a.dart file when we analyze with the summary store.
-    // We can instantiate the class A the library a.dart.
-    // We can instantiate the class _A the part b.dart.
-    AnalysisDriver driver =
-        createAnalysisDriver(externalSummaries: summaryStore);
-    ResolvedUnitResult result = await driver.getResult(c);
-    expect(result.errors, isEmpty);
-  }
-
   test_generatedFile() async {
     Uri uri = Uri.parse('package:aaa/foo.dart');
     String templatePath = convertPath('/aaa/lib/foo.dart');
@@ -1444,251 +1734,9 @@
     }, throwsArgumentError);
   }
 
-  test_getLibraryByUri_external() async {
-    var a = convertPath('/test/lib/a.dart');
-    var b = convertPath('/test/lib/b.dart');
-
-    String aUriStr = 'package:test/a.dart';
-    String bUriStr = 'package:test/b.dart';
-
-    newFile(a, content: r'''
-part 'b.dart';
-
-class A {}
-''');
-
-    newFile(b, content: r'''
-part of 'a.dart';
-
-class B {}
-''');
-
-    // Prepare the store with package:test/test.dart URI.
-    var store = await createAnalysisDriver().test.getSummaryStore(a);
-
-    // package:test/test.dart is in the store.
-    expect(store.unlinkedMap.keys, contains(aUriStr));
-    expect(store.unlinkedMap.keys, contains(bUriStr));
-    expect(store.linkedMap.keys, contains(aUriStr));
-    expect(store.linkedMap.keys, isNot(contains(bUriStr)));
-
-    // Remove the files from the file system.
-    deleteFile(a);
-    deleteFile(b);
-
-    // We can resynthesize the library from the store.
-    var driver = createAnalysisDriver(externalSummaries: store);
-
-    // Ask by URI, so we get the "external" FileState.
-    var aUri = Uri.parse(aUriStr);
-    var aFile = driver.fsState.getFileForUri(aUri);
-    expect(aFile.uri, aUri);
-    expect(aFile.path, isNull);
-
-    // We still can resynthesize the library.
-    // The URI is known to be external, so we don't talk to the file.
-    var library = await driver.getLibraryByUri(aUriStr);
-    expect(library.getType('A'), isNotNull);
-    expect(library.getType('B'), isNotNull);
-
-    // It is an error to ask for a library when we know that it is a part.
+  test_getLibraryByUri_unresolvedUri() async {
     expect(() async {
-      await driver.getLibraryByUri(bUriStr);
-    }, throwsArgumentError);
-  }
-
-  test_getLibraryByUri_sdk_analyze() async {
-    LibraryElement coreLibrary = await driver.getLibraryByUri('dart:core');
-    expect(coreLibrary, isNotNull);
-    expect(coreLibrary.getType('Object'), isNotNull);
-    expect(coreLibrary.getType('int'), isNotNull);
-  }
-
-  test_getLibraryByUri_sdk_resynthesize() async {
-    String corePath = sdk.mapDartUri('dart:core').fullName;
-    String asyncPath = sdk.mapDartUri('dart:async').fullName;
-    var sdkStore = await createAnalysisDriver().test.getSummaryStore(corePath);
-
-    // There are dart:core and dart:async in the store.
-    expect(sdkStore.unlinkedMap.keys, contains('dart:core'));
-    expect(sdkStore.unlinkedMap.keys, contains('dart:async'));
-    expect(sdkStore.linkedMap.keys, contains('dart:core'));
-    expect(sdkStore.linkedMap.keys, contains('dart:async'));
-
-    // Remove dart:core and dart:async.
-    // So, the new driver below cannot parse and summarize them.
-    deleteFile(corePath);
-    deleteFile(asyncPath);
-
-    // We still get get dart:core library element.
-    AnalysisDriver driver = createAnalysisDriver(externalSummaries: sdkStore);
-    LibraryElement coreLibrary = await driver.getLibraryByUri('dart:core');
-    expect(coreLibrary, isNotNull);
-    expect(coreLibrary.getType('Object'), isNotNull);
-  }
-
-  test_getParsedLibrary_external() async {
-    var a1 = convertPath('/aaa/lib/a1.dart');
-    var a2 = convertPath('/aaa/lib/a2.dart');
-
-    var a1UriStr = 'package:aaa/a1.dart';
-    var a2UriStr = 'package:aaa/a2.dart';
-
-    newFile(a1, content: "part 'a2.dart';  class A {}");
-    newFile(a2, content: "part of 'a1.dart';");
-
-    // Build the store with the library.
-    var store = await createAnalysisDriver().test.getSummaryStore(a1);
-    expect(store.unlinkedMap.keys, contains(a1UriStr));
-    expect(store.unlinkedMap.keys, contains(a2UriStr));
-    expect(store.linkedMap.keys, contains(a1UriStr));
-
-    var driver = createAnalysisDriver(externalSummaries: store);
-    var libraryElement = await driver.getLibraryByUri(a1UriStr);
-    var classA = libraryElement.library.getType('A');
-
-    var parsedLibrary = driver.getParsedLibrary(a1);
-    expect(parsedLibrary, isNotNull);
-    expect(parsedLibrary.state, ResultState.NOT_A_FILE);
-    expect(() {
-      parsedLibrary.getElementDeclaration(classA);
-    }, throwsStateError);
-
-    // It is an error to ask for a library when we know that it is a part.
-    expect(() {
-      driver.getParsedLibrary(a2);
-    }, throwsArgumentError);
-  }
-
-  test_getParsedLibraryByUri_external() async {
-    var a1 = convertPath('/aaa/lib/a1.dart');
-    var a2 = convertPath('/aaa/lib/a2.dart');
-
-    var a1UriStr = 'package:aaa/a1.dart';
-    var a2UriStr = 'package:aaa/a2.dart';
-
-    var a1Uri = Uri.parse(a1UriStr);
-    var a2Uri = Uri.parse(a2UriStr);
-
-    newFile(a1, content: "part 'a2.dart';  class A {}");
-    newFile(a2, content: "part of 'a1.dart';");
-
-    // Build the store with the library.
-    var store = await createAnalysisDriver().test.getSummaryStore(a1);
-    expect(store.unlinkedMap.keys, contains(a1UriStr));
-    expect(store.unlinkedMap.keys, contains(a2UriStr));
-    expect(store.linkedMap.keys, contains(a1UriStr));
-
-    var driver = createAnalysisDriver(externalSummaries: store);
-    var libraryElement = await driver.getLibraryByUri(a1UriStr);
-    var classA = libraryElement.library.getType('A');
-
-    {
-      var parsedLibrary = driver.getParsedLibraryByUri(a1Uri);
-      expect(parsedLibrary, isNotNull);
-      expect(parsedLibrary.state, ResultState.NOT_A_FILE);
-      expect(() {
-        parsedLibrary.getElementDeclaration(classA);
-      }, throwsStateError);
-    }
-
-    // We can also get the result from the session.
-    {
-      var session = driver.currentSession;
-      var parsedLibrary = session.getParsedLibraryByElement(libraryElement);
-      expect(parsedLibrary, isNotNull);
-      expect(parsedLibrary.state, ResultState.NOT_A_FILE);
-      expect(() {
-        parsedLibrary.getElementDeclaration(classA);
-      }, throwsStateError);
-    }
-
-    // It is an error to ask for a library when we know that it is a part.
-    expect(() {
-      driver.getParsedLibraryByUri(a2Uri);
-    }, throwsArgumentError);
-  }
-
-  test_getResolvedLibrary_external() async {
-    var a1 = convertPath('/aaa/lib/a1.dart');
-    var a2 = convertPath('/aaa/lib/a2.dart');
-
-    var a1UriStr = 'package:aaa/a1.dart';
-    var a2UriStr = 'package:aaa/a2.dart';
-
-    newFile(a1, content: "part 'a2.dart';  class A {}");
-    newFile(a2, content: "part of 'a1.dart';");
-
-    // Build the store with the library.
-    var store = await createAnalysisDriver().test.getSummaryStore(a1);
-    expect(store.unlinkedMap.keys, contains(a1UriStr));
-    expect(store.unlinkedMap.keys, contains(a2UriStr));
-    expect(store.linkedMap.keys, contains(a1UriStr));
-
-    var driver = createAnalysisDriver(externalSummaries: store);
-    var libraryElement = await driver.getLibraryByUri(a1UriStr);
-    var classA = libraryElement.library.getType('A');
-
-    var resolvedLibrary = await driver.getResolvedLibrary(a1);
-    expect(resolvedLibrary, isNotNull);
-    expect(resolvedLibrary.state, ResultState.NOT_A_FILE);
-    expect(() {
-      resolvedLibrary.getElementDeclaration(classA);
-    }, throwsStateError);
-
-    // It is an error to ask for a library when we know that it is a part.
-    expect(() async {
-      await driver.getResolvedLibrary(a2);
-    }, throwsArgumentError);
-  }
-
-  test_getResolvedLibraryByUri_external() async {
-    var a1 = convertPath('/aaa/lib/a1.dart');
-    var a2 = convertPath('/aaa/lib/a2.dart');
-
-    var a1UriStr = 'package:aaa/a1.dart';
-    var a2UriStr = 'package:aaa/a2.dart';
-
-    var a1Uri = Uri.parse(a1UriStr);
-    var a2Uri = Uri.parse(a2UriStr);
-
-    newFile(a1, content: "part 'a2.dart';  class A {}");
-    newFile(a2, content: "part of 'a1.dart';");
-
-    // Build the store with the library.
-    var store = await createAnalysisDriver().test.getSummaryStore(a1);
-    expect(store.unlinkedMap.keys, contains(a1UriStr));
-    expect(store.unlinkedMap.keys, contains(a2UriStr));
-    expect(store.linkedMap.keys, contains(a1UriStr));
-
-    var driver = createAnalysisDriver(externalSummaries: store);
-    var libraryElement = await driver.getLibraryByUri(a1UriStr);
-    var classA = libraryElement.library.getType('A');
-
-    {
-      var resolvedLibrary = await driver.getResolvedLibraryByUri(a1Uri);
-      expect(resolvedLibrary, isNotNull);
-      expect(resolvedLibrary.state, ResultState.NOT_A_FILE);
-      expect(() {
-        resolvedLibrary.getElementDeclaration(classA);
-      }, throwsStateError);
-    }
-
-    // We can also get the result from the session.
-    {
-      var session = driver.currentSession;
-      var resolvedLibrary =
-          await session.getResolvedLibraryByElement(libraryElement);
-      expect(resolvedLibrary, isNotNull);
-      expect(resolvedLibrary.state, ResultState.NOT_A_FILE);
-      expect(() {
-        resolvedLibrary.getElementDeclaration(classA);
-      }, throwsStateError);
-    }
-
-    // It is an error to ask for a library when we know that it is a part.
-    expect(() async {
-      await driver.getResolvedLibraryByUri(a2Uri);
+      await driver.getLibraryByUri('package:foo/foo.dart');
     }, throwsArgumentError);
   }
 
@@ -1705,7 +1753,7 @@
     expect(result.errors, hasLength(0));
 
     var f = result.unit.declarations[0] as FunctionDeclaration;
-    expect(f.name.staticType.toString(), '() → int');
+    expect(f.name.staticType.toString(), 'int Function()');
     expect(f.returnType.type.toString(), 'int');
 
     // The same result is also received through the stream.
@@ -2179,102 +2227,6 @@
     expect(await driver.getSourceKind(path), SourceKind.PART);
   }
 
-  test_getTopLevelNameDeclarations() async {
-    var a = convertPath('/test/lib/a.dart');
-    var b = convertPath('/test/lib/b.dart');
-    var c = convertPath('/test/lib/c.dart');
-    var d = convertPath('/test/lib/d.dart');
-
-    newFile(a, content: 'class A {}');
-    newFile(b, content: 'export "a.dart"; class B {}');
-    newFile(c, content: 'import "d.dart"; class C {}');
-    newFile(d, content: 'class D {}');
-
-    driver.addFile(a);
-    driver.addFile(b);
-    driver.addFile(c);
-    // Don't add d.dart, it is referenced implicitly.
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('A'), [a, b], [false, true]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('B'), [b], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('C'), [c], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('D'), [d], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('X'), [], []);
-  }
-
-  test_getTopLevelNameDeclarations_discover() async {
-    var t = convertPath('/test/lib/test.dart');
-    var a1 = convertPath('/aaa/lib/a1.dart');
-    var a2 = convertPath('/aaa/lib/src/a2.dart');
-    var b = convertPath('/bbb/lib/b.dart');
-    var c = convertPath('/ccc/lib/c.dart');
-
-    newFile(t, content: 'class T {}');
-    newFile(a1, content: 'class A1 {}');
-    newFile(a2, content: 'class A2 {}');
-    newFile(b, content: 'class B {}');
-    newFile(c, content: 'class C {}');
-
-    driver.addFile(t);
-    // Don't add a1.dart, a2.dart, or b.dart - they should be discovered.
-    // And c.dart is not in .packages, so should not be discovered.
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('T'), [t], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('A1'), [a1], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('A2'), [a2], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('B'), [b], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('C'), [], []);
-  }
-
-  test_getTopLevelNameDeclarations_parts() async {
-    var a = convertPath('/test/lib/a.dart');
-    var b = convertPath('/test/lib/b.dart');
-    var c = convertPath('/test/lib/c.dart');
-
-    newFile(a, content: r'''
-library lib;
-part 'b.dart';
-part 'c.dart';
-class A {}
-''');
-    newFile(b, content: 'part of lib; class B {}');
-    newFile(c, content: 'part of lib; class C {}');
-
-    driver.addFile(a);
-    driver.addFile(b);
-    driver.addFile(c);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('A'), [a], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('B'), [a], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('C'), [a], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('X'), [], []);
-  }
-
   test_getUnitElement() async {
     String content = r'''
 foo(int p) {}
@@ -2465,41 +2417,6 @@
     await waitForIdleWithoutExceptions();
   }
 
-  test_isLibraryByUri() async {
-    var a1 = '/aaa/lib/a1.dart';
-    var a2 = '/aaa/lib/a2.dart';
-    var b1 = '/bbb/lib/b1.dart';
-    var b2 = '/bbb/lib/b2.dart';
-
-    String a1UriStr = 'package:aaa/a1.dart';
-    String a2UriStr = 'package:aaa/a2.dart';
-    String b1UriStr = 'package:bbb/b1.dart';
-    String b2UriStr = 'package:bbb/b2.dart';
-
-    newFile(a1, content: "part 'a2.dart';");
-    newFile(a2, content: "part of 'a1.dart';");
-    newFile(b1, content: "part 'b2.dart';");
-    newFile(b2, content: "part of 'b1.dart';");
-
-    // Build the store with the library.
-    var store =
-        await createAnalysisDriver().test.getSummaryStore(convertPath(a1));
-    expect(store.unlinkedMap.keys, contains(a1UriStr));
-    expect(store.unlinkedMap.keys, contains(a2UriStr));
-    expect(store.linkedMap.keys, contains(a1UriStr));
-
-    // Remove the stored files from the file system.
-    deleteFile(a1);
-    deleteFile(a2);
-
-    // We can ask isLibraryByUri() for both external and local units.
-    AnalysisDriver driver = createAnalysisDriver(externalSummaries: store);
-    expect(driver.isLibraryByUri(Uri.parse(a1UriStr)), isTrue);
-    expect(driver.isLibraryByUri(Uri.parse(a2UriStr)), isFalse);
-    expect(driver.isLibraryByUri(Uri.parse(b1UriStr)), isTrue);
-    expect(driver.isLibraryByUri(Uri.parse(b2UriStr)), isFalse);
-  }
-
   test_isLibraryByUri_doesNotExist() async {
     var uri = Uri.parse('file:///test.dart');
     expect(driver.isLibraryByUri(uri), isTrue);
@@ -3378,7 +3295,7 @@
     expect(result.errors, hasLength(0));
 
     var f = result.unit.declarations[0] as FunctionDeclaration;
-    expect(f.name.staticType.toString(), '() → int');
+    expect(f.name.staticType.toString(), 'int Function()');
     expect(f.returnType.type.toString(), 'int');
   }
 
@@ -3499,20 +3416,6 @@
     }
   }
 
-  void _assertTopLevelDeclarations(
-      List<TopLevelDeclarationInSource> declarations,
-      List<String> expectedFiles,
-      List<bool> expectedIsExported) {
-    expect(expectedFiles, hasLength(expectedIsExported.length));
-    for (int i = 0; i < expectedFiles.length; i++) {
-      expect(declarations,
-          contains(predicate((TopLevelDeclarationInSource declaration) {
-        return declaration.source.fullName == expectedFiles[i] &&
-            declaration.isExported == expectedIsExported[i];
-      })));
-    }
-  }
-
   void _expectCircularityError(EvaluationResultImpl evaluationResult) {
     expect(evaluationResult, isNotNull);
     expect(evaluationResult.value, isNull);
diff --git a/pkg/analyzer/test/src/dart/analysis/experiments_test.dart b/pkg/analyzer/test/src/dart/analysis/experiments_test.dart
index aa83160..740c46f 100644
--- a/pkg/analyzer/test/src/dart/analysis/experiments_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/experiments_test.dart
@@ -51,7 +51,8 @@
 
   test_fromStrings_default_values() {
     knownFeatures['a'] = ExperimentalFeature(0, 'a', false, false, 'a');
-    knownFeatures['b'] = ExperimentalFeature(1, 'b', true, false, 'b');
+    knownFeatures['b'] = ExperimentalFeature(1, 'b', true, false, 'b',
+        firstSupportedVersion: '1.0.0');
     expect(getFlags(fromStrings([])), [false, true]);
   }
 
@@ -61,7 +62,8 @@
   }
 
   test_fromStrings_disable_enabled_feature() {
-    knownFeatures['a'] = ExperimentalFeature(0, 'a', true, false, 'a');
+    knownFeatures['a'] = ExperimentalFeature(0, 'a', true, false, 'a',
+        firstSupportedVersion: '1.0.0');
     expect(getFlags(fromStrings(['no-a'])), [false]);
   }
 
@@ -71,32 +73,35 @@
   }
 
   test_fromStrings_enable_enabled_feature() {
-    knownFeatures['a'] = ExperimentalFeature(0, 'a', true, false, 'a');
+    knownFeatures['a'] = ExperimentalFeature(0, 'a', true, false, 'a',
+        firstSupportedVersion: '1.0.0');
     expect(getFlags(fromStrings(['a'])), [true]);
   }
 
   test_fromStrings_illegal_use_of_expired_flag_disable() {
     // Expired flags are ignored even if they would fail validation.
-    knownFeatures['a'] = ExperimentalFeature(null, 'a', true, true, 'a');
-    expect(getFlags(fromStrings(['no-a'])), []);
+    knownFeatures['a'] = ExperimentalFeature(0, 'a', true, true, 'a',
+        firstSupportedVersion: '1.0.0');
+    expect(getFlags(fromStrings(['no-a'])), [true]);
   }
 
   test_fromStrings_illegal_use_of_expired_flag_enable() {
     // Expired flags are ignored even if they would fail validation.
-    knownFeatures['a'] = ExperimentalFeature(null, 'a', false, true, 'a');
-    expect(getFlags(fromStrings(['a'])), []);
+    knownFeatures['a'] = ExperimentalFeature(0, 'a', false, true, 'a');
+    expect(getFlags(fromStrings(['a'])), [false]);
   }
 
   test_fromStrings_unnecessary_use_of_expired_flag_disable() {
     // Expired flags are ignored.
-    knownFeatures['a'] = ExperimentalFeature(null, 'a', false, true, 'a');
-    expect(getFlags(fromStrings(['no-a'])), []);
+    knownFeatures['a'] = ExperimentalFeature(0, 'a', false, true, 'a');
+    expect(getFlags(fromStrings(['no-a'])), [false]);
   }
 
   test_fromStrings_unnecessary_use_of_expired_flag_enable() {
     // Expired flags are ignored.
-    knownFeatures['a'] = ExperimentalFeature(null, 'a', true, true, 'a');
-    expect(getFlags(fromStrings(['a'])), []);
+    knownFeatures['a'] = ExperimentalFeature(0, 'a', true, true, 'a',
+        firstSupportedVersion: '1.0.0');
+    expect(getFlags(fromStrings(['a'])), [true]);
   }
 
   test_fromStrings_unrecognized_flag() {
@@ -162,7 +167,8 @@
   }
 
   test_validateFlags_ignore_redundant_disable_flags() {
-    knownFeatures['a'] = ExperimentalFeature(0, 'a', true, false, 'a');
+    knownFeatures['a'] = ExperimentalFeature(0, 'a', true, false, 'a',
+        firstSupportedVersion: '1.0.0');
     expect(getValidationResult(['no-a', 'no-a']), isEmpty);
   }
 
@@ -172,7 +178,8 @@
   }
 
   test_validateFlags_illegal_use_of_expired_flag_disable() {
-    knownFeatures['a'] = ExperimentalFeature(null, 'a', true, true, 'a');
+    knownFeatures['a'] = ExperimentalFeature(0, 'a', true, true, 'a',
+        firstSupportedVersion: '1.0.0');
     var validationResult = getValidationResult(['no-a']);
     expect(validationResult, hasLength(1));
     var error = validationResult[0] as IllegalUseOfExpiredFlag;
@@ -183,7 +190,7 @@
   }
 
   test_validateFlags_illegal_use_of_expired_flag_enable() {
-    knownFeatures['a'] = ExperimentalFeature(null, 'a', false, true, 'a');
+    knownFeatures['a'] = ExperimentalFeature(0, 'a', false, true, 'a');
     var validationResult = getValidationResult(['a']);
     expect(validationResult, hasLength(1));
     var error = validationResult[0] as IllegalUseOfExpiredFlag;
@@ -194,7 +201,7 @@
   }
 
   test_validateFlags_unnecessary_use_of_expired_flag_disable() {
-    knownFeatures['a'] = ExperimentalFeature(null, 'a', false, true, 'a');
+    knownFeatures['a'] = ExperimentalFeature(0, 'a', false, true, 'a');
     var validationResult = getValidationResult(['no-a']);
     expect(validationResult, hasLength(1));
     var error = validationResult[0] as UnnecessaryUseOfExpiredFlag;
@@ -205,7 +212,8 @@
   }
 
   test_validateFlags_unnecessary_use_of_expired_flag_enable() {
-    knownFeatures['a'] = ExperimentalFeature(null, 'a', true, true, 'a');
+    knownFeatures['a'] = ExperimentalFeature(0, 'a', true, true, 'a',
+        firstSupportedVersion: '1.0.0');
     var validationResult = getValidationResult(['a']);
     expect(validationResult, hasLength(1));
     var error = validationResult[0] as UnnecessaryUseOfExpiredFlag;
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index f69ba70..24ec015 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -10,7 +10,6 @@
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/library_graph.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisOptions, AnalysisOptionsImpl;
@@ -104,249 +103,6 @@
         unorderedEquals(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']));
   }
 
-  test_exportedTopLevelDeclarations_cycle() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    String c = convertPath('/aaa/lib/c.dart');
-    newFile(a, content: r'''
-export 'b.dart';
-class A {}
-''');
-    newFile(b, content: r'''
-export 'c.dart';
-class B {}
-''');
-    newFile(c, content: r'''
-export 'a.dart';
-class C {}
-''');
-    _assertExportedTopLevelDeclarations(a, ['A', 'B', 'C']);
-
-    // We asked for 'a', and it was computed.
-    // But 'b' and 'c' are not computed, because we detect that there is
-    // cycle with 'a', so we cannot get all exported declarations of 'a'.
-    _assertHasComputedExportedDeclarations([a]);
-  }
-
-  test_exportedTopLevelDeclarations_cycle_anotherOutsideCycle() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    String c = convertPath('/aaa/lib/c.dart');
-    String d = convertPath('/aaa/lib/d.dart');
-    newFile(a, content: r'''
-export 'b.dart';
-class A {}
-''');
-    newFile(b, content: r'''
-export 'c.dart';
-class B {}
-''');
-    newFile(c, content: r'''
-export 'b.dart';
-export 'd.dart';
-class C {}
-''');
-    newFile(d, content: r'''
-class D {}
-''');
-    _assertExportedTopLevelDeclarations(a, ['A', 'B', 'C', 'D']);
-
-    // To compute 'a' we compute 'b'.
-    // But 'c' is not computed, because of the cycle [b, c].
-    // However 'd' is not a part of a cycle, so it is computed too.
-    _assertHasComputedExportedDeclarations([a, b, d]);
-  }
-
-  test_exportedTopLevelDeclarations_cycle_onSequence() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    String c = convertPath('/aaa/lib/c.dart');
-    String d = convertPath('/aaa/lib/d.dart');
-    String e = convertPath('/aaa/lib/e.dart');
-    newFile(a, content: r'''
-export 'b.dart';
-class A {}
-''');
-    newFile(b, content: r'''
-export 'c.dart';
-class B {}
-''');
-    newFile(c, content: r'''
-export 'd.dart';
-class C {}
-''');
-    newFile(d, content: r'''
-export 'e.dart';
-class D {}
-''');
-    newFile(e, content: r'''
-export 'c.dart';
-class E {}
-''');
-    // We compute 'a'.
-    // To compute it we also compute 'b' and 'c'.
-    // But 'd' and 'e' are not computed, because of the cycle [c, d, e].
-    _assertExportedTopLevelDeclarations(a, ['A', 'B', 'C', 'D', 'E']);
-    _assertHasComputedExportedDeclarations([a, b, c]);
-
-    // We compute 'd', and try to compute 'e', because 'd' needs 'e'; 'e' can
-    // be computed because 'c' is ready, so the cycle [c, d, e] is broken.
-    _assertExportedTopLevelDeclarations(d, ['C', 'D', 'E']);
-    _assertHasComputedExportedDeclarations([a, b, c, d, e]);
-  }
-
-  test_exportedTopLevelDeclarations_export() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class A {}
-''');
-    newFile(b, content: r'''
-export 'a.dart';
-class B {}
-''');
-    _assertExportedTopLevelDeclarations(b, ['A', 'B']);
-    _assertHasComputedExportedDeclarations([a, b]);
-  }
-
-  test_exportedTopLevelDeclarations_export2_show() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    String c = convertPath('/aaa/lib/c.dart');
-    newFile(a, content: r'''
-class A1 {}
-class A2 {}
-class A3 {}
-''');
-    newFile(b, content: r'''
-export 'a.dart' show A1, A2;
-class B1 {}
-class B2 {}
-''');
-    newFile(c, content: r'''
-export 'b.dart' show A2, A3, B1;
-class C {}
-''');
-    _assertExportedTopLevelDeclarations(c, ['A2', 'B1', 'C']);
-    _assertHasComputedExportedDeclarations([a, b, c]);
-  }
-
-  test_exportedTopLevelDeclarations_export_flushOnChange() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class A {}
-''');
-    newFile(b, content: r'''
-export 'a.dart';
-class B {}
-''');
-
-    // Initial exported declarations.
-    _assertExportedTopLevelDeclarations(b, ['A', 'B']);
-
-    // Update a.dart, so a.dart and b.dart exported declarations are flushed.
-    newFile(a, content: 'class A {} class A2 {}');
-    fileSystemState.getFileForPath(a).refresh();
-    _assertExportedTopLevelDeclarations(b, ['A', 'A2', 'B']);
-  }
-
-  test_exportedTopLevelDeclarations_export_hide() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class A1 {}
-class A2 {}
-class A3 {}
-''');
-    newFile(b, content: r'''
-export 'a.dart' hide A2;
-class B {}
-''');
-    _assertExportedTopLevelDeclarations(b, ['A1', 'A3', 'B']);
-  }
-
-  test_exportedTopLevelDeclarations_export_preferLocal() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class V {}
-''');
-    newFile(b, content: r'''
-export 'a.dart';
-int V;
-''');
-    FileState file = fileSystemState.getFileForPath(b);
-    Map<String, TopLevelDeclaration> declarations =
-        file.exportedTopLevelDeclarations;
-    expect(declarations.keys, unorderedEquals(['V']));
-    expect(declarations['V'].kind, TopLevelDeclarationKind.variable);
-  }
-
-  test_exportedTopLevelDeclarations_export_show() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class A1 {}
-class A2 {}
-''');
-    newFile(b, content: r'''
-export 'a.dart' show A2;
-class B {}
-''');
-    _assertExportedTopLevelDeclarations(b, ['A2', 'B']);
-  }
-
-  test_exportedTopLevelDeclarations_export_show2() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    String c = convertPath('/aaa/lib/c.dart');
-    String d = convertPath('/aaa/lib/d.dart');
-    newFile(a, content: r'''
-export 'b.dart' show Foo;
-export 'c.dart' show Bar;
-''');
-    newFile(b, content: r'''
-export 'd.dart';
-''');
-    newFile(c, content: r'''
-export 'd.dart';
-''');
-    newFile(d, content: r'''
-class Foo {}
-class Bar {}
-''');
-    _assertExportedTopLevelDeclarations(a, ['Foo', 'Bar']);
-  }
-
-  test_exportedTopLevelDeclarations_import() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class A {}
-''');
-    newFile(b, content: r'''
-import 'a.dart';
-class B {}
-''');
-    _assertExportedTopLevelDeclarations(b, ['B']);
-  }
-
-  test_exportedTopLevelDeclarations_parts() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String a2 = convertPath('/aaa/lib/a2.dart');
-    newFile(a, content: r'''
-library lib;
-part 'a2.dart';
-class A1 {}
-''');
-    newFile(a2, content: r'''
-part of lib;
-class A2 {}
-''');
-    _assertExportedTopLevelDeclarations(a, ['A1', 'A2']);
-  }
-
   test_getFileForPath_doesNotExist() {
     String path = convertPath('/aaa/lib/a.dart');
     FileState file = fileSystemState.getFileForPath(path);
@@ -811,52 +567,6 @@
     expect(file.referencedNames, unorderedEquals(['A', 'B', 'C', 'D']));
   }
 
-  test_topLevelDeclarations() {
-    String path = convertPath('/aaa/lib/a.dart');
-    newFile(path, content: r'''
-class C {}
-typedef F();
-enum E {E1, E2}
-mixin M {}
-void f() {}
-var V1;
-get V2 => null;
-set V3(_) {}
-get V4 => null;
-set V4(_) {}
-
-class _C {}
-typedef _F();
-enum _E {E1, E2}
-mixin _M {}
-void _f() {}
-var _V1;
-get _V2 => null;
-set _V3(_) {}
-''');
-    FileState file = fileSystemState.getFileForPath(path);
-
-    Map<String, TopLevelDeclaration> declarations = file.topLevelDeclarations;
-
-    void assertHas(String name, TopLevelDeclarationKind kind) {
-      expect(declarations[name]?.kind, kind);
-    }
-
-    expect(
-      declarations.keys,
-      unorderedEquals(['C', 'F', 'E', 'M', 'f', 'V1', 'V2', 'V3', 'V4']),
-    );
-    assertHas('C', TopLevelDeclarationKind.type);
-    assertHas('F', TopLevelDeclarationKind.type);
-    assertHas('E', TopLevelDeclarationKind.type);
-    assertHas('M', TopLevelDeclarationKind.type);
-    assertHas('f', TopLevelDeclarationKind.function);
-    assertHas('V1', TopLevelDeclarationKind.variable);
-    assertHas('V2', TopLevelDeclarationKind.variable);
-    assertHas('V3', TopLevelDeclarationKind.variable);
-    assertHas('V4', TopLevelDeclarationKind.variable);
-  }
-
   test_transitiveSignature() {
     String pa = convertPath('/aaa/lib/a.dart');
     String pb = convertPath('/aaa/lib/b.dart');
@@ -917,24 +627,11 @@
     expect(bSignature, isNot(aSignature));
   }
 
-  void _assertExportedTopLevelDeclarations(String path, List<String> expected) {
-    FileState file = fileSystemState.getFileForPath(path);
-    Map<String, TopLevelDeclaration> declarations =
-        file.exportedTopLevelDeclarations;
-    expect(declarations.keys, unorderedEquals(expected));
-  }
-
   void _assertFilesWithoutLibraryCycle(List<FileState> expected) {
     var actual = fileSystemState.test.filesWithoutLibraryCycle;
     expect(_excludeSdk(actual), unorderedEquals(expected));
   }
 
-  void _assertHasComputedExportedDeclarations(List<String> expectedPathList) {
-    FileSystemStateTestView test = fileSystemState.test;
-    expect(test.librariesWithComputedExportedDeclarations.map((f) => f.path),
-        unorderedEquals(expectedPathList));
-  }
-
   void _assertIsUnresolvedFile(FileState file) {
     expect(file.path, isNull);
     expect(file.uri, isNull);
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index a4217fe..56fb0c4 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -883,6 +883,19 @@
     assertThat(element)..isReferencedAt('p: 1', true);
   }
 
+  test_isReferencedBy_ParameterElement_genericFunctionType() async {
+    await _indexTestUnit('''
+typedef F = void Function({int p});
+
+void main() {
+  F f;
+  f(p: 0);
+}
+''');
+    // We should not crash because of reference to "p" - a named parameter
+    // of a generic function type.
+  }
+
   test_isReferencedBy_ParameterElement_optionalPositional() async {
     await _indexTestUnit('''
 foo([p]) {
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index 555c2ec..055a4c0 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -73,6 +73,12 @@
     expect(library.getType('C'), isNull);
   }
 
+  test_getLibraryByUri_unresolvedUri() async {
+    expect(() async {
+      await session.getLibraryByUri('package:foo/foo.dart');
+    }, throwsArgumentError);
+  }
+
   test_getParsedLibrary() async {
     newFile(testPath, content: r'''
 class A {}
diff --git a/pkg/analyzer/test/src/dart/analysis/test_all.dart b/pkg/analyzer/test/src/dart/analysis/test_all.dart
index 481b428..689b3d4 100644
--- a/pkg/analyzer/test/src/dart/analysis/test_all.dart
+++ b/pkg/analyzer/test/src/dart/analysis/test_all.dart
@@ -26,6 +26,7 @@
 import 'search_test.dart' as search;
 import 'session_helper_test.dart' as session_helper;
 import 'session_test.dart' as session;
+import 'unlinked_api_signature_test.dart' as unlinked_api_signature;
 import 'uri_converter_test.dart' as uri_converter;
 
 main() {
@@ -52,6 +53,7 @@
     search.main();
     session.main();
     session_helper.main();
+    unlinked_api_signature.main();
     uri_converter.main();
   }, name: 'analysis');
 }
diff --git a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
new file mode 100644
index 0000000..8222c70
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
@@ -0,0 +1,851 @@
+// Copyright (c) 2019, 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:analyzer/src/dart/analysis/unlinked_api_signature.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../ast/parse_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnitApiSignatureTest);
+  });
+}
+
+@reflectiveTest
+class UnitApiSignatureTest extends ParseBase {
+  void assertNotSameSignature(String oldCode, String newCode) {
+    assertSignature(oldCode, newCode, same: false);
+  }
+
+  void assertSameSignature(String oldCode, String newCode) {
+    assertSignature(oldCode, newCode, same: true);
+  }
+
+  void assertSignature(String oldCode, String newCode, {bool same}) {
+    var path = convertPath('/test.dart');
+
+    newFile(path, content: oldCode);
+    var oldUnit = parseUnit(path).unit;
+    var oldSignature = computeUnlinkedApiSignature(oldUnit);
+
+    newFile(path, content: newCode);
+    var newUnit = parseUnit(path).unit;
+    var newSignature = computeUnlinkedApiSignature(newUnit);
+
+    if (same) {
+      expect(newSignature, oldSignature);
+    } else {
+      expect(newSignature, isNot(oldSignature));
+    }
+  }
+
+  test_class_annotation() async {
+    assertNotSameSignature(r'''
+const a = 0;
+
+class C {}
+''', r'''
+const a = 0;
+
+@a
+class C {}
+''');
+  }
+
+  test_class_constructor_block_to_empty() {
+    assertSameSignature(r'''
+class C {
+  C() {
+    var v = 1;
+  }
+}
+''', r'''
+class C {
+  C();
+}
+''');
+  }
+
+  test_class_constructor_body() {
+    assertSameSignature(r'''
+class C {
+  C() {
+    var v = 1;
+  }
+}
+''', r'''
+class C {
+  C() {
+    var v = 2;
+  }
+}
+''');
+  }
+
+  test_class_constructor_empty_to_block() {
+    assertSameSignature(r'''
+class C {
+  C();
+}
+''', r'''
+class C {
+  C() {
+    var v = 1;
+  }
+}
+''');
+  }
+
+  test_class_constructor_initializer_const() {
+    assertNotSameSignature(r'''
+class C {
+  final int f;
+  const C() : f = 1;
+}
+''', r'''
+class C {
+  final int f;
+  const C() : f = 2;
+}
+''');
+  }
+
+  test_class_constructor_initializer_empty() {
+    assertSameSignature(r'''
+class C {
+  C.foo() : ;
+}
+''', r'''
+class C {
+  C.foo() : f;
+}
+''');
+  }
+
+  test_class_constructor_initializer_notConst() {
+    assertSameSignature(r'''
+class C {
+  final int f;
+  C.foo() : f = 1;
+  const C.bar();
+}
+''', r'''
+class C {
+  final int f;
+  C.foo() : f = 2;
+  const C.bar();
+}
+''');
+  }
+
+  test_class_constructor_parameters_add() {
+    assertNotSameSignature(r'''
+class C {
+  C(int a);
+}
+''', r'''
+class C {
+  C(int a, int b);
+}
+''');
+  }
+
+  test_class_constructor_parameters_remove() {
+    assertNotSameSignature(r'''
+class C {
+  C(int a, int b);
+}
+''', r'''
+class C {
+  C(int a);
+}
+''');
+  }
+
+  test_class_constructor_parameters_rename() {
+    assertNotSameSignature(r'''
+class C {
+  C(int a);
+}
+''', r'''
+class C {
+  C(int b);
+}
+''');
+  }
+
+  test_class_constructor_parameters_type() {
+    assertNotSameSignature(r'''
+class C {
+  C(int p);
+}
+''', r'''
+class C {
+  C(double p);
+}
+''');
+  }
+
+  test_class_extends() {
+    assertNotSameSignature(r'''
+class A {}
+class B {}
+''', r'''
+class A {}
+class B extends A {}
+''');
+  }
+
+  test_class_field_withoutType() {
+    assertNotSameSignature(r'''
+class C {
+  var a = 1;
+}
+''', r'''
+class C {
+  var a = 2;
+}
+''');
+  }
+
+  test_class_field_withoutType2() {
+    assertNotSameSignature(r'''
+class C {
+  var a = 1, b = 2, c, d = 4;
+}
+''', r'''
+class C {
+  var a = 1, b, c = 3, d = 4;
+}
+''');
+  }
+
+  test_class_field_withType() {
+    assertSameSignature(r'''
+class C {
+  int a = 1, b, c = 3;
+}
+''', r'''
+class C {
+  int a = 0, b = 2, c;
+}
+''');
+  }
+
+  test_class_field_withType_const() {
+    assertNotSameSignature(r'''
+class C {
+  static const int a = 1;
+}
+''', r'''
+class C {
+  static const int a = 2;
+}
+''');
+  }
+
+  test_class_field_withType_final_hasConstConstructor() {
+    assertNotSameSignature(r'''
+class C {
+  final int a = 1;
+  const C();
+}
+''', r'''
+class C {
+  final int a = 2;
+  const C();
+}
+''');
+  }
+
+  test_class_field_withType_final_noConstConstructor() {
+    assertSameSignature(r'''
+class C {
+  final int a = 1;
+}
+''', r'''
+class C {
+  final int a = 2;
+}
+''');
+  }
+
+  test_class_field_withType_hasConstConstructor() {
+    assertSameSignature(r'''
+class C {
+  int a = 1;
+  const C();
+}
+''', r'''
+class C {
+  int a = 2;
+  const C();
+}
+''');
+  }
+
+  test_class_field_withType_static_final_hasConstConstructor() {
+    assertSameSignature(r'''
+class C {
+  static final int a = 1;
+  const C();
+}
+''', r'''
+class C {
+  static final int a = 2;
+  const C();
+}
+''');
+  }
+
+  test_class_field_withType_static_hasConstConstructor() {
+    assertSameSignature(r'''
+class C {
+  static int a = 1;
+  const C();
+}
+''', r'''
+class C {
+  static int a = 2;
+  const C();
+}
+''');
+  }
+
+  test_class_implements() {
+    assertNotSameSignature(r'''
+class A {}
+class B {}
+''', r'''
+class A {}
+class B implements A {}
+''');
+  }
+
+  test_class_method_annotation() {
+    assertNotSameSignature(r'''
+const a = 0;
+
+class C {
+  void foo() {}
+}
+''', r'''
+const a = 0;
+
+class C {
+  @a
+  void foo() {}
+}
+''');
+  }
+
+  test_class_method_body_async_to_sync() {
+    assertSameSignature(r'''
+class C {
+  Future foo() async {}
+}
+''', r'''
+class C {
+  Future foo() {}
+}
+''');
+  }
+
+  test_class_method_body_block() {
+    assertSameSignature(r'''
+class C {
+  int foo() {
+    return 1;
+  }
+}
+''', r'''
+class C {
+  int foo() {
+    return 2;
+  }
+}
+''');
+  }
+
+  test_class_method_body_block_to_expression() {
+    assertSameSignature(r'''
+class C {
+  int foo() {
+    return 1;
+  }
+}
+''', r'''
+class C {
+  int foo() => 2;
+}
+''');
+  }
+
+  test_class_method_body_empty_to_block() {
+    assertSameSignature(r'''
+class C {
+  int foo();
+}
+''', r'''
+class C {
+  int foo() {
+    var v = 0;
+  }
+}
+''');
+  }
+
+  test_class_method_body_expression() {
+    assertSameSignature(r'''
+class C {
+  int foo() => 1;
+}
+''', r'''
+class C {
+  int foo() => 2;
+}
+''');
+  }
+
+  test_class_method_body_sync_to_async() {
+    assertSameSignature(r'''
+class C {
+  Future foo() {}
+}
+''', r'''
+class C {
+  Future foo() async {}
+}
+''');
+  }
+
+  test_class_method_getter_body_block_to_expression() {
+    assertSameSignature(r'''
+class C {
+  int get foo {
+    return 1;
+  }
+}
+''', r'''
+class C {
+  int get foo => 2;
+}
+''');
+  }
+
+  test_class_method_getter_body_empty_to_expression() {
+    assertSameSignature(r'''
+class C {
+  int get foo;
+}
+''', r'''
+class C {
+  int get foo => 2;
+}
+''');
+  }
+
+  test_class_method_parameters_add() {
+    assertNotSameSignature(r'''
+class C {
+  foo(int a) {}
+}
+''', r'''
+class C {
+  foo(int a, int b) {}
+}
+''');
+  }
+
+  test_class_method_parameters_remove() {
+    assertNotSameSignature(r'''
+class C {
+  foo(int a, int b) {}
+}
+''', r'''
+class C {
+  foo(int a) {}
+}
+''');
+  }
+
+  test_class_method_parameters_rename() {
+    assertNotSameSignature(r'''
+class C {
+  void foo(int a) {}
+}
+''', r'''
+class C {
+  void foo(int b) {}
+}
+''');
+  }
+
+  test_class_method_parameters_type() {
+    assertNotSameSignature(r'''
+class C {
+  void foo(int p) {}
+}
+''', r'''
+class C {
+  void foo(double p) {}
+}
+''');
+  }
+
+  test_class_method_returnType() {
+    assertNotSameSignature(r'''
+class C {
+  int foo() => 0;
+}
+''', r'''
+class C {
+  num foo() => 0;
+}
+''');
+  }
+
+  test_class_method_typeParameters_add() async {
+    assertNotSameSignature(r'''
+class C {
+  void foo() {}
+}
+''', r'''
+class C {
+  void foo<T>() {}
+}
+''');
+  }
+
+  test_class_method_typeParameters_remove() {
+    assertNotSameSignature(r'''
+class C {
+  void foo<T>() {}
+}
+''', r'''
+class C {
+  void foo() {}
+}
+''');
+  }
+
+  test_class_method_typeParameters_rename() {
+    assertNotSameSignature(r'''
+class C {
+  void foo<T>() {}
+}
+''', r'''
+class C {
+  void foo<U>() {}
+}
+''');
+  }
+
+  test_class_modifier() {
+    assertNotSameSignature(r'''
+class C {}
+''', r'''
+abstract class C {}
+''');
+  }
+
+  test_class_with() {
+    assertNotSameSignature(r'''
+class A {}
+class B {}
+class C extends A {}
+''', r'''
+class A {}
+class B {}
+class C extends A with B {}
+''');
+  }
+
+  test_commentAdd() {
+    assertSameSignature(r'''
+var a = 1;
+var b = 2;
+var c = 3;
+''', r'''
+var a = 1; // comment
+
+/// comment 1
+/// comment 2
+var b = 2;
+
+/**
+ *  Comment
+ */
+var c = 3;
+''');
+  }
+
+  test_commentRemove() {
+    assertSameSignature(r'''
+var a = 1; // comment
+
+/// comment 1
+/// comment 2
+var b = 2;
+
+/**
+ *  Comment
+ */
+var c = 3;
+''', r'''
+var a = 1;
+var b = 2;
+var c = 3;
+''');
+  }
+
+  test_function_annotation() {
+    assertNotSameSignature(r'''
+const a = 0;
+
+void foo() {}
+''', r'''
+const a = 0;
+
+@a
+void foo() {}
+''');
+  }
+
+  test_function_body_async_to_sync() {
+    assertSameSignature(r'''
+Future foo() async {}
+''', r'''
+Future foo() {}
+''');
+  }
+
+  test_function_body_block() {
+    assertSameSignature(r'''
+int foo() {
+  return 1;
+}
+''', r'''
+int foo() {
+  return 2;
+}
+''');
+  }
+
+  test_function_body_block_to_expression() {
+    assertSameSignature(r'''
+int foo() {
+  return 1;
+}
+''', r'''
+int foo() => 2;
+''');
+  }
+
+  test_function_body_expression() {
+    assertSameSignature(r'''
+int foo() => 1;
+''', r'''
+int foo() => 2;
+''');
+  }
+
+  test_function_body_sync_to_async() {
+    assertSameSignature(r'''
+Future foo() {}
+''', r'''
+Future foo() async {}
+''');
+  }
+
+  test_function_getter_block_to_expression() {
+    assertSameSignature(r'''
+int get foo {
+  return 1;
+}
+''', r'''
+int get foo => 2;
+''');
+  }
+
+  test_function_parameters_rename() {
+    assertNotSameSignature(r'''
+void foo(int a) {}
+''', r'''
+void foo(int b) {}
+''');
+  }
+
+  test_function_parameters_type() {
+    assertNotSameSignature(r'''
+void foo(int p) {}
+''', r'''
+void foo(double p) {}
+''');
+  }
+
+  test_function_returnType() {
+    assertNotSameSignature(r'''
+int foo() => 0;
+''', r'''
+num foo() => 0;
+''');
+  }
+
+  test_function_typeParameters_add() {
+    assertNotSameSignature(r'''
+void foo() {}
+''', r'''
+void foo<T>() {}
+''');
+  }
+
+  test_function_typeParameters_remove() {
+    assertNotSameSignature(r'''
+void foo<T>() {}
+''', r'''
+void foo() {}
+''');
+  }
+
+  test_function_typeParameters_rename() {
+    assertNotSameSignature(r'''
+void foo<T>() {}
+''', r'''
+void foo<U>() {}
+''');
+  }
+
+  test_issue34850() {
+    assertNotSameSignature(r'''
+foo
+Future<List<int>> bar() {}
+''', r'''
+foo
+Future<List<int>> bar(int x) {}
+''');
+  }
+
+  test_mixin_field_withoutType() {
+    assertNotSameSignature(r'''
+mixin M {
+  var a = 1;
+}
+''', r'''
+mixin M {
+  var a = 2;
+}
+''');
+  }
+
+  test_mixin_field_withType() {
+    assertSameSignature(r'''
+mixin M {
+  int a = 1, b, c = 3;
+}
+''', r'''
+mixin M {
+  int a = 0, b = 2, c;
+}
+''');
+  }
+
+  test_mixin_implements() {
+    assertNotSameSignature(r'''
+class A {}
+mixin M {}
+''', r'''
+class A {}
+mixin M implements A {}
+''');
+  }
+
+  test_mixin_method_body_block() {
+    assertSameSignature(r'''
+mixin M {
+  int foo() {
+    return 1;
+  }
+}
+''', r'''
+mixin M {
+  int foo() {
+    return 2;
+  }
+}
+''');
+  }
+
+  test_mixin_method_body_expression() {
+    assertSameSignature(r'''
+mixin M {
+  int foo() => 1;
+}
+''', r'''
+mixin M {
+  int foo() => 2;
+}
+''');
+  }
+
+  test_mixin_on() {
+    assertNotSameSignature(r'''
+class A {}
+mixin M {}
+''', r'''
+class A {}
+mixin M on A {}
+''');
+  }
+
+  test_topLevelVariable_withoutType() {
+    assertNotSameSignature(r'''
+var a = 1;
+''', r'''
+var a = 2;
+''');
+  }
+
+  test_topLevelVariable_withoutType2() {
+    assertNotSameSignature(r'''
+var a = 1, b = 2, c, d = 4;;
+''', r'''
+var a = 1, b, c = 3, d = 4;;
+''');
+  }
+
+  test_topLevelVariable_withType() {
+    assertSameSignature(r'''
+int a = 1, b, c = 3;
+''', r'''
+int a = 0, b = 2, c;
+''');
+  }
+
+  test_topLevelVariable_withType_const() {
+    assertNotSameSignature(r'''
+const int a = 1;
+''', r'''
+const int a = 2;
+''');
+  }
+
+  test_topLevelVariable_withType_final() {
+    assertSameSignature(r'''
+final int a = 1;
+''', r'''
+final int a = 2;
+''');
+  }
+
+  test_typedef_generic_parameters_type() {
+    assertNotSameSignature(r'''
+typedef F = void Function(int);
+''', r'''
+typedef F = void Function(double);
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/ast/parse_base.dart b/pkg/analyzer/test/src/dart/ast/parse_base.dart
index 78f17d5..2dd3de6 100644
--- a/pkg/analyzer/test/src/dart/ast/parse_base.dart
+++ b/pkg/analyzer/test/src/dart/ast/parse_base.dart
@@ -22,24 +22,20 @@
     var content = file.readAsStringSync();
 
     var analysisOptions = this.analysisOptions;
-    var experimentStatus = analysisOptions.experimentStatus;
+    var featureSet = analysisOptions.contextFeatures;
 
     var errorListener = RecordingErrorListener();
 
     var reader = CharSequenceReader(content);
-    var scanner = Scanner(source, reader, errorListener);
+    var scanner = Scanner(source, reader, errorListener)
+      ..configureFeatures(featureSet);
 
-    scanner.enableGtGtGt = experimentStatus.constant_update_2018;
     var token = scanner.tokenize();
 
     var useFasta = analysisOptions.useFastaParser;
-    var parser = Parser(source, errorListener, useFasta: useFasta);
+    var parser = Parser(source, errorListener,
+        featureSet: featureSet, useFasta: useFasta);
     parser.enableOptionalNewAndConst = true;
-    parser.enableNonNullable = experimentStatus.non_nullable;
-    parser.enableSpreadCollections = experimentStatus.spread_collections;
-    parser.enableControlFlowCollections =
-        experimentStatus.control_flow_collections;
-    parser.enableTripleShift = experimentStatus.triple_shift;
 
     var unit = parser.parseCompilationUnit(token);
     unit.lineInfo = LineInfo(scanner.lineStarts);
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index 31e9a56..00cf65e 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -640,7 +640,7 @@
   void test_visitPartDirective() {
     PartDirective fromNode = AstTestFactory.partDirective2("part.dart");
     LibraryElement element = new LibraryElementImpl.forNode(
-        null, null, AstTestFactory.libraryIdentifier2(["lib"]));
+        null, null, AstTestFactory.libraryIdentifier2(["lib"]), true);
     fromNode.element = element;
     PartDirective toNode = AstTestFactory.partDirective2("part.dart");
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -651,7 +651,7 @@
     PartOfDirective fromNode = AstTestFactory.partOfDirective(
         AstTestFactory.libraryIdentifier2(["lib"]));
     LibraryElement element = new LibraryElementImpl.forNode(
-        null, null, AstTestFactory.libraryIdentifier2(["lib"]));
+        null, null, AstTestFactory.libraryIdentifier2(["lib"]), true);
     fromNode.element = element;
     PartOfDirective toNode = AstTestFactory.partOfDirective(
         AstTestFactory.libraryIdentifier2(["lib"]));
@@ -1713,6 +1713,48 @@
         AstTestFactory.extendsClause(AstTestFactory.typeName4("C")));
   }
 
+  void test_visitExtensionDeclaration_empty() {
+    _assertSource(
+        'extension E on C {}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E', extendedType: AstTestFactory.typeName4('C')));
+  }
+
+  void test_visitExtensionDeclaration_multipleMember() {
+    _assertSource(
+        'extension E on C {var a; var b;}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            extendedType: AstTestFactory.typeName4('C'),
+            members: [
+              AstTestFactory.fieldDeclaration2(false, Keyword.VAR,
+                  [AstTestFactory.variableDeclaration('a')]),
+              AstTestFactory.fieldDeclaration2(
+                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('b')])
+            ]));
+  }
+
+  void test_visitExtensionDeclaration_parameters() {
+    _assertSource(
+        'extension E<T> on C {}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            typeParameters: AstTestFactory.typeParameterList(['T']),
+            extendedType: AstTestFactory.typeName4('C')));
+  }
+
+  void test_visitExtensionDeclaration_singleMember() {
+    _assertSource(
+        'extension E on C {var a;}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            extendedType: AstTestFactory.typeName4('C'),
+            members: [
+              AstTestFactory.fieldDeclaration2(
+                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('a')])
+            ]));
+  }
+
   void test_visitFieldDeclaration_instance() {
     _assertSource(
         "var a;",
@@ -2351,6 +2393,16 @@
         "f()", AstTestFactory.functionTypedFormalParameter(null, "f"));
   }
 
+  void test_visitFunctionTypedFormalParameter_nullable() {
+    _assertSource(
+        "T f()?",
+        astFactory.functionTypedFormalParameter2(
+            returnType: AstTestFactory.typeName4("T"),
+            identifier: AstTestFactory.identifier3('f'),
+            parameters: AstTestFactory.formalParameterList([]),
+            question: TokenFactory.tokenFromType(TokenType.QUESTION)));
+  }
+
   void test_visitFunctionTypedFormalParameter_type() {
     _assertSource(
         "T f()",
@@ -4427,6 +4479,48 @@
         AstTestFactory.extendsClause(AstTestFactory.typeName4("C")));
   }
 
+  void test_visitExtensionDeclaration_empty() {
+    _assertSource(
+        'extension E on C {}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E', extendedType: AstTestFactory.typeName4('C')));
+  }
+
+  void test_visitExtensionDeclaration_multipleMember() {
+    _assertSource(
+        'extension E on C {var a; var b;}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            extendedType: AstTestFactory.typeName4('C'),
+            members: [
+              AstTestFactory.fieldDeclaration2(false, Keyword.VAR,
+                  [AstTestFactory.variableDeclaration('a')]),
+              AstTestFactory.fieldDeclaration2(
+                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('b')])
+            ]));
+  }
+
+  void test_visitExtensionDeclaration_parameters() {
+    _assertSource(
+        'extension E<T> on C {}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            typeParameters: AstTestFactory.typeParameterList(['T']),
+            extendedType: AstTestFactory.typeName4('C')));
+  }
+
+  void test_visitExtensionDeclaration_singleMember() {
+    _assertSource(
+        'extension E on C {var a;}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            extendedType: AstTestFactory.typeName4('C'),
+            members: [
+              AstTestFactory.fieldDeclaration2(
+                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('a')])
+            ]));
+  }
+
   void test_visitFieldDeclaration_instance() {
     _assertSource(
         "var a;",
@@ -5065,6 +5159,16 @@
         "f()", AstTestFactory.functionTypedFormalParameter(null, "f"));
   }
 
+  void test_visitFunctionTypedFormalParameter_nullable() {
+    _assertSource(
+        "T f()?",
+        astFactory.functionTypedFormalParameter2(
+            returnType: AstTestFactory.typeName4("T"),
+            identifier: AstTestFactory.identifier3('f'),
+            parameters: AstTestFactory.formalParameterList([]),
+            question: TokenFactory.tokenFromType(TokenType.QUESTION)));
+  }
+
   void test_visitFunctionTypedFormalParameter_type() {
     _assertSource(
         "T f()",
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 36e49bc..6644cb8 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -834,13 +834,6 @@
 @reflectiveTest
 class ConstantVisitorWithFlowControlAndSpreadCollectionsTest
     extends ConstantVisitorTestSupport {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_listLiteral_ifElement_false_withElse() async {
     await _resolveTestCode('''
 const c = [1, if (1 < 0) 2 else 3, 4];
diff --git a/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
index c26a62f..a18956a 100644
--- a/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/constant/potentially_constant.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -14,7 +13,6 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(IsConstantTypeExpressionTest);
     defineReflectiveTests(PotentiallyConstantTest);
-    defineReflectiveTests(PotentiallyConstantWithUIAsCodeTest);
   });
 }
 
@@ -195,6 +193,32 @@
             ]);
   }
 
+  test_ifElement_then() async {
+    await _assertConst(r'''
+const a = 0;
+const b = 0;
+var x = const [if (a) b];
+''', () => _xInitializer());
+  }
+
+  test_ifElement_then_final() async {
+    await _assertNotConst(r'''
+final a = 0;
+final b = 0;
+var x = const [if (a) b];
+''', () => _xInitializer(),
+        () => [findNode.simple('a)'), findNode.simple('b]')]);
+  }
+
+  test_ifElement_thenElse() async {
+    await _assertConst(r'''
+const a = 0;
+const b = 0;
+const c = 0;
+var x = const [if (a) b else c];
+''', () => _xInitializer());
+  }
+
   test_instanceCreation() async {
     await _assertNotConst(r'''
 class A {
@@ -747,6 +771,19 @@
 ''', () => findNode.constructorFieldInitializer('f =').expression);
   }
 
+  test_simpleIdentifier_parameterOfConstConstructor_notConst() async {
+    await _assertNotConst(
+      r'''
+class C {
+  final int f;
+  C(int a) : f = a + 1;
+}
+''',
+      () => findNode.constructorFieldInitializer('f =').expression,
+      () => [findNode.simple('a +')],
+    );
+  }
+
   test_simpleIdentifier_topVar_const() async {
     await _assertConst(r'''
 const a = 0;
@@ -771,6 +808,20 @@
 ''', () => _xInitializer());
   }
 
+  test_spreadElement() async {
+    await _assertConst(r'''
+const a = [0, 1, 2];
+var x = const [...a];
+''', () => _xInitializer());
+  }
+
+  test_spreadElement_final() async {
+    await _assertNotConst(r'''
+final a = [0, 1, 2];
+var x = const [...a];
+''', () => _xInitializer(), () => [findNode.simple('a];')]);
+  }
+
   test_stringInterpolation_topVar_const() async {
     await _assertConst(r'''
 const a = 0;
@@ -820,50 +871,3 @@
     return findNode.variableDeclaration('x = ').initializer;
   }
 }
-
-@reflectiveTest
-class PotentiallyConstantWithUIAsCodeTest extends PotentiallyConstantTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
-
-  test_ifElement_then() async {
-    await _assertConst(r'''
-const a = 0;
-const b = 0;
-var x = const [if (a) b];
-''', () => _xInitializer());
-  }
-
-  test_ifElement_then_final() async {
-    await _assertNotConst(r'''
-final a = 0;
-final b = 0;
-var x = const [if (a) b];
-''', () => _xInitializer(),
-        () => [findNode.simple('a)'), findNode.simple('b]')]);
-  }
-
-  test_ifElement_thenElse() async {
-    await _assertConst(r'''
-const a = 0;
-const b = 0;
-const c = 0;
-var x = const [if (a) b else c];
-''', () => _xInitializer());
-  }
-
-  test_spreadElement() async {
-    await _assertConst(r'''
-const a = [0, 1, 2];
-var x = const [...a];
-''', () => _xInitializer());
-  }
-
-  test_spreadElement_final() async {
-    await _assertNotConst(r'''
-final a = [0, 1, 2];
-var x = const [...a];
-''', () => _xInitializer(), () => [findNode.simple('a];')]);
-  }
-}
diff --git a/pkg/analyzer/test/src/dart/constant/value_test.dart b/pkg/analyzer/test/src/dart/constant/value_test.dart
index b6c7046..521182b 100644
--- a/pkg/analyzer/test/src/dart/constant/value_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/value_test.dart
@@ -595,10 +595,6 @@
     expect(_doubleValue(null).hasKnownValue, isFalse);
   }
 
-  void test_hasKnownValue_dynamic() {
-    expect(_dynamicValue().hasKnownValue, isTrue);
-  }
-
   void test_hasKnownValue_int_known() {
     expect(_intValue(23).hasKnownValue, isTrue);
   }
@@ -611,10 +607,6 @@
     expect(_listValue().hasKnownValue, isTrue);
   }
 
-  void test_hasKnownValue_list_invalidElement() {
-    expect(_listValue([_dynamicValue()]).hasKnownValue, isTrue);
-  }
-
   void test_hasKnownValue_list_valid() {
     expect(_listValue([_intValue(23)]).hasKnownValue, isTrue);
   }
@@ -623,16 +615,6 @@
     expect(_mapValue().hasKnownValue, isTrue);
   }
 
-  void test_hasKnownValue_map_invalidKey() {
-    expect(_mapValue([_dynamicValue(), _stringValue("value")]).hasKnownValue,
-        isTrue);
-  }
-
-  void test_hasKnownValue_map_invalidValue() {
-    expect(_mapValue([_stringValue("key"), _dynamicValue()]).hasKnownValue,
-        isTrue);
-  }
-
   void test_hasKnownValue_map_valid() {
     expect(
         _mapValue([_stringValue("key"), _stringValue("value")]).hasKnownValue,
@@ -643,10 +625,6 @@
     expect(_nullValue().hasKnownValue, isTrue);
   }
 
-  void test_hasKnownValue_num() {
-    expect(_numValue().hasKnownValue, isFalse);
-  }
-
   void test_hasKnownValue_string_known() {
     expect(_stringValue("twenty-three").hasKnownValue, isTrue);
   }
@@ -801,10 +779,6 @@
     expect(_doubleValue(null).isBoolNumStringOrNull, isTrue);
   }
 
-  void test_isBoolNumStringOrNull_dynamic() {
-    expect(_dynamicValue().isBoolNumStringOrNull, isTrue);
-  }
-
   void test_isBoolNumStringOrNull_int_known() {
     expect(_intValue(23).isBoolNumStringOrNull, isTrue);
   }
@@ -821,10 +795,6 @@
     expect(_nullValue().isBoolNumStringOrNull, isTrue);
   }
 
-  void test_isBoolNumStringOrNull_num() {
-    expect(_numValue().isBoolNumStringOrNull, isTrue);
-  }
-
   void test_isBoolNumStringOrNull_string_known() {
     expect(_stringValue("twenty-three").isBoolNumStringOrNull, isTrue);
   }
@@ -1944,11 +1914,6 @@
     }
   }
 
-  DartObjectImpl _dynamicValue() {
-    return new DartObjectImpl(
-        _typeProvider.nullType, DynamicState.DYNAMIC_STATE);
-  }
-
   DartObjectImpl _intValue(int value) {
     if (value == null) {
       return new DartObjectImpl(_typeProvider.intType, IntState.UNKNOWN_VALUE);
@@ -1977,10 +1942,6 @@
     return new DartObjectImpl(_typeProvider.nullType, NullState.NULL_STATE);
   }
 
-  DartObjectImpl _numValue() {
-    return new DartObjectImpl(_typeProvider.nullType, NumState.UNKNOWN_VALUE);
-  }
-
   DartObjectImpl _setValue([Set<DartObjectImpl> elements]) {
     return new DartObjectImpl(_typeProvider.setType,
         new SetState(elements ?? new Set<DartObjectImpl>()));
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index 1abce89..792b693 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -238,7 +238,7 @@
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
-    method.abstract = true;
+    method.isAbstract = true;
     classA.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
@@ -260,7 +260,7 @@
     classA.methods = <MethodElement>[inheritedMethod];
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
-    method.abstract = true;
+    method.isAbstract = true;
     classB.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
@@ -298,11 +298,11 @@
     // }
     LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.abstract = true;
+    classA.isAbstract = true;
     String methodName = "m";
     MethodElementImpl inheritedMethod =
         ElementFactory.methodElement(methodName, null);
-    inheritedMethod.abstract = true;
+    inheritedMethod.isAbstract = true;
     classA.methods = <MethodElement>[inheritedMethod];
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     MethodElement method = ElementFactory.methodElement(methodName, null);
@@ -485,7 +485,7 @@
     classA.methods = <MethodElement>[inheritedMethod];
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
-    method.abstract = true;
+    method.isAbstract = true;
     classB.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
@@ -524,11 +524,11 @@
     // }
     LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.abstract = true;
+    classA.isAbstract = true;
     String methodName = "m";
     MethodElementImpl inheritedMethod =
         ElementFactory.methodElement(methodName, null);
-    inheritedMethod.abstract = true;
+    inheritedMethod.isAbstract = true;
     classA.methods = <MethodElement>[inheritedMethod];
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     MethodElement method = ElementFactory.methodElement(methodName, null);
@@ -558,7 +558,7 @@
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     MethodElementImpl abstractMethod =
         ElementFactory.methodElement(methodName, null);
-    abstractMethod.abstract = true;
+    abstractMethod.isAbstract = true;
     classB.methods = <MethodElement>[abstractMethod];
     ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
@@ -1834,14 +1834,14 @@
     var s = ElementFactory.genericTypeAliasElement("s");
     t.function.returnType = s.type;
     s.function.returnType = t.type;
-    expect(t.type.toString(), '() \u2192 () \u2192 ...');
+    expect(t.type.toString(), '... Function() Function()');
   }
 
   void test_toString_recursive_via_interface_type() {
     var f = ElementFactory.genericTypeAliasElement('f');
     ClassElementImpl c = ElementFactory.classElement2('C', ['T']);
     f.function.returnType = c.type.instantiate([f.type]);
-    expect(f.type.toString(), '() \u2192 C<...>');
+    expect(f.type.toString(), 'C<...> Function()');
   }
 
   void test_typeParameters_genericLocalFunction_genericMethod_genericClass() {
@@ -3559,7 +3559,7 @@
   void test_creation() {
     expect(
         new LibraryElementImpl.forNode(createAnalysisContext(), null,
-            AstTestFactory.libraryIdentifier2(["l"])),
+            AstTestFactory.libraryIdentifier2(["l"]), true),
         isNotNull);
   }
 
@@ -3646,7 +3646,7 @@
   void test_setImports() {
     AnalysisContext context = createAnalysisContext();
     LibraryElementImpl library = new LibraryElementImpl.forNode(
-        context, null, AstTestFactory.libraryIdentifier2(["l1"]));
+        context, null, AstTestFactory.libraryIdentifier2(["l1"]), true);
     List<ImportElementImpl> expectedImports = [
       ElementFactory.importFor(ElementFactory.library(context, "l2"), null),
       ElementFactory.importFor(ElementFactory.library(context, "l3"), null)
@@ -3844,6 +3844,88 @@
     expect(type.resolveToBound(null), same(classS.type));
   }
 
+  void test_resolveToBound_bound_nullableInner() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound =
+        (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+    expect(type.resolveToBound(null), same(element.bound));
+  }
+
+  void test_resolveToBound_bound_nullableInnerOuter() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound =
+        (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+        .withNullability(NullabilitySuffix.question);
+    expect(type.resolveToBound(null), same(element.bound));
+  }
+
+  void test_resolveToBound_bound_nullableInnerStarOuter() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound =
+        (classS.type as TypeImpl).withNullability(NullabilitySuffix.star);
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+        .withNullability(NullabilitySuffix.question);
+    expect(
+        type.resolveToBound(null),
+        equals((classS.type as TypeImpl)
+            .withNullability(NullabilitySuffix.question)));
+  }
+
+  void test_resolveToBound_bound_nullableOuter() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound = classS.type;
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+        .withNullability(NullabilitySuffix.question);
+    expect(
+        type.resolveToBound(null),
+        equals((classS.type as TypeImpl)
+            .withNullability(NullabilitySuffix.question)));
+  }
+
+  void test_resolveToBound_bound_starInner() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound =
+        (classS.type as TypeImpl).withNullability(NullabilitySuffix.star);
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+    expect(type.resolveToBound(null), same(element.bound));
+  }
+
+  void test_resolveToBound_bound_starInnerNullableOuter() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound =
+        (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+        .withNullability(NullabilitySuffix.star);
+    expect(type.resolveToBound(null), same(element.bound));
+  }
+
+  void test_resolveToBound_bound_starOuter() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound = classS.type;
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+        .withNullability(NullabilitySuffix.star);
+    expect(
+        type.resolveToBound(null),
+        same(
+            (classS.type as TypeImpl).withNullability(NullabilitySuffix.star)));
+  }
+
   void test_resolveToBound_nestedBound() {
     ClassElementImpl classS = ElementFactory.classElement2("A");
     TypeParameterElementImpl elementE =
diff --git a/pkg/analyzer/test/src/dart/element/function_type_test.dart b/pkg/analyzer/test/src/dart/element/function_type_test.dart
index 975952b..d5bb2f7 100644
--- a/pkg/analyzer/test/src/dart/element/function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -46,7 +46,7 @@
 
   void basicChecks(FunctionType f,
       {element,
-      displayName: '() → dynamic',
+      displayName: 'dynamic Function()',
       returnType,
       namedParameterTypes: isEmpty,
       normalParameterNames: isEmpty,
@@ -148,7 +148,7 @@
     var e = new MockGenericTypeAliasElement('F');
     basicChecks(e.type, element: same(e), displayName: 'F', name: 'F');
     basicChecks(e.function.type,
-        element: same(e.function), displayName: '() → dynamic');
+        element: same(e.function), displayName: 'dynamic Function()');
   }
 
   test_forTypedef_innerAndOuterTypeParameter() {
@@ -172,7 +172,7 @@
         typeFormals: [same(t)]);
     basicChecks(e.function.type,
         element: same(e.function),
-        displayName: '<U>(U) → T',
+        displayName: 'T Function<U>(U)',
         returnType: same(t.type),
         typeArguments: [same(t.type)],
         typeParameters: [same(t)],
@@ -223,7 +223,7 @@
         returnType: same(t.type));
     basicChecks(e.function.type,
         element: same(e.function),
-        displayName: '<T>() → T',
+        displayName: 'T Function<T>()',
         returnType: same(t.type),
         typeFormals: [same(t)]);
   }
@@ -240,7 +240,7 @@
         parameters: [same(p)]);
     basicChecks(e.function.type,
         element: same(e.function),
-        displayName: '(dynamic) → dynamic',
+        displayName: 'dynamic Function(dynamic)',
         normalParameterNames: ['p'],
         normalParameterTypes: [same(dynamicType)],
         parameters: [same(p)]);
@@ -260,7 +260,7 @@
     if (bug_33302_fixed) {
       expect(fReturn.displayName, 'List<G>');
     } else {
-      expect(fReturn.displayName, 'List<() → List<...>>');
+      expect(fReturn.displayName, 'List<List<...> Function()>');
     }
     var fReturnArg = (fReturn as InterfaceType).typeArguments[0];
     expect(fReturnArg.element, same(g.function));
@@ -271,9 +271,10 @@
     basicChecks(f.function.type,
         element: same(f.function), displayName: isNotNull, returnType: fReturn);
     if (bug_33302_fixed) {
-      expect(f.function.type.displayName, '() → List<G>');
+      expect(f.function.type.displayName, 'List<G> Function()');
     } else {
-      expect(f.function.type.displayName, '() → List<() → List<...>>');
+      expect(
+          f.function.type.displayName, 'List<List<...> Function()> Function()');
     }
     basicChecks(g.type,
         element: same(g), displayName: 'G', name: 'G', returnType: isNotNull);
@@ -282,7 +283,7 @@
     if (bug_33302_fixed) {
       expect(gReturn.displayName, 'List<F>');
     } else {
-      expect(gReturn.displayName, 'List<() → List<...>>');
+      expect(gReturn.displayName, 'List<List<...> Function()>');
     }
     var gReturnArg = (gReturn as InterfaceType).typeArguments[0];
     expect(gReturnArg.element, same(f.function));
@@ -293,9 +294,10 @@
     basicChecks(g.function.type,
         element: same(g.function), displayName: isNotNull, returnType: gReturn);
     if (bug_33302_fixed) {
-      expect(g.function.type.displayName, '() → F');
+      expect(g.function.type.displayName, 'F Function()');
     } else {
-      expect(g.function.type.displayName, '() → List<() → List<...>>');
+      expect(
+          g.function.type.displayName, 'List<List<...> Function()> Function()');
     }
   }
 
@@ -326,9 +328,9 @@
         normalParameterNames: ['g'],
         returnType: same(voidType));
     if (bug_33302_fixed) {
-      expect(f.function.type.displayName, '(G) → void');
+      expect(f.function.type.displayName, 'void Function(G)');
     } else {
-      expect(f.function.type.displayName, '((...) → void) → void');
+      expect(f.function.type.displayName, 'void Function(void Function(...))');
     }
     basicChecks(g.type,
         element: same(g),
@@ -350,9 +352,9 @@
         normalParameterNames: ['f'],
         returnType: same(voidType));
     if (bug_33302_fixed) {
-      expect(g.function.type.displayName, '(F) → void');
+      expect(g.function.type.displayName, 'void Function(F)');
     } else {
-      expect(g.function.type.displayName, '((...) → void) → void');
+      expect(g.function.type.displayName, 'void Function(void Function(...))');
     }
   }
 
@@ -372,9 +374,9 @@
     basicChecks(f.function.type,
         element: same(f.function), displayName: isNotNull, returnType: fReturn);
     if (bug_33302_fixed) {
-      expect(f.function.type.displayName, '() → G');
+      expect(f.function.type.displayName, 'G Function()');
     } else {
-      expect(f.function.type.displayName, '() → () → ...');
+      expect(f.function.type.displayName, '... Function() Function()');
     }
     basicChecks(g.type,
         element: same(g), displayName: 'G', name: 'G', returnType: isNotNull);
@@ -385,9 +387,9 @@
     basicChecks(g.function.type,
         element: same(g.function), displayName: isNotNull, returnType: gReturn);
     if (bug_33302_fixed) {
-      expect(g.function.type.displayName, '() → F');
+      expect(g.function.type.displayName, 'F Function()');
     } else {
-      expect(g.function.type.displayName, '() → () → ...');
+      expect(g.function.type.displayName, '... Function() Function()');
     }
   }
 
@@ -397,7 +399,7 @@
         element: same(e), displayName: 'F', name: 'F', returnType: objectType);
     basicChecks(e.function.type,
         element: same(e.function),
-        displayName: '() → Object',
+        displayName: 'Object Function()',
         returnType: objectType);
   }
 
@@ -405,7 +407,7 @@
     var e = new MockGenericTypeAliasElement.withNullReturn('F');
     basicChecks(e.type, element: same(e), displayName: 'F', name: 'F');
     basicChecks(e.function.type,
-        element: same(e.function), displayName: '() → dynamic');
+        element: same(e.function), displayName: 'dynamic Function()');
   }
 
   test_forTypedef_typeParameter() {
@@ -421,7 +423,7 @@
         typeFormals: [same(t)]);
     basicChecks(e.function.type,
         element: same(e.function),
-        displayName: '() → T',
+        displayName: 'T Function()',
         returnType: same(t.type),
         typeArguments: [same(t.type)],
         typeParameters: [same(t)]);
@@ -440,7 +442,7 @@
     FunctionType instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: isNull,
-        displayName: '(Object) → Object',
+        displayName: 'Object Function(Object)',
         returnType: same(objectType),
         normalParameterNames: ['x'],
         normalParameterTypes: [same(objectType)],
@@ -467,7 +469,7 @@
     FunctionType instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: isNull,
-        displayName: '(int) → Object',
+        displayName: 'Object Function(int)',
         returnType: same(objectType),
         normalParameterNames: ['x'],
         normalParameterTypes: [same(intType)],
@@ -480,7 +482,7 @@
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
     basicChecks(f,
         element: isNull,
-        displayName: '({x: Object}) → dynamic',
+        displayName: 'dynamic Function({x: Object})',
         namedParameterTypes: {'x': same(objectType)},
         parameters: hasLength(1));
     expect(f.parameters[0].isNamed, isTrue);
@@ -493,11 +495,11 @@
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
     basicChecks(f,
         element: isNull,
-        displayName: '(Object) → dynamic',
+        displayName: 'dynamic Function(Object)',
         normalParameterNames: ['x'],
         normalParameterTypes: [same(objectType)],
         parameters: hasLength(1));
-    expect(f.parameters[0].isNotOptional, isTrue);
+    expect(f.parameters[0].isRequiredPositional, isTrue);
     expect(f.parameters[0].name, 'x');
     expect(f.parameters[0].type, same(objectType));
   }
@@ -508,7 +510,7 @@
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
     basicChecks(f,
         element: isNull,
-        displayName: '([Object]) → dynamic',
+        displayName: 'dynamic Function([Object])',
         optionalParameterNames: ['x'],
         optionalParameterTypes: [same(objectType)],
         parameters: hasLength(1));
@@ -521,7 +523,7 @@
     FunctionType f = new FunctionTypeImpl.synthetic(objectType, [], []);
     basicChecks(f,
         element: isNull,
-        displayName: '() → Object',
+        displayName: 'Object Function()',
         returnType: same(objectType));
   }
 
@@ -537,7 +539,7 @@
     var uSubstituted = substituted.typeFormals[0];
     basicChecks(substituted,
         element: isNull,
-        displayName: '<U extends Object>(Object, U) → Map<Object, U>',
+        displayName: 'Map<Object, U> Function<U extends Object>(Object, U)',
         returnType: mapOf(objectType, uSubstituted.type),
         typeFormals: [uSubstituted],
         normalParameterNames: ['x', 'y'],
@@ -562,7 +564,7 @@
     FunctionType substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: isNull,
-        displayName: '<U extends Object>(int) → int',
+        displayName: 'int Function<U extends Object>(int)',
         returnType: same(f.returnType),
         typeFormals: hasLength(1),
         normalParameterNames: ['x'],
@@ -582,7 +584,7 @@
     FunctionType substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: isNull,
-        displayName: '<U>(Object, U) → int',
+        displayName: 'int Function<U>(Object, U)',
         returnType: same(f.returnType),
         typeFormals: same(f.typeFormals),
         normalParameterNames: ['x', 'y'],
@@ -599,7 +601,7 @@
     FunctionType substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: isNull,
-        displayName: '<U>(U) → Object',
+        displayName: 'Object Function<U>(U)',
         returnType: same(objectType),
         typeFormals: same(f.typeFormals),
         normalParameterNames: ['x'],
@@ -622,7 +624,7 @@
     FunctionType f = new FunctionTypeImpl.synthetic(t.type, [t], []);
     basicChecks(f,
         element: isNull,
-        displayName: '<T>() → T',
+        displayName: 'T Function<T>()',
         returnType: same(t.type),
         typeFormals: [same(t)]);
   }
@@ -648,7 +650,7 @@
     var instantiated = f.instantiate([t.type]);
     basicChecks(instantiated,
         element: same(e),
-        displayName: '(T) → dynamic',
+        displayName: 'dynamic Function(T)',
         typeArguments: hasLength(1),
         typeParameters: [same(t)],
         normalParameterNames: ['x'],
@@ -671,7 +673,7 @@
     var instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: same(e),
-        displayName: '(Object) → dynamic',
+        displayName: 'dynamic Function(Object)',
         typeArguments: hasLength(1),
         typeParameters: [same(t)],
         normalParameterNames: ['x'],
@@ -690,7 +692,7 @@
     var instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: same(e),
-        displayName: '() → Object',
+        displayName: 'Object Function()',
         typeArguments: hasLength(1),
         typeParameters: [same(t)],
         returnType: same(objectType));
@@ -703,7 +705,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '({x: dynamic}) → dynamic',
+        displayName: 'dynamic Function({x: dynamic})',
         namedParameterTypes: {'x': same(dynamicType)},
         parameters: [same(p)]);
   }
@@ -715,7 +717,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '({x: Object}) → dynamic',
+        displayName: 'dynamic Function({x: Object})',
         namedParameterTypes: {'x': same(objectType)},
         parameters: [same(p)]);
   }
@@ -735,7 +737,7 @@
         element: same(e),
         typeArguments: [same(t.type)],
         typeParameters: [same(t)],
-        displayName: '() → T',
+        displayName: 'T Function()',
         returnType: same(t.type));
   }
 
@@ -745,7 +747,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '(dynamic) → dynamic',
+        displayName: 'dynamic Function(dynamic)',
         normalParameterNames: ['x'],
         normalParameterTypes: [same(dynamicType)],
         parameters: [same(p)]);
@@ -757,7 +759,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '(Object) → dynamic',
+        displayName: 'dynamic Function(Object)',
         normalParameterNames: ['x'],
         normalParameterTypes: [same(objectType)],
         parameters: [same(p)]);
@@ -770,7 +772,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '([dynamic]) → dynamic',
+        displayName: 'dynamic Function([dynamic])',
         optionalParameterNames: ['x'],
         optionalParameterTypes: [same(dynamicType)],
         parameters: [same(p)]);
@@ -783,7 +785,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '([Object]) → dynamic',
+        displayName: 'dynamic Function([Object])',
         optionalParameterNames: ['x'],
         optionalParameterTypes: [same(objectType)],
         parameters: [same(p)]);
@@ -795,7 +797,7 @@
     basicChecks(f,
         element: same(e),
         returnType: same(objectType),
-        displayName: '() → Object');
+        displayName: 'Object Function()');
   }
 
   test_unnamedConstructor_returnType_null() {
@@ -804,7 +806,7 @@
     basicChecks(f,
         element: same(e),
         returnType: same(dynamicType),
-        displayName: '() → dynamic');
+        displayName: 'dynamic Function()');
   }
 
   test_unnamedConstructor_staticMethod_ignores_enclosing_type_params() {
@@ -854,10 +856,10 @@
         typeArguments: [same(objectType)]);
     if (bug_33300_fixed) {
       expect(substituted.displayName,
-          '<S extends T,T extends Object,V extends T>() → Map<S, V>');
+          'Map<S, V> Function<S extends T,T extends Object,V extends T>()');
     } else {
       expect(substituted.displayName,
-          '<S extends T extends Object,T extends Object,V extends T>() → Map<S, V>');
+          'Map<S, V> Function<S extends T extends Object,T extends Object,V extends T>()');
     }
     var s2 = substituted.typeFormals[0];
     var t2 = substituted.typeFormals[1];
@@ -908,12 +910,10 @@
         typeArguments: [same(objectType)]);
     if (bug_33300_fixed) {
       expect(substituted.displayName,
-          '<S extends T,T extends Object,V extends T>(S, V) → void');
+          'void Function<S extends T,T extends Object,V extends T>(S, V)');
     } else {
-      expect(
-          substituted.displayName,
-          '<S extends T extends Object,T extends Object,V extends T>(S, V) '
-          '→ void');
+      expect(substituted.displayName,
+          'void Function<S extends T extends Object,T extends Object,V extends T>(S, V)');
     }
     var s2 = substituted.typeFormals[0];
     var t2 = substituted.typeFormals[1];
@@ -944,7 +944,7 @@
     var substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: same(e),
-        displayName: '<U extends Object>() → U',
+        displayName: 'U Function<U extends Object>()',
         typeArguments: [same(objectType)],
         typeParameters: [same(t)],
         returnType: isNotNull,
@@ -961,7 +961,9 @@
     FunctionType f = new FunctionTypeImpl(e);
     var substituted = f.substitute2([t.type], [t.type]);
     basicChecks(substituted,
-        element: same(e), displayName: '() → T', returnType: same(t.type));
+        element: same(e),
+        displayName: 'T Function()',
+        returnType: same(t.type));
     // TODO(paulberry): test substitute length mismatch
   }
 
@@ -974,7 +976,7 @@
     var substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: same(e),
-        displayName: '(Object) → dynamic',
+        displayName: 'dynamic Function(Object)',
         normalParameterNames: ['x'],
         normalParameterTypes: [same(objectType)],
         parameters: hasLength(1),
@@ -993,7 +995,7 @@
     var substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: same(e),
-        displayName: '() → Object',
+        displayName: 'Object Function()',
         returnType: same(objectType),
         typeArguments: [same(objectType)],
         typeParameters: [same(t)]);
@@ -1005,7 +1007,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '<T>() → dynamic',
+        displayName: 'dynamic Function<T>()',
         typeFormals: [same(t)]);
     // TODO(paulberry): test pruning of bounds
   }
@@ -1019,7 +1021,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '<U extends T>() → U',
+        displayName: 'U Function<U extends T>()',
         typeArguments: [same(t.type)],
         typeParameters: [same(t)],
         returnType: same(u.type),
@@ -1038,7 +1040,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '() → T',
+        displayName: 'T Function()',
         returnType: same(t.type),
         typeArguments: [same(t.type)],
         typeParameters: [same(t)]);
@@ -1226,7 +1228,9 @@
   ClassElement get enclosingElement => super.enclosingElement;
 }
 
-class MockParameterElement implements ParameterElementImpl {
+class MockParameterElement
+    with ParameterElementMixin
+    implements ParameterElementImpl {
   @override
   Element enclosingElement;
 
@@ -1245,15 +1249,6 @@
   @override
   get displayName => name;
 
-  @override
-  bool get isNamed => parameterKind == ParameterKind.NAMED;
-
-  @override
-  bool get isNotOptional => parameterKind == ParameterKind.REQUIRED;
-
-  @override
-  bool get isOptionalPositional => parameterKind == ParameterKind.POSITIONAL;
-
   noSuchMethod(Invocation invocation) {
     return super.noSuchMethod(invocation);
   }
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
index 07b9de2..6286672 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
@@ -47,7 +47,7 @@
     _assertGetInherited(
       className: 'X',
       name: 'foo',
-      expected: 'B.foo: () → void',
+      expected: 'B.foo: void Function()',
     );
   }
 
@@ -70,7 +70,7 @@
     _assertGetInherited(
       className: 'X',
       name: 'foo',
-      expected: 'J.foo: () → void',
+      expected: 'J.foo: void Function()',
     );
   }
 
@@ -93,7 +93,7 @@
     _assertGetInherited(
       className: 'X',
       name: 'foo',
-      expected: 'M.foo: () → void',
+      expected: 'M.foo: void Function()',
     );
   }
 
@@ -116,7 +116,7 @@
     _assertGetInherited(
       className: 'X',
       name: 'foo',
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -131,7 +131,7 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
 ''');
   }
 
@@ -158,7 +158,7 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
 ''');
   }
 
@@ -181,7 +181,7 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -214,7 +214,7 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('C', r'''
-A.foo: (int) → void
+A.foo: void Function(int)
 ''');
   }
 
@@ -242,7 +242,7 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -261,8 +261,8 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('C', r'''
-A.foo: () → void
-B.bar: () → void
+A.foo: void Function()
+B.bar: void Function()
 ''');
   }
 
@@ -277,7 +277,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
 ''');
   }
 
@@ -292,7 +292,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
 ''');
   }
 
@@ -307,7 +307,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
 ''');
   }
 
@@ -326,7 +326,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('X', r'''
-B.foo: () → void
+B.foo: void Function()
 ''');
   }
 
@@ -341,8 +341,8 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
-A.foo=: (int) → void
+A.foo: int Function()
+A.foo=: void Function(int)
 ''');
   }
 
@@ -357,8 +357,8 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
-A.foo=: (int) → void
+A.foo: int Function()
+A.foo=: void Function(int)
 ''');
   }
 
@@ -373,8 +373,8 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
-A.foo=: (int) → void
+A.foo: int Function()
+A.foo=: void Function(int)
 ''');
   }
 
@@ -398,7 +398,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -413,7 +413,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -428,7 +428,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -449,7 +449,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('X', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -470,7 +470,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-J.bar: () → void
+J.bar: void Function()
 ''');
   }
 
@@ -489,8 +489,8 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-I.foo: () → int
-J.bar: () → double
+I.foo: int Function()
+J.bar: double Function()
 ''');
   }
 
@@ -509,7 +509,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-J.foo: () → int
+J.foo: int Function()
 ''');
   }
 
@@ -528,7 +528,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-J.foo: () → void
+J.foo: void Function()
 ''');
   }
 
@@ -548,11 +548,11 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-I.foo=: (num) → void
+I.foo=: void Function(num)
 ''');
 
     _assertInheritedMap('B', r'''
-I.foo=: (num) → void
+I.foo=: void Function(num)
 ''');
   }
 
@@ -580,11 +580,11 @@
     await resolveTestFile();
 
     _assertInheritedMap('D', r'''
-I3.foo: () → C
+I3.foo: C Function()
 ''');
 
     _assertInheritedMap('E', r'''
-I3.foo: () → C
+I3.foo: C Function()
 ''');
   }
 
@@ -612,7 +612,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('D', r'''
-I1.foo: (A) → void
+I1.foo: void Function(A)
 ''');
   }
 
@@ -640,11 +640,11 @@
     await resolveTestFile();
 
     _assertInheritedMap('D', r'''
-I1.foo=: (A) → void
+I1.foo=: void Function(A)
 ''');
 
     _assertInheritedMap('E', r'''
-I1.foo=: (A) → void
+I1.foo=: void Function(A)
 ''');
   }
 
@@ -664,11 +664,11 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-I2.foo: ([int]) → int
+I2.foo: int Function([int])
 ''');
 
     _assertInheritedMap('B', r'''
-I2.foo: ([int]) → int
+I2.foo: int Function([int])
 ''');
   }
 
@@ -692,11 +692,11 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-I3.foo: ([int, int]) → int
+I3.foo: int Function([int, int])
 ''');
 
     _assertInheritedMap('B', r'''
-I3.foo: ([int, int]) → int
+I3.foo: int Function([int, int])
 ''');
   }
 
@@ -717,7 +717,7 @@
     _assertGetMember(
       className: 'C',
       name: 'f',
-      expected: 'I2.f: (Object) → void',
+      expected: 'I2.f: void Function(Object)',
     );
   }
 
@@ -733,7 +733,7 @@
       className: 'A',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -766,7 +766,7 @@
       className: 'X',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -786,7 +786,7 @@
       className: 'X',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -806,7 +806,7 @@
       className: 'X',
       name: 'toString',
       concrete: true,
-      expected: 'A.toString: () → String',
+      expected: 'A.toString: String Function()',
     );
   }
 
@@ -824,7 +824,7 @@
       className: 'X',
       name: 'foo',
       concrete: true,
-      expected: 'M.foo: () → void',
+      expected: 'M.foo: void Function()',
     );
   }
 
@@ -844,14 +844,14 @@
       className: 'B',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
 
     _assertGetMember(
       className: 'C',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -886,14 +886,14 @@
       className: 'B',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
 
     _assertGetMember(
       className: 'C',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -938,7 +938,7 @@
       className: 'C',
       name: 'foo',
       concrete: true,
-      expected: 'C.foo: ([int]) → void',
+      expected: 'C.foo: void Function([int])',
     );
   }
 
@@ -967,7 +967,7 @@
     _assertGetMember(
       className: 'X',
       name: 'foo',
-      expected: 'M2.foo: () → void',
+      expected: 'M2.foo: void Function()',
     );
   }
 
@@ -992,7 +992,7 @@
     _assertGetMember(
       className: 'X',
       name: 'foo',
-      expected: 'B.foo: () → void',
+      expected: 'B.foo: void Function()',
     );
   }
 
@@ -1015,7 +1015,7 @@
     _assertGetMember(
       className: 'X',
       name: 'foo',
-      expected: 'X.foo: () → void',
+      expected: 'X.foo: void Function()',
     );
   }
 
@@ -1069,7 +1069,7 @@
       className: 'M',
       name: 'foo',
       forSuper: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -1089,7 +1089,7 @@
       className: 'X',
       name: 'foo',
       forSuper: true,
-      expected: 'M.foo: () → void',
+      expected: 'M.foo: void Function()',
     );
   }
 
@@ -1109,7 +1109,7 @@
       className: 'B',
       name: 'foo',
       forSuper: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -1145,7 +1145,7 @@
       className: 'B',
       name: 'foo',
       forSuper: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
diff --git a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
index 5aa1321..0069fd1 100644
--- a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
@@ -92,7 +92,7 @@
       {t: intType},
       {t: BottomTypeImpl.instance},
     ).substituteType(type);
-    assertElementTypeString(result, '(<bottom>) → int');
+    assertElementTypeString(result, 'int Function(Never)');
   }
 }
 
@@ -138,11 +138,11 @@
 
     var type = findElement.genericTypeAlias('F').function.type;
     var t = findElement.typeParameter('T');
-    assertElementTypeString(type, '<U extends T>(U) → T');
+    assertElementTypeString(type, 'T Function<U extends T>(U)');
     _assertSubstitution(
       type,
       {t: intType},
-      '<U extends int>(U) → int',
+      'int Function<U extends int>(U)',
     );
   }
 
@@ -155,16 +155,16 @@
     var type = findElement.genericTypeAlias('F').function.type;
     var t = findElement.typeParameter('T');
     var u = findElement.typeParameter('U');
-    assertElementTypeString(type, '(U, bool) → T');
+    assertElementTypeString(type, 'T Function(U, bool)');
     _assertSubstitution(
       type,
       {t: intType},
-      '(U, bool) → int',
+      'int Function(U, bool)',
     );
     _assertSubstitution(
       type,
       {t: intType, u: doubleType},
-      '(double, bool) → int',
+      'int Function(double, bool)',
     );
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
index 37aa571..d1b41ac 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
@@ -26,7 +26,7 @@
 ''');
     await resolveTestFile();
     assertNoTestErrors();
-    assertConstructors(findElement.class_('X'), ['X() → X']);
+    assertConstructors(findElement.class_('X'), ['X X()']);
   }
 
   test_element() async {
@@ -83,8 +83,8 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    assertConstructors(findElement.class_('C1'), ['C1(int i) → C1']);
-    assertConstructors(findElement.class_('C2'), ['C2(int i) → C2']);
+    assertConstructors(findElement.class_('C1'), ['C1 C1(int i)']);
+    assertConstructors(findElement.class_('C2'), ['C2 C2(int i)']);
   }
 
   test_implicitConstructors_optionalParameters() async {
@@ -105,9 +105,9 @@
     assertConstructors(
       findElement.class_('C'),
       [
-        'C.c1(int a) → C',
-        'C.c2(int a, [int b, int c]) → C',
-        'C.c3(int a, {int b, int c}) → C'
+        'C C.c1(int a)',
+        'C C.c2(int a, [int b, int c])',
+        'C C.c3(int a, {int b, int c})'
       ],
     );
   }
@@ -125,6 +125,6 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    assertConstructors(findElement.class_('B'), ['B(E x, E y) → B<E>']);
+    assertConstructors(findElement.class_('B'), ['B<E> B(E x, E y)']);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/comment_test.dart b/pkg/analyzer/test/src/dart/resolution/comment_test.dart
index dc7def9..c93fc8d 100644
--- a/pkg/analyzer/test/src/dart/resolution/comment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/comment_test.dart
@@ -13,13 +13,9 @@
   });
 }
 
-@reflectiveTest
-class CommentDriverResolutionTest extends DriverResolutionTest
-    with ClassAliasResolutionMixin {}
-
 mixin ClassAliasResolutionMixin implements ResolutionTest {
   test_error_unqualifiedReferenceToNonLocalStaticMember() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   static void foo() {}
 }
@@ -27,8 +23,6 @@
 /// [foo]
 class B extends A {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     assertElement(
       findNode.simple('foo]'),
@@ -36,41 +30,26 @@
     );
   }
 
-  test_new() async {
-    addTestFile(r'''
+  test_identifier_beforeClass() async {
+    await assertNoErrorsInCode(r'''
+/// [foo]
 class A {
-  A();
-  A.named();
+  foo() {}
 }
-
-/// [new A] or [new A.named]
-main() {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     assertElement(
-      findNode.simple('A]'),
-      findElement.unnamedConstructor('A'),
-    );
-    assertElement(
-      findNode.simple('A.named]'),
-      findElement.class_('A'),
-    );
-    assertElement(
-      findNode.simple('named]'),
-      findElement.constructor('named', of: 'A'),
+      findNode.simple('foo]'),
+      findElement.method('foo'),
     );
   }
 
   test_identifier_beforeConstructor() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   /// [p]
   A(int p);
 }''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     assertElement(
       findNode.simple('p]'),
@@ -79,7 +58,7 @@
   }
 
   test_identifier_beforeEnum() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 /// This is the [Samurai] kind.
 enum Samurai {
   /// Use [int].
@@ -87,8 +66,6 @@
   /// Like [WITH_SWORD], but only without one.
   WITHOUT_SWORD
 }''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     assertElement(
       findNode.simple('Samurai]'),
@@ -105,12 +82,10 @@
   }
 
   test_identifier_beforeFunction_blockBody() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 /// [p]
 foo(int p) {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     assertElement(
       findNode.simple('p]'),
@@ -118,27 +93,11 @@
     );
   }
 
-  test_identifier_parameter_functionTyped() async {
-    addTestFile(r'''
-/// [bar]
-foo(int bar()) {}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-
-    assertElement(
-      findNode.simple('bar]'),
-      findElement.parameter('bar'),
-    );
-  }
-
   test_identifier_beforeFunction_expressionBody() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 /// [p]
 foo(int p) => null;
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     assertElement(
       findNode.simple('p]'),
@@ -147,12 +106,10 @@
   }
 
   test_identifier_beforeFunctionTypeAlias() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 /// [p]
 typedef Foo(int p);
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     assertElement(
       findNode.simple('p]'),
@@ -161,12 +118,10 @@
   }
 
   test_identifier_beforeGenericTypeAlias() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 /// Can resolve [T], [S], and [p].
 typedef Foo<T> = Function<S>(int p);
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     assertElement(
       findNode.simple('T]'),
@@ -180,18 +135,16 @@
   }
 
   test_identifier_beforeGetter() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 /// [int]
 get g => null;
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     assertElement(findNode.simple('int]'), intElement);
   }
 
   test_identifier_beforeMethod() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   /// [p1]
   ma(int p1);
@@ -206,8 +159,6 @@
   md(int p5, {int p6});
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     assertElement(findNode.simple('p1]'), findElement.parameter('p1'));
     assertElement(findNode.simple('p2]'), findElement.parameter('p2'));
@@ -216,24 +167,20 @@
     assertElement(findNode.simple('p5]'), findElement.parameter('p5'));
   }
 
-  test_identifier_beforeClass() async {
-    addTestFile(r'''
-/// [foo]
-class A {
-  foo() {}
-}
+  test_identifier_parameter_functionTyped() async {
+    await assertNoErrorsInCode(r'''
+/// [bar]
+foo(int bar()) {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     assertElement(
-      findNode.simple('foo]'),
-      findElement.method('foo'),
+      findNode.simple('bar]'),
+      findElement.parameter('bar'),
     );
   }
 
   test_identifier_setter() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   /// [x] in A
   mA() {}
@@ -245,11 +192,38 @@
   mB() {}
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var x = findElement.setter('x', of: 'A');
     assertElement(findNode.simple('x] in A'), x);
     assertElement(findNode.simple('x] in B'), x);
   }
+
+  test_new() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A();
+  A.named();
 }
+
+/// [new A] or [new A.named]
+main() {}
+''');
+
+    assertElement(
+      findNode.simple('A]'),
+      findElement.unnamedConstructor('A'),
+    );
+    assertElement(
+      findNode.simple('A.named]'),
+      findElement.class_('A'),
+    );
+    assertElement(
+      findNode.simple('named]'),
+      findElement.constructor('named', of: 'A'),
+    );
+  }
+}
+
+@reflectiveTest
+class CommentDriverResolutionTest extends DriverResolutionTest
+    with ClassAliasResolutionMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/constructor_test.dart b/pkg/analyzer/test/src/dart/resolution/constructor_test.dart
new file mode 100644
index 0000000..b91fbda
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/constructor_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, 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:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConstructorResolutionTest);
+  });
+}
+
+@reflectiveTest
+class ConstructorResolutionTest extends DriverResolutionTest {
+  test_initializer_field_functionExpression_expressionBody() async {
+    addTestFile(r'''
+class C {
+  final int x;
+  C(int a) : x = (() => a + 1)();
+}
+''');
+    await resolveTestFile();
+    assertElement(findNode.simple('a + 1'), findElement.parameter('a'));
+  }
+
+  test_initializer_field_functionExpression_blockBody() async {
+    addTestFile(r'''
+class C {
+  var x;
+  C(int a) : x = (() {return a + 1;})();
+}
+''');
+    await resolveTestFile();
+    assertElement(findNode.simple('a + 1'), findElement.parameter('a'));
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/export_test.dart b/pkg/analyzer/test/src/dart/resolution/export_test.dart
new file mode 100644
index 0000000..565f72d
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/export_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, 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:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExportResolutionTest);
+  });
+}
+
+@reflectiveTest
+class ExportResolutionTest extends DriverResolutionTest {
+  /// Test that both getter and setter are in the export namespace.
+  test_namespace_getter_setter() async {
+    newFile('/test/lib/a.dart', content: r'''
+get f => null;
+set f(_) {}
+''');
+    addTestFile(r'''
+export 'a.dart';
+''');
+    await resolveTestFile();
+    var exportNamespace = result.libraryElement.exportNamespace;
+    expect(exportNamespace.get('f'), isNotNull);
+    expect(exportNamespace.get('f='), isNotNull);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/flow_analysis_test.dart b/pkg/analyzer/test/src/dart/resolution/flow_analysis_test.dart
index 3143da1..5dd9420 100644
--- a/pkg/analyzer/test/src/dart/resolution/flow_analysis_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/flow_analysis_test.dart
@@ -9,9 +9,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_system.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -22,7 +20,6 @@
     defineReflectiveTests(NullableFlowTest);
     defineReflectiveTests(DefiniteAssignmentFlowTest);
     defineReflectiveTests(ReachableFlowTest);
-    defineReflectiveTests(ReachableFlowTest_SpreadCollections);
     defineReflectiveTests(TypePromotionFlowTest);
   });
 }
@@ -2118,13 +2115,6 @@
 }
 
 @reflectiveTest
-class ReachableFlowTest_SpreadCollections extends ReachableFlowTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => new AnalysisOptionsImpl()
-    ..enabledExperiments = [EnableString.spread_collections];
-}
-
-@reflectiveTest
 class TypePromotionFlowTest extends DriverResolutionTest {
   final Map<AstNode, DartType> promotedTypes = {};
 
diff --git a/pkg/analyzer/test/src/dart/resolution/for_element_test.dart b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
index 967b539..54f31ff 100644
--- a/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
@@ -2,7 +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.
 
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
@@ -16,10 +15,6 @@
 
 @reflectiveTest
 class ForEachElementTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
-
   test_declaredIdentifierScope() async {
     addTestFile(r'''
 main() {
@@ -43,10 +38,6 @@
 
 @reflectiveTest
 class ForLoopElementTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
-
   test_declaredVariableScope() async {
     addTestFile(r'''
 main() {
diff --git a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
new file mode 100644
index 0000000..503a83f
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2019, 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:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FunctionExpressionInvocationTest);
+  });
+}
+
+@reflectiveTest
+class FunctionExpressionInvocationTest extends DriverResolutionTest {
+  test_dynamic_withoutTypeArguments() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  (main as dynamic)(0);
+}
+''');
+
+    var invocation = findNode.functionExpressionInvocation('(0)');
+    assertTypeDynamic(invocation);
+    assertInvokeTypeDynamic(invocation);
+    assertTypeArgumentTypes(invocation, []);
+  }
+
+  test_dynamic_withTypeArguments() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  (main as dynamic)<bool, int>(0);
+}
+''');
+
+    var invocation = findNode.functionExpressionInvocation('(0)');
+    assertTypeDynamic(invocation);
+    assertInvokeTypeDynamic(invocation);
+    assertTypeArgumentTypes(invocation, ['bool', 'int']);
+  }
+
+  test_generic() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  (f)(0);
+}
+
+bool f<T>(T a) => true;
+''');
+
+    var invocation = findNode.functionExpressionInvocation('(0)');
+    assertType(invocation, 'bool');
+    assertInvokeType(invocation, 'bool Function(int)');
+    assertTypeArgumentTypes(invocation, ['int']);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart b/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart
new file mode 100644
index 0000000..ae124eb
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart
@@ -0,0 +1,146 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(GenericFunctionTypeResolutionTest);
+  });
+}
+
+@reflectiveTest
+class GenericFunctionTypeResolutionTest extends DriverResolutionTest {
+  /// Test that when [GenericFunctionType] is used in a constant variable
+  /// initializer, analysis does not throw an exception; and that the next
+  /// [GenericFunctionType] is also handled correctly.
+  test_constInitializer_field_static_const() async {
+    await assertNoErrorsInCode('''
+class A<T> {
+  const A();
+}
+
+class B {
+  static const x = const A<bool Function()>();
+}
+
+int Function(int a) y;
+''');
+  }
+
+  /// Test that when [GenericFunctionType] is used in a constant variable
+  /// initializer, analysis does not throw an exception; and that the next
+  /// [GenericFunctionType] is also handled correctly.
+  test_constInitializer_topLevel() async {
+    await assertNoErrorsInCode('''
+class A<T> {
+  const A();
+}
+
+const x = const A<bool Function()>();
+
+int Function(int a) y;
+''');
+  }
+
+  /// Test that when multiple [GenericFunctionType]s are used in a
+  /// [FunctionDeclaration], all of them are resolved correctly.
+  test_typeAnnotation_function() async {
+    await assertNoErrorsInCode('''
+void Function() f<T extends bool Function()>(int Function() a) {
+  return null;
+}
+
+double Function() x;
+''');
+    assertType(
+      findNode.genericFunctionType('void Function()'),
+      'void Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('bool Function()'),
+      'bool Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('int Function()'),
+      'int Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('double Function()'),
+      'double Function()',
+    );
+  }
+
+  /// Test that when multiple [GenericFunctionType]s are used in a
+  /// [FunctionDeclaration], the one in the return type is consumed before the
+  /// one in the parameter type. This is necessary because matching of
+  /// [GenericFunctionType] nodes to their elements is based on the sequential
+  /// identifier of a node in the unit.
+  test_typeAnnotation_function_returnType_parameterType() async {
+    await assertNoErrorsInCode(r'''
+void Function(E a) f<E>(void Function() b) {
+  return (_) {};
+}
+''');
+  }
+
+  /// Test that when multiple [GenericFunctionType]s are used in a
+  /// [GenericFunctionType], all of them are resolved correctly.
+  test_typeAnnotation_genericFunctionType() async {
+    await assertNoErrorsInCode('''
+void f(
+  void Function() a,
+  bool Function() Function(int Function()) b,
+) {}
+''');
+  }
+
+  /// Test that when multiple [GenericFunctionType]s are used in a
+  /// [FunctionDeclaration], all of them are resolved correctly.
+  test_typeAnnotation_method() async {
+    await assertNoErrorsInCode('''
+class C {
+  void Function() m<T extends bool Function()>(int Function() a) {
+    return null;
+  }
+}
+
+double Function() x;
+''');
+    assertType(
+      findNode.genericFunctionType('void Function()'),
+      'void Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('bool Function()'),
+      'bool Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('int Function()'),
+      'int Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('double Function()'),
+      'double Function()',
+    );
+  }
+
+  /// Test that when multiple [GenericFunctionType]s are used in a
+  /// [MethodDeclaration], the one in the return type is consumed before the
+  /// one in the parameter type. This is necessary because matching of
+  /// [GenericFunctionType] nodes to their elements is based on the sequential
+  /// identifier of a node in the unit.
+  test_typeAnnotation_method_returnType_parameterType() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  void Function(E a) f<E>(void Function() b) {
+    return (_) {};
+  }
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index 307d438..c31ff84 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -38,7 +38,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertSuperExpression(invocation.target);
   }
@@ -63,7 +63,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertSuperExpression(invocation.target);
   }
@@ -88,7 +88,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '() → int',
+      'int Function()',
     );
     assertSuperExpression(invocation.target);
   }
@@ -116,7 +116,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'M'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertSuperExpression(invocation.target);
   }
@@ -140,7 +140,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '() → int',
+      'int Function()',
     );
     assertSuperExpression(invocation.target);
   }
@@ -168,7 +168,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertSuperExpression(invocation.target);
   }
@@ -195,7 +195,7 @@
     ]);
 
     var invocation = findNode.methodInvocation('foo(0)');
-    assertInvokeType(invocation, '(int) → void');
+    assertInvokeType(invocation, 'void Function(int)');
     assertType(invocation, 'void');
   }
 
@@ -221,7 +221,7 @@
     ]);
 
     var invocation = findNode.methodInvocation('foo(0)');
-    assertInvokeType(invocation, '(int) → void');
+    assertInvokeType(invocation, 'void Function(int)');
     assertType(invocation, 'void');
   }
 
@@ -311,7 +311,7 @@
     _assertInvalidInvocation(
       'c.foo();',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → dynamic',
+      expectedMethodNameType: 'dynamic Function()',
     );
   }
 
@@ -332,7 +332,7 @@
     _assertInvalidInvocation(
       'foo();',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → dynamic',
+      expectedMethodNameType: 'dynamic Function()',
     );
   }
 
@@ -351,7 +351,7 @@
     _assertInvalidInvocation(
       'foo();',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → dynamic',
+      expectedMethodNameType: 'dynamic Function()',
     );
   }
 
@@ -383,8 +383,8 @@
     assertMethodInvocation(
       findNode.methodInvocation('foo(0)'),
       findElement.getter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → T',
+      'double Function(int)',
+      expectedMethodNameType: 'T Function()',
     );
   }
 
@@ -405,7 +405,7 @@
     _assertInvalidInvocation(
       'foo()',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → int',
+      expectedMethodNameType: 'int Function()',
     );
   }
 
@@ -426,7 +426,7 @@
     _assertInvalidInvocation(
       'foo()',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → int',
+      expectedMethodNameType: 'int Function()',
     );
   }
 
@@ -449,7 +449,7 @@
     _assertInvalidInvocation(
       'foo()',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → int',
+      expectedMethodNameType: 'int Function()',
     );
   }
 
@@ -476,7 +476,7 @@
     assertMethodInvocation(
       invocation,
       import.topFunction('foo'),
-      '() → void',
+      'void Function()',
     );
     assertImportPrefix(invocation.target, import.prefix);
   }
@@ -500,7 +500,7 @@
     assertMethodInvocation(
       invocation,
       import.importedLibrary.loadLibraryFunction,
-      '() → Future<dynamic>',
+      'Future<dynamic> Function()',
     );
     assertImportPrefix(invocation.target, import.prefix);
   }
@@ -629,7 +629,10 @@
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
 
-    _assertUnresolvedMethodInvocation('foo<int>();');
+    _assertUnresolvedMethodInvocation(
+      'foo<int>();',
+      expectedTypeArguments: ['int'],
+    );
     assertTypeName(findNode.typeName('int>'), intElement, 'int');
   }
 
@@ -864,7 +867,7 @@
       'c.foo()',
       findElement.getter('foo'),
       expectedNameType: 'void',
-      expectedMethodNameType: '() → void',
+      expectedMethodNameType: 'void Function()',
     );
   }
 
@@ -901,7 +904,7 @@
     assertMethodInvocation(
       findNode.methodInvocation('foo()()'),
       findElement.topFunction('foo'),
-      '() → void',
+      'void Function()',
     );
   }
 
@@ -921,7 +924,7 @@
       'foo()',
       findElement.topGet('foo'),
       expectedNameType: 'void',
-      expectedMethodNameType: '() → void',
+      expectedMethodNameType: 'void Function()',
     );
   }
 
@@ -940,7 +943,7 @@
     assertMethodInvocation(
       findNode.methodInvocation('toString()'),
       null,
-      '() → String',
+      'String Function()',
     );
   }
 
@@ -959,7 +962,7 @@
     assertMethodInvocation(
       findNode.methodInvocation('toString()'),
       null,
-      '() → String',
+      'String Function()',
     );
   }
 
@@ -978,7 +981,7 @@
     assertMethodInvocation(
       findNode.methodInvocation('toString()'),
       null,
-      '() → String',
+      'String Function()',
     );
   }
 
@@ -997,7 +1000,7 @@
     assertMethodInvocation(
       findNode.methodInvocation('foo<int>()'),
       findElement.topFunction('foo'),
-      '() → void',
+      'void Function()',
     );
     assertTypeName(findNode.typeName('int>'), intElement, 'int');
   }
@@ -1017,7 +1020,8 @@
     assertMethodInvocation(
       findNode.methodInvocation('foo<int>()'),
       findElement.topFunction('foo'),
-      '() → Map<num, dynamic>',
+      'Map<num, dynamic> Function()',
+      expectedTypeArguments: ['num', 'dynamic'],
     );
     assertTypeName(findNode.typeName('int>'), intElement, 'int');
   }
@@ -1039,8 +1043,8 @@
     assertMethodInvocation(
       invocation,
       findElement.getter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
     assertClassRef(invocation.target, findElement.class_('C'));
   }
@@ -1062,7 +1066,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertClassRef(invocation.target, findElement.class_('C'));
   }
@@ -1084,7 +1088,7 @@
     assertMethodInvocation(
       invocation,
       import.importedLibrary.loadLibraryFunction,
-      '() → Future<dynamic>',
+      'Future<dynamic> Function()',
     );
     assertImportPrefix(invocation.target, import.prefix);
   }
@@ -1104,10 +1108,10 @@
     assertMethodInvocation(
       invocation,
       null,
-      '(int) → void',
+      'void Function(int)',
     );
     assertElement(invocation.target, findElement.topFunction('foo'));
-    assertType(invocation.target, '(int) → void');
+    assertType(invocation.target, 'void Function(int)');
   }
 
   test_hasReceiver_importPrefix_topFunction() async {
@@ -1131,7 +1135,8 @@
     assertMethodInvocation(
       invocation,
       import.topFunction('foo'),
-      '(int, int) → int',
+      'int Function(int, int)',
+      expectedTypeArguments: ['int'],
     );
     assertImportPrefix(invocation.target, import.prefix);
   }
@@ -1157,8 +1162,9 @@
     assertMethodInvocation(
       invocation,
       import.topGetter('foo'),
-      '(int, int) → int',
-      expectedMethodNameType: '() → <T>(T, T) → T',
+      'int Function(int, int)',
+      expectedMethodNameType: 'T Function<T>(T, T) Function()',
+      expectedTypeArguments: ['int'],
     );
     assertImportPrefix(invocation.target, import.prefix);
   }
@@ -1206,8 +1212,8 @@
     assertMethodInvocation(
       invocation,
       findElement.getter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
   }
 
@@ -1228,9 +1234,10 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → void',
-      expectedMethodNameType: '(int) → void',
+      'void Function(int)',
+      expectedMethodNameType: 'void Function(int)',
     );
+    assertTypeArgumentTypes(invocation, []);
   }
 
   test_hasReceiver_instance_method_generic() async {
@@ -1252,9 +1259,11 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → int',
-      expectedMethodNameType: '(int) → int',
+      'int Function(int)',
+      expectedMethodNameType: 'int Function(int)',
+      expectedTypeArguments: ['int'],
     );
+    assertTypeArgumentTypes(invocation, ['int']);
   }
 
   test_hasReceiver_instance_method_issue30552() async {
@@ -1284,7 +1293,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'I2'),
-      '(Object) → void',
+      'void Function(Object)',
     );
   }
 
@@ -1309,7 +1318,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1336,8 +1345,8 @@
     assertMethodInvocation(
       invocation,
       import.class_('C').getGetter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
 
     PrefixedIdentifier target = invocation.target;
@@ -1368,7 +1377,7 @@
     assertMethodInvocation(
       invocation,
       import.class_('C').getMethod('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
 
     PrefixedIdentifier target = invocation.target;
@@ -1395,8 +1404,8 @@
     assertMethodInvocation(
       invocation,
       findElement.getter('foo', of: 'A'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
     assertSuperExpression(invocation.target);
   }
@@ -1420,7 +1429,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertSuperExpression(invocation.target);
   }
@@ -1440,7 +1449,7 @@
     assertMethodInvocation(
       invocation,
       findElement.topFunction('foo'),
-      '({a: int, b: bool}) → void',
+      'void Function({a: int, b: bool})',
     );
     assertNamedParameterRef('b: false', 'b');
     assertNamedParameterRef('a: 0', 'a');
@@ -1465,8 +1474,8 @@
     assertMethodInvocation(
       invocation,
       findElement.getter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
   }
 
@@ -1487,8 +1496,8 @@
     assertMethodInvocation(
       invocation,
       findElement.getter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
   }
 
@@ -1522,7 +1531,7 @@
     assertMethodInvocation(
       invocation,
       findElement.localFunction('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1541,7 +1550,7 @@
     assertMethodInvocation(
       invocation,
       findElement.localVar('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1562,7 +1571,7 @@
     assertMethodInvocation(
       invocation,
       findElement.parameter('c'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1582,7 +1591,7 @@
     assertMethodInvocation(
       invocation,
       findElement.localVar('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1605,7 +1614,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1626,7 +1635,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1645,8 +1654,8 @@
     assertMethodInvocation(
       invocation,
       findElement.topFunction('foo'),
-      '(int) → void',
-      expectedMethodNameType: '(int) → void',
+      'void Function(int)',
+      expectedMethodNameType: 'void Function(int)',
     );
   }
 
@@ -1665,8 +1674,8 @@
     assertMethodInvocation(
       invocation,
       findElement.topGet('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
   }
 
@@ -1685,8 +1694,8 @@
     assertMethodInvocation(
       invocation,
       findElement.topGet('foo'),
-      '(int) → void',
-      expectedMethodNameType: '() → (int) → void',
+      'void Function(int)',
+      expectedMethodNameType: 'void Function(int) Function()',
     );
   }
 
@@ -1717,13 +1726,81 @@
     assertMethodInvocation(
       invocation,
       typeProvider.objectType.getMethod('toString'),
-      '() → String',
+      'String Function()',
     );
   }
 
+  test_typeArgumentTypes_generic_inferred() async {
+    await assertNoErrorsInCode(r'''
+U foo<T, U>(T a) => null;
+
+main() {
+  bool v = foo(0);
+}
+''');
+
+    var invocation = findNode.methodInvocation('foo(0)');
+    assertTypeArgumentTypes(invocation, ['int', 'bool']);
+  }
+
+  test_typeArgumentTypes_generic_instantiateToBounds() async {
+    await assertNoErrorsInCode(r'''
+void foo<T extends num>() {}
+
+main() {
+  foo();
+}
+''');
+
+    var invocation = findNode.methodInvocation('foo();');
+    assertTypeArgumentTypes(invocation, ['num']);
+  }
+
+  test_typeArgumentTypes_generic_typeArguments_notBounds() async {
+    addTestFile(r'''
+void foo<T extends num>() {}
+
+main() {
+  foo<bool>();
+}
+''');
+    await resolveTestFile();
+
+    var invocation = findNode.methodInvocation('foo<bool>();');
+    assertTypeArgumentTypes(invocation, ['bool']);
+  }
+
+  test_typeArgumentTypes_generic_typeArguments_wrongNumber() async {
+    addTestFile(r'''
+void foo<T>() {}
+
+main() {
+  foo<int, double>();
+}
+''');
+    await resolveTestFile();
+
+    var invocation = findNode.methodInvocation('foo<int, double>();');
+    assertTypeArgumentTypes(invocation, ['dynamic']);
+  }
+
+  test_typeArgumentTypes_notGeneric() async {
+    await assertNoErrorsInCode(r'''
+void foo(int a) {}
+
+main() {
+  foo(0);
+}
+''');
+
+    var invocation = findNode.methodInvocation('foo(0)');
+    assertTypeArgumentTypes(invocation, []);
+  }
+
   void _assertInvalidInvocation(String search, Element expectedElement,
       {String expectedMethodNameType,
       String expectedNameType,
+      List<String> expectedTypeArguments: const <String>[],
       bool dynamicNameType: false}) {
     var invocation = findNode.methodInvocation(search);
     if (dynamicNameType) {
@@ -1737,12 +1814,21 @@
       expectedMethodNameType: expectedMethodNameType,
       expectedNameType: expectedNameType,
       expectedType: 'dynamic',
+      expectedTypeArguments: expectedTypeArguments,
     );
+    assertTypeArgumentTypes(invocation, expectedTypeArguments);
   }
 
-  void _assertUnresolvedMethodInvocation(String search) {
+  void _assertUnresolvedMethodInvocation(
+    String search, {
+    List<String> expectedTypeArguments: const <String>[],
+  }) {
     // TODO(scheglov) clean up
-    _assertInvalidInvocation(search, null);
+    _assertInvalidInvocation(
+      search,
+      null,
+      expectedTypeArguments: expectedTypeArguments,
+    );
 //    var invocation = findNode.methodInvocation(search);
 //    assertTypeDynamic(invocation.methodName);
 //    // TODO(scheglov) I think `invokeType` should be `null`.
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index 46ff61b..671bdef5 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -9,7 +9,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -18,18 +17,13 @@
 }
 
 @reflectiveTest
-class MixinDriverResolutionTest extends DriverResolutionTest
-    with MixinResolutionMixin {}
-
-mixin MixinResolutionMixin implements ResolutionTest {
+class MixinDriverResolutionTest extends DriverResolutionTest {
   test_accessor_getter() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 mixin M {
   int get g => 0;
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var element = findElement.mixin('M');
 
@@ -48,13 +42,11 @@
   }
 
   test_accessor_method() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 mixin M {
   void foo() {}
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var element = findElement.mixin('M');
 
@@ -69,13 +61,11 @@
   }
 
   test_accessor_setter() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 mixin M {
   void set s(int _) {}
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var element = findElement.mixin('M');
 
@@ -94,12 +84,10 @@
   }
 
   test_classDeclaration_with() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 mixin M {}
 class A extends Object with M {} // A
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var mElement = findElement.mixin('M');
 
@@ -111,12 +99,10 @@
   }
 
   test_classTypeAlias_with() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 mixin M {}
 class A = Object with M;
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var mElement = findElement.mixin('M');
 
@@ -128,14 +114,12 @@
   }
 
   test_commentReference() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 const a = 0;
 
 /// Reference [a] in documentation.
 mixin M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var aRef = findNode.commentReference('a]').identifier;
     assertElement(aRef, findElement.topGet('a'));
@@ -143,23 +127,20 @@
   }
 
   test_conflictingGenericInterfaces() async {
-    addTestFile('''
+    await assertErrorsInCode('''
 class I<T> {}
 class A implements I<int> {}
 class B implements I<String> {}
 mixin M on A implements B {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 75, 28),
+    ]);
   }
 
   test_element() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 mixin M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var mixin = findNode.mixin('mixin M');
     var element = findElement.mixin('M');
@@ -179,7 +160,7 @@
   }
 
   test_element_allSupertypes() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B {}
 class C {}
@@ -187,8 +168,6 @@
 mixin M1 on A, B {}
 mixin M2 on A implements B, C {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var a = findElement.class_('A');
     var b = findElement.class_('B');
@@ -204,15 +183,13 @@
   }
 
   test_element_allSupertypes_generic() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A<T, U> {}
 class B<T> extends A<int, T> {}
 
 mixin M1 on A<int, double> {}
 mixin M2 on B<String> {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var a = findElement.class_('A');
     var b = findElement.class_('B');
@@ -234,16 +211,15 @@
   }
 
   test_error_builtInIdentifierAsTypeName() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin as {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME]);
+''', [
+      error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME, 6, 2),
+    ]);
   }
 
   test_error_builtInIdentifierAsTypeName_OK_on() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 
 mixin on on A {}
@@ -256,533 +232,489 @@
 class C = B with M;
 class D = Object with M2;
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_conflictingStaticAndInstance_inClass_getter_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   static int get foo => 0;
   int get foo => 0;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 27, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inClass_getter_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   static int get foo => 0;
   void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 27, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inClass_getter_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   static int get foo => 0;
   set foo(_) {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 27, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inClass_method_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   static void foo() {}
   int get foo => 0;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 24, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inClass_method_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   static void foo() {}
   void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 24, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inClass_method_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   static void foo() {}
   set foo(_) {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 24, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inClass_setter_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   static set foo(_) {}
   int get foo => 0;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 23, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inClass_setter_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   static set foo(_) {}
   void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 23, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inClass_setter_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   static set foo(_) {}
   set foo(_) {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 23, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inConstraint_getter_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   int get foo => 0;
 }
 mixin M on A {
   static int get foo => 0;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 64, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inConstraint_getter_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   int get foo => 0;
 }
 mixin M on A {
   static void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 61, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inConstraint_getter_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   set foo(_) {}
 }
 mixin M on A {
   static int get foo => 0;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 60, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inConstraint_method_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   int get foo => 0;
 }
 mixin M on A {
   static void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 61, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inConstraint_method_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   void foo() {}
 }
 mixin M on A {
   static void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 57, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inConstraint_method_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   set foo(_) {}
 }
 mixin M on A {
   static void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 57, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inConstraint_setter_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   void foo() {}
 }
 mixin M on A {
   static set foo(_) {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 56, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inConstraint_setter_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   set foo(_) {}
 }
 mixin M on A {
   static set foo(_) {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 56, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inInterface_getter_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   int get foo => 0;
 }
 mixin M implements A {
   static int get foo => 0;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 72, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inInterface_getter_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   int get foo => 0;
 }
 mixin M implements A {
   static void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 69, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inInterface_getter_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   set foo(_) {}
 }
 mixin M implements A {
   static int get foo => 0;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 68, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inInterface_method_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   int get foo => 0;
 }
 mixin M implements A {
   static void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 69, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inInterface_method_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   void foo() {}
 }
 mixin M implements A {
   static void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 65, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inInterface_method_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   set foo(_) {}
 }
 mixin M implements A {
   static void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 65, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inInterface_setter_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   void foo() {}
 }
 mixin M implements A {
   static set foo(_) {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 64, 3),
+    ]);
   }
 
   test_error_conflictingStaticAndInstance_inInterface_setter_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   set foo(_) {}
 }
 mixin M implements A {
   static set foo(_) {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE]);
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 64, 3),
+    ]);
   }
 
   test_error_conflictingTypeVariableAndClass() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M<M> {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS,
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS, 8, 1),
     ]);
   }
 
   test_error_conflictingTypeVariableAndMember_field() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M<T> {
   var T;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, 8, 1),
     ]);
   }
 
   test_error_conflictingTypeVariableAndMember_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M<T> {
   get T => null;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, 8, 1),
     ]);
   }
 
   test_error_conflictingTypeVariableAndMember_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M<T> {
   T() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, 8, 1),
     ]);
   }
 
   test_error_conflictingTypeVariableAndMember_method_static() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M<T> {
   static T() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, 8, 1),
     ]);
   }
 
   test_error_conflictingTypeVariableAndMember_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M<T> {
   void set T(_) {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, 8, 1),
     ]);
   }
 
   test_error_duplicateDefinition_field() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   int t;
   int t;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 25, 1),
+    ]);
   }
 
   test_error_duplicateDefinition_field_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   int t;
   void t() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 26, 1),
+    ]);
   }
 
   test_error_duplicateDefinition_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   int get t => 0;
   int get t => 0;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 38, 1),
+    ]);
   }
 
   test_error_duplicateDefinition_getter_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   int get foo => 0;
   void foo() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 37, 3),
+    ]);
   }
 
   test_error_duplicateDefinition_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   void t() {}
   void t() {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 31, 1),
+    ]);
   }
 
   test_error_duplicateDefinition_method_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   void foo() {}
   int get foo => 0;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 36, 3),
+    ]);
   }
 
   test_error_duplicateDefinition_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   void set t(_) {}
   void set t(_) {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 40, 1),
+    ]);
   }
 
   test_error_finalNotInitialized() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   final int f;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([StaticWarningCode.FINAL_NOT_INITIALIZED]);
+''', [
+      error(StaticWarningCode.FINAL_NOT_INITIALIZED, 22, 1),
+    ]);
   }
 
   test_error_finalNotInitialized_OK() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 mixin M {
   final int f = 0;
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_finalNotInitializedConstructor() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   final int f;
   M();
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR,
-      StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1,
+''', [
+      error(CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR, 27, 1),
+      error(StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1, 27, 1),
     ]);
   }
 
   test_error_finalNotInitializedConstructor_OK() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   final int f;
   M(this.f);
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR, 27, 1),
+    ]);
 
     var element = findElement.mixin('M');
     var constructorElement = element.constructors.single;
@@ -795,18 +727,15 @@
   }
 
   test_error_implementsClause_deferredClass() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 import 'dart:math' deferred as math;
 mixin M implements math.Random {}
-''');
-    await resolveTestFile();
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS, 56, 11),
+    ]);
     var mathImport = findElement.import('dart:math');
     var randomElement = mathImport.importedLibrary.getType('Random');
 
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS,
-    ]);
-
     var element = findElement.mixin('M');
     assertElementTypes(element.interfaces, [randomElement.type]);
 
@@ -816,13 +745,10 @@
   }
 
   test_error_implementsClause_disallowedClass_int() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M implements int {}
-''');
-    await resolveTestFile();
-
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 3),
     ]);
 
     var element = findElement.mixin('M');
@@ -833,14 +759,11 @@
   }
 
   test_error_implementsClause_nonClass_void() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M implements void {}
-''');
-    await resolveTestFile();
-
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.IMPLEMENTS_NON_CLASS,
-      ParserErrorCode.EXPECTED_TYPE_NAME,
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_NON_CLASS, 19, 4),
+      error(ParserErrorCode.EXPECTED_TYPE_NAME, 19, 4),
     ]);
 
     var element = findElement.mixin('M');
@@ -851,57 +774,56 @@
   }
 
   test_error_implementsRepeated() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {}
 mixin M implements A, A {}
-''');
-    await resolveTestFile();
-    CompileTimeErrorCode.IMPLEMENTS_REPEATED;
-    assertTestErrorsWithCodes([CompileTimeErrorCode.IMPLEMENTS_REPEATED]);
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_REPEATED, 33, 1),
+    ]);
   }
 
   test_error_memberWithClassName_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   int get M => 0;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
+''', [
+      error(CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, 20, 1),
+    ]);
   }
 
   test_error_memberWithClassName_getter_static() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   static int get M => 0;
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
+''', [
+      error(CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, 27, 1),
+    ]);
   }
 
   test_error_memberWithClassName_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   void set M(_) {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
+''', [
+      error(CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, 21, 1),
+    ]);
   }
 
   test_error_memberWithClassName_setter_static() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   static void set M(_) {}
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
+''', [
+      error(CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, 28, 1),
+    ]);
   }
 
   test_error_mixinApplicationConcreteSuperInvokedMemberType_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class I {
   void foo([int p]) {}
 }
@@ -921,15 +843,17 @@
 }
 
 abstract class X extends B with M {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE,
+''', [
+      error(
+          CompileTimeErrorCode
+              .MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE,
+          224,
+          1),
     ]);
   }
 
   test_error_mixinApplicationConcreteSuperInvokedMemberType_OK_method_overriddenInMixin() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A<T> {
   void remove(T x) {}
 }
@@ -942,12 +866,10 @@
 
 class X<T> = A<T> with M<T>;
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_mixinApplicationNoConcreteSuperInvokedMember_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   int get foo;
 }
@@ -959,15 +881,17 @@
 }
 
 abstract class X extends A with M {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
+''', [
+      error(
+          CompileTimeErrorCode
+              .MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
+          121,
+          1),
     ]);
   }
 
   test_error_mixinApplicationNoConcreteSuperInvokedMember_inNextMixin() async {
-    addTestFile('''
+    await assertErrorsInCode('''
 abstract class A {
   void foo();
 }
@@ -983,15 +907,17 @@
 }
 
 class X extends A with M1, M2 {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER
+''', [
+      error(
+          CompileTimeErrorCode
+              .MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
+          149,
+          2),
     ]);
   }
 
   test_error_mixinApplicationNoConcreteSuperInvokedMember_inSameMixin() async {
-    addTestFile('''
+    await assertErrorsInCode('''
 abstract class A {
   void foo();
 }
@@ -1003,15 +929,17 @@
 }
 
 class X extends A with M {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER
+''', [
+      error(
+          CompileTimeErrorCode
+              .MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
+          113,
+          1),
     ]);
   }
 
   test_error_mixinApplicationNoConcreteSuperInvokedMember_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   void foo();
 }
@@ -1023,15 +951,17 @@
 }
 
 abstract class X extends A with M {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
+''', [
+      error(
+          CompileTimeErrorCode
+              .MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
+          122,
+          1),
     ]);
   }
 
   test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_hasNSM() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   void foo();
 }
@@ -1048,12 +978,10 @@
 
 class X extends C with M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_hasNSM2() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   void foo();
 }
@@ -1074,12 +1002,10 @@
 
 class X extends C with M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_inPreviousMixin() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   void foo();
 }
@@ -1096,12 +1022,10 @@
 
 class X extends A with M1, M2 {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_inSuper_fromMixin() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   void foo();
 }
@@ -1120,12 +1044,10 @@
 
 class X extends B with M2 {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_notInvoked() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A {
   void foo();
 }
@@ -1134,12 +1056,10 @@
 
 abstract class X extends A with M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_super_covariant() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   bar(num n) {}
 }
@@ -1156,12 +1076,10 @@
 
 class C extends B with M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_mixinApplicationNoConcreteSuperInvokedMember_setter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   void set foo(_);
 }
@@ -1173,43 +1091,43 @@
 }
 
 abstract class X extends A with M {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
+''', [
+      error(
+          CompileTimeErrorCode
+              .MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
+          129,
+          1),
     ]);
   }
 
   test_error_mixinApplicationNotImplementedInterface() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {}
 
 mixin M on A {}
 
 class X = Object with M;
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
+''', [
+      error(CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
+          51, 1),
     ]);
   }
 
   test_error_mixinApplicationNotImplementedInterface_generic() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A<T> {}
 
 mixin M on A<int> {}
 
 class X = A<double> with M;
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
+''', [
+      error(CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
+          62, 1),
     ]);
   }
 
   test_error_mixinApplicationNotImplementedInterface_noMemberErrors() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {
   void foo() {}
 }
@@ -1225,37 +1143,32 @@
 }
 
 class X = C with M;
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
+''', [
+      error(CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
+          134, 1),
     ]);
   }
 
   test_error_mixinApplicationNotImplementedInterface_OK_0() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 mixin M {}
 
 class X = Object with M;
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_mixinApplicationNotImplementedInterface_OK_1() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 
 mixin M on A {}
 
 class X = A with M;
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_mixinApplicationNotImplementedInterface_OK_generic() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A<T> {}
 
 mixin M<T> on A<T> {}
@@ -1264,12 +1177,10 @@
 
 class C<T> = B<T> with M<T>;
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_mixinApplicationNotImplementedInterface_OK_previousMixin() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 
 mixin M1 implements A {}
@@ -1278,12 +1189,10 @@
 
 class X = Object with M1, M2;
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_error_mixinApplicationNotImplementedInterface_oneOfTwo() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {}
 class B {}
 class C {}
@@ -1291,24 +1200,22 @@
 mixin M on A, B {}
 
 class X = C with M;
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
+''', [
+      error(CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
+          71, 1),
     ]);
   }
 
   test_error_mixinDeclaresConstructor() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   M(int a) {
     a; // read
   }
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes(
-        [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR, 12, 1),
+    ]);
 
     // Even though it is an error for a mixin to declare a constructor,
     // we still build elements for constructors, and resolve them.
@@ -1347,7 +1254,7 @@
   }
 
   test_error_mixinInstantiate_named() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {
   M.named() {}
 }
@@ -1355,11 +1262,9 @@
 main() {
   new M.named();
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR,
-      CompileTimeErrorCode.MIXIN_INSTANTIATE,
+''', [
+      error(CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR, 12, 1),
+      error(CompileTimeErrorCode.MIXIN_INSTANTIATE, 43, 1),
     ]);
 
     var creation = findNode.instanceCreation('M.named();');
@@ -1368,16 +1273,14 @@
   }
 
   test_error_mixinInstantiate_undefined() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M {}
 
 main() {
   new M.named();
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_INSTANTIATE,
+''', [
+      error(CompileTimeErrorCode.MIXIN_INSTANTIATE, 27, 1),
     ]);
 
     var creation = findNode.instanceCreation('M.named();');
@@ -1386,18 +1289,16 @@
   }
 
   test_error_onClause_deferredClass() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 import 'dart:math' deferred as math;
 mixin M on math.Random {}
-''');
-    await resolveTestFile();
+''', [
+      error(CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS,
+          48, 11),
+    ]);
     var mathImport = findElement.import('dart:math');
     var randomElement = mathImport.importedLibrary.getType('Random');
 
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS,
-    ]);
-
     var element = findElement.mixin('M');
     assertElementTypes(element.superclassConstraints, [randomElement.type]);
 
@@ -1407,13 +1308,11 @@
   }
 
   test_error_onClause_disallowedClass_int() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M on int {}
-''');
-    await resolveTestFile();
-
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS,
+''', [
+      error(CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS,
+          11, 3),
     ]);
 
     var element = findElement.mixin('M');
@@ -1424,13 +1323,11 @@
   }
 
   test_error_onClause_nonInterface_dynamic() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M on dynamic {}
-''');
-    await resolveTestFile();
-
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE,
+''', [
+      error(CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE, 11,
+          7),
     ]);
 
     var element = findElement.mixin('M');
@@ -1441,14 +1338,12 @@
   }
 
   test_error_onClause_nonInterface_enum() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 enum E {E1, E2, E3}
 mixin M on E {}
-''');
-    await resolveTestFile();
-
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE,
+''', [
+      error(CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE, 31,
+          1),
     ]);
 
     var element = findElement.mixin('M');
@@ -1459,14 +1354,12 @@
   }
 
   test_error_onClause_nonInterface_void() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin M on void {}
-''');
-    await resolveTestFile();
-
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE,
-      ParserErrorCode.EXPECTED_TYPE_NAME,
+''', [
+      error(ParserErrorCode.EXPECTED_TYPE_NAME, 11, 4),
+      error(CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE, 11,
+          4),
     ]);
 
     var element = findElement.mixin('M');
@@ -1477,12 +1370,10 @@
   }
 
   test_error_onClause_OK_mixin() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 mixin A {}
 mixin B on A {} // ref
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var a = findElement.mixin('A');
     var b = findElement.mixin('B');
@@ -1490,17 +1381,16 @@
   }
 
   test_error_onRepeated() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {}
 mixin M on A, A {}
-''');
-    await resolveTestFile();
-    CompileTimeErrorCode.IMPLEMENTS_REPEATED;
-    assertTestErrorsWithCodes([CompileTimeErrorCode.ON_REPEATED]);
+''', [
+      error(CompileTimeErrorCode.ON_REPEATED, 25, 1),
+    ]);
   }
 
   test_error_undefinedSuperMethod() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 class A {}
 
 mixin M on A {
@@ -1508,9 +1398,9 @@
     super.foo(42);
   }
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([StaticTypeWarningCode.UNDEFINED_SUPER_METHOD]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, 52, 3),
+    ]);
 
     var invocation = findNode.methodInvocation('foo(42)');
     assertElementNull(invocation.methodName);
@@ -1519,13 +1409,11 @@
   }
 
   test_field() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 mixin M<T> {
   T f;
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var element = findElement.mixin('M');
 
@@ -1558,14 +1446,12 @@
   }
 
   test_implementsClause() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B {}
 
 mixin M implements A, B {} // M
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var element = findElement.mixin('M');
     assertElementTypes(element.interfaces, [
@@ -1581,7 +1467,7 @@
   }
 
   test_inconsistentInheritance_implements_parameterType() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   x(int i);
 }
@@ -1589,15 +1475,13 @@
   x(String s);
 }
 mixin M implements A, B {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.INCONSISTENT_INHERITANCE,
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 75, 1),
     ]);
   }
 
   test_inconsistentInheritance_implements_requiredParameters() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   x();
 }
@@ -1605,15 +1489,13 @@
   x(int y);
 }
 mixin M implements A, B {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.INCONSISTENT_INHERITANCE,
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 67, 1),
     ]);
   }
 
   test_inconsistentInheritance_implements_returnType() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   int x();
 }
@@ -1621,15 +1503,13 @@
   String x();
 }
 mixin M implements A, B {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.INCONSISTENT_INHERITANCE,
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 73, 1),
     ]);
   }
 
   test_inconsistentInheritance_on_parameterType() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   x(int i);
 }
@@ -1637,15 +1517,13 @@
   x(String s);
 }
 mixin M on A, B {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.INCONSISTENT_INHERITANCE,
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 75, 1),
     ]);
   }
 
   test_inconsistentInheritance_on_requiredParameters() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   x();
 }
@@ -1653,15 +1531,13 @@
   x(int y);
 }
 mixin M on A, B {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.INCONSISTENT_INHERITANCE,
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 67, 1),
     ]);
   }
 
   test_inconsistentInheritance_on_returnType() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   int x();
 }
@@ -1669,15 +1545,13 @@
   String x();
 }
 mixin M on A, B {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.INCONSISTENT_INHERITANCE,
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 73, 1),
     ]);
   }
 
   test_inconsistentInheritanceGetterAndMethod_implements_getter_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   int get x;
 }
@@ -1685,15 +1559,14 @@
   int x();
 }
 mixin M implements A, B {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD,
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD, 72,
+          1),
     ]);
   }
 
   test_inconsistentInheritanceGetterAndMethod_implements_method_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   int x();
 }
@@ -1701,15 +1574,14 @@
   int get x;
 }
 mixin M implements A, B {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD,
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD, 72,
+          1),
     ]);
   }
 
   test_inconsistentInheritanceGetterAndMethod_on_getter_method() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   int get x;
 }
@@ -1717,15 +1589,14 @@
   int x();
 }
 mixin M implements A, B {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD,
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD, 72,
+          1),
     ]);
   }
 
   test_inconsistentInheritanceGetterAndMethod_on_method_getter() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   int x();
 }
@@ -1733,15 +1604,14 @@
   int get x;
 }
 mixin M implements A, B {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD,
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD, 72,
+          1),
     ]);
   }
 
   test_invalid_unresolved_before_mixin() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   int foo();
 }
@@ -1753,23 +1623,23 @@
 }
 
 abstract class X extends A with U1, U2, M {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
-      CompileTimeErrorCode.MIXIN_OF_NON_CLASS,
-      CompileTimeErrorCode.MIXIN_OF_NON_CLASS,
-      StaticWarningCode.UNDEFINED_CLASS,
-      StaticWarningCode.UNDEFINED_CLASS,
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 121, 2),
+      error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 121, 2),
+      error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 125, 2),
+      error(StaticWarningCode.UNDEFINED_CLASS, 125, 2),
+      error(
+          CompileTimeErrorCode
+              .MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
+          129,
+          1),
     ]);
   }
 
   test_isMoreSpecificThan() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 mixin M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var element = findElement.mixin('M');
     var type = element.type;
@@ -1777,26 +1647,22 @@
   }
 
   test_lookUpMemberInInterfaces_Object() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class Foo {}
 
 mixin UnhappyMixin on Foo {
   String toString() => '$runtimeType';
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_metadata() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 const a = 0;
 
 @a
 mixin M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var a = findElement.topGet('a');
     var element = findElement.mixin('M');
@@ -1811,7 +1677,7 @@
   }
 
   test_methodCallTypeInference_mixinType() async {
-    addTestFile('''
+    await assertNoErrorsInCode('''
 main() {
   C<int> c = f();
 }
@@ -1822,21 +1688,17 @@
 
 M<T> f<T>() => null;
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
     var fInvocation = findNode.methodInvocation('f()');
-    expect(fInvocation.staticInvokeType.toString(), '() → M<int>');
+    expect(fInvocation.staticInvokeType.toString(), 'M<int> Function()');
   }
 
   test_onClause() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 class B {}
 
 mixin M on A, B {} // M
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var element = findElement.mixin('M');
     assertElementTypes(element.superclassConstraints, [
@@ -1852,39 +1714,33 @@
   }
 
   test_recursiveInterfaceInheritance_implements() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin A implements B {}
-mixin B implements A {}''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
+mixin B implements A {}''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 30, 1),
     ]);
   }
 
   test_recursiveInterfaceInheritance_on() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin A on B {}
-mixin B on A {}''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
+mixin B on A {}''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 22, 1),
     ]);
   }
 
   test_recursiveInterfaceInheritanceOn() async {
-    addTestFile(r'''
+    await assertErrorsInCode(r'''
 mixin A on A {}
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_ON,
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_ON, 6, 1),
     ]);
   }
 
   test_superInvocation_getter() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int get foo => 0;
 }
@@ -1897,8 +1753,6 @@
 
 class X extends A with M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var access = findNode.propertyAccess('super.foo;');
     assertElement(access, findElement.getter('foo'));
@@ -1906,7 +1760,7 @@
   }
 
   test_superInvocation_method() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   void foo(int x) {}
 }
@@ -1919,17 +1773,15 @@
 
 class X extends A with M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(42)');
     assertElement(invocation, findElement.method('foo'));
-    assertInvokeType(invocation, '(int) → void');
+    assertInvokeType(invocation, 'void Function(int)');
     assertType(invocation, 'void');
   }
 
   test_superInvocation_setter() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   void set foo(_) {}
 }
@@ -1942,8 +1794,6 @@
 
 class X extends A with M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var access = findNode.propertyAccess('super.foo = 0');
     assertElement(access, findElement.setter('foo'));
diff --git a/pkg/analyzer/test/src/dart/resolution/namespace_test.dart b/pkg/analyzer/test/src/dart/resolution/namespace_test.dart
new file mode 100644
index 0000000..7cceecc
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/namespace_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ImportResolutionTest);
+    defineReflectiveTests(ImportResolutionWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class ImportResolutionTest extends DriverResolutionTest {
+  test_overrideCoreType_Never() async {
+    newFile('/test/lib/declares_never.dart', content: '''
+class Never {}
+''');
+    assertNoErrorsInCode(r'''
+import 'declares_never.dart';
+
+Never f() => throw 'foo';
+''');
+  }
+}
+
+@reflectiveTest
+class ImportResolutionWithNnbdTest extends ImportResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index 820678a..c722521 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
@@ -26,6 +26,85 @@
   @override
   bool get typeToStringWithNullability => true;
 
+  test_local_getterNullAwareAccess_interfaceType() async {
+    addTestFile(r'''
+m() {
+  int? x;
+  return x?.isEven;
+}
+''');
+
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.propertyAccess('x?.isEven'), 'bool?');
+  }
+
+  test_local_methodNullAwareCall_interfaceType() async {
+    await addTestFile(r'''
+class C {
+  bool x() => true;
+}
+m() {
+  C? c;
+  return c?.x();
+}
+''');
+
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.methodInvocation('c?.x()'), 'bool?');
+  }
+
+  test_local_nullCoalesce_nullableInt_int() async {
+    await addTestFile(r'''
+m() {
+  int? x;
+  int y;
+  x ?? y;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.binary('x ?? y'), 'int');
+  }
+
+  test_local_nullCoalesce_nullableInt_nullableInt() async {
+    await addTestFile(r'''
+m() {
+  int? x;
+  x ?? x;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.binary('x ?? x'), 'int?');
+  }
+
+  test_local_nullCoalesceAssign_nullableInt_int() async {
+    await addTestFile(r'''
+m() {
+  int? x;
+  int y;
+  x ??= y;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.assignment('x ??= y'), 'int');
+  }
+
+  test_local_nullCoalesceAssign_nullableInt_nullableInt() async {
+    await addTestFile(r'''
+m() {
+  int? x;
+  x ??= x;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.assignment('x ??= x'), 'int?');
+  }
+
   test_local_parameter_interfaceType() async {
     addTestFile('''
 main() {
@@ -116,6 +195,30 @@
     assertType(findNode.typeName('T? b'), 'T?');
   }
 
+  test_member_potentiallyNullable_called() async {
+    addTestFile(r'''
+m<T extends Function>() {
+  List<T?> x;
+  x.first();
+}
+''');
+    await resolveTestFile();
+    // Do not assert no test errors. Deliberately invokes nullable type.
+    assertType(findNode.methodInvocation('first').methodName, 'Function?');
+  }
+
+  test_null_assertion_operator_changes_null_to_never() async {
+    addTestFile('''
+main() {
+  Null x = null;
+  x!;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.postfix('x!'), 'Never');
+  }
+
   test_null_assertion_operator_removes_nullability() async {
     addTestFile('''
 main() {
@@ -139,7 +242,7 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    assertType(findNode.typeName('F? a'), '(bool, String?) → int??');
+    assertType(findNode.typeName('F? a'), 'int? Function(bool, String?)?');
   }
 
   @failingTest
@@ -156,15 +259,9 @@
 
     assertType(
       findNode.typeName('F<String>'),
-      '(bool!, String!, String?) → int??',
+      'int? Function(bool!, String!, String?)?',
     );
   }
-}
-
-@reflectiveTest
-class NullableTest extends DriverResolutionTest {
-  @override
-  bool get typeToStringWithNullability => true;
 
   test_class_hierarchy() async {
     addTestFile('''
@@ -198,6 +295,58 @@
     assertType(findNode.typeName('C;'), 'C');
   }
 
+  test_mixin_hierarchy() async {
+    addTestFile('''
+class A {}
+
+mixin X1 on A {} // 1
+mixin X2 implements A {} // 2
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('A {} // 1'), 'A');
+    assertType(findNode.typeName('A {} // 2'), 'A');
+  }
+}
+
+@reflectiveTest
+class NullableTest extends DriverResolutionTest {
+  @override
+  bool get typeToStringWithNullability => true;
+
+  test_class_hierarchy() async {
+    addTestFile('''
+class A {}
+
+class X1 extends A {} // 1
+class X2 implements A {} // 2
+class X3 with A {} // 3
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('A {} // 1'), 'A*');
+    assertType(findNode.typeName('A {} // 2'), 'A*');
+    assertType(findNode.typeName('A {} // 3'), 'A*');
+  }
+
+  test_classTypeAlias_hierarchy() async {
+    addTestFile('''
+class A {}
+class B {}
+class C {}
+
+class X = A with B implements C;
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('A with'), 'A*');
+    assertType(findNode.typeName('B implements'), 'B*');
+    assertType(findNode.typeName('C;'), 'C*');
+  }
+
   test_local_variable_interfaceType_notMigrated() async {
     addTestFile('''
 main() {
@@ -222,7 +371,7 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    assertType(findNode.typeName('A {} // 1'), 'A');
-    assertType(findNode.typeName('A {} // 2'), 'A');
+    assertType(findNode.typeName('A {} // 1'), 'A*');
+    assertType(findNode.typeName('A {} // 2'), 'A*');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
index 895ec43..5a47b69 100644
--- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -56,6 +57,7 @@
       'B<num>',
       constructorName: 'named',
       expectedConstructorMember: true,
+      expectedPrefix: _importOfA()?.prefix,
     );
   }
 
@@ -66,6 +68,7 @@
       libraryA.getType('B'),
       'B<num>',
       expectedConstructorMember: true,
+      expectedPrefix: _importOfA()?.prefix,
     );
   }
 
@@ -96,6 +99,7 @@
       libraryA.getType('A'),
       'A',
       constructorName: 'named',
+      expectedPrefix: _importOfA()?.prefix,
     );
   }
 
@@ -106,9 +110,50 @@
       creation,
       libraryA.getType('A'),
       'A',
+      expectedPrefix: _importOfA()?.prefix,
     );
   }
 
+  test_prefixed_unnamed_generic() async {
+    newFile('/test/lib/a.dart', content: r'''
+class C<T> {
+  const C();
+}
+''');
+    await assertNoErrorsInCode(r'''
+import 'a.dart' as p;
+
+const x = p.C<int>();
+''');
+    _fillLibraries();
+
+    var element_C = libraryA.getType('C');
+    var element_p = findElement.prefix('p');
+
+    var creation = findNode.instanceCreation('p.C<int>()');
+    assertType(creation, 'C<int>');
+
+    var constructorName = creation.constructorName;
+
+    var typeName = constructorName.type;
+    assertType(typeName, 'C<int>');
+
+    var pC = typeName.name as PrefixedIdentifier;
+    assertElement(pC, element_C);
+    // TODO(scheglov) enforce
+//    assertTypeNull(pC);
+
+    var ref_p = pC.prefix;
+    assertElement(ref_p, element_p);
+    assertTypeNull(ref_p);
+
+    var ref_C = pC.identifier;
+    assertElement(ref_C, element_C);
+    assertTypeNull(ref_C);
+
+    assertType(typeName.typeArguments.arguments[0], 'int');
+  }
+
   void _fillLibraries([LibraryElement library]) {
     library ??= result.unit.declaredElement.library;
     var uriStr = library.source.uri.toString();
@@ -118,6 +163,15 @@
     }
   }
 
+  ImportElement _importOfA() {
+    if (AnalysisDriver.useSummary2) {
+      var importOfB = findElement.import('package:test/b.dart');
+      return importOfB.importedLibrary.imports[0];
+    } else {
+      return null;
+    }
+  }
+
   Future<InstanceCreationExpression> _resolveImplicitConst(String expr,
       {String prefix}) async {
     newFile('/test/lib/a.dart', content: '''
@@ -154,7 +208,9 @@
     var v = vg.variable as ConstVariableElement;
 
     InstanceCreationExpression creation = v.constantInitializer;
-    expect(creation.keyword.keyword, Keyword.CONST);
+    if (!AnalysisDriver.useSummary2) {
+      expect(creation.keyword.keyword, Keyword.CONST);
+    }
 
     return creation;
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index b713264..56deafe 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -26,8 +26,6 @@
 
 final isDynamicType = new TypeMatcher<DynamicTypeImpl>();
 
-final isUndefinedType = new TypeMatcher<UndefinedTypeImpl>();
-
 final isVoidType = new TypeMatcher<VoidTypeImpl>();
 
 /// Base for resolution tests.
@@ -200,7 +198,7 @@
     var getter = findElement.topGet(name);
     assertElement(ref, getter);
 
-    var type = getter.returnType.toString();
+    var type = typeString(getter.returnType);
     assertType(ref, type);
   }
 
@@ -208,7 +206,7 @@
     var setter = findElement.topSet(name);
     assertElement(ref, setter);
 
-    var type = setter.parameters[0].type.toString();
+    var type = typeString(setter.parameters[0].type);
     assertType(ref, type);
   }
 
@@ -265,8 +263,8 @@
   }
 
   void assertInvokeType(InvocationExpression node, String expected) {
-    DartType actual = node.staticInvokeType;
-    expect(actual?.toString(), expected);
+    TypeImpl actual = node.staticInvokeType;
+    expect(typeString(actual), expected);
   }
 
   void assertInvokeTypeDynamic(InvocationExpression node) {
@@ -277,15 +275,19 @@
   void assertMember(
       Expression node, String expectedDefiningType, Element expectedBase) {
     Member actual = getNodeElement(node);
-    expect(actual.definingType.toString(), expectedDefiningType);
+    expect(typeString(actual.definingType), expectedDefiningType);
     expect(actual.baseElement, same(expectedBase));
   }
 
-  void assertMethodInvocation(MethodInvocation invocation,
-      Element expectedElement, String expectedInvokeType,
-      {String expectedMethodNameType,
-      String expectedNameType,
-      String expectedType}) {
+  void assertMethodInvocation(
+    MethodInvocation invocation,
+    Element expectedElement,
+    String expectedInvokeType, {
+    String expectedMethodNameType,
+    String expectedNameType,
+    String expectedType,
+    List<String> expectedTypeArguments: const <String>[],
+  }) {
     MethodInvocationImpl invocationImpl = invocation;
 
     // TODO(scheglov) Check for Member.
@@ -307,6 +309,8 @@
 //    }
 //    assertType(invocation.methodName, expectedNameType);
 
+    assertTypeArgumentTypes(invocation, expectedTypeArguments);
+
     assertInvokeType(invocation, expectedInvokeType);
 
     expectedType ??= _extractReturnType(expectedInvokeType);
@@ -369,8 +373,15 @@
     } else {
       fail('Unsupported node: (${node.runtimeType}) $node');
     }
-    expect(actual?.toString(withNullability: typeToStringWithNullability),
-        expected);
+    expect(typeString(actual), expected);
+  }
+
+  void assertTypeArgumentTypes(
+    InvocationExpression node,
+    List<String> expected,
+  ) {
+    var actual = node.typeArgumentTypes.map((t) => typeString(t)).toList();
+    expect(actual, expected);
   }
 
   void assertTypeDynamic(Expression expression) {
@@ -395,7 +406,12 @@
       expect(name.prefix.staticType, isNull);
 
       assertElement(name.identifier, expectedElement);
-      expect(name.identifier.staticType, isNull);
+
+      // TODO(scheglov) This should be null, but it is not.
+      // ResolverVisitor sets the tpe for `Bar` in `new foo.Bar()`. This is
+      // probably wrong. It is fine for the TypeName `foo.Bar` to have a type,
+      // and for `foo.Bar()` to have a type. But not a name of a type? No.
+//      expect(name.identifier.staticType, isNull);
     }
   }
 
@@ -443,6 +459,11 @@
     findElement = new FindElement(result.unit);
   }
 
+  /// Return a textual representation of the [type] that is appropriate for
+  /// tests.
+  String typeString(DartType type) => (type as TypeImpl)
+      ?.toString(withNullability: typeToStringWithNullability);
+
   Element _unwrapHandle(Element element) {
     if (element is ElementHandle && element is! Member) {
       return element.actualElement;
@@ -451,8 +472,8 @@
   }
 
   static String _extractReturnType(String invokeType) {
-    int arrowIndex = invokeType.indexOf('→');
-    expect(arrowIndex, isNonNegative);
-    return invokeType.substring(arrowIndex + 1).trim();
+    int functionIndex = invokeType.indexOf(' Function');
+    expect(functionIndex, isNonNegative);
+    return invokeType.substring(0, functionIndex);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index ccbc919..10b3832 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -9,11 +9,16 @@
 import 'class_test.dart' as class_resolution;
 import 'comment_test.dart' as comment;
 import 'constant_test.dart' as constant;
+import 'constructor_test.dart' as constructor;
 import 'definite_assignment_test.dart' as definite_assignment;
 import 'enum_test.dart' as enum_resolution;
+import 'export_test.dart' as export_;
 import 'flow_analysis_test.dart' as flow_analysis;
 import 'for_element_test.dart' as for_element;
 import 'for_in_test.dart' as for_in;
+import 'function_expression_invocation_test.dart'
+    as function_expression_invocation;
+import 'generic_function_type_test.dart' as generic_function_type;
 import 'generic_type_alias_test.dart' as generic_type_alias;
 import 'import_prefix_test.dart' as import_prefix;
 import 'instance_creation_test.dart' as instance_creation;
@@ -23,6 +28,7 @@
     as instance_member_inference_mixin;
 import 'method_invocation_test.dart' as method_invocation;
 import 'mixin_test.dart' as mixin_resolution;
+import 'namespace_test.dart' as namespace;
 import 'non_nullable_test.dart' as non_nullable;
 import 'optional_const_test.dart' as optional_const;
 import 'property_access_test.dart' as property_access;
@@ -36,11 +42,15 @@
     class_resolution.main();
     comment.main();
     constant.main();
+    constructor.main();
     definite_assignment.main();
     enum_resolution.main();
+    export_.main();
     flow_analysis.main();
     for_element.main();
     for_in.main();
+    function_expression_invocation.main();
+    generic_function_type.main();
     generic_type_alias.main();
     import_prefix.main();
     instance_creation.main();
@@ -48,6 +58,7 @@
     instance_member_inference_mixin.main();
     method_invocation.main();
     mixin_resolution.main();
+    namespace.main();
     non_nullable.main();
     optional_const.main();
     property_access.main();
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
new file mode 100644
index 0000000..0b07098
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
@@ -0,0 +1,335 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ForElementWithNnbdTest);
+    defineReflectiveTests(IfElementWithNnbdTest);
+    defineReflectiveTests(SpreadElementWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class ForElementWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_list_awaitForIn_dynamic_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int>[await for (var e in a()) e];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+  }
+
+  @failingTest
+  test_list_awaitForIn_int_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int>[await for (int e in a()) e];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+  }
+
+  @failingTest
+  test_list_for_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>[for (int i = 0; a(); i++) i];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_list_forIn_dynamic_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>[for (var e in a()) e];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+  }
+
+  @failingTest
+  test_list_forIn_int_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>[for (int e in a()) e];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+
+  @failingTest
+  test_map_awaitForIn_dynamic_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int, int>{await for (var e in a()) e : e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+  }
+
+  @failingTest
+  test_map_awaitForIn_int_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int, int>{await for (int e in a()) e : e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+  }
+
+  @failingTest
+  test_map_for_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int, int>{for (int i = 0; a(); i++) i : i};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_map_forIn_dynamic_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int, int>{for (var e in a()) e : e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+  }
+
+  @failingTest
+  test_map_forIn_int_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int, int>{for (int e in a()) e : e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+
+  @failingTest
+  test_set_awaitForIn_dynamic_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int>{await for (var e in a()) e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+  }
+
+  @failingTest
+  test_set_awaitForIn_int_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int>{await for (int e in a()) e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+  }
+
+  @failingTest
+  test_set_for_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>{for (int i = 0; a(); i++) i};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_set_forIn_dynamic_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>{for (var e in a()) e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+  }
+
+  @failingTest
+  test_set_forIn_int_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>{for (int e in a()) e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+}
+
+@reflectiveTest
+class IfElementWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_list_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>[if (a()) 1];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_map_downward() async {
+    addTestFile('''
+void f() {
+  var b = <String, int>{if (a()) 'a' : 1};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_set_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>{if (a()) 1};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+}
+
+@reflectiveTest
+class SpreadElementWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_list_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>[...a()];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+
+  @failingTest
+  test_map_downward() async {
+    addTestFile('''
+void f() {
+  var b = <String, int>{...a()};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Map<String, int> Function()');
+  }
+
+  @failingTest
+  test_set_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>{...a()};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
new file mode 100644
index 0000000..72ebc03
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConditionalExpressionTest);
+    defineReflectiveTests(ConditionalExpressionWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class ConditionalExpressionTest extends DriverResolutionTest {
+  test_upward() async {
+    addTestFile('''
+void f(bool a, int b, int c) {
+  var d = a ? b : c;
+  print(d);
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.simple('d)'), 'int');
+  }
+}
+
+@reflectiveTest
+class ConditionalExpressionWithNnbdTest extends ConditionalExpressionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f(int b, int c) {
+  var d = a() ? b : c;
+  print(d);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('d)'), 'bool Function()');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/equality_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/equality_expressions_test.dart
new file mode 100644
index 0000000..d0bf2ff
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/equality_expressions_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(EqualTest);
+    defineReflectiveTests(EqualWithNnbdTest);
+    defineReflectiveTests(NotEqualTest);
+    defineReflectiveTests(NotEqualWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class EqualTest extends DriverResolutionTest {
+  test_simple() async {
+    addTestFile('''
+void f(Object a, Object b) {
+  var c = a == b;
+  print(c);
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.simple('c)'), 'bool');
+  }
+}
+
+@reflectiveTest
+class EqualWithNnbdTest extends EqualTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+}
+
+@reflectiveTest
+class NotEqualTest extends DriverResolutionTest {
+  test_simple() async {
+    addTestFile('''
+void f(Object a, Object b) {
+  var c = a != b;
+  print(c);
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.simple('c)'), 'bool');
+  }
+}
+
+@reflectiveTest
+class NotEqualWithNnbdTest extends NotEqualTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
index 1f90c94..daf22e8 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
@@ -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.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../driver_resolution.dart';
@@ -11,7 +9,6 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ListLiteralTest);
-    defineReflectiveTests(ListLiteralWithFlowControlAndSpreadCollectionsTest);
   });
 }
 
@@ -136,58 +133,6 @@
     assertType(findNode.listLiteral('['), 'List<Object>');
   }
 
-  test_noContext_noTypeArgs_noElements() async {
-    addTestFile('''
-var a = [];
-''');
-    await resolveTestFile();
-    assertType(findNode.listLiteral('['), 'List<dynamic>');
-  }
-
-  test_noContext_typeArgs_expression_conflict() async {
-    addTestFile('''
-var a = <String>[1];
-''');
-    await resolveTestFile();
-    assertType(findNode.listLiteral('['), 'List<String>');
-  }
-
-  test_noContext_typeArgs_expression_noConflict() async {
-    addTestFile('''
-var a = <int>[1];
-''');
-    await resolveTestFile();
-    assertType(findNode.listLiteral('['), 'List<int>');
-  }
-
-  @failingTest
-  test_noContext_typeArgs_expressions_conflict() async {
-    addTestFile('''
-var a = <int, String>[1, 2];
-''');
-    await resolveTestFile();
-    assertType(findNode.listLiteral('['), 'List<int>');
-  }
-
-  test_noContext_typeArgs_noElements() async {
-    addTestFile('''
-var a = <num>[];
-''');
-    await resolveTestFile();
-    assertType(findNode.listLiteral('['), 'List<num>');
-  }
-}
-
-@reflectiveTest
-class ListLiteralWithFlowControlAndSpreadCollectionsTest
-    extends ListLiteralTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_noContext_noTypeArgs_forEachWithDeclaration() async {
     addTestFile('''
 List<int> c;
@@ -260,6 +205,14 @@
     assertType(findNode.listLiteral('['), 'List<Object>');
   }
 
+  test_noContext_noTypeArgs_noElements() async {
+    addTestFile('''
+var a = [];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<dynamic>');
+  }
+
   test_noContext_noTypeArgs_spread() async {
     addTestFile('''
 List<int> c;
@@ -330,4 +283,37 @@
     await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<Null>');
   }
+
+  test_noContext_typeArgs_expression_conflict() async {
+    addTestFile('''
+var a = <String>[1];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<String>');
+  }
+
+  test_noContext_typeArgs_expression_noConflict() async {
+    addTestFile('''
+var a = <int>[1];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<int>');
+  }
+
+  @failingTest
+  test_noContext_typeArgs_expressions_conflict() async {
+    addTestFile('''
+var a = <int, String>[1, 2];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<int>');
+  }
+
+  test_noContext_typeArgs_noElements() async {
+    addTestFile('''
+var a = <num>[];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<num>');
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart
new file mode 100644
index 0000000..bf31077
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(LogicalAndTest);
+    defineReflectiveTests(LogicalAndWithNnbdTest);
+    defineReflectiveTests(LogicalOrTest);
+    defineReflectiveTests(LogicalOrWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class LogicalAndTest extends DriverResolutionTest {
+  test_upward() async {
+    addTestFile('''
+void f(bool a, bool b) {
+  var c = a && b;
+  print(c);
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.simple('c)'), 'bool');
+  }
+}
+
+@reflectiveTest
+class LogicalAndWithNnbdTest extends LogicalAndTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f(b) {
+  var c = a() && b();
+  print(c);
+}
+T a<T>() => throw '';
+T b<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+    assertInvokeType(findNode.methodInvocation('b('), 'bool Function()');
+  }
+}
+
+@reflectiveTest
+class LogicalOrTest extends DriverResolutionTest {
+  test_upward() async {
+    addTestFile('''
+void f(bool a, bool b) {
+  var c = a || b;
+  print(c);
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.simple('c)'), 'bool');
+  }
+}
+
+@reflectiveTest
+class LogicalOrWithNnbdTest extends LogicalOrTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f(b) {
+  var c = a() || b();
+  print(c);
+}
+T a<T>() => throw '';
+T b<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+    assertInvokeType(findNode.methodInvocation('b('), 'bool Function()');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
index 7c7d5cd..d09d57f 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
@@ -3,8 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../driver_resolution.dart';
@@ -12,7 +10,6 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapLiteralTest);
-    defineReflectiveTests(MapLiteralWithFlowControlAndSpreadCollectionsTest);
   });
 }
 
@@ -154,76 +151,6 @@
     assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
   }
 
-  test_noContext_noTypeArgs_noEntries() async {
-    addTestFile('''
-var a = {};
-''');
-    await resolveTestFile();
-    assertType(setOrMapLiteral('{'), 'Map<dynamic, dynamic>');
-  }
-
-  test_noContext_typeArgs_entry_conflictingKey() async {
-    addTestFile('''
-var a = <String, int>{1 : 2};
-''');
-    await resolveTestFile();
-    assertType(setOrMapLiteral('{'), 'Map<String, int>');
-  }
-
-  test_noContext_typeArgs_entry_conflictingValue() async {
-    addTestFile('''
-var a = <String, int>{'a' : 'b'};
-''');
-    await resolveTestFile();
-    assertType(setOrMapLiteral('{'), 'Map<String, int>');
-  }
-
-  test_noContext_typeArgs_entry_noConflict() async {
-    addTestFile('''
-var a = <int, int>{1 : 2};
-''');
-    await resolveTestFile();
-    assertType(setOrMapLiteral('{'), 'Map<int, int>');
-  }
-
-  test_noContext_typeArgs_expression_conflictingElement() async {
-    addTestFile('''
-var a = <int, String>{1};
-''');
-    await resolveTestFile();
-    assertType(setOrMapLiteral('{'), 'Map<int, String>');
-  }
-
-  @failingTest
-  test_noContext_typeArgs_expressions_conflictingTypeArgs() async {
-    addTestFile('''
-var a = <int>{1 : 2, 3 : 4};
-''');
-    await resolveTestFile();
-    assertType(setOrMapLiteral('{'), 'Map<int, int>');
-  }
-
-  test_noContext_typeArgs_noEntries() async {
-    addTestFile('''
-var a = <num, String>{};
-''');
-    await resolveTestFile();
-    assertType(setOrMapLiteral('{'), 'Map<num, String>');
-  }
-}
-
-@reflectiveTest
-class MapLiteralWithFlowControlAndSpreadCollectionsTest extends MapLiteralTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
-  @override
-  AstNode setOrMapLiteral(String search) => findNode.setOrMapLiteral(search);
-
   test_noContext_noTypeArgs_forEachWithDeclaration() async {
     addTestFile('''
 List<int> c;
@@ -296,6 +223,14 @@
     assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
   }
 
+  test_noContext_noTypeArgs_noEntries() async {
+    addTestFile('''
+var a = {};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<dynamic, dynamic>');
+  }
+
   test_noContext_noTypeArgs_spread() async {
     addTestFile('''
 Map<int, int> c;
@@ -376,4 +311,53 @@
     await resolveTestFile();
     assertType(setOrMapLiteral('{...'), 'dynamic');
   }
+
+  test_noContext_typeArgs_entry_conflictingKey() async {
+    addTestFile('''
+var a = <String, int>{1 : 2};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<String, int>');
+  }
+
+  test_noContext_typeArgs_entry_conflictingValue() async {
+    addTestFile('''
+var a = <String, int>{'a' : 'b'};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<String, int>');
+  }
+
+  test_noContext_typeArgs_entry_noConflict() async {
+    addTestFile('''
+var a = <int, int>{1 : 2};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<int, int>');
+  }
+
+  test_noContext_typeArgs_expression_conflictingElement() async {
+    addTestFile('''
+var a = <int, String>{1};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<int, String>');
+  }
+
+  @failingTest
+  test_noContext_typeArgs_expressions_conflictingTypeArgs() async {
+    addTestFile('''
+var a = <int>{1 : 2, 3 : 4};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<int, int>');
+  }
+
+  test_noContext_typeArgs_noEntries() async {
+    addTestFile('''
+var a = <num, String>{};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<num, String>');
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart
new file mode 100644
index 0000000..60335c4
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NotTest);
+    defineReflectiveTests(NotWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class NotTest extends DriverResolutionTest {
+  test_upward() async {
+    addTestFile('''
+void f(bool a) {
+  var b = !a;
+  print(b);
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.simple('b)'), 'bool');
+  }
+}
+
+@reflectiveTest
+class NotWithNnbdTest extends NotTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f(b) {
+  var c = !a();
+  print(c);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
index b2da4b7..a6a6664 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
@@ -3,8 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../driver_resolution.dart';
@@ -12,7 +10,6 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SetLiteralTest);
-    defineReflectiveTests(SetLiteralWithFlowControlAndSpreadCollectionsTest);
   });
 }
 
@@ -129,52 +126,6 @@
     assertType(setLiteral('{'), 'Set<Object>');
   }
 
-  test_noContext_typeArgs_expression_conflict() async {
-    addTestFile('''
-var a = <String>{1};
-''');
-    await resolveTestFile();
-    assertType(setLiteral('{'), 'Set<String>');
-  }
-
-  test_noContext_typeArgs_expression_noConflict() async {
-    addTestFile('''
-var a = <int>{1};
-''');
-    await resolveTestFile();
-    assertType(setLiteral('{'), 'Set<int>');
-  }
-
-  @failingTest
-  test_noContext_typeArgs_expressions_conflict() async {
-    addTestFile('''
-var a = <int, String>{1, 2};
-''');
-    await resolveTestFile();
-    assertType(setLiteral('{'), 'Set<int>');
-  }
-
-  test_noContext_typeArgs_noElements() async {
-    addTestFile('''
-var a = <num>{};
-''');
-    await resolveTestFile();
-    assertType(setLiteral('{'), 'Set<num>');
-  }
-}
-
-@reflectiveTest
-class SetLiteralWithFlowControlAndSpreadCollectionsTest extends SetLiteralTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
-  @override
-  AstNode setLiteral(String search) => findNode.setOrMapLiteral(search);
-
   test_noContext_noTypeArgs_forEachWithDeclaration() async {
     addTestFile('''
 List<int> c;
@@ -307,4 +258,37 @@
     await resolveTestFile();
     assertType(setLiteral('{1'), 'Set<int>');
   }
+
+  test_noContext_typeArgs_expression_conflict() async {
+    addTestFile('''
+var a = <String>{1};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{'), 'Set<String>');
+  }
+
+  test_noContext_typeArgs_expression_noConflict() async {
+    addTestFile('''
+var a = <int>{1};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{'), 'Set<int>');
+  }
+
+  @failingTest
+  test_noContext_typeArgs_expressions_conflict() async {
+    addTestFile('''
+var a = <int, String>{1, 2};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{'), 'Set<int>');
+  }
+
+  test_noContext_typeArgs_noElements() async {
+    addTestFile('''
+var a = <num>{};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{'), 'Set<num>');
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
new file mode 100644
index 0000000..6137756
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
@@ -0,0 +1,185 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AssertWithNnbdTest);
+    defineReflectiveTests(DoWithNnbdTest);
+    defineReflectiveTests(ForWithNnbdTest);
+    defineReflectiveTests(IfWithNnbdTest);
+    defineReflectiveTests(WhileWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class AssertWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f() {
+  assert(a());
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+}
+
+@reflectiveTest
+class DoWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f() {
+  do {} while(a())
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+}
+
+@reflectiveTest
+class ForWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_awaitForIn_dynamic_downward() async {
+    addTestFile('''
+void f() async {
+  await for (var e in a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+  }
+
+  @failingTest
+  test_awaitForIn_int_downward() async {
+    addTestFile('''
+void f() async {
+  await for (int e in a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+  }
+
+  @failingTest
+  test_for_downward() async {
+    addTestFile('''
+void f() {
+  for (int i = 0; a(); i++) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_forIn_dynamic_downward() async {
+    addTestFile('''
+void f() {
+  for (var e in a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+  }
+
+  @failingTest
+  test_forIn_int_downward() async {
+    addTestFile('''
+void f() {
+  for (int e in a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+}
+
+@reflectiveTest
+class IfWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f() {
+  if (a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+}
+
+@reflectiveTest
+class WhileWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f() {
+  while (a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
index 54ada38..0369a65 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
@@ -4,14 +4,30 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'collection_elements_test.dart' as collection_elements;
+import 'conditional_expression_test.dart' as conditional_expression;
+import 'equality_expressions_test.dart' as equality_expressions;
 import 'list_literal_test.dart' as list_literal;
+import 'logical_boolean_expressions_test.dart' as logical_boolean_expressions;
 import 'map_literal_test.dart' as map_literal;
+import 'prefix_expressions_test.dart' as prefix_expressions;
 import 'set_literal_test.dart' as set_literal;
+import 'statements_test.dart' as statements;
+import 'throw_test.dart' as throw_expression;
+import 'type_test_expressions_test.dart' as type_test_expressions;
 
 main() {
   defineReflectiveSuite(() {
+    collection_elements.main();
+    conditional_expression.main();
+    equality_expressions.main();
     list_literal.main();
+    logical_boolean_expressions.main();
     map_literal.main();
+    prefix_expressions.main();
     set_literal.main();
+    statements.main();
+    throw_expression.main();
+    type_test_expressions.main();
   }, name: 'type inference');
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
new file mode 100644
index 0000000..8cdfe3a
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ThrowWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class ThrowWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f() {
+  throw a();
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'dynamic Function()');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/type_test_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/type_test_expressions_test.dart
new file mode 100644
index 0000000..9dd6039
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/type_test_expressions_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(IsNotTest);
+    defineReflectiveTests(IsNotWithNnbdTest);
+    defineReflectiveTests(IsTest);
+    defineReflectiveTests(IsWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class IsNotTest extends DriverResolutionTest {
+  test_simple() async {
+    addTestFile('''
+void f(Object a) {
+  var b = a is! String;
+  print(b);
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.simple('b)'), 'bool');
+  }
+}
+
+@reflectiveTest
+class IsNotWithNnbdTest extends IsNotTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+}
+
+@reflectiveTest
+class IsTest extends DriverResolutionTest {
+  test_simple() async {
+    addTestFile('''
+void f(Object a) {
+  var b = a is String;
+  print(b);
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.simple('b)'), 'bool');
+  }
+}
+
+@reflectiveTest
+class IsWithNnbdTest extends IsTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+}
diff --git a/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
index 6a313d0..46c0d8d 100644
--- a/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
+++ b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
@@ -3,8 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:test/test.dart';
@@ -25,13 +23,6 @@
 /// experiments be enabled.
 @reflectiveTest
 class ExitDetectorForCodeAsUiTest extends ParseBase {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
   test_for_condition() async {
     _assertTrue('[for (; throw 0;) 0]');
   }
diff --git a/pkg/analyzer/test/src/dart/sdk/patch_test.dart b/pkg/analyzer/test/src/dart/sdk/patch_test.dart
index 0357f98..7c13bdf 100644
--- a/pkg/analyzer/test/src/dart/sdk/patch_test.dart
+++ b/pkg/analyzer/test/src/dart/sdk/patch_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -21,6 +22,8 @@
 
 @reflectiveTest
 class SdkPatcherTest with ResourceProviderMixin {
+  final featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
+
   Folder sdkFolder;
   FolderBasedDartSdk sdk;
 
@@ -720,7 +723,7 @@
       };
       File file = newFile('/sdk/lib/test/test.dart');
       Source source = file.createSource(Uri.parse('dart:test'));
-      CompilationUnit unit = SdkPatcher.parse(source, listener);
+      CompilationUnit unit = SdkPatcher.parse(source, listener, featureSet);
       patcher.patch(resourceProvider, patchPaths, listener, source, unit);
     }, throwsArgumentError);
   }
@@ -755,7 +758,7 @@
     _createSdk();
 
     Source source = file.createSource(Uri.parse('dart:_internal'));
-    CompilationUnit unit = SdkPatcher.parse(source, listener);
+    CompilationUnit unit = SdkPatcher.parse(source, listener, featureSet);
     patcher.patch(resourceProvider, patchPaths, listener, source, unit);
     _assertUnitCode(
         unit,
@@ -807,7 +810,7 @@
     {
       Uri uri = Uri.parse('dart:test');
       Source source = fileLib.createSource(uri);
-      CompilationUnit unit = SdkPatcher.parse(source, listener);
+      CompilationUnit unit = SdkPatcher.parse(source, listener, featureSet);
       patcher.patch(resourceProvider, patchPaths, listener, source, unit);
       _assertUnitCode(
           unit,
@@ -818,7 +821,7 @@
     {
       Uri uri = Uri.parse('dart:test/test_part.dart');
       Source source = filePart.createSource(uri);
-      CompilationUnit unit = SdkPatcher.parse(source, listener);
+      CompilationUnit unit = SdkPatcher.parse(source, listener, featureSet);
       patcher.patch(resourceProvider, patchPaths, listener, source, unit);
       _assertUnitCode(unit, "part of test; class B {int _b() => 1;}");
     }
@@ -1071,7 +1074,7 @@
     _createSdk();
 
     Source source = file.createSource(Uri.parse('dart:test'));
-    CompilationUnit unit = SdkPatcher.parse(source, listener);
+    CompilationUnit unit = SdkPatcher.parse(source, listener, featureSet);
     patcher.patch(resourceProvider, patchPaths, listener, source, unit);
     return unit;
   }
diff --git a/pkg/analyzer/test/src/dartdoc/dartdoc_directive_info_test.dart b/pkg/analyzer/test/src/dartdoc/dartdoc_directive_info_test.dart
index 43c386a..389fff5 100644
--- a/pkg/analyzer/test/src/dartdoc/dartdoc_directive_info_test.dart
+++ b/pkg/analyzer/test/src/dartdoc/dartdoc_directive_info_test.dart
@@ -81,4 +81,30 @@
     expect(result, '''
 Comment without a macro.''');
   }
+
+  test_processDartdoc_youtube_directive() {
+    String result = info.processDartdoc('''
+/// {@youtube 560 315 https://www.youtube.com/watch?v=2uaoEDOgk_I}
+''');
+    expect(result, '''
+[www.youtube.com/watch?v=2uaoEDOgk_I](https://www.youtube.com/watch?v=2uaoEDOgk_I)''');
+  }
+
+  test_processDartdoc_youtube_malformed() {
+    String result = info.processDartdoc('''
+/// {@youtube 560x315 https://www.youtube.com/watch?v=2uaoEDOgk_I}
+''');
+    expect(result,
+        '{@youtube 560x315 https://www.youtube.com/watch?v=2uaoEDOgk_I}');
+  }
+
+  test_processDartdoc_animation_directive() {
+    String result = info.processDartdoc('''
+/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_bounce_in.mp4}
+''');
+    expect(
+        result,
+        '[flutter.github.io/assets-for-api-docs/assets/animation/curve_bounce_in.mp4]'
+        '(https://flutter.github.io/assets-for-api-docs/assets/animation/curve_bounce_in.mp4)');
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart b/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart
index 202c01bd..26f5983 100644
--- a/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart
@@ -2,9 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -18,13 +16,6 @@
 
 @reflectiveTest
 class AmbiguousSetOrMapLiteralBothTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_setAndMap() async {
     assertErrorsInCode('''
 Map<int, int> map;
@@ -38,12 +29,14 @@
 
 @reflectiveTest
 class AmbiguousSetOrMapLiteralEitherTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
+  test_invalidPrefixOperator() async {
+    // Guard against an exception being thrown.
+    await assertErrorsInCode('''
+union(a, b) => !{...a, ...b};
+''', [
+      error(CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER, 16, 12),
+    ]);
+  }
 
   test_setAndMap() async {
     assertErrorsInCode('''
diff --git a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
index 28b285e..06192b0 100644
--- a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
@@ -2,7 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -10,6 +12,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ArgumentTypeNotAssignableTest);
+    defineReflectiveTests(ArgumentTypeNotAssignableTest_NNBD);
   });
 }
 
@@ -41,3 +44,45 @@
     ]);
   }
 }
+
+@reflectiveTest
+class ArgumentTypeNotAssignableTest_NNBD extends ArgumentTypeNotAssignableTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
+
+  test_downcast() async {
+    await assertErrorsInCode(r'''
+m() {
+  num y = 1;
+  n(y);
+}
+n(int x) {}
+''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 23, 1),
+    ]);
+  }
+
+  @failingTest
+  test_downcast_nullableNonNullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? y;
+  n(y);
+}
+n(int x) {}
+''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 24, 1),
+    ]);
+  }
+
+  test_dynamicCast() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  dynamic i;
+  n(i);
+}
+n(int i) {}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart b/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
index 28ab163..f773a8c 100644
--- a/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
@@ -16,278 +16,6 @@
 
 @reflectiveTest
 class AsyncKeywordUsedAsIdentifierTest extends DriverResolutionTest {
-  test_async_annotation() async {
-    await assertErrorsInCode('''
-const int async = 0;
-f() async {
-  g(@async x) {}
-  g(0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
-    ]);
-  }
-
-  test_async_argumentLabel() async {
-    await assertErrorsInCode('''
-f(c) async {
-  c.g(async: 0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 19, 5),
-    ]);
-  }
-
-  test_async_async() async {
-    await assertErrorsInCode('''
-f() async {
-  var async = 1;
-  print(async);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
-    ]);
-  }
-
-  test_async_asyncStar() async {
-    await assertErrorsInCode('''
-f() async* {
-  var async = 1;
-  print(async);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 19, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
-    ]);
-  }
-
-  test_async_break() async {
-    await assertErrorsInCode('''
-f() async {
-  while (true) {
-    break async;
-  }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 39, 5),
-      error(CompileTimeErrorCode.LABEL_UNDEFINED, 39, 5),
-    ]);
-  }
-
-  test_async_catchException() async {
-    await assertErrorsInCode('''
-g() {}
-f() async {
-  try {
-    g();
-  } catch (async) { }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 47, 5),
-    ]);
-  }
-
-  test_async_catchStacktrace() async {
-    await assertErrorsInCode('''
-g() {}
-f() async {
-  try {
-    g();
-  } catch (e, async) { }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 50, 5),
-      error(HintCode.UNUSED_CATCH_STACK, 50, 5),
-    ]);
-  }
-
-  test_async_continue() async {
-    await assertErrorsInCode('''
-f() async {
-  while (true) {
-    continue async;
-  }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 42, 5),
-      error(CompileTimeErrorCode.LABEL_UNDEFINED, 42, 5),
-    ]);
-  }
-
-  test_async_for() async {
-    await assertErrorsInCode('''
-var async;
-f() async {
-  for (async in []) {}
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 30, 5),
-    ]);
-  }
-
-  test_async_formalParameter() async {
-    await assertErrorsInCode('''
-f() async {
-  g(int async) {}
-  g(0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 20, 5),
-    ]);
-  }
-
-  test_async_getter() async {
-    await assertErrorsInCode('''
-class C {
-  int get async => 1;
-}
-f() async {
-  return new C().async;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 63, 5),
-    ]);
-  }
-
-  test_async_invocation() async {
-    await assertErrorsInCode('''
-class C {
-  int async() => 1;
-}
-f() async {
-  return new C().async();
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 61, 5),
-    ]);
-  }
-
-  test_async_invocation_cascaded() async {
-    await assertErrorsInCode('''
-class C {
-  int async() => 1;
-}
-f() async {
-  return new C()..async();
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 62, 5),
-    ]);
-  }
-
-  test_async_label() async {
-    await assertErrorsInCode('''
-f() async {
-  async: g();
-}
-g() {}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 14, 5),
-      error(HintCode.UNUSED_LABEL, 14, 6),
-    ]);
-  }
-
-  test_async_localFunction() async {
-    await assertErrorsInCode('''
-f() async {
-  int async() => null;
-  async();
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
-    ]);
-  }
-
-  test_async_prefix() async {
-    await assertErrorsInCode('''
-import 'dart:async' as async;
-f() async {
-  return new async.Future.value(0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 55, 5),
-    ]);
-  }
-
-  test_async_setter() async {
-    await assertErrorsInCode('''
-class C {
-  void set async(int i) {}
-}
-f() async {
-  new C().async = 1;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 61, 5),
-    ]);
-  }
-
-  test_async_setter_cascaded() async {
-    await assertErrorsInCode('''
-class C {
-  void set async(int i) {}
-}
-f() async {
-  return new C()..async = 1;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 69, 5),
-    ]);
-  }
-
-  test_async_stringInterpolation() async {
-    await assertErrorsInCode(r'''
-int async = 1;
-f() async {
-  return "$async";
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
-    ]);
-  }
-
-  test_async_suffix() async {
-    newFile("/test/lib/lib1.dart", content: r'''
-library lib1;
-int async;
-''');
-    await assertErrorsInCode('''
-import 'lib1.dart' as l;
-f() async {
-  return l.async;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 48, 5),
-    ]);
-  }
-
-  test_async_switchLabel() async {
-    await assertErrorsInCode('''
-f() async {
-  switch (0) {
-    async: case 0: break;
-  }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 31, 5),
-      error(HintCode.UNUSED_LABEL, 31, 6),
-    ]);
-  }
-
-  test_async_syncStar() async {
-    await assertErrorsInCode('''
-f() sync* {
-  var async = 1;
-  print(async);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
-    ]);
-  }
-
   test_await_async() async {
     await assertErrorsInCode('''
 f() async {
diff --git a/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart b/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
index 662215a..4800889 100644
--- a/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
@@ -16,7 +16,7 @@
 @reflectiveTest
 class ConstConstructorWithMixinWithFieldTest extends DriverResolutionTest {
   test_class_instance() async {
-    addTestFile(r'''
+    await assertErrorsInCode('''
 class A {
   var a;
 }
@@ -24,16 +24,16 @@
 class B extends Object with A {
   const B();
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
+''', [
+      error(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 56, 10),
+      error(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 62, 1),
     ]);
   }
 
   test_class_instance_final() async {
-    addTestFile(r'''
+    await assertErrorsInCode('''
 class A {
   final a = 0;
 }
@@ -41,27 +41,24 @@
 class B extends Object with A {
   const B();
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
+''', [
+      error(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 68, 1),
     ]);
   }
 
   test_class_noFields() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode('''
 class M {}
 
 class X extends Object with M {
   const X();
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_class_static() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode('''
 class M {
   static final a = 0;
 }
@@ -70,12 +67,10 @@
   const X();
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_mixin_instance() async {
-    addTestFile(r'''
+    await assertErrorsInCode('''
 mixin M {
   var a;
 }
@@ -83,16 +78,16 @@
 class X extends Object with M {
   const X();
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
+''', [
+      error(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 56, 10),
+      error(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 62, 1),
     ]);
   }
 
   test_mixin_instance_final() async {
-    addTestFile(r'''
+    await assertErrorsInCode('''
 mixin M {
   final a = 0;
 }
@@ -100,27 +95,24 @@
 class X extends Object with M {
   const X();
 }
-''');
-    await resolveTestFile();
-    assertTestErrorsWithCodes([
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
+''', [
+      error(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 68, 1),
     ]);
   }
 
   test_mixin_noFields() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode('''
 mixin M {}
 
 class X extends Object with M {
   const X();
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_mixin_static() async {
-    addTestFile(r'''
+    await assertNoErrorsInCode('''
 mixin M {
   static final a = 0;
 }
@@ -129,7 +121,5 @@
   const X();
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart b/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
index ba1168f..aa13cab 100644
--- a/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
@@ -14,8 +14,6 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(ConstEvalThrowsExceptionTest);
     defineReflectiveTests(ConstEvalThrowsExceptionWithConstantUpdateTest);
-    defineReflectiveTests(ConstEvalThrowsExceptionWithUiAsCodeAndConstantsTest);
-    defineReflectiveTests(ConstEvalThrowsExceptionWithUIAsCodeTest);
   });
 }
 
@@ -25,15 +23,6 @@
 class ConstEvalThrowsExceptionTest extends DriverResolutionTest {
   test_CastError_intToDouble_constructor_importAnalyzedAfter() async {
     // See dartbug.com/35993
-    addTestFile(r'''
-import 'other.dart';
-
-void main() {
-  const foo = Foo(1);
-  const bar = Bar.some();
-  print("$foo, $bar");
-}
-''');
     newFile('/test/lib/other.dart', content: '''
 class Foo {
   final double value;
@@ -48,8 +37,15 @@
 
   const Bar.some() : this(const Foo(1));
 }''');
-    await resolveTestFile();
-    assertNoTestErrors();
+    await assertNoErrorsInCode(r'''
+import 'other.dart';
+
+void main() {
+  const foo = Foo(1);
+  const bar = Bar.some();
+  print("$foo, $bar");
+}
+''');
     var otherFileResult =
         await resolveFile(convertPath('/test/lib/other.dart'));
     expect(otherFileResult.errors, isEmpty);
@@ -57,15 +53,6 @@
 
   test_CastError_intToDouble_constructor_importAnalyzedBefore() async {
     // See dartbug.com/35993
-    addTestFile(r'''
-import 'other.dart';
-
-void main() {
-  const foo = Foo(1);
-  const bar = Bar.some();
-  print("$foo, $bar");
-}
-''');
     newFile('/test/lib/other.dart', content: '''
 class Foo {
   final double value;
@@ -80,21 +67,21 @@
 
   const Bar.some() : this(const Foo(1));
 }''');
+    await assertNoErrorsInCode(r'''
+import 'other.dart';
+
+void main() {
+  const foo = Foo(1);
+  const bar = Bar.some();
+  print("$foo, $bar");
+}
+''');
     var otherFileResult =
         await resolveFile(convertPath('/test/lib/other.dart'));
     expect(otherFileResult.errors, isEmpty);
-    await resolveTestFile();
-    assertNoTestErrors();
   }
 
   test_default_constructor_arg_empty_map_importAnalyzedAfter() async {
-    addTestFile('''
-import 'other.dart';
-
-main() {
-  var c = const C();
-}
-''');
     newFile('/test/lib/other.dart', content: '''
 class C {
   final Map<String, int> m;
@@ -102,21 +89,19 @@
     : assert(m != null);
 }
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
+    await assertNoErrorsInCode('''
+import 'other.dart';
+
+main() {
+  var c = const C();
+}
+''');
     var otherFileResult =
         await resolveFile(convertPath('/test/lib/other.dart'));
     expect(otherFileResult.errors, isEmpty);
   }
 
   test_default_constructor_arg_empty_map_importAnalyzedBefore() async {
-    addTestFile('''
-import 'other.dart';
-
-main() {
-  var c = const C();
-}
-''');
     newFile('/test/lib/other.dart', content: '''
 class C {
   final Map<String, int> m;
@@ -124,11 +109,103 @@
     : assert(m != null);
 }
 ''');
+    await assertNoErrorsInCode('''
+import 'other.dart';
+
+main() {
+  var c = const C();
+}
+''');
     var otherFileResult =
         await resolveFile(convertPath('/test/lib/other.dart'));
     expect(otherFileResult.errors, isEmpty);
-    await resolveTestFile();
-    assertNoTestErrors();
+  }
+
+  test_fromEnvironment_assertInitializer() async {
+    await assertNoErrorsInCode('''
+class A {
+  const A(int x) : assert(x > 5);
+}
+
+main() {
+  var c = const A(int.fromEnvironment('x'));
+  print(c);
+}
+''');
+  }
+
+  test_ifElement_false_thenNotEvaluated() async {
+    await assertErrorsInCode(
+        '''
+const dynamic nil = null;
+const c = [if (1 < 0) nil + 1];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 37, 18),
+              ]);
+  }
+
+  test_ifElement_nonBoolCondition_list() async {
+    await assertErrorsInCode(
+        '''
+const dynamic nonBool = 3;
+const c = const [if (nonBool) 'a'];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 48, 7),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 44, 16),
+                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 48, 7),
+              ]);
+  }
+
+  test_ifElement_nonBoolCondition_map() async {
+    await assertErrorsInCode(
+        '''
+const dynamic nonBool = null;
+const c = const {if (nonBool) 'a' : 1};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 51, 7),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 20),
+                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 51, 7),
+              ]);
+  }
+
+  test_ifElement_nonBoolCondition_set() async {
+    await assertErrorsInCode(
+        '''
+const dynamic nonBool = 'a';
+const c = const {if (nonBool) 3};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 50, 7),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 46, 14),
+                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 50, 7),
+              ]);
+  }
+
+  test_ifElement_true_elseNotEvaluated() async {
+    await assertErrorsInCode(
+        '''
+const dynamic nil = null;
+const c = [if (0 < 1) 3 else nil + 1];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 37, 25),
+              ]);
   }
 }
 
@@ -150,91 +227,16 @@
 }
 ''');
   }
+
+  test_fromEnvironment_ifElement() async {
+    await assertNoErrorsInCode('''
+const b = bool.fromEnvironment('foo');
+
+main() {
+  const l1 = [1, 2, 3];
+  const l2 = [if (b) ...l1];
+  print(l2);
 }
-
-@reflectiveTest
-class ConstEvalThrowsExceptionWithUiAsCodeAndConstantsTest
-    extends ConstEvalThrowsExceptionWithUIAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class ConstEvalThrowsExceptionWithUIAsCodeTest
-    extends ConstEvalThrowsExceptionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
-  test_ifElement_false_thenNotEvaluated() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic nil = null;
-const c = [if (1 < 0) nil + 1];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_ifElement_nonBoolCondition_list() async {
-    assertErrorCodesInCode(
-        '''
-const dynamic nonBool = 3;
-const c = const [if (nonBool) 'a'];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]
-            : [
-                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
-                CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT
-              ]);
-  }
-
-  test_ifElement_nonBoolCondition_map() async {
-    assertErrorCodesInCode(
-        '''
-const dynamic nonBool = null;
-const c = const {if (nonBool) 'a' : 1};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]
-            : [
-                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
-                CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
-              ]);
-  }
-
-  test_ifElement_nonBoolCondition_set() async {
-    assertErrorCodesInCode(
-        '''
-const dynamic nonBool = 'a';
-const c = const {if (nonBool) 3};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]
-            : [
-                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
-                CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT
-              ]);
-  }
-
-  test_ifElement_true_elseNotEvaluated() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic nil = null;
-const c = [if (0 < 1) 3 else nil + 1];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+''');
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/const_map_key_expression_type_implements_equals_test.dart b/pkg/analyzer/test/src/diagnostics/const_map_key_expression_type_implements_equals_test.dart
index 0a03667..f30871d 100644
--- a/pkg/analyzer/test/src/diagnostics/const_map_key_expression_type_implements_equals_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_map_key_expression_type_implements_equals_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -11,9 +10,6 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ConstMapKeyExpressionTypeImplementsEqualsTest);
-    defineReflectiveTests(
-      ConstMapKeyExpressionTypeImplementsEqualsWithUIAsCodeTest,
-    );
   });
 }
 
@@ -34,15 +30,20 @@
   }
 
   test_constField() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   const {double.INFINITY: 0};
 }
-''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+''', [
+      error(
+          CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
+          18,
+          15),
+    ]);
   }
 
   test_direct() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A();
   operator ==(other) => false;
@@ -51,14 +52,19 @@
 main() {
   const {const A() : 0};
 }
-''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+''', [
+      error(
+          CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
+          75,
+          9),
+    ]);
   }
 
   test_dynamic() async {
     // Note: static type of B.a is "dynamic", but actual type of the const
     // object is A.  We need to make sure we examine the actual type when
     // deciding whether there is a problem with operator==.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A();
   operator ==(other) => false;
@@ -71,11 +77,16 @@
 main() {
   const {B.a : 0};
 }
-''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+''', [
+      error(
+          CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
+          118,
+          3),
+    ]);
   }
 
   test_factory() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const factory A() = B;
 }
@@ -88,11 +99,16 @@
 main() {
   const {const A(): 42};
 }
-''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+''', [
+      error(
+          CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
+          121,
+          9),
+    ]);
   }
 
   test_super() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A();
   operator ==(other) => false;
@@ -105,14 +121,11 @@
 main() {
   const {const B() : 0};
 }
-''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+''', [
+      error(
+          CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
+          111,
+          9),
+    ]);
   }
 }
-
-@reflectiveTest
-class ConstMapKeyExpressionTypeImplementsEqualsWithUIAsCodeTest
-    extends ConstMapKeyExpressionTypeImplementsEqualsTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
-}
diff --git a/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart b/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart
index ded7bfb..c58b4cf 100644
--- a/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart
@@ -14,16 +14,13 @@
     defineReflectiveTests(ConstSetElementTypeImplementsEqualsTest);
     defineReflectiveTests(
         ConstSetElementTypeImplementsEqualsWithUIAsCodeAndConstantsTest);
-    defineReflectiveTests(
-      ConstSetElementTypeImplementsEqualsWithUIAsCodeTest,
-    );
   });
 }
 
 @reflectiveTest
 class ConstSetElementTypeImplementsEqualsTest extends DriverResolutionTest {
   test_constField() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   static const a = const A();
   const A();
@@ -32,11 +29,14 @@
 main() {
   const {A.a};
 }
-''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+''', [
+      error(CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS, 104,
+          3),
+    ]);
   }
 
   test_direct() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A();
   operator ==(other) => false;
@@ -44,14 +44,17 @@
 main() {
   const {const A()};
 }
-''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+''', [
+      error(
+          CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS, 74, 9),
+    ]);
   }
 
   test_dynamic() async {
     // Note: static type of B.a is "dynamic", but actual type of the const
     // object is A.  We need to make sure we examine the actual type when
     // deciding whether there is a problem with operator==.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A();
   operator ==(other) => false;
@@ -62,11 +65,14 @@
 main() {
   const {B.a};
 }
-''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+''', [
+      error(CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS, 116,
+          3),
+    ]);
   }
 
   test_factory() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A { const factory A() = B; }
 
 class B implements A {
@@ -77,50 +83,16 @@
 
 main() {
   var m = const {const A()};
+  print(m);
 }
-''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+''', [
+      error(CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS, 128,
+          9),
+    ]);
   }
 
-  test_super() async {
-    await assertErrorCodesInCode(r'''
-class A {
-  const A();
-  operator ==(other) => false;
-}
-class B extends A {
-  const B();
-}
-main() {
-  const {const B()};
-}
-''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
-  }
-}
-
-@reflectiveTest
-class ConstSetElementTypeImplementsEqualsWithUIAsCodeAndConstantsTest
-    extends ConstSetElementTypeImplementsEqualsWithUIAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class ConstSetElementTypeImplementsEqualsWithUIAsCodeTest
-    extends ConstSetElementTypeImplementsEqualsTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_spread_list() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 class A {
   const A();
@@ -132,12 +104,20 @@
 }
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            ? [
+                error(
+                    CompileTimeErrorCode
+                        .CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+                    75,
+                    8),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 75, 8),
+              ]);
   }
 
   test_spread_set() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 class A {
   const A();
@@ -149,10 +129,46 @@
 }
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]
+            ? [
+                error(
+                    CompileTimeErrorCode
+                        .CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+                    79,
+                    3),
+              ]
             : [
-                CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
-                CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 75, 8),
+                error(
+                    CompileTimeErrorCode
+                        .CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+                    79,
+                    3),
               ]);
   }
+
+  test_super() async {
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+  operator ==(other) => false;
+}
+class B extends A {
+  const B();
+}
+main() {
+  const {const B()};
+}
+''', [
+      error(CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS, 109,
+          9),
+    ]);
+  }
+}
+
+@reflectiveTest
+class ConstSetElementTypeImplementsEqualsWithUIAsCodeAndConstantsTest
+    extends ConstSetElementTypeImplementsEqualsTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart b/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart
index 5863409..76a0602 100644
--- a/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart
@@ -18,143 +18,178 @@
 
 @reflectiveTest
 class ConstSpreadExpectedListOrSetTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_const_listInt() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 5;
 var b = const <int>[...a];
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+                    44, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 41, 4),
+              ]);
   }
 
   test_const_listList() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = [5];
 var b = const <int>[...a];
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 43, 4),
+              ]);
   }
 
   test_const_listMap() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = <int, int>{0: 1};
 var b = const <int>[...a];
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+                    59, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 56, 4),
+              ]);
   }
 
   test_const_listNull() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = null;
 var b = const <int>[...a];
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+                    47, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 44, 4),
+              ]);
   }
 
   test_const_listNull_nullable() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = null;
 var b = const <int>[...?a];
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 44, 5),
+              ]);
   }
 
   test_const_listSet() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = <int>{5};
 var b = const <int>[...a];
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 48, 4),
+              ]);
   }
 
   test_const_setInt() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 5;
 var b = const <int>{...a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+                    44, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 4),
+              ]);
   }
 
   test_const_setList() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = <int>[5];
 var b = const <int>{...a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 48, 4),
+              ]);
   }
 
   test_const_setMap() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = <int, int>{1: 2};
 var b = const <int>{...a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+                    59, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 56, 4),
+              ]);
   }
 
   test_const_setNull() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = null;
 var b = const <int>{...a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+                    47, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 44, 4),
+              ]);
   }
 
   test_const_setNull_nullable() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = null;
 var b = const <int>{...?a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 44, 5),
+              ]);
   }
 
   test_const_setSet() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = <int>{5};
 var b = const <int>{...a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 48, 4),
+              ]);
   }
 
   test_nonConst_listInt() async {
@@ -177,9 +212,5 @@
     extends ConstSpreadExpectedListOrSetTest {
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart b/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart
index 93d86bb..d6892c7 100644
--- a/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart
@@ -18,33 +18,34 @@
 
 @reflectiveTest
 class ConstSpreadExpectedMapTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_const_mapInt() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 5;
 var b = const <int, int>{...a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 49, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 4),
+              ]);
   }
 
   test_const_mapList() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = <int>[5];
 var b = const <int, int>{...a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 56, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 53, 4),
+              ]);
   }
 
   test_const_mapMap() async {
@@ -55,14 +56,18 @@
   }
 
   test_const_mapNull() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = null;
 var b = const <int, int>{...a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 52, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 4),
+              ]);
   }
 
   test_const_mapNull_nullable() async {
@@ -73,14 +78,18 @@
   }
 
   test_const_mapSet() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = <int>{5};
 var b = const <int, int>{...a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 56, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 53, 4),
+              ]);
   }
 
   test_nonConst_mapInt() async {
@@ -103,9 +112,5 @@
     extends ConstSpreadExpectedMapTest {
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
index e97aa48..c84553a 100644
--- a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
@@ -66,10 +66,12 @@
   }
 
   test_deadBlock_conditionalElse() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   true ? 1 : 2;
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 19, 1),
+    ]);
   }
 
   test_deadBlock_conditionalElse_debugConst() async {
@@ -82,17 +84,21 @@
 
   test_deadBlock_conditionalElse_nested() async {
     // Test that a dead else-statement can't generate additional violations.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   true ? true : false && false;
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 22, 14),
+    ]);
   }
 
   test_deadBlock_conditionalIf() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   false ? 1 : 2;
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 16, 1),
+    ]);
   }
 
   test_deadBlock_conditionalIf_debugConst() async {
@@ -105,17 +111,21 @@
 
   test_deadBlock_conditionalIf_nested() async {
     // Test that a dead then-statement can't generate additional violations.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   false ? false && false : true;
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 16, 14),
+    ]);
   }
 
   test_deadBlock_else() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   if(true) {} else {}
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 25, 2),
+    ]);
   }
 
   test_deadBlock_else_debugConst() async {
@@ -128,17 +138,21 @@
 
   test_deadBlock_else_nested() async {
     // Test that a dead else-statement can't generate additional violations.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   if(true) {} else {if (false) {}}
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 25, 15),
+    ]);
   }
 
   test_deadBlock_if() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   if(false) {}
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 18, 2),
+    ]);
   }
 
   test_deadBlock_if_debugConst_prefixedIdentifier() async {
@@ -189,17 +203,21 @@
 
   test_deadBlock_if_nested() async {
     // Test that a dead then-statement can't generate additional violations.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   if(false) {if(false) {}}
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 18, 14),
+    ]);
   }
 
   test_deadBlock_while() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   while(false) {}
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 21, 2),
+    ]);
   }
 
   test_deadBlock_while_debugConst() async {
@@ -212,61 +230,81 @@
 
   test_deadBlock_while_nested() async {
     // Test that a dead while body can't generate additional violations.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   while(false) {if(false) {}}
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 21, 14),
+    ]);
   }
 
   test_deadCatch_catchFollowingCatch() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 f() {
   try {} catch (e) {} catch (e) {}
-}''', [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]);
+}''', [
+      error(HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, 39, 12),
+    ]);
   }
 
   test_deadCatch_catchFollowingCatch_nested() async {
     // Test that a dead catch clause can't generate additional violations.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 f() {
   try {} catch (e) {} catch (e) {if(false) {}}
-}''', [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]);
+}''', [
+      error(HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, 39, 24),
+    ]);
   }
 
   test_deadCatch_catchFollowingCatch_object() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   try {} on Object catch (e) {} catch (e) {}
-}''', [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]);
+}''', [
+      error(HintCode.UNUSED_CATCH_CLAUSE, 32, 1),
+      error(HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, 38, 12),
+    ]);
   }
 
   test_deadCatch_catchFollowingCatch_object_nested() async {
     // Test that a dead catch clause can't generate additional violations.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   try {} on Object catch (e) {} catch (e) {if(false) {}}
-}''', [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]);
+}''', [
+      error(HintCode.UNUSED_CATCH_CLAUSE, 32, 1),
+      error(HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, 38, 24),
+    ]);
   }
 
   test_deadCatch_onCatchSubtype() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 class B extends A {}
 f() {
   try {} on A catch (e) {} on B catch (e) {}
-}''', [HintCode.DEAD_CODE_ON_CATCH_SUBTYPE]);
+}''', [
+      error(HintCode.UNUSED_CATCH_CLAUSE, 59, 1),
+      error(HintCode.DEAD_CODE_ON_CATCH_SUBTYPE, 65, 17),
+      error(HintCode.UNUSED_CATCH_CLAUSE, 77, 1),
+    ]);
   }
 
   test_deadCatch_onCatchSubtype_nested() async {
     // Test that a dead catch clause can't generate additional violations.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 class B extends A {}
 f() {
   try {} on A catch (e) {} on B catch (e) {if(false) {}}
-}''', [HintCode.DEAD_CODE_ON_CATCH_SUBTYPE]);
+}''', [
+      error(HintCode.UNUSED_CATCH_CLAUSE, 59, 1),
+      error(HintCode.DEAD_CODE_ON_CATCH_SUBTYPE, 65, 29),
+      error(HintCode.UNUSED_CATCH_CLAUSE, 77, 1),
+    ]);
   }
 
   test_deadCatch_onCatchSupertype() async {
@@ -284,7 +322,7 @@
   switch (true) {
   case true:
     try {
-      int a = 1;
+      print(1);
     } finally {
       return;
     }
@@ -296,12 +334,12 @@
   }
 
   test_deadFinalReturnInCase() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   switch (true) {
   case true:
     try {
-      int a = 1;
+      print(1);
     } finally {
       return;
     }
@@ -309,16 +347,18 @@
   default:
     break;
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 103, 7),
+    ]);
   }
 
   test_deadFinalStatementInCase() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   switch (true) {
   case true:
     try {
-      int a = 1;
+      print(1);
     } finally {
       return;
     }
@@ -326,14 +366,19 @@
   default:
     break;
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 103, 12),
+    ]);
   }
 
   test_deadOperandLHS_and() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   bool b = false && false;
-}''', [HintCode.DEAD_CODE]);
+  print(b);
+}''', [
+      error(HintCode.DEAD_CODE, 26, 5),
+    ]);
   }
 
   test_deadOperandLHS_and_debugConst() async {
@@ -341,21 +386,28 @@
 const bool DEBUG = false;
 f() {
   bool b = DEBUG && false;
+  print(b);
 }''');
   }
 
   test_deadOperandLHS_and_nested() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   bool b = false && (false && false);
-}''', [HintCode.DEAD_CODE]);
+  print(b);
+}''', [
+      error(HintCode.DEAD_CODE, 26, 16),
+    ]);
   }
 
   test_deadOperandLHS_or() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   bool b = true || true;
-}''', [HintCode.DEAD_CODE]);
+  print(b);
+}''', [
+      error(HintCode.DEAD_CODE, 25, 4),
+    ]);
   }
 
   test_deadOperandLHS_or_debugConst() async {
@@ -367,15 +419,18 @@
   }
 
   test_deadOperandLHS_or_nested() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   bool b = true || (false && false);
-}''', [HintCode.DEAD_CODE]);
+  print(b);
+}''', [
+      error(HintCode.DEAD_CODE, 25, 16),
+    ]);
   }
 
   test_statementAfterAlwaysThrowsFunction() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 @alwaysThrows
@@ -384,16 +439,18 @@
 }
 
 f() {
-  var one = 1;
+  print(1);
   a();
-  var two = 2;
-}''', [HintCode.DEAD_CODE]);
+  print(2);
+}''', [
+      error(HintCode.DEAD_CODE, 104, 9),
+    ]);
   }
 
   @failingTest
   test_statementAfterAlwaysThrowsGetter() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 class C {
@@ -403,15 +460,17 @@
   }
 
 f() {
-  var one = 1;
+  print(1);
   new C().a;
-  var two = 2;
-}''', [HintCode.DEAD_CODE]);
+  print(2);
+}''', [
+      error(HintCode.DEAD_CODE, 129, 9),
+    ]);
   }
 
   test_statementAfterAlwaysThrowsMethod() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 class C {
@@ -422,107 +481,127 @@
 }
 
 f() {
-  var one = 1;
+  print(1);
   new C().a();
-  var two = 2;
-}''', [HintCode.DEAD_CODE]);
+  print(2);
+}''', [
+      error(HintCode.DEAD_CODE, 132, 9),
+    ]);
   }
 
   test_statementAfterBreak_inDefaultCase() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(v) {
   switch(v) {
     case 1:
     default:
       break;
-      var a;
+      print(1);
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 65, 9),
+    ]);
   }
 
   test_statementAfterBreak_inForEachStatement() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   var list;
   for(var l in list) {
     break;
-    var a;
+    print(l);
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 56, 9),
+    ]);
   }
 
   test_statementAfterBreak_inForStatement() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   for(;;) {
     break;
-    var a;
+    print(1);
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 33, 9),
+    ]);
   }
 
   test_statementAfterBreak_inSwitchCase() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(v) {
   switch(v) {
     case 1:
       break;
-      var a;
+      print(1);
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 52, 9),
+    ]);
   }
 
   test_statementAfterBreak_inWhileStatement() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(v) {
   while(v) {
     break;
-    var a;
+    print(1);
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 35, 9),
+    ]);
   }
 
   test_statementAfterContinue_inForEachStatement() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   var list;
   for(var l in list) {
     continue;
-    var a;
+    print(l);
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 59, 9),
+    ]);
   }
 
   test_statementAfterContinue_inForStatement() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   for(;;) {
     continue;
-    var a;
+    print(1);
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 36, 9),
+    ]);
   }
 
   test_statementAfterContinue_inWhileStatement() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(v) {
   while(v) {
     continue;
-    var a;
+    print(1);
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 38, 9),
+    ]);
   }
 
   test_statementAfterExitingIf_returns() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   if (1 > 2) {
     return;
   } else {
     return;
   }
-  var one = 1;
-}''', [HintCode.DEAD_CODE]);
+  print(1);
+}''', [
+      error(HintCode.DEAD_CODE, 62, 9),
+    ]);
   }
 
   test_statementAfterIfWithoutElse() async {
@@ -531,80 +610,94 @@
   if (1 < 0) {
     return;
   }
-  int a = 1;
+  print(1);
 }''');
   }
 
   test_statementAfterRethrow() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   try {
-    var one = 1;
+    print(1);
   } catch (e) {
     rethrow;
-    var two = 2;
+    print(2);
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 61, 9),
+    ]);
   }
 
   test_statementAfterReturn_function() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
-  var one = 1;
+  print(1);
   return;
-  var two = 2;
-}''', [HintCode.DEAD_CODE]);
+  print(2);
+}''', [
+      error(HintCode.DEAD_CODE, 30, 9),
+    ]);
   }
 
   test_statementAfterReturn_ifStatement() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(bool b) {
   if(b) {
-    var one = 1;
+    print(1);
     return;
-    var two = 2;
+    print(2);
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 52, 9),
+    ]);
   }
 
   test_statementAfterReturn_method() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   m() {
-    var one = 1;
+    print(1);
     return;
-    var two = 2;
+    print(2);
   }
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 48, 9),
+    ]);
   }
 
   test_statementAfterReturn_nested() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
-  var one = 1;
+  print(1);
   return;
   if(false) {}
-}''', [HintCode.DEAD_CODE]);
+}''', [
+      error(HintCode.DEAD_CODE, 30, 12),
+    ]);
   }
 
   test_statementAfterReturn_twoReturns() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
-  var one = 1;
+  print(1);
   return;
-  var two = 2;
+  print(2);
   return;
-  var three = 3;
-}''', [HintCode.DEAD_CODE]);
+  print(3);
+}''', [
+      error(HintCode.DEAD_CODE, 30, 31),
+    ]);
   }
 
   test_statementAfterThrow() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
-  var one = 1;
+  print(1);
   throw 'Stop here';
-  var two = 2;
-}''', [HintCode.DEAD_CODE]);
+  print(2);
+}''', [
+      error(HintCode.DEAD_CODE, 41, 9),
+    ]);
   }
 }
 
@@ -627,7 +720,7 @@
   }
 
   test_nullCoalesce_nonNullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 @pragma('analyzer:non-nullable')
 library foo;
 
@@ -635,7 +728,9 @@
   int x;
   x ?? 1;
 }
-''', [HintCode.DEAD_CODE]);
+''', [
+      error(HintCode.DEAD_CODE, 69, 1),
+    ]);
   }
 
   test_nullCoalesce_nullable() async {
@@ -675,7 +770,7 @@
   }
 
   test_nullCoalesceAssign_nonNullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 @pragma('analyzer:non-nullable')
 library foo;
 
@@ -683,7 +778,9 @@
   int x;
   x ??= 1;
 }
-''', [HintCode.DEAD_CODE]);
+''', [
+      error(HintCode.DEAD_CODE, 70, 1),
+    ]);
   }
 
   test_nullCoalesceAssign_nullable() async {
diff --git a/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
new file mode 100644
index 0000000..30e9267
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DefaultListConstructorMismatch);
+  });
+}
+
+@reflectiveTest
+class DefaultListConstructorMismatch extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_nonNullableType() async {
+    await assertErrorsInCode('''
+var l = new List<int>(3);
+''', [
+      error(CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR_MISMATCH, 12, 9),
+    ]);
+  }
+
+  test_nullableType() async {
+    await assertNoErrorsInCode('''
+var l = new List<String?>(3);
+''');
+  }
+
+  test_inferredType() async {
+    await assertErrorsInCode('''
+class C {}
+List<C> v = List(5);
+''', [
+      error(CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR_MISMATCH, 23, 4),
+    ]);
+  }
+
+  test_typeParameter() async {
+    await assertErrorsInCode('''
+class C<T> {
+  var l = new List<T>(3);
+}
+''', [
+      error(CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR_MISMATCH, 27, 7),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/default_value_on_required_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/default_value_on_required_parameter_test.dart
new file mode 100644
index 0000000..c8d20cd
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/default_value_on_required_parameter_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DefaultValueOnRequiredParameterTest);
+  });
+}
+
+@reflectiveTest
+class DefaultValueOnRequiredParameterTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_notRequired_default() async {
+    await assertNoErrorsInCode('''
+void log({String message: 'no message'}) {}
+''');
+  }
+
+  test_notRequired_noDefault() async {
+    await assertNoErrorsInCode('''
+void log({String? message}) {}
+''');
+  }
+
+  test_required_default() async {
+    await assertErrorsInCode('''
+void log({required String? message: 'no message'}) {}
+''', [
+      error(CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER, 27, 7),
+    ]);
+  }
+
+  test_required_noDefault() async {
+    await assertNoErrorsInCode('''
+void log({required String message}) {}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart b/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart
index 1ef1b7e..f0f3141 100644
--- a/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart
@@ -19,32 +19,40 @@
     await assertNoErrorsInCode(r'''
 f(int x, int y) {
   var v = x / y.toInt();
+  print(v);
 }
 ''');
   }
 
   test_double() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(double x, double y) {
   var v = (x / y).toInt();
+  print(v);
 }
-''', [HintCode.DIVISION_OPTIMIZATION]);
+''', [
+      error(HintCode.DIVISION_OPTIMIZATION, 34, 15),
+    ]);
   }
 
   test_dynamic() async {
     await assertNoErrorsInCode(r'''
 f(x, y) {
   var v = (x / y).toInt();
+  print(v);
 }
 ''');
   }
 
   test_int() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(int x, int y) {
   var v = (x / y).toInt();
+  print(v);
 }
-''', [HintCode.DIVISION_OPTIMIZATION]);
+''', [
+      error(HintCode.DIVISION_OPTIMIZATION, 28, 15),
+    ]);
   }
 
   test_nonNumeric() async {
@@ -54,15 +62,19 @@
 }
 f(A x, A y) {
   var v = (x / y).toInt();
+  print(v);
 }
 ''');
   }
 
   test_wrappedInParentheses() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(int x, int y) {
   var v = (((x / y))).toInt();
+  print(v);
 }
-''', [HintCode.DIVISION_OPTIMIZATION]);
+''', [
+      error(HintCode.DIVISION_OPTIMIZATION, 28, 19),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/equal_elements_in_const_set_test.dart b/pkg/analyzer/test/src/diagnostics/equal_elements_in_const_set_test.dart
index 91c8202f..61548d2 100644
--- a/pkg/analyzer/test/src/diagnostics/equal_elements_in_const_set_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/equal_elements_in_const_set_test.dart
@@ -12,27 +12,106 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(EqualElementsInConstSetTest);
-    defineReflectiveTests(EqualElementsInConstSetWithUIAsCodeAndConstantsTest);
-    defineReflectiveTests(EqualElementsInConstSetWithUIAsCodeTest);
+    defineReflectiveTests(EqualElementsInConstSetWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class EqualElementsInConstSetTest extends DriverResolutionTest {
   test_const_entry() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var c = const {1, 2, 1};
-''', [CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET]);
+''', [
+      error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 21, 1),
+    ]);
+  }
+
+  test_const_ifElement_thenElseFalse() async {
+    await assertErrorsInCode(
+        '''
+var c = const {1, if (1 < 0) 2 else 1};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 36, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenElseFalse_onlyElse() async {
+    await assertErrorsInCode(
+        '''
+var c = const {if (0 < 1) 1 else 1};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 15, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenElseTrue() async {
+    await assertErrorsInCode(
+        '''
+var c = const {1, if (0 < 1) 2 else 1};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenElseTrue_onlyThen() async {
+    await assertErrorsInCode(
+        '''
+var c = const {if (0 < 1) 1 else 1};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 15, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse() async {
+    await assertErrorsInCode(
+        '''
+var c = const {2, if (1 < 0) 2};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 12),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue() async {
+    await assertErrorsInCode(
+        '''
+var c = const {1, if (0 < 1) 1};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 29, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 12),
+              ]);
   }
 
   test_const_instanceCreation_equalTypeArgs() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<T> {
   const A();
 }
 
 var c = const {const A<int>(), const A<int>()};
-''', [CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET]);
+''', [
+      error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 60, 14),
+    ]);
   }
 
   test_const_instanceCreation_notEqualTypeArgs() async {
@@ -46,6 +125,32 @@
 ''');
   }
 
+  test_const_spread__noDuplicate() async {
+    await assertErrorsInCode(
+        '''
+var c = const {1, ...{2}};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 6),
+              ]);
+  }
+
+  test_const_spread_hasDuplicate() async {
+    await assertErrorsInCode(
+        '''
+var c = const {1, ...{1}};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 21, 3),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 6),
+              ]);
+  }
+
   test_nonConst_entry() async {
     await assertNoErrorsInCode('''
 var c = {1, 2, 1};
@@ -54,104 +159,9 @@
 }
 
 @reflectiveTest
-class EqualElementsInConstSetWithUIAsCodeAndConstantsTest
-    extends EqualElementsInConstSetWithUIAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class EqualElementsInConstSetWithUIAsCodeTest
+class EqualElementsInConstSetWithConstantsTest
     extends EqualElementsInConstSetTest {
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
-  test_const_ifElement_thenElseFalse() async {
-    await assertErrorCodesInCode(
-        '''
-var c = const {1, if (1 < 0) 2 else 1};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseFalse_onlyElse() async {
-    assertErrorCodesInCode(
-        '''
-var c = const {if (0 < 1) 1 else 1};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseTrue() async {
-    assertErrorCodesInCode(
-        '''
-var c = const {1, if (0 < 1) 2 else 1};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseTrue_onlyThen() async {
-    assertErrorCodesInCode(
-        '''
-var c = const {if (0 < 1) 1 else 1};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse() async {
-    assertErrorCodesInCode(
-        '''
-var c = const {2, if (1 < 0) 2};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue() async {
-    await assertErrorCodesInCode(
-        '''
-var c = const {1, if (0 < 1) 1};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_spread__noDuplicate() async {
-    await assertErrorCodesInCode(
-        '''
-var c = const {1, ...{2}};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_spread_hasDuplicate() async {
-    await assertErrorCodesInCode(
-        '''
-var c = const {1, ...{1}};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/equal_keys_in_const_map_test.dart b/pkg/analyzer/test/src/diagnostics/equal_keys_in_const_map_test.dart
index c4ff97b..590411c 100644
--- a/pkg/analyzer/test/src/diagnostics/equal_keys_in_const_map_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/equal_keys_in_const_map_test.dart
@@ -12,27 +12,106 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(EqualKeysInConstMapTest);
-    defineReflectiveTests(EqualKeysInConstMapWithUIAsCodeAndConstantsTest);
-    defineReflectiveTests(EqualKeysInConstMapWithUIAsCodeTest);
+    defineReflectiveTests(EqualKeysInConstMapWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class EqualKeysInConstMapTest extends DriverResolutionTest {
   test_const_entry() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var c = const {1: null, 2: null, 1: null};
-''', [CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP]);
+''', [
+      error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 33, 1),
+    ]);
+  }
+
+  test_const_ifElement_thenElseFalse() async {
+    await assertErrorsInCode(
+        '''
+var c = const {1: null, if (1 < 0) 2: null else 1: null};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 48, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 31),
+              ]);
+  }
+
+  test_const_ifElement_thenElseFalse_onlyElse() async {
+    await assertErrorsInCode(
+        '''
+var c = const {if (0 < 1) 1: null else 1: null};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 15, 31),
+              ]);
+  }
+
+  test_const_ifElement_thenElseTrue() async {
+    await assertErrorsInCode(
+        '''
+var c = const {1: null, if (0 < 1) 2: null else 1: null};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 31),
+              ]);
+  }
+
+  test_const_ifElement_thenElseTrue_onlyThen() async {
+    await assertErrorsInCode(
+        '''
+var c = const {if (0 < 1) 1: null else 1: null};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 15, 31),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse() async {
+    await assertErrorsInCode(
+        '''
+var c = const {2: null, if (1 < 0) 2: 2};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 15),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue() async {
+    await assertErrorsInCode(
+        '''
+var c = const {1: null, if (0 < 1) 1: null};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 35, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 18),
+              ]);
   }
 
   test_const_instanceCreation_equalTypeArgs() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<T> {
   const A();
 }
 
 var c = const {const A<int>(): null, const A<int>(): null};
-''', [CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP]);
+''', [
+      error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 66, 14),
+    ]);
   }
 
   test_const_instanceCreation_notEqualTypeArgs() async {
@@ -46,6 +125,32 @@
 ''');
   }
 
+  test_const_spread__noDuplicate() async {
+    await assertErrorsInCode(
+        '''
+var c = const {1: null, ...{2: null}};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 12),
+              ]);
+  }
+
+  test_const_spread_hasDuplicate() async {
+    await assertErrorsInCode(
+        '''
+var c = const {1: null, ...{1: null}};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 27, 9),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 12),
+              ]);
+  }
+
   test_nonConst_entry() async {
     await assertNoErrorsInCode('''
 var c = {1: null, 2: null, 1: null};
@@ -54,103 +159,8 @@
 }
 
 @reflectiveTest
-class EqualKeysInConstMapWithUIAsCodeAndConstantsTest
-    extends EqualKeysInConstMapWithUIAsCodeTest {
+class EqualKeysInConstMapWithConstantsTest extends EqualKeysInConstMapTest {
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class EqualKeysInConstMapWithUIAsCodeTest extends EqualKeysInConstMapTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
-  test_const_ifElement_thenElseFalse() async {
-    await assertErrorCodesInCode(
-        '''
-var c = const {1: null, if (1 < 0) 2: null else 1: null};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseFalse_onlyElse() async {
-    assertErrorCodesInCode(
-        '''
-var c = const {if (0 < 1) 1: null else 1: null};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseTrue() async {
-    assertErrorCodesInCode(
-        '''
-var c = const {1: null, if (0 < 1) 2: null else 1: null};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseTrue_onlyThen() async {
-    assertErrorCodesInCode(
-        '''
-var c = const {if (0 < 1) 1: null else 1: null};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse() async {
-    assertErrorCodesInCode(
-        '''
-var c = const {2: null, if (1 < 0) 2: 2};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue() async {
-    await assertErrorCodesInCode(
-        '''
-var c = const {1: null, if (0 < 1) 1: null};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_spread__noDuplicate() async {
-    await assertErrorCodesInCode(
-        '''
-var c = const {1: null, ...{2: null}};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_spread_hasDuplicate() async {
-    await assertErrorCodesInCode(
-        '''
-var c = const {1: null, ...{1: null}};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/expression_in_map_test.dart b/pkg/analyzer/test/src/diagnostics/expression_in_map_test.dart
index b53dea9..cc3ffe3 100644
--- a/pkg/analyzer/test/src/diagnostics/expression_in_map_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/expression_in_map_test.dart
@@ -2,10 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -13,7 +10,6 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ExpressionInMapTest);
-    defineReflectiveTests(ExpressionInMapWithUiAsCodeTest);
   });
 }
 
@@ -22,56 +18,18 @@
   bool get isUiAsCode => analysisOptions.experimentStatus.spread_collections;
 
   test_map() async {
-    await assertErrorCodesInCode(
-      '''
+    await assertErrorsInCode('''
 var m = <String, int>{'a', 'b' : 2};
-''',
-      isUiAsCode
-          ? [
-              CompileTimeErrorCode.EXPRESSION_IN_MAP,
-            ]
-          : [
-              ParserErrorCode.EXPECTED_TOKEN,
-              ParserErrorCode.MISSING_IDENTIFIER
-            ],
-    );
+''', [
+      error(CompileTimeErrorCode.EXPRESSION_IN_MAP, 22, 3),
+    ]);
   }
 
   test_map_const() async {
-    await assertErrorCodesInCode(
-      '''
-var m = <String, int>{'a', 'b' : 2};
-''',
-      isUiAsCode
-          ? [
-              CompileTimeErrorCode.EXPRESSION_IN_MAP,
-            ]
-          : [
-              ParserErrorCode.EXPECTED_TOKEN,
-              ParserErrorCode.MISSING_IDENTIFIER
-            ],
-    );
-  }
-}
-
-@reflectiveTest
-class ExpressionInMapWithUiAsCodeTest extends ExpressionInMapTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
-  test_map() async {
-    await assertErrorCodesInCode('''
-var m = <String, int>{'a', 'b' : 2};
-''', [CompileTimeErrorCode.EXPRESSION_IN_MAP]);
-  }
-
-  test_map_const() async {
-    await assertErrorCodesInCode('''
-var m = <String, int>{'a', 'b' : 2};
-''', [CompileTimeErrorCode.EXPRESSION_IN_MAP]);
+    await assertErrorsInCode('''
+const m = <String, int>{'a', 'b' : 2};
+''', [
+      error(CompileTimeErrorCode.EXPRESSION_IN_MAP, 24, 3),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart b/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart
new file mode 100644
index 0000000..1859d26
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+//    defineReflectiveTests(ExtendsNonClassTest);
+    defineReflectiveTests(ExtendsNonClassWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class ExtendsNonClassTest extends DriverResolutionTest {}
+
+@reflectiveTest
+class ExtendsNonClassWithNnbdTest extends ExtendsNonClassTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_Never() async {
+    await assertErrorsInCode('''
+class A extends Never {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 16, 5),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart b/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
new file mode 100644
index 0000000..28b987a
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2019, 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:analyzer/src/error/codes.dart';
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+//    defineReflectiveTests(FinalNotInitializedTest);
+    defineReflectiveTests(FinalNotInitializedWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class FinalNotInitializedTest extends DriverResolutionTest {}
+
+@reflectiveTest
+class FinalNotInitializedWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_field_noConstructor_initializer() {
+    assertNoErrorsInCode('''
+class C {
+  late final f = 1;
+}
+''');
+  }
+
+  test_field_noConstructor_noInitializer() {
+    assertNoErrorsInCode('''
+class C {
+  late final f;
+}
+''');
+  }
+
+  test_field_unnamedConstructor_constructorInitializer() {
+    assertNoErrorsInCode('''
+class C {
+  late final f;
+  C() : f = 2;
+}
+''');
+  }
+
+  test_field_unnamedConstructor_fieldFormalParameter() {
+    assertNoErrorsInCode('''
+class C {
+  late final f;
+  C(this.f);
+}
+''');
+  }
+
+  test_field_unnamedConstructor_initializer() {
+    assertNoErrorsInCode('''
+class C {
+  late final f = 1;
+  C();
+}
+''');
+  }
+
+  test_field_unnamedConstructor_noInitializer() {
+    assertNoErrorsInCode('''
+class C {
+  late final f;
+  C();
+}
+''');
+  }
+
+  test_localVariable_initializer() {
+    assertNoErrorsInCode('''
+f() {
+  late final x = 1;
+}
+''');
+  }
+
+  test_localVariable_noInitializer() {
+    assertNoErrorsInCode('''
+f() {
+  late final x;
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/implements_non_class_test.dart b/pkg/analyzer/test/src/diagnostics/implements_non_class_test.dart
new file mode 100644
index 0000000..176830e
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/implements_non_class_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+//    defineReflectiveTests(ImplementsNonClassTest);
+    defineReflectiveTests(ImplementsNonClassWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class ImplementsNonClassTest extends DriverResolutionTest {}
+
+@reflectiveTest
+class ImplementsNonClassWithNnbdTest extends ImplementsNonClassTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_Never() async {
+    await assertErrorsInCode('''
+class A implements Never {}
+''', [
+      error(CompileTimeErrorCode.IMPLEMENTS_NON_CLASS, 19, 5),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/implicit_this_reference_in_initializer_test.dart b/pkg/analyzer/test/src/diagnostics/implicit_this_reference_in_initializer_test.dart
new file mode 100644
index 0000000..8dc2f67
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/implicit_this_reference_in_initializer_test.dart
@@ -0,0 +1,229 @@
+// Copyright (c) 2019, 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ImplicitThisReferenceInInitializerTest);
+  });
+}
+
+@reflectiveTest
+class ImplicitThisReferenceInInitializerTest extends DriverResolutionTest {
+  test_implicitThisReferenceInInitializer_constructorName() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A.named() {}
+}
+class B {
+  var v;
+  B() : v = new A.named();
+}
+''');
+  }
+
+  test_implicitThisReferenceInInitializer_field() async {
+    await assertErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f;
+  var f;
+}
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 31, 1),
+    ]);
+  }
+
+  test_implicitThisReferenceInInitializer_field2() async {
+    await assertErrorsInCode(r'''
+class A {
+  final x = 0;
+  final y = x;
+}
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 37, 1),
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 37, 1),
+    ]);
+  }
+
+  test_implicitThisReferenceInInitializer_invocation() async {
+    await assertErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f();
+  f() {}
+}
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 31, 1),
+    ]);
+  }
+
+  test_implicitThisReferenceInInitializer_invocationInStatic() async {
+    await assertErrorsInCode(r'''
+class A {
+  static var F = m();
+  int m() => 0;
+}
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 27, 1),
+    ]);
+  }
+
+  test_implicitThisReferenceInInitializer_prefixedIdentifier() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var f;
+}
+class B {
+  var v;
+  B(A a) : v = a.f;
+}
+''');
+  }
+
+  test_implicitThisReferenceInInitializer_qualifiedMethodInvocation() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  f() {}
+}
+class B {
+  var v;
+  B() : v = new A().f();
+}
+''');
+  }
+
+  test_implicitThisReferenceInInitializer_qualifiedPropertyAccess() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var f;
+}
+class B {
+  var v;
+  B() : v = new A().f;
+}
+''');
+  }
+
+  test_implicitThisReferenceInInitializer_redirectingConstructorInvocation() async {
+    await assertErrorsInCode(r'''
+class A {
+  A(p) {}
+  A.named() : this(f);
+  var f;
+}
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 39, 1),
+    ]);
+  }
+
+  test_implicitThisReferenceInInitializer_staticField_thisClass() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f;
+  static var f;
+}
+''');
+  }
+
+  test_implicitThisReferenceInInitializer_staticGetter() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f;
+  static get f => 42;
+}
+''');
+  }
+
+  test_implicitThisReferenceInInitializer_staticMethod() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f();
+  static f() => 42;
+}
+''');
+  }
+
+  test_implicitThisReferenceInInitializer_superConstructorInvocation() async {
+    await assertErrorsInCode(r'''
+class A {
+  A(p) {}
+}
+class B extends A {
+  B() : super(f);
+  var f;
+}
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 56, 1),
+    ]);
+  }
+
+  test_implicitThisReferenceInInitializer_topLevelField() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f;
+}
+var f = 42;
+''');
+  }
+
+  test_implicitThisReferenceInInitializer_topLevelFunction() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f();
+}
+f() => 42;
+''');
+  }
+
+  test_implicitThisReferenceInInitializer_topLevelGetter() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f;
+}
+get f => 42;
+''');
+  }
+
+  test_implicitThisReferenceInInitializer_typeParameter() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  var v;
+  A(p) : v = (p is T);
+}
+''');
+  }
+
+  test_isInInstanceVariableInitializer_restored() async {
+    // If ErrorVerifier._isInInstanceVariableInitializer is not properly
+    // restored on exit from visitVariableDeclaration, the error at (1)
+    // won't be detected.
+    await assertErrorsInCode(r'''
+class Foo {
+  var bar;
+  Map foo = {
+    'bar': () {
+        var _bar;
+    },
+    'bop': _foo // (1)
+  };
+  _foo() {
+  }
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 65, 4),
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 89, 4),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
index 6e45cc9..cdba8f3 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
@@ -16,7 +16,7 @@
 @reflectiveTest
 class InvalidAssignmentTest extends DriverResolutionTest {
   test_instanceVariable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int x;
 }
@@ -26,17 +26,22 @@
     a.x = y;
   }
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 70, 1),
+    ]);
   }
 
   test_localVariable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(var y) {
   if (y is String) {
     int x = y;
+    print(x);
   }
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 44, 1),
+    ]);
   }
 
   test_promotedTypeParameter_regress35306() async {
@@ -58,7 +63,7 @@
   }
 
   test_staticVariable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   static int x;
 }
@@ -67,11 +72,13 @@
     A.x = y;
   }
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 70, 1),
+    ]);
   }
 
   test_typeParameterRecursion_regress35306() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 class B extends A {}
 class C extends D {}
@@ -80,14 +87,17 @@
 void f<X extends A, Y extends B>(X x) {
   if (x is Y) {
     D d = x;
+    print(d);
   }
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 131, 1),
+    ]);
   }
 
   test_variableDeclaration() async {
     // 17971
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class Point {
   final num x, y;
   Point(this.x, this.y);
@@ -99,7 +109,10 @@
   var p1 = new Point(0, 0);
   var p2 = new Point(10, 10);
   int n = p1 + p2;
+  print(n);
 }
-''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 218, 7),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart
index c60fc29..88a6917 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -16,12 +15,8 @@
 
 @reflectiveTest
 class InvalidCastNewExprTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions =>
-      AnalysisOptionsImpl()..enabledExperiments = ['set-literals'];
-
   test_listLiteral_const() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 const c = <B>[A()];
 class A {
   const A();
@@ -30,13 +25,13 @@
   const B();
 }
 ''', [
-      StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
-      StrongModeCode.INVALID_CAST_NEW_EXPR,
+      error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 14, 3),
+      error(StrongModeCode.INVALID_CAST_NEW_EXPR, 14, 3),
     ]);
   }
 
   test_listLiteral_nonConst() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 var c = <B>[A()];
 class A {
   const A();
@@ -44,11 +39,13 @@
 class B extends A {
   const B();
 }
-''', [StrongModeCode.INVALID_CAST_NEW_EXPR]);
+''', [
+      error(StrongModeCode.INVALID_CAST_NEW_EXPR, 12, 3),
+    ]);
   }
 
   test_setLiteral_const() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 const c = <B>{A()};
 class A {
   const A();
@@ -57,13 +54,13 @@
   const B();
 }
 ''', [
-      StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE,
-      StrongModeCode.INVALID_CAST_NEW_EXPR,
+      error(StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 14, 3),
+      error(StrongModeCode.INVALID_CAST_NEW_EXPR, 14, 3),
     ]);
   }
 
   test_setLiteral_nonConst() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 var c = <B>{A()};
 class A {
   const A();
@@ -71,6 +68,8 @@
 class B extends A {
   const B();
 }
-''', [StrongModeCode.INVALID_CAST_NEW_EXPR]);
+''', [
+      error(StrongModeCode.INVALID_CAST_NEW_EXPR, 12, 3),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_factory_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_factory_annotation_test.dart
index d692547..0011b60 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_factory_annotation_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_factory_annotation_test.dart
@@ -19,31 +19,37 @@
     with PackageMixin {
   test_class() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @factory
 class X {
 }
-''', [HintCode.INVALID_FACTORY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_FACTORY_ANNOTATION, 33, 8),
+    ]);
   }
 
   test_field() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class X {
   @factory
   int x;
 }
-''', [HintCode.INVALID_FACTORY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_FACTORY_ANNOTATION, 45, 8),
+    ]);
   }
 
   test_topLevelFunction() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @factory
 main() { }
-''', [HintCode.INVALID_FACTORY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_FACTORY_ANNOTATION, 33, 8),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_factory_method_impl_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_factory_method_impl_test.dart
index b685325..c11b9f2 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_factory_method_impl_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_factory_method_impl_test.dart
@@ -31,7 +31,7 @@
 
   test_badReturn() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class Stateful {
   State _s = new State();
@@ -40,7 +40,9 @@
   State createState() => _s;
 }
 class State { }
-''', [HintCode.INVALID_FACTORY_METHOD_IMPL]);
+''', [
+      error(HintCode.INVALID_FACTORY_METHOD_IMPL, 96, 11),
+    ]);
   }
 
   test_block() async {
@@ -131,13 +133,15 @@
 
   test_voidReturn() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 class Stateful {
   @factory
   void createState() {}
 }
-''', [HintCode.INVALID_FACTORY_METHOD_DECL]);
+''', [
+      error(HintCode.INVALID_FACTORY_METHOD_DECL, 69, 11),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_immutable_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_immutable_annotation_test.dart
index f494f73..86f3980 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_immutable_annotation_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_immutable_annotation_test.dart
@@ -30,12 +30,14 @@
 
   test_method() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   @immutable
   void m() {}
 }
-''', [HintCode.INVALID_IMMUTABLE_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_IMMUTABLE_ANNOTATION, 45, 10),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_literal_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_literal_annotation_test.dart
index 5a3c051..08262bc 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_literal_annotation_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_literal_annotation_test.dart
@@ -30,23 +30,27 @@
 
   test_nonConstConstructor() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   @literal
   A() {}
 }
-''', [HintCode.INVALID_LITERAL_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_LITERAL_ANNOTATION, 45, 8),
+    ]);
   }
 
   test_nonConstructor() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   @literal
   void m() {}
 }
-''', [HintCode.INVALID_LITERAL_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_LITERAL_ANNOTATION, 45, 8),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_optional_parameter_type_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_optional_parameter_type_test.dart
new file mode 100644
index 0000000..51ad294
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_optional_parameter_type_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MissingDefaultValueForParameterTest);
+  });
+}
+
+@reflectiveTest
+class MissingDefaultValueForParameterTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_typeParameter_potentiallyNonNullable_named_optional_noDefault() async {
+    await assertErrorsInCode('''
+class A<T extends Object?> {
+  void f({T a}) {}
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_OPTIONAL_PARAMETER_TYPE, 41, 1),
+    ]);
+  }
+
+  test_typeParameter_potentiallyNonNullable_positional_optional_noDefault() async {
+    await assertErrorsInCode('''
+class A<T extends Object?> {
+  void f([T a]) {}
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_OPTIONAL_PARAMETER_TYPE, 41, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart
index 867b204..017f646 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart
@@ -32,13 +32,16 @@
   }
 
   test_differentValues() async {
-    await _assertError(r'''
+    await assertErrorsInCode(r'''
 class A {
   m({x = 0}) {}
 }
 class B extends A {
   m({x = 1}) {}
-}''');
+}''', [
+      error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+          53, 5),
+    ]);
   }
 
   test_equal_values_generic_different_files() async {
@@ -58,7 +61,7 @@
   test_equal_values_generic_undefined_value_base() async {
     // Note: we expect some errors due to the constant referring to undefined
     // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   m({x = Undefined.value}) {}
 }
@@ -66,15 +69,15 @@
   m({x = 1}) {}
 }
 ''', [
-      CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE,
-      StaticWarningCode.UNDEFINED_IDENTIFIER
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 19, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 19, 9),
     ]);
   }
 
   test_equal_values_generic_undefined_value_both() async {
     // Note: we expect some errors due to the constant referring to undefined
     // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   m({x = Undefined.value}) {}
 }
@@ -82,17 +85,17 @@
   m({x = Undefined2.value2}) {}
 }
 ''', [
-      CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE,
-      CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE,
-      StaticWarningCode.UNDEFINED_IDENTIFIER,
-      StaticWarningCode.UNDEFINED_IDENTIFIER
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 19, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 19, 9),
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 71, 10),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 71, 10),
     ]);
   }
 
   test_equal_values_generic_undefined_value_derived() async {
     // Note: we expect some errors due to the constant referring to undefined
     // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   m({x = 1}) {}
 }
@@ -100,8 +103,8 @@
   m({x = Undefined.value}) {}
 }
 ''', [
-      CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE,
-      StaticWarningCode.UNDEFINED_IDENTIFIER
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 57, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 57, 9),
     ]);
   }
 
@@ -164,19 +167,16 @@
     // If the base class provided an explicit value for a default parameter,
     // then it is a static warning for the derived class to provide a different
     // value, even if implicitly.
-    await _assertError(r'''
+    await assertErrorsInCode(r'''
 class A {
   foo({x: 1}) {}
 }
 class B extends A {
   foo({x}) {}
 }
-''');
-  }
-
-  Future<void> _assertError(String code) async {
-    await assertErrorCodesInCode(code, [
-      StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+''', [
+      error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+          56, 1),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart
index d1421cb..07cfc59 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart
@@ -32,13 +32,19 @@
   }
 
   test_differentValues() async {
-    await _assertError(r'''
+    await assertErrorsInCode(r'''
 class A {
   m([x = 0]) {}
 }
 class B extends A {
   m([x = 1]) {}
-}''');
+}''', [
+      error(
+          StaticWarningCode
+              .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+          53,
+          5),
+    ]);
   }
 
   test_equal_values_generic_different_files() async {
@@ -58,7 +64,7 @@
   test_equal_values_generic_undefined_value_base() async {
     // Note: we expect some errors due to the constant referring to undefined
     // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   m([x = Undefined.value]) {}
 }
@@ -66,15 +72,15 @@
   m([x = 1]) {}
 }
 ''', [
-      CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE,
-      StaticWarningCode.UNDEFINED_IDENTIFIER
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 19, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 19, 9),
     ]);
   }
 
   test_equal_values_generic_undefined_value_both() async {
     // Note: we expect some errors due to the constant referring to undefined
     // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   m([x = Undefined.value]) {}
 }
@@ -82,17 +88,17 @@
   m([x = Undefined2.value2]) {}
 }
 ''', [
-      CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE,
-      CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE,
-      StaticWarningCode.UNDEFINED_IDENTIFIER,
-      StaticWarningCode.UNDEFINED_IDENTIFIER
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 19, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 19, 9),
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 71, 10),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 71, 10),
     ]);
   }
 
   test_equal_values_generic_undefined_value_derived() async {
     // Note: we expect some errors due to the constant referring to undefined
     // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   m([x = 1]) {}
 }
@@ -100,8 +106,8 @@
   m([x = Undefined.value]) {}
 }
 ''', [
-      CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE,
-      StaticWarningCode.UNDEFINED_IDENTIFIER
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 57, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 57, 9),
     ]);
   }
 
@@ -164,19 +170,19 @@
     // If the base class provided an explicit value for a default parameter,
     // then it is a static warning for the derived class to provide a different
     // value, even if implicitly.
-    await _assertError(r'''
+    await assertErrorsInCode(r'''
 class A {
   foo([x = 1]) {}
 }
 class B extends A {
   foo([x]) {}
 }
-''');
-  }
-
-  Future<void> _assertError(String code) async {
-    await assertErrorCodesInCode(code, [
-      StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+''', [
+      error(
+          StaticWarningCode
+              .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+          57,
+          1),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_required_param_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_required_param_test.dart
index 2194b85..739f3e5 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_required_param_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_required_param_test.dart
@@ -23,35 +23,43 @@
   }
 
   test_namedParameter_withDefault() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 m({@required a = 1}) => null;
-''', [HintCode.INVALID_REQUIRED_PARAM]);
+''', [
+      error(HintCode.INVALID_REQUIRED_PARAM, 37, 15),
+    ]);
   }
 
   test_positionalParameter_noDefault() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 m([@required a]) => null;
-''', [HintCode.INVALID_REQUIRED_PARAM]);
+''', [
+      error(HintCode.INVALID_REQUIRED_PARAM, 37, 11),
+    ]);
   }
 
   test_positionalParameter_withDefault() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 m([@required a = 1]) => null;
-''', [HintCode.INVALID_REQUIRED_PARAM]);
+''', [
+      error(HintCode.INVALID_REQUIRED_PARAM, 37, 15),
+    ]);
   }
 
   test_requiredParameter() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 m(@required a) => null;
-''', [HintCode.INVALID_REQUIRED_PARAM]);
+''', [
+      error(HintCode.INVALID_REQUIRED_PARAM, 36, 11),
+    ]);
   }
 
   test_valid() async {
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_sealed_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_sealed_annotation_test.dart
index 428a164..62dd3d0 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_sealed_annotation_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_sealed_annotation_test.dart
@@ -31,11 +31,13 @@
   }
 
   test_mixin() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 @sealed mixin M {}
-''', [HintCode.INVALID_SEALED_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_SEALED_ANNOTATION, 34, 7),
+    ]);
   }
 
   test_mixinApplication() async {
@@ -51,10 +53,12 @@
   }
 
   test_nonClass() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 @sealed m({a = 1}) => null;
-''', [HintCode.INVALID_SEALED_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_SEALED_ANNOTATION, 34, 7),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_visibility_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_visibility_annotation_test.dart
index b9523f5..b827bcc 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_visibility_annotation_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_visibility_annotation_test.dart
@@ -24,23 +24,28 @@
   }
 
   test_fields_multipleMixed() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class C {
   @visibleForTesting int _a, b;
 }
-''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 45, 18),
+      error(HintCode.UNUSED_FIELD, 68, 2),
+    ]);
   }
 
   test_fields_multiplePrivate() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class C {
   @visibleForTesting int _a, _b;
 }
 ''', [
-      HintCode.INVALID_VISIBILITY_ANNOTATION,
-      HintCode.INVALID_VISIBILITY_ANNOTATION
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 45, 18),
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 45, 18),
+      error(HintCode.UNUSED_FIELD, 68, 2),
+      error(HintCode.UNUSED_FIELD, 72, 2),
     ]);
   }
 
@@ -54,88 +59,119 @@
   }
 
   test_privateClass() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @visibleForTesting class _C {}
-''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 33, 18),
+      error(HintCode.UNUSED_ELEMENT, 58, 2),
+    ]);
   }
 
   test_privateConstructor() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class C {
   @visibleForTesting C._() {}
 }
-''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 45, 18),
+    ]);
   }
 
   test_privateEnum() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @visibleForTesting enum _E {a, b, c}
-''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 33, 18),
+      error(HintCode.UNUSED_ELEMENT, 57, 2),
+    ]);
   }
 
   test_privateField() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class C {
   @visibleForTesting int _a;
 }
-''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 45, 18),
+      error(HintCode.UNUSED_FIELD, 68, 2),
+    ]);
   }
 
   test_privateMethod() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class C {
   @visibleForTesting void _m() {}
 }
-''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 45, 18),
+      error(HintCode.UNUSED_ELEMENT, 69, 2),
+    ]);
   }
 
   test_privateMixin() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @visibleForTesting mixin _M {}
-''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 33, 18),
+      error(HintCode.UNUSED_ELEMENT, 58, 2),
+    ]);
   }
 
   test_privateTopLevelFunction() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @visibleForTesting void _f() {}
-''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 33, 18),
+      error(HintCode.UNUSED_ELEMENT, 57, 2),
+    ]);
   }
 
   test_privateTopLevelVariable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @visibleForTesting final _a = 1;
-''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 33, 18),
+      error(HintCode.UNUSED_ELEMENT, 58, 2),
+    ]);
   }
 
   test_privateTypedef() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @visibleForTesting typedef _T = Function();
-''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 33, 18),
+      error(HintCode.UNUSED_ELEMENT, 60, 2),
+    ]);
   }
 
   test_topLevelVariable_multipleMixed() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @visibleForTesting final _a = 1, b = 2;
-''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+''', [
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 33, 18),
+      error(HintCode.UNUSED_ELEMENT, 58, 2),
+    ]);
   }
 
   test_topLevelVariable_multiplePrivate() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @visibleForTesting final _a = 1, _b = 2;
 ''', [
-      HintCode.INVALID_VISIBILITY_ANNOTATION,
-      HintCode.INVALID_VISIBILITY_ANNOTATION
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 33, 18),
+      error(HintCode.INVALID_VISIBILITY_ANNOTATION, 33, 18),
+      error(HintCode.UNUSED_ELEMENT, 58, 2),
+      error(HintCode.UNUSED_ELEMENT, 66, 2),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
index 65a09dc..6026a10 100644
--- a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
@@ -12,25 +12,129 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ListElementTypeNotAssignableTest);
-    defineReflectiveTests(
-        ListElementTypeNotAssignableWithUIAsCodeAndConstantsTest);
-    defineReflectiveTests(ListElementTypeNotAssignableWithUIAsCodeTest);
+    defineReflectiveTests(ListElementTypeNotAssignableWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class ListElementTypeNotAssignableTest extends DriverResolutionTest {
+  test_const_ifElement_thenElseFalse_intInt() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <int>[if (1 < 0) a else b];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 62, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenElseFalse_intString() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <int>[if (1 < 0) a else b];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(
+                    StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 82, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 64, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_intString() async {
+    await assertErrorsInCode(
+        '''
+var v = const <int>[if (1 < 0) 'a'];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(
+                    StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 31, 3),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 20, 14),
+                error(
+                    StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 31, 3),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_intString_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 'a';
+var v = const <int>[if (1 < 0) a];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 43, 12),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_intInt() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+var v = const <int>[if (true) a];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 41, 11),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_intString() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 'a';
+var v = const <int>[if (true) a];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(
+                    StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 53, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 43, 11),
+              ]);
+  }
+
+  test_const_spread_intInt() async {
+    await assertErrorsInCode(
+        '''
+var v = const <int>[...[0, 1]];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 20, 9),
+              ]);
+  }
+
   test_const_stringInt() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <String>[42];
-''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 23, 2),
+    ]);
   }
 
   test_const_stringInt_dynamic() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const dynamic x = 42;
 var v = const <String>[x];
-''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 45, 1),
+    ]);
   }
 
   test_const_stringNull() async {
@@ -52,128 +156,6 @@
 ''');
   }
 
-  test_nonConst_stringInt() async {
-    await assertErrorCodesInCode('''
-var v = <String>[42];
-''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
-  }
-
-  test_nonConst_stringInt_dynamic() async {
-    await assertNoErrorsInCode('''
-const dynamic x = 42;
-var v = <String>[x];
-''');
-  }
-
-  test_nonConst_voidInt() async {
-    await assertNoErrorsInCode('''
-var v = <void>[42];
-''');
-  }
-}
-
-@reflectiveTest
-class ListElementTypeNotAssignableWithUIAsCodeAndConstantsTest
-    extends ListElementTypeNotAssignableWithUIAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class ListElementTypeNotAssignableWithUIAsCodeTest
-    extends ListElementTypeNotAssignableTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
-  test_const_ifElement_thenElseFalse_intInt() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-const dynamic b = 0;
-var v = const <int>[if (1 < 0) a else b];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseFalse_intString() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-const dynamic b = 'b';
-var v = const <int>[if (1 < 0) a else b];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_intString() async {
-    await assertErrorCodesInCode(
-        '''
-var v = const <int>[if (1 < 0) 'a'];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]
-            : [
-                StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
-                CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT
-              ]);
-  }
-
-  test_const_ifElement_thenFalse_intString_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 'a';
-var v = const <int>[if (1 < 0) a];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_intInt() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-var v = const <int>[if (true) a];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_intString() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 'a';
-var v = const <int>[if (true) a];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_spread_intInt() async {
-    await assertErrorCodesInCode(
-        '''
-var v = const <int>[...[0, 1]];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
   test_nonConst_ifElement_thenElseFalse_intDynamic() async {
     await assertNoErrorsInCode('''
 const dynamic a = 'a';
@@ -191,9 +173,11 @@
   }
 
   test_nonConst_ifElement_thenFalse_intString() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <int>[if (1 < 0) 'a'];
-''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 25, 3),
+    ]);
   }
 
   test_nonConst_ifElement_thenTrue_intDynamic() async {
@@ -215,4 +199,33 @@
 var v = <int>[...[0, 1]];
 ''');
   }
+
+  test_nonConst_stringInt() async {
+    await assertErrorsInCode('''
+var v = <String>[42];
+''', [
+      error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 17, 2),
+    ]);
+  }
+
+  test_nonConst_stringInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic x = 42;
+var v = <String>[x];
+''');
+  }
+
+  test_nonConst_voidInt() async {
+    await assertNoErrorsInCode('''
+var v = <void>[42];
+''');
+  }
+}
+
+@reflectiveTest
+class ListElementTypeNotAssignableWithConstantsTest
+    extends ListElementTypeNotAssignableTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart b/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
index 782e3e7..3a1725e 100644
--- a/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
@@ -2,10 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -13,53 +10,24 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapEntryNotInMapTest);
-    defineReflectiveTests(MapEntryNotInMapWithUiAsCodeTest);
   });
 }
 
 @reflectiveTest
 class MapEntryNotInMapTest extends DriverResolutionTest {
-  bool get isUiAsCode => analysisOptions.experimentStatus.spread_collections;
-
   test_set() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var c = <int>{1:2};
 ''', [
-      isUiAsCode
-          ? CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP
-          : ParserErrorCode.UNEXPECTED_TOKEN
+      error(CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP, 14, 3),
     ]);
   }
 
   test_set_const() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var c = const <int>{1:2};
 ''', [
-      isUiAsCode
-          ? CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP
-          : ParserErrorCode.UNEXPECTED_TOKEN
+      error(CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP, 20, 3),
     ]);
   }
 }
-
-@reflectiveTest
-class MapEntryNotInMapWithUiAsCodeTest extends MapEntryNotInMapTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
-  test_set() async {
-    await assertErrorCodesInCode('''
-var c = <int>{1:2};
-''', [CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP]);
-  }
-
-  test_set_const() async {
-    await assertErrorCodesInCode('''
-var c = const <int>{1:2};
-''', [CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP]);
-  }
-}
diff --git a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
index e629629..949841c 100644
--- a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
@@ -12,13 +12,113 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapKeyTypeNotAssignableTest);
-    defineReflectiveTests(MapKeyTypeNotAssignableWithUIAsCodeAndConstantsTest);
-    defineReflectiveTests(MapKeyTypeNotAssignableWithUIAsCodeTest);
+    defineReflectiveTests(MapKeyTypeNotAssignableWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class MapKeyTypeNotAssignableTest extends DriverResolutionTest {
+  test_const_ifElement_thenElseFalse_intInt_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <int, bool>{if (1 < 0) a: true else b: false};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 68, 32),
+              ]);
+  }
+
+  test_const_ifElement_thenElseFalse_intString_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <int, bool>{if (1 < 0) a: true else b: false};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 94, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 70, 32),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_intString_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 'a';
+var v = const <int, bool>{if (1 < 0) a: true};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 18),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_intString_value() async {
+    await assertErrorsInCode(
+        '''
+var v = const <int, bool>{if (1 < 0) 'a': true};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 37, 3),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 20),
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 37, 3),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_intInt_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+var v = const <int, bool>{if (true) a: true};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 17),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_intString_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 'a';
+var v = const <int, bool>{if (true) a: true};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 59, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 17),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_notConst() async {
+    await assertErrorsInCode(
+        '''
+final a = 0;
+var v = const <int, bool>{if (1 < 2) a: true};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 50, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 39, 18),
+              ]);
+  }
+
   test_const_intInt_dynamic() async {
     await assertNoErrorsInCode('''
 const dynamic a = 0;
@@ -27,163 +127,47 @@
   }
 
   test_const_intString_dynamic() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const dynamic a = 'a';
 var v = const <int, bool>{a : true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 49, 1),
+    ]);
   }
 
   test_const_intString_value() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <int, bool>{'a' : true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
-  }
-
-  test_nonConst_intInt_dynamic() async {
-    await assertNoErrorsInCode('''
-const dynamic a = 0;
-var v = <int, bool>{a : true};
-''');
-  }
-
-  test_nonConst_intString_dynamic() async {
-    await assertNoErrorsInCode('''
-const dynamic a = 'a';
-var v = <int, bool>{a : true};
-''');
-  }
-
-  test_nonConst_intString_value() async {
-    await assertErrorCodesInCode('''
-var v = <int, bool>{'a' : true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
-  }
-}
-
-@reflectiveTest
-class MapKeyTypeNotAssignableWithUIAsCodeAndConstantsTest
-    extends MapKeyTypeNotAssignableWithUIAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class MapKeyTypeNotAssignableWithUIAsCodeTest
-    extends MapKeyTypeNotAssignableTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
-  test_const_ifElement_thenElseFalse_intInt_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-const dynamic b = 0;
-var v = const <int, bool>{if (1 < 0) a: true else b: false};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseFalse_intString_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-const dynamic b = 'b';
-var v = const <int, bool>{if (1 < 0) a: true else b: false};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_intString_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 'a';
-var v = const <int, bool>{if (1 < 0) a: true};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_intString_value() async {
-    await assertErrorCodesInCode(
-        '''
-var v = const <int, bool>{if (1 < 0) 'a': true};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
-            : [
-                StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
-                CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
-              ]);
-  }
-
-  test_const_ifElement_thenTrue_intInt_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-var v = const <int, bool>{if (true) a: true};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_intString_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 'a';
-var v = const <int, bool>{if (true) a: true};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_notConst() async {
-    await assertErrorCodesInCode(
-        '''
-final a = 0;
-var v = const <int, bool>{if (1 < 2) a: true};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+''', [
+      error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 26, 3),
+    ]);
   }
 
   test_const_spread_intInt() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 var v = const <int, String>{...{1: 'a'}};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 28, 11),
+              ]);
   }
 
   test_const_spread_intString_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 'a';
 var v = const <int, String>{...{a: 'a'}};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
+            ? [
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 55, 1),
+              ]
             : [
-                StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
-                CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 51, 11),
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 55, 1),
               ]);
   }
 
@@ -204,9 +188,11 @@
   }
 
   test_nonConst_ifElement_thenFalse_intString_value() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <int, bool>{if (1 < 0) 'a': true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 31, 3),
+    ]);
   }
 
   test_nonConst_ifElement_thenTrue_intInt_dynamic() async {
@@ -223,6 +209,28 @@
 ''');
   }
 
+  test_nonConst_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <int, bool>{a : true};
+''');
+  }
+
+  test_nonConst_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <int, bool>{a : true};
+''');
+  }
+
+  test_nonConst_intString_value() async {
+    await assertErrorsInCode('''
+var v = <int, bool>{'a' : true};
+''', [
+      error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 20, 3),
+    ]);
+  }
+
   test_nonConst_spread_intInt() async {
     await assertNoErrorsInCode('''
 var v = <int, String>{...{1: 'a'}};
@@ -236,9 +244,11 @@
   }
 
   test_nonConst_spread_intString() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <int, String>{...{'a': 'a'}};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 26, 3),
+    ]);
   }
 
   test_nonConst_spread_intString_dynamic() async {
@@ -248,3 +258,11 @@
 ''');
   }
 }
+
+@reflectiveTest
+class MapKeyTypeNotAssignableWithConstantsTest
+    extends MapKeyTypeNotAssignableTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
+}
diff --git a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
index c5e15e3..86a5746 100644
--- a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
@@ -12,14 +12,113 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapValueTypeNotAssignableTest);
-    defineReflectiveTests(
-        MapValueTypeNotAssignableWithUIAsCodeAndConstantsTest);
-    defineReflectiveTests(MapValueTypeNotAssignableWithUIAsCodeTest);
+    defineReflectiveTests(MapValueTypeNotAssignableWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class MapValueTypeNotAssignableTest extends DriverResolutionTest {
+  test_const_ifElement_thenElseFalse_intInt_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <bool, int>{if (1 < 0) true: a else false: b};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 68, 32),
+              ]);
+  }
+
+  test_const_ifElement_thenElseFalse_intString_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <bool, int>{if (1 < 0) true: a else false: b};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 101, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 70, 32),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_intString_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 'a';
+var v = const <bool, int>{if (1 < 0) true: a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 18),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_intString_value() async {
+    await assertErrorsInCode(
+        '''
+var v = const <bool, int>{if (1 < 0) true: 'a'};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 43, 3),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 20),
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 43, 3),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_intInt_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+var v = const <bool, int>{if (true) true: a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 17),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_intString_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 'a';
+var v = const <bool, int>{if (true) true: a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 65, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 17),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_notConst() async {
+    await assertErrorsInCode(
+        '''
+final a = 0;
+var v = const <bool, int>{if (1 < 2) true: a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 56, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 39, 18),
+              ]);
+  }
+
   test_const_intInt_dynamic() async {
     await assertNoErrorsInCode('''
 const dynamic a = 0;
@@ -28,162 +127,47 @@
   }
 
   test_const_intString_dynamic() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const dynamic a = 'a';
 var v = const <bool, int>{true: a};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 55, 1),
+    ]);
   }
 
   test_const_intString_value() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <bool, int>{true: 'a'};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
-  }
-
-  test_nonConst_intInt_dynamic() async {
-    await assertNoErrorsInCode('''
-const dynamic a = 0;
-var v = <bool, int>{true: a};
-''');
-  }
-
-  test_nonConst_intString_dynamic() async {
-    await assertNoErrorsInCode('''
-const dynamic a = 'a';
-var v = <bool, int>{true: a};
-''');
-  }
-
-  test_nonConst_intString_value() async {
-    await assertErrorCodesInCode('''
-var v = <bool, int>{true: 'a'};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
-  }
-}
-
-@reflectiveTest
-class MapValueTypeNotAssignableWithUIAsCodeAndConstantsTest
-    extends MapValueTypeNotAssignableWithUIAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-}
-
-@reflectiveTest
-class MapValueTypeNotAssignableWithUIAsCodeTest
-    extends MapValueTypeNotAssignableTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
-  test_const_ifElement_thenElseFalse_intInt_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-const dynamic b = 0;
-var v = const <bool, int>{if (1 < 0) true: a else false: b};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseFalse_intString_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-const dynamic b = 'b';
-var v = const <bool, int>{if (1 < 0) true: a else false: b};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_intString_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 'a';
-var v = const <bool, int>{if (1 < 0) true: a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_intString_value() async {
-    await assertErrorCodesInCode(
-        '''
-var v = const <bool, int>{if (1 < 0) true: 'a'};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
-            : [
-                StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
-                CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
-              ]);
-  }
-
-  test_const_ifElement_thenTrue_intInt_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-var v = const <bool, int>{if (true) true: a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_intString_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 'a';
-var v = const <bool, int>{if (true) true: a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_notConst() async {
-    await assertErrorCodesInCode(
-        '''
-final a = 0;
-var v = const <bool, int>{if (1 < 2) true: a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 32, 3),
+    ]);
   }
 
   test_const_spread_intInt() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 var v = const <bool, int>{...{true: 1}};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 12),
+              ]);
   }
 
   test_const_spread_intString_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 'a';
 var v = const <bool, int>{...{true: a}};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
+            ? [
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 59, 1),
+              ]
             : [
-                StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
-                CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 12),
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 59, 1),
               ]);
   }
 
@@ -204,9 +188,11 @@
   }
 
   test_nonConst_ifElement_thenFalse_intString_value() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <bool, int>{if (1 < 0) true: 'a'};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 37, 3),
+    ]);
   }
 
   test_nonConst_ifElement_thenTrue_intInt_dynamic() async {
@@ -223,6 +209,28 @@
 ''');
   }
 
+  test_nonConst_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <bool, int>{true: a};
+''');
+  }
+
+  test_nonConst_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <bool, int>{true: a};
+''');
+  }
+
+  test_nonConst_intString_value() async {
+    await assertErrorsInCode('''
+var v = <bool, int>{true: 'a'};
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 26, 3),
+    ]);
+  }
+
   test_nonConst_spread_intInt() async {
     await assertNoErrorsInCode('''
 var v = <bool, int>{...{true: 1}};
@@ -236,9 +244,11 @@
   }
 
   test_nonConst_spread_intString() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <bool, int>{...{true: 'a'}};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 30, 3),
+    ]);
   }
 
   test_nonConst_spread_intString_dynamic() async {
@@ -248,3 +258,11 @@
 ''');
   }
 }
+
+@reflectiveTest
+class MapValueTypeNotAssignableWithConstantsTest
+    extends MapValueTypeNotAssignableTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
+}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
new file mode 100644
index 0000000..b18a85e
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
@@ -0,0 +1,191 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MissingDefaultValueForParameterTest);
+  });
+}
+
+@reflectiveTest
+class MissingDefaultValueForParameterTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_class_nonNullable_named_optional_default() async {
+    await assertNoErrorsInCode('''
+void f({int a = 0}) {}
+''');
+  }
+
+  test_class_nonNullable_named_optional_noDefault() async {
+    await assertErrorsInCode('''
+void f({int a}) {}
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 12, 1),
+    ]);
+  }
+
+  test_class_nonNullable_named_required() async {
+    await assertNoErrorsInCode('''
+void f({required int a}) {}
+''');
+  }
+
+  test_class_nonNullable_positional_optional_default() async {
+    await assertNoErrorsInCode('''
+void f([int a = 0]) {}
+''');
+  }
+
+  test_class_nonNullable_positional_optional_noDefault() async {
+    await assertErrorsInCode('''
+void f([int a]) {}
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 12, 1),
+    ]);
+  }
+
+  test_class_nonNullable_positional_required() async {
+    await assertNoErrorsInCode('''
+void f(int a) {}
+''');
+  }
+
+  test_class_nullable_named_optional_default() async {
+    await assertNoErrorsInCode('''
+void f({int? a = 0}) {}
+''');
+  }
+
+  test_class_nullable_named_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+void f({int? a}) {}
+''');
+  }
+
+  test_class_nullable_named_required() async {
+    await assertNoErrorsInCode('''
+void f({required int? a}) {}
+''');
+  }
+
+  test_class_nullable_positional_optional_default() async {
+    await assertNoErrorsInCode('''
+void f([int? a = 0]) {}
+''');
+  }
+
+  test_class_nullable_positional_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+void f([int? a]) {}
+''');
+  }
+
+  test_class_nullable_positional_required() async {
+    await assertNoErrorsInCode('''
+void f(int? a) {}
+''');
+  }
+
+  test_fieldFormalParameter() async {
+    await assertNoErrorsInCode('''
+class A {
+  final log;
+  A(void this.log({String s})) {}
+}
+''');
+  }
+
+  test_functionTypeAlias() async {
+    await assertNoErrorsInCode('''
+typedef void log({String});
+''');
+  }
+
+  test_functionTypedParameter() async {
+    await assertNoErrorsInCode('''
+void printToLog(void log({String})) {}
+''');
+  }
+
+  test_genericFunctionType() async {
+    await assertNoErrorsInCode('''
+void Function({String s}) log;
+''');
+  }
+
+  test_typeParameter_nullable_named_optional_default() async {
+    await assertNoErrorsInCode('''
+class A<T extends Object?> {
+  void f({T? a = null}) {}
+}
+''');
+  }
+
+  test_typeParameter_nullable_named_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+class A<T extends Object?> {
+  void f({T? a}) {}
+}
+''');
+  }
+
+  test_typeParameter_nullable_named_required() async {
+    await assertNoErrorsInCode('''
+class A<T extends Object?> {
+  void f({required T? a}) {}
+}
+''');
+  }
+
+  test_typeParameter_nullable_positional_optional_default() async {
+    await assertNoErrorsInCode('''
+class A<T extends Object?> {
+  void f([T? a = null]) {}
+}
+''');
+  }
+
+  test_typeParameter_nullable_positional_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+class A<T extends Object?> {
+  void f([T? a]) {}
+}
+''');
+  }
+
+  test_typeParameter_nullable_positional_required() async {
+    await assertNoErrorsInCode('''
+class A<T extends Object?> {
+  void f(T? a) {}
+}
+''');
+  }
+
+  test_typeParameter_potentiallyNonNullable_named_required() async {
+    await assertNoErrorsInCode('''
+class A<T extends Object?> {
+  void f({required T a}) {}
+}
+''');
+  }
+
+  test_typeParameter_potentiallyNonNullable_positional_required() async {
+    await assertNoErrorsInCode('''
+class A<T extends Object?> {
+  void f(T a) {}
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart b/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
index 99866a3..fa860a6 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
@@ -2,7 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/test_utilities/package_mixin.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -11,6 +13,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MissingRequiredParamTest);
+    defineReflectiveTests(MissingRequiredParamWithNnbdTest);
   });
 }
 
@@ -33,7 +36,7 @@
 
   test_constructorParam_missingArgument() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class C {
   C({@Required('must specify an `a`') int a}) {}
@@ -41,12 +44,14 @@
 main() {
   new C();
 }
-''', [HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS]);
+''', [
+      error(HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS, 109, 1),
+    ]);
   }
 
   test_constructorParam_noReason() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 class C {
@@ -56,12 +61,14 @@
 main() {
   new C();
 }
-''', [HintCode.MISSING_REQUIRED_PARAM]);
+''', [
+      error(HintCode.MISSING_REQUIRED_PARAM, 88, 1),
+    ]);
   }
 
   test_constructorParam_nullReason() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 class C {
@@ -71,23 +78,44 @@
 main() {
   new C();
 }
-''', [HintCode.MISSING_REQUIRED_PARAM]);
+''', [
+      error(HintCode.MISSING_REQUIRED_PARAM, 94, 1),
+    ]);
   }
 
   test_constructorParam_redirectingConstructorCall() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class C {
   C({@required int x});
   C.named() : this();
 }
-''', [HintCode.MISSING_REQUIRED_PARAM]);
+''', [
+      error(HintCode.MISSING_REQUIRED_PARAM, 81, 6),
+    ]);
+  }
+
+  test_constructorParam_superCall() async {
+    addMetaPackage();
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  C({@Required('must specify an `a`') int a}) {}
+}
+
+class D extends C {
+  D() : super();
+}
+''', [
+      error(HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS, 124, 7),
+    ]);
   }
 
   test_functionParam() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 void f({@Required('must specify an `a`') int a}) {}
@@ -95,12 +123,14 @@
 main() {
   f();
 }
-''', [HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS]);
+''', [
+      error(HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS, 98, 1),
+    ]);
   }
 
   test_methodParam() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   void m({@Required('must specify an `a`') int a}) {}
@@ -108,7 +138,9 @@
 f() {
   new A().m();
 }
-''', [HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS]);
+''', [
+      error(HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS, 115, 1),
+    ]);
   }
 
   test_methodParam_inOtherLib() async {
@@ -132,24 +164,9 @@
     assertTestErrorsWithCodes([HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS]);
   }
 
-  test_requiredConstructor_paramSuperCall() async {
-    addMetaPackage();
-    await assertErrorCodesInCode(r'''
-import 'package:meta/meta.dart';
-
-class C {
-  C({@Required('must specify an `a`') int a}) {}
-}
-
-class D extends C {
-  D() : super();
-}
-''', [HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS]);
-  }
-
   test_typedef_functionParam() async {
     addMetaPackage();
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 
 String test(C c) => c.m()();
@@ -159,7 +176,9 @@
 class C {
   F m() => ({@required String x}) => null;
 }
-''', [HintCode.MISSING_REQUIRED_PARAM]);
+''', [
+      error(HintCode.MISSING_REQUIRED_PARAM, 54, 7),
+    ]);
   }
 
   /// Resolve the test file at [path].
@@ -169,3 +188,127 @@
     result = await resolveFile(convertPath(path));
   }
 }
+
+@reflectiveTest
+class MissingRequiredParamWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_constructorParam_argumentGiven() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C({required int a}) {}
+}
+
+main() {
+  new C(a: 2);
+}
+''');
+  }
+
+  test_constructorParam_missingArgument() async {
+    await assertErrorsInCode(r'''
+class C {
+  C({required int a}) {}
+}
+main() {
+  new C();
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 52, 1),
+    ]);
+  }
+
+  test_constructorParam_redirectingConstructorCall() async {
+    await assertErrorsInCode(r'''
+class C {
+  C({required int x});
+  C.named() : this();
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 47, 6),
+    ]);
+  }
+
+  test_constructorParam_superCall() async {
+    await assertErrorsInCode(r'''
+class C {
+  C({required int a}) {}
+}
+
+class D extends C {
+  D() : super();
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 66, 7),
+    ]);
+  }
+
+  test_functionInvocation() async {
+    await assertErrorsInCode(r'''
+void Function({required int a}) f() => throw '';
+g() {
+  f()();
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 57, 5),
+    ]);
+  }
+
+  test_functionParam() async {
+    await assertErrorsInCode(r'''
+void f({required int a}) {}
+
+main() {
+  f();
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 40, 1),
+    ]);
+  }
+
+  test_methodParam() async {
+    await assertErrorsInCode(r'''
+class A {
+  void m({required int a}) {}
+}
+f() {
+  new A().m();
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 58, 1),
+    ]);
+  }
+
+  test_methodParam_inOtherLib() async {
+    newFile('/test/lib/a_lib.dart', content: r'''
+class A {
+  void m({required int a}) {}
+}
+''');
+    await assertErrorsInCode(r'''
+import "a_lib.dart";
+f() {
+  new A().m();
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 37, 1),
+    ]);
+  }
+
+  test_typedef_functionParam() async {
+    await assertErrorsInCode(r'''
+String test(C c) => c.m()();
+
+typedef String F({required String x});
+
+class C {
+  F m() => ({required String x}) => throw '';
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 20, 7),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_return_test.dart b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
index 41042fb..56a4de8 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
@@ -32,10 +32,12 @@
   }
 
   test_async() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'dart:async';
 Future<int> f() async {}
-''', [HintCode.MISSING_RETURN]);
+''', [
+      error(HintCode.MISSING_RETURN, 21, 11),
+    ]);
   }
 
   test_async_futureOrVoid() async {
@@ -66,35 +68,139 @@
   }
 
   test_factory() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   factory A() {}
 }
-''', [HintCode.MISSING_RETURN]);
+''', [
+      error(HintCode.MISSING_RETURN, 12, 14),
+    ]);
   }
 
   test_function() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 int f() {}
-''', [HintCode.MISSING_RETURN]);
+''', [
+      error(HintCode.MISSING_RETURN, 0, 3),
+    ]);
+  }
+
+  test_functionExpression_declared() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  f() {} // no hint
+}
+''');
+  }
+
+  test_functionExpression_expression() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  int Function() f = () => null; // no hint
+}
+''');
+  }
+
+  test_functionExpression_futureOrDynamic() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:async';
+main() {
+  FutureOr<dynamic> Function() f = () { print(42); };
+}
+''');
+  }
+
+  test_functionExpression_futureOrInt() async {
+    await assertErrorsInCode(r'''
+import 'dart:async';
+main() {
+  FutureOr<int> Function() f = () { print(42); };
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 57, 1),
+      error(HintCode.MISSING_RETURN, 61, 17),
+    ]);
+  }
+
+  test_functionExpression_inferred() async {
+    await assertErrorsInCode(r'''
+main() {
+  int Function() f = () { print(42); };
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 26, 1),
+      error(HintCode.MISSING_RETURN, 30, 17),
+    ]);
+  }
+
+  test_functionExpression_inferred_dynamic() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  Function() f = () { print(42); }; // no hint
+}
+''');
+  }
+
+  test_functionExpressionAsync_inferred() async {
+    await assertErrorsInCode(r'''
+main() {
+  Future<int> Function() f = () async { print(42); }; 
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 34, 1),
+      error(HintCode.MISSING_RETURN, 38, 23),
+    ]);
+  }
+
+  test_functionExpressionAsync_inferred_dynamic() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  Future Function() f = () async { print(42); }; // no hint
+}
+''');
   }
 
   test_method() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int m() {}
-}''', [HintCode.MISSING_RETURN]);
+}
+''', [
+      error(HintCode.MISSING_RETURN, 12, 3),
+    ]);
+  }
+
+  test_method_futureOrDynamic() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:async';
+class A {
+  FutureOr<dynamic> m() {}
+}
+''');
+  }
+
+  test_method_futureOrInt() async {
+    await assertErrorsInCode(r'''
+import 'dart:async';
+class A {
+  FutureOr<int> m() {}
+}
+''', [
+      error(HintCode.MISSING_RETURN, 33, 13),
+    ]);
   }
 
   test_method_inferred() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   int m();
 }
 class B extends A {
   m() {}
 }
-''', [HintCode.MISSING_RETURN]);
+''', [
+      error(HintCode.MISSING_RETURN, 54, 6),
+    ]);
   }
 
   test_noReturnType() async {
diff --git a/pkg/analyzer/test/src/diagnostics/mixin_of_non_class_test.dart b/pkg/analyzer/test/src/diagnostics/mixin_of_non_class_test.dart
new file mode 100644
index 0000000..6e5666d
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/mixin_of_non_class_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+//    defineReflectiveTests(MixinOfNonClassTest);
+    defineReflectiveTests(MixinOfNonClassWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class MixinOfNonClassTest extends DriverResolutionTest {}
+
+@reflectiveTest
+class MixinOfNonClassWithNnbdTest extends MixinOfNonClassTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_Never() async {
+    await assertErrorsInCode('''
+class A with Never {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 13, 5),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/mixin_super_class_constraint_non_interface_test.dart b/pkg/analyzer/test/src/diagnostics/mixin_super_class_constraint_non_interface_test.dart
new file mode 100644
index 0000000..07fbff3
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/mixin_super_class_constraint_non_interface_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MixinSuperClassConstraintNonInterfaceTest);
+    defineReflectiveTests(MixinSuperClassConstraintNonInterfaceWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class MixinSuperClassConstraintNonInterfaceTest extends DriverResolutionTest {}
+
+@reflectiveTest
+class MixinSuperClassConstraintNonInterfaceWithNnbdTest
+    extends MixinSuperClassConstraintNonInterfaceTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_Never() async {
+    await assertErrorsInCode('''
+mixin M on Never {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE, 11,
+          5),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart b/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart
index e907d2c..8ada226 100644
--- a/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart
@@ -22,34 +22,40 @@
   }
 
   test_directAnnotation() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @immutable
 class A {
   int x;
 }
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 50, 1),
+    ]);
   }
 
   test_directMixinAnnotation() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @immutable
 mixin A {
   int x;
 }
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 50, 1),
+    ]);
   }
 
   test_extendsClassWithAnnotation() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @immutable
 class A {}
 class B extends A {
   int x;
 }
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 61, 1),
+    ]);
   }
 
   test_finalField() async {
@@ -64,7 +70,7 @@
   }
 
   test_fromMixinWithAnnotation() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @immutable
 class A {}
@@ -72,11 +78,13 @@
   int x;
 }
 class C extends A with B {}
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 82, 1),
+    ]);
   }
 
   test_mixinApplication() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @immutable
 class A {}
@@ -84,11 +92,13 @@
   int x;
 }
 class C = A with B;
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 82, 1),
+    ]);
   }
 
   test_mixinApplicationBase() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   int x;
@@ -96,7 +106,9 @@
 class B {}
 @immutable
 class C = A with B;
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 82, 1),
+    ]);
   }
 
   test_staticField() async {
diff --git a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
index 588df81..ed220c7 100644
--- a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
@@ -38,7 +38,7 @@
   }
 
   test_fromExtendingClass() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   @mustCallSuper
@@ -49,7 +49,37 @@
   void a()
   {}
 }
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+      error(HintCode.MUST_CALL_SUPER, 115, 1),
+    ]);
+  }
+
+  test_fromExtendingClass_abstractInSuperclass() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+abstract class A {
+  @mustCallSuper
+  void a();
+}
+class B extends A {
+  @override
+  void a() {}
+}
+''');
+  }
+
+  test_fromExtendingClass_abstractInSubclass() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+abstract class A {
+  @mustCallSuper
+  void a() {}
+}
+class B extends A {
+  @override
+  void a();
+}
+''');
   }
 
   test_fromInterface() async {
@@ -66,8 +96,24 @@
 ''');
   }
 
+  test_fromMixin() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class Mixin {
+  @mustCallSuper
+  void a() {}
+}
+class C with Mixin {
+  @override
+  void a() {}
+}
+''', [
+      error(HintCode.MUST_CALL_SUPER, 120, 1),
+    ]);
+  }
+
   test_indirectlyInherited() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   @mustCallSuper
@@ -83,7 +129,42 @@
   @override
   void a() {}
 }
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+      error(HintCode.MUST_CALL_SUPER, 181, 1),
+    ]);
+  }
+
+  test_indirectlyInheritedFromMixin() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class Mixin {
+  @mustCallSuper
+  void b() {}
+}
+class C extends Object with Mixin {}
+class D extends C {
+  @override
+  void b() {}
+}
+''', [
+      error(HintCode.MUST_CALL_SUPER, 156, 1),
+    ]);
+  }
+
+  test_indirectlyInheritedFromMixinConstraint() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  void a() {}
+}
+mixin C on A {
+  @override
+  void a() {}
+}
+''', [
+      error(HintCode.MUST_CALL_SUPER, 110, 1),
+    ]);
   }
 
   test_overriddenWithFuture() async {
diff --git a/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
index 3199d246..b32c756 100644
--- a/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
@@ -11,46 +11,32 @@
 
 main() {
   defineReflectiveSuite(() {
-//    defineReflectiveTests(NonBoolConditionTest);
-    defineReflectiveTests(NonBoolConditionWithUIAsCodeAndConstantsTest);
-    defineReflectiveTests(NonBoolConditionWithUIAsCodeTest);
+    defineReflectiveTests(NonBoolConditionTest);
+    defineReflectiveTests(NonBoolConditionWithConstantsTest);
   });
 }
 
-//@reflectiveTest
-class NonBoolConditionTest extends DriverResolutionTest {}
-
 @reflectiveTest
-class NonBoolConditionWithUIAsCodeAndConstantsTest
-    extends NonBoolConditionWithUIAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class NonBoolConditionWithUIAsCodeTest extends NonBoolConditionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
+class NonBoolConditionTest extends DriverResolutionTest {
   test_ifElement() async {
-    assertErrorCodesInCode(
+    assertErrorsInCode(
         '''
 const c = [if (3) 1];
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticTypeWarningCode.NON_BOOL_CONDITION]
+            ? [
+                error(StaticTypeWarningCode.NON_BOOL_CONDITION, 15, 1),
+              ]
             : [
-                StaticTypeWarningCode.NON_BOOL_CONDITION,
-                CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 11, 8),
+                error(StaticTypeWarningCode.NON_BOOL_CONDITION, 15, 1),
               ]);
   }
 }
+
+@reflectiveTest
+class NonBoolConditionWithConstantsTest extends NonBoolConditionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_const_call_to_literal_constructor.dart b/pkg/analyzer/test/src/diagnostics/non_const_call_to_literal_constructor.dart
index 3b24286..408fc1a 100644
--- a/pkg/analyzer/test/src/diagnostics/non_const_call_to_literal_constructor.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_const_call_to_literal_constructor.dart
@@ -62,7 +62,7 @@
   }
 
   test_namedConstructor() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   @literal
@@ -71,11 +71,14 @@
 void main() {
   var a = A.named();
 }
-''', [HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 95, 1),
+      error(HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR, 99, 9),
+    ]);
   }
 
   test_nonConstContext() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   @literal
@@ -84,7 +87,10 @@
 void main() {
   var a = A();
 }
-''', [HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 89, 1),
+      error(HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR, 93, 3),
+    ]);
   }
 
   test_unconstableCreation() async {
@@ -102,7 +108,7 @@
   }
 
   test_usingNew() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   @literal
@@ -111,6 +117,9 @@
 void main() {
   var a = new A();
 }
-''', [HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 89, 1),
+      error(HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW, 93, 7),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_if_element_condition_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_if_element_condition_from_deferred_library_test.dart
index 759b7de..7f85015 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_if_element_condition_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_if_element_condition_from_deferred_library_test.dart
@@ -12,23 +12,18 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantIfElementConditionFromDeferredLibraryTest);
+    defineReflectiveTests(
+        NonConstantIfElementConditionFromDeferredLibraryWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class NonConstantIfElementConditionFromDeferredLibraryTest
     extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_inList_deferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const bool c = true;''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' deferred as a;
 f() {
@@ -36,10 +31,15 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? [
-                CompileTimeErrorCode
-                    .NON_CONSTANT_IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY
+                error(
+                    CompileTimeErrorCode
+                        .NON_CONSTANT_IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY,
+                    59,
+                    3),
               ]
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 56, 9),
+              ]);
   }
 
   test_inList_nonConst() async {
@@ -55,7 +55,7 @@
   test_inList_notDeferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const bool c = true;''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' as a;
 f() {
@@ -63,13 +63,15 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 9),
+              ]);
   }
 
   test_inMap_deferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const bool c = true;''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' deferred as a;
 f() {
@@ -77,10 +79,15 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? [
-                CompileTimeErrorCode
-                    .NON_CONSTANT_IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY
+                error(
+                    CompileTimeErrorCode
+                        .NON_CONSTANT_IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY,
+                    59,
+                    3),
               ]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 56, 13),
+              ]);
   }
 
   test_inMap_notConst() async {
@@ -96,7 +103,7 @@
   test_inMap_notDeferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const bool c = true;''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' as a;
 f() {
@@ -104,13 +111,15 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 13),
+              ]);
   }
 
   test_inSet_deferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const bool c = true;''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' deferred as a;
 f() {
@@ -118,10 +127,15 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? [
-                CompileTimeErrorCode
-                    .NON_CONSTANT_IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY
+                error(
+                    CompileTimeErrorCode
+                        .NON_CONSTANT_IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY,
+                    59,
+                    3),
               ]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 56, 9),
+              ]);
   }
 
   test_inSet_notConst() async {
@@ -137,7 +151,7 @@
   test_inSet_notDeferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const bool c = true;''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' as a;
 f() {
@@ -145,7 +159,9 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 47, 9),
+              ]);
   }
 }
 
@@ -154,9 +170,5 @@
     extends NonConstantIfElementConditionFromDeferredLibraryTest {
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart
index 8359de2..998262b 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart
@@ -13,72 +13,34 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantListElementFromDeferredLibraryTest);
     defineReflectiveTests(
-        NonConstantListValueFromDeferredLibraryWithUiAsCodeAndConstantsTest);
-    defineReflectiveTests(
-        NonConstantListValueFromDeferredLibraryWithUiAsCodeTest);
+        NonConstantListValueFromDeferredLibraryWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class NonConstantListElementFromDeferredLibraryTest
     extends DriverResolutionTest {
-  test_const_topLevel_deferred() async {
-    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
-const int c = 1;''');
-    await assertErrorCodesInCode(r'''
-import 'lib1.dart' deferred as a;
-var v = const [a.c];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY]);
-  }
-
-  test_const_topLevel_deferred_nested() async {
-    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
-const int c = 1;''');
-    await assertErrorCodesInCode(r'''
-import 'lib1.dart' deferred as a;
-var v = const [a.c + 1];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY]);
-  }
-}
-
-@reflectiveTest
-class NonConstantListValueFromDeferredLibraryWithUiAsCodeAndConstantsTest
-    extends NonConstantListValueFromDeferredLibraryWithUiAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class NonConstantListValueFromDeferredLibraryWithUiAsCodeTest
-    extends NonConstantListElementFromDeferredLibraryTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   @failingTest
   test_const_ifElement_thenTrue_deferredElse() async {
     // reports wrong error code (which is not crucial to fix)
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const int c = 1;''');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
 var v = const [ if (cond) 'a' else a.c ];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY]);
+''', [
+      error(
+          CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
+          0,
+          0),
+    ]);
   }
 
   test_const_ifElement_thenTrue_deferredThen() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const int c = 1;''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
@@ -86,9 +48,50 @@
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? [
-                CompileTimeErrorCode
-                    .NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY
+                error(
+                    CompileTimeErrorCode
+                        .NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
+                    79,
+                    3),
               ]
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 69, 13),
+              ]);
   }
+
+  test_const_topLevel_deferred() async {
+    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
+const int c = 1;''');
+    await assertErrorsInCode(r'''
+import 'lib1.dart' deferred as a;
+var v = const [a.c];
+''', [
+      error(
+          CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
+          49,
+          3),
+    ]);
+  }
+
+  test_const_topLevel_deferred_nested() async {
+    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
+const int c = 1;''');
+    await assertErrorsInCode(r'''
+import 'lib1.dart' deferred as a;
+var v = const [a.c + 1];
+''', [
+      error(
+          CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
+          49,
+          7),
+    ]);
+  }
+}
+
+@reflectiveTest
+class NonConstantListValueFromDeferredLibraryWithConstantsTest
+    extends NonConstantListElementFromDeferredLibraryTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart
index aafeb85..2803c58 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart
@@ -12,25 +12,153 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantListElementTest);
-    defineReflectiveTests(NonConstantListElementWithUiAsCodeAndConstantsTest);
-    defineReflectiveTests(NonConstantListElementWithUiAsCodeTest);
+    defineReflectiveTests(NonConstantListElementWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class NonConstantListElementTest extends DriverResolutionTest {
+  test_const_forElement() async {
+    await assertErrorsInCode(r'''
+const Set set = {};
+var v = const [for(final x in set) x];
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 35, 21),
+    ]);
+  }
+
+  test_const_ifElement_thenElseFalse_finalElse() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const [if (1 < 0) 0 else a];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 54, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenElseFalse_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const [if (1 < 0) a else 0];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalElse() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const [if (1 > 0) 0 else a];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 54, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const [if (1 > 0) a else 0];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_constThen() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+var v = const [if (1 < 0) a];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 12),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const [if (1 < 0) a];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 12),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_constThen() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+var v = const [if (1 > 0) a];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 12),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const [if (1 > 0) a];
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 12),
+              ]);
+  }
+
   test_const_topVar() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const [a];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 1),
+    ]);
   }
 
   test_const_topVar_nested() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 final dynamic a = 0;
 var v = const [a + 1];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 1),
+    ]);
   }
 
   test_nonConst_topVar() async {
@@ -42,95 +170,9 @@
 }
 
 @reflectiveTest
-class NonConstantListElementWithUiAsCodeAndConstantsTest
-    extends NonConstantListElementWithUiAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class NonConstantListElementWithUiAsCodeTest
+class NonConstantListElementWithConstantsTest
     extends NonConstantListElementTest {
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
-  test_const_forElement() async {
-    await assertErrorCodesInCode(r'''
-const Set set = {};
-var v = const [for(final x in set) x];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseFalse_finalElse() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const [if (1 < 0) 0 else a];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseFalse_finalThen() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const [if (1 < 0) a else 0];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseTrue_finalElse() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const [if (1 > 0) 0 else a];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseTrue_finalThen() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const [if (1 > 0) a else 0];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_constThen() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-var v = const [if (1 < 0) a];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_finalThen() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const [if (1 < 0) a];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_constThen() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-var v = const [if (1 > 0) a];
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_finalThen() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const [if (1 > 0) a];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
index 692b49b..a57c563 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
@@ -11,50 +11,42 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(NonConstantMapElementWithUiAsCodeAndConstantTest);
-    defineReflectiveTests(NonConstantMapElementWithUiAsCodeTest);
+    defineReflectiveTests(NonConstantMapElementTest);
+    defineReflectiveTests(NonConstantMapElementWithConstantTest);
     defineReflectiveTests(NonConstantMapKeyTest);
-    defineReflectiveTests(NonConstantMapKeyWithUiAsCodeTest);
     defineReflectiveTests(NonConstantMapValueTest);
-    defineReflectiveTests(NonConstantMapValueWithUiAsCodeTest);
   });
 }
 
 @reflectiveTest
-class NonConstantMapElementWithUiAsCodeAndConstantTest
-    extends NonConstantMapElementWithUiAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class NonConstantMapElementWithUiAsCodeTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
+class NonConstantMapElementTest extends DriverResolutionTest {
   test_forElement_cannotBeConst() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 void main() {
   const {1: null, for (final x in const []) null: null};
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 32, 36),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 43, 1),
+    ]);
   }
 
   test_forElement_nested_cannotBeConst() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode(
+        '''
 void main() {
   const {1: null, if (true) for (final x in const []) null: null};
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 42, 36),
+                error(HintCode.UNUSED_LOCAL_VARIABLE, 53, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 32, 46),
+                error(HintCode.UNUSED_LOCAL_VARIABLE, 53, 1),
+              ]);
   }
 
   test_forElement_notConst_noError() async {
@@ -67,7 +59,7 @@
   }
 
   test_ifElement_mayBeConst() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 void main() {
   const {1: null, if (true) null: null};
@@ -75,11 +67,13 @@
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 32, 20),
+              ]);
   }
 
   test_ifElement_nested_mayBeConst() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 void main() {
   const {1: null, if (true) if (true) null: null};
@@ -87,20 +81,30 @@
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 32, 30),
+              ]);
   }
 
   test_ifElement_notConstCondition() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode(
+        '''
 void main() {
   bool notConst = true;
   const {1: null, if (notConst) null: null};
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 60, 8),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 56, 24),
+              ]);
   }
 
   test_ifElementWithElse_mayBeConst() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 void main() {
   const isTrue = true;
@@ -109,11 +113,13 @@
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 55, 38),
+              ]);
   }
 
   test_spreadElement_mayBeConst() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 void main() {
   const {1: null, ...{null: null}};
@@ -121,26 +127,161 @@
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 32, 15),
+              ]);
   }
 
   test_spreadElement_notConst() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode(
+        '''
 void main() {
   var notConst = {};
   const {1: null, ...notConst};
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 56, 8),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 53, 11),
+              ]);
   }
 }
 
 @reflectiveTest
+class NonConstantMapElementWithConstantTest extends NonConstantMapElementTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
+}
+
+@reflectiveTest
 class NonConstantMapKeyTest extends DriverResolutionTest {
+  test_const_ifElement_thenElseFalse_finalElse() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) 0: 0 else a: 0};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
+              ]);
+  }
+
+  test_const_ifElement_thenElseFalse_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) a: 0 else 0: 0};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
+              ]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalElse() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) 0: 0 else a: 0};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
+              ]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) a: 0 else 0: 0};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_constThen() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+var v = const <int, int>{if (1 < 0) a: 0};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) a: 0};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_constThen() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+var v = const <int, int>{if (1 > 0) a: 0};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) a: 0};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
+              ]);
+  }
+
   test_const_topVar() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{a: 0};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 46, 1),
+    ]);
   }
 
   test_nonConst_topVar() async {
@@ -152,110 +293,130 @@
 }
 
 @reflectiveTest
-class NonConstantMapKeyWithUiAsCodeTest extends NonConstantMapKeyTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
+class NonConstantMapValueTest extends DriverResolutionTest {
   test_const_ifElement_thenElseFalse_finalElse() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 final dynamic a = 0;
-var v = const <int, int>{if (1 < 0) 0: 0 else a: 0};
+var v = const <int, int>{if (1 < 0) 0: 0 else 0: a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
+              ]);
   }
 
   test_const_ifElement_thenElseFalse_finalThen() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 final dynamic a = 0;
-var v = const <int, int>{if (1 < 0) a: 0 else 0: 0};
+var v = const <int, int>{if (1 < 0) 0: a else 0: 0};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
+              ]);
   }
 
   test_const_ifElement_thenElseTrue_finalElse() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 final dynamic a = 0;
-var v = const <int, int>{if (1 > 0) 0: 0 else a: 0};
+var v = const <int, int>{if (1 > 0) 0: 0 else 0: a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
+              ]);
   }
 
   test_const_ifElement_thenElseTrue_finalThen() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 final dynamic a = 0;
-var v = const <int, int>{if (1 > 0) a: 0 else 0: 0};
+var v = const <int, int>{if (1 > 0) 0: a else 0: 0};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
+              ]);
   }
 
   test_const_ifElement_thenFalse_constThen() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 0;
-var v = const <int, int>{if (1 < 0) a: 0};
+var v = const <int, int>{if (1 < 0) 0: a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
+              ]);
   }
 
   test_const_ifElement_thenFalse_finalThen() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 final dynamic a = 0;
-var v = const <int, int>{if (1 < 0) a: 0};
+var v = const <int, int>{if (1 < 0) 0: a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
+              ]);
   }
 
   test_const_ifElement_thenTrue_constThen() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 0;
-var v = const <int, int>{if (1 > 0) a: 0};
+var v = const <int, int>{if (1 > 0) 0: a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
+              ]);
   }
 
   test_const_ifElement_thenTrue_finalThen() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 final dynamic a = 0;
-var v = const <int, int>{if (1 > 0) a: 0};
+var v = const <int, int>{if (1 > 0) 0: a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 0, 0),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
+              ]);
   }
-}
 
-@reflectiveTest
-class NonConstantMapValueTest extends DriverResolutionTest {
   test_const_topVar() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{0: a};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 49, 1),
+    ]);
   }
 
   test_nonConst_topVar() async {
@@ -265,101 +426,3 @@
 ''');
   }
 }
-
-@reflectiveTest
-class NonConstantMapValueWithUiAsCodeTest extends NonConstantMapValueTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
-  test_const_ifElement_thenElseFalse_finalElse() async {
-    await assertErrorCodesInCode(
-        '''
-final dynamic a = 0;
-var v = const <int, int>{if (1 < 0) 0: 0 else 0: a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseFalse_finalThen() async {
-    await assertErrorCodesInCode(
-        '''
-final dynamic a = 0;
-var v = const <int, int>{if (1 < 0) 0: a else 0: 0};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseTrue_finalElse() async {
-    await assertErrorCodesInCode(
-        '''
-final dynamic a = 0;
-var v = const <int, int>{if (1 > 0) 0: 0 else 0: a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseTrue_finalThen() async {
-    await assertErrorCodesInCode(
-        '''
-final dynamic a = 0;
-var v = const <int, int>{if (1 > 0) 0: a else 0: 0};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_constThen() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-var v = const <int, int>{if (1 < 0) 0: a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_finalThen() async {
-    await assertErrorCodesInCode(
-        '''
-final dynamic a = 0;
-var v = const <int, int>{if (1 < 0) 0: a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_constThen() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-var v = const <int, int>{if (1 > 0) 0: a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_finalThen() async {
-    await assertErrorCodesInCode(
-        '''
-final dynamic a = 0;
-var v = const <int, int>{if (1 > 0) 0: a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
-  }
-}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart
index 43225c7..8796e37 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart
@@ -13,77 +13,78 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantMapKeyFromDeferredLibraryTest);
     defineReflectiveTests(
-        NonConstantMapKeyFromDeferredLibraryWithUiAsCodeAndConstantsTest);
-    defineReflectiveTests(NonConstantMapKeyFromDeferredLibraryWithUiAsCodeTest);
+        NonConstantMapKeyFromDeferredLibraryWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class NonConstantMapKeyFromDeferredLibraryTest extends DriverResolutionTest {
-  test_const_topLevel_deferred() async {
-    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
-const int c = 1;''');
-    await assertErrorCodesInCode(r'''
-import 'lib1.dart' deferred as a;
-var v = const {a.c : 0};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY]);
-  }
-
-  test_const_topLevel_deferred_nested() async {
-    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
-const int c = 1;''');
-    await assertErrorCodesInCode(r'''
-import 'lib1.dart' deferred as a;
-var v = const {a.c + 1 : 0};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY]);
-  }
-}
-
-@reflectiveTest
-class NonConstantMapKeyFromDeferredLibraryWithUiAsCodeAndConstantsTest
-    extends NonConstantMapKeyFromDeferredLibraryWithUiAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class NonConstantMapKeyFromDeferredLibraryWithUiAsCodeTest
-    extends NonConstantMapKeyFromDeferredLibraryTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   @failingTest
   test_const_ifElement_thenTrue_deferredElse() async {
 // reports wrong error code
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const int c = 1;''');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
 var v = const { if (cond) 0: 1 else a.c : 0};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY, 0,
+          0),
+    ]);
   }
 
   test_const_ifElement_thenTrue_deferredThen() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const int c = 1;''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
 var v = const { if (cond) a.c : 0};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(
+                    CompileTimeErrorCode
+                        .NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY,
+                    79,
+                    3),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 69, 17),
+              ]);
   }
+
+  test_const_topLevel_deferred() async {
+    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
+const int c = 1;''');
+    await assertErrorsInCode(r'''
+import 'lib1.dart' deferred as a;
+var v = const {a.c : 0};
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY, 49,
+          3),
+    ]);
+  }
+
+  test_const_topLevel_deferred_nested() async {
+    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
+const int c = 1;''');
+    await assertErrorsInCode(r'''
+import 'lib1.dart' deferred as a;
+var v = const {a.c + 1 : 0};
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY, 49,
+          7),
+    ]);
+  }
+}
+
+@reflectiveTest
+class NonConstantMapKeyFromDeferredLibraryWithConstantsTest
+    extends NonConstantMapKeyFromDeferredLibraryTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_test.dart
index 48a454b..0f7a698 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_test.dart
@@ -12,63 +12,57 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantMapKeyTest);
-    defineReflectiveTests(NonConstantMapKeyWithUiAsCodeAndConstantsTest);
-    defineReflectiveTests(NonConstantMapKeyWithUiAsCodeTest);
+    defineReflectiveTests(NonConstantMapKeyWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class NonConstantMapKeyTest extends DriverResolutionTest {
-  test_const_topLevel() async {
-    await assertErrorCodesInCode(r'''
-final dynamic a = 0;
-var v = const {a : 0};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
-  }
-}
-
-@reflectiveTest
-class NonConstantMapKeyWithUiAsCodeAndConstantsTest
-    extends NonConstantMapKeyWithUiAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class NonConstantMapKeyWithUiAsCodeTest extends NonConstantMapKeyTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_const_ifElement_thenTrue_elseFinal() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 final dynamic a = 0;
 const cond = true;
 var v = const {if (cond) 0: 1 else a : 0};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 75, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 55, 25),
+              ]);
   }
 
   test_const_ifElement_thenTrue_thenFinal() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 final dynamic a = 0;
 const cond = true;
 var v = const {if (cond) a : 0};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 65, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 55, 15),
+              ]);
   }
+
+  test_const_topLevel() async {
+    await assertErrorsInCode(r'''
+final dynamic a = 0;
+var v = const {a : 0};
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 36, 1),
+    ]);
+  }
+}
+
+@reflectiveTest
+class NonConstantMapKeyWithConstantsTest extends NonConstantMapKeyTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart
index ddfde67..d116bb9 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart
@@ -13,71 +13,31 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantMapValueFromDeferredLibraryTest);
     defineReflectiveTests(
-        NonConstantMapValueFromDeferredLibraryWithUiAsCodeAndConstantsTest);
-    defineReflectiveTests(
-        NonConstantMapValueFromDeferredLibraryWithUiAsCodeTest);
+        NonConstantMapValueFromDeferredLibraryWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class NonConstantMapValueFromDeferredLibraryTest extends DriverResolutionTest {
-  test_const_topLevel_deferred() async {
-    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
-const int c = 1;''');
-    await assertErrorCodesInCode(r'''
-import 'lib1.dart' deferred as a;
-var v = const {'a' : a.c};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY]);
-  }
-
-  test_const_topLevel_deferred_nested() async {
-    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
-const int c = 1;''');
-    await assertErrorCodesInCode(r'''
-import 'lib1.dart' deferred as a;
-var v = const {'a' : a.c + 1};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY]);
-  }
-}
-
-@reflectiveTest
-class NonConstantMapValueFromDeferredLibraryWithUiAsCodeAndConstantsTest
-    extends NonConstantMapValueFromDeferredLibraryWithUiAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class NonConstantMapValueFromDeferredLibraryWithUiAsCodeTest
-    extends NonConstantMapValueFromDeferredLibraryTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   @failingTest
   test_const_ifElement_thenTrue_elseDeferred() async {
     // reports wrong error code
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const int c = 1;''');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
 var v = const { if (cond) 'a': 'b' else 'c' : a.c};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
+          99, 3),
+    ]);
   }
 
   test_const_ifElement_thenTrue_thenDeferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const int c = 1;''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
@@ -85,9 +45,46 @@
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? [
-                CompileTimeErrorCode
-                    .NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY
+                error(
+                    CompileTimeErrorCode
+                        .NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
+                    85,
+                    3),
               ]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 69, 19),
+              ]);
   }
+
+  test_const_topLevel_deferred() async {
+    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
+const int c = 1;''');
+    await assertErrorsInCode(r'''
+import 'lib1.dart' deferred as a;
+var v = const {'a' : a.c};
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
+          55, 3),
+    ]);
+  }
+
+  test_const_topLevel_deferred_nested() async {
+    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
+const int c = 1;''');
+    await assertErrorsInCode(r'''
+import 'lib1.dart' deferred as a;
+var v = const {'a' : a.c + 1};
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
+          55, 7),
+    ]);
+  }
+}
+
+@reflectiveTest
+class NonConstantMapValueFromDeferredLibraryWithConstantsTest
+    extends NonConstantMapValueFromDeferredLibraryTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_test.dart
index a88a96d..a448d9c 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_test.dart
@@ -12,66 +12,58 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantMapValueTest);
-    defineReflectiveTests(NonConstantMapValueWithUiAsCodeAndConstantsTest);
-    defineReflectiveTests(NonConstantMapValueWithUiAsCodeTest);
+    defineReflectiveTests(NonConstantMapValueWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class NonConstantMapValueTest extends DriverResolutionTest {
-  test_const_topLevel() async {
-    await assertErrorCodesInCode(r'''
-final dynamic a = 0;
-var v = const {'a' : a};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
-  }
-}
-
-@reflectiveTest
-class NonConstantMapValueWithUiAsCodeAndConstantsTest
-    extends NonConstantMapValueWithUiAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class NonConstantMapValueWithUiAsCodeTest extends NonConstantMapValueTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_const_ifTrue_elseFinal() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 final dynamic a = 0;
 const cond = true;
 var v = const {if (cond) 'a': 'b', 'c' : a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 81, 1),
+              ]
             : [
-                CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE,
-                CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 55, 18),
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 81, 1),
               ]);
   }
 
   test_const_ifTrue_thenFinal() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 final dynamic a = 0;
 const cond = true;
 var v = const {if (cond) 'a' : a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 71, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 55, 17),
+              ]);
   }
+
+  test_const_topLevel() async {
+    await assertErrorsInCode(r'''
+final dynamic a = 0;
+var v = const {'a' : a};
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 42, 1),
+    ]);
+  }
+}
+
+@reflectiveTest
+class NonConstantMapValueWithConstantsTest extends NonConstantMapValueTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_set_element_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_from_deferred_library_test.dart
index 7a2ea68..7dd39c4 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_set_element_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_from_deferred_library_test.dart
@@ -13,72 +13,32 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantSetElementFromDeferredLibraryTest);
     defineReflectiveTests(
-        NonConstantSetElementFromDeferredLibraryWithUiAsCodeAndConstantsTest);
-    defineReflectiveTests(
-        NonConstantSetElementFromDeferredLibraryWithUiAsCodeTest);
+        NonConstantSetElementFromDeferredLibraryWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class NonConstantSetElementFromDeferredLibraryTest
     extends DriverResolutionTest {
-  test_const_topLevel_deferred() async {
-    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
-const int c = 1;''');
-    await assertErrorCodesInCode(r'''
-import 'lib1.dart' deferred as a;
-var v = const {a.c};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY]);
-  }
-
-  test_const_topLevel_deferred_nested() async {
-    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
-const int c = 1;''');
-    await assertErrorCodesInCode(r'''
-import 'lib1.dart' deferred as a;
-var v = const {a.c + 1};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY]);
-  }
-}
-
-@reflectiveTest
-class NonConstantSetElementFromDeferredLibraryWithUiAsCodeAndConstantsTest
-    extends NonConstantSetElementFromDeferredLibraryWithUiAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class NonConstantSetElementFromDeferredLibraryWithUiAsCodeTest
-    extends NonConstantSetElementFromDeferredLibraryTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   @failingTest
   test_const_ifElement_thenTrue_elseDeferred() async {
     // reports wrong error code
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const int c = 1;''');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
 var v = const {if (cond) null else a.c};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY,
+          88, 3),
+    ]);
   }
 
   test_const_ifElement_thenTrue_thenDeferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const int c = 1;''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
@@ -86,9 +46,46 @@
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? [
-                CompileTimeErrorCode
-                    .NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY
+                error(
+                    CompileTimeErrorCode
+                        .NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY,
+                    78,
+                    3),
               ]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 68, 13),
+              ]);
   }
+
+  test_const_topLevel_deferred() async {
+    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
+const int c = 1;''');
+    await assertErrorsInCode(r'''
+import 'lib1.dart' deferred as a;
+var v = const {a.c};
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY,
+          49, 3),
+    ]);
+  }
+
+  test_const_topLevel_deferred_nested() async {
+    newFile(convertPath('/test/lib/lib1.dart'), content: r'''
+const int c = 1;''');
+    await assertErrorsInCode(r'''
+import 'lib1.dart' deferred as a;
+var v = const {a.c + 1};
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY,
+          49, 7),
+    ]);
+  }
+}
+
+@reflectiveTest
+class NonConstantSetElementFromDeferredLibraryWithConstantsTest
+    extends NonConstantSetElementFromDeferredLibraryTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
index 753d602..7793685 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
@@ -12,25 +12,159 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantSetElementTest);
-    defineReflectiveTests(NonConstantSetElementWithUiAsCodeAndConstantsTest);
-    defineReflectiveTests(NonConstantSetElementWithUiAsCodeTest);
+    defineReflectiveTests(NonConstantSetElementWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class NonConstantSetElementTest extends DriverResolutionTest {
+  test_const_ifElement_thenElseFalse_finalElse() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int>{if (1 < 0) 0 else a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 59, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenElseFalse_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int>{if (1 < 0) a else 0};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalElse() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int>{if (1 > 0) 0 else a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 59, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int>{if (1 > 0) a else 0};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_constThen() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+var v = const <int>{if (1 < 0) a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 12),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int>{if (1 < 0) a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 12),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_constThen() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+var v = const <int>{if (1 > 0) a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 12),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_finalThen() async {
+    await assertErrorsInCode(
+        '''
+final dynamic a = 0;
+var v = const <int>{if (1 > 0) a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 12),
+              ]);
+  }
+
   test_const_parameter() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(a) {
   return const {a};
-}''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+}''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 23, 1),
+    ]);
+  }
+
+  test_const_spread_final() async {
+    await assertErrorsInCode(
+        r'''
+final Set x = null;
+var v = const {...x};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 38, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 35, 4),
+              ]);
   }
 
   test_const_topVar() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int>{a};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 1),
+    ]);
   }
 
   test_nonConst_topVar() async {
@@ -42,94 +176,8 @@
 }
 
 @reflectiveTest
-class NonConstantSetElementWithUiAsCodeAndConstantsTest
-    extends NonConstantSetElementWithUiAsCodeTest {
+class NonConstantSetElementWithConstantsTest extends NonConstantSetElementTest {
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class NonConstantSetElementWithUiAsCodeTest extends NonConstantSetElementTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
-  test_const_ifElement_thenElseFalse_finalElse() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const <int>{if (1 < 0) 0 else a};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseFalse_finalThen() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const <int>{if (1 < 0) a else 0};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseTrue_finalElse() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const <int>{if (1 > 0) 0 else a};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseTrue_finalThen() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const <int>{if (1 > 0) a else 0};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_constThen() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-var v = const <int>{if (1 < 0) a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_finalThen() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const <int>{if (1 < 0) a};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_constThen() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-var v = const <int>{if (1 > 0) a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_finalThen() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const <int>{if (1 > 0) a};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_spread_final() async {
-    await assertErrorCodesInCode(r'''
-final Set x = null;
-var v = const {...x};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_spread_expression_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_spread_expression_from_deferred_library_test.dart
index 5d0e702..b8ad8b4 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_spread_expression_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_spread_expression_from_deferred_library_test.dart
@@ -20,17 +20,10 @@
 @reflectiveTest
 class NonConstantSpreadExpressionFromDeferredLibraryTest
     extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_inList_deferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const List c = [];''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' deferred as a;
 f() {
@@ -38,10 +31,15 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? [
-                CompileTimeErrorCode
-                    .NON_CONSTANT_SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY
+                error(
+                    CompileTimeErrorCode
+                        .NON_CONSTANT_SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY,
+                    59,
+                    3),
               ]
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 56, 6),
+              ]);
   }
 
   test_inList_deferred_notConst() async {
@@ -57,7 +55,7 @@
   test_inList_notDeferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const List c = [];''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' as a;
 f() {
@@ -65,13 +63,15 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 6),
+              ]);
   }
 
   test_inMap_deferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const Map c = <int, int>{};''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' deferred as a;
 f() {
@@ -79,10 +79,15 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? [
-                CompileTimeErrorCode
-                    .NON_CONSTANT_SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY
+                error(
+                    CompileTimeErrorCode
+                        .NON_CONSTANT_SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY,
+                    59,
+                    3),
               ]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 56, 6),
+              ]);
   }
 
   test_inMap_notConst() async {
@@ -98,7 +103,7 @@
   test_inMap_notDeferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const Map c = <int, int>{};''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' as a;
 f() {
@@ -106,13 +111,15 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 6),
+              ]);
   }
 
   test_inSet_deferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const Set c = <int>{};''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' deferred as a;
 f() {
@@ -120,10 +127,15 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? [
-                CompileTimeErrorCode
-                    .NON_CONSTANT_SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY
+                error(
+                    CompileTimeErrorCode
+                        .NON_CONSTANT_SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY,
+                    59,
+                    3),
               ]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 56, 6),
+              ]);
   }
 
   test_inSet_notConst() async {
@@ -139,7 +151,7 @@
   test_inSet_notDeferred() async {
     newFile(convertPath('/test/lib/lib1.dart'), content: r'''
 const Set c = <int>{};''');
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         r'''
 import 'lib1.dart' as a;
 f() {
@@ -147,7 +159,9 @@
 }''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 47, 6),
+              ]);
   }
 }
 
@@ -156,9 +170,5 @@
     extends NonConstantSpreadExpressionFromDeferredLibraryTest {
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_null_opt_out_test.dart b/pkg/analyzer/test/src/diagnostics/non_null_opt_out_test.dart
new file mode 100644
index 0000000..8c5936c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/non_null_opt_out_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2019, 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:analyzer/src/error/codes.dart';
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NonNullOptOutTest);
+  });
+}
+
+@reflectiveTest
+class NonNullOptOutTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_nnbd_optOut_invalidSyntax() async {
+    assertErrorsInCode('''
+// @dart = 2.2
+// NNBD syntax is not allowed
+f(x, y, z) { (x is String?) ? (x + y) : z; }
+''', [error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 70, 1)]);
+  }
+
+  test_nnbd_optOut_late() async {
+    assertNoErrorsInCode('''
+// @dart = 2.2
+class C {
+  // "late" is allowed as an identifier
+  int late;
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart b/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart
index 08a4506..4b774e1 100644
--- a/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart
@@ -2,9 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -17,13 +15,6 @@
 
 @reflectiveTest
 class NotIterableSpreadTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
   test_iterable_list() async {
     await assertNoErrorsInCode('''
 var a = [0];
@@ -38,30 +29,39 @@
   }
 
   test_notIterable_direct() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var a = 0;
 var v = [...a];
-''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_ITERABLE_SPREAD, 23, 1),
+    ]);
   }
 
   test_notIterable_forElement() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var a = 0;
 var v = [for (var i in []) ...a];
-''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 29, 1),
+      error(CompileTimeErrorCode.NOT_ITERABLE_SPREAD, 41, 1),
+    ]);
   }
 
   test_notIterable_ifElement_else() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var a = 0;
 var v = [if (1 > 0) ...[] else ...a];
-''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_ITERABLE_SPREAD, 45, 1),
+    ]);
   }
 
   test_notIterable_ifElement_then() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var a = 0;
 var v = [if (1 > 0) ...a];
-''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_ITERABLE_SPREAD, 34, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart b/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart
index 57031dd..2f7e415 100644
--- a/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart
@@ -2,9 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -17,13 +15,6 @@
 
 @reflectiveTest
 class NotMapSpreadTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
   test_map() async {
     await assertNoErrorsInCode('''
 var a = {0: 0};
@@ -38,30 +29,39 @@
   }
 
   test_notMap_direct() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var a = 0;
 var v = <int, int>{...a};
-''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_MAP_SPREAD, 33, 1),
+    ]);
   }
 
   test_notMap_forElement() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var a = 0;
 var v = <int, int>{for (var i in []) ...a};
-''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 39, 1),
+      error(CompileTimeErrorCode.NOT_MAP_SPREAD, 51, 1),
+    ]);
   }
 
   test_notMap_ifElement_else() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var a = 0;
 var v = <int, int>{if (1 > 0) ...<int, int>{} else ...a};
-''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_MAP_SPREAD, 65, 1),
+    ]);
   }
 
   test_notMap_ifElement_then() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var a = 0;
 var v = <int, int>{if (1 > 0) ...a};
-''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_MAP_SPREAD, 44, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/not_null_aware_null_spread_test.dart b/pkg/analyzer/test/src/diagnostics/not_null_aware_null_spread_test.dart
index 45ffdf8..115ffde 100644
--- a/pkg/analyzer/test/src/diagnostics/not_null_aware_null_spread_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_null_aware_null_spread_test.dart
@@ -2,9 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -17,24 +15,21 @@
 
 @reflectiveTest
 class NotNullAwareNullSpreadTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
   test_listLiteral_notNullAware_nullLiteral() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = [...null];
-''', [CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD, 12, 4),
+    ]);
   }
 
   test_listLiteral_notNullAware_nullTyped() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 Null a = null;
 var v = [...a];
-''', [CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD, 27, 1),
+    ]);
   }
 
   test_listLiteral_nullAware_nullLiteral() async {
@@ -51,16 +46,20 @@
   }
 
   test_mapLiteral_notNullAware_nullLiteral() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <int, int>{...null};
-''', [CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD, 22, 4),
+    ]);
   }
 
   test_mapLiteral_notNullAware_nullType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 Null a = null;
 var v = <int, int>{...a};
-''', [CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD, 37, 1),
+    ]);
   }
 
   test_mapLiteral_nullAware_nullLiteral() async {
@@ -77,16 +76,20 @@
   }
 
   test_setLiteral_notNullAware_nullLiteral() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <int>{...null};
-''', [CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD, 17, 4),
+    ]);
   }
 
   test_setLiteral_notNullAware_nullTyped() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 Null a = null;
 var v = <int>{...a};
-''', [CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD]);
+''', [
+      error(CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD, 32, 1),
+    ]);
   }
 
   test_setLiteral_nullAware_nullLiteral() async {
diff --git a/pkg/analyzer/test/src/diagnostics/null_aware_before_operator_test.dart b/pkg/analyzer/test/src/diagnostics/null_aware_before_operator_test.dart
index 7f89a71..6b5be07 100644
--- a/pkg/analyzer/test/src/diagnostics/null_aware_before_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/null_aware_before_operator_test.dart
@@ -48,11 +48,13 @@
   }
 
   test_minus() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   x?.a - '';
 }
-''', [HintCode.NULL_AWARE_BEFORE_OPERATOR]);
+''', [
+      error(HintCode.NULL_AWARE_BEFORE_OPERATOR, 9, 4),
+    ]);
   }
 
   test_not_equal() async {
diff --git a/pkg/analyzer/test/src/diagnostics/null_aware_in_condition_test.dart b/pkg/analyzer/test/src/diagnostics/null_aware_in_condition_test.dart
index 89203f2..c057732 100644
--- a/pkg/analyzer/test/src/diagnostics/null_aware_in_condition_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/null_aware_in_condition_test.dart
@@ -16,58 +16,72 @@
 @reflectiveTest
 class NullAwareInConditionTest extends DriverResolutionTest {
   test_assert() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   assert (x?.a);
 }
-''', [HintCode.NULL_AWARE_IN_CONDITION]);
+''', [
+      error(HintCode.NULL_AWARE_IN_CONDITION, 17, 4),
+    ]);
   }
 
   test_conditionalExpression() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   return x?.a ? 0 : 1;
 }
-''', [HintCode.NULL_AWARE_IN_CONDITION]);
+''', [
+      error(HintCode.NULL_AWARE_IN_CONDITION, 16, 4),
+    ]);
   }
 
   test_do() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   do {} while (x?.a);
 }
-''', [HintCode.NULL_AWARE_IN_CONDITION]);
+''', [
+      error(HintCode.NULL_AWARE_IN_CONDITION, 22, 4),
+    ]);
   }
 
   test_for() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   for (var v = x; v?.a; v = v.next) {}
 }
-''', [HintCode.NULL_AWARE_IN_CONDITION]);
+''', [
+      error(HintCode.NULL_AWARE_IN_CONDITION, 25, 4),
+    ]);
   }
 
   test_if() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   if (x?.a) {}
 }
-''', [HintCode.NULL_AWARE_IN_CONDITION]);
+''', [
+      error(HintCode.NULL_AWARE_IN_CONDITION, 13, 4),
+    ]);
   }
 
   test_if_parenthesized() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   if ((x?.a)) {}
 }
-''', [HintCode.NULL_AWARE_IN_CONDITION]);
+''', [
+      error(HintCode.NULL_AWARE_IN_CONDITION, 13, 6),
+    ]);
   }
 
   test_while() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   while (x?.a) {}
 }
-''', [HintCode.NULL_AWARE_IN_CONDITION]);
+''', [
+      error(HintCode.NULL_AWARE_IN_CONDITION, 16, 4),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/null_aware_in_logical_operator_test.dart b/pkg/analyzer/test/src/diagnostics/null_aware_in_logical_operator_test.dart
index b60810e..d445199 100644
--- a/pkg/analyzer/test/src/diagnostics/null_aware_in_logical_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/null_aware_in_logical_operator_test.dart
@@ -16,51 +16,63 @@
 @reflectiveTest
 class NullAwareInLogicalOperatorTest extends DriverResolutionTest {
   test_conditionalAnd_first() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   x?.a && x.b;
 }
-''', [HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR]);
+''', [
+      error(HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR, 9, 4),
+    ]);
   }
 
   test_conditionalAnd_second() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   x.a && x?.b;
 }
-''', [HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR]);
+''', [
+      error(HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR, 16, 4),
+    ]);
   }
 
   test_conditionalAnd_third() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   x.a && x.b && x?.c;
 }
-''', [HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR]);
+''', [
+      error(HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR, 23, 4),
+    ]);
   }
 
   test_conditionalOr_first() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   x?.a || x.b;
 }
-''', [HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR]);
+''', [
+      error(HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR, 9, 4),
+    ]);
   }
 
   test_conditionalOr_second() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   x.a || x?.b;
 }
-''', [HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR]);
+''', [
+      error(HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR, 16, 4),
+    ]);
   }
 
   test_conditionalOr_third() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   x.a || x.b || x?.c;
 }
-''', [HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR]);
+''', [
+      error(HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR, 23, 4),
+    ]);
   }
 
   test_for_noCondition() async {
@@ -80,10 +92,12 @@
   }
 
   test_not() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(x) {
   !x?.a;
 }
-''', [HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR]);
+''', [
+      error(HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR, 10, 4),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/nullable_type_in_catch_clause_test.dart b/pkg/analyzer/test/src/diagnostics/nullable_type_in_catch_clause_test.dart
index b500cd6..3948d35 100644
--- a/pkg/analyzer/test/src/diagnostics/nullable_type_in_catch_clause_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/nullable_type_in_catch_clause_test.dart
@@ -31,7 +31,18 @@
 ''');
   }
 
-  test_on_class() async {
+  test_on_class_nonNullable() async {
+    assertNoErrorsInCode('''
+class A {}
+f() {
+  try {
+  } on A catch (e) {
+  }
+}
+''');
+  }
+
+  test_on_class_nullable() async {
     assertErrorsInCode('''
 class A {}
 f() {
@@ -57,4 +68,16 @@
       error(CompileTimeErrorCode.NULLABLE_TYPE_IN_CATCH_CLAUSE, 40, 1),
     ]);
   }
+
+  test_on_typeParameter_nonNullable() async {
+    assertNoErrorsInCode('''
+class A<B extends Object> {
+  m() {
+    try {
+    } on B {
+    }
+  }
+}
+''');
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/nullable_type_in_extends_clause_test.dart b/pkg/analyzer/test/src/diagnostics/nullable_type_in_extends_clause_test.dart
index 2478d79..b2f454b 100644
--- a/pkg/analyzer/test/src/diagnostics/nullable_type_in_extends_clause_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/nullable_type_in_extends_clause_test.dart
@@ -29,10 +29,12 @@
   }
 
   test_class_nullable() async {
-    assertErrorCodesInCode('''
+    assertErrorsInCode('''
 class A {}
 class B extends A? {}
-''', [CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE]);
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE, 27, 2),
+    ]);
   }
 
   test_classAlias_withClass_nonNullable() async {
@@ -44,11 +46,13 @@
   }
 
   test_classAlias_withClass_nullable() async {
-    assertErrorCodesInCode('''
+    assertErrorsInCode('''
 class A {}
 class B {}
 class C = A? with B;
-''', [CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE]);
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE, 32, 2),
+    ]);
   }
 
   test_classAlias_withMixin_nonNullable() async {
@@ -60,10 +64,12 @@
   }
 
   test_classAlias_withMixin_nullable() async {
-    assertErrorCodesInCode('''
+    assertErrorsInCode('''
 class A {}
 mixin B {}
 class C = A? with B;
-''', [CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE]);
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE, 32, 2),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/nullable_type_in_implements_clause_test.dart b/pkg/analyzer/test/src/diagnostics/nullable_type_in_implements_clause_test.dart
index ec81d73..39ffb8e 100644
--- a/pkg/analyzer/test/src/diagnostics/nullable_type_in_implements_clause_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/nullable_type_in_implements_clause_test.dart
@@ -29,10 +29,12 @@
   }
 
   test_class_nullable() async {
-    assertErrorCodesInCode('''
+    assertErrorsInCode('''
 class A {}
 class B implements A? {}
-''', [CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE]);
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE, 30, 2),
+    ]);
   }
 
   test_mixin_nonNullable() async {
@@ -43,9 +45,11 @@
   }
 
   test_mixin_nullable() async {
-    assertErrorCodesInCode('''
+    assertErrorsInCode('''
 class A {}
 mixin B implements A? {}
-''', [CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE]);
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE, 30, 2),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/nullable_type_in_on_clause_test.dart b/pkg/analyzer/test/src/diagnostics/nullable_type_in_on_clause_test.dart
index d9613ee..60e319a 100644
--- a/pkg/analyzer/test/src/diagnostics/nullable_type_in_on_clause_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/nullable_type_in_on_clause_test.dart
@@ -29,9 +29,11 @@
   }
 
   test_nullable() async {
-    assertErrorCodesInCode('''
+    assertErrorsInCode('''
 class A {}
 mixin B on A? {}
-''', [CompileTimeErrorCode.NULLABLE_TYPE_IN_ON_CLAUSE]);
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_ON_CLAUSE, 22, 2),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/nullable_type_in_with_clause_test.dart b/pkg/analyzer/test/src/diagnostics/nullable_type_in_with_clause_test.dart
index d25ad1f..c05909c 100644
--- a/pkg/analyzer/test/src/diagnostics/nullable_type_in_with_clause_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/nullable_type_in_with_clause_test.dart
@@ -29,10 +29,12 @@
   }
 
   test_class_nullable() async {
-    assertErrorCodesInCode('''
+    assertErrorsInCode('''
 class A {}
 class B with A? {}
-''', [CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE]);
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE, 24, 2),
+    ]);
   }
 
   test_classAlias_withClass_nonNullable() async {
@@ -44,11 +46,13 @@
   }
 
   test_classAlias_withClass_nullable() async {
-    assertErrorCodesInCode('''
+    assertErrorsInCode('''
 class A {}
 class B {}
 class C = A with B?;
-''', [CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE]);
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE, 39, 2),
+    ]);
   }
 
   test_classAlias_withMixin_nonNullable() async {
@@ -60,10 +64,12 @@
   }
 
   test_classAlias_withMixin_nullable() async {
-    assertErrorCodesInCode('''
+    assertErrorsInCode('''
 class A {}
 mixin B {}
 class C = A with B?;
-''', [CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE]);
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE, 39, 2),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/override_equals_but_not_hashcode_test.dart b/pkg/analyzer/test/src/diagnostics/override_equals_but_not_hashcode_test.dart
index 7ecb535..7def0c4 100644
--- a/pkg/analyzer/test/src/diagnostics/override_equals_but_not_hashcode_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/override_equals_but_not_hashcode_test.dart
@@ -25,9 +25,11 @@
 
   @failingTest
   test_overrideEquals_andNotHashCode() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   bool operator ==(x) {}
-}''', [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE]);
+}''', [
+      error(HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE, 6, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart
index 514ad99..2a978fe 100644
--- a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart
@@ -16,7 +16,7 @@
 @reflectiveTest
 class OverrideOnNonOverridingFieldTest extends DriverResolutionTest {
   test_inInterface() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int get a => 0;
   void set b(_) {}
@@ -29,11 +29,13 @@
   int b;
   @override
   int c;
-}''', [CompileTimeErrorCode.INVALID_OVERRIDE]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 126, 5),
+    ]);
   }
 
   test_inSuperclass() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int get a => 0;
   void set b(_) {}
@@ -46,16 +48,20 @@
   int b;
   @override
   int c;
-}''', [CompileTimeErrorCode.INVALID_OVERRIDE]);
+}''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 123, 5),
+    ]);
   }
 
   test_invalid() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
 }
 class B extends A {
   @override
   final int m = 1;
-}''', [HintCode.OVERRIDE_ON_NON_OVERRIDING_FIELD]);
+}''', [
+      error(HintCode.OVERRIDE_ON_NON_OVERRIDING_FIELD, 56, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_getter_test.dart b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_getter_test.dart
index 58dfef6..3a3345c 100644
--- a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_getter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_getter_test.dart
@@ -38,12 +38,14 @@
   }
 
   test_invalid() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
 }
 class B extends A {
   @override
   int get m => 1;
-}''', [HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER]);
+}''', [
+      error(HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER, 54, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_method_test.dart b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_method_test.dart
index 608295d..19a2cbd 100644
--- a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_method_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_method_test.dart
@@ -65,12 +65,14 @@
   }
 
   test_invalid() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
 }
 class B extends A {
   @override
   int m() => 1;
-}''', [HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD]);
+}''', [
+      error(HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD, 50, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_setter_test.dart b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_setter_test.dart
index 0625741..748aa24 100644
--- a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_setter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_setter_test.dart
@@ -38,12 +38,14 @@
   }
 
   test_invalid() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
 }
 class B extends A {
   @override
   set m(int x) {}
-}''', [HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER]);
+}''', [
+      error(HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER, 50, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_constraint_verifier_support.dart b/pkg/analyzer/test/src/diagnostics/sdk_constraint_verifier_support.dart
index feb02f5..8bd294a 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_constraint_verifier_support.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_constraint_verifier_support.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.
 
-import 'package:analyzer/error/error.dart';
 import 'package:pub_semver/pub_semver.dart';
 
 import '../dart/resolution/driver_resolution.dart';
+import '../../generated/test_support.dart';
 
 /// A base class designed to be used by tests of the hints produced by the
 /// SdkConstraintVerifier.
@@ -13,10 +13,10 @@
   /// Verify that the [errorCodes] are produced if the [source] is analyzed in
   /// a context that specifies the minimum SDK version to be [version].
   verifyVersion(String version, String source,
-      {List<ErrorCode> errorCodes}) async {
+      {List<ExpectedError> expectedErrors}) async {
     driver.configure(
         analysisOptions: analysisOptions
           ..sdkVersionConstraint = VersionConstraint.parse(version));
-    await assertErrorCodesInCode(source, errorCodes ?? []);
+    await assertErrorsInCode(source, expectedErrors ?? []);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart
index b63e481..106093c 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart
@@ -23,7 +23,7 @@
     ..enabledExperiments = [EnableString.constant_update_2018];
 
   test_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const dynamic a = 2;
 const c = (a as int) + 2;
 ''');
@@ -33,6 +33,8 @@
     verifyVersion('2.2.0', '''
 const dynamic a = 2;
 const c = (a as int) + 2;
-''', errorCodes: [HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT, 32, 8),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_async_exported_from_core_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_async_exported_from_core_test.dart
index 7e04d6d..2a296e2 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_async_exported_from_core_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_async_exported_from_core_test.dart
@@ -72,7 +72,9 @@
 import 'dart:core' show Future, int;
 
 Future<int> zero() async => 0;
-''', errorCodes: [HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE, 38, 6),
+    ]);
   }
 
   test_lessThan_explicitImportOfExportingLibrary() async {
@@ -89,7 +91,9 @@
   test_lessThan_implicitImportOfCore() async {
     await verifyVersion('2.0.0', '''
 Future<int> zero() async => 0;
-''', errorCodes: [HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE, 0, 6),
+    ]);
   }
 
   test_lessThan_implicitImportOfCore_inPart() async {
@@ -100,7 +104,9 @@
 part of lib;
 
 Future<int> zero() async => 0;
-''', errorCodes: [HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE, 14, 6),
+    ]);
   }
 
   test_lessThan_onlyReferencedInExport_hide() async {
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart
index 1b16612..4183627 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart
@@ -22,7 +22,7 @@
     ..enabledExperiments = [EnableString.constant_update_2018];
 
   test_and_const_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const c = true & false;
 ''');
   }
@@ -30,7 +30,9 @@
   test_and_const_lessThan() {
     verifyVersion('2.2.0', '''
 const c = true & false;
-''', errorCodes: [HintCode.SDK_VERSION_BOOL_OPERATOR]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_BOOL_OPERATOR, 15, 1),
+    ]);
   }
 
   test_and_nonConst_equals() {
@@ -46,7 +48,7 @@
   }
 
   test_or_const_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const c = true | false;
 ''');
   }
@@ -54,7 +56,9 @@
   test_or_const_lessThan() {
     verifyVersion('2.2.0', '''
 const c = true | false;
-''', errorCodes: [HintCode.SDK_VERSION_BOOL_OPERATOR]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_BOOL_OPERATOR, 15, 1),
+    ]);
   }
 
   test_or_nonConst_equals() {
@@ -70,7 +74,7 @@
   }
 
   test_xor_const_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const c = true ^ false;
 ''');
   }
@@ -78,7 +82,9 @@
   test_xor_const_lessThan() {
     verifyVersion('2.2.0', '''
 const c = true ^ false;
-''', errorCodes: [HintCode.SDK_VERSION_BOOL_OPERATOR]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_BOOL_OPERATOR, 15, 1),
+    ]);
   }
 
   test_xor_nonConst_equals() {
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart
index 3d6b6ca..e1814bb 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart
@@ -22,7 +22,7 @@
     ..enabledExperiments = [EnableString.constant_update_2018];
 
   test_left_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 class A {
   const A();
 }
@@ -38,11 +38,13 @@
 }
 const A a = A();
 const c = a == null;
-''', errorCodes: [HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT, 54, 2),
+    ]);
   }
 
   test_right_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 class A {
   const A();
 }
@@ -58,6 +60,8 @@
 }
 const A a = A();
 const c = null == a;
-''', errorCodes: [HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT, 57, 2),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
index 5e5f140..ed8c441 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
@@ -24,9 +24,11 @@
   test_const_equals() {
     // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
     //  UNDEFINED_OPERATOR when triple_shift is enabled by default.
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const a = 42 >>> 3;
-''', errorCodes: [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+''', expectedErrors: [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 13, 3),
+    ]);
   }
 
   test_const_lessThan() {
@@ -34,14 +36,14 @@
     //  UNDEFINED_OPERATOR when triple_shift is enabled by default.
     verifyVersion('2.2.0', '''
 const a = 42 >>> 3;
-''', errorCodes: [
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
-      HintCode.SDK_VERSION_GT_GT_GT_OPERATOR
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_GT_GT_GT_OPERATOR, 13, 3),
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 13, 3),
     ]);
   }
 
   test_declaration_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 class A {
   A operator >>>(A a) => this;
 }
@@ -53,15 +55,19 @@
 class A {
   A operator >>>(A a) => this;
 }
-''', errorCodes: [HintCode.SDK_VERSION_GT_GT_GT_OPERATOR]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_GT_GT_GT_OPERATOR, 23, 3),
+    ]);
   }
 
   test_nonConst_equals() {
     // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
     //  UNDEFINED_OPERATOR when constant update is enabled by default.
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 var a = 42 >>> 3;
-''', errorCodes: [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+''', expectedErrors: [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 11, 3),
+    ]);
   }
 
   test_nonConst_lessThan() {
@@ -69,9 +75,9 @@
     //  UNDEFINED_OPERATOR when constant update is enabled by default.
     verifyVersion('2.2.0', '''
 var a = 42 >>> 3;
-''', errorCodes: [
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
-      HintCode.SDK_VERSION_GT_GT_GT_OPERATOR
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_GT_GT_GT_OPERATOR, 11, 3),
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 11, 3),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart
index 70778cf..fb7197a 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart
@@ -23,7 +23,7 @@
     ..enabledExperiments = [EnableString.constant_update_2018];
 
   test_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const dynamic a = 2;
 const c = a is int;
 ''');
@@ -33,6 +33,8 @@
     verifyVersion('2.2.0', '''
 const dynamic a = 2;
 const c = a is int;
-''', errorCodes: [HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT, 31, 8),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_never_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_never_test.dart
new file mode 100644
index 0000000..f9703db
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_never_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2018, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/dart/error/hint_codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'sdk_constraint_verifier_support.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SdkVersionNeverTest);
+  });
+}
+
+@reflectiveTest
+class SdkVersionNeverTest extends SdkConstraintVerifierTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @failingTest
+  test_equals() async {
+    // This test cannot pass because there is no version number that is equal to
+    // when non-nullable was enabled.
+    await verifyVersion('2.1.0', '''
+Never sink;
+''');
+  }
+
+  @failingTest
+  test_greaterThan() async {
+    // This test cannot pass because there is no version number that is equal to
+    // when non-nullable was enabled.
+    await verifyVersion('2.1.0', '''
+Never sink;
+''');
+  }
+
+  test_lessThan() async {
+    await verifyVersion('2.3.0', '''
+Never sink;
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_NEVER, 0, 5),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_set_literal_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_set_literal_test.dart
index 4a7b294..8164001 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_set_literal_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_set_literal_test.dart
@@ -30,6 +30,8 @@
   test_lessThan() async {
     await verifyVersion('2.1.0', '''
 Set<int> zero() => <int>{0};
-''', errorCodes: [HintCode.SDK_VERSION_SET_LITERAL]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_SET_LITERAL, 19, 8),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_ui_as_code_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_ui_as_code_test.dart
index d14a9a2..b75a1a6 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_ui_as_code_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_ui_as_code_test.dart
@@ -2,9 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'sdk_constraint_verifier_support.dart';
@@ -17,13 +15,6 @@
 
 @reflectiveTest
 class SdkVersionUiAsCodeTest extends SdkConstraintVerifierTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_equals() async {
     await verifyVersion('2.2.2', '''
 List<int> zero() => [for (var e in [0]) e];
@@ -39,6 +30,8 @@
   test_lessThan() async {
     await verifyVersion('2.2.1', '''
 List<int> zero() => [if (0 < 1) 0];
-''', errorCodes: [HintCode.SDK_VERSION_UI_AS_CODE]);
+''', expectedErrors: [
+      error(HintCode.SDK_VERSION_UI_AS_CODE, 21, 12),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
index 1a71c80..caac598 100644
--- a/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
@@ -12,18 +12,116 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SetElementTypeNotAssignableTest);
-    defineReflectiveTests(
-        SetElementTypeNotAssignableWithUiAsCodeAndConstantTest);
-    defineReflectiveTests(SetElementTypeNotAssignableWithUIAsCodeTest);
+    defineReflectiveTests(SetElementTypeNotAssignableWithConstantTest);
   });
 }
 
 @reflectiveTest
 class SetElementTypeNotAssignableTest extends DriverResolutionTest {
+  test_const_ifElement_thenElseFalse_intInt() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <int>{if (1 < 0) a else b};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 62, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenElseFalse_intString() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <int>{if (1 < 0) a else b};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 82, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 64, 19),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_intString() async {
+    await assertErrorsInCode(
+        '''
+var v = const <int>{if (1 < 0) 'a'};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 31, 3),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 20, 14),
+                error(StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 31, 3),
+              ]);
+  }
+
+  test_const_ifElement_thenFalse_intString_dynamic() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 'a';
+var v = const <int>{if (1 < 0) a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 43, 12),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_intInt() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 0;
+var v = const <int>{if (true) a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 11),
+              ]);
+  }
+
+  test_const_ifElement_thenTrue_intString() async {
+    await assertErrorsInCode(
+        '''
+const dynamic a = 'a';
+var v = const <int>{if (true) a};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? [
+                error(StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 53, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 43, 11),
+              ]);
+  }
+
+  test_const_spread_intInt() async {
+    await assertErrorsInCode(
+        '''
+var v = const <int>{...[0, 1]};
+''',
+        analysisOptions.experimentStatus.constant_update_2018
+            ? []
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 20, 9),
+              ]);
+  }
+
   test_explicitTypeArgs_const() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <String>{42};
-''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 23, 2),
+    ]);
   }
 
   test_explicitTypeArgs_const_actualTypeMatch() async {
@@ -34,119 +132,20 @@
   }
 
   test_explicitTypeArgs_const_actualTypeMismatch() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const dynamic x = 42;
 var v = const <String>{x};
-''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 45, 1),
+    ]);
   }
 
   test_explicitTypeArgs_notConst() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <String>{42};
-''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
-  }
-}
-
-@reflectiveTest
-class SetElementTypeNotAssignableWithUiAsCodeAndConstantTest
-    extends SetElementTypeNotAssignableWithUIAsCodeTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-      EnableString.constant_update_2018
-    ];
-}
-
-@reflectiveTest
-class SetElementTypeNotAssignableWithUIAsCodeTest
-    extends SetElementTypeNotAssignableTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
-  test_const_ifElement_thenElseFalse_intInt() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-const dynamic b = 0;
-var v = const <int>{if (1 < 0) a else b};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenElseFalse_intString() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-const dynamic b = 'b';
-var v = const <int>{if (1 < 0) a else b};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenFalse_intString() async {
-    await assertErrorCodesInCode(
-        '''
-var v = const <int>{if (1 < 0) 'a'};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]
-            : [
-                StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE,
-                CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT
-              ]);
-  }
-
-  test_const_ifElement_thenFalse_intString_dynamic() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 'a';
-var v = const <int>{if (1 < 0) a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_intInt() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 0;
-var v = const <int>{if (true) a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_ifElement_thenTrue_intString() async {
-    await assertErrorCodesInCode(
-        '''
-const dynamic a = 'a';
-var v = const <int>{if (true) a};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_spread_intInt() async {
-    await assertErrorCodesInCode(
-        '''
-var v = const <int>{...[0, 1]};
-''',
-        analysisOptions.experimentStatus.constant_update_2018
-            ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+''', [
+      error(StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 17, 2),
+    ]);
   }
 
   test_nonConst_ifElement_thenElseFalse_intDynamic() async {
@@ -166,9 +165,11 @@
   }
 
   test_nonConst_ifElement_thenFalse_intString() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <int>[if (1 < 0) 'a'];
-''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 25, 3),
+    ]);
   }
 
   test_nonConst_ifElement_thenTrue_intDynamic() async {
@@ -191,3 +192,11 @@
 ''');
   }
 }
+
+@reflectiveTest
+class SetElementTypeNotAssignableWithConstantTest
+    extends SetElementTypeNotAssignableTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 56a1409..bf27038 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -22,12 +22,21 @@
     as const_spread_expected_list_or_set;
 import 'const_spread_expected_map_test.dart' as const_spread_expected_map;
 import 'dead_code_test.dart' as dead_code;
+import 'default_list_constructor_mismatch_test.dart'
+    as default_list_constructor_mismatch;
+import 'default_value_on_required_parameter_test.dart'
+    as default_value_on_required_paramter;
 import 'deprecated_member_use_test.dart' as deprecated_member_use;
 import 'division_optimization_test.dart' as division_optimization;
 import 'duplicate_import_test.dart' as duplicate_import;
 import 'equal_elements_in_const_set_test.dart' as equal_elements_in_const_set;
 import 'equal_keys_in_const_map_test.dart' as equal_keys_in_const_map;
 import 'expression_in_map_test.dart' as expression_in_map;
+import 'extends_non_class_test.dart' as extends_non_class;
+import 'final_not_initialized_test.dart' as final_not_initialized;
+import 'implements_non_class_test.dart' as implements_non_class;
+import 'implicit_this_reference_in_initializer_test.dart'
+    as implicit_this_reference_in_initializer;
 import 'import_deferred_library_with_load_function_test.dart'
     as import_deferred_library_with_load_function;
 import 'invalid_assignment_test.dart' as invalid_assignment;
@@ -36,6 +45,8 @@
 import 'invalid_factory_method_impl_test.dart' as invalid_factory_method_impl;
 import 'invalid_immutable_annotation_test.dart' as invalid_immutable_annotation;
 import 'invalid_literal_annotation_test.dart' as invalid_literal_annotation;
+import 'invalid_optional_parameter_type_test.dart'
+    as invalid_optional_parameter_type;
 import 'invalid_override_different_default_values_named_test.dart'
     as invalid_override_different_default_values_named;
 import 'invalid_override_different_default_values_positional_test.dart'
@@ -56,9 +67,14 @@
 import 'map_key_type_not_assignable_test.dart' as map_key_type_not_assignable;
 import 'map_value_type_not_assignable_test.dart'
     as map_value_type_not_assignable;
+import 'missing_default_value_for_parameter_test.dart'
+    as missing_default_value_for_paramter;
 import 'missing_required_param_test.dart' as missing_required_param;
 import 'missing_return_test.dart' as missing_return;
+import 'mixin_of_non_class_test.dart' as mixin_of_non_class;
 import 'mixin_on_sealed_class_test.dart' as mixin_on_sealed_class;
+import 'mixin_super_class_constraint_non_interface_test.dart'
+    as mixin_super_class_constraint_non_interface;
 import 'must_be_immutable_test.dart' as must_be_immutable;
 import 'must_call_super_test.dart' as must_call_super;
 import 'non_bool_condition_test.dart' as non_bool_condition;
@@ -79,6 +95,7 @@
 import 'non_constant_set_element_test.dart' as non_constant_set_element;
 import 'non_constant_spread_expression_from_deferred_library_test.dart'
     as non_constant_spread_expression_from_deferred_library;
+import 'non_null_opt_out_test.dart' as non_null_opt_out;
 import 'not_iterable_spread_test.dart' as not_iterable_spread;
 import 'not_map_spread_test.dart' as not_map_spread;
 import 'not_null_aware_null_spread_test.dart' as not_null_aware_null_spread;
@@ -114,6 +131,7 @@
     as sdk_version_gt_gt_gt_operator;
 import 'sdk_version_is_expression_in_const_context_test.dart'
     as sdk_version_is_expression_in_const_context;
+import 'sdk_version_never_test.dart' as sdk_version_never;
 import 'sdk_version_set_literal_test.dart' as sdk_version_set_literal;
 import 'sdk_version_ui_as_code_test.dart' as sdk_version_ui_as_code;
 import 'set_element_type_not_assignable_test.dart'
@@ -147,6 +165,8 @@
 import 'unused_shown_name_test.dart' as unused_shown_name;
 import 'use_of_void_result_test.dart' as use_of_void_result;
 import 'variable_type_mismatch_test.dart' as variable_type_mismatch;
+import 'wrong_type_parameter_variance_in_superinterface_test.dart'
+    as wrong_type_parameter_variance_in_superinterface;
 
 main() {
   defineReflectiveSuite(() {
@@ -162,12 +182,18 @@
     const_spread_expected_list_or_set.main();
     const_spread_expected_map.main();
     dead_code.main();
+    default_list_constructor_mismatch.main();
+    default_value_on_required_paramter.main();
     deprecated_member_use.main();
     division_optimization.main();
     duplicate_import.main();
     equal_elements_in_const_set.main();
     equal_keys_in_const_map.main();
     expression_in_map.main();
+    extends_non_class.main();
+    final_not_initialized.main();
+    implements_non_class.main();
+    implicit_this_reference_in_initializer.main();
     import_deferred_library_with_load_function.main();
     invalid_assignment.main();
     invalid_cast_new_expr.main();
@@ -175,6 +201,7 @@
     invalid_factory_method_impl.main();
     invalid_immutable_annotation.main();
     invalid_literal_annotation.main();
+    invalid_optional_parameter_type.main();
     invalid_override_different_default_values_named.main();
     invalid_override_different_default_values_positional.main();
     invalid_required_param.main();
@@ -187,9 +214,12 @@
     map_entry_not_in_map.main();
     map_key_type_not_assignable.main();
     map_value_type_not_assignable.main();
+    missing_default_value_for_paramter.main();
     missing_required_param.main();
     missing_return.main();
+    mixin_of_non_class.main();
     mixin_on_sealed_class.main();
+    mixin_super_class_constraint_non_interface.main();
     must_be_immutable.main();
     must_call_super.main();
     non_bool_condition.main();
@@ -204,6 +234,7 @@
     non_constant_set_element.main();
     non_constant_set_element_from_deferred_library.main();
     non_constant_spread_expression_from_deferred_library.main();
+    non_null_opt_out.main();
     not_iterable_spread.main();
     not_map_spread.main();
     not_null_aware_null_spread.main();
@@ -226,6 +257,7 @@
     sdk_version_eq_eq_operator.main();
     sdk_version_gt_gt_gt_operator.main();
     sdk_version_is_expression_in_const_context.main();
+    sdk_version_never.main();
     sdk_version_set_literal.main();
     sdk_version_ui_as_code.main();
     set_element_type_not_assignable.main();
@@ -257,5 +289,6 @@
     unused_shown_name.main();
     use_of_void_result.main();
     variable_type_mismatch.main();
+    wrong_type_parameter_variance_in_superinterface.main();
   }, name: 'diagnostics');
 }
diff --git a/pkg/analyzer/test/src/diagnostics/top_level_instance_getter_test.dart b/pkg/analyzer/test/src/diagnostics/top_level_instance_getter_test.dart
index 8427700..ceb09b7 100644
--- a/pkg/analyzer/test/src/diagnostics/top_level_instance_getter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/top_level_instance_getter_test.dart
@@ -52,6 +52,19 @@
     expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
   }
 
+  test_field_imported() async {
+    newFile('/test/lib/a.dart', content: '''
+class A {
+  int f;
+}
+''');
+    await assertNoErrorsInCode('''
+import 'a.dart';
+var b = new A().f;
+''');
+    assertElementTypeString(findElement.topVar('b').type, 'int');
+  }
+
   test_field_prefixedIdentifier() async {
     await assertNoErrorsInCode('''
 class A {
@@ -76,64 +89,76 @@
   }
 
   test_implicitlyTyped() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   get g => 0;
 }
 var b = new A().g;
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 42, 1),
+    ]);
   }
 
   test_implicitlyTyped_call() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   get g => () => 0;
 }
 var a = new A();
 var b = a.g();
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 57, 5),
+    ]);
   }
 
   test_implicitlyTyped_field() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   var g = 0;
 }
 var b = new A().g;
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 41, 1),
+    ]);
   }
 
   test_implicitlyTyped_field_call() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   var g = () => 0;
 }
 var a = new A();
 var b = a.g();
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 56, 5),
+    ]);
   }
 
   test_implicitlyTyped_field_prefixedIdentifier() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   var g = 0;
 }
 var a = new A();
 var b = a.g;
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 52, 1),
+    ]);
   }
 
   test_implicitlyTyped_fn() async {
     // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because f is
     // generic, so the type of a.x might affect the type of b.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   var x = 0;
 }
 int f<T>(x) => 0;
 var a = new A();
 var b = f(a.x);
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 72, 1),
+    ]);
   }
 
   test_implicitlyTyped_fn_explicit_type_params() async {
@@ -178,13 +203,15 @@
   test_implicitlyTyped_invoke() async {
     // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because the
     // closure is generic, so the type of a.x might affect the type of b.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   var x = 0;
 }
 var a = new A();
 var b = (<T>(y) => 0)(a.x);
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 66, 1),
+    ]);
   }
 
   test_implicitlyTyped_invoke_explicit_type_params() async {
@@ -214,14 +241,16 @@
   test_implicitlyTyped_method() async {
     // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because f is
     // generic, so the type of a.x might affect the type of b.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   var x = 0;
   int f<T>(int x) => 0;
 }
 var a = new A();
 var b = a.f(a.x);
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 80, 1),
+    ]);
   }
 
   test_implicitlyTyped_method_explicit_type_params() async {
@@ -253,7 +282,7 @@
   test_implicitlyTyped_new() async {
     // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because B is
     // generic, so the type of a.x might affect the type of b.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   var x = 0;
 }
@@ -262,7 +291,9 @@
 }
 var a = new A();
 var b = new B(a.x);
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 81, 1),
+    ]);
   }
 
   test_implicitlyTyped_new_explicit_type_params() async {
@@ -316,7 +347,7 @@
   test_implicitlyTyped_new_named() async {
     // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because B is
     // generic, so the type of a.x might affect the type of b.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   var x = 0;
 }
@@ -325,7 +356,9 @@
 }
 var a = new A();
 var b = new B.named(a.x);
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 93, 1),
+    ]);
   }
 
   test_implicitlyTyped_new_not_generic() async {
@@ -384,30 +417,34 @@
 ''');
     // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because B is
     // generic, so the type of a.x might affect the type of b.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 import 'lib1.dart' as foo;
 class A {
   var x = 0;
 }
 var a = new A();
 var b = new foo.B(a.x);
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 89, 1),
+    ]);
   }
 
   test_implicitlyTyped_prefixedIdentifier() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   get g => 0;
 }
 var a = new A();
 var b = a.g;
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 53, 1),
+    ]);
   }
 
   test_implicitlyTyped_propertyAccessLhs() async {
     // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because the type
     // of a.x affects the lookup of y, which in turn affects the type of b.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   var x = new B();
   int operator[](int value) => 0;
@@ -417,7 +454,9 @@
 }
 var a = new A();
 var b = (a.x).y;
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 114, 1),
+    ]);
   }
 
   test_prefixedIdentifier() async {
diff --git a/pkg/analyzer/test/src/diagnostics/top_level_instance_method_test.dart b/pkg/analyzer/test/src/diagnostics/top_level_instance_method_test.dart
index 221a7f0..00a78e1 100644
--- a/pkg/analyzer/test/src/diagnostics/top_level_instance_method_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/top_level_instance_method_test.dart
@@ -16,12 +16,14 @@
 @reflectiveTest
 class TopLevelInstanceMethodTest extends DriverResolutionTest {
   test_noParameter() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   f() => 0;
 }
 var x = new A().f();
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, 32, 11),
+    ]);
   }
 
   test_parameter() async {
@@ -34,12 +36,14 @@
   }
 
   test_parameter_generic() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   int f<T>(v) => 0;
 }
 var x = new A().f(0);
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, 40, 12),
+    ]);
   }
 
   test_parameter_generic_explicit() async {
@@ -61,21 +65,25 @@
   }
 
   test_tearOff() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   f() => 0;
 }
 var x = new A().f;
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, 40, 1),
+    ]);
   }
 
   test_tearOff_parameter() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class A {
   int f(v) => 0;
 }
 var x = new A().f;
-''', [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
+''', [
+      error(StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, 45, 1),
+    ]);
   }
 
   test_tearoff_static() async {
diff --git a/pkg/analyzer/test/src/diagnostics/type_check_is_not_null_test.dart b/pkg/analyzer/test/src/diagnostics/type_check_is_not_null_test.dart
index 9a473f0..e5e14a3 100644
--- a/pkg/analyzer/test/src/diagnostics/type_check_is_not_null_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_check_is_not_null_test.dart
@@ -16,10 +16,12 @@
 @reflectiveTest
 class TypeCheckIsNotNullTest extends DriverResolutionTest {
   test_not_Null() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 bool m(i) {
   return i is! Null;
 }
-''', [HintCode.TYPE_CHECK_IS_NOT_NULL]);
+''', [
+      error(HintCode.TYPE_CHECK_IS_NOT_NULL, 21, 10),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/type_check_is_null_test.dart b/pkg/analyzer/test/src/diagnostics/type_check_is_null_test.dart
index 42d8555..19d804b 100644
--- a/pkg/analyzer/test/src/diagnostics/type_check_is_null_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_check_is_null_test.dart
@@ -16,10 +16,12 @@
 @reflectiveTest
 class TypeCheckIsNullTest extends DriverResolutionTest {
   test_is_Null() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 bool m(i) {
   return i is Null;
 }
-''', [HintCode.TYPE_CHECK_IS_NULL]);
+''', [
+      error(HintCode.TYPE_CHECK_IS_NULL, 21, 9),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart b/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
index ce2c1f0..6dc6cfc 100644
--- a/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
@@ -31,12 +31,14 @@
   }
 
   test_and_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   bool? x;
   if(x && true) {}
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 22, 1),
+    ]);
   }
 
   test_as_nullable() async {
@@ -48,6 +50,26 @@
 ''');
   }
 
+  test_assert_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  bool x = true;
+  assert(x);
+}
+''');
+  }
+
+  test_assert_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  bool? x;
+  assert(x);
+}
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 26, 1),
+    ]);
+  }
+
   test_await_nonNullable() async {
     await assertNoErrorsInCode(r'''
 m() async {
@@ -76,12 +98,14 @@
   }
 
   test_cascade_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   x..isEven;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+    ]);
   }
 
   test_eq_nullable() async {
@@ -103,12 +127,15 @@
   }
 
   test_forLoop_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   List? x;
   for (var y in x) {}
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 28, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 33, 1),
+    ]);
   }
 
   test_if_nonNullable() async {
@@ -121,12 +148,14 @@
   }
 
   test_if_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   bool? x;
   if (x) {}
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 23, 1),
+    ]);
   }
 
   test_index_nonNullable() async {
@@ -139,12 +168,14 @@
   }
 
   test_index_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   List? x;
   x[0];
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 19, 1),
+    ]);
   }
 
   test_invoke_dynamicFunctionType_nonNullable() async {
@@ -156,16 +187,15 @@
 ''');
   }
 
-  @failingTest
   test_invoke_dynamicFunctionType_nullable() async {
-    // test is failing because nullable function invocations aren't being
-    // resolved correctly
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   Function? x;
   x();
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 23, 1),
+    ]);
   }
 
   test_invoke_nonNullable() async {
@@ -177,16 +207,15 @@
 ''');
   }
 
-  @failingTest
   test_invoke_nullable() async {
-    // test is failing because nullable function invocations aren't being
-    // resolved correctly
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   Function()? x;
   x();
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 25, 1),
+    ]);
   }
 
   test_invoke_parenthesized_nonNullable() async {
@@ -207,6 +236,15 @@
 ''');
   }
 
+  test_member_dynamic_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  dynamic x;
+  x.foo;
+}
+''');
+  }
+
   test_member_hashCode_nullable() async {
     await assertNoErrorsInCode(r'''
 m() {
@@ -226,12 +264,14 @@
   }
 
   test_member_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   x.isEven;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+    ]);
   }
 
   test_member_parenthesized_hashCode_nullable() async {
@@ -244,12 +284,14 @@
   }
 
   test_member_parenthesized_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   (x).isEven;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 3),
+    ]);
   }
 
   test_member_parenthesized_runtimeType_nullable() async {
@@ -261,6 +303,28 @@
 ''');
   }
 
+  test_member_potentiallyNullable() async {
+    await assertErrorsInCode(r'''
+m<T extends int?>() {
+  T x;
+  x.isEven;
+}
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 31, 1),
+    ]);
+  }
+
+  test_member_potentiallyNullable_called() async {
+    await assertErrorsInCode(r'''
+m<T extends Function>() {
+  List<T?> x;
+  x.first();
+}
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 44, 5),
+    ]);
+  }
+
   test_member_questionDot_nullable() async {
     await assertNoErrorsInCode(r'''
 m() {
@@ -292,18 +356,20 @@
     await assertNoErrorsInCode(r'''
 m() {
   int x;
-  x.noSuchMethod(null);
+  x.noSuchMethod(throw '');
 }
 ''');
   }
 
   test_method_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   x.round();
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+    ]);
   }
 
   test_method_questionDot_nullable() async {
@@ -334,12 +400,15 @@
   }
 
   test_minusEq_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   x -= 1;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+    ]);
   }
 
   test_not_nonNullable() async {
@@ -352,12 +421,14 @@
   }
 
   test_not_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   bool? x;
   if(!x) {}
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 23, 1),
+    ]);
   }
 
   test_notEq_nullable() async {
@@ -379,12 +450,14 @@
   }
 
   test_operatorMinus_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   x - 3;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+    ]);
   }
 
   test_operatorPlus_nonNullable() async {
@@ -397,12 +470,14 @@
   }
 
   test_operatorPlus_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   x + 3;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+    ]);
   }
 
   test_operatorPostfixDec_nonNullable() async {
@@ -415,12 +490,15 @@
   }
 
   test_operatorPostfixDec_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   x--;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+    ]);
   }
 
   test_operatorPostfixInc_nonNullable() async {
@@ -433,12 +511,15 @@
   }
 
   test_operatorPostfixInc_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   x++;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+    ]);
   }
 
   test_operatorPrefixDec_nonNullable() async {
@@ -451,12 +532,15 @@
   }
 
   test_operatorPrefixDec_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   --x;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 20, 1),
+    ]);
   }
 
   test_operatorPrefixInc_nonNullable() async {
@@ -469,12 +553,15 @@
   }
 
   test_operatorPrefixInc_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   ++x;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 20, 1),
+    ]);
   }
 
   test_operatorUnaryMinus_nonNullable() async {
@@ -487,12 +574,15 @@
   }
 
   test_operatorUnaryMinus_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   -x;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 19, 1),
+    ]);
   }
 
   test_or_nonNullable() async {
@@ -505,12 +595,14 @@
   }
 
   test_or_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   bool? x;
   if(x || false) {}
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 22, 1),
+    ]);
   }
 
   test_plusEq_nonNullable() async {
@@ -523,21 +615,26 @@
   }
 
   test_plusEq_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   int? x;
   x += 1;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+    ]);
   }
 
   test_ternary_condition_nullable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   bool? x;
   x ? 0 : 1;
 }
-''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 19, 1),
+    ]);
   }
 
   test_ternary_lhs_nullable() async {
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
index e2ace47b..6feaae5 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
@@ -2,9 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -12,20 +10,75 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(UndefinedGetterTest);
-    defineReflectiveTests(UndefinedGetterWithControlFlowCollectionsTest);
   });
 }
 
 @reflectiveTest
 class UndefinedGetterTest extends DriverResolutionTest {
+  test_ifElement_inList_notPromoted() async {
+    await assertErrorsInCode('''
+f(int x) {
+  return [if (x is String) x.length];
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 40, 6),
+    ]);
+  }
+
+  test_ifElement_inList_promoted() async {
+    await assertNoErrorsInCode('''
+f(Object x) {
+  return [if (x is String) x.length];
+}
+''');
+  }
+
+  test_ifElement_inMap_notPromoted() async {
+    await assertErrorsInCode('''
+f(int x) {
+  return {if (x is String) x : x.length};
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 44, 6),
+    ]);
+  }
+
+  test_ifElement_inMap_promoted() async {
+    await assertNoErrorsInCode('''
+f(Object x) {
+  return {if (x is String) x : x.length};
+}
+''');
+  }
+
+  test_ifElement_inSet_notPromoted() async {
+    await assertErrorsInCode('''
+f(int x) {
+  return {if (x is String) x.length};
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 40, 6),
+    ]);
+  }
+
+  test_ifElement_inSet_promoted() async {
+    await assertNoErrorsInCode('''
+f(Object x) {
+  return {if (x is String) x.length};
+}
+''');
+  }
+
   test_ifStatement_notPromoted() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 f(int x) {
   if (x is String) {
     x.length;
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 38, 6),
+    ]);
   }
 
   test_ifStatement_promoted() async {
@@ -39,68 +92,14 @@
   }
 
   test_promotedTypeParameter_regress35305() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 void f<X extends num, Y extends X>(Y y) {
   if (y is int) {
     y.isEven;
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
-  }
-}
-
-@reflectiveTest
-class UndefinedGetterWithControlFlowCollectionsTest
-    extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [EnableString.control_flow_collections];
-
-  test_ifElement_inList_notPromoted() async {
-    await assertErrorCodesInCode('''
-f(int x) {
-  return [if (x is String) x.length];
-}
-''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
-  }
-
-  test_ifElement_inList_promoted() async {
-    await assertNoErrorsInCode('''
-f(Object x) {
-  return [if (x is String) x.length];
-}
-''');
-  }
-
-  test_ifElement_inMap_notPromoted() async {
-    await assertErrorCodesInCode('''
-f(int x) {
-  return {if (x is String) x : x.length};
-}
-''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
-  }
-
-  test_ifElement_inMap_promoted() async {
-    await assertNoErrorsInCode('''
-f(Object x) {
-  return {if (x is String) x : x.length};
-}
-''');
-  }
-
-  test_ifElement_inSet_notPromoted() async {
-    await assertErrorCodesInCode('''
-f(int x) {
-  return {if (x is String) x.length};
-}
-''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
-  }
-
-  test_ifElement_inSet_promoted() async {
-    await assertNoErrorsInCode('''
-f(Object x) {
-  return {if (x is String) x.length};
-}
-''');
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 66, 6),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_hidden_name_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_hidden_name_test.dart
index 888721c..94e0131 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_hidden_name_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_hidden_name_test.dart
@@ -17,15 +17,20 @@
 class UndefinedHiddenNameTest extends DriverResolutionTest {
   test_export() async {
     newFile('/test/lib/lib1.dart');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 export 'lib1.dart' hide a;
-''', [HintCode.UNDEFINED_HIDDEN_NAME]);
+''', [
+      error(HintCode.UNDEFINED_HIDDEN_NAME, 24, 1),
+    ]);
   }
 
   test_import() async {
     newFile('/test/lib/lib1.dart');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' hide a;
-''', [HintCode.UNUSED_IMPORT, HintCode.UNDEFINED_HIDDEN_NAME]);
+''', [
+      error(HintCode.UNUSED_IMPORT, 7, 11),
+      error(HintCode.UNDEFINED_HIDDEN_NAME, 24, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
index 7b44210..895322a 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
@@ -2,9 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -12,12 +10,30 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(UndefinedIdentifierTest);
-    defineReflectiveTests(UndefinedIdentifierWithControlFlowCollectionsTest);
   });
 }
 
 @reflectiveTest
 class UndefinedIdentifierTest extends DriverResolutionTest {
+  test_forElement_inList_insideElement() async {
+    await assertNoErrorsInCode('''
+f(Object x) {
+  return [for(int x in []) x, null];
+}
+''');
+  }
+
+  test_forElement_inList_outsideElement() async {
+    await assertErrorsInCode('''
+f() {
+  return [for (int x in []) null, x];
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 25, 1),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 40, 1),
+    ]);
+  }
+
   test_forStatement_inBody() async {
     await assertNoErrorsInCode('''
 f() {
@@ -29,35 +45,14 @@
   }
 
   test_forStatement_outsideBody() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 f() {
   for (int x in []) {}
   x;
 }
-''', [StaticWarningCode.UNDEFINED_IDENTIFIER]);
-  }
-}
-
-@reflectiveTest
-class UndefinedIdentifierWithControlFlowCollectionsTest
-    extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [EnableString.control_flow_collections];
-
-  test_forElement_inList_insideElement() async {
-    await assertNoErrorsInCode('''
-f(Object x) {
-  return [for(int x in []) x, null];
-}
-''');
-  }
-
-  test_forElement_inList_outsideElement() async {
-    await assertErrorCodesInCode('''
-f() {
-  return [for (int x in []) null, x];
-}
-''', [StaticWarningCode.UNDEFINED_IDENTIFIER]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 31, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_operator_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_operator_test.dart
index a10a3ee..8ce6206 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_operator_test.dart
@@ -16,18 +16,20 @@
 @reflectiveTest
 class UndefinedOperatorTest extends DriverResolutionTest {
   test_binaryExpression() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 f(var a) {
   if (a is A) {
     a + 1;
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 44, 1),
+    ]);
   }
 
   test_binaryExpression_inSubtype() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 class B extends A {
   operator +(B b) {}
@@ -37,11 +39,13 @@
     a + 1;
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 87, 1),
+    ]);
   }
 
   test_indexBoth() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 f(var a) {
   if (a is A) {
@@ -49,13 +53,13 @@
   }
 }
 ''', [
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 43, 3),
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 43, 3),
     ]);
   }
 
   test_indexBoth_inSubtype() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 class B extends A {
   operator [](int index) {}
@@ -66,24 +70,26 @@
   }
 }
 ''', [
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 93, 3),
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 93, 3),
     ]);
   }
 
   test_indexGetter() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 f(var a) {
   if (a is A) {
     a[0];
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 43, 3),
+    ]);
   }
 
   test_indexGetter_inSubtype() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 class B extends A {
   operator [](int index) {}
@@ -93,22 +99,26 @@
     a[0];
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 93, 3),
+    ]);
   }
 
   test_indexSetter() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 f(var a) {
   if (a is A) {
     a[0] = 1;
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 43, 3),
+    ]);
   }
 
   test_indexSetter_inSubtype() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 class B extends A {
   operator []=(i, v) {}
@@ -118,7 +128,9 @@
     a[0] = 1;
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 89, 3),
+    ]);
   }
 
   test_postfixExpression() async {
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_prefixed_name_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_prefixed_name_test.dart
index 6de8429..3485b60 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_prefixed_name_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_prefixed_name_test.dart
@@ -17,19 +17,23 @@
 class UndefinedPrefixedNameTest extends DriverResolutionTest {
   test_getterContext() async {
     newFile('/test/lib/lib.dart');
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 import 'lib.dart' as p;
 f() => p.c;
-''', [StaticTypeWarningCode.UNDEFINED_PREFIXED_NAME]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_PREFIXED_NAME, 33, 1),
+    ]);
   }
 
   test_setterContext() async {
     newFile('/test/lib/lib.dart');
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 import 'lib.dart' as p;
 f() {
   p.c = 0;
 }
-''', [StaticTypeWarningCode.UNDEFINED_PREFIXED_NAME]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_PREFIXED_NAME, 34, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart
index 7306c0e..827b77e 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart
@@ -16,7 +16,7 @@
 @reflectiveTest
 class UndefinedSetterTest extends DriverResolutionTest {
   test_inSubtype() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 class B extends A {
   set b(x) {}
@@ -26,17 +26,21 @@
     a.b = 0;
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_SETTER]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_SETTER, 80, 1),
+    ]);
   }
 
   test_inType() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {}
 f(var a) {
   if(a is A) {
     a.m = 0;
   }
 }
-''', [StaticTypeWarningCode.UNDEFINED_SETTER]);
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_SETTER, 43, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_shown_name_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_shown_name_test.dart
index 3243bb2..121fbda 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_shown_name_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_shown_name_test.dart
@@ -17,15 +17,20 @@
 class UndefinedShownNameTest extends DriverResolutionTest {
   test_export() async {
     newFile('/test/lib/lib1.dart');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 export 'lib1.dart' show a;
-''', [HintCode.UNDEFINED_SHOWN_NAME]);
+''', [
+      error(HintCode.UNDEFINED_SHOWN_NAME, 24, 1),
+    ]);
   }
 
   test_import() async {
     newFile('/test/lib/lib1.dart');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' show a;
-''', [HintCode.UNUSED_IMPORT, HintCode.UNDEFINED_SHOWN_NAME]);
+''', [
+      error(HintCode.UNUSED_IMPORT, 7, 11),
+      error(HintCode.UNDEFINED_SHOWN_NAME, 24, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart
index 0d89796..a7a5c1a 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart
@@ -59,13 +59,15 @@
 
   test_generics() async {
     // dartbug.com/18953
-    assertErrorCodesInCode(r'''
+    assertErrorsInCode(r'''
 import 'dart:async';
 Future<int> f() => new Future.value(0);
 void g(bool c) {
   (c ? f(): new Future.value(0) as Future<int>).then((int value) {});
 }
-''', [HintCode.UNNECESSARY_CAST]);
+''', [
+      error(HintCode.UNNECESSARY_CAST, 90, 34),
+    ]);
   }
 
   test_parameter_A() async {
@@ -92,18 +94,24 @@
   }
 
   test_type_supertype() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(int i) {
   var b = i as Object;
 }
-''', [HintCode.UNNECESSARY_CAST]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(HintCode.UNNECESSARY_CAST, 21, 11),
+    ]);
   }
 
   test_type_type() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(num i) {
   var b = i as num;
 }
-''', [HintCode.UNNECESSARY_CAST]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(HintCode.UNNECESSARY_CAST, 21, 8),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_no_such_method_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_no_such_method_test.dart
index 0801ae0..d443e12 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_no_such_method_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_no_such_method_test.dart
@@ -16,7 +16,7 @@
 @reflectiveTest
 class UnnecessaryNoSuchMethodTest extends DriverResolutionTest {
   test_blockBody() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   noSuchMethod(x) => super.noSuchMethod(x);
 }
@@ -26,7 +26,9 @@
     return super.noSuchMethod(y);
   }
 }
-''', [HintCode.UNNECESSARY_NO_SUCH_METHOD]);
+''', [
+      error(HintCode.UNNECESSARY_NO_SUCH_METHOD, 87, 55),
+    ]);
   }
 
   test_blockBody_notReturnStatement() async {
@@ -59,7 +61,7 @@
   }
 
   test_expressionBody() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   noSuchMethod(x) => super.noSuchMethod(x);
 }
@@ -67,7 +69,9 @@
   mmm();
   noSuchMethod(y) => super.noSuchMethod(y);
 }
-''', [HintCode.UNNECESSARY_NO_SUCH_METHOD]);
+''', [
+      error(HintCode.UNNECESSARY_NO_SUCH_METHOD, 87, 41),
+    ]);
   }
 
   test_expressionBody_notNoSuchMethod() async {
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_null_aware_call_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_null_aware_call_test.dart
index 6ca3733..a1aa080 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_null_aware_call_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_null_aware_call_test.dart
@@ -4,9 +4,10 @@
 
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../generated/resolver_test_case.dart';
+import '../dart/resolution/driver_resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -15,9 +16,10 @@
 }
 
 @reflectiveTest
-class UnnecessaryNullAwareCallTest extends ResolverTestCase {
+class UnnecessaryNullAwareCallTest extends DriverResolutionTest {
   @override
-  List<String> get enabledExperiments => [EnableString.non_nullable];
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
 
   test_getter_parenthesized_nonNull() async {
     await assertErrorsInCode('''
@@ -28,7 +30,9 @@
   int x;
   (x)?.isEven;
 }
-''', [HintCode.UNNECESSARY_NULL_AWARE_CALL]);
+''', [
+      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 67, 2),
+    ]);
   }
 
   test_getter_parenthesized_nullable() async {
@@ -52,7 +56,9 @@
   int x;
   x?.isEven;
 }
-''', [HintCode.UNNECESSARY_NULL_AWARE_CALL]);
+''', [
+      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 65, 2),
+    ]);
   }
 
   test_getter_simple_nullable() async {
@@ -76,7 +82,9 @@
   int x;
   (x)?.round();
 }
-''', [HintCode.UNNECESSARY_NULL_AWARE_CALL]);
+''', [
+      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 67, 2),
+    ]);
   }
 
   test_method_parenthesized_nullable() async {
@@ -100,7 +108,9 @@
   int x;
   x?.round();
 }
-''', [HintCode.UNNECESSARY_NULL_AWARE_CALL]);
+''', [
+      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 65, 2),
+    ]);
   }
 
   test_method_simple_nullable() async {
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_false_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_false_test.dart
index e3316ad..727f808 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_false_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_false_test.dart
@@ -16,24 +16,32 @@
 @reflectiveTest
 class UnnecessaryTypeCheckFalseTest extends DriverResolutionTest {
   test_null_not_Null() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 bool b = null is! Null;
-''', [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
+''', [
+      error(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, 9, 13),
+    ]);
   }
 
   test_type_not_dynamic() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(i) {
   bool b = i is! dynamic;
 }
-''', [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, 18, 13),
+    ]);
   }
 
   test_type_not_object() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(i) {
   bool b = i is! Object;
 }
-''', [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, 18, 12),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_true_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_true_test.dart
index 269d39a..daae87f 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_true_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_true_test.dart
@@ -16,24 +16,32 @@
 @reflectiveTest
 class UnnecessaryTypeCheckTrueTest extends DriverResolutionTest {
   test_null_is_Null() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 bool b = null is Null;
-''', [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
+''', [
+      error(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, 9, 12),
+    ]);
   }
 
   test_type_is_dynamic() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(i) {
   bool b = i is dynamic;
 }
-''', [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, 18, 12),
+    ]);
   }
 
   test_type_is_object() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 m(i) {
   bool b = i is Object;
 }
-''', [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, 18, 11),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unused_catch_clause_test.dart b/pkg/analyzer/test/src/diagnostics/unused_catch_clause_test.dart
index de74c41..9eefe4c 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_catch_clause_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_catch_clause_test.dart
@@ -19,13 +19,15 @@
   bool get enableUnusedLocalVariable => true;
 
   test_on_unusedException() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   try {
   } on String catch (exception) {
   }
 }
-''', [HintCode.UNUSED_CATCH_CLAUSE]);
+''', [
+      error(HintCode.UNUSED_CATCH_CLAUSE, 38, 9),
+    ]);
   }
 
   test_on_usedException() async {
diff --git a/pkg/analyzer/test/src/diagnostics/unused_catch_stack_test.dart b/pkg/analyzer/test/src/diagnostics/unused_catch_stack_test.dart
index 84303fa..9ee0541 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_catch_stack_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_catch_stack_test.dart
@@ -19,13 +19,15 @@
   bool get enableUnusedLocalVariable => true;
 
   test_on_unusedStack() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   try {
   } on String catch (exception, stackTrace) {
   }
 }
-''', [HintCode.UNUSED_CATCH_STACK]);
+''', [
+      error(HintCode.UNUSED_CATCH_STACK, 49, 10),
+    ]);
   }
 
   test_on_usedStack() async {
@@ -40,13 +42,15 @@
   }
 
   test_unusedStack() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   try {
   } catch (exception, stackTrace) {
   }
 }
-''', [HintCode.UNUSED_CATCH_STACK]);
+''', [
+      error(HintCode.UNUSED_CATCH_STACK, 39, 10),
+    ]);
   }
 
   test_usedStack() async {
diff --git a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
index 8f16748..ef38d33 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
@@ -85,7 +85,7 @@
   }
 
   test_class_notUsed_inClassMember() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class _A {
   static staticMethod() {
     new _A();
@@ -94,45 +94,55 @@
     new _A();
   }
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
   }
 
   test_class_notUsed_inConstructorName() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class _A {
   _A() {}
   _A.named() {}
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
   }
 
   test_class_notUsed_isExpression() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class _A {}
 main(p) {
   if (p is _A) {
   }
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
   }
 
   test_class_notUsed_noReference() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class _A {}
 main() {
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
   }
 
   test_class_notUsed_variableDeclaration() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class _A {}
 main() {
   _A v;
   print(v);
 }
 print(x) {}
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
   }
 
   test_enum_isUsed_fieldReference() async {
@@ -145,11 +155,13 @@
   }
 
   test_enum_notUsed_noReference() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 enum _MyEnum {A, B, C}
 main() {
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 5, 7),
+    ]);
   }
 
   test_functionLocal_isUsed_closure() async {
@@ -181,21 +193,25 @@
   }
 
   test_functionLocal_notUsed_noReference() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   f() {}
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 11, 1),
+    ]);
   }
 
   test_functionLocal_notUsed_referenceFromItself() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   _f(int p) {
     _f(p - 1);
   }
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 11, 2),
+    ]);
   }
 
   test_functionTop_isUsed_invocation() async {
@@ -218,21 +234,25 @@
   }
 
   test_functionTop_notUsed_noReference() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 _f() {}
 main() {
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 0, 2),
+    ]);
   }
 
   test_functionTop_notUsed_referenceFromItself() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 _f(int p) {
   _f(p - 1);
 }
 main() {
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 0, 2),
+    ]);
   }
 
   test_functionTypeAlias_isUsed_isExpression() async {
@@ -274,11 +294,13 @@
   }
 
   test_functionTypeAlias_notUsed_noReference() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 typedef _F(a, b);
 main() {
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 8, 2),
+    ]);
   }
 
   test_getter_isUsed_invocation_implicitThis() async {
@@ -315,21 +337,25 @@
   }
 
   test_getter_notUsed_noReference() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   get _g => null;
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 16, 2),
+    ]);
   }
 
   test_getter_notUsed_referenceFromItself() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   get _g {
     return _g;
   }
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 16, 2),
+    ]);
   }
 
   test_method_isUsed_hasReference_implicitThis() async {
@@ -477,21 +503,25 @@
   }
 
   test_method_notUsed_noReference() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   static _m() {}
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 19, 2),
+    ]);
   }
 
   test_method_notUsed_referenceFromItself() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   static _m(int p) {
     _m(p - 1);
   }
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 19, 2),
+    ]);
   }
 
   test_setter_isUsed_invocation_implicitThis() async {
@@ -528,15 +558,17 @@
   }
 
   test_setter_notUsed_noReference() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   set _s(x) {}
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 16, 2),
+    ]);
   }
 
   test_setter_notUsed_referenceFromItself() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   set _s(int x) {
     if (x > 5) {
@@ -544,7 +576,9 @@
     }
   }
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 16, 2),
+    ]);
   }
 
   test_topLevelVariable_isUsed() async {
@@ -567,11 +601,13 @@
   }
 
   test_topLevelVariable_notUsed() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 int _a = 1;
 main() {
   _a = 2;
 }
-''', [HintCode.UNUSED_ELEMENT]);
+''', [
+      error(HintCode.UNUSED_ELEMENT, 4, 2),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unused_field_test.dart b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
index a0dacdb..fa17061 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
@@ -105,40 +105,48 @@
   }
 
   test_unusedField_notUsed_compoundAssign() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int _f;
   main() {
     _f += 2;
   }
 }
-''', [HintCode.UNUSED_FIELD]);
+''', [
+      error(HintCode.UNUSED_FIELD, 16, 2),
+    ]);
   }
 
   test_unusedField_notUsed_constructorFieldInitializers() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int _f;
   A() : _f = 0;
 }
-''', [HintCode.UNUSED_FIELD]);
+''', [
+      error(HintCode.UNUSED_FIELD, 16, 2),
+    ]);
   }
 
   test_unusedField_notUsed_fieldFormalParameter() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int _f;
   A(this._f);
 }
-''', [HintCode.UNUSED_FIELD]);
+''', [
+      error(HintCode.UNUSED_FIELD, 16, 2),
+    ]);
   }
 
   test_unusedField_notUsed_noReference() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int _f;
 }
-''', [HintCode.UNUSED_FIELD]);
+''', [
+      error(HintCode.UNUSED_FIELD, 16, 2),
+    ]);
   }
 
   test_unusedField_notUsed_nullAssign() async {
@@ -154,29 +162,33 @@
   }
 
   test_unusedField_notUsed_postfixExpr() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int _f = 0;
   main() {
     _f++;
   }
 }
-''', [HintCode.UNUSED_FIELD]);
+''', [
+      error(HintCode.UNUSED_FIELD, 16, 2),
+    ]);
   }
 
   test_unusedField_notUsed_prefixExpr() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int _f = 0;
   main() {
     ++_f;
   }
 }
-''', [HintCode.UNUSED_FIELD]);
+''', [
+      error(HintCode.UNUSED_FIELD, 16, 2),
+    ]);
   }
 
   test_unusedField_notUsed_simpleAssignment() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int _f;
   m() {
@@ -186,6 +198,8 @@
 main(A a) {
   a._f = 2;
 }
-''', [HintCode.UNUSED_FIELD]);
+''', [
+      error(HintCode.UNUSED_FIELD, 16, 2),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unused_import_test.dart b/pkg/analyzer/test/src/diagnostics/unused_import_test.dart
index 84ac848..2159a68 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_import_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_import_test.dart
@@ -31,11 +31,13 @@
     newFile('/test/lib/lib1.dart', content: r'''
 class A {}
 ''');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart';
 import 'lib1.dart' as one;
 one.A a;
-''', [HintCode.UNUSED_IMPORT]);
+''', [
+      error(HintCode.UNUSED_IMPORT, 7, 11),
+    ]);
   }
 
   test_as_equalPrefixes_referenced() async {
@@ -63,11 +65,13 @@
     newFile('/test/lib/lib2.dart', content: r'''
 class B {}
 ''');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' as one;
 import 'lib2.dart' as one;
 one.A a;
-''', [HintCode.UNUSED_IMPORT]);
+''', [
+      error(HintCode.UNUSED_IMPORT, 32, 11),
+    ]);
   }
 
   test_core_library() async {
@@ -131,11 +135,13 @@
     newFile('/test/lib/lib1.dart', content: r'''
 class A {}
 ''');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart';
 import 'lib1.dart' hide A;
 A a;
-''', [HintCode.UNUSED_IMPORT]);
+''', [
+      error(HintCode.UNUSED_IMPORT, 27, 11),
+    ]);
   }
 
   test_inComment_libraryDirective() async {
@@ -200,17 +206,21 @@
 class A {}
 class B {}
 ''');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' show A;
 import 'lib1.dart' show B;
 A a;
-''', [HintCode.UNUSED_IMPORT]);
+''', [
+      error(HintCode.UNUSED_IMPORT, 34, 11),
+    ]);
   }
 
   test_unusedImport() async {
     newFile('/test/lib/lib1.dart');
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart';
-''', [HintCode.UNUSED_IMPORT]);
+''', [
+      error(HintCode.UNUSED_IMPORT, 7, 11),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unused_label_test.dart b/pkg/analyzer/test/src/diagnostics/unused_label_test.dart
index 3322685..4d1c338 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_label_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_label_test.dart
@@ -16,7 +16,7 @@
 @reflectiveTest
 class UnusedLabelTest extends DriverResolutionTest {
   test_unused_inSwitch() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(x) {
   switch (x) {
     label: case 0:
@@ -25,17 +25,21 @@
       break;
   }
 }
-''', [HintCode.UNUSED_LABEL]);
+''', [
+      error(HintCode.UNUSED_LABEL, 26, 6),
+    ]);
   }
 
   test_unused_onWhile() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f(condition()) {
   label: while (condition()) {
     break;
   }
 }
-''', [HintCode.UNUSED_LABEL]);
+''', [
+      error(HintCode.UNUSED_LABEL, 19, 6),
+    ]);
   }
 
   test_used_inSwitch() async {
diff --git a/pkg/analyzer/test/src/diagnostics/unused_local_variable_test.dart b/pkg/analyzer/test/src/diagnostics/unused_local_variable_test.dart
index d4281bc..5bf524c 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_local_variable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_local_variable_test.dart
@@ -31,23 +31,27 @@
   }
 
   test_inFunction() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   var v = 1;
   v = 2;
 }
-''', [HintCode.UNUSED_LOCAL_VARIABLE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
+    ]);
   }
 
   test_inMethod() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   foo() {
     var v = 1;
     v = 2;
   }
 }
-''', [HintCode.UNUSED_LOCAL_VARIABLE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 28, 1),
+    ]);
   }
 
   test_isInvoked() async {
@@ -72,30 +76,36 @@
   }
 
   test_isRead_notUsed_compoundAssign() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   var v = 1;
   v += 2;
 }
-''', [HintCode.UNUSED_LOCAL_VARIABLE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
+    ]);
   }
 
   test_isRead_notUsed_postfixExpr() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   var v = 1;
   v++;
 }
-''', [HintCode.UNUSED_LOCAL_VARIABLE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
+    ]);
   }
 
   test_isRead_notUsed_prefixExpr() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   var v = 1;
   ++v;
 }
-''', [HintCode.UNUSED_LOCAL_VARIABLE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
+    ]);
   }
 
   test_isRead_usedArgument() async {
diff --git a/pkg/analyzer/test/src/diagnostics/unused_shown_name_test.dart b/pkg/analyzer/test/src/diagnostics/unused_shown_name_test.dart
index fd823b1..99b749b 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_shown_name_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_shown_name_test.dart
@@ -20,10 +20,12 @@
 class A {}
 class B {}
 ''');
-    assertErrorCodesInCode(r'''
+    assertErrorsInCode(r'''
 import 'lib1.dart' show A, B;
 A a;
-''', [HintCode.UNUSED_SHOWN_NAME]);
+''', [
+      error(HintCode.UNUSED_SHOWN_NAME, 27, 1),
+    ]);
   }
 
   test_unusedShownName_as() async {
@@ -31,10 +33,12 @@
 class A {}
 class B {}
 ''');
-    assertErrorCodesInCode(r'''
+    assertErrorsInCode(r'''
 import 'lib1.dart' as p show A, B;
 p.A a;
-''', [HintCode.UNUSED_SHOWN_NAME]);
+''', [
+      error(HintCode.UNUSED_SHOWN_NAME, 32, 1),
+    ]);
   }
 
   test_unusedShownName_duplicates() async {
@@ -44,12 +48,15 @@
 class C {}
 class D {}
 ''');
-    assertErrorCodesInCode(r'''
+    assertErrorsInCode(r'''
 import 'lib1.dart' show A, B;
 import 'lib1.dart' show C, D;
 A a;
 C c;
-''', [HintCode.UNUSED_SHOWN_NAME, HintCode.UNUSED_SHOWN_NAME]);
+''', [
+      error(HintCode.UNUSED_SHOWN_NAME, 27, 1),
+      error(HintCode.UNUSED_SHOWN_NAME, 57, 1),
+    ]);
   }
 
   test_unusedShownName_topLevelVariable() async {
@@ -59,12 +66,14 @@
 const int var3 = 3;
 const int var4 = 4;
 ''');
-    assertErrorCodesInCode(r'''
+    assertErrorsInCode(r'''
 import 'lib1.dart' show var1, var2;
 import 'lib1.dart' show var3, var4;
 int a = var1;
 int b = var2;
 int c = var3;
-''', [HintCode.UNUSED_SHOWN_NAME]);
+''', [
+      error(HintCode.UNUSED_SHOWN_NAME, 66, 4),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/wrong_type_parameter_variance_in_superinterface_test.dart b/pkg/analyzer/test/src/diagnostics/wrong_type_parameter_variance_in_superinterface_test.dart
new file mode 100644
index 0000000..5815369
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/wrong_type_parameter_variance_in_superinterface_test.dart
@@ -0,0 +1,334 @@
+// Copyright (c) 2019, 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:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(WrongTypeParameterVarianceInSuperinterfaceTest);
+  });
+}
+
+@reflectiveTest
+class WrongTypeParameterVarianceInSuperinterfaceTest
+    extends DriverResolutionTest {
+  test_class_extends_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+class B<X> extends A<F<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_class_extends_function_parameterType_parameterType() async {
+    await assertNoErrorsInCode(r'''
+typedef F1<X> = void Function(X);
+typedef F2<X> = void Function(F1<X>);
+class A<X> {}
+class B<X> extends A<F2<X>> {}
+''');
+  }
+
+  test_class_extends_function_parameterType_returnType() async {
+    await assertErrorsInCode(r'''
+typedef F1<X> = X Function();
+typedef F2<X> = void Function(F1<X>);
+class A<X> {}
+class B<X> extends A<F2<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        90,
+        1,
+      ),
+    ]);
+  }
+
+  test_class_extends_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+class B<X> extends A<F<X>> {}
+''');
+  }
+
+  test_class_extends_function_returnType_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F1<X> = void Function(X);
+typedef F2<X> = F1<X> Function();
+class A<X> {}
+class B<X> extends A<F2<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        90,
+        1,
+      ),
+    ]);
+  }
+
+  test_class_extends_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+class B<X> extends A<X> {}
+''');
+  }
+
+  test_class_implements_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+class B<X> implements A<F<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_class_implements_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+class B<X> implements A<F<X>> {}
+''');
+  }
+
+  test_class_implements_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+class B<X> implements A<X> {}
+''');
+  }
+
+  test_class_with_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+class B<X> extends Object with A<F<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_class_with_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+class B<X> extends Object with A<F<X>> {}
+''');
+  }
+
+  test_class_with_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+class B<X> extends Object with A<X> {}
+''');
+  }
+
+  test_classTypeAlias_extends_function_invariant() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = X Function(X);
+class A<X> {}
+mixin M {}
+class B<X> = A<F<X>> with M;
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        63,
+        1,
+      ),
+    ]);
+  }
+
+  test_classTypeAlias_extends_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin M {}
+class B<X> = A<F<X>> with M;
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        66,
+        1,
+      ),
+    ]);
+  }
+
+  test_classTypeAlias_extends_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin M {}
+class B<X> = A<F<X>> with M;
+''');
+  }
+
+  test_classTypeAlias_extends_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin M {}
+class B<X> = A<X> with M;
+''');
+  }
+
+  test_classTypeAlias_implements_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin M {}
+class B<X> = Object with M implements A<F<X>>;
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        66,
+        1,
+      ),
+    ]);
+  }
+
+  test_classTypeAlias_implements_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin M {}
+class B<X> = Object with M implements A<F<X>>;
+''');
+  }
+
+  test_classTypeAlias_implements_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin M {}
+class B<X> = Object with M implements A<X>;
+''');
+  }
+
+  test_classTypeAlias_with_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+mixin M<X> {}
+class B<X> = Object with M<F<X>>;
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_classTypeAlias_with_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+mixin M<X> {}
+class B<X> = Object with M<F<X>>;
+''');
+  }
+
+  test_classTypeAlias_with_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+mixin M<X> {}
+class B<X> = Object with M<X>;
+''');
+  }
+
+  test_mixin_implements_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin B<X> implements A<F<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_mixin_implements_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin B<X> implements A<F<X>> {}
+''');
+  }
+
+  test_mixin_implements_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin B<X> implements A<X> {}
+''');
+  }
+
+  test_mixin_on_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin B<X> on A<F<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_mixin_on_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin B<X> on A<F<X>> {}
+''');
+  }
+
+  test_mixin_on_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin B<X> on A<X> {}
+''');
+  }
+
+  test_typeParameter_bound() async {
+    try {
+      await assertErrorsInCode(r'''
+class A<X> {}
+class B<X> extends A<void Function<Y extends X>()> {}
+''', [
+        error(
+          CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+          22,
+          1,
+        ),
+      ]);
+    } catch (_) {
+      // TODO(scheglov) This code crashes with summary1.
+//    NoSuchMethodError: The getter 'bound' was called on null.
+//    Receiver: null
+//    Tried calling: bound
+//    #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
+//    #1      ErrorVerifier._checkForTypeParameterSupertypeOfItsBound (error_verifier.dart:5438:30)
+      if (AnalysisDriver.useSummary2) rethrow;
+    }
+  }
+}
diff --git a/pkg/analyzer/test/src/fasta/message_coverage_test.dart b/pkg/analyzer/test/src/fasta/message_coverage_test.dart
index f40c351..291f940 100644
--- a/pkg/analyzer/test/src/fasta/message_coverage_test.dart
+++ b/pkg/analyzer/test/src/fasta/message_coverage_test.dart
@@ -38,7 +38,7 @@
   }
 
   /**
-   * Given the path to the file 'message.yaml', return a list of the top-level
+   * Given the path to the file 'messages.yaml', return a list of the top-level
    * keys defined in that file that define an 'analyzerCode'.
    */
   List<String> getMappedCodes(String messagesPath) {
@@ -61,7 +61,7 @@
   }
 
   /**
-   * Given the path to the file 'message.yaml', return a list of the analyzer
+   * Given the path to the file 'messages.yaml', return a list of the analyzer
    * codes defined in that file.
    */
   List<String> getReferencedCodes(String messagesPath) {
diff --git a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
index 5ac8dc9..ba3ae38 100644
--- a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -43,7 +44,7 @@
 f() => [a, if (x) b c];
 ''', [ParserErrorCode.EXPECTED_ELSE_OR_COMMA], '''
 f() => [a, if (x) b, c];
-''', enableControlFlowCollections: true);
+''', featureSet: controlFlow);
   }
 
   void test_missingComma_afterIfElse() {
@@ -51,7 +52,7 @@
 f() => [a, if (x) b else y c];
 ''', [ParserErrorCode.EXPECTED_TOKEN], '''
 f() => [a, if (x) b else y, c];
-''', enableControlFlowCollections: true);
+''', featureSet: controlFlow);
   }
 }
 
@@ -60,6 +61,8 @@
  */
 @reflectiveTest
 class MapLiteralTest extends AbstractRecoveryTest {
+  final beforeUiAsCode = FeatureSet.forTesting(sdkVersion: '2.2.0');
+
   void test_extraComma() {
     testRecovery('''
 f() => {a: b, , c: d};
@@ -69,7 +72,7 @@
       ParserErrorCode.MISSING_IDENTIFIER
     ], '''
 f() => {a: b, _s_: _s_, c: d};
-''');
+''', featureSet: beforeUiAsCode);
   }
 
   void test_missingColonAndValue_last() {
@@ -77,7 +80,7 @@
 f() => {a: b, c };
 ''', [ParserErrorCode.EXPECTED_TOKEN, ParserErrorCode.MISSING_IDENTIFIER], '''
 f() => {a: b, c: _s_};
-''');
+''', featureSet: beforeUiAsCode);
   }
 
   void test_missingComma() {
@@ -93,7 +96,7 @@
 f() => {a: b, if (x) c: d e: f};
 ''', [ParserErrorCode.EXPECTED_ELSE_OR_COMMA], '''
 f() => {a: b, if (x) c: d, e: f};
-''', enableControlFlowCollections: true);
+''', featureSet: controlFlow);
   }
 
   void test_missingComma_afterIfElse() {
@@ -101,7 +104,7 @@
 f() => {a: b, if (x) c: d else y: z e: f};
 ''', [ParserErrorCode.EXPECTED_TOKEN], '''
 f() => {a: b, if (x) c: d else y: z, e: f};
-''', enableControlFlowCollections: true);
+''', featureSet: controlFlow);
   }
 
   void test_missingKey() {
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/extension_declaration_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/extension_declaration_test.dart
new file mode 100644
index 0000000..e04eadd
--- /dev/null
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/extension_declaration_test.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+
+import 'partial_code_support.dart';
+
+main() {
+  new ExtensionDeclarationTest().buildAll();
+}
+
+class ExtensionDeclarationTest extends PartialCodeTest {
+  buildAll() {
+    buildTests(
+        'extension_declaration',
+        [
+          new TestDescriptor(
+              'keyword',
+              'extension',
+              [
+                ParserErrorCode.MISSING_IDENTIFIER,
+                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_TYPE_NAME,
+                ParserErrorCode.EXPECTED_BODY,
+              ],
+              'extension _s_ on _s_ {}',
+              failing: ['getter', 'functionNonVoid', 'functionVoid', 'mixin']),
+          new TestDescriptor(
+              'named',
+              'extension E',
+              [
+                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_TYPE_NAME,
+                ParserErrorCode.EXPECTED_BODY,
+              ],
+              'extension E on _s_ {}',
+              failing: ['getter', 'functionNonVoid', 'functionVoid', 'mixin']),
+          new TestDescriptor(
+              'on',
+              'extension E on',
+              [
+                ParserErrorCode.EXPECTED_TYPE_NAME,
+                ParserErrorCode.EXPECTED_BODY,
+              ],
+              'extension E on _s_ {}',
+              failing: ['getter', 'functionNonVoid', 'functionVoid', 'mixin']),
+          new TestDescriptor(
+              'extendedType',
+              'extension E on String',
+              [
+                ParserErrorCode.EXPECTED_BODY,
+              ],
+              'extension E on String {}'),
+          // Most of the failing tests are because the following text could be
+          // a member of the class, so the parser adds the closing brace _after_
+          // the declaration that's expected to follow it.
+          //
+          // The notable exceptions are 'class', 'enum', 'mixin', and 'typedef'.
+          new TestDescriptor(
+              'partialBody',
+              'extension E on String {',
+              [
+                ScannerErrorCode.EXPECTED_TOKEN,
+              ],
+              'extension E on String {}',
+              failing: [
+                'class',
+                'const',
+                'enum',
+                'final',
+                'functionNonVoid',
+                'functionVoid',
+                'mixin',
+                'getter',
+                'setter',
+                'typedef',
+                'var'
+              ]),
+        ],
+        PartialCodeTest.declarationSuffixes,
+        featureSet: new FeatureSet.forTesting(
+            sdkVersion: '2.3.0',
+            additionalFeatures: [Feature.extension_methods]));
+  }
+}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart
index 8634b8f..45263e5 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
@@ -47,6 +48,7 @@
   static final List<TestSuffix> declarationSuffixes = <TestSuffix>[
     new TestSuffix('class', 'class A {}'),
     new TestSuffix('enum', 'enum E { v }'),
+//    new TestSuffix('extension', 'extension E on A {}'),
     new TestSuffix('mixin', 'mixin M {}'),
     new TestSuffix('typedef', 'typedef A = B Function(C, D);'),
     new TestSuffix('functionVoid', 'void f() {}'),
@@ -107,16 +109,21 @@
    */
   buildTests(String groupName, List<TestDescriptor> descriptors,
       List<TestSuffix> suffixes,
-      {String head, bool includeEof: true, String tail}) {
+      {FeatureSet featureSet,
+      String head,
+      bool includeEof: true,
+      String tail}) {
     group(groupName, () {
       for (TestDescriptor descriptor in descriptors) {
         if (includeEof) {
           _buildTestForDescriptorAndSuffix(
-              descriptor, TestSuffix.eof, 0, head, tail);
+              descriptor, TestSuffix.eof, 0, head, tail,
+              featureSet: featureSet);
         }
         for (int i = 0; i < suffixes.length; i++) {
           _buildTestForDescriptorAndSuffix(
-              descriptor, suffixes[i], i + 1, head, tail);
+              descriptor, suffixes[i], i + 1, head, tail,
+              featureSet: featureSet);
         }
         if (descriptor.failing != null) {
           test('${descriptor.name}_failingList', () {
@@ -138,7 +145,8 @@
    * Build a single test based on the given [descriptor] and [suffix].
    */
   _buildTestForDescriptorAndSuffix(TestDescriptor descriptor, TestSuffix suffix,
-      int suffixIndex, String head, String tail) {
+      int suffixIndex, String head, String tail,
+      {FeatureSet featureSet}) {
     test('${descriptor.name}_${suffix.name}', () {
       //
       // Compose the invalid and valid pieces of code.
@@ -172,7 +180,7 @@
       //
       GatheringErrorListener listener =
           new GatheringErrorListener(checkRanges: true);
-      parseCompilationUnit2(base.toString(), listener);
+      parseCompilationUnit2(base.toString(), listener, featureSet: featureSet);
       var baseErrorCodes = <ErrorCode>[];
       listener.errors.forEach((AnalysisError error) {
         if (error.errorCode == ParserErrorCode.BREAK_OUTSIDE_OF_LOOP ||
@@ -218,7 +226,8 @@
             invalid.toString(), expectedInvalidCodeErrors, valid.toString(),
             adjustValidUnitBeforeComparison:
                 descriptor.adjustValidUnitBeforeComparison,
-            expectedErrorsInValidCode: expectedValidCodeErrors);
+            expectedErrorsInValidCode: expectedValidCodeErrors,
+            featureSet: featureSet);
       }
     });
   }
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart
index f8a05c4..914e1f6 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart
@@ -22,7 +22,7 @@
               'switch',
               [
                 ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ParserErrorCode.EXPECTED_TOKEN
               ],
               "switch (_s_) {}",
@@ -32,7 +32,7 @@
               'switch (',
               [
                 ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "switch (_s_) {}",
@@ -47,11 +47,11 @@
           new TestDescriptor(
               'expression',
               'switch (a',
-              [ParserErrorCode.EXPECTED_TOKEN, ScannerErrorCode.EXPECTED_TOKEN],
+              [ParserErrorCode.EXPECTED_BODY, ScannerErrorCode.EXPECTED_TOKEN],
               "switch (a) {}",
               failing: ['block']),
           new TestDescriptor('rightParen', 'switch (a)',
-              [ParserErrorCode.EXPECTED_TOKEN], "switch (a) {}",
+              [ParserErrorCode.EXPECTED_BODY], "switch (a) {}",
               failing: ['block']),
           new TestDescriptor('leftBrace', 'switch (a) {',
               [ScannerErrorCode.EXPECTED_TOKEN], "switch (a) {}",
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/test_all.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/test_all.dart
index 768c05b..0b20072 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/test_all.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/test_all.dart
@@ -13,6 +13,7 @@
 import 'do_statement_test.dart' as do_statement;
 import 'enum_declaration_test.dart' as enum_declaration;
 import 'export_directive_test.dart' as export_directive;
+import 'extension_declaration_test.dart' as extension_declaration;
 import 'field_declaration_test.dart' as field_declaration;
 import 'forEach_statement_test.dart' as forEach_statement;
 import 'for_statement_test.dart' as for_statement;
@@ -46,6 +47,7 @@
     do_statement.main();
     enum_declaration.main();
     export_directive.main();
+    extension_declaration.main();
     field_declaration.main();
     for_statement.main();
     forEach_statement.main();
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
index ca80f4c..1e2f8a5 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
@@ -22,7 +22,7 @@
               'keyword',
               'try',
               [
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ParserErrorCode.MISSING_CATCH_OR_FINALLY
               ],
               "try {} finally {}",
@@ -38,7 +38,7 @@
               'try {} on',
               [
                 ParserErrorCode.EXPECTED_TYPE_NAME,
-                ParserErrorCode.EXPECTED_TOKEN
+                ParserErrorCode.EXPECTED_BODY
               ],
               "try {} on _s_ {}",
               failing: [
@@ -48,7 +48,7 @@
                 'localFunctionVoid'
               ]),
           new TestDescriptor('on_identifier', 'try {} on A',
-              [ParserErrorCode.EXPECTED_TOKEN], "try {} on A {}",
+              [ParserErrorCode.EXPECTED_BODY], "try {} on A {}",
               failing: ['block']),
           //
           // Single catch clause.
@@ -56,7 +56,7 @@
           new TestDescriptor(
               'catch',
               'try {} catch',
-              [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_TOKEN],
+              [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_BODY],
               "try {} catch (e) {}",
               failing: ['block']),
           new TestDescriptor(
@@ -65,7 +65,7 @@
               [
                 ScannerErrorCode.EXPECTED_TOKEN,
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN
+                ParserErrorCode.EXPECTED_BODY
               ],
               "try {} catch (e) {}",
               failing: ['block', 'labeled', 'localFunctionNonVoid']),
@@ -74,7 +74,7 @@
               'try {} catch (e',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} catch (e) {}",
@@ -84,7 +84,7 @@
               'try {} catch (e, ',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} catch (e, _s_) {}",
@@ -96,13 +96,13 @@
                 // TODO(danrubel): Update parser to generate CATCH_SYNTAX
                 // because in this situation there are not any extra parameters.
                 ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} catch (e, s) {}",
               failing: ['eof', 'block']),
           new TestDescriptor('catch_rightParen', 'try {} catch (e, s)',
-              [ParserErrorCode.EXPECTED_TOKEN], "try {} catch (e, s) {}",
+              [ParserErrorCode.EXPECTED_BODY], "try {} catch (e, s) {}",
               failing: ['block']),
           //
           // Single catch clause after an on clause.
@@ -110,7 +110,7 @@
           new TestDescriptor(
               'on_catch',
               'try {} on A catch',
-              [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_TOKEN],
+              [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_BODY],
               "try {} on A catch (e) {}",
               failing: ['block']),
           new TestDescriptor(
@@ -118,7 +118,7 @@
               'try {} on A catch (',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e) {}",
@@ -128,7 +128,7 @@
               'try {} on A catch (e',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e) {}",
@@ -138,7 +138,7 @@
               'try {} on A catch (e, ',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e, _s_) {}",
@@ -150,19 +150,19 @@
                 // TODO(danrubel): Update parser to generate CATCH_SYNTAX
                 // because in this situation there are not any extra parameters.
                 ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e, s) {}",
               failing: ['eof', 'block']),
           new TestDescriptor('on_catch_rightParen', 'try {} on A catch (e, s)',
-              [ParserErrorCode.EXPECTED_TOKEN], "try {} on A catch (e, s) {}",
+              [ParserErrorCode.EXPECTED_BODY], "try {} on A catch (e, s) {}",
               failing: ['block']),
           //
           // Only a finally clause.
           //
           new TestDescriptor('finally_noCatch_noBlock', 'try {} finally',
-              [ParserErrorCode.EXPECTED_TOKEN], "try {} finally {}",
+              [ParserErrorCode.EXPECTED_BODY], "try {} finally {}",
               failing: ['block']),
           //
           // A catch and finally clause.
@@ -170,7 +170,7 @@
           new TestDescriptor(
               'finally_catch_noBlock',
               'try {} catch (e) {} finally',
-              [ParserErrorCode.EXPECTED_TOKEN],
+              [ParserErrorCode.EXPECTED_BODY],
               "try {} catch (e) {} finally {}",
               failing: ['block']),
         ],
diff --git a/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart b/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
index d0cdb3b..3f5de77 100644
--- a/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/error.dart';
@@ -19,15 +20,14 @@
   void testRecovery(
       String invalidCode, List<ErrorCode> errorCodes, String validCode,
       {CompilationUnit adjustValidUnitBeforeComparison(CompilationUnit unit),
-      bool enableControlFlowCollections,
-      List<ErrorCode> expectedErrorsInValidCode}) {
+      List<ErrorCode> expectedErrorsInValidCode,
+      FeatureSet featureSet}) {
     CompilationUnit validUnit;
 
     // Assert that the valid code is indeed valid.
     try {
       validUnit = parseCompilationUnit(validCode,
-          codes: expectedErrorsInValidCode,
-          enableControlFlowCollections: enableControlFlowCollections);
+          codes: expectedErrorsInValidCode, featureSet: featureSet);
       validateTokenStream(validUnit.beginToken);
     } catch (e) {
 //      print('');
@@ -41,8 +41,8 @@
     // Compare the structures before asserting valid errors.
     GatheringErrorListener listener =
         new GatheringErrorListener(checkRanges: true);
-    CompilationUnit invalidUnit = parseCompilationUnit2(invalidCode, listener,
-        enableControlFlowCollections: enableControlFlowCollections);
+    CompilationUnit invalidUnit =
+        parseCompilationUnit2(invalidCode, listener, featureSet: featureSet);
     validateTokenStream(invalidUnit.beginToken);
     if (adjustValidUnitBeforeComparison != null) {
       validUnit = adjustValidUnitBeforeComparison(validUnit);
diff --git a/pkg/analyzer/test/src/lint/lint_rule_test.dart b/pkg/analyzer/test/src/lint/lint_rule_test.dart
new file mode 100644
index 0000000..55b1e3e5
--- /dev/null
+++ b/pkg/analyzer/test/src/lint/lint_rule_test.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/error/lint_codes.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/lint/linter.dart';
+import 'package:test/test.dart';
+
+import '../../generated/test_support.dart';
+
+main() {
+  group('lint rule', () {
+    group('error code reporting', () {
+      test('reportLintForToken (custom)', () {
+        final rule = TestRule();
+        final reporter = CollectingReporter(
+            GatheringErrorListener(), new _MockSource('mock'));
+        rule.reporter = reporter;
+
+        rule.reportLintForToken(Token.eof(0),
+            errorCode: customCode, ignoreSyntheticTokens: false);
+        expect(reporter.code, customCode);
+      });
+      test('reportLintForToken (default)', () {
+        final rule = TestRule();
+        final reporter = CollectingReporter(
+            GatheringErrorListener(), new _MockSource('mock'));
+        rule.reporter = reporter;
+
+        rule.reportLintForToken(Token.eof(0), ignoreSyntheticTokens: false);
+        expect(reporter.code, rule.lintCode);
+      });
+      test('reportLint (custom)', () {
+        final rule = TestRule();
+        final reporter = CollectingReporter(
+            GatheringErrorListener(), new _MockSource('mock'));
+        rule.reporter = reporter;
+
+        final node =
+            EmptyStatementImpl(new SimpleToken(TokenType.SEMICOLON, 0));
+        rule.reportLint(node, errorCode: customCode);
+        expect(reporter.code, customCode);
+      });
+      test('reportLint (default)', () {
+        final rule = TestRule();
+        final reporter = CollectingReporter(
+            GatheringErrorListener(), new _MockSource('mock'));
+        rule.reporter = reporter;
+
+        final node =
+            EmptyStatementImpl(new SimpleToken(TokenType.SEMICOLON, 0));
+        rule.reportLint(node);
+        expect(reporter.code, rule.lintCode);
+      });
+    });
+  });
+}
+
+const LintCode customCode = const LintCode(
+    'hash_and_equals', 'Override `==` if overriding `hashCode`.',
+    correction: 'Implement `==`.');
+
+class CollectingReporter extends ErrorReporter {
+  ErrorCode code;
+
+  CollectingReporter(AnalysisErrorListener listener, Source source)
+      : super(listener, source);
+  void reportErrorForElement(ErrorCode errorCode, Element element,
+      [List<Object> arguments]) {
+    code = errorCode;
+  }
+
+  void reportErrorForNode(ErrorCode errorCode, AstNode node,
+      [List<Object> arguments]) {
+    code = errorCode;
+  }
+
+  @override
+  void reportErrorForToken(ErrorCode errorCode, Token token,
+      [List<Object> arguments]) {
+    code = errorCode;
+  }
+}
+
+class TestRule extends LintRule {
+  TestRule()
+      : super(
+          name: 'test_rule',
+          description: '',
+          details: '... tl;dr ...',
+          group: Group.errors,
+        );
+}
+
+class _MockSource implements Source {
+  @override
+  final String fullName;
+
+  _MockSource(this.fullName);
+
+  @override
+  noSuchMethod(Invocation invocation) {
+    throw new StateError('Unexpected invocation of ${invocation.memberName}');
+  }
+}
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
index 4c9693a..8761698 100644
--- a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
+++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -4,55 +4,142 @@
 
 import 'dart:async';
 
-import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../generated/resolver_test_case.dart';
+import '../../dart/resolution/driver_resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(LinterContextImplTest);
+    defineReflectiveTests(CanBeConstConstructorTest);
+    defineReflectiveTests(CanBeConstTest);
   });
 }
 
 @reflectiveTest
-class LinterContextImplTest extends ResolverTestCase {
-  String testSource;
-  CompilationUnitImpl testUnit;
+abstract class AbstractLinterContextTest extends DriverResolutionTest {
   LinterContextImpl context;
 
-  void assertCanBeConst(String snippet, bool expectedResult) {
-    int index = testSource.indexOf(snippet);
-    expect(index >= 0, isTrue);
-    NodeLocator visitor = new NodeLocator(index);
-    AstNodeImpl node = visitor.searchWithin(testUnit);
-    node = node.thisOrAncestorOfType<InstanceCreationExpressionImpl>();
-    expect(node, isNotNull);
-    expect(context.canBeConst(node as InstanceCreationExpressionImpl),
-        expectedResult ? isTrue : isFalse);
-  }
+  Future<void> resolve(String content) async {
+    addTestFile(content);
+    await resolveTestFile();
 
-  Future<void> resolve(String sourceText) async {
-    testSource = sourceText;
-    Source source = addNamedSource('/test.dart', sourceText);
-    ResolvedUnitResult analysisResult = await driver.getResult(source.fullName);
-    testUnit = analysisResult.unit;
-    LinterContextUnit contextUnit = new LinterContextUnit(sourceText, testUnit);
+    var contextUnit = LinterContextUnit(result.content, result.unit);
     context = new LinterContextImpl(
-        [contextUnit],
-        contextUnit,
-        analysisResult.session.declaredVariables,
-        analysisResult.typeProvider,
-        analysisResult.typeSystem,
-        analysisOptions);
+      [contextUnit],
+      contextUnit,
+      result.session.declaredVariables,
+      result.typeProvider,
+      result.typeSystem,
+      analysisOptions,
+    );
+  }
+}
+
+@reflectiveTest
+class CanBeConstConstructorTest extends AbstractLinterContextTest {
+  LinterContextImpl context;
+
+  void assertCanBeConstConstructor(String search, bool expectedResult) {
+    var constructor = findNode.constructor(search);
+    expect(context.canBeConstConstructor(constructor), expectedResult);
   }
 
-  void test_canBeConst_false_argument_invocation() async {
+  test_assertInitializer_parameter() async {
+    await resolve(r'''
+class C {
+  C(int a) : assert(a >= 0, 'error');
+}
+''');
+    assertCanBeConstConstructor('C(int a)', true);
+  }
+
+  test_empty() async {
+    await resolve(r'''
+class C {
+  C();
+}
+''');
+    assertCanBeConstConstructor('C()', true);
+  }
+
+  test_field_notConstInitializer() async {
+    await resolve(r'''
+class C {
+  final int f = a;
+  C();
+}
+
+var a = 0;
+''');
+    assertCanBeConstConstructor('C()', false);
+  }
+
+  test_field_notFinal() async {
+    await resolve(r'''
+class C {
+  int f = 0;
+  C();
+}
+''');
+    assertCanBeConstConstructor('C()', false);
+  }
+
+  test_field_notFinal_inherited() async {
+    await resolve(r'''
+class A {
+  int f = 0;
+}
+
+class B extends A {
+  B();
+}
+''');
+    assertCanBeConstConstructor('B()', false);
+  }
+
+  test_fieldInitializer_literal() async {
+    await resolve(r'''
+class C {
+  final int f;
+  C() : f = 0;
+}
+''');
+    assertCanBeConstConstructor('C()', true);
+  }
+
+  test_fieldInitializer_notConst() async {
+    await resolve(r'''
+class C {
+  final int f;
+  C() : f = a;
+}
+
+var a = 0;
+''');
+    assertCanBeConstConstructor('C()', false);
+  }
+
+  test_fieldInitializer_parameter() async {
+    await resolve(r'''
+class C {
+  final int f;
+  C(int a) : f = a;
+}
+''');
+    assertCanBeConstConstructor('C(int a)', true);
+  }
+}
+
+@reflectiveTest
+class CanBeConstTest extends AbstractLinterContextTest {
+  void assertCanBeConst(String snippet, bool expectedResult) {
+    var node = findNode.instanceCreation(snippet);
+    expect(context.canBeConst(node), expectedResult);
+  }
+
+  void test_false_argument_invocation() async {
     await resolve('''
 class A {}
 class B {
@@ -64,7 +151,7 @@
     assertCanBeConst("B(f", false);
   }
 
-  void test_canBeConst_false_argument_invocationInList() async {
+  void test_false_argument_invocationInList() async {
     await resolve('''
 class A {}
 class B {
@@ -76,7 +163,7 @@
     assertCanBeConst("B([", false);
   }
 
-  void test_canBeConst_false_argument_nonConstConstructor() async {
+  void test_false_argument_nonConstConstructor() async {
     await resolve('''
 class A {}
 class B {
@@ -87,7 +174,7 @@
     assertCanBeConst("B(A(", false);
   }
 
-  void test_canBeConst_false_nonConstConstructor() async {
+  void test_false_nonConstConstructor() async {
     await resolve('''
 class A {}
 A f() => A();
@@ -95,7 +182,7 @@
     assertCanBeConst("A(", false);
   }
 
-  void test_canBeConst_true_constConstructorArg() async {
+  void test_true_constConstructorArg() async {
     await resolve('''
 class A {
   const A();
@@ -108,7 +195,7 @@
     assertCanBeConst("B(A(", true);
   }
 
-  void test_canBeConst_true_constListArg() async {
+  void test_true_constListArg() async {
     await resolve('''
 class A {
   const A(List<int> l);
diff --git a/pkg/analyzer/test/src/lint/test_all.dart b/pkg/analyzer/test/src/lint/test_all.dart
index 47596f2..6b1afdc 100644
--- a/pkg/analyzer/test/src/lint/test_all.dart
+++ b/pkg/analyzer/test/src/lint/test_all.dart
@@ -6,6 +6,7 @@
 
 import 'config_test.dart' as config;
 import 'io_test.dart' as io;
+import 'lint_rule_test.dart' as lint_rule;
 import 'linter/test_all.dart' as linter;
 import 'project_test.dart' as project;
 import 'pub_test.dart' as pub;
@@ -14,6 +15,7 @@
   defineReflectiveSuite(() {
     config.main();
     io.main();
+    lint_rule.main();
     linter.main();
     project.main();
     pub.main();
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index dbf23a4..38bd97b 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -226,6 +226,51 @@
 
 @reflectiveTest
 class ChangeFileTest extends _Base {
+  disabled_test_updated_library_parted() async {
+    // TODO(scheglov) Figure out why this fails on Windows.
+    var a = convertPath('/home/test/lib/a.dart');
+    var b = convertPath('/home/test/lib/b.dart');
+
+    newFile(a, content: r'''
+class A {}
+''');
+    newFile(b, content: r'''
+part 'a.dart';
+class B {}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasNoLibrary('package:test/a.dart');
+    _assertHasLibrary('package:test/b.dart', declarations: [
+      _ExpectedDeclaration.class_('A', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+      _ExpectedDeclaration.class_('B', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+
+    newFile(a, content: r'''
+class A2 {}
+''');
+    tracker.changeFile(a);
+    await _doAllTrackerWork();
+    _assertHasLibrary('package:test/a.dart', declarations: [
+      _ExpectedDeclaration.class_('A2', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+    _assertHasLibrary('package:test/b.dart', declarations: [
+      _ExpectedDeclaration.class_('A2', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+      _ExpectedDeclaration.class_('B', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+  }
+
   test_added_exported() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
@@ -855,6 +900,41 @@
     ]);
   }
 
+  test_updated_library_to_part() async {
+    var a = convertPath('/home/test/lib/a.dart');
+
+    newFile(a, content: r'''
+class A {}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasLibrary('package:test/a.dart', declarations: [
+      _ExpectedDeclaration.class_('A', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+
+    newFile(a, content: r'''
+part of nothing;
+class A {}
+''');
+    tracker.changeFile(a);
+    await _doAllTrackerWork();
+    _assertHasNoLibrary('package:test/a.dart');
+
+    newFile(a, content: r'''
+class A2 {}
+''');
+    tracker.changeFile(a);
+    await _doAllTrackerWork();
+    _assertHasLibrary('package:test/a.dart', declarations: [
+      _ExpectedDeclaration.class_('A2', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+  }
+
   test_updated_part() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
@@ -910,6 +990,42 @@
     ]);
   }
 
+  test_updated_part_exported() async {
+    var a = convertPath('/home/test/lib/a.dart');
+    var b = convertPath('/home/test/lib/b.dart');
+
+    newFile(a, content: r'''
+part of unknown;
+class A {}
+''');
+    newFile(b, content: r'''
+export 'a.dart';
+class B {}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasNoLibrary('package:test/a.dart');
+    _assertHasLibrary('package:test/b.dart', declarations: [
+      _ExpectedDeclaration.class_('B', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+
+    newFile(a, content: r'''
+part of unknown;
+class A2 {}
+''');
+    tracker.changeFile(a);
+    await _doAllTrackerWork();
+    _assertHasNoLibrary('package:test/a.dart');
+    _assertHasLibrary('package:test/b.dart', declarations: [
+      _ExpectedDeclaration.class_('B', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+  }
+
   test_updated_part_withoutLibrary() async {
     var b = convertPath('/home/test/lib/b.dart');
 
@@ -1491,6 +1607,101 @@
     _assertNoDeclaration(library, 'A');
   }
 
+  test_FUNCTION_TYPE_ALIAS_old() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+typedef void A();
+
+@deprecated
+typedef void B();
+
+/// aaa
+///
+/// bbb bbb
+typedef void C();
+
+typedef int D(int p1, [double p2, String p3]);
+
+typedef void E(int p1, double p2, {String p3});
+
+typedef void F<T extends num, U>();
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'A'),
+      'A',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      parameters: '()',
+      parameterNames: [],
+      parameterTypes: [],
+      relevanceTags: ['package:test/test.dart::A'],
+      requiredParameterCount: 0,
+      returnType: 'void',
+    );
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'B'),
+      'B',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      isDeprecated: true,
+      parameters: '()',
+      parameterNames: [],
+      parameterTypes: [],
+      relevanceTags: ['package:test/test.dart::B'],
+      requiredParameterCount: 0,
+      returnType: 'void',
+    );
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'C'),
+      'C',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      docSummary: 'aaa',
+      docComplete: 'aaa\n\nbbb bbb',
+      parameters: '()',
+      parameterNames: [],
+      parameterTypes: [],
+      relevanceTags: ['package:test/test.dart::C'],
+      requiredParameterCount: 0,
+      returnType: 'void',
+    );
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'D'),
+      'D',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      parameters: '(int p1, [double p2, String p3])',
+      parameterNames: ['p1', 'p2', 'p3'],
+      parameterTypes: ['int', 'double', 'String'],
+      relevanceTags: ['package:test/test.dart::D'],
+      requiredParameterCount: 1,
+      returnType: 'int',
+    );
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'E'),
+      'E',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      parameters: '(int p1, double p2, {String p3})',
+      parameterNames: ['p1', 'p2', 'p3'],
+      parameterTypes: ['int', 'double', 'String'],
+      relevanceTags: ['package:test/test.dart::E'],
+      requiredParameterCount: 2,
+      returnType: 'void',
+    );
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'F'),
+      'F',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      parameters: '()',
+      parameterNames: [],
+      parameterTypes: [],
+      requiredParameterCount: 0,
+      relevanceTags: ['package:test/test.dart::F'],
+      returnType: 'void',
+      typeParameters: '<T extends num, U>',
+    );
+  }
+
   test_GETTER() async {
     newFile('/home/test/lib/test.dart', content: r'''
 int get a => 0;
@@ -2816,6 +3027,7 @@
     tracker.changes.listen((change) {
       changes.add(change);
       for (var library in change.changed) {
+        expect(library.declarations, isNotNull);
         idToLibrary[library.id] = library;
         uriToLibrary[library.uriStr] = library;
       }
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 61c752d..14354cc 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -59,7 +59,8 @@
     bool withOffsets: false,
     bool withSyntheticAccessors: false,
     bool withSyntheticFields: false,
-    bool withTypes: false}) {
+    bool withTypes: false,
+    bool annotateNullability: false}) {
   var writer = new _ElementWriter(
       withCodeRanges: withCodeRanges,
       withConstElements: withConstElements,
@@ -67,7 +68,8 @@
       withOffsets: withOffsets,
       withSyntheticAccessors: withSyntheticAccessors,
       withSyntheticFields: withSyntheticFields,
-      withTypes: withTypes);
+      withTypes: withTypes,
+      annotateNullability: annotateNullability);
   writer.writeLibraryElement(library);
 
   String actualText = writer.buffer.toString();
@@ -135,6 +137,7 @@
   final bool withSyntheticAccessors;
   final bool withSyntheticFields;
   final bool withTypes;
+  final bool annotateNullability;
   final StringBuffer buffer = new StringBuffer();
 
   _ElementWriter(
@@ -144,7 +147,8 @@
       this.withOffsets: false,
       this.withSyntheticAccessors: false,
       this.withSyntheticFields: false,
-      this.withTypes: false});
+      this.withTypes: false,
+      this.annotateNullability: false});
 
   bool isDynamicType(DartType type) => type is DynamicTypeImpl;
 
@@ -311,6 +315,22 @@
     buffer.writeln(';');
   }
 
+  void writeExportScope(LibraryElement e) {
+    if (!withExportScope) return;
+
+    buffer.writeln();
+    buffer.writeln('-' * 20);
+    buffer.writeln('Exports:');
+
+    var map = e.exportNamespace.definedNames;
+    var names = map.keys.toList()..sort();
+    for (var name in names) {
+      var element = map[name];
+      var elementLocationStr = _getElementLocationString(element);
+      buffer.writeln('  $name: $elementLocationStr');
+    }
+  }
+
   void writeFunctionElement(FunctionElement e) {
     writeDocumentation(e);
     writeMetadata(e, '', '\n');
@@ -338,14 +358,20 @@
     if (e is GenericTypeAliasElement) {
       buffer.write('typedef ');
       writeName(e);
+      writeCodeRange(e);
       writeTypeParameterElements(e.typeParameters);
 
       buffer.write(' = ');
 
-      writeType(e.function.returnType);
-      buffer.write(' Function');
-      writeTypeParameterElements(e.function.typeParameters);
-      writeParameterElements(e.function.parameters);
+      var function = e.function;
+      if (function != null) {
+        writeType(function.returnType);
+        buffer.write(' Function');
+        writeTypeParameterElements(function.typeParameters);
+        writeParameterElements(function.parameters);
+      } else {
+        buffer.write('<null>');
+      }
     } else {
       buffer.write('typedef ');
       writeType2(e.returnType);
@@ -546,6 +572,17 @@
       }
     } else if (e is DoubleLiteral) {
       buffer.write(e.value);
+    } else if (e is GenericFunctionType) {
+      if (e.returnType != null) {
+        writeNode(e.returnType);
+        buffer.write(' ');
+      }
+      buffer.write('Function');
+      if (e.typeParameters != null) {
+        writeList('<', '>', e.typeParameters.typeParameters, ', ', writeNode);
+      }
+      writeList('(', ')', e.parameters.parameters, ', ', writeNode,
+          includeEmpty: true);
     } else if (e is InstanceCreationExpression) {
       if (e.keyword != null) {
         buffer.write(e.keyword.lexeme);
@@ -635,6 +672,12 @@
       }
       writeList('(', ')', e.argumentList.arguments, ', ', writeNode,
           includeEmpty: true);
+    } else if (e is SimpleFormalParameter) {
+      writeNode(e.type);
+      if (e.identifier != null) {
+        buffer.write(' ');
+        buffer.write(e.identifier.name);
+      }
     } else if (e is SimpleIdentifier) {
       if (withConstElements) {
         buffer.writeln();
@@ -705,7 +748,7 @@
     String defaultValueSeparator;
     Expression defaultValue;
     String closeString;
-    if (e.isNotOptional) {
+    if (e.isRequiredPositional) {
       closeString = '';
     } else if (e.isOptionalPositional) {
       buffer.write('[');
@@ -726,12 +769,7 @@
     writeIf(e.isCovariant, 'covariant ');
     writeIf(e.isFinal, 'final ');
 
-    if (e.parameters.isNotEmpty) {
-      var type = e.type as FunctionType;
-      writeType2(type.returnType);
-    } else {
-      writeType2(e.type);
-    }
+    writeType2(e.type);
 
     if (e is FieldFormalParameterElement) {
       buffer.write('this.');
@@ -741,8 +779,9 @@
     writeCodeRange(e);
 
     if (e.parameters.isNotEmpty) {
-      writeList('(', ')', e.parameters, ', ', writeParameterElement,
-          includeEmpty: true);
+      buffer.write('/*');
+      writeList('(', ')', e.parameters, ', ', writeParameterElement);
+      buffer.write('*/');
     }
 
     writeVariableTypeInferenceError(e);
@@ -874,6 +913,7 @@
       writeMetadata(e, '', '\n');
     }
 
+    writeIf(e.isLate, 'late ');
     writeIf(e.isFinal, 'final ');
     writeIf(e.isConst, 'const ');
     writeType2(type);
@@ -904,9 +944,42 @@
       if (type.element.typeParameters.isNotEmpty) {
         writeList('<', '>', type.typeArguments, ', ', writeType);
       }
+    } else if (type is CircularFunctionTypeImpl) {
+      buffer.write('...');
+    } else if (type is FunctionType) {
+      writeType2(type.returnType);
+      buffer.write('Function');
+      writeTypeParameterElements(type.typeFormals);
+      buffer.write('(');
+      bool commaNeeded = false;
+      commaNeeded = _writeParameters(
+          type.parameters.where((p) => p.isRequiredPositional),
+          commaNeeded,
+          '',
+          '');
+      commaNeeded = _writeParameters(
+          type.parameters.where((p) => p.isOptionalPositional),
+          commaNeeded,
+          '[',
+          ']');
+      commaNeeded = _writeParameters(
+          type.parameters.where((p) => p.isNamed), commaNeeded, '{', '}');
+      buffer.write(')');
     } else {
       buffer.write(type.displayName);
     }
+    if (annotateNullability) {
+      switch ((type as TypeImpl).nullabilitySuffix) {
+        case NullabilitySuffix.none:
+          break;
+        case NullabilitySuffix.question:
+          buffer.write('?');
+          break;
+        case NullabilitySuffix.star:
+          buffer.write('*');
+          break;
+      }
+    }
   }
 
   void writeType2(DartType type) {
@@ -915,12 +988,18 @@
   }
 
   void writeTypeParameterElement(TypeParameterElement e) {
+    writeMetadata(e, '', '\n');
     writeName(e);
     writeCodeRange(e);
     if (e.bound != null && !e.bound.isObject) {
       buffer.write(' extends ');
       writeType(e.bound);
     }
+    // TODO(scheglov) print the default type
+//    if (e is TypeParameterElementImpl && e.defaultType != null) {
+//      buffer.write(' = ');
+//      writeType(e.defaultType);
+//    }
   }
 
   void writeTypeParameterElements(List<TypeParameterElement> elements) {
@@ -942,22 +1021,6 @@
     e.functions.forEach(writeFunctionElement);
   }
 
-  void writeExportScope(LibraryElement e) {
-    if (!withExportScope) return;
-
-    buffer.writeln();
-    buffer.writeln('-' * 20);
-    buffer.writeln('Exports:');
-
-    var map = e.exportNamespace.definedNames;
-    var names = map.keys.toList()..sort();
-    for (var name in names) {
-      var element = map[name];
-      var elementLocationStr = _getElementLocationString(element);
-      buffer.writeln('  $name: $elementLocationStr');
-    }
-  }
-
   void writeUri(Source source) {
     if (source != null) {
       Uri uri = source.uri;
@@ -1026,6 +1089,32 @@
     }
     return components.join(';');
   }
+
+  bool _writeParameters(Iterable<ParameterElement> parameters, bool commaNeeded,
+      String prefix, String suffix) {
+    if (parameters.isEmpty) return commaNeeded;
+    if (commaNeeded) {
+      buffer.write(', ');
+      commaNeeded = false;
+    }
+    buffer.write(prefix);
+    for (var parameter in parameters) {
+      if (commaNeeded) {
+        buffer.write(', ');
+      }
+      if (parameter.isRequiredNamed) {
+        buffer.write('required ');
+      }
+      writeType(parameter.type);
+      if (parameter.isNamed) {
+        buffer.write(' ');
+        buffer.write(parameter.name);
+      }
+      commaNeeded = true;
+    }
+    buffer.write(suffix);
+    return commaNeeded;
+  }
 }
 
 class _Replacement {
diff --git a/pkg/analyzer/test/src/summary/expr_builder_test.dart b/pkg/analyzer/test/src/summary/expr_builder_test.dart
index d2c9611..385c03e 100644
--- a/pkg/analyzer/test/src/summary/expr_builder_test.dart
+++ b/pkg/analyzer/test/src/summary/expr_builder_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.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
@@ -296,7 +296,6 @@
   }
 
   void test_list_for() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (i = 0; i < 10; i++) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -305,7 +304,6 @@
   }
 
   void test_list_for_each_with_declaration_typed() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (int i in const []) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -319,7 +317,6 @@
   }
 
   void test_list_for_each_with_declaration_untyped() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (var i in const []) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -333,7 +330,6 @@
   }
 
   void test_list_for_each_with_identifier() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (i in const []) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -342,7 +338,6 @@
   }
 
   void test_list_for_each_with_identifier_await() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[await for (i in const []) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -351,7 +346,6 @@
   }
 
   void test_list_for_empty_condition() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (i = 0;; i++) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -360,7 +354,6 @@
   }
 
   void test_list_for_empty_initializer() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (; i < 10; i++) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -369,7 +362,6 @@
   }
 
   void test_list_for_two_updaters() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (i = 0; i < 10; i++, j++) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -378,7 +370,6 @@
   }
 
   void test_list_for_with_one_declaration_typed() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (int i = 0; i < 10; i++) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -398,7 +389,6 @@
   }
 
   void test_list_for_with_one_declaration_untyped() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (var i = 0; i < 10; i++) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -418,7 +408,6 @@
   }
 
   void test_list_for_with_two_declarations_untyped() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (var i = 0, j = 0; i < 10; j++) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -439,7 +428,6 @@
   }
 
   void test_list_for_with_uninitialized_declaration_untyped() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (var i; i < 10; i++) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -459,7 +447,6 @@
   }
 
   void test_list_for_zero_updaters() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '[for (i = 0; i < 10;) i]';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -488,7 +475,6 @@
   }
 
   void test_map_for() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '{1 : 2, for (i = 0; i < 10; i++) i : i}';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -646,7 +632,6 @@
   }
 
   void test_set_for() {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var sourceText = '{1, for (i = 0; i < 10; i++) i}';
     // Resynthesis inserts synthetic "const" tokens; work around that.
     var expectedText = 'const $sourceText';
@@ -772,8 +757,9 @@
 class ExprBuilderWithConstantUpdateTest extends ResynthesizeTestStrategyTwoPhase
     with ExprBuilderTestHelpers {
   @override
-  ExperimentStatus get experimentStatus =>
-      new ExperimentStatus.fromStrings([EnableString.constant_update_2018]);
+  FeatureSet get featureSet => new FeatureSet.forTesting(
+      sdkVersion: '2.2.2',
+      additionalFeatures: [Feature.constant_update_2018, Feature.triple_shift]);
 
   void test_bitShiftRightLogical() {
     checkSimpleExpression('0 >>> 1');
@@ -782,6 +768,8 @@
 
 @reflectiveTest
 class TokensToStringTest {
+  final featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
+
   void test_empty_list_no_space() {
     // This is an interesting test case because "[]" is scanned as a single
     // token, but the parser splits it into two.
@@ -860,7 +848,8 @@
     var errorListener = AnalysisErrorListener.NULL_LISTENER;
     var reader = new CharSequenceReader(newString);
     var stringSource = new StringSource(newString, null);
-    var scanner = new Scanner(stringSource, reader, errorListener);
+    var scanner = new Scanner(stringSource, reader, errorListener)
+      ..configureFeatures(featureSet);
     var startToken = scanner.tokenize();
     var newTokens = _extractTokenList(startToken);
     expect(newTokens, originalTokens);
@@ -888,9 +877,11 @@
     var errorListener = AnalysisErrorListener.NULL_LISTENER;
     var reader = new CharSequenceReader(sourceText);
     var stringSource = new StringSource(sourceText, null);
-    var scanner = new Scanner(stringSource, reader, errorListener);
+    var scanner = new Scanner(stringSource, reader, errorListener)
+      ..configureFeatures(featureSet);
     var startToken = scanner.tokenize();
-    var parser = new Parser(stringSource, errorListener);
+    var parser =
+        new Parser(stringSource, errorListener, featureSet: featureSet);
     var compilationUnit = parser.parseCompilationUnit(startToken);
     var f = compilationUnit.declarations[0] as FunctionDeclaration;
     var body = f.functionExpression.body as ExpressionFunctionBody;
diff --git a/pkg/analyzer/test/src/summary/linker_test.dart b/pkg/analyzer/test/src/summary/linker_test.dart
index ab21dcd..3a24bb1 100644
--- a/pkg/analyzer/test/src/summary/linker_test.dart
+++ b/pkg/analyzer/test/src/summary/linker_test.dart
@@ -225,7 +225,7 @@
     ClassElementForLink_Class B = library.getContainedName('B');
     expect(B.fields, hasLength(1));
     FieldElementForLink f = B.fields[0];
-    expect(f.type.toString(), '(num) → int');
+    expect(f.type.toString(), 'int Function(num)');
   }
 
   void test_getContainedName_nonStaticField() {
@@ -267,7 +267,7 @@
 ''');
     LibraryElementForLink library = linker.getLibrary(testDartUri);
     expect(_getVariable(library.getContainedName('y')).inferredType.toString(),
-        '() → Null');
+        'Null Function()');
   }
 
   void test_inferredType_closure_fromBundle_identifierSequence() {
@@ -287,7 +287,7 @@
 ''');
     LibraryElementForLink library = linker.getLibrary(testDartUri);
     expect(_getVariable(library.getContainedName('y')).inferredType.toString(),
-        '(D) → E');
+        'E Function(D)');
   }
 
   void test_inferredType_implicitFunctionTypeIndices() {
@@ -327,7 +327,7 @@
     ClassElementForLink_Class cls = library.getContainedName('C');
     expect(cls.fields, hasLength(1));
     var field = cls.fields[0];
-    expect(field.type.toString(), '(<bottom>) → int');
+    expect(field.type.toString(), 'int Function(Never)');
   }
 
   void test_inferredType_instanceField_dynamic() {
@@ -379,7 +379,7 @@
     var method = cls.methods[0];
     expect(method.parameters, hasLength(1));
     var pType = method.parameters[0].type;
-    expect(pType.toString(), '<T,U>(T, U) → Map<T, List<U>>');
+    expect(pType.toString(), 'Map<T, List<U>> Function<T,U>(T, U)');
   }
 
   void test_inferredType_methodReturnType_dynamic() {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 7ec7d23..ec7bbef 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -2,14 +2,16 @@
 // 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:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/summary_sdk.dart';
+import 'package:analyzer/src/summary2/informative_data.dart';
 import 'package:analyzer/src/summary2/link.dart';
 import 'package:analyzer/src/summary2/linked_bundle_context.dart';
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
@@ -41,7 +43,7 @@
     for (var sdkLibrary in sdk.sdkLibraries) {
       var source = sourceFactory.resolveUri(null, sdkLibrary.shortName);
       var text = getFile(source.fullName).readAsStringSync();
-      var unit = parseText(text);
+      var unit = parseText(text, featureSet);
 
       var inputUnits = <LinkInputUnit>[];
       _addLibraryUnits(source, unit, inputUnits);
@@ -50,14 +52,20 @@
       );
     }
 
-    var sdkLinkResult = link(
-      AnalysisOptionsImpl(),
-      sourceFactory,
-      declaredVariables,
-      [],
-      inputLibraries,
+    var elementFactory = LinkedElementFactory(
+      RestrictedAnalysisContext(
+        SynchronousSession(
+          AnalysisOptionsImpl(),
+          declaredVariables,
+        ),
+        sourceFactory,
+      ),
+      _AnalysisSessionForLinking(),
+      Reference.root(),
     );
 
+    var sdkLinkResult = link(elementFactory, inputLibraries);
+
     var bytes = sdkLinkResult.bundle.toBuffer();
     return _sdkBundle = LinkedNodeBundle.fromBuffer(bytes);
   }
@@ -70,60 +78,66 @@
     var inputLibraries = <LinkInputLibrary>[];
     _addNonDartLibraries(Set(), inputLibraries, source);
 
-    var linkResult = link(
-      AnalysisOptionsImpl(),
+    var analysisContext = RestrictedAnalysisContext(
+      SynchronousSession(
+        AnalysisOptionsImpl()..contextFeatures = featureSet,
+        declaredVariables,
+      ),
       sourceFactory,
-      declaredVariables,
-      [sdkBundle],
-      inputLibraries,
     );
 
-    var analysisContext = _FakeAnalysisContext(sourceFactory);
-
-    var rootReference = Reference.root();
-    rootReference.getChild('dart:core').getChild('dynamic').element =
-        DynamicElementImpl.instance;
-
     var elementFactory = LinkedElementFactory(
       analysisContext,
-      null,
-      rootReference,
+      _AnalysisSessionForLinking(),
+      Reference.root(),
     );
     elementFactory.addBundle(
       LinkedBundleContext(elementFactory, sdkBundle),
     );
+
+    var linkResult = link(
+      elementFactory,
+      inputLibraries,
+    );
+
     elementFactory.addBundle(
       LinkedBundleContext(elementFactory, linkResult.bundle),
     );
 
-    var dartCore = elementFactory.libraryOfUri('dart:core');
-    var dartAsync = elementFactory.libraryOfUri('dart:async');
-    var typeProvider = SummaryTypeProvider()
-      ..initializeCore(dartCore)
-      ..initializeAsync(dartAsync);
-    analysisContext.typeProvider = typeProvider;
-    analysisContext.typeSystem = Dart2TypeSystem(typeProvider);
+    // Set informative data.
+    for (var inputLibrary in inputLibraries) {
+      var libraryUriStr = '${inputLibrary.source.uri}';
+      for (var inputUnit in inputLibrary.units) {
+        var unitSource = inputUnit.source;
+        if (unitSource != null) {
+          var unitUriStr = '${unitSource.uri}';
+          var informativeData = createInformativeData(inputUnit.unit);
+          elementFactory.setInformativeData(
+            libraryUriStr,
+            unitUriStr,
+            informativeData,
+          );
+        }
+      }
+    }
 
-    dartCore.createLoadLibraryFunction(typeProvider);
-    dartAsync.createLoadLibraryFunction(typeProvider);
+    if (analysisContext.typeProvider == null) {
+      var dartCore = elementFactory.libraryOfUri('dart:core');
+      var dartAsync = elementFactory.libraryOfUri('dart:async');
+      var typeProvider = SummaryTypeProvider()
+        ..initializeCore(dartCore)
+        ..initializeAsync(dartAsync);
+      analysisContext.typeProvider = typeProvider;
+
+      dartCore.createLoadLibraryFunction(typeProvider);
+      dartAsync.createLoadLibraryFunction(typeProvider);
+    }
 
     return elementFactory.libraryOfUri('${source.uri}');
   }
 
   @override
   @failingTest
-  test_const_constructor_inferred_args() async {
-    await super.test_const_constructor_inferred_args();
-  }
-
-  @override
-  @failingTest
-  test_parameter_covariant_inherited() async {
-    await super.test_parameter_covariant_inherited();
-  }
-
-  @override
-  @failingTest
   test_syntheticFunctionType_genericClosure() async {
     // TODO(scheglov) Bug in TypeSystem.getLeastUpperBound().
     // LUB(<T>(T) → int, <T>(T) → int) gives `(T) → int`, note absence of `<T>`.
@@ -136,7 +150,7 @@
     List<LinkInputUnit> units,
   ) {
     units.add(
-      LinkInputUnit(definingSource, definingUnit),
+      LinkInputUnit(definingSource, false, definingUnit),
     );
     for (var directive in definingUnit.directives) {
       if (directive is PartDirective) {
@@ -149,14 +163,14 @@
 
         if (partSource != null) {
           var text = _readSafely(partSource.fullName);
-          var unit = parseText(text, experimentStatus: experimentStatus);
+          var unit = parseText(text, featureSet);
           units.add(
-            LinkInputUnit(partSource, unit),
+            LinkInputUnit(partSource, false, unit),
           );
         } else {
-          var unit = parseText('', experimentStatus: experimentStatus);
+          var unit = parseText('', featureSet);
           units.add(
-            LinkInputUnit(partSource, unit),
+            LinkInputUnit(partSource, false, unit),
           );
         }
       }
@@ -175,7 +189,7 @@
     }
 
     var text = _readSafely(source.fullName);
-    var unit = parseText(text, experimentStatus: experimentStatus);
+    var unit = parseText(text, featureSet);
 
     var units = <LinkInputUnit>[];
     _addLibraryUnits(source, unit, units);
@@ -209,17 +223,6 @@
   }
 }
 
-class _FakeAnalysisContext implements AnalysisContext {
-  final SourceFactory sourceFactory;
-  TypeProvider typeProvider;
-  Dart2TypeSystem typeSystem;
-
-  _FakeAnalysisContext(this.sourceFactory);
-
-  @override
-  AnalysisOptions get analysisOptions {
-    return AnalysisOptionsImpl();
-  }
-
+class _AnalysisSessionForLinking implements AnalysisSession {
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
index 70ecb30..b4acb72 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
@@ -10,8 +10,8 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ResynthesizeAstStrongTest);
     defineReflectiveTests(ApplyCheckElementTextReplacements);
+    defineReflectiveTests(ResynthesizeAstStrongTest);
   });
 }
 
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index b049e24..b67a6f2 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -5,12 +5,14 @@
 import 'dart:async';
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
@@ -204,6 +206,11 @@
 /// applied to a class implementing [ResynthesizeTestStrategy], along with the
 /// mixin [ResynthesizeTestHelpers].
 mixin ResynthesizeTestCases implements ResynthesizeTestHelpers {
+  FeatureSet get disableNnbd => FeatureSet.forTesting(sdkVersion: '2.2.2');
+
+  FeatureSet get enableNnbd =>
+      FeatureSet.forTesting(additionalFeatures: [Feature.non_nullable]);
+
   test_class_abstract() async {
     var library = await checkLibrary('abstract class C {}');
     checkElementText(library, r'''
@@ -602,7 +609,7 @@
     checkElementText(library, r'''
 class C {
   dynamic x;
-  C((double) → dynamic this.x);
+  C(dynamic Function(double) this.x/*(double b)*/);
 }
 ''');
   }
@@ -617,7 +624,7 @@
     checkElementText(library, r'''
 class C {
   dynamic x;
-  C((double) → int this.x);
+  C(int Function(double) this.x/*(double b)*/);
 }
 ''');
   }
@@ -1000,6 +1007,17 @@
 ''');
   }
 
+  test_class_field_const_late() async {
+    featureSet = enableNnbd;
+    var library =
+        await checkLibrary('class C { static late const int i = 0; }');
+    checkElementText(library, r'''
+class C {
+  static late const int i = 0;
+}
+''');
+  }
+
   test_class_field_implicit_type() async {
     var library = await checkLibrary('class C { var x; }');
     checkElementText(library, r'''
@@ -1009,6 +1027,16 @@
 ''');
   }
 
+  test_class_field_implicit_type_late() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('class C { late var x; }');
+    checkElementText(library, r'''
+class C {
+  late dynamic x;
+}
+''');
+  }
+
   test_class_field_static() async {
     var library = await checkLibrary('class C { static int i; }');
     checkElementText(library, r'''
@@ -1018,6 +1046,16 @@
 ''');
   }
 
+  test_class_field_static_late() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('class C { static late int i; }');
+    checkElementText(library, r'''
+class C {
+  static late int i;
+}
+''');
+  }
+
   test_class_fields() async {
     var library = await checkLibrary('class C { int i; int j; }');
     checkElementText(library, r'''
@@ -1028,6 +1066,17 @@
 ''');
   }
 
+  test_class_fields_late() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('class C { int i; late int j; }');
+    checkElementText(library, r'''
+class C {
+  int i;
+  late int j;
+}
+''');
+  }
+
   test_class_getter_abstract() async {
     var library = await checkLibrary('abstract class C { int get x; }');
     checkElementText(library, r'''
@@ -1153,6 +1202,22 @@
 ''');
   }
 
+  test_class_method_namedAsSupertype() async {
+    var library = await checkLibrary(r'''
+class A {}
+class B extends A {
+  void A() {}
+}
+''');
+    checkElementText(library, r'''
+class A {
+}
+class B extends A {
+  void A() {}
+}
+''');
+  }
+
   test_class_method_params() async {
     var library = await checkLibrary('class C { f(x, y) {} }');
     checkElementText(library, r'''
@@ -1248,7 +1313,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = dynamic Function(C<dynamic> value);
-notSimplyBounded class C<T extends (C<dynamic>) → dynamic> {
+notSimplyBounded class C<T extends dynamic Function(C<dynamic>)> {
 }
 ''');
   }
@@ -1270,12 +1335,21 @@
 class C<T extends D> {}
 class D<T extends C> {}
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+notSimplyBounded class C<T extends D<dynamic>> {
+}
+notSimplyBounded class D<T extends C<dynamic>> {
+}
+''');
+    } else {
+      checkElementText(library, r'''
 notSimplyBounded class C<T extends D<dynamic>> {
 }
 notSimplyBounded class D<T extends C<D<dynamic>>> {
 }
 ''');
+    }
   }
 
   test_class_notSimplyBounded_complex_by_reference_to_cycle() async {
@@ -1324,7 +1398,7 @@
 class C<T extends void Function(T)> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends (T) → void> {
+notSimplyBounded class C<T extends void Function(T)> {
 }
 ''');
   }
@@ -1334,7 +1408,7 @@
 class C<T extends T Function()> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends () → T> {
+notSimplyBounded class C<T extends T Function()> {
 }
 ''');
   }
@@ -1344,7 +1418,7 @@
 class C<T extends void Function()> {}
 ''');
     checkElementText(library, r'''
-class C<T extends () → void> {
+class C<T extends void Function()> {
 }
 ''');
   }
@@ -1360,16 +1434,16 @@
 ''');
     if (isAstBasedSummary) {
       checkElementText(library, r'''
-notSimplyBounded typedef F = dynamic Function(((dynamic) → dynamic) → dynamic value);
-notSimplyBounded typedef G = dynamic Function(((dynamic) → dynamic) → dynamic value);
-notSimplyBounded class C<T extends ((dynamic) → dynamic) → dynamic> {
+notSimplyBounded typedef F = dynamic Function(dynamic Function(dynamic Function(dynamic)) value);
+notSimplyBounded typedef G = dynamic Function(dynamic Function(dynamic) value);
+notSimplyBounded class C<T extends dynamic Function(dynamic Function(dynamic Function(dynamic)))> {
 }
 ''');
     } else {
       checkElementText(library, r'''
-notSimplyBounded typedef F = dynamic Function(((...) → dynamic) → dynamic value);
-notSimplyBounded typedef G = dynamic Function(((...) → dynamic) → dynamic value);
-notSimplyBounded class C<T extends ((...) → dynamic) → dynamic> {
+notSimplyBounded typedef F = dynamic Function(dynamic Function(dynamic Function(...)) value);
+notSimplyBounded typedef G = dynamic Function(dynamic Function(dynamic Function(...)) value);
+notSimplyBounded class C<T extends dynamic Function(dynamic Function(...))> {
 }
 ''');
     }
@@ -1422,6 +1496,54 @@
 ''');
   }
 
+  test_class_ref_nullability_none() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('''
+class C {}
+C c;
+''');
+    checkElementText(
+        library,
+        '''
+class C {
+}
+C c;
+''',
+        annotateNullability: true);
+  }
+
+  test_class_ref_nullability_question() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('''
+class C {}
+C? c;
+''');
+    checkElementText(
+        library,
+        '''
+class C {
+}
+C? c;
+''',
+        annotateNullability: true);
+  }
+
+  test_class_ref_nullability_star() async {
+    featureSet = disableNnbd;
+    var library = await checkLibrary('''
+class C {}
+C c;
+''');
+    checkElementText(
+        library,
+        '''
+class C {
+}
+C* c;
+''',
+        annotateNullability: true);
+  }
+
   test_class_setter_abstract() async {
     var library =
         await checkLibrary('abstract class C { void set x(int value); }');
@@ -1547,6 +1669,19 @@
 ''');
   }
 
+  test_class_supertype_typeArguments_self() async {
+    var library = await checkLibrary('''
+class A<T> {}
+class B extends A<B> {}
+''');
+    checkElementText(library, r'''
+class A<T> {
+}
+class B extends A<B> {
+}
+''');
+  }
+
   test_class_supertype_unresolved() async {
     var library = await checkLibrary('class C extends D {}', allowErrors: true);
     checkElementText(library, r'''
@@ -1619,7 +1754,7 @@
 final f = <U, V>(U x, V y) => y;
 ''');
     checkElementText(library, r'''
-final <U,V>(U, V) → V f;
+final V Function<U, V>(U, V) f;
 ''');
   }
 
@@ -1635,7 +1770,7 @@
 --------------------
 unit: a.dart
 
-final (int) → double f;
+final double Function(int) f;
 ''');
   }
 
@@ -2027,6 +2162,108 @@
         withConstElements: false);
   }
 
+  test_codeRange_functionTypeAlias() async {
+    var library = await checkLibrary('''
+typedef Raw();
+
+/// Comment 1.
+/// Comment 2.
+typedef HasDocComment();
+
+@Object()
+typedef HasAnnotation();
+
+@Object()
+/// Comment 1.
+/// Comment 2.
+typedef AnnotationThenComment();
+
+/// Comment 1.
+/// Comment 2.
+@Object()
+typedef CommentThenAnnotation();
+
+/// Comment 1.
+@Object()
+/// Comment 2.
+typedef CommentAroundAnnotation();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef Raw/*codeOffset=0, codeLength=14*/ = dynamic Function();
+/// Comment 1.
+/// Comment 2.
+typedef HasDocComment/*codeOffset=16, codeLength=54*/ = dynamic Function();
+@Object()
+typedef HasAnnotation/*codeOffset=72, codeLength=34*/ = dynamic Function();
+/// Comment 1.
+/// Comment 2.
+@Object()
+typedef AnnotationThenComment/*codeOffset=108, codeLength=72*/ = dynamic Function();
+/// Comment 1.
+/// Comment 2.
+@Object()
+typedef CommentThenAnnotation/*codeOffset=182, codeLength=72*/ = dynamic Function();
+/// Comment 2.
+@Object()
+typedef CommentAroundAnnotation/*codeOffset=271, codeLength=59*/ = dynamic Function();
+''',
+        withCodeRanges: true,
+        withConstElements: false);
+  }
+
+  test_codeRange_genericTypeAlias() async {
+    var library = await checkLibrary('''
+typedef Raw = Function();
+
+/// Comment 1.
+/// Comment 2.
+typedef HasDocComment = Function();
+
+@Object()
+typedef HasAnnotation = Function();
+
+@Object()
+/// Comment 1.
+/// Comment 2.
+typedef AnnotationThenComment = Function();
+
+/// Comment 1.
+/// Comment 2.
+@Object()
+typedef CommentThenAnnotation = Function();
+
+/// Comment 1.
+@Object()
+/// Comment 2.
+typedef CommentAroundAnnotation = Function();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef Raw/*codeOffset=0, codeLength=25*/ = dynamic Function();
+/// Comment 1.
+/// Comment 2.
+typedef HasDocComment/*codeOffset=27, codeLength=65*/ = dynamic Function();
+@Object()
+typedef HasAnnotation/*codeOffset=94, codeLength=45*/ = dynamic Function();
+/// Comment 1.
+/// Comment 2.
+@Object()
+typedef AnnotationThenComment/*codeOffset=141, codeLength=83*/ = dynamic Function();
+/// Comment 1.
+/// Comment 2.
+@Object()
+typedef CommentThenAnnotation/*codeOffset=226, codeLength=83*/ = dynamic Function();
+/// Comment 2.
+@Object()
+typedef CommentAroundAnnotation/*codeOffset=326, codeLength=70*/ = dynamic Function();
+''',
+        withCodeRanges: true,
+        withConstElements: false);
+  }
+
   test_codeRange_method() async {
     var library = await checkLibrary('''
 class C {
@@ -2211,6 +2448,46 @@
         withConstElements: false);
   }
 
+  test_compilationUnit_nnbd_disabled_via_dart_directive() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('''
+// @dart=2.2
+''');
+    expect(library.isNonNullableByDefault, isFalse);
+  }
+
+  test_compilationUnit_nnbd_disabled_via_feature_set() async {
+    featureSet = disableNnbd;
+    var library = await checkLibrary('');
+    expect(library.isNonNullableByDefault, isFalse);
+  }
+
+  test_compilationUnit_nnbd_enabled() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('');
+    expect(library.isNonNullableByDefault, isTrue);
+  }
+
+  test_const_classField() async {
+    var library = await checkLibrary(r'''
+class C {
+  static const int f1 = 1;
+  static const int f2 = C.f1, f3 = C.f2;
+}
+''');
+    checkElementText(library, r'''
+class C {
+  static const int f1 = 1;
+  static const int f2 =
+        C/*location: test.dart;C*/.
+        f1/*location: test.dart;C;f1?*/;
+  static const int f3 =
+        C/*location: test.dart;C*/.
+        f2/*location: test.dart;C;f2?*/;
+}
+''');
+  }
+
   test_const_constructor_inferred_args() async {
     var library = await checkLibrary('''
 class C<T> {
@@ -2260,6 +2537,66 @@
 ''');
   }
 
+  test_const_inference_downward_list() async {
+    var library = await checkLibrary('''
+class P<T> {
+  const P();
+}
+
+class P1<T> extends P<T> {
+  const P1();
+}
+
+class P2<T> extends P<T> {
+  const P2();
+}
+
+const List<P> values = [
+  P1(),
+  P2<int>(),
+];
+''');
+    if (isAstBasedSummary) {
+      checkElementText(
+          library,
+          '''
+class P<T> {
+  const P();
+}
+class P1<T> extends P<T> {
+  const P1();
+}
+class P2<T> extends P<T> {
+  const P2();
+}
+const List<P<dynamic>> values = /*typeArgs=P<dynamic>*/[/*typeArgs=dynamic*/
+        P1/*location: test.dart;P1*/(),
+        P2/*location: test.dart;P2*/<
+        int/*location: dart:core;int*/>()];
+''',
+          withTypes: true);
+    } else {
+      checkElementText(
+          library,
+          '''
+class P<T> {
+  const P();
+}
+class P1<T> extends P<T> {
+  const P1();
+}
+class P2<T> extends P<T> {
+  const P2();
+}
+const List<P<dynamic>> values = const /*typeArgs=dynamic*/[const /*typeArgs=dynamic*/
+        P1/*location: test.dart;P1*/(), const
+        P2/*location: test.dart;P2*/<
+        int/*location: dart:core;int*/>()];
+''',
+          withTypes: true);
+    }
+  }
+
   test_const_invalid_field_const() async {
     var library = await checkLibrary(r'''
 class C {
@@ -2888,14 +3225,13 @@
 class C {
   static int length() {}
 }
-const () → int v =
+const int Function() v =
         C/*location: test.dart;C*/.
         length/*location: test.dart;C;length*/;
 ''');
   }
 
   test_const_list_if() async {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int>[if (true) 1];
 ''');
@@ -2909,7 +3245,6 @@
   }
 
   test_const_list_if_else() async {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int>[if (true) 1 else 2];
 ''');
@@ -2945,7 +3280,6 @@
   }
 
   test_const_list_spread() async {
-    experimentStatus = ExperimentStatus(spread_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int>[...<int>[1]];
 ''');
@@ -2968,7 +3302,6 @@
   }
 
   test_const_list_spread_null_aware() async {
-    experimentStatus = ExperimentStatus(spread_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int>[...?<int>[1]];
 ''');
@@ -2991,7 +3324,6 @@
   }
 
   test_const_map_if() async {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int, int>{if (true) 1: 2};
 ''');
@@ -3006,7 +3338,6 @@
   }
 
   test_const_map_if_else() async {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int, int>{if (true) 1: 2 else 3: 4];
 ''');
@@ -3044,7 +3375,6 @@
   }
 
   test_const_map_spread() async {
-    experimentStatus = ExperimentStatus(spread_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int, int>{...<int, int>{1: 2}};
 ''');
@@ -3071,7 +3401,6 @@
   }
 
   test_const_map_spread_null_aware() async {
-    experimentStatus = ExperimentStatus(spread_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int, int>{...?<int, int>{1: 2}};
 ''');
@@ -3233,7 +3562,7 @@
 class C {
   static int m(int a, String b) {}
 }
-const (int, String) → int V =
+const int Function(int, String) V =
         C/*location: test.dart;C*/.
         m/*location: test.dart;C;m*/;
 ''');
@@ -3251,7 +3580,7 @@
 ''');
     checkElementText(library, r'''
 import 'a.dart';
-const (int, String) → int V =
+const int Function(int, String) V =
         C/*location: a.dart;C*/.
         m/*location: a.dart;C;m*/;
 ''');
@@ -3269,7 +3598,7 @@
 ''');
     checkElementText(library, r'''
 import 'a.dart' as p;
-const (int, String) → int V =
+const int Function(int, String) V =
         p/*location: test.dart;p*/.
         C/*location: a.dart;C*/.
         m/*location: a.dart;C;m*/;
@@ -3282,7 +3611,7 @@
 const V = foo;
 ''');
     checkElementText(library, r'''
-const () → dynamic V =
+const dynamic Function() V =
         foo/*location: test.dart;foo*/;
 dynamic foo() {}
 ''');
@@ -3294,7 +3623,7 @@
 const V = foo;
 ''');
     checkElementText(library, r'''
-const <P,R>(P) → R V =
+const R Function<P, R>(P) V =
         foo/*location: test.dart;foo*/;
 R foo<P, R>(P p) {}
 ''');
@@ -3310,7 +3639,7 @@
 ''');
     checkElementText(library, r'''
 import 'a.dart';
-const () → dynamic V =
+const dynamic Function() V =
         foo/*location: a.dart;foo*/;
 ''');
   }
@@ -3325,7 +3654,7 @@
 ''');
     checkElementText(library, r'''
 import 'a.dart' as p;
-const () → dynamic V =
+const dynamic Function() V =
         p/*location: test.dart;p*/.
         foo/*location: a.dart;foo*/;
 ''');
@@ -3429,7 +3758,7 @@
     checkElementText(library, r'''
 typedef F = dynamic Function();
 class C {
-  final List<() → dynamic> f;
+  final List<dynamic Function()> f;
 }
 ''');
   }
@@ -3538,7 +3867,6 @@
   }
 
   test_const_set_if() async {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int>{if (true) 1};
 ''');
@@ -3552,7 +3880,6 @@
   }
 
   test_const_set_if_else() async {
-    experimentStatus = ExperimentStatus(control_flow_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int>{if (true) 1 else 2];
 ''');
@@ -3588,7 +3915,6 @@
   }
 
   test_const_set_spread() async {
-    experimentStatus = ExperimentStatus(spread_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int>{...<int>{1}};
 ''');
@@ -3611,7 +3937,6 @@
   }
 
   test_const_set_spread_null_aware() async {
-    experimentStatus = ExperimentStatus(spread_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int>{...?<int>{1}};
 ''');
@@ -3879,7 +4204,7 @@
     if (isAstBasedSummary) {
       checkElementText(library, r'''
 typedef F = int Function(String id);
-const List<(String) → int> v = const <
+const List<int Function(String)> v = const <
         F/*location: test.dart;F*/>[];
 ''');
     } else {
@@ -3887,7 +4212,7 @@
       // `F` must be the reference to `typedef F` element, not the type.
       checkElementText(library, r'''
 typedef F = int Function(String id);
-const List<(String) → int> v = const <
+const List<int Function(String)> v = const <
         null/*location: test.dart;F;-*/>[];
 ''');
     }
@@ -4036,7 +4361,7 @@
     if (isAstBasedSummary) {
       checkElementText(library, r'''
 class C {
-  static const () → dynamic a =
+  static const dynamic Function() a =
         m/*location: test.dart;C;m*/;
   static dynamic m() {}
 }
@@ -4044,7 +4369,7 @@
     } else {
       checkElementText(library, r'''
 class C {
-  static const () → dynamic a =
+  static const dynamic Function() a =
         C/*location: test.dart;C*/.
         m/*location: test.dart;C;m*/;
   static dynamic m() {}
@@ -4788,8 +5113,8 @@
     checkElementText(library, r'''
 typedef F<T> = void Function(T v);
 class X {
-  final (dynamic) → void f;
-  const X({(dynamic) → void this.f:
+  final void Function(dynamic) f;
+  const X({void Function(dynamic) this.f:
         defaultF/*location: test.dart;defaultF*/});
 }
 void defaultF<T>(T v) {}
@@ -5158,7 +5483,7 @@
 ''');
     checkElementText(library, r'''
 typedef F = dynamic Function(int p);
-dynamic main((int) → dynamic f) {}
+dynamic main(dynamic Function(int) f) {}
 ''');
   }
 
@@ -5361,6 +5686,25 @@
         withExportScope: true);
   }
 
+  test_export_show_getter_setter() async {
+    addLibrarySource('/a.dart', '''
+get f => null;
+void set f(value) {}
+''');
+    var library = await checkLibrary('export "a.dart" show f;');
+    checkElementText(
+        library,
+        r'''
+export 'a.dart' show f;
+
+--------------------
+Exports:
+  f: a.dart;f?
+  f=: a.dart;f=
+''',
+        withExportScope: true);
+  }
+
   test_export_typedef() async {
     addLibrarySource('/a.dart', 'typedef F();');
     var library = await checkLibrary('export "a.dart";');
@@ -5529,6 +5873,60 @@
 ''');
   }
 
+  test_field_final_hasInitializer_hasConstConstructor() async {
+    var library = await checkLibrary('''
+class C {
+  final x = 42;
+  const C();
+}
+''');
+    checkElementText(library, r'''
+class C {
+  final int x = 42;
+  const C();
+}
+''');
+  }
+
+  test_field_final_hasInitializer_hasConstConstructor_genericFunctionType() async {
+    var library = await checkLibrary('''
+class A<T> {
+  const A();
+}
+class B {
+  final f = const A<int Function(double a)>();
+  const B();
+}
+''');
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+class A<T> {
+  const A();
+}
+class B {
+  final A<int Function(double)> f = const
+        A/*location: test.dart;A*/<
+        int/*location: dart:core;int*/ Function(
+        double/*location: dart:core;double*/ a)>();
+  const B();
+}
+''');
+    }
+  }
+
+  test_field_final_hasInitializer_noConstConstructor() async {
+    var library = await checkLibrary('''
+class C {
+  final x = 42;
+}
+''');
+    checkElementText(library, r'''
+class C {
+  final int x;
+}
+''');
+  }
+
   test_field_formal_param_inferred_type_implicit() async {
     var library = await checkLibrary('class C extends D { var v; C(this.v); }'
         ' abstract class D { int get v; }');
@@ -5762,6 +6160,22 @@
 ''');
   }
 
+  test_function_hasImplicitReturnType_false() async {
+    var library = await checkLibrary('''
+int f() => 0;
+''');
+    var f = library.definingCompilationUnit.functions.single;
+    expect(f.hasImplicitReturnType, isFalse);
+  }
+
+  test_function_hasImplicitReturnType_true() async {
+    var library = await checkLibrary('''
+f() => 0;
+''');
+    var f = library.definingCompilationUnit.functions.single;
+    expect(f.hasImplicitReturnType, isTrue);
+  }
+
   test_function_parameter_final() async {
     var library = await checkLibrary('f(final x) {}');
     checkElementText(library, r'''
@@ -5793,21 +6207,21 @@
   test_function_parameter_parameters() async {
     var library = await checkLibrary('f(g(x, y)) {}');
     checkElementText(library, r'''
-dynamic f((dynamic, dynamic) → dynamic g) {}
+dynamic f(dynamic Function(dynamic, dynamic) g/*(dynamic x, dynamic y)*/) {}
 ''');
   }
 
   test_function_parameter_return_type() async {
     var library = await checkLibrary('f(int g()) {}');
     checkElementText(library, r'''
-dynamic f(() → int g) {}
+dynamic f(int Function() g) {}
 ''');
   }
 
   test_function_parameter_return_type_void() async {
     var library = await checkLibrary('f(void g()) {}');
     checkElementText(library, r'''
-dynamic f(() → void g) {}
+dynamic f(void Function() g) {}
 ''');
   }
 
@@ -5856,7 +6270,7 @@
   test_function_type_parameter_with_function_typed_parameter() async {
     var library = await checkLibrary('void f<T, U>(T x(U u)) {}');
     checkElementText(library, r'''
-void f<T, U>((U) → T x) {}
+void f<T, U>(T Function(U) x/*(U u)*/) {}
 ''');
   }
 
@@ -5925,6 +6339,45 @@
     expect(y.type.toString(), 'dynamic');
   }
 
+  test_generic_function_type_nullability_none() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('''
+void Function() f;
+''');
+    checkElementText(
+        library,
+        '''
+void Function() f;
+''',
+        annotateNullability: true);
+  }
+
+  test_generic_function_type_nullability_question() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('''
+void Function()? f;
+''');
+    checkElementText(
+        library,
+        '''
+void Function()? f;
+''',
+        annotateNullability: true);
+  }
+
+  test_generic_function_type_nullability_star() async {
+    featureSet = disableNnbd;
+    var library = await checkLibrary('''
+void Function() f;
+''');
+    checkElementText(
+        library,
+        '''
+void Function()* f;
+''',
+        annotateNullability: true);
+  }
+
   test_generic_gClass_gMethodStatic() async {
     var library = await checkLibrary('''
 class C<T, U> {
@@ -5946,7 +6399,7 @@
 int Function(int a, String b) f() => null;
 ''');
     checkElementText(library, r'''
-(int, String) → int f() {}
+int Function(int, String) f() {}
 ''');
   }
 
@@ -5955,7 +6408,7 @@
 void f(int Function(int a, String b) p(num c)) => null;
 ''');
     checkElementText(library, r'''
-void f((num) → (int, String) → int p) {}
+void f(int Function(int, String) Function(num) p/*(num c)*/) {}
 ''');
   }
 
@@ -5964,7 +6417,7 @@
 typedef F = void Function(String a) Function(int b);
 ''');
     checkElementText(library, r'''
-typedef F = (String) → void Function(int b);
+typedef F = void Function(String) Function(int b);
 ''');
   }
 
@@ -5976,7 +6429,7 @@
 ''');
     checkElementText(library, r'''
 class C {
-  (int, String) → int m() {}
+  int Function(int, String) m() {}
 }
 ''');
   }
@@ -5986,7 +6439,7 @@
 void f(int Function(int a, String b) p) => null;
 ''');
     checkElementText(library, r'''
-void f((int, String) → int p) {}
+void f(int Function(int, String) p) {}
 ''');
   }
 
@@ -5995,7 +6448,7 @@
 int Function(int a, String b) v;
 ''');
     checkElementText(library, r'''
-(int, String) → int v;
+int Function(int, String) v;
 ''');
   }
 
@@ -6292,7 +6745,7 @@
     checkElementText(library, '''
 typedef F<T> = D<T, U> Function<U>();
 class C<V> {
-  const C(<U>() → D<V, U> f);
+  const C(D<V, U> Function<U>() f);
 }
 class D<T, U> {
 }
@@ -6316,7 +6769,7 @@
     checkElementText(library, '''
 typedef F = D<T> Function<T>();
 class C {
-  const C(<T>() → D<T> f);
+  const C(D<T> Function<T>() f);
 }
 class D<T> {
 }
@@ -6526,21 +6979,12 @@
 var c = a + 3;
 var d = 4;
 ''');
-    if (isAstBasedSummary) {
-      checkElementText(library, r'''
-dynamic a;
-dynamic b;
-dynamic c;
-int d;
-''');
-    } else {
-      checkElementText(library, r'''
+    checkElementText(library, r'''
 dynamic a/*error: dependencyCycle*/;
 dynamic b/*error: dependencyCycle*/;
 dynamic c/*error: dependencyCycle*/;
 int d;
 ''');
-    }
   }
 
   test_inferred_type_is_typedef() async {
@@ -6550,14 +6994,78 @@
     checkElementText(library, r'''
 typedef F = int Function(String s);
 class C extends D {
-  (String) → int v;
+  int Function(String) v;
 }
 abstract class D {
-  (String) → int get v;
+  int Function(String) get v;
 }
 ''');
   }
 
+  test_inferred_type_nullability_class_ref_none() async {
+    featureSet = enableNnbd;
+    addSource('/a.dart', 'int f() => 0;');
+    var library = await checkLibrary('''
+import 'a.dart';
+var x = f();
+''');
+    checkElementText(
+        library,
+        r'''
+import 'a.dart';
+int x;
+''',
+        annotateNullability: true);
+  }
+
+  test_inferred_type_nullability_class_ref_question() async {
+    featureSet = enableNnbd;
+    addSource('/a.dart', 'int? f() => 0;');
+    var library = await checkLibrary('''
+import 'a.dart';
+var x = f();
+''');
+    checkElementText(
+        library,
+        r'''
+import 'a.dart';
+int? x;
+''',
+        annotateNullability: true);
+  }
+
+  test_inferred_type_nullability_function_type_none() async {
+    featureSet = enableNnbd;
+    addSource('/a.dart', 'void Function() f() => () {};');
+    var library = await checkLibrary('''
+import 'a.dart';
+var x = f();
+''');
+    checkElementText(
+        library,
+        r'''
+import 'a.dart';
+void Function() x;
+''',
+        annotateNullability: true);
+  }
+
+  test_inferred_type_nullability_function_type_question() async {
+    featureSet = enableNnbd;
+    addSource('/a.dart', 'void Function()? f() => () {};');
+    var library = await checkLibrary('''
+import 'a.dart';
+var x = f();
+''');
+    checkElementText(
+        library,
+        r'''
+import 'a.dart';
+void Function()? x;
+''',
+        annotateNullability: true);
+  }
+
   test_inferred_type_refers_to_bound_type_param() async {
     var library = await checkLibrary('''
 class C<T> extends D<int, T> {
@@ -6584,9 +7092,9 @@
 var v = h(/*info:INFERRED_TYPE_CLOSURE*/(y) {});
 ''');
     checkElementText(library, r'''
-typedef F = void Function((String) → int g);
+typedef F = void Function(int Function(String) g/*(String s)*/);
 dynamic v;
-dynamic h(((String) → int) → void f) {}
+dynamic h(void Function(int Function(String)) f) {}
 ''');
   }
 
@@ -6600,10 +7108,10 @@
 }''');
     checkElementText(library, r'''
 class C<T, U> extends D<U, int> {
-  void f(int x, (U) → int g) {}
+  void f(int x, int Function(U) g) {}
 }
 abstract class D<V, W> {
-  void f(int x, (V) → W g);
+  void f(int x, W Function(V) g/*(V s)*/);
 }
 ''');
   }
@@ -6627,7 +7135,7 @@
     checkElementText(library, r'''
 import 'a.dart';
 class C extends D {
-  void f(int x, (String) → int g) {}
+  void f(int x, int Function(String) g) {}
 }
 ''');
   }
@@ -6637,10 +7145,10 @@
         ' abstract class D { void f(int x, int g(String s)); }');
     checkElementText(library, r'''
 class C extends D {
-  void f(int x, (String) → int g) {}
+  void f(int x, int Function(String) g) {}
 }
 abstract class D {
-  void f(int x, (String) → int g);
+  void f(int x, int Function(String) g/*(String s)*/);
 }
 ''');
   }
@@ -6652,7 +7160,7 @@
 ''');
     checkElementText(library, r'''
 dynamic v;
-dynamic f((int, () → void) → void g) {}
+dynamic f(void Function(int, void Function()) g/*(int x, void Function() h)*/) {}
 ''');
   }
 
@@ -6663,7 +7171,7 @@
 ''');
     checkElementText(library, r'''
 dynamic v;
-dynamic f({(int, () → void) → void g}) {}
+dynamic f({void Function(int, void Function()) g/*(int x, void Function() h)*/}) {}
 ''');
   }
 
@@ -6672,10 +7180,10 @@
         ' abstract class D { void set f(int g(String s)); }');
     checkElementText(library, r'''
 class C extends D {
-  void set f((String) → int g) {}
+  void set f(int Function(String) g) {}
 }
 abstract class D {
-  void set f((String) → int g);
+  void set f(int Function(String) g/*(String s)*/);
 }
 ''');
   }
@@ -6757,9 +7265,9 @@
 var v = [f, g];
 ''');
     checkElementText(library, r'''
-List<((String) → int) → Object> v;
-int f((String) → int x) {}
-String g((String) → int x) {}
+List<Object Function(int Function(String))> v;
+int f(int Function(String) x/*(String y)*/) {}
+String g(int Function(String) x/*(String y)*/) {}
 ''');
   }
 
@@ -6797,14 +7305,14 @@
   test_initializer_executable_with_return_type_from_closure() async {
     var library = await checkLibrary('var v = () => 0;');
     checkElementText(library, r'''
-() → int v;
+int Function() v;
 ''');
   }
 
   test_initializer_executable_with_return_type_from_closure_await_dynamic() async {
     var library = await checkLibrary('var v = (f) async => await f;');
     checkElementText(library, r'''
-(dynamic) → Future<dynamic> v;
+Future<dynamic> Function(dynamic) v;
 ''');
   }
 
@@ -6816,7 +7324,7 @@
     // The analyzer type system over-flattens - see dartbug.com/31887
     checkElementText(library, r'''
 import 'dart:async';
-(Future<Future<Future<int>>>) → Future<int> v;
+Future<int> Function(Future<Future<Future<int>>>) v;
 ''');
   }
 
@@ -6827,7 +7335,7 @@
 ''');
     checkElementText(library, r'''
 import 'dart:async';
-(Future<int>) → Future<int> v;
+Future<int> Function(Future<int>) v;
 ''');
   }
 
@@ -6838,7 +7346,7 @@
 ''');
     checkElementText(library, r'''
 import 'dart:async';
-(Future<dynamic>) → Future<dynamic> v;
+Future<dynamic> Function(Future<dynamic>) v;
 ''');
   }
 
@@ -6850,7 +7358,7 @@
 ''');
     checkElementText(library, r'''
 class C {
-  () → int v;
+  int Function() v;
 }
 ''');
   }
@@ -6928,7 +7436,7 @@
     checkElementText(library, r'''
 import 'b.dart';
 class C {
-  (O) → O f() {}
+  O Function(O) f() {}
 }
 ''');
   }
@@ -6940,7 +7448,18 @@
 ''');
     checkElementText(library, r'''
 typedef F<T extends num> = dynamic Function(T p);
-(num) → dynamic f;
+dynamic Function(num) f;
+''');
+  }
+
+  test_instantiateToBounds_genericTypeAlias_simple() async {
+    var library = await checkLibrary('''
+typedef F<T extends num> = S Function<S>(T p);
+F f;
+''');
+    checkElementText(library, r'''
+typedef F<T extends num> = S Function<S>(T p);
+S Function<S>(num) f;
 ''');
   }
 
@@ -7747,7 +8266,7 @@
     checkElementText(library, r'''
 const dynamic a = null;
 dynamic f(@
-        a/*location: test.dart;a?*/ () → dynamic g) {}
+        a/*location: test.dart;a?*/ dynamic Function() g) {}
 ''');
   }
 
@@ -7756,7 +8275,25 @@
     checkElementText(library, r'''
 const dynamic a = null;
 dynamic f([@
-        a/*location: test.dart;a?*/ () → dynamic g = null]) {}
+        a/*location: test.dart;a?*/ dynamic Function() g = null]) {}
+''');
+  }
+
+  test_metadata_genericTypeAlias() async {
+    var library = await checkLibrary(r'''
+const a = null;
+const b = null;
+@a
+@b
+typedef F = void Function();''');
+    checkElementText(library, r'''
+@
+        a/*location: test.dart;a?*/
+@
+        b/*location: test.dart;b?*/
+typedef F = void Function();
+const dynamic a = null;
+const dynamic b = null;
 ''');
   }
 
@@ -7839,6 +8376,29 @@
 ''');
   }
 
+  test_metadata_methodDeclaration_method_mixin() async {
+    var library = await checkLibrary(r'''
+const a = null;
+const b = null;
+mixin M {
+  @a
+  @b
+  m() {}
+}
+''');
+    checkElementText(library, r'''
+mixin M on Object {
+  @
+        a/*location: test.dart;a?*/
+  @
+        b/*location: test.dart;b?*/
+  dynamic m() {}
+}
+const dynamic a = null;
+const dynamic b = null;
+''');
+  }
+
   test_metadata_methodDeclaration_setter() async {
     var library = await checkLibrary('''
 const a = null;
@@ -7857,6 +8417,25 @@
 ''');
   }
 
+  test_metadata_mixinDeclaration() async {
+    var library = await checkLibrary(r'''
+const a = null;
+const b = null;
+@a
+@b
+mixin M {}''');
+    checkElementText(library, r'''
+@
+        a/*location: test.dart;a?*/
+@
+        b/*location: test.dart;b?*/
+mixin M on Object {
+}
+const dynamic a = null;
+const dynamic b = null;
+''');
+  }
+
   test_metadata_partDirective() async {
     addSource('/foo.dart', 'part of L;');
     var library = await checkLibrary('''
@@ -7937,7 +8516,9 @@
   test_metadata_typeParameter_ofClass() async {
     var library = await checkLibrary('const a = null; class C<@a T> {}');
     checkElementText(library, r'''
-class C<T> {
+class C<@
+        a/*location: test.dart;a?*/
+T> {
 }
 const dynamic a = null;
 ''');
@@ -7950,7 +8531,9 @@
 class D {}
 class E {}''');
     checkElementText(library, r'''
-class alias C<T> extends D with E {
+class alias C<@
+        a/*location: test.dart;a?*/
+T> extends D with E {
   synthetic C() = D;
 }
 class D {
@@ -7965,14 +8548,18 @@
     var library = await checkLibrary('const a = null; f<@a T>() {}');
     checkElementText(library, r'''
 const dynamic a = null;
-dynamic f<T>() {}
+dynamic f<@
+        a/*location: test.dart;a?*/
+T>() {}
 ''');
   }
 
   test_metadata_typeParameter_ofTypedef() async {
     var library = await checkLibrary('const a = null; typedef F<@a T>();');
     checkElementText(library, r'''
-typedef F<T> = dynamic Function();
+typedef F<@
+        a/*location: test.dart;a?*/
+T> = dynamic Function();
 const dynamic a = null;
 ''');
   }
@@ -7995,6 +8582,28 @@
 ''');
   }
 
+  test_method_hasImplicitReturnType_false() async {
+    var library = await checkLibrary('''
+class C {
+  int m() => 0;
+}
+''');
+    var c = library.definingCompilationUnit.types.single;
+    var m = c.methods.single;
+    expect(m.hasImplicitReturnType, isFalse);
+  }
+
+  test_method_hasImplicitReturnType_true() async {
+    var library = await checkLibrary('''
+class C {
+  m() => 0;
+}
+''');
+    var c = library.definingCompilationUnit.types.single;
+    var m = c.methods.single;
+    expect(m.hasImplicitReturnType, isTrue);
+  }
+
   test_method_inferred_type_nonStatic_implicit_param() async {
     var library = await checkLibrary('class C extends D { void f(value) {} }'
         ' abstract class D { void f(int value); }');
@@ -8053,7 +8662,7 @@
     var library = await checkLibrary('class C { void f<T, U>(T x(U u)) {} }');
     checkElementText(library, r'''
 class C {
-  void f<T, U>((U) → T x) {}
+  void f<T, U>(T Function(U) x/*(U u)*/) {}
 }
 ''');
   }
@@ -8111,6 +8720,18 @@
 ''');
   }
 
+  test_mixin_field_inferredType_final() async {
+    var library = await checkLibrary('''
+mixin M {
+  final x = 0;
+}''');
+    checkElementText(library, r'''
+mixin M on Object {
+  final int x;
+}
+''');
+  }
+
   test_mixin_implicitObjectSuperclassConstraint() async {
     var library = await checkLibrary(r'''
 mixin M {}
@@ -8121,6 +8742,22 @@
 ''');
   }
 
+  test_mixin_method_namedAsConstraint() async {
+    var library = await checkLibrary(r'''
+class A {}
+mixin B on A {
+  void A() {}
+}
+''');
+    checkElementText(library, r'''
+class A {
+}
+mixin B on A {
+  void A() {}
+}
+''');
+  }
+
   test_nameConflict_exportedAndLocal() async {
     addLibrarySource('/a.dart', 'class C {}');
     addLibrarySource('/c.dart', '''
@@ -8271,7 +8908,7 @@
 typedef F<T extends F> = void Function();
 ''');
     checkElementText(library, r'''
-notSimplyBounded typedef F<T extends () → void> = void Function();
+notSimplyBounded typedef F<T extends void Function()> = void Function();
 ''');
   }
 
@@ -8298,7 +8935,7 @@
 typedef void F<T extends F>();
 ''');
     checkElementText(library, r'''
-notSimplyBounded typedef F<T extends () → void> = void Function();
+notSimplyBounded typedef F<T extends void Function()> = void Function();
 ''');
   }
 
@@ -8410,11 +9047,41 @@
         withOffsets: true);
   }
 
-  test_parameter_covariant() async {
-    var library = await checkLibrary('class C { void m(covariant C c) {} }');
+  test_parameter_covariant_explicit_named() async {
+    var library = await checkLibrary('''
+class A {
+  void m({covariant A a}) {}
+}
+''');
     checkElementText(library, r'''
-class C {
-  void m(covariant C c) {}
+class A {
+  void m({covariant A a}) {}
+}
+''');
+  }
+
+  test_parameter_covariant_explicit_positional() async {
+    var library = await checkLibrary('''
+class A {
+  void m([covariant A a]) {}
+}
+''');
+    checkElementText(library, r'''
+class A {
+  void m([covariant A a]) {}
+}
+''');
+  }
+
+  test_parameter_covariant_explicit_required() async {
+    var library = await checkLibrary('''
+class A {
+  void m(covariant A a) {}
+}
+''');
+    checkElementText(library, r'''
+class A {
+  void m(covariant A a) {}
 }
 ''');
   }
@@ -8438,11 +9105,30 @@
 ''');
   }
 
+  test_parameter_covariant_inherited_named() async {
+    var library = await checkLibrary('''
+class A {
+  void m({covariant A a}) {}
+}
+class B extends A {
+  void m({B a}) {}
+}
+''');
+    checkElementText(library, r'''
+class A {
+  void m({covariant A a}) {}
+}
+class B extends A {
+  void m({covariant B a}) {}
+}
+''');
+  }
+
   test_parameter_parameters() async {
     var library = await checkLibrary('class C { f(g(x, y)) {} }');
     checkElementText(library, r'''
 class C {
-  dynamic f((dynamic, dynamic) → dynamic g) {}
+  dynamic f(dynamic Function(dynamic, dynamic) g/*(dynamic x, dynamic y)*/) {}
 }
 ''');
   }
@@ -8451,7 +9137,7 @@
     var library = await checkLibrary('class C<A, B> { f(A g(B x)) {} }');
     checkElementText(library, r'''
 class C<A, B> {
-  dynamic f((B) → A g) {}
+  dynamic f(A Function(B) g/*(B x)*/) {}
 }
 ''');
   }
@@ -8460,7 +9146,7 @@
     var library = await checkLibrary('class C { f(int g()) {} }');
     checkElementText(library, r'''
 class C {
-  dynamic f(() → int g) {}
+  dynamic f(int Function() g) {}
 }
 ''');
   }
@@ -8469,7 +9155,7 @@
     var library = await checkLibrary('class C { f(void g()) {} }');
     checkElementText(library, r'''
 class C {
-  dynamic f(() → void g) {}
+  dynamic f(void Function() g) {}
 }
 ''');
   }
@@ -8710,7 +9396,7 @@
 bool f() => true;
 ''');
     checkElementText(library, r'''
-final (<bottom>) → int v;
+final int Function(Never) v;
 bool f() {}
 ''');
   }
@@ -8735,7 +9421,7 @@
 ''');
     checkElementText(library, r'''
 class C<T, U> {
-  (T, U) → int v;
+  int Function(T, U) v;
 }
 bool f() {}
 ''');
@@ -8758,7 +9444,7 @@
 bool f() => true;
 ''');
     checkElementText(library, r'''
-final () → int v;
+final int Function() v;
 bool f() {}
 ''');
   }
@@ -8769,7 +9455,7 @@
 bool f() => true;
 ''');
     checkElementText(library, r'''
-final (int, String) → int v;
+final int Function(int, String) v;
 bool f() {}
 ''');
   }
@@ -8824,7 +9510,7 @@
 ''');
     checkElementText(library, '''
 import 'a.dart' deferred as a;
-() → Future<dynamic> x;
+Future<dynamic> Function() x;
 ''');
   }
 
@@ -8833,7 +9519,7 @@
 var x = (int f(String x)) => 0;
 ''');
     checkElementText(library, '''
-((String) → int) → int x;
+int Function(int Function(String)) x;
 ''');
   }
 
@@ -8842,7 +9528,7 @@
 var x = (int Function(String) f) => 0;
 ''');
     checkElementText(library, '''
-((String) → int) → int x;
+int Function(int Function(String)) x;
 ''');
   }
 
@@ -8879,7 +9565,7 @@
 var x = (t) => (u) => t + u;
 ''');
     checkElementText(library, '''
-(dynamic) → (dynamic) → dynamic x;
+dynamic Function(dynamic) Function(dynamic) x;
 ''');
   }
 
@@ -8888,7 +9574,7 @@
 var x = (int t) => (int u) => t + u;
 ''');
     checkElementText(library, '''
-(int) → (int) → int x;
+int Function(int) Function(int) x;
 ''');
   }
 
@@ -8897,7 +9583,7 @@
 var x = ([y: 0]) => y;
 ''');
     checkElementText(library, '''
-([dynamic]) → dynamic x;
+dynamic Function([dynamic]) x;
 ''');
   }
 
@@ -8952,6 +9638,91 @@
 ''');
   }
 
+  test_type_param_generic_function_type_nullability_legacy() async {
+    featureSet = disableNnbd;
+    var library = await checkLibrary('''
+T f<T>(T t) {}
+var g = f;
+''');
+    checkElementText(library, '''
+T Function<T>(T) g;
+T f<T>(T t) {}
+''');
+    var g = library.definingCompilationUnit.topLevelVariables[0];
+    var t = (g.type as FunctionType).typeFormals[0];
+    // TypeParameterElement.type has a nullability suffix of `star` regardless
+    // of whether it appears in a migrated library.
+    expect((t.type as TypeImpl).nullabilitySuffix, NullabilitySuffix.star);
+  }
+
+  test_type_param_generic_function_type_nullability_migrated() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('''
+T f<T>(T t) {}
+var g = f;
+''');
+    checkElementText(library, '''
+T Function<T>(T) g;
+T f<T>(T t) {}
+''');
+    var g = library.definingCompilationUnit.topLevelVariables[0];
+    var t = (g.type as FunctionType).typeFormals[0];
+    // TypeParameterElement.type has a nullability suffix of `star` regardless
+    // of whether it appears in a migrated library.
+    expect((t.type as TypeImpl).nullabilitySuffix, NullabilitySuffix.star);
+  }
+
+  test_type_param_ref_nullability_none() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('''
+class C<T> {
+  T t;
+}
+''');
+    checkElementText(
+        library,
+        '''
+class C<T> {
+  T t;
+}
+''',
+        annotateNullability: true);
+  }
+
+  test_type_param_ref_nullability_question() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('''
+class C<T> {
+  T? t;
+}
+''');
+    checkElementText(
+        library,
+        '''
+class C<T> {
+  T? t;
+}
+''',
+        annotateNullability: true);
+  }
+
+  test_type_param_ref_nullability_star() async {
+    featureSet = disableNnbd;
+    var library = await checkLibrary('''
+class C<T> {
+  T t;
+}
+''');
+    checkElementText(
+        library,
+        '''
+class C<T> {
+  T* t;
+}
+''',
+        annotateNullability: true);
+  }
+
   test_type_reference_lib_to_lib() async {
     var library = await checkLibrary('''
 class C {}
@@ -8972,7 +9743,7 @@
 }
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -8985,7 +9756,7 @@
 part 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 --------------------
 unit: a.dart
 
@@ -9022,7 +9793,7 @@
 
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9052,7 +9823,7 @@
 
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9077,7 +9848,7 @@
 }
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9128,7 +9899,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9140,7 +9911,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9153,7 +9924,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9166,7 +9937,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9178,7 +9949,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9190,7 +9961,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9214,7 +9985,7 @@
 import 'b.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9225,7 +9996,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9233,7 +10004,7 @@
     var library = await checkLibrary('typedef F(); F f;');
     checkElementText(library, r'''
 typedef F = dynamic Function();
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9242,7 +10013,7 @@
         await checkLibrary('typedef U F<T, U>(T t); F<int, String> f;');
     checkElementText(library, r'''
 typedef F<T, U> = U Function(T t);
-(int) → String f;
+String Function(int) f;
 ''');
   }
 
@@ -9250,7 +10021,7 @@
     var library = await checkLibrary('typedef U F<T, U>(T t); F f;');
     checkElementText(library, r'''
 typedef F<T, U> = U Function(T t);
-(dynamic) → dynamic f;
+dynamic Function(dynamic) f;
 ''');
   }
 
@@ -9289,7 +10060,7 @@
     var library = await checkLibrary(
         'typedef F<T> = int Function<S>(List<S> list, num Function<A>(A), T);');
     checkElementText(library, r'''
-typedef F<T> = int Function<S>(List<S> list, <A>(A) → num , T );
+typedef F<T> = int Function<S>(List<S> list, num Function<A>(A) , T );
 ''');
   }
 
@@ -9303,11 +10074,22 @@
     checkElementText(library, r'''
 typedef Foo<S> = S Function<T>(T x);
 class A {
-  <T>(T) → int f;
+  int Function<T>(T) f;
 }
 ''');
   }
 
+  test_typedef_generic_invalid() async {
+    var library = await checkLibrary('''
+typedef F = int;
+F f;
+''');
+    checkElementText(library, r'''
+typedef F = <null>;
+dynamic f;
+''');
+  }
+
   test_typedef_notSimplyBounded_dependency_via_param_type_new_style_name_included() async {
     // F is considered "not simply bounded" because it expands to a type that
     // refers to C, which is not simply bounded.
@@ -9315,19 +10097,11 @@
 typedef F = void Function(C c);
 class C<T extends C<T>> {}
 ''');
-    if (isAstBasedSummary) {
-      checkElementText(library, r'''
-notSimplyBounded typedef F = void Function(C<dynamic> c);
-notSimplyBounded class C<T extends C<T>> {
-}
-''');
-    } else {
-      checkElementText(library, r'''
+    checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> c);
 notSimplyBounded class C<T extends C<T>> {
 }
 ''');
-    }
   }
 
   test_typedef_notSimplyBounded_dependency_via_param_type_new_style_name_omitted() async {
@@ -9337,19 +10111,11 @@
 typedef F = void Function(C);
 class C<T extends C<T>> {}
 ''');
-    if (isAstBasedSummary) {
-      checkElementText(library, r'''
-notSimplyBounded typedef F = void Function(C<dynamic> );
-notSimplyBounded class C<T extends C<T>> {
-}
-''');
-    } else {
-      checkElementText(library, r'''
+    checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> );
 notSimplyBounded class C<T extends C<T>> {
 }
 ''');
-    }
   }
 
   test_typedef_notSimplyBounded_dependency_via_param_type_old_style() async {
@@ -9359,19 +10125,11 @@
 typedef void F(C c);
 class C<T extends C<T>> {}
 ''');
-    if (isAstBasedSummary) {
-      checkElementText(library, r'''
-notSimplyBounded typedef F = void Function(C<dynamic> c);
-notSimplyBounded class C<T extends C<T>> {
-}
-''');
-    } else {
-      checkElementText(library, r'''
+    checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> c);
 notSimplyBounded class C<T extends C<T>> {
 }
 ''');
-    }
   }
 
   test_typedef_notSimplyBounded_dependency_via_return_type_new_style() async {
@@ -9381,19 +10139,11 @@
 typedef F = C Function();
 class C<T extends C<T>> {}
 ''');
-    if (isAstBasedSummary) {
-      checkElementText(library, r'''
-notSimplyBounded typedef F = C<dynamic> Function();
-notSimplyBounded class C<T extends C<T>> {
-}
-''');
-    } else {
-      checkElementText(library, r'''
+    checkElementText(library, r'''
 notSimplyBounded typedef F = C<C<dynamic>> Function();
 notSimplyBounded class C<T extends C<T>> {
 }
 ''');
-    }
   }
 
   test_typedef_notSimplyBounded_dependency_via_return_type_old_style() async {
@@ -9403,39 +10153,31 @@
 typedef C F();
 class C<T extends C<T>> {}
 ''');
-    if (isAstBasedSummary) {
-      checkElementText(library, r'''
-notSimplyBounded typedef F = C<dynamic> Function();
-notSimplyBounded class C<T extends C<T>> {
-}
-''');
-    } else {
-      checkElementText(library, r'''
+    checkElementText(library, r'''
 notSimplyBounded typedef F = C<C<dynamic>> Function();
 notSimplyBounded class C<T extends C<T>> {
 }
 ''');
-    }
   }
 
   test_typedef_parameter_parameters() async {
     var library = await checkLibrary('typedef F(g(x, y));');
     checkElementText(library, r'''
-typedef F = dynamic Function((dynamic, dynamic) → dynamic g);
+typedef F = dynamic Function(dynamic Function(dynamic, dynamic) g/*(dynamic x, dynamic y)*/);
 ''');
   }
 
   test_typedef_parameter_parameters_in_generic_class() async {
     var library = await checkLibrary('typedef F<A, B>(A g(B x));');
     checkElementText(library, r'''
-typedef F<A, B> = dynamic Function((B) → A g);
+typedef F<A, B> = dynamic Function(A Function(B) g/*(B x)*/);
 ''');
   }
 
   test_typedef_parameter_return_type() async {
     var library = await checkLibrary('typedef F(int g());');
     checkElementText(library, r'''
-typedef F = dynamic Function(() → int g);
+typedef F = dynamic Function(int Function() g);
 ''');
   }
 
@@ -9516,22 +10258,16 @@
     var library = await checkLibrary('typedef void F<T extends F>();');
     // Typedefs cannot reference themselves.
     checkElementText(library, r'''
-notSimplyBounded typedef F<T extends () → void> = void Function();
+notSimplyBounded typedef F<T extends void Function()> = void Function();
 ''');
   }
 
   test_typedef_type_parameters_bound_recursive2() async {
     var library = await checkLibrary('typedef void F<T extends List<F>>();');
     // Typedefs cannot reference themselves.
-    if (isAstBasedSummary) {
-      checkElementText(library, r'''
-notSimplyBounded typedef F<T extends List<dynamic>> = void Function();
+    checkElementText(library, r'''
+notSimplyBounded typedef F<T extends List<void Function()>> = void Function();
 ''');
-    } else {
-      checkElementText(library, r'''
-notSimplyBounded typedef F<T extends List<() → void>> = void Function();
-''');
-    }
   }
 
   test_typedef_type_parameters_f_bound_complex() async {
@@ -9786,7 +10522,7 @@
   void f() {}
 }
 C<int> c;
-() → void v;
+void Function() v;
 ''');
   }
 
@@ -9810,6 +10546,14 @@
 ''');
   }
 
+  test_variable_const_late() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('late const int i = 0;');
+    checkElementText(library, r'''
+late const int i = 0;
+''');
+  }
+
   test_variable_documented() async {
     var library = await checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -9832,6 +10576,14 @@
 ''');
   }
 
+  test_variable_final_late() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('late final int x = 0;');
+    checkElementText(library, r'''
+late final int x;
+''');
+  }
+
   test_variable_getterInLib_setterInPart() async {
     addSource('/a.dart', '''
 part of my.lib;
@@ -9935,6 +10687,14 @@
 ''');
   }
 
+  test_variable_late() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('late int x = 0;');
+    checkElementText(library, r'''
+late int x;
+''');
+  }
+
   test_variable_propagatedType_const_noDep() async {
     var library = await checkLibrary('const i = 0;');
     checkElementText(library, r'''
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index e4043ad..10f6ccd 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -2,9 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/parser.dart';
@@ -20,11 +20,9 @@
 
 import 'test_strategies.dart';
 
-/**
- * Convert a summary object (or a portion of one) into a canonical form that
- * can be easily compared using [expect].  If [orderByName] is true, and the
- * object is a [List], it is sorted by the `name` field of its elements.
- */
+/// Convert a summary object (or a portion of one) into a canonical form that
+/// can be easily compared using [expect].  If [orderByName] is true, and the
+/// object is a [List], it is sorted by the `name` field of its elements.
 Object canonicalize(Object obj, {bool orderByName: false}) {
   if (obj is SummaryClass) {
     Map<String, Object> result = <String, Object>{};
@@ -60,20 +58,20 @@
 }
 
 UnlinkedPublicNamespace computePublicNamespaceFromText(
-    String text, Source source) {
+    String text, Source source, FeatureSet featureSet) {
   CharacterReader reader = new CharSequenceReader(text);
   Scanner scanner =
-      new Scanner(source, reader, AnalysisErrorListener.NULL_LISTENER);
-  Parser parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
+      new Scanner(source, reader, AnalysisErrorListener.NULL_LISTENER)
+        ..configureFeatures(featureSet);
+  Parser parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER,
+      featureSet: featureSet);
   CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
   UnlinkedPublicNamespace namespace = new UnlinkedPublicNamespace.fromBuffer(
       public_namespace.computePublicNamespace(unit).toBuffer());
   return namespace;
 }
 
-/**
- * Type of a function that validates an [EntityRef].
- */
+/// Type of a function that validates an [EntityRef].
 typedef void _EntityRefValidator(EntityRef entityRef);
 
 /// Test cases that exercise summary generation in a black-box fashion.
@@ -82,14 +80,15 @@
 /// [SummaryBlackBoxTestStrategy], allowing summary generation to be unit-tested
 /// in a variety of ways.
 mixin SummaryTestCases implements SummaryBlackBoxTestStrategy {
-  /**
-   * Get access to the linked defining compilation unit.
-   */
+  /// Get access to the linked defining compilation unit.
   LinkedUnit get definingUnit => linked.units[0];
 
-  /**
-   * TODO(scheglov) rename "Const" to "Expr" everywhere
-   */
+  FeatureSet get disableNnbd => FeatureSet.forTesting(sdkVersion: '2.2.2');
+
+  FeatureSet get enableNnbd =>
+      FeatureSet.forTesting(additionalFeatures: [Feature.non_nullable]);
+
+  /// TODO(scheglov) rename "Const" to "Expr" everywhere
   void assertUnlinkedConst(UnlinkedExpr constExpr, String sourceRepresentation,
       {bool isValidConst: true,
       List<UnlinkedExprOperation> operators: const <UnlinkedExprOperation>[],
@@ -120,10 +119,8 @@
     }
   }
 
-  /**
-   * Check that [annotations] contains a single entry which is a reference to
-   * a top level variable called `a` in the current library.
-   */
+  /// Check that [annotations] contains a single entry which is a reference to
+  /// a top level variable called `a` in the current library.
   void checkAnnotationA(List<UnlinkedExpr> annotations) {
     expect(annotations, hasLength(1));
     assertUnlinkedConst(annotations[0], 'a', operators: [
@@ -149,32 +146,26 @@
     }
   }
 
-  /**
-   * Verify that the [dependency]th element of the dependency table represents
-   * a file reachable via the given [absoluteUri].
-   */
+  /// Verify that the [dependency]th element of the dependency table represents
+  /// a file reachable via the given [absoluteUri].
   void checkDependency(int dependency, String absoluteUri) {
     expect(dependency, new TypeMatcher<int>());
     expect(linked.dependencies[dependency].uri, absoluteUri);
   }
 
-  /**
-   * Verify that the given [dependency] lists the given
-   * [relativeUris] as its parts.
-   */
+  /// Verify that the given [dependency] lists the given
+  /// [relativeUris] as its parts.
   void checkDependencyParts(
       LinkedDependency dependency, List<String> relativeUris) {
     expect(dependency.parts, relativeUris);
   }
 
-  /**
-   * Check that the given [documentationComment] matches the first
-   * Javadoc-style comment found in [text].
-   *
-   * Note that the algorithm for finding the Javadoc-style comment in [text] is
-   * a simple-minded text search; it is easily confused by corner cases such as
-   * strings containing comments, nested comments, etc.
-   */
+  /// Check that the given [documentationComment] matches the first
+  /// Javadoc-style comment found in [text].
+  ///
+  /// Note that the algorithm for finding the Javadoc-style comment in [text] is
+  /// a simple-minded text search; it is easily confused by corner cases such as
+  /// strings containing comments, nested comments, etc.
   void checkDocumentationComment(
       UnlinkedDocumentationComment documentationComment, String text) {
     expect(documentationComment, isNotNull);
@@ -188,21 +179,17 @@
     expect(documentationComment.text, expectedCommentText);
   }
 
-  /**
-   * Verify that the given [typeRef] represents the type `dynamic`.
-   */
+  /// Verify that the given [typeRef] represents the type `dynamic`.
   void checkDynamicTypeRef(EntityRef typeRef) {
     checkTypeRef(typeRef, null, 'dynamic');
   }
 
-  /**
-   * Verify that the given [exportName] represents a reference to an entity
-   * declared in a file reachable via [absoluteUri], having name [expectedName].
-   * [expectedKind] is the kind of object referenced. [expectedTargetUnit] is
-   * the index of the compilation unit in which the target of the [exportName]
-   * is expected to appear; if not specified it is assumed to be the defining
-   * compilation unit.
-   */
+  /// Verify that the given [exportName] represents a reference to an entity
+  /// declared in a file reachable via [absoluteUri], having name [expectedName].
+  /// [expectedKind] is the kind of object referenced. [expectedTargetUnit] is
+  /// the index of the compilation unit in which the target of the [exportName]
+  /// is expected to appear; if not specified it is assumed to be the defining
+  /// compilation unit.
   void checkExportName(LinkedExportName exportName, String absoluteUri,
       String expectedName, ReferenceKind expectedKind,
       {int expectedTargetUnit: 0}) {
@@ -215,14 +202,12 @@
     expect(exportName.unit, expectedTargetUnit);
   }
 
-  /**
-   * Verify that the dependency table contains an entry for a file reachable
-   * via the given [relativeUri].  If [fullyLinked] is
-   * `true`, then the dependency should be a fully-linked dependency; otherwise
-   * it should be a prelinked dependency.
-   *
-   * The index of the [LinkedDependency] is returned.
-   */
+  /// Verify that the dependency table contains an entry for a file reachable
+  /// via the given [relativeUri].  If [fullyLinked] is
+  /// `true`, then the dependency should be a fully-linked dependency; otherwise
+  /// it should be a prelinked dependency.
+  ///
+  /// The index of the [LinkedDependency] is returned.
   int checkHasDependency(String relativeUri, {bool fullyLinked: false}) {
     List<String> found = <String>[];
     for (int i = 0; i < linked.dependencies.length; i++) {
@@ -240,11 +225,9 @@
     fail('Did not find dependency $relativeUri.  Found: $found');
   }
 
-  /**
-   * Test an inferred type.  If [onlyInStrongMode] is `true` (the default) and
-   * strong mode is disabled, verify that the given [slotId] exists and has no
-   * associated type.  Otherwise, behave as in [checkLinkedTypeSlot].
-   */
+  /// Test an inferred type.  If [onlyInStrongMode] is `true` (the default) and
+  /// strong mode is disabled, verify that the given [slotId] exists and has no
+  /// associated type.  Otherwise, behave as in [checkLinkedTypeSlot].
   void checkInferredTypeSlot(
       int slotId, String absoluteUri, String expectedName,
       {int numTypeArguments: 0,
@@ -263,10 +246,8 @@
         numTypeParameters: numTypeParameters);
   }
 
-  /**
-   * Verify that the dependency table *does not* contain any entries for a file
-   * reachable via the given [relativeUri].
-   */
+  /// Verify that the dependency table *does not* contain any entries for a file
+  /// reachable via the given [relativeUri].
   void checkLacksDependency(String relativeUri) {
     for (LinkedDependency dep in linked.dependencies) {
       if (dep.uri == relativeUri) {
@@ -275,26 +256,22 @@
     }
   }
 
-  /**
-   * Verify that the given [typeRef] represents the type `dynamic`.
-   */
+  /// Verify that the given [typeRef] represents the type `dynamic`.
   void checkLinkedDynamicTypeRef(EntityRef typeRef) {
     checkLinkedTypeRef(typeRef, null, 'dynamic');
   }
 
-  /**
-   * Verify that the given [typeRef] represents a reference to a type declared
-   * in a file reachable via [absoluteUri], having name [expectedName].  Verify
-   * that the number of type arguments is equal to [numTypeArguments].
-   * [expectedKind] is the kind of object referenced.  [linkedSourceUnit] and
-   * [unlinkedSourceUnit] refer to the compilation unit within which the
-   * [typeRef] appears; if not specified they are assumed to refer to the
-   * defining compilation unit. [expectedTargetUnit] is the index of the
-   * compilation unit in which the target of the [typeRef] is expected to
-   * appear; if not specified it is assumed to be the defining compilation unit.
-   * [numTypeParameters] is the number of type parameters of the thing being
-   * referred to.
-   */
+  /// Verify that the given [typeRef] represents a reference to a type declared
+  /// in a file reachable via [absoluteUri], having name [expectedName].  Verify
+  /// that the number of type arguments is equal to [numTypeArguments].
+  /// [expectedKind] is the kind of object referenced.  [linkedSourceUnit] and
+  /// [unlinkedSourceUnit] refer to the compilation unit within which the
+  /// [typeRef] appears; if not specified they are assumed to refer to the
+  /// defining compilation unit. [expectedTargetUnit] is the index of the
+  /// compilation unit in which the target of the [typeRef] is expected to
+  /// appear; if not specified it is assumed to be the defining compilation unit.
+  /// [numTypeParameters] is the number of type parameters of the thing being
+  /// referred to.
   void checkLinkedTypeRef(
       EntityRef typeRef, String absoluteUri, String expectedName,
       {int numTypeArguments: 0,
@@ -317,19 +294,17 @@
         numTypeParameters: numTypeParameters);
   }
 
-  /**
-   * Verify that the given [slotId] represents a reference to a type declared
-   * in a file reachable via [absoluteUri], having name [expectedName].  Verify
-   * that the number of type arguments is equal to [numTypeArguments].
-   * [expectedKind] is the kind of object referenced.  [linkedSourceUnit] and
-   * [unlinkedSourceUnit] refer to the compilation unit within which the
-   * [typeRef] appears; if not specified they are assumed to refer to the
-   * defining compilation unit. [expectedTargetUnit] is the index of the
-   * compilation unit in which the target of the [typeRef] is expected to
-   * appear; if not specified it is assumed to be the defining compilation unit.
-   * [numTypeParameters] is the number of type parameters of the thing being
-   * referred to.
-   */
+  /// Verify that the given [slotId] represents a reference to a type declared
+  /// in a file reachable via [absoluteUri], having name [expectedName].  Verify
+  /// that the number of type arguments is equal to [numTypeArguments].
+  /// [expectedKind] is the kind of object referenced.  [linkedSourceUnit] and
+  /// [unlinkedSourceUnit] refer to the compilation unit within which the
+  /// [typeRef] appears; if not specified they are assumed to refer to the
+  /// defining compilation unit. [expectedTargetUnit] is the index of the
+  /// compilation unit in which the target of the [typeRef] is expected to
+  /// appear; if not specified it is assumed to be the defining compilation unit.
+  /// [numTypeParameters] is the number of type parameters of the thing being
+  /// referred to.
   void checkLinkedTypeSlot(int slotId, String absoluteUri, String expectedName,
       {int numTypeArguments: 0,
       ReferenceKind expectedKind: ReferenceKind.classOrEnum,
@@ -355,10 +330,8 @@
         numTypeParameters: numTypeParameters);
   }
 
-  /**
-   * Verify that the given [typeRef] represents a reference to a type parameter
-   * having the given [deBruijnIndex].
-   */
+  /// Verify that the given [typeRef] represents a reference to a type parameter
+  /// having the given [deBruijnIndex].
   void checkParamTypeRef(EntityRef typeRef, int deBruijnIndex) {
     expect(typeRef, new TypeMatcher<EntityRef>());
     expect(typeRef.reference, 0);
@@ -366,10 +339,8 @@
     expect(typeRef.paramReference, deBruijnIndex);
   }
 
-  /**
-   * Verify that [prefixReference] is a valid reference to a prefix having the
-   * given [name].
-   */
+  /// Verify that [prefixReference] is a valid reference to a prefix having the
+  /// given [name].
   void checkPrefix(int prefixReference, String name) {
     expect(prefixReference, isNot(0));
     expect(unlinkedUnits[0].references[prefixReference].prefixReference, 0);
@@ -379,13 +350,11 @@
     expect(definingUnit.references[prefixReference].unit, 0);
   }
 
-  /**
-   * Check the data structures that are reachable from an index in the
-   * references table.  If the reference in question is an explicit
-   * reference, return the [UnlinkedReference] that is used to make the
-   * explicit reference.  If the type reference in question is an implicit
-   * reference, return `null`.
-   */
+  /// Check the data structures that are reachable from an index in the
+  /// references table.  If the reference in question is an explicit
+  /// reference, return the [UnlinkedReference] that is used to make the
+  /// explicit reference.  If the type reference in question is an implicit
+  /// reference, return `null`.
   UnlinkedReference checkReferenceIndex(
       int referenceIndex, String absoluteUri, String expectedName,
       {ReferenceKind expectedKind: ReferenceKind.classOrEnum,
@@ -434,20 +403,18 @@
     return reference;
   }
 
-  /**
-   * Verify that the given [typeRef] represents a reference to a type declared
-   * in a file reachable via [absoluteUri], having name [expectedName].
-   * If [expectedPrefix] is supplied, verify that the type is reached via the
-   * given prefix.  Verify that the number of type arguments is equal to
-   * [numTypeArguments].  [expectedKind] is the kind of object referenced.
-   * [linkedSourceUnit] and [unlinkedSourceUnit] refer to the compilation unit
-   * within which the [typeRef] appears; if not specified they are assumed to
-   * refer to the defining compilation unit. [expectedTargetUnit] is the index
-   * of the compilation unit in which the target of the [typeRef] is expected
-   * to appear; if not specified it is assumed to be the defining compilation
-   * unit.  [numTypeParameters] is the number of type parameters of the thing
-   * being referred to.
-   */
+  /// Verify that the given [typeRef] represents a reference to a type declared
+  /// in a file reachable via [absoluteUri], having name [expectedName].
+  /// If [expectedPrefix] is supplied, verify that the type is reached via the
+  /// given prefix.  Verify that the number of type arguments is equal to
+  /// [numTypeArguments].  [expectedKind] is the kind of object referenced.
+  /// [linkedSourceUnit] and [unlinkedSourceUnit] refer to the compilation unit
+  /// within which the [typeRef] appears; if not specified they are assumed to
+  /// refer to the defining compilation unit. [expectedTargetUnit] is the index
+  /// of the compilation unit in which the target of the [typeRef] is expected
+  /// to appear; if not specified it is assumed to be the defining compilation
+  /// unit.  [numTypeParameters] is the number of type parameters of the thing
+  /// being referred to.
   void checkTypeRef(EntityRef typeRef, String absoluteUri, String expectedName,
       {String expectedPrefix,
       List<_PrefixExpectation> prefixExpectations,
@@ -458,12 +425,15 @@
       LinkedUnit linkedSourceUnit,
       UnlinkedUnit unlinkedSourceUnit,
       int numTypeParameters: 0,
-      bool unresolvedHasName: false}) {
+      bool unresolvedHasName: false,
+      EntityRefNullabilitySuffix nullabilitySuffix:
+          EntityRefNullabilitySuffix.starOrIrrelevant}) {
     linkedSourceUnit ??= definingUnit;
     expect(typeRef, new TypeMatcher<EntityRef>());
     expect(typeRef.paramReference, 0);
     int index = typeRef.reference;
     expect(typeRef.typeArguments, hasLength(numTypeArguments));
+    expect(typeRef.nullabilitySuffix, nullabilitySuffix);
 
     if (entityKind == EntityRefKind.genericFunctionType) {
       // [GenericFunctionType]s don't have references to check.
@@ -499,10 +469,8 @@
     }
   }
 
-  /**
-   * Verify that the given [typeRef] represents a reference to an unresolved
-   * type.
-   */
+  /// Verify that the given [typeRef] represents a reference to an unresolved
+  /// type.
   void checkUnresolvedTypeRef(
       EntityRef typeRef, String expectedPrefix, String expectedName,
       {LinkedUnit linkedSourceUnit, UnlinkedUnit unlinkedSourceUnit}) {
@@ -515,9 +483,7 @@
         unlinkedSourceUnit: unlinkedSourceUnit);
   }
 
-  /**
-   * Verify that the given [typeRef] represents the type `void`.
-   */
+  /// Verify that the given [typeRef] represents the type `void`.
   void checkVoidTypeRef(EntityRef typeRef) {
     checkTypeRef(typeRef, null, 'void');
   }
@@ -553,11 +519,9 @@
         serializeTypeText('void.T', allowErrors: true), 'void', 'T');
   }
 
-  /**
-   * Find the class with the given [className] in the summary, and return its
-   * [UnlinkedClass] data structure.  If [unit] is not given, the class is
-   * looked for in the defining compilation unit.
-   */
+  /// Find the class with the given [className] in the summary, and return its
+  /// [UnlinkedClass] data structure.  If [unit] is not given, the class is
+  /// looked for in the defining compilation unit.
   UnlinkedClass findClass(String className,
       {bool failIfAbsent: false, UnlinkedUnit unit}) {
     unit ??= unlinkedUnits[0];
@@ -576,11 +540,9 @@
     return result;
   }
 
-  /**
-   * Find the enum with the given [enumName] in the summary, and return its
-   * [UnlinkedEnum] data structure.  If [unit] is not given, the enum is looked
-   * for in the defining compilation unit.
-   */
+  /// Find the enum with the given [enumName] in the summary, and return its
+  /// [UnlinkedEnum] data structure.  If [unit] is not given, the enum is looked
+  /// for in the defining compilation unit.
   UnlinkedEnum findEnum(String enumName,
       {bool failIfAbsent: false, UnlinkedUnit unit}) {
     unit ??= unlinkedUnits[0];
@@ -599,12 +561,10 @@
     return result;
   }
 
-  /**
-   * Find the executable with the given [executableName] in the summary, and
-   * return its [UnlinkedExecutable] data structure.  If [executables] is not
-   * given, then the executable is searched for in the defining compilation
-   * unit.
-   */
+  /// Find the executable with the given [executableName] in the summary, and
+  /// return its [UnlinkedExecutable] data structure.  If [executables] is not
+  /// given, then the executable is searched for in the defining compilation
+  /// unit.
   UnlinkedExecutable findExecutable(String executableName,
       {List<UnlinkedExecutable> executables, bool failIfAbsent: false}) {
     executables ??= unlinkedUnits[0].executables;
@@ -623,10 +583,8 @@
     return result;
   }
 
-  /**
-   * Find the mixin with the given [name] in the summary, and return its
-   * [UnlinkedClass] data structure.
-   */
+  /// Find the mixin with the given [name] in the summary, and return its
+  /// [UnlinkedClass] data structure.
   UnlinkedClass findMixin(String name) {
     UnlinkedClass result;
     for (UnlinkedClass mixin in unlinkedUnits[0].mixins) {
@@ -643,9 +601,7 @@
     return result;
   }
 
-  /**
-   * Find the parameter with the given [name] in [parameters].
-   */
+  /// Find the parameter with the given [name] in [parameters].
   UnlinkedParam findParameter(List<UnlinkedParam> parameters, String name) {
     UnlinkedParam result;
     for (UnlinkedParam parameter in parameters) {
@@ -662,11 +618,9 @@
     return result;
   }
 
-  /**
-   * Find the typedef with the given [typedefName] in the summary, and return
-   * its [UnlinkedTypedef] data structure.  If [unit] is not given, the typedef
-   * is looked for in the defining compilation unit.
-   */
+  /// Find the typedef with the given [typedefName] in the summary, and return
+  /// its [UnlinkedTypedef] data structure.  If [unit] is not given, the typedef
+  /// is looked for in the defining compilation unit.
   UnlinkedTypedef findTypedef(String typedefName,
       {bool failIfAbsent: false, UnlinkedUnit unit}) {
     unit ??= unlinkedUnits[0];
@@ -685,11 +639,9 @@
     return result;
   }
 
-  /**
-   * Find the top level variable with the given [variableName] in the summary,
-   * and return its [UnlinkedVariable] data structure.  If [variables] is not
-   * specified, the variable is looked for in the defining compilation unit.
-   */
+  /// Find the top level variable with the given [variableName] in the summary,
+  /// and return its [UnlinkedVariable] data structure.  If [variables] is not
+  /// specified, the variable is looked for in the defining compilation unit.
   UnlinkedVariable findVariable(String variableName,
       {List<UnlinkedVariable> variables, bool failIfAbsent: false}) {
     variables ??= unlinkedUnits[0].variables;
@@ -708,9 +660,7 @@
     return result;
   }
 
-  /**
-   * Find the entry in [linkedSourceUnit.types] matching [slotId].
-   */
+  /// Find the entry in [linkedSourceUnit.types] matching [slotId].
   EntityRef getTypeRefForSlot(int slotId, {LinkedUnit linkedSourceUnit}) {
     linkedSourceUnit ??= definingUnit;
     for (EntityRef typeRef in linkedSourceUnit.types) {
@@ -721,39 +671,31 @@
     return null;
   }
 
-  /**
-   * Serialize the given library [text] and return the summary of the class
-   * with the given [className].
-   */
+  /// Serialize the given library [text] and return the summary of the class
+  /// with the given [className].
   UnlinkedClass serializeClassText(String text,
       {String className: 'C', bool allowErrors: false}) {
     serializeLibraryText(text, allowErrors: allowErrors);
     return findClass(className, failIfAbsent: true);
   }
 
-  /**
-   * Serialize the given library [text] and return the summary of the enum with
-   * the given [enumName].
-   */
+  /// Serialize the given library [text] and return the summary of the enum with
+  /// the given [enumName].
   UnlinkedEnum serializeEnumText(String text, [String enumName = 'E']) {
     serializeLibraryText(text);
     return findEnum(enumName, failIfAbsent: true);
   }
 
-  /**
-   * Serialize the given library [text] and return the summary of the
-   * executable with the given [executableName].
-   */
+  /// Serialize the given library [text] and return the summary of the
+  /// executable with the given [executableName].
   UnlinkedExecutable serializeExecutableText(String text,
       {String executableName: 'f', bool allowErrors: false}) {
     serializeLibraryText(text, allowErrors: allowErrors);
     return findExecutable(executableName, failIfAbsent: true);
   }
 
-  /**
-   * Serialize the given method [text] and return the summary of the executable
-   * with the given [executableName].
-   */
+  /// Serialize the given method [text] and return the summary of the executable
+  /// with the given [executableName].
   UnlinkedExecutable serializeMethodText(String text,
       [String executableName = 'f']) {
     serializeLibraryText('class C { $text }');
@@ -762,32 +704,26 @@
         failIfAbsent: true);
   }
 
-  /**
-   * Serialize the given library [text] and return the summary of the mixin
-   * with the given [name].
-   */
+  /// Serialize the given library [text] and return the summary of the mixin
+  /// with the given [name].
   UnlinkedClass serializeMixinText(String text,
       {String name: 'M', bool allowErrors: false}) {
     serializeLibraryText(text, allowErrors: allowErrors);
     return findMixin(name);
   }
 
-  /**
-   * Serialize the given library [text] and return the summary of the typedef
-   * with the given [typedefName].
-   */
+  /// Serialize the given library [text] and return the summary of the typedef
+  /// with the given [typedefName].
   UnlinkedTypedef serializeTypedefText(String text,
       [String typedefName = 'F']) {
     serializeLibraryText(text);
     return findTypedef(typedefName, failIfAbsent: true);
   }
 
-  /**
-   * Serialize a type declaration using the given [text] as a type name, and
-   * return a summary of the corresponding [EntityRef].  If the type
-   * declaration needs to refer to types that are not available in core, those
-   * types may be declared in [otherDeclarations].
-   */
+  /// Serialize a type declaration using the given [text] as a type name, and
+  /// return a summary of the corresponding [EntityRef].  If the type
+  /// declaration needs to refer to types that are not available in core, those
+  /// types may be declared in [otherDeclarations].
   EntityRef serializeTypeText(String text,
       {String otherDeclarations: '', bool allowErrors: false}) {
     return serializeVariableText('$otherDeclarations\n$text v;',
@@ -795,29 +731,17 @@
         .type;
   }
 
-  /**
-   * Serialize the given library [text] and return the summary of the variable
-   * with the given [variableName].
-   */
+  /// Serialize the given library [text] and return the summary of the variable
+  /// with the given [variableName].
   UnlinkedVariable serializeVariableText(String text,
-      {String variableName: 'v', bool allowErrors: false}) {
-    serializeLibraryText(text, allowErrors: allowErrors);
+      {String variableName: 'v', bool allowErrors: false, imports: ''}) {
+    if (imports.isNotEmpty && !imports.endsWith('\n')) {
+      imports += '\n';
+    }
+    serializeLibraryText('$imports$text', allowErrors: allowErrors);
     return findVariable(variableName, failIfAbsent: true);
   }
 
-  test_constExpr_binary_bitShiftRightLogical() {
-    experimentStatus = ExperimentStatus(constant_update_2018: true);
-    UnlinkedVariable variable = serializeVariableText('const v = 1 >>> 2;');
-    assertUnlinkedConst(variable.initializer.bodyExpr, '1 >>> 2', operators: [
-      UnlinkedExprOperation.pushInt,
-      UnlinkedExprOperation.pushInt,
-      UnlinkedExprOperation.bitShiftRightLogical
-    ], ints: [
-      1,
-      2
-    ]);
-  }
-
   test_apiSignature() {
     List<int> signature1;
     List<int> signature2;
@@ -1680,6 +1604,26 @@
     }
   }
 
+  test_compilationUnit_nnbd_disabled_via_dart_directive() {
+    featureSet = enableNnbd;
+    serializeLibraryText('''
+// @dart=2.2
+''');
+    expect(unlinkedUnits[0].isNNBD, false);
+  }
+
+  test_compilationUnit_nnbd_disabled_via_feature_set() {
+    featureSet = disableNnbd;
+    serializeLibraryText('');
+    expect(unlinkedUnits[0].isNNBD, false);
+  }
+
+  test_compilationUnit_nnbd_enabled() {
+    featureSet = enableNnbd;
+    serializeLibraryText('');
+    expect(unlinkedUnits[0].isNNBD, true);
+  }
+
   test_constExpr_binary_add() {
     UnlinkedVariable variable = serializeVariableText('const v = 1 + 2;');
     assertUnlinkedConst(variable.initializer.bodyExpr, '1 + 2', operators: [
@@ -1751,6 +1695,24 @@
     ]);
   }
 
+  test_constExpr_binary_bitShiftRightLogical() {
+    featureSet = FeatureSet.forTesting(
+        sdkVersion: '2.2.2',
+        additionalFeatures: [
+          Feature.constant_update_2018,
+          Feature.triple_shift
+        ]);
+    UnlinkedVariable variable = serializeVariableText('const v = 1 >>> 2;');
+    assertUnlinkedConst(variable.initializer.bodyExpr, '1 >>> 2', operators: [
+      UnlinkedExprOperation.pushInt,
+      UnlinkedExprOperation.pushInt,
+      UnlinkedExprOperation.bitShiftRightLogical
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
   test_constExpr_binary_bitXor() {
     UnlinkedVariable variable = serializeVariableText('const v = 1 ^ 2;');
     assertUnlinkedConst(variable.initializer.bodyExpr, '1 ^ 2', operators: [
@@ -1987,6 +1949,57 @@
         operators: [UnlinkedExprOperation.pushParameter], strings: ['T']);
   }
 
+  test_constExpr_function_type_arg_nullability_suffix_none() {
+    featureSet = enableNnbd;
+    var variable =
+        serializeVariableText('const v = const <void Function()>[];');
+    assertUnlinkedConst(
+        variable.initializer.bodyExpr, 'const <void Function()>[]', operators: [
+      UnlinkedExprOperation.makeTypedList
+    ], ints: [
+      0
+    ], referenceValidators: [
+      (EntityRef r) =>
+          expect(r.nullabilitySuffix, EntityRefNullabilitySuffix.none)
+    ]);
+  }
+
+  test_constExpr_function_type_arg_nullability_suffix_question() {
+    featureSet = enableNnbd;
+    var variable =
+        serializeVariableText('const v = const <void Function()?>[];');
+    assertUnlinkedConst(
+        variable.initializer.bodyExpr, 'const <void Function()?>[]',
+        operators: [
+          UnlinkedExprOperation.makeTypedList
+        ],
+        ints: [
+          0
+        ],
+        referenceValidators: [
+          (EntityRef r) =>
+              expect(r.nullabilitySuffix, EntityRefNullabilitySuffix.question)
+        ]);
+  }
+
+  test_constExpr_function_type_arg_nullability_suffix_star() {
+    featureSet = disableNnbd;
+    var variable =
+        serializeVariableText('const v = const <void Function()>[];');
+    assertUnlinkedConst(
+        variable.initializer.bodyExpr, 'const <void Function()>[]',
+        operators: [
+          UnlinkedExprOperation.makeTypedList
+        ],
+        ints: [
+          0
+        ],
+        referenceValidators: [
+          (EntityRef r) => expect(
+              r.nullabilitySuffix, EntityRefNullabilitySuffix.starOrIrrelevant)
+        ]);
+  }
+
   test_constExpr_functionExpression() {
     UnlinkedVariable variable = serializeVariableText('''
 import 'dart:async';
@@ -2768,8 +2781,6 @@
   }
 
   test_constExpr_list_if() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = [if (true) 1];');
     assertUnlinkedConst(variable.initializer.bodyExpr, '[if (true) 1]',
@@ -2786,8 +2797,6 @@
   }
 
   test_constExpr_list_if_else() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = [if (true) 1 else 2];');
     assertUnlinkedConst(variable.initializer.bodyExpr, '[if (true) 1 else 2]',
@@ -2806,8 +2815,6 @@
   }
 
   test_constExpr_list_spread() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable = serializeVariableText('const v = [...[]];');
     assertUnlinkedConst(variable.initializer.bodyExpr, '[...[]]', operators: [
       UnlinkedExprOperation.makeUntypedList,
@@ -2820,8 +2827,6 @@
   }
 
   test_constExpr_list_spread_null_aware() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable = serializeVariableText('const v = [...?[]];');
     assertUnlinkedConst(variable.initializer.bodyExpr, '[...?[]]', operators: [
       UnlinkedExprOperation.makeUntypedList,
@@ -3026,7 +3031,6 @@
   }
 
   test_constExpr_makeTypedSet() {
-    experimentStatus = ExperimentStatus(set_literals: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = const <int>{11, 22, 33};');
     assertUnlinkedConst(
@@ -3047,7 +3051,6 @@
   }
 
   test_constExpr_makeTypedSet_dynamic() {
-    experimentStatus = ExperimentStatus(set_literals: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = const <dynamic>{11, 22, 33};');
     assertUnlinkedConst(
@@ -3065,7 +3068,6 @@
   }
 
   test_constExpr_makeTypedSet_functionType() {
-    experimentStatus = ExperimentStatus(set_literals: true);
     UnlinkedVariable variable =
         serializeVariableText('final v = <void Function(int)>{};');
     assertUnlinkedConst(variable.initializer.bodyExpr, '<void Function(int)>{}',
@@ -3094,7 +3096,6 @@
   }
 
   test_constExpr_makeTypedSet_functionType_withTypeParameters() {
-    experimentStatus = ExperimentStatus(set_literals: true);
     UnlinkedVariable variable = serializeVariableText(
         'final v = <void Function<T>(Function<Q>(T, Q))>{};');
     assertUnlinkedConst(variable.initializer.bodyExpr,
@@ -3186,7 +3187,6 @@
   }
 
   test_constExpr_makeUntypedSet() {
-    experimentStatus = ExperimentStatus(set_literals: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = const {11, 22, 33};');
     assertUnlinkedConst(
@@ -3203,8 +3203,6 @@
   }
 
   test_constExpr_map_if() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = <int, int>{if (true) 1 : 2};');
     assertUnlinkedConst(
@@ -3231,8 +3229,6 @@
   }
 
   test_constExpr_map_if_else() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable = serializeVariableText(
         'const v = <int, int>{if (true) 1 : 2 else 3 : 4};');
     assertUnlinkedConst(
@@ -3264,8 +3260,6 @@
   }
 
   test_constExpr_map_spread() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = <int, String>{...<int, String>{}};');
     assertUnlinkedConst(
@@ -3292,8 +3286,6 @@
   }
 
   test_constExpr_map_spread_null_aware() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = <int, String>{...?<int, String>{}};');
     assertUnlinkedConst(
@@ -4038,8 +4030,6 @@
   }
 
   test_constExpr_set_if() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = <int>{if (true) 1};');
     assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{if (true) 1}',
@@ -4060,8 +4050,6 @@
   }
 
   test_constExpr_set_if_else() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = <int>{if (true) 1 else 2};');
     assertUnlinkedConst(
@@ -4085,8 +4073,6 @@
   }
 
   test_constExpr_set_spread() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = <int>{...<int>{}};');
     assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{...<int>{}}',
@@ -4108,8 +4094,6 @@
   }
 
   test_constExpr_set_spread_null_aware() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = <int>{...?<int>{}};');
     assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{...?<int>{}}',
@@ -4130,6 +4114,133 @@
         ]);
   }
 
+  test_constExpr_type_arg_nullability_suffix_none() {
+    featureSet = enableNnbd;
+    var variable = serializeVariableText('const v = const <int>[];');
+    assertUnlinkedConst(variable.initializer.bodyExpr, 'const <int>[]',
+        operators: [
+          UnlinkedExprOperation.makeTypedList
+        ],
+        ints: [
+          0
+        ],
+        referenceValidators: [
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum,
+              nullabilitySuffix: EntityRefNullabilitySuffix.none)
+        ]);
+  }
+
+  test_constExpr_type_arg_nullability_suffix_question() {
+    featureSet = enableNnbd;
+    var variable = serializeVariableText('const v = const <int?>[];');
+    assertUnlinkedConst(variable.initializer.bodyExpr, 'const <int?>[]',
+        operators: [
+          UnlinkedExprOperation.makeTypedList
+        ],
+        ints: [
+          0
+        ],
+        referenceValidators: [
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum,
+              nullabilitySuffix: EntityRefNullabilitySuffix.question)
+        ]);
+  }
+
+  test_constExpr_type_arg_nullability_suffix_star() {
+    featureSet = disableNnbd;
+    var variable = serializeVariableText('const v = const <int>[];');
+    assertUnlinkedConst(variable.initializer.bodyExpr, 'const <int>[]',
+        operators: [
+          UnlinkedExprOperation.makeTypedList
+        ],
+        ints: [
+          0
+        ],
+        referenceValidators: [
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum,
+              nullabilitySuffix: EntityRefNullabilitySuffix.starOrIrrelevant)
+        ]);
+  }
+
+  test_constExpr_type_nullability_suffix_none() {
+    featureSet = enableNnbd;
+    var variable = serializeVariableText('const v = int;');
+    assertUnlinkedConst(variable.initializer.bodyExpr, 'int', operators: [
+      UnlinkedExprOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+          expectedKind: ReferenceKind.classOrEnum,
+          nullabilitySuffix: EntityRefNullabilitySuffix.none)
+    ]);
+  }
+
+  test_constExpr_type_nullability_suffix_question() {
+    // This is a placeholder for testing that `const v = int?;` is serialized
+    // correctly, if we decide that this syntax is allowed.
+    // TODO(paulberry): fill out this test if necessary.
+    // See https://github.com/dart-lang/language/issues/278
+
+    // var variable = serializeVariableText('const v = int?;', nnbd: true);
+    // assertUnlinkedConst(variable.initializer.bodyExpr, ...);
+  }
+
+  test_constExpr_type_nullability_suffix_star() {
+    featureSet = disableNnbd;
+    var variable = serializeVariableText('const v = int;');
+    assertUnlinkedConst(variable.initializer.bodyExpr, 'int', operators: [
+      UnlinkedExprOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+          expectedKind: ReferenceKind.classOrEnum,
+          nullabilitySuffix: EntityRefNullabilitySuffix.starOrIrrelevant)
+    ]);
+  }
+
+  test_constExpr_type_prefixed_nullability_suffix_none() {
+    featureSet = enableNnbd;
+    var variable = serializeVariableText('const v = core.int;',
+        imports: 'import "dart:core" as core;');
+    assertUnlinkedConst(variable.initializer.bodyExpr, 'core.int', operators: [
+      UnlinkedExprOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+          expectedKind: ReferenceKind.classOrEnum,
+          prefixExpectations: [
+            _PrefixExpectation(ReferenceKind.prefix, 'core')
+          ],
+          nullabilitySuffix: EntityRefNullabilitySuffix.none)
+    ]);
+  }
+
+  test_constExpr_type_prefixed_nullability_suffix_question() {
+    // This is a placeholder for testing that `const v = core.int?;` is
+    // serialized correctly, if we decide that this syntax is allowed.
+    // TODO(paulberry): fill out this test if necessary.
+    // See https://github.com/dart-lang/language/issues/278
+
+    // var variable = serializeVariableText('const v = core.int?;', imports: 'import "dart:core: as core;', nnbd: true);
+    // assertUnlinkedConst(variable.initializer.bodyExpr, ...);
+  }
+
+  test_constExpr_type_prefixed_nullability_suffix_star() {
+    featureSet = disableNnbd;
+    var variable = serializeVariableText('const v = core.int;',
+        imports: 'import "dart:core" as core;');
+    assertUnlinkedConst(variable.initializer.bodyExpr, 'core.int', operators: [
+      UnlinkedExprOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+          expectedKind: ReferenceKind.classOrEnum,
+          prefixExpectations: [
+            _PrefixExpectation(ReferenceKind.prefix, 'core')
+          ],
+          nullabilitySuffix: EntityRefNullabilitySuffix.starOrIrrelevant)
+    ]);
+  }
+
   test_constructor() {
     String text = 'class C { C(); }';
     UnlinkedExecutable executable =
@@ -4525,7 +4636,7 @@
 ''').executables);
     UnlinkedParam param = executable.parameters[0];
     expect(param.isFunctionTyped, isTrue);
-    expect(param.kind, UnlinkedParamKind.positional);
+    expect(param.kind, UnlinkedParamKind.optionalPositional);
     expect(param.defaultValueCode, 'foo');
     assertUnlinkedConst(param.initializer.bodyExpr, 'foo', operators: [
       UnlinkedExprOperation.pushReference
@@ -4558,7 +4669,7 @@
         executables: serializeClassText('class C { C({this.x}); final x; }')
             .executables);
     UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.kind, UnlinkedParamKind.named);
+    expect(parameter.kind, UnlinkedParamKind.optionalNamed);
     expect(parameter.initializer, isNull);
     expect(parameter.defaultValueCode, isEmpty);
   }
@@ -4568,7 +4679,7 @@
         executables: serializeClassText('class C { C({this.x: 42}); final x; }')
             .executables);
     UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.kind, UnlinkedParamKind.named);
+    expect(parameter.kind, UnlinkedParamKind.optionalNamed);
     expect(parameter.initializer, isNotNull);
     expect(parameter.defaultValueCode, '42');
     _assertCodeRange(parameter.codeRange, 13, 10);
@@ -4589,7 +4700,7 @@
         executables: serializeClassText('class C { C([this.x]); final x; }')
             .executables);
     UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.kind, UnlinkedParamKind.positional);
+    expect(parameter.kind, UnlinkedParamKind.optionalPositional);
     expect(parameter.initializer, isNull);
     expect(parameter.defaultValueCode, isEmpty);
   }
@@ -4600,7 +4711,7 @@
             serializeClassText('class C { C([this.x = 42]); final x; }')
                 .executables);
     UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.kind, UnlinkedParamKind.positional);
+    expect(parameter.kind, UnlinkedParamKind.optionalPositional);
     expect(parameter.initializer, isNotNull);
     expect(parameter.defaultValueCode, '42');
     _assertCodeRange(parameter.codeRange, 13, 11);
@@ -4613,7 +4724,7 @@
         executables:
             serializeClassText('class C { C(this.x); final x; }').executables);
     UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.kind, UnlinkedParamKind.required);
+    expect(parameter.kind, UnlinkedParamKind.requiredPositional);
   }
 
   test_constructor_initializing_formal_typedef() {
@@ -4634,7 +4745,7 @@
   final int x;
 }''').executables);
     UnlinkedParam param = executable.parameters[0];
-    expect(param.kind, UnlinkedParamKind.positional);
+    expect(param.kind, UnlinkedParamKind.optionalPositional);
     expect(param.defaultValueCode, '42');
     assertUnlinkedConst(param.initializer.bodyExpr, '42',
         operators: [UnlinkedExprOperation.pushInt], ints: [42]);
@@ -6174,7 +6285,7 @@
 int foo(int a, String b) => 0;
 ''');
     UnlinkedParam param = executable.parameters[0];
-    expect(param.kind, UnlinkedParamKind.positional);
+    expect(param.kind, UnlinkedParamKind.optionalPositional);
     expect(param.initializer, isNotNull);
     expect(param.defaultValueCode, 'foo');
     assertUnlinkedConst(param.initializer.bodyExpr, 'foo', operators: [
@@ -6198,7 +6309,7 @@
   test_executable_param_kind_named() {
     UnlinkedExecutable executable = serializeExecutableText('f({x}) {}');
     UnlinkedParam param = executable.parameters[0];
-    expect(param.kind, UnlinkedParamKind.named);
+    expect(param.kind, UnlinkedParamKind.optionalNamed);
     expect(param.initializer, isNull);
     expect(param.defaultValueCode, isEmpty);
   }
@@ -6206,7 +6317,7 @@
   test_executable_param_kind_named_withDefault() {
     UnlinkedExecutable executable = serializeExecutableText('f({x: 42}) {}');
     UnlinkedParam param = executable.parameters[0];
-    expect(param.kind, UnlinkedParamKind.named);
+    expect(param.kind, UnlinkedParamKind.optionalNamed);
     expect(param.initializer, isNotNull);
     expect(param.defaultValueCode, '42');
     _assertCodeRange(param.codeRange, 3, 5);
@@ -6217,7 +6328,7 @@
   test_executable_param_kind_positional() {
     UnlinkedExecutable executable = serializeExecutableText('f([x]) {}');
     UnlinkedParam param = executable.parameters[0];
-    expect(param.kind, UnlinkedParamKind.positional);
+    expect(param.kind, UnlinkedParamKind.optionalPositional);
     expect(param.initializer, isNull);
     expect(param.defaultValueCode, isEmpty);
   }
@@ -6225,7 +6336,7 @@
   test_executable_param_kind_positional_withDefault() {
     UnlinkedExecutable executable = serializeExecutableText('f([x = 42]) {}');
     UnlinkedParam param = executable.parameters[0];
-    expect(param.kind, UnlinkedParamKind.positional);
+    expect(param.kind, UnlinkedParamKind.optionalPositional);
     expect(param.initializer, isNotNull);
     expect(param.defaultValueCode, '42');
     _assertCodeRange(param.codeRange, 3, 6);
@@ -6236,7 +6347,7 @@
   test_executable_param_kind_required() {
     UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
     UnlinkedParam param = executable.parameters[0];
-    expect(param.kind, UnlinkedParamKind.required);
+    expect(param.kind, UnlinkedParamKind.requiredPositional);
     expect(param.initializer, isNull);
     expect(param.defaultValueCode, isEmpty);
   }
@@ -7664,8 +7775,6 @@
   }
 
   test_expr_list_for() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('int i; var v = [for (i = 0; i < 10; i++) i];');
     assertUnlinkedConst(
@@ -7706,8 +7815,6 @@
   }
 
   test_expr_list_for_each_with_declaration_typed() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('var v = [for (int i in []) i];');
     assertUnlinkedConst(variable.initializer.bodyExpr, '[for (int i in []) i]',
@@ -7733,8 +7840,6 @@
   }
 
   test_expr_list_for_each_with_declaration_untyped() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('var v = [for (var i in []) i];');
     assertUnlinkedConst(variable.initializer.bodyExpr, '[for (var i in []) i]',
@@ -7757,8 +7862,6 @@
   }
 
   test_expr_list_for_each_with_identifier() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('int i; var v = [for (i in []) i];');
     assertUnlinkedConst(variable.initializer.bodyExpr, '[for (i in []) i]',
@@ -7784,8 +7887,6 @@
   }
 
   test_expr_list_for_each_with_identifier_await() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('int i; var v = [await for (i in []) i];');
     assertUnlinkedConst(
@@ -7812,8 +7913,6 @@
   }
 
   test_expr_list_for_empty_condition() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('int i; var v = [for (i = 0;; i++) i];');
     assertUnlinkedConst(variable.initializer.bodyExpr, '[for (i = 0;; i++) i]',
@@ -7848,8 +7947,6 @@
   }
 
   test_expr_list_for_empty_initializer() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('int i; var v = [for (; i < 10; i++) i];');
     assertUnlinkedConst(
@@ -7885,8 +7982,6 @@
   }
 
   test_expr_list_for_two_updaters() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable = serializeVariableText(
         'int i; int j; var v = [for (i = 0; i < 10; i++, j++) i];');
     assertUnlinkedConst(
@@ -7931,8 +8026,6 @@
   }
 
   test_expr_list_for_with_one_declaration_typed() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('var v = [for (int i = 0; i < 10; i++) i];');
     assertUnlinkedConst(
@@ -7975,8 +8068,6 @@
   }
 
   test_expr_list_for_with_one_declaration_untyped() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('var v = [for (var i = 0; i < 10; i++) i];');
     assertUnlinkedConst(
@@ -8016,8 +8107,6 @@
   }
 
   test_expr_list_for_with_two_declarations_untyped() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable = serializeVariableText(
         'var v = [for (var i = 0, j = 0; i < 10; i++) i];');
     assertUnlinkedConst(variable.initializer.bodyExpr,
@@ -8063,8 +8152,6 @@
   }
 
   test_expr_list_for_with_uninitialized_declaration_untyped() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('var v = [for (var i; i < 10; i++) i];');
     assertUnlinkedConst(
@@ -8103,8 +8190,6 @@
   }
 
   test_expr_list_for_zero_updaters() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable =
         serializeVariableText('int i; var v = [for (i = 0; i < 10;) i];');
     assertUnlinkedConst(
@@ -8170,7 +8255,6 @@
   }
 
   test_expr_makeTypedSet() {
-    experimentStatus = ExperimentStatus(set_literals: true);
     UnlinkedVariable variable =
         serializeVariableText('var v = <int>{11, 22, 33};');
     assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{11, 22, 33}',
@@ -8219,7 +8303,6 @@
   }
 
   test_expr_makeUntypedSet() {
-    experimentStatus = ExperimentStatus(set_literals: true);
     UnlinkedVariable variable = serializeVariableText('var v = {11, 22, 33};');
     assertUnlinkedConst(variable.initializer.bodyExpr, '{11, 22, 33}',
         operators: [
@@ -8233,8 +8316,6 @@
   }
 
   test_expr_map_for() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable = serializeVariableText(
         'int i; var v = {1: 2, for (i = 0; i < 10; i++) i: i};');
     assertUnlinkedConst(
@@ -8284,8 +8365,6 @@
   }
 
   test_expr_set_for() {
-    experimentStatus = ExperimentStatus(
-        control_flow_collections: true, spread_collections: true);
     UnlinkedVariable variable = serializeVariableText(
         'int i; var v = {1, for (i = 0; i < 10; i++) i};');
     assertUnlinkedConst(
@@ -8406,6 +8485,7 @@
     UnlinkedVariable variable = findVariable('i', variables: cls.fields);
     expect(variable, isNotNull);
     expect(variable.isConst, isFalse);
+    expect(variable.isLate, isFalse);
     expect(variable.isStatic, isFalse);
     expect(variable.isFinal, isFalse);
     expect(variable.initializer, isNull);
@@ -8675,9 +8755,28 @@
     expect(variable.inheritsCovariantSlot, isNot(0));
   }
 
+  test_field_late() {
+    featureSet = enableNnbd;
+    UnlinkedClass cls = serializeClassText('class C { late int i; }');
+    UnlinkedVariable variable = findVariable('i', variables: cls.fields);
+    expect(variable, isNotNull);
+    expect(variable.isConst, isFalse);
+    expect(variable.isLate, isTrue);
+    expect(variable.isStatic, isFalse);
+    expect(variable.isFinal, isFalse);
+    expect(variable.initializer, isNull);
+    expect(variable.inheritsCovariantSlot, isNot(0));
+    expect(findExecutable('i', executables: cls.executables), isNull);
+    expect(findExecutable('i=', executables: cls.executables), isNull);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
+    expect(unlinkedUnits[0].publicNamespace.names[0].members, isEmpty);
+  }
+
   test_field_static() {
     UnlinkedVariable variable =
         serializeClassText('class C { static int i; }').fields[0];
+    expect(variable.isLate, isFalse);
     expect(variable.isStatic, isTrue);
     expect(variable.initializer, isNull);
     expect(variable.inheritsCovariantSlot, 0);
@@ -8697,6 +8796,19 @@
   test_field_static_final() {
     UnlinkedVariable variable =
         serializeClassText('class C { static final int i = 0; }').fields[0];
+    expect(variable.isLate, isFalse);
+    expect(variable.isStatic, isTrue);
+    expect(variable.isFinal, isTrue);
+    expect(variable.initializer.bodyExpr, isNull);
+    expect(variable.inheritsCovariantSlot, 0);
+  }
+
+  test_field_static_final_late() {
+    featureSet = enableNnbd;
+    UnlinkedVariable variable =
+        serializeClassText('class C { static late final int i = 0; }')
+            .fields[0];
+    expect(variable.isLate, isTrue);
     expect(variable.isStatic, isTrue);
     expect(variable.isFinal, isTrue);
     expect(variable.initializer.bodyExpr, isNull);
@@ -8714,6 +8826,27 @@
     expect(variable.inheritsCovariantSlot, 0);
   }
 
+  test_field_static_late() {
+    featureSet = enableNnbd;
+    UnlinkedVariable variable =
+        serializeClassText('class C { static late int i; }').fields[0];
+    expect(variable.isLate, isTrue);
+    expect(variable.isStatic, isTrue);
+    expect(variable.initializer, isNull);
+    expect(variable.inheritsCovariantSlot, 0);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
+    expect(unlinkedUnits[0].publicNamespace.names[0].members, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].members[0].name, 'i');
+    expect(unlinkedUnits[0].publicNamespace.names[0].members[0].kind,
+        ReferenceKind.propertyAccessor);
+    expect(
+        unlinkedUnits[0].publicNamespace.names[0].members[0].numTypeParameters,
+        0);
+    expect(
+        unlinkedUnits[0].publicNamespace.names[0].members[0].members, isEmpty);
+  }
+
   test_fully_linked_references_follow_other_references() {
     if (skipFullyLinkedData) {
       return;
@@ -8753,6 +8886,28 @@
     expect(f.inferredReturnTypeSlot, 0);
   }
 
+  test_function_type_nullability_suffix_none() {
+    featureSet = enableNnbd;
+    EntityRef typeRef = serializeTypeText('void Function()');
+    expect(typeRef.entityKind, EntityRefKind.genericFunctionType);
+    expect(typeRef.nullabilitySuffix, EntityRefNullabilitySuffix.none);
+  }
+
+  test_function_type_nullability_suffix_question() {
+    featureSet = enableNnbd;
+    EntityRef typeRef = serializeTypeText('void Function()?');
+    expect(typeRef.entityKind, EntityRefKind.genericFunctionType);
+    expect(typeRef.nullabilitySuffix, EntityRefNullabilitySuffix.question);
+  }
+
+  test_function_type_nullability_suffix_star() {
+    featureSet = disableNnbd;
+    EntityRef typeRef = serializeTypeText('void Function()');
+    expect(typeRef.entityKind, EntityRefKind.genericFunctionType);
+    expect(
+        typeRef.nullabilitySuffix, EntityRefNullabilitySuffix.starOrIrrelevant);
+  }
+
   test_generic_method_in_generic_class() {
     UnlinkedClass cls = serializeClassText(
         'class C<T, U> { void m<V, W>(T t, U u, V v, W w) {} }');
@@ -9369,7 +9524,7 @@
     UnlinkedVariable variable = serializeVariableText('int v = null;');
     expect(variable.initializer.returnType, isNull);
     checkInferredTypeSlot(
-        variable.initializer.inferredReturnTypeSlot, null, '*bottom*',
+        variable.initializer.inferredReturnTypeSlot, null, 'Never',
         onlyInStrongMode: false);
   }
 
@@ -10692,7 +10847,7 @@
     EntityRef inferredType = getTypeRefForSlot(variable.inferredTypeSlot);
     checkLinkedTypeRef(inferredType.syntheticReturnType, 'dart:core', 'int');
     expect(inferredType.syntheticParams, hasLength(1));
-    checkLinkedTypeRef(inferredType.syntheticParams[0].type, null, '*bottom*');
+    checkLinkedTypeRef(inferredType.syntheticParams[0].type, null, 'Never');
   }
 
   test_syntheticFunctionType_inGenericClass() {
@@ -10830,6 +10985,27 @@
     checkTypeRef(m.parameters[0].type, null, 'dynamic');
   }
 
+  test_type_nullability_suffix_none() {
+    featureSet = enableNnbd;
+    EntityRef typeRef = serializeTypeText('int');
+    checkTypeRef(typeRef, 'dart:core', 'int',
+        nullabilitySuffix: EntityRefNullabilitySuffix.none);
+  }
+
+  test_type_nullability_suffix_question() {
+    featureSet = enableNnbd;
+    EntityRef typeRef = serializeTypeText('int?');
+    checkTypeRef(typeRef, 'dart:core', 'int',
+        nullabilitySuffix: EntityRefNullabilitySuffix.question);
+  }
+
+  test_type_nullability_suffix_star() {
+    featureSet = disableNnbd;
+    EntityRef typeRef = serializeTypeText('int');
+    checkTypeRef(typeRef, 'dart:core', 'int',
+        nullabilitySuffix: EntityRefNullabilitySuffix.starOrIrrelevant);
+  }
+
   test_type_param_codeRange() {
     UnlinkedClass cls =
         serializeClassText('class A {} class C<T extends A> {}');
@@ -11500,6 +11676,16 @@
     }
   }
 
+  test_variable_late() {
+    featureSet = enableNnbd;
+    UnlinkedVariable variable =
+        serializeVariableText('late int i;', variableName: 'i');
+    expect(variable.isLate, isTrue);
+    expect(variable.isStatic, isFalse);
+    expect(variable.isConst, isFalse);
+    expect(variable.isFinal, isFalse);
+  }
+
   test_variable_name() {
     UnlinkedVariable variable =
         serializeVariableText('int i;', variableName: 'i');
@@ -11509,6 +11695,7 @@
   test_variable_no_flags() {
     UnlinkedVariable variable =
         serializeVariableText('int i;', variableName: 'i');
+    expect(variable.isLate, isFalse);
     expect(variable.isStatic, isFalse);
     expect(variable.isConst, isFalse);
     expect(variable.isFinal, isFalse);
@@ -11529,6 +11716,7 @@
   test_variable_non_static() {
     UnlinkedVariable variable =
         serializeClassText('class C { int i; }').fields[0];
+    expect(variable.isLate, isFalse);
     expect(variable.isStatic, isFalse);
   }
 
@@ -11536,6 +11724,7 @@
     // Top level variables are considered non-static.
     UnlinkedVariable variable =
         serializeVariableText('int i;', variableName: 'i');
+    expect(variable.isLate, isFalse);
     expect(variable.isStatic, isFalse);
   }
 
@@ -11547,6 +11736,7 @@
   test_variable_static() {
     UnlinkedVariable variable =
         serializeClassText('class C { static int i; }').fields[0];
+    expect(variable.isLate, isFalse);
     expect(variable.isStatic, isTrue);
   }
 
@@ -11556,10 +11746,8 @@
     checkTypeRef(variable.type, 'dart:core', 'int');
   }
 
-  /**
-   * Assert that serializing the given [expr] of form `(a op= 1 + 2) + 3`
-   * uses the given [expectedAssignOperator].
-   */
+  /// Assert that serializing the given [expr] of form `(a op= 1 + 2) + 3`
+  /// uses the given [expectedAssignOperator].
   void _assertAssignmentOperator(
       String expr, UnlinkedExprAssignOperator expectedAssignOperator) {
     UnlinkedVariable variable = serializeVariableText('''
@@ -11606,10 +11794,8 @@
     expect(p.visibleLength, isZero);
   }
 
-  /**
-   * Assert that the [expr] of the form `++a + 2` is serialized with the
-   * [expectedAssignmentOperator].
-   */
+  /// Assert that the [expr] of the form `++a + 2` is serialized with the
+  /// [expectedAssignmentOperator].
   void _assertRefPrefixPostfixIncrementDecrement(
       String expr, UnlinkedExprAssignOperator expectedAssignmentOperator) {
     UnlinkedVariable variable = serializeVariableText('''
@@ -11646,10 +11832,10 @@
     var reader = new CharSequenceReader(sourceText);
     var stringSource = new StringSource(sourceText, null);
     var scanner = new Scanner(stringSource, reader, errorListener)
-      ..enableGtGtGt = true;
+      ..configureFeatures(featureSet);
     var startToken = scanner.tokenize();
-    var parser = new Parser(stringSource, errorListener)
-      ..enableNonNullable = experimentStatus.non_nullable;
+    var parser =
+        new Parser(stringSource, errorListener, featureSet: featureSet);
     var compilationUnit = parser.parseCompilationUnit(startToken);
     var f = compilationUnit.declarations[0] as FunctionDeclaration;
     var body = f.functionExpression.body as ExpressionFunctionBody;
@@ -11658,9 +11844,7 @@
   }
 }
 
-/**
- * Description of expectations for a prelinked prefix reference.
- */
+/// Description of expectations for a prelinked prefix reference.
 class _PrefixExpectation {
   final ReferenceKind kind;
   final String name;
diff --git a/pkg/analyzer/test/src/summary/test_strategies.dart b/pkg/analyzer/test/src/summary/test_strategies.dart
index bc55e22..7f0aa49 100644
--- a/pkg/analyzer/test/src/summary/test_strategies.dart
+++ b/pkg/analyzer/test/src/summary/test_strategies.dart
@@ -3,12 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -35,21 +36,21 @@
 }
 
 CompilationUnit parseText(
-  String text, {
-  ExperimentStatus experimentStatus,
-}) {
-  experimentStatus ??= ExperimentStatus();
+  String text,
+  FeatureSet featureSet,
+) {
+  featureSet ??= FeatureSet.forTesting(sdkVersion: '2.3.0');
   CharSequenceReader reader = new CharSequenceReader(text);
   Scanner scanner =
       new Scanner(null, reader, AnalysisErrorListener.NULL_LISTENER)
-        ..enableGtGtGt = experimentStatus.constant_update_2018;
+        ..configureFeatures(featureSet);
   Token token = scanner.tokenize();
+  // Pass the feature set from the scanner to the parser
+  // because the scanner may have detected a language version comment
+  // and downgraded the feature set it holds.
   Parser parser = new Parser(
-      NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER)
-    ..enableNonNullable = experimentStatus.non_nullable
-    ..enableSpreadCollections = experimentStatus.spread_collections
-    ..enableControlFlowCollections = experimentStatus.control_flow_collections
-    ..enableTripleShift = experimentStatus.triple_shift;
+      NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER,
+      featureSet: scanner.featureSet);
   CompilationUnit unit = parser.parseCompilationUnit(token);
   unit.lineInfo = new LineInfo(scanner.lineStarts);
   return unit;
@@ -96,8 +97,8 @@
 /// The tests themselves can then be provided via mixin, allowing summaries to
 /// be tested in a variety of ways.
 abstract class ResynthesizeTestStrategy {
-  /// The set of [ExperimentStatus] enabled in this test.
-  ExperimentStatus experimentStatus;
+  /// The set of features enabled in this test.
+  FeatureSet featureSet;
 
   void set allowMissingFiles(bool value);
 
@@ -130,7 +131,7 @@
 class ResynthesizeTestStrategyTwoPhase extends AbstractResynthesizeTest
     implements ResynthesizeTestStrategy {
   @override
-  ExperimentStatus experimentStatus = ExperimentStatus();
+  FeatureSet featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
 
   final Set<Source> serializedSources = new Set<Source>();
 
@@ -179,15 +180,15 @@
         .map((Source source) => source.uri.toString())
         .toSet();
 
-    var analysisOptions = AnalysisOptionsImpl()
-      ..enabledExperiments = experimentStatus.toStringList();
+    var analysisOptions = AnalysisOptionsImpl()..contextFeatures = featureSet;
 
     Map<String, LinkedLibrary> linkedSummaries = link(nonSdkLibraryUris,
         getDependency, getUnit, declaredVariables, analysisOptions);
 
+    var synchronousSession =
+        SynchronousSession(analysisOptions, declaredVariables);
     var analysisContext = RestrictedAnalysisContext(
-      analysisOptions,
-      declaredVariables,
+      synchronousSession,
       sourceFactory,
     );
 
@@ -229,8 +230,7 @@
         contents = '';
       }
 
-      CompilationUnit unit =
-          parseText(contents, experimentStatus: experimentStatus);
+      CompilationUnit unit = parseText(contents, featureSet);
 
       UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
       bundleAssembler.addUnlinkedUnit(source, unlinkedUnit);
@@ -311,8 +311,8 @@
 /// The tests themselves can then be provided via mixin, allowing summaries to
 /// be tested in a variety of ways.
 abstract class SummaryBaseTestStrategy {
-  /// The set of [ExperimentStatus] enabled in this test.
-  ExperimentStatus experimentStatus;
+  /// The set of features enabled in this test.
+  FeatureSet featureSet;
 
   /// Add the given package bundle as a dependency so that it may be referenced
   /// by the files under test.
@@ -531,12 +531,12 @@
       new _FilesToLink<UnlinkedUnitBuilder>();
 
   @override
-  ExperimentStatus experimentStatus = ExperimentStatus();
+  FeatureSet featureSet = FeatureSet.forTesting();
 
   _LinkerInputs _linkerInputs;
 
-  AnalysisOptions get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = experimentStatus.toStringList();
+  AnalysisOptions get analysisOptions =>
+      AnalysisOptionsImpl()..contextFeatures = featureSet;
 
   bool get _allowMissingFiles;
 
@@ -547,7 +547,7 @@
 
   @override
   void addNamedSource(String filePath, String contents) {
-    CompilationUnit unit = parseText(contents);
+    CompilationUnit unit = parseText(contents, featureSet);
     UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
     _filesToLink.uriToUnit[absUri(filePath)] = unlinkedUnit;
   }
@@ -572,7 +572,7 @@
   }
 
   UnlinkedUnitBuilder createUnlinkedSummary(Uri uri, String text) =>
-      serializeAstUnlinked(parseText(text, experimentStatus: experimentStatus));
+      serializeAstUnlinked(parseText(text, featureSet));
 
   _LinkerInputs _createLinkerInputs(String text,
       {String path: '/test.dart', String uri}) {
diff --git a/pkg/analyzer/test/src/summary/top_level_inference_test.dart b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
index 77990a8..72e6c9f 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -19,7 +20,6 @@
     defineReflectiveTests(TopLevelInferenceTest);
     defineReflectiveTests(TopLevelInferenceErrorsTest);
     defineReflectiveTests(TopLevelInferenceTestWithSpread);
-    defineReflectiveTests(TopLevelInferenceErrorsTestWithUiAsCode);
 //    defineReflectiveTests(ApplyCheckElementTextReplacements);
   });
 }
@@ -366,14 +366,6 @@
 }
 
 @reflectiveTest
-class TopLevelInferenceErrorsTestWithUiAsCode
-    extends TopLevelInferenceErrorsTest {
-  @override
-  List<String> get enabledExperiments =>
-      [EnableString.spread_collections, EnableString.control_flow_collections];
-}
-
-@reflectiveTest
 class TopLevelInferenceTest extends BaseAnalysisDriverTest {
   test_initializer_additive() async {
     var library = await _encodeDecodeLibrary(r'''
@@ -506,8 +498,8 @@
 ''');
     checkElementText(library, r'''
 import 'dart:async';
-() → Future<int> uValue;
-() → Future<int> uFuture;
+Future<int> Function() uValue;
+Future<int> Function() uFuture;
 int fValue() {}
 Future<int> fFuture() async {}
 ''');
@@ -669,40 +661,106 @@
 ''');
   }
 
-  test_initializer_extractProperty() async {
-    var library = await _encodeDecodeLibrary(r'''
+  test_initializer_extractProperty_explicitlyTyped_differentLibraryCycle() async {
+    newFile('/a.dart', content: r'''
 class C {
-  bool b;
+  int f = 0;
 }
-C f() => null;
-var x = f().b;
+''');
+    var library = await _encodeDecodeLibrary(r'''
+import 'a.dart';
+var x = new C().f;
 ''');
     checkElementText(library, r'''
-class C {
-  bool b;
-}
-bool x;
-C f() {}
+import 'a.dart';
+int x;
 ''');
   }
 
-  test_initializer_extractProperty_inOtherLibraryCycle() async {
-    newFile('/a.dart', content: r'''
-import 'b.dart';
+  test_initializer_extractProperty_explicitlyTyped_sameLibrary() async {
+    var library = await _encodeDecodeLibrary(r'''
+class C {
+  int f = 0;
+}
 var x = new C().f;
 ''');
-    newFile('/b.dart', content: r'''
+    checkElementText(library, r'''
+class C {
+  int f;
+}
+int x;
+''');
+  }
+
+  test_initializer_extractProperty_explicitlyTyped_sameLibraryCycle() async {
+    newFile('/a.dart', content: r'''
+import 'test.dart'; // just do make it part of the library cycle
+class C {
+  int f = 0;
+}
+''');
+    var library = await _encodeDecodeLibrary(r'''
+import 'a.dart';
+var x = new C().f;
+''');
+    checkElementText(library, r'''
+import 'a.dart';
+int x;
+''');
+  }
+
+  test_initializer_extractProperty_implicitlyTyped_differentLibraryCycle() async {
+    newFile('/a.dart', content: r'''
 class C {
   var f = 0;
 }
 ''');
     var library = await _encodeDecodeLibrary(r'''
 import 'a.dart';
-var t1 = x;
+var x = new C().f;
+''');
+    if (AnalysisDriver.useSummary2) {
+      checkElementText(library, r'''
+import 'a.dart';
+int x;
+''');
+    } else {
+      checkElementText(library, r'''
+import 'a.dart';
+dynamic x;
+''');
+    }
+  }
+
+  test_initializer_extractProperty_implicitlyTyped_sameLibrary() async {
+    var library = await _encodeDecodeLibrary(r'''
+class C {
+  var f = 0;
+}
+var x = new C().f;
+''');
+    checkElementText(library, r'''
+class C {
+  int f;
+}
+dynamic x;
+''');
+  }
+
+  test_initializer_extractProperty_implicitlyTyped_sameLibraryCycle() async {
+    newFile('/a.dart', content: r'''
+import 'test.dart'; // just do make it part of the library cycle
+class C {
+  var f = 0;
+}
+''');
+    var library = await _encodeDecodeLibrary(r'''
+import 'a.dart';
+var x = new C().f;
 ''');
     checkElementText(library, r'''
 import 'a.dart';
-dynamic t1;
+dynamic x;
 ''');
   }
 
@@ -795,11 +853,11 @@
     checkElementText(library, r'''
 import 'dart:async';
 Future<int> vFuture;
-() → int v_noParameters_inferredReturnType;
-(String) → int v_hasParameter_withType_inferredReturnType;
-(String) → String v_hasParameter_withType_returnParameter;
-() → Future<int> v_async_returnValue;
-() → Future<int> v_async_returnFuture;
+int Function() v_noParameters_inferredReturnType;
+int Function(String) v_hasParameter_withType_inferredReturnType;
+String Function(String) v_hasParameter_withType_returnParameter;
+Future<int> Function() v_async_returnValue;
+Future<int> Function() v_async_returnFuture;
 ''');
   }
 
@@ -867,14 +925,14 @@
   String instanceClassMethod(int p) {}
 }
 int topLevelVariable;
-(int) → String r_topLevelFunction;
+String Function(int) r_topLevelFunction;
 int r_topLevelVariable;
 int r_topLevelGetter;
 int r_staticClassVariable;
 int r_staticGetter;
-(int) → String r_staticClassMethod;
+String Function(int) r_staticClassMethod;
 A instanceOfA;
-(int) → String r_instanceClassMethod;
+String Function(int) r_instanceClassMethod;
 int get topLevelGetter {}
 String topLevelFunction(int p) {}
 ''');
@@ -1988,12 +2046,12 @@
     checkElementText(library, r'''
 typedef F<T> = dynamic Function();
 class A<T> {
-  () → dynamic get x {}
-  List<() → dynamic> get y {}
+  dynamic Function() get x {}
+  List<dynamic Function()> get y {}
 }
 class B extends A<int> {
-  () → dynamic get x {}
-  List<() → dynamic> get y {}
+  dynamic Function() get x {}
+  List<dynamic Function()> get y {}
 }
 ''');
   }
diff --git a/pkg/analyzer/test/src/summary2/ast_binary_writer_integration_test.dart b/pkg/analyzer/test/src/summary2/ast_binary_writer_integration_test.dart
deleted file mode 100644
index e79a3a7..0000000
--- a/pkg/analyzer/test/src/summary2/ast_binary_writer_integration_test.dart
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright (c) 2019, 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:io';
-
-import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/ast_binary_reader.dart';
-import 'package:analyzer/src/summary2/ast_binary_writer.dart';
-import 'package:analyzer/src/summary2/ast_text_printer.dart';
-import 'package:analyzer/src/summary2/linked_bundle_context.dart';
-import 'package:analyzer/src/summary2/linked_element_factory.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
-import 'package:analyzer/src/summary2/linking_bundle_context.dart';
-import 'package:analyzer/src/summary2/reference.dart';
-import 'package:analyzer/src/summary2/tokens_writer.dart';
-import 'package:front_end/src/testing/package_root.dart' as package_root;
-import 'package:test/test.dart';
-
-import '../dart/ast/parse_base.dart';
-
-main() {
-  group('AstBinaryWriter |', () {
-    _buildTests();
-  });
-}
-
-/// Parse the [code] into AST, serialize using [AstBinaryWriter], read using
-/// [AstBinaryReader], and dump back into code. The resulting code must be
-/// the same as the input [code].
-///
-/// Whitespaces and newlines are normalized and ignored.
-/// Files with parsing errors are silently skipped.
-void _assertCode(ParseBase base, String code) {
-  code = code.trimRight();
-  code = code.replaceAll('\t', ' ');
-  code = code.replaceAll('\r\n', '\n');
-  code = code.replaceAll('\r', '\n');
-
-  LineInfo lineInfo;
-  LinkedNodeUnit linkedNodeUnit;
-  {
-    var path = base.newFile('/home/test/lib/test.dart', content: code).path;
-
-    ParseResult parseResult;
-    try {
-      parseResult = base.parseUnit(path);
-    } catch (e) {
-      return;
-    }
-
-    // Code with parsing errors cannot be restored.
-    if (parseResult.errors.isNotEmpty) {
-      return;
-    }
-
-    lineInfo = parseResult.lineInfo;
-    var originalUnit = parseResult.unit;
-
-    TokensResult tokensResult = TokensWriter().writeTokens(
-      originalUnit.beginToken,
-      originalUnit.endToken,
-    );
-    var tokensContext = tokensResult.toContext();
-
-    var rootReference = Reference.root();
-    var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
-
-    var linkingBundleContext = LinkingBundleContext(dynamicRef);
-    var writer = new AstBinaryWriter(linkingBundleContext, tokensContext);
-    var unitLinkedNode = writer.writeNode(originalUnit);
-
-    linkedNodeUnit = LinkedNodeUnitBuilder(
-      node: unitLinkedNode,
-      tokens: tokensResult.tokens,
-    );
-  }
-
-  var rootReference = Reference.root();
-  var bundleContext = LinkedBundleContext(
-    LinkedElementFactory(null, null, rootReference),
-    LinkedNodeBundleBuilder(
-      references: LinkedNodeReferencesBuilder(name: ['']),
-    ),
-  );
-  var unitContext = LinkedUnitContext(
-    bundleContext,
-    null,
-    0,
-    null,
-    linkedNodeUnit,
-  );
-
-  var reader = AstBinaryReader(unitContext);
-  var deserializedUnit = reader.readNode(linkedNodeUnit.node);
-
-  var buffer = StringBuffer();
-  deserializedUnit.accept(
-    AstTextPrinter(buffer, lineInfo),
-  );
-
-  expect(buffer.toString(), code);
-}
-
-void _buildTests() {
-  var provider = PhysicalResourceProvider.INSTANCE;
-  var pathContext = provider.pathContext;
-
-  var packageRoot = pathContext.normalize(package_root.packageRoot);
-  var dartFiles = Directory(packageRoot)
-      .listSync(recursive: true)
-      .whereType<File>()
-      .where((e) => e.path.endsWith('.dart'))
-      .toList();
-
-  var base = ParseBase();
-  for (var file in dartFiles) {
-    // TODO(scheglov) https://github.com/dart-lang/sdk/issues/36262
-    if (file.path.endsWith('issue_31198.dart')) {
-      continue;
-    }
-
-    var relPath = pathContext.relative(file.path, from: packageRoot);
-    test(relPath, () {
-      var code = file.readAsStringSync();
-      _assertCode(base, code);
-    });
-  }
-}
diff --git a/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart b/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
deleted file mode 100644
index e23f4c1..0000000
--- a/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) 2019, 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:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary2/ast_binary_reader.dart';
-import 'package:analyzer/src/summary2/ast_binary_writer.dart';
-import 'package:analyzer/src/summary2/linked_bundle_context.dart';
-import 'package:analyzer/src/summary2/linked_element_factory.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
-import 'package:analyzer/src/summary2/linking_bundle_context.dart';
-import 'package:analyzer/src/summary2/reference.dart';
-import 'package:analyzer/src/summary2/tokens_writer.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../dart/resolution/driver_resolution.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(AstBinaryWriterTest);
-  });
-}
-
-/// Just a very simple test that at least something works.
-@reflectiveTest
-class AstBinaryWriterTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.non_nullable,
-      EnableString.spread_collections,
-    ];
-
-  test_classTypeAlias() async {
-    _assertUnresolvedCode('''
-mixin M1 {}
-mixin M2 {}
-
-class I1 {}
-class I2 {}
-
-class X = Object with M1, M2 implements I1, I2;
-''');
-  }
-
-  test_configuration() async {
-    _assertUnresolvedCode('''
-import 'dart:math'
-  if (a.b.c == 'd1') 'e1'
-  if (a.b.c == 'd2') 'e2';
-''');
-  }
-
-  test_emptyStatement() async {
-    _assertUnresolvedCode('''
-main() {
-  if (true);
-}
-''');
-  }
-
-  test_forElement() async {
-    _assertUnresolvedCode('''
-main() {
-  return [1, for (var i = 0; i < 10; i++) i * i, 2];
-}
-''');
-  }
-
-  test_ifElement() async {
-    _assertUnresolvedCode('''
-main(bool b) {
-  return [1, if (b) 2 else 3, 4];
-}
-''');
-  }
-
-  test_labeledStatement() async {
-    _assertUnresolvedCode('''
-main() {
-  a: b: 42;
-}
-''');
-  }
-
-  test_scriptTag() async {
-    _assertUnresolvedCode('''
-#!/bin/dart
-
-main() {}
-''');
-  }
-
-  test_simple() async {
-    _assertUnresolvedCode('''
-const zero = 0;
-
-@zero
-class A<T extends num> {}
-
-class B extends A<int> {}
-
-void f() { // ref
-  1 + 2.0;
-  <double>[1, 2];
-}
-''');
-  }
-
-  test_spreadElement() async {
-    _assertUnresolvedCode('''
-main() {
-var a = [1, 2, 3];
-  return [...a];
-}
-''');
-  }
-
-  void _assertUnresolvedCode(String inputCode) {
-    var path = convertPath('/test/lib/test.dart');
-    newFile(path, content: inputCode);
-
-    var parseResult = driver.parseFileSync(path);
-    var originalUnit = parseResult.unit;
-    var originalCode = originalUnit.toSource();
-
-    var tokensResult = TokensWriter().writeTokens(
-      originalUnit.beginToken,
-      originalUnit.endToken,
-    );
-    var tokensContext = tokensResult.toContext();
-
-    var rootReference = Reference.root();
-    var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
-
-    var linkingBundleContext = LinkingBundleContext(dynamicRef);
-    var writer = new AstBinaryWriter(linkingBundleContext, tokensContext);
-    var builder = writer.writeNode(originalUnit);
-
-    var bundleContext = LinkedBundleContext(
-      LinkedElementFactory(null, null, rootReference),
-      LinkedNodeBundleBuilder(
-        references: LinkedNodeReferencesBuilder(name: ['']),
-      ),
-    );
-    var unitContext = LinkedUnitContext(
-      bundleContext,
-      null,
-      0,
-      null,
-      LinkedNodeUnitBuilder(
-        node: builder,
-        tokens: tokensResult.tokens,
-      ),
-    );
-
-    var reader = AstBinaryReader(unitContext);
-    var deserializedUnit = reader.readNode(builder);
-    var deserializedCode = deserializedUnit.toSource();
-
-    expect(deserializedCode, originalCode);
-  }
-}
diff --git a/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart b/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart
index 48bbada..7ff704f 100644
--- a/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart
@@ -30,11 +30,6 @@
 
   var base = ParseBase();
   for (var file in dartFiles) {
-    // TODO(scheglov) https://github.com/dart-lang/sdk/issues/36262
-    if (file.path.endsWith('issue_31198.dart')) {
-      continue;
-    }
-
     var relPath = pathContext.relative(file.path, from: packageRoot);
     test(relPath, () {
       var code = file.readAsStringSync();
diff --git a/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart b/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
index 7e04023..906407f 100644
--- a/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
@@ -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.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/summary2/ast_text_printer.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -13,7 +11,6 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AstTextPrinterTest);
-    defineReflectiveTests(AstTextPrinterWithUiAsCodeTest);
   });
 }
 
@@ -63,6 +60,24 @@
 ''');
   }
 
+  test_forElement() async {
+    assertParseCodeAndPrintAst(this, r'''
+var _ = [1, for (var v in [2, 3, 4]) v, 5];
+''');
+  }
+
+  test_ifElement_then() async {
+    assertParseCodeAndPrintAst(this, r'''
+var _ = [1, if (true) 2, 3];
+''');
+  }
+
+  test_ifElement_thenElse() async {
+    assertParseCodeAndPrintAst(this, r'''
+var _ = [1, if (true) 2 else 3, 4];
+''');
+  }
+
   test_simple() async {
     assertParseCodeAndPrintAst(this, r'''
 class C {
@@ -81,34 +96,6 @@
 class B {}
 ''');
   }
-}
-
-@reflectiveTest
-class AstTextPrinterWithUiAsCodeTest extends ParseBase {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
-  test_forElement() async {
-    assertParseCodeAndPrintAst(this, r'''
-var _ = [1, for (var v in [2, 3, 4]) v, 5];
-''');
-  }
-
-  test_ifElement_then() async {
-    assertParseCodeAndPrintAst(this, r'''
-var _ = [1, if (true) 2, 3];
-''');
-  }
-
-  test_ifElement_thenElse() async {
-    assertParseCodeAndPrintAst(this, r'''
-var _ = [1, if (true) 2 else 3, 4];
-''');
-  }
 
   test_spreadElement() async {
     assertParseCodeAndPrintAst(this, r'''
diff --git a/pkg/analyzer/test/src/summary2/test_all.dart b/pkg/analyzer/test/src/summary2/test_all.dart
index d7b4c0b..bff7e8b 100644
--- a/pkg/analyzer/test/src/summary2/test_all.dart
+++ b/pkg/analyzer/test/src/summary2/test_all.dart
@@ -4,12 +4,10 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'ast_binary_writer_test.dart' as ast_binary_writer;
 import 'ast_text_printer_test.dart' as ast_text_printer;
 
 main() {
   defineReflectiveSuite(() {
-    ast_binary_writer.main();
     ast_text_printer.main();
   }, name: 'summary2');
 }
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 11182d9..e93a4af 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -18,7 +18,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:analyzer/src/lint/registry.dart';
-import 'package:analyzer/src/manifest/manifest_warning_code.dart';
 import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
@@ -238,9 +237,17 @@
         declaredNames.remove('TODO_REGEX');
       } else if (errorType == ParserErrorCode) {
         declaredNames.remove('CONST_AFTER_FACTORY');
-      } else if (errorType == ManifestWarningCode) {
-        declaredNames.remove('NON_RESIZABLE_ACTIVITY');
-        declaredNames.remove('SETTING_ORIENTATION_ON_ACTIVITY');
+        declaredNames.remove('CONST_AND_COVARIANT');
+        declaredNames.remove('CONST_AND_VAR');
+        declaredNames.remove('COVARIANT_AFTER_FINAL');
+        declaredNames.remove('COVARIANT_AFTER_VAR');
+        declaredNames.remove('EXTERNAL_AFTER_CONST');
+        declaredNames.remove('EXTERNAL_AFTER_FACTORY');
+        declaredNames.remove('EXTERNAL_AFTER_STATIC');
+        declaredNames.remove('MISSING_CLASS_BODY');
+        declaredNames.remove('STATIC_AFTER_CONST');
+        declaredNames.remove('STATIC_AFTER_FINAL');
+        declaredNames.remove('STATIC_AFTER_VAR');
       }
 
       // Assert that all remaining declared names are in errorCodeValues
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index f247d09..46590c8 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -2,7 +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.
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/test_utilities/package_mixin.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -11,7 +10,6 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(CheckerTest);
-    defineReflectiveTests(CheckerWithUiAsCodeTest);
   });
 }
 
@@ -2971,6 +2969,134 @@
 ''');
   }
 
+  test_list_ifElement_dynamicCondition_disableImplicitCasts() async {
+    addFile(r'''
+dynamic c;
+void main() {
+  <int>[if (/*error:NON_BOOL_CONDITION*/c) 0];
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_list_ifElement_dynamicCondition_implicitCasts() async {
+    addFile(r'''
+dynamic c;
+void main() {
+  <int>[if (/*info:DYNAMIC_CAST*/c) 0];
+}
+''');
+    await check();
+  }
+
+  test_list_ifElement_falseBranch_dynamic_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int>[if (c) 0 else /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/dyn];
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_list_ifElement_falseBranch_dynamic_implicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int>[if (c) 0 else /*info:DYNAMIC_CAST*/dyn];
+}
+''');
+    await check();
+  }
+
+  test_list_ifElement_falseBranch_supertype_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int>[if (c) 0 else /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/someNum];
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_list_ifElement_falseBranch_supertype_implicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int>[if (c) 0 else /*info:DOWN_CAST_IMPLICIT*/someNum];
+}
+''');
+    await check();
+  }
+
+  test_list_ifElement_objectCondition_disableImplicitCasts() async {
+    addFile(r'''
+Object c;
+void main() {
+  <int>[if (/*error:NON_BOOL_CONDITION*/c) 0];
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_list_ifElement_objectCondition_implicitCasts() async {
+    addFile(r'''
+Object c;
+void main() {
+  <int>[if (/*info:DOWN_CAST_IMPLICIT*/c) 0];
+}
+''');
+    await check();
+  }
+
+  test_list_ifElement_trueBranch_dynamic_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int>[if (c) /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/dyn];
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_list_ifElement_trueBranch_dynamic_implicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int>[if (c) /*info:DYNAMIC_CAST*/dyn];
+}
+''');
+    await check();
+  }
+
+  test_list_ifElement_trueBranch_supertype_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int>[if (c) /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/someNum];
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_list_ifElement_trueBranch_supertype_implicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int>[if (c) /*info:DOWN_CAST_IMPLICIT*/someNum];
+}
+''');
+    await check();
+  }
+
   test_loadLibrary() async {
     addFile('''library lib1;''', name: '/lib1.dart');
     await checkFile(r'''
@@ -2981,6 +3107,222 @@
 }''');
   }
 
+  test_map_ifElement_dynamicCondition_disableImplicitCasts() async {
+    addFile(r'''
+dynamic c;
+void main() {
+  <int, int>{if (/*error:NON_BOOL_CONDITION*/c) 0: 0};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_map_ifElement_dynamicCondition_implicitCasts() async {
+    addFile(r'''
+dynamic c;
+void main() {
+  <int, int>{if (/*info:DYNAMIC_CAST*/c) 0: 0};
+}
+''');
+    await check();
+  }
+
+  test_map_ifElement_falseBranch_dynamicKey_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int, int>{if (c) 0:0 else /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/dyn:0};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_map_ifElement_falseBranch_dynamicKey_implicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int, int>{if (c) 0:0 else /*info:DYNAMIC_CAST*/dyn:0};
+}
+''');
+    await check();
+  }
+
+  test_map_ifElement_falseBranch_dynamicValue_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int, int>{if (c) 0:0 else 0:/*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/dyn};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_map_ifElement_falseBranch_dynamicValue_implicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int, int>{if (c) 0:0 else 0:/*info:DYNAMIC_CAST*/dyn};
+}
+''');
+    await check();
+  }
+
+  test_map_ifElement_falseBranch_supertypeKey_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int, int>{if (c) 0:0 else /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/someNum:0};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_map_ifElement_falseBranch_supertypeKey_implicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int, int>{if (c) 0:0 else /*info:DOWN_CAST_IMPLICIT*/someNum:0};
+}
+''');
+    await check();
+  }
+
+  test_map_ifElement_falseBranch_supertypeValue_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int, int>{if (c) 0:0 else 0:/*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/someNum};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_map_ifElement_falseBranch_supertypeValue_implicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int, int>{if (c) 0:0 else 0:/*info:DOWN_CAST_IMPLICIT*/someNum};
+}
+''');
+    await check();
+  }
+
+  test_map_ifElement_objectCondition_disableImplicitCasts() async {
+    addFile(r'''
+Object c;
+void main() {
+  <int, int>{if (/*error:NON_BOOL_CONDITION*/c) 0: 0};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_map_ifElement_objectCondition_implicitCasts() async {
+    addFile(r'''
+Object c;
+void main() {
+  <int, int>{if (/*info:DOWN_CAST_IMPLICIT*/c) 0: 0};
+}
+''');
+    await check();
+  }
+
+  test_map_ifElement_trueBranch_dynamicKey_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int, int>{if (c) /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/dyn:0 else 0:0};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_map_ifElement_trueBranch_dynamicKey_implicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int, int>{if (c) /*info:DYNAMIC_CAST*/dyn:0 else 0:0};
+}
+''');
+    await check();
+  }
+
+  test_map_ifElement_trueBranch_dynamicValue_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int, int>{if (c) 0:/*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/dyn else 0:0};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_map_ifElement_trueBranch_dynamicValue_implicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int, int>{if (c) 0:/*info:DYNAMIC_CAST*/dyn else 0:0};
+}
+''');
+    await check();
+  }
+
+  test_map_ifElement_trueBranch_supertypeKey_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int, int>{if (c) /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/someNum:0 else 0:0};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_map_ifElement_trueBranch_supertypeKey_implicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int, int>{if (c) /*info:DOWN_CAST_IMPLICIT*/someNum:0 else 0:0};
+}
+''');
+    await check();
+  }
+
+  test_map_ifElement_trueBranch_supertypeValue_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int, int>{if (c) 0:/*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/someNum else 0:0};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_map_ifElement_trueBranch_supertypeValue_implicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int, int>{if (c) 0:/*info:DOWN_CAST_IMPLICIT*/someNum else 0:0};
+}
+''');
+    await check();
+  }
+
   test_methodOverride() async {
     await checkFile('''
 class A {}
@@ -3581,6 +3923,134 @@
 ''');
   }
 
+  test_set_ifElement_dynamicCondition_disableImplicitCasts() async {
+    addFile(r'''
+dynamic c;
+void main() {
+  <int>{if (/*error:NON_BOOL_CONDITION*/c) 0};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_set_ifElement_dynamicCondition_implicitCasts() async {
+    addFile(r'''
+dynamic c;
+void main() {
+  <int>{if (/*info:DYNAMIC_CAST*/c) 0};
+}
+''');
+    await check();
+  }
+
+  test_set_ifElement_falseBranch_dynamic_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int>{if (c) 0 else /*error:SET_ELEMENT_TYPE_NOT_ASSIGNABLE*/dyn};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_set_ifElement_falseBranch_dynamic_implicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int>{if (c) 0 else /*info:DYNAMIC_CAST*/dyn};
+}
+''');
+    await check();
+  }
+
+  test_set_ifElement_falseBranch_supertype_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int>{if (c) 0 else /*error:SET_ELEMENT_TYPE_NOT_ASSIGNABLE*/someNum};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_set_ifElement_falseBranch_supertype_implicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int>{if (c) 0 else /*info:DOWN_CAST_IMPLICIT*/someNum};
+}
+''');
+    await check();
+  }
+
+  test_set_ifElement_objectCondition_disableImplicitCasts() async {
+    addFile(r'''
+Object c;
+void main() {
+  <int>{if (/*error:NON_BOOL_CONDITION*/c) 0};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_set_ifElement_objectCondition_implicitCasts() async {
+    addFile(r'''
+Object c;
+void main() {
+  <int>{if (/*info:DOWN_CAST_IMPLICIT*/c) 0};
+}
+''');
+    await check();
+  }
+
+  test_set_ifElement_trueBranch_dynamic_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int>{if (c) /*error:SET_ELEMENT_TYPE_NOT_ASSIGNABLE*/dyn};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_set_ifElement_trueBranch_dynamic_implicitCasts() async {
+    addFile(r'''
+bool c;
+dynamic dyn;
+void main() {
+  <int>[if (c) /*info:DYNAMIC_CAST*/dyn];
+}
+''');
+    await check();
+  }
+
+  test_set_ifElement_trueBranch_supertype_disableImplicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int>{if (c) /*error:SET_ELEMENT_TYPE_NOT_ASSIGNABLE*/someNum};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_set_ifElement_trueBranch_supertype_implicitCasts() async {
+    addFile(r'''
+bool c;
+num someNum;
+void main() {
+  <int>{if (c) /*info:DOWN_CAST_IMPLICIT*/someNum};
+}
+''');
+    await check();
+  }
+
   test_setterOverride() async {
     await checkFile('''
 typedef void ToVoid<T>(T x);
@@ -3649,6 +4119,152 @@
 ''');
   }
 
+  @failingTest
+  test_spread_dynamicInList_disableImplicitCasts() async {
+    // TODO(mfairhurst) fix this, see https://github.com/dart-lang/sdk/issues/36267
+    addFile(r'''
+dynamic dyn;
+void main() {
+  [.../*error:INVALID_ASSIGNMENT*/dyn];
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_spread_dynamicInList_implicitCasts() async {
+    addFile(r'''
+dynamic dyn;
+void main() {
+  [.../*info:DYNAMIC_CAST*/dyn];
+}
+''');
+    await check();
+  }
+
+  @failingTest
+  test_spread_dynamicInMap_disableImplicitCasts() async {
+    // TODO(mfairhurst) fix this, see https://github.com/dart-lang/sdk/issues/36267
+    addFile(r'''
+dynamic dyn;
+void main() {
+  <dynamic, dynamic>{.../*error:INVALID_ASSIGNMENT*/dyn};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_spread_dynamicInMap_implicitCasts() async {
+    addFile(r'''
+dynamic dyn;
+void main() {
+  <dynamic, dynamic>{.../*info:DYNAMIC_CAST*/dyn};
+}
+''');
+    await check();
+  }
+
+  @failingTest
+  test_spread_dynamicInSet_disableImplicitCasts() async {
+    // TODO(mfairhurst) fix this, see https://github.com/dart-lang/sdk/issues/36267
+    addFile(r'''
+dynamic dyn;
+void main() {
+  <dynamic>{.../*error:INVALID_ASSIGNMENT*/dyn};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_spread_dynamicInSet_implicitCasts() async {
+    addFile(r'''
+dynamic dyn;
+void main() {
+  <dynamic>{.../*info:DYNAMIC_CAST*/dyn};
+}
+''');
+    await check();
+  }
+
+  test_spread_listElement_disableImplicitCasts() async {
+    addFile(r'''
+Iterable<num> i;
+void main() {
+  <int>[.../*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/i];
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_spread_listElement_implicitCasts() async {
+    addFile(r'''
+Iterable<num> i;
+void main() {
+  <int>[.../*info:DOWN_CAST_IMPLICIT*/i];
+}
+''');
+    await check();
+  }
+
+  test_spread_mapKey_disableImplicitCasts() async {
+    addFile(r'''
+Map<num, dynamic> map;
+void main() {
+  <int, dynamic>{1: 2, .../*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/map};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_spread_mapKey_implicitCasts() async {
+    addFile(r'''
+Map<num, dynamic> map;
+void main() {
+  <int, dynamic>{1: 2, .../*info:DOWN_CAST_IMPLICIT*/map};
+}
+''');
+    await check();
+  }
+
+  test_spread_mapValue_disableImplicitCasts() async {
+    addFile(r'''
+Map<dynamic, num> map;
+void main() {
+  <dynamic, int>{1: 2, .../*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/map};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_spread_mapValue_implicitCasts() async {
+    addFile(r'''
+Map<dynamic, num> map;
+void main() {
+  <dynamic, int>{1: 2, .../*info:DOWN_CAST_IMPLICIT*/map};
+}
+''');
+    await check();
+  }
+
+  test_spread_setElement_disableImplicitCasts() async {
+    addFile(r'''
+Iterable<num> i;
+void main() {
+  <int>{.../*error:SET_ELEMENT_TYPE_NOT_ASSIGNABLE*/i};
+}
+''');
+    await check(implicitCasts: false);
+  }
+
+  test_spread_setElement_implicitCasts() async {
+    addFile(r'''
+Iterable<num> i;
+void main() {
+  <int>{.../*info:DOWN_CAST_IMPLICIT*/i};
+}
+''');
+    await check();
+  }
+
   test_strictInference_collectionLiterals() async {
     addFile(r'''
 main() {
@@ -3798,14 +4414,22 @@
 
   {
     Object isCheck;
-    if (isCheck is /*info:STRICT_RAW_TYPE*/List) {}
-    if (isCheck is /*info:STRICT_RAW_TYPE*/C) {}
+    if (isCheck is /*info:STRICT_RAW_TYPE_IN_IS*/List) {}
+    if (isCheck is List</*info:STRICT_RAW_TYPE_IN_IS*/List>) {}
+    if (isCheck is /*info:STRICT_RAW_TYPE_IN_IS*/C) {}
 
     if (isCheck is List<dynamic>) {}
     if (isCheck is List<int>) {}
     if (isCheck is C<dynamic>) {}
     if (isCheck is C<int>) {}
   }
+
+  {
+    Object asCheck;
+    var asList = asCheck as /*info:STRICT_RAW_TYPE_IN_AS*/List;
+    var asMap = asCheck as Map<dynamic, /*info:STRICT_RAW_TYPE_IN_AS*/List>;
+    var asC = asCheck as /*info:STRICT_RAW_TYPE_IN_AS*/C;
+  }
 }
     ''');
     await check(strictRawTypes: true);
@@ -4534,628 +5158,3 @@
     ''', name: '/meta.dart');
   }
 }
-
-@reflectiveTest
-class CheckerWithUiAsCodeTest extends AbstractStrongTest {
-  @override
-  List<String> get enabledExperiments =>
-      [EnableString.spread_collections, EnableString.control_flow_collections];
-
-  test_list_ifElement_dynamicCondition_disableImplicitCasts() async {
-    addFile(r'''
-dynamic c;
-void main() {
-  <int>[if (/*error:NON_BOOL_CONDITION*/c) 0];
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_list_ifElement_dynamicCondition_implicitCasts() async {
-    addFile(r'''
-dynamic c;
-void main() {
-  <int>[if (/*info:DYNAMIC_CAST*/c) 0];
-}
-''');
-    await check();
-  }
-
-  test_list_ifElement_falseBranch_dynamic_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int>[if (c) 0 else /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/dyn];
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_list_ifElement_falseBranch_dynamic_implicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int>[if (c) 0 else /*info:DYNAMIC_CAST*/dyn];
-}
-''');
-    await check();
-  }
-
-  test_list_ifElement_falseBranch_supertype_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int>[if (c) 0 else /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/someNum];
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_list_ifElement_falseBranch_supertype_implicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int>[if (c) 0 else /*info:DOWN_CAST_IMPLICIT*/someNum];
-}
-''');
-    await check();
-  }
-
-  test_list_ifElement_objectCondition_disableImplicitCasts() async {
-    addFile(r'''
-Object c;
-void main() {
-  <int>[if (/*error:NON_BOOL_CONDITION*/c) 0];
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_list_ifElement_objectCondition_implicitCasts() async {
-    addFile(r'''
-Object c;
-void main() {
-  <int>[if (/*info:DOWN_CAST_IMPLICIT*/c) 0];
-}
-''');
-    await check();
-  }
-
-  test_list_ifElement_trueBranch_dynamic_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int>[if (c) /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/dyn];
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_list_ifElement_trueBranch_dynamic_implicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int>[if (c) /*info:DYNAMIC_CAST*/dyn];
-}
-''');
-    await check();
-  }
-
-  test_list_ifElement_trueBranch_supertype_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int>[if (c) /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/someNum];
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_list_ifElement_trueBranch_supertype_implicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int>[if (c) /*info:DOWN_CAST_IMPLICIT*/someNum];
-}
-''');
-    await check();
-  }
-
-  test_map_ifElement_dynamicCondition_disableImplicitCasts() async {
-    addFile(r'''
-dynamic c;
-void main() {
-  <int, int>{if (/*error:NON_BOOL_CONDITION*/c) 0: 0};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_map_ifElement_dynamicCondition_implicitCasts() async {
-    addFile(r'''
-dynamic c;
-void main() {
-  <int, int>{if (/*info:DYNAMIC_CAST*/c) 0: 0};
-}
-''');
-    await check();
-  }
-
-  test_map_ifElement_falseBranch_dynamicKey_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int, int>{if (c) 0:0 else /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/dyn:0};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_map_ifElement_falseBranch_dynamicKey_implicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int, int>{if (c) 0:0 else /*info:DYNAMIC_CAST*/dyn:0};
-}
-''');
-    await check();
-  }
-
-  test_map_ifElement_falseBranch_dynamicValue_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int, int>{if (c) 0:0 else 0:/*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/dyn};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_map_ifElement_falseBranch_dynamicValue_implicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int, int>{if (c) 0:0 else 0:/*info:DYNAMIC_CAST*/dyn};
-}
-''');
-    await check();
-  }
-
-  test_map_ifElement_falseBranch_supertypeKey_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int, int>{if (c) 0:0 else /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/someNum:0};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_map_ifElement_falseBranch_supertypeKey_implicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int, int>{if (c) 0:0 else /*info:DOWN_CAST_IMPLICIT*/someNum:0};
-}
-''');
-    await check();
-  }
-
-  test_map_ifElement_falseBranch_supertypeValue_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int, int>{if (c) 0:0 else 0:/*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/someNum};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_map_ifElement_falseBranch_supertypeValue_implicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int, int>{if (c) 0:0 else 0:/*info:DOWN_CAST_IMPLICIT*/someNum};
-}
-''');
-    await check();
-  }
-
-  test_map_ifElement_objectCondition_disableImplicitCasts() async {
-    addFile(r'''
-Object c;
-void main() {
-  <int, int>{if (/*error:NON_BOOL_CONDITION*/c) 0: 0};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_map_ifElement_objectCondition_implicitCasts() async {
-    addFile(r'''
-Object c;
-void main() {
-  <int, int>{if (/*info:DOWN_CAST_IMPLICIT*/c) 0: 0};
-}
-''');
-    await check();
-  }
-
-  test_map_ifElement_trueBranch_dynamicKey_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int, int>{if (c) /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/dyn:0 else 0:0};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_map_ifElement_trueBranch_dynamicKey_implicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int, int>{if (c) /*info:DYNAMIC_CAST*/dyn:0 else 0:0};
-}
-''');
-    await check();
-  }
-
-  test_map_ifElement_trueBranch_dynamicValue_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int, int>{if (c) 0:/*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/dyn else 0:0};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_map_ifElement_trueBranch_dynamicValue_implicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int, int>{if (c) 0:/*info:DYNAMIC_CAST*/dyn else 0:0};
-}
-''');
-    await check();
-  }
-
-  test_map_ifElement_trueBranch_supertypeKey_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int, int>{if (c) /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/someNum:0 else 0:0};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_map_ifElement_trueBranch_supertypeKey_implicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int, int>{if (c) /*info:DOWN_CAST_IMPLICIT*/someNum:0 else 0:0};
-}
-''');
-    await check();
-  }
-
-  test_map_ifElement_trueBranch_supertypeValue_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int, int>{if (c) 0:/*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/someNum else 0:0};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_map_ifElement_trueBranch_supertypeValue_implicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int, int>{if (c) 0:/*info:DOWN_CAST_IMPLICIT*/someNum else 0:0};
-}
-''');
-    await check();
-  }
-
-  test_set_ifElement_dynamicCondition_disableImplicitCasts() async {
-    addFile(r'''
-dynamic c;
-void main() {
-  <int>{if (/*error:NON_BOOL_CONDITION*/c) 0};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_set_ifElement_dynamicCondition_implicitCasts() async {
-    addFile(r'''
-dynamic c;
-void main() {
-  <int>{if (/*info:DYNAMIC_CAST*/c) 0};
-}
-''');
-    await check();
-  }
-
-  test_set_ifElement_falseBranch_dynamic_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int>{if (c) 0 else /*error:SET_ELEMENT_TYPE_NOT_ASSIGNABLE*/dyn};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_set_ifElement_falseBranch_dynamic_implicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int>{if (c) 0 else /*info:DYNAMIC_CAST*/dyn};
-}
-''');
-    await check();
-  }
-
-  test_set_ifElement_falseBranch_supertype_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int>{if (c) 0 else /*error:SET_ELEMENT_TYPE_NOT_ASSIGNABLE*/someNum};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_set_ifElement_falseBranch_supertype_implicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int>{if (c) 0 else /*info:DOWN_CAST_IMPLICIT*/someNum};
-}
-''');
-    await check();
-  }
-
-  test_set_ifElement_objectCondition_disableImplicitCasts() async {
-    addFile(r'''
-Object c;
-void main() {
-  <int>{if (/*error:NON_BOOL_CONDITION*/c) 0};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_set_ifElement_objectCondition_implicitCasts() async {
-    addFile(r'''
-Object c;
-void main() {
-  <int>{if (/*info:DOWN_CAST_IMPLICIT*/c) 0};
-}
-''');
-    await check();
-  }
-
-  test_set_ifElement_trueBranch_dynamic_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int>{if (c) /*error:SET_ELEMENT_TYPE_NOT_ASSIGNABLE*/dyn};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_set_ifElement_trueBranch_dynamic_implicitCasts() async {
-    addFile(r'''
-bool c;
-dynamic dyn;
-void main() {
-  <int>[if (c) /*info:DYNAMIC_CAST*/dyn];
-}
-''');
-    await check();
-  }
-
-  test_set_ifElement_trueBranch_supertype_disableImplicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int>{if (c) /*error:SET_ELEMENT_TYPE_NOT_ASSIGNABLE*/someNum};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_set_ifElement_trueBranch_supertype_implicitCasts() async {
-    addFile(r'''
-bool c;
-num someNum;
-void main() {
-  <int>{if (c) /*info:DOWN_CAST_IMPLICIT*/someNum};
-}
-''');
-    await check();
-  }
-
-  @failingTest
-  test_spread_dynamicInList_disableImplicitCasts() async {
-    // TODO(mfairhurst) fix this, see https://github.com/dart-lang/sdk/issues/36267
-    addFile(r'''
-dynamic dyn;
-void main() {
-  [.../*error:INVALID_ASSIGNMENT*/dyn];
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_spread_dynamicInList_implicitCasts() async {
-    addFile(r'''
-dynamic dyn;
-void main() {
-  [.../*info:DYNAMIC_CAST*/dyn];
-}
-''');
-    await check();
-  }
-
-  @failingTest
-  test_spread_dynamicInMap_disableImplicitCasts() async {
-    // TODO(mfairhurst) fix this, see https://github.com/dart-lang/sdk/issues/36267
-    addFile(r'''
-dynamic dyn;
-void main() {
-  <dynamic, dynamic>{.../*error:INVALID_ASSIGNMENT*/dyn};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_spread_dynamicInMap_implicitCasts() async {
-    addFile(r'''
-dynamic dyn;
-void main() {
-  <dynamic, dynamic>{.../*info:DYNAMIC_CAST*/dyn};
-}
-''');
-    await check();
-  }
-
-  @failingTest
-  test_spread_dynamicInSet_disableImplicitCasts() async {
-    // TODO(mfairhurst) fix this, see https://github.com/dart-lang/sdk/issues/36267
-    addFile(r'''
-dynamic dyn;
-void main() {
-  <dynamic>{.../*error:INVALID_ASSIGNMENT*/dyn};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_spread_dynamicInSet_implicitCasts() async {
-    addFile(r'''
-dynamic dyn;
-void main() {
-  <dynamic>{.../*info:DYNAMIC_CAST*/dyn};
-}
-''');
-    await check();
-  }
-
-  test_spread_listElement_disableImplicitCasts() async {
-    addFile(r'''
-Iterable<num> i;
-void main() {
-  <int>[.../*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/i];
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_spread_listElement_implicitCasts() async {
-    addFile(r'''
-Iterable<num> i;
-void main() {
-  <int>[.../*info:DOWN_CAST_IMPLICIT*/i];
-}
-''');
-    await check();
-  }
-
-  test_spread_mapKey_disableImplicitCasts() async {
-    addFile(r'''
-Map<num, dynamic> map;
-void main() {
-  <int, dynamic>{1: 2, .../*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/map};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_spread_mapKey_implicitCasts() async {
-    addFile(r'''
-Map<num, dynamic> map;
-void main() {
-  <int, dynamic>{1: 2, .../*info:DOWN_CAST_IMPLICIT*/map};
-}
-''');
-    await check();
-  }
-
-  test_spread_mapValue_disableImplicitCasts() async {
-    addFile(r'''
-Map<dynamic, num> map;
-void main() {
-  <dynamic, int>{1: 2, .../*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/map};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_spread_mapValue_implicitCasts() async {
-    addFile(r'''
-Map<dynamic, num> map;
-void main() {
-  <dynamic, int>{1: 2, .../*info:DOWN_CAST_IMPLICIT*/map};
-}
-''');
-    await check();
-  }
-
-  test_spread_setElement_disableImplicitCasts() async {
-    addFile(r'''
-Iterable<num> i;
-void main() {
-  <int>{.../*error:SET_ELEMENT_TYPE_NOT_ASSIGNABLE*/i};
-}
-''');
-    await check(implicitCasts: false);
-  }
-
-  test_spread_setElement_implicitCasts() async {
-    addFile(r'''
-Iterable<num> i;
-void main() {
-  <int>{.../*info:DOWN_CAST_IMPLICIT*/i};
-}
-''');
-    await check();
-  }
-}
diff --git a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
index c2960c3..2ec431a6 100644
--- a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
+++ b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
@@ -51,15 +51,15 @@
       return invocation.staticInvokeType.toString();
     }
 
-    expect(getType('f()); // 1'), '() → bool');
+    expect(getType('f()); // 1'), 'bool Function()');
 
-    expect(getType('f(), '), '() → bool');
-    expect(getType('f()); // 2'), '() → dynamic');
+    expect(getType('f(), '), 'bool Function()');
+    expect(getType('f()); // 2'), 'dynamic Function()');
 
-    expect(getType('f()), // 3'), '() → bool');
+    expect(getType('f()), // 3'), 'bool Function()');
 
-    expect(getType('f(), '), '() → bool');
-    expect(getType('f()); // 4'), '() → dynamic');
+    expect(getType('f(), '), 'bool Function()');
+    expect(getType('f()); // 4'), 'dynamic Function()');
   }
 
   test_bool_logical() async {
@@ -80,7 +80,7 @@
 
     void assertType(String prefix) {
       var invocation = _findMethodInvocation(unit, code, prefix);
-      expect(invocation.staticInvokeType.toString(), '() → bool');
+      expect(invocation.staticInvokeType.toString(), 'bool Function()');
     }
 
     assertType('f() || f(); // 1');
@@ -111,7 +111,7 @@
 
     void assertType(String prefix) {
       var invocation = _findMethodInvocation(unit, code, prefix);
-      expect(invocation.staticInvokeType.toString(), '() → bool');
+      expect(invocation.staticInvokeType.toString(), 'bool Function()');
     }
 
     assertType('f()) {} // 1');
@@ -132,7 +132,7 @@
     var unit = analysisResult.unit;
 
     Expression closure = _findExpression(unit, code, '() => 42');
-    expect(closure.staticType.toString(), '() → List<int>');
+    expect(closure.staticType.toString(), 'List<int> Function()');
   }
 
   test_closure_downwardReturnType_block() async {
@@ -149,7 +149,7 @@
     var unit = analysisResult.unit;
 
     Expression closure = _findExpression(unit, code, '() { // mark');
-    expect(closure.staticType.toString(), '() → List<int>');
+    expect(closure.staticType.toString(), 'List<int> Function()');
   }
 
   test_compoundAssignment_index() async {
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 4a036db..a3a31c2 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -59,10 +60,10 @@
     expect(futureInt.type.toString(), 'Future<int>');
     var f = mainUnit.topLevelVariables[1];
     expect(f.name, 'f');
-    expect(f.type.toString(), '() → Future<int>');
+    expect(f.type.toString(), 'Future<int> Function()');
     var g = mainUnit.topLevelVariables[2];
     expect(g.name, 'g');
-    expect(g.type.toString(), '() → Future<int>');
+    expect(g.type.toString(), 'Future<int> Function()');
   }
 
   test_asyncClosureReturnType_future() async {
@@ -71,7 +72,7 @@
 ''');
     var f = mainUnit.topLevelVariables[0];
     expect(f.name, 'f');
-    expect(f.type.toString(), '() → Future<int>');
+    expect(f.type.toString(), 'Future<int> Function()');
   }
 
   test_asyncClosureReturnType_futureOr() async {
@@ -86,10 +87,10 @@
     expect(futureOrInt.type.toString(), 'FutureOr<int>');
     var f = mainUnit.topLevelVariables[1];
     expect(f.name, 'f');
-    expect(f.type.toString(), '() → FutureOr<int>');
+    expect(f.type.toString(), 'FutureOr<int> Function()');
     var g = mainUnit.topLevelVariables[2];
     expect(g.name, 'g');
-    expect(g.type.toString(), '() → Future<int>');
+    expect(g.type.toString(), 'Future<int> Function()');
   }
 
   test_blockBodiedLambdas_async_allReturnsAreFutures() async {
@@ -112,7 +113,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Future<num>');
+    expect(f.type.toString(), 'Future<num> Function()');
   }
 
   test_blockBodiedLambdas_async_allReturnsAreValues() async {
@@ -135,7 +136,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Future<num>');
+    expect(f.type.toString(), 'Future<num> Function()');
   }
 
   test_blockBodiedLambdas_async_mixOfValuesAndFutures() async {
@@ -158,7 +159,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Future<num>');
+    expect(f.type.toString(), 'Future<num> Function()');
   }
 
   test_blockBodiedLambdas_asyncStar() async {
@@ -178,7 +179,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Stream<num>');
+    expect(f.type.toString(), 'Stream<num> Function()');
   }
 
   test_blockBodiedLambdas_basic() async {
@@ -203,7 +204,7 @@
 }
 ''');
     var g = findLocalVariable(unit, 'g');
-    expect(g.type.toString(), '() → String');
+    expect(g.type.toString(), 'String Function()');
   }
 
   test_blockBodiedLambdas_downwardsIncompatibleWithUpwardsInference_topLevel() async {
@@ -212,7 +213,7 @@
 var g = f;
 ''');
     var g = unit.topLevelVariables[0];
-    expect(g.type.toString(), '() → String');
+    expect(g.type.toString(), 'String Function()');
   }
 
   test_blockBodiedLambdas_inferBottom_async() async {
@@ -229,7 +230,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Future<Null>');
+    expect(f.type.toString(), 'Future<Null> Function()');
   }
 
   test_blockBodiedLambdas_inferBottom_asyncStar() async {
@@ -246,7 +247,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Stream<Null>');
+    expect(f.type.toString(), 'Stream<Null> Function()');
   }
 
   test_blockBodiedLambdas_inferBottom_sync() async {
@@ -271,7 +272,7 @@
 ''');
 
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '(Object) → Null');
+    expect(f.type.toString(), 'Null Function(Object)');
   }
 
   test_blockBodiedLambdas_inferBottom_syncStar() async {
@@ -287,7 +288,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Iterable<Null>');
+    expect(f.type.toString(), 'Iterable<Null> Function()');
   }
 
   test_blockBodiedLambdas_LUB() async {
@@ -321,7 +322,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → (int) → double');
+    expect(f.type.toString(), 'double Function(int) Function()');
   }
 
   test_blockBodiedLambdas_noReturn() async {
@@ -354,7 +355,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Iterable<num>');
+    expect(f.type.toString(), 'Iterable<num> Function()');
   }
 
   test_bottom() async {
@@ -366,7 +367,11 @@
 ''');
     var v = mainUnit.topLevelVariables[0];
     expect(v.type.toString(), 'dynamic');
-    expect(v.initializer.type.toString(), '() → Null');
+    if (AnalysisDriver.useSummary2) {
+      expect(v.initializer.type.toString(), 'dynamic Function()');
+    } else {
+      expect(v.initializer.type.toString(), 'Null Function()');
+    }
   }
 
   test_bottom_inClosure() async {
@@ -376,8 +381,8 @@
 var v = /*info:INFERRED_TYPE_CLOSURE*/() => null;
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), '() → Null');
-    expect(v.initializer.type.toString(), '() → () → Null');
+    expect(v.type.toString(), 'Null Function()');
+    expect(v.initializer.type.toString(), 'Null Function() Function()');
   }
 
   test_circularReference_viaClosures() async {
@@ -402,8 +407,8 @@
     var y = mainUnit.topLevelVariables[1];
     expect(x.name, 'x');
     expect(y.name, 'y');
-    expect(x.initializer.returnType.toString(), '() → dynamic');
-    expect(y.initializer.returnType.toString(), '() → dynamic');
+    expect(x.initializer.returnType.toString(), 'dynamic Function()');
+    expect(y.initializer.returnType.toString(), 'dynamic Function()');
   }
 
   test_conflictsCanHappen() async {
@@ -1980,7 +1985,7 @@
 typedef void F<V>(V v);
 ''');
     var f = mainUnit.getType('C').methods[0];
-    expect(f.type.toString(), '<U>(U) → (U) → void');
+    expect(f.type.toString(), 'void Function(U) Function<U>(U)');
   }
 
   test_genericMethods_inferGenericFunctionParameterType2() async {
@@ -1994,7 +1999,7 @@
 typedef List<V> G<V>();
 ''');
     var f = mainUnit.getType('C').methods[0];
-    expect(f.type.toString(), '<U>(() → List<U>) → void');
+    expect(f.type.toString(), 'void Function<U>(List<U> Function())');
   }
 
   test_genericMethods_inferGenericFunctionReturnType() async {
@@ -2008,7 +2013,7 @@
 typedef V F<V>();
 ''');
     var f = mainUnit.getType('C').methods[0];
-    expect(f.type.toString(), '<U>(U) → () → U');
+    expect(f.type.toString(), 'U Function() Function<U>(U)');
   }
 
   test_genericMethods_inferGenericInstantiation() async {
@@ -2187,7 +2192,7 @@
 }
 ''');
     var v = findLocalVariable(unit, 'v');
-    expect(v.type.toString(), '(num) → List<int>');
+    expect(v.type.toString(), 'List<int> Function(num)');
   }
 
   test_genericMethods_usesGreatestLowerBound_topLevel() async {
@@ -2200,7 +2205,7 @@
 var v = generic(/*info:INFERRED_TYPE_CLOSURE*/(F f) => null, /*info:INFERRED_TYPE_CLOSURE*/(G g) => null);
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), '(num) → List<int>');
+    expect(v.type.toString(), 'List<int> Function(num)');
   }
 
   test_infer_assignToIndex() async {
@@ -2411,7 +2416,18 @@
   }
 
   test_infer_use_of_void() async {
-    await checkFileElement('''
+    if (AnalysisDriver.useSummary2) {
+      await checkFileElement('''
+class B {
+  void f() {}
+}
+class C extends B {
+  f() {}
+}
+var x = /*error:TOP_LEVEL_INSTANCE_METHOD*/new C().f();
+''');
+    } else {
+      await checkFileElement('''
 class B {
   void f() {}
 }
@@ -2420,6 +2436,7 @@
 }
 var x = /*error:TOP_LEVEL_INSTANCE_METHOD*/new C()./*error:USE_OF_VOID_RESULT*/f();
 ''');
+    }
   }
 
   test_inferConstsTransitively() async {
@@ -2478,7 +2495,7 @@
 var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<() → Object>');
+    expect(v.type.toString(), 'List<Object Function()>');
   }
 
   test_inferedType_usesSyntheticFunctionType_functionTypedParam() async {
@@ -2488,7 +2505,7 @@
 var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<((String) → int) → Object>');
+    expect(v.type.toString(), 'List<Object Function(int Function(String))>');
   }
 
   test_inferedType_usesSyntheticFunctionType_namedParam() async {
@@ -2498,7 +2515,7 @@
 var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<({x: int}) → Object>');
+    expect(v.type.toString(), 'List<Object Function({x: int})>');
   }
 
   test_inferedType_usesSyntheticFunctionType_positionalParam() async {
@@ -2508,7 +2525,7 @@
 var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<([int]) → Object>');
+    expect(v.type.toString(), 'List<Object Function([int])>');
   }
 
   test_inferedType_usesSyntheticFunctionType_requiredParam() async {
@@ -2518,7 +2535,7 @@
 var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<(int) → Object>');
+    expect(v.type.toString(), 'List<Object Function(int)>');
   }
 
   test_inferFromComplexExpressionsIfOuterMostValueIsPrecise() async {
@@ -2766,20 +2783,25 @@
   f9 /*info:INFERRED_TYPE_CLOSURE*/() => f5();
 }
 ''');
-    expect(findLocalFunction(unit, 'f0').type.toString(), '() → int');
-    expect(findLocalFunction(unit, 'f1').type.toString(), '() → Future<int>');
+    expect(findLocalFunction(unit, 'f0').type.toString(), 'int Function()');
+    expect(findLocalFunction(unit, 'f1').type.toString(),
+        'Future<int> Function()');
 
-    expect(findLocalFunction(unit, 'f2').type.toString(), '() → int');
-    expect(findLocalFunction(unit, 'f3').type.toString(), '() → Future<int>');
-    expect(findLocalFunction(unit, 'f4').type.toString(), '() → Iterable<int>');
-    expect(findLocalFunction(unit, 'f5').type.toString(), '() → Stream<int>');
+    expect(findLocalFunction(unit, 'f2').type.toString(), 'int Function()');
+    expect(findLocalFunction(unit, 'f3').type.toString(),
+        'Future<int> Function()');
+    expect(findLocalFunction(unit, 'f4').type.toString(),
+        'Iterable<int> Function()');
+    expect(findLocalFunction(unit, 'f5').type.toString(),
+        'Stream<int> Function()');
 
-    expect(findLocalFunction(unit, 'f6').type.toString(), '() → num');
+    expect(findLocalFunction(unit, 'f6').type.toString(), 'num Function()');
 
     // Recursive cases: these infer in declaration order.
-    expect(findLocalFunction(unit, 'f7').type.toString(), '() → dynamic');
-    expect(findLocalFunction(unit, 'f8').type.toString(), '() → dynamic');
-    expect(findLocalFunction(unit, 'f9').type.toString(), '() → Stream<int>');
+    expect(findLocalFunction(unit, 'f7').type.toString(), 'dynamic Function()');
+    expect(findLocalFunction(unit, 'f8').type.toString(), 'dynamic Function()');
+    expect(findLocalFunction(unit, 'f9').type.toString(),
+        'Stream<int> Function()');
   }
 
   test_inferParameterType_setter_fromField() async {
@@ -2792,7 +2814,7 @@
 }
 ''');
     var f = mainUnit.getType('C').accessors[0];
-    expect(f.type.toString(), '(int) → void');
+    expect(f.type.toString(), 'void Function(int)');
   }
 
   test_inferParameterType_setter_fromSetter() async {
@@ -2805,7 +2827,7 @@
 }
 ''');
     var f = mainUnit.getType('C').accessors[0];
-    expect(f.type.toString(), '(int) → void');
+    expect(f.type.toString(), 'void Function(int)');
   }
 
   test_inferred_nonstatic_field_depends_on_static_field_complex() async {
@@ -2856,7 +2878,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Null');
+    expect(f.type.toString(), 'Null Function()');
   }
 
   test_inferredType_cascade() async {
@@ -2967,7 +2989,7 @@
 ''');
     var x = mainUnit.topLevelVariables[0];
     expect(x.name, 'x');
-    expect(x.type.toString(), '() → bool');
+    expect(x.type.toString(), 'bool Function()');
   }
 
   test_inferredType_extractMethodTearOff_viaInterface() async {
@@ -2981,7 +3003,7 @@
 ''');
     var x = mainUnit.topLevelVariables[0];
     expect(x.name, 'x');
-    expect(x.type.toString(), '() → bool');
+    expect(x.type.toString(), 'bool Function()');
   }
 
   test_inferredType_fromTopLevelExecutableTearoff() async {
@@ -2989,7 +3011,7 @@
 var v = print;
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), '(Object) → void');
+    expect(v.type.toString(), 'void Function(Object)');
   }
 
   test_inferredType_invokeMethod() async {
@@ -3043,7 +3065,7 @@
 final x = <String, F>{};
 ''');
     var x = mainUnit.topLevelVariables[0];
-    expect(x.type.toString(), 'Map<String, () → void>');
+    expect(x.type.toString(), 'Map<String, void Function()>');
   }
 
   test_inferredType_isTypedef_parameterized() async {
@@ -3052,7 +3074,7 @@
 final x = <String, F<int>>{};
 ''');
     var x = mainUnit.topLevelVariables[0];
-    expect(x.type.toString(), 'Map<String, () → int>');
+    expect(x.type.toString(), 'Map<String, int Function()>');
   }
 
   test_inferredType_viaClosure_multipleLevelsOfNesting() async {
@@ -3063,7 +3085,7 @@
 }
 ''');
     var f = mainUnit.getType('C').fields[0];
-    expect(f.type.toString(), '(bool) → (int) → Map<int, bool>');
+    expect(f.type.toString(), 'Map<int, bool> Function(int) Function(bool)');
   }
 
   test_inferredType_viaClosure_typeDependsOnArgs() async {
@@ -3073,7 +3095,7 @@
 }
 ''');
     var f = mainUnit.getType('C').fields[0];
-    expect(f.type.toString(), '(bool) → bool');
+    expect(f.type.toString(), 'bool Function(bool)');
   }
 
   test_inferredType_viaClosure_typeIndependentOfArgs_field() async {
@@ -3083,7 +3105,7 @@
 }
 ''');
     var f = mainUnit.getType('C').fields[0];
-    expect(f.type.toString(), '(bool) → int');
+    expect(f.type.toString(), 'int Function(bool)');
   }
 
   test_inferredType_viaClosure_typeIndependentOfArgs_topLevel() async {
@@ -3091,7 +3113,7 @@
 final f = /*info:INFERRED_TYPE_CLOSURE*/(bool b) => 1;
 ''');
     var f = mainUnit.topLevelVariables[0];
-    expect(f.type.toString(), '(bool) → int');
+    expect(f.type.toString(), 'int Function(bool)');
   }
 
   test_inferReturnOfStatementLambda() async {
@@ -4054,7 +4076,7 @@
 }
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), '(String) → int');
+    expect(v.type.toString(), 'int Function(String)');
   }
 
   test_unsafeBlockClosureInference_closureCall() async {
@@ -4254,7 +4276,7 @@
 }
 ''');
     var v = findLocalVariable(unit, 'v');
-    expect(v.type.toString(), 'List<() → int>');
+    expect(v.type.toString(), 'List<int Function()>');
   }
 
   test_unsafeBlockClosureInference_inList_untyped() async {
@@ -4267,7 +4289,7 @@
 }
 ''');
     var v = findLocalVariable(unit, 'v');
-    expect(v.type.toString(), 'List<() → int>');
+    expect(v.type.toString(), 'List<int Function()>');
   }
 
   test_unsafeBlockClosureInference_inMap_dynamic() async {
@@ -4288,7 +4310,7 @@
 }
 ''');
     var v = findLocalVariable(unit, 'v');
-    expect(v.type.toString(), 'Map<int, () → int>');
+    expect(v.type.toString(), 'Map<int, int Function()>');
   }
 
   test_unsafeBlockClosureInference_inMap_untyped() async {
@@ -4301,7 +4323,7 @@
 }
 ''');
     var v = findLocalVariable(unit, 'v');
-    expect(v.type.toString(), 'Map<int, () → int>');
+    expect(v.type.toString(), 'Map<int, int Function()>');
   }
 
   test_unsafeBlockClosureInference_methodCall_explicitDynamicParam() async {
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index 03726eb..b78eabd 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -242,10 +242,10 @@
   AnalysisContext _context = null;
   AnalysisDriver _driver = null;
 
-  List<String> get enabledExperiments => [];
-
   Map<String, List<Folder>> packageMap;
 
+  List<String> get enabledExperiments => [];
+
   /// Adds a file to check. The file should contain:
   ///
   ///   * all expected failures are listed in the source code using comments
@@ -338,6 +338,8 @@
         return code.errorSeverity.ordinal > ErrorSeverity.INFO.ordinal ||
             code == HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL ||
             code == HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION ||
+            code == HintCode.STRICT_RAW_TYPE_IN_AS ||
+            code == HintCode.STRICT_RAW_TYPE_IN_IS ||
             code == HintCode.STRICT_RAW_TYPE;
       }
       return true;
diff --git a/pkg/analyzer/test/src/workspace/basic_test.dart b/pkg/analyzer/test/src/workspace/basic_test.dart
index 6df62db..cdd5e28 100644
--- a/pkg/analyzer/test/src/workspace/basic_test.dart
+++ b/pkg/analyzer/test/src/workspace/basic_test.dart
@@ -10,6 +10,8 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../generated/test_support.dart';
+
 class MockContextBuilder implements ContextBuilder {
   Map<String, Packages> packagesMapMap = <String, Packages>{};
   Map<Packages, Map<String, List<Folder>>> packagesToMapMap =
@@ -102,7 +104,10 @@
 
     var package = workspace
         .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
-    expect(package.contains('/workspace2/project/lib/file.dart'), isFalse);
+    expect(
+        package.contains(
+            TestSource(convertPath('/workspace2/project/lib/file.dart'))),
+        isFalse);
   }
 
   void test_contains_sameWorkspace() {
@@ -110,8 +115,17 @@
 
     var package = workspace
         .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
-    expect(package.contains('/workspace/project/lib/file2.dart'), isTrue);
-    expect(package.contains('/workspace/project/bin/bin.dart'), isTrue);
-    expect(package.contains('/workspace/project/test/test.dart'), isTrue);
+    expect(
+        package.contains(
+            TestSource(convertPath('/workspace/project/lib/file2.dart'))),
+        isTrue);
+    expect(
+        package.contains(
+            TestSource(convertPath('/workspace/project/bin/bin.dart'))),
+        isTrue);
+    expect(
+        package.contains(
+            TestSource(convertPath('/workspace/project/test/test.dart'))),
+        isTrue);
   }
 }
diff --git a/pkg/analyzer/test/src/workspace/bazel_test.dart b/pkg/analyzer/test/src/workspace/bazel_test.dart
index 799eff6..aab84ef 100644
--- a/pkg/analyzer/test/src/workspace/bazel_test.dart
+++ b/pkg/analyzer/test/src/workspace/bazel_test.dart
@@ -3,11 +3,14 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer/src/workspace/bazel.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../generated/test_support.dart';
+
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(BazelFileUriResolverTest);
@@ -704,7 +707,8 @@
     final targetFile = newFile('/ws/some/code/lib/code.dart');
 
     var package = workspace.findPackageFor(targetFile.path);
-    expect(package.contains('/ws2/some/file.dart'), isFalse);
+    expect(package.contains(TestSource(convertPath('/ws2/some/file.dart'))),
+        isFalse);
   }
 
   void test_contains_differentPackageInWorkspace() {
@@ -712,9 +716,12 @@
     final targetFile = newFile('/ws/some/code/lib/code.dart');
 
     var package = workspace.findPackageFor(targetFile.path);
-    // A file that is _not_ in this package is not required to have a BUILD.gn
+    // A file that is _not_ in this package is not required to have a BUILD
     // file above it, for simplicity and reduced I/O.
-    expect(package.contains('/ws/some/other/code/file.dart'), isFalse);
+    expect(
+        package
+            .contains(TestSource(convertPath('/ws/some/other/code/file.dart'))),
+        isFalse);
   }
 
   void test_contains_samePackage() {
@@ -726,10 +733,10 @@
     final targetTestFile = newFile('/ws/some/code/test/code_test.dart');
 
     var package = workspace.findPackageFor(targetFile.path);
-    expect(package.contains(targetFile2.path), isTrue);
-    expect(package.contains(targetFile3.path), isTrue);
-    expect(package.contains(targetBinFile.path), isTrue);
-    expect(package.contains(targetTestFile.path), isTrue);
+    expect(package.contains(TestSource(targetFile2.path)), isTrue);
+    expect(package.contains(TestSource(targetFile3.path)), isTrue);
+    expect(package.contains(TestSource(targetBinFile.path)), isTrue);
+    expect(package.contains(TestSource(targetTestFile.path)), isTrue);
   }
 
   void test_contains_subPackage() {
@@ -741,9 +748,36 @@
     var package =
         workspace.findPackageFor(convertPath('/ws/some/code/lib/code.dart'));
     expect(
-        package.contains(convertPath('/ws/some/code/testing/lib/testing.dart')),
+        package.contains(
+            TestSource(convertPath('/ws/some/code/testing/lib/testing.dart'))),
         isFalse);
   }
+
+  void test_contains_differentPackage_summarySource() {
+    newFile('/ws/some/code/BUILD');
+    final targetFile = newFile('/ws/some/code/lib/code.dart');
+
+    var package = workspace.findPackageFor(targetFile.path);
+    var source = InSummarySource(
+        Uri.parse('package:some.other.code/file.dart'), '' /* summaryPath */);
+    expect(package.contains(source), isFalse);
+  }
+
+  void test_contains_samePackage_summarySource() {
+    newFile('/ws/some/code/BUILD');
+    final targetFile = newFile('/ws/some/code/lib/code.dart');
+    newFile('/ws/some/code/lib/code2.dart');
+    newFile('/ws/some/code/lib/src/code3.dart');
+
+    final file2Source = InSummarySource(
+        Uri.parse('package:some.code/code2.dart'), '' /* summaryPath */);
+    final file3Source = InSummarySource(
+        Uri.parse('package:some.code/src/code2.dart'), '' /* summaryPath */);
+
+    var package = workspace.findPackageFor(targetFile.path);
+    expect(package.contains(file2Source), isTrue);
+    expect(package.contains(file3Source), isTrue);
+  }
 }
 
 class _MockSource implements Source {
diff --git a/pkg/analyzer/test/src/workspace/gn_test.dart b/pkg/analyzer/test/src/workspace/gn_test.dart
index 5d15441..6349e70 100644
--- a/pkg/analyzer/test/src/workspace/gn_test.dart
+++ b/pkg/analyzer/test/src/workspace/gn_test.dart
@@ -7,6 +7,8 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../generated/test_support.dart';
+
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(GnWorkspaceTest);
@@ -206,7 +208,8 @@
     var targetFile = newFile('/ws/some/code/lib/code.dart');
 
     var package = workspace.findPackageFor(targetFile.path);
-    expect(package.contains('/ws2/some/file.dart'), isFalse);
+    expect(package.contains(TestSource(convertPath('/ws2/some/file.dart'))),
+        isFalse);
   }
 
   void test_contains_differentPackageInWorkspace() {
@@ -217,7 +220,10 @@
     var package = workspace.findPackageFor(targetFile.path);
     // A file that is _not_ in this package is not required to have a BUILD.gn
     // file above it, for simplicity and reduced I/O.
-    expect(package.contains('/ws/some/other/code/file.dart'), isFalse);
+    expect(
+        package
+            .contains(TestSource(convertPath('/ws/some/other/code/file.dart'))),
+        isFalse);
   }
 
   void test_contains_samePackage() {
@@ -230,10 +236,10 @@
     var targetTestFile = newFile('/ws/some/code/test/code_test.dart');
 
     var package = workspace.findPackageFor(targetFile.path);
-    expect(package.contains(targetFile2.path), isTrue);
-    expect(package.contains(targetFile3.path), isTrue);
-    expect(package.contains(targetBinFile.path), isTrue);
-    expect(package.contains(targetTestFile.path), isTrue);
+    expect(package.contains(TestSource(targetFile2.path)), isTrue);
+    expect(package.contains(TestSource(targetFile3.path)), isTrue);
+    expect(package.contains(TestSource(targetBinFile.path)), isTrue);
+    expect(package.contains(TestSource(targetTestFile.path)), isTrue);
   }
 
   void test_contains_subPackage() {
@@ -246,7 +252,8 @@
     var package =
         workspace.findPackageFor(convertPath('/ws/some/code/lib/code.dart'));
     expect(
-        package.contains(convertPath('/ws/some/code/testing/lib/testing.dart')),
+        package.contains(
+            TestSource(convertPath('/ws/some/code/testing/lib/testing.dart'))),
         isFalse);
   }
 }
diff --git a/pkg/analyzer/test/src/workspace/package_build_test.dart b/pkg/analyzer/test/src/workspace/package_build_test.dart
index 7fd9011..ef5bd9f 100644
--- a/pkg/analyzer/test/src/workspace/package_build_test.dart
+++ b/pkg/analyzer/test/src/workspace/package_build_test.dart
@@ -2,16 +2,18 @@
 // 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:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer/src/workspace/package_build.dart';
 import 'package:package_config/packages.dart';
-import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../generated/test_support.dart';
+
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PackageBuildFileUriResolverTest);
@@ -229,6 +231,113 @@
 }
 
 @reflectiveTest
+class PackageBuildWorkspacePackageTest with ResourceProviderMixin {
+  MockUriResolver packageUriResolver;
+
+  void test_contains_differentWorkspace() {
+    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
+    newFile('/workspace2/project2/lib/file.dart');
+
+    var package = workspace
+        .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
+    expect(
+        package.contains(
+            TestSource(convertPath('/workspace2/project2/lib/file.dart'))),
+        isFalse);
+  }
+
+  void test_contains_sameWorkspace() {
+    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
+    newFile('/workspace/project/lib/file2.dart');
+
+    var package = workspace
+        .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
+    var file2Path = convertPath('/workspace/project/lib/file2.dart');
+    expect(package.contains(TestSource(file2Path)), isTrue);
+    var binPath = convertPath('/workspace/project/bin/bin.dart');
+    expect(package.contains(TestSource(binPath)), isTrue);
+    var testPath = convertPath('/workspace/project/test/test.dart');
+    expect(package.contains(TestSource(testPath)), isTrue);
+  }
+
+  void test_contains_packageUris() {
+    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
+    newFile('/workspace/project/lib/file2.dart');
+    var package = workspace
+        .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
+    var file2Source = InSummarySource(
+        Uri.parse('package:project/file2.dart'), '' /* summaryPath */);
+    expect(package.contains(file2Source), isTrue);
+  }
+
+  void test_contains_packageUris_unrelatedFile() {
+    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
+    newFile('/workspace/project/lib/file2.dart');
+    var package = workspace
+        .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
+    var file2Source = InSummarySource(
+        Uri.parse('package:project2/file2.dart'), '' /* summaryPath */);
+    expect(package.contains(file2Source), isFalse);
+  }
+
+  void test_findPackageFor_includedFile() {
+    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
+    newFile('/workspace/project/lib/file.dart');
+
+    var package = workspace
+        .findPackageFor(convertPath('/workspace/project/lib/file.dart'));
+    expect(package, isNotNull);
+    expect(package.root, convertPath('/workspace'));
+    expect(package.workspace, equals(workspace));
+  }
+
+  void test_findPackageFor_testFile() {
+    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
+    newFile('/workspace/project/test/test.dart');
+
+    var package = workspace
+        .findPackageFor(convertPath('/workspace/project/test/test.dart'));
+    expect(package, isNotNull);
+    expect(package.root, convertPath('/workspace'));
+    expect(package.workspace, equals(workspace));
+  }
+
+  void test_findPackageFor_unrelatedFile() {
+    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
+    newFile('/workspace/project/lib/file.dart');
+
+    var package = workspace
+        .findPackageFor(convertPath('/workspace2/project2/lib/file.dart'));
+    expect(package, isNull);
+  }
+
+  PackageBuildWorkspace _createPackageBuildWorkspace() {
+    final contextBuilder = new MockContextBuilder();
+    final packagesForWorkspace = new MockPackages();
+    contextBuilder.packagesMapMap[convertPath('/workspace')] =
+        packagesForWorkspace;
+    contextBuilder.packagesToMapMap[packagesForWorkspace] = {
+      'project': <Folder>[getFolder('/workspace')]
+    };
+
+    final packagesForWorkspace2 = new MockPackages();
+    contextBuilder.packagesMapMap[convertPath('/workspace2')] =
+        packagesForWorkspace2;
+    contextBuilder.packagesToMapMap[packagesForWorkspace2] = {
+      'project2': <Folder>[]
+    };
+
+    newFolder('/workspace/.dart_tool/build');
+    newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+    PackageBuildWorkspace workspace = PackageBuildWorkspace.find(
+        resourceProvider, convertPath('/workspace'), contextBuilder);
+    packageUriResolver = new MockUriResolver();
+    new PackageBuildPackageUriResolver(workspace, packageUriResolver);
+    return workspace;
+  }
+}
+
+@reflectiveTest
 class PackageBuildWorkspaceTest with ResourceProviderMixin {
   void test_builtFile_currentProject() {
     newFolder('/workspace/.dart_tool/build');
@@ -483,74 +592,3 @@
         resourceProvider, convertPath(root), contextBuilder);
   }
 }
-
-@reflectiveTest
-class PackageBuildWorkspacePackageTest with ResourceProviderMixin {
-  PackageBuildWorkspace _createPackageBuildWorkspace() {
-    final contextBuilder = new MockContextBuilder();
-    final packagesForWorkspace = new MockPackages();
-    contextBuilder.packagesMapMap[convertPath('/workspace')] =
-        packagesForWorkspace;
-    contextBuilder.packagesToMapMap[packagesForWorkspace] = {
-      'project': <Folder>[]
-    };
-
-    final packagesForWorkspace2 = new MockPackages();
-    contextBuilder.packagesMapMap[convertPath('/workspace2')] =
-        packagesForWorkspace2;
-    contextBuilder.packagesToMapMap[packagesForWorkspace2] = {
-      'project2': <Folder>[]
-    };
-
-    newFolder('/workspace/.dart_tool/build');
-    newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
-    return PackageBuildWorkspace.find(
-        resourceProvider, convertPath('/workspace'), contextBuilder);
-  }
-
-  void test_findPackageFor_unrelatedFile() {
-    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
-    newFile('/workspace/project/lib/file.dart');
-
-    var package = workspace
-        .findPackageFor(convertPath('/workspace2/project2/lib/file.dart'));
-    expect(package, isNull);
-  }
-
-  void test_findPackageFor_includedFile() {
-    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
-    newFile('/workspace/project/lib/file.dart');
-
-    var package = workspace
-        .findPackageFor(convertPath('/workspace/project/lib/file.dart'));
-    expect(package, isNotNull);
-    expect(package.root, convertPath('/workspace'));
-    expect(package.workspace, equals(workspace));
-  }
-
-  void test_contains_differentWorkspace() {
-    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
-    newFile('/workspace2/project2/lib/file.dart');
-
-    var package = workspace
-        .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
-    expect(package.contains('/workspace2/project2/lib/file.dart'), isFalse);
-  }
-
-  void test_contains_sameWorkspace() {
-    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
-    newFile('/workspace/project/lib/file2.dart');
-
-    var package = workspace
-        .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
-    var file2Path =
-        path.separator + path.join('workspace', 'project', 'lib', 'file2.dart');
-    expect(package.contains(file2Path), isTrue);
-    var binPath =
-        path.separator + path.join('workspace', 'project', 'bin', 'bin.dart');
-    expect(package.contains(binPath), isTrue);
-    var testPath =
-        path.separator + path.join('workspace', 'project', 'test', 'test.dart');
-    expect(package.contains(testPath), isTrue);
-  }
-}
diff --git a/pkg/analyzer/test/src/workspace/pub_test.dart b/pkg/analyzer/test/src/workspace/pub_test.dart
index 48d88d6..7e18297 100644
--- a/pkg/analyzer/test/src/workspace/pub_test.dart
+++ b/pkg/analyzer/test/src/workspace/pub_test.dart
@@ -10,6 +10,8 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../generated/test_support.dart';
+
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PubWorkspacePackageTest);
@@ -74,7 +76,10 @@
 
     var package = workspace
         .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
-    expect(package.contains('/workspace2/project/lib/file.dart'), isFalse);
+    expect(
+        package.contains(
+            TestSource(convertPath('/workspace2/project/lib/file.dart'))),
+        isFalse);
   }
 
   void test_contains_sameWorkspace() {
@@ -82,9 +87,18 @@
 
     var package = workspace
         .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
-    expect(package.contains('/workspace/project/lib/file2.dart'), isTrue);
-    expect(package.contains('/workspace/project/bin/bin.dart'), isTrue);
-    expect(package.contains('/workspace/project/test/test.dart'), isTrue);
+    expect(
+        package.contains(
+            TestSource(convertPath('/workspace/project/lib/file2.dart'))),
+        isTrue);
+    expect(
+        package.contains(
+            TestSource(convertPath('/workspace/project/bin/bin.dart'))),
+        isTrue);
+    expect(
+        package.contains(
+            TestSource(convertPath('/workspace/project/test/test.dart'))),
+        isTrue);
   }
 }
 
diff --git a/pkg/analyzer/test/test_all.dart b/pkg/analyzer/test/test_all.dart
index a27c273..f68ff2b 100644
--- a/pkg/analyzer/test/test_all.dart
+++ b/pkg/analyzer/test/test_all.dart
@@ -13,6 +13,7 @@
 import 'parse_compilation_unit_test.dart' as parse_compilation_unit;
 import 'source/test_all.dart' as source;
 import 'src/test_all.dart' as src;
+import 'verify_docs_test.dart' as verify_docs;
 import 'verify_tests_test.dart' as verify_tests;
 
 main() {
@@ -26,6 +27,7 @@
     parse_compilation_unit.main();
     source.main();
     src.main();
+    verify_docs.main();
     verify_tests.main();
   }, name: 'analyzer');
 }
diff --git a/pkg/analyzer/test/verify_docs_test.dart b/pkg/analyzer/test/verify_docs_test.dart
new file mode 100644
index 0000000..22c3858
--- /dev/null
+++ b/pkg/analyzer/test/verify_docs_test.dart
@@ -0,0 +1,161 @@
+// Copyright (c) 2019, 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:convert';
+
+import 'package:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/overlay_file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:front_end/src/testing/package_root.dart' as package_root;
+import 'package:test/test.dart';
+
+main() async {
+  SnippetTester tester = SnippetTester();
+  await tester.verify();
+  if (tester.output.isNotEmpty) {
+    fail(tester.output.toString());
+  }
+}
+
+class SnippetTester {
+  OverlayResourceProvider provider;
+  Folder docFolder;
+  String snippetDirPath;
+  String snippetPath;
+
+  StringBuffer output = StringBuffer();
+
+  SnippetTester() {
+    provider = OverlayResourceProvider(PhysicalResourceProvider.INSTANCE);
+    String packageRoot =
+        provider.pathContext.normalize(package_root.packageRoot);
+    String analyzerPath = provider.pathContext.join(packageRoot, 'analyzer');
+    String docPath = provider.pathContext.join(analyzerPath, 'doc');
+    docFolder = provider.getFolder(docPath);
+    snippetDirPath =
+        provider.pathContext.join(analyzerPath, 'test', 'snippets');
+    snippetPath = provider.pathContext.join(snippetDirPath, 'snippet.dart');
+  }
+
+  void verify() async {
+    await verifyFolder(docFolder);
+  }
+
+  void verifyFile(File file) async {
+    String content = file.readAsStringSync();
+    List<String> lines = const LineSplitter().convert(content);
+    List<String> codeLines = [];
+    bool inCode = false;
+    for (int i = 0; i < lines.length; i++) {
+      String line = lines[i];
+      if (line == '```dart') {
+        if (inCode) {
+          // TODO(brianwilkerson) Report this.
+        }
+        inCode = true;
+      } else if (line == '```') {
+        if (!inCode) {
+          // TODO(brianwilkerson) Report this.
+        }
+        await verifySnippet(file, codeLines.join('\n'));
+        codeLines.clear();
+        inCode = false;
+      } else if (inCode) {
+        codeLines.add(line);
+      }
+    }
+  }
+
+  void verifyFolder(Folder folder) async {
+    for (Resource child in folder.getChildren()) {
+      if (child is File) {
+        if (child.shortName.endsWith('.md')) {
+          await verifyFile(child);
+        }
+      } else if (child is Folder) {
+        await verifyFolder(child);
+      }
+    }
+  }
+
+  void verifySnippet(File file, String snippet) async {
+    // TODO(brianwilkerson) When the files outside of 'src' contain only public
+    //  API, write code to compute the list of imports so that new public API
+    //  will automatically be allowed.
+    String imports = '''
+import 'dart:math' as math;
+
+import 'package:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.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';
+
+''';
+    provider.setOverlay(snippetPath,
+        content: '''
+$imports
+$snippet
+''',
+        modificationStamp: 1);
+    try {
+      AnalysisContextCollection collection = new AnalysisContextCollection(
+          includedPaths: <String>[snippetDirPath], resourceProvider: provider);
+      List<AnalysisContext> contexts = collection.contexts;
+      if (contexts.length != 1) {
+        fail('The snippets directory contains multiple analysis contexts.');
+      }
+      ErrorsResult results =
+          await contexts[0].currentSession.getErrors(snippetPath);
+      Iterable<AnalysisError> errors = results.errors.where((error) {
+        ErrorCode errorCode = error.errorCode;
+        return errorCode != HintCode.UNUSED_IMPORT &&
+            errorCode != HintCode.UNUSED_LOCAL_VARIABLE;
+      });
+      if (errors.isNotEmpty) {
+        String filePath =
+            provider.pathContext.relative(file.path, from: docFolder.path);
+        if (output.isNotEmpty) {
+          output.writeln();
+        }
+        output.writeln('Errors in snippet in "$filePath":');
+        output.writeln();
+        output.writeln(snippet);
+        output.writeln();
+        int importsLength = imports.length + 1; // account for the '\n'.
+        for (var error in errors) {
+          writeError(error, importsLength);
+        }
+      }
+    } catch (exception, stackTrace) {
+      if (output.isNotEmpty) {
+        output.writeln();
+      }
+      output.writeln('Exception while analyzing "$snippet"');
+      output.writeln();
+      output.writeln(exception);
+      output.writeln(stackTrace);
+    } finally {
+      provider.removeOverlay(snippetPath);
+    }
+  }
+
+  void writeError(AnalysisError error, int prefixLength) {
+    output.write(error.errorCode);
+    output.write(' (');
+    output.write(error.offset - prefixLength);
+    output.write(', ');
+    output.write(error.length);
+    output.write(') ');
+    output.writeln(error.message);
+  }
+}
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
new file mode 100644
index 0000000..b3fc35b
--- /dev/null
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -0,0 +1,415 @@
+---
+title: Diagnostics
+description: Details for diagnostics produced by the Dart analyzer.
+---
+
+This page lists diagnostic messages produced by the Dart analyzer,
+with details about what those messages mean and how you can fix your code.
+For more information about the analyzer, see
+[Customizing static analysis](/guides/language/analysis-options).
+
+## Glossary
+
+This page uses the following terms.
+
+### Potentially non-nullable
+
+A type is _potentially non-nullable_ if it's either explicitly non-nullable or
+if it's a type parameter. The latter case is included because the actual runtime
+type might be non-nullable.
+
+## Diagnostics
+
+The analyzer produces the following diagnostics for code that
+doesn't conform to the language specification or
+that might work in unexpected ways.
+
+### ambiguous\_set\_or\_map\_literal\_both
+
+_This literal contains both 'Map' and 'Iterable' spreads, which makes it
+impossible to determine whether the literal is a map or a set._
+
+#### Description
+
+Because map and set literals use the same delimiters (`{` and `}`), the
+analyzer looks at the type arguments and the elements to determine which
+kind of literal you meant. When there are no type arguments and all of the
+elements are spread elements (which are allowed in both kinds of literals),
+then the analyzer uses the types of the expressions that are being spread.
+If all of the expressions have the type `Iterable`, then it's a set
+literal; if they all have the type `Map`, then it's a map literal.
+
+The analyzer produces this diagnostic when some of the expressions being
+spread have the type `Iterable` and others have the type `Map`, making it
+impossible for the analyzer to determine whether you are writing a map
+literal or a set literal.
+
+#### Example
+
+The following code produces this diagnostic:
+
+```dart
+union(Map<String, String> a, List<String> b, Map<String, String> c) =>
+    {...a, ...b, ...c};
+```
+
+The list `b` can only be spread into a set, and the maps `a` and `c` can
+only be spread into a map, and the literal can't be both.
+
+#### Common fixes
+
+There are two common ways to fix this problem. The first is to remove all
+of the spread elements of one kind or the other, so that the elements are
+consistent. In this case, that likely means removing the list (and
+deciding what to do about the now unused parameter):
+
+```dart
+union(Map<String, String> a, List<String> b, Map<String, String> c) =>
+    {...a, ...c};
+```
+
+The second fix is to change the elements of one kind into elements that are
+consistent with the other elements. For example, you could add the elements
+of the list as keys that map to themselves:
+
+```dart
+union(Map<String, String> a, List<String> b, Map<String, String> c) =>
+    {...a, for (String s in b) s: s, ...c};
+```
+
+### ambiguous\_set\_or\_map\_literal\_either
+
+_This literal must be either a map or a set, but the elements don't have enough
+type information for type inference to work._
+
+#### Description
+
+Because map and set literals use the same delimiters (`‘{` and `}`), the
+analyzer looks at the type arguments and the elements to determine which
+kind of literal you meant. When there are no type arguments and all of the
+elements are spread elements (which are allowed in both kinds of literals)
+then the analyzer uses the types of the expressions that are being spread
+to decide. If all of the expressions have the type `Iterable`, then it's a
+set literal, if they all have the type `Map`, then it's a map literal.
+
+This diagnostic is produced when none of the expressions being spread has a
+type that allows the analyzer to decide whether you were writing a map
+literal or a set literal.
+
+#### Example
+
+The following code produces this diagnostic:
+
+```dart
+union(a, b) => !{...a, ...b}!;
+```
+
+The problem occurs because there are no type arguments, and there is no
+information about the type of either `a` or `b`.
+
+#### Common fixes
+
+There are three common ways to fix this problem. The first is to add type
+arguments to the literal. For example, if the literal is intended to be a
+map literal, you might write something like this:
+
+```dart
+union(a, b) => <String, String>{...a, ...b};
+```
+
+The second fix is to add type information so that the expressions have
+either the type `Iterable` or the type `Map`. You could add an explicit
+cast or, in this case, add types to the declarations of the two parameters:
+
+```dart
+union(List<int> a, List<int> b) => {...a, ...b};
+```
+
+The third fix is to add context information. In this case, that means
+adding a return type to the function:
+
+```dart
+Set<String> union(a, b) => {...a, ...b};
+```
+
+In other cases, you might add a type somewhere else. For example, say the
+original code looks like this:
+
+```dart
+union(a, b) {
+  var x = {...a, ...b};
+  return x;
+}
+```
+
+You might add a type annotation on `x`, like this:
+
+```dart
+union(a, b) {
+  Map<String, String> x = {...a, ...b};
+  return x;
+}
+```
+
+### default\_value\_on\_required\_parameter
+
+_Required named parameters can't have a default value._
+
+#### Description
+
+The analyzer produces this diagnostic when a named parameter has both the
+`required` modifier and a default value. If the parameter is required, then
+a value for the parameter is always provided at the call sites, so the
+default value can never be used.
+
+#### Example
+
+The following code generates this diagnostic:
+
+```dart
+void log({required String !message! = 'no message'}) {}
+```
+
+#### Common fixes
+
+If the parameter is really required, then remove the default value:
+
+```dart
+void log({required String message}) {}
+```
+
+If the parameter isn't always required, then remove the `required`
+modifier:
+
+```dart
+void log({String message = 'no message'}) {}
+```
+
+### deprecated\_member\_use
+
+_'{0}' is deprecated and shouldn't be used._
+
+#### Description
+
+The analyzer produces this diagnostic when a deprecated library or class
+member is used in a different package.
+
+#### Example
+
+If the method `m` in the class `C` is annotated with `@deprecated`, then
+the following code produces this diagnostic:
+
+```dart
+void f(C c) {
+  c.!m!();
+}
+```
+
+#### Common fixes
+
+The documentation for declarations that are annotated with `@deprecated`
+should have documentation to indicate what code to use in place of the
+deprecated code.
+
+### expression\_in\_map
+
+_Expressions can't be used in a map literal._
+
+#### Description
+
+The analyzer produces this diagnostic when the analyzer finds an
+expression, rather than a map entry, in what appears to be a map literal.
+
+#### Example
+
+The following code generates this diagnostic:
+
+```dart
+var map = <String, int>{'a': 0, 'b': 1, !'c'!};
+```
+
+#### Common fixes
+
+If the expression is intended to compute either a key or a value in an
+entry, fix the issue by completing the code:
+
+```dart
+var map = <String, int>{'a': 0, 'b': 1, 'c': 2};
+```
+
+### invalid\_literal\_annotation
+
+_Only const constructors can have the `@literal` annotation._
+
+#### Description
+
+The meaning of the `@literal` annotation is only defined when it's applied
+to a const constructor.
+
+#### Example
+
+The following code produces this diagnostic:
+
+```dart
+!@literal!
+var x;
+```
+
+#### Common fixes
+
+Remove the annotation:
+
+```dart
+var x;
+```
+
+### missing\_default\_value\_for\_parameter
+
+_The parameter '{0}' can't have a value of 'null' because of its type, so it
+must either be a required parameter or have a default value._
+
+#### Description
+
+The analyzer produces this diagnostic when an optional parameter doesn't
+have a default value, but has a
+<a href=”#potentially-non-nullable”>potentially non-nullable</a> type.
+Optional parameters that have no explicit default value have an implicit
+default value of `null`. If the type of the parameter doesn't allow the
+parameter to have a value of null, then the implicit default value is not
+valid.
+
+#### Example
+
+The following code generates this diagnostic:
+
+```dart
+void log({String !message!}) {}
+```
+
+#### Common fixes
+
+If the parameter can have the value `null`, then add a question mark after
+the type annotation:
+
+```dart
+void log({String? message}) {}
+```
+
+If the parameter can't be null, then either provide a default value:
+
+```dart
+void log({String message = ''}) {}
+```
+
+or add the `required` modifier to the parameter:
+
+```dart
+void log({required String message}) {}
+```
+
+### not\_iterable\_spread
+
+_Spread elements in list or set literals must implement 'Iterable'._
+
+#### Description
+
+The analyzer produces this diagnostic when the static type of the
+expression of a spread element that appears in either a list literal or a
+set literal doesn't implement the type `Iterable`.
+
+#### Example
+
+The following code generates this diagnostic:
+
+```dart
+var m = <String, int>{'a': 0, 'b': 1};
+var s = <String>{...m};
+```
+
+#### Common fixes
+
+The most common fix is to replace the expression with one that produces an
+iterable object:
+
+```dart
+var m = <String, int>{'a': 0, 'b': 1};
+var s = <String>{...m.keys};
+```
+
+### nullable\_type\_in\_extends\_clause
+
+_A class can't extend a nullable type._
+
+#### Description
+
+The analyzer produces this diagnostic when a class declaration uses an
+extends clause to specify a superclass, and the type that's specified is a
+nullable type.
+
+The reason the supertype is a _type_ rather than a class name is to allow
+you to control the signatures of the members to be inherited from the
+supertype, such as by specifying type arguments. However, the nullability
+of a type doesn't change the signatures of any members, so there isn't any
+reason to allow the nullability to be specified when used in the extends
+clause.
+
+#### Example
+
+The following code generates this diagnostic:
+
+```dart
+class Invalid extends !Duration?! {}
+```
+
+#### Common fixes
+
+The most common fix is to remove the question mark:
+
+```dart
+class Invalid extends Duration {}
+```
+
+### sdk\_version\_set\_literal
+
+_Set literals weren't supported until version 2.2, but this code must be able to
+run on earlier versions._
+
+#### Description
+
+The analyzer produces this diagnostic when a set literal is found in code
+that has an SDK constraint whose lower bound is less than 2.2. Set literals
+were not supported in earlier versions, so this code won't be able to run
+against earlier versions of the SDK.
+
+#### Example
+
+In a package that defines SDK constraints in the `pubspec.yaml` file that
+have a lower bound that's less than 2.2:
+
+```yaml
+environment:
+  sdk: '>=2.1.0 <2.4.0'
+```
+
+The following code generates this diagnostic:
+
+```dart
+var s = !<int>{}!;
+```
+
+#### Common fixes
+
+If you don't need to support older versions of the SDK, then you can
+increase the SDK constraint to allow the syntax to be used:
+
+```yaml
+environment:
+  sdk: '>=2.2.0 <2.4.0'
+```
+
+If you do need to support older versions of the SDK, then replace the set
+literal with code that creates the set without the use of a literal:
+
+```dart
+var s = new Set<int>();
+```
diff --git a/pkg/analyzer/tool/diagnostics/generate.dart b/pkg/analyzer/tool/diagnostics/generate.dart
new file mode 100644
index 0000000..17350b5
--- /dev/null
+++ b/pkg/analyzer/tool/diagnostics/generate.dart
@@ -0,0 +1,216 @@
+// Copyright (c) 2019, 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:io';
+
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:front_end/src/testing/package_root.dart' as package_root;
+import 'package:path/src/context.dart';
+
+/// Generate the file `diagnostics.md` based on the documentation associated
+/// with the declarations of the error codes.
+void main() async {
+  Context pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
+  String packageRoot = pathContext.normalize(package_root.packageRoot);
+  String analyzerPath = pathContext.join(packageRoot, 'analyzer');
+  List<String> docPaths = [
+    pathContext.join(
+        analyzerPath, 'lib', 'src', 'dart', 'error', 'hint_codes.dart'),
+    pathContext.join(analyzerPath, 'lib', 'src', 'error', 'codes.dart'),
+  ];
+  String outputPath =
+      pathContext.join(analyzerPath, 'tool', 'diagnostics', 'diagnostics.md');
+
+  DocumentationGenerator generator = DocumentationGenerator(docPaths);
+  generator.writeDocumentation(outputPath);
+}
+
+/// A class used to generate diagnostic documentation.
+class DocumentationGenerator {
+  /// The absolute paths of the files containing the declarations of the error
+  /// codes.
+  final List<String> docPaths;
+
+  /// A map from the name of a diagnostic code to the lines of the documentation
+  /// for that code.
+  Map<String, List<String>> docsByCode = {};
+
+  /// Initialize a newly created documentation generator.
+  DocumentationGenerator(this.docPaths) {
+    _extractAllDocs();
+  }
+
+  /// Write the documentation to the file at the given [outputPath].
+  void writeDocumentation(String outputPath) async {
+    IOSink sink = File(outputPath).openWrite();
+    _writeHeader(sink);
+    _writeGlossary(sink);
+    _writeDiagnostics(sink);
+    await sink.flush();
+    await sink.close();
+  }
+
+  /// Return a version of the [text] in which characters that have special
+  /// meaning in markdown have been escaped.
+  String _escape(String text) {
+    return text.replaceAll('_', '\\_');
+  }
+
+  /// Extract documentation from all of the files containing the definitions of
+  /// diagnostics.
+  void _extractAllDocs() {
+    AnalysisContextCollection collection = new AnalysisContextCollection(
+        includedPaths: docPaths,
+        resourceProvider: PhysicalResourceProvider.INSTANCE);
+    for (String docPath in docPaths) {
+      _extractDocs(_parse(collection, docPath));
+    }
+  }
+
+  /// Extract documentation from the given [field] declaration.
+  List<String> _extractDoc(FieldDeclaration field) {
+    Token comments = field.firstTokenAfterCommentAndMetadata.precedingComments;
+    if (comments == null) {
+      return null;
+    }
+    List<String> docs = [];
+    while (comments != null) {
+      String lexeme = comments.lexeme;
+      if (lexeme.startsWith('// TODO')) {
+        break;
+      } else if (lexeme.startsWith('// ')) {
+        docs.add(lexeme.substring(3));
+      } else if (lexeme == '//') {
+        docs.add('');
+      }
+      comments = comments.next;
+    }
+    if (docs.isEmpty) {
+      return null;
+    }
+    return docs;
+  }
+
+  /// Extract documentation from the file that was parsed to produce the given
+  /// [result].
+  void _extractDocs(ParsedUnitResult result) {
+    CompilationUnit unit = result.unit;
+    for (CompilationUnitMember declaration in unit.declarations) {
+      if (declaration is ClassDeclaration) {
+        for (ClassMember member in declaration.members) {
+          if (member is FieldDeclaration) {
+            List<String> docs = _extractDoc(member);
+            if (docs != null) {
+              VariableDeclaration variable = member.fields.variables[0];
+              String variableName = variable.name.name;
+              if (docsByCode.containsKey(variableName)) {
+                throw StateError('Duplicate diagnostic code');
+              }
+              String message =
+                  ((variable.initializer as InstanceCreationExpression)
+                          .argumentList
+                          .arguments[1] as StringLiteral)
+                      .stringValue;
+              docs = [
+                '### ${_escape(variableName.toLowerCase())}',
+                '',
+                ..._split('_${_escape(message)}_'),
+                '',
+                ...docs,
+              ];
+              docsByCode[variableName] = docs;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /// Use the analysis context [collection] to parse the file at the given
+  /// [path] and return the result.
+  ParsedUnitResult _parse(AnalysisContextCollection collection, String path) {
+    AnalysisSession session = collection.contextFor(path).currentSession;
+    if (session == null) {
+      throw new StateError('No session for "$path"');
+    }
+    ParsedUnitResult result = session.getParsedUnit(path);
+    if (result.state != ResultState.VALID) {
+      throw new StateError('Unable to parse "$path"');
+    }
+    return result;
+  }
+
+  /// Split the [message] into multiple lines, each of which is less than 80
+  /// characters long.
+  List<String> _split(String message) {
+    // This uses a brute force approach because we don't expect to have messages
+    // that need to be split more than once.
+    int length = message.length;
+    if (length <= 80) {
+      return [message];
+    }
+    int endIndex = message.lastIndexOf(' ', 80);
+    if (endIndex < 0) {
+      return [message];
+    }
+    return [message.substring(0, endIndex), message.substring(endIndex + 1)];
+  }
+
+  /// Write the documentation for all of the diagnostics.
+  void _writeDiagnostics(IOSink sink) {
+    sink.write('''
+
+## Diagnostics
+
+The analyzer produces the following diagnostics for code that
+doesn't conform to the language specification or
+that might work in unexpected ways.
+''');
+    List<String> errorCodes = docsByCode.keys.toList();
+    errorCodes.sort();
+    for (String errorCode in errorCodes) {
+      List<String> docs = docsByCode[errorCode];
+      sink.writeln();
+      for (String line in docs) {
+        sink.writeln(line);
+      }
+    }
+  }
+
+  /// Write the glossary.
+  void _writeGlossary(IOSink sink) {
+    sink.write('''
+
+## Glossary
+
+This page uses the following terms.
+
+### Potentially non-nullable
+
+A type is _potentially non-nullable_ if it's either explicitly non-nullable or
+if it's a type parameter. The latter case is included because the actual runtime
+type might be non-nullable.
+''');
+  }
+
+  /// Write the header of the file.
+  void _writeHeader(IOSink sink) {
+    sink.write('''
+---
+title: Diagnostics
+description: Details for diagnostics produced by the Dart analyzer.
+---
+
+This page lists diagnostic messages produced by the Dart analyzer,
+with details about what those messages mean and how you can fix your code.
+For more information about the analyzer, see
+[Customizing static analysis](/guides/language/analysis-options).
+''');
+  }
+}
diff --git a/pkg/analyzer/tool/experiments/experiments_test.dart b/pkg/analyzer/tool/experiments/experiments_test.dart
new file mode 100644
index 0000000..167c033
--- /dev/null
+++ b/pkg/analyzer/tool/experiments/experiments_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, 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:io" show Platform;
+
+import 'package:analysis_tool/tools.dart';
+import 'package:path/path.dart';
+
+import 'generate.dart';
+
+/**
+ * Check that all targets have been code generated.  If they haven't tell the
+ * user to run generate_all.dart.
+ */
+main() async {
+  String script = Platform.script.toFilePath(windows: Platform.isWindows);
+  List<String> components = split(script);
+  int index = components.indexOf('analyzer');
+  String pkgPath = joinAll(components.sublist(0, index + 1));
+  await GeneratedContent.checkAll(pkgPath,
+      join(pkgPath, 'tool', 'experiments', 'generate.dart'), allTargets);
+}
diff --git a/pkg/analyzer/tool/experiments/generate.dart b/pkg/analyzer/tool/experiments/generate.dart
new file mode 100644
index 0000000..d74f223
--- /dev/null
+++ b/pkg/analyzer/tool/experiments/generate.dart
@@ -0,0 +1,271 @@
+/**
+ * This file contains code to generate experimental flags
+ * based on the information in tools/experimental_features.yaml.
+ */
+import 'dart:io';
+
+import 'package:analysis_tool/tools.dart';
+import 'package:front_end/src/fasta/scanner/characters.dart' show $MINUS, $_;
+import 'package:front_end/src/testing/package_root.dart' as pkgRoot;
+import 'package:path/path.dart';
+import 'package:yaml/yaml.dart' show YamlMap, loadYaml;
+
+main() async {
+  await GeneratedContent.generateAll(
+      normalize(join(pkgRoot.packageRoot, 'analyzer')), allTargets);
+}
+
+List<GeneratedContent> get allTargets {
+  Map<dynamic, dynamic> experimentsYaml = loadYaml(new File(join(
+          normalize(join(pkgRoot.packageRoot, '../tools')),
+          'experimental_features.yaml'))
+      .readAsStringSync());
+
+  return <GeneratedContent>[
+    new GeneratedFile('lib/src/dart/analysis/experiments.g.dart',
+        (String pkgPath) async {
+      var generator = new _ExperimentsGenerator(experimentsYaml);
+      generator.generateFormatCode();
+      return generator.out.toString();
+    }),
+  ];
+}
+
+String keyToIdentifier(String key) {
+  var identifier = StringBuffer();
+  for (int index = 0; index < key.length; ++index) {
+    var code = key.codeUnitAt(index);
+    if (code == $MINUS) {
+      code = $_;
+    }
+    identifier.writeCharCode(code);
+  }
+  return identifier.toString();
+}
+
+class _ExperimentsGenerator {
+  final Map experimentsYaml;
+
+  List<String> keysSorted;
+
+  final out = new StringBuffer('''
+//
+// THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Instead modify 'tools/experimental_features.yaml' and run
+// 'dart pkg/analyzer/tool/experiments/generate.dart' to update.
+
+part of 'experiments.dart';
+''');
+
+  _ExperimentsGenerator(this.experimentsYaml);
+
+  void generateFormatCode() {
+    keysSorted = experimentsYaml.keys.cast<String>().toList()..sort();
+    generateSection_KnownFeatures();
+    generateSection_BuildExperimentalFlagsArray();
+    generateSection_EnableString();
+    generateSection_ExperimentalFeature();
+    generateSection_IsEnabledByDefault();
+    generateSection_IsExpired();
+    generateSection_CurrentState();
+  }
+
+  void generateSection_BuildExperimentalFlagsArray() {
+    out.write('''
+
+List<bool> _buildExperimentalFlagsArray() => <bool>[
+''');
+    for (var key in keysSorted) {
+      var id = keyToIdentifier(key);
+      var entry = experimentsYaml[key] as YamlMap;
+      bool shipped = entry['enabledIn'] != null;
+      bool expired = entry['expired'];
+      if (shipped || expired == true) {
+        out.writeln('true, // $key');
+      } else {
+        out.writeln('IsEnabledByDefault.$id,');
+      }
+    }
+    // TODO(danrubel): Remove bogus entries
+    out.write('''
+      false, // bogus-disabled
+      true, // bogus-enabled
+    ];
+''');
+  }
+
+  void generateSection_CurrentState() {
+    // TODO(danrubel): Remove bogus entries
+    out.write('''
+
+mixin _CurrentState {
+  /// Current state for the flag "bogus-disabled"
+  bool get bogus_disabled => isEnabled(ExperimentalFeatures.bogus_disabled);
+
+  /// Current state for the flag "bogus-enabled"
+  bool get bogus_enabled => isEnabled(ExperimentalFeatures.bogus_enabled);
+''');
+    for (var key in keysSorted) {
+      var id = keyToIdentifier(key);
+      out.write('''
+  /// Current state for the flag "$key"
+  bool get $id => isEnabled(ExperimentalFeatures.$id);
+    ''');
+    }
+    out.write('''
+
+  bool isEnabled(covariant ExperimentalFeature feature);
+}''');
+  }
+
+  void generateSection_EnableString() {
+    out.write('''
+
+/// Constant strings for enabling each of the currently known experimental
+/// flags.
+class EnableString {
+''');
+    for (var key in keysSorted) {
+      out.write('''
+      /// String to enable the experiment "$key"
+      static const String ${keyToIdentifier(key)} = '$key';
+    ''');
+    }
+    // TODO(danrubel): Remove bogus entries
+    out.write('''
+
+      /// String to enable the experiment "bogus-disabled"
+      static const String bogus_disabled = 'bogus-disabled';
+
+      /// String to enable the experiment "bogus-enabled"
+      static const String bogus_enabled = 'bogus-enabled';
+    }''');
+  }
+
+  void generateSection_ExperimentalFeature() {
+    out.write('''
+
+class ExperimentalFeatures {
+''');
+    int index = 0;
+    for (var key in keysSorted) {
+      var id = keyToIdentifier(key);
+      var help = (experimentsYaml[key] as YamlMap)['help'] ?? '';
+      var enabledIn = (experimentsYaml[key] as YamlMap)['enabledIn'];
+      out.write('''
+
+      static const $id = const ExperimentalFeature(
+      $index,
+      EnableString.$id,
+      IsEnabledByDefault.$id,
+      IsExpired.$id,
+      '$help'
+    ''');
+      if (enabledIn != null) {
+        if (enabledIn is double) {
+          enabledIn = '$enabledIn.0';
+        }
+        out.write(",firstSupportedVersion: '$enabledIn'");
+      }
+      out.writeln(');');
+      ++index;
+    }
+    // TODO(danrubel): Remove bogus entries
+    out.write('''
+
+      static const bogus_disabled = const ExperimentalFeature(
+        $index,
+        EnableString.bogus_disabled,
+        IsEnabledByDefault.bogus_disabled,
+        IsExpired.bogus_disabled,
+        null);
+
+      static const bogus_enabled = const ExperimentalFeature(
+        ${index + 1},
+        EnableString.bogus_enabled,
+        IsEnabledByDefault.bogus_enabled,
+        IsExpired.bogus_enabled,
+        null,
+        firstSupportedVersion: '1.0.0');
+    }''');
+  }
+
+  void generateSection_IsEnabledByDefault() {
+    out.write('''
+
+/// Constant bools indicating whether each experimental flag is currently
+/// enabled by default.
+class IsEnabledByDefault {
+''');
+    for (var key in keysSorted) {
+      var entry = experimentsYaml[key] as YamlMap;
+      bool shipped = entry['enabledIn'] != null;
+      out.write('''
+      /// Default state of the experiment "$key"
+      static const bool ${keyToIdentifier(key)} = $shipped;
+    ''');
+    }
+    // TODO(danrubel): Remove bogus entries
+    out.write('''
+
+      /// Default state of the experiment "bogus-disabled"
+      static const bool bogus_disabled = false;
+
+      /// Default state of the experiment "bogus-enabled"
+      static const bool bogus_enabled = true;
+    }''');
+  }
+
+  void generateSection_IsExpired() {
+    out.write('''
+
+/// Constant bools indicating whether each experimental flag is currently
+/// expired (meaning its enable/disable status can no longer be altered from the
+/// value in [IsEnabledByDefault]).
+class IsExpired {
+''');
+    for (var key in keysSorted) {
+      var entry = experimentsYaml[key] as YamlMap;
+      bool shipped = entry['enabledIn'] != null;
+      bool expired = entry['expired'];
+      out.write('''
+      /// Expiration status of the experiment "$key"
+      static const bool ${keyToIdentifier(key)} = ${expired == true};
+    ''');
+      if (shipped && expired == false) {
+        throw 'Cannot mark shipped feature as "expired: false"';
+      }
+    }
+    // TODO(danrubel): Remove bogus entries
+    out.write('''
+
+      /// Expiration status of the experiment "bogus-disabled"
+      static const bool bogus_disabled = true;
+
+      /// Expiration status of the experiment "bogus-enabled"
+      static const bool bogus_enabled = true;
+    }''');
+  }
+
+  void generateSection_KnownFeatures() {
+    out.write('''
+
+/// A map containing information about all known experimental flags.
+const _knownFeatures = <String, ExperimentalFeature>{
+''');
+    for (var key in keysSorted) {
+      var id = keyToIdentifier(key);
+      out.write('''
+  EnableString.$id: ExperimentalFeatures.$id,
+    ''');
+    }
+    // TODO(danrubel): Remove bogus entries
+    out.write('''
+
+  EnableString.bogus_disabled: ExperimentalFeatures.bogus_disabled,
+  EnableString.bogus_enabled: ExperimentalFeatures.bogus_enabled,
+};
+''');
+  }
+}
diff --git a/pkg/analyzer/tool/messages/generate.dart b/pkg/analyzer/tool/messages/generate.dart
index a88a897..babac722 100644
--- a/pkg/analyzer/tool/messages/generate.dart
+++ b/pkg/analyzer/tool/messages/generate.dart
@@ -62,7 +62,7 @@
 """;
 
 const shouldRunFastaGenerateMessagesFirst = """
-Error: After modifying message.yaml, run this first:
+Error: After modifying messages.yaml, run this first:
        pkg/front_end/tool/fasta generate-messages
 """;
 
diff --git a/pkg/analyzer/tool/summary/dump_inferred_types.dart b/pkg/analyzer/tool/summary/dump_inferred_types.dart
index 81d2a34..ee6bb64 100644
--- a/pkg/analyzer/tool/summary/dump_inferred_types.dart
+++ b/pkg/analyzer/tool/summary/dump_inferred_types.dart
@@ -176,9 +176,9 @@
     } else {
       result = param.name;
     }
-    if (param.kind == UnlinkedParamKind.named) {
+    if (param.kind == UnlinkedParamKind.optionalNamed) {
       result = '{$result}';
-    } else if (param.kind == UnlinkedParamKind.positional) {
+    } else if (param.kind == UnlinkedParamKind.optionalPositional) {
       result = '[$result]';
     }
     return result;
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index 798e369..d27a4d8 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -54,16 +54,591 @@
 
 typedef String _StringToString(String s);
 
-class _CodeGenerator {
+class _BaseGenerator {
   static const String _throwDeprecated =
       "throw new UnimplementedError('attempt to access deprecated field')";
 
+  /// Semantic model of the "IDL" input file.
+  final idlModel.Idl _idl;
+
   /// Buffer in which generated code is accumulated.
-  final StringBuffer _outBuffer = new StringBuffer();
+  final StringBuffer _outBuffer;
 
   /// Current indentation level.
   String _indentation = '';
 
+  _BaseGenerator(this._idl, this._outBuffer);
+
+  /// Generate a Dart expression representing the default value for a field
+  /// having the given [type], or `null` if there is no default value.
+  ///
+  /// If [builder] is `true`, the returned type should be appropriate for use in
+  /// a builder class.
+  String defaultValue(idlModel.FieldType type, bool builder) {
+    if (type.isList) {
+      if (builder) {
+        idlModel.FieldType elementType =
+            new idlModel.FieldType(type.typeName, false);
+        return '<${encodedType(elementType)}>[]';
+      } else {
+        return 'const <${idlPrefix(type.typeName)}>[]';
+      }
+    } else if (_idl.enums.containsKey(type.typeName)) {
+      return '${idlPrefix(type.typeName)}.'
+          '${_idl.enums[type.typeName].values[0].name}';
+    } else if (type.typeName == 'double') {
+      return '0.0';
+    } else if (type.typeName == 'int') {
+      return '0';
+    } else if (type.typeName == 'String') {
+      return "''";
+    } else if (type.typeName == 'bool') {
+      return 'false';
+    } else {
+      return null;
+    }
+  }
+
+  /// Generate a string representing the Dart type which should be used to
+  /// represent [type] while building a serialized data structure.
+  String encodedType(idlModel.FieldType type) {
+    String typeStr;
+    if (_idl.classes.containsKey(type.typeName)) {
+      typeStr = '${type.typeName}Builder';
+    } else {
+      typeStr = idlPrefix(type.typeName);
+    }
+    if (type.isList) {
+      return 'List<$typeStr>';
+    } else {
+      return typeStr;
+    }
+  }
+
+  /// Add the prefix `idl.` to a type name, unless that type name is the name of
+  /// a built-in type.
+  String idlPrefix(String s) {
+    switch (s) {
+      case 'bool':
+      case 'double':
+      case 'int':
+      case 'String':
+        return s;
+      default:
+        return 'idl.$s';
+    }
+  }
+
+  /// Execute [callback] with two spaces added to [_indentation].
+  void indent(void callback()) {
+    String oldIndentation = _indentation;
+    try {
+      _indentation += '  ';
+      callback();
+    } finally {
+      _indentation = oldIndentation;
+    }
+  }
+
+  /// Add the string [s] to the output as a single line, indenting as
+  /// appropriate.
+  void out([String s = '']) {
+    if (s == '') {
+      _outBuffer.writeln('');
+    } else {
+      _outBuffer.writeln('$_indentation$s');
+    }
+  }
+
+  void outDoc(String documentation) {
+    if (documentation != null) {
+      documentation.split('\n').forEach(out);
+    }
+  }
+
+  /// Enclose [s] in quotes, escaping as necessary.
+  String quoted(String s) {
+    return json.encode(s);
+  }
+
+  List<String> _computeVariants(idlModel.ClassDeclaration cls) {
+    var allVariants = Set<String>();
+    for (var field in cls.fields) {
+      var logicalFields = field.logicalProperties?.values;
+      if (logicalFields != null) {
+        for (var logicalField in logicalFields) {
+          allVariants.addAll(logicalField.variants);
+        }
+      }
+    }
+    return allVariants.toList()..sort();
+  }
+
+  String _variantAssertStatement(
+    idlModel.ClassDeclaration class_,
+    idlModel.LogicalProperty property,
+  ) {
+    var assertCondition = property.variants
+        ?.map((key) => '${class_.variantField} == idl.$key')
+        ?.join(' || ');
+    return 'assert($assertCondition);';
+  }
+}
+
+class _BuilderGenerator extends _BaseGenerator {
+  final idlModel.ClassDeclaration cls;
+  List<String> constructorParams = <String>[];
+
+  _BuilderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+      : super(idl, outBuffer);
+
+  String get builderName => name + 'Builder';
+
+  String get name => cls.name;
+
+  void generate() {
+    String mixinName = '_${name}Mixin';
+    var implementsClause =
+        cls.isDeprecated ? '' : ' implements ${idlPrefix(name)}';
+    out('class $builderName extends Object with $mixinName$implementsClause {');
+    indent(() {
+      _generateFields();
+      _generateGettersSetters();
+      _generateConstructors();
+      _generateFlushInformative();
+      _generateCollectApiSignature();
+      _generateToBuffer();
+      _generateFinish();
+    });
+    out('}');
+  }
+
+  void _generateCollectApiSignature() {
+    out();
+    out('/// Accumulate non-[informative] data into [signature].');
+    out('void collectApiSignature(api_sig.ApiSignature signature) {');
+
+    void writeField(String name, idlModel.FieldType type, bool isInformative) {
+      if (isInformative) {
+        return;
+      }
+      String ref = 'this.$name';
+      if (type.isList) {
+        out('if ($ref == null) {');
+        indent(() {
+          out('signature.addInt(0);');
+        });
+        out('} else {');
+        indent(() {
+          out('signature.addInt($ref.length);');
+          out('for (var x in $ref) {');
+          indent(() {
+            _generateSignatureCall(type.typeName, 'x', false);
+          });
+          out('}');
+        });
+        out('}');
+      } else {
+        _generateSignatureCall(type.typeName, ref, true);
+      }
+    }
+
+    indent(() {
+      List<idlModel.FieldDeclaration> sortedFields = cls.fields.toList()
+        ..sort((idlModel.FieldDeclaration a, idlModel.FieldDeclaration b) =>
+            a.id.compareTo(b.id));
+      if (cls.variantField != null) {
+        var firstVariant = true;
+        for (var variant in _computeVariants(cls)) {
+          if (firstVariant) {
+            firstVariant = false;
+          } else {
+            out('else');
+          }
+          out('if (${cls.variantField} == idl.$variant) {');
+          indent(() {
+            for (var field in sortedFields) {
+              var logicalProperties = field.logicalProperties;
+              if (logicalProperties != null) {
+                for (var logicalName in logicalProperties.keys) {
+                  var logicalProperty = logicalProperties[logicalName];
+                  if (logicalProperty.variants.contains(variant)) {
+                    writeField(
+                      logicalName,
+                      field.type,
+                      logicalProperty.isInformative,
+                    );
+                  }
+                }
+              } else {
+                writeField(field.name, field.type, field.isInformative);
+              }
+            }
+          });
+          out('}');
+        }
+      } else {
+        for (idlModel.FieldDeclaration field in sortedFields) {
+          writeField('_${field.name}', field.type, field.isInformative);
+        }
+      }
+    });
+    out('}');
+  }
+
+  void _generateConstructors() {
+    out();
+    if (cls.variantField != null) {
+      for (var variant in _computeVariants(cls)) {
+        var constructorName = variant.split('.')[1];
+        out('$builderName.$constructorName({');
+
+        for (var field in cls.fields) {
+          if (field.logicalProperties != null) {
+            for (var logicalName in field.logicalProperties.keys) {
+              var logicalProperty = field.logicalProperties[logicalName];
+              if (logicalProperty.variants.contains(variant)) {
+                out('${encodedType(field.type)} $logicalName,');
+              }
+            }
+          }
+        }
+
+        out('}) : ');
+
+        out('_${cls.variantField} = idl.$variant');
+
+        var separator = ',';
+        for (var field in cls.fields) {
+          if (field.logicalProperties != null) {
+            for (var logicalName in field.logicalProperties.keys) {
+              var logicalProperty = field.logicalProperties[logicalName];
+              if (logicalProperty.variants.contains(variant)) {
+                out('$separator _${field.name} = $logicalName');
+                separator = ', ';
+              }
+            }
+          }
+        }
+
+        out(';');
+        out();
+      }
+    } else {
+      out('$builderName({${constructorParams.join(', ')}})');
+      List<idlModel.FieldDeclaration> fields = cls.fields.toList();
+      for (int i = 0; i < fields.length; i++) {
+        idlModel.FieldDeclaration field = fields[i];
+        String prefix = i == 0 ? '  : ' : '    ';
+        String suffix = i == fields.length - 1 ? ';' : ',';
+        out('${prefix}_${field.name} = ${field.name}$suffix');
+      }
+    }
+  }
+
+  void _generateFields() {
+    for (idlModel.FieldDeclaration field in cls.fields) {
+      String fieldName = field.name;
+      idlModel.FieldType type = field.type;
+      String typeStr = encodedType(type);
+      out('$typeStr _$fieldName;');
+    }
+  }
+
+  void _generateFinish() {
+    out();
+    out('fb.Offset finish(fb.Builder fbBuilder) {');
+    indent(() {
+      // Write objects and remember Offset(s).
+      for (idlModel.FieldDeclaration field in cls.fields) {
+        idlModel.FieldType fieldType = field.type;
+        String offsetName = 'offset_' + field.name;
+        if (fieldType.isList ||
+            fieldType.typeName == 'String' ||
+            _idl.classes.containsKey(fieldType.typeName)) {
+          out('fb.Offset $offsetName;');
+        }
+      }
+
+      for (idlModel.FieldDeclaration field in cls.fields) {
+        idlModel.FieldType fieldType = field.type;
+        String valueName = '_' + field.name;
+        String offsetName = 'offset_' + field.name;
+        String condition;
+        String writeCode;
+        if (fieldType.isList) {
+          condition = ' || $valueName.isEmpty';
+          if (_idl.classes.containsKey(fieldType.typeName)) {
+            String itemCode = 'b.finish(fbBuilder)';
+            String listCode = '$valueName.map((b) => $itemCode).toList()';
+            writeCode = '$offsetName = fbBuilder.writeList($listCode);';
+          } else if (_idl.enums.containsKey(fieldType.typeName)) {
+            String itemCode = 'b.index';
+            String listCode = '$valueName.map((b) => $itemCode).toList()';
+            writeCode = '$offsetName = fbBuilder.writeListUint8($listCode);';
+          } else if (fieldType.typeName == 'bool') {
+            writeCode = '$offsetName = fbBuilder.writeListBool($valueName);';
+          } else if (fieldType.typeName == 'int') {
+            writeCode = '$offsetName = fbBuilder.writeListUint32($valueName);';
+          } else if (fieldType.typeName == 'double') {
+            writeCode = '$offsetName = fbBuilder.writeListFloat64($valueName);';
+          } else {
+            assert(fieldType.typeName == 'String');
+            String itemCode = 'fbBuilder.writeString(b)';
+            String listCode = '$valueName.map((b) => $itemCode).toList()';
+            writeCode = '$offsetName = fbBuilder.writeList($listCode);';
+          }
+        } else if (fieldType.typeName == 'String') {
+          writeCode = '$offsetName = fbBuilder.writeString($valueName);';
+        } else if (_idl.classes.containsKey(fieldType.typeName)) {
+          writeCode = '$offsetName = $valueName.finish(fbBuilder);';
+        }
+        if (writeCode != null) {
+          if (condition == null) {
+            out('if ($valueName != null) {');
+          } else {
+            out('if (!($valueName == null$condition)) {');
+          }
+          indent(() {
+            out(writeCode);
+          });
+          out('}');
+        }
+      }
+
+      // Write the table.
+      out('fbBuilder.startTable();');
+      for (idlModel.FieldDeclaration field in cls.fields) {
+        int index = field.id;
+        idlModel.FieldType fieldType = field.type;
+        String valueName = '_' + field.name;
+        String condition = '$valueName != null';
+        String writeCode;
+        if (fieldType.isList ||
+            fieldType.typeName == 'String' ||
+            _idl.classes.containsKey(fieldType.typeName)) {
+          String offsetName = 'offset_' + field.name;
+          condition = '$offsetName != null';
+          writeCode = 'fbBuilder.addOffset($index, $offsetName);';
+        } else if (fieldType.typeName == 'bool') {
+          condition = '$valueName == true';
+          writeCode = 'fbBuilder.addBool($index, true);';
+        } else if (fieldType.typeName == 'double') {
+          condition += ' && $valueName != ${defaultValue(fieldType, true)}';
+          writeCode = 'fbBuilder.addFloat64($index, $valueName);';
+        } else if (fieldType.typeName == 'int') {
+          condition += ' && $valueName != ${defaultValue(fieldType, true)}';
+          writeCode = 'fbBuilder.addUint32($index, $valueName);';
+        } else if (_idl.enums.containsKey(fieldType.typeName)) {
+          condition += ' && $valueName != ${defaultValue(fieldType, true)}';
+          writeCode = 'fbBuilder.addUint8($index, $valueName.index);';
+        }
+        if (writeCode == null) {
+          throw new UnimplementedError('Writing type ${fieldType.typeName}');
+        }
+        out('if ($condition) {');
+        indent(() {
+          out(writeCode);
+        });
+        out('}');
+      }
+      out('return fbBuilder.endTable();');
+    });
+    out('}');
+  }
+
+  void _generateFlushInformative() {
+    out();
+    out('/// Flush [informative] data recursively.');
+    out('void flushInformative() {');
+
+    void writeField(String name, idlModel.FieldType type, bool isInformative) {
+      if (isInformative) {
+        out('$name = null;');
+      } else if (_idl.classes.containsKey(type.typeName)) {
+        if (type.isList) {
+          out('$name?.forEach((b) => b.flushInformative());');
+        } else {
+          out('$name?.flushInformative();');
+        }
+      }
+    }
+
+    indent(() {
+      if (cls.variantField != null) {
+        var firstVariant = true;
+        for (var variant in _computeVariants(cls)) {
+          if (firstVariant) {
+            firstVariant = false;
+          } else {
+            out('else');
+          }
+          out('if (${cls.variantField} == idl.$variant) {');
+          indent(() {
+            for (var field in cls.fields) {
+              var logicalProperties = field.logicalProperties;
+              if (logicalProperties != null) {
+                for (var logicalName in logicalProperties.keys) {
+                  var logicalProperty = logicalProperties[logicalName];
+                  if (logicalProperty.variants.contains(variant)) {
+                    writeField(
+                      logicalName,
+                      field.type,
+                      logicalProperty.isInformative,
+                    );
+                  }
+                }
+              } else {
+                writeField(field.name, field.type, field.isInformative);
+              }
+            }
+          });
+          out('}');
+        }
+      } else {
+        for (idlModel.FieldDeclaration field in cls.fields) {
+          writeField('_${field.name}', field.type, field.isInformative);
+        }
+      }
+    });
+    out('}');
+  }
+
+  void _generateGettersSetters() {
+    for (idlModel.FieldDeclaration field in cls.allFields) {
+      String fieldName = field.name;
+      idlModel.FieldType fieldType = field.type;
+      String typeStr = encodedType(fieldType);
+      String def = defaultValue(fieldType, true);
+      String defSuffix = def == null ? '' : ' ??= $def';
+      out();
+      if (field.isDeprecated) {
+        out('@override');
+        out('Null get $fieldName => ${_BaseGenerator._throwDeprecated};');
+      } else {
+        if (field.logicalProperties != null) {
+          for (var logicalName in field.logicalProperties.keys) {
+            var logicalProperty = field.logicalProperties[logicalName];
+            out('@override');
+            out('$typeStr get $logicalName {');
+            indent(() {
+              out(_variantAssertStatement(cls, logicalProperty));
+              out('return _${field.name}$defSuffix;');
+            });
+            out('}');
+            out();
+          }
+        } else {
+          out('@override');
+          out('$typeStr get $fieldName => _$fieldName$defSuffix;');
+        }
+        out();
+
+        constructorParams.add('$typeStr $fieldName');
+
+        outDoc(field.documentation);
+
+        if (field.logicalProperties != null) {
+          for (var logicalName in field.logicalProperties.keys) {
+            var logicalProperty = field.logicalProperties[logicalName];
+            out('set $logicalName($typeStr value) {');
+            indent(() {
+              out(_variantAssertStatement(cls, logicalProperty));
+              _generateNonNegativeInt(fieldType);
+              out('_variantField_${field.id} = value;');
+            });
+            out('}');
+            out();
+          }
+        } else {
+          out('set $fieldName($typeStr value) {');
+          indent(() {
+            _generateNonNegativeInt(fieldType);
+            out('this._$fieldName = value;');
+          });
+          out('}');
+        }
+      }
+    }
+  }
+
+  void _generateNonNegativeInt(idlModel.FieldType fieldType) {
+    if (fieldType.typeName == 'int') {
+      if (!fieldType.isList) {
+        out('assert(value == null || value >= 0);');
+      } else {
+        out('assert(value == null || value.every((e) => e >= 0));');
+      }
+    }
+  }
+
+  /// Generate a call to the appropriate method of [ApiSignature] for the type
+  /// [typeName], using the data named by [ref].  If [couldBeNull] is `true`,
+  /// generate code to handle the possibility that [ref] is `null` (substituting
+  /// in the appropriate default value).
+  void _generateSignatureCall(String typeName, String ref, bool couldBeNull) {
+    if (_idl.enums.containsKey(typeName)) {
+      if (couldBeNull) {
+        out('signature.addInt($ref == null ? 0 : $ref.index);');
+      } else {
+        out('signature.addInt($ref.index);');
+      }
+    } else if (_idl.classes.containsKey(typeName)) {
+      if (couldBeNull) {
+        out('signature.addBool($ref != null);');
+      }
+      out('$ref?.collectApiSignature(signature);');
+    } else {
+      switch (typeName) {
+        case 'String':
+          if (couldBeNull) {
+            ref += " ?? ''";
+          }
+          out("signature.addString($ref);");
+          break;
+        case 'int':
+          if (couldBeNull) {
+            ref += ' ?? 0';
+          }
+          out('signature.addInt($ref);');
+          break;
+        case 'bool':
+          if (couldBeNull) {
+            ref += ' == true';
+          }
+          out('signature.addBool($ref);');
+          break;
+        case 'double':
+          if (couldBeNull) {
+            ref += ' ?? 0.0';
+          }
+          out('signature.addDouble($ref);');
+          break;
+        default:
+          throw "Don't know how to generate signature call for $typeName";
+      }
+    }
+  }
+
+  void _generateToBuffer() {
+    if (cls.isTopLevel) {
+      out();
+      out('List<int> toBuffer() {');
+      indent(() {
+        out('fb.Builder fbBuilder = new fb.Builder();');
+        String fileId =
+            cls.fileIdentifier == null ? '' : ', ${quoted(cls.fileIdentifier)}';
+        out('return fbBuilder.finish(finish(fbBuilder)$fileId);');
+      });
+      out('}');
+    }
+  }
+}
+
+class _CodeGenerator {
+  /// Buffer in which generated code is accumulated.
+  final StringBuffer _outBuffer = new StringBuffer();
+
   /// Semantic model of the "IDL" input file.
   idlModel.Idl _idl;
 
@@ -133,63 +708,6 @@
     });
   }
 
-  /// Generate a string representing the Dart type which should be used to
-  /// represent [type] when deserialized.
-  String dartType(idlModel.FieldType type) {
-    String baseType = idlPrefix(type.typeName);
-    if (type.isList) {
-      return 'List<$baseType>';
-    } else {
-      return baseType;
-    }
-  }
-
-  /// Generate a Dart expression representing the default value for a field
-  /// having the given [type], or `null` if there is no default value.
-  ///
-  /// If [builder] is `true`, the returned type should be appropriate for use in
-  /// a builder class.
-  String defaultValue(idlModel.FieldType type, bool builder) {
-    if (type.isList) {
-      if (builder) {
-        idlModel.FieldType elementType =
-            new idlModel.FieldType(type.typeName, false);
-        return '<${encodedType(elementType)}>[]';
-      } else {
-        return 'const <${idlPrefix(type.typeName)}>[]';
-      }
-    } else if (_idl.enums.containsKey(type.typeName)) {
-      return '${idlPrefix(type.typeName)}.'
-          '${_idl.enums[type.typeName].values[0].name}';
-    } else if (type.typeName == 'double') {
-      return '0.0';
-    } else if (type.typeName == 'int') {
-      return '0';
-    } else if (type.typeName == 'String') {
-      return "''";
-    } else if (type.typeName == 'bool') {
-      return 'false';
-    } else {
-      return null;
-    }
-  }
-
-  /// Generate a string representing the Dart type which should be used to
-  /// represent [type] while building a serialized data structure.
-  String encodedType(idlModel.FieldType type) {
-    String typeStr;
-    if (_idl.classes.containsKey(type.typeName)) {
-      typeStr = '${type.typeName}Builder';
-    } else {
-      typeStr = idlPrefix(type.typeName);
-    }
-    if (type.isList) {
-      return 'List<$typeStr>';
-    } else {
-      return typeStr;
-    }
-  }
-
   /// Process the AST in [idlParsed] and store the resulting semantic model in
   /// [_idl].  Also perform some error checking.
   void extractIdl(CompilationUnit idlParsed) {
@@ -283,91 +801,10 @@
     }
   }
 
-  /// Generate a string representing the FlatBuffer schema type which should be
-  /// used to represent [type].
-  String fbsType(idlModel.FieldType type) {
-    String typeStr;
-    switch (type.typeName) {
-      case 'bool':
-        typeStr = 'bool';
-        break;
-      case 'double':
-        typeStr = 'double';
-        break;
-      case 'int':
-        typeStr = 'uint';
-        break;
-      case 'String':
-        typeStr = 'string';
-        break;
-      default:
-        typeStr = type.typeName;
-        break;
-    }
-    if (type.isList) {
-      // FlatBuffers don't natively support a packed list of booleans, so we
-      // treat it as a list of unsigned bytes, which is a compatible data
-      // structure.
-      if (typeStr == 'bool') {
-        typeStr = 'ubyte';
-      }
-      return '[$typeStr]';
-    } else {
-      return typeStr;
-    }
-  }
-
   /// Entry point to the code generator when generating the "format.fbs" file.
   void generateFlatBufferSchema() {
     outputHeader();
-    for (idlModel.EnumDeclaration enm in _idl.enums.values) {
-      out();
-      outDoc(enm.documentation);
-      out('enum ${enm.name} : byte {');
-      indent(() {
-        for (int i = 0; i < enm.values.length; i++) {
-          idlModel.EnumValueDeclaration value = enm.values[i];
-          if (i != 0) {
-            out();
-          }
-          String suffix = i < enm.values.length - 1 ? ',' : '';
-          outDoc(value.documentation);
-          out('${value.name}$suffix');
-        }
-      });
-      out('}');
-    }
-    for (idlModel.ClassDeclaration cls in _idl.classes.values) {
-      out();
-      outDoc(cls.documentation);
-      out('table ${cls.name} {');
-      indent(() {
-        for (int i = 0; i < cls.allFields.length; i++) {
-          idlModel.FieldDeclaration field = cls.allFields[i];
-          if (i != 0) {
-            out();
-          }
-          outDoc(field.documentation);
-          List<String> attributes = <String>['id: ${field.id}'];
-          if (field.isDeprecated) {
-            attributes.add('deprecated');
-          }
-          String attrText = attributes.join(', ');
-          out('${field.name}:${fbsType(field.type)} ($attrText);');
-        }
-      });
-      out('}');
-    }
-    out();
-    // Standard flatbuffers only support one root type.  We support multiple
-    // root types.  For now work around this by forcing PackageBundle to be the
-    // root type.  TODO(paulberry): come up with a better solution.
-    idlModel.ClassDeclaration rootType = _idl.classes['PackageBundle'];
-    out('root_type ${rootType.name};');
-    if (rootType.fileIdentifier != null) {
-      out();
-      out('file_identifier ${quoted(rootType.fileIdentifier)};');
-    }
+    _FlatBufferSchemaGenerator(_idl, _outBuffer).generate();
   }
 
   /// Entry point to the code generator when generating the "format.dart" file.
@@ -382,69 +819,33 @@
     out();
     out("import 'idl.dart' as idl;");
     out();
-    for (idlModel.EnumDeclaration enm in _idl.enums.values) {
-      _generateEnumReader(enm);
+    for (idlModel.EnumDeclaration enum_ in _idl.enums.values) {
+      _EnumReaderGenerator(_idl, _outBuffer, enum_).generate();
       out();
     }
     for (idlModel.ClassDeclaration cls in _idl.classes.values) {
       if (!cls.isDeprecated) {
-        _generateBuilder(cls);
+        _BuilderGenerator(_idl, _outBuffer, cls).generate();
         out();
       }
       if (cls.isTopLevel) {
-        _generateReadFunction(cls);
+        _ReaderGenerator(_idl, _outBuffer, cls).generateReaderFunction();
         out();
       }
       if (!cls.isDeprecated) {
-        _generateReader(cls);
+        _ReaderGenerator(_idl, _outBuffer, cls).generateReader();
         out();
-        _generateImpl(cls);
+        _ImplGenerator(_idl, _outBuffer, cls).generate();
         out();
-        _generateMixin(cls);
+        _MixinGenerator(_idl, _outBuffer, cls).generate();
         out();
       }
     }
   }
 
-  /// Add the prefix `idl.` to a type name, unless that type name is the name of
-  /// a built-in type.
-  String idlPrefix(String s) {
-    switch (s) {
-      case 'bool':
-      case 'double':
-      case 'int':
-      case 'String':
-        return s;
-      default:
-        return 'idl.$s';
-    }
-  }
-
-  /// Execute [callback] with two spaces added to [_indentation].
-  void indent(void callback()) {
-    String oldIndentation = _indentation;
-    try {
-      _indentation += '  ';
-      callback();
-    } finally {
-      _indentation = oldIndentation;
-    }
-  }
-
-  /// Add the string [s] to the output as a single line, indenting as
-  /// appropriate.
+  /// Add the string [s] to the output as a single line.
   void out([String s = '']) {
-    if (s == '') {
-      _outBuffer.writeln('');
-    } else {
-      _outBuffer.writeln('$_indentation$s');
-    }
-  }
-
-  void outDoc(String documentation) {
-    if (documentation != null) {
-      documentation.split('\n').forEach(out);
-    }
+    _outBuffer.writeln(s);
   }
 
   void outputHeader() {
@@ -459,11 +860,6 @@
     out();
   }
 
-  /// Enclose [s] in quotes, escaping as necessary.
-  String quoted(String s) {
-    return json.encode(s);
-  }
-
   void _addFieldForGetter(
     idlModel.ClassDeclaration cls,
     MethodDeclaration getter,
@@ -572,21 +968,21 @@
     var fieldType = new idlModel.FieldType(type.name, isList);
 
     String name = getter.name;
-    Map<String, List<String>> variantMap;
+    Map<String, idlModel.LogicalProperty> logicalProperties;
     if (variants != null) {
       var fieldsWithSameId =
           cls.allFields.where((field) => field.id == id).toList();
       if (fieldsWithSameId.isNotEmpty) {
-        var existingField = fieldsWithSameId.first;
-        if (existingField.variantMap == null) {
+        var existingField = fieldsWithSameId.single;
+        if (existingField.logicalProperties == null) {
           throw Exception('$desc: id $id is already used as a non-variant '
               'field: ${existingField.name}');
         }
 
-        var map = existingField.variantMap;
+        var map = existingField.logicalProperties;
         for (var variant in variants) {
           for (var logicalName in map.keys) {
-            if (map[logicalName].contains(variant)) {
+            if (map[logicalName].variants.contains(variant)) {
               throw Exception('$desc: id $id is already used for $logicalName');
             }
           }
@@ -598,11 +994,27 @@
           );
         }
 
-        map.putIfAbsent(getter.name, () => <String>[]).addAll(variants);
+        if (map[getter.name] != null) {
+          throw Exception(
+            '$desc: logical property ${getter.name} is already used',
+          );
+        }
+
+        map[getter.name] = idlModel.LogicalProperty(
+          isDeprecated: isDeprecated,
+          isInformative: isInformative,
+          variants: variants,
+        );
         return;
       } else {
         name = 'variantField_$id';
-        variantMap = <String, List<String>>{getter.name: variants};
+        logicalProperties = <String, idlModel.LogicalProperty>{
+          getter.name: idlModel.LogicalProperty(
+            isDeprecated: isDeprecated,
+            isInformative: isInformative,
+            variants: variants,
+          ),
+        };
       }
     }
 
@@ -614,318 +1026,46 @@
         id: id,
         isDeprecated: isDeprecated,
         isInformative: isInformative,
-        variantMap: variantMap,
+        logicalProperties: logicalProperties,
       ),
     );
   }
 
-  Iterable<String> _computeVariants(idlModel.ClassDeclaration cls) {
-    return cls.fields
-        .map((f) => f.variantMap?.values ?? [])
-        .expand((v) => v)
-        .expand((v) => v)
-        .toSet();
+  /// Return the documentation text of the given [node], or `null` if the [node]
+  /// does not have a comment.  Each line is `\n` separated.
+  String _getNodeDoc(AnnotatedNode node) {
+    Comment comment = node.documentationComment;
+    if (comment != null && comment.isDocumentation) {
+      if (comment.tokens.length == 1 &&
+          comment.tokens.first.lexeme.startsWith('/*')) {
+        Token token = comment.tokens.first;
+        return token.lexeme.split('\n').map((String line) {
+          line = line.trimLeft();
+          if (line.startsWith('*')) line = ' ' + line;
+          return line;
+        }).join('\n');
+      } else if (comment.tokens
+          .every((token) => token.lexeme.startsWith('///'))) {
+        return comment.tokens
+            .map((token) => token.lexeme.trimLeft())
+            .join('\n');
+      }
+    }
+    return null;
   }
+}
 
-  void _generateBuilder(idlModel.ClassDeclaration cls) {
-    String name = cls.name;
-    String builderName = name + 'Builder';
-    String mixinName = '_${name}Mixin';
-    List<String> constructorParams = <String>[];
-    var implementsClause =
-        cls.isDeprecated ? '' : ' implements ${idlPrefix(name)}';
-    out('class $builderName extends Object with $mixinName$implementsClause {');
-    indent(() {
-      // Generate fields.
-      for (idlModel.FieldDeclaration field in cls.fields) {
-        String fieldName = field.name;
-        idlModel.FieldType type = field.type;
-        String typeStr = encodedType(type);
-        out('$typeStr _$fieldName;');
-      }
+class _EnumReaderGenerator extends _BaseGenerator {
+  final idlModel.EnumDeclaration enum_;
 
-      // Generate getters and setters.
-      for (idlModel.FieldDeclaration field in cls.allFields) {
-        String fieldName = field.name;
-        idlModel.FieldType fieldType = field.type;
-        String typeStr = encodedType(fieldType);
-        String def = defaultValue(fieldType, true);
-        String defSuffix = def == null ? '' : ' ??= $def';
-        out();
-        if (field.isDeprecated) {
-          out('@override');
-          out('Null get $fieldName => $_throwDeprecated;');
-        } else {
-          if (field.variantMap != null) {
-            for (var logicalName in field.variantMap.keys) {
-              var variants = field.variantMap[logicalName];
-              out('@override');
-              out('$typeStr get $logicalName {');
-              indent(() {
-                out(_variantAssertStatement(cls, variants));
-                out('return _${field.name}$defSuffix;');
-              });
-              out('}');
-              out();
-            }
-          } else {
-            out('@override');
-            out('$typeStr get $fieldName => _$fieldName$defSuffix;');
-          }
-          out();
+  _EnumReaderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.enum_)
+      : super(idl, outBuffer);
 
-          constructorParams.add('$typeStr $fieldName');
-
-          outDoc(field.documentation);
-
-          if (field.variantMap != null) {
-            for (var logicalName in field.variantMap.keys) {
-              var variants = field.variantMap[logicalName];
-              out('set $logicalName($typeStr value) {');
-              indent(() {
-                out(_variantAssertStatement(cls, variants));
-                _generateNonNegativeInt(fieldType);
-                out('_variantField_${field.id} = value;');
-              });
-              out('}');
-              out();
-            }
-          } else {
-            out('set $fieldName($typeStr value) {');
-            indent(() {
-              _generateNonNegativeInt(fieldType);
-              out('this._$fieldName = value;');
-            });
-            out('}');
-          }
-        }
-      }
-      // Generate constructor.
-      out();
-      if (cls.variantField != null) {
-        for (var variant in _computeVariants(cls)) {
-          var constructorName = variant.split('.')[1];
-          out('$builderName.$constructorName({');
-
-          for (var field in cls.fields) {
-            if (field.variantMap != null) {
-              for (var property in field.variantMap.keys) {
-                if (field.variantMap[property].contains(variant)) {
-                  out('${encodedType(field.type)} $property,');
-                }
-              }
-            }
-          }
-
-          out('}) : ');
-
-          out('_${cls.variantField} = idl.$variant');
-
-          var separator = ',';
-          for (var field in cls.fields) {
-            if (field.variantMap != null) {
-              for (var property in field.variantMap.keys) {
-                if (field.variantMap[property].contains(variant)) {
-                  out('$separator _${field.name} = $property');
-                  separator = ', ';
-                }
-              }
-            }
-          }
-
-          out(';');
-          out();
-        }
-      } else {
-        out('$builderName({${constructorParams.join(', ')}})');
-        List<idlModel.FieldDeclaration> fields = cls.fields.toList();
-        for (int i = 0; i < fields.length; i++) {
-          idlModel.FieldDeclaration field = fields[i];
-          String prefix = i == 0 ? '  : ' : '    ';
-          String suffix = i == fields.length - 1 ? ';' : ',';
-          out('${prefix}_${field.name} = ${field.name}$suffix');
-        }
-      }
-
-      // Generate flushInformative().
-      {
-        out();
-        out('/// Flush [informative] data recursively.');
-        out('void flushInformative() {');
-        indent(() {
-          for (idlModel.FieldDeclaration field in cls.fields) {
-            idlModel.FieldType fieldType = field.type;
-            String valueName = '_' + field.name;
-            if (field.isInformative) {
-              out('$valueName = null;');
-            } else if (_idl.classes.containsKey(fieldType.typeName)) {
-              if (fieldType.isList) {
-                out('$valueName?.forEach((b) => b.flushInformative());');
-              } else {
-                out('$valueName?.flushInformative();');
-              }
-            }
-          }
-        });
-        out('}');
-      }
-      // Generate collectApiSignature().
-      {
-        out();
-        out('/// Accumulate non-[informative] data into [signature].');
-        out('void collectApiSignature(api_sig.ApiSignature signature) {');
-        indent(() {
-          List<idlModel.FieldDeclaration> sortedFields = cls.fields.toList()
-            ..sort((idlModel.FieldDeclaration a, idlModel.FieldDeclaration b) =>
-                a.id.compareTo(b.id));
-          for (idlModel.FieldDeclaration field in sortedFields) {
-            if (field.isInformative) {
-              continue;
-            }
-            String ref = 'this._${field.name}';
-            if (field.type.isList) {
-              out('if ($ref == null) {');
-              indent(() {
-                out('signature.addInt(0);');
-              });
-              out('} else {');
-              indent(() {
-                out('signature.addInt($ref.length);');
-                out('for (var x in $ref) {');
-                indent(() {
-                  _generateSignatureCall(field.type.typeName, 'x', false);
-                });
-                out('}');
-              });
-              out('}');
-            } else {
-              _generateSignatureCall(field.type.typeName, ref, true);
-            }
-          }
-        });
-        out('}');
-      }
-      // Generate finish.
-      if (cls.isTopLevel) {
-        out();
-        out('List<int> toBuffer() {');
-        indent(() {
-          out('fb.Builder fbBuilder = new fb.Builder();');
-          String fileId = cls.fileIdentifier == null
-              ? ''
-              : ', ${quoted(cls.fileIdentifier)}';
-          out('return fbBuilder.finish(finish(fbBuilder)$fileId);');
-        });
-        out('}');
-      }
-      out();
-      out('fb.Offset finish(fb.Builder fbBuilder) {');
-      indent(() {
-        // Write objects and remember Offset(s).
-        for (idlModel.FieldDeclaration field in cls.fields) {
-          idlModel.FieldType fieldType = field.type;
-          String offsetName = 'offset_' + field.name;
-          if (fieldType.isList ||
-              fieldType.typeName == 'String' ||
-              _idl.classes.containsKey(fieldType.typeName)) {
-            out('fb.Offset $offsetName;');
-          }
-        }
-        for (idlModel.FieldDeclaration field in cls.fields) {
-          idlModel.FieldType fieldType = field.type;
-          String valueName = '_' + field.name;
-          String offsetName = 'offset_' + field.name;
-          String condition;
-          String writeCode;
-          if (fieldType.isList) {
-            condition = ' || $valueName.isEmpty';
-            if (_idl.classes.containsKey(fieldType.typeName)) {
-              String itemCode = 'b.finish(fbBuilder)';
-              String listCode = '$valueName.map((b) => $itemCode).toList()';
-              writeCode = '$offsetName = fbBuilder.writeList($listCode);';
-            } else if (_idl.enums.containsKey(fieldType.typeName)) {
-              String itemCode = 'b.index';
-              String listCode = '$valueName.map((b) => $itemCode).toList()';
-              writeCode = '$offsetName = fbBuilder.writeListUint8($listCode);';
-            } else if (fieldType.typeName == 'bool') {
-              writeCode = '$offsetName = fbBuilder.writeListBool($valueName);';
-            } else if (fieldType.typeName == 'int') {
-              writeCode =
-                  '$offsetName = fbBuilder.writeListUint32($valueName);';
-            } else if (fieldType.typeName == 'double') {
-              writeCode =
-                  '$offsetName = fbBuilder.writeListFloat64($valueName);';
-            } else {
-              assert(fieldType.typeName == 'String');
-              String itemCode = 'fbBuilder.writeString(b)';
-              String listCode = '$valueName.map((b) => $itemCode).toList()';
-              writeCode = '$offsetName = fbBuilder.writeList($listCode);';
-            }
-          } else if (fieldType.typeName == 'String') {
-            writeCode = '$offsetName = fbBuilder.writeString($valueName);';
-          } else if (_idl.classes.containsKey(fieldType.typeName)) {
-            writeCode = '$offsetName = $valueName.finish(fbBuilder);';
-          }
-          if (writeCode != null) {
-            if (condition == null) {
-              out('if ($valueName != null) {');
-            } else {
-              out('if (!($valueName == null$condition)) {');
-            }
-            indent(() {
-              out(writeCode);
-            });
-            out('}');
-          }
-        }
-        // Write the table.
-        out('fbBuilder.startTable();');
-        for (idlModel.FieldDeclaration field in cls.fields) {
-          int index = field.id;
-          idlModel.FieldType fieldType = field.type;
-          String valueName = '_' + field.name;
-          String condition = '$valueName != null';
-          String writeCode;
-          if (fieldType.isList ||
-              fieldType.typeName == 'String' ||
-              _idl.classes.containsKey(fieldType.typeName)) {
-            String offsetName = 'offset_' + field.name;
-            condition = '$offsetName != null';
-            writeCode = 'fbBuilder.addOffset($index, $offsetName);';
-          } else if (fieldType.typeName == 'bool') {
-            condition = '$valueName == true';
-            writeCode = 'fbBuilder.addBool($index, true);';
-          } else if (fieldType.typeName == 'double') {
-            condition += ' && $valueName != ${defaultValue(fieldType, true)}';
-            writeCode = 'fbBuilder.addFloat64($index, $valueName);';
-          } else if (fieldType.typeName == 'int') {
-            condition += ' && $valueName != ${defaultValue(fieldType, true)}';
-            writeCode = 'fbBuilder.addUint32($index, $valueName);';
-          } else if (_idl.enums.containsKey(fieldType.typeName)) {
-            condition += ' && $valueName != ${defaultValue(fieldType, true)}';
-            writeCode = 'fbBuilder.addUint8($index, $valueName.index);';
-          }
-          if (writeCode == null) {
-            throw new UnimplementedError('Writing type ${fieldType.typeName}');
-          }
-          out('if ($condition) {');
-          indent(() {
-            out(writeCode);
-          });
-          out('}');
-        }
-        out('return fbBuilder.endTable();');
-      });
-      out('}');
-    });
-    out('}');
-  }
-
-  void _generateEnumReader(idlModel.EnumDeclaration enm) {
-    String name = enm.name;
+  void generate() {
+    String name = enum_.name;
     String readerName = '_${name}Reader';
     String count = '${idlPrefix(name)}.values.length';
-    String def = '${idlPrefix(name)}.${enm.values[0].name}';
+    String def = '${idlPrefix(name)}.${enum_.values[0].name}';
     out('class $readerName extends fb.Reader<${idlPrefix(name)}> {');
     indent(() {
       out('const $readerName() : super();');
@@ -943,8 +1083,105 @@
     });
     out('}');
   }
+}
 
-  void _generateImpl(idlModel.ClassDeclaration cls) {
+class _FlatBufferSchemaGenerator extends _BaseGenerator {
+  _FlatBufferSchemaGenerator(idlModel.Idl idl, StringBuffer outBuffer)
+      : super(idl, outBuffer);
+
+  void generate() {
+    for (idlModel.EnumDeclaration enm in _idl.enums.values) {
+      out();
+      outDoc(enm.documentation);
+      out('enum ${enm.name} : byte {');
+      indent(() {
+        for (int i = 0; i < enm.values.length; i++) {
+          idlModel.EnumValueDeclaration value = enm.values[i];
+          if (i != 0) {
+            out();
+          }
+          String suffix = i < enm.values.length - 1 ? ',' : '';
+          outDoc(value.documentation);
+          out('${value.name}$suffix');
+        }
+      });
+      out('}');
+    }
+    for (idlModel.ClassDeclaration cls in _idl.classes.values) {
+      out();
+      outDoc(cls.documentation);
+      out('table ${cls.name} {');
+      indent(() {
+        for (int i = 0; i < cls.allFields.length; i++) {
+          idlModel.FieldDeclaration field = cls.allFields[i];
+          if (i != 0) {
+            out();
+          }
+          outDoc(field.documentation);
+          List<String> attributes = <String>['id: ${field.id}'];
+          if (field.isDeprecated) {
+            attributes.add('deprecated');
+          }
+          String attrText = attributes.join(', ');
+          out('${field.name}:${_fbsType(field.type)} ($attrText);');
+        }
+      });
+      out('}');
+    }
+    out();
+    // Standard flatbuffers only support one root type.  We support multiple
+    // root types.  For now work around this by forcing PackageBundle to be the
+    // root type.  TODO(paulberry): come up with a better solution.
+    idlModel.ClassDeclaration rootType = _idl.classes['PackageBundle'];
+    out('root_type ${rootType.name};');
+    if (rootType.fileIdentifier != null) {
+      out();
+      out('file_identifier ${quoted(rootType.fileIdentifier)};');
+    }
+  }
+
+  /// Generate a string representing the FlatBuffer schema type which should be
+  /// used to represent [type].
+  String _fbsType(idlModel.FieldType type) {
+    String typeStr;
+    switch (type.typeName) {
+      case 'bool':
+        typeStr = 'bool';
+        break;
+      case 'double':
+        typeStr = 'double';
+        break;
+      case 'int':
+        typeStr = 'uint';
+        break;
+      case 'String':
+        typeStr = 'string';
+        break;
+      default:
+        typeStr = type.typeName;
+        break;
+    }
+    if (type.isList) {
+      // FlatBuffers don't natively support a packed list of booleans, so we
+      // treat it as a list of unsigned bytes, which is a compatible data
+      // structure.
+      if (typeStr == 'bool') {
+        typeStr = 'ubyte';
+      }
+      return '[$typeStr]';
+    } else {
+      return typeStr;
+    }
+  }
+}
+
+class _ImplGenerator extends _BaseGenerator {
+  final idlModel.ClassDeclaration cls;
+
+  _ImplGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+      : super(idl, outBuffer);
+
+  void generate() {
     String name = cls.name;
     String implName = '_${name}Impl';
     String mixinName = '_${name}Mixin';
@@ -958,7 +1195,7 @@
       out();
       // Write cache fields.
       for (idlModel.FieldDeclaration field in cls.fields) {
-        String returnType = dartType(field.type);
+        String returnType = _dartType(field.type);
         String fieldName = field.name;
         out('$returnType _$fieldName;');
       }
@@ -1005,18 +1242,18 @@
         assert(readCode != null);
         // Write the getter implementation.
         out();
-        String returnType = dartType(type);
+        String returnType = _dartType(type);
         if (field.isDeprecated) {
           out('@override');
-          out('Null get $fieldName => $_throwDeprecated;');
+          out('Null get $fieldName => ${_BaseGenerator._throwDeprecated};');
         } else {
-          if (field.variantMap != null) {
-            for (var logicalName in field.variantMap.keys) {
-              var variants = field.variantMap[logicalName];
+          if (field.logicalProperties != null) {
+            for (var logicalName in field.logicalProperties.keys) {
+              var logicalProperty = field.logicalProperties[logicalName];
               out('@override');
               out('$returnType get $logicalName {');
               indent(() {
-                out(_variantAssertStatement(cls, variants));
+                out(_variantAssertStatement(cls, logicalProperty));
                 String readExpr =
                     '$readCode.vTableGet(_bc, _bcOffset, $index, $def)';
                 out('_$fieldName ??= $readExpr;');
@@ -1042,7 +1279,25 @@
     out('}');
   }
 
-  void _generateMixin(idlModel.ClassDeclaration cls) {
+  /// Generate a string representing the Dart type which should be used to
+  /// represent [type] when deserialized.
+  String _dartType(idlModel.FieldType type) {
+    String baseType = idlPrefix(type.typeName);
+    if (type.isList) {
+      return 'List<$baseType>';
+    } else {
+      return baseType;
+    }
+  }
+}
+
+class _MixinGenerator extends _BaseGenerator {
+  final idlModel.ClassDeclaration cls;
+
+  _MixinGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+      : super(idl, outBuffer);
+
+  void generate() {
     String name = cls.name;
     String mixinName = '_${name}Mixin';
     out('abstract class $mixinName implements ${idlPrefix(name)} {');
@@ -1088,7 +1343,7 @@
         if (cls.variantField != null) {
           indent(() {
             for (idlModel.FieldDeclaration field in cls.fields) {
-              if (field.variantMap == null) {
+              if (field.logicalProperties == null) {
                 var condition = jsonCondition(field.type, field.name);
                 var storeField = jsonStore(field.type, field.name);
                 out('if ($condition) $storeField;');
@@ -1098,9 +1353,11 @@
               out('if (${cls.variantField} == idl.$variant) {');
               indent(() {
                 for (idlModel.FieldDeclaration field in cls.fields) {
-                  if (field.variantMap != null) {
-                    for (var logicalName in field.variantMap.keys) {
-                      if (field.variantMap[logicalName].contains(variant)) {
+                  var logicalProperties = field.logicalProperties;
+                  if (logicalProperties != null) {
+                    for (var logicalName in logicalProperties.keys) {
+                      var logicalProperty = logicalProperties[logicalName];
+                      if (logicalProperty.variants.contains(variant)) {
                         var condition = jsonCondition(field.type, logicalName);
                         var storeField = jsonStore(field.type, logicalName);
                         out('if ($condition) $storeField;');
@@ -1136,9 +1393,10 @@
           indent(() {
             out('return {');
             for (idlModel.FieldDeclaration field in cls.fields) {
-              if (field.variantMap != null) {
-                for (var logicalName in field.variantMap.keys) {
-                  if (field.variantMap[logicalName].contains(variant)) {
+              if (field.logicalProperties != null) {
+                for (var logicalName in field.logicalProperties.keys) {
+                  var logicalProperty = field.logicalProperties[logicalName];
+                  if (logicalProperty.variants.contains(variant)) {
                     out('${quoted(logicalName)}: $logicalName,');
                   }
                 }
@@ -1170,18 +1428,15 @@
     });
     out('}');
   }
+}
 
-  void _generateNonNegativeInt(idlModel.FieldType fieldType) {
-    if (fieldType.typeName == 'int') {
-      if (!fieldType.isList) {
-        out('assert(value == null || value >= 0);');
-      } else {
-        out('assert(value == null || value.every((e) => e >= 0));');
-      }
-    }
-  }
+class _ReaderGenerator extends _BaseGenerator {
+  final idlModel.ClassDeclaration cls;
 
-  void _generateReader(idlModel.ClassDeclaration cls) {
+  _ReaderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+      : super(idl, outBuffer);
+
+  void generateReader() {
     String name = cls.name;
     String readerName = '_${name}Reader';
     String implName = '_${name}Impl';
@@ -1195,7 +1450,7 @@
     out('}');
   }
 
-  void _generateReadFunction(idlModel.ClassDeclaration cls) {
+  void generateReaderFunction() {
     String name = cls.name;
     out('${idlPrefix(name)} read$name(List<int> buffer) {');
     indent(() {
@@ -1204,85 +1459,4 @@
     });
     out('}');
   }
-
-  /// Generate a call to the appropriate method of [ApiSignature] for the type
-  /// [typeName], using the data named by [ref].  If [couldBeNull] is `true`,
-  /// generate code to handle the possibility that [ref] is `null` (substituting
-  /// in the appropriate default value).
-  void _generateSignatureCall(String typeName, String ref, bool couldBeNull) {
-    if (_idl.enums.containsKey(typeName)) {
-      if (couldBeNull) {
-        out('signature.addInt($ref == null ? 0 : $ref.index);');
-      } else {
-        out('signature.addInt($ref.index);');
-      }
-    } else if (_idl.classes.containsKey(typeName)) {
-      if (couldBeNull) {
-        out('signature.addBool($ref != null);');
-      }
-      out('$ref?.collectApiSignature(signature);');
-    } else {
-      switch (typeName) {
-        case 'String':
-          if (couldBeNull) {
-            ref += " ?? ''";
-          }
-          out("signature.addString($ref);");
-          break;
-        case 'int':
-          if (couldBeNull) {
-            ref += ' ?? 0';
-          }
-          out('signature.addInt($ref);');
-          break;
-        case 'bool':
-          if (couldBeNull) {
-            ref += ' == true';
-          }
-          out('signature.addBool($ref);');
-          break;
-        case 'double':
-          if (couldBeNull) {
-            ref += ' ?? 0.0';
-          }
-          out('signature.addDouble($ref);');
-          break;
-        default:
-          throw "Don't know how to generate signature call for $typeName";
-      }
-    }
-  }
-
-  /// Return the documentation text of the given [node], or `null` if the [node]
-  /// does not have a comment.  Each line is `\n` separated.
-  String _getNodeDoc(AnnotatedNode node) {
-    Comment comment = node.documentationComment;
-    if (comment != null && comment.isDocumentation) {
-      if (comment.tokens.length == 1 &&
-          comment.tokens.first.lexeme.startsWith('/*')) {
-        Token token = comment.tokens.first;
-        return token.lexeme.split('\n').map((String line) {
-          line = line.trimLeft();
-          if (line.startsWith('*')) line = ' ' + line;
-          return line;
-        }).join('\n');
-      } else if (comment.tokens
-          .every((token) => token.lexeme.startsWith('///'))) {
-        return comment.tokens
-            .map((token) => token.lexeme.trimLeft())
-            .join('\n');
-      }
-    }
-    return null;
-  }
-
-  String _variantAssertStatement(
-    idlModel.ClassDeclaration class_,
-    List<String> variants,
-  ) {
-    var assertCondition = variants
-        ?.map((key) => '${class_.variantField} == idl.$key')
-        ?.join(' || ');
-    return 'assert($assertCondition);';
-  }
 }
diff --git a/pkg/analyzer/tool/summary/idl_model.dart b/pkg/analyzer/tool/summary/idl_model.dart
index 597e669..5354155 100644
--- a/pkg/analyzer/tool/summary/idl_model.dart
+++ b/pkg/analyzer/tool/summary/idl_model.dart
@@ -115,9 +115,9 @@
   final bool isInformative;
 
   /**
-   * Maps logical property names to variants in which this field is available.
+   * Maps logical property names to logical property.
    */
-  final Map<String, List<String>> variantMap;
+  final Map<String, LogicalProperty> logicalProperties;
 
   FieldDeclaration({
     @required String documentation,
@@ -126,7 +126,7 @@
     @required this.id,
     @required this.isDeprecated,
     @required this.isInformative,
-    @required this.variantMap,
+    @required this.logicalProperties,
   }) : super(documentation, name);
 }
 
@@ -179,3 +179,29 @@
    */
   final Map<String, EnumDeclaration> enums = <String, EnumDeclaration>{};
 }
+
+/**
+ * Information about a logical property mapped to a single data fields.
+ */
+class LogicalProperty {
+  /**
+   * Indicates whether the property is deprecated.
+   */
+  final bool isDeprecated;
+
+  /**
+   * Indicates whether the property is informative.
+   */
+  final bool isInformative;
+
+  /**
+   * Names of variants in which this property is available.
+   */
+  final List<String> variants;
+
+  LogicalProperty({
+    @required this.isDeprecated,
+    @required this.isInformative,
+    @required this.variants,
+  });
+}
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
index cf52e31..b218815 100644
--- a/pkg/analyzer/tool/summary/mini_ast.dart
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -454,8 +454,14 @@
   }
 
   @override
-  void endTopLevelFields(Token staticToken, Token covariantToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
     // We ignore top level variable declarations; they are present just to make
     // the IDL analyze without warnings.
     debugEvent("TopLevelFields");
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index b2e0dfb..39e0a65 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -8,6 +8,7 @@
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
@@ -15,7 +16,10 @@
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -28,6 +32,10 @@
 import 'package:analyzer/src/summary/summarize_ast.dart';
 import 'package:analyzer/src/summary/summarize_elements.dart';
 import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
+import 'package:analyzer/src/summary2/link.dart' as summary2;
+import 'package:analyzer/src/summary2/linked_bundle_context.dart' as summary2;
+import 'package:analyzer/src/summary2/linked_element_factory.dart' as summary2;
+import 'package:analyzer/src/summary2/reference.dart' as summary2;
 import 'package:analyzer_cli/src/context_cache.dart';
 import 'package:analyzer_cli/src/driver.dart';
 import 'package:analyzer_cli/src/error_formatter.dart';
@@ -79,8 +87,6 @@
    */
   Future<void> analyze(
       CommandLineOptions options, Map<String, WorkerInput> inputs) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var packageBundleProvider =
         new WorkerPackageBundleProvider(packageBundleCache, inputs);
     var buildMode = new BuildMode(
@@ -99,11 +105,7 @@
    */
   @override
   Future<WorkResponse> performRequest(WorkRequest request) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     return logger.runAsync('Perform request', () async {
-      // TODO(brianwilkerson) Determine whether this await is necessary.
-      await null;
       errorBuffer.clear();
       outBuffer.clear();
       try {
@@ -148,8 +150,6 @@
    */
   @override
   Future<void> run() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     errorSink = errorBuffer;
     outSink = outBuffer;
     exitHandler = (int exitCode) {
@@ -183,16 +183,23 @@
   final ContextCache contextCache;
 
   SummaryDataStore summaryDataStore;
-  AnalysisOptions analysisOptions;
+  AnalysisOptionsImpl analysisOptions;
   Map<Uri, File> uriToFileMap;
   final List<Source> explicitSources = <Source>[];
   final List<PackageBundle> unlinkedBundles = <PackageBundle>[];
 
+  SourceFactory sourceFactory;
+  DeclaredVariables declaredVariables;
   AnalysisDriver analysisDriver;
 
   PackageBundleAssembler assembler;
   final Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
 
+  final bool buildSummary2 = true;
+  final bool consumeSummary2 = false;
+  final Map<String, ParsedUnitResult> inputParsedUnitResults = {};
+  summary2.LinkedElementFactory elementFactory;
+
   // May be null.
   final DependencyTracker dependencyTracker;
 
@@ -213,11 +220,7 @@
    * Perform package analysis according to the given [options].
    */
   Future<ErrorSeverity> analyze() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     return await logger.runAsync('Analyze', () async {
-      // TODO(brianwilkerson) Determine whether this await is necessary.
-      await null;
       // Write initial progress message.
       if (!options.machineFormat) {
         outSink.writeln("Analyzing ${options.sourceFiles.join(', ')}...");
@@ -266,12 +269,8 @@
       assembler = new PackageBundleAssembler();
       if (_shouldOutputSummary) {
         await logger.runAsync('Build and write output summary', () async {
-          // TODO(brianwilkerson) Determine whether this await is necessary.
-          await null;
           // Prepare all unlinked units.
           await logger.runAsync('Prepare unlinked units', () async {
-            // TODO(brianwilkerson) Determine whether this await is necessary.
-            await null;
             for (var src in explicitSources) {
               await _prepareUnlinkedUnit('${src.uri}');
             }
@@ -291,6 +290,10 @@
             _computeLinkedLibraries(unlinkedUris);
           }
 
+          if (buildSummary2) {
+            _computeLinkedLibraries2();
+          }
+
           // Write the whole package bundle.
           PackageBundleBuilder bundle = assembler.assemble();
           if (options.buildSummaryOutput != null) {
@@ -336,6 +339,9 @@
    * add them to  the [assembler].
    */
   void _computeLinkedLibraries(Set<String> libraryUris) {
+    // Ensure that summary1 linking is done with summary1 rules.
+    AnalysisDriver.useSummary2 = false;
+
     logger.run('Link output summary', () {
       void trackDependency(String absoluteUri) {
         if (dependencyTracker != null) {
@@ -367,9 +373,60 @@
     });
   }
 
+  /**
+   * Use [elementFactory] filled with input summaries, and link prepared
+   * [inputParsedUnitResults] to produce linked libraries in [assembler].
+   */
+  void _computeLinkedLibraries2() {
+    AnalysisDriver.useSummary2 = consumeSummary2;
+    logger.run('Link output summary2', () {
+      var inputLibraries = <summary2.LinkInputLibrary>[];
+
+      for (var librarySource in explicitSources) {
+        var path = librarySource.fullName;
+
+        var parseResult = inputParsedUnitResults[path];
+        if (parseResult == null) {
+          throw ArgumentError('No parsed unit for $path');
+        }
+
+        var unit = parseResult.unit;
+        var isPart = unit.directives.any((d) => d is PartOfDirective);
+        if (isPart) {
+          continue;
+        }
+
+        var inputUnits = <summary2.LinkInputUnit>[];
+        inputUnits.add(
+          summary2.LinkInputUnit(librarySource, false, unit),
+        );
+
+        for (var directive in unit.directives) {
+          if (directive is PartDirective) {
+            var partUri = directive.uri.stringValue;
+            var partSource = sourceFactory.resolveUri(librarySource, partUri);
+            var partPath = partSource.fullName;
+            var partParseResult = inputParsedUnitResults[partPath];
+            if (partParseResult == null) {
+              throw ArgumentError('No parsed unit for part $partPath in $path');
+            }
+            inputUnits.add(
+              summary2.LinkInputUnit(partSource, false, partParseResult.unit),
+            );
+          }
+        }
+
+        inputLibraries.add(
+          summary2.LinkInputLibrary(librarySource, inputUnits),
+        );
+      }
+
+      var linkResult = summary2.link(elementFactory, inputLibraries);
+      assembler.setBundle2(linkResult.bundle);
+    });
+  }
+
   Future<ErrorSeverity> _computeMaxSeverity() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     ErrorSeverity maxSeverity = ErrorSeverity.NONE;
     if (!options.buildSuppressExitCode) {
       for (Source source in explicitSources) {
@@ -447,7 +504,7 @@
       summaryDataStore.addBundle(null, sdkBundle);
     });
 
-    var sourceFactory = new SourceFactory(<UriResolver>[
+    sourceFactory = new SourceFactory(<UriResolver>[
       new DartUriResolver(sdk),
       new TrackingInSummaryUriResolver(
           new InSummaryUriResolver(resourceProvider, summaryDataStore),
@@ -458,6 +515,9 @@
     analysisOptions =
         createAnalysisOptionsForCommandLineOptions(options, rootPath);
 
+    // Ensure that FileState prepare summary2 information if necessary.
+    AnalysisDriver.useSummary2 = consumeSummary2;
+
     AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(logger);
     analysisDriver = new AnalysisDriver(
         scheduler,
@@ -467,14 +527,38 @@
         new FileContentOverlay(),
         null,
         sourceFactory,
-        analysisOptions as AnalysisOptionsImpl,
+        analysisOptions,
         externalSummaries: summaryDataStore);
-    analysisDriver.declaredVariables =
-        new DeclaredVariables.fromMap(options.definedVariables);
+
+    declaredVariables = new DeclaredVariables.fromMap(options.definedVariables);
+    analysisDriver.declaredVariables = declaredVariables;
+
+    if (buildSummary2) {
+      _createLinkedElementFactory();
+    }
 
     scheduler.start();
   }
 
+  void _createLinkedElementFactory() {
+    var analysisContext = RestrictedAnalysisContext(
+      SynchronousSession(analysisOptions, declaredVariables),
+      sourceFactory,
+    );
+
+    elementFactory = summary2.LinkedElementFactory(
+      analysisContext,
+      null,
+      summary2.Reference.root(),
+    );
+
+    for (var bundle in summaryDataStore.bundles) {
+      elementFactory.addBundle(
+        summary2.LinkedBundleContext(elementFactory, bundle.bundle2),
+      );
+    }
+  }
+
   /**
    * Convert [sourceEntities] (a list of file specifications of the form
    * "$uri|$path") to a map from URI to path.  If an error occurs, report the
@@ -507,21 +591,20 @@
    * Otherwise compute it and store into the [uriToUnit] and [assembler].
    */
   Future<void> _prepareUnlinkedUnit(String absoluteUri) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     // Maybe an input package contains the source.
     if (summaryDataStore.unlinkedMap[absoluteUri] != null) {
       return;
     }
     // Parse the source and serialize its AST.
     Uri uri = Uri.parse(absoluteUri);
-    Source source = analysisDriver.sourceFactory.forUri2(uri);
+    Source source = sourceFactory.forUri2(uri);
     if (!source.exists()) {
       // TODO(paulberry): we should report a warning/error because DDC
       // compilations are unlikely to work.
       return;
     }
     var result = await analysisDriver.parseFile(source.fullName);
+    inputParsedUnitResults[result.path] = result;
     UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(result.unit);
     uriToUnit[absoluteUri] = unlinkedUnit;
     assembler.addUnlinkedUnit(source, unlinkedUnit);
@@ -532,11 +615,9 @@
    * is sent to a new file at that path.
    */
   Future<void> _printErrors({String outputPath}) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
+    AnalysisDriver.useSummary2 = consumeSummary2;
+
     await logger.runAsync('Compute and print analysis errors', () async {
-      // TODO(brianwilkerson) Determine whether this await is necessary.
-      await null;
       StringBuffer buffer = new StringBuffer();
       var severityProcessor = (AnalysisError error) =>
           determineProcessedSeverity(error, options, analysisOptions);
@@ -650,6 +731,29 @@
 }
 
 /**
+ * Wrapper for [InSummaryUriResolver] that tracks accesses to summaries.
+ */
+class TrackingInSummaryUriResolver extends UriResolver {
+  // May be null.
+  final DependencyTracker dependencyTracker;
+  final InSummaryUriResolver inSummaryUriResolver;
+
+  TrackingInSummaryUriResolver(
+      this.inSummaryUriResolver, this.dependencyTracker);
+
+  @override
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+    var source = inSummaryUriResolver.resolveAbsolute(uri, actualUri);
+    if (dependencyTracker != null &&
+        source != null &&
+        source is InSummarySource) {
+      dependencyTracker.record(source.summaryPath);
+    }
+    return source;
+  }
+}
+
+/**
  * Worker input.
  *
  * Bazel does not specify the format of the digest, so we cannot assume that
@@ -744,26 +848,3 @@
     return cache.get(inputs, path);
   }
 }
-
-/**
- * Wrapper for [InSummaryUriResolver] that tracks accesses to summaries.
- */
-class TrackingInSummaryUriResolver extends UriResolver {
-  // May be null.
-  final DependencyTracker dependencyTracker;
-  final InSummaryUriResolver inSummaryUriResolver;
-
-  TrackingInSummaryUriResolver(
-      this.inSummaryUriResolver, this.dependencyTracker);
-
-  @override
-  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
-    var source = inSummaryUriResolver.resolveAbsolute(uri, actualUri);
-    if (dependencyTracker != null &&
-        source != null &&
-        source is InSummarySource) {
-      dependencyTracker.record(source.summaryPath);
-    }
-    return source;
-  }
-}
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index 054521d..8903b6a 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -789,24 +789,6 @@
     });
   }
 
-  test_pubspecYaml() async {
-    await withTempDirAsync((tempDir) async {
-      String filePath = path.join(tempDir, AnalysisEngine.PUBSPEC_YAML_FILE);
-      new File(filePath).writeAsStringSync('''
-name: foo
-flutter:
-  assets:
-    doesNotExist.gif
-''');
-      await drive(filePath);
-      expect(
-          bulletToDash(outSink),
-          contains(
-              "warning - The value of the 'asset' field is expected to be a list of relative file paths"));
-      expect(exitCode, 0);
-    });
-  }
-
   test_manifestFileChecks() async {
     await withTempDirAsync((tempDir) async {
       String filePath =
@@ -821,12 +803,33 @@
       new File(manifestPath).writeAsStringSync('''
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
     <uses-feature android:name="android.software.home_screen" />
 </manifest>
 ''');
       await drive(manifestPath, options: filePath);
-      expect(bulletToDash(outSink),
-          contains("warning - This feature is not supported on Chrome OS"));
+      expect(
+          bulletToDash(outSink),
+          contains(
+              "warning - The feature android.software.home_screen is not supported on Chrome OS"));
+      expect(exitCode, 0);
+    });
+  }
+
+  test_pubspecYaml() async {
+    await withTempDirAsync((tempDir) async {
+      String filePath = path.join(tempDir, AnalysisEngine.PUBSPEC_YAML_FILE);
+      new File(filePath).writeAsStringSync('''
+name: foo
+flutter:
+  assets:
+    doesNotExist.gif
+''');
+      await drive(filePath);
+      expect(
+          bulletToDash(outSink),
+          contains(
+              "warning - The value of the 'asset' field is expected to be a list of relative file paths"));
       expect(exitCode, 0);
     });
   }
@@ -965,5 +968,8 @@
   TestSource();
 
   @override
+  String get fullName => '/package/lib/test.dart';
+
+  @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/analyzer_cli/test/mocks.dart b/pkg/analyzer_cli/test/mocks.dart
index 3d3ad59..b5e5627 100644
--- a/pkg/analyzer_cli/test/mocks.dart
+++ b/pkg/analyzer_cli/test/mocks.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -30,7 +31,19 @@
   MockAnalysisError(this.source, this.errorCode, this.offset, this.message);
 
   @override
+  List<DiagnosticMessage> get contextMessages => null;
+
+  @override
   String get correction => null;
+
+  @override
+  String get correctionMessage => null;
+
+  @override
+  DiagnosticMessage get problemMessage => null;
+
+  @override
+  Severity get severity => null;
 }
 
 class MockAnalysisErrorInfo implements AnalysisErrorInfo {
@@ -74,6 +87,9 @@
   }
 
   @override
+  bool get hasPublishedDocs => false;
+
+  @override
   bool get isUnresolvedIdentifier => false;
 
   @override
diff --git a/pkg/analyzer_cli/tool/perf.dart b/pkg/analyzer_cli/tool/perf.dart
index 7d9bd7e..391c811 100644
--- a/pkg/analyzer_cli/tool/perf.dart
+++ b/pkg/analyzer_cli/tool/perf.dart
@@ -6,6 +6,7 @@
 import 'dart:async';
 import 'dart:io' show exit;
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
@@ -77,7 +78,9 @@
 /// Uses the diet-parser to parse only directives in [source].
 CompilationUnit parseDirectives(Source source) {
   var token = tokenize(source);
-  var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
+  var featureSet = FeatureSet.fromEnableFlags([]);
+  var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER,
+      featureSet: featureSet);
   return parser.parseDirectives(token);
 }
 
@@ -107,7 +110,9 @@
 /// Parse the full body of [source] and return it's compilation unit.
 CompilationUnit parseFull(Source source) {
   var token = tokenize(source);
-  var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
+  var featureSet = FeatureSet.fromEnableFlags([]);
+  var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER,
+      featureSet: featureSet);
   return parser.parseCompilationUnit(token);
 }
 
@@ -192,10 +197,13 @@
   scanTimer.start();
   var contents = source.contents.data;
   scanTotalChars += contents.length;
+  // TODO(paulberry): figure out the appropriate featureSet to use here
+  var featureSet = FeatureSet.fromEnableFlags([]);
   // TODO(sigmund): is there a way to scan from a random-access-file without
   // first converting to String?
   var scanner = new Scanner(source, new CharSequenceReader(contents),
       AnalysisErrorListener.NULL_LISTENER)
+    ..configureFeatures(featureSet)
     ..preserveComments = false;
   var token = scanner.tokenize();
   scanTimer.stop();
diff --git a/pkg/analyzer_plugin/.gitignore b/pkg/analyzer_plugin/.gitignore
new file mode 100644
index 0000000..79f51c3
--- /dev/null
+++ b/pkg/analyzer_plugin/.gitignore
@@ -0,0 +1,3 @@
+.dart_tool
+.packages
+pubspec.lock
diff --git a/pkg/analyzer_plugin/CHANGELOG.md b/pkg/analyzer_plugin/CHANGELOG.md
index 923ee0c..32d0093 100644
--- a/pkg/analyzer_plugin/CHANGELOG.md
+++ b/pkg/analyzer_plugin/CHANGELOG.md
@@ -1,4 +1,6 @@
-# Changelog
+## 0.0.1-alpha.8
+
+- Support the latest `pkg:analyzer`.
 
 ## 0.0.1-alpha.7
 
@@ -8,7 +10,7 @@
 
 ## 0.0.1-alpha.4
 
-- Upgrade the Dart SDK version contraint
+- Upgrade the Dart SDK version constraint
 
 ## 0.0.1
 
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index 53599dd..910ab7a 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -905,6 +905,12 @@
         <p>
           The URL of a page containing documentation associated with this error.
         </p>
+      </dd><dt class="field"><b>contextMessages: List&lt;<a href="#type_DiagnosticMessage">DiagnosticMessage</a>&gt;<span style="color:#999999"> (optional)</span></b></dt><dd>
+        
+        <p>
+          Additional messages associated with this diagnostic that provide
+          context to help the user understand the diagnostic.
+        </p>
       </dd><dt class="field"><b>hasFix: bool<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
@@ -1191,6 +1197,27 @@
           The absolute path of the analysis options file that should be used to
           control the analysis of the files in the context.
         </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_DiagnosticMessage">DiagnosticMessage: object</a></dt><dd>
+    <p>
+      A message associated with a diagnostic.
+    </p>
+    <p>
+      For example, if the diagnostic is reporting that a variable has been
+      referenced before it was declared, it might have a diagnostic message that
+      indicates where the variable is declared.
+    </p>
+    
+  <dl><dt class="field"><b>message: String</b></dt><dd>
+        
+        <p>
+          The message to be displayed to the user.
+        </p>
+      </dd><dt class="field"><b>location: <a href="#type_Location">Location</a></b></dt><dd>
+        
+        <p>
+          The location associated with or referenced by the message. Clients
+          should provide the ability to navigate to the location.
+        </p>
       </dd></dl></dd><dt class="typeDefinition"><a name="type_Element">Element: object</a></dt><dd>
     <p>
       Information about an element (something that can be declared in code).
@@ -2404,7 +2431,7 @@
         </p>
       </dd></dl></dd></dl>
 <h2 class="domain"><a name="index">Index</a></h2>
-<h3>Domains</h3><h4>plugin (<a href="#domain_plugin">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_plugin.versionCheck">versionCheck</a></li><li><a href="#request_plugin.shutdown">shutdown</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_plugin.error">error</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.handleWatchEvents">handleWatchEvents</a></li><li><a href="#request_analysis.setContextRoots">setContextRoots</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li></ul></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getFixes">getFixes</a></li></ul></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextRoot">ContextRoot</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PrioritizedSourceChange">PrioritizedSourceChange</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_WatchEvent">WatchEvent</a></li><li><a href="#type_WatchEventType">WatchEventType</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
+<h3>Domains</h3><h4>plugin (<a href="#domain_plugin">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_plugin.versionCheck">versionCheck</a></li><li><a href="#request_plugin.shutdown">shutdown</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_plugin.error">error</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.handleWatchEvents">handleWatchEvents</a></li><li><a href="#request_analysis.setContextRoots">setContextRoots</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li></ul></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getFixes">getFixes</a></li></ul></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextRoot">ContextRoot</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PrioritizedSourceChange">PrioritizedSourceChange</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_WatchEvent">WatchEvent</a></li><li><a href="#type_WatchEventType">WatchEventType</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
 
 
 </body></html>
\ No newline at end of file
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index cbc0442..77cf688 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -103,6 +103,7 @@
  *   "correction": optional String
  *   "code": String
  *   "url": optional String
+ *   "contextMessages": optional List<DiagnosticMessage>
  *   "hasFix": optional bool
  * }
  *
@@ -123,6 +124,8 @@
 
   String _url;
 
+  List<DiagnosticMessage> _contextMessages;
+
   bool _hasFix;
 
   /**
@@ -221,6 +224,20 @@
   }
 
   /**
+   * Additional messages associated with this diagnostic that provide context
+   * to help the user understand the diagnostic.
+   */
+  List<DiagnosticMessage> get contextMessages => _contextMessages;
+
+  /**
+   * Additional messages associated with this diagnostic that provide context
+   * to help the user understand the diagnostic.
+   */
+  void set contextMessages(List<DiagnosticMessage> value) {
+    this._contextMessages = value;
+  }
+
+  /**
    * A hint to indicate to interested clients that this error has an associated
    * fix (or fixes). The absence of this field implies there are not known to
    * be fixes. Note that since the operation to calculate whether fixes apply
@@ -248,7 +265,10 @@
 
   AnalysisError(AnalysisErrorSeverity severity, AnalysisErrorType type,
       Location location, String message, String code,
-      {String correction, String url, bool hasFix}) {
+      {String correction,
+      String url,
+      List<DiagnosticMessage> contextMessages,
+      bool hasFix}) {
     this.severity = severity;
     this.type = type;
     this.location = location;
@@ -256,6 +276,7 @@
     this.correction = correction;
     this.code = code;
     this.url = url;
+    this.contextMessages = contextMessages;
     this.hasFix = hasFix;
   }
 
@@ -308,12 +329,23 @@
       if (json.containsKey("url")) {
         url = jsonDecoder.decodeString(jsonPath + ".url", json["url"]);
       }
+      List<DiagnosticMessage> contextMessages;
+      if (json.containsKey("contextMessages")) {
+        contextMessages = jsonDecoder.decodeList(
+            jsonPath + ".contextMessages",
+            json["contextMessages"],
+            (String jsonPath, Object json) =>
+                new DiagnosticMessage.fromJson(jsonDecoder, jsonPath, json));
+      }
       bool hasFix;
       if (json.containsKey("hasFix")) {
         hasFix = jsonDecoder.decodeBool(jsonPath + ".hasFix", json["hasFix"]);
       }
       return new AnalysisError(severity, type, location, message, code,
-          correction: correction, url: url, hasFix: hasFix);
+          correction: correction,
+          url: url,
+          contextMessages: contextMessages,
+          hasFix: hasFix);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "AnalysisError", json);
     }
@@ -333,6 +365,11 @@
     if (url != null) {
       result["url"] = url;
     }
+    if (contextMessages != null) {
+      result["contextMessages"] = contextMessages
+          .map((DiagnosticMessage value) => value.toJson())
+          .toList();
+    }
     if (hasFix != null) {
       result["hasFix"] = hasFix;
     }
@@ -352,6 +389,8 @@
           correction == other.correction &&
           code == other.code &&
           url == other.url &&
+          listEqual(contextMessages, other.contextMessages,
+              (DiagnosticMessage a, DiagnosticMessage b) => a == b) &&
           hasFix == other.hasFix;
     }
     return false;
@@ -367,6 +406,7 @@
     hash = JenkinsSmiHash.combine(hash, correction.hashCode);
     hash = JenkinsSmiHash.combine(hash, code.hashCode);
     hash = JenkinsSmiHash.combine(hash, url.hashCode);
+    hash = JenkinsSmiHash.combine(hash, contextMessages.hashCode);
     hash = JenkinsSmiHash.combine(hash, hasFix.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
@@ -1452,6 +1492,108 @@
 }
 
 /**
+ * DiagnosticMessage
+ *
+ * {
+ *   "message": String
+ *   "location": Location
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class DiagnosticMessage implements HasToJson {
+  String _message;
+
+  Location _location;
+
+  /**
+   * The message to be displayed to the user.
+   */
+  String get message => _message;
+
+  /**
+   * The message to be displayed to the user.
+   */
+  void set message(String value) {
+    assert(value != null);
+    this._message = value;
+  }
+
+  /**
+   * The location associated with or referenced by the message. Clients should
+   * provide the ability to navigate to the location.
+   */
+  Location get location => _location;
+
+  /**
+   * The location associated with or referenced by the message. Clients should
+   * provide the ability to navigate to the location.
+   */
+  void set location(Location value) {
+    assert(value != null);
+    this._location = value;
+  }
+
+  DiagnosticMessage(String message, Location location) {
+    this.message = message;
+    this.location = location;
+  }
+
+  factory DiagnosticMessage.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String message;
+      if (json.containsKey("message")) {
+        message =
+            jsonDecoder.decodeString(jsonPath + ".message", json["message"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "message");
+      }
+      Location location;
+      if (json.containsKey("location")) {
+        location = new Location.fromJson(
+            jsonDecoder, jsonPath + ".location", json["location"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "location");
+      }
+      return new DiagnosticMessage(message, location);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "DiagnosticMessage", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["message"] = message;
+    result["location"] = location.toJson();
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is DiagnosticMessage) {
+      return message == other.message && location == other.location;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, message.hashCode);
+    hash = JenkinsSmiHash.combine(hash, location.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * Element
  *
  * {
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/import_library_element.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/import_library_element.dart
index b9e33ed..f135dd8 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/import_library_element.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/import_library_element.dart
@@ -27,7 +27,7 @@
   }
 
   var requestedElements = requestedLibrary.exportNamespace.definedNames;
-  _removeEntryForDynamic(requestedElements);
+  _removeEntriesForDynamicAndNever(requestedElements);
 
   // Find URIs of all libraries that import the requested name into the target.
   var unprefixedNameUriSet = Set<Uri>();
@@ -112,7 +112,7 @@
 
   // Check for existing imports of the requested library.
   for (var import in targetLibrary.imports) {
-    if (import.importedLibrary.source.uri == requestedLibraryUri) {
+    if (import.importedLibrary?.source?.uri == requestedLibraryUri) {
       var importedNames = import.namespace.definedNames;
       if (import.prefix == null) {
         if (canUseUnprefixedImport &&
@@ -145,11 +145,13 @@
   return ImportLibraryRequest(requestedLibraryUri, prefix);
 }
 
-/// The type `dynamic` is part of 'dart:core', but has no library.
-void _removeEntryForDynamic(Map<String, Element> requestedElements) {
+/// The types `dynamic` and `Never` are part of 'dart:core', but have no
+/// library.
+void _removeEntriesForDynamicAndNever(Map<String, Element> requestedElements) {
   requestedElements.removeWhere((_, element) {
     if (element.librarySource == null) {
-      assert(element.displayName == 'dynamic');
+      assert(
+          element.displayName == 'dynamic' || element.displayName == 'Never');
       return true;
     }
     return false;
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart
index 2f545d1..894e061 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart
@@ -142,6 +142,22 @@
   }
 
   @override
+  void visitFieldDeclaration(FieldDeclaration node) {
+    var variableList = node.fields;
+
+    // `Foo^ Foo bar() {}` is recovered as `Foo Foo; bar() {}`, i.e. the
+    // return type of `bar()` gets associated with a new variable declaration.
+    if (node.semicolon.isSynthetic) {
+      if (variableList.variables.length == 1) {
+        var name = variableList.variables[0].name.name;
+        names.remove(name);
+      }
+    }
+
+    super.visitFieldDeclaration(node);
+  }
+
+  @override
   void visitForElement(ForElement node) {
     if (!_isCoveredBy(node)) return;
 
@@ -236,6 +252,15 @@
       return;
     }
 
+    // `Foo^ Foo bar() {}` is recovered as `Foo Foo; bar() {}`, i.e. the
+    // return type of `bar()` gets associated with a new variable declaration.
+    if (node.semicolon.isSynthetic) {
+      if (variableList.variables.length == 1) {
+        var name = variableList.variables[0].name.name;
+        names.remove(name);
+      }
+    }
+
     super.visitTopLevelVariableDeclaration(node);
   }
 
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index 2449bb7..4050a75 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -393,6 +393,34 @@
     return parameterElement?.type is FunctionType;
   }
 
+  /**
+   * Given that the [node] contains the [offset], return the [FormalParameter]
+   * that encloses the [offset], or `null`.
+   */
+  static FormalParameter findFormalParameter(
+    FormalParameterList node,
+    int offset,
+  ) {
+    assert(node.offset < offset && offset < node.end);
+    var parameters = node.parameters;
+    for (var i = 0; i < parameters.length; i++) {
+      var parameter = parameters[i];
+      if (i == 0 && offset < parameter.offset) {
+        return parameter;
+      }
+      if (parameter.offset <= offset) {
+        if (i < parameters.length - 1) {
+          if (offset < parameters[i + 1].offset) {
+            return parameter;
+          }
+        } else if (offset <= node.rightParenthesis.offset) {
+          return parameter;
+        }
+      }
+    }
+    return null;
+  }
+
   static int _computeArgIndex(AstNode containingNode, Object entity) {
     var argList = containingNode;
     if (argList is NamedExpression) {
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index 93c1024..2b0dc59 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -83,6 +82,17 @@
   bool includeVarNameSuggestions = false;
 
   /**
+   * Indicates whether the completion location is in a field declaration.
+   */
+  bool inFieldDeclaration = false;
+
+  /**
+   * Indicates whether the completion location is in a top-level variable
+   * declaration.
+   */
+  bool inTopLevelVariableDeclaration = false;
+
+  /**
    * Indicates whether the completion location is in the body of a static method.
    */
   bool inStaticMethodBody = false;
@@ -151,6 +161,11 @@
       }
     }
 
+    optype.inFieldDeclaration =
+        targetNode.thisOrAncestorOfType<FieldDeclaration>() != null;
+    optype.inTopLevelVariableDeclaration =
+        targetNode.thisOrAncestorOfType<TopLevelVariableDeclaration>() != null;
+
     // If a value should be suggested, suggest also constructors.
     if (optype.includeReturnValueSuggestions) {
       // Careful: in angular plugin, `target.unit` may be null!
@@ -622,6 +637,22 @@
   }
 
   @override
+  visitForElement(ForElement node) {
+    // for (^) {}
+    // for (Str^ str = null;) {}
+    // In theory it is possible to specify any expression in initializer,
+    // but for any practical use we need only types.
+    if (entity == node.forLoopParts) {
+      optype.includeTypeNameSuggestions = true;
+    }
+
+    if (entity == node.body) {
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions = true;
+    }
+  }
+
+  @override
   void visitFormalParameterList(FormalParameterList node) {
     dynamic entity = this.entity;
     if (entity is Token) {
@@ -633,28 +664,27 @@
         }
       }
     }
+
+    // Find the containing parameter.
+    var parameter = CompletionTarget.findFormalParameter(node, offset);
+    if (parameter == null) return;
+
     // Handle default normal parameter just as a normal parameter.
-    if (entity is DefaultFormalParameter) {
-      entity = entity.parameter;
+    if (parameter is DefaultFormalParameter) {
+      parameter = (parameter as DefaultFormalParameter).parameter;
     }
+
     // "(^ this.field)"
-    if (entity is FieldFormalParameter) {
-      if (offset < entity.thisKeyword.offset) {
+    if (parameter is FieldFormalParameter) {
+      if (offset < parameter.thisKeyword.offset) {
         optype.includeTypeNameSuggestions = true;
       }
+      return;
     }
+
     // "(Type name)"
-    if (entity is SimpleFormalParameter) {
-      // "(Type^)" is parsed as a parameter with the _name_ "Type".
-      if (entity.type == null) {
-        optype.includeTypeNameSuggestions = true;
-      }
-      // If inside of "Type" in "(Type^ name)", then include types.
-      if (entity.type != null &&
-          entity.type.offset <= offset &&
-          offset <= entity.type.end) {
-        optype.includeTypeNameSuggestions = true;
-      }
+    if (parameter is SimpleFormalParameter) {
+      visitSimpleFormalParameter(parameter);
     }
   }
 
@@ -688,22 +718,6 @@
 
   @override
   void visitForStatement(ForStatement node) {
-    var entity = this.entity;
-    var entity2 = entity; // Work around limitations of type promotion
-    if (entity2 is SyntacticEntity &&
-        entity2.offset >= node.forLoopParts.offset &&
-        entity2.end <= node.forLoopParts.end) {
-      // Older versions of the analyzer yield elements of `node.forLoopParts`
-      // when iterating through children of `ForEachStatement`.  Handle this
-      // situation by simulating the behavior of newer versions of the analyzer.
-      // TODO(paulberry): remove this case once we require a version of analyzer
-      // containing a1349ac52972a4c69e1b05079ed1662b3b0f8c3f
-      if (entity2.offset == node.forLoopParts.offset) {
-        entity = node.forLoopParts;
-      } else {
-        return node.forLoopParts.accept(this);
-      }
-    }
     // for (^) {}
     // for (Str^ str = null;) {}
     // In theory it is possible to specify any expression in initializer,
@@ -736,6 +750,19 @@
   }
 
   @override
+  visitIfElement(IfElement node) {
+    if (identical(entity, node.condition)) {
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions = true;
+    } else if (identical(entity, node.thenElement) ||
+        identical(entity, node.elseElement)) {
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions = true;
+      optype.includeVoidReturnSuggestions = true;
+    }
+  }
+
+  @override
   void visitIfStatement(IfStatement node) {
     if (_isEntityPrevTokenSynthetic()) {
       // Actual: if (var v i^)
@@ -962,6 +989,45 @@
   }
 
   @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    var type = node.type;
+    var name = node.identifier;
+
+    // "(Type^)" is parsed as a parameter with the _name_ "Type".
+    if (type == null &&
+        name != null &&
+        name.offset <= offset &&
+        offset <= name.end) {
+      optype.includeTypeNameSuggestions = true;
+      return;
+    }
+
+    // If "(^ Type)", then include types.
+    if (type == null && offset < name.offset) {
+      optype.includeTypeNameSuggestions = true;
+      return;
+    }
+
+    // If "(Type ^)", then include parameter names.
+    if (type == null && name.end < offset && offset <= name.token.next.offset) {
+      optype.includeVarNameSuggestions = true;
+      return;
+    }
+
+    // If inside of "Type" in "(Type^ name)", then include types.
+    if (type != null && type.offset <= offset && offset <= type.end) {
+      optype.includeTypeNameSuggestions = true;
+      return;
+    }
+
+    // If "(Type name^)", then include parameter names.
+    if (type != null && name.offset <= offset && offset <= name.end) {
+      optype.includeVarNameSuggestions = true;
+      return;
+    }
+  }
+
+  @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
     // This should never happen; the containingNode will always be some node
     // higher up in the parse tree, and the SimpleIdentifier will be the
@@ -970,6 +1036,14 @@
   }
 
   @override
+  visitSpreadElement(SpreadElement node) {
+    if (identical(entity, node.expression)) {
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions = true;
+    }
+  }
+
+  @override
   void visitStringLiteral(StringLiteral node) {
     // no suggestions
   }
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/suggestion_builder.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/suggestion_builder.dart
index d5122fc75..228f53d 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/suggestion_builder.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/suggestion_builder.dart
@@ -125,7 +125,7 @@
       }).toList();
 
       Iterable<ParameterElement> requiredParameters = element.parameters
-          .where((ParameterElement param) => param.isNotOptional);
+          .where((ParameterElement param) => param.isRequiredPositional);
       suggestion.requiredParameterCount = requiredParameters.length;
 
       Iterable<ParameterElement> namedParameters =
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 5ac22f2..db15540 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -1,14 +1,14 @@
 name: analyzer_plugin
 description: A framework for building plugins for the analysis server.
-version: 0.0.1-alpha.7
+version: 0.0.1-alpha.8
 author: Dart Team <misc@dartlang.org>
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_plugin
 
 environment:
-  sdk: '>=1.8.0 <3.0.0'
+  sdk: '>=2.0.0 <3.0.0'
 
 dependencies:
-  analyzer: '^0.35.3'
+  analyzer: '>=0.35.3 <0.37.0'
   charcode: '^1.1.0'
   html: '>=0.13.1 <0.15.0'
   meta: ^1.0.2
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 9e28ca2..d7aeda7 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -35,6 +35,7 @@
  *   "correction": optional String
  *   "code": String
  *   "url": optional String
+ *   "contextMessages": optional List<DiagnosticMessage>
  *   "hasFix": optional bool
  * }
  */
@@ -48,6 +49,7 @@
         }, optionalFields: {
           "correction": isString,
           "url": isString,
+          "contextMessages": isListOf(isDiagnosticMessage),
           "hasFix": isBool
         }));
 
@@ -223,6 +225,17 @@
     optionalFields: {"optionsFile": isFilePath}));
 
 /**
+ * DiagnosticMessage
+ *
+ * {
+ *   "message": String
+ *   "location": Location
+ * }
+ */
+final Matcher isDiagnosticMessage = new LazyMatcher(() => new MatchesJsonObject(
+    "DiagnosticMessage", {"message": isString, "location": isLocation}));
+
+/**
  * Element
  *
  * {
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
index 8873d2e..fade0d2 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
@@ -161,6 +161,50 @@
 
 @reflectiveTest
 class ImportLibraryElement_incompleteCode_Test extends _Base {
+  test_fieldDeclaration_atEnd() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+class C {
+  A^
+}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+      expectedCode: r'''
+import 'package:test/a.dart';
+
+class C {
+  A
+}
+''',
+    );
+  }
+
+  test_fieldDeclaration_beforeReturnType() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+class C {
+  A^
+  
+  A foo() => null;
+}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+      expectedCode: r'''
+import 'package:test/a.dart';
+
+class C {
+  A
+  
+  A foo() => null;
+}
+''',
+    );
+  }
+
   test_formalParameter() async {
     newFile('/home/test/lib/a.dart', content: 'class A {}');
     newFile('/home/test/lib/b.dart', content: r'''
@@ -180,7 +224,7 @@
     );
   }
 
-  test_topLevelVariable() async {
+  test_topLevelVariable_atEnd() async {
     newFile('/home/test/lib/a.dart', content: 'class A {}');
     newFile('/home/test/lib/b.dart', content: r'''
 export 'a.dart';
@@ -198,6 +242,26 @@
 ''',
     );
   }
+
+  test_topLevelVariable_beforeReturnType() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+A^
+
+A foo() => null;
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+      expectedCode: r'''
+import 'package:test/a.dart';
+
+A
+
+A foo() => null;
+''',
+    );
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
index 8f42f89..83a16cf 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
@@ -37,7 +37,7 @@
       '',
       'b: ',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: ({a: int, b: String}) → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function({a: int, b: String})',
       expectedParameter: 'b: String',
     );
   }
@@ -55,7 +55,7 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: (int) → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function(int)',
       expectedParameter: 'a: int',
     );
   }
@@ -83,7 +83,7 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: (int, int) → Foo<int>',
+      expectedExecutable: 'Foo.<init>: Foo<int> Function(int, int)',
       expectedParameter: 'a: int',
     );
   }
@@ -102,7 +102,7 @@
       ')',
       '(false)',
       argIndex: 1,
-      expectedExecutable: 'Foo.<init>: (bool, bool) → Foo<bool>',
+      expectedExecutable: 'Foo.<init>: Foo<bool> Function(bool, bool)',
       expectedParameter: 'b: bool',
     );
   }
@@ -121,7 +121,8 @@
       '',
       'b: ',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: ({a: int, b: String, c: double}) → Foo',
+      expectedExecutable:
+          'Foo.<init>: Foo Function({a: int, b: String, c: double})',
       expectedParameter: 'b: String',
     );
   }
@@ -140,7 +141,7 @@
       '',
       'b: ',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: ({a: int}) → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function({a: int})',
     );
   }
 
@@ -158,7 +159,7 @@
       ')',
       '(0)',
       argIndex: 1,
-      expectedExecutable: 'Foo.named: (int, String, double) → Foo',
+      expectedExecutable: 'Foo.named: Foo Function(int, String, double)',
       expectedParameter: 'b: String',
     );
   }
@@ -177,7 +178,7 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: (int) → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function(int)',
       expectedParameter: 'a: int',
     );
   }
@@ -196,8 +197,8 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: ((String) → int) → Foo',
-      expectedParameter: 'f: (String) → int',
+      expectedExecutable: 'Foo.<init>: Foo Function(int Function(String))',
+      expectedParameter: 'f: int Function(String)',
       isFunctionalArgument: true,
     );
   }
@@ -214,7 +215,7 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: () → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function()',
     );
   }
 
@@ -230,7 +231,7 @@
       ')',
       '(a)',
       argIndex: 1,
-      expectedExecutable: 'Foo.<init>: () → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function()',
     );
   }
 
@@ -246,7 +247,7 @@
       '',
       'b: ',
       argIndex: 0,
-      expectedExecutable: 'foo: ({a: int, b: String, c: double}) → int',
+      expectedExecutable: 'foo: int Function({a: int, b: String, c: double})',
       expectedParameter: 'b: String',
     );
   }
@@ -263,8 +264,8 @@
       '',
       'f: ',
       argIndex: 0,
-      expectedExecutable: 'foo: ({f: (String) → int}) → int',
-      expectedParameter: 'f: (String) → int',
+      expectedExecutable: 'foo: int Function({f: int Function(String)})',
+      expectedParameter: 'f: int Function(String)',
       isFunctionalArgument: true,
     );
   }
@@ -281,7 +282,7 @@
       '',
       'b: ',
       argIndex: 0,
-      expectedExecutable: 'foo: ({a: int}) → int',
+      expectedExecutable: 'foo: int Function({a: int})',
     );
   }
 
@@ -297,7 +298,7 @@
       ')',
       '(0)',
       argIndex: 1,
-      expectedExecutable: 'foo: (int, String) → int',
+      expectedExecutable: 'foo: int Function(int, String)',
       expectedParameter: 'b: String',
     );
   }
@@ -314,8 +315,8 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'foo: ((String) → int) → int',
-      expectedParameter: 'f: (String) → int',
+      expectedExecutable: 'foo: int Function(int Function(String))',
+      expectedParameter: 'f: int Function(String)',
       isFunctionalArgument: true,
     );
   }
@@ -334,8 +335,8 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'C.foo: ((String) → int) → int',
-      expectedParameter: 'f: (String) → int',
+      expectedExecutable: 'C.foo: int Function(int Function(String))',
+      expectedParameter: 'f: int Function(String)',
       isFunctionalArgument: true,
     );
   }
@@ -352,7 +353,7 @@
       'n',
       '(n)',
       argIndex: 0,
-      expectedExecutable: 'foo: (int, String) → int',
+      expectedExecutable: 'foo: int Function(int, String)',
       expectedParameter: 'a: int',
     );
   }
@@ -369,7 +370,7 @@
       ')',
       '((n))',
       argIndex: 0,
-      expectedExecutable: 'foo: (int, String) → int',
+      expectedExecutable: 'foo: int Function(int, String)',
       expectedParameter: 'a: int',
     );
   }
@@ -386,7 +387,7 @@
       'n',
       '(n)',
       argIndex: 0,
-      expectedExecutable: 'foo: (int, String) → int',
+      expectedExecutable: 'foo: int Function(int, String)',
       expectedParameter: 'a: int',
     );
   }
@@ -664,6 +665,13 @@
     assertTarget('new C();', '{var f; {var x;} new C();}');
   }
 
+  test_MapLiteral_empty() async {
+    // MapLiteral  VariableDeclaration
+    await createTarget('foo = {^');
+    // fasta scanner inserts synthetic closing '}'
+    assertTarget('}', '{}');
+  }
+
   test_MapLiteral_expression() async {
     super.setUp();
     final experimentStatus =
@@ -683,13 +691,6 @@
     }
   }
 
-  test_MapLiteral_empty() async {
-    // MapLiteral  VariableDeclaration
-    await createTarget('foo = {^');
-    // fasta scanner inserts synthetic closing '}'
-    assertTarget('}', '{}');
-  }
-
   test_MapLiteralEntry() async {
     // SimpleIdentifier  MapLiteralEntry  MapLiteral  VariableDeclaration
     await createTarget('foo = {7:T^};');
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
index f4c2eb8..186cfa7 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
@@ -715,6 +715,29 @@
         functionBody: true);
   }
 
+  test_ForElement_body() async {
+    addTestSource('main(args) {[for (var foo in [0]) ^];}');
+    await assertOpType(
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        functionBody: true);
+  }
+
+  test_ForElement_forEachParts_iterable() async {
+    addTestSource('main(args) {[for (var foo in ^) foo];}');
+    await assertOpType(
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        functionBody: true);
+  }
+
+  test_ForElement_forEachParts_type() async {
+    addTestSource('main(args) {[for (i^ foo in [0]) foo];}');
+    await assertOpType(typeNames: true, functionBody: true);
+  }
+
   test_FormalParameter_partialType() async {
     // FormalParameterList MethodDeclaration
     addTestSource('class A {a(b.^ f) { }}');
@@ -780,6 +803,47 @@
         functionBody: true);
   }
 
+  test_IfElement_condition() async {
+    addTestSource('''
+main() {
+  [if (^)];
+}
+''');
+    await assertOpType(
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        functionBody: true);
+  }
+
+  test_IfElement_else() async {
+    addTestSource('''
+main() {
+  [if (true) 0 else ^];
+}
+''');
+    await assertOpType(
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        functionBody: true,
+        voidReturn: true);
+  }
+
+  test_IfElement_then() async {
+    addTestSource('''
+main() {
+  [if (true) ^];
+}
+''');
+    await assertOpType(
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        functionBody: true,
+        voidReturn: true);
+  }
+
   test_IfStatement() async {
     // EmptyStatement  IfStatement  Block  BlockFunctionBody
     addTestSource('main(){var a; if (true) ^}');
@@ -1043,6 +1107,19 @@
         functionBody: true);
   }
 
+  test_SpreadElement() async {
+    addTestSource(r'''
+main() {
+  [...^];
+}
+''');
+    await assertOpType(
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        functionBody: true);
+  }
+
   test_SwitchCase_between() async {
     // SwitchCase  SwitchStatement  Block
     addTestSource('main() {switch(k) {case 1: ^ case 2: return}}');
@@ -1234,7 +1311,7 @@
     // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
     addTestSource(
       'main() { new A.b(^); }'
-          'class A{ A.b({one, two}) {} }',
+      'class A{ A.b({one, two}) {} }',
     );
     await assertOpType(namedArgs: true, functionBody: true);
   }
@@ -1243,7 +1320,7 @@
     // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
     addTestSource(
       'main() { new A.b(o^); }'
-          'class A { A.b({one, two}) {} }',
+      'class A { A.b({one, two}) {} }',
     );
     await assertOpType(namedArgs: true, functionBody: true);
   }
@@ -1252,7 +1329,7 @@
     // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
     addTestSource(
       'main() { new A(^); }'
-          'class A{ A({one, two}) {} }',
+      'class A{ A({one, two}) {} }',
     );
     await assertOpType(namedArgs: true, functionBody: true);
   }
@@ -1261,7 +1338,7 @@
     // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
     addTestSource(
       'main() { new A(o^); }'
-          'class A { A({one, two}) {} }',
+      'class A { A({one, two}) {} }',
     );
     await assertOpType(namedArgs: true, functionBody: true);
   }
@@ -1270,7 +1347,7 @@
     // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
     addTestSource(
       'main() { new A.b(^); }'
-          'class A{ factory A.b({one, two}) {} }',
+      'class A{ factory A.b({one, two}) {} }',
     );
     await assertOpType(namedArgs: true, functionBody: true);
   }
@@ -1279,7 +1356,7 @@
     // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
     addTestSource(
       'main() { new A.b(o^); }'
-          'class A { factory A.b({one, two}) {} }',
+      'class A { factory A.b({one, two}) {} }',
     );
     await assertOpType(namedArgs: true, functionBody: true);
   }
@@ -1288,7 +1365,7 @@
     // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
     addTestSource(
       'main() { new A(^); }'
-          'class A{ factory A({one, two}) {} }',
+      'class A{ factory A({one, two}) {} }',
     );
     await assertOpType(namedArgs: true, functionBody: true);
   }
@@ -1297,7 +1374,7 @@
     // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
     addTestSource(
       'main() { new A(o^); }'
-          'class A { factory A({one, two}) {} }',
+      'class A { factory A({one, two}) {} }',
     );
     await assertOpType(namedArgs: true, functionBody: true);
   }
@@ -2054,23 +2131,35 @@
     await assertOpType(functionBody: true);
   }
 
-//
   test_SimpleFormalParameter_closure() async {
     // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
     addTestSource('mth() { PNGS.sort((String a, Str^) => a.compareTo(b)); }');
     await assertOpType(typeNames: true, functionBody: true);
   }
 
-  test_SimpleFormalParameter_name1() async {
-    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
-    addTestSource('m(String na^) {}');
-    await assertOpType(typeNames: false);
+  test_SimpleFormalParameter_name_typed() async {
+    addTestSource('f(String ^, int b) {}');
+    await assertOpType(typeNames: false, varNames: true);
   }
 
-  test_SimpleFormalParameter_name2() async {
-    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
-    addTestSource('m(int first, String na^) {}');
-    await assertOpType(typeNames: false);
+  test_SimpleFormalParameter_name_typed_hasName() async {
+    addTestSource('f(String n^, int b) {}');
+    await assertOpType(typeNames: false, varNames: true);
+  }
+
+  test_SimpleFormalParameter_name_typed_last() async {
+    addTestSource('f(String ^) {}');
+    await assertOpType(typeNames: false, varNames: true);
+  }
+
+  test_SimpleFormalParameter_name_typed_last_hasName() async {
+    addTestSource('f(String n^) {}');
+    await assertOpType(typeNames: false, varNames: true);
+  }
+
+  test_SimpleFormalParameter_type_named() async {
+    addTestSource('f(^ name) {}');
+    await assertOpType(typeNames: true, varNames: false);
   }
 
   test_SimpleFormalParameter_type_optionalNamed() async {
@@ -2109,6 +2198,11 @@
     await assertOpType(typeNames: true);
   }
 
+  test_SimpleFormalParameter_untyped() async {
+    addTestSource('main(final ^) {}');
+    await assertOpType(typeNames: true, varNames: false);
+  }
+
   test_SwitchCase_before() async {
     // SwitchCase  SwitchStatement  Block
     addTestSource('main() {switch(k) {^case 1:}}');
diff --git a/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart b/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart
index ee9466e..673e646 100644
--- a/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
@@ -23,11 +24,13 @@
 class LocalDeclarationVisitorTest {
   CompilationUnit parseCompilationUnit(String content) {
     AnalysisErrorListener listener = AnalysisErrorListener.NULL_LISTENER;
+    var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
     Scanner scanner =
-        new Scanner(null, new CharSequenceReader(content), listener);
+        new Scanner(null, new CharSequenceReader(content), listener)
+          ..configureFeatures(featureSet);
     Token token = scanner.tokenize();
     var source = new StringSource(content, '/test.dart');
-    Parser parser = new Parser(source, listener);
+    Parser parser = new Parser(source, listener, featureSet: featureSet);
     CompilationUnit unit = parser.parseCompilationUnit(token);
     expect(unit, isNotNull);
     return unit;
diff --git a/pkg/analyzer_plugin/test/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/utilities/completion/completion_target_test.dart
index 9b44141..1136327 100644
--- a/pkg/analyzer_plugin/test/utilities/completion/completion_target_test.dart
+++ b/pkg/analyzer_plugin/test/utilities/completion/completion_target_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -29,11 +30,14 @@
   /// instance, does this.
   Expression parseDanglingDart(String code) {
     final reader = new CharSequenceReader(code);
-    final scanner = new Scanner(null, reader, null);
+    var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
+    final scanner = new Scanner(null, reader, null)
+      ..configureFeatures(featureSet);
     final source = new StringSource(code, 'test.dart');
     final listener = new _ErrorCollector();
+    final parser = new Parser(source, listener, featureSet: featureSet);
 
-    return new Parser(source, listener).parseExpression(scanner.tokenize());
+    return parser.parseExpression(scanner.tokenize());
   }
 
   test_danglingExpressionCompletionIsValid() {
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index 3572838..aac0a52 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -101,6 +101,15 @@
           The URL of a page containing documentation associated with this error.
         </p>
       </field>
+      <field name="contextMessages" optional="true">
+        <list>
+          <ref>DiagnosticMessage</ref>
+        </list>
+        <p>
+          Additional messages associated with this diagnostic that provide
+          context to help the user understand the diagnostic.
+        </p>
+      </field>
       <field name="hasFix" optional="true">
         <ref>bool</ref>
         <p>
@@ -407,6 +416,31 @@
       <value><code>PARAMETER</code></value>
     </enum>
   </type>
+  <type name="DiagnosticMessage">
+    <p>
+      A message associated with a diagnostic.
+    </p>
+    <p>
+      For example, if the diagnostic is reporting that a variable has been
+      referenced before it was declared, it might have a diagnostic message that
+      indicates where the variable is declared.
+    </p>
+    <object>
+      <field name="message">
+        <ref>String</ref>
+        <p>
+          The message to be displayed to the user.
+        </p>
+      </field>
+      <field name="location">
+        <ref>Location</ref>
+        <p>
+          The location associated with or referenced by the message. Clients
+          should provide the ability to navigate to the location.
+        </p>
+      </field>
+    </object>
+  </type>
   <type name="Element">
     <p>
       Information about an element (something that can be declared in code).
diff --git a/pkg/expect/lib/async_minitest.dart b/pkg/async_helper/lib/async_minitest.dart
similarity index 100%
rename from pkg/expect/lib/async_minitest.dart
rename to pkg/async_helper/lib/async_minitest.dart
diff --git a/pkg/async_helper/pubspec.yaml b/pkg/async_helper/pubspec.yaml
index ceb2634..df92b53 100644
--- a/pkg/async_helper/pubspec.yaml
+++ b/pkg/async_helper/pubspec.yaml
@@ -7,3 +7,6 @@
  language tests.
  Third parties are discouraged from using this, and should use
  the facilities provided in package:test.
+
+dependencies:
+  expect: any
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index c5cfe60..d9a48b1 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -5,6 +5,7 @@
 library dart2js.backend_strategy;
 
 import 'common.dart';
+import 'common/codegen.dart';
 import 'common/tasks.dart';
 import 'deferred_load.dart' show OutputUnitData;
 import 'enqueue.dart';
@@ -12,8 +13,9 @@
 import 'inferrer/types.dart';
 import 'io/source_information.dart';
 import 'js_backend/inferred_data.dart';
-import 'js_backend/js_backend.dart';
+import 'js_backend/interceptor_data.dart';
 import 'js_backend/native_data.dart';
+import 'serialization/serialization.dart';
 import 'ssa/ssa.dart';
 import 'universe/codegen_world_builder.dart';
 import 'universe/world_builder.dart';
@@ -36,15 +38,16 @@
   CodegenWorldBuilder createCodegenWorldBuilder(
       NativeBasicData nativeBasicData,
       JClosedWorld closedWorld,
-      SelectorConstraintsStrategy selectorConstraintsStrategy);
+      SelectorConstraintsStrategy selectorConstraintsStrategy,
+      OneShotInterceptorData oneShotInterceptorData);
 
   /// Creates the [WorkItemBuilder] used by the codegen enqueuer.
-  WorkItemBuilder createCodegenWorkItemBuilder(JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults);
+  WorkItemBuilder createCodegenWorkItemBuilder(
+      JClosedWorld closedWorld, CodegenResults codegenResults);
 
   /// Creates the [SsaBuilder] used for the element model.
-  SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
-      SourceInformationStrategy sourceInformationStrategy);
+  SsaBuilder createSsaBuilder(
+      CompilerTask task, SourceInformationStrategy sourceInformationStrategy);
 
   /// Returns the [SourceInformationStrategy] use for the element model.
   SourceInformationStrategy get sourceInformationStrategy;
@@ -55,4 +58,15 @@
   /// Creates the [TypesInferrer] used by this strategy.
   TypesInferrer createTypesInferrer(
       JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder);
+
+  /// Calls [f] for every member that needs to be serialized for modular code
+  /// generation and returns an [EntityWriter] for encoding these members in
+  /// the serialized data.
+  ///
+  /// The needed members include members computed on demand during non-modular
+  /// code generation, such as constructor bodies and and generator bodies.
+  EntityWriter forEachCodegenMember(void Function(MemberEntity member) f);
+
+  /// Prepare [source] to deserialize modular code generation data.
+  void prepareCodegenReader(DataSource source);
 }
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 343d58b..beb4c95 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -261,6 +261,9 @@
   /// the closure class.
   FunctionEntity get callMethod => null;
 
+  /// The signature method for [callMethod] if needed.
+  FunctionEntity get signatureMethod => null;
+
   /// List of locals that this closure class has created corresponding field
   /// entities for.
   @deprecated
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 576cfc4..801a18f 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -84,6 +84,10 @@
   static const String dillDependencies = '--dill-dependencies';
   static const String readData = '--read-data';
   static const String writeData = '--write-data';
+  static const String readCodegen = '--read-codegen';
+  static const String writeCodegen = '--write-codegen';
+  static const String codegenShard = '--codegen-shard';
+  static const String codegenShards = '--codegen-shards';
   static const String cfeOnly = '--cfe-only';
   static const String debugGlobalInference = '--debug-global-inference';
 
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index ec92751..f7c4050 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -4,20 +4,43 @@
 
 library dart2js.common.codegen;
 
+import 'package:js_ast/src/precedence.dart' as js show PRIMARY;
+
+import '../common.dart';
 import '../common_elements.dart';
+import '../constants/values.dart';
+import '../deferred_load.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart' show DartType, InterfaceType;
+import '../inferrer/abstract_value_domain.dart';
+import '../inferrer/types.dart';
+import '../io/source_information.dart';
+import '../js/js.dart' as js;
+import '../js_backend/backend.dart';
+import '../js_backend/namer.dart';
+import '../js_emitter/code_emitter_task.dart' show Emitter;
+import '../native/behavior.dart';
+import '../serialization/serialization.dart';
+import '../ssa/ssa.dart';
 import '../universe/feature.dart';
+import '../universe/selector.dart';
 import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
 import '../universe/world_impact.dart'
     show WorldImpact, WorldImpactBuilderImpl, WorldImpactVisitor;
 import '../util/enumset.dart';
-import '../util/util.dart' show Pair, Setlet;
-import 'work.dart' show WorkItem;
+import '../util/util.dart';
+import '../world.dart';
 
 class CodegenImpact extends WorldImpact {
   const CodegenImpact();
 
+  factory CodegenImpact.readFromDataSource(DataSource source) =
+      _CodegenImpact.readFromDataSource;
+
+  void writeToDataSink(DataSink sink) {
+    throw new UnsupportedError('CodegenImpact.writeToDataSink');
+  }
+
   Iterable<Pair<DartType, DartType>> get typeVariableBoundsSubtypeChecks {
     return const <Pair<DartType, DartType>>[];
   }
@@ -34,18 +57,139 @@
 
   Iterable<GenericInstantiation> get genericInstantiations =>
       const <GenericInstantiation>[];
+
+  Iterable<NativeBehavior> get nativeBehaviors => const [];
+
+  Iterable<FunctionEntity> get nativeMethods => const [];
+
+  Iterable<Selector> get oneShotInterceptors => const [];
 }
 
 class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
-  Setlet<Pair<DartType, DartType>> _typeVariableBoundsSubtypeChecks;
-  Setlet<String> _constSymbols;
+  static const String tag = 'codegen-impact';
+
+  Set<Pair<DartType, DartType>> _typeVariableBoundsSubtypeChecks;
+  Set<String> _constSymbols;
   List<Set<ClassEntity>> _specializedGetInterceptors;
   bool _usesInterceptor = false;
   EnumSet<AsyncMarker> _asyncMarkers;
   Set<GenericInstantiation> _genericInstantiations;
+  List<NativeBehavior> _nativeBehaviors;
+  Set<FunctionEntity> _nativeMethods;
+  Set<Selector> _oneShotInterceptors;
 
   _CodegenImpact();
 
+  _CodegenImpact.internal(
+      Set<DynamicUse> dynamicUses,
+      Set<StaticUse> staticUses,
+      Set<TypeUse> typeUses,
+      Set<ConstantUse> constantUses,
+      this._typeVariableBoundsSubtypeChecks,
+      this._constSymbols,
+      this._specializedGetInterceptors,
+      this._usesInterceptor,
+      this._asyncMarkers,
+      this._genericInstantiations,
+      this._nativeBehaviors,
+      this._nativeMethods,
+      this._oneShotInterceptors)
+      : super.internal(dynamicUses, staticUses, typeUses, constantUses);
+
+  factory _CodegenImpact.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    Set<DynamicUse> dynamicUses = source
+        .readList(() => DynamicUse.readFromDataSource(source),
+            emptyAsNull: true)
+        ?.toSet();
+    Set<StaticUse> staticUses = source
+        .readList(() => StaticUse.readFromDataSource(source), emptyAsNull: true)
+        ?.toSet();
+    Set<TypeUse> typeUses = source
+        .readList(() => TypeUse.readFromDataSource(source), emptyAsNull: true)
+        ?.toSet();
+    Set<ConstantUse> constantUses = source
+        .readList(() => ConstantUse.readFromDataSource(source),
+            emptyAsNull: true)
+        ?.toSet();
+    Set<Pair<DartType, DartType>> typeVariableBoundsSubtypeChecks =
+        source.readList(() {
+      return new Pair(source.readDartType(), source.readDartType());
+    }, emptyAsNull: true)?.toSet();
+    Set<String> constSymbols = source.readStrings(emptyAsNull: true)?.toSet();
+    List<Set<ClassEntity>> specializedGetInterceptors = source.readList(() {
+      return source.readClasses().toSet();
+    }, emptyAsNull: true);
+    bool usesInterceptor = source.readBool();
+    int asyncMarkersValue = source.readIntOrNull();
+    EnumSet<AsyncMarker> asyncMarkers = asyncMarkersValue != null
+        ? new EnumSet.fromValue(asyncMarkersValue)
+        : null;
+    Set<GenericInstantiation> genericInstantiations = source
+        .readList(() => GenericInstantiation.readFromDataSource(source),
+            emptyAsNull: true)
+        ?.toSet();
+    List<NativeBehavior> nativeBehaviors = source.readList(
+        () => NativeBehavior.readFromDataSource(source),
+        emptyAsNull: true);
+    Set<FunctionEntity> nativeMethods =
+        source.readMembers<FunctionEntity>(emptyAsNull: true)?.toSet();
+    Set<Selector> oneShotInterceptors = source
+        .readList(() => Selector.readFromDataSource(source), emptyAsNull: true)
+        ?.toSet();
+    source.end(tag);
+    return new _CodegenImpact.internal(
+        dynamicUses,
+        staticUses,
+        typeUses,
+        constantUses,
+        typeVariableBoundsSubtypeChecks,
+        constSymbols,
+        specializedGetInterceptors,
+        usesInterceptor,
+        asyncMarkers,
+        genericInstantiations,
+        nativeBehaviors,
+        nativeMethods,
+        oneShotInterceptors);
+  }
+
+  @override
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeList(dynamicUses, (DynamicUse use) => use.writeToDataSink(sink),
+        allowNull: true);
+    sink.writeList(staticUses, (StaticUse use) => use.writeToDataSink(sink),
+        allowNull: true);
+    sink.writeList(typeUses, (TypeUse use) => use.writeToDataSink(sink),
+        allowNull: true);
+    sink.writeList(constantUses, (ConstantUse use) => use.writeToDataSink(sink),
+        allowNull: true);
+    sink.writeList<Pair<DartType, DartType>>(_typeVariableBoundsSubtypeChecks,
+        (pair) {
+      sink.writeDartType(pair.a);
+      sink.writeDartType(pair.b);
+    }, allowNull: true);
+    sink.writeStrings(_constSymbols, allowNull: true);
+    sink.writeList(_specializedGetInterceptors, sink.writeClasses,
+        allowNull: true);
+    sink.writeBool(_usesInterceptor);
+    sink.writeIntOrNull(_asyncMarkers?.value);
+    sink.writeList(
+        _genericInstantiations,
+        (GenericInstantiation instantiation) =>
+            instantiation.writeToDataSink(sink),
+        allowNull: true);
+    sink.writeList(_nativeBehaviors,
+        (NativeBehavior behavior) => behavior.writeToDataSink(sink),
+        allowNull: true);
+    sink.writeMembers(_nativeMethods, allowNull: true);
+    sink.writeList(_oneShotInterceptors,
+        (Selector selector) => selector.writeToDataSink(sink),
+        allowNull: true);
+    sink.end(tag);
+  }
+
   @override
   void apply(WorldImpactVisitor visitor) {
     staticUses.forEach(visitor.visitStaticUse);
@@ -55,7 +199,7 @@
 
   void registerTypeVariableBoundsSubtypeCheck(
       DartType subtype, DartType supertype) {
-    _typeVariableBoundsSubtypeChecks ??= new Setlet<Pair<DartType, DartType>>();
+    _typeVariableBoundsSubtypeChecks ??= {};
     _typeVariableBoundsSubtypeChecks
         .add(new Pair<DartType, DartType>(subtype, supertype));
   }
@@ -68,7 +212,7 @@
   }
 
   void registerConstSymbol(String name) {
-    _constSymbols ??= new Setlet<String>();
+    _constSymbols ??= {};
     _constSymbols.add(name);
   }
 
@@ -109,7 +253,7 @@
   }
 
   void registerGenericInstantiation(GenericInstantiation instantiation) {
-    _genericInstantiations ??= new Set<GenericInstantiation>();
+    _genericInstantiations ??= {};
     _genericInstantiations.add(instantiation);
   }
 
@@ -117,22 +261,80 @@
   Iterable<GenericInstantiation> get genericInstantiations {
     return _genericInstantiations ?? const <GenericInstantiation>[];
   }
+
+  void registerNativeBehavior(NativeBehavior nativeBehavior) {
+    _nativeBehaviors ??= [];
+    _nativeBehaviors.add(nativeBehavior);
+  }
+
+  @override
+  Iterable<NativeBehavior> get nativeBehaviors {
+    return _nativeBehaviors ?? const <NativeBehavior>[];
+  }
+
+  void registerNativeMethod(FunctionEntity function) {
+    _nativeMethods ??= {};
+    _nativeMethods.add(function);
+  }
+
+  @override
+  Iterable<FunctionEntity> get nativeMethods {
+    return _nativeMethods ?? const [];
+  }
+
+  void registerOneShotInterceptor(Selector selector) {
+    _oneShotInterceptors ??= {};
+    _oneShotInterceptors.add(selector);
+  }
+
+  @override
+  Iterable<Selector> get oneShotInterceptors {
+    return _oneShotInterceptors ?? const [];
+  }
+
+  @override
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.write('CodegenImpact:');
+    WorldImpact.printOn(sb, this);
+
+    void add(String title, Iterable iterable) {
+      if (iterable.isNotEmpty) {
+        sb.write('\n $title:');
+        iterable.forEach((e) => sb.write('\n  $e'));
+      }
+    }
+
+    add('typeVariableBoundsSubtypeChecks', typeVariableBoundsSubtypeChecks);
+    add('constSymbols', constSymbols);
+    add('specializedGetInterceptors', specializedGetInterceptors);
+    if (usesInterceptor) {
+      sb.write('\n usesInterceptor: true');
+    }
+    add('asyncMarkers', asyncMarkers);
+    add('genericInstantiations', genericInstantiations);
+    add('nativeBehaviors', nativeBehaviors);
+    add('nativeMethods', nativeMethods);
+    add('oneShotInterceptors', oneShotInterceptors);
+
+    return sb.toString();
+  }
 }
 
 // TODO(johnniwinther): Split this class into interface and implementation.
 // TODO(johnniwinther): Move this implementation to the JS backend.
 class CodegenRegistry {
   final ElementEnvironment _elementEnvironment;
-  final MemberEntity currentElement;
-  final _CodegenImpact worldImpact;
+  final MemberEntity _currentElement;
+  final _CodegenImpact _worldImpact;
+  List<ModularName> _names;
+  List<ModularExpression> _expressions;
 
-  CodegenRegistry(this._elementEnvironment, this.currentElement)
-      : this.worldImpact = new _CodegenImpact();
-
-  bool get isForResolution => false;
+  CodegenRegistry(this._elementEnvironment, this._currentElement)
+      : this._worldImpact = new _CodegenImpact();
 
   @override
-  String toString() => 'CodegenRegistry for $currentElement';
+  String toString() => 'CodegenRegistry for $_currentElement';
 
   @deprecated
   void registerInstantiatedClass(ClassEntity element) {
@@ -140,40 +342,44 @@
   }
 
   void registerStaticUse(StaticUse staticUse) {
-    worldImpact.registerStaticUse(staticUse);
+    _worldImpact.registerStaticUse(staticUse);
   }
 
   void registerDynamicUse(DynamicUse dynamicUse) {
-    worldImpact.registerDynamicUse(dynamicUse);
+    _worldImpact.registerDynamicUse(dynamicUse);
   }
 
   void registerTypeUse(TypeUse typeUse) {
-    worldImpact.registerTypeUse(typeUse);
+    _worldImpact.registerTypeUse(typeUse);
   }
 
   void registerConstantUse(ConstantUse constantUse) {
-    worldImpact.registerConstantUse(constantUse);
+    _worldImpact.registerConstantUse(constantUse);
   }
 
   void registerTypeVariableBoundsSubtypeCheck(
       DartType subtype, DartType supertype) {
-    worldImpact.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
+    _worldImpact.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
   }
 
   void registerInstantiatedClosure(FunctionEntity element) {
-    worldImpact.registerStaticUse(new StaticUse.callMethod(element));
+    _worldImpact.registerStaticUse(new StaticUse.callMethod(element));
   }
 
   void registerConstSymbol(String name) {
-    worldImpact.registerConstSymbol(name);
+    _worldImpact.registerConstSymbol(name);
   }
 
   void registerSpecializedGetInterceptor(Set<ClassEntity> classes) {
-    worldImpact.registerSpecializedGetInterceptor(classes);
+    _worldImpact.registerSpecializedGetInterceptor(classes);
+  }
+
+  void registerOneShotInterceptor(Selector selector) {
+    _worldImpact.registerOneShotInterceptor(selector);
   }
 
   void registerUseInterceptor() {
-    worldImpact.registerUseInterceptor();
+    _worldImpact.registerUseInterceptor();
   }
 
   void registerInstantiation(InterfaceType type) {
@@ -181,15 +387,1770 @@
   }
 
   void registerAsyncMarker(AsyncMarker asyncMarker) {
-    worldImpact.registerAsyncMarker(asyncMarker);
+    _worldImpact.registerAsyncMarker(asyncMarker);
   }
 
   void registerGenericInstantiation(GenericInstantiation instantiation) {
-    worldImpact.registerGenericInstantiation(instantiation);
+    _worldImpact.registerGenericInstantiation(instantiation);
+  }
+
+  void registerNativeBehavior(NativeBehavior nativeBehavior) {
+    _worldImpact.registerNativeBehavior(nativeBehavior);
+  }
+
+  void registerNativeMethod(FunctionEntity function) {
+    _worldImpact.registerNativeMethod(function);
+  }
+
+  void registerModularName(ModularName name) {
+    _names ??= [];
+    _names.add(name);
+  }
+
+  void registerModularExpression(ModularExpression expression) {
+    _expressions ??= [];
+    _expressions.add(expression);
+  }
+
+  CodegenResult close(js.Fun code) {
+    return new CodegenResult(
+        code, _worldImpact, _names ?? const [], _expressions ?? const []);
   }
 }
 
-/// [WorkItem] used exclusively by the [CodegenEnqueuer].
-abstract class CodegenWorkItem extends WorkItem {
-  CodegenRegistry get registry;
+/// Interface for reading the code generation results for all [MemberEntity]s.
+abstract class CodegenResults {
+  GlobalTypeInferenceResults get globalTypeInferenceResults;
+  CodegenInputs get codegenInputs;
+  CodegenResult getCodegenResults(MemberEntity member);
+}
+
+/// Code generation results computed on-demand.
+///
+/// This is used in the non-modular codegen enqueuer driving code generation.
+class OnDemandCodegenResults extends CodegenResults {
+  @override
+  final GlobalTypeInferenceResults globalTypeInferenceResults;
+  @override
+  final CodegenInputs codegenInputs;
+  final SsaFunctionCompiler _functionCompiler;
+
+  OnDemandCodegenResults(this.globalTypeInferenceResults, this.codegenInputs,
+      this._functionCompiler);
+
+  @override
+  CodegenResult getCodegenResults(MemberEntity member) {
+    return _functionCompiler.compile(member);
+  }
+}
+
+/// Deserialized code generation results.
+///
+/// This is used for modular code generation.
+class DeserializedCodegenResults extends CodegenResults {
+  @override
+  final GlobalTypeInferenceResults globalTypeInferenceResults;
+  @override
+  final CodegenInputs codegenInputs;
+
+  final Map<MemberEntity, CodegenResult> _map;
+
+  DeserializedCodegenResults(
+      this.globalTypeInferenceResults, this.codegenInputs, this._map);
+
+  @override
+  CodegenResult getCodegenResults(MemberEntity member) {
+    CodegenResult result = _map[member];
+    if (result == null) {
+      failedAt(member,
+          "No codegen results from $member (${identityHashCode(member)}).");
+    }
+    return result;
+  }
+}
+
+/// The code generation result for a single [MemberEntity].
+class CodegenResult {
+  static const String tag = 'codegen-result';
+
+  final js.Fun code;
+  final CodegenImpact impact;
+  final Iterable<ModularName> modularNames;
+  final Iterable<ModularExpression> modularExpressions;
+
+  CodegenResult(
+      this.code, this.impact, this.modularNames, this.modularExpressions);
+
+  /// Reads a [CodegenResult] object from [source].
+  ///
+  /// The [ModularName] and [ModularExpression] nodes read during
+  /// deserialization are collected in [modularNames] and [modularExpressions]
+  /// to avoid the need for visiting the [code] node post deserialization.
+  factory CodegenResult.readFromDataSource(
+      DataSource source,
+      List<ModularName> modularNames,
+      List<ModularExpression> modularExpressions) {
+    source.begin(tag);
+    js.Fun code = source.readJsNodeOrNull();
+    CodegenImpact impact = CodegenImpact.readFromDataSource(source);
+    source.end(tag);
+    return new CodegenResult(code, impact, modularNames, modularExpressions);
+  }
+
+  /// Writes the [CodegenResult] object to [sink].
+  ///
+  /// The [modularNames] and [modularExpressions] fields are not directly
+  /// serializes because these are embedded in the [code] node and collected
+  /// through this during deserialization.
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeJsNodeOrNull(code);
+    impact.writeToDataSink(sink);
+    sink.end(tag);
+  }
+
+  void applyModularState(Namer namer, Emitter emitter) {
+    for (ModularName name in modularNames) {
+      switch (name.kind) {
+        case ModularNameKind.rtiField:
+          name.value = namer.rtiFieldJsName;
+          break;
+        case ModularNameKind.runtimeTypeName:
+          name.value = namer.runtimeTypeName(name.data);
+          break;
+        case ModularNameKind.className:
+          name.value = namer.className(name.data);
+          break;
+        case ModularNameKind.aliasedSuperMember:
+          name.value = namer.aliasedSuperMemberPropertyName(name.data);
+          break;
+        case ModularNameKind.staticClosure:
+          name.value = namer.staticClosureName(name.data);
+          break;
+        case ModularNameKind.methodProperty:
+          name.value = namer.methodPropertyName(name.data);
+          break;
+        case ModularNameKind.operatorIs:
+          name.value = namer.operatorIs(name.data);
+          break;
+        case ModularNameKind.operatorIsType:
+          name.value = namer.operatorIsType(name.data);
+          break;
+        case ModularNameKind.substitution:
+          name.value = namer.substitutionName(name.data);
+          break;
+        case ModularNameKind.instanceMethod:
+          name.value = namer.instanceMethodName(name.data);
+          break;
+        case ModularNameKind.instanceField:
+          name.value = namer.instanceFieldPropertyName(name.data);
+          break;
+        case ModularNameKind.invocation:
+          name.value = namer.invocationName(name.data);
+          break;
+        case ModularNameKind.lazyInitializer:
+          name.value = namer.lazyInitializerName(name.data);
+          break;
+        case ModularNameKind.globalPropertyNameForClass:
+          name.value = namer.globalPropertyNameForClass(name.data);
+          break;
+        case ModularNameKind.globalPropertyNameForType:
+          name.value = namer.globalPropertyNameForType(name.data);
+          break;
+        case ModularNameKind.globalPropertyNameForMember:
+          name.value = namer.globalPropertyNameForMember(name.data);
+          break;
+        case ModularNameKind.nameForGetInterceptor:
+          name.value = namer.nameForGetInterceptor(name.set);
+          break;
+        case ModularNameKind.nameForOneShotInterceptor:
+          name.value = namer.nameForOneShotInterceptor(name.data, name.set);
+          break;
+        case ModularNameKind.asName:
+          name.value = namer.asName(name.data);
+          break;
+      }
+    }
+    for (ModularExpression expression in modularExpressions) {
+      switch (expression.kind) {
+        case ModularExpressionKind.globalObjectForLibrary:
+          expression.value = namer
+              .readGlobalObjectForLibrary(expression.data)
+              .withSourceInformation(expression.sourceInformation);
+          break;
+        case ModularExpressionKind.globalObjectForClass:
+          expression.value = namer
+              .readGlobalObjectForClass(expression.data)
+              .withSourceInformation(expression.sourceInformation);
+          break;
+        case ModularExpressionKind.globalObjectForType:
+          expression.value = namer
+              .readGlobalObjectForType(expression.data)
+              .withSourceInformation(expression.sourceInformation);
+          break;
+        case ModularExpressionKind.globalObjectForMember:
+          expression.value = namer
+              .readGlobalObjectForMember(expression.data)
+              .withSourceInformation(expression.sourceInformation);
+          break;
+        case ModularExpressionKind.constant:
+          expression.value = emitter
+              .constantReference(expression.data)
+              .withSourceInformation(expression.sourceInformation);
+          break;
+        case ModularExpressionKind.embeddedGlobalAccess:
+          expression.value = emitter
+              .generateEmbeddedGlobalAccess(expression.data)
+              .withSourceInformation(expression.sourceInformation);
+          break;
+      }
+    }
+  }
+
+  @override
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.write('CodegenResult(code=');
+    sb.write(code != null ? js.DebugPrint(code) : '<null>,');
+    sb.write('impact=$impact,');
+    sb.write('modularNames=$modularNames,');
+    sb.write('modularExpressions=$modularExpressions');
+    sb.write(')');
+    return sb.toString();
+  }
+}
+
+enum ModularNameKind {
+  rtiField,
+  runtimeTypeName,
+  className,
+  aliasedSuperMember,
+  staticClosure,
+  methodProperty,
+  operatorIs,
+  operatorIsType,
+  substitution,
+  instanceMethod,
+  instanceField,
+  invocation,
+  lazyInitializer,
+  globalPropertyNameForClass,
+  globalPropertyNameForType,
+  globalPropertyNameForMember,
+  nameForGetInterceptor,
+  nameForOneShotInterceptor,
+  asName,
+}
+
+class ModularName extends js.Name implements js.AstContainer {
+  static const String tag = 'modular-name';
+
+  final ModularNameKind kind;
+  js.Name _value;
+  final Object data;
+  final Set<ClassEntity> set;
+
+  ModularName(this.kind, {this.data, this.set});
+
+  factory ModularName.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    ModularNameKind kind = source.readEnum(ModularNameKind.values);
+    Object data;
+    Set<ClassEntity> set;
+    switch (kind) {
+      case ModularNameKind.rtiField:
+        break;
+      case ModularNameKind.globalPropertyNameForType:
+      case ModularNameKind.runtimeTypeName:
+        bool dataIsClassEntity = source.readBool();
+        if (dataIsClassEntity) {
+          data = source.readClass();
+        } else {
+          data = source.readTypedef();
+        }
+        break;
+      case ModularNameKind.className:
+      case ModularNameKind.operatorIs:
+      case ModularNameKind.substitution:
+      case ModularNameKind.globalPropertyNameForClass:
+        data = source.readClass();
+        break;
+      case ModularNameKind.aliasedSuperMember:
+      case ModularNameKind.staticClosure:
+      case ModularNameKind.methodProperty:
+      case ModularNameKind.instanceField:
+      case ModularNameKind.instanceMethod:
+      case ModularNameKind.lazyInitializer:
+      case ModularNameKind.globalPropertyNameForMember:
+        data = source.readMember();
+        break;
+      case ModularNameKind.operatorIsType:
+        data = source.readDartType();
+        break;
+      case ModularNameKind.invocation:
+        data = Selector.readFromDataSource(source);
+        break;
+      case ModularNameKind.nameForGetInterceptor:
+        set = source.readClasses().toSet();
+        break;
+      case ModularNameKind.nameForOneShotInterceptor:
+        data = Selector.readFromDataSource(source);
+        set = source.readClasses().toSet();
+        break;
+      case ModularNameKind.asName:
+        data = source.readString();
+        break;
+    }
+    source.end(tag);
+    return new ModularName(kind, data: data, set: set);
+  }
+
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeEnum(kind);
+    switch (kind) {
+      case ModularNameKind.rtiField:
+        break;
+      case ModularNameKind.globalPropertyNameForType:
+      case ModularNameKind.runtimeTypeName:
+        sink.writeBool(data is ClassEntity);
+        if (data is ClassEntity) {
+          sink.writeClass(data);
+        } else {
+          sink.writeTypedef(data);
+        }
+        break;
+      case ModularNameKind.className:
+      case ModularNameKind.operatorIs:
+      case ModularNameKind.substitution:
+      case ModularNameKind.globalPropertyNameForClass:
+        sink.writeClass(data);
+        break;
+      case ModularNameKind.aliasedSuperMember:
+      case ModularNameKind.staticClosure:
+      case ModularNameKind.methodProperty:
+      case ModularNameKind.instanceField:
+      case ModularNameKind.instanceMethod:
+      case ModularNameKind.lazyInitializer:
+      case ModularNameKind.globalPropertyNameForMember:
+        sink.writeMember(data);
+        break;
+      case ModularNameKind.operatorIsType:
+        sink.writeDartType(data);
+        break;
+      case ModularNameKind.invocation:
+        Selector selector = data;
+        selector.writeToDataSink(sink);
+        break;
+      case ModularNameKind.nameForGetInterceptor:
+        sink.writeClasses(set);
+        break;
+      case ModularNameKind.nameForOneShotInterceptor:
+        Selector selector = data;
+        selector.writeToDataSink(sink);
+        sink.writeClasses(set);
+        break;
+      case ModularNameKind.asName:
+        sink.writeString(data);
+        break;
+    }
+    sink.end(tag);
+  }
+
+  js.Name get value {
+    assert(_value != null);
+    return _value;
+  }
+
+  void set value(js.Name node) {
+    assert(_value == null);
+    assert(node != null);
+    _value = node.withSourceInformation(sourceInformation);
+  }
+
+  @override
+  String get key {
+    assert(_value != null);
+    return _value.key;
+  }
+
+  @override
+  String get name {
+    assert(_value != null);
+    return _value.name;
+  }
+
+  @override
+  bool get allowRename {
+    assert(_value != null);
+    return _value.allowRename;
+  }
+
+  @override
+  int compareTo(js.Name other) {
+    assert(_value != null);
+    return _value.compareTo(other);
+  }
+
+  @override
+  Iterable<js.Node> get containedNodes {
+    return _value != null ? [_value] : const [];
+  }
+
+  @override
+  int get hashCode {
+    return Hashing.setHash(set, Hashing.objectsHash(kind, data));
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return other is ModularName &&
+        kind == other.kind &&
+        data == other.data &&
+        equalSets(set, other.set);
+  }
+
+  @override
+  String toString() => 'ModularName(kind=$kind,data=$data,value=${value?.key})';
+}
+
+enum ModularExpressionKind {
+  globalObjectForLibrary,
+  globalObjectForClass,
+  globalObjectForType,
+  globalObjectForMember,
+  constant,
+  embeddedGlobalAccess,
+}
+
+class ModularExpression extends js.DeferredExpression
+    implements js.AstContainer {
+  static const String tag = 'modular-expression';
+
+  final ModularExpressionKind kind;
+  final Object data;
+  js.Expression _value;
+
+  ModularExpression(this.kind, this.data);
+
+  factory ModularExpression.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    ModularExpressionKind kind = source.readEnum(ModularExpressionKind.values);
+    Object data;
+    switch (kind) {
+      case ModularExpressionKind.globalObjectForLibrary:
+        data = source.readLibrary();
+        break;
+      case ModularExpressionKind.globalObjectForClass:
+        data = source.readClass();
+        break;
+      case ModularExpressionKind.globalObjectForType:
+        bool dataIsClassEntity = source.readBool();
+        if (dataIsClassEntity) {
+          data = source.readClass();
+        } else {
+          data = source.readTypedef();
+        }
+        break;
+      case ModularExpressionKind.globalObjectForMember:
+        data = source.readMember();
+        break;
+      case ModularExpressionKind.constant:
+        data = source.readConstant();
+        break;
+      case ModularExpressionKind.embeddedGlobalAccess:
+        data = source.readString();
+        break;
+    }
+    source.end(tag);
+    return new ModularExpression(kind, data);
+  }
+
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeEnum(kind);
+    switch (kind) {
+      case ModularExpressionKind.globalObjectForLibrary:
+        sink.writeLibrary(data);
+        break;
+      case ModularExpressionKind.globalObjectForClass:
+        sink.writeClass(data);
+        break;
+      case ModularExpressionKind.globalObjectForType:
+        sink.writeBool(data is ClassEntity);
+        if (data is ClassEntity) {
+          sink.writeClass(data);
+        } else {
+          sink.writeTypedef(data);
+        }
+        break;
+      case ModularExpressionKind.globalObjectForMember:
+        sink.writeMember(data);
+        break;
+      case ModularExpressionKind.constant:
+        sink.writeConstant(data);
+        break;
+      case ModularExpressionKind.embeddedGlobalAccess:
+        sink.writeString(data);
+        break;
+    }
+    sink.end(tag);
+  }
+
+  @override
+  js.Expression get value {
+    assert(_value != null);
+    return _value;
+  }
+
+  void set value(js.Expression node) {
+    assert(_value == null);
+    assert(node != null);
+    _value = node.withSourceInformation(sourceInformation);
+  }
+
+  @override
+  int get precedenceLevel => _value?.precedenceLevel ?? js.PRIMARY;
+
+  @override
+  Iterable<js.Node> get containedNodes {
+    return _value != null ? [_value] : const [];
+  }
+
+  @override
+  int get hashCode {
+    return Hashing.objectsHash(kind, data);
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return other is ModularExpression &&
+        kind == other.kind &&
+        data == other.data;
+  }
+
+  @override
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.write('ModularExpression(kind=$kind,data=');
+    if (data is ConstantValue) {
+      sb.write((data as ConstantValue).toStructuredText());
+    } else {
+      sb.write(data);
+    }
+    sb.write(',value=$_value)');
+    return sb.toString();
+  }
+}
+
+enum JsNodeKind {
+  comment,
+  await,
+  regExpLiteral,
+  property,
+  objectInitializer,
+  arrayHole,
+  arrayInitializer,
+  parentheses,
+  modularName,
+  asyncName,
+  stringBackedName,
+  stringConcatenation,
+  literalNull,
+  literalNumber,
+  literalString,
+  literalStringFromName,
+  literalBool,
+  modularExpression,
+  function,
+  namedFunction,
+  access,
+  parameter,
+  variableDeclaration,
+  thisExpression,
+  variableUse,
+  postfix,
+  prefix,
+  binary,
+  callExpression,
+  newExpression,
+  conditional,
+  variableInitialization,
+  assignment,
+  variableDeclarationList,
+  literalExpression,
+  dartYield,
+  literalStatement,
+  labeledStatement,
+  functionDeclaration,
+  switchDefault,
+  switchCase,
+  switchStatement,
+  catchClause,
+  tryStatement,
+  throwStatement,
+  returnStatement,
+  breakStatement,
+  continueStatement,
+  doStatement,
+  whileStatement,
+  forInStatement,
+  forStatement,
+  ifStatement,
+  emptyStatement,
+  expressionStatement,
+  block,
+  program,
+}
+
+/// Tags used for debugging serialization/deserialization boundary mismatches.
+class JsNodeTags {
+  static const String tag = 'js-node';
+  static const String comment = 'js-comment';
+  static const String await = 'js-await';
+  static const String regExpLiteral = 'js-regExpLiteral';
+  static const String property = 'js-property';
+  static const String objectInitializer = 'js-objectInitializer';
+  static const String arrayHole = 'js-arrayHole';
+  static const String arrayInitializer = 'js-arrayInitializer';
+  static const String parentheses = 'js-parentheses';
+  static const String modularName = 'js-modularName';
+  static const String asyncName = 'js-asyncName';
+  static const String stringBackedName = 'js-stringBackedName';
+  static const String stringConcatenation = 'js-stringConcatenation';
+  static const String literalNull = 'js-literalNull';
+  static const String literalNumber = 'js-literalNumber';
+  static const String literalString = 'js-literalString';
+  static const String literalStringFromName = 'js-literalStringFromName';
+  static const String literalBool = 'js-literalBool';
+  static const String modularExpression = 'js-modularExpression';
+  static const String function = 'js-function';
+  static const String namedFunction = 'js-namedFunction';
+  static const String access = 'js-access';
+  static const String parameter = 'js-parameter';
+  static const String variableDeclaration = 'js-variableDeclaration';
+  static const String thisExpression = 'js-thisExpression';
+  static const String variableUse = 'js-variableUse';
+  static const String postfix = 'js-postfix';
+  static const String prefix = 'js-prefix';
+  static const String binary = 'js-binary';
+  static const String callExpression = 'js-callExpression';
+  static const String newExpression = 'js-newExpression';
+  static const String conditional = 'js-conditional';
+  static const String variableInitialization = 'js-variableInitialization';
+  static const String assignment = 'js-assignment';
+  static const String variableDeclarationList = 'js-variableDeclarationList';
+  static const String literalExpression = 'js-literalExpression';
+  static const String dartYield = 'js-dartYield';
+  static const String literalStatement = 'js-literalStatement';
+  static const String labeledStatement = 'js-labeledStatement';
+  static const String functionDeclaration = 'js-functionDeclaration';
+  static const String switchDefault = 'js-switchDefault';
+  static const String switchCase = 'js-switchCase';
+  static const String switchStatement = 'js-switchStatement';
+  static const String catchClause = 'js-catchClause';
+  static const String tryStatement = 'js-tryStatement';
+  static const String throwStatement = 'js-throwStatement';
+  static const String returnStatement = 'js-returnStatement';
+  static const String breakStatement = 'js-breakStatement';
+  static const String continueStatement = 'js-continueStatement';
+  static const String doStatement = 'js-doStatement';
+  static const String whileStatement = 'js-whileStatement';
+  static const String forInStatement = 'js-forInStatement';
+  static const String forStatement = 'js-forStatement';
+  static const String ifStatement = 'js-ifStatement';
+  static const String emptyStatement = 'js-emptyStatement';
+  static const String expressionStatement = 'js-expressionStatement';
+  static const String block = 'js-block';
+  static const String program = 'js-program';
+}
+
+/// Visitor that serializes a [js.Node] into a [DataSink].
+class JsNodeSerializer implements js.NodeVisitor<void> {
+  final DataSink sink;
+
+  JsNodeSerializer._(this.sink);
+
+  static void writeToDataSink(DataSink sink, js.Node node) {
+    sink.begin(JsNodeTags.tag);
+    JsNodeSerializer serializer = new JsNodeSerializer._(sink);
+    serializer.visit(node);
+    sink.end(JsNodeTags.tag);
+  }
+
+  void visit(js.Node node, {bool allowNull: false}) {
+    if (allowNull) {
+      sink.writeBool(node != null);
+      if (node != null) {
+        node.accept(this);
+      }
+    } else {
+      node.accept(this);
+    }
+  }
+
+  void visitList(Iterable<js.Node> nodes) {
+    sink.writeList(nodes, visit);
+  }
+
+  void _writeInfo(js.Node node) {
+    sink.writeCached<SourceInformation>(node.sourceInformation,
+        (SourceInformation sourceInformation) {
+      SourceInformation.writeToDataSink(sink, sourceInformation);
+    });
+  }
+
+  @override
+  void visitInterpolatedDeclaration(js.InterpolatedDeclaration node) {
+    throw new UnsupportedError('JsNodeSerializer.visitInterpolatedDeclaration');
+  }
+
+  @override
+  void visitInterpolatedStatement(js.InterpolatedStatement node) {
+    throw new UnsupportedError('JsNodeSerializer.visitInterpolatedStatement');
+  }
+
+  @override
+  void visitInterpolatedSelector(js.InterpolatedSelector node) {
+    throw new UnsupportedError('JsNodeSerializer.visitInterpolatedDeclaration');
+  }
+
+  @override
+  void visitInterpolatedParameter(js.InterpolatedParameter node) {
+    throw new UnsupportedError('JsNodeSerializer.visitInterpolatedParameter');
+  }
+
+  @override
+  void visitInterpolatedLiteral(js.InterpolatedLiteral node) {
+    throw new UnsupportedError('JsNodeSerializer.visitInterpolatedLiteral');
+  }
+
+  @override
+  void visitInterpolatedExpression(js.InterpolatedExpression node) {
+    throw new UnsupportedError('JsNodeSerializer.visitInterpolatedExpression');
+  }
+
+  @override
+  void visitComment(js.Comment node) {
+    sink.writeEnum(JsNodeKind.comment);
+    sink.begin(JsNodeTags.comment);
+    sink.writeString(node.comment);
+    sink.end(JsNodeTags.comment);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitAwait(js.Await node) {
+    sink.writeEnum(JsNodeKind.await);
+    sink.begin(JsNodeTags.await);
+    visit(node.expression);
+    sink.end(JsNodeTags.await);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitRegExpLiteral(js.RegExpLiteral node) {
+    sink.writeEnum(JsNodeKind.regExpLiteral);
+    sink.begin(JsNodeTags.regExpLiteral);
+    sink.writeString(node.pattern);
+    sink.end(JsNodeTags.regExpLiteral);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitProperty(js.Property node) {
+    sink.writeEnum(JsNodeKind.property);
+    sink.begin(JsNodeTags.property);
+    visit(node.name);
+    visit(node.value);
+    sink.end(JsNodeTags.property);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitObjectInitializer(js.ObjectInitializer node) {
+    sink.writeEnum(JsNodeKind.objectInitializer);
+    sink.begin(JsNodeTags.objectInitializer);
+    visitList(node.properties);
+    sink.writeBool(node.isOneLiner);
+    sink.end(JsNodeTags.objectInitializer);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitArrayHole(js.ArrayHole node) {
+    sink.writeEnum(JsNodeKind.arrayHole);
+    sink.begin(JsNodeTags.arrayHole);
+    sink.end(JsNodeTags.arrayHole);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitArrayInitializer(js.ArrayInitializer node) {
+    sink.writeEnum(JsNodeKind.arrayInitializer);
+    sink.begin(JsNodeTags.arrayInitializer);
+    visitList(node.elements);
+    sink.end(JsNodeTags.arrayInitializer);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitParentheses(js.Parentheses node) {
+    sink.writeEnum(JsNodeKind.parentheses);
+    sink.begin(JsNodeTags.parentheses);
+    visit(node.enclosed);
+    sink.end(JsNodeTags.parentheses);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitName(js.Name node) {
+    if (node is ModularName) {
+      sink.writeEnum(JsNodeKind.modularName);
+      sink.begin(JsNodeTags.modularName);
+      node.writeToDataSink(sink);
+      sink.end(JsNodeTags.modularName);
+      _writeInfo(node);
+    } else if (node is AsyncName) {
+      sink.writeEnum(JsNodeKind.asyncName);
+      sink.begin(JsNodeTags.asyncName);
+      visit(node.prefix);
+      visit(node.base);
+      sink.end(JsNodeTags.asyncName);
+      _writeInfo(node);
+    } else if (node is StringBackedName) {
+      sink.writeEnum(JsNodeKind.stringBackedName);
+      sink.begin(JsNodeTags.stringBackedName);
+      sink.writeString(node.name);
+      sink.end(JsNodeTags.stringBackedName);
+      _writeInfo(node);
+    } else {
+      throw new UnsupportedError(
+          'Unexpected deferred expression: ${node.runtimeType}.');
+    }
+  }
+
+  @override
+  void visitStringConcatenation(js.StringConcatenation node) {
+    sink.writeEnum(JsNodeKind.stringConcatenation);
+    sink.begin(JsNodeTags.stringConcatenation);
+    visitList(node.parts);
+    sink.end(JsNodeTags.stringConcatenation);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitLiteralNull(js.LiteralNull node) {
+    sink.writeEnum(JsNodeKind.literalNull);
+    sink.begin(JsNodeTags.literalNull);
+    sink.end(JsNodeTags.literalNull);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitLiteralNumber(js.LiteralNumber node) {
+    sink.writeEnum(JsNodeKind.literalNumber);
+    sink.begin(JsNodeTags.literalNumber);
+    sink.writeString(node.value);
+    sink.end(JsNodeTags.literalNumber);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitLiteralString(js.LiteralString node) {
+    if (node is js.LiteralStringFromName) {
+      sink.writeEnum(JsNodeKind.literalStringFromName);
+      sink.begin(JsNodeTags.literalStringFromName);
+      visit(node.name);
+      sink.end(JsNodeTags.literalStringFromName);
+    } else {
+      sink.writeEnum(JsNodeKind.literalString);
+      sink.begin(JsNodeTags.literalString);
+      sink.writeString(node.value);
+      sink.end(JsNodeTags.literalString);
+    }
+    _writeInfo(node);
+  }
+
+  @override
+  void visitLiteralBool(js.LiteralBool node) {
+    sink.writeEnum(JsNodeKind.literalBool);
+    sink.begin(JsNodeTags.literalBool);
+    sink.writeBool(node.value);
+    sink.end(JsNodeTags.literalBool);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitDeferredString(js.DeferredString node) {
+    throw new UnsupportedError('JsNodeSerializer.visitDeferredString');
+  }
+
+  @override
+  void visitDeferredNumber(js.DeferredNumber node) {
+    throw new UnsupportedError('JsNodeSerializer.visitDeferredNumber');
+  }
+
+  @override
+  void visitDeferredExpression(js.DeferredExpression node) {
+    if (node is ModularExpression) {
+      sink.writeEnum(JsNodeKind.modularExpression);
+      sink.begin(JsNodeTags.modularExpression);
+      node.writeToDataSink(sink);
+      sink.end(JsNodeTags.modularExpression);
+      _writeInfo(node);
+    } else {
+      throw new UnsupportedError(
+          'Unexpected deferred expression: ${node.runtimeType}.');
+    }
+  }
+
+  @override
+  void visitFun(js.Fun node) {
+    sink.writeEnum(JsNodeKind.function);
+    sink.begin(JsNodeTags.function);
+    visitList(node.params);
+    visit(node.body);
+    sink.writeEnum(node.asyncModifier);
+    sink.end(JsNodeTags.function);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitNamedFunction(js.NamedFunction node) {
+    sink.writeEnum(JsNodeKind.namedFunction);
+    sink.begin(JsNodeTags.namedFunction);
+    visit(node.name);
+    visit(node.function);
+    sink.end(JsNodeTags.namedFunction);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitAccess(js.PropertyAccess node) {
+    sink.writeEnum(JsNodeKind.access);
+    sink.begin(JsNodeTags.access);
+    visit(node.receiver);
+    visit(node.selector);
+    sink.end(JsNodeTags.access);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitParameter(js.Parameter node) {
+    sink.writeEnum(JsNodeKind.parameter);
+    sink.begin(JsNodeTags.parameter);
+    sink.writeString(node.name);
+    sink.end(JsNodeTags.parameter);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitVariableDeclaration(js.VariableDeclaration node) {
+    sink.writeEnum(JsNodeKind.variableDeclaration);
+    sink.begin(JsNodeTags.variableDeclaration);
+    sink.writeString(node.name);
+    sink.writeBool(node.allowRename);
+    sink.end(JsNodeTags.variableDeclaration);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitThis(js.This node) {
+    sink.writeEnum(JsNodeKind.thisExpression);
+    sink.begin(JsNodeTags.thisExpression);
+    sink.end(JsNodeTags.thisExpression);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitVariableUse(js.VariableUse node) {
+    sink.writeEnum(JsNodeKind.variableUse);
+    sink.begin(JsNodeTags.variableUse);
+    sink.writeString(node.name);
+    sink.end(JsNodeTags.variableUse);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitPostfix(js.Postfix node) {
+    sink.writeEnum(JsNodeKind.postfix);
+    sink.begin(JsNodeTags.postfix);
+    sink.writeString(node.op);
+    visit(node.argument);
+    sink.end(JsNodeTags.postfix);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitPrefix(js.Prefix node) {
+    sink.writeEnum(JsNodeKind.prefix);
+    sink.begin(JsNodeTags.prefix);
+    sink.writeString(node.op);
+    visit(node.argument);
+    sink.end(JsNodeTags.prefix);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitBinary(js.Binary node) {
+    sink.writeEnum(JsNodeKind.binary);
+    sink.begin(JsNodeTags.binary);
+    sink.writeString(node.op);
+    visit(node.left);
+    visit(node.right);
+    sink.end(JsNodeTags.binary);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitCall(js.Call node) {
+    sink.writeEnum(JsNodeKind.callExpression);
+    sink.begin(JsNodeTags.callExpression);
+    visit(node.target);
+    visitList(node.arguments);
+    sink.end(JsNodeTags.callExpression);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitNew(js.New node) {
+    sink.writeEnum(JsNodeKind.newExpression);
+    sink.begin(JsNodeTags.newExpression);
+    visit(node.target);
+    visitList(node.arguments);
+    sink.end(JsNodeTags.newExpression);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitConditional(js.Conditional node) {
+    sink.writeEnum(JsNodeKind.conditional);
+    sink.begin(JsNodeTags.conditional);
+    visit(node.condition);
+    visit(node.then);
+    visit(node.otherwise);
+    sink.end(JsNodeTags.conditional);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitVariableInitialization(js.VariableInitialization node) {
+    sink.writeEnum(JsNodeKind.variableInitialization);
+    sink.begin(JsNodeTags.variableInitialization);
+    visit(node.declaration);
+    visit(node.value, allowNull: true);
+    sink.end(JsNodeTags.variableInitialization);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitAssignment(js.Assignment node) {
+    sink.writeEnum(JsNodeKind.assignment);
+    sink.begin(JsNodeTags.assignment);
+    visit(node.leftHandSide);
+    sink.writeStringOrNull(node.op);
+    visit(node.value);
+    sink.end(JsNodeTags.assignment);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitVariableDeclarationList(js.VariableDeclarationList node) {
+    sink.writeEnum(JsNodeKind.variableDeclarationList);
+    sink.begin(JsNodeTags.variableDeclarationList);
+    visitList(node.declarations);
+    sink.writeBool(node.indentSplits);
+    sink.end(JsNodeTags.variableDeclarationList);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitLiteralExpression(js.LiteralExpression node) {
+    sink.writeEnum(JsNodeKind.literalExpression);
+    sink.begin(JsNodeTags.literalExpression);
+    sink.writeString(node.template);
+    visitList(node.inputs);
+    sink.end(JsNodeTags.literalExpression);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitDartYield(js.DartYield node) {
+    sink.writeEnum(JsNodeKind.dartYield);
+    sink.begin(JsNodeTags.dartYield);
+    visit(node.expression);
+    sink.writeBool(node.hasStar);
+    sink.end(JsNodeTags.dartYield);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitLiteralStatement(js.LiteralStatement node) {
+    sink.writeEnum(JsNodeKind.literalStatement);
+    sink.begin(JsNodeTags.literalStatement);
+    sink.writeString(node.code);
+    sink.end(JsNodeTags.literalStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitLabeledStatement(js.LabeledStatement node) {
+    sink.writeEnum(JsNodeKind.labeledStatement);
+    sink.begin(JsNodeTags.labeledStatement);
+    sink.writeString(node.label);
+    visit(node.body);
+    sink.end(JsNodeTags.labeledStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitFunctionDeclaration(js.FunctionDeclaration node) {
+    sink.writeEnum(JsNodeKind.functionDeclaration);
+    sink.begin(JsNodeTags.functionDeclaration);
+    visit(node.name);
+    visit(node.function);
+    sink.end(JsNodeTags.functionDeclaration);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitDefault(js.Default node) {
+    sink.writeEnum(JsNodeKind.switchDefault);
+    sink.begin(JsNodeTags.switchDefault);
+    visit(node.body);
+    sink.end(JsNodeTags.switchDefault);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitCase(js.Case node) {
+    sink.writeEnum(JsNodeKind.switchCase);
+    sink.begin(JsNodeTags.switchCase);
+    visit(node.expression);
+    visit(node.body);
+    sink.end(JsNodeTags.switchCase);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitSwitch(js.Switch node) {
+    sink.writeEnum(JsNodeKind.switchStatement);
+    sink.begin(JsNodeTags.switchStatement);
+    visit(node.key);
+    visitList(node.cases);
+    sink.end(JsNodeTags.switchStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitCatch(js.Catch node) {
+    sink.writeEnum(JsNodeKind.catchClause);
+    sink.begin(JsNodeTags.catchClause);
+    visit(node.declaration);
+    visit(node.body);
+    sink.end(JsNodeTags.catchClause);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitTry(js.Try node) {
+    sink.writeEnum(JsNodeKind.tryStatement);
+    sink.begin(JsNodeTags.tryStatement);
+    visit(node.body);
+    visit(node.catchPart, allowNull: true);
+    visit(node.finallyPart, allowNull: true);
+    sink.end(JsNodeTags.tryStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitThrow(js.Throw node) {
+    sink.writeEnum(JsNodeKind.throwStatement);
+    sink.begin(JsNodeTags.throwStatement);
+    visit(node.expression);
+    sink.end(JsNodeTags.throwStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitReturn(js.Return node) {
+    sink.writeEnum(JsNodeKind.returnStatement);
+    sink.begin(JsNodeTags.returnStatement);
+    visit(node.value, allowNull: true);
+    sink.end(JsNodeTags.returnStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitBreak(js.Break node) {
+    sink.writeEnum(JsNodeKind.breakStatement);
+    sink.begin(JsNodeTags.breakStatement);
+    sink.writeStringOrNull(node.targetLabel);
+    sink.end(JsNodeTags.breakStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitContinue(js.Continue node) {
+    sink.writeEnum(JsNodeKind.continueStatement);
+    sink.begin(JsNodeTags.continueStatement);
+    sink.writeStringOrNull(node.targetLabel);
+    sink.end(JsNodeTags.continueStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitDo(js.Do node) {
+    sink.writeEnum(JsNodeKind.doStatement);
+    sink.begin(JsNodeTags.doStatement);
+    visit(node.body);
+    visit(node.condition);
+    sink.end(JsNodeTags.doStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitWhile(js.While node) {
+    sink.writeEnum(JsNodeKind.whileStatement);
+    sink.begin(JsNodeTags.whileStatement);
+    visit(node.condition);
+    visit(node.body);
+    sink.end(JsNodeTags.whileStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitForIn(js.ForIn node) {
+    sink.writeEnum(JsNodeKind.forInStatement);
+    sink.begin(JsNodeTags.forInStatement);
+    visit(node.leftHandSide);
+    visit(node.object);
+    visit(node.body);
+    sink.end(JsNodeTags.forInStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitFor(js.For node) {
+    sink.writeEnum(JsNodeKind.forStatement);
+    sink.begin(JsNodeTags.forStatement);
+    visit(node.init, allowNull: true);
+    visit(node.condition, allowNull: true);
+    visit(node.update, allowNull: true);
+    visit(node.body);
+    sink.end(JsNodeTags.forStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitIf(js.If node) {
+    sink.writeEnum(JsNodeKind.ifStatement);
+    sink.begin(JsNodeTags.ifStatement);
+    visit(node.condition);
+    visit(node.then);
+    visit(node.otherwise);
+    sink.end(JsNodeTags.ifStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitEmptyStatement(js.EmptyStatement node) {
+    sink.writeEnum(JsNodeKind.emptyStatement);
+    sink.begin(JsNodeTags.emptyStatement);
+    sink.end(JsNodeTags.emptyStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitExpressionStatement(js.ExpressionStatement node) {
+    sink.writeEnum(JsNodeKind.expressionStatement);
+    sink.begin(JsNodeTags.expressionStatement);
+    visit(node.expression);
+    sink.end(JsNodeTags.expressionStatement);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitBlock(js.Block node) {
+    sink.writeEnum(JsNodeKind.block);
+    sink.begin(JsNodeTags.block);
+    visitList(node.statements);
+    sink.end(JsNodeTags.block);
+    _writeInfo(node);
+  }
+
+  @override
+  void visitProgram(js.Program node) {
+    sink.writeEnum(JsNodeKind.program);
+    sink.begin(JsNodeTags.program);
+    visitList(node.body);
+    sink.end(JsNodeTags.program);
+    _writeInfo(node);
+  }
+}
+
+/// Helper class that deserializes a [js.Node] from [DataSource].
+///
+/// Deserialized [ModularName]s and [ModularExpression]s are collected in the
+/// [modularNames] and [modularExpressions] lists.
+class JsNodeDeserializer {
+  final DataSource source;
+  final List<ModularName> modularNames;
+  final List<ModularExpression> modularExpressions;
+
+  JsNodeDeserializer._(this.source, this.modularNames, this.modularExpressions);
+
+  static js.Node readFromDataSource(
+      DataSource source,
+      List<ModularName> modularNames,
+      List<ModularExpression> modularExpressions) {
+    source.begin(JsNodeTags.tag);
+    JsNodeDeserializer deserializer =
+        new JsNodeDeserializer._(source, modularNames, modularExpressions);
+    js.Node node = deserializer.read();
+    source.end(JsNodeTags.tag);
+    return node;
+  }
+
+  T read<T extends js.Node>({bool allowNull: false}) {
+    if (allowNull) {
+      bool hasValue = source.readBool();
+      if (!hasValue) return null;
+    }
+    JsNodeKind kind = source.readEnum(JsNodeKind.values);
+    js.Node node;
+    switch (kind) {
+      case JsNodeKind.comment:
+        source.begin(JsNodeTags.comment);
+        node = new js.Comment(source.readString());
+        source.end(JsNodeTags.comment);
+        break;
+      case JsNodeKind.await:
+        source.begin(JsNodeTags.await);
+        node = new js.Await(read());
+        source.end(JsNodeTags.await);
+        break;
+      case JsNodeKind.regExpLiteral:
+        source.begin(JsNodeTags.regExpLiteral);
+        node = new js.RegExpLiteral(source.readString());
+        source.end(JsNodeTags.regExpLiteral);
+        break;
+      case JsNodeKind.property:
+        source.begin(JsNodeTags.property);
+        js.Expression name = read();
+        js.Expression value = read();
+        node = new js.Property(name, value);
+        source.end(JsNodeTags.property);
+        break;
+      case JsNodeKind.objectInitializer:
+        source.begin(JsNodeTags.objectInitializer);
+        List<js.Property> properties = readList();
+        bool isOneLiner = source.readBool();
+        node = new js.ObjectInitializer(properties, isOneLiner: isOneLiner);
+        source.end(JsNodeTags.objectInitializer);
+        break;
+      case JsNodeKind.arrayHole:
+        source.begin(JsNodeTags.arrayHole);
+        node = new js.ArrayHole();
+        source.end(JsNodeTags.arrayHole);
+        break;
+      case JsNodeKind.arrayInitializer:
+        source.begin(JsNodeTags.arrayInitializer);
+        List<js.Expression> elements = readList();
+        node = new js.ArrayInitializer(elements);
+        source.end(JsNodeTags.arrayInitializer);
+        break;
+      case JsNodeKind.parentheses:
+        source.begin(JsNodeTags.parentheses);
+        node = new js.Parentheses(read());
+        source.end(JsNodeTags.parentheses);
+        break;
+      case JsNodeKind.modularName:
+        source.begin(JsNodeTags.modularName);
+        ModularName modularName = ModularName.readFromDataSource(source);
+        modularNames.add(modularName);
+        node = modularName;
+        source.end(JsNodeTags.modularName);
+        break;
+      case JsNodeKind.asyncName:
+        source.begin(JsNodeTags.asyncName);
+        js.Name prefix = read();
+        js.Name base = read();
+        node = new AsyncName(prefix, base);
+        source.end(JsNodeTags.asyncName);
+        break;
+      case JsNodeKind.stringBackedName:
+        source.begin(JsNodeTags.stringBackedName);
+        node = new StringBackedName(source.readString());
+        source.end(JsNodeTags.stringBackedName);
+        break;
+      case JsNodeKind.stringConcatenation:
+        source.begin(JsNodeTags.stringConcatenation);
+        List<js.Literal> parts = readList();
+        node = new js.StringConcatenation(parts);
+        source.end(JsNodeTags.stringConcatenation);
+        break;
+      case JsNodeKind.literalNull:
+        source.begin(JsNodeTags.literalNull);
+        node = new js.LiteralNull();
+        source.end(JsNodeTags.literalNull);
+        break;
+      case JsNodeKind.literalNumber:
+        source.begin(JsNodeTags.literalNumber);
+        node = new js.LiteralNumber(source.readString());
+        source.end(JsNodeTags.literalNumber);
+        break;
+      case JsNodeKind.literalString:
+        source.begin(JsNodeTags.literalString);
+        node = new js.LiteralString(source.readString());
+        source.end(JsNodeTags.literalString);
+        break;
+      case JsNodeKind.literalStringFromName:
+        source.begin(JsNodeTags.literalStringFromName);
+        js.Name name = read();
+        node = new js.LiteralStringFromName(name);
+        source.end(JsNodeTags.literalStringFromName);
+        break;
+      case JsNodeKind.literalBool:
+        source.begin(JsNodeTags.literalBool);
+        node = new js.LiteralBool(source.readBool());
+        source.end(JsNodeTags.literalBool);
+        break;
+      case JsNodeKind.modularExpression:
+        source.begin(JsNodeTags.modularExpression);
+        ModularExpression modularExpression =
+            ModularExpression.readFromDataSource(source);
+        modularExpressions.add(modularExpression);
+        node = modularExpression;
+        source.end(JsNodeTags.modularExpression);
+        break;
+      case JsNodeKind.function:
+        source.begin(JsNodeTags.function);
+        List<js.Parameter> params = readList();
+        js.Block body = read();
+        js.AsyncModifier asyncModifier =
+            source.readEnum(js.AsyncModifier.values);
+        node = new js.Fun(params, body, asyncModifier: asyncModifier);
+        source.end(JsNodeTags.function);
+        break;
+      case JsNodeKind.namedFunction:
+        source.begin(JsNodeTags.namedFunction);
+        js.Declaration name = read();
+        js.Fun function = read();
+        node = new js.NamedFunction(name, function);
+        source.end(JsNodeTags.namedFunction);
+        break;
+      case JsNodeKind.access:
+        source.begin(JsNodeTags.access);
+        js.Expression receiver = read();
+        js.Expression selector = read();
+        node = new js.PropertyAccess(receiver, selector);
+        source.end(JsNodeTags.access);
+        break;
+      case JsNodeKind.parameter:
+        source.begin(JsNodeTags.parameter);
+        node = new js.Parameter(source.readString());
+        source.end(JsNodeTags.parameter);
+        break;
+      case JsNodeKind.variableDeclaration:
+        source.begin(JsNodeTags.variableDeclaration);
+        String name = source.readString();
+        bool allowRename = source.readBool();
+        node = new js.VariableDeclaration(name, allowRename: allowRename);
+        source.end(JsNodeTags.variableDeclaration);
+        break;
+      case JsNodeKind.thisExpression:
+        source.begin(JsNodeTags.thisExpression);
+        node = new js.This();
+        source.end(JsNodeTags.thisExpression);
+        break;
+      case JsNodeKind.variableUse:
+        source.begin(JsNodeTags.variableUse);
+        node = new js.VariableUse(source.readString());
+        source.end(JsNodeTags.variableUse);
+        break;
+      case JsNodeKind.postfix:
+        source.begin(JsNodeTags.postfix);
+        String op = source.readString();
+        js.Expression argument = read();
+        node = new js.Postfix(op, argument);
+        source.end(JsNodeTags.postfix);
+        break;
+      case JsNodeKind.prefix:
+        source.begin(JsNodeTags.prefix);
+        String op = source.readString();
+        js.Expression argument = read();
+        node = new js.Prefix(op, argument);
+        source.end(JsNodeTags.prefix);
+        break;
+      case JsNodeKind.binary:
+        source.begin(JsNodeTags.binary);
+        String op = source.readString();
+        js.Expression left = read();
+        js.Expression right = read();
+        node = new js.Binary(op, left, right);
+        source.end(JsNodeTags.binary);
+        break;
+      case JsNodeKind.callExpression:
+        source.begin(JsNodeTags.callExpression);
+        js.Expression target = read();
+        List<js.Expression> arguments = readList();
+        node = new js.Call(target, arguments);
+        source.end(JsNodeTags.callExpression);
+        break;
+      case JsNodeKind.newExpression:
+        source.begin(JsNodeTags.newExpression);
+        js.Expression cls = read();
+        List<js.Expression> arguments = readList();
+        node = new js.New(cls, arguments);
+        source.end(JsNodeTags.newExpression);
+        break;
+      case JsNodeKind.conditional:
+        source.begin(JsNodeTags.conditional);
+        js.Expression condition = read();
+        js.Expression then = read();
+        js.Expression otherwise = read();
+        node = new js.Conditional(condition, then, otherwise);
+        source.end(JsNodeTags.conditional);
+        break;
+      case JsNodeKind.variableInitialization:
+        source.begin(JsNodeTags.variableInitialization);
+        js.Declaration declaration = read();
+        js.Expression value = source.readValueOrNull(read);
+        node = new js.VariableInitialization(declaration, value);
+        source.end(JsNodeTags.variableInitialization);
+        break;
+      case JsNodeKind.assignment:
+        source.begin(JsNodeTags.assignment);
+        js.Expression leftHandSide = read();
+        String op = source.readStringOrNull();
+        js.Expression value = read();
+        node = new js.Assignment.compound(leftHandSide, op, value);
+        source.end(JsNodeTags.assignment);
+        break;
+      case JsNodeKind.variableDeclarationList:
+        source.begin(JsNodeTags.variableDeclarationList);
+        List<js.VariableInitialization> declarations = readList();
+        bool indentSplits = source.readBool();
+        node = new js.VariableDeclarationList(declarations,
+            indentSplits: indentSplits);
+        source.end(JsNodeTags.variableDeclarationList);
+        break;
+      case JsNodeKind.literalExpression:
+        source.begin(JsNodeTags.literalExpression);
+        String template = source.readString();
+        List<js.Expression> inputs = readList();
+        node = new js.LiteralExpression.withData(template, inputs);
+        source.end(JsNodeTags.literalExpression);
+        break;
+      case JsNodeKind.dartYield:
+        source.begin(JsNodeTags.dartYield);
+        js.Expression expression = read();
+        bool hasStar = source.readBool();
+        node = new js.DartYield(expression, hasStar);
+        source.end(JsNodeTags.dartYield);
+        break;
+      case JsNodeKind.literalStatement:
+        source.begin(JsNodeTags.literalStatement);
+        node = new js.LiteralStatement(source.readString());
+        source.end(JsNodeTags.literalStatement);
+        break;
+      case JsNodeKind.labeledStatement:
+        source.begin(JsNodeTags.labeledStatement);
+        String label = source.readString();
+        js.Statement body = read();
+        node = new js.LabeledStatement(label, body);
+        source.end(JsNodeTags.labeledStatement);
+        break;
+      case JsNodeKind.functionDeclaration:
+        source.begin(JsNodeTags.functionDeclaration);
+        js.Declaration name = read();
+        js.Fun function = read();
+        node = new js.FunctionDeclaration(name, function);
+        source.end(JsNodeTags.functionDeclaration);
+        break;
+      case JsNodeKind.switchDefault:
+        source.begin(JsNodeTags.switchDefault);
+        js.Block body = read();
+        node = new js.Default(body);
+        source.end(JsNodeTags.switchDefault);
+        break;
+      case JsNodeKind.switchCase:
+        source.begin(JsNodeTags.switchCase);
+        js.Expression expression = read();
+        js.Block body = read();
+        node = new js.Case(expression, body);
+        source.end(JsNodeTags.switchCase);
+        break;
+      case JsNodeKind.switchStatement:
+        source.begin(JsNodeTags.switchStatement);
+        js.Expression key = read();
+        List<js.SwitchClause> cases = readList();
+        node = new js.Switch(key, cases);
+        source.end(JsNodeTags.switchStatement);
+        break;
+      case JsNodeKind.catchClause:
+        source.begin(JsNodeTags.catchClause);
+        js.Declaration declaration = read();
+        js.Block body = read();
+        node = new js.Catch(declaration, body);
+        source.end(JsNodeTags.catchClause);
+        break;
+      case JsNodeKind.tryStatement:
+        source.begin(JsNodeTags.tryStatement);
+        js.Block body = read();
+        js.Catch catchPart = source.readValueOrNull(read);
+        js.Block finallyPart = source.readValueOrNull(read);
+        node = new js.Try(body, catchPart, finallyPart);
+        source.end(JsNodeTags.tryStatement);
+        break;
+      case JsNodeKind.throwStatement:
+        source.begin(JsNodeTags.throwStatement);
+        js.Expression expression = read();
+        node = new js.Throw(expression);
+        source.end(JsNodeTags.throwStatement);
+        break;
+      case JsNodeKind.returnStatement:
+        source.begin(JsNodeTags.returnStatement);
+        js.Expression value = source.readValueOrNull(read);
+        node = new js.Return(value);
+        source.end(JsNodeTags.returnStatement);
+        break;
+      case JsNodeKind.breakStatement:
+        source.begin(JsNodeTags.breakStatement);
+        String targetLabel = source.readStringOrNull();
+        node = new js.Break(targetLabel);
+        source.end(JsNodeTags.breakStatement);
+        break;
+      case JsNodeKind.continueStatement:
+        source.begin(JsNodeTags.continueStatement);
+        String targetLabel = source.readStringOrNull();
+        node = new js.Continue(targetLabel);
+        source.end(JsNodeTags.continueStatement);
+        break;
+      case JsNodeKind.doStatement:
+        source.begin(JsNodeTags.doStatement);
+        js.Statement body = read();
+        js.Expression condition = read();
+        node = new js.Do(body, condition);
+        source.end(JsNodeTags.doStatement);
+        break;
+      case JsNodeKind.whileStatement:
+        source.begin(JsNodeTags.whileStatement);
+        js.Expression condition = read();
+        js.Statement body = read();
+        node = new js.While(condition, body);
+        source.end(JsNodeTags.whileStatement);
+        break;
+      case JsNodeKind.forInStatement:
+        source.begin(JsNodeTags.forInStatement);
+        js.Expression leftHandSide = read();
+        js.Expression object = read();
+        js.Statement body = read();
+        node = new js.ForIn(leftHandSide, object, body);
+        source.end(JsNodeTags.forInStatement);
+        break;
+      case JsNodeKind.forStatement:
+        source.begin(JsNodeTags.forStatement);
+        js.Expression init = read(allowNull: true);
+        js.Expression condition = read(allowNull: true);
+        js.Expression update = read(allowNull: true);
+        js.Statement body = read();
+        node = new js.For(init, condition, update, body);
+        source.end(JsNodeTags.forStatement);
+        break;
+      case JsNodeKind.ifStatement:
+        source.begin(JsNodeTags.ifStatement);
+        js.Expression condition = read();
+        js.Statement then = read();
+        js.Statement otherwise = read();
+        node = new js.If(condition, then, otherwise);
+        source.end(JsNodeTags.ifStatement);
+        break;
+      case JsNodeKind.emptyStatement:
+        source.begin(JsNodeTags.emptyStatement);
+        node = new js.EmptyStatement();
+        source.end(JsNodeTags.emptyStatement);
+        break;
+      case JsNodeKind.expressionStatement:
+        source.begin(JsNodeTags.expressionStatement);
+        node = new js.ExpressionStatement(read());
+        source.end(JsNodeTags.expressionStatement);
+        break;
+      case JsNodeKind.block:
+        source.begin(JsNodeTags.block);
+        List<js.Statement> statements = readList();
+        node = new js.Block(statements);
+        source.end(JsNodeTags.block);
+        break;
+      case JsNodeKind.program:
+        source.begin(JsNodeTags.program);
+        List<js.Statement> body = readList();
+        node = new js.Program(body);
+        source.end(JsNodeTags.program);
+        break;
+    }
+    SourceInformation sourceInformation =
+        source.readCached<SourceInformation>(() {
+      return SourceInformation.readFromDataSource(source);
+    });
+    if (sourceInformation != null) {
+      node = node.withSourceInformation(sourceInformation);
+    }
+    return node;
+  }
+
+  List<T> readList<T extends js.Node>({bool emptyAsNull: false}) {
+    return source.readList(read, emptyAsNull: emptyAsNull);
+  }
+}
+
+class CodegenReaderImpl implements CodegenReader {
+  final JClosedWorld closedWorld;
+  final List<ModularName> modularNames;
+  final List<ModularExpression> modularExpressions;
+
+  CodegenReaderImpl(
+      this.closedWorld, this.modularNames, this.modularExpressions);
+
+  @override
+  AbstractValue readAbstractValue(DataSource source) {
+    return closedWorld.abstractValueDomain
+        .readAbstractValueFromDataSource(source);
+  }
+
+  @override
+  js.Node readJsNode(DataSource source) {
+    return JsNodeDeserializer.readFromDataSource(
+        source, modularNames, modularExpressions);
+  }
+
+  @override
+  OutputUnit readOutputUnitReference(DataSource source) {
+    return closedWorld.outputUnitData.outputUnits[source.readInt()];
+  }
+}
+
+class CodegenWriterImpl implements CodegenWriter {
+  final JClosedWorld closedWorld;
+
+  CodegenWriterImpl(this.closedWorld);
+
+  @override
+  void writeAbstractValue(DataSink sink, AbstractValue value) {
+    closedWorld.abstractValueDomain.writeAbstractValueToDataSink(sink, value);
+  }
+
+  @override
+  void writeJsNode(DataSink sink, js.Node node) {
+    JsNodeSerializer.writeToDataSink(sink, node);
+  }
+
+  @override
+  void writeOutputUnitReference(DataSink sink, OutputUnit value) {
+    sink.writeInt(closedWorld.outputUnitData.outputUnits.indexOf(value));
+  }
 }
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index ec947a4..a8eaea4 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -214,6 +214,9 @@
   static final Uri dart__js_helper =
       new Uri(scheme: 'dart', path: '_js_helper');
 
+  /// The URI for 'dart:_rti'.
+  static final Uri dart__rti = new Uri(scheme: 'dart', path: '_rti');
+
   /// The URI for 'dart:_interceptors'.
   static final Uri dart__interceptors =
       new Uri(scheme: 'dart', path: '_interceptors');
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 008c8d3..36d7296 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -14,6 +14,7 @@
 import 'elements/types.dart';
 import 'inferrer/abstract_value_domain.dart';
 import 'js_backend/native_data.dart' show NativeBasicData;
+import 'js_model/locals.dart';
 import 'kernel/dart2js_target.dart';
 import 'universe/selector.dart' show Selector;
 
@@ -2152,4 +2153,30 @@
   /// marker. The return type of the method is inspected to determine the type
   /// parameter of the Future, Stream or Iterable.
   DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function);
+
+  /// Calls [f] with every instance field, together with its declarer, in an
+  /// instance of [cls]. All fields inherited from superclasses and mixins are
+  /// included.
+  ///
+  /// If [isElided] is `true`, the field is not read and should therefore not
+  /// be emitted.
+  void forEachInstanceField(
+      ClassEntity cls, void f(ClassEntity declarer, FieldEntity field));
+
+  /// Calls [f] with every instance field declared directly in class [cls]
+  /// (i.e. no inherited fields). Fields are presented in initialization
+  /// (i.e. textual) order.
+  ///
+  /// If [isElided] is `true`, the field is not read and should therefore not
+  /// be emitted.
+  void forEachDirectInstanceField(ClassEntity cls, void f(FieldEntity field));
+
+  /// Calls [f] for each parameter of [function] providing the type and name of
+  /// the parameter and the [defaultValue] if the parameter is optional.
+  void forEachParameter(covariant FunctionEntity function,
+      void f(DartType type, String name, ConstantValue defaultValue));
+
+  /// Calls [f] for each parameter - given as a [Local] - of [function].
+  void forEachParameterAsLocal(GlobalLocalsMap globalLocalsMap,
+      FunctionEntity function, void f(Local parameter));
 }
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 03f5b05..ed69778 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -11,11 +11,11 @@
 
 import '../compiler_new.dart' as api;
 import 'backend_strategy.dart';
+import 'common/codegen.dart';
 import 'common/names.dart' show Selectors, Uris;
 import 'common/tasks.dart' show CompilerTask, GenericTask, Measurer;
 import 'common/work.dart' show WorkItem;
 import 'common.dart';
-import 'compile_time_constants.dart';
 import 'common_elements.dart' show ElementEnvironment;
 import 'deferred_load.dart' show DeferredLoadTask, OutputUnitData;
 import 'diagnostics/code_location.dart';
@@ -32,7 +32,7 @@
 import 'inferrer/types.dart'
     show GlobalTypeInferenceResults, GlobalTypeInferenceTask;
 import 'io/source_information.dart' show SourceInformation;
-import 'js_backend/backend.dart' show JavaScriptBackend;
+import 'js_backend/backend.dart' show CodegenInputs, JavaScriptBackend;
 import 'js_backend/inferred_data.dart';
 import 'js_model/js_strategy.dart';
 import 'kernel/kernel_strategy.dart';
@@ -86,12 +86,6 @@
   Map<Entity, WorldImpact> get impactCache => _impactCache;
   ImpactCacheDeleter get impactCacheDeleter => _impactCacheDeleter;
 
-  // TODO(zarah): Remove this map and incorporate compile-time errors
-  // in the model.
-  /// Tracks elements with compile-time errors.
-  final Map<Entity, List<DiagnosticMessage>> elementsWithCompileTimeErrors =
-      new Map<Entity, List<DiagnosticMessage>>();
-
   final Environment environment;
   // TODO(sigmund): delete once we migrate the rest of the compiler to use
   // `environment` directly.
@@ -110,10 +104,6 @@
 
   GenericTask selfTask;
 
-  /// The constant environment for the frontend interpretation of compile-time
-  /// constants.
-  ConstantEnvironment constants;
-
   EnqueueTask enqueuer;
   DeferredLoadTask deferredLoadTask;
   DumpInfoTask dumpInfoTask;
@@ -176,14 +166,14 @@
           options, provider, _outputProvider, reporter, measurer),
       kernelFrontEndTask,
       globalInference = new GlobalTypeInferenceTask(this),
-      constants = backend.constantCompilerTask,
       deferredLoadTask = frontendStrategy.createDeferredLoadTask(this),
       // [enqueuer] is created earlier because it contains the resolution world
       // objects needed by other tasks.
       enqueuer,
       dumpInfoTask = new DumpInfoTask(this),
       selfTask,
-      serializationTask = new SerializationTask(this, measurer),
+      serializationTask = new SerializationTask(
+          options, reporter, provider, outputProvider, measurer),
     ];
 
     tasks.addAll(backend.tasks);
@@ -210,6 +200,8 @@
     return _codegenWorldBuilder;
   }
 
+  CodegenWorld codegenWorldForTesting;
+
   bool get disableTypeInference =>
       options.disableTypeInference || compilationFailed;
 
@@ -237,18 +229,19 @@
     reporter.log('Compiling $uri (${options.buildId})');
 
     if (options.readDataUri != null) {
-      GlobalTypeInferenceResults results =
-          await serializationTask.deserialize();
+      GlobalTypeInferenceResults globalTypeInferenceResults =
+          await serializationTask.deserializeGlobalTypeInference(
+              environment, abstractValueStrategy);
       if (options.debugGlobalInference) {
-        performGlobalTypeInference(results.closedWorld);
+        performGlobalTypeInference(globalTypeInferenceResults.closedWorld);
         return;
       }
-      generateJavaScriptCode(results);
+      await generateJavaScriptCode(globalTypeInferenceResults);
     } else {
       KernelResult result = await kernelLoader.load(uri);
       reporter.log("Kernel load complete");
       if (result == null) return;
-      if (compilationFailed && !options.generateCodeWithCompileTimeErrors) {
+      if (compilationFailed) {
         return;
       }
       if (options.cfeOnly) return;
@@ -273,6 +266,32 @@
     }
   }
 
+  void generateJavaScriptCode(
+      GlobalTypeInferenceResults globalTypeInferenceResults) async {
+    JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
+    backendStrategy.registerJClosedWorld(closedWorld);
+    phase = PHASE_COMPILING;
+    CodegenInputs codegenInputs =
+        backend.onCodegenStart(globalTypeInferenceResults);
+
+    if (options.readCodegenUri != null) {
+      CodegenResults codegenResults =
+          await serializationTask.deserializeCodegen(
+              backendStrategy, globalTypeInferenceResults, codegenInputs);
+      reporter.log('Compiling methods');
+      runCodegenEnqueuer(codegenResults);
+    } else {
+      reporter.log('Compiling methods');
+      CodegenResults codegenResults = new OnDemandCodegenResults(
+          globalTypeInferenceResults, codegenInputs, backend.functionCompiler);
+      if (options.writeCodegenUri != null) {
+        serializationTask.serializeCodegen(backendStrategy, codegenResults);
+      } else {
+        runCodegenEnqueuer(codegenResults);
+      }
+    }
+  }
+
   /// Clear the internal compiler state to prevent memory leaks when invoking
   /// the compiler multiple times (e.g. in batch mode).
   // TODO(ahe): implement a better mechanism where we can store
@@ -331,7 +350,7 @@
 
     phase = PHASE_RESOLVING;
     resolutionEnqueuer.applyImpact(mainImpact);
-    if (options.showInternalProgress) reporter.log('Resolving...');
+    if (options.showInternalProgress) reporter.log('Computing closed world');
 
     processQueue(
         frontendStrategy.elementEnvironment, resolutionEnqueuer, mainFunction,
@@ -342,13 +361,7 @@
     _reporter.reportSuppressedMessagesSummary();
 
     if (compilationFailed) {
-      if (!options.generateCodeWithCompileTimeErrors) {
-        return null;
-      }
-      if (mainFunction == null) return null;
-      if (!backend.enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) {
-        return null;
-      }
+      return null;
     }
 
     assert(mainFunction != null);
@@ -364,36 +377,40 @@
   GlobalTypeInferenceResults performGlobalTypeInference(
       JClosedWorld closedWorld) {
     FunctionEntity mainFunction = closedWorld.elementEnvironment.mainFunction;
-    if (options.showInternalProgress) reporter.log('Inferring types...');
+    reporter.log('Performing global type inference');
     InferredDataBuilder inferredDataBuilder =
         new InferredDataBuilderImpl(closedWorld.annotationsData);
     return globalInference.runGlobalTypeInference(
         mainFunction, closedWorld, inferredDataBuilder);
   }
 
-  void generateJavaScriptCode(
-      GlobalTypeInferenceResults globalInferenceResults) {
+  void runCodegenEnqueuer(CodegenResults codegenResults) {
+    GlobalTypeInferenceResults globalInferenceResults =
+        codegenResults.globalTypeInferenceResults;
     JClosedWorld closedWorld = globalInferenceResults.closedWorld;
-    backendStrategy.registerJClosedWorld(closedWorld);
-    FunctionEntity mainFunction = closedWorld.elementEnvironment.mainFunction;
-    if (options.showInternalProgress) reporter.log('Compiling...');
-    phase = PHASE_COMPILING;
+    CodegenInputs codegenInputs = codegenResults.codegenInputs;
+    Enqueuer codegenEnqueuer = enqueuer.createCodegenEnqueuer(
+        closedWorld, globalInferenceResults, codegenInputs, codegenResults);
+    _codegenWorldBuilder = codegenEnqueuer.worldBuilder;
 
-    Enqueuer codegenEnqueuer =
-        startCodegen(closedWorld, globalInferenceResults);
+    FunctionEntity mainFunction = closedWorld.elementEnvironment.mainFunction;
     processQueue(closedWorld.elementEnvironment, codegenEnqueuer, mainFunction,
         onProgress: showCodegenProgress);
     codegenEnqueuer.logSummary(reporter.log);
-
-    int programSize = backend.assembleProgram(
-        closedWorld, globalInferenceResults.inferredData);
+    CodegenWorld codegenWorld = codegenWorldBuilder.close();
+    if (retainDataForTesting) {
+      codegenWorldForTesting = codegenWorld;
+    }
+    reporter.log('Emitting JavaScript');
+    int programSize = backend.assembleProgram(closedWorld,
+        globalInferenceResults.inferredData, codegenInputs, codegenWorld);
 
     if (options.dumpInfo) {
       dumpInfoTask.reportSize(programSize);
       dumpInfoTask.dumpInfo(closedWorld, globalInferenceResults);
     }
 
-    backend.onCodegenEnd();
+    backend.onCodegenEnd(codegenInputs);
 
     checkQueue(codegenEnqueuer);
   }
@@ -408,7 +425,8 @@
         GlobalTypeInferenceResults globalInferenceResults =
             performGlobalTypeInference(closedWorld);
         if (options.writeDataUri != null) {
-          serializationTask.serialize(globalInferenceResults);
+          serializationTask
+              .serializeGlobalTypeInference(globalInferenceResults);
           return;
         }
         if (options.testMode) {
@@ -431,16 +449,6 @@
     });
   }
 
-  Enqueuer startCodegen(JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
-    Enqueuer codegenEnqueuer =
-        enqueuer.createCodegenEnqueuer(closedWorld, globalInferenceResults);
-    _codegenWorldBuilder = codegenEnqueuer.worldBuilder;
-    codegenEnqueuer.applyImpact(backend.onCodegenStart(
-        closedWorld, _codegenWorldBuilder, closedWorld.sorter));
-    return codegenEnqueuer;
-  }
-
   /// Perform the steps needed to fully end the resolution phase.
   JClosedWorld closeResolution(FunctionEntity mainFunction) {
     phase = PHASE_DONE_RESOLVING;
@@ -539,7 +547,6 @@
     if (markCompilationAsFailed(message, kind)) {
       compilationFailed = true;
     }
-    registerCompileTimeError(currentElement, message);
   }
 
   /// Helper for determining whether the current element is declared within
@@ -604,27 +611,6 @@
     }
     return null;
   }
-
-  /// Returns [true] if a compile-time error has been reported for element.
-  bool elementHasCompileTimeError(Entity element) {
-    return elementsWithCompileTimeErrors.containsKey(element);
-  }
-
-  /// Associate [element] with a compile-time error [message].
-  void registerCompileTimeError(Entity element, DiagnosticMessage message) {
-    // The information is only needed if [generateCodeWithCompileTimeErrors].
-    if (options.generateCodeWithCompileTimeErrors) {
-      if (element == null) {
-        // Record as global error.
-        // TODO(zarah): Extend element model to represent compile-time
-        // errors instead of using a map.
-        element = frontendStrategy.elementEnvironment.mainFunction;
-      }
-      elementsWithCompileTimeErrors
-          .putIfAbsent(element, () => <DiagnosticMessage>[])
-          .add(message);
-    }
-  }
 }
 
 class _CompilerOutput implements api.CompilerOutput {
@@ -638,14 +624,8 @@
   api.OutputSink createOutputSink(
       String name, String extension, api.OutputType type) {
     if (_compiler.compilationFailed) {
-      if (!_compiler.options.generateCodeWithCompileTimeErrors ||
-          _compiler.options.testMode) {
-        // Disable output in test mode: The build bot currently uses the time
-        // stamp of the generated file to determine whether the output is
-        // up-to-date.
-        return const NullCompilerOutput()
-            .createOutputSink(name, extension, type);
-      }
+      // Ensure that we don't emit output when the compilation has failed.
+      return const NullCompilerOutput().createOutputSink(name, extension, type);
     }
     return _userOutput.createOutputSink(name, extension, type);
   }
@@ -759,13 +739,6 @@
     if (kind == api.Diagnostic.ERROR ||
         kind == api.Diagnostic.CRASH ||
         (options.fatalWarnings && kind == api.Diagnostic.WARNING)) {
-      Entity errorElement;
-      if (message.spannable is Entity) {
-        errorElement = message.spannable;
-      } else {
-        errorElement = currentElement;
-      }
-      compiler.registerCompileTimeError(errorElement, message);
       compiler.fatalDiagnosticReported(message, infos, kind);
     }
   }
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index ffb7acf..67b4c3f 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -9,6 +9,8 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../deferred_load.dart' show OutputUnit;
+import '../inferrer/abstract_value_domain.dart';
+import '../js/js.dart' as js;
 import '../util/util.dart';
 
 enum ConstantValueKind {
@@ -24,7 +26,9 @@
   CONSTRUCTED,
   TYPE,
   INTERCEPTOR,
-  SYNTHETIC,
+  JS_NAME,
+  DUMMY_INTERCEPTOR,
+  UNREACHABLE,
   INSTANTIATION,
   DEFERRED_GLOBAL,
   NON_CONSTANT,
@@ -47,7 +51,11 @@
   R visitType(covariant TypeConstantValue constant, covariant A arg);
   R visitInterceptor(
       covariant InterceptorConstantValue constant, covariant A arg);
-  R visitSynthetic(covariant SyntheticConstantValue constant, covariant A arg);
+  R visitDummyInterceptor(
+      covariant DummyInterceptorConstantValue constant, covariant A arg);
+  R visitUnreachable(
+      covariant UnreachableConstantValue constant, covariant A arg);
+  R visitJsName(covariant JsNameConstantValue constant, covariant A arg);
   R visitDeferredGlobal(
       covariant DeferredGlobalConstantValue constant, covariant A arg);
   R visitNonConstant(covariant NonConstantValue constant, covariant A arg);
@@ -808,42 +816,110 @@
   }
 }
 
-class SyntheticConstantValue extends ConstantValue {
-  final payload;
-  final valueKind;
+class JsNameConstantValue extends ConstantValue {
+  final js.LiteralString name;
 
-  SyntheticConstantValue(this.valueKind, this.payload);
+  JsNameConstantValue(this.name);
 
   @override
   bool get isDummy => true;
 
   @override
   bool operator ==(other) {
-    return other is SyntheticConstantValue && payload == other.payload;
+    return other is JsNameConstantValue && name == other.name;
   }
 
   @override
-  get hashCode => payload.hashCode * 17 + valueKind.hashCode;
+  get hashCode => name.hashCode * 17;
 
   @override
   List<ConstantValue> getDependencies() => const <ConstantValue>[];
 
   @override
   accept(ConstantValueVisitor visitor, arg) {
-    return visitor.visitSynthetic(this, arg);
+    return visitor.visitJsName(this, arg);
   }
 
   @override
   DartType getType(CommonElements types) => types.dynamicType;
 
   @override
-  ConstantValueKind get kind => ConstantValueKind.SYNTHETIC;
+  ConstantValueKind get kind => ConstantValueKind.JS_NAME;
 
   @override
-  String toDartText() => 'synthetic($valueKind, $payload)';
+  String toDartText() => 'js_name(${name})';
 
   @override
-  String toStructuredText() => 'SyntheticConstant($valueKind, $payload)';
+  String toStructuredText() => 'JsNameConstant(${name})';
+}
+
+/// A constant used as the dummy interceptor value for intercepted calls with
+/// a known non-interceptor target.
+class DummyInterceptorConstantValue extends ConstantValue {
+  final AbstractValue abstractValue;
+
+  DummyInterceptorConstantValue(this.abstractValue);
+
+  @override
+  bool get isDummy => true;
+
+  @override
+  bool operator ==(other) {
+    return other is DummyInterceptorConstantValue &&
+        abstractValue == other.abstractValue;
+  }
+
+  @override
+  get hashCode => abstractValue.hashCode * 17;
+
+  @override
+  List<ConstantValue> getDependencies() => const <ConstantValue>[];
+
+  @override
+  accept(ConstantValueVisitor visitor, arg) {
+    return visitor.visitDummyInterceptor(this, arg);
+  }
+
+  @override
+  DartType getType(CommonElements types) => types.dynamicType;
+
+  @override
+  ConstantValueKind get kind => ConstantValueKind.DUMMY_INTERCEPTOR;
+
+  @override
+  String toDartText() => 'dummy_interceptor($abstractValue)';
+
+  @override
+  String toStructuredText() => 'DummyInterceptorConstant($abstractValue)';
+}
+
+// A constant with an empty type used in [HInstruction]s of an expression
+// in an unreachable context.
+class UnreachableConstantValue extends ConstantValue {
+  const UnreachableConstantValue();
+
+  @override
+  bool get isDummy => true;
+
+  @override
+  List<ConstantValue> getDependencies() => const <ConstantValue>[];
+
+  @override
+  accept(ConstantValueVisitor visitor, arg) {
+    return visitor.visitUnreachable(this, arg);
+  }
+
+  @override
+  DartType getType(CommonElements types) => types.dynamicType;
+
+  @override
+  ConstantValueKind get kind => ConstantValueKind.UNREACHABLE;
+
+  @override
+  String toDartText() => 'unreachable()';
+
+  @override
+  String toStructuredText() => 'UnreachableConstant()';
 }
 
 class ConstructedConstantValue extends ObjectConstantValue {
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index c829eaa..7348d20 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -110,6 +110,10 @@
   Uri sourceMapOut;
   Uri readDataUri;
   Uri writeDataUri;
+  Uri readCodegenUri;
+  Uri writeCodegenUri;
+  int codegenShard;
+  int codegenShards;
   List<String> bazelPaths;
   Uri packageConfig = null;
   Uri packageRoot = null;
@@ -129,7 +133,8 @@
   int optimizationLevel = null;
   Uri platformBinaries;
   Map<String, String> environment = new Map<String, String>();
-  CompilationStrategy compilationStrategy = CompilationStrategy.direct;
+  ReadStrategy readStrategy = ReadStrategy.fromDart;
+  WriteStrategy writeStrategy = WriteStrategy.toJs;
 
   void passThrough(String argument) => options.add(argument);
   void ignoreOption(String argument) {}
@@ -246,13 +251,12 @@
   }
 
   void setReadData(String argument) {
-    if (compilationStrategy == CompilationStrategy.toData) {
-      fail("Cannot read and write serialized simultaneously.");
-    }
     if (argument != Flags.readData) {
       readDataUri = nativeToUri(extractPath(argument, isDirectory: false));
     }
-    compilationStrategy = CompilationStrategy.fromData;
+    if (readStrategy != ReadStrategy.fromCodegen) {
+      readStrategy = ReadStrategy.fromData;
+    }
   }
 
   void setDillDependencies(String argument) {
@@ -263,17 +267,58 @@
   }
 
   void setCfeOnly(String argument) {
-    compilationStrategy = CompilationStrategy.toKernel;
+    if (writeStrategy == WriteStrategy.toData) {
+      fail("Cannot use ${Flags.cfeOnly} "
+          "and write serialized data simultaneously.");
+    }
+    if (writeStrategy == WriteStrategy.toCodegen) {
+      fail("Cannot use ${Flags.cfeOnly} "
+          "and write serialized codegen simultaneously.");
+    }
+    writeStrategy = WriteStrategy.toKernel;
+  }
+
+  void setReadCodegen(String argument) {
+    if (argument != Flags.readCodegen) {
+      readCodegenUri = nativeToUri(extractPath(argument, isDirectory: false));
+    }
+    readStrategy = ReadStrategy.fromCodegen;
   }
 
   void setWriteData(String argument) {
-    if (compilationStrategy == CompilationStrategy.fromData) {
-      fail("Cannot read and write serialized simultaneously.");
+    if (writeStrategy == WriteStrategy.toKernel) {
+      fail("Cannot use ${Flags.cfeOnly} "
+          "and write serialized data simultaneously.");
+    }
+    if (writeStrategy == WriteStrategy.toCodegen) {
+      fail("Cannot write serialized data and codegen simultaneously.");
     }
     if (argument != Flags.writeData) {
       writeDataUri = nativeToUri(extractPath(argument, isDirectory: false));
     }
-    compilationStrategy = CompilationStrategy.toData;
+    writeStrategy = WriteStrategy.toData;
+  }
+
+  void setWriteCodegen(String argument) {
+    if (writeStrategy == WriteStrategy.toKernel) {
+      fail("Cannot use ${Flags.cfeOnly} "
+          "and write serialized codegen simultaneously.");
+    }
+    if (writeStrategy == WriteStrategy.toData) {
+      fail("Cannot write serialized data and codegen data simultaneously.");
+    }
+    if (argument != Flags.writeCodegen) {
+      writeCodegenUri = nativeToUri(extractPath(argument, isDirectory: false));
+    }
+    writeStrategy = WriteStrategy.toCodegen;
+  }
+
+  void setCodegenShard(String argument) {
+    codegenShard = int.parse(extractParameter(argument));
+  }
+
+  void setCodegenShards(String argument) {
+    codegenShards = int.parse(extractParameter(argument));
   }
 
   void setDumpInfo(String argument) {
@@ -349,6 +394,12 @@
     new OptionHandler('${Flags.dillDependencies}=.+', setDillDependencies),
     new OptionHandler('${Flags.readData}|${Flags.readData}=.+', setReadData),
     new OptionHandler('${Flags.writeData}|${Flags.writeData}=.+', setWriteData),
+    new OptionHandler(
+        '${Flags.readCodegen}|${Flags.readCodegen}=.+', setReadCodegen),
+    new OptionHandler(
+        '${Flags.writeCodegen}|${Flags.writeCodegen}=.+', setWriteCodegen),
+    new OptionHandler('${Flags.codegenShard}=.+', setCodegenShard),
+    new OptionHandler('${Flags.codegenShards}=.+', setCodegenShards),
     new OptionHandler(Flags.cfeOnly, setCfeOnly),
     new OptionHandler(Flags.debugGlobalInference, passThrough),
     new OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
@@ -414,7 +465,7 @@
     new OptionHandler('--enable-null-aware-operators', ignoreOption),
     new OptionHandler('--enable-enum', ignoreOption),
     new OptionHandler(Flags.allowNativeExtensions, setAllowNativeExtensions),
-    new OptionHandler(Flags.generateCodeWithCompileTimeErrors, passThrough),
+    new OptionHandler(Flags.generateCodeWithCompileTimeErrors, ignoreOption),
     new OptionHandler(Flags.useMultiSourceInfo, passThrough),
     new OptionHandler(Flags.useNewSourceInfo, passThrough),
     new OptionHandler(Flags.testMode, passThrough),
@@ -511,28 +562,86 @@
 
   String scriptName = arguments[0];
 
-  switch (compilationStrategy) {
-    case CompilationStrategy.direct:
+  switch (writeStrategy) {
+    case WriteStrategy.toJs:
       out ??= currentDirectory.resolve('out.js');
       break;
-    case CompilationStrategy.toKernel:
+    case WriteStrategy.toKernel:
       out ??= currentDirectory.resolve('out.dill');
       options.add(Flags.cfeOnly);
+      if (readStrategy == ReadStrategy.fromData) {
+        fail("Cannot use ${Flags.cfeOnly} "
+            "and read serialized data simultaneously.");
+      } else if (readStrategy == ReadStrategy.fromCodegen) {
+        fail("Cannot use ${Flags.cfeOnly} "
+            "and read serialized codegen simultaneously.");
+      }
       break;
-    case CompilationStrategy.toData:
+    case WriteStrategy.toData:
       out ??= currentDirectory.resolve('out.dill');
       writeDataUri ??= currentDirectory.resolve('$out.data');
       options.add('${Flags.writeData}=${writeDataUri}');
+      if (readStrategy == ReadStrategy.fromData) {
+        fail("Cannot read and write serialized data simultaneously.");
+      } else if (readStrategy == ReadStrategy.fromCodegen) {
+        fail("Cannot read serialized codegen and "
+            "write serialized data simultaneously.");
+      }
       break;
-    case CompilationStrategy.fromData:
-      out ??= currentDirectory.resolve('out.js');
+    case WriteStrategy.toCodegen:
+      // TODO(johnniwinther): Avoid the need for an [out] value in this case or
+      // use [out] to pass [writeCodegenUri].
+      out ??= currentDirectory.resolve('out');
+      writeCodegenUri ??= currentDirectory.resolve('$out.code');
+      options.add('${Flags.writeCodegen}=${writeCodegenUri}');
+      if (readStrategy == ReadStrategy.fromCodegen) {
+        fail("Cannot read and write serialized codegen simultaneously.");
+      }
+      if (readStrategy != ReadStrategy.fromData) {
+        fail("Can only write serialized codegen from serialized data.");
+      }
+      if (codegenShards == null) {
+        fail("Cannot write serialized codegen without setting "
+            "${Flags.codegenShards}.");
+      } else if (codegenShards <= 0) {
+        fail("${Flags.codegenShards} must be a positive integer.");
+      }
+      if (codegenShard == null) {
+        fail("Cannot write serialized codegen without setting "
+            "${Flags.codegenShard}.");
+      } else if (codegenShard < 0 || codegenShard >= codegenShards) {
+        fail("${Flags.codegenShard} must be between 0 and "
+            "${Flags.codegenShards}.");
+      }
+      options.add('${Flags.codegenShard}=$codegenShard');
+      options.add('${Flags.codegenShards}=$codegenShards');
+      break;
+  }
+  switch (readStrategy) {
+    case ReadStrategy.fromDart:
+      break;
+    case ReadStrategy.fromData:
       readDataUri ??= currentDirectory.resolve('$scriptName.data');
       options.add('${Flags.readData}=${readDataUri}');
       break;
+    case ReadStrategy.fromCodegen:
+      readDataUri ??= currentDirectory.resolve('$scriptName.data');
+      options.add('${Flags.readData}=${readDataUri}');
+      readCodegenUri ??= currentDirectory.resolve('$scriptName.code');
+      options.add('${Flags.readCodegen}=${readCodegenUri}');
+      if (codegenShards == null) {
+        fail("Cannot write serialized codegen without setting "
+            "${Flags.codegenShards}.");
+      } else if (codegenShards <= 0) {
+        fail("${Flags.codegenShards} must be a positive integer.");
+      }
+      options.add('${Flags.codegenShards}=$codegenShards');
   }
   options.add('--out=$out');
-  sourceMapOut = Uri.parse('$out.map');
-  options.add('--source-map=${sourceMapOut}');
+  if (writeStrategy == WriteStrategy.toJs) {
+    sourceMapOut = Uri.parse('$out.map');
+    options.add('--source-map=${sourceMapOut}');
+  }
 
   RandomAccessFileOutputProvider outputProvider =
       new RandomAccessFileOutputProvider(out, sourceMapOut,
@@ -544,86 +653,98 @@
     }
     writeString(
         Uri.parse('$out.deps'), getDepsOutput(inputProvider.getSourceUris()));
-    switch (compilationStrategy) {
-      case CompilationStrategy.direct:
-        int dartCharactersRead = inputProvider.dartCharactersRead;
-        int jsCharactersWritten =
-            outputProvider.totalCharactersWrittenJavaScript;
-        int jsCharactersPrimary = outputProvider.totalCharactersWrittenPrimary;
-        print('Compiled '
-            '${_formatCharacterCount(dartCharactersRead)} characters Dart to '
-            '${_formatCharacterCount(jsCharactersWritten)} characters '
-            'JavaScript in '
-            '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
 
-        diagnosticHandler
-            .info('${_formatCharacterCount(jsCharactersPrimary)} characters '
-                'JavaScript in '
-                '${relativize(currentDirectory, out, Platform.isWindows)}');
-        if (outputSpecified || diagnosticHandler.verbose) {
-          String input = uriPathToNative(scriptName);
-          String output = relativize(currentDirectory, out, Platform.isWindows);
-          print('Dart file ($input) compiled to JavaScript: $output');
-          if (diagnosticHandler.verbose) {
-            var files = outputProvider.allOutputFiles;
-            int jsCount = files.where((f) => f.endsWith('.js')).length;
-            print('Emitted file $jsCount JavaScript files.');
-          }
-        }
+    String input = uriPathToNative(scriptName);
+    int inputSize;
+    String processName;
+    String inputName;
+
+    int outputSize;
+    int primaryOutputSize;
+    String outputName;
+
+    String summary;
+    switch (readStrategy) {
+      case ReadStrategy.fromDart:
+        inputName = 'characters Dart';
+        inputSize = inputProvider.dartCharactersRead;
+        summary = 'Dart file $input ';
         break;
-      case CompilationStrategy.toKernel:
-        int dartCharactersRead = inputProvider.dartCharactersRead;
-        int dataBytesWritten = outputProvider.totalDataWritten;
-        print('Compiled '
-            '${_formatCharacterCount(dartCharactersRead)} characters Dart to '
-            '${_formatCharacterCount(dataBytesWritten)} kernel bytes in '
-            '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
-        String input = uriPathToNative(scriptName);
-        String dillOutput =
-            relativize(currentDirectory, out, Platform.isWindows);
-        print('Dart file ($input) compiled to ${dillOutput}.');
+      case ReadStrategy.fromData:
+        inputName = 'bytes data';
+        inputSize = inputProvider.dartCharactersRead;
+        String dataInput =
+            relativize(currentDirectory, readDataUri, Platform.isWindows);
+        summary = 'Data files $input and $dataInput ';
         break;
-      case CompilationStrategy.toData:
-        int dartCharactersRead = inputProvider.dartCharactersRead;
-        int dataBytesWritten = outputProvider.totalDataWritten;
-        print('Serialized '
-            '${_formatCharacterCount(dartCharactersRead)} characters Dart to '
-            '${_formatCharacterCount(dataBytesWritten)} bytes data in '
-            '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
-        String input = uriPathToNative(scriptName);
-        String dillOutput =
-            relativize(currentDirectory, out, Platform.isWindows);
+      case ReadStrategy.fromCodegen:
+        inputName = 'bytes data';
+        inputSize = inputProvider.dartCharactersRead;
+        String dataInput =
+            relativize(currentDirectory, readDataUri, Platform.isWindows);
+        String codeInput =
+            relativize(currentDirectory, readCodegenUri, Platform.isWindows);
+        summary = 'Data files $input, $dataInput and '
+            '${codeInput}[0-${codegenShards - 1}] ';
+        break;
+    }
+
+    switch (writeStrategy) {
+      case WriteStrategy.toJs:
+        processName = 'Compiled';
+        outputName = 'characters JavaScript';
+        outputSize = outputProvider.totalCharactersWrittenJavaScript;
+        primaryOutputSize = outputProvider.totalCharactersWrittenPrimary;
+        String output = relativize(currentDirectory, out, Platform.isWindows);
+        summary += 'compiled to JavaScript: ${output}';
+        break;
+      case WriteStrategy.toKernel:
+        processName = 'Compiled';
+        outputName = 'kernel bytes';
+        outputSize = outputProvider.totalDataWritten;
+        String output = relativize(currentDirectory, out, Platform.isWindows);
+        summary += 'compiled to dill: ${output}.';
+        break;
+      case WriteStrategy.toData:
+        processName = 'Serialized';
+        outputName = 'bytes data';
+        outputSize = outputProvider.totalDataWritten;
+        String output = relativize(currentDirectory, out, Platform.isWindows);
         String dataOutput =
             relativize(currentDirectory, writeDataUri, Platform.isWindows);
-        print('Dart file ($input) serialized to '
-            '${dillOutput} and ${dataOutput}.');
+        summary += 'serialized to dill and data: ${output} and ${dataOutput}.';
         break;
-      case CompilationStrategy.fromData:
-        int dataCharactersRead = inputProvider.dartCharactersRead;
-        int jsCharactersWritten =
-            outputProvider.totalCharactersWrittenJavaScript;
-        int jsCharactersPrimary = outputProvider.totalCharactersWrittenPrimary;
-        print('Compiled '
-            '${_formatCharacterCount(dataCharactersRead)} bytes data to '
-            '${_formatCharacterCount(jsCharactersWritten)} characters '
-            'JavaScript in '
-            '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
+      case WriteStrategy.toCodegen:
+        processName = 'Serialized';
+        outputName = 'bytes data';
+        outputSize = outputProvider.totalDataWritten;
+        String codeOutput =
+            relativize(currentDirectory, writeCodegenUri, Platform.isWindows);
+        summary += 'serialized to codegen data: '
+            '${codeOutput}${codegenShard}.';
+        break;
+    }
 
-        diagnosticHandler
-            .info('${_formatCharacterCount(jsCharactersPrimary)} characters '
-                'JavaScript in '
-                '${relativize(currentDirectory, out, Platform.isWindows)}');
-        if (outputSpecified || diagnosticHandler.verbose) {
-          String input = uriPathToNative(scriptName);
-          String output = relativize(currentDirectory, out, Platform.isWindows);
-          print('Dart file ($input) compiled to JavaScript: $output');
-          if (diagnosticHandler.verbose) {
-            var files = outputProvider.allOutputFiles;
-            int jsCount = files.where((f) => f.endsWith('.js')).length;
-            print('Emitted file $jsCount JavaScript files.');
-          }
+    print('$processName '
+        '${_formatCharacterCount(inputSize)} $inputName to '
+        '${_formatCharacterCount(outputSize)} $outputName in '
+        '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
+    if (primaryOutputSize != null) {
+      diagnosticHandler
+          .info('${_formatCharacterCount(primaryOutputSize)} $outputName '
+              'in ${relativize(currentDirectory, out, Platform.isWindows)}');
+    }
+    if (writeStrategy == WriteStrategy.toJs) {
+      if (outputSpecified || diagnosticHandler.verbose) {
+        print(summary);
+        if (diagnosticHandler.verbose) {
+          var files = outputProvider.allOutputFiles;
+          int jsCount = files.where((f) => f.endsWith('.js')).length;
+          print('Emitted file $jsCount JavaScript files.');
         }
-        break;
+      }
+    } else {
+      print(summary);
     }
 
     return result;
@@ -1043,4 +1164,5 @@
   });
 }
 
-enum CompilationStrategy { direct, toKernel, toData, fromData }
+enum ReadStrategy { fromDart, fromData, fromCodegen }
+enum WriteStrategy { toKernel, toData, toCodegen, toJs }
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index a412c65..118d4ed 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -296,7 +296,7 @@
               _collectTypeArgumentDependencies(
                   staticUse.type.typeArguments, dependencies);
               break;
-            case StaticUseKind.INVOKE:
+            case StaticUseKind.STATIC_INVOKE:
             case StaticUseKind.CLOSURE_CALL:
             case StaticUseKind.DIRECT_INVOKE:
               // TODO(johnniwinther): Use rti need data to skip unneeded type
@@ -1218,6 +1218,23 @@
   }
 }
 
+/// Interface for updating an [OutputUnitData] object with data for late
+/// members, that is, members created on demand during code generation.
+class LateOutputUnitDataBuilder {
+  final OutputUnitData _outputUnitData;
+
+  LateOutputUnitDataBuilder(this._outputUnitData);
+
+  /// Registers [newEntity] to be emitted in the same output unit as
+  /// [existingEntity];
+  void registerColocatedMembers(
+      MemberEntity existingEntity, MemberEntity newEntity) {
+    assert(_outputUnitData._memberToUnit[newEntity] == null);
+    _outputUnitData._memberToUnit[newEntity] =
+        _outputUnitData.outputUnitForMember(existingEntity);
+  }
+}
+
 /// Results of the deferred loading algorithm.
 ///
 /// Provides information about the output unit associated with entities and
@@ -1235,7 +1252,7 @@
   final Map<MemberEntity, OutputUnit> _memberToUnit;
   final Map<Local, OutputUnit> _localFunctionToUnit;
   final Map<ConstantValue, OutputUnit> _constantToUnit;
-  final Iterable<OutputUnit> outputUnits;
+  final List<OutputUnit> outputUnits;
   final Map<ImportEntity, String> _importDeferName;
 
   /// A mapping from the name of a defer import to all the output units it
@@ -1393,24 +1410,28 @@
   }
 
   /// Returns the [OutputUnit] where [cls] belongs.
-  OutputUnit outputUnitForClass(ClassEntity cls) {
+  // TODO(johnniwinther): Remove the need for [allowNull]. Dump-info currently
+  // needs it.
+  OutputUnit outputUnitForClass(ClassEntity cls, {bool allowNull: false}) {
     if (!isProgramSplit) return mainOutputUnit;
     OutputUnit unit = _classToUnit[cls];
+    assert(allowNull || unit != null, 'No output unit for class $cls');
     return unit ?? mainOutputUnit;
   }
 
+  OutputUnit outputUnitForClassForTesting(ClassEntity cls) => _classToUnit[cls];
+
   /// Returns the [OutputUnit] where [member] belongs.
   OutputUnit outputUnitForMember(MemberEntity member) {
     if (!isProgramSplit) return mainOutputUnit;
     OutputUnit unit = _memberToUnit[member];
-    if (unit != null) return unit;
-    if (member.isInstanceMember) {
-      return outputUnitForClass(member.enclosingClass);
-    }
-
-    return mainOutputUnit;
+    assert(unit != null, 'No output unit for member $member');
+    return unit ?? mainOutputUnit;
   }
 
+  OutputUnit outputUnitForMemberForTesting(MemberEntity member) =>
+      _memberToUnit[member];
+
   /// Direct access to the output-unit to constants map used for testing.
   Iterable<ConstantValue> get constantsForTesting => _constantToUnit.keys;
 
@@ -1420,6 +1441,9 @@
     return _constantToUnit[constant];
   }
 
+  OutputUnit outputUnitForConstantForTesting(ConstantValue constant) =>
+      _constantToUnit[constant];
+
   /// Indicates whether [element] is deferred.
   bool isDeferredClass(ClassEntity element) {
     return outputUnitForClass(element) != mainOutputUnit;
@@ -1456,22 +1480,14 @@
 
   /// Registers that a constant is used in the same deferred output unit as
   /// [field].
-  void registerConstantDeferredUse(
-      DeferredGlobalConstantValue constant, OutputUnit unit) {
+  void registerConstantDeferredUse(DeferredGlobalConstantValue constant) {
     if (!isProgramSplit) return;
+    OutputUnit unit = constant.unit;
     assert(
         _constantToUnit[constant] == null || _constantToUnit[constant] == unit);
     _constantToUnit[constant] = unit;
   }
 
-  /// Registers [newEntity] to be emitted in the same output unit as
-  /// [existingEntity];
-  void registerColocatedMembers(
-      MemberEntity existingEntity, MemberEntity newEntity) {
-    assert(_memberToUnit[newEntity] == null);
-    _memberToUnit[newEntity] = outputUnitForMember(existingEntity);
-  }
-
   /// Returns the unique name for the given deferred [import].
   String getImportDeferName(Spannable node, ImportEntity import) {
     String name = _importDeferName[import];
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 35be4dd..454d157 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -204,7 +204,7 @@
 
     classInfo.size = size;
 
-    if (!compiler.backend.emitter.neededClasses.contains(clazz) &&
+    if (!compiler.backend.emitterTask.neededClasses.contains(clazz) &&
         classInfo.fields.isEmpty &&
         classInfo.functions.isEmpty) {
       return null;
@@ -269,11 +269,13 @@
 
     List<ParameterInfo> parameters = <ParameterInfo>[];
     List<String> inferredParameterTypes = <String>[];
-    codegenWorldBuilder.forEachParameterAsLocal(function, (parameter) {
+
+    closedWorld.elementEnvironment.forEachParameterAsLocal(
+        closedWorld.globalLocalsMap, function, (parameter) {
       inferredParameterTypes.add('${_resultOfParameter(parameter)}');
     });
     int parameterIndex = 0;
-    codegenWorldBuilder.forEachParameter(function, (type, name, _) {
+    closedWorld.elementEnvironment.forEachParameter(function, (type, name, _) {
       parameters.add(new ParameterInfo(
           name, inferredParameterTypes[parameterIndex++], '$type'));
     });
@@ -348,7 +350,7 @@
           ? compiler.options.outputUri.pathSegments.last
           : deferredPartFileName(compiler.options, outputUnit.name);
       OutputUnitInfo info = new OutputUnitInfo(filename, outputUnit.name,
-          backend.emitter.emitter.generatedSize(outputUnit));
+          backend.emitterTask.emitter.generatedSize(outputUnit));
       info.imports
           .addAll(closedWorld.outputUnitData.getImportNames(outputUnit));
       result.outputUnits.add(info);
@@ -363,7 +365,7 @@
 
   OutputUnitInfo _unitInfoForClass(ClassEntity entity) {
     return _infoFromOutputUnit(
-        closedWorld.outputUnitData.outputUnitForClass(entity));
+        closedWorld.outputUnitData.outputUnitForClass(entity, allowNull: true));
   }
 
   OutputUnitInfo _unitInfoForConstant(ConstantValue constant) {
diff --git a/pkg/compiler/lib/src/elements/indexed.dart b/pkg/compiler/lib/src/elements/indexed.dart
index e83b8a0..6a6afc4 100644
--- a/pkg/compiler/lib/src/elements/indexed.dart
+++ b/pkg/compiler/lib/src/elements/indexed.dart
@@ -56,6 +56,8 @@
 
 /// Base implementation for an index based map of entities of type [E].
 abstract class EntityMapBase<E extends _Indexed> {
+  bool _closed = false;
+
   int _size = 0;
   List<E> _list = <E>[];
 
@@ -67,6 +69,14 @@
 
   /// Returns the number (null and non-null) entities in the map.
   int get length => _list.length;
+
+  /// Closes the entity map, prohibiting further registration.
+  ///
+  /// This is used to ensure that no new entities are added while serializing
+  /// modular code generation data.
+  void close() {
+    _closed = true;
+  }
 }
 
 /// Index based map of entities of type [E].
@@ -76,6 +86,8 @@
   /// The index of [entity] is set to match its index in the entity list in this
   /// map.
   E0 register<E0 extends E>(E0 entity) {
+    assert(
+        !_closed, "Trying to register $entity @ ${_list.length} when closed.");
     assert(entity != null);
     assert(entity._index == null);
     entity._index = _list.length;
@@ -134,6 +146,8 @@
   /// The index of [entity] is set to match its index in the entity and data
   /// lists in this map.
   E0 register<E0 extends E, D0 extends D>(E0 entity, D0 data) {
+    assert(
+        !_closed, "Trying to register $entity @ ${_list.length} when closed.");
     assert(entity != null);
     assert(entity._index == null);
     assert(
@@ -199,6 +213,8 @@
   /// environment lists in this map.
   E0 register<E0 extends E, D0 extends D, V0 extends V>(
       E0 entity, D0 data, V0 env) {
+    assert(
+        !_closed, "Trying to register $entity @ ${_list.length} when closed.");
     assert(entity != null);
     assert(entity._index == null);
     assert(
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index ef66b6e..81ca07d 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -6,6 +6,7 @@
 
 import 'dart:collection' show Queue;
 
+import 'common/codegen.dart';
 import 'common/tasks.dart' show CompilerTask;
 import 'common/work.dart' show WorkItem;
 import 'common.dart';
@@ -16,6 +17,7 @@
 import 'elements/entities.dart';
 import 'elements/types.dart';
 import 'inferrer/types.dart';
+import 'js_backend/backend.dart' show CodegenInputs;
 import 'js_backend/enqueuer.dart';
 import 'universe/member_usage.dart';
 import 'universe/resolution_world_builder.dart';
@@ -64,10 +66,13 @@
           ..onEmptyForTesting = compiler.onResolutionQueueEmptyForTesting;
   }
 
-  Enqueuer createCodegenEnqueuer(JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
-    Enqueuer enqueuer = compiler.backend.createCodegenEnqueuer(
-        this, compiler, closedWorld, globalInferenceResults)
+  Enqueuer createCodegenEnqueuer(
+      JClosedWorld closedWorld,
+      GlobalTypeInferenceResults globalInferenceResults,
+      CodegenInputs codegenInputs,
+      CodegenResults codegenResults) {
+    Enqueuer enqueuer = compiler.backend.createCodegenEnqueuer(this, compiler,
+        closedWorld, globalInferenceResults, codegenInputs, codegenResults)
       ..onEmptyForTesting = compiler.onCodegenQueueEmptyForTesting;
     if (retainDataForTesting) {
       codegenEnqueuerForTesting = enqueuer;
@@ -207,7 +212,7 @@
 
   /// Check enqueuer consistency after the queue has been closed.
   bool checkEnqueuerConsistency(ElementEnvironment elementEnvironment) {
-    task.measure(() {
+    task.measureSubtask('resolution.check', () {
       // Run through the classes and see if we need to enqueue more methods.
       for (ClassEntity classElement
           in worldBuilder.directlyInstantiatedClasses) {
@@ -283,11 +288,10 @@
   void _registerInstantiatedType(InterfaceType type,
       {ConstructorEntity constructor,
       bool nativeUsage: false,
-      bool globalDependency: false,
-      bool isRedirection: false}) {
-    task.measure(() {
+      bool globalDependency: false}) {
+    task.measureSubtask('resolution.typeUse', () {
       _worldBuilder.registerTypeInstantiation(type, _applyClassUse,
-          constructor: constructor, isRedirection: isRedirection);
+          constructor: constructor);
       listener.registerInstantiatedType(type,
           isGlobal: globalDependency, nativeUsage: nativeUsage);
     });
@@ -308,7 +312,7 @@
         _reporter.internalError(member,
             'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}');
       }
-    }, dryRun: true);
+    }, checkEnqueuerConsistency: true);
   }
 
   /// Callback for applying the use of a [member].
@@ -344,14 +348,14 @@
 
   @override
   void processDynamicUse(DynamicUse dynamicUse) {
-    task.measure(() {
+    task.measureSubtask('resolution.dynamicUse', () {
       _worldBuilder.registerDynamicUse(dynamicUse, _applyMemberUse);
     });
   }
 
   @override
   void processConstantUse(ConstantUse constantUse) {
-    task.measure(() {
+    task.measureSubtask('resolution.constantUse', () {
       if (_worldBuilder.registerConstantUse(constantUse)) {
         applyImpact(listener.registerUsedConstant(constantUse.value),
             impactSource: 'constant use');
@@ -362,24 +366,20 @@
 
   @override
   void processStaticUse(StaticUse staticUse) {
-    _worldBuilder.registerStaticUse(staticUse, _applyMemberUse);
-    // TODO(johnniwinther): Add `ResolutionWorldBuilder.registerConstructorUse`
-    // for these:
-    switch (staticUse.kind) {
-      case StaticUseKind.CONSTRUCTOR_INVOKE:
-      case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
-        _registerInstantiatedType(staticUse.type,
-            constructor: staticUse.element, globalDependency: false);
-        break;
-      case StaticUseKind.REDIRECTION:
-        _registerInstantiatedType(staticUse.type,
-            constructor: staticUse.element,
-            globalDependency: false,
-            isRedirection: true);
-        break;
-      default:
-        break;
-    }
+    task.measureSubtask('resolution.staticUse', () {
+      _worldBuilder.registerStaticUse(staticUse, _applyMemberUse);
+      // TODO(johnniwinther): Add `ResolutionWorldBuilder.registerConstructorUse`
+      // for these:
+      switch (staticUse.kind) {
+        case StaticUseKind.CONSTRUCTOR_INVOKE:
+        case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
+          _registerInstantiatedType(staticUse.type,
+              constructor: staticUse.element, globalDependency: false);
+          break;
+        default:
+          break;
+      }
+    });
   }
 
   @override
diff --git a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
index 1503b1d..a064777 100644
--- a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
@@ -8,6 +8,7 @@
 import '../elements/entities.dart';
 import '../elements/names.dart';
 import '../elements/types.dart' show DartType;
+import '../ir/static_type.dart';
 import '../serialization/serialization.dart';
 import '../universe/selector.dart';
 import '../universe/world_builder.dart';
@@ -161,6 +162,11 @@
   /// `Stream` class used for the `async*` implementation.
   AbstractValue get asyncStarStreamType;
 
+  /// Creates an [AbstractValue] corresponding to an expression of the given
+  /// static [type] and [classRelation].
+  AbstractValue createFromStaticType(DartType type,
+      [ClassRelation classRelation = ClassRelation.subtype]);
+
   /// Creates an [AbstractValue] for a non-null exact instance of [cls].
   AbstractValue createNonNullExact(ClassEntity cls);
 
diff --git a/pkg/compiler/lib/src/inferrer/trivial.dart b/pkg/compiler/lib/src/inferrer/trivial.dart
index 9d4d5ef..a7dd919 100644
--- a/pkg/compiler/lib/src/inferrer/trivial.dart
+++ b/pkg/compiler/lib/src/inferrer/trivial.dart
@@ -6,6 +6,7 @@
 import '../elements/entities.dart';
 import '../elements/names.dart';
 import '../elements/types.dart' show DartType;
+import '../ir/static_type.dart';
 import '../serialization/serialization.dart';
 import '../universe/selector.dart';
 import '../universe/world_builder.dart';
@@ -358,6 +359,11 @@
       const TrivialAbstractValue();
 
   @override
+  AbstractValue createFromStaticType(DartType type,
+          [ClassRelation classRelation = ClassRelation.subtype]) =>
+      const TrivialAbstractValue();
+
+  @override
   AbstractValue get asyncStarStreamType => const TrivialAbstractValue();
 
   @override
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/constants.dart b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
index 9b5232f..0994564 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
@@ -4,10 +4,8 @@
 
 library types.constants;
 
-import '../../common.dart';
 import '../../constants/constant_system.dart' as constant_system;
 import '../../constants/values.dart';
-import '../../js_backend/js_backend.dart' show SyntheticConstantKind;
 import '../../world.dart' show JClosedWorld;
 import 'masks.dart';
 
@@ -50,21 +48,20 @@
   }
 
   @override
-  TypeMask visitSynthetic(
-      SyntheticConstantValue constant, JClosedWorld closedWorld) {
-    switch (constant.valueKind) {
-      case SyntheticConstantKind.DUMMY_INTERCEPTOR:
-        return constant.payload;
-      case SyntheticConstantKind.EMPTY_VALUE:
-        return constant.payload;
-      case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
-        return closedWorld.abstractValueDomain.intType;
-      case SyntheticConstantKind.NAME:
-        return closedWorld.abstractValueDomain.stringType;
-      default:
-        throw failedAt(CURRENT_ELEMENT_SPANNABLE,
-            "Unexpected DummyConstantKind: ${constant.toStructuredText()}.");
-    }
+  TypeMask visitDummyInterceptor(
+      DummyInterceptorConstantValue constant, JClosedWorld closedWorld) {
+    return constant.abstractValue;
+  }
+
+  @override
+  TypeMask visitUnreachable(
+      UnreachableConstantValue constant, JClosedWorld closedWorld) {
+    return closedWorld.abstractValueDomain.emptyType;
+  }
+
+  @override
+  TypeMask visitJsName(JsNameConstantValue constant, JClosedWorld closedWorld) {
+    return closedWorld.abstractValueDomain.stringType;
   }
 
   @override
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
index 748c280..f487ba4 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
@@ -11,7 +11,8 @@
 import '../../constants/values.dart';
 import '../../elements/entities.dart';
 import '../../elements/names.dart';
-import '../../elements/types.dart' show DartType, InterfaceType, DynamicType;
+import '../../elements/types.dart';
+import '../../ir/static_type.dart';
 import '../../serialization/serialization.dart';
 import '../../universe/class_hierarchy.dart';
 import '../../universe/selector.dart' show Selector;
@@ -263,6 +264,35 @@
   }
 
   @override
+  AbstractValue createFromStaticType(DartType type,
+      [ClassRelation classRelation = ClassRelation.subtype]) {
+    while (type is TypeVariableType) {
+      TypeVariableType typeVariable = type;
+      type = _closedWorld.elementEnvironment
+          .getTypeVariableBound(typeVariable.element);
+      classRelation = ClassRelation.subtype;
+    }
+    if (type is InterfaceType) {
+      switch (classRelation) {
+        case ClassRelation.exact:
+          return new TypeMask.exact(type.element, _closedWorld);
+        case ClassRelation.thisExpression:
+          if (!_closedWorld.isUsedAsMixin(type.element)) {
+            return new TypeMask.subclass(type.element, _closedWorld);
+          }
+          break;
+        case ClassRelation.subtype:
+          break;
+      }
+      return new TypeMask.subtype(type.element, _closedWorld);
+    } else if (type is FunctionType) {
+      return new TypeMask.subtype(commonElements.functionClass, _closedWorld);
+    } else {
+      return dynamicType;
+    }
+  }
+
+  @override
   TypeMask excludeNull(TypeMask mask) => mask.nonNullable();
 
   @override
diff --git a/pkg/compiler/lib/src/inferrer/types.dart b/pkg/compiler/lib/src/inferrer/types.dart
index 265d76d..f68b519 100644
--- a/pkg/compiler/lib/src/inferrer/types.dart
+++ b/pkg/compiler/lib/src/inferrer/types.dart
@@ -129,9 +129,9 @@
 
   AbstractValue resultOfParameter(Local parameter);
 
-  /// Returns the type of a [selector] when applied to a receiver with the given
-  /// type [mask].
-  AbstractValue typeOfSelector(Selector selector, AbstractValue mask);
+  /// Returns the type of the result of applying [selector] to a receiver with
+  /// the given [receiver] type.
+  AbstractValue resultTypeOfSelector(Selector selector, AbstractValue receiver);
 
   /// Returns whether a fixed-length constructor call goes through a growable
   /// check.
@@ -290,10 +290,9 @@
     return parameterResults[parameter] ?? _trivialParameterResult;
   }
 
-  /// Returns the type of a [selector] when applied to a receiver with the given
-  /// [receiver] type.
   @override
-  AbstractValue typeOfSelector(Selector selector, AbstractValue receiver) {
+  AbstractValue resultTypeOfSelector(
+      Selector selector, AbstractValue receiver) {
     // Bailout for closure calls. We're not tracking types of
     // closures.
     if (selector.isClosureCall)
@@ -462,7 +461,7 @@
   bool isFixedArrayCheckedForGrowable(ir.Node node) => false;
 
   @override
-  AbstractValue typeOfSelector(Selector selector, AbstractValue mask) {
+  AbstractValue resultTypeOfSelector(Selector selector, AbstractValue mask) {
     return closedWorld.abstractValueDomain.dynamicType;
   }
 
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 732b841..cb1c2a4 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -11,12 +11,16 @@
 import '../js/js.dart' as js;
 import '../js/js_debug.dart';
 import '../js/js_source_mapping.dart';
+import '../serialization/serialization.dart';
+import '../util/util.dart';
 import 'code_output.dart' show BufferedCodeOutput;
 import 'source_information.dart';
 
 /// [SourceInformation] that consists of an offset position into the source
 /// code.
 class PositionSourceInformation extends SourceInformation {
+  static const String tag = 'source-information';
+
   @override
   final SourceLocation startPosition;
 
@@ -29,6 +33,36 @@
   PositionSourceInformation(
       this.startPosition, this.innerPosition, this.inliningContext);
 
+  factory PositionSourceInformation.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    SourceLocation startPosition = source.readCached<SourceLocation>(
+        () => SourceLocation.readFromDataSource(source));
+    SourceLocation innerPosition = source.readCached<SourceLocation>(
+        () => SourceLocation.readFromDataSource(source));
+    List<FrameContext> inliningContext = source.readList(
+        () => FrameContext.readFromDataSource(source),
+        emptyAsNull: true);
+    source.end(tag);
+    return new PositionSourceInformation(
+        startPosition, innerPosition, inliningContext);
+  }
+
+  void writeToDataSinkInternal(DataSink sink) {
+    sink.begin(tag);
+    sink.writeCached(
+        startPosition,
+        (SourceLocation sourceLocation) =>
+            SourceLocation.writeToDataSink(sink, sourceLocation));
+    sink.writeCached(
+        innerPosition,
+        (SourceLocation sourceLocation) =>
+            SourceLocation.writeToDataSink(sink, sourceLocation));
+    sink.writeList(inliningContext,
+        (FrameContext context) => context.writeToDataSink(sink),
+        allowNull: true);
+    sink.end(tag);
+  }
+
   @override
   List<SourceLocation> get sourceLocations {
     List<SourceLocation> list = <SourceLocation>[];
@@ -52,16 +86,17 @@
 
   @override
   int get hashCode {
-    return 0x7FFFFFFF &
-        (startPosition.hashCode * 17 + innerPosition.hashCode * 19);
+    return Hashing.listHash(
+        inliningContext, Hashing.objectsHash(startPosition, innerPosition));
   }
 
   @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
-    if (other is! PositionSourceInformation) return false;
-    return startPosition == other.startPosition &&
-        innerPosition == other.innerPosition;
+    return other is PositionSourceInformation &&
+        startPosition == other.startPosition &&
+        innerPosition == other.innerPosition &&
+        equalElements(inliningContext, other.inliningContext);
   }
 
   /// Create a textual representation of the source information using [uriText]
@@ -647,18 +682,18 @@
   /// (@ marks the current JavaScript position and ^ point to the mapped Dart
   /// code position.)
   static CallPosition getSemanticPositionForCall(js.Call node) {
-    if (node.target is js.PropertyAccess) {
-      js.PropertyAccess access = node.target;
+    js.Expression access = js.undefer(node.target);
+    if (access is js.PropertyAccess) {
       js.Node target = access;
       bool pureAccess = false;
       while (target is js.PropertyAccess) {
         js.PropertyAccess targetAccess = target;
-        if (targetAccess.receiver is js.VariableUse ||
-            targetAccess.receiver is js.This) {
+        js.Node receiver = js.undefer(targetAccess.receiver);
+        if (receiver is js.VariableUse || receiver is js.This) {
           pureAccess = true;
           break;
         } else {
-          target = targetAccess.receiver;
+          target = receiver;
         }
       }
       if (pureAccess) {
@@ -672,19 +707,19 @@
         return new CallPosition(
             access.selector, CodePositionKind.START, SourcePositionKind.INNER);
       }
-    } else if (node.target is js.VariableUse || node.target is js.This) {
+    } else if (access is js.VariableUse || access is js.This) {
       // m()   this()
       // ^     ^
       return new CallPosition(
           node, CodePositionKind.START, SourcePositionKind.START);
-    } else if (node.target is js.Fun ||
-        node.target is js.New ||
-        node.target is js.NamedFunction) {
+    } else if (access is js.Fun ||
+        access is js.New ||
+        access is js.NamedFunction) {
       // function(){}()  new Function("...")()   function foo(){}()
       //             ^                      ^                    ^
       return new CallPosition(
           node.target, CodePositionKind.END, SourcePositionKind.INNER);
-    } else if (node.target is js.Binary || node.target is js.Call) {
+    } else if (access is js.Binary || access is js.Call) {
       // (0,a)()   m()()
       //      ^       ^
       return new CallPosition(
@@ -1271,6 +1306,11 @@
     statementOffset = null;
   }
 
+  @override
+  visitDeferredExpression(js.DeferredExpression node) {
+    visit(node.value);
+  }
+
   Offset getOffsetForNode(js.Node node, int codeOffset) {
     if (codeOffset == null) {
       CodePosition codePosition = codePositions[node];
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index 64ca507..0034fb5 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -8,14 +8,41 @@
 import '../common.dart';
 import '../elements/entities.dart';
 import '../js/js.dart' show JavaScriptNodeSourceInformation;
+import '../serialization/serialization.dart';
 import '../universe/call_structure.dart';
 import 'source_file.dart';
+import 'position_information.dart';
 
 /// Interface for passing source information, for instance for use in source
 /// maps, through the backend.
 abstract class SourceInformation extends JavaScriptNodeSourceInformation {
   const SourceInformation();
 
+  static SourceInformation readFromDataSource(DataSource source) {
+    int hasSourceInformation = source.readInt();
+    if (hasSourceInformation == 0) {
+      return null;
+    } else if (hasSourceInformation == 1) {
+      return const SourceMappedMarker();
+    } else {
+      assert(hasSourceInformation == 2);
+      return PositionSourceInformation.readFromDataSource(source);
+    }
+  }
+
+  static void writeToDataSink(
+      DataSink sink, SourceInformation sourceInformation) {
+    if (sourceInformation == null) {
+      sink.writeInt(0);
+    } else if (sourceInformation is SourceMappedMarker) {
+      sink.writeInt(1);
+    } else {
+      sink.writeInt(2);
+      PositionSourceInformation positionSourceInformation = sourceInformation;
+      positionSourceInformation.writeToDataSinkInternal(sink);
+    }
+  }
+
   SourceSpan get sourceSpan;
 
   /// The source location associated with the start of the JS node.
@@ -45,6 +72,8 @@
 /// precise data about inlining that can then be used by defobuscation tools
 /// when reconstructing a source stack from a production stack trace.
 class FrameContext {
+  static const String tag = 'frame-context';
+
   /// Location of the call that was inlined.
   final SourceInformation callInformation;
 
@@ -53,6 +82,25 @@
 
   FrameContext(this.callInformation, this.inlinedMethodName);
 
+  factory FrameContext.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    SourceInformation callInformation = source.readCached<SourceInformation>(
+        () => SourceInformation.readFromDataSource(source));
+    String inlinedMethodName = source.readString();
+    source.end(tag);
+    return new FrameContext(callInformation, inlinedMethodName);
+  }
+
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeCached<SourceInformation>(
+        callInformation,
+        (SourceInformation sourceInformation) =>
+            SourceInformation.writeToDataSink(sink, sourceInformation));
+    sink.writeString(inlinedMethodName);
+    sink.end(tag);
+  }
+
   @override
   String toString() => "(FrameContext: $callInformation, $inlinedMethodName)";
 }
@@ -206,6 +254,8 @@
 
 /// A location in a source file.
 abstract class SourceLocation {
+  static const String tag = 'source-location';
+
   const SourceLocation();
 
   /// The absolute URI of the source file of this source location.
@@ -223,8 +273,42 @@
   /// The name associated with this source location, if any.
   String get sourceName;
 
-  /// `true` if the offset within the length of the source file.
-  bool get isValid;
+  static SourceLocation readFromDataSource(DataSource source) {
+    int hasSourceLocation = source.readInt();
+    if (hasSourceLocation == 0) {
+      return null;
+    } else if (hasSourceLocation == 1) {
+      return const NoSourceLocationMarker();
+    } else {
+      assert(hasSourceLocation == 2);
+      source.begin(tag);
+      Uri sourceUri = source.readUri();
+      int offset = source.readInt();
+      int line = source.readInt();
+      int column = source.readInt();
+      String sourceName = source.readString();
+      source.end(tag);
+      return new DirectSourceLocation(
+          sourceUri, offset, line, column, sourceName);
+    }
+  }
+
+  static void writeToDataSink(DataSink sink, SourceLocation sourceLocation) {
+    if (sourceLocation == null) {
+      sink.writeInt(0);
+    } else if (sourceLocation is NoSourceLocationMarker) {
+      sink.writeInt(1);
+    } else {
+      sink.writeInt(2);
+      sink.begin(tag);
+      sink.writeUri(sourceLocation.sourceUri);
+      sink.writeInt(sourceLocation.offset);
+      sink.writeInt(sourceLocation.line);
+      sink.writeInt(sourceLocation.column);
+      sink.writeString(sourceLocation.sourceName);
+      sink.end(tag);
+    }
+  }
 
   @override
   int get hashCode {
@@ -236,8 +320,8 @@
   @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
-    if (other is! SourceLocation) return false;
-    return sourceUri == other.sourceUri &&
+    return other is SourceLocation &&
+        sourceUri == other.sourceUri &&
         offset == other.offset &&
         sourceName == other.sourceName;
   }
@@ -248,6 +332,26 @@
   String toString() => '${sourceUri}:[${line},${column}]';
 }
 
+class DirectSourceLocation extends SourceLocation {
+  @override
+  final Uri sourceUri;
+
+  @override
+  final int offset;
+
+  @override
+  final int line;
+
+  @override
+  final int column;
+
+  @override
+  final String sourceName;
+
+  DirectSourceLocation(
+      this.sourceUri, this.offset, this.line, this.column, this.sourceName);
+}
+
 /// A location in a source file.
 abstract class AbstractSourceLocation extends SourceLocation {
   final SourceFile _sourceFile;
@@ -255,7 +359,7 @@
 
   AbstractSourceLocation(this._sourceFile) {
     assert(
-        isValid,
+        offset < _sourceFile.length,
         failedAt(
             new SourceSpan(sourceUri, 0, 0),
             "Invalid source location in ${sourceUri}: "
@@ -283,9 +387,6 @@
   String get sourceName;
 
   @override
-  bool get isValid => offset < _sourceFile.length;
-
-  @override
   String get shortText => '${sourceUri.pathSegments.last}:[$line,$column]';
 
   @override
@@ -359,9 +460,6 @@
   Uri get sourceUri => null;
 
   @override
-  bool get isValid => true;
-
-  @override
   String get sourceName => null;
 
   @override
diff --git a/pkg/compiler/lib/src/ir/annotations.dart b/pkg/compiler/lib/src/ir/annotations.dart
index ae07571..4e10bf8 100644
--- a/pkg/compiler/lib/src/ir/annotations.dart
+++ b/pkg/compiler/lib/src/ir/annotations.dart
@@ -4,6 +4,7 @@
 
 import 'package:kernel/ast.dart' as ir;
 import '../common/names.dart';
+import 'modular.dart';
 
 class IrAnnotationData {
   Map<ir.Class, String> _nativeClassNames = {};
@@ -119,7 +120,8 @@
   }
 }
 
-IrAnnotationData processAnnotations(ir.Component component) {
+IrAnnotationData processAnnotations(ModularCore modularCore) {
+  ir.Component component = modularCore.component;
   IrAnnotationData data = new IrAnnotationData();
 
   void processMember(ir.Member member) {
@@ -128,7 +130,8 @@
     List<String> returnsAnnotations;
     for (ir.Expression annotation in member.annotations) {
       if (annotation is ir.ConstantExpression) {
-        ir.Constant constant = annotation.constant;
+        ir.Constant constant =
+            modularCore.constantEvaluator.evaluate(annotation);
 
         String jsName = _getJsInteropName(constant);
         if (jsName != null) {
@@ -175,7 +178,8 @@
   for (ir.Library library in component.libraries) {
     for (ir.Expression annotation in library.annotations) {
       if (annotation is ir.ConstantExpression) {
-        ir.Constant constant = annotation.constant;
+        ir.Constant constant =
+            modularCore.constantEvaluator.evaluate(annotation);
 
         String jsName = _getJsInteropName(constant);
         if (jsName != null) {
@@ -186,7 +190,8 @@
     for (ir.Class cls in library.classes) {
       for (ir.Expression annotation in cls.annotations) {
         if (annotation is ir.ConstantExpression) {
-          ir.Constant constant = annotation.constant;
+          ir.Constant constant =
+              modularCore.constantEvaluator.evaluate(annotation);
 
           String nativeClassName = _getNativeClassName(constant);
           if (nativeClassName != null) {
@@ -357,6 +362,8 @@
     if (metadata is! ir.ConstantExpression) continue;
     ir.ConstantExpression constantExpression = metadata;
     ir.Constant constant = constantExpression.constant;
+    assert(constant is! ir.UnevaluatedConstant,
+        "Unexpected unevaluated constant on $member: $metadata");
     PragmaAnnotationData data = _getPragmaAnnotation(constant);
     if (data != null) {
       annotations.add(data);
diff --git a/pkg/compiler/lib/src/ir/cached_static_type.dart b/pkg/compiler/lib/src/ir/cached_static_type.dart
index 6067b5e..ea00634 100644
--- a/pkg/compiler/lib/src/ir/cached_static_type.dart
+++ b/pkg/compiler/lib/src/ir/cached_static_type.dart
@@ -8,12 +8,14 @@
 import 'package:kernel/type_algebra.dart' as ir;
 import 'package:kernel/type_environment.dart' as ir;
 import 'static_type_base.dart';
+import 'static_type_cache.dart';
 import 'static_type_provider.dart';
 
 /// Class that provides the static type of expression using the visitor pattern
 /// and a precomputed cache for complex expression type.
 class CachedStaticType extends StaticTypeBase implements StaticTypeProvider {
-  final Map<ir.Expression, ir.DartType> _cache;
+  final StaticTypeCache _cache;
+
   @override
   final ThisInterfaceType thisType;
 
@@ -28,6 +30,13 @@
     return type;
   }
 
+  @override
+  ir.DartType getForInIteratorType(ir.ForInStatement node) {
+    ir.DartType type = _cache.getForInIteratorType(node);
+    assert(type != null, "No for-in iterator type found for ${node}.");
+    return type;
+  }
+
   ir.DartType _getStaticType(ir.Expression node) {
     ir.DartType type = _cache[node];
     assert(type != null, "No static type cached for ${node.runtimeType}.");
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index d635b78..8799d9b 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -15,7 +15,7 @@
 import 'runtime_type_analysis.dart';
 import 'scope.dart';
 import 'static_type.dart';
-import 'static_type_base.dart';
+import 'static_type_cache.dart';
 import 'util.dart';
 
 /// Interface for collecting world impact data.
@@ -77,9 +77,11 @@
 
   void registerThrow();
 
-  void registerSyncForIn(ir.DartType iterableType);
+  void registerSyncForIn(ir.DartType iterableType, ir.DartType iteratorType,
+      ClassRelation iteratorClassRelation);
 
-  void registerAsyncForIn(ir.DartType iterableType);
+  void registerAsyncForIn(ir.DartType iterableType, ir.DartType iteratorType,
+      ClassRelation iteratorClassRelation);
 
   void registerCatch();
 
@@ -200,16 +202,6 @@
       ir.ClassHierarchy classHierarchy, this.variableScopeModel)
       : super(typeEnvironment, classHierarchy);
 
-  ClassRelation _computeClassRelationFromType(ir.DartType type) {
-    if (type is ThisInterfaceType) {
-      return ClassRelation.thisExpression;
-    } else if (type is ExactInterfaceType) {
-      return ClassRelation.exact;
-    } else {
-      return ClassRelation.subtype;
-    }
-  }
-
   @override
   void handleIntLiteral(ir.IntLiteral node) {
     registerIntLiteral(node.value);
@@ -378,11 +370,14 @@
   }
 
   @override
-  void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType) {
+  void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType,
+      ir.DartType iteratorType) {
     if (node.isAsync) {
-      registerAsyncForIn(iterableType);
+      registerAsyncForIn(iterableType, iteratorType,
+          computeClassRelationFromType(iteratorType));
     } else {
-      registerSyncForIn(iterableType);
+      registerSyncForIn(iterableType, iteratorType,
+          computeClassRelationFromType(iteratorType));
     }
   }
 
@@ -536,7 +531,7 @@
       registerLocalFunctionInvocation(receiver.variable.parent,
           positionArguments, namedArguments, typeArguments);
     } else {
-      ClassRelation relation = _computeClassRelationFromType(receiverType);
+      ClassRelation relation = computeClassRelationFromType(receiverType);
 
       ir.Member interfaceTarget = node.interfaceTarget;
       if (interfaceTarget == null) {
@@ -584,7 +579,7 @@
   @override
   void handlePropertyGet(
       ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {
-    ClassRelation relation = _computeClassRelationFromType(receiverType);
+    ClassRelation relation = computeClassRelationFromType(receiverType);
     if (node.interfaceTarget != null) {
       registerInstanceGet(receiverType, relation, node.interfaceTarget);
     } else {
@@ -601,7 +596,7 @@
   @override
   void handlePropertySet(
       ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) {
-    ClassRelation relation = _computeClassRelationFromType(receiverType);
+    ClassRelation relation = computeClassRelationFromType(receiverType);
     if (node.interfaceTarget != null) {
       registerInstanceSet(receiverType, relation, node.interfaceTarget);
     } else {
@@ -682,7 +677,7 @@
     }
     node.accept(this);
     return new ImpactBuilderData(
-        impactData, typeMapsForTesting, cachedStaticTypes);
+        impactData, typeMapsForTesting, getStaticTypeCache());
   }
 }
 
@@ -693,7 +688,7 @@
 class ImpactBuilderData {
   final ImpactData impactData;
   final Map<ir.Expression, TypeMap> typeMapsForTesting;
-  final Map<ir.Expression, ir.DartType> cachedStaticTypes;
+  final StaticTypeCache cachedStaticTypes;
 
   ImpactBuilderData(
       this.impactData, this.typeMapsForTesting, this.cachedStaticTypes);
diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart
index 543d3ed..79a7960 100644
--- a/pkg/compiler/lib/src/ir/impact_data.dart
+++ b/pkg/compiler/lib/src/ir/impact_data.dart
@@ -259,13 +259,21 @@
   }
 
   @override
-  void registerAsyncForIn(ir.DartType iterableType) {
-    _registerTypeUse(iterableType, _TypeUseKind.asyncForIn);
+  void registerAsyncForIn(ir.DartType iterableType, ir.DartType iteratorType,
+      ClassRelation iteratorClassRelation) {
+    _data._forInData ??= [];
+    _data._forInData.add(new _ForInData(
+        iterableType, iteratorType, iteratorClassRelation,
+        isAsync: true));
   }
 
   @override
-  void registerSyncForIn(ir.DartType iterableType) {
-    _registerTypeUse(iterableType, _TypeUseKind.syncForIn);
+  void registerSyncForIn(ir.DartType iterableType, ir.DartType iteratorType,
+      ClassRelation iteratorClassRelation) {
+    _data._forInData ??= [];
+    _data._forInData.add(new _ForInData(
+        iterableType, iteratorType, iteratorClassRelation,
+        isAsync: false));
   }
 
   @override
@@ -506,6 +514,7 @@
   List<double> _doubleLiterals;
   List<int> _intLiterals;
   List<_RuntimeTypeUse> _runtimeTypeUses;
+  List<_ForInData> _forInData;
 
   // TODO(johnniwinther): Remove these when CFE provides constants.
   List<ir.Constructor> _constructorNodes;
@@ -868,12 +877,6 @@
           case _TypeUseKind.catchType:
             registry.registerCatchType(data.type);
             break;
-          case _TypeUseKind.asyncForIn:
-            registry.registerAsyncForIn(data.type);
-            break;
-          case _TypeUseKind.syncForIn:
-            registry.registerSyncForIn(data.type);
-            break;
           case _TypeUseKind.asCast:
             registry.registerAsCast(data.type);
             break;
@@ -997,6 +1000,17 @@
             data.node, data.kind, data.receiverType, data.argumentType);
       }
     }
+    if (_forInData != null) {
+      for (_ForInData data in _forInData) {
+        if (data.isAsync) {
+          registry.registerAsyncForIn(
+              data.iterableType, data.iteratorType, data.iteratorClassRelation);
+        } else {
+          registry.registerSyncForIn(
+              data.iterableType, data.iteratorType, data.iteratorClassRelation);
+        }
+      }
+    }
 
     // TODO(johnniwinther): Remove these when CFE provides constants.
     if (_constructorNodes != null) {
@@ -1415,8 +1429,6 @@
 enum _TypeUseKind {
   parameterCheck,
   catchType,
-  asyncForIn,
-  syncForIn,
   asCast,
   implicitCast,
   isCheck,
@@ -1606,3 +1618,34 @@
     sink.end(tag);
   }
 }
+
+class _ForInData {
+  static const String tag = '_ForInData';
+
+  final ir.DartType iterableType;
+  final ir.DartType iteratorType;
+  final ClassRelation iteratorClassRelation;
+  final bool isAsync;
+
+  _ForInData(this.iterableType, this.iteratorType, this.iteratorClassRelation,
+      {this.isAsync});
+
+  factory _ForInData.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.DartType iterableType = source.readDartTypeNode();
+    ir.DartType iteratorType = source.readDartTypeNode(allowNull: true);
+    ClassRelation iteratorClassRelation = source.readEnum(ClassRelation.values);
+    bool isAsync = source.readBool();
+    return new _ForInData(iterableType, iteratorType, iteratorClassRelation,
+        isAsync: isAsync);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNode(iterableType);
+    sink.writeDartTypeNode(iteratorType);
+    sink.writeEnum(iteratorClassRelation);
+    sink.writeBool(isAsync);
+    sink.end(tag);
+  }
+}
diff --git a/pkg/compiler/lib/src/ir/modular.dart b/pkg/compiler/lib/src/ir/modular.dart
index 9d7ea73..37eb213 100644
--- a/pkg/compiler/lib/src/ir/modular.dart
+++ b/pkg/compiler/lib/src/ir/modular.dart
@@ -11,9 +11,17 @@
 import '../js_backend/annotations.dart';
 import '../util/enumset.dart';
 import 'annotations.dart';
+import 'constants.dart';
 import 'impact.dart';
 import 'scope.dart';
 
+class ModularCore {
+  final ir.Component component;
+  final Dart2jsConstantEvaluator constantEvaluator;
+
+  ModularCore(this.component, this.constantEvaluator);
+}
+
 class ModularMemberData {
   final ScopeModel scopeModel;
   final ImpactBuilderData impactBuilderData;
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 9731e80..ba35b89 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -12,6 +12,7 @@
 import 'runtime_type_analysis.dart';
 import 'scope.dart';
 import 'static_type_base.dart';
+import 'static_type_cache.dart';
 
 /// Enum values for how the target of a static type should be interpreted.
 enum ClassRelation {
@@ -27,6 +28,16 @@
   exact,
 }
 
+ClassRelation computeClassRelationFromType(ir.DartType type) {
+  if (type is ThisInterfaceType) {
+    return ClassRelation.thisExpression;
+  } else if (type is ExactInterfaceType) {
+    return ClassRelation.exact;
+  } else {
+    return ClassRelation.subtype;
+  }
+}
+
 /// Visitor that computes and caches the static type of expression while
 /// visiting the full tree at expression level.
 ///
@@ -35,7 +46,8 @@
 /// adds 'handleX' hooks for subclasses to handle individual expressions using
 /// the readily compute static types of subexpressions.
 abstract class StaticTypeVisitor extends StaticTypeBase {
-  Map<ir.Expression, ir.DartType> _cache = {};
+  final Map<ir.Expression, ir.DartType> _expressionTypeCache = {};
+  Map<ir.ForInStatement, ir.DartType> _forInIteratorTypeCache;
   Map<ir.Expression, TypeMap> typeMapsForTesting;
   Map<ir.PropertyGet, RuntimeTypeUseData> _pendingRuntimeTypeUseData = {};
 
@@ -46,7 +58,9 @@
   StaticTypeVisitor(ir.TypeEnvironment typeEnvironment, this.hierarchy)
       : super(typeEnvironment);
 
-  Map<ir.Expression, ir.DartType> get cachedStaticTypes => _cache;
+  StaticTypeCache getStaticTypeCache() {
+    return new StaticTypeCache(_expressionTypeCache, _forInIteratorTypeCache);
+  }
 
   /// If `true`, the effect of executing assert statements is taken into account
   /// when computing the static type.
@@ -141,6 +155,13 @@
     visitNodes(node.fields);
   }
 
+  ir.InterfaceType getInterfaceTypeOf(ir.DartType type) {
+    while (type is ir.TypeParameterType) {
+      type = (type as ir.TypeParameterType).parameter.bound;
+    }
+    return type is ir.InterfaceType ? type : null;
+  }
+
   /// Returns the static type of the expression as an instantiation of
   /// [superclass].
   ///
@@ -215,8 +236,8 @@
   @override
   ir.DartType visitPropertyGet(ir.PropertyGet node) {
     ir.DartType receiverType = visitNode(node.receiver);
-    ir.DartType resultType =
-        _cache[node] = _computePropertyGetType(node, receiverType);
+    ir.DartType resultType = _expressionTypeCache[node] =
+        _computePropertyGetType(node, receiverType);
     receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
     handlePropertyGet(node, receiverType, resultType);
     if (node.name.name == Identifiers.runtimeType_) {
@@ -297,7 +318,7 @@
     receiverType = getTypeAsInstanceOf(receiverType, superclass);
     ir.DartType resultType = ir.Substitution.fromInterfaceType(receiverType)
         .substituteType(node.target.getterType);
-    _cache[node] = resultType;
+    _expressionTypeCache[node] = resultType;
     handleDirectPropertyGet(node, receiverType, resultType);
     return resultType;
   }
@@ -326,7 +347,7 @@
               node.target.function.typeParameters, node.arguments.types)
           .substituteType(returnType);
     }
-    _cache[node] = returnType;
+    _expressionTypeCache[node] = returnType;
     handleDirectMethodInvocation(node, receiverType, argumentTypes, returnType);
     return returnType;
   }
@@ -500,7 +521,7 @@
       ir.VariableGet get = new ir.VariableGet(variable)..parent = parent;
       // Visit the newly created variable get.
       handleVariableGet(get, argumentType);
-      cachedStaticTypes[get] = argumentType;
+      _expressionTypeCache[get] = argumentType;
 
       if (checkedParameterType == null) {
         return get;
@@ -682,7 +703,7 @@
             .promote(right.variable, right.variable.type, isTrue: true);
       }
     }
-    _cache[node] = returnType;
+    _expressionTypeCache[node] = returnType;
     handleMethodInvocation(node, receiverType, argumentTypes, returnType);
     return returnType;
   }
@@ -701,7 +722,7 @@
             typeEnvironment.isSubtypeOf(promotedType, node.promotedType),
         "Unexpected promotion of ${node.variable} in ${node.parent}. "
         "Expected ${node.promotedType}, found $promotedType");
-    _cache[node] = promotedType;
+    _expressionTypeCache[node] = promotedType;
     handleVariableGet(node, promotedType);
     return promotedType;
   }
@@ -748,7 +769,7 @@
     ir.DartType returnType = ir.Substitution.fromPairs(
             node.target.function.typeParameters, node.arguments.types)
         .substituteType(node.target.function.returnType);
-    _cache[node] = returnType;
+    _expressionTypeCache[node] = returnType;
     handleStaticInvocation(node, argumentTypes, returnType);
     return returnType;
   }
@@ -763,7 +784,7 @@
         ? new ExactInterfaceType.from(node.target.enclosingClass.rawType)
         : new ExactInterfaceType(
             node.target.enclosingClass, node.arguments.types);
-    _cache[node] = resultType;
+    _expressionTypeCache[node] = resultType;
     handleConstructorInvocation(node, argumentTypes, resultType);
     return resultType;
   }
@@ -788,7 +809,7 @@
             .substituteType(node.interfaceTarget.getterType);
       }
     }
-    _cache[node] = resultType;
+    _expressionTypeCache[node] = resultType;
     handleSuperPropertyGet(node, resultType);
     return resultType;
   }
@@ -824,7 +845,7 @@
               node.arguments.types)
           .substituteType(returnType);
     }
-    _cache[node] = returnType;
+    _expressionTypeCache[node] = returnType;
     handleSuperMethodInvocation(node, argumentTypes, returnType);
     return returnType;
   }
@@ -919,7 +940,7 @@
 
   @override
   ir.DartType visitLet(ir.Let node) {
-    visitNode(node.variable.initializer);
+    _processLocalVariable(node.variable);
     return super.visitLet(node);
   }
 
@@ -943,7 +964,7 @@
   ir.DartType visitInstantiation(ir.Instantiation node) {
     ir.FunctionType expressionType = visitNode(node.expression);
     ir.DartType resultType = _computeInstantiationType(node, expressionType);
-    _cache[node] = resultType;
+    _expressionTypeCache[node] = resultType;
     handleInstantiation(node, expressionType, resultType);
     return resultType;
   }
@@ -1071,14 +1092,18 @@
 
   @override
   ir.DartType visitFunctionExpression(ir.FunctionExpression node) {
+    TypeMap beforeClosure =
+        typeMap.remove(variableScopeModel.getScopeFor(node).assignedVariables);
+    typeMap = typeMap.remove(variableScopeModel.assignedVariables);
     ir.DartType returnType = super.visitFunctionExpression(node);
     Set<ir.VariableDeclaration> _oldVariables = _currentVariables;
-    _currentVariables = new Set<ir.VariableDeclaration>();
+    _currentVariables = {};
     visitSignature(node.function);
     visitNode(node.function.body);
     handleFunctionExpression(node);
     _invalidatedVariables.removeAll(_currentVariables);
     _currentVariables = _oldVariables;
+    typeMap = beforeClosure;
     return returnType;
   }
 
@@ -1172,16 +1197,42 @@
     typeMap = beforeLoop;
   }
 
-  void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType) {}
+  void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType,
+      ir.DartType iteratorType) {}
 
   @override
   Null visitForInStatement(ir.ForInStatement node) {
+    // For sync for-in [iterableType] is a subtype of `Iterable`, for async
+    // for-in [iterableType] is a subtype of `Stream`.
     ir.DartType iterableType = visitNode(node.iterable);
+    ir.DartType iteratorType = const ir.DynamicType();
+    if (node.isAsync) {
+      ir.InterfaceType streamInterfaceType = getInterfaceTypeOf(iterableType);
+      ir.InterfaceType streamType = typeEnvironment.getTypeAsInstanceOf(
+          streamInterfaceType, typeEnvironment.coreTypes.streamClass);
+      if (streamType != null) {
+        iteratorType = new ir.InterfaceType(
+            typeEnvironment.coreTypes.streamIteratorClass,
+            streamType.typeArguments);
+      }
+    } else {
+      ir.InterfaceType iterableInterfaceType = getInterfaceTypeOf(iterableType);
+      ir.Member member = hierarchy.getInterfaceMember(
+          iterableInterfaceType.classNode, new ir.Name(Identifiers.iterator));
+      if (member != null) {
+        iteratorType = ir.Substitution.fromInterfaceType(
+                typeEnvironment.getTypeAsInstanceOf(
+                    iterableInterfaceType, member.enclosingClass))
+            .substituteType(member.getterType);
+      }
+    }
+    _forInIteratorTypeCache ??= {};
+    _forInIteratorTypeCache[node] = iteratorType;
     TypeMap beforeLoop = typeMap =
         typeMap.remove(variableScopeModel.getScopeFor(node).assignedVariables);
     visitNode(node.variable);
     visitNode(node.body);
-    handleForInStatement(node, iterableType);
+    handleForInStatement(node, iterableType, iteratorType);
     typeMap = beforeLoop;
   }
 
@@ -1288,9 +1339,10 @@
   @override
   Null visitFunctionDeclaration(ir.FunctionDeclaration node) {
     TypeMap beforeClosure =
-        typeMap = typeMap.remove(variableScopeModel.assignedVariables);
+        typeMap.remove(variableScopeModel.getScopeFor(node).assignedVariables);
+    typeMap = typeMap.remove(variableScopeModel.assignedVariables);
     Set<ir.VariableDeclaration> _oldVariables = _currentVariables;
-    _currentVariables = new Set<ir.VariableDeclaration>();
+    _currentVariables = {};
     visitSignature(node.function);
     visitNode(node.function.body);
     handleFunctionDeclaration(node);
@@ -1320,7 +1372,7 @@
   @override
   Null visitProcedure(ir.Procedure node) {
     thisType = new ThisInterfaceType.from(node.enclosingClass?.thisType);
-    _currentVariables = new Set<ir.VariableDeclaration>();
+    _currentVariables = {};
     visitSignature(node.function);
     visitNode(node.function.body);
     handleProcedure(node);
@@ -1334,7 +1386,7 @@
   @override
   Null visitConstructor(ir.Constructor node) {
     thisType = new ThisInterfaceType.from(node.enclosingClass.thisType);
-    _currentVariables = new Set<ir.VariableDeclaration>();
+    _currentVariables = {};
     visitSignature(node.function);
     visitNodes(node.initializers);
     visitNode(node.function.body);
@@ -1349,7 +1401,7 @@
   @override
   Null visitField(ir.Field node) {
     thisType = new ThisInterfaceType.from(node.enclosingClass?.thisType);
-    _currentVariables = new Set<ir.VariableDeclaration>();
+    _currentVariables = {};
     visitNode(node.initializer);
     handleField(node);
     _invalidatedVariables.removeAll(_currentVariables);
@@ -1359,8 +1411,7 @@
 
   void handleVariableDeclaration(ir.VariableDeclaration node) {}
 
-  @override
-  Null visitVariableDeclaration(ir.VariableDeclaration node) {
+  void _processLocalVariable(ir.VariableDeclaration node) {
     _currentVariables.add(node);
     ir.DartType type = visitNode(node.initializer);
     if (node.initializer != null &&
@@ -1368,6 +1419,11 @@
         inferEffectivelyFinalVariableTypes) {
       node.type = type;
     }
+  }
+
+  @override
+  Null visitVariableDeclaration(ir.VariableDeclaration node) {
+    _processLocalVariable(node);
     handleVariableDeclaration(node);
   }
 
diff --git a/pkg/compiler/lib/src/ir/static_type_cache.dart b/pkg/compiler/lib/src/ir/static_type_cache.dart
new file mode 100644
index 0000000..64cf6b8
--- /dev/null
+++ b/pkg/compiler/lib/src/ir/static_type_cache.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2017, 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:kernel/ast.dart' as ir;
+import 'package:kernel/class_hierarchy.dart' as ir;
+import 'package:kernel/core_types.dart' as ir;
+import 'package:kernel/type_algebra.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
+
+import '../serialization/serialization.dart';
+
+class StaticTypeCache {
+  static const String tag = 'static-type-cache';
+
+  final Map<ir.Expression, ir.DartType> _expressionTypes;
+  final Map<ir.ForInStatement, ir.DartType> _forInIteratorTypes;
+
+  const StaticTypeCache(
+      [this._expressionTypes = const {}, this._forInIteratorTypes]);
+
+  factory StaticTypeCache.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    Map<ir.Expression, ir.DartType> expressionTypes =
+        source.readTreeNodeMap(source.readDartTypeNode);
+    Map<ir.ForInStatement, ir.DartType> forInIteratorTypes =
+        source.readTreeNodeMap(source.readDartTypeNode, emptyAsNull: true);
+    source.end(tag);
+    return new StaticTypeCache(expressionTypes, forInIteratorTypes);
+  }
+
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeTreeNodeMap(_expressionTypes, sink.writeDartTypeNode);
+    sink.writeTreeNodeMap(_forInIteratorTypes, sink.writeDartTypeNode,
+        allowNull: true);
+    sink.end(tag);
+  }
+
+  ir.DartType operator [](ir.Expression node) => _expressionTypes[node];
+
+  ir.DartType getForInIteratorType(ir.ForInStatement node) {
+    return _forInIteratorTypes != null ? _forInIteratorTypes[node] : null;
+  }
+}
diff --git a/pkg/compiler/lib/src/ir/static_type_provider.dart b/pkg/compiler/lib/src/ir/static_type_provider.dart
index 2901f34..ee0db10 100644
--- a/pkg/compiler/lib/src/ir/static_type_provider.dart
+++ b/pkg/compiler/lib/src/ir/static_type_provider.dart
@@ -11,4 +11,5 @@
 /// Interface for accessing static types on expressions.
 abstract class StaticTypeProvider {
   ir.DartType getStaticType(ir.Expression node);
+  ir.DartType getForInIteratorType(ir.ForInStatement node);
 }
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index c62d6f3..c2f8403 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -119,7 +119,7 @@
 }
 
 abstract class ReferenceCountedAstNode implements Node {
-  markSeen(TokenCounter visitor);
+  void markSeen(TokenCounter visitor);
 }
 
 /// Represents the LiteralString resulting from unparsing [expression]. The
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index b3768c4..01cad9d 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -1385,8 +1385,9 @@
           if (clause is js.Case) {
             return new js.Case(
                 clause.expression, translateToBlock(clause.body));
-          } else if (clause is js.Default) {
-            return new js.Default(translateToBlock(clause.body));
+          } else {
+            return new js.Default(
+                translateToBlock((clause as js.Default).body));
           }
         }).toList();
         addStatement(new js.Switch(key, cases));
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 6f44b97..d187523 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -6,41 +6,33 @@
 
 import '../common.dart';
 import '../common/backend_api.dart' show ImpactTransformer;
-import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
+import '../common/codegen.dart';
 import '../common/names.dart' show Uris;
 import '../common/tasks.dart' show CompilerTask;
-import '../common_elements.dart'
-    show CommonElements, ElementEnvironment, JElementEnvironment;
+import '../common/work.dart';
+import '../common_elements.dart' show CommonElements, ElementEnvironment;
 import '../compiler.dart' show Compiler;
 import '../deferred_load.dart' show DeferredLoadTask;
 import '../dump_info.dart' show DumpInfoTask;
 import '../elements/entities.dart';
-import '../elements/types.dart';
 import '../enqueue.dart' show Enqueuer, EnqueueTask, ResolutionEnqueuer;
 import '../frontend_strategy.dart';
 import '../inferrer/types.dart';
-import '../io/source_information.dart'
-    show SourceInformation, SourceInformationStrategy;
+import '../io/source_information.dart' show SourceInformationStrategy;
 import '../js/js.dart' as jsAst;
-import '../js/js.dart' show js;
 import '../js_model/elements.dart';
-import '../js/rewrite_async.dart';
 import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
-import '../js_emitter/sorter.dart' show Sorter;
 import '../kernel/dart2js_target.dart';
 import '../native/enqueue.dart';
+import '../serialization/serialization.dart';
 import '../ssa/ssa.dart' show SsaFunctionCompiler;
 import '../tracer.dart';
-import '../universe/call_structure.dart' show CallStructure;
 import '../universe/class_hierarchy.dart'
     show ClassHierarchyBuilder, ClassQueries;
 import '../universe/codegen_world_builder.dart';
-import '../universe/selector.dart' show Selector;
-import '../universe/use.dart' show StaticUse;
 import '../universe/world_builder.dart';
 import '../universe/world_impact.dart'
     show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor;
-import '../util/util.dart';
 import '../world.dart' show JClosedWorld;
 import 'field_analysis.dart';
 import 'annotations.dart';
@@ -48,7 +40,6 @@
 import 'backend_usage.dart';
 import 'checked_mode_helpers.dart';
 import 'codegen_listener.dart';
-import 'constant_handler_javascript.dart';
 import 'custom_elements_analysis.dart';
 import 'enqueuer.dart';
 import 'impact_transformer.dart';
@@ -61,11 +52,11 @@
 import 'runtime_types.dart';
 
 abstract class FunctionCompiler {
-  void onCodegenStart();
+  void initialize(
+      GlobalTypeInferenceResults globalInferenceResults, CodegenInputs codegen);
 
-  /// Generates JavaScript code for `work.element`.
-  jsAst.Fun compile(CodegenWorkItem work, JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults);
+  /// Generates JavaScript code for [member].
+  CodegenResult compile(MemberEntity member);
 
   Iterable get tasks;
 }
@@ -91,11 +82,12 @@
   final Map<FunctionEntity, int> _cachedDecisions =
       new Map<FunctionEntity, int>();
 
+  final Set<FunctionEntity> _noInlineFunctions = new Set<FunctionEntity>();
   final Set<FunctionEntity> _tryInlineFunctions = new Set<FunctionEntity>();
 
   FunctionInlineCache(AnnotationsData annotationsData) {
     annotationsData.forEachNoInline((FunctionEntity function) {
-      markAsNonInlinable(function);
+      markAsNoInline(function);
     });
     annotationsData.forEachTryInline((FunctionEntity function) {
       markAsTryInline(function);
@@ -181,7 +173,7 @@
         case _mustNotInline:
           throw failedAt(
               element,
-              "Can't mark a function as non-inlinable and inlinable at the "
+              "Can't mark $element as non-inlinable and inlinable at the "
               "same time.");
 
         case _unknown:
@@ -207,7 +199,7 @@
         case _canInlineInLoopMustNotOutside:
           throw failedAt(
               element,
-              "Can't mark a function as non-inlinable and inlinable at the "
+              "Can't mark $element as non-inlinable and inlinable at the "
               "same time.");
 
         case _unknown:
@@ -237,7 +229,7 @@
         case _canInline:
           throw failedAt(
               element,
-              "Can't mark a function as non-inlinable and inlinable at the "
+              "Can't mark $element as non-inlinable and inlinable at the "
               "same time.");
 
         case _mayInlineInLoopMustNotOutside:
@@ -254,7 +246,7 @@
         case _canInline:
           throw failedAt(
               element,
-              "Can't mark a function as non-inlinable and inlinable at the "
+              "Can't mark $element as non-inlinable and inlinable at the "
               "same time.");
 
         case _unknown:
@@ -279,6 +271,16 @@
     }
   }
 
+  void markAsNoInline(FunctionEntity element) {
+    assert(checkFunction(element), failedAt(element));
+    _noInlineFunctions.add(element);
+  }
+
+  bool markedAsNoInline(FunctionEntity element) {
+    assert(checkFunction(element), failedAt(element));
+    return _noInlineFunctions.contains(element);
+  }
+
   void markAsTryInline(FunctionEntity element) {
     assert(checkFunction(element), failedAt(element));
     _tryInlineFunctions.add(element);
@@ -290,13 +292,6 @@
   }
 }
 
-enum SyntheticConstantKind {
-  DUMMY_INTERCEPTOR,
-  EMPTY_VALUE,
-  TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data.
-  NAME
-}
-
 class JavaScriptBackend {
   static const String JS = 'JS';
   static const String JS_BUILTIN = 'JS_BUILTIN';
@@ -310,7 +305,7 @@
 
   FunctionCompiler functionCompiler;
 
-  CodeEmitterTask emitter;
+  CodeEmitterTask emitterTask;
 
   /// The generated code as a js AST for compiled methods.
   final Map<MemberEntity, jsAst.Expression> generatedCode =
@@ -318,27 +313,19 @@
 
   Namer _namer;
 
-  Namer get namer {
-    assert(_namer != null,
-        failedAt(NO_LOCATION_SPANNABLE, "Namer has not been created yet."));
-    return _namer;
-  }
+  Namer get namerForTesting => _namer;
 
   /// Set of classes whose `operator ==` methods handle `null` themselves.
   final Set<ClassEntity> specialOperatorEqClasses = new Set<ClassEntity>();
 
   List<CompilerTask> get tasks {
     List<CompilerTask> result = functionCompiler.tasks;
-    result.add(emitter);
+    result.add(emitterTask);
     return result;
   }
 
   RuntimeTypesChecksBuilder _rtiChecksBuilder;
 
-  RuntimeTypesSubstitutions _rtiSubstitutions;
-
-  RuntimeTypesEncoder _rtiEncoder;
-
   /// True if the html library has been loaded.
   bool htmlLibraryIsLoaded = false;
 
@@ -355,10 +342,6 @@
   /// Support for classifying `noSuchMethod` implementations.
   NoSuchMethodRegistry noSuchMethodRegistry;
 
-  /// The compiler task responsible for the compilation of constants for both
-  /// the frontend and the backend.
-  final JavaScriptConstantTask constantCompilerTask;
-
   /// Backend transformation methods for the world impacts.
   ImpactTransformer impactTransformer;
 
@@ -369,34 +352,29 @@
 
   NativeDataBuilderImpl _nativeDataBuilder;
   NativeDataBuilder get nativeDataBuilder => _nativeDataBuilder;
-  OneShotInterceptorData _oneShotInterceptorData;
   BackendUsageBuilder _backendUsageBuilder;
 
-  CheckedModeHelpers _checkedModeHelpers;
-
-  final SuperMemberData superMemberData = new SuperMemberData();
-
   NativeResolutionEnqueuer _nativeResolutionEnqueuer;
   NativeCodegenEnqueuer _nativeCodegenEnqueuer;
 
-  Tracer tracer;
-
   JavaScriptBackend(this.compiler,
       {bool generateSourceMap: true,
       bool useMultiSourceInfo: false,
       bool useNewSourceInfo: false})
       : this.sourceInformationStrategy =
-            compiler.backendStrategy.sourceInformationStrategy,
-        constantCompilerTask = new JavaScriptConstantTask(compiler) {
+            compiler.backendStrategy.sourceInformationStrategy {
     CommonElements commonElements = compiler.frontendStrategy.commonElements;
     _backendUsageBuilder =
         new BackendUsageBuilderImpl(compiler.frontendStrategy);
-    _checkedModeHelpers = new CheckedModeHelpers();
-    emitter = new CodeEmitterTask(compiler, generateSourceMap);
+    emitterTask = new CodeEmitterTask(compiler, generateSourceMap);
     noSuchMethodRegistry = new NoSuchMethodRegistryImpl(
         commonElements, compiler.frontendStrategy.createNoSuchMethodResolver());
     functionCompiler = new SsaFunctionCompiler(
-        this, compiler.measurer, sourceInformationStrategy);
+        compiler.options,
+        compiler.reporter,
+        compiler.backendStrategy,
+        compiler.measurer,
+        sourceInformationStrategy);
   }
 
   DiagnosticReporter get reporter => compiler.reporter;
@@ -425,14 +403,6 @@
     return _customElementsCodegenAnalysis;
   }
 
-  OneShotInterceptorData get oneShotInterceptorData {
-    assert(
-        _oneShotInterceptorData != null,
-        failedAt(NO_LOCATION_SPANNABLE,
-            "OneShotInterceptorData has not been prepared yet."));
-    return _oneShotInterceptorData;
-  }
-
   RuntimeTypesChecksBuilder get rtiChecksBuilder {
     assert(
         _rtiChecksBuilder != null,
@@ -447,39 +417,6 @@
 
   RuntimeTypesChecksBuilder get rtiChecksBuilderForTesting => _rtiChecksBuilder;
 
-  RuntimeTypesSubstitutions get rtiSubstitutions {
-    assert(
-        _rtiSubstitutions != null,
-        failedAt(NO_LOCATION_SPANNABLE,
-            "RuntimeTypesSubstitutions has not been created yet."));
-    return _rtiSubstitutions;
-  }
-
-  RuntimeTypesEncoder get rtiEncoder {
-    assert(
-        _rtiEncoder != null,
-        failedAt(NO_LOCATION_SPANNABLE,
-            "RuntimeTypesEncoder has not been created."));
-    return _rtiEncoder;
-  }
-
-  CheckedModeHelpers get checkedModeHelpers => _checkedModeHelpers;
-
-  /// Returns constant environment for the JavaScript interpretation of the
-  /// constants.
-  JavaScriptConstantCompiler get constants {
-    return constantCompilerTask.jsConstantCompiler;
-  }
-
-  Namer determineNamer(
-      JClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder) {
-    return compiler.options.enableMinification
-        ? compiler.options.useFrequencyNamer
-            ? new FrequencyBasedNamer(closedWorld, codegenWorldBuilder)
-            : new MinifyNamer(closedWorld, codegenWorldBuilder)
-        : new Namer(closedWorld, codegenWorldBuilder);
-  }
-
   void validateInterceptorImplementsAllObjectMethods(
       ClassEntity interceptorClass) {
     if (interceptorClass == null) return;
@@ -608,29 +545,30 @@
       CompilerTask task,
       Compiler compiler,
       JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
+      GlobalTypeInferenceResults globalInferenceResults,
+      CodegenInputs codegen,
+      CodegenResults codegenResults) {
+    OneShotInterceptorData oneShotInterceptorData = new OneShotInterceptorData(
+        closedWorld.interceptorData,
+        closedWorld.commonElements,
+        closedWorld.nativeData);
+    _onCodegenEnqueuerStart(
+        globalInferenceResults, codegen, oneShotInterceptorData);
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
     CommonElements commonElements = closedWorld.commonElements;
     BackendImpacts impacts = new BackendImpacts(commonElements);
     _customElementsCodegenAnalysis = new CustomElementsCodegenAnalysis(
         commonElements, elementEnvironment, closedWorld.nativeData);
-    _nativeCodegenEnqueuer = new NativeCodegenEnqueuer(
-        compiler.options,
-        elementEnvironment,
-        commonElements,
-        closedWorld.dartTypes,
-        emitter,
-        closedWorld.liveNativeClasses,
-        closedWorld.nativeData);
     return new CodegenEnqueuer(
         task,
         compiler.options,
         compiler.backendStrategy.createCodegenWorldBuilder(
             closedWorld.nativeData,
             closedWorld,
-            compiler.abstractValueStrategy.createSelectorStrategy()),
+            compiler.abstractValueStrategy.createSelectorStrategy(),
+            oneShotInterceptorData),
         compiler.backendStrategy
-            .createCodegenWorkItemBuilder(closedWorld, globalInferenceResults),
+            .createCodegenWorkItemBuilder(closedWorld, codegenResults),
         new CodegenEnqueuerListener(
             elementEnvironment,
             commonElements,
@@ -643,44 +581,41 @@
 
   Map<MemberEntity, WorldImpact> codegenImpactsForTesting;
 
-  WorldImpact codegen(CodegenWorkItem work, JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
-    MemberEntity element = work.element;
-    if (compiler.elementHasCompileTimeError(element)) {
-      DiagnosticMessage message =
-          // If there's more than one error, the first is probably most
-          // informative, as the following errors may be side-effects of the
-          // first error.
-          compiler.elementsWithCompileTimeErrors[element].first;
-      String messageText = message.message.computeMessage();
-      jsAst.LiteralString messageLiteral =
-          js.escapedString("Compile time error in $element: $messageText");
-      generatedCode[element] =
-          js("function () { throw new Error(#); }", [messageLiteral]);
-      return const WorldImpact();
+  WorldImpact generateCode(
+      WorkItem work,
+      JClosedWorld closedWorld,
+      CodegenResults codegenResults,
+      EntityLookup entityLookup,
+      ComponentLookup componentLookup) {
+    MemberEntity member = work.element;
+    CodegenResult result = codegenResults.getCodegenResults(member);
+    if (compiler.options.testMode) {
+      bool useDataKinds = true;
+      List<Object> data = [];
+      DataSink sink = new ObjectSink(data, useDataKinds: useDataKinds);
+      sink.registerCodegenWriter(new CodegenWriterImpl(closedWorld));
+      result.writeToDataSink(sink);
+      DataSource source = new ObjectSource(data, useDataKinds: useDataKinds);
+      List<ModularName> modularNames = [];
+      List<ModularExpression> modularExpression = [];
+      source.registerCodegenReader(
+          new CodegenReaderImpl(closedWorld, modularNames, modularExpression));
+      source.registerEntityLookup(entityLookup);
+      source.registerComponentLookup(componentLookup);
+      result = CodegenResult.readFromDataSource(
+          source, modularNames, modularExpression);
     }
-    if (element.isConstructor &&
-        element.enclosingClass == closedWorld.commonElements.jsNullClass) {
-      // Work around a problem compiling JSNull's constructor.
-      return const WorldImpact();
-    }
-
-    jsAst.Fun function =
-        functionCompiler.compile(work, closedWorld, globalInferenceResults);
-    if (function != null) {
-      if (function.sourceInformation == null) {
-        function = function.withSourceInformation(
-            sourceInformationStrategy.buildSourceMappedMarker());
-      }
-      generatedCode[element] = function;
+    if (result.code != null) {
+      generatedCode[member] = result.code;
     }
     if (retainDataForTesting) {
       codegenImpactsForTesting ??= <MemberEntity, WorldImpact>{};
-      codegenImpactsForTesting[element] = work.registry.worldImpact;
+      codegenImpactsForTesting[member] = result.impact;
     }
-    WorldImpact worldImpact = _codegenImpactTransformer
-        .transformCodegenImpact(work.registry.worldImpact);
-    compiler.dumpInfoTask.registerImpact(element, worldImpact);
+    WorldImpact worldImpact =
+        _codegenImpactTransformer.transformCodegenImpact(result.impact);
+    compiler.dumpInfoTask.registerImpact(member, worldImpact);
+    result.applyModularState(_namer, emitterTask.emitter);
     return worldImpact;
   }
 
@@ -698,30 +633,14 @@
   }
 
   /// Generates the output and returns the total size of the generated code.
-  int assembleProgram(JClosedWorld closedWorld, InferredData inferredData) {
-    int programSize = emitter.assembleProgram(namer, closedWorld, inferredData);
+  int assembleProgram(JClosedWorld closedWorld, InferredData inferredData,
+      CodegenInputs codegenInputs, CodegenWorld codegenWorld) {
+    int programSize = emitterTask.assembleProgram(
+        _namer, closedWorld, inferredData, codegenInputs, codegenWorld);
     closedWorld.noSuchMethodData.emitDiagnostic(reporter);
     return programSize;
   }
 
-  /// Returns [:true:] if the checking of [type] is performed directly on the
-  /// object and not on an interceptor.
-  bool hasDirectCheckFor(CommonElements commonElements, DartType type) {
-    if (!type.isInterfaceType) return false;
-    InterfaceType interfaceType = type;
-    ClassEntity element = interfaceType.element;
-    return element == commonElements.stringClass ||
-        element == commonElements.boolClass ||
-        element == commonElements.numClass ||
-        element == commonElements.intClass ||
-        element == commonElements.doubleClass ||
-        element == commonElements.jsArrayClass ||
-        element == commonElements.jsMutableArrayClass ||
-        element == commonElements.jsExtendableArrayClass ||
-        element == commonElements.jsFixedArrayClass ||
-        element == commonElements.jsUnmodifiableArrayClass;
-  }
-
   /// This method is called immediately after the [library] and its parts have
   /// been loaded.
   void setAnnotations(LibraryEntity library) {
@@ -733,41 +652,75 @@
     processor.extractJsInteropAnnotations(library);
     Uri uri = library.canonicalUri;
     if (uri == Uris.dart_html) {
-      htmlLibraryIsLoaded = true;
+      _backendUsageBuilder.registerHtmlIsLoaded();
     }
   }
 
-  /// Called when the compiler starts running the codegen enqueuer. The
-  /// [WorldImpact] of enabled backend features is returned.
-  WorldImpact onCodegenStart(JClosedWorld closedWorld,
-      CodegenWorldBuilder codegenWorldBuilder, Sorter sorter) {
-    functionCompiler.onCodegenStart();
-    _oneShotInterceptorData = new OneShotInterceptorData(
-        closedWorld.interceptorData, closedWorld.commonElements);
-    _namer = determineNamer(closedWorld, codegenWorldBuilder);
-    tracer = new Tracer(closedWorld, namer, compiler.outputProvider);
-    _rtiEncoder = _namer.rtiEncoder = new RuntimeTypesEncoderImpl(
-        namer,
+  /// Called when the compiler starts running the codegen.
+  ///
+  /// Returns the [CodegenInputs] objects with the needed data.
+  CodegenInputs onCodegenStart(
+      GlobalTypeInferenceResults globalTypeInferenceResults) {
+    JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
+    RuntimeTypeTags rtiTags = const RuntimeTypeTags();
+    FixedNames fixedNames = compiler.options.enableMinification
+        ? const MinifiedFixedNames()
+        : const FixedNames();
+
+    Tracer tracer = new Tracer(closedWorld, compiler.outputProvider);
+    RuntimeTypesEncoder rtiEncoder = new RuntimeTypesEncoderImpl(
+        rtiTags,
         closedWorld.nativeData,
         closedWorld.elementEnvironment,
         closedWorld.commonElements,
         closedWorld.rtiNeed);
-    emitter.createEmitter(namer, closedWorld, codegenWorldBuilder, sorter);
-    // TODO(johnniwinther): Share the impact object created in
-    // createCodegenEnqueuer.
-    BackendImpacts impacts = new BackendImpacts(closedWorld.commonElements);
+    RuntimeTypesSubstitutions rtiSubstitutions;
     if (compiler.options.disableRtiOptimization) {
-      _rtiSubstitutions = new TrivialRuntimeTypesSubstitutions(closedWorld);
+      rtiSubstitutions = new TrivialRuntimeTypesSubstitutions(closedWorld);
       _rtiChecksBuilder =
-          new TrivialRuntimeTypesChecksBuilder(closedWorld, _rtiSubstitutions);
+          new TrivialRuntimeTypesChecksBuilder(closedWorld, rtiSubstitutions);
     } else {
       RuntimeTypesImpl runtimeTypesImpl = new RuntimeTypesImpl(closedWorld);
       _rtiChecksBuilder = runtimeTypesImpl;
-      _rtiSubstitutions = runtimeTypesImpl;
+      rtiSubstitutions = runtimeTypesImpl;
     }
 
+    CodegenInputs codegen = new CodegenInputsImpl(
+        rtiSubstitutions, rtiEncoder, tracer, rtiTags, fixedNames);
+
+    functionCompiler.initialize(globalTypeInferenceResults, codegen);
+    return codegen;
+  }
+
+  /// Called before the compiler starts running the codegen enqueuer.
+  void _onCodegenEnqueuerStart(
+      GlobalTypeInferenceResults globalTypeInferenceResults,
+      CodegenInputs codegen,
+      OneShotInterceptorData oneShotInterceptorData) {
+    JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
+    RuntimeTypeTags rtiTags = codegen.rtiTags;
+    FixedNames fixedNames = codegen.fixedNames;
+    _namer = compiler.options.enableMinification
+        ? compiler.options.useFrequencyNamer
+            ? new FrequencyBasedNamer(closedWorld, rtiTags, fixedNames)
+            : new MinifyNamer(closedWorld, rtiTags, fixedNames)
+        : new Namer(closedWorld, rtiTags, fixedNames);
+    _nativeCodegenEnqueuer = new NativeCodegenEnqueuer(
+        compiler.options,
+        closedWorld.elementEnvironment,
+        closedWorld.commonElements,
+        closedWorld.dartTypes,
+        emitterTask,
+        closedWorld.liveNativeClasses,
+        closedWorld.nativeData);
+    emitterTask.createEmitter(_namer, codegen, closedWorld);
+    // TODO(johnniwinther): Share the impact object created in
+    // createCodegenEnqueuer.
+    BackendImpacts impacts = new BackendImpacts(closedWorld.commonElements);
+
     _codegenImpactTransformer = new CodegenImpactTransformer(
         compiler.options,
+        closedWorld,
         closedWorld.elementEnvironment,
         closedWorld.commonElements,
         impacts,
@@ -775,131 +728,16 @@
         closedWorld.backendUsage,
         closedWorld.rtiNeed,
         nativeCodegenEnqueuer,
-        namer,
+        _namer,
         oneShotInterceptorData,
-        rtiChecksBuilder);
-    return const WorldImpact();
+        rtiChecksBuilder,
+        emitterTask.nativeEmitter);
   }
 
   /// Called when code generation has been completed.
-  void onCodegenEnd() {
+  void onCodegenEnd(CodegenInputs codegen) {
     sourceInformationStrategy.onComplete();
-    tracer.close();
-  }
-
-  /// Enable compilation of code with compile time errors. Returns `true` if
-  /// supported by the backend.
-  bool enableCodegenWithErrorsIfSupported(Spannable node) => true;
-
-  jsAst.Expression rewriteAsync(
-      CommonElements commonElements,
-      JElementEnvironment elementEnvironment,
-      CodegenRegistry registry,
-      FunctionEntity element,
-      jsAst.Expression code,
-      DartType asyncTypeParameter,
-      SourceInformation bodySourceInformation,
-      SourceInformation exitSourceInformation) {
-    if (element.asyncMarker == AsyncMarker.SYNC) return code;
-
-    AsyncRewriterBase rewriter = null;
-    jsAst.Name name = namer.methodPropertyName(
-        element is JGeneratorBody ? element.function : element);
-
-    switch (element.asyncMarker) {
-      case AsyncMarker.ASYNC:
-        rewriter = _makeAsyncRewriter(commonElements, elementEnvironment,
-            registry, element, code, asyncTypeParameter, name);
-        break;
-      case AsyncMarker.SYNC_STAR:
-        rewriter = new SyncStarRewriter(reporter, element,
-            endOfIteration:
-                emitter.staticFunctionAccess(commonElements.endOfIteration),
-            iterableFactory: emitter
-                .staticFunctionAccess(commonElements.syncStarIterableFactory),
-            iterableFactoryTypeArguments: _fetchItemType(asyncTypeParameter),
-            yieldStarExpression:
-                emitter.staticFunctionAccess(commonElements.yieldStar),
-            uncaughtErrorExpression: emitter
-                .staticFunctionAccess(commonElements.syncStarUncaughtError),
-            safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
-            bodyName: namer.deriveAsyncBodyName(name));
-        registry.registerStaticUse(new StaticUse.staticInvoke(
-            commonElements.syncStarIterableFactory,
-            const CallStructure.unnamed(1, 1), [
-          elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)
-        ]));
-        break;
-      case AsyncMarker.ASYNC_STAR:
-        rewriter = new AsyncStarRewriter(reporter, element,
-            asyncStarHelper:
-                emitter.staticFunctionAccess(commonElements.asyncStarHelper),
-            streamOfController:
-                emitter.staticFunctionAccess(commonElements.streamOfController),
-            wrapBody: emitter.staticFunctionAccess(commonElements.wrapBody),
-            newController: emitter.staticFunctionAccess(
-                commonElements.asyncStarStreamControllerFactory),
-            newControllerTypeArguments: _fetchItemType(asyncTypeParameter),
-            safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
-            yieldExpression:
-                emitter.staticFunctionAccess(commonElements.yieldSingle),
-            yieldStarExpression:
-                emitter.staticFunctionAccess(commonElements.yieldStar),
-            bodyName: namer.deriveAsyncBodyName(name));
-        registry.registerStaticUse(new StaticUse.staticInvoke(
-            commonElements.asyncStarStreamControllerFactory,
-            const CallStructure.unnamed(1, 1), [
-          elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)
-        ]));
-        break;
-    }
-    return rewriter.rewrite(code, bodySourceInformation, exitSourceInformation);
-  }
-
-  /// Returns an optional expression that evaluates [type].  Returns `null` if
-  /// the type expression is determined by the outside context and should be
-  /// added as a function parameter to the rewritten code.
-  // TODO(sra): We could also return an empty list if the generator takes no
-  // type (e.g. due to rtiNeed optimization).
-  List<jsAst.Expression> _fetchItemType(DartType type) {
-    if (type == null) return null;
-    var ast = rtiEncoder.getTypeRepresentation(emitter.emitter, type, null);
-    return <jsAst.Expression>[ast];
-  }
-
-  AsyncRewriter _makeAsyncRewriter(
-      CommonElements commonElements,
-      JElementEnvironment elementEnvironment,
-      CodegenRegistry registry,
-      FunctionEntity element,
-      jsAst.Expression code,
-      DartType elementType,
-      jsAst.Name name) {
-    var startFunction = commonElements.asyncHelperStartSync;
-    var completerFactory = commonElements.asyncAwaitCompleterFactory;
-
-    List<jsAst.Expression> itemTypeExpression = _fetchItemType(elementType);
-
-    var rewriter = new AsyncRewriter(reporter, element,
-        asyncStart: emitter.staticFunctionAccess(startFunction),
-        asyncAwait:
-            emitter.staticFunctionAccess(commonElements.asyncHelperAwait),
-        asyncReturn:
-            emitter.staticFunctionAccess(commonElements.asyncHelperReturn),
-        asyncRethrow:
-            emitter.staticFunctionAccess(commonElements.asyncHelperRethrow),
-        wrapBody: emitter.staticFunctionAccess(commonElements.wrapBody),
-        completerFactory: emitter.staticFunctionAccess(completerFactory),
-        completerFactoryTypeArguments: itemTypeExpression,
-        safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
-        bodyName: namer.deriveAsyncBodyName(name));
-
-    registry.registerStaticUse(new StaticUse.staticInvoke(
-        completerFactory,
-        const CallStructure.unnamed(0, 1),
-        [elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)]));
-
-    return rewriter;
+    codegen.tracer.close();
   }
 
   /// Creates an impact strategy to use for compilation.
@@ -952,27 +790,35 @@
   }
 }
 
-class SuperMemberData {
-  /// A set of member that are called from subclasses via `super`.
-  final Set<MemberEntity> _aliasedSuperMembers = new Setlet<MemberEntity>();
+/// Interface for resources only used during code generation.
+abstract class CodegenInputs {
+  CheckedModeHelpers get checkedModeHelpers;
+  RuntimeTypesSubstitutions get rtiSubstitutions;
+  RuntimeTypesEncoder get rtiEncoder;
+  Tracer get tracer;
+  RuntimeTypeTags get rtiTags;
+  FixedNames get fixedNames;
+}
 
-  /// Record that [member] is called from a subclass via `super`.
-  bool maybeRegisterAliasedSuperMember(MemberEntity member, Selector selector) {
-    if (!canUseAliasedSuperMember(member, selector)) {
-      // Invoking a super getter isn't supported, this would require changes to
-      // compact field descriptors in the emitter.
-      return false;
-    }
-    _aliasedSuperMembers.add(member);
-    return true;
-  }
+class CodegenInputsImpl implements CodegenInputs {
+  @override
+  final CheckedModeHelpers checkedModeHelpers = new CheckedModeHelpers();
 
-  bool canUseAliasedSuperMember(MemberEntity member, Selector selector) {
-    return !selector.isGetter;
-  }
+  @override
+  final RuntimeTypesSubstitutions rtiSubstitutions;
 
-  /// Returns `true` if [member] is called from a subclass via `super`.
-  bool isAliasedSuperMember(MemberEntity member) {
-    return _aliasedSuperMembers.contains(member);
-  }
+  @override
+  final RuntimeTypesEncoder rtiEncoder;
+
+  @override
+  final Tracer tracer;
+
+  @override
+  final RuntimeTypeTags rtiTags;
+
+  @override
+  final FixedNames fixedNames;
+
+  CodegenInputsImpl(this.rtiSubstitutions, this.rtiEncoder, this.tracer,
+      this.rtiTags, this.fixedNames);
 }
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 36d9600..256d8f1 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -66,7 +66,8 @@
     }
     for (Selector selector in dynamicUses) {
       assert(selector != null);
-      worldImpactBuilder.registerDynamicUse(new DynamicUse(selector));
+      worldImpactBuilder
+          .registerDynamicUse(new DynamicUse(selector, null, const []));
     }
     for (InterfaceType instantiatedType in instantiatedTypes) {
       worldImpactBuilder
@@ -698,7 +699,7 @@
   BackendImpact _noSuchMethodSupport;
 
   BackendImpact get noSuchMethodSupport {
-    return _noSuchMethodSupport ??= new BackendImpact(staticUses: [
+    return _noSuchMethodSupport ??= new BackendImpact(globalUses: [
       _commonElements.createInvocationMirror,
       _commonElements.createUnmangledInvocationMirror
     ], dynamicUses: [
diff --git a/pkg/compiler/lib/src/js_backend/backend_usage.dart b/pkg/compiler/lib/src/js_backend/backend_usage.dart
index 09ce162..ad3877c 100644
--- a/pkg/compiler/lib/src/js_backend/backend_usage.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_usage.dart
@@ -53,6 +53,10 @@
 
   /// `true` if `noSuchMethod` is used.
   bool get isNoSuchMethodUsed;
+
+  /// `true` if the `dart:html` is loaded.
+  // TODO(johnniwinther): This is always `true` with the CFE.
+  bool get isHtmlLoaded;
 }
 
 abstract class BackendUsageBuilder {
@@ -90,6 +94,9 @@
   /// `true` if `noSuchMethod` is used.
   bool isNoSuchMethodUsed;
 
+  /// Register that `dart:html` is loaded.
+  void registerHtmlIsLoaded();
+
   BackendUsage close();
 }
 
@@ -122,6 +129,8 @@
   @override
   bool isNoSuchMethodUsed = false;
 
+  bool isHtmlLoaded = false;
+
   BackendUsageBuilderImpl(this._frontendStrategy);
 
   KCommonElements get _commonElements => _frontendStrategy.commonElements;
@@ -261,6 +270,11 @@
   }
 
   @override
+  void registerHtmlIsLoaded() {
+    isHtmlLoaded = true;
+  }
+
+  @override
   BackendUsage close() {
     return new BackendUsageImpl(
         globalFunctionDependencies: _globalFunctionDependencies,
@@ -273,7 +287,8 @@
         runtimeTypeUses: _runtimeTypeUses,
         isFunctionApplyUsed: isFunctionApplyUsed,
         isMirrorsUsed: isMirrorsUsed,
-        isNoSuchMethodUsed: isNoSuchMethodUsed);
+        isNoSuchMethodUsed: isNoSuchMethodUsed,
+        isHtmlLoaded: isHtmlLoaded);
   }
 }
 
@@ -311,6 +326,9 @@
   @override
   final bool isNoSuchMethodUsed;
 
+  @override
+  final bool isHtmlLoaded;
+
   BackendUsageImpl(
       {Set<FunctionEntity> globalFunctionDependencies,
       Set<ClassEntity> globalClassDependencies,
@@ -322,7 +340,8 @@
       Set<RuntimeTypeUse> runtimeTypeUses,
       this.isFunctionApplyUsed,
       this.isMirrorsUsed,
-      this.isNoSuchMethodUsed})
+      this.isNoSuchMethodUsed,
+      this.isHtmlLoaded})
       : this._globalFunctionDependencies = globalFunctionDependencies,
         this._globalClassDependencies = globalClassDependencies,
         this._helperFunctionsUsed = helperFunctionsUsed,
@@ -349,6 +368,7 @@
     bool isFunctionApplyUsed = source.readBool();
     bool isMirrorsUsed = source.readBool();
     bool isNoSuchMethodUsed = source.readBool();
+    bool isHtmlLoaded = source.readBool();
     source.end(tag);
     return new BackendUsageImpl(
         globalFunctionDependencies: globalFunctionDependencies,
@@ -361,7 +381,8 @@
         requiresPreamble: requiresPreamble,
         isFunctionApplyUsed: isFunctionApplyUsed,
         isMirrorsUsed: isMirrorsUsed,
-        isNoSuchMethodUsed: isNoSuchMethodUsed);
+        isNoSuchMethodUsed: isNoSuchMethodUsed,
+        isHtmlLoaded: isHtmlLoaded);
   }
 
   @override
@@ -382,6 +403,7 @@
     sink.writeBool(isFunctionApplyUsed);
     sink.writeBool(isMirrorsUsed);
     sink.writeBool(isNoSuchMethodUsed);
+    sink.writeBool(isHtmlLoaded);
     sink.end(tag);
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
index 751295e..c577600 100644
--- a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
@@ -12,7 +12,7 @@
 import '../ssa/nodes.dart' show HTypeConversion;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/use.dart' show StaticUse;
-import 'namer.dart' show Namer;
+import 'namer.dart' show ModularNamer;
 
 class CheckedModeHelper {
   final String name;
@@ -28,7 +28,7 @@
 
   CallStructure get callStructure => CallStructure.ONE_ARG;
 
-  void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+  void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
       HTypeConversion node, List<jsAst.Expression> arguments) {
     // No additional arguments needed.
   }
@@ -41,7 +41,7 @@
   CallStructure get callStructure => CallStructure.TWO_ARGS;
 
   @override
-  void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+  void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
       HTypeConversion node, List<jsAst.Expression> arguments) {
     DartType type = node.typeExpression;
     jsAst.Name additionalArgument = namer.operatorIsType(type);
@@ -56,7 +56,7 @@
   CallStructure get callStructure => CallStructure.TWO_ARGS;
 
   @override
-  void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+  void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
       HTypeConversion node, List<jsAst.Expression> arguments) {
     assert(node.typeExpression.isTypeVariable);
     codegen.use(node.typeRepresentation);
@@ -71,7 +71,7 @@
   CallStructure get callStructure => CallStructure.TWO_ARGS;
 
   @override
-  void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+  void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
       HTypeConversion node, List<jsAst.Expression> arguments) {
     assert(node.typeExpression.isFunctionType);
     codegen.use(node.typeRepresentation);
@@ -86,7 +86,7 @@
   CallStructure get callStructure => CallStructure.TWO_ARGS;
 
   @override
-  void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+  void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
       HTypeConversion node, List<jsAst.Expression> arguments) {
     assert(node.typeExpression.isFutureOr);
     codegen.use(node.typeRepresentation);
@@ -101,7 +101,7 @@
   CallStructure get callStructure => const CallStructure.unnamed(4);
 
   @override
-  void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+  void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
       HTypeConversion node, List<jsAst.Expression> arguments) {
     // TODO(sra): Move these calls into the SSA graph so that the arguments can
     // be optimized, e,g, GVNed.
diff --git a/pkg/compiler/lib/src/js_backend/codegen_listener.dart b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
index 57e2fc0..2306ad6 100644
--- a/pkg/compiler/lib/src/js_backend/codegen_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
@@ -82,8 +82,12 @@
       mainImpact.registerStaticUse(
           new StaticUse.staticInvoke(mainMethod, callStructure));
     }
-    mainImpact.registerStaticUse(
-        new StaticUse.staticInvoke(mainMethod, CallStructure.NO_ARGS));
+    if (mainMethod.isGetter) {
+      mainImpact.registerStaticUse(new StaticUse.staticGet(mainMethod));
+    } else {
+      mainImpact.registerStaticUse(
+          new StaticUse.staticInvoke(mainMethod, CallStructure.NO_ARGS));
+    }
     return mainImpact;
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 86cbeb5..06ec784 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -11,53 +11,23 @@
 import '../io/code_output.dart';
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
+import '../js_backend/field_analysis.dart';
 import '../js_emitter/code_emitter_task.dart';
 import '../options.dart';
-import '../universe/codegen_world_builder.dart';
 import 'field_analysis.dart' show JFieldAnalysis;
-import 'js_backend.dart';
 import 'runtime_types.dart';
 
 typedef jsAst.Expression _ConstantReferenceGenerator(ConstantValue constant);
 
 typedef jsAst.Expression _ConstantListGenerator(jsAst.Expression array);
 
-/// Generates the JavaScript expressions for constants.
-///
-/// It uses a given [constantReferenceGenerator] to reference nested constants
-/// (if there are some). It is hence up to that function to decide which
-/// constants should be inlined or not.
-class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
-  // Matches blank lines, comment lines and trailing comments that can't be part
-  // of a string.
-  static final RegExp COMMENT_RE =
-      new RegExp(r'''^ *(//.*)?\n|  *//[^''"\n]*$''', multiLine: true);
-
+/// Visitor that creates [jsAst.Expression]s for constants that are inlined
+/// and therefore can be created during modular code generation.
+class ModularConstantEmitter
+    implements ConstantValueVisitor<jsAst.Expression, Null> {
   final CompilerOptions _options;
-  final JCommonElements _commonElements;
-  final CodegenWorldBuilder _worldBuilder;
-  final RuntimeTypesNeed _rtiNeed;
-  final RuntimeTypesEncoder _rtiEncoder;
-  final JFieldAnalysis _fieldAnalysis;
-  final CodeEmitterTask _task;
-  final _ConstantReferenceGenerator constantReferenceGenerator;
-  final _ConstantListGenerator makeConstantList;
 
-  /// The given [constantReferenceGenerator] function must, when invoked with a
-  /// constant, either return a reference or return its literal expression if it
-  /// can be inlined.
-  ConstantEmitter(
-      this._options,
-      this._commonElements,
-      this._worldBuilder,
-      this._rtiNeed,
-      this._rtiEncoder,
-      this._fieldAnalysis,
-      this._task,
-      this.constantReferenceGenerator,
-      this.makeConstantList);
-
-  Emitter get _emitter => _task.emitter;
+  ModularConstantEmitter(this._options);
 
   /// Constructs a literal expression that evaluates to the constant. Uses a
   /// canonical name unless the constant can be emitted multiple times (as for
@@ -174,12 +144,94 @@
   }
 
   @override
+  jsAst.Expression visitDummyInterceptor(DummyInterceptorConstantValue constant,
+      [_]) {
+    return new jsAst.LiteralNumber('0');
+  }
+
+  @override
+  jsAst.Expression visitUnreachable(UnreachableConstantValue constant, [_]) {
+    return new jsAst.LiteralNumber('0');
+  }
+
+  @override
+  jsAst.Expression visitJsName(JsNameConstantValue constant, [_]) {
+    return constant.name;
+  }
+
+  @override
+  jsAst.Expression visitInstantiation(InstantiationConstantValue constant,
+          [_]) =>
+      null;
+
+  @override
+  jsAst.Expression visitDeferredGlobal(DeferredGlobalConstantValue constant,
+          [_]) =>
+      null;
+
+  @override
+  jsAst.Expression visitInterceptor(InterceptorConstantValue constant, [_]) =>
+      null;
+
+  @override
+  jsAst.Expression visitType(TypeConstantValue constant, [_]) => null;
+
+  @override
+  jsAst.Expression visitConstructed(ConstructedConstantValue constant, [_]) =>
+      null;
+
+  @override
+  jsAst.Expression visitMap(MapConstantValue constant, [_]) => null;
+
+  @override
+  jsAst.Expression visitSet(SetConstantValue constant, [_]) => null;
+
+  @override
+  jsAst.Expression visitList(ListConstantValue constant, [_]) => null;
+}
+
+/// Generates the JavaScript expressions for constants.
+///
+/// It uses a given [_constantReferenceGenerator] to reference nested constants
+/// (if there are some). It is hence up to that function to decide which
+/// constants should be inlined or not.
+class ConstantEmitter extends ModularConstantEmitter {
+  // Matches blank lines, comment lines and trailing comments that can't be part
+  // of a string.
+  static final RegExp COMMENT_RE =
+      new RegExp(r'''^ *(//.*)?\n|  *//[^''"\n]*$''', multiLine: true);
+
+  final JCommonElements _commonElements;
+  final JElementEnvironment _elementEnvironment;
+  final RuntimeTypesNeed _rtiNeed;
+  final RuntimeTypesEncoder _rtiEncoder;
+  final JFieldAnalysis _fieldAnalysis;
+  final Emitter _emitter;
+  final _ConstantReferenceGenerator _constantReferenceGenerator;
+  final _ConstantListGenerator _makeConstantList;
+
+  /// The given [_constantReferenceGenerator] function must, when invoked with a
+  /// constant, either return a reference or return its literal expression if it
+  /// can be inlined.
+  ConstantEmitter(
+      CompilerOptions options,
+      this._commonElements,
+      this._elementEnvironment,
+      this._rtiNeed,
+      this._rtiEncoder,
+      this._fieldAnalysis,
+      this._emitter,
+      this._constantReferenceGenerator,
+      this._makeConstantList)
+      : super(options);
+
+  @override
   jsAst.Expression visitList(ListConstantValue constant, [_]) {
     List<jsAst.Expression> elements = constant.entries
-        .map(constantReferenceGenerator)
+        .map(_constantReferenceGenerator)
         .toList(growable: false);
     jsAst.ArrayInitializer array = new jsAst.ArrayInitializer(elements);
-    jsAst.Expression value = makeConstantList(array);
+    jsAst.Expression value = _makeConstantList(array);
     return maybeAddTypeArguments(constant, constant.type, value);
   }
 
@@ -195,7 +247,7 @@
     }
 
     List<jsAst.Expression> arguments = <jsAst.Expression>[
-      constantReferenceGenerator(constant.entries),
+      _constantReferenceGenerator(constant.entries),
     ];
 
     if (_rtiNeed.classNeedsTypeArguments(classElement)) {
@@ -221,7 +273,7 @@
         // Keys in literal maps must be emitted in place.
         jsAst.Literal keyExpression = _visit(key);
         jsAst.Expression valueExpression =
-            constantReferenceGenerator(constant.values[i]);
+            _constantReferenceGenerator(constant.values[i]);
         properties.add(new jsAst.Property(keyExpression, valueExpression));
       }
       return new jsAst.ObjectInitializer(properties);
@@ -231,9 +283,9 @@
       List<jsAst.Expression> data = <jsAst.Expression>[];
       for (int i = 0; i < constant.keys.length; i++) {
         jsAst.Expression keyExpression =
-            constantReferenceGenerator(constant.keys[i]);
+            _constantReferenceGenerator(constant.keys[i]);
         jsAst.Expression valueExpression =
-            constantReferenceGenerator(constant.values[i]);
+            _constantReferenceGenerator(constant.values[i]);
         data.add(keyExpression);
         data.add(valueExpression);
       }
@@ -248,9 +300,9 @@
     // The arguments of the JavaScript constructor for any given Dart class
     // are in the same order as the members of the class element.
     int emittedArgumentCount = 0;
-    _worldBuilder.forEachInstanceField(classElement,
-        (ClassEntity enclosing, FieldEntity field, {bool isElided}) {
-      if (isElided) return;
+    _elementEnvironment.forEachInstanceField(classElement,
+        (ClassEntity enclosing, FieldEntity field) {
+      if (_fieldAnalysis.getFieldData(field).isElided) return;
       if (field.name == constant_system.JavaScriptMapConstant.LENGTH_NAME) {
         arguments
             .add(new jsAst.LiteralNumber('${constant.keyList.entries.length}'));
@@ -259,11 +311,11 @@
         arguments.add(jsMap());
       } else if (field.name ==
           constant_system.JavaScriptMapConstant.KEYS_NAME) {
-        arguments.add(constantReferenceGenerator(constant.keyList));
+        arguments.add(_constantReferenceGenerator(constant.keyList));
       } else if (field.name ==
           constant_system.JavaScriptMapConstant.PROTO_VALUE) {
         assert(constant.protoValue != null);
-        arguments.add(constantReferenceGenerator(constant.protoValue));
+        arguments.add(_constantReferenceGenerator(constant.protoValue));
       } else if (field.name ==
           constant_system.JavaScriptMapConstant.JS_DATA_NAME) {
         arguments.add(jsGeneralMap());
@@ -320,22 +372,7 @@
   @override
   jsAst.Expression visitInterceptor(InterceptorConstantValue constant, [_]) {
     ClassEntity interceptorClass = constant.cls;
-    return _task.interceptorPrototypeAccess(interceptorClass);
-  }
-
-  @override
-  jsAst.Expression visitSynthetic(SyntheticConstantValue constant, [_]) {
-    switch (constant.valueKind) {
-      case SyntheticConstantKind.DUMMY_INTERCEPTOR:
-      case SyntheticConstantKind.EMPTY_VALUE:
-        return new jsAst.LiteralNumber('0');
-      case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
-      case SyntheticConstantKind.NAME:
-        return constant.payload;
-      default:
-        throw failedAt(NO_LOCATION_SPANNABLE,
-            "Unexpected DummyConstantKind ${constant.kind}");
-    }
+    return _emitter.interceptorPrototypeAccess(interceptorClass);
   }
 
   @override
@@ -349,11 +386,11 @@
     jsAst.Expression constructor =
         _emitter.constructorAccess(constant.type.element);
     List<jsAst.Expression> fields = <jsAst.Expression>[];
-    _worldBuilder.forEachInstanceField(element, (_, FieldEntity field,
-        {bool isElided}) {
-      if (isElided) return;
-      if (!_fieldAnalysis.getFieldData(field).isInitializedInAllocator) {
-        fields.add(constantReferenceGenerator(constant.fields[field]));
+    _elementEnvironment.forEachInstanceField(element, (_, FieldEntity field) {
+      FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(field);
+      if (fieldData.isElided) return;
+      if (!fieldData.isInitializedInAllocator) {
+        fields.add(_constantReferenceGenerator(constant.fields[field]));
       }
     });
     if (_rtiNeed.classNeedsTypeArguments(constant.type.element)) {
@@ -368,7 +405,7 @@
     ClassEntity cls =
         _commonElements.getInstantiationClass(constant.typeArguments.length);
     List<jsAst.Expression> fields = <jsAst.Expression>[
-      constantReferenceGenerator(constant.function),
+      _constantReferenceGenerator(constant.function),
       _reifiedTypeArguments(constant, constant.typeArguments)
     ];
     jsAst.Expression constructor = _emitter.constructorAccess(cls);
@@ -412,6 +449,6 @@
   @override
   jsAst.Expression visitDeferredGlobal(DeferredGlobalConstantValue constant,
       [_]) {
-    return constantReferenceGenerator(constant.referenced);
+    return _constantReferenceGenerator(constant.referenced);
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
deleted file mode 100644
index 2b65955..0000000
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ /dev/null
@@ -1,45 +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.
-
-import '../compile_time_constants.dart';
-import '../compiler.dart' show Compiler;
-import '../elements/entities.dart';
-
-/// [ConstantCompilerTask] for compilation of constants for the JavaScript
-/// backend.
-///
-/// Since this task needs to distinguish between frontend and backend constants
-/// the actual compilation of the constants is forwarded to a
-/// [DartConstantCompiler] for the frontend interpretation of the constants and
-/// to a [JavaScriptConstantCompiler] for the backend interpretation.
-class JavaScriptConstantTask extends ConstantCompilerTask {
-  JavaScriptConstantCompiler jsConstantCompiler;
-
-  JavaScriptConstantTask(Compiler compiler)
-      : this.jsConstantCompiler = new JavaScriptConstantCompiler(),
-        super(compiler.measurer);
-
-  @override
-  String get name => 'ConstantHandler';
-}
-
-/// The [JavaScriptConstantCompiler] is used to keep track of compile-time
-/// constants, initializations of global and static fields, and default values
-/// of optional parameters for the JavaScript interpretation of constants.
-class JavaScriptConstantCompiler implements BackendConstantEnvironment {
-  // TODO(johnniwinther): Move this to the backend constant handler.
-  /// Caches the statics where the initial value cannot be eagerly compiled.
-  final Set<FieldEntity> lazyStatics = new Set<FieldEntity>();
-
-  JavaScriptConstantCompiler();
-
-  @override
-  void registerLazyStatic(FieldEntity element) {
-    lazyStatics.add(element);
-  }
-
-  List<FieldEntity> getLazilyInitializedFieldsForEmission() {
-    return new List<FieldEntity>.from(lazyStatics);
-  }
-}
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index 9eb8195..ba98487 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -107,7 +107,7 @@
 
   void _registerInstantiatedType(InterfaceType type,
       {bool nativeUsage: false}) {
-    task.measure(() {
+    task.measureSubtask('codegen.typeUse', () {
       _worldBuilder.registerTypeInstantiation(type, _applyClassUse);
       listener.registerInstantiatedType(type, nativeUsage: nativeUsage);
     });
@@ -127,7 +127,7 @@
         failedAt(member,
             'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}');
       }
-    }, dryRun: true);
+    }, checkEnqueuerConsistency: true);
   }
 
   /// Callback for applying the use of a [cls].
@@ -160,27 +160,28 @@
 
   @override
   void processDynamicUse(DynamicUse dynamicUse) {
-    task.measure(() {
+    task.measureSubtask('codegen.dynamicUse', () {
       _worldBuilder.registerDynamicUse(dynamicUse, _applyMemberUse);
     });
   }
 
   @override
   void processStaticUse(StaticUse staticUse) {
-    _worldBuilder.registerStaticUse(staticUse, _applyMemberUse);
-    switch (staticUse.kind) {
-      case StaticUseKind.CONSTRUCTOR_INVOKE:
-      case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
-      case StaticUseKind.REDIRECTION:
-        processTypeUse(new TypeUse.instantiation(staticUse.type));
-        break;
-      case StaticUseKind.INLINING:
-        // TODO(johnniwinther): Should this be tracked with _MemberUsage ?
-        listener.registerUsedElement(staticUse.element);
-        break;
-      default:
-        break;
-    }
+    task.measureSubtask('codegen.staticUse', () {
+      _worldBuilder.registerStaticUse(staticUse, _applyMemberUse);
+      switch (staticUse.kind) {
+        case StaticUseKind.CONSTRUCTOR_INVOKE:
+        case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
+          processTypeUse(new TypeUse.instantiation(staticUse.type));
+          break;
+        case StaticUseKind.INLINING:
+          // TODO(johnniwinther): Should this be tracked with _MemberUsage ?
+          listener.registerUsedElement(staticUse.element);
+          break;
+        default:
+          break;
+      }
+    });
   }
 
   @override
@@ -230,7 +231,7 @@
 
   @override
   void processConstantUse(ConstantUse constantUse) {
-    task.measure(() {
+    task.measureSubtask('codegen.constantUse', () {
       if (_worldBuilder.registerConstantUse(constantUse)) {
         applyImpact(listener.registerUsedConstant(constantUse.value));
         _recentConstants = true;
@@ -245,7 +246,6 @@
   void _registerClosurizedMember(FunctionEntity element) {
     assert(element.isInstanceMember);
     applyImpact(listener.registerClosurizedMember(element));
-    _worldBuilder.registerClosurizedMember(element);
   }
 
   void _forEach(void f(WorkItem work)) {
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 36ff852..1396e15 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -23,24 +23,6 @@
   bool get shouldMinify => true;
 
   @override
-  final String getterPrefix = 'g';
-  @override
-  final String setterPrefix = 's';
-  @override
-  final String callPrefix = ''; // this will create function names $<n>
-  @override
-  String get operatorIsPrefix => r'$i';
-  @override
-  String get operatorAsPrefix => r'$a';
-  @override
-  String get callCatchAllName => r'$C';
-  @override
-  String get requiredParameterField => r'$R';
-  @override
-  String get defaultValuesField => r'$D';
-  @override
-  String get operatorSignature => r'$S';
-  @override
   String get genericInstantiationPrefix => r'$I';
 
   @override
@@ -48,8 +30,8 @@
       _staticsPropertyName ??= getFreshName(instanceScope, 'static');
 
   FrequencyBasedNamer(
-      JClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder)
-      : super(closedWorld, codegenWorldBuilder) {
+      JClosedWorld closedWorld, RuntimeTypeTags rtiTags, FixedNames fixedNames)
+      : super(closedWorld, rtiTags, fixedNames) {
     fieldRegistry = new _FieldNamingRegistry(this);
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index 5536b96..2084a1d 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -13,16 +13,19 @@
 import '../common/resolution.dart' show ResolutionImpact;
 import '../common_elements.dart' show ElementEnvironment;
 import '../constants/expressions.dart';
+import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
+import '../js_emitter/native_emitter.dart';
 import '../native/enqueue.dart';
 import '../native/behavior.dart';
 import '../options.dart';
 import '../universe/feature.dart';
-import '../universe/use.dart'
-    show StaticUse, StaticUseKind, TypeUse, TypeUseKind;
+import '../universe/selector.dart';
+import '../universe/use.dart';
 import '../universe/world_impact.dart' show TransformedWorldImpact, WorldImpact;
 import '../util/util.dart';
+import '../world.dart';
 import 'backend_impact.dart';
 import 'backend_usage.dart';
 import 'custom_elements_analysis.dart';
@@ -88,12 +91,6 @@
         case Feature.CATCH_STATEMENT:
           registerImpact(_impacts.catchStatement);
           break;
-        case Feature.COMPILE_TIME_ERROR:
-          if (_options.generateCodeWithCompileTimeErrors) {
-            // TODO(johnniwinther): This should have its own uncatchable error.
-            registerImpact(_impacts.throwRuntimeError);
-          }
-          break;
         case Feature.FALL_THROUGH_ERROR:
           registerImpact(_impacts.fallThroughError);
           break;
@@ -347,6 +344,7 @@
 
 class CodegenImpactTransformer {
   final CompilerOptions _options;
+  final JClosedWorld _closedWorld;
   final ElementEnvironment _elementEnvironment;
   final CommonElements _commonElements;
   final BackendImpacts _impacts;
@@ -357,9 +355,11 @@
   final Namer _namer;
   final OneShotInterceptorData _oneShotInterceptorData;
   final RuntimeTypesChecksBuilder _rtiChecksBuilder;
+  final NativeEmitter _nativeEmitter;
 
   CodegenImpactTransformer(
       this._options,
+      this._closedWorld,
       this._elementEnvironment,
       this._commonElements,
       this._impacts,
@@ -369,7 +369,8 @@
       this._nativeCodegenEnqueuer,
       this._namer,
       this._oneShotInterceptorData,
-      this._rtiChecksBuilder);
+      this._rtiChecksBuilder,
+      this._nativeEmitter);
 
   void onIsCheckForCodegen(DartType type, TransformedWorldImpact transformed) {
     if (type.isDynamic) return;
@@ -398,6 +399,17 @@
       }
     }
 
+    for (ConstantUse constantUse in impact.constantUses) {
+      switch (constantUse.value.kind) {
+        case ConstantValueKind.DEFERRED_GLOBAL:
+          _closedWorld.outputUnitData
+              .registerConstantDeferredUse(constantUse.value);
+          break;
+        default:
+          break;
+      }
+    }
+
     for (Pair<DartType, DartType> check
         in impact.typeVariableBoundsSubtypeChecks) {
       _rtiChecksBuilder.registerTypeVariableBoundsSubtypeCheck(
@@ -405,12 +417,34 @@
     }
 
     for (StaticUse staticUse in impact.staticUses) {
-      if (staticUse.kind == StaticUseKind.CALL_METHOD) {
-        FunctionEntity callMethod = staticUse.element;
-        if (_rtiNeed.methodNeedsSignature(callMethod)) {
-          _impacts.computeSignature
-              .registerImpact(transformed, _elementEnvironment);
-        }
+      switch (staticUse.kind) {
+        case StaticUseKind.CALL_METHOD:
+          FunctionEntity callMethod = staticUse.element;
+          if (_rtiNeed.methodNeedsSignature(callMethod)) {
+            _impacts.computeSignature
+                .registerImpact(transformed, _elementEnvironment);
+          }
+          break;
+        case StaticUseKind.STATIC_TEAR_OFF:
+        case StaticUseKind.INSTANCE_FIELD_GET:
+        case StaticUseKind.INSTANCE_FIELD_SET:
+        case StaticUseKind.SUPER_INVOKE:
+        case StaticUseKind.STATIC_INVOKE:
+        case StaticUseKind.SUPER_FIELD_SET:
+        case StaticUseKind.SUPER_SETTER_SET:
+        case StaticUseKind.STATIC_SET:
+        case StaticUseKind.SUPER_TEAR_OFF:
+        case StaticUseKind.SUPER_GET:
+        case StaticUseKind.STATIC_GET:
+        case StaticUseKind.FIELD_INIT:
+        case StaticUseKind.FIELD_CONSTANT_INIT:
+        case StaticUseKind.CONSTRUCTOR_INVOKE:
+        case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
+        case StaticUseKind.DIRECT_INVOKE:
+        case StaticUseKind.INLINING:
+        case StaticUseKind.CLOSURE:
+        case StaticUseKind.CLOSURE_CALL:
+          break;
       }
     }
 
@@ -449,6 +483,20 @@
       _rtiChecksBuilder.registerGenericInstantiation(instantiation);
     }
 
+    for (NativeBehavior behavior in impact.nativeBehaviors) {
+      _nativeCodegenEnqueuer.registerNativeBehavior(
+          transformed, behavior, impact);
+    }
+
+    for (FunctionEntity function in impact.nativeMethods) {
+      _nativeEmitter.nativeMethods.add(function);
+    }
+
+    for (Selector selector in impact.oneShotInterceptors) {
+      _oneShotInterceptorData.registerOneShotInterceptor(
+          selector, _namer, _closedWorld);
+    }
+
     // TODO(johnniwinther): Remove eager registration.
     return transformed;
   }
diff --git a/pkg/compiler/lib/src/js_backend/interceptor_data.dart b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
index 1d604c9..db85765 100644
--- a/pkg/compiler/lib/src/js_backend/interceptor_data.dart
+++ b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
@@ -12,9 +12,10 @@
 import '../inferrer/abstract_value_domain.dart';
 import '../js/js.dart' as jsAst;
 import '../serialization/serialization.dart';
+import '../universe/class_set.dart';
 import '../universe/selector.dart';
 import '../world.dart' show JClosedWorld;
-import 'namer.dart';
+import 'namer.dart' show ModularNamer, suffixForGetInterceptor;
 import 'native_data.dart';
 
 abstract class InterceptorData {
@@ -252,6 +253,7 @@
           if (result == null) result = new Set<ClassEntity>();
           result.add(subclass);
         }
+        return IterationStep.CONTINUE;
       });
     }
     return result;
@@ -354,55 +356,79 @@
 class OneShotInterceptorData {
   final InterceptorData _interceptorData;
   final CommonElements _commonElements;
+  final NativeData _nativeData;
 
-  OneShotInterceptorData(this._interceptorData, this._commonElements);
+  OneShotInterceptorData(
+      this._interceptorData, this._commonElements, this._nativeData);
 
-  /// A collection of selectors that must have a one shot interceptor generated.
-  final Map<jsAst.Name, Selector> _oneShotInterceptors =
-      <jsAst.Name, Selector>{};
+  Iterable<OneShotInterceptor> get oneShotInterceptors {
+    List<OneShotInterceptor> interceptors = [];
+    for (var map in _oneShotInterceptors.values) {
+      interceptors.addAll(map.values);
+    }
+    return interceptors;
+  }
 
-  Selector getOneShotInterceptorSelector(jsAst.Name name) =>
-      _oneShotInterceptors[name];
+  Map<Selector, Map<String, OneShotInterceptor>> _oneShotInterceptors = {};
 
-  Iterable<jsAst.Name> get oneShotInterceptorNames =>
-      _oneShotInterceptors.keys.toList()..sort();
-
-  /// A map of specialized versions of the [getInterceptorMethod].
+  /// A set of specialized versions of the [getInterceptorMethod].
   ///
   /// Since [getInterceptorMethod] is a hot method at runtime, we're always
   /// specializing it based on the incoming type. The keys in the map are the
   /// names of these specialized versions. Note that the generic version that
   /// contains all possible type checks is also stored in this map.
-  final Map<jsAst.Name, Set<ClassEntity>> _specializedGetInterceptors =
-      <jsAst.Name, Set<ClassEntity>>{};
+  Iterable<SpecializedGetInterceptor> get specializedGetInterceptors =>
+      _specializedGetInterceptors.values;
 
-  Iterable<jsAst.Name> get specializedGetInterceptorNames =>
-      _specializedGetInterceptors.keys.toList()..sort();
-
-  Set<ClassEntity> getSpecializedGetInterceptorsFor(jsAst.Name name) =>
-      _specializedGetInterceptors[name];
+  Map<String, SpecializedGetInterceptor> _specializedGetInterceptors = {};
 
   jsAst.Name registerOneShotInterceptor(
-      Selector selector, Namer namer, JClosedWorld closedWorld) {
+      Selector selector, ModularNamer namer, JClosedWorld closedWorld) {
+    selector = selector.toNormalized();
     Set<ClassEntity> classes =
         _interceptorData.getInterceptedClassesOn(selector.name, closedWorld);
-    jsAst.Name name = namer.nameForGetOneShotInterceptor(selector, classes);
-    if (!_oneShotInterceptors.containsKey(name)) {
-      registerSpecializedGetInterceptor(classes, namer);
-      _oneShotInterceptors[name] = selector;
-    }
-    return name;
+    String key = suffixForGetInterceptor(_commonElements, _nativeData, classes);
+    Map<String, OneShotInterceptor> interceptors =
+        _oneShotInterceptors[selector] ??= {};
+    OneShotInterceptor interceptor =
+        interceptors[key] ??= new OneShotInterceptor(key, selector);
+    interceptor.classes.addAll(classes);
+    registerSpecializedGetInterceptor(classes, namer);
+    return namer.nameForOneShotInterceptor(selector, classes);
   }
 
   void registerSpecializedGetInterceptor(
-      Set<ClassEntity> classes, Namer namer) {
-    jsAst.Name name = namer.nameForGetInterceptor(classes);
+      Set<ClassEntity> classes, ModularNamer namer) {
     if (classes.contains(_commonElements.jsInterceptorClass)) {
       // We can't use a specialized [getInterceptorMethod], so we make
       // sure we emit the one with all checks.
-      _specializedGetInterceptors[name] = _interceptorData.interceptedClasses;
-    } else {
-      _specializedGetInterceptors[name] = classes;
+      classes = _interceptorData.interceptedClasses;
     }
+    String key = suffixForGetInterceptor(_commonElements, _nativeData, classes);
+    SpecializedGetInterceptor interceptor =
+        _specializedGetInterceptors[key] ??= new SpecializedGetInterceptor(key);
+    interceptor.classes.addAll(classes);
   }
 }
+
+class OneShotInterceptor {
+  final Selector selector;
+  final String key;
+  final Set<ClassEntity> classes = {};
+
+  OneShotInterceptor(this.key, this.selector);
+
+  @override
+  String toString() =>
+      'OneShotInterceptor(selector=$selector,key=$key,classes=$classes)';
+}
+
+class SpecializedGetInterceptor {
+  final String key;
+  final Set<ClassEntity> classes = {};
+
+  SpecializedGetInterceptor(this.key);
+
+  @override
+  String toString() => 'SpecializedGetInterceptor(key=$key,classes=$classes)';
+}
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index ab26bfb..7a00a6c 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -7,7 +7,6 @@
 export 'backend.dart';
 export 'checked_mode_helpers.dart';
 export 'constant_emitter.dart';
-export 'constant_handler_javascript.dart';
 export 'custom_elements_analysis.dart';
 export 'namer.dart';
 export 'no_such_method_registry.dart';
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 225d9b5..549909d 100644
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -14,11 +14,11 @@
 import 'namer.dart';
 import 'native_data.dart';
 
-jsAst.Statement buildJsInteropBootstrap(CodegenWorldBuilder codegenWorldBuilder,
-    NativeBasicData nativeBasicData, Namer namer) {
+jsAst.Statement buildJsInteropBootstrap(
+    CodegenWorld codegenWorld, NativeBasicData nativeBasicData, Namer namer) {
   if (!nativeBasicData.isJsInteropUsed) return null;
   List<jsAst.Statement> statements = <jsAst.Statement>[];
-  codegenWorldBuilder.forEachInvokedName(
+  codegenWorld.forEachInvokedName(
       (String name, Map<Selector, SelectorConstraints> selectors) {
     selectors.forEach((Selector selector, SelectorConstraints constraints) {
       if (selector.isClosureCall) {
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index 3179a2f..709ee76 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -10,8 +10,9 @@
         _MinifiedFieldNamer,
         _MinifyConstructorBodyNamer,
         _MinifiedOneShotInterceptorNamer {
-  MinifyNamer(JClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder)
-      : super(closedWorld, codegenWorldBuilder) {
+  MinifyNamer(
+      JClosedWorld closedWorld, RuntimeTypeTags rtiTags, FixedNames fixedNames)
+      : super(closedWorld, rtiTags, fixedNames) {
     reserveBackendNames();
     fieldRegistry = new _FieldNamingRegistry(this);
   }
@@ -25,25 +26,6 @@
   String get isolatePropertiesName => 'p';
   @override
   bool get shouldMinify => true;
-
-  @override
-  final String getterPrefix = 'g';
-  @override
-  final String setterPrefix = 's';
-  @override
-  final String callPrefix = ''; // this will create function names $<n>
-  @override
-  String get operatorIsPrefix => r'$i';
-  @override
-  String get operatorAsPrefix => r'$a';
-  @override
-  String get callCatchAllName => r'$C';
-  @override
-  String get requiredParameterField => r'$R';
-  @override
-  String get defaultValuesField => r'$D';
-  @override
-  String get operatorSignature => r'$S';
   @override
   String get genericInstantiationPrefix => r'$I';
 
@@ -392,7 +374,7 @@
   @override
   jsAst.Name constructorBodyName(ConstructorBodyEntity method) {
     _ConstructorBodyNamingScope scope = new _ConstructorBodyNamingScope(
-        method.enclosingClass, _constructorBodyScopes, elementEnvironment);
+        method.enclosingClass, _constructorBodyScopes, _elementEnvironment);
     String key = scope.constructorBodyKeyFor(method);
     return _disambiguateMemberByKey(
         key, () => _proposeNameForConstructorBody(method));
@@ -403,7 +385,7 @@
   /// Property name used for the one-shot interceptor method for the given
   /// [selector] and return-type specialization.
   @override
-  jsAst.Name nameForGetOneShotInterceptor(
+  jsAst.Name nameForOneShotInterceptor(
       Selector selector, Iterable<ClassEntity> classes) {
     String root = selector.isOperator
         ? operatorNameToIdentifier(selector.name)
@@ -413,7 +395,8 @@
     String callSuffix = selector.isCall
         ? Namer.callSuffixForStructure(selector.callStructure).join()
         : "";
-    String suffix = suffixForGetInterceptor(classes);
+    String suffix =
+        suffixForGetInterceptor(_commonElements, _nativeData, classes);
     String fullName = "\$intercepted$prefix\$$root$callSuffix\$$suffix";
     return _disambiguateInternalGlobal(fullName);
   }
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 0648b9c..c4b1477 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -13,7 +13,9 @@
 
 import '../closure.dart';
 import '../common.dart';
+import '../common/codegen.dart';
 import '../common/names.dart' show Identifiers, Names, Selectors;
+import '../common_elements.dart' show JElementEnvironment;
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
 import '../common_elements.dart' show CommonElements, ElementEnvironment;
@@ -24,16 +26,15 @@
 import '../elements/names.dart';
 import '../elements/types.dart';
 import '../js/js.dart' as jsAst;
+import '../js_backend/field_analysis.dart';
+import '../js_backend/runtime_types.dart' show RuntimeTypeTags;
 import '../js_model/closure.dart';
 import '../js_model/elements.dart' show JGeneratorBody;
 import '../universe/call_structure.dart' show CallStructure;
-import '../universe/codegen_world_builder.dart';
 import '../universe/selector.dart' show Selector, SelectorKind;
 import '../util/util.dart';
 import '../world.dart' show JClosedWorld;
-import 'backend.dart';
 import 'native_data.dart';
-import 'runtime_types.dart';
 
 part 'field_naming_mixin.dart';
 part 'frequency_namer.dart';
@@ -135,7 +136,7 @@
 ///
 /// For local variables, the [Namer] only provides *proposed names*. These names
 /// must be disambiguated elsewhere.
-class Namer {
+class Namer extends ModularNamer {
   static const List<String> javaScriptKeywords = const <String>[
     // ES5 7.6.1.1 Keywords.
     'break',
@@ -420,45 +421,21 @@
     return _jsReserved;
   }
 
-  Set<String> _jsVariableReserved = null;
-
-  /// Names that cannot be used by local variables and parameters.
-  Set<String> get jsVariableReserved {
-    if (_jsVariableReserved == null) {
-      _jsVariableReserved = new Set<String>();
-      _jsVariableReserved.addAll(javaScriptKeywords);
-      _jsVariableReserved.addAll(reservedPropertySymbols);
-      _jsVariableReserved.addAll(reservedGlobalSymbols);
-      _jsVariableReserved.addAll(reservedGlobalObjectNames);
-      // 26 letters in the alphabet, 25 not counting I.
-      assert(reservedGlobalObjectNames.length == 25);
-      _jsVariableReserved.addAll(reservedGlobalHelperFunctions);
-    }
-    return _jsVariableReserved;
-  }
-
-  final String asyncPrefix = r"$async$";
-  final String staticStateHolder = r'$';
-  final String getterPrefix = r'get$';
   final String lazyGetterPrefix = r'$get$';
-  final String setterPrefix = r'set$';
   final String superPrefix = r'super$';
   final String metadataField = '@';
-  final String callPrefix = 'call';
-  String get callCatchAllName => r'call*';
-  final String callNameField = r'$callName';
   final String stubNameField = r'$stubName';
-  final String reflectableField = r'$reflectable';
   final String reflectionInfoField = r'$reflectionInfo';
   final String reflectionNameField = r'$reflectionName';
   final String metadataIndexField = r'$metadataIndex';
-  String get requiredParameterField => r'$requiredArgCount';
-  String get defaultValuesField => r'$defaultValues';
   final String methodsWithOptionalArgumentsField =
       r'$methodsWithOptionalArguments';
-  final String deferredAction = r'$deferredAction';
 
-  final String classDescriptorProperty = r'^';
+  @override
+  final RuntimeTypeTags rtiTags;
+
+  @override
+  final FixedNames fixedNames;
 
   /// The non-minifying namer's [callPrefix] with a dollar after it.
   static const String _callPrefixDollar = r'call$';
@@ -468,7 +445,6 @@
   static final jsAst.Name literalPlus = new StringBackedName('+');
   static final jsAst.Name _literalDynamic = new StringBackedName("dynamic");
 
-  jsAst.Name _literalAsyncPrefix;
   jsAst.Name _literalGetterPrefix;
   jsAst.Name _literalSetterPrefix;
 
@@ -477,11 +453,11 @@
   jsAst.Name get staticsPropertyName =>
       _staticsPropertyName ??= new StringBackedName('static');
 
-  final String rtiName = r'$ti';
-
   jsAst.Name _rtiFieldJsName;
+
+  @override
   jsAst.Name get rtiFieldJsName =>
-      _rtiFieldJsName ??= new StringBackedName(rtiName);
+      _rtiFieldJsName ??= new StringBackedName(fixedNames.rtiName);
 
   // Name of property in a class description for the native dispatch metadata.
   final String nativeSpecProperty = '%';
@@ -490,22 +466,6 @@
   static final RegExp NON_IDENTIFIER_CHAR = new RegExp(r'[^A-Za-z_0-9$]');
 
   final JClosedWorld _closedWorld;
-  final CodegenWorldBuilder _codegenWorldBuilder;
-
-  RuntimeTypesEncoder _rtiEncoder;
-  RuntimeTypesEncoder get rtiEncoder {
-    assert(_rtiEncoder != null,
-        failedAt(NO_LOCATION_SPANNABLE, "Namer.rtiEncoder has not been set."));
-    return _rtiEncoder;
-  }
-
-  void set rtiEncoder(RuntimeTypesEncoder value) {
-    assert(
-        _rtiEncoder == null,
-        failedAt(
-            NO_LOCATION_SPANNABLE, "Namer.rtiEncoder has already been set."));
-    _rtiEncoder = value;
-  }
 
   /// Used disambiguated names in the global namespace, issued by
   /// [_disambiguateGlobal], and [_disambiguateInternalGlobal].
@@ -596,14 +556,15 @@
   /// key into maps.
   final Map<LibraryEntity, String> _libraryKeys = HashMap();
 
-  Namer(this._closedWorld, this._codegenWorldBuilder) {
-    _literalAsyncPrefix = new StringBackedName(asyncPrefix);
-    _literalGetterPrefix = new StringBackedName(getterPrefix);
-    _literalSetterPrefix = new StringBackedName(setterPrefix);
+  Namer(this._closedWorld, this.rtiTags, this.fixedNames) {
+    _literalGetterPrefix = new StringBackedName(fixedNames.getterPrefix);
+    _literalSetterPrefix = new StringBackedName(fixedNames.setterPrefix);
   }
 
-  ElementEnvironment get elementEnvironment => _closedWorld.elementEnvironment;
+  JElementEnvironment get _elementEnvironment =>
+      _closedWorld.elementEnvironment;
 
+  @override
   CommonElements get _commonElements => _closedWorld.commonElements;
 
   NativeData get _nativeData => _closedWorld.nativeData;
@@ -625,83 +586,6 @@
         entity.rootOfScope, () => new NamingScope());
   }
 
-  /// Returns the string that is to be used as the result of a call to
-  /// [JS_GET_NAME] at [node] with argument [name].
-  jsAst.Name getNameForJsGetName(Spannable spannable, JsGetName name) {
-    switch (name) {
-      case JsGetName.GETTER_PREFIX:
-        return asName(getterPrefix);
-      case JsGetName.SETTER_PREFIX:
-        return asName(setterPrefix);
-      case JsGetName.CALL_PREFIX:
-        return asName(callPrefix);
-      case JsGetName.CALL_PREFIX0:
-        return asName('${callPrefix}\$0');
-      case JsGetName.CALL_PREFIX1:
-        return asName('${callPrefix}\$1');
-      case JsGetName.CALL_PREFIX2:
-        return asName('${callPrefix}\$2');
-      case JsGetName.CALL_PREFIX3:
-        return asName('${callPrefix}\$3');
-      case JsGetName.CALL_PREFIX4:
-        return asName('${callPrefix}\$4');
-      case JsGetName.CALL_PREFIX5:
-        return asName('${callPrefix}\$5');
-      case JsGetName.CALL_CATCH_ALL:
-        return asName(callCatchAllName);
-      case JsGetName.REFLECTABLE:
-        return asName(reflectableField);
-      case JsGetName.CLASS_DESCRIPTOR_PROPERTY:
-        return asName(classDescriptorProperty);
-      case JsGetName.REQUIRED_PARAMETER_PROPERTY:
-        return asName(requiredParameterField);
-      case JsGetName.DEFAULT_VALUES_PROPERTY:
-        return asName(defaultValuesField);
-      case JsGetName.CALL_NAME_PROPERTY:
-        return asName(callNameField);
-      case JsGetName.DEFERRED_ACTION_PROPERTY:
-        return asName(deferredAction);
-      case JsGetName.OPERATOR_AS_PREFIX:
-        return asName(operatorAsPrefix);
-      case JsGetName.SIGNATURE_NAME:
-        return asName(operatorSignature);
-      case JsGetName.RTI_NAME:
-        return asName(rtiName);
-      case JsGetName.TYPEDEF_TAG:
-        return asName(typedefTag);
-      case JsGetName.FUNCTION_TYPE_TAG:
-        return asName(functionTypeTag);
-      case JsGetName.FUNCTION_TYPE_GENERIC_BOUNDS_TAG:
-        return asName(functionTypeGenericBoundsTag);
-      case JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG:
-        return asName(functionTypeVoidReturnTag);
-      case JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG:
-        return asName(functionTypeReturnTypeTag);
-      case JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG:
-        return asName(functionTypeRequiredParametersTag);
-      case JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG:
-        return asName(functionTypeOptionalParametersTag);
-      case JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG:
-        return asName(functionTypeNamedParametersTag);
-      case JsGetName.FUTURE_OR_TAG:
-        return asName(futureOrTag);
-      case JsGetName.FUTURE_OR_TYPE_ARGUMENT_TAG:
-        return asName(futureOrTypeTag);
-      case JsGetName.IS_INDEXABLE_FIELD_NAME:
-        return operatorIs(_commonElements.jsIndexingBehaviorInterface);
-      case JsGetName.NULL_CLASS_TYPE_NAME:
-        return runtimeTypeName(_commonElements.nullClass);
-      case JsGetName.OBJECT_CLASS_TYPE_NAME:
-        return runtimeTypeName(_commonElements.objectClass);
-      case JsGetName.FUNCTION_CLASS_TYPE_NAME:
-        return runtimeTypeName(_commonElements.functionClass);
-      case JsGetName.FUTURE_CLASS_TYPE_NAME:
-        return runtimeTypeName(_commonElements.futureClass);
-      default:
-        throw failedAt(spannable, 'Error: Namer has no name for "$name".');
-    }
-  }
-
   /// Return a reference to the given [name].
   ///
   /// This is used to ensure that every use site of a name has a unique node so
@@ -731,34 +615,14 @@
   String constantLongName(ConstantValue constant) {
     String longName = _constantLongNames[constant];
     if (longName == null) {
-      _constantHasher ??=
-          new ConstantCanonicalHasher(rtiEncoder, _codegenWorldBuilder);
-      longName = new ConstantNamingVisitor(
-              rtiEncoder, _codegenWorldBuilder, _constantHasher)
+      _constantHasher ??= new ConstantCanonicalHasher(this, _closedWorld);
+      longName = new ConstantNamingVisitor(this, _closedWorld, _constantHasher)
           .getName(constant);
       _constantLongNames[constant] = longName;
     }
     return longName;
   }
 
-  String breakLabelName(LabelDefinition label) {
-    return '\$${label.labelName}\$${label.target.nestingLevel}';
-  }
-
-  String implicitBreakLabelName(JumpTarget target) {
-    return '\$${target.nestingLevel}';
-  }
-
-  // We sometimes handle continue targets differently from break targets,
-  // so we have special continue-only labels.
-  String continueLabelName(LabelDefinition label) {
-    return 'c\$${label.labelName}\$${label.target.nestingLevel}';
-  }
-
-  String implicitContinueLabelName(JumpTarget target) {
-    return 'c\$${target.nestingLevel}';
-  }
-
   /// If the [originalName] is not private returns [originalName]. Otherwise
   /// mangles the [originalName] so that each library has its own distinguished
   /// version of the name.
@@ -823,7 +687,7 @@
     });
   }
 
-  /// Annotated name for [method] encoding arity and named parameters.
+  @override
   jsAst.Name instanceMethodName(FunctionEntity method) {
     // TODO(johnniwinther): Avoid the use of [ConstructorBodyEntity] and
     // [JGeneratorBody]. The codegen model should be explicit about its
@@ -846,7 +710,8 @@
   /// concatenation at runtime, by applyFunction in js_helper.dart.
   jsAst.Name deriveCallMethodName(List<String> suffix) {
     // TODO(asgerf): Avoid clashes when named parameters contain $ symbols.
-    return new StringBackedName('$callPrefix\$${suffix.join(r'$')}');
+    return new StringBackedName(
+        '${fixedNames.callPrefix}\$${suffix.join(r'$')}');
   }
 
   /// The suffix list for the pattern:
@@ -882,7 +747,7 @@
     return suffixes;
   }
 
-  /// Annotated name for the member being invoked by [selector].
+  @override
   jsAst.Name invocationName(Selector selector) {
     switch (selector.kind) {
       case SelectorKind.GETTER:
@@ -950,31 +815,19 @@
         : _disambiguateGlobalMember(element);
   }
 
-  /// Returns a JavaScript property name used to store the member [element] on
-  /// one of the global objects.
-  ///
-  /// Should be used together with [globalObjectForMember], which denotes the
-  /// object on which the returned property name should be used.
+  @override
   jsAst.Name globalPropertyNameForMember(MemberEntity element) =>
       _disambiguateGlobalMember(element);
 
-  /// Returns a JavaScript property name used to store the class [element] on
-  /// one of the global objects.
-  ///
-  /// Should be used together with [globalObjectForClass], which denotes the
-  /// object on which the returned property name should be used.
+  @override
   jsAst.Name globalPropertyNameForClass(ClassEntity element) =>
       _disambiguateGlobalType(element);
 
-  /// Returns a JavaScript property name used to store the type (typedef)
-  /// [element] on one of the global objects.
-  ///
-  /// Should be used together with [globalObjectForType], which denotes the
-  /// object on which the returned property name should be used.
+  @override
   jsAst.Name globalPropertyNameForType(Entity element) =>
       _disambiguateGlobalType(element);
 
-  /// Returns the JavaScript property name used to store an instance field.
+  @override
   jsAst.Name instanceFieldPropertyName(FieldEntity element) {
     ClassEntity enclosingClass = element.enclosingClass;
 
@@ -1020,10 +873,10 @@
     bool isPrivate = Name.isPrivateName(fieldName);
     LibraryEntity memberLibrary = element.library;
     ClassEntity lookupClass =
-        elementEnvironment.getSuperClass(element.enclosingClass);
+        _elementEnvironment.getSuperClass(element.enclosingClass);
     while (lookupClass != null) {
       MemberEntity foundMember =
-          elementEnvironment.lookupLocalClassMember(lookupClass, fieldName);
+          _elementEnvironment.lookupLocalClassMember(lookupClass, fieldName);
       if (foundMember != null) {
         if (foundMember.isField) {
           if (!isPrivate || memberLibrary == foundMember.library) {
@@ -1033,7 +886,7 @@
           }
         }
       }
-      lookupClass = elementEnvironment.getSuperClass(lookupClass);
+      lookupClass = _elementEnvironment.getSuperClass(lookupClass);
     }
     return false;
   }
@@ -1340,8 +1193,8 @@
     // or with one of the `call` stubs, such as `call$1`.
     assert(this is! MinifyNamer);
     if (name.startsWith(r'$') ||
-        name.startsWith(getterPrefix) ||
-        name.startsWith(setterPrefix) ||
+        name.startsWith(fixedNames.getterPrefix) ||
+        name.startsWith(fixedNames.setterPrefix) ||
         name.startsWith(_callPrefixDollar)) {
       name = '\$$name';
     }
@@ -1439,34 +1292,6 @@
     return disambiguated;
   }
 
-  String suffixForGetInterceptor(Iterable<ClassEntity> classes) {
-    String abbreviate(ClassEntity cls) {
-      if (cls == _commonElements.objectClass) return "o";
-      if (cls == _commonElements.jsStringClass) return "s";
-      if (cls == _commonElements.jsArrayClass) return "a";
-      if (cls == _commonElements.jsDoubleClass) return "d";
-      if (cls == _commonElements.jsIntClass) return "i";
-      if (cls == _commonElements.jsNumberClass) return "n";
-      if (cls == _commonElements.jsNullClass) return "u";
-      if (cls == _commonElements.jsBoolClass) return "b";
-      if (cls == _commonElements.jsInterceptorClass) return "I";
-      return cls.name;
-    }
-
-    List<String> names = classes
-        .where((cls) => !_nativeData.isNativeOrExtendsNative(cls))
-        .map(abbreviate)
-        .toList();
-    // There is one dispatch mechanism for all native classes.
-    if (classes.any((cls) => _nativeData.isNativeOrExtendsNative(cls))) {
-      names.add("x");
-    }
-    // Sort the names of the classes after abbreviating them to ensure
-    // the suffix is stable and predictable for the suggested names.
-    names.sort();
-    return names.join();
-  }
-
   String _getSuffixForInterceptedClasses(Iterable<ClassEntity> classes) {
     if (classes.isEmpty) {
       // TODO(johnniwinther,sra): If [classes] is empty it should either have
@@ -1484,15 +1309,11 @@
       // set of classes for most general variant, e.g. "$lt$n" could be "$lt".
       return '';
     } else {
-      return suffixForGetInterceptor(classes);
+      return suffixForGetInterceptor(_commonElements, _nativeData, classes);
     }
   }
 
-  /// Property name used for a specialization of `getInterceptor`.
-  ///
-  /// js_runtime contains a top-level `getInterceptor` method. The
-  /// specializations have the same name, but with a suffix to avoid name
-  /// collisions.
+  @override
   jsAst.Name nameForGetInterceptor(Iterable<ClassEntity> classes) {
     // If the base Interceptor class is in the set of intercepted classes, we
     // need to go through the generic getInterceptor method (any subclass of the
@@ -1501,9 +1322,8 @@
     return _disambiguateInternalGlobal('getInterceptor\$$suffix');
   }
 
-  /// Property name used for the one-shot interceptor method for the given
-  /// [selector] and return-type specialization.
-  jsAst.Name nameForGetOneShotInterceptor(
+  @override
+  jsAst.Name nameForOneShotInterceptor(
       Selector selector, Iterable<ClassEntity> classes) {
     // The one-shot name is a global name derived from the invocation name.  To
     // avoid instability we would like the names to be unique and not clash with
@@ -1515,15 +1335,7 @@
         [root, _literalDollar, new StringBackedName(suffix)]);
   }
 
-  /// Returns the runtime name for [element].
-  ///
-  /// This name is used as the basis for deriving `is` and `as` property names
-  /// for the given type.
-  ///
-  /// The result is not always safe as a property name unless prefixing
-  /// [operatorIsPrefix] or [operatorAsPrefix]. If this is a function type,
-  /// then by convention, an underscore must also separate [operatorIsPrefix]
-  /// from the type name.
+  @override
   jsAst.Name runtimeTypeName(Entity element) {
     if (element == null) return _literalDynamic;
     // The returned name affects both the global and instance member namespaces:
@@ -1540,32 +1352,10 @@
     return _disambiguateGlobalType(element);
   }
 
-  /// Returns the disambiguated name of [class_].
-  ///
-  /// This is both the *runtime type* of the class (see [runtimeTypeName])
-  /// and a global property name in which to store its JS constructor.
+  @override
   jsAst.Name className(ClassEntity class_) => _disambiguateGlobalType(class_);
 
-  /// Property name on which [member] can be accessed directly,
-  /// without clashing with another JS property name.
-  ///
-  /// This is used for implementing super-calls, where ordinary dispatch
-  /// semantics must be circumvented. For example:
-  ///
-  ///     class A { foo() }
-  ///     class B extends A {
-  ///         foo() { super.foo() }
-  ///     }
-  ///
-  /// Example translation to JS:
-  ///
-  ///     A.prototype.super$A$foo = function() {...}
-  ///     A.prototype.foo$0 = A.prototype.super$A$foo
-  ///
-  ///     B.prototype.foo$0 = function() {
-  ///         this.super$A$foo(); // super.foo()
-  ///     }
-  ///
+  @override
   jsAst.Name aliasedSuperMemberPropertyName(MemberEntity member) {
     assert(!member.isField); // Fields do not need super aliases.
     return _disambiguateInternalMember(member, () {
@@ -1575,12 +1365,7 @@
     });
   }
 
-  /// Property name in which to store the given static or instance [method].
-  /// For instance methods, this includes the suffix encoding arity and named
-  /// parameters.
-  ///
-  /// The name is not necessarily unique to [method], since a static method
-  /// may share its name with an instance method.
+  @override
   jsAst.Name methodPropertyName(FunctionEntity method) {
     return method.isInstanceMember
         ? instanceMethodName(method)
@@ -1604,10 +1389,23 @@
     return globalObjectForLibrary(element.library);
   }
 
+  @override
+  jsAst.VariableUse readGlobalObjectForMember(MemberEntity element) {
+    if (_isPropertyOfStaticStateHolder(element)) {
+      return new jsAst.VariableUse(staticStateHolder);
+    }
+    return readGlobalObjectForLibrary(element.library);
+  }
+
   String globalObjectForClass(ClassEntity element) {
     return globalObjectForLibrary(element.library);
   }
 
+  @override
+  jsAst.VariableUse readGlobalObjectForClass(ClassEntity element) {
+    return readGlobalObjectForLibrary(element.library);
+  }
+
   String globalObjectForType(Entity element) {
     if (element is TypedefEntity) {
       return globalObjectForLibrary(element.library);
@@ -1615,6 +1413,14 @@
     return globalObjectForClass(element);
   }
 
+  @override
+  jsAst.VariableUse readGlobalObjectForType(Entity element) {
+    if (element is TypedefEntity) {
+      return readGlobalObjectForLibrary(element.library);
+    }
+    return readGlobalObjectForClass(element);
+  }
+
   /// Returns the [reservedGlobalObjectNames] for [library].
   String globalObjectForLibrary(LibraryEntity library) {
     if (library == _commonElements.interceptorsLibrary) return 'J';
@@ -1627,6 +1433,12 @@
     return userGlobalObjects[library.name.hashCode % userGlobalObjects.length];
   }
 
+  @override
+  jsAst.VariableUse readGlobalObjectForLibrary(LibraryEntity library) {
+    return new jsAst.VariableUse(globalObjectForLibrary(library));
+  }
+
+  @override
   jsAst.Name lazyInitializerName(FieldEntity element) {
     assert(element.isTopLevel || element.isStatic);
     jsAst.Name name = _disambiguateGlobal<MemberEntity>(
@@ -1634,6 +1446,7 @@
     return name;
   }
 
+  @override
   jsAst.Name staticClosureName(FunctionEntity element) {
     assert(element.isTopLevel || element.isStatic);
     String enclosing =
@@ -1654,34 +1467,8 @@
 
   String globalObjectForConstant(ConstantValue constant) => 'C';
 
-  String get operatorIsPrefix => r'$is';
-
-  String get operatorAsPrefix => r'$as';
-
-  String get operatorSignature => r'$signature';
-
   String get genericInstantiationPrefix => r'$instantiate';
 
-  String get typedefTag => r'typedef';
-
-  String get functionTypeTag => r'func';
-
-  String get functionTypeVoidReturnTag => r'v';
-
-  String get functionTypeReturnTypeTag => r'ret';
-
-  String get functionTypeRequiredParametersTag => r'args';
-
-  String get functionTypeOptionalParametersTag => r'opt';
-
-  String get functionTypeNamedParametersTag => r'named';
-
-  String get functionTypeGenericBoundsTag => r'bounds';
-
-  String get futureOrTag => r'futureOr';
-
-  String get futureOrTypeTag => r'type';
-
   // The name of the variable used to offset function signatures in deferred
   // parts with the fast-startup emitter.
   String get typesOffsetName => r'typesOffset';
@@ -1692,17 +1479,18 @@
 
   jsAst.Name getFunctionTypeName(FunctionType functionType) {
     return functionTypeNameMap.putIfAbsent(functionType, () {
-      _functionTypeNamer ??= new FunctionTypeNamer(rtiEncoder);
+      _functionTypeNamer ??= new FunctionTypeNamer();
       String proposedName = _functionTypeNamer.computeName(functionType);
       return getFreshName(instanceScope, proposedName);
     });
   }
 
+  @override
   jsAst.Name operatorIsType(DartType type) {
     if (type.isFunctionType) {
       // TODO(erikcorry): Reduce from $isx to ix when we are minifying.
       return new CompoundName([
-        new StringBackedName(operatorIsPrefix),
+        new StringBackedName(fixedNames.operatorIsPrefix),
         _literalUnderscore,
         getFunctionTypeName(type)
       ]);
@@ -1711,10 +1499,13 @@
     return operatorIs(interfaceType.element);
   }
 
+  @override
   jsAst.Name operatorIs(ClassEntity element) {
     // TODO(erikcorry): Reduce from $isx to ix when we are minifying.
-    return new CompoundName(
-        [new StringBackedName(operatorIsPrefix), runtimeTypeName(element)]);
+    return new CompoundName([
+      new StringBackedName(fixedNames.operatorIsPrefix),
+      runtimeTypeName(element)
+    ]);
   }
 
   /// Returns a name that does not clash with reserved JS keywords.
@@ -1726,56 +1517,30 @@
     return name;
   }
 
+  @override
   jsAst.Name substitutionName(ClassEntity element) {
-    return new CompoundName(
-        [new StringBackedName(operatorAsPrefix), runtimeTypeName(element)]);
+    return new CompoundName([
+      new StringBackedName(fixedNames.operatorAsPrefix),
+      runtimeTypeName(element)
+    ]);
   }
 
-  /// Translates a [String] into the corresponding [Name] data structure as
-  /// used by the namer.
-  ///
-  /// If [name] is a setter or getter name, the corresponding [GetterName] or
-  /// [SetterName] data structure is used.
+  @override
   jsAst.Name asName(String name) {
-    if (name.startsWith(getterPrefix) && name.length > getterPrefix.length) {
+    if (name.startsWith(fixedNames.getterPrefix) &&
+        name.length > fixedNames.getterPrefix.length) {
       return new GetterName(_literalGetterPrefix,
-          new StringBackedName(name.substring(getterPrefix.length)));
+          new StringBackedName(name.substring(fixedNames.getterPrefix.length)));
     }
-    if (name.startsWith(setterPrefix) && name.length > setterPrefix.length) {
+    if (name.startsWith(fixedNames.setterPrefix) &&
+        name.length > fixedNames.setterPrefix.length) {
       return new GetterName(_literalSetterPrefix,
-          new StringBackedName(name.substring(setterPrefix.length)));
+          new StringBackedName(name.substring(fixedNames.setterPrefix.length)));
     }
 
     return new StringBackedName(name);
   }
 
-  /// Returns a variable name that cannot clash with a keyword, a global
-  /// variable, or any name starting with a single '$'.
-  ///
-  /// Furthermore, this function is injective, that is, it never returns the
-  /// same name for two different inputs.
-  String safeVariableName(String name) {
-    name = name.replaceAll('#', '_');
-    if (jsVariableReserved.contains(name) || name.startsWith(r'$')) {
-      return '\$$name';
-    }
-    return name;
-  }
-
-  /// Returns a safe variable name for use in async rewriting.
-  ///
-  /// Has the same property as [safeVariableName] but does not clash with
-  /// names returned from there.
-  /// Additionally, when used as a prefix to a variable name, the result
-  /// will be safe to use, as well.
-  String safeVariablePrefixForAsyncRewrite(String name) {
-    return "$asyncPrefix$name";
-  }
-
-  jsAst.Name deriveAsyncBodyName(jsAst.Name original) {
-    return new _AsyncName(_literalAsyncPrefix, original);
-  }
-
   String operatorNameToIdentifier(String name) {
     if (name == null) return null;
     if (name == '==') {
@@ -1822,6 +1587,64 @@
       return name;
     }
   }
+
+  String getTypeRepresentationForTypeConstant(DartType type) {
+    if (type.isDynamic) return "dynamic";
+    if (type is TypedefType) {
+      return uniqueNameForTypeConstantElement(
+          type.element.library, type.element);
+    }
+    if (type is FunctionType) {
+      // TODO(johnniwinther): Add naming scheme for function type literals.
+      // These currently only occur from kernel.
+      return '()->';
+    }
+    InterfaceType interface = type;
+    String name = uniqueNameForTypeConstantElement(
+        interface.element.library, interface.element);
+
+    // Type constants can currently only be raw types, so there is no point
+    // adding ground-term type parameters, as they would just be 'dynamic'.
+    // TODO(sra): Since the result string is used only in constructing constant
+    // names, it would result in more readable names if the final string was a
+    // legal JavaScript identifier.
+    if (interface.typeArguments.isEmpty) return name;
+    String arguments =
+        new List.filled(interface.typeArguments.length, 'dynamic').join(', ');
+    return '$name<$arguments>';
+  }
+}
+
+/// Returns a unique suffix for an intercepted accesses to [classes]. This is
+/// used as the suffix for emitted interceptor methods and as the unique key
+/// used to distinguish equivalences of sets of intercepted classes.
+String suffixForGetInterceptor(CommonElements commonElements,
+    NativeData nativeData, Iterable<ClassEntity> classes) {
+  String abbreviate(ClassEntity cls) {
+    if (cls == commonElements.objectClass) return "o";
+    if (cls == commonElements.jsStringClass) return "s";
+    if (cls == commonElements.jsArrayClass) return "a";
+    if (cls == commonElements.jsDoubleClass) return "d";
+    if (cls == commonElements.jsIntClass) return "i";
+    if (cls == commonElements.jsNumberClass) return "n";
+    if (cls == commonElements.jsNullClass) return "u";
+    if (cls == commonElements.jsBoolClass) return "b";
+    if (cls == commonElements.jsInterceptorClass) return "I";
+    return cls.name;
+  }
+
+  List<String> names = classes
+      .where((cls) => !nativeData.isNativeOrExtendsNative(cls))
+      .map(abbreviate)
+      .toList();
+  // There is one dispatch mechanism for all native classes.
+  if (classes.any((cls) => nativeData.isNativeOrExtendsNative(cls))) {
+    names.add("x");
+  }
+  // Sort the names of the classes after abbreviating them to ensure
+  // the suffix is stable and predictable for the suggested names.
+  names.sort();
+  return names.join();
 }
 
 /// Generator of names for [ConstantValue] values.
@@ -1843,16 +1666,20 @@
   static const MAX_EXTRA_LENGTH = 30;
   static const DEFAULT_TAG_LENGTH = 3;
 
-  final RuntimeTypesEncoder rtiEncoder;
-  final CodegenWorldBuilder codegenWorldBuilder;
-  final ConstantCanonicalHasher hasher;
+  final Namer _namer;
+  final JClosedWorld _closedWorld;
+  final ConstantCanonicalHasher _hasher;
 
   String root = null; // First word, usually a type name.
   bool failed = false; // Failed to generate something pretty.
   List<String> fragments = <String>[];
   int length = 0;
 
-  ConstantNamingVisitor(this.rtiEncoder, this.codegenWorldBuilder, this.hasher);
+  ConstantNamingVisitor(this._namer, this._closedWorld, this._hasher);
+
+  JElementEnvironment get _elementEnvironment =>
+      _closedWorld.elementEnvironment;
+  JFieldAnalysis get _fieldAnalysis => _closedWorld.fieldAnalysis;
 
   String getName(ConstantValue constant) {
     _visit(constant);
@@ -1863,7 +1690,7 @@
   }
 
   String getHashTag(ConstantValue constant, int width) =>
-      hashWord(hasher.getHash(constant), width);
+      hashWord(_hasher.getHash(constant), width);
 
   String hashWord(int hash, int length) {
     hash &= 0x1fffffff;
@@ -2021,10 +1848,10 @@
     }
 
     // TODO(johnniwinther): This should be accessed from a codegen closed world.
-    codegenWorldBuilder.forEachInstanceField(constant.type.element,
-        (_, FieldEntity field, {bool isElided}) {
+    _elementEnvironment.forEachInstanceField(constant.type.element,
+        (_, FieldEntity field) {
       if (failed) return;
-      if (isElided) return;
+      if (_fieldAnalysis.getFieldData(field).isElided) return;
       _visit(constant.fields[field]);
     });
   }
@@ -2043,7 +1870,7 @@
     }
     if (name == null) {
       // e.g. DartType 'dynamic' has no element.
-      name = rtiEncoder.getTypeRepresentationForTypeConstant(type);
+      name = _namer.getTypeRepresentationForTypeConstant(type);
     }
     addIdentifier(name);
     add(getHashTag(constant, 3));
@@ -2057,21 +1884,18 @@
   }
 
   @override
-  void visitSynthetic(SyntheticConstantValue constant, [_]) {
-    switch (constant.valueKind) {
-      case SyntheticConstantKind.DUMMY_INTERCEPTOR:
-        add('dummy_receiver');
-        break;
-      case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
-        // Omit. These are opaque deferred indexes with nothing helpful to add.
-        break;
-      case SyntheticConstantKind.NAME:
-        add('name');
-        break;
-      default:
-        failedAt(
-            CURRENT_ELEMENT_SPANNABLE, "Unexpected SyntheticConstantValue");
-    }
+  void visitDummyInterceptor(DummyInterceptorConstantValue constant, [_]) {
+    add('dummy_interceptor');
+  }
+
+  @override
+  void visitUnreachable(UnreachableConstantValue constant, [_]) {
+    add('unreachable');
+  }
+
+  @override
+  void visitJsName(JsNameConstantValue constant, [_]) {
+    add('name');
   }
 
   @override
@@ -2090,19 +1914,23 @@
   static const _MASK = 0x1fffffff;
   static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024;
 
-  final RuntimeTypesEncoder rtiEncoder;
-  final CodegenWorldBuilder codegenWorldBuilder;
-  final Map<ConstantValue, int> hashes = {};
+  final Namer _namer;
+  final JClosedWorld _closedWorld;
+  final Map<ConstantValue, int> _hashes = {};
 
-  ConstantCanonicalHasher(this.rtiEncoder, this.codegenWorldBuilder);
+  ConstantCanonicalHasher(this._namer, this._closedWorld);
+
+  JElementEnvironment get _elementEnvironment =>
+      _closedWorld.elementEnvironment;
+  JFieldAnalysis get _fieldAnalysis => _closedWorld.fieldAnalysis;
 
   int getHash(ConstantValue constant) => _visit(constant);
 
   int _visit(ConstantValue constant) {
-    int hash = hashes[constant];
+    int hash = _hashes[constant];
     if (hash == null) {
       hash = _finish(constant.accept(this, null));
-      hashes[constant] = hash;
+      _hashes[constant] = hash;
     }
     return hash;
   }
@@ -2166,9 +1994,9 @@
   @override
   int visitConstructed(ConstructedConstantValue constant, [_]) {
     int hash = _hashString(3, constant.type.element.name);
-    codegenWorldBuilder.forEachInstanceField(constant.type.element,
-        (_, FieldEntity field, {bool isElided}) {
-      if (isElided) return;
+    _elementEnvironment.forEachInstanceField(constant.type.element,
+        (_, FieldEntity field) {
+      if (_fieldAnalysis.getFieldData(field).isElided) return;
       hash = _combine(hash, _visit(constant.fields[field]));
     });
     return hash;
@@ -2178,7 +2006,7 @@
   int visitType(TypeConstantValue constant, [_]) {
     DartType type = constant.representedType;
     // This name includes the library name and type parameters.
-    String name = rtiEncoder.getTypeRepresentationForTypeConstant(type);
+    String name = _namer.getTypeRepresentationForTypeConstant(type);
     return _hashString(4, name);
   }
 
@@ -2189,19 +2017,27 @@
   }
 
   @override
-  int visitSynthetic(SyntheticConstantValue constant, [_]) {
-    switch (constant.valueKind) {
-      case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
-        // These contain a deferred opaque index into metadata. There is nothing
-        // we can access that is stable between compiles.  Luckily, since they
-        // resolve to integer indexes, they're always part of a larger constant.
-        return 0;
-      default:
-        throw failedAt(
-            NO_LOCATION_SPANNABLE,
-            'SyntheticConstantValue should never be named and '
-            'never be subconstant');
-    }
+  int visitDummyInterceptor(DummyInterceptorConstantValue constant, [_]) {
+    throw failedAt(
+        NO_LOCATION_SPANNABLE,
+        'DummyInterceptorConstantValue should never be named and '
+        'never be subconstant');
+  }
+
+  @override
+  int visitUnreachable(UnreachableConstantValue constant, [_]) {
+    throw failedAt(
+        NO_LOCATION_SPANNABLE,
+        'UnreachableConstantValue should never be named and '
+        'never be subconstant');
+  }
+
+  @override
+  int visitJsName(JsNameConstantValue constant, [_]) {
+    throw failedAt(
+        NO_LOCATION_SPANNABLE,
+        'JsNameConstantValue should never be named and '
+        'never be subconstant');
   }
 
   @override
@@ -2280,10 +2116,9 @@
 }
 
 class FunctionTypeNamer extends BaseDartTypeVisitor {
-  final RuntimeTypesEncoder rtiEncoder;
   StringBuffer sb;
 
-  FunctionTypeNamer(this.rtiEncoder);
+  FunctionTypeNamer();
 
   String computeName(DartType type) {
     sb = new StringBuffer();
@@ -2314,9 +2149,19 @@
     sb.write(type.element.name);
   }
 
+  bool _isSimpleFunctionType(FunctionType type) {
+    if (!type.returnType.isDynamic) return false;
+    if (!type.optionalParameterTypes.isEmpty) return false;
+    if (!type.namedParameterTypes.isEmpty) return false;
+    for (DartType parameter in type.parameterTypes) {
+      if (!parameter.isDynamic) return false;
+    }
+    return true;
+  }
+
   @override
   visitFunctionType(FunctionType type, _) {
-    if (rtiEncoder.isSimpleFunctionType(type)) {
+    if (_isSimpleFunctionType(type)) {
       sb.write('args${type.parameterTypes.length}');
       return;
     }
@@ -2375,3 +2220,555 @@
     return _suggestedNames.containsValue(candidate);
   }
 }
+
+/// Fixed names usage by the namer.
+class FixedNames {
+  const FixedNames();
+
+  String get getterPrefix => r'get$';
+  String get setterPrefix => r'set$';
+  String get callPrefix => 'call';
+  String get callCatchAllName => r'call*';
+  String get callNameField => r'$callName';
+  String get reflectableField => r'$reflectable';
+  String get classDescriptorProperty => r'^';
+  String get defaultValuesField => r'$defaultValues';
+  String get deferredAction => r'$deferredAction';
+  String get operatorIsPrefix => r'$is';
+  String get operatorAsPrefix => r'$as';
+  String get operatorSignature => r'$signature';
+  String get requiredParameterField => r'$requiredArgCount';
+  String get rtiName => r'$ti';
+}
+
+/// Minified version of the fixed names usage by the namer.
+// TODO(johnniwinther): This should implement [FixedNames] and minify all fixed
+// names.
+class MinifiedFixedNames extends FixedNames {
+  const MinifiedFixedNames();
+
+  @override
+  String get getterPrefix => 'g';
+  @override
+  String get setterPrefix => 's';
+  @override
+  String get callPrefix => ''; // this will create function names $<n>
+  @override
+  String get operatorIsPrefix => r'$i';
+  @override
+  String get operatorAsPrefix => r'$a';
+  @override
+  String get callCatchAllName => r'$C';
+  @override
+  String get requiredParameterField => r'$R';
+  @override
+  String get defaultValuesField => r'$D';
+  @override
+  String get operatorSignature => r'$S';
+}
+
+/// Namer interface that can be used in modular code generation.
+abstract class ModularNamer {
+  FixedNames get fixedNames;
+  RuntimeTypeTags get rtiTags;
+
+  /// Returns a variable use for accessing [library].
+  ///
+  /// This is one of the [reservedGlobalObjectNames]
+  jsAst.Expression readGlobalObjectForLibrary(LibraryEntity library);
+
+  /// Returns a variable use for accessing the class [element].
+  ///
+  /// This is one of the [reservedGlobalObjectNames]
+  jsAst.Expression readGlobalObjectForClass(ClassEntity element);
+
+  /// Returns a variable use for accessing the type [element].
+  ///
+  /// This is one of the [reservedGlobalObjectNames]
+  jsAst.Expression readGlobalObjectForType(Entity element);
+
+  /// Returns a variable use for accessing the member [element].
+  ///
+  /// This is either the [staticStateHolder] or one of the
+  /// [reservedGlobalObjectNames]
+  jsAst.Expression readGlobalObjectForMember(MemberEntity element);
+
+  /// Returns a JavaScript property name used to store the class [element] on
+  /// one of the global objects.
+  ///
+  /// Should be used together with [globalObjectForClass], which denotes the
+  /// object on which the returned property name should be used.
+  jsAst.Name globalPropertyNameForClass(ClassEntity element);
+
+  /// Returns a JavaScript property name used to store the member [element] on
+  /// one of the global objects.
+  ///
+  /// Should be used together with [globalObjectForMember], which denotes the
+  /// object on which the returned property name should be used.
+  jsAst.Name globalPropertyNameForMember(MemberEntity element);
+
+  /// Returns a JavaScript property name used to store the type (typedef)
+  /// [element] on one of the global objects.
+  ///
+  /// Should be used together with [globalObjectForType], which denotes the
+  /// object on which the returned property name should be used.
+  jsAst.Name globalPropertyNameForType(Entity element);
+
+  /// Returns the name for the instance field that holds runtime type arguments
+  /// on generic classes.
+  jsAst.Name get rtiFieldJsName;
+
+  /// Property name on which [member] can be accessed directly,
+  /// without clashing with another JS property name.
+  ///
+  /// This is used for implementing super-calls, where ordinary dispatch
+  /// semantics must be circumvented. For example:
+  ///
+  ///     class A { foo() }
+  ///     class B extends A {
+  ///         foo() { super.foo() }
+  ///     }
+  ///
+  /// Example translation to JS:
+  ///
+  ///     A.prototype.super$A$foo = function() {...}
+  ///     A.prototype.foo$0 = A.prototype.super$A$foo
+  ///
+  ///     B.prototype.foo$0 = function() {
+  ///         this.super$A$foo(); // super.foo()
+  ///     }
+  ///
+  jsAst.Name aliasedSuperMemberPropertyName(MemberEntity member);
+
+  /// Returns the JavaScript property name used to store an instance field.
+  jsAst.Name instanceFieldPropertyName(FieldEntity element);
+
+  /// Annotated name for [method] encoding arity and named parameters.
+  jsAst.Name instanceMethodName(FunctionEntity method);
+
+  /// Translates a [String] into the corresponding [Name] data structure as
+  /// used by the namer.
+  ///
+  /// If [name] is a setter or getter name, the corresponding [GetterName] or
+  /// [SetterName] data structure is used.
+  jsAst.Name asName(String name);
+
+  /// Annotated name for the member being invoked by [selector].
+  jsAst.Name invocationName(Selector selector);
+
+  /// Property name used for a specialization of `getInterceptor`.
+  ///
+  /// js_runtime contains a top-level `getInterceptor` method. The
+  /// specializations have the same name, but with a suffix to avoid name
+  /// collisions.
+  jsAst.Name nameForGetInterceptor(Set<ClassEntity> classes);
+
+  /// Property name used for the one-shot interceptor method for the given
+  /// [selector] and return-type specialization.
+  jsAst.Name nameForOneShotInterceptor(
+      Selector selector, Set<ClassEntity> classes);
+
+  /// Returns the runtime name for [element].
+  ///
+  /// This name is used as the basis for deriving `is` and `as` property names
+  /// for the given type.
+  ///
+  /// The result is not always safe as a property name unless prefixing
+  /// [operatorIsPrefix] or [operatorAsPrefix]. If this is a function type,
+  /// then by convention, an underscore must also separate [operatorIsPrefix]
+  /// from the type name.
+  jsAst.Name runtimeTypeName(Entity element);
+
+  /// Property name in which to store the given static or instance [method].
+  /// For instance methods, this includes the suffix encoding arity and named
+  /// parameters.
+  ///
+  /// The name is not necessarily unique to [method], since a static method
+  /// may share its name with an instance method.
+  jsAst.Name methodPropertyName(FunctionEntity method);
+
+  /// Returns the name of the `isX` property for classes that implement
+  /// [element].
+  jsAst.Name operatorIs(ClassEntity element);
+
+  /// Return the name of the `isX` property for classes that implement [type].
+  jsAst.Name operatorIsType(DartType type);
+
+  /// Returns the name of the `asX` function for classes that implement the
+  /// generic class [element].
+  jsAst.Name substitutionName(ClassEntity element);
+
+  /// Returns the name of the lazy initializer for the static field [element].
+  jsAst.Name lazyInitializerName(FieldEntity element);
+
+  /// Returns the name of the closure of the static method [element].
+  jsAst.Name staticClosureName(FunctionEntity element);
+
+  /// Returns the disambiguated name of [class_].
+  ///
+  /// This is both the *runtime type* of the class (see [runtimeTypeName])
+  /// and a global property name in which to store its JS constructor.
+  jsAst.Name className(ClassEntity class_);
+
+  /// The prefix used for encoding async properties.
+  final String asyncPrefix = r"$async$";
+
+  /// Returns the name for the holder of static state.
+  ///
+  /// This is used for mutable static fields.
+  final String staticStateHolder = r'$';
+
+  jsAst.Name _literalAsyncPrefix;
+
+  ModularNamer() {
+    _literalAsyncPrefix = new StringBackedName(asyncPrefix);
+  }
+
+  /// Returns a safe variable name for use in async rewriting.
+  ///
+  /// Has the same property as [safeVariableName] but does not clash with
+  /// names returned from there.
+  /// Additionally, when used as a prefix to a variable name, the result
+  /// will be safe to use, as well.
+  String safeVariablePrefixForAsyncRewrite(String name) {
+    return "$asyncPrefix$name";
+  }
+
+  /// Returns the name for the async body of the method with the [original]
+  /// name.
+  jsAst.Name deriveAsyncBodyName(jsAst.Name original) {
+    return new AsyncName(_literalAsyncPrefix, original);
+  }
+
+  /// Returns the label name for [label] used as a break target.
+  String breakLabelName(LabelDefinition label) {
+    return '\$${label.labelName}\$${label.target.nestingLevel}';
+  }
+
+  /// Returns the label name for the implicit break label needed for the jump
+  /// [target].
+  String implicitBreakLabelName(JumpTarget target) {
+    return '\$${target.nestingLevel}';
+  }
+
+  /// Returns the label name for [label] used as a continue target.
+  ///
+  /// We sometimes handle continue targets differently from break targets,
+  /// so we have special continue-only labels.
+  String continueLabelName(LabelDefinition label) {
+    return 'c\$${label.labelName}\$${label.target.nestingLevel}';
+  }
+
+  /// Returns the label name for the implicit continue label needed for the jump
+  /// [target].
+  String implicitContinueLabelName(JumpTarget target) {
+    return 'c\$${target.nestingLevel}';
+  }
+
+  Set<String> _jsVariableReservedCache = null;
+
+  /// Names that cannot be used by local variables and parameters.
+  Set<String> get _jsVariableReserved {
+    if (_jsVariableReservedCache == null) {
+      _jsVariableReservedCache = new Set<String>();
+      _jsVariableReservedCache.addAll(Namer.javaScriptKeywords);
+      _jsVariableReservedCache.addAll(Namer.reservedPropertySymbols);
+      _jsVariableReservedCache.addAll(Namer.reservedGlobalSymbols);
+      _jsVariableReservedCache.addAll(Namer.reservedGlobalObjectNames);
+      // 26 letters in the alphabet, 25 not counting I.
+      assert(Namer.reservedGlobalObjectNames.length == 25);
+      _jsVariableReservedCache.addAll(Namer.reservedGlobalHelperFunctions);
+    }
+    return _jsVariableReservedCache;
+  }
+
+  /// Returns a variable name that cannot clash with a keyword, a global
+  /// variable, or any name starting with a single '$'.
+  ///
+  /// Furthermore, this function is injective, that is, it never returns the
+  /// same name for two different inputs.
+  String safeVariableName(String name) {
+    name = name.replaceAll('#', '_');
+    if (_jsVariableReserved.contains(name) || name.startsWith(r'$')) {
+      return '\$$name';
+    }
+    return name;
+  }
+
+  CommonElements get _commonElements;
+
+  /// Returns the string that is to be used as the result of a call to
+  /// [JS_GET_NAME] at [node] with argument [name].
+  jsAst.Name getNameForJsGetName(Spannable spannable, JsGetName name) {
+    switch (name) {
+      case JsGetName.GETTER_PREFIX:
+        return asName(fixedNames.getterPrefix);
+      case JsGetName.SETTER_PREFIX:
+        return asName(fixedNames.setterPrefix);
+      case JsGetName.CALL_PREFIX:
+        return asName(fixedNames.callPrefix);
+      case JsGetName.CALL_PREFIX0:
+        return asName('${fixedNames.callPrefix}\$0');
+      case JsGetName.CALL_PREFIX1:
+        return asName('${fixedNames.callPrefix}\$1');
+      case JsGetName.CALL_PREFIX2:
+        return asName('${fixedNames.callPrefix}\$2');
+      case JsGetName.CALL_PREFIX3:
+        return asName('${fixedNames.callPrefix}\$3');
+      case JsGetName.CALL_PREFIX4:
+        return asName('${fixedNames.callPrefix}\$4');
+      case JsGetName.CALL_PREFIX5:
+        return asName('${fixedNames.callPrefix}\$5');
+      case JsGetName.CALL_CATCH_ALL:
+        return asName(fixedNames.callCatchAllName);
+      case JsGetName.REFLECTABLE:
+        return asName(fixedNames.reflectableField);
+      case JsGetName.CLASS_DESCRIPTOR_PROPERTY:
+        return asName(fixedNames.classDescriptorProperty);
+      case JsGetName.REQUIRED_PARAMETER_PROPERTY:
+        return asName(fixedNames.requiredParameterField);
+      case JsGetName.DEFAULT_VALUES_PROPERTY:
+        return asName(fixedNames.defaultValuesField);
+      case JsGetName.CALL_NAME_PROPERTY:
+        return asName(fixedNames.callNameField);
+      case JsGetName.DEFERRED_ACTION_PROPERTY:
+        return asName(fixedNames.deferredAction);
+      case JsGetName.OPERATOR_AS_PREFIX:
+        return asName(fixedNames.operatorAsPrefix);
+      case JsGetName.SIGNATURE_NAME:
+        return asName(fixedNames.operatorSignature);
+      case JsGetName.RTI_NAME:
+        return asName(fixedNames.rtiName);
+      case JsGetName.TYPEDEF_TAG:
+        return asName(rtiTags.typedefTag);
+      case JsGetName.FUNCTION_TYPE_TAG:
+        return asName(rtiTags.functionTypeTag);
+      case JsGetName.FUNCTION_TYPE_GENERIC_BOUNDS_TAG:
+        return asName(rtiTags.functionTypeGenericBoundsTag);
+      case JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG:
+        return asName(rtiTags.functionTypeVoidReturnTag);
+      case JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG:
+        return asName(rtiTags.functionTypeReturnTypeTag);
+      case JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG:
+        return asName(rtiTags.functionTypeRequiredParametersTag);
+      case JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG:
+        return asName(rtiTags.functionTypeOptionalParametersTag);
+      case JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG:
+        return asName(rtiTags.functionTypeNamedParametersTag);
+      case JsGetName.FUTURE_OR_TAG:
+        return asName(rtiTags.futureOrTag);
+      case JsGetName.FUTURE_OR_TYPE_ARGUMENT_TAG:
+        return asName(rtiTags.futureOrTypeTag);
+      case JsGetName.IS_INDEXABLE_FIELD_NAME:
+        return operatorIs(_commonElements.jsIndexingBehaviorInterface);
+      case JsGetName.NULL_CLASS_TYPE_NAME:
+        return runtimeTypeName(_commonElements.nullClass);
+      case JsGetName.OBJECT_CLASS_TYPE_NAME:
+        return runtimeTypeName(_commonElements.objectClass);
+      case JsGetName.FUNCTION_CLASS_TYPE_NAME:
+        return runtimeTypeName(_commonElements.functionClass);
+      case JsGetName.FUTURE_CLASS_TYPE_NAME:
+        return runtimeTypeName(_commonElements.futureClass);
+      default:
+        throw failedAt(spannable, 'Error: Namer has no name for "$name".');
+    }
+  }
+}
+
+class ModularNamerImpl extends ModularNamer {
+  final CodegenRegistry _registry;
+  @override
+  final RuntimeTypeTags rtiTags;
+  @override
+  final FixedNames fixedNames;
+
+  @override
+  final CommonElements _commonElements;
+
+  ModularNamerImpl(
+      this._registry, this._commonElements, this.rtiTags, this.fixedNames);
+
+  @override
+  jsAst.Name get rtiFieldJsName {
+    jsAst.Name name = new ModularName(ModularNameKind.rtiField);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name runtimeTypeName(Entity element) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.runtimeTypeName, data: element);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name className(ClassEntity element) {
+    jsAst.Name name = new ModularName(ModularNameKind.className, data: element);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Expression readGlobalObjectForLibrary(LibraryEntity library) {
+    jsAst.Expression expression = new ModularExpression(
+        ModularExpressionKind.globalObjectForLibrary, library);
+    _registry.registerModularExpression(expression);
+    return expression;
+  }
+
+  @override
+  jsAst.Expression readGlobalObjectForClass(ClassEntity element) {
+    jsAst.Expression expression = new ModularExpression(
+        ModularExpressionKind.globalObjectForClass, element);
+    _registry.registerModularExpression(expression);
+    return expression;
+  }
+
+  @override
+  jsAst.Expression readGlobalObjectForType(Entity element) {
+    jsAst.Expression expression = new ModularExpression(
+        ModularExpressionKind.globalObjectForType, element);
+    _registry.registerModularExpression(expression);
+    return expression;
+  }
+
+  @override
+  jsAst.Expression readGlobalObjectForMember(MemberEntity element) {
+    jsAst.Expression expression = new ModularExpression(
+        ModularExpressionKind.globalObjectForMember, element);
+    _registry.registerModularExpression(expression);
+    return expression;
+  }
+
+  @override
+  jsAst.Name aliasedSuperMemberPropertyName(MemberEntity member) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.aliasedSuperMember, data: member);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name staticClosureName(FunctionEntity element) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.staticClosure, data: element);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name methodPropertyName(FunctionEntity method) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.methodProperty, data: method);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name instanceFieldPropertyName(FieldEntity element) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.instanceField, data: element);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name operatorIsType(DartType type) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.operatorIsType, data: type);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name instanceMethodName(FunctionEntity method) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.instanceMethod, data: method);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name invocationName(Selector selector) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.invocation, data: selector);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name lazyInitializerName(FieldEntity element) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.lazyInitializer, data: element);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name operatorIs(ClassEntity element) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.operatorIs, data: element);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name globalPropertyNameForType(Entity element) {
+    jsAst.Name name = new ModularName(ModularNameKind.globalPropertyNameForType,
+        data: element);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name globalPropertyNameForClass(ClassEntity element) {
+    jsAst.Name name = new ModularName(
+        ModularNameKind.globalPropertyNameForClass,
+        data: element);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name globalPropertyNameForMember(MemberEntity element) {
+    jsAst.Name name = new ModularName(
+        ModularNameKind.globalPropertyNameForMember,
+        data: element);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name nameForGetInterceptor(Set<ClassEntity> classes) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.nameForGetInterceptor, set: classes);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name nameForOneShotInterceptor(
+      Selector selector, Set<ClassEntity> classes) {
+    jsAst.Name name = new ModularName(ModularNameKind.nameForOneShotInterceptor,
+        data: selector, set: classes);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name asName(String text) {
+    jsAst.Name name = new ModularName(ModularNameKind.asName, data: text);
+    _registry.registerModularName(name);
+    return name;
+  }
+
+  @override
+  jsAst.Name substitutionName(ClassEntity element) {
+    jsAst.Name name =
+        new ModularName(ModularNameKind.substitution, data: element);
+    _registry.registerModularName(name);
+    return name;
+  }
+}
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index db0819d..f405dc0 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -4,7 +4,6 @@
 
 part of js_backend.namer;
 
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 abstract class _NamerName extends jsAst.Name {
   int get _kind;
   _NamerName get _target => this;
@@ -20,7 +19,6 @@
 
 enum _NamerNameKinds { StringBacked, Getter, Setter, Async, Compound, Token }
 
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class StringBackedName extends _NamerName {
   @override
   final String name;
@@ -43,14 +41,19 @@
   int get hashCode => name.hashCode;
 
   @override
-  int compareTo(covariant _NamerName other) {
-    other = other._target;
-    if (other._kind != _kind) return other._kind - _kind;
-    return name.compareTo(other.name);
+  int compareTo(jsAst.Name other) {
+    _NamerName otherNamerName;
+    if (other is ModularName) {
+      otherNamerName = other.value;
+    } else {
+      otherNamerName = other;
+    }
+    otherNamerName = otherNamerName._target;
+    if (otherNamerName._kind != _kind) return otherNamerName._kind - _kind;
+    return name.compareTo(otherNamerName.name);
   }
 }
 
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 abstract class _PrefixedName extends _NamerName implements jsAst.AstContainer {
   final jsAst.Name prefix;
   final jsAst.Name base;
@@ -80,10 +83,16 @@
   int get hashCode => base.hashCode * 13 + prefix.hashCode;
 
   @override
-  int compareTo(covariant _NamerName other) {
-    other = other._target;
-    if (other._kind != _kind) return other._kind - _kind;
-    _PrefixedName otherSameKind = other;
+  int compareTo(jsAst.Name other) {
+    _NamerName otherNamerName;
+    if (other is ModularName) {
+      otherNamerName = other.value;
+    } else {
+      otherNamerName = other;
+    }
+    otherNamerName = otherNamerName._target;
+    if (otherNamerName._kind != _kind) return otherNamerName._kind - _kind;
+    _PrefixedName otherSameKind = otherNamerName;
     int result = prefix.compareTo(otherSameKind.prefix);
     if (result == 0) {
       result = prefix.compareTo(otherSameKind.prefix);
@@ -95,7 +104,6 @@
   }
 }
 
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class GetterName extends _PrefixedName {
   @override
   int get _kind => _NamerNameKinds.Getter.index;
@@ -103,7 +111,6 @@
   GetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
 }
 
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class SetterName extends _PrefixedName {
   @override
   int get _kind => _NamerNameKinds.Setter.index;
@@ -111,18 +118,16 @@
   SetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
 }
 
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
-class _AsyncName extends _PrefixedName {
+class AsyncName extends _PrefixedName {
   @override
   int get _kind => _NamerNameKinds.Async.index;
 
-  _AsyncName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
+  AsyncName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
 
   @override
   bool get allowRename => true;
 }
 
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class CompoundName extends _NamerName implements jsAst.AstContainer {
   final List<_NamerName> _parts;
   @override
@@ -170,10 +175,16 @@
   }
 
   @override
-  int compareTo(covariant _NamerName other) {
-    other = other._target;
-    if (other._kind != _kind) return other._kind - _kind;
-    CompoundName otherSameKind = other;
+  int compareTo(jsAst.Name other) {
+    _NamerName otherNamerName;
+    if (other is ModularName) {
+      otherNamerName = other.value;
+    } else {
+      otherNamerName = other;
+    }
+    otherNamerName = otherNamerName._target;
+    if (otherNamerName._kind != _kind) return otherNamerName._kind - _kind;
+    CompoundName otherSameKind = otherNamerName;
     if (otherSameKind._parts.length != _parts.length) {
       return otherSameKind._parts.length - _parts.length;
     }
@@ -185,7 +196,6 @@
   }
 }
 
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class TokenName extends _NamerName implements jsAst.ReferenceCountedAstNode {
   @override
   int get _kind => _NamerNameKinds.Token.index;
@@ -201,7 +211,7 @@
 
   @override
   String get name {
-    assert(isFinalized);
+    assert(isFinalized, "TokenName($key) has not been finalized.");
     return _name;
   }
 
@@ -214,7 +224,7 @@
   }
 
   @override
-  markSeen(jsAst.TokenCounter counter) => _rc++;
+  void markSeen(jsAst.TokenCounter counter) => _rc++;
 
   @override
   bool operator ==(other) {
@@ -226,7 +236,7 @@
   @override
   int get hashCode => super.hashCode;
 
-  finalize() {
+  void finalize() {
     assert(
         !isFinalized,
         failedAt(NO_LOCATION_SPANNABLE,
@@ -235,7 +245,6 @@
   }
 }
 
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class _NameReference extends _NamerName implements jsAst.AstContainer {
   @override
   _NamerName _target;
@@ -254,7 +263,15 @@
   String get name => _target.name;
 
   @override
-  int compareTo(covariant _NamerName other) => _target.compareTo(other);
+  int compareTo(jsAst.Name other) {
+    _NamerName otherNamerName;
+    if (other is ModularName) {
+      otherNamerName = other.value;
+    } else {
+      otherNamerName = other;
+    }
+    return _target.compareTo(otherNamerName);
+  }
 
   @override
   bool operator ==(other) => _target == other;
diff --git a/pkg/compiler/lib/src/js_backend/resolution_listener.dart b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
index e084b4c..04381e4 100644
--- a/pkg/compiler/lib/src/js_backend/resolution_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
@@ -121,8 +121,12 @@
       mainImpact.registerStaticUse(
           new StaticUse.staticInvoke(mainMethod, callStructure));
     }
-    mainImpact.registerStaticUse(
-        new StaticUse.staticInvoke(mainMethod, CallStructure.NO_ARGS));
+    if (mainMethod.isGetter) {
+      mainImpact.registerStaticUse(new StaticUse.staticGet(mainMethod));
+    } else {
+      mainImpact.registerStaticUse(
+          new StaticUse.staticInvoke(mainMethod, CallStructure.NO_ARGS));
+    }
     return mainImpact;
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 5094315..fa7a7d1 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -18,16 +18,15 @@
 import '../ir/runtime_type_analysis.dart';
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
-import '../js_emitter/js_emitter.dart' show Emitter;
+import '../js_emitter/js_emitter.dart' show ModularEmitter;
 import '../options.dart';
 import '../serialization/serialization.dart';
 import '../universe/class_hierarchy.dart';
+import '../universe/class_set.dart';
 import '../universe/codegen_world_builder.dart';
 import '../universe/feature.dart';
-import '../universe/resolution_world_builder.dart';
 import '../universe/selector.dart';
-import '../universe/world_builder.dart';
-import '../world.dart' show JClosedWorld, KClosedWorld;
+import '../world.dart';
 import 'backend_usage.dart';
 import 'namer.dart';
 import 'native_data.dart';
@@ -168,9 +167,7 @@
 
   /// Computes the [RuntimeTypesNeed] for the data registered with this builder.
   RuntimeTypesNeed computeRuntimeTypesNeed(
-      ResolutionWorldBuilder resolutionWorldBuilder,
-      KClosedWorld closedWorld,
-      CompilerOptions options);
+      KClosedWorld closedWorld, CompilerOptions options);
 }
 
 class TrivialRuntimeTypesNeedBuilder implements RuntimeTypesNeedBuilder {
@@ -190,9 +187,7 @@
 
   @override
   RuntimeTypesNeed computeRuntimeTypesNeed(
-      ResolutionWorldBuilder resolutionWorldBuilder,
-      KClosedWorld closedWorld,
-      CompilerOptions options) {
+      KClosedWorld closedWorld, CompilerOptions options) {
     return const TrivialRuntimeTypesNeed();
   }
 }
@@ -237,7 +232,7 @@
 
   /// Computes the [RuntimeTypesChecks] for the data in this builder.
   RuntimeTypesChecks computeRequiredChecks(
-      CodegenWorldBuilder codegenWorldBuilder, CompilerOptions options);
+      CodegenWorld codegenWorld, CompilerOptions options);
 
   bool get rtiChecksBuilderClosed;
 }
@@ -261,7 +256,7 @@
 
   @override
   RuntimeTypesChecks computeRequiredChecks(
-      CodegenWorldBuilder codegenWorldBuilder, CompilerOptions options) {
+      CodegenWorld codegenWorld, CompilerOptions options) {
     rtiChecksBuilderClosed = true;
 
     Map<ClassEntity, ClassUse> classUseMap = <ClassEntity, ClassUse>{};
@@ -662,15 +657,8 @@
 }
 
 abstract class RuntimeTypesEncoder {
-  bool isSimpleFunctionType(FunctionType type);
-
-  jsAst.Expression getSignatureEncoding(
-      Emitter emitter, DartType type, jsAst.Expression this_);
-
-  jsAst.Expression getSubstitutionRepresentation(
-      Emitter emitter, List<DartType> types, OnVariableCallback onVariable);
-  jsAst.Expression getSubstitutionCode(
-      Emitter emitter, Substitution substitution);
+  jsAst.Expression getSignatureEncoding(ModularNamer namer,
+      ModularEmitter emitter, DartType type, jsAst.Expression this_);
 
   /// Returns the JavaScript template to determine at runtime if a type object
   /// is a function type.
@@ -692,15 +680,16 @@
   /// is a type argument of js-interop class.
   jsAst.Template get templateForIsJsInteropTypeArgument;
 
-  jsAst.Name get getFunctionThatReturnsNullName;
-
   /// Returns a [jsAst.Expression] representing the given [type]. Type variables
   /// are replaced by the [jsAst.Expression] returned by [onVariable].
   jsAst.Expression getTypeRepresentation(
-      Emitter emitter, DartType type, OnVariableCallback onVariable,
+      ModularEmitter emitter, DartType type, OnVariableCallback onVariable,
       [ShouldEncodeTypedefCallback shouldEncodeTypedef]);
 
-  String getTypeRepresentationForTypeConstant(DartType type);
+  jsAst.Expression getJsInteropTypeArguments(int count);
+
+  /// Fixed strings used for runtime types encoding.
+  RuntimeTypeTags get rtiTags;
 }
 
 /// Common functionality for [_RuntimeTypesNeedBuilder] and [_RuntimeTypes].
@@ -855,18 +844,18 @@
       ElementEnvironment elementEnvironment,
       CommonElements commonElements,
       DartTypes types,
-      WorldBuilder worldBuilder,
+      BuiltWorld world,
       Set<GenericInstantiation> genericInstantiations,
       {bool forRtiNeeds: true})
-      : explicitIsChecks = new Set<DartType>.from(worldBuilder.isChecks) {
+      : explicitIsChecks = new Set<DartType>.from(world.isChecks) {
     _setupDependencies(
-        elementEnvironment, commonElements, worldBuilder, genericInstantiations,
+        elementEnvironment, commonElements, world, genericInstantiations,
         forRtiNeeds: forRtiNeeds);
-    _propagateTests(commonElements, elementEnvironment, worldBuilder);
+    _propagateTests(commonElements, elementEnvironment, world);
     if (forRtiNeeds) {
-      _propagateLiterals(elementEnvironment, worldBuilder);
+      _propagateLiterals(elementEnvironment, world);
     }
-    _collectResults(commonElements, elementEnvironment, types, worldBuilder,
+    _collectResults(commonElements, elementEnvironment, types, world,
         forRtiNeeds: forRtiNeeds);
   }
 
@@ -977,7 +966,7 @@
   }
 
   MethodNode _getMethodNode(ElementEnvironment elementEnvironment,
-      WorldBuilder worldBuilder, Entity function) {
+      BuiltWorld world, Entity function) {
     return _methods.putIfAbsent(function, () {
       MethodNode node;
       if (function is FunctionEntity) {
@@ -985,11 +974,11 @@
         bool isCallTarget;
         bool isNoSuchMethod;
         if (function.isInstanceMember) {
-          isCallTarget = worldBuilder.closurizedMembers.contains(function);
+          isCallTarget = world.closurizedMembers.contains(function);
           instanceName = function.memberName;
           isNoSuchMethod = instanceName.text == Identifiers.noSuchMethod_;
         } else {
-          isCallTarget = worldBuilder.closurizedStatics.contains(function);
+          isCallTarget = world.closurizedStatics.contains(function);
           isNoSuchMethod = false;
         }
         node = new MethodNode(function, function.parameterStructure,
@@ -1009,7 +998,7 @@
   void _setupDependencies(
       ElementEnvironment elementEnvironment,
       CommonElements commonElements,
-      WorldBuilder worldBuilder,
+      BuiltWorld world,
       Set<GenericInstantiation> genericInstantiations,
       {bool forRtiNeeds: true}) {
     /// Register that if `node.entity` needs type arguments then so do entities
@@ -1026,8 +1015,8 @@
         if (typeDeclaration is ClassEntity) {
           node.addDependency(_getClassNode(typeDeclaration));
         } else {
-          node.addDependency(_getMethodNode(
-              elementEnvironment, worldBuilder, typeDeclaration));
+          node.addDependency(
+              _getMethodNode(elementEnvironment, world, typeDeclaration));
         }
       });
     }
@@ -1085,34 +1074,29 @@
       }
     }
 
-    worldBuilder.isChecks.forEach(processCheckedType);
+    world.isChecks.forEach(processCheckedType);
 
-    worldBuilder.instantiatedTypes.forEach((InterfaceType type) {
+    world.instantiatedTypes.forEach((InterfaceType type) {
       // Register that if [cls] needs type arguments then so do the entities
       // that declare type variables occurring in [type].
       ClassEntity cls = type.element;
       registerDependencies(_getClassNode(cls), type);
     });
 
-    worldBuilder.forEachStaticTypeArgument(
+    world.forEachStaticTypeArgument(
         (Entity entity, Iterable<DartType> typeArguments) {
       for (DartType type in typeArguments) {
         // Register that if [entity] needs type arguments then so do the
         // entities that declare type variables occurring in [type].
         registerDependencies(
-            _getMethodNode(elementEnvironment, worldBuilder, entity), type);
+            _getMethodNode(elementEnvironment, world, entity), type);
       }
     });
 
-    // TODO(johnniwinther): Cached here because the world builders computes
-    // this lazily. Track this set directly in the world builders .
-    Iterable<FunctionEntity> genericInstanceMethods =
-        worldBuilder.genericInstanceMethods;
-    worldBuilder.forEachDynamicTypeArgument(
+    world.forEachDynamicTypeArgument(
         (Selector selector, Iterable<DartType> typeArguments) {
       void processEntity(Entity entity) {
-        MethodNode node =
-            _getMethodNode(elementEnvironment, worldBuilder, entity);
+        MethodNode node = _getMethodNode(elementEnvironment, world, entity);
         if (node.selectorApplies(selector)) {
           for (DartType type in typeArguments) {
             // Register that if `node.entity` needs type arguments then so do
@@ -1122,16 +1106,15 @@
         }
       }
 
-      genericInstanceMethods.forEach(processEntity);
-      worldBuilder.genericLocalFunctions.forEach(processEntity);
-      worldBuilder.closurizedStatics.forEach(processEntity);
-      worldBuilder.userNoSuchMethods.forEach(processEntity);
+      world.forEachGenericInstanceMethod(processEntity);
+      world.genericLocalFunctions.forEach(processEntity);
+      world.closurizedStatics.forEach(processEntity);
+      world.userNoSuchMethods.forEach(processEntity);
     });
 
     for (GenericInstantiation instantiation in genericInstantiations) {
       void processEntity(Entity entity) {
-        MethodNode node =
-            _getMethodNode(elementEnvironment, worldBuilder, entity);
+        MethodNode node = _getMethodNode(elementEnvironment, world, entity);
         if (node.parameterStructure.typeParameters ==
             instantiation.typeArguments.length) {
           if (forRtiNeeds) {
@@ -1148,14 +1131,14 @@
         }
       }
 
-      worldBuilder.closurizedMembers.forEach(processEntity);
-      worldBuilder.closurizedStatics.forEach(processEntity);
-      worldBuilder.genericLocalFunctions.forEach(processEntity);
+      world.closurizedMembers.forEach(processEntity);
+      world.closurizedStatics.forEach(processEntity);
+      world.genericLocalFunctions.forEach(processEntity);
     }
   }
 
   void _propagateTests(CommonElements commonElements,
-      ElementEnvironment elementEnvironment, WorldBuilder worldBuilder) {
+      ElementEnvironment elementEnvironment, BuiltWorld worldBuilder) {
     void processTypeVariableType(TypeVariableType type, {bool direct: true}) {
       TypeVariableEntity variable = type.element;
       if (variable.typeDeclaration is ClassEntity) {
@@ -1182,99 +1165,18 @@
   }
 
   void _propagateLiterals(
-      ElementEnvironment elementEnvironment, WorldBuilder worldBuilder) {
-    worldBuilder.typeVariableTypeLiterals
-        .forEach((TypeVariableType typeVariableType) {
+      ElementEnvironment elementEnvironment, BuiltWorld world) {
+    world.typeVariableTypeLiterals.forEach((TypeVariableType typeVariableType) {
       TypeVariableEntity variable = typeVariableType.element;
       if (variable.typeDeclaration is ClassEntity) {
         _getClassNode(variable.typeDeclaration).markDirectLiteral();
       } else {
-        _getMethodNode(
-                elementEnvironment, worldBuilder, variable.typeDeclaration)
+        _getMethodNode(elementEnvironment, world, variable.typeDeclaration)
             .markDirectLiteral();
       }
     });
   }
 
-  void _collectResults(
-      CommonElements commonElements,
-      ElementEnvironment elementEnvironment,
-      DartTypes types,
-      WorldBuilder worldBuilder,
-      {bool forRtiNeeds: true}) {
-    /// Register the implicit is-test of [type].
-    ///
-    /// If [type] is of the form `FutureOr<X>`, also register the implicit
-    /// is-tests of `Future<X>` and `X`.
-    void addImplicitCheck(DartType type) {
-      if (implicitIsChecks.add(type)) {
-        if (type is FutureOrType) {
-          addImplicitCheck(commonElements.futureType(type.typeArgument));
-          addImplicitCheck(type.typeArgument);
-        }
-      }
-    }
-
-    void addImplicitChecks(Iterable<DartType> types) {
-      types.forEach(addImplicitCheck);
-    }
-
-    worldBuilder.isChecks.forEach((DartType type) {
-      if (type is FutureOrType) {
-        addImplicitCheck(commonElements.futureType(type.typeArgument));
-        addImplicitCheck(type.typeArgument);
-      }
-    });
-
-    // Compute type arguments of classes that use one of their type variables in
-    // is-checks and add the is-checks that they imply.
-    _classes.forEach((ClassEntity cls, ClassNode node) {
-      if (!node.hasTest) return;
-      // Find all instantiated types that are a subtype of a class that uses
-      // one of its type arguments in an is-check and add the arguments to the
-      // set of is-checks.
-      for (InterfaceType type in worldBuilder.instantiatedTypes) {
-        // We need the type as instance of its superclass anyway, so we just
-        // try to compute the substitution; if the result is [:null:], the
-        // classes are not related.
-        InterfaceType instance = types.asInstanceOf(type, cls);
-        if (instance != null) {
-          for (DartType argument in instance.typeArguments) {
-            addImplicitCheck(argument.unaliased);
-          }
-        }
-      }
-    });
-
-    worldBuilder.forEachStaticTypeArgument(
-        (Entity function, Iterable<DartType> typeArguments) {
-      if (!_getMethodNode(elementEnvironment, worldBuilder, function).hasTest) {
-        return;
-      }
-      addImplicitChecks(typeArguments);
-    });
-
-    if (forRtiNeeds) {
-      _appliedSelectorMap = <Selector, Set<Entity>>{};
-    }
-
-    worldBuilder.forEachDynamicTypeArgument(
-        (Selector selector, Iterable<DartType> typeArguments) {
-      for (MethodNode node in _methods.values) {
-        if (node.selectorApplies(selector)) {
-          if (forRtiNeeds) {
-            _appliedSelectorMap
-                .putIfAbsent(selector, () => new Set<Entity>())
-                .add(node.entity);
-          }
-          if (node.hasTest) {
-            addImplicitChecks(typeArguments);
-          }
-        }
-      }
-    });
-  }
-
   String dump({bool verbose: false}) {
     StringBuffer sb = new StringBuffer();
 
@@ -1322,6 +1224,82 @@
 
     return sb.toString();
   }
+
+  void _collectResults(CommonElements commonElements,
+      ElementEnvironment elementEnvironment, DartTypes types, BuiltWorld world,
+      {bool forRtiNeeds: true}) {
+    /// Register the implicit is-test of [type].
+    ///
+    /// If [type] is of the form `FutureOr<X>`, also register the implicit
+    /// is-tests of `Future<X>` and `X`.
+    void addImplicitCheck(DartType type) {
+      if (implicitIsChecks.add(type)) {
+        if (type is FutureOrType) {
+          addImplicitCheck(commonElements.futureType(type.typeArgument));
+          addImplicitCheck(type.typeArgument);
+        }
+      }
+    }
+
+    void addImplicitChecks(Iterable<DartType> types) {
+      types.forEach(addImplicitCheck);
+    }
+
+    world.isChecks.forEach((DartType type) {
+      if (type is FutureOrType) {
+        addImplicitCheck(commonElements.futureType(type.typeArgument));
+        addImplicitCheck(type.typeArgument);
+      }
+    });
+
+    // Compute type arguments of classes that use one of their type variables in
+    // is-checks and add the is-checks that they imply.
+    _classes.forEach((ClassEntity cls, ClassNode node) {
+      if (!node.hasTest) return;
+      // Find all instantiated types that are a subtype of a class that uses
+      // one of its type arguments in an is-check and add the arguments to the
+      // set of is-checks.
+      for (InterfaceType type in world.instantiatedTypes) {
+        // We need the type as instance of its superclass anyway, so we just
+        // try to compute the substitution; if the result is [:null:], the
+        // classes are not related.
+        InterfaceType instance = types.asInstanceOf(type, cls);
+        if (instance != null) {
+          for (DartType argument in instance.typeArguments) {
+            addImplicitCheck(argument.unaliased);
+          }
+        }
+      }
+    });
+
+    world.forEachStaticTypeArgument(
+        (Entity function, Iterable<DartType> typeArguments) {
+      if (!_getMethodNode(elementEnvironment, world, function).hasTest) {
+        return;
+      }
+      addImplicitChecks(typeArguments);
+    });
+
+    if (forRtiNeeds) {
+      _appliedSelectorMap = <Selector, Set<Entity>>{};
+    }
+
+    world.forEachDynamicTypeArgument(
+        (Selector selector, Iterable<DartType> typeArguments) {
+      for (MethodNode node in _methods.values) {
+        if (node.selectorApplies(selector)) {
+          if (forRtiNeeds) {
+            _appliedSelectorMap
+                .putIfAbsent(selector, () => new Set<Entity>())
+                .add(node.entity);
+          }
+          if (node.hasTest) {
+            addImplicitChecks(typeArguments);
+          }
+        }
+      }
+    });
+  }
 }
 
 abstract class RtiNode {
@@ -1512,14 +1490,12 @@
 
   @override
   RuntimeTypesNeed computeRuntimeTypesNeed(
-      ResolutionWorldBuilder resolutionWorldBuilder,
-      KClosedWorld closedWorld,
-      CompilerOptions options) {
+      KClosedWorld closedWorld, CompilerOptions options) {
     TypeVariableTests typeVariableTests = new TypeVariableTests(
         closedWorld.elementEnvironment,
         closedWorld.commonElements,
         closedWorld.dartTypes,
-        resolutionWorldBuilder,
+        closedWorld,
         _genericInstantiations);
     Set<ClassEntity> classesNeedingTypeArguments = new Set<ClassEntity>();
     Set<FunctionEntity> methodsNeedingSignature = new Set<FunctionEntity>();
@@ -1550,6 +1526,7 @@
         closedWorld.classHierarchy.forEachStrictSubtypeOf(cls,
             (ClassEntity sub) {
           potentiallyNeedTypeArguments(sub);
+          return IterationStep.CONTINUE;
         });
       } else if (entity is FunctionEntity) {
         methodsNeedingTypeArguments.add(entity);
@@ -1564,9 +1541,9 @@
       });
     }
 
-    Set<Local> localFunctions = resolutionWorldBuilder.localFunctions.toSet();
+    Set<Local> localFunctions = closedWorld.localFunctions.toSet();
     Set<FunctionEntity> closurizedMembers =
-        resolutionWorldBuilder.closurizedMembersWithFreeTypeVariables.toSet();
+        closedWorld.closurizedMembersWithFreeTypeVariables.toSet();
 
     // Check local functions and closurized members.
     void checkClosures({DartType potentialSubtypeOf}) {
@@ -1657,11 +1634,11 @@
     localFunctionsUsingTypeVariableLiterals
         .forEach(potentiallyNeedTypeArguments);
 
-    if (resolutionWorldBuilder.isMemberUsed(
+    if (closedWorld.isMemberUsed(
         closedWorld.commonElements.invocationTypeArgumentGetter)) {
       // If `Invocation.typeArguments` is live, mark all user-defined
       // implementations of `noSuchMethod` as needing type arguments.
-      for (MemberEntity member in resolutionWorldBuilder.userNoSuchMethods) {
+      for (MemberEntity member in closedWorld.userNoSuchMethods) {
         potentiallyNeedTypeArguments(member);
       }
     }
@@ -1679,11 +1656,11 @@
         }
       }
 
-      for (FunctionEntity method in resolutionWorldBuilder.genericMethods) {
+      closedWorld.forEachGenericMethod((FunctionEntity method) {
         checkFunction(method, _elementEnvironment.getFunctionType(method));
-      }
+      });
 
-      for (Local function in resolutionWorldBuilder.genericLocalFunctions) {
+      for (Local function in closedWorld.genericLocalFunctions) {
         checkFunction(
             function, _elementEnvironment.getLocalFunctionType(function));
       }
@@ -1804,7 +1781,7 @@
     }
     allClassesNeedingRuntimeType.forEach(potentiallyNeedTypeArguments);
     if (neededOnFunctions) {
-      for (Local function in resolutionWorldBuilder.genericLocalFunctions) {
+      for (Local function in closedWorld.genericLocalFunctions) {
         potentiallyNeedTypeArguments(function);
       }
       for (Local function in localFunctions) {
@@ -1819,7 +1796,7 @@
         localFunctionsNeedingSignature.addAll(localFunctions);
       }
       for (FunctionEntity function
-          in resolutionWorldBuilder.closurizedMembersWithFreeTypeVariables) {
+          in closedWorld.closurizedMembersWithFreeTypeVariables) {
         methodsNeedingSignature.add(function);
         potentiallyNeedTypeArguments(function.enclosingClass);
       }
@@ -1980,12 +1957,12 @@
 
   @override
   RuntimeTypesChecks computeRequiredChecks(
-      CodegenWorldBuilder codegenWorldBuilder, CompilerOptions options) {
+      CodegenWorld codegenWorld, CompilerOptions options) {
     TypeVariableTests typeVariableTests = new TypeVariableTests(
         _elementEnvironment,
         _commonElements,
         _types,
-        codegenWorldBuilder,
+        codegenWorld,
         _genericInstantiations,
         forRtiNeeds: false);
     Set<DartType> explicitIsChecks = typeVariableTests.explicitIsChecks;
@@ -2068,13 +2045,13 @@
       }
     });
 
-    codegenWorldBuilder.instantiatedClasses.forEach((ClassEntity cls) {
+    codegenWorld.instantiatedClasses.forEach((ClassEntity cls) {
       ClassUse classUse = classUseMap.putIfAbsent(cls, () => new ClassUse());
       classUse.instance = true;
     });
 
     Set<ClassEntity> visitedSuperClasses = {};
-    codegenWorldBuilder.instantiatedTypes.forEach((InterfaceType type) {
+    codegenWorld.instantiatedTypes.forEach((InterfaceType type) {
       liveTypeVisitor.visitType(type, TypeVisitorState.direct);
       ClassUse classUse =
           classUseMap.putIfAbsent(type.element, () => new ClassUse());
@@ -2107,13 +2084,12 @@
       }
     });
 
-    for (FunctionEntity element
-        in codegenWorldBuilder.staticFunctionsNeedingGetter) {
+    for (FunctionEntity element in codegenWorld.closurizedStatics) {
       FunctionType functionType = _elementEnvironment.getFunctionType(element);
       liveTypeVisitor.visitType(functionType, TypeVisitorState.direct);
     }
 
-    for (FunctionEntity element in codegenWorldBuilder.closurizedMembers) {
+    for (FunctionEntity element in codegenWorld.closurizedMembers) {
       FunctionType functionType = _elementEnvironment.getFunctionType(element);
       liveTypeVisitor.visitType(functionType, TypeVisitorState.direct);
     }
@@ -2125,12 +2101,12 @@
       }
     }
 
-    codegenWorldBuilder.forEachStaticTypeArgument(processMethodTypeArguments);
-    codegenWorldBuilder.forEachDynamicTypeArgument(processMethodTypeArguments);
-    codegenWorldBuilder.liveTypeArguments.forEach((DartType type) {
+    codegenWorld.forEachStaticTypeArgument(processMethodTypeArguments);
+    codegenWorld.forEachDynamicTypeArgument(processMethodTypeArguments);
+    codegenWorld.liveTypeArguments.forEach((DartType type) {
       liveTypeVisitor.visitType(type, TypeVisitorState.covariantTypeArgument);
     });
-    codegenWorldBuilder.constTypeLiterals.forEach((DartType type) {
+    codegenWorld.constTypeLiterals.forEach((DartType type) {
       liveTypeVisitor.visitType(type, TypeVisitorState.typeLiteral);
     });
 
@@ -2174,7 +2150,7 @@
     liveClasses.forEach(processClass);
 
     if (options.parameterCheckPolicy.isEmitted) {
-      for (FunctionEntity method in codegenWorldBuilder.genericMethods) {
+      codegenWorld.forEachGenericMethod((FunctionEntity method) {
         if (_rtiNeed.methodNeedsTypeArguments(method)) {
           for (TypeVariableType typeVariable
               in _elementEnvironment.getFunctionTypeVariables(method)) {
@@ -2185,7 +2161,7 @@
                 bound, TypeVisitorState.covariantTypeArgument);
           }
         }
-      }
+      });
     }
 
     cachedRequiredChecks = _computeChecks(classUseMap);
@@ -2226,27 +2202,17 @@
 }
 
 class RuntimeTypesEncoderImpl implements RuntimeTypesEncoder {
-  final Namer namer;
   final ElementEnvironment _elementEnvironment;
   final CommonElements commonElements;
   final TypeRepresentationGenerator _representationGenerator;
   final RuntimeTypesNeed _rtiNeed;
+  @override
+  final RuntimeTypeTags rtiTags;
 
-  RuntimeTypesEncoderImpl(this.namer, NativeBasicData nativeData,
+  RuntimeTypesEncoderImpl(this.rtiTags, NativeBasicData nativeData,
       this._elementEnvironment, this.commonElements, this._rtiNeed)
       : _representationGenerator =
-            new TypeRepresentationGenerator(namer, nativeData);
-
-  @override
-  bool isSimpleFunctionType(FunctionType type) {
-    if (!type.returnType.isDynamic) return false;
-    if (!type.optionalParameterTypes.isEmpty) return false;
-    if (!type.namedParameterTypes.isEmpty) return false;
-    for (DartType parameter in type.parameterTypes) {
-      if (!parameter.isDynamic) return false;
-    }
-    return true;
-  }
+            new TypeRepresentationGenerator(rtiTags, nativeData);
 
   /// Returns the JavaScript template to determine at runtime if a type object
   /// is a function type.
@@ -2283,28 +2249,18 @@
 
   @override
   jsAst.Expression getTypeRepresentation(
-      Emitter emitter, DartType type, OnVariableCallback onVariable,
+      ModularEmitter emitter, DartType type, OnVariableCallback onVariable,
       [ShouldEncodeTypedefCallback shouldEncodeTypedef]) {
     return _representationGenerator.getTypeRepresentation(
         emitter, type, onVariable, shouldEncodeTypedef);
   }
 
-  @override
-  jsAst.Expression getSubstitutionRepresentation(
-      Emitter emitter, List<DartType> types, OnVariableCallback onVariable) {
-    List<jsAst.Expression> elements = types
-        .map(
-            (DartType type) => getTypeRepresentation(emitter, type, onVariable))
-        .toList(growable: false);
-    return new jsAst.ArrayInitializer(elements);
-  }
-
   String getTypeVariableName(TypeVariableType type) {
     String name = type.element.name;
     return name.replaceAll('#', '_');
   }
 
-  jsAst.Expression getTypeEncoding(Emitter emitter, DartType type,
+  jsAst.Expression getTypeEncoding(ModularEmitter emitter, DartType type,
       {bool alwaysGenerateFunction: false}) {
     ClassEntity contextClass = DartTypes.getClassContext(type);
     jsAst.Expression onVariable(TypeVariableType v) {
@@ -2331,8 +2287,8 @@
   }
 
   @override
-  jsAst.Expression getSignatureEncoding(
-      Emitter emitter, DartType type, jsAst.Expression this_) {
+  jsAst.Expression getSignatureEncoding(ModularNamer namer,
+      ModularEmitter emitter, DartType type, jsAst.Expression this_) {
     ClassEntity contextClass = DartTypes.getClassContext(type);
     jsAst.Expression encoding =
         getTypeEncoding(emitter, type, alwaysGenerateFunction: true);
@@ -2358,100 +2314,41 @@
     }
   }
 
-  /// Compute a JavaScript expression that describes the necessary substitution
-  /// for type arguments in a subtype test.
-  ///
-  /// The result can be:
-  ///  1) `null`, if no substituted check is necessary, because the type
-  ///     variables are the same or there are no type variables in the class
-  ///     that is checked for.
-  ///  2) A list expression describing the type arguments to be used in the
-  ///     subtype check, if the type arguments to be used in the check do not
-  ///     depend on the type arguments of the object.
-  ///  3) A function mapping the type variables of the object to be checked to
-  ///     a list expression.
   @override
-  jsAst.Expression getSubstitutionCode(
-      Emitter emitter, Substitution substitution) {
-    if (substitution.isTrivial) {
-      return new jsAst.LiteralNull();
-    }
-
-    if (substitution.isJsInterop) {
-      return js(
-          'function() { return # }',
-          _representationGenerator
-              .getJsInteropTypeArguments(substitution.length));
-    }
-
-    jsAst.Expression declaration(TypeVariableType variable) {
-      return new jsAst.Parameter(getVariableName(variable.element.name));
-    }
-
-    jsAst.Expression use(TypeVariableType variable) {
-      return new jsAst.VariableUse(getVariableName(variable.element.name));
-    }
-
-    if (substitution.arguments.every((DartType type) => type.isDynamic)) {
-      return emitter.generateFunctionThatReturnsNull();
-    } else {
-      jsAst.Expression value =
-          getSubstitutionRepresentation(emitter, substitution.arguments, use);
-      if (substitution.isFunction) {
-        Iterable<jsAst.Expression> formals =
-            // TODO(johnniwinther): Pass [declaration] directly to `map` when
-            // `substitution.parameters` can no longer be a
-            // `List<ResolutionDartType>`.
-            substitution.parameters.map((type) => declaration(type));
-        return js('function(#) { return # }', [formals, value]);
-      } else {
-        return js('function() { return # }', value);
-      }
-    }
-  }
-
-  String getVariableName(String name) {
-    // Kernel type variable names for anonymous mixin applications have names
-    // canonicalized to a non-identified, e.g. '#U0'.
-    name = name.replaceAll('#', '_');
-    return namer.safeVariableName(name);
-  }
-
-  @override
-  jsAst.Name get getFunctionThatReturnsNullName =>
-      namer.internalGlobal('functionThatReturnsNull');
-
-  @override
-  String getTypeRepresentationForTypeConstant(DartType type) {
-    if (type.isDynamic) return "dynamic";
-    if (type is TypedefType) {
-      return namer.uniqueNameForTypeConstantElement(
-          type.element.library, type.element);
-    }
-    if (type is FunctionType) {
-      // TODO(johnniwinther): Add naming scheme for function type literals.
-      // These currently only occur from kernel.
-      return '()->';
-    }
-    InterfaceType interface = type;
-    String name = namer.uniqueNameForTypeConstantElement(
-        interface.element.library, interface.element);
-
-    // Type constants can currently only be raw types, so there is no point
-    // adding ground-term type parameters, as they would just be 'dynamic'.
-    // TODO(sra): Since the result string is used only in constructing constant
-    // names, it would result in more readable names if the final string was a
-    // legal JavaScript identifier.
-    if (interface.typeArguments.isEmpty) return name;
-    String arguments =
-        new List.filled(interface.typeArguments.length, 'dynamic').join(', ');
-    return '$name<$arguments>';
+  jsAst.Expression getJsInteropTypeArguments(int count) {
+    return _representationGenerator.getJsInteropTypeArguments(count);
   }
 }
 
+/// Fixed strings used for runtime types encoding.
+// TODO(johnniwinther): Use different names for minified code?
+class RuntimeTypeTags {
+  const RuntimeTypeTags();
+
+  String get typedefTag => r'typedef';
+
+  String get functionTypeTag => r'func';
+
+  String get functionTypeVoidReturnTag => r'v';
+
+  String get functionTypeReturnTypeTag => r'ret';
+
+  String get functionTypeRequiredParametersTag => r'args';
+
+  String get functionTypeOptionalParametersTag => r'opt';
+
+  String get functionTypeNamedParametersTag => r'named';
+
+  String get functionTypeGenericBoundsTag => r'bounds';
+
+  String get futureOrTag => r'futureOr';
+
+  String get futureOrTypeTag => r'type';
+}
+
 class TypeRepresentationGenerator
-    implements DartTypeVisitor<jsAst.Expression, Emitter> {
-  final Namer namer;
+    implements DartTypeVisitor<jsAst.Expression, ModularEmitter> {
+  final RuntimeTypeTags _rtiTags;
   final NativeBasicData _nativeData;
 
   OnVariableCallback onVariable;
@@ -2459,12 +2356,12 @@
   Map<TypeVariableType, jsAst.Expression> typedefBindings;
   List<FunctionTypeVariable> functionTypeVariables = <FunctionTypeVariable>[];
 
-  TypeRepresentationGenerator(this.namer, this._nativeData);
+  TypeRepresentationGenerator(this._rtiTags, this._nativeData);
 
   /// Creates a type representation for [type]. [onVariable] is called to
   /// provide the type representation for type variables.
   jsAst.Expression getTypeRepresentation(
-      Emitter emitter,
+      ModularEmitter emitter,
       DartType type,
       OnVariableCallback onVariable,
       ShouldEncodeTypedefCallback encodeTypedef) {
@@ -2479,7 +2376,8 @@
     return representation;
   }
 
-  jsAst.Expression getJavaScriptClassName(Entity element, Emitter emitter) {
+  jsAst.Expression getJavaScriptClassName(
+      Entity element, ModularEmitter emitter) {
     return emitter.typeAccess(element);
   }
 
@@ -2489,12 +2387,12 @@
 
   jsAst.Expression getJsInteropTypeArgumentValue() => js('-2');
   @override
-  jsAst.Expression visit(DartType type, Emitter emitter) =>
+  jsAst.Expression visit(DartType type, ModularEmitter emitter) =>
       type.accept(this, emitter);
 
   @override
   jsAst.Expression visitTypeVariableType(
-      TypeVariableType type, Emitter emitter) {
+      TypeVariableType type, ModularEmitter emitter) {
     if (typedefBindings != null) {
       assert(typedefBindings[type] != null);
       return typedefBindings[type];
@@ -2504,14 +2402,14 @@
 
   @override
   jsAst.Expression visitFunctionTypeVariable(
-      FunctionTypeVariable type, Emitter emitter) {
+      FunctionTypeVariable type, ModularEmitter emitter) {
     int position = functionTypeVariables.indexOf(type);
     assert(position >= 0);
     return js.number(functionTypeVariables.length - position - 1);
   }
 
   @override
-  jsAst.Expression visitDynamicType(DynamicType type, Emitter emitter) {
+  jsAst.Expression visitDynamicType(DynamicType type, ModularEmitter emitter) {
     return getDynamicValue();
   }
 
@@ -2528,7 +2426,8 @@
   }
 
   @override
-  jsAst.Expression visitInterfaceType(InterfaceType type, Emitter emitter) {
+  jsAst.Expression visitInterfaceType(
+      InterfaceType type, ModularEmitter emitter) {
     jsAst.Expression name = getJavaScriptClassName(type.element, emitter);
     jsAst.Expression result;
     if (type.typeArguments.isEmpty) {
@@ -2547,7 +2446,7 @@
     return result;
   }
 
-  jsAst.Expression visitList(List<DartType> types, Emitter emitter,
+  jsAst.Expression visitList(List<DartType> types, ModularEmitter emitter,
       {jsAst.Expression head}) {
     List<jsAst.Expression> elements = <jsAst.Expression>[];
     if (head != null) {
@@ -2567,13 +2466,13 @@
   /// Returns the JavaScript template to determine at runtime if a type object
   /// is a function type.
   jsAst.Template get templateForIsFunctionType {
-    return jsAst.js.expressionTemplateFor("'${namer.functionTypeTag}' in #");
+    return jsAst.js.expressionTemplateFor("'${_rtiTags.functionTypeTag}' in #");
   }
 
   /// Returns the JavaScript template to determine at runtime if a type object
   /// is a FutureOr type.
   jsAst.Template get templateForIsFutureOrType {
-    return jsAst.js.expressionTemplateFor("'${namer.futureOrTag}' in #");
+    return jsAst.js.expressionTemplateFor("'${_rtiTags.futureOrTag}' in #");
   }
 
   /// Returns the JavaScript template to determine at runtime if a type object
@@ -2593,7 +2492,8 @@
   }
 
   @override
-  jsAst.Expression visitFunctionType(FunctionType type, Emitter emitter) {
+  jsAst.Expression visitFunctionType(
+      FunctionType type, ModularEmitter emitter) {
     List<jsAst.Property> properties = <jsAst.Property>[];
 
     void addProperty(String name, jsAst.Expression value) {
@@ -2602,7 +2502,7 @@
 
     // Type representations for functions have a property which is a tag marking
     // them as function types. The value is not used, so '1' is just a dummy.
-    addProperty(namer.functionTypeTag, js.number(1));
+    addProperty(_rtiTags.functionTypeTag, js.number(1));
 
     if (type.typeVariables.isNotEmpty) {
       // Generic function types have type parameters which are reduced to de
@@ -2613,20 +2513,20 @@
       // TODO(sra): This emits `P.Object` for the common unbounded case. We
       // could replace the Object bounds with an array hole for a compact `[,,]`
       // representation.
-      addProperty(namer.functionTypeGenericBoundsTag,
+      addProperty(_rtiTags.functionTypeGenericBoundsTag,
           visitList(type.typeVariables.map((v) => v.bound).toList(), emitter));
     }
 
     if (!type.returnType.treatAsDynamic) {
       addProperty(
-          namer.functionTypeReturnTypeTag, visit(type.returnType, emitter));
+          _rtiTags.functionTypeReturnTypeTag, visit(type.returnType, emitter));
     }
     if (!type.parameterTypes.isEmpty) {
-      addProperty(namer.functionTypeRequiredParametersTag,
+      addProperty(_rtiTags.functionTypeRequiredParametersTag,
           visitList(type.parameterTypes, emitter));
     }
     if (!type.optionalParameterTypes.isEmpty) {
-      addProperty(namer.functionTypeOptionalParametersTag,
+      addProperty(_rtiTags.functionTypeOptionalParametersTag,
           visitList(type.optionalParameterTypes, emitter));
     }
     if (!type.namedParameterTypes.isEmpty) {
@@ -2639,7 +2539,7 @@
         namedArguments
             .add(new jsAst.Property(name, visit(types[index], emitter)));
       }
-      addProperty(namer.functionTypeNamedParametersTag,
+      addProperty(_rtiTags.functionTypeNamedParametersTag,
           new jsAst.ObjectInitializer(namedArguments));
     }
 
@@ -2652,12 +2552,12 @@
   }
 
   @override
-  jsAst.Expression visitVoidType(VoidType type, Emitter emitter) {
+  jsAst.Expression visitVoidType(VoidType type, ModularEmitter emitter) {
     return getVoidValue();
   }
 
   @override
-  jsAst.Expression visitTypedefType(TypedefType type, Emitter emitter) {
+  jsAst.Expression visitTypedefType(TypedefType type, ModularEmitter emitter) {
     bool shouldEncode = shouldEncodeTypedef(type);
     DartType unaliasedType = type.unaliased;
 
@@ -2703,7 +2603,7 @@
           : visitList(type.typeArguments, emitter, head: name);
 
       // Add it to the function-type object.
-      jsAst.LiteralString tag = js.string(namer.typedefTag);
+      jsAst.LiteralString tag = js.string(_rtiTags.typedefTag);
       initializer.properties.add(new jsAst.Property(tag, encodedTypedef));
       return finish(initializer);
     } else {
@@ -2712,7 +2612,8 @@
   }
 
   @override
-  jsAst.Expression visitFutureOrType(FutureOrType type, Emitter emitter) {
+  jsAst.Expression visitFutureOrType(
+      FutureOrType type, ModularEmitter emitter) {
     List<jsAst.Property> properties = <jsAst.Property>[];
 
     void addProperty(String name, jsAst.Expression value) {
@@ -2721,9 +2622,9 @@
 
     // Type representations for FutureOr have a property which is a tag marking
     // them as FutureOr types. The value is not used, so '1' is just a dummy.
-    addProperty(namer.futureOrTag, js.number(1));
+    addProperty(_rtiTags.futureOrTag, js.number(1));
     if (!type.typeArgument.treatAsDynamic) {
-      addProperty(namer.futureOrTypeTag, visit(type.typeArgument, emitter));
+      addProperty(_rtiTags.futureOrTypeTag, visit(type.typeArgument, emitter));
     }
 
     return new jsAst.ObjectInitializer(properties);
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index 81b9f9e..b6f90d4 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -23,14 +23,14 @@
 
 class ClassStubGenerator {
   final Namer _namer;
-  final CodegenWorldBuilder _worldBuilder;
+  final CodegenWorld _codegenWorld;
   final JClosedWorld _closedWorld;
   final bool enableMinification;
   final Emitter _emitter;
   final CommonElements _commonElements;
 
   ClassStubGenerator(this._emitter, this._commonElements, this._namer,
-      this._worldBuilder, this._closedWorld,
+      this._codegenWorld, this._closedWorld,
       {this.enableMinification});
 
   InterceptorData get _interceptorData => _closedWorld.interceptorData;
@@ -62,7 +62,7 @@
       typeParameters,
       fieldInitializers,
       typeInits,
-      _namer.deferredAction
+      _namer.fixedNames.deferredAction
     ]);
   }
 
@@ -164,7 +164,7 @@
     Map<jsAst.Name, Selector> jsNames = <jsAst.Name, Selector>{};
 
     // Do not generate no such method handlers if there is no class.
-    if (_worldBuilder.directlyInstantiatedClasses.isEmpty) {
+    if (_codegenWorld.directlyInstantiatedClasses.isEmpty) {
       return jsNames;
     }
 
@@ -189,9 +189,9 @@
       }
     }
 
-    _worldBuilder.forEachInvokedName(addNoSuchMethodHandlers);
-    _worldBuilder.forEachInvokedGetter(addNoSuchMethodHandlers);
-    _worldBuilder.forEachInvokedSetter(addNoSuchMethodHandlers);
+    _codegenWorld.forEachInvokedName(addNoSuchMethodHandlers);
+    _codegenWorld.forEachInvokedGetter(addNoSuchMethodHandlers);
+    _codegenWorld.forEachInvokedSetter(addNoSuchMethodHandlers);
     return jsNames;
   }
 
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 0320701..3871204 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -4,8 +4,6 @@
 
 library dart2js.js_emitter.code_emitter_task;
 
-import 'package:js_runtime/shared/embedded_names.dart' show JsBuiltin;
-
 import '../common.dart';
 import '../common/tasks.dart' show CompilerTask;
 import '../compiler.dart' show Compiler;
@@ -13,8 +11,9 @@
 import '../deferred_load.dart' show OutputUnit;
 import '../elements/entities.dart';
 import '../js/js.dart' as jsAst;
-import '../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
+import '../js_backend/backend.dart' show CodegenInputs, JavaScriptBackend;
 import '../js_backend/inferred_data.dart';
+import '../js_backend/namer.dart' show Namer;
 import '../universe/codegen_world_builder.dart';
 import '../world.dart' show JClosedWorld;
 import 'program_builder/program_builder.dart';
@@ -24,7 +23,6 @@
 import 'model.dart';
 import 'native_emitter.dart' show NativeEmitter;
 import 'type_test_registry.dart' show TypeTestRegistry;
-import 'sorter.dart';
 
 /// Generates the code for all used classes in the program. Static fields (even
 /// in classes) are ignored, since they can be treated as non-class elements.
@@ -34,11 +32,11 @@
   TypeTestRegistry typeTestRegistry;
   NativeEmitter _nativeEmitter;
   MetadataCollector metadataCollector;
-  final EmitterFactory _emitterFactory;
   Emitter _emitter;
-  final Compiler compiler;
+  final Compiler _compiler;
+  final bool _generateSourceMap;
 
-  JavaScriptBackend get backend => compiler.backend;
+  JavaScriptBackend get _backend => _compiler.backend;
 
   @deprecated
   // This field should be removed. It's currently only needed for dump-info and
@@ -47,11 +45,8 @@
   /// Contains a list of all classes that are emitted.
   Set<ClassEntity> neededClasses;
 
-  CodeEmitterTask(Compiler compiler, bool generateSourceMap)
-      : compiler = compiler,
-        _emitterFactory = startup_js_emitter.EmitterFactory(
-            generateSourceMap: generateSourceMap),
-        super(compiler.measurer);
+  CodeEmitterTask(this._compiler, this._generateSourceMap)
+      : super(_compiler.measurer);
 
   NativeEmitter get nativeEmitter {
     assert(
@@ -70,133 +65,81 @@
   @override
   String get name => 'Code emitter';
 
-  /// Returns true, if the emitter supports reflection.
-  bool get supportsReflection => _emitterFactory.supportsReflection;
-
-  /// Returns the closure expression of a static function.
-  jsAst.Expression isolateStaticClosureAccess(FunctionEntity element) {
-    return emitter.isolateStaticClosureAccess(element);
-  }
-
-  /// Returns the JS function that must be invoked to get the value of the
-  /// lazily initialized static.
-  jsAst.Expression isolateLazyInitializerAccess(FieldEntity element) {
-    return emitter.isolateLazyInitializerAccess(element);
-  }
-
-  /// Returns the JS code for accessing the embedded [global].
-  jsAst.Expression generateEmbeddedGlobalAccess(String global) {
-    return emitter.generateEmbeddedGlobalAccess(global);
-  }
-
-  /// Returns the JS code for accessing the given [constant].
-  jsAst.Expression constantReference(ConstantValue constant) {
-    return emitter.constantReference(constant);
-  }
-
-  jsAst.Expression staticFieldAccess(FieldEntity e) {
-    return emitter.staticFieldAccess(e);
-  }
-
-  /// Returns the JS function representing the given function.
-  ///
-  /// The function must be invoked and can not be used as closure.
-  jsAst.Expression staticFunctionAccess(FunctionEntity e) {
-    return emitter.staticFunctionAccess(e);
-  }
-
-  /// Returns the JS constructor of the given element.
-  ///
-  /// The returned expression must only be used in a JS `new` expression.
-  jsAst.Expression constructorAccess(ClassEntity e) {
-    return emitter.constructorAccess(e);
-  }
-
-  /// Returns the JS prototype of the given class [e].
-  jsAst.Expression prototypeAccess(ClassEntity e,
-      {bool hasBeenInstantiated: false}) {
-    return emitter.prototypeAccess(e, hasBeenInstantiated);
-  }
-
-  /// Returns the JS prototype of the given interceptor class [e].
-  jsAst.Expression interceptorPrototypeAccess(ClassEntity e) {
-    return jsAst.js('#.prototype', interceptorClassAccess(e));
-  }
-
-  /// Returns the JS constructor of the given interceptor class [e].
-  jsAst.Expression interceptorClassAccess(ClassEntity e) {
-    return emitter.interceptorClassAccess(e);
-  }
-
-  /// Returns the JS expression representing the type [e].
-  ///
-  /// The given type [e] might be a Typedef.
-  jsAst.Expression typeAccess(Entity e) {
-    return emitter.typeAccess(e);
-  }
-
-  /// Returns the JS template for the given [builtin].
-  jsAst.Template builtinTemplateFor(JsBuiltin builtin) {
-    return emitter.templateForBuiltin(builtin);
-  }
-
-  void _finalizeRti() {
+  void _finalizeRti(CodegenInputs codegen, CodegenWorld codegenWorld) {
     // Compute the required type checks to know which classes need a
     // 'is$' method.
-    typeTestRegistry.computeRequiredTypeChecks(backend.rtiChecksBuilder);
+    typeTestRegistry.computeRequiredTypeChecks(
+        _backend.rtiChecksBuilder, codegenWorld);
     // Compute the classes needed by RTI.
     typeTestRegistry.computeRtiNeededClasses(
-        backend.rtiSubstitutions, backend.generatedCode.keys);
+        codegen.rtiSubstitutions, _backend.generatedCode.keys);
   }
 
   /// Creates the [Emitter] for this task.
-  void createEmitter(Namer namer, JClosedWorld closedWorld,
-      CodegenWorldBuilder codegenWorldBuilder, Sorter sorter) {
+  void createEmitter(
+      Namer namer, CodegenInputs codegen, JClosedWorld closedWorld) {
     measure(() {
-      _nativeEmitter = new NativeEmitter(this, closedWorld, codegenWorldBuilder,
-          backend.nativeCodegenEnqueuer);
-      _emitter =
-          _emitterFactory.createEmitter(this, namer, closedWorld, sorter);
-      metadataCollector = new MetadataCollector(compiler.options,
-          compiler.reporter, _emitter, backend.rtiEncoder, codegenWorldBuilder);
-      typeTestRegistry = new TypeTestRegistry(compiler.options,
-          codegenWorldBuilder, closedWorld.elementEnvironment);
+      _nativeEmitter =
+          new NativeEmitter(this, closedWorld, _backend.nativeCodegenEnqueuer);
+      _emitter = new startup_js_emitter.EmitterImpl(
+          _compiler.options,
+          _compiler.reporter,
+          _compiler.outputProvider,
+          _compiler.dumpInfoTask,
+          namer,
+          closedWorld,
+          codegen.rtiEncoder,
+          _backend.sourceInformationStrategy,
+          this,
+          _generateSourceMap);
+      metadataCollector = new MetadataCollector(
+          _compiler.options,
+          _compiler.reporter,
+          _emitter,
+          codegen.rtiEncoder,
+          closedWorld.elementEnvironment);
+      typeTestRegistry = new TypeTestRegistry(
+          _compiler.options, closedWorld.elementEnvironment);
     });
   }
 
   int assembleProgram(
-      Namer namer, JClosedWorld closedWorld, InferredData inferredData) {
+      Namer namer,
+      JClosedWorld closedWorld,
+      InferredData inferredData,
+      CodegenInputs codegenInputs,
+      CodegenWorld codegenWorld) {
     return measure(() {
-      _finalizeRti();
+      measureSubtask('finalize rti', () {
+        _finalizeRti(codegenInputs, codegenWorld);
+      });
       ProgramBuilder programBuilder = new ProgramBuilder(
-          compiler.options,
-          compiler.reporter,
+          _compiler.options,
+          _compiler.reporter,
           closedWorld.elementEnvironment,
           closedWorld.commonElements,
           closedWorld.outputUnitData,
-          compiler.codegenWorldBuilder,
-          backend.nativeCodegenEnqueuer,
+          codegenWorld,
+          _backend.nativeCodegenEnqueuer,
           closedWorld.backendUsage,
-          backend.constants,
           closedWorld.nativeData,
           closedWorld.rtiNeed,
           closedWorld.interceptorData,
-          backend.superMemberData,
           typeTestRegistry.rtiChecks,
-          backend.rtiEncoder,
-          backend.oneShotInterceptorData,
-          backend.customElementsCodegenAnalysis,
-          backend.generatedCode,
+          codegenInputs.rtiEncoder,
+          codegenWorld.oneShotInterceptorData,
+          _backend.customElementsCodegenAnalysis,
+          _backend.generatedCode,
           namer,
           this,
           closedWorld,
           closedWorld.fieldAnalysis,
           inferredData,
-          backend.sourceInformationStrategy,
+          _backend.sourceInformationStrategy,
           closedWorld.sorter,
           typeTestRegistry.rtiNeededClasses,
           closedWorld.elementEnvironment.mainFunction);
-      int size = emitter.emitProgram(programBuilder);
+      int size = emitter.emitProgram(programBuilder, codegenWorld);
       // TODO(floitsch): we shouldn't need the `neededClasses` anymore.
       neededClasses = programBuilder.collector.neededClasses;
       return size;
@@ -204,31 +147,14 @@
   }
 }
 
-abstract class EmitterFactory {
-  /// Returns true, if the emitter supports reflection.
-  bool get supportsReflection;
-
-  /// Create the [Emitter] for the emitter [task] that uses the given [namer].
-  Emitter createEmitter(CodeEmitterTask task, Namer namer,
-      JClosedWorld closedWorld, Sorter sorter);
-}
-
-abstract class Emitter {
-  Program get programForTesting;
-
-  /// Uses the [programBuilder] to generate a model of the program, emits
-  /// the program, and returns the size of the generated output.
-  int emitProgram(ProgramBuilder programBuilder);
-
-  /// Returns the JS function that must be invoked to get the value of the
-  /// lazily initialized static.
-  jsAst.Expression isolateLazyInitializerAccess(covariant FieldEntity element);
-
-  /// Returns the closure expression of a static function.
-  jsAst.Expression isolateStaticClosureAccess(covariant FunctionEntity element);
-
-  /// Returns the JS code for accessing the embedded [global].
-  jsAst.Expression generateEmbeddedGlobalAccess(String global);
+/// Interface for the subset of the [Emitter] that can be used during modular
+/// code generation.
+///
+/// Note that the emission phase is not itself modular but performed on
+/// the closed world computed by the codegen enqueuer.
+abstract class ModularEmitter {
+  /// Returns the JS prototype of the given class [e].
+  jsAst.Expression prototypeAccess(ClassEntity e, {bool hasBeenInstantiated});
 
   /// Returns the JS function representing the given function.
   ///
@@ -237,85 +163,54 @@
 
   jsAst.Expression staticFieldAccess(FieldEntity element);
 
+  /// Returns the JS function that must be invoked to get the value of the
+  /// lazily initialized static.
+  jsAst.Expression isolateLazyInitializerAccess(covariant FieldEntity element);
+
+  /// Returns the closure expression of a static function.
+  jsAst.Expression staticClosureAccess(covariant FunctionEntity element);
+
   /// Returns the JS constructor of the given element.
   ///
   /// The returned expression must only be used in a JS `new` expression.
   jsAst.Expression constructorAccess(ClassEntity e);
 
-  /// Returns the JS prototype of the given class [e].
-  jsAst.Expression prototypeAccess(
-      covariant ClassEntity e, bool hasBeenInstantiated);
+  /// Returns the JS expression representing the type [e].
+  jsAst.Expression typeAccess(Entity e);
+
+  /// Returns the JS code for accessing the embedded [global].
+  jsAst.Expression generateEmbeddedGlobalAccess(String global);
+
+  /// Returns the JS code for accessing the given [constant].
+  jsAst.Expression constantReference(ConstantValue constant);
+
+  /// Returns the JS code for accessing the global property [global].
+  String generateEmbeddedGlobalAccessString(String global);
+}
+
+/// Interface for the emitter that is used during the emission phase on the
+/// closed world computed by the codegen enqueuer.
+///
+/// These methods are _not_ available during modular code generation.
+abstract class Emitter implements ModularEmitter {
+  Program get programForTesting;
+
+  /// Uses the [programBuilder] to generate a model of the program, emits
+  /// the program, and returns the size of the generated output.
+  int emitProgram(ProgramBuilder programBuilder, CodegenWorld codegenWorld);
+
+  /// Returns the JS prototype of the given interceptor class [e].
+  jsAst.Expression interceptorPrototypeAccess(ClassEntity e);
 
   /// Returns the JS constructor of the given interceptor class [e].
   jsAst.Expression interceptorClassAccess(ClassEntity e);
 
-  /// Returns the JS expression representing the type [e].
-  jsAst.Expression typeAccess(Entity e);
-
   /// Returns the JS expression representing a function that returns 'null'
   jsAst.Expression generateFunctionThatReturnsNull();
 
   int compareConstants(ConstantValue a, ConstantValue b);
   bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant);
 
-  /// Returns the JS code for accessing the given [constant].
-  jsAst.Expression constantReference(ConstantValue constant);
-
-  /// Returns the JS template for the given [builtin].
-  jsAst.Template templateForBuiltin(JsBuiltin builtin);
-
   /// Returns the size of the code generated for a given output [unit].
   int generatedSize(OutputUnit unit);
 }
-
-abstract class EmitterBase implements Emitter {
-  @override
-  Program programForTesting;
-  Namer get namer;
-
-  jsAst.PropertyAccess globalPropertyAccessForMember(MemberEntity element) {
-    jsAst.Name name = namer.globalPropertyNameForMember(element);
-    jsAst.PropertyAccess pa = new jsAst.PropertyAccess(
-        new jsAst.VariableUse(namer.globalObjectForMember(element)), name);
-    return pa;
-  }
-
-  jsAst.PropertyAccess globalPropertyAccessForClass(ClassEntity element) {
-    jsAst.Name name = namer.globalPropertyNameForClass(element);
-    jsAst.PropertyAccess pa = new jsAst.PropertyAccess(
-        new jsAst.VariableUse(namer.globalObjectForClass(element)), name);
-    return pa;
-  }
-
-  jsAst.PropertyAccess globalPropertyAccessForType(Entity element) {
-    jsAst.Name name = namer.globalPropertyNameForType(element);
-    jsAst.PropertyAccess pa = new jsAst.PropertyAccess(
-        new jsAst.VariableUse(namer.globalObjectForType(element)), name);
-    return pa;
-  }
-
-  @override
-  jsAst.PropertyAccess staticFieldAccess(FieldEntity element) {
-    return globalPropertyAccessForMember(element);
-  }
-
-  @override
-  jsAst.PropertyAccess staticFunctionAccess(FunctionEntity element) {
-    return globalPropertyAccessForMember(element);
-  }
-
-  @override
-  jsAst.PropertyAccess constructorAccess(ClassEntity element) {
-    return globalPropertyAccessForClass(element);
-  }
-
-  @override
-  jsAst.Expression interceptorClassAccess(ClassEntity element) {
-    return globalPropertyAccessForClass(element);
-  }
-
-  @override
-  jsAst.Expression typeAccess(Entity element) {
-    return globalPropertyAccessForType(element);
-  }
-}
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index 9306361..f205845 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -8,7 +8,6 @@
 import '../elements/entities.dart'
     show ClassEntity, FieldEntity, MemberEntity, TypedefEntity;
 import '../elements/types.dart';
-import '../js_backend/js_backend.dart' show SyntheticConstantKind;
 import 'sorter.dart' show Sorter;
 
 /// A canonical but arbitrary ordering of constants. The ordering is 'stable'
@@ -32,7 +31,7 @@
 
   int compareValues(ConstantValue a, ConstantValue b) {
     if (identical(a, b)) return 0;
-    int r = _KindVisitor.kind(a).compareTo(_KindVisitor.kind(b));
+    int r = a.kind.index.compareTo(b.kind.index);
     if (r != 0) return r;
     return a.accept(this, b);
   }
@@ -169,32 +168,22 @@
   }
 
   @override
-  int visitSynthetic(SyntheticConstantValue a, SyntheticConstantValue b) {
-    // [SyntheticConstantValue]s have abstract fields that are set only by
-    // convention.  Lucky for us, they do not occur as top level constant, only
-    // as elements of a few constants.  If this becomes a source of instability,
-    // we will need to add a total ordering on JavaScript ASTs including
-    // deferred elements.
-    SyntheticConstantKind aKind = a.valueKind;
-    SyntheticConstantKind bKind = b.valueKind;
-    int r = aKind.index - bKind.index;
-    if (r != 0) return r;
-    switch (aKind) {
-      case SyntheticConstantKind.DUMMY_INTERCEPTOR:
-      case SyntheticConstantKind.EMPTY_VALUE:
-        // Never emitted.
-        return 0;
+  int visitDummyInterceptor(
+      DummyInterceptorConstantValue a, DummyInterceptorConstantValue b) {
+    // Never emitted.
+    return 0;
+  }
 
-      case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
-        // An opaque deferred JS AST reference to a type in reflection data.
-        return 0;
-      case SyntheticConstantKind.NAME:
-        // An opaque deferred JS AST reference to a name.
-        return 0;
-      default:
-        // Should not happen.
-        throw 'unexpected SyntheticConstantKind $aKind';
-    }
+  @override
+  int visitUnreachable(UnreachableConstantValue a, UnreachableConstantValue b) {
+    // Never emitted.
+    return 0;
+  }
+
+  @override
+  int visitJsName(JsNameConstantValue a, JsNameConstantValue b) {
+    // An opaque deferred JS AST reference to a name.
+    return 0;
   }
 
   @override
@@ -214,63 +203,6 @@
   }
 }
 
-class _KindVisitor implements ConstantValueVisitor<int, Null> {
-  const _KindVisitor();
-
-  static const int FUNCTION = 1;
-  static const int NULL = 2;
-  static const int INT = 3;
-  static const int DOUBLE = 4;
-  static const int BOOL = 5;
-  static const int STRING = 6;
-  static const int LIST = 7;
-  static const int SET = 8;
-  static const int MAP = 9;
-  static const int CONSTRUCTED = 10;
-  static const int TYPE = 11;
-  static const int INTERCEPTOR = 12;
-  static const int SYNTHETIC = 13;
-  static const int DEFERRED_GLOBAL = 14;
-  static const int NONCONSTANT = 15;
-  static const int INSTANTIATION = 16;
-
-  static int kind(ConstantValue constant) =>
-      constant.accept(const _KindVisitor(), null);
-
-  @override
-  int visitFunction(FunctionConstantValue a, _) => FUNCTION;
-  @override
-  int visitNull(NullConstantValue a, _) => NULL;
-  @override
-  int visitNonConstant(NonConstantValue a, _) => NONCONSTANT;
-  @override
-  int visitInt(IntConstantValue a, _) => INT;
-  @override
-  int visitDouble(DoubleConstantValue a, _) => DOUBLE;
-  @override
-  int visitBool(BoolConstantValue a, _) => BOOL;
-  @override
-  int visitString(StringConstantValue a, _) => STRING;
-  @override
-  int visitList(ListConstantValue a, _) => LIST;
-  @override
-  int visitSet(SetConstantValue a, _) => SET;
-  @override
-  int visitMap(MapConstantValue a, _) => MAP;
-  @override
-  int visitConstructed(ConstructedConstantValue a, _) => CONSTRUCTED;
-  @override
-  int visitType(TypeConstantValue a, _) => TYPE;
-  @override
-  int visitInterceptor(InterceptorConstantValue a, _) => INTERCEPTOR;
-  @override
-  int visitSynthetic(SyntheticConstantValue a, _) => SYNTHETIC;
-  @override
-  int visitDeferredGlobal(DeferredGlobalConstantValue a, _) => DEFERRED_GLOBAL;
-  @override
-  int visitInstantiation(InstantiationConstantValue a, _) => INSTANTIATION;
-}
-
 /// Visitor for distinguishing types by kind.
 class _DartTypeKindVisitor extends DartTypeVisitor<int, Null> {
   const _DartTypeKindVisitor();
diff --git a/pkg/compiler/lib/src/js_emitter/headers.dart b/pkg/compiler/lib/src/js_emitter/headers.dart
index 9af8ea1..08fd664a 100644
--- a/pkg/compiler/lib/src/js_emitter/headers.dart
+++ b/pkg/compiler/lib/src/js_emitter/headers.dart
@@ -4,12 +4,12 @@
 
 library dart2js.js_emitter.headers;
 
-import '../compiler.dart' show Compiler;
+import '../options.dart';
 
-String generatedBy(Compiler compiler, {String flavor: ""}) {
+String generatedBy(CompilerOptions options, {String flavor: ""}) {
   String suffix = '';
-  if (compiler.options.hasBuildId) {
-    suffix = ' version: ${compiler.options.buildId}';
+  if (options.hasBuildId) {
+    suffix = ' version: ${options.buildId}';
   }
   if (flavor != "") flavor = " ($flavor)";
   return '// Generated by dart2js$flavor, '
@@ -37,8 +37,4 @@
 //    if this function is defined, it will be called at each entry of a
 //    method or constructor. Used only when compiling programs with
 //    --experiment-call-instrumentation.
-//
-// defaultPackagesBase:
-//    Override the location where `package:` uris are resolved from. By default
-//    they are resolved under "packages/" from the current window location.
 """;
diff --git a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
index e44e0a8..7a13db6 100644
--- a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
@@ -4,8 +4,7 @@
 
 library dart2js.js_emitter.instantiation_stub_generator;
 
-import '../common/names.dart';
-import '../common_elements.dart' show CommonElements;
+import '../common_elements.dart' show JCommonElements, JElementEnvironment;
 import '../elements/entities.dart';
 import '../io/source_information.dart';
 import '../js/js.dart' as jsAst;
@@ -24,23 +23,21 @@
 // Generator of stubs required for Instantiation classes.
 class InstantiationStubGenerator {
   final CodeEmitterTask _emitterTask;
-  final CommonElements _commonElements;
   final Namer _namer;
-  final CodegenWorldBuilder _codegenWorldBuilder;
+  final CodegenWorld _codegenWorld;
   final JClosedWorld _closedWorld;
   // ignore: UNUSED_FIELD
   final SourceInformationStrategy _sourceInformationStrategy;
 
-  InstantiationStubGenerator(
-      this._emitterTask,
-      this._commonElements,
-      this._namer,
-      this._codegenWorldBuilder,
-      this._closedWorld,
-      this._sourceInformationStrategy);
+  InstantiationStubGenerator(this._emitterTask, this._namer, this._closedWorld,
+      this._codegenWorld, this._sourceInformationStrategy);
 
   Emitter get _emitter => _emitterTask.emitter;
 
+  JCommonElements get _commonElements => _closedWorld.commonElements;
+  JElementEnvironment get _elementEnvironment =>
+      _closedWorld.elementEnvironment;
+
   /// Generates a stub to forward a call selector with no type arguments to a
   /// call selector with stored types.
   ///
@@ -109,7 +106,8 @@
   /// }
   /// ```
   ParameterStubMethod _generateSignatureStub(FieldEntity functionField) {
-    jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
+    jsAst.Name operatorSignature =
+        _namer.asName(_namer.fixedNames.operatorSignature);
 
     jsAst.Fun function = js('function() { return #(#(this.#), this.#); }', [
       _emitter.staticFunctionAccess(
@@ -138,9 +136,9 @@
 
     // 2. Find the function field access path.
     FieldEntity functionField;
-    _codegenWorldBuilder.forEachInstanceField(instantiationClass,
-        (ClassEntity enclosing, FieldEntity field, {bool isElided}) {
-      if (isElided) return;
+    _elementEnvironment.forEachInstanceField(instantiationClass,
+        (ClassEntity enclosing, FieldEntity field) {
+      if (_closedWorld.fieldAnalysis.getFieldData(field).isElided) return;
       if (field.name == '_genericClosure') functionField = field;
     });
     assert(functionField != null,
@@ -148,26 +146,21 @@
 
     String call = _namer.closureInvocationSelectorName;
     Map<Selector, SelectorConstraints> callSelectors =
-        _codegenWorldBuilder.invocationsByName(call);
+        _codegenWorld.invocationsByName(call);
 
     Set<ParameterStructure> computeLiveParameterStructures() {
       Set<ParameterStructure> parameterStructures =
           new Set<ParameterStructure>();
 
-      void process(Iterable<FunctionEntity> functions) {
-        for (FunctionEntity function in functions) {
-          if (function.parameterStructure.typeParameters == typeArgumentCount) {
-            parameterStructures.add(function.parameterStructure);
-          }
+      void process(FunctionEntity function) {
+        if (function.parameterStructure.typeParameters == typeArgumentCount) {
+          parameterStructures.add(function.parameterStructure);
         }
       }
 
-      process(_codegenWorldBuilder.closurizedStatics);
-      process(_codegenWorldBuilder.closurizedMembers);
-      process(_codegenWorldBuilder.genericInstanceMethods.where(
-          (FunctionEntity function) =>
-              function.name == Identifiers.call &&
-              function.enclosingClass.isClosure));
+      _codegenWorld.closurizedStatics.forEach(process);
+      _codegenWorld.closurizedMembers.forEach(process);
+      _codegenWorld.forEachGenericClosureCallMethod(process);
 
       return parameterStructures;
     }
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index 3bbdcfa0..495613f 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -23,39 +23,38 @@
 import '../universe/selector.dart' show Selector;
 import '../world.dart' show JClosedWorld;
 
-import 'code_emitter_task.dart' show CodeEmitterTask, Emitter;
+import 'code_emitter_task.dart' show Emitter;
 
 class InterceptorStubGenerator {
   final CompilerOptions _options;
   final CommonElements _commonElements;
-  final CodeEmitterTask _emitterTask;
+  final Emitter _emitter;
   final NativeCodegenEnqueuer _nativeCodegenEnqueuer;
   final Namer _namer;
-  final OneShotInterceptorData _oneShotInterceptorData;
   final CustomElementsCodegenAnalysis _customElementsCodegenAnalysis;
-  final CodegenWorldBuilder _codegenWorldBuilder;
+  final CodegenWorld _codegenWorld;
   final JClosedWorld _closedWorld;
 
   InterceptorStubGenerator(
       this._options,
       this._commonElements,
-      this._emitterTask,
+      this._emitter,
       this._nativeCodegenEnqueuer,
       this._namer,
-      this._oneShotInterceptorData,
       this._customElementsCodegenAnalysis,
-      this._codegenWorldBuilder,
+      this._codegenWorld,
       this._closedWorld);
 
   NativeData get _nativeData => _closedWorld.nativeData;
 
   InterceptorData get _interceptorData => _closedWorld.interceptorData;
 
-  Emitter get _emitter => _emitterTask.emitter;
+  jsAst.Expression generateGetInterceptorMethod(
+      SpecializedGetInterceptor interceptor) {
+    Set<ClassEntity> classes = interceptor.classes;
 
-  jsAst.Expression generateGetInterceptorMethod(Set<ClassEntity> classes) {
     jsAst.Expression interceptorFor(ClassEntity cls) {
-      return _emitterTask.interceptorPrototypeAccess(cls);
+      return _emitter.interceptorPrototypeAccess(cls);
     }
 
     /// Build a JavaScript AST node for doing a type check on
@@ -199,8 +198,7 @@
       ]));
     } else {
       ClassEntity jsUnknown = _commonElements.jsUnknownJavaScriptObjectClass;
-      if (_codegenWorldBuilder.directlyInstantiatedClasses
-          .contains(jsUnknown)) {
+      if (_codegenWorld.directlyInstantiatedClasses.contains(jsUnknown)) {
         statements.add(js.statement('if (!(receiver instanceof #)) return #;', [
           _emitter.constructorAccess(_commonElements.objectClass),
           interceptorFor(jsUnknown)
@@ -377,11 +375,9 @@
     return null;
   }
 
-  jsAst.Expression generateOneShotInterceptor(jsAst.Name name) {
-    Selector selector =
-        _oneShotInterceptorData.getOneShotInterceptorSelector(name);
-    Set<ClassEntity> classes =
-        _interceptorData.getInterceptedClassesOn(selector.name, _closedWorld);
+  jsAst.Expression generateOneShotInterceptor(OneShotInterceptor interceptor) {
+    Selector selector = interceptor.selector;
+    Set<ClassEntity> classes = interceptor.classes;
     jsAst.Name getInterceptorName = _namer.nameForGetInterceptor(classes);
 
     List<String> parameterNames = <String>[];
@@ -422,8 +418,8 @@
     if (!analysis.needsTable) return null;
 
     List<jsAst.Expression> elements = <jsAst.Expression>[];
-    List<ConstantValue> constants =
-        _codegenWorldBuilder.getConstantsForEmission(_emitter.compareConstants);
+    Iterable<ConstantValue> constants =
+        _codegenWorld.getConstantsForEmission(_emitter.compareConstants);
     for (ConstantValue constant in constants) {
       if (constant is TypeConstantValue &&
           constant.representedType is InterfaceType) {
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index 39b2574..0fa30eb 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -7,6 +7,7 @@
 import 'package:js_ast/src/precedence.dart' as js_precedence;
 
 import '../common.dart';
+import '../common_elements.dart' show JElementEnvironment;
 import '../constants/values.dart';
 import '../deferred_load.dart' show OutputUnit;
 import '../elements/entities.dart' show FunctionEntity;
@@ -17,7 +18,6 @@
 import '../js/js.dart' show js;
 import '../js_backend/runtime_types.dart' show RuntimeTypesEncoder;
 import '../options.dart';
-import '../universe/codegen_world_builder.dart';
 
 import 'code_emitter_task.dart' show Emitter;
 
@@ -37,7 +37,7 @@
   // will be applied to the [entry] to also mark potential [_MetadataEntry]
   // instances in the [entry] as seen.
   @override
-  markSeen(jsAst.TokenCounter visitor);
+  void markSeen(jsAst.TokenCounter visitor);
 }
 
 class _BoundMetadataEntry extends _MetadataEntry {
@@ -65,7 +65,7 @@
   bool get isUsed => _rc > 0;
 
   @override
-  markSeen(jsAst.BaseVisitor visitor) {
+  void markSeen(jsAst.BaseVisitor visitor) {
     _rc++;
     if (_rc == 1) entry.accept(visitor);
   }
@@ -101,7 +101,7 @@
   final DiagnosticReporter reporter;
   final Emitter _emitter;
   final RuntimeTypesEncoder _rtiEncoder;
-  final CodegenWorldBuilder _codegenWorldBuilder;
+  final JElementEnvironment _elementEnvironment;
 
   /// A map with a token per output unit for a list of expressions that
   /// represent metadata, parameter names and type variable types.
@@ -131,13 +131,13 @@
       <OutputUnit, Map<DartType, _BoundMetadataEntry>>{};
 
   MetadataCollector(this._options, this.reporter, this._emitter,
-      this._rtiEncoder, this._codegenWorldBuilder);
+      this._rtiEncoder, this._elementEnvironment);
 
   List<jsAst.DeferredNumber> reifyDefaultArguments(
       FunctionEntity function, OutputUnit outputUnit) {
     // TODO(sra): These are stored on the InstanceMethod or StaticDartMethod.
     List<jsAst.DeferredNumber> defaultValues = <jsAst.DeferredNumber>[];
-    _codegenWorldBuilder.forEachParameter(function,
+    _elementEnvironment.forEachParameter(function,
         (_, String name, ConstantValue constant) {
       if (constant == null) return;
       jsAst.Expression expression = _emitter.constantReference(constant);
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 2e0dca3..7be3f0d 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -5,7 +5,7 @@
 library dart2js.js_emitter.native_emitter;
 
 import '../common.dart';
-import '../common_elements.dart' show CommonElements;
+import '../common_elements.dart' show JCommonElements, JElementEnvironment;
 import '../elements/types.dart' show DartType, FunctionType;
 import '../elements/entities.dart';
 import '../js/js.dart' as jsAst;
@@ -13,7 +13,6 @@
 import '../js_backend/interceptor_data.dart';
 import '../js_backend/native_data.dart';
 import '../native/enqueue.dart' show NativeCodegenEnqueuer;
-import '../universe/codegen_world_builder.dart';
 import '../world.dart' show JClosedWorld;
 
 import 'code_emitter_task.dart' show CodeEmitterTask;
@@ -22,7 +21,6 @@
 class NativeEmitter {
   final CodeEmitterTask _emitterTask;
   final JClosedWorld _closedWorld;
-  final CodegenWorldBuilder _worldBuilder;
   final NativeCodegenEnqueuer _nativeCodegenEnqueuer;
 
   // Whether the application contains native classes.
@@ -39,10 +37,12 @@
   // Caches the methods that have a native body.
   Set<FunctionEntity> nativeMethods = new Set<FunctionEntity>();
 
-  NativeEmitter(this._emitterTask, this._closedWorld, this._worldBuilder,
-      this._nativeCodegenEnqueuer);
+  NativeEmitter(
+      this._emitterTask, this._closedWorld, this._nativeCodegenEnqueuer);
 
-  CommonElements get _commonElements => _closedWorld.commonElements;
+  JCommonElements get _commonElements => _closedWorld.commonElements;
+  JElementEnvironment get _elementEnvironment =>
+      _closedWorld.elementEnvironment;
   NativeData get _nativeData => _closedWorld.nativeData;
   InterceptorData get _interceptorData => _closedWorld.interceptorData;
 
@@ -261,14 +261,15 @@
   void potentiallyConvertDartClosuresToJs(List<jsAst.Statement> statements,
       FunctionEntity member, List<jsAst.Parameter> stubParameters) {
     jsAst.Expression closureConverter;
-    _worldBuilder.forEachParameter(member, (DartType type, String name, _) {
+    _elementEnvironment.forEachParameter(member,
+        (DartType type, String name, _) {
       // If [name] is not in [stubParameters], then the parameter is an optional
       // parameter that was not provided for this stub.
       for (jsAst.Parameter stubParameter in stubParameters) {
         if (stubParameter.name == name) {
           type = type.unaliased;
           if (type.isFunctionType) {
-            closureConverter ??= _emitterTask
+            closureConverter ??= _emitterTask.emitter
                 .staticFunctionAccess(_commonElements.closureConverter);
 
             // The parameter type is a function type either directly or through
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index dd65523..14ae576 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -4,6 +4,7 @@
 
 library dart2js.js_emitter.parameter_stub_generator;
 
+import '../common_elements.dart' show JElementEnvironment;
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
@@ -22,34 +23,38 @@
 
 import 'model.dart';
 
-import 'code_emitter_task.dart' show CodeEmitterTask, Emitter;
+import 'code_emitter_task.dart' show Emitter;
+import 'native_emitter.dart';
 
 class ParameterStubGenerator {
   static final Set<Selector> emptySelectorSet = new Set<Selector>();
 
-  final CodeEmitterTask _emitterTask;
+  final Emitter _emitter;
+  final NativeEmitter _nativeEmitter;
   final Namer _namer;
   final RuntimeTypesEncoder _rtiEncoder;
   final NativeData _nativeData;
   final InterceptorData _interceptorData;
-  final CodegenWorldBuilder _codegenWorldBuilder;
+  final CodegenWorld _codegenWorld;
   final JClosedWorld _closedWorld;
   final SourceInformationStrategy _sourceInformationStrategy;
 
   ParameterStubGenerator(
-      this._emitterTask,
+      this._emitter,
+      this._nativeEmitter,
       this._namer,
       this._rtiEncoder,
       this._nativeData,
       this._interceptorData,
-      this._codegenWorldBuilder,
+      this._codegenWorld,
       this._closedWorld,
       this._sourceInformationStrategy);
 
-  Emitter get _emitter => _emitterTask.emitter;
+  JElementEnvironment get _elementEnvironment =>
+      _closedWorld.elementEnvironment;
 
   bool needsSuperGetter(FunctionEntity element) =>
-      _codegenWorldBuilder.methodsNeedingSuperGetter.contains(element);
+      _codegenWorld.methodsNeedsSuperGetter(element);
 
   /// Generates stubs to fill in missing optional named or positional arguments
   /// and missing type arguments.  Returns `null` if no stub is needed.
@@ -128,7 +133,7 @@
     // Includes extra receiver argument when using interceptor convention
     int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1;
 
-    _codegenWorldBuilder.forEachParameter(member,
+    _elementEnvironment.forEachParameter(member,
         (_, String name, ConstantValue value) {
       String jsName = _namer.safeVariableName(name);
       assert(jsName != receiverArgumentName);
@@ -186,7 +191,7 @@
 
     var body; // List or jsAst.Statement.
     if (_nativeData.hasFixedBackendName(member)) {
-      body = _emitterTask.nativeEmitter.generateParameterStubStatements(
+      body = _nativeEmitter.generateParameterStubStatements(
           member,
           isInterceptedMethod,
           _namer.invocationName(selector),
@@ -202,7 +207,7 @@
         // Instead we need to call the statically resolved target.
         //   `<class>.prototype.bar$1.call(this, argument0, ...)`.
         body = js.statement('return #.#.call(this, #);', [
-          _emitterTask.prototypeAccess(superClass, hasBeenInstantiated: true),
+          _emitter.prototypeAccess(superClass, hasBeenInstantiated: true),
           methodName,
           targetArguments
         ]);
@@ -280,12 +285,12 @@
 
     // Only instance members (not static methods) need stubs.
     if (member.isInstanceMember) {
-      liveSelectors = _codegenWorldBuilder.invocationsByName(member.name);
+      liveSelectors = _codegenWorld.invocationsByName(member.name);
     }
 
     if (canTearOff) {
       String call = _namer.closureInvocationSelectorName;
-      callSelectors = _codegenWorldBuilder.invocationsByName(call);
+      callSelectors = _codegenWorld.invocationsByName(call);
     }
 
     assert(emptySelectorSet.isEmpty);
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index d0e09c8..7b49849f 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -13,11 +13,10 @@
   final JCommonElements _commonElements;
   final JElementEnvironment _elementEnvironment;
   final OutputUnitData _outputUnitData;
-  final CodegenWorldBuilder _worldBuilder;
+  final CodegenWorld _codegenWorld;
   // TODO(floitsch): the code-emitter task should not need a namer.
   final Namer _namer;
   final Emitter _emitter;
-  final JavaScriptConstantCompiler _constantHandler;
   final NativeData _nativeData;
   final InterceptorData _interceptorData;
   final OneShotInterceptorData _oneShotInterceptorData;
@@ -52,10 +51,9 @@
       this._commonElements,
       this._elementEnvironment,
       this._outputUnitData,
-      this._worldBuilder,
+      this._codegenWorld,
       this._namer,
       this._emitter,
-      this._constantHandler,
       this._nativeData,
       this._interceptorData,
       this._oneShotInterceptorData,
@@ -66,7 +64,7 @@
 
   Set<ClassEntity> computeInterceptorsReferencedFromConstants() {
     Set<ClassEntity> classes = new Set<ClassEntity>();
-    List<ConstantValue> constants = _worldBuilder.getConstantsForEmission();
+    Iterable<ConstantValue> constants = _codegenWorld.getConstantsForEmission();
     for (ConstantValue constant in constants) {
       if (constant is InterceptorConstantValue) {
         InterceptorConstantValue interceptorConstant = constant;
@@ -87,10 +85,9 @@
     // Go over specialized interceptors and then constants to know which
     // interceptors are needed.
     Set<ClassEntity> needed = new Set<ClassEntity>();
-    for (js.Name name
-        in _oneShotInterceptorData.specializedGetInterceptorNames) {
-      needed.addAll(
-          _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name));
+    for (SpecializedGetInterceptor interceptor
+        in _oneShotInterceptorData.specializedGetInterceptors) {
+      needed.addAll(interceptor.classes);
     }
 
     // Add interceptors referenced by constants.
@@ -127,8 +124,8 @@
 
   /// Compute all the constants that must be emitted.
   void computeNeededConstants() {
-    List<ConstantValue> constants =
-        _worldBuilder.getConstantsForEmission(_emitter.compareConstants);
+    Iterable<ConstantValue> constants =
+        _codegenWorld.getConstantsForEmission(_emitter.compareConstants);
     for (ConstantValue constant in constants) {
       if (_emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue;
 
@@ -156,7 +153,7 @@
     Set<ClassEntity> instantiatedClasses =
         // TODO(johnniwinther): This should be accessed from a codegen closed
         // world.
-        _worldBuilder.directlyInstantiatedClasses
+        _codegenWorld.directlyInstantiatedClasses
             .where(computeClassFilter(backendTypeHelpers))
             .toSet();
 
@@ -268,14 +265,14 @@
       list.add(element);
     }
 
-    List<FieldEntity> fields =
-        // TODO(johnniwinther): This should be accessed from a codegen closed
-        // world.
-        _worldBuilder.allReferencedStaticFields.where((FieldEntity field) {
-      return _closedWorld.fieldAnalysis.getFieldData(field).isEager;
-    }).toList();
+    List<FieldEntity> eagerFields = [];
+    _codegenWorld.forEachStaticField((FieldEntity field) {
+      if (_closedWorld.fieldAnalysis.getFieldData(field).isEager) {
+        eagerFields.add(field);
+      }
+    });
 
-    fields.sort((FieldEntity a, FieldEntity b) {
+    eagerFields.sort((FieldEntity a, FieldEntity b) {
       FieldAnalysisData aFieldData = _closedWorld.fieldAnalysis.getFieldData(a);
       FieldAnalysisData bFieldData = _closedWorld.fieldAnalysis.getFieldData(b);
       int aIndex = aFieldData.eagerCreationIndex;
@@ -292,7 +289,7 @@
         return _sorter.compareMembersByLocation(a, b);
       }
     });
-    fields.forEach(addToOutputUnit);
+    eagerFields.forEach(addToOutputUnit);
   }
 
   void computeNeededLibraries() {
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
index 493afa9..763bde2 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
@@ -27,19 +27,13 @@
   final CompilerOptions _options;
   final JElementEnvironment _elementEnvironment;
   final JCommonElements _commonElements;
-  final CodegenWorldBuilder _codegenWorldBuilder;
+  final CodegenWorld _codegenWorld;
   final NativeData _nativeData;
   final Namer _namer;
   final JClosedWorld _closedWorld;
 
-  FieldVisitor(
-      this._options,
-      this._elementEnvironment,
-      this._commonElements,
-      this._codegenWorldBuilder,
-      this._nativeData,
-      this._namer,
-      this._closedWorld);
+  FieldVisitor(this._options, this._elementEnvironment, this._commonElements,
+      this._codegenWorld, this._nativeData, this._namer, this._closedWorld);
 
   /// Invokes [f] for each of the fields of [element].
   ///
@@ -65,8 +59,7 @@
 
       // If the class is never instantiated we still need to set it up for
       // inheritance purposes, but we can simplify its JavaScript constructor.
-      isInstantiated =
-          _codegenWorldBuilder.directlyInstantiatedClasses.contains(cls);
+      isInstantiated = _codegenWorld.directlyInstantiatedClasses.contains(cls);
     } else if (library != null) {
       isLibrary = true;
       assert(visitStatics, failedAt(library));
@@ -141,16 +134,14 @@
   bool fieldNeedsGetter(FieldEntity field) {
     assert(field.isField);
     if (fieldAccessNeverThrows(field)) return false;
-    return field.enclosingClass != null &&
-        _codegenWorldBuilder.hasInvokedGetter(field);
+    return field.isInstanceMember && _codegenWorld.hasInvokedGetter(field);
   }
 
   bool fieldNeedsSetter(FieldEntity field) {
     assert(field.isField);
     if (fieldAccessNeverThrows(field)) return false;
     if (!field.isAssignable) return false;
-    return field.enclosingClass != null &&
-        _codegenWorldBuilder.hasInvokedSetter(field);
+    return field.isInstanceMember && _codegenWorld.hasInvokedSetter(field);
   }
 
   static bool fieldAccessNeverThrows(FieldEntity field) {
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index f5b5b0c..0cc2993 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
@@ -20,10 +20,7 @@
 import '../../js/js.dart' as js;
 import '../../js_backend/field_analysis.dart'
     show FieldAnalysisData, JFieldAnalysis;
-import '../../js_backend/backend.dart' show SuperMemberData;
 import '../../js_backend/backend_usage.dart';
-import '../../js_backend/constant_handler_javascript.dart'
-    show JavaScriptConstantCompiler;
 import '../../js_backend/custom_elements_analysis.dart';
 import '../../js_backend/inferred_data.dart';
 import '../../js_backend/interceptor_data.dart';
@@ -64,14 +61,12 @@
   final JElementEnvironment _elementEnvironment;
   final JCommonElements _commonElements;
   final OutputUnitData _outputUnitData;
-  final CodegenWorldBuilder _worldBuilder;
+  final CodegenWorld _codegenWorld;
   final NativeCodegenEnqueuer _nativeCodegenEnqueuer;
   final BackendUsage _backendUsage;
-  final JavaScriptConstantCompiler _constantHandler;
   final NativeData _nativeData;
   final RuntimeTypesNeed _rtiNeed;
   final InterceptorData _interceptorData;
-  final SuperMemberData _superMemberData;
   final RuntimeTypesChecks _rtiChecks;
   final RuntimeTypesEncoder _rtiEncoder;
   final OneShotInterceptorData _oneShotInterceptorData;
@@ -108,14 +103,12 @@
       this._elementEnvironment,
       this._commonElements,
       this._outputUnitData,
-      this._worldBuilder,
+      this._codegenWorld,
       this._nativeCodegenEnqueuer,
       this._backendUsage,
-      this._constantHandler,
       this._nativeData,
       this._rtiNeed,
       this._interceptorData,
-      this._superMemberData,
       this._rtiChecks,
       this._rtiEncoder,
       this._oneShotInterceptorData,
@@ -135,10 +128,9 @@
             _commonElements,
             _elementEnvironment,
             _outputUnitData,
-            _worldBuilder,
+            _codegenWorld,
             _namer,
             _task.emitter,
-            _constantHandler,
             _nativeData,
             _interceptorData,
             _oneShotInterceptorData,
@@ -347,12 +339,11 @@
     InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
         _options,
         _commonElements,
-        _task,
+        _task.emitter,
         _nativeCodegenEnqueuer,
         _namer,
-        _oneShotInterceptorData,
         _customElementsCodegenAnalysis,
-        _worldBuilder,
+        _codegenWorld,
         _closedWorld);
     return stubGenerator.generateTypeToInterceptorMap();
   }
@@ -435,11 +426,14 @@
 
   List<StaticField> _buildStaticLazilyInitializedFields(
       LibrariesMap librariesMap) {
-    Iterable<FieldEntity> lazyFields = _constantHandler
-        .getLazilyInitializedFieldsForEmission()
-        .where((FieldEntity element) =>
-            _outputUnitData.outputUnitForMember(element) ==
-            librariesMap.outputUnit);
+    List<FieldEntity> lazyFields = [];
+    _codegenWorld.forEachStaticField((FieldEntity field) {
+      if (_closedWorld.fieldAnalysis.getFieldData(field).isLazy &&
+          _outputUnitData.outputUnitForMember(field) ==
+              librariesMap.outputUnit) {
+        lazyFields.add(field);
+      }
+    });
     return _sorter
         .sortMembers(lazyFields)
         .map(_buildLazyField)
@@ -477,7 +471,7 @@
 
   void _addJsInteropStubs(LibrariesMap librariesMap) {
     if (_classes.containsKey(_commonElements.objectClass)) {
-      var toStringInvocation = _namer.invocationName(Selectors.toString_);
+      js.Name toStringInvocation = _namer.invocationName(Selectors.toString_);
       // TODO(jacobr): register toString as used so that it is always accessible
       // from JavaScript.
       _classes[_commonElements.objectClass].callStubs.add(_buildStubMethod(
@@ -492,22 +486,23 @@
     // a regular getter that returns a JavaScript function and tearing off
     // a method in the case where there exist multiple JavaScript classes
     // that conflict on whether the member is a getter or a method.
-    var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass];
-    var stubNames = new Set<String>();
+    Class interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass];
+    Set<String> stubNames = {};
     librariesMap
         .forEach((LibraryEntity library, List<ClassEntity> classElements, _) {
       for (ClassEntity cls in classElements) {
         if (_nativeData.isJsInteropClass(cls)) {
           _elementEnvironment.forEachLocalClassMember(cls,
               (MemberEntity member) {
-            var jsName = _nativeData.computeUnescapedJSInteropName(member.name);
+            String jsName =
+                _nativeData.computeUnescapedJSInteropName(member.name);
             if (!member.isInstanceMember) return;
             if (member.isGetter || member.isField || member.isFunction) {
-              var selectors =
-                  _worldBuilder.getterInvocationsByName(member.name);
+              Iterable<Selector> selectors =
+                  _codegenWorld.getterInvocationsByName(member.name);
               if (selectors != null && !selectors.isEmpty) {
-                for (var selector in selectors.keys) {
-                  var stubName = _namer.invocationName(selector);
+                for (Selector selector in selectors) {
+                  js.Name stubName = _namer.invocationName(selector);
                   if (stubNames.add(stubName.key)) {
                     interceptorClass.callStubs.add(_buildStubMethod(stubName,
                         js.js('function(obj) { return obj.# }', [jsName]),
@@ -518,8 +513,8 @@
             }
 
             if (member.isSetter || (member.isField && !member.isConst)) {
-              var selectors =
-                  _worldBuilder.setterInvocationsByName(member.name);
+              Iterable<Selector> selectors =
+                  _codegenWorld.setterInvocationsByName(member.name);
               if (selectors != null && !selectors.isEmpty) {
                 var stubName = _namer.setterForMember(member);
                 if (stubNames.add(stubName.key)) {
@@ -552,7 +547,7 @@
                 minArgs = 0;
                 maxArgs = 32767;
               }
-              var selectors = _worldBuilder.invocationsByName(member.name);
+              var selectors = _codegenWorld.invocationsByName(member.name);
               // Named arguments are not yet supported. In the future we
               // may want to map named arguments to an object literal containing
               // all named arguments.
@@ -640,7 +635,7 @@
     List<StubMethod> callStubs = <StubMethod>[];
 
     ClassStubGenerator classStubGenerator = new ClassStubGenerator(
-        _task.emitter, _commonElements, _namer, _worldBuilder, _closedWorld,
+        _task.emitter, _commonElements, _namer, _codegenWorld, _closedWorld,
         enableMinification: _options.enableMinification);
     RuntimeTypeGenerator runtimeTypeGenerator = new RuntimeTypeGenerator(
         _commonElements,
@@ -659,7 +654,7 @@
       }
       if (member.isGetter || member.isField) {
         Map<Selector, SelectorConstraints> selectors =
-            _worldBuilder.invocationsByName(member.name);
+            _codegenWorld.invocationsByName(member.name);
         if (selectors != null && !selectors.isEmpty) {
           Map<js.Name, js.Expression> callStubsForMember =
               classStubGenerator.generateCallStubsForGetter(member, selectors);
@@ -765,11 +760,11 @@
           assert(!field.needsUncheckedSetter);
           FieldEntity element = field.element;
           js.Expression code = _generatedCode[element];
+          assert(code != null, "No setter code for field: $field");
           if (code == null) {
-            // TODO(johnniwinther): Static types are not honoured in the dynamic
-            // uses created in codegen, leading to dead code, as known by the
-            // closed world computation, being triggered by the codegen
-            // enqueuer. We cautiously generate an empty function for this case.
+            // This should never occur because codegen member usage is now
+            // limited by closed world member usage. In the case we've missed a
+            // spot we cautiously generate an empty function.
             code = js.js("function() {}");
           }
           js.Name name = _namer.deriveSetterName(field.accessorName);
@@ -788,7 +783,7 @@
     // building a class.
     Holder holder = _registry.registerHolder(holderName);
     bool isInstantiated = !_nativeData.isJsInteropClass(cls) &&
-        _worldBuilder.directlyInstantiatedClasses.contains(cls);
+        _codegenWorld.directlyInstantiatedClasses.contains(cls);
 
     Class result;
     if (_elementEnvironment.isMixinApplication(cls) &&
@@ -853,7 +848,7 @@
     ParameterStructure parameterStructure = method.parameterStructure;
     if (parameterStructure.namedParameters.isNotEmpty) {
       optionalParameterDefaultValues = new Map<String, ConstantValue>();
-      _worldBuilder.forEachParameter(method,
+      _elementEnvironment.forEachParameter(method,
           (DartType type, String name, ConstantValue defaultValue) {
         if (parameterStructure.namedParameters.contains(name)) {
           assert(defaultValue != null);
@@ -863,7 +858,7 @@
     } else {
       optionalParameterDefaultValues = <ConstantValue>[];
       int index = 0;
-      _worldBuilder.forEachParameter(method,
+      _elementEnvironment.forEachParameter(method,
           (DartType type, String name, ConstantValue defaultValue) {
         if (index >= parameterStructure.requiredParameters) {
           optionalParameterDefaultValues.add(defaultValue);
@@ -889,7 +884,7 @@
 
     bool canBeApplied = _methodCanBeApplied(element);
 
-    js.Name aliasName = _superMemberData.isAliasedSuperMember(element)
+    js.Name aliasName = _codegenWorld.isAliasedSuperMember(element)
         ? _namer.aliasedSuperMemberPropertyName(element)
         : null;
 
@@ -901,9 +896,8 @@
         isClosureCallMethod = true;
       } else {
         // Careful with operators.
-        canTearOff = _worldBuilder.hasInvokedGetter(element);
-        assert(canTearOff ||
-            !_worldBuilder.methodsNeedingSuperGetter.contains(element));
+        canTearOff = _codegenWorld.hasInvokedGetter(element) ||
+            _codegenWorld.methodsNeedsSuperGetter(element);
         tearOffName = _namer.getterForElement(element);
       }
     }
@@ -960,7 +954,8 @@
       FunctionType type, OutputUnit outputUnit) {
     if (type.containsTypeVariables) {
       js.Expression thisAccess = js.js(r'this.$receiver');
-      return _rtiEncoder.getSignatureEncoding(_task.emitter, type, thisAccess);
+      return _rtiEncoder.getSignatureEncoding(
+          _namer, _task.emitter, type, thisAccess);
     } else {
       return _task.metadataCollector.reifyType(type, outputUnit);
     }
@@ -971,12 +966,13 @@
     if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[];
 
     ParameterStubGenerator generator = new ParameterStubGenerator(
-        _task,
+        _task.emitter,
+        _task.nativeEmitter,
         _namer,
         _rtiEncoder,
         _nativeData,
         _interceptorData,
-        _worldBuilder,
+        _codegenWorld,
         _closedWorld,
         _sourceInformationStrategy);
     return generator.generateParameterStubs(element,
@@ -985,12 +981,7 @@
 
   List<StubMethod> _generateInstantiationStubs(ClassEntity instantiationClass) {
     InstantiationStubGenerator generator = new InstantiationStubGenerator(
-        _task,
-        _commonElements,
-        _namer,
-        _worldBuilder,
-        _closedWorld,
-        _sourceInformationStrategy);
+        _task, _namer, _closedWorld, _codegenWorld, _sourceInformationStrategy);
     return generator.generateStubs(instantiationClass, null);
   }
 
@@ -1007,11 +998,10 @@
   // We must evaluate these classes eagerly so that the prototype is
   // accessible.
   void _markEagerInterceptorClasses() {
-    Iterable<js.Name> names =
-        _oneShotInterceptorData.specializedGetInterceptorNames;
-    for (js.Name name in names) {
-      for (ClassEntity element
-          in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) {
+    Iterable<SpecializedGetInterceptor> interceptors =
+        _oneShotInterceptorData.specializedGetInterceptors;
+    for (SpecializedGetInterceptor interceptor in interceptors) {
+      for (ClassEntity element in interceptor.classes) {
         Class cls = _classes[element];
         if (cls != null) cls.isEager = true;
       }
@@ -1022,12 +1012,11 @@
     InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
         _options,
         _commonElements,
-        _task,
+        _task.emitter,
         _nativeCodegenEnqueuer,
         _namer,
-        _oneShotInterceptorData,
         _customElementsCodegenAnalysis,
-        _worldBuilder,
+        _codegenWorld,
         _closedWorld);
 
     String holderName =
@@ -1035,13 +1024,23 @@
     // TODO(floitsch): we shouldn't update the registry in the middle of
     // generating the interceptor methods.
     Holder holder = _registry.registerHolder(holderName);
-
-    Iterable<js.Name> names =
-        _oneShotInterceptorData.specializedGetInterceptorNames;
+    List<js.Name> names = [];
+    Map<js.Name, SpecializedGetInterceptor> interceptorMap = {};
+    for (SpecializedGetInterceptor interceptor
+        in _oneShotInterceptorData.specializedGetInterceptors) {
+      js.Name name = _namer.nameForGetInterceptor(interceptor.classes);
+      names.add(name);
+      assert(
+          !interceptorMap.containsKey(name),
+          "Duplicate specialized get interceptor for $name: Existing: "
+          "${interceptorMap[name]}, new ${interceptor}.");
+      interceptorMap[name] = interceptor;
+    }
+    names.sort();
     return names.map((js.Name name) {
-      Set<ClassEntity> classes =
-          _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name);
-      js.Expression code = stubGenerator.generateGetInterceptorMethod(classes);
+      SpecializedGetInterceptor interceptor = interceptorMap[name];
+      js.Expression code =
+          stubGenerator.generateGetInterceptorMethod(interceptor);
       return new StaticStubMethod(name, holder, code);
     });
   }
@@ -1107,7 +1106,7 @@
     }
 
     FieldVisitor visitor = new FieldVisitor(_options, _elementEnvironment,
-        _commonElements, _worldBuilder, _nativeData, _namer, _closedWorld);
+        _commonElements, _codegenWorld, _nativeData, _namer, _closedWorld);
     visitor.visitFields(visitField,
         visitStatics: visitStatics, library: library, cls: cls);
 
@@ -1118,12 +1117,11 @@
     InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
         _options,
         _commonElements,
-        _task,
+        _task.emitter,
         _nativeCodegenEnqueuer,
         _namer,
-        _oneShotInterceptorData,
         _customElementsCodegenAnalysis,
-        _worldBuilder,
+        _codegenWorld,
         _closedWorld);
 
     String holderName =
@@ -1131,10 +1129,24 @@
     // TODO(floitsch): we shouldn't update the registry in the middle of
     // generating the interceptor methods.
     Holder holder = _registry.registerHolder(holderName);
-
-    List<js.Name> names = _oneShotInterceptorData.oneShotInterceptorNames;
+    List<js.Name> names = [];
+    Map<js.Name, OneShotInterceptor> interceptorMap = {};
+    for (OneShotInterceptor interceptor
+        in _oneShotInterceptorData.oneShotInterceptors) {
+      js.Name name = _namer.nameForOneShotInterceptor(
+          interceptor.selector, interceptor.classes);
+      names.add(name);
+      assert(
+          !interceptorMap.containsKey(name),
+          "Duplicate specialized get interceptor for $name: Existing: "
+          "${interceptorMap[name]}, new ${interceptor}.");
+      interceptorMap[name] = interceptor;
+    }
+    names.sort();
     return names.map((js.Name name) {
-      js.Expression code = stubGenerator.generateOneShotInterceptor(name);
+      OneShotInterceptor interceptor = interceptorMap[name];
+      js.Expression code =
+          stubGenerator.generateOneShotInterceptor(interceptor);
       return new StaticStubMethod(name, holder, code);
     });
   }
@@ -1148,8 +1160,8 @@
         !element.isConstructor && !element.isGetter && !element.isSetter;
     bool canBeApplied = _methodCanBeApplied(element);
 
-    bool needsTearOff = isApplyTarget &&
-        _worldBuilder.staticFunctionsNeedingGetter.contains(element);
+    bool needsTearOff =
+        isApplyTarget && _codegenWorld.closurizedStatics.contains(element);
 
     js.Name tearOffName =
         needsTearOff ? _namer.staticClosureName(element) : null;
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 02cdf45..d82e130 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -16,6 +16,7 @@
     show
         ClassChecks,
         ClassFunctionType,
+        OnVariableCallback,
         RuntimeTypesChecks,
         RuntimeTypesEncoder,
         Substitution,
@@ -23,7 +24,7 @@
 import '../js_emitter/sorter.dart';
 import '../util/util.dart' show Setlet;
 
-import 'code_emitter_task.dart' show CodeEmitterTask;
+import 'code_emitter_task.dart' show CodeEmitterTask, Emitter;
 
 // Function signatures used in the generation of runtime type information.
 typedef void FunctionTypeSignatureEmitter(ClassFunctionType classFunctionType);
@@ -172,7 +173,7 @@
         }
         if (encoding != null) {
           jsAst.Name operatorSignature =
-              _namer.asName(_namer.operatorSignature);
+              _namer.asName(_namer.fixedNames.operatorSignature);
           result.addSignature(classElement, operatorSignature, encoding);
         }
       }
@@ -187,7 +188,7 @@
       Substitution substitution = check.substitution;
       if (substitution != null) {
         jsAst.Expression body =
-            _rtiEncoder.getSubstitutionCode(emitterTask.emitter, substitution);
+            _getSubstitutionCode(emitterTask.emitter, substitution);
         result.addSubstitution(
             checkedClass, _namer.substitutionName(checkedClass), body);
       }
@@ -201,14 +202,80 @@
       if (type != null) {
         jsAst.Expression thisAccess = new jsAst.This();
         jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding(
-            emitterTask.emitter, type, thisAccess);
-        jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
+            _namer, emitterTask.emitter, type, thisAccess);
+        jsAst.Name operatorSignature =
+            _namer.asName(_namer.fixedNames.operatorSignature);
         result.addSignature(classElement, operatorSignature, encoding);
       }
     }
     return result;
   }
 
+  /// Compute a JavaScript expression that describes the necessary substitution
+  /// for type arguments in a subtype test.
+  ///
+  /// The result can be:
+  ///  1) `null`, if no substituted check is necessary, because the type
+  ///     variables are the same or there are no type variables in the class
+  ///     that is checked for.
+  ///  2) A list expression describing the type arguments to be used in the
+  ///     subtype check, if the type arguments to be used in the check do not
+  ///     depend on the type arguments of the object.
+  ///  3) A function mapping the type variables of the object to be checked to
+  ///     a list expression.
+  jsAst.Expression _getSubstitutionCode(
+      Emitter emitter, Substitution substitution) {
+    if (substitution.isTrivial) {
+      return new jsAst.LiteralNull();
+    }
+
+    if (substitution.isJsInterop) {
+      return js('function() { return # }',
+          _rtiEncoder.getJsInteropTypeArguments(substitution.length));
+    }
+
+    jsAst.Expression declaration(TypeVariableType variable) {
+      return new jsAst.Parameter(_getVariableName(variable.element.name));
+    }
+
+    jsAst.Expression use(TypeVariableType variable) {
+      return new jsAst.VariableUse(_getVariableName(variable.element.name));
+    }
+
+    if (substitution.arguments.every((DartType type) => type.isDynamic)) {
+      return emitter.generateFunctionThatReturnsNull();
+    } else {
+      jsAst.Expression value =
+          _getSubstitutionRepresentation(emitter, substitution.arguments, use);
+      if (substitution.isFunction) {
+        Iterable<jsAst.Expression> formals =
+            // TODO(johnniwinther): Pass [declaration] directly to `map` when
+            // `substitution.parameters` can no longer be a
+            // `List<ResolutionDartType>`.
+            substitution.parameters.map((type) => declaration(type));
+        return js('function(#) { return # }', [formals, value]);
+      } else {
+        return js('function() { return # }', value);
+      }
+    }
+  }
+
+  jsAst.Expression _getSubstitutionRepresentation(
+      Emitter emitter, List<DartType> types, OnVariableCallback onVariable) {
+    List<jsAst.Expression> elements = types
+        .map((DartType type) =>
+            _rtiEncoder.getTypeRepresentation(emitter, type, onVariable))
+        .toList(growable: false);
+    return new jsAst.ArrayInitializer(elements);
+  }
+
+  String _getVariableName(String name) {
+    // Kernel type variable names for anonymous mixin applications have names
+    // canonicalized to a non-identified, e.g. '#U0'.
+    name = name.replaceAll('#', '_');
+    return _namer.safeVariableName(name);
+  }
+
   void _generateIsTestsOn(
       ClassEntity cls,
       FunctionTypeSignatureEmitter generateFunctionTypeSignature,
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 75acab7..c664a0f 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -4,69 +4,191 @@
 
 library dart2js.js_emitter.startup_emitter;
 
-import 'package:js_runtime/shared/embedded_names.dart'
-    show JsBuiltin, METADATA, TYPES;
-
+import '../../../compiler_new.dart';
 import '../../common.dart';
-import '../../compiler.dart' show Compiler;
-import '../../constants/values.dart' show ConstantValue;
+import '../../common/codegen.dart';
+import '../../common/tasks.dart';
+import '../../constants/values.dart';
 import '../../deferred_load.dart' show OutputUnit;
+import '../../dump_info.dart';
 import '../../elements/entities.dart';
+import '../../io/source_information.dart';
 import '../../js/js.dart' as js;
-import '../../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
+import '../../js_backend/constant_emitter.dart';
+import '../../js_backend/namer.dart';
+import '../../js_backend/runtime_types.dart';
+import '../../options.dart';
+import '../../universe/codegen_world_builder.dart' show CodegenWorld;
 import '../../world.dart' show JClosedWorld;
-import '../js_emitter.dart' show CodeEmitterTask, NativeEmitter;
-import '../js_emitter.dart' as emitterTask show EmitterBase, EmitterFactory;
+import '../js_emitter.dart' show Emitter, ModularEmitter;
 import '../model.dart';
 import '../program_builder/program_builder.dart' show ProgramBuilder;
-import '../sorter.dart' show Sorter;
 import 'model_emitter.dart';
 
-class EmitterFactory implements emitterTask.EmitterFactory {
-  final bool generateSourceMap;
+abstract class ModularEmitterBase implements ModularEmitter {
+  final ModularNamer _namer;
 
-  EmitterFactory({this.generateSourceMap});
+  ModularEmitterBase(this._namer);
+
+  js.PropertyAccess globalPropertyAccessForClass(ClassEntity element) {
+    js.Name name = _namer.globalPropertyNameForClass(element);
+    js.PropertyAccess pa =
+        new js.PropertyAccess(_namer.readGlobalObjectForClass(element), name);
+    return pa;
+  }
+
+  js.PropertyAccess globalPropertyAccessForType(Entity element) {
+    js.Name name = _namer.globalPropertyNameForType(element);
+    js.PropertyAccess pa =
+        new js.PropertyAccess(_namer.readGlobalObjectForType(element), name);
+    return pa;
+  }
+
+  js.PropertyAccess globalPropertyAccessForMember(MemberEntity element) {
+    js.Name name = _namer.globalPropertyNameForMember(element);
+    js.PropertyAccess pa =
+        new js.PropertyAccess(_namer.readGlobalObjectForMember(element), name);
+    return pa;
+  }
 
   @override
-  bool get supportsReflection => false;
+  js.PropertyAccess constructorAccess(ClassEntity element) {
+    return globalPropertyAccessForClass(element);
+  }
 
   @override
-  Emitter createEmitter(CodeEmitterTask task, Namer namer,
-      JClosedWorld closedWorld, Sorter sorter) {
-    return new Emitter(task.compiler, namer, task.nativeEmitter, closedWorld,
-        sorter, task, generateSourceMap);
+  js.Expression isolateLazyInitializerAccess(FieldEntity element) {
+    return new js.PropertyAccess(_namer.readGlobalObjectForMember(element),
+        _namer.lazyInitializerName(element));
+  }
+
+  @override
+  js.PropertyAccess staticFunctionAccess(FunctionEntity element) {
+    return globalPropertyAccessForMember(element);
+  }
+
+  @override
+  js.PropertyAccess staticFieldAccess(FieldEntity element) {
+    return globalPropertyAccessForMember(element);
+  }
+
+  @override
+  js.PropertyAccess prototypeAccess(ClassEntity element,
+      {bool hasBeenInstantiated}) {
+    js.Expression constructor =
+        hasBeenInstantiated ? constructorAccess(element) : typeAccess(element);
+    return js.js('#.prototype', constructor);
+  }
+
+  @override
+  js.Expression typeAccess(Entity element) {
+    return globalPropertyAccessForType(element);
+  }
+
+  @override
+  js.Expression staticClosureAccess(FunctionEntity element) {
+    return new js.Call(
+        new js.PropertyAccess(_namer.readGlobalObjectForMember(element),
+            _namer.staticClosureName(element)),
+        const []);
+  }
+
+  @override
+  String generateEmbeddedGlobalAccessString(String global) {
+    // TODO(floitsch): don't use 'init' as global embedder storage.
+    return 'init.$global';
   }
 }
 
-class Emitter extends emitterTask.EmitterBase {
-  final Compiler _compiler;
+class ModularEmitterImpl extends ModularEmitterBase {
+  final CodegenRegistry _registry;
+  final ModularConstantEmitter _constantEmitter;
+
+  ModularEmitterImpl(
+      ModularNamer namer, this._registry, CompilerOptions options)
+      : _constantEmitter = new ModularConstantEmitter(options),
+        super(namer);
+
+  @override
+  js.Expression constantReference(ConstantValue constant) {
+    if (constant.isFunction) {
+      FunctionConstantValue function = constant;
+      return staticClosureAccess(function.element);
+    }
+    js.Expression expression = _constantEmitter.generate(constant);
+    if (expression != null) {
+      return expression;
+    }
+    expression =
+        new ModularExpression(ModularExpressionKind.constant, constant);
+    _registry.registerModularExpression(expression);
+    return expression;
+  }
+
+  @override
+  js.Expression generateEmbeddedGlobalAccess(String global) {
+    js.Expression expression = new ModularExpression(
+        ModularExpressionKind.embeddedGlobalAccess, global);
+    _registry.registerModularExpression(expression);
+    return expression;
+  }
+}
+
+class EmitterImpl extends ModularEmitterBase implements Emitter {
+  final DiagnosticReporter _reporter;
   final JClosedWorld _closedWorld;
+  final RuntimeTypesEncoder _rtiEncoder;
+  final CompilerTask _task;
+  ModelEmitter _emitter;
+
   @override
-  final Namer namer;
-  final ModelEmitter _emitter;
+  Program programForTesting;
 
-  JavaScriptBackend get _backend => _compiler.backend;
-
-  Emitter(
-      this._compiler,
-      this.namer,
-      NativeEmitter nativeEmitter,
+  EmitterImpl(
+      CompilerOptions options,
+      this._reporter,
+      CompilerOutput outputProvider,
+      DumpInfoTask dumpInfoTask,
+      Namer namer,
       this._closedWorld,
-      Sorter sorter,
-      CodeEmitterTask task,
+      this._rtiEncoder,
+      SourceInformationStrategy sourceInformationStrategy,
+      this._task,
       bool shouldGenerateSourceMap)
-      : _emitter = new ModelEmitter(_compiler, namer, nativeEmitter,
-            _closedWorld, sorter, task, shouldGenerateSourceMap);
-
-  DiagnosticReporter get reporter => _compiler.reporter;
+      : super(namer) {
+    _emitter = new ModelEmitter(
+        options,
+        _reporter,
+        outputProvider,
+        dumpInfoTask,
+        namer,
+        _closedWorld,
+        _task,
+        this,
+        sourceInformationStrategy,
+        _rtiEncoder,
+        shouldGenerateSourceMap);
+  }
 
   @override
-  int emitProgram(ProgramBuilder programBuilder) {
-    Program program = programBuilder.buildProgram();
+  Namer get _namer => super._namer;
+
+  @override
+  int emitProgram(ProgramBuilder programBuilder, CodegenWorld codegenWorld) {
+    Program program = _task.measureSubtask('build program', () {
+      return programBuilder.buildProgram();
+    });
     if (retainDataForTesting) {
       programForTesting = program;
     }
-    return _emitter.emitProgram(program);
+    return _task.measureSubtask('emit program', () {
+      return _emitter.emitProgram(program, codegenWorld);
+    });
+  }
+
+  @override
+  js.Expression interceptorClassAccess(ClassEntity element) {
+    return globalPropertyAccessForClass(element);
   }
 
   @override
@@ -86,7 +208,7 @@
 
   @override
   js.Expression generateEmbeddedGlobalAccess(String global) {
-    return _emitter.generateEmbeddedGlobalAccess(global);
+    return js.js(generateEmbeddedGlobalAccessString(global));
   }
 
   @override
@@ -96,81 +218,8 @@
   }
 
   @override
-  js.Expression isolateLazyInitializerAccess(FieldEntity element) {
-    return js.js('#.#', [
-      namer.globalObjectForMember(element),
-      namer.lazyInitializerName(element)
-    ]);
-  }
-
-  @override
-  js.Expression isolateStaticClosureAccess(FunctionEntity element) {
-    return _emitter.generateStaticClosureAccess(element);
-  }
-
-  @override
-  js.PropertyAccess prototypeAccess(
-      ClassEntity element, bool hasBeenInstantiated) {
-    js.Expression constructor =
-        hasBeenInstantiated ? constructorAccess(element) : typeAccess(element);
-    return js.js('#.prototype', constructor);
-  }
-
-  @override
-  js.Template templateForBuiltin(JsBuiltin builtin) {
-    switch (builtin) {
-      case JsBuiltin.dartObjectConstructor:
-        ClassEntity objectClass = _closedWorld.commonElements.objectClass;
-        return js.js.expressionTemplateYielding(typeAccess(objectClass));
-
-      case JsBuiltin.isCheckPropertyToJsConstructorName:
-        int isPrefixLength = namer.operatorIsPrefix.length;
-        return js.js.expressionTemplateFor('#.substring($isPrefixLength)');
-
-      case JsBuiltin.isFunctionType:
-        return _backend.rtiEncoder.templateForIsFunctionType;
-
-      case JsBuiltin.isFutureOrType:
-        return _backend.rtiEncoder.templateForIsFutureOrType;
-
-      case JsBuiltin.isVoidType:
-        return _backend.rtiEncoder.templateForIsVoidType;
-
-      case JsBuiltin.isDynamicType:
-        return _backend.rtiEncoder.templateForIsDynamicType;
-
-      case JsBuiltin.isJsInteropTypeArgument:
-        return _backend.rtiEncoder.templateForIsJsInteropTypeArgument;
-
-      case JsBuiltin.rawRtiToJsConstructorName:
-        return js.js.expressionTemplateFor("#.name");
-
-      case JsBuiltin.rawRuntimeType:
-        return js.js.expressionTemplateFor("#.constructor");
-
-      case JsBuiltin.isSubtype:
-        // TODO(floitsch): move this closer to where is-check properties are
-        // built.
-        String isPrefix = namer.operatorIsPrefix;
-        return js.js.expressionTemplateFor("('$isPrefix' + #) in #.prototype");
-
-      case JsBuiltin.isGivenTypeRti:
-        return js.js.expressionTemplateFor('#.name === #');
-
-      case JsBuiltin.getMetadata:
-        String metadataAccess =
-            _emitter.generateEmbeddedGlobalAccessString(METADATA);
-        return js.js.expressionTemplateFor("$metadataAccess[#]");
-
-      case JsBuiltin.getType:
-        String typesAccess = _emitter.generateEmbeddedGlobalAccessString(TYPES);
-        return js.js.expressionTemplateFor("$typesAccess[#]");
-
-      default:
-        reporter.internalError(
-            NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin");
-        return null;
-    }
+  js.Expression interceptorPrototypeAccess(ClassEntity e) {
+    return js.js('#.prototype', interceptorClassAccess(e));
   }
 
   @override
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 1cac12f..0e58794 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
@@ -569,39 +569,48 @@
 ///
 /// This class is stateless and can be reused for different fragments.
 class FragmentEmitter {
-  final Compiler compiler;
-  final Namer namer;
-  final JavaScriptBackend backend;
-  final ConstantEmitter constantEmitter;
-  final ModelEmitter modelEmitter;
+  final CompilerOptions _options;
+  final DumpInfoTask _dumpInfoTask;
+  final Namer _namer;
+  final Emitter _emitter;
+  final ConstantEmitter _constantEmitter;
+  final ModelEmitter _modelEmitter;
   final JClosedWorld _closedWorld;
+  final CodegenWorld _codegenWorld;
 
   js.Name _call0Name, _call1Name, _call2Name;
   js.Name get call0Name =>
-      _call0Name ??= namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX0);
+      _call0Name ??= _namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX0);
   js.Name get call1Name =>
-      _call1Name ??= namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX1);
+      _call1Name ??= _namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX1);
   js.Name get call2Name =>
-      _call2Name ??= namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX2);
+      _call2Name ??= _namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX2);
 
-  FragmentEmitter(this.compiler, this.namer, this.backend, this.constantEmitter,
-      this.modelEmitter, this._closedWorld);
+  FragmentEmitter(
+      this._options,
+      this._dumpInfoTask,
+      this._namer,
+      this._emitter,
+      this._constantEmitter,
+      this._modelEmitter,
+      this._closedWorld,
+      this._codegenWorld);
 
   js.Expression generateEmbeddedGlobalAccess(String global) =>
-      modelEmitter.generateEmbeddedGlobalAccess(global);
+      _emitter.generateEmbeddedGlobalAccess(global);
 
   js.Expression generateConstantReference(ConstantValue value) =>
-      modelEmitter.generateConstantReference(value);
+      _modelEmitter.generateConstantReference(value);
 
   js.Expression classReference(Class cls) {
     return js.js('#.#', [cls.holder.name, cls.name]);
   }
 
   void registerEntityAst(Entity entity, js.Node code, {LibraryEntity library}) {
-    compiler.dumpInfoTask.registerEntityAst(entity, code);
+    _dumpInfoTask.registerEntityAst(entity, code);
     // TODO(sigmund): stop recoding associations twice, dump-info already
     // has library to element dependencies to recover this data.
-    if (library != null) compiler.dumpInfoTask.registerEntityAst(library, code);
+    if (library != null) _dumpInfoTask.registerEntityAst(library, code);
   }
 
   js.Statement emitMainFragment(
@@ -620,30 +629,30 @@
       // TODO(29455): 'hunkHelpers' displaces other names, so don't minify it.
       'hunkHelpers': js.VariableDeclaration('hunkHelpers', allowRename: false),
       'directAccessTestExpression': js.js(directAccessTestExpression),
-      'cyclicThrow': backend.emitter
+      'cyclicThrow': _emitter
           .staticFunctionAccess(_closedWorld.commonElements.cyclicThrowHelper),
-      'operatorIsPrefix': js.string(namer.operatorIsPrefix),
-      'tearOffCode': new js.Block(buildTearOffCode(compiler.options,
-          backend.emitter.emitter, backend.namer, _closedWorld.commonElements)),
+      'operatorIsPrefix': js.string(_namer.fixedNames.operatorIsPrefix),
+      'tearOffCode': new js.Block(buildTearOffCode(
+          _options, _emitter, _namer, _closedWorld.commonElements)),
       'embeddedTypes': generateEmbeddedGlobalAccess(TYPES),
       'embeddedInterceptorTags':
           generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG),
       'embeddedLeafTags': generateEmbeddedGlobalAccess(LEAF_TAGS),
       'embeddedGlobalsObject': js.js("init"),
       'staticStateDeclaration': new js.VariableDeclaration(
-          namer.staticStateHolder,
+          _namer.staticStateHolder,
           allowRename: false),
-      'staticState': js.js('#', namer.staticStateHolder),
+      'staticState': js.js('#', _namer.staticStateHolder),
       'constantHolderReference': buildConstantHolderReference(program),
       'holders': holderCode.statements,
-      'callName': js.string(namer.callNameField),
-      'stubName': js.string(namer.stubNameField),
-      'argumentCount': js.string(namer.requiredParameterField),
-      'defaultArgumentValues': js.string(namer.defaultValuesField),
+      'callName': js.string(_namer.fixedNames.callNameField),
+      'stubName': js.string(_namer.stubNameField),
+      'argumentCount': js.string(_namer.fixedNames.requiredParameterField),
+      'defaultArgumentValues': js.string(_namer.fixedNames.defaultValuesField),
       'deferredGlobal': ModelEmitter.deferredInitializersGlobal,
       'hasSoftDeferredClasses': program.hasSoftDeferredClasses,
       'softId': js.string(softDeferredId),
-      'isTrackingAllocations': compiler.options.experimentalTrackAllocations,
+      'isTrackingAllocations': _options.experimentalTrackAllocations,
       'prototypes': emitPrototypes(fragment),
       'inheritance': emitInheritance(fragment),
       'aliases': emitInstanceMethodAliases(fragment),
@@ -656,7 +665,7 @@
           ? emitNativeSupport(fragment)
           : new js.EmptyStatement(),
       'jsInteropSupport': jsInteropAnalysis.buildJsInteropBootstrap(
-              compiler.codegenWorldBuilder, _closedWorld.nativeData, namer) ??
+              _codegenWorld, _closedWorld.nativeData, _namer) ??
           new js.EmptyStatement(),
       'invokeMain': fragment.invokeMain,
 
@@ -671,7 +680,7 @@
           'softId': js.string(softDeferredId),
           // TODO(floitsch): don't just reference 'init'.
           'embeddedGlobalsObject': new js.Parameter('init'),
-          'staticState': new js.Parameter(namer.staticStateHolder),
+          'staticState': new js.Parameter(_namer.staticStateHolder),
           'installHoldersAsLocals':
               emitInstallHoldersAsLocals(nonStaticStateHolders),
           'prototypes': emitPrototypes(fragment, softDeferred: true),
@@ -762,7 +771,7 @@
     js.Expression code = js.js(deferredBoilerplateDart2, {
       // TODO(floitsch): don't just reference 'init'.
       'embeddedGlobalsObject': new js.Parameter('init'),
-      'staticState': new js.Parameter(namer.staticStateHolder),
+      'staticState': new js.Parameter(_namer.staticStateHolder),
       'holders': holderCode.statements,
       'deferredHoldersList': new js.ArrayInitializer(holderCode.activeHolders
           .map((holder) => js.js("#", holder.name))
@@ -778,10 +787,10 @@
       'lazyStatics': lazyInitializers,
       'types': deferredTypes,
       'nativeSupport': nativeSupport,
-      'typesOffset': namer.typesOffsetName,
+      'typesOffset': _namer.typesOffsetName,
     });
 
-    if (compiler.options.experimentStartupFunctions) {
+    if (_options.experimentStartupFunctions) {
       code = js.Parentheses(code);
     }
     return code;
@@ -808,8 +817,8 @@
     for (Library library in fragment.libraries) {
       for (StaticMethod method in library.statics) {
         assert(!method.holder.isStaticStateHolder);
-        var staticMethod = emitStaticMethod(method);
-        staticMethod.forEach((key, value) {
+        Map<js.Name, js.Expression> propertyMap = emitStaticMethod(method);
+        propertyMap.forEach((js.Name key, js.Expression value) {
           var property = new js.Property(js.quoteName(key), value);
           holderCode[method.holder].add(property);
           registerEntityAst(method.element, property, library: library.element);
@@ -817,7 +826,7 @@
       }
       for (Class cls in library.classes) {
         assert(!cls.holder.isStaticStateHolder);
-        var constructor = emitConstructor(cls);
+        js.Expression constructor = emitConstructor(cls);
         var property = new js.Property(js.quoteName(cls.name), constructor);
         registerEntityAst(cls.element, property, library: library.element);
         holderCode[cls.holder].add(property);
@@ -914,7 +923,7 @@
 
     if (cls.isSoftDeferred) {
       statements.add(js.js.statement('softDef(this)'));
-    } else if (compiler.options.experimentalTrackAllocations) {
+    } else if (_options.experimentalTrackAllocations) {
       String qualifiedName =
           "${cls.element.library.canonicalUri}:${cls.element.name}";
       statements.add(js.js.statement('allocations["$qualifiedName"] = true'));
@@ -959,7 +968,7 @@
           assignment = js.js('#.# = #', [
             thisRef,
             field.name,
-            constantEmitter.generate(constant),
+            _constantEmitter.generate(constant),
           ]);
         }
         ++chainLength;
@@ -978,7 +987,7 @@
       js.Parameter parameter = new js.Parameter('t${parameters.length}');
       parameters.add(parameter);
       statements.add(js.js.statement(
-          '#.# = #', [thisRef, namer.rtiFieldJsName, parameter.name]));
+          '#.# = #', [thisRef, _namer.rtiFieldJsName, parameter.name]));
     }
 
     return js.js('function #(#) { # }', [name, parameters, statements]);
@@ -1046,7 +1055,7 @@
       // TODO(sra): What is this doing? Document or remove.
       properties
           .add(js.Property(js.string("constructor"), classReference(cls)));
-      properties.add(js.Property(namer.operatorIs(cls.element), js.number(1)));
+      properties.add(js.Property(_namer.operatorIs(cls.element), js.number(1)));
     }
 
     allMethods.forEach((Method method) {
@@ -1063,14 +1072,15 @@
       // prototype for common values.
 
       // Closures taking exactly one argument are common.
+      properties.add(js.Property(js.string(_namer.fixedNames.callCatchAllName),
+          js.quoteName(call1Name)));
       properties.add(js.Property(
-          js.string(namer.callCatchAllName), js.quoteName(call1Name)));
-      properties.add(
-          js.Property(js.string(namer.requiredParameterField), js.number(1)));
+          js.string(_namer.fixedNames.requiredParameterField), js.number(1)));
 
       // Most closures have no optional arguments.
       properties.add(js.Property(
-          js.string(namer.defaultValuesField), new js.LiteralNull()));
+          js.string(_namer.fixedNames.defaultValuesField),
+          new js.LiteralNull()));
     }
 
     return new js.ObjectInitializer(properties);
@@ -1083,11 +1093,12 @@
     js.Expression code;
     if (field.isElided) {
       ConstantValue constantValue = field.constantValue;
+      assert(
+          constantValue != null, "No constant value for elided field: $field");
       if (constantValue == null) {
-        // TODO(johnniwinther): Static types are not honoured in the dynamic
-        // uses created in codegen, leading to dead code, as known by the closed
-        // world computation, being triggered by the codegen enqueuer. We
-        // cautiously generate a null constant for this case.
+        // This should never occur because codegen member usage is now limited
+        // by closed world member usage. In the case we've missed a spot we
+        // cautiously generate a null constant.
         constantValue = new NullConstantValue();
       }
       code = js.js(
@@ -1105,7 +1116,7 @@
       js.Expression fieldName = js.quoteName(field.name);
       code = js.js(template, fieldName);
     }
-    js.Name getterName = namer.deriveGetterName(field.accessorName);
+    js.Name getterName = _namer.deriveGetterName(field.accessorName);
     return new StubMethod(getterName, code);
   }
 
@@ -1130,7 +1141,7 @@
       code = js.js(template, fieldName);
     }
 
-    js.Name setterName = namer.deriveSetterName(field.accessorName);
+    js.Name setterName = _namer.deriveSetterName(field.accessorName);
     return new StubMethod(setterName, code);
   }
 
@@ -1179,12 +1190,12 @@
           js.Name applyName = method.applyIndex == 0
               ? method.name
               : method.parameterStubs[method.applyIndex - 1].name;
-          properties[js.string(namer.callCatchAllName)] =
+          properties[js.string(_namer.fixedNames.callCatchAllName)] =
               js.quoteName(applyName);
         }
         // Common case of '1' is stored on the Closure class.
         if (method.requiredParameterCount != 1 || forceAdd) {
-          properties[js.string(namer.requiredParameterField)] =
+          properties[js.string(_namer.fixedNames.requiredParameterField)] =
               js.number(method.requiredParameterCount);
         }
 
@@ -1193,7 +1204,8 @@
         // Default values property of `null` is stored on the common JS
         // superclass.
         if (defaultValues is! js.LiteralNull || forceAdd) {
-          properties[js.string(namer.defaultValuesField)] = defaultValues;
+          properties[js.string(_namer.fixedNames.defaultValuesField)] =
+              defaultValues;
         }
       }
     }
@@ -1578,9 +1590,9 @@
       var assignment = js.js.statement('#.# = #', [
         constant.holder.name,
         constant.name,
-        constantEmitter.generate(constant.value)
+        _constantEmitter.generate(constant.value)
       ]);
-      compiler.dumpInfoTask.registerConstantAst(constant.value, assignment);
+      _dumpInfoTask.registerConstantAst(constant.value, assignment);
       assignments.add(assignment);
       if (constant.value.isList) hasList = true;
     }
@@ -1623,6 +1635,7 @@
         // avoid redundant declaration of local variable, for instance for
         // type arguments.
         js.Fun code = field.code;
+        assert(code != null, "No code for $field");
         if (code.params.isEmpty &&
             code.body.statements.length == 1 &&
             code.body.statements.last is js.Return) {
@@ -1798,7 +1811,7 @@
     // TODO(floitsch): this should probably be on a per-fragment basis.
     nativeClassesNeedingUnmangledName.forEach((element) {
       names.add(new js.Property(
-          js.quoteName(namer.className(element)), js.string(element.name)));
+          js.quoteName(_namer.className(element)), js.string(element.name)));
     });
 
     return new js.Property(
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 3233491..78b6164 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -31,47 +31,52 @@
 
 import '../../../compiler_new.dart';
 import '../../common.dart';
-import '../../compiler.dart' show Compiler;
+import '../../common/tasks.dart';
 import '../../constants/values.dart'
     show ConstantValue, FunctionConstantValue, NullConstantValue;
 import '../../common_elements.dart' show CommonElements;
+import '../../dump_info.dart';
 import '../../elements/entities.dart';
 import '../../hash/sha1.dart' show Hasher;
 import '../../io/code_output.dart';
 import '../../io/location_provider.dart' show LocationCollector;
+import '../../io/source_information.dart';
 import '../../io/source_map_builder.dart' show SourceMapBuilder;
 import '../../js/js.dart' as js;
 import '../../js_backend/js_backend.dart'
-    show JavaScriptBackend, Namer, ConstantEmitter, StringBackedName;
+    show Namer, ConstantEmitter, StringBackedName;
 import '../../js_backend/js_interop_analysis.dart' as jsInteropAnalysis;
+import '../../js_backend/runtime_types.dart';
+import '../../options.dart';
+import '../../universe/codegen_world_builder.dart' show CodegenWorld;
 import '../../world.dart';
 import '../code_emitter_task.dart';
 import '../constant_ordering.dart' show ConstantOrdering;
 import '../headers.dart';
-import '../js_emitter.dart' show NativeEmitter;
 import '../js_emitter.dart' show buildTearOffCode, NativeGenerator;
 import '../model.dart';
-import '../sorter.dart' show Sorter;
 
 part 'fragment_emitter.dart';
 
 class ModelEmitter {
-  final Compiler compiler;
-  final Namer namer;
-  final CodeEmitterTask task;
-  ConstantEmitter constantEmitter;
-  final NativeEmitter nativeEmitter;
-  final bool shouldGenerateSourceMap;
+  final CompilerOptions _options;
+  final DiagnosticReporter _reporter;
+  final CompilerOutput _outputProvider;
+  final DumpInfoTask _dumpInfoTask;
+  final Namer _namer;
+  final CompilerTask _task;
+  final Emitter _emitter;
+  ConstantEmitter _constantEmitter;
+  final bool _shouldGenerateSourceMap;
   final JClosedWorld _closedWorld;
   final ConstantOrdering _constantOrdering;
+  final SourceInformationStrategy _sourceInformationStrategy;
 
   // The full code that is written to each hunk part-file.
   final Map<Fragment, CodeOutput> outputBuffers = {};
 
   Set<Fragment> omittedFragments = Set();
 
-  JavaScriptBackend get backend => compiler.backend;
-
   /// For deferred loading we communicate the initializers via this global var.
   static const String deferredInitializersGlobal =
       r"$__dart_deferred_initializers__";
@@ -81,37 +86,36 @@
 
   static const String typeNameProperty = r"builtin$cls";
 
-  ModelEmitter(this.compiler, this.namer, this.nativeEmitter, this._closedWorld,
-      Sorter sorter, this.task, this.shouldGenerateSourceMap)
-      : _constantOrdering = new ConstantOrdering(sorter) {
-    this.constantEmitter = new ConstantEmitter(
-        compiler.options,
+  ModelEmitter(
+      this._options,
+      this._reporter,
+      this._outputProvider,
+      this._dumpInfoTask,
+      this._namer,
+      this._closedWorld,
+      this._task,
+      this._emitter,
+      this._sourceInformationStrategy,
+      RuntimeTypesEncoder rtiEncoder,
+      this._shouldGenerateSourceMap)
+      : _constantOrdering = new ConstantOrdering(_closedWorld.sorter) {
+    this._constantEmitter = new ConstantEmitter(
+        _options,
         _closedWorld.commonElements,
-        compiler.codegenWorldBuilder,
+        _closedWorld.elementEnvironment,
         _closedWorld.rtiNeed,
-        compiler.backend.rtiEncoder,
+        rtiEncoder,
         _closedWorld.fieldAnalysis,
-        task,
+        _emitter,
         this.generateConstantReference,
         constantListGenerator);
   }
 
-  DiagnosticReporter get reporter => compiler.reporter;
-
   js.Expression constantListGenerator(js.Expression array) {
     // TODO(floitsch): remove hard-coded name.
     return js.js('makeConstList(#)', [array]);
   }
 
-  js.Expression generateEmbeddedGlobalAccess(String global) {
-    return js.js(generateEmbeddedGlobalAccessString(global));
-  }
-
-  String generateEmbeddedGlobalAccessString(String global) {
-    // TODO(floitsch): don't use 'init' as global embedder storage.
-    return 'init.$global';
-  }
-
   bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
     if (constant.isFunction) return true; // Already emitted.
     if (constant.isPrimitive) return true; // Inlined.
@@ -135,42 +139,42 @@
 
     // Sorting by the long name clusters constants with the same constructor
     // which compresses a tiny bit better.
-    int r = namer.constantLongName(a).compareTo(namer.constantLongName(b));
+    int r = _namer.constantLongName(a).compareTo(_namer.constantLongName(b));
     if (r != 0) return r;
 
     // Resolve collisions in the long name by using a structural order.
     return _constantOrdering.compare(a, b);
   }
 
-  js.Expression generateStaticClosureAccess(FunctionEntity element) {
-    return js.js('#.#()', [
-      namer.globalObjectForMember(element),
-      namer.staticClosureName(element)
-    ]);
-  }
-
   js.Expression generateConstantReference(ConstantValue value) {
     if (value.isFunction) {
       FunctionConstantValue functionConstant = value;
-      return generateStaticClosureAccess(functionConstant.element);
+      return _emitter.staticClosureAccess(functionConstant.element);
     }
 
     // We are only interested in the "isInlined" part, but it does not hurt to
     // test for the other predicates.
     if (isConstantInlinedOrAlreadyEmitted(value)) {
-      return constantEmitter.generate(value);
+      return _constantEmitter.generate(value);
     }
     return js.js('#.#',
-        [namer.globalObjectForConstant(value), namer.constantName(value)]);
+        [_namer.globalObjectForConstant(value), _namer.constantName(value)]);
   }
 
-  int emitProgram(Program program) {
+  int emitProgram(Program program, CodegenWorld codegenWorld) {
     MainFragment mainFragment = program.fragments.first;
     List<DeferredFragment> deferredFragments =
         new List<DeferredFragment>.from(program.deferredFragments);
 
     FragmentEmitter fragmentEmitter = new FragmentEmitter(
-        compiler, namer, backend, constantEmitter, this, _closedWorld);
+        _options,
+        _dumpInfoTask,
+        _namer,
+        _emitter,
+        _constantEmitter,
+        this,
+        _closedWorld,
+        codegenWorld);
 
     var deferredLoadingState = new DeferredLoadingState();
     js.Statement mainCode =
@@ -197,28 +201,32 @@
     program.finalizers.forEach((js.TokenFinalizer f) => f.finalizeTokens());
 
     // TODO(sra): This is where we know if the types (and potentially other
-    // deferred ASTs inside the parts) have any contents. We shoudl wait until
+    // deferred ASTs inside the parts) have any contents. We should wait until
     // this point to decide if a part is empty.
 
     Map<DeferredFragment, String> hunkHashes =
-        writeDeferredFragments(deferredFragmentsCode);
+        _task.measureSubtask('write fragments', () {
+      return writeDeferredFragments(deferredFragmentsCode);
+    });
 
     // Now that we have written the deferred hunks, we can create the deferred
     // loading data.
     fragmentEmitter.finalizeDeferredLoadingData(
         program.loadMap, hunkHashes, deferredLoadingState);
 
-    writeMainFragment(mainFragment, mainCode,
-        isSplit: program.deferredFragments.isNotEmpty ||
-            program.hasSoftDeferredClasses ||
-            compiler.options.experimentalTrackAllocations);
+    _task.measureSubtask('write fragments', () {
+      writeMainFragment(mainFragment, mainCode,
+          isSplit: program.deferredFragments.isNotEmpty ||
+              program.hasSoftDeferredClasses ||
+              _options.experimentalTrackAllocations);
+    });
 
     if (_closedWorld.backendUsage.requiresPreamble &&
-        !backend.htmlLibraryIsLoaded) {
-      reporter.reportHintMessage(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
+        !_closedWorld.backendUsage.isHtmlLoaded) {
+      _reporter.reportHintMessage(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
     }
 
-    if (compiler.options.deferredMapUri != null) {
+    if (_options.deferredMapUri != null) {
       writeDeferredMap();
     }
 
@@ -232,13 +240,13 @@
     flavor.write('fast startup emitter');
     // TODO(johnniwinther): Remove this flavor.
     flavor.write(', strong');
-    if (compiler.options.trustPrimitives) flavor.write(', trust primitives');
-    if (compiler.options.omitImplicitChecks) flavor.write(', omit checks');
-    if (compiler.options.laxRuntimeTypeToString) {
+    if (_options.trustPrimitives) flavor.write(', trust primitives');
+    if (_options.omitImplicitChecks) flavor.write(', omit checks');
+    if (_options.laxRuntimeTypeToString) {
       flavor.write(', lax runtime type');
     }
-    if (compiler.options.useContentSecurityPolicy) flavor.write(', CSP');
-    return new js.Comment(generatedBy(compiler, flavor: '$flavor'));
+    if (_options.useContentSecurityPolicy) flavor.write(', CSP');
+    return new js.Comment(generatedBy(_options, flavor: '$flavor'));
   }
 
   /// Writes all deferred fragment's code into files.
@@ -272,15 +280,15 @@
       {bool isSplit}) {
     LocationCollector locationCollector;
     List<CodeOutputListener> codeOutputListeners;
-    if (shouldGenerateSourceMap) {
-      task.measureSubtask('source-maps', () {
+    if (_shouldGenerateSourceMap) {
+      _task.measureSubtask('source-maps', () {
         locationCollector = new LocationCollector();
         codeOutputListeners = <CodeOutputListener>[locationCollector];
       });
     }
 
     CodeOutput mainOutput = new StreamCodeOutput(
-        compiler.outputProvider.createOutputSink('', 'js', OutputType.js),
+        _outputProvider.createOutputSink('', 'js', OutputType.js),
         codeOutputListeners);
     outputBuffers[fragment] = mainOutput;
 
@@ -291,30 +299,33 @@
       code
     ]);
 
-    mainOutput.addBuffer(js.createCodeBuffer(
-        program, compiler.options, backend.sourceInformationStrategy,
-        monitor: compiler.dumpInfoTask));
+    CodeBuffer buffer = js.createCodeBuffer(
+        program, _options, _sourceInformationStrategy,
+        monitor: _dumpInfoTask);
+    _task.measureSubtask('emit buffers', () {
+      mainOutput.addBuffer(buffer);
+    });
 
-    if (shouldGenerateSourceMap) {
-      task.measureSubtask('source-maps', () {
+    if (_shouldGenerateSourceMap) {
+      _task.measureSubtask('source-maps', () {
         mainOutput.add(SourceMapBuilder.generateSourceMapTag(
-            compiler.options.sourceMapUri, compiler.options.outputUri));
+            _options.sourceMapUri, _options.outputUri));
       });
     }
 
     mainOutput.close();
 
-    if (shouldGenerateSourceMap) {
-      task.measureSubtask('source-maps', () {
+    if (_shouldGenerateSourceMap) {
+      _task.measureSubtask('source-maps', () {
         SourceMapBuilder.outputSourceMap(
             mainOutput,
             locationCollector,
-            namer.createMinifiedGlobalNameMap(),
-            namer.createMinifiedInstanceNameMap(),
+            _namer.createMinifiedGlobalNameMap(),
+            _namer.createMinifiedInstanceNameMap(),
             '',
-            compiler.options.sourceMapUri,
-            compiler.options.outputUri,
-            compiler.outputProvider);
+            _options.sourceMapUri,
+            _options.outputUri,
+            _outputProvider);
       });
     }
   }
@@ -330,8 +341,8 @@
     outputListeners.add(hasher);
 
     LocationCollector locationCollector;
-    if (shouldGenerateSourceMap) {
-      task.measureSubtask('source-maps', () {
+    if (_shouldGenerateSourceMap) {
+      _task.measureSubtask('source-maps', () {
         locationCollector = new LocationCollector();
         outputListeners.add(locationCollector);
       });
@@ -340,8 +351,8 @@
     String hunkPrefix = fragment.outputFileName;
 
     CodeOutput output = new StreamCodeOutput(
-        compiler.outputProvider
-            .createOutputSink(hunkPrefix, deferredExtension, OutputType.jsPart),
+        _outputProvider.createOutputSink(
+            hunkPrefix, deferredExtension, OutputType.jsPart),
         outputListeners);
 
     outputBuffers[fragment] = output;
@@ -361,9 +372,12 @@
       js.js.statement('$deferredInitializersGlobal.current = #', code)
     ]);
 
-    output.addBuffer(js.createCodeBuffer(
-        program, compiler.options, backend.sourceInformationStrategy,
-        monitor: compiler.dumpInfoTask));
+    CodeBuffer buffer = js.createCodeBuffer(
+        program, _options, _sourceInformationStrategy,
+        monitor: _dumpInfoTask);
+    _task.measureSubtask('emit buffers', () {
+      output.addBuffer(buffer);
+    });
 
     // Make a unique hash of the code (before the sourcemaps are added)
     // This will be used to retrieve the initializing function from the global
@@ -374,11 +388,11 @@
     output.add('\n${deferredInitializersGlobal}["$hash"] = '
         '${deferredInitializersGlobal}.current');
 
-    if (shouldGenerateSourceMap) {
-      task.measureSubtask('source-maps', () {
+    if (_shouldGenerateSourceMap) {
+      _task.measureSubtask('source-maps', () {
         Uri mapUri, partUri;
-        Uri sourceMapUri = compiler.options.sourceMapUri;
-        Uri outputUri = compiler.options.outputUri;
+        Uri sourceMapUri = _options.sourceMapUri;
+        Uri outputUri = _options.outputUri;
         String partName = "$hunkPrefix.$partExtension";
         String hunkFileName = "$hunkPrefix.$deferredExtension";
 
@@ -386,21 +400,19 @@
           String mapFileName = hunkFileName + ".map";
           List<String> mapSegments = sourceMapUri.pathSegments.toList();
           mapSegments[mapSegments.length - 1] = mapFileName;
-          mapUri =
-              compiler.options.sourceMapUri.replace(pathSegments: mapSegments);
+          mapUri = _options.sourceMapUri.replace(pathSegments: mapSegments);
         }
 
         if (outputUri != null) {
           List<String> partSegments = outputUri.pathSegments.toList();
           partSegments[partSegments.length - 1] = hunkFileName;
-          partUri =
-              compiler.options.outputUri.replace(pathSegments: partSegments);
+          partUri = _options.outputUri.replace(pathSegments: partSegments);
         }
 
         output.add(SourceMapBuilder.generateSourceMapTag(mapUri, partUri));
         output.close();
         SourceMapBuilder.outputSourceMap(output, locationCollector, {}, {},
-            partName, mapUri, partUri, compiler.outputProvider);
+            partName, mapUri, partUri, _outputProvider);
       });
     } else {
       output.close();
@@ -420,11 +432,11 @@
     mapping["_comment"] = "This mapping shows which compiled `.js` files are "
         "needed for a given deferred library import.";
     mapping.addAll(_closedWorld.outputUnitData.computeDeferredMap(
-        compiler.options, _closedWorld.elementEnvironment,
+        _options, _closedWorld.elementEnvironment,
         omittedUnits:
-            omittedFragments.map((fragemnt) => fragemnt.outputUnit).toSet()));
-    compiler.outputProvider.createOutputSink(
-        compiler.options.deferredMapUri.path, '', OutputType.deferredMap)
+            omittedFragments.map((fragment) => fragment.outputUnit).toSet()));
+    _outputProvider.createOutputSink(
+        _options.deferredMapUri.path, '', OutputType.deferredMap)
       ..add(const JsonEncoder.withIndent("  ").convert(mapping))
       ..close();
   }
diff --git a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
index fd5ffa3..7a2c9e4 100644
--- a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
+++ b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
@@ -23,12 +23,10 @@
   Set<ClassEntity> _rtiNeededClasses;
 
   final CompilerOptions _options;
-  final CodegenWorldBuilder _codegenWorldBuilder;
 
   RuntimeTypesChecks _rtiChecks;
 
-  TypeTestRegistry(
-      this._options, this._codegenWorldBuilder, this._elementEnvironment);
+  TypeTestRegistry(this._options, this._elementEnvironment);
 
   RuntimeTypesChecks get rtiChecks {
     assert(
@@ -70,8 +68,8 @@
     addClassesWithSuperclasses(rtiChecks.requiredClasses);
   }
 
-  void computeRequiredTypeChecks(RuntimeTypesChecksBuilder rtiChecksBuilder) {
-    _rtiChecks =
-        rtiChecksBuilder.computeRequiredChecks(_codegenWorldBuilder, _options);
+  void computeRequiredTypeChecks(
+      RuntimeTypesChecksBuilder rtiChecksBuilder, CodegenWorld codegenWorld) {
+    _rtiChecks = rtiChecksBuilder.computeRequiredChecks(codegenWorld, _options);
   }
 }
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index d3295fe..9a39986 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -12,6 +12,7 @@
 import '../elements/types.dart';
 import '../ir/closure.dart';
 import '../ir/element_map.dart';
+import '../ir/static_type_cache.dart';
 import '../js_model/element_map.dart';
 import '../js_model/env.dart';
 import '../ordered_typeset.dart';
@@ -627,6 +628,7 @@
 
   @override
   JFunction callMethod;
+  @override
   JSignatureMethod signatureMethod;
   @override
   final Local closureEntity;
@@ -939,8 +941,6 @@
 /// A variable that has been "boxed" to prevent name shadowing with the
 /// original variable and ensure that this variable is updated/read with the
 /// most recent value.
-/// This corresponds to BoxFieldElement; we reuse BoxLocal from the original
-/// algorithm to correspond to the actual name of the variable.
 class JRecordField extends JField {
   /// Tag used for identifying serialized [JRecordField] objects in a
   /// debugging data stream.
@@ -973,8 +973,16 @@
     sink.end(tag);
   }
 
+  // TODO(johnniwinther): Remove these anomalies. Maybe by separating the
+  // J-entities from the K-entities.
   @override
   bool get isInstanceMember => false;
+
+  @override
+  bool get isTopLevel => false;
+
+  @override
+  bool get isStatic => false;
 }
 
 class ClosureClassData extends RecordClassData {
@@ -1059,7 +1067,7 @@
   ClosureMemberData(this.definition, this.memberThisType);
 
   @override
-  Map<ir.Expression, ir.DartType> get staticTypes {
+  StaticTypeCache get staticTypes {
     // The cached types are stored in the data for enclosing member.
     throw new UnsupportedError("ClosureMemberData.staticTypes");
   }
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 2afbce4..2b2d412 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -15,9 +15,6 @@
 import '../ir/closure.dart';
 import '../ir/static_type_provider.dart';
 import '../ir/util.dart';
-import '../js/js.dart' as js;
-import '../js_backend/namer.dart';
-import '../js_emitter/code_emitter_task.dart';
 import '../js_model/closure.dart' show JRecordField;
 import '../js_model/elements.dart' show JGeneratorBody;
 import '../native/behavior.dart';
@@ -104,9 +101,6 @@
   NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
       ir.StaticInvocation node);
 
-  /// Returns the [js.Name] for the `JsGetName` [constant] value.
-  js.Name getNameForJsGetName(ConstantValue constant, Namer namer);
-
   /// Computes the [ConstantValue] for the constant [expression].
   // TODO(johnniwinther): Move to [KernelToElementMapForBuilding]. This is only
   // used in impact builder for symbol constants.
@@ -140,10 +134,6 @@
   /// Returns the [LibraryEntity] corresponding to the library [node].
   LibraryEntity getLibrary(ir.Library node);
 
-  /// Returns the [js.Template] for the `JsBuiltin` [constant] value.
-  js.Template getJsBuiltinTemplate(
-      ConstantValue constant, CodeEmitterTask emitter);
-
   /// Returns a [Spannable] for a message pointing to the IR [node] in the
   /// context of [member].
   Spannable getSpannable(MemberEntity member, ir.Node node);
@@ -209,9 +199,9 @@
   /// Returns the inferred type of the [parameter].
   AbstractValue getInferredTypeOfParameter(Local parameter);
 
-  /// Returns the inferred type of a dynamic [selector] access on the
+  /// Returns the inferred result type of a dynamic [selector] access on the
   /// [receiver].
-  AbstractValue selectorTypeOf(Selector selector, AbstractValue receiver);
+  AbstractValue resultTypeOfSelector(Selector selector, AbstractValue receiver);
 
   /// Returns the returned type annotation in the [nativeBehavior].
   AbstractValue typeFromNativeBehavior(
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 657dadf..e24352c 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -4,7 +4,6 @@
 
 import 'package:front_end/src/api_unstable/dart2js.dart' show Link, LinkBuilder;
 
-import 'package:js_runtime/shared/embedded_names.dart';
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/class_hierarchy.dart' as ir;
 import 'package:kernel/core_types.dart' as ir;
@@ -20,6 +19,7 @@
 import '../constants/evaluation.dart';
 import '../constants/expressions.dart';
 import '../constants/values.dart';
+import '../deferred_load.dart';
 import '../elements/entities.dart';
 import '../elements/entity_utils.dart' as utils;
 import '../elements/indexed.dart';
@@ -33,13 +33,11 @@
 import '../ir/types.dart';
 import '../ir/visitors.dart';
 import '../ir/static_type_base.dart';
+import '../ir/static_type_cache.dart';
 import '../ir/static_type_provider.dart';
 import '../ir/util.dart';
-import '../js/js.dart' as js;
 import '../js_backend/annotations.dart';
-import '../js_backend/namer.dart';
 import '../js_backend/native_data.dart';
-import '../js_emitter/code_emitter_task.dart';
 import '../kernel/element_map_impl.dart';
 import '../kernel/env.dart';
 import '../kernel/kelements.dart';
@@ -58,17 +56,7 @@
 import 'env.dart';
 import 'locals.dart';
 
-/// Interface for kernel queries needed to implement the [CodegenWorldBuilder].
-abstract class JsToWorldBuilder implements JsToElementMap {
-  /// Calls [f] for each parameter of [function] providing the type and name of
-  /// the parameter and the [defaultValue] if the parameter is optional.
-  void forEachParameter(FunctionEntity function,
-      void f(DartType type, String name, ConstantValue defaultValue),
-      {bool isNative: false});
-}
-
-class JsKernelToElementMap
-    implements JsToWorldBuilder, JsToElementMap, IrToElementMap {
+class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
   /// Tag used for identifying serialized [JsKernelToElementMap] objects in a
   /// debugging data stream.
   static const String tag = 'js-kernel-to-element-map';
@@ -132,13 +120,16 @@
   /// Map from members to the call methods created for their nested closures.
   Map<IndexedMember, List<IndexedFunction>> _nestedClosureMap = {};
 
-  /// NativeBasicData is need for computation of the default super class.
-  NativeBasicData nativeBasicData;
+  /// NativeData is need for computation of the default super class and
+  /// parameter ordering.
+  NativeData nativeData;
 
   Map<IndexedFunction, JGeneratorBody> _generatorBodies = {};
 
   Map<IndexedClass, List<IndexedMember>> _injectedClassMembers = {};
 
+  LateOutputUnitDataBuilder lateOutputUnitDataBuilder;
+
   JsKernelToElementMap(
       this.reporter,
       Environment environment,
@@ -159,7 +150,8 @@
       IndexedLibrary oldLibrary = _elementMap.libraries.getEntity(libraryIndex);
       KLibraryEnv oldEnv = _elementMap.libraries.getEnv(oldLibrary);
       KLibraryData data = _elementMap.libraries.getData(oldLibrary);
-      IndexedLibrary newLibrary = convertLibrary(oldLibrary);
+      IndexedLibrary newLibrary =
+          new JLibrary(oldLibrary.name, oldLibrary.canonicalUri);
       JLibraryEnv newEnv = oldEnv.convert(_elementMap, liveMemberUsage);
       libraryMap[oldEnv.library] =
           libraries.register<IndexedLibrary, JLibraryData, JLibraryEnv>(
@@ -176,7 +168,8 @@
       KClassData data = _elementMap.classes.getData(oldClass);
       IndexedLibrary oldLibrary = oldClass.library;
       LibraryEntity newLibrary = libraries.getEntity(oldLibrary.libraryIndex);
-      IndexedClass newClass = convertClass(newLibrary, oldClass);
+      IndexedClass newClass = new JClass(newLibrary, oldClass.name,
+          isAbstract: oldClass.isAbstract);
       JClassEnv newEnv = env.convert(_elementMap, liveMemberUsage);
       classMap[env.cls] = classes.register(newClass, data.convert(), newEnv);
       assert(newClass.classIndex == oldClass.classIndex);
@@ -189,7 +182,7 @@
       KTypedefData data = _elementMap.typedefs.getData(oldTypedef);
       IndexedLibrary oldLibrary = oldTypedef.library;
       LibraryEntity newLibrary = libraries.getEntity(oldLibrary.libraryIndex);
-      IndexedTypedef newTypedef = convertTypedef(newLibrary, oldTypedef);
+      IndexedTypedef newTypedef = new JTypedef(newLibrary, oldTypedef.name);
       typedefMap[data.node] = typedefs.register(
           newTypedef,
           new JTypedefData(
@@ -201,6 +194,7 @@
                   getDartType(data.node.type))));
       assert(newTypedef.typedefIndex == oldTypedef.typedefIndex);
     }
+
     for (int memberIndex = 0;
         memberIndex < _elementMap.members.length;
         memberIndex++) {
@@ -216,8 +210,59 @@
       LibraryEntity newLibrary = libraries.getEntity(oldLibrary.libraryIndex);
       ClassEntity newClass =
           oldClass != null ? classes.getEntity(oldClass.classIndex) : null;
-      IndexedMember newMember = convertMember(
-          newLibrary, newClass, oldMember, memberUsage, annotations);
+      IndexedMember newMember;
+      Name memberName = new Name(oldMember.memberName.text, newLibrary,
+          isSetter: oldMember.memberName.isSetter);
+      if (oldMember.isField) {
+        IndexedField field = oldMember;
+        newMember = new JField(newLibrary, newClass, memberName,
+            isStatic: field.isStatic,
+            isAssignable: field.isAssignable,
+            isConst: field.isConst);
+      } else if (oldMember.isConstructor) {
+        IndexedConstructor constructor = oldMember;
+        ParameterStructure parameterStructure =
+            annotations.hasNoElision(constructor)
+                ? constructor.parameterStructure
+                : memberUsage.invokedParameters;
+        if (constructor.isFactoryConstructor) {
+          // TODO(redemption): This should be a JFunction.
+          newMember = new JFactoryConstructor(
+              newClass, memberName, parameterStructure,
+              isExternal: constructor.isExternal,
+              isConst: constructor.isConst,
+              isFromEnvironmentConstructor:
+                  constructor.isFromEnvironmentConstructor);
+        } else {
+          newMember = new JGenerativeConstructor(
+              newClass, memberName, parameterStructure,
+              isExternal: constructor.isExternal, isConst: constructor.isConst);
+        }
+      } else if (oldMember.isGetter) {
+        IndexedFunction getter = oldMember;
+        newMember = new JGetter(
+            newLibrary, newClass, memberName, getter.asyncMarker,
+            isStatic: getter.isStatic,
+            isExternal: getter.isExternal,
+            isAbstract: getter.isAbstract);
+      } else if (oldMember.isSetter) {
+        IndexedFunction setter = oldMember;
+        newMember = new JSetter(newLibrary, newClass, memberName,
+            isStatic: setter.isStatic,
+            isExternal: setter.isExternal,
+            isAbstract: setter.isAbstract);
+      } else {
+        IndexedFunction function = oldMember;
+        ParameterStructure parameterStructure =
+            annotations.hasNoElision(function)
+                ? function.parameterStructure
+                : memberUsage.invokedParameters;
+        newMember = new JMethod(newLibrary, newClass, memberName,
+            parameterStructure, function.asyncMarker,
+            isStatic: function.isStatic,
+            isExternal: function.isExternal,
+            isAbstract: function.isAbstract);
+      }
       members.register(newMember, data.convert());
       assert(
           newMember.memberIndex == oldMember.memberIndex,
@@ -399,6 +444,31 @@
     source.end(tag);
   }
 
+  /// Prepares the entity maps for codegen serialization and returns the member
+  /// index limit for early members.
+  ///
+  /// This method creates all late members, such as constructor bodies and
+  /// generator bodies, and closes the entity maps for further registration.
+  int prepareForCodegenSerialization() {
+    int length = members.length;
+    for (int memberIndex = 0; memberIndex < length; memberIndex++) {
+      MemberEntity member = members.getEntity(memberIndex);
+      if (member == null) continue;
+      if (member is JGenerativeConstructor) {
+        getConstructorBody(members.getData(member).definition.node);
+      }
+      if (member is IndexedFunction && member.asyncMarker != AsyncMarker.SYNC) {
+        getGeneratorBody(member);
+      }
+    }
+    libraries.close();
+    classes.close();
+    members.close();
+    typedefs.close();
+    typeVariables.close();
+    return length;
+  }
+
   /// Serializes this [JsToElementMap] to [sink].
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
@@ -690,7 +760,7 @@
         }
         if (supertype == _commonElements.objectType) {
           ClassEntity defaultSuperclass =
-              _commonElements.getDefaultSuperclass(cls, nativeBasicData);
+              _commonElements.getDefaultSuperclass(cls, nativeData);
           data.supertype = _elementEnvironment.getRawType(defaultSuperclass);
         } else {
           data.supertype = supertype;
@@ -1098,7 +1168,7 @@
   @override
   StaticTypeProvider getStaticTypeProvider(MemberEntity member) {
     MemberDefinition memberDefinition = members.getData(member).definition;
-    Map<ir.Expression, ir.DartType> cachedStaticTypes;
+    StaticTypeCache cachedStaticTypes;
     ir.InterfaceType thisType;
     switch (memberDefinition.kind) {
       case MemberKind.regular:
@@ -1123,7 +1193,7 @@
       case MemberKind.closureField:
       case MemberKind.signature:
       case MemberKind.generatorBody:
-        cachedStaticTypes = const {};
+        cachedStaticTypes = const StaticTypeCache();
         break;
     }
 
@@ -1264,6 +1334,7 @@
       type ??= findIn(Uris.dart_web_sql);
       type ??= findIn(Uris.dart_indexed_db);
       type ??= findIn(Uris.dart_typed_data);
+      type ??= findIn(Uris.dart__rti);
       type ??= findIn(Uris.dart_mirrors);
       if (type == null && required) {
         reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
@@ -1373,29 +1444,6 @@
   }
 
   @override
-  js.Name getNameForJsGetName(ConstantValue constant, Namer namer) {
-    int index = extractEnumIndexFromConstantValue(
-        constant, commonElements.jsGetNameEnum);
-    if (index == null) return null;
-    return namer.getNameForJsGetName(
-        CURRENT_ELEMENT_SPANNABLE, JsGetName.values[index]);
-  }
-
-  int extractEnumIndexFromConstantValue(
-      ConstantValue constant, ClassEntity classElement) {
-    if (constant is ConstructedConstantValue) {
-      if (constant.type.element == classElement) {
-        assert(constant.fields.length == 1 || constant.fields.length == 2);
-        ConstantValue indexConstant = constant.fields.values.first;
-        if (indexConstant is IntConstantValue) {
-          return indexConstant.intValue.toInt();
-        }
-      }
-    }
-    return null;
-  }
-
-  @override
   ConstantValue getConstantValue(ir.Expression node,
       {bool requireConstant: true, bool implicitNull: false}) {
     if (node is ir.ConstantExpression) {
@@ -1464,40 +1512,11 @@
     return function;
   }
 
-  IndexedLibrary createLibrary(String name, Uri canonicalUri) {
-    return new JLibrary(name, canonicalUri);
-  }
-
-  IndexedClass createClass(LibraryEntity library, String name,
-      {bool isAbstract}) {
-    return new JClass(library, name, isAbstract: isAbstract);
-  }
-
-  IndexedTypedef createTypedef(LibraryEntity library, String name) {
-    return new JTypedef(library, name);
-  }
-
   TypeVariableEntity createTypeVariable(
       Entity typeDeclaration, String name, int index) {
     return new JTypeVariable(typeDeclaration, name, index);
   }
 
-  IndexedConstructor createGenerativeConstructor(ClassEntity enclosingClass,
-      Name name, ParameterStructure parameterStructure,
-      {bool isExternal, bool isConst}) {
-    return new JGenerativeConstructor(enclosingClass, name, parameterStructure,
-        isExternal: isExternal, isConst: isConst);
-  }
-
-  IndexedConstructor createFactoryConstructor(ClassEntity enclosingClass,
-      Name name, ParameterStructure parameterStructure,
-      {bool isExternal, bool isConst, bool isFromEnvironmentConstructor}) {
-    return new JFactoryConstructor(enclosingClass, name, parameterStructure,
-        isExternal: isExternal,
-        isConst: isConst,
-        isFromEnvironmentConstructor: isFromEnvironmentConstructor);
-  }
-
   JConstructorBody createConstructorBody(
       ConstructorEntity constructor, ParameterStructure parameterStructure) {
     return new JConstructorBody(constructor, parameterStructure);
@@ -1508,109 +1527,6 @@
     return new JGeneratorBody(function, elementType);
   }
 
-  IndexedFunction createGetter(LibraryEntity library,
-      ClassEntity enclosingClass, Name name, AsyncMarker asyncMarker,
-      {bool isStatic, bool isExternal, bool isAbstract}) {
-    return new JGetter(library, enclosingClass, name, asyncMarker,
-        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
-  }
-
-  IndexedFunction createMethod(
-      LibraryEntity library,
-      ClassEntity enclosingClass,
-      Name name,
-      ParameterStructure parameterStructure,
-      AsyncMarker asyncMarker,
-      {bool isStatic,
-      bool isExternal,
-      bool isAbstract}) {
-    return new JMethod(
-        library, enclosingClass, name, parameterStructure, asyncMarker,
-        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
-  }
-
-  IndexedFunction createSetter(
-      LibraryEntity library, ClassEntity enclosingClass, Name name,
-      {bool isStatic, bool isExternal, bool isAbstract}) {
-    return new JSetter(library, enclosingClass, name,
-        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
-  }
-
-  IndexedField createField(
-      LibraryEntity library, ClassEntity enclosingClass, Name name,
-      {bool isStatic, bool isAssignable, bool isConst}) {
-    return new JField(library, enclosingClass, name,
-        isStatic: isStatic, isAssignable: isAssignable, isConst: isConst);
-  }
-
-  LibraryEntity convertLibrary(IndexedLibrary library) {
-    return createLibrary(library.name, library.canonicalUri);
-  }
-
-  ClassEntity convertClass(LibraryEntity library, IndexedClass cls) {
-    return createClass(library, cls.name, isAbstract: cls.isAbstract);
-  }
-
-  TypedefEntity convertTypedef(LibraryEntity library, IndexedTypedef typedef) {
-    return createTypedef(library, typedef.name);
-  }
-
-  MemberEntity convertMember(
-      LibraryEntity library,
-      ClassEntity cls,
-      IndexedMember member,
-      MemberUsage memberUsage,
-      AnnotationsData annotations) {
-    Name memberName = new Name(member.memberName.text, library,
-        isSetter: member.memberName.isSetter);
-    if (member.isField) {
-      IndexedField field = member;
-      return createField(library, cls, memberName,
-          isStatic: field.isStatic,
-          isAssignable: field.isAssignable,
-          isConst: field.isConst);
-    } else if (member.isConstructor) {
-      IndexedConstructor constructor = member;
-      ParameterStructure parameterStructure =
-          annotations.hasNoElision(constructor)
-              ? constructor.parameterStructure
-              : memberUsage.invokedParameters;
-      if (constructor.isFactoryConstructor) {
-        // TODO(redemption): This should be a JFunction.
-        return createFactoryConstructor(cls, memberName, parameterStructure,
-            isExternal: constructor.isExternal,
-            isConst: constructor.isConst,
-            isFromEnvironmentConstructor:
-                constructor.isFromEnvironmentConstructor);
-      } else {
-        return createGenerativeConstructor(cls, memberName, parameterStructure,
-            isExternal: constructor.isExternal, isConst: constructor.isConst);
-      }
-    } else if (member.isGetter) {
-      IndexedFunction getter = member;
-      return createGetter(library, cls, memberName, getter.asyncMarker,
-          isStatic: getter.isStatic,
-          isExternal: getter.isExternal,
-          isAbstract: getter.isAbstract);
-    } else if (member.isSetter) {
-      IndexedFunction setter = member;
-      return createSetter(library, cls, memberName,
-          isStatic: setter.isStatic,
-          isExternal: setter.isExternal,
-          isAbstract: setter.isAbstract);
-    } else {
-      IndexedFunction function = member;
-      ParameterStructure parameterStructure = annotations.hasNoElision(function)
-          ? function.parameterStructure
-          : memberUsage.invokedParameters;
-      return createMethod(
-          library, cls, memberName, parameterStructure, function.asyncMarker,
-          isStatic: function.isStatic,
-          isExternal: function.isExternal,
-          isAbstract: function.isAbstract);
-    }
-  }
-
   void forEachNestedClosure(
       MemberEntity member, void f(FunctionEntity closure)) {
     assert(checkFamily(member));
@@ -1717,33 +1633,35 @@
   @override
   FunctionEntity getConstructorBody(ir.Constructor node) {
     ConstructorEntity constructor = getConstructor(node);
-    return _getConstructorBody(node, constructor);
+    return _getConstructorBody(constructor);
   }
 
-  FunctionEntity _getConstructorBody(
-      ir.Constructor node, covariant IndexedConstructor constructor) {
+  JConstructorBody _getConstructorBody(IndexedConstructor constructor) {
     JConstructorDataImpl data = members.getData(constructor);
     if (data.constructorBody == null) {
       /// The constructor calls the constructor body with all parameters.
       // TODO(johnniwinther): Remove parameters that are not used in the
       //  constructor body.
       ParameterStructure parameterStructure =
-          _getParameterStructureFromFunctionNode(node.function);
+          _getParameterStructureFromFunctionNode(data.node.function);
 
       JConstructorBody constructorBody =
           createConstructorBody(constructor, parameterStructure);
       members.register<IndexedFunction, FunctionData>(
           constructorBody,
           new ConstructorBodyDataImpl(
-              node,
-              node.function,
-              new SpecialMemberDefinition(node, MemberKind.constructorBody),
+              data.node,
+              data.node.function,
+              new SpecialMemberDefinition(
+                  data.node, MemberKind.constructorBody),
               data.staticTypes));
       IndexedClass cls = constructor.enclosingClass;
       JClassEnvImpl classEnv = classes.getEnv(cls);
       // TODO(johnniwinther): Avoid this by only including live members in the
       // js-model.
       classEnv.addConstructorBody(constructorBody);
+      lateOutputUnitDataBuilder.registerColocatedMembers(
+          constructor, constructorBody);
       data.constructorBody = constructorBody;
     }
     return data.constructorBody;
@@ -1759,7 +1677,8 @@
     return getClassDefinitionInternal(cls);
   }
 
-  @override
+  /// Calls [f] for each parameter of [function] providing the type and name of
+  /// the parameter and the [defaultValue] if the parameter is optional.
   void forEachParameter(covariant IndexedFunction function,
       void f(DartType type, String name, ConstantValue defaultValue),
       {bool isNative: false}) {
@@ -2191,18 +2110,12 @@
         (_injectedClassMembers[function.enclosingClass] ??= <IndexedMember>[])
             .add(generatorBody);
       }
+      lateOutputUnitDataBuilder.registerColocatedMembers(
+          generatorBody.function, generatorBody);
+      _generatorBodies[function] = generatorBody;
     }
     return generatorBody;
   }
-
-  @override
-  js.Template getJsBuiltinTemplate(
-      ConstantValue constant, CodeEmitterTask emitter) {
-    int index = extractEnumIndexFromConstantValue(
-        constant, commonElements.jsBuiltinEnum);
-    if (index == null) return null;
-    return emitter.builtinTemplateFor(JsBuiltin.values[index]);
-  }
 }
 
 class JsElementEnvironment extends ElementEnvironment
@@ -2474,6 +2387,47 @@
     JClassData classData = elementMap.classes.getData(cls);
     return classData.isEnumClass;
   }
+
+  @override
+  void forEachParameter(FunctionEntity function,
+      void f(DartType type, String name, ConstantValue defaultValue)) {
+    elementMap.forEachParameter(function, f,
+        isNative: elementMap.nativeData.isNativeMember(function));
+  }
+
+  @override
+  void forEachParameterAsLocal(GlobalLocalsMap globalLocalsMap,
+      FunctionEntity function, void f(Local parameter)) {
+    forEachOrderedParameterAsLocal(globalLocalsMap, elementMap, function,
+        (Local parameter, {bool isElided}) {
+      if (!isElided) {
+        f(parameter);
+      }
+    });
+  }
+
+  @override
+  void forEachInstanceField(
+      ClassEntity cls, void f(ClassEntity declarer, FieldEntity field)) {
+    forEachClassMember(cls, (ClassEntity declarer, MemberEntity member) {
+      if (member.isField && member.isInstanceMember) {
+        f(declarer, member);
+      }
+    });
+  }
+
+  @override
+  void forEachDirectInstanceField(ClassEntity cls, void f(FieldEntity field)) {
+    // TODO(sra): Add ElementEnvironment.forEachDirectInstanceField or
+    // parameterize [forEachInstanceField] to filter members to avoid a
+    // potentially O(n^2) scan of the superclasses.
+    forEachClassMember(cls, (ClassEntity declarer, MemberEntity member) {
+      if (declarer != cls) return;
+      if (!member.isField) return;
+      if (!member.isInstanceMember) return;
+      f(member);
+    });
+  }
 }
 
 /// [BehaviorBuilder] for kernel based elements.
@@ -2664,3 +2618,113 @@
     return typeVariable;
   }
 }
+
+/// [EntityLookup] implementation for an fully built [JsKernelToElementMap].
+class ClosedEntityLookup implements EntityLookup {
+  final JsKernelToElementMap _elementMap;
+
+  ClosedEntityLookup(this._elementMap);
+
+  @override
+  IndexedTypeVariable getTypeVariableByIndex(int index) {
+    return _elementMap.typeVariables.getEntity(index);
+  }
+
+  @override
+  IndexedMember getMemberByIndex(int index) {
+    return _elementMap.members.getEntity(index);
+  }
+
+  @override
+  IndexedTypedef getTypedefByIndex(int index) {
+    return _elementMap.typedefs.getEntity(index);
+  }
+
+  @override
+  IndexedClass getClassByIndex(int index) {
+    return _elementMap.classes.getEntity(index);
+  }
+
+  @override
+  IndexedLibrary getLibraryByIndex(int index) {
+    return _elementMap.libraries.getEntity(index);
+  }
+}
+
+/// Enum used for serialization of 'late members', that is, members normally
+/// created on demand, like constructor bodies and generator bodies.
+enum LateMemberKind {
+  constructorBody,
+  generatorBody,
+}
+
+/// Entity reader that supports member entities normally created on-demand, like
+/// constructor bodies and generator bodies.
+///
+/// The support encoding corresponds to the encoding generated by the
+/// [ClosedEntityWriter].
+class ClosedEntityReader extends EntityReader {
+  final JsKernelToElementMap _elementMap;
+
+  ClosedEntityReader(this._elementMap);
+
+  @override
+  IndexedMember readMemberFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    int index = source.readInt();
+    if (index == 0) {
+      return _readLateMemberFromDataSource(source, entityLookup);
+    } else {
+      return entityLookup.getMemberByIndex(index - 1);
+    }
+  }
+
+  IndexedMember _readLateMemberFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    LateMemberKind kind = source.readEnum(LateMemberKind.values);
+    switch (kind) {
+      case LateMemberKind.constructorBody:
+        IndexedConstructor constructor = source.readMember();
+        return _elementMap._getConstructorBody(constructor);
+      case LateMemberKind.generatorBody:
+        IndexedFunction function = source.readMember();
+        return _elementMap.getGeneratorBody(function);
+    }
+    throw new UnsupportedError("Unexpected late member kind: $kind.");
+  }
+}
+
+/// Entity writer that supports member entities normally created on-demand, like
+/// constructor bodies and generator bodies.
+///
+/// The generated encoding corresponds to the encoding read by the
+/// [ClosedEntityReader].
+class ClosedEntityWriter extends EntityWriter {
+  final int _earlyMemberIndexLimit;
+
+  final JsKernelToElementMap _elementMap;
+
+  ClosedEntityWriter(this._elementMap, this._earlyMemberIndexLimit);
+
+  @override
+  void writeMemberToDataSink(DataSink sink, IndexedMember value) {
+    if (value.memberIndex >= _earlyMemberIndexLimit) {
+      sink.writeInt(0);
+      _writeLateMemberToDataSink(sink, value);
+    } else {
+      sink.writeInt(value.memberIndex + 1);
+    }
+  }
+
+  void _writeLateMemberToDataSink(DataSink sink, IndexedMember value) {
+    if (value is JConstructorBody) {
+      sink.writeEnum(LateMemberKind.constructorBody);
+      sink.writeMember(value.constructor);
+    } else if (value is JGeneratorBody) {
+      sink.writeEnum(LateMemberKind.generatorBody);
+      sink.writeMember(value.function);
+    } else {
+      throw new UnsupportedError("Unexpected late member $value.");
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index 4bd4808..9017330 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -14,6 +14,7 @@
 import '../elements/indexed.dart';
 import '../elements/types.dart';
 import '../ir/element_map.dart';
+import '../ir/static_type_cache.dart';
 import '../ir/visitors.dart';
 import '../js_model/element_map.dart';
 import '../ordered_typeset.dart';
@@ -520,7 +521,7 @@
 
   ClassTypeVariableAccess get classTypeVariableAccess;
 
-  Map<ir.Expression, ir.DartType> get staticTypes;
+  StaticTypeCache get staticTypes;
 
   JMemberData();
 
@@ -559,7 +560,7 @@
   final MemberDefinition definition;
 
   @override
-  final Map<ir.Expression, ir.DartType> staticTypes;
+  final StaticTypeCache staticTypes;
 
   JMemberDataImpl(this.node, this.definition, this.staticTypes);
 
@@ -659,7 +660,7 @@
   FunctionType _type;
 
   FunctionDataImpl(ir.Member node, this.functionNode,
-      MemberDefinition definition, Map<ir.Expression, ir.DartType> staticTypes)
+      MemberDefinition definition, StaticTypeCache staticTypes)
       : super(node, definition, staticTypes);
 
   factory FunctionDataImpl.readFromDataSource(DataSource source) {
@@ -676,8 +677,8 @@
     }
     MemberDefinition definition =
         new MemberDefinition.readFromDataSource(source);
-    Map<ir.Expression, ir.DartType> staticTypes =
-        source.readTreeNodeMap(() => source.readDartTypeNode());
+    StaticTypeCache staticTypes =
+        new StaticTypeCache.readFromDataSource(source);
     source.end(tag);
     return new FunctionDataImpl(node, functionNode, definition, staticTypes);
   }
@@ -688,7 +689,7 @@
     sink.begin(tag);
     sink.writeMemberNode(node);
     definition.writeToDataSink(sink);
-    sink.writeTreeNodeMap(staticTypes, sink.writeDartTypeNode);
+    staticTypes.writeToDataSink(sink);
     sink.end(tag);
   }
 
@@ -744,7 +745,7 @@
   }
 
   @override
-  Map<ir.Expression, ir.DartType> get staticTypes => const {};
+  StaticTypeCache get staticTypes => const StaticTypeCache();
 
   @override
   FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
@@ -840,7 +841,7 @@
   }
 
   @override
-  Map<ir.Expression, ir.DartType> get staticTypes => const {};
+  StaticTypeCache get staticTypes => const StaticTypeCache();
 }
 
 abstract class JConstructorData extends FunctionData {
@@ -858,7 +859,7 @@
   JConstructorBody constructorBody;
 
   JConstructorDataImpl(ir.Member node, ir.FunctionNode functionNode,
-      MemberDefinition definition, Map<ir.Expression, ir.DartType> staticTypes)
+      MemberDefinition definition, StaticTypeCache staticTypes)
       : super(node, functionNode, definition, staticTypes);
 
   factory JConstructorDataImpl.readFromDataSource(DataSource source) {
@@ -875,8 +876,8 @@
     }
     MemberDefinition definition =
         new MemberDefinition.readFromDataSource(source);
-    Map<ir.Expression, ir.DartType> staticTypes =
-        source.readTreeNodeMap(() => source.readDartTypeNode());
+    StaticTypeCache staticTypes =
+        new StaticTypeCache.readFromDataSource(source);
     source.end(tag);
     return new JConstructorDataImpl(
         node, functionNode, definition, staticTypes);
@@ -889,7 +890,7 @@
     sink.writeMemberNode(node);
     definition.writeToDataSink(sink);
     assert(constructorBody == null);
-    sink.writeTreeNodeMap(staticTypes, sink.writeDartTypeNode);
+    staticTypes.writeToDataSink(sink);
     sink.end(tag);
   }
 
@@ -921,7 +922,7 @@
   static const String tag = 'constructor-body-data';
 
   ConstructorBodyDataImpl(ir.Member node, ir.FunctionNode functionNode,
-      MemberDefinition definition, Map<ir.Expression, ir.DartType> staticTypes)
+      MemberDefinition definition, StaticTypeCache staticTypes)
       : super(node, functionNode, definition, staticTypes);
 
   factory ConstructorBodyDataImpl.readFromDataSource(DataSource source) {
@@ -938,8 +939,8 @@
     }
     MemberDefinition definition =
         new MemberDefinition.readFromDataSource(source);
-    Map<ir.Expression, ir.DartType> staticTypes =
-        source.readTreeNodeMap(() => source.readDartTypeNode());
+    StaticTypeCache staticTypes =
+        new StaticTypeCache.readFromDataSource(source);
     source.end(tag);
     return new ConstructorBodyDataImpl(
         node, functionNode, definition, staticTypes);
@@ -951,7 +952,7 @@
     sink.begin(tag);
     sink.writeMemberNode(node);
     definition.writeToDataSink(sink);
-    sink.writeTreeNodeMap(staticTypes, sink.writeDartTypeNode);
+    staticTypes.writeToDataSink(sink);
     sink.end(tag);
   }
 
@@ -977,8 +978,8 @@
   DartType _type;
   ConstantExpression _constantExpression;
 
-  JFieldDataImpl(ir.Field node, MemberDefinition definition,
-      Map<ir.Expression, ir.DartType> staticTypes)
+  JFieldDataImpl(
+      ir.Field node, MemberDefinition definition, StaticTypeCache staticTypes)
       : super(node, definition, staticTypes);
 
   factory JFieldDataImpl.readFromDataSource(DataSource source) {
@@ -986,8 +987,8 @@
     ir.Member node = source.readMemberNode();
     MemberDefinition definition =
         new MemberDefinition.readFromDataSource(source);
-    Map<ir.Expression, ir.DartType> staticTypes =
-        source.readTreeNodeMap(() => source.readDartTypeNode());
+    StaticTypeCache staticTypes =
+        new StaticTypeCache.readFromDataSource(source);
     source.end(tag);
     return new JFieldDataImpl(node, definition, staticTypes);
   }
@@ -998,7 +999,7 @@
     sink.begin(tag);
     sink.writeMemberNode(node);
     definition.writeToDataSink(sink);
-    sink.writeTreeNodeMap(staticTypes, sink.writeDartTypeNode);
+    staticTypes.writeToDataSink(sink);
     sink.end(tag);
   }
 
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 2090143..2a64023 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -8,10 +8,12 @@
 
 import '../backend_strategy.dart';
 import '../common.dart';
-import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
+import '../common/codegen.dart' show CodegenRegistry, CodegenResults;
 import '../common/tasks.dart';
+import '../common/work.dart';
 import '../compiler.dart';
-import '../deferred_load.dart';
+import '../deferred_load.dart' hide WorkItem;
+import '../dump_info.dart';
 import '../elements/entities.dart';
 import '../enqueue.dart';
 import '../io/kernel_source_information.dart'
@@ -23,9 +25,14 @@
 import '../js/js_source_mapping.dart';
 import '../js_backend/backend.dart';
 import '../js_backend/inferred_data.dart';
+import '../js_backend/interceptor_data.dart';
 import '../js_backend/native_data.dart';
+import '../js_backend/namer.dart' show ModularNamer;
+import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
 import '../kernel/kernel_strategy.dart';
 import '../native/behavior.dart';
+import '../options.dart';
+import '../serialization/serialization.dart';
 import '../ssa/builder_kernel.dart';
 import '../ssa/nodes.dart';
 import '../ssa/ssa.dart';
@@ -74,8 +81,11 @@
         closureDataBuilder,
         _compiler.options,
         _compiler.abstractValueStrategy);
-    return closedWorldBuilder.convertClosedWorld(
+    JClosedWorld jClosedWorld = closedWorldBuilder.convertClosedWorld(
         closedWorld, strategy.closureModels, outputUnitData);
+    _elementMap.lateOutputUnitDataBuilder =
+        new LateOutputUnitDataBuilder(jClosedWorld.outputUnitData);
+    return jClosedWorld;
   }
 
   @override
@@ -92,29 +102,42 @@
   }
 
   @override
-  SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
-      SourceInformationStrategy sourceInformationStrategy) {
+  SsaBuilder createSsaBuilder(
+      CompilerTask task, SourceInformationStrategy sourceInformationStrategy) {
     return new KernelSsaBuilder(
         task,
-        backend.compiler,
+        _compiler.options,
+        _compiler.reporter,
+        _compiler.dumpInfoTask,
         // ignore:deprecated_member_use_from_same_package
-        elementMap);
+        elementMap,
+        sourceInformationStrategy);
   }
 
   @override
-  WorkItemBuilder createCodegenWorkItemBuilder(JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
+  WorkItemBuilder createCodegenWorkItemBuilder(
+      JClosedWorld closedWorld, CodegenResults codegenResults) {
+    assert(_elementMap != null,
+        "JsBackendStrategy.elementMap has not been created yet.");
     return new KernelCodegenWorkItemBuilder(
-        _compiler.backend, closedWorld, globalInferenceResults);
+        _compiler.backend,
+        closedWorld,
+        codegenResults,
+        new ClosedEntityLookup(_elementMap),
+        // TODO(johnniwinther): Avoid the need for a [ComponentLookup]. This
+        // is caused by some type masks holding a kernel node for using in
+        // tracing.
+        new ComponentLookup(_elementMap.programEnv.mainComponent));
   }
 
   @override
   CodegenWorldBuilder createCodegenWorldBuilder(
       NativeBasicData nativeBasicData,
-      covariant JsClosedWorld closedWorld,
-      SelectorConstraintsStrategy selectorConstraintsStrategy) {
+      JClosedWorld closedWorld,
+      SelectorConstraintsStrategy selectorConstraintsStrategy,
+      OneShotInterceptorData oneShotInterceptorData) {
     return new CodegenWorldBuilderImpl(
-        closedWorld.elementMap, closedWorld, selectorConstraintsStrategy);
+        closedWorld, selectorConstraintsStrategy, oneShotInterceptorData);
   }
 
   @override
@@ -127,70 +150,114 @@
       JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder) {
     return new TypeGraphInferrer(_compiler, closedWorld, inferredDataBuilder);
   }
+
+  @override
+  void prepareCodegenReader(DataSource source) {
+    source.registerEntityReader(new ClosedEntityReader(_elementMap));
+    source.registerEntityLookup(new ClosedEntityLookup(_elementMap));
+    source.registerComponentLookup(
+        new ComponentLookup(_elementMap.programEnv.mainComponent));
+  }
+
+  @override
+  EntityWriter forEachCodegenMember(void Function(MemberEntity member) f) {
+    int earlyMemberIndexLimit = _elementMap.prepareForCodegenSerialization();
+    ClosedEntityWriter entityWriter =
+        new ClosedEntityWriter(_elementMap, earlyMemberIndexLimit);
+    for (int memberIndex = 0;
+        memberIndex < _elementMap.members.length;
+        memberIndex++) {
+      MemberEntity member = _elementMap.members.getEntity(memberIndex);
+      if (member == null || member.isAbstract) continue;
+      f(member);
+    }
+    return entityWriter;
+  }
 }
 
 class KernelCodegenWorkItemBuilder implements WorkItemBuilder {
   final JavaScriptBackend _backend;
   final JClosedWorld _closedWorld;
-  final GlobalTypeInferenceResults _globalInferenceResults;
+  final CodegenResults _codegenResults;
+  final EntityLookup _entityLookup;
+  final ComponentLookup _componentLookup;
 
-  KernelCodegenWorkItemBuilder(
-      this._backend, this._closedWorld, this._globalInferenceResults);
+  KernelCodegenWorkItemBuilder(this._backend, this._closedWorld,
+      this._codegenResults, this._entityLookup, this._componentLookup);
 
   @override
-  CodegenWorkItem createWorkItem(MemberEntity entity) {
+  WorkItem createWorkItem(MemberEntity entity) {
     if (entity.isAbstract) return null;
-    return new KernelCodegenWorkItem(
-        _backend, _closedWorld, _globalInferenceResults, entity);
+    return new KernelCodegenWorkItem(_backend, _closedWorld, _codegenResults,
+        _entityLookup, _componentLookup, entity);
   }
 }
 
-class KernelCodegenWorkItem extends CodegenWorkItem {
+class KernelCodegenWorkItem extends WorkItem {
   final JavaScriptBackend _backend;
   final JClosedWorld _closedWorld;
+  final CodegenResults _codegenResults;
+  final EntityLookup _entityLookup;
+  final ComponentLookup _componentLookup;
   @override
   final MemberEntity element;
-  @override
-  final CodegenRegistry registry;
-  final GlobalTypeInferenceResults _globalInferenceResults;
 
-  KernelCodegenWorkItem(this._backend, this._closedWorld,
-      this._globalInferenceResults, this.element)
-      : registry =
-            new CodegenRegistry(_closedWorld.elementEnvironment, element);
+  KernelCodegenWorkItem(this._backend, this._closedWorld, this._codegenResults,
+      this._entityLookup, this._componentLookup, this.element);
 
   @override
   WorldImpact run() {
-    return _backend.codegen(this, _closedWorld, _globalInferenceResults);
+    return _backend.generateCode(
+        this, _closedWorld, _codegenResults, _entityLookup, _componentLookup);
   }
 }
 
 /// Task for building SSA from kernel IR loaded from .dill.
 class KernelSsaBuilder implements SsaBuilder {
-  final CompilerTask task;
-  final Compiler _compiler;
+  final CompilerTask _task;
+  final CompilerOptions _options;
+  final DiagnosticReporter _reporter;
+  final DumpInfoTask _dumpInfoTask;
   final JsToElementMap _elementMap;
-  FunctionInlineCache _inlineCache;
+  final SourceInformationStrategy _sourceInformationStrategy;
 
-  KernelSsaBuilder(this.task, this._compiler, this._elementMap);
+  FunctionInlineCache _inlineCache;
+  InlineDataCache _inlineDataCache;
+
+  KernelSsaBuilder(this._task, this._options, this._reporter,
+      this._dumpInfoTask, this._elementMap, this._sourceInformationStrategy);
 
   @override
-  HGraph build(CodegenWorkItem work, JClosedWorld closedWorld,
-      GlobalTypeInferenceResults results) {
+  HGraph build(
+      MemberEntity member,
+      JClosedWorld closedWorld,
+      GlobalTypeInferenceResults results,
+      CodegenInputs codegen,
+      CodegenRegistry registry,
+      ModularNamer namer,
+      ModularEmitter emitter) {
     _inlineCache ??= new FunctionInlineCache(closedWorld.annotationsData);
-    return task.measure(() {
+    _inlineDataCache ??= new InlineDataCache(
+        enableUserAssertions: _options.enableUserAssertions,
+        omitImplicitCasts: _options.omitImplicitChecks);
+    return _task.measure(() {
       KernelSsaGraphBuilder builder = new KernelSsaGraphBuilder(
-          work.element,
-          _elementMap.getMemberThisType(work.element),
-          _compiler,
+          _options,
+          _reporter,
+          member,
+          _elementMap.getMemberThisType(member),
+          _dumpInfoTask,
           _elementMap,
           results,
           closedWorld,
-          _compiler.codegenWorldBuilder,
-          work.registry,
-          _compiler.backend.emitter.nativeEmitter,
-          _compiler.backend.sourceInformationStrategy,
-          _inlineCache);
+          registry,
+          namer,
+          emitter,
+          codegen.tracer,
+          codegen.rtiEncoder,
+          _sourceInformationStrategy,
+          _inlineCache,
+          _inlineDataCache);
       return builder.build();
     });
   }
@@ -268,7 +335,7 @@
 
   @override
   AbstractValue inferredIndexType(ir.ForInStatement node) {
-    return AbstractValueFactory.inferredTypeForSelector(
+    return AbstractValueFactory.inferredResultTypeForSelector(
         new Selector.index(), typeOfIterator(node), _globalInferenceResults);
   }
 
@@ -285,8 +352,8 @@
   }
 
   @override
-  AbstractValue selectorTypeOf(Selector selector, AbstractValue mask) {
-    return AbstractValueFactory.inferredTypeForSelector(
+  AbstractValue resultTypeOfSelector(Selector selector, AbstractValue mask) {
+    return AbstractValueFactory.inferredResultTypeForSelector(
         selector, mask, _globalInferenceResults);
   }
 
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index bcb9df1..3515770 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -32,6 +32,7 @@
 import '../universe/class_hierarchy.dart';
 import '../universe/class_set.dart';
 import '../universe/function_set.dart' show FunctionSet;
+import '../universe/member_usage.dart';
 import '../universe/selector.dart';
 import '../world.dart';
 import 'element_map.dart';
@@ -93,6 +94,8 @@
   final OutputUnitData outputUnitData;
   Sorter _sorter;
 
+  final Map<MemberEntity, MemberAccess> memberAccess;
+
   JsClosedWorld(
       this.elementMap,
       this.nativeData,
@@ -113,7 +116,8 @@
       this.annotationsData,
       this.globalLocalsMap,
       this.closureDataLookup,
-      this.outputUnitData) {
+      this.outputUnitData,
+      this.memberAccess) {
     _abstractValueDomain = abstractValueStrategy.createDomain(this);
   }
 
@@ -137,7 +141,7 @@
         source, elementMap.commonElements);
     NativeData nativeData = new NativeData.readFromDataSource(
         source, elementMap.elementEnvironment);
-    elementMap.nativeBasicData = nativeData;
+    elementMap.nativeData = nativeData;
     InterceptorData interceptorData = new InterceptorData.readFromDataSource(
         source, nativeData, elementMap.commonElements);
     BackendUsage backendUsage = new BackendUsage.readFromDataSource(source);
@@ -166,6 +170,11 @@
 
     OutputUnitData outputUnitData =
         new OutputUnitData.readFromDataSource(source);
+    elementMap.lateOutputUnitDataBuilder =
+        new LateOutputUnitDataBuilder(outputUnitData);
+
+    Map<MemberEntity, MemberAccess> memberAccess =
+        source.readMemberMap(() => new MemberAccess.readFromDataSource(source));
 
     source.end(tag);
 
@@ -189,7 +198,8 @@
         annotationsData,
         globalLocalsMap,
         closureData,
-        outputUnitData);
+        outputUnitData,
+        memberAccess);
   }
 
   /// Serializes this [JsClosedWorld] to [sink].
@@ -217,6 +227,8 @@
     annotationsData.writeToDataSink(sink);
     closureDataLookup.writeToDataSink(sink);
     outputUnitData.writeToDataSink(sink);
+    sink.writeMemberMap(
+        memberAccess, (MemberAccess access) => access.writeToDataSink(sink));
     sink.end(tag);
   }
 
@@ -539,6 +551,11 @@
     return elementEnvironment.isMixinApplication(cls) &&
         !elementEnvironment.isUnnamedMixinApplication(cls);
   }
+
+  @override
+  MemberAccess getMemberAccess(MemberEntity member) {
+    return memberAccess[member];
+  }
 }
 
 class KernelSorter implements Sorter {
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index c8210a9..f4d964c 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -29,6 +29,7 @@
 import '../universe/class_hierarchy.dart';
 import '../universe/class_set.dart';
 import '../universe/feature.dart';
+import '../universe/member_usage.dart';
 import '../universe/selector.dart';
 import '../world.dart';
 import 'closure.dart';
@@ -63,7 +64,7 @@
     BackendUsage backendUsage =
         _convertBackendUsage(map, closedWorld.backendUsage);
     NativeData nativeData = _convertNativeData(map, closedWorld.nativeData);
-    _elementMap.nativeBasicData = nativeData;
+    _elementMap.nativeData = nativeData;
     InterceptorData interceptorData =
         _convertInterceptorData(map, nativeData, closedWorld.interceptorData);
 
@@ -107,6 +108,7 @@
         .getClassHierarchyNode(closedWorld.commonElements.objectClass)
         .forEachSubclass((ClassEntity cls) {
       convertClassSet(closedWorld.classHierarchy.getClassSet(cls));
+      return IterationStep.CONTINUE;
     }, ClassHierarchyNode.ALL);
 
     Set<MemberEntity> liveInstanceMembers =
@@ -202,6 +204,11 @@
     OutputUnitData outputUnitData =
         _convertOutputUnitData(map, kOutputUnitData, closureData);
 
+    Map<MemberEntity, MemberAccess> memberAccess = map.toBackendMemberMap(
+        closedWorld.liveMemberUsage,
+        (MemberUsage usage) =>
+            new MemberAccess(usage.reads, usage.writes, usage.invokes));
+
     return new JsClosedWorld(
         _elementMap,
         nativeData,
@@ -226,7 +233,8 @@
         annotationsData,
         _globalLocalsMap,
         closureData,
-        outputUnitData);
+        outputUnitData,
+        memberAccess);
   }
 
   BackendUsage _convertBackendUsage(
@@ -260,7 +268,8 @@
         runtimeTypeUses: runtimeTypeUses,
         isFunctionApplyUsed: backendUsage.isFunctionApplyUsed,
         isMirrorsUsed: backendUsage.isMirrorsUsed,
-        isNoSuchMethodUsed: backendUsage.isNoSuchMethodUsed);
+        isNoSuchMethodUsed: backendUsage.isNoSuchMethodUsed,
+        isHtmlLoaded: backendUsage.isHtmlLoaded);
   }
 
   NativeBasicData _convertNativeBasicData(
@@ -477,6 +486,9 @@
         if (entity is KLocalFunction) {
           var closureInfo = closureDataLookup.getClosureInfo(entity.node);
           result[closureInfo.callMethod] = unit;
+          if (closureInfo.signatureMethod != null) {
+            result[closureInfo.signatureMethod] = unit;
+          }
         }
       });
       return result;
@@ -487,7 +499,7 @@
         map.toBackendLibrary,
         convertClassMap,
         convertMemberMap,
-        (m) => convertMap<ConstantValue, OutputUnit>(
+        (m) => convertMap<ConstantValue, OutputUnit, OutputUnit>(
             m, map.toBackendConstant, (v) => v));
   }
 }
@@ -633,20 +645,20 @@
     return convertMap(map, toBackendClass, convert);
   }
 
-  Map<MemberEntity, V> toBackendMemberMap<V>(
-      Map<MemberEntity, V> map, V convert(V value)) {
+  Map<MemberEntity, V2> toBackendMemberMap<V1, V2>(
+      Map<MemberEntity, V1> map, V2 convert(V1 value)) {
     return convertMap(map, toBackendMember, convert);
   }
 }
 
 E identity<E>(E element) => element;
 
-Map<K, V> convertMap<K, V>(
-    Map<K, V> map, K convertKey(K key), V convertValue(V value)) {
-  Map<K, V> newMap = <K, V>{};
-  map.forEach((K key, V value) {
+Map<K, V2> convertMap<K, V1, V2>(
+    Map<K, V1> map, K convertKey(K key), V2 convertValue(V1 value)) {
+  Map<K, V2> newMap = <K, V2>{};
+  map.forEach((K key, V1 value) {
     K newKey = convertKey(key);
-    V newValue = convertValue(value);
+    V2 newValue = convertValue(value);
     if (newKey != null && newValue != null) {
       // Entities that are not used don't have a corresponding backend entity.
       newMap[newKey] = newValue;
@@ -838,7 +850,14 @@
   @override
   ConstantValue visitString(StringConstantValue constant, _) => constant;
   @override
-  ConstantValue visitSynthetic(SyntheticConstantValue constant, _) => constant;
+  ConstantValue visitDummyInterceptor(
+          DummyInterceptorConstantValue constant, _) =>
+      constant;
+  @override
+  ConstantValue visitUnreachable(UnreachableConstantValue constant, _) =>
+      constant;
+  @override
+  ConstantValue visitJsName(JsNameConstantValue constant, _) => constant;
   @override
   ConstantValue visitNonConstant(NonConstantValue constant, _) => constant;
 
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 7a2b12a..84f80cc 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -34,6 +34,7 @@
 import '../ir/impact.dart';
 import '../ir/impact_data.dart';
 import '../ir/static_type.dart';
+import '../ir/static_type_cache.dart';
 import '../ir/scope.dart';
 import '../ir/types.dart';
 import '../ir/visitors.dart';
@@ -887,6 +888,7 @@
       type ??= findIn(Uris.dart_web_sql);
       type ??= findIn(Uris.dart_indexed_db);
       type ??= findIn(Uris.dart_typed_data);
+      type ??= findIn(Uris.dart__rti);
       type ??= findIn(Uris.dart_mirrors);
       if (type == null && required) {
         reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
@@ -1389,14 +1391,13 @@
         typeMapsForTesting[member] = builder.typeMapsForTesting = {};
       }
       node.accept(builder);
-      memberData.staticTypes = builder.cachedStaticTypes;
+      memberData.staticTypes = builder.getStaticTypeCache();
       return builder.impactBuilder;
     }
   }
 
-  Map<ir.Expression, ir.DartType> getCachedStaticTypes(KMember member) {
-    Map<ir.Expression, ir.DartType> staticTypes =
-        members.getData(member).staticTypes;
+  StaticTypeCache getCachedStaticTypes(KMember member) {
+    StaticTypeCache staticTypes = members.getData(member).staticTypes;
     assert(staticTypes != null, "No static types cached for $member.");
     return staticTypes;
   }
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 0f004e3..c76aaaa 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -19,6 +19,7 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../ir/element_map.dart';
+import '../ir/static_type_cache.dart';
 import '../ir/visitors.dart';
 import '../ir/util.dart';
 import '../js_model/element_map.dart';
@@ -669,7 +670,7 @@
 abstract class KMemberData {
   ir.Member get node;
 
-  Map<ir.Expression, ir.DartType> staticTypes;
+  StaticTypeCache staticTypes;
 
   Iterable<ConstantValue> getMetadata(IrToElementMap elementMap);
 
@@ -688,7 +689,7 @@
   Iterable<ConstantValue> _metadata;
 
   @override
-  Map<ir.Expression, ir.DartType> staticTypes;
+  StaticTypeCache staticTypes;
 
   KMemberDataImpl(this.node);
 
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index e32ea87..5415e98 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -466,7 +466,7 @@
     Selector selector = new Selector.callClosure(
         0, const <String>[], thisType.typeArguments.length);
     impactBuilder.registerDynamicUse(
-        new ConstrainedDynamicUse(selector, null, thisType.typeArguments));
+        new DynamicUse(selector, null, thisType.typeArguments));
   }
 
   @override
@@ -564,8 +564,8 @@
     // TODO(johnniwinther): Yet, alas, we need the dynamic use for now. Remove
     // this when kernel adds an `isFunctionCall` flag to
     // [ir.MethodInvocation].
-    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
-        callStructure.callSelector, null, dartTypeArguments));
+    impactBuilder.registerDynamicUse(
+        new DynamicUse(callStructure.callSelector, null, dartTypeArguments));
   }
 
   @override
@@ -579,7 +579,7 @@
     Selector selector = elementMap.getInvocationSelector(
         name, positionalArguments, namedArguments, typeArguments.length);
     List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
-    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(selector,
+    impactBuilder.registerDynamicUse(new DynamicUse(selector,
         _computeReceiverConstraint(receiverType, relation), dartTypeArguments));
   }
 
@@ -594,7 +594,7 @@
         namedArguments,
         typeArguments.length);
     List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
-    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+    impactBuilder.registerDynamicUse(new DynamicUse(
         callStructure.callSelector,
         _computeReceiverConstraint(receiverType, ClassRelation.subtype),
         dartTypeArguments));
@@ -609,7 +609,7 @@
       List<String> namedArguments,
       List<ir.DartType> typeArguments) {
     List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
-    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+    impactBuilder.registerDynamicUse(new DynamicUse(
         elementMap.getInvocationSelector(target.name, positionalArguments,
             namedArguments, typeArguments.length),
         _computeReceiverConstraint(receiverType, relation),
@@ -619,7 +619,7 @@
   @override
   void registerDynamicGet(
       ir.DartType receiverType, ClassRelation relation, ir.Name name) {
-    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+    impactBuilder.registerDynamicUse(new DynamicUse(
         new Selector.getter(elementMap.getName(name)),
         _computeReceiverConstraint(receiverType, relation),
         const <DartType>[]));
@@ -628,7 +628,7 @@
   @override
   void registerInstanceGet(
       ir.DartType receiverType, ClassRelation relation, ir.Member target) {
-    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+    impactBuilder.registerDynamicUse(new DynamicUse(
         new Selector.getter(elementMap.getName(target.name)),
         _computeReceiverConstraint(receiverType, relation),
         const <DartType>[]));
@@ -637,7 +637,7 @@
   @override
   void registerDynamicSet(
       ir.DartType receiverType, ClassRelation relation, ir.Name name) {
-    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+    impactBuilder.registerDynamicUse(new DynamicUse(
         new Selector.setter(elementMap.getName(name)),
         _computeReceiverConstraint(receiverType, relation),
         const <DartType>[]));
@@ -646,7 +646,7 @@
   @override
   void registerInstanceSet(
       ir.DartType receiverType, ClassRelation relation, ir.Member target) {
-    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+    impactBuilder.registerDynamicUse(new DynamicUse(
         new Selector.setter(elementMap.getName(target.name)),
         _computeReceiverConstraint(receiverType, relation),
         const <DartType>[]));
@@ -739,23 +739,31 @@
   }
 
   @override
-  void registerSyncForIn(ir.DartType iterableType) {
-    // TODO(johnniwinther): Use receiver constraints for the dynamic uses in
-    // strong mode.
+  void registerSyncForIn(ir.DartType iterableType, ir.DartType iteratorType,
+      ClassRelation iteratorClassRelation) {
+    Object receiverConstraint =
+        _computeReceiverConstraint(iteratorType, iteratorClassRelation);
     impactBuilder.registerFeature(Feature.SYNC_FOR_IN);
-    impactBuilder.registerDynamicUse(new DynamicUse(Selectors.iterator));
-    impactBuilder.registerDynamicUse(new DynamicUse(Selectors.current));
-    impactBuilder.registerDynamicUse(new DynamicUse(Selectors.moveNext));
+    impactBuilder.registerDynamicUse(
+        new DynamicUse(Selectors.iterator, receiverConstraint, const []));
+    impactBuilder.registerDynamicUse(
+        new DynamicUse(Selectors.current, receiverConstraint, const []));
+    impactBuilder.registerDynamicUse(
+        new DynamicUse(Selectors.moveNext, receiverConstraint, const []));
   }
 
   @override
-  void registerAsyncForIn(ir.DartType iterableType) {
-    // TODO(johnniwinther): Use receiver constraints for the dynamic uses in
-    // strong mode.
+  void registerAsyncForIn(ir.DartType iterableType, ir.DartType iteratorType,
+      ClassRelation iteratorClassRelation) {
+    Object receiverConstraint =
+        _computeReceiverConstraint(iteratorType, iteratorClassRelation);
     impactBuilder.registerFeature(Feature.ASYNC_FOR_IN);
-    impactBuilder.registerDynamicUse(new DynamicUse(Selectors.cancel));
-    impactBuilder.registerDynamicUse(new DynamicUse(Selectors.current));
-    impactBuilder.registerDynamicUse(new DynamicUse(Selectors.moveNext));
+    impactBuilder.registerDynamicUse(
+        new DynamicUse(Selectors.cancel, receiverConstraint, const []));
+    impactBuilder.registerDynamicUse(
+        new DynamicUse(Selectors.current, receiverConstraint, const []));
+    impactBuilder.registerDynamicUse(
+        new DynamicUse(Selectors.moveNext, receiverConstraint, const []));
   }
 
   @override
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index 1559108..c93e50f 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -71,7 +71,8 @@
   void registerLoadedLibraries(KernelResult kernelResult) {
     _elementMap.addComponent(kernelResult.component);
     if (_options.useCFEConstants) {
-      _irAnnotationData = processAnnotations(kernelResult.component);
+      _irAnnotationData = processAnnotations(new ModularCore(
+          kernelResult.component, _elementMap.constantEvaluator));
     }
     _annotationProcessor = new KernelAnnotationProcessor(
         elementMap, nativeBasicDataBuilder, _irAnnotationData);
diff --git a/pkg/compiler/lib/src/kernel/kernel_world.dart b/pkg/compiler/lib/src/kernel/kernel_world.dart
index c9d4200..bf9f1b0 100644
--- a/pkg/compiler/lib/src/kernel/kernel_world.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_world.dart
@@ -2,10 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import '../common/names.dart';
 import '../common_elements.dart';
-
 import '../elements/entities.dart';
-
 import '../elements/types.dart';
 import '../js_backend/annotations.dart';
 import '../js_backend/field_analysis.dart' show KFieldAnalysis;
@@ -17,25 +16,32 @@
 import '../options.dart';
 import '../universe/class_hierarchy.dart';
 import '../universe/member_usage.dart';
-import '../universe/resolution_world_builder.dart';
+import '../universe/selector.dart';
 import '../world.dart';
 
 import 'element_map_impl.dart';
 
 class KClosedWorldImpl implements KClosedWorld {
   final KernelToElementMapImpl elementMap;
+
   @override
   final KElementEnvironment elementEnvironment;
+
   @override
   final DartTypes dartTypes;
+
   @override
   final KCommonElements commonElements;
+
   @override
   final NativeData nativeData;
+
   @override
   final InterceptorData interceptorData;
+
   @override
   final BackendUsage backendUsage;
+
   @override
   final NoSuchMethodData noSuchMethodData;
 
@@ -70,6 +76,31 @@
 
   RuntimeTypesNeed _rtiNeed;
 
+  @override
+  final Set<DartType> isChecks;
+
+  final Map<Entity, Set<DartType>> staticTypeArgumentDependencies;
+
+  final Map<Selector, Set<DartType>> dynamicTypeArgumentDependencies;
+
+  @override
+  final Set<TypeVariableType> typeVariableTypeLiterals;
+
+  @override
+  final Set<Local> genericLocalFunctions;
+
+  @override
+  final Set<FunctionEntity> closurizedMembersWithFreeTypeVariables;
+
+  @override
+  final Iterable<Local> localFunctions;
+
+  @override
+  final Iterable<InterfaceType> instantiatedTypes;
+
+  @override
+  RuntimeTypesNeed get rtiNeed => _rtiNeed;
+
   KClosedWorldImpl(this.elementMap,
       {CompilerOptions options,
       this.elementEnvironment,
@@ -79,7 +110,6 @@
       this.interceptorData,
       this.backendUsage,
       this.noSuchMethodData,
-      ResolutionWorldBuilder resolutionWorldBuilder,
       RuntimeTypesNeedBuilder rtiNeedBuilder,
       this.fieldAnalysis,
       Set<ClassEntity> implementedClasses,
@@ -90,20 +120,113 @@
       this.mixinUses,
       this.typesImplementedBySubclasses,
       this.classHierarchy,
-      this.annotationsData})
+      this.annotationsData,
+      this.isChecks,
+      this.staticTypeArgumentDependencies,
+      this.dynamicTypeArgumentDependencies,
+      this.typeVariableTypeLiterals,
+      this.genericLocalFunctions,
+      this.closurizedMembersWithFreeTypeVariables,
+      this.localFunctions,
+      this.instantiatedTypes})
       : _implementedClasses = implementedClasses {
-    _rtiNeed = rtiNeedBuilder.computeRuntimeTypesNeed(
-        resolutionWorldBuilder, this, options);
+    _rtiNeed = rtiNeedBuilder.computeRuntimeTypesNeed(this, options);
   }
 
   @override
-  RuntimeTypesNeed get rtiNeed => _rtiNeed;
-
-  @override
   bool isImplemented(ClassEntity cls) {
     return _implementedClasses.contains(cls);
   }
 
   /// Needed for testing.
   Iterable<MemberEntity> get processedMembers => liveMemberUsage.keys;
+
+  @override
+  void forEachStaticTypeArgument(
+      void f(Entity function, Set<DartType> typeArguments)) {
+    staticTypeArgumentDependencies.forEach(f);
+  }
+
+  @override
+  void forEachDynamicTypeArgument(
+      void f(Selector selector, Set<DartType> typeArguments)) {
+    dynamicTypeArgumentDependencies.forEach(f);
+  }
+
+  @override
+  bool isMemberUsed(MemberEntity member) => liveMemberUsage.containsKey(member);
+
+  @override
+  void forEachGenericMethod(Function f) {
+    liveMemberUsage.forEach((MemberEntity member, MemberUsage usage) {
+      if (member is FunctionEntity &&
+          elementEnvironment.getFunctionTypeVariables(member).isNotEmpty) {
+        f(member);
+      }
+    });
+  }
+
+  @override
+  void forEachGenericInstanceMethod(Function f) {
+    liveMemberUsage.forEach((MemberEntity member, MemberUsage usage) {
+      if (member is FunctionEntity &&
+          member.isInstanceMember &&
+          elementEnvironment.getFunctionTypeVariables(member).isNotEmpty) {
+        f(member);
+      }
+    });
+  }
+
+  List<FunctionEntity> _userNoSuchMethodsCache;
+
+  @override
+  Iterable<FunctionEntity> get userNoSuchMethods {
+    if (_userNoSuchMethodsCache == null) {
+      _userNoSuchMethodsCache = <FunctionEntity>[];
+
+      liveMemberUsage.forEach((MemberEntity member, MemberUsage memberUsage) {
+        if (member is FunctionEntity && memberUsage.hasUse) {
+          if (member.isInstanceMember &&
+              member.name == Identifiers.noSuchMethod_ &&
+              !commonElements.isDefaultNoSuchMethodImplementation(member)) {
+            _userNoSuchMethodsCache.add(member);
+          }
+        }
+      });
+    }
+
+    return _userNoSuchMethodsCache;
+  }
+
+  Set<FunctionEntity> _closurizedMembersCache;
+
+  @override
+  Iterable<FunctionEntity> get closurizedMembers {
+    if (_closurizedMembersCache == null) {
+      _closurizedMembersCache = {};
+      liveMemberUsage.forEach((MemberEntity member, MemberUsage usage) {
+        if (member.isFunction && member.isInstanceMember && usage.hasRead) {
+          _closurizedMembersCache.add(member);
+        }
+      });
+    }
+    return _closurizedMembersCache;
+  }
+
+  Set<FunctionEntity> _closurizedStaticsCache;
+
+  @override
+  Iterable<FunctionEntity> get closurizedStatics {
+    if (_closurizedStaticsCache == null) {
+      _closurizedStaticsCache = {};
+      liveMemberUsage.forEach((MemberEntity member, MemberUsage usage) {
+        if (member.isFunction &&
+            (member.isStatic || member.isTopLevel) &&
+            usage.hasRead) {
+          _closurizedStaticsCache.add(member);
+        }
+      });
+    }
+    return _closurizedStaticsCache;
+  }
 }
diff --git a/pkg/compiler/lib/src/old_to_new_api.dart b/pkg/compiler/lib/src/old_to_new_api.dart
index 808e242..a5d7c45 100644
--- a/pkg/compiler/lib/src/old_to_new_api.dart
+++ b/pkg/compiler/lib/src/old_to_new_api.dart
@@ -23,6 +23,8 @@
 
   @override
   Future<Input> readFromUri(Uri uri, {InputKind inputKind: InputKind.UTF8}) {
+    // The switch handles all enum values, but not null.
+    // ignore: missing_return
     return _inputProvider(uri).then((/*String|List<int>*/ data) {
       switch (inputKind) {
         case InputKind.UTF8:
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index f91b15b..acce37c 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -76,6 +76,16 @@
   /// If this is set, the compilation stops after type inference.
   Uri writeDataUri;
 
+  /// Location from which codegen data is read.
+  ///
+  /// If this is set, the compilation starts at codegen enqueueing.
+  Uri readCodegenUri;
+
+  /// Location to which codegen data is serialized.
+  ///
+  /// If this is set, the compilation stops after code generation.
+  Uri writeCodegenUri;
+
   /// Whether to run only the CFE and emit the generated kernel file in
   /// [outputUri].
   bool cfeOnly = false;
@@ -215,9 +225,6 @@
   /// Whether to generate code containing user's `assert` statements.
   bool enableUserAssertions = false;
 
-  /// Whether to generate output even when there are compile-time errors.
-  bool generateCodeWithCompileTimeErrors = false;
-
   /// Whether to generate a source-map file together with the output program.
   bool generateSourceMap = true;
 
@@ -328,6 +335,13 @@
   /// If specified, a bundle of optimizations to enable (or disable).
   int optimizationLevel = null;
 
+  /// The shard to serialize when using [writeCodegenUri].
+  int codegenShard;
+
+  /// The number of shards to serialize when using [writeCodegenUri] or to
+  /// deserialize when using [readCodegenUri].
+  int codegenShards;
+
   // -------------------------------------------------
   // Options for deprecated features
   // -------------------------------------------------
@@ -385,8 +399,6 @@
       ..experimentCallInstrumentation =
           _hasOption(options, Flags.experimentCallInstrumentation)
       ..experimentNewRti = _hasOption(options, Flags.experimentNewRti)
-      ..generateCodeWithCompileTimeErrors =
-          _hasOption(options, Flags.generateCodeWithCompileTimeErrors)
       ..generateSourceMap = !_hasOption(options, Flags.noSourceMaps)
       ..outputUri = _extractUriOption(options, '--out=')
       ..platformBinaries =
@@ -412,6 +424,10 @@
           _extractUriListOption(options, '${Flags.dillDependencies}')
       ..readDataUri = _extractUriOption(options, '${Flags.readData}=')
       ..writeDataUri = _extractUriOption(options, '${Flags.writeData}=')
+      ..readCodegenUri = _extractUriOption(options, '${Flags.readCodegen}=')
+      ..writeCodegenUri = _extractUriOption(options, '${Flags.writeCodegen}=')
+      ..codegenShard = _extractIntOption(options, '${Flags.codegenShard}=')
+      ..codegenShards = _extractIntOption(options, '${Flags.codegenShards}=')
       ..cfeOnly = _hasOption(options, Flags.cfeOnly)
       ..debugGlobalInference = _hasOption(options, Flags.debugGlobalInference);
   }
@@ -464,9 +480,6 @@
       }
     }
 
-    // TODO(johnniwinther): Should we support this in the future?
-    generateCodeWithCompileTimeErrors = false;
-
     // Strong mode always trusts type annotations (inferred or explicit), so
     // assignments checks should be trusted.
     assignmentCheckPolicy = CheckPolicy.trusted;
@@ -541,10 +554,15 @@
 }
 
 Uri _extractUriOption(List<String> options, String prefix) {
-  var option = _extractStringOption(options, prefix, null);
+  String option = _extractStringOption(options, prefix, null);
   return (option == null) ? null : Uri.parse(option);
 }
 
+int _extractIntOption(List<String> options, String prefix) {
+  String option = _extractStringOption(options, prefix, null);
+  return (option == null) ? null : int.parse(option);
+}
+
 bool _hasOption(List<String> options, String option) {
   return options.indexOf(option) >= 0;
 }
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index dfe4e9b..a1af8e8 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -34,7 +34,12 @@
 
   Map<Type, IndexedSink> _generalCaches = {};
 
-  AbstractDataSink({this.useDataKinds: false}) {
+  EntityWriter _entityWriter = const EntityWriter();
+  CodegenWriter _codegenWriter;
+
+  final Map<String, int> tagFrequencyMap;
+
+  AbstractDataSink({this.useDataKinds: false, this.tagFrequencyMap}) {
     _dartTypeWriter = new DartTypeWriter(this);
     _dartTypeNodeWriter = new DartTypeNodeWriter(this);
     _stringIndex = new IndexedSink<String>(this);
@@ -45,6 +50,10 @@
 
   @override
   void begin(String tag) {
+    if (tagFrequencyMap != null) {
+      tagFrequencyMap[tag] ??= 0;
+      tagFrequencyMap[tag]++;
+    }
     if (useDataKinds) {
       _tags ??= <String>[];
       _tags.add(tag);
@@ -305,22 +314,26 @@
 
   @override
   void writeLibrary(IndexedLibrary value) {
-    writeInt(value.libraryIndex);
+    _entityWriter.writeLibraryToDataSink(this, value);
   }
 
   @override
   void writeClass(IndexedClass value) {
-    writeInt(value.classIndex);
+    _entityWriter.writeClassToDataSink(this, value);
   }
 
   @override
   void writeTypedef(IndexedTypedef value) {
-    writeInt(value.typedefIndex);
+    _entityWriter.writeTypedefToDataSink(this, value);
   }
 
   @override
   void writeMember(IndexedMember value) {
-    writeInt(value.memberIndex);
+    _entityWriter.writeMemberToDataSink(this, value);
+  }
+
+  void writeTypeVariable(IndexedTypeVariable value) {
+    _entityWriter.writeTypeVariableToDataSink(this, value);
   }
 
   @override
@@ -439,12 +452,25 @@
         break;
       case ConstantValueKind.NON_CONSTANT:
         break;
-      case ConstantValueKind.DEFERRED_GLOBAL:
       case ConstantValueKind.INTERCEPTOR:
-      case ConstantValueKind.SYNTHETIC:
-        // These are only created in the SSA graph builder.
-        throw new UnsupportedError(
-            "Unsupported constant value kind ${value.kind}.");
+        InterceptorConstantValue constant = value;
+        writeClass(constant.cls);
+        break;
+      case ConstantValueKind.DEFERRED_GLOBAL:
+        DeferredGlobalConstantValue constant = value;
+        writeConstant(constant.referenced);
+        writeOutputUnitReference(constant.unit);
+        break;
+      case ConstantValueKind.DUMMY_INTERCEPTOR:
+        DummyInterceptorConstantValue constant = value;
+        writeAbstractValue(constant.abstractValue);
+        break;
+      case ConstantValueKind.UNREACHABLE:
+        break;
+      case ConstantValueKind.JS_NAME:
+        JsNameConstantValue constant = value;
+        writeJsNode(constant.name);
+        break;
     }
   }
 
@@ -474,6 +500,42 @@
     _writeBool(value.isDeferred);
   }
 
+  @override
+  void registerEntityWriter(EntityWriter writer) {
+    assert(writer != null);
+    _entityWriter = writer;
+  }
+
+  @override
+  void registerCodegenWriter(CodegenWriter writer) {
+    assert(writer != null);
+    assert(_codegenWriter == null);
+    _codegenWriter = writer;
+  }
+
+  @override
+  void writeOutputUnitReference(OutputUnit value) {
+    assert(
+        _codegenWriter != null,
+        "Can not serialize an OutputUnit reference "
+        "without a registered codegen writer.");
+    _codegenWriter.writeOutputUnitReference(this, value);
+  }
+
+  @override
+  void writeAbstractValue(AbstractValue value) {
+    assert(_codegenWriter != null,
+        "Can not serialize an AbstractValue without a registered codegen writer.");
+    _codegenWriter.writeAbstractValue(this, value);
+  }
+
+  @override
+  void writeJsNode(js.Node value) {
+    assert(_codegenWriter != null,
+        "Can not serialize a JS ndoe without a registered codegen writer.");
+    _codegenWriter.writeJsNode(this, value);
+  }
+
   /// Actual serialization of a section begin tag, implemented by subclasses.
   void _begin(String tag);
 
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index f4160ce..a2fa583 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -9,9 +9,11 @@
 abstract class AbstractDataSource extends DataSourceMixin
     implements DataSource {
   final bool useDataKinds;
+  EntityReader _entityReader = const EntityReader();
   ComponentLookup _componentLookup;
   EntityLookup _entityLookup;
   LocalLookup _localLookup;
+  CodegenReader _codegenReader;
 
   IndexedSource<String> _stringIndex;
   IndexedSource<Uri> _uriIndex;
@@ -65,12 +67,31 @@
     _localLookup = localLookup;
   }
 
+  @override
+  void registerEntityReader(EntityReader reader) {
+    assert(reader != null);
+    _entityReader = reader;
+  }
+
   LocalLookup get localLookup {
     assert(_localLookup != null);
     return _localLookup;
   }
 
   @override
+  void registerCodegenReader(CodegenReader reader) {
+    assert(reader != null);
+    assert(_codegenReader == null);
+    _codegenReader = reader;
+  }
+
+  @override
+  void deregisterCodegenReader(CodegenReader reader) {
+    assert(_codegenReader == reader);
+    _codegenReader = null;
+  }
+
+  @override
   E readCached<E>(E f()) {
     IndexedSource source = _generalCaches[E] ??= new IndexedSource<E>(this);
     return source.read(f);
@@ -78,38 +99,27 @@
 
   @override
   IndexedLibrary readLibrary() {
-    return getIndexedLibrary(readInt());
+    return _entityReader.readLibraryFromDataSource(this, entityLookup);
   }
 
   @override
   IndexedClass readClass() {
-    return getIndexedClass(readInt());
+    return _entityReader.readClassFromDataSource(this, entityLookup);
   }
 
   @override
   IndexedTypedef readTypedef() {
-    return getIndexedTypedef(readInt());
+    return _entityReader.readTypedefFromDataSource(this, entityLookup);
   }
 
   @override
   IndexedMember readMember() {
-    return getIndexedMember(readInt());
+    return _entityReader.readMemberFromDataSource(this, entityLookup);
   }
 
-  IndexedLibrary getIndexedLibrary(int libraryIndex) =>
-      entityLookup.getLibraryByIndex(libraryIndex);
-
-  IndexedClass getIndexedClass(int classIndex) =>
-      entityLookup.getClassByIndex(classIndex);
-
-  IndexedTypedef getIndexedTypedef(int typedefIndex) =>
-      entityLookup.getTypedefByIndex(typedefIndex);
-
-  IndexedMember getIndexedMember(int memberIndex) =>
-      entityLookup.getMemberByIndex(memberIndex);
-
-  IndexedTypeVariable getIndexedTypeVariable(int typeVariableIndex) =>
-      entityLookup.getTypeVariableByIndex(typeVariableIndex);
+  IndexedTypeVariable readTypeVariable() {
+    return _entityReader.readTypeVariableFromDataSource(this, entityLookup);
+  }
 
   List<DartType> _readDartTypes(
       List<FunctionTypeVariable> functionTypeVariables) {
@@ -156,7 +166,7 @@
       case DartTypeKind.voidType:
         return const VoidType();
       case DartTypeKind.typeVariable:
-        return new TypeVariableType(getIndexedTypeVariable(readInt()));
+        return new TypeVariableType(readTypeVariable());
       case DartTypeKind.functionTypeVariable:
         int index = readInt();
         assert(0 <= index && index < functionTypeVariables.length);
@@ -192,11 +202,11 @@
             typeVariables);
 
       case DartTypeKind.interfaceType:
-        IndexedClass cls = getIndexedClass(readInt());
+        IndexedClass cls = readClass();
         List<DartType> typeArguments = _readDartTypes(functionTypeVariables);
         return new InterfaceType(cls, typeArguments);
       case DartTypeKind.typedef:
-        IndexedTypedef typedef = getIndexedTypedef(readInt());
+        IndexedTypedef typedef = readTypedef();
         List<DartType> typeArguments = _readDartTypes(functionTypeVariables);
         DartType unaliased = _readDartType(functionTypeVariables);
         return new TypedefType(typedef, typeArguments, unaliased);
@@ -495,11 +505,21 @@
         return new InstantiationConstantValue(typeArguments, function);
       case ConstantValueKind.NON_CONSTANT:
         return new NonConstantValue();
-      case ConstantValueKind.DEFERRED_GLOBAL:
       case ConstantValueKind.INTERCEPTOR:
-      case ConstantValueKind.SYNTHETIC:
-        // These are only created in the SSA graph builder.
-        throw new UnsupportedError("Unsupported constant value kind ${kind}.");
+        ClassEntity cls = readClass();
+        return new InterceptorConstantValue(cls);
+      case ConstantValueKind.DEFERRED_GLOBAL:
+        ConstantValue constant = readConstant();
+        OutputUnit unit = readOutputUnitReference();
+        return new DeferredGlobalConstantValue(constant, unit);
+      case ConstantValueKind.DUMMY_INTERCEPTOR:
+        AbstractValue abstractValue = readAbstractValue();
+        return new DummyInterceptorConstantValue(abstractValue);
+      case ConstantValueKind.UNREACHABLE:
+        return const UnreachableConstantValue();
+      case ConstantValueKind.JS_NAME:
+        js.LiteralString name = readJsNode();
+        return new JsNameConstantValue(name);
     }
     throw new UnsupportedError("Unexpexted constant value kind ${kind}.");
   }
@@ -626,6 +646,31 @@
     return new ImportEntity(isDeferred, name, uri, enclosingLibraryUri);
   }
 
+  @override
+  OutputUnit readOutputUnitReference() {
+    assert(
+        _codegenReader != null,
+        "Can not deserialize an OutputUnit reference "
+        "without a registered codegen reader.");
+    return _codegenReader.readOutputUnitReference(this);
+  }
+
+  @override
+  AbstractValue readAbstractValue() {
+    assert(
+        _codegenReader != null,
+        "Can not deserialize an AbstractValue "
+        "without a registered codegen reader.");
+    return _codegenReader.readAbstractValue(this);
+  }
+
+  @override
+  js.Node readJsNode() {
+    assert(_codegenReader != null,
+        "Can not deserialize a JS node without a registered codegen reader.");
+    return _codegenReader.readJsNode(this);
+  }
+
   /// Actual deserialization of a section begin tag, implemented by subclasses.
   void _begin(String tag);
 
diff --git a/pkg/compiler/lib/src/serialization/binary_sink.dart b/pkg/compiler/lib/src/serialization/binary_sink.dart
index 3f771b4..6d46fb4 100644
--- a/pkg/compiler/lib/src/serialization/binary_sink.dart
+++ b/pkg/compiler/lib/src/serialization/binary_sink.dart
@@ -12,9 +12,10 @@
   BufferedSink _bufferedSink;
   int _length = 0;
 
-  BinarySink(this.sink, {bool useDataKinds: false})
+  BinarySink(this.sink,
+      {bool useDataKinds: false, Map<String, int> tagFrequencyMap})
       : _bufferedSink = new BufferedSink(sink),
-        super(useDataKinds: useDataKinds);
+        super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
 
   @override
   void _begin(String tag) {
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index 40cc83d..b73a8c9 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -130,7 +130,7 @@
       List<FunctionTypeVariable> functionTypeVariables) {
     _sink.writeEnum(DartTypeKind.typeVariable);
     IndexedTypeVariable typeVariable = type.element;
-    _sink.writeInt(typeVariable.typeVariableIndex);
+    _sink.writeTypeVariable(typeVariable);
   }
 
   @override
@@ -336,6 +336,7 @@
 class IndexedSink<E> {
   final AbstractDataSink _sink;
   final Map<E, int> _cache = {};
+  Set<E> _current = {};
 
   IndexedSink(this._sink);
 
@@ -346,10 +347,14 @@
   void write(E value, void writeValue(E value)) {
     int index = _cache[value];
     if (index == null) {
+      if (!_current.add(value)) {
+        throw new ArgumentError("Cyclic dependency on cached value: $value");
+      }
       index = _cache.length;
-      _cache[value] = index;
       _sink._writeIntInternal(index);
       writeValue(value);
+      _cache[value] = index;
+      _current.remove(value);
     } else {
       _sink._writeIntInternal(index);
     }
diff --git a/pkg/compiler/lib/src/serialization/mixins.dart b/pkg/compiler/lib/src/serialization/mixins.dart
index 695d112..2de3e8a 100644
--- a/pkg/compiler/lib/src/serialization/mixins.dart
+++ b/pkg/compiler/lib/src/serialization/mixins.dart
@@ -314,6 +314,15 @@
   }
 
   @override
+  ImportEntity readImportOrNull() {
+    bool hasClass = readBool();
+    if (hasClass) {
+      return readImport();
+    }
+    return null;
+  }
+
+  @override
   List<ImportEntity> readImports({bool emptyAsNull: false}) {
     int count = readInt();
     if (count == 0 && emptyAsNull) return null;
@@ -366,6 +375,15 @@
   ir.LibraryDependency readLibraryDependencyNodeOrNull() {
     return readValueOrNull(readLibraryDependencyNode);
   }
+
+  @override
+  js.Node readJsNodeOrNull() {
+    bool hasValue = readBool();
+    if (hasValue) {
+      return readJsNode();
+    }
+    return null;
+  }
 }
 
 /// Mixin that implements all convenience methods of [DataSink].
@@ -693,6 +711,14 @@
   }
 
   @override
+  void writeImportOrNull(ImportEntity value) {
+    writeBool(value != null);
+    if (value != null) {
+      writeImport(value);
+    }
+  }
+
+  @override
   void writeImports(Iterable<ImportEntity> values, {bool allowNull: false}) {
     if (values == null) {
       assert(allowNull);
@@ -751,4 +777,12 @@
   void writeLibraryDependencyNodeOrNull(ir.LibraryDependency value) {
     writeValueOrNull(value, writeLibraryDependencyNode);
   }
+
+  @override
+  void writeJsNodeOrNull(js.Node value) {
+    writeBool(value != null);
+    if (value != null) {
+      writeJsNode(value);
+    }
+  }
 }
diff --git a/pkg/compiler/lib/src/serialization/object_sink.dart b/pkg/compiler/lib/src/serialization/object_sink.dart
index 31376e3..82c8885 100644
--- a/pkg/compiler/lib/src/serialization/object_sink.dart
+++ b/pkg/compiler/lib/src/serialization/object_sink.dart
@@ -11,8 +11,8 @@
 class ObjectSink extends AbstractDataSink {
   List<dynamic> _data;
 
-  ObjectSink(this._data, {bool useDataKinds})
-      : super(useDataKinds: useDataKinds);
+  ObjectSink(this._data, {bool useDataKinds, Map<String, int> tagFrequencyMap})
+      : super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
 
   @override
   void _begin(String tag) {
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 8623f87..92e6ad0 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -11,12 +11,15 @@
 import '../closure.dart';
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
+import '../deferred_load.dart';
 import '../diagnostics/source_span.dart';
 import '../elements/entities.dart';
 import '../elements/indexed.dart';
 import '../elements/types.dart';
+import '../inferrer/abstract_value_domain.dart';
 import '../ir/constants.dart';
 import '../ir/static_type_base.dart';
+import '../js/js.dart' as js;
 import '../js_model/closure.dart';
 import '../js_model/locals.dart';
 
@@ -357,6 +360,9 @@
   /// Writes the import [value] to this data sink.
   void writeImport(ImportEntity value);
 
+  /// Writes the potentially `null` import [value] to this data sink.
+  void writeImportOrNull(ImportEntity value);
+
   /// Writes import [values] to this data sink. If [allowNull] is `true`,
   /// [values] is allowed to be `null`.
   ///
@@ -372,6 +378,34 @@
   /// [DataSource.readImportMap].
   void writeImportMap<V>(Map<ImportEntity, V> map, void f(V value),
       {bool allowNull: false});
+
+  /// Writes an abstract [value] to this data sink.
+  ///
+  /// This feature is only available a [CodegenWriter] has been registered.
+  void writeAbstractValue(AbstractValue value);
+
+  /// Writes a reference to the output unit [value] to this data sink.
+  ///
+  /// This feature is only available a [CodegenWriter] has been registered.
+  void writeOutputUnitReference(OutputUnit value);
+
+  /// Writes a js node [value] to this data sink.
+  ///
+  /// This feature is only available a [CodegenWriter] has been registered.
+  void writeJsNode(js.Node value);
+
+  /// Writes a potentially `null` js node [value] to this data sink.
+  ///
+  /// This feature is only available a [CodegenWriter] has been registered.
+  void writeJsNodeOrNull(js.Node value);
+
+  /// Register an [EntityWriter] with this data sink for non-default encoding
+  /// of entity references.
+  void registerEntityWriter(EntityWriter writer);
+
+  /// Register a [CodegenWriter] with this data sink to support serialization
+  /// of codegen only data.
+  void registerCodegenWriter(CodegenWriter writer);
 }
 
 /// Interface for deserialization.
@@ -396,10 +430,22 @@
   /// deserialization of references to indexed entities.
   void registerEntityLookup(EntityLookup entityLookup);
 
+  /// Registers an [EntityReader] with this data source for non-default encoding
+  /// of entity references.
+  void registerEntityReader(EntityReader reader);
+
   /// Registers a [LocalLookup] object with this data source to support
   /// deserialization of references to locals.
   void registerLocalLookup(LocalLookup localLookup);
 
+  /// Registers a [CodegenReader] with this data source to support
+  /// deserialization of codegen only data.
+  void registerCodegenReader(CodegenReader reader);
+
+  /// Unregisters the [CodegenReader] from this data source to remove support
+  /// for deserialization of codegen only data.
+  void deregisterCodegenReader(CodegenReader reader);
+
   /// Reads a reference to an [E] value from this data source. If the value has
   /// not yet been deserialized, [f] is called to deserialize the value itself.
   E readCached<E>(E f());
@@ -680,6 +726,9 @@
   /// Reads a import from this data source.
   ImportEntity readImport();
 
+  /// Reads a potentially `null` import from this data source.
+  ImportEntity readImportOrNull();
+
   /// Reads a list of imports from this data source. If [emptyAsNull] is
   /// `true`, `null` is returned instead of an empty list.
   ///
@@ -694,6 +743,26 @@
   /// This is a convenience method to be used together with
   /// [DataSink.writeImportMap].
   Map<ImportEntity, V> readImportMap<V>(V f(), {bool emptyAsNull: false});
+
+  /// Reads an [AbstractValue] from this data source.
+  ///
+  /// This feature is only available a [CodegenReader] has been registered.
+  AbstractValue readAbstractValue();
+
+  /// Reads a reference to an [OutputUnit] from this data source.
+  ///
+  /// This feature is only available a [CodegenReader] has been registered.
+  OutputUnit readOutputUnitReference();
+
+  /// Reads a [js.Node] value from this data source.
+  ///
+  /// This feature is only available a [CodegenReader] has been registered.
+  js.Node readJsNode();
+
+  /// Reads a potentially `null` [js.Node] value from this data source.
+  ///
+  /// This feature is only available a [CodegenReader] has been registered.
+  js.Node readJsNodeOrNull();
 }
 
 /// Interface used for looking up entities by index during deserialization.
@@ -714,7 +783,76 @@
   IndexedTypeVariable getTypeVariableByIndex(int index);
 }
 
+/// Decoding strategy for entity references.
+class EntityReader {
+  const EntityReader();
+
+  IndexedLibrary readLibraryFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    return entityLookup.getLibraryByIndex(source.readInt());
+  }
+
+  IndexedClass readClassFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    return entityLookup.getClassByIndex(source.readInt());
+  }
+
+  IndexedTypedef readTypedefFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    return entityLookup.getTypedefByIndex(source.readInt());
+  }
+
+  IndexedMember readMemberFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    return entityLookup.getMemberByIndex(source.readInt());
+  }
+
+  IndexedTypeVariable readTypeVariableFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    return entityLookup.getTypeVariableByIndex(source.readInt());
+  }
+}
+
+/// Encoding strategy for entity references.
+class EntityWriter {
+  const EntityWriter();
+
+  void writeLibraryToDataSink(DataSink sink, IndexedLibrary value) {
+    sink.writeInt(value.libraryIndex);
+  }
+
+  void writeClassToDataSink(DataSink sink, IndexedClass value) {
+    sink.writeInt(value.classIndex);
+  }
+
+  void writeTypedefToDataSink(DataSink sink, IndexedTypedef value) {
+    sink.writeInt(value.typedefIndex);
+  }
+
+  void writeMemberToDataSink(DataSink sink, IndexedMember value) {
+    sink.writeInt(value.memberIndex);
+  }
+
+  void writeTypeVariableToDataSink(DataSink sink, IndexedTypeVariable value) {
+    sink.writeInt(value.typeVariableIndex);
+  }
+}
+
 /// Interface used for looking up locals by index during deserialization.
 abstract class LocalLookup {
   Local getLocalByIndex(MemberEntity memberContext, int index);
 }
+
+/// Interface used for reading codegen only data during deserialization.
+abstract class CodegenReader {
+  AbstractValue readAbstractValue(DataSource source);
+  OutputUnit readOutputUnitReference(DataSource source);
+  js.Node readJsNode(DataSource source);
+}
+
+/// Interface used for writing codegen only data during serialization.
+abstract class CodegenWriter {
+  void writeAbstractValue(DataSink sink, AbstractValue value);
+  void writeOutputUnitReference(DataSink sink, OutputUnit value);
+  void writeJsNode(DataSink sink, js.Node node);
+}
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 56ab4bd..61771d5 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -7,16 +7,20 @@
 import 'package:kernel/binary/ast_from_binary.dart' as ir;
 import 'package:kernel/binary/ast_to_binary.dart' as ir;
 import '../../compiler_new.dart' as api;
+import '../backend_strategy.dart';
+import '../common/codegen.dart';
 import '../common/tasks.dart';
-import '../compiler.dart';
 import '../diagnostics/diagnostic_listener.dart';
+import '../elements/entities.dart';
 import '../environment.dart';
 import '../inferrer/abstract_value_domain.dart';
 import '../inferrer/types.dart';
+import '../js_backend/backend.dart';
 import '../js_backend/inferred_data.dart';
 import '../js_model/js_world.dart';
 import '../options.dart';
 import '../util/sink_adapter.dart';
+import '../world.dart';
 import 'serialization.dart';
 
 void serializeGlobalTypeInferenceResults(
@@ -45,21 +49,26 @@
 }
 
 class SerializationTask extends CompilerTask {
-  final Compiler compiler;
+  final CompilerOptions _options;
+  final DiagnosticReporter _reporter;
+  final api.CompilerInput _provider;
+  final api.CompilerOutput _outputProvider;
 
-  SerializationTask(this.compiler, Measurer measurer) : super(measurer);
+  SerializationTask(this._options, this._reporter, this._provider,
+      this._outputProvider, Measurer measurer)
+      : super(measurer);
 
   @override
   String get name => 'Serialization';
 
-  void serialize(GlobalTypeInferenceResults results) {
+  void serializeGlobalTypeInference(GlobalTypeInferenceResults results) {
     measureSubtask('serialize dill', () {
       // TODO(sigmund): remove entirely: we will do this immediately as soon as
       // we get the component in the kernel/loader.dart task once we refactor
       // how we apply our modular kernel transformation for super mixin calls.
-      compiler.reporter.log('Writing dill to ${compiler.options.outputUri}');
+      _reporter.log('Writing dill to ${_options.outputUri}');
       api.BinaryOutputSink dillOutput =
-          compiler.outputProvider.createBinarySink(compiler.options.outputUri);
+          _outputProvider.createBinarySink(_options.outputUri);
       JsClosedWorld closedWorld = results.closedWorld;
       ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
       BinaryOutputSinkAdapter irSink = new BinaryOutputSinkAdapter(dillOutput);
@@ -69,40 +78,99 @@
     });
 
     measureSubtask('serialize data', () {
-      compiler.reporter.log('Writing data to ${compiler.options.writeDataUri}');
-      api.BinaryOutputSink dataOutput = compiler.outputProvider
-          .createBinarySink(compiler.options.writeDataUri);
+      _reporter.log('Writing data to ${_options.writeDataUri}');
+      api.BinaryOutputSink dataOutput =
+          _outputProvider.createBinarySink(_options.writeDataUri);
       DataSink sink = new BinarySink(new BinaryOutputSinkAdapter(dataOutput));
       serializeGlobalTypeInferenceResults(results, sink);
     });
   }
 
-  Future<GlobalTypeInferenceResults> deserialize() async {
+  Future<GlobalTypeInferenceResults> deserializeGlobalTypeInference(
+      Environment environment,
+      AbstractValueStrategy abstractValueStrategy) async {
     ir.Component component =
         await measureIoSubtask('deserialize dill', () async {
-      compiler.reporter.log('Reading dill from ${compiler.options.entryPoint}');
-      api.Input<List<int>> dillInput = await compiler.provider.readFromUri(
-          compiler.options.entryPoint,
-          inputKind: api.InputKind.binary);
+      _reporter.log('Reading dill from ${_options.entryPoint}');
+      api.Input<List<int>> dillInput = await _provider
+          .readFromUri(_options.entryPoint, inputKind: api.InputKind.binary);
       ir.Component component = new ir.Component();
       new ir.BinaryBuilder(dillInput.data).readComponent(component);
       return component;
     });
 
     return await measureIoSubtask('deserialize data', () async {
-      compiler.reporter
-          .log('Reading data from ${compiler.options.readDataUri}');
-      api.Input<List<int>> dataInput = await compiler.provider.readFromUri(
-          compiler.options.readDataUri,
-          inputKind: api.InputKind.binary);
+      _reporter.log('Reading data from ${_options.readDataUri}');
+      api.Input<List<int>> dataInput = await _provider
+          .readFromUri(_options.readDataUri, inputKind: api.InputKind.binary);
       DataSource source = new BinarySourceImpl(dataInput.data);
-      return deserializeGlobalTypeInferenceResults(
-          compiler.options,
-          compiler.reporter,
-          compiler.environment,
-          compiler.abstractValueStrategy,
-          component,
-          source);
+      return deserializeGlobalTypeInferenceResults(_options, _reporter,
+          environment, abstractValueStrategy, component, source);
     });
   }
+
+  void serializeCodegen(
+      BackendStrategy backendStrategy, CodegenResults codegenResults) {
+    GlobalTypeInferenceResults globalTypeInferenceResults =
+        codegenResults.globalTypeInferenceResults;
+    JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
+    int shard = _options.codegenShard;
+    int shards = _options.codegenShards;
+    Map<MemberEntity, CodegenResult> results = {};
+    int index = 0;
+    EntityWriter entityWriter =
+        backendStrategy.forEachCodegenMember((MemberEntity member) {
+      if (index % shards == shard) {
+        CodegenResult codegenResult = codegenResults.getCodegenResults(member);
+        results[member] = codegenResult;
+      }
+      index++;
+    });
+    measureSubtask('serialize codegen', () {
+      Uri uri = Uri.parse('${_options.writeCodegenUri}$shard');
+      api.BinaryOutputSink dataOutput = _outputProvider.createBinarySink(uri);
+      DataSink sink = new BinarySink(new BinaryOutputSinkAdapter(dataOutput));
+      _reporter.log('Writing data to ${uri}');
+      sink.registerEntityWriter(entityWriter);
+      sink.registerCodegenWriter(new CodegenWriterImpl(closedWorld));
+      sink.writeMemberMap(
+          results, (CodegenResult result) => result.writeToDataSink(sink));
+      sink.close();
+    });
+  }
+
+  Future<CodegenResults> deserializeCodegen(
+      BackendStrategy backendStrategy,
+      GlobalTypeInferenceResults globalTypeInferenceResults,
+      CodegenInputs codegenInputs) async {
+    int shards = _options.codegenShards;
+    JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
+    Map<MemberEntity, CodegenResult> results = {};
+    for (int shard = 0; shard < shards; shard++) {
+      Uri uri = Uri.parse('${_options.readCodegenUri}$shard');
+      await measureIoSubtask('deserialize codegen', () async {
+        _reporter.log('Reading data from ${uri}');
+        api.Input<List<int>> dataInput =
+            await _provider.readFromUri(uri, inputKind: api.InputKind.binary);
+        DataSource source = new BinarySourceImpl(dataInput.data);
+        backendStrategy.prepareCodegenReader(source);
+        Map<MemberEntity, CodegenResult> codegenResults =
+            source.readMemberMap(() {
+          List<ModularName> modularNames = [];
+          List<ModularExpression> modularExpressions = [];
+          CodegenReader reader = new CodegenReaderImpl(
+              closedWorld, modularNames, modularExpressions);
+          source.registerCodegenReader(reader);
+          CodegenResult result = CodegenResult.readFromDataSource(
+              source, modularNames, modularExpressions);
+          source.deregisterCodegenReader(reader);
+          return result;
+        });
+        _reporter.log('Read ${codegenResults.length} members from ${uri}');
+        results.addAll(codegenResults);
+      });
+    }
+    return new DeserializedCodegenResults(
+        globalTypeInferenceResults, codegenInputs, results);
+  }
 }
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 7070b01..9c0a6a5 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:js_runtime/shared/embedded_names.dart';
 import 'package:kernel/ast.dart' as ir;
 
 import '../closure.dart';
@@ -9,14 +10,9 @@
 import '../common/codegen.dart' show CodegenRegistry;
 import '../common/names.dart';
 import '../common_elements.dart';
-import '../compiler.dart';
 import '../constants/constant_system.dart' as constant_system;
-import '../constants/values.dart'
-    show
-        ConstantValue,
-        InterceptorConstantValue,
-        StringConstantValue,
-        TypeConstantValue;
+import '../constants/values.dart';
+import '../deferred_load.dart';
 import '../dump_info.dart';
 import '../elements/entities.dart';
 import '../elements/jumps.dart';
@@ -25,13 +21,19 @@
 import '../inferrer/abstract_value_domain.dart';
 import '../inferrer/types.dart';
 import '../io/source_information.dart';
+import '../ir/static_type.dart';
 import '../ir/static_type_provider.dart';
 import '../ir/util.dart';
 import '../js/js.dart' as js;
+import '../js_backend/backend.dart' show FunctionInlineCache;
 import '../js_backend/field_analysis.dart'
     show FieldAnalysisData, JFieldAnalysis;
-import '../js_backend/backend.dart' show FunctionInlineCache, JavaScriptBackend;
-import '../js_emitter/js_emitter.dart' show NativeEmitter;
+import '../js_backend/interceptor_data.dart';
+import '../js_backend/inferred_data.dart';
+import '../js_backend/namer.dart' show ModularNamer;
+import '../js_backend/native_data.dart';
+import '../js_backend/runtime_types.dart';
+import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
 import '../js_model/locals.dart' show JumpVisitor;
 import '../js_model/elements.dart' show JGeneratorBody;
 import '../js_model/element_map.dart';
@@ -39,21 +41,20 @@
 import '../kernel/invocation_mirror_constants.dart';
 import '../native/behavior.dart';
 import '../native/js.dart';
+import '../options.dart';
+import '../tracer.dart';
 import '../universe/call_structure.dart';
-import '../universe/codegen_world_builder.dart';
 import '../universe/feature.dart';
 import '../universe/selector.dart';
 import '../universe/side_effects.dart' show SideEffects;
 import '../universe/target_checks.dart' show TargetChecks;
 import '../universe/use.dart' show ConstantUse, StaticUse;
 import '../world.dart';
-import 'graph_builder.dart';
 import 'jump_handler.dart';
 import 'kernel_string_builder.dart';
 import 'locals_handler.dart';
 import 'loop_handler.dart';
 import 'nodes.dart';
-import 'ssa.dart';
 import 'ssa_branch_builder.dart';
 import 'switch_continue_analysis.dart';
 import 'type_builder.dart';
@@ -81,18 +82,43 @@
       this.staticTypeProvider);
 }
 
-class KernelSsaGraphBuilder extends ir.Visitor
-    with GraphBuilder, SsaBuilderFieldMixin {
-  @override
-  final MemberEntity targetElement;
-  final MemberEntity initialTargetElement;
+class KernelSsaGraphBuilder extends ir.Visitor {
+  /// Holds the resulting SSA graph.
+  final HGraph graph = new HGraph();
 
-  @override
+  /// True if the builder is processing nodes inside a try statement. This is
+  /// important for generating control flow out of a try block like returns or
+  /// breaks.
+  bool _inTryStatement = false;
+
+  /// Used to track the locals while building the graph.
+  LocalsHandler localsHandler;
+
+  /// A stack of instructions.
+  ///
+  /// We build the SSA graph by simulating a stack machine.
+  List<HInstruction> stack = <HInstruction>[];
+
+  /// The count of nested loops we are currently building.
+  ///
+  /// The loop nesting is consulted when inlining a function invocation. The
+  /// inlining heuristics take this information into account.
+  int loopDepth = 0;
+
+  /// A mapping from jump targets to their handlers.
+  Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{};
+
+  final CompilerOptions options;
+  final DiagnosticReporter reporter;
+  final ModularEmitter _emitter;
+  final ModularNamer _namer;
+  final MemberEntity targetElement;
+  final MemberEntity _initialTargetElement;
   final JClosedWorld closedWorld;
-  final CodegenWorldBuilder _worldBuilder;
-  @override
   final CodegenRegistry registry;
-  final ClosureData closureDataLookup;
+  final ClosureData _closureDataLookup;
+  final Tracer _tracer;
+  final RuntimeTypesEncoder _rtiEncoder;
 
   /// A stack of [InterfaceType]s that have been seen during inlining of
   /// factory constructors.  These types are preserved in [HInvokeStatic]s and
@@ -100,29 +126,19 @@
   /// for these nodes.
   // TODO(karlklose): consider removing this and keeping the (substituted) types
   // of the type variables in an environment (like the [LocalsHandler]).
-  final List<InterfaceType> currentImplicitInstantiations = <InterfaceType>[];
+  final List<InterfaceType> _currentImplicitInstantiations = <InterfaceType>[];
 
   /// Used to report information about inlining (which occurs while building the
   /// SSA graph), when dump-info is enabled.
   final InfoReporter _infoReporter;
 
-  HInstruction rethrowableException;
-
-  @override
-  final Compiler compiler;
-
-  @override
-  JavaScriptBackend get backend => compiler.backend;
+  HInstruction _rethrowableException;
 
   final SourceInformationStrategy _sourceInformationStrategy;
   final JsToElementMap _elementMap;
-  @override
   final GlobalTypeInferenceResults globalInferenceResults;
-  LoopHandler loopHandler;
-  @override
-  TypeBuilder typeBuilder;
-
-  final NativeEmitter nativeEmitter;
+  LoopHandler _loopHandler;
+  TypeBuilder _typeBuilder;
 
   /// True if we are visiting the expression of a throw statement; we assume
   /// this is a slow path.
@@ -135,40 +151,47 @@
 
   StackFrame _currentFrame;
 
-  final FunctionInlineCache inlineCache;
+  final FunctionInlineCache _inlineCache;
+  final InlineDataCache _inlineDataCache;
 
   KernelSsaGraphBuilder(
-      this.initialTargetElement,
+      this.options,
+      this.reporter,
+      this._initialTargetElement,
       InterfaceType instanceType,
-      this.compiler,
+      this._infoReporter,
       this._elementMap,
       this.globalInferenceResults,
       this.closedWorld,
-      this._worldBuilder,
       this.registry,
-      this.nativeEmitter,
+      this._namer,
+      this._emitter,
+      this._tracer,
+      this._rtiEncoder,
       this._sourceInformationStrategy,
-      this.inlineCache)
-      : this.targetElement = _effectiveTargetElementFor(initialTargetElement),
-        _infoReporter = compiler.dumpInfoTask,
-        this.closureDataLookup = closedWorld.closureDataLookup {
+      this._inlineCache,
+      this._inlineDataCache)
+      : this.targetElement = _effectiveTargetElementFor(_initialTargetElement),
+        this._closureDataLookup = closedWorld.closureDataLookup {
     _enterFrame(targetElement, null);
-    this.loopHandler = new KernelLoopHandler(this);
-    typeBuilder = new KernelTypeBuilder(this, _elementMap);
+    this._loopHandler = new KernelLoopHandler(this);
+    _typeBuilder = new KernelTypeBuilder(this, _elementMap);
     graph.element = targetElement;
     graph.sourceInformation =
         _sourceInformationBuilder.buildVariableDeclaration();
     this.localsHandler = new LocalsHandler(this, targetElement, targetElement,
-        instanceType, nativeData, interceptorData);
+        instanceType, _nativeData, _interceptorData);
   }
 
-  KernelToLocalsMap get localsMap => _currentFrame.localsMap;
+  KernelToLocalsMap get _localsMap => _currentFrame.localsMap;
 
-  Map<ir.VariableDeclaration, HInstruction> get letBindings =>
+  Map<ir.VariableDeclaration, HInstruction> get _letBindings =>
       _currentFrame.letBindings;
 
   JCommonElements get _commonElements => _elementMap.commonElements;
 
+  JElementEnvironment get _elementEnvironment => _elementMap.elementEnvironment;
+
   JFieldAnalysis get _fieldAnalysis => closedWorld.fieldAnalysis;
 
   KernelToTypeInferenceMap get _typeInferenceMap =>
@@ -177,11 +200,205 @@
   SourceInformationBuilder get _sourceInformationBuilder =>
       _currentFrame.sourceInformationBuilder;
 
-  DartType _getStaticType(ir.Expression node) {
+  AbstractValueDomain get _abstractValueDomain =>
+      closedWorld.abstractValueDomain;
+
+  NativeData get _nativeData => closedWorld.nativeData;
+
+  InterceptorData get _interceptorData => closedWorld.interceptorData;
+
+  RuntimeTypesNeed get _rtiNeed => closedWorld.rtiNeed;
+
+  InferredData get _inferredData => globalInferenceResults.inferredData;
+
+  DartTypes get types => closedWorld.dartTypes;
+
+  void push(HInstruction instruction) {
+    add(instruction);
+    stack.add(instruction);
+  }
+
+  HInstruction pop() {
+    return stack.removeLast();
+  }
+
+  /// Pushes a boolean checking [expression] against null.
+  pushCheckNull(HInstruction expression) {
+    push(new HIdentity(expression, graph.addConstantNull(closedWorld), null,
+        _abstractValueDomain.boolType));
+  }
+
+  HBasicBlock _current;
+
+  /// The current block to add instructions to. Might be null, if we are
+  /// visiting dead code, but see [_isReachable].
+  HBasicBlock get current => _current;
+
+  void set current(c) {
+    _isReachable = c != null;
+    _current = c;
+  }
+
+  /// The most recently opened block. Has the same value as [current] while
+  /// the block is open, but unlike [current], it isn't cleared when the
+  /// current block is closed.
+  HBasicBlock lastOpenedBlock;
+
+  /// Indicates whether the current block is dead (because it has a throw or a
+  /// return further up). If this is false, then [current] may be null. If the
+  /// block is dead then it may also be aborted, but for simplicity we only
+  /// abort on statement boundaries, not in the middle of expressions. See
+  /// [isAborted].
+  bool _isReachable = true;
+
+  HLocalValue lastAddedParameter;
+
+  Map<Local, HInstruction> parameters = <Local, HInstruction>{};
+  Set<Local> elidedParameters;
+
+  HBasicBlock addNewBlock() {
+    HBasicBlock block = graph.addNewBlock();
+    // If adding a new block during building of an expression, it is due to
+    // conditional expressions or short-circuit logical operators.
+    return block;
+  }
+
+  void open(HBasicBlock block) {
+    block.open();
+    current = block;
+    lastOpenedBlock = block;
+  }
+
+  HBasicBlock close(HControlFlow end) {
+    HBasicBlock result = current;
+    current.close(end);
+    current = null;
+    return result;
+  }
+
+  HBasicBlock _closeAndGotoExit(HControlFlow end) {
+    HBasicBlock result = current;
+    current.close(end);
+    current = null;
+    result.addSuccessor(graph.exit);
+    return result;
+  }
+
+  void goto(HBasicBlock from, HBasicBlock to) {
+    from.close(new HGoto(_abstractValueDomain));
+    from.addSuccessor(to);
+  }
+
+  bool isAborted() {
+    return current == null;
+  }
+
+  /// Creates a new block, transitions to it from any current block, and
+  /// opens the new block.
+  HBasicBlock openNewBlock() {
+    HBasicBlock newBlock = addNewBlock();
+    if (!isAborted()) goto(current, newBlock);
+    open(newBlock);
+    return newBlock;
+  }
+
+  void add(HInstruction instruction) {
+    current.add(instruction);
+  }
+
+  HLocalValue addParameter(Entity parameter, AbstractValue type,
+      {bool isElided: false}) {
+    HLocalValue result = isElided
+        ? new HLocalValue(parameter, type)
+        : new HParameterValue(parameter, type);
+    if (lastAddedParameter == null) {
+      graph.entry.addBefore(graph.entry.first, result);
+    } else {
+      graph.entry.addAfter(lastAddedParameter, result);
+    }
+    lastAddedParameter = result;
+    return result;
+  }
+
+  HSubGraphBlockInformation wrapStatementGraph(SubGraph statements) {
+    if (statements == null) return null;
+    return new HSubGraphBlockInformation(statements);
+  }
+
+  HSubExpressionBlockInformation wrapExpressionGraph(SubExpression expression) {
+    if (expression == null) return null;
+    return new HSubExpressionBlockInformation(expression);
+  }
+
+  HLiteralList _buildLiteralList(List<HInstruction> inputs) {
+    return new HLiteralList(inputs, _abstractValueDomain.growableListType);
+  }
+
+  HInstruction _callSetRuntimeTypeInfoWithTypeArguments(
+      InterfaceType type,
+      List<HInstruction> rtiInputs,
+      HInstruction newObject,
+      SourceInformation sourceInformation) {
+    if (!_rtiNeed.classNeedsTypeArguments(type.element)) {
+      return newObject;
+    }
+
+    HInstruction typeInfo = new HTypeInfoExpression(
+        TypeInfoExpressionKind.INSTANCE,
+        closedWorld.elementEnvironment.getThisType(type.element),
+        rtiInputs,
+        _abstractValueDomain.dynamicType);
+    add(typeInfo);
+    return _callSetRuntimeTypeInfo(typeInfo, newObject, sourceInformation);
+  }
+
+  /// Called when control flow is about to change, in which case we need to
+  /// specify special successors if we are already in a try/catch/finally block.
+  void _handleInTryStatement() {
+    if (!_inTryStatement) return;
+    HBasicBlock block = close(new HExitTry(_abstractValueDomain));
+    HBasicBlock newBlock = graph.addNewBlock();
+    block.addSuccessor(newBlock);
+    open(newBlock);
+  }
+
+  /// Helper to implement JS_GET_FLAG.
+  ///
+  /// The concrete SSA graph builder will extract a flag parameter from the
+  /// JS_GET_FLAG call and then push a boolean result onto the stack. This
+  /// function provides the boolean value corresponding to the given [flagName].
+  /// If [flagName] is not recognized, this function returns `null` and the
+  /// concrete SSA builder reports an error.
+  bool _getFlagValue(String flagName) {
+    switch (flagName) {
+      case 'MINIFIED':
+        return options.enableMinification;
+      case 'MUST_RETAIN_METADATA':
+        return false;
+      case 'USE_CONTENT_SECURITY_POLICY':
+        return options.useContentSecurityPolicy;
+      case 'USE_NEW_RTI':
+        return options.experimentNewRti;
+      default:
+        return null;
+    }
+  }
+
+  StaticType _getStaticType(ir.Expression node) {
     // TODO(johnniwinther): Substitute the type by the this type and type
     // arguments of the current frame.
-    return _elementMap
-        .getDartType(_currentFrame.staticTypeProvider.getStaticType(node));
+    ir.DartType type = _currentFrame.staticTypeProvider.getStaticType(node);
+    return new StaticType(
+        _elementMap.getDartType(type), computeClassRelationFromType(type));
+  }
+
+  StaticType _getStaticForInIteratorType(ir.ForInStatement node) {
+    // TODO(johnniwinther): Substitute the type by the this type and type
+    // arguments of the current frame.
+    ir.DartType type =
+        _currentFrame.staticTypeProvider.getForInIteratorType(node);
+    return new StaticType(
+        _elementMap.getDartType(type), computeClassRelationFromType(type));
   }
 
   static MemberEntity _effectiveTargetElementFor(MemberEntity member) {
@@ -215,11 +432,11 @@
   }
 
   HGraph build() {
-    return reporter.withCurrentElement(localsMap.currentMember, () {
+    return reporter.withCurrentElement(_localsMap.currentMember, () {
       // TODO(het): no reason to do this here...
       HInstruction.idCounter = 0;
       MemberDefinition definition =
-          _elementMap.getMemberDefinition(initialTargetElement);
+          _elementMap.getMemberDefinition(_initialTargetElement);
 
       switch (definition.kind) {
         case MemberKind.regular:
@@ -227,39 +444,44 @@
           ir.Node target = definition.node;
           if (target is ir.Procedure) {
             if (target.isExternal) {
-              buildExternalFunctionNode(
+              _buildExternalFunctionNode(
                   targetElement, _ensureDefaultArgumentValues(target.function));
             } else {
-              buildFunctionNode(
+              _buildFunctionNode(
                   targetElement, _ensureDefaultArgumentValues(target.function));
             }
           } else if (target is ir.Field) {
-            if (handleConstantField(targetElement, registry, closedWorld)) {
-              // No code is generated for `targetElement`: All references inline
-              // the constant value.
-              return null;
-            } else if (targetElement.isStatic || targetElement.isTopLevel) {
-              if (_fieldAnalysis.getFieldData(targetElement).isLazy) {
-                // TODO(johnniwinther): Lazy fields should be collected like
-                // eager and non-final fields.
-                backend.constants.registerLazyStatic(targetElement);
+            FieldAnalysisData fieldData =
+                closedWorld.fieldAnalysis.getFieldData(targetElement);
+
+            if (fieldData.initialValue != null) {
+              registry.registerConstantUse(
+                  new ConstantUse.init(fieldData.initialValue));
+              if (targetElement.isStatic || targetElement.isTopLevel) {
+                /// No code is created for this field: All references inline the
+                /// constant value.
+                return null;
               }
-            } else {
-              assert(targetElement.isInstanceMember);
-              if (_fieldAnalysis
-                      .getFieldData(targetElement)
-                      .isEffectivelyFinal ||
+            } else if (fieldData.isLazy) {
+              // The generated initializer needs be wrapped in the cyclic-error
+              // helper.
+              registry.registerStaticUse(new StaticUse.staticInvoke(
+                  closedWorld.commonElements.cyclicThrowHelper,
+                  CallStructure.ONE_ARG));
+            }
+            if (targetElement.isInstanceMember) {
+              if (fieldData.isEffectivelyFinal ||
                   !options.parameterCheckPolicy.isEmitted) {
                 // No need for a checked setter.
                 return null;
               }
             }
-            buildField(target);
+            _buildField(target);
           } else if (target is ir.FunctionExpression) {
-            buildFunctionNode(
+            _buildFunctionNode(
                 targetElement, _ensureDefaultArgumentValues(target.function));
           } else if (target is ir.FunctionDeclaration) {
-            buildFunctionNode(
+            _buildFunctionNode(
                 targetElement, _ensureDefaultArgumentValues(target.function));
           } else {
             throw 'No case implemented to handle target: '
@@ -269,12 +491,12 @@
         case MemberKind.constructor:
           ir.Constructor constructor = definition.node;
           _ensureDefaultArgumentValues(constructor.function);
-          buildConstructor(targetElement, constructor);
+          _buildConstructor(targetElement, constructor);
           break;
         case MemberKind.constructorBody:
           ir.Constructor constructor = definition.node;
           _ensureDefaultArgumentValues(constructor.function);
-          buildConstructorBody(constructor);
+          _buildConstructorBody(constructor);
           break;
         case MemberKind.closureField:
           // Closure fields have no setter and therefore never require any code.
@@ -294,17 +516,17 @@
                 "Unexpected function signature: "
                 "$targetElement inside a non-closure: $target");
           }
-          buildMethodSignature(originalClosureNode);
+          _buildMethodSignature(originalClosureNode);
           break;
         case MemberKind.generatorBody:
-          buildGeneratorBody(
-              initialTargetElement, _functionNodeOf(definition.node));
+          _buildGeneratorBody(
+              _initialTargetElement, _functionNodeOf(definition.node));
           break;
       }
-      assert(graph.isValid(), "Invalid graph for $initialTargetElement.");
+      assert(graph.isValid(), "Invalid graph for $_initialTargetElement.");
 
-      if (backend.tracer.isEnabled) {
-        MemberEntity member = initialTargetElement;
+      if (_tracer.isEnabled) {
+        MemberEntity member = _initialTargetElement;
         String name = member.name;
         if (member.isInstanceMember ||
             member.isConstructor ||
@@ -314,8 +536,8 @@
             name += " (body)";
           }
         }
-        backend.tracer.traceCompilation(name);
-        backend.tracer.traceGraph('builder', graph);
+        _tracer.traceCompilation(name);
+        _tracer.traceGraph('builder', graph);
       }
 
       return graph;
@@ -343,7 +565,7 @@
     // were generated by the codegen enqueuer. In practice even in huge programs
     // there are only very small number of constants created here that are not
     // actually used.
-    void registerDefaultValue(ir.VariableDeclaration node) {
+    void _registerDefaultValue(ir.VariableDeclaration node) {
       ConstantValue constantValue =
           _elementMap.getConstantValue(node.initializer, implicitNull: true);
       assert(
@@ -355,47 +577,47 @@
 
     function.positionalParameters
         .skip(function.requiredParameterCount)
-        .forEach(registerDefaultValue);
-    function.namedParameters.forEach(registerDefaultValue);
+        .forEach(_registerDefaultValue);
+    function.namedParameters.forEach(_registerDefaultValue);
     return function;
   }
 
-  void buildField(ir.Field node) {
+  void _buildField(ir.Field node) {
     _inLazyInitializerExpression = node.isStatic;
     FieldEntity field = _elementMap.getMember(node);
-    openFunction(field, checks: TargetChecks.none);
+    _openFunction(field, checks: TargetChecks.none);
     if (node.isInstanceMember && options.parameterCheckPolicy.isEmitted) {
       HInstruction thisInstruction = localsHandler.readThis(
           sourceInformation: _sourceInformationBuilder.buildGet(node));
       // Use dynamic type because the type computed by the inferrer is
       // narrowed to the type annotation.
       HInstruction parameter =
-          new HParameterValue(field, abstractValueDomain.dynamicType);
+          new HParameterValue(field, _abstractValueDomain.dynamicType);
       // Add the parameter as the last instruction of the entry block.
       // If the method is intercepted, we want the actual receiver
       // to be the first parameter.
       graph.entry.addBefore(graph.entry.last, parameter);
-      HInstruction value = typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
+      HInstruction value = _typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
           parameter, _getDartTypeIfValid(node.type));
       if (!_fieldAnalysis.getFieldData(field).isElided) {
-        add(new HFieldSet(abstractValueDomain, field, thisInstruction, value));
+        add(new HFieldSet(_abstractValueDomain, field, thisInstruction, value));
       }
     } else {
       if (node.initializer != null) {
         node.initializer.accept(this);
         HInstruction fieldValue = pop();
         HInstruction checkInstruction =
-            typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
+            _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
                 fieldValue, _getDartTypeIfValid(node.type));
         stack.add(checkInstruction);
       } else {
         stack.add(graph.addConstantNull(closedWorld));
       }
       HInstruction value = pop();
-      closeAndGotoExit(new HReturn(abstractValueDomain, value,
+      _closeAndGotoExit(new HReturn(_abstractValueDomain, value,
           _sourceInformationBuilder.buildReturn(node)));
     }
-    closeFunction();
+    _closeFunction();
   }
 
   DartType _getDartTypeIfValid(ir.DartType type) {
@@ -403,18 +625,11 @@
     return _elementMap.getDartType(type);
   }
 
-  /// Pops the most recent instruction from the stack and 'boolifies' it.
-  ///
-  /// Boolification is checking if the value is '=== true'.
-  @override
+  /// Pops the most recent instruction from the stack and ensures that it is a
+  /// non-null bool.
   HInstruction popBoolified() {
     HInstruction value = pop();
-    if (typeBuilder.checkOrTrustTypes) {
-      return typeBuilder.potentiallyCheckOrTrustTypeOfCondition(value);
-    }
-    HInstruction result = new HBoolify(value, abstractValueDomain.boolType);
-    add(result);
-    return result;
+    return _typeBuilder.potentiallyCheckOrTrustTypeOfCondition(value);
   }
 
   /// Extend current method parameters with parameters for the class type
@@ -426,17 +641,17 @@
       return;
     }
     ClassEntity cls = member.enclosingClass;
-    InterfaceType thisType = _elementMap.elementEnvironment.getThisType(cls);
+    InterfaceType thisType = _elementEnvironment.getThisType(cls);
     if (thisType.typeArguments.isEmpty) {
       return;
     }
-    bool needsTypeArguments = rtiNeed.classNeedsTypeArguments(cls);
+    bool needsTypeArguments = _rtiNeed.classNeedsTypeArguments(cls);
     thisType.typeArguments.forEach((DartType _typeVariable) {
       TypeVariableType typeVariableType = _typeVariable;
       HInstruction param;
       if (needsTypeArguments) {
         param = addParameter(
-            typeVariableType.element, abstractValueDomain.nonNullType);
+            typeVariableType.element, _abstractValueDomain.nonNullType);
       } else {
         // Unused, so bind to `dynamic`.
         param = graph.addConstantNull(closedWorld);
@@ -457,32 +672,32 @@
 
     FunctionEntity function = member;
     List<TypeVariableType> typeVariables =
-        _elementMap.elementEnvironment.getFunctionTypeVariables(function);
+        _elementEnvironment.getFunctionTypeVariables(function);
     if (typeVariables.isEmpty) {
       return;
     }
-    bool needsTypeArguments = rtiNeed.methodNeedsTypeArguments(function);
+    bool needsTypeArguments = _rtiNeed.methodNeedsTypeArguments(function);
     bool elideTypeParameters = function.parameterStructure.typeParameters == 0;
     for (TypeVariableType typeVariable
-        in _elementMap.elementEnvironment.getFunctionTypeVariables(function)) {
+        in _elementEnvironment.getFunctionTypeVariables(function)) {
       HInstruction param;
       if (elideTypeParameters) {
         // Add elided type parameters.
         param = _computeTypeArgumentDefaultValue(function, typeVariable);
       } else if (needsTypeArguments) {
-        param =
-            addParameter(typeVariable.element, abstractValueDomain.nonNullType);
+        param = addParameter(
+            typeVariable.element, _abstractValueDomain.nonNullType);
       } else {
         // Unused, so bind to `dynamic`.
         param = graph.addConstantNull(closedWorld);
       }
       Local local = localsHandler.getTypeVariableAsLocal(typeVariable);
       localsHandler.directLocals[local] = param;
-      functionTypeParameterLocals.add(local);
+      _functionTypeParameterLocals.add(local);
     }
   }
 
-  List<Local> functionTypeParameterLocals = <Local>[];
+  List<Local> _functionTypeParameterLocals = <Local>[];
 
   /// Builds a generative constructor.
   ///
@@ -511,13 +726,13 @@
   /// implication is that a class cannot be extended or mixed-in twice. If we in
   /// future support repeated uses of a mixin class, we should do so by cloning
   /// the mixin class in the Kernel input.
-  void buildConstructor(ConstructorEntity constructor, ir.Constructor node) {
+  void _buildConstructor(ConstructorEntity constructor, ir.Constructor node) {
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildCreate(node);
     ClassEntity cls = constructor.enclosingClass;
 
     if (_inliningStack.isEmpty) {
-      openFunction(constructor,
+      _openFunction(constructor,
           functionNode: node.function,
           parameterStructure: constructor.parameterStructure,
           checks: TargetChecks.none);
@@ -531,33 +746,34 @@
     List<HInstruction> constructorArguments = <HInstruction>[];
     // Doing this instead of fieldValues.forEach because we haven't defined the
     // order of the arguments here. We can define that with JElements.
-    bool isCustomElement = nativeData.isNativeOrExtendsNative(cls) &&
-        !nativeData.isJsInteropClass(cls);
-    InterfaceType thisType = _elementMap.elementEnvironment.getThisType(cls);
+    bool isCustomElement = _nativeData.isNativeOrExtendsNative(cls) &&
+        !_nativeData.isJsInteropClass(cls);
+    InterfaceType thisType = _elementEnvironment.getThisType(cls);
     List<FieldEntity> fields = <FieldEntity>[];
-    _worldBuilder.forEachInstanceField(cls,
-        (ClassEntity enclosingClass, FieldEntity member, {bool isElided}) {
+    _elementEnvironment.forEachInstanceField(cls,
+        (ClassEntity enclosingClass, FieldEntity member) {
       HInstruction value = constructorData.fieldValues[member];
+      FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(member);
       if (value == null) {
         assert(
-            _fieldAnalysis.getFieldData(member).isInitializedInAllocator ||
+            fieldData.isInitializedInAllocator ||
                 isCustomElement ||
                 reporter.hasReportedError,
             'No initializer value for field ${member}');
       } else {
-        if (!isElided) {
+        if (!fieldData.isElided) {
           fields.add(member);
-          DartType type = _elementMap.elementEnvironment.getFieldType(member);
+          DartType type = _elementEnvironment.getFieldType(member);
           type = localsHandler.substInContext(type);
-          constructorArguments.add(
-              typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(value, type));
+          constructorArguments.add(_typeBuilder
+              .potentiallyCheckOrTrustTypeOfAssignment(value, type));
         }
       }
     });
 
-    addImplicitInstantiation(thisType);
+    _addImplicitInstantiation(thisType);
     List<DartType> instantiatedTypes =
-        new List<InterfaceType>.from(currentImplicitInstantiations);
+        new List<InterfaceType>.from(_currentImplicitInstantiations);
 
     HInstruction newObject;
     if (isCustomElement) {
@@ -567,10 +783,10 @@
       // 'new' of the constructor instead of via an upgrade. It is optimized out
       // if there are field initializers.
       add(new HFieldGet(
-          null, newObject, abstractValueDomain.dynamicType, sourceInformation,
+          null, newObject, _abstractValueDomain.dynamicType, sourceInformation,
           isAssignable: false));
       for (int i = 0; i < fields.length; i++) {
-        add(new HFieldSet(abstractValueDomain, fields[i], newObject,
+        add(new HFieldSet(_abstractValueDomain, fields[i], newObject,
             constructorArguments[i]));
       }
     } else {
@@ -581,8 +797,7 @@
         // Read the values of the type arguments and create a
         // HTypeInfoExpression to set on the newly created object.
         List<HInstruction> typeArguments = <HInstruction>[];
-        InterfaceType thisType =
-            _elementMap.elementEnvironment.getThisType(cls);
+        InterfaceType thisType = _elementEnvironment.getThisType(cls);
         for (DartType typeVariable in thisType.typeArguments) {
           HInstruction argument = localsHandler
               .readLocal(localsHandler.getTypeVariableAsLocal(typeVariable));
@@ -593,19 +808,19 @@
             TypeInfoExpressionKind.INSTANCE,
             thisType,
             typeArguments,
-            abstractValueDomain.dynamicType);
+            _abstractValueDomain.dynamicType);
         add(typeInfo);
         constructorArguments.add(typeInfo);
       }
 
       newObject = new HCreate(cls, constructorArguments,
-          abstractValueDomain.createNonNullExact(cls), sourceInformation,
+          _abstractValueDomain.createNonNullExact(cls), sourceInformation,
           instantiatedTypes: instantiatedTypes,
           hasRtiInput: needsTypeArguments);
 
       add(newObject);
     }
-    removeImplicitInstantiation(thisType);
+    _removeImplicitInstantiation(thisType);
 
     HInstruction interceptor;
     // Generate calls to the constructor bodies.
@@ -627,7 +842,7 @@
 
       ConstructorEntity inlinedConstructor = _elementMap.getConstructor(body);
 
-      inlinedFrom(
+      _inlinedFrom(
           inlinedConstructor, _sourceInformationBuilder.buildCall(body, body),
           () {
         ConstructorBodyEntity constructorBody =
@@ -636,7 +851,7 @@
         void handleParameter(ir.VariableDeclaration node, {bool isElided}) {
           if (isElided) return;
 
-          Local parameter = localsMap.getLocalVariable(node);
+          Local parameter = _localsMap.getLocalVariable(node);
           // If [parameter] is boxed, it will be a field in the box passed as
           // the last parameter. So no need to directly pass it.
           if (!localsHandler.isBoxed(parameter)) {
@@ -650,7 +865,7 @@
         // If there are locals that escape (i.e. mutated in closures), we pass the
         // box to the constructor.
         CapturedScope scopeData =
-            closureDataLookup.getCapturedScope(constructorBody);
+            _closureDataLookup.getCapturedScope(constructorBody);
         if (scopeData.requiresContextBox) {
           bodyCallInputs.add(localsHandler.readLocal(scopeData.context));
         }
@@ -659,12 +874,12 @@
         ClassEntity inlinedConstructorClass = constructorBody.enclosingClass;
         if (closedWorld.rtiNeed
             .classNeedsTypeArguments(inlinedConstructorClass)) {
-          InterfaceType thisType = _elementMap.elementEnvironment
-              .getThisType(inlinedConstructorClass);
+          InterfaceType thisType =
+              _elementEnvironment.getThisType(inlinedConstructorClass);
           for (DartType typeVariable in thisType.typeArguments) {
             DartType result = localsHandler.substInContext(typeVariable);
             HInstruction argument =
-                typeBuilder.analyzeTypeArgument(result, sourceElement);
+                _typeBuilder.analyzeTypeArgument(result, sourceElement);
             bodyCallInputs.add(argument);
           }
         }
@@ -681,9 +896,9 @@
     }
 
     if (_inliningStack.isEmpty) {
-      closeAndGotoExit(
-          new HReturn(abstractValueDomain, newObject, sourceInformation));
-      closeFunction();
+      _closeAndGotoExit(
+          new HReturn(_abstractValueDomain, newObject, sourceInformation));
+      _closeFunction();
     } else {
       localsHandler.updateLocal(_returnLocal, newObject,
           sourceInformation: sourceInformation);
@@ -700,13 +915,13 @@
       List<HInstruction> inputs, SourceInformation sourceInformation) {
     MemberEntity constructorBody = _elementMap.getConstructorBody(constructor);
     HInvokeConstructorBody invoke = new HInvokeConstructorBody(constructorBody,
-        inputs, abstractValueDomain.nonNullType, sourceInformation);
+        inputs, _abstractValueDomain.nonNullType, sourceInformation);
     add(invoke);
   }
 
   /// Sets context for generating code that is the result of inlining
   /// [inlinedTarget].
-  inlinedFrom(MemberEntity inlinedTarget,
+  void _inlinedFrom(MemberEntity inlinedTarget,
       SourceInformation callSourceInformation, f()) {
     reporter.withCurrentElement(inlinedTarget, () {
       _enterFrame(inlinedTarget, callSourceInformation);
@@ -719,13 +934,12 @@
   void _ensureTypeVariablesForInitializers(
       ConstructorData constructorData, ClassEntity enclosingClass) {
     if (!constructorData.includedClasses.add(enclosingClass)) return;
-    if (rtiNeed.classNeedsTypeArguments(enclosingClass)) {
+    if (_rtiNeed.classNeedsTypeArguments(enclosingClass)) {
       // If [enclosingClass] needs RTI, we have to give a value to its type
       // parameters. For a super constructor call, the type is the supertype
       // of current class. For a redirecting constructor, the type is the
       // current type. [LocalsHandler.substInContext] takes care of both.
-      InterfaceType thisType =
-          _elementMap.elementEnvironment.getThisType(enclosingClass);
+      InterfaceType thisType = _elementEnvironment.getThisType(enclosingClass);
       InterfaceType type = localsHandler.substInContext(thisType);
       List<DartType> arguments = type.typeArguments;
       List<DartType> typeVariables = thisType.typeArguments;
@@ -736,7 +950,7 @@
         TypeVariableType typeVariable = variables.current;
         localsHandler.updateLocal(
             localsHandler.getTypeVariableAsLocal(typeVariable),
-            typeBuilder.analyzeTypeArgument(argument, sourceElement));
+            _typeBuilder.analyzeTypeArgument(argument, sourceElement));
       });
     }
   }
@@ -745,8 +959,7 @@
   /// [clazz].
   void _collectFieldValues(ir.Class clazz, ConstructorData constructorData) {
     ClassEntity cls = _elementMap.getClass(clazz);
-    _worldBuilder.forEachDirectInstanceField(cls, (FieldEntity field,
-        {bool isElided}) {
+    _elementEnvironment.forEachDirectInstanceField(cls, (FieldEntity field) {
       _ensureTypeVariablesForInitializers(
           constructorData, field.enclosingClass);
 
@@ -761,10 +974,10 @@
       }
 
       bool ignoreAllocatorAnalysis = false;
-      if (nativeData.isNativeOrExtendsNative(cls)) {
+      if (_nativeData.isNativeOrExtendsNative(cls)) {
         // @Native classes have 'fields' which are really getters/setter.  Do
         // not try to initialize e.g. 'tagName'.
-        if (nativeData.isNativeClass(cls)) return;
+        if (_nativeData.isNativeClass(cls)) return;
         // Fields that survive this test are fields of custom elements.
         ignoreAllocatorAnalysis = true;
       }
@@ -779,7 +992,7 @@
           // class type parameters are accessed as values.
           // TODO(sra): It would be sufficient to know the context was a field
           // initializer.
-          inlinedFrom(field,
+          _inlinedFrom(field,
               _sourceInformationBuilder.buildAssignment(node.initializer), () {
             node.initializer.accept(this);
             constructorData.fieldValues[field] = pop();
@@ -789,7 +1002,7 @@
     });
   }
 
-  static bool isRedirectingConstructor(ir.Constructor constructor) =>
+  static bool _isRedirectingConstructor(ir.Constructor constructor) =>
       constructor.initializers
           .any((initializer) => initializer is ir.RedirectingInitializer);
 
@@ -797,14 +1010,14 @@
   void _buildInitializers(
       ir.Constructor constructor, ConstructorData constructorData) {
     assert(
-        _elementMap.getConstructor(constructor) == localsMap.currentMember,
+        _elementMap.getConstructor(constructor) == _localsMap.currentMember,
         failedAt(
-            localsMap.currentMember,
-            'Expected ${localsMap.currentMember} '
+            _localsMap.currentMember,
+            'Expected ${_localsMap.currentMember} '
             'but found ${_elementMap.getConstructor(constructor)}.'));
     constructorData.constructorChain.add(constructor);
 
-    if (!isRedirectingConstructor(constructor)) {
+    if (!_isRedirectingConstructor(constructor)) {
       // Compute values for field initializers, but only if this is not a
       // redirecting constructor, since the target will compute the fields.
       _collectFieldValues(constructor.enclosingClass, constructorData);
@@ -834,7 +1047,7 @@
         variable.initializer.accept(this);
         HInstruction value = pop();
         // TODO(sra): Apply inferred type information.
-        letBindings[variable] = value;
+        _letBindings[variable] = value;
       } else if (initializer is ir.AssertInitializer) {
         // Assert in initializer is currently not supported in dart2js.
         // TODO(johnniwinther): Support assert in initializer.
@@ -955,11 +1168,11 @@
     ConstructorEntity element = _elementMap.getConstructor(constructor);
     ScopeInfo oldScopeInfo = localsHandler.scopeInfo;
 
-    inlinedFrom(
+    _inlinedFrom(
         element, _sourceInformationBuilder.buildCall(initializer, initializer),
         () {
       void handleParameter(ir.VariableDeclaration node) {
-        Local parameter = localsMap.getLocalVariable(node);
+        Local parameter = _localsMap.getLocalVariable(node);
         HInstruction argument = arguments[index++];
         // Because we are inlining the initializer, we must update
         // what was given as parameter. This will be used in case
@@ -977,9 +1190,9 @@
           constructorData, element.enclosingClass);
 
       // Set the locals handler state as if we were inlining the constructor.
-      ScopeInfo newScopeInfo = closureDataLookup.getScopeInfo(element);
+      ScopeInfo newScopeInfo = _closureDataLookup.getScopeInfo(element);
       localsHandler.scopeInfo = newScopeInfo;
-      localsHandler.enterScope(closureDataLookup.getCapturedScope(element),
+      localsHandler.enterScope(_closureDataLookup.getCapturedScope(element),
           _sourceInformationBuilder.buildDeclaration(element));
       _buildInitializers(constructor, constructorData);
     });
@@ -989,8 +1202,8 @@
   /// Constructs a special signature function for a closure. It is unique in
   /// that no corresponding ir.Node actually exists for it. We just use the
   /// targetElement.
-  void buildMethodSignature(ir.FunctionNode originalClosureNode) {
-    openFunction(targetElement);
+  void _buildMethodSignature(ir.FunctionNode originalClosureNode) {
+    _openFunction(targetElement);
     List<HInstruction> typeArguments = <HInstruction>[];
 
     // Add function type variables.
@@ -999,40 +1212,40 @@
     functionType.forEachTypeVariable((TypeVariableType typeVariableType) {
       DartType result = localsHandler.substInContext(typeVariableType);
       HInstruction argument =
-          typeBuilder.analyzeTypeArgument(result, sourceElement);
+          _typeBuilder.analyzeTypeArgument(result, sourceElement);
       typeArguments.add(argument);
     });
     push(new HTypeInfoExpression(
         TypeInfoExpressionKind.COMPLETE,
         _elementMap.getFunctionType(originalClosureNode),
         typeArguments,
-        abstractValueDomain.functionType));
+        _abstractValueDomain.functionType));
     HInstruction value = pop();
-    close(new HReturn(abstractValueDomain, value,
+    close(new HReturn(_abstractValueDomain, value,
             _sourceInformationBuilder.buildReturn(originalClosureNode)))
         .addSuccessor(graph.exit);
 
-    closeFunction();
+    _closeFunction();
   }
 
   /// Builds generative constructor body.
-  void buildConstructorBody(ir.Constructor constructor) {
+  void _buildConstructorBody(ir.Constructor constructor) {
     FunctionEntity constructorBody =
         _elementMap.getConstructorBody(constructor);
-    openFunction(constructorBody,
+    _openFunction(constructorBody,
         functionNode: constructor.function,
         parameterStructure: constructorBody.parameterStructure,
         checks: TargetChecks.none);
     constructor.function.body.accept(this);
-    closeFunction();
+    _closeFunction();
   }
 
   /// Builds a SSA graph for FunctionNodes, found in FunctionExpressions and
   /// Procedures.
-  void buildFunctionNode(
+  void _buildFunctionNode(
       FunctionEntity function, ir.FunctionNode functionNode) {
     if (functionNode.asyncMarker != ir.AsyncMarker.Sync) {
-      buildGenerator(function, functionNode);
+      _buildGenerator(function, functionNode);
       return;
     }
 
@@ -1040,7 +1253,7 @@
     // checks.
     // TODO(sra): Instance methods can be generated with reduced checks if
     // called only from non-dynamic call-sites.
-    openFunction(function,
+    _openFunction(function,
         functionNode: functionNode,
         parameterStructure: function.parameterStructure);
 
@@ -1049,15 +1262,15 @@
     // check.
     if (function.name == '==') {
       if (!_commonElements.operatorEqHandlesNullArgument(function)) {
-        handleIf(
+        _handleIf(
             visitCondition: () {
               HParameterValue parameter = parameters.values.first;
               push(new HIdentity(parameter, graph.addConstantNull(closedWorld),
-                  null, abstractValueDomain.boolType));
+                  null, _abstractValueDomain.boolType));
             },
             visitThen: () {
-              closeAndGotoExit(new HReturn(
-                  abstractValueDomain,
+              _closeAndGotoExit(new HReturn(
+                  _abstractValueDomain,
                   graph.addConstantBool(false, closedWorld),
                   _sourceInformationBuilder.buildReturn(functionNode)));
             },
@@ -1067,20 +1280,20 @@
     }
     if (const bool.fromEnvironment('unreachable-throw')) {
       var emptyParameters = parameters.values.where((p) =>
-          abstractValueDomain.isEmpty(p.instructionType).isDefinitelyTrue);
+          _abstractValueDomain.isEmpty(p.instructionType).isDefinitelyTrue);
       if (emptyParameters.length > 0) {
-        addComment('${emptyParameters} inferred as [empty]');
+        _addComment('${emptyParameters} inferred as [empty]');
         add(new HInvokeStatic(
-            commonElements.assertUnreachableMethod,
+            _commonElements.assertUnreachableMethod,
             <HInstruction>[],
-            abstractValueDomain.dynamicType,
+            _abstractValueDomain.dynamicType,
             const <DartType>[]));
-        closeFunction();
+        _closeFunction();
         return;
       }
     }
     functionNode.body.accept(this);
-    closeFunction();
+    _closeFunction();
   }
 
   /// Adds a JavaScript comment to the output. The comment will be omitted in
@@ -1088,9 +1301,9 @@
   /// Use sparingly. In order for the comment to be retained it is modeled as
   /// having side effects which will inhibit code motion.
   // TODO(sra): Figure out how to keep comment anchored without effects.
-  void addComment(String text) {
+  void _addComment(String text) {
     add(new HForeignCode(js.js.statementTemplateYielding(new js.Comment(text)),
-        abstractValueDomain.dynamicType, <HInstruction>[],
+        _abstractValueDomain.dynamicType, <HInstruction>[],
         isStatement: true));
   }
 
@@ -1098,8 +1311,8 @@
   /// entry function which tail-calls a body function. The entry contains
   /// per-invocation checks and the body, which is later transformed, contains
   /// the re-entrant 'state machine' code.
-  void buildGenerator(FunctionEntity function, ir.FunctionNode functionNode) {
-    openFunction(function,
+  void _buildGenerator(FunctionEntity function, ir.FunctionNode functionNode) {
+    _openFunction(function,
         functionNode: functionNode,
         parameterStructure: function.parameterStructure);
 
@@ -1121,18 +1334,18 @@
         inputs.add(localsHandler.readLocal(local));
       }
     }
-    for (Local local in functionTypeParameterLocals) {
+    for (Local local in _functionTypeParameterLocals) {
       inputs.add(localsHandler.readLocal(local));
     }
 
     // Add the type parameter for the generator's element type.
-    DartType elementType = _elementMap.elementEnvironment
-        .getAsyncOrSyncStarElementType(function.asyncMarker, _returnType);
+    DartType elementType = _elementEnvironment.getAsyncOrSyncStarElementType(
+        function.asyncMarker, _returnType);
 
     if (elementType.containsFreeTypeVariables) {
       // Type must be computed in the entry function, where the type variables
       // are in scope, and passed to the body function.
-      inputs.add(typeBuilder.analyzeTypeArgument(elementType, function));
+      inputs.add(_typeBuilder.analyzeTypeArgument(elementType, function));
     } else {
       // Types with no type variables can be emitted as part of the generator,
       // avoiding an extra argument.
@@ -1144,30 +1357,29 @@
         graph.needsAsyncRewrite = true;
         graph.asyncElementType = elementType;
         functionNode.body.accept(this);
-        closeFunction();
+        _closeFunction();
         return;
       }
     }
 
     JGeneratorBody body = _elementMap.getGeneratorBody(function);
-    closedWorld.outputUnitData.registerColocatedMembers(function, body);
     push(new HInvokeGeneratorBody(
         body,
         inputs,
-        abstractValueDomain.dynamicType, // TODO: better type.
+        _abstractValueDomain.dynamicType, // TODO: better type.
         sourceInformation));
 
-    closeAndGotoExit(
-        new HReturn(abstractValueDomain, pop(), sourceInformation));
+    _closeAndGotoExit(
+        new HReturn(_abstractValueDomain, pop(), sourceInformation));
 
-    closeFunction();
+    _closeFunction();
   }
 
   /// Builds a SSA graph for a sync*/async/async* generator body.
-  void buildGeneratorBody(
+  void _buildGeneratorBody(
       JGeneratorBody function, ir.FunctionNode functionNode) {
     FunctionEntity entry = function.function;
-    openFunction(entry,
+    _openFunction(entry,
         functionNode: functionNode,
         parameterStructure: function.parameterStructure,
         checks: TargetChecks.none);
@@ -1177,7 +1389,7 @@
       graph.asyncElementType = function.elementType;
     }
     functionNode.body.accept(this);
-    closeFunction();
+    _closeFunction();
   }
 
   bool _generatedEntryIsEmpty() {
@@ -1199,7 +1411,7 @@
     // check.
 
     if (targetChecks.checkTypeParameters) {
-      checkTypeVariableBounds(targetElement);
+      _checkTypeVariableBounds(targetElement);
     }
 
     MemberDefinition definition =
@@ -1207,9 +1419,9 @@
     bool nodeIsConstructorBody = definition.kind == MemberKind.constructorBody;
 
     void _handleParameter(ir.VariableDeclaration variable) {
-      Local local = localsMap.getLocalVariable(variable);
+      Local local = _localsMap.getLocalVariable(variable);
       if (nodeIsConstructorBody &&
-          closureDataLookup
+          _closureDataLookup
               .getCapturedScope(targetElement)
               .isBoxedVariable(local)) {
         // If local is boxed, then `variable` will be a field inside the box
@@ -1224,10 +1436,10 @@
       if (targetChecks.checkAllParameters ||
           (targetChecks.checkCovariantParameters &&
               (variable.isGenericCovariantImpl || variable.isCovariant))) {
-        newParameter = typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
+        newParameter = _typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
             newParameter, type);
       } else {
-        newParameter = typeBuilder.trustTypeOfParameter(newParameter, type);
+        newParameter = _typeBuilder.trustTypeOfParameter(newParameter, type);
       }
 
       localsHandler.directLocals[local] = newParameter;
@@ -1237,12 +1449,12 @@
     function.namedParameters.toList()..forEach(_handleParameter);
   }
 
-  void checkTypeVariableBounds(FunctionEntity method) {
-    if (rtiNeed.methodNeedsTypeArguments(method) &&
+  void _checkTypeVariableBounds(FunctionEntity method) {
+    if (_rtiNeed.methodNeedsTypeArguments(method) &&
         options.parameterCheckPolicy.isEmitted) {
       ir.FunctionNode function = getFunctionNode(_elementMap, method);
       for (ir.TypeParameter typeParameter in function.typeParameters) {
-        Local local = localsMap.getLocalTypeVariable(
+        Local local = _localsMap.getLocalTypeVariable(
             new ir.TypeParameterType(typeParameter), _elementMap);
         HInstruction newParameter = localsHandler.directLocals[local];
         DartType bound = _getDartTypeIfValid(typeParameter.bound);
@@ -1261,17 +1473,17 @@
   }
 
   /// Builds a SSA graph for FunctionNodes of external methods.
-  void buildExternalFunctionNode(
+  void _buildExternalFunctionNode(
       FunctionEntity function, ir.FunctionNode functionNode) {
     // TODO(johnniwinther): Non-js-interop external functions should
     // throw a runtime error.
     assert(functionNode.body == null);
-    openFunction(function,
+    _openFunction(function,
         functionNode: functionNode,
         parameterStructure: function.parameterStructure);
 
     if (closedWorld.nativeData.isNativeMember(targetElement)) {
-      nativeEmitter.nativeMethods.add(targetElement);
+      registry.registerNativeMethod(targetElement);
       String nativeName;
       if (closedWorld.nativeData.hasFixedBackendName(targetElement)) {
         nativeName = closedWorld.nativeData.getFixedBackendName(targetElement);
@@ -1291,7 +1503,7 @@
 
       void handleParameter(ir.VariableDeclaration param) {
         templateArguments.add('#');
-        Local local = localsMap.getLocalVariable(param);
+        Local local = _localsMap.getLocalVariable(param);
         // Convert Dart function to JavaScript function.
         HInstruction argument = localsHandler.readLocal(local);
         ir.DartType type = param.type;
@@ -1300,7 +1512,7 @@
           _pushStaticInvocation(
               _commonElements.closureConverter,
               [argument, graph.addConstantInt(arity, closedWorld)],
-              abstractValueDomain.dynamicType,
+              _abstractValueDomain.dynamicType,
               const <DartType>[],
               sourceInformation: null);
           argument = pop();
@@ -1328,7 +1540,7 @@
       String arguments = templateArguments.join(',');
 
       // TODO(sra): Use declared type or NativeBehavior type.
-      AbstractValue typeMask = abstractValueDomain.dynamicType;
+      AbstractValue typeMask = _abstractValueDomain.dynamicType;
       String template;
       if (targetElement.isGetter) {
         template = '${templateReceiver}$nativeName';
@@ -1346,27 +1558,27 @@
       if (targetElement.isSetter) {
         value = graph.addConstantNull(closedWorld);
       }
-      close(new HReturn(abstractValueDomain, value,
+      close(new HReturn(_abstractValueDomain, value,
               _sourceInformationBuilder.buildReturn(functionNode)))
           .addSuccessor(graph.exit);
     }
     // TODO(sra): Handle JS-interop methods.
-    closeFunction();
+    _closeFunction();
   }
 
-  void addImplicitInstantiation(DartType type) {
+  void _addImplicitInstantiation(DartType type) {
     if (type != null) {
-      currentImplicitInstantiations.add(type);
+      _currentImplicitInstantiations.add(type);
     }
   }
 
-  void removeImplicitInstantiation(DartType type) {
+  void _removeImplicitInstantiation(DartType type) {
     if (type != null) {
-      currentImplicitInstantiations.removeLast();
+      _currentImplicitInstantiations.removeLast();
     }
   }
 
-  void openFunction(MemberEntity member,
+  void _openFunction(MemberEntity member,
       {ir.FunctionNode functionNode,
       ParameterStructure parameterStructure,
       TargetChecks checks}) {
@@ -1381,7 +1593,7 @@
 
       void handleParameter(ir.VariableDeclaration node,
           {bool isOptional, bool isElided}) {
-        Local local = localsMap.getLocalVariable(node);
+        Local local = _localsMap.getLocalVariable(node);
         if (isElided) {
           elidedParameters.add(node);
           elidedParameterSet.add(local);
@@ -1402,20 +1614,20 @@
     // but cannot receive constants before it has been closed. By closing it
     // here, we can use constants in the code that sets up the function.
     open(graph.entry);
-    close(new HGoto(abstractValueDomain)).addSuccessor(block);
+    close(new HGoto(_abstractValueDomain)).addSuccessor(block);
     open(block);
 
     localsHandler.startFunction(
         targetElement,
-        closureDataLookup.getScopeInfo(targetElement),
-        closureDataLookup.getCapturedScope(targetElement),
+        _closureDataLookup.getScopeInfo(targetElement),
+        _closureDataLookup.getCapturedScope(targetElement),
         parameterMap,
         elidedParameterSet,
         _sourceInformationBuilder.buildDeclaration(targetElement),
         isGenerativeConstructorBody: targetElement is ConstructorBodyEntity);
 
     for (ir.VariableDeclaration node in elidedParameters) {
-      Local local = localsMap.getLocalVariable(node);
+      Local local = _localsMap.getLocalVariable(node);
       localsHandler.updateLocal(local, _defaultValueForParameter(node));
     }
 
@@ -1428,9 +1640,9 @@
     _insertCoverageCall(member);
   }
 
-  void closeFunction() {
-    if (!isAborted()) closeAndGotoExit(new HGoto(abstractValueDomain));
-    graph.finalize(abstractValueDomain);
+  void _closeFunction() {
+    if (!isAborted()) _closeAndGotoExit(new HGoto(_abstractValueDomain));
+    graph.finalize(_abstractValueDomain);
   }
 
   @override
@@ -1439,12 +1651,9 @@
   }
 
   /// Returns the current source element. This is used by the type builder.
-  ///
-  /// The returned element is a declaration element.
   // TODO(efortuna): Update this when we implement inlining.
   // TODO(sra): Re-implement type builder using Kernel types and the
   // `target` for context.
-  @override
   MemberEntity get sourceElement => _currentFrame.member;
 
   @override
@@ -1471,9 +1680,9 @@
         _elementMap.getImport(loadLibrary.import));
     // TODO(efortuna): Source information!
     push(new HInvokeStatic(
-        commonElements.loadDeferredLibrary,
+        _commonElements.loadDeferredLibrary,
         <HInstruction>[graph.addConstantString(loadId, closedWorld)],
-        abstractValueDomain.nonNullType,
+        _abstractValueDomain.nonNullType,
         const <DartType>[],
         targetCanThrow: false));
   }
@@ -1481,10 +1690,10 @@
   @override
   void visitBlock(ir.Block block) {
     assert(!isAborted());
-    if (!isReachable) return; // This can only happen when inlining.
+    if (!_isReachable) return; // This can only happen when inlining.
     for (ir.Statement statement in block.statements) {
       statement.accept(this);
-      if (!isReachable) {
+      if (!_isReachable) {
         // The block has been aborted by a return or a throw.
         if (stack.isNotEmpty) {
           reporter.internalError(
@@ -1507,15 +1716,15 @@
 
   @override
   void visitExpressionStatement(ir.ExpressionStatement node) {
-    if (!isReachable) return;
+    if (!_isReachable) return;
     ir.Expression expression = node.expression;
     if (expression is ir.Throw && _inliningStack.isEmpty) {
       _visitThrowExpression(expression.expression);
-      handleInTryStatement();
+      _handleInTryStatement();
       SourceInformation sourceInformation =
           _sourceInformationBuilder.buildThrow(node.expression);
-      closeAndGotoExit(
-          new HThrow(abstractValueDomain, pop(), sourceInformation));
+      _closeAndGotoExit(
+          new HThrow(_abstractValueDomain, pop(), sourceInformation));
     } else {
       expression.accept(this);
       pop();
@@ -1529,37 +1738,19 @@
         _sourceInformationBuilder.buildGet(node);
     if (!closedWorld.outputUnitData
         .hasOnlyNonDeferredImportPathsToConstant(targetElement, value)) {
+      OutputUnit outputUnit =
+          closedWorld.outputUnitData.outputUnitForConstant(value);
+      ConstantValue deferredConstant =
+          new DeferredGlobalConstantValue(value, outputUnit);
+      registry.registerConstantUse(new ConstantUse.deferred(deferredConstant));
       stack.add(graph.addDeferredConstant(
-          value,
-          closedWorld.outputUnitData.outputUnitForConstant(value),
-          sourceInformation,
-          closedWorld));
+          deferredConstant, sourceInformation, closedWorld));
     } else {
       stack.add(graph.addConstant(value, closedWorld,
           sourceInformation: sourceInformation));
     }
   }
 
-  /// Returns true if the [type] is a valid return type for an asynchronous
-  /// function.
-  ///
-  /// Asynchronous functions return a `Future`, and a valid return is thus
-  /// either dynamic, Object, or Future.
-  ///
-  /// We do not accept the internal Future implementation class.
-  bool isValidAsyncReturnType(DartType type) {
-    // TODO(sigurdm): In an internal library a function could be declared:
-    //
-    // _FutureImpl foo async => 1;
-    //
-    // This should be valid (because the actual value returned from an async
-    // function is a `_FutureImpl`), but currently false is returned in this
-    // case.
-    return type.isDynamic ||
-        type == _commonElements.objectType ||
-        (type is InterfaceType && type.element == _commonElements.futureClass);
-  }
-
   @override
   void visitReturnStatement(ir.ReturnStatement node) {
     SourceInformation sourceInformation =
@@ -1583,11 +1774,11 @@
           return;
         }*/
       } else {
-        value = typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
+        value = _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
             value, _returnType);
       }
     }
-    handleInTryStatement();
+    _handleInTryStatement();
     if (_inliningStack.isEmpty && targetElement.isSetter) {
       if (node.parent is ir.FunctionNode) {
         // An arrow function definition of a setter has a ReturnStatemnt as a
@@ -1601,7 +1792,7 @@
 
   @override
   void visitForStatement(ir.ForStatement node) {
-    assert(isReachable);
+    assert(_isReachable);
     assert(node.body != null);
     void buildInitializer() {
       for (ir.VariableDeclaration declaration in node.variables) {
@@ -1631,10 +1822,10 @@
       node.body.accept(this);
     }
 
-    JumpTarget jumpTarget = localsMap.getJumpTargetForFor(node);
-    loopHandler.handleLoop(
+    JumpTarget jumpTarget = _localsMap.getJumpTargetForFor(node);
+    _loopHandler.handleLoop(
         node,
-        closureDataLookup.getCapturedLoopScope(node),
+        _closureDataLookup.getCapturedLoopScope(node),
         jumpTarget,
         buildInitializer,
         buildCondition,
@@ -1648,7 +1839,7 @@
     if (node.isAsync) {
       _buildAsyncForIn(node);
     } else if (_typeInferenceMap.isJsIndexableIterator(
-        node, abstractValueDomain)) {
+        node, _abstractValueDomain)) {
       // If the expression being iterated over is a JS indexable type, we can
       // generate an optimized version of for-in that uses indexing.
       _buildForInIndexable(node);
@@ -1668,7 +1859,7 @@
   ///      <declaredIdentifier> = a[i];
   ///      <body>
   ///    }
-  _buildForInIndexable(ir.ForInStatement node) {
+  void _buildForInIndexable(ir.ForInStatement node) {
     SyntheticLocal indexVariable = localsHandler.createLocal('_i');
 
     // These variables are shared by initializer, condition, body and update.
@@ -1678,7 +1869,7 @@
 
     HInstruction buildGetLength(SourceInformation sourceInformation) {
       HGetLength result = new HGetLength(
-          array, abstractValueDomain.positiveIntType,
+          array, _abstractValueDomain.positiveIntType,
           isAssignable: !isFixed)
         ..sourceInformation = sourceInformation;
       add(result);
@@ -1696,7 +1887,7 @@
           _sourceInformationBuilder.buildForInMoveNext(node);
       HInstruction length = buildGetLength(sourceInformation);
       push(new HIdentity(
-          length, originalLength, null, abstractValueDomain.boolType)
+          length, originalLength, null, _abstractValueDomain.boolType)
         ..sourceInformation = sourceInformation);
       _pushStaticInvocation(
           _commonElements.checkConcurrentModificationError,
@@ -1714,7 +1905,7 @@
 
       node.iterable.accept(this);
       array = pop();
-      isFixed = abstractValueDomain
+      isFixed = _abstractValueDomain
           .isFixedLengthJsIndexable(array.instructionType)
           .isDefinitelyTrue;
       localsHandler.updateLocal(
@@ -1730,7 +1921,7 @@
           sourceInformation: sourceInformation);
       HInstruction length = buildGetLength(sourceInformation);
       HInstruction compare =
-          new HLess(index, length, null, abstractValueDomain.boolType)
+          new HLess(index, length, null, _abstractValueDomain.boolType)
             ..sourceInformation = sourceInformation;
       add(compare);
       return compare;
@@ -1757,7 +1948,7 @@
         ..sourceInformation = sourceInformation;
       add(value);
 
-      Local loopVariableLocal = localsMap.getLocalVariable(node.variable);
+      Local loopVariableLocal = _localsMap.getLocalVariable(node.variable);
       localsHandler.updateLocal(loopVariableLocal, value,
           sourceInformation: sourceInformation);
       // Hint to name loop value after name of loop variable.
@@ -1782,17 +1973,17 @@
           sourceInformation: sourceInformation);
       HInstruction one = graph.addConstantInt(1, closedWorld);
       HInstruction addInstruction =
-          new HAdd(index, one, null, abstractValueDomain.positiveIntType)
+          new HAdd(index, one, null, _abstractValueDomain.positiveIntType)
             ..sourceInformation = sourceInformation;
       add(addInstruction);
       localsHandler.updateLocal(indexVariable, addInstruction,
           sourceInformation: sourceInformation);
     }
 
-    loopHandler.handleLoop(
+    _loopHandler.handleLoop(
         node,
-        closureDataLookup.getCapturedLoopScope(node),
-        localsMap.getJumpTargetForForIn(node),
+        _closureDataLookup.getCapturedLoopScope(node),
+        _localsMap.getJumpTargetForForIn(node),
         buildInitializer,
         buildCondition,
         buildUpdate,
@@ -1800,7 +1991,7 @@
         _sourceInformationBuilder.buildLoop(node));
   }
 
-  _buildForInIterator(ir.ForInStatement node) {
+  void _buildForInIterator(ir.ForInStatement node) {
     // Generate a structure equivalent to:
     //   Iterator<E> $iter = <iterable>.iterator;
     //   while ($iter.moveNext()) {
@@ -1810,14 +2001,16 @@
 
     // The iterator is shared between initializer, condition and body.
     HInstruction iterator;
+    StaticType iteratorType = _getStaticForInIteratorType(node);
 
     void buildInitializer() {
-      AbstractValue mask = _typeInferenceMap.typeOfIterator(node);
+      AbstractValue receiverType = _typeInferenceMap.typeOfIterator(node);
       node.iterable.accept(this);
       HInstruction receiver = pop();
       _pushDynamicInvocation(
           node,
-          mask,
+          _getStaticType(node.iterable),
+          receiverType,
           Selectors.iterator,
           <HInstruction>[receiver],
           const <DartType>[],
@@ -1826,10 +2019,12 @@
     }
 
     HInstruction buildCondition() {
-      AbstractValue mask = _typeInferenceMap.typeOfIteratorMoveNext(node);
+      AbstractValue receiverType =
+          _typeInferenceMap.typeOfIteratorMoveNext(node);
       _pushDynamicInvocation(
           node,
-          mask,
+          iteratorType,
+          receiverType,
           Selectors.moveNext,
           <HInstruction>[iterator],
           const <DartType>[],
@@ -1840,12 +2035,13 @@
     void buildBody() {
       SourceInformation sourceInformation =
           _sourceInformationBuilder.buildForInCurrent(node);
-      AbstractValue mask = _typeInferenceMap.typeOfIteratorCurrent(node);
-      _pushDynamicInvocation(node, mask, Selectors.current, [iterator],
-          const <DartType>[], sourceInformation);
+      AbstractValue receiverType =
+          _typeInferenceMap.typeOfIteratorCurrent(node);
+      _pushDynamicInvocation(node, iteratorType, receiverType,
+          Selectors.current, [iterator], const <DartType>[], sourceInformation);
 
-      Local loopVariableLocal = localsMap.getLocalVariable(node.variable);
-      HInstruction value = typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
+      Local loopVariableLocal = _localsMap.getLocalVariable(node.variable);
+      HInstruction value = _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
           pop(), _getDartTypeIfValid(node.variable.type));
       localsHandler.updateLocal(loopVariableLocal, value,
           sourceInformation: sourceInformation);
@@ -1856,10 +2052,10 @@
       node.body.accept(this);
     }
 
-    loopHandler.handleLoop(
+    _loopHandler.handleLoop(
         node,
-        closureDataLookup.getCapturedLoopScope(node),
-        localsMap.getJumpTargetForForIn(node),
+        _closureDataLookup.getCapturedLoopScope(node),
+        _localsMap.getJumpTargetForForIn(node),
         buildInitializer,
         buildCondition,
         () {},
@@ -1878,12 +2074,15 @@
     DartType typeArg = _elementMap.getDartType(node.variable.type);
     InterfaceType instanceType =
         localsHandler.substInContext(new InterfaceType(cls, [typeArg]));
-    addImplicitInstantiation(instanceType);
+    // TODO(johnniwinther): This should be the exact type.
+    StaticType staticInstanceType =
+        new StaticType(instanceType, ClassRelation.subtype);
+    _addImplicitInstantiation(instanceType);
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildForInIterator(node);
     // TODO(johnniwinther): Pass type arguments to constructors like calling
     // a generic method.
-    if (rtiNeed.classNeedsTypeArguments(cls)) {
+    if (_rtiNeed.classNeedsTypeArguments(cls)) {
       _addTypeArguments(arguments, [typeArg], sourceInformation);
     }
     ConstructorEntity constructor = _commonElements.streamIteratorConstructor;
@@ -1896,30 +2095,34 @@
     void buildInitializer() {}
 
     HInstruction buildCondition() {
-      AbstractValue mask = _typeInferenceMap.typeOfIteratorMoveNext(node);
+      AbstractValue receiverType =
+          _typeInferenceMap.typeOfIteratorMoveNext(node);
       _pushDynamicInvocation(
           node,
-          mask,
+          staticInstanceType,
+          receiverType,
           Selectors.moveNext,
           [streamIterator],
           const <DartType>[],
           _sourceInformationBuilder.buildForInMoveNext(node));
       HInstruction future = pop();
-      push(new HAwait(future, abstractValueDomain.dynamicType));
+      push(new HAwait(future, _abstractValueDomain.dynamicType));
       return popBoolified();
     }
 
     void buildBody() {
-      AbstractValue mask = _typeInferenceMap.typeOfIteratorCurrent(node);
+      AbstractValue receiverType =
+          _typeInferenceMap.typeOfIteratorCurrent(node);
       _pushDynamicInvocation(
           node,
-          mask,
+          staticInstanceType,
+          receiverType,
           Selectors.current,
           [streamIterator],
           const <DartType>[],
           _sourceInformationBuilder.buildForInIterator(node));
       localsHandler.updateLocal(
-          localsMap.getLocalVariable(node.variable), pop());
+          _localsMap.getLocalVariable(node.variable), pop());
       node.body.accept(this);
     }
 
@@ -1929,10 +2132,10 @@
     TryCatchFinallyBuilder tryBuilder = new TryCatchFinallyBuilder(
         this, _sourceInformationBuilder.buildLoop(node));
     // Build fake try body:
-    loopHandler.handleLoop(
+    _loopHandler.handleLoop(
         node,
-        closureDataLookup.getCapturedLoopScope(node),
-        localsMap.getJumpTargetForForIn(node),
+        _closureDataLookup.getCapturedLoopScope(node),
+        _localsMap.getJumpTargetForForIn(node),
         buildInitializer,
         buildCondition,
         buildUpdate,
@@ -1942,6 +2145,7 @@
     void finalizerFunction() {
       _pushDynamicInvocation(
           node,
+          staticInstanceType,
           null,
           Selectors.cancel,
           [streamIterator],
@@ -1949,7 +2153,7 @@
           _sourceInformationBuilder
               // ignore:deprecated_member_use_from_same_package
               .buildGeneric(node));
-      add(new HAwait(pop(), abstractValueDomain.dynamicType));
+      add(new HAwait(pop(), _abstractValueDomain.dynamicType));
     }
 
     tryBuilder
@@ -1958,14 +2162,13 @@
       ..cleanUp();
   }
 
-  @override
-  HInstruction callSetRuntimeTypeInfo(HInstruction typeInfo,
+  HInstruction _callSetRuntimeTypeInfo(HInstruction typeInfo,
       HInstruction newObject, SourceInformation sourceInformation) {
     // Set the runtime type information on the object.
     FunctionEntity typeInfoSetterFn = _commonElements.setRuntimeTypeInfo;
     // TODO(efortuna): Insert source information in this static invocation.
     _pushStaticInvocation(typeInfoSetterFn, <HInstruction>[newObject, typeInfo],
-        abstractValueDomain.dynamicType, const <DartType>[],
+        _abstractValueDomain.dynamicType, const <DartType>[],
         sourceInformation: sourceInformation);
 
     // The new object will now be referenced through the
@@ -1984,16 +2187,16 @@
 
   @override
   void visitWhileStatement(ir.WhileStatement node) {
-    assert(isReachable);
+    assert(_isReachable);
     HInstruction buildCondition() {
       node.condition.accept(this);
       return popBoolified();
     }
 
-    loopHandler.handleLoop(
+    _loopHandler.handleLoop(
         node,
-        closureDataLookup.getCapturedLoopScope(node),
-        localsMap.getJumpTargetForWhile(node),
+        _closureDataLookup.getCapturedLoopScope(node),
+        _localsMap.getJumpTargetForWhile(node),
         () {},
         buildCondition,
         () {}, () {
@@ -2002,17 +2205,17 @@
   }
 
   @override
-  visitDoStatement(ir.DoStatement node) {
+  void visitDoStatement(ir.DoStatement node) {
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildLoop(node);
     // TODO(efortuna): I think this can be rewritten using
     // LoopHandler.handleLoop with some tricks about when the "update" happens.
     LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
     CapturedLoopScope loopClosureInfo =
-        closureDataLookup.getCapturedLoopScope(node);
+        _closureDataLookup.getCapturedLoopScope(node);
     localsHandler.startLoop(loopClosureInfo, sourceInformation);
-    JumpTarget target = localsMap.getJumpTargetForDo(node);
-    JumpHandler jumpHandler = loopHandler.beginLoopHeader(node, target);
+    JumpTarget target = _localsMap.getJumpTargetForDo(node);
+    JumpHandler jumpHandler = _loopHandler.beginLoopHeader(node, target);
     HLoopInformation loopInfo = current.loopInformation;
     HBasicBlock loopEntryBlock = current;
     HBasicBlock bodyEntryBlock = current;
@@ -2035,7 +2238,7 @@
     HBasicBlock bodyExitBlock;
     bool isAbortingBody = false;
     if (current != null) {
-      bodyExitBlock = close(new HGoto(abstractValueDomain));
+      bodyExitBlock = close(new HGoto(_abstractValueDomain));
     } else {
       isAbortingBody = true;
       bodyExitBlock = lastOpenedBlock;
@@ -2080,13 +2283,15 @@
       node.condition.accept(this);
       assert(!isAborted());
       HInstruction conditionInstruction = popBoolified();
-      HBasicBlock conditionEndBlock = close(new HLoopBranch(abstractValueDomain,
-          conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
+      HBasicBlock conditionEndBlock = close(new HLoopBranch(
+          _abstractValueDomain,
+          conditionInstruction,
+          HLoopBranch.DO_WHILE_LOOP));
 
       HBasicBlock avoidCriticalEdge = addNewBlock();
       conditionEndBlock.addSuccessor(avoidCriticalEdge);
       open(avoidCriticalEdge);
-      close(new HGoto(abstractValueDomain));
+      close(new HGoto(_abstractValueDomain));
       avoidCriticalEdge.addSuccessor(loopEntryBlock); // The back-edge.
 
       conditionExpression =
@@ -2095,10 +2300,10 @@
       // Avoid a critical edge from the condition to the loop-exit body.
       HBasicBlock conditionExitBlock = addNewBlock();
       open(conditionExitBlock);
-      close(new HGoto(abstractValueDomain));
+      close(new HGoto(_abstractValueDomain));
       conditionEndBlock.addSuccessor(conditionExitBlock);
 
-      loopHandler.endLoop(
+      _loopHandler.endLoop(
           loopEntryBlock, conditionExitBlock, jumpHandler, localsHandler);
 
       loopEntryBlock.postProcessLoopHeader();
@@ -2122,12 +2327,12 @@
       if (jumpHandler.hasAnyBreak()) {
         // Null branchBlock because the body of the do-while loop always aborts,
         // so we never get to the condition.
-        loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler);
+        _loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler);
 
         // Since the body of the loop has a break, we attach a synthesized label
         // to the body.
         SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
-        JumpTarget target = localsMap.getJumpTargetForDo(node);
+        JumpTarget target = _localsMap.getJumpTargetForDo(node);
         LabelDefinition label = target.addLabel('loop', isBreakTarget: true);
         HLabeledBlockInformation info = new HLabeledBlockInformation(
             new HSubGraphBlockInformation(bodyGraph), <LabelDefinition>[label]);
@@ -2135,7 +2340,7 @@
         jumpHandler.forEachBreak((HBreak breakInstruction, _) {
           HBasicBlock block = breakInstruction.block;
           block.addAtExit(new HBreak.toLabel(
-              abstractValueDomain, label, sourceInformation));
+              _abstractValueDomain, label, sourceInformation));
           block.remove(breakInstruction);
         });
       }
@@ -2145,14 +2350,14 @@
 
   @override
   void visitIfStatement(ir.IfStatement node) {
-    handleIf(
+    _handleIf(
         visitCondition: () => node.condition.accept(this),
         visitThen: () => node.then.accept(this),
         visitElse: () => node.otherwise?.accept(this),
         sourceInformation: _sourceInformationBuilder.buildIf(node));
   }
 
-  void handleIf(
+  void _handleIf(
       {ir.Node node,
       void visitCondition(),
       void visitThen(),
@@ -2169,9 +2374,9 @@
     ir.Expression operand = node.operand;
     operand.accept(this);
 
-    DartType operandType = _getStaticType(operand);
+    StaticType operandType = _getStaticType(operand);
     DartType type = _elementMap.getDartType(node.type);
-    if (_elementMap.types.isSubtype(operandType, type)) {
+    if (_elementMap.types.isSubtype(operandType.type, type)) {
       // Skip unneeded casts.
       if (operand is! ir.PropertyGet) {
         // TODO(johnniwinther): Support property get. Currently CFE inserts
@@ -2188,18 +2393,18 @@
     HInstruction expressionInstruction = pop();
 
     if (node.type is ir.InvalidType) {
-      generateTypeError('invalid type', sourceInformation);
+      _generateTypeError('invalid type', sourceInformation);
       return;
     }
 
     if ((!node.isTypeError && !options.omitAsCasts) ||
         options.implicitDowncastCheckPolicy.isEmitted) {
-      HInstruction converted = typeBuilder.buildTypeConversion(
+      HInstruction converted = _typeBuilder.buildTypeConversion(
           expressionInstruction,
           localsHandler.substInContext(type),
           node.isTypeError
-              ? HTypeConversion.CHECKED_MODE_CHECK
-              : HTypeConversion.CAST_TYPE_CHECK,
+              ? HTypeConversion.TYPE_CHECK
+              : HTypeConversion.CAST_CHECK,
           sourceInformation: sourceInformation);
       if (converted != expressionInstruction) {
         add(converted);
@@ -2210,7 +2415,7 @@
     }
   }
 
-  void generateError(FunctionEntity function, String message,
+  void _generateError(FunctionEntity function, String message,
       AbstractValue typeMask, SourceInformation sourceInformation) {
     HInstruction errorMessage = graph.addConstantString(message, closedWorld);
     _pushStaticInvocation(
@@ -2218,17 +2423,17 @@
         sourceInformation: sourceInformation);
   }
 
-  void generateTypeError(String message, SourceInformation sourceInformation) {
-    generateError(
+  void _generateTypeError(String message, SourceInformation sourceInformation) {
+    _generateError(
         _commonElements.throwTypeError,
         message,
         _typeInferenceMap.getReturnTypeOf(_commonElements.throwTypeError),
         sourceInformation);
   }
 
-  void generateUnsupportedError(
+  void _generateUnsupportedError(
       String message, SourceInformation sourceInformation) {
-    generateError(
+    _generateError(
         _commonElements.throwUnsupportedError,
         message,
         _typeInferenceMap
@@ -2274,7 +2479,7 @@
       pop();
     }
 
-    handleIf(visitCondition: buildCondition, visitThen: fail);
+    _handleIf(visitCondition: buildCondition, visitThen: fail);
   }
 
   /// Creates a [JumpHandler] for a statement. The node must be a jump
@@ -2291,7 +2496,7 @@
       return new NullJumpHandler(reporter);
     }
     if (isLoopJump && node is ir.SwitchStatement) {
-      return new KernelSwitchCaseJumpHandler(this, target, node, localsMap);
+      return new KernelSwitchCaseJumpHandler(this, target, node, _localsMap);
     }
 
     return new JumpHandler(this, target);
@@ -2300,14 +2505,14 @@
   @override
   void visitBreakStatement(ir.BreakStatement node) {
     assert(!isAborted());
-    handleInTryStatement();
-    JumpTarget target = localsMap.getJumpTargetForBreak(node);
+    _handleInTryStatement();
+    JumpTarget target = _localsMap.getJumpTargetForBreak(node);
     assert(target != null);
     JumpHandler handler = jumpTargets[target];
     assert(handler != null);
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildGoto(node);
-    if (localsMap.generateContinueForBreak(node)) {
+    if (_localsMap.generateContinueForBreak(node)) {
       if (handler.labels.isNotEmpty) {
         handler.generateContinue(sourceInformation, handler.labels.first);
       } else {
@@ -2330,7 +2535,7 @@
       body.accept(this);
       return;
     }
-    JumpTarget jumpTarget = localsMap.getJumpTargetForLabel(node);
+    JumpTarget jumpTarget = _localsMap.getJumpTargetForLabel(node);
     if (jumpTarget == null) {
       // The label is not needed.
       body.accept(this);
@@ -2385,8 +2590,8 @@
 
   @override
   void visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {
-    handleInTryStatement();
-    JumpTarget target = localsMap.getJumpTargetForContinueSwitch(node);
+    _handleInTryStatement();
+    JumpTarget target = _localsMap.getJumpTargetForContinueSwitch(node);
     assert(target != null);
     JumpHandler handler = jumpTargets[target];
     assert(handler != null);
@@ -2417,7 +2622,7 @@
     }
 
     JumpHandler jumpHandler =
-        createJumpHandler(node, localsMap.getJumpTargetForSwitch(node));
+        createJumpHandler(node, _localsMap.getJumpTargetForSwitch(node));
     if (!hasContinue) {
       // If the switch statement has no switch cases targeted by continue
       // statements we encode the switch statement directly.
@@ -2512,7 +2717,8 @@
     // This is because JS does not have this same "continue label" semantics so
     // we encode it in the form of a state machine.
 
-    JumpTarget switchTarget = localsMap.getJumpTargetForSwitch(switchStatement);
+    JumpTarget switchTarget =
+        _localsMap.getJumpTargetForSwitch(switchStatement);
     localsHandler.updateLocal(switchTarget, graph.addConstantNull(closedWorld));
 
     var switchCases = switchStatement.cases;
@@ -2591,9 +2797,9 @@
     }
 
     void buildLoop() {
-      loopHandler.handleLoop(
+      _loopHandler.handleLoop(
           switchStatement,
-          closureDataLookup.getCapturedLoopScope(switchStatement),
+          _closureDataLookup.getCapturedLoopScope(switchStatement),
           switchTarget,
           () {},
           buildCondition,
@@ -2611,12 +2817,12 @@
       // null, so we don't drop into the while loop.
       void buildCondition() {
         js.Template code = js.js.parseForeignJS('#');
-        push(new HForeignCode(code, abstractValueDomain.boolType,
+        push(new HForeignCode(code, _abstractValueDomain.boolType,
             [localsHandler.readLocal(switchTarget)],
             nativeBehavior: NativeBehavior.PURE));
       }
 
-      handleIf(
+      _handleIf(
           node: switchStatement,
           visitCondition: buildCondition,
           visitThen: buildLoop,
@@ -2647,7 +2853,7 @@
     }
 
     HSwitch switchInstruction =
-        new HSwitch(abstractValueDomain, <HInstruction>[expression]);
+        new HSwitch(_abstractValueDomain, <HInstruction>[expression]);
     HBasicBlock expressionEnd = close(switchInstruction);
     LocalsHandler savedLocals = localsHandler;
 
@@ -2707,7 +2913,7 @@
               'Continue cannot target a switch.'));
     });
     if (!isAborted()) {
-      current.close(new HGoto(abstractValueDomain));
+      current.close(new HGoto(_abstractValueDomain));
       lastOpenedBlock.addSuccessor(joinBlock);
       caseHandlers.add(localsHandler);
     }
@@ -2717,7 +2923,7 @@
       HBasicBlock defaultCase = addNewBlock();
       expressionEnd.addSuccessor(defaultCase);
       open(defaultCase);
-      close(new HGoto(abstractValueDomain));
+      close(new HGoto(_abstractValueDomain));
       defaultCase.addSuccessor(joinBlock);
       caseHandlers.add(savedLocals);
       statements.add(new HSubGraphBlockInformation(
@@ -2833,16 +3039,16 @@
   /// Set the runtime type information if necessary.
   HInstruction _setListRuntimeTypeInfoIfNeeded(HInstruction object,
       InterfaceType type, SourceInformation sourceInformation) {
-    if (!rtiNeed.classNeedsTypeArguments(type.element) || type.treatAsRaw) {
+    if (!_rtiNeed.classNeedsTypeArguments(type.element) || type.treatAsRaw) {
       return object;
     }
     List<HInstruction> arguments = <HInstruction>[];
     for (DartType argument in type.typeArguments) {
-      arguments.add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
+      arguments.add(_typeBuilder.analyzeTypeArgument(argument, sourceElement));
     }
     // TODO(15489): Register at codegen.
     registry?.registerInstantiation(type);
-    return callSetRuntimeTypeInfoWithTypeArguments(
+    return _callSetRuntimeTypeInfoWithTypeArguments(
         type, arguments, object, sourceInformation);
   }
 
@@ -2858,7 +3064,7 @@
         element.accept(this);
         elements.add(pop());
       }
-      listInstruction = buildLiteralList(elements);
+      listInstruction = _buildLiteralList(elements);
       add(listInstruction);
       SourceInformation sourceInformation =
           _sourceInformationBuilder.buildListLiteral(node);
@@ -2869,8 +3075,8 @@
     }
 
     AbstractValue type =
-        _typeInferenceMap.typeOfListLiteral(node, abstractValueDomain);
-    if (abstractValueDomain.containsAll(type).isDefinitelyFalse) {
+        _typeInferenceMap.typeOfListLiteral(node, _abstractValueDomain);
+    if (_abstractValueDomain.containsAll(type).isDefinitelyFalse) {
       listInstruction.instructionType = type;
     }
     stack.add(listInstruction);
@@ -2898,7 +3104,7 @@
       constructor = _commonElements.setLiteralConstructorEmpty;
     } else {
       constructor = _commonElements.setLiteralConstructor;
-      HLiteralList argList = buildLiteralList(elements);
+      HLiteralList argList = _buildLiteralList(elements);
       add(argList);
       inputs.add(argList);
     }
@@ -2910,17 +3116,17 @@
         _commonElements.setType(_elementMap.getDartType(node.typeArgument)));
     ClassEntity cls = constructor.enclosingClass;
 
-    if (rtiNeed.classNeedsTypeArguments(cls)) {
+    if (_rtiNeed.classNeedsTypeArguments(cls)) {
       List<HInstruction> typeInputs = <HInstruction>[];
       type.typeArguments.forEach((DartType argument) {
         typeInputs
-            .add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
+            .add(_typeBuilder.analyzeTypeArgument(argument, sourceElement));
       });
 
       // We lift this common call pattern into a helper function to save space
       // in the output.
       if (typeInputs.every((HInstruction input) =>
-          input.isNull(abstractValueDomain).isDefinitelyTrue)) {
+          input.isNull(_abstractValueDomain).isDefinitelyTrue)) {
         if (elements.isEmpty) {
           constructor = _commonElements.setLiteralUntypedEmptyMaker;
         } else {
@@ -2941,18 +3147,18 @@
     // type inference might discover a more specific type or find nothing (in
     // dart2js unit tests).
 
-    AbstractValue setType = abstractValueDomain
+    AbstractValue setType = _abstractValueDomain
         .createNonNullSubtype(_commonElements.setLiteralClass);
     AbstractValue returnTypeMask =
         _typeInferenceMap.getReturnTypeOf(constructor);
     AbstractValue instructionType =
-        abstractValueDomain.intersection(setType, returnTypeMask);
+        _abstractValueDomain.intersection(setType, returnTypeMask);
 
-    addImplicitInstantiation(type);
+    _addImplicitInstantiation(type);
     _pushStaticInvocation(
         constructor, inputs, instructionType, const <DartType>[],
         sourceInformation: _sourceInformationBuilder.buildNew(node));
-    removeImplicitInstantiation(type);
+    _removeImplicitInstantiation(type);
   }
 
   @override
@@ -2979,7 +3185,7 @@
       constructor = _commonElements.mapLiteralConstructorEmpty;
     } else {
       constructor = _commonElements.mapLiteralConstructor;
-      HLiteralList argList = buildLiteralList(constructorArgs);
+      HLiteralList argList = _buildLiteralList(constructorArgs);
       add(argList);
       inputs.add(argList);
     }
@@ -2992,17 +3198,17 @@
         _elementMap.getDartType(node.valueType)));
     ClassEntity cls = constructor.enclosingClass;
 
-    if (rtiNeed.classNeedsTypeArguments(cls)) {
+    if (_rtiNeed.classNeedsTypeArguments(cls)) {
       List<HInstruction> typeInputs = <HInstruction>[];
       type.typeArguments.forEach((DartType argument) {
         typeInputs
-            .add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
+            .add(_typeBuilder.analyzeTypeArgument(argument, sourceElement));
       });
 
       // We lift this common call pattern into a helper function to save space
       // in the output.
       if (typeInputs.every((HInstruction input) =>
-          input.isNull(abstractValueDomain).isDefinitelyTrue)) {
+          input.isNull(_abstractValueDomain).isDefinitelyTrue)) {
         if (constructorArgs.isEmpty) {
           constructor = _commonElements.mapLiteralUntypedEmptyMaker;
         } else {
@@ -3023,18 +3229,18 @@
     // type inference might discover a more specific type, or find nothing (in
     // dart2js unit tests).
 
-    AbstractValue mapType = abstractValueDomain
+    AbstractValue mapType = _abstractValueDomain
         .createNonNullSubtype(_commonElements.mapLiteralClass);
     AbstractValue returnTypeMask =
         _typeInferenceMap.getReturnTypeOf(constructor);
     AbstractValue instructionType =
-        abstractValueDomain.intersection(mapType, returnTypeMask);
+        _abstractValueDomain.intersection(mapType, returnTypeMask);
 
-    addImplicitInstantiation(type);
+    _addImplicitInstantiation(type);
     _pushStaticInvocation(
         constructor, inputs, instructionType, const <DartType>[],
         sourceInformation: _sourceInformationBuilder.buildNew(node));
-    removeImplicitInstantiation(type);
+    _removeImplicitInstantiation(type);
   }
 
   @override
@@ -3067,7 +3273,7 @@
 
     DartType dartType = _elementMap.getDartType(type);
     dartType = localsHandler.substInContext(dartType);
-    HInstruction value = typeBuilder.analyzeTypeArgument(
+    HInstruction value = _typeBuilder.analyzeTypeArgument(
         dartType, sourceElement,
         sourceInformation: sourceInformation);
     _pushStaticInvocation(
@@ -3097,15 +3303,20 @@
         push(new HStatic(field, _typeInferenceMap.getInferredTypeOf(field),
             sourceInformation));
       } else if (fieldData.isEffectivelyConstant) {
-        var unit = closedWorld.outputUnitData.outputUnitForMember(field);
+        OutputUnit outputUnit =
+            closedWorld.outputUnitData.outputUnitForMember(field);
         // TODO(sigmund): this is not equivalent to what the old FE does: if
         // there is no prefix the old FE wouldn't treat this in any special
         // way. Also, if the prefix points to a constant in the main output
         // unit, the old FE would still generate a deferred wrapper here.
         if (!closedWorld.outputUnitData
             .hasOnlyNonDeferredImportPaths(targetElement, field)) {
+          ConstantValue deferredConstant = new DeferredGlobalConstantValue(
+              fieldData.initialValue, outputUnit);
+          registry
+              .registerConstantUse(new ConstantUse.deferred(deferredConstant));
           stack.add(graph.addDeferredConstant(
-              fieldData.initialValue, unit, sourceInformation, closedWorld));
+              deferredConstant, sourceInformation, closedWorld));
         } else {
           stack.add(graph.addConstant(fieldData.initialValue, closedWorld,
               sourceInformation: sourceInformation));
@@ -3143,9 +3354,9 @@
       MemberEntity target = _elementMap.getMember(staticTarget);
       if (!_fieldAnalysis.getFieldData(target).isElided) {
         add(new HStaticStore(
-            abstractValueDomain,
+            _abstractValueDomain,
             target,
-            typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
+            _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
                 value, _getDartTypeIfValid(staticTarget.setterType))));
       }
     }
@@ -3159,6 +3370,7 @@
 
     _pushDynamicInvocation(
         node,
+        _getStaticType(node.receiver),
         _typeInferenceMap.receiverTypeOfGet(node),
         new Selector.getter(_elementMap.getName(node.name)),
         <HInstruction>[receiver],
@@ -3169,13 +3381,13 @@
   @override
   void visitVariableGet(ir.VariableGet node) {
     ir.VariableDeclaration variable = node.variable;
-    HInstruction letBinding = letBindings[variable];
+    HInstruction letBinding = _letBindings[variable];
     if (letBinding != null) {
       stack.add(letBinding);
       return;
     }
 
-    Local local = localsMap.getLocalVariable(node.variable);
+    Local local = _localsMap.getLocalVariable(node.variable);
     stack.add(localsHandler.readLocal(local,
         sourceInformation: _sourceInformationBuilder.buildGet(node)));
   }
@@ -3189,7 +3401,8 @@
 
     _pushDynamicInvocation(
         node,
-        _typeInferenceMap.receiverTypeOfSet(node, abstractValueDomain),
+        _getStaticType(node.receiver),
+        _typeInferenceMap.receiverTypeOfSet(node, _abstractValueDomain),
         new Selector.setter(_elementMap.getName(node.name)),
         <HInstruction>[receiver, value],
         const <DartType>[],
@@ -3208,6 +3421,7 @@
     // TODO(sra): Implement direct invocations properly.
     _pushDynamicInvocation(
         node,
+        _getStaticType(node.receiver),
         _typeInferenceMap.receiverTypeOfDirectGet(node),
         new Selector.getter(_elementMap.getMember(node.target).memberName),
         <HInstruction>[receiver],
@@ -3260,7 +3474,7 @@
 
   @override
   void visitVariableDeclaration(ir.VariableDeclaration node) {
-    Local local = localsMap.getLocalVariable(node);
+    Local local = _localsMap.getLocalVariable(node);
     if (node.initializer == null) {
       HInstruction initialValue = graph.addConstantNull(closedWorld);
       localsHandler.updateLocal(local, initialValue);
@@ -3283,7 +3497,7 @@
 
   void _visitLocalSetter(ir.VariableDeclaration variable, HInstruction value,
       SourceInformation sourceInformation) {
-    Local local = localsMap.getLocalVariable(variable);
+    Local local = _localsMap.getLocalVariable(variable);
 
     // Give the value a name if it doesn't have one already.
     if (value.sourceElement == null) {
@@ -3293,7 +3507,7 @@
     stack.add(value);
     localsHandler.updateLocal(
         local,
-        typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
+        _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
             value, _getDartTypeIfValid(variable.type)),
         sourceInformation: sourceInformation);
   }
@@ -3304,7 +3518,7 @@
     variable.initializer.accept(this);
     HInstruction initializedValue = pop();
     // TODO(sra): Apply inferred type information.
-    letBindings[variable] = initializedValue;
+    _letBindings[variable] = initializedValue;
     node.body.accept(this);
   }
 
@@ -3401,7 +3615,7 @@
   Selector _fillDynamicTypeArguments(
       Selector selector, ir.Arguments arguments, List<DartType> typeArguments) {
     if (selector.typeArgumentCount > 0) {
-      if (rtiNeed.selectorNeedsTypeArguments(selector)) {
+      if (_rtiNeed.selectorNeedsTypeArguments(selector)) {
         typeArguments.addAll(arguments.types.map(_elementMap.getDartType));
       } else {
         return selector.toNonGeneric();
@@ -3421,7 +3635,7 @@
   // constructors like calling a generic method.
   List<DartType> _getClassTypeArguments(
       ClassEntity cls, ir.Arguments arguments) {
-    if (rtiNeed.classNeedsTypeArguments(cls)) {
+    if (_rtiNeed.classNeedsTypeArguments(cls)) {
       return arguments.types.map(_elementMap.getDartType).toList();
     }
     return const <DartType>[];
@@ -3429,7 +3643,7 @@
 
   List<DartType> _getStaticTypeArguments(
       FunctionEntity function, ir.Arguments arguments) {
-    if (rtiNeed.methodNeedsTypeArguments(function)) {
+    if (_rtiNeed.methodNeedsTypeArguments(function)) {
       return arguments.types.map(_elementMap.getDartType).toList();
     }
     return const <DartType>[];
@@ -3491,7 +3705,7 @@
       List<DartType> typeArguments, SourceInformation sourceInformation) {
     if (typeArguments.isEmpty) return;
     for (DartType type in typeArguments) {
-      values.add(typeBuilder.analyzeTypeArgument(type, sourceElement,
+      values.add(_typeBuilder.analyzeTypeArgument(type, sourceElement,
           sourceInformation: sourceInformation));
     }
   }
@@ -3510,12 +3724,12 @@
         _sourceInformationBuilder.buildCall(node, node);
     FunctionEntity function = _elementMap.getMember(target);
     if (_commonElements.isForeignHelper(function)) {
-      handleInvokeStaticForeign(node, function);
+      _handleInvokeStaticForeign(node, function);
       return;
     }
 
     if (_commonElements.isExtractTypeArguments(function) &&
-        handleExtractTypeArguments(node, sourceInformation)) {
+        _handleExtractTypeArguments(node, sourceInformation)) {
       return;
     }
 
@@ -3540,7 +3754,7 @@
     }
 
     if (function is ConstructorEntity && function.isFactoryConstructor) {
-      handleInvokeFactoryConstructor(
+      _handleInvokeFactoryConstructor(
           node, function, typeMask, arguments, sourceInformation);
       return;
     }
@@ -3550,7 +3764,7 @@
         sourceInformation: sourceInformation);
   }
 
-  void handleInvokeFactoryConstructor(
+  void _handleInvokeFactoryConstructor(
       ir.StaticInvocation invocation,
       ConstructorEntity function,
       AbstractValue typeMask,
@@ -3563,7 +3777,7 @@
             _elementMap.getConstantValue(invocation), closedWorld,
             sourceInformation: sourceInformation));
       } else {
-        generateUnsupportedError(
+        _generateUnsupportedError(
             '${function.enclosingClass.name}.${function.name} '
             'can only be used as a const constructor',
             sourceInformation);
@@ -3576,7 +3790,7 @@
     // Recognize `new List()` and `new List(n)`.
     bool isFixedListConstructorCall = false;
     bool isGrowableListConstructorCall = false;
-    if (commonElements.isUnnamedListConstructor(function) &&
+    if (_commonElements.isUnnamedListConstructor(function) &&
         invocation.arguments.named.isEmpty) {
       int argumentCount = invocation.arguments.positional.length;
       isFixedListConstructorCall = argumentCount == 1;
@@ -3590,11 +3804,11 @@
     AbstractValue resultType = typeMask;
 
     bool isJSArrayTypedConstructor =
-        function == commonElements.jsArrayTypedConstructor;
+        function == _commonElements.jsArrayTypedConstructor;
 
     _inferredTypeOfNewList(ir.StaticInvocation node) {
       return globalInferenceResults.typeOfNewList(node) ??
-          abstractValueDomain.dynamicType;
+          _abstractValueDomain.dynamicType;
     }
 
     if (isFixedListConstructorCall) {
@@ -3606,11 +3820,11 @@
               "Unexpected arguments. "
               "Expected 1-2 argument, actual: $arguments."));
       HInstruction lengthInput = arguments.first;
-      if (lengthInput.isNumber(abstractValueDomain).isPotentiallyFalse) {
-        HTypeConversion conversion = new HTypeConversion(
-            commonElements.numType,
-            HTypeConversion.ARGUMENT_TYPE_CHECK,
-            abstractValueDomain.numType,
+      if (lengthInput.isNumber(_abstractValueDomain).isPotentiallyFalse) {
+        HPrimitiveCheck conversion = new HPrimitiveCheck(
+            _commonElements.numType,
+            HPrimitiveCheck.ARGUMENT_TYPE_CHECK,
+            _abstractValueDomain.numType,
             lengthInput,
             sourceInformation);
         add(conversion);
@@ -3629,14 +3843,14 @@
       // TODO(sra): Array allocation should be an instruction so that canThrow
       // can depend on a length type discovered in optimization.
       bool canThrow = true;
-      if (lengthInput.isUInt32(abstractValueDomain).isDefinitelyTrue) {
+      if (lengthInput.isUInt32(_abstractValueDomain).isDefinitelyTrue) {
         canThrow = false;
       }
 
       var inferredType = _inferredTypeOfNewList(invocation);
       resultType =
-          abstractValueDomain.containsAll(inferredType).isPotentiallyTrue
-              ? abstractValueDomain.fixedListType
+          _abstractValueDomain.containsAll(inferredType).isPotentiallyTrue
+              ? _abstractValueDomain.fixedListType
               : inferredType;
       HForeignCode foreign = new HForeignCode(
           code, resultType, <HInstruction>[lengthInput],
@@ -3652,15 +3866,15 @@
         js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array');
         // We set the instruction as [canThrow] to avoid it being dead code.
         // We need a finer grained side effect.
-        add(new HForeignCode(code, abstractValueDomain.nullType, [stack.last],
+        add(new HForeignCode(code, _abstractValueDomain.nullType, [stack.last],
             throwBehavior: NativeThrowBehavior.MAY));
       }
     } else if (isGrowableListConstructorCall) {
-      push(buildLiteralList(<HInstruction>[]));
+      push(_buildLiteralList(<HInstruction>[]));
       var inferredType = _inferredTypeOfNewList(invocation);
       resultType =
-          abstractValueDomain.containsAll(inferredType).isPotentiallyTrue
-              ? abstractValueDomain.growableListType
+          _abstractValueDomain.containsAll(inferredType).isPotentiallyTrue
+              ? _abstractValueDomain.growableListType
               : inferredType;
       stack.last.instructionType = resultType;
     } else if (isJSArrayTypedConstructor) {
@@ -3690,7 +3904,7 @@
           _getClassTypeArguments(function.enclosingClass, invocation.arguments),
           sourceInformation);
       instanceType = localsHandler.substInContext(instanceType);
-      addImplicitInstantiation(instanceType);
+      _addImplicitInstantiation(instanceType);
       _pushStaticInvocation(function, arguments, typeMask, typeArguments,
           sourceInformation: sourceInformation, instanceType: instanceType);
     }
@@ -3705,7 +3919,7 @@
       graph.allocatedFixedLists.add(newInstance);
     }
 
-    if (rtiNeed.classNeedsTypeArguments(commonElements.listClass) &&
+    if (_rtiNeed.classNeedsTypeArguments(_commonElements.listClass) &&
         (isFixedListConstructorCall ||
             isGrowableListConstructorCall ||
             isJSArrayTypedConstructor)) {
@@ -3718,7 +3932,7 @@
 
   /// Replace calls to `extractTypeArguments` with equivalent code. Returns
   /// `true` if `extractTypeArguments` is handled.
-  bool handleExtractTypeArguments(
+  bool _handleExtractTypeArguments(
       ir.StaticInvocation invocation, SourceInformation sourceInformation) {
     // Expand calls as follows:
     //
@@ -3747,7 +3961,7 @@
     if (!interfaceType.treatAsRaw) return false;
 
     ClassEntity cls = interfaceType.element;
-    InterfaceType thisType = _elementMap.elementEnvironment.getThisType(cls);
+    InterfaceType thisType = _elementEnvironment.getThisType(cls);
 
     List<HInstruction> arguments =
         _visitPositionalArguments(invocation.arguments);
@@ -3763,7 +3977,7 @@
       TypeVariableType variable = _typeVariable;
       typeArguments.add(variable);
       HInstruction readType = new HTypeInfoReadVariable.intercepted(
-          variable, interceptor, object, abstractValueDomain.dynamicType);
+          variable, interceptor, object, _abstractValueDomain.dynamicType);
       add(readType);
       inputs.add(readType);
     });
@@ -3773,41 +3987,45 @@
 
     Selector selector =
         new Selector.callClosure(0, const <String>[], typeArguments.length);
-    push(new HInvokeClosure(
-        selector, inputs, abstractValueDomain.dynamicType, typeArguments));
+    StaticType receiverStaticType =
+        _getStaticType(invocation.arguments.positional[1]);
+    AbstractValue receiverType = _abstractValueDomain.createFromStaticType(
+        receiverStaticType.type, receiverStaticType.relation);
+    push(new HInvokeClosure(selector, receiverType, inputs,
+        _abstractValueDomain.dynamicType, typeArguments));
 
     return true;
   }
 
-  void handleInvokeStaticForeign(
+  void _handleInvokeStaticForeign(
       ir.StaticInvocation invocation, MemberEntity member) {
     String name = member.name;
     if (name == 'JS') {
-      handleForeignJs(invocation);
+      _handleForeignJs(invocation);
     } else if (name == 'DART_CLOSURE_TO_JS') {
-      handleForeignDartClosureToJs(invocation, 'DART_CLOSURE_TO_JS');
+      _handleForeignDartClosureToJs(invocation, 'DART_CLOSURE_TO_JS');
     } else if (name == 'RAW_DART_FUNCTION_REF') {
-      handleForeignRawFunctionRef(invocation, 'RAW_DART_FUNCTION_REF');
+      _handleForeignRawFunctionRef(invocation, 'RAW_DART_FUNCTION_REF');
     } else if (name == 'JS_SET_STATIC_STATE') {
-      handleForeignJsSetStaticState(invocation);
+      _handleForeignJsSetStaticState(invocation);
     } else if (name == 'JS_GET_STATIC_STATE') {
-      handleForeignJsGetStaticState(invocation);
+      _handleForeignJsGetStaticState(invocation);
     } else if (name == 'JS_GET_NAME') {
-      handleForeignJsGetName(invocation);
+      _handleForeignJsGetName(invocation);
     } else if (name == 'JS_EMBEDDED_GLOBAL') {
-      handleForeignJsEmbeddedGlobal(invocation);
+      _handleForeignJsEmbeddedGlobal(invocation);
     } else if (name == 'JS_BUILTIN') {
-      handleForeignJsBuiltin(invocation);
+      _handleForeignJsBuiltin(invocation);
     } else if (name == 'JS_GET_FLAG') {
-      handleForeignJsGetFlag(invocation);
+      _handleForeignJsGetFlag(invocation);
     } else if (name == 'JS_EFFECT') {
       stack.add(graph.addConstantNull(closedWorld));
     } else if (name == 'JS_INTERCEPTOR_CONSTANT') {
-      handleJsInterceptorConstant(invocation);
+      _handleJsInterceptorConstant(invocation);
     } else if (name == 'getInterceptor') {
-      handleForeignGetInterceptor(invocation);
+      _handleForeignGetInterceptor(invocation);
     } else if (name == 'JS_STRING_CONCAT') {
-      handleJsStringConcat(invocation);
+      _handleJsStringConcat(invocation);
     } else if (name == '_createInvocationMirror') {
       _handleCreateInvocationMirror(invocation);
     } else {
@@ -3906,7 +4124,7 @@
         _sourceInformationBuilder.buildCall(invocation, invocation);
     _addTypeArguments(arguments, typeArguments, sourceInformation);
 
-    HInstruction argumentsInstruction = buildLiteralList(arguments);
+    HInstruction argumentsInstruction = _buildLiteralList(arguments);
     add(argumentsInstruction);
 
     List<HInstruction> argumentNames = <HInstruction>[];
@@ -3916,13 +4134,13 @@
           constant_system.createString(argumentName);
       argumentNames.add(graph.addConstant(argumentNameConstant, closedWorld));
     }
-    HInstruction argumentNamesInstruction = buildLiteralList(argumentNames);
+    HInstruction argumentNamesInstruction = _buildLiteralList(argumentNames);
     add(argumentNamesInstruction);
 
     HInstruction typeArgumentCount =
         graph.addConstantInt(typeArguments.length, closedWorld);
 
-    js.Name internalName = namer.invocationName(selector);
+    js.Name internalName = _namer.invocationName(selector);
 
     ConstantValue kindConstant =
         constant_system.createIntFromInt(selector.invocationMirrorKind);
@@ -3937,7 +4155,7 @@
           argumentNamesInstruction,
           typeArgumentCount,
         ],
-        abstractValueDomain.dynamicType,
+        _abstractValueDomain.dynamicType,
         const <DartType>[],
         sourceInformation: sourceInformation);
   }
@@ -4017,14 +4235,14 @@
     return stringConstant.stringValue;
   }
 
-  void handleForeignDartClosureToJs(
+  void _handleForeignDartClosureToJs(
       ir.StaticInvocation invocation, String name) {
     // TODO(sra): Do we need to wrap the closure in something that saves the
     // current isolate?
-    handleForeignRawFunctionRef(invocation, name);
+    _handleForeignRawFunctionRef(invocation, name);
   }
 
-  void handleForeignRawFunctionRef(
+  void _handleForeignRawFunctionRef(
       ir.StaticInvocation invocation, String name) {
     if (_unexpectedForeignArguments(invocation,
         minPositional: 1, maxPositional: 1)) {
@@ -4043,9 +4261,9 @@
               function.positionalParameters.length &&
           function.namedParameters.isEmpty) {
         push(new HForeignCode(
-            js.js.expressionTemplateYielding(
-                emitter.staticFunctionAccess(_elementMap.getMethod(procedure))),
-            abstractValueDomain.dynamicType,
+            js.js.expressionTemplateYielding(_emitter
+                .staticFunctionAccess(_elementMap.getMethod(procedure))),
+            _abstractValueDomain.dynamicType,
             <HInstruction>[],
             nativeBehavior: NativeBehavior.PURE,
             foreignFunction: _elementMap.getMethod(procedure)));
@@ -4080,7 +4298,7 @@
     return;
   }
 
-  void handleForeignJsSetStaticState(ir.StaticInvocation invocation) {
+  void _handleForeignJsSetStaticState(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation,
         minPositional: 1, maxPositional: 1)) {
       // Result expected on stack.
@@ -4090,15 +4308,15 @@
 
     List<HInstruction> inputs = _visitPositionalArguments(invocation.arguments);
 
-    String isolateName = namer.staticStateHolder;
+    String isolateName = _namer.staticStateHolder;
     SideEffects sideEffects = new SideEffects.empty();
     sideEffects.setAllSideEffects();
     push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"),
-        abstractValueDomain.dynamicType, inputs,
+        _abstractValueDomain.dynamicType, inputs,
         nativeBehavior: NativeBehavior.CHANGES_OTHER, effects: sideEffects));
   }
 
-  void handleForeignJsGetStaticState(ir.StaticInvocation invocation) {
+  void _handleForeignJsGetStaticState(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation,
         minPositional: 0, maxPositional: 0)) {
       // Result expected on stack.
@@ -4106,12 +4324,12 @@
       return;
     }
 
-    push(new HForeignCode(js.js.parseForeignJS(namer.staticStateHolder),
-        abstractValueDomain.dynamicType, <HInstruction>[],
+    push(new HForeignCode(js.js.parseForeignJS(_namer.staticStateHolder),
+        _abstractValueDomain.dynamicType, <HInstruction>[],
         nativeBehavior: NativeBehavior.DEPENDS_OTHER));
   }
 
-  void handleForeignJsGetName(ir.StaticInvocation invocation) {
+  void _handleForeignJsGetName(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation,
         minPositional: 1, maxPositional: 1)) {
       // Result expected on stack.
@@ -4124,8 +4342,7 @@
     HInstruction instruction = pop();
 
     if (instruction is HConstant) {
-      js.Name name =
-          _elementMap.getNameForJsGetName(instruction.constant, namer);
+      js.Name name = _getNameForJsGetName(instruction.constant, _namer);
       stack.add(graph.addConstantStringFromName(name, closedWorld));
       return;
     }
@@ -4138,7 +4355,30 @@
     stack.add(graph.addConstantNull(closedWorld));
   }
 
-  void handleForeignJsEmbeddedGlobal(ir.StaticInvocation invocation) {
+  int _extractEnumIndexFromConstantValue(
+      ConstantValue constant, ClassEntity classElement) {
+    if (constant is ConstructedConstantValue) {
+      if (constant.type.element == classElement) {
+        assert(constant.fields.length == 1 || constant.fields.length == 2);
+        ConstantValue indexConstant = constant.fields.values.first;
+        if (indexConstant is IntConstantValue) {
+          return indexConstant.intValue.toInt();
+        }
+      }
+    }
+    return null;
+  }
+
+  /// Returns the [js.Name] for the `JsGetName` [constant] value.
+  js.Name _getNameForJsGetName(ConstantValue constant, ModularNamer namer) {
+    int index = _extractEnumIndexFromConstantValue(
+        constant, _commonElements.jsGetNameEnum);
+    if (index == null) return null;
+    return namer.getNameForJsGetName(
+        CURRENT_ELEMENT_SPANNABLE, JsGetName.values[index]);
+  }
+
+  void _handleForeignJsEmbeddedGlobal(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation,
         minPositional: 2, maxPositional: 2)) {
       // Result expected on stack.
@@ -4148,7 +4388,7 @@
     String globalName = _foreignConstantStringArgument(
         invocation, 1, 'JS_EMBEDDED_GLOBAL', 'second ');
     js.Template expr = js.js.expressionTemplateYielding(
-        emitter.generateEmbeddedGlobalAccess(globalName));
+        _emitter.generateEmbeddedGlobalAccess(globalName));
 
     NativeBehavior nativeBehavior =
         _elementMap.getNativeBehaviorForJsEmbeddedGlobalCall(invocation);
@@ -4163,7 +4403,7 @@
         nativeBehavior: nativeBehavior));
   }
 
-  void handleForeignJsBuiltin(ir.StaticInvocation invocation) {
+  void _handleForeignJsBuiltin(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation, minPositional: 2)) {
       // Result expected on stack.
       stack.add(graph.addConstantNull(closedWorld));
@@ -4178,8 +4418,7 @@
 
     js.Template template;
     if (instruction is HConstant) {
-      template =
-          _elementMap.getJsBuiltinTemplate(instruction.constant, emitter);
+      template = _getJsBuiltinTemplate(instruction.constant, _emitter);
     }
     if (template == null) {
       reporter.reportErrorMessage(
@@ -4210,7 +4449,74 @@
         nativeBehavior: nativeBehavior));
   }
 
-  void handleForeignJsGetFlag(ir.StaticInvocation invocation) {
+  /// Returns the [js.Template] for the `JsBuiltin` [constant] value.
+  js.Template _getJsBuiltinTemplate(
+      ConstantValue constant, ModularEmitter emitter) {
+    int index = _extractEnumIndexFromConstantValue(
+        constant, _commonElements.jsBuiltinEnum);
+    if (index == null) return null;
+    return _templateForBuiltin(JsBuiltin.values[index]);
+  }
+
+  /// Returns the JS template for the given [builtin].
+  js.Template _templateForBuiltin(JsBuiltin builtin) {
+    switch (builtin) {
+      case JsBuiltin.dartObjectConstructor:
+        ClassEntity objectClass = closedWorld.commonElements.objectClass;
+        return js.js
+            .expressionTemplateYielding(_emitter.typeAccess(objectClass));
+
+      case JsBuiltin.isCheckPropertyToJsConstructorName:
+        int isPrefixLength = _namer.fixedNames.operatorIsPrefix.length;
+        return js.js.expressionTemplateFor('#.substring($isPrefixLength)');
+
+      case JsBuiltin.isFunctionType:
+        return _rtiEncoder.templateForIsFunctionType;
+
+      case JsBuiltin.isFutureOrType:
+        return _rtiEncoder.templateForIsFutureOrType;
+
+      case JsBuiltin.isVoidType:
+        return _rtiEncoder.templateForIsVoidType;
+
+      case JsBuiltin.isDynamicType:
+        return _rtiEncoder.templateForIsDynamicType;
+
+      case JsBuiltin.isJsInteropTypeArgument:
+        return _rtiEncoder.templateForIsJsInteropTypeArgument;
+
+      case JsBuiltin.rawRtiToJsConstructorName:
+        return js.js.expressionTemplateFor("#.name");
+
+      case JsBuiltin.rawRuntimeType:
+        return js.js.expressionTemplateFor("#.constructor");
+
+      case JsBuiltin.isSubtype:
+        // TODO(floitsch): move this closer to where is-check properties are
+        // built.
+        String isPrefix = _namer.fixedNames.operatorIsPrefix;
+        return js.js.expressionTemplateFor("('$isPrefix' + #) in #.prototype");
+
+      case JsBuiltin.isGivenTypeRti:
+        return js.js.expressionTemplateFor('#.name === #');
+
+      case JsBuiltin.getMetadata:
+        String metadataAccess =
+            _emitter.generateEmbeddedGlobalAccessString(METADATA);
+        return js.js.expressionTemplateFor("$metadataAccess[#]");
+
+      case JsBuiltin.getType:
+        String typesAccess = _emitter.generateEmbeddedGlobalAccessString(TYPES);
+        return js.js.expressionTemplateFor("$typesAccess[#]");
+
+      default:
+        reporter.internalError(
+            NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin");
+        return null;
+    }
+  }
+
+  void _handleForeignJsGetFlag(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation,
         minPositional: 1, maxPositional: 1)) {
       stack.add(
@@ -4219,7 +4525,7 @@
       return;
     }
     String name = _foreignConstantStringArgument(invocation, 0, 'JS_GET_FLAG');
-    bool value = getFlagValue(name);
+    bool value = _getFlagValue(name);
     if (value == null) {
       reporter.reportErrorMessage(
           _elementMap.getSpannable(targetElement, invocation),
@@ -4230,7 +4536,7 @@
     }
   }
 
-  void handleJsInterceptorConstant(ir.StaticInvocation invocation) {
+  void _handleJsInterceptorConstant(ir.StaticInvocation invocation) {
     // Single argument must be a TypeConstant which is converted into a
     // InterceptorConstant.
     if (_unexpectedForeignArguments(invocation,
@@ -4261,7 +4567,7 @@
     stack.add(graph.addConstantNull(closedWorld));
   }
 
-  void handleForeignGetInterceptor(ir.StaticInvocation invocation) {
+  void _handleForeignGetInterceptor(ir.StaticInvocation invocation) {
     // Single argument is the intercepted object.
     if (_unexpectedForeignArguments(invocation,
         minPositional: 1, maxPositional: 1)) {
@@ -4280,7 +4586,7 @@
     stack.add(instruction);
   }
 
-  void handleForeignJs(ir.StaticInvocation invocation) {
+  void _handleForeignJs(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation,
         minPositional: 2, maxPositional: null, typeArgumentCount: 1)) {
       // Result expected on stack.
@@ -4332,17 +4638,17 @@
     push(code);
 
     DartType type = _getDartTypeIfValid(invocation.arguments.types.single);
-    AbstractValue trustedMask = typeBuilder.trustTypeMask(type);
+    AbstractValue trustedMask = _typeBuilder.trustTypeMask(type);
 
     if (trustedMask != null) {
       // We only allow the type argument to narrow `dynamic`, which probably
       // comes from an unspecified return type in the NativeBehavior.
-      if (abstractValueDomain
+      if (_abstractValueDomain
           .containsAll(code.instructionType)
           .isPotentiallyTrue) {
         // Overwrite the type with the narrower type.
         code.instructionType = trustedMask;
-      } else if (abstractValueDomain
+      } else if (_abstractValueDomain
           .contains(trustedMask, code.instructionType)
           .isPotentiallyTrue) {
         // It is acceptable for the type parameter to be broader than the
@@ -4359,7 +4665,7 @@
     }
   }
 
-  void handleJsStringConcat(ir.StaticInvocation invocation) {
+  void _handleJsStringConcat(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation,
         minPositional: 2, maxPositional: 2)) {
       // Result expected on stack.
@@ -4368,7 +4674,7 @@
     }
     List<HInstruction> inputs = _visitPositionalArguments(invocation.arguments);
     push(new HStringConcat(
-        inputs[0], inputs[1], abstractValueDomain.stringType));
+        inputs[0], inputs[1], _abstractValueDomain.stringType));
   }
 
   void _pushStaticInvocation(MemberEntity target, List<HInstruction> arguments,
@@ -4387,25 +4693,32 @@
     } else {
       instruction = new HInvokeStatic(
           target, arguments, typeMask, typeArguments,
-          targetCanThrow: !inferredData.getCannotThrow(target))
+          targetCanThrow: !_inferredData.getCannotThrow(target))
         ..sourceInformation = sourceInformation;
 
-      if (currentImplicitInstantiations.isNotEmpty) {
+      if (_currentImplicitInstantiations.isNotEmpty) {
         instruction.instantiatedTypes =
-            new List<InterfaceType>.from(currentImplicitInstantiations);
+            new List<InterfaceType>.from(_currentImplicitInstantiations);
       }
-      instruction.sideEffects = inferredData.getSideEffectsOfElement(target);
+      instruction.sideEffects = _inferredData.getSideEffectsOfElement(target);
     }
     push(instruction);
   }
 
   void _pushDynamicInvocation(
       ir.Node node,
-      AbstractValue mask,
+      StaticType staticReceiverType,
+      AbstractValue receiverType,
       Selector selector,
       List<HInstruction> arguments,
       List<DartType> typeArguments,
       SourceInformation sourceInformation) {
+    AbstractValue typeBound = _abstractValueDomain.createFromStaticType(
+        staticReceiverType.type, staticReceiverType.relation);
+    receiverType = receiverType == null
+        ? typeBound
+        : _abstractValueDomain.intersection(receiverType, typeBound);
+
     // We prefer to not inline certain operations on indexables,
     // because the constant folder will handle them better and turn
     // them into simpler instructions that allow further
@@ -4415,10 +4728,10 @@
       bool isLength = selector.isGetter && selector.name == "length";
       if (isLength || selector.isIndex) {
         return closedWorld.classHierarchy.isSubtypeOf(
-            element.enclosingClass, commonElements.jsIndexableClass);
+            element.enclosingClass, _commonElements.jsIndexableClass);
       } else if (selector.isIndexSet) {
         return closedWorld.classHierarchy.isSubtypeOf(
-            element.enclosingClass, commonElements.jsMutableIndexableClass);
+            element.enclosingClass, _commonElements.jsMutableIndexableClass);
       } else {
         return false;
       }
@@ -4427,27 +4740,28 @@
     bool isOptimizableOperation(Selector selector, MemberEntity element) {
       ClassEntity cls = element.enclosingClass;
       if (isOptimizableOperationOnIndexable(selector, element)) return true;
-      if (!interceptorData.interceptedClasses.contains(cls)) return false;
+      if (!_interceptorData.interceptedClasses.contains(cls)) return false;
       if (selector.isOperator) return true;
       if (selector.isSetter) return true;
       if (selector.isIndex) return true;
       if (selector.isIndexSet) return true;
-      if (element == commonElements.jsArrayAdd ||
-          element == commonElements.jsArrayRemoveLast ||
-          commonElements.isJsStringSplit(element)) {
+      if (element == _commonElements.jsArrayAdd ||
+          element == _commonElements.jsArrayRemoveLast ||
+          _commonElements.isJsStringSplit(element)) {
         return true;
       }
       return false;
     }
 
-    MemberEntity element = closedWorld.locateSingleMember(selector, mask);
+    MemberEntity element =
+        closedWorld.locateSingleMember(selector, receiverType);
     if (element != null &&
         !element.isField &&
         !(element.isGetter && selector.isCall) &&
         !(element.isFunction && selector.isGetter) &&
         !isOptimizableOperation(selector, element)) {
-      if (_tryInlineMethod(element, selector, mask, arguments, typeArguments,
-          node, sourceInformation)) {
+      if (_tryInlineMethod(element, selector, receiverType, arguments,
+          typeArguments, node, sourceInformation)) {
         return;
       }
     }
@@ -4466,20 +4780,22 @@
     }
     inputs.addAll(arguments);
 
-    AbstractValue type = _typeInferenceMap.selectorTypeOf(selector, mask);
+    AbstractValue resultType =
+        _typeInferenceMap.resultTypeOfSelector(selector, receiverType);
     if (selector.isGetter) {
-      push(new HInvokeDynamicGetter(selector, mask, element, inputs,
-          isIntercepted, type, sourceInformation));
+      push(new HInvokeDynamicGetter(selector, receiverType, element, inputs,
+          isIntercepted, resultType, sourceInformation));
     } else if (selector.isSetter) {
-      push(new HInvokeDynamicSetter(selector, mask, element, inputs,
-          isIntercepted, type, sourceInformation));
+      push(new HInvokeDynamicSetter(selector, receiverType, element, inputs,
+          isIntercepted, resultType, sourceInformation));
     } else if (selector.isClosureCall) {
       assert(!isIntercepted);
-      push(new HInvokeClosure(selector, inputs, type, typeArguments)
+      push(new HInvokeClosure(
+          selector, receiverType, inputs, resultType, typeArguments)
         ..sourceInformation = sourceInformation);
     } else {
-      push(new HInvokeDynamicMethod(
-          selector, mask, inputs, type, typeArguments, sourceInformation,
+      push(new HInvokeDynamicMethod(selector, receiverType, inputs, resultType,
+          typeArguments, sourceInformation,
           isIntercepted: isIntercepted));
     }
   }
@@ -4487,11 +4803,11 @@
   HForeignCode _invokeJsInteropFunction(
       FunctionEntity element, List<HInstruction> arguments) {
     assert(closedWorld.nativeData.isJsInteropMember(element));
-    nativeEmitter.nativeMethods.add(element);
+    registry.registerNativeMethod(element);
 
     if (element is ConstructorEntity &&
         element.isFactoryConstructor &&
-        nativeData.isAnonymousJsInteropClass(element.enclosingClass)) {
+        _nativeData.isAnonymousJsInteropClass(element.enclosingClass)) {
       // Factory constructor that is syntactic sugar for creating a JavaScript
       // object literal.
       ConstructorEntity constructor = element;
@@ -4516,7 +4832,7 @@
         HInstruction argument = arguments[i];
         if (argument != null) {
           filteredArguments.add(argument);
-          var jsName = nativeData.computeUnescapedJSInteropName(parameterName);
+          var jsName = _nativeData.computeUnescapedJSInteropName(parameterName);
           parameterNameMap[jsName] = new js.InterpolatedExpression(positions++);
         }
         i++;
@@ -4526,20 +4842,21 @@
 
       var nativeBehavior = new NativeBehavior()..codeTemplate = codeTemplate;
       if (options.trustJSInteropTypeAnnotations) {
-        InterfaceType thisType = _elementMap.elementEnvironment
-            .getThisType(constructor.enclosingClass);
+        InterfaceType thisType =
+            _elementEnvironment.getThisType(constructor.enclosingClass);
         nativeBehavior.typesReturned.add(thisType);
       }
       // TODO(efortuna): Source information.
       return new HForeignCode(
-          codeTemplate, abstractValueDomain.dynamicType, filteredArguments,
+          codeTemplate, _abstractValueDomain.dynamicType, filteredArguments,
           nativeBehavior: nativeBehavior);
     }
 
     var target = new HForeignCode(
-        js.js.parseForeignJS("${nativeData.getFixedBackendMethodPath(element)}."
-            "${nativeData.getFixedBackendName(element)}"),
-        abstractValueDomain.dynamicType,
+        js.js
+            .parseForeignJS("${_nativeData.getFixedBackendMethodPath(element)}."
+                "${_nativeData.getFixedBackendName(element)}"),
+        _abstractValueDomain.dynamicType,
         <HInstruction>[]);
     add(target);
     // Strip off trailing arguments that were not specified.
@@ -4552,8 +4869,8 @@
     var nativeBehavior = new NativeBehavior()..sideEffects.setAllSideEffects();
 
     DartType type = element is ConstructorEntity
-        ? _elementMap.elementEnvironment.getThisType(element.enclosingClass)
-        : _elementMap.elementEnvironment.getFunctionType(element).returnType;
+        ? _elementEnvironment.getThisType(element.enclosingClass)
+        : _elementEnvironment.getFunctionType(element).returnType;
     // Native behavior effects here are similar to native/behavior.dart.
     // The return type is dynamic if we don't trust js-interop type
     // declarations.
@@ -4562,17 +4879,17 @@
 
     // The allocation effects include the declared type if it is native (which
     // includes js interop types).
-    if (type is InterfaceType && nativeData.isNativeClass(type.element)) {
+    if (type is InterfaceType && _nativeData.isNativeClass(type.element)) {
       nativeBehavior.typesInstantiated.add(type);
     }
 
     // It also includes any other JS interop type if we don't trust the
     // annotation or if is declared too broad.
     if (!options.trustJSInteropTypeAnnotations ||
-        type == commonElements.objectType ||
+        type == _commonElements.objectType ||
         type is DynamicType) {
-      nativeBehavior.typesInstantiated.add(_elementMap.elementEnvironment
-          .getThisType(commonElements.jsJavaScriptObjectClass));
+      nativeBehavior.typesInstantiated.add(_elementEnvironment
+          .getThisType(_commonElements.jsJavaScriptObjectClass));
     }
 
     String template;
@@ -4589,28 +4906,28 @@
 
     // TODO(efortuna): Add source information.
     return new HForeignCode(
-        codeTemplate, abstractValueDomain.dynamicType, inputs,
+        codeTemplate, _abstractValueDomain.dynamicType, inputs,
         nativeBehavior: nativeBehavior);
   }
 
   @override
-  visitFunctionNode(ir.FunctionNode node) {
+  void visitFunctionNode(ir.FunctionNode node) {
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildCreate(node);
     ClosureRepresentationInfo closureInfo =
-        closureDataLookup.getClosureInfo(node.parent);
+        _closureDataLookup.getClosureInfo(node.parent);
     ClassEntity closureClassEntity = closureInfo.closureClassEntity;
 
     List<HInstruction> capturedVariables = <HInstruction>[];
-    _worldBuilder.forEachInstanceField(closureClassEntity,
-        (_, FieldEntity field, {bool isElided}) {
-      if (isElided) return;
+    _elementEnvironment.forEachInstanceField(closureClassEntity,
+        (_, FieldEntity field) {
+      if (_fieldAnalysis.getFieldData(field).isElided) return;
       capturedVariables
           .add(localsHandler.readLocal(closureInfo.getLocalForField(field)));
     });
 
     AbstractValue type =
-        abstractValueDomain.createNonNullExact(closureClassEntity);
+        _abstractValueDomain.createNonNullExact(closureClassEntity);
     // TODO(efortuna): Add source information here.
     push(new HCreate(
         closureClassEntity, capturedVariables, type, sourceInformation,
@@ -4618,10 +4935,10 @@
   }
 
   @override
-  visitFunctionDeclaration(ir.FunctionDeclaration declaration) {
-    assert(isReachable);
+  void visitFunctionDeclaration(ir.FunctionDeclaration declaration) {
+    assert(_isReachable);
     declaration.function.accept(this);
-    Local local = localsMap.getLocalVariable(declaration.variable);
+    Local local = _localsMap.getLocalVariable(declaration.variable);
     localsHandler.updateLocal(local, pop());
   }
 
@@ -4635,20 +4952,20 @@
     var arguments = <HInstruction>[];
     node.expression.accept(this);
     arguments.add(pop());
-    // TODO(johnniwinther): Use the static type of the expression.
-    bool typeArgumentsNeeded = rtiNeed.instantiationNeedsTypeArguments(
-        null, node.typeArguments.length);
+    StaticType expressionType = _getStaticType(node.expression);
+    bool typeArgumentsNeeded = _rtiNeed.instantiationNeedsTypeArguments(
+        expressionType.type, node.typeArguments.length);
     List<DartType> typeArguments = node.typeArguments
         .map((type) => typeArgumentsNeeded
             ? _elementMap.getDartType(type)
             : _commonElements.dynamicType)
         .toList();
     registry.registerGenericInstantiation(
-        new GenericInstantiation(null, typeArguments));
+        new GenericInstantiation(expressionType.type, typeArguments));
     // TODO(johnniwinther): Can we avoid creating the instantiation object?
     for (DartType type in typeArguments) {
       HInstruction instruction =
-          typeBuilder.analyzeTypeArgument(type, sourceElement);
+          _typeBuilder.analyzeTypeArgument(type, sourceElement);
       arguments.add(instruction);
     }
     int typeArgumentCount = node.typeArguments.length;
@@ -4664,7 +4981,7 @@
       return;
     }
     HInstruction instruction = new HInvokeStatic(
-        target, arguments, abstractValueDomain.functionType, <DartType>[],
+        target, arguments, _abstractValueDomain.functionType, <DartType>[],
         targetCanThrow: targetCanThrow);
     // TODO(sra): ..sourceInformation = sourceInformation
     instruction.sideEffects
@@ -4684,7 +5001,8 @@
         _fillDynamicTypeArguments(selector, node.arguments, typeArguments);
     _pushDynamicInvocation(
         node,
-        _typeInferenceMap.receiverTypeOfInvocation(node, abstractValueDomain),
+        _getStaticType(node.receiver),
+        _typeInferenceMap.receiverTypeOfInvocation(node, _abstractValueDomain),
         selector,
         <HInstruction>[receiver]..addAll(_visitArgumentsForDynamicTarget(
             selector, node.arguments, typeArguments)),
@@ -4695,7 +5013,7 @@
   HInterceptor _interceptorFor(
       HInstruction intercepted, SourceInformation sourceInformation) {
     HInterceptor interceptor =
-        new HInterceptor(intercepted, abstractValueDomain.nonNullType)
+        new HInterceptor(intercepted, _abstractValueDomain.nonNullType)
           ..sourceInformation = sourceInformation;
     add(interceptor);
     return interceptor;
@@ -4723,9 +5041,9 @@
 
     ConstantValue nameConstant = constant_system.createString(publicName);
 
-    js.Name internalName = namer.invocationName(selector);
+    js.Name internalName = _namer.invocationName(selector);
 
-    var argumentsInstruction = buildLiteralList(arguments);
+    var argumentsInstruction = _buildLiteralList(arguments);
     add(argumentsInstruction);
 
     var argumentNames = new List<HInstruction>();
@@ -4734,7 +5052,7 @@
           constant_system.createString(argumentName);
       argumentNames.add(graph.addConstant(argumentNameConstant, closedWorld));
     }
-    var argumentNamesInstruction = buildLiteralList(argumentNames);
+    var argumentNamesInstruction = _buildLiteralList(argumentNames);
     add(argumentNamesInstruction);
 
     ConstantValue kindConstant =
@@ -4750,7 +5068,7 @@
           argumentNamesInstruction,
           graph.addConstantInt(typeArguments.length, closedWorld),
         ],
-        abstractValueDomain.dynamicType,
+        _abstractValueDomain.dynamicType,
         typeArguments,
         sourceInformation: sourceInformation);
 
@@ -4781,7 +5099,7 @@
     if (target is FunctionEntity) {
       typeMask = _typeInferenceMap.getReturnTypeOf(target);
     } else {
-      typeMask = abstractValueDomain.dynamicType;
+      typeMask = _abstractValueDomain.dynamicType;
     }
     HInstruction instruction = new HInvokeSuper(
         target,
@@ -4794,7 +5112,7 @@
         sourceInformation,
         isSetter: selector.isSetter || selector.isIndexSet);
     instruction.sideEffects =
-        inferredData.getSideEffectsOfSelector(selector, null);
+        _inferredData.getSideEffectsOfSelector(selector, null);
     push(instruction);
     return instruction;
   }
@@ -4868,14 +5186,14 @@
 
   void _assertIsType(HInstruction subtypeInstruction, DartType supertype,
       String prefix, String infix, String suffix) {
-    HInstruction supertypeInstruction = typeBuilder.analyzeTypeArgument(
+    HInstruction supertypeInstruction = _typeBuilder.analyzeTypeArgument(
         localsHandler.substInContext(supertype), sourceElement);
     HInstruction prefixInstruction =
         graph.addConstantString(prefix, closedWorld);
     HInstruction infixInstruction = graph.addConstantString(infix, closedWorld);
     HInstruction suffixInstruction =
         graph.addConstantString(suffix, closedWorld);
-    FunctionEntity element = commonElements.assertIsSubtype;
+    FunctionEntity element = _commonElements.assertIsSubtype;
     var inputs = <HInstruction>[
       subtypeInstruction,
       supertypeInstruction,
@@ -4902,15 +5220,15 @@
 
     ConstructorEntity constructor = _elementMap.getConstructor(target);
     ClassEntity cls = constructor.enclosingClass;
-    AbstractValue typeMask = abstractValueDomain.createNonNullExact(cls);
+    AbstractValue typeMask = _abstractValueDomain.createNonNullExact(cls);
     InterfaceType instanceType = _elementMap.createInterfaceType(
         target.enclosingClass, node.arguments.types);
     instanceType = localsHandler.substInContext(instanceType);
 
     List<HInstruction> arguments = <HInstruction>[];
     if (constructor.isGenerativeConstructor &&
-        nativeData.isNativeOrExtendsNative(constructor.enclosingClass) &&
-        !nativeData.isJsInteropMember(constructor)) {
+        _nativeData.isNativeOrExtendsNative(constructor.enclosingClass) &&
+        !_nativeData.isJsInteropMember(constructor)) {
       // Native class generative constructors take a pre-constructed object.
       arguments.add(graph.addConstantNull(closedWorld));
     }
@@ -4924,27 +5242,27 @@
             node.arguments,
             typeArguments,
             sourceInformation));
-    if (commonElements.isSymbolConstructor(constructor)) {
-      constructor = commonElements.symbolValidatedConstructor;
+    if (_commonElements.isSymbolConstructor(constructor)) {
+      constructor = _commonElements.symbolValidatedConstructor;
     }
     // TODO(johnniwinther): Remove this when type arguments are passed to
     // constructors like calling a generic method.
     _addTypeArguments(arguments, _getClassTypeArguments(cls, node.arguments),
         sourceInformation);
-    addImplicitInstantiation(instanceType);
+    _addImplicitInstantiation(instanceType);
     _pushStaticInvocation(constructor, arguments, typeMask, typeArguments,
         sourceInformation: sourceInformation, instanceType: instanceType);
-    removeImplicitInstantiation(instanceType);
+    _removeImplicitInstantiation(instanceType);
   }
 
   @override
   void visitIsExpression(ir.IsExpression node) {
     node.operand.accept(this);
     HInstruction expression = pop();
-    pushIsTest(node.type, expression, _sourceInformationBuilder.buildIs(node));
+    _pushIsTest(node.type, expression, _sourceInformationBuilder.buildIs(node));
   }
 
-  void pushIsTest(ir.DartType type, HInstruction expression,
+  void _pushIsTest(ir.DartType type, HInstruction expression,
       SourceInformation sourceInformation) {
     // Note: The call to "unalias" this type like in the original SSA builder is
     // unnecessary in kernel because Kernel has no notion of typedef.
@@ -4952,7 +5270,7 @@
 
     if (type is ir.InvalidType) {
       // TODO(sra): Make InvalidType carry a message.
-      generateTypeError('invalid type', sourceInformation);
+      _generateTypeError('invalid type', sourceInformation);
       pop();
       stack.add(graph.addConstantBool(true, closedWorld));
       return;
@@ -4968,63 +5286,63 @@
 
     if (typeValue is FunctionType) {
       HInstruction representation =
-          typeBuilder.analyzeTypeArgument(typeValue, sourceElement);
+          _typeBuilder.analyzeTypeArgument(typeValue, sourceElement);
       List<HInstruction> inputs = <HInstruction>[
         expression,
         representation,
       ];
       _pushStaticInvocation(_commonElements.functionTypeTest, inputs,
-          abstractValueDomain.boolType, const <DartType>[],
+          _abstractValueDomain.boolType, const <DartType>[],
           sourceInformation: sourceInformation);
       HInstruction call = pop();
       push(new HIs.compound(typeValue, expression, call,
-          abstractValueDomain.boolType, sourceInformation));
+          _abstractValueDomain.boolType, sourceInformation));
       return;
     }
 
     if (typeValue is FutureOrType) {
       HInstruction representation =
-          typeBuilder.analyzeTypeArgument(typeValue, sourceElement);
+          _typeBuilder.analyzeTypeArgument(typeValue, sourceElement);
       List<HInstruction> inputs = <HInstruction>[
         expression,
         representation,
       ];
       _pushStaticInvocation(_commonElements.futureOrTest, inputs,
-          abstractValueDomain.boolType, const <DartType>[],
+          _abstractValueDomain.boolType, const <DartType>[],
           sourceInformation: sourceInformation);
       HInstruction call = pop();
       push(new HIs.compound(typeValue, expression, call,
-          abstractValueDomain.boolType, sourceInformation));
+          _abstractValueDomain.boolType, sourceInformation));
       return;
     }
 
     if (typeValue is TypeVariableType) {
       HInstruction runtimeType =
-          typeBuilder.addTypeVariableReference(typeValue, sourceElement);
+          _typeBuilder.addTypeVariableReference(typeValue, sourceElement);
       _pushStaticInvocation(
           _commonElements.checkSubtypeOfRuntimeType,
           <HInstruction>[expression, runtimeType],
-          abstractValueDomain.boolType,
+          _abstractValueDomain.boolType,
           const <DartType>[],
           sourceInformation: sourceInformation);
       push(new HIs.variable(typeValue, expression, pop(),
-          abstractValueDomain.boolType, sourceInformation));
+          _abstractValueDomain.boolType, sourceInformation));
       return;
     }
 
     if (typeValue is InterfaceType && !_canIgnoreTypeArguments(typeValue)) {
-      HInstruction representations = typeBuilder
+      HInstruction representations = _typeBuilder
           .buildTypeArgumentRepresentations(typeValue, sourceElement);
       add(representations);
       ClassEntity element = typeValue.element;
-      js.Name operator = namer.operatorIs(element);
+      js.Name operator = _namer.operatorIs(element);
       HInstruction isFieldName =
           graph.addConstantStringFromName(operator, closedWorld);
       HInstruction asFieldName =
           closedWorld.classHierarchy.hasAnyStrictSubtype(element) ||
                   closedWorld.nativeData.isJsInteropClass(element)
               ? graph.addConstantStringFromName(
-                  namer.substitutionName(element), closedWorld)
+                  _namer.substitutionName(element), closedWorld)
               : graph.addConstantNull(closedWorld);
       List<HInstruction> inputs = <HInstruction>[
         expression,
@@ -5033,15 +5351,15 @@
         asFieldName
       ];
       _pushStaticInvocation(_commonElements.checkSubtype, inputs,
-          abstractValueDomain.boolType, const <DartType>[],
+          _abstractValueDomain.boolType, const <DartType>[],
           sourceInformation: sourceInformation);
       push(new HIs.compound(typeValue, expression, pop(),
-          abstractValueDomain.boolType, sourceInformation));
+          _abstractValueDomain.boolType, sourceInformation));
       return;
     }
 
-    if (backend.hasDirectCheckFor(closedWorld.commonElements, typeValue)) {
-      push(new HIs.direct(typeValue, expression, abstractValueDomain.boolType,
+    if (_hasDirectCheckFor(typeValue)) {
+      push(new HIs.direct(typeValue, expression, _abstractValueDomain.boolType,
           sourceInformation));
       return;
     }
@@ -5051,24 +5369,41 @@
         typeValue,
         expression,
         _interceptorFor(expression, sourceInformation),
-        abstractValueDomain.boolType,
+        _abstractValueDomain.boolType,
         sourceInformation));
     return;
   }
 
+  /// Returns `true` if the checking of [type] is performed directly on the
+  /// object and not on an interceptor.
+  bool _hasDirectCheckFor(DartType type) {
+    if (!type.isInterfaceType) return false;
+    InterfaceType interfaceType = type;
+    ClassEntity element = interfaceType.element;
+    return element == _commonElements.stringClass ||
+        element == _commonElements.boolClass ||
+        element == _commonElements.numClass ||
+        element == _commonElements.intClass ||
+        element == _commonElements.doubleClass ||
+        element == _commonElements.jsArrayClass ||
+        element == _commonElements.jsMutableArrayClass ||
+        element == _commonElements.jsExtendableArrayClass ||
+        element == _commonElements.jsFixedArrayClass ||
+        element == _commonElements.jsUnmodifiableArrayClass;
+  }
+
   /// Whether an is-check for [type] can be done ignoring type-arguments.
   /// This will be true if [type] is raw, or all its type-arguments match the
   /// type-parameter bounds.
   bool _canIgnoreTypeArguments(InterfaceType type) {
-    InterfaceType thisType =
-        _elementMap.elementEnvironment.getThisType(type.element);
+    InterfaceType thisType = _elementEnvironment.getThisType(type.element);
     List<DartType> bounds = thisType.typeArguments;
     for (int i = 0; i < bounds.length; i++) {
       DartType arg = type.typeArguments[i];
       if (arg.treatAsDynamic) continue;
       TypeVariableType typeVariable = bounds[i];
-      DartType bound = _elementMap.elementEnvironment
-          .getTypeVariableBound(typeVariable.element);
+      DartType bound =
+          _elementEnvironment.getTypeVariableBound(typeVariable.element);
       if (bound != arg) return false;
     }
     return true;
@@ -5077,12 +5412,13 @@
   @override
   void visitThrow(ir.Throw node) {
     _visitThrowExpression(node.expression);
-    if (isReachable) {
+    if (_isReachable) {
       SourceInformation sourceInformation =
           _sourceInformationBuilder.buildThrow(node);
-      handleInTryStatement();
-      push(new HThrowExpression(abstractValueDomain, pop(), sourceInformation));
-      isReachable = false;
+      _handleInTryStatement();
+      push(
+          new HThrowExpression(_abstractValueDomain, pop(), sourceInformation));
+      _isReachable = false;
     }
   }
 
@@ -5099,7 +5435,7 @@
   @override
   void visitYieldStatement(ir.YieldStatement node) {
     node.expression.accept(this);
-    add(new HYield(abstractValueDomain, pop(), node.isYieldStar,
+    add(new HYield(_abstractValueDomain, pop(), node.isYieldStar,
         _sourceInformationBuilder.buildYield(node)));
   }
 
@@ -5108,23 +5444,23 @@
     node.operand.accept(this);
     HInstruction awaited = pop();
     // TODO(herhut): Improve this type.
-    push(new HAwait(awaited, abstractValueDomain.dynamicType)
+    push(new HAwait(awaited, _abstractValueDomain.dynamicType)
       ..sourceInformation = _sourceInformationBuilder.buildAwait(node));
   }
 
   @override
   void visitRethrow(ir.Rethrow node) {
-    HInstruction exception = rethrowableException;
+    HInstruction exception = _rethrowableException;
     if (exception == null) {
       exception = graph.addConstantNull(closedWorld);
       reporter.internalError(_elementMap.getSpannable(targetElement, node),
           'rethrowableException should not be null.');
     }
-    handleInTryStatement();
+    _handleInTryStatement();
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildThrow(node);
-    closeAndGotoExit(new HThrow(
-        abstractValueDomain, exception, sourceInformation,
+    _closeAndGotoExit(new HThrow(
+        _abstractValueDomain, exception, sourceInformation,
         isRethrow: true));
     // ir.Rethrow is an expression so we need to push a value - a constant with
     // no type.
@@ -5140,7 +5476,7 @@
   @override
   void visitNot(ir.Not node) {
     node.operand.accept(this);
-    push(new HNot(popBoolified(), abstractValueDomain.boolType)
+    push(new HNot(popBoolified(), _abstractValueDomain.boolType)
       ..sourceInformation = _sourceInformationBuilder.buildUnary(node));
   }
 
@@ -5211,20 +5547,19 @@
       return false;
     }
 
-    if (nativeData.isJsInteropMember(function) &&
+    if (_nativeData.isJsInteropMember(function) &&
         !(function is ConstructorEntity && function.isFactoryConstructor)) {
       // We only inline factory JavaScript interop constructors.
       return false;
     }
 
-    if (compiler.elementHasCompileTimeError(function)) return false;
-
     bool insideLoop = loopDepth > 0 || graph.calledInLoop;
 
     // Bail out early if the inlining decision is in the cache and we can't
     // inline (no need to check the hard constraints).
+    if (_inlineCache.markedAsNoInline(function)) return false;
     bool cachedCanBeInlined =
-        inlineCache.canInline(function, insideLoop: insideLoop);
+        _inlineCache.canInline(function, insideLoop: insideLoop);
     if (cachedCanBeInlined == false) return false;
 
     bool meetsHardConstraints() {
@@ -5240,20 +5575,20 @@
       if (selector != null) {
         if (!selector.applies(function)) return false;
         if (mask != null &&
-            abstractValueDomain
+            _abstractValueDomain
                 .isTargetingMember(mask, function, selector.memberName)
                 .isDefinitelyFalse) {
           return false;
         }
       }
 
-      if (nativeData.isJsInteropMember(function)) return false;
+      if (_nativeData.isJsInteropMember(function)) return false;
 
       // Don't inline operator== methods if the parameter can be null.
       if (function.name == '==') {
-        if (function.enclosingClass != commonElements.objectClass &&
+        if (function.enclosingClass != _commonElements.objectClass &&
             providedArguments[1]
-                .isNull(abstractValueDomain)
+                .isNull(_abstractValueDomain)
                 .isPotentiallyTrue) {
           return false;
         }
@@ -5263,7 +5598,7 @@
       // and have an extra argument that causes problems with inlining.
       if (function is ConstructorEntity &&
           function.isGenerativeConstructor &&
-          nativeData.isNativeOrExtendsNative(function.enclosingClass)) {
+          _nativeData.isNativeOrExtendsNative(function.enclosingClass)) {
         return false;
       }
 
@@ -5275,7 +5610,7 @@
           // since we are _not_ going to inline [function]. This has
           // implications in switch cases where we might need to insert a
           // `break` that was skipped due to `isReachable` being `false`.
-          isReachable = false;
+          _isReachable = false;
           return false;
         }
       }
@@ -5283,26 +5618,22 @@
       return true;
     }
 
-    bool doesNotContainCode() {
+    bool doesNotContainCode(InlineData inlineData) {
       // A function with size 1 does not contain any code.
-      return InlineWeeder.canBeInlined(_elementMap, function, 1,
-          enableUserAssertions: options.enableUserAssertions);
+      return inlineData.canBeInlined(maxInliningNodes: 1);
     }
 
-    bool reductiveHeuristic() {
+    bool reductiveHeuristic(InlineData inlineData) {
       // The call is on a path which is executed rarely, so inline only if it
       // does not make the program larger.
       if (_isCalledOnce(function)) {
-        return InlineWeeder.canBeInlined(_elementMap, function, null,
-            enableUserAssertions: options.enableUserAssertions);
+        return inlineData.canBeInlined();
       }
-      if (InlineReductiveWeeder.canBeInlined(
-          _elementMap, function, providedArguments.length,
-          enableUserAssertions: options.enableUserAssertions,
-          omitImplicitCasts: options.omitImplicitChecks)) {
+      if (inlineData.canBeInlinedReductive(
+          argumentCount: providedArguments.length)) {
         return true;
       }
-      return doesNotContainCode();
+      return doesNotContainCode(inlineData);
     }
 
     bool heuristicSayGoodToGo() {
@@ -5314,15 +5645,18 @@
       // Don't inline across deferred import to prevent leaking code. The only
       // exception is an empty function (which does not contain code).
       bool hasOnlyNonDeferredImportPaths = closedWorld.outputUnitData
-          .hasOnlyNonDeferredImportPaths(compiler.currentElement, function);
+          .hasOnlyNonDeferredImportPaths(_initialTargetElement, function);
+
+      InlineData inlineData =
+          _inlineDataCache.getInlineData(_elementMap, function);
 
       if (!hasOnlyNonDeferredImportPaths) {
-        return doesNotContainCode();
+        return doesNotContainCode(inlineData);
       }
 
       // Do not inline code that is rarely executed unless it reduces size.
       if (_inExpressionOfThrow || _inLazyInitializerExpression) {
-        return reductiveHeuristic();
+        return reductiveHeuristic(inlineData);
       }
 
       if (cachedCanBeInlined == true) {
@@ -5330,10 +5664,7 @@
         // if we can inline this method regardless of size.
         String reason;
         assert(
-            (reason = InlineWeeder.cannotBeInlinedReason(
-                    _elementMap, function, null,
-                    allowLoops: true,
-                    enableUserAssertions: options.enableUserAssertions)) ==
+            (reason = inlineData.cannotBeInlinedReason(allowLoops: true)) ==
                 null,
             failedAt(function, "Cannot inline $function: $reason"));
         return true;
@@ -5349,7 +5680,7 @@
             InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters;
       }
 
-      bool markedTryInline = inlineCache.markedAsTryInline(function);
+      bool markedTryInline = _inlineCache.markedAsTryInline(function);
       bool calledOnce = _isCalledOnce(function);
       // If a method is called only once, and all the methods in the inlining
       // stack are called only once as well, we know we will save on output size
@@ -5362,26 +5693,29 @@
         allowLoops = true;
       }
 
-      bool canInline = InlineWeeder.canBeInlined(
-          _elementMap, function, maxInliningNodes,
-          allowLoops: allowLoops,
-          enableUserAssertions: options.enableUserAssertions);
+      bool canInline = inlineData.canBeInlined(
+          maxInliningNodes: maxInliningNodes, allowLoops: allowLoops);
       if (markedTryInline) {
         if (canInline) {
-          inlineCache.markAsInlinable(function, insideLoop: true);
-          inlineCache.markAsInlinable(function, insideLoop: false);
+          _inlineCache.markAsInlinable(function, insideLoop: true);
+          _inlineCache.markAsInlinable(function, insideLoop: false);
         } else {
-          inlineCache.markAsNonInlinable(function, insideLoop: true);
-          inlineCache.markAsNonInlinable(function, insideLoop: false);
+          _inlineCache.markAsNonInlinable(function, insideLoop: true);
+          _inlineCache.markAsNonInlinable(function, insideLoop: false);
         }
       } else if (calledOnce) {
         // TODO(34203): We can't update the decision due to imprecision in the
         // calledOnce data, described in Issue 34203.
       } else {
         if (canInline) {
-          inlineCache.markAsInlinable(function, insideLoop: insideLoop);
+          _inlineCache.markAsInlinable(function, insideLoop: insideLoop);
         } else {
-          inlineCache.markAsNonInlinable(function, insideLoop: insideLoop);
+          if (_isFunctionCalledOnce(function)) {
+            // TODO(34203): We can't update the decision due to imprecision in
+            // the calledOnce data, described in Issue 34203.
+          } else {
+            _inlineCache.markAsNonInlinable(function, insideLoop: insideLoop);
+          }
         }
       }
       return canInline;
@@ -5404,16 +5738,16 @@
       if (function.isInstanceMember &&
           function is! ConstructorBodyEntity &&
           (mask == null ||
-              abstractValueDomain.isNull(mask).isPotentiallyTrue)) {
+              _abstractValueDomain.isNull(mask).isPotentiallyTrue)) {
         add(new HFieldGet(null, providedArguments[0],
-            abstractValueDomain.dynamicType, sourceInformation,
+            _abstractValueDomain.dynamicType, sourceInformation,
             isAssignable: false));
       }
       List<HInstruction> compiledArguments = _completeCallArgumentsList(
           function, selector, providedArguments, currentNode);
       _enterInlinedMethod(function, compiledArguments, instanceType);
-      inlinedFrom(function, sourceInformation, () {
-        if (!isReachable) {
+      _inlinedFrom(function, sourceInformation, () {
+        if (!_isReachable) {
           _emitReturn(graph.addConstantNull(closedWorld), sourceInformation);
         } else {
           _doInline(function);
@@ -5497,7 +5831,7 @@
     int positionalArgumentIndex = 0;
     int namedArgumentIndex = 0;
 
-    _worldBuilder.forEachParameter(function,
+    _elementEnvironment.forEachParameter(function,
         (DartType type, String name, ConstantValue defaultValue) {
       if (positionalArgumentIndex < parameterStructure.positionalParameters) {
         if (positionalArgumentIndex < callStructure.positionalArgumentCount) {
@@ -5534,7 +5868,7 @@
         }
       }
     });
-    if (rtiNeed.methodNeedsTypeArguments(function)) {
+    if (_rtiNeed.methodNeedsTypeArguments(function)) {
       if (callStructure.typeArgumentCount ==
           parameterStructure.typeParameters) {
         /// Offset of type arguments in [providedArguments].
@@ -5549,8 +5883,8 @@
       } else {
         assert(callStructure.typeArgumentCount == 0);
         // Pass type variable bounds as type arguments.
-        for (TypeVariableType typeVariable in _elementMap.elementEnvironment
-            .getFunctionTypeVariables(function)) {
+        for (TypeVariableType typeVariable
+            in _elementEnvironment.getFunctionTypeVariables(function)) {
           compiledArguments[compiledArgumentIndex++] =
               _computeTypeArgumentDefaultValue(function, typeVariable);
         }
@@ -5561,15 +5895,15 @@
 
   HInstruction _computeTypeArgumentDefaultValue(
       FunctionEntity function, TypeVariableType typeVariable) {
-    DartType bound = _elementMap.elementEnvironment
-        .getTypeVariableDefaultType(typeVariable.element);
+    DartType bound =
+        _elementEnvironment.getTypeVariableDefaultType(typeVariable.element);
     if (bound.containsTypeVariables) {
       // TODO(33422): Support type variables in default
       // types. Temporarily using the "any" type (encoded as -2) to
       // avoid failing on bounds checks.
       return graph.addConstantInt(-2, closedWorld);
     } else {
-      return typeBuilder.analyzeTypeArgument(bound, function);
+      return _typeBuilder.analyzeTypeArgument(bound, function);
     }
   }
 
@@ -5583,7 +5917,7 @@
         _returnType,
         stack,
         localsHandler,
-        inTryStatement,
+        _inTryStatement,
         _isCalledOnce(function));
     _inliningStack.add(state);
 
@@ -5597,7 +5931,7 @@
   /// [function]. The arguments of the function are inserted into the
   /// [localsHandler].
   ///
-  /// When inlining a function, [:return:] statements are not emitted as
+  /// When inlining a function, `return` statements are not emitted as
   /// [HReturn] instructions. Instead, the value of a synthetic element is
   /// updated in the [localsHandler]. This function creates such an element and
   /// stores it in the [_returnLocal] field.
@@ -5608,17 +5942,17 @@
         function,
         function,
         instanceType ?? _elementMap.getMemberThisType(function),
-        nativeData,
-        interceptorData);
-    localsHandler.scopeInfo = closureDataLookup.getScopeInfo(function);
+        _nativeData,
+        _interceptorData);
+    localsHandler.scopeInfo = _closureDataLookup.getScopeInfo(function);
 
-    CapturedScope scopeData = closureDataLookup.getCapturedScope(function);
+    CapturedScope scopeData = _closureDataLookup.getCapturedScope(function);
     bool forGenerativeConstructorBody = function is ConstructorBodyEntity;
 
     _returnLocal = new SyntheticLocal("result", function, function);
     localsHandler.updateLocal(_returnLocal, graph.addConstantNull(closedWorld));
 
-    inTryStatement = false; // TODO(lry): why? Document.
+    _inTryStatement = false; // TODO(lry): why? Document.
 
     int argumentIndex = 0;
     if (function.isInstanceMember) {
@@ -5658,9 +5992,8 @@
 
     ClassEntity enclosing = function.enclosingClass;
     if ((function.isConstructor || function is ConstructorBodyEntity) &&
-        rtiNeed.classNeedsTypeArguments(enclosing)) {
-      InterfaceType thisType =
-          _elementMap.elementEnvironment.getThisType(enclosing);
+        _rtiNeed.classNeedsTypeArguments(enclosing)) {
+      InterfaceType thisType = _elementEnvironment.getThisType(enclosing);
       thisType.typeArguments.forEach((_typeVariable) {
         TypeVariableType typeVariable = _typeVariable;
         HInstruction argument = compiledArguments[argumentIndex++];
@@ -5668,11 +6001,11 @@
             localsHandler.getTypeVariableAsLocal(typeVariable), argument);
       });
     }
-    if (rtiNeed.methodNeedsTypeArguments(function)) {
+    if (_rtiNeed.methodNeedsTypeArguments(function)) {
       bool inlineTypeParameters =
           function.parameterStructure.typeParameters == 0;
-      for (TypeVariableType typeVariable in _elementMap.elementEnvironment
-          .getFunctionTypeVariables(function)) {
+      for (TypeVariableType typeVariable
+          in _elementEnvironment.getFunctionTypeVariables(function)) {
         HInstruction argument;
         if (inlineTypeParameters) {
           // Add inlined type parameters.
@@ -5686,7 +6019,7 @@
     }
     assert(
         argumentIndex == compiledArguments.length ||
-            !rtiNeed.methodNeedsTypeArguments(function) &&
+            !_rtiNeed.methodNeedsTypeArguments(function) &&
                 compiledArguments.length - argumentIndex ==
                     function.parameterStructure.typeParameters,
         failedAt(
@@ -5695,8 +6028,7 @@
             "arguments have been read from: ${compiledArguments} passed to "
             "$function."));
 
-    _returnType =
-        _elementMap.elementEnvironment.getFunctionType(function).returnType;
+    _returnType = _elementEnvironment.getFunctionType(function).returnType;
     stack = <HInstruction>[];
 
     _insertCoverageCall(function);
@@ -5712,14 +6044,14 @@
   void _restoreState(KernelInliningState state) {
     localsHandler = state.oldLocalsHandler;
     _returnLocal = state.oldReturnLocal;
-    inTryStatement = state.inTryStatement;
+    _inTryStatement = state.inTryStatement;
     _returnType = state.oldReturnType;
     assert(stack.isEmpty);
     stack = state.oldStack;
   }
 
   bool _providedArgumentsKnownToBeComplete(ir.Node currentNode) {
-    /* When inlining the iterator methods generated for a [:for-in:] loop, the
+    /* When inlining the iterator methods generated for a for-in loop, the
      * [currentNode] is the [ForIn] tree. The compiler-generated iterator
      * invocations are known to have fully specified argument lists, no default
      * arguments are used. See invocations of [pushInvokeDynamic] in
@@ -5731,8 +6063,8 @@
 
   void _emitReturn(HInstruction value, SourceInformation sourceInformation) {
     if (_inliningStack.isEmpty) {
-      closeAndGotoExit(
-          new HReturn(abstractValueDomain, value, sourceInformation));
+      _closeAndGotoExit(
+          new HReturn(_abstractValueDomain, value, sourceInformation));
     } else {
       localsHandler.updateLocal(_returnLocal, value);
     }
@@ -5749,7 +6081,7 @@
     MemberDefinition definition = _elementMap.getMemberDefinition(function);
     switch (definition.kind) {
       case MemberKind.constructor:
-        buildConstructor(function, definition.node);
+        _buildConstructor(function, definition.node);
         return;
       case MemberKind.constructorBody:
         ir.Constructor constructor = definition.node;
@@ -5783,8 +6115,6 @@
 
   /// Generates type tests for the parameters of the inlined function.
   void _potentiallyCheckInlinedParameterTypes(FunctionEntity function) {
-    if (!typeBuilder.checkOrTrustTypes) return;
-
     // TODO(sra): Incorporate properties of call site to help determine which
     // type parameters and value parameters need to be checked.
     bool trusted = false;
@@ -5798,7 +6128,7 @@
     }
 
     if (!trusted) {
-      checkTypeVariableBounds(function);
+      _checkTypeVariableBounds(function);
     }
 
     KernelToLocalsMap localsMap =
@@ -5810,10 +6140,10 @@
       DartType type = localsMap.getLocalType(_elementMap, parameter);
       HInstruction checkedOrTrusted;
       if (trusted) {
-        checkedOrTrusted = typeBuilder.trustTypeOfParameter(argument, type);
+        checkedOrTrusted = _typeBuilder.trustTypeOfParameter(argument, type);
       } else {
         checkedOrTrusted =
-            typeBuilder.potentiallyCheckOrTrustTypeOfParameter(argument, type);
+            _typeBuilder.potentiallyCheckOrTrustTypeOfParameter(argument, type);
       }
       localsHandler.updateLocal(parameter, checkedOrTrusted);
     });
@@ -5845,7 +6175,7 @@
 
   void _insertCoverageCall(MemberEntity element) {
     if (!options.experimentCallInstrumentation) return;
-    if (element == commonElements.traceHelper) return;
+    if (element == _commonElements.traceHelper) return;
     // TODO(sigmund): create a better uuid for elements.
     HConstant idConstant = graph.addConstantInt(element.hashCode, closedWorld);
     n(e) => e == null ? '' : e.name;
@@ -5853,9 +6183,9 @@
         "${n(element)}";
     HConstant nameConstant = graph.addConstantString(name, closedWorld);
     add(new HInvokeStatic(
-        commonElements.traceHelper,
+        _commonElements.traceHelper,
         <HInstruction>[idConstant, nameConstant],
-        abstractValueDomain.dynamicType,
+        _abstractValueDomain.dynamicType,
         const <DartType>[]));
   }
 }
@@ -5890,517 +6220,10 @@
       this.oldLocalsHandler,
       this.inTryStatement,
       this.allFunctionsCalledOnce);
-}
-
-class InlineWeeder extends ir.Visitor {
-  // Invariant: *INSIDE_LOOP* > *OUTSIDE_LOOP*
-  static const INLINING_NODES_OUTSIDE_LOOP = 15;
-  static const INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR = 3;
-  static const INLINING_NODES_INSIDE_LOOP = 34;
-  static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4;
-
-  static bool canBeInlined(
-      JsToElementMap elementMap, FunctionEntity function, int maxInliningNodes,
-      {bool allowLoops: false, bool enableUserAssertions: null}) {
-    return cannotBeInlinedReason(elementMap, function, maxInliningNodes,
-            allowLoops: allowLoops,
-            enableUserAssertions: enableUserAssertions) ==
-        null;
-  }
-
-  static String cannotBeInlinedReason(
-      JsToElementMap elementMap, FunctionEntity function, int maxInliningNodes,
-      {bool allowLoops: false, bool enableUserAssertions: null}) {
-    InlineWeeder visitor =
-        new InlineWeeder(maxInliningNodes, allowLoops, enableUserAssertions);
-    ir.FunctionNode node = getFunctionNode(elementMap, function);
-    node.accept(visitor);
-    if (function.isConstructor) {
-      MemberDefinition definition = elementMap.getMemberDefinition(function);
-      ir.Node node = definition.node;
-      if (node is ir.Constructor) {
-        node.initializers.forEach((n) => n.accept(visitor));
-      }
-    }
-    return visitor.tooDifficultReason;
-  }
-
-  final int maxInliningNodes; // `null` for unbounded.
-  final bool allowLoops;
-  final bool enableUserAssertions;
-
-  bool seenReturn = false;
-  int nodeCount = 0;
-  String tooDifficultReason;
-  bool get tooDifficult => tooDifficultReason != null;
-
-  InlineWeeder(
-      this.maxInliningNodes, this.allowLoops, this.enableUserAssertions);
-
-  bool registerNode() {
-    if (maxInliningNodes == null) return true;
-    if (nodeCount++ > maxInliningNodes) {
-      tooDifficultReason ??= 'too many nodes';
-      return false;
-    }
-    return true;
-  }
 
   @override
-  defaultNode(ir.Node node) {
-    if (tooDifficult) return;
-    if (!registerNode()) return;
-    if (seenReturn) {
-      tooDifficultReason ??= 'code after return';
-      return;
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  visitReturnStatement(ir.ReturnStatement node) {
-    if (!registerNode()) return;
-    if (seenReturn) {
-      tooDifficultReason ??= 'code after return';
-      return;
-    }
-    node.visitChildren(this);
-    seenReturn = true;
-  }
-
-  @override
-  visitThrow(ir.Throw node) {
-    if (!registerNode()) return;
-    if (seenReturn) {
-      tooDifficultReason ??= 'code after return';
-      return;
-    }
-    node.visitChildren(this);
-  }
-
-  _handleLoop(ir.Node node) {
-    // It's actually not difficult to inline a method with a loop, but our
-    // measurements show that it's currently better to not inline a method that
-    // contains a loop.
-    if (!allowLoops) tooDifficultReason ??= 'loop';
-    node.visitChildren(this);
-  }
-
-  @override
-  visitForStatement(ir.ForStatement node) {
-    _handleLoop(node);
-  }
-
-  @override
-  visitForInStatement(ir.ForInStatement node) {
-    _handleLoop(node);
-  }
-
-  @override
-  visitWhileStatement(ir.WhileStatement node) {
-    _handleLoop(node);
-  }
-
-  @override
-  visitDoStatement(ir.DoStatement node) {
-    _handleLoop(node);
-  }
-
-  @override
-  visitTryCatch(ir.TryCatch node) {
-    tooDifficultReason ??= 'try';
-  }
-
-  @override
-  visitTryFinally(ir.TryFinally node) {
-    tooDifficultReason ??= 'try';
-  }
-
-  @override
-  visitFunctionExpression(ir.FunctionExpression node) {
-    if (!registerNode()) return;
-    tooDifficultReason ??= 'closure';
-  }
-
-  @override
-  visitFunctionDeclaration(ir.FunctionDeclaration node) {
-    if (!registerNode()) return;
-    tooDifficultReason ??= 'closure';
-  }
-
-  @override
-  visitFunctionNode(ir.FunctionNode node) {
-    if (node.asyncMarker != ir.AsyncMarker.Sync) {
-      tooDifficultReason ??= 'async/await';
-      return;
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  visitConditionalExpression(ir.ConditionalExpression node) {
-    // Heuristic: In "parameter ? A : B" there is a high probability that
-    // parameter is a constant. Assuming the parameter is constant, we can
-    // compute a count that is bounded by the largest arm rather than the sum of
-    // both arms.
-    ir.Expression condition = node.condition;
-    condition.accept(this);
-    if (tooDifficult) return;
-    int commonPrefixCount = nodeCount;
-
-    node.then.accept(this);
-    if (tooDifficult) return;
-    int thenCount = nodeCount - commonPrefixCount;
-
-    nodeCount = commonPrefixCount;
-    node.otherwise.accept(this);
-    if (tooDifficult) return;
-    int elseCount = nodeCount - commonPrefixCount;
-
-    nodeCount = commonPrefixCount + thenCount + elseCount;
-    if (condition is ir.VariableGet &&
-        condition.variable.parent is ir.FunctionNode) {
-      nodeCount =
-          commonPrefixCount + (thenCount > elseCount ? thenCount : elseCount);
-    }
-    // This is last so that [tooDifficult] is always updated.
-    if (!registerNode()) return;
-  }
-
-  @override
-  visitAssertInitializer(ir.AssertInitializer node) {
-    if (!enableUserAssertions) return;
-    node.visitChildren(this);
-  }
-
-  @override
-  visitAssertStatement(ir.AssertStatement node) {
-    if (!enableUserAssertions) return;
-    defaultNode(node);
-  }
-}
-
-/// Determines if inlining a function is very likely to reduce code size.
-class InlineReductiveWeeder extends ir.Visitor {
-  // We allow the body to be a single function call that does not have any more
-  // inputs than the inlinee.
-  //
-  // We allow the body to be the return of an 'eligible' constant. A constant is
-  // 'eligible' if it is not large (e.g. a long string).
-  //
-  // We skip 'e as{TypeError} T' when the checks are omitted.
-  //
-  //
-  // TODO(sra): Consider slightly expansive simple constructors where all we
-  // gain is a 'new' keyword, e.g. `new X.Foo(a)` vs `X.Foo$(a)`.
-  //
-  // TODO(25231): Make larger string constants eligible by sharing references.
-
-  static bool canBeInlined(
-      JsToElementMap elementMap, FunctionEntity function, int argumentCount,
-      {bool enableUserAssertions: null, bool omitImplicitCasts: null}) {
-    return cannotBeInlinedReason(elementMap, function, argumentCount,
-            enableUserAssertions: enableUserAssertions,
-            omitImplicitCasts: omitImplicitCasts) ==
-        null;
-  }
-
-  static String cannotBeInlinedReason(
-      JsToElementMap elementMap, FunctionEntity function, int argumentCount,
-      {bool enableUserAssertions: null, bool omitImplicitCasts: null}) {
-    assert(enableUserAssertions != null);
-    assert(omitImplicitCasts != null);
-    var visitor = new InlineReductiveWeeder(
-        argumentCount, enableUserAssertions, omitImplicitCasts);
-    ir.FunctionNode node = getFunctionNode(elementMap, function);
-    if (function.isConstructor) {
-      return visitor.tooDifficultReason ??= 'constructor';
-    }
-    node.accept(visitor);
-    return visitor.tooDifficultReason;
-  }
-
-  final int argumentCount;
-  final bool enableUserAssertions;
-  final bool omitImplicitCasts;
-  final int maxInliningNodes;
-
-  bool seenReturn = false;
-  int nodeCount = 0;
-  int callCount = 0;
-  String tooDifficultReason;
-  bool get tooDifficult => tooDifficultReason != null;
-
-  InlineReductiveWeeder(
-      this.argumentCount, this.enableUserAssertions, this.omitImplicitCasts)
-      :
-        // Node budget that covers one call and the passed-in arguments.
-        // The +1 also allows a top-level zero-argument to be inlined if it
-        // returns a constant.
-        maxInliningNodes = argumentCount + 1;
-
-  bool registerNode() {
-    if (++nodeCount > maxInliningNodes) {
-      tooDifficultReason ??= 'too many nodes';
-      return false;
-    }
-    return true;
-  }
-
-  bool registerCall() {
-    if (++callCount > 1) {
-      tooDifficultReason ??= 'too many calls';
-      return false;
-    }
-    return true;
-  }
-
-  @override
-  defaultNode(ir.Node node) {
-    if (tooDifficult) return;
-    if (seenReturn) {
-      tooDifficultReason ??= 'code after return';
-      return;
-    }
-    if (!registerNode()) return;
-    node.visitChildren(this);
-  }
-
-  @override
-  visitReturnStatement(ir.ReturnStatement node) {
-    if (seenReturn) {
-      tooDifficultReason ??= 'code after return';
-      return;
-    }
-    node.visitChildren(this);
-    seenReturn = true;
-  }
-
-  @override
-  visitThrow(ir.Throw node) {
-    tooDifficultReason ??= 'throw';
-  }
-
-  @override
-  visitEmptyStatement(ir.EmptyStatement node) {}
-
-  @override
-  visitExpressionStatement(ir.ExpressionStatement node) {
-    node.visitChildren(this);
-  }
-
-  @override
-  visitBlock(ir.Block node) {
-    node.visitChildren(this);
-  }
-
-  @override
-  visitStringLiteral(ir.StringLiteral node) {
-    registerNode();
-    // Avoid copying long strings into call site.
-    if (node.value.length > 14) tooDifficultReason ??= 'long string';
-  }
-
-  @override
-  visitPropertyGet(ir.PropertyGet node) {
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    node.receiver.accept(this);
-  }
-
-  @override
-  visitDirectPropertyGet(ir.DirectPropertyGet node) {
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    node.receiver.accept(this);
-  }
-
-  @override
-  visitPropertySet(ir.PropertySet node) {
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    node.receiver.accept(this);
-    node.value.accept(this);
-  }
-
-  @override
-  visitDirectPropertySet(ir.DirectPropertySet node) {
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    node.receiver.accept(this);
-    node.value.accept(this);
-  }
-
-  @override
-  visitVariableGet(ir.VariableGet node) {
-    registerNode();
-  }
-
-  @override
-  visitThisExpression(ir.ThisExpression node) {
-    registerNode();
-  }
-
-  @override
-  visitStaticGet(ir.StaticGet node) {
-    // Assume lazy-init static, loaded via a call: `$.$get$foo()`.
-    if (!registerCall()) return;
-    registerNode();
-  }
-
-  @override
-  visitConstructorInvocation(ir.ConstructorInvocation node) {
-    if (node.isConst) {
-      // A const constructor call compiles to a constant pool reference.
-      registerNode();
-      return;
-    }
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    _processArguments(node.arguments, node.target?.function);
-  }
-
-  @override
-  visitStaticInvocation(ir.StaticInvocation node) {
-    if (node.isConst) {
-      tooDifficultReason ??= 'external const constructor';
-      return;
-    }
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    _processArguments(node.arguments, node.target?.function);
-  }
-
-  @override
-  visitMethodInvocation(ir.MethodInvocation node) {
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    node.receiver.accept(this);
-    _processArguments(node.arguments, null);
-  }
-
-  _processArguments(ir.Arguments arguments, ir.FunctionNode target) {
-    if (arguments.types.isNotEmpty) {
-      tooDifficultReason ??= 'type arguments';
-      return;
-    }
-    int count = arguments.positional.length + arguments.named.length;
-    if (count > argumentCount) {
-      tooDifficultReason ??= 'increasing arguments';
-      return;
-    }
-
-    if (target != null) {
-      // Disallow defaulted optional arguments since they will be passed
-      // explicitly.
-      if (target.positionalParameters.length + target.namedParameters.length >
-          count) {
-        tooDifficultReason ??= 'argument defaulting';
-        return;
-      }
-    }
-
-    for (var e in arguments.positional) {
-      e.accept(this);
-      if (tooDifficult) return;
-    }
-    for (var e in arguments.named) {
-      e.value.accept(this);
-      if (tooDifficult) return;
-    }
-  }
-
-  @override
-  visitAsExpression(ir.AsExpression node) {
-    if (node.isTypeError && omitImplicitCasts) {
-      node.operand.accept(this);
-      return;
-    }
-    tooDifficultReason ??= 'cast';
-  }
-
-  @override
-  visitVariableDeclaration(ir.VariableDeclaration node) {
-    // A local variable is an alias for the initializer expression.
-    if (node.initializer != null) {
-      --nodeCount; // discount one reference to the variable.
-      node.initializer.accept(this);
-      return;
-    }
-  }
-
-  @override
-  visitForStatement(ir.ForStatement node) {
-    tooDifficultReason ??= 'loop';
-  }
-
-  @override
-  visitForInStatement(ir.ForInStatement node) {
-    tooDifficultReason ??= 'loop';
-  }
-
-  @override
-  visitWhileStatement(ir.WhileStatement node) {
-    tooDifficultReason ??= 'loop';
-  }
-
-  @override
-  visitDoStatement(ir.DoStatement node) {
-    tooDifficultReason ??= 'loop';
-  }
-
-  @override
-  visitTryCatch(ir.TryCatch node) {
-    tooDifficultReason ??= 'try';
-  }
-
-  @override
-  visitTryFinally(ir.TryFinally node) {
-    tooDifficultReason ??= 'try';
-  }
-
-  @override
-  visitIfStatement(ir.IfStatement node) {
-    tooDifficultReason ??= 'if';
-  }
-
-  @override
-  visitFunctionExpression(ir.FunctionExpression node) {
-    tooDifficultReason ??= 'closure';
-  }
-
-  @override
-  visitFunctionDeclaration(ir.FunctionDeclaration node) {
-    tooDifficultReason ??= 'closure';
-  }
-
-  @override
-  visitFunctionNode(ir.FunctionNode node) {
-    if (node.asyncMarker != ir.AsyncMarker.Sync) {
-      tooDifficultReason ??= 'async/await';
-      return;
-    }
-    // TODO(sra): Cost of parameter checking?
-    node.body.accept(this);
-  }
-
-  @override
-  visitConditionalExpression(ir.ConditionalExpression node) {
-    if (!registerNode()) return;
-    node.visitChildren(this);
-  }
-
-  @override
-  visitAssertInitializer(ir.AssertInitializer node) {
-    if (!enableUserAssertions) return;
-    node.visitChildren(this);
-  }
-
-  @override
-  visitAssertStatement(ir.AssertStatement node) {
-    if (!enableUserAssertions) return;
-    defaultNode(node);
-  }
+  String toString() => 'KernelInliningState($function,'
+      'allFunctionsCalledOnce=$allFunctionsCalledOnce)';
 }
 
 /// Class in charge of building try, catch and/or finally blocks. This handles
@@ -6438,12 +6261,12 @@
   LocalsHandler originalSavedLocals;
 
   TryCatchFinallyBuilder(this.kernelBuilder, this.trySourceInformation) {
-    tryInstruction = new HTry(kernelBuilder.abstractValueDomain);
+    tryInstruction = new HTry(kernelBuilder._abstractValueDomain);
     originalSavedLocals = new LocalsHandler.from(kernelBuilder.localsHandler);
     enterBlock = kernelBuilder.openNewBlock();
     kernelBuilder.close(tryInstruction);
-    previouslyInTryStatement = kernelBuilder.inTryStatement;
-    kernelBuilder.inTryStatement = true;
+    previouslyInTryStatement = kernelBuilder._inTryStatement;
+    kernelBuilder._inTryStatement = true;
 
     startTryBlock = kernelBuilder.graph.addNewBlock();
     kernelBuilder.open(startTryBlock);
@@ -6510,7 +6333,7 @@
     buildFinalizer();
     if (!kernelBuilder.isAborted()) {
       endFinallyBlock =
-          kernelBuilder.close(new HGoto(kernelBuilder.abstractValueDomain));
+          kernelBuilder.close(new HGoto(kernelBuilder._abstractValueDomain));
     }
     tryInstruction.finallyBlock = startFinallyBlock;
     finallyGraph =
@@ -6523,7 +6346,7 @@
     // the catch or finally block.
     if (!kernelBuilder.isAborted()) {
       endTryBlock =
-          kernelBuilder.close(new HExitTry(kernelBuilder.abstractValueDomain));
+          kernelBuilder.close(new HExitTry(kernelBuilder._abstractValueDomain));
     }
     bodyGraph = new SubGraph(startTryBlock, kernelBuilder.lastOpenedBlock);
   }
@@ -6535,11 +6358,11 @@
     // Note that the name of this local is irrelevant.
     SyntheticLocal local = kernelBuilder.localsHandler.createLocal('exception');
     exception =
-        new HLocalValue(local, kernelBuilder.abstractValueDomain.nonNullType)
+        new HLocalValue(local, kernelBuilder._abstractValueDomain.nonNullType)
           ..sourceInformation = trySourceInformation;
     kernelBuilder.add(exception);
-    HInstruction oldRethrowableException = kernelBuilder.rethrowableException;
-    kernelBuilder.rethrowableException = exception;
+    HInstruction oldRethrowableException = kernelBuilder._rethrowableException;
+    kernelBuilder._rethrowableException = exception;
 
     kernelBuilder._pushStaticInvocation(
         kernelBuilder._commonElements.exceptionUnwrapper,
@@ -6554,7 +6377,7 @@
 
     void pushCondition(ir.Catch catchBlock) {
       // `guard` is often `dynamic`, which generates `true`.
-      kernelBuilder.pushIsTest(catchBlock.guard, unwrappedException,
+      kernelBuilder._pushIsTest(catchBlock.guard, unwrappedException,
           kernelBuilder._sourceInformationBuilder.buildCatch(catchBlock));
     }
 
@@ -6563,7 +6386,7 @@
       catchesIndex++;
       if (catchBlock.exception != null) {
         Local exceptionVariable =
-            kernelBuilder.localsMap.getLocalVariable(catchBlock.exception);
+            kernelBuilder._localsMap.getLocalVariable(catchBlock.exception);
         kernelBuilder.localsHandler.updateLocal(
             exceptionVariable, unwrappedException,
             sourceInformation:
@@ -6580,7 +6403,7 @@
                 kernelBuilder._sourceInformationBuilder.buildCatch(catchBlock));
         HInstruction traceInstruction = kernelBuilder.pop();
         Local traceVariable =
-            kernelBuilder.localsMap.getLocalVariable(catchBlock.stackTrace);
+            kernelBuilder._localsMap.getLocalVariable(catchBlock.stackTrace);
         kernelBuilder.localsHandler.updateLocal(traceVariable, traceInstruction,
             sourceInformation:
                 kernelBuilder._sourceInformationBuilder.buildCatch(catchBlock));
@@ -6590,14 +6413,14 @@
 
     void visitElse() {
       if (catchesIndex >= tryCatch.catches.length) {
-        kernelBuilder.closeAndGotoExit(new HThrow(
-            kernelBuilder.abstractValueDomain,
+        kernelBuilder._closeAndGotoExit(new HThrow(
+            kernelBuilder._abstractValueDomain,
             exception,
             exception.sourceInformation,
             isRethrow: true));
       } else {
         ir.Catch nextCatch = tryCatch.catches[catchesIndex];
-        kernelBuilder.handleIf(
+        kernelBuilder._handleIf(
             visitCondition: () {
               pushCondition(nextCatch);
             },
@@ -6609,7 +6432,7 @@
     }
 
     ir.Catch firstBlock = tryCatch.catches[catchesIndex];
-    kernelBuilder.handleIf(
+    kernelBuilder._handleIf(
         visitCondition: () {
           pushCondition(firstBlock);
         },
@@ -6619,10 +6442,10 @@
             kernelBuilder._sourceInformationBuilder.buildCatch(firstBlock));
     if (!kernelBuilder.isAborted()) {
       endCatchBlock =
-          kernelBuilder.close(new HGoto(kernelBuilder.abstractValueDomain));
+          kernelBuilder.close(new HGoto(kernelBuilder._abstractValueDomain));
     }
 
-    kernelBuilder.rethrowableException = oldRethrowableException;
+    kernelBuilder._rethrowableException = oldRethrowableException;
     tryInstruction.catchBlock = startCatchBlock;
     catchGraph = new SubGraph(startCatchBlock, kernelBuilder.lastOpenedBlock);
   }
@@ -6642,7 +6465,7 @@
             kernelBuilder.wrapStatementGraph(catchGraph),
             kernelBuilder.wrapStatementGraph(finallyGraph)),
         exitBlock);
-    kernelBuilder.inTryStatement = previouslyInTryStatement;
+    kernelBuilder._inTryStatement = previouslyInTryStatement;
   }
 }
 
@@ -6693,7 +6516,7 @@
 /// Special [JumpHandler] implementation used to handle continue statements
 /// targeting switch cases.
 class KernelSwitchCaseJumpHandler extends SwitchCaseJumpHandler {
-  KernelSwitchCaseJumpHandler(GraphBuilder builder, JumpTarget target,
+  KernelSwitchCaseJumpHandler(KernelSsaGraphBuilder builder, JumpTarget target,
       ir.SwitchStatement switchStatement, KernelToLocalsMap localsMap)
       : super(builder, target) {
     // The switch case indices must match those computed in
@@ -6714,3 +6537,642 @@
     }
   }
 }
+
+class StaticType {
+  final DartType type;
+  final ClassRelation relation;
+
+  StaticType(this.type, this.relation);
+
+  @override
+  int get hashCode => type.hashCode * 13 + relation.hashCode * 19;
+
+  @override
+  bool operator ==(other) {
+    if (identical(this, other)) return true;
+    return other is StaticType &&
+        type == other.type &&
+        relation == other.relation;
+  }
+
+  @override
+  String toString() => 'StaticType($type,$relation)';
+}
+
+class InlineData {
+  bool isConstructor = false;
+  bool codeAfterReturn = false;
+  bool hasLoop = false;
+  bool hasClosure = false;
+  bool hasTry = false;
+  bool hasAsyncAwait = false;
+  bool hasThrow = false;
+  bool hasLongString = false;
+  bool hasExternalConstantConstructorCall = false;
+  bool hasTypeArguments = false;
+  bool hasArgumentDefaulting = false;
+  bool hasCast = false;
+  bool hasIf = false;
+  List<int> argumentCounts = [];
+  int regularNodeCount = 0;
+  int callCount = 0;
+  int reductiveNodeCount = 0;
+
+  InlineData();
+
+  InlineData.internal(
+      {this.codeAfterReturn,
+      this.hasLoop,
+      this.hasClosure,
+      this.hasTry,
+      this.hasAsyncAwait,
+      this.hasThrow,
+      this.hasLongString,
+      this.regularNodeCount,
+      this.callCount});
+
+  bool canBeInlined({int maxInliningNodes, bool allowLoops: false}) {
+    return cannotBeInlinedReason(
+            maxInliningNodes: maxInliningNodes, allowLoops: allowLoops) ==
+        null;
+  }
+
+  String cannotBeInlinedReason({int maxInliningNodes, bool allowLoops: false}) {
+    if (hasLoop && !allowLoops) {
+      return 'loop';
+    } else if (hasTry) {
+      return 'try';
+    } else if (hasClosure) {
+      return 'closure';
+    } else if (codeAfterReturn) {
+      return 'code after return';
+    } else if (hasAsyncAwait) {
+      return 'async/await';
+    } else if (maxInliningNodes != null &&
+        regularNodeCount - 1 > maxInliningNodes) {
+      return 'too many nodes (${regularNodeCount - 1}>$maxInliningNodes)';
+    }
+    return null;
+  }
+
+  bool canBeInlinedReductive({int argumentCount}) {
+    return cannotBeInlinedReductiveReason(argumentCount: argumentCount) == null;
+  }
+
+  String cannotBeInlinedReductiveReason({int argumentCount}) {
+    if (hasTry) {
+      return 'try';
+    } else if (hasClosure) {
+      return 'closure';
+    } else if (codeAfterReturn) {
+      return 'code after return';
+    } else if (hasAsyncAwait) {
+      return 'async/await';
+    } else if (callCount > 1) {
+      return 'too many calls';
+    } else if (hasThrow) {
+      return 'throw';
+    } else if (hasLongString) {
+      return 'long string';
+    } else if (hasExternalConstantConstructorCall) {
+      return 'external const constructor';
+    } else if (hasTypeArguments) {
+      return 'type arguments';
+    } else if (hasArgumentDefaulting) {
+      return 'argument defaulting';
+    } else if (hasCast) {
+      return 'cast';
+    } else if (hasIf) {
+      return 'if';
+    } else if (isConstructor) {
+      return 'constructor';
+    }
+    for (int count in argumentCounts) {
+      if (count > argumentCount) {
+        return 'increasing arguments';
+      }
+    }
+    // Node budget that covers one call and the passed-in arguments.
+    // The +1 also allows a top-level zero-argument to be inlined if it
+    // returns a constant.
+    int maxInliningNodes = argumentCount + 1;
+    if (reductiveNodeCount > maxInliningNodes) {
+      return 'too many nodes (${reductiveNodeCount}>$maxInliningNodes)';
+    }
+
+    return null;
+  }
+
+  @override
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.write('InlineData(');
+    String comma = '';
+    if (isConstructor) {
+      sb.write('isConstructor');
+      comma = ',';
+    }
+    if (codeAfterReturn) {
+      sb.write(comma);
+      sb.write('codeAfterReturn');
+      comma = ',';
+    }
+    if (hasLoop) {
+      sb.write(comma);
+      sb.write('hasLoop');
+      comma = ',';
+    }
+    if (hasClosure) {
+      sb.write(comma);
+      sb.write('hasClosure');
+      comma = ',';
+    }
+    if (hasTry) {
+      sb.write(comma);
+      sb.write('hasTry');
+      comma = ',';
+    }
+    if (hasAsyncAwait) {
+      sb.write(comma);
+      sb.write('hasAsyncAwait');
+      comma = ',';
+    }
+    if (hasThrow) {
+      sb.write(comma);
+      sb.write('hasThrow');
+      comma = ',';
+    }
+    if (hasLongString) {
+      sb.write(comma);
+      sb.write('hasLongString');
+      comma = ',';
+    }
+    if (hasExternalConstantConstructorCall) {
+      sb.write(comma);
+      sb.write('hasExternalConstantConstructorCall');
+      comma = ',';
+    }
+    if (hasTypeArguments) {
+      sb.write(comma);
+      sb.write('hasTypeArguments');
+      comma = ',';
+    }
+    if (hasArgumentDefaulting) {
+      sb.write(comma);
+      sb.write('hasArgumentDefaulting');
+      comma = ',';
+    }
+    if (hasCast) {
+      sb.write(comma);
+      sb.write('hasCast');
+      comma = ',';
+    }
+    if (hasIf) {
+      sb.write(comma);
+      sb.write('hasIf');
+      comma = ',';
+    }
+    if (argumentCounts.isNotEmpty) {
+      sb.write(comma);
+      sb.write('argumentCounts={${argumentCounts.join(',')}}');
+      comma = ',';
+    }
+    sb.write(comma);
+    sb.write('regularNodeCount=$regularNodeCount,');
+    sb.write('callCount=$callCount,');
+    sb.write('reductiveNodeCount=$reductiveNodeCount');
+    sb.write(')');
+    return sb.toString();
+  }
+}
+
+class InlineDataCache {
+  final bool enableUserAssertions;
+  final bool omitImplicitCasts;
+
+  InlineDataCache(
+      {this.enableUserAssertions: false, this.omitImplicitCasts: false});
+
+  Map<FunctionEntity, InlineData> _cache = {};
+
+  InlineData getInlineData(JsToElementMap elementMap, FunctionEntity function) {
+    return _cache[function] ??= InlineWeeder.computeInlineData(
+        elementMap, function,
+        enableUserAssertions: enableUserAssertions,
+        omitImplicitCasts: omitImplicitCasts);
+  }
+}
+
+class InlineWeeder extends ir.Visitor {
+  // Invariant: *INSIDE_LOOP* > *OUTSIDE_LOOP*
+  static const INLINING_NODES_OUTSIDE_LOOP = 15;
+  static const INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR = 3;
+  static const INLINING_NODES_INSIDE_LOOP = 34;
+  static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4;
+
+  final bool enableUserAssertions;
+  final bool omitImplicitCasts;
+
+  final InlineData data = new InlineData();
+  bool seenReturn = false;
+
+  /// Whether node-count is collector to determine if a function can be
+  /// inlined.
+  bool countRegularNode = true;
+
+  /// Whether node-count is collected to determine if inlining a function is
+  /// very likely to reduce code size.
+  ///
+  /// For the reductive analysis:
+  /// We allow the body to be a single function call that does not have any more
+  /// inputs than the inlinee.
+  ///
+  /// We allow the body to be the return of an 'eligible' constant. A constant
+  /// is 'eligible' if it is not large (e.g. a long string).
+  ///
+  /// We skip 'e as{TypeError} T' when the checks are omitted.
+  //
+  // TODO(sra): Consider slightly expansive simple constructors where all we
+  // gain is a 'new' keyword, e.g. `new X.Foo(a)` vs `X.Foo$(a)`.
+  //
+  // TODO(25231): Make larger string constants eligible by sharing references.
+  bool countReductiveNode = true;
+
+  InlineWeeder(
+      {this.enableUserAssertions: false, this.omitImplicitCasts: false});
+
+  static InlineData computeInlineData(
+      JsToElementMap elementMap, FunctionEntity function,
+      {bool enableUserAssertions: false, bool omitImplicitCasts: false}) {
+    InlineWeeder visitor = new InlineWeeder(
+        enableUserAssertions: enableUserAssertions,
+        omitImplicitCasts: omitImplicitCasts);
+    ir.FunctionNode node = getFunctionNode(elementMap, function);
+    node.accept(visitor);
+    if (function.isConstructor) {
+      visitor.data.isConstructor = true;
+      MemberDefinition definition = elementMap.getMemberDefinition(function);
+      visitor.skipReductiveNodes(() {
+        ir.Node node = definition.node;
+        if (node is ir.Constructor) {
+          visitor.visitList(node.initializers);
+        }
+      });
+    }
+    return visitor.data;
+  }
+
+  void skipRegularNodes(void f()) {
+    bool oldCountRegularNode = countRegularNode;
+    countRegularNode = false;
+    f();
+    countRegularNode = oldCountRegularNode;
+  }
+
+  void skipReductiveNodes(void f()) {
+    bool oldCountReductiveNode = countReductiveNode;
+    countReductiveNode = false;
+    f();
+    countReductiveNode = oldCountReductiveNode;
+  }
+
+  void registerRegularNode() {
+    if (countRegularNode) {
+      data.regularNodeCount++;
+      if (seenReturn) {
+        data.codeAfterReturn = true;
+      }
+    }
+  }
+
+  void registerReductiveNode() {
+    if (countReductiveNode) {
+      data.reductiveNodeCount++;
+      if (seenReturn) {
+        data.codeAfterReturn = true;
+      }
+    }
+  }
+
+  void unregisterReductiveNode() {
+    if (countReductiveNode) {
+      data.reductiveNodeCount--;
+    }
+  }
+
+  void visit(ir.Node node) => node?.accept(this);
+
+  void visitList(List<ir.Node> nodes) {
+    for (ir.Node node in nodes) {
+      visit(node);
+    }
+  }
+
+  @override
+  defaultNode(ir.Node node) {
+    registerRegularNode();
+    registerReductiveNode();
+    node.visitChildren(this);
+  }
+
+  @override
+  visitReturnStatement(ir.ReturnStatement node) {
+    registerRegularNode();
+    node.visitChildren(this);
+    seenReturn = true;
+  }
+
+  @override
+  visitThrow(ir.Throw node) {
+    registerRegularNode();
+    data.hasThrow = true;
+    node.visitChildren(this);
+  }
+
+  _handleLoop(ir.Node node) {
+    // It's actually not difficult to inline a method with a loop, but our
+    // measurements show that it's currently better to not inline a method that
+    // contains a loop.
+    data.hasLoop = true;
+    node.visitChildren(this);
+  }
+
+  @override
+  visitForStatement(ir.ForStatement node) {
+    _handleLoop(node);
+  }
+
+  @override
+  visitForInStatement(ir.ForInStatement node) {
+    _handleLoop(node);
+  }
+
+  @override
+  visitWhileStatement(ir.WhileStatement node) {
+    _handleLoop(node);
+  }
+
+  @override
+  visitDoStatement(ir.DoStatement node) {
+    _handleLoop(node);
+  }
+
+  @override
+  visitTryCatch(ir.TryCatch node) {
+    data.hasTry = true;
+  }
+
+  @override
+  visitTryFinally(ir.TryFinally node) {
+    data.hasTry = true;
+  }
+
+  @override
+  visitFunctionExpression(ir.FunctionExpression node) {
+    registerRegularNode();
+    data.hasClosure = true;
+  }
+
+  @override
+  visitFunctionDeclaration(ir.FunctionDeclaration node) {
+    registerRegularNode();
+    data.hasClosure = true;
+  }
+
+  @override
+  visitFunctionNode(ir.FunctionNode node) {
+    if (node.asyncMarker != ir.AsyncMarker.Sync) {
+      data.hasAsyncAwait = true;
+    }
+    // TODO(sra): Cost of parameter checking?
+    skipReductiveNodes(() {
+      visitList(node.typeParameters);
+      visitList(node.positionalParameters);
+      visitList(node.namedParameters);
+      visit(node.returnType);
+    });
+    visit(node.body);
+  }
+
+  @override
+  visitConditionalExpression(ir.ConditionalExpression node) {
+    // Heuristic: In "parameter ? A : B" there is a high probability that
+    // parameter is a constant. Assuming the parameter is constant, we can
+    // compute a count that is bounded by the largest arm rather than the sum of
+    // both arms.
+    ir.Expression condition = node.condition;
+    visit(condition);
+    int commonPrefixCount = data.regularNodeCount;
+
+    visit(node.then);
+    int thenCount = data.regularNodeCount - commonPrefixCount;
+
+    data.regularNodeCount = commonPrefixCount;
+    visit(node.otherwise);
+    int elseCount = data.regularNodeCount - commonPrefixCount;
+
+    data.regularNodeCount = commonPrefixCount + thenCount + elseCount;
+    if (condition is ir.VariableGet &&
+        condition.variable.parent is ir.FunctionNode) {
+      data.regularNodeCount =
+          commonPrefixCount + (thenCount > elseCount ? thenCount : elseCount);
+    }
+    // This is last so that [tooDifficult] is always updated.
+    registerRegularNode();
+    registerReductiveNode();
+    skipRegularNodes(() => visit(node.staticType));
+  }
+
+  @override
+  visitAssertInitializer(ir.AssertInitializer node) {
+    if (!enableUserAssertions) return;
+    node.visitChildren(this);
+  }
+
+  @override
+  visitAssertStatement(ir.AssertStatement node) {
+    if (!enableUserAssertions) return;
+    defaultNode(node);
+  }
+
+  void registerCall() {
+    ++data.callCount;
+  }
+
+  @override
+  visitEmptyStatement(ir.EmptyStatement node) {
+    registerRegularNode();
+  }
+
+  @override
+  visitExpressionStatement(ir.ExpressionStatement node) {
+    registerRegularNode();
+    node.visitChildren(this);
+  }
+
+  @override
+  visitBlock(ir.Block node) {
+    registerRegularNode();
+    node.visitChildren(this);
+  }
+
+  @override
+  visitStringLiteral(ir.StringLiteral node) {
+    registerRegularNode();
+    registerReductiveNode();
+    // Avoid copying long strings into call site.
+    if (node.value.length > 14) {
+      data.hasLongString = true;
+    }
+  }
+
+  @override
+  visitPropertyGet(ir.PropertyGet node) {
+    registerCall();
+    registerRegularNode();
+    registerReductiveNode();
+    skipReductiveNodes(() => visit(node.name));
+    visit(node.receiver);
+  }
+
+  @override
+  visitDirectPropertyGet(ir.DirectPropertyGet node) {
+    registerCall();
+    registerRegularNode();
+    registerReductiveNode();
+    visit(node.receiver);
+  }
+
+  @override
+  visitPropertySet(ir.PropertySet node) {
+    registerCall();
+    registerRegularNode();
+    registerReductiveNode();
+    skipReductiveNodes(() => visit(node.name));
+    visit(node.receiver);
+    visit(node.value);
+  }
+
+  @override
+  visitDirectPropertySet(ir.DirectPropertySet node) {
+    registerCall();
+    registerRegularNode();
+    registerReductiveNode();
+    visit(node.receiver);
+    visit(node.value);
+  }
+
+  @override
+  visitVariableGet(ir.VariableGet node) {
+    registerRegularNode();
+    registerReductiveNode();
+    skipReductiveNodes(() => visit(node.promotedType));
+  }
+
+  @override
+  visitThisExpression(ir.ThisExpression node) {
+    registerRegularNode();
+    registerReductiveNode();
+  }
+
+  @override
+  visitStaticGet(ir.StaticGet node) {
+    // Assume lazy-init static, loaded via a call: `$.$get$foo()`.
+    registerCall();
+    registerRegularNode();
+    registerReductiveNode();
+  }
+
+  @override
+  visitConstructorInvocation(ir.ConstructorInvocation node) {
+    registerRegularNode();
+    registerReductiveNode();
+    if (node.isConst) {
+      // A const constructor call compiles to a constant pool reference.
+      skipReductiveNodes(() => node.visitChildren(this));
+    } else {
+      registerCall();
+      _processArguments(node.arguments, node.target?.function);
+    }
+  }
+
+  @override
+  visitStaticInvocation(ir.StaticInvocation node) {
+    registerRegularNode();
+    if (node.isConst) {
+      data.hasExternalConstantConstructorCall = true;
+      skipReductiveNodes(() => node.visitChildren(this));
+    } else {
+      registerCall();
+      registerReductiveNode();
+      _processArguments(node.arguments, node.target?.function);
+    }
+  }
+
+  @override
+  visitMethodInvocation(ir.MethodInvocation node) {
+    registerRegularNode();
+    registerReductiveNode();
+    registerCall();
+    visit(node.receiver);
+    skipReductiveNodes(() => visit(node.name));
+    _processArguments(node.arguments, null);
+  }
+
+  _processArguments(ir.Arguments arguments, ir.FunctionNode target) {
+    registerRegularNode();
+    if (arguments.types.isNotEmpty) {
+      data.hasTypeArguments = true;
+      skipReductiveNodes(() => visitList(arguments.types));
+    }
+    int count = arguments.positional.length + arguments.named.length;
+    data.argumentCounts.add(count);
+
+    if (target != null) {
+      // Disallow defaulted optional arguments since they will be passed
+      // explicitly.
+      if (target.positionalParameters.length + target.namedParameters.length >
+          count) {
+        data.hasArgumentDefaulting = true;
+      }
+    }
+
+    visitList(arguments.positional);
+    for (ir.NamedExpression expression in arguments.named) {
+      registerRegularNode();
+      expression.value.accept(this);
+    }
+  }
+
+  @override
+  visitAsExpression(ir.AsExpression node) {
+    registerRegularNode();
+    visit(node.operand);
+    skipReductiveNodes(() => visit(node.type));
+    if (!(node.isTypeError && omitImplicitCasts)) {
+      data.hasCast = true;
+    }
+  }
+
+  @override
+  visitVariableDeclaration(ir.VariableDeclaration node) {
+    registerRegularNode();
+    skipReductiveNodes(() {
+      visitList(node.annotations);
+      visit(node.type);
+    });
+    visit(node.initializer);
+
+    // A local variable is an alias for the initializer expression.
+    if (node.initializer != null) {
+      unregisterReductiveNode(); // discount one reference to the variable.
+    }
+  }
+
+  @override
+  visitIfStatement(ir.IfStatement node) {
+    registerRegularNode();
+    node.visitChildren(this);
+    data.hasIf = true;
+  }
+}
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 6c5852a..5fabe81 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -9,8 +9,8 @@
 
 import '../common.dart';
 import '../common/names.dart';
-import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
-import '../common/tasks.dart' show CompilerTask;
+import '../common/codegen.dart' show CodegenRegistry;
+import '../common/tasks.dart' show Measurer, CompilerTask;
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
 import '../common_elements.dart' show JCommonElements;
@@ -21,21 +21,19 @@
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
 import '../js_backend/interceptor_data.dart';
-import '../js_backend/backend.dart';
+import '../js_backend/backend.dart' show CodegenInputs;
 import '../js_backend/checked_mode_helpers.dart';
 import '../js_backend/native_data.dart';
-import '../js_backend/namer.dart';
+import '../js_backend/namer.dart' show ModularNamer;
 import '../js_backend/runtime_types.dart';
-import '../js_emitter/code_emitter_task.dart';
+import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
 import '../js_model/elements.dart' show JGeneratorBody;
 import '../native/behavior.dart';
-import '../native/enqueue.dart';
 import '../options.dart';
 import '../tracer.dart';
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
-import '../universe/use.dart'
-    show ConstantUse, ConstrainedDynamicUse, StaticUse, TypeUse;
+import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
 import '../world.dart' show JClosedWorld;
 import 'codegen_helpers.dart';
 import 'nodes.dart';
@@ -47,12 +45,12 @@
 }
 
 class SsaCodeGeneratorTask extends CompilerTask {
-  final JavaScriptBackend backend;
-  final SourceInformationStrategy sourceInformationFactory;
+  final CompilerOptions _options;
+  final SourceInformationStrategy sourceInformationStrategy;
 
-  SsaCodeGeneratorTask(JavaScriptBackend backend, this.sourceInformationFactory)
-      : this.backend = backend,
-        super(backend.compiler.measurer);
+  SsaCodeGeneratorTask(
+      Measurer measurer, this._options, this.sourceInformationStrategy)
+      : super(measurer);
 
   @override
   String get name => 'SSA code generator';
@@ -61,7 +59,7 @@
       List<js.Parameter> parameters, js.Block body) {
     js.Fun finish(js.AsyncModifier asyncModifier) {
       return new js.Fun(parameters, body, asyncModifier: asyncModifier)
-          .withSourceInformation(sourceInformationFactory
+          .withSourceInformation(sourceInformationStrategy
               .createBuilderForContext(element)
               .buildDeclaration(element));
     }
@@ -69,77 +67,90 @@
     if (needsAsyncRewrite) {
       return finish(element.asyncMarker.isAsync
           ? (element.asyncMarker.isYielding
-              ? const js.AsyncModifier.asyncStar()
-              : const js.AsyncModifier.async())
+              ? js.AsyncModifier.asyncStar
+              : js.AsyncModifier.async)
           : (element.asyncMarker.isYielding
-              ? const js.AsyncModifier.syncStar()
-              : const js.AsyncModifier.sync()));
+              ? js.AsyncModifier.syncStar
+              : js.AsyncModifier.sync));
     } else {
-      return finish(const js.AsyncModifier.sync());
+      return finish(js.AsyncModifier.sync);
     }
   }
 
   js.Expression generateCode(
-      CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
-    if (work.element.isField) {
-      return generateLazyInitializer(work, graph, closedWorld);
+      MemberEntity member,
+      HGraph graph,
+      CodegenInputs codegen,
+      JClosedWorld closedWorld,
+      CodegenRegistry registry,
+      ModularNamer namer,
+      ModularEmitter emitter) {
+    if (member.isField) {
+      return generateLazyInitializer(
+          member, graph, codegen, closedWorld, registry, namer, emitter);
     } else {
-      return generateMethod(work, graph, closedWorld);
+      return generateMethod(
+          member, graph, codegen, closedWorld, registry, namer, emitter);
     }
   }
 
   js.Expression generateLazyInitializer(
-      CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
+      FieldEntity field,
+      HGraph graph,
+      CodegenInputs codegen,
+      JClosedWorld closedWorld,
+      CodegenRegistry registry,
+      ModularNamer namer,
+      ModularEmitter emitter) {
     return measure(() {
-      backend.tracer.traceGraph("codegen", graph);
-      SourceInformation sourceInformation = sourceInformationFactory
-          .createBuilderForContext(work.element)
-          .buildDeclaration(work.element);
-      SsaCodeGenerator codegen = new SsaCodeGenerator(
+      codegen.tracer.traceGraph("codegen", graph);
+      SourceInformation sourceInformation = sourceInformationStrategy
+          .createBuilderForContext(field)
+          .buildDeclaration(field);
+      SsaCodeGenerator codeGenerator = new SsaCodeGenerator(
           this,
-          backend.compiler.options,
-          backend.emitter,
-          backend.nativeCodegenEnqueuer,
-          backend.checkedModeHelpers,
-          backend.oneShotInterceptorData,
-          backend.rtiSubstitutions,
-          backend.rtiEncoder,
-          backend.namer,
-          backend.superMemberData,
-          backend.tracer,
+          _options,
+          emitter,
+          codegen.checkedModeHelpers,
+          codegen.rtiSubstitutions,
+          codegen.rtiEncoder,
+          namer,
+          codegen.tracer,
           closedWorld,
-          work);
-      codegen.visitGraph(graph);
-      return new js.Fun(codegen.parameters, codegen.body)
+          registry);
+      codeGenerator.visitGraph(graph);
+      return new js.Fun(codeGenerator.parameters, codeGenerator.body)
           .withSourceInformation(sourceInformation);
     });
   }
 
   js.Expression generateMethod(
-      CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
+      FunctionEntity method,
+      HGraph graph,
+      CodegenInputs codegen,
+      JClosedWorld closedWorld,
+      CodegenRegistry registry,
+      ModularNamer namer,
+      ModularEmitter emitter) {
     return measure(() {
-      FunctionEntity element = work.element;
-      if (element.asyncMarker != AsyncMarker.SYNC) {
-        work.registry.registerAsyncMarker(element.asyncMarker);
+      if (method.asyncMarker != AsyncMarker.SYNC) {
+        registry.registerAsyncMarker(method.asyncMarker);
       }
-      SsaCodeGenerator codegen = new SsaCodeGenerator(
+      SsaCodeGenerator codeGenerator = new SsaCodeGenerator(
           this,
-          backend.compiler.options,
-          backend.emitter,
-          backend.nativeCodegenEnqueuer,
-          backend.checkedModeHelpers,
-          backend.oneShotInterceptorData,
-          backend.rtiSubstitutions,
-          backend.rtiEncoder,
-          backend.namer,
-          backend.superMemberData,
-          backend.tracer,
+          _options,
+          emitter,
+          codegen.checkedModeHelpers,
+          codegen.rtiSubstitutions,
+          codegen.rtiEncoder,
+          namer,
+          codegen.tracer,
           closedWorld,
-          work);
-      codegen.visitGraph(graph);
-      backend.tracer.traceGraph("codegen", graph);
-      return buildJavaScriptFunction(graph.needsAsyncRewrite, work.element,
-          codegen.parameters, codegen.body);
+          registry);
+      codeGenerator.visitGraph(graph);
+      codegen.tracer.traceGraph("codegen", graph);
+      return buildJavaScriptFunction(graph.needsAsyncRewrite, method,
+          codeGenerator.parameters, codeGenerator.body);
     });
   }
 }
@@ -165,17 +176,14 @@
 
   final CompilerTask _codegenTask;
   final CompilerOptions _options;
-  final CodeEmitterTask _emitter;
-  final NativeCodegenEnqueuer _nativeEnqueuer;
+  final ModularEmitter _emitter;
   final CheckedModeHelpers _checkedModeHelpers;
-  final OneShotInterceptorData _oneShotInterceptorData;
   final RuntimeTypesSubstitutions _rtiSubstitutions;
   final RuntimeTypesEncoder _rtiEncoder;
-  final Namer _namer;
-  final SuperMemberData _superMemberData;
+  final ModularNamer _namer;
   final Tracer _tracer;
   final JClosedWorld _closedWorld;
-  final CodegenWorkItem _work;
+  final CodegenRegistry _registry;
 
   final Set<HInstruction> generateAtUseSite;
   final Set<HInstruction> controlFlowOperators;
@@ -223,16 +231,13 @@
       this._codegenTask,
       this._options,
       this._emitter,
-      this._nativeEnqueuer,
       this._checkedModeHelpers,
-      this._oneShotInterceptorData,
       this._rtiSubstitutions,
       this._rtiEncoder,
       this._namer,
-      this._superMemberData,
       this._tracer,
       this._closedWorld,
-      this._work,
+      this._registry,
       {SourceInformation sourceInformation})
       : declaredLocals = new Set<String>(),
         collectedVariableDeclarations = new Set<String>(),
@@ -246,8 +251,6 @@
         continueAction = new Set<LabelDefinition>(),
         implicitContinueAction = new Set<JumpTarget>();
 
-  CodegenRegistry get _registry => _work.registry;
-
   JCommonElements get _commonElements => _closedWorld.commonElements;
 
   NativeData get _nativeData => _closedWorld.nativeData;
@@ -378,8 +381,7 @@
     runPhase(new SsaTypeKnownRemover());
     runPhase(new SsaTrustedCheckRemover(_options));
     runPhase(new SsaAssignmentChaining(_options, _closedWorld));
-    runPhase(new SsaInstructionMerger(
-        _abstractValueDomain, generateAtUseSite, _superMemberData));
+    runPhase(new SsaInstructionMerger(_abstractValueDomain, generateAtUseSite));
     runPhase(new SsaConditionMerger(generateAtUseSite, controlFlowOperators));
     runPhase(new SsaShareRegionConstants(_options));
 
@@ -617,6 +619,9 @@
 
   js.Expression generateExpressionAssignment(String variableName,
       js.Expression value, SourceInformation sourceInformation) {
+    // TODO(johnniwinther): Introduce a DeferredVariableUse to handle this
+    // in the SSA codegen or let the JS printer handle it fully and remove it
+    // here.
     if (value is js.Binary) {
       js.Binary binary = value;
       String op = binary.op;
@@ -628,14 +633,15 @@
           op == '^' ||
           op == '&' ||
           op == '|') {
-        if (binary.left is js.VariableUse &&
-            (binary.left as js.VariableUse).name == variableName) {
+        js.Expression left = binary.left;
+        if (left is js.VariableUse && left.name == variableName) {
           // We know now, that we can shorten x = x + y into x += y.
           // Also check for the shortcut where y equals 1: x++ and x--.
+          js.Expression right = binary.right;
           if ((op == '+' || op == '-') &&
-              binary.right is js.LiteralNumber &&
-              (binary.right as js.LiteralNumber).value == "1") {
-            return new js.Prefix(op == '+' ? '++' : '--', binary.left);
+              right is js.LiteralNumber &&
+              right.value == "1") {
+            return new js.Prefix(op == '+' ? '++' : '--', left);
           }
           return new js.Assignment.compound(binary.left, op, binary.right);
         }
@@ -687,11 +693,14 @@
     // emit an assignment, because the intTypeCheck just returns its
     // argument.
     bool needsAssignment = true;
-    if (instruction is HTypeConversion) {
-      HTypeConversion typeConversion = instruction;
-      String inputName = variableNames.getName(typeConversion.checkedInput);
-      if (variableNames.getName(instruction) == inputName) {
-        needsAssignment = false;
+    if (instruction is HCheck) {
+      if (instruction is HTypeConversion ||
+          instruction is HPrimitiveCheck ||
+          instruction is HBoolConversion) {
+        String inputName = variableNames.getName(instruction.checkedInput);
+        if (variableNames.getName(instruction) == inputName) {
+          needsAssignment = false;
+        }
       }
     }
     if (instruction is HLocalValue) {
@@ -1555,15 +1564,6 @@
   visitGreaterEqual(HGreaterEqual node) => visitRelational(node, '>=');
 
   @override
-  visitBoolify(HBoolify node) {
-    assert(node.inputs.length == 1);
-    use(node.inputs[0]);
-    push(new js.Binary(
-            '===', pop(), newLiteralBool(true, node.sourceInformation))
-        .withSourceInformation(node.sourceInformation));
-  }
-
-  @override
   visitExit(HExit node) {
     // Don't do anything.
   }
@@ -1816,8 +1816,8 @@
       assert(node.inputs.length == 1);
       _registry.registerSpecializedGetInterceptor(node.interceptedClasses);
       js.Name name = _namer.nameForGetInterceptor(node.interceptedClasses);
-      var isolate = new js.VariableUse(
-          _namer.globalObjectForLibrary(_commonElements.interceptorsLibrary));
+      js.Expression isolate = _namer
+          .readGlobalObjectForLibrary(_commonElements.interceptorsLibrary);
       use(node.receiver);
       List<js.Expression> arguments = <js.Expression>[pop()];
       push(js
@@ -1908,11 +1908,13 @@
   @override
   void visitOneShotInterceptor(HOneShotInterceptor node) {
     List<js.Expression> arguments = visitArguments(node.inputs);
-    var isolate = new js.VariableUse(
-        _namer.globalObjectForLibrary(_commonElements.interceptorsLibrary));
+    js.Expression isolate =
+        _namer.readGlobalObjectForLibrary(_commonElements.interceptorsLibrary);
     Selector selector = node.selector;
-    js.Name methodName = _oneShotInterceptorData.registerOneShotInterceptor(
-        selector, _namer, _closedWorld);
+    Set<ClassEntity> classes =
+        _interceptorData.getInterceptedClassesOn(selector.name, _closedWorld);
+    _registry.registerOneShotInterceptor(selector);
+    js.Name methodName = _namer.nameForOneShotInterceptor(selector, classes);
     push(js
         .propertyCall(isolate, methodName, arguments)
         .withSourceInformation(node.sourceInformation));
@@ -1969,8 +1971,8 @@
       // may know something about the types of closures that need
       // the specific closure call method.
       Selector call = new Selector.callClosureFrom(selector);
-      _registry.registerDynamicUse(
-          new ConstrainedDynamicUse(call, null, node.typeArguments));
+      _registry
+          .registerDynamicUse(new DynamicUse(call, null, node.typeArguments));
     }
     if (target != null) {
       // This is a dynamic invocation which we have found to have a single
@@ -1979,12 +1981,15 @@
       // for this to work.
       assert(selector.applies(target),
           failedAt(node, '$selector does not apply to $target'));
+      assert(!selector.isGetter && !selector.isSetter,
+          "Unexpected direct invocation selector: $selector.");
       _registry.registerStaticUse(new StaticUse.directInvoke(
           target, selector.callStructure, node.typeArguments));
     } else {
-      AbstractValue mask = getOptimizedSelectorFor(node, selector, node.mask);
+      AbstractValue mask =
+          getOptimizedSelectorFor(node, selector, node.receiverType);
       _registry.registerDynamicUse(
-          new ConstrainedDynamicUse(selector, mask, node.typeArguments));
+          new DynamicUse(selector, mask, node.typeArguments));
     }
   }
 
@@ -1997,9 +2002,10 @@
       _registry.registerStaticUse(new StaticUse.directSet(node.element));
     } else {
       Selector selector = node.selector;
-      AbstractValue mask = getOptimizedSelectorFor(node, selector, node.mask);
+      AbstractValue mask =
+          getOptimizedSelectorFor(node, selector, node.receiverType);
       _registry.registerDynamicUse(
-          new ConstrainedDynamicUse(selector, mask, node.typeArguments));
+          new DynamicUse(selector, mask, node.typeArguments));
     }
   }
 
@@ -2014,9 +2020,10 @@
       _registry.registerStaticUse(new StaticUse.directGet(node.element));
     } else {
       Selector selector = node.selector;
-      AbstractValue mask = getOptimizedSelectorFor(node, selector, node.mask);
+      AbstractValue mask =
+          getOptimizedSelectorFor(node, selector, node.receiverType);
       _registry.registerDynamicUse(
-          new ConstrainedDynamicUse(selector, mask, node.typeArguments));
+          new DynamicUse(selector, mask, node.typeArguments));
     }
   }
 
@@ -2051,8 +2058,8 @@
     // TODO(kasperl): If we have a typed selector for the call, we
     // may know something about the types of closures that need
     // the specific closure call method.
-    _registry.registerDynamicUse(
-        new ConstrainedDynamicUse(call, null, node.typeArguments));
+    _registry
+        .registerDynamicUse(new DynamicUse(call, null, node.typeArguments));
   }
 
   @override
@@ -2092,12 +2099,23 @@
       push(js.js('# || #', [arguments[0], right]).withSourceInformation(
           node.sourceInformation));
     } else {
-      CallStructure callStructure = new CallStructure.unnamed(
-          arguments.length, node.typeArguments.length);
-      _registry.registerStaticUse(element.isConstructor
-          ? new StaticUse.constructorInvoke(element, callStructure)
-          : new StaticUse.staticInvoke(
-              element, callStructure, node.typeArguments));
+      StaticUse staticUse;
+      if (element.isConstructor) {
+        CallStructure callStructure = new CallStructure.unnamed(
+            arguments.length, node.typeArguments.length);
+        staticUse = new StaticUse.constructorInvoke(element, callStructure);
+      } else if (element.isGetter) {
+        staticUse = new StaticUse.staticGet(element);
+      } else if (element.isSetter) {
+        staticUse = new StaticUse.staticSet(element);
+      } else {
+        assert(element.isFunction);
+        CallStructure callStructure = new CallStructure.unnamed(
+            arguments.length, node.typeArguments.length);
+        staticUse = new StaticUse.staticInvoke(
+            element, callStructure, node.typeArguments);
+      }
+      _registry.registerStaticUse(staticUse);
       push(_emitter.staticFunctionAccess(element));
       push(new js.Call(pop(), arguments,
           sourceInformation: node.sourceInformation));
@@ -2108,26 +2126,45 @@
   visitInvokeSuper(HInvokeSuper node) {
     MemberEntity superElement = node.element;
     ClassEntity superClass = superElement.enclosingClass;
+    Selector selector = node.selector;
+    bool useAliasedSuper = canUseAliasedSuperMember(superElement, selector);
+    if (selector.isGetter) {
+      if (superElement.isField || superElement.isGetter) {
+        _registry.registerStaticUse(new StaticUse.superGet(superElement));
+      } else {
+        _registry.registerStaticUse(new StaticUse.superTearOff(node.element));
+      }
+    } else if (selector.isSetter) {
+      if (superElement.isField) {
+        _registry.registerStaticUse(new StaticUse.superFieldSet(superElement));
+      } else {
+        assert(superElement.isSetter);
+        _registry.registerStaticUse(new StaticUse.superSetterSet(superElement));
+      }
+    } else {
+      if (useAliasedSuper) {
+        _registry.registerStaticUse(new StaticUse.superInvoke(
+            superElement, new CallStructure.unnamed(node.inputs.length)));
+      } else {
+        _registry.registerStaticUse(new StaticUse.superInvoke(
+            superElement, new CallStructure.unnamed(node.inputs.length - 1)));
+      }
+    }
+
     if (superElement.isField) {
       js.Name fieldName = _namer.instanceFieldPropertyName(superElement);
       use(node.inputs[0]);
       js.PropertyAccess access = new js.PropertyAccess(pop(), fieldName)
           .withSourceInformation(node.sourceInformation);
       if (node.isSetter) {
-        _registry.registerStaticUse(superElement.isSetter
-            ? new StaticUse.superSetterSet(superElement)
-            : new StaticUse.superFieldSet(superElement));
         use(node.value);
         push(new js.Assignment(access, pop())
             .withSourceInformation(node.sourceInformation));
       } else {
-        _registry.registerStaticUse(new StaticUse.superGet(superElement));
         push(access);
       }
     } else {
-      Selector selector = node.selector;
-      if (!_superMemberData.maybeRegisterAliasedSuperMember(
-          superElement, selector)) {
+      if (!useAliasedSuper) {
         js.Name methodName;
         if (selector.isGetter && !superElement.isGetter) {
           // If this is a tear-off, register the fact that a tear-off closure
@@ -2139,13 +2176,11 @@
               new CallStructure.unnamed(
                   node.inputs.length, node.typeArguments.length),
               node.typeArguments));
-          _registry.registerStaticUse(new StaticUse.superTearOff(node.element));
           methodName = _namer.invocationName(selector);
         } else {
           methodName = _namer.instanceMethodName(superElement);
         }
-        _registry.registerStaticUse(new StaticUse.superInvoke(
-            superElement, new CallStructure.unnamed(node.inputs.length)));
+
         push(js.js('#.#.call(#)', [
           _emitter.prototypeAccess(superClass, hasBeenInstantiated: true),
           methodName,
@@ -2153,8 +2188,6 @@
         ]).withSourceInformation(node.sourceInformation));
       } else {
         use(node.receiver);
-        _registry.registerStaticUse(new StaticUse.superInvoke(
-            superElement, new CallStructure.unnamed(node.inputs.length - 1)));
         push(js.js('#.#(#)', [
           pop(),
           _namer.aliasedSuperMemberPropertyName(superElement),
@@ -2241,8 +2274,7 @@
   void registerForeignTypes(HForeign node) {
     NativeBehavior nativeBehavior = node.nativeBehavior;
     if (nativeBehavior == null) return;
-    _nativeEnqueuer.registerNativeBehavior(
-        _registry.worldImpact, nativeBehavior, node);
+    _registry.registerNativeBehavior(nativeBehavior);
   }
 
   @override
@@ -2388,11 +2420,6 @@
         use(input.inputs[0]);
       } else if (input is HIdentity) {
         emitIdentityComparison(input, sourceInformation, inverse: true);
-      } else if (input is HBoolify) {
-        use(input.inputs[0]);
-        push(new js.Binary(
-                "!==", pop(), newLiteralBool(true, input.sourceInformation))
-            .withSourceInformation(sourceInformation));
       } else if (canGenerateOptimizedComparison(input)) {
         HRelational relational = input;
         constant_system.BinaryOperation operation = relational.operation();
@@ -2614,7 +2641,7 @@
     assert(element.isFunction || element.isField);
     if (element.isFunction) {
       push(_emitter
-          .isolateStaticClosureAccess(element)
+          .staticClosureAccess(element)
           .withSourceInformation(node.sourceInformation));
       _registry.registerStaticUse(new StaticUse.staticTearOff(element));
     } else {
@@ -3080,55 +3107,9 @@
         negative: negative);
   }
 
-  js.Expression generateReceiverOrArgumentTypeTest(HTypeConversion node) {
-    DartType type = node.typeExpression;
-    HInstruction input = node.checkedInput;
-    AbstractValue checkedType = node.checkedType;
-    // This path is no longer used for indexable primitive types.
-    assert(_abstractValueDomain.isJsIndexable(checkedType).isPotentiallyFalse);
-    // Figure out if it is beneficial to use a null check.  V8 generally prefers
-    // 'typeof' checks, but for integers we cannot compile this test into a
-    // single typeof check so the null check is cheaper.
-    if (type == _commonElements.numType) {
-      // input is !num
-      checkNum(input, '!==', input.sourceInformation);
-      return pop();
-    } else if (type == _commonElements.boolType) {
-      // input is !bool
-      checkBool(input, '!==', input.sourceInformation);
-      return pop();
-    }
-    throw failedAt(input, 'Unexpected check: $type.');
-  }
-
   @override
   void visitTypeConversion(HTypeConversion node) {
-    if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
-      js.Expression test = generateReceiverOrArgumentTypeTest(node);
-      js.Block oldContainer = currentContainer;
-      js.Statement body = new js.Block.empty();
-      currentContainer = body;
-      if (node.isArgumentTypeCheck) {
-        generateThrowWithHelper(
-            _commonElements.throwIllegalArgumentException, node.checkedInput,
-            sourceInformation: node.sourceInformation);
-      } else if (node.isReceiverTypeCheck) {
-        use(node.checkedInput);
-        js.Name methodName =
-            _namer.invocationName(node.receiverTypeCheckSelector);
-        js.Expression call = js.propertyCall(pop(), methodName,
-            []).withSourceInformation(node.sourceInformation);
-        pushStatement(
-            new js.Return(call).withSourceInformation(node.sourceInformation));
-      }
-      currentContainer = oldContainer;
-      body = unwrapStatement(body);
-      pushStatement(new js.If.noElse(test, body)
-          .withSourceInformation(node.sourceInformation));
-      return;
-    }
-
-    assert(node.isCheckedModeCheck || node.isCastTypeCheck);
+    assert(node.isTypeCheck || node.isCastCheck);
     DartType type = node.typeExpression;
     assert(!type.isTypedef);
     assert(!type.isDynamic);
@@ -3141,14 +3122,9 @@
     }
     _registry.registerTypeUse(new TypeUse.isCheck(type));
 
-    CheckedModeHelper helper;
-    if (node.isBooleanConversionCheck) {
-      helper = const CheckedModeHelper('boolConversionCheck');
-    } else {
-      helper = _checkedModeHelpers.getCheckedModeHelper(
-          type, _closedWorld.commonElements,
-          typeCast: node.isCastTypeCheck);
-    }
+    CheckedModeHelper helper = _checkedModeHelpers.getCheckedModeHelper(
+        type, _closedWorld.commonElements,
+        typeCast: node.isCastCheck);
 
     StaticUse staticUse = helper.getStaticUse(_closedWorld.commonElements);
     _registry.registerStaticUse(staticUse);
@@ -3162,6 +3138,66 @@
   }
 
   @override
+  void visitPrimitiveCheck(HPrimitiveCheck node) {
+    js.Expression test = _generateReceiverOrArgumentTypeTest(node);
+    js.Block oldContainer = currentContainer;
+    js.Statement body = new js.Block.empty();
+    currentContainer = body;
+    if (node.isArgumentTypeCheck) {
+      generateThrowWithHelper(
+          _commonElements.throwIllegalArgumentException, node.checkedInput,
+          sourceInformation: node.sourceInformation);
+    } else if (node.isReceiverTypeCheck) {
+      use(node.checkedInput);
+      js.Name methodName =
+          _namer.invocationName(node.receiverTypeCheckSelector);
+      js.Expression call = js.propertyCall(
+          pop(), methodName, []).withSourceInformation(node.sourceInformation);
+      pushStatement(
+          new js.Return(call).withSourceInformation(node.sourceInformation));
+    }
+    currentContainer = oldContainer;
+    body = unwrapStatement(body);
+    pushStatement(new js.If.noElse(test, body)
+        .withSourceInformation(node.sourceInformation));
+  }
+
+  js.Expression _generateReceiverOrArgumentTypeTest(HPrimitiveCheck node) {
+    DartType type = node.typeExpression;
+    HInstruction input = node.checkedInput;
+    AbstractValue checkedType = node.checkedType;
+    // This path is no longer used for indexable primitive types.
+    assert(_abstractValueDomain.isJsIndexable(checkedType).isPotentiallyFalse);
+    // Figure out if it is beneficial to use a null check.  V8 generally prefers
+    // 'typeof' checks, but for integers we cannot compile this test into a
+    // single typeof check so the null check is cheaper.
+    if (type == _commonElements.numType) {
+      // input is !num
+      checkNum(input, '!==', input.sourceInformation);
+      return pop();
+    }
+    if (type == _commonElements.boolType) {
+      // input is !bool
+      checkBool(input, '!==', input.sourceInformation);
+      return pop();
+    }
+    throw failedAt(input, 'Unexpected check: $type.');
+  }
+
+  @override
+  void visitBoolConversion(HBoolConversion node) {
+    _registry.registerTypeUse(new TypeUse.isCheck(_commonElements.boolType));
+    CheckedModeHelper helper = const CheckedModeHelper('boolConversionCheck');
+    StaticUse staticUse = helper.getStaticUse(_commonElements);
+    _registry.registerStaticUse(staticUse);
+    use(node.checkedInput);
+    List<js.Expression> arguments = [pop()];
+    push(
+        new js.Call(_emitter.staticFunctionAccess(staticUse.element), arguments)
+            .withSourceInformation(node.sourceInformation));
+  }
+
+  @override
   void visitTypeKnown(HTypeKnown node) {
     // [HTypeKnown] instructions are removed before generating code.
     assert(false);
@@ -3246,9 +3282,7 @@
       case TypeInfoExpressionKind.COMPLETE:
         int index = 0;
         js.Expression result = _rtiEncoder.getTypeRepresentation(
-            _emitter.emitter,
-            type,
-            (TypeVariableType variable) => arguments[index++]);
+            _emitter, type, (TypeVariableType variable) => arguments[index++]);
         assert(
             index == node.inputs.length,
             "Not all input is read for type ${type}: "
@@ -3296,4 +3330,34 @@
   void visitRef(HRef node) {
     visit(node.value);
   }
+
+  @override
+  visitIsTest(HIsTest node) {
+    throw UnimplementedError('SsaCodeGenerator.visitIsTest');
+  }
+
+  @override
+  visitAsCheck(HAsCheck node) {
+    throw UnimplementedError('SsaCodeGenerator.visitAsCheck');
+  }
+
+  @override
+  visitSubtypeCheck(HSubtypeCheck node) {
+    throw UnimplementedError('SsaCodeGenerator.visitSubtypeCheck');
+  }
+
+  @override
+  visitLoadType(HLoadType node) {
+    throw UnimplementedError('SsaCodeGenerator.visitLoadType');
+  }
+
+  @override
+  visitTypeEval(HTypeEval node) {
+    throw UnimplementedError('SsaCodeGenerator.visitTypeEval');
+  }
+
+  @override
+  visitTypeBind(HTypeBind node) {
+    throw UnimplementedError('SsaCodeGenerator.visitTypeBind');
+  }
 }
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index 4ad0571..8ffd0ed 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -5,7 +5,6 @@
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../inferrer/abstract_value_domain.dart';
-import '../js_backend/js_backend.dart';
 import '../js_backend/interceptor_data.dart';
 import '../options.dart';
 import '../universe/selector.dart' show Selector;
@@ -13,6 +12,15 @@
 import 'codegen.dart' show CodegenPhase;
 import 'nodes.dart';
 
+/// Returns `true` if the invocation of [selector] on [member] can use an
+/// aliased member.
+///
+/// Invoking a super getter isn't supported, this would require changes to
+/// compact field descriptors in the emitter.
+bool canUseAliasedSuperMember(MemberEntity member, Selector selector) {
+  return !selector.isGetter;
+}
+
 /// Replaces some instructions with specialized versions to make codegen easier.
 /// Caches codegen information on nodes.
 class SsaInstructionSelection extends HBaseVisitor with CodegenPhase {
@@ -136,7 +144,7 @@
   @override
   HInstruction visitInvokeDynamic(HInvokeDynamic node) {
     if (node.isInterceptedCall) {
-      tryReplaceInterceptorWithDummy(node, node.selector, node.mask);
+      tryReplaceInterceptorWithDummy(node, node.selector, node.receiverType);
     }
     return node;
   }
@@ -190,9 +198,8 @@
       if (_interceptorData.isInterceptedSelector(selector) &&
           !_interceptorData.isInterceptedMixinSelector(
               selector, mask, _closedWorld)) {
-        ConstantValue constant = new SyntheticConstantValue(
-            SyntheticConstantKind.DUMMY_INTERCEPTOR,
-            receiverArgument.instructionType);
+        ConstantValue constant =
+            new DummyInterceptorConstantValue(receiverArgument.instructionType);
         HConstant dummy = graph.addConstant(constant, _closedWorld);
         receiverArgument.usedBy.remove(node);
         node.inputs[1] = dummy;
@@ -373,6 +380,8 @@
     for (HInstruction user in instruction.usedBy) {
       if (user is HTypeConversion) {
         user.inputType = instruction.instructionType;
+      } else if (user is HPrimitiveCheck) {
+        user.inputType = instruction.instructionType;
       }
     }
     instruction.block.rewrite(instruction, instruction.checkedInput);
@@ -380,7 +389,7 @@
   }
 }
 
-/// Remove [HTypeConversion] instructions from the graph in '--trust-primitives'
+/// Remove [HPrimitiveCheck] instructions from the graph in '--trust-primitives'
 /// mode.
 class SsaTrustedCheckRemover extends HBaseVisitor with CodegenPhase {
   final CompilerOptions _options;
@@ -404,11 +413,15 @@
   }
 
   @override
-  void visitTypeConversion(HTypeConversion instruction) {
-    if (instruction.isReceiverTypeCheck || instruction.isArgumentTypeCheck) {
-      instruction.block.rewrite(instruction, instruction.checkedInput);
-      instruction.block.remove(instruction);
-    }
+  void visitPrimitiveCheck(HPrimitiveCheck instruction) {
+    instruction.block.rewrite(instruction, instruction.checkedInput);
+    instruction.block.remove(instruction);
+  }
+
+  @override
+  void visitBoolConversion(HBoolConversion instruction) {
+    instruction.block.rewrite(instruction, instruction.checkedInput);
+    instruction.block.remove(instruction);
   }
 }
 
@@ -590,7 +603,6 @@
 ///   t2 = add(4, 3);
 class SsaInstructionMerger extends HBaseVisitor with CodegenPhase {
   final AbstractValueDomain _abstractValueDomain;
-  final SuperMemberData _superMemberData;
 
   /// List of [HInstruction] that the instruction merger expects in
   /// order when visiting the inputs of an instruction.
@@ -607,8 +619,7 @@
     generateAtUseSite.add(instruction);
   }
 
-  SsaInstructionMerger(
-      this._abstractValueDomain, this.generateAtUseSite, this._superMemberData);
+  SsaInstructionMerger(this._abstractValueDomain, this.generateAtUseSite);
 
   @override
   void visitGraph(HGraph graph) {
@@ -694,7 +705,7 @@
     // after first access if we use lazy initialization.
     // In this case, we therefore don't allow the receiver (the first argument)
     // to be generated at use site, and only analyze all other arguments.
-    if (!_superMemberData.canUseAliasedSuperMember(superMethod, selector)) {
+    if (!canUseAliasedSuperMember(superMethod, selector)) {
       analyzeInputs(instruction, 1);
     } else {
       super.visitInvokeSuper(instruction);
@@ -738,16 +749,15 @@
 
   @override
   void visitTypeConversion(HTypeConversion instruction) {
-    if (!instruction.isArgumentTypeCheck && !instruction.isReceiverTypeCheck) {
-      assert(instruction.isCheckedModeCheck || instruction.isCastTypeCheck);
-      // Checked mode checks and cast checks compile to code that
-      // only use their input once, so we can safely visit them
-      // and try to merge the input.
-      visitInstruction(instruction);
-    }
+    // Type checks and cast checks compile to code that only use their input
+    // once, so we can safely visit them and try to merge the input.
+    visitInstruction(instruction);
   }
 
   @override
+  void visitPrimitiveCheck(HPrimitiveCheck instruction) {}
+
+  @override
   void visitTypeKnown(HTypeKnown instruction) {
     // [HTypeKnown] instructions are removed before code generation.
     assert(false);
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
deleted file mode 100644
index 4b5d9cf..0000000
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ /dev/null
@@ -1,295 +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.
-
-import '../common/codegen.dart' show CodegenRegistry;
-import '../common_elements.dart';
-import '../compiler.dart';
-import '../deferred_load.dart';
-import '../diagnostics/diagnostic_listener.dart';
-import '../elements/entities.dart' show Entity, Local, MemberEntity;
-import '../elements/jumps.dart';
-import '../elements/types.dart';
-import '../inferrer/abstract_value_domain.dart';
-import '../inferrer/types.dart';
-import '../io/source_information.dart';
-import '../js_backend/backend.dart';
-import '../js_backend/backend_usage.dart';
-import '../js_backend/constant_handler_javascript.dart';
-import '../js_backend/interceptor_data.dart';
-import '../js_backend/inferred_data.dart';
-import '../js_backend/namer.dart';
-import '../js_backend/native_data.dart';
-import '../js_backend/runtime_types.dart';
-import '../js_emitter/code_emitter_task.dart';
-import '../options.dart';
-import '../world.dart' show JClosedWorld;
-import 'jump_handler.dart';
-import 'locals_handler.dart';
-import 'nodes.dart';
-import 'type_builder.dart';
-
-/// Base class for objects that build up an SSA graph.
-///
-/// This contains helpers for building the graph and tracking information about
-/// the current state of the graph being built.
-abstract class GraphBuilder {
-  /// Holds the resulting SSA graph.
-  final HGraph graph = new HGraph();
-
-  // TODO(het): remove this
-  /// A reference to the compiler.
-  Compiler get compiler;
-
-  /// True if the builder is processing nodes inside a try statement. This is
-  /// important for generating control flow out of a try block like returns or
-  /// breaks.
-  bool inTryStatement = false;
-
-  /// The JavaScript backend we are targeting in this compilation.
-  JavaScriptBackend get backend;
-
-  CodegenRegistry get registry;
-
-  JClosedWorld get closedWorld;
-
-  AbstractValueDomain get abstractValueDomain =>
-      closedWorld.abstractValueDomain;
-
-  DiagnosticReporter get reporter => backend.reporter;
-
-  CompilerOptions get options => compiler.options;
-
-  JCommonElements get commonElements => closedWorld.commonElements;
-
-  CodeEmitterTask get emitter => backend.emitter;
-
-  GlobalTypeInferenceResults get globalInferenceResults;
-
-  NativeData get nativeData => closedWorld.nativeData;
-
-  InterceptorData get interceptorData => closedWorld.interceptorData;
-
-  BackendUsage get backendUsage => closedWorld.backendUsage;
-
-  Namer get namer => backend.namer;
-
-  RuntimeTypesNeed get rtiNeed => closedWorld.rtiNeed;
-
-  JavaScriptConstantCompiler get constants => backend.constants;
-
-  RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder;
-
-  InferredData get inferredData => globalInferenceResults.inferredData;
-
-  DeferredLoadTask get deferredLoadTask => compiler.deferredLoadTask;
-
-  DartTypes get types => closedWorld.dartTypes;
-
-  /// Used to track the locals while building the graph.
-  LocalsHandler localsHandler;
-
-  /// A stack of instructions.
-  ///
-  /// We build the SSA graph by simulating a stack machine.
-  List<HInstruction> stack = <HInstruction>[];
-
-  /// The count of nested loops we are currently building.
-  ///
-  /// The loop nesting is consulted when inlining a function invocation. The
-  /// inlining heuristics take this information into account.
-  int loopDepth = 0;
-
-  /// A mapping from jump targets to their handlers.
-  Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{};
-
-  void push(HInstruction instruction) {
-    add(instruction);
-    stack.add(instruction);
-  }
-
-  HInstruction pop() {
-    return stack.removeLast();
-  }
-
-  /// Pops the most recent instruction from the stack and 'boolifies' it.
-  ///
-  /// Boolification is checking if the value is '=== true'.
-  HInstruction popBoolified();
-
-  /// Pushes a boolean checking [expression] against null.
-  pushCheckNull(HInstruction expression) {
-    push(new HIdentity(expression, graph.addConstantNull(closedWorld), null,
-        abstractValueDomain.boolType));
-  }
-
-  void dup() {
-    stack.add(stack.last);
-  }
-
-  HBasicBlock _current;
-
-  /// The current block to add instructions to. Might be null, if we are
-  /// visiting dead code, but see [isReachable].
-  HBasicBlock get current => _current;
-
-  void set current(c) {
-    isReachable = c != null;
-    _current = c;
-  }
-
-  /// The most recently opened block. Has the same value as [current] while
-  /// the block is open, but unlike [current], it isn't cleared when the
-  /// current block is closed.
-  HBasicBlock lastOpenedBlock;
-
-  /// Indicates whether the current block is dead (because it has a throw or a
-  /// return further up). If this is false, then [current] may be null. If the
-  /// block is dead then it may also be aborted, but for simplicity we only
-  /// abort on statement boundaries, not in the middle of expressions. See
-  /// [isAborted].
-  bool isReachable = true;
-
-  HLocalValue lastAddedParameter;
-
-  Map<Local, HInstruction> parameters = <Local, HInstruction>{};
-  Set<Local> elidedParameters;
-
-  HBasicBlock addNewBlock() {
-    HBasicBlock block = graph.addNewBlock();
-    // If adding a new block during building of an expression, it is due to
-    // conditional expressions or short-circuit logical operators.
-    return block;
-  }
-
-  void open(HBasicBlock block) {
-    block.open();
-    current = block;
-    lastOpenedBlock = block;
-  }
-
-  HBasicBlock close(HControlFlow end) {
-    HBasicBlock result = current;
-    current.close(end);
-    current = null;
-    return result;
-  }
-
-  HBasicBlock closeAndGotoExit(HControlFlow end) {
-    HBasicBlock result = current;
-    current.close(end);
-    current = null;
-    result.addSuccessor(graph.exit);
-    return result;
-  }
-
-  void goto(HBasicBlock from, HBasicBlock to) {
-    from.close(new HGoto(abstractValueDomain));
-    from.addSuccessor(to);
-  }
-
-  bool isAborted() {
-    return current == null;
-  }
-
-  /// Creates a new block, transitions to it from any current block, and
-  /// opens the new block.
-  HBasicBlock openNewBlock() {
-    HBasicBlock newBlock = addNewBlock();
-    if (!isAborted()) goto(current, newBlock);
-    open(newBlock);
-    return newBlock;
-  }
-
-  void add(HInstruction instruction) {
-    current.add(instruction);
-  }
-
-  HLocalValue addParameter(Entity parameter, AbstractValue type,
-      {bool isElided: false}) {
-    HLocalValue result = isElided
-        ? new HLocalValue(parameter, type)
-        : new HParameterValue(parameter, type);
-    if (lastAddedParameter == null) {
-      graph.entry.addBefore(graph.entry.first, result);
-    } else {
-      graph.entry.addAfter(lastAddedParameter, result);
-    }
-    lastAddedParameter = result;
-    return result;
-  }
-
-  HSubGraphBlockInformation wrapStatementGraph(SubGraph statements) {
-    if (statements == null) return null;
-    return new HSubGraphBlockInformation(statements);
-  }
-
-  HSubExpressionBlockInformation wrapExpressionGraph(SubExpression expression) {
-    if (expression == null) return null;
-    return new HSubExpressionBlockInformation(expression);
-  }
-
-  /// Returns the current source element.
-  ///
-  /// The returned element is a declaration element.
-  MemberEntity get sourceElement;
-
-  HLiteralList buildLiteralList(List<HInstruction> inputs) {
-    return new HLiteralList(inputs, abstractValueDomain.growableListType);
-  }
-
-  HInstruction callSetRuntimeTypeInfoWithTypeArguments(
-      InterfaceType type,
-      List<HInstruction> rtiInputs,
-      HInstruction newObject,
-      SourceInformation sourceInformation) {
-    if (!rtiNeed.classNeedsTypeArguments(type.element)) {
-      return newObject;
-    }
-
-    HInstruction typeInfo = new HTypeInfoExpression(
-        TypeInfoExpressionKind.INSTANCE,
-        closedWorld.elementEnvironment.getThisType(type.element),
-        rtiInputs,
-        abstractValueDomain.dynamicType);
-    add(typeInfo);
-    return callSetRuntimeTypeInfo(typeInfo, newObject, sourceInformation);
-  }
-
-  /// Called when control flow is about to change, in which case we need to
-  /// specify special successors if we are already in a try/catch/finally block.
-  void handleInTryStatement() {
-    if (!inTryStatement) return;
-    HBasicBlock block = close(new HExitTry(abstractValueDomain));
-    HBasicBlock newBlock = graph.addNewBlock();
-    block.addSuccessor(newBlock);
-    open(newBlock);
-  }
-
-  HInstruction callSetRuntimeTypeInfo(HInstruction typeInfo,
-      HInstruction newObject, SourceInformation sourceInformation);
-
-  /// The element for which this SSA builder is being used.
-  MemberEntity get targetElement;
-  TypeBuilder get typeBuilder;
-
-  /// Helper to implement JS_GET_FLAG.
-  ///
-  /// The concrete SSA graph builder will extract a flag parameter from the
-  /// JS_GET_FLAG call and then push a boolean result onto the stack. This
-  /// function provides the boolean value corresponding to the given [flagName].
-  /// If [flagName] is not recognized, this function returns `null` and the
-  /// concrete SSA builder reports an error.
-  bool getFlagValue(String flagName) {
-    switch (flagName) {
-      case 'MINIFIED':
-        return options.enableMinification;
-      case 'MUST_RETAIN_METADATA':
-        return false;
-      case 'USE_CONTENT_SECURITY_POLICY':
-        return options.useContentSecurityPolicy;
-      default:
-        return null;
-    }
-  }
-}
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index 098809b..a16575c 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -370,7 +370,7 @@
         HOneShotInterceptor oneShotInterceptor = new HOneShotInterceptor(
             _abstractValueDomain,
             user.selector,
-            user.mask,
+            user.receiverType,
             inputs,
             user.instructionType,
             user.typeArguments,
@@ -447,12 +447,12 @@
     if (constant == null) return false;
 
     Selector selector = node.selector;
-    AbstractValue mask = node.mask;
+    AbstractValue receiverType = node.receiverType;
     HInstruction instruction;
     if (selector.isGetter) {
       instruction = new HInvokeDynamicGetter(
           selector,
-          mask,
+          receiverType,
           node.element,
           <HInstruction>[constant, node.inputs[1]],
           true,
@@ -461,7 +461,7 @@
     } else if (selector.isSetter) {
       instruction = new HInvokeDynamicSetter(
           selector,
-          mask,
+          receiverType,
           node.element,
           <HInstruction>[constant, node.inputs[1], node.inputs[2]],
           true,
@@ -470,7 +470,7 @@
     } else {
       List<HInstruction> inputs = new List<HInstruction>.from(node.inputs);
       inputs[0] = constant;
-      instruction = new HInvokeDynamicMethod(selector, mask, inputs,
+      instruction = new HInvokeDynamicMethod(selector, receiverType, inputs,
           node.instructionType, node.typeArguments, node.sourceInformation,
           isIntercepted: true);
     }
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index 0601adb..d0eb67d 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -29,8 +29,8 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JClosedWorld closedWorld) {
-    return AbstractValueFactory.inferredTypeForSelector(
-        instruction.selector, instruction.mask, results);
+    return AbstractValueFactory.inferredResultTypeForSelector(
+        instruction.selector, instruction.receiverType, results);
   }
 
   HInstruction tryConvertToBuiltin(
@@ -212,8 +212,9 @@
     }
     AbstractValue receiverType =
         instruction.getDartReceiver(closedWorld).instructionType;
-    AbstractValue elementType = AbstractValueFactory.inferredTypeForSelector(
-        instruction.selector, receiverType, results);
+    AbstractValue elementType =
+        AbstractValueFactory.inferredResultTypeForSelector(
+            instruction.selector, receiverType, results);
     if (abstractValueDomain.isTypedArray(receiverType).isDefinitelyTrue) {
       elementType = abstractValueDomain.excludeNull(elementType);
     }
diff --git a/pkg/compiler/lib/src/ssa/jump_handler.dart b/pkg/compiler/lib/src/ssa/jump_handler.dart
index df6a83e..767df33 100644
--- a/pkg/compiler/lib/src/ssa/jump_handler.dart
+++ b/pkg/compiler/lib/src/ssa/jump_handler.dart
@@ -4,9 +4,10 @@
 
 import '../common.dart';
 import '../elements/jumps.dart';
+import '../inferrer/abstract_value_domain.dart';
 import '../io/source_information.dart';
 
-import 'graph_builder.dart';
+import 'builder_kernel.dart';
 import 'locals_handler.dart';
 import 'nodes.dart';
 
@@ -20,7 +21,7 @@
 }
 
 abstract class JumpHandler {
-  factory JumpHandler(GraphBuilder builder, JumpTarget target) {
+  factory JumpHandler(KernelSsaGraphBuilder builder, JumpTarget target) {
     return new TargetJumpHandler(builder, target);
   }
   void generateBreak(SourceInformation sourceInformation,
@@ -81,28 +82,31 @@
 /// Breaks are always forward jumps. Continues in loops are implemented as
 /// breaks of the body. Continues in switches is currently not handled.
 class TargetJumpHandler implements JumpHandler {
-  final GraphBuilder builder;
+  final KernelSsaGraphBuilder builder;
   @override
   final JumpTarget target;
   final List<_JumpHandlerEntry> jumps;
 
-  TargetJumpHandler(GraphBuilder builder, this.target)
+  TargetJumpHandler(KernelSsaGraphBuilder builder, this.target)
       : this.builder = builder,
         jumps = <_JumpHandlerEntry>[] {
     assert(builder.jumpTargets[target] == null);
     builder.jumpTargets[target] = this;
   }
 
+  AbstractValueDomain get _abstractValueDomain =>
+      builder.closedWorld.abstractValueDomain;
+
   @override
   void generateBreak(SourceInformation sourceInformation,
       [LabelDefinition label]) {
     HInstruction breakInstruction;
     if (label == null) {
       breakInstruction =
-          new HBreak(builder.abstractValueDomain, target, sourceInformation);
+          new HBreak(_abstractValueDomain, target, sourceInformation);
     } else {
-      breakInstruction = new HBreak.toLabel(
-          builder.abstractValueDomain, label, sourceInformation);
+      breakInstruction =
+          new HBreak.toLabel(_abstractValueDomain, label, sourceInformation);
     }
     LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
     builder.close(breakInstruction);
@@ -115,10 +119,10 @@
     HInstruction continueInstruction;
     if (label == null) {
       continueInstruction =
-          new HContinue(builder.abstractValueDomain, target, sourceInformation);
+          new HContinue(_abstractValueDomain, target, sourceInformation);
     } else {
-      continueInstruction = new HContinue.toLabel(
-          builder.abstractValueDomain, label, sourceInformation);
+      continueInstruction =
+          new HContinue.toLabel(_abstractValueDomain, label, sourceInformation);
       // Switch case continue statements must be handled by the
       // [SwitchCaseJumpHandler].
       assert(!label.target.isSwitchCase);
@@ -182,7 +186,7 @@
   /// switch case loop.
   final Map<JumpTarget, int> targetIndexMap = new Map<JumpTarget, int>();
 
-  SwitchCaseJumpHandler(GraphBuilder builder, JumpTarget target)
+  SwitchCaseJumpHandler(KernelSsaGraphBuilder builder, JumpTarget target)
       : super(builder, target);
 
   @override
@@ -194,7 +198,7 @@
       // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
 
       HInstruction breakInstruction = new HBreak(
-          builder.abstractValueDomain, target, sourceInformation,
+          _abstractValueDomain, target, sourceInformation,
           breakSwitchContinueLoop: true);
       LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
       builder.close(breakInstruction);
@@ -223,7 +227,7 @@
 
       assert(label.target.labels.contains(label));
       HInstruction continueInstruction =
-          new HContinue(builder.abstractValueDomain, target, sourceInformation);
+          new HContinue(_abstractValueDomain, target, sourceInformation);
       LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
       builder.close(continueInstruction);
       jumps.add(new _JumpHandlerEntry(continueInstruction, locals));
diff --git a/pkg/compiler/lib/src/ssa/kernel_string_builder.dart b/pkg/compiler/lib/src/ssa/kernel_string_builder.dart
index e30817c..0d8a57a 100644
--- a/pkg/compiler/lib/src/ssa/kernel_string_builder.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_string_builder.dart
@@ -5,6 +5,7 @@
 import 'package:kernel/ast.dart' as ir;
 
 import '../common.dart';
+import '../inferrer/abstract_value_domain.dart';
 import 'builder_kernel.dart';
 import 'nodes.dart';
 
@@ -17,6 +18,9 @@
 
   KernelStringBuilder(this.builder);
 
+  AbstractValueDomain get _abstractValueDomain =>
+      builder.closedWorld.abstractValueDomain;
+
   @override
   void defaultNode(ir.Node node) {
     failedAt(CURRENT_ELEMENT_SPANNABLE, 'Unexpected node: $node');
@@ -33,7 +37,7 @@
     //      conversions.
     //   2. The value can be primitive, because the library stringifier has
     //      fast-path code for most primitives.
-    if (expression.isPrimitive(builder.abstractValueDomain).isPotentiallyTrue) {
+    if (expression.isPrimitive(_abstractValueDomain).isPotentiallyTrue) {
       append(stringify(expression));
       return;
     }
@@ -57,14 +61,14 @@
 
   HInstruction concat(HInstruction left, HInstruction right) {
     HInstruction instruction =
-        new HStringConcat(left, right, builder.abstractValueDomain.stringType);
+        new HStringConcat(left, right, _abstractValueDomain.stringType);
     builder.add(instruction);
     return instruction;
   }
 
   HInstruction stringify(HInstruction expression) {
     HInstruction instruction =
-        new HStringify(expression, builder.abstractValueDomain.stringType)
+        new HStringify(expression, _abstractValueDomain.stringType)
           ..sourceInformation = expression.sourceInformation;
     builder.add(instruction);
     return instruction;
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index 9c08d57..de63ecb 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -15,7 +15,7 @@
 import '../js_model/locals.dart' show JLocal;
 import '../world.dart' show JClosedWorld;
 
-import 'graph_builder.dart';
+import 'builder_kernel.dart';
 import 'nodes.dart';
 import 'types.dart';
 
@@ -32,7 +32,7 @@
   /// don't have source locations for [Elements.compareByPosition].
   Map<Local, HInstruction> directLocals = new Map<Local, HInstruction>();
   Map<Local, FieldEntity> redirectionMapping = new Map<Local, FieldEntity>();
-  final GraphBuilder builder;
+  final KernelSsaGraphBuilder builder;
   ScopeInfo scopeInfo;
   Map<TypeVariableType, TypeVariableLocal> typeVariableLocals =
       new Map<TypeVariableType, TypeVariableLocal>();
@@ -65,10 +65,10 @@
   LocalsHandler(this.builder, this.executableContext, this.memberContext,
       this.instanceType, this._nativeData, this._interceptorData);
 
-  JClosedWorld get closedWorld => builder.closedWorld;
+  JClosedWorld get _closedWorld => builder.closedWorld;
 
   AbstractValueDomain get _abstractValueDomain =>
-      closedWorld.abstractValueDomain;
+      _closedWorld.abstractValueDomain;
 
   GlobalTypeInferenceResults get _globalInferenceResults =>
       builder.globalInferenceResults;
@@ -80,13 +80,14 @@
     if (instanceType != null) {
       ClassEntity typeContext = DartTypes.getClassContext(newType);
       if (typeContext != null) {
-        newType = builder.types.substByContext(
+        newType = _closedWorld.dartTypes.substByContext(
             newType,
-            builder.types.asInstanceOf(
-                builder.types.getThisType(instanceType.element), typeContext));
+            _closedWorld.dartTypes.asInstanceOf(
+                _closedWorld.dartTypes.getThisType(instanceType.element),
+                typeContext));
       }
       if (!instanceType.containsTypeVariables) {
-        newType = builder.types.substByContext(newType, instanceType);
+        newType = _closedWorld.dartTypes.substByContext(newType, instanceType);
       }
     }
     return newType;
@@ -278,7 +279,7 @@
       // Unlike `this`, receiver is nullable since direct calls to generative
       // constructor call the constructor with `null`.
       HParameterValue value = new HParameterValue(
-          parameter, closedWorld.abstractValueDomain.createNullableExact(cls));
+          parameter, _closedWorld.abstractValueDomain.createNullableExact(cls));
       builder.graph.explicitReceiverParameter = value;
       builder.graph.entry.addAtEntry(value);
       if (builder.lastAddedParameter == null) {
@@ -438,15 +439,13 @@
       // Inside the closure the box is stored in a closure-field and cannot
       // be accessed directly.
       HInstruction box = readLocal(localBox);
-      builder.add(
-          new HFieldSet(builder.abstractValueDomain, redirect, box, value)
-            ..sourceInformation = sourceInformation);
+      builder.add(new HFieldSet(_abstractValueDomain, redirect, box, value)
+        ..sourceInformation = sourceInformation);
     } else {
       assert(_isUsedInTryOrGenerator(local));
       HLocalValue localValue = getLocal(local);
-      builder.add(
-          new HLocalSet(builder.abstractValueDomain, local, localValue, value)
-            ..sourceInformation = sourceInformation);
+      builder.add(new HLocalSet(_abstractValueDomain, local, localValue, value)
+        ..sourceInformation = sourceInformation);
     }
   }
 
@@ -653,7 +652,7 @@
     if (result == null) {
       ThisLocal local = scopeInfo.thisLocal;
       ClassEntity cls = local.enclosingClass;
-      if (closedWorld.isUsedAsMixin(cls)) {
+      if (_closedWorld.isUsedAsMixin(cls)) {
         // If the enclosing class is used as a mixin, [:this:] can be
         // of the class that mixins the enclosing class. These two
         // classes do not have a subclass relationship, so, for
diff --git a/pkg/compiler/lib/src/ssa/logging.dart b/pkg/compiler/lib/src/ssa/logging.dart
index 0a99d31..cdfb2a9 100644
--- a/pkg/compiler/lib/src/ssa/logging.dart
+++ b/pkg/compiler/lib/src/ssa/logging.dart
@@ -214,30 +214,18 @@
     _registerSpecializer(original, null, null, 'Round');
   }
 
-  void registerTypeConversion(
-      HInstruction original, HTypeConversion converted) {
+  void registerPrimitiveCheck(HInstruction original, HPrimitiveCheck check) {
     Features features = new Features();
-    switch (converted.kind) {
-      case HTypeConversion.CHECKED_MODE_CHECK:
-        features['kind'] = 'checked';
-        break;
-      case HTypeConversion.ARGUMENT_TYPE_CHECK:
-        features['kind'] = 'argument';
-        break;
-      case HTypeConversion.CAST_TYPE_CHECK:
-        features['kind'] = 'cast';
-        break;
-      case HTypeConversion.BOOLEAN_CONVERSION_CHECK:
-        features['kind'] = 'boolean';
-        break;
-      case HTypeConversion.RECEIVER_TYPE_CHECK:
-        features['kind'] = 'receiver';
-        break;
+
+    if (check.isReceiverTypeCheck) {
+      features['kind'] = 'receiver';
+    } else if (check.isArgumentTypeCheck) {
+      features['kind'] = 'argument';
     }
-    if (converted.typeExpression != null) {
-      features['type'] = '${converted.typeExpression}';
+    if (check.typeExpression != null) {
+      features['type'] = '${check.typeExpression}';
     }
-    entries.add(new OptimizationLogEntry('TypeConversion', features));
+    entries.add(new OptimizationLogEntry('PrimitiveCheck', features));
   }
 
   String getText() {
diff --git a/pkg/compiler/lib/src/ssa/loop_handler.dart b/pkg/compiler/lib/src/ssa/loop_handler.dart
index f9fda03..9138b8b 100644
--- a/pkg/compiler/lib/src/ssa/loop_handler.dart
+++ b/pkg/compiler/lib/src/ssa/loop_handler.dart
@@ -6,20 +6,23 @@
 
 import '../closure.dart' show CapturedLoopScope;
 import '../elements/jumps.dart';
+import '../inferrer/abstract_value_domain.dart';
 import '../io/source_information.dart';
 
 import 'builder_kernel.dart';
-import 'graph_builder.dart';
 import 'jump_handler.dart';
 import 'locals_handler.dart';
 import 'nodes.dart';
 
 /// Builds the SSA graph for loop nodes.
 abstract class LoopHandler {
-  final GraphBuilder builder;
+  final KernelSsaGraphBuilder builder;
 
   LoopHandler(this.builder);
 
+  AbstractValueDomain get _abstractValueDomain =>
+      builder.closedWorld.abstractValueDomain;
+
   /// Builds a graph for the given [loop] node.
   ///
   /// For while loops, [initialize] and [update] are null.
@@ -63,8 +66,8 @@
     if (startBlock == null) startBlock = conditionBlock;
 
     HInstruction conditionInstruction = condition();
-    HBasicBlock conditionEndBlock = builder.close(
-        new HLoopBranch(builder.abstractValueDomain, conditionInstruction));
+    HBasicBlock conditionEndBlock = builder
+        .close(new HLoopBranch(_abstractValueDomain, conditionInstruction));
     SubExpression conditionExpression =
         new SubExpression(conditionBlock, conditionEndBlock);
 
@@ -83,8 +86,7 @@
 
     SubGraph bodyGraph = new SubGraph(beginBodyBlock, builder.lastOpenedBlock);
     HBasicBlock bodyBlock = builder.current;
-    if (builder.current != null)
-      builder.close(new HGoto(builder.abstractValueDomain));
+    if (builder.current != null) builder.close(new HGoto(_abstractValueDomain));
 
     SubExpression updateGraph;
 
@@ -133,7 +135,7 @@
       update();
 
       HBasicBlock updateEndBlock =
-          builder.close(new HGoto(builder.abstractValueDomain));
+          builder.close(new HGoto(_abstractValueDomain));
       // The back-edge completing the cycle.
       updateEndBlock.addSuccessor(conditionBlock);
       updateGraph = new SubExpression(updateBlock, updateEndBlock);
@@ -141,7 +143,7 @@
       // Avoid a critical edge from the condition to the loop-exit body.
       HBasicBlock conditionExitBlock = builder.addNewBlock();
       builder.open(conditionExitBlock);
-      builder.close(new HGoto(builder.abstractValueDomain));
+      builder.close(new HGoto(_abstractValueDomain));
       conditionEndBlock.addSuccessor(conditionExitBlock);
 
       endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals);
@@ -172,7 +174,7 @@
       // label to the if.
       HBasicBlock elseBlock = builder.addNewBlock();
       builder.open(elseBlock);
-      builder.close(new HGoto(builder.abstractValueDomain));
+      builder.close(new HGoto(_abstractValueDomain));
       // Pass the elseBlock as the branchBlock, because that's the block we go
       // to just before leaving the 'loop'.
       endLoop(conditionBlock, elseBlock, jumpHandler, savedLocals);
@@ -184,8 +186,7 @@
       // Remove the [HLoopBranch] instruction and replace it with
       // [HIf].
       HInstruction condition = conditionEndBlock.last.inputs[0];
-      conditionEndBlock
-          .addAtExit(new HIf(builder.abstractValueDomain, condition));
+      conditionEndBlock.addAtExit(new HIf(_abstractValueDomain, condition));
       conditionEndBlock.addSuccessor(elseBlock);
       conditionEndBlock.remove(conditionEndBlock.last);
       HIfBlockInformation info = new HIfBlockInformation(
@@ -212,7 +213,7 @@
         jumpHandler.forEachBreak((HBreak breakInstruction, _) {
           HBasicBlock block = breakInstruction.block;
           block.addAtExit(new HBreak.toLabel(
-              builder.abstractValueDomain, label, sourceInformation));
+              _abstractValueDomain, label, sourceInformation));
           block.remove(breakInstruction);
         });
       }
@@ -226,8 +227,7 @@
   /// Also notifies the locals handler that we're entering a loop.
   JumpHandler beginLoopHeader(ir.TreeNode node, JumpTarget jumpTarget) {
     assert(!builder.isAborted());
-    HBasicBlock previousBlock =
-        builder.close(new HGoto(builder.abstractValueDomain));
+    HBasicBlock previousBlock = builder.close(new HGoto(_abstractValueDomain));
 
     JumpHandler jumpHandler =
         createJumpHandler(node, jumpTarget, isLoopJump: true);
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index c6e5a6d..3d8a473 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -8,14 +8,12 @@
 import '../common.dart';
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
-import '../deferred_load.dart' show OutputUnit;
 import '../elements/entities.dart';
 import '../elements/jumps.dart';
 import '../elements/types.dart';
 import '../inferrer/abstract_value_domain.dart';
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
-import '../js_backend/js_backend.dart';
 import '../native/behavior.dart';
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
@@ -32,7 +30,6 @@
   R visitBitNot(HBitNot node);
   R visitBitOr(HBitOr node);
   R visitBitXor(HBitXor node);
-  R visitBoolify(HBoolify node);
   R visitBoundsCheck(HBoundsCheck node);
   R visitBreak(HBreak node);
   R visitConstant(HConstant node);
@@ -98,12 +95,22 @@
   R visitTruncatingDivide(HTruncatingDivide node);
   R visitTry(HTry node);
   R visitTypeConversion(HTypeConversion node);
+  R visitPrimitiveCheck(HPrimitiveCheck node);
+  R visitBoolConversion(HBoolConversion node);
   R visitTypeKnown(HTypeKnown node);
   R visitYield(HYield node);
 
   R visitTypeInfoReadRaw(HTypeInfoReadRaw node);
   R visitTypeInfoReadVariable(HTypeInfoReadVariable node);
   R visitTypeInfoExpression(HTypeInfoExpression node);
+
+  // Instructions for 'dart:_rti'.
+  R visitIsTest(HIsTest node);
+  R visitAsCheck(HAsCheck node);
+  R visitSubtypeCheck(HSubtypeCheck node);
+  R visitLoadType(HLoadType node);
+  R visitTypeEval(HTypeEval node);
+  R visitTypeBind(HTypeBind node);
 }
 
 abstract class HGraphVisitor {
@@ -285,11 +292,9 @@
     return result;
   }
 
-  HConstant addDeferredConstant(ConstantValue constant, OutputUnit unit,
+  HConstant addDeferredConstant(DeferredGlobalConstantValue constant,
       SourceInformation sourceInformation, JClosedWorld closedWorld) {
-    ConstantValue wrapper = new DeferredGlobalConstantValue(constant, unit);
-    closedWorld.outputUnitData.registerConstantDeferredUse(wrapper, unit);
-    return addConstant(wrapper, closedWorld,
+    return addConstant(constant, closedWorld,
         sourceInformation: sourceInformation);
   }
 
@@ -313,9 +318,7 @@
 
   HConstant addConstantStringFromName(js.Name name, JClosedWorld closedWorld) {
     return addConstant(
-        new SyntheticConstantValue(
-            SyntheticConstantKind.NAME, js.quoteName(name)),
-        closedWorld);
+        new JsNameConstantValue(js.quoteName(name)), closedWorld);
   }
 
   HConstant addConstantBool(bool value, JClosedWorld closedWorld) {
@@ -329,10 +332,7 @@
   HConstant addConstantUnreachable(JClosedWorld closedWorld) {
     // A constant with an empty type used as the HInstruction of an expression
     // in an unreachable context.
-    return addConstant(
-        new SyntheticConstantValue(SyntheticConstantKind.EMPTY_VALUE,
-            closedWorld.abstractValueDomain.emptyType),
-        closedWorld);
+    return addConstant(const UnreachableConstantValue(), closedWorld);
   }
 
   void finalize(AbstractValueDomain domain) {
@@ -439,8 +439,6 @@
   @override
   visitBitXor(HBitXor node) => visitBinaryBitOp(node);
   @override
-  visitBoolify(HBoolify node) => visitInstruction(node);
-  @override
   visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
   @override
   visitBreak(HBreak node) => visitJump(node);
@@ -579,6 +577,10 @@
   @override
   visitTypeConversion(HTypeConversion node) => visitCheck(node);
   @override
+  visitBoolConversion(HBoolConversion node) => visitCheck(node);
+  @override
+  visitPrimitiveCheck(HPrimitiveCheck node) => visitCheck(node);
+  @override
   visitTypeKnown(HTypeKnown node) => visitCheck(node);
   @override
   visitAwait(HAwait node) => visitInstruction(node);
@@ -590,8 +592,22 @@
   @override
   visitTypeInfoReadVariable(HTypeInfoReadVariable node) =>
       visitInstruction(node);
+
   @override
   visitTypeInfoExpression(HTypeInfoExpression node) => visitInstruction(node);
+
+  @override
+  visitIsTest(HIsTest node) => visitInstruction(node);
+  @override
+  visitAsCheck(HAsCheck node) => visitCheck(node);
+  @override
+  visitSubtypeCheck(HSubtypeCheck node) => visitCheck(node);
+  @override
+  visitLoadType(HLoadType node) => visitInstruction(node);
+  @override
+  visitTypeEval(HTypeEval node) => visitInstruction(node);
+  @override
+  visitTypeBind(HTypeBind node) => visitInstruction(node);
 }
 
 class SubGraph {
@@ -1025,7 +1041,6 @@
 
   // Type codes.
   static const int UNDEFINED_TYPECODE = -1;
-  static const int BOOLIFY_TYPECODE = 0;
   static const int TYPE_GUARD_TYPECODE = 1;
   static const int BOUNDS_CHECK_TYPECODE = 2;
   static const int INTEGER_CHECK_TYPECODE = 3;
@@ -1068,6 +1083,15 @@
   static const int REMAINDER_TYPECODE = 42;
   static const int GET_LENGTH_TYPECODE = 43;
   static const int ABS_TYPECODE = 44;
+  static const int BOOL_CONVERSION_TYPECODE = 45;
+  static const int PRIMITIVE_CHECK_TYPECODE = 46;
+
+  static const int IS_TEST_TYPECODE = 47;
+  static const int AS_CHECK_TYPECODE = 48;
+  static const int SUBTYPE_CHECK_TYPECODE = 49;
+  static const int LOAD_TYPE_TYPECODE = 50;
+  static const int TYPE_EVAL_TYPECODE = 51;
+  static const int TYPE_BIND_TYPECODE = 52;
 
   HInstruction(this.inputs, this.instructionType)
       : id = idCounter++,
@@ -1374,11 +1398,7 @@
           closedWorld.abstractValueDomain.dynamicType, this, sourceInformation);
     }
     assert(type.isInterfaceType);
-    if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) {
-      // Boolean conversion checks work on non-nullable booleans.
-      return new HTypeConversion(type, kind,
-          closedWorld.abstractValueDomain.boolType, this, sourceInformation);
-    } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) {
+    if (kind == HTypeConversion.TYPE_CHECK && !type.treatAsRaw) {
       throw 'creating compound check to $type (this = ${this})';
     } else {
       InterfaceType interfaceType = type;
@@ -1393,6 +1413,9 @@
   bool hasSameLoopHeaderAs(HInstruction other) {
     return block.enclosingLoopHeader == other.block.enclosingLoopHeader;
   }
+
+  @override
+  String toString() => '${this.runtimeType}()';
 }
 
 /// The set of uses of [source] that are dominated by [dominator].
@@ -1564,23 +1587,6 @@
       : super(inputs, type);
 }
 
-class HBoolify extends HInstruction {
-  HBoolify(HInstruction value, AbstractValue type)
-      : super(<HInstruction>[value], type) {
-    setUseGvn();
-    sourceInformation = value.sourceInformation;
-  }
-
-  @override
-  accept(HVisitor visitor) => visitor.visitBoolify(this);
-  @override
-  int typeCode() => HInstruction.BOOLIFY_TYPECODE;
-  @override
-  bool typeEquals(other) => other is HBoolify;
-  @override
-  bool dataEquals(HInstruction other) => true;
-}
-
 /// A [HCheck] instruction is an instruction that might do a dynamic
 /// check at runtime on another instruction. To have proper instruction
 /// dependencies in the graph, instructions that depend on the check
@@ -1713,15 +1719,20 @@
   /// calling convention where the first input is the methods and the second
   /// input is the Dart receiver.
   bool isInterceptedCall = false;
-  HInvoke(List<HInstruction> inputs, type) : super(inputs, type) {
+
+  HInvoke(List<HInstruction> inputs, AbstractValue resultType)
+      : super(inputs, resultType) {
     sideEffects.setAllSideEffects();
     sideEffects.setDependsOnSomething();
   }
   static const int ARGUMENTS_OFFSET = 1;
+
   @override
   bool canThrow(AbstractValueDomain domain) => true;
+
   @override
   bool isAllocation(AbstractValueDomain domain) => _isAllocation;
+
   void setAllocation(bool value) {
     _isAllocation = value;
   }
@@ -1731,22 +1742,36 @@
   final InvokeDynamicSpecializer specializer;
   @override
   Selector selector;
-  AbstractValue mask;
+  AbstractValue _receiverType;
+  final AbstractValue _originalReceiverType;
   MemberEntity element;
 
-  HInvokeDynamic(Selector selector, this.mask, this.element,
-      List<HInstruction> inputs, bool isIntercepted, AbstractValue type)
+  HInvokeDynamic(Selector selector, this._receiverType, this.element,
+      List<HInstruction> inputs, bool isIntercepted, AbstractValue resultType)
       : this.selector = selector,
+        this._originalReceiverType = _receiverType,
         specializer = isIntercepted
             ? InvokeDynamicSpecializer.lookupSpecializer(selector)
             : const InvokeDynamicSpecializer(),
-        super(inputs, type) {
+        super(inputs, resultType) {
     assert(isIntercepted != null);
+    assert(_receiverType != null);
     isInterceptedCall = isIntercepted;
   }
+
+  AbstractValue get receiverType => _receiverType;
+
+  void updateReceiverType(
+      AbstractValueDomain abstractValueDomain, AbstractValue value) {
+    _receiverType =
+        abstractValueDomain.intersection(_originalReceiverType, value);
+  }
+
   @override
-  toString() => 'invoke dynamic: selector=$selector, mask=$mask';
+  String toString() => 'invoke dynamic: selector=$selector, mask=$receiverType';
+
   HInstruction get receiver => inputs[0];
+
   @override
   HInstruction getDartReceiver(JClosedWorld closedWorld) {
     return isCallOnInterceptor(closedWorld) ? inputs[1] : inputs[0];
@@ -1762,8 +1787,10 @@
 
   @override
   int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;
+
   @override
   bool typeEquals(other) => other is HInvokeDynamic;
+
   @override
   bool dataEquals(HInvokeDynamic other) {
     // Use the name and the kind instead of [Selector.operator==]
@@ -1778,9 +1805,9 @@
   @override
   final List<DartType> typeArguments;
 
-  HInvokeClosure(Selector selector, List<HInstruction> inputs,
-      AbstractValue type, this.typeArguments)
-      : super(selector, null, null, inputs, false, type) {
+  HInvokeClosure(Selector selector, AbstractValue receiverType,
+      List<HInstruction> inputs, AbstractValue resultType, this.typeArguments)
+      : super(selector, receiverType, null, inputs, false, resultType) {
     assert(selector.isClosureCall);
     assert(selector.callStructure.typeArgumentCount == typeArguments.length);
     assert(!isInterceptedCall);
@@ -1795,19 +1822,20 @@
 
   HInvokeDynamicMethod(
       Selector selector,
-      AbstractValue mask,
+      AbstractValue receiverType,
       List<HInstruction> inputs,
-      AbstractValue type,
+      AbstractValue resultType,
       this.typeArguments,
       SourceInformation sourceInformation,
       {bool isIntercepted: false})
-      : super(selector, mask, null, inputs, isIntercepted, type) {
+      : super(selector, receiverType, null, inputs, isIntercepted, resultType) {
     this.sourceInformation = sourceInformation;
     assert(selector.callStructure.typeArgumentCount == typeArguments.length);
   }
 
   @override
-  String toString() => 'invoke dynamic method: selector=$selector, mask=$mask';
+  String toString() =>
+      'invoke dynamic method: selector=$selector, mask=$receiverType';
   @override
   accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
 }
@@ -1815,27 +1843,30 @@
 abstract class HInvokeDynamicField extends HInvokeDynamic {
   HInvokeDynamicField(
       Selector selector,
-      AbstractValue mask,
+      AbstractValue receiverType,
       MemberEntity element,
       List<HInstruction> inputs,
       bool isIntercepted,
-      AbstractValue type)
-      : super(selector, mask, element, inputs, isIntercepted, type);
+      AbstractValue resultType)
+      : super(
+            selector, receiverType, element, inputs, isIntercepted, resultType);
 
   @override
-  String toString() => 'invoke dynamic field: selector=$selector, mask=$mask';
+  String toString() =>
+      'invoke dynamic field: selector=$selector, mask=$receiverType';
 }
 
 class HInvokeDynamicGetter extends HInvokeDynamicField {
   HInvokeDynamicGetter(
       Selector selector,
-      AbstractValue mask,
+      AbstractValue receiverType,
       MemberEntity element,
       List<HInstruction> inputs,
       bool isIntercepted,
-      AbstractValue type,
+      AbstractValue resultType,
       SourceInformation sourceInformation)
-      : super(selector, mask, element, inputs, isIntercepted, type) {
+      : super(selector, receiverType, element, inputs, isIntercepted,
+            resultType) {
     this.sourceInformation = sourceInformation;
   }
 
@@ -1854,7 +1885,8 @@
       : super.canThrow(domain);
 
   @override
-  String toString() => 'invoke dynamic getter: selector=$selector, mask=$mask';
+  String toString() =>
+      'invoke dynamic getter: selector=$selector, mask=$receiverType';
 }
 
 class HInvokeDynamicSetter extends HInvokeDynamicField {
@@ -1864,13 +1896,16 @@
 
   HInvokeDynamicSetter(
       Selector selector,
-      AbstractValue mask,
+      AbstractValue receiverType,
       MemberEntity element,
       List<HInstruction> inputs,
       bool isIntercepted,
-      AbstractValue type,
+      // TODO(johnniwinther): The result type for a setter should be the empty
+      // type.
+      AbstractValue resultType,
       SourceInformation sourceInformation)
-      : super(selector, mask, element, inputs, isIntercepted, type) {
+      : super(selector, receiverType, element, inputs, isIntercepted,
+            resultType) {
     this.sourceInformation = sourceInformation;
   }
 
@@ -1882,7 +1917,7 @@
 
   @override
   String toString() =>
-      'invoke dynamic setter: selector=$selector, mask=$mask, element=$element';
+      'invoke dynamic setter: selector=$selector, mask=$receiverType, element=$element';
 }
 
 class HInvokeStatic extends HInvoke {
@@ -3176,12 +3211,12 @@
   HOneShotInterceptor(
       AbstractValueDomain domain,
       Selector selector,
-      AbstractValue mask,
+      AbstractValue receiverType,
       List<HInstruction> inputs,
-      AbstractValue type,
+      AbstractValue resultType,
       this.typeArguments,
       this.interceptedClasses)
-      : super(selector, mask, null, inputs, true, type) {
+      : super(selector, receiverType, null, inputs, true, resultType) {
     assert(inputs[0] is HConstant);
     assert(inputs[0].instructionType == domain.nullType);
     assert(selector.callStructure.typeArgumentCount == typeArguments.length);
@@ -3190,7 +3225,8 @@
   bool isCallOnInterceptor(JClosedWorld closedWorld) => true;
 
   @override
-  String toString() => 'one shot interceptor: selector=$selector, mask=$mask';
+  String toString() =>
+      'one shot interceptor: selector=$selector, mask=$receiverType';
   @override
   accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
 }
@@ -3338,6 +3374,7 @@
       receiver.isNull(domain).isPotentiallyTrue;
 }
 
+/// Is-test using legacy constructor based typ representation.
 class HIs extends HInstruction {
   /// A check against a raw type: 'o is int', 'o is A'.
   static const int RAW_CHECK = 0;
@@ -3472,7 +3509,7 @@
 ///
 /// HLateValue is useful for naming values that would otherwise be generated at
 /// use site, for example, if 'this' is used many times, replacing uses of
-/// 'this' with HLateValhe(HThis) will have the effect of copying 'this' to a
+/// 'this' with HLateValue(HThis) will have the effect of copying 'this' to a
 /// temporary will reduce the size of minified code.
 class HLateValue extends HLateInstruction {
   HLateValue(HInstruction target) : super([target], target.instructionType);
@@ -3485,60 +3522,36 @@
   toString() => 'HLateValue($target)';
 }
 
+/// Type check or cast using legacy constructor-based type representation.
 class HTypeConversion extends HCheck {
   // Values for [kind].
-  static const int CHECKED_MODE_CHECK = 0;
-  static const int ARGUMENT_TYPE_CHECK = 1;
-  static const int CAST_TYPE_CHECK = 2;
-  static const int BOOLEAN_CONVERSION_CHECK = 3;
-  static const int RECEIVER_TYPE_CHECK = 4;
+  static const int TYPE_CHECK = 0;
+  static const int CAST_CHECK = 1;
 
   final DartType typeExpression;
   final int kind;
-  // [receiverTypeCheckSelector] is the selector used for a receiver type check
-  // on open-coded operators, e.g. the not-null check on `x` in `x + 1` would be
-  // compiled to the following, for which we need the selector `$add`.
-  //
-  //     if (typeof x != "number") x.$add();
-  //
-  final Selector receiverTypeCheckSelector;
 
   AbstractValue checkedType; // Not final because we refine it.
   AbstractValue
       inputType; // Holds input type for codegen after HTypeKnown removal.
 
   HTypeConversion(this.typeExpression, this.kind, AbstractValue type,
-      HInstruction input, SourceInformation sourceInformation,
-      {this.receiverTypeCheckSelector})
+      HInstruction input, SourceInformation sourceInformation)
       : checkedType = type,
         super(<HInstruction>[input], type) {
-    assert(!isReceiverTypeCheck || receiverTypeCheckSelector != null);
     assert(typeExpression == null || !typeExpression.isTypedef);
-    assert(!isControlFlow() || typeExpression != null);
-    sourceElement = input.sourceElement;
+    this.sourceElement = input.sourceElement;
     this.sourceInformation = sourceInformation;
   }
 
   HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
       AbstractValue type, HInstruction input, HInstruction typeRepresentation)
       : checkedType = type,
-        receiverTypeCheckSelector = null,
         super(<HInstruction>[input, typeRepresentation], type) {
     assert(!typeExpression.isTypedef);
     sourceElement = input.sourceElement;
   }
 
-  HTypeConversion.viaMethodOnType(this.typeExpression, this.kind,
-      AbstractValue type, HInstruction reifiedType, HInstruction input)
-      : checkedType = type,
-        receiverTypeCheckSelector = null,
-        super(<HInstruction>[reifiedType, input], type) {
-    // This form is currently used only for function types.
-    assert(typeExpression.isFunctionType);
-    assert(kind == CHECKED_MODE_CHECK || kind == CAST_TYPE_CHECK);
-    sourceElement = input.sourceElement;
-  }
-
   bool get hasTypeRepresentation {
     return typeExpression != null &&
         typeExpression.isInterfaceType &&
@@ -3553,23 +3566,13 @@
   @override
   HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
     if (typeExpression == type) {
-      // Don't omit a boolean conversion (which doesn't allow `null`) unless
-      // this type conversion is already a boolean conversion.
-      if (kind != BOOLEAN_CONVERSION_CHECK || isBooleanConversionCheck) {
-        return this;
-      }
+      return this;
     }
     return super.convertType(closedWorld, type, kind);
   }
 
-  bool get isCheckedModeCheck {
-    return kind == CHECKED_MODE_CHECK || kind == BOOLEAN_CONVERSION_CHECK;
-  }
-
-  bool get isArgumentTypeCheck => kind == ARGUMENT_TYPE_CHECK;
-  bool get isReceiverTypeCheck => kind == RECEIVER_TYPE_CHECK;
-  bool get isCastTypeCheck => kind == CAST_TYPE_CHECK;
-  bool get isBooleanConversionCheck => kind == BOOLEAN_CONVERSION_CHECK;
+  bool get isTypeCheck => kind == TYPE_CHECK;
+  bool get isCastCheck => kind == CAST_CHECK;
 
   @override
   accept(HVisitor visitor) => visitor.visitTypeConversion(this);
@@ -3577,7 +3580,7 @@
   @override
   bool isJsStatement() => isControlFlow();
   @override
-  bool isControlFlow() => isArgumentTypeCheck || isReceiverTypeCheck;
+  bool isControlFlow() => false;
 
   @override
   int typeCode() => HInstruction.TYPE_CONVERSION_TYPECODE;
@@ -3590,8 +3593,7 @@
   bool dataEquals(HTypeConversion other) {
     return kind == other.kind &&
         typeExpression == other.typeExpression &&
-        checkedType == other.checkedType &&
-        receiverTypeCheckSelector == other.receiverTypeCheckSelector;
+        checkedType == other.checkedType;
   }
 
   bool isRedundant(JClosedWorld closedWorld) {
@@ -3639,6 +3641,130 @@
       'checkedInput=$checkedInput)';
 }
 
+/// Check for receiver or argument type when lowering operation to a primitive,
+/// e.g. lowering `+` to [HAdd].
+///
+/// After NNBD, `a + b` will require `a` and `b` are non-nullable and these
+/// checks will become explicit in the source (e.g. `a! + b!`). At that time,
+/// this check should be removed.  If needed, the `!` check can be optimized
+/// give the same signals to the JavaScript VM.
+class HPrimitiveCheck extends HCheck {
+  // Values for [kind].
+  static const int ARGUMENT_TYPE_CHECK = 1;
+  static const int RECEIVER_TYPE_CHECK = 3;
+
+  final DartType typeExpression;
+  final int kind;
+
+  // [receiverTypeCheckSelector] is the selector used for a receiver type check
+  // on open-coded operators, e.g. the not-null check on `x` in `x + 1` would be
+  // compiled to the following, for which we need the selector `$add`.
+  //
+  //     if (typeof x != "number") x.$add();
+  //
+  final Selector receiverTypeCheckSelector;
+
+  AbstractValue checkedType; // Not final because we refine it.
+  AbstractValue
+      inputType; // Holds input type for codegen after HTypeKnown removal.
+
+  HPrimitiveCheck(this.typeExpression, this.kind, AbstractValue type,
+      HInstruction input, SourceInformation sourceInformation,
+      {this.receiverTypeCheckSelector})
+      : checkedType = type,
+        super(<HInstruction>[input], type) {
+    assert(isReceiverTypeCheck == (receiverTypeCheckSelector != null));
+    this.sourceElement = input.sourceElement;
+    this.sourceInformation = sourceInformation;
+  }
+
+  @override
+  HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
+    if (typeExpression == type) {
+      return this;
+    }
+    return super.convertType(closedWorld, type, kind);
+  }
+
+  bool get isArgumentTypeCheck => kind == ARGUMENT_TYPE_CHECK;
+  bool get isReceiverTypeCheck => kind == RECEIVER_TYPE_CHECK;
+
+  @override
+  accept(HVisitor visitor) => visitor.visitPrimitiveCheck(this);
+
+  @override
+  bool isJsStatement() => true;
+  @override
+  bool isControlFlow() => true;
+
+  @override
+  int typeCode() => HInstruction.PRIMITIVE_CHECK_TYPECODE;
+  @override
+  bool typeEquals(HInstruction other) => other is HPrimitiveCheck;
+  @override
+  bool isCodeMotionInvariant() => false;
+
+  @override
+  bool dataEquals(HPrimitiveCheck other) {
+    return kind == other.kind &&
+        checkedType == other.checkedType &&
+        receiverTypeCheckSelector == other.receiverTypeCheckSelector;
+  }
+
+  bool isRedundant(JClosedWorld closedWorld) {
+    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
+    // Type is refined from `dynamic`, so it might become non-redundant.
+    if (abstractValueDomain.containsAll(checkedType).isPotentiallyTrue) {
+      return false;
+    }
+    AbstractValue inputType = checkedInput.instructionType;
+    return abstractValueDomain.isIn(inputType, checkedType).isDefinitelyTrue;
+  }
+
+  @override
+  String toString() => 'HPrimitiveCheck(checkedType=$checkedType, kind=$kind, '
+      'checkedInput=$checkedInput)';
+}
+
+/// A check that the input to a condition (if, ?:, while, etc) is non-null. The
+/// front-end generates 'as bool' checks, but until the transition to NNBD is
+/// complete, this allows `null` to be passed to the condition.
+///
+// TODO(sra): Once NNDB is far enough along that the front-end can generate `as
+// bool!` checks and the backend checks them correctly, this instruction will
+// become unnecessary and should be removed.
+class HBoolConversion extends HCheck {
+  HBoolConversion(HInstruction input, AbstractValue type)
+      : super(<HInstruction>[input], type);
+
+  @override
+  bool isJsStatement() => false;
+
+  @override
+  bool isCodeMotionInvariant() => false;
+
+  @override
+  accept(HVisitor visitor) => visitor.visitBoolConversion(this);
+
+  @override
+  int typeCode() => HInstruction.BOOL_CONVERSION_TYPECODE;
+  @override
+  bool typeEquals(HInstruction other) => other is HBoolConversion;
+  @override
+  bool dataEquals(HBoolConversion other) => true;
+
+  bool isRedundant(JClosedWorld closedWorld) {
+    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
+    AbstractValue inputType = checkedInput.instructionType;
+    return abstractValueDomain
+        .isIn(inputType, instructionType)
+        .isDefinitelyTrue;
+  }
+
+  @override
+  toString() => 'HBoolConversion($checkedInput)';
+}
+
 /// The [HTypeKnown] instruction marks a value with a refined type.
 class HTypeKnown extends HCheck {
   AbstractValue knownType;
@@ -3730,8 +3856,8 @@
 /// The part of string interpolation which converts and interpolated expression
 /// into a String value.
 class HStringify extends HInstruction {
-  HStringify(HInstruction input, AbstractValue type)
-      : super(<HInstruction>[input], type) {
+  HStringify(HInstruction input, AbstractValue resultType)
+      : super(<HInstruction>[input], resultType) {
     sideEffects.setAllSideEffects();
     sideEffects.setDependsOnSomething();
   }
@@ -4207,3 +4333,179 @@
     }
   }
 }
+
+// -----------------------------------------------------------------------------
+
+/// Is-test using Rti form of type expression.
+///
+/// This instruction can be used for any type. Tests for simple types are
+/// lowered to other instructions, so this instruction remains for types that
+/// depend on type variables and complex types.
+class HIsTest extends HInstruction {
+  HIsTest(HInstruction checked, HInstruction rti, AbstractValue type)
+      : super([rti, checked], type) {
+    setUseGvn();
+  }
+
+  // The type input is first to facilitate the `type.is(value)` codegen pattern.
+  HInstruction get typeInput => inputs[0];
+  HInstruction get checkedInput => inputs[1];
+
+  @override
+  accept(HVisitor visitor) => visitor.visitIsTest(this);
+
+  @override
+  int typeCode() => HInstruction.IS_TEST_TYPECODE;
+
+  @override
+  bool typeEquals(HInstruction other) => other is HIsTest;
+
+  @override
+  bool dataEquals(HIsTest other) => true;
+
+  @override
+  String toString() => 'HIsTest()';
+}
+
+/// Type cast or type check using Rti form of type expression.
+class HAsCheck extends HCheck {
+  final bool isTypeError;
+
+  HAsCheck(HInstruction checked, HInstruction rti, this.isTypeError,
+      AbstractValue type)
+      : super([rti, checked], type) {}
+
+  // The type input is first to facilitate the `type.as(value)` codegen pattern.
+  HInstruction get typeInput => inputs[0];
+  @override
+  HInstruction get checkedInput => inputs[1];
+
+  @override
+  accept(HVisitor visitor) => visitor.visitAsCheck(this);
+
+  @override
+  int typeCode() => HInstruction.AS_CHECK_TYPECODE;
+
+  @override
+  bool typeEquals(HInstruction other) => other is HAsCheck;
+
+  @override
+  bool dataEquals(HAsCheck other) {
+    return isTypeError == other.isTypeError;
+  }
+
+  @override
+  String toString() {
+    String error = isTypeError ? 'TypeError' : 'CastError';
+    return 'HAsCheck($error)';
+  }
+}
+
+/// Subtype check comparing two Rti types.
+class HSubtypeCheck extends HCheck {
+  HSubtypeCheck(
+      HInstruction subtype, HInstruction supertype, AbstractValue type)
+      : super([subtype, supertype], type) {
+    setUseGvn();
+  }
+
+  HInstruction get typeInput => inputs[1];
+
+  @override
+  accept(HVisitor visitor) => visitor.visitSubtypeCheck(this);
+
+  @override
+  int typeCode() => HInstruction.SUBTYPE_CHECK_TYPECODE;
+
+  @override
+  bool typeEquals(HInstruction other) => other is HSubtypeCheck;
+
+  @override
+  bool dataEquals(HSubtypeCheck other) => true;
+
+  @override
+  String toString() => 'HSubtypeCheck()';
+}
+
+/// Common superclass for instructions that generate Rti values.
+abstract class HRtiInstruction extends HInstruction {
+  HRtiInstruction(List<HInstruction> inputs, AbstractValue type)
+      : super(inputs, type);
+}
+
+/// Evaluates an Rti type recipe in the global environment.
+class HLoadType extends HRtiInstruction {
+  DartType typeExpression; // TODO(sra): Allow a type environment expression.
+
+  HLoadType(this.typeExpression, AbstractValue type) : super([], type) {
+    setUseGvn();
+  }
+
+  @override
+  accept(HVisitor visitor) => visitor.visitLoadType(this);
+
+  @override
+  int typeCode() => HInstruction.LOAD_TYPE_TYPECODE;
+
+  @override
+  bool typeEquals(HInstruction other) => other is HLoadType;
+
+  @override
+  bool dataEquals(HLoadType other) {
+    return typeExpression == other.typeExpression;
+  }
+
+  @override
+  String toString() => 'HLoadType($typeExpression)';
+}
+
+/// Evaluates an Rti type recipe in an Rti environment.
+class HTypeEval extends HRtiInstruction {
+  DartType typeExpression; // TODO(sra); Allow a type environment expression.
+
+  HTypeEval(HInstruction environment, this.typeExpression, AbstractValue type)
+      : super([environment], type) {
+    setUseGvn();
+  }
+
+  @override
+  accept(HVisitor visitor) => visitor.visitTypeEval(this);
+
+  @override
+  int typeCode() => HInstruction.TYPE_EVAL_TYPECODE;
+
+  @override
+  bool typeEquals(HInstruction other) => other is HTypeEval;
+
+  @override
+  bool dataEquals(HTypeEval other) {
+    return typeExpression == other.typeExpression;
+  }
+
+  @override
+  String toString() => 'HTypeEval($typeExpression)';
+}
+
+/// Extends an Rti type environment with generic function types.
+class HTypeBind extends HRtiInstruction {
+  HTypeBind(
+      HInstruction environment, HInstruction typeArguments, AbstractValue type)
+      : super([environment, typeArguments], type) {
+    setUseGvn();
+  }
+
+  @override
+  accept(HVisitor visitor) => visitor.visitTypeBind(this);
+
+  @override
+  int typeCode() => HInstruction.TYPE_BIND_TYPECODE;
+
+  @override
+  bool typeEquals(HInstruction other) => other is HTypeBind;
+
+  @override
+  bool dataEquals(HTypeBind other) => true;
+
+  @override
+  String toString() => 'HTypeBind()';
+}
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index e584210..249121e 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -3,10 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import '../common.dart';
-import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
+import '../common/codegen.dart' show CodegenRegistry;
 import '../common/names.dart' show Selectors;
-import '../common/tasks.dart' show CompilerTask;
-import '../compiler.dart' show Compiler;
+import '../common/tasks.dart' show Measurer, CompilerTask;
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
 import '../common_elements.dart' show JCommonElements;
@@ -16,7 +15,7 @@
 import '../inferrer/types.dart';
 import '../js_backend/field_analysis.dart'
     show FieldAnalysisData, JFieldAnalysis;
-import '../js_backend/backend.dart';
+import '../js_backend/backend.dart' show CodegenInputs;
 import '../js_backend/native_data.dart' show NativeData;
 import '../js_backend/runtime_types.dart';
 import '../native/behavior.dart';
@@ -40,33 +39,31 @@
 }
 
 class SsaOptimizerTask extends CompilerTask {
-  final JavaScriptBackend _backend;
+  final CompilerOptions _options;
 
   Map<HInstruction, Range> ranges = <HInstruction, Range>{};
 
   Map<MemberEntity, OptimizationTestLog> loggersForTesting;
 
-  SsaOptimizerTask(this._backend) : super(_backend.compiler.measurer);
+  SsaOptimizerTask(Measurer measurer, this._options) : super(measurer);
 
   @override
   String get name => 'SSA optimizer';
 
-  Compiler get _compiler => _backend.compiler;
-
-  CompilerOptions get _options => _compiler.options;
-
-  RuntimeTypesSubstitutions get _rtiSubstitutions => _backend.rtiSubstitutions;
-
-  void optimize(CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
+  void optimize(
+      MemberEntity member,
+      HGraph graph,
+      CodegenInputs codegen,
+      JClosedWorld closedWorld,
+      GlobalTypeInferenceResults globalInferenceResults,
+      CodegenRegistry registry) {
     void runPhase(OptimizationPhase phase) {
       measureSubtask(phase.name, () => phase.visitGraph(graph));
-      _backend.tracer.traceGraph(phase.name, graph);
+      codegen.tracer.traceGraph(phase.name, graph);
       assert(graph.isValid(), 'Graph not valid after ${phase.name}');
     }
 
     bool trustPrimitives = _options.trustPrimitives;
-    CodegenRegistry registry = work.registry;
     Set<HInstruction> boundsChecked = new Set<HInstruction>();
     SsaCodeMotion codeMotion;
     SsaLoadElimination loadElimination;
@@ -74,7 +71,7 @@
     OptimizationTestLog log;
     if (retainDataForTesting) {
       loggersForTesting ??= {};
-      loggersForTesting[work.element] = log = new OptimizationTestLog();
+      loggersForTesting[member] = log = new OptimizationTestLog();
     }
 
     measure(() {
@@ -82,7 +79,7 @@
         // Run trivial instruction simplification first to optimize
         // some patterns useful for type conversion.
         new SsaInstructionSimplifier(globalInferenceResults, _options,
-            _rtiSubstitutions, closedWorld, registry, log),
+            codegen.rtiSubstitutions, closedWorld, registry, log),
         new SsaTypeConversionInserter(closedWorld),
         new SsaRedundantPhiEliminator(),
         new SsaDeadPhiEliminator(),
@@ -91,10 +88,10 @@
         // After type propagation, more instructions can be
         // simplified.
         new SsaInstructionSimplifier(globalInferenceResults, _options,
-            _rtiSubstitutions, closedWorld, registry, log),
+            codegen.rtiSubstitutions, closedWorld, registry, log),
         new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
         new SsaInstructionSimplifier(globalInferenceResults, _options,
-            _rtiSubstitutions, closedWorld, registry, log),
+            codegen.rtiSubstitutions, closedWorld, registry, log),
         new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
         new SsaTypePropagator(globalInferenceResults, _options,
             closedWorld.commonElements, closedWorld, log),
@@ -107,7 +104,7 @@
         new SsaTypePropagator(globalInferenceResults, _options,
             closedWorld.commonElements, closedWorld, log),
         codeMotion = new SsaCodeMotion(closedWorld.abstractValueDomain),
-        loadElimination = new SsaLoadElimination(_compiler, closedWorld),
+        loadElimination = new SsaLoadElimination(closedWorld),
         new SsaRedundantPhiEliminator(),
         new SsaDeadPhiEliminator(),
         // After GVN and load elimination the same value may be used in code
@@ -120,7 +117,7 @@
         // Previous optimizations may have generated new
         // opportunities for instruction simplification.
         new SsaInstructionSimplifier(globalInferenceResults, _options,
-            _rtiSubstitutions, closedWorld, registry, log),
+            codegen.rtiSubstitutions, closedWorld, registry, log),
         new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
       ];
       phases.forEach(runPhase);
@@ -128,8 +125,7 @@
       // Simplifying interceptors is not strictly just an optimization, it is
       // required for implementation correctness because the code generator
       // assumes it is always performed.
-      runPhase(new SsaSimplifyInterceptors(
-          closedWorld, work.element.enclosingClass));
+      runPhase(new SsaSimplifyInterceptors(closedWorld, member.enclosingClass));
 
       SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(closedWorld, this);
       runPhase(dce);
@@ -143,9 +139,9 @@
           new SsaCodeMotion(closedWorld.abstractValueDomain),
           new SsaValueRangeAnalyzer(closedWorld, this),
           new SsaInstructionSimplifier(globalInferenceResults, _options,
-              _rtiSubstitutions, closedWorld, registry, log),
+              codegen.rtiSubstitutions, closedWorld, registry, log),
           new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
-          new SsaSimplifyInterceptors(closedWorld, work.element.enclosingClass),
+          new SsaSimplifyInterceptors(closedWorld, member.enclosingClass),
           new SsaDeadCodeEliminator(closedWorld, this),
         ];
       } else {
@@ -155,7 +151,7 @@
           // Run the simplifier to remove unneeded type checks inserted by
           // type propagation.
           new SsaInstructionSimplifier(globalInferenceResults, _options,
-              _rtiSubstitutions, closedWorld, registry, log),
+              codegen.rtiSubstitutions, closedWorld, registry, log),
         ];
       }
       phases.forEach(runPhase);
@@ -443,33 +439,6 @@
   }
 
   @override
-  HInstruction visitBoolify(HBoolify node) {
-    List<HInstruction> inputs = node.inputs;
-    assert(inputs.length == 1);
-    HInstruction input = inputs[0];
-    if (input.isBoolean(_abstractValueDomain).isDefinitelyTrue) {
-      return input;
-    }
-
-    // If the code is unreachable, remove the HBoolify.  This can happen when
-    // there is a throw expression in a short-circuit conditional.  Removing the
-    // unreachable HBoolify makes it easier to reconstruct the short-circuit
-    // operation.
-    if (_abstractValueDomain.isEmpty(input.instructionType).isDefinitelyTrue) {
-      return input;
-    }
-
-    // All values that cannot be 'true' are boolified to false.
-    AbstractValue mask = input.instructionType;
-    if (_abstractValueDomain
-        .containsType(mask, commonElements.jsBoolClass)
-        .isPotentiallyFalse) {
-      return _graph.addConstantBool(false, _closedWorld);
-    }
-    return node;
-  }
-
-  @override
   HInstruction visitNot(HNot node) {
     List<HInstruction> inputs = node.inputs;
     assert(inputs.length == 1);
@@ -563,7 +532,7 @@
     }
 
     Selector selector = node.selector;
-    AbstractValue mask = node.mask;
+    AbstractValue mask = node.receiverType;
     HInstruction input = node.inputs[1];
 
     bool applies(MemberEntity element) {
@@ -616,7 +585,7 @@
         // optimization.
         HInvokeDynamicMethod result = new HInvokeDynamicMethod(
             node.selector,
-            node.mask,
+            node.receiverType,
             node.inputs.sublist(1), // Drop interceptor.
             node.instructionType,
             node.typeArguments,
@@ -653,7 +622,7 @@
 
     HInvokeDynamicMethod splitInstruction = new HInvokeDynamicMethod(
         node.selector,
-        node.mask,
+        node.receiverType,
         node.inputs.sublist(1), // Drop interceptor.
         resultMask,
         const <DartType>[],
@@ -780,8 +749,14 @@
         Selector callSelector = new Selector.callClosureFrom(node.selector);
         List<HInstruction> inputs = <HInstruction>[load]
           ..addAll(node.inputs.skip(node.isInterceptedCall ? 2 : 1));
+        DartType fieldType =
+            _closedWorld.elementEnvironment.getFieldType(field);
         HInstruction closureCall = new HInvokeClosure(
-            callSelector, inputs, node.instructionType, node.typeArguments)
+            callSelector,
+            _abstractValueDomain.createFromStaticType(fieldType),
+            inputs,
+            node.instructionType,
+            node.typeArguments)
           ..sourceInformation = node.sourceInformation;
         node.block.addAfter(insertionPoint, closureCall);
         return closureCall;
@@ -849,7 +824,7 @@
         AbstractValueFactory.fromNativeBehavior(nativeBehavior, _closedWorld);
     HInvokeDynamicMethod result = new HInvokeDynamicMethod(
         node.selector,
-        node.mask,
+        node.receiverType,
         inputs.sublist(1), // Drop interceptor.
         returnType,
         node.typeArguments,
@@ -923,23 +898,8 @@
     return node;
   }
 
-  bool allUsersAreBoolifies(HInstruction instruction) {
-    List<HInstruction> users = instruction.usedBy;
-    int length = users.length;
-    for (int i = 0; i < length; i++) {
-      if (users[i] is! HBoolify) return false;
-    }
-    return true;
-  }
-
   @override
   HInstruction visitRelational(HRelational node) {
-    if (allUsersAreBoolifies(node)) {
-      // TODO(ngeoffray): Call a boolified selector.
-      // This node stays the same, but the Boolify node will go away.
-    }
-    // Note that we still have to call [super] to make sure that we end up
-    // in the remaining optimizations.
     return super.visitRelational(node);
   }
 
@@ -1159,6 +1119,18 @@
   }
 
   @override
+  HInstruction visitPrimitiveCheck(HPrimitiveCheck node) {
+    if (node.isRedundant(_closedWorld)) return node.checkedInput;
+    return node;
+  }
+
+  @override
+  HInstruction visitBoolConversion(HBoolConversion node) {
+    if (node.isRedundant(_closedWorld)) return node.checkedInput;
+    return node;
+  }
+
+  @override
   HInstruction visitTypeKnown(HTypeKnown node) {
     return node.isRedundant(_closedWorld) ? node.checkedInput : node;
   }
@@ -1362,8 +1334,8 @@
         node.needsCheck = true;
         return node;
       }
-      HInstruction other = value.convertType(
-          _closedWorld, type, HTypeConversion.CHECKED_MODE_CHECK);
+      HInstruction other =
+          value.convertType(_closedWorld, type, HTypeConversion.TYPE_CHECK);
       if (other != value) {
         node.block.addBefore(node, other);
         value = other;
@@ -1601,8 +1573,9 @@
         return null;
       }
       Selector selector = Selectors.toString_;
-      AbstractValue toStringType = AbstractValueFactory.inferredTypeForSelector(
-          selector, input.instructionType, _globalInferenceResults);
+      AbstractValue toStringType =
+          AbstractValueFactory.inferredResultTypeForSelector(
+              selector, input.instructionType, _globalInferenceResults);
       if (_abstractValueDomain
           .containsOnlyType(
               toStringType, _closedWorld.commonElements.jsStringClass)
@@ -1617,7 +1590,7 @@
         var inputs = <HInstruction>[input, input]; // [interceptor, receiver].
         HInstruction result = new HInvokeDynamicMethod(
             selector,
-            input.instructionType, // receiver mask.
+            input.instructionType, // receiver type.
             inputs,
             toStringType,
             const <DartType>[],
@@ -1952,8 +1925,7 @@
   HInstruction get zapInstruction {
     if (zapInstructionCache == null) {
       // A constant with no type does not pollute types at phi nodes.
-      ConstantValue constant = new SyntheticConstantValue(
-          SyntheticConstantKind.EMPTY_VALUE, _abstractValueDomain.emptyType);
+      ConstantValue constant = const UnreachableConstantValue();
       zapInstructionCache = analyzer.graph.addConstant(constant, closedWorld);
     }
     return zapInstructionCache;
@@ -2926,10 +2898,6 @@
             collectTargets(user, trueTargets, null);
           }
         }
-      } else if (user is HBoolify) {
-        // We collect targets for strictly boolean operations so HBoolify cannot
-        // change the result.
-        collectTargets(user, trueTargets, falseTargets);
       }
     }
   }
@@ -2939,8 +2907,7 @@
 /// [HFieldGet]), when it knows the value stored in that memory location, and
 /// stores that overwrite with the same value.
 class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase {
-  final Compiler compiler;
-  final JClosedWorld closedWorld;
+  final JClosedWorld _closedWorld;
   final JFieldAnalysis _fieldAnalysis;
   @override
   final String name = "SsaLoadElimination";
@@ -2949,11 +2916,11 @@
   bool newGvnCandidates = false;
   HGraph _graph;
 
-  SsaLoadElimination(this.compiler, this.closedWorld)
-      : _fieldAnalysis = closedWorld.fieldAnalysis;
+  SsaLoadElimination(this._closedWorld)
+      : _fieldAnalysis = _closedWorld.fieldAnalysis;
 
   AbstractValueDomain get _abstractValueDomain =>
-      closedWorld.abstractValueDomain;
+      _closedWorld.abstractValueDomain;
 
   @override
   void visitGraph(HGraph graph) {
@@ -2978,7 +2945,7 @@
   void visitBasicBlock(HBasicBlock block) {
     if (block.predecessors.length == 0) {
       // Entry block.
-      memorySet = new MemorySet(closedWorld);
+      memorySet = new MemorySet(_closedWorld);
     } else if (block.predecessors.length == 1 &&
         block.predecessors[0].successors.length == 1) {
       // No need to clone, there is no other successor for
@@ -3021,7 +2988,8 @@
   void visitFieldGet(HFieldGet instruction) {
     if (instruction.isNullCheck) return;
     FieldEntity element = instruction.element;
-    HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck();
+    HInstruction receiver =
+        instruction.getDartReceiver(_closedWorld).nonCheck();
     _visitFieldGet(element, receiver, instruction);
   }
 
@@ -3054,7 +3022,8 @@
   @override
   void visitFieldSet(HFieldSet instruction) {
     FieldEntity element = instruction.element;
-    HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck();
+    HInstruction receiver =
+        instruction.getDartReceiver(_closedWorld).nonCheck();
     if (memorySet.registerFieldValueUpdate(
         element, receiver, instruction.value)) {
       instruction.block.remove(instruction);
@@ -3066,17 +3035,14 @@
     memorySet.registerAllocation(instruction);
     if (shouldTrackInitialValues(instruction)) {
       int argumentIndex = 0;
-      compiler.codegenWorldBuilder.forEachInstanceField(instruction.element,
-          (_, FieldEntity member, {bool isElided}) {
-        if (isElided) return;
-        if (compiler.elementHasCompileTimeError(
-            // ignore: UNNECESSARY_CAST
-            member as Entity)) return;
+      _closedWorld.elementEnvironment.forEachInstanceField(instruction.element,
+          (_, FieldEntity member) {
         FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(member);
+        if (fieldData.isElided) return;
         if (fieldData.isInitializedInAllocator) {
           // TODO(sra): Can we avoid calling HGraph.addConstant?
           ConstantValue value = fieldData.initialValue;
-          HConstant constant = _graph.addConstant(value, closedWorld);
+          HConstant constant = _graph.addConstant(value, _closedWorld);
           memorySet.registerFieldValue(member, instruction, constant);
         } else {
           memorySet.registerFieldValue(
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index cdcc910..12f1db9 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -4,16 +4,25 @@
 
 library ssa;
 
-import '../common/codegen.dart' show CodegenWorkItem, CodegenRegistry;
+import '../backend_strategy.dart';
+import '../common.dart';
+import '../common_elements.dart' show CommonElements, JElementEnvironment;
+import '../common/codegen.dart' show CodegenResult, CodegenRegistry;
 import '../common/tasks.dart' show CompilerTask, Measurer;
-import '../elements/entities.dart' show MemberEntity;
+import '../elements/entities.dart';
+import '../elements/types.dart';
 import '../inferrer/types.dart';
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
-import '../js_backend/field_analysis.dart';
-import '../js_backend/backend.dart' show JavaScriptBackend, FunctionCompiler;
-import '../universe/call_structure.dart';
-import '../universe/use.dart';
+import '../js/rewrite_async.dart';
+import '../js_backend/backend.dart' show CodegenInputs, FunctionCompiler;
+import '../js_backend/namer.dart' show ModularNamer, ModularNamerImpl;
+import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
+import '../js_emitter/startup_emitter/emitter.dart' show ModularEmitterImpl;
+import '../js_model/elements.dart';
+import '../options.dart';
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/use.dart' show StaticUse;
 import '../world.dart' show JClosedWorld;
 
 import 'codegen.dart';
@@ -21,47 +30,212 @@
 import 'optimize.dart';
 
 class SsaFunctionCompiler implements FunctionCompiler {
+  final CompilerOptions _options;
+  final DiagnosticReporter _reporter;
   final SsaCodeGeneratorTask generator;
   final SsaBuilderTask _builder;
   final SsaOptimizerTask optimizer;
-  final JavaScriptBackend backend;
+  final SourceInformationStrategy sourceInformationStrategy;
+  GlobalTypeInferenceResults _globalInferenceResults;
+  CodegenInputs _codegen;
 
-  SsaFunctionCompiler(JavaScriptBackend backend, Measurer measurer,
-      SourceInformationStrategy sourceInformationFactory)
-      : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory),
-        _builder = new SsaBuilderTask(backend, sourceInformationFactory),
-        optimizer = new SsaOptimizerTask(backend),
-        backend = backend;
+  SsaFunctionCompiler(
+      this._options,
+      this._reporter,
+      BackendStrategy backendStrategy,
+      Measurer measurer,
+      this.sourceInformationStrategy)
+      : generator = new SsaCodeGeneratorTask(
+            measurer, _options, sourceInformationStrategy),
+        _builder = new SsaBuilderTask(
+            measurer, backendStrategy, sourceInformationStrategy),
+        optimizer = new SsaOptimizerTask(measurer, _options);
 
   @override
-  void onCodegenStart() {
+  void initialize(GlobalTypeInferenceResults globalInferenceResults,
+      CodegenInputs codegen) {
+    _globalInferenceResults = globalInferenceResults;
+    _codegen = codegen;
     _builder.onCodegenStart();
   }
 
-  /// Generates JavaScript code for `work.element`.
+  /// Generates JavaScript code for [member].
   /// Using the ssa builder, optimizer and code generator.
   @override
-  js.Fun compile(CodegenWorkItem work, JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
-    HGraph graph = _builder.build(work, closedWorld, globalInferenceResults);
-    if (graph == null) return null;
-    optimizer.optimize(work, graph, closedWorld, globalInferenceResults);
-    MemberEntity element = work.element;
-    js.Expression result = generator.generateCode(work, graph, closedWorld);
+  CodegenResult compile(MemberEntity member) {
+    JClosedWorld closedWorld = _globalInferenceResults.closedWorld;
+    CodegenRegistry registry =
+        new CodegenRegistry(closedWorld.elementEnvironment, member);
+    ModularNamer namer = new ModularNamerImpl(registry,
+        closedWorld.commonElements, _codegen.rtiTags, _codegen.fixedNames);
+    ModularEmitter emitter = new ModularEmitterImpl(namer, registry, _options);
+    if (member.isConstructor &&
+        member.enclosingClass == closedWorld.commonElements.jsNullClass) {
+      // Work around a problem compiling JSNull's constructor.
+      return registry.close(null);
+    }
+
+    HGraph graph = _builder.build(member, closedWorld, _globalInferenceResults,
+        _codegen, registry, namer, emitter);
+    if (graph == null) {
+      return registry.close(null);
+    }
+    optimizer.optimize(member, graph, _codegen, closedWorld,
+        _globalInferenceResults, registry);
+    js.Expression result = generator.generateCode(
+        member, graph, _codegen, closedWorld, registry, namer, emitter);
     if (graph.needsAsyncRewrite) {
       SourceInformationBuilder sourceInformationBuilder =
-          backend.sourceInformationStrategy.createBuilderForContext(element);
-      result = backend.rewriteAsync(
+          sourceInformationStrategy.createBuilderForContext(member);
+      result = _rewriteAsync(
+          _codegen,
           closedWorld.commonElements,
           closedWorld.elementEnvironment,
-          work.registry,
-          element,
+          registry,
+          namer,
+          emitter,
+          member,
           result,
           graph.asyncElementType,
           sourceInformationBuilder.buildAsyncBody(),
           sourceInformationBuilder.buildAsyncExit());
     }
-    return result;
+    if (result.sourceInformation == null) {
+      result = result.withSourceInformation(
+          sourceInformationStrategy.buildSourceMappedMarker());
+    }
+
+    return registry.close(result);
+  }
+
+  js.Expression _rewriteAsync(
+      CodegenInputs codegen,
+      CommonElements commonElements,
+      JElementEnvironment elementEnvironment,
+      CodegenRegistry registry,
+      ModularNamer namer,
+      ModularEmitter emitter,
+      FunctionEntity element,
+      js.Expression code,
+      DartType asyncTypeParameter,
+      SourceInformation bodySourceInformation,
+      SourceInformation exitSourceInformation) {
+    if (element.asyncMarker == AsyncMarker.SYNC) return code;
+
+    AsyncRewriterBase rewriter = null;
+    js.Name name = namer.methodPropertyName(
+        element is JGeneratorBody ? element.function : element);
+
+    switch (element.asyncMarker) {
+      case AsyncMarker.ASYNC:
+        rewriter = _makeAsyncRewriter(
+            codegen,
+            commonElements,
+            elementEnvironment,
+            registry,
+            namer,
+            emitter,
+            element,
+            code,
+            asyncTypeParameter,
+            name);
+        break;
+      case AsyncMarker.SYNC_STAR:
+        rewriter = new SyncStarRewriter(_reporter, element,
+            endOfIteration:
+                emitter.staticFunctionAccess(commonElements.endOfIteration),
+            iterableFactory: emitter
+                .staticFunctionAccess(commonElements.syncStarIterableFactory),
+            iterableFactoryTypeArguments:
+                _fetchItemType(codegen, emitter, asyncTypeParameter),
+            yieldStarExpression:
+                emitter.staticFunctionAccess(commonElements.yieldStar),
+            uncaughtErrorExpression: emitter
+                .staticFunctionAccess(commonElements.syncStarUncaughtError),
+            safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
+            bodyName: namer.deriveAsyncBodyName(name));
+        registry.registerStaticUse(new StaticUse.staticInvoke(
+            commonElements.syncStarIterableFactory,
+            const CallStructure.unnamed(1, 1), [
+          elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)
+        ]));
+        break;
+      case AsyncMarker.ASYNC_STAR:
+        rewriter = new AsyncStarRewriter(_reporter, element,
+            asyncStarHelper:
+                emitter.staticFunctionAccess(commonElements.asyncStarHelper),
+            streamOfController:
+                emitter.staticFunctionAccess(commonElements.streamOfController),
+            wrapBody: emitter.staticFunctionAccess(commonElements.wrapBody),
+            newController: emitter.staticFunctionAccess(
+                commonElements.asyncStarStreamControllerFactory),
+            newControllerTypeArguments:
+                _fetchItemType(codegen, emitter, asyncTypeParameter),
+            safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
+            yieldExpression:
+                emitter.staticFunctionAccess(commonElements.yieldSingle),
+            yieldStarExpression:
+                emitter.staticFunctionAccess(commonElements.yieldStar),
+            bodyName: namer.deriveAsyncBodyName(name));
+        registry.registerStaticUse(new StaticUse.staticInvoke(
+            commonElements.asyncStarStreamControllerFactory,
+            const CallStructure.unnamed(1, 1), [
+          elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)
+        ]));
+        break;
+    }
+    return rewriter.rewrite(code, bodySourceInformation, exitSourceInformation);
+  }
+
+  /// Returns an optional expression that evaluates [type].  Returns `null` if
+  /// the type expression is determined by the outside context and should be
+  /// added as a function parameter to the rewritten code.
+  // TODO(sra): We could also return an empty list if the generator takes no
+  // type (e.g. due to rtiNeed optimization).
+  List<js.Expression> _fetchItemType(
+      CodegenInputs codegen, ModularEmitter emitter, DartType type) {
+    if (type == null) return null;
+    var ast = codegen.rtiEncoder.getTypeRepresentation(emitter, type, null);
+    return <js.Expression>[ast];
+  }
+
+  AsyncRewriter _makeAsyncRewriter(
+      CodegenInputs codegen,
+      CommonElements commonElements,
+      JElementEnvironment elementEnvironment,
+      CodegenRegistry registry,
+      ModularNamer namer,
+      ModularEmitter emitter,
+      FunctionEntity element,
+      js.Expression code,
+      DartType elementType,
+      js.Name name) {
+    FunctionEntity startFunction = commonElements.asyncHelperStartSync;
+    FunctionEntity completerFactory = commonElements.asyncAwaitCompleterFactory;
+
+    List<js.Expression> itemTypeExpression =
+        _fetchItemType(codegen, emitter, elementType);
+
+    AsyncRewriter rewriter = new AsyncRewriter(_reporter, element,
+        asyncStart: emitter.staticFunctionAccess(startFunction),
+        asyncAwait:
+            emitter.staticFunctionAccess(commonElements.asyncHelperAwait),
+        asyncReturn:
+            emitter.staticFunctionAccess(commonElements.asyncHelperReturn),
+        asyncRethrow:
+            emitter.staticFunctionAccess(commonElements.asyncHelperRethrow),
+        wrapBody: emitter.staticFunctionAccess(commonElements.wrapBody),
+        completerFactory: emitter.staticFunctionAccess(completerFactory),
+        completerFactoryTypeArguments: itemTypeExpression,
+        safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
+        bodyName: namer.deriveAsyncBodyName(name));
+
+    registry.registerStaticUse(new StaticUse.staticInvoke(
+        completerFactory,
+        const CallStructure.unnamed(0, 1),
+        [elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)]));
+
+    return rewriter;
   }
 
   @override
@@ -71,70 +245,46 @@
 }
 
 abstract class SsaBuilder {
-  /// Creates the [HGraph] for [work] or returns `null` if no code is needed
-  /// for [work].
-  HGraph build(CodegenWorkItem work, JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults);
+  /// Creates the [HGraph] for [member] or returns `null` if no code is needed
+  /// for [member].
+  HGraph build(
+      MemberEntity member,
+      JClosedWorld closedWorld,
+      GlobalTypeInferenceResults globalInferenceResults,
+      CodegenInputs codegen,
+      CodegenRegistry registry,
+      ModularNamer namer,
+      ModularEmitter emitter);
 }
 
 class SsaBuilderTask extends CompilerTask {
-  final JavaScriptBackend _backend;
+  final BackendStrategy _backendStrategy;
   final SourceInformationStrategy _sourceInformationFactory;
   SsaBuilder _builder;
 
-  SsaBuilderTask(this._backend, this._sourceInformationFactory)
-      : super(_backend.compiler.measurer);
+  SsaBuilderTask(
+      Measurer measurer, this._backendStrategy, this._sourceInformationFactory)
+      : super(measurer);
 
   @override
   String get name => 'SSA builder';
 
   void onCodegenStart() {
-    _builder = _backend.compiler.backendStrategy
-        .createSsaBuilder(this, _backend, _sourceInformationFactory);
+    _builder =
+        _backendStrategy.createSsaBuilder(this, _sourceInformationFactory);
   }
 
-  /// Creates the [HGraph] for [work] or returns `null` if no code is needed
-  /// for [work].
-  HGraph build(CodegenWorkItem work, JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
-    return _builder.build(work, closedWorld, globalInferenceResults);
-  }
-}
-
-abstract class SsaBuilderFieldMixin {
-  /// Handle field initializer of [element]. Returns `true` if no code
-  /// is needed for the field.
-  ///
-  /// If [element] is a field with a constant initializer, the value is
-  /// registered with the world impact. Otherwise the cyclic-throw helper is
-  /// registered for the lazy value computation.
-  ///
-  /// If the field is constant, no code is needed for the field and the method
-  /// returns `true`.
-  bool handleConstantField(MemberEntity element, CodegenRegistry registry,
-      JClosedWorld closedWorld) {
-    if (element.isField) {
-      FieldAnalysisData fieldData =
-          closedWorld.fieldAnalysis.getFieldData(element);
-      if (fieldData.initialValue != null) {
-        registry.worldImpact
-            .registerConstantUse(new ConstantUse.init(fieldData.initialValue));
-        // We don't need to generate code for static or top-level
-        // variables. For instance variables, we may need to generate
-        // the checked setter.
-        if (element.isStatic || element.isTopLevel) {
-          /// No code is created for this field: All references inline the
-          /// constant value.
-          return true;
-        }
-      } else if (fieldData.isLazy) {
-        // The generated initializer needs be wrapped in the cyclic-error
-        // helper.
-        registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke(
-            closedWorld.commonElements.cyclicThrowHelper,
-            CallStructure.ONE_ARG));
-      }
-    }
-    return false;
+  /// Creates the [HGraph] for [member] or returns `null` if no code is needed
+  /// for [member].
+  HGraph build(
+      MemberEntity member,
+      JClosedWorld closedWorld,
+      GlobalTypeInferenceResults globalInferenceResults,
+      CodegenInputs codegen,
+      CodegenRegistry registry,
+      ModularNamer namer,
+      ModularEmitter emitter) {
+    return _builder.build(member, closedWorld, globalInferenceResults, codegen,
+        registry, namer, emitter);
   }
 }
diff --git a/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart b/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
index 5f2e064..9383983 100644
--- a/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
@@ -3,9 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import '../common.dart';
+import '../inferrer/abstract_value_domain.dart';
 import '../io/source_information.dart';
 
-import 'graph_builder.dart';
+import 'builder_kernel.dart';
 import 'locals_handler.dart';
 import 'nodes.dart';
 
@@ -20,11 +21,14 @@
 }
 
 class SsaBranchBuilder {
-  final GraphBuilder builder;
+  final KernelSsaGraphBuilder builder;
   final Spannable diagnosticNode;
 
   SsaBranchBuilder(this.builder, [this.diagnosticNode]);
 
+  AbstractValueDomain get _abstractValueDomain =>
+      builder.closedWorld.abstractValueDomain;
+
   void checkNotAborted() {
     if (builder.isAborted()) {
       failedAt(diagnosticNode, "aborted control flow");
@@ -42,7 +46,7 @@
     checkNotAborted();
     assert(identical(builder.current, builder.lastOpenedBlock));
     HInstruction conditionValue = builder.popBoolified();
-    HIf branch = new HIf(builder.abstractValueDomain, conditionValue)
+    HIf branch = new HIf(_abstractValueDomain, conditionValue)
       ..sourceInformation = sourceInformation;
     HBasicBlock conditionExitBlock = builder.current;
     builder.close(branch);
@@ -159,9 +163,8 @@
       boolifiedLeft = builder.popBoolified();
       builder.stack.add(boolifiedLeft);
       if (!isAnd) {
-        builder.push(
-            new HNot(builder.pop(), builder.abstractValueDomain.boolType)
-              ..sourceInformation = sourceInformation);
+        builder.push(new HNot(builder.pop(), _abstractValueDomain.boolType)
+          ..sourceInformation = sourceInformation);
       }
     }
 
@@ -177,7 +180,7 @@
     HPhi result = new HPhi.manyInputs(
         null,
         <HInstruction>[boolifiedRight, notIsAnd],
-        builder.abstractValueDomain.dynamicType)
+        _abstractValueDomain.dynamicType)
       ..sourceInformation = sourceInformation;
     builder.current.addPhi(result);
     builder.stack.add(result);
@@ -204,7 +207,7 @@
     if (isExpression) {
       assert(thenValue != null && elseValue != null);
       HPhi phi = new HPhi.manyInputs(null, <HInstruction>[thenValue, elseValue],
-          builder.abstractValueDomain.dynamicType);
+          _abstractValueDomain.dynamicType);
       joinBranch.block.addPhi(phi);
       builder.stack.add(phi);
     }
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 40770be..95bfbb5 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -7,7 +7,7 @@
 import '../../compiler_new.dart' show OutputSink;
 import '../diagnostics/invariant.dart' show DEBUG_MODE;
 import '../inferrer/abstract_value_domain.dart';
-import '../js_backend/namer.dart' show Namer;
+import '../js_backend/namer.dart' show suffixForGetInterceptor;
 import '../tracer.dart';
 import '../world.dart' show JClosedWorld;
 import 'nodes.dart';
@@ -17,11 +17,10 @@
 /// to enable it.
 class HTracer extends HGraphVisitor with TracerUtil {
   final JClosedWorld closedWorld;
-  final Namer namer;
   @override
   final OutputSink output;
 
-  HTracer(this.output, this.closedWorld, this.namer);
+  HTracer(this.output, this.closedWorld);
 
   void traceGraph(String name, HGraph graph) {
     DEBUG_MODE = true;
@@ -76,7 +75,7 @@
   @override
   void visitBasicBlock(HBasicBlock block) {
     HInstructionStringifier stringifier =
-        new HInstructionStringifier(block, closedWorld, namer);
+        new HInstructionStringifier(block, closedWorld);
     assert(block.id != null);
     tag("block", () {
       printProperty("name", "B${block.id}");
@@ -114,10 +113,9 @@
 
 class HInstructionStringifier implements HVisitor<String> {
   final JClosedWorld closedWorld;
-  final Namer namer;
   final HBasicBlock currentBlock;
 
-  HInstructionStringifier(this.currentBlock, this.closedWorld, this.namer);
+  HInstructionStringifier(this.currentBlock, this.closedWorld);
 
   AbstractValueDomain get _abstractValueDomain =>
       closedWorld.abstractValueDomain;
@@ -175,11 +173,6 @@
     return "LateValue: ${temporaryId(node.inputs[0])}";
   }
 
-  @override
-  String visitBoolify(HBoolify node) {
-    return "Boolify: ${temporaryId(node.inputs[0])}";
-  }
-
   String handleInvokeBinary(HInvokeBinary node, String opcode) {
     String left = temporaryId(node.left);
     String right = temporaryId(node.right);
@@ -356,8 +349,9 @@
   String visitInterceptor(HInterceptor node) {
     String value = temporaryId(node.inputs[0]);
     if (node.interceptedClasses != null) {
-      String cls = namer.suffixForGetInterceptor(node.interceptedClasses);
-      return "Interceptor ($cls): $value";
+      String cls = suffixForGetInterceptor(closedWorld.commonElements,
+          closedWorld.nativeData, node.interceptedClasses);
+      return "Interceptor (${cls}): $value";
     }
     return "Interceptor: $value";
   }
@@ -372,7 +366,8 @@
     String target = "$receiver.$name";
     int offset = HInvoke.ARGUMENTS_OFFSET;
     List arguments = invoke.inputs.sublist(offset);
-    return handleGenericInvoke(kind, target, arguments) + "(${invoke.mask})";
+    return handleGenericInvoke(kind, target, arguments) +
+        "(${invoke.receiverType})";
   }
 
   @override
@@ -609,22 +604,32 @@
   }
 
   String _typeConversionKind(HTypeConversion node) {
-    switch (node.kind) {
-      case HTypeConversion.CHECKED_MODE_CHECK:
-        return 'CHECKED_MODE';
-      case HTypeConversion.ARGUMENT_TYPE_CHECK:
-        return 'ARGUMENT';
-      case HTypeConversion.CAST_TYPE_CHECK:
-        return 'CAST';
-      case HTypeConversion.BOOLEAN_CONVERSION_CHECK:
-        return 'BOOLEAN_CONVERSION';
-      case HTypeConversion.RECEIVER_TYPE_CHECK:
-        return 'RECEIVER';
-    }
+    if (node.isTypeCheck) return 'TYPE_CHECK';
+    if (node.isCastCheck) return 'CAST_CHECK';
     return '?';
   }
 
   @override
+  String visitPrimitiveCheck(HPrimitiveCheck node) {
+    String checkedInput = temporaryId(node.checkedInput);
+    assert(node.inputs.length == 1);
+    String kind = _primitiveCheckKind(node);
+    return "PrimitiveCheck: $kind $checkedInput to ${node.instructionType}";
+  }
+
+  String _primitiveCheckKind(HPrimitiveCheck node) {
+    if (node.isReceiverTypeCheck) return 'RECEIVER';
+    if (node.isArgumentTypeCheck) return 'ARGUMENT';
+    return '?';
+  }
+
+  @override
+  String visitBoolConversion(HBoolConversion node) {
+    String checkedInput = temporaryId(node.checkedInput);
+    return "BoolConversion: $checkedInput";
+  }
+
+  @override
   String visitTypeKnown(HTypeKnown node) {
     assert(node.inputs.length <= 2);
     String result =
@@ -668,4 +673,41 @@
   String visitYield(HYield node) {
     return "Yield${node.hasStar ? "*" : ""}: ${temporaryId(node.inputs[0])}";
   }
+
+  @override
+  visitIsTest(HIsTest node) {
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    return "IsTest: $inputs";
+  }
+
+  @override
+  visitAsCheck(HAsCheck node) {
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    String error = node.isTypeError ? 'TypeError' : 'CastError';
+    return "AsCheck: $error $inputs";
+  }
+
+  @override
+  visitSubtypeCheck(HSubtypeCheck node) {
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    return "SubtypeCheck: $inputs";
+  }
+
+  @override
+  visitLoadType(HLoadType node) {
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    return "LoadType: $inputs";
+  }
+
+  @override
+  visitTypeEval(HTypeEval node) {
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    return "TypeEval: $inputs";
+  }
+
+  @override
+  visitTypeBind(HTypeBind node) {
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    return "TypeBind: $inputs";
+  }
 }
diff --git a/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart b/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
index bebc7e6..1733898 100644
--- a/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
+++ b/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
@@ -1,3 +1,7 @@
+// Copyright (c) 2017, 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:kernel/ast.dart' as ir;
 
 /// Helper class that traverses a kernel AST subtree to see if it has any
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index bb7e4ed..0a5d8fe 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -2,13 +2,14 @@
 // 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 'graph_builder.dart';
+import 'builder_kernel.dart';
 import 'nodes.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../inferrer/abstract_value_domain.dart';
 import '../io/source_information.dart';
 import '../universe/use.dart' show TypeUse;
+import '../world.dart';
 
 /// Enum that defines how a member has access to the current type variables.
 enum ClassTypeVariableAccess {
@@ -35,9 +36,15 @@
 /// Functions to insert type checking, coercion, and instruction insertion
 /// depending on the environment for dart code.
 abstract class TypeBuilder {
-  final GraphBuilder builder;
+  final KernelSsaGraphBuilder builder;
+
   TypeBuilder(this.builder);
 
+  JClosedWorld get _closedWorld => builder.closedWorld;
+
+  AbstractValueDomain get _abstractValueDomain =>
+      _closedWorld.abstractValueDomain;
+
   /// Create a type mask for 'trusting' a DartType. Returns `null` if there is
   /// no approximating type mask (i.e. the type mask would be `dynamic`).
   AbstractValue trustTypeMask(DartType type) {
@@ -46,10 +53,10 @@
     type = type.unaliased;
     if (type.isDynamic) return null;
     if (!type.isInterfaceType) return null;
-    if (type == builder.commonElements.objectType) return null;
+    if (type == _closedWorld.commonElements.objectType) return null;
     // The type element is either a class or the void element.
     ClassEntity element = (type as InterfaceType).element;
-    return builder.abstractValueDomain.createNullableSubtype(element);
+    return _abstractValueDomain.createNullableSubtype(element);
   }
 
   /// Create an instruction to simply trust the provided type.
@@ -78,6 +85,19 @@
     return other;
   }
 
+  /// Produces code that checks the runtime type is actually the type specified
+  /// by attempting a type conversion.
+  HInstruction _checkBoolConverion(HInstruction original) {
+    var checkInstruction =
+        HBoolConversion(original, _abstractValueDomain.boolType);
+    if (checkInstruction.isRedundant(_closedWorld)) {
+      return original;
+    }
+    DartType boolType = _closedWorld.commonElements.boolType;
+    builder.registry?.registerTypeUse(new TypeUse.isCheck(boolType));
+    return checkInstruction;
+  }
+
   HInstruction trustTypeOfParameter(HInstruction original, DartType type) {
     if (type == null) return original;
     HInstruction trusted = _trustType(original, type);
@@ -96,8 +116,7 @@
     if (builder.options.parameterCheckPolicy.isTrusted) {
       checkedOrTrusted = _trustType(original, type);
     } else if (builder.options.parameterCheckPolicy.isEmitted) {
-      checkedOrTrusted =
-          _checkType(original, type, HTypeConversion.CHECKED_MODE_CHECK);
+      checkedOrTrusted = _checkType(original, type, HTypeConversion.TYPE_CHECK);
     }
     if (checkedOrTrusted == original) return original;
     builder.add(checkedOrTrusted);
@@ -109,7 +128,7 @@
   /// trusts the written type.
   HInstruction potentiallyCheckOrTrustTypeOfAssignment(
       HInstruction original, DartType type,
-      {int kind: HTypeConversion.CHECKED_MODE_CHECK}) {
+      {int kind: HTypeConversion.TYPE_CHECK}) {
     if (type == null) return original;
     HInstruction checkedOrTrusted = original;
     if (builder.options.assignmentCheckPolicy.isTrusted) {
@@ -123,13 +142,12 @@
   }
 
   HInstruction potentiallyCheckOrTrustTypeOfCondition(HInstruction original) {
-    DartType boolType = builder.commonElements.boolType;
+    DartType boolType = _closedWorld.commonElements.boolType;
     HInstruction checkedOrTrusted = original;
     if (builder.options.conditionCheckPolicy.isTrusted) {
       checkedOrTrusted = _trustType(original, boolType);
     } else if (builder.options.conditionCheckPolicy.isEmitted) {
-      checkedOrTrusted = _checkType(
-          original, boolType, HTypeConversion.BOOLEAN_CONVERSION_CHECK);
+      checkedOrTrusted = _checkBoolConverion(original);
     }
     if (checkedOrTrusted == original) return original;
     builder.add(checkedOrTrusted);
@@ -194,11 +212,11 @@
     HInstruction target =
         builder.localsHandler.readThis(sourceInformation: sourceInformation);
     HInstruction interceptor =
-        new HInterceptor(target, builder.abstractValueDomain.nonNullType)
+        new HInterceptor(target, _abstractValueDomain.nonNullType)
           ..sourceInformation = sourceInformation;
     builder.add(interceptor);
     builder.push(new HTypeInfoReadVariable.intercepted(
-        variable, interceptor, target, builder.abstractValueDomain.dynamicType)
+        variable, interceptor, target, _abstractValueDomain.dynamicType)
       ..sourceInformation = sourceInformation);
     return builder.pop();
   }
@@ -218,9 +236,9 @@
     }
     HInstruction representation = new HTypeInfoExpression(
         TypeInfoExpressionKind.INSTANCE,
-        builder.closedWorld.elementEnvironment.getThisType(interface.element),
+        _closedWorld.elementEnvironment.getThisType(interface.element),
         inputs,
-        builder.abstractValueDomain.dynamicType)
+        _abstractValueDomain.dynamicType)
       ..sourceInformation = sourceInformation;
     return representation;
   }
@@ -231,7 +249,7 @@
     argument = argument.unaliased;
     if (argument.treatAsDynamic) {
       // Represent [dynamic] as [null].
-      return builder.graph.addConstantNull(builder.closedWorld);
+      return builder.graph.addConstantNull(_closedWorld);
     }
 
     if (argument.isTypeVariable) {
@@ -249,14 +267,12 @@
         TypeInfoExpressionKind.COMPLETE,
         argument,
         inputs,
-        builder.abstractValueDomain.dynamicType)
+        _abstractValueDomain.dynamicType)
       ..sourceInformation = sourceInformation;
     builder.add(result);
     return result;
   }
 
-  bool get checkOrTrustTypes => true;
-
   /// Build a [HTypeConversion] for converting [original] to type [type].
   ///
   /// Invariant: [type] must be valid in the context.
@@ -268,8 +284,8 @@
     type = type.unaliased;
     if (type.isInterfaceType && !type.treatAsRaw) {
       InterfaceType interfaceType = type;
-      AbstractValue subtype = builder.abstractValueDomain
-          .createNullableSubtype(interfaceType.element);
+      AbstractValue subtype =
+          _abstractValueDomain.createNullableSubtype(interfaceType.element);
       HInstruction representations = buildTypeArgumentRepresentations(
           type, builder.sourceElement, sourceInformation);
       builder.add(representations);
@@ -292,7 +308,7 @@
           type, kind, refinedMask, original, reifiedType)
         ..sourceInformation = sourceInformation;
     } else {
-      return original.convertType(builder.closedWorld, type, kind)
+      return original.convertType(_closedWorld, type, kind)
         ..sourceInformation = sourceInformation;
     }
   }
diff --git a/pkg/compiler/lib/src/ssa/types.dart b/pkg/compiler/lib/src/ssa/types.dart
index 4fa5ee5..1795329 100644
--- a/pkg/compiler/lib/src/ssa/types.dart
+++ b/pkg/compiler/lib/src/ssa/types.dart
@@ -29,9 +29,9 @@
         results.closedWorld.abstractValueDomain.dynamicType;
   }
 
-  static AbstractValue inferredTypeForSelector(Selector selector,
+  static AbstractValue inferredResultTypeForSelector(Selector selector,
       AbstractValue receiver, GlobalTypeInferenceResults results) {
-    return results.typeOfSelector(selector, receiver) ??
+    return results.resultTypeOfSelector(selector, receiver) ??
         results.closedWorld.abstractValueDomain.dynamicType;
   }
 
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index e716108..257ce71 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -222,24 +222,29 @@
     HInstruction input = instruction.checkedInput;
     AbstractValue inputType = input.instructionType;
     AbstractValue checkedType = instruction.checkedType;
-    if (instruction.isArgumentTypeCheck || instruction.isReceiverTypeCheck) {
-      // We must make sure a type conversion for receiver or argument check
-      // does not try to do an int check, because an int check is not enough.
-      // We only do an int check if the input is integer or null.
-      if (abstractValueDomain.isNumberOrNull(checkedType).isDefinitelyTrue &&
-          abstractValueDomain.isDoubleOrNull(checkedType).isDefinitelyFalse &&
-          input.isIntegerOrNull(abstractValueDomain).isDefinitelyTrue) {
-        instruction.checkedType = abstractValueDomain.intType;
-      } else if (abstractValueDomain
-              .isIntegerOrNull(checkedType)
-              .isDefinitelyTrue &&
-          input.isIntegerOrNull(abstractValueDomain).isPotentiallyFalse) {
-        instruction.checkedType = abstractValueDomain.numType;
-      }
-    }
-
     AbstractValue outputType =
         abstractValueDomain.intersection(checkedType, inputType);
+    outputType = _numericFixup(outputType, inputType, checkedType);
+    if (inputType != outputType) {
+      // Replace dominated uses of input with uses of this HTypeConversion so
+      // the uses benefit from the stronger type.
+      //
+      // The dependency on the checked value also improves the generated
+      // JavaScript. Many checks are compiled to a function call expression that
+      // returns the checked result, so the check can be generated as a
+      // subexpression rather than a separate statement.
+      //
+      // Do not replace local accesses, since the local must be a HLocalValue,
+      // not a HTypeConversion.
+      if (!(input is HParameterValue && input.usedAsVariable())) {
+        input.replaceAllUsersDominatedBy(instruction.next, instruction);
+      }
+    }
+    return outputType;
+  }
+
+  AbstractValue _numericFixup(AbstractValue outputType, AbstractValue inputType,
+      AbstractValue checkedType) {
     if (abstractValueDomain.isEmpty(outputType).isDefinitelyTrue) {
       // Intersection of double and integer conflicts (is empty), but JS numbers
       // can be both int and double at the same time.  For example, the input
@@ -257,17 +262,38 @@
         }
       }
     }
+    return outputType;
+  }
+
+  @override
+  AbstractValue visitPrimitiveCheck(HPrimitiveCheck instruction) {
+    HInstruction input = instruction.checkedInput;
+    AbstractValue inputType = input.instructionType;
+    AbstractValue checkedType = instruction.checkedType;
+
+    // We must make sure a receiver or argument check does not try to do an int
+    // check, because an int check is not enough.  We only do an int check if
+    // the input is integer or null.
+    if (abstractValueDomain.isNumberOrNull(checkedType).isDefinitelyTrue &&
+        abstractValueDomain.isDoubleOrNull(checkedType).isDefinitelyFalse &&
+        input.isIntegerOrNull(abstractValueDomain).isDefinitelyTrue) {
+      instruction.checkedType = abstractValueDomain.intType;
+    } else if (abstractValueDomain
+            .isIntegerOrNull(checkedType)
+            .isDefinitelyTrue &&
+        input.isIntegerOrNull(abstractValueDomain).isPotentiallyFalse) {
+      instruction.checkedType = abstractValueDomain.numType;
+    }
+
+    AbstractValue outputType =
+        abstractValueDomain.intersection(checkedType, inputType);
+    outputType = _numericFixup(outputType, inputType, checkedType);
     if (inputType != outputType) {
-      // Replace dominated uses of input with uses of this HTypeConversion so
+      // Replace dominated uses of input with uses of this HPrimitiveCheck so
       // the uses benefit from the stronger type.
       //
-      // The dependency on the checked value also improves the generated
-      // JavaScript. Many checks are compiled to a function call expression that
-      // returns the checked result, so the check can be generated as a
-      // subexpression rather than a separate statement.
-      //
-      // Do not replace local accesses, since the local must be a HLocalValue,
-      // not a HTypeConversion.
+      // Do not replace local variable accesses, since the local must be a
+      // HLocalValue, not another kind of instruction.
       if (!(input is HParameterValue && input.usedAsVariable())) {
         input.replaceAllUsersDominatedBy(instruction.next, instruction);
       }
@@ -289,15 +315,17 @@
 
   void convertInput(HInvokeDynamic instruction, HInstruction input,
       AbstractValue type, int kind, DartType typeExpression) {
-    Selector selector = (kind == HTypeConversion.RECEIVER_TYPE_CHECK)
+    assert(kind == HPrimitiveCheck.RECEIVER_TYPE_CHECK ||
+        kind == HPrimitiveCheck.ARGUMENT_TYPE_CHECK);
+    Selector selector = (kind == HPrimitiveCheck.RECEIVER_TYPE_CHECK)
         ? instruction.selector
         : null;
-    HTypeConversion converted = new HTypeConversion(
+    HPrimitiveCheck converted = new HPrimitiveCheck(
         typeExpression, kind, type, input, instruction.sourceInformation,
         receiverTypeCheckSelector: selector);
     instruction.block.addBefore(instruction, converted);
     input.replaceAllUsersDominatedBy(instruction, converted);
-    _log?.registerTypeConversion(instruction, converted);
+    _log?.registerPrimitiveCheck(instruction, converted);
   }
 
   bool isCheckEnoughForNsmOrAe(HInstruction instruction, AbstractValue type) {
@@ -327,16 +355,16 @@
           instruction,
           receiver,
           abstractValueDomain.excludeNull(receiver.instructionType),
-          HTypeConversion.RECEIVER_TYPE_CHECK,
+          HPrimitiveCheck.RECEIVER_TYPE_CHECK,
           commonElements.numType);
       return true;
     } else if (instruction.element == null) {
       if (closedWorld.includesClosureCall(
-          instruction.selector, instruction.mask)) {
+          instruction.selector, instruction.receiverType)) {
         return false;
       }
-      Iterable<MemberEntity> targets =
-          closedWorld.locateMembers(instruction.selector, instruction.mask);
+      Iterable<MemberEntity> targets = closedWorld.locateMembers(
+          instruction.selector, instruction.receiverType);
       if (targets.length == 1) {
         MemberEntity target = targets.first;
         ClassEntity cls = target.enclosingClass;
@@ -353,7 +381,7 @@
         if (!isCheckEnoughForNsmOrAe(receiver, type)) return false;
         instruction.element = target;
         convertInput(instruction, receiver, type,
-            HTypeConversion.RECEIVER_TYPE_CHECK, typeExpression);
+            HPrimitiveCheck.RECEIVER_TYPE_CHECK, typeExpression);
         return true;
       }
     }
@@ -382,7 +410,7 @@
       // still add a check because it allows to GVN these operations,
       // but we should find a better way.
       convertInput(instruction, right, type,
-          HTypeConversion.ARGUMENT_TYPE_CHECK, commonElements.numType);
+          HPrimitiveCheck.ARGUMENT_TYPE_CHECK, commonElements.numType);
       return true;
     }
     return false;
@@ -436,7 +464,7 @@
 
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
     AbstractValue receiverType = receiver.instructionType;
-    instruction.mask = receiverType;
+    instruction.updateReceiverType(abstractValueDomain, receiverType);
 
     // Try to refine that the receiver is not null after this call by inserting
     // a refinement node (HTypeKnown).
diff --git a/pkg/compiler/lib/src/ssa/variable_allocator.dart b/pkg/compiler/lib/src/ssa/variable_allocator.dart
index a9f6e39..33f1006 100644
--- a/pkg/compiler/lib/src/ssa/variable_allocator.dart
+++ b/pkg/compiler/lib/src/ssa/variable_allocator.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import '../common.dart';
-import '../js_backend/js_backend.dart';
+import '../js_backend/namer.dart' show ModularNamer;
 import 'codegen.dart' show CodegenPhase;
 import 'nodes.dart';
 
@@ -450,7 +450,7 @@
 /// Allocates variable names for instructions, making sure they don't collide.
 class VariableNamer {
   final VariableNames names;
-  final Namer _namer;
+  final ModularNamer _namer;
   final Set<String> usedNames;
   final List<String> freeTemporaryNames;
   int temporaryIndex = 0;
@@ -570,7 +570,7 @@
 /// instruction, and allocates a name to the instruction. For each phi,
 /// it adds a copy to the CopyHandler of the corresponding predecessor.
 class SsaVariableAllocator extends HBaseVisitor with CodegenPhase {
-  final Namer _namer;
+  final ModularNamer _namer;
   final Map<HBasicBlock, LiveEnvironment> liveInstructions;
   final Map<HInstruction, LiveInterval> liveIntervals;
   final Set<HInstruction> generateAtUseSite;
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index 2c687bf..c67cafc 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -5,7 +5,6 @@
 library tracer;
 
 import '../compiler_new.dart' as api;
-import 'js_backend/namer.dart' show Namer;
 import 'ssa/nodes.dart' as ssa show HGraph;
 import 'ssa/ssa_tracer.dart' show HTracer;
 import 'util/util.dart' show Indentation;
@@ -24,13 +23,12 @@
 /// readable by IR Hydra.
 class Tracer extends TracerUtil {
   final JClosedWorld closedWorld;
-  final Namer namer;
   bool traceActive = false;
   @override
   final api.OutputSink output;
   final RegExp traceFilter;
 
-  Tracer(this.closedWorld, this.namer, api.CompilerOutput compilerOutput)
+  Tracer(this.closedWorld, api.CompilerOutput compilerOutput)
       : traceFilter = TRACE_FILTER_PATTERN == null
             ? null
             : new RegExp(TRACE_FILTER_PATTERN),
@@ -55,7 +53,7 @@
   void traceGraph(String name, var irObject) {
     if (!traceActive) return;
     if (irObject is ssa.HGraph) {
-      new HTracer(output, closedWorld, namer).traceGraph(name, irObject);
+      new HTracer(output, closedWorld).traceGraph(name, irObject);
     }
   }
 
diff --git a/pkg/compiler/lib/src/universe/call_structure.dart b/pkg/compiler/lib/src/universe/call_structure.dart
index 8c148c8..5410034 100644
--- a/pkg/compiler/lib/src/universe/call_structure.dart
+++ b/pkg/compiler/lib/src/universe/call_structure.dart
@@ -67,6 +67,15 @@
     sink.end(tag);
   }
 
+  /// Returns `true` if this call structure is normalized, that is, its named
+  /// arguments are sorted.
+  bool get isNormalized => true;
+
+  /// Returns the normalized version of this call structure.
+  ///
+  /// A [CallStructure] is normalized if its named arguments are sorted.
+  CallStructure toNormalized() => this;
+
   CallStructure withTypeArgumentCount(int typeArgumentCount) =>
       new CallStructure(argumentCount, namedArguments, typeArgumentCount);
 
@@ -185,17 +194,21 @@
   }
 }
 
-///
+/// Call structure with named arguments.
 class NamedCallStructure extends CallStructure {
   @override
   final List<String> namedArguments;
-  final List<String> _orderedNamedArguments = <String>[];
+  final List<String> _orderedNamedArguments;
 
   NamedCallStructure(
-      int argumentCount, this.namedArguments, int typeArgumentCount)
-      : super.unnamed(argumentCount, typeArgumentCount) {
-    assert(namedArguments.isNotEmpty);
-  }
+      int argumentCount, List<String> namedArguments, int typeArgumentCount)
+      : this.internal(
+            argumentCount, namedArguments, typeArgumentCount, <String>[]);
+
+  NamedCallStructure.internal(int argumentCount, this.namedArguments,
+      int typeArgumentCount, this._orderedNamedArguments)
+      : assert(namedArguments.isNotEmpty),
+        super.unnamed(argumentCount, typeArgumentCount);
 
   @override
   bool get isNamed => true;
@@ -210,6 +223,16 @@
   int get positionalArgumentCount => argumentCount - namedArgumentCount;
 
   @override
+  bool get isNormalized => namedArguments == _orderedNamedArguments;
+
+  @override
+  CallStructure toNormalized() => new NamedCallStructure.internal(
+      argumentCount,
+      getOrderedNamedArguments(),
+      typeArgumentCount,
+      getOrderedNamedArguments());
+
+  @override
   List<String> getOrderedNamedArguments() {
     if (!_orderedNamedArguments.isEmpty) return _orderedNamedArguments;
 
diff --git a/pkg/compiler/lib/src/universe/class_hierarchy.dart b/pkg/compiler/lib/src/universe/class_hierarchy.dart
index 776b4f1..49a899e 100644
--- a/pkg/compiler/lib/src/universe/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/universe/class_hierarchy.dart
@@ -195,10 +195,12 @@
         getClassHierarchyNode(_commonElements.objectClass);
     node.forEachSubclass((ClassEntity cls) {
       getClassHierarchyNode(cls).writeToDataSink(sink);
+      return null;
     }, ClassHierarchyNode.ALL);
     ClassSet set = getClassSet(_commonElements.objectClass);
     set.forEachSubclass((ClassEntity cls) {
       getClassSet(cls).writeToDataSink(sink);
+      return null;
     }, ClassHierarchyNode.ALL);
     sink.end(tag);
   }
@@ -836,6 +838,7 @@
         if (builder._isSubtypeOf(z, y)) {
           classes.add(z);
         }
+        return null;
       }, ClassHierarchyNode.ALL, strict: strict);
     }
 
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index eb54121..afe16e0 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -4,17 +4,19 @@
 
 import 'dart:collection';
 
+import '../common.dart';
 import '../common/names.dart' show Identifiers;
 import '../common_elements.dart';
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
+import '../js_backend/interceptor_data.dart' show OneShotInterceptorData;
 import '../js_backend/native_data.dart' show NativeBasicData;
-import '../js_model/locals.dart';
-import '../js_model/element_map_impl.dart';
+import '../js_model/elements.dart';
 import '../util/enumset.dart';
 import '../util/util.dart';
-import '../world.dart' show JClosedWorld;
+import '../world.dart';
+import 'call_structure.dart';
 import 'member_usage.dart';
 import 'selector.dart' show Selector;
 import 'use.dart'
@@ -25,35 +27,29 @@
 ///
 /// This adds additional access to liveness of selectors and elements.
 abstract class CodegenWorldBuilder implements WorldBuilder {
-  /// All directly or indirectly instantiated classes.
-  Iterable<ClassEntity> get instantiatedClasses;
+  /// Register [constant] as needed for emission.
+  void addCompileTimeConstantForEmission(ConstantValue constant);
 
-  /// Calls [f] with every instance field, together with its declarer, in an
-  /// instance of [cls]. All fields inherited from superclasses and mixins are
-  /// included.
-  ///
-  /// If [isElided] is `true`, the field is not read and should therefore not
-  /// be emitted.
-  void forEachInstanceField(covariant ClassEntity cls,
-      void f(ClassEntity declarer, FieldEntity field, {bool isElided}));
+  /// Close the codegen world builder and return the immutable [CodegenWorld]
+  /// as the result.
+  CodegenWorld close();
+}
 
-  /// Calls [f] with every instance field declared directly in class [cls]
-  /// (i.e. no inherited fields). Fields are presented in initialization
-  /// (i.e. textual) order.
-  ///
-  /// If [isElided] is `true`, the field is not read and should therefore not
-  /// be emitted.
-  void forEachDirectInstanceField(
-      covariant ClassEntity cls, void f(FieldEntity field, {bool isElided}));
+// The immutable result of the [CodegenWorldBuilder].
+abstract class CodegenWorld extends BuiltWorld {
+  /// Calls [f] for each generic call method on a live closure class.
+  void forEachGenericClosureCallMethod(void Function(FunctionEntity) f);
 
-  /// Calls [f] for each parameter of [function] providing the type and name of
-  /// the parameter and the [defaultValue] if the parameter is optional.
-  void forEachParameter(covariant FunctionEntity function,
-      void f(DartType type, String name, ConstantValue defaultValue));
+  bool hasInvokedGetter(MemberEntity member);
 
-  /// Calls [f] for each parameter - given as a [Local] - of [function].
-  void forEachParameterAsLocal(
-      covariant FunctionEntity function, void f(Local parameter));
+  /// Returns `true` if [member] is invoked as a setter.
+  bool hasInvokedSetter(MemberEntity member);
+
+  Map<Selector, SelectorConstraints> invocationsByName(String name);
+
+  Iterable<Selector> getterInvocationsByName(String name);
+
+  Iterable<Selector> setterInvocationsByName(String name);
 
   void forEachInvokedName(
       f(String name, Map<Selector, SelectorConstraints> selectors));
@@ -64,30 +60,25 @@
   void forEachInvokedSetter(
       f(String name, Map<Selector, SelectorConstraints> selectors));
 
-  /// Returns `true` if [member] is invoked as a setter.
-  bool hasInvokedSetter(MemberEntity member);
+  /// All directly instantiated classes, that is, classes with a generative
+  /// constructor that has been called directly and not only through a
+  /// super-call.
+  // TODO(johnniwinther): Improve semantic precision.
+  Iterable<ClassEntity> get directlyInstantiatedClasses;
 
-  bool hasInvokedGetter(MemberEntity member);
+  /// All directly or indirectly instantiated classes.
+  Iterable<ClassEntity> get instantiatedClasses;
 
-  Map<Selector, SelectorConstraints> invocationsByName(String name);
+  bool methodsNeedsSuperGetter(FunctionEntity function);
 
-  Map<Selector, SelectorConstraints> getterInvocationsByName(String name);
+  /// The calls [f] for all static fields.
+  void forEachStaticField(void Function(FieldEntity) f);
 
-  Map<Selector, SelectorConstraints> setterInvocationsByName(String name);
+  /// Returns the types that are live as constant type literals.
+  Iterable<DartType> get constTypeLiterals;
 
-  Iterable<FunctionEntity> get staticFunctionsNeedingGetter;
-  Iterable<FunctionEntity> get methodsNeedingSuperGetter;
-
-  /// The set of all referenced static fields.
-  ///
-  /// Invariant: Elements are declaration elements.
-  Iterable<FieldEntity> get allReferencedStaticFields;
-
-  @override
-  Iterable<FunctionEntity> get closurizedMembers;
-
-  /// Register [constant] as needed for emission.
-  void addCompileTimeConstantForEmission(ConstantValue constant);
+  /// Returns the types that are live as constant type arguments.
+  Iterable<DartType> get liveTypeArguments;
 
   /// Returns a list of constants topologically sorted so that dependencies
   /// appear before the dependent constant.
@@ -95,19 +86,19 @@
   /// [preSortCompare] is a comparator function that gives the constants a
   /// consistent order prior to the topological sort which gives the constants
   /// an ordering that is less sensitive to perturbations in the source code.
-  List<ConstantValue> getConstantsForEmission(
+  Iterable<ConstantValue> getConstantsForEmission(
       [Comparator<ConstantValue> preSortCompare]);
 
-  /// Returns the types that are live as constant type literals.
-  Iterable<DartType> get constTypeLiterals;
+  /// Returns `true` if [member] is called from a subclass via `super`.
+  bool isAliasedSuperMember(MemberEntity member);
 
-  /// Returns the types that are live as constant type arguments.
-  Iterable<DartType> get liveTypeArguments;
+  OneShotInterceptorData get oneShotInterceptorData;
 }
 
 class CodegenWorldBuilderImpl extends WorldBuilderBase
     implements CodegenWorldBuilder {
-  final JClosedWorld _world;
+  final JClosedWorld _closedWorld;
+  final OneShotInterceptorData _oneShotInterceptorData;
 
   /// The set of all directly instantiated classes, that is, classes with a
   /// generative constructor that has been called directly and not only through
@@ -127,15 +118,6 @@
   /// Classes implemented by directly instantiated classes.
   final Set<ClassEntity> _implementedClasses = new Set<ClassEntity>();
 
-  @override
-  final Set<FieldEntity> allReferencedStaticFields = new Set<FieldEntity>();
-
-  @override
-  final Set<FunctionEntity> staticFunctionsNeedingGetter =
-      new Set<FunctionEntity>();
-  @override
-  final Set<FunctionEntity> methodsNeedingSuperGetter =
-      new Set<FunctionEntity>();
   final Map<String, Map<Selector, SelectorConstraints>> _invokedNames =
       <String, Map<Selector, SelectorConstraints>>{};
   final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters =
@@ -148,52 +130,44 @@
 
   Map<ClassEntity, ClassUsage> get classUsageForTesting => _processedClasses;
 
-  /// Map of registered usage of static members of live classes.
-  final Map<Entity, StaticMemberUsage> _staticMemberUsage =
-      <Entity, StaticMemberUsage>{};
-
-  Map<Entity, StaticMemberUsage> get staticMemberUsageForTesting =>
-      _staticMemberUsage;
-
-  /// Map of registered usage of instance members of live classes.
-  final Map<MemberEntity, MemberUsage> _instanceMemberUsage =
+  /// Map of registered usage of static and instance members.
+  final Map<MemberEntity, MemberUsage> _memberUsage =
       <MemberEntity, MemberUsage>{};
 
-  Map<MemberEntity, MemberUsage> get instanceMemberUsageForTesting =>
-      _instanceMemberUsage;
-
-  /// Map containing instance members of live classes that are not yet live
-  /// themselves.
-  final Map<String, Set<MemberUsage>> _instanceMembersByName =
+  /// Map containing instance members of live classes that have not yet been
+  /// fully invoked dynamically.
+  ///
+  /// A method is fully invoked if all is optional parameter have been passed
+  /// in some invocation.
+  final Map<String, Set<MemberUsage>> _invokableInstanceMembersByName =
       <String, Set<MemberUsage>>{};
 
-  /// Map containing instance methods of live classes that are not yet
-  /// closurized.
-  final Map<String, Set<MemberUsage>> _instanceFunctionsByName =
+  /// Map containing instance members of live classes that have not yet been
+  /// read from dynamically.
+  final Map<String, Set<MemberUsage>> _readableInstanceMembersByName =
       <String, Set<MemberUsage>>{};
 
-  @override
-  final Set<DartType> isChecks = new Set<DartType>();
+  /// Map containing instance members of live classes that have not yet been
+  /// written to dynamically.
+  final Map<String, Set<MemberUsage>> _writableInstanceMembersByName =
+      <String, Set<MemberUsage>>{};
 
-  final SelectorConstraintsStrategy selectorConstraintsStrategy;
+  final Set<DartType> _isChecks = new Set<DartType>();
+
+  final SelectorConstraintsStrategy _selectorConstraintsStrategy;
 
   final Set<ConstantValue> _constantValues = new Set<ConstantValue>();
 
-  final JsToWorldBuilder _elementMap;
-
   final Set<DartType> _constTypeLiterals = new Set<DartType>();
   final Set<DartType> _liveTypeArguments = new Set<DartType>();
 
-  CodegenWorldBuilderImpl(
-      this._elementMap, this._world, this.selectorConstraintsStrategy);
+  CodegenWorldBuilderImpl(this._closedWorld, this._selectorConstraintsStrategy,
+      this._oneShotInterceptorData);
 
-  ElementEnvironment get _elementEnvironment => _world.elementEnvironment;
+  ElementEnvironment get _elementEnvironment => _closedWorld.elementEnvironment;
 
-  NativeBasicData get _nativeBasicData => _world.nativeData;
+  NativeBasicData get _nativeBasicData => _closedWorld.nativeData;
 
-  GlobalLocalsMap get _globalLocalsMap => _world.globalLocalsMap;
-
-  @override
   Iterable<ClassEntity> get instantiatedClasses => _processedClasses.keys
       .where((cls) => _processedClasses[cls].isInstantiated);
 
@@ -203,10 +177,6 @@
     return _directlyInstantiatedClasses;
   }
 
-  // TODO(johnniwinther): Improve semantic precision.
-  @override
-  Iterable<InterfaceType> get instantiatedTypes => _instantiatedTypes;
-
   /// Register [type] as (directly) instantiated.
   // TODO(johnniwinther): Fully enforce the separation between exact, through
   // subclass and through subtype instantiated types/classes.
@@ -252,34 +222,51 @@
     return false;
   }
 
-  bool hasInvocation(MemberEntity member) {
-    return _hasMatchingSelector(_invokedNames[member.name], member, _world);
+  Iterable<CallStructure> _getMatchingCallStructures(
+      Map<Selector, SelectorConstraints> selectors, MemberEntity member) {
+    if (selectors == null) return const <CallStructure>[];
+    Set<CallStructure> callStructures;
+    for (Selector selector in selectors.keys) {
+      if (selector.appliesUnnamed(member)) {
+        SelectorConstraints masks = selectors[selector];
+        if (masks.canHit(member, selector.memberName, _closedWorld)) {
+          callStructures ??= new Set<CallStructure>();
+          callStructures.add(selector.callStructure);
+        }
+      }
+    }
+    return callStructures ?? const <CallStructure>[];
   }
 
-  @override
-  bool hasInvokedGetter(MemberEntity member) {
-    return _hasMatchingSelector(_invokedGetters[member.name], member, _world) ||
-        member.isFunction && methodsNeedingSuperGetter.contains(member);
+  Iterable<CallStructure> _getInvocationCallStructures(MemberEntity member) {
+    return _getMatchingCallStructures(_invokedNames[member.name], member);
   }
 
-  @override
-  bool hasInvokedSetter(MemberEntity member) {
-    return _hasMatchingSelector(_invokedSetters[member.name], member, _world);
+  bool _hasInvokedGetter(MemberEntity member) {
+    return _hasMatchingSelector(
+        _invokedGetters[member.name], member, _closedWorld);
   }
 
-  bool registerDynamicUse(
+  bool _hasInvokedSetter(MemberEntity member) {
+    return _hasMatchingSelector(
+        _invokedSetters[member.name], member, _closedWorld);
+  }
+
+  void registerDynamicUse(
       DynamicUse dynamicUse, MemberUsedCallback memberUsed) {
     Selector selector = dynamicUse.selector;
     String methodName = selector.name;
 
-    void _process(Map<String, Set<MemberUsage>> memberMap,
-        EnumSet<MemberUse> action(MemberUsage usage)) {
+    void _process(
+        Map<String, Set<MemberUsage>> memberMap,
+        EnumSet<MemberUse> action(MemberUsage usage),
+        bool shouldBeRemoved(MemberUsage usage)) {
       _processSet(memberMap, methodName, (MemberUsage usage) {
         if (selector.appliesUnnamed(usage.entity) &&
-            selectorConstraintsStrategy.appliedUnnamed(
-                dynamicUse, usage.entity, _world)) {
+            _selectorConstraintsStrategy.appliedUnnamed(
+                dynamicUse, usage.entity, _closedWorld)) {
           memberUsed(usage.entity, action(usage));
-          return true;
+          return shouldBeRemoved(usage);
         }
         return false;
       });
@@ -290,27 +277,31 @@
         registerDynamicInvocation(
             dynamicUse.selector, dynamicUse.typeArguments);
         if (_registerNewSelector(dynamicUse, _invokedNames)) {
-          // We don't track parameters in the codegen world builder, so we
-          // pass `null` instead of the concrete call structure.
-          _process(_instanceMembersByName, (m) => m.invoke(null));
-          return true;
+          _process(
+              _invokableInstanceMembersByName,
+              (m) => m.invoke(Accesses.dynamicAccess, selector.callStructure),
+              // If not all optional parameters have been passed in invocations
+              // we must keep the member in [_invokableInstanceMembersByName].
+              (u) => !u.hasPendingDynamicInvoke);
         }
         break;
       case DynamicUseKind.GET:
         if (_registerNewSelector(dynamicUse, _invokedGetters)) {
-          _process(_instanceMembersByName, (m) => m.read());
-          _process(_instanceFunctionsByName, (m) => m.read());
-          return true;
+          _process(
+              _readableInstanceMembersByName,
+              (m) => m.read(Accesses.dynamicAccess),
+              (u) => !u.hasPendingDynamicRead);
         }
         break;
       case DynamicUseKind.SET:
         if (_registerNewSelector(dynamicUse, _invokedSetters)) {
-          _process(_instanceMembersByName, (m) => m.write());
-          return true;
+          _process(
+              _writableInstanceMembersByName,
+              (m) => m.write(Accesses.dynamicAccess),
+              (u) => !u.hasPendingDynamicWrite);
         }
         break;
     }
-    return false;
   }
 
   bool _registerNewSelector(DynamicUse dynamicUse,
@@ -322,144 +313,80 @@
         selectorMap[name] ??= new Maplet<Selector, SelectorConstraints>();
     UniverseSelectorConstraints constraints = selectors[selector];
     if (constraints == null) {
-      selectors[selector] = selectorConstraintsStrategy
+      selectors[selector] = _selectorConstraintsStrategy
           .createSelectorConstraints(selector, constraint);
       return true;
     }
     return constraints.addReceiverConstraint(constraint);
   }
 
-  Map<Selector, SelectorConstraints> _asUnmodifiable(
-      Map<Selector, SelectorConstraints> map) {
-    if (map == null) return null;
-    return new UnmodifiableMapView(map);
-  }
-
-  @override
-  Map<Selector, SelectorConstraints> invocationsByName(String name) {
-    return _asUnmodifiable(_invokedNames[name]);
-  }
-
-  @override
-  Map<Selector, SelectorConstraints> getterInvocationsByName(String name) {
-    return _asUnmodifiable(_invokedGetters[name]);
-  }
-
-  @override
-  Map<Selector, SelectorConstraints> setterInvocationsByName(String name) {
-    return _asUnmodifiable(_invokedSetters[name]);
-  }
-
-  @override
-  void forEachInvokedName(
-      f(String name, Map<Selector, SelectorConstraints> selectors)) {
-    _invokedNames.forEach(f);
-  }
-
-  @override
-  void forEachInvokedGetter(
-      f(String name, Map<Selector, SelectorConstraints> selectors)) {
-    _invokedGetters.forEach(f);
-  }
-
-  @override
-  void forEachInvokedSetter(
-      f(String name, Map<Selector, SelectorConstraints> selectors)) {
-    _invokedSetters.forEach(f);
-  }
-
   void registerIsCheck(covariant DartType type) {
-    isChecks.add(type.unaliased);
-  }
-
-  void _registerStaticUse(StaticUse staticUse) {
-    if (staticUse.element is FieldEntity) {
-      FieldEntity field = staticUse.element;
-      if (field.isTopLevel || field.isStatic) {
-        allReferencedStaticFields.add(field);
-      }
-    }
-    switch (staticUse.kind) {
-      case StaticUseKind.STATIC_TEAR_OFF:
-        staticFunctionsNeedingGetter.add(staticUse.element);
-        break;
-      case StaticUseKind.SUPER_TEAR_OFF:
-        methodsNeedingSuperGetter.add(staticUse.element);
-        break;
-      case StaticUseKind.SUPER_FIELD_SET:
-      case StaticUseKind.FIELD_SET:
-      case StaticUseKind.CLOSURE:
-      case StaticUseKind.CLOSURE_CALL:
-      case StaticUseKind.CALL_METHOD:
-      case StaticUseKind.FIELD_GET:
-      case StaticUseKind.CONSTRUCTOR_INVOKE:
-      case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
-      case StaticUseKind.REDIRECTION:
-      case StaticUseKind.DIRECT_INVOKE:
-      case StaticUseKind.INLINING:
-      case StaticUseKind.INVOKE:
-      case StaticUseKind.GET:
-      case StaticUseKind.SET:
-      case StaticUseKind.FIELD_INIT:
-      case StaticUseKind.FIELD_CONSTANT_INIT:
-        break;
-    }
+    _isChecks.add(type.unaliased);
   }
 
   void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
-    Entity element = staticUse.element;
-    _registerStaticUse(staticUse);
-    StaticMemberUsage usage = _staticMemberUsage.putIfAbsent(element, () {
-      if (element is MemberEntity &&
-          (element.isStatic || element.isTopLevel) &&
-          element.isFunction) {
-        return new StaticFunctionUsage(element);
-      } else {
-        return new GeneralStaticMemberUsage(element);
-      }
-    });
+    MemberEntity element = staticUse.element;
     EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
+    MemberUsage usage = _getMemberUsage(element, useSet);
     switch (staticUse.kind) {
       case StaticUseKind.STATIC_TEAR_OFF:
-        closurizedStatics.add(element);
-        useSet.addAll(usage.tearOff());
+        useSet.addAll(usage.read(Accesses.staticAccess));
         break;
-      case StaticUseKind.FIELD_GET:
-      case StaticUseKind.FIELD_SET:
-      case StaticUseKind.CLOSURE:
-      case StaticUseKind.CLOSURE_CALL:
+      case StaticUseKind.INSTANCE_FIELD_GET:
+      case StaticUseKind.INSTANCE_FIELD_SET:
       case StaticUseKind.CALL_METHOD:
         // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and
         // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue.
         // Also [CLOSURE] contains [LocalFunctionElement] which we cannot
         // enqueue.
         break;
-      case StaticUseKind.INVOKE:
+      case StaticUseKind.SUPER_INVOKE:
         registerStaticInvocation(staticUse);
-        useSet.addAll(usage.normalUse());
+        useSet.addAll(
+            usage.invoke(Accesses.superAccess, staticUse.callStructure));
+        break;
+      case StaticUseKind.STATIC_INVOKE:
+        registerStaticInvocation(staticUse);
+        useSet.addAll(
+            usage.invoke(Accesses.staticAccess, staticUse.callStructure));
         break;
       case StaticUseKind.SUPER_FIELD_SET:
+        useSet.addAll(usage.write(Accesses.superAccess));
+        break;
+      case StaticUseKind.SUPER_SETTER_SET:
+        useSet.addAll(usage.write(Accesses.superAccess));
+        break;
+      case StaticUseKind.STATIC_SET:
+        useSet.addAll(usage.write(Accesses.staticAccess));
+        break;
       case StaticUseKind.SUPER_TEAR_OFF:
-      case StaticUseKind.GET:
-      case StaticUseKind.SET:
+        useSet.addAll(usage.read(Accesses.superAccess));
+        break;
+      case StaticUseKind.SUPER_GET:
+        useSet.addAll(usage.read(Accesses.superAccess));
+        break;
+      case StaticUseKind.STATIC_GET:
+        useSet.addAll(usage.read(Accesses.staticAccess));
+        break;
       case StaticUseKind.FIELD_INIT:
+        useSet.addAll(usage.init());
+        break;
       case StaticUseKind.FIELD_CONSTANT_INIT:
-        useSet.addAll(usage.normalUse());
+        useSet.addAll(usage.constantInit(staticUse.constant));
         break;
       case StaticUseKind.CONSTRUCTOR_INVOKE:
       case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
-      case StaticUseKind.REDIRECTION:
-        useSet.addAll(usage.normalUse());
+        // We don't track parameters in the codegen world builder, so we
+        // pass `null` instead of the concrete call structure.
+        useSet.addAll(
+            usage.invoke(Accesses.staticAccess, staticUse.callStructure));
         break;
       case StaticUseKind.DIRECT_INVOKE:
         MemberEntity member = staticUse.element;
-        MemberUsage instanceUsage = _getMemberUsage(member, memberUsed);
         // We don't track parameters in the codegen world builder, so we
         // pass `null` instead of the concrete call structure.
-        memberUsed(instanceUsage.entity, instanceUsage.invoke(null));
-        _instanceMembersByName[instanceUsage.entity.name]
-            ?.remove(instanceUsage);
-        useSet.addAll(usage.normalUse());
+        useSet.addAll(
+            usage.invoke(Accesses.staticAccess, staticUse.callStructure));
         if (staticUse.typeArguments?.isNotEmpty ?? false) {
           registerDynamicInvocation(
               new Selector.call(member.memberName, staticUse.callStructure),
@@ -469,78 +396,110 @@
       case StaticUseKind.INLINING:
         registerStaticInvocation(staticUse);
         break;
+      case StaticUseKind.CLOSURE:
+      case StaticUseKind.CLOSURE_CALL:
+        failedAt(CURRENT_ELEMENT_SPANNABLE,
+            "Static use ${staticUse.kind} is not supported during codegen.");
     }
     if (useSet.isNotEmpty) {
       memberUsed(usage.entity, useSet);
     }
   }
 
-  /// Registers that [element] has been closurized.
-  void registerClosurizedMember(MemberEntity element) {
-    closurizedMembers.add(element);
-  }
-
   void processClassMembers(ClassEntity cls, MemberUsedCallback memberUsed,
-      {bool dryRun: false}) {
+      {bool checkEnqueuerConsistency: false}) {
     _elementEnvironment.forEachClassMember(cls,
         (ClassEntity cls, MemberEntity member) {
-      _processInstantiatedClassMember(cls, member, memberUsed, dryRun: dryRun);
+      _processInstantiatedClassMember(cls, member, memberUsed,
+          checkEnqueuerConsistency: checkEnqueuerConsistency);
     });
   }
 
-  void _processInstantiatedClassMember(ClassEntity cls,
-      covariant MemberEntity member, MemberUsedCallback memberUsed,
-      {bool dryRun: false}) {
+  void _processInstantiatedClassMember(
+      ClassEntity cls, MemberEntity member, MemberUsedCallback memberUsed,
+      {bool checkEnqueuerConsistency: false}) {
     if (!member.isInstanceMember) return;
-    _getMemberUsage(member, memberUsed);
+    EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
+    MemberUsage usage = _getMemberUsage(member, useSet);
+    if (useSet.isNotEmpty) {
+      if (checkEnqueuerConsistency) {
+        throw new SpannableAssertionFailure(member,
+            'Unenqueued usage of $member: \nbefore: <none>\nafter : $usage');
+      } else {
+        memberUsed(member, useSet);
+      }
+    }
   }
 
-  MemberUsage _getMemberUsage(
-      covariant MemberEntity member, MemberUsedCallback memberUsed,
-      {bool dryRun: false}) {
+  MemberUsage _getMemberUsage(MemberEntity member, EnumSet<MemberUse> useSet,
+      {bool checkEnqueuerConsistency: false}) {
     // TODO(johnniwinther): Change [TypeMask] to not apply to a superclass
     // member unless the class has been instantiated. Similar to
     // [StrongModeConstraint].
-    MemberUsage usage = _instanceMemberUsage[member];
+    MemberUsage usage = _memberUsage[member];
     if (usage == null) {
-      String memberName = member.name;
-      ClassEntity cls = member.enclosingClass;
-      bool isNative = _nativeBasicData.isNativeClass(cls);
-      usage = new MemberUsage(member, isNative: isNative);
-      EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
-      useSet.addAll(usage.appliedUse);
-      if (!usage.hasRead && hasInvokedGetter(member)) {
-        useSet.addAll(usage.read());
-      }
-      if (!usage.hasWrite && hasInvokedSetter(member)) {
-        useSet.addAll(usage.write());
-      }
-      if (!usage.hasInvoke && hasInvocation(member)) {
-        // We don't track parameters in the codegen world builder, so we
-        // pass `null` instead of the concrete call structures.
-        useSet.addAll(usage.invoke(null));
-      }
+      MemberAccess potentialAccess = _closedWorld.getMemberAccess(member);
+      if (member.isInstanceMember) {
+        String memberName = member.name;
+        ClassEntity cls = member.enclosingClass;
+        bool isNative = _nativeBasicData.isNativeClass(cls);
+        usage = new MemberUsage(member, potentialAccess: potentialAccess);
+        if (member.isField && !isNative) {
+          useSet.addAll(usage.init());
+        }
+        if (member is JSignatureMethod) {
+          // We mark signature methods as "always used" to prevent them from
+          // being optimized away.
+          // TODO(johnniwinther): Make this a part of the regular enqueueing.
+          useSet.addAll(
+              usage.invoke(Accesses.dynamicAccess, CallStructure.NO_ARGS));
+        }
 
-      if (!dryRun) {
-        if (usage.hasPendingClosurizationUse) {
-          // Store the member in [instanceFunctionsByName] to catch
-          // getters on the function.
-          _instanceFunctionsByName
-              .putIfAbsent(usage.entity.name, () => new Set<MemberUsage>())
-              .add(usage);
+        if (usage.hasPendingDynamicRead && _hasInvokedGetter(member)) {
+          useSet.addAll(usage.read(Accesses.dynamicAccess));
         }
-        if (usage.hasPendingNormalUse) {
-          // The element is not yet used. Add it to the list of instance
-          // members to still be processed.
-          _instanceMembersByName
-              .putIfAbsent(memberName, () => new Set<MemberUsage>())
-              .add(usage);
+        if (usage.hasPendingDynamicWrite && _hasInvokedSetter(member)) {
+          useSet.addAll(usage.write(Accesses.dynamicAccess));
         }
-        _instanceMemberUsage[member] = usage;
+        if (usage.hasPendingDynamicInvoke) {
+          Iterable<CallStructure> callStructures =
+              _getInvocationCallStructures(member);
+          for (CallStructure callStructure in callStructures) {
+            useSet.addAll(usage.invoke(Accesses.dynamicAccess, callStructure));
+            if (!usage.hasPendingDynamicInvoke) {
+              break;
+            }
+          }
+        }
+
+        if (!checkEnqueuerConsistency) {
+          if (usage.hasPendingDynamicInvoke) {
+            _invokableInstanceMembersByName
+                .putIfAbsent(memberName, () => {})
+                .add(usage);
+          }
+          if (usage.hasPendingDynamicRead) {
+            _readableInstanceMembersByName
+                .putIfAbsent(memberName, () => {})
+                .add(usage);
+          }
+          if (usage.hasPendingDynamicWrite) {
+            _writableInstanceMembersByName
+                .putIfAbsent(memberName, () => {})
+                .add(usage);
+          }
+        }
+      } else {
+        usage = new MemberUsage(member, potentialAccess: potentialAccess);
+        if (member.isField) {
+          useSet.addAll(usage.init());
+        }
       }
-      memberUsed(member, useSet);
+      if (!checkEnqueuerConsistency) {
+        _memberUsage[member] = usage;
+      }
     } else {
-      if (dryRun) {
+      if (checkEnqueuerConsistency) {
         usage = usage.clone();
       }
     }
@@ -586,15 +545,317 @@
   }
 
   /// Set of all registered compiled constants.
-  final Set<ConstantValue> compiledConstants = new Set<ConstantValue>();
+  final Set<ConstantValue> _compiledConstants = new Set<ConstantValue>();
+
+  Iterable<ConstantValue> get compiledConstantsForTesting => _compiledConstants;
 
   @override
   void addCompileTimeConstantForEmission(ConstantValue constant) {
-    compiledConstants.add(constant);
+    _compiledConstants.add(constant);
+  }
+
+  /// Register the constant [use] with this world builder. Returns `true` if
+  /// the constant use was new to the world.
+  bool registerConstantUse(ConstantUse use) {
+    addCompileTimeConstantForEmission(use.value);
+    return _constantValues.add(use.value);
+  }
+
+  void registerConstTypeLiteral(DartType type) {
+    _constTypeLiterals.add(type);
+  }
+
+  void registerTypeArgument(DartType type) {
+    _liveTypeArguments.add(type);
   }
 
   @override
-  List<ConstantValue> getConstantsForEmission(
+  CodegenWorld close() {
+    Map<MemberEntity, MemberUsage> liveMemberUsage = {};
+    _memberUsage.forEach((MemberEntity member, MemberUsage usage) {
+      if (usage.hasUse) {
+        liveMemberUsage[member] = usage;
+      }
+    });
+    return new CodegenWorldImpl(_closedWorld, liveMemberUsage,
+        constTypeLiterals: _constTypeLiterals,
+        directlyInstantiatedClasses: directlyInstantiatedClasses,
+        typeVariableTypeLiterals: typeVariableTypeLiterals,
+        instantiatedClasses: instantiatedClasses,
+        isChecks: _isChecks,
+        instantiatedTypes: _instantiatedTypes,
+        liveTypeArguments: _liveTypeArguments,
+        compiledConstants: _compiledConstants,
+        invokedNames: _invokedNames,
+        invokedGetters: _invokedGetters,
+        invokedSetters: _invokedSetters,
+        staticTypeArgumentDependencies: staticTypeArgumentDependencies,
+        dynamicTypeArgumentDependencies: dynamicTypeArgumentDependencies,
+        oneShotInterceptorData: _oneShotInterceptorData);
+  }
+}
+
+class CodegenWorldImpl implements CodegenWorld {
+  JClosedWorld _closedWorld;
+
+  final Map<MemberEntity, MemberUsage> _liveMemberUsage;
+
+  @override
+  final Iterable<DartType> constTypeLiterals;
+
+  @override
+  final Iterable<ClassEntity> directlyInstantiatedClasses;
+
+  @override
+  final Iterable<TypeVariableType> typeVariableTypeLiterals;
+
+  @override
+  final Iterable<ClassEntity> instantiatedClasses;
+
+  @override
+  final Iterable<DartType> isChecks;
+
+  @override
+  final Iterable<InterfaceType> instantiatedTypes;
+
+  @override
+  final Iterable<DartType> liveTypeArguments;
+
+  final Iterable<ConstantValue> _compiledConstants;
+
+  final Map<String, Map<Selector, SelectorConstraints>> _invokedNames;
+
+  final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters;
+
+  final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters;
+
+  final Map<Entity, Set<DartType>> _staticTypeArgumentDependencies;
+
+  final Map<Selector, Set<DartType>> _dynamicTypeArgumentDependencies;
+
+  @override
+  final OneShotInterceptorData oneShotInterceptorData;
+
+  CodegenWorldImpl(this._closedWorld, this._liveMemberUsage,
+      {this.constTypeLiterals,
+      this.directlyInstantiatedClasses,
+      this.typeVariableTypeLiterals,
+      this.instantiatedClasses,
+      this.isChecks,
+      this.instantiatedTypes,
+      this.liveTypeArguments,
+      Iterable<ConstantValue> compiledConstants,
+      Map<String, Map<Selector, SelectorConstraints>> invokedNames,
+      Map<String, Map<Selector, SelectorConstraints>> invokedGetters,
+      Map<String, Map<Selector, SelectorConstraints>> invokedSetters,
+      Map<Entity, Set<DartType>> staticTypeArgumentDependencies,
+      Map<Selector, Set<DartType>> dynamicTypeArgumentDependencies,
+      this.oneShotInterceptorData})
+      : _compiledConstants = compiledConstants,
+        _invokedNames = invokedNames,
+        _invokedGetters = invokedGetters,
+        _invokedSetters = invokedSetters,
+        _staticTypeArgumentDependencies = staticTypeArgumentDependencies,
+        _dynamicTypeArgumentDependencies = dynamicTypeArgumentDependencies;
+
+  @override
+  void forEachStaticField(void Function(FieldEntity) f) {
+    bool failure = false;
+    _liveMemberUsage.forEach((MemberEntity member, MemberUsage usage) {
+      if (member is FieldEntity && (member.isStatic || member.isTopLevel)) {
+        f(member);
+      }
+    });
+    if (failure) throw 'failure';
+  }
+
+  @override
+  void forEachGenericMethod(Function f) {
+    _liveMemberUsage.forEach((MemberEntity member, MemberUsage usage) {
+      if (member is FunctionEntity &&
+          _closedWorld.elementEnvironment
+              .getFunctionTypeVariables(member)
+              .isNotEmpty) {
+        f(member);
+      }
+    });
+  }
+
+  @override
+  void forEachGenericInstanceMethod(Function f) {
+    _liveMemberUsage.forEach((MemberEntity member, MemberUsage usage) {
+      if (member is FunctionEntity &&
+          member.isInstanceMember &&
+          _closedWorld.elementEnvironment
+              .getFunctionTypeVariables(member)
+              .isNotEmpty) {
+        f(member);
+      }
+    });
+  }
+
+  @override
+  void forEachGenericClosureCallMethod(Function f) {
+    _liveMemberUsage.forEach((MemberEntity member, MemberUsage usage) {
+      if (member.name == Identifiers.call &&
+          member.isInstanceMember &&
+          member.enclosingClass.isClosure &&
+          member is FunctionEntity &&
+          _closedWorld.elementEnvironment
+              .getFunctionTypeVariables(member)
+              .isNotEmpty) {
+        f(member);
+      }
+    });
+  }
+
+  List<FunctionEntity> _userNoSuchMethodsCache;
+
+  @override
+  Iterable<FunctionEntity> get userNoSuchMethods {
+    if (_userNoSuchMethodsCache == null) {
+      _userNoSuchMethodsCache = <FunctionEntity>[];
+
+      _liveMemberUsage.forEach((MemberEntity member, MemberUsage memberUsage) {
+        if (member is FunctionEntity) {
+          if (member.isInstanceMember &&
+              member.name == Identifiers.noSuchMethod_ &&
+              !_closedWorld.commonElements
+                  .isDefaultNoSuchMethodImplementation(member)) {
+            _userNoSuchMethodsCache.add(member);
+          }
+        }
+      });
+    }
+
+    return _userNoSuchMethodsCache;
+  }
+
+  @override
+  Iterable<Local> get genericLocalFunctions => const [];
+
+  Set<FunctionEntity> _closurizedMembersCache;
+
+  @override
+  Iterable<FunctionEntity> get closurizedMembers {
+    if (_closurizedMembersCache == null) {
+      _closurizedMembersCache = {};
+      _liveMemberUsage.forEach((MemberEntity member, MemberUsage usage) {
+        if ((member.isFunction || member is JGeneratorBody) &&
+            member.isInstanceMember &&
+            usage.hasRead) {
+          _closurizedMembersCache.add(member);
+        }
+      });
+    }
+    return _closurizedMembersCache;
+  }
+
+  Set<FunctionEntity> _closurizedStaticsCache;
+
+  @override
+  Iterable<FunctionEntity> get closurizedStatics {
+    if (_closurizedStaticsCache == null) {
+      _closurizedStaticsCache = {};
+      _liveMemberUsage.forEach((MemberEntity member, MemberUsage usage) {
+        if (member.isFunction &&
+            (member.isStatic || member.isTopLevel) &&
+            usage.hasRead) {
+          _closurizedStaticsCache.add(member);
+        }
+      });
+    }
+    return _closurizedStaticsCache;
+  }
+
+  @override
+  void forEachStaticTypeArgument(
+      void f(Entity function, Set<DartType> typeArguments)) {
+    _staticTypeArgumentDependencies.forEach(f);
+  }
+
+  @override
+  void forEachDynamicTypeArgument(
+      void f(Selector selector, Set<DartType> typeArguments)) {
+    _dynamicTypeArgumentDependencies.forEach(f);
+  }
+
+  @override
+  void forEachInvokedName(
+      f(String name, Map<Selector, SelectorConstraints> selectors)) {
+    _invokedNames.forEach(f);
+  }
+
+  @override
+  void forEachInvokedGetter(
+      f(String name, Map<Selector, SelectorConstraints> selectors)) {
+    _invokedGetters.forEach(f);
+  }
+
+  @override
+  void forEachInvokedSetter(
+      f(String name, Map<Selector, SelectorConstraints> selectors)) {
+    _invokedSetters.forEach(f);
+  }
+
+  bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors,
+      MemberEntity member, JClosedWorld world) {
+    if (selectors == null) return false;
+    for (Selector selector in selectors.keys) {
+      if (selector.appliesUnnamed(member)) {
+        SelectorConstraints masks = selectors[selector];
+        if (masks.canHit(member, selector.memberName, world)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  @override
+  bool hasInvokedGetter(MemberEntity member) {
+    MemberUsage memberUsage = _liveMemberUsage[member];
+    if (memberUsage == null) return false;
+    return memberUsage.reads.contains(Access.dynamicAccess);
+  }
+
+  @override
+  bool methodsNeedsSuperGetter(FunctionEntity function) {
+    MemberUsage memberUsage = _liveMemberUsage[function];
+    if (memberUsage == null) return false;
+    return memberUsage.reads.contains(Access.superAccess);
+  }
+
+  @override
+  bool hasInvokedSetter(MemberEntity member) {
+    MemberUsage memberUsage = _liveMemberUsage[member];
+    if (memberUsage == null) return false;
+    return memberUsage.writes.contains(Access.dynamicAccess);
+  }
+
+  Map<Selector, SelectorConstraints> _asUnmodifiable(
+      Map<Selector, SelectorConstraints> map) {
+    if (map == null) return null;
+    return new UnmodifiableMapView(map);
+  }
+
+  @override
+  Map<Selector, SelectorConstraints> invocationsByName(String name) {
+    return _asUnmodifiable(_invokedNames[name]);
+  }
+
+  @override
+  Iterable<Selector> getterInvocationsByName(String name) {
+    return _invokedGetters[name]?.keys;
+  }
+
+  @override
+  Iterable<Selector> setterInvocationsByName(String name) {
+    return _invokedSetters[name]?.keys;
+  }
+
+  @override
+  Iterable<ConstantValue> getConstantsForEmission(
       [Comparator<ConstantValue> preSortCompare]) {
     // We must emit dependencies before their uses.
     Set<ConstantValue> seenConstants = new Set<ConstantValue>();
@@ -609,132 +870,21 @@
       }
     }
 
-    List<ConstantValue> sorted = compiledConstants.toList();
     if (preSortCompare != null) {
+      List<ConstantValue> sorted = _compiledConstants.toList();
       sorted.sort(preSortCompare);
+      sorted.forEach(addConstant);
+    } else {
+      _compiledConstants.forEach(addConstant);
     }
-    sorted.forEach(addConstant);
     return result;
   }
 
-  /// Register the constant [use] with this world builder. Returns `true` if
-  /// the constant use was new to the world.
-  bool registerConstantUse(ConstantUse use) {
-    addCompileTimeConstantForEmission(use.value);
-    return _constantValues.add(use.value);
-  }
-
   @override
-  Iterable<Local> get genericLocalFunctions => const <Local>[];
-
-  @override
-  Iterable<FunctionEntity> get genericInstanceMethods {
-    List<FunctionEntity> functions = <FunctionEntity>[];
-
-    void processMemberUse(MemberEntity member, MemberUsage memberUsage) {
-      if (member.isInstanceMember &&
-          member is FunctionEntity &&
-          memberUsage.hasUse &&
-          _elementEnvironment.getFunctionTypeVariables(member).isNotEmpty) {
-        functions.add(member);
-      }
-    }
-
-    _instanceMemberUsage.forEach(processMemberUse);
-    return functions;
+  bool isAliasedSuperMember(MemberEntity member) {
+    MemberUsage usage = _liveMemberUsage[member];
+    if (usage == null) return false;
+    return usage.invokes.contains(Access.superAccess) ||
+        usage.writes.contains(Access.superAccess);
   }
-
-  @override
-  Iterable<FunctionEntity> get userNoSuchMethods {
-    List<FunctionEntity> functions = <FunctionEntity>[];
-
-    void processMemberUse(MemberEntity member, MemberUsage memberUsage) {
-      if (member.isInstanceMember &&
-          member is FunctionEntity &&
-          memberUsage.hasUse &&
-          member.name == Identifiers.noSuchMethod_ &&
-          !_world.commonElements.isDefaultNoSuchMethodImplementation(member)) {
-        functions.add(member);
-      }
-    }
-
-    _instanceMemberUsage.forEach(processMemberUse);
-    return functions;
-  }
-
-  @override
-  Iterable<FunctionEntity> get genericMethods {
-    List<FunctionEntity> functions = <FunctionEntity>[];
-
-    void processMemberUse(Entity member, AbstractUsage memberUsage) {
-      if (member is FunctionEntity &&
-          memberUsage.hasUse &&
-          _elementEnvironment.getFunctionTypeVariables(member).isNotEmpty) {
-        functions.add(member);
-      }
-    }
-
-    _instanceMemberUsage.forEach(processMemberUse);
-    _staticMemberUsage.forEach(processMemberUse);
-    return functions;
-  }
-
-  @override
-  void forEachParameter(FunctionEntity function,
-      void f(DartType type, String name, ConstantValue defaultValue)) {
-    _elementMap.forEachParameter(function, f,
-        isNative: _world.nativeData.isNativeMember(function));
-  }
-
-  @override
-  void forEachParameterAsLocal(
-      FunctionEntity function, void f(Local parameter)) {
-    forEachOrderedParameterAsLocal(_globalLocalsMap, _elementMap, function,
-        (Local parameter, {bool isElided}) {
-      if (!isElided) {
-        f(parameter);
-      }
-    });
-  }
-
-  @override
-  void forEachInstanceField(ClassEntity cls,
-      void f(ClassEntity declarer, FieldEntity field, {bool isElided})) {
-    _elementEnvironment.forEachClassMember(cls,
-        (ClassEntity declarer, MemberEntity member) {
-      if (member.isField && member.isInstanceMember) {
-        f(declarer, member,
-            isElided: _world.fieldAnalysis.getFieldData(member).isElided);
-      }
-    });
-  }
-
-  @override
-  void forEachDirectInstanceField(
-      ClassEntity cls, void f(FieldEntity field, {bool isElided})) {
-    // TODO(sra): Add ElementEnvironment.forEachDirectInstanceField or
-    // parameterize [forEachInstanceField] to filter members to avoid a
-    // potentially O(n^2) scan of the superclasses.
-    _elementEnvironment.forEachClassMember(cls,
-        (ClassEntity declarer, MemberEntity member) {
-      if (declarer != cls) return;
-      if (!member.isField) return;
-      if (!member.isInstanceMember) return;
-      f(member, isElided: _world.fieldAnalysis.getFieldData(member).isElided);
-    });
-  }
-
-  void registerConstTypeLiteral(DartType type) {
-    _constTypeLiterals.add(type);
-  }
-
-  @override
-  Iterable<DartType> get constTypeLiterals => _constTypeLiterals;
-
-  void registerTypeArgument(DartType type) {
-    _liveTypeArguments.add(type);
-  }
-
-  @override
-  Iterable<DartType> get liveTypeArguments => _liveTypeArguments;
 }
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index 484ce10..92ded95 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -10,6 +10,7 @@
 
 import '../elements/types.dart';
 import '../ir/runtime_type_analysis.dart';
+import '../serialization/serialization.dart';
 import '../util/util.dart';
 
 /// A language feature that may be seen in the program.
@@ -36,9 +37,6 @@
   /// A catch statement.
   CATCH_STATEMENT,
 
-  /// A compile time error.
-  COMPILE_TIME_ERROR,
-
   /// A fall through in a switch case.
   FALL_THROUGH_ERROR,
 
@@ -239,6 +237,8 @@
 /// A generic instantiation of an expression of type [functionType] with the
 /// given [typeArguments].
 class GenericInstantiation {
+  static const String tag = 'generic-instantiation';
+
   /// The static type of the instantiated expression.
   final DartType functionType;
 
@@ -247,6 +247,21 @@
 
   GenericInstantiation(this.functionType, this.typeArguments);
 
+  factory GenericInstantiation.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    DartType functionType = source.readDartType();
+    List<DartType> typeArguments = source.readDartTypes();
+    source.end(tag);
+    return new GenericInstantiation(functionType, typeArguments);
+  }
+
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartType(functionType);
+    sink.writeDartTypes(typeArguments);
+    sink.end(tag);
+  }
+
   /// Short textual representation use for testing.
   String get shortText => '<${typeArguments.join(',')}>';
 
diff --git a/pkg/compiler/lib/src/universe/member_usage.dart b/pkg/compiler/lib/src/universe/member_usage.dart
index e368cbb..a322bc3 100644
--- a/pkg/compiler/lib/src/universe/member_usage.dart
+++ b/pkg/compiler/lib/src/universe/member_usage.dart
@@ -7,7 +7,8 @@
 import '../common.dart';
 import '../constants/values.dart';
 import '../elements/entities.dart';
-import '../js_model/elements.dart' show JSignatureMethod;
+import '../js_model/closure.dart';
+import '../serialization/serialization.dart';
 import '../util/enumset.dart';
 import 'call_structure.dart';
 
@@ -21,12 +22,12 @@
   }
 
   /// Returns the uses of [entity] that have been registered.
-  EnumSet<T> get appliedUse => _originalUse.minus(_pendingUse);
+  EnumSet<T> get _appliedUse => _originalUse.minus(_pendingUse);
 
   EnumSet<T> get _originalUse;
 
-  /// `true` if the [appliedUse] is non-empty.
-  bool get hasUse => appliedUse.isNotEmpty;
+  /// `true` if the [_appliedUse] is non-empty.
+  bool get hasUse => _appliedUse.isNotEmpty;
 
   /// Returns `true` if [other] has the same original and pending usage as this.
   bool hasSameUsage(AbstractUsage<T> other) {
@@ -38,6 +39,10 @@
 
 /// Registry for the observed use of a member [entity] in the open world.
 abstract class MemberUsage extends AbstractUsage<MemberUse> {
+  /// Constant empty access set used as the potential access set for impossible
+  /// accesses, for instance writing to a final field or invoking a setter.
+  static const EnumSet<Access> emptySet = const EnumSet.fixed(0);
+
   final MemberEntity entity;
 
   MemberUsage.internal(this.entity) : super();
@@ -45,76 +50,140 @@
   MemberUsage.cloned(this.entity, EnumSet<MemberUse> pendingUse)
       : super.cloned(pendingUse);
 
-  factory MemberUsage(MemberEntity member,
-      {bool isNative: false, bool trackParameters: false}) {
+  factory MemberUsage(MemberEntity member, {MemberAccess potentialAccess}) {
+    /// Create the set of potential accesses to [member], limited to [original]
+    /// if provided.
+    EnumSet<Access> createPotentialAccessSet(EnumSet<Access> original) {
+      if (original != null) {
+        if (original.isEmpty) return emptySet;
+        return original.clone();
+      }
+      if (member.isTopLevel || member.isStatic || member.isConstructor) {
+        // TODO(johnniwinther): Track super constructor invocations?
+        return new EnumSet.fromValues([Access.staticAccess]);
+      } else if (member.isInstanceMember) {
+        return new EnumSet.fromValues(Access.values);
+      } else {
+        assert(member is JRecordField, "Unexpected member: $member");
+        return new EnumSet();
+      }
+    }
+
+    /// Create the set of potential read accesses to [member], limited to reads
+    /// in [potentialAccess] if provided.
+    EnumSet<Access> createPotentialReads() {
+      return createPotentialAccessSet(potentialAccess?.reads);
+    }
+
+    /// Create the set of potential write accesses to [member], limited to
+    /// writes in [potentialAccess] if provided.
+    EnumSet<Access> createPotentialWrites() {
+      return createPotentialAccessSet(potentialAccess?.writes);
+    }
+
+    /// Create the set of potential invocation accesses to [member], limited to
+    /// invocations in [potentialAccess] if provided.
+    EnumSet<Access> createPotentialInvokes() {
+      return createPotentialAccessSet(potentialAccess?.invokes);
+    }
+
     if (member.isField) {
       if (member.isAssignable) {
-        return new FieldUsage(member, isNative: isNative);
+        return new FieldUsage(member,
+            potentialReads: createPotentialReads(),
+            potentialWrites: createPotentialWrites(),
+            potentialInvokes: createPotentialInvokes());
       } else {
-        return new FinalFieldUsage(member, isNative: isNative);
+        return new FieldUsage(member,
+            potentialReads: createPotentialReads(),
+            potentialWrites: emptySet,
+            potentialInvokes: createPotentialInvokes());
       }
     } else if (member.isGetter) {
-      return new GetterUsage(member);
+      return new PropertyUsage(member,
+          potentialReads: createPotentialReads(),
+          potentialWrites: emptySet,
+          potentialInvokes: createPotentialInvokes());
     } else if (member.isSetter) {
-      return new SetterUsage(member);
+      return new PropertyUsage(member,
+          potentialReads: emptySet,
+          potentialWrites: createPotentialWrites(),
+          potentialInvokes: emptySet);
     } else if (member.isConstructor) {
-      if (trackParameters) {
-        return new ParameterTrackingConstructorUsage(member);
-      } else {
-        return new ConstructorUsage(member);
-      }
+      return new MethodUsage(member,
+          potentialReads: emptySet, potentialInvokes: createPotentialInvokes());
     } else {
-      assert(member.isFunction, failedAt(member, "Unexpected member: $member"));
-      if (trackParameters) {
-        return new ParameterTrackingFunctionUsage(member);
-      } else {
-        return new FunctionUsage(member);
-      }
+      assert(member is FunctionEntity,
+          failedAt(member, "Unexpected member: $member"));
+      return new MethodUsage(member,
+          potentialReads: createPotentialReads(),
+          potentialInvokes: createPotentialInvokes());
     }
   }
 
   /// `true` if [entity] has been initialized.
   bool get hasInit => true;
 
+  /// The set of constant initial values for a field.
   Iterable<ConstantValue> get initialConstants => null;
 
   /// `true` if [entity] has been read as a value. For a field this is a normal
   /// read access, for a function this is a closurization.
-  bool get hasRead => false;
+  bool get hasRead => reads.isNotEmpty;
+
+  /// The set of potential read accesses to this member that have not yet
+  /// been registered.
+  EnumSet<Access> get potentialReads => const EnumSet.fixed(0);
+
+  /// The set of registered read accesses to this member.
+  EnumSet<Access> get reads => const EnumSet.fixed(0);
 
   /// `true` if a value has been written to [entity].
-  bool get hasWrite => false;
+  bool get hasWrite => writes.isNotEmpty;
+
+  /// The set of potential write accesses to this member that have not yet
+  /// been registered.
+  EnumSet<Access> get potentialWrites => const EnumSet.fixed(0);
+
+  /// The set of registered write accesses to this member.
+  EnumSet<Access> get writes => const EnumSet.fixed(0);
 
   /// `true` if an invocation has been performed on the value [entity]. For a
   /// function this is a normal invocation, for a field this is a read access
   /// followed by an invocation of the function-like value.
-  bool get hasInvoke => false;
+  bool get hasInvoke => invokes.isNotEmpty;
 
-  /// `true` if all parameters are provided in invocations of [entity].
-  ///
-  /// For method or constructors with no optional arguments this is the same
-  /// as [hasInvoke] but for method or constructors with optional arguments some
-  /// parameters may have been provided in any invocation in which case
-  /// [isFullyInvoked] is `false`.
-  bool get isFullyInvoked => hasInvoke;
+  /// The set of potential invocation accesses to this member that have not yet
+  /// been registered.
+  EnumSet<Access> get potentialInvokes => const EnumSet.fixed(0);
+
+  /// The set of registered invocation accesses to this member.
+  EnumSet<Access> get invokes => const EnumSet.fixed(0);
 
   /// Returns the [ParameterStructure] corresponding to the parameters that are
   /// used in invocations of [entity]. For a field, getter or setter this is
   /// always `null`.
   ParameterStructure get invokedParameters => null;
 
-  /// `true` if [entity] has further normal use. For a field this means that
-  /// it hasn't been read from or written to. For a function this means that it
-  /// hasn't been invoked or, when parameter usage is tracked, that some
-  /// parameters haven't been provided in any invocation.
-  bool get hasPendingNormalUse => _pendingUse.contains(MemberUse.NORMAL);
+  /// Whether this member has any potential but unregistered dynamic reads,
+  /// writes or invocations.
+  bool get hasPendingDynamicUse =>
+      hasPendingDynamicInvoke ||
+      hasPendingDynamicRead ||
+      hasPendingDynamicWrite;
 
-  /// `true` if [entity] hasn't been closurized. This is only used for
-  /// functions.
-  bool get hasPendingClosurizationUse => false;
+  /// Whether this member has any potential but unregistered dynamic
+  /// invocations.
+  bool get hasPendingDynamicInvoke =>
+      potentialInvokes.contains(Access.dynamicAccess);
 
-  /// `true` if [entity] has been used in all the ways possible.
-  bool get fullyUsed;
+  /// Whether this member has any potential but unregistered dynamic reads.
+  bool get hasPendingDynamicRead =>
+      potentialReads.contains(Access.dynamicAccess);
+
+  /// Whether this member has any potential but unregistered dynamic writes.
+  bool get hasPendingDynamicWrite =>
+      potentialWrites.contains(Access.dynamicAccess);
 
   /// Registers the [entity] has been initialized and returns the new
   /// [MemberUse]s that it caused.
@@ -135,22 +204,20 @@
   ///
   /// For a field this is a normal read access, for a function this is a
   /// closurization.
-  EnumSet<MemberUse> read() => MemberUses.NONE;
+  EnumSet<MemberUse> read(EnumSet<Access> accesses) => MemberUses.NONE;
 
   /// Registers a write of a value to [entity] and returns the new [MemberUse]s
   /// that it caused.
-  EnumSet<MemberUse> write() => MemberUses.NONE;
+  EnumSet<MemberUse> write(EnumSet<Access> accesses) => MemberUses.NONE;
 
   /// Registers an invocation on the value of [entity] and returns the new
   /// [MemberUse]s that it caused.
   ///
   /// For a function this is a normal invocation, for a field this is a read
   /// access followed by an invocation of the function-like value.
-  EnumSet<MemberUse> invoke(CallStructure callStructure) => MemberUses.NONE;
-
-  /// Registers all possible uses of [entity] and returns the new [MemberUse]s
-  /// that it caused.
-  EnumSet<MemberUse> fullyUse() => MemberUses.NONE;
+  EnumSet<MemberUse> invoke(
+          EnumSet<Access> accesses, CallStructure callStructure) =>
+      MemberUses.NONE;
 
   @override
   EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
@@ -173,63 +240,187 @@
         hasRead == other.hasRead &&
         hasInvoke == other.hasInvoke &&
         hasWrite == other.hasWrite &&
-        hasPendingClosurizationUse == other.hasPendingClosurizationUse &&
-        hasPendingNormalUse == other.hasPendingNormalUse &&
-        fullyUsed == other.fullyUsed &&
-        isFullyInvoked == other.isFullyInvoked &&
+        hasPendingDynamicRead == other.hasPendingDynamicRead &&
+        hasPendingDynamicWrite == other.hasPendingDynamicWrite &&
+        hasPendingDynamicInvoke == other.hasPendingDynamicInvoke &&
+        hasPendingDynamicUse == other.hasPendingDynamicUse &&
         _pendingUse == other._pendingUse &&
-        appliedUse == other.appliedUse;
+        _appliedUse == other._appliedUse &&
+        reads == other.reads &&
+        writes == other.writes &&
+        invokes == other.invokes &&
+        potentialReads == other.potentialReads &&
+        potentialWrites == other.potentialWrites &&
+        potentialInvokes == other.potentialInvokes &&
+        invokedParameters == other.invokedParameters;
+  }
+}
+
+/// Member usage tracking for a getter or setter.
+class PropertyUsage extends MemberUsage {
+  @override
+  final EnumSet<Access> potentialReads;
+
+  @override
+  final EnumSet<Access> potentialWrites;
+
+  @override
+  final EnumSet<Access> potentialInvokes;
+
+  @override
+  final EnumSet<Access> reads;
+
+  @override
+  final EnumSet<Access> writes;
+
+  @override
+  final EnumSet<Access> invokes;
+
+  PropertyUsage.cloned(MemberEntity member, EnumSet<MemberUse> pendingUse,
+      {this.potentialReads,
+      this.potentialWrites,
+      this.potentialInvokes,
+      this.reads,
+      this.writes,
+      this.invokes})
+      : assert(potentialReads != null),
+        assert(potentialWrites != null),
+        assert(potentialInvokes != null),
+        assert(reads != null),
+        assert(writes != null),
+        assert(invokes != null),
+        super.cloned(member, pendingUse);
+
+  PropertyUsage(MemberEntity member,
+      {this.potentialReads, this.potentialWrites, this.potentialInvokes})
+      : reads = new EnumSet(),
+        writes = new EnumSet(),
+        invokes = new EnumSet(),
+        assert(potentialReads != null),
+        assert(potentialWrites != null),
+        assert(potentialInvokes != null),
+        super.internal(member);
+
+  @override
+  EnumSet<MemberUse> read(EnumSet<Access> accesses) {
+    bool alreadyHasRead = hasRead;
+    reads.addAll(potentialReads.removeAll(accesses));
+    if (alreadyHasRead) {
+      return MemberUses.NONE;
+    }
+    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
   }
 
   @override
-  String toString() => '$entity:${appliedUse.iterable(MemberUse.values)}';
+  EnumSet<MemberUse> write(EnumSet<Access> accesses) {
+    bool alreadyHasWrite = hasWrite;
+    writes.addAll(potentialWrites.removeAll(accesses));
+    if (alreadyHasWrite) {
+      return MemberUses.NONE;
+    }
+    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
+  }
+
+  @override
+  EnumSet<MemberUse> invoke(
+      EnumSet<Access> accesses, CallStructure callStructure) {
+    // We use `hasRead` here instead of `hasInvoke` because getters only have
+    // 'normal use' (they cannot be closurized). This means that invoking an
+    // already read getter does not result a new member use.
+    bool alreadyHasRead = hasRead;
+    reads.addAll(potentialReads.removeAll(Accesses.staticAccess));
+    invokes.addAll(potentialInvokes.removeAll(accesses));
+    if (alreadyHasRead) {
+      return MemberUses.NONE;
+    }
+    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
+  }
+
+  @override
+  MemberUsage clone() {
+    return new PropertyUsage.cloned(entity, _pendingUse.clone(),
+        potentialReads: potentialReads.clone(),
+        potentialWrites: potentialWrites.clone(),
+        potentialInvokes: potentialInvokes.clone(),
+        reads: reads.clone(),
+        writes: writes.clone(),
+        invokes: invokes.clone());
+  }
+
+  @override
+  String toString() => 'PropertyUsage($entity,'
+      'reads=${reads.iterable(Access.values)},'
+      'writes=${writes.iterable(Access.values)},'
+      'invokes=${invokes.iterable(Access.values)},'
+      'potentialReads=${potentialReads.iterable(Access.values)},'
+      'potentialWrites=${potentialWrites.iterable(Access.values)},'
+      'potentialInvokes=${potentialInvokes.iterable(Access.values)},'
+      'pendingUse=${_pendingUse.iterable(MemberUse.values)},'
+      'initialConstants=${initialConstants?.map((c) => c.toStructuredText())})';
 }
 
+/// Member usage tracking for a field.
 class FieldUsage extends MemberUsage {
   @override
   bool hasInit;
+
   @override
-  bool hasRead;
+  final EnumSet<Access> potentialReads;
+
   @override
-  bool hasWrite;
+  final EnumSet<Access> potentialWrites;
+
+  @override
+  final EnumSet<Access> potentialInvokes;
+
+  @override
+  final EnumSet<Access> reads;
+
+  @override
+  final EnumSet<Access> invokes;
+
+  @override
+  final EnumSet<Access> writes;
 
   List<ConstantValue> _initialConstants;
 
   FieldUsage.cloned(FieldEntity field, EnumSet<MemberUse> pendingUse,
-      {this.hasInit, this.hasRead, this.hasWrite})
-      : super.cloned(field, pendingUse);
+      {this.potentialReads,
+      this.potentialWrites,
+      this.potentialInvokes,
+      this.hasInit,
+      this.reads,
+      this.writes,
+      this.invokes})
+      : assert(potentialReads != null),
+        assert(potentialWrites != null),
+        assert(potentialInvokes != null),
+        assert(reads != null),
+        assert(writes != null),
+        assert(invokes != null),
+        super.cloned(field, pendingUse);
 
-  FieldUsage(FieldEntity field, {bool isNative: false})
+  FieldUsage(FieldEntity field,
+      {this.potentialReads, this.potentialWrites, this.potentialInvokes})
       : hasInit = false,
-        hasRead = false,
-        hasWrite = false,
-        super.internal(field) {
-    // TODO(johnniwinther): Track native fields through member usage.
-    if (!isNative) {
-      init();
-    }
-  }
+        reads = new EnumSet(),
+        writes = new EnumSet(),
+        invokes = new EnumSet(),
+        assert(potentialReads != null),
+        assert(potentialWrites != null),
+        assert(potentialInvokes != null),
+        super.internal(field);
 
   @override
   Iterable<ConstantValue> get initialConstants => _initialConstants ?? const [];
 
   @override
-  bool get hasPendingNormalUse => !fullyUsed;
-
-  @override
-  bool get fullyUsed => hasInit && hasRead && hasWrite;
-
-  @override
   EnumSet<MemberUse> init() {
     if (hasInit) {
       return MemberUses.NONE;
     }
     hasInit = true;
-    EnumSet<MemberUse> result = _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
-    if (!fullyUsed) {
-      result = result.union(MemberUses.PARTIAL_USE_ONLY);
-    }
-    return result;
+    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
   }
 
   @override
@@ -240,204 +431,128 @@
   }
 
   @override
-  EnumSet<MemberUse> read() {
-    if (hasRead) {
+  bool get hasRead => reads.isNotEmpty;
+
+  @override
+  EnumSet<MemberUse> read(EnumSet<Access> accesses) {
+    bool alreadyHasRead = hasRead;
+    reads.addAll(potentialReads.removeAll(accesses));
+    if (alreadyHasRead) {
       return MemberUses.NONE;
     }
-    hasRead = true;
-    EnumSet<MemberUse> result = _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
-    if (!fullyUsed) {
-      result = result.union(MemberUses.PARTIAL_USE_ONLY);
-    }
-    return result;
+    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
   }
 
   @override
-  EnumSet<MemberUse> write() {
-    if (hasWrite) {
+  bool get hasWrite => writes.isNotEmpty;
+
+  @override
+  EnumSet<MemberUse> write(EnumSet<Access> accesses) {
+    bool alreadyHasWrite = hasWrite;
+    writes.addAll(potentialWrites.removeAll(accesses));
+    if (alreadyHasWrite) {
       return MemberUses.NONE;
     }
-    hasWrite = true;
-    EnumSet<MemberUse> result = _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
-    if (!fullyUsed) {
-      result = result.union(MemberUses.PARTIAL_USE_ONLY);
-    }
-    return result;
+    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
   }
 
   @override
-  EnumSet<MemberUse> invoke(CallStructure callStructure) => read();
-
-  @override
-  EnumSet<MemberUse> fullyUse() {
-    if (fullyUsed) {
+  EnumSet<MemberUse> invoke(
+      EnumSet<Access> accesses, CallStructure callStructure) {
+    // We use `hasRead` here instead of `hasInvoke` because fields only have
+    // 'normal use' (they cannot be closurized). This means that invoking an
+    // already read field does not result a new member use.
+    bool alreadyHasRead = hasRead;
+    reads.addAll(potentialReads.removeAll(Accesses.staticAccess));
+    invokes.addAll(potentialInvokes.removeAll(accesses));
+    if (alreadyHasRead) {
       return MemberUses.NONE;
     }
-    hasInit = hasRead = hasWrite = true;
     return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
   }
 
   @override
   MemberUsage clone() {
     return new FieldUsage.cloned(entity, _pendingUse.clone(),
-        hasInit: hasInit, hasRead: hasRead, hasWrite: hasWrite);
+        potentialReads: potentialReads.clone(),
+        potentialWrites: potentialWrites.clone(),
+        potentialInvokes: potentialInvokes.clone(),
+        hasInit: hasInit,
+        reads: reads.clone(),
+        writes: writes.clone(),
+        invokes: invokes.clone());
   }
 
   @override
-  String toString() => 'FieldUsage($entity,hasInit=$hasInit,hasRead=$hasRead,'
-      'hasWrite=$hasWrite,pendingUse=${_pendingUse.iterable(MemberUse.values)},'
+  String toString() => 'FieldUsage($entity,hasInit=$hasInit,'
+      'reads=${reads.iterable(Access.values)},'
+      'writes=${writes.iterable(Access.values)},'
+      'invokes=${invokes.iterable(Access.values)},'
+      'potentialReads=${potentialReads.iterable(Access.values)},'
+      'potentialWrites=${potentialWrites.iterable(Access.values)},'
+      'potentialInvokes=${potentialInvokes.iterable(Access.values)},'
+      'pendingUse=${_pendingUse.iterable(MemberUse.values)},'
       'initialConstants=${initialConstants.map((c) => c.toStructuredText())})';
 }
 
-class FinalFieldUsage extends MemberUsage {
+/// Member usage tracking for a constructor or method.
+class MethodUsage extends MemberUsage {
   @override
-  bool hasInit;
-  @override
-  bool hasRead;
-
-  List<ConstantValue> _initialConstants;
-
-  FinalFieldUsage.cloned(FieldEntity field, EnumSet<MemberUse> pendingUse,
-      {this.hasInit, this.hasRead})
-      : super.cloned(field, pendingUse);
-
-  FinalFieldUsage(FieldEntity field, {bool isNative: false})
-      : this.hasInit = false,
-        this.hasRead = false,
-        super.internal(field) {
-    if (!isNative) {
-      init();
-    }
-  }
+  final EnumSet<Access> potentialReads;
 
   @override
-  Iterable<ConstantValue> get initialConstants => _initialConstants ?? const [];
+  final EnumSet<Access> potentialInvokes;
 
   @override
-  bool get hasPendingNormalUse => !fullyUsed;
+  final EnumSet<Access> reads;
 
   @override
-  bool get fullyUsed => hasInit && hasRead;
+  final EnumSet<Access> invokes;
+
+  final ParameterUsage parameterUsage;
+
+  MethodUsage.cloned(FunctionEntity function, this.parameterUsage,
+      EnumSet<MemberUse> pendingUse,
+      {this.potentialReads, this.reads, this.potentialInvokes, this.invokes})
+      : assert(potentialReads != null),
+        assert(potentialInvokes != null),
+        assert(reads != null),
+        assert(invokes != null),
+        super.cloned(function, pendingUse);
+
+  MethodUsage(FunctionEntity function,
+      {this.potentialReads, this.potentialInvokes})
+      : reads = new EnumSet(),
+        invokes = new EnumSet(),
+        parameterUsage = new ParameterUsage(function.parameterStructure),
+        assert(potentialReads != null),
+        assert(potentialInvokes != null),
+        super.internal(function);
 
   @override
-  EnumSet<MemberUse> init() {
-    if (hasInit) {
-      return MemberUses.NONE;
-    }
-    hasInit = true;
-    EnumSet<MemberUse> result = _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
-    if (!fullyUsed) {
-      result = result.union(MemberUses.PARTIAL_USE_ONLY);
-    }
-    return result;
-  }
-
-  @override
-  EnumSet<MemberUse> constantInit(ConstantValue constant) {
-    _initialConstants ??= [];
-    _initialConstants.add(constant);
-    return init();
-  }
-
-  @override
-  EnumSet<MemberUse> read() {
-    if (hasRead) {
-      return MemberUses.NONE;
-    }
-    hasRead = true;
-    EnumSet<MemberUse> result = _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
-    if (!fullyUsed) {
-      result = result.union(MemberUses.PARTIAL_USE_ONLY);
-    }
-    return result;
-  }
-
-  @override
-  EnumSet<MemberUse> invoke(CallStructure callStructure) => read();
-
-  @override
-  EnumSet<MemberUse> fullyUse() {
-    if (fullyUsed) {
-      return MemberUses.NONE;
-    }
-    hasInit = hasRead = true;
-    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
-  }
-
-  @override
-  MemberUsage clone() {
-    return new FinalFieldUsage.cloned(entity, _pendingUse.clone(),
-        hasInit: hasInit, hasRead: hasRead);
-  }
-
-  @override
-  String toString() => 'FinalFieldUsage($entity,hasInit=$hasInit,'
-      'hasRead=$hasRead,pendingUse=${_pendingUse.iterable(MemberUse.values)},'
-      'initialConstants=${initialConstants.map((c) => c.toStructuredText())})';
-}
-
-class FunctionUsage extends MemberUsage {
-  @override
-  bool hasInvoke;
-  @override
-  bool hasRead;
-
-  FunctionUsage.cloned(FunctionEntity function, EnumSet<MemberUse> pendingUse,
-      {this.hasInvoke, this.hasRead})
-      : super.cloned(function, pendingUse);
-
-  FunctionUsage(FunctionEntity function)
-      : this.hasInvoke = false,
-        this.hasRead = false,
-        super.internal(function) {
-    if (function is JSignatureMethod) {
-      // We mark signature methods as "always used" to prevent them from being
-      // optimized away.
-      // TODO(johnniwinther): Make this a part of the regular enqueueing.
-      invoke(function.parameterStructure.callStructure);
-    }
-  }
-
-  @override
-  FunctionEntity get entity => super.entity;
+  bool get hasInvoke => invokes.isNotEmpty && parameterUsage.hasInvoke;
 
   @override
   EnumSet<MemberUse> get _originalUse =>
       entity.isInstanceMember ? MemberUses.ALL_INSTANCE : MemberUses.ALL_STATIC;
 
   @override
-  bool get hasPendingClosurizationUse => entity.isInstanceMember
-      ? _pendingUse.contains(MemberUse.CLOSURIZE_INSTANCE)
-      : _pendingUse.contains(MemberUse.CLOSURIZE_STATIC);
-
-  @override
-  EnumSet<MemberUse> read() => fullyUse();
-
-  @override
-  EnumSet<MemberUse> invoke(CallStructure callStructure) {
-    if (hasInvoke) {
-      return MemberUses.NONE;
-    }
-    hasInvoke = true;
-    return _pendingUse
-        .removeAll(hasRead ? MemberUses.NONE : MemberUses.NORMAL_ONLY);
-  }
-
-  @override
-  EnumSet<MemberUse> fullyUse() {
-    if (hasInvoke) {
-      if (hasRead) {
+  EnumSet<MemberUse> read(EnumSet<Access> accesses) {
+    bool alreadyHasInvoke = hasInvoke;
+    bool alreadyHasRead = hasRead;
+    reads.addAll(potentialReads.removeAll(accesses));
+    invokes.addAll(potentialInvokes.removeAll(Accesses.dynamicAccess));
+    parameterUsage.fullyUse();
+    if (alreadyHasInvoke) {
+      if (alreadyHasRead) {
         return MemberUses.NONE;
       }
-      hasRead = true;
       return _pendingUse.removeAll(entity.isInstanceMember
           ? MemberUses.CLOSURIZE_INSTANCE_ONLY
           : MemberUses.CLOSURIZE_STATIC_ONLY);
-    } else if (hasRead) {
-      hasInvoke = true;
+    } else if (alreadyHasRead) {
       return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
     } else {
-      hasRead = hasInvoke = true;
       return _pendingUse.removeAll(entity.isInstanceMember
           ? MemberUses.ALL_INSTANCE
           : MemberUses.ALL_STATIC);
@@ -445,296 +560,45 @@
   }
 
   @override
-  bool get fullyUsed => hasInvoke && hasRead;
-
-  @override
-  ParameterStructure get invokedParameters =>
-      hasInvoke ? entity.parameterStructure : null;
-
-  @override
-  MemberUsage clone() {
-    return new FunctionUsage.cloned(entity, _pendingUse.clone(),
-        hasInvoke: hasInvoke, hasRead: hasRead);
-  }
-}
-
-class ParameterTrackingFunctionUsage extends MemberUsage {
-  @override
-  bool hasRead;
-
-  final ParameterUsage _parameterUsage;
-
-  ParameterTrackingFunctionUsage.cloned(FunctionEntity function,
-      this._parameterUsage, EnumSet<MemberUse> pendingUse,
-      {this.hasRead})
-      : super.cloned(function, pendingUse);
-
-  ParameterTrackingFunctionUsage(FunctionEntity function)
-      : hasRead = false,
-        _parameterUsage = new ParameterUsage(function.parameterStructure),
-        super.internal(function) {
-    if (function is JSignatureMethod) {
-      // We mark signature methods as "always used" to prevent them from being
-      // optimized away.
-      // TODO(johnniwinther): Make this a part of the regular enqueueing.
-      invoke(CallStructure.NO_ARGS);
-    }
-  }
-
-  @override
-  bool get hasInvoke => _parameterUsage.hasInvoke;
-
-  @override
-  bool get hasPendingClosurizationUse => entity.isInstanceMember
-      ? _pendingUse.contains(MemberUse.CLOSURIZE_INSTANCE)
-      : _pendingUse.contains(MemberUse.CLOSURIZE_STATIC);
-
-  @override
-  EnumSet<MemberUse> get _originalUse =>
-      entity.isInstanceMember ? MemberUses.ALL_INSTANCE : MemberUses.ALL_STATIC;
-
-  @override
-  EnumSet<MemberUse> read() => fullyUse();
-
-  @override
-  EnumSet<MemberUse> invoke(CallStructure callStructure) {
-    if (_parameterUsage.isFullyUsed) {
-      return MemberUses.NONE;
-    }
+  EnumSet<MemberUse> invoke(
+      EnumSet<Access> accesses, CallStructure callStructure) {
     bool alreadyHasInvoke = hasInvoke;
-    bool hasPartialChange = _parameterUsage.invoke(callStructure);
-    EnumSet<MemberUse> result;
+    parameterUsage.invoke(callStructure);
+    invokes.addAll(potentialInvokes.removeAll(accesses));
     if (alreadyHasInvoke) {
-      result = MemberUses.NONE;
+      return MemberUses.NONE;
     } else {
-      result = _pendingUse
+      return _pendingUse
           .removeAll(hasRead ? MemberUses.NONE : MemberUses.NORMAL_ONLY);
     }
-    return hasPartialChange
-        ? result.union(MemberUses.PARTIAL_USE_ONLY)
-        : result;
   }
 
   @override
-  EnumSet<MemberUse> fullyUse() {
-    bool alreadyHasInvoke = hasInvoke;
-    _parameterUsage.fullyUse();
-    if (alreadyHasInvoke) {
-      if (hasRead) {
-        return MemberUses.NONE;
-      }
-      hasRead = true;
-      return _pendingUse.removeAll(entity.isInstanceMember
-          ? MemberUses.CLOSURIZE_INSTANCE_ONLY
-          : MemberUses.CLOSURIZE_STATIC_ONLY);
-    } else if (hasRead) {
-      return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
-    } else {
-      hasRead = true;
-      return _pendingUse.removeAll(entity.isInstanceMember
-          ? MemberUses.ALL_INSTANCE
-          : MemberUses.ALL_STATIC);
-    }
-  }
+  ParameterStructure get invokedParameters => parameterUsage.invokedParameters;
 
   @override
-  bool get hasPendingNormalUse => !isFullyInvoked;
-
-  @override
-  bool get isFullyInvoked => _parameterUsage.isFullyUsed;
-
-  @override
-  bool get fullyUsed => isFullyInvoked && hasRead;
-
-  @override
-  ParameterStructure get invokedParameters => _parameterUsage.invokedParameters;
+  bool get hasPendingDynamicInvoke =>
+      potentialInvokes.contains(Access.dynamicAccess) ||
+      (invokes.contains(Access.dynamicAccess) && !parameterUsage.isFullyUsed);
 
   @override
   MemberUsage clone() {
-    return new ParameterTrackingFunctionUsage.cloned(
-        entity, _parameterUsage.clone(), _pendingUse.clone(),
-        hasRead: hasRead);
-  }
-}
-
-class GetterUsage extends MemberUsage {
-  @override
-  bool hasRead;
-
-  GetterUsage.cloned(FunctionEntity getter, EnumSet<MemberUse> pendingUse,
-      {this.hasRead})
-      : super.cloned(getter, pendingUse);
-
-  GetterUsage(FunctionEntity getter)
-      : hasRead = false,
-        super.internal(getter);
-
-  @override
-  bool get fullyUsed => hasRead;
-
-  @override
-  EnumSet<MemberUse> read() {
-    if (hasRead) {
-      return MemberUses.NONE;
-    }
-    hasRead = true;
-    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
+    return new MethodUsage.cloned(
+        entity, parameterUsage.clone(), _pendingUse.clone(),
+        reads: reads.clone(),
+        potentialReads: potentialReads.clone(),
+        invokes: invokes.clone(),
+        potentialInvokes: potentialInvokes.clone());
   }
 
   @override
-  EnumSet<MemberUse> invoke(CallStructure callStructure) => read();
-
-  @override
-  EnumSet<MemberUse> fullyUse() => read();
-
-  @override
-  MemberUsage clone() {
-    return new GetterUsage.cloned(entity, _pendingUse.clone(),
-        hasRead: hasRead);
-  }
-}
-
-class SetterUsage extends MemberUsage {
-  @override
-  bool hasWrite;
-
-  SetterUsage.cloned(FunctionEntity setter, EnumSet<MemberUse> pendingUse,
-      {this.hasWrite})
-      : super.cloned(setter, pendingUse);
-
-  SetterUsage(FunctionEntity setter)
-      : hasWrite = false,
-        super.internal(setter);
-
-  @override
-  bool get fullyUsed => hasWrite;
-
-  @override
-  EnumSet<MemberUse> write() {
-    if (hasWrite) {
-      return MemberUses.NONE;
-    }
-    hasWrite = true;
-    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
-  }
-
-  @override
-  EnumSet<MemberUse> fullyUse() => write();
-
-  @override
-  MemberUsage clone() {
-    return new SetterUsage.cloned(entity, _pendingUse.clone(),
-        hasWrite: hasWrite);
-  }
-}
-
-class ConstructorUsage extends MemberUsage {
-  @override
-  bool hasInvoke;
-
-  ConstructorUsage.cloned(
-      ConstructorEntity constructor, EnumSet<MemberUse> pendingUse,
-      {this.hasInvoke})
-      : super.cloned(constructor, pendingUse);
-
-  ConstructorUsage(ConstructorEntity constructor)
-      : hasInvoke = false,
-        super.internal(constructor);
-
-  @override
-  ConstructorEntity get entity => super.entity;
-
-  @override
-  EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
-
-  @override
-  EnumSet<MemberUse> invoke(CallStructure callStructure) {
-    if (hasInvoke) {
-      return MemberUses.NONE;
-    }
-    hasInvoke = true;
-    return _pendingUse
-        .removeAll(hasRead ? MemberUses.NONE : MemberUses.NORMAL_ONLY);
-  }
-
-  @override
-  EnumSet<MemberUse> fullyUse() =>
-      invoke(entity.parameterStructure.callStructure);
-
-  @override
-  bool get fullyUsed => hasInvoke;
-
-  @override
-  ParameterStructure get invokedParameters =>
-      hasInvoke ? entity.parameterStructure : null;
-
-  @override
-  MemberUsage clone() {
-    return new ConstructorUsage.cloned(entity, _pendingUse.clone(),
-        hasInvoke: hasInvoke);
-  }
-}
-
-class ParameterTrackingConstructorUsage extends MemberUsage {
-  final ParameterUsage _parameterUsage;
-
-  ParameterTrackingConstructorUsage.cloned(ConstructorEntity constructor,
-      this._parameterUsage, EnumSet<MemberUse> pendingUse)
-      : super.cloned(constructor, pendingUse);
-
-  ParameterTrackingConstructorUsage(ConstructorEntity constructor)
-      : _parameterUsage = new ParameterUsage(constructor.parameterStructure),
-        super.internal(constructor);
-
-  @override
-  ConstructorEntity get entity => super.entity;
-
-  @override
-  EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
-
-  @override
-  EnumSet<MemberUse> invoke(CallStructure callStructure) {
-    if (isFullyInvoked) {
-      return MemberUses.NONE;
-    }
-    bool alreadyHasInvoke = hasInvoke;
-    bool hasPartialChange = _parameterUsage.invoke(callStructure);
-    EnumSet<MemberUse> result;
-    if (alreadyHasInvoke) {
-      result = MemberUses.NONE;
-    } else {
-      result = _pendingUse
-          .removeAll(hasRead ? MemberUses.NONE : MemberUses.NORMAL_ONLY);
-    }
-    return hasPartialChange
-        ? result.union(MemberUses.PARTIAL_USE_ONLY)
-        : result;
-  }
-
-  @override
-  EnumSet<MemberUse> fullyUse() =>
-      invoke(entity.parameterStructure.callStructure);
-
-  @override
-  bool get hasInvoke => _parameterUsage.hasInvoke;
-
-  @override
-  bool get fullyUsed => _parameterUsage.isFullyUsed;
-
-  @override
-  bool get hasPendingNormalUse => !isFullyInvoked;
-
-  @override
-  bool get isFullyInvoked => _parameterUsage.isFullyUsed;
-
-  @override
-  ParameterStructure get invokedParameters => _parameterUsage.invokedParameters;
-
-  @override
-  MemberUsage clone() {
-    return new ParameterTrackingConstructorUsage.cloned(
-        entity, _parameterUsage.clone(), _pendingUse.clone());
-  }
+  String toString() => 'MethodUsage($entity,'
+      'reads=${reads.iterable(Access.values)},'
+      'invokes=${invokes.iterable(Access.values)},'
+      'parameterUsage=${parameterUsage},'
+      'potentialReads=${potentialReads.iterable(Access.values)},'
+      'potentialInvokes=${potentialInvokes.iterable(Access.values)},'
+      'pendingUse=${_pendingUse.iterable(MemberUse.values)})';
 }
 
 /// Enum class for the possible kind of use of [MemberEntity] objects.
@@ -747,12 +611,6 @@
 
   /// Tear-off of a static method.
   CLOSURIZE_STATIC,
-
-  /// Invocation that provides previously unprovided optional parameters.
-  ///
-  /// This is used to check that no partial use is missed by the enqueuer, as
-  /// asserted through the `Enqueuery.checkEnqueuerConsistency` method.
-  PARTIAL_USE,
 }
 
 /// Common [EnumSet]s used for [MemberUse].
@@ -768,8 +626,6 @@
       const EnumSet<MemberUse>.fixed(3);
   static const EnumSet<MemberUse> ALL_STATIC =
       const EnumSet<MemberUse>.fixed(5);
-  static const EnumSet<MemberUse> PARTIAL_USE_ONLY =
-      const EnumSet<MemberUse>.fixed(8);
 }
 
 typedef void MemberUsedCallback(MemberEntity member, EnumSet<MemberUse> useSet);
@@ -804,7 +660,7 @@
   EnumSet<ClassUse> get _originalUse => ClassUses.ALL;
 
   @override
-  String toString() => '$cls:${appliedUse.iterable(ClassUse.values)}';
+  String toString() => '$cls:${_appliedUse.iterable(ClassUse.values)}';
 }
 
 /// Enum class for the possible kind of use of [ClassEntity] objects.
@@ -822,179 +678,6 @@
 
 typedef void ClassUsedCallback(ClassEntity cls, EnumSet<ClassUse> useSet);
 
-// TODO(johnniwinther): Merge this with [MemberUsage].
-abstract class StaticMemberUsage extends AbstractUsage<MemberUse>
-    implements MemberUsage {
-  @override
-  final MemberEntity entity;
-
-  bool hasNormalUse;
-  bool get hasClosurization => false;
-
-  StaticMemberUsage.cloned(this.entity, EnumSet<MemberUse> pendingUse,
-      {this.hasNormalUse: false})
-      : super.cloned(pendingUse);
-
-  StaticMemberUsage.internal(this.entity)
-      : this.hasNormalUse = false,
-        super();
-
-  EnumSet<MemberUse> normalUse() {
-    if (hasNormalUse) {
-      return MemberUses.NONE;
-    }
-    hasNormalUse = true;
-    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
-  }
-
-  EnumSet<MemberUse> tearOff();
-
-  @override
-  EnumSet<MemberUse> init() => normalUse();
-
-  @override
-  EnumSet<MemberUse> constantInit(ConstantValue constant) => normalUse();
-
-  @override
-  EnumSet<MemberUse> read() => tearOff();
-
-  @override
-  EnumSet<MemberUse> write() => normalUse();
-
-  @override
-  EnumSet<MemberUse> invoke(CallStructure callStructure) => normalUse();
-
-  @override
-  EnumSet<MemberUse> fullyUse() => normalUse();
-
-  @override
-  Iterable<ConstantValue> get initialConstants => null;
-
-  @override
-  bool get hasPendingNormalUse => _pendingUse.contains(MemberUse.NORMAL);
-
-  @override
-  bool get isFullyInvoked => hasInvoke;
-
-  @override
-  EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
-
-  @override
-  bool dataEquals(MemberUsage other) {
-    assert(entity == other.entity);
-    return hasInit == other.hasInit &&
-        hasRead == other.hasRead &&
-        hasInvoke == other.hasInvoke &&
-        hasWrite == other.hasWrite &&
-        hasPendingClosurizationUse == other.hasPendingClosurizationUse &&
-        hasPendingNormalUse == other.hasPendingNormalUse &&
-        fullyUsed == other.fullyUsed &&
-        isFullyInvoked == other.isFullyInvoked &&
-        _pendingUse == other._pendingUse &&
-        appliedUse == other.appliedUse;
-  }
-
-  @override
-  String toString() => '$entity:${appliedUse.iterable(MemberUse.values)}';
-}
-
-class GeneralStaticMemberUsage extends StaticMemberUsage {
-  GeneralStaticMemberUsage(MemberEntity entity) : super.internal(entity);
-
-  GeneralStaticMemberUsage.cloned(
-      MemberEntity entity, EnumSet<MemberUse> pendingUse,
-      {bool hasNormalUse})
-      : super.cloned(entity, pendingUse, hasNormalUse: hasNormalUse);
-
-  @override
-  EnumSet<MemberUse> tearOff() => normalUse();
-
-  @override
-  bool get hasInit => true;
-
-  @override
-  bool get fullyUsed => hasNormalUse;
-
-  @override
-  bool get hasInvoke => hasNormalUse;
-
-  @override
-  bool get hasWrite => hasNormalUse;
-
-  @override
-  bool get hasRead => hasNormalUse;
-
-  @override
-  bool get hasPendingClosurizationUse => false;
-
-  @override
-  ParameterStructure get invokedParameters => null;
-
-  @override
-  MemberUsage clone() {
-    return new GeneralStaticMemberUsage.cloned(entity, _pendingUse.clone(),
-        hasNormalUse: hasNormalUse);
-  }
-}
-
-class StaticFunctionUsage extends StaticMemberUsage {
-  @override
-  bool hasClosurization;
-
-  StaticFunctionUsage(FunctionEntity entity)
-      : hasClosurization = false,
-        super.internal(entity);
-
-  StaticFunctionUsage.cloned(
-      FunctionEntity entity, EnumSet<MemberUse> pendingUse,
-      {bool hasNormalUse, this.hasClosurization})
-      : super.cloned(entity, pendingUse, hasNormalUse: hasNormalUse);
-
-  @override
-  FunctionEntity get entity => super.entity;
-
-  @override
-  bool get hasInit => true;
-
-  @override
-  EnumSet<MemberUse> tearOff() {
-    if (hasClosurization) {
-      return MemberUses.NONE;
-    }
-    hasNormalUse = hasClosurization = true;
-    return _pendingUse.removeAll(MemberUses.ALL_STATIC);
-  }
-
-  @override
-  EnumSet<MemberUse> get _originalUse => MemberUses.ALL_STATIC;
-
-  @override
-  bool get hasPendingClosurizationUse =>
-      _pendingUse.contains(MemberUse.CLOSURIZE_STATIC);
-
-  @override
-  bool get fullyUsed => hasNormalUse && hasClosurization;
-
-  @override
-  bool get hasInvoke => hasNormalUse;
-
-  @override
-  bool get hasWrite => hasNormalUse;
-
-  @override
-  bool get hasRead => hasClosurization;
-
-  @override
-  ParameterStructure get invokedParameters =>
-      hasInvoke ? entity.parameterStructure : null;
-
-  @override
-  MemberUsage clone() {
-    return new StaticFunctionUsage.cloned(entity, _pendingUse.clone(),
-        hasNormalUse: hasNormalUse, hasClosurization: hasClosurization);
-  }
-}
-
 /// Object used for tracking parameter use in constructor and method
 /// invocations.
 class ParameterUsage {
@@ -1112,4 +795,68 @@
         areAllTypeParametersProvided: _areAllTypeParametersProvided,
         unprovidedNamedParameters: _unprovidedNamedParameters?.toSet());
   }
+
+  @override
+  String toString() {
+    return 'ParameterUsage('
+        '_hasInvoke=$_hasInvoke,'
+        '_providedPositionalParameters=$_providedPositionalParameters,'
+        '_areAllTypeParametersProvided=$_areAllTypeParametersProvided,'
+        '_unprovidedNamedParameters=$_unprovidedNamedParameters)';
+  }
+}
+
+/// Enum for member access kinds use in [MemberUsage] computation during
+/// resolution or codegen enqueueing.
+enum Access {
+  /// Statically bound access of a member.
+  staticAccess,
+
+  /// Dynamically bound access of a member.
+  dynamicAccess,
+
+  /// Direct access of a super class member.
+  superAccess,
+}
+
+/// Access sets used for registration of member usage.
+class Accesses {
+  /// Statically bound access of a member.
+  static const EnumSet<Access> staticAccess = const EnumSet<Access>.fixed(1);
+
+  /// Dynamically bound access of a member. This implies the statically bound
+  /// access of the member.
+  static const EnumSet<Access> dynamicAccess = const EnumSet<Access>.fixed(3);
+
+  /// Direct access of a super class member. This implies the statically bound
+  /// access of the member.
+  static const EnumSet<Access> superAccess = const EnumSet<Access>.fixed(5);
+}
+
+/// The accesses of a member collected during closed world computation.
+class MemberAccess {
+  static const String tag = 'MemberAccess';
+
+  final EnumSet<Access> reads;
+  final EnumSet<Access> writes;
+  final EnumSet<Access> invokes;
+
+  MemberAccess(this.reads, this.writes, this.invokes);
+
+  factory MemberAccess.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    EnumSet<Access> reads = new EnumSet.fixed(source.readInt());
+    EnumSet<Access> writes = new EnumSet.fixed(source.readInt());
+    EnumSet<Access> invokes = new EnumSet.fixed(source.readInt());
+    source.end(tag);
+    return new MemberAccess(reads, writes, invokes);
+  }
+
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeInt(reads.value);
+    sink.writeInt(writes.value);
+    sink.writeInt(invokes.value);
+    sink.end(tag);
+  }
 }
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index 7415ea2..82cc3a2 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -18,7 +18,6 @@
 import '../js_backend/no_such_method_registry.dart';
 import '../js_backend/runtime_types.dart';
 import '../kernel/element_map_impl.dart';
-import '../kernel/kelements.dart';
 import '../kernel/kernel_world.dart';
 import '../native/enqueue.dart' show NativeResolutionEnqueuer;
 import '../options.dart';
@@ -35,47 +34,6 @@
 import 'world_builder.dart';
 
 abstract class ResolutionWorldBuilder implements WorldBuilder, OpenWorld {
-  /// Calls [f] for all local functions in the program together with the member
-  /// in which they are declared.
-  ///
-  /// Used by the mirror tracking system to find all live closure instances.
-  void forEachLocalFunction(void f(MemberEntity member, Local localFunction));
-
-  /// Set of (live) local functions (closures).
-  ///
-  /// A live function is one whose enclosing member function has been enqueued.
-  Iterable<Local> get localFunctions;
-
-  /// Set of (live) local functions (closures) whose signatures reference type
-  /// variables.
-  ///
-  /// A live function is one whose enclosing member function has been enqueued.
-  Iterable<Local> get localFunctionsWithFreeTypeVariables;
-
-  /// Set of live closurized members whose signatures reference type variables.
-  ///
-  /// A closurized method is considered live if the enclosing class has been
-  /// instantiated.
-  Iterable<FunctionEntity> get closurizedMembersWithFreeTypeVariables;
-
-  /// Returns `true` if [cls] is considered to be implemented by an
-  /// instantiated class, either directly, through subclasses or through
-  /// subtypes. The latter case only contains spurious information from
-  /// instantiations through factory constructors and mixins.
-  // TODO(johnniwinther): Improve semantic precision.
-  bool isImplemented(covariant ClassEntity cls);
-
-  /// Set of all fields that are statically known to be written to.
-  Iterable<FieldEntity> get fieldSetters;
-
-  /// Call [f] for all classes with instantiated types. This includes the
-  /// directly and abstractly instantiated classes but also classes whose type
-  /// arguments are used in live factory constructors.
-  void forEachInstantiatedClass(f(ClassEntity cls, InstantiationInfo info));
-
-  /// Returns `true` if [member] is invoked as a setter.
-  bool hasInvokedSetter(MemberEntity member);
-
   /// Returns `true` if [member] has been marked as used (called, read, etc.) in
   /// this world builder.
   // TODO(johnniwinther): Maybe this should be part of [ClosedWorld] (instead).
@@ -104,12 +62,16 @@
   // TODO(johnniwinther): Support unknown type arguments for generic types.
   void registerTypeInstantiation(
       InterfaceType type, ClassUsedCallback classUsed,
-      {ConstructorEntity constructor, bool isRedirection: false});
+      {ConstructorEntity constructor});
 
   /// Computes usage for all members declared by [cls]. Calls [membersUsed] with
   /// the usage changes for each member.
+  ///
+  /// If [checkEnqueuerConsistency] is `true` we check that no new member
+  /// usage can be found. This check is performed without changing the already
+  /// collected member usage.
   void processClassMembers(ClassEntity cls, MemberUsedCallback memberUsed,
-      {bool dryRun: false});
+      {bool checkEnqueuerConsistency: false});
 
   /// Applies the [dynamicUse] to applicable instance members. Calls
   /// [membersUsed] with the usage changes for each member.
@@ -139,23 +101,19 @@
 class Instance {
   final InterfaceType type;
   final Instantiation kind;
-  final bool isRedirection;
 
-  Instance(this.type, this.kind, {this.isRedirection: false});
+  Instance(this.type, this.kind);
 
   @override
   int get hashCode {
-    return Hashing.objectHash(
-        type, Hashing.objectHash(kind, Hashing.objectHash(isRedirection)));
+    return Hashing.objectHash(type, Hashing.objectHash(kind));
   }
 
   @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! Instance) return false;
-    return type == other.type &&
-        kind == other.kind &&
-        isRedirection == other.isRedirection;
+    return type == other.type && kind == other.kind;
   }
 
   @override
@@ -169,9 +127,6 @@
     } else if (kind == Instantiation.UNINSTANTIATED) {
       sb.write(' none');
     }
-    if (isRedirection) {
-      sb.write(' redirect');
-    }
     return sb.toString();
   }
 }
@@ -242,12 +197,11 @@
 
   /// Register [type] as the instantiation [kind] using [constructor].
   void addInstantiation(
-      ConstructorEntity constructor, InterfaceType type, Instantiation kind,
-      {bool isRedirection: false}) {
+      ConstructorEntity constructor, InterfaceType type, Instantiation kind) {
     instantiationMap ??= <ConstructorEntity, Set<Instance>>{};
     instantiationMap
         .putIfAbsent(constructor, () => new Set<Instance>())
-        .add(new Instance(type, kind, isRedirection: isRedirection));
+        .add(new Instance(type, kind));
     switch (kind) {
       case Instantiation.DIRECTLY_INSTANTIATED:
         isDirectlyInstantiated = true;
@@ -313,12 +267,12 @@
   /// The set of all referenced static fields.
   ///
   /// Invariant: Elements are declaration elements.
-  final Set<FieldEntity> allReferencedStaticFields = new Set<FieldEntity>();
+  final Set<FieldEntity> _allReferencedStaticFields = new Set<FieldEntity>();
 
   /// Documentation wanted -- johnniwinther
   ///
   /// Invariant: Elements are declaration elements.
-  final Set<FunctionEntity> methodsNeedingSuperGetter =
+  final Set<FunctionEntity> _methodsNeedingSuperGetter =
       new Set<FunctionEntity>();
   final Map<String, Map<Selector, SelectorConstraints>> _invokedNames =
       <String, Map<Selector, SelectorConstraints>>{};
@@ -338,56 +292,33 @@
 
   Map<MemberEntity, MemberUsage> get memberUsageForTesting => _memberUsage;
 
-  Map<MemberEntity, MemberUsage> get staticMemberUsageForTesting {
-    Map<MemberEntity, MemberUsage> map = <MemberEntity, MemberUsage>{};
-    _memberUsage.forEach((MemberEntity member, MemberUsage usage) {
-      if (!member.isInstanceMember) {
-        map[member] = usage;
-      }
-    });
-    return map;
-  }
-
-  Map<MemberEntity, MemberUsage> get instanceMemberUsageForTesting {
-    Map<MemberEntity, MemberUsage> map = <MemberEntity, MemberUsage>{};
-    _memberUsage.forEach((MemberEntity member, MemberUsage usage) {
-      if (member.isInstanceMember) {
-        map[member] = usage;
-      }
-    });
-    return map;
-  }
-
-  /// Map containing instance members of live classes that are not yet fully
-  /// live themselves.
-  final Map<String, Set<MemberUsage>> _instanceMembersByName =
+  /// Map containing instance members of live classes that have not yet been
+  /// fully invoked dynamically.
+  ///
+  /// A method is fully invoked if all is optional parameter have been passed
+  /// in some invocation.
+  final Map<String, Set<MemberUsage>> _invokableInstanceMembersByName =
       <String, Set<MemberUsage>>{};
 
-  /// Map containing instance methods of live classes that are not yet
-  /// closurized.
-  final Map<String, Set<MemberUsage>> _instanceFunctionsByName =
+  /// Map containing instance members of live classes that have not yet been
+  /// read from dynamically.
+  final Map<String, Set<MemberUsage>> _readableInstanceMembersByName =
       <String, Set<MemberUsage>>{};
 
-  @override
-  final Set<FieldEntity> fieldSetters = new Set<FieldEntity>();
-  @override
-  final Set<DartType> isChecks = new Set<DartType>();
+  /// Map containing instance members of live classes that have not yet been
+  /// written to dynamically.
+  final Map<String, Set<MemberUsage>> _writableInstanceMembersByName =
+      <String, Set<MemberUsage>>{};
+
+  final Set<FieldEntity> _fieldSetters = new Set<FieldEntity>();
+
+  final Set<DartType> _isChecks = new Set<DartType>();
 
   /// Set of all closures in the program. Used by the mirror tracking system
   /// to find all live closure instances.
-  @override
-  final Set<Local> localFunctions = new Set<Local>();
+  final Set<Local> _localFunctions = new Set<Local>();
 
-  /// Set of live local functions (closures) whose signatures reference type
-  /// variables.
-  ///
-  /// A local function is considered live if the enclosing member function is
-  /// live.
-  @override
-  final Set<Local> localFunctionsWithFreeTypeVariables = new Set<Local>();
-
-  @override
-  final Set<FunctionEntity> closurizedMembersWithFreeTypeVariables =
+  final Set<FunctionEntity> _closurizedMembersWithFreeTypeVariables =
       new Set<FunctionEntity>();
 
   final CompilerOptions _options;
@@ -409,17 +340,13 @@
   final ClassHierarchyBuilder _classHierarchyBuilder;
   final ClassQueries _classQueries;
 
-  bool hasRuntimeTypeSupport = false;
-  bool hasFunctionApplySupport = false;
-
   bool _closed = false;
   KClosedWorld _closedWorldCache;
   final Set<MemberEntity> _liveInstanceMembers = new Set<MemberEntity>();
 
   final Set<ConstantValue> _constantValues = new Set<ConstantValue>();
 
-  @override
-  final Set<Local> genericLocalFunctions = new Set<Local>();
+  final Set<Local> _genericLocalFunctions = new Set<Local>();
 
   Set<MemberEntity> _processedMembers = new Set<MemberEntity>();
 
@@ -460,33 +387,6 @@
   }
 
   @override
-  Iterable<FunctionEntity> get genericInstanceMethods {
-    List<FunctionEntity> functions = <FunctionEntity>[];
-    for (MemberEntity member in processedMembers) {
-      if (member.isInstanceMember &&
-          member.isFunction &&
-          _elementEnvironment.getFunctionTypeVariables(member).isNotEmpty) {
-        functions.add(member);
-      }
-    }
-    return functions;
-  }
-
-  @override
-  Iterable<FunctionEntity> get userNoSuchMethods {
-    List<FunctionEntity> functions = <FunctionEntity>[];
-    for (MemberEntity member in processedMembers) {
-      if (member.isInstanceMember &&
-          member.isFunction &&
-          member.name == Identifiers.noSuchMethod_ &&
-          !_commonElements.isDefaultNoSuchMethodImplementation(member)) {
-        functions.add(member);
-      }
-    }
-    return functions;
-  }
-
-  @override
   Iterable<MemberEntity> get processedMembers => _processedMembers;
 
   @override
@@ -510,33 +410,11 @@
     return classes;
   }
 
-  // TODO(johnniwinther): Improve semantic precision.
-  @override
-  Iterable<InterfaceType> get instantiatedTypes {
-    Set<InterfaceType> types = new Set<InterfaceType>();
-    getInstantiationMap().forEach((_, InstantiationInfo info) {
-      if (info.instantiationMap != null) {
-        for (Set<Instance> instances in info.instantiationMap.values) {
-          for (Instance instance in instances) {
-            types.add(instance.type);
-          }
-        }
-      }
-    });
-    return types;
-  }
-
-  @override
-  bool isImplemented(ClassEntity cls) {
-    return _implementedClasses.contains(cls);
-  }
-
   @override
   void registerClosurizedMember(MemberEntity element) {
-    closurizedMembers.add(element);
     FunctionType type = _elementEnvironment.getFunctionType(element);
     if (type.containsTypeVariables) {
-      closurizedMembersWithFreeTypeVariables.add(element);
+      _closurizedMembersWithFreeTypeVariables.add(element);
     }
   }
 
@@ -546,7 +424,7 @@
   @override
   void registerTypeInstantiation(
       InterfaceType type, ClassUsedCallback classUsed,
-      {ConstructorEntity constructor, bool isRedirection: false}) {
+      {ConstructorEntity constructor}) {
     ClassEntity cls = type.element;
     InstantiationInfo info =
         _instantiationInfo.putIfAbsent(cls, () => new InstantiationInfo());
@@ -563,8 +441,7 @@
         kind = Instantiation.DIRECTLY_INSTANTIATED;
       }
     }
-    info.addInstantiation(constructor, type, kind,
-        isRedirection: isRedirection);
+    info.addInstantiation(constructor, type, kind);
     if (kind != Instantiation.UNINSTANTIATED) {
       _classHierarchyBuilder.updateClassHierarchyNodeForClass(cls,
           directlyInstantiated: info.isDirectlyInstantiated,
@@ -585,11 +462,6 @@
     }
   }
 
-  @override
-  void forEachInstantiatedClass(f(ClassEntity cls, InstantiationInfo info)) {
-    getInstantiationMap().forEach(f);
-  }
-
   Iterable<CallStructure> _getMatchingCallStructures(
       Map<Selector, SelectorConstraints> selectors, MemberEntity member) {
     if (selectors == null) return const <CallStructure>[];
@@ -630,12 +502,10 @@
   }
 
   bool _hasInvokedGetter(MemberEntity member) {
-    return _hasMatchingSelector(_invokedGetters[member.name], member) ||
-        member.isFunction && methodsNeedingSuperGetter.contains(member);
+    return _hasMatchingSelector(_invokedGetters[member.name], member);
   }
 
-  @override
-  bool hasInvokedSetter(MemberEntity member) {
+  bool _hasInvokedSetter(MemberEntity member) {
     return _hasMatchingSelector(_invokedSetters[member.name], member);
   }
 
@@ -666,23 +536,36 @@
             dynamicUse.selector, dynamicUse.typeArguments);
         if (_registerNewSelector(dynamicUse, _invokedNames)) {
           _process(
-              _instanceMembersByName,
-              (m) => m.invoke(dynamicUse.selector.callStructure),
-              (u) => !u.hasPendingNormalUse);
+              _invokableInstanceMembersByName,
+              (m) => m.invoke(
+                  Accesses.dynamicAccess, dynamicUse.selector.callStructure),
+              // If not all optional parameters have been passed in invocations
+              // we must keep the member in [_invokableInstanceMembersByName].
+              // TODO(johnniwinther): Also remove from
+              // [_readableInstanceMembersByName] in case of getters/setters.
+              (u) => !u.hasPendingDynamicInvoke);
         }
         break;
       case DynamicUseKind.GET:
         if (_registerNewSelector(dynamicUse, _invokedGetters)) {
-          _process(_instanceMembersByName, (m) => m.read(),
-              (u) => !u.hasPendingNormalUse);
-          _process(_instanceFunctionsByName, (m) => m.read(),
-              (u) => !u.hasPendingClosurizationUse);
+          _process(
+              _readableInstanceMembersByName,
+              (m) => m.read(Accesses.dynamicAccess),
+              // TODO(johnniwinther): Members cannot be partially read so
+              // we should always remove them.
+              // TODO(johnniwinther): Also remove from
+              // [_invokableInstanceMembersByName] in case of methods.
+              (u) => !u.hasPendingDynamicRead);
         }
         break;
       case DynamicUseKind.SET:
         if (_registerNewSelector(dynamicUse, _invokedSetters)) {
-          _process(_instanceMembersByName, (m) => m.write(),
-              (u) => !u.hasPendingNormalUse);
+          _process(
+              _writableInstanceMembersByName,
+              (m) => m.write(Accesses.dynamicAccess),
+              // TODO(johnniwinther): Members cannot be partially written so
+              // we should always remove them.
+              (u) => !u.hasPendingDynamicWrite);
         }
         break;
     }
@@ -706,7 +589,7 @@
 
   @override
   void registerIsCheck(covariant DartType type) {
-    isChecks.add(type);
+    _isChecks.add(type);
   }
 
   @override
@@ -720,13 +603,10 @@
       Local localFunction = staticUse.element;
       FunctionType type =
           _elementEnvironment.getLocalFunctionType(localFunction);
-      if (type.containsTypeVariables) {
-        localFunctionsWithFreeTypeVariables.add(localFunction);
-      }
       if (type.typeVariables.isNotEmpty) {
-        genericLocalFunctions.add(localFunction);
+        _genericLocalFunctions.add(localFunction);
       }
-      localFunctions.add(staticUse.element);
+      _localFunctions.add(staticUse.element);
       return;
     } else if (staticUse.kind == StaticUseKind.CLOSURE_CALL) {
       if (staticUse.typeArguments?.isNotEmpty ?? false) {
@@ -742,39 +622,45 @@
     MemberUsage usage = _getMemberUsage(element, useSet);
 
     if ((element.isStatic || element.isTopLevel) && element.isField) {
-      allReferencedStaticFields.add(staticUse.element);
+      _allReferencedStaticFields.add(staticUse.element);
     }
     // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and
     // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue.
     // Also [CLOSURE] contains [LocalFunctionElement] which we cannot
     // enqueue.
+
     switch (staticUse.kind) {
-      case StaticUseKind.FIELD_GET:
+      case StaticUseKind.INSTANCE_FIELD_GET:
         break;
-      case StaticUseKind.FIELD_SET:
-        fieldSetters.add(staticUse.element);
+      case StaticUseKind.INSTANCE_FIELD_SET:
+        _fieldSetters.add(staticUse.element);
         break;
       case StaticUseKind.CLOSURE:
       case StaticUseKind.CLOSURE_CALL:
         // Already handled above.
         break;
       case StaticUseKind.SUPER_TEAR_OFF:
-        useSet.addAll(usage.read());
-        methodsNeedingSuperGetter.add(staticUse.element);
+        useSet.addAll(usage.read(Accesses.superAccess));
+        _methodsNeedingSuperGetter.add(staticUse.element);
         break;
       case StaticUseKind.SUPER_FIELD_SET:
-        fieldSetters.add(staticUse.element);
-        useSet.addAll(usage.write());
+        _fieldSetters.add(staticUse.element);
+        useSet.addAll(usage.write(Accesses.superAccess));
         break;
-      case StaticUseKind.GET:
-        useSet.addAll(usage.read());
+      case StaticUseKind.SUPER_GET:
+        useSet.addAll(usage.read(Accesses.superAccess));
+        break;
+      case StaticUseKind.STATIC_GET:
+        useSet.addAll(usage.read(Accesses.staticAccess));
         break;
       case StaticUseKind.STATIC_TEAR_OFF:
-        closurizedStatics.add(element);
-        useSet.addAll(usage.read());
+        useSet.addAll(usage.read(Accesses.staticAccess));
         break;
-      case StaticUseKind.SET:
-        useSet.addAll(usage.write());
+      case StaticUseKind.SUPER_SETTER_SET:
+        useSet.addAll(usage.write(Accesses.superAccess));
+        break;
+      case StaticUseKind.STATIC_SET:
+        useSet.addAll(usage.write(Accesses.staticAccess));
         break;
       case StaticUseKind.FIELD_INIT:
         useSet.addAll(usage.init());
@@ -782,14 +668,20 @@
       case StaticUseKind.FIELD_CONSTANT_INIT:
         useSet.addAll(usage.constantInit(staticUse.constant));
         break;
-      case StaticUseKind.INVOKE:
+      case StaticUseKind.SUPER_INVOKE:
         registerStaticInvocation(staticUse);
-        useSet.addAll(usage.invoke(staticUse.callStructure));
+        useSet.addAll(
+            usage.invoke(Accesses.superAccess, staticUse.callStructure));
+        break;
+      case StaticUseKind.STATIC_INVOKE:
+        registerStaticInvocation(staticUse);
+        useSet.addAll(
+            usage.invoke(Accesses.staticAccess, staticUse.callStructure));
         break;
       case StaticUseKind.CONSTRUCTOR_INVOKE:
       case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
-      case StaticUseKind.REDIRECTION:
-        useSet.addAll(usage.invoke(staticUse.callStructure));
+        useSet.addAll(
+            usage.invoke(Accesses.staticAccess, staticUse.callStructure));
         break;
       case StaticUseKind.DIRECT_INVOKE:
         failedAt(element, 'Direct static use is not supported for resolution.');
@@ -838,10 +730,11 @@
 
   @override
   void processClassMembers(ClassEntity cls, MemberUsedCallback memberUsed,
-      {bool dryRun: false}) {
+      {bool checkEnqueuerConsistency: false}) {
     _elementEnvironment.forEachClassMember(cls,
         (ClassEntity cls, MemberEntity member) {
-      _processInstantiatedClassMember(cls, member, memberUsed, dryRun: dryRun);
+      _processInstantiatedClassMember(cls, member, memberUsed,
+          checkEnqueuerConsistency: checkEnqueuerConsistency);
     });
   }
 
@@ -866,7 +759,7 @@
   }
 
   MemberUsage _getMemberUsage(MemberEntity member, EnumSet<MemberUse> useSet,
-      {bool dryRun: false}) {
+      {bool checkEnqueuerConsistency: false}) {
     MemberUsage usage = _memberUsage[member];
     if (usage == null) {
       if (member.isInstanceMember) {
@@ -882,112 +775,129 @@
         // Note: this assumes that there are no non-native fields on native
         // classes, which may not be the case when a native class is subclassed.
         bool isNative = _nativeBasicData.isNativeClass(cls);
-        usage =
-            new MemberUsage(member, isNative: isNative, trackParameters: true);
-        useSet.addAll(usage.appliedUse);
-        if (!dryRun) {
+        usage = new MemberUsage(member);
+        if (member.isField && !isNative) {
+          useSet.addAll(usage.init());
+        }
+        if (!checkEnqueuerConsistency) {
           if (member.isField && isNative) {
             registerUsedElement(member);
           }
           if (member.isFunction &&
               member.name == Identifiers.call &&
               _elementEnvironment.isGenericClass(cls)) {
-            closurizedMembersWithFreeTypeVariables.add(member);
+            _closurizedMembersWithFreeTypeVariables.add(member);
           }
         }
 
-        if (!usage.hasRead && _hasInvokedGetter(member)) {
-          useSet.addAll(usage.read());
+        if (usage.hasPendingDynamicRead && _hasInvokedGetter(member)) {
+          useSet.addAll(usage.read(Accesses.dynamicAccess));
         }
-        if (!usage.isFullyInvoked) {
+        if (usage.hasPendingDynamicInvoke) {
           Iterable<CallStructure> callStructures =
               _getInvocationCallStructures(member);
           for (CallStructure callStructure in callStructures) {
-            useSet.addAll(usage.invoke(callStructure));
-            if (usage.isFullyInvoked) {
+            useSet.addAll(usage.invoke(Accesses.dynamicAccess, callStructure));
+            if (!usage.hasPendingDynamicInvoke) {
               break;
             }
           }
         }
-        if (!usage.hasWrite && hasInvokedSetter(member)) {
-          useSet.addAll(usage.write());
+        if (usage.hasPendingDynamicWrite && _hasInvokedSetter(member)) {
+          useSet.addAll(usage.write(Accesses.dynamicAccess));
         }
 
-        if (!dryRun) {
-          if (usage.hasPendingNormalUse) {
-            // The element is not yet used. Add it to the list of instance
-            // members to still be processed.
-            _instanceMembersByName
-                .putIfAbsent(memberName, () => new Set<MemberUsage>())
+        if (!checkEnqueuerConsistency) {
+          if (usage.hasPendingDynamicInvoke) {
+            _invokableInstanceMembersByName
+                .putIfAbsent(memberName, () => {})
                 .add(usage);
           }
-          if (usage.hasPendingClosurizationUse) {
-            // Store the member in [instanceFunctionsByName] to catch
-            // getters on the function.
-            _instanceFunctionsByName
-                .putIfAbsent(memberName, () => new Set<MemberUsage>())
+          if (usage.hasPendingDynamicRead) {
+            _readableInstanceMembersByName
+                .putIfAbsent(memberName, () => {})
+                .add(usage);
+          }
+          if (usage.hasPendingDynamicWrite) {
+            _writableInstanceMembersByName
+                .putIfAbsent(memberName, () => {})
                 .add(usage);
           }
         }
       } else {
-        usage = new MemberUsage(member, trackParameters: true);
-        useSet.addAll(usage.appliedUse);
+        usage = new MemberUsage(member);
+        if (member.isField) {
+          useSet.addAll(usage.init());
+        }
       }
-    }
-    if (!dryRun) {
-      _memberUsage[member] = usage;
+      if (!checkEnqueuerConsistency) {
+        _memberUsage[member] = usage;
+      }
     }
     return usage;
   }
 
-  void _processInstantiatedClassMember(ClassEntity cls,
-      covariant MemberEntity member, MemberUsedCallback memberUsed,
-      {bool dryRun: false}) {
+  void _processInstantiatedClassMember(
+      ClassEntity cls, MemberEntity member, MemberUsedCallback memberUsed,
+      {bool checkEnqueuerConsistency: false}) {
     if (!member.isInstanceMember) return;
     String memberName = member.name;
 
     MemberUsage usage = _memberUsage[member];
     if (usage == null) {
       EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
-      usage = _getMemberUsage(member, useSet, dryRun: dryRun);
-      memberUsed(usage.entity, useSet);
+      usage = _getMemberUsage(member, useSet,
+          checkEnqueuerConsistency: checkEnqueuerConsistency);
+      if (useSet.isNotEmpty) {
+        if (checkEnqueuerConsistency) {
+          throw new SpannableAssertionFailure(member,
+              'Unenqueued usage of $member: \nbefore: <none>\nafter : $usage');
+        } else {
+          memberUsed(usage.entity, useSet);
+        }
+      }
     } else {
       MemberUsage original = usage;
-      if (dryRun) {
+      if (checkEnqueuerConsistency) {
         usage = usage.clone();
       }
-      if (!usage.fullyUsed) {
+      if (usage.hasPendingDynamicUse) {
         EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
-        if (!usage.hasRead && _hasInvokedGetter(member)) {
-          useSet.addAll(usage.read());
+        if (usage.hasPendingDynamicRead && _hasInvokedGetter(member)) {
+          useSet.addAll(usage.read(Accesses.dynamicAccess));
         }
-        if (!usage.isFullyInvoked) {
+        if (usage.hasPendingDynamicInvoke) {
           Iterable<CallStructure> callStructures =
               _getInvocationCallStructures(member);
           for (CallStructure callStructure in callStructures) {
-            useSet.addAll(usage.invoke(callStructure));
-            if (usage.isFullyInvoked) {
+            useSet.addAll(usage.invoke(Accesses.dynamicAccess, callStructure));
+            if (!usage.hasPendingDynamicInvoke) {
               break;
             }
           }
         }
-        if (!usage.hasWrite && hasInvokedSetter(member)) {
-          useSet.addAll(usage.write());
+        if (usage.hasPendingDynamicWrite && _hasInvokedSetter(member)) {
+          useSet.addAll(usage.write(Accesses.dynamicAccess));
         }
-        if (!dryRun) {
-          if (!usage.hasPendingNormalUse) {
-            _instanceMembersByName[memberName]?.remove(usage);
+        if (!checkEnqueuerConsistency) {
+          if (!usage.hasPendingDynamicRead) {
+            _readableInstanceMembersByName[memberName]?.remove(usage);
           }
-          if (!usage.hasPendingClosurizationUse) {
-            _instanceFunctionsByName[memberName]?.remove(usage);
+          if (!usage.hasPendingDynamicInvoke) {
+            _invokableInstanceMembersByName[memberName]?.remove(usage);
           }
+          if (!usage.hasPendingDynamicWrite) {
+            _writableInstanceMembersByName[memberName]?.remove(usage);
+          }
+        }
+        if (checkEnqueuerConsistency && !original.dataEquals(usage)) {
+          _elementMap.reporter.internalError(
+              member,
+              'Unenqueued usage of $member: \n'
+              'before: $original\nafter : $usage');
         }
         memberUsed(usage.entity, useSet);
       }
-      if (dryRun && !original.dataEquals(usage)) {
-        _elementMap.reporter.internalError(member,
-            'Unenqueued usage of $member: before: $original, after: $usage');
-      }
     }
   }
 
@@ -1042,7 +952,7 @@
     // classes: if the superclass of these classes require RTI, then
     // they also need RTI, so that a constructor passes the type
     // variables to the super constructor.
-    forEachInstantiatedClass(addSubtypes);
+    getInstantiationMap().forEach(addSubtypes);
 
     return typesImplementedBySubclasses;
   }
@@ -1050,11 +960,11 @@
   Iterable<MemberEntity> computeAssignedInstanceMembers() {
     Set<MemberEntity> assignedInstanceMembers = new Set<MemberEntity>();
     for (MemberEntity instanceMember in _liveInstanceMembers) {
-      if (hasInvokedSetter(instanceMember)) {
+      if (_hasInvokedSetter(instanceMember)) {
         assignedInstanceMembers.add(instanceMember);
       }
     }
-    assignedInstanceMembers.addAll(fieldSetters);
+    assignedInstanceMembers.addAll(_fieldSetters);
     return assignedInstanceMembers;
   }
 
@@ -1093,22 +1003,6 @@
   }
 
   @override
-  Iterable<FunctionEntity> get genericMethods {
-    List<FunctionEntity> functions = <FunctionEntity>[];
-
-    void processMemberUse(Entity member, AbstractUsage memberUsage) {
-      if (member is FunctionEntity &&
-          memberUsage.hasUse &&
-          _elementEnvironment.getFunctionTypeVariables(member).isNotEmpty) {
-        functions.add(member);
-      }
-    }
-
-    _memberUsage.forEach(processMemberUse);
-    return functions;
-  }
-
-  @override
   KClosedWorld closeWorld(DiagnosticReporter reporter) {
     Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses =
         populateHierarchyNodes();
@@ -1132,6 +1026,17 @@
           "Member $member is processed but has not usage.");
     }
 
+    Set<InterfaceType> instantiatedTypes = new Set<InterfaceType>();
+    getInstantiationMap().forEach((_, InstantiationInfo info) {
+      if (info.instantiationMap != null) {
+        for (Set<Instance> instances in info.instantiationMap.values) {
+          for (Instance instance in instances) {
+            instantiatedTypes.add(instance.type);
+          }
+        }
+      }
+    });
+
     KClosedWorld closedWorld = new KClosedWorldImpl(_elementMap,
         options: _options,
         elementEnvironment: _elementEnvironment,
@@ -1141,7 +1046,6 @@
         interceptorData: _interceptorDataBuilder.close(),
         backendUsage: backendUsage,
         noSuchMethodData: _noSuchMethodRegistry.close(),
-        resolutionWorldBuilder: this,
         rtiNeedBuilder: _rtiNeedBuilder,
         fieldAnalysis: _allocatorAnalysis,
         implementedClasses: _implementedClasses,
@@ -1152,17 +1056,19 @@
         mixinUses: _classHierarchyBuilder.mixinUses,
         typesImplementedBySubclasses: typesImplementedBySubclasses,
         classHierarchy: _classHierarchyBuilder.close(),
-        annotationsData: _annotationsDataBuilder.close());
+        annotationsData: _annotationsDataBuilder.close(),
+        isChecks: _isChecks,
+        staticTypeArgumentDependencies: staticTypeArgumentDependencies,
+        dynamicTypeArgumentDependencies: dynamicTypeArgumentDependencies,
+        typeVariableTypeLiterals: typeVariableTypeLiterals,
+        genericLocalFunctions: _genericLocalFunctions,
+        closurizedMembersWithFreeTypeVariables:
+            _closurizedMembersWithFreeTypeVariables,
+        localFunctions: _localFunctions,
+        instantiatedTypes: instantiatedTypes);
     if (retainDataForTesting) {
       _closedWorldCache = closedWorld;
     }
     return closedWorld;
   }
-
-  @override
-  void forEachLocalFunction(void f(MemberEntity member, Local localFunction)) {
-    for (KLocalFunction local in localFunctions) {
-      f(local.memberContext, local);
-    }
-  }
 }
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index 2f70e16..20f8391 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -315,6 +315,15 @@
     return 'Selector($kind, $name, ${callStructure.structureToString()})';
   }
 
+  /// Returns the normalized version of this selector.
+  ///
+  /// A selector is normalized if its call structure is normalized.
+  // TODO(johnniwinther): Use normalized selectors as much as possible,
+  // especially where selectors are used in sets or as keys in maps.
+  Selector toNormalized() => callStructure.isNormalized
+      ? this
+      : new Selector(kind, memberName, callStructure.toNormalized());
+
   Selector toCallSelector() => new Selector.callClosureFrom(this);
 
   /// Returns the non-generic [Selector] corresponding to this selector.
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 01b0d07..5e124f3 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -20,6 +20,8 @@
 import '../constants/values.dart';
 import '../elements/types.dart';
 import '../elements/entities.dart';
+import '../inferrer/abstract_value_domain.dart';
+import '../serialization/serialization.dart';
 import '../js_model/closure.dart';
 import '../util/util.dart' show equalElements, Hashing;
 import 'call_structure.dart' show CallStructure;
@@ -36,9 +38,49 @@
 /// property and [receiverConstraint] defines the known constraint for the
 /// object on which the property is accessed.
 class DynamicUse {
-  final Selector selector;
+  static const String tag = 'dynamic-use';
 
-  DynamicUse(this.selector);
+  final Selector selector;
+  final Object receiverConstraint;
+  final List<DartType> _typeArguments;
+
+  DynamicUse(this.selector, this.receiverConstraint, this._typeArguments) {
+    assert(
+        selector.callStructure.typeArgumentCount ==
+            (_typeArguments?.length ?? 0),
+        "Type argument count mismatch. Selector has "
+        "${selector.callStructure.typeArgumentCount} but "
+        "${_typeArguments?.length ?? 0} were passed.");
+  }
+
+  factory DynamicUse.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    Selector selector = Selector.readFromDataSource(source);
+    bool hasConstraint = source.readBool();
+    Object receiverConstraint;
+    if (hasConstraint) {
+      receiverConstraint = source.readAbstractValue();
+    }
+    List<DartType> typeArguments = source.readDartTypes(emptyAsNull: true);
+    source.end(tag);
+    return new DynamicUse(selector, receiverConstraint, typeArguments);
+  }
+
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    selector.writeToDataSink(sink);
+    sink.writeBool(receiverConstraint != null);
+    if (receiverConstraint != null) {
+      if (receiverConstraint is AbstractValue) {
+        sink.writeAbstractValue(receiverConstraint);
+      } else {
+        throw new UnsupportedError(
+            "Unsupported receiver constraint: ${receiverConstraint}");
+      }
+    }
+    sink.writeDartTypes(_typeArguments, allowNull: true);
+    sink.end(tag);
+  }
 
   /// Short textual representation use for testing.
   String get shortText {
@@ -71,8 +113,6 @@
     return sb.toString();
   }
 
-  Object get receiverConstraint => null;
-
   DynamicUseKind get kind {
     if (selector.isGetter) {
       return DynamicUseKind.GET;
@@ -83,7 +123,7 @@
     }
   }
 
-  List<DartType> get typeArguments => const <DartType>[];
+  List<DartType> get typeArguments => _typeArguments ?? const <DartType>[];
 
   @override
   int get hashCode => Hashing.listHash(
@@ -99,67 +139,28 @@
   }
 
   @override
-  String toString() => '$selector,$receiverConstraint';
-}
-
-class GenericDynamicUse extends DynamicUse {
-  final List<DartType> _typeArguments;
-
-  GenericDynamicUse(Selector selector, [this._typeArguments])
-      : super(selector) {
-    assert(
-        selector.callStructure.typeArgumentCount ==
-            (_typeArguments?.length ?? 0),
-        "Type argument count mismatch. Selector has "
-        "${selector.callStructure.typeArgumentCount} but "
-        "${typeArguments?.length ?? 0} were passed.");
-  }
-
-  @override
-  List<DartType> get typeArguments => _typeArguments ?? const <DartType>[];
-}
-
-/// A dynamic use with a receiver constraint.
-///
-/// This is used in the codegen phase where receivers are constrained to a
-/// type mask or similar.
-class ConstrainedDynamicUse extends DynamicUse {
-  @override
-  final Object receiverConstraint;
-  final List<DartType> _typeArguments;
-
-  ConstrainedDynamicUse(
-      Selector selector, this.receiverConstraint, this._typeArguments)
-      : super(selector) {
-    assert(
-        selector.callStructure.typeArgumentCount ==
-            (_typeArguments?.length ?? 0),
-        "Type argument count mismatch. Selector has "
-        "${selector.callStructure.typeArgumentCount} but "
-        "${_typeArguments?.length ?? 0} were passed.");
-  }
-
-  @override
-  List<DartType> get typeArguments => _typeArguments ?? const <DartType>[];
+  String toString() => '$selector,$receiverConstraint,$typeArguments';
 }
 
 enum StaticUseKind {
   STATIC_TEAR_OFF,
   SUPER_TEAR_OFF,
   SUPER_FIELD_SET,
-  FIELD_GET,
-  FIELD_SET,
+  SUPER_GET,
+  SUPER_SETTER_SET,
+  SUPER_INVOKE,
+  INSTANCE_FIELD_GET,
+  INSTANCE_FIELD_SET,
   CLOSURE,
   CLOSURE_CALL,
   CALL_METHOD,
   CONSTRUCTOR_INVOKE,
   CONST_CONSTRUCTOR_INVOKE,
-  REDIRECTION,
   DIRECT_INVOKE,
   INLINING,
-  INVOKE,
-  GET,
-  SET,
+  STATIC_INVOKE,
+  STATIC_GET,
+  STATIC_SET,
   FIELD_INIT,
   FIELD_CONSTANT_INIT,
 }
@@ -168,6 +169,8 @@
 // TODO(johnniwinther): Create backend-specific implementations with better
 // invariants.
 class StaticUse {
+  static const String tag = 'static-use';
+
   final Entity element;
   final StaticUseKind kind;
   @override
@@ -176,31 +179,77 @@
   final CallStructure callStructure;
   final ImportEntity deferredImport;
   final ConstantValue constant;
+  final List<DartType> typeArguments;
 
   StaticUse.internal(Entity element, this.kind,
       {this.type,
       this.callStructure,
       this.deferredImport,
-      typeArgumentsHash: 0,
+      this.typeArguments,
       this.constant})
       : this.element = element,
         this.hashCode = Hashing.listHash([
           element,
           kind,
           type,
-          typeArgumentsHash,
+          Hashing.listHash(typeArguments),
           callStructure,
           deferredImport,
           constant
         ]);
 
+  bool _checkGenericInvariants() {
+    assert(
+        (callStructure?.typeArgumentCount ?? 0) == (typeArguments?.length ?? 0),
+        failedAt(
+            element,
+            "Type argument count mismatch. Call structure has "
+            "${callStructure?.typeArgumentCount ?? 0} but "
+            "${typeArguments?.length ?? 0} were passed in $this."));
+    return true;
+  }
+
+  factory StaticUse.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    MemberEntity element = source.readMember();
+    StaticUseKind kind = source.readEnum(StaticUseKind.values);
+    InterfaceType type = source.readDartType(allowNull: true);
+    CallStructure callStructure =
+        source.readValueOrNull(() => CallStructure.readFromDataSource(source));
+    ImportEntity deferredImport = source.readImportOrNull();
+    ConstantValue constant = source.readConstantOrNull();
+    List<DartType> typeArguments = source.readDartTypes(emptyAsNull: true);
+    source.end(tag);
+    return new StaticUse.internal(element, kind,
+        type: type,
+        callStructure: callStructure,
+        deferredImport: deferredImport,
+        constant: constant,
+        typeArguments: typeArguments);
+  }
+
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    assert(element is MemberEntity, "Unsupported entity: $element");
+    sink.writeMember(element);
+    sink.writeEnum(kind);
+    sink.writeDartType(type, allowNull: true);
+    sink.writeValueOrNull(
+        callStructure, (CallStructure c) => c.writeToDataSink(sink));
+    sink.writeImportOrNull(deferredImport);
+    sink.writeConstantOrNull(constant);
+    sink.writeDartTypes(typeArguments, allowNull: true);
+    sink.end(tag);
+  }
+
   /// Short textual representation use for testing.
   String get shortText {
     StringBuffer sb = new StringBuffer();
     switch (kind) {
-      case StaticUseKind.FIELD_SET:
+      case StaticUseKind.INSTANCE_FIELD_SET:
       case StaticUseKind.SUPER_FIELD_SET:
-      case StaticUseKind.SET:
+      case StaticUseKind.SUPER_SETTER_SET:
+      case StaticUseKind.STATIC_SET:
         sb.write('set:');
         break;
       case StaticUseKind.FIELD_INIT:
@@ -249,8 +298,6 @@
     return sb.toString();
   }
 
-  List<DartType> get typeArguments => null;
-
   /// Invocation of a static or top-level [element] with the given
   /// [callStructure].
   factory StaticUse.staticInvoke(
@@ -262,13 +309,20 @@
             element,
             "Static invoke element $element must be a top-level "
             "or static method."));
+    assert(element.isFunction,
+        failedAt(element, "Static get element $element must be a function."));
     assert(
         callStructure != null,
         failedAt(element,
             "Not CallStructure for static invocation of element $element."));
 
-    return new GenericStaticUse(element, StaticUseKind.INVOKE, callStructure,
-        typeArguments, deferredImport);
+    StaticUse staticUse = new StaticUse.internal(
+        element, StaticUseKind.STATIC_INVOKE,
+        callStructure: callStructure,
+        typeArguments: typeArguments,
+        deferredImport: deferredImport);
+    assert(staticUse._checkGenericInvariants());
+    return staticUse;
   }
 
   /// Closurization of a static or top-level function [element].
@@ -280,6 +334,8 @@
             element,
             "Static tear-off element $element must be a top-level "
             "or static method."));
+    assert(element.isFunction,
+        failedAt(element, "Static get element $element must be a function."));
     return new StaticUse.internal(element, StaticUseKind.STATIC_TEAR_OFF,
         deferredImport: deferredImport);
   }
@@ -292,12 +348,12 @@
         failedAt(
             element,
             "Static get element $element must be a top-level "
-            "or static method."));
+            "or static field or getter."));
     assert(
         element.isField || element.isGetter,
         failedAt(element,
             "Static get element $element must be a field or a getter."));
-    return new StaticUse.internal(element, StaticUseKind.GET,
+    return new StaticUse.internal(element, StaticUseKind.STATIC_GET,
         deferredImport: deferredImport);
   }
 
@@ -311,10 +367,10 @@
             "Static set element $element "
             "must be a top-level or static method."));
     assert(
-        element.isField || element.isSetter,
+        (element.isField && element.isAssignable) || element.isSetter,
         failedAt(element,
             "Static set element $element must be a field or a setter."));
-    return new StaticUse.internal(element, StaticUseKind.SET,
+    return new StaticUse.internal(element, StaticUseKind.STATIC_SET,
         deferredImport: deferredImport);
   }
 
@@ -344,8 +400,11 @@
         callStructure != null,
         failedAt(element,
             "Not CallStructure for super invocation of element $element."));
-    return new GenericStaticUse(
-        element, StaticUseKind.INVOKE, callStructure, typeArguments);
+    StaticUse staticUse = new StaticUse.internal(
+        element, StaticUseKind.SUPER_INVOKE,
+        callStructure: callStructure, typeArguments: typeArguments);
+    assert(staticUse._checkGenericInvariants());
+    return staticUse;
   }
 
   /// Read access of a super field or getter [element].
@@ -358,7 +417,7 @@
         element.isField || element.isGetter,
         failedAt(element,
             "Super get element $element must be a field or a getter."));
-    return new StaticUse.internal(element, StaticUseKind.GET);
+    return new StaticUse.internal(element, StaticUseKind.SUPER_GET);
   }
 
   /// Write access of a super field [element].
@@ -380,7 +439,7 @@
             element, "Super set element $element must be an instance method."));
     assert(element.isSetter,
         failedAt(element, "Super set element $element must be a setter."));
-    return new StaticUse.internal(element, StaticUseKind.SET);
+    return new StaticUse.internal(element, StaticUseKind.SUPER_SETTER_SET);
   }
 
   /// Closurization of a super method [element].
@@ -408,7 +467,7 @@
             element,
             "Not CallStructure for super constructor invocation of element "
             "$element."));
-    return new StaticUse.internal(element, StaticUseKind.INVOKE,
+    return new StaticUse.internal(element, StaticUseKind.STATIC_INVOKE,
         callStructure: callStructure);
   }
 
@@ -422,14 +481,14 @@
             element,
             "Not CallStructure for constructor body invocation of element "
             "$element."));
-    return new StaticUse.internal(element, StaticUseKind.INVOKE,
+    return new StaticUse.internal(element, StaticUseKind.STATIC_INVOKE,
         callStructure: callStructure);
   }
 
   /// Direct invocation of a generator (body) [element], as a static call or
   /// through a this or super constructor call.
   factory StaticUse.generatorBodyInvoke(FunctionEntity element) {
-    return new StaticUse.internal(element, StaticUseKind.INVOKE,
+    return new StaticUse.internal(element, StaticUseKind.STATIC_INVOKE,
         callStructure: CallStructure.NO_ARGS);
   }
 
@@ -442,8 +501,11 @@
             "Direct invoke element $element must be an instance member."));
     assert(element.isFunction,
         failedAt(element, "Direct invoke element $element must be a method."));
-    return new GenericStaticUse(
-        element, StaticUseKind.DIRECT_INVOKE, callStructure, typeArguments);
+    StaticUse staticUse = new StaticUse.internal(
+        element, StaticUseKind.DIRECT_INVOKE,
+        callStructure: callStructure, typeArguments: typeArguments);
+    assert(staticUse._checkGenericInvariants());
+    return staticUse;
   }
 
   /// Direct read access of a field or getter [element].
@@ -456,7 +518,7 @@
         element.isField || element.isGetter,
         failedAt(element,
             "Direct get element $element must be a field or a getter."));
-    return new StaticUse.internal(element, StaticUseKind.GET);
+    return new StaticUse.internal(element, StaticUseKind.STATIC_GET);
   }
 
   /// Direct write access of a field [element].
@@ -467,7 +529,7 @@
             "Direct set element $element must be an instance member."));
     assert(element.isField,
         failedAt(element, "Direct set element $element must be a field."));
-    return new StaticUse.internal(element, StaticUseKind.SET);
+    return new StaticUse.internal(element, StaticUseKind.STATIC_SET);
   }
 
   /// Constructor invocation of [element] with the given [callStructure].
@@ -483,7 +545,7 @@
             element,
             "Not CallStructure for constructor invocation of element "
             "$element."));
-    return new StaticUse.internal(element, StaticUseKind.INVOKE,
+    return new StaticUse.internal(element, StaticUseKind.STATIC_INVOKE,
         callStructure: callStructure);
   }
 
@@ -530,19 +592,6 @@
         deferredImport: deferredImport);
   }
 
-  /// Constructor redirection to [element] on [type].
-  factory StaticUse.constructorRedirect(
-      ConstructorEntity element, InterfaceType type) {
-    assert(type != null,
-        failedAt(element, "No type provided for constructor redirection."));
-    assert(
-        element.isConstructor,
-        failedAt(element,
-            "Constructor redirection element $element must be a constructor."));
-    return new StaticUse.internal(element, StaticUseKind.REDIRECTION,
-        type: type);
-  }
-
   /// Initialization of an instance field [element].
   factory StaticUse.fieldInit(FieldEntity element) {
     assert(
@@ -569,7 +618,7 @@
         element.isInstanceMember || element is JRecordField,
         failedAt(element,
             "Field init element $element must be an instance or boxed field."));
-    return new StaticUse.internal(element, StaticUseKind.FIELD_GET);
+    return new StaticUse.internal(element, StaticUseKind.INSTANCE_FIELD_GET);
   }
 
   /// Write access of an instance field or boxed field [element].
@@ -578,7 +627,7 @@
         element.isInstanceMember || element is JRecordField,
         failedAt(element,
             "Field init element $element must be an instance or boxed field."));
-    return new StaticUse.internal(element, StaticUseKind.FIELD_SET);
+    return new StaticUse.internal(element, StaticUseKind.INSTANCE_FIELD_SET);
   }
 
   /// Read of a local function [element].
@@ -590,8 +639,11 @@
   /// [callStructure] and [typeArguments].
   factory StaticUse.closureCall(Local element, CallStructure callStructure,
       List<DartType> typeArguments) {
-    return new GenericStaticUse(
-        element, StaticUseKind.CLOSURE_CALL, callStructure, typeArguments);
+    StaticUse staticUse = new StaticUse.internal(
+        element, StaticUseKind.CLOSURE_CALL,
+        callStructure: callStructure, typeArguments: typeArguments);
+    assert(staticUse._checkGenericInvariants());
+    return staticUse;
   }
 
   /// Read of a call [method] on a closureClass.
@@ -602,7 +654,7 @@
   /// Implicit method/constructor invocation of [element] created by the
   /// backend.
   factory StaticUse.implicitInvoke(FunctionEntity element) {
-    return new StaticUse.internal(element, StaticUseKind.INVOKE,
+    return new StaticUse.internal(element, StaticUseKind.STATIC_INVOKE,
         callStructure: element.parameterStructure.callStructure);
   }
 
@@ -616,7 +668,8 @@
   /// Inlining of [element].
   factory StaticUse.methodInlining(
       FunctionEntity element, List<DartType> typeArguments) {
-    return new GenericStaticUse.methodInlining(element, typeArguments);
+    return new StaticUse.internal(element, StaticUseKind.INLINING,
+        typeArguments: typeArguments);
   }
 
   @override
@@ -637,31 +690,6 @@
       'StaticUse($element,$kind,$type,$typeArguments,$callStructure)';
 }
 
-class GenericStaticUse extends StaticUse {
-  @override
-  final List<DartType> typeArguments;
-
-  GenericStaticUse(Entity entity, StaticUseKind kind,
-      CallStructure callStructure, this.typeArguments,
-      [ImportEntity deferredImport])
-      : super.internal(entity, kind,
-            callStructure: callStructure,
-            deferredImport: deferredImport,
-            typeArgumentsHash: Hashing.listHash(typeArguments)) {
-    assert(
-        (callStructure?.typeArgumentCount ?? 0) == (typeArguments?.length ?? 0),
-        failedAt(
-            element,
-            "Type argument count mismatch. Call structure has "
-            "${callStructure?.typeArgumentCount ?? 0} but "
-            "${typeArguments?.length ?? 0} were passed."));
-  }
-
-  GenericStaticUse.methodInlining(FunctionEntity entity, this.typeArguments)
-      : super.internal(entity, StaticUseKind.INLINING,
-            typeArgumentsHash: Hashing.listHash(typeArguments));
-}
-
 enum TypeUseKind {
   IS_CHECK,
   AS_CAST,
@@ -678,6 +706,8 @@
 
 /// Use of a [DartType].
 class TypeUse {
+  static const String tag = 'type-use';
+
   final DartType type;
   final TypeUseKind kind;
   @override
@@ -689,6 +719,23 @@
         this.kind = kind,
         this.hashCode = Hashing.objectsHash(type, kind, deferredImport);
 
+  factory TypeUse.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    DartType type = source.readDartType();
+    TypeUseKind kind = source.readEnum(TypeUseKind.values);
+    ImportEntity deferredImport = source.readImportOrNull();
+    source.end(tag);
+    return new TypeUse.internal(type, kind, deferredImport);
+  }
+
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartType(type);
+    sink.writeEnum(kind);
+    sink.writeImportOrNull(deferredImport);
+    sink.end(tag);
+  }
+
   /// Short textual representation use for testing.
   String get shortText {
     StringBuffer sb = new StringBuffer();
@@ -824,10 +871,25 @@
 
 /// Use of a [ConstantValue].
 class ConstantUse {
+  static const String tag = 'constant-use';
+
   final ConstantValue value;
 
   ConstantUse._(this.value);
 
+  factory ConstantUse.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    ConstantValue value = source.readConstant();
+    source.end(tag);
+    return new ConstantUse._(value);
+  }
+
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeConstant(value);
+    sink.end(tag);
+  }
+
   /// Short textual representation use for testing.
   String get shortText {
     return value.toDartText();
@@ -839,9 +901,12 @@
   /// Type constant used for registration of custom elements.
   ConstantUse.customElements(TypeConstantValue value) : this._(value);
 
-  /// Constant literal used on code.
+  /// Constant literal used in code.
   ConstantUse.literal(ConstantValue value) : this._(value);
 
+  /// Deferred constant used in code.
+  ConstantUse.deferred(DeferredGlobalConstantValue value) : this._(value);
+
   @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index a26e453..3a91904 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -217,74 +217,28 @@
   /// super-call.
   // TODO(johnniwinther): Improve semantic precision.
   Iterable<ClassEntity> get directlyInstantiatedClasses;
-
-  /// All types that are checked either through is, as or checked mode checks.
-  Iterable<DartType> get isChecks;
-
-  /// All directly instantiated types, that is, the types of
-  /// [directlyInstantiatedClasses].
-  // TODO(johnniwinther): Improve semantic precision.
-  Iterable<InterfaceType> get instantiatedTypes;
-
-  // TODO(johnniwinther): Clean up these getters.
-  /// Methods in instantiated classes that are potentially closurized.
-  Iterable<FunctionEntity> get closurizedMembers;
-
-  /// Static or top level methods that are closurized.
-  Iterable<FunctionEntity> get closurizedStatics;
-
-  /// Live generic instance methods.
-  Iterable<FunctionEntity> get genericInstanceMethods;
-
-  /// Live generic local functions.
-  Iterable<Local> get genericLocalFunctions;
-
-  /// Live generic methods.
-  Iterable<FunctionEntity> get genericMethods;
-
-  /// Live user-defined 'noSuchMethod' implementations.
-  Iterable<FunctionEntity> get userNoSuchMethods;
-
-  /// Type variables used as type literals.
-  Iterable<TypeVariableType> get typeVariableTypeLiterals;
-
-  /// Call [f] for each generic [function] with the type arguments passed
-  /// through static calls to [function].
-  void forEachStaticTypeArgument(
-      void f(Entity function, Set<DartType> typeArguments));
-
-  /// Call [f] for each generic [selector] with the type arguments passed
-  /// through dynamic calls to [selector].
-  void forEachDynamicTypeArgument(
-      void f(Selector selector, Set<DartType> typeArguments));
 }
 
 abstract class WorldBuilderBase {
-  final Map<Entity, Set<DartType>> _staticTypeArgumentDependencies =
+  final Map<Entity, Set<DartType>> staticTypeArgumentDependencies =
       <Entity, Set<DartType>>{};
 
-  final Map<Selector, Set<DartType>> _dynamicTypeArgumentDependencies =
+  final Map<Selector, Set<DartType>> dynamicTypeArgumentDependencies =
       <Selector, Set<DartType>>{};
 
-  /// Set of methods in instantiated classes that are potentially closurized.
-  final Set<FunctionEntity> closurizedMembers = new Set<FunctionEntity>();
-
-  /// Set of static or top level methods that are closurized.
-  final Set<FunctionEntity> closurizedStatics = new Set<FunctionEntity>();
-
   final Set<TypeVariableType> typeVariableTypeLiterals =
       new Set<TypeVariableType>();
 
   void _registerStaticTypeArgumentDependency(
       Entity element, List<DartType> typeArguments) {
-    _staticTypeArgumentDependencies.putIfAbsent(
+    staticTypeArgumentDependencies.putIfAbsent(
         element, () => new Set<DartType>())
       ..addAll(typeArguments);
   }
 
   void _registerDynamicTypeArgumentDependency(
       Selector selector, List<DartType> typeArguments) {
-    _dynamicTypeArgumentDependencies.putIfAbsent(
+    dynamicTypeArgumentDependencies.putIfAbsent(
         selector, () => new Set<DartType>())
       ..addAll(typeArguments);
   }
@@ -303,16 +257,6 @@
     _registerDynamicTypeArgumentDependency(selector, typeArguments);
   }
 
-  void forEachStaticTypeArgument(
-      void f(Entity function, Set<DartType> typeArguments)) {
-    _staticTypeArgumentDependencies.forEach(f);
-  }
-
-  void forEachDynamicTypeArgument(
-      void f(Selector selector, Set<DartType> typeArguments)) {
-    _dynamicTypeArgumentDependencies.forEach(f);
-  }
-
   void registerTypeVariableTypeLiteral(TypeVariableType typeVariable) {
     typeVariableTypeLiterals.add(typeVariable);
   }
diff --git a/pkg/compiler/lib/src/universe/world_impact.dart b/pkg/compiler/lib/src/universe/world_impact.dart
index cc9a92c..f3c8e21 100644
--- a/pkg/compiler/lib/src/universe/world_impact.dart
+++ b/pkg/compiler/lib/src/universe/world_impact.dart
@@ -82,6 +82,11 @@
   Set<TypeUse> _typeUses;
   Set<ConstantUse> _constantUses;
 
+  WorldImpactBuilderImpl();
+
+  WorldImpactBuilderImpl.internal(
+      this._dynamicUses, this._staticUses, this._typeUses, this._constantUses);
+
   @override
   bool get isEmpty =>
       _dynamicUses == null &&
diff --git a/pkg/compiler/lib/src/util/enumset.dart b/pkg/compiler/lib/src/util/enumset.dart
index 4872be1..8db885e 100644
--- a/pkg/compiler/lib/src/util/enumset.dart
+++ b/pkg/compiler/lib/src/util/enumset.dart
@@ -36,14 +36,16 @@
   /// value indices.
   void set value(int mask);
 
-  /// Adds [enumValue] to this set.
-  void add(E enumValue);
+  /// Adds [enumValue] to this set. Returns `true` if the set was changed by
+  /// this action.
+  bool add(E enumValue);
 
   /// Adds all enum values in [set] to this set.
   void addAll(EnumSet<E> set);
 
-  /// Removes [enumValue] from this set.
-  void remove(E enumValue);
+  /// Removes [enumValue] from this set. Returns `true` if the set was changed
+  /// by this action.
+  bool remove(E enumValue);
 
   /// Removes all enum values in [set] from this set. The set of removed values
   /// is returned.
@@ -149,8 +151,10 @@
   }
 
   @override
-  void add(E enumValue) {
+  bool add(E enumValue) {
+    int before = _value;
     _value |= 1 << (enumValue as dynamic).index;
+    return _value != before;
   }
 
   @override
@@ -159,8 +163,10 @@
   }
 
   @override
-  void remove(E enumValue) {
+  bool remove(E enumValue) {
+    int before = _value;
     _value &= ~(1 << (enumValue as dynamic).index);
+    return _value != before;
   }
 
   @override
@@ -201,7 +207,7 @@
   }
 
   @override
-  void add(E enumValue) {
+  bool add(E enumValue) {
     throw new UnsupportedError('EnumSet.add');
   }
 
@@ -212,16 +218,36 @@
 
   @override
   void clear() {
-    throw new UnsupportedError('EnumSet.clear');
+    if (isEmpty) {
+      // We allow this no-op operation on an immutable set to support using a
+      // constant empty set together with mutable sets where applicable.
+    } else {
+      throw new UnsupportedError('EnumSet.clear');
+    }
   }
 
   @override
-  void remove(E enumValue) {
+  bool remove(E enumValue) {
+    if (isEmpty) {
+      // We allow this no-op operation on an immutable set to support using a
+      // constant empty set together with mutable sets where applicable.
+      return false;
+    }
     throw new UnsupportedError('EnumSet.remove');
   }
 
   @override
   EnumSet<E> removeAll(EnumSet<E> set) {
+    if (isEmpty) {
+      // We allow this no-op operation on an immutable set to support using a
+      // constant empty set together with mutable sets where applicable.
+      return this;
+    }
+    if (set.isEmpty) {
+      // We allow this no-op operation on an immutable set to support using a
+      // constant empty set together with mutable sets where applicable.
+      return set.clone();
+    }
     throw new UnsupportedError('EnumSet.removeAll');
   }
 }
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 9b9e9e9..c592196 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -198,6 +198,10 @@
   /// Returns the single [MemberEntity] that matches a call to [selector] on the
   /// [receiver]. If multiple targets exist, `null` is returned.
   MemberEntity locateSingleMember(Selector selector, AbstractValue receiver);
+
+  /// Returns the set of read, write, and invocation accesses found on [member]
+  /// during the closed world computation.
+  MemberAccess getMemberAccess(MemberEntity member);
 }
 
 abstract class OpenWorld implements World {
@@ -225,7 +229,52 @@
       MemberEntity member, ClassEntity type, ClassRelation relation);
 }
 
-abstract class KClosedWorld {
+/// A [BuiltWorld] is an immutable result of a [WorldBuilder].
+abstract class BuiltWorld {
+  /// Calls [f] for each live generic method.
+  void forEachGenericMethod(void Function(FunctionEntity) f);
+
+  /// All types that are checked either through is, as or checked mode checks.
+  Iterable<DartType> get isChecks;
+
+  /// All directly instantiated types, that is, the types of
+  /// [directlyInstantiatedClasses].
+  // TODO(johnniwinther): Improve semantic precision.
+  Iterable<InterfaceType> get instantiatedTypes;
+
+  // TODO(johnniwinther): Clean up these getters.
+  /// Methods in instantiated classes that are potentially closurized.
+  Iterable<FunctionEntity> get closurizedMembers;
+
+  /// Static or top level methods that are closurized.
+  Iterable<FunctionEntity> get closurizedStatics;
+
+  /// Type variables used as type literals.
+  Iterable<TypeVariableType> get typeVariableTypeLiterals;
+
+  /// Live user-defined 'noSuchMethod' implementations.
+  Iterable<FunctionEntity> get userNoSuchMethods;
+
+  /// Calls [f] for each live generic instance methods.
+  void forEachGenericInstanceMethod(void Function(FunctionEntity) f);
+
+  /// Live generic local functions.
+  Iterable<Local> get genericLocalFunctions;
+
+  /// Call [f] for each generic [function] with the type arguments passed
+  /// through static calls to [function].
+  void forEachStaticTypeArgument(
+      void f(Entity function, Set<DartType> typeArguments));
+
+  /// Call [f] for each generic [selector] with the type arguments passed
+  /// through dynamic calls to [selector].
+  void forEachDynamicTypeArgument(
+      void f(Selector selector, Set<DartType> typeArguments));
+}
+
+// TODO(johnniwinther): Rename this to `ResolutionWorld` or `KWorld`?
+// The immutable result of the [ResolutionWorldBuilder].
+abstract class KClosedWorld implements BuiltWorld {
   DartTypes get dartTypes;
   KFieldAnalysis get fieldAnalysis;
   BackendUsage get backendUsage;
@@ -251,4 +300,20 @@
   NoSuchMethodData get noSuchMethodData;
 
   AnnotationsData get annotationsData;
+
+  /// Set of live closurized members whose signatures reference type variables.
+  ///
+  /// A closurized method is considered live if the enclosing class has been
+  /// instantiated.
+  Iterable<FunctionEntity> get closurizedMembersWithFreeTypeVariables;
+
+  /// Set of (live) local functions (closures).
+  ///
+  /// A live function is one whose enclosing member function has been enqueued.
+  Iterable<Local> get localFunctions;
+
+  /// Returns `true` if [member] has been marked as used (called, read, etc.) in
+  /// this world builder.
+  // TODO(johnniwinther): Maybe this should be part of [ClosedWorld] (instead).
+  bool isMemberUsed(MemberEntity member);
 }
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index b34280b..2dbf1fb 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -3,7 +3,7 @@
 name: compiler
 publish_to: none
 environment:
-  sdk: '>=2.2.0 <3.0.0'
+  sdk: '>=2.3.0 <3.0.0'
 
 # NOTE: `pub get / pub upgrade` are generally not needed when working on this
 # package. The `.packages` file in the repository root will be used by default.
diff --git a/pkg/compiler/tool/modular_dart2js.dart b/pkg/compiler/tool/modular_dart2js.dart
new file mode 100644
index 0000000..f8e15e3
--- /dev/null
+++ b/pkg/compiler/tool/modular_dart2js.dart
@@ -0,0 +1,180 @@
+// Copyright (c) 2019, 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:convert';
+import 'dart:io';
+import 'package:compiler/src/commandline_options.dart';
+
+main(List<String> args) async {
+  Stopwatch stopwatch = new Stopwatch();
+  String input;
+  String serializedInput;
+  String output = 'out.js';
+  List<String> arguments = [];
+  int start = 0;
+  int stop = 3;
+  int shards;
+  bool enableAssertions = false;
+  for (String arg in args) {
+    if (arg.startsWith('-')) {
+      if (arg.startsWith('--start=')) {
+        start = int.parse(arg.substring('--start='.length));
+      } else if (arg.startsWith('--stop=')) {
+        stop = int.parse(arg.substring('--stop='.length));
+      } else if (arg.startsWith('--shards=')) {
+        shards = int.parse(arg.substring('--shards='.length));
+      } else if (arg == '-ea' || arg == '--enable_asserts') {
+        enableAssertions = true;
+      } else if (arg.startsWith('--in=')) {
+        serializedInput = arg.substring('--in='.length);
+      } else if (arg.startsWith('-o')) {
+        output = arg.substring('-o'.length);
+      } else if (arg.startsWith('--out=')) {
+        output = arg.substring('--out='.length);
+      } else {
+        arguments.add(arg);
+      }
+    } else {
+      if (input != null) {
+        print("Multiple entrypoints provided: '${input}' and '${arg}'.");
+        exit(-1);
+      }
+      input = arg;
+    }
+  }
+
+  if (input == null) {
+    print("No entrypoint provided.");
+    exit(-1);
+  }
+
+  serializedInput ??= output;
+
+  String inputPrefix = serializedInput;
+  if (serializedInput.endsWith('.js')) {
+    inputPrefix = output.substring(0, output.length - '.js'.length);
+  }
+  String outputPrefix = output;
+  if (output.endsWith('.js')) {
+    outputPrefix = output.substring(0, output.length - '.js'.length);
+  }
+
+  List<String> baseOptions = ['--packages=${Platform.packageConfig}'];
+  if (enableAssertions) {
+    baseOptions.add('--enable_asserts');
+  }
+  baseOptions.add('package:compiler/src/dart2js.dart');
+  baseOptions.addAll(arguments);
+
+  String cfeOutput = '${inputPrefix}0.dill';
+  String dillOutput = '${inputPrefix}.dill';
+  String dataOutput = '${inputPrefix}.dill.data';
+  String codeOutput = '${outputPrefix}.code';
+  shards ??= 2;
+
+  stopwatch.start();
+  if (start <= 0 && stop >= 0) {
+    await subProcess(
+        baseOptions, [input, Flags.cfeOnly, '--out=$cfeOutput'], '0:\t');
+  }
+  if (start <= 1 && stop >= 1) {
+    await subProcess(
+        baseOptions,
+        [cfeOutput, '--out=$dillOutput', '${Flags.writeData}=${dataOutput}'],
+        '1:\t');
+  }
+  if (shards <= 1) {
+    await subProcess(
+        baseOptions,
+        [dillOutput, '${Flags.readData}=${dataOutput}', '--out=${output}'],
+        '3:\t');
+  } else {
+    if (start <= 2 && stop >= 2) {
+      List<List<String>> additionalArguments = [];
+      List<String> outputPrefixes = [];
+      for (int shard = 0; shard < shards; shard++) {
+        additionalArguments.add([
+          dillOutput,
+          '${Flags.readData}=${dataOutput}',
+          '${Flags.codegenShard}=$shard',
+          '${Flags.codegenShards}=$shards',
+          '${Flags.writeCodegen}=${codeOutput}'
+        ]);
+        outputPrefixes.add('2:${shard + 1}/$shards\t');
+      }
+
+      Stopwatch subwatch = new Stopwatch();
+      subwatch.start();
+      await Future.wait(new List<Future>.generate(shards, (int shard) {
+        return subProcess(
+            baseOptions, additionalArguments[shard], outputPrefixes[shard]);
+      }));
+      subwatch.stop();
+      print('2:\tTotal time: ${_formatMs(subwatch.elapsedMilliseconds)}');
+    }
+    if (start <= 3 && stop >= 3) {
+      await subProcess(
+          baseOptions,
+          [
+            dillOutput,
+            '${Flags.readData}=${dataOutput}',
+            '${Flags.readCodegen}=${codeOutput}',
+            '${Flags.codegenShards}=$shards',
+            '--out=${output}'
+          ],
+          '3:\t');
+    }
+  }
+  stopwatch.stop();
+  print('Total time: ${_formatMs(stopwatch.elapsedMilliseconds)}');
+}
+
+Future subProcess(List<String> baseOptions, List<String> additionalOptions,
+    String outputPrefix) async {
+  List<String> options = []..addAll(baseOptions)..addAll(additionalOptions);
+  print(
+      '${outputPrefix}Command: ${Platform.resolvedExecutable} ${options.join(' ')}');
+  Process process = await Process.start(Platform.resolvedExecutable, options,
+      runInShell: true);
+  _Prefixer stdoutPrefixer = new _Prefixer(outputPrefix, stdout);
+  _Prefixer stderrOutputter = new _Prefixer(outputPrefix, stderr);
+  process.stdout.transform(utf8.decoder).listen(stdoutPrefixer);
+  process.stderr.transform(utf8.decoder).listen(stderrOutputter);
+
+  int exitCode = await process.exitCode;
+  if (exitCode != 0) {
+    exit(exitCode);
+  }
+}
+
+class _Prefixer {
+  final String _prefix;
+  final Stdout _stdout;
+  bool _atNewLine = true;
+
+  _Prefixer(this._prefix, this._stdout);
+
+  void call(String text) {
+    int index = 0;
+    while (index < text.length) {
+      if (_atNewLine) {
+        _stdout.write(_prefix);
+        _atNewLine = false;
+      }
+      int pos = text.indexOf('\n', index);
+      if (pos != -1) {
+        _stdout.write(text.substring(index, pos + 1));
+        _atNewLine = true;
+        index = pos + 1;
+      } else {
+        _stdout.write(text.substring(index));
+        index = text.length;
+      }
+    }
+  }
+}
+
+String _formatMs(int ms) {
+  return (ms / 1000).toStringAsFixed(3) + 's';
+}
diff --git a/pkg/compiler/tool/modular_test_suite.dart b/pkg/compiler/tool/modular_test_suite.dart
new file mode 100644
index 0000000..67c5bf0
--- /dev/null
+++ b/pkg/compiler/tool/modular_test_suite.dart
@@ -0,0 +1,442 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Test the modular compilation pipeline of dart2js.
+///
+/// This is a shell that runs multiple tests, one per folder under `data/`.
+import 'dart:io';
+
+import 'package:compiler/src/commandline_options.dart';
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+    show computePlatformBinariesLocation;
+import 'package:modular_test/src/io_pipeline.dart';
+import 'package:modular_test/src/pipeline.dart';
+import 'package:modular_test/src/suite.dart';
+import 'package:modular_test/src/runner.dart';
+
+Uri sdkRoot = Platform.script.resolve("../../../");
+Options _options;
+String _dart2jsScript;
+String _kernelWorkerScript;
+main(List<String> args) async {
+  _options = Options.parse(args);
+  await _resolveScripts();
+  await runSuite(
+      sdkRoot.resolve('tests/modular/'),
+      'tests/modular',
+      _options,
+      new IOPipeline([
+        SourceToDillStep(),
+        GlobalAnalysisStep(),
+        Dart2jsCodegenStep(codeId0),
+        Dart2jsCodegenStep(codeId1),
+        Dart2jsEmissionStep(),
+        RunD8(),
+      ], cacheSharedModules: true));
+}
+
+const dillId = const DataId("dill");
+const updatedDillId = const DataId("udill");
+const globalDataId = const DataId("gdata");
+const codeId = const ShardsDataId("code", 2);
+const codeId0 = const ShardDataId(codeId, 0);
+const codeId1 = const ShardDataId(codeId, 1);
+const jsId = const DataId("js");
+const txtId = const DataId("txt");
+
+// Step that compiles sources in a module to a .dill file.
+class SourceToDillStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [dillId];
+
+  @override
+  bool get needsSources => true;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [dillId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [];
+
+  @override
+  bool get onlyOnMain => false;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: source-to-dill on $module");
+
+    // We use non file-URI schemes for representeing source locations in a
+    // root-agnostic way. This allows us to refer to file across modules and
+    // across steps without exposing the underlying temporary folders that are
+    // created by the framework. In build systems like bazel this is especially
+    // important because each step may be run on a different machine.
+    //
+    // Files in packages are defined in terms of `package:` URIs, while
+    // non-package URIs are defined using the `dart-dev-app` scheme.
+    String rootScheme = module.isSdk ? 'dart-dev-sdk' : 'dev-dart-app';
+    String sourceToImportUri(Uri relativeUri) {
+      if (module.isPackage) {
+        var basePath = module.packageBase.path;
+        var packageRelativePath = basePath == "./"
+            ? relativeUri.path
+            : relativeUri.path.substring(basePath.length);
+        return 'package:${module.name}/$packageRelativePath';
+      } else {
+        return '$rootScheme:/$relativeUri';
+      }
+    }
+
+    // We create a .packages file which defines the location of this module if
+    // it is a package.  The CFE requires that if a `package:` URI of a
+    // dependency is used in an import, then we need that package entry in the
+    // .packages file. However, after it checks that the definition exists, the
+    // CFE will not actually use the resolved URI if a library for the import
+    // URI is already found in one of the provided .dill files of the
+    // dependencies. For that reason, and to ensure that a step only has access
+    // to the files provided in a module, we generate a .packages with invalid
+    // folders for other packages.
+    // TODO(sigmund): follow up with the CFE to see if we can remove the need
+    // for the .packages entry altogether if they won't need to read the
+    // sources.
+    var packagesContents = new StringBuffer();
+    if (module.isPackage) {
+      packagesContents.write('${module.name}:${module.packageBase}\n');
+    }
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    for (Module dependency in transitiveDependencies) {
+      if (dependency.isPackage) {
+        packagesContents.write('${dependency.name}:unused\n');
+      }
+    }
+
+    await File.fromUri(root.resolve('.packages'))
+        .writeAsString('$packagesContents');
+
+    List<String> sources;
+    List<String> extraArgs;
+    if (module.isSdk) {
+      // When no flags are passed, we can skip compilation and reuse the
+      // platform.dill created by build.py.
+      if (flags.isEmpty) {
+        var platform =
+            computePlatformBinariesLocation().resolve("dart2js_platform.dill");
+        var destination = root.resolveUri(toUri(module, dillId));
+        if (_options.verbose) {
+          print('command:\ncp $platform $destination');
+        }
+        await File.fromUri(platform).copy(destination.toFilePath());
+        return;
+      }
+      sources = ['dart:core'];
+      extraArgs = ['--libraries-file', '$rootScheme:///sdk/lib/libraries.json'];
+      assert(transitiveDependencies.isEmpty);
+    } else {
+      sources = module.sources.map(sourceToImportUri).toList();
+      extraArgs = ['--packages-file', '$rootScheme:/.packages'];
+    }
+
+    List<String> args = [
+      _kernelWorkerScript,
+      '--no-summary-only',
+      '--target',
+      'dart2js',
+      '--multi-root',
+      '$root',
+      '--multi-root-scheme',
+      rootScheme,
+      ...extraArgs,
+      '--output',
+      '${toUri(module, dillId)}',
+      ...(transitiveDependencies
+          .expand((m) => ['--input-linked', '${toUri(m, dillId)}'])),
+      ...(sources.expand((String uri) => ['--source', uri])),
+      ...(flags.expand((String flag) => ['--enable-experiment', flag])),
+    ];
+
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: source-to-dill on $module");
+  }
+}
+
+// Step that invokes the dart2js global analysis on the main module by providing
+// the .dill files of all transitive modules as inputs.
+class GlobalAnalysisStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [globalDataId, updatedDillId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [dillId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [dillId];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: dart2js global analysis on $module");
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    Iterable<String> dillDependencies =
+        transitiveDependencies.map((m) => '${toUri(m, dillId)}');
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      _dart2jsScript,
+      // TODO(sigmund): remove this dependency on libraries.json
+      if (_options.useSdk)
+        '--libraries-spec=$_librarySpecForSnapshot',
+      '${toUri(module, dillId)}',
+      for (String flag in flags) '--enable-experiment=$flag',
+      '${Flags.dillDependencies}=${dillDependencies.join(',')}',
+      '${Flags.writeData}=${toUri(module, globalDataId)}',
+      '--out=${toUri(module, updatedDillId)}',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose)
+      print("\ncached step: dart2js global analysis on $module");
+  }
+}
+
+// Step that invokes the dart2js code generation on the main module given the
+// results of the global analysis step and produces one shard of the codegen
+// output.
+class Dart2jsCodegenStep implements IOModularStep {
+  final ShardDataId codeId;
+
+  Dart2jsCodegenStep(this.codeId);
+
+  @override
+  List<DataId> get resultData => [codeId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [updatedDillId, globalDataId];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: dart2js backend on $module");
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      _dart2jsScript,
+      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
+      '${toUri(module, updatedDillId)}',
+      for (String flag in flags) '--enable-experiment=$flag',
+      '${Flags.readData}=${toUri(module, globalDataId)}',
+      '${Flags.writeCodegen}=${toUri(module, codeId.dataId)}',
+      '${Flags.codegenShard}=${codeId.shard}',
+      '${Flags.codegenShards}=${codeId.dataId.shards}',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("cached step: dart2js backend on $module");
+  }
+}
+
+// Step that invokes the dart2js codegen enqueuer and emitter on the main module
+// given the results of the global analysis step and codegen shards.
+class Dart2jsEmissionStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [jsId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [];
+
+  @override
+  List<DataId> get moduleDataNeeded =>
+      const [updatedDillId, globalDataId, codeId0, codeId1];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("step: dart2js backend on $module");
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      _dart2jsScript,
+      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
+      '${toUri(module, updatedDillId)}',
+      for (String flag in flags) '${Flags.enableLanguageExperiments}=$flag',
+      '${Flags.readData}=${toUri(module, globalDataId)}',
+      '${Flags.readCodegen}=${toUri(module, codeId)}',
+      '${Flags.codegenShards}=${codeId.shards}',
+      '--out=${toUri(module, jsId)}',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: dart2js backend on $module");
+  }
+}
+
+/// Step that runs the output of dart2js in d8 and saves the output.
+class RunD8 implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [txtId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [jsId];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: d8 on $module");
+    List<String> d8Args = [
+      sdkRoot
+          .resolve('sdk/lib/_internal/js_runtime/lib/preambles/d8.js')
+          .toFilePath(),
+      root.resolveUri(toUri(module, jsId)).toFilePath(),
+    ];
+    var result = await _runProcess(
+        sdkRoot.resolve(_d8executable).toFilePath(), d8Args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+
+    await File.fromUri(root.resolveUri(toUri(module, txtId)))
+        .writeAsString(result.stdout);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: d8 on $module");
+  }
+}
+
+void _checkExitCode(ProcessResult result, IOModularStep step, Module module) {
+  if (result.exitCode != 0 || _options.verbose) {
+    stdout.write(result.stdout);
+    stderr.write(result.stderr);
+  }
+  if (result.exitCode != 0) {
+    throw "${step.runtimeType} failed on $module:\n\n"
+        "stdout:\n${result.stdout}\n\n"
+        "stderr:\n${result.stderr}";
+  }
+}
+
+Future<ProcessResult> _runProcess(
+    String command, List<String> arguments, String workingDirectory) {
+  if (_options.verbose) {
+    print('command:\n$command ${arguments.join(' ')} from $workingDirectory');
+  }
+  return Process.run(command, arguments, workingDirectory: workingDirectory);
+}
+
+String get _d8executable {
+  if (Platform.isWindows) {
+    return 'third_party/d8/windows/d8.exe';
+  } else if (Platform.isLinux) {
+    return 'third_party/d8/linux/d8';
+  } else if (Platform.isMacOS) {
+    return 'third_party/d8/macos/d8';
+  }
+  throw new UnsupportedError('Unsupported platform.');
+}
+
+class ShardsDataId implements DataId {
+  @override
+  final String name;
+  final int shards;
+
+  const ShardsDataId(this.name, this.shards);
+
+  @override
+  String toString() => name;
+}
+
+class ShardDataId implements DataId {
+  final ShardsDataId dataId;
+  final int _shard;
+
+  const ShardDataId(this.dataId, this._shard);
+
+  int get shard {
+    assert(0 <= _shard && _shard < dataId.shards);
+    return _shard;
+  }
+
+  @override
+  String get name => '${dataId.name}${shard}';
+
+  @override
+  String toString() => name;
+}
+
+Future<void> _resolveScripts() async {
+  Future<String> resolve(
+      String sourceUriOrPath, String relativeSnapshotPath) async {
+    Uri sourceUri = sdkRoot.resolve(sourceUriOrPath);
+    String result =
+        sourceUri.scheme == 'file' ? sourceUri.toFilePath() : sourceUriOrPath;
+    if (_options.useSdk) {
+      String snapshot = Uri.file(Platform.resolvedExecutable)
+          .resolve(relativeSnapshotPath)
+          .toFilePath();
+      if (await File(snapshot).exists()) {
+        return snapshot;
+      }
+    }
+    return result;
+  }
+
+  _dart2jsScript = await resolve(
+      'package:compiler/src/dart2js.dart', 'snapshots/dart2js.dart.snapshot');
+  _kernelWorkerScript = await resolve('utils/bazel/kernel_worker.dart',
+      'snapshots/kernel_worker.dart.snapshot');
+}
+
+String _librarySpecForSnapshot = Uri.file(Platform.resolvedExecutable)
+    .resolve('../lib/libraries.json')
+    .toFilePath();
diff --git a/pkg/dart_internal/pubspec.yaml b/pkg/dart_internal/pubspec.yaml
index da61ece..9a15238 100644
--- a/pkg/dart_internal/pubspec.yaml
+++ b/pkg/dart_internal/pubspec.yaml
@@ -1,5 +1,5 @@
 name: dart_internal
-version: 0.1.3
+version: 0.1.4
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 description: >
@@ -16,4 +16,4 @@
 environment:
   # Restrict the upper bound so that we can remove support for this in a later
   # version of the SDK without it being a breaking change.
-  sdk: ">=2.0.0-dev.12.0 <2.3.0"
+  sdk: ">=2.0.0-dev.12.0 <2.4.0"
diff --git a/pkg/dartfix/analysis_options.yaml b/pkg/dartfix/analysis_options.yaml
index e36185e..309f5ca 100644
--- a/pkg/dartfix/analysis_options.yaml
+++ b/pkg/dartfix/analysis_options.yaml
@@ -1,6 +1,7 @@
+include: package:pedantic/analysis_options.yaml
+
 linter:
   rules:
-    - empty_constructor_bodies
+    - directives_ordering
     - empty_statements
     - unnecessary_brace_in_string_interps
-    - valid_regexps
diff --git a/pkg/dartfix/bin/dartfix.dart b/pkg/dartfix/bin/dartfix.dart
new file mode 100644
index 0000000..7df5fc4
--- /dev/null
+++ b/pkg/dartfix/bin/dartfix.dart
@@ -0,0 +1,14 @@
+#!/usr/bin/env dart
+// Copyright (c) 2018, 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:dartfix/src/driver.dart';
+
+/// The entry point for dartfix.
+void main(List<String> args) async {
+  Driver starter = new Driver();
+
+  // Wait for the starter to complete.
+  await starter.start(args);
+}
diff --git a/pkg/dartfix/bin/fix.dart b/pkg/dartfix/bin/fix.dart
deleted file mode 100644
index 0e2a489..0000000
--- a/pkg/dartfix/bin/fix.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env dart
-// Copyright (c) 2018, 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:dartfix/src/driver.dart';
-
-/// The entry point for dartfix.
-main(List<String> args) async {
-  Driver starter = new Driver();
-
-  // Wait for the starter to complete.
-  await starter.start(args);
-}
diff --git a/pkg/dartfix/lib/listener/recording_listener.dart b/pkg/dartfix/lib/listener/recording_listener.dart
index 7ac4a12..db0dcf1 100644
--- a/pkg/dartfix/lib/listener/recording_listener.dart
+++ b/pkg/dartfix/lib/listener/recording_listener.dart
@@ -2,8 +2,8 @@
 // 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:analysis_server_client/server.dart';
 import 'package:analysis_server_client/listener/server_listener.dart';
+import 'package:analysis_server_client/server.dart';
 import 'package:dartfix/listener/bad_message_listener.dart';
 import 'package:dartfix/listener/timed_listener.dart';
 
diff --git a/pkg/dartfix/lib/src/driver.dart b/pkg/dartfix/lib/src/driver.dart
index 42bec0e..d999d83 100644
--- a/pkg/dartfix/lib/src/driver.dart
+++ b/pkg/dartfix/lib/src/driver.dart
@@ -31,9 +31,12 @@
 
   Ansi get ansi => logger.ansi;
 
-  Future start(List<String> args,
-      {Context testContext, Logger testLogger}) async {
-    final Options options = Options.parse(args);
+  Future start(
+    List<String> args, {
+    Context testContext,
+    Logger testLogger,
+  }) async {
+    final Options options = Options.parse(args, testContext, testLogger);
 
     force = options.force;
     overwrite = options.overwrite;
@@ -43,23 +46,44 @@
     server = new Server(listener: new _Listener(logger));
     handler = new _Handler(this);
 
+    // Start showing progress before we start the analysis server.
+    Progress progress;
+    if (options.showHelp) {
+      progress = logger.progress('${ansi.emphasized('Listing fixes')}');
+    } else {
+      progress = logger.progress('${ansi.emphasized('Calculating fixes')}');
+    }
+
     if (!await startServer(options)) {
       context.exit(15);
     }
-    try {
-      if (checkSupported(options)) {
-        if (options.listFixes) {
-          await showListOfFixes();
-        } else {
-          final progress = await setupAnalysis(options);
-          result = await requestFixes(options, progress);
-        }
-      }
-    } finally {
+
+    if (!checkSupported(options)) {
       await server.stop();
+      context.exit(1);
     }
-    if (result != null) {
-      applyFixes();
+
+    if (options.showHelp) {
+      try {
+        await showListOfFixes(progress: progress);
+      } finally {
+        await server.stop();
+      }
+      context.exit(0);
+    }
+
+    Future serverStopped;
+    try {
+      await setupFixesAnalysis(options);
+      result = await requestFixes(options, progress: progress);
+      serverStopped = server.stop();
+      await applyFixes();
+      await serverStopped;
+    } finally {
+      // If we didn't already try to stop the server, then stop it now.
+      if (serverStopped == null) {
+        await server.stop();
+      }
     }
   }
 
@@ -80,7 +104,7 @@
       serverPath: serverPath,
     );
     server.listenToOutput(notificationProcessor: handler.handleEvent);
-    return handler.serverConnected(timeLimit: const Duration(seconds: 15));
+    return handler.serverConnected(timeLimit: const Duration(seconds: 30));
   }
 
   /// Check if the specified options is supported by the version of analysis
@@ -98,14 +122,13 @@
       unsupportedOption(includeOption);
       return false;
     }
-    if (options.listFixes) {
-      unsupportedOption(listOption);
-      return false;
-    }
     if (options.requiredFixes) {
       unsupportedOption(requiredOption);
       return false;
     }
+    if (options.showHelp) {
+      return false;
+    }
     return true;
   }
 
@@ -116,8 +139,10 @@
 Please upgrade to a newer version of the Dart SDK to use this option.''');
   }
 
-  Future<Progress> setupAnalysis(Options options) async {
-    final progress = logger.progress('${ansi.emphasized('Calculating fixes')}');
+  Future<Progress> setupFixesAnalysis(
+    Options options, {
+    Progress progress,
+  }) async {
     logger.trace('');
     logger.trace('Setup analysis');
     await server.send(SERVER_REQUEST_SET_SUBSCRIPTIONS,
@@ -132,7 +157,9 @@
   }
 
   Future<EditDartfixResult> requestFixes(
-      Options options, Progress progress) async {
+    Options options, {
+    Progress progress,
+  }) async {
     logger.trace('Requesting fixes');
     Future isAnalysisComplete = handler.analysisComplete();
 
@@ -232,34 +259,42 @@
     return filePath;
   }
 
-  showListOfFixes() async {
-    final progress =
-        logger.progress('${ansi.emphasized('Getting list of fixes')}');
-    logger.trace('');
+  Future<EditGetDartfixInfoResult> showListOfFixes({Progress progress}) async {
     Map<String, dynamic> json = await server.send(
         EDIT_REQUEST_GET_DARTFIX_INFO, new EditGetDartfixInfoParams().toJson());
-
-    progress.finish(showTiming: true);
+    progress?.finish(showTiming: true);
     ResponseDecoder decoder = new ResponseDecoder(null);
     final result = EditGetDartfixInfoResult.fromJson(decoder, 'result', json);
 
     final fixes = new List<DartFix>.from(result.fixes)
       ..sort((f1, f2) => f1.name.compareTo(f2.name));
 
-    for (DartFix fix in fixes) {
-      String line = fix.name;
-      if (fix.isRequired == true) {
-        line = '$line (required)';
-      }
-      logger.stdout('');
-      logger.stdout(line);
-      if (fix.description != null) {
-        for (String line in indentAndWrapDescription(fix.description)) {
-          logger.stdout(line);
-        }
+    logger.stdout('''
+
+These fixes are automatically applied unless at least one
+--$includeOption option is specified and --$requiredOption is not specified.
+They may be individually disabled using --$excludeOption.''');
+
+    fixes.where((fix) => fix.isRequired).forEach(showFix);
+
+    logger.stdout('''
+
+These fixes are NOT automatically applied, but may be enabled using --$includeOption.''');
+
+    fixes.where((fix) => !fix.isRequired).forEach(showFix);
+
+    return result;
+  }
+
+  void showFix(DartFix fix) {
+    logger.stdout('''
+
+* ${fix.name}''');
+    if (fix.description != null) {
+      for (String line in indentAndWrapDescription(fix.description)) {
+        logger.stdout(line);
       }
     }
-    return result;
   }
 
   List<String> indentAndWrapDescription(String description) =>
diff --git a/pkg/dartfix/lib/src/options.dart b/pkg/dartfix/lib/src/options.dart
index a9af28e..a4d8923 100644
--- a/pkg/dartfix/lib/src/options.dart
+++ b/pkg/dartfix/lib/src/options.dart
@@ -4,9 +4,9 @@
 
 import 'dart:io';
 
-import 'package:dartfix/src/context.dart';
 import 'package:args/args.dart';
 import 'package:cli_util/cli_logging.dart';
+import 'package:dartfix/src/context.dart';
 import 'package:path/path.dart' as path;
 
 /// Command line options for `dartfix`.
@@ -22,12 +22,12 @@
   final List<String> excludeFixes;
 
   final bool force;
-  final bool listFixes;
+  final bool showHelp;
   final bool overwrite;
   final bool useColor;
   final bool verbose;
 
-  static Options parse(List<String> args, {Context context, Logger logger}) {
+  static Options parse(List<String> args, Context context, Logger logger) {
     final parser = new ArgParser(allowTrailingOptions: true)
       ..addSeparator('Choosing fixes to be applied:')
       ..addMultiOption(includeOption,
@@ -39,11 +39,6 @@
           help: 'Apply required fixes.',
           defaultsTo: false,
           negatable: false)
-      ..addFlag(listOption,
-          abbr: 'l',
-          help: 'Display a list of fixes that can be applied.',
-          defaultsTo: false,
-          negatable: false)
       ..addSeparator('Modifying files:')
       ..addFlag(overwriteOption,
           abbr: 'w',
@@ -55,10 +50,7 @@
           help: 'Overwrite files even if there are errors.',
           defaultsTo: false,
           negatable: false)
-      ..addSeparator('Miscelaneous:')
-      ..addFlag(_colorOption,
-          help: 'Use ansi colors when printing messages.',
-          defaultsTo: Ansi.terminalSupportsAnsi)
+      ..addSeparator('Miscellaneous:')
       ..addFlag(_helpOption,
           abbr: 'h',
           help: 'Display this help message.',
@@ -68,7 +60,10 @@
           abbr: 'v',
           defaultsTo: false,
           help: 'Verbose output.',
-          negatable: false);
+          negatable: false)
+      ..addFlag(_colorOption,
+          help: 'Use ansi colors when printing messages.',
+          defaultsTo: Ansi.terminalSupportsAnsi);
 
     context ??= new Context();
 
@@ -78,6 +73,7 @@
     } on FormatException catch (e) {
       logger ??= new Logger.standard(ansi: new Ansi(Ansi.terminalSupportsAnsi));
       logger.stderr(e.message);
+      logger.stderr('\n');
       _showUsage(parser, logger);
       context.exit(15);
     }
@@ -98,13 +94,9 @@
     }
     options.logger = logger;
 
-    if (results[_helpOption] as bool) {
-      _showUsage(parser, logger);
-      context.exit(1);
-    }
-
-    if (options.listFixes) {
-      _showUsage(parser, logger, showListHint: false);
+    // For '--help', we short circuit the logic to validate the sdk and project.
+    if (options.showHelp) {
+      _showUsage(parser, logger, showHelpHint: false);
       return options;
     }
 
@@ -112,19 +104,17 @@
     String sdkPath = options.sdkPath;
     if (sdkPath == null) {
       logger.stderr('No Dart SDK found.');
-      _showUsage(parser, logger);
       context.exit(15);
     }
+
     if (!context.exists(sdkPath)) {
       logger.stderr('Invalid Dart SDK path: $sdkPath');
-      _showUsage(parser, logger);
       context.exit(15);
     }
 
     // Check for files and/or directories to analyze.
     if (options.targets == null || options.targets.isEmpty) {
       logger.stderr('Expected at least one file or directory to analyze.');
-      _showUsage(parser, logger);
       context.exit(15);
     }
 
@@ -138,7 +128,6 @@
         } else {
           logger.stderr('Expected directory, but found: $target');
         }
-        _showUsage(parser, logger);
         context.exit(15);
       }
     }
@@ -159,10 +148,10 @@
             (results[includeOption] as List ?? []).cast<String>().toList(),
         excludeFixes =
             (results[excludeOption] as List ?? []).cast<String>().toList(),
-        listFixes = results[listOption] as bool,
         overwrite = results[overwriteOption] as bool,
         requiredFixes = results[requiredOption] as bool,
         sdkPath = _getSdkPath(),
+        showHelp = results[_helpOption] as bool || results.arguments.isEmpty,
         targets = results.rest,
         useColor = results.wasParsed(_colorOption)
             ? results[_colorOption] as bool
@@ -183,21 +172,18 @@
   }
 
   static _showUsage(ArgParser parser, Logger logger,
-      {bool showListHint = true}) {
-    logger.stderr('Usage: $_binaryName [options...] <directory paths>');
-    logger.stderr('');
-    logger.stderr(parser.usage);
-    logger.stderr('''
-
-If neither --$includeOption nor --$requiredOption is specified, then all fixes
-will be applied. Any fixes specified using --$excludeOption will not be applied
-regardless of whether they are required or specifed using --$includeOption.''');
-    if (showListHint) {
-      logger.stderr('''
-
-Use --list to display the fixes that can be specified
-using either --$includeOption or --$excludeOption.''');
-    }
+      {bool showHelpHint = true}) {
+    Function(String message) out = showHelpHint ? logger.stderr : logger.stdout;
+    // show help on stdout when showHelp is true and showHelpHint is false
+    out('''
+Usage: $_binaryName [options...] <directory paths>
+''');
+    out(parser.usage);
+    out(showHelpHint
+        ? '''
+Use --$_helpOption to display the fixes that can be specified using either
+--$includeOption or --$excludeOption.'''
+        : '');
   }
 }
 
@@ -211,5 +197,4 @@
 // options only supported by server 1.22.2 and greater
 const excludeOption = 'exclude';
 const includeOption = 'include';
-const listOption = 'list';
 const requiredOption = 'required';
diff --git a/pkg/dartfix/pubspec.yaml b/pkg/dartfix/pubspec.yaml
index 88c9dfc..8f6b34b 100644
--- a/pkg/dartfix/pubspec.yaml
+++ b/pkg/dartfix/pubspec.yaml
@@ -2,13 +2,16 @@
 version: 0.1.5-dev
 author: Dart Team <misc@dartlang.org>
 description:
-  A tool for migrating Dart source to newer versions of the Dart SDK,
+  A tool for migrating Dart source to newer versions of the Dart SDK
   and fixing common issues.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dartfix
-executables:
-  dartfix: fix
 environment:
-  sdk: '>=2.1.0 <3.0.0'
+  sdk: '>=2.2.0 <3.0.0'
+
+# Add the bin/dartfix.dart script to the scripts pub installs.
+executables:
+  dartfix:
+
 dependencies:
   # pin to an exact version of analysis_server_client because the edit.dartfix protocol
   # is experimental and will continue to evolve
@@ -17,6 +20,8 @@
   cli_util: ^0.1.3
   path: ^1.6.0
   pub_semver: ^1.4.2
+
 dev_dependencies:
   analyzer: ^0.33.0
+  pedantic: ^1.5.0
   test: ^1.3.0
diff --git a/pkg/dartfix/test/all.dart b/pkg/dartfix/test/all.dart
index 010f047..f06cf57 100644
--- a/pkg/dartfix/test/all.dart
+++ b/pkg/dartfix/test/all.dart
@@ -6,8 +6,8 @@
 
 import 'src/client_version_test.dart' as client_version_test;
 import 'src/driver_exclude_test.dart' as driver_exclude_test;
+import 'src/driver_help_test.dart' as driver_list_test;
 import 'src/driver_include_test.dart' as driver_include_test;
-import 'src/driver_list_test.dart' as driver_list_test;
 import 'src/driver_required_test.dart' as driver_required_test;
 import 'src/driver_test.dart' as driver_test;
 import 'src/options_test.dart' as options_test;
diff --git a/pkg/dartfix/test/src/driver_help_test.dart b/pkg/dartfix/test/src/driver_help_test.dart
new file mode 100644
index 0000000..b7e944c
--- /dev/null
+++ b/pkg/dartfix/test/src/driver_help_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2019, 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:dartfix/src/driver.dart';
+import 'package:dartfix/src/options.dart';
+import 'package:test/test.dart';
+
+import 'test_context.dart';
+
+main() {
+  test('help explicit', () async {
+    final driver = new Driver();
+    final testContext = new TestContext();
+    final testLogger = new TestLogger();
+    try {
+      await driver.start(
+        ['--help'], // display help and list fixes
+        testContext: testContext,
+        testLogger: testLogger,
+      );
+      fail('expected exception');
+    } on TestExit catch (e) {
+      expect(e.code, 0);
+    }
+    final errText = testLogger.stderrBuffer.toString();
+    final outText = testLogger.stdoutBuffer.toString();
+    expect(errText, isEmpty);
+    expect(outText, contains('--$excludeOption'));
+    expect(outText, isNot(contains('Use --help to display the fixes')));
+    expect(outText, contains('use-mixin'));
+  });
+
+  test('help implicit', () async {
+    final driver = new Driver();
+    final testContext = new TestContext();
+    final testLogger = new TestLogger();
+    try {
+      await driver.start(
+        [], // no options or arguments should display help and list fixes
+        testContext: testContext,
+        testLogger: testLogger,
+      );
+      fail('expected exception');
+    } on TestExit catch (e) {
+      expect(e.code, 0);
+    }
+    final errText = testLogger.stderrBuffer.toString();
+    final outText = testLogger.stdoutBuffer.toString();
+    print(errText);
+    print(outText);
+    expect(errText, isEmpty);
+    expect(outText, contains('--$excludeOption'));
+    expect(outText, isNot(contains('Use --help to display the fixes')));
+    expect(outText, contains('use-mixin'));
+  });
+}
diff --git a/pkg/dartfix/test/src/driver_list_test.dart b/pkg/dartfix/test/src/driver_list_test.dart
deleted file mode 100644
index 372c98b..0000000
--- a/pkg/dartfix/test/src/driver_list_test.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2019, 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:dartfix/src/driver.dart';
-import 'package:test/test.dart';
-
-import 'test_context.dart';
-
-main() {
-  test('list fixes', () async {
-    final driver = new Driver();
-    final testContext = new TestContext();
-    final testLogger = new TestLogger();
-    await driver.start(['--list'], // list fixes
-        testContext: testContext,
-        testLogger: testLogger);
-    final errText = testLogger.stderrBuffer.toString();
-    final outText = testLogger.stdoutBuffer.toString();
-    print(errText);
-    print(outText);
-    expect(outText, contains('use-mixin'));
-  });
-}
diff --git a/pkg/dartfix/test/src/options_test.dart b/pkg/dartfix/test/src/options_test.dart
index 971517a..b0b74d7 100644
--- a/pkg/dartfix/test/src/options_test.dart
+++ b/pkg/dartfix/test/src/options_test.dart
@@ -26,7 +26,7 @@
     bool force = false,
     List<String> includeFixes = const <String>[],
     List<String> excludeFixes = const <String>[],
-    bool listFixes = false,
+    bool showHelp = false,
     String normalOut,
     bool requiredFixes = false,
     bool overwrite = false,
@@ -36,7 +36,7 @@
     Options options;
     int actualExitCode;
     try {
-      options = Options.parse(args, context: context, logger: logger);
+      options = Options.parse(args, context, logger);
     } on TestExit catch (e) {
       actualExitCode = e.code;
     }
@@ -53,7 +53,7 @@
     expect(options.force, force);
     expect(options.requiredFixes, requiredFixes);
     expect(options.overwrite, overwrite);
-    expect(options.listFixes, listFixes);
+    expect(options.showHelp, showHelp);
     expect(options.includeFixes, includeFixes);
     expect(options.excludeFixes, excludeFixes);
     expect(options.verbose, verbose);
@@ -79,8 +79,12 @@
     parse(['--force', 'foo'], force: true, targetSuffixes: ['foo']);
   });
 
-  test('help', () {
-    parse(['--help'], errorOut: 'Display this help message', exitCode: 1);
+  test('help explicit', () {
+    parse(['--help'], normalOut: 'Display this help message', showHelp: true);
+  });
+
+  test('help implicit', () {
+    parse([], normalOut: 'Display this help message', showHelp: true);
   });
 
   test('include fix', () {
@@ -95,7 +99,7 @@
 
   test('invalid option no logger', () {
     try {
-      Options.parse(['--foo'], context: context);
+      Options.parse(['--foo'], context, null);
       fail('Expected exception');
     } on TestExit catch (e) {
       expect(e.code, 15, reason: 'exit code');
@@ -107,10 +111,6 @@
         errorOut: 'Expected directory, but found', exitCode: 15);
   });
 
-  test('list fixes', () {
-    parse(['--list'], errorOut: 'Display this help message', listFixes: true);
-  });
-
   test('overwrite', () {
     parse(['--overwrite', 'foo'], overwrite: true, targetSuffixes: ['foo']);
   });
diff --git a/pkg/dev_compiler/README.md b/pkg/dev_compiler/README.md
index 565ac17..ea460c0 100644
--- a/pkg/dev_compiler/README.md
+++ b/pkg/dev_compiler/README.md
@@ -1,15 +1,8 @@
-dev_compiler
-============
-
-[![Build Status](https://travis-ci.org/dart-lang/sdk.svg?branch=master)](https://travis-ci.org/dart-lang/sdk)
-
 The Dart Dev Compiler (DDC) is a fast, modular compiler that generates modern JavaScript (EcmaScript 6).  Its primary use today is to support fast, iterative development of Dart web applications for Chrome and other modern browsers.
 
-Most users will use DDC via [pub](https://webdev.dartlang.org/tools/pub/pub-serve).  It is supported by pub starting with the Dart 1.24 release.
-
 # Soundness and Restrictions
 
-DDC is built upon Dart's new [strong mode](STRONG_MODE.md) type system.  It only compiles programs that statically type check (i.e., no strong mode errors).  It leverages static type checking to generate simpler, readable, and more idiomatic code with fewer runtime checks.  In general, DDC is able to provide stronger type guarantees - i.e., *soundness* - than traditional Dart checked mode with significantly fewer runtime checks.
+DDC is built upon Dart's [sound](https://www.dartlang.org/guides/language/sound-dart) type system.  It only compiles programs that statically type check (i.e., no strong mode errors).  It leverages static type checking to generate simpler, readable, and more idiomatic code with fewer runtime checks.  In general, DDC is able to provide stronger type guarantees - i.e., *soundness* - than traditional Dart checked mode with significantly fewer runtime checks.
 
 With strong mode, DDC is stricter than traditional Dart production mode or checked mode.  Running existing Dart code on DDC will generally require fixing both static and runtime type errors.  
 
@@ -28,17 +21,11 @@
 List<int> list3 = list2;  // Implicit runtime downcast triggers error.
 ```  
 
-See the [strong mode documentation](STRONG_MODE.md) for more details.
-
 # Modularity
 
 DDC provides fast, incremental compilation based on standard JavaScript modules.  Unlike Dart2JS, DDC does not require an entire Dart application.  Instead, it operates modularly: it compiles a set of Dart files into a JavaScript module.  A DDC compilation step requires a set of input Dart files and a set of *summaries* of dependencies.  It performs modular type checking as part of this compilation step, and, if the input type checks, it generates a JavaScript module (e.g., [*ES6*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import), [*AMD*](https://github.com/amdjs/amdjs-api/blob/master/AMD.md), or [*CommonJS*](https://nodejs.org/docs/latest/api/modules.html)).  The browser (i.e., the JavaScript runtime) loads and links the generated modules when running the application.
 During development, a compilation step only needs to be rerun if the Dart files or summaries it relies upon change.  For most changes, only a very small part of your code will require recompilation.  Moreover, modules that are unchanged can be cached in the browser.
 
-Most users invoke DDC indirectly via [pub](https://webdev.dartlang.org/tools/pub/pub-serve).  Pub computes module structure and build steps automatically and invoke DDC accordingly.  Pub configures DDC to use AMD modules and uses the standard [AMD `require.js` loader](http://requirejs.org/) to bootstrap and load the application.
-
-More advanced users may want to configure or invoke DDC directly.  In general, the mapping of Dart files to JS modules is flexible.  The key requirement is that module dependencies (i.e., `require` in AMD or CommonJS or `import` in ES6) must be acyclic.  In practice, this means that individual Dart libraries cannot each be mapped to a corresponding JS module (as Dart imports can be and often are cyclic).  See the [usage document](USAGE.md) for more details.
-
 # EcmaScript 6
 
 DDC attempts to map Dart to idiomatic EcmaScript 6 (ES6) as cleanly as possible, and it relies heavily on static typing to do this.  In general, where Dart concepts map directly to ES6, DDC generates code accordingly.  For example, Dart classes are mapped to ES6 classes, Dart fields to ES6 properties, Dart getters/setters to ES6 getters/setters, Dart methods to ES6 methods, and so on.  In most cases, names are preserved and calling conventions are natural JavaScript ones.
diff --git a/pkg/dev_compiler/analysis_options.yaml b/pkg/dev_compiler/analysis_options.yaml
index 55db4c5..007c3e7 100644
--- a/pkg/dev_compiler/analysis_options.yaml
+++ b/pkg/dev_compiler/analysis_options.yaml
@@ -1,4 +1,8 @@
 analyzer:
+  strong-mode:
+    implicit-casts: false
+  errors:
+    todo: ignore
   exclude:
     - doc/api/**
     - gen/**
@@ -6,4 +10,27 @@
     - test/codegen/**
     - test/samples/**
     - test/transformer/hello_app/**
-    - tool/input_sdk/**
+
+linter:
+  rules:
+    - annotate_overrides
+    - avoid_empty_else
+    - avoid_init_to_null
+    - avoid_return_types_on_setters
+    - avoid_shadowing_type_parameters
+    - avoid_types_as_parameter_names
+    - curly_braces_in_flow_control_structures
+    - empty_constructor_bodies
+    - library_names
+    - no_duplicate_case_values
+    - null_closures
+    - prefer_contains
+    - prefer_equal_for_default_values
+    - prefer_is_empty
+    - prefer_is_not_empty
+    - recursive_getters
+    - type_init_formals
+    - unnecessary_null_in_if_null_operators
+    - unrelated_type_equality_checks
+    - use_rethrow_when_possible
+    - valid_regexps
diff --git a/pkg/dev_compiler/bin/dartdevc.dart b/pkg/dev_compiler/bin/dartdevc.dart
index 1075043..db2f7b8 100755
--- a/pkg/dev_compiler/bin/dartdevc.dart
+++ b/pkg/dev_compiler/bin/dartdevc.dart
@@ -47,6 +47,7 @@
   CompilerResult lastResult;
 
   /// Performs each individual work request.
+  @override
   Future<WorkResponse> performRequest(WorkRequest request) async {
     var args = _startupArgs.merge(request.arguments);
     var output = StringBuffer();
@@ -56,18 +57,6 @@
             ZoneSpecification(print: (self, parent, zone, message) {
       output.writeln(message.toString());
     }));
-
-    if (lastResult.crashed && context != null) {
-      // TODO(vsm): See https://github.com/dart-lang/sdk/issues/36644.
-      // If the CFE is crashing with previous state, then clear compilation
-      // state and try again.
-      output.clear();
-      lastResult = await runZoned(() => compile(args, previousResult: null),
-          zoneSpecification:
-              ZoneSpecification(print: (self, parent, zone, message) {
-        output.writeln(message.toString());
-      }));
-    }
     return WorkResponse()
       ..exitCode = lastResult.success ? 0 : 1
       ..output = output.toString();
diff --git a/pkg/dev_compiler/lib/src/analyzer/ast_builder.dart b/pkg/dev_compiler/lib/src/analyzer/ast_builder.dart
index 672a2a3..120b590 100644
--- a/pkg/dev_compiler/lib/src/analyzer/ast_builder.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/ast_builder.dart
@@ -16,15 +16,15 @@
   KeywordToken get constKeyword => KeywordToken(Keyword.CONST, 0);
 
   TypeName typeName(Identifier id, List<TypeAnnotation> args) {
-    TypeArgumentList argList = null;
-    if (args != null && args.length > 0) argList = typeArgumentList(args);
+    TypeArgumentList argList;
+    if (args != null && args.isNotEmpty) argList = typeArgumentList(args);
     return astFactory.typeName(id, argList);
   }
 
   FunctionTypeAlias functionTypeAlias(TypeName ret, SimpleIdentifier name,
       List<TypeParameter> tParams, List<FormalParameter> params) {
     TypeParameterList tps =
-        (tParams.length == 0) ? null : typeParameterList(tParams);
+        (tParams.isEmpty) ? null : typeParameterList(tParams);
     FormalParameterList fps = formalParameterList(params);
     Token semi = Token(TokenType.SEMICOLON, 0);
     Token td = KeywordToken(Keyword.TYPEDEF, 0);
@@ -100,6 +100,10 @@
         return TokenType.GT_GT;
       case ">>=":
         return TokenType.GT_GT_EQ;
+      case ">>>":
+        return TokenType.GT_GT_GT;
+      case ">>>=":
+        return TokenType.GT_GT_GT_EQ;
       case "#":
         return TokenType.HASH;
       case "[]":
@@ -309,7 +313,7 @@
     return astFactory.prefixedIdentifier(pre, period, id);
   }
 
-  TypeParameter typeParameter(SimpleIdentifier name, [TypeName bound = null]) {
+  TypeParameter typeParameter(SimpleIdentifier name, [TypeName bound]) {
     Token keyword = (bound == null) ? null : KeywordToken(Keyword.EXTENDS, 0);
     return astFactory.typeParameter(null, null, name, keyword, bound);
   }
@@ -384,8 +388,8 @@
     bool hasOptional = params.any((p) => p.isPositional);
     bool hasNamed = params.any((p) => p.isNamed);
     assert(!(hasOptional && hasNamed));
-    Token ld = null;
-    Token rd = null;
+    Token ld;
+    Token rd;
     if (hasOptional) {
       ld = BeginToken(TokenType.OPEN_SQUARE_BRACKET, 0);
       rd = Token(TokenType.CLOSE_SQUARE_BRACKET, 0);
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 39f7c88f..3ff97b0 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart' show StringToken;
 import 'package:analyzer/src/dart/ast/utilities.dart' show UIAsCodeVisitorMixin;
 import 'package:analyzer/src/dart/element/element.dart';
@@ -23,7 +24,6 @@
 import 'package:analyzer/src/generated/resolver.dart'
     show TypeProvider, NamespaceBuilder;
 import 'package:analyzer/src/generated/type_system.dart' show Dart2TypeSystem;
-import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/task/strong/ast_properties.dart';
 import 'package:path/path.dart' as path;
@@ -82,6 +82,7 @@
   /// Errors that were produced during compilation, if any.
   final ErrorCollector errors;
 
+  @override
   JSTypeRep jsTypeRep;
 
   /// The list of dart:_runtime SDK functions; these are assumed by other code
@@ -111,6 +112,7 @@
   /// The  type provider from the current Analysis [context].
   final TypeProvider types;
 
+  @override
   final LibraryElement coreLibrary;
   final LibraryElement dartJSLibrary;
 
@@ -182,6 +184,7 @@
 
   /// Information about virtual fields for all libraries in the current build
   /// unit.
+  @override
   final virtualFields = VirtualFieldModel();
 
   final _usedCovariantPrivateMembers = HashSet<ExecutableElement>();
@@ -233,6 +236,7 @@
     jsTypeRep = JSTypeRep(rules, driver);
   }
 
+  @override
   LibraryElement get currentLibrary => _currentElement.library;
 
   @override
@@ -423,7 +427,7 @@
   String jsLibraryName(LibraryElement library) {
     var uri = library.source.uri;
     if (uri.scheme == 'dart') {
-      return uri.path;
+      return isSdkInternalRuntime(library) ? 'dart' : uri.path;
     }
     // TODO(vsm): This is not necessarily unique if '__' appears in a file name.
     var encodedSeparator = '__';
@@ -462,6 +466,10 @@
   }
 
   @override
+  Iterable<String> jsPartDebuggerNames(LibraryElement library) =>
+      library.parts.map((part) => part.uri);
+
+  @override
   String libraryToModule(LibraryElement library) {
     var source = library.source;
     // TODO(jmesserly): we need to split out HTML.
@@ -605,7 +613,7 @@
 
   @override
   visitExportDirective(ExportDirective node) {
-    ExportElement element = node.element;
+    var element = node.element as ExportElement;
     var currentLibrary = element.library;
 
     var currentNames = currentLibrary.publicNamespace.definedNames;
@@ -691,7 +699,7 @@
         // TODO(jmesserly): fuse this with notNull check.
         // TODO(jmesserly): this does not correctly distinguish user casts from
         // required-for-soundness casts.
-        return runtimeCall('asInt(#)', jsFrom);
+        return runtimeCall('asInt(#)', [jsFrom]);
       }
 
       // A no-op in JavaScript.
@@ -1539,7 +1547,7 @@
           param = covariantParams.lookup(param) as ParameterElement;
 
           if (param == null) continue;
-          if (param.kind == ParameterKind.NAMED) {
+          if (param.isNamed) {
             foundNamedParams = true;
 
             var name = propertyName(param.name);
@@ -1552,10 +1560,12 @@
             var jsParam = _emitParameter(param);
             jsParams.add(jsParam);
 
-            if (param.kind == ParameterKind.POSITIONAL) {
+            if (param.isPositional) {
               body.add(js.statement('if (# !== void 0) #;',
                   [jsParam, _emitCast(param.type, jsParam)]));
             } else {
+              //TODO(nshahan) Cleanup this logic. Do we need this else branch?
+              // https://github.com/dart-lang/sdk/issues/37123
               body.add(_emitCast(param.type, jsParam).toStatement());
             }
           }
@@ -1829,8 +1839,8 @@
       ClassElement classElem, String jsPeerName, List<JS.Statement> body) {
     var className = _emitTopLevelName(classElem);
     if (jsTypeRep.isPrimitive(classElem.type)) {
-      body.add(
-          runtimeStatement('definePrimitiveHashCode(#.prototype)', className));
+      body.add(runtimeStatement(
+          'definePrimitiveHashCode(#.prototype)', [className]));
     }
     body.add(runtimeStatement(
         'registerExtension(#, #)', [js.string(jsPeerName), className]));
@@ -2170,6 +2180,10 @@
       emitSignature('Setter', instanceSetters);
       emitSignature('StaticGetter', staticGetters);
       emitSignature('StaticSetter', staticSetters);
+      body.add(runtimeStatement('setLibraryUri(#, #)', [
+        className,
+        js.escapedString(jsLibraryDebuggerName(classElem.library))
+      ]));
     }
 
     {
@@ -2270,7 +2284,7 @@
   JS.Block _emitConstructorBody(ConstructorDeclaration node,
       List<VariableDeclaration> fields, JS.Expression className) {
     var body = <JS.Statement>[];
-    ClassDeclaration cls = node.parent;
+    var cls = node.parent as ClassDeclaration;
 
     // Generate optional/named argument value assignment. These can not have
     // side effects, and may be used by the constructor's initializers, so it's
@@ -2569,7 +2583,7 @@
     }
 
     if (node.isGetter || node.isSetter) {
-      PropertyAccessorElement element = node.declaredElement;
+      var element = node.declaredElement as PropertyAccessorElement;
       var pairAccessor = node.isGetter
           ? element.correspondingSetter
           : element.correspondingGetter;
@@ -2713,7 +2727,7 @@
 
     // Simplify `=> { return e; }` to `=> e`
     if (body is JS.Block) {
-      JS.Block block = body;
+      var block = body as JS.Block;
       if (block.statements.length == 1) {
         JS.Statement s = block.statements[0];
         if (s is JS.Return && s.value != null) body = s.value;
@@ -3039,7 +3053,7 @@
       // If the type is a type literal expression in Dart code, wrap the raw
       // runtime type in a "Type" instance.
       if (!_isInForeignJS && _isTypeLiteral(node)) {
-        typeName = runtimeCall('wrapType(#)', typeName);
+        typeName = runtimeCall('wrapType(#)', [typeName]);
       }
 
       return typeName;
@@ -3278,7 +3292,7 @@
     if (_isExternal(member)) {
       var nativeName = _extensionTypes.getNativePeers(c);
       if (nativeName.isNotEmpty) {
-        return runtimeCall('global.#', nativeName[0]);
+        return runtimeCall('global.#', [nativeName[0]]);
       }
     }
     return _emitTopLevelName(c);
@@ -3316,7 +3330,8 @@
     // Anonymous JS types do not have a corresponding concrete JS type so we
     // have to use a helper to define them.
     if (_isObjectLiteral(element)) {
-      return runtimeCall('anonymousJSType(#)', js.escapedString(element.name));
+      return runtimeCall(
+          'anonymousJSType(#)', [js.escapedString(element.name)]);
     }
     var jsName = _getJSNameWithoutGlobal(element);
     if (jsName != null) {
@@ -3443,7 +3458,7 @@
       return _emitSetSimpleIdentifier(left, right);
     }
 
-    Expression target = null;
+    Expression target;
     SimpleIdentifier id;
     if (left is PropertyAccess) {
       if (left.operator.lexeme == '?.') {
@@ -3767,7 +3782,8 @@
     // Handle Object methods that are supported by `null`.
     if (_isObjectMethodCall(name, argumentList.arguments) &&
         isNullable(target)) {
-      assert(typeArgs == null); // Object methods don't take type args.
+      assert(typeArgs == null ||
+          typeArgs.isEmpty); // Object methods don't take type args.
       return runtimeCall('#(#, #)', [name, jsTarget, args]);
     }
 
@@ -3961,23 +3977,30 @@
       return null;
     }
     return _emitFunctionTypeArguments(
-        function.staticType, node.staticInvokeType, node.typeArguments);
+        node, function.staticType, node.staticInvokeType, node.typeArguments);
   }
 
   /// If `g` is a generic function type, and `f` is an instantiation of it,
   /// then this will return the type arguments to apply, otherwise null.
-  List<JS.Expression> _emitFunctionTypeArguments(DartType g, DartType f,
+  List<JS.Expression> _emitFunctionTypeArguments(
+      AstNode node, DartType g, DartType f,
       [TypeArgumentList typeArgs]) {
+    if (node is InvocationExpression) {
+      if (g is! FunctionType && typeArgs == null) {
+        return null;
+      }
+      var typeArguments = node.typeArgumentTypes;
+      return typeArguments.map(_emitType).toList(growable: false);
+    }
+
     if (g is FunctionType &&
         g.typeFormals.isNotEmpty &&
         f is FunctionType &&
         f.typeFormals.isEmpty) {
-      return _recoverTypeArguments(g, f).map(_emitType).toList(growable: false);
-    } else if (typeArgs != null) {
-      // Dynamic calls may have type arguments, even though the function types
-      // are not known.
-      return _visitExpressionList(typeArgs.arguments);
+      var typeArguments = _recoverTypeArguments(g, f);
+      return typeArguments.map(_emitType).toList(growable: false);
     }
+
     return null;
   }
 
@@ -4130,16 +4153,26 @@
     if (conditionType is FunctionType &&
         conditionType.parameters.isEmpty &&
         conditionType.returnType == types.boolType) {
-      jsCondition = runtimeCall('test(#())', jsCondition);
+      jsCondition = runtimeCall('test(#())', [jsCondition]);
     } else if (conditionType != types.boolType) {
-      jsCondition = runtimeCall('dassert(#)', jsCondition);
+      jsCondition = runtimeCall('dassert(#)', [jsCondition]);
     } else if (isNullable(condition)) {
-      jsCondition = runtimeCall('test(#)', jsCondition);
+      jsCondition = runtimeCall('test(#)', [jsCondition]);
     }
-    return js.statement(' if (!#) #.assertFailed(#);', [
+
+    var location = _getLocation(condition.offset);
+    return js.statement(' if (!#) #.assertFailed(#, #, #, #, #);', [
       jsCondition,
       runtimeModule,
-      message != null ? [_visitExpression(message)] : []
+      if (message == null)
+        JS.LiteralNull()
+      else
+        _visitExpression(message),
+      js.escapedString(location.sourceUrl.toString()),
+      // Lines and columns are typically printed with 1 based indexing.
+      js.number(location.line + 1),
+      js.number(location.column + 1),
+      js.escapedString(condition.toSource()),
     ]);
   }
 
@@ -4540,7 +4573,7 @@
     if (expr == null) return null;
     var jsExpr = _visitExpression(expr);
     if (!isNullable(expr)) return jsExpr;
-    return runtimeCall('notNull(#)', jsExpr);
+    return runtimeCall('notNull(#)', [jsExpr]);
   }
 
   JS.Expression _emitEqualityOperator(BinaryExpression node, Token op) {
@@ -4764,7 +4797,9 @@
 
   AstNode _parentOperation(AstNode node) {
     node = node.parent;
-    while (node is ParenthesizedExpression) node = node.parent;
+    while (node is ParenthesizedExpression) {
+      node = node.parent;
+    }
     return node;
   }
 
@@ -5022,6 +5057,11 @@
     var op = node.operator;
     var expr = node.operand;
 
+    if (op.type == TokenType.BANG) {
+      // If the expression is non-nullable already, this is a no-op.
+      return isNullable(expr) ? notNull(expr) : _visitExpression(expr);
+    }
+
     var dispatchType = getStaticType(expr);
     if (jsTypeRep.unaryOperationIsPrimitive(dispatchType)) {
       if (!isNullable(expr)) {
@@ -5177,9 +5217,12 @@
       return ast.propertyAccess(newTarget, node.propertyName);
     } else {
       var invoke = node as MethodInvocation;
-      return ast.methodInvoke(newTarget, invoke.methodName,
+      var newNode = ast.methodInvoke(newTarget, invoke.methodName,
           invoke.typeArguments, invoke.argumentList.arguments)
         ..staticInvokeType = invoke.staticInvokeType;
+      (newNode as MethodInvocationImpl).typeArgumentTypes =
+          invoke.typeArgumentTypes;
+      return newNode;
     }
   }
 
@@ -5193,7 +5236,7 @@
 
     // TODO(jmesserly): handle explicitly passed type args.
     if (type == null) return null;
-    return _emitFunctionTypeArguments(type, instantiated);
+    return _emitFunctionTypeArguments(null, type, instantiated);
   }
 
   /// Shared code for [PrefixedIdentifier] and [PropertyAccess].
@@ -5345,12 +5388,13 @@
 
   @override
   JS.Expression visitThrowExpression(ThrowExpression node) {
-    return runtimeCall('throw(#)', _visitExpression(node.expression));
+    return runtimeCall('throw(#)', [_visitExpression(node.expression)]);
   }
 
   @override
   JS.Expression visitRethrowExpression(RethrowExpression node) {
-    return runtimeCall('rethrow(#)', _emitSimpleIdentifier(_rethrowParameter));
+    return runtimeCall(
+        'rethrow(#)', [_emitSimpleIdentifier(_rethrowParameter)]);
   }
 
   /// Visits a statement, and ensures the resulting AST handles block scope
@@ -5757,7 +5801,7 @@
         var jsExpr = _visitExpression(e);
         parts.add(e.staticType == types.stringType && !isNullable(e)
             ? jsExpr
-            : runtimeCall('str(#)', jsExpr));
+            : runtimeCall('str(#)', [jsExpr]));
       }
     }
     if (parts.isEmpty) return js.string('');
@@ -5826,8 +5870,7 @@
     /// fucntion, call it, and yield the result of [yieldType].
     /// TODO(nshahan) Move to share between compilers. Need to work out a common
     /// emitLibraryName().
-    JS.Expression detectYieldAndCall(
-        JS.Statement body, InterfaceType yieldType) {
+    JS.Expression detectYieldAndCall(JS.Block body, InterfaceType yieldType) {
       var finder = YieldFinder();
       body.accept(finder);
       if (finder.hasYield) {
@@ -5854,7 +5897,7 @@
         // a function call that returns the list.
         var functionBody = JS.Block([
           items,
-          node.accept<JS.Node>(this),
+          node.accept<JS.Node>(this) as JS.Statement,
           JS.Return(_currentCollectionVariable)
         ]);
         var functionCall = detectYieldAndCall(functionBody, arrayType);
@@ -5885,7 +5928,7 @@
       ]);
     }
 
-    return pushToCurrentCollection(node);
+    return pushToCurrentCollection(node as Expression);
   }
 
   /// Returns `true` if [node] is a UI-as-Code [CollectionElement].
@@ -6002,10 +6045,10 @@
     }
     if (node is AsExpression && CoercionReifier.isImplicit(node)) {
       assert(node.staticType == types.boolType);
-      return runtimeCall('dtest(#)', _visitExpression(node.expression));
+      return runtimeCall('dtest(#)', [_visitExpression(node.expression)]);
     }
     var result = _visitExpression(node);
-    if (isNullable(node)) result = runtimeCall('test(#)', result);
+    if (isNullable(node)) result = runtimeCall('test(#)', [result]);
     return result;
   }
 
@@ -6207,6 +6250,7 @@
 
   /// Return true if this is one of the methods/properties on all Dart Objects
   /// (toString, hashCode, noSuchMethod, runtimeType, ==).
+  @override
   bool isObjectMember(String name) {
     // We could look these up on Object, but we have hard coded runtime helpers
     // so it's not really providing any benefit.
@@ -6242,7 +6286,7 @@
     }
     var type = functionType.returnType;
 
-    InterfaceType expectedType = null;
+    InterfaceType expectedType;
     if (element.isAsynchronous) {
       if (element.isGenerator) {
         // Stream<T> -> T
@@ -6273,9 +6317,9 @@
   }
 
   JS.Expression _throwUnsafe(String message) => runtimeCall(
-      'throw(Error(#))', js.escapedString("compile error: $message"));
+      'throw(Error(#))', [js.escapedString("compile error: $message")]);
 
-  JS.Node _unreachable(Object node) {
+  Null _unreachable(Object node) {
     throw UnsupportedError('tried to generate an unreachable node: `$node`');
   }
 
@@ -6427,9 +6471,9 @@
 
   JS.For _emitFor(ForParts forParts, JS.Statement body) {
     JS.Expression init;
-    if (forParts is ForPartsWithExpression)
+    if (forParts is ForPartsWithExpression) {
       init = _visitExpression(forParts.initialization);
-    else if (forParts is ForPartsWithDeclarations) {
+    } else if (forParts is ForPartsWithDeclarations) {
       init = visitVariableDeclarationList(forParts.variables);
     } else {
       throw new StateError('Unrecognized for loop parts');
@@ -6471,7 +6515,7 @@
   @override
   JS.Statement visitForElement(ForElement node) {
     var jsBody = _isUiAsCodeElement(node.body)
-        ? node.body.accept(this)
+        ? node.body.accept(this) as JS.Statement
         : _visitNestedCollectionElement(node.body);
     return _forAdaptor(node.forLoopParts, node.awaitKeyword, jsBody);
   }
@@ -6479,13 +6523,13 @@
   @override
   JS.Statement visitIfElement(IfElement node) {
     var thenElement = _isUiAsCodeElement(node.thenElement)
-        ? node.thenElement.accept(this)
+        ? node.thenElement.accept(this) as JS.Statement
         : _visitNestedCollectionElement(node.thenElement);
 
     JS.Statement elseElement;
     if (node.elseElement != null) {
       if (_isUiAsCodeElement(node.elseElement)) {
-        elseElement = node.elseElement.accept<JS.Node>(this);
+        elseElement = node.elseElement.accept<JS.Node>(this) as JS.Statement;
       } else {
         elseElement = _visitNestedCollectionElement(node.elseElement);
       }
@@ -6565,7 +6609,8 @@
     /// Returns [expression] wrapped in an implict cast to [castType] or
     /// [expression] as provided if [castType] is `null` signifying that
     /// no cast is needed.
-    JS.Expression wrapInImplicitCast(JS.Expression expression, castType) =>
+    JS.Expression wrapInImplicitCast(
+            JS.Expression expression, DartType castType) =>
         castType == null ? expression : _emitCast(castType, expression);
 
     /// Returns a statement spreading the elements of [expression] into
@@ -6655,6 +6700,9 @@
   @override
   visitForPartsWithExpression(ForPartsWithExpression node) =>
       _unreachable(node);
+
+  @override
+  visitExtensionDeclaration(ExtensionDeclaration node) => _unreachable(node);
 }
 
 // TODO(jacobr): we would like to do something like the following
@@ -6676,8 +6724,10 @@
         : enclosingElement;
   }
 
+  @override
   int get hashCode => identityHashCode(this);
 
+  @override
   bool operator ==(Object other) => identical(this, other);
 }
 
diff --git a/pkg/dev_compiler/lib/src/analyzer/command.dart b/pkg/dev_compiler/lib/src/analyzer/command.dart
index 2d32c8d..d8e2363 100644
--- a/pkg/dev_compiler/lib/src/analyzer/command.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/command.dart
@@ -140,12 +140,12 @@
   if (outPaths.isEmpty) {
     throw UsageException(
         'Please specify the output file location. For example:\n'
-        '    -o PATH/TO/OUTPUT_FILE.js',
+            '    -o PATH/TO/OUTPUT_FILE.js',
         '');
   } else if (outPaths.length != moduleFormats.length) {
     throw UsageException(
         'Number of output files (${outPaths.length}) must match '
-        'number of module formats (${moduleFormats.length}).',
+            'number of module formats (${moduleFormats.length}).',
         '');
   }
 
@@ -208,11 +208,13 @@
 
 /// Thrown when the input source code has errors.
 class CompileErrorException implements Exception {
+  @override
   toString() => '\nPlease fix all errors before compiling (warnings are okay).';
 }
 
 /// Thrown when force compilation failed (probably due to static errors).
 class ForceCompileErrorException extends CompileErrorException {
+  @override
   toString() =>
       '\nForce-compilation not successful. Please check static errors.';
 }
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
index 7c5d95b..9e9cb02 100644
--- a/pkg/dev_compiler/lib/src/analyzer/driver.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/library_analyzer.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -80,10 +81,10 @@
     var resourceProvider = options.resourceProvider;
     var contextBuilder = options.createContextBuilder();
 
-    var analysisOptions =
-        contextBuilder.getAnalysisOptions(options.analysisRoot);
+    var analysisOptions = contextBuilder
+        .getAnalysisOptions(options.analysisRoot) as AnalysisOptionsImpl;
 
-    (analysisOptions as AnalysisOptionsImpl).enabledExperiments =
+    analysisOptions.enabledExperiments =
         experiments.entries.where((e) => e.value).map((e) => e.key).toList();
 
     var dartSdk = contextBuilder.findSdk(null, analysisOptions);
@@ -241,8 +242,9 @@
     var bundle = PackageBundle.fromBuffer(summaryBytes);
 
     /// Create an analysis context to contain the state for this build unit.
-    var context = RestrictedAnalysisContext(
-        analysisOptions, declaredVariables, sourceFactory);
+    var synchronousSession =
+        SynchronousSession(analysisOptions, declaredVariables);
+    var context = RestrictedAnalysisContext(synchronousSession, sourceFactory);
     var resynthesizer = StoreBasedSummaryResynthesizer(
       context,
       null,
@@ -334,12 +336,13 @@
 
     var libraryFile = _fsState.getFileForUri(Uri.parse(libraryUri));
     var analyzer = LibraryAnalyzer(
-        analysisOptions,
+        analysisOptions as AnalysisOptionsImpl,
         declaredVariables,
         resynthesizer.sourceFactory,
         (uri) => _isLibraryUri('$uri'),
         resynthesizer.context,
         resynthesizer,
+        null,
         InheritanceManager2(resynthesizer.typeSystem),
         libraryFile,
         _resourceProvider);
diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
index 45f443f..e8fe0f0 100644
--- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
@@ -124,7 +124,7 @@
   if (node == null) return false;
   var parent = node.parent;
   while (parent is ParenthesizedExpression) {
-    node = parent;
+    node = parent as Expression;
     parent = node.parent;
   }
   return parent is InvocationExpression && identical(node, parent.function) ||
diff --git a/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
index 1528546..db93257 100644
--- a/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
@@ -34,7 +34,9 @@
   }
 
   void addAll(LineInfo lineInfo, Iterable<AnalysisError> errors) {
-    for (var e in errors) add(lineInfo, e);
+    for (var e in errors) {
+      add(lineInfo, e);
+    }
   }
 
   ErrorSeverity _errorSeverity(AnalysisError error) {
@@ -123,4 +125,4 @@
     ErrorType.COMPILE_TIME_ERROR,
     'INVALID_JS_INTEGER',
     "The integer literal '{0}' can't be represented exactly in JavaScript. "
-    "The nearest value that can be represented exactly is '{1}'.");
+        "The nearest value that can be represented exactly is '{1}'.");
diff --git a/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart b/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart
index ef723c2..885172f 100644
--- a/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart
@@ -136,8 +136,8 @@
     // leads to O(depth) cost for calling this function. We could store the
     // resulting value if that becomes an issue, so we maintain the invariant
     // that each node is visited once.
-    Element element = null;
-    String name = null;
+    Element element;
+    String name;
     if (expr is PropertyAccess &&
         expr.operator?.type != TokenType.QUESTION_PERIOD) {
       element = expr.propertyName.staticElement;
@@ -196,7 +196,7 @@
       // they will throw noSuchMethod.
       // The only properties/methods on `null` are those on Object itself.
       for (var section in expr.cascadeSections) {
-        Element e = null;
+        Element e;
         if (section is PropertyAccess) {
           e = section.propertyName.staticElement;
         } else if (section is MethodInvocation) {
diff --git a/pkg/dev_compiler/lib/src/analyzer/property_model.dart b/pkg/dev_compiler/lib/src/analyzer/property_model.dart
index b7dc784..d63abc3 100644
--- a/pkg/dev_compiler/lib/src/analyzer/property_model.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/property_model.dart
@@ -77,8 +77,9 @@
       // add it to our work set if this is the first time we've visited it.
       for (var superclass in getImmediateSuperclasses(extensibleClass)) {
         if (!superclass.isPublic && superclass.library == library) {
-          if (_extensiblePrivateClasses.add(superclass))
+          if (_extensiblePrivateClasses.add(superclass)) {
             classesToVisit.add(superclass);
+          }
         }
       }
     }
@@ -282,8 +283,12 @@
     void visit(InterfaceType type, bool isAbstract) {
       if (type == null) return;
       visit(type.superclass, isAbstract);
-      for (var m in type.mixins) visit(m, isAbstract);
-      for (var i in type.interfaces) visit(i, true);
+      for (var m in type.mixins) {
+        visit(m, isAbstract);
+      }
+      for (var i in type.interfaces) {
+        visit(i, true);
+      }
 
       for (var m in [type.methods, type.accessors].expand((m) => m)) {
         if (m.isStatic) continue;
diff --git a/pkg/dev_compiler/lib/src/analyzer/reify_coercions.dart b/pkg/dev_compiler/lib/src/analyzer/reify_coercions.dart
index a071fcb..9d2ad1d 100644
--- a/pkg/dev_compiler/lib/src/analyzer/reify_coercions.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/reify_coercions.dart
@@ -6,7 +6,11 @@
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/visitor.dart' show GeneralizingAstVisitor;
 import 'package:analyzer/dart/element/type.dart' show DartType;
-import 'package:analyzer/src/dart/ast/ast.dart' show FunctionBodyImpl;
+import 'package:analyzer/src/dart/ast/ast.dart'
+    show
+        FunctionBodyImpl,
+        FunctionExpressionInvocationImpl,
+        MethodInvocationImpl;
 import 'package:analyzer/src/dart/ast/utilities.dart'
     show AstCloner, NodeReplacer;
 import 'package:analyzer/src/generated/parser.dart' show ResolutionCopier;
@@ -185,6 +189,22 @@
     return clone;
   }
 
+  @override
+  FunctionExpressionInvocation visitFunctionExpressionInvocation(
+      FunctionExpressionInvocation node) {
+    var clone = super.visitFunctionExpressionInvocation(node);
+    (clone as FunctionExpressionInvocationImpl).typeArgumentTypes =
+        node.typeArgumentTypes;
+    return clone;
+  }
+
+  @override
+  MethodInvocation visitMethodInvocation(MethodInvocation node) {
+    var clone = super.visitMethodInvocation(node);
+    (clone as MethodInvocationImpl).typeArgumentTypes = node.typeArgumentTypes;
+    return clone;
+  }
+
   // TODO(jmesserly): workaround for
   // https://github.com/dart-lang/sdk/issues/26368
   @override
diff --git a/pkg/dev_compiler/lib/src/analyzer/side_effect_analysis.dart b/pkg/dev_compiler/lib/src/analyzer/side_effect_analysis.dart
index 145219f..44517f2 100644
--- a/pkg/dev_compiler/lib/src/analyzer/side_effect_analysis.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/side_effect_analysis.dart
@@ -132,3 +132,39 @@
     return initializer.accept(constantVisitor);
   }
 }
+
+class LabelContinueFinder extends SimpleAstVisitor {
+  var found = false;
+  visit(Statement s) {
+    if (!found && s != null) s.accept(this);
+  }
+
+  @override
+  visitBlock(Block node) => node.statements.forEach(visit);
+  @override
+  visitWhileStatement(WhileStatement node) => visit(node.body);
+  @override
+  visitDoStatement(DoStatement node) => visit(node.body);
+  @override
+  visitForStatement(ForStatement node) => visit(node.body);
+  @override
+  visitLabeledStatement(LabeledStatement node) => visit(node.statement);
+  @override
+  visitContinueStatement(ContinueStatement node) => found = node.label != null;
+  @override
+  visitSwitchStatement(SwitchStatement node) {
+    node.members.forEach((m) => m.statements.forEach(visit));
+  }
+
+  @override
+  visitIfStatement(IfStatement node) {
+    visit(node.thenStatement);
+    visit(node.elseStatement);
+  }
+
+  @override
+  visitTryStatement(TryStatement node) {
+    node.body.accept(this);
+    node.finallyBlock.accept(this);
+  }
+}
diff --git a/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart b/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
index 91978e7..dc52e86 100644
--- a/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
@@ -134,6 +134,7 @@
 
   _GeneratorTable(this._runtimeModule);
 
+  @override
   JS.Statement _dischargeType(DartType t) {
     var name = _names.remove(t);
     if (name != null) {
diff --git a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
index e911dca..94f1c2edb 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
@@ -54,17 +54,18 @@
   /// Returns an expression that ignores the result. This is a cross between
   /// [toExpression] and [toStatement]. Used for C-style for-loop updaters,
   /// which is an expression syntactically, but functions more like a statement.
+  @override
   Expression toVoidExpression() {
     var block = toStatement();
     var s = block.statements;
     if (s.length == 1 && s.first is ExpressionStatement) {
-      ExpressionStatement es = s.first;
-      return es.expression;
+      return (s.first as ExpressionStatement).expression;
     }
 
     return _toInvokedFunction(block);
   }
 
+  @override
   Expression toAssignExpression(Expression left, [String op]) {
     if (left is Identifier) {
       return _simplifyAssignment(left, op: op) ?? _toAssign(left, op);
@@ -82,6 +83,7 @@
     return MetaLet(variables, exprs);
   }
 
+  @override
   Statement toVariableDeclaration(VariableBinding name) {
     if (name is Identifier) {
       var simple = _simplifyAssignment(name, isDeclaration: true);
@@ -111,13 +113,13 @@
     var block = toReturn();
     var s = block.statements;
     if (s.length == 1 && s.first is Return) {
-      Return es = s.first;
-      return _expression = es.value;
+      return _expression = (s.first as Return).value;
     }
     // Wrap it in an immediately called function to get in expression context.
     return _expression = _toInvokedFunction(block);
   }
 
+  @override
   Block toStatement() {
     // Skip return value if not used.
     var statements = body.map((e) => e.toStatement()).toList();
@@ -125,6 +127,7 @@
     return _finishStatement(statements);
   }
 
+  @override
   Block toReturn() {
     var statements = body
         .map((e) => e == body.last ? e.toReturn() : e.toStatement())
@@ -132,6 +135,7 @@
     return _finishStatement(statements);
   }
 
+  @override
   Block toYieldStatement({bool star = false}) {
     var statements = body
         .map((e) =>
@@ -140,6 +144,7 @@
     return _finishStatement(statements);
   }
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) {
     // TODO(jmesserly): we special case vistors from js_ast.Template, because it
     // doesn't know about MetaLet. Should we integrate directly?
@@ -153,6 +158,7 @@
     }
   }
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     // TODO(jmesserly): we special case vistors from js_ast.Template, because it
     // doesn't know about MetaLet. Should we integrate directly?
@@ -166,6 +172,7 @@
   }
 
   /// This generates as either a comma expression or a call.
+  @override
   int get precedenceLevel => toExpression().precedenceLevel;
 
   /// Patch to pretend [Template] supports visitMetaLet.
@@ -199,7 +206,9 @@
     var node = Block(statements);
     node.accept(counter);
     // Also count the init expressions.
-    for (var init in variables.values) init.accept(counter);
+    for (var init in variables.values) {
+      init.accept(counter);
+    }
 
     var initializers = <VariableInitialization>[];
     var substitutions = <MetaLetVariable, Expression>{};
@@ -269,7 +278,7 @@
       }
 
       assert(body.isNotEmpty);
-      Binary newBody = Expression.binary([assign]..addAll(body), ',');
+      var newBody = Expression.binary([assign]..addAll(body), ',') as Binary;
       newBody = _substitute(newBody, {result: left});
       return MetaLet(vars, newBody.commaToExpressionList(),
           statelessResult: statelessResult);
diff --git a/pkg/dev_compiler/lib/src/compiler/js_names.dart b/pkg/dev_compiler/lib/src/compiler/js_names.dart
index c4c1c11..ba120a3 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_names.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_names.dart
@@ -29,7 +29,9 @@
   //
   // However we may need to fix this if we want hover to work well for things
   // like library prefixes and field-initializing formals.
+  @override
   get sourceInformation => null;
+  @override
   set sourceInformation(Object obj) {}
 
   TemporaryId(String name) : super(name);
@@ -60,10 +62,13 @@
     }
   }
 
+  @override
   int get precedenceLevel => _expr.precedenceLevel;
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => _expr.accept(visitor);
 
+  @override
   void visitChildren(NodeVisitor visitor) => _expr.visitChildren(visitor);
 }
 
@@ -83,16 +88,19 @@
 
   TemporaryNamer(Node node) : scope = _RenameVisitor.build(node).rootScope;
 
+  @override
   String getName(Identifier node) {
     var rename = scope.renames[identifierKey(node)];
     if (rename != null) return rename;
     return node.name;
   }
 
+  @override
   void enterScope(Node node) {
     scope = scope.childScopes[node];
   }
 
+  @override
   void leaveScope() {
     scope = scope.parent;
   }
@@ -138,6 +146,7 @@
     _finishNames();
   }
 
+  @override
   declare(Identifier node) {
     var id = identifierKey(node);
     var notAlreadyDeclared = scope.declared.add(id);
@@ -147,6 +156,7 @@
     _markUsed(node, id, scope);
   }
 
+  @override
   visitIdentifier(Identifier node) {
     var id = identifierKey(node);
 
@@ -166,7 +176,7 @@
   _markUsed(Identifier node, Object id, _FunctionScope declScope) {
     // If it needs rename, we can't add it to the used name set yet, instead we
     // will record all scopes it is visible in.
-    Set<_FunctionScope> usedIn = null;
+    Set<_FunctionScope> usedIn;
     var rename = declScope != globalScope && needsRename(node);
     if (rename) {
       usedIn = pendingRenames.putIfAbsent(id, () => HashSet());
@@ -180,11 +190,13 @@
     }
   }
 
+  @override
   visitFunctionExpression(FunctionExpression node) {
     // Visit nested functions after all identifiers are declared.
     scope.childScopes[node] = _FunctionScope(scope);
   }
 
+  @override
   visitClassExpression(ClassExpression node) {
     scope.childScopes[node] = _FunctionScope(scope);
   }
@@ -195,7 +207,7 @@
       if (node is FunctionExpression) {
         super.visitFunctionExpression(node);
       } else {
-        super.visitClassExpression(node);
+        super.visitClassExpression(node as ClassExpression);
       }
       _finishScopes();
       scope = scope.parent;
@@ -277,7 +289,6 @@
     case "import":
     case "in":
     case "instanceof":
-    case "let":
     case "new":
     case "return":
     case "super":
diff --git a/pkg/dev_compiler/lib/src/compiler/js_typerep.dart b/pkg/dev_compiler/lib/src/compiler/js_typerep.dart
index a7bd241..f5e355b 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_typerep.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_typerep.dart
@@ -31,9 +31,13 @@
 /// Inhabited by booleans (including JSBool), null, and undefined
 class JSBoolean extends JSType {
   const JSBoolean();
+  @override
   bool get isPrimitive => true;
+  @override
   bool get isPrimitiveInJS => true;
+  @override
   bool get isFalsey => true;
+  @override
   String get primitiveTypeOf => 'boolean';
 }
 
@@ -45,42 +49,59 @@
 /// It's defined in our "dart:_interceptors".
 class JSNumber extends JSType {
   const JSNumber();
+  @override
   bool get isPrimitive => true;
+  @override
   bool get isPrimitiveInJS => true;
+  @override
   bool get isFalsey => true;
+  @override
   String get primitiveTypeOf => 'number';
 }
 
 /// Inhabited by null and undefined
 class JSNull extends JSType {
   const JSNull();
+  @override
   bool get isPrimitive => false;
+  @override
   bool get isPrimitiveInJS => false;
+  @override
   bool get isFalsey => true;
 }
 
 /// Inhabited by objects, null, and undefined
 class JSObject extends JSType {
   const JSObject();
+  @override
   bool get isPrimitive => false;
+  @override
   bool get isPrimitiveInJS => false;
+  @override
   bool get isFalsey => false;
 }
 
 /// Inhabited by strings (including JSString), null, and undefined
 class JSString extends JSType {
   const JSString();
+  @override
   bool get isPrimitive => true;
+  @override
   bool get isPrimitiveInJS => false;
+  @override
   bool get isFalsey => true;
+  @override
   String get primitiveTypeOf => 'string';
 }
 
 /// Inhabitance not statically known
 class JSUnknown extends JSType {
   const JSUnknown();
+  @override
   bool get isPrimitive => false;
+  @override
   bool get isPrimitiveInJS => false;
+  @override
   bool get isFalsey => true;
 }
 
diff --git a/pkg/dev_compiler/lib/src/compiler/js_utils.dart b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
index 74820eb..997702f 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_utils.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
@@ -10,7 +10,7 @@
   if (fn.body is Block && fn.body.statements.length == 1) {
     var stat = fn.body.statements.single;
     if (stat is Return && stat.value is Call) {
-      Call call = stat.value;
+      var call = stat.value as Call;
       var innerFun = call.target;
       if (innerFun is ArrowFun &&
           call.arguments.isEmpty &&
diff --git a/pkg/dev_compiler/lib/src/compiler/module_builder.dart b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
index f3db4fa..a6ebc20 100644
--- a/pkg/dev_compiler/lib/src/compiler/module_builder.dart
+++ b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
@@ -58,7 +58,7 @@
         default:
           throw UsageException(
               'Format $format cannot be combined with '
-              'single-out-file. Only amd and legacy modes are supported.',
+                  'single-out-file. Only amd and legacy modes are supported.',
               '');
       }
     }
@@ -345,10 +345,10 @@
 
 /// Escape [name] to make it into a valid identifier.
 String toJSIdentifier(String name) {
-  if (name.length == 0) return r'$';
+  if (name.isEmpty) return r'$';
 
   // Escape any invalid characters
-  StringBuffer buffer = null;
+  StringBuffer buffer;
   for (int i = 0; i < name.length; i++) {
     var ch = name[i];
     var needsEscape = ch == r'$' || _invalidCharInIdentifier.hasMatch(ch);
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index d9270a2..6a3182d 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -108,6 +108,10 @@
   @protected
   String jsLibraryDebuggerName(Library library);
 
+  /// Debugger friendly names for all parts in a Dart [library].
+  @protected
+  Iterable<String> jsPartDebuggerNames(Library library);
+
   /// Gets the module import URI that contains [library].
   @protected
   String libraryToModule(Library library);
@@ -142,7 +146,7 @@
     if (name == '[]=') {
       _operatorSetResultStack.add(isLastParamMutated()
           ? JS.TemporaryId((formals.last as JS.Identifier).name)
-          : formals.last);
+          : formals.last as JS.Identifier);
     } else {
       _operatorSetResultStack.add(null);
     }
@@ -202,34 +206,21 @@
   ///
   /// For example:
   ///
-  ///     runtimeCall('asInt(#)', expr)
+  ///     runtimeCall('asInt(#)', [<expr>])
   ///
   /// Generates a JS AST representing:
   ///
   ///     dart.asInt(<expr>)
   ///
   @protected
-  JS.Expression runtimeCall(String code, [args]) {
-    if (args != null) {
-      var newArgs = <Object>[runtimeModule];
-      if (args is Iterable) {
-        newArgs.addAll(args);
-      } else {
-        newArgs.add(args);
-      }
-      args = newArgs;
-    } else {
-      args = runtimeModule;
-    }
-    return js.call('#.$code', args);
-  }
+  JS.Expression runtimeCall(String code, [List<Object> args]) =>
+      js.call('#.$code', <Object>[runtimeModule, ...?args]);
 
   /// Calls [runtimeCall] and uses `toStatement()` to convert the resulting
   /// expression into a statement.
   @protected
-  JS.Statement runtimeStatement(String code, [args]) {
-    return runtimeCall(code, args).toStatement();
-  }
+  JS.Statement runtimeStatement(String code, [List<Object> args]) =>
+      runtimeCall(code, args).toStatement();
 
   /// Emits a private name JS Symbol for [name] scoped to the Dart [library].
   ///
@@ -342,7 +333,7 @@
   /// constant instance of a user-defined class stored in [expr].
   @protected
   JS.Expression canonicalizeConstObject(JS.Expression expr) =>
-      cacheConst(runtimeCall('const(#)', expr));
+      cacheConst(runtimeCall('const(#)', [expr]));
 
   /// Emits preamble for the module containing [libraries], and returns the
   /// list of module items for further items to be added.
@@ -486,19 +477,25 @@
 
   void _emitDebuggerExtensionInfo(String name) {
     var properties = <JS.Property>[];
+    var parts = <JS.Property>[];
     _libraries.forEach((library, value) {
       // TODO(jacobr): we could specify a short library name instead of the
       // full library uri if we wanted to save space.
-      properties.add(
-          JS.Property(js.escapedString(jsLibraryDebuggerName(library)), value));
+      var libraryName = js.escapedString(jsLibraryDebuggerName(library));
+      properties.add(JS.Property(libraryName, value));
+      var partNames = jsPartDebuggerNames(library);
+      if (partNames.isNotEmpty) {
+        parts.add(JS.Property(libraryName, js.stringArray(partNames)));
+      }
     });
     var module = JS.ObjectInitializer(properties, multiline: true);
+    var partMap = JS.ObjectInitializer(parts, multiline: true);
 
     // Track the module name for each library in the module.
     // This data is only required for debugging.
     moduleItems.add(js.statement(
-        '#.trackLibraries(#, #, $sourceMapLocationID);',
-        [runtimeModule, js.string(name), module]));
+        '#.trackLibraries(#, #, #, $sourceMapLocationID);',
+        [runtimeModule, js.string(name), module, partMap]));
   }
 
   /// Finishes the module created by [startModule], by combining the preable
@@ -585,10 +582,12 @@
 
   static final instance = _IdentifierFinder();
 
+  @override
   visitIdentifier(node) {
     if (node.name == nameToFind) found = true;
   }
 
+  @override
   visitNode(node) {
     if (!found) super.visitNode(node);
   }
diff --git a/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart b/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart
deleted file mode 100644
index 02d12f2..0000000
--- a/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart
+++ /dev/null
@@ -1,582 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(jmesserly): this file was copied from:
-// https://github.com/flutter/engine/blob/4b01d795feec3ba8231a397a4ec2759954d8216e/flutter_kernel_transformers/lib/track_widget_constructor_locations.dart
-//
-// Longer term, this transform should be injected by Flutter when they building
-// the Flutter-specific `dartdevc` script.
-//
-// The following modifications were made:
-// - remove "package:vm" dependency (only used for one interface)
-// - pass in the class hierarchy that DDC already has available.
-library track_widget_constructor_locations;
-
-// The kernel/src import below that requires lint `ignore_for_file`
-// is a temporary state of things until kernel team builds better api that would
-// replace api used below. This api was made private in an effort to discourage
-// further use.
-// ignore_for_file: implementation_imports
-import 'package:kernel/ast.dart';
-import 'package:kernel/class_hierarchy.dart';
-import 'package:meta/meta.dart';
-
-// Parameter name used to track were widget constructor calls were made from.
-//
-// The parameter name contains a randomly generate hex string to avoid collision
-// with user generated parameters.
-const String _creationLocationParameterName =
-    r'$creationLocationd_0dea112b090073317d4';
-
-/// Name of private field added to the Widget class and any other classes that
-/// implement Widget.
-///
-/// Regardless of what library a class implementing Widget is defined in, the
-/// private field will always be defined in the context of the widget_inspector
-/// library ensuring no name conflicts with regular fields.
-const String _locationFieldName = r'_location';
-
-bool _hasNamedParameter(FunctionNode function, String name) {
-  return function.namedParameters
-      .any((VariableDeclaration parameter) => parameter.name == name);
-}
-
-bool _hasNamedArgument(Arguments arguments, String argumentName) {
-  return arguments.named
-      .any((NamedExpression argument) => argument.name == argumentName);
-}
-
-VariableDeclaration _getNamedParameter(
-  FunctionNode function,
-  String parameterName,
-) {
-  for (VariableDeclaration parameter in function.namedParameters) {
-    if (parameter.name == parameterName) {
-      return parameter;
-    }
-  }
-  return null;
-}
-
-// TODO(jacobr): find a solution that supports optional positional parameters.
-/// Add the creation location to the arguments list if possible.
-///
-/// Returns whether the creation location argument could be added. We cannot
-/// currently add the named argument for functions with optional positional
-/// parameters as the current scheme requires adding the creation location as a
-/// named parameter. Fortunately that is not a significant issue in practice as
-/// no Widget classes in package:flutter have optional positional parameters.
-/// This code degrades gracefully for constructors with optional positional
-/// parameters by skipping adding the creation location argument rather than
-/// failing.
-void _maybeAddCreationLocationArgument(
-  Arguments arguments,
-  FunctionNode function,
-  Expression creationLocation,
-  Class locationClass,
-) {
-  if (_hasNamedArgument(arguments, _creationLocationParameterName)) {
-    return;
-  }
-  if (!_hasNamedParameter(function, _creationLocationParameterName)) {
-    // TODO(jakemac): We don't apply the transformation to dependencies kernel
-    // outlines, so instead we just assume the named parameter exists.
-    //
-    // The only case in which it shouldn't exist is if the function has optional
-    // positional parameters so it cannot have optional named parameters.
-    if (function.requiredParameterCount !=
-        function.positionalParameters.length) {
-      return;
-    }
-  }
-
-  final NamedExpression namedArgument =
-      new NamedExpression(_creationLocationParameterName, creationLocation);
-  namedArgument.parent = arguments;
-  arguments.named.add(namedArgument);
-}
-
-/// Adds a named parameter to a function if the function does not already have
-/// a named parameter with the name or optional positional parameters.
-bool _maybeAddNamedParameter(
-  FunctionNode function,
-  VariableDeclaration variable,
-) {
-  if (_hasNamedParameter(function, _creationLocationParameterName)) {
-    // Gracefully handle if this method is called on a function that has already
-    // been transformed.
-    return false;
-  }
-  // Function has optional positional parameters so cannot have optional named
-  // parameters.
-  if (function.requiredParameterCount != function.positionalParameters.length) {
-    return false;
-  }
-  variable.parent = function;
-  function.namedParameters.add(variable);
-  return true;
-}
-
-/// Transformer that modifies all calls to Widget constructors to include
-/// a [DebugLocation] parameter specifying the location where the constructor
-/// call was made.
-///
-/// This transformer requires that all Widget constructors have already been
-/// transformed to have a named parameter with the name specified by
-/// `_locationParameterName`.
-class _WidgetCallSiteTransformer extends Transformer {
-  final ClassHierarchy _hierarchy;
-
-  /// The [Widget] class defined in the `package:flutter` library.
-  ///
-  /// Used to perform instanceof checks to determine whether Dart constructor
-  /// calls are creating [Widget] objects.
-  Class _widgetClass;
-
-  /// The [DebugLocation] class defined in the `package:flutter` library.
-  Class _locationClass;
-
-  /// Current factory constructor that node being transformed is inside.
-  ///
-  /// Used to flow the location passed in as an argument to the factory to the
-  /// actual constructor call within the factory.
-  Procedure _currentFactory;
-
-  _WidgetCallSiteTransformer(
-    this._hierarchy, {
-    @required Class widgetClass,
-    @required Class locationClass,
-  })  : _widgetClass = widgetClass,
-        _locationClass = locationClass;
-
-  /// Builds a call to the const constructor of the [DebugLocation]
-  /// object specifying the location where a constructor call was made and
-  /// optionally the locations for all parameters passed in.
-  ///
-  /// Specifying the parameters passed in is an experimental feature. With
-  /// access to the source code of an application you could determine the
-  /// locations of the parameters passed in from the source location of the
-  /// constructor call but it is convenient to bundle the location and names
-  /// of the parameters passed in so that tools can show parameter locations
-  /// without re-parsing the source code.
-  ConstructorInvocation _constructLocation(
-    Location location, {
-    String name,
-    ListLiteral parameterLocations,
-    bool showFile: true,
-  }) {
-    final List<NamedExpression> arguments = <NamedExpression>[
-      new NamedExpression('line', new IntLiteral(location.line)),
-      new NamedExpression('column', new IntLiteral(location.column)),
-    ];
-    if (showFile) {
-      arguments.add(new NamedExpression(
-          'file', new StringLiteral(location.file.toString())));
-    }
-    if (name != null) {
-      arguments.add(new NamedExpression('name', new StringLiteral(name)));
-    }
-    if (parameterLocations != null) {
-      arguments
-          .add(new NamedExpression('parameterLocations', parameterLocations));
-    }
-    return new ConstructorInvocation(
-      _locationClass.constructors.first,
-      new Arguments(<Expression>[], named: arguments),
-      isConst: true,
-    );
-  }
-
-  @override
-  Procedure visitProcedure(Procedure node) {
-    if (node.isFactory) {
-      _currentFactory = node;
-      node.transformChildren(this);
-      _currentFactory = null;
-      return node;
-    }
-    return defaultTreeNode(node);
-  }
-
-  bool _isSubclassOfWidget(Class clazz) {
-    // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
-    // non-deprecated ClassHierarchy constructor.
-    return _hierarchy.isSubclassOf(clazz, _widgetClass);
-  }
-
-  @override
-  StaticInvocation visitStaticInvocation(StaticInvocation node) {
-    node.transformChildren(this);
-    final Procedure target = node.target;
-    if (!target.isFactory) {
-      return node;
-    }
-    final Class constructedClass = target.enclosingClass;
-    if (!_isSubclassOfWidget(constructedClass)) {
-      return node;
-    }
-
-    _addLocationArgument(node, target.function, constructedClass);
-    return node;
-  }
-
-  void _addLocationArgument(InvocationExpression node, FunctionNode function,
-      Class constructedClass) {
-    _maybeAddCreationLocationArgument(
-      node.arguments,
-      function,
-      _computeLocation(node, function, constructedClass),
-      _locationClass,
-    );
-  }
-
-  @override
-  ConstructorInvocation visitConstructorInvocation(ConstructorInvocation node) {
-    node.transformChildren(this);
-
-    final Constructor constructor = node.target;
-    final Class constructedClass = constructor.enclosingClass;
-    if (!_isSubclassOfWidget(constructedClass)) {
-      return node;
-    }
-
-    _addLocationArgument(node, constructor.function, constructedClass);
-    return node;
-  }
-
-  Expression _computeLocation(InvocationExpression node, FunctionNode function,
-      Class constructedClass) {
-    // For factory constructors we need to use the location specified as an
-    // argument to the factory constructor rather than the location
-    // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
-    // non-deprecated ClassHierarchy constructor.
-    if (_currentFactory != null &&
-        _hierarchy.isSubclassOf(
-            constructedClass, _currentFactory.enclosingClass)) {
-      final VariableDeclaration creationLocationParameter = _getNamedParameter(
-        _currentFactory.function,
-        _creationLocationParameterName,
-      );
-      if (creationLocationParameter != null) {
-        return new VariableGet(creationLocationParameter);
-      }
-    }
-
-    final Arguments arguments = node.arguments;
-    final Location location = node.location;
-    final List<ConstructorInvocation> parameterLocations =
-        <ConstructorInvocation>[];
-    final List<VariableDeclaration> parameters = function.positionalParameters;
-    for (int i = 0; i < arguments.positional.length; ++i) {
-      final Expression expression = arguments.positional[i];
-      final VariableDeclaration parameter = parameters[i];
-      parameterLocations.add(_constructLocation(
-        expression.location,
-        name: parameter.name,
-        showFile: false,
-      ));
-    }
-    for (NamedExpression expression in arguments.named) {
-      parameterLocations.add(_constructLocation(
-        expression.location,
-        name: expression.name,
-        showFile: false,
-      ));
-    }
-    return _constructLocation(
-      location,
-      parameterLocations: new ListLiteral(
-        parameterLocations,
-        typeArgument: _locationClass.thisType,
-        isConst: true,
-      ),
-    );
-  }
-}
-
-/// Rewrites all widget constructors and constructor invocations to add a
-/// parameter specifying the location the constructor was called from.
-///
-/// The creation location is stored as a private field named `_location`
-/// on the base widget class and flowed through the constructors using a named
-/// parameter.
-class WidgetCreatorTracker {
-  Class _widgetClass;
-  Class _locationClass;
-
-  /// Marker interface indicating that a private _location field is
-  /// available.
-  Class _hasCreationLocationClass;
-
-  /// The [ClassHierarchy] that should be used after applying this transformer.
-  /// If any class was updated, in general we need to create a new
-  /// [ClassHierarchy] instance, with new dispatch targets; or at least let
-  /// the existing instance know that some of its dispatch tables are not
-  /// valid anymore.
-  final ClassHierarchy hierarchy;
-
-  WidgetCreatorTracker(this.hierarchy);
-
-  void _resolveFlutterClasses(Iterable<Library> libraries) {
-    // If the Widget or Debug location classes have been updated we need to get
-    // the latest version
-    for (Library library in libraries) {
-      final Uri importUri = library.importUri;
-      if (importUri != null && importUri.scheme == 'package') {
-        if (importUri.path == 'flutter/src/widgets/framework.dart' ||
-            importUri.path == 'flutter_web/src/widgets/framework.dart') {
-          for (Class class_ in library.classes) {
-            if (class_.name == 'Widget') {
-              _widgetClass = class_;
-            }
-          }
-        } else {
-          if (importUri.path == 'flutter/src/widgets/widget_inspector.dart' ||
-              importUri.path ==
-                  'flutter_web/src/widgets/widget_inspector.dart') {
-            for (Class class_ in library.classes) {
-              if (class_.name == '_HasCreationLocation') {
-                _hasCreationLocationClass = class_;
-              } else if (class_.name == '_Location') {
-                _locationClass = class_;
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-
-  /// Modify [clazz] to add a field named [_locationFieldName] that is the
-  /// first parameter of all constructors of the class.
-  ///
-  /// This method should only be called for classes that implement but do not
-  /// extend [Widget].
-  void _transformClassImplementingWidget(Class clazz) {
-    if (clazz.fields
-        .any((Field field) => field.name.name == _locationFieldName)) {
-      // This class has already been transformed. Skip
-      return;
-    }
-    clazz.implementedTypes
-        .add(new Supertype(_hasCreationLocationClass, <DartType>[]));
-    // We intentionally use the library context of the _HasCreationLocation
-    // class for the private field even if [clazz] is in a different library
-    // so that all classes implementing Widget behave consistently.
-    final Field locationField = new Field(
-      new Name(
-        _locationFieldName,
-        _hasCreationLocationClass.enclosingLibrary,
-      ),
-      isFinal: true,
-    );
-    clazz.addMember(locationField);
-
-    final Set<Constructor> _handledConstructors =
-        new Set<Constructor>.identity();
-
-    void handleConstructor(Constructor constructor) {
-      if (!_handledConstructors.add(constructor)) {
-        return;
-      }
-      assert(!_hasNamedParameter(
-        constructor.function,
-        _creationLocationParameterName,
-      ));
-      final VariableDeclaration variable = new VariableDeclaration(
-        _creationLocationParameterName,
-        type: _locationClass.thisType,
-      );
-      if (!_maybeAddNamedParameter(constructor.function, variable)) {
-        return;
-      }
-
-      bool hasRedirectingInitializer = false;
-      for (Initializer initializer in constructor.initializers) {
-        if (initializer is RedirectingInitializer) {
-          if (initializer.target.enclosingClass == clazz) {
-            // We need to handle this constructor first or the call to
-            // addDebugLocationArgument bellow will fail due to the named
-            // parameter not yet existing on the constructor.
-            handleConstructor(initializer.target);
-          }
-          _maybeAddCreationLocationArgument(
-            initializer.arguments,
-            initializer.target.function,
-            new VariableGet(variable),
-            _locationClass,
-          );
-          hasRedirectingInitializer = true;
-          break;
-        }
-      }
-      if (!hasRedirectingInitializer) {
-        constructor.initializers.add(new FieldInitializer(
-          locationField,
-          new VariableGet(variable),
-        ));
-        // TODO(jacobr): add an assert verifying the locationField is not
-        // null. Currently, we cannot safely add this assert because we do not
-        // handle Widget classes with optional positional arguments. There are
-        // no Widget classes in the flutter repo with optional positional
-        // arguments but it is possible users could add classes with optional
-        // positional arguments.
-        //
-        // constructor.initializers.add(new AssertInitializer(new AssertStatement(
-        //   new IsExpression(
-        //       new VariableGet(variable), _locationClass.thisType),
-        //   conditionStartOffset: constructor.fileOffset,
-        //   conditionEndOffset: constructor.fileOffset,
-        // )));
-      }
-    }
-
-    // Add named parameters to all constructors.
-    clazz.constructors.forEach(handleConstructor);
-  }
-
-  /// Transform the given [module].
-  void transform(Component module) {
-    final List<Library> libraries = module.libraries;
-
-    if (libraries.isEmpty) {
-      return;
-    }
-
-    _resolveFlutterClasses(libraries);
-
-    if (_widgetClass == null) {
-      // This application doesn't actually use the package:flutter library.
-      return;
-    }
-
-    final Set<Class> transformedClasses = new Set<Class>.identity();
-    final Set<Library> librariesToTransform = new Set<Library>.identity()
-      ..addAll(module.libraries);
-
-    for (Library library in module.libraries) {
-      if (library.isExternal) {
-        continue;
-      }
-      for (Class class_ in library.classes) {
-        _transformWidgetConstructors(
-          librariesToTransform,
-          transformedClasses,
-          class_,
-        );
-      }
-    }
-
-    // Transform call sites to pass the location parameter.
-    final _WidgetCallSiteTransformer callsiteTransformer =
-        new _WidgetCallSiteTransformer(
-      hierarchy,
-      widgetClass: _widgetClass,
-      locationClass: _locationClass,
-    );
-
-    for (Library library in module.libraries) {
-      if (library.isExternal) {
-        continue;
-      }
-      library.transformChildren(callsiteTransformer);
-    }
-  }
-
-  bool _isSubclassOfWidget(Class clazz) {
-    if (clazz == null) {
-      return false;
-    }
-    // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
-    // non-deprecated ClassHierarchy constructor.
-    return hierarchy.isSubclassOf(clazz, _widgetClass);
-  }
-
-  void _transformWidgetConstructors(Set<Library> librariesToBeTransformed,
-      Set<Class> transformedClasses, Class clazz) {
-    if (!_isSubclassOfWidget(clazz) ||
-        !librariesToBeTransformed.contains(clazz.enclosingLibrary) ||
-        !transformedClasses.add(clazz)) {
-      return;
-    }
-
-    // Ensure super classes have been transformed before this class.
-    if (clazz.superclass != null &&
-        !transformedClasses.contains(clazz.superclass)) {
-      _transformWidgetConstructors(
-        librariesToBeTransformed,
-        transformedClasses,
-        clazz.superclass,
-      );
-    }
-
-    for (Procedure procedure in clazz.procedures) {
-      if (procedure.isFactory) {
-        _maybeAddNamedParameter(
-          procedure.function,
-          new VariableDeclaration(
-            _creationLocationParameterName,
-            type: _locationClass.thisType,
-          ),
-        );
-      }
-    }
-
-    // Handle the widget class and classes that implement but do not extend the
-    // widget class.
-    if (!_isSubclassOfWidget(clazz.superclass)) {
-      _transformClassImplementingWidget(clazz);
-      return;
-    }
-
-    final Set<Constructor> _handledConstructors =
-        new Set<Constructor>.identity();
-
-    void handleConstructor(Constructor constructor) {
-      if (!_handledConstructors.add(constructor)) {
-        return;
-      }
-
-      final VariableDeclaration variable = new VariableDeclaration(
-        _creationLocationParameterName,
-        type: _locationClass.thisType,
-      );
-      if (_hasNamedParameter(
-          constructor.function, _creationLocationParameterName)) {
-        // Constructor was already rewritten. TODO(jacobr): is this case actually hit?
-        return;
-      }
-      if (!_maybeAddNamedParameter(constructor.function, variable)) {
-        return;
-      }
-      for (Initializer initializer in constructor.initializers) {
-        if (initializer is RedirectingInitializer) {
-          if (initializer.target.enclosingClass == clazz) {
-            // We need to handle this constructor first or the call to
-            // addDebugLocationArgument could fail due to the named parameter
-            // not existing.
-            handleConstructor(initializer.target);
-          }
-
-          _maybeAddCreationLocationArgument(
-            initializer.arguments,
-            initializer.target.function,
-            new VariableGet(variable),
-            _locationClass,
-          );
-        } else if (initializer is SuperInitializer &&
-            _isSubclassOfWidget(initializer.target.enclosingClass)) {
-          _maybeAddCreationLocationArgument(
-            initializer.arguments,
-            initializer.target.function,
-            new VariableGet(variable),
-            _locationClass,
-          );
-        }
-      }
-    }
-
-    clazz.constructors.forEach(handleConstructor);
-  }
-}
diff --git a/pkg/dev_compiler/lib/src/js_ast/builder.dart b/pkg/dev_compiler/lib/src/js_ast/builder.dart
index fc44cb9..2d0dd51 100644
--- a/pkg/dev_compiler/lib/src/js_ast/builder.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/builder.dart
@@ -432,11 +432,12 @@
 }
 
 class MiniJsParserError {
-  MiniJsParserError(this.parser, this.message) {}
+  MiniJsParserError(this.parser, this.message);
 
   final MiniJsParser parser;
   final String message;
 
+  @override
   String toString() {
     int pos = parser.lastPosition;
 
@@ -491,7 +492,7 @@
   }
 
   int lastCategory = NONE;
-  String lastToken = null;
+  String lastToken;
   int lastPosition = 0;
   int position = 0;
   bool skippedNewline = false; // skipped newline in last getToken?
@@ -1550,12 +1551,12 @@
     //     for (let variable of Expression) Statement
     //
     Statement finishFor(Expression init) {
-      Expression condition = null;
+      Expression condition;
       if (!acceptCategory(SEMICOLON)) {
         condition = parseExpression();
         expectCategory(SEMICOLON);
       }
-      Expression update = null;
+      Expression update;
       if (!acceptCategory(RPAREN)) {
         update = parseExpression();
         expectCategory(RPAREN);
@@ -1613,9 +1614,9 @@
   Statement parseTry() {
     expectCategory(LBRACE);
     Block body = parseBlock();
-    Catch catchPart = null;
+    Catch catchPart;
     if (acceptString('catch')) catchPart = parseCatch();
-    Block finallyPart = null;
+    Block finallyPart;
     if (acceptString('finally')) {
       expectCategory(LBRACE);
       finallyPart = parseBlock();
@@ -1626,7 +1627,7 @@
   }
 
   SwitchCase parseSwitchClause() {
-    Expression expression = null;
+    Expression expression;
     if (acceptString('case')) {
       expression = parseExpression();
       expectCategory(COLON);
@@ -1689,7 +1690,7 @@
 
   ClassExpression parseClass() {
     Identifier name = parseIdentifier();
-    Expression heritage = null;
+    Expression heritage;
     if (acceptString('extends')) {
       heritage = parseConditional();
     }
@@ -1718,7 +1719,7 @@
 
     bool isGetter = lastToken == 'get';
     bool isSetter = lastToken == 'set';
-    Expression name = null;
+    Expression name;
     if (isGetter || isSetter) {
       var token = lastToken;
       getToken();
diff --git a/pkg/dev_compiler/lib/src/js_ast/nodes.dart b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
index 9cd3b7b..36d2368 100644
--- a/pkg/dev_compiler/lib/src/js_ast/nodes.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
@@ -101,121 +101,197 @@
     return null;
   }
 
+  @override
   T visitProgram(Program node) => visitNode(node);
 
   T visitStatement(Statement node) => visitModuleItem(node);
   T visitLoop(Loop node) => visitStatement(node);
   T visitJump(Statement node) => visitStatement(node);
 
+  @override
   T visitBlock(Block node) => visitStatement(node);
+  @override
   T visitDebuggerStatement(node) => visitStatement(node);
+  @override
   T visitExpressionStatement(ExpressionStatement node) => visitStatement(node);
+  @override
   T visitEmptyStatement(EmptyStatement node) => visitStatement(node);
+  @override
   T visitIf(If node) => visitStatement(node);
+  @override
   T visitFor(For node) => visitLoop(node);
+  @override
   T visitForIn(ForIn node) => visitLoop(node);
+  @override
   T visitForOf(ForOf node) => visitLoop(node);
+  @override
   T visitWhile(While node) => visitLoop(node);
+  @override
   T visitDo(Do node) => visitLoop(node);
+  @override
   T visitContinue(Continue node) => visitJump(node);
+  @override
   T visitBreak(Break node) => visitJump(node);
+  @override
   T visitReturn(Return node) => visitJump(node);
+  @override
   T visitThrow(Throw node) => visitJump(node);
+  @override
   T visitTry(Try node) => visitStatement(node);
+  @override
   T visitSwitch(Switch node) => visitStatement(node);
+  @override
   T visitFunctionDeclaration(FunctionDeclaration node) => visitStatement(node);
+  @override
   T visitLabeledStatement(LabeledStatement node) => visitStatement(node);
+  @override
   T visitLiteralStatement(LiteralStatement node) => visitStatement(node);
 
+  @override
   T visitCatch(Catch node) => visitNode(node);
+  @override
   T visitSwitchCase(SwitchCase node) => visitNode(node);
 
   T visitExpression(Expression node) => visitNode(node);
 
+  @override
   T visitLiteralExpression(LiteralExpression node) => visitExpression(node);
+  @override
   T visitVariableDeclarationList(VariableDeclarationList node) =>
       visitExpression(node);
+  @override
   T visitAssignment(Assignment node) => visitExpression(node);
+  @override
   T visitVariableInitialization(VariableInitialization node) =>
       visitExpression(node);
 
+  @override
   T visitConditional(Conditional node) => visitExpression(node);
+  @override
   T visitNew(New node) => visitExpression(node);
+  @override
   T visitCall(Call node) => visitExpression(node);
+  @override
   T visitBinary(Binary node) => visitExpression(node);
+  @override
   T visitPrefix(Prefix node) => visitExpression(node);
+  @override
   T visitPostfix(Postfix node) => visitExpression(node);
+  @override
   T visitSpread(Spread node) => visitPrefix(node);
+  @override
   T visitYield(Yield node) => visitExpression(node);
+  @override
   T visitAccess(PropertyAccess node) => visitExpression(node);
 
+  @override
   T visitIdentifier(Identifier node) => visitExpression(node);
+  @override
   T visitThis(This node) => visitExpression(node);
+  @override
   T visitSuper(Super node) => visitExpression(node);
 
+  @override
   T visitRestParameter(RestParameter node) => visitNode(node);
 
+  @override
   T visitNamedFunction(NamedFunction node) => visitExpression(node);
   T visitFunctionExpression(FunctionExpression node) => visitExpression(node);
+  @override
   T visitFun(Fun node) => visitFunctionExpression(node);
+  @override
   T visitArrowFun(ArrowFun node) => visitFunctionExpression(node);
 
   T visitLiteral(Literal node) => visitExpression(node);
 
+  @override
   T visitLiteralBool(LiteralBool node) => visitLiteral(node);
+  @override
   T visitLiteralString(LiteralString node) => visitLiteral(node);
+  @override
   T visitLiteralNumber(LiteralNumber node) => visitLiteral(node);
+  @override
   T visitLiteralNull(LiteralNull node) => visitLiteral(node);
 
+  @override
   T visitArrayInitializer(ArrayInitializer node) => visitExpression(node);
+  @override
   T visitArrayHole(ArrayHole node) => visitExpression(node);
+  @override
   T visitObjectInitializer(ObjectInitializer node) => visitExpression(node);
+  @override
   T visitProperty(Property node) => visitNode(node);
+  @override
   T visitRegExpLiteral(RegExpLiteral node) => visitExpression(node);
+  @override
   T visitTemplateString(TemplateString node) => visitExpression(node);
+  @override
   T visitTaggedTemplate(TaggedTemplate node) => visitExpression(node);
 
+  @override
   T visitClassDeclaration(ClassDeclaration node) => visitStatement(node);
+  @override
   T visitClassExpression(ClassExpression node) => visitExpression(node);
+  @override
   T visitMethod(Method node) => visitProperty(node);
 
   T visitModuleItem(ModuleItem node) => visitNode(node);
+  @override
   T visitImportDeclaration(ImportDeclaration node) => visitModuleItem(node);
+  @override
   T visitExportDeclaration(ExportDeclaration node) => visitModuleItem(node);
+  @override
   T visitExportClause(ExportClause node) => visitNode(node);
+  @override
   T visitNameSpecifier(NameSpecifier node) => visitNode(node);
+  @override
   T visitModule(Module node) => visitNode(node);
 
   T visitInterpolatedNode(InterpolatedNode node) => visitNode(node);
 
+  @override
   T visitInterpolatedExpression(InterpolatedExpression node) =>
       visitInterpolatedNode(node);
+  @override
   T visitInterpolatedLiteral(InterpolatedLiteral node) =>
       visitInterpolatedNode(node);
+  @override
   T visitInterpolatedParameter(InterpolatedParameter node) =>
       visitInterpolatedNode(node);
+  @override
   T visitInterpolatedSelector(InterpolatedSelector node) =>
       visitInterpolatedNode(node);
+  @override
   T visitInterpolatedStatement(InterpolatedStatement node) =>
       visitInterpolatedNode(node);
+  @override
   T visitInterpolatedMethod(InterpolatedMethod node) =>
       visitInterpolatedNode(node);
+  @override
   T visitInterpolatedIdentifier(InterpolatedIdentifier node) =>
       visitInterpolatedNode(node);
 
   // Ignore comments by default.
+  @override
   T visitComment(Comment node) => null;
+  @override
   T visitCommentExpression(CommentExpression node) => null;
 
+  @override
   T visitAwait(Await node) => visitExpression(node);
+  @override
   T visitDartYield(DartYield node) => visitStatement(node);
 
   T visitBindingPattern(BindingPattern node) => visitNode(node);
+  @override
   T visitArrayBindingPattern(ArrayBindingPattern node) =>
       visitBindingPattern(node);
+  @override
   T visitObjectBindingPattern(ObjectBindingPattern node) =>
       visitBindingPattern(node);
+  @override
   T visitDestructuredVariable(DestructuredVariable node) => visitNode(node);
+  @override
   T visitSimpleBindingPattern(SimpleBindingPattern node) => visitNode(node);
 }
 
@@ -255,6 +331,7 @@
   }
 
   // For debugging
+  @override
   String toString() {
     var context = SimpleJavaScriptPrintingContext();
     var opts = JavaScriptPrintingOptions(allowKeywordsInProperties: true);
@@ -280,18 +357,23 @@
 
   Program(this.body, {this.scriptTag, this.name});
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitProgram(this);
+  @override
   void visitChildren(NodeVisitor visitor) {
-    for (ModuleItem statement in body) statement.accept(visitor);
+    for (ModuleItem statement in body) {
+      statement.accept(visitor);
+    }
   }
 
+  @override
   Program _clone() => Program(body);
 }
 
 abstract class Statement extends ModuleItem {
   static Statement from(List<Statement> statements) {
     // TODO(jmesserly): empty block singleton? Should this use empty statement?
-    if (statements.length == 0) return Block([]);
+    if (statements.isEmpty) return Block([]);
     if (statements.length == 1) return statements[0];
     return Block(statements);
   }
@@ -317,7 +399,9 @@
     return shadows(names) ? Block([this], isScope: true) : this;
   }
 
+  @override
   Statement toStatement() => this;
+  @override
   Statement toReturn() => Block([this, Return()]);
 
   Block toBlock() => Block([this]);
@@ -355,11 +439,16 @@
       ..sourceInformation = sourceInformation;
   }
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitBlock(this);
+  @override
   void visitChildren(NodeVisitor visitor) {
-    for (Statement statement in statements) statement.accept(visitor);
+    for (Statement statement in statements) {
+      statement.accept(visitor);
+    }
   }
 
+  @override
   Block _clone() => Block(statements);
 }
 
@@ -373,19 +462,25 @@
     return expression is VariableDeclarationList && expression.shadows(names);
   }
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitExpressionStatement(this);
+  @override
   void visitChildren(NodeVisitor visitor) {
     expression.accept(visitor);
   }
 
+  @override
   ExpressionStatement _clone() => ExpressionStatement(expression);
 }
 
 class EmptyStatement extends Statement {
   EmptyStatement();
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitEmptyStatement(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
+  @override
   EmptyStatement _clone() => EmptyStatement();
 }
 
@@ -403,14 +498,17 @@
 
   bool get hasElse => otherwise != null;
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitIf(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     condition.accept(visitor);
     then.accept(visitor);
     if (otherwise != null) otherwise.accept(visitor);
   }
 
+  @override
   If _clone() => If(condition, then, otherwise);
 }
 
@@ -426,8 +524,10 @@
 
   For(this.init, this.condition, this.update, Statement body) : super(body);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitFor(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     if (init != null) init.accept(visitor);
     if (condition != null) condition.accept(visitor);
@@ -435,6 +535,7 @@
     body.accept(visitor);
   }
 
+  @override
   For _clone() => For(init, condition, update, body);
 }
 
@@ -446,14 +547,17 @@
 
   ForIn(this.leftHandSide, this.object, Statement body) : super(body);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitForIn(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     leftHandSide.accept(visitor);
     object.accept(visitor);
     body.accept(visitor);
   }
 
+  @override
   ForIn _clone() => ForIn(leftHandSide, object, body);
 }
 
@@ -465,14 +569,17 @@
 
   ForOf(this.leftHandSide, this.iterable, Statement body) : super(body);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitForOf(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     leftHandSide.accept(visitor);
     iterable.accept(visitor);
     body.accept(visitor);
   }
 
+  @override
   ForIn _clone() => ForIn(leftHandSide, iterable, body);
 }
 
@@ -481,13 +588,16 @@
 
   While(this.condition, Statement body) : super(body);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitWhile(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     condition.accept(visitor);
     body.accept(visitor);
   }
 
+  @override
   While _clone() => While(condition, body);
 }
 
@@ -496,13 +606,16 @@
 
   Do(Statement body, this.condition) : super(body);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitDo(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     body.accept(visitor);
     condition.accept(visitor);
   }
 
+  @override
   Do _clone() => Do(body, condition);
 }
 
@@ -511,9 +624,12 @@
 
   Continue(this.targetLabel);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitContinue(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
 
+  @override
   Continue _clone() => Continue(targetLabel);
 }
 
@@ -522,28 +638,35 @@
 
   Break(this.targetLabel);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitBreak(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
 
+  @override
   Break _clone() => Break(targetLabel);
 }
 
 class Return extends Statement {
   final Expression value; // Can be null.
 
-  Return([this.value = null]);
+  Return([this.value]);
 
   @override
   bool get alwaysReturns => true;
 
+  @override
   Statement toReturn() => this;
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitReturn(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     if (value != null) value.accept(visitor);
   }
 
+  @override
   Return _clone() => Return(value);
 
   static bool foundIn(Node node) {
@@ -557,10 +680,12 @@
 
 class _ReturnFinder extends BaseVisitor {
   bool found = false;
+  @override
   visitReturn(Return node) {
     found = true;
   }
 
+  @override
   visitNode(Node node) {
     if (!found) super.visitNode(node);
   }
@@ -571,12 +696,15 @@
 
   Throw(this.expression);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitThrow(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     expression.accept(visitor);
   }
 
+  @override
   Throw _clone() => Throw(expression);
 }
 
@@ -589,14 +717,17 @@
     assert(catchPart != null || finallyPart != null);
   }
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitTry(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     body.accept(visitor);
     if (catchPart != null) catchPart.accept(visitor);
     if (finallyPart != null) finallyPart.accept(visitor);
   }
 
+  @override
   Try _clone() => Try(body, catchPart, finallyPart);
 }
 
@@ -606,13 +737,16 @@
 
   Catch(this.declaration, this.body);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitCatch(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     declaration.accept(visitor);
     body.accept(visitor);
   }
 
+  @override
   Catch _clone() => Catch(declaration, body);
 }
 
@@ -622,13 +756,18 @@
 
   Switch(this.key, this.cases);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitSwitch(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     key.accept(visitor);
-    for (var clause in cases) clause.accept(visitor);
+    for (var clause in cases) {
+      clause.accept(visitor);
+    }
   }
 
+  @override
   Switch _clone() => Switch(key, cases);
 }
 
@@ -641,13 +780,16 @@
 
   bool get isDefault => expression == null;
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitSwitchCase(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     expression?.accept(visitor);
     body.accept(visitor);
   }
 
+  @override
   SwitchCase _clone() => SwitchCase(expression, body);
 }
 
@@ -657,13 +799,16 @@
 
   FunctionDeclaration(this.name, this.function);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitFunctionDeclaration(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     name.accept(visitor);
     function.accept(visitor);
   }
 
+  @override
   FunctionDeclaration _clone() => FunctionDeclaration(name, function);
 }
 
@@ -673,12 +818,15 @@
 
   LabeledStatement(this.label, this.body);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitLabeledStatement(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     body.accept(visitor);
   }
 
+  @override
   LabeledStatement _clone() => LabeledStatement(label, body);
 }
 
@@ -687,9 +835,12 @@
 
   LiteralStatement(this.code);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitLiteralStatement(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
 
+  @override
   LiteralStatement _clone() => LiteralStatement(code);
 }
 
@@ -702,12 +853,15 @@
 
   DartYield(this.expression, this.hasStar);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitDartYield(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     expression.accept(visitor);
   }
 
+  @override
   DartYield _clone() => DartYield(expression, hasStar);
 }
 
@@ -715,7 +869,7 @@
   Expression();
 
   factory Expression.binary(List<Expression> exprs, String op) {
-    Expression comma = null;
+    Expression comma;
     for (var node in exprs) {
       comma = (comma == null) ? node : Binary(op, comma, node);
     }
@@ -724,7 +878,9 @@
 
   int get precedenceLevel;
 
+  @override
   Statement toStatement() => ExpressionStatement(toVoidExpression());
+  @override
   Statement toReturn() => Return(this);
 
   // TODO(jmesserly): make this return a Yield?
@@ -748,18 +904,24 @@
   LiteralExpression(this.template) : inputs = const [];
   LiteralExpression.withData(this.template, this.inputs);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitLiteralExpression(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     if (inputs != null) {
-      for (Expression expr in inputs) expr.accept(visitor);
+      for (Expression expr in inputs) {
+        expr.accept(visitor);
+      }
     }
   }
 
+  @override
   LiteralExpression _clone() => LiteralExpression.withData(template, inputs);
 
   // Code that uses JS must take care of operator precedences, and
   // put parenthesis if needed.
+  @override
   int get precedenceLevel => PRIMARY;
 }
 
@@ -782,22 +944,28 @@
   /// Analogous to the predicate [Statement.shadows].
   bool shadows(Set<String> names) {
     if (keyword == 'var') return false;
-    for (var d in declarations) if (d.declaration.shadows(names)) return true;
+    for (var d in declarations) {
+      if (d.declaration.shadows(names)) return true;
+    }
     return false;
   }
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) =>
       visitor.visitVariableDeclarationList(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     for (VariableInitialization declaration in declarations) {
       declaration.accept(visitor);
     }
   }
 
+  @override
   VariableDeclarationList _clone() =>
       VariableDeclarationList(keyword, declarations);
 
+  @override
   int get precedenceLevel => EXPRESSION;
 }
 
@@ -809,17 +977,21 @@
   Assignment(this.leftHandSide, this.value) : op = null;
   Assignment.compound(this.leftHandSide, this.op, this.value);
 
+  @override
   int get precedenceLevel => ASSIGNMENT;
 
   bool get isCompound => op != null;
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitAssignment(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     leftHandSide.accept(visitor);
     if (value != null) value.accept(visitor);
   }
 
+  @override
   Assignment _clone() => Assignment.compound(leftHandSide, op, value);
 }
 
@@ -830,13 +1002,17 @@
   /// [value] may be null.
   VariableInitialization(this.declaration, this.value);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) =>
       visitor.visitVariableInitialization(this);
 
+  @override
   VariableInitialization _clone() => VariableInitialization(declaration, value);
 
+  @override
   int get precedenceLevel => ASSIGNMENT;
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     declaration.accept(visitor);
     if (value != null) value.accept(visitor);
@@ -872,13 +1048,16 @@
     assert(name != null || structure != null);
   }
 
+  @override
   bool shadows(Set<String> names) {
     return (name?.shadows(names) ?? false) ||
         (structure?.shadows(names) ?? false);
   }
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) =>
       visitor.visitDestructuredVariable(this);
+  @override
   void visitChildren(NodeVisitor visitor) {
     name?.accept(visitor);
     structure?.accept(visitor);
@@ -902,13 +1081,19 @@
   final List<DestructuredVariable> variables;
   BindingPattern(this.variables);
 
+  @override
   bool shadows(Set<String> names) {
-    for (var v in variables) if (v.shadows(names)) return true;
+    for (var v in variables) {
+      if (v.shadows(names)) return true;
+    }
     return false;
   }
 
+  @override
   void visitChildren(NodeVisitor visitor) {
-    for (DestructuredVariable v in variables) v.accept(visitor);
+    for (DestructuredVariable v in variables) {
+      v.accept(visitor);
+    }
   }
 }
 
@@ -918,6 +1103,7 @@
       : name = name,
         super([DestructuredVariable(name: name)]);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) =>
       visitor.visitSimpleBindingPattern(this);
 
@@ -933,6 +1119,7 @@
 
 class ObjectBindingPattern extends BindingPattern {
   ObjectBindingPattern(List<DestructuredVariable> variables) : super(variables);
+  @override
   T accept<T>(NodeVisitor<T> visitor) =>
       visitor.visitObjectBindingPattern(this);
 
@@ -945,6 +1132,7 @@
 
 class ArrayBindingPattern extends BindingPattern {
   ArrayBindingPattern(List<DestructuredVariable> variables) : super(variables);
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitArrayBindingPattern(this);
 
   /// Avoid parenthesis when pretty-printing.
@@ -961,16 +1149,20 @@
 
   Conditional(this.condition, this.then, this.otherwise);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitConditional(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     condition.accept(visitor);
     then.accept(visitor);
     otherwise.accept(visitor);
   }
 
+  @override
   Conditional _clone() => Conditional(condition, then, otherwise);
 
+  @override
   int get precedenceLevel => ASSIGNMENT;
 }
 
@@ -980,25 +1172,34 @@
 
   Call(this.target, this.arguments);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitCall(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     target.accept(visitor);
-    for (Expression arg in arguments) arg.accept(visitor);
+    for (Expression arg in arguments) {
+      arg.accept(visitor);
+    }
   }
 
+  @override
   Call _clone() => Call(target, arguments);
 
+  @override
   int get precedenceLevel => CALL;
 }
 
 class New extends Call {
   New(Expression cls, List<Expression> arguments) : super(cls, arguments);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitNew(this);
 
+  @override
   New _clone() => New(target, arguments);
 
+  @override
   int get precedenceLevel => ACCESS;
 }
 
@@ -1009,17 +1210,22 @@
 
   Binary(this.op, this.left, this.right);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitBinary(this);
 
+  @override
   Binary _clone() => Binary(op, left, right);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     left.accept(visitor);
     right.accept(visitor);
   }
 
+  @override
   bool get isCommaOperator => op == ',';
 
+  @override
   Expression toVoidExpression() {
     if (!isCommaOperator) return super.toVoidExpression();
     var l = left.toVoidExpression();
@@ -1028,16 +1234,19 @@
     return Binary(',', l, r);
   }
 
+  @override
   Statement toStatement() {
     if (!isCommaOperator) return super.toStatement();
     return Block([left.toStatement(), right.toStatement()]);
   }
 
+  @override
   Statement toReturn() {
     if (!isCommaOperator) return super.toReturn();
     return Block([left.toStatement(), right.toReturn()]);
   }
 
+  @override
   Statement toYieldStatement({bool star = false}) {
     if (!isCommaOperator) return super.toYieldStatement(star: star);
     return Block([left.toStatement(), right.toYieldStatement(star: star)]);
@@ -1060,6 +1269,7 @@
     }
   }
 
+  @override
   int get precedenceLevel {
     // TODO(floitsch): switch to constant map.
     switch (op) {
@@ -1110,14 +1320,18 @@
 
   Prefix(this.op, this.argument);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitPrefix(this);
 
+  @override
   Prefix _clone() => Prefix(op, argument);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     argument.accept(visitor);
   }
 
+  @override
   int get precedenceLevel => UNARY;
 }
 
@@ -1127,7 +1341,9 @@
 class Spread extends Prefix {
   Spread(Expression operand) : super('...', operand);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitSpread(this);
+  @override
   Spread _clone() => Spread(argument);
 }
 
@@ -1137,14 +1353,18 @@
 
   Postfix(this.op, this.argument);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitPostfix(this);
 
+  @override
   Postfix _clone() => Postfix(op, argument);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     argument.accept(visitor);
   }
 
+  @override
   int get precedenceLevel => UNARY;
 }
 
@@ -1163,12 +1383,18 @@
   }
   static RegExp _identifierRE = RegExp(r'^[A-Za-z_$][A-Za-z_$0-9]*$');
 
+  @override
   bool shadows(Set<String> names) => names.contains(name);
 
+  @override
   Identifier _clone() => Identifier(name, allowRename: allowRename);
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitIdentifier(this);
+  @override
   int get precedenceLevel => PRIMARY;
+  @override
   String get parameterName => name;
+  @override
   void visitChildren(NodeVisitor visitor) {}
 }
 
@@ -1178,31 +1404,45 @@
 
   RestParameter(this.parameter);
 
+  @override
   bool shadows(Set<String> names) => names.contains(parameter.name);
 
+  @override
   RestParameter _clone() => RestParameter(parameter);
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitRestParameter(this);
+  @override
   void visitChildren(NodeVisitor visitor) {
     parameter.accept(visitor);
   }
 
+  @override
   int get precedenceLevel => PRIMARY;
+  @override
   String get parameterName => parameter.parameterName;
 }
 
 class This extends Expression {
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitThis(this);
+  @override
   This _clone() => This();
+  @override
   int get precedenceLevel => PRIMARY;
+  @override
   void visitChildren(NodeVisitor visitor) {}
 }
 
 // `super` is more restricted in the ES6 spec, but for simplicity we accept
 // it anywhere that `this` is accepted.
 class Super extends Expression {
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitSuper(this);
+  @override
   Super _clone() => Super();
+  @override
   int get precedenceLevel => PRIMARY;
+  @override
   void visitChildren(NodeVisitor visitor) {}
 }
 
@@ -1216,15 +1456,19 @@
 
   NamedFunction(this.name, this.function, [this.immediatelyInvoked = false]);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitNamedFunction(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     name.accept(visitor);
     function.accept(visitor);
   }
 
+  @override
   NamedFunction _clone() => NamedFunction(name, function, immediatelyInvoked);
 
+  @override
   int get precedenceLevel =>
       immediatelyInvoked ? EXPRESSION : PRIMARY_LOW_PRECEDENCE;
 }
@@ -1235,7 +1479,9 @@
 }
 
 class Fun extends FunctionExpression {
+  @override
   final List<Parameter> params;
+  @override
   final Block body;
 
   /** Whether this is a JS generator (`function*`) that may contain `yield`. */
@@ -1247,34 +1493,48 @@
       {this.isGenerator = false,
       this.asyncModifier = const AsyncModifier.sync()});
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitFun(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
-    for (Parameter param in params) param.accept(visitor);
+    for (Parameter param in params) {
+      param.accept(visitor);
+    }
     body.accept(visitor);
   }
 
+  @override
   Fun _clone() =>
       Fun(params, body, isGenerator: isGenerator, asyncModifier: asyncModifier);
 
+  @override
   int get precedenceLevel => PRIMARY_LOW_PRECEDENCE;
 }
 
 class ArrowFun extends FunctionExpression {
+  @override
   final List<Parameter> params;
+  @override
   final body; // Expression or Block
 
   ArrowFun(this.params, this.body);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitArrowFun(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
-    for (Parameter param in params) param.accept(visitor);
+    for (Parameter param in params) {
+      param.accept(visitor);
+    }
     body.accept(visitor);
   }
 
+  @override
   int get precedenceLevel => PRIMARY_LOW_PRECEDENCE;
 
+  @override
   ArrowFun _clone() => ArrowFun(params, body);
 }
 
@@ -1305,6 +1565,7 @@
       : isAsync = false,
         isYielding = true,
         description = "sync*";
+  @override
   toString() => description;
 }
 
@@ -1318,21 +1579,27 @@
   PropertyAccess.indexed(this.receiver, int index)
       : selector = LiteralNumber('$index');
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitAccess(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     receiver.accept(visitor);
     selector.accept(visitor);
   }
 
+  @override
   PropertyAccess _clone() => PropertyAccess(receiver, selector);
 
+  @override
   int get precedenceLevel => ACCESS;
 }
 
 abstract class Literal extends Expression {
+  @override
   void visitChildren(NodeVisitor visitor) {}
 
+  @override
   int get precedenceLevel => PRIMARY;
 }
 
@@ -1341,15 +1608,19 @@
 
   LiteralBool(this.value);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitLiteralBool(this);
   // [visitChildren] inherited from [Literal].
+  @override
   LiteralBool _clone() => LiteralBool(value);
 }
 
 class LiteralNull extends Literal {
   LiteralNull();
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitLiteralNull(this);
+  @override
   LiteralNull _clone() => LiteralNull();
 }
 
@@ -1371,7 +1642,9 @@
   /// Gets the value inside the string without the beginning and end quotes.
   String get valueWithoutQuotes => value.substring(1, value.length - 1);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitLiteralString(this);
+  @override
   LiteralString _clone() => LiteralString(value);
 }
 
@@ -1380,13 +1653,16 @@
 
   LiteralNumber(this.value);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitLiteralNumber(this);
+  @override
   LiteralNumber _clone() => LiteralNumber(value);
 
   /**
    * Use a different precedence level depending on whether the value contains a
    * dot to ensure we generate `(1).toString()` and `1.0.toString()`.
    */
+  @override
   int get precedenceLevel => value.contains('.') ? PRIMARY : UNARY;
 }
 
@@ -1396,14 +1672,20 @@
 
   ArrayInitializer(this.elements, {this.multiline = false});
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitArrayInitializer(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
-    for (Expression element in elements) element.accept(visitor);
+    for (Expression element in elements) {
+      element.accept(visitor);
+    }
   }
 
+  @override
   ArrayInitializer _clone() => ArrayInitializer(elements);
 
+  @override
   int get precedenceLevel => PRIMARY;
 }
 
@@ -1412,12 +1694,16 @@
  * For example the list [1, , , 2] would contain two holes.
  */
 class ArrayHole extends Expression {
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitArrayHole(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {}
 
+  @override
   ArrayHole _clone() => ArrayHole();
 
+  @override
   int get precedenceLevel => PRIMARY;
 }
 
@@ -1431,14 +1717,20 @@
   ObjectInitializer(this.properties, {bool multiline = false})
       : _multiline = multiline;
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitObjectInitializer(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
-    for (Property init in properties) init.accept(visitor);
+    for (Property init in properties) {
+      init.accept(visitor);
+    }
   }
 
+  @override
   ObjectInitializer _clone() => ObjectInitializer(properties);
 
+  @override
   int get precedenceLevel => PRIMARY;
   /**
    * If set to true, forces a vertical layout when using the [Printer].
@@ -1456,13 +1748,16 @@
 
   Property(this.name, this.value);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitProperty(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     name.accept(visitor);
     value.accept(visitor);
   }
 
+  @override
   Property _clone() => Property(name, value);
 }
 
@@ -1492,16 +1787,20 @@
     assert(strings.length == interpolations.length + 1);
   }
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitTemplateString(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     for (var element in interpolations) {
       element.accept(visitor);
     }
   }
 
+  @override
   TemplateString _clone() => TemplateString(strings, interpolations);
 
+  @override
   int get precedenceLevel => PRIMARY;
 }
 
@@ -1512,15 +1811,19 @@
 
   TaggedTemplate(this.tag, this.template);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitTaggedTemplate(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     tag.accept(visitor);
     template.accept(visitor);
   }
 
+  @override
   TaggedTemplate _clone() => TaggedTemplate(tag, template);
 
+  @override
   int get precedenceLevel => CALL;
 }
 
@@ -1536,14 +1839,18 @@
 
   Yield(this.value, {this.star = false});
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitYield(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     if (value != null) value.accept(visitor);
   }
 
+  @override
   Yield _clone() => Yield(value);
 
+  @override
   int get precedenceLevel => YIELD;
 }
 
@@ -1552,8 +1859,11 @@
 
   ClassDeclaration(this.classExpr);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitClassDeclaration(this);
+  @override
   visitChildren(NodeVisitor visitor) => classExpr.accept(visitor);
+  @override
   ClassDeclaration _clone() => ClassDeclaration(classExpr);
 }
 
@@ -1564,23 +1874,30 @@
 
   ClassExpression(this.name, this.heritage, this.methods);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitClassExpression(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     name.accept(visitor);
     if (heritage != null) heritage.accept(visitor);
-    for (Method element in methods) element.accept(visitor);
+    for (Method element in methods) {
+      element.accept(visitor);
+    }
   }
 
   @override
   ClassDeclaration toStatement() => ClassDeclaration(this);
 
+  @override
   ClassExpression _clone() => ClassExpression(name, heritage, methods);
 
+  @override
   int get precedenceLevel => PRIMARY_LOW_PRECEDENCE;
 }
 
 class Method extends Node implements Property {
+  @override
   final Expression name;
   final Fun function;
   final bool isGetter;
@@ -1589,20 +1906,24 @@
 
   Method(this.name, this.function,
       {this.isGetter = false, this.isSetter = false, this.isStatic = false}) {
-    assert(!isGetter || function.params.length == 0);
+    assert(!isGetter || function.params.isEmpty);
     assert(!isSetter || function.params.length == 1);
     assert(!isGetter && !isSetter || !function.isGenerator);
   }
 
+  @override
   Fun get value => function;
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitMethod(this);
 
+  @override
   void visitChildren(NodeVisitor visitor) {
     name.accept(visitor);
     function.accept(visitor);
   }
 
+  @override
   Method _clone() => Method(name, function,
       isGetter: isGetter, isSetter: isSetter, isStatic: isStatic);
 }
@@ -1616,76 +1937,103 @@
 }
 
 class InterpolatedExpression extends Expression with InterpolatedNode {
+  @override
   final nameOrPosition;
 
   InterpolatedExpression(this.nameOrPosition);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) =>
       visitor.visitInterpolatedExpression(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
+  @override
   InterpolatedExpression _clone() => InterpolatedExpression(nameOrPosition);
 
+  @override
   int get precedenceLevel => PRIMARY;
 }
 
 class InterpolatedLiteral extends Literal with InterpolatedNode {
+  @override
   final nameOrPosition;
 
   InterpolatedLiteral(this.nameOrPosition);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitInterpolatedLiteral(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
+  @override
   InterpolatedLiteral _clone() => InterpolatedLiteral(nameOrPosition);
 }
 
 class InterpolatedParameter extends Expression
     with InterpolatedNode
     implements Identifier {
+  @override
   final nameOrPosition;
 
+  @override
   String get name {
     throw "InterpolatedParameter.name must not be invoked";
   }
 
+  @override
   String get parameterName {
     throw "InterpolatedParameter.parameterName must not be invoked";
   }
 
+  @override
   bool shadows(Set<String> names) => false;
 
+  @override
   bool get allowRename => false;
 
   InterpolatedParameter(this.nameOrPosition);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) =>
       visitor.visitInterpolatedParameter(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
+  @override
   InterpolatedParameter _clone() => InterpolatedParameter(nameOrPosition);
 
+  @override
   int get precedenceLevel => PRIMARY;
 }
 
 class InterpolatedSelector extends Expression with InterpolatedNode {
+  @override
   final nameOrPosition;
 
   InterpolatedSelector(this.nameOrPosition);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) =>
       visitor.visitInterpolatedSelector(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
+  @override
   InterpolatedSelector _clone() => InterpolatedSelector(nameOrPosition);
 
+  @override
   int get precedenceLevel => PRIMARY;
 }
 
 class InterpolatedStatement extends Statement with InterpolatedNode {
+  @override
   final nameOrPosition;
 
   InterpolatedStatement(this.nameOrPosition);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) =>
       visitor.visitInterpolatedStatement(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
+  @override
   InterpolatedStatement _clone() => InterpolatedStatement(nameOrPosition);
 }
 
@@ -1693,20 +2041,31 @@
 class InterpolatedMethod extends Expression
     with InterpolatedNode
     implements Method {
+  @override
   final nameOrPosition;
 
   InterpolatedMethod(this.nameOrPosition);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitInterpolatedMethod(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
+  @override
   InterpolatedMethod _clone() => InterpolatedMethod(nameOrPosition);
 
+  @override
   int get precedenceLevel => PRIMARY;
+  @override
   Expression get name => throw _unsupported;
+  @override
   Fun get value => throw _unsupported;
+  @override
   bool get isGetter => throw _unsupported;
+  @override
   bool get isSetter => throw _unsupported;
+  @override
   bool get isStatic => throw _unsupported;
+  @override
   Fun get function => throw _unsupported;
   Error get _unsupported =>
       UnsupportedError('$runtimeType does not support this member.');
@@ -1715,21 +2074,30 @@
 class InterpolatedIdentifier extends Expression
     with InterpolatedNode
     implements Identifier {
+  @override
   final nameOrPosition;
 
   InterpolatedIdentifier(this.nameOrPosition);
 
+  @override
   bool shadows(Set<String> names) => false;
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) =>
       visitor.visitInterpolatedIdentifier(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
+  @override
   InterpolatedIdentifier _clone() => InterpolatedIdentifier(nameOrPosition);
 
+  @override
   int get precedenceLevel => PRIMARY;
+  @override
   String get name => throw '$runtimeType does not support this member.';
+  @override
   String get parameterName =>
       throw '$runtimeType does not support this member.';
+  @override
   bool get allowRename => false;
 }
 
@@ -1744,10 +2112,14 @@
 
   RegExpLiteral(this.pattern);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitRegExpLiteral(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
+  @override
   RegExpLiteral _clone() => RegExpLiteral(pattern);
 
+  @override
   int get precedenceLevel => PRIMARY;
 }
 
@@ -1763,9 +2135,13 @@
 
   Await(this.expression);
 
+  @override
   int get precedenceLevel => UNARY;
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitAwait(this);
+  @override
   void visitChildren(NodeVisitor visitor) => expression.accept(visitor);
+  @override
   Await _clone() => Await(expression);
 }
 
@@ -1780,9 +2156,12 @@
 
   Comment(this.comment);
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitComment(this);
+  @override
   Comment _clone() => Comment(comment);
 
+  @override
   void visitChildren(NodeVisitor visitor) {}
 }
 
@@ -1798,16 +2177,23 @@
 
   CommentExpression(this.comment, this.expression);
 
+  @override
   int get precedenceLevel => PRIMARY;
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitCommentExpression(this);
+  @override
   CommentExpression _clone() => CommentExpression(comment, expression);
 
+  @override
   void visitChildren(NodeVisitor visitor) => expression.accept(visitor);
 }
 
 class DebuggerStatement extends Statement {
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitDebuggerStatement(this);
+  @override
   DebuggerStatement _clone() => DebuggerStatement();
+  @override
   void visitChildren(NodeVisitor visitor) {}
 }
 
@@ -1842,14 +2228,19 @@
     return null;
   }
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitImportDeclaration(this);
+  @override
   void visitChildren(NodeVisitor visitor) {
     if (namedImports != null) {
-      for (NameSpecifier name in namedImports) name.accept(visitor);
+      for (NameSpecifier name in namedImports) {
+        name.accept(visitor);
+      }
     }
     from.accept(visitor);
   }
 
+  @override
   ImportDeclaration _clone() => ImportDeclaration(
       defaultBinding: defaultBinding, namedImports: namedImports, from: from);
 }
@@ -1897,8 +2288,11 @@
     throw StateError('invalid export declaration');
   }
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitExportDeclaration(this);
+  @override
   visitChildren(NodeVisitor visitor) => exported.accept(visitor);
+  @override
   ExportDeclaration _clone() =>
       ExportDeclaration(exported, isDefault: isDefault);
 }
@@ -1916,12 +2310,17 @@
   /** True if this is an `export *`. */
   bool get exportStar => exports.length == 1 && exports[0].isStar;
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitExportClause(this);
+  @override
   void visitChildren(NodeVisitor visitor) {
-    for (NameSpecifier name in exports) name.accept(visitor);
+    for (NameSpecifier name in exports) {
+      name.accept(visitor);
+    }
     if (from != null) from.accept(visitor);
   }
 
+  @override
   ExportClause _clone() => ExportClause(exports, from: from);
 }
 
@@ -1936,8 +2335,11 @@
   /** True if this is a `* as someName` specifier. */
   bool get isStar => name == null;
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitNameSpecifier(this);
+  @override
   void visitChildren(NodeVisitor visitor) {}
+  @override
   NameSpecifier _clone() => NameSpecifier(name, asName: asName);
 }
 
@@ -1951,10 +2353,15 @@
   final List<ModuleItem> body;
   Module(this.body, {this.name});
 
+  @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitModule(this);
+  @override
   void visitChildren(NodeVisitor visitor) {
-    for (ModuleItem item in body) item.accept(visitor);
+    for (ModuleItem item in body) {
+      item.accept(visitor);
+    }
   }
 
+  @override
   Module _clone() => Module(body);
 }
diff --git a/pkg/dev_compiler/lib/src/js_ast/printer.dart b/pkg/dev_compiler/lib/src/js_ast/printer.dart
index bdd29bd..f4a9717 100644
--- a/pkg/dev_compiler/lib/src/js_ast/printer.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/printer.dart
@@ -47,6 +47,7 @@
 class SimpleJavaScriptPrintingContext extends JavaScriptPrintingContext {
   final StringBuffer buffer = StringBuffer();
 
+  @override
   void emit(String string) {
     buffer.write(string);
   }
@@ -129,10 +130,10 @@
     if (!shouldCompressOutput) out(" ");
   }
 
-  String lastAddedString = null;
+  String lastAddedString;
   int get lastCharCode {
     if (lastAddedString == null) return 0;
-    assert(lastAddedString.length != "");
+    assert(lastAddedString.isNotEmpty);
     return lastAddedString.codeUnitAt(lastAddedString.length - 1);
   }
 
@@ -233,6 +234,7 @@
     nodes.forEach(visit);
   }
 
+  @override
   visitProgram(Program program) {
     if (program.scriptTag != null) {
       out('#!${program.scriptTag}\n');
@@ -284,14 +286,17 @@
     if (needsNewline) lineOut();
   }
 
+  @override
   visitBlock(Block block) {
     blockOut(block, true, true);
   }
 
+  @override
   visitDebuggerStatement(node) {
     outIndentLn('debugger;');
   }
 
+  @override
   visitExpressionStatement(ExpressionStatement expressionStatement) {
     indent();
     visitNestedExpression(expressionStatement.expression, EXPRESSION,
@@ -299,6 +304,7 @@
     outSemicolonLn();
   }
 
+  @override
   visitEmptyStatement(EmptyStatement nop) {
     outIndentLn(";");
   }
@@ -352,10 +358,12 @@
     }
   }
 
+  @override
   visitIf(If node) {
     ifOut(node, true);
   }
 
+  @override
   visitFor(For loop) {
     outIndent("for");
     spaceOut();
@@ -380,6 +388,7 @@
     blockBody(loop.body, needsSeparation: false, needsNewline: true);
   }
 
+  @override
   visitForIn(ForIn loop) {
     outIndent("for");
     spaceOut();
@@ -394,6 +403,7 @@
     blockBody(loop.body, needsSeparation: false, needsNewline: true);
   }
 
+  @override
   visitForOf(ForOf loop) {
     outIndent("for");
     spaceOut();
@@ -408,6 +418,7 @@
     blockBody(loop.body, needsSeparation: false, needsNewline: true);
   }
 
+  @override
   visitWhile(While loop) {
     outIndent("while");
     spaceOut();
@@ -418,6 +429,7 @@
     blockBody(loop.body, needsSeparation: false, needsNewline: true);
   }
 
+  @override
   visitDo(Do loop) {
     outIndent("do");
     if (blockBody(loop.body, needsSeparation: true, needsNewline: false)) {
@@ -434,6 +446,7 @@
     outSemicolonLn();
   }
 
+  @override
   visitContinue(Continue node) {
     if (node.targetLabel == null) {
       outIndent("continue");
@@ -443,6 +456,7 @@
     outSemicolonLn();
   }
 
+  @override
   visitBreak(Break node) {
     if (node.targetLabel == null) {
       outIndent("break");
@@ -452,6 +466,7 @@
     outSemicolonLn();
   }
 
+  @override
   visitReturn(Return node) {
     if (node.value == null) {
       outIndent("return");
@@ -464,6 +479,7 @@
     outSemicolonLn();
   }
 
+  @override
   visitDartYield(DartYield node) {
     if (node.hasStar) {
       outIndent("yield*");
@@ -476,6 +492,7 @@
     outSemicolonLn();
   }
 
+  @override
   visitThrow(Throw node) {
     outIndent("throw");
     pendingSpace = true;
@@ -484,6 +501,7 @@
     outSemicolonLn();
   }
 
+  @override
   visitTry(Try node) {
     outIndent("try");
     blockBody(node.body, needsSeparation: true, needsNewline: false);
@@ -499,6 +517,7 @@
     }
   }
 
+  @override
   visitCatch(Catch node) {
     spaceOut();
     out("catch");
@@ -510,6 +529,7 @@
     blockBody(node.body, needsSeparation: false, needsNewline: false);
   }
 
+  @override
   visitSwitch(Switch node) {
     outIndent("switch");
     spaceOut();
@@ -525,6 +545,7 @@
     outIndentLn("}");
   }
 
+  @override
   visitSwitchCase(SwitchCase node) {
     if (node.isDefault) {
       outIndentLn("default:");
@@ -535,11 +556,12 @@
           newInForInit: false, newAtStatementBegin: false);
       outLn(":");
     }
-    if (!node.body.statements.isEmpty) {
+    if (node.body.statements.isNotEmpty) {
       blockOut(node.body, true, true);
     }
   }
 
+  @override
   visitLabeledStatement(LabeledStatement node) {
     outIndent("${node.label}:");
     blockBody(node.body, needsSeparation: false, needsNewline: true);
@@ -578,6 +600,7 @@
     localNamer.leaveScope();
   }
 
+  @override
   visitFunctionDeclaration(FunctionDeclaration declaration) {
     indent();
     var f = declaration.function;
@@ -616,6 +639,7 @@
     }
   }
 
+  @override
   visitVariableDeclarationList(VariableDeclarationList list) {
     // Note: keyword can be null for non-static field declarations.
     if (list.keyword != null) {
@@ -626,6 +650,7 @@
         newInForInit: inForInit, newAtStatementBegin: false);
   }
 
+  @override
   visitArrayBindingPattern(ArrayBindingPattern node) {
     out("[");
     visitCommaSeparated(node.variables, EXPRESSION,
@@ -633,6 +658,7 @@
     out("]");
   }
 
+  @override
   visitObjectBindingPattern(ObjectBindingPattern node) {
     out("{");
     visitCommaSeparated(node.variables, EXPRESSION,
@@ -640,6 +666,7 @@
     out("}");
   }
 
+  @override
   visitDestructuredVariable(DestructuredVariable node) {
     var name = node.name;
     var property = node.property;
@@ -668,10 +695,12 @@
     }
   }
 
+  @override
   visitSimpleBindingPattern(SimpleBindingPattern node) {
     visit(node.name);
   }
 
+  @override
   visitAssignment(Assignment assignment) {
     visitNestedExpression(assignment.leftHandSide, LEFT_HAND_SIDE,
         newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
@@ -686,6 +715,7 @@
     }
   }
 
+  @override
   visitVariableInitialization(VariableInitialization init) {
     visitNestedExpression(init.declaration, LEFT_HAND_SIDE,
         newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
@@ -698,6 +728,7 @@
     }
   }
 
+  @override
   visitConditional(Conditional cond) {
     visitNestedExpression(cond.condition, LOGICAL_OR,
         newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
@@ -714,6 +745,7 @@
         newInForInit: inForInit, newAtStatementBegin: false);
   }
 
+  @override
   visitNew(New node) {
     out("new ");
     inNewTarget = true;
@@ -726,6 +758,7 @@
     out(")");
   }
 
+  @override
   visitCall(Call call) {
     visitNestedExpression(call.target, LEFT_HAND_SIDE,
         newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
@@ -735,6 +768,7 @@
     out(")");
   }
 
+  @override
   visitBinary(Binary binary) {
     Expression left = binary.left;
     Expression right = binary.right;
@@ -835,6 +869,7 @@
         newInForInit: inForInit, newAtStatementBegin: false);
   }
 
+  @override
   visitPrefix(Prefix unary) {
     String op = unary.op;
     switch (op) {
@@ -863,8 +898,10 @@
         newInForInit: inForInit, newAtStatementBegin: false);
   }
 
+  @override
   visitSpread(Spread unary) => visitPrefix(unary);
 
+  @override
   visitYield(Yield yield) {
     out(yield.star ? "yield*" : "yield");
     if (yield.value == null) return;
@@ -873,24 +910,29 @@
         newInForInit: inForInit, newAtStatementBegin: false);
   }
 
+  @override
   visitPostfix(Postfix postfix) {
     visitNestedExpression(postfix.argument, LEFT_HAND_SIDE,
         newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
     out(postfix.op);
   }
 
+  @override
   visitThis(This node) {
     out("this");
   }
 
+  @override
   visitSuper(Super node) {
     out("super");
   }
 
+  @override
   visitIdentifier(Identifier node) {
     out(localNamer.getName(node));
   }
 
+  @override
   visitRestParameter(RestParameter node) {
     out('...');
     visitIdentifier(node.parameter);
@@ -921,6 +963,7 @@
     return options.allowKeywordsInProperties || field != '"super"';
   }
 
+  @override
   visitAccess(PropertyAccess access) {
     // Normally we can omit parens on the receiver if it is a Call, even though
     // Call expressions have lower precedence. However this optimization doesn't
@@ -943,6 +986,7 @@
     propertyNameOut(access.selector, inAccess: true);
   }
 
+  @override
   visitNamedFunction(NamedFunction namedFunction) {
     var f = namedFunction.function;
     context.enterNode(f);
@@ -950,10 +994,12 @@
     context.exitNode(f);
   }
 
+  @override
   visitFun(Fun fun) {
     functionOut(fun, null);
   }
 
+  @override
   visitArrowFun(ArrowFun fun) {
     localNamer.enterScope(fun);
     if (fun.params.length == 1 && fun.params[0] is Identifier) {
@@ -984,14 +1030,17 @@
     localNamer.leaveScope();
   }
 
+  @override
   visitLiteralBool(LiteralBool node) {
     out(node.value ? "true" : "false");
   }
 
+  @override
   visitLiteralString(LiteralString node) {
     out(node.value);
   }
 
+  @override
   visitLiteralNumber(LiteralNumber node) {
     int charCode = node.value.codeUnitAt(0);
     if (charCode == charCodes.$MINUS && lastCharCode == charCodes.$MINUS) {
@@ -1000,10 +1049,12 @@
     out(node.value);
   }
 
+  @override
   visitLiteralNull(LiteralNull node) {
     out("null");
   }
 
+  @override
   visitArrayInitializer(ArrayInitializer node) {
     out("[");
     indentMore();
@@ -1038,10 +1089,12 @@
     out("]");
   }
 
+  @override
   visitArrayHole(ArrayHole node) {
     throw "Unreachable";
   }
 
+  @override
   visitObjectInitializer(ObjectInitializer node) {
     List<Property> properties = node.properties;
     out("{");
@@ -1067,6 +1120,7 @@
     out("}");
   }
 
+  @override
   visitProperty(Property node) {
     propertyNameOut(node.name);
     out(":");
@@ -1075,10 +1129,12 @@
         newInForInit: false, newAtStatementBegin: false);
   }
 
+  @override
   visitRegExpLiteral(RegExpLiteral node) {
     out(node.pattern);
   }
 
+  @override
   visitTemplateString(TemplateString node) {
     out('`');
     int len = node.interpolations.length;
@@ -1092,17 +1148,20 @@
     out('`');
   }
 
+  @override
   visitTaggedTemplate(TaggedTemplate node) {
     visit(node.tag);
     visit(node.template);
   }
 
+  @override
   visitClassDeclaration(ClassDeclaration node) {
     indent();
     visit(node.classExpr);
     lineOut();
   }
 
+  @override
   visitClassExpression(ClassExpression node) {
     localNamer.enterScope(node);
     out('class ');
@@ -1130,6 +1189,7 @@
     localNamer.leaveScope();
   }
 
+  @override
   visitMethod(Method node) {
     if (node.isStatic) {
       out('static ');
@@ -1189,6 +1249,7 @@
     }
   }
 
+  @override
   visitImportDeclaration(ImportDeclaration node) {
     indent();
     out('import ');
@@ -1204,6 +1265,7 @@
     outSemicolonLn();
   }
 
+  @override
   visitExportDeclaration(ExportDeclaration node) {
     indent();
     out('export ');
@@ -1213,6 +1275,7 @@
     outSemicolonLn();
   }
 
+  @override
   visitExportClause(ExportClause node) {
     nameSpecifierListOut(node.exports, true);
     fromClauseOut(node.from);
@@ -1221,7 +1284,7 @@
   nameSpecifierListOut(List<NameSpecifier> names, bool export) {
     if (names == null) return;
 
-    if (names.length == 1 && names[0].name == '*') {
+    if (names.length == 1 && names[0].name.name == '*') {
       nameSpecifierOut(names[0], export);
       return;
     }
@@ -1243,11 +1306,12 @@
     if (from != null) {
       out(' from');
       spaceOut();
-      visit(from);
+      out("'${from.valueWithoutQuotes}.js'");
     }
   }
 
   /// This is unused, see [nameSpecifierOut].
+  @override
   visitNameSpecifier(NameSpecifier node) {
     throw UnsupportedError('visitNameSpecifier');
   }
@@ -1276,10 +1340,12 @@
     }
   }
 
+  @override
   visitModule(Module node) {
     visitAll(node.body);
   }
 
+  @override
   visitLiteralExpression(LiteralExpression node) {
     String template = node.template;
     List<Expression> inputs = node.inputs;
@@ -1298,6 +1364,7 @@
     }
   }
 
+  @override
   visitLiteralStatement(LiteralStatement node) {
     outLn(node.code);
   }
@@ -1306,28 +1373,36 @@
     out('#${node.nameOrPosition}');
   }
 
+  @override
   visitInterpolatedExpression(InterpolatedExpression node) =>
       visitInterpolatedNode(node);
 
+  @override
   visitInterpolatedLiteral(InterpolatedLiteral node) =>
       visitInterpolatedNode(node);
 
+  @override
   visitInterpolatedParameter(InterpolatedParameter node) =>
       visitInterpolatedNode(node);
 
+  @override
   visitInterpolatedSelector(InterpolatedSelector node) =>
       visitInterpolatedNode(node);
 
+  @override
   visitInterpolatedMethod(InterpolatedMethod node) =>
       visitInterpolatedNode(node);
 
+  @override
   visitInterpolatedIdentifier(InterpolatedIdentifier node) =>
       visitInterpolatedNode(node);
 
+  @override
   visitInterpolatedStatement(InterpolatedStatement node) {
     outLn('#${node.nameOrPosition}');
   }
 
+  @override
   void visitComment(Comment node) {
     if (shouldCompressOutput) return;
     String comment = node.comment.trim();
@@ -1341,6 +1416,7 @@
     }
   }
 
+  @override
   void visitCommentExpression(CommentExpression node) {
     if (shouldCompressOutput) return;
     String comment = node.comment.trim();
@@ -1353,6 +1429,7 @@
     visit(node.expression);
   }
 
+  @override
   void visitAwait(Await node) {
     out("await ");
     visit(node.expression);
@@ -1389,39 +1466,49 @@
     }
   }
 
+  @override
   void visitFunctionDeclaration(FunctionDeclaration declaration) {
     // Note that we don't bother collecting the name of the function.
     collectVarsInFunction(declaration.function);
   }
 
+  @override
   void visitNamedFunction(NamedFunction namedFunction) {
     // Note that we don't bother collecting the name of the function.
     collectVarsInFunction(namedFunction.function);
   }
 
+  @override
   void visitMethod(Method declaration) {
     collectVarsInFunction(declaration.function);
   }
 
+  @override
   void visitFun(Fun fun) {
     collectVarsInFunction(fun);
   }
 
+  @override
   void visitArrowFun(ArrowFun fun) {
     collectVarsInFunction(fun);
   }
 
+  @override
   void visitClassExpression(ClassExpression node) {
     // Note that we don't bother collecting the name of the class.
     if (node.heritage != null) node.heritage.accept(this);
-    for (Method method in node.methods) method.accept(this);
+    for (Method method in node.methods) {
+      method.accept(this);
+    }
   }
 
+  @override
   void visitCatch(Catch node) {
     declareVariable(node.declaration);
     node.body.accept(this);
   }
 
+  @override
   void visitVariableInitialization(VariableInitialization node) {
     // TODO(jmesserly): add ES6 support. Currently not needed because
     // dart2js does not emit ES6 rest param or destructuring.
@@ -1443,30 +1530,46 @@
 
   DanglingElseVisitor(this.context);
 
+  @override
   bool visitProgram(Program node) => false;
 
+  @override
   bool visitNode(Node node) {
     context.error("Forgot node: $node");
     return null;
   }
 
+  @override
   bool visitBlock(Block node) => false;
+  @override
   bool visitExpressionStatement(ExpressionStatement node) => false;
+  @override
   bool visitEmptyStatement(EmptyStatement node) => false;
+  @override
   bool visitIf(If node) {
     if (!node.hasElse) return true;
     return node.otherwise.accept(this);
   }
 
+  @override
   bool visitFor(For node) => node.body.accept(this);
+  @override
   bool visitForIn(ForIn node) => node.body.accept(this);
+  @override
   bool visitForOf(ForOf node) => node.body.accept(this);
+  @override
   bool visitWhile(While node) => node.body.accept(this);
+  @override
   bool visitDo(Do node) => false;
+  @override
   bool visitContinue(Continue node) => false;
+  @override
   bool visitBreak(Break node) => false;
+  @override
   bool visitReturn(Return node) => false;
+  @override
   bool visitThrow(Throw node) => false;
+  @override
   bool visitTry(Try node) {
     if (node.finallyPart != null) {
       return node.finallyPart.accept(this);
@@ -1475,14 +1578,22 @@
     }
   }
 
+  @override
   bool visitCatch(Catch node) => node.body.accept(this);
+  @override
   bool visitSwitch(Switch node) => false;
+  @override
   bool visitSwitchCase(SwitchCase node) => false;
+  @override
   bool visitFunctionDeclaration(FunctionDeclaration node) => false;
+  @override
   bool visitLabeledStatement(LabeledStatement node) => node.body.accept(this);
+  @override
   bool visitLiteralStatement(LiteralStatement node) => true;
+  @override
   bool visitClassDeclaration(ClassDeclaration node) => false;
 
+  @override
   bool visitExpression(Expression node) => false;
 }
 
@@ -1493,8 +1604,11 @@
 }
 
 class IdentityNamer implements LocalNamer {
+  @override
   String getName(Identifier node) => node.name;
+  @override
   void enterScope(Node node) {}
+  @override
   void leaveScope() {}
 }
 
@@ -1505,6 +1619,7 @@
   int parameterNumber = 0;
   int variableNumber = 0;
 
+  @override
   void enterScope(Node node) {
     var vars = VarCollector();
     node.accept(vars);
@@ -1515,12 +1630,14 @@
     vars.forEachParam(declareParameter);
   }
 
+  @override
   void leaveScope() {
     maps.removeLast();
     variableNumber = variableNumberStack.removeLast();
     parameterNumber = parameterNumberStack.removeLast();
   }
 
+  @override
   String getName(Identifier node) {
     String oldName = node.name;
     // Go from inner scope to outer looking for mapping of name.
@@ -1625,6 +1742,7 @@
 abstract class VariableDeclarationVisitor extends BaseVisitor<void> {
   declare(Identifier node);
 
+  @override
   visitFunctionExpression(FunctionExpression node) {
     node.params.forEach(_scanVariableBinding);
     node.body.accept(this);
@@ -1638,45 +1756,55 @@
     }
   }
 
+  @override
   visitRestParameter(RestParameter node) {
     _scanVariableBinding(node.parameter);
     super.visitRestParameter(node);
   }
 
+  @override
   visitDestructuredVariable(DestructuredVariable node) {
     var name = node.name;
     if (name is Identifier) _scanVariableBinding(name);
     super.visitDestructuredVariable(node);
   }
 
+  @override
   visitSimpleBindingPattern(SimpleBindingPattern node) {
     _scanVariableBinding(node.name);
     super.visitSimpleBindingPattern(node);
   }
 
+  @override
   visitVariableInitialization(VariableInitialization node) {
     _scanVariableBinding(node.declaration);
     if (node.value != null) node.value.accept(this);
   }
 
+  @override
   visitCatch(Catch node) {
     declare(node.declaration);
     node.body.accept(this);
   }
 
+  @override
   visitFunctionDeclaration(FunctionDeclaration node) {
     declare(node.name);
     node.function.accept(this);
   }
 
+  @override
   visitNamedFunction(NamedFunction node) {
     declare(node.name);
     node.function.accept(this);
   }
 
+  @override
   visitClassExpression(ClassExpression node) {
     declare(node.name);
     if (node.heritage != null) node.heritage.accept(this);
-    for (Method element in node.methods) element.accept(this);
+    for (Method element in node.methods) {
+      element.accept(this);
+    }
   }
 }
diff --git a/pkg/dev_compiler/lib/src/js_ast/source_map_printer.dart b/pkg/dev_compiler/lib/src/js_ast/source_map_printer.dart
index af5a5b6..d9e7da8 100644
--- a/pkg/dev_compiler/lib/src/js_ast/source_map_printer.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/source_map_printer.dart
@@ -9,12 +9,14 @@
 class NodeEnd {
   final SourceLocation end;
   NodeEnd(this.end);
+  @override
   toString() => '#<NodeEnd $end>';
 }
 
 class NodeSpan {
   final SourceLocation start, end;
   NodeSpan(this.start, this.end);
+  @override
   toString() => '#<NodeSpan $start to $end>';
 }
 
@@ -22,6 +24,7 @@
   final SourceLocation start, end;
   final Expression expression;
   HoverComment(this.expression, this.start, this.end);
+  @override
   toString() => '#<HoverComment `$expression` @ $start to $end>';
 }
 
diff --git a/pkg/dev_compiler/lib/src/js_ast/template.dart b/pkg/dev_compiler/lib/src/js_ast/template.dart
index 178b15c..6363cd6 100644
--- a/pkg/dev_compiler/lib/src/js_ast/template.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/template.dart
@@ -176,6 +176,7 @@
     throw UnimplementedError('visit${node.runtimeType}');
   }
 
+  @override
   Instantiator<Expression> visitInterpolatedExpression(
       InterpolatedExpression node) {
     var nameOrPosition = node.nameOrPosition;
@@ -212,7 +213,9 @@
     for (var instantiator in makers) {
       var result = instantiator(args);
       if (result is Iterable) {
-        for (var e in result) exprs.add(e as T);
+        for (var e in result) {
+          exprs.add(e as T);
+        }
       } else {
         exprs.add(result as T);
       }
@@ -220,6 +223,7 @@
     return exprs;
   }
 
+  @override
   Instantiator<Literal> visitInterpolatedLiteral(InterpolatedLiteral node) {
     var nameOrPosition = node.nameOrPosition;
     return (arguments) {
@@ -230,6 +234,7 @@
     };
   }
 
+  @override
   Instantiator visitInterpolatedParameter(InterpolatedParameter node) {
     var nameOrPosition = node.nameOrPosition;
     return (arguments) {
@@ -248,6 +253,7 @@
     };
   }
 
+  @override
   Instantiator<Expression> visitInterpolatedSelector(
       InterpolatedSelector node) {
     // A selector is an expression, as in `a[selector]`.
@@ -263,6 +269,7 @@
     };
   }
 
+  @override
   Instantiator<Statement> visitInterpolatedStatement(
       InterpolatedStatement node) {
     var nameOrPosition = node.nameOrPosition;
@@ -274,6 +281,7 @@
     };
   }
 
+  @override
   Instantiator visitInterpolatedMethod(InterpolatedMethod node) {
     var nameOrPosition = node.nameOrPosition;
     return (arguments) {
@@ -289,6 +297,7 @@
     };
   }
 
+  @override
   Instantiator<Identifier> visitInterpolatedIdentifier(
       InterpolatedIdentifier node) {
     var nameOrPosition = node.nameOrPosition;
@@ -320,6 +329,7 @@
     return visit(node);
   }
 
+  @override
   Instantiator<Program> visitProgram(Program node) {
     var instantiators = node.body.map(visitSplayableStatement).toList();
     return (a) => Program(splayStatements(instantiators, a));
@@ -331,7 +341,9 @@
       var node = instantiator(arguments);
       if (node is EmptyStatement) continue;
       if (node is Iterable) {
-        for (var n in node) statements.add(n as Statement);
+        for (var n in node) {
+          statements.add(n as Statement);
+        }
       } else if (node is Block && !node.isScope) {
         statements.addAll(node.statements);
       } else {
@@ -341,22 +353,27 @@
     return statements;
   }
 
+  @override
   Instantiator<Block> visitBlock(Block node) {
     var instantiators = node.statements.map(visitSplayableStatement).toList();
     return (a) => Block(splayStatements(instantiators, a));
   }
 
+  @override
   Instantiator<Statement> visitExpressionStatement(ExpressionStatement node) {
-    Instantiator<Expression> makeExpression = visit(node.expression);
+    var makeExpression = visit(node.expression) as Instantiator<Expression>;
     return (a) => makeExpression(a).toStatement();
   }
 
+  @override
   Instantiator<DebuggerStatement> visitDebuggerStatement(node) =>
       (a) => DebuggerStatement();
 
+  @override
   Instantiator<EmptyStatement> visitEmptyStatement(EmptyStatement node) =>
       (a) => EmptyStatement();
 
+  @override
   Instantiator<Statement> visitIf(If node) {
     var condition = node.condition;
     if (condition is InterpolatedExpression) {
@@ -368,8 +385,8 @@
 
   Instantiator<Statement> visitIfConditionalCompilation(
       If node, InterpolatedExpression condition) {
-    Instantiator<Statement> makeThen = visit(node.then);
-    Instantiator<Statement> makeOtherwise = visit(node.otherwise);
+    var makeThen = visit(node.then) as Instantiator<Statement>;
+    var makeOtherwise = visit(node.otherwise) as Instantiator<Statement>;
     return (arguments) {
       // Allow bools to be used for conditional compliation.
       var nameOrPosition = condition.nameOrPosition;
@@ -383,111 +400,132 @@
   }
 
   Instantiator<Statement> visitIfNormal(If node) {
-    Instantiator<Expression> makeCondition = visit(node.condition);
-    Instantiator<Statement> makeThen = visit(node.then);
-    Instantiator<Statement> makeOtherwise = visit(node.otherwise);
+    var makeCondition = visit(node.condition) as Instantiator<Expression>;
+    var makeThen = visit(node.then) as Instantiator<Statement>;
+    var makeOtherwise = visit(node.otherwise) as Instantiator<Statement>;
     return (a) => If(makeCondition(a), makeThen(a), makeOtherwise(a));
   }
 
+  @override
   Instantiator<Statement> visitFor(For node) {
-    Instantiator<Expression> makeInit = visitNullable(node.init);
-    Instantiator<Expression> makeCondition = visitNullable(node.condition);
-    Instantiator<Expression> makeUpdate = visitNullable(node.update);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeInit = visitNullable(node.init) as Instantiator<Expression>;
+    var makeCondition =
+        visitNullable(node.condition) as Instantiator<Expression>;
+    var makeUpdate = visitNullable(node.update) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => For(makeInit(a), makeCondition(a),
         makeUpdate(a)?.toVoidExpression(), makeBody(a));
   }
 
+  @override
   Instantiator<ForIn> visitForIn(ForIn node) {
-    Instantiator<Expression> makeLeftHandSide = visit(node.leftHandSide);
-    Instantiator<Expression> makeObject = visit(node.object);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeLeftHandSide = visit(node.leftHandSide) as Instantiator<Expression>;
+    var makeObject = visit(node.object) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => ForIn(makeLeftHandSide(a), makeObject(a), makeBody(a));
   }
 
+  @override
   Instantiator<ForOf> visitForOf(ForOf node) {
-    Instantiator<Expression> makeLeftHandSide = visit(node.leftHandSide);
-    Instantiator<Expression> makeObject = visit(node.iterable);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeLeftHandSide = visit(node.leftHandSide) as Instantiator<Expression>;
+    var makeObject = visit(node.iterable) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => ForOf(makeLeftHandSide(a), makeObject(a), makeBody(a));
   }
 
+  @override
   Instantiator<While> visitWhile(While node) {
-    Instantiator<Expression> makeCondition = visit(node.condition);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeCondition = visit(node.condition) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => While(makeCondition(a), makeBody(a));
   }
 
+  @override
   Instantiator<Do> visitDo(Do node) {
-    Instantiator<Statement> makeBody = visit(node.body);
-    Instantiator<Expression> makeCondition = visit(node.condition);
+    var makeBody = visit(node.body) as Instantiator<Statement>;
+    var makeCondition = visit(node.condition) as Instantiator<Expression>;
     return (a) => Do(makeBody(a), makeCondition(a));
   }
 
+  @override
   Instantiator<Continue> visitContinue(Continue node) =>
       (a) => Continue(node.targetLabel);
 
+  @override
   Instantiator<Break> visitBreak(Break node) => (a) => Break(node.targetLabel);
 
+  @override
   Instantiator<Statement> visitReturn(Return node) {
     if (node.value == null) return (args) => Return();
-    Instantiator<Expression> makeExpression = visit(node.value);
+    var makeExpression = visit(node.value) as Instantiator<Expression>;
     return (a) => makeExpression(a).toReturn();
   }
 
+  @override
   Instantiator<DartYield> visitDartYield(DartYield node) {
-    Instantiator<Expression> makeExpression = visit(node.expression);
+    var makeExpression = visit(node.expression) as Instantiator<Expression>;
     return (a) => DartYield(makeExpression(a), node.hasStar);
   }
 
+  @override
   Instantiator<Throw> visitThrow(Throw node) {
-    Instantiator<Expression> makeExpression = visit(node.expression);
+    var makeExpression = visit(node.expression) as Instantiator<Expression>;
     return (a) => Throw(makeExpression(a));
   }
 
+  @override
   Instantiator<Try> visitTry(Try node) {
-    Instantiator<Block> makeBody = visit(node.body);
-    Instantiator<Catch> makeCatch = visitNullable(node.catchPart);
-    Instantiator<Block> makeFinally = visitNullable(node.finallyPart);
+    var makeBody = visit(node.body) as Instantiator<Block>;
+    var makeCatch = visitNullable(node.catchPart) as Instantiator<Catch>;
+    var makeFinally = visitNullable(node.finallyPart) as Instantiator<Block>;
     return (a) => Try(makeBody(a), makeCatch(a), makeFinally(a));
   }
 
+  @override
   Instantiator<Catch> visitCatch(Catch node) {
-    Instantiator<Identifier> makeDeclaration = visit(node.declaration);
-    Instantiator<Block> makeBody = visit(node.body);
+    var makeDeclaration = visit(node.declaration) as Instantiator<Identifier>;
+    var makeBody = visit(node.body) as Instantiator<Block>;
     return (a) => Catch(makeDeclaration(a), makeBody(a));
   }
 
+  @override
   Instantiator<Switch> visitSwitch(Switch node) {
-    Instantiator<Expression> makeKey = visit(node.key);
+    var makeKey = visit(node.key) as Instantiator<Expression>;
     var makeCases = node.cases.map(visitSwitchCase).toList();
     return (a) => Switch(makeKey(a), makeCases.map((m) => m(a)).toList());
   }
 
+  @override
   Instantiator<SwitchCase> visitSwitchCase(SwitchCase node) {
-    Instantiator<Expression> makeExpression = visitNullable(node.expression);
-    Instantiator<Block> makeBody = visit(node.body);
+    var makeExpression =
+        visitNullable(node.expression) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Block>;
     return (arguments) {
       return SwitchCase(makeExpression(arguments), makeBody(arguments));
     };
   }
 
+  @override
   Instantiator<FunctionDeclaration> visitFunctionDeclaration(
       FunctionDeclaration node) {
-    Instantiator<Identifier> makeName = visit(node.name);
-    Instantiator<Fun> makeFunction = visit(node.function);
+    var makeName = visit(node.name) as Instantiator<Identifier>;
+    var makeFunction = visit(node.function) as Instantiator<Fun>;
     return (a) => FunctionDeclaration(makeName(a), makeFunction(a));
   }
 
+  @override
   Instantiator<LabeledStatement> visitLabeledStatement(LabeledStatement node) {
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => LabeledStatement(node.label, makeBody(a));
   }
 
+  @override
   Instantiator visitLiteralStatement(LiteralStatement node) => visitNode(node);
+  @override
   Instantiator visitLiteralExpression(LiteralExpression node) =>
       visitNode(node);
 
+  @override
   Instantiator<VariableDeclarationList> visitVariableDeclarationList(
       VariableDeclarationList node) {
     var declarationMakers =
@@ -496,36 +534,42 @@
         node.keyword, declarationMakers.map((m) => m(a)).toList());
   }
 
+  @override
   Instantiator<Expression> visitAssignment(Assignment node) {
     Instantiator makeLeftHandSide = visit(node.leftHandSide);
     String op = node.op;
     Instantiator makeValue = visitNullable(node.value);
     return (arguments) {
       return makeValue(arguments)
-          .toAssignExpression(makeLeftHandSide(arguments), op);
+          .toAssignExpression(makeLeftHandSide(arguments), op) as Expression;
     };
   }
 
+  @override
   Instantiator<VariableInitialization> visitVariableInitialization(
       VariableInitialization node) {
-    Instantiator<VariableBinding> makeDeclaration = visit(node.declaration);
-    Instantiator<Expression> makeValue = visitNullable(node.value);
+    var makeDeclaration =
+        visit(node.declaration) as Instantiator<VariableBinding>;
+    var makeValue = visitNullable(node.value) as Instantiator<Expression>;
     return (a) => VariableInitialization(makeDeclaration(a), makeValue(a));
   }
 
+  @override
   Instantiator<Conditional> visitConditional(Conditional cond) {
-    Instantiator<Expression> makeCondition = visit(cond.condition);
-    Instantiator<Expression> makeThen = visit(cond.then);
-    Instantiator<Expression> makeOtherwise = visit(cond.otherwise);
+    var makeCondition = visit(cond.condition) as Instantiator<Expression>;
+    var makeThen = visit(cond.then) as Instantiator<Expression>;
+    var makeOtherwise = visit(cond.otherwise) as Instantiator<Expression>;
     return (a) => Conditional(makeCondition(a), makeThen(a), makeOtherwise(a));
   }
 
+  @override
   Instantiator<Call> visitNew(New node) => handleCallOrNew(node, true);
 
+  @override
   Instantiator<Call> visitCall(Call node) => handleCallOrNew(node, false);
 
   Instantiator<Call> handleCallOrNew(Call node, bool isNew) {
-    Instantiator<Expression> makeTarget = visit(node.target);
+    var makeTarget = visit(node.target) as Instantiator<Expression>;
     var argumentMakers = node.arguments.map(visitSplayableExpression).toList();
 
     // TODO(sra): Avoid copying call arguments if no interpolation or forced
@@ -537,177 +581,213 @@
     };
   }
 
+  @override
   Instantiator<Binary> visitBinary(Binary node) {
-    Instantiator<Expression> makeLeft = visit(node.left);
-    Instantiator<Expression> makeRight = visit(node.right);
+    var makeLeft = visit(node.left) as Instantiator<Expression>;
+    var makeRight = visit(node.right) as Instantiator<Expression>;
     String op = node.op;
     return (a) => Binary(op, makeLeft(a), makeRight(a));
   }
 
+  @override
   Instantiator<Prefix> visitPrefix(Prefix node) {
-    Instantiator<Expression> makeOperand = visit(node.argument);
+    var makeOperand = visit(node.argument) as Instantiator<Expression>;
     String op = node.op;
     return (a) => Prefix(op, makeOperand(a));
   }
 
+  @override
   Instantiator<Postfix> visitPostfix(Postfix node) {
-    Instantiator<Expression> makeOperand = visit(node.argument);
+    var makeOperand = visit(node.argument) as Instantiator<Expression>;
     String op = node.op;
     return (a) => Postfix(op, makeOperand(a));
   }
 
+  @override
   Instantiator<This> visitThis(This node) => (a) => This();
+  @override
   Instantiator<Super> visitSuper(Super node) => (a) => Super();
 
+  @override
   Instantiator<Identifier> visitIdentifier(Identifier node) =>
       (a) => Identifier(node.name);
 
+  @override
   Instantiator<Spread> visitSpread(Spread node) {
     var maker = visit(node.argument);
     return (a) => Spread(maker(a) as Expression);
   }
 
+  @override
   Instantiator<Yield> visitYield(Yield node) {
     var maker = visitNullable(node.value);
     return (a) => Yield(maker(a) as Expression, star: node.star);
   }
 
+  @override
   Instantiator<RestParameter> visitRestParameter(RestParameter node) {
     var maker = visit(node.parameter);
     return (a) => RestParameter(maker(a) as Identifier);
   }
 
+  @override
   Instantiator<PropertyAccess> visitAccess(PropertyAccess node) {
-    Instantiator<Expression> makeReceiver = visit(node.receiver);
-    Instantiator<Expression> makeSelector = visit(node.selector);
+    var makeReceiver = visit(node.receiver) as Instantiator<Expression>;
+    var makeSelector = visit(node.selector) as Instantiator<Expression>;
     return (a) => PropertyAccess(makeReceiver(a), makeSelector(a));
   }
 
+  @override
   Instantiator<NamedFunction> visitNamedFunction(NamedFunction node) {
-    Instantiator<Identifier> makeDeclaration = visit(node.name);
-    Instantiator<Fun> makeFunction = visit(node.function);
+    var makeDeclaration = visit(node.name) as Instantiator<Identifier>;
+    var makeFunction = visit(node.function) as Instantiator<Fun>;
     return (a) => NamedFunction(makeDeclaration(a), makeFunction(a));
   }
 
+  @override
   Instantiator<Fun> visitFun(Fun node) {
     var paramMakers = node.params.map(visitSplayable).toList();
-    Instantiator<Block> makeBody = visit(node.body);
+    var makeBody = visit(node.body) as Instantiator<Block>;
     return (a) => Fun(splayNodes(paramMakers, a), makeBody(a),
         isGenerator: node.isGenerator, asyncModifier: node.asyncModifier);
   }
 
+  @override
   Instantiator<ArrowFun> visitArrowFun(ArrowFun node) {
     var paramMakers = node.params.map(visitSplayable).toList();
     Instantiator makeBody = visit(node.body);
-    return (a) => ArrowFun(splayNodes(paramMakers, a), makeBody(a));
+    return (a) => ArrowFun(splayNodes(paramMakers, a), makeBody(a) as Node);
   }
 
+  @override
   Instantiator<LiteralBool> visitLiteralBool(LiteralBool node) =>
       (a) => LiteralBool(node.value);
 
+  @override
   Instantiator<LiteralString> visitLiteralString(LiteralString node) =>
       (a) => LiteralString(node.value);
 
+  @override
   Instantiator<LiteralNumber> visitLiteralNumber(LiteralNumber node) =>
       (a) => LiteralNumber(node.value);
 
+  @override
   Instantiator<LiteralNull> visitLiteralNull(LiteralNull node) =>
       (a) => LiteralNull();
 
+  @override
   Instantiator<ArrayInitializer> visitArrayInitializer(ArrayInitializer node) {
     var makers = node.elements.map(visitSplayableExpression).toList();
     return (a) => ArrayInitializer(splayNodes(makers, a));
   }
 
+  @override
   Instantiator visitArrayHole(ArrayHole node) {
     return (arguments) => ArrayHole();
   }
 
+  @override
   Instantiator<ObjectInitializer> visitObjectInitializer(
       ObjectInitializer node) {
     var propertyMakers = node.properties.map(visitSplayable).toList();
     return (a) => ObjectInitializer(splayNodes(propertyMakers, a));
   }
 
+  @override
   Instantiator<Property> visitProperty(Property node) {
-    Instantiator<Expression> makeName = visit(node.name);
-    Instantiator<Expression> makeValue = visit(node.value);
+    var makeName = visit(node.name) as Instantiator<Expression>;
+    var makeValue = visit(node.value) as Instantiator<Expression>;
     return (a) => Property(makeName(a), makeValue(a));
   }
 
+  @override
   Instantiator<RegExpLiteral> visitRegExpLiteral(RegExpLiteral node) =>
       (a) => RegExpLiteral(node.pattern);
 
+  @override
   Instantiator<TemplateString> visitTemplateString(TemplateString node) {
     var makeElements = node.interpolations.map(visit).toList();
     return (a) => TemplateString(node.strings, splayNodes(makeElements, a));
   }
 
+  @override
   Instantiator<TaggedTemplate> visitTaggedTemplate(TaggedTemplate node) {
-    Instantiator<Expression> makeTag = visit(node.tag);
+    var makeTag = visit(node.tag) as Instantiator<Expression>;
     var makeTemplate = visitTemplateString(node.template);
     return (a) => TaggedTemplate(makeTag(a), makeTemplate(a));
   }
 
+  @override
   Instantiator visitClassDeclaration(ClassDeclaration node) {
     var makeClass = visitClassExpression(node.classExpr);
     return (a) => ClassDeclaration(makeClass(a));
   }
 
+  @override
   Instantiator<ClassExpression> visitClassExpression(ClassExpression node) {
     var makeMethods = node.methods.map(visitSplayableExpression).toList();
-    Instantiator<Identifier> makeName = visit(node.name);
-    Instantiator<Expression> makeHeritage = visit(node.heritage);
+    var makeName = visit(node.name) as Instantiator<Identifier>;
+    var makeHeritage = visit(node.heritage) as Instantiator<Expression>;
 
     return (a) => ClassExpression(
         makeName(a), makeHeritage(a), splayNodes(makeMethods, a));
   }
 
+  @override
   Instantiator<Method> visitMethod(Method node) {
-    Instantiator<Expression> makeName = visit(node.name);
-    Instantiator<Fun> makeFunction = visit(node.function);
+    var makeName = visit(node.name) as Instantiator<Expression>;
+    var makeFunction = visit(node.function) as Instantiator<Fun>;
     return (a) => Method(makeName(a), makeFunction(a),
         isGetter: node.isGetter,
         isSetter: node.isSetter,
         isStatic: node.isStatic);
   }
 
+  @override
   Instantiator<Comment> visitComment(Comment node) =>
       (a) => Comment(node.comment);
 
+  @override
   Instantiator<CommentExpression> visitCommentExpression(
       CommentExpression node) {
-    Instantiator<Expression> makeExpr = visit(node.expression);
+    var makeExpr = visit(node.expression) as Instantiator<Expression>;
     return (a) => CommentExpression(node.comment, makeExpr(a));
   }
 
+  @override
   Instantiator<Await> visitAwait(Await node) {
-    Instantiator<Expression> makeExpr = visit(node.expression);
+    var makeExpr = visit(node.expression) as Instantiator<Expression>;
     return (a) => Await(makeExpr(a));
   }
 
   // Note: these are not supported yet in the interpolation grammar.
+  @override
   Instantiator visitModule(Module node) => throw UnimplementedError();
+  @override
   Instantiator visitNameSpecifier(NameSpecifier node) =>
       throw UnimplementedError();
 
+  @override
   Instantiator visitImportDeclaration(ImportDeclaration node) =>
       throw UnimplementedError();
 
+  @override
   Instantiator visitExportDeclaration(ExportDeclaration node) =>
       throw UnimplementedError();
 
+  @override
   Instantiator visitExportClause(ExportClause node) =>
       throw UnimplementedError();
 
   @override
   Instantiator<DestructuredVariable> visitDestructuredVariable(
       DestructuredVariable node) {
-    Instantiator<Identifier> makeName = visitNullable(node.name);
-    Instantiator<Expression> makeProperty = visitNullable(node.property);
-    Instantiator<BindingPattern> makeStructure = visitNullable(node.structure);
-    Instantiator<Expression> makeDefaultValue =
-        visitNullable(node.defaultValue);
+    var makeName = visitNullable(node.name) as Instantiator<Identifier>;
+    var makeProperty = visitNullable(node.property) as Instantiator<Expression>;
+    var makeStructure =
+        visitNullable(node.structure) as Instantiator<BindingPattern>;
+    var makeDefaultValue =
+        visitNullable(node.defaultValue) as Instantiator<Expression>;
     return (a) => DestructuredVariable(
         name: makeName(a),
         property: makeProperty(a),
@@ -751,6 +831,7 @@
     node.accept(this);
   }
 
+  @override
   void visitNode(Node node) {
     int before = count;
     node.visitChildren(this);
@@ -758,6 +839,7 @@
     return null;
   }
 
+  @override
   visitInterpolatedNode(InterpolatedNode node) {
     containsInterpolatedNode.add(node);
     if (node.isNamed) holeNames.add(node.nameOrPosition as String);
diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
index 308e199..caa8b83 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -645,7 +645,9 @@
     var f = type as a.FunctionType;
     if (f.name != null && f.name != '') {
       var ref = ensureNode
-          ? visitFunctionTypeAliasElement(f.element).reference
+          ? visitFunctionTypeAliasElement(
+                  f.element as a.FunctionTypeAliasElement)
+              .reference
           : _reference(f.element);
       return TypedefType.byReference(ref, f.typeArguments.map(visit).toList());
     }
@@ -752,8 +754,8 @@
       void Function(Expression) addAnnotation) {
     if (metadata.isEmpty) return;
 
-    for (a.ElementAnnotationImpl annotation in metadata) {
-      var ast = annotation.annotationAst;
+    for (a.ElementAnnotation annotation in metadata) {
+      var ast = (annotation as a.ElementAnnotationImpl).annotationAst;
       var arguments = ast.arguments;
       if (arguments == null) {
         var e = ast.element;
@@ -833,7 +835,8 @@
         //
         // This leads to mismatch in how we call this constructor. So we need to
         // find the redirected one.
-        for (var rc; (rc = constructor.redirectedConstructor) != null;) {
+        for (a.ConstructorElement rc;
+            (rc = constructor.redirectedConstructor) != null;) {
           constructor = rc;
         }
         constructor = constructor is a.ConstructorMember
@@ -852,7 +855,9 @@
     }
     if (obj is a.DartObjectImpl && type is a.FunctionType) {
       var e = obj.toFunctionValue();
-      e = e is a.PropertyAccessorElement && e.isSynthetic ? e.variable : e;
+      e = e is a.PropertyAccessorElement && e.isSynthetic
+          ? e.variable as a.ExecutableElement
+          : e;
       // TODO(jmesserly): support generic tear-off implicit instantiation.
       return StaticGet.byReference(_reference(e));
     }
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index e9f2a3a..364981a 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -11,6 +11,8 @@
 import 'package:cli_util/cli_util.dart' show getSdkPath;
 import 'package:front_end/src/api_unstable/ddc.dart' as fe;
 import 'package:kernel/kernel.dart' hide MapEntry;
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+import 'package:kernel/target/targets.dart';
 import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
 import 'package:kernel/binary/ast_to_binary.dart' as kernel show BinaryPrinter;
 import 'package:path/path.dart' as path;
@@ -20,7 +22,6 @@
 import '../compiler/module_builder.dart';
 import '../compiler/shared_command.dart';
 import '../compiler/shared_compiler.dart';
-import '../flutter/track_widget_constructor_locations.dart';
 import '../js_ast/js_ast.dart' as JS;
 import '../js_ast/js_ast.dart' show js;
 import '../js_ast/source_map_printer.dart' show SourceMapPrintingContext;
@@ -36,7 +37,7 @@
 /// Returns `true` if the program compiled without any fatal errors.
 Future<CompilerResult> compile(List<String> args,
     {fe.InitializedCompilerState compilerState,
-    bool useIncrementalCompiler: false}) async {
+    bool useIncrementalCompiler = false}) async {
   try {
     return await _compile(args,
         compilerState: compilerState,
@@ -67,7 +68,7 @@
 
 Future<CompilerResult> _compile(List<String> args,
     {fe.InitializedCompilerState compilerState,
-    bool useIncrementalCompiler: false}) async {
+    bool useIncrementalCompiler = false}) async {
   // TODO(jmesserly): refactor options to share code with dartdevc CLI.
   var argParser = ArgParser(allowTrailingOptions: true)
     ..addFlag('help',
@@ -92,7 +93,11 @@
             'specified multi-root scheme.',
         defaultsTo: [Uri.base.path])
     ..addOption('dart-sdk',
-        help: '(unsupported with --kernel) path to the Dart SDK.', hide: true);
+        help: '(unsupported with --kernel) path to the Dart SDK.', hide: true)
+    ..addFlag('compile-sdk',
+        help: 'Build an SDK module.', defaultsTo: false, hide: true)
+    ..addOption('libraries-file',
+        help: 'The path to the libraries.json file for the sdk.');
   SharedCompilerOptions.addArguments(argParser);
 
   var declaredVariables = parseAndRemoveDeclaredVariables(args);
@@ -154,15 +159,17 @@
       summaryPaths.map(sourcePathToUri), options.summaryModules.values);
   var useAnalyzer = summaryPaths.any((s) => !s.endsWith('.dill'));
   var sdkSummaryPath = argResults['dart-sdk-summary'] as String;
-  String librarySpecPath;
+  var librarySpecPath = argResults['libraries-file'] as String;
   if (sdkSummaryPath == null) {
     sdkSummaryPath =
         useAnalyzer ? defaultAnalyzerSdkSummaryPath : defaultSdkSummaryPath;
-    librarySpecPath = defaultLibrarySpecPath;
-  } else {
+    librarySpecPath ??= defaultLibrarySpecPath;
+  }
+
+  if (librarySpecPath == null) {
     // TODO(jmesserly): the `isSupported` bit should be included in the SDK
     // summary, but front_end requires a separate file, so we have to work
-    // around that, while avoiding yet another command line option.
+    // around that, while not requiring yet another command line option.
     //
     // Right now we search two locations: one level above the SDK summary
     // (this works for the build and SDK layouts) or next to the SDK summary
@@ -213,6 +220,10 @@
     }
   }
 
+  bool trackWidgetCreation =
+      argResults['track-widget-creation'] as bool ?? false;
+
+  var compileSdk = argResults['compile-sdk'] == true;
   var oldCompilerState = compilerState;
   List<Component> doneInputSummaries;
   fe.IncrementalCompiler incrementalCompiler;
@@ -220,11 +231,14 @@
   if (useAnalyzer || !useIncrementalCompiler) {
     compilerState = await fe.initializeCompiler(
         oldCompilerState,
-        sourcePathToUri(sdkSummaryPath),
+        compileSdk,
+        sourcePathToUri(getSdkPath()),
+        compileSdk ? null : sourcePathToUri(sdkSummaryPath),
         sourcePathToUri(packageFile),
         sourcePathToUri(librarySpecPath),
         summaryModules.keys.toList(),
-        DevCompilerTarget(),
+        DevCompilerTarget(
+            TargetFlags(trackWidgetCreation: trackWidgetCreation)),
         fileSystem: fileSystem,
         experiments: experiments);
   } else {
@@ -232,11 +246,14 @@
     compilerState = await fe.initializeIncrementalCompiler(
         oldCompilerState,
         doneInputSummaries,
-        sourcePathToUri(sdkSummaryPath),
+        compileSdk,
+        sourcePathToUri(getSdkPath()),
+        compileSdk ? null : sourcePathToUri(sdkSummaryPath),
         sourcePathToUri(packageFile),
         sourcePathToUri(librarySpecPath),
         summaryModules.keys.toList(),
-        DevCompilerTarget(),
+        DevCompilerTarget(
+            TargetFlags(trackWidgetCreation: trackWidgetCreation)),
         fileSystem: fileSystem,
         experiments: experiments);
     incrementalCompiler = compilerState.incrementalCompiler;
@@ -260,7 +277,7 @@
     converter.dispose();
   }
 
-  var hierarchy;
+  ClassHierarchy hierarchy;
   fe.DdcResult result;
   if (useAnalyzer || !useIncrementalCompiler) {
     result = await fe.compile(compilerState, inputs, diagnosticMessageHandler);
@@ -320,12 +337,6 @@
     hierarchy = target.hierarchy;
   }
 
-  // TODO(jmesserly): remove this hack once Flutter SDK has a `dartdevc` with
-  // support for the widget inspector.
-  if (argResults['track-widget-creation'] as bool) {
-    WidgetCreatorTracker(hierarchy).transform(component);
-  }
-
   var compiler =
       ProgramCompiler(component, hierarchy, options, declaredVariables);
 
@@ -456,7 +467,7 @@
 
 bool _checkForDartMirrorsImport(Component component) {
   for (var library in component.libraries) {
-    if (library.isExternal) continue;
+    if (library.isExternal || library.importUri.scheme == 'dart') continue;
     for (var dep in library.dependencies) {
       var uri = dep.targetLibrary.importUri;
       if (uri.scheme == 'dart' && uri.path == 'mirrors') {
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index b6c1925..531ca40 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:collection';
+import 'dart:convert';
 import 'dart:math' show max, min;
 
 import 'package:front_end/src/api_unstable/ddc.dart' show TypeSchemaEnvironment;
@@ -166,6 +167,24 @@
   /// label name that was assigned to it.
   final _labelNames = HashMap<Statement, String>.identity();
 
+  /// Indicates that the current context exists within a switch statement that
+  /// uses at least one continue statement with a target label.
+  ///
+  /// JS forbids labels at case statement boundaries, so these switch
+  /// statements must be generated less directly.
+  /// Updated from the method 'visitSwitchStatement'.
+  bool _inLabeledContinueSwitch = false;
+
+  /// A map from switch statements to their state information.
+  /// State information includes the names of the switch statement's implicit
+  /// label name and implicit state variable name.
+  ///
+  /// Entries are only created for switch statements that contain labeled
+  /// continue statements and are used to simulate "jumping" to case statements.
+  /// State variables hold the next constant case expression, while labels act
+  /// as targets for continue and break.
+  final _switchLabelStates = HashMap<Statement, SwitchLabelState>();
+
   final Class _jsArrayClass;
   final Class privateSymbolClass;
   final Class linkedHashMapImplClass;
@@ -298,7 +317,9 @@
   @override
   String jsLibraryName(Library library) {
     var uri = library.importUri;
-    if (uri.scheme == 'dart') return uri.path;
+    if (uri.scheme == 'dart') {
+      return isSdkInternalRuntime(library) ? 'dart' : uri.path;
+    }
 
     // TODO(vsm): This is not necessarily unique if '__' appears in a file name.
     Iterable<String> segments;
@@ -317,13 +338,11 @@
   }
 
   @override
-  String jsLibraryDebuggerName(Library library) {
-    var uri = library.importUri;
-    // For package: and dart: uris show the entire
-    if (uri.scheme == 'dart' || uri.scheme == 'package') return uri.toString();
-    // TODO(jmesserly): this is not unique typically.
-    return uri.pathSegments.last;
-  }
+  String jsLibraryDebuggerName(Library library) => '${library.importUri}';
+
+  @override
+  Iterable<String> jsPartDebuggerNames(Library library) =>
+      library.parts.map((part) => part.partUri);
 
   @override
   bool isSdkInternalRuntime(Library l) {
@@ -533,10 +552,11 @@
       className ?? JS.Identifier(name)
     ]);
 
-    var genericArgs = [typeConstructor];
-    if (deferredBaseClass != null && deferredBaseClass.isNotEmpty) {
-      genericArgs.add(js.call('(#) => { #; }', [jsFormals, deferredBaseClass]));
-    }
+    var genericArgs = [
+      typeConstructor,
+      if (deferredBaseClass != null && deferredBaseClass.isNotEmpty)
+        js.call('(#) => { #; }', [jsFormals, deferredBaseClass]),
+    ];
 
     var genericCall = runtimeCall('generic(#)', [genericArgs]);
 
@@ -705,12 +725,12 @@
         _currentUri = ctor.enclosingClass.fileUri;
         var jsParams = _emitParameters(ctor.function);
         _currentUri = savedUri;
-        var ctorBody = <JS.Statement>[];
-        if (mixinCtor != null) ctorBody.add(mixinCtor);
         var name = ctor.name.name;
-        if (name != '' || hasUnnamedSuper) {
-          ctorBody.add(_emitSuperConstructorCall(className, name, jsParams));
-        }
+        var ctorBody = [
+          if (mixinCtor != null) mixinCtor,
+          if (name != '' || hasUnnamedSuper)
+            _emitSuperConstructorCall(className, name, jsParams),
+        ];
         body.add(_addConstructorToClass(
             c, className, name, JS.Fun(jsParams, JS.Block(ctorBody))));
       }
@@ -1146,7 +1166,7 @@
     var savedClass = _classEmittingSignatures;
     _classEmittingSignatures = c;
 
-    var interfaces = List.from(c.implementedTypes)
+    var interfaces = c.implementedTypes.toList()
       ..addAll(c.superclassConstraints());
     if (interfaces.isNotEmpty) {
       body.add(js.statement('#[#.implements] = () => [#];', [
@@ -1250,6 +1270,10 @@
     emitSignature('Setter', instanceSetters);
     emitSignature('StaticGetter', staticGetters);
     emitSignature('StaticSetter', staticSetters);
+    body.add(runtimeStatement('setLibraryUri(#, #)', [
+      className,
+      js.escapedString(jsLibraryDebuggerName(c.enclosingLibrary))
+    ]));
 
     var instanceFields = <JS.Property>[];
     var staticFields = <JS.Property>[];
@@ -1270,8 +1294,10 @@
 
     if (emitMetadata) {
       var constructors = <JS.Property>[];
-      var allConstructors = List<Member>.from(c.constructors)
-        ..addAll(c.procedures.where((p) => p.isFactory));
+      var allConstructors = [
+        ...c.constructors,
+        ...c.procedures.where((p) => p.isFactory),
+      ];
       for (var ctor in allConstructors) {
         var memberName = _constructorName(ctor.name.name);
         var type = _emitAnnotatedFunctionType(
@@ -1534,7 +1560,7 @@
     if (expr == null) return null;
     var jsExpr = _visitExpression(expr);
     if (!isNullable(expr)) return jsExpr;
-    return runtimeCall('notNull(#)', jsExpr);
+    return runtimeCall('notNull(#)', [jsExpr]);
   }
 
   /// If the class has only factory constructors, and it can be mixed in,
@@ -1978,8 +2004,8 @@
       Class c, String jsPeerName, List<JS.Statement> body) {
     var className = _emitTopLevelName(c);
     if (_typeRep.isPrimitive(c.rawType)) {
-      body.add(
-          runtimeStatement('definePrimitiveHashCode(#.prototype)', className));
+      body.add(runtimeStatement(
+          'definePrimitiveHashCode(#.prototype)', [className]));
     }
     body.add(runtimeStatement(
         'registerExtension(#, #)', [js.string(jsPeerName), className]));
@@ -2419,22 +2445,22 @@
   }
 
   @override
-  defaultDartType(type) => _emitInvalidNode(type);
+  JS.Expression defaultDartType(DartType type) => _emitInvalidNode(type);
 
   @override
-  visitInvalidType(type) => defaultDartType(type);
+  JS.Expression visitInvalidType(InvalidType type) => defaultDartType(type);
 
   @override
-  visitDynamicType(type) => runtimeCall('dynamic');
+  JS.Expression visitDynamicType(DynamicType type) => runtimeCall('dynamic');
 
   @override
-  visitVoidType(type) => runtimeCall('void');
+  JS.Expression visitVoidType(VoidType type) => runtimeCall('void');
 
   @override
-  visitBottomType(type) => runtimeCall('bottom');
+  JS.Expression visitBottomType(BottomType type) => runtimeCall('bottom');
 
   @override
-  visitInterfaceType(type) {
+  JS.Expression visitInterfaceType(InterfaceType type) {
     var c = type.classNode;
     _declareBeforeUse(c);
 
@@ -2453,7 +2479,7 @@
     // have to use a helper to define them.
     if (isJSAnonymousType(c)) {
       return runtimeCall(
-          'anonymousJSType(#)', js.escapedString(getLocalClassName(c)));
+          'anonymousJSType(#)', [js.escapedString(getLocalClassName(c))]);
     }
     var jsName = _getJSNameWithoutGlobal(c);
     if (jsName != null) {
@@ -2462,7 +2488,7 @@
     }
 
     var args = type.typeArguments;
-    Iterable<JS.Expression> jsArgs = null;
+    Iterable<JS.Expression> jsArgs;
     if (args.any((a) => a != const DynamicType())) {
       jsArgs = args.map(_emitType);
     }
@@ -2492,7 +2518,7 @@
   }
 
   @override
-  visitFunctionType(type, {Member member, bool lazy = false}) {
+  JS.Expression visitFunctionType(type, {Member member, bool lazy = false}) {
     var requiredTypes =
         type.positionalParameters.take(type.requiredParameterCount).toList();
     var function = member?.function;
@@ -2647,14 +2673,15 @@
   }
 
   @override
-  visitTypeParameterType(type) => _emitTypeParameter(type.parameter);
+  JS.Expression visitTypeParameterType(TypeParameterType type) =>
+      _emitTypeParameter(type.parameter);
 
-  JS.Identifier _emitTypeParameter(TypeParameter t) {
-    return JS.Identifier(getTypeParameterName(t));
-  }
+  JS.Identifier _emitTypeParameter(TypeParameter t) =>
+      JS.Identifier(getTypeParameterName(t));
 
   @override
-  visitTypedefType(type) => visitFunctionType(type.unalias);
+  JS.Expression visitTypedefType(TypedefType type) =>
+      visitFunctionType(type.unalias as FunctionType);
 
   JS.Fun _emitFunction(FunctionNode f, String name) {
     // normal function (sync), vs (sync*, async, async*)
@@ -2680,11 +2707,11 @@
 
   List<JS.Parameter> _emitParameters(FunctionNode f) {
     var positional = f.positionalParameters;
-    var result = List<JS.Parameter>.from(positional.map(_emitVariableDef));
+    var result = List<JS.Parameter>.of(positional.map(_emitVariableDef));
     if (positional.isNotEmpty &&
         f.requiredParameterCount == positional.length &&
         positional.last.annotations.any(isJsRestAnnotation)) {
-      result.last = JS.RestParameter(result.last);
+      result.last = JS.RestParameter(result.last as JS.Identifier);
     }
     if (f.namedParameters.isNotEmpty) result.add(namedArgumentTemp);
     return result;
@@ -2771,8 +2798,9 @@
             .toList();
         return mutatedParams;
       });
-      if (mutatedParams.isNotEmpty)
+      if (mutatedParams.isNotEmpty) {
         gen = js.call('() => #(#)', [gen, mutatedParams]);
+      }
 
       var returnType =
           _getExpectedReturnType(function, coreTypes.iterableClass);
@@ -3004,9 +3032,10 @@
       // (sync*/async/async*). Our code generator assumes it can emit names for
       // named argument initialization, and sync* functions also emit locally
       // modified parameters into the function's scope.
-      var parameterNames = HashSet<String>()
-        ..addAll(f.positionalParameters.map((p) => p.name))
-        ..addAll(f.namedParameters.map((p) => p.name));
+      var parameterNames = {
+        for (var p in f.positionalParameters) p.name,
+        for (var p in f.namedParameters) p.name,
+      };
 
       return jsBody.toScopedBlock(parameterNames);
     }
@@ -3041,11 +3070,11 @@
 
     if (node is AsExpression && node.isTypeError) {
       assert(node.getStaticType(types) == types.boolType);
-      return runtimeCall('dtest(#)', _visitExpression(node.operand));
+      return runtimeCall('dtest(#)', [_visitExpression(node.operand)]);
     }
 
     var result = _visitExpression(node);
-    if (isNullable(node)) result = runtimeCall('test(#)', result);
+    if (isNullable(node)) result = runtimeCall('test(#)', [result]);
     return result;
   }
 
@@ -3098,6 +3127,8 @@
       // TODO(jmesserly): figure out why this is throwing. Perhaps the file URI
       // and offset are mismatched and don't correspond to the same source?
       return null;
+    } on RangeError catch (_) {
+      return null;
     }
   }
 
@@ -3114,10 +3145,11 @@
   }
 
   @override
-  defaultStatement(Statement node) => _emitInvalidNode(node).toStatement();
+  JS.Statement defaultStatement(Statement node) =>
+      _emitInvalidNode(node).toStatement();
 
   @override
-  visitExpressionStatement(ExpressionStatement node) {
+  JS.Statement visitExpressionStatement(ExpressionStatement node) {
     var expr = node.expression;
     if (expr is StaticInvocation) {
       if (isInlineJS(expr.target)) {
@@ -3131,7 +3163,7 @@
   }
 
   @override
-  visitBlock(Block node) {
+  JS.Statement visitBlock(Block node) {
     // If this is the block body of a function, don't mark it as a separate
     // scope, because the function is the scope. This avoids generating an
     // unncessary nested block.
@@ -3145,17 +3177,17 @@
   }
 
   @override
-  visitEmptyStatement(EmptyStatement node) => JS.EmptyStatement();
+  JS.Statement visitEmptyStatement(EmptyStatement node) => JS.EmptyStatement();
 
   @override
-  visitAssertBlock(AssertBlock node) {
+  JS.Statement visitAssertBlock(AssertBlock node) {
     // AssertBlocks are introduced by the VM-specific async elimination
     // transformation.  We do not expect them to arise here.
     throw UnsupportedError('compilation of an assert block');
   }
 
   @override
-  visitAssertStatement(AssertStatement node) {
+  JS.Statement visitAssertStatement(AssertStatement node) {
     if (!options.enableAsserts) return JS.EmptyStatement();
     var condition = node.condition;
     var conditionType = condition.getStaticType(types);
@@ -3165,16 +3197,30 @@
     if (conditionType is FunctionType &&
         conditionType.requiredParameterCount == 0 &&
         conditionType.returnType == boolType) {
-      jsCondition = runtimeCall('test(#())', jsCondition);
+      jsCondition = runtimeCall('test(#())', [jsCondition]);
     } else if (conditionType != boolType) {
-      jsCondition = runtimeCall('dassert(#)', jsCondition);
+      jsCondition = runtimeCall('dassert(#)', [jsCondition]);
     } else if (isNullable(condition)) {
-      jsCondition = runtimeCall('test(#)', jsCondition);
+      jsCondition = runtimeCall('test(#)', [jsCondition]);
     }
-    return js.statement(' if (!#) #.assertFailed(#);', [
+
+    var encodedConditionSource = node
+        .enclosingComponent.uriToSource[node.location.file].source
+        .sublist(node.conditionStartOffset, node.conditionEndOffset);
+    var conditionSource = utf8.decode(encodedConditionSource);
+    var location = _getLocation(node.conditionStartOffset);
+    return js.statement(' if (!#) #.assertFailed(#, #, #, #, #);', [
       jsCondition,
       runtimeModule,
-      node.message != null ? [_visitExpression(node.message)] : []
+      if (node.message == null)
+        JS.LiteralNull()
+      else
+        _visitExpression(node.message),
+      js.escapedString(location.sourceUrl.toString()),
+      // Lines and columns are typically printed with 1 based indexing.
+      js.number(location.line + 1),
+      js.number(location.column + 1),
+      js.escapedString(conditionSource),
     ]);
   }
 
@@ -3189,7 +3235,7 @@
   }
 
   @override
-  visitLabeledStatement(LabeledStatement node) {
+  JS.Statement visitLabeledStatement(LabeledStatement node) {
     List<LabeledStatement> saved;
     var target = _effectiveTargets[node];
     // If the effective target is known then this statement is either contained
@@ -3205,7 +3251,9 @@
         statements.add(labeled);
         target = labeled.body;
       }
-      for (var statement in statements) _effectiveTargets[statement] = target;
+      for (var statement in statements) {
+        _effectiveTargets[statement] = target;
+      }
 
       // If the effective target will compile to something that can have a
       // break from it without a label (e.g., a loop but not a block), then any
@@ -3225,7 +3273,13 @@
   }
 
   @override
-  visitBreakStatement(BreakStatement node) {
+  JS.Statement visitBreakStatement(BreakStatement node) {
+    // Switch statements with continue labels must explicitly break to their
+    // implicit label due to their being wrapped in a loop.
+    if (_inLabeledContinueSwitch &&
+        _switchLabelStates.containsKey(node.target.body)) {
+      return JS.Break(_switchLabelStates[node.target.body].label);
+    }
     // Can it be compiled to a break without a label?
     if (_currentBreakTargets.contains(node.target)) {
       return JS.Break(null);
@@ -3238,7 +3292,7 @@
     // Ensure the effective target is labeled.  Labels are named globally per
     // Kernel binary.
     //
-    // TODO(kmillikin): Preserve Dart label names in Kernel and here.
+    // TODO(markzipan): Retrieve the real label name with source offsets
     var target = _effectiveTargets[node.target];
     var name = _labelNames[target];
     if (name == null) _labelNames[target] = name = 'L${_labelNames.length}';
@@ -3406,44 +3460,103 @@
   }
 
   @override
-  visitSwitchStatement(SwitchStatement node) {
+  JS.Statement visitSwitchStatement(SwitchStatement node) {
+    // Switches with labeled continues are generated as an infinite loop with
+    // an explicit variable for holding the switch's next case state and an
+    // explicit label. Any implicit breaks are made explicit (e.g., when break
+    // is omitted for the final case statement).
+    var previous = _inLabeledContinueSwitch;
+    _inLabeledContinueSwitch = hasLabeledContinue(node);
+
     var cases = <JS.SwitchCase>[];
-    var emptyBlock = JS.Block.empty();
-    for (var c in node.cases) {
-      // TODO(jmesserly): make sure we are statically checking fall through
-      var body = _visitStatement(c.body).toBlock();
-      var expressions = c.expressions;
-      var last =
-          expressions.isNotEmpty && !c.isDefault ? expressions.last : null;
-      for (var e in expressions) {
-        var jsExpr = _visitExpression(e);
-        cases.add(JS.SwitchCase(jsExpr, e == last ? body : emptyBlock));
+
+    if (_inLabeledContinueSwitch) {
+      var labelState = JS.TemporaryId("labelState");
+      // TODO(markzipan): Retrieve the real label name with source offsets
+      var labelName = 'SL${_switchLabelStates.length}';
+      _switchLabelStates[node] = SwitchLabelState(labelName, labelState);
+
+      for (var c in node.cases) {
+        var subcases =
+            _visitSwitchCase(c, lastSwitchCase: c == node.cases.last);
+        if (subcases.isNotEmpty) cases.addAll(subcases);
       }
-      if (c.isDefault) cases.add(JS.SwitchCase.defaultCase(body));
+
+      var switchExpr = _visitExpression(node.expression);
+      var switchStmt = JS.Switch(labelState, cases);
+      var loopBody = JS.Block([switchStmt, JS.Break(null)]);
+      var loopStmt = JS.While(js.boolean(true), loopBody);
+      // Note: Cannot use _labelNames, as the label must be on the loop.
+      // not the block surrounding the switch statement.
+      var labeledStmt = JS.LabeledStatement(labelName, loopStmt);
+      var block = JS.Block([
+        js.statement('let # = #', [labelState, switchExpr]),
+        labeledStmt
+      ]);
+      _inLabeledContinueSwitch = previous;
+      return block;
     }
 
-    return JS.Switch(_visitExpression(node.expression), cases);
+    for (var c in node.cases) {
+      var subcases = _visitSwitchCase(c);
+      if (subcases.isNotEmpty) cases.addAll(subcases);
+    }
+
+    var stmt = JS.Switch(_visitExpression(node.expression), cases);
+    _inLabeledContinueSwitch = previous;
+    return stmt;
+  }
+
+  /// Helper for visiting a SwitchCase statement.
+  ///
+  /// lastSwitchCase is only used when the current switch statement contains
+  /// labeled continues. Dart permits the final case to implicitly break, but
+  /// switch statements with labeled continues must explicitly break/continue
+  /// to escape the surrounding infinite loop.
+  List<JS.SwitchCase> _visitSwitchCase(SwitchCase node,
+      {bool lastSwitchCase = false}) {
+    var cases = <JS.SwitchCase>[];
+    var emptyBlock = JS.Block.empty();
+    // TODO(jmesserly): make sure we are statically checking fall through
+    var body = _visitStatement(node.body).toBlock();
+    var expressions = node.expressions;
+    var lastExpr =
+        expressions.isNotEmpty && !node.isDefault ? expressions.last : null;
+    for (var e in expressions) {
+      var jsExpr = _visitExpression(e);
+      cases.add(JS.SwitchCase(jsExpr, e == lastExpr ? body : emptyBlock));
+    }
+    if (node.isDefault) {
+      cases.add(JS.SwitchCase.defaultCase(body));
+    }
+    // Switch statements with continue labels must explicitly break from their
+    // last case to escape the additional loop around the switch.
+    if (lastSwitchCase && _inLabeledContinueSwitch && cases.isNotEmpty) {
+      // TODO(markzipan): avoid generating unreachable breaks
+      assert(_switchLabelStates.containsKey(node.parent));
+      var breakStmt = JS.Break(_switchLabelStates[node.parent].label);
+      var switchBody = JS.Block(cases.last.body.statements..add(breakStmt));
+      var updatedSwitch = JS.SwitchCase(cases.last.expression, switchBody);
+      cases.removeLast();
+      cases.add(updatedSwitch);
+    }
+    return cases;
   }
 
   @override
-  visitContinueSwitchStatement(ContinueSwitchStatement node) {
-    SwitchCase switchCase;
-    for (Statement current = node;;) {
-      var parent = current.parent;
-      if (parent is Block && parent.statements.last == current) {
-        current = parent;
-        continue;
-      }
-      if (parent is SwitchCase) switchCase = parent;
-      break;
-    }
-    if (switchCase != null) {
-      var switchCases = (switchCase.parent as SwitchStatement).cases;
-      var fromIndex = switchCases.indexOf(switchCase);
-      var toIndex = switchCases.indexOf(node.target);
-      if (toIndex == fromIndex + 1) {
-        return JS.Comment('continue to next case');
-      }
+  JS.Statement visitContinueSwitchStatement(ContinueSwitchStatement node) {
+    var switchStmt = node.target.parent;
+    if (_inLabeledContinueSwitch &&
+        _switchLabelStates.containsKey(switchStmt)) {
+      var switchState = _switchLabelStates[switchStmt];
+      // Use the first constant expression that can match the collated switch
+      // case. Use an unused symbol otherwise to force the default case.
+      var jsExpr = node.target.expressions.isEmpty
+          ? js.call("Symbol('_default')", [])
+          : _visitExpression(node.target.expressions[0]);
+      var setStateStmt = js.statement("# = #", [switchState.variable, jsExpr]);
+      var continueStmt = JS.Continue(switchState.label);
+      return JS.Block([setStateStmt, continueStmt]);
     }
     return _emitInvalidNode(
             node, 'see https://github.com/dart-lang/sdk/issues/29352')
@@ -3451,7 +3564,7 @@
   }
 
   @override
-  visitIfStatement(IfStatement node) {
+  JS.Statement visitIfStatement(IfStatement node) {
     return JS.If(_visitTest(node.condition), _visitScope(node.then),
         _visitScope(node.otherwise));
   }
@@ -3477,7 +3590,7 @@
   }
 
   @override
-  visitTryCatch(TryCatch node) {
+  JS.Statement visitTryCatch(TryCatch node) {
     return JS.Try(
         _visitStatement(node.body).toBlock(), _visitCatch(node.catches), null);
   }
@@ -3512,15 +3625,14 @@
         runtimeModule,
         _emitVariableRef(caughtError)
       ]),
+      if (stackTraceParameter != null)
+        js.statement('let # = #.stackTrace(#)', [
+          _emitVariableDef(stackTraceParameter),
+          runtimeModule,
+          _emitVariableRef(caughtError)
+        ]),
+      catchBody,
     ];
-    if (stackTraceParameter != null) {
-      catchStatements.add(js.statement('let # = #.stackTrace(#)', [
-        _emitVariableDef(stackTraceParameter),
-        runtimeModule,
-        _emitVariableRef(caughtError)
-      ]));
-    }
-    catchStatements.add(catchBody);
     _rethrowParameter = savedRethrow;
     return JS.Catch(_emitVariableDef(caughtError), JS.Block(catchStatements));
   }
@@ -3559,7 +3671,7 @@
   }
 
   @override
-  visitTryFinally(TryFinally node) {
+  JS.Statement visitTryFinally(TryFinally node) {
     var body = _visitStatement(node.body);
     var finallyBlock =
         _superDisallowed(() => _visitStatement(node.finalizer).toBlock());
@@ -3574,7 +3686,7 @@
   }
 
   @override
-  visitYieldStatement(YieldStatement node) {
+  JS.Statement visitYieldStatement(YieldStatement node) {
     var jsExpr = _visitExpression(node.expression);
     var star = node.isYieldStar;
     if (_asyncStarController != null) {
@@ -3601,7 +3713,7 @@
   }
 
   @override
-  visitVariableDeclaration(VariableDeclaration node) {
+  JS.Statement visitVariableDeclaration(VariableDeclaration node) {
     // TODO(jmesserly): casts are sometimes required here.
     // Kernel does not represent these explicitly.
     var v = _emitVariableDef(node);
@@ -3610,7 +3722,7 @@
   }
 
   @override
-  visitFunctionDeclaration(FunctionDeclaration node) {
+  JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
     var func = node.function;
     var fn = _emitFunction(func, node.variable.name);
 
@@ -3628,20 +3740,22 @@
   }
 
   @override
-  defaultExpression(Expression node) => _emitInvalidNode(node);
+  JS.Expression defaultExpression(Expression node) => _emitInvalidNode(node);
 
   @override
-  defaultBasicLiteral(BasicLiteral node) => defaultExpression(node);
+  JS.Expression defaultBasicLiteral(BasicLiteral node) =>
+      defaultExpression(node);
 
   @override
-  visitInvalidExpression(InvalidExpression node) => defaultExpression(node);
+  JS.Expression visitInvalidExpression(InvalidExpression node) =>
+      defaultExpression(node);
 
   @override
-  visitConstantExpression(ConstantExpression node) =>
-      node.constant.accept(this);
+  JS.Expression visitConstantExpression(ConstantExpression node) =>
+      node.constant.accept(this) as JS.Expression;
 
   @override
-  visitVariableGet(VariableGet node) {
+  JS.Expression visitVariableGet(VariableGet node) {
     var v = node.variable;
     var id = _emitVariableRef(v);
     if (id.name == v.name) {
@@ -3681,28 +3795,29 @@
 
   // TODO(jmesserly): resugar operators for kernel, such as ++x, x++, x+=.
   @override
-  visitVariableSet(VariableSet node) => _visitExpression(node.value)
-      .toAssignExpression(_emitVariableRef(node.variable));
+  JS.Expression visitVariableSet(VariableSet node) =>
+      _visitExpression(node.value)
+          .toAssignExpression(_emitVariableRef(node.variable));
 
   @override
-  visitPropertyGet(PropertyGet node) {
+  JS.Expression visitPropertyGet(PropertyGet node) {
     return _emitPropertyGet(
         node.receiver, node.interfaceTarget, node.name.name);
   }
 
   @override
-  visitPropertySet(PropertySet node) {
+  JS.Expression visitPropertySet(PropertySet node) {
     return _emitPropertySet(
         node.receiver, node.interfaceTarget, node.value, node.name.name);
   }
 
   @override
-  visitDirectPropertyGet(DirectPropertyGet node) {
+  JS.Expression visitDirectPropertyGet(DirectPropertyGet node) {
     return _emitPropertyGet(node.receiver, node.target);
   }
 
   @override
-  visitDirectPropertySet(DirectPropertySet node) {
+  JS.Expression visitDirectPropertySet(DirectPropertySet node) {
     return _emitPropertySet(node.receiver, node.target, node.value);
   }
 
@@ -3767,7 +3882,7 @@
   }
 
   @override
-  visitSuperPropertyGet(SuperPropertyGet node) {
+  JS.Expression visitSuperPropertyGet(SuperPropertyGet node) {
     var target = node.interfaceTarget;
     var jsTarget = _emitSuperTarget(target);
     if (_reifyTearoff(target)) {
@@ -3777,14 +3892,14 @@
   }
 
   @override
-  visitSuperPropertySet(SuperPropertySet node) {
+  JS.Expression visitSuperPropertySet(SuperPropertySet node) {
     var target = node.interfaceTarget;
     var jsTarget = _emitSuperTarget(target, setter: true);
     return _visitExpression(node.value).toAssignExpression(jsTarget);
   }
 
   @override
-  visitStaticGet(StaticGet node) => _emitStaticGet(node.target);
+  JS.Expression visitStaticGet(StaticGet node) => _emitStaticGet(node.target);
 
   JS.Expression _emitStaticGet(Member target) {
     // TODO(vsm): Re-inline constants.  See:
@@ -3800,19 +3915,19 @@
   }
 
   @override
-  visitStaticSet(StaticSet node) {
+  JS.Expression visitStaticSet(StaticSet node) {
     return _visitExpression(node.value)
         .toAssignExpression(_emitStaticTarget(node.target));
   }
 
   @override
-  visitMethodInvocation(MethodInvocation node) {
+  JS.Expression visitMethodInvocation(MethodInvocation node) {
     return _emitMethodCall(
         node.receiver, node.interfaceTarget, node.arguments, node);
   }
 
   @override
-  visitDirectMethodInvocation(DirectMethodInvocation node) {
+  JS.Expression visitDirectMethodInvocation(DirectMethodInvocation node) {
     return _emitMethodCall(node.receiver, node.target, node.arguments, node);
   }
 
@@ -3920,7 +4035,7 @@
     return null;
   }
 
-  _isDynamicOrFunction(DartType t) =>
+  bool _isDynamicOrFunction(DartType t) =>
       t == coreTypes.functionClass.rawType || t == const DynamicType();
 
   JS.Expression _emitUnaryOperator(
@@ -4276,7 +4391,7 @@
 
   // TODO(jmesserly): optimize super operators for kernel
   @override
-  visitSuperMethodInvocation(SuperMethodInvocation node) {
+  JS.Expression visitSuperMethodInvocation(SuperMethodInvocation node) {
     var target = node.interfaceTarget;
     return JS.Call(_emitSuperTarget(target),
         _emitArgumentList(node.arguments, target: target));
@@ -4310,13 +4425,12 @@
             isGetter: !setter, isSetter: setter);
       } else {
         var function = member.function;
-        var params = _emitTypeFormals(function.typeParameters);
-        for (var param in function.positionalParameters) {
-          params.add(JS.Identifier(param.name));
-        }
-        if (function.namedParameters.isNotEmpty) {
-          params.add(namedArgumentTemp);
-        }
+        var params = [
+          ..._emitTypeFormals(function.typeParameters),
+          for (var param in function.positionalParameters)
+            JS.Identifier(param.name),
+          if (function.namedParameters.isNotEmpty) namedArgumentTemp,
+        ];
 
         var fn = js.fun(
             'function(#) { return super[#](#); }', [params, jsName, params]);
@@ -4328,7 +4442,7 @@
   }
 
   @override
-  visitStaticInvocation(StaticInvocation node) {
+  JS.Expression visitStaticInvocation(StaticInvocation node) {
     var target = node.target;
     if (isInlineJS(target)) return _emitInlineJSCode(node) as JS.Expression;
     if (target.isFactory) return _emitFactoryInvocation(node);
@@ -4429,26 +4543,18 @@
   List<JS.Expression> _emitArgumentList(Arguments node,
       {bool types = true, Member target}) {
     types = types && _reifyGenericFunction(target);
-    var args = <JS.Expression>[];
-    if (types) {
-      for (var typeArg in node.types) {
-        args.add(_emitType(typeArg));
-      }
-    }
-    for (var arg in node.positional) {
-      if (arg is StaticInvocation &&
-          isJSSpreadInvocation(arg.target) &&
-          arg.arguments.positional.length == 1) {
-        args.add(JS.Spread(_visitExpression(arg.arguments.positional[0])));
-      } else {
-        args.add(_visitExpression(arg));
-      }
-    }
-    if (node.named.isNotEmpty) {
-      args.add(
-          JS.ObjectInitializer(node.named.map(_emitNamedExpression).toList()));
-    }
-    return args;
+    return [
+      if (types) for (var typeArg in node.types) _emitType(typeArg),
+      for (var arg in node.positional)
+        if (arg is StaticInvocation &&
+            isJSSpreadInvocation(arg.target) &&
+            arg.arguments.positional.length == 1)
+          JS.Spread(_visitExpression(arg.arguments.positional[0]))
+        else
+          _visitExpression(arg),
+      if (node.named.isNotEmpty)
+        JS.ObjectInitializer(node.named.map(_emitNamedExpression).toList()),
+    ];
   }
 
   JS.Property _emitNamedExpression(NamedExpression arg) {
@@ -4563,7 +4669,7 @@
   }
 
   @override
-  visitConstructorInvocation(ConstructorInvocation node) {
+  JS.Expression visitConstructorInvocation(ConstructorInvocation node) {
     var ctor = node.target;
     var args = node.arguments;
     var result = JS.New(_emitConstructorName(node.constructedType, ctor),
@@ -4586,7 +4692,9 @@
 
     if (isFromEnvironmentInvocation(coreTypes, node)) {
       var value = _constants.evaluate(node);
-      if (value is PrimitiveConstant) return value.accept(this);
+      if (value is PrimitiveConstant) {
+        return value.accept(this) as JS.Expression;
+      }
     }
 
     if (args.positional.isEmpty &&
@@ -4659,7 +4767,7 @@
   }
 
   @override
-  visitNot(Not node) {
+  JS.Expression visitNot(Not node) {
     var operand = node.operand;
     if (operand is MethodInvocation && operand.name.name == '==') {
       return _emitEqualityOperator(operand.receiver, operand.interfaceTarget,
@@ -4681,14 +4789,14 @@
   }
 
   @override
-  visitLogicalExpression(LogicalExpression node) {
+  JS.Expression visitLogicalExpression(LogicalExpression node) {
     // The operands of logical boolean operators are subject to boolean
     // conversion.
     return _visitTest(node);
   }
 
   @override
-  visitConditionalExpression(ConditionalExpression node) {
+  JS.Expression visitConditionalExpression(ConditionalExpression node) {
     return js.call('# ? # : #', [
       _visitTest(node.condition),
       _visitExpression(node.then),
@@ -4698,7 +4806,7 @@
   }
 
   @override
-  visitStringConcatenation(StringConcatenation node) {
+  JS.Expression visitStringConcatenation(StringConcatenation node) {
     var parts = <JS.Expression>[];
     for (var e in node.expressions) {
       var jsExpr = _visitExpression(e);
@@ -4707,20 +4815,20 @@
       }
       parts.add(e.getStaticType(types) == types.stringType && !isNullable(e)
           ? jsExpr
-          : runtimeCall('str(#)', jsExpr));
+          : runtimeCall('str(#)', [jsExpr]));
     }
     if (parts.isEmpty) return js.string('');
     return JS.Expression.binary(parts, '+');
   }
 
   @override
-  visitListConcatenation(ListConcatenation node) {
+  JS.Expression visitListConcatenation(ListConcatenation node) {
     // Only occurs inside unevaluated constants.
     List<JS.Expression> entries = [];
     _concatenate(Expression node) {
-      if (node is ListConcatenation)
+      if (node is ListConcatenation) {
         node.lists.forEach(_concatenate);
-      else {
+      } else {
         node.accept(this);
         if (node is ConstantExpression) {
           var list = node.constant as ListConstant;
@@ -4736,13 +4844,13 @@
   }
 
   @override
-  visitSetConcatenation(SetConcatenation node) {
+  JS.Expression visitSetConcatenation(SetConcatenation node) {
     // Only occurs inside unevaluated constants.
     List<JS.Expression> entries = [];
     _concatenate(Expression node) {
-      if (node is SetConcatenation)
+      if (node is SetConcatenation) {
         node.sets.forEach(_concatenate);
-      else {
+      } else {
         node.accept(this);
         if (node is ConstantExpression) {
           var set = node.constant as SetConstant;
@@ -4758,13 +4866,13 @@
   }
 
   @override
-  visitMapConcatenation(MapConcatenation node) {
+  JS.Expression visitMapConcatenation(MapConcatenation node) {
     // Only occurs inside unevaluated constants.
     List<JS.Expression> entries = [];
     _concatenate(Expression node) {
-      if (node is MapConcatenation)
+      if (node is MapConcatenation) {
         node.maps.forEach(_concatenate);
-      else {
+      } else {
         node.accept(this);
         if (node is ConstantExpression) {
           var map = node.constant as MapConstant;
@@ -4786,13 +4894,13 @@
   }
 
   @override
-  visitInstanceCreation(InstanceCreation node) {
+  JS.Expression visitInstanceCreation(InstanceCreation node) {
     // Only occurs inside unevaluated constants.
     throw new UnsupportedError("Instance creation");
   }
 
   @override
-  visitIsExpression(IsExpression node) {
+  JS.Expression visitIsExpression(IsExpression node) {
     return _emitIsExpression(node.operand, node.type);
   }
 
@@ -4809,7 +4917,7 @@
   }
 
   @override
-  visitAsExpression(AsExpression node) {
+  JS.Expression visitAsExpression(AsExpression node) {
     Expression fromExpr = node.operand;
     var to = node.type;
     var jsFrom = _visitExpression(fromExpr);
@@ -4843,7 +4951,7 @@
         // TODO(jmesserly): fuse this with notNull check.
         // TODO(jmesserly): this does not correctly distinguish user casts from
         // required-for-soundness casts.
-        return runtimeCall('asInt(#)', jsFrom);
+        return runtimeCall('asInt(#)', [jsFrom]);
       }
 
       // A no-op in JavaScript.
@@ -4862,32 +4970,34 @@
   }
 
   @override
-  visitSymbolLiteral(SymbolLiteral node) => emitDartSymbol(node.value);
+  JS.Expression visitSymbolLiteral(SymbolLiteral node) =>
+      emitDartSymbol(node.value);
 
   @override
-  visitTypeLiteral(TypeLiteral node) => _emitTypeLiteral(node.type);
+  JS.Expression visitTypeLiteral(TypeLiteral node) =>
+      _emitTypeLiteral(node.type);
 
-  _emitTypeLiteral(DartType type) {
+  JS.Expression _emitTypeLiteral(DartType type) {
     var typeRep = _emitType(type);
     // If the type is a type literal expression in Dart code, wrap the raw
     // runtime type in a "Type" instance.
-    return _isInForeignJS ? typeRep : runtimeCall('wrapType(#)', typeRep);
+    return _isInForeignJS ? typeRep : runtimeCall('wrapType(#)', [typeRep]);
   }
 
   @override
-  visitThisExpression(ThisExpression node) => JS.This();
+  JS.Expression visitThisExpression(ThisExpression node) => JS.This();
 
   @override
-  visitRethrow(Rethrow node) {
-    return runtimeCall('rethrow(#)', _emitVariableRef(_rethrowParameter));
+  JS.Expression visitRethrow(Rethrow node) {
+    return runtimeCall('rethrow(#)', [_emitVariableRef(_rethrowParameter)]);
   }
 
   @override
-  visitThrow(Throw node) =>
-      runtimeCall('throw(#)', _visitExpression(node.expression));
+  JS.Expression visitThrow(Throw node) =>
+      runtimeCall('throw(#)', [_visitExpression(node.expression)]);
 
   @override
-  visitListLiteral(ListLiteral node) {
+  JS.Expression visitListLiteral(ListLiteral node) {
     var elementType = node.typeArgument;
     var elements = _visitExpressionList(node.expressions);
     // TODO(markzipan): remove const check when we use front-end const eval
@@ -4919,7 +5029,7 @@
   }
 
   @override
-  visitSetLiteral(SetLiteral node) {
+  JS.Expression visitSetLiteral(SetLiteral node) {
     // TODO(markzipan): remove const check when we use front-end const eval
     if (!node.isConst) {
       var setType = visitInterfaceType(
@@ -4941,12 +5051,13 @@
   }
 
   @override
-  visitMapLiteral(MapLiteral node) {
-    var entries = <JS.Expression>[];
-    for (var e in node.entries) {
-      entries.add(_visitExpression(e.key));
-      entries.add(_visitExpression(e.value));
-    }
+  JS.Expression visitMapLiteral(MapLiteral node) {
+    var entries = [
+      for (var e in node.entries) ...[
+        _visitExpression(e.key),
+        _visitExpression(e.value),
+      ],
+    ];
 
     // TODO(markzipan): remove const check when we use front-end const eval
     if (!node.isConst) {
@@ -4967,11 +5078,11 @@
   }
 
   @override
-  visitAwaitExpression(AwaitExpression node) =>
+  JS.Expression visitAwaitExpression(AwaitExpression node) =>
       JS.Yield(_visitExpression(node.operand));
 
   @override
-  visitFunctionExpression(FunctionExpression node) {
+  JS.Expression visitFunctionExpression(FunctionExpression node) {
     var fn = _emitArrowFunction(node);
     if (!_reifyFunctionType(node.function)) return fn;
     return _emitFunctionTagged(fn, node.getStaticType(types) as FunctionType);
@@ -4983,11 +5094,11 @@
 
     // Simplify `=> { return e; }` to `=> e`
     if (body is JS.Block) {
-      JS.Block block = body;
+      var block = body as JS.Block;
       if (block.statements.length == 1) {
         JS.Statement s = block.statements[0];
         if (s is JS.Block) {
-          block = s;
+          block = s as JS.Block;
           s = block.statements.length == 1 ? block.statements[0] : null;
         }
         if (s is JS.Return && s.value != null) body = s.value;
@@ -5000,22 +5111,24 @@
   }
 
   @override
-  visitStringLiteral(StringLiteral node) => js.escapedString(node.value, '"');
+  JS.Expression visitStringLiteral(StringLiteral node) =>
+      js.escapedString(node.value, '"');
 
   @override
-  visitIntLiteral(IntLiteral node) => js.uint64(node.value);
+  JS.Expression visitIntLiteral(IntLiteral node) => js.uint64(node.value);
 
   @override
-  visitDoubleLiteral(DoubleLiteral node) => js.number(node.value);
+  JS.Expression visitDoubleLiteral(DoubleLiteral node) => js.number(node.value);
 
   @override
-  visitBoolLiteral(BoolLiteral node) => JS.LiteralBool(node.value);
+  JS.Expression visitBoolLiteral(BoolLiteral node) =>
+      JS.LiteralBool(node.value);
 
   @override
-  visitNullLiteral(NullLiteral node) => JS.LiteralNull();
+  JS.Expression visitNullLiteral(NullLiteral node) => JS.LiteralNull();
 
   @override
-  visitLet(Let node) {
+  JS.Expression visitLet(Let node) {
     var v = node.variable;
     var init = _visitExpression(v.initializer);
     var body = _visitExpression(node.body);
@@ -5037,12 +5150,12 @@
   }
 
   @override
-  visitBlockExpression(BlockExpression node) {
+  JS.Expression visitBlockExpression(BlockExpression node) {
     var jsExpr = _visitExpression(node.value);
-    List<JS.Statement> jsStmts = node.body.statements
-        .map(_visitStatement)
-        .toList()
-          ..add(JS.Return(jsExpr));
+    var jsStmts = [
+      for (var s in node.body.statements) _visitStatement(s),
+      JS.Return(jsExpr),
+    ];
     var jsBlock = JS.Block(jsStmts);
     // BlockExpressions with async operations must be constructed
     // with a generator instead of a lambda.
@@ -5060,7 +5173,7 @@
   }
 
   @override
-  visitInstantiation(Instantiation node) {
+  JS.Expression visitInstantiation(Instantiation node) {
     return runtimeCall('gbind(#, #)', [
       _visitExpression(node.expression),
       node.typeArguments.map(_emitType).toList()
@@ -5068,14 +5181,16 @@
   }
 
   @override
-  visitLoadLibrary(LoadLibrary node) => runtimeCall('loadLibrary()');
+  JS.Expression visitLoadLibrary(LoadLibrary node) =>
+      runtimeCall('loadLibrary()');
 
   // TODO(jmesserly): DDC loads all libraries eagerly.
   // See
   // https://github.com/dart-lang/sdk/issues/27776
   // https://github.com/dart-lang/sdk/issues/27777
   @override
-  visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) => js.boolean(true);
+  JS.Expression visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
+      js.boolean(true);
 
   bool _reifyFunctionType(FunctionNode f) {
     if (_currentLibrary.importUri.scheme != 'dart') return true;
@@ -5118,18 +5233,19 @@
   /// Calls [findAnnotation] followed by [getNameFromAnnotation].
   String getAnnotationName(NamedNode node, bool test(Expression value)) {
     return _constants.getFieldValueFromAnnotation(
-        findAnnotation(node, test), 'name');
+        findAnnotation(node, test), 'name') as String;
   }
 
-  JS.Expression visitConstant(Constant node) => node.accept(this);
+  JS.Expression visitConstant(Constant node) =>
+      node.accept(this) as JS.Expression;
   @override
-  visitNullConstant(NullConstant node) => JS.LiteralNull();
+  JS.Expression visitNullConstant(NullConstant node) => JS.LiteralNull();
   @override
-  visitBoolConstant(BoolConstant node) => js.boolean(node.value);
+  JS.Expression visitBoolConstant(BoolConstant node) => js.boolean(node.value);
   @override
-  visitIntConstant(IntConstant node) => js.number(node.value);
+  JS.Expression visitIntConstant(IntConstant node) => js.number(node.value);
   @override
-  visitDoubleConstant(DoubleConstant node) {
+  JS.Expression visitDoubleConstant(DoubleConstant node) {
     var value = node.value;
 
     // Emit the constant as an integer, if possible.
@@ -5147,41 +5263,41 @@
   }
 
   @override
-  visitStringConstant(StringConstant node) => js.escapedString(node.value, '"');
+  JS.Expression visitStringConstant(StringConstant node) =>
+      js.escapedString(node.value, '"');
 
   // DDC does not currently use the non-primivite constant nodes; rather these
   // are emitted via their normal expression nodes.
   @override
-  defaultConstant(Constant node) => _emitInvalidNode(node);
+  JS.Expression defaultConstant(Constant node) => _emitInvalidNode(node);
 
   @override
-  visitSymbolConstant(node) => emitDartSymbol(node.name);
+  JS.Expression visitSymbolConstant(SymbolConstant node) =>
+      emitDartSymbol(node.name);
 
   @override
-  visitMapConstant(node) {
-    var entries = <JS.Expression>[];
-    for (var e in node.entries) {
-      entries.add(visitConstant(e.key));
-      entries.add(visitConstant(e.value));
-    }
-
+  JS.Expression visitMapConstant(MapConstant node) {
+    var entries = [
+      for (var e in node.entries) ...[
+        visitConstant(e.key),
+        visitConstant(e.value),
+      ],
+    ];
     return _emitConstMap(node.keyType, node.valueType, entries);
   }
 
   @override
-  visitListConstant(node) => _emitConstList(
+  JS.Expression visitListConstant(ListConstant node) => _emitConstList(
       node.typeArgument, node.entries.map(visitConstant).toList());
 
   @override
-  visitSetConstant(node) {
-    return _emitConstSet(
-        node.typeArgument, node.entries.map(visitConstant).toList());
-  }
+  JS.Expression visitSetConstant(SetConstant node) => _emitConstSet(
+      node.typeArgument, node.entries.map(visitConstant).toList());
 
   @override
-  visitInstanceConstant(node) {
+  JS.Expression visitInstanceConstant(InstanceConstant node) {
     entryToProperty(MapEntry<Reference, Constant> entry) {
-      var constant = entry.value.accept(this);
+      var constant = entry.value.accept(this) as JS.Expression;
       var member = entry.key.asField;
       return JS.Property(
           _emitMemberName(member.name.name, member: member), constant);
@@ -5189,30 +5305,33 @@
 
     var type = visitInterfaceType(node.getType(types) as InterfaceType);
     var prototype = js.call("#.prototype", [type]);
-    var properties = [JS.Property(propertyName("__proto__"), prototype)]
-      ..addAll(node.fieldValues.entries.map(entryToProperty));
+    var properties = [
+      JS.Property(propertyName("__proto__"), prototype),
+      for (var e in node.fieldValues.entries) entryToProperty(e),
+    ];
     return canonicalizeConstObject(
         JS.ObjectInitializer(properties, multiline: true));
   }
 
   @override
-  visitTearOffConstant(node) => _emitStaticGet(node.procedure);
+  JS.Expression visitTearOffConstant(TearOffConstant node) =>
+      _emitStaticGet(node.procedure);
 
   @override
-  visitTypeLiteralConstant(node) => _emitTypeLiteral(node.type);
+  JS.Expression visitTypeLiteralConstant(TypeLiteralConstant node) =>
+      _emitTypeLiteral(node.type);
 
   @override
-  visitPartialInstantiationConstant(node) {
-    return runtimeCall('gbind(#, #)', [
-      visitConstant(node.tearOffConstant),
-      node.types.map(_emitType).toList()
-    ]);
-  }
+  JS.Expression visitPartialInstantiationConstant(
+          PartialInstantiationConstant node) =>
+      runtimeCall('gbind(#, #)', [
+        visitConstant(node.tearOffConstant),
+        node.types.map(_emitType).toList()
+      ]);
 
   @override
-  visitUnevaluatedConstant(node) {
-    return _visitExpression(node.expression);
-  }
+  JS.Expression visitUnevaluatedConstant(UnevaluatedConstant node) =>
+      _visitExpression(node.expression);
 }
 
 bool _isInlineJSFunction(Statement body) {
@@ -5261,3 +5380,10 @@
   }
   return false;
 }
+
+class SwitchLabelState {
+  String label;
+  JS.Identifier variable;
+
+  SwitchLabelState(this.label, this.variable);
+}
diff --git a/pkg/dev_compiler/lib/src/kernel/constants.dart b/pkg/dev_compiler/lib/src/kernel/constants.dart
index 55885a5..3066d8e 100644
--- a/pkg/dev_compiler/lib/src/kernel/constants.dart
+++ b/pkg/dev_compiler/lib/src/kernel/constants.dart
@@ -118,14 +118,21 @@
   final CoreTypes coreTypes;
   _ConstantVisitor(this.coreTypes);
 
-  bool isConstant(Expression e) => e.accept(this);
+  bool isConstant(Expression e) => e.accept(this) as bool;
 
+  @override
   defaultExpression(node) => false;
+  @override
   defaultBasicLiteral(node) => true;
+  @override
   visitTypeLiteral(node) => true; // TODO(jmesserly): deferred libraries?
+  @override
   visitSymbolLiteral(node) => true;
+  @override
   visitListLiteral(node) => node.isConst;
+  @override
   visitMapLiteral(node) => node.isConst;
+  @override
   visitStaticInvocation(node) {
     return node.isConst ||
         node.target == coreTypes.identicalProcedure &&
@@ -135,27 +142,34 @@
             node.arguments.named.every((n) => isConstant(n.value));
   }
 
+  @override
   visitDirectMethodInvocation(node) {
     return node.receiver is BasicLiteral &&
         isOperatorMethodName(node.name.name) &&
         node.arguments.positional.every((p) => p is BasicLiteral);
   }
 
+  @override
   visitMethodInvocation(node) {
     return node.receiver is BasicLiteral &&
         isOperatorMethodName(node.name.name) &&
         node.arguments.positional.every((p) => p is BasicLiteral);
   }
 
+  @override
   visitConstructorInvocation(node) => node.isConst;
+  @override
   visitStringConcatenation(node) =>
       node.expressions.every((e) => e is BasicLiteral);
+  @override
   visitStaticGet(node) {
     var target = node.target;
     return target is Procedure || target is Field && target.isConst;
   }
 
+  @override
   visitVariableGet(node) => node.variable.isConst;
+  @override
   visitNot(node) {
     var operand = node.operand;
     return operand is BoolLiteral ||
@@ -164,13 +178,16 @@
         operand is MethodInvocation && visitMethodInvocation(operand);
   }
 
+  @override
   visitLogicalExpression(node) =>
       node.left is BoolLiteral && node.right is BoolLiteral;
+  @override
   visitConditionalExpression(node) =>
       node.condition is BoolLiteral &&
       node.then is BoolLiteral &&
       node.otherwise is BoolLiteral;
 
+  @override
   visitLet(Let node) {
     var init = node.variable.initializer;
     return (init == null || isConstant(init)) && isConstant(node.body);
@@ -183,6 +200,23 @@
 
   @override
   NumberSemantics get numberSemantics => NumberSemantics.js;
+
+  @override
+  bool shouldInlineConstant(ConstantExpression initializer) {
+    Constant constant = initializer.constant;
+    if (constant is StringConstant) {
+      // Only inline small string constants, not large ones.
+      // (The upper bound value is arbitrary.)
+      return constant.value.length < 32;
+    } else if (constant is PrimitiveConstant) {
+      // Inline all other primitives.
+      return true;
+    } else {
+      // Don't inline other constants, because it would take too much code size.
+      // Better to refer to them by their field/variable name.
+      return false;
+    }
+  }
 }
 
 class _ErrorReporter extends SimpleErrorReporter {
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index bca5ea6..3b3b66a 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -276,3 +276,56 @@
   }
   return sc;
 }
+
+/// Returns true if a switch statement contains any continues with a label.
+bool hasLabeledContinue(SwitchStatement node) {
+  var visitor = LabelContinueFinder();
+  node.accept(visitor);
+  return visitor.found;
+}
+
+class LabelContinueFinder extends StatementVisitor {
+  var found = false;
+
+  visit(Statement s) {
+    if (!found && s != null) s.accept(this);
+  }
+
+  @override
+  visitBlock(Block node) => node.statements.forEach(visit);
+  @override
+  visitAssertBlock(AssertBlock node) => node.statements.forEach(visit);
+  @override
+  visitWhileStatement(WhileStatement node) => visit(node.body);
+  @override
+  visitDoStatement(DoStatement node) => visit(node.body);
+  @override
+  visitForStatement(ForStatement node) => visit(node.body);
+  @override
+  visitForInStatement(ForInStatement node) => visit(node.body);
+  @override
+  visitContinueSwitchStatement(ContinueSwitchStatement node) => found = true;
+
+  @override
+  visitSwitchStatement(SwitchStatement node) {
+    node.cases.forEach((c) => visit(c.body));
+  }
+
+  @override
+  visitIfStatement(IfStatement node) {
+    visit(node.then);
+    visit(node.otherwise);
+  }
+
+  @override
+  visitTryCatch(TryCatch node) {
+    visit(node.body);
+    node.catches.forEach((c) => visit(c.body));
+  }
+
+  @override
+  visitTryFinally(TryFinally node) {
+    visit(node.body);
+    visit(node.finalizer);
+  }
+}
diff --git a/pkg/dev_compiler/lib/src/kernel/native_types.dart b/pkg/dev_compiler/lib/src/kernel/native_types.dart
index 99a2140..d5450f6 100644
--- a/pkg/dev_compiler/lib/src/kernel/native_types.dart
+++ b/pkg/dev_compiler/lib/src/kernel/native_types.dart
@@ -142,7 +142,7 @@
   /// field (which is also the constructor parameter).
   String _getNativeAnnotationName(Expression annotation) {
     if (!_isNativeAnnotation(annotation)) return null;
-    return constants.getFieldValueFromAnnotation(annotation, 'name');
+    return constants.getFieldValueFromAnnotation(annotation, 'name') as String;
   }
 }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index 185d3f0..481a4e8 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -230,7 +230,7 @@
   @override
   visitConstantExpression(ConstantExpression node) {
     var c = node.constant;
-    if (c is UnevaluatedConstant) return c.expression.accept(this);
+    if (c is UnevaluatedConstant) return c.expression.accept(this) as bool;
     if (c is PrimitiveConstant) return c.value == null;
     return false;
   }
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 4b08093..e954139 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -8,19 +8,28 @@
 import 'package:kernel/core_types.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/target/targets.dart';
+import 'package:kernel/transformations/track_widget_constructor_locations.dart';
 import 'constants.dart' show DevCompilerConstantsBackend;
 import 'kernel_helpers.dart';
 
 /// A kernel [Target] to configure the Dart Front End for dartdevc.
 class DevCompilerTarget extends Target {
+  DevCompilerTarget(this.flags);
+
+  final TargetFlags flags;
+
   ClassHierarchy hierarchy;
 
+  @override
   bool get legacyMode => false;
 
+  @override
   bool get enableSuperMixins => true;
 
+  @override
   String get name => 'dartdevc';
 
+  @override
   List<String> get extraRequiredLibraries => const [
         'dart:_runtime',
         'dart:_debugger',
@@ -58,8 +67,21 @@
       uri.scheme == 'dart' &&
       (uri.path == 'core' || uri.path == '_interceptors');
 
+  bool _allowedTestLibrary(Uri uri) {
+    String scriptName = uri.path;
+    return scriptName.contains('tests/compiler/dartdevc_native');
+  }
+
+  bool _allowedDartLibrary(Uri uri) => uri.scheme == 'dart';
+
   @override
-  bool enableNative(Uri uri) => uri.scheme == 'dart';
+  bool enableNative(Uri uri) =>
+      _allowedTestLibrary(uri) || _allowedDartLibrary(uri);
+
+  @override
+  bool allowPlatformPrivateLibraryAccess(Uri importer, Uri imported) =>
+      super.allowPlatformPrivateLibraryAccess(importer, imported) ||
+      _allowedTestLibrary(importer);
 
   @override
   bool get nativeExtensionExpectsString => false;
@@ -88,6 +110,18 @@
   }
 
   @override
+  void performPreConstantEvaluationTransformations(
+      Component component,
+      CoreTypes coreTypes,
+      List<Library> libraries,
+      DiagnosticReporter diagnosticReporter,
+      {void logger(String msg)}) {
+    if (flags.trackWidgetCreation) {
+      WidgetCreatorTracker().transform(component, libraries);
+    }
+  }
+
+  @override
   Expression instantiateInvocation(CoreTypes coreTypes, Expression receiver,
       String name, Arguments arguments, int offset, bool isSuper) {
     // TODO(jmesserly): preserve source information?
diff --git a/pkg/dev_compiler/lib/src/kernel/type_table.dart b/pkg/dev_compiler/lib/src/kernel/type_table.dart
index 313e8c9..7dd63c9 100644
--- a/pkg/dev_compiler/lib/src/kernel/type_table.dart
+++ b/pkg/dev_compiler/lib/src/kernel/type_table.dart
@@ -116,6 +116,7 @@
 
   _GeneratorTable(this._runtimeModule);
 
+  @override
   JS.Statement _dischargeType(DartType t) {
     var name = _names.remove(t);
     if (name != null) {
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
index ea33a0b..7ca09fb 100644
--- a/pkg/dev_compiler/pubspec.yaml
+++ b/pkg/dev_compiler/pubspec.yaml
@@ -2,7 +2,7 @@
 publish_to: none
 
 environment:
-  sdk: '>=2.1.0 <3.0.0'
+  sdk: '>=2.3.0 <3.0.0'
 
 dependencies:
   analyzer: any
diff --git a/pkg/dev_compiler/test/js/builder_test.dart b/pkg/dev_compiler/test/js/builder_test.dart
index d294048..0dfae14 100644
--- a/pkg/dev_compiler/test/js/builder_test.dart
+++ b/pkg/dev_compiler/test/js/builder_test.dart
@@ -13,7 +13,7 @@
 
 _checkExpression(String src) => _check(_parser(src).parseExpression(), src);
 
-main() {
+void main() {
   group('MiniJsParser', () {
     // TODO(ochafik): Add more coverage.
     test('parses classes with complex members', () {
diff --git a/pkg/dev_compiler/test/modular_suite.dart b/pkg/dev_compiler/test/modular_suite.dart
new file mode 100644
index 0000000..78c22cb
--- /dev/null
+++ b/pkg/dev_compiler/test/modular_suite.dart
@@ -0,0 +1,335 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Test the modular compilation pipeline of ddc.
+///
+/// This is a shell that runs multiple tests, one per folder under `data/`.
+import 'dart:io';
+
+import 'package:modular_test/src/io_pipeline.dart';
+import 'package:modular_test/src/pipeline.dart';
+import 'package:modular_test/src/suite.dart';
+import 'package:modular_test/src/runner.dart';
+
+Uri sdkRoot = Platform.script.resolve("../../../");
+Options _options;
+String _dartdevcScript;
+String _kernelWorkerScript;
+main(List<String> args) async {
+  _options = Options.parse(args);
+  await _resolveScripts();
+  await runSuite(
+      sdkRoot.resolve('tests/modular/'),
+      'tests/modular',
+      _options,
+      new IOPipeline([
+        SourceToSummaryDillStep(),
+        DDKStep(),
+        RunD8(),
+      ], cacheSharedModules: true));
+}
+
+const dillId = const DataId("dill");
+const jsId = const DataId("js");
+const txtId = const DataId("txt");
+
+class SourceToSummaryDillStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [dillId];
+
+  @override
+  bool get needsSources => true;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [dillId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [];
+
+  @override
+  bool get onlyOnMain => false;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: source-to-dill on $module");
+
+    // We use non file-URI schemes for representing source locations in a
+    // root-agnostic way. This allows us to refer to file across modules and
+    // across steps without exposing the underlying temporary folders that are
+    // created by the framework. In build systems like bazel this is especially
+    // important because each step may be run on a different machine.
+    //
+    // Files in packages are defined in terms of `package:` URIs, while
+    // non-package URIs are defined using the `dart-dev-app` scheme.
+    String rootScheme = module.isSdk ? 'dev-dart-sdk' : 'dev-dart-app';
+    String sourceToImportUri(Uri relativeUri) =>
+        _sourceToImportUri(module, rootScheme, relativeUri);
+
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    _createPackagesFile(module, root, transitiveDependencies);
+
+    List<String> sources;
+    List<String> extraArgs;
+    if (module.isSdk) {
+      sources = ['dart:core'];
+      extraArgs = ['--libraries-file', '$rootScheme:///sdk/lib/libraries.json'];
+      assert(transitiveDependencies.isEmpty);
+    } else {
+      sources = module.sources.map(sourceToImportUri).toList();
+      extraArgs = ['--packages-file', '$rootScheme:/.packages'];
+    }
+
+    List<String> args = [
+      _kernelWorkerScript,
+      '--summary-only',
+      '--target',
+      'ddc',
+      '--multi-root',
+      '$root',
+      '--multi-root-scheme',
+      rootScheme,
+      ...extraArgs,
+      '--output',
+      '${toUri(module, dillId)}',
+      ...(transitiveDependencies
+          .expand((m) => ['--input-linked', '${toUri(m, dillId)}'])),
+      ...(sources.expand((String uri) => ['--source', uri])),
+      ...(flags.expand((String flag) => ['--enable-experiment', flag])),
+    ];
+
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: source-to-dill on $module");
+  }
+}
+
+class DDKStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [jsId];
+
+  @override
+  bool get needsSources => true;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [dillId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [dillId];
+
+  @override
+  bool get onlyOnMain => false;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: ddk on $module");
+
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    _createPackagesFile(module, root, transitiveDependencies);
+
+    String rootScheme = module.isSdk ? 'dev-dart-sdk' : 'dev-dart-app';
+    List<String> sources;
+    List<String> extraArgs;
+    if (module.isSdk) {
+      sources = ['dart:core'];
+      extraArgs = ['--compile-sdk'];
+      assert(transitiveDependencies.isEmpty);
+    } else {
+      Module sdkModule = module.dependencies.firstWhere((m) => m.isSdk);
+      sources = module.sources
+          .map((relativeUri) =>
+              _sourceToImportUri(module, rootScheme, relativeUri))
+          .toList();
+      extraArgs = [
+        '--dart-sdk-summary',
+        '${toUri(sdkModule, dillId)}',
+        '--packages',
+        '.packages',
+      ];
+    }
+
+    Uri output = toUri(module, jsId);
+
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      _dartdevcScript,
+      '--kernel',
+      '--modules=es6',
+      '--no-summarize',
+      '--no-source-map',
+      '--multi-root-scheme',
+      rootScheme,
+      ...sources,
+      ...extraArgs,
+      for (String flag in flags) '--enable-experiment=$flag',
+      ...(transitiveDependencies
+          .where((m) => !m.isSdk)
+          .expand((m) => ['-s', '${toUri(m, dillId)}=${m.name}'])),
+      '-o',
+      '$output',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: ddk on $module");
+  }
+}
+
+class RunD8 implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [txtId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [jsId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [jsId];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: d8 on $module");
+
+    // Rename sdk.js to dart_sdk.js (the alternative, but more hermetic solution
+    // would be to rename the import on all other .js files, but seems
+    // overkill/unnecessary.
+    if (await File.fromUri(root.resolve('dart_sdk.js')).exists()) {
+      throw 'error: dart_sdk.js already exists.';
+    }
+
+    await File.fromUri(root.resolve('sdk.js'))
+        .copy(root.resolve('dart_sdk.js').toFilePath());
+    var runjs = '''
+    import { dart, _isolate_helper } from 'dart_sdk.js';
+    import { main } from 'main.js';
+    _isolate_helper.startRootIsolate(() => {}, []);
+    main.main();
+    ''';
+
+    var wrapper =
+        root.resolveUri(toUri(module, jsId)).toFilePath() + ".wrapper.js";
+    await File(wrapper).writeAsString(runjs);
+    List<String> d8Args = ['--module', wrapper];
+    var result = await _runProcess(
+        sdkRoot.resolve(_d8executable).toFilePath(), d8Args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+
+    await File.fromUri(root.resolveUri(toUri(module, txtId)))
+        .writeAsString(result.stdout as String);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: d8 on $module");
+  }
+}
+
+void _checkExitCode(ProcessResult result, IOModularStep step, Module module) {
+  if (result.exitCode != 0 || _options.verbose) {
+    stdout.write(result.stdout);
+    stderr.write(result.stderr);
+  }
+  if (result.exitCode != 0) {
+    throw "${step.runtimeType} failed on $module:\n\n"
+        "stdout:\n${result.stdout}\n\n"
+        "stderr:\n${result.stderr}";
+  }
+}
+
+Future<ProcessResult> _runProcess(
+    String command, List<String> arguments, String workingDirectory) {
+  if (_options.verbose) {
+    print('command:\n$command ${arguments.join(' ')} from $workingDirectory');
+  }
+  return Process.run(command, arguments, workingDirectory: workingDirectory);
+}
+
+String get _d8executable {
+  if (Platform.isWindows) {
+    return 'third_party/d8/windows/d8.exe';
+  } else if (Platform.isLinux) {
+    return 'third_party/d8/linux/d8';
+  } else if (Platform.isMacOS) {
+    return 'third_party/d8/macos/d8';
+  }
+  throw new UnsupportedError('Unsupported platform.');
+}
+
+Future<void> _createPackagesFile(
+    Module module, Uri root, Set<Module> transitiveDependencies) async {
+  // We create a .packages file which defines the location of this module if
+  // it is a package.  The CFE requires that if a `package:` URI of a
+  // dependency is used in an import, then we need that package entry in the
+  // .packages file. However, after it checks that the definition exists, the
+  // CFE will not actually use the resolved URI if a library for the import
+  // URI is already found in one of the provided .dill files of the
+  // dependencies. For that reason, and to ensure that a step only has access
+  // to the files provided in a module, we generate a .packages with invalid
+  // folders for other packages.
+  // TODO(sigmund): follow up with the CFE to see if we can remove the need
+  // for the .packages entry altogether if they won't need to read the
+  // sources.
+  var packagesContents = new StringBuffer();
+  if (module.isPackage) {
+    packagesContents.write('${module.name}:${module.packageBase}\n');
+  }
+  for (Module dependency in transitiveDependencies) {
+    if (dependency.isPackage) {
+      packagesContents.write('${dependency.name}:unused\n');
+    }
+  }
+
+  await File.fromUri(root.resolve('.packages'))
+      .writeAsString('$packagesContents');
+}
+
+String _sourceToImportUri(Module module, String rootScheme, Uri relativeUri) {
+  if (module.isPackage) {
+    var basePath = module.packageBase.path;
+    var packageRelativePath = basePath == "./"
+        ? relativeUri.path
+        : relativeUri.path.substring(basePath.length);
+    return 'package:${module.name}/$packageRelativePath';
+  } else {
+    return '$rootScheme:/$relativeUri';
+  }
+}
+
+Future<void> _resolveScripts() async {
+  Future<String> resolve(
+      String sdkSourcePath, String relativeSnapshotPath) async {
+    String result = sdkRoot.resolve(sdkSourcePath).toFilePath();
+    if (_options.useSdk) {
+      String snapshot = Uri.file(Platform.resolvedExecutable)
+          .resolve(relativeSnapshotPath)
+          .toFilePath();
+      if (await File(snapshot).exists()) {
+        return snapshot;
+      }
+    }
+    return result;
+  }
+
+  _dartdevcScript = await resolve(
+      'pkg/dev_compiler/bin/dartdevc.dart', 'snapshots/dartdevc.dart.snapshot');
+  _kernelWorkerScript = await resolve('utils/bazel/kernel_worker.dart',
+      'snapshots/kernel_worker.dart.snapshot');
+}
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index e7cb728..7690119 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -8,6 +8,7 @@
 import 'package:kernel/core_types.dart';
 import 'package:kernel/kernel.dart';
 import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/target/targets.dart';
 import 'package:test/test.dart';
 
 import 'package:dev_compiler/src/kernel/command.dart';
@@ -338,7 +339,7 @@
           // arithmetic operation results on `i` are themselves not null, even
           // though `i` is nullable.
           '0, i.{dart.core::num::<}(10), 10, i = i.{dart.core::num::+}(1), '
-          'i.{dart.core::num::+}(1), 1, i.{dart.core::num::>=}(10), 10');
+              'i.{dart.core::num::+}(1), 1, i.{dart.core::num::>=}(10), 10');
     });
     test('for-in', () async {
       await expectNotNull('''main() {
@@ -429,7 +430,7 @@
       test('parameters', () async {
         await expectNotNull(
             '$imports f(@notNull x, [@notNull y, @notNull z = 42]) '
-            '{ x; y; z; }',
+                '{ x; y; z; }',
             '42, x, y, z');
       });
       test('named parameters', () async {
@@ -456,7 +457,7 @@
     test('method', () async {
       await expectNotNull(
           'library b; $imports class C { @notNull m() {} } '
-          'main() { var c = new C(); c.m(); }',
+              'main() { var c = new C(); c.m(); }',
           'new b::C::•(), c.{b::C::m}(), c');
     });
   });
@@ -575,8 +576,8 @@
   var mainUri = Uri.file('/memory/test.dart');
   _fileSystem.entityForUri(mainUri).writeAsStringSync(code);
   var oldCompilerState = _compilerState;
-  _compilerState = await fe.initializeCompiler(
-      oldCompilerState, sdkUri, packagesUri, null, [], DevCompilerTarget(),
+  _compilerState = await fe.initializeCompiler(oldCompilerState, false, null,
+      sdkUri, packagesUri, null, [], DevCompilerTarget(TargetFlags()),
       fileSystem: _fileSystem, experiments: const {});
   if (!identical(oldCompilerState, _compilerState)) inference = null;
   fe.DdcResult result =
diff --git a/pkg/dev_compiler/test/options/options_test.dart b/pkg/dev_compiler/test/options/options_test.dart
index 3f5b3b1..7f78142 100644
--- a/pkg/dev_compiler/test/options/options_test.dart
+++ b/pkg/dev_compiler/test/options/options_test.dart
@@ -24,7 +24,7 @@
 
 final sdkSummaryArgs = ['--$sdkSummaryPathOption', sdkSummaryFile];
 
-main() {
+void main() {
   test('basic', () {
     var options = AnalyzerOptions.basic()..analysisRoot = optionsDir;
     var driver = CompilerAnalysisDriver(options);
diff --git a/pkg/dev_compiler/test/sourcemap/common.dart b/pkg/dev_compiler/test/sourcemap/common.dart
index c4868c3..86f1e30 100644
--- a/pkg/dev_compiler/test/sourcemap/common.dart
+++ b/pkg/dev_compiler/test/sourcemap/common.dart
@@ -21,6 +21,7 @@
 abstract class ChainContextWithCleanupHelper extends ChainContext {
   Map<TestDescription, Data> cleanupHelper = {};
 
+  @override
   Future<void> cleanUp(TestDescription description, Result result) {
     if (debugging() && result.outcome != Expectation.Pass) {
       print("Not cleaning up: Running in debug-mode for non-passing test.");
@@ -38,8 +39,10 @@
 class Setup extends Step<TestDescription, Data, ChainContext> {
   const Setup();
 
+  @override
   String get name => "setup";
 
+  @override
   Future<Result<Data>> run(TestDescription input, ChainContext context) async {
     Data data = Data()..uri = input.uri;
     if (context is ChainContextWithCleanupHelper) {
@@ -52,8 +55,10 @@
 class SetCwdToSdkRoot extends Step<Data, Data, ChainContext> {
   const SetCwdToSdkRoot();
 
+  @override
   String get name => "setCWD";
 
+  @override
   Future<Result<Data>> run(Data input, ChainContext context) async {
     // stacktrace_helper assumes CWD is the sdk root dir.
     Directory.current = sdkRoot;
@@ -64,8 +69,10 @@
 class StepWithD8 extends Step<Data, Data, ChainContext> {
   const StepWithD8();
 
+  @override
   String get name => "step";
 
+  @override
   Future<Result<Data>> run(Data data, ChainContext context) async {
     var outWrapperPath = path.join(data.outDir.path, "wrapper.js");
     ProcessResult runResult =
@@ -80,8 +87,10 @@
 
   CheckSteps(this.debug);
 
+  @override
   String get name => "check";
 
+  @override
   Future<Result<Data>> run(Data data, ChainContext context) async {
     checkD8Steps(data.outDir.path, data.d8Output, data.code, debug: debug);
     return pass(data);
diff --git a/pkg/dev_compiler/test/sourcemap/ddc_common.dart b/pkg/dev_compiler/test/sourcemap/ddc_common.dart
index 437b008..4308f5b 100644
--- a/pkg/dev_compiler/test/sourcemap/ddc_common.dart
+++ b/pkg/dev_compiler/test/sourcemap/ddc_common.dart
@@ -29,8 +29,10 @@
 
   const Compile(this.runner);
 
+  @override
   String get name => "compile";
 
+  @override
   Future<Result<Data>> run(Data data, ChainContext context) async {
     var dartScriptAbsolute = File.fromUri(data.uri).absolute;
     var inputFile = dartScriptAbsolute.path;
@@ -58,8 +60,10 @@
 
   const TestStackTrace(this.runner, this.marker, this.knownMarkers);
 
+  @override
   String get name => "TestStackTrace";
 
+  @override
   Future<Result<Data>> run(Data data, ChainContext context) async {
     data.outDir = await Directory.systemTemp.createTemp("stacktrace-test");
     String code = await File.fromUri(data.uri).readAsString();
@@ -99,8 +103,9 @@
     if (result.startsWith("Object.")) result = result.substring(7);
     String inputName =
         INPUT_FILE_NAME.substring(0, INPUT_FILE_NAME.indexOf(".") + 1);
-    if (result.startsWith(inputName))
+    if (result.startsWith(inputName)) {
       result = result.substring(inputName.length);
+    }
     return result;
   }
 }
@@ -162,7 +167,7 @@
   var sdkFile = File(path.relative(sdkJsFile.path, from: sdkRoot.path));
   String jsRootDart = "/root_dart/${sdkFile.uri}";
   File.fromUri(outputFile.resolve("$outputFilename.html.js")).writeAsStringSync(
-      jsContent.replaceFirst("from 'dart_sdk'", "from '$jsRootDart'"));
+      jsContent.replaceFirst("from 'dart_sdk.js'", "from '$jsRootDart'"));
   File.fromUri(outputFile.resolve("$outputFilename.html.html"))
       .writeAsStringSync(getWrapperHtmlContent(
           jsRootDart, "/root_build/$outputFilename.html.js"));
@@ -200,6 +205,6 @@
 Uri selfUri = currentMirrorSystem()
     .findLibrary(#dev_compiler.test.sourcemap.ddc_common)
     .uri;
-String d8Preambles = File.fromUri(
-        selfUri.resolve('../../tool/input_sdk/private/preambles/d8.js'))
+String d8Preambles = File.fromUri(selfUri.resolve(
+        '../../../../sdk/lib/_internal/js_dev_runtime/private/preambles/d8.js'))
     .readAsStringSync();
diff --git a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
index d8b3c1a..275870c 100644
--- a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
@@ -21,6 +21,7 @@
 
   List<Step> _steps;
 
+  @override
   List<Step> get steps => _steps ??= <Step>[
         const Setup(),
         Compile(DevCompilerRunner(environment.containsKey("debug"))),
@@ -28,6 +29,7 @@
         CheckSteps(environment.containsKey("debug")),
       ];
 
+  @override
   bool debugging() => environment.containsKey("debug");
 }
 
@@ -36,6 +38,7 @@
 
   const DevCompilerRunner([this.debugging = false]);
 
+  @override
   Future<Null> run(Uri inputFile, Uri outputFile, Uri outWrapperFile) async {
     Uri outDir = outputFile.resolve(".");
     String outputFilename = outputFile.pathSegments.last;
@@ -67,7 +70,7 @@
 
     var jsContent = File.fromUri(outputFile).readAsStringSync();
     File.fromUri(outputFile).writeAsStringSync(jsContent.replaceFirst(
-        "from 'dart_sdk'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
+        "from 'dart_sdk.js'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
 
     if (debugging) {
       createHtmlWrapper(
@@ -82,4 +85,5 @@
   }
 }
 
-main(List<String> arguments) => runMe(arguments, createContext, "testing.json");
+void main(List<String> arguments) =>
+    runMe(arguments, createContext, "testing.json");
diff --git a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
index b275906..1d1fb94 100644
--- a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
@@ -21,12 +21,14 @@
 class SourceMapContext extends ChainContextWithCleanupHelper
     implements WithCompilerState {
   final Map<String, String> environment;
+  @override
   fe.InitializedCompilerState compilerState;
 
   SourceMapContext(this.environment);
 
   List<Step> _steps;
 
+  @override
   List<Step> get steps {
     return _steps ??= <Step>[
       const Setup(),
@@ -36,6 +38,7 @@
     ];
   }
 
+  @override
   bool debugging() => environment.containsKey("debug");
 }
 
@@ -45,6 +48,7 @@
 
   const DevCompilerRunner(this.context, [this.debugging = false]);
 
+  @override
   Future<Null> run(Uri inputFile, Uri outputFile, Uri outWrapperFile) async {
     Uri outDir = outputFile.resolve(".");
     String outputFilename = outputFile.pathSegments.last;
@@ -66,7 +70,8 @@
     bool succeeded = false;
     try {
       var result = await compile(args, compilerState: context.compilerState);
-      context.compilerState = result.compilerState;
+      context.compilerState =
+          result.compilerState as fe.InitializedCompilerState;
       succeeded = result.success;
     } catch (e, s) {
       print('Unhandled exception:');
@@ -84,7 +89,7 @@
 
     var jsContent = File.fromUri(outputFile).readAsStringSync();
     File.fromUri(outputFile).writeAsStringSync(jsContent.replaceFirst(
-        "from 'dart_sdk'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
+        "from 'dart_sdk.js'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
 
     if (debugging) {
       createHtmlWrapper(
@@ -99,4 +104,5 @@
   }
 }
 
-main(List<String> arguments) => runMe(arguments, createContext, "testing.json");
+void main(List<String> arguments) =>
+    runMe(arguments, createContext, "testing.json");
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_ddc_suite.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_ddc_suite.dart
index c4b1fae..d137aa1 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_ddc_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_ddc_suite.dart
@@ -10,6 +10,7 @@
 }
 
 class StackTraceContext extends ChainContextWithCleanupHelper {
+  @override
   final List<Step> steps = <Step>[
     const Setup(),
     const SetCwdToSdkRoot(),
@@ -18,4 +19,5 @@
   ];
 }
 
-main(List<String> arguments) => runMe(arguments, createContext, "testing.json");
+void main(List<String> arguments) =>
+    runMe(arguments, createContext, "testing.json");
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_ddk_suite.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_ddk_suite.dart
index 65fb257..94d26c6 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_ddk_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_ddk_suite.dart
@@ -12,10 +12,12 @@
 
 class StackTraceContext extends ChainContextWithCleanupHelper
     implements WithCompilerState {
+  @override
   fe.InitializedCompilerState compilerState;
 
   List<Step> _steps;
 
+  @override
   List<Step> get steps {
     return _steps ??= <Step>[
       const Setup(),
@@ -26,4 +28,5 @@
   }
 }
 
-main(List<String> arguments) => runMe(arguments, createContext, "testing.json");
+void main(List<String> arguments) =>
+    runMe(arguments, createContext, "testing.json");
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/null_instance_field.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/null_instance_field.dart
index a624b2e..131d057 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/null_instance_field.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/null_instance_field.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*1:main*/ test(Class());
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/null_interceptor_field.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/null_interceptor_field.dart
index 21fc03c..beec13d 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/null_interceptor_field.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/null_interceptor_field.dart
@@ -6,7 +6,7 @@
   get length => 3; // ensures we build an interceptor for `.length`
 }
 
-main() {
+void main() {
   confuse('').trim(); // includes some code above the interceptors
   confuse([]).length;
   confuse(MyType()).length;
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/rethrow.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/rethrow.dart
index 2354061..82a3819 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/rethrow.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/rethrow.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*1:main*/ test();
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_async.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_async.dart
index 0f6165e..ea6ab10 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_async.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_async.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*1:main*/ test();
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_awaited_async.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_awaited_async.dart
index 2801397..5e4721a 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_awaited_async.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_awaited_async.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*1:main*/ test1();
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_constructor.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_constructor.dart
index fde3136..f57db8f 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_constructor.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_constructor.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   // ignore: UNUSED_LOCAL_VARIABLE
   var /*ddc.1:main*/ c = /*ddk.1:main*/ Class();
 }
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_constructor_from_async.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_constructor_from_async.dart
index 907777c..6d251e8 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_constructor_from_async.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_constructor_from_async.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   // This call is no longer on the stack when the error is thrown.
   /*1:main*/ test();
 }
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_instance_method.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_instance_method.dart
index 4261c48..2fbc97f 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_instance_method.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_instance_method.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   var c = Class();
   c. /*1:main*/ test();
 }
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_main.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_main.dart
index f43b4d4..c7043fe 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_main.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_main.dart
@@ -2,6 +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.
 
-main() {
+void main() {
   /*1:main*/ throw '>ExceptionMarker<';
 }
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_static_method.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_static_method.dart
index 4c4e5b8..658db6a 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_static_method.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_static_method.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*ddc.1:main*/ Class. /*ddk.1:main*/ test();
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_top_level_method.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_top_level_method.dart
index 962e60c..d03d29a 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_top_level_method.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_top_level_method.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*1:main*/ test();
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_top_level_method_from_async.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_top_level_method_from_async.dart
index f58dde6..f5240ee 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_top_level_method_from_async.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_top_level_method_from_async.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*1:main*/ test1();
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_try_catch.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_try_catch.dart
index 2bb8501..1da6f77 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_try_catch.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_try_catch.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*1:main*/ test();
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_try_finally.dart b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_try_finally.dart
index fe97b70..7bfcd1a 100644
--- a/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_try_finally.dart
+++ b/pkg/dev_compiler/test/sourcemap/stacktrace_testfiles/throw_in_try_finally.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*1:main*/ test();
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/breakpoint_on_function_line_breaks_in_body.dart b/pkg/dev_compiler/test/sourcemap/testfiles/breakpoint_on_function_line_breaks_in_body.dart
index c133da3..e7f354b 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/breakpoint_on_function_line_breaks_in_body.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/breakpoint_on_function_line_breaks_in_body.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   foo();
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/call_on_field_in_class.dart b/pkg/dev_compiler/test/sourcemap/testfiles/call_on_field_in_class.dart
index 69b242d..567e68e 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/call_on_field_in_class.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/call_on_field_in_class.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /* bl */ var foo = /*sl:1*/ Foo();
   foo.foo = foo. /*sl:2*/ fooMethod;
   foo /*sl:3*/ .fooMethod();
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/hello_async.dart b/pkg/dev_compiler/test/sourcemap/testfiles/hello_async.dart
index 6758e46..cfa5b12 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/hello_async.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/hello_async.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*bl*/
   /*s:1*/ foo();
   /*s:4*/
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/hello_call.dart b/pkg/dev_compiler/test/sourcemap/testfiles/hello_call.dart
index 0d3d2e4..a5662bb 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/hello_call.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/hello_call.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*bl*/
   /*s:1*/ foo();
 }
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/hello_class_call.dart b/pkg/dev_compiler/test/sourcemap/testfiles/hello_class_call.dart
index 31e4aa7..de068a9 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/hello_class_call.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/hello_class_call.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*bl*/
   Foo foo = Foo();
   foo.foo();
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/hello_sane_column_on_print_return_value.dart b/pkg/dev_compiler/test/sourcemap/testfiles/hello_sane_column_on_print_return_value.dart
index 6c1b07afa..49408f2 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/hello_sane_column_on_print_return_value.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/hello_sane_column_on_print_return_value.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*bc:3*/ print(/*bc:1*/ foo());
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/hello_world.dart b/pkg/dev_compiler/test/sourcemap/testfiles/hello_world.dart
index 59746a1..019e2de 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/hello_world.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/hello_world.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /*nb*/ // no break on empty line
   /*bl*/ print("Hello, World!");
 /*s:1*/
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/method_call_with_named_parameters.dart b/pkg/dev_compiler/test/sourcemap/testfiles/method_call_with_named_parameters.dart
index 426e385..f665d7c 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/method_call_with_named_parameters.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/method_call_with_named_parameters.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   foo(/*bc:1*/ bar(), baz: /*bc:2*/ baz());
   /*nbb:0:4*/
 }
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/method_call_with_named_parameters_no_given.dart b/pkg/dev_compiler/test/sourcemap/testfiles/method_call_with_named_parameters_no_given.dart
index 6091682..763d098 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/method_call_with_named_parameters_no_given.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/method_call_with_named_parameters_no_given.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   foo(/*bc:1*/ bar());
   /*nbb:0:3*/
 }
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assert.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assert.dart
index 0b692fa..bcf0307 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assert.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assert.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*Debugger:stepOver*/
-main() {
+void main() {
   assert(/*bc:1*/ foo());
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assign_call_test.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assign_call_test.dart
index f44926d..b4941e7 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assign_call_test.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assign_call_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*Debugger:stepOver*/
-main() {
+void main() {
   /*nb*/ int a;
   /*nb*/ int b;
   a = b = /*bc:1*/ foo();
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assign_int_test.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assign_int_test.dart
index bed6ec6..5a4452e 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assign_int_test.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_assign_int_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*Debugger:stepOver*/
-main() {
+void main() {
   /*nb*/ int a;
   /*nb*/ int b;
   /*bl*/
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_catch_test.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_catch_test.dart
index 777af94..fe9fde0 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_catch_test.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_catch_test.dart
@@ -4,7 +4,7 @@
 
 /*Debugger:stepOver*/
 
-main() {
+void main() {
   /*bl*/
   try {
     /*sl:1*/ var value = "world";
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_for_each_loop_test.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_for_each_loop_test.dart
index 112a8fb..d59f77b 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_for_each_loop_test.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_for_each_loop_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*Debugger:stepOver*/
-main() {
+void main() {
   /*bl*/ /*sl:1*/ List<int> data = [1, 2, 3];
   for (
       // comment forcing formatting
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_for_loop_with_break_and_continue_test.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_for_loop_with_break_and_continue_test.dart
index c51f64f..f562c22 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_for_loop_with_break_and_continue_test.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_for_loop_with_break_and_continue_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*Debugger:stepOver*/
-main() {
+void main() {
   /*bl*/ /*sl:1*/ int count = 0;
   for (/*sl:2*/ int i = 0;
       /*sl:3*/ /*sl:8*/ /*sl:13*/ /*sl:17*/ /*nbb:18:21*/ i < 42;
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_is_and_as_test.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_is_and_as_test.dart
index d3b49d1..2f90736 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_is_and_as_test.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_is_and_as_test.dart
@@ -4,7 +4,7 @@
 
 /*Debugger:stepOver*/
 
-main() {
+void main() {
   /*bl*/
   /*sl:1*/ var i = 42.42;
   /*sl:2*/ var hex = 0x42;
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_map_creation.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_map_creation.dart
index 83e19bb..8d38e83 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_map_creation.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_map_creation.dart
@@ -4,7 +4,7 @@
 
 /*Debugger:stepOver*/
 
-main() {
+void main() {
   /*bl*/
   var x = {/*bc:1*/ foo(): /*bc:2*/ bar() };
   /*sl:3*/ print(x);
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_multi_catch_test.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_multi_catch_test.dart
index e2c30d0..d2ecc4c 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_multi_catch_test.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_multi_catch_test.dart
@@ -4,7 +4,7 @@
 
 /*Debugger:stepOver*/
 
-main() {
+void main() {
   /*bl*/
   try {
     /*sl:1*/ throw "Boom!";
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_on_super_test.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_on_super_test.dart
index b84e3fa..de8c40d 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_on_super_test.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_on_super_test.dart
@@ -14,13 +14,14 @@
 }
 
 class Class3 extends Class2 {
+  @override
   code() {
     /*bl*/ /*sl:1*/ super[42];
     /*sl:2*/ return super[42];
   }
 }
 
-main() {
+void main() {
   Class3 c = Class3();
   c[42];
   c.code();
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_on_this_test.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_on_this_test.dart
index d529139..f0f1130 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_on_this_test.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_on_this_test.dart
@@ -13,7 +13,7 @@
   }
 }
 
-main() {
+void main() {
   Class2 c = Class2();
   c[42];
   c.code();
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_test.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_test.dart
index c3d7835..90fa680 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_test.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_operator_bracket_test.dart
@@ -13,7 +13,7 @@
   }
 }
 
-main() {
+void main() {
   /*bl*/ /*sl:1*/ Class2 c = Class2();
   c /*sl:2*/ [42];
   c /*sl:3*/ .code();
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_static_set.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_static_set.dart
index a621285..7bdd6e4 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_static_set.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_static_set.dart
@@ -6,7 +6,7 @@
 
 var bar = 0;
 
-main() {
+void main() {
   bar = /*bc:1*/ foo();
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_string_concatenation.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_string_concatenation.dart
index 2db6757..610c2aa 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_string_concatenation.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_string_concatenation.dart
@@ -4,9 +4,9 @@
 
 /*Debugger:stepOver*/
 
-main() {
+void main() {
   var qux;
-  qux = "${/*bc:1*/foo()} x ${/*bc:2*/bar()} x ${/*bc:3*/baz()}";
+  qux = "${/*bc:1*/ foo()} x ${/*bc:2*/ bar()} x ${/*bc:3*/ baz()}";
   print(qux);
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_string_plus.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_string_plus.dart
index 382044e..bc5d2f5 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_string_plus.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_string_plus.dart
@@ -4,7 +4,7 @@
 
 /*Debugger:stepOver*/
 
-main() {
+void main() {
   var qux;
   qux = /*bc:1*/ foo() + /*bc:2*/ bar();
   print(qux);
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_throw.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_throw.dart
index 586d52d..1d7b275 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_throw.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_throw.dart
@@ -4,7 +4,7 @@
 
 /*Debugger:stepOver*/
 
-main() {
+void main() {
   try {
     throw /*bc:1*/ foo();
   } catch (e) {
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_variable_set.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_variable_set.dart
index 50177f2..54e362b 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_variable_set.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_variable_set.dart
@@ -4,7 +4,7 @@
 
 /*Debugger:stepOver*/
 
-main() {
+void main() {
   /*bl*/
   /*sl:1*/ var x = 0;
   x = /*bc:2*/ foo();
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_yield.dart b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_yield.dart
index 05ca943..882e28c 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/next_through_yield.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/next_through_yield.dart
@@ -4,7 +4,7 @@
 
 /*Debugger:stepOver*/
 
-main() {
+void main() {
   for (int i in naturalsTo(2)) {
     print(i);
   }
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_constructor_line.dart b/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_constructor_line.dart
index f6b3b13..aa521b6 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_constructor_line.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_constructor_line.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   // ignore: unused_local_variable
   Foo foo = Foo();
 }
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_function_line.dart b/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_function_line.dart
index 26508de..33ea7c2 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_function_line.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_function_line.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   Foo foo = Foo();
   foo.foo();
 }
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_line.dart b/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_line.dart
index 0233caa4..d64c1fa 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_line.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_line.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   Foo foo = Foo();
   foo.foo();
 }
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_named_constructor_line.dart b/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_named_constructor_line.dart
index 32ddfc4..22930ce 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_named_constructor_line.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_class_named_constructor_line.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   // ignore: unused_local_variable
   Foo foo = Foo.named();
 }
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_function_line.dart b/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_function_line.dart
index 48223d1..a80c41e 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_function_line.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/no_mapping_on_function_line.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*nm*/
-main() {
+void main() {
   foo();
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/printing_class_fields.dart b/pkg/dev_compiler/test/sourcemap/testfiles/printing_class_fields.dart
index 8bf01a3..0d94442 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/printing_class_fields.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/printing_class_fields.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*Debugger:stepOver*/
-main() {
+void main() {
   /*bl*/
   /*sl:1*/ Foo foo = Foo(1, 2);
   /*sl:2*/ print(foo.x);
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/printing_class_fields_step_into.dart b/pkg/dev_compiler/test/sourcemap/testfiles/printing_class_fields_step_into.dart
index f3f17c1..e889171 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/printing_class_fields_step_into.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/printing_class_fields_step_into.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*nb*/
-main() {
+void main() {
   /*bl*/
   Foo foo = /*sl:1*/ Foo(1, 2);
   /*s:5*/ print(foo.x);
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_async_star_yield.dart b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_async_star_yield.dart
index ec3cab3..36bd4ef 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_async_star_yield.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_async_star_yield.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() async {
+void main() async {
   await for (var i in foobar()) {
     print(i);
   }
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_await_for.dart b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_await_for.dart
index e2021cf..e5b6d10 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_await_for.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_await_for.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() async {
+void main() async {
   /* bl */
   /*sl:1 */ print("About to loop!");
   await for (var /*s:3*/ /*s:5*/ i in foobar /*sl:2*/ ()) {
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_conditional_expression.dart b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_conditional_expression.dart
index 8ea00cf..867c480 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_conditional_expression.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_conditional_expression.dart
@@ -4,7 +4,7 @@
 
 /*Debugger:stepOver*/
 
-main() {
+void main() {
   print(/*bc:1*/ foo() ? bar() : /*bc:2*/ baz());
   print(/*bc:4*/ ! /*bc:3*/ foo() ? /*bc:5*/ bar() : baz());
 }
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_if_and_identical.dart b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_if_and_identical.dart
index 0b81376..7984135 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_if_and_identical.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_if_and_identical.dart
@@ -4,7 +4,7 @@
 
 /*Debugger:stepOver*/
 
-main() {
+void main() {
   if (/*bc:1*/ foo() == /*bc:2*/ bar()) {
     print("wat?!?");
   }
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_property_get_test.dart b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_property_get_test.dart
index 061bfde..78826c7 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_property_get_test.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_property_get_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   Bar bar = Bar();
   bar.doStuff();
 }
@@ -26,6 +26,7 @@
     data3 = this;
   }
 
+  @override
   void doStuff() {
     /* bl */
     /*s:1*/ print(data2);
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_sync_star.dart b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_sync_star.dart
index 84bb777..36768c1 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/step_through_sync_star.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/step_through_sync_star.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   /* bl */
   /*sl:1*/ var iterator = naturalsTo(2);
   for (int /*bc:3*/ /*bc:8*/ /*bc:12*/ i in /*bc:2*/ iterator) {
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/stops_at_ending_brace.dart b/pkg/dev_compiler/test/sourcemap/testfiles/stops_at_ending_brace.dart
index 8bcca4b..d322e4c 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/stops_at_ending_brace.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/stops_at_ending_brace.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-main() {
+void main() {
   Foo();
   // Comment to push the ending brace back a bit.
 /*s:2*/
diff --git a/pkg/dev_compiler/test/string_to_uri_test.dart b/pkg/dev_compiler/test/string_to_uri_test.dart
index 31b86f6..063b87a 100755
--- a/pkg/dev_compiler/test/string_to_uri_test.dart
+++ b/pkg/dev_compiler/test/string_to_uri_test.dart
@@ -2,7 +2,7 @@
 import 'package:dev_compiler/src/compiler/shared_command.dart';
 import 'package:test/test.dart';
 
-main(List<String> args) {
+void main(List<String> args) {
   String currentDir;
   setUpAll(() {
     currentDir = Directory.current.path.replaceAll(r'\', r'/');
diff --git a/pkg/dev_compiler/test/testing.dart b/pkg/dev_compiler/test/testing.dart
index d350f57..449f460 100644
--- a/pkg/dev_compiler/test/testing.dart
+++ b/pkg/dev_compiler/test/testing.dart
@@ -20,6 +20,7 @@
 class _TestUtils {}
 
 class TestUriResolver extends ResourceUriResolver {
+  @override
   final MemoryResourceProvider provider;
   TestUriResolver(this.provider) : super(provider);
 
diff --git a/pkg/dev_compiler/test/worker/worker_test.dart b/pkg/dev_compiler/test/worker/worker_test.dart
index 07c9dc9..5d8e8ff 100644
--- a/pkg/dev_compiler/test/worker/worker_test.dart
+++ b/pkg/dev_compiler/test/worker/worker_test.dart
@@ -150,6 +150,19 @@
       expect((await futureProcessOutput).join(), isEmpty);
       expect(outputJsFile.existsSync(), isTrue);
     });
+
+    test('can compile in basic mode with "legacy" modules', () async {
+      var args = List<String>.from(executableArgs)
+        ..add('--modules')
+        ..add('legacy')
+        ..addAll(compilerArgs);
+      var result = Process.runSync(executable, args);
+
+      expect(result.exitCode, EXIT_CODE_OK);
+      expect(result.stdout, isEmpty);
+      expect(result.stderr, isEmpty);
+      expect(outputJsFile.existsSync(), isTrue);
+    });
   });
 
   group('$mode: Hello World with Summaries', () {
diff --git a/pkg/dev_compiler/tool/build_sdk.dart b/pkg/dev_compiler/tool/build_sdk.dart
index 5fc97e0..60eb377 100644
--- a/pkg/dev_compiler/tool/build_sdk.dart
+++ b/pkg/dev_compiler/tool/build_sdk.dart
@@ -13,7 +13,7 @@
 
 import 'package:dev_compiler/src/analyzer/command.dart';
 
-main(List<String> arguments) async {
+void main(List<String> arguments) async {
   var args = ['--no-source-map', '--no-emit-metadata'];
   args.addAll(arguments);
   args.addAll([
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
index b5cb2fa..6cd6de3 100755
--- a/pkg/dev_compiler/tool/ddb
+++ b/pkg/dev_compiler/tool/ddb
@@ -12,7 +12,6 @@
 // Saves the output in the same directory as the sources for convenient
 // inspection, modification or rerunning the code.
 
-import 'dart:async';
 import 'dart:io';
 
 import 'package:args/args.dart' show ArgParser;
@@ -22,11 +21,22 @@
 // configurable for manual testing.
 const ignoreWhitelistedErrors = false;
 
-void main(List<String> args) {
+void main(List<String> args) async {
+  void printUsage() {
+    print('Usage: ddb [options] <dart-script-file>\n');
+    print('Compiles <dart-script-file> with the dev_compiler and runs it on a '
+        'JS platform.\n');
+  }
+
   // Parse flags.
   var parser = new ArgParser()
+    ..addFlag('help', abbr: 'h', help: 'Display this message.')
     ..addFlag('kernel',
         abbr: 'k', help: 'Compile with the new kernel-based front end.')
+    ..addMultiOption('summary',
+        abbr: 's',
+        help: 'summary file(s) of imported libraries, optionally\n'
+            'with module import path: -s path.sum=js/import/path')
     ..addFlag('debug',
         abbr: 'd',
         help: 'Use current source instead of built SDK.',
@@ -40,13 +50,21 @@
         abbr: 'p',
         help: 'Run with the corresponding chrome/V8 debugging port open.',
         defaultsTo: '9222')
-    ..addOption('enable-experiment',
-        help: 'Run with specified experiments enabled.', defaultsTo: '')
+    ..addMultiOption('enable-experiment',
+        help: 'Run with specified experiments enabled.')
     ..addOption('binary', abbr: 'b', help: 'Runtime binary path.');
 
   var options = parser.parse(args);
+  if (options['help']) {
+    printUsage();
+    print('Available options:');
+    print(parser.usage);
+    exit(0);
+  }
   if (options.rest.length != 1) {
-    throw 'Expected a single dart entrypoint.';
+    print('Dart script file required.\n');
+    printUsage();
+    exit(1);
   }
   var entry = options.rest.first;
   var libRoot = path.dirname(entry);
@@ -55,31 +73,50 @@
   var debug = options['debug'] as bool;
   var kernel = options['kernel'] as bool;
   var binary = options['binary'] as String;
-  var experiment = options['enable-experiment'] as String;
+  var experiments = options['enable-experiment'] as List;
+  var summaries = options['summary'] as List;
   var port = int.parse(options['port'] as String);
 
+  // By default (no `-d`), we use the `dartdevc` binary on the user's path to
+  // compute the SDK we use for execution.  I.e., we assume that `dart` is
+  // under `$DART_SDK/bin/dart` and use that to find `dartdevc` and related
+  // artifacts.  In this mode, this script can run against any installed SDK.
+  // If you want to run against a freshly built SDK, that must be first on
+  // your path.
   var dartBinary = Platform.resolvedExecutable;
-  var dartPath = path.dirname(dartBinary);
-  var dartSdk = path.dirname(dartPath);
+  var dartSdk = path.dirname(path.dirname(dartBinary));
+
+  // In debug mode (`-d`), we run from the `pkg/dev_compiler` sources.  We
+  // determine the location via this actual script (i.e., `-d` assumes
+  // this script remains under to `tool` sub-directory).
   var toolPath = Platform.script.normalizePath().toFilePath();
   var ddcPath = path.dirname(path.dirname(toolPath));
+  var dartCheckoutPath = path.dirname(path.dirname(ddcPath));
 
   ProcessResult runDdc(String command, List<String> args) {
     if (debug) {
       // Use unbuilt script.  This only works from a source checkout.
-      args.insertAll(0, [
-        '--preview-dart-2',
-        '--enable-asserts',
-        path.join(ddcPath, 'bin', '${command}.dart')
-      ]);
+      args.insertAll(0,
+          ['--enable-asserts', path.join(ddcPath, 'bin', '${command}.dart')]);
       command = dartBinary;
     } else {
       // Use built snapshot.
-      command = path.join(dartPath, command);
+      command = path.join(dartSdk, 'bin', command);
     }
     return Process.runSync(command, args);
   }
 
+  /// Writes stdout and stderr from [result] to this process.
+  ///
+  /// Will exit with the exit code from [result] when it's not zero.
+  void echoResult(ProcessResult result) async {
+    stdout.write(result.stdout);
+    await stdout.flush();
+    stderr.write(result.stderr);
+    await stderr.flush();
+    if (result.exitCode != 0) exit(result.exitCode);
+  }
+
   String mod;
   bool chrome = false;
   bool node = false;
@@ -105,7 +142,6 @@
   if (debug) {
     var sdkRoot = path.dirname(path.dirname(ddcPath));
     var buildDir = path.join(sdkRoot, Platform.isMacOS ? 'xcodebuild' : 'out');
-    var genDir = path.join(buildDir, 'ReleaseX64', 'gen', 'utils', 'dartdevc');
     sdkJsPath = path.join(buildDir, 'ReleaseX64', 'gen', 'utils', 'dartdevc',
         kernel ? 'kernel' : 'js', mod);
     requirePath = path.join(sdkRoot, 'third_party', 'requirejs');
@@ -119,33 +155,22 @@
         dartSdk, 'lib', '_internal', kernel ? 'ddc_sdk.dill' : 'ddc_sdk.sum');
   }
   ProcessResult result;
-  if (kernel) {
-    result = runDdc('dartdevc', [
-      '--kernel',
-      '--modules=$mod',
-      '--dart-sdk-summary=$ddcSdk',
-      '--enable-experiment=$experiment',
-      '-o',
-      '$libRoot/$basename.js',
-      entry
-    ]);
-  } else {
-    result = runDdc('dartdevc', [
-      '--modules=$mod',
-      '--dart-sdk-summary=$ddcSdk',
+  var ddcArgs = [
+    if (kernel) '--kernel',
+    '--modules=$mod',
+    '--dart-sdk-summary=$ddcSdk',
+    // TODO(nshahan) Cleanup when we settle on using or removing library-root.
+    if (!kernel)
       '--library-root=$libRoot',
-      '--enable-experiment=$experiment',
-      '-o',
-      '$libRoot/$basename.js',
-      entry
-    ]);
-  }
+    for (var summary in summaries) '--summary=$summary',
+    for (var experiment in experiments) '--enable-experiment=$experiment',
+    '-o',
+    '$libRoot/$basename.js',
+    entry
+  ];
 
-  print(result.stdout);
-  if (result.exitCode != 0) {
-    print(result.stderr);
-    exit(result.exitCode);
-  }
+  result = runDdc('dartdevc', ddcArgs);
+  await echoResult(result);
 
   if (chrome) {
     String chromeBinary;
@@ -220,10 +245,16 @@
     result = Process.runSync(
         nodeBinary, ['--inspect=localhost:$port', nodeFile],
         environment: {'NODE_PATH': nodePath});
-    stdout
-      ..write(result.stdout)
-      ..flush();
   } else if (d8) {
+    // Fix SDK import.  `d8` doesn't let us set paths, so we need a full path
+    // to the SDK.
+
+    var jsFile = File('$libRoot/$basename.js');
+    var jsContents = jsFile.readAsStringSync();
+    jsContents = jsContents.replaceFirst(
+        "from 'dart_sdk.js'", "from '$sdkJsPath/dart_sdk.js'");
+    jsFile.writeAsStringSync(jsContents);
+
     var runjs = '''
     import { dart, _isolate_helper } from '$sdkJsPath/dart_sdk.js';
     import { $basename } from '$basename.js';
@@ -236,16 +267,21 @@
       console.error(e);
     }
     ''';
-    var d8File = '$libRoot/$basename.d8.js';
+    var d8File = path.join(libRoot, '$basename.d8.js');
     new File(d8File).writeAsStringSync(runjs);
-    var d8Binary = binary ?? 'd8';
-    result = Process.runSync(binary, ['--module', d8File]);
-    stdout
-      ..write(result.stdout)
-      ..flush();
+    var d8Binary = binary ?? path.join(dartCheckoutPath, _d8executable);
+    result = Process.runSync(d8Binary, ['--module', d8File]);
   }
-  if (result.exitCode != 0) {
-    print(result.stderr);
-    exit(result.exitCode);
+  await echoResult(result);
+}
+
+String get _d8executable {
+  if (Platform.isWindows) {
+    return path.join('third_party', 'd8', 'windows', 'd8.exe');
+  } else if (Platform.isLinux) {
+    return path.join('third_party', 'd8', 'linux', 'd8');
+  } else if (Platform.isMacOS) {
+    return path.join('third_party', 'd8', 'macos', 'd8');
   }
+  throw new UnsupportedError('Unsupported platform.');
 }
diff --git a/pkg/dev_compiler/tool/ddw b/pkg/dev_compiler/tool/ddw
deleted file mode 100755
index c35b2ca..0000000
--- a/pkg/dev_compiler/tool/ddw
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/bin/bash
-#
-# Compiles code with DDC and runs the resulting code in node.js.
-#
-# The first script supplied should be the one with `main()`.
-#
-# Saves the output in the same directory as the sources for convenient
-# inspection, modification or rerunning the code.
-set -e
-
-function follow_links() {
-  file="$1"
-  while [ -h "$file" ]; do
-    file="$(readlink "$file")"
-  done
-  echo "$file"
-}
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-SDK_DIR="$( cd "${PROG_NAME%/*}/../../.."; pwd -P)"
-
-if [[ `uname` == 'Darwin' ]];
-then
-  OUT_DIR="$SDK_DIR"/xcodebuild
-else
-  OUT_DIR="$SDK_DIR"/out
-fi
-
-if [ -z "$DART_CONFIGURATION" ];
-then
-  DIRS=$( ls "$OUT_DIR" )
-  # list of possible configurations in decreasing desirability
-  CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
-    "ReleaseARM"    "ReleaseARM64"    "ReleaseARMV5TE"
-    "DebugARM"      "DebugARM64"      "DebugARMV5TE")
-  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
-
-GEN_DIR="$OUT_DIR"/"$DART_CONFIGURATION"/gen/utils/dartdevc
-
-KERNEL=false
-if [ "$1" = "-k" ]; then
-  KERNEL=true
-  shift
-fi
-
-BASENAME=$( basename "${1%.*}")
-LIBROOT=$(cd $( dirname "${1%.*}") && pwd)
-
-if [ "$KERNEL" = true ]; then
-
-  if [ ! -e $GEN_DIR/kernel/ddc_sdk.dill ]; then
-    echo "DDC SDK must be built first, please run:"
-    echo "    pushd $SDKDIR"
-    echo "    ./tools/build.py -m release dartdevc_kernel_sdk"
-    exit 1
-  fi
-
-  NODE_PATH=$GEN_DIR/kernel/common:$LIBROOT:$NODE_PATH
-
-  dart -c $SDK_DIR/pkg/dev_compiler/bin/dartdevc.dart --kernel --modules=node \
-      --dart-sdk-summary=$GEN_DIR/kernel/ddc_sdk.dill \
-      -o $LIBROOT/$BASENAME.js $*
-else
-
-  if [ ! -e $GEN_DIR/ddc_sdk.sum ]; then
-    echo "DDC SDK must be built first, please run:"
-    echo "    pushd $SDKDIR"
-    echo "    ./tools/build.py -m release dartdevc_sdk"
-    exit 1
-  fi
-
-  NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
-
-  dart -c $SDK_DIR/pkg/dev_compiler/bin/dartdevc.dart --modules=node \
-      --library-root=$LIBROOT --dart-sdk-summary=$GEN_DIR/ddc_sdk.sum \
-      -o $LIBROOT/$BASENAME.js $*
-fi
-
-pushd $LIBROOT > /dev/null
-echo "
-    // Fix the node.js search paths that Electron cleared out.
-    const Module = require('module');
-    const originalResolveFilename = Module._resolveFilename;
-    Module._resolveFilename = function (request, parent, isMain) {
-      let paths = parent.paths;
-      const ddcPath = \"$GEN_DIR/js/common\";
-      if (paths[0] != ddcPath) {
-        paths.splice(0, 0, ddcPath, \"$LIBROOT\");
-      }
-      return originalResolveFilename(request, parent, isMain);
-    };
-    let sdk = require(\"dart_sdk\");
-    let main = require(\"$BASENAME\").$BASENAME.main;
-    sdk.dart.ignoreWhitelistedErrors(false);
-    sdk._isolate_helper.startRootIsolate(main, []);" \
-    > $LIBROOT/$BASENAME.run.js
-devtool $LIBROOT/$BASENAME.run.js
-popd > /dev/null
diff --git a/pkg/dev_compiler/tool/global_compile.dart b/pkg/dev_compiler/tool/global_compile.dart
deleted file mode 100644
index de1bb64..0000000
--- a/pkg/dev_compiler/tool/global_compile.dart
+++ /dev/null
@@ -1,284 +0,0 @@
-#!/usr/bin/env dart
-// 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:io';
-
-import 'package:analyzer/analyzer.dart' show parseDirectives;
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:args/args.dart' show ArgParser;
-import 'package:path/path.dart' as path;
-
-const ENTRY = "main";
-
-void main(List<String> args) {
-  // Parse flags.
-  var parser = ArgParser()
-    ..addOption('out',
-        help: 'Output file (defaults to "out.js")',
-        abbr: 'o',
-        defaultsTo: 'out.js')
-    ..addFlag('unsafe-force-compile',
-        help: 'Generate code with undefined behavior', negatable: false)
-    ..addFlag('emit-metadata',
-        help: 'Preserve annotations in generated code', negatable: false)
-    ..addOption('package-root',
-        help: 'Directory containing packages',
-        abbr: 'p',
-        defaultsTo: 'packages/')
-    ..addFlag('log', help: 'Show individual build commands')
-    ..addOption('tmp',
-        help:
-            'Directory for temporary artifacts (defaults to a system tmp directory)');
-
-  var options = parser.parse(args);
-  if (options.rest.length != 1) {
-    throw 'Expected a single dart entrypoint.';
-  }
-  var entry = options.rest.first;
-  var outfile = options['out'] as String;
-  var packageRoot = options['package-root'] as String;
-  var unsafe = options['unsafe-force-compile'] as bool;
-  var log = options['log'] as bool;
-  var tmp = options['tmp'] as String;
-  var metadata = options['emit-metadata'] as bool;
-
-  // Build an invocation to dartdevc
-  var dartPath = Platform.resolvedExecutable;
-  var ddcPath = path.dirname(path.dirname(Platform.script.toFilePath()));
-  var template = [
-    '$ddcPath/bin/dartdevc.dart',
-    '--modules=legacy', // TODO(vsm): Change this to use common format.
-    '--single-out-file',
-    '--inline-source-map',
-    '-p',
-    packageRoot
-  ];
-  if (metadata) {
-    template.add('--emit-metadata');
-  }
-  if (unsafe) {
-    template.add('--unsafe-force-compile');
-  }
-
-  // Compute the transitive closure
-  var total = Stopwatch()..start();
-  var partial = Stopwatch()..start();
-
-  // TODO(vsm): We're using the analyzer just to compute the import/export/part
-  // dependence graph.  This is expensive.  Is there a lighterweight way to do
-  // this?
-  transitiveFiles(entry, Directory.current.path, packageRoot);
-  orderModules();
-  computeTransitiveDependences();
-
-  var graphTime = partial.elapsedMilliseconds / 1000;
-  print('Computed global build graph in $graphTime seconds');
-
-  // Prepend Dart runtime files to the output
-  var out = File(outfile);
-  var dartLibrary =
-      File(path.join(ddcPath, 'lib', 'js', 'legacy', 'dart_library.js'))
-          .readAsStringSync();
-  out.writeAsStringSync(dartLibrary);
-  var dartSdk = File(path.join(ddcPath, 'lib', 'js', 'legacy', 'dart_sdk.js'))
-      .readAsStringSync();
-  out.writeAsStringSync(dartSdk, mode: FileMode.append);
-
-  // Linearize module concatenation for deterministic output
-  var last = Future.value();
-  for (var module in orderedModules) {
-    linearizerMap[module] = last;
-    var completer = Completer();
-    completerMap[module] = completer;
-    last = completer.future;
-  }
-
-  // Build modules asynchronously
-  var tmpdir = (tmp == null)
-      ? Directory.systemTemp
-          .createTempSync(outfile.replaceAll(path.separator, '__'))
-      : Directory(tmp)
-    ..createSync();
-  for (var module in orderedModules) {
-    var file = tmpdir.path + path.separator + module + '.js';
-    var command = template.toList()..addAll(['-o', file]);
-    var dependences = transitiveDependenceMap[module];
-    for (var dependence in dependences) {
-      var summary = tmpdir.path + path.separator + dependence + '.sum';
-      command.addAll(['-s', summary]);
-    }
-    var infiles = fileMap[module];
-    command.addAll(infiles);
-
-    var waitList = dependenceMap.containsKey(module)
-        ? dependenceMap[module].map((dep) => readyMap[dep])
-        : <Future>[];
-    var future = Future.wait(waitList);
-    readyMap[module] = future.then((_) {
-      var ready = Process.run(dartPath, command);
-      if (log) {
-        print(command.join(' '));
-      }
-      return ready.then((result) {
-        if (result.exitCode != 0) {
-          print('ERROR: compiling $module');
-          print(result.stdout);
-          print(result.stderr);
-          out.deleteSync();
-          exit(1);
-        }
-        print('Compiled $module (${infiles.length} files)');
-        print(result.stdout);
-
-        // Schedule module append once the previous module is written
-        var codefile = File(file);
-        linearizerMap[module]
-            .then((_) => codefile.readAsString())
-            .then((code) =>
-                out.writeAsString(code, mode: FileMode.append, flush: true))
-            .then((_) => completerMap[module].complete());
-      });
-    });
-  }
-
-  last.then((_) {
-    var time = total.elapsedMilliseconds / 1000;
-    print('Successfully compiled ${inputSet.length} files in $time seconds');
-
-    // Append the entry point invocation.
-    var libraryName =
-        path.withoutExtension(entry).replaceAll(path.separator, '__');
-    out.writeAsStringSync('dart_library.start("$ENTRY", "$libraryName");\n',
-        mode: FileMode.append);
-  });
-}
-
-final inputSet = Set<String>();
-final dependenceMap = Map<String, Set<String>>();
-final transitiveDependenceMap = Map<String, Set<String>>();
-final fileMap = Map<String, Set<String>>();
-
-final readyMap = Map<String, Future>();
-final linearizerMap = Map<String, Future>();
-final completerMap = Map<String, Completer>();
-
-final orderedModules = List<String>();
-final visitedModules = Set<String>();
-
-void orderModules(
-    [String module = ENTRY, List<String> stack, Set<String> visited]) {
-  if (stack == null) {
-    assert(visited == null);
-    stack = List<String>();
-    visited = Set<String>();
-  }
-  if (visited.contains(module)) return;
-  visited.add(module);
-  if (stack.contains(module)) {
-    print(stack);
-    throw 'Circular dependence on $module';
-  }
-  stack.add(module);
-  var dependences = dependenceMap[module];
-  if (dependences != null) {
-    for (var dependence in dependences) {
-      orderModules(dependence, stack, visited);
-    }
-  }
-  orderedModules.add(module);
-  assert(module == stack.last);
-  stack.removeLast();
-}
-
-void computeTransitiveDependences() {
-  for (var module in orderedModules) {
-    var transitiveSet = Set<String>();
-    if (dependenceMap.containsKey(module)) {
-      transitiveSet.addAll(dependenceMap[module]);
-      for (var dependence in dependenceMap[module]) {
-        transitiveSet.addAll(transitiveDependenceMap[dependence]);
-      }
-    }
-    transitiveDependenceMap[module] = transitiveSet;
-  }
-}
-
-String getModule(String uri) {
-  var sourceUri = Uri.parse(uri);
-  if (sourceUri.scheme == 'dart') {
-    return 'dart';
-  } else if (sourceUri.scheme == 'package') {
-    return path.split(sourceUri.path)[0];
-  } else {
-    return ENTRY;
-  }
-}
-
-bool processFile(String file) {
-  inputSet.add(file);
-
-  var module = getModule(file);
-  fileMap.putIfAbsent(module, () => Set<String>());
-  return fileMap[module].add(file);
-}
-
-void processDependence(String from, String to) {
-  var fromModule = getModule(from);
-  var toModule = getModule(to);
-  if (fromModule == toModule || toModule == 'dart') return;
-  dependenceMap.putIfAbsent(fromModule, () => Set<String>());
-  dependenceMap[fromModule].add(toModule);
-}
-
-String canonicalize(String uri, String root) {
-  var sourceUri = Uri.parse(uri);
-  if (sourceUri.scheme == '') {
-    sourceUri = path.toUri(
-        path.isAbsolute(uri) ? path.absolute(uri) : path.join(root, uri));
-    return sourceUri.path;
-  }
-  return sourceUri.toString();
-}
-
-/// Simplified from ParseDartTask.resolveDirective.
-String _resolveDirective(UriBasedDirectiveImpl directive) {
-  StringLiteral uriLiteral = directive.uri;
-  String uriContent = uriLiteral.stringValue;
-  if (uriContent != null) {
-    uriContent = uriContent.trim();
-    directive.uriContent = uriContent;
-  }
-  return directive.validate() == null ? uriContent : null;
-}
-
-String _loadFile(String uri, String packageRoot) {
-  if (uri.startsWith('package:')) {
-    uri = path.join(packageRoot, uri.substring(8));
-  }
-  return File(uri).readAsStringSync();
-}
-
-void transitiveFiles(String entryPoint, String root, String packageRoot) {
-  entryPoint = canonicalize(entryPoint, root);
-  if (entryPoint.startsWith('dart:')) return;
-  if (processFile(entryPoint)) {
-    // Process this
-    var source = _loadFile(entryPoint, packageRoot);
-    var entryDir = path.dirname(entryPoint);
-    var unit = parseDirectives(source, name: entryPoint, suppressErrors: true);
-    for (var d in unit.directives) {
-      if (d is NamespaceDirectiveImpl) {
-        var uri = _resolveDirective(d);
-        processDependence(entryPoint, canonicalize(uri, entryDir));
-        transitiveFiles(uri, entryDir, packageRoot);
-      } else if (d is PartDirectiveImpl) {
-        var uri = _resolveDirective(d);
-        processFile(canonicalize(uri, entryDir));
-      }
-    }
-  }
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart b/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
deleted file mode 100644
index 6e5eb6d..0000000
--- a/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
+++ /dev/null
@@ -1,584 +0,0 @@
-// 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.
-
-/**
- * Support for interoperating with JavaScript.
- *
- * This library provides access to JavaScript objects from Dart, allowing
- * Dart code to get and set properties, and call methods of JavaScript objects
- * and invoke JavaScript functions. The library takes care of converting
- * between Dart and JavaScript objects where possible, or providing proxies if
- * conversion isn't possible.
- *
- * This library does not yet make Dart objects usable from JavaScript, their
- * methods and proeprties are not accessible, though it does allow Dart
- * functions to be passed into and called from JavaScript.
- *
- * [JsObject] is the core type and represents a proxy of a JavaScript object.
- * JsObject gives access to the underlying JavaScript objects properties and
- * methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
- * created from proxies to JavaScript constructors.
- *
- * The top-level getter [context] provides a [JsObject] that represents the
- * global object in JavaScript, usually `window`.
- *
- * The following example shows an alert dialog via a JavaScript call to the
- * global function `alert()`:
- *
- *     import 'dart:js';
- *
- *     main() => context.callMethod('alert', ['Hello from Dart!']);
- *
- * This example shows how to create a [JsObject] from a JavaScript constructor
- * and access its properties:
- *
- *     import 'dart:js';
- *
- *     main() {
- *       var object = new JsObject(context['Object']);
- *       object['greeting'] = 'Hello';
- *       object['greet'] = (name) => "${object['greeting']} $name";
- *       var message = object.callMethod('greet', ['JavaScript']);
- *       context['console'].callMethod('log', [message]);
- *     }
- *
- * ## Proxying and automatic conversion
- *
- * When setting properties on a JsObject or passing arguments to a Javascript
- * method or function, Dart objects are automatically converted or proxied to
- * JavaScript objects. When accessing JavaScript properties, or when a Dart
- * closure is invoked from JavaScript, the JavaScript objects are also
- * converted to Dart.
- *
- * Functions and closures are proxied in such a way that they are callable. A
- * Dart closure assigned to a JavaScript property is proxied by a function in
- * JavaScript. A JavaScript function accessed from Dart is proxied by a
- * [JsFunction], which has a [apply] method to invoke it.
- *
- * The following types are transferred directly and not proxied:
- *
- * * "Basic" types: `null`, `bool`, `num`, `String`, `DateTime`
- * * `Blob`
- * * `Event`
- * * `HtmlCollection`
- * * `ImageData`
- * * `KeyRange`
- * * `Node`
- * * `NodeList`
- * * `TypedData`, including its subclasses like `Int32List`, but _not_
- *   `ByteBuffer`
- * * `Window`
- *
- * ## Converting collections with JsObject.jsify()
- *
- * To create a JavaScript collection from a Dart collection use the
- * [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
- * into JavaScript Objects and Arrays.
- *
- * The following expression creates a new JavaScript object with the properties
- * `a` and `b` defined:
- *
- *     var jsMap = new JsObject.jsify({'a': 1, 'b': 2});
- *
- * This expression creates a JavaScript array:
- *
- *     var jsArray = new JsObject.jsify([1, 2, 3]);
- */
-library dart.js;
-
-import 'dart:collection' show HashMap, ListMixin;
-
-import 'dart:_js_helper' show Primitives;
-import 'dart:_foreign_helper' show JS;
-import 'dart:_runtime' as dart;
-
-final JsObject context = _wrapToDart(dart.global_);
-
-/**
- * Proxies a JavaScript object to Dart.
- *
- * The properties of the JavaScript object are accessible via the `[]` and
- * `[]=` operators. Methods are callable via [callMethod].
- */
-class JsObject {
-  // The wrapped JS object.
-  final dynamic _jsObject;
-
-  // This should only be called from _wrapToDart
-  JsObject._fromJs(this._jsObject) {
-    assert(_jsObject != null);
-  }
-
-  /**
-   * Constructs a new JavaScript object from [constructor] and returns a proxy
-   * to it.
-   */
-  factory JsObject(JsFunction constructor, [List arguments]) {
-    var ctor = constructor._jsObject;
-    if (arguments == null) {
-      return _wrapToDart(JS('', 'new #()', ctor));
-    }
-    var unwrapped = List.from(arguments.map(_convertToJS));
-    return _wrapToDart(JS('', 'new #(...#)', ctor, unwrapped));
-  }
-
-  /**
-   * Constructs a [JsObject] that proxies a native Dart object; _for expert use
-   * only_.
-   *
-   * Use this constructor only if you wish to get access to JavaScript
-   * properties attached to a browser host object, such as a Node or Blob, that
-   * is normally automatically converted into a native Dart object.
-   *
-   * An exception will be thrown if [object] either is `null` or has the type
-   * `bool`, `num`, or `String`.
-   */
-  factory JsObject.fromBrowserObject(object) {
-    if (object is num || object is String || object is bool || object == null) {
-      throw ArgumentError("object cannot be a num, string, bool, or null");
-    }
-    return _wrapToDart(_convertToJS(object));
-  }
-
-  /**
-   * 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 transferable values are directly converted to their
-   * JavaScript type, and all other objects are proxied.
-   */
-  factory JsObject.jsify(object) {
-    if ((object is! Map) && (object is! Iterable)) {
-      throw ArgumentError("object must be a Map or Iterable");
-    }
-    return _wrapToDart(_convertDataTree(object));
-  }
-
-  static _convertDataTree(data) {
-    var _convertedObjects = HashMap.identity();
-
-    _convert(o) {
-      if (_convertedObjects.containsKey(o)) {
-        return _convertedObjects[o];
-      }
-      if (o is Map) {
-        final convertedMap = JS('', '{}');
-        _convertedObjects[o] = convertedMap;
-        for (var key in o.keys) {
-          JS('', '#[#] = #', 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 _convertToJS(o);
-      }
-    }
-
-    return _convert(data);
-  }
-
-  /**
-   * Returns the value associated with [property] from the proxied JavaScript
-   * object.
-   *
-   * The type of [property] must be either [String] or [num].
-   */
-  dynamic operator [](Object property) {
-    if (property is! String && property is! num) {
-      throw ArgumentError("property is not a String or num");
-    }
-    return _convertToDart(JS('', '#[#]', _jsObject, property));
-  }
-
-  /**
-   * Sets the value associated with [property] on the proxied JavaScript
-   * object.
-   *
-   * The type of [property] must be either [String] or [num].
-   */
-  void operator []=(Object property, value) {
-    if (property is! String && property is! num) {
-      throw ArgumentError("property is not a String or num");
-    }
-    JS('', '#[#] = #', _jsObject, property, _convertToJS(value));
-  }
-
-  int get hashCode => 0;
-
-  bool operator ==(other) =>
-      other is JsObject && JS('bool', '# === #', _jsObject, other._jsObject);
-
-  /**
-   * Returns `true` if the JavaScript object contains the specified property
-   * either directly or though its prototype chain.
-   *
-   * This is the equivalent of the `in` operator in JavaScript.
-   */
-  bool hasProperty(property) {
-    if (property is! String && property is! num) {
-      throw ArgumentError("property is not a String or num");
-    }
-    return JS('bool', '# in #', property, _jsObject);
-  }
-
-  /**
-   * Removes [property] from the JavaScript object.
-   *
-   * This is the equivalent of the `delete` operator in JavaScript.
-   */
-  void deleteProperty(property) {
-    if (property is! String && property is! num) {
-      throw ArgumentError("property is not a String or num");
-    }
-    JS('bool', 'delete #[#]', _jsObject, property);
-  }
-
-  /**
-   * Returns `true` if the JavaScript object has [type] in its prototype chain.
-   *
-   * This is the equivalent of the `instanceof` operator in JavaScript.
-   */
-  bool instanceof(JsFunction type) {
-    return JS('bool', '# instanceof #', _jsObject, _convertToJS(type));
-  }
-
-  /**
-   * Returns the result of the JavaScript objects `toString` method.
-   */
-  String toString() {
-    try {
-      return JS('String', 'String(#)', _jsObject);
-    } catch (e) {
-      return super.toString();
-    }
-  }
-
-  /**
-   * Calls [method] on the JavaScript object with the arguments [args] and
-   * returns the result.
-   *
-   * The type of [method] must be either [String] or [num].
-   */
-  dynamic callMethod(method, [List args]) {
-    if (method is! String && method is! num) {
-      throw ArgumentError("method is not a String or num");
-    }
-    if (args != null) args = List.from(args.map(_convertToJS));
-    var fn = JS('', '#[#]', _jsObject, method);
-    if (JS('bool', 'typeof(#) !== "function"', fn)) {
-      throw NoSuchMethodError(_jsObject, Symbol(method), args, {});
-    }
-    return _convertToDart(JS('', '#.apply(#, #)', fn, _jsObject, args));
-  }
-}
-
-/**
- * Proxies a JavaScript Function object.
- */
-class JsFunction extends JsObject {
-  /**
-   * Returns a [JsFunction] that captures its 'this' binding and calls [f]
-   * with the value of this passed as the first argument.
-   */
-  factory JsFunction.withThis(Function f) {
-    return JsFunction._fromJs(JS(
-        '',
-        'function(/*...arguments*/) {'
-        '  let args = [#(this)];'
-        '  for (let arg of arguments) {'
-        '    args.push(#(arg));'
-        '  }'
-        '  return #(#(...args));'
-        '}',
-        _convertToDart,
-        _convertToDart,
-        _convertToJS,
-        f));
-  }
-
-  JsFunction._fromJs(jsObject) : super._fromJs(jsObject);
-
-  /**
-   * 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}) => _convertToDart(JS(
-      '',
-      '#.apply(#, #)',
-      _jsObject,
-      _convertToJS(thisArg),
-      args == null ? null : List.from(args.map(_convertToJS))));
-}
-
-// TODO(jmesserly): this is totally unnecessary in dev_compiler.
-/** A [List] that proxies a JavaScript array. */
-class JsArray<E> extends JsObject with ListMixin<E> {
-  /**
-   * Creates a new JavaScript array.
-   */
-  JsArray() : super._fromJs([]);
-
-  /**
-   * Creates a new JavaScript array and initializes it to the contents of
-   * [other].
-   */
-  JsArray.from(Iterable<E> other)
-      : super._fromJs([]..addAll(other.map(_convertToJS)));
-
-  JsArray._fromJs(jsObject) : super._fromJs(jsObject);
-
-  _checkIndex(int index) {
-    if (index is int && (index < 0 || index >= length)) {
-      throw RangeError.range(index, 0, length);
-    }
-  }
-
-  _checkInsertIndex(int index) {
-    if (index is int && (index < 0 || index >= length + 1)) {
-      throw RangeError.range(index, 0, length);
-    }
-  }
-
-  static _checkRange(int start, int end, int length) {
-    if (start < 0 || start > length) {
-      throw RangeError.range(start, 0, length);
-    }
-    if (end < start || end > length) {
-      throw RangeError.range(end, start, length);
-    }
-  }
-
-  // Methods required by ListMixin
-
-  E operator [](Object index) {
-    // TODO(justinfagnani): fix the semantics for non-ints
-    // dartbug.com/14605
-    if (index is num && index == index.toInt()) {
-      _checkIndex(index);
-    }
-    return super[index] as E;
-  }
-
-  void operator []=(Object index, value) {
-    // TODO(justinfagnani): fix the semantics for non-ints
-    // dartbug.com/14605
-    if (index is num && index == index.toInt()) {
-      _checkIndex(index);
-    }
-    super[index] = value;
-  }
-
-  int get length {
-    // Check the length honours the List contract.
-    var len = JS('', '#.length', _jsObject);
-    // JavaScript arrays have lengths which are unsigned 32-bit integers.
-    if (JS('bool', 'typeof # === "number" && (# >>> 0) === #', len, len, len)) {
-      return JS('int', '#', len);
-    }
-    throw StateError('Bad JsArray length');
-  }
-
-  void set length(int length) {
-    super['length'] = length;
-  }
-
-  // Methods overridden for better performance
-
-  void add(E value) {
-    callMethod('push', [value]);
-  }
-
-  void addAll(Iterable<E> iterable) {
-    var list = (JS('bool', '# instanceof Array', iterable))
-        ? iterable
-        : List.from(iterable);
-    callMethod('push', list);
-  }
-
-  void insert(int index, E element) {
-    _checkInsertIndex(index);
-    callMethod('splice', [index, 0, element]);
-  }
-
-  E removeAt(int index) {
-    _checkIndex(index);
-    return callMethod('splice', [index, 1])[0] as E;
-  }
-
-  E removeLast() {
-    if (length == 0) throw RangeError(-1);
-    return callMethod('pop') as E;
-  }
-
-  void removeRange(int start, int end) {
-    _checkRange(start, end, length);
-    callMethod('splice', [start, end - start]);
-  }
-
-  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
-    _checkRange(start, end, this.length);
-    int length = end - start;
-    if (length == 0) return;
-    if (skipCount < 0) throw ArgumentError(skipCount);
-    var args = <Object>[start, length]
-      ..addAll(iterable.skip(skipCount).take(length));
-    callMethod('splice', args);
-  }
-
-  void sort([int compare(E a, E b)]) {
-    // Note: arr.sort(null) is a type error in FF
-    callMethod('sort', compare == null ? [] : [compare]);
-  }
-}
-
-// Cross frame objects should not be considered browser types.
-// We include the instanceof Object test to filter out cross frame objects
-// on FireFox. Surprisingly on FireFox the instanceof Window test succeeds for
-// cross frame windows while the instanceof Object test fails.
-bool _isBrowserType(o) => JS(
-    'bool',
-    '# instanceof Object && ('
-    '# instanceof Blob || '
-    '# instanceof Event || '
-    '(window.KeyRange && # instanceof KeyRange) || '
-    '(window.IDBKeyRange && # instanceof IDBKeyRange) || '
-    '# instanceof ImageData || '
-    '# instanceof Node || '
-    // Int8Array.__proto__ is TypedArray.
-    '(window.Int8Array && # instanceof Int8Array.__proto__) || '
-    '# instanceof Window)',
-    o,
-    o,
-    o,
-    o,
-    o,
-    o,
-    o,
-    o,
-    o);
-
-class _DartObject {
-  final _dartObj;
-  _DartObject(this._dartObj);
-}
-
-dynamic _convertToJS(dynamic o) {
-  if (o == null || o is String || o is num || o is bool || _isBrowserType(o)) {
-    return o;
-  } else if (o is DateTime) {
-    return Primitives.lazyAsJsDate(o);
-  } else if (o is JsObject) {
-    return o._jsObject;
-  } else if (o is Function) {
-    return _putIfAbsent(_jsProxies, o, _wrapDartFunction);
-  } else {
-    // TODO(jmesserly): for now, we wrap other objects, to keep compatibility
-    // with the original dart:js behavior.
-    return _putIfAbsent(_jsProxies, o, (o) => _DartObject(o));
-  }
-}
-
-dynamic _wrapDartFunction(f) {
-  var wrapper = JS(
-      '',
-      'function(/*...arguments*/) {'
-      '  let args = Array.prototype.map.call(arguments, #);'
-      '  return #(#(...args));'
-      '}',
-      _convertToDart,
-      _convertToJS,
-      f);
-  JS('', '#.set(#, #)', _dartProxies, wrapper, f);
-
-  return wrapper;
-}
-
-// converts a Dart object to a reference to a native JS object
-// which might be a DartObject JS->Dart proxy
-Object _convertToDart(o) {
-  if (o == null || o is String || o is num || o is bool || _isBrowserType(o)) {
-    return o;
-  } else if (JS('!', '# instanceof Date', o)) {
-    num ms = JS('!', '#.getTime()', o);
-    return DateTime.fromMillisecondsSinceEpoch(ms);
-  } else if (o is _DartObject &&
-      !identical(dart.getReifiedType(o), dart.jsobject)) {
-    return o._dartObj;
-  } else {
-    return _wrapToDart(o);
-  }
-}
-
-Object _wrapToDart(o) => _putIfAbsent(_dartProxies, o, _wrapToDartHelper);
-
-Object _wrapToDartHelper(o) {
-  if (JS('bool', 'typeof # == "function"', o)) {
-    return JsFunction._fromJs(o);
-  }
-  if (JS('bool', '# instanceof Array', o)) {
-    return JsArray._fromJs(o);
-  }
-  return JsObject._fromJs(o);
-}
-
-final _dartProxies = JS('', 'new WeakMap()');
-final _jsProxies = JS('', 'new WeakMap()');
-
-Object _putIfAbsent(weakMap, o, getValue(o)) {
-  var value = JS('', '#.get(#)', weakMap, o);
-  if (value == null) {
-    value = getValue(o);
-    JS('', '#.set(#, #)', weakMap, o, value);
-  }
-  return value;
-}
-
-// The allowInterop method is a no-op in Dart Dev Compiler.
-// TODO(jacobr): tag methods so we can throw if a Dart method is passed to
-// JavaScript using the new interop without calling allowInterop.
-
-/// Returns a wrapper around function [f] that can be called from JavaScript
-/// using the package:js Dart-JavaScript interop.
-///
-/// For performance reasons in Dart2Js, by default Dart functions cannot be
-/// passed directly to JavaScript unless this method is called to create
-/// a Function compatible with both Dart and JavaScript.
-/// Calling this method repeatedly on a function will return the same function.
-/// The [Function] returned by this method can be used from both Dart and
-/// 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.
-F allowInterop<F extends Function>(F f) => f;
-
-Expando<Function> _interopCaptureThisExpando = Expando<Function>();
-
-/// Returns a [Function] that when called from JavaScript captures its 'this'
-/// binding and calls [f] with the value of this passed as the first argument.
-/// When called from Dart, [null] will be passed as the first argument.
-///
-/// See the documentation for [allowInterop]. This method should only be used
-/// with package:js Dart-JavaScript interop.
-Function allowInteropCaptureThis(Function f) {
-  var ret = _interopCaptureThisExpando[f];
-  if (ret == null) {
-    ret = JS(
-        '',
-        'function(/*...arguments*/) {'
-        '  let args = [this];'
-        '  for (let arg of arguments) {'
-        '    args.push(arg);'
-        '  }'
-        '  return #(...args);'
-        '}',
-        f);
-    _interopCaptureThisExpando[f] = ret;
-  }
-  return ret;
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/libraries.dart b/pkg/dev_compiler/tool/input_sdk/libraries.dart
deleted file mode 100644
index 6009d0c..0000000
--- a/pkg/dev_compiler/tool/input_sdk/libraries.dart
+++ /dev/null
@@ -1,310 +0,0 @@
-// 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.
-
-library libraries;
-
-/**
- * A bit flag used by [LibraryInfo] indicating that a library is used by dart2js
- */
-const int DART2JS_PLATFORM = 1;
-
-/**
- * A bit flag used by [LibraryInfo] indicating that a library is used by the VM
- */
-const int VM_PLATFORM = 2;
-
-/// The contexts that a library can be used from.
-enum Category {
-  /// Indicates that a library can be used in a browser context.
-  client,
-
-  /// Indicates that a library can be used in a command line context.
-  server,
-
-  /// Indicates that a library can be used from embedded devices.
-  embedded
-}
-
-Category parseCategory(String name) {
-  switch (name) {
-    case "Client":
-      return Category.client;
-    case "Server":
-      return Category.server;
-    case "Embedded":
-      return Category.embedded;
-  }
-  return null;
-}
-
-/// Mapping of "dart:" library name (e.g. "core") to information about that
-/// library.
-const Map<String, LibraryInfo> libraries = const {
-  "async": const LibraryInfo("async/async.dart",
-      categories: "Client,Server",
-      maturity: Maturity.STABLE,
-      dart2jsPatchPath: "_internal/js_runtime/lib/async_patch.dart"),
-  "collection": const LibraryInfo("collection/collection.dart",
-      categories: "Client,Server,Embedded",
-      maturity: Maturity.STABLE,
-      dart2jsPatchPath: "_internal/js_runtime/lib/collection_patch.dart"),
-  "convert": const LibraryInfo("convert/convert.dart",
-      categories: "Client,Server",
-      maturity: Maturity.STABLE,
-      dart2jsPatchPath: "_internal/js_runtime/lib/convert_patch.dart"),
-  "core": const LibraryInfo("core/core.dart",
-      categories: "Client,Server,Embedded",
-      maturity: Maturity.STABLE,
-      dart2jsPatchPath: "_internal/js_runtime/lib/core_patch.dart"),
-  "developer": const LibraryInfo("developer/developer.dart",
-      categories: "Client,Server,Embedded",
-      maturity: Maturity.UNSTABLE,
-      dart2jsPatchPath: "_internal/js_runtime/lib/developer_patch.dart"),
-  "html": const LibraryInfo("html/dart2js/html_dart2js.dart",
-      categories: "Client",
-      maturity: Maturity.WEB_STABLE,
-      platforms: DART2JS_PLATFORM),
-  "html_common": const LibraryInfo("html/html_common/html_common.dart",
-      categories: "Client",
-      maturity: Maturity.WEB_STABLE,
-      dart2jsPath: "html/html_common/html_common_dart2js.dart",
-      documented: false,
-      implementation: true),
-  "indexed_db": const LibraryInfo("indexed_db/dart2js/indexed_db_dart2js.dart",
-      categories: "Client",
-      maturity: Maturity.WEB_STABLE,
-      platforms: DART2JS_PLATFORM),
-  "_http":
-      const LibraryInfo("_http/http.dart", categories: "", documented: false),
-  "io": const LibraryInfo("io/io.dart",
-      categories: "Server",
-      dart2jsPatchPath: "_internal/js_runtime/lib/io_patch.dart"),
-  "isolate": const LibraryInfo("isolate/isolate.dart",
-      categories: "Client,Server",
-      maturity: Maturity.STABLE,
-      dart2jsPatchPath: "_internal/js_runtime/lib/isolate_patch.dart"),
-  "js": const LibraryInfo("js/dart2js/js_dart2js.dart",
-      categories: "Client",
-      maturity: Maturity.STABLE,
-      platforms: DART2JS_PLATFORM),
-  "js_util": const LibraryInfo("js_util/dart2js/js_util_dart2js.dart",
-      categories: "Client",
-      maturity: Maturity.STABLE,
-      platforms: DART2JS_PLATFORM),
-  "math": const LibraryInfo("math/math.dart",
-      categories: "Client,Server,Embedded",
-      maturity: Maturity.STABLE,
-      dart2jsPatchPath: "_internal/js_runtime/lib/math_patch.dart"),
-  "mirrors": const LibraryInfo("mirrors/mirrors.dart",
-      categories: "Client,Server",
-      maturity: Maturity.UNSTABLE,
-      dart2jsPatchPath: "_internal/js_runtime/lib/mirrors_patch.dart"),
-  "nativewrappers": const LibraryInfo("html/dartium/nativewrappers.dart",
-      categories: "Client",
-      implementation: true,
-      documented: false,
-      platforms: DART2JS_PLATFORM),
-  "typed_data": const LibraryInfo("typed_data/typed_data.dart",
-      categories: "Client,Server,Embedded",
-      maturity: Maturity.STABLE,
-      dart2jsPatchPath: "_internal/js_runtime/lib/typed_data_patch.dart"),
-  "_native_typed_data": const LibraryInfo(
-      "_internal/js_runtime/lib/native_typed_data.dart",
-      categories: "",
-      implementation: true,
-      documented: false,
-      platforms: DART2JS_PLATFORM),
-  "cli": const LibraryInfo("cli/cli.dart",
-      categories: "Server",
-      dart2jsPatchPath: "_internal/js_runtime/lib/cli_patch.dart"),
-  "svg": const LibraryInfo("svg/dart2js/svg_dart2js.dart",
-      categories: "Client",
-      maturity: Maturity.WEB_STABLE,
-      platforms: DART2JS_PLATFORM),
-  "web_audio": const LibraryInfo("web_audio/dart2js/web_audio_dart2js.dart",
-      categories: "Client",
-      maturity: Maturity.WEB_STABLE,
-      platforms: DART2JS_PLATFORM),
-  "web_gl": const LibraryInfo("web_gl/dart2js/web_gl_dart2js.dart",
-      categories: "Client",
-      maturity: Maturity.WEB_STABLE,
-      platforms: DART2JS_PLATFORM),
-  "web_sql": const LibraryInfo("web_sql/dart2js/web_sql_dart2js.dart",
-      categories: "Client",
-      maturity: Maturity.WEB_STABLE,
-      platforms: DART2JS_PLATFORM),
-  "_internal": const LibraryInfo("internal/internal.dart",
-      categories: "",
-      documented: false,
-      dart2jsPatchPath: "_internal/js_runtime/lib/internal_patch.dart"),
-  "_js_helper": const LibraryInfo("_internal/js_runtime/lib/js_helper.dart",
-      categories: "", documented: false, platforms: DART2JS_PLATFORM),
-  "_interceptors": const LibraryInfo(
-      "_internal/js_runtime/lib/interceptors.dart",
-      categories: "",
-      documented: false,
-      platforms: DART2JS_PLATFORM),
-  "_foreign_helper": const LibraryInfo(
-      "_internal/js_runtime/lib/foreign_helper.dart",
-      categories: "",
-      documented: false,
-      platforms: DART2JS_PLATFORM),
-  "_isolate_helper": const LibraryInfo(
-      "_internal/js_runtime/lib/isolate_helper.dart",
-      categories: "",
-      documented: false,
-      platforms: DART2JS_PLATFORM),
-  "_js_mirrors": const LibraryInfo("_internal/js_runtime/lib/js_mirrors.dart",
-      categories: "", documented: false, platforms: DART2JS_PLATFORM),
-  "_js_primitives": const LibraryInfo(
-      "_internal/js_runtime/lib/js_primitives.dart",
-      categories: "",
-      documented: false,
-      platforms: DART2JS_PLATFORM),
-  "_metadata": const LibraryInfo("html/html_common/metadata.dart",
-      categories: "", documented: false, platforms: DART2JS_PLATFORM),
-  "_debugger": const LibraryInfo("_internal/js_runtime/lib/debugger.dart",
-      category: "", documented: false, platforms: DART2JS_PLATFORM),
-  "_runtime": const LibraryInfo(
-      "_internal/js_runtime/lib/ddc_runtime/runtime.dart",
-      category: "",
-      documented: false,
-      platforms: DART2JS_PLATFORM),
-};
-
-/**
- * Information about a "dart:" library.
- */
-class LibraryInfo {
-  /**
-   * Path to the library's *.dart file relative to this file.
-   */
-  final String path;
-
-  /**
-   * The categories in which the library can be used encoded as a
-   * comma-separated String.
-   */
-  final String _categories;
-
-  /**
-   * Path to the dart2js library's *.dart file relative to this file
-   * or null if dart2js uses the common library path defined above.
-   * Access using the [#getDart2JsPath()] method.
-   */
-  final String dart2jsPath;
-
-  /**
-   * Path to the dart2js library's patch file relative to this file
-   * or null if no dart2js patch file associated with this library.
-   * Access using the [#getDart2JsPatchPath()] method.
-   */
-  final String dart2jsPatchPath;
-
-  /**
-   * True if this library is documented and should be shown to the user.
-   */
-  final bool documented;
-
-  /**
-   * Bit flags indicating which platforms consume this library.
-   * See [DART2JS_LIBRARY] and [VM_LIBRARY].
-   */
-  final int platforms;
-
-  /**
-   * True if the library contains implementation details for another library.
-   * The implication is that these libraries are less commonly used
-   * and that tools like Dart Editor should not show these libraries
-   * in a list of all libraries unless the user specifically asks the tool to
-   * do so.
-   */
-  final bool implementation;
-
-  /**
-   * States the current maturity of this library.
-   */
-  final Maturity maturity;
-
-  const LibraryInfo(this.path,
-      {String categories: "",
-      this.dart2jsPath,
-      this.dart2jsPatchPath,
-      this.implementation: false,
-      this.documented: true,
-      this.maturity: Maturity.UNSPECIFIED,
-      this.platforms: DART2JS_PLATFORM | VM_PLATFORM})
-      : _categories = categories;
-
-  bool get isDart2jsLibrary => (platforms & DART2JS_PLATFORM) != 0;
-  bool get isVmLibrary => (platforms & VM_PLATFORM) != 0;
-
-  /**
-   * The categories in which the library can be used.
-   *
-   * If no categories are specified, the library is internal and can not be
-   * loaded by user code.
-   */
-  List<Category> get categories {
-    // `"".split(,)` returns [""] not [], so we handle that case separately.
-    if (_categories == "") return const <Category>[];
-    return _categories.split(",").map(parseCategory).toList();
-  }
-
-  bool get isInternal => categories.isEmpty;
-
-  /// The original "categories" String that was passed to the constructor.
-  ///
-  /// Can be used to construct a slightly modified copy of this LibraryInfo.
-  String get categoriesString {
-    return _categories;
-  }
-}
-
-/**
- * Abstraction to capture the maturity of a library.
- */
-class Maturity {
-  final int level;
-  final String name;
-  final String description;
-
-  const Maturity(this.level, this.name, this.description);
-
-  String toString() => "$name: $level\n$description\n";
-
-  static const Maturity DEPRECATED = const Maturity(0, "Deprecated",
-      "This library will be remove before next major release.");
-
-  static const Maturity EXPERIMENTAL = const Maturity(
-      1,
-      "Experimental",
-      "This library is experimental and will likely change or be removed\n"
-      "in future versions.");
-
-  static const Maturity UNSTABLE = const Maturity(
-      2,
-      "Unstable",
-      "This library is in still changing and have not yet endured\n"
-      "sufficient real-world testing.\n"
-      "Backwards-compatibility is NOT guaranteed.");
-
-  static const Maturity WEB_STABLE = const Maturity(
-      3,
-      "Web Stable",
-      "This library is tracking the DOM evolution as defined by WC3.\n"
-      "Backwards-compatibility is NOT guaranteed.");
-
-  static const Maturity STABLE = const Maturity(
-      4,
-      "Stable",
-      "The library is stable. API backwards-compatibility is guaranteed.\n"
-      "However implementation details might change.");
-
-  static const Maturity LOCKED = const Maturity(5, "Locked",
-      "This library will not change except when serious bugs are encountered.");
-
-  static const Maturity UNSPECIFIED = const Maturity(-1, "Unspecified",
-      "The maturity for this library has not been specified.");
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart
deleted file mode 100644
index f9dd584..0000000
--- a/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart
+++ /dev/null
@@ -1,601 +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.
-
-// Patch file for dart:collection classes.
-import 'dart:_foreign_helper' show JS, JSExportName;
-import 'dart:_runtime' as dart;
-import 'dart:_interceptors' show JSArray;
-import 'dart:_js_helper'
-    show
-        NoInline,
-        NoSideEffects,
-        NoThrows,
-        patch,
-        LinkedMap,
-        IdentityMap,
-        CustomHashMap,
-        CustomKeyHashMap,
-        DartIterator,
-        notNull,
-        putLinkedMapKey;
-
-@patch
-class HashMap<K, V> {
-  @patch
-  factory HashMap(
-      {bool equals(K key1, K key2),
-      int hashCode(K key),
-      bool isValidKey(Object potentialKey)}) {
-    if (isValidKey == null) {
-      if (hashCode == null) {
-        if (equals == null) {
-          if (identical(K, String) || identical(K, int)) {
-            return IdentityMap<K, V>();
-          }
-          return LinkedMap<K, V>();
-        }
-        hashCode = dart.hashCode;
-      } else if (identical(identityHashCode, hashCode) &&
-          identical(identical, equals)) {
-        return IdentityMap<K, V>();
-      }
-      return CustomHashMap<K, V>(equals ?? dart.equals, hashCode);
-    }
-    return CustomKeyHashMap<K, V>(
-        equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey);
-  }
-
-  @patch
-  factory HashMap.identity() = IdentityMap<K, V>;
-}
-
-@patch
-class LinkedHashMap<K, V> {
-  @patch
-  factory LinkedHashMap(
-      {bool equals(K key1, K key2),
-      int hashCode(K key),
-      bool isValidKey(Object potentialKey)}) {
-    if (isValidKey == null) {
-      if (hashCode == null) {
-        if (equals == null) {
-          if (identical(K, String) || identical(K, int)) {
-            return IdentityMap<K, V>();
-          }
-          return LinkedMap<K, V>();
-        }
-        hashCode = dart.hashCode;
-      } else if (identical(identityHashCode, hashCode) &&
-          identical(identical, equals)) {
-        return IdentityMap<K, V>();
-      }
-      return CustomHashMap<K, V>(equals ?? dart.equals, hashCode);
-    }
-    return CustomKeyHashMap<K, V>(
-        equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey);
-  }
-
-  @patch
-  factory LinkedHashMap.identity() = IdentityMap<K, V>;
-}
-
-@patch
-class HashSet<E> {
-  @patch
-  factory HashSet(
-      {bool equals(E e1, E e2),
-      int hashCode(E e),
-      bool isValidKey(Object potentialKey)}) {
-    if (isValidKey == null) {
-      if (hashCode == null) {
-        if (equals == null) {
-          if (identical(E, String) || identical(E, int)) {
-            return _IdentityHashSet<E>();
-          }
-          return _HashSet<E>();
-        }
-        hashCode = dart.hashCode;
-      } else if (identical(identityHashCode, hashCode) &&
-          identical(identical, equals)) {
-        return _IdentityHashSet<E>();
-      }
-      return _CustomHashSet<E>(
-          equals ?? dart.equals, hashCode ?? dart.hashCode);
-    }
-    return _CustomKeyHashSet<E>(
-        equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey);
-  }
-
-  @patch
-  factory HashSet.identity() = _IdentityHashSet<E>;
-}
-
-@patch
-class LinkedHashSet<E> {
-  @patch
-  factory LinkedHashSet(
-      {bool equals(E e1, E e2),
-      int hashCode(E e),
-      bool isValidKey(Object potentialKey)}) {
-    if (isValidKey == null) {
-      if (hashCode == null) {
-        if (equals == null) {
-          if (identical(E, String) || identical(E, int)) {
-            return _IdentityHashSet<E>();
-          }
-          return _HashSet<E>();
-        }
-        hashCode = dart.hashCode;
-      } else if (identical(identityHashCode, hashCode) &&
-          identical(identical, equals)) {
-        return _IdentityHashSet<E>();
-      }
-      return _CustomHashSet<E>(
-          equals ?? dart.equals, hashCode ?? dart.hashCode);
-    }
-    return _CustomKeyHashSet<E>(
-        equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey);
-  }
-
-  @patch
-  factory LinkedHashSet.identity() = _IdentityHashSet<E>;
-}
-
-class _HashSet<E> extends _InternalSet<E>
-    implements HashSet<E>, LinkedHashSet<E> {
-  /// The backing store for this set.
-  ///
-  /// Keys that use identity equality are stored directly. For other types of
-  /// keys, we first look them up (by hashCode) in the [_keyMap] map, then
-  /// we lookup the key in this map.
-  @notNull
-  final _map = JS('', 'new Set()');
-
-  /// Items that use custom equality semantics.
-  ///
-  /// This maps from the item's hashCode to the canonical key, which is then
-  /// used to lookup the item in [_map]. Keeping the data in our primary backing
-  /// map gives us the ordering semantics requred by [LinkedHashMap], while
-  /// also providing convenient access to keys/values.
-  @notNull
-  final _keyMap = JS('', 'new Map()');
-
-  // We track the number of modifications done to the key set of the
-  // hash map to be able to throw when the map is modified while being
-  // iterated over.
-  //
-  // Value cycles after 2^30 modifications so that modification counts are
-  // always unboxed (Smi) values. Modification detection will be missed if you
-  // make exactly some multiple of 2^30 modifications between advances of an
-  // iterator.
-  @notNull
-  int _modifications = 0;
-
-  _HashSet();
-
-  Set<E> _newSet() => _HashSet<E>();
-
-  Set<R> _newSimilarSet<R>() => _HashSet<R>();
-
-  bool contains(Object key) {
-    if (key == null) {
-      key = null;
-    } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
-        dart.identityEquals)) {
-      @notNull
-      var k = key;
-      var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, k.hashCode);
-      if (buckets != null) {
-        for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
-          k = JS('', '#[#]', buckets, i);
-          if (k == key) return true;
-        }
-      }
-      return false;
-    }
-    return JS('bool', '#.has(#)', _map, key);
-  }
-
-  E lookup(Object key) {
-    if (key == null) return null;
-    if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
-        dart.identityEquals)) {
-      @notNull
-      var k = key;
-      var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, k.hashCode);
-      if (buckets != null) {
-        for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
-          k = JS('', '#[#]', buckets, i);
-          if (k == key) return JS('', '#', k);
-        }
-      }
-      return null;
-    }
-    return JS('', '#.has(#) ? # : null', _map, key, key);
-  }
-
-  bool add(E key) {
-    var map = _map;
-    if (key == null) {
-      if (JS('', '#.has(null)', map)) return false;
-      key = null;
-    } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
-        dart.identityEquals)) {
-      var keyMap = _keyMap;
-      @notNull
-      var k = key;
-      int hash = JS('!', '# & 0x3ffffff', k.hashCode);
-      var buckets = JS('', '#.get(#)', keyMap, hash);
-      if (buckets == null) {
-        JS('', '#.set(#, [#])', keyMap, hash, key);
-      } else {
-        for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
-          k = JS('', '#[#]', buckets, i);
-          if (k == key) return false;
-        }
-        JS('', '#.push(#)', buckets, key);
-      }
-    } else if (JS('', '#.has(#)', map, key)) {
-      return false;
-    }
-    JS('', '#.add(#)', map, key);
-    _modifications = (_modifications + 1) & 0x3ffffff;
-    return true;
-  }
-
-  void addAll(Iterable<E> objects) {
-    var map = _map;
-    int length = JS('', '#.size', map);
-    for (E key in objects) {
-      if (key == null) {
-        key = null; // converts undefined to null, if needed.
-      } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
-          dart.identityEquals)) {
-        key = putLinkedMapKey(key, _keyMap);
-      }
-      JS('', '#.add(#)', map, key);
-    }
-    if (length != JS<int>('!', '#.size', map)) {
-      _modifications = (_modifications + 1) & 0x3ffffff;
-    }
-  }
-
-  bool remove(Object key) {
-    if (key == null) {
-      key = null;
-    } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
-        dart.identityEquals)) {
-      @notNull
-      var k = key;
-      int hash = JS('!', '# & 0x3ffffff', k.hashCode);
-      var buckets = JS('', '#.get(#)', _keyMap, hash);
-      if (buckets == null) return false; // not found
-      for (int i = 0, n = JS('!', '#.length', buckets);;) {
-        k = JS('', '#[#]', buckets, i);
-        if (k == key) {
-          key = k;
-          if (n == 1) {
-            JS('', '#.delete(#)', _keyMap, hash);
-          } else {
-            JS('', '#.splice(#, 1)', buckets, i);
-          }
-          break;
-        }
-        if (++i >= n) return false; // not found
-      }
-    }
-    var map = _map;
-    if (JS('bool', '#.delete(#)', map, key)) {
-      _modifications = (_modifications + 1) & 0x3ffffff;
-      return true;
-    }
-    return false;
-  }
-
-  void clear() {
-    var map = _map;
-    if (JS<int>('!', '#.size', map) > 0) {
-      JS('', '#.clear()', map);
-      JS('', '#.clear()', _keyMap);
-      _modifications = (_modifications + 1) & 0x3ffffff;
-    }
-  }
-}
-
-class ImmutableSet<E> extends _HashSet<E> {
-  ImmutableSet.from(JSArray entries) {
-    var map = _map;
-    for (Object key in entries) {
-      if (key == null) {
-        key = null; // converts undefined to null, if needed.
-      } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
-          dart.identityEquals)) {
-        key = putLinkedMapKey(key, _keyMap);
-      }
-      JS('', '#.add(#)', map, key);
-    }
-  }
-
-  bool add(Object other) => throw _unsupported();
-  void addAll(Object other) => throw _unsupported();
-  void clear() => throw _unsupported();
-  bool remove(Object key) => throw _unsupported();
-
-  static Error _unsupported() =>
-      UnsupportedError("Cannot modify unmodifiable map");
-}
-
-class _IdentityHashSet<E> extends _InternalSet<E>
-    implements HashSet<E>, LinkedHashSet<E> {
-  /// The backing store for this set.
-  @notNull
-  final _map = JS('', 'new Set()');
-
-  @notNull
-  int _modifications = 0;
-
-  _IdentityHashSet();
-
-  Set<E> _newSet() => _IdentityHashSet<E>();
-
-  Set<R> _newSimilarSet<R>() => _IdentityHashSet<R>();
-
-  bool contains(Object element) {
-    return JS('', '#.has(#)', _map, element);
-  }
-
-  E lookup(Object element) {
-    return JS('', '#.has(#)', _map, element) ? element : null;
-  }
-
-  bool add(E element) {
-    var map = _map;
-    if (JS('bool', '#.has(#)', map, element)) return false;
-    JS('', '#.add(#)', map, element);
-    _modifications = (_modifications + 1) & 0x3ffffff;
-    return true;
-  }
-
-  void addAll(Iterable<E> objects) {
-    var map = _map;
-    int length = JS('', '#.size', map);
-    for (E key in objects) {
-      JS('', '#.add(#)', map, key);
-    }
-    if (length != JS<int>('!', '#.size', map)) {
-      _modifications = (_modifications + 1) & 0x3ffffff;
-    }
-  }
-
-  bool remove(Object element) {
-    if (JS('bool', '#.delete(#)', _map, element)) {
-      _modifications = (_modifications + 1) & 0x3ffffff;
-      return true;
-    }
-    return false;
-  }
-
-  void clear() {
-    var map = _map;
-    if (JS<int>('!', '#.size', map) > 0) {
-      JS('', '#.clear()', map);
-      _modifications = (_modifications + 1) & 0x3ffffff;
-    }
-  }
-}
-
-class _CustomKeyHashSet<E> extends _CustomHashSet<E> {
-  _Predicate<Object> _validKey;
-  _CustomKeyHashSet(_Equality<E> equals, _Hasher<E> hashCode, this._validKey)
-      : super(equals, hashCode);
-
-  Set<E> _newSet() => _CustomKeyHashSet<E>(_equals, _hashCode, _validKey);
-
-  Set<R> _newSimilarSet<R>() => _HashSet<R>();
-
-  bool contains(Object element) {
-    // TODO(jmesserly): there is a subtle difference here compared to Dart 1.
-    // See the comment on CustomKeyHashMap.containsKey for more information.
-    // Treatment of `null` is different due to strong mode's requirement to
-    // perform an `element is E` check before calling equals/hashCode.
-    if (!_validKey(element)) return false;
-    return super.contains(element);
-  }
-
-  E lookup(Object element) {
-    if (!_validKey(element)) return null;
-    return super.lookup(element);
-  }
-
-  bool remove(Object element) {
-    if (!_validKey(element)) return false;
-    return super.remove(element);
-  }
-}
-
-class _CustomHashSet<E> extends _InternalSet<E>
-    implements HashSet<E>, LinkedHashSet<E> {
-  _Equality<E> _equals;
-  _Hasher<E> _hashCode;
-
-  // We track the number of modifications done to the key set of the
-  // hash map to be able to throw when the map is modified while being
-  // iterated over.
-  //
-  // Value cycles after 2^30 modifications so that modification counts are
-  // always unboxed (Smi) values. Modification detection will be missed if you
-  // make exactly some multiple of 2^30 modifications between advances of an
-  // iterator.
-  @notNull
-  int _modifications = 0;
-
-  /// The backing store for this set, used to handle ordering.
-  // TODO(jmesserly): a non-linked custom hash set could skip this.
-  @notNull
-  final _map = JS('', 'new Set()');
-
-  /// Our map used to map keys onto the canonical key that is stored in [_map].
-  @notNull
-  final _keyMap = JS('', 'new Map()');
-
-  _CustomHashSet(this._equals, this._hashCode);
-
-  Set<E> _newSet() => _CustomHashSet<E>(_equals, _hashCode);
-  Set<R> _newSimilarSet<R>() => _HashSet<R>();
-
-  bool contains(Object key) {
-    if (key is E) {
-      var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, _hashCode(key));
-      if (buckets != null) {
-        var equals = _equals;
-        for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
-          E k = JS('', '#[#]', buckets, i);
-          if (equals(k, key)) return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  E lookup(Object key) {
-    if (key is E) {
-      var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, _hashCode(key));
-      if (buckets != null) {
-        var equals = _equals;
-        for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
-          E k = JS('', '#[#]', buckets, i);
-          if (equals(k, key)) return k;
-        }
-      }
-    }
-    return null;
-  }
-
-  bool add(E key) {
-    var keyMap = _keyMap;
-    var hash = JS<int>('!', '# & 0x3ffffff', _hashCode(key));
-    var buckets = JS('', '#.get(#)', keyMap, hash);
-    if (buckets == null) {
-      JS('', '#.set(#, [#])', keyMap, hash, key);
-    } else {
-      var equals = _equals;
-      for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
-        E k = JS('', '#[#]', buckets, i);
-        if (equals(k, key)) return false;
-      }
-      JS('', '#.push(#)', buckets, key);
-    }
-    JS('', '#.add(#)', _map, key);
-    _modifications = (_modifications + 1) & 0x3ffffff;
-    return true;
-  }
-
-  void addAll(Iterable<E> objects) {
-    // TODO(jmesserly): it'd be nice to skip the covariance check here.
-    for (E element in objects) add(element);
-  }
-
-  bool remove(Object key) {
-    if (key is E) {
-      var hash = JS<int>('!', '# & 0x3ffffff', _hashCode(key));
-      var keyMap = _keyMap;
-      var buckets = JS('', '#.get(#)', keyMap, hash);
-      if (buckets == null) return false; // not found
-      var equals = _equals;
-      for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
-        E k = JS('', '#[#]', buckets, i);
-        if (equals(k, key)) {
-          if (n == 1) {
-            JS('', '#.delete(#)', keyMap, hash);
-          } else {
-            JS('', '#.splice(#, 1)', buckets, i);
-          }
-          JS('', '#.delete(#)', _map, k);
-          _modifications = (_modifications + 1) & 0x3ffffff;
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  void clear() {
-    var map = _map;
-    if (JS<int>('!', '#.size', map) > 0) {
-      JS('', '#.clear()', map);
-      JS('', '#.clear()', _keyMap);
-      _modifications = (_modifications + 1) & 0x3ffffff;
-    }
-  }
-}
-
-/// Base class for our internal [LinkedHashSet]/[HashSet] implementations.
-///
-/// This implements the common functionality.
-abstract class _InternalSet<E> extends _SetBase<E> {
-  @notNull
-  get _map;
-
-  @notNull
-  int get _modifications;
-
-  @notNull
-  int get length => JS<int>('!', '#.size', _map);
-
-  @notNull
-  bool get isEmpty => JS('bool', '#.size == 0', _map);
-
-  @notNull
-  bool get isNotEmpty => JS('bool', '#.size != 0', _map);
-
-  Iterator<E> get iterator => DartIterator<E>(_jsIterator());
-
-  @JSExportName('Symbol.iterator')
-  _jsIterator() {
-    var self = this;
-    var iterator = JS('', '#.values()', self._map);
-    int modifications = self._modifications;
-    return JS(
-        '',
-        '''{
-      next() {
-        if (# != #) {
-          throw #;
-        }
-        return #.next();
-      }
-    }''',
-        modifications,
-        self._modifications,
-        ConcurrentModificationError(self),
-        iterator);
-  }
-}
-
-@patch
-abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
-  @patch
-  Node _splayMin(Node node) {
-    Node current = node;
-    while (current.left != null) {
-      Node left = current.left;
-      current.left = left.right;
-      left.right = current;
-      current = left;
-    }
-    return current;
-  }
-
-  @patch
-  Node _splayMax(Node node) {
-    Node current = node;
-    while (current.right != null) {
-      Node right = current.right;
-      current.right = right.left;
-      right.left = current;
-      current = right;
-    }
-    return current;
-  }
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
deleted file mode 100644
index 192b5f6..0000000
--- a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
+++ /dev/null
@@ -1,2892 +0,0 @@
-// 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.
-
-// Patch file for dart:core classes.
-import "dart:_internal" as _symbol_dev;
-import 'dart:_interceptors';
-import 'dart:_js_helper'
-    show
-        patch,
-        checkInt,
-        getRuntimeType,
-        LinkedMap,
-        JSSyntaxRegExp,
-        NoInline,
-        notNull,
-        nullCheck,
-        Primitives,
-        PrivateSymbol,
-        quoteStringForRegExp,
-        undefined;
-import 'dart:_runtime' as dart;
-import 'dart:_foreign_helper' show JS;
-import 'dart:_native_typed_data' show NativeUint8List;
-import 'dart:collection' show UnmodifiableMapView;
-import 'dart:convert' show Encoding, utf8;
-import 'dart:typed_data' show Endian, Uint8List, Uint16List;
-
-String _symbolToString(Symbol symbol) => symbol is PrivateSymbol
-    ? PrivateSymbol.getName(symbol)
-    : _symbol_dev.Symbol.getName(symbol);
-
-@patch
-int identityHashCode(Object object) {
-  if (object == null) return 0;
-  // Note: this works for primitives because we define the `identityHashCode`
-  // for them to be equivalent to their computed hashCode function.
-  int hash = JS('int|Null', r'#[#]', object, dart.identityHashCode_);
-  if (hash == null) {
-    hash = JS('int', '(Math.random() * 0x3fffffff) | 0');
-    JS('void', r'#[#] = #', object, dart.identityHashCode_, hash);
-  }
-  return JS('int', '#', hash);
-}
-
-// Patch for Object implementation.
-@patch
-class Object {
-  @patch
-  bool operator ==(other) => identical(this, other);
-
-  @patch
-  int get hashCode => identityHashCode(this);
-
-  @patch
-  String toString() =>
-      "Instance of '${dart.typeName(dart.getReifiedType(this))}'";
-
-  @patch
-  noSuchMethod(Invocation invocation) {
-    return dart.defaultNoSuchMethod(this, invocation);
-  }
-
-  @patch
-  Type get runtimeType => dart.wrapType(dart.getReifiedType(this));
-}
-
-@patch
-class Null {
-  @patch
-  int get hashCode => super.hashCode;
-}
-
-// Patch for Function implementation.
-@patch
-class Function {
-  @patch
-  static apply(Function f, List positionalArguments,
-      [Map<Symbol, dynamic> namedArguments]) {
-    positionalArguments ??= [];
-    // dcall expects the namedArguments as a JS map in the last slot.
-    if (namedArguments != null && namedArguments.isNotEmpty) {
-      var map = JS('', '{}');
-      namedArguments.forEach((symbol, arg) {
-        JS('', '#[#] = #', map, _symbolToString(symbol), arg);
-      });
-      return dart.dcall(f, positionalArguments, map);
-    }
-    return dart.dcall(f, positionalArguments);
-  }
-
-  static Map<String, dynamic> _toMangledNames(
-      Map<Symbol, dynamic> namedArguments) {
-    Map<String, dynamic> result = {};
-    namedArguments.forEach((symbol, value) {
-      result[_symbolToString(symbol)] = value;
-    });
-    return result;
-  }
-}
-
-// TODO(jmesserly): switch to WeakMap
-// Patch for Expando implementation.
-@patch
-class Expando<T> {
-  @patch
-  Expando([String name]) : this.name = name;
-
-  @patch
-  T operator [](Object object) {
-    var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME);
-    return (values == null) ? null : Primitives.getProperty(values, _getKey());
-  }
-
-  @patch
-  void operator []=(Object object, T value) {
-    var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME);
-    if (values == null) {
-      values = Object();
-      Primitives.setProperty(object, _EXPANDO_PROPERTY_NAME, values);
-    }
-    Primitives.setProperty(values, _getKey(), value);
-  }
-
-  String _getKey() {
-    String key = Primitives.getProperty(this, _KEY_PROPERTY_NAME);
-    if (key == null) {
-      key = "expando\$key\$${_keyCount++}";
-      Primitives.setProperty(this, _KEY_PROPERTY_NAME, key);
-    }
-    return key;
-  }
-
-  static const String _KEY_PROPERTY_NAME = 'expando\$key';
-  static const String _EXPANDO_PROPERTY_NAME = 'expando\$values';
-  static int _keyCount = 0;
-}
-
-Null _kNull(_) => null;
-
-@patch
-class int {
-  @patch
-  static int parse(String source,
-      {int radix, @deprecated int onError(String source)}) {
-    return Primitives.parseInt(source, radix, onError);
-  }
-
-  @patch
-  static int tryParse(String source, {int radix}) {
-    return Primitives.parseInt(source, radix, _kNull);
-  }
-
-  @patch
-  factory int.fromEnvironment(String name, {int defaultValue}) {
-    // ignore: const_constructor_throws_exception
-    throw UnsupportedError(
-        'int.fromEnvironment can only be used as a const constructor');
-  }
-}
-
-@patch
-class double {
-  @patch
-  static double parse(String source,
-      [@deprecated double onError(String source)]) {
-    return Primitives.parseDouble(source, onError);
-  }
-
-  @patch
-  static double tryParse(String source) {
-    return Primitives.parseDouble(source, _kNull);
-  }
-}
-
-@patch
-class BigInt implements Comparable<BigInt> {
-  @patch
-  static BigInt get zero => _BigIntImpl.zero;
-  @patch
-  static BigInt get one => _BigIntImpl.one;
-  @patch
-  static BigInt get two => _BigIntImpl.two;
-
-  @patch
-  static BigInt parse(String source, {int radix}) =>
-      _BigIntImpl.parse(source, radix: radix);
-
-  @patch
-  static BigInt tryParse(String source, {int radix}) =>
-      _BigIntImpl._tryParse(source, radix: radix);
-
-  @patch
-  factory BigInt.from(num value) = _BigIntImpl.from;
-}
-
-@patch
-class Error {
-  @patch
-  static String _objectToString(Object object) {
-    return "Instance of '${dart.typeName(dart.getReifiedType(object))}'";
-  }
-
-  @patch
-  static String _stringToSafeString(String string) {
-    return JS("String", "JSON.stringify(#)", string);
-  }
-
-  @patch
-  StackTrace get stackTrace => dart.stackTraceForError(this);
-}
-
-@patch
-class FallThroughError {
-  @patch
-  FallThroughError._create(String url, int line);
-
-  @patch
-  String toString() => super.toString();
-}
-
-@patch
-class AbstractClassInstantiationError {
-  @patch
-  String toString() => "Cannot instantiate abstract class: '$_className'";
-}
-
-// Patch for DateTime implementation.
-@patch
-class DateTime {
-  @patch
-  DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
-      {bool isUtc = false})
-      : this._withValue(millisecondsSinceEpoch, isUtc: isUtc);
-
-  @patch
-  DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
-      {bool isUtc = false})
-      : this._withValue(
-            _microsecondInRoundedMilliseconds(microsecondsSinceEpoch),
-            isUtc: isUtc);
-
-  @patch
-  DateTime._internal(int year, int month, int day, int hour, int minute,
-      int second, int millisecond, int microsecond, bool isUtc)
-      // checkBool is manually inlined here because dart2js doesn't inline it
-      // and [isUtc] is usually a constant.
-      : this.isUtc =
-            isUtc is bool ? isUtc : throw ArgumentError.value(isUtc, 'isUtc'),
-        _value = checkInt(Primitives.valueFromDecomposedDate(
-            year,
-            month,
-            day,
-            hour,
-            minute,
-            second,
-            millisecond + _microsecondInRoundedMilliseconds(microsecond),
-            isUtc));
-
-  @patch
-  DateTime._now()
-      : isUtc = false,
-        _value = Primitives.dateNow();
-
-  /// Rounds the given [microsecond] to the nearest milliseconds value.
-  ///
-  /// For example, invoked with argument `2600` returns `3`.
-  static int _microsecondInRoundedMilliseconds(int microsecond) {
-    return (microsecond / 1000).round();
-  }
-
-  @patch
-  static int _brokenDownDateToValue(int year, int month, int day, int hour,
-      int minute, int second, int millisecond, int microsecond, bool isUtc) {
-    return Primitives.valueFromDecomposedDate(
-        year,
-        month,
-        day,
-        hour,
-        minute,
-        second,
-        millisecond + _microsecondInRoundedMilliseconds(microsecond),
-        isUtc);
-  }
-
-  @patch
-  String get timeZoneName {
-    if (isUtc) return "UTC";
-    return Primitives.getTimeZoneName(this);
-  }
-
-  @patch
-  Duration get timeZoneOffset {
-    if (isUtc) return Duration();
-    return Duration(minutes: Primitives.getTimeZoneOffsetInMinutes(this));
-  }
-
-  @patch
-  DateTime add(Duration duration) {
-    return DateTime._withValue(_value + duration.inMilliseconds, isUtc: isUtc);
-  }
-
-  @patch
-  DateTime subtract(Duration duration) {
-    return DateTime._withValue(_value - duration.inMilliseconds, isUtc: isUtc);
-  }
-
-  @patch
-  Duration difference(DateTime other) {
-    return Duration(milliseconds: _value - other._value);
-  }
-
-  @patch
-  int get millisecondsSinceEpoch => _value;
-
-  @patch
-  int get microsecondsSinceEpoch => _value * 1000;
-
-  @patch
-  int get year => Primitives.getYear(this);
-
-  @patch
-  int get month => Primitives.getMonth(this);
-
-  @patch
-  int get day => Primitives.getDay(this);
-
-  @patch
-  int get hour => Primitives.getHours(this);
-
-  @patch
-  int get minute => Primitives.getMinutes(this);
-
-  @patch
-  int get second => Primitives.getSeconds(this);
-
-  @patch
-  int get millisecond => Primitives.getMilliseconds(this);
-
-  @patch
-  int get microsecond => 0;
-
-  @patch
-  int get weekday => Primitives.getWeekday(this);
-
-  @patch
-  bool operator ==(dynamic other) =>
-      other is DateTime &&
-      _value == other.millisecondsSinceEpoch &&
-      isUtc == other.isUtc;
-
-  @patch
-  bool isBefore(DateTime other) => _value < other.millisecondsSinceEpoch;
-
-  @patch
-  bool isAfter(DateTime other) => _value > other.millisecondsSinceEpoch;
-
-  @patch
-  bool isAtSameMomentAs(DateTime other) =>
-      _value == other.millisecondsSinceEpoch;
-
-  @patch
-  int compareTo(DateTime other) =>
-      _value.compareTo(other.millisecondsSinceEpoch);
-}
-
-// Patch for Stopwatch implementation.
-@patch
-class Stopwatch {
-  @patch
-  static void _initTicker() {
-    Primitives.initTicker();
-    _frequency = Primitives.timerFrequency;
-  }
-
-  @patch
-  static int _now() => Primitives.timerTicks();
-
-  @patch
-  int get elapsedMicroseconds {
-    int ticks = elapsedTicks;
-    if (_frequency == 1000000) return ticks;
-    assert(_frequency == 1000);
-    return ticks * 1000;
-  }
-
-  @patch
-  int get elapsedMilliseconds {
-    int ticks = elapsedTicks;
-    if (_frequency == 1000) return ticks;
-    assert(_frequency == 1000000);
-    return ticks ~/ 1000;
-  }
-}
-
-// Patch for List implementation.
-@patch
-class List<E> {
-  @patch
-  factory List([@undefined int _length]) {
-    dynamic list;
-    if (JS('bool', '# === void 0', _length)) {
-      list = JS('', '[]');
-    } else {
-      int length = JS('!', '#', _length);
-      if (_length == null || length < 0) {
-        throw ArgumentError("Length must be a non-negative integer: $_length");
-      }
-      list = JS('', 'new Array(#)', length);
-      JS('', '#.fill(null)', list);
-      JSArray.markFixedList(list);
-    }
-    return JSArray<E>.of(list);
-  }
-
-  @patch
-  factory List.filled(@nullCheck int length, E fill, {bool growable = false}) {
-    var list = JSArray<E>.of(JS('', 'new Array(#)', length));
-    JS('', '#.fill(#)', list, fill);
-    if (!growable) JSArray.markFixedList(list);
-    return list;
-  }
-
-  @patch
-  factory List.from(Iterable elements, {bool growable = true}) {
-    var list = JSArray<E>.of(JS('', '[]'));
-    // Specialize the copy loop for the case that doesn't need a
-    // runtime check.
-    if (elements is Iterable<E>) {
-      for (var e in elements) {
-        list.add(e);
-      }
-    } else {
-      for (var e in elements) {
-        list.add(e as E);
-      }
-    }
-    if (!growable) JSArray.markFixedList(list);
-    return list;
-  }
-
-  @patch
-  factory List.unmodifiable(Iterable elements) {
-    var list = List<E>.from(elements);
-    JSArray.markUnmodifiableList(list);
-    return list;
-  }
-}
-
-@patch
-class Map<K, V> {
-  @patch
-  factory Map.unmodifiable(Map other) {
-    return UnmodifiableMapView<K, V>(Map<K, V>.from(other));
-  }
-
-  @patch
-  factory Map() = LinkedMap<K, V>;
-}
-
-@patch
-class String {
-  @patch
-  factory String.fromCharCodes(Iterable<int> charCodes,
-      [int start = 0, int end]) {
-    if (charCodes is JSArray) {
-      return _stringFromJSArray(charCodes, start, end);
-    }
-    if (charCodes is NativeUint8List) {
-      return _stringFromUint8List(charCodes, start, end);
-    }
-    return _stringFromIterable(charCodes, start, end);
-  }
-
-  @patch
-  factory String.fromCharCode(int charCode) {
-    return Primitives.stringFromCharCode(charCode);
-  }
-
-  @patch
-  factory String.fromEnvironment(String name, {String defaultValue}) {
-    // ignore: const_constructor_throws_exception
-    throw UnsupportedError(
-        'String.fromEnvironment can only be used as a const constructor');
-  }
-
-  static String _stringFromJSArray(
-      /*=JSArray<int>*/ list,
-      int start,
-      int endOrNull) {
-    int len = list.length;
-    int end = RangeError.checkValidRange(start, endOrNull, len);
-    if (start > 0 || end < len) {
-      list = list.sublist(start, end);
-    }
-    return Primitives.stringFromCharCodes(list);
-  }
-
-  static String _stringFromUint8List(
-      NativeUint8List charCodes, int start, int endOrNull) {
-    int len = charCodes.length;
-    int end = RangeError.checkValidRange(start, endOrNull, len);
-    return Primitives.stringFromNativeUint8List(charCodes, start, end);
-  }
-
-  static String _stringFromIterable(
-      Iterable<int> charCodes, int start, int end) {
-    if (start < 0) throw RangeError.range(start, 0, charCodes.length);
-    if (end != null && end < start) {
-      throw RangeError.range(end, start, charCodes.length);
-    }
-    var it = charCodes.iterator;
-    for (int i = 0; i < start; i++) {
-      if (!it.moveNext()) {
-        throw RangeError.range(start, 0, i);
-      }
-    }
-    var list = <int>[];
-    if (end == null) {
-      while (it.moveNext()) list.add(it.current);
-    } else {
-      for (int i = start; i < end; i++) {
-        if (!it.moveNext()) {
-          throw RangeError.range(end, start, i);
-        }
-        list.add(it.current);
-      }
-    }
-    return Primitives.stringFromCharCodes(list);
-  }
-}
-
-@patch
-class bool {
-  @patch
-  factory bool.fromEnvironment(String name, {bool defaultValue = false}) {
-    // ignore: const_constructor_throws_exception
-    throw UnsupportedError(
-        'bool.fromEnvironment can only be used as a const constructor');
-  }
-
-  @patch
-  int get hashCode => super.hashCode;
-}
-
-@patch
-class RegExp {
-  @patch
-  factory RegExp(String source,
-          {bool multiLine = false, bool caseSensitive = true}) =>
-      JSSyntaxRegExp(source,
-          multiLine: multiLine, caseSensitive: caseSensitive);
-
-  @patch
-  static String escape(String text) => quoteStringForRegExp(text);
-}
-
-// Patch for 'identical' function.
-@patch
-bool identical(Object a, Object b) {
-  return JS('bool', '(# == null ? # == null : # === #)', a, b, a, b);
-}
-
-@patch
-class StringBuffer {
-  String _contents;
-
-  @patch
-  StringBuffer([Object content = ""]) : _contents = '$content';
-
-  @patch
-  int get length => _contents.length;
-
-  @patch
-  void write(Object obj) {
-    _writeString('$obj');
-  }
-
-  @patch
-  void writeCharCode(int charCode) {
-    _writeString(String.fromCharCode(charCode));
-  }
-
-  @patch
-  void writeAll(Iterable objects, [String separator = ""]) {
-    _contents = _writeAll(_contents, objects, separator);
-  }
-
-  @patch
-  void writeln([Object obj = ""]) {
-    _writeString('$obj\n');
-  }
-
-  @patch
-  void clear() {
-    _contents = "";
-  }
-
-  @patch
-  String toString() => Primitives.flattenString(_contents);
-
-  void _writeString(str) {
-    _contents = Primitives.stringConcatUnchecked(_contents, str);
-  }
-
-  static String _writeAll(String string, Iterable objects, String separator) {
-    Iterator iterator = objects.iterator;
-    if (!iterator.moveNext()) return string;
-    if (separator.isEmpty) {
-      do {
-        string = _writeOne(string, iterator.current);
-      } while (iterator.moveNext());
-    } else {
-      string = _writeOne(string, iterator.current);
-      while (iterator.moveNext()) {
-        string = _writeOne(string, separator);
-        string = _writeOne(string, iterator.current);
-      }
-    }
-    return string;
-  }
-
-  static String _writeOne(String string, Object obj) {
-    return Primitives.stringConcatUnchecked(string, '$obj');
-  }
-}
-
-// TODO(jmesserly): kernel expects to find this in our SDK.
-class _CompileTimeError extends Error {
-  final String _errorMsg;
-  _CompileTimeError(this._errorMsg);
-  String toString() => _errorMsg;
-}
-
-@patch
-class NoSuchMethodError {
-  final Object _receiver;
-  final Symbol _memberName;
-  final List _arguments;
-  final Map<Symbol, dynamic> _namedArguments;
-  final List _existingArgumentNames;
-
-  @patch
-  NoSuchMethodError(Object receiver, Symbol memberName,
-      List positionalArguments, Map<Symbol, dynamic> namedArguments,
-      [List existingArgumentNames = null])
-      : _receiver = receiver,
-        _memberName = memberName,
-        _arguments = positionalArguments,
-        _namedArguments = namedArguments,
-        _existingArgumentNames = existingArgumentNames;
-
-  @patch
-  NoSuchMethodError.withInvocation(Object receiver, Invocation invocation)
-      : _receiver = receiver,
-        _memberName = invocation.memberName,
-        _arguments = invocation.positionalArguments,
-        _namedArguments = invocation.namedArguments,
-        _existingArgumentNames = null;
-
-  @patch
-  String toString() {
-    StringBuffer sb = StringBuffer('');
-    String comma = '';
-    if (_arguments != null) {
-      for (var argument in _arguments) {
-        sb.write(comma);
-        sb.write(Error.safeToString(argument));
-        comma = ', ';
-      }
-    }
-    if (_namedArguments != null) {
-      _namedArguments.forEach((Symbol key, var value) {
-        sb.write(comma);
-        sb.write(_symbolToString(key));
-        sb.write(": ");
-        sb.write(Error.safeToString(value));
-        comma = ', ';
-      });
-    }
-    String memberName = _symbolToString(_memberName);
-    String receiverText = Error.safeToString(_receiver);
-    String actualParameters = '$sb';
-    if (_existingArgumentNames == null) {
-      return "NoSuchMethodError: method not found: '$memberName'\n"
-          "Receiver: ${receiverText}\n"
-          "Arguments: [$actualParameters]";
-    } else {
-      String formalParameters = _existingArgumentNames.join(', ');
-      return "NoSuchMethodError: incorrect number of arguments passed to "
-          "method named '$memberName'\n"
-          "Receiver: ${receiverText}\n"
-          "Tried calling: $memberName($actualParameters)\n"
-          "Found: $memberName($formalParameters)";
-    }
-  }
-}
-
-@patch
-class Uri {
-  @patch
-  static Uri get base {
-    String uri = Primitives.currentUri();
-    if (uri != null) return Uri.parse(uri);
-    throw UnsupportedError("'Uri.base' is not supported");
-  }
-}
-
-@patch
-class _Uri {
-  @patch
-  static bool get _isWindows => _isWindowsCached;
-
-  static final bool _isWindowsCached = JS(
-      'bool',
-      'typeof process != "undefined" && '
-      'Object.prototype.toString.call(process) == "[object process]" && '
-      'process.platform == "win32"');
-
-  // Matches a String that _uriEncodes to itself regardless of the kind of
-  // component.  This corresponds to [_unreservedTable], i.e. characters that
-  // are not encoded by any encoding table.
-  static final RegExp _needsNoEncoding = RegExp(r'^[\-\.0-9A-Z_a-z~]*$');
-
-  /**
-   * This is the internal implementation of JavaScript's encodeURI function.
-   * It encodes all characters in the string [text] except for those
-   * that appear in [canonicalTable], and returns the escaped string.
-   */
-  @patch
-  static String _uriEncode(List<int> canonicalTable, String text,
-      Encoding encoding, bool spaceToPlus) {
-    if (identical(encoding, utf8) && _needsNoEncoding.hasMatch(text)) {
-      return text;
-    }
-
-    // Encode the string into bytes then generate an ASCII only string
-    // by percent encoding selected bytes.
-    StringBuffer result = StringBuffer('');
-    var bytes = encoding.encode(text);
-    for (int i = 0; i < bytes.length; i++) {
-      int byte = bytes[i];
-      if (byte < 128 &&
-          ((canonicalTable[byte >> 4] & (1 << (byte & 0x0f))) != 0)) {
-        result.writeCharCode(byte);
-      } else if (spaceToPlus && byte == _SPACE) {
-        result.write('+');
-      } else {
-        const String hexDigits = '0123456789ABCDEF';
-        result.write('%');
-        result.write(hexDigits[(byte >> 4) & 0x0f]);
-        result.write(hexDigits[byte & 0x0f]);
-      }
-    }
-    return result.toString();
-  }
-}
-
-@patch
-class StackTrace {
-  @patch
-  @NoInline()
-  static StackTrace get current {
-    return dart.stackTrace(JS('', 'Error()'));
-  }
-}
-
-// TODO(jmesserly): this class is supposed to be obsolete in Strong Mode, but
-// the front-end crashes without it
-class _DuplicatedFieldInitializerError {
-  final String _name;
-
-  _DuplicatedFieldInitializerError(this._name);
-
-  toString() => "Error: field '$_name' is already initialized.";
-}
-
-// TODO(jmesserly): The rest of this core_patch.dart source should reside in an
-// included part file instead of being inlined. However, part files are not
-// properly supported here.
-
-// Copyright (c) 2017, 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 dart.core;
-
-int _max(int a, int b) => a > b ? a : b;
-int _min(int a, int b) => a < b ? a : b;
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Copyright (c) 2003-2005  Tom Wu
- * Copyright (c) 2012 Adam Singer (adam@solvr.io)
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
- * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * In addition, the following condition applies:
- *
- * All redistributions must retain an intact copy of this copyright notice
- * and disclaimer.
- */
-
-/**
- * An implementation for the arbitrarily large integer.
- *
- * The integer number is represented by a sign, an array of 16-bit unsigned
- * integers in little endian format, and a number of used digits in that array.
- */
-class _BigIntImpl implements BigInt {
-  // Bits per digit.
-  static const int _digitBits = 16;
-  static const int _digitBase = 1 << _digitBits;
-  static const int _digitMask = (1 << _digitBits) - 1;
-
-  static final _BigIntImpl zero = _BigIntImpl._fromInt(0);
-  static final _BigIntImpl one = _BigIntImpl._fromInt(1);
-  static final _BigIntImpl two = _BigIntImpl._fromInt(2);
-
-  static final _BigIntImpl _minusOne = -one;
-  static final _BigIntImpl _bigInt10000 = _BigIntImpl._fromInt(10000);
-
-  // Result cache for last _divRem call.
-  // Result cache for last _divRem call.
-  static Uint16List _lastDividendDigits;
-  static int _lastDividendUsed;
-  static Uint16List _lastDivisorDigits;
-  static int _lastDivisorUsed;
-  static Uint16List _lastQuoRemDigits;
-  static int _lastQuoRemUsed;
-  static int _lastRemUsed;
-  static int _lastRem_nsh;
-
-  /// Whether this bigint is negative.
-  final bool _isNegative;
-
-  /// The unsigned digits of this bigint.
-  ///
-  /// The least significant digit is in slot 0.
-  /// The list may have more digits than needed. That is, `_digits.length` may
-  /// be strictly greater than `_used`.
-  final Uint16List _digits;
-
-  /// The number of used entries in [_digits].
-  ///
-  /// To avoid reallocating [Uint16List]s, lists that are too big are not
-  /// replaced.
-  final int _used;
-
-  /**
-   * Parses [source] as a, possibly signed, integer literal and returns its
-   * value.
-   *
-   * The [source] must be a non-empty sequence of base-[radix] digits,
-   * optionally prefixed with a minus or plus sign ('-' or '+').
-   *
-   * The [radix] must be in the range 2..36. The digits used are
-   * first the decimal digits 0..9, and then the letters 'a'..'z' with
-   * values 10 through 35. Also accepts upper-case letters with the same
-   * values as the lower-case ones.
-   *
-   * If no [radix] is given then it defaults to 10. In this case, the [source]
-   * digits may also start with `0x`, in which case the number is interpreted
-   * as a hexadecimal literal, which effectively means that the `0x` is ignored
-   * and the radix is instead set to 16.
-   *
-   * For any int `n` and radix `r`, it is guaranteed that
-   * `n == int.parse(n.toRadixString(r), radix: r)`.
-   *
-   * Throws a [FormatException] if the [source] is not a valid integer literal,
-   * optionally prefixed by a sign.
-   */
-  static _BigIntImpl parse(String source, {int radix}) {
-    var result = _tryParse(source, radix: radix);
-    if (result == null) {
-      throw FormatException("Could not parse BigInt", source);
-    }
-    return result;
-  }
-
-  /// Parses a decimal bigint literal.
-  ///
-  /// The [source] must not contain leading or trailing whitespace.
-  static _BigIntImpl _parseDecimal(String source, bool isNegative) {
-    const _0 = 48;
-
-    int part = 0;
-    _BigIntImpl result = zero;
-    // Read in the source 4 digits at a time.
-    // The first part may have a few leading virtual '0's to make the remaining
-    // parts all have exactly 4 digits.
-    int digitInPartCount = 4 - source.length.remainder(4);
-    if (digitInPartCount == 4) digitInPartCount = 0;
-    for (int i = 0; i < source.length; i++) {
-      part = part * 10 + source.codeUnitAt(i) - _0;
-      if (++digitInPartCount == 4) {
-        result = result * _bigInt10000 + _BigIntImpl._fromInt(part);
-        part = 0;
-        digitInPartCount = 0;
-      }
-    }
-    if (isNegative) return -result;
-    return result;
-  }
-
-  /// Returns the value of a given source digit.
-  ///
-  /// Source digits between "0" and "9" (inclusive) return their decimal value.
-  ///
-  /// Source digits between "a" and "z", or "A" and "Z" (inclusive) return
-  /// 10 + their position in the ASCII alphabet.
-  ///
-  /// The incoming [codeUnit] must be an ASCII code-unit.
-  static int _codeUnitToRadixValue(int codeUnit) {
-    // We know that the characters must be ASCII as otherwise the
-    // regexp wouldn't have matched. Lowercasing by doing `| 0x20` is thus
-    // guaranteed to be a safe operation, since it preserves digits
-    // and lower-cases ASCII letters.
-    const int _0 = 48;
-    const int _9 = 57;
-    const int _a = 97;
-    if (_0 <= codeUnit && codeUnit <= _9) return codeUnit - _0;
-    codeUnit |= 0x20;
-    var result = codeUnit - _a + 10;
-    return result;
-  }
-
-  /// Parses the given [source] string, starting at [startPos], as a hex
-  /// literal.
-  ///
-  /// If [isNegative] is true, negates the result before returning it.
-  ///
-  /// The [source] (substring) must be a valid hex literal.
-  static _BigIntImpl _parseHex(String source, int startPos, bool isNegative) {
-    int hexDigitsPerChunk = _digitBits ~/ 4;
-    int sourceLength = source.length - startPos;
-    int chunkCount = (sourceLength / hexDigitsPerChunk).ceil();
-    var digits = Uint16List(chunkCount);
-
-    int lastDigitLength = sourceLength - (chunkCount - 1) * hexDigitsPerChunk;
-    int digitIndex = digits.length - 1;
-    int i = startPos;
-    int chunk = 0;
-    for (int j = 0; j < lastDigitLength; j++) {
-      var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i++));
-      if (digitValue >= 16) return null;
-      chunk = chunk * 16 + digitValue;
-    }
-    digits[digitIndex--] = chunk;
-
-    while (i < source.length) {
-      chunk = 0;
-      for (int j = 0; j < hexDigitsPerChunk; j++) {
-        var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i++));
-        if (digitValue >= 16) return null;
-        chunk = chunk * 16 + digitValue;
-      }
-      digits[digitIndex--] = chunk;
-    }
-    if (digits.length == 1 && digits[0] == 0) return zero;
-    return _BigIntImpl._(isNegative, digits.length, digits);
-  }
-
-  /// Parses the given [source] as a [radix] literal.
-  ///
-  /// The [source] will be checked for invalid characters. If it is invalid,
-  /// this function returns `null`.
-  static _BigIntImpl _parseRadix(String source, int radix, bool isNegative) {
-    var result = zero;
-    var base = _BigIntImpl._fromInt(radix);
-    for (int i = 0; i < source.length; i++) {
-      var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i));
-      if (digitValue >= radix) return null;
-      result = result * base + _BigIntImpl._fromInt(digitValue);
-    }
-    if (isNegative) return -result;
-    return result;
-  }
-
-  /// Tries to parse the given [source] as a [radix] literal.
-  ///
-  /// Returns the parsed big integer, or `null` if it failed.
-  ///
-  /// If the [radix] is `null` accepts decimal literals or `0x` hex literals.
-  static _BigIntImpl _tryParse(String source, {int radix}) {
-    if (source == "") return null;
-
-    var re = RegExp(r'^\s*([+-]?)((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$',
-        caseSensitive: false);
-    var match = re.firstMatch(source);
-    int signIndex = 1;
-    int hexIndex = 3;
-    int decimalIndex = 4;
-    int nonDecimalHexIndex = 5;
-    if (match == null) return null;
-
-    bool isNegative = match[signIndex] == "-";
-
-    String decimalMatch = match[decimalIndex];
-    String hexMatch = match[hexIndex];
-    String nonDecimalMatch = match[nonDecimalHexIndex];
-
-    if (radix == null) {
-      if (decimalMatch != null) {
-        // Cannot fail because we know that the digits are all decimal.
-        return _parseDecimal(decimalMatch, isNegative);
-      }
-      if (hexMatch != null) {
-        // Cannot fail because we know that the digits are all hex.
-        return _parseHex(hexMatch, 2, isNegative);
-      }
-      return null;
-    }
-
-    if (radix is! int) {
-      throw ArgumentError.value(radix, 'radix', 'is not an integer');
-    }
-    if (radix < 2 || radix > 36) {
-      throw RangeError.range(radix, 2, 36, 'radix');
-    }
-    if (radix == 10 && decimalMatch != null) {
-      return _parseDecimal(decimalMatch, isNegative);
-    }
-    if (radix == 16 && (decimalMatch != null || nonDecimalMatch != null)) {
-      return _parseHex(decimalMatch ?? nonDecimalMatch, 0, isNegative);
-    }
-
-    return _parseRadix(
-        decimalMatch ?? nonDecimalMatch ?? hexMatch, radix, isNegative);
-  }
-
-  /// Finds the amount significant digits in the provided [digits] array.
-  static int _normalize(int used, Uint16List digits) {
-    while (used > 0 && digits[used - 1] == 0) used--;
-    return used;
-  }
-
-  /// Factory returning an instance initialized with the given field values.
-  /// If the [digits] array contains leading 0s, the [used] value is adjusted
-  /// accordingly. The [digits] array is not modified.
-  _BigIntImpl._(bool isNegative, int used, Uint16List digits)
-      : this._normalized(isNegative, _normalize(used, digits), digits);
-
-  _BigIntImpl._normalized(bool isNegative, this._used, this._digits)
-      : _isNegative = _used == 0 ? false : isNegative;
-
-  /// Whether this big integer is zero.
-  bool get _isZero => _used == 0;
-
-  /// Allocates an array of the given [length] and copies the [digits] in the
-  /// range [from] to [to-1], starting at index 0, followed by leading zero
-  /// digits.
-  static Uint16List _cloneDigits(
-      Uint16List digits, int from, int to, int length) {
-    var resultDigits = Uint16List(length);
-    var n = to - from;
-    for (var i = 0; i < n; i++) {
-      resultDigits[i] = digits[from + i];
-    }
-    return resultDigits;
-  }
-
-  /// Allocates a big integer from the provided [value] number.
-  factory _BigIntImpl.from(num value) {
-    if (value == 0) return zero;
-    if (value == 1) return one;
-    if (value == 2) return two;
-
-    // Given this order dart2js will use the `_fromInt` for smaller value and
-    // then use the bit-manipulating `_fromDouble` for all other values.
-    if (value.abs() < 0x100000000) return _BigIntImpl._fromInt(value.toInt());
-    if (value is double) return _BigIntImpl._fromDouble(value);
-    return _BigIntImpl._fromInt(value);
-  }
-
-  factory _BigIntImpl._fromInt(int value) {
-    bool isNegative = value < 0;
-    assert(_digitBits == 16);
-    if (isNegative) {
-      // Handle the min 64-bit value differently, since its negation is not
-      // positive.
-      const int minInt64 = -0x80000000 * 0x100000000;
-      if (value == minInt64) {
-        var digits = Uint16List(4);
-        digits[3] = 0x8000;
-        return _BigIntImpl._(true, 4, digits);
-      }
-      value = -value;
-    }
-    if (value < _digitBase) {
-      var digits = Uint16List(1);
-      digits[0] = value;
-      return _BigIntImpl._(isNegative, 1, digits);
-    }
-    if (value <= 0xFFFFFFFF) {
-      var digits = Uint16List(2);
-      digits[0] = value & _digitMask;
-      digits[1] = value >> _digitBits;
-      return _BigIntImpl._(isNegative, 2, digits);
-    }
-
-    var bits = value.bitLength;
-    var digits = Uint16List((bits - 1) ~/ _digitBits + 1);
-    var i = 0;
-    while (value != 0) {
-      digits[i++] = value & _digitMask;
-      value = value ~/ _digitBase;
-    }
-    return _BigIntImpl._(isNegative, digits.length, digits);
-  }
-
-  /// An 8-byte Uint8List we can reuse for [_fromDouble] to avoid generating
-  /// garbage.
-  static final Uint8List _bitsForFromDouble = Uint8List(8);
-
-  factory _BigIntImpl._fromDouble(double value) {
-    const int exponentBias = 1075;
-
-    if (value.isNaN || value.isInfinite) {
-      throw ArgumentError("Value must be finite: $value");
-    }
-    bool isNegative = value < 0;
-    if (isNegative) value = -value;
-
-    value = value.floorToDouble();
-    if (value == 0) return zero;
-
-    var bits = _bitsForFromDouble;
-    for (int i = 0; i < 8; i++) {
-      bits[i] = 0;
-    }
-    bits.buffer.asByteData().setFloat64(0, value, Endian.little);
-    // The exponent is in bits 53..63.
-    var biasedExponent = (bits[7] << 4) + (bits[6] >> 4);
-    var exponent = biasedExponent - exponentBias;
-
-    assert(_digitBits == 16);
-    // The significant bits are in 0 .. 52.
-    var unshiftedDigits = Uint16List(4);
-    unshiftedDigits[0] = (bits[1] << 8) + bits[0];
-    unshiftedDigits[1] = (bits[3] << 8) + bits[2];
-    unshiftedDigits[2] = (bits[5] << 8) + bits[4];
-    // Don't forget to add the hidden bit.
-    unshiftedDigits[3] = 0x10 | (bits[6] & 0xF);
-
-    var unshiftedBig = _BigIntImpl._normalized(false, 4, unshiftedDigits);
-    _BigIntImpl absResult = unshiftedBig;
-    if (exponent < 0) {
-      absResult = unshiftedBig >> -exponent;
-    } else if (exponent > 0) {
-      absResult = unshiftedBig << exponent;
-    }
-    if (isNegative) return -absResult;
-    return absResult;
-  }
-
-  /**
-   * Return the negative value of this integer.
-   *
-   * The result of negating an integer always has the opposite sign, except
-   * for zero, which is its own negation.
-   */
-  _BigIntImpl operator -() {
-    if (_used == 0) return this;
-    return _BigIntImpl._(!_isNegative, _used, _digits);
-  }
-
-  /**
-   * Returns the absolute value of this integer.
-   *
-   * For any integer `x`, the result is the same as `x < 0 ? -x : x`.
-   */
-  _BigIntImpl abs() => _isNegative ? -this : this;
-
-  /// Returns this << n *_DIGIT_BITS.
-  _BigIntImpl _dlShift(int n) {
-    final used = _used;
-    if (used == 0) {
-      return zero;
-    }
-    final resultUsed = used + n;
-    final digits = _digits;
-    final resultDigits = Uint16List(resultUsed);
-    for (int i = used - 1; i >= 0; i--) {
-      resultDigits[i + n] = digits[i];
-    }
-    return _BigIntImpl._(_isNegative, resultUsed, resultDigits);
-  }
-
-  /// Same as [_dlShift] but works on the decomposed big integers.
-  ///
-  /// Returns `resultUsed`.
-  ///
-  /// `resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n*_DIGIT_BITS`.
-  static int _dlShiftDigits(
-      Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
-    if (xUsed == 0) {
-      return 0;
-    }
-    if (n == 0 && identical(resultDigits, xDigits)) {
-      return xUsed;
-    }
-    final resultUsed = xUsed + n;
-    for (int i = xUsed - 1; i >= 0; i--) {
-      resultDigits[i + n] = xDigits[i];
-    }
-    for (int i = n - 1; i >= 0; i--) {
-      resultDigits[i] = 0;
-    }
-    return resultUsed;
-  }
-
-  /// Returns `this >> n*_DIGIT_BITS`.
-  _BigIntImpl _drShift(int n) {
-    final used = _used;
-    if (used == 0) {
-      return zero;
-    }
-    final resultUsed = used - n;
-    if (resultUsed <= 0) {
-      return _isNegative ? _minusOne : zero;
-    }
-    final digits = _digits;
-    final resultDigits = Uint16List(resultUsed);
-    for (var i = n; i < used; i++) {
-      resultDigits[i - n] = digits[i];
-    }
-    final result = _BigIntImpl._(_isNegative, resultUsed, resultDigits);
-    if (_isNegative) {
-      // Round down if any bit was shifted out.
-      for (var i = 0; i < n; i++) {
-        if (digits[i] != 0) {
-          return result - one;
-        }
-      }
-    }
-    return result;
-  }
-
-  /// Shifts the digits of [xDigits] into the right place in [resultDigits].
-  ///
-  /// `resultDigits[ds..xUsed+ds] = xDigits[0..xUsed-1] << (n % _DIGIT_BITS)`
-  ///   where `ds = n ~/ _DIGIT_BITS`
-  ///
-  /// Does *not* clear digits below ds.
-  static void _lsh(
-      Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
-    assert(xUsed > 0);
-    final digitShift = n ~/ _digitBits;
-    final bitShift = n % _digitBits;
-    final carryBitShift = _digitBits - bitShift;
-    final bitMask = (1 << carryBitShift) - 1;
-    var carry = 0;
-    for (int i = xUsed - 1; i >= 0; i--) {
-      final digit = xDigits[i];
-      resultDigits[i + digitShift + 1] = (digit >> carryBitShift) | carry;
-      carry = (digit & bitMask) << bitShift;
-    }
-    resultDigits[digitShift] = carry;
-  }
-
-  /**
-   * Shift the bits of this integer to the left by [shiftAmount].
-   *
-   * Shifting to the left makes the number larger, effectively multiplying
-   * the number by `pow(2, shiftIndex)`.
-   *
-   * There is no limit on the size of the result. It may be relevant to
-   * limit intermediate values by using the "and" operator with a suitable
-   * mask.
-   *
-   * It is an error if [shiftAmount] is negative.
-   */
-  _BigIntImpl operator <<(int shiftAmount) {
-    if (shiftAmount < 0) {
-      throw ArgumentError("shift-amount must be posititve $shiftAmount");
-    }
-    if (_isZero) return this;
-    final digitShift = shiftAmount ~/ _digitBits;
-    final bitShift = shiftAmount % _digitBits;
-    if (bitShift == 0) {
-      return _dlShift(digitShift);
-    }
-    var resultUsed = _used + digitShift + 1;
-    var resultDigits = Uint16List(resultUsed);
-    _lsh(_digits, _used, shiftAmount, resultDigits);
-    return _BigIntImpl._(_isNegative, resultUsed, resultDigits);
-  }
-
-  // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n.
-  // Returns resultUsed.
-  static int _lShiftDigits(
-      Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
-    final digitsShift = n ~/ _digitBits;
-    final bitShift = n % _digitBits;
-    if (bitShift == 0) {
-      return _dlShiftDigits(xDigits, xUsed, digitsShift, resultDigits);
-    }
-    var resultUsed = xUsed + digitsShift + 1;
-    _lsh(xDigits, xUsed, n, resultDigits);
-    var i = digitsShift;
-    while (--i >= 0) {
-      resultDigits[i] = 0;
-    }
-    if (resultDigits[resultUsed - 1] == 0) {
-      resultUsed--; // Clamp result.
-    }
-    return resultUsed;
-  }
-
-  // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
-  static void _rsh(
-      Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
-    assert(xUsed > 0);
-    final digitsShift = n ~/ _digitBits;
-    final bitShift = n % _digitBits;
-    final carryBitShift = _digitBits - bitShift;
-    final bitMask = (1 << bitShift) - 1;
-    var carry = xDigits[digitsShift] >> bitShift;
-    final last = xUsed - digitsShift - 1;
-    for (var i = 0; i < last; i++) {
-      final digit = xDigits[i + digitsShift + 1];
-      resultDigits[i] = ((digit & bitMask) << carryBitShift) | carry;
-      carry = digit >> bitShift;
-    }
-    resultDigits[last] = carry;
-  }
-
-  /**
-   * Shift the bits of this integer to the right by [shiftAmount].
-   *
-   * Shifting to the right makes the number smaller and drops the least
-   * significant bits, effectively doing an integer division by
-   *`pow(2, shiftIndex)`.
-   *
-   * It is an error if [shiftAmount] is negative.
-   */
-  _BigIntImpl operator >>(int shiftAmount) {
-    if (shiftAmount < 0) {
-      throw ArgumentError("shift-amount must be posititve $shiftAmount");
-    }
-    if (_isZero) return this;
-    final digitShift = shiftAmount ~/ _digitBits;
-    final bitShift = shiftAmount % _digitBits;
-    if (bitShift == 0) {
-      return _drShift(digitShift);
-    }
-    final used = _used;
-    final resultUsed = used - digitShift;
-    if (resultUsed <= 0) {
-      return _isNegative ? _minusOne : zero;
-    }
-    final digits = _digits;
-    final resultDigits = Uint16List(resultUsed);
-    _rsh(digits, used, shiftAmount, resultDigits);
-    final result = _BigIntImpl._(_isNegative, resultUsed, resultDigits);
-    if (_isNegative) {
-      // Round down if any bit was shifted out.
-      if ((digits[digitShift] & ((1 << bitShift) - 1)) != 0) {
-        return result - one;
-      }
-      for (var i = 0; i < digitShift; i++) {
-        if (digits[i] != 0) {
-          return result - one;
-        }
-      }
-    }
-    return result;
-  }
-
-  /// Compares this to [other] taking the absolute value of both operands.
-  ///
-  /// Returns 0 if abs(this) == abs(other); a positive number if
-  /// abs(this) > abs(other); and a negative number if abs(this) < abs(other).
-  int _absCompare(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    return _compareDigits(_digits, _used, other._digits, other._used);
-  }
-
-  /**
-   * Compares this to `other`.
-   *
-   * Returns a negative number if `this` is less than `other`, zero if they are
-   * equal, and a positive number if `this` is greater than `other`.
-   */
-  int compareTo(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    if (_isNegative == other._isNegative) {
-      var result = _absCompare(other);
-      // Use 0 - result to avoid negative zero in JavaScript.
-      return _isNegative ? 0 - result : result;
-    }
-    return _isNegative ? -1 : 1;
-  }
-
-  /// Compares `digits[0..used-1]` with `otherDigits[0..otherUsed-1]`.
-  ///
-  /// Returns 0 if equal; a positive number if larger;
-  /// and a negative number if smaller.
-  static int _compareDigits(
-      Uint16List digits, int used, Uint16List otherDigits, int otherUsed) {
-    var result = used - otherUsed;
-    if (result == 0) {
-      for (int i = used - 1; i >= 0; i--) {
-        result = digits[i] - otherDigits[i];
-        if (result != 0) return result;
-      }
-    }
-    return result;
-  }
-
-  // resultDigits[0..used] = digits[0..used-1] + otherDigits[0..otherUsed-1].
-  // used >= otherUsed > 0.
-  static void _absAdd(Uint16List digits, int used, Uint16List otherDigits,
-      int otherUsed, Uint16List resultDigits) {
-    assert(used >= otherUsed && otherUsed > 0);
-    var carry = 0;
-    for (var i = 0; i < otherUsed; i++) {
-      carry += digits[i] + otherDigits[i];
-      resultDigits[i] = carry & _digitMask;
-      carry >>= _digitBits;
-    }
-    for (var i = otherUsed; i < used; i++) {
-      carry += digits[i];
-      resultDigits[i] = carry & _digitMask;
-      carry >>= _digitBits;
-    }
-    resultDigits[used] = carry;
-  }
-
-  // resultDigits[0..used-1] = digits[0..used-1] - otherDigits[0..otherUsed-1].
-  // used >= otherUsed > 0.
-  static void _absSub(Uint16List digits, int used, Uint16List otherDigits,
-      int otherUsed, Uint16List resultDigits) {
-    assert(used >= otherUsed && otherUsed > 0);
-
-    var carry = 0;
-    for (var i = 0; i < otherUsed; i++) {
-      carry += digits[i] - otherDigits[i];
-      resultDigits[i] = carry & _digitMask;
-      // Dart2js only supports unsigned shifts.
-      // Since the carry can only be -1 or 0 use this hack.
-      carry = 0 - ((carry >> _digitBits) & 1);
-    }
-    for (var i = otherUsed; i < used; i++) {
-      carry += digits[i];
-      resultDigits[i] = carry & _digitMask;
-      // Dart2js only supports unsigned shifts.
-      // Since the carry can only be -1 or 0 use this hack.
-      carry = 0 - ((carry >> _digitBits) & 1);
-    }
-  }
-
-  /// Returns `abs(this) + abs(other)` with sign set according to [isNegative].
-  _BigIntImpl _absAddSetSign(_BigIntImpl other, bool isNegative) {
-    var used = _used;
-    var otherUsed = other._used;
-    if (used < otherUsed) {
-      return other._absAddSetSign(this, isNegative);
-    }
-    if (used == 0) {
-      assert(!isNegative);
-      return zero;
-    }
-    if (otherUsed == 0) {
-      return _isNegative == isNegative ? this : -this;
-    }
-    var resultUsed = used + 1;
-    var resultDigits = Uint16List(resultUsed);
-    _absAdd(_digits, used, other._digits, otherUsed, resultDigits);
-    return _BigIntImpl._(isNegative, resultUsed, resultDigits);
-  }
-
-  /// Returns `abs(this) - abs(other)` with sign set according to [isNegative].
-  ///
-  /// Requirement: `abs(this) >= abs(other)`.
-  _BigIntImpl _absSubSetSign(_BigIntImpl other, bool isNegative) {
-    assert(_absCompare(other) >= 0);
-    var used = _used;
-    if (used == 0) {
-      assert(!isNegative);
-      return zero;
-    }
-    var otherUsed = other._used;
-    if (otherUsed == 0) {
-      return _isNegative == isNegative ? this : -this;
-    }
-    var resultDigits = Uint16List(used);
-    _absSub(_digits, used, other._digits, otherUsed, resultDigits);
-    return _BigIntImpl._(isNegative, used, resultDigits);
-  }
-
-  /// Returns `abs(this) & abs(other)` with sign set according to [isNegative].
-  _BigIntImpl _absAndSetSign(_BigIntImpl other, bool isNegative) {
-    var resultUsed = _min(_used, other._used);
-    var digits = _digits;
-    var otherDigits = other._digits;
-    var resultDigits = Uint16List(resultUsed);
-    for (var i = 0; i < resultUsed; i++) {
-      resultDigits[i] = digits[i] & otherDigits[i];
-    }
-    return _BigIntImpl._(isNegative, resultUsed, resultDigits);
-  }
-
-  /// Returns `abs(this) &~ abs(other)` with sign set according to [isNegative].
-  _BigIntImpl _absAndNotSetSign(_BigIntImpl other, bool isNegative) {
-    var resultUsed = _used;
-    var digits = _digits;
-    var otherDigits = other._digits;
-    var resultDigits = Uint16List(resultUsed);
-    var m = _min(resultUsed, other._used);
-    for (var i = 0; i < m; i++) {
-      resultDigits[i] = digits[i] & ~otherDigits[i];
-    }
-    for (var i = m; i < resultUsed; i++) {
-      resultDigits[i] = digits[i];
-    }
-    return _BigIntImpl._(isNegative, resultUsed, resultDigits);
-  }
-
-  /// Returns `abs(this) | abs(other)` with sign set according to [isNegative].
-  _BigIntImpl _absOrSetSign(_BigIntImpl other, bool isNegative) {
-    var used = _used;
-    var otherUsed = other._used;
-    var resultUsed = _max(used, otherUsed);
-    var digits = _digits;
-    var otherDigits = other._digits;
-    var resultDigits = Uint16List(resultUsed);
-    var l, m;
-    if (used < otherUsed) {
-      l = other;
-      m = used;
-    } else {
-      l = this;
-      m = otherUsed;
-    }
-    for (var i = 0; i < m; i++) {
-      resultDigits[i] = digits[i] | otherDigits[i];
-    }
-    var lDigits = l._digits;
-    for (var i = m; i < resultUsed; i++) {
-      resultDigits[i] = lDigits[i];
-    }
-    return _BigIntImpl._(isNegative, resultUsed, resultDigits);
-  }
-
-  /// Returns `abs(this) ^ abs(other)` with sign set according to [isNegative].
-  _BigIntImpl _absXorSetSign(_BigIntImpl other, bool isNegative) {
-    var used = _used;
-    var otherUsed = other._used;
-    var resultUsed = _max(used, otherUsed);
-    var digits = _digits;
-    var otherDigits = other._digits;
-    var resultDigits = Uint16List(resultUsed);
-    var l, m;
-    if (used < otherUsed) {
-      l = other;
-      m = used;
-    } else {
-      l = this;
-      m = otherUsed;
-    }
-    for (var i = 0; i < m; i++) {
-      resultDigits[i] = digits[i] ^ otherDigits[i];
-    }
-    var lDigits = l._digits;
-    for (var i = m; i < resultUsed; i++) {
-      resultDigits[i] = lDigits[i];
-    }
-    return _BigIntImpl._(isNegative, resultUsed, resultDigits);
-  }
-
-  /**
-   * Bit-wise and operator.
-   *
-   * Treating both `this` and [other] as sufficiently large two's component
-   * integers, the result is a number with only the bits set that are set in
-   * both `this` and [other]
-   *
-   * Of both operands are negative, the result is negative, otherwise
-   * the result is non-negative.
-   */
-  _BigIntImpl operator &(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    if (_isZero || other._isZero) return zero;
-    if (_isNegative == other._isNegative) {
-      if (_isNegative) {
-        // (-this) & (-other) == ~(this-1) & ~(other-1)
-        //                    == ~((this-1) | (other-1))
-        //                    == -(((this-1) | (other-1)) + 1)
-        _BigIntImpl this1 = _absSubSetSign(one, true);
-        _BigIntImpl other1 = other._absSubSetSign(one, true);
-        // Result cannot be zero if this and other are negative.
-        return this1._absOrSetSign(other1, true)._absAddSetSign(one, true);
-      }
-      return _absAndSetSign(other, false);
-    }
-    // _isNegative != other._isNegative
-    var p, n;
-    if (_isNegative) {
-      p = other;
-      n = this;
-    } else {
-      // & is symmetric.
-      p = this;
-      n = other;
-    }
-    // p & (-n) == p & ~(n-1) == p &~ (n-1)
-    var n1 = n._absSubSetSign(one, false);
-    return p._absAndNotSetSign(n1, false);
-  }
-
-  /**
-   * Bit-wise or operator.
-   *
-   * Treating both `this` and [other] as sufficiently large two's component
-   * integers, the result is a number with the bits set that are set in either
-   * of `this` and [other]
-   *
-   * If both operands are non-negative, the result is non-negative,
-   * otherwise the result us negative.
-   */
-  _BigIntImpl operator |(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    if (_isZero) return other;
-    if (other._isZero) return this;
-    if (_isNegative == other._isNegative) {
-      if (_isNegative) {
-        // (-this) | (-other) == ~(this-1) | ~(other-1)
-        //                    == ~((this-1) & (other-1))
-        //                    == -(((this-1) & (other-1)) + 1)
-        var this1 = _absSubSetSign(one, true);
-        var other1 = other._absSubSetSign(one, true);
-        // Result cannot be zero if this and a are negative.
-        return this1._absAndSetSign(other1, true)._absAddSetSign(one, true);
-      }
-      return _absOrSetSign(other, false);
-    }
-    // _neg != a._neg
-    var p, n;
-    if (_isNegative) {
-      p = other;
-      n = this;
-    } else {
-      // | is symmetric.
-      p = this;
-      n = other;
-    }
-    // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1)
-    var n1 = n._absSubSetSign(one, true);
-    // Result cannot be zero if only one of this or a is negative.
-    return n1._absAndNotSetSign(p, true)._absAddSetSign(one, true);
-  }
-
-  /**
-   * Bit-wise exclusive-or operator.
-   *
-   * Treating both `this` and [other] as sufficiently large two's component
-   * integers, the result is a number with the bits set that are set in one,
-   * but not both, of `this` and [other]
-   *
-   * If the operands have the same sign, the result is non-negative,
-   * otherwise the result is negative.
-   */
-  _BigIntImpl operator ^(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    if (_isZero) return other;
-    if (other._isZero) return this;
-    if (_isNegative == other._isNegative) {
-      if (_isNegative) {
-        // (-this) ^ (-other) == ~(this-1) ^ ~(other-1) == (this-1) ^ (other-1)
-        var this1 = _absSubSetSign(one, true);
-        var other1 = other._absSubSetSign(one, true);
-        return this1._absXorSetSign(other1, false);
-      }
-      return _absXorSetSign(other, false);
-    }
-    // _isNegative != a._isNegative
-    var p, n;
-    if (_isNegative) {
-      p = other;
-      n = this;
-    } else {
-      // ^ is symmetric.
-      p = this;
-      n = other;
-    }
-    // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1)
-    var n1 = n._absSubSetSign(one, true);
-    // Result cannot be zero if only one of this or a is negative.
-    return p._absXorSetSign(n1, true)._absAddSetSign(one, true);
-  }
-
-  /**
-   * The bit-wise negate operator.
-   *
-   * Treating `this` as a sufficiently large two's component integer,
-   * the result is a number with the opposite bits set.
-   *
-   * This maps any integer `x` to `-x - 1`.
-   */
-  _BigIntImpl operator ~() {
-    if (_isZero) return _minusOne;
-    if (_isNegative) {
-      // ~(-this) == ~(~(this-1)) == this-1
-      return _absSubSetSign(one, false);
-    }
-    // ~this == -this-1 == -(this+1)
-    // Result cannot be zero if this is positive.
-    return _absAddSetSign(one, true);
-  }
-
-  /// Addition operator.
-  _BigIntImpl operator +(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    if (_isZero) return other;
-    if (other._isZero) return this;
-    var isNegative = _isNegative;
-    if (isNegative == other._isNegative) {
-      // this + other == this + other
-      // (-this) + (-other) == -(this + other)
-      return _absAddSetSign(other, isNegative);
-    }
-    // this + (-other) == this - other == -(this - other)
-    // (-this) + other == other - this == -(this - other)
-    if (_absCompare(other) >= 0) {
-      return _absSubSetSign(other, isNegative);
-    }
-    return other._absSubSetSign(this, !isNegative);
-  }
-
-  /// Subtraction operator.
-  _BigIntImpl operator -(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    if (_isZero) return -other;
-    if (other._isZero) return this;
-    var isNegative = _isNegative;
-    if (isNegative != other._isNegative) {
-      // this - (-other) == this + other
-      // (-this) - other == -(this + other)
-      return _absAddSetSign(other, isNegative);
-    }
-    // this - other == this - a == -(this - other)
-    // (-this) - (-other) == other - this == -(this - other)
-    if (_absCompare(other) >= 0) {
-      return _absSubSetSign(other, isNegative);
-    }
-    return other._absSubSetSign(this, !isNegative);
-  }
-
-  /// Multiplies [x] with [multiplicandDigits] and adds the result to
-  /// [accumulatorDigits].
-  ///
-  /// The [multiplicandDigits] in the range [i] to [i]+[n]-1 are the
-  /// multiplicand digits.
-  ///
-  /// The [acculumatorDigits] in the range [j] to [j]+[n]-1 are the accumulator
-  /// digits.
-  ///
-  /// Adds the result of the multiplicand-digits * [x] to the accumulator.
-  ///
-  /// Concretely: `accumulatorDigits[j..j+n] += x * m_digits[i..i+n-1]`.
-  static void _mulAdd(int x, Uint16List multiplicandDigits, int i,
-      Uint16List accumulatorDigits, int j, int n) {
-    if (x == 0) {
-      // No-op if x is 0.
-      return;
-    }
-    int c = 0;
-    while (--n >= 0) {
-      int product = x * multiplicandDigits[i++];
-      int combined = product + accumulatorDigits[j] + c;
-      accumulatorDigits[j++] = combined & _digitMask;
-      // Note that this works with 53 bits, as the division will not lose
-      // bits.
-      c = combined ~/ _digitBase;
-    }
-    while (c != 0) {
-      int l = accumulatorDigits[j] + c;
-      accumulatorDigits[j++] = l & _digitMask;
-      c = l ~/ _digitBase;
-    }
-  }
-
-  /// Multiplication operator.
-  _BigIntImpl operator *(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    var used = _used;
-    var otherUsed = other._used;
-    if (used == 0 || otherUsed == 0) {
-      return zero;
-    }
-    var resultUsed = used + otherUsed;
-    var digits = _digits;
-    var otherDigits = other._digits;
-    var resultDigits = Uint16List(resultUsed);
-    var i = 0;
-    while (i < otherUsed) {
-      _mulAdd(otherDigits[i], digits, 0, resultDigits, i, used);
-      i++;
-    }
-    return _BigIntImpl._(
-        _isNegative != other._isNegative, resultUsed, resultDigits);
-  }
-
-  // r_digits[0..rUsed-1] = xDigits[0..xUsed-1]*otherDigits[0..otherUsed-1].
-  // Return resultUsed = xUsed + otherUsed.
-  static int _mulDigits(Uint16List xDigits, int xUsed, Uint16List otherDigits,
-      int otherUsed, Uint16List resultDigits) {
-    var resultUsed = xUsed + otherUsed;
-    var i = resultUsed;
-    assert(resultDigits.length >= i);
-    while (--i >= 0) {
-      resultDigits[i] = 0;
-    }
-    i = 0;
-    while (i < otherUsed) {
-      _mulAdd(otherDigits[i], xDigits, 0, resultDigits, i, xUsed);
-      i++;
-    }
-    return resultUsed;
-  }
-
-  /// Returns an estimate of `digits[i-1..i] ~/ topDigitDivisor`.
-  static int _estimateQuotientDigit(
-      int topDigitDivisor, Uint16List digits, int i) {
-    if (digits[i] == topDigitDivisor) return _digitMask;
-    var quotientDigit =
-        (digits[i] << _digitBits | digits[i - 1]) ~/ topDigitDivisor;
-    if (quotientDigit > _digitMask) return _digitMask;
-    return quotientDigit;
-  }
-
-  /// Returns `trunc(this / other)`, with `other != 0`.
-  _BigIntImpl _div(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    assert(other._used > 0);
-    if (_used < other._used) {
-      return zero;
-    }
-    _divRem(other);
-    // Return quotient, i.e.
-    // _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign.
-    var lastQuo_used = _lastQuoRemUsed - _lastRemUsed;
-    var quo_digits = _cloneDigits(
-        _lastQuoRemDigits, _lastRemUsed, _lastQuoRemUsed, lastQuo_used);
-    var quo = _BigIntImpl._(false, lastQuo_used, quo_digits);
-    if ((_isNegative != other._isNegative) && (quo._used > 0)) {
-      quo = -quo;
-    }
-    return quo;
-  }
-
-  /// Returns `this - other * trunc(this / other)`, with `other != 0`.
-  _BigIntImpl _rem(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    assert(other._used > 0);
-    if (_used < other._used) {
-      return this;
-    }
-    _divRem(other);
-    // Return remainder, i.e.
-    // denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign.
-    var remDigits =
-        _cloneDigits(_lastQuoRemDigits, 0, _lastRemUsed, _lastRemUsed);
-    var rem = _BigIntImpl._(false, _lastRemUsed, remDigits);
-    if (_lastRem_nsh > 0) {
-      rem = rem >> _lastRem_nsh; // Denormalize remainder.
-    }
-    if (_isNegative && (rem._used > 0)) {
-      rem = -rem;
-    }
-    return rem;
-  }
-
-  /// Computes this ~/ other and this.remainder(other).
-  ///
-  /// Stores the result in [_lastQuoRemDigits], [_lastQuoRemUsed] and
-  /// [_lastRemUsed]. The [_lastQuoRemDigits] contains the digits of *both*, the
-  /// quotient and the remainder.
-  ///
-  /// Caches the input to avoid doing the work again when users write
-  /// `a ~/ b` followed by a `a % b`.
-  void _divRem(_BigIntImpl other) {
-    // Check if result is already cached.
-    if ((this._used == _lastDividendUsed) &&
-        (other._used == _lastDivisorUsed) &&
-        identical(this._digits, _lastDividendDigits) &&
-        identical(other._digits, _lastDivisorDigits)) {
-      return;
-    }
-    assert(_used >= other._used);
-
-    var nsh = _digitBits - other._digits[other._used - 1].bitLength;
-    // Concatenated positive quotient and normalized positive remainder.
-    // The resultDigits can have at most one more digit than the dividend.
-    Uint16List resultDigits;
-    int resultUsed;
-    // Normalized positive divisor.
-    // The normalized divisor has the most-significant bit of its most
-    // significant digit set.
-    // This makes estimating the quotient easier.
-    Uint16List yDigits;
-    int yUsed;
-    if (nsh > 0) {
-      yDigits = Uint16List(other._used + 5);
-      yUsed = _lShiftDigits(other._digits, other._used, nsh, yDigits);
-      resultDigits = Uint16List(_used + 5);
-      resultUsed = _lShiftDigits(_digits, _used, nsh, resultDigits);
-    } else {
-      yDigits = other._digits;
-      yUsed = other._used;
-      resultDigits = _cloneDigits(_digits, 0, _used, _used + 2);
-      resultUsed = _used;
-    }
-    var topDigitDivisor = yDigits[yUsed - 1];
-    var i = resultUsed;
-    var j = i - yUsed;
-    // tmpDigits is a temporary array of i (resultUsed) digits.
-    var tmpDigits = Uint16List(i);
-    var tmpUsed = _dlShiftDigits(yDigits, yUsed, j, tmpDigits);
-    // Explicit first division step in case normalized dividend is larger or
-    // equal to shifted normalized divisor.
-    if (_compareDigits(resultDigits, resultUsed, tmpDigits, tmpUsed) >= 0) {
-      assert(i == resultUsed);
-      resultDigits[resultUsed++] = 1; // Quotient = 1.
-      // Subtract divisor from remainder.
-      _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
-    } else {
-      // Account for possible carry in _mulAdd step.
-      resultDigits[resultUsed++] = 0;
-    }
-
-    // Negate y so we can later use _mulAdd instead of non-existent _mulSub.
-    var nyDigits = Uint16List(yUsed + 2);
-    nyDigits[yUsed] = 1;
-    _absSub(nyDigits, yUsed + 1, yDigits, yUsed, nyDigits);
-    // nyDigits is read-only and has yUsed digits (possibly including several
-    // leading zeros).
-    // resultDigits is modified during iteration.
-    // resultDigits[0..yUsed-1] is the current remainder.
-    // resultDigits[yUsed..resultUsed-1] is the current quotient.
-    --i;
-
-    while (j > 0) {
-      var estimatedQuotientDigit =
-          _estimateQuotientDigit(topDigitDivisor, resultDigits, i);
-      j--;
-      _mulAdd(estimatedQuotientDigit, nyDigits, 0, resultDigits, j, yUsed);
-      if (resultDigits[i] < estimatedQuotientDigit) {
-        // Reusing the already existing tmpDigits array.
-        var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
-        _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
-        while (resultDigits[i] < --estimatedQuotientDigit) {
-          _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
-        }
-      }
-      i--;
-    }
-    // Cache result.
-    _lastDividendDigits = _digits;
-    _lastDividendUsed = _used;
-    _lastDivisorDigits = other._digits;
-    _lastDivisorUsed = other._used;
-    _lastQuoRemDigits = resultDigits;
-    _lastQuoRemUsed = resultUsed;
-    _lastRemUsed = yUsed;
-    _lastRem_nsh = nsh;
-  }
-
-  int get hashCode {
-    // This is the [Jenkins hash function][1] but using masking to keep
-    // values in SMI range.
-    //
-    // [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
-
-    int combine(int hash, int value) {
-      hash = 0x1fffffff & (hash + value);
-      hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
-      return hash ^ (hash >> 6);
-    }
-
-    int finish(int hash) {
-      hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
-      hash = hash ^ (hash >> 11);
-      return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
-    }
-
-    if (_isZero) return 6707; // Just a random number.
-    var hash = _isNegative ? 83585 : 429689; // Also random.
-    for (int i = 0; i < _used; i++) {
-      hash = combine(hash, _digits[i]);
-    }
-    return finish(hash);
-  }
-
-  /**
-   * Test whether this value is numerically equal to `other`.
-   *
-   * If [other] is a [_BigIntImpl] returns whether the two operands have the same
-   * value.
-   *
-   * Returns false if `other` is not a [_BigIntImpl].
-   */
-  bool operator ==(Object other) =>
-      other is _BigIntImpl && compareTo(other) == 0;
-
-  /**
-   * Returns the minimum number of bits required to store this big integer.
-   *
-   * The number of bits excludes the sign bit, which gives the natural length
-   * for non-negative (unsigned) values.  Negative values are complemented to
-   * return the bit position of the first bit that differs from the sign bit.
-   *
-   * To find the number of bits needed to store the value as a signed value,
-   * add one, i.e. use `x.bitLength + 1`.
-   *
-   * ```
-   * x.bitLength == (-x-1).bitLength
-   *
-   * new BigInt.from(3).bitLength == 2;   // 00000011
-   * new BigInt.from(2).bitLength == 2;   // 00000010
-   * new BigInt.from(1).bitLength == 1;   // 00000001
-   * new BigInt.from(0).bitLength == 0;   // 00000000
-   * new BigInt.from(-1).bitLength == 0;  // 11111111
-   * new BigInt.from(-2).bitLength == 1;  // 11111110
-   * new BigInt.from(-3).bitLength == 2;  // 11111101
-   * new BigInt.from(-4).bitLength == 2;  // 11111100
-   * ```
-   */
-  int get bitLength {
-    if (_used == 0) return 0;
-    if (_isNegative) return (~this).bitLength;
-    return _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
-  }
-
-  /**
-   * Truncating division operator.
-   *
-   * Performs a truncating integer division, where the remainder is discarded.
-   *
-   * The remainder can be computed using the [remainder] method.
-   *
-   * Examples:
-   * ```
-   * var seven = new BigInt.from(7);
-   * var three = new BigInt.from(3);
-   * seven ~/ three;    // => 2
-   * (-seven) ~/ three; // => -2
-   * seven ~/ -three;   // => -2
-   * seven.remainder(three);    // => 1
-   * (-seven).remainder(three); // => -1
-   * seven.remainder(-three);   // => 1
-   * ```
-   */
-  _BigIntImpl operator ~/(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    if (other._used == 0) {
-      throw const IntegerDivisionByZeroException();
-    }
-    return _div(other);
-  }
-
-  /**
-   * Returns the remainder of the truncating division of `this` by [other].
-   *
-   * The result `r` of this operation satisfies:
-   * `this == (this ~/ other) * other + r`.
-   * As a consequence the remainder `r` has the same sign as the divider `this`.
-   */
-  _BigIntImpl remainder(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    if (other._used == 0) {
-      throw const IntegerDivisionByZeroException();
-    }
-    return _rem(other);
-  }
-
-  /// Division operator.
-  double operator /(BigInt other) => this.toDouble() / other.toDouble();
-
-  /** Relational less than operator. */
-  bool operator <(BigInt other) => compareTo(other) < 0;
-
-  /** Relational less than or equal operator. */
-  bool operator <=(BigInt other) => compareTo(other) <= 0;
-
-  /** Relational greater than operator. */
-  bool operator >(BigInt other) => compareTo(other) > 0;
-
-  /** Relational greater than or equal operator. */
-  bool operator >=(BigInt other) => compareTo(other) >= 0;
-
-  /**
-   * Euclidean modulo operator.
-   *
-   * Returns the remainder of the Euclidean division. The Euclidean division of
-   * two integers `a` and `b` yields two integers `q` and `r` such that
-   * `a == b * q + r` and `0 <= r < b.abs()`.
-   *
-   * The sign of the returned value `r` is always positive.
-   *
-   * See [remainder] for the remainder of the truncating division.
-   */
-  _BigIntImpl operator %(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    if (other._used == 0) {
-      throw const IntegerDivisionByZeroException();
-    }
-    var result = _rem(other);
-    if (result._isNegative) {
-      if (other._isNegative) {
-        result = result - other;
-      } else {
-        result = result + other;
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Returns the sign of this big integer.
-   *
-   * Returns 0 for zero, -1 for values less than zero and
-   * +1 for values greater than zero.
-   */
-  int get sign {
-    if (_used == 0) return 0;
-    return _isNegative ? -1 : 1;
-  }
-
-  /// Whether this big integer is even.
-  bool get isEven => _used == 0 || (_digits[0] & 1) == 0;
-
-  /// Whether this big integer is odd.
-  bool get isOdd => !isEven;
-
-  /// Whether this number is negative.
-  bool get isNegative => _isNegative;
-
-  _BigIntImpl pow(int exponent) {
-    if (exponent < 0) {
-      throw ArgumentError("Exponent must not be negative: $exponent");
-    }
-    if (exponent == 0) return one;
-
-    // Exponentiation by squaring.
-    var result = one;
-    var base = this;
-    while (exponent != 0) {
-      if ((exponent & 1) == 1) {
-        result *= base;
-      }
-      exponent >>= 1;
-      // Skip unnecessary operation.
-      if (exponent != 0) {
-        base *= base;
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Returns this integer to the power of [exponent] modulo [modulus].
-   *
-   * The [exponent] must be non-negative and [modulus] must be
-   * positive.
-   */
-  _BigIntImpl modPow(BigInt bigExponent, BigInt bigModulus) {
-    _BigIntImpl exponent = bigExponent;
-    _BigIntImpl modulus = bigModulus;
-    if (exponent._isNegative) {
-      throw ArgumentError("exponent must be positive: $exponent");
-    }
-    if (modulus <= zero) {
-      throw ArgumentError("modulus must be strictly positive: $modulus");
-    }
-    if (exponent._isZero) return one;
-
-    final modulusUsed = modulus._used;
-    final modulusUsed2p4 = 2 * modulusUsed + 4;
-    final exponentBitlen = exponent.bitLength;
-    if (exponentBitlen <= 0) return one;
-    _BigIntReduction z = _BigIntClassic(modulus);
-    var resultDigits = Uint16List(modulusUsed2p4);
-    var result2Digits = Uint16List(modulusUsed2p4);
-    var gDigits = Uint16List(modulusUsed);
-    var gUsed = z.convert(this, gDigits);
-    // Initialize result with g.
-    // Copy leading zero if any.
-    for (int j = gUsed - 1; j >= 0; j--) {
-      resultDigits[j] = gDigits[j];
-    }
-    var resultUsed = gUsed;
-    var result2Used;
-    for (int i = exponentBitlen - 2; i >= 0; i--) {
-      result2Used = z.sqr(resultDigits, resultUsed, result2Digits);
-      if (!(exponent & (one << i))._isZero) {
-        resultUsed =
-            z.mul(result2Digits, result2Used, gDigits, gUsed, resultDigits);
-      } else {
-        // Swap result and result2.
-        var tmpDigits = resultDigits;
-        var tmpUsed = resultUsed;
-        resultDigits = result2Digits;
-        resultUsed = result2Used;
-        result2Digits = tmpDigits;
-        result2Used = tmpUsed;
-      }
-    }
-    return z.revert(resultDigits, resultUsed);
-  }
-
-  // If inv is false, returns gcd(x, y).
-  // If inv is true and gcd(x, y) = 1, returns d, so that c*x + d*y = 1.
-  // If inv is true and gcd(x, y) != 1, throws Exception("Not coprime").
-  static _BigIntImpl _binaryGcd(_BigIntImpl x, _BigIntImpl y, bool inv) {
-    var xDigits = x._digits;
-    var yDigits = y._digits;
-    var xUsed = x._used;
-    var yUsed = y._used;
-    var maxUsed = xUsed > yUsed ? xUsed : yUsed;
-    var unshiftedMaxUsed = maxUsed; // Keep
-    xDigits = _cloneDigits(xDigits, 0, xUsed, maxUsed);
-    yDigits = _cloneDigits(yDigits, 0, yUsed, maxUsed);
-    int shiftAmount = 0;
-    if (inv) {
-      if ((yUsed == 1) && (yDigits[0] == 1)) return one;
-      if ((yUsed == 0) || (yDigits[0].isEven && xDigits[0].isEven)) {
-        throw Exception("Not coprime");
-      }
-    } else {
-      if (x._isZero) {
-        throw ArgumentError.value(0, "this", "must not be zero");
-      }
-      if (y._isZero) {
-        throw ArgumentError.value(0, "other", "must not be zero");
-      }
-      if (((xUsed == 1) && (xDigits[0] == 1)) ||
-          ((yUsed == 1) && (yDigits[0] == 1))) return one;
-      while (((xDigits[0] & 1) == 0) && ((yDigits[0] & 1) == 0)) {
-        _rsh(xDigits, xUsed, 1, xDigits);
-        _rsh(yDigits, yUsed, 1, yDigits);
-        shiftAmount++;
-      }
-      if (shiftAmount >= _digitBits) {
-        var digitShiftAmount = shiftAmount ~/ _digitBits;
-        xUsed -= digitShiftAmount;
-        yUsed -= digitShiftAmount;
-        maxUsed -= digitShiftAmount;
-      }
-      if ((yDigits[0] & 1) == 1) {
-        // Swap x and y.
-        var tmpDigits = xDigits;
-        var tmpUsed = xUsed;
-        xDigits = yDigits;
-        xUsed = yUsed;
-        yDigits = tmpDigits;
-        yUsed = tmpUsed;
-      }
-    }
-    var uDigits = _cloneDigits(xDigits, 0, xUsed, unshiftedMaxUsed);
-    var vDigits =
-        _cloneDigits(yDigits, 0, yUsed, unshiftedMaxUsed + 2); // +2 for lsh.
-    final bool ac = (xDigits[0] & 1) == 0;
-
-    // Variables a, b, c, and d require one more digit.
-    final abcdUsed = maxUsed + 1;
-    final abcdLen = abcdUsed + 2; // +2 to satisfy _absAdd.
-    var aDigits, bDigits, cDigits, dDigits;
-    bool aIsNegative, bIsNegative, cIsNegative, dIsNegative;
-    if (ac) {
-      aDigits = Uint16List(abcdLen);
-      aIsNegative = false;
-      aDigits[0] = 1;
-      cDigits = Uint16List(abcdLen);
-      cIsNegative = false;
-    }
-    bDigits = Uint16List(abcdLen);
-    bIsNegative = false;
-    dDigits = Uint16List(abcdLen);
-    dIsNegative = false;
-    dDigits[0] = 1;
-
-    while (true) {
-      while ((uDigits[0] & 1) == 0) {
-        _rsh(uDigits, maxUsed, 1, uDigits);
-        if (ac) {
-          if (((aDigits[0] & 1) == 1) || ((bDigits[0] & 1) == 1)) {
-            if (aIsNegative) {
-              if ((aDigits[maxUsed] != 0) ||
-                  (_compareDigits(aDigits, maxUsed, yDigits, maxUsed)) > 0) {
-                _absSub(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
-              } else {
-                _absSub(yDigits, maxUsed, aDigits, maxUsed, aDigits);
-                aIsNegative = false;
-              }
-            } else {
-              _absAdd(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
-            }
-            if (bIsNegative) {
-              _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
-            } else if ((bDigits[maxUsed] != 0) ||
-                (_compareDigits(bDigits, maxUsed, xDigits, maxUsed) > 0)) {
-              _absSub(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
-            } else {
-              _absSub(xDigits, maxUsed, bDigits, maxUsed, bDigits);
-              bIsNegative = true;
-            }
-          }
-          _rsh(aDigits, abcdUsed, 1, aDigits);
-        } else if ((bDigits[0] & 1) == 1) {
-          if (bIsNegative) {
-            _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
-          } else if ((bDigits[maxUsed] != 0) ||
-              (_compareDigits(bDigits, maxUsed, xDigits, maxUsed) > 0)) {
-            _absSub(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
-          } else {
-            _absSub(xDigits, maxUsed, bDigits, maxUsed, bDigits);
-            bIsNegative = true;
-          }
-        }
-        _rsh(bDigits, abcdUsed, 1, bDigits);
-      }
-      while ((vDigits[0] & 1) == 0) {
-        _rsh(vDigits, maxUsed, 1, vDigits);
-        if (ac) {
-          if (((cDigits[0] & 1) == 1) || ((dDigits[0] & 1) == 1)) {
-            if (cIsNegative) {
-              if ((cDigits[maxUsed] != 0) ||
-                  (_compareDigits(cDigits, maxUsed, yDigits, maxUsed) > 0)) {
-                _absSub(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
-              } else {
-                _absSub(yDigits, maxUsed, cDigits, maxUsed, cDigits);
-                cIsNegative = false;
-              }
-            } else {
-              _absAdd(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
-            }
-            if (dIsNegative) {
-              _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-            } else if ((dDigits[maxUsed] != 0) ||
-                (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-              _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-            } else {
-              _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-              dIsNegative = true;
-            }
-          }
-          _rsh(cDigits, abcdUsed, 1, cDigits);
-        } else if ((dDigits[0] & 1) == 1) {
-          if (dIsNegative) {
-            _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-          } else if ((dDigits[maxUsed] != 0) ||
-              (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-            _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-          } else {
-            _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-            dIsNegative = true;
-          }
-        }
-        _rsh(dDigits, abcdUsed, 1, dDigits);
-      }
-      if (_compareDigits(uDigits, maxUsed, vDigits, maxUsed) >= 0) {
-        _absSub(uDigits, maxUsed, vDigits, maxUsed, uDigits);
-        if (ac) {
-          if (aIsNegative == cIsNegative) {
-            var a_cmp_c = _compareDigits(aDigits, abcdUsed, cDigits, abcdUsed);
-            if (a_cmp_c > 0) {
-              _absSub(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
-            } else {
-              _absSub(cDigits, abcdUsed, aDigits, abcdUsed, aDigits);
-              aIsNegative = !aIsNegative && (a_cmp_c != 0);
-            }
-          } else {
-            _absAdd(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
-          }
-        }
-        if (bIsNegative == dIsNegative) {
-          var b_cmp_d = _compareDigits(bDigits, abcdUsed, dDigits, abcdUsed);
-          if (b_cmp_d > 0) {
-            _absSub(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
-          } else {
-            _absSub(dDigits, abcdUsed, bDigits, abcdUsed, bDigits);
-            bIsNegative = !bIsNegative && (b_cmp_d != 0);
-          }
-        } else {
-          _absAdd(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
-        }
-      } else {
-        _absSub(vDigits, maxUsed, uDigits, maxUsed, vDigits);
-        if (ac) {
-          if (cIsNegative == aIsNegative) {
-            var c_cmp_a = _compareDigits(cDigits, abcdUsed, aDigits, abcdUsed);
-            if (c_cmp_a > 0) {
-              _absSub(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
-            } else {
-              _absSub(aDigits, abcdUsed, cDigits, abcdUsed, cDigits);
-              cIsNegative = !cIsNegative && (c_cmp_a != 0);
-            }
-          } else {
-            _absAdd(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
-          }
-        }
-        if (dIsNegative == bIsNegative) {
-          var d_cmp_b = _compareDigits(dDigits, abcdUsed, bDigits, abcdUsed);
-          if (d_cmp_b > 0) {
-            _absSub(dDigits, abcdUsed, bDigits, abcdUsed, dDigits);
-          } else {
-            _absSub(bDigits, abcdUsed, dDigits, abcdUsed, dDigits);
-            dIsNegative = !dIsNegative && (d_cmp_b != 0);
-          }
-        } else {
-          _absAdd(dDigits, abcdUsed, bDigits, abcdUsed, dDigits);
-        }
-      }
-      // Exit loop if u == 0.
-      var i = maxUsed;
-      while ((i > 0) && (uDigits[i - 1] == 0)) --i;
-      if (i == 0) break;
-    }
-    if (!inv) {
-      if (shiftAmount > 0) {
-        maxUsed = _lShiftDigits(vDigits, maxUsed, shiftAmount, vDigits);
-      }
-      return _BigIntImpl._(false, maxUsed, vDigits);
-    }
-    // No inverse if v != 1.
-    var i = maxUsed - 1;
-    while ((i > 0) && (vDigits[i] == 0)) --i;
-    if ((i != 0) || (vDigits[0] != 1)) {
-      throw Exception("Not coprime");
-    }
-
-    if (dIsNegative) {
-      if ((dDigits[maxUsed] != 0) ||
-          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-        _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        if ((dDigits[maxUsed] != 0) ||
-            (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-          _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        } else {
-          _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-          dIsNegative = false;
-        }
-      } else {
-        _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-        dIsNegative = false;
-      }
-    } else if ((dDigits[maxUsed] != 0) ||
-        (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-      _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-      if ((dDigits[maxUsed] != 0) ||
-          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-        _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-      }
-    }
-    return _BigIntImpl._(false, maxUsed, dDigits);
-  }
-
-  /**
-   * Returns the modular multiplicative inverse of this big integer
-   * modulo [modulus].
-   *
-   * The [modulus] must be positive.
-   *
-   * It is an error if no modular inverse exists.
-   */
-  // Returns 1/this % modulus, with modulus > 0.
-  _BigIntImpl modInverse(BigInt bigInt) {
-    _BigIntImpl modulus = bigInt;
-    if (modulus <= zero) {
-      throw ArgumentError("Modulus must be strictly positive: $modulus");
-    }
-    if (modulus == one) return zero;
-    var tmp = this;
-    if (tmp._isNegative || (tmp._absCompare(modulus) >= 0)) {
-      tmp %= modulus;
-    }
-    return _binaryGcd(modulus, tmp, true);
-  }
-
-  /**
-   * Returns the greatest common divisor of this big integer and [other].
-   *
-   * If either number is non-zero, the result is the numerically greatest
-   * integer dividing both `this` and `other`.
-   *
-   * The greatest common divisor is independent of the order,
-   * so `x.gcd(y)` is  always the same as `y.gcd(x)`.
-   *
-   * For any integer `x`, `x.gcd(x)` is `x.abs()`.
-   *
-   * If both `this` and `other` is zero, the result is also zero.
-   */
-  _BigIntImpl gcd(BigInt bigInt) {
-    _BigIntImpl other = bigInt;
-    if (_isZero) return other.abs();
-    if (other._isZero) return this.abs();
-    return _binaryGcd(this, other, false);
-  }
-
-  /**
-   * Returns the least significant [width] bits of this big integer as a
-   * non-negative number (i.e. unsigned representation).  The returned value has
-   * zeros in all bit positions higher than [width].
-   *
-   * ```
-   * new BigInt.from(-1).toUnsigned(5) == 31   // 11111111  ->  00011111
-   * ```
-   *
-   * This operation can be used to simulate arithmetic from low level languages.
-   * For example, to increment an 8 bit quantity:
-   *
-   * ```
-   * q = (q + 1).toUnsigned(8);
-   * ```
-   *
-   * `q` will count from `0` up to `255` and then wrap around to `0`.
-   *
-   * If the input fits in [width] bits without truncation, the result is the
-   * same as the input.  The minimum width needed to avoid truncation of `x` is
-   * given by `x.bitLength`, i.e.
-   *
-   * ```
-   * x == x.toUnsigned(x.bitLength);
-   * ```
-   */
-  _BigIntImpl toUnsigned(int width) {
-    return this & ((one << width) - one);
-  }
-
-  /**
-   * Returns the least significant [width] bits of this integer, extending the
-   * highest retained bit to the sign.  This is the same as truncating the value
-   * to fit in [width] bits using an signed 2-s complement representation.  The
-   * returned value has the same bit value in all positions higher than [width].
-   *
-   * ```
-   * var big15 = new BigInt.from(15);
-   * var big16 = new BigInt.from(16);
-   * var big239 = new BigInt.from(239);
-   *                                      V--sign bit-V
-   * big16.toSigned(5) == -big16   //  00010000 -> 11110000
-   * big239.toSigned(5) == big15   //  11101111 -> 00001111
-   *                                      ^           ^
-   * ```
-   *
-   * This operation can be used to simulate arithmetic from low level languages.
-   * For example, to increment an 8 bit signed quantity:
-   *
-   * ```
-   * q = (q + 1).toSigned(8);
-   * ```
-   *
-   * `q` will count from `0` up to `127`, wrap to `-128` and count back up to
-   * `127`.
-   *
-   * If the input value fits in [width] bits without truncation, the result is
-   * the same as the input.  The minimum width needed to avoid truncation of `x`
-   * is `x.bitLength + 1`, i.e.
-   *
-   * ```
-   * x == x.toSigned(x.bitLength + 1);
-   * ```
-   */
-  _BigIntImpl toSigned(int width) {
-    // The value of binary number weights each bit by a power of two.  The
-    // twos-complement value weights the sign bit negatively.  We compute the
-    // value of the negative weighting by isolating the sign bit with the
-    // correct power of two weighting and subtracting it from the value of the
-    // lower bits.
-    var signMask = one << (width - 1);
-    return (this & (signMask - one)) - (this & signMask);
-  }
-
-  // Maximum number of digits that always fit in mantissa.
-  static const _simpleValidIntDigits = 53 ~/ _digitBits;
-
-  bool get isValidInt {
-    if (_used <= _simpleValidIntDigits) return true;
-    var asInt = toInt();
-    if (!asInt.toDouble().isFinite) return false;
-    return this == _BigIntImpl._fromInt(asInt);
-  }
-
-  int toInt() {
-    var result = 0;
-    for (int i = _used - 1; i >= 0; i--) {
-      result = result * _digitBase + _digits[i];
-    }
-    return _isNegative ? -result : result;
-  }
-
-  /**
-   * Returns this [_BigIntImpl] as a [double].
-   *
-   * If the number is not representable as a [double], an
-   * approximation is returned. For numerically large integers, the
-   * approximation may be infinite.
-   */
-  double toDouble() {
-    const int exponentBias = 1075;
-    // There are 11 bits for the exponent.
-    // 2047 (all bits set to 1) is reserved for infinity and NaN.
-    // When storing the exponent in the 11 bits, it is biased by exponentBias
-    // to support negative exponents.
-    const int maxDoubleExponent = 2046 - exponentBias;
-    if (_isZero) return 0.0;
-
-    // We fill the 53 bits little-endian.
-    var resultBits = Uint8List(8);
-
-    var length = _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
-    if (length > maxDoubleExponent + 53) {
-      return _isNegative ? double.negativeInfinity : double.infinity;
-    }
-
-    // The most significant bit is for the sign.
-    if (_isNegative) resultBits[7] = 0x80;
-
-    // Write the exponent into bits 1..12:
-    var biasedExponent = length - 53 + exponentBias;
-    resultBits[6] = (biasedExponent & 0xF) << 4;
-    resultBits[7] |= biasedExponent >> 4;
-
-    int cachedBits = 0;
-    int cachedBitsLength = 0;
-    int digitIndex = _used - 1;
-    int readBits(int n) {
-      // Ensure that we have enough bits in [cachedBits].
-      while (cachedBitsLength < n) {
-        int nextDigit;
-        int nextDigitLength = _digitBits; // May get updated.
-        if (digitIndex < 0) {
-          nextDigit = 0;
-          digitIndex--;
-        } else {
-          nextDigit = _digits[digitIndex];
-          if (digitIndex == _used - 1) nextDigitLength = nextDigit.bitLength;
-          digitIndex--;
-        }
-        cachedBits = (cachedBits << nextDigitLength) + nextDigit;
-        cachedBitsLength += nextDigitLength;
-      }
-      // Read the top [n] bits.
-      var result = cachedBits >> (cachedBitsLength - n);
-      // Remove the bits from the cache.
-      cachedBits -= result << (cachedBitsLength - n);
-      cachedBitsLength -= n;
-      return result;
-    }
-
-    // The first leading 1 bit is implicit in the double-representation and can
-    // be discarded.
-    var leadingBits = readBits(5) & 0xF;
-    resultBits[6] |= leadingBits;
-
-    for (int i = 5; i >= 0; i--) {
-      // Get the remaining 48 bits.
-      resultBits[i] = readBits(8);
-    }
-
-    void roundUp() {
-      // Simply consists of adding 1 to the whole 64 bit "number".
-      // It will update the exponent, if necessary.
-      // It might even round up to infinity (which is what we want).
-      var carry = 1;
-      for (int i = 0; i < 8; i++) {
-        if (carry == 0) break;
-        var sum = resultBits[i] + carry;
-        resultBits[i] = sum & 0xFF;
-        carry = sum >> 8;
-      }
-    }
-
-    if (readBits(1) == 1) {
-      if (resultBits[0].isOdd) {
-        // Rounds to even all the time.
-        roundUp();
-      } else {
-        // Round up, if there is at least one other digit that is not 0.
-        if (cachedBits != 0) {
-          // There is already one in the cachedBits.
-          roundUp();
-        } else {
-          for (int i = digitIndex; digitIndex >= 0; i--) {
-            if (_digits[i] != 0) {
-              roundUp();
-              break;
-            }
-          }
-        }
-      }
-    }
-    return resultBits.buffer.asByteData().getFloat64(0, Endian.little);
-  }
-
-  /**
-   * Returns a String-representation of this integer.
-   *
-   * The returned string is parsable by [parse].
-   * For any `_BigIntImpl` `i`, it is guaranteed that
-   * `i == _BigIntImpl.parse(i.toString())`.
-   */
-  String toString() {
-    if (_used == 0) return "0";
-    if (_used == 1) {
-      if (_isNegative) return (-_digits[0]).toString();
-      return _digits[0].toString();
-    }
-
-    // Generate in chunks of 4 digits.
-    // The chunks are in reversed order.
-    var decimalDigitChunks = <String>[];
-    var rest = isNegative ? -this : this;
-    while (rest._used > 1) {
-      var digits4 = rest.remainder(_bigInt10000).toString();
-      decimalDigitChunks.add(digits4);
-      if (digits4.length == 1) decimalDigitChunks.add("000");
-      if (digits4.length == 2) decimalDigitChunks.add("00");
-      if (digits4.length == 3) decimalDigitChunks.add("0");
-      rest = rest ~/ _bigInt10000;
-    }
-    decimalDigitChunks.add(rest._digits[0].toString());
-    if (_isNegative) decimalDigitChunks.add("-");
-    return decimalDigitChunks.reversed.join();
-  }
-
-  int _toRadixCodeUnit(int digit) {
-    const int _0 = 48;
-    const int _a = 97;
-    if (digit < 10) return _0 + digit;
-    return _a + digit - 10;
-  }
-
-  /**
-   * Converts [this] to a string representation in the given [radix].
-   *
-   * In the string representation, lower-case letters are used for digits above
-   * '9', with 'a' being 10 an 'z' being 35.
-   *
-   * The [radix] argument must be an integer in the range 2 to 36.
-   */
-  String toRadixString(int radix) {
-    if (radix > 36) throw RangeError.range(radix, 2, 36);
-
-    if (_used == 0) return "0";
-
-    if (_used == 1) {
-      var digitString = _digits[0].toRadixString(radix);
-      if (_isNegative) return "-" + digitString;
-      return digitString;
-    }
-
-    if (radix == 16) return _toHexString();
-
-    var base = _BigIntImpl._fromInt(radix);
-    var reversedDigitCodeUnits = <int>[];
-    var rest = this.abs();
-    while (!rest._isZero) {
-      var digit = rest.remainder(base).toInt();
-      rest = rest ~/ base;
-      reversedDigitCodeUnits.add(_toRadixCodeUnit(digit));
-    }
-    var digitString = String.fromCharCodes(reversedDigitCodeUnits.reversed);
-    if (_isNegative) return "-" + digitString;
-    return digitString;
-  }
-
-  String _toHexString() {
-    var chars = <int>[];
-    for (int i = 0; i < _used - 1; i++) {
-      int chunk = _digits[i];
-      for (int j = 0; j < (_digitBits ~/ 4); j++) {
-        chars.add(_toRadixCodeUnit(chunk & 0xF));
-        chunk >>= 4;
-      }
-    }
-    var msbChunk = _digits[_used - 1];
-    while (msbChunk != 0) {
-      chars.add(_toRadixCodeUnit(msbChunk & 0xF));
-      msbChunk >>= 4;
-    }
-    if (_isNegative) {
-      const _dash = 45;
-      chars.add(_dash);
-    }
-    return String.fromCharCodes(chars.reversed);
-  }
-}
-
-// Interface for modular reduction.
-abstract class _BigIntReduction {
-  // Return the number of digits used by r_digits.
-  int convert(_BigIntImpl x, Uint16List r_digits);
-  int mul(Uint16List xDigits, int xUsed, Uint16List yDigits, int yUsed,
-      Uint16List resultDigits);
-  int sqr(Uint16List xDigits, int xUsed, Uint16List resultDigits);
-
-  // Return x reverted to _BigIntImpl.
-  _BigIntImpl revert(Uint16List xDigits, int xUsed);
-}
-
-// Modular reduction using "classic" algorithm.
-class _BigIntClassic implements _BigIntReduction {
-  final _BigIntImpl _modulus; // Modulus.
-  final _BigIntImpl _normalizedModulus; // Normalized _modulus.
-
-  _BigIntClassic(this._modulus)
-      : _normalizedModulus = _modulus <<
-            (_BigIntImpl._digitBits -
-                _modulus._digits[_modulus._used - 1].bitLength);
-
-  int convert(_BigIntImpl x, Uint16List resultDigits) {
-    var digits;
-    var used;
-    if (x._isNegative || x._absCompare(_modulus) >= 0) {
-      var remainder = x._rem(_modulus);
-      if (x._isNegative && remainder._used > 0) {
-        assert(remainder._isNegative);
-        remainder += _modulus;
-      }
-      assert(!remainder._isNegative);
-      used = remainder._used;
-      digits = remainder._digits;
-    } else {
-      used = x._used;
-      digits = x._digits;
-    }
-    var i = used; // Copy leading zero if any.
-    while (--i >= 0) {
-      resultDigits[i] = digits[i];
-    }
-    return used;
-  }
-
-  _BigIntImpl revert(Uint16List xDigits, int xUsed) {
-    return _BigIntImpl._(false, xUsed, xDigits);
-  }
-
-  int _reduce(Uint16List xDigits, int xUsed) {
-    if (xUsed < _modulus._used) {
-      return xUsed;
-    }
-    var reverted = revert(xDigits, xUsed);
-    var rem = reverted._rem(_normalizedModulus);
-    return convert(rem, xDigits);
-  }
-
-  int sqr(Uint16List xDigits, int xUsed, Uint16List resultDigits) {
-    var b = _BigIntImpl._(false, xUsed, xDigits);
-    var b2 = b * b;
-    for (int i = 0; i < b2._used; i++) {
-      resultDigits[i] = b2._digits[i];
-    }
-    for (int i = b2._used; i < 2 * xUsed; i++) {
-      resultDigits[i] = 0;
-    }
-    return _reduce(resultDigits, 2 * xUsed);
-  }
-
-  int mul(Uint16List xDigits, int xUsed, Uint16List yDigits, int yUsed,
-      Uint16List resultDigits) {
-    var resultUsed =
-        _BigIntImpl._mulDigits(xDigits, xUsed, yDigits, yUsed, resultDigits);
-    return _reduce(resultDigits, resultUsed);
-  }
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/isolate_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/isolate_patch.dart
deleted file mode 100644
index 9ccdada..0000000
--- a/pkg/dev_compiler/tool/input_sdk/patch/isolate_patch.dart
+++ /dev/null
@@ -1,122 +0,0 @@
-// 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.
-
-// Patch file for the dart:isolate library.
-
-import 'dart:_js_helper' show patch, NoReifyGeneric;
-import 'dart:async';
-
-@patch
-class Isolate {
-  // `current` must be a getter, not just a final field,
-  // to match the external declaration.
-  @patch
-  static Isolate get current => _unsupported();
-
-  @patch
-  String get debugName => _unsupported();
-
-  @patch
-  static Future<Uri> get packageRoot => _unsupported();
-
-  @patch
-  static Future<Uri> get packageConfig => _unsupported();
-
-  static Uri _packageBase = Uri.base.resolve('packages/');
-
-  @patch
-  static Future<Uri> resolvePackageUri(Uri packageUri) async {
-    if (packageUri.scheme != 'package') return packageUri;
-    return _packageBase.resolveUri(packageUri.replace(scheme: ''));
-  }
-
-  @patch
-  static Future<Isolate> spawn<T>(void entryPoint(T message), T message,
-          {bool paused = false,
-          bool errorsAreFatal,
-          SendPort onExit,
-          SendPort onError}) =>
-      _unsupported();
-
-  @patch
-  static Future<Isolate> spawnUri(Uri uri, List<String> args, var message,
-          {bool paused = false,
-          SendPort onExit,
-          SendPort onError,
-          bool errorsAreFatal,
-          bool checked,
-          Map<String, String> environment,
-          Uri packageRoot,
-          Uri packageConfig,
-          bool automaticPackageResolution = false}) =>
-      _unsupported();
-
-  @patch
-  void _pause(Capability resumeCapability) => _unsupported();
-
-  @patch
-  void resume(Capability resumeCapability) => _unsupported();
-
-  @patch
-  void addOnExitListener(SendPort responsePort, {Object response}) =>
-      _unsupported();
-
-  @patch
-  void removeOnExitListener(SendPort responsePort) => _unsupported();
-
-  @patch
-  void setErrorsFatal(bool errorsAreFatal) => _unsupported();
-
-  @patch
-  void kill({int priority = beforeNextEvent}) => _unsupported();
-  @patch
-  void ping(SendPort responsePort,
-          {Object response, int priority = immediate}) =>
-      _unsupported();
-
-  @patch
-  void addErrorListener(SendPort port) => _unsupported();
-
-  @patch
-  void removeErrorListener(SendPort port) => _unsupported();
-}
-
-/** Default factory for receive ports. */
-@patch
-class ReceivePort {
-  @patch
-  factory ReceivePort() = _ReceivePort;
-
-  @patch
-  factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) =>
-      _unsupported();
-}
-
-/// ReceivePort is supported by dev_compiler because async test packages
-/// (async_helper, unittest) create a dummy receive port to keep the Dart VM
-/// alive.
-class _ReceivePort extends Stream implements ReceivePort {
-  close() {}
-
-  get sendPort => _unsupported();
-
-  listen(onData, {onError, onDone, cancelOnError}) => _unsupported();
-}
-
-@patch
-class RawReceivePort {
-  @patch
-  factory RawReceivePort([void handler(event)]) => _unsupported();
-}
-
-@patch
-class Capability {
-  @patch
-  factory Capability() => _unsupported();
-}
-
-@NoReifyGeneric()
-T _unsupported<T>() {
-  throw UnsupportedError('dart:isolate is not supported on dart4web');
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
deleted file mode 100644
index 3f848d6..0000000
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
+++ /dev/null
@@ -1,526 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// This library defines the operations that define and manipulate Dart
-/// classes.  Included in this are:
-///   - Generics
-///   - Class metadata
-///   - Extension methods
-///
-
-// TODO(leafp): Consider splitting some of this out.
-part of dart._runtime;
-
-/// Returns a new type that mixes members from base and the mixin.
-void applyMixin(to, from) {
-  JS('', '#[#] = #', to, _mixin, from);
-  var toProto = JS('', '#.prototype', to);
-  var fromProto = JS('', '#.prototype', from);
-  _copyMembers(toProto, fromProto);
-  _mixinSignature(to, from, _methodSig);
-  _mixinSignature(to, from, _fieldSig);
-  _mixinSignature(to, from, _getterSig);
-  _mixinSignature(to, from, _setterSig);
-  var mixinOnFn = JS('', '#[#]', from, mixinOn);
-  if (mixinOnFn != null) {
-    var proto = JS('', '#(#.__proto__).prototype', mixinOnFn, to);
-    _copyMembers(toProto, proto);
-  }
-}
-
-void _copyMembers(to, from) {
-  var names = getOwnNamesAndSymbols(from);
-  for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) {
-    String name = JS('', '#[#]', names, i);
-    if (name == 'constructor') continue;
-    _copyMember(to, from, name);
-  }
-  return to;
-}
-
-void _copyMember(to, from, name) {
-  var desc = getOwnPropertyDescriptor(from, name);
-  if (JS('!', '# == Symbol.iterator', name)) {
-    // On native types, Symbol.iterator may already be present.
-    // TODO(jmesserly): investigate if we still need this.
-    // If so, we need to find a better solution.
-    // See https://github.com/dart-lang/sdk/issues/28324
-    var existing = getOwnPropertyDescriptor(to, name);
-    if (existing != null) {
-      if (JS('!', '#.writable', existing)) {
-        JS('', '#[#] = #.value', to, name, desc);
-      }
-      return;
-    }
-  }
-  var getter = JS('', '#.get', desc);
-  var setter = JS('', '#.set', desc);
-  if (getter != null) {
-    if (setter == null) {
-      var obj = JS(
-          '',
-          '#.set = { __proto__: #.__proto__, '
-          'set [#](x) { return super[#] = x; } }',
-          desc,
-          to,
-          name,
-          name);
-      JS('', '#.set = #.set', desc, getOwnPropertyDescriptor(obj, name));
-    }
-  } else if (setter != null) {
-    if (getter == null) {
-      var obj = JS(
-          '',
-          '#.get = { __proto__: #.__proto__, '
-          'get [#]() { return super[#]; } }',
-          desc,
-          to,
-          name,
-          name);
-      JS('', '#.get = #.get', desc, getOwnPropertyDescriptor(obj, name));
-    }
-  }
-  defineProperty(to, name, desc);
-}
-
-void _mixinSignature(to, from, kind) {
-  JS('', '#[#] = #', to, kind, () {
-    var baseMembers = _getMembers(JS('', '#.__proto__', to), kind);
-    var fromMembers = _getMembers(from, kind);
-    if (fromMembers == null) return baseMembers;
-    var toSignature = JS('', '{ __proto__: # }', baseMembers);
-    copyProperties(toSignature, fromMembers);
-    return toSignature;
-  });
-}
-
-final _mixin = JS('', 'Symbol("mixin")');
-
-getMixin(clazz) => JS('', 'Object.hasOwnProperty.call(#, #) ? #[#] : null',
-    clazz, _mixin, clazz, _mixin);
-
-final mixinOn = JS('', 'Symbol("mixinOn")');
-
-@JSExportName('implements')
-final implements_ = JS('', 'Symbol("implements")');
-
-List Function() getImplements(clazz) => JS(
-    '',
-    'Object.hasOwnProperty.call(#, #) ? #[#] : null',
-    clazz,
-    implements_,
-    clazz,
-    implements_);
-
-/// The Symbol for storing type arguments on a specialized generic type.
-final _typeArguments = JS('', 'Symbol("typeArguments")');
-
-final _originalDeclaration = JS('', 'Symbol("originalDeclaration")');
-
-final mixinNew = JS('', 'Symbol("dart.mixinNew")');
-
-/// Memoize a generic type constructor function.
-generic(typeConstructor, setBaseClass) => JS('', '''(() => {
-  let length = $typeConstructor.length;
-  if (length < 1) {
-    $throwInternalError('must have at least one generic type argument');
-  }
-  let resultMap = new Map();
-  $_cacheMaps.push(resultMap);
-  function makeGenericType(...args) {
-    if (args.length != length && args.length != 0) {
-      $throwInternalError('requires ' + length + ' or 0 type arguments');
-    }
-    while (args.length < length) args.push($dynamic);
-
-    let value = resultMap;
-    for (let i = 0; i < length; i++) {
-      let arg = args[i];
-      if (arg == null) {
-        $throwInternalError('type arguments should not be null: '
-                          + $typeConstructor);
-      }
-      let map = value;
-      value = map.get(arg);
-      if (value === void 0) {
-        if (i + 1 == length) {
-          value = $typeConstructor.apply(null, args);
-          // Save the type constructor and arguments for reflection.
-          if (value) {
-            value[$_typeArguments] = args;
-            value[$_originalDeclaration] = makeGenericType;
-          }
-          map.set(arg, value);
-          if ($setBaseClass != null) $setBaseClass.apply(null, args);
-        } else {
-          value = new Map();
-          map.set(arg, value);
-        }
-      }
-    }
-    return value;
-  }
-  makeGenericType[$_genericTypeCtor] = $typeConstructor;
-  return makeGenericType;
-})()''');
-
-getGenericClass(type) => safeGetOwnProperty(type, _originalDeclaration);
-
-List getGenericArgs(type) =>
-    JS('List', '#', safeGetOwnProperty(type, _typeArguments));
-
-List<TypeVariable> getGenericTypeFormals(genericClass) {
-  return _typeFormalsFromFunction(getGenericTypeCtor(genericClass));
-}
-
-Object instantiateClass(Object genericClass, List<Object> typeArgs) {
-  return JS('', '#.apply(null, #)', genericClass, typeArgs);
-}
-
-final _constructorSig = JS('', 'Symbol("sigCtor")');
-final _methodSig = JS('', 'Symbol("sigMethod")');
-final _fieldSig = JS('', 'Symbol("sigField")');
-final _getterSig = JS('', 'Symbol("sigGetter")');
-final _setterSig = JS('', 'Symbol("sigSetter")');
-final _staticMethodSig = JS('', 'Symbol("sigStaticMethod")');
-final _staticFieldSig = JS('', 'Symbol("sigStaticField")');
-final _staticGetterSig = JS('', 'Symbol("sigStaticGetter")');
-final _staticSetterSig = JS('', 'Symbol("sigStaticSetter")');
-final _genericTypeCtor = JS('', 'Symbol("genericType")');
-
-getConstructors(value) => _getMembers(value, _constructorSig);
-getMethods(value) => _getMembers(value, _methodSig);
-getFields(value) => _getMembers(value, _fieldSig);
-getGetters(value) => _getMembers(value, _getterSig);
-getSetters(value) => _getMembers(value, _setterSig);
-getStaticMethods(value) => _getMembers(value, _staticMethodSig);
-getStaticFields(value) => _getMembers(value, _staticFieldSig);
-getStaticGetters(value) => _getMembers(value, _staticGetterSig);
-getStaticSetters(value) => _getMembers(value, _staticSetterSig);
-
-getGenericTypeCtor(value) => JS('', '#[#]', value, _genericTypeCtor);
-
-/// Get the type of a method from an object using the stored signature
-getType(obj) =>
-    JS('', '# == null ? # : #.__proto__.constructor', obj, Object, obj);
-
-bool isJsInterop(obj) {
-  if (obj == null) return false;
-  if (JS('!', 'typeof # === "function"', obj)) {
-    // A function is a Dart function if it has runtime type information.
-    return JS('!', '#[#] == null', obj, _runtimeType);
-  }
-  // Primitive types are not JS interop types.
-  if (JS('!', 'typeof # !== "object"', obj)) return false;
-
-  // Extension types are not considered JS interop types.
-  // Note that it is still possible to call typed JS interop methods on
-  // extension types but the calls must be statically typed.
-  if (JS('!', '#[#] != null', obj, _extensionType)) return false;
-  return JS('!', '!($obj instanceof $Object)');
-}
-
-/// Get the type of a method from a type using the stored signature
-getMethodType(type, name) {
-  var m = getMethods(type);
-  return m != null ? JS('', '#[#]', m, name) : null;
-}
-
-/// Gets the type of the corresponding setter (this includes writable fields).
-getSetterType(type, name) {
-  var setters = getSetters(type);
-  if (setters != null) {
-    var type = JS('', '#[#]', setters, name);
-    if (type != null) {
-      if (JS('!', '# instanceof Array', type)) {
-        // The type has metadata attached.  Pull out just the type.
-        // TODO(jmesserly): remove when we remove mirrors
-        return JS('', '#[0]', type);
-      }
-      return type;
-    }
-  }
-  var fields = getFields(type);
-  if (fields != null) {
-    var fieldInfo = JS('', '#[#]', fields, name);
-    if (fieldInfo != null && JS<bool>('!', '!#.isFinal', fieldInfo)) {
-      return JS('', '#.type', fieldInfo);
-    }
-  }
-  return null;
-}
-
-finalFieldType(type, metadata) =>
-    JS('', '{ type: #, isFinal: true, metadata: # }', type, metadata);
-
-fieldType(type, metadata) =>
-    JS('', '{ type: #, isFinal: false, metadata: # }', type, metadata);
-
-/// Get the type of a constructor from a class using the stored signature
-/// If name is undefined, returns the type of the default constructor
-/// Returns undefined if the constructor is not found.
-classGetConstructorType(cls, name) {
-  if (cls == null) return null;
-  if (name == null) name = 'new';
-  var ctors = getConstructors(cls);
-  return ctors != null ? JS('', '#[#]', ctors, name) : null;
-}
-
-void setMethodSignature(f, sigF) => JS('', '#[#] = #', f, _methodSig, sigF);
-void setFieldSignature(f, sigF) => JS('', '#[#] = #', f, _fieldSig, sigF);
-void setGetterSignature(f, sigF) => JS('', '#[#] = #', f, _getterSig, sigF);
-void setSetterSignature(f, sigF) => JS('', '#[#] = #', f, _setterSig, sigF);
-
-// Set up the constructor signature field on the constructor
-void setConstructorSignature(f, sigF) =>
-    JS('', '#[#] = #', f, _constructorSig, sigF);
-
-// Set up the static signature field on the constructor
-void setStaticMethodSignature(f, sigF) =>
-    JS('', '#[#] = #', f, _staticMethodSig, sigF);
-
-void setStaticFieldSignature(f, sigF) =>
-    JS('', '#[#] = #', f, _staticFieldSig, sigF);
-
-void setStaticGetterSignature(f, sigF) =>
-    JS('', '#[#] = #', f, _staticGetterSig, sigF);
-
-void setStaticSetterSignature(f, sigF) =>
-    JS('', '#[#] = #', f, _staticSetterSig, sigF);
-
-_getMembers(type, kind) {
-  var sig = JS('', '#[#]', type, kind);
-  return JS<bool>('!', 'typeof # == "function"', sig)
-      ? JS('', '#[#] = #()', type, kind, sig)
-      : sig;
-}
-
-bool _hasMember(type, kind, name) {
-  var sig = _getMembers(type, kind);
-  return sig != null && JS<bool>('!', '# in #', name, sig);
-}
-
-bool hasMethod(type, name) => _hasMember(type, _methodSig, name);
-bool hasGetter(type, name) => _hasMember(type, _getterSig, name);
-bool hasSetter(type, name) => _hasMember(type, _setterSig, name);
-bool hasField(type, name) => _hasMember(type, _fieldSig, name);
-
-final _extensionType = JS('', 'Symbol("extensionType")');
-
-final dartx = JS('', 'dartx');
-
-/// Install properties in prototype-first order.  Properties / descriptors from
-/// more specific types should overwrite ones from less specific types.
-void _installProperties(jsProto, dartType, installedParent) {
-  if (JS('!', '# === #', dartType, Object)) {
-    _installPropertiesForObject(jsProto);
-    return;
-  }
-  // If the extension methods of the parent have been installed on the parent
-  // of [jsProto], the methods will be available via prototype inheritance.
-  var dartSupertype = JS('', '#.__proto__', dartType);
-  if (JS('!', '# !== #', dartSupertype, installedParent)) {
-    _installProperties(jsProto, dartSupertype, installedParent);
-  }
-
-  var dartProto = JS('', '#.prototype', dartType);
-  copyTheseProperties(jsProto, dartProto, getOwnPropertySymbols(dartProto));
-}
-
-void _installPropertiesForObject(jsProto) {
-  // core.Object members need to be copied from the non-symbol name to the
-  // symbol name.
-  var coreObjProto = JS('', '#.prototype', Object);
-  var names = getOwnPropertyNames(coreObjProto);
-  for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) {
-    var name = JS<String>('!', '#[#]', names, i);
-    if (name == 'constructor') continue;
-    var desc = getOwnPropertyDescriptor(coreObjProto, name);
-    defineProperty(jsProto, JS('', '#.#', dartx, name), desc);
-  }
-}
-
-void _installPropertiesForGlobalObject(jsProto) {
-  _installPropertiesForObject(jsProto);
-  // Use JS toString for JS objects, rather than the Dart one.
-  JS('', '#[dartx.toString] = function() { return this.toString(); }', jsProto);
-  identityEquals ??= JS('', '#[dartx._equals]', jsProto);
-}
-
-final _extensionMap = JS('', 'new Map()');
-
-_applyExtension(jsType, dartExtType) {
-  // TODO(vsm): Not all registered js types are real.
-  if (jsType == null) return;
-  var jsProto = JS('', '#.prototype', jsType);
-  if (jsProto == null) return;
-
-  if (JS('!', '# === #', dartExtType, Object)) {
-    _installPropertiesForGlobalObject(jsProto);
-    return;
-  }
-
-  _installProperties(
-      jsProto, dartExtType, JS('', '#[#]', jsProto, _extensionType));
-
-  // Mark the JS type's instances so we can easily check for extensions.
-  if (JS('!', '# !== #', dartExtType, JSFunction)) {
-    JS('', '#[#] = #', jsProto, _extensionType, dartExtType);
-  }
-  JS('', '#[#] = #[#]', jsType, _methodSig, dartExtType, _methodSig);
-  JS('', '#[#] = #[#]', jsType, _fieldSig, dartExtType, _fieldSig);
-  JS('', '#[#] = #[#]', jsType, _getterSig, dartExtType, _getterSig);
-  JS('', '#[#] = #[#]', jsType, _setterSig, dartExtType, _setterSig);
-}
-
-/// Apply the previously registered extension to the type of [nativeObject].
-/// This is intended for types that are not available to polyfill at startup.
-applyExtension(name, nativeObject) {
-  var dartExtType = JS('', '#.get(#)', _extensionMap, name);
-  var jsType = JS('', '#.constructor', nativeObject);
-  _applyExtension(jsType, dartExtType);
-}
-
-/// Apply all registered extensions to a window.  This is intended for
-/// different frames, where registrations need to be reapplied.
-applyAllExtensions(global) {
-  JS('', '#.forEach((dartExtType, name) => #(#[name], dartExtType))',
-      _extensionMap, _applyExtension, global);
-}
-
-/// Copy symbols from the prototype of the source to destination.
-/// These are the only properties safe to copy onto an existing public
-/// JavaScript class.
-registerExtension(name, dartExtType) {
-  JS('', '#.set(#, #)', _extensionMap, name, dartExtType);
-  var jsType = JS('', '#[#]', global_, name);
-  _applyExtension(jsType, dartExtType);
-}
-
-///
-/// Mark a concrete type as implementing extension methods.
-/// For example: `class MyIter implements Iterable`.
-///
-/// This takes a list of names, which are the extension methods implemented.
-/// It will add a forwarder, so the extension method name redirects to the
-/// normal Dart method name. For example:
-///
-///     defineExtensionMembers(MyType, ['add', 'remove']);
-///
-/// Results in:
-///
-///     MyType.prototype[dartx.add] = MyType.prototype.add;
-///     MyType.prototype[dartx.remove] = MyType.prototype.remove;
-///
-// TODO(jmesserly): essentially this gives two names to the same method.
-// This benefit is roughly equivalent call performance either way, but the
-// cost is we need to call defineExtensionMembers any time a subclass
-// overrides one of these methods.
-defineExtensionMethods(type, Iterable memberNames) {
-  var proto = JS('', '#.prototype', type);
-  for (var name in memberNames) {
-    JS('', '#[dartx.#] = #[#]', proto, name, proto, name);
-  }
-}
-
-/// Like [defineExtensionMethods], but for getter/setter pairs.
-defineExtensionAccessors(type, Iterable memberNames) {
-  var proto = JS('', '#.prototype', type);
-  for (var name in memberNames) {
-    // Find the member. It should always exist (or we have a compiler bug).
-    var member;
-    var p = proto;
-    for (;; p = JS('', '#.__proto__', p)) {
-      member = getOwnPropertyDescriptor(p, name);
-      if (member != null) break;
-    }
-    defineProperty(proto, JS('', 'dartx[#]', name), member);
-  }
-}
-
-definePrimitiveHashCode(proto) {
-  defineProperty(proto, identityHashCode_,
-      getOwnPropertyDescriptor(proto, extensionSymbol('hashCode')));
-}
-
-/// Link the extension to the type it's extending as a base class.
-setBaseClass(derived, base) {
-  JS('', '#.prototype.__proto__ = #.prototype', derived, base);
-  // We use __proto__ to track the superclass hierarchy (see isSubtypeOf).
-  JS('', '#.__proto__ = #', derived, base);
-}
-
-/// Like [setBaseClass], but for generic extension types such as `JSArray<E>`.
-setExtensionBaseClass(dartType, jsType) {
-  // Mark the generic type as an extension type and link the prototype objects.
-  var dartProto = JS('', '#.prototype', dartType);
-  JS('', '#[#] = #', dartProto, _extensionType, dartType);
-  JS('', '#.__proto__ = #.prototype', dartProto, jsType);
-}
-
-/// Adds type test predicates to a class/interface type [ctor], using the
-/// provided [isClass] JS Symbol.
-///
-/// This will operate quickly for non-generic types, native extension types,
-/// as well as matching exact generic type arguments:
-///
-///     class C<T> {}
-///     class D extends C<int> {}
-///     main() { dynamic d = new D(); d as C<int>; }
-///
-addTypeTests(ctor, isClass) {
-  if (isClass == null) isClass = JS('', 'Symbol("_is_" + ctor.name)');
-  // TODO(jmesserly): since we know we're dealing with class/interface types,
-  // we can optimize this rather than go through the generic `dart.is` helpers.
-  JS('', '#.prototype[#] = true', ctor, isClass);
-  JS(
-      '',
-      '''#.is = function is_C(obj) {
-    return obj != null && (obj[#] || #(obj, this));
-  }''',
-      ctor,
-      isClass,
-      instanceOf);
-  JS(
-      '',
-      '''#.as = function as_C(obj) {
-    if (obj == null || obj[#]) return obj;
-    return #(obj, this, false);
-  }''',
-      ctor,
-      isClass,
-      cast);
-  JS(
-      '',
-      '''#._check = function check_C(obj) {
-    if (obj == null || obj[#]) return obj;
-    return #(obj, this, true);
-  }''',
-      ctor,
-      isClass,
-      cast);
-}
-
-// TODO(jmesserly): should we do this for all interfaces?
-
-/// The well known symbol for testing `is Future`
-final isFuture = JS('', 'Symbol("_is_Future")');
-
-/// The well known symbol for testing `is Iterable`
-final isIterable = JS('', 'Symbol("_is_Iterable")');
-
-/// The well known symbol for testing `is List`
-final isList = JS('', 'Symbol("_is_List")');
-
-/// The well known symbol for testing `is Map`
-final isMap = JS('', 'Symbol("_is_Map")');
-
-/// The well known symbol for testing `is Stream`
-final isStream = JS('', 'Symbol("_is_Stream")');
-
-/// The well known symbol for testing `is StreamSubscription`
-final isStreamSubscription = JS('', 'Symbol("_is_StreamSubscription")');
-
-/// The default `operator ==` that calls [identical].
-var identityEquals;
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
deleted file mode 100644
index 8c8e929..0000000
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart._runtime;
-
-// We need to set these properties while the sdk is only partially initialized
-// so we cannot use regular Dart fields.
-// The default values for these properties are set when the global_ final field
-// in runtime.dart is initialized.
-
-// Override, e.g., for testing
-void trapRuntimeErrors(bool flag) {
-  JS('', 'dart.__trapRuntimeErrors = #', flag);
-}
-
-void ignoreWhitelistedErrors(bool flag) {
-  JS('', 'dart.__ignoreWhitelistedErrors = #', flag);
-}
-
-// TODO(jmesserly): remove this?
-void ignoreAllErrors(bool flag) {
-  JS('', 'dart.__ignoreAllErrors = #', flag);
-}
-
-argumentError(value) {
-  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
-  throw ArgumentError.value(value);
-}
-
-throwUnimplementedError(String message) {
-  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
-  throw UnimplementedError(message);
-}
-
-assertFailed(message) {
-  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
-  throw AssertionErrorImpl(message);
-}
-
-throwCyclicInitializationError([Object field]) {
-  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
-  throw CyclicInitializationError(field);
-}
-
-throwNullValueError() {
-  // TODO(vsm): Per spec, we should throw an NSM here.  Technically, we ought
-  // to thread through method info, but that uglifies the code and can't
-  // actually be queried ... it only affects how the error is printed.
-  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
-  throw NoSuchMethodError(
-      null, Symbol('<Unexpected Null Value>'), null, null, null);
-}
-
-castError(obj, expectedType, [@notNull bool isImplicit = false]) {
-  var actualType = getReifiedType(obj);
-  var message = _castErrorMessage(actualType, expectedType);
-  if (JS('!', 'dart.__ignoreAllErrors')) {
-    JS('', 'console.error(#)', message);
-    return obj;
-  }
-  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
-  var error = isImplicit ? TypeErrorImpl(message) : CastErrorImpl(message);
-  throw error;
-}
-
-String _castErrorMessage(from, to) {
-  // If both types are generic classes, see if we can infer generic type
-  // arguments for `from` that would allow the subtype relation to work.
-  var fromClass = getGenericClass(from);
-  if (fromClass != null) {
-    var fromTypeFormals = getGenericTypeFormals(fromClass);
-    var fromType = instantiateClass(fromClass, fromTypeFormals);
-    var inferrer = _TypeInferrer(fromTypeFormals);
-    if (inferrer.trySubtypeMatch(fromType, to)) {
-      var inferredTypes = inferrer.getInferredTypes();
-      if (inferredTypes != null) {
-        var inferred = instantiateClass(fromClass, inferredTypes);
-        return "Type '${typeName(from)}' should be '${typeName(inferred)}' "
-            "to implement expected type '${typeName(to)}'.";
-      }
-    }
-  }
-  return "Expected a value of type '${typeName(to)}', "
-      "but got one of type '${typeName(from)}'";
-}
-
-/// The symbol that references the thrown Dart Object (typically but not
-/// necessarily an [Error] or [Exception]), used by the [exception] function.
-final Object _thrownValue = JS('', 'Symbol("_thrownValue")');
-
-/// For a Dart [Error], this provides access to the JS Error object that
-/// contains the stack trace if the error was thrown.
-final Object _jsError = JS('', 'Symbol("_jsError")');
-
-/// Gets the thrown Dart Object from an [error] caught by a JS catch.
-///
-/// If the throw originated in Dart, the result will typically be an [Error]
-/// or [Exception], but it could be any Dart object.
-///
-/// If the throw originated in JavaScript, then there is not a corresponding
-/// Dart value, so we just return the error object.
-Object getThrown(Object error) {
-  if (error != null) {
-    // Get the Dart thrown value, if any.
-    var value = JS('', '#[#]', error, _thrownValue);
-    if (value != null) return value;
-  }
-  // Otherwise return the original object.
-  return error;
-}
-
-final _stackTrace = JS('', 'Symbol("_stackTrace")');
-
-/// Returns the stack trace from an [error] caught by a JS catch.
-///
-/// If the throw originated in Dart, we should always have JS Error
-/// (see [throw_]) so we can create a Dart [StackTrace] from that (or return a
-/// previously created instance).
-///
-/// If the throw originated in JavaScript and was an `Error`, then we can get
-/// the corresponding stack trace the same way we do for Dart throws. If the
-/// throw object was not an Error, then we don't have a JS trace, so we create
-/// one here.
-StackTrace stackTrace(Object error) {
-  if (JS<bool>('!', '!(# instanceof Error)', error)) {
-    // We caught something that isn't a JS Error.
-    //
-    // We should only hit this path when a non-Error was thrown from JS. In
-    // case, there is no stack trace available, so create one here.
-    return _StackTrace.missing(error);
-  }
-
-  // If we've already created the Dart stack trace object, return it.
-  StackTrace trace = JS('', '#[#]', error, _stackTrace);
-  if (trace != null) return trace;
-
-  // Otherwise create the Dart stack trace (by parsing the JS stack), and
-  // cache it so we don't repeat the parsing/allocation.
-  return JS('', '#[#] = #', error, _stackTrace, _StackTrace(error));
-}
-
-StackTrace stackTraceForError(Error error) {
-  return stackTrace(JS('', '#[#]', error, _jsError));
-}
-
-/// Implements `rethrow` of [error], allowing rethrow in an expression context.
-///
-/// Note: [error] must be the raw JS error caught in the JS catch, not the
-/// unwrapped value returned by [getThrown].
-@JSExportName('rethrow')
-void rethrow_(Object error) {
-  JS('', 'throw #', error);
-}
-
-/// Subclass of JS `Error` that wraps a thrown Dart object, and evaluates the
-/// message lazily by calling `toString()` on the wrapped Dart object.
-///
-/// Also creates a pointer from the thrown Dart object to the JS Error
-/// (via [_jsError]). This is used to implement [Error.stackTrace], but also
-/// provides a way to recover the stack trace if we lose track of it.
-/// [Error] requires preserving the original stack trace if an error is
-/// rethrown, so we only update the pointer if it wasn't already set.
-///
-/// TODO(jmesserly): Dart Errors should simply be JS Errors.
-final Object DartError = JS(
-    '!',
-    '''class DartError extends Error {
-      constructor(error) {
-        super();
-        if (error == null) error = #;
-        this[#] = error;
-        if (error != null && typeof error == "object" && error[#] == null) {
-          error[#] = this;
-        }
-      }
-      get message() {
-        return #(this[#]);
-      }
-    }''',
-    NullThrownError(),
-    _thrownValue,
-    _jsError,
-    _jsError,
-    _toString,
-    _thrownValue);
-
-/// Subclass of [DartError] for cases where we're rethrowing with a different,
-/// original Dart StackTrace object.
-///
-/// This includes the original stack trace in the JS Error message so it doesn't
-/// get lost if the exception reaches JS.
-final Object RethrownDartError = JS(
-    '!',
-    '''class RethrownDartError extends # {
-      constructor(error, stackTrace) {
-        super(error);
-        this[#] = stackTrace;
-      }
-      get message() {
-        return super.message + "\\n    " + #(this[#]) + "\\n";
-      }
-    }''',
-    DartError,
-    _stackTrace,
-    _toString,
-    _stackTrace);
-
-/// Implements `throw` of [exception], allowing for throw in an expression
-/// context, and capturing the current stack trace.
-@JSExportName('throw')
-void throw_(Object exception) {
-  /// Wrap the object so we capture a new stack trace, and so it will print
-  /// nicely from JS, as if it were a normal JS error.
-  JS('', 'throw new #(#)', DartError, exception);
-}
-
-/// Returns a JS error for throwing the Dart [exception] Object and using the
-/// provided stack [trace].
-///
-/// This is used by dart:async to rethrow unhandled errors in [Zone]s, and by
-/// `async`/`async*` to rethrow errors from Futures/Streams into the generator
-/// (so a try/catch in there can catch it).
-///
-/// If the exception and trace originated from the same Dart throw, then we can
-/// simply return the original JS Error. Otherwise, we have to create a new JS
-/// Error. The new error will have the correct Dart trace, but it will not have
-/// the correct JS stack trace (visible if JavaScript ends up handling it). To
-/// fix that, we use [RethrownDartError] to preserve the Dart trace and make
-/// sure it gets displayed in the JS error message.
-///
-/// If the stack trace is null, this will preserve the original stack trace
-/// on the exception, if available, otherwise it will capture the current stack
-/// trace.
-Object createErrorWithStack(Object exception, StackTrace trace) {
-  if (trace == null) {
-    var error = JS('', '#[#]', exception, _jsError);
-    return error != null ? error : JS('', 'new #(#)', DartError, exception);
-  }
-  if (trace is _StackTrace) {
-    /// Optimization: if this stack trace and exception already have a matching
-    /// Error, we can just rethrow it.
-    var originalError = trace._jsError;
-    if (identical(exception, getThrown(originalError))) {
-      return originalError;
-    }
-  }
-  return JS('', 'new #(#, #)', RethrownDartError, exception, trace);
-}
-
-// This is a utility function: it is only intended to be called from dev
-// tools.
-void stackPrint(Object error) {
-  JS('', 'console.log(#.stack ? #.stack : "No stack trace for: " + #)', error,
-      error, error);
-}
-
-class _StackTrace implements StackTrace {
-  final Object _jsError;
-  final Object _jsObjectMissingTrace;
-  String _trace;
-
-  _StackTrace(this._jsError) : _jsObjectMissingTrace = null;
-
-  _StackTrace.missing(Object caughtObj)
-      : _jsObjectMissingTrace = caughtObj != null ? caughtObj : 'null',
-        _jsError = JS('', 'Error()');
-
-  String toString() {
-    if (_trace != null) return _trace;
-
-    var e = _jsError;
-    String trace = '';
-    if (e != null && JS('bool', 'typeof # === "object"', e)) {
-      trace = e is NativeError ? e.dartStack() : JS<String>('', '#.stack', e);
-      if (trace != null && stackTraceMapper != null) {
-        trace = stackTraceMapper(trace);
-      }
-    }
-    if (trace.isEmpty || _jsObjectMissingTrace != null) {
-      String jsToString;
-      try {
-        jsToString = JS('', '"" + #', _jsObjectMissingTrace);
-      } catch (_) {
-        jsToString = '<error converting JS object to string>';
-      }
-      trace = 'Non-error `$jsToString` thrown by JS does not have stack trace.'
-          '\nCaught in Dart at:\n\n$trace';
-    }
-    return _trace = trace;
-  }
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
deleted file mode 100644
index 7ab4a81..0000000
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
+++ /dev/null
@@ -1,758 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// This library defines runtime operations on objects used by the code
-/// generator.
-part of dart._runtime;
-
-// TODO(jmesserly): remove this in favor of _Invocation.
-class InvocationImpl extends Invocation {
-  final Symbol memberName;
-  final List positionalArguments;
-  final Map<Symbol, dynamic> namedArguments;
-  final List<Type> typeArguments;
-  final bool isMethod;
-  final bool isGetter;
-  final bool isSetter;
-
-  InvocationImpl(memberName, List<Object> positionalArguments,
-      {namedArguments,
-      List typeArguments,
-      this.isMethod = false,
-      this.isGetter = false,
-      this.isSetter = false})
-      : memberName =
-            isSetter ? _setterSymbol(memberName) : _dartSymbol(memberName),
-        positionalArguments = List.unmodifiable(positionalArguments),
-        namedArguments = _namedArgsToSymbols(namedArguments),
-        typeArguments = typeArguments == null
-            ? const []
-            : List.unmodifiable(typeArguments.map(wrapType));
-
-  static Map<Symbol, dynamic> _namedArgsToSymbols(namedArgs) {
-    if (namedArgs == null) return const {};
-    return Map.unmodifiable(Map.fromIterable(getOwnPropertyNames(namedArgs),
-        key: _dartSymbol, value: (k) => JS('', '#[#]', namedArgs, k)));
-  }
-}
-
-/// Given an object and a method name, tear off the method.
-/// Sets the runtime type of the torn off method appropriately,
-/// and also binds the object.
-///
-/// If the optional `f` argument is passed in, it will be used as the method.
-/// This supports cases like `super.foo` where we need to tear off the method
-/// from the superclass, not from the `obj` directly.
-// TODO(leafp): Consider caching the tearoff on the object?
-bind(obj, name, method) {
-  if (obj == null) obj = jsNull;
-  if (method == null) method = JS('', '#[#]', obj, name);
-  var f = JS('', '#.bind(#)', method, obj);
-  // TODO(jmesserly): canonicalize tearoffs.
-  JS('', '#._boundObject = #', f, obj);
-  JS('', '#._boundMethod = #', f, method);
-  JS('', '#[#] = #', f, _runtimeType, getMethodType(getType(obj), name));
-  return f;
-}
-
-/// Binds the `call` method of an interface type, handling null.
-///
-/// Essentially this works like `obj?.call`. It also handles the needs of
-/// [dsend]/[dcall], returning `null` if no method was found with the given
-/// canonical member [name].
-///
-/// [name] is typically `"call"` but it could be the [extensionSymbol] for
-/// `call`, if we define it on a native type, and [obj] is known statially to be
-/// a native type/interface with `call`.
-bindCall(obj, name) {
-  if (obj == null) return null;
-  var ftype = getMethodType(getType(obj), name);
-  if (ftype == null) return null;
-  var method = JS('', '#[#]', obj, name);
-  var f = JS('', '#.bind(#)', method, obj);
-  // TODO(jmesserly): canonicalize tearoffs.
-  JS('', '#._boundObject = #', f, obj);
-  JS('', '#._boundMethod = #', f, method);
-  JS('', '#[#] = #', f, _runtimeType, ftype);
-  return f;
-}
-
-/// Instantiate a generic method.
-///
-/// We need to apply the type arguments both to the function, as well as its
-/// associated function type.
-gbind(f, @rest List typeArgs) {
-  GenericFunctionType type = JS('!', '#[#]', f, _runtimeType);
-  type.checkBounds(typeArgs);
-  // Create a JS wrapper function that will also pass the type arguments, and
-  // tag it with the instantiated function type.
-  var result =
-      JS('', '(...args) => #.apply(null, #.concat(args))', f, typeArgs);
-  return fn(result, type.instantiate(typeArgs));
-}
-
-dloadRepl(obj, field) => dload(obj, replNameLookup(obj, field), false);
-
-// Warning: dload, dput, and dsend assume they are never called on methods
-// implemented by the Object base class as those methods can always be
-// statically resolved.
-dload(obj, field, [@undefined mirrors]) {
-  if (JS('!', 'typeof # == "function" && # == "call"', obj, field)) {
-    return obj;
-  }
-  var f = _canonicalMember(obj, field);
-
-  trackCall(obj);
-  if (f != null) {
-    var type = getType(obj);
-
-    if (hasField(type, f) || hasGetter(type, f)) return JS('', '#[#]', obj, f);
-    if (hasMethod(type, f)) return bind(obj, f, null);
-
-    // Always allow for JS interop objects.
-    if (!JS<bool>('!', '#', mirrors) && isJsInterop(obj)) {
-      return JS('', '#[#]', obj, f);
-    }
-  }
-  return noSuchMethod(obj, InvocationImpl(field, JS('', '[]'), isGetter: true));
-}
-
-// Version of dload that matches legacy mirrors behavior for JS types.
-dloadMirror(obj, field) => dload(obj, field, true);
-
-_stripGenericArguments(type) {
-  var genericClass = getGenericClass(type);
-  if (genericClass != null) return JS('', '#()', genericClass);
-  return type;
-}
-
-// Version of dput that matches legacy Dart 1 type check rules and mirrors
-// behavior for JS types.
-// TODO(jacobr): remove the type checking rules workaround when mirrors based
-// PageLoader code can generate the correct reified generic types.
-dputMirror(obj, field, value) => dput(obj, field, value, true);
-
-dputRepl(obj, field, value) =>
-    dput(obj, replNameLookup(obj, field), value, false);
-
-dput(obj, field, value, [@undefined mirrors]) {
-  var f = _canonicalMember(obj, field);
-  trackCall(obj);
-  if (f != null) {
-    var setterType = getSetterType(getType(obj), f);
-    if (setterType != null) {
-      if (JS('!', '#', mirrors))
-        setterType = _stripGenericArguments(setterType);
-      return JS('', '#[#] = #._check(#)', obj, f, setterType, value);
-    }
-    // Always allow for JS interop objects.
-    if (!JS<bool>('!', '#', mirrors) && isJsInterop(obj)) {
-      return JS('', '#[#] = #', obj, f, value);
-    }
-  }
-  noSuchMethod(
-      obj, InvocationImpl(field, JS('', '[#]', value), isSetter: true));
-  return value;
-}
-
-/// Check that a function of a given type can be applied to
-/// actuals.
-bool _checkApply(FunctionType type, List actuals, namedActuals) {
-  // Check for too few required arguments.
-  int actualsCount = JS('!', '#.length', actuals);
-  var required = type.args;
-  int requiredCount = JS('!', '#.length', required);
-  if (actualsCount < requiredCount) return false;
-
-  // Check for too many postional arguments.
-  var extras = actualsCount - requiredCount;
-  var optionals = type.optionals;
-  if (extras > JS<int>('!', '#.length', optionals)) return false;
-
-  // Check if we have invalid named arguments.
-  Iterable names;
-  var named = type.named;
-  if (namedActuals != null) {
-    names = getOwnPropertyNames(namedActuals);
-    for (var name in names) {
-      if (!JS('!', '#.hasOwnProperty(#)', named, name)) return false;
-    }
-  }
-  // Now that we know the signature matches, we can perform type checks.
-  for (var i = 0; i < requiredCount; ++i) {
-    JS('', '#[#]._check(#[#])', required, i, actuals, i);
-  }
-  for (var i = 0; i < extras; ++i) {
-    JS('', '#[#]._check(#[#])', optionals, i, actuals, i + requiredCount);
-  }
-  if (names != null) {
-    for (var name in names) {
-      JS('', '#[#]._check(#[#])', named, name, namedActuals, name);
-    }
-  }
-  return true;
-}
-
-_toSymbolName(symbol) => JS('', '''(() => {
-        let str = $symbol.toString();
-        // Strip leading 'Symbol(' and trailing ')'
-        return str.substring(7, str.length-1);
-    })()''');
-
-_toDisplayName(name) => JS('', '''(() => {
-      // Names starting with _ are escaped names used to disambiguate Dart and
-      // JS names.
-      if ($name[0] === '_') {
-        // Inverse of
-        switch($name) {
-          case '_get':
-            return '[]';
-          case '_set':
-            return '[]=';
-          case '_negate':
-            return 'unary-';
-          case '_constructor':
-          case '_prototype':
-            return $name.substring(1);
-        }
-      }
-      return $name;
-  })()''');
-
-Symbol _dartSymbol(name) {
-  return (JS<bool>('!', 'typeof # === "symbol"', name))
-      ? JS('Symbol', '#(new #.new(#, #))', const_, PrivateSymbol,
-          _toSymbolName(name), name)
-      : JS('Symbol', '#(new #.new(#))', const_, internal.Symbol,
-          _toDisplayName(name));
-}
-
-Symbol _setterSymbol(name) {
-  return (JS<bool>('!', 'typeof # === "symbol"', name))
-      ? JS('Symbol', '#(new #.new(# + "=", #))', const_, PrivateSymbol,
-          _toSymbolName(name), name)
-      : JS('Symbol', '#(new #.new(# + "="))', const_, internal.Symbol,
-          _toDisplayName(name));
-}
-
-_checkAndCall(f, ftype, obj, typeArgs, args, named, displayName) =>
-    JS('', '''(() => {
-  $trackCall($obj);
-
-  let originalTarget = obj === void 0 ? f : obj;
-
-  function callNSM() {
-    return $noSuchMethod(originalTarget, new $InvocationImpl.new(
-        $displayName, $args, {
-          namedArguments: $named,
-          typeArguments: $typeArgs,
-          isMethod: true
-        }));
-  }
-  if (!($f instanceof Function)) {
-    // We're not a function (and hence not a method either)
-    // Grab the `call` method if it's not a function.
-    if ($f != null) {
-      // Getting the member succeeded, so update the originalTarget.
-      // (we're now trying `call()` on `f`, so we want to call its nSM rather
-      // than the original target's nSM).
-      originalTarget = f;
-      $f = ${bindCall(f, _canonicalMember(f, 'call'))};
-      $ftype = null;
-    }
-    if ($f == null) return callNSM();
-  }
-  // If f is a function, but not a method (no method type)
-  // then it should have been a function valued field, so
-  // get the type from the function.
-  if ($ftype == null) $ftype = $f[$_runtimeType];
-
-  if ($ftype == null) {
-    // TODO(leafp): Allow JS objects to go through?
-    if ($typeArgs != null) {
-      // TODO(jmesserly): is there a sensible way to handle these?
-      $throwTypeError('call to JS object `' + $obj +
-          '` with type arguments <' + $typeArgs + '> is not supported.');
-    }
-
-    if ($named != null) $args.push($named);
-    return $f.apply($obj, $args);
-  }
-
-  // TODO(vsm): Remove when we no longer need mirrors metadata.
-  // An array is used to encode annotations attached to the type.
-  if ($ftype instanceof Array) $ftype = $ftype[0];
-
-  // Apply type arguments
-  if ($ftype instanceof $GenericFunctionType) {
-    let formalCount = $ftype.formalCount;
-
-    if ($typeArgs == null) {
-      $typeArgs = $ftype.instantiateDefaultBounds();
-    } else if ($typeArgs.length != formalCount) {
-      return callNSM();
-    } else {
-      $ftype.checkBounds($typeArgs);
-    }
-    $ftype = $ftype.instantiate($typeArgs);
-  } else if ($typeArgs != null) {
-    return callNSM();
-  }
-
-  if ($_checkApply($ftype, $args, $named)) {
-    if ($typeArgs != null) $args = $typeArgs.concat($args);
-    if ($named != null) $args.push($named);
-    return $f.apply($obj, $args);
-  }
-  return callNSM();
-})()''');
-
-dcall(f, args, [@undefined named]) =>
-    _checkAndCall(f, null, JS('', 'void 0'), null, args, named, 'call');
-
-dgcall(f, typeArgs, args, [@undefined named]) =>
-    _checkAndCall(f, null, JS('', 'void 0'), typeArgs, args, named, 'call');
-
-/// Helper for REPL dynamic invocation variants that make a best effort to
-/// enable accessing private members across library boundaries.
-replNameLookup(object, field) => JS('', '''(() => {
-  let rawField = $field;
-  if (typeof(field) == 'symbol') {
-    // test if the specified field exists in which case it is safe to use it.
-    if ($field in $object) return $field;
-
-    // Symbol is from a different library. Make a best effort to
-    $field = $field.toString();
-    $field = $field.substring('Symbol('.length, field.length - 1);
-
-  } else if ($field.charAt(0) != '_') {
-    // Not a private member so default call path is safe.
-    return $field;
-  }
-
-  // If the exact field name is present, invoke callback with it.
-  if ($field in $object) return $field;
-
-  // TODO(jacobr): warn if there are multiple private members with the same
-  // name which could happen if super classes in different libraries have
-  // the same private member name.
-  let proto = $object;
-  while (proto !== null) {
-    // Private field (indicated with "_").
-    let symbols = Object.getOwnPropertySymbols(proto);
-    let target = 'Symbol(' + $field + ')';
-
-    for (let s = 0; s < symbols.length; s++) {
-      let sym = symbols[s];
-      if (target == sym.toString()) return sym;
-    }
-    proto = proto.__proto__;
-  }
-  // We didn't find a plausible alternate private symbol so just fall back
-  // to the regular field.
-  return rawField;
-})()''');
-
-// TODO(jmesserly): the debugger extension hardcodes a call to this private
-// function. Fix that.
-@Deprecated('use replNameLookup')
-_dhelperRepl(obj, field, Function(Object) callback) {
-  return callback(replNameLookup(obj, field));
-}
-
-/// Shared code for dsend, dindex, and dsetindex.
-callMethod(obj, name, typeArgs, args, named, displayName) {
-  if (JS('!', 'typeof # == "function" && # == "call"', obj, name)) {
-    return dgcall(obj, typeArgs, args, named);
-  }
-  var symbol = _canonicalMember(obj, name);
-  if (symbol == null) {
-    return noSuchMethod(obj, InvocationImpl(displayName, args, isMethod: true));
-  }
-  var f = obj != null ? JS('', '#[#]', obj, symbol) : null;
-  var type = getType(obj);
-  var ftype = getMethodType(type, symbol);
-  // No such method if dart object and ftype is missing.
-  return _checkAndCall(f, ftype, obj, typeArgs, args, named, displayName);
-}
-
-dsend(obj, method, args, [@undefined named]) =>
-    callMethod(obj, method, null, args, named, method);
-
-dgsend(obj, typeArgs, method, args, [@undefined named]) =>
-    callMethod(obj, method, typeArgs, args, named, method);
-
-dsendRepl(obj, method, args, [@undefined named]) =>
-    callMethod(obj, replNameLookup(obj, method), null, args, named, method);
-
-dgsendRepl(obj, typeArgs, method, args, [@undefined named]) =>
-    callMethod(obj, replNameLookup(obj, method), typeArgs, args, named, method);
-
-dindex(obj, index) => callMethod(obj, '_get', null, [index], null, '[]');
-
-dsetindex(obj, index, value) =>
-    callMethod(obj, '_set', null, [index, value], null, '[]=');
-
-final _ignoreSubtypeCache = JS('', 'new Map()');
-
-/// Whether [t1] <: [t2], or if [isImplicit] is set and we should ignore the
-/// cast failure from t1 to t2.
-///
-/// See [_isSubtypeOrLegacySubtype] and [ignoreWhitelistedErrors].
-@notNull
-bool _isSubtypeOrIgnorableCastFailure(
-    Object t1, Object t2, @notNull bool isImplicit) {
-  var result = _isSubtypeOrLegacySubtype(t1, t2);
-  return result == true ||
-      result == null &&
-          isImplicit &&
-          JS<bool>('!', 'dart.__ignoreWhitelistedErrors') &&
-          _ignoreTypeFailure(t1, t2);
-}
-
-@notNull
-bool _ignoreTypeFailure(Object t1, Object t2) {
-  var map = JS('', '#.get(#)', _ignoreSubtypeCache, t1);
-  if (map != null) {
-    bool result = JS('', '#.get(#)', map, t2);
-    if (JS('!', '# !== void 0', result)) return result;
-  } else {
-    map = JS('', 'new Map()');
-    JS('', '#.set(#, #)', _ignoreSubtypeCache, t1, map);
-  }
-
-  // TODO(vsm): Remove this hack ...
-  // This is primarily due to the lack of generic methods,
-  // but we need to triage all the types.
-  @notNull
-  bool result;
-  if (_isFutureOr(t2)) {
-    // Ignore if we would ignore either side of union.
-    var typeArg = getGenericArgs(t2)[0];
-    var typeFuture = JS('', '#(#)', getGenericClass(Future), typeArg);
-    result =
-        _ignoreTypeFailure(t1, typeFuture) || _ignoreTypeFailure(t1, typeArg);
-  } else {
-    result = t1 is FunctionType && t2 is FunctionType ||
-        isSubtypeOf(t2, unwrapType(Iterable)) &&
-            isSubtypeOf(t1, unwrapType(Iterable));
-    if (result) {
-      _warn('Ignoring cast fail from ${typeName(t1)} to ${typeName(t2)}');
-    }
-  }
-  JS('', '#.set(#, #)', map, t2, result);
-  return result;
-}
-
-@notNull
-@JSExportName('is')
-bool instanceOf(obj, type) {
-  if (obj == null) {
-    return identical(type, unwrapType(Null)) || _isTop(type);
-  }
-  return isSubtypeOf(getReifiedType(obj), type);
-}
-
-@JSExportName('as')
-cast(obj, type, @notNull bool isImplicit) {
-  if (obj == null) return obj;
-  var actual = getReifiedType(obj);
-  if (_isSubtypeOrIgnorableCastFailure(actual, type, isImplicit)) {
-    return obj;
-  }
-  return castError(obj, type, isImplicit);
-}
-
-bool test(bool obj) {
-  if (obj == null) _throwBooleanConversionError();
-  return obj;
-}
-
-bool dtest(obj) {
-  if (obj is! bool) booleanConversionFailed(obj);
-  return obj;
-}
-
-void _throwBooleanConversionError() => throw BooleanConversionAssertionError();
-
-void booleanConversionFailed(obj) {
-  var actual = typeName(getReifiedType(test(obj)));
-  throw TypeErrorImpl("type '$actual' is not a 'bool' in boolean expression");
-}
-
-asInt(obj) {
-  if (obj == null) return null;
-
-  if (JS('!', 'Math.floor(#) != #', obj, obj)) {
-    castError(obj, JS('', '#', int), false);
-  }
-  return obj;
-}
-
-/// Checks that `x` is not null or undefined.
-//
-// TODO(jmesserly): inline this, either by generating it as a function into
-// the module, or via some other pattern such as:
-//
-//     <expr> || nullErr()
-//     (t0 = <expr>) != null ? t0 : nullErr()
-@JSExportName('notNull')
-_notNull(x) {
-  if (x == null) throwNullValueError();
-  return x;
-}
-
-/// The global constant map table.
-final constantMaps = JS('', 'new Map()');
-
-// TODO(leafp): This table gets quite large in apps.
-// Keeping the paths is probably expensive.  It would probably
-// be more space efficient to just use a direct hash table with
-// an appropriately defined structural equality function.
-Object _lookupNonTerminal(Object map, Object key) {
-  var result = JS('', '#.get(#)', map, key);
-  if (result != null) return result;
-  JS('', '#.set(#, # = new Map())', map, key, result);
-  return result;
-}
-
-Map<K, V> constMap<K, V>(JSArray elements) {
-  var count = elements.length;
-  var map = _lookupNonTerminal(constantMaps, count);
-  for (var i = 0; i < count; i++) {
-    map = _lookupNonTerminal(map, JS('', '#[#]', elements, i));
-  }
-  map = _lookupNonTerminal(map, K);
-  var result = JS('', '#.get(#)', map, V);
-  if (result != null) return result;
-  result = ImmutableMap<K, V>.from(elements);
-  JS('', '#.set(#, #)', map, V, result);
-  return result;
-}
-
-final constantSets = JS('', 'new Map()');
-
-Set<E> constSet<E>(JSArray<E> elements) {
-  var count = elements.length;
-  var map = _lookupNonTerminal(constantSets, count);
-  for (var i = 0; i < count; i++) {
-    map = _lookupNonTerminal(map, JS('', '#[#]', elements, i));
-  }
-  var result = JS('', '#.get(#)', map, E);
-  if (result != null) return result;
-  result = ImmutableSet<E>.from(elements);
-  JS('', '#.set(#, #)', map, E, result);
-  return result;
-}
-
-bool dassert(value) {
-  if (JS('!', '# != null && #[#] instanceof #', value, value, _runtimeType,
-      AbstractFunctionType)) {
-    value = dcall(value, []);
-  }
-  return dtest(value);
-}
-
-final _value = JS('', 'Symbol("_value")');
-
-///
-/// Looks up a sequence of [keys] in [map], recursively, and
-/// returns the result. If the value is not found, [valueFn] will be called to
-/// add it. For example:
-///
-///     let map = new Map();
-///     putIfAbsent(map, [1, 2, 'hi ', 'there '], () => 'world');
-///
-/// ... will create a Map with a structure like:
-///
-///     { 1: { 2: { 'hi ': { 'there ': 'world' } } } }
-///
-multiKeyPutIfAbsent(map, keys, valueFn) => JS('', '''(() => {
-  for (let k of $keys) {
-    let value = $map.get(k);
-    if (!value) {
-      // TODO(jmesserly): most of these maps are very small (e.g. 1 item),
-      // so it may be worth optimizing for that.
-      $map.set(k, value = new Map());
-    }
-    $map = value;
-  }
-  if ($map.has($_value)) return $map.get($_value);
-  let value = $valueFn();
-  $map.set($_value, value);
-  return value;
-})()''');
-
-/// The global constant table.
-/// This maps the number of names in the object (n)
-/// to a path of length 2*n of maps indexed by the name and
-/// and value of the field.  The final map is
-/// indexed by runtime type, and contains the canonical
-/// version of the object.
-final constants = JS('', 'new Map()');
-
-///
-/// Canonicalize a constant object.
-///
-/// Preconditions:
-/// - `obj` is an objects or array, not a primitive.
-/// - nested values of the object are themselves already canonicalized.
-///
-@JSExportName('const')
-const_(obj) => JS('', '''(() => {  
-  let names = $getOwnNamesAndSymbols($obj);
-  let count = names.length;
-  // Index by count.  All of the paths through this map
-  // will have 2*count length.
-  let map = $_lookupNonTerminal($constants, count);
-  // TODO(jmesserly): there's no guarantee in JS that names/symbols are
-  // returned in the same order.
-  //
-  // We could probably get the same order if we're judicious about
-  // initializing fields in a consistent order across all const constructors.
-  // Alternatively we need a way to sort them to make consistent.
-  //
-  // Right now we use the (name,value) pairs in sequence, which prevents
-  // an object with incorrect field values being returned, but won't
-  // canonicalize correctly if key order is different.
-  //
-  // See issue https://github.com/dart-lang/sdk/issues/30876
-  for (let i = 0; i < count; i++) {
-    let name = names[i];
-    map = $_lookupNonTerminal(map, name);
-    map = $_lookupNonTerminal(map, $obj[name]);
-  }
-  // TODO(leafp): It may be the case that the reified type
-  // is always one of the keys already used above?
-  let type = $getReifiedType($obj);
-  let value = map.get(type);
-  if (value) return value;
-  map.set(type, $obj);
-  return $obj;
-})()''');
-
-/// The global constant list table.
-/// This maps the number of elements in the list (n)
-/// to a path of length n of maps indexed by the value
-/// of the field.  The final map is indexed by the element
-/// type and contains the canonical version of the list.
-final constantLists = JS('', 'new Map()');
-
-/// Canonicalize a constant list
-constList(elements, elementType) => JS('', '''(() => {
-  let count = $elements.length;
-  let map = $_lookupNonTerminal($constantLists, count);
-  for (let i = 0; i < count; i++) {
-    map = $_lookupNonTerminal(map, elements[i]);
-  }
-  let value = map.get($elementType);
-  if (value) return value;
-
-  ${getGenericClass(JSArray)}($elementType).unmodifiable($elements);
-  map.set($elementType, elements);
-  return elements;
-})()''');
-
-constFn(x) => JS('', '() => x');
-
-/// Gets the extension symbol given a member [name].
-///
-/// This is inlined by the compiler when used with a literal string.
-extensionSymbol(String name) => JS('', 'dartx[#]', name);
-
-// The following are helpers for Object methods when the receiver
-// may be null. These should only be generated by the compiler.
-bool equals(x, y) {
-  // We handle `y == null` inside our generated operator methods, to keep this
-  // function minimal.
-  // This pattern resulted from performance testing; it found that dispatching
-  // was the fastest solution, even for primitive types.
-  return JS('!', '# == null ? # == null : #[#](#)', x, y, x,
-      extensionSymbol('_equals'), y);
-}
-
-int hashCode(obj) {
-  return obj == null ? 0 : JS('!', '#[#]', obj, extensionSymbol('hashCode'));
-}
-
-@JSExportName('toString')
-String _toString(obj) {
-  if (obj == null) return "null";
-  if (obj is String) return obj;
-  return JS('!', '#[#]()', obj, extensionSymbol('toString'));
-}
-
-/// Converts to a non-null [String], equivalent to
-/// `dart.notNull(dart.toString(obj))`.
-///
-/// This is commonly used in string interpolation.
-@notNull
-String str(obj) {
-  if (obj == null) return "null";
-  if (obj is String) return obj;
-  return _notNull(JS('!', '#[#]()', obj, extensionSymbol('toString')));
-}
-
-// TODO(jmesserly): is the argument type verified statically?
-noSuchMethod(obj, Invocation invocation) {
-  if (obj == null) defaultNoSuchMethod(obj, invocation);
-  return JS('', '#[#](#)', obj, extensionSymbol('noSuchMethod'), invocation);
-}
-
-/// The default implementation of `noSuchMethod` to match `Object.noSuchMethod`.
-defaultNoSuchMethod(obj, Invocation i) {
-  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
-  throw NoSuchMethodError.withInvocation(obj, i);
-}
-
-runtimeType(obj) {
-  return obj == null ? Null : JS('', '#[dartx.runtimeType]', obj);
-}
-
-final identityHashCode_ = JS('', 'Symbol("_identityHashCode")');
-
-/// Adapts a Dart `get iterator` into a JS `[Symbol.iterator]`.
-// TODO(jmesserly): instead of an adaptor, we could compile Dart iterators
-// natively implementing the JS iterator protocol. This would allow us to
-// optimize them a bit.
-final JsIterator = JS('', '''
-  class JsIterator {
-    constructor(dartIterator) {
-      this.dartIterator = dartIterator;
-    }
-    next() {
-      let i = this.dartIterator;
-      let done = !i.moveNext();
-      return { done: done, value: done ? void 0 : i.current };
-    }
-  }
-''');
-
-_canonicalMember(obj, name) {
-  // Private names are symbols and are already canonical.
-  if (JS('!', 'typeof # === "symbol"', name)) return name;
-
-  if (obj != null && JS<bool>('!', '#[#] != null', obj, _extensionType)) {
-    return JS('', 'dartx.#', name);
-  }
-
-  // Check for certain names that we can't use in JS
-  if (JS('!', '# == "constructor" || # == "prototype"', name, name)) {
-    JS('', '# = "+" + #', name, name);
-  }
-  return name;
-}
-
-/// Emulates the implicit "loadLibrary" function provided by a deferred library.
-///
-/// Libraries are not actually deferred in DDC, so this just returns a future
-/// that completes immediately.
-Future loadLibrary() => Future.value();
-
-/// Defines lazy statics.
-void defineLazy(to, from) {
-  for (var name in getOwnNamesAndSymbols(from)) {
-    defineLazyField(to, name, getOwnPropertyDescriptor(from, name));
-  }
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart
deleted file mode 100644
index 5e784a4..0000000
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// This library defines the association between runtime objects and
-/// runtime types.
-part of dart._runtime;
-
-/// Runtime type information.  This module defines the mapping from
-/// runtime objects to their runtime type information.  See the types
-/// module for the definition of how type information is represented.
-///
-/// There are two kinds of objects that represent "types" at runtime. A
-/// "runtime type" contains all of the data needed to implement the runtime
-/// type checking inserted by the compiler. These objects fall into four
-/// categories:
-///
-///   - Things represented by javascript primitives, such as
-///     null, numbers, booleans, strings, and symbols.  For these
-///     we map directly from the javascript type (given by typeof)
-///     to the appropriate class type from core, which serves as their
-///     rtti.
-///
-///   - Functions, which are represented by javascript functions.
-///     Representations of Dart functions always have a
-///     _runtimeType property attached to them with the appropriate
-///     rtti.
-///
-///   - Objects (instances) which are represented by instances of
-///     javascript (ES6) classes.  Their types are given by their
-///     classes, and the rtti is accessed by projecting out their
-///     constructor field.
-///
-///   - Types objects, which are represented as described in the types
-///     module.  Types always have a _runtimeType property attached to
-///     them with the appropriate rtti.  The rtti for these is always
-///     core.Type.  TODO(leafp): consider the possibility that we can
-///     reliably recognize type objects and map directly to core.Type
-///     rather than attaching this property everywhere.
-///
-/// The other kind of object representing a "type" is the instances of the
-/// dart:core Type class. These are the user visible objects you get by calling
-/// "runtimeType" on an object or using a class literal expression. These are
-/// different from the above objects, and are created by calling `wrapType()`
-/// on a runtime type.
-
-/// Tag a closure with a type.
-///
-/// `dart.fn(closure, type)` marks [closure] with the provided runtime [type].
-fn(closure, type) {
-  JS('', '#[#] = #', closure, _runtimeType, type);
-  return closure;
-}
-
-/// Tag a closure with a type that's computed lazily.
-///
-/// `dart.fn(closure, type)` marks [closure] with a getter that uses
-/// [computeType] to return the runtime type.
-///
-/// The getter/setter replaces the property with a value property, so the
-/// resulting function is compatible with [fn] and the type can be set again
-/// safely.
-lazyFn(closure, Object Function() computeType) {
-  defineAccessor(closure, _runtimeType,
-      get: () => defineValue(closure, _runtimeType, computeType()),
-      set: (value) => defineValue(closure, _runtimeType, value),
-      configurable: true);
-  return closure;
-}
-
-// TODO(vsm): How should we encode the runtime type?
-final _runtimeType = JS('', 'Symbol("_runtimeType")');
-
-final _moduleName = JS('', 'Symbol("_moduleName")');
-
-getFunctionType(obj) {
-  // TODO(vsm): Encode this properly on the function for Dart-generated code.
-  var args = JS<List>('!', 'Array(#.length).fill(#)', obj, dynamic);
-  return fnType(bottom, args, JS('', 'void 0'));
-}
-
-/// Returns the runtime representation of the type of obj.
-///
-/// The resulting object is used internally for runtime type checking. This is
-/// different from the user-visible Type object returned by calling
-/// `runtimeType` on some Dart object.
-getReifiedType(obj) {
-  switch (JS<String>('!', 'typeof #', obj)) {
-    case "object":
-      if (obj == null) return JS('', '#', Null);
-      if (JS('!', '# instanceof #', obj, Object)) {
-        return JS('', '#.constructor', obj);
-      }
-      var result = JS('', '#[#]', obj, _extensionType);
-      if (result == null) return JS('', '#', jsobject);
-      return result;
-    case "function":
-      // All Dart functions and callable classes must set _runtimeType
-      var result = JS('', '#[#]', obj, _runtimeType);
-      if (result != null) return result;
-      return JS('', '#', jsobject);
-    case "undefined":
-      return JS('', '#', Null);
-    case "number":
-      return JS('', 'Math.floor(#) == # ? # : #', obj, obj, int, double);
-    case "boolean":
-      return JS('', '#', bool);
-    case "string":
-      return JS('', '#', String);
-    case "symbol":
-    default:
-      return JS('', '#', jsobject);
-  }
-}
-
-/// Return the module name for a raw library object.
-String getModuleName(Object module) => JS('', '#[#]', module, _moduleName);
-
-final _loadedModules = JS('', 'new Map()');
-final _loadedSourceMaps = JS('', 'new Map()');
-
-List<String> getModuleNames() {
-  return JSArray<String>.of(JS('', 'Array.from(#.keys())', _loadedModules));
-}
-
-String getSourceMap(String moduleName) {
-  return JS('!', '#.get(#)', _loadedSourceMaps, moduleName);
-}
-
-/// Return all library objects in the specified module.
-getModuleLibraries(String name) {
-  var module = JS('', '#.get(#)', _loadedModules, name);
-  if (module == null) return null;
-  JS('', '#[#] = #', module, _moduleName, name);
-  return module;
-}
-
-/// Track all libraries
-void trackLibraries(String moduleName, Object libraries, String sourceMap) {
-  JS('', '#.set(#, #)', _loadedSourceMaps, moduleName, sourceMap);
-  JS('', '#.set(#, #)', _loadedModules, moduleName, libraries);
-}
-
-List<String> _libraries;
-
-/// Returns a JSArray of library uris (e.g,
-/// ['dart:core', 'dart:_internal', ..., 'package:foo/bar.dart', ... 'main.dart'])
-/// loaded in this application.
-List<String> getLibraries() {
-  if (_libraries == null) {
-    _libraries = [];
-    var modules = getModuleNames();
-    for (var name in modules) {
-      var module = getModuleLibraries(name);
-      List props = getOwnPropertyNames(module);
-      _libraries.addAll(props.whereType());
-    }
-  }
-  return _libraries;
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart
deleted file mode 100644
index e943f3e..0000000
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart
+++ /dev/null
@@ -1,217 +0,0 @@
-// 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.
-
-@ReifyFunctionTypes(false)
-library dart._runtime;
-
-import 'dart:async';
-import 'dart:collection';
-
-import 'dart:_debugger' show stackTraceMapper, trackCall;
-import 'dart:_foreign_helper' show JS, JSExportName, rest, spread;
-import 'dart:_interceptors' show JSArray, jsNull, JSFunction, NativeError;
-import 'dart:_internal' as internal show Symbol;
-import 'dart:_js_helper'
-    show
-        AssertionErrorImpl,
-        BooleanConversionAssertionError,
-        CastErrorImpl,
-        DartIterator,
-        TypeErrorImpl,
-        JsLinkedHashMap,
-        ImmutableMap,
-        PrivateSymbol,
-        ReifyFunctionTypes,
-        NoReifyGeneric,
-        notNull,
-        undefined;
-
-export 'dart:_debugger' show getDynamicStats, clearDynamicStats, trackCall;
-
-part 'utils.dart';
-part 'classes.dart';
-part 'rtti.dart';
-part 'types.dart';
-part 'errors.dart';
-part 'operations.dart';
-
-// TODO(vsm): Move polyfill code to dart:html.
-// Note, native extensions are registered onto types in dart.global.
-// This polyfill needs to run before the corresponding dart:html code is run.
-final _polyfilled = JS('', 'Symbol("_polyfilled")');
-
-bool polyfill(window) => JS('', '''(() => {
-  if ($window[$_polyfilled]) return false;
-  $window[$_polyfilled] = true;
-
-  if (typeof $window.NodeList !== "undefined") {
-    // TODO(vsm): Do we still need these?
-    $window.NodeList.prototype.get = function(i) { return this[i]; };
-    $window.NamedNodeMap.prototype.get = function(i) { return this[i]; };
-    $window.DOMTokenList.prototype.get = function(i) { return this[i]; };
-    $window.HTMLCollection.prototype.get = function(i) { return this[i]; };
-
-    // Expose constructors for DOM types dart:html needs to assume are
-    // available on window.
-    if (typeof $window.PannerNode == "undefined") {
-      let audioContext;
-      if (typeof $window.AudioContext == "undefined" &&
-          (typeof $window.webkitAudioContext != "undefined")) {
-        audioContext = new $window.webkitAudioContext();
-      } else {
-        audioContext = new $window.AudioContext();
-        $window.StereoPannerNode =
-            audioContext.createStereoPanner().constructor;
-      }
-      $window.PannerNode = audioContext.createPanner().constructor;
-    }
-    if (typeof $window.AudioSourceNode == "undefined") {
-      $window.AudioSourceNode = MediaElementAudioSourceNode.__proto__;
-    }
-    if (typeof $window.FontFaceSet == "undefined") {
-      // CSS Font Loading is not supported on Edge.
-      if (typeof $window.document.fonts != "undefined") {
-        $window.FontFaceSet = $window.document.fonts.__proto__.constructor;
-      }
-    }
-    if (typeof $window.MemoryInfo == "undefined") {
-      if (typeof $window.performance.memory != "undefined") {
-        $window.MemoryInfo = $window.performance.memory.constructor;
-      }
-    }
-    if (typeof $window.Geolocation == "undefined") {
-      $window.Geolocation == $window.navigator.geolocation.constructor;
-    }
-    if (typeof $window.Animation == "undefined") {
-      let d = $window.document.createElement('div');
-      if (typeof d.animate != "undefined") {
-        $window.Animation = d.animate(d).constructor;
-      }
-    }
-    if (typeof $window.SourceBufferList == "undefined") {
-      $window.SourceBufferList =
-        new $window.MediaSource().sourceBuffers.constructor;
-    }
-    if (typeof $window.SpeechRecognition == "undefined") {
-      $window.SpeechRecognition = $window.webkitSpeechRecognition;
-      $window.SpeechRecognitionError = $window.webkitSpeechRecognitionError;
-      $window.SpeechRecognitionEvent = $window.webkitSpeechRecognitionEvent;
-    }
-  }
-  return true;
-})()''');
-
-@JSExportName('global')
-final global_ = JS('', '''
-  function () {
-    // Find global object.
-    var globalState = (typeof window != "undefined") ? window
-      : (typeof global != "undefined") ? global
-      : (typeof self != "undefined") ? self : null;
-    if (!globalState) {
-      // Some platforms (e.g., d8) do not define any of the above.  The
-      // following is a non-CSP safe way to access the global object:
-      globalState = new Function('return this;')();
-    }
-
-    $polyfill(globalState);
-
-    // By default, stack traces cutoff at 10.  Set the limit to Infinity for
-    // better debugging.
-    if (globalState.Error) {
-      globalState.Error.stackTraceLimit = Infinity;
-    }
-
-    // These settings must be configured before the application starts so that
-    // user code runs with the correct configuration.
-    let settings = 'ddcSettings' in globalState ? globalState.ddcSettings : {};
-    $trapRuntimeErrors(
-        'trapRuntimeErrors' in settings ? settings.trapRuntimeErrors : false);
-    $ignoreWhitelistedErrors(
-        'ignoreWhitelistedErrors' in settings ?
-            settings.ignoreWhitelistedErrors : false);
-
-    $ignoreAllErrors(
-        'ignoreAllErrors' in settings ? settings.ignoreAllErrors : false);
-
-    $trackProfile(
-        'trackProfile' in settings ? settings.trackProfile : false);
-
-    return globalState;
-  }()
-''');
-
-void trackProfile(bool flag) {
-  JS('', 'dart.__trackProfile = #', flag);
-}
-
-final JsSymbol = JS('', 'Symbol');
-
-/// The prototype used for all Dart libraries.
-///
-/// This makes it easy to identify Dart library objects, and also improves
-/// performance (JS engines such as V8 tend to assume `Object.create(null)` is
-/// used for a Map, so they don't optimize it as they normally would for
-/// class-like objects).
-///
-/// The `dart.library` field is set by the compiler during SDK bootstrapping
-/// (because it is needed for dart:_runtime itself), so we don't need to
-/// initialize it here. The name `dart.library` is used because it reads nicely,
-/// for example:
-///
-///     const my_library = Object.create(dart.library);
-///
-Object libraryPrototype = JS('', 'dart.library');
-
-// TODO(vsm): Remove once this flag we've removed the ability to
-// whitelist / fallback on the old behavior.
-bool startAsyncSynchronously = true;
-void setStartAsyncSynchronously([bool value = true]) {
-  startAsyncSynchronously = value;
-}
-
-/// A list of all JS Maps used for caching results, such as by [isSubtypeOf] and
-/// [generic].
-///
-/// This is used by [hotRestart] to ensure we don't leak types from previous
-/// libraries.
-@notNull
-final List<Object> _cacheMaps = JS('!', '[]');
-
-/// A list of functions to reset static fields back to their uninitialized
-/// state.
-///
-/// This is populated by [defineLazyField], and only contains the list of fields
-/// that have actually been initialized.
-@notNull
-final List<void Function()> _resetFields = JS('', '[]');
-
-/// Clears out runtime state in `dartdevc` so we can hot-restart.
-///
-/// This should be called when the user requests a hot-restart, when the UI is
-/// handling that user action.
-void hotRestart() {
-  // TODO(jmesserly): we need to prevent all pending callbacks from firing.
-  for (var f in _resetFields) f();
-  _resetFields.clear();
-  for (var m in _cacheMaps) JS('', '#.clear()', m);
-  _cacheMaps.clear();
-  JS('', '#.clear()', constantMaps);
-  JS('', '#.clear()', _ignoreSubtypeCache);
-}
-
-/// Marks enqueuing an async operation.
-///
-/// This will be called by library code when enqueuing an async operation
-/// controlled by the JavaScript event handler.
-///
-/// It will also call [removeAsyncCallback] when Dart callback is about to be
-/// executed (note this is called *before* the callback executes, so more
-/// async operations could be added from that).
-void Function() addAsyncCallback = JS('', 'function() {}');
-
-/// Marks leaving a javascript async operation.
-///
-/// See [addAsyncCallback].
-void Function() removeAsyncCallback = JS('', 'function() {}');
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
deleted file mode 100644
index a5d6dd0..0000000
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
+++ /dev/null
@@ -1,1448 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// This library defines the representation of runtime types.
-part of dart._runtime;
-
-final metadata = JS('', 'Symbol("metadata")');
-
-/// Types in dart are represented internally at runtime as follows.
-///
-///   - Normal nominal types, produced from classes, are represented
-///     at runtime by the JS class of which they are an instance.
-///     If the type is the result of instantiating a generic class,
-///     then the "classes" module manages the association between the
-///     instantiated class and the original class declaration
-///     and the type arguments with which it was instantiated.  This
-///     association can be queried via the "classes" module".
-///
-///   - All other types are represented as instances of class [DartType],
-///     defined in this module.
-///     - Dynamic, Void, and Bottom are singleton instances of sentinal
-///       classes.
-///     - Function types are instances of subclasses of AbstractFunctionType.
-///
-/// Function types are represented in one of two ways:
-///   - As an instance of FunctionType.  These are eagerly computed.
-///   - As an instance of TypeDef.  The TypeDef representation lazily
-///     computes an instance of FunctionType, and delegates to that instance.
-///
-/// These above "runtime types" are what is used for implementing DDC's
-/// internal type checks. These objects are distinct from the objects exposed
-/// to user code by class literals and calling `Object.runtimeType`. In DDC,
-/// the latter are represented by instances of WrappedType which contain a
-/// real runtime type internally. This ensures that the returned object only
-/// exposes the API that Type defines:
-///
-///     get String name;
-///     String toString();
-///
-/// These "runtime types" have methods for performing type checks. The methods
-/// have the following JavaScript names which are designed to not collide with
-/// static methods, which are also placed 'on' the class constructor function.
-///
-///     T.is(o): Implements 'o is T'.
-///     T.as(o): Implements 'o as T'.
-///     T._check(o): Implements the type assertion of 'T x = o;'
-///
-/// By convention, we used named JavaScript functions for these methods with the
-/// name 'is_X', 'as_X' and 'check_X' for various X to indicate the type or the
-/// implementation strategy for the test (e.g 'is_String', 'is_G' for generic
-/// types, etc.)
-// TODO(jmesserly): we shouldn't implement Type here. It should be moved down
-// to AbstractFunctionType.
-class DartType implements Type {
-  String get name => this.toString();
-
-  // TODO(jmesserly): these should never be reached, can be make them abstract?
-  @notNull
-  @JSExportName('is')
-  bool is_T(object) => instanceOf(object, this);
-
-  @JSExportName('as')
-  as_T(object) => cast(object, this, false);
-
-  @JSExportName('_check')
-  check_T(object) => cast(object, this, true);
-}
-
-class DynamicType extends DartType {
-  toString() => 'dynamic';
-
-  @JSExportName('is')
-  bool is_T(object) => true;
-
-  @JSExportName('as')
-  as_T(object) => object;
-
-  @JSExportName('_check')
-  check_T(object) => object;
-}
-
-@notNull
-bool _isJsObject(obj) => JS('!', '# === #', getReifiedType(obj), jsobject);
-
-/// The Dart type that represents a JavaScript class(/constructor) type.
-///
-/// The JavaScript type may not exist, either because it's not loaded yet, or
-/// because it's not available (such as with mocks). To handle this gracefully,
-/// we disable type checks for in these cases, and allow any JS object to work
-/// as if it were an instance of this JS type.
-class LazyJSType extends DartType {
-  Function() _getRawJSTypeFn;
-  @notNull
-  final String _dartName;
-  Object _rawJSType;
-
-  LazyJSType(this._getRawJSTypeFn, this._dartName);
-
-  toString() {
-    var raw = _getRawJSType();
-    return raw != null ? typeName(raw) : "JSObject<$_dartName>";
-  }
-
-  Object _getRawJSType() {
-    var raw = _rawJSType;
-    if (raw != null) return raw;
-
-    // Try to evaluate the JS type. If this fails for any reason, we'll try
-    // again next time.
-    // TODO(jmesserly): is it worth trying again? It may create unnecessary
-    // overhead, especially if exceptions are being thrown. Also it means the
-    // behavior of a given type check can change later on.
-    try {
-      raw = _getRawJSTypeFn();
-    } catch (e) {}
-
-    if (raw == null) {
-      _warn('Cannot find native JavaScript type ($_dartName) for type check');
-    } else {
-      _rawJSType = raw;
-      _getRawJSTypeFn = null; // Free the function that computes the JS type.
-    }
-    return raw;
-  }
-
-  Object rawJSTypeForCheck() => _getRawJSType() ?? jsobject;
-
-  @notNull
-  bool isRawJSType(obj) {
-    var raw = _getRawJSType();
-    if (raw != null) return JS('!', '# instanceof #', obj, raw);
-    return _isJsObject(obj);
-  }
-
-  @notNull
-  @JSExportName('is')
-  bool is_T(obj) => isRawJSType(obj) || instanceOf(obj, this);
-
-  @JSExportName('as')
-  as_T(obj) => obj == null || is_T(obj) ? obj : castError(obj, this, false);
-
-  @JSExportName('_check')
-  check_T(obj) => obj == null || is_T(obj) ? obj : castError(obj, this, true);
-}
-
-/// An anonymous JS type
-///
-/// For the purposes of subtype checks, these match any JS type.
-class AnonymousJSType extends DartType {
-  final String _dartName;
-  AnonymousJSType(this._dartName);
-  toString() => _dartName;
-
-  @JSExportName('is')
-  bool is_T(obj) => _isJsObject(obj) || instanceOf(obj, this);
-
-  @JSExportName('as')
-  as_T(obj) => obj == null || _isJsObject(obj) ? obj : cast(obj, this, false);
-
-  @JSExportName('_check')
-  check_T(obj) => obj == null || _isJsObject(obj) ? obj : cast(obj, this, true);
-}
-
-void _warn(arg) {
-  JS('void', 'console.warn(#)', arg);
-}
-
-var _lazyJSTypes = JS('', 'new Map()');
-var _anonymousJSTypes = JS('', 'new Map()');
-
-lazyJSType(Function() getJSTypeCallback, String name) {
-  var ret = JS('', '#.get(#)', _lazyJSTypes, name);
-  if (ret == null) {
-    ret = LazyJSType(getJSTypeCallback, name);
-    JS('', '#.set(#, #)', _lazyJSTypes, name, ret);
-  }
-  return ret;
-}
-
-anonymousJSType(String name) {
-  var ret = JS('', '#.get(#)', _anonymousJSTypes, name);
-  if (ret == null) {
-    ret = AnonymousJSType(name);
-    JS('', '#.set(#, #)', _anonymousJSTypes, name, ret);
-  }
-  return ret;
-}
-
-@JSExportName('dynamic')
-final _dynamic = DynamicType();
-
-class VoidType extends DartType {
-  toString() => 'void';
-}
-
-@JSExportName('void')
-final void_ = VoidType();
-
-class BottomType extends DartType {
-  toString() => 'bottom';
-}
-
-final bottom = BottomType();
-
-class JSObjectType extends DartType {
-  toString() => 'NativeJavaScriptObject';
-}
-
-final jsobject = JSObjectType();
-
-/// Dev Compiler's implementation of Type, wrapping its internal [_type].
-class _Type extends Type {
-  /// The internal type representation, either a [DartType] or class constructor
-  /// function.
-  // TODO(jmesserly): introduce InterfaceType so we don't have to special case
-  // classes
-  @notNull
-  final Object _type;
-
-  _Type(this._type);
-
-  toString() => typeName(_type);
-
-  Type get runtimeType => Type;
-}
-
-/// Given an internal runtime type object, wraps it in a `_Type` object
-/// that implements the dart:core Type interface.
-Type wrapType(type) {
-  // If we've already wrapped this type once, use the previous wrapper. This
-  // way, multiple references to the same type return an identical Type.
-  if (JS('!', '#.hasOwnProperty(#)', type, _typeObject)) {
-    return JS('', '#[#]', type, _typeObject);
-  }
-  var result = _Type(type);
-  JS('', '#[#] = #', type, _typeObject, result);
-  return result;
-}
-
-/// The symbol used to store the cached `Type` object associated with a class.
-final _typeObject = JS('', 'Symbol("typeObject")');
-
-/// Given a WrappedType, return the internal runtime type object.
-Object unwrapType(Type obj) => JS<_Type>('', '#', obj)._type;
-
-// Marker class for generic functions, typedefs, and non-generic functions.
-abstract class AbstractFunctionType extends DartType {}
-
-/// Memo table for named argument groups. A named argument packet
-/// {name1 : type1, ..., namen : typen} corresponds to the path
-/// n, name1, type1, ...., namen, typen.  The element of the map
-/// reached via this path (if any) is the canonical representative
-/// for this packet.
-final _fnTypeNamedArgMap = JS('', 'new Map()');
-
-/// Memo table for positional argument groups. A positional argument
-/// packet [type1, ..., typen] (required or optional) corresponds to
-/// the path n, type1, ...., typen.  The element reached via
-/// this path (if any) is the canonical representative for this
-/// packet. Note that required and optional parameters packages
-/// may have the same canonical representation.
-final _fnTypeArrayArgMap = JS('', 'new Map()');
-
-/// Memo table for function types. The index path consists of the
-/// path length - 1, the returnType, the canonical positional argument
-/// packet, and if present, the canonical optional or named argument
-/// packet.  A level of indirection could be avoided here if desired.
-final _fnTypeTypeMap = JS('', 'new Map()');
-
-/// Memo table for small function types with no optional or named
-/// arguments and less than a fixed n (currently 3) number of
-/// required arguments.  Indexing into this table by the number
-/// of required arguments yields a map which is indexed by the
-/// argument types themselves.  The element reached via this
-/// index path (if present) is the canonical function type.
-final List _fnTypeSmallMap = JS('', '[new Map(), new Map(), new Map()]');
-
-@NoReifyGeneric()
-T _memoizeArray<T>(map, arr, T create()) => JS('', '''(() => {
-  let len = $arr.length;
-  $map = $_lookupNonTerminal($map, len);
-  for (var i = 0; i < len-1; ++i) {
-    $map = $_lookupNonTerminal($map, $arr[i]);
-  }
-  let result = $map.get($arr[len-1]);
-  if (result !== void 0) return result;
-  $map.set($arr[len-1], result = $create());
-  return result;
-})()''');
-
-List _canonicalizeArray(List array, map) =>
-    _memoizeArray(map, array, () => array);
-
-// TODO(leafp): This only canonicalizes of the names are
-// emitted in a consistent order.
-_canonicalizeNamed(named, map) => JS('', '''(() => {
-  let key = [];
-  let names = $getOwnPropertyNames($named);
-  for (var i = 0; i < names.length; ++i) {
-    let name = names[i];
-    let type = $named[name];
-    key.push(name);
-    key.push(type);
-  }
-  return $_memoizeArray($map, key, () => $named);
-})()''');
-
-// TODO(leafp): This handles some low hanging fruit, but
-// really we should make all of this faster, and also
-// handle more cases here.
-FunctionType _createSmall(returnType, List required) => JS('', '''(() => {
-  let count = $required.length;
-  let map = $_fnTypeSmallMap[count];
-  for (var i = 0; i < count; ++i) {
-    map = $_lookupNonTerminal(map, $required[i]);
- }
- let result = map.get($returnType);
- if (result !== void 0) return result;
- result = ${new FunctionType(returnType, required, [], JS('', '{}'))};
- map.set($returnType, result);
- return result;
-})()''');
-
-class FunctionType extends AbstractFunctionType {
-  final returnType;
-  List args;
-  List optionals;
-  final named;
-  // TODO(vsm): This is just parameter metadata for now.
-  List metadata = [];
-  String _stringValue;
-
-  /**
-   * Construct a function type.
-   *
-   * We eagerly normalize the argument types to avoid having to deal with
-   * this logic in multiple places.
-   *
-   * This code does best effort canonicalization.  It does not guarantee
-   * that all instances will share.
-   *
-   */
-  static FunctionType create(returnType, List args, extra) {
-    // Note that if extra is ever passed as an empty array
-    // or an empty map, we can end up with semantically
-    // identical function types that don't canonicalize
-    // to the same object since we won't fall into this
-    // fast path.
-    if (extra == null && JS<bool>('!', '#.length < 3', args)) {
-      return _createSmall(returnType, args);
-    }
-    args = _canonicalizeArray(args, _fnTypeArrayArgMap);
-    var keys;
-    FunctionType Function() create;
-    if (extra == null) {
-      keys = [returnType, args];
-      create = () => FunctionType(returnType, args, [], JS('', '{}'));
-    } else if (JS('!', '# instanceof Array', extra)) {
-      var optionals =
-          _canonicalizeArray(JS('', '#', extra), _fnTypeArrayArgMap);
-      keys = [returnType, args, optionals];
-      create = () => FunctionType(returnType, args, optionals, JS('', '{}'));
-    } else {
-      var named = _canonicalizeNamed(extra, _fnTypeNamedArgMap);
-      keys = [returnType, args, named];
-      create = () => FunctionType(returnType, args, [], named);
-    }
-    return _memoizeArray(_fnTypeTypeMap, keys, create);
-  }
-
-  List _process(List array) {
-    var result = [];
-    for (var i = 0; JS<bool>('!', '# < #.length', i, array); ++i) {
-      var arg = JS('', '#[#]', array, i);
-      if (JS('!', '# instanceof Array', arg)) {
-        JS('', '#.push(#.slice(1))', metadata, arg);
-        JS('', '#.push(#[0])', result, arg);
-      } else {
-        JS('', '#.push([])', metadata);
-        JS('', '#.push(#)', result, arg);
-      }
-    }
-    return result;
-  }
-
-  FunctionType(this.returnType, this.args, this.optionals, this.named) {
-    this.args = _process(this.args);
-    this.optionals = _process(this.optionals);
-    // TODO(vsm): Add named arguments.
-  }
-
-  toString() => name;
-
-  int get requiredParameterCount => args.length;
-  int get positionalParameterCount => args.length + optionals.length;
-
-  getPositionalParameter(int i) {
-    int n = args.length;
-    return i < n ? args[i] : optionals[i + n];
-  }
-
-  Map<String, Object> getNamedParameters() {
-    var result = <String, Object>{};
-    var names = getOwnPropertyNames(named);
-    JS('', '#.sort()', names);
-    for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
-      String name = JS('!', '#[#]', names, i);
-      result[name] = JS('', '#[#]', named, name);
-    }
-    return result;
-  }
-
-  get name {
-    if (_stringValue != null) return _stringValue;
-
-    var buffer = '(';
-    for (var i = 0; JS<bool>('!', '# < #.length', i, args); ++i) {
-      if (i > 0) {
-        buffer += ', ';
-      }
-      buffer += typeName(JS('', '#[#]', args, i));
-    }
-    if (JS('!', '#.length > 0', optionals)) {
-      if (JS('!', '#.length > 0', args)) buffer += ', ';
-      buffer += '[';
-      for (var i = 0; JS<bool>('!', '# < #.length', i, optionals); ++i) {
-        if (i > 0) {
-          buffer += ', ';
-        }
-        buffer += typeName(JS('', '#[#]', optionals, i));
-      }
-      buffer += ']';
-    } else if (JS('!', 'Object.keys(#).length > 0', named)) {
-      if (JS('!', '#.length > 0', args)) buffer += ', ';
-      buffer += '{';
-      var names = getOwnPropertyNames(named);
-      JS('', '#.sort()', names);
-      for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
-        if (i > 0) {
-          buffer += ', ';
-        }
-        var typeNameString = typeName(JS('', '#[#[#]]', named, names, i));
-        buffer += '$typeNameString ${JS('', '#[#]', names, i)}';
-      }
-      buffer += '}';
-    }
-
-    var returnTypeName = typeName(returnType);
-    buffer += ') => $returnTypeName';
-    _stringValue = buffer;
-    return buffer;
-  }
-
-  @JSExportName('is')
-  bool is_T(obj) {
-    if (JS('!', 'typeof # == "function"', obj)) {
-      var actual = JS('', '#[#]', obj, _runtimeType);
-      // If there's no actual type, it's a JS function.
-      // Allow them to subtype all Dart function types.
-      return actual == null || isSubtypeOf(actual, this);
-    }
-    return false;
-  }
-
-  @JSExportName('as')
-  as_T(obj, [@notNull bool isImplicit = false]) {
-    if (obj == null) return obj;
-    if (JS('!', 'typeof # == "function"', obj)) {
-      var actual = JS('', '#[#]', obj, _runtimeType);
-      // If there's no actual type, it's a JS function.
-      // Allow them to subtype all Dart function types.
-      if (actual == null ||
-          _isSubtypeOrIgnorableCastFailure(actual, this, isImplicit)) {
-        return obj;
-      }
-    }
-    return castError(obj, this, isImplicit);
-  }
-
-  @JSExportName('_check')
-  check_T(obj) => as_T(obj, true);
-}
-
-/// A type variable, used by [GenericFunctionType] to represent a type formal.
-class TypeVariable extends DartType {
-  final String name;
-
-  TypeVariable(this.name);
-
-  toString() => name;
-}
-
-class GenericFunctionType extends AbstractFunctionType {
-  final _instantiateTypeParts;
-  final int formalCount;
-  final _instantiateTypeBounds;
-  List<TypeVariable> _typeFormals;
-
-  GenericFunctionType(instantiateTypeParts, this._instantiateTypeBounds)
-      : _instantiateTypeParts = instantiateTypeParts,
-        formalCount = JS('!', '#.length', instantiateTypeParts);
-
-  List<TypeVariable> get typeFormals {
-    if (_typeFormals != null) return _typeFormals;
-    return _typeFormals = _typeFormalsFromFunction(_instantiateTypeParts);
-  }
-
-  /// Checks that [typeArgs] satisfies the upper bounds of the [typeFormals],
-  /// and throws a [TypeError] if they do not.
-  void checkBounds(List typeArgs) {
-    // If we don't have explicit type parameter bounds, the bounds default to
-    // a top type, so there's nothing to check here.
-    if (_instantiateTypeBounds == null) return;
-
-    var bounds = instantiateTypeBounds(typeArgs);
-    var typeFormals = this.typeFormals;
-    for (var i = 0; i < typeArgs.length; i++) {
-      checkTypeBound(typeArgs[i], bounds[i], typeFormals[i].name);
-    }
-  }
-
-  FunctionType instantiate(typeArgs) {
-    var parts = JS('', '#.apply(null, #)', _instantiateTypeParts, typeArgs);
-    return FunctionType.create(
-        JS('', '#[0]', parts), JS('', '#[1]', parts), JS('', '#[2]', parts));
-  }
-
-  List instantiateTypeBounds(List typeArgs) {
-    var boundsFn = _instantiateTypeBounds;
-    if (boundsFn == null) {
-      // The Dart 1 spec says omitted type parameters have an upper bound of
-      // Object. However Dart 2 uses `dynamic` for the purpose of instantiate to
-      // bounds, so we use that here.
-      return List.filled(formalCount, _dynamic);
-    }
-    // Bounds can be recursive or depend on other type parameters, so we need to
-    // apply type arguments and return the resulting bounds.
-    return JS('List', '#.apply(null, #)', boundsFn, typeArgs);
-  }
-
-  toString() {
-    String s = "<";
-    var typeFormals = this.typeFormals;
-    var typeBounds = instantiateTypeBounds(typeFormals);
-    for (int i = 0, n = typeFormals.length; i < n; i++) {
-      if (i != 0) s += ", ";
-      s += JS<String>('!', '#[#].name', typeFormals, i);
-      var bound = typeBounds[i];
-      if (JS('!', '# !== # && # !== #', bound, dynamic, bound, Object)) {
-        s += " extends $bound";
-      }
-    }
-    s += ">" + instantiate(typeFormals).toString();
-    return s;
-  }
-
-  /// Given a [DartType] [type], if [type] is an uninstantiated
-  /// parameterized type then instantiate the parameters to their
-  /// bounds and return those type arguments.
-  ///
-  /// See the issue for the algorithm description:
-  /// <https://github.com/dart-lang/sdk/issues/27526#issuecomment-260021397>
-  List instantiateDefaultBounds() {
-    var typeFormals = this.typeFormals;
-
-    // All type formals
-    var all = HashMap<Object, int>.identity();
-    // ground types, by index.
-    //
-    // For each index, this will be a ground type for the corresponding type
-    // formal if known, or it will be the original TypeVariable if we are still
-    // solving for it. This array is passed to `instantiateToBounds` as we are
-    // progressively solving for type variables.
-    var defaults = List<Object>(typeFormals.length);
-    // not ground
-    var partials = Map<TypeVariable, Object>.identity();
-
-    var typeBounds = this.instantiateTypeBounds(typeFormals);
-    for (var i = 0; i < typeFormals.length; i++) {
-      var typeFormal = typeFormals[i];
-      var bound = typeBounds[i];
-      all[typeFormal] = i;
-      if (identical(bound, _dynamic)) {
-        defaults[i] = bound;
-      } else {
-        defaults[i] = typeFormal;
-        partials[typeFormal] = bound;
-      }
-    }
-
-    bool hasFreeFormal(Object t) {
-      if (partials.containsKey(t)) return true;
-
-      // Generic classes and typedefs.
-      var typeArgs = getGenericArgs(t);
-      if (typeArgs != null) return typeArgs.any(hasFreeFormal);
-
-      if (t is GenericFunctionType) {
-        return hasFreeFormal(t.instantiate(t.typeFormals));
-      }
-
-      if (t is FunctionType) {
-        return hasFreeFormal(t.returnType) || t.args.any(hasFreeFormal);
-      }
-
-      return false;
-    }
-
-    var hasProgress = true;
-    while (hasProgress) {
-      hasProgress = false;
-      for (var typeFormal in partials.keys) {
-        var partialBound = partials[typeFormal];
-        if (!hasFreeFormal(partialBound)) {
-          int index = all[typeFormal];
-          defaults[index] = instantiateTypeBounds(defaults)[index];
-          partials.remove(typeFormal);
-          hasProgress = true;
-          break;
-        }
-      }
-    }
-
-    // If we stopped making progress, and not all types are ground,
-    // then the whole type is malbounded and an error should be reported
-    // if errors are requested, and a partially completed type should
-    // be returned.
-    if (partials.isNotEmpty) {
-      throwTypeError('Instantiate to bounds failed for type with '
-          'recursive generic bounds: ${typeName(this)}. '
-          'Try passing explicit type arguments.');
-    }
-    return defaults;
-  }
-
-  @notNull
-  @JSExportName('is')
-  bool is_T(obj) {
-    if (JS('!', 'typeof # == "function"', obj)) {
-      var actual = JS('', '#[#]', obj, _runtimeType);
-      return actual != null && isSubtypeOf(actual, this);
-    }
-    return false;
-  }
-
-  @JSExportName('as')
-  as_T(obj) {
-    if (obj == null || is_T(obj)) return obj;
-    return castError(obj, this, false);
-  }
-
-  @JSExportName('_check')
-  check_T(obj) {
-    if (obj == null || is_T(obj)) return obj;
-    return castError(obj, this, true);
-  }
-}
-
-List<TypeVariable> _typeFormalsFromFunction(Object typeConstructor) {
-  // Extract parameter names from the function parameters.
-  //
-  // This is not robust in general for user-defined JS functions, but it
-  // should handle the functions generated by our compiler.
-  //
-  // TODO(jmesserly): names of TypeVariables are only used for display
-  // purposes, such as when an error happens or if someone calls
-  // `Type.toString()`. So we could recover them lazily rather than eagerly.
-  // Alternatively we could synthesize new names.
-  String str = JS('!', '#.toString()', typeConstructor);
-  var hasParens = str[0] == '(';
-  var end = str.indexOf(hasParens ? ')' : '=>');
-  if (hasParens) {
-    return str
-        .substring(1, end)
-        .split(',')
-        .map((n) => TypeVariable(n.trim()))
-        .toList();
-  } else {
-    return [TypeVariable(str.substring(0, end).trim())];
-  }
-}
-
-/// Create a function type.
-FunctionType fnType(returnType, List args, [@undefined extra]) =>
-    FunctionType.create(returnType, args, extra);
-
-/// Creates a generic function type.
-///
-/// A function type consists of two things: an instantiate function, and an
-/// function that returns a list of upper bound constraints for each
-/// the type formals. Both functions accept the type parameters, allowing us
-/// to substitute values. The upper bound constraints can be omitted if all
-/// of the type parameters use the default upper bound.
-///
-/// For example given the type <T extends Iterable<T>>(T) -> T, we can declare
-/// this type with `gFnType(T => [T, [T]], T => [Iterable$(T)])`.\
-gFnType(instantiateFn, typeBounds) =>
-    GenericFunctionType(instantiateFn, typeBounds);
-
-/// TODO(vsm): Remove when mirrors is deprecated.
-/// This is a temporary workaround to support dart:mirrors, which doesn't
-/// understand generic methods.
-getFunctionTypeMirror(AbstractFunctionType type) {
-  if (type is GenericFunctionType) {
-    var typeArgs = List.filled(type.formalCount, dynamic);
-    return type.instantiate(typeArgs);
-  }
-  return type;
-}
-
-/// Whether the given JS constructor [obj] is a Dart class type.
-@notNull
-bool isType(obj) => JS('', '#[#] === #', obj, _runtimeType, Type);
-
-void checkTypeBound(
-    @notNull Object type, @notNull Object bound, @notNull String name) {
-  if (!isSubtypeOf(type, bound)) {
-    throwTypeError('type `$type` does not extend `$bound` of `$name`.');
-  }
-}
-
-@notNull
-String typeName(type) => JS('', '''(() => {
-  if ($type === void 0) return "undefined type";
-  if ($type === null) return "null type";
-  // Non-instance types
-  if ($type instanceof $DartType) {
-    return $type.toString();
-  }
-
-  // Instance types
-  let tag = $type[$_runtimeType];
-  if (tag === $Type) {
-    let name = $type.name;
-    let args = ${getGenericArgs(type)};
-    if (args == null) return name;
-
-    if (${getGenericClass(type)} == ${getGenericClass(JSArray)}) name = 'List';
-
-    let result = name;
-    result += '<';
-    for (let i = 0; i < args.length; ++i) {
-      if (i > 0) result += ', ';
-      result += $typeName(args[i]);
-    }
-    result += '>';
-    return result;
-  }
-  if (tag) return "Not a type: " + tag.name;
-  return "JSObject<" + $type.name + ">";
-})()''');
-
-/// Returns true if [ft1] <: [ft2].
-/// Returns false if [ft1] </: [ft2] in both spec and strong mode
-/// Returns null if [ft1] </: [ft2] in strong mode, but spec mode
-/// may differ
-/// If [isCovariant] is true, then we are checking subtyping in a covariant
-/// position, and hence the direction of the check for function types
-/// corresponds to the direction of the check according to the Dart spec.
-_isFunctionSubtype(ft1, ft2, isCovariant) => JS('', '''(() => {
-  let ret1 = $ft1.returnType;
-  let ret2 = $ft2.returnType;
-
-  let args1 = $ft1.args;
-  let args2 = $ft2.args;
-
-  if (args1.length > args2.length) {
-    // If we're in a covariant position, then Dart's arity rules
-    // agree with strong mode, otherwise we can't be sure.
-    return ($isCovariant) ? false : null;
-  }
-
-  for (let i = 0; i < args1.length; ++i) {
-    if (!$_isSubtype(args2[i], args1[i], !$isCovariant)) {
-      // Even if isSubtypeOf returns false, assignability
-      // means that we can't be definitive
-      return null;
-    }
-  }
-
-  let optionals1 = $ft1.optionals;
-  let optionals2 = $ft2.optionals;
-
-  if (args1.length + optionals1.length < args2.length + optionals2.length) {
-    return ($isCovariant) ? false : null;
-  }
-
-  let j = 0;
-  for (let i = args1.length; i < args2.length; ++i, ++j) {
-    if (!$_isSubtype(args2[i], optionals1[j], !$isCovariant)) {
-      return null;
-    }
-  }
-
-  for (let i = 0; i < optionals2.length; ++i, ++j) {
-    if (!$_isSubtype(optionals2[i], optionals1[j], !$isCovariant)) {
-      return null;
-    }
-  }
-
-  let named1 = $ft1.named;
-  let named2 = $ft2.named;
-
-  let names = $getOwnPropertyNames(named2);
-  for (let i = 0; i < names.length; ++i) {
-    let name = names[i];
-    let n1 = named1[name];
-    let n2 = named2[name];
-    if (n1 === void 0) {
-      return ($isCovariant) ? false : null;
-    }
-    if (!$_isSubtype(n2, n1, !$isCovariant)) {
-      return null;
-    }
-  }
-
-  // Check return type last, so that arity mismatched functions can be
-  // definitively rejected.
-
-  // For `void` we will give the same answer as the VM, so don't return null.
-  if (ret1 === $void_) return $_isTop(ret2);
-
-  if (!$_isSubtype(ret1, ret2, $isCovariant)) return null;
-  return true;
-})()''');
-
-/// Whether [t1] <: [t2].
-@notNull
-bool isSubtypeOf(Object t1, Object t2) {
-  // TODO(jmesserly): we've optimized `is`/`as`/implicit type checks, so they're
-  // dispatched on the type. Can we optimize the subtype relation too?
-  return JS('!', '!!#', _isSubtypeOrLegacySubtype(t1, t2));
-}
-
-/// Returns true if [t1] <: [t2].
-/// Returns false if [t1] </: [t2] and we should not ignore this cast failure.
-/// Returns null if [t1] </: [t2] and we should ignore this cast failure when
-/// the appropriate flags are set.
-bool _isSubtypeOrLegacySubtype(Object t1, Object t2) {
-  Object map;
-  if (JS('!', '!#.hasOwnProperty(#)', t1, _subtypeCache)) {
-    JS('', '#[#] = # = new Map()', t1, _subtypeCache, map);
-    _cacheMaps.add(map);
-  } else {
-    map = JS('', '#[#]', t1, _subtypeCache);
-    bool result = JS('', '#.get(#)', map, t2);
-    if (JS('!', '# !== void 0', result)) return result;
-  }
-  var result = _isSubtype(t1, t2, true);
-  JS('', '#.set(#, #)', map, t2, result);
-  return result;
-}
-
-final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
-
-@notNull
-bool _isBottom(type) => JS('!', '# == # || # == #', type, bottom, type, Null);
-
-@notNull
-bool _isTop(type) {
-  if (_isFutureOr(type)) {
-    return _isTop(JS('', '#[0]', getGenericArgs(type)));
-  }
-  return JS('!', '# == # || # == # || # == #', type, Object, type, dynamic,
-      type, void_);
-}
-
-@notNull
-bool _isFutureOr(type) =>
-    identical(getGenericClass(type), getGenericClass(FutureOr));
-
-bool _isSubtype(t1, t2, isCovariant) => JS('', '''(() => {
-  if ($t1 === $t2) return true;
-
-  // Trivially true.
-  if (${_isTop(t2)} || ${_isBottom(t1)}) {
-    return true;
-  }
-
-  // Trivially false.
-  if (${_isBottom(t2)}) return null;
-  if (${_isTop(t1)}) {
-    if ($t1 === $dynamic) return null;
-    return false;
-  }
-
-  // Handle FutureOr<T> union type.
-  if (${_isFutureOr(t1)}) {
-    let t1TypeArg = ${getGenericArgs(t1)}[0];
-    if (${_isFutureOr(t2)}) {
-      let t2TypeArg = ${getGenericArgs(t2)}[0];
-      // FutureOr<A> <: FutureOr<B> iff A <: B
-      return $_isSubtype(t1TypeArg, t2TypeArg, $isCovariant);
-    }
-
-    // given t1 is Future<A> | A, then:
-    // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
-    let t1Future = ${getGenericClass(Future)}(t1TypeArg);
-    return $_isSubtype(t1Future, $t2, $isCovariant) &&
-        $_isSubtype(t1TypeArg, $t2, $isCovariant);
-  }
-
-  if ($_isFutureOr($t2)) {
-    // given t2 is Future<A> | A, then:
-    // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
-    let t2TypeArg = ${getGenericArgs(t2)}[0];
-    let t2Future = ${getGenericClass(Future)}(t2TypeArg);
-    let s1 = $_isSubtype($t1, t2Future, $isCovariant);
-    let s2 = $_isSubtype($t1, t2TypeArg, $isCovariant);
-    if (s1 === true || s2 === true) return true;
-    if (s1 === null || s2 === null) return null;
-    return false;
-  }
-
-  // "Traditional" name-based subtype check.  Avoid passing
-  // function types to the class subtype checks, since we don't
-  // currently distinguish between generic typedefs and classes.
-  if (!($t2 instanceof $AbstractFunctionType)) {
-    // t2 is an interface type.
-
-    if ($t1 instanceof $AbstractFunctionType) {
-      // Function types are only subtypes of interface types `Function` (and top
-      // types, handled already above).
-      return $t2 === $Function;
-    }
-
-    // All JS types are subtypes of anonymous JS types.
-    if ($t1 === $jsobject && $t2 instanceof $AnonymousJSType) return true;
-
-    // Compare two interface types:
-    return ${_isInterfaceSubtype(t1, t2, isCovariant)};
-  }
-
-  // Function subtyping.
-  if (!($t1 instanceof $AbstractFunctionType)) return false;
-
-  // Handle generic functions.
-  if ($t1 instanceof $GenericFunctionType) {
-    if (!($t2 instanceof $GenericFunctionType)) return false;
-
-    // Given generic functions g1 and g2, g1 <: g2 iff:
-    //
-    //     g1<TFresh> <: g2<TFresh>
-    //
-    // where TFresh is a list of fresh type variables that both g1 and g2 will
-    // be instantiated with.
-    let formalCount = $t1.formalCount;
-    if (formalCount !== $t2.formalCount) return false;
-
-    // Using either function's type formals will work as long as they're both
-    // instantiated with the same ones. The instantiate operation is guaranteed
-    // to avoid capture because it does not depend on its TypeVariable objects,
-    // rather it uses JS function parameters to ensure correct binding.
-    let fresh = $t2.typeFormals;
-
-    // Check the bounds of the type parameters of g1 and g2.
-    // given a type parameter `T1 extends U1` from g1, and a type parameter
-    // `T2 extends U2` from g2, we must ensure that:
-    //
-    //      U2 <: U1
-    //
-    // (Note the reversal of direction -- type formal bounds are contravariant,
-    // similar to the function's formal parameter types).
-    //
-    let t1Bounds = $t1.instantiateTypeBounds(fresh);
-    let t2Bounds = $t2.instantiateTypeBounds(fresh);
-    // TODO(jmesserly): we could optimize for the common case of no bounds.
-    for (let i = 0; i < formalCount; i++) {
-      if (!$_isSubtype(t2Bounds[i], t1Bounds[i], !$isCovariant)) {
-        return false;
-      }
-    }
-
-    $t1 = $t1.instantiate(fresh);
-    $t2 = $t2.instantiate(fresh);
-  } else if ($t2 instanceof $GenericFunctionType) {
-    return false;
-  }
-
-  // Handle non-generic functions.
-  return ${_isFunctionSubtype(t1, t2, isCovariant)};
-})()''');
-
-bool _isInterfaceSubtype(t1, t2, isCovariant) => JS('', '''(() => {
-  // We support Dart's covariant generics with the caveat that we do not
-  // substitute bottom for dynamic in subtyping rules.
-  // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow:
-  // - S !<: S<T1, ..., Tn>
-  // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn>
-  
-  // If we have lazy JS types, unwrap them.  This will effectively
-  // reduce to a prototype check below.
-  if ($t1 instanceof $LazyJSType) $t1 = $t1.rawJSTypeForCheck();
-  if ($t2 instanceof $LazyJSType) $t2 = $t2.rawJSTypeForCheck();
-
-  if ($t1 === $t2) return true;
-  if ($t1 === $Object) return false;
-
-  // Classes cannot subtype `Function` or vice versa.
-  if ($t1 === $Function || $t2 === $Function) return false;
-
-  // If t1 is a JS Object, we may not hit core.Object.
-  if ($t1 == null) return $t2 == $Object || $t2 == $dynamic;
-
-  // Check if t1 and t2 have the same raw type.  If so, check covariance on
-  // type parameters.
-  let raw1 = $getGenericClass($t1);
-  let raw2 = $getGenericClass($t2);
-  if (raw1 != null && raw1 == raw2) {
-    let typeArguments1 = $getGenericArgs($t1);
-    let typeArguments2 = $getGenericArgs($t2);
-    let length = typeArguments1.length;
-    if (typeArguments2.length == 0) {
-      // t2 is the raw form of t1
-      return true;
-    } else if (length == 0) {
-      // t1 is raw, but t2 is not
-      if (typeArguments2.every($_isTop)) return true;
-      return null;
-    }
-    if (length != typeArguments2.length) $assertFailed();
-    for (let i = 0; i < length; ++i) {
-      let result =
-          $_isSubtype(typeArguments1[i], typeArguments2[i], $isCovariant);
-      if (!result) {
-        return result;
-      }
-    }
-    return true;
-  }
-
-  let indefinite = false;
-  function definitive(t1, t2) {
-    let result = $_isInterfaceSubtype(t1, t2, $isCovariant);
-    if (result == null) {
-      indefinite = true;
-      return false;
-    }
-    return result;
-  }
-
-  if (definitive($t1.__proto__, $t2)) return true;
-
-  // Check mixin.
-  let m1 = $getMixin($t1);
-  if (m1 != null) {
-    if (definitive(m1, $t2)) return true;
-  }
-
-  // Check interfaces.
-  let getInterfaces = $getImplements($t1);
-  if (getInterfaces) {
-    for (let i1 of getInterfaces()) {
-      if (definitive(i1, $t2)) return true;
-    }
-  }
-
-  // We found no definite supertypes, and at least one indefinite supertype
-  // so the answer is indefinite.
-  if (indefinite) return null;
-  // We found no definite supertypes and no indefinite supertypes, so we
-  // can return false.
-  return false;
-})()''');
-
-Object extractTypeArguments<T>(T instance, Function f) {
-  if (instance == null) {
-    throw ArgumentError('Cannot extract type of null instance.');
-  }
-  var type = unwrapType(T);
-  if (type is AbstractFunctionType || _isFutureOr(type)) {
-    throw ArgumentError('Cannot extract from non-class type ($type).');
-  }
-  var typeArguments = getGenericArgs(type);
-  if (typeArguments.isEmpty) {
-    throw ArgumentError('Cannot extract from non-generic type ($type).');
-  }
-  var supertype = _getMatchingSupertype(getReifiedType(instance), type);
-  // The signature of this method guarantees that instance is a T, so we
-  // should have a valid non-empty list at this point.
-  assert(supertype != null);
-  var typeArgs = getGenericArgs(supertype);
-  assert(typeArgs != null && typeArgs.isNotEmpty);
-  return dgcall(f, typeArgs, []);
-}
-
-/// Infers type variables based on a series of [trySubtypeMatch] calls, followed
-/// by [getInferredTypes] to return the type.
-class _TypeInferrer {
-  final Map<TypeVariable, TypeConstraint> _typeVariables;
-
-  /// Creates a [TypeConstraintGatherer] which is prepared to gather type
-  /// constraints for the given type parameters.
-  _TypeInferrer(Iterable<TypeVariable> typeVariables)
-      : _typeVariables = Map.fromIterables(
-            typeVariables, typeVariables.map((_) => TypeConstraint()));
-
-  /// Returns the inferred types based on the current constraints.
-  List<Object> getInferredTypes() {
-    var result = List<Object>();
-    for (var constraint in _typeVariables.values) {
-      // Prefer the known bound, if any.
-      if (constraint.lower != null) {
-        result.add(constraint.lower);
-      } else if (constraint.upper != null) {
-        result.add(constraint.upper);
-      } else {
-        return null;
-      }
-    }
-    return result;
-  }
-
-  /// Tries to match [subtype] against [supertype].
-  ///
-  /// If the match succeeds, the resulting type constraints are recorded for
-  /// later use by [computeConstraints].  If the match fails, the set of type
-  /// constraints is unchanged.
-  bool trySubtypeMatch(Object subtype, Object supertype) =>
-      _isSubtypeMatch(subtype, supertype);
-
-  void _constrainLower(TypeVariable parameter, Object lower) {
-    _typeVariables[parameter]._constrainLower(lower);
-  }
-
-  void _constrainUpper(TypeVariable parameter, Object upper) {
-    _typeVariables[parameter]._constrainUpper(upper);
-  }
-
-  bool _isFunctionSubtypeMatch(FunctionType subtype, FunctionType supertype) {
-    // A function type `(M0,..., Mn, [M{n+1}, ..., Mm]) -> R0` is a subtype
-    // match for a function type `(N0,..., Nk, [N{k+1}, ..., Nr]) -> R1` with
-    // respect to `L` under constraints `C0 + ... + Cr + C`
-    // - If `R0` is a subtype match for a type `R1` with respect to `L` under
-    //   constraints `C`:
-    // - If `n <= k` and `r <= m`.
-    // - And for `i` in `0...r`, `Ni` is a subtype match for `Mi` with respect
-    //   to `L` under constraints `Ci`.
-    // Function types with named parameters are treated analogously to the
-    // positional parameter case above.
-    // A generic function type `<T0 extends B0, ..., Tn extends Bn>F0` is a
-    // subtype match for a generic function type `<S0 extends B0, ..., Sn
-    // extends Bn>F1` with respect to `L` under constraints `Cl`:
-    // - If `F0[Z0/T0, ..., Zn/Tn]` is a subtype match for `F0[Z0/S0, ...,
-    //   Zn/Sn]` with respect to `L` under constraints `C`, where each `Zi` is a
-    //   fresh type variable with bound `Bi`.
-    // - And `Cl` is `C` with each constraint replaced with its closure with
-    //   respect to `[Z0, ..., Zn]`.
-    if (subtype.requiredParameterCount > supertype.requiredParameterCount) {
-      return false;
-    }
-    if (subtype.positionalParameterCount < supertype.positionalParameterCount) {
-      return false;
-    }
-    // Test the return types.
-    if (supertype.returnType is! VoidType &&
-        !_isSubtypeMatch(subtype.returnType, supertype.returnType)) {
-      return false;
-    }
-
-    // Test the parameter types.
-    for (int i = 0, n = supertype.positionalParameterCount; i < n; ++i) {
-      if (!_isSubtypeMatch(supertype.getPositionalParameter(i),
-          subtype.getPositionalParameter(i))) {
-        return false;
-      }
-    }
-    var supertypeNamed = supertype.getNamedParameters();
-    var subtypeNamed = supertype.getNamedParameters();
-    for (var name in supertypeNamed.keys) {
-      var subtypeParamType = subtypeNamed[name];
-      if (subtypeParamType == null) return false;
-      if (!_isSubtypeMatch(supertypeNamed[name], subtypeParamType)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  bool _isInterfaceSubtypeMatch(Object subtype, Object supertype) {
-    // A type `P<M0, ..., Mk>` is a subtype match for `P<N0, ..., Nk>` with
-    // respect to `L` under constraints `C0 + ... + Ck`:
-    // - If `Mi` is a subtype match for `Ni` with respect to `L` under
-    //   constraints `Ci`.
-    // A type `P<M0, ..., Mk>` is a subtype match for `Q<N0, ..., Nj>` with
-    // respect to `L` under constraints `C`:
-    // - If `R<B0, ..., Bj>` is the superclass of `P<M0, ..., Mk>` and `R<B0,
-    //   ..., Bj>` is a subtype match for `Q<N0, ..., Nj>` with respect to `L`
-    //   under constraints `C`.
-    // - Or `R<B0, ..., Bj>` is one of the interfaces implemented by `P<M0, ...,
-    //   Mk>` (considered in lexical order) and `R<B0, ..., Bj>` is a subtype
-    //   match for `Q<N0, ..., Nj>` with respect to `L` under constraints `C`.
-    // - Or `R<B0, ..., Bj>` is a mixin into `P<M0, ..., Mk>` (considered in
-    //   lexical order) and `R<B0, ..., Bj>` is a subtype match for `Q<N0, ...,
-    //   Nj>` with respect to `L` under constraints `C`.
-
-    // Note that since kernel requires that no class may only appear in the set
-    // of supertypes of a given type more than once, the order of the checks
-    // above is irrelevant; we just need to find the matched superclass,
-    // substitute, and then iterate through type variables.
-    var matchingSupertype = _getMatchingSupertype(subtype, supertype);
-    if (matchingSupertype == null) return false;
-
-    var matchingTypeArgs = getGenericArgs(matchingSupertype);
-    var supertypeTypeArgs = getGenericArgs(supertype);
-    for (int i = 0; i < supertypeTypeArgs.length; i++) {
-      if (!_isSubtypeMatch(matchingTypeArgs[i], supertypeTypeArgs[i])) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  bool _isNull(Object type) => identical(type, unwrapType(Null));
-
-  /// Attempts to match [subtype] as a subtype of [supertype], gathering any
-  /// constraints discovered in the process.
-  ///
-  /// If a set of constraints was found, `true` is returned and the caller
-  /// may proceed to call [computeConstraints].  Otherwise, `false` is returned.
-  ///
-  /// In the case where `false` is returned, some bogus constraints may have
-  /// been added to [_protoConstraints].  It is the caller's responsibility to
-  /// discard them if necessary.
-  bool _isSubtypeMatch(Object subtype, Object supertype) {
-    // A type variable `T` in `L` is a subtype match for any type schema `Q`:
-    // - Under constraint `T <: Q`.
-    if (subtype is TypeVariable && _typeVariables.containsKey(subtype)) {
-      _constrainUpper(subtype, supertype);
-      return true;
-    }
-    // A type schema `Q` is a subtype match for a type variable `T` in `L`:
-    // - Under constraint `Q <: T`.
-    if (supertype is TypeVariable && _typeVariables.containsKey(supertype)) {
-      _constrainLower(supertype, subtype);
-      return true;
-    }
-    // Any two equal types `P` and `Q` are subtype matches under no constraints.
-    // Note: to avoid making the algorithm quadratic, we just check for
-    // identical().  If P and Q are equal but not identical, recursing through
-    // the types will give the proper result.
-    if (identical(subtype, supertype)) return true;
-    // Any type `P` is a subtype match for `dynamic`, `Object`, or `void` under
-    // no constraints.
-    if (_isTop(supertype)) return true;
-    // `Null` is a subtype match for any type `Q` under no constraints.
-    // Note that nullable types will change this.
-    if (_isNull(subtype)) return true;
-
-    // Handle FutureOr<T> union type.
-    if (_isFutureOr(subtype)) {
-      var subtypeArg = getGenericArgs(subtype)[0];
-      if (_isFutureOr(supertype)) {
-        // `FutureOr<P>` is a subtype match for `FutureOr<Q>` with respect to `L`
-        // under constraints `C`:
-        // - If `P` is a subtype match for `Q` with respect to `L` under constraints
-        //   `C`.
-        var supertypeArg = getGenericArgs(supertype)[0];
-        return _isSubtypeMatch(subtypeArg, supertypeArg);
-      }
-
-      // `FutureOr<P>` is a subtype match for `Q` with respect to `L` under
-      // constraints `C0 + C1`:
-      // - If `Future<P>` is a subtype match for `Q` with respect to `L` under
-      //   constraints `C0`.
-      // - And `P` is a subtype match for `Q` with respect to `L` under
-      //   constraints `C1`.
-      var subtypeFuture = JS('!', '#(#)', getGenericClass(Future), subtypeArg);
-      return _isSubtypeMatch(subtypeFuture, supertype) &&
-          _isSubtypeMatch(subtypeArg, supertype);
-    }
-
-    if (_isFutureOr(supertype)) {
-      // `P` is a subtype match for `FutureOr<Q>` with respect to `L` under
-      // constraints `C`:
-      // - If `P` is a subtype match for `Future<Q>` with respect to `L` under
-      //   constraints `C`.
-      // - Or `P` is not a subtype match for `Future<Q>` with respect to `L` under
-      //   constraints `C`
-      //   - And `P` is a subtype match for `Q` with respect to `L` under
-      //     constraints `C`
-      var supertypeArg = getGenericArgs(supertype)[0];
-      var supertypeFuture =
-          JS('!', '#(#)', getGenericClass(Future), supertypeArg);
-      return _isSubtypeMatch(subtype, supertypeFuture) ||
-          _isSubtypeMatch(subtype, supertypeArg);
-    }
-
-    // A type variable `T` not in `L` with bound `P` is a subtype match for the
-    // same type variable `T` with bound `Q` with respect to `L` under
-    // constraints `C`:
-    // - If `P` is a subtype match for `Q` with respect to `L` under constraints
-    //   `C`.
-    if (subtype is TypeVariable) {
-      return supertype is TypeVariable && identical(subtype, supertype);
-    }
-    if (subtype is GenericFunctionType) {
-      if (supertype is GenericFunctionType) {
-        // Given generic functions g1 and g2, g1 <: g2 iff:
-        //
-        //     g1<TFresh> <: g2<TFresh>
-        //
-        // where TFresh is a list of fresh type variables that both g1 and g2 will
-        // be instantiated with.
-        var formalCount = subtype.formalCount;
-        if (formalCount != supertype.formalCount) return false;
-
-        // Using either function's type formals will work as long as they're
-        // both instantiated with the same ones. The instantiate operation is
-        // guaranteed to avoid capture because it does not depend on its
-        // TypeVariable objects, rather it uses JS function parameters to ensure
-        // correct binding.
-        var fresh = supertype.typeFormals;
-
-        // Check the bounds of the type parameters of g1 and g2.
-        // given a type parameter `T1 extends U1` from g1, and a type parameter
-        // `T2 extends U2` from g2, we must ensure that:
-        //
-        //      U2 <: U1
-        //
-        // (Note the reversal of direction -- type formal bounds are
-        // contravariant, similar to the function's formal parameter types).
-        //
-        var t1Bounds = subtype.instantiateTypeBounds(fresh);
-        var t2Bounds = supertype.instantiateTypeBounds(fresh);
-        // TODO(jmesserly): we could optimize for the common case of no bounds.
-        for (var i = 0; i < formalCount; i++) {
-          if (!_isSubtypeMatch(t2Bounds[i], t1Bounds[i])) {
-            return false;
-          }
-        }
-        return _isFunctionSubtypeMatch(
-            subtype.instantiate(fresh), supertype.instantiate(fresh));
-      } else {
-        return false;
-      }
-    } else if (supertype is GenericFunctionType) {
-      return false;
-    }
-
-    // A type `P` is a subtype match for `Function` with respect to `L` under no
-    // constraints:
-    // - If `P` implements a call method.
-    // - Or if `P` is a function type.
-    // TODO(paulberry): implement this case.
-    // A type `P` is a subtype match for a type `Q` with respect to `L` under
-    // constraints `C`:
-    // - If `P` is an interface type which implements a call method of type `F`,
-    //   and `F` is a subtype match for a type `Q` with respect to `L` under
-    //   constraints `C`.
-    // TODO(paulberry): implement this case.
-    if (subtype is FunctionType) {
-      if (supertype is! FunctionType) {
-        if (identical(supertype, unwrapType(Function)) ||
-            identical(supertype, unwrapType(Object))) {
-          return true;
-        } else {
-          return false;
-        }
-      }
-      if (supertype is FunctionType) {
-        return _isFunctionSubtypeMatch(subtype, supertype);
-      }
-    }
-    return _isInterfaceSubtypeMatch(subtype, supertype);
-  }
-
-  bool _isTop(Object type) =>
-      identical(type, _dynamic) ||
-      identical(type, void_) ||
-      identical(type, unwrapType(Object));
-}
-
-/// A constraint on a type parameter that we're inferring.
-class TypeConstraint {
-  /// The lower bound of the type being constrained.  This bound must be a
-  /// subtype of the type being constrained.
-  Object lower;
-
-  /// The upper bound of the type being constrained.  The type being constrained
-  /// must be a subtype of this bound.
-  Object upper;
-
-  void _constrainLower(Object type) {
-    if (lower != null) {
-      if (isSubtypeOf(lower, type)) {
-        // nothing to do, existing lower bound is lower than the new one.
-        return;
-      }
-      if (!isSubtypeOf(type, lower)) {
-        // Neither bound is lower and we don't have GLB, so use bottom type.
-        type = unwrapType(Null);
-      }
-    }
-    lower = type;
-  }
-
-  void _constrainUpper(Object type) {
-    if (upper != null) {
-      if (isSubtypeOf(type, upper)) {
-        // nothing to do, existing upper bound is higher than the new one.
-        return;
-      }
-      if (!isSubtypeOf(upper, type)) {
-        // Neither bound is higher and we don't have LUB, so use top type.
-        type = unwrapType(Object);
-      }
-    }
-    upper = type;
-  }
-
-  String toString() => '${typeName(lower)} <: <type> <: ${typeName(upper)}';
-}
-
-/// Finds a supertype of [subtype] that matches the class [supertype], but may
-/// contain different generic type arguments.
-Object _getMatchingSupertype(Object subtype, Object supertype) {
-  if (identical(subtype, supertype)) return supertype;
-  if (subtype == null || subtype == unwrapType(Object)) return null;
-
-  var subclass = getGenericClass(subtype);
-  var superclass = getGenericClass(supertype);
-  if (subclass != null && identical(subclass, superclass)) {
-    return subtype; // matching supertype found!
-  }
-
-  var result = _getMatchingSupertype(JS('', '#.__proto__', subtype), supertype);
-  if (result != null) return result;
-
-  // Check mixin.
-  var mixin = getMixin(subtype);
-  if (mixin != null) {
-    result = _getMatchingSupertype(mixin, supertype);
-    if (result != null) return result;
-  }
-
-  // Check interfaces.
-  var getInterfaces = getImplements(subtype);
-  if (getInterfaces != null) {
-    for (var iface in getInterfaces()) {
-      result = _getMatchingSupertype(iface, supertype);
-      if (result != null) return result;
-    }
-  }
-
-  return null;
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart b/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
deleted file mode 100644
index 3a6f4e9..0000000
--- a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
+++ /dev/null
@@ -1,990 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart._debugger;
-
-import 'dart:_foreign_helper' show JS;
-import 'dart:_interceptors' show JSArray;
-import 'dart:_runtime' as dart;
-import 'dart:core';
-import 'dart:collection';
-import 'dart:html' as html;
-import 'dart:math';
-
-part 'profile.dart';
-
-/// JsonMLConfig object to pass to devtools to specify how an Object should
-/// be displayed. skipDart signals that an object should not be formatted
-/// by the Dart formatter. This is used to specify that an Object
-/// should just be displayed using the regular JavaScript view instead of a
-/// custom Dart view. For example, this is used to display the JavaScript view
-/// of a Dart Function as a child of the regular Function object. keyToString
-/// signals that a map key object should have its toString() displayed by
-/// the Dart formatter.
-///
-/// We'd like this to be an enum, but we can't because it's a dev_compiler bug.
-class JsonMLConfig {
-  const JsonMLConfig(this.name);
-
-  final String name;
-  static const none = JsonMLConfig("none");
-  static const skipDart = JsonMLConfig("skipDart");
-  static const keyToString = JsonMLConfig("keyToString");
-  static const asClass = JsonMLConfig("asClass");
-  static const asObject = JsonMLConfig("asObject");
-  toString() => "JsonMLConfig($name)";
-}
-
-int _maxSpanLength = 100;
-var _devtoolsFormatter = JsonMLFormatter(DartFormatter());
-
-/// We truncate a toString() longer than [maxStringLength].
-int maxFormatterStringLength = 100;
-
-String _typeof(object) => JS('String', 'typeof #', object);
-
-List<String> getOwnPropertyNames(object) =>
-    JSArray<String>.of(dart.getOwnPropertyNames(object));
-
-List getOwnPropertySymbols(object) =>
-    JS('List', 'Object.getOwnPropertySymbols(#)', object);
-
-// TODO(jacobr): move this to dart:js and fully implement.
-class JSNative {
-  // Name may be a String or a Symbol.
-  static getProperty(object, name) => JS('', '#[#]', object, name);
-  // Name may be a String or a Symbol.
-  static setProperty(object, name, value) =>
-      JS('', '#[#]=#', object, name, value);
-}
-
-void addMetadataChildren(object, Set<NameValuePair> ret) {
-  ret.add(NameValuePair(
-      name: "[[class]]",
-      value: dart.getReifiedType(object),
-      config: JsonMLConfig.asClass));
-}
-
-/// Add properties from a signature definition [sig] for [object].
-/// Walk the prototype chain if [walkProtypeChain] is set.
-/// Tag types on function typed properties of [object] if [tagTypes] is set.
-///
-void addPropertiesFromSignature(
-    sig, Set<NameValuePair> properties, object, bool walkPrototypeChain,
-    {tagTypes = false}) {
-  // Including these property names doesn't add any value and just clutters
-  // the debugger output.
-  // TODO(jacobr): consider adding runtimeType to this list.
-  var skippedNames = Set()..add('hashCode');
-  var objectPrototype = JS('', 'Object.prototype');
-  while (sig != null && !identical(sig, objectPrototype)) {
-    for (var symbol in getOwnPropertySymbols(sig)) {
-      var dartName = symbolName(symbol);
-      String dartXPrefix = 'dartx.';
-      if (dartName.startsWith(dartXPrefix)) {
-        dartName = dartName.substring(dartXPrefix.length);
-      }
-      if (skippedNames.contains(dartName)) continue;
-      var value = safeGetProperty(object, symbol);
-      // Tag the function with its runtime type.
-      if (tagTypes && _typeof(value) == 'function') {
-        dart.fn(value, JS('', '#[#]', sig, symbol));
-      }
-      properties.add(NameValuePair(name: dartName, value: value));
-    }
-
-    for (var name in getOwnPropertyNames(sig)) {
-      var value = safeGetProperty(object, name);
-      if (skippedNames.contains(name)) continue;
-      // Tag the function with its runtime type.
-      if (tagTypes && _typeof(value) == 'function') {
-        dart.fn(value, JS('', '#[#]', sig, name));
-      }
-      properties.add(NameValuePair(name: name, value: value));
-    }
-
-    if (!walkPrototypeChain) break;
-
-    sig = dart.getPrototypeOf(sig);
-  }
-}
-
-/// Sort properties sorting public names before private names.
-List<NameValuePair> sortProperties(Iterable<NameValuePair> properties) {
-  var sortedProperties = properties.toList();
-
-  sortedProperties.sort((a, b) {
-    var aPrivate = a.name.startsWith('_');
-    var bPrivate = b.name.startsWith('_');
-    if (aPrivate != bPrivate) return aPrivate ? 1 : -1;
-    return a.name.compareTo(b.name);
-  });
-  return sortedProperties;
-}
-
-String getObjectTypeName(object) {
-  var reifiedType = dart.getReifiedType(object);
-  if (reifiedType == null) {
-    if (_typeof(object) == 'function') {
-      return '[[Raw JavaScript Function]]';
-    }
-    return '<Error getting type name>';
-  }
-  return getTypeName(reifiedType);
-}
-
-String getTypeName(type) {
-  // TODO(jacobr): it would be nice if there was a way we could distinguish
-  // between a List<dynamic> created from Dart and an Array passed in from
-  // JavaScript.
-  return dart.typeName(type);
-}
-
-String safePreview(object, config) {
-  try {
-    var preview = _devtoolsFormatter._simpleFormatter.preview(object, config);
-    if (preview != null) return preview;
-    return object.toString();
-  } catch (e) {
-    return '<Exception thrown> $e';
-  }
-}
-
-String symbolName(symbol) {
-  var name = symbol.toString();
-  assert(name.startsWith('Symbol('));
-  return name.substring('Symbol('.length, name.length - 1);
-}
-
-bool hasMethod(object, String name) {
-  try {
-    return dart.hasMethod(object, name);
-  } catch (e) {
-    return false;
-  }
-}
-
-/// [JsonMLFormatter] consumes [NameValuePair] objects and
-class NameValuePair {
-  NameValuePair(
-      {this.name,
-      this.value,
-      this.config = JsonMLConfig.none,
-      this.hideName = false});
-
-  // Define equality and hashCode so that NameValuePair can be used
-  // in a Set to dedupe entries with duplicate names.
-  bool operator ==(other) {
-    if (other is! NameValuePair) return false;
-    if (this.hideName || other.hideName) return identical(this, other);
-    return other.name == name;
-  }
-
-  int get hashCode => name.hashCode;
-
-  final String name;
-  final Object value;
-  final JsonMLConfig config;
-  final bool hideName;
-
-  String get displayName => hideName ? '' : name;
-}
-
-class MapEntry {
-  MapEntry({this.key, this.value});
-
-  final Object key;
-  final Object value;
-}
-
-class IterableSpan {
-  IterableSpan(this.start, this.end, this.iterable);
-
-  final int start;
-  final int end;
-  final Iterable iterable;
-  int get length => end - start;
-
-  /// Using length - .5, a list of length 10000 results in a
-  /// maxPowerOfSubsetSize of 1, so the list will be broken up into 100,
-  /// 100-length subsets. A list of length 10001 results in a
-  /// maxPowerOfSubsetSize of 2, so the list will be broken up into 1
-  /// 10000-length subset and 1 1-length subset.
-  int get maxPowerOfSubsetSize =>
-      (log(length - .5) / log(_maxSpanLength)).truncate();
-  int get subsetSize => pow(_maxSpanLength, maxPowerOfSubsetSize);
-
-  Map<int, dynamic> asMap() =>
-      iterable.skip(start).take(length).toList().asMap();
-
-  List<NameValuePair> children() {
-    var children = <NameValuePair>[];
-    if (length <= _maxSpanLength) {
-      asMap().forEach((i, element) {
-        children
-            .add(NameValuePair(name: (i + start).toString(), value: element));
-      });
-    } else {
-      for (var i = start; i < end; i += subsetSize) {
-        var subSpan = IterableSpan(i, min(end, subsetSize + i), iterable);
-        if (subSpan.length == 1) {
-          children.add(
-              NameValuePair(name: i.toString(), value: iterable.elementAt(i)));
-        } else {
-          children.add(NameValuePair(
-              name: '[${i}...${subSpan.end - 1}]',
-              value: subSpan,
-              hideName: true));
-        }
-      }
-    }
-    return children;
-  }
-}
-
-class Library {
-  Library(this.name, this.object);
-
-  final String name;
-  final Object object;
-}
-
-class NamedConstructor {
-  NamedConstructor(this.object);
-
-  final Object object;
-}
-
-class HeritageClause {
-  HeritageClause(this.name, this.types);
-
-  final String name;
-  final List types;
-}
-
-Object safeGetProperty(Object protoChain, Object name) {
-  try {
-    return JSNative.getProperty(protoChain, name);
-  } catch (e) {
-    return '<Exception thrown> $e';
-  }
-}
-
-safeProperties(object) => Map.fromIterable(
-    getOwnPropertyNames(object)
-        .where((each) => safeGetProperty(object, each) != null),
-    key: (name) => name,
-    value: (name) => safeGetProperty(object, name));
-
-/// Class to simplify building the JsonML objects expected by the
-/// Devtools Formatter API.
-class JsonMLElement {
-  dynamic _attributes;
-  List _jsonML;
-
-  JsonMLElement(tagName) {
-    _attributes = JS('', '{}');
-    _jsonML = [tagName, _attributes];
-  }
-
-  appendChild(element) {
-    _jsonML.add(element.toJsonML());
-  }
-
-  JsonMLElement createChild(String tagName) {
-    var c = JsonMLElement(tagName);
-    _jsonML.add(c.toJsonML());
-    return c;
-  }
-
-  JsonMLElement createObjectTag(object) =>
-      createChild('object')..addAttribute('object', object);
-
-  void setStyle(String style) {
-    _attributes.style = style;
-  }
-
-  addStyle(String style) {
-    if (_attributes.style == null) {
-      _attributes.style = style;
-    } else {
-      _attributes.style += style;
-    }
-  }
-
-  addAttribute(key, value) {
-    JSNative.setProperty(_attributes, key, value);
-  }
-
-  createTextChild(String text) {
-    _jsonML.add(text);
-  }
-
-  toJsonML() => _jsonML;
-}
-
-/// Whether an object is a native JavaScript type where we should display the
-/// JavaScript view of the object instead of the custom Dart specific render
-/// of properties.
-bool isNativeJavaScriptObject(object) {
-  var type = _typeof(object);
-  if (type != 'object' && type != 'function') return true;
-
-  // Consider all regular JS objects that do not represent Dart modules native
-  // JavaScript objects.
-  if (dart.isJsInterop(object) && dart.getModuleName(object) == null) {
-    return true;
-  }
-
-  // Treat Node objects as a native JavaScript type as the regular DOM render
-  // in devtools is superior to the dart specific view.
-  return object is html.Node;
-}
-
-/// Class implementing the Devtools Formatter API described by:
-/// https://docs.google.com/document/d/1FTascZXT9cxfetuPRT2eXPQKXui4nWFivUnS_335T3U
-/// Specifically, a formatter implements a header, hasBody, and body method.
-/// This class renders the simple structured format objects [_simpleFormatter]
-/// provides as JsonML.
-class JsonMLFormatter {
-  // TODO(jacobr): define a SimpleFormatter base class that DartFormatter
-  // implements if we decide to use this class elsewhere. We specify that the
-  // type is DartFormatter here purely to get type checking benefits not because
-  // this class is really intended to only support instances of type
-  // DartFormatter.
-  DartFormatter _simpleFormatter;
-
-  bool customFormattersOn = false;
-
-  JsonMLFormatter(this._simpleFormatter);
-
-  void setMaxSpanLengthForTestingOnly(int spanLength) {
-    _maxSpanLength = spanLength;
-  }
-
-  header(object, config) {
-    customFormattersOn = true;
-    if (config == JsonMLConfig.skipDart || isNativeJavaScriptObject(object)) {
-      return null;
-    }
-    var c = _simpleFormatter.preview(object, config);
-    if (c == null) return null;
-
-    if (config == JsonMLConfig.keyToString) {
-      c = object.toString();
-    }
-
-    // Indicate this is a Dart Object by using a Dart background color.
-    // This is stylistically a bit ugly but it eases distinguishing Dart and
-    // JS objects.
-    var element = JsonMLElement('span')
-      ..setStyle('background-color: #d9edf7;color: black')
-      ..createTextChild(c);
-    return element.toJsonML();
-  }
-
-  bool hasBody(object, config) => _simpleFormatter.hasChildren(object, config);
-
-  body(object, config) {
-    var body = JsonMLElement('ol')
-      ..setStyle('list-style-type: none;'
-          'padding-left: 0px;'
-          'margin-top: 0px;'
-          'margin-bottom: 0px;'
-          'margin-left: 12px;');
-    if (object is StackTrace) {
-      body.addStyle('background-color: thistle;color: rgb(196, 26, 22);');
-    }
-    var children = _simpleFormatter.children(object, config);
-    if (children == null) return body.toJsonML();
-    for (NameValuePair child in children) {
-      var li = body.createChild('li');
-      li.setStyle("padding-left: 13px;");
-
-      // The value is indented when it is on a different line from the name
-      // by setting right padding of the name to -13px and the padding of the
-      // value to 13px.
-      JsonMLElement nameSpan;
-      var valueStyle = '';
-      if (!child.hideName) {
-        nameSpan = JsonMLElement('span')
-          ..createTextChild(
-              child.displayName.isNotEmpty ? '${child.displayName}: ' : '')
-          ..setStyle(
-              'background-color: thistle; color: rgb(136, 19, 145); margin-right: -13px');
-        valueStyle = 'margin-left: 13px';
-      }
-
-      if (_typeof(child.value) == 'object' ||
-          _typeof(child.value) == 'function') {
-        var valueSpan = JsonMLElement('span')..setStyle(valueStyle);
-        valueSpan.createObjectTag(child.value)
-          ..addAttribute('config', child.config);
-        if (nameSpan != null) {
-          li.appendChild(nameSpan);
-        }
-        li.appendChild(valueSpan);
-      } else {
-        var line = li.createChild('span');
-        if (nameSpan != null) {
-          line.appendChild(nameSpan);
-        }
-        line.appendChild(JsonMLElement('span')
-          ..createTextChild(safePreview(child.value, child.config))
-          ..setStyle(valueStyle));
-      }
-    }
-    return body.toJsonML();
-  }
-}
-
-abstract class Formatter {
-  bool accept(object, config);
-  String preview(object);
-  bool hasChildren(object);
-  List<NameValuePair> children(object);
-}
-
-class DartFormatter {
-  List<Formatter> _formatters;
-
-  DartFormatter() {
-    // The order of formatters matters as formatters earlier in the list take
-    // precedence.
-    _formatters = [
-      ObjectInternalsFormatter(),
-      ClassFormatter(),
-      TypeFormatter(),
-      NamedConstructorFormatter(),
-      MapFormatter(),
-      IterableFormatter(),
-      IterableSpanFormatter(),
-      MapEntryFormatter(),
-      StackTraceFormatter(),
-      ErrorAndExceptionFormatter(),
-      FunctionFormatter(),
-      HeritageClauseFormatter(),
-      LibraryModuleFormatter(),
-      LibraryFormatter(),
-      ObjectFormatter(),
-    ];
-  }
-
-  String preview(object, config) {
-    try {
-      if (object == null ||
-          object is num ||
-          object is String ||
-          isNativeJavaScriptObject(object)) {
-        return object.toString();
-      }
-      for (var formatter in _formatters) {
-        if (formatter.accept(object, config)) return formatter.preview(object);
-      }
-    } catch (e, trace) {
-      // Log formatter internal errors as unfortunately the devtools cannot
-      // be used to debug formatter errors.
-      html.window.console.error("Caught exception $e\n trace:\n$trace");
-    }
-
-    return null;
-  }
-
-  bool hasChildren(object, config) {
-    if (object == null) return false;
-    try {
-      for (var formatter in _formatters) {
-        if (formatter.accept(object, config))
-          return formatter.hasChildren(object);
-      }
-    } catch (e, trace) {
-      // See comment for preview.
-      html.window.console
-          .error("[hasChildren] Caught exception $e\n trace:\n$trace");
-    }
-    return false;
-  }
-
-  List<NameValuePair> children(object, config) {
-    try {
-      if (object != null) {
-        for (var formatter in _formatters) {
-          if (formatter.accept(object, config))
-            return formatter.children(object);
-        }
-      }
-    } catch (e, trace) {
-      // See comment for preview.
-      html.window.console.error("Caught exception $e\n trace:\n$trace");
-    }
-    return <NameValuePair>[];
-  }
-}
-
-/// Default formatter for Dart Objects.
-class ObjectFormatter extends Formatter {
-  bool accept(object, config) => !isNativeJavaScriptObject(object);
-
-  String preview(object) {
-    var typeName = getObjectTypeName(object);
-    try {
-      // An explicit toString() call might not actually be a string. This way
-      // we're sure.
-      var toString = "$object";
-      if (toString.length > maxFormatterStringLength) {
-        toString = toString.substring(0, maxFormatterStringLength - 3) + "...";
-      }
-      // The default toString() will be "Instance of 'Foo'", in which case we
-      // don't need any further indication of the class.
-      if (toString.contains(typeName)) {
-        return toString;
-      } else {
-        // If there's no class indication, e.g. an Int64 that just prints as a
-        // number, then add the class name.
-        return "$toString ($typeName)";
-      }
-    } catch (e) {}
-    // We will only get here if there was an error getting the toString, in
-    // which case we just use the type name.
-    return typeName;
-  }
-
-  bool hasChildren(object) => true;
-
-  List<NameValuePair> children(object) {
-    var type = dart.getType(object);
-    var ret = LinkedHashSet<NameValuePair>();
-    // We use a Set rather than a List to avoid duplicates.
-    var fields = Set<NameValuePair>();
-    addPropertiesFromSignature(dart.getFields(type), fields, object, true);
-    var getters = Set<NameValuePair>();
-    addPropertiesFromSignature(dart.getGetters(type), getters, object, true);
-    ret.addAll(sortProperties(fields));
-    ret.addAll(sortProperties(getters));
-    addMetadataChildren(object, ret);
-    return ret.toList();
-  }
-}
-
-/// Show the object instance members and a reduced preview.
-///
-/// Used as a sub-entry to show the internals of objects that have a different
-/// primary format. For example, a Map shows the key-value pairs, but this makes
-/// the internals of the map visible for debugging.
-class ObjectInternalsFormatter extends ObjectFormatter {
-  bool accept(object, config) =>
-      super.accept(object, config) && config == JsonMLConfig.asObject;
-
-  // A minimal preview because we expect a full preview is already shown in a
-  // parent formatter.
-  String preview(object) {
-    return getObjectTypeName(object);
-  }
-}
-
-/// Formatter for module Dart Library objects.
-class LibraryModuleFormatter implements Formatter {
-  accept(object, config) => dart.getModuleName(object) != null;
-
-  bool hasChildren(object) => true;
-
-  String preview(object) {
-    var libraryNames = dart.getModuleName(object).split('/');
-    // Library names are received with a repeat directory name, so strip the
-    // last directory entry here to make the path cleaner. For example, the
-    // library "third_party/dart/utf/utf" shoud display as
-    // "third_party/dart/utf/".
-    if (libraryNames.length > 1 &&
-        libraryNames.last == libraryNames[libraryNames.length - 2]) {
-      libraryNames[libraryNames.length - 1] = '';
-    }
-    return 'Library Module: ${libraryNames.join('/')}';
-  }
-
-  List<NameValuePair> children(object) {
-    var children = LinkedHashSet<NameValuePair>();
-    for (var name in getOwnPropertyNames(object)) {
-      var value = safeGetProperty(object, name);
-      children.add(NameValuePair(
-          name: name, value: Library(name, value), hideName: true));
-    }
-    return children.toList();
-  }
-}
-
-class LibraryFormatter implements Formatter {
-  var genericParameters = HashMap<String, String>();
-
-  accept(object, config) => object is Library;
-
-  bool hasChildren(object) => true;
-
-  String preview(object) => object.name;
-
-  List<NameValuePair> children(object) {
-    // Maintain library member order rather than sorting members as is the
-    // case for class members.
-    var children = LinkedHashSet<NameValuePair>();
-    var objectProperties = safeProperties(object.object);
-    objectProperties.forEach((name, value) {
-      // Skip the generic constructors for each class as users are only
-      // interested in seeing the actual classes.
-      if (dart.getGenericTypeCtor(value) != null) return;
-
-      children.add(dart.isType(value)
-          ? classChild(name, value)
-          : NameValuePair(name: name, value: value));
-    });
-    return children.toList();
-  }
-
-  classChild(String name, Object child) {
-    var typeName = getTypeName(child);
-    return NameValuePair(
-        name: typeName, value: child, config: JsonMLConfig.asClass);
-  }
-}
-
-/// Formatter for Dart Function objects.
-/// Dart functions happen to be regular JavaScript Function objects but
-/// we can distinguish them based on whether they have been tagged with
-/// runtime type information.
-class FunctionFormatter implements Formatter {
-  accept(object, config) {
-    if (_typeof(object) != 'function') return false;
-    return dart.getReifiedType(object) != null;
-  }
-
-  bool hasChildren(object) => true;
-
-  String preview(object) {
-    // The debugger can createa a preview of a FunctionType while it's being
-    // constructed (before argument types exist), so we need to catch errors.
-    try {
-      return dart.typeName(dart.getReifiedType(object));
-    } catch (e) {
-      return safePreview(object, JsonMLConfig.none);
-    }
-  }
-
-  List<NameValuePair> children(object) => <NameValuePair>[
-        NameValuePair(name: 'signature', value: preview(object)),
-        NameValuePair(
-            name: 'JavaScript Function',
-            value: object,
-            config: JsonMLConfig.skipDart)
-      ];
-}
-
-/// Formatter for Dart Map objects.
-class MapFormatter implements Formatter {
-  accept(object, config) => object is Map;
-
-  bool hasChildren(object) => true;
-
-  String preview(object) {
-    Map map = object;
-    try {
-      return '${getObjectTypeName(map)} length ${map.length}';
-    } catch (e) {
-      return safePreview(object, JsonMLConfig.none);
-    }
-  }
-
-  List<NameValuePair> children(object) {
-    // TODO(jacobr): be lazier about enumerating contents of Maps that are not
-    // the build in LinkedHashMap class.
-    // TODO(jacobr): handle large Maps better.
-    Map map = object;
-    var entries = LinkedHashSet<NameValuePair>();
-    map.forEach((key, value) {
-      var entryWrapper = MapEntry(key: key, value: value);
-      entries.add(
-          NameValuePair(name: entries.length.toString(), value: entryWrapper));
-    });
-    addInstanceMembers(object, entries);
-    addMetadataChildren(object, entries);
-    return entries.toList();
-  }
-
-  // We've formatted as a Map, but we may want to see the internals
-  // of the Map, particularly for domain objects that implement Map.
-  // Add an ObjectFormatter view underneath.
-  void addInstanceMembers(object, Set<NameValuePair> ret) {
-    ret.add(NameValuePair(
-        name: "[[instance members]]",
-        value: object,
-        config: JsonMLConfig.asObject));
-  }
-}
-
-/// Formatter for Dart Iterable objects including List and Set.
-class IterableFormatter implements Formatter {
-  bool accept(object, config) => object is Iterable;
-
-  String preview(object) {
-    Iterable iterable = object;
-    try {
-      var length = iterable.length;
-      return '${getObjectTypeName(iterable)} length $length';
-    } catch (_) {
-      return '${getObjectTypeName(iterable)}';
-    }
-  }
-
-  bool hasChildren(object) => true;
-
-  List<NameValuePair> children(object) {
-    // TODO(jacobr): be lazier about enumerating contents of Iterables that
-    // are not the built in Set or List types.
-    // TODO(jacobr): handle large Iterables better.
-    // TODO(jacobr): consider only using numeric indices
-    var children = LinkedHashSet<NameValuePair>();
-    children.addAll(IterableSpan(0, object.length, object).children());
-    // TODO(jacobr): provide a link to show regular class properties here.
-    // required for subclasses of iterable, etc.
-    addMetadataChildren(object, children);
-    return children.toList();
-  }
-}
-
-class NamedConstructorFormatter implements Formatter {
-  accept(object, config) => object is NamedConstructor;
-
-  // TODO(bmilligan): Display the signature of the named constructor as the
-  // preview.
-  String preview(object) => 'Named Constructor';
-
-  bool hasChildren(object) => true;
-
-  List<NameValuePair> children(object) => <NameValuePair>[
-        NameValuePair(
-            name: 'JavaScript Function',
-            value: object,
-            config: JsonMLConfig.skipDart)
-      ];
-}
-
-/// Formatter for synthetic MapEntry objects used to display contents of a Map
-/// cleanly.
-class MapEntryFormatter implements Formatter {
-  accept(object, config) => object is MapEntry;
-
-  String preview(object) {
-    MapEntry entry = object;
-    return '${safePreview(entry.key, JsonMLConfig.none)} => ${safePreview(entry.value, JsonMLConfig.none)}';
-  }
-
-  bool hasChildren(object) => true;
-
-  List<NameValuePair> children(object) => <NameValuePair>[
-        NameValuePair(
-            name: 'key', value: object.key, config: JsonMLConfig.keyToString),
-        NameValuePair(name: 'value', value: object.value)
-      ];
-}
-
-/// Formatter for Dart Iterable objects including List and Set.
-class HeritageClauseFormatter implements Formatter {
-  bool accept(object, config) => object is HeritageClause;
-
-  String preview(object) {
-    HeritageClause clause = object;
-    var typeNames = clause.types.map(getTypeName);
-    return '${clause.name} ${typeNames.join(", ")}';
-  }
-
-  bool hasChildren(object) => true;
-
-  List<NameValuePair> children(object) {
-    HeritageClause clause = object;
-    var children = <NameValuePair>[];
-    for (var type in clause.types) {
-      children.add(NameValuePair(value: type, config: JsonMLConfig.asClass));
-    }
-    return children;
-  }
-}
-
-/// Formatter for synthetic IterableSpan objects used to display contents of
-/// an Iterable cleanly.
-class IterableSpanFormatter implements Formatter {
-  accept(object, config) => object is IterableSpan;
-
-  String preview(object) {
-    return '[${object.start}...${object.end - 1}]';
-  }
-
-  bool hasChildren(object) => true;
-
-  List<NameValuePair> children(object) => object.children();
-}
-
-/// Formatter for Dart Errors and Exceptions.
-class ErrorAndExceptionFormatter extends ObjectFormatter {
-  static final RegExp _pattern = RegExp(r'\d+\:\d+');
-
-  accept(object, config) => object is Error || object is Exception;
-
-  bool hasChildren(object) => true;
-
-  String preview(object) {
-    var trace = dart.stackTrace(object);
-    // TODO(vsm): Pull our stack mapping logic here.  We should aim to
-    // provide the first meaningful stack frame.
-    var line = '$trace'.split('\n').firstWhere(
-        (l) =>
-            l.contains(_pattern) &&
-            !l.contains('dart:sdk') &&
-            !l.contains('dart_sdk'),
-        orElse: () => null);
-    return line != null ? '${object} at ${line}' : '${object}';
-  }
-
-  List<NameValuePair> children(object) {
-    var trace = dart.stackTrace(object);
-    var entries = LinkedHashSet<NameValuePair>();
-    entries.add(NameValuePair(name: 'stackTrace', value: trace));
-    addInstanceMembers(object, entries);
-    addMetadataChildren(object, entries);
-    return entries.toList();
-  }
-
-  // Add an ObjectFormatter view underneath.
-  void addInstanceMembers(object, Set<NameValuePair> ret) {
-    ret.add(NameValuePair(
-        name: "[[instance members]]",
-        value: object,
-        config: JsonMLConfig.asObject));
-  }
-}
-
-class StackTraceFormatter implements Formatter {
-  accept(object, config) => object is StackTrace;
-
-  String preview(object) => 'StackTrace';
-
-  bool hasChildren(object) => true;
-
-  // Using the stack_trace formatting would be ideal, but adding the
-  // dependency or re-writing the code is too messy, so each line of the
-  // StackTrace will be added as its own child.
-  List<NameValuePair> children(object) => object
-      .toString()
-      .split('\n')
-      .map((line) => NameValuePair(
-          value: line.replaceFirst(RegExp(r'^\s+at\s'), ''), hideName: true))
-      .toList();
-}
-
-class ClassFormatter implements Formatter {
-  accept(object, config) => config == JsonMLConfig.asClass;
-
-  String preview(type) {
-    var implements = dart.getImplements(type);
-    var typeName = getTypeName(type);
-    if (implements != null) {
-      var typeNames = implements().map(getTypeName);
-      return '${typeName} implements ${typeNames.join(", ")}';
-    } else {
-      return typeName;
-    }
-  }
-
-  bool hasChildren(object) => true;
-
-  List<NameValuePair> children(type) {
-    // TODO(jacobr): add other entries describing the class such as
-    // implemented interfaces, and methods.
-    var ret = LinkedHashSet<NameValuePair>();
-
-    var staticProperties = Set<NameValuePair>();
-    var staticMethods = Set<NameValuePair>();
-    // Static fields and properties.
-    addPropertiesFromSignature(
-        dart.getStaticFields(type), staticProperties, type, false);
-    addPropertiesFromSignature(
-        dart.getStaticGetters(type), staticProperties, type, false);
-    // static methods.
-    addPropertiesFromSignature(
-        dart.getStaticMethods(type), staticMethods, type, false);
-
-    if (staticProperties.isNotEmpty || staticMethods.isNotEmpty) {
-      ret
-        ..add(NameValuePair(value: '[[Static members]]', hideName: true))
-        ..addAll(sortProperties(staticProperties))
-        ..addAll(sortProperties(staticMethods));
-    }
-
-    // instance methods.
-    var instanceMethods = Set<NameValuePair>();
-    // Instance methods are defined on the prototype not the constructor object.
-    addPropertiesFromSignature(dart.getMethods(type), instanceMethods,
-        JS('', '#.prototype', type), false,
-        tagTypes: true);
-    if (instanceMethods.isNotEmpty) {
-      ret
-        ..add(NameValuePair(value: '[[Instance Methods]]', hideName: true))
-        ..addAll(sortProperties(instanceMethods));
-    }
-
-    var mixin = dart.getMixin(type);
-    if (mixin != null) {
-      // TODO(jmesserly): this can only be one value.
-      ret.add(NameValuePair(
-          name: '[[Mixins]]', value: HeritageClause('mixins', [mixin])));
-    }
-
-    var baseProto = JS('', '#.__proto__', type);
-    if (baseProto != null && !dart.isJsInterop(baseProto)) {
-      ret.add(NameValuePair(
-          name: "[[base class]]",
-          value: baseProto,
-          config: JsonMLConfig.asClass));
-    }
-
-    // TODO(jacobr): add back fields for named constructors.
-    return ret.toList();
-  }
-}
-
-class TypeFormatter implements Formatter {
-  accept(object, config) => object is Type;
-
-  String preview(object) => object.toString();
-
-  bool hasChildren(object) => false;
-
-  List<NameValuePair> children(object) => [];
-}
-
-typedef String StackTraceMapper(String stackTrace);
-
-/// Hook for other parts of the SDK To use to map JS stack traces to Dart
-/// stack traces.
-///
-/// Raw JS stack traces are used if $dartStackTraceUtility has not been
-/// specified.
-StackTraceMapper get stackTraceMapper {
-  var _util = JS('', r'#.$dartStackTraceUtility', dart.global_);
-  return _util != null ? JS('!', '#.mapper', _util) : null;
-}
-
-/// This entry point is automatically invoked by the code generated by
-/// Dart Dev Compiler
-registerDevtoolsFormatter() {
-  JS('', '#.devtoolsFormatters = [#]', dart.global_, _devtoolsFormatter);
-}
-
-// These methods are exposed here for debugger tests.
-//
-// TODO(jmesserly): these are not exports because there is existing code that
-// calls into them from JS. Currently `dartdevc` always resolves exports at
-// compile time, so there is no need to make exports available at runtime by
-// copying properties. For that reason we cannot use re-export.
-//
-// If these methods are only for tests, we should move them here, or change the
-// tests to call the methods directly on dart:_runtime.
-List<String> getModuleNames() => dart.getModuleNames();
-getModuleLibraries(String name) => dart.getModuleLibraries(name);
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart b/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart
deleted file mode 100644
index cf6b1e6..0000000
--- a/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart
+++ /dev/null
@@ -1,808 +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 dart._js_helper;
-
-import 'dart:collection';
-
-import 'dart:_foreign_helper' show JS, JS_STRING_CONCAT, JSExportName;
-
-import 'dart:_interceptors';
-import 'dart:_internal'
-    show
-        EfficientLengthIterable,
-        MappedIterable,
-        IterableElementError,
-        SubListIterable;
-
-import 'dart:_native_typed_data';
-import 'dart:_runtime' as dart;
-
-part 'annotations.dart';
-part 'linked_hash_map.dart';
-part 'identity_hash_map.dart';
-part 'custom_hash_map.dart';
-part 'native_helper.dart';
-part 'regexp_helper.dart';
-part 'string_helper.dart';
-part 'js_rti.dart';
-
-class _Patch {
-  const _Patch();
-}
-
-const _Patch patch = _Patch();
-
-/// Adapts a JS `[Symbol.iterator]` to a Dart `get iterator`.
-///
-/// This is the inverse of `JsIterator`, for classes where we can more
-/// efficiently obtain a JS iterator instead of a Dart one.
-///
-// TODO(jmesserly): this adapter is to work around
-// https://github.com/dart-lang/sdk/issues/28320
-class DartIterator<E> implements Iterator<E> {
-  final _jsIterator;
-  E _current;
-
-  DartIterator(this._jsIterator);
-
-  E get current => _current;
-
-  bool moveNext() {
-    final ret = JS('', '#.next()', _jsIterator);
-    _current = JS('', '#.value', ret);
-    return JS('bool', '!#.done', ret);
-  }
-}
-
-/// Used to compile `sync*`.
-class SyncIterable<E> extends IterableBase<E> {
-  final Function() _initGenerator;
-  SyncIterable(this._initGenerator);
-
-  @JSExportName('Symbol.iterator')
-  _jsIterator() => _initGenerator();
-
-  get iterator => DartIterator(_initGenerator());
-}
-
-class Primitives {
-  @NoInline()
-  static int _parseIntError(String source, int handleError(String source)) {
-    if (handleError == null) throw FormatException(source);
-    return handleError(source);
-  }
-
-  static int parseInt(
-      @nullCheck String source, int _radix, int handleError(String source)) {
-    var re = JS('', r'/^\s*[+-]?((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$/i');
-    // TODO(jmesserly): this isn't reified List<String>, but it's safe to use as
-    // long as we use it locally and don't expose it to user code.
-    List<String> match = JS('', '#.exec(#)', re, source);
-    int digitsIndex = 1;
-    int hexIndex = 2;
-    int decimalIndex = 3;
-    if (match == null) {
-      // TODO(sra): It might be that the match failed due to unrecognized U+0085
-      // spaces.  We could replace them with U+0020 spaces and try matching
-      // again.
-      return _parseIntError(source, handleError);
-    }
-    String decimalMatch = match[decimalIndex];
-    if (_radix == null) {
-      if (decimalMatch != null) {
-        // Cannot fail because we know that the digits are all decimal.
-        return JS('int', r'parseInt(#, 10)', source);
-      }
-      if (match[hexIndex] != null) {
-        // Cannot fail because we know that the digits are all hex.
-        return JS('int', r'parseInt(#, 16)', source);
-      }
-      return _parseIntError(source, handleError);
-    }
-    @notNull
-    var radix = _radix;
-    if (radix < 2 || radix > 36) {
-      throw RangeError.range(radix, 2, 36, 'radix');
-    }
-    if (radix == 10 && decimalMatch != null) {
-      // Cannot fail because we know that the digits are all decimal.
-      return JS('int', r'parseInt(#, 10)', source);
-    }
-    // If radix >= 10 and we have only decimal digits the string is safe.
-    // Otherwise we need to check the digits.
-    if (radix < 10 || decimalMatch == null) {
-      // We know that the characters must be ASCII as otherwise the
-      // regexp wouldn't have matched. Lowercasing by doing `| 0x20` is thus
-      // guaranteed to be a safe operation, since it preserves digits
-      // and lower-cases ASCII letters.
-      int maxCharCode;
-      if (radix <= 10) {
-        // Allow all digits less than the radix. For example 0, 1, 2 for
-        // radix 3.
-        // "0".codeUnitAt(0) + radix - 1;
-        maxCharCode = (0x30 - 1) + radix;
-      } else {
-        // Letters are located after the digits in ASCII. Therefore we
-        // only check for the character code. The regexp above made already
-        // sure that the string does not contain anything but digits or
-        // letters.
-        // "a".codeUnitAt(0) + (radix - 10) - 1;
-        maxCharCode = (0x61 - 10 - 1) + radix;
-      }
-      assert(match[digitsIndex] is String);
-      String digitsPart = JS('String', '#[#]', match, digitsIndex);
-      for (int i = 0; i < digitsPart.length; i++) {
-        int characterCode = digitsPart.codeUnitAt(i) | 0x20;
-        if (characterCode > maxCharCode) {
-          return _parseIntError(source, handleError);
-        }
-      }
-    }
-    // The above matching and checks ensures the source has at least one digits
-    // and all digits are suitable for the radix, so parseInt cannot return NaN.
-    return JS('int', r'parseInt(#, #)', source, radix);
-  }
-
-  @NoInline()
-  static double _parseDoubleError(
-      String source, double handleError(String source)) {
-    if (handleError == null) {
-      throw FormatException('Invalid double', source);
-    }
-    return handleError(source);
-  }
-
-  static double parseDouble(
-      @nullCheck String source, double handleError(String source)) {
-    // Notice that JS parseFloat accepts garbage at the end of the string.
-    // Accept only:
-    // - [+/-]NaN
-    // - [+/-]Infinity
-    // - a Dart double literal
-    // We do allow leading or trailing whitespace.
-    if (!JS(
-        'bool',
-        r'/^\s*[+-]?(?:Infinity|NaN|'
-        r'(?:\.\d+|\d+(?:\.\d*)?)(?:[eE][+-]?\d+)?)\s*$/.test(#)',
-        source)) {
-      return _parseDoubleError(source, handleError);
-    }
-    num result = JS('!', r'parseFloat(#)', source);
-    if (result.isNaN) {
-      var trimmed = source.trim();
-      if (trimmed == 'NaN' || trimmed == '+NaN' || trimmed == '-NaN') {
-        return result;
-      }
-      return _parseDoubleError(source, handleError);
-    }
-    return result;
-  }
-
-  /** `r"$".codeUnitAt(0)` */
-  static const int DOLLAR_CHAR_VALUE = 36;
-
-  static int dateNow() => JS('int', r'Date.now()');
-
-  static void initTicker() {
-    if (timerFrequency != null) return;
-    // Start with low-resolution. We overwrite the fields if we find better.
-    timerFrequency = 1000;
-    timerTicks = dateNow;
-    if (JS('bool', 'typeof window == "undefined"')) return;
-    var jsWindow = JS('var', 'window');
-    if (jsWindow == null) return;
-    var performance = JS('var', '#.performance', jsWindow);
-    if (performance == null) return;
-    if (JS('bool', 'typeof #.now != "function"', performance)) return;
-    timerFrequency = 1000000;
-    timerTicks = () => (1000 * JS<num>('!', '#.now()', performance)).floor();
-  }
-
-  static int timerFrequency;
-  static num Function() timerTicks;
-
-  static bool get isD8 {
-    return JS(
-        'bool',
-        'typeof version == "function"'
-        ' && typeof os == "object" && "system" in os');
-  }
-
-  static bool get isJsshell {
-    return JS(
-        'bool', 'typeof version == "function" && typeof system == "function"');
-  }
-
-  static String currentUri() {
-    // In a browser return self.location.href.
-    if (JS('bool', '!!#.location', dart.global_)) {
-      return JS('String', '#.location.href', dart.global_);
-    }
-
-    // TODO(vsm): Consider supporting properly in non-browser settings.
-    return '';
-  }
-
-  // This is to avoid stack overflows due to very large argument arrays in
-  // apply().  It fixes http://dartbug.com/6919
-  @notNull
-  static String _fromCharCodeApply(List<int> array) {
-    const kMaxApply = 500;
-    @nullCheck
-    int end = array.length;
-    if (end <= kMaxApply) {
-      return JS('String', r'String.fromCharCode.apply(null, #)', array);
-    }
-    String result = '';
-    for (int i = 0; i < end; i += kMaxApply) {
-      int chunkEnd = (i + kMaxApply < end) ? i + kMaxApply : end;
-      result = JS(
-          'String',
-          r'# + String.fromCharCode.apply(null, #.slice(#, #))',
-          result,
-          array,
-          i,
-          chunkEnd);
-    }
-    return result;
-  }
-
-  @notNull
-  static String stringFromCodePoints(JSArray<int> codePoints) {
-    List<int> a = <int>[];
-    for (@nullCheck var i in codePoints) {
-      if (i <= 0xffff) {
-        a.add(i);
-      } else if (i <= 0x10ffff) {
-        a.add(0xd800 + ((((i - 0x10000) >> 10) & 0x3ff)));
-        a.add(0xdc00 + (i & 0x3ff));
-      } else {
-        throw argumentErrorValue(i);
-      }
-    }
-    return _fromCharCodeApply(a);
-  }
-
-  @notNull
-  static String stringFromCharCodes(JSArray<int> charCodes) {
-    for (@nullCheck var i in charCodes) {
-      if (i < 0) throw argumentErrorValue(i);
-      if (i > 0xffff) return stringFromCodePoints(charCodes);
-    }
-    return _fromCharCodeApply(charCodes);
-  }
-
-  // [start] and [end] are validated.
-  @notNull
-  static String stringFromNativeUint8List(
-      NativeUint8List charCodes, @nullCheck int start, @nullCheck int end) {
-    const kMaxApply = 500;
-    if (end <= kMaxApply && start == 0 && end == charCodes.length) {
-      return JS('String', r'String.fromCharCode.apply(null, #)', charCodes);
-    }
-    String result = '';
-    for (int i = start; i < end; i += kMaxApply) {
-      int chunkEnd = (i + kMaxApply < end) ? i + kMaxApply : end;
-      result = JS(
-          'String',
-          r'# + String.fromCharCode.apply(null, #.subarray(#, #))',
-          result,
-          charCodes,
-          i,
-          chunkEnd);
-    }
-    return result;
-  }
-
-  @notNull
-  static String stringFromCharCode(@nullCheck int charCode) {
-    if (0 <= charCode) {
-      if (charCode <= 0xffff) {
-        return JS('String', 'String.fromCharCode(#)', charCode);
-      }
-      if (charCode <= 0x10ffff) {
-        var bits = charCode - 0x10000;
-        var low = 0xDC00 | (bits & 0x3ff);
-        var high = 0xD800 | (bits >> 10);
-        return JS('String', 'String.fromCharCode(#, #)', high, low);
-      }
-    }
-    throw RangeError.range(charCode, 0, 0x10ffff);
-  }
-
-  static String stringConcatUnchecked(String string1, String string2) {
-    return JS_STRING_CONCAT(string1, string2);
-  }
-
-  static String flattenString(String str) {
-    return JS('String', "#.charCodeAt(0) == 0 ? # : #", str, str, str);
-  }
-
-  static String getTimeZoneName(DateTime receiver) {
-    // Firefox and Chrome emit the timezone in parenthesis.
-    // Example: "Wed May 16 2012 21:13:00 GMT+0200 (CEST)".
-    // We extract this name using a regexp.
-    var d = lazyAsJsDate(receiver);
-    List match = JS('JSArray|Null', r'/\((.*)\)/.exec(#.toString())', d);
-    if (match != null) return match[1];
-
-    // Internet Explorer 10+ emits the zone name without parenthesis:
-    // Example: Thu Oct 31 14:07:44 PDT 2013
-    match = JS(
-        'JSArray|Null',
-        // Thu followed by a space.
-        r'/^[A-Z,a-z]{3}\s'
-        // Oct 31 followed by space.
-        r'[A-Z,a-z]{3}\s\d+\s'
-        // Time followed by a space.
-        r'\d{2}:\d{2}:\d{2}\s'
-        // The time zone name followed by a space.
-        r'([A-Z]{3,5})\s'
-        // The year.
-        r'\d{4}$/'
-        '.exec(#.toString())',
-        d);
-    if (match != null) return match[1];
-
-    // IE 9 and Opera don't provide the zone name. We fall back to emitting the
-    // UTC/GMT offset.
-    // Example (IE9): Wed Nov 20 09:51:00 UTC+0100 2013
-    //       (Opera): Wed Nov 20 2013 11:03:38 GMT+0100
-    match = JS('JSArray|Null', r'/(?:GMT|UTC)[+-]\d{4}/.exec(#.toString())', d);
-    if (match != null) return match[0];
-    return "";
-  }
-
-  static int getTimeZoneOffsetInMinutes(DateTime receiver) {
-    // Note that JS and Dart disagree on the sign of the offset.
-    return -JS('int', r'#.getTimezoneOffset()', lazyAsJsDate(receiver));
-  }
-
-  static num valueFromDecomposedDate(
-      @nullCheck int years,
-      @nullCheck int month,
-      @nullCheck int day,
-      @nullCheck int hours,
-      @nullCheck int minutes,
-      @nullCheck int seconds,
-      @nullCheck int milliseconds,
-      @nullCheck bool isUtc) {
-    final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000;
-    var jsMonth = month - 1;
-    num value;
-    if (isUtc) {
-      value = JS('!', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth, day,
-          hours, minutes, seconds, milliseconds);
-    } else {
-      value = JS('!', r'new Date(#, #, #, #, #, #, #).valueOf()', years,
-          jsMonth, day, hours, minutes, seconds, milliseconds);
-    }
-    if (value.isNaN ||
-        value < -MAX_MILLISECONDS_SINCE_EPOCH ||
-        value > MAX_MILLISECONDS_SINCE_EPOCH) {
-      return null;
-    }
-    if (years <= 0 || years < 100) return patchUpY2K(value, years, isUtc);
-    return value;
-  }
-
-  static num patchUpY2K(value, years, isUtc) {
-    var date = JS('', r'new Date(#)', value);
-    if (isUtc) {
-      JS('', r'#.setUTCFullYear(#)', date, years);
-    } else {
-      JS('', r'#.setFullYear(#)', date, years);
-    }
-    return JS('!', r'#.valueOf()', date);
-  }
-
-  // Lazily keep a JS Date stored in the JS object.
-  static lazyAsJsDate(DateTime receiver) {
-    if (JS('bool', r'#.date === (void 0)', receiver)) {
-      JS('void', r'#.date = new Date(#)', receiver,
-          receiver.millisecondsSinceEpoch);
-    }
-    return JS('var', r'#.date', receiver);
-  }
-
-  // The getters for date and time parts below add a positive integer to ensure
-  // that the result is really an integer, because the JavaScript implementation
-  // may return -0.0 instead of 0.
-
-  static int getYear(DateTime receiver) {
-    return (receiver.isUtc)
-        ? JS('int', r'(#.getUTCFullYear() + 0)', lazyAsJsDate(receiver))
-        : JS('int', r'(#.getFullYear() + 0)', lazyAsJsDate(receiver));
-  }
-
-  static int getMonth(DateTime receiver) {
-    return (receiver.isUtc)
-        ? JS('int', r'#.getUTCMonth() + 1', lazyAsJsDate(receiver))
-        : JS('int', r'#.getMonth() + 1', lazyAsJsDate(receiver));
-  }
-
-  static int getDay(DateTime receiver) {
-    return (receiver.isUtc)
-        ? JS('int', r'(#.getUTCDate() + 0)', lazyAsJsDate(receiver))
-        : JS('int', r'(#.getDate() + 0)', lazyAsJsDate(receiver));
-  }
-
-  static int getHours(DateTime receiver) {
-    return (receiver.isUtc)
-        ? JS('int', r'(#.getUTCHours() + 0)', lazyAsJsDate(receiver))
-        : JS('int', r'(#.getHours() + 0)', lazyAsJsDate(receiver));
-  }
-
-  static int getMinutes(DateTime receiver) {
-    return (receiver.isUtc)
-        ? JS('int', r'(#.getUTCMinutes() + 0)', lazyAsJsDate(receiver))
-        : JS('int', r'(#.getMinutes() + 0)', lazyAsJsDate(receiver));
-  }
-
-  static int getSeconds(DateTime receiver) {
-    return (receiver.isUtc)
-        ? JS('int', r'(#.getUTCSeconds() + 0)', lazyAsJsDate(receiver))
-        : JS('int', r'(#.getSeconds() + 0)', lazyAsJsDate(receiver));
-  }
-
-  static int getMilliseconds(DateTime receiver) {
-    return (receiver.isUtc)
-        ? JS('int', r'(#.getUTCMilliseconds() + 0)', lazyAsJsDate(receiver))
-        : JS('int', r'(#.getMilliseconds() + 0)', lazyAsJsDate(receiver));
-  }
-
-  static int getWeekday(DateTime receiver) {
-    int weekday = (receiver.isUtc)
-        ? JS('int', r'#.getUTCDay() + 0', lazyAsJsDate(receiver))
-        : JS('int', r'#.getDay() + 0', lazyAsJsDate(receiver));
-    // Adjust by one because JS weeks start on Sunday.
-    return (weekday + 6) % 7 + 1;
-  }
-
-  static num valueFromDateString(str) {
-    if (str is! String) throw argumentErrorValue(str);
-    num value = JS('!', r'Date.parse(#)', str);
-    if (value.isNaN) throw argumentErrorValue(str);
-    return value;
-  }
-
-  static getProperty(object, key) {
-    if (object == null || object is bool || object is num || object is String) {
-      throw argumentErrorValue(object);
-    }
-    return JS('var', '#[#]', object, key);
-  }
-
-  static void setProperty(object, key, value) {
-    if (object == null || object is bool || object is num || object is String) {
-      throw argumentErrorValue(object);
-    }
-    JS('void', '#[#] = #', object, key, value);
-  }
-}
-
-/**
- * Diagnoses an indexing error. Returns the ArgumentError or RangeError that
- * describes the problem.
- */
-@NoInline()
-Error diagnoseIndexError(indexable, int index) {
-  int length = indexable.length;
-  // The following returns the same error that would be thrown by calling
-  // [RangeError.checkValidIndex] with no optional parameters provided.
-  if (index < 0 || index >= length) {
-    return RangeError.index(index, indexable, 'index', null, length);
-  }
-  // The above should always match, but if it does not, use the following.
-  return RangeError.value(index, 'index');
-}
-
-/**
- * Diagnoses a range error. Returns the ArgumentError or RangeError that
- * describes the problem.
- */
-@NoInline()
-Error diagnoseRangeError(int start, int end, int length) {
-  if (start == null) {
-    return ArgumentError.value(start, 'start');
-  }
-  if (start < 0 || start > length) {
-    return RangeError.range(start, 0, length, 'start');
-  }
-  if (end != null) {
-    if (end < start || end > length) {
-      return RangeError.range(end, start, length, 'end');
-    }
-  }
-  // The above should always match, but if it does not, use the following.
-  return ArgumentError.value(end, "end");
-}
-
-@notNull
-int stringLastIndexOfUnchecked(receiver, element, start) =>
-    JS('int', r'#.lastIndexOf(#, #)', receiver, element, start);
-
-/// 'factory' for constructing ArgumentError.value to keep the call sites small.
-@NoInline()
-ArgumentError argumentErrorValue(object) {
-  return ArgumentError.value(object);
-}
-
-void throwArgumentErrorValue(value) {
-  throw argumentErrorValue(value);
-}
-
-checkInt(value) {
-  if (value is! int) throw argumentErrorValue(value);
-  return value;
-}
-
-throwRuntimeError(message) {
-  throw RuntimeError(message);
-}
-
-throwAbstractClassInstantiationError(className) {
-  throw AbstractClassInstantiationError(className);
-}
-
-@NoInline()
-throwConcurrentModificationError(collection) {
-  throw ConcurrentModificationError(collection);
-}
-
-class JsNoSuchMethodError extends Error implements NoSuchMethodError {
-  final String _message;
-  final String _method;
-  final String _receiver;
-
-  JsNoSuchMethodError(this._message, match)
-      : _method = match == null ? null : JS('String|Null', '#.method', match),
-        _receiver =
-            match == null ? null : JS('String|Null', '#.receiver', match);
-
-  String toString() {
-    if (_method == null) return 'NoSuchMethodError: $_message';
-    if (_receiver == null) {
-      return "NoSuchMethodError: method not found: '$_method' ($_message)";
-    }
-    return "NoSuchMethodError: "
-        "method not found: '$_method' on '$_receiver' ($_message)";
-  }
-}
-
-class UnknownJsTypeError extends Error {
-  final String _message;
-
-  UnknownJsTypeError(this._message);
-
-  String toString() => _message.isEmpty ? 'Error' : 'Error: $_message';
-}
-
-/**
- * Called by generated code to build a map literal. [keyValuePairs] is
- * a list of key, value, key, value, ..., etc.
- */
-fillLiteralMap(keyValuePairs, Map result) {
-  // TODO(johnniwinther): Use JSArray to optimize this code instead of calling
-  // [getLength] and [getIndex].
-  int index = 0;
-  int length = getLength(keyValuePairs);
-  while (index < length) {
-    var key = getIndex(keyValuePairs, index++);
-    var value = getIndex(keyValuePairs, index++);
-    result[key] = value;
-  }
-  return result;
-}
-
-bool jsHasOwnProperty(var jsObject, String property) {
-  return JS('bool', r'#.hasOwnProperty(#)', jsObject, property);
-}
-
-jsPropertyAccess(var jsObject, String property) {
-  return JS('var', r'#[#]', jsObject, property);
-}
-
-/**
- * Called at the end of unaborted switch cases to get the singleton
- * FallThroughError exception that will be thrown.
- */
-getFallThroughError() => FallThroughErrorImplementation();
-
-/**
- * A metadata annotation describing the types instantiated by a native element.
- *
- * The annotation is valid on a native method and a field of a native class.
- *
- * By default, a field of a native class is seen as an instantiation point for
- * all native classes that are a subtype of the field's type, and a native
- * method is seen as an instantiation point fo all native classes that are a
- * subtype of the method's return type, or the argument types of the declared
- * type of the method's callback parameter.
- *
- * An @[Creates] annotation overrides the default set of instantiated types.  If
- * one or more @[Creates] annotations are present, the type of the native
- * element is ignored, and the union of @[Creates] annotations is used instead.
- * The names in the strings are resolved and the program will fail to compile
- * with dart2js if they do not name types.
- *
- * The argument to [Creates] is a string.  The string is parsed as the names of
- * one or more types, separated by vertical bars `|`.  There are some special
- * names:
- *
- * * `=Object`. This means 'exactly Object', which is a plain JavaScript object
- *   with properties and none of the subtypes of Object.
- *
- * Example: we may know that a method always returns a specific implementation:
- *
- *     @Creates('_NodeList')
- *     List<Node> getElementsByTagName(String tag) native;
- *
- * Useful trick: A method can be marked as not instantiating any native classes
- * with the annotation `@Creates('Null')`.  This is useful for fields on native
- * classes that are used only in Dart code.
- *
- *     @Creates('Null')
- *     var _cachedFoo;
- */
-class Creates {
-  final String types;
-  const Creates(this.types);
-}
-
-/**
- * A metadata annotation describing the types returned or yielded by a native
- * element.
- *
- * The annotation is valid on a native method and a field of a native class.
- *
- * By default, a native method or field is seen as returning or yielding all
- * subtypes if the method return type or field type.  This annotation allows a
- * more precise set of types to be specified.
- *
- * See [Creates] for the syntax of the argument.
- *
- * Example: IndexedDB keys are numbers, strings and JavaScript Arrays of keys.
- *
- *     @Returns('String|num|JSExtendableArray')
- *     dynamic key;
- *
- *     // Equivalent:
- *     @Returns('String') @Returns('num') @Returns('JSExtendableArray')
- *     dynamic key;
- */
-class Returns {
-  final String types;
-  const Returns(this.types);
-}
-
-/**
- * A metadata annotation placed on native methods and fields of native classes
- * to specify the JavaScript name.
- *
- * This example declares a Dart field + getter + setter called `$dom_title` that
- * corresponds to the JavaScript property `title`.
- *
- *     class Document native "*Foo" {
- *       @JSName('title')
- *       String $dom_title;
- *     }
- */
-class JSName {
-  final String name;
-  const JSName(this.name);
-}
-
-/**
- * Special interface recognized by the compiler and implemented by DOM
- * objects that support integer indexing. This interface is not
- * visible to anyone, and is only injected into special libraries.
- */
-abstract class JavaScriptIndexingBehavior<E> {}
-
-// TODO(lrn): These exceptions should be implemented in core.
-// When they are, remove the 'Implementation' here.
-
-/// Thrown by type assertions that fail.
-class TypeErrorImpl extends Error implements TypeError {
-  final String message;
-
-  TypeErrorImpl(this.message);
-
-  String toString() => message;
-}
-
-/// Thrown by the 'as' operator if the cast isn't valid.
-class CastErrorImpl extends Error implements CastError {
-  final String message;
-
-  CastErrorImpl(this.message);
-
-  String toString() => message;
-}
-
-class FallThroughErrorImplementation extends FallThroughError {
-  String toString() => "Switch case fall-through.";
-}
-
-/**
- * Error thrown when a runtime error occurs.
- */
-class RuntimeError extends Error {
-  final message;
-  RuntimeError(this.message);
-  String toString() => "RuntimeError: $message";
-}
-
-/// Error thrown by DDC when an `assert()` fails (with or without a message).
-class AssertionErrorImpl extends AssertionError {
-  AssertionErrorImpl(message) : super(message);
-  String toString() =>
-      "Assertion failed: " +
-      (message != null ? Error.safeToString(message) : "is not true");
-}
-
-/**
- * Creates a random number with 64 bits of randomness.
- *
- * This will be truncated to the 53 bits available in a double.
- */
-int random64() {
-  // TODO(lrn): Use a secure random source.
-  int int32a = JS("int", "(Math.random() * 0x100000000) >>> 0");
-  int int32b = JS("int", "(Math.random() * 0x100000000) >>> 0");
-  return int32a + int32b * 0x100000000;
-}
-
-class BooleanConversionAssertionError extends AssertionError {
-  toString() => 'Failed assertion: boolean expression must not be null';
-}
-
-// Hook to register new global object.  This is invoked from dart:html
-// whenever a new window is accessed for the first time.
-void registerGlobalObject(object) {
-  try {
-    if (dart.polyfill(object)) {
-      dart.applyAllExtensions(object);
-    }
-  } catch (e) {
-    // This may fail due to cross-origin errors.  In that case, we shouldn't
-    // need to polyfill as we can't get objects from that frame.
-
-    // TODO(vsm): Detect this more robustly - ideally before we try to polyfill.
-  }
-}
-
-/// Expose browser JS classes.
-void applyExtension(name, nativeObject) {
-  dart.applyExtension(name, nativeObject);
-}
-
-/// Used internally by DDC to map ES6 symbols to Dart.
-class PrivateSymbol implements Symbol {
-  // TODO(jmesserly): could also get this off the native symbol instead of
-  // storing it. Mirrors already does this conversion.
-  final String _name;
-  final Object _nativeSymbol;
-
-  const PrivateSymbol(this._name, this._nativeSymbol);
-
-  static String getName(Symbol symbol) => (symbol as PrivateSymbol)._name;
-
-  static Object getNativeSymbol(Symbol symbol) {
-    if (symbol is PrivateSymbol) return symbol._nativeSymbol;
-    return null;
-  }
-
-  bool operator ==(other) =>
-      other is PrivateSymbol &&
-      _name == other._name &&
-      identical(_nativeSymbol, other._nativeSymbol);
-
-  get hashCode => _name.hashCode;
-
-  // TODO(jmesserly): is this equivalent to _nativeSymbol toString?
-  toString() => 'Symbol("$_name")';
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart b/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart
deleted file mode 100644
index 9206685..0000000
--- a/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart
+++ /dev/null
@@ -1,253 +0,0 @@
-// 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.
-
-part of dart._js_helper;
-
-// Helper method used by internal libraries.
-regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp;
-
-/**
- * Returns a native version of the RegExp with the global flag set.
- *
- * The RegExp's `lastIndex` property is zero when it is returned.
- *
- * The returned regexp is shared, and its `lastIndex` property may be
- * modified by other uses, so the returned regexp must be used immediately
- * when it's returned, with no user-provided code run in between.
- */
-regExpGetGlobalNative(JSSyntaxRegExp regexp) {
-  var nativeRegexp = regexp._nativeGlobalVersion;
-  JS("void", "#.lastIndex = 0", nativeRegexp);
-  return nativeRegexp;
-}
-
-/**
- * Computes the number of captures in a regexp.
- *
- * This currently involves creating a new RegExp object with a different
- * source and running it against the empty string (the last part is usually
- * fast).
- *
- * The JSSyntaxRegExp could cache the result, and set the cache any time
- * it finds a match.
- */
-int regExpCaptureCount(JSSyntaxRegExp regexp) {
-  var nativeAnchoredRegExp = regexp._nativeAnchoredVersion;
-  JSExtendableArray match =
-      JS('JSExtendableArray', "#.exec('')", nativeAnchoredRegExp);
-  // The native-anchored regexp always have one capture more than the original,
-  // and always matches the empty string.
-  return match.length - 2;
-}
-
-class JSSyntaxRegExp implements RegExp {
-  final String pattern;
-  final _nativeRegExp;
-  var _nativeGlobalRegExp;
-  var _nativeAnchoredRegExp;
-
-  String toString() => "RegExp/$pattern/";
-
-  JSSyntaxRegExp(String source,
-      {bool multiLine = false, bool caseSensitive = true})
-      : this.pattern = source,
-        this._nativeRegExp =
-            makeNative(source, multiLine, caseSensitive, false);
-
-  get _nativeGlobalVersion {
-    if (_nativeGlobalRegExp != null) return _nativeGlobalRegExp;
-    return _nativeGlobalRegExp =
-        makeNative(pattern, _isMultiLine, _isCaseSensitive, true);
-  }
-
-  get _nativeAnchoredVersion {
-    if (_nativeAnchoredRegExp != null) return _nativeAnchoredRegExp;
-    // An "anchored version" of a regexp is created by adding "|()" to the
-    // source. This means that the regexp always matches at the first position
-    // that it tries, and you can see if the original regexp matched, or it
-    // was the added zero-width match that matched, by looking at the last
-    // capture. If it is a String, the match participated, otherwise it didn't.
-    return _nativeAnchoredRegExp =
-        makeNative("$pattern|()", _isMultiLine, _isCaseSensitive, true);
-  }
-
-  bool get _isMultiLine => JS("bool", "#.multiline", _nativeRegExp);
-  bool get _isCaseSensitive => JS("bool", "!#.ignoreCase", _nativeRegExp);
-
-  static makeNative(@nullCheck String source, bool multiLine,
-      bool caseSensitive, bool global) {
-    String m = multiLine ? 'm' : '';
-    String i = caseSensitive ? '' : 'i';
-    String g = global ? 'g' : '';
-    // We're using the JavaScript's try catch instead of the Dart one
-    // to avoid dragging in Dart runtime support just because of using
-    // RegExp.
-    var regexp = JS(
-        '',
-        '(function() {'
-        'try {'
-        'return new RegExp(#, # + # + #);'
-        '} catch (e) {'
-        'return e;'
-        '}'
-        '})()',
-        source,
-        m,
-        i,
-        g);
-    if (JS('bool', '# instanceof RegExp', regexp)) return regexp;
-    // The returned value is the JavaScript exception. Turn it into a
-    // Dart exception.
-    String errorMessage = JS('String', r'String(#)', regexp);
-    throw FormatException("Illegal RegExp pattern: $source, $errorMessage");
-  }
-
-  Match firstMatch(@nullCheck String string) {
-    List m = JS('JSExtendableArray|Null', r'#.exec(#)', _nativeRegExp, string);
-    if (m == null) return null;
-    return _MatchImplementation(this, JSArray<String>.of(m));
-  }
-
-  @notNull
-  bool hasMatch(@nullCheck String string) {
-    return JS('bool', r'#.test(#)', _nativeRegExp, string);
-  }
-
-  String stringMatch(String string) {
-    var match = firstMatch(string);
-    if (match != null) return match.group(0);
-    return null;
-  }
-
-  Iterable<Match> allMatches(@nullCheck String string,
-      [@nullCheck int start = 0]) {
-    if (start < 0 || start > string.length) {
-      throw RangeError.range(start, 0, string.length);
-    }
-    return _AllMatchesIterable(this, string, start);
-  }
-
-  Match _execGlobal(String string, int start) {
-    Object regexp = _nativeGlobalVersion;
-    JS("void", "#.lastIndex = #", regexp, start);
-    List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string);
-    if (match == null) return null;
-    return _MatchImplementation(this, JSArray<String>.of(match));
-  }
-
-  Match _execAnchored(String string, int start) {
-    Object regexp = _nativeAnchoredVersion;
-    JS("void", "#.lastIndex = #", regexp, start);
-    List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string);
-    if (match == null) return null;
-    // If the last capture group participated, the original regexp did not
-    // match at the start position.
-    if (match[match.length - 1] != null) return null;
-    match.length -= 1;
-    return _MatchImplementation(this, JSArray<String>.of(match));
-  }
-
-  Match matchAsPrefix(String string, [int start = 0]) {
-    if (start < 0 || start > string.length) {
-      throw RangeError.range(start, 0, string.length);
-    }
-    return _execAnchored(string, start);
-  }
-
-  bool get isMultiLine => _isMultiLine;
-  bool get isCaseSensitive => _isCaseSensitive;
-}
-
-class _MatchImplementation implements RegExpMatch {
-  final Pattern pattern;
-  // Contains a JS RegExp match object.
-  // It is an Array of String values with extra "index" and "input" properties.
-  final List<String> _match;
-
-  _MatchImplementation(this.pattern, this._match) {
-    assert(JS("var", "#.input", _match) is String);
-    assert(JS("var", "#.index", _match) is int);
-  }
-
-  String get input => JS("String", "#.input", _match);
-  int get start => JS("int", "#.index", _match);
-  int get end => start + _match[0].length;
-
-  String group(int index) => _match[index];
-  String operator [](int index) => group(index);
-  int get groupCount => _match.length - 1;
-
-  List<String> groups(List<int> groups) {
-    List<String> out = [];
-    for (int i in groups) {
-      out.add(group(i));
-    }
-    return out;
-  }
-
-  String namedGroup(String name) {
-    var groups = JS('Object', '#.groups', _match);
-    if (groups != null) {
-      var result = JS('String|Null', '#[#]', groups, name);
-      if (result != null || JS('bool', '# in #', name, groups)) {
-        return result;
-      }
-    }
-    throw ArgumentError.value(name, "name", "Not a capture group name");
-  }
-
-  Iterable<String> get groupNames {
-    var groups = JS('Object', '#.groups', _match);
-    if (groups != null) {
-      var keys = JSArray<String>.of(JS('', 'Object.keys(#)', groups));
-      return SubListIterable(keys, 0, null);
-    }
-    return Iterable.empty();
-  }
-}
-
-class _AllMatchesIterable extends IterableBase<Match> {
-  final JSSyntaxRegExp _re;
-  final String _string;
-  final int _start;
-
-  _AllMatchesIterable(this._re, this._string, this._start);
-
-  Iterator<Match> get iterator => _AllMatchesIterator(_re, _string, _start);
-}
-
-class _AllMatchesIterator implements Iterator<Match> {
-  final JSSyntaxRegExp _regExp;
-  String _string;
-  int _nextIndex;
-  Match _current;
-
-  _AllMatchesIterator(this._regExp, this._string, this._nextIndex);
-
-  Match get current => _current;
-
-  bool moveNext() {
-    if (_string == null) return false;
-    if (_nextIndex <= _string.length) {
-      var match = _regExp._execGlobal(_string, _nextIndex);
-      if (match != null) {
-        _current = match;
-        int nextIndex = match.end;
-        if (match.start == nextIndex) {
-          nextIndex++;
-        }
-        _nextIndex = nextIndex;
-        return true;
-      }
-    }
-    _current = null;
-    _string = null; // Marks iteration as ended.
-    return false;
-  }
-}
-
-/** Find the first match of [regExp] in [string] at or after [start]. */
-Match firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) {
-  return regExp._execGlobal(string, start);
-}
diff --git a/pkg/dev_compiler/tool/kernel_sdk.dart b/pkg/dev_compiler/tool/kernel_sdk.dart
index 2827fbe..0366522 100755
--- a/pkg/dev_compiler/tool/kernel_sdk.dart
+++ b/pkg/dev_compiler/tool/kernel_sdk.dart
@@ -14,8 +14,14 @@
 import 'package:dev_compiler/src/kernel/command.dart';
 import 'package:dev_compiler/src/kernel/compiler.dart';
 import 'package:front_end/src/api_unstable/ddc.dart'
-    show CompilerOptions, kernelForComponent;
+    show
+        CompilerOptions,
+        kernelForComponent,
+        DiagnosticMessage,
+        printDiagnosticMessage,
+        Severity;
 import 'package:kernel/kernel.dart';
+import 'package:kernel/target/targets.dart';
 import 'package:path/path.dart' as path;
 
 Future main(List<String> args) async {
@@ -37,14 +43,25 @@
   }
 
   var librarySpecPath = parserOptions['libraries'] as String;
+  var packagesPath = path.join(ddcPath, '../../.packages');
 
-  var target = DevCompilerTarget();
+  var target = DevCompilerTarget(TargetFlags());
+  void onDiagnostic(DiagnosticMessage message) {
+    printDiagnosticMessage(message, print);
+    if (message.severity == Severity.error ||
+        message.severity == Severity.internalProblem) {
+      exitCode = 1;
+    }
+  }
+
   var options = CompilerOptions()
     ..compileSdk = true
-    // TODO(sigmund): remove this unnecessary option when possible.
+    // TODO(sigmund): remove these two unnecessary options when possible.
     ..sdkRoot = Uri.base
+    ..packagesFileUri = Uri.base.resolveUri(Uri.file(packagesPath))
     ..librariesSpecificationUri = Uri.base.resolveUri(Uri.file(librarySpecPath))
-    ..target = target;
+    ..target = target
+    ..onDiagnostic = onDiagnostic;
 
   var inputs = target.extraRequiredLibraries.map(Uri.parse).toList();
   var component = await kernelForComponent(inputs, options);
diff --git a/pkg/dev_compiler/tool/patch_sdk.dart b/pkg/dev_compiler/tool/patch_sdk.dart
index e6d123b..c890b2e 100755
--- a/pkg/dev_compiler/tool/patch_sdk.dart
+++ b/pkg/dev_compiler/tool/patch_sdk.dart
@@ -9,6 +9,7 @@
 import 'dart:io';
 import 'dart:math' as math;
 
+// ignore: deprecated_member_use
 import 'package:analyzer/analyzer.dart'
     show parseCompilationUnit, parseDirectives;
 import 'package:analyzer/dart/ast/ast.dart';
@@ -21,9 +22,12 @@
   var self = path.relative(path.fromUri(Platform.script));
   if (argv.length < 3) {
     var toolDir = path.relative(path.dirname(path.fromUri(Platform.script)));
+    var dartDir = path.dirname(path
+        .dirname(path.dirname(path.dirname(path.fromUri(Platform.script)))));
 
     var repoExample = path.join(toolDir, '..', '..', '..');
-    var patchExample = path.join(toolDir, 'input_sdk');
+    var patchExample =
+        path.join(dartDir, 'sdk', 'lib', '_internal', 'js_dev_runtime');
     var outExample =
         path.relative(path.normalize(path.join('gen', 'patched_sdk')));
 
@@ -270,7 +274,7 @@
   void _maybePatch(Declaration node) {
     if (node is FieldDeclaration) return;
 
-    Token externalKeyword = (node as dynamic).externalKeyword;
+    var externalKeyword = (node as dynamic).externalKeyword as Token;
     if (externalKeyword == null) return;
 
     var name = _qualifiedName(node);
@@ -360,7 +364,7 @@
     result = "${parent.name.name}.";
   }
 
-  SimpleIdentifier name = (node as dynamic).name;
+  var name = (node as dynamic).name as SimpleIdentifier;
   if (name != null) result += name.name;
 
   // Make sure setters and getters don't collide.
@@ -391,7 +395,7 @@
   /// Creates a new transaction.
   StringEditBuffer(this.original);
 
-  bool get hasEdits => _edits.length > 0;
+  bool get hasEdits => _edits.isNotEmpty;
 
   /// Edit the original text, replacing text on the range [begin] and
   /// exclusive [end] with the [replacement] string.
@@ -415,9 +419,10 @@
   ///
   /// Throws [UnsupportedError] if the edits were overlapping. If no edits were
   /// made, the original string will be returned.
+  @override
   String toString() {
     var sb = StringBuffer();
-    if (_edits.length == 0) return original;
+    if (_edits.isEmpty) return original;
 
     // Sort edits by start location.
     _edits.sort();
@@ -461,8 +466,10 @@
 
   int get length => end - begin;
 
+  @override
   String toString() => '(Edit @ $begin,$end: "$replace")';
 
+  @override
   int compareTo(_StringEdit other) {
     int diff = begin - other.begin;
     if (diff != 0) return diff;
diff --git a/pkg/dev_compiler/web/main.dart b/pkg/dev_compiler/web/main.dart
index 67a02bd..df7682f 100755
--- a/pkg/dev_compiler/web/main.dart
+++ b/pkg/dev_compiler/web/main.dart
@@ -17,7 +17,7 @@
 external set setUpCompilerInBrowser(Function function);
 
 Future<dynamic> _setUpCompilerInBrowser;
-main() {
+void main() {
   var args = ['compile'];
 
   // Avoid race condition when users try to call $setUpDartDevCompilerInBrowser
diff --git a/pkg/dev_compiler/web/stack_trace_mapper.dart b/pkg/dev_compiler/web/stack_trace_mapper.dart
index de9e2b6..7fa1dc1 100644
--- a/pkg/dev_compiler/web/stack_trace_mapper.dart
+++ b/pkg/dev_compiler/web/stack_trace_mapper.dart
@@ -66,6 +66,7 @@
 
   List toJson() => _bundle.toJson();
 
+  @override
   SourceMapSpan spanFor(int line, int column,
       {Map<String, SourceFile> files, String uri}) {
     if (uri == null) {
@@ -111,7 +112,7 @@
   _mapping = LazyMapping(provider);
 }
 
-main() {
+void main() {
   // Register with DDC.
   dartStackTraceUtility = DartStackTraceUtility(
       mapper: allowInterop(mapper),
diff --git a/pkg/dev_compiler/web/web_command.dart b/pkg/dev_compiler/web/web_command.dart
index 2904b5a..2a7496d 100644
--- a/pkg/dev_compiler/web/web_command.dart
+++ b/pkg/dev_compiler/web/web_command.dart
@@ -59,8 +59,10 @@
 
 /// The command for invoking the modular compiler.
 class WebCompileCommand extends Command {
+  @override
   get name => 'compile';
 
+  @override
   get description => 'Compile a set of Dart files into a JavaScript module.';
   final MessageHandler messageHandler;
 
@@ -146,7 +148,7 @@
       var bytes = summaryBytes[i];
 
       // Packages with no dart source files will have empty invalid summaries.
-      if (bytes.length == 0) continue;
+      if (bytes.isEmpty) continue;
 
       var moduleId = moduleIds[i];
       var url = '/$moduleId.api.ds';
@@ -164,7 +166,7 @@
       var uri = Uri.parse(url);
       var base = path.basename(url);
       var parts = uri.pathSegments;
-      var match = null;
+      var match;
       int bestScore = 0;
       for (var candidate in summaryData.uriToSummaryPath.keys) {
         if (path.basename(candidate) != base) continue;
@@ -306,5 +308,6 @@
 
 /// Thrown when the input source code has errors.
 class CompileErrorException implements Exception {
+  @override
   toString() => '\nPlease fix all errors before compiling (warnings are okay).';
 }
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index d0615fd..6428f9b 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -2,13 +2,19 @@
 // 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.
 
-// TODO(askesc): Generate this file from a flag specification.
+// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Instead modify 'tools/experimental_features.yaml' and run
+// 'pkg/front_end/tool/fasta generate-experimental-flags' to update.
 
 enum ExperimentalFlag {
   constantUpdate2018,
   controlFlowCollections,
+  extensionMethods,
+  nonNullable,
   setLiterals,
   spreadCollections,
+  tripleShift,
 }
 
 ExperimentalFlag parseExperimentalFlag(String flag) {
@@ -17,10 +23,16 @@
       return ExperimentalFlag.constantUpdate2018;
     case "control-flow-collections":
       return ExperimentalFlag.controlFlowCollections;
+    case "extension-methods":
+      return ExperimentalFlag.extensionMethods;
+    case "non-nullable":
+      return ExperimentalFlag.nonNullable;
     case "set-literals":
       return ExperimentalFlag.setLiterals;
     case "spread-collections":
       return ExperimentalFlag.spreadCollections;
+    case "triple-shift":
+      return ExperimentalFlag.tripleShift;
   }
   return null;
 }
@@ -28,6 +40,9 @@
 const Map<ExperimentalFlag, bool> defaultExperimentalFlags = {
   ExperimentalFlag.constantUpdate2018: false,
   ExperimentalFlag.controlFlowCollections: true,
+  ExperimentalFlag.extensionMethods: false,
+  ExperimentalFlag.nonNullable: false,
   ExperimentalFlag.setLiterals: true,
   ExperimentalFlag.spreadCollections: true,
+  ExperimentalFlag.tripleShift: false,
 };
diff --git a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
index 6f37ab2..c9969c5 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -11,10 +11,13 @@
 
 import 'package:kernel/target/targets.dart' show Target;
 
-import '../api_prototype/compiler_options.dart' show CompilerOptions;
+import '../api_prototype/compiler_options.dart'
+    show CompilerOptions, parseExperimentalFlags;
 
 import '../api_prototype/diagnostic_message.dart' show DiagnosticMessageHandler;
 
+import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
+
 import '../api_prototype/file_system.dart' show FileSystem;
 
 import '../base/processed_options.dart' show ProcessedOptions;
@@ -23,9 +26,7 @@
 
 import '../fasta/incremental_compiler.dart' show IncrementalCompiler;
 
-import '../fasta/kernel/utils.dart' show serializeComponent;
-
-import '../kernel_generator_impl.dart' show generateKernel;
+import '../kernel_generator_impl.dart' show CompilerResult, generateKernel;
 
 import 'compiler_state.dart'
     show InitializedCompilerState, WorkerInputComponent, digestsEqual;
@@ -43,6 +44,8 @@
 
 export 'compiler_state.dart' show InitializedCompilerState;
 
+import 'util.dart' show equalMaps;
+
 /// Initializes the compiler for a modular build.
 ///
 /// Re-uses cached components from [_workerInputCache], and reloads them
@@ -56,8 +59,12 @@
     Map<Uri, List<int>> workerInputDigests,
     Target target,
     FileSystem fileSystem,
+    Iterable<String> experiments,
     bool outlineOnly) async {
-  List<int> sdkDigest = workerInputDigests[sdkSummary];
+  final List<int> sdkDigest = workerInputDigests[sdkSummary];
+  if (sdkDigest == null) {
+    throw new StateError("Expected to get digest for $sdkSummary");
+  }
   IncrementalCompiler incrementalCompiler;
   CompilerOptions options;
   ProcessedOptions processedOpts;
@@ -65,19 +72,27 @@
   Map<Uri, WorkerInputComponent> workerInputCache =
       oldState?.workerInputCache ?? new Map<Uri, WorkerInputComponent>();
   bool startOver = false;
+  Map<ExperimentalFlag, bool> experimentalFlags =
+      parseExperimentalFlags(experiments, (e) => throw e);
 
   if (oldState == null ||
       oldState.incrementalCompiler == null ||
-      oldState.incrementalCompiler.outlineOnly != outlineOnly) {
-    // No previous state.
+      oldState.incrementalCompiler.outlineOnly != outlineOnly ||
+      !equalMaps(oldState.options.experimentalFlags, experimentalFlags)) {
+    // No - or immediately not correct - previous state.
     startOver = true;
+
+    // We'll load a new sdk, anything loaded already will have a wrong root.
+    workerInputCache.clear();
   } else {
     // We do have a previous state.
     cachedSdkInput = workerInputCache[sdkSummary];
     if (cachedSdkInput == null ||
-        !digestsEqual(cachedSdkInput.digest, workerInputDigests[sdkSummary])) {
+        !digestsEqual(cachedSdkInput.digest, sdkDigest)) {
       // The sdk is out of date.
       startOver = true;
+      // We'll load a new sdk, anything loaded already will have a wrong root.
+      workerInputCache.clear();
     }
   }
 
@@ -104,36 +119,44 @@
   } else {
     options = oldState.options;
     processedOpts = oldState.processedOpts;
-
     var sdkComponent = cachedSdkInput.component;
     // Reset the state of the component.
     for (var lib in sdkComponent.libraries) {
       lib.isExternal = cachedSdkInput.externalLibs.contains(lib.importUri);
     }
+
+    // Make sure the canonical name root knows about the sdk - otherwise we
+    // won't be able to link to it when loading more outlines.
     sdkComponent.adoptChildren();
+
+    // TODO(jensj): This is - at least currently - neccessary,
+    // although it's not entirely obvious why.
+    // It likely has to do with several outlines containing the same libraries.
+    // Once that stops (and we check for it) we can probably remove this,
+    // and instead only do it when about to reuse an outline in the
+    // 'inputSummaries.add(component);' line further down.
     for (WorkerInputComponent cachedInput in workerInputCache.values) {
       cachedInput.component.adoptChildren();
     }
-    sdkComponent.unbindCanonicalNames();
-    sdkComponent.computeCanonicalNames();
 
     // Reuse the incremental compiler, but reset as needed.
     incrementalCompiler = oldState.incrementalCompiler;
     incrementalCompiler.invalidateAllSources();
     options.packagesFileUri = packagesFile;
     options.fileSystem = fileSystem;
+    processedOpts.clearFileSystemCache();
   }
 
   // Then read all the input summary components.
-  // The nameRoot from the sdk was either just created or just unbound.
-  // If just unbound, only the sdk stuff is bound. Either way, don't clear it
-  // again and bind as much as possible before loading new stuff!
   CanonicalName nameRoot = cachedSdkInput.component.root;
   final inputSummaries = <Component>[];
   List<Uri> loadFromDill = new List<Uri>();
   for (Uri summary in summaryInputs) {
     var cachedInput = workerInputCache[summary];
     var summaryDigest = workerInputDigests[summary];
+    if (summaryDigest == null) {
+      throw new StateError("Expected to get digest for $summary");
+    }
     if (cachedInput == null ||
         cachedInput.component.root != nameRoot ||
         !digestsEqual(cachedInput.digest, summaryDigest)) {
@@ -144,21 +167,21 @@
       for (var lib in component.libraries) {
         lib.isExternal = cachedInput.externalLibs.contains(lib.importUri);
       }
-      // We don't unbind as the root was unbound already. We do have to compute
-      // the canonical names though, to rebind everything in the component.
-      component.adoptChildren();
-      component.computeCanonicalNames();
       inputSummaries.add(component);
     }
   }
 
   for (int i = 0; i < loadFromDill.length; i++) {
     Uri summary = loadFromDill[i];
-    var summaryDigest = workerInputDigests[summary];
+    List<int> summaryDigest = workerInputDigests[summary];
+    if (summaryDigest == null) {
+      throw new StateError("Expected to get digest for $summary");
+    }
     WorkerInputComponent cachedInput = WorkerInputComponent(
         summaryDigest,
         await processedOpts.loadComponent(
-            await fileSystem.entityForUri(summary).readAsBytes(), nameRoot));
+            await fileSystem.entityForUri(summary).readAsBytes(), nameRoot,
+            alwaysCreateNewNamedNodes: true));
     workerInputCache[summary] = cachedInput;
     inputSummaries.add(cachedInput.component);
   }
@@ -178,7 +201,8 @@
     List<Uri> summaryInputs,
     List<Uri> linkedInputs,
     Target target,
-    FileSystem fileSystem) async {
+    FileSystem fileSystem,
+    Iterable<String> experiments) async {
   // TODO(sigmund): use incremental compiler when it supports our use case.
   // Note: it is common for the summary worker to invoke the compiler with the
   // same input summary URIs, but with different contents, so we'd need to be
@@ -192,16 +216,17 @@
     ..linkedDependencies = linkedInputs
     ..target = target
     ..fileSystem = fileSystem
-    ..environmentDefines = const {};
+    ..environmentDefines = const {}
+    ..experimentalFlags = parseExperimentalFlags(experiments, (e) => throw e);
 
   ProcessedOptions processedOpts = new ProcessedOptions(options: options);
 
   return new InitializedCompilerState(options, processedOpts);
 }
 
-Future<List<int>> compile(InitializedCompilerState compilerState,
+Future<CompilerResult> _compile(InitializedCompilerState compilerState,
     List<Uri> inputs, DiagnosticMessageHandler diagnosticMessageHandler,
-    {bool summaryOnly}) async {
+    {bool summaryOnly, bool includeOffsets: true}) {
   summaryOnly ??= true;
   CompilerOptions options = compilerState.options;
   options..onDiagnostic = diagnosticMessageHandler;
@@ -210,11 +235,27 @@
   processedOpts.inputs.clear();
   processedOpts.inputs.addAll(inputs);
 
-  var result = await generateKernel(processedOpts,
-      buildSummary: summaryOnly, buildComponent: !summaryOnly);
+  return generateKernel(processedOpts,
+      buildSummary: summaryOnly,
+      buildComponent: !summaryOnly,
+      includeOffsets: includeOffsets);
+}
+
+Future<List<int>> compileSummary(InitializedCompilerState compilerState,
+    List<Uri> inputs, DiagnosticMessageHandler diagnosticMessageHandler,
+    {bool includeOffsets: false}) async {
+  var result = await _compile(compilerState, inputs, diagnosticMessageHandler,
+      summaryOnly: true, includeOffsets: includeOffsets);
+  return result?.summary;
+}
+
+Future<Component> compileComponent(InitializedCompilerState compilerState,
+    List<Uri> inputs, DiagnosticMessageHandler diagnosticMessageHandler) async {
+  var result = await _compile(compilerState, inputs, diagnosticMessageHandler,
+      summaryOnly: false);
 
   var component = result?.component;
-  if (component != null && !summaryOnly) {
+  if (component != null) {
     for (var lib in component.libraries) {
       if (!inputs.contains(lib.importUri)) {
         // Excluding the library also means that their canonical names will not
@@ -226,9 +267,5 @@
       }
     }
   }
-
-  return summaryOnly
-      ? result?.summary
-      : serializeComponent(result?.component,
-          filter: (library) => inputs.contains(library.importUri));
+  return component;
 }
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index 8ec174d..e6f8ac6 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -32,6 +32,8 @@
 
 import 'compiler_state.dart' show InitializedCompilerState;
 
+import 'util.dart' show equalLists, equalMaps;
+
 export '../api_prototype/compiler_options.dart'
     show CompilerOptions, parseExperimentalFlags;
 
@@ -116,30 +118,13 @@
     Map<ExperimentalFlag, bool> experimentalFlags,
     bool verify: false,
     bool enableAsserts: false}) {
-  bool mapEqual(Map<ExperimentalFlag, bool> a, Map<ExperimentalFlag, bool> b) {
-    if (a == null || b == null) return a == b;
-    if (a.length != b.length) return false;
-    for (var flag in a.keys) {
-      if (!b.containsKey(flag) || a[flag] != b[flag]) return false;
-    }
-    return true;
-  }
-
-  bool listEqual(List<Uri> a, List<Uri> b) {
-    if (a.length != b.length) return false;
-    for (int i = 0; i < a.length; ++i) {
-      if (a[i] != b[i]) return false;
-    }
-    return true;
-  }
-
   linkedDependencies.sort((a, b) => a.toString().compareTo(b.toString()));
 
   if (oldState != null &&
       oldState.options.packagesFileUri == packagesFileUri &&
       oldState.options.librariesSpecificationUri == librariesSpecificationUri &&
-      listEqual(oldState.options.linkedDependencies, linkedDependencies) &&
-      mapEqual(oldState.options.experimentalFlags, experimentalFlags)) {
+      equalLists(oldState.options.linkedDependencies, linkedDependencies) &&
+      equalMaps(oldState.options.experimentalFlags, experimentalFlags)) {
     return oldState;
   }
 
diff --git a/pkg/front_end/lib/src/api_unstable/ddc.dart b/pkg/front_end/lib/src/api_unstable/ddc.dart
index 4542aa3..4c2076b 100644
--- a/pkg/front_end/lib/src/api_unstable/ddc.dart
+++ b/pkg/front_end/lib/src/api_unstable/ddc.dart
@@ -29,6 +29,8 @@
 import 'compiler_state.dart'
     show InitializedCompilerState, WorkerInputComponent, digestsEqual;
 
+import 'util.dart' show equalLists, equalMaps;
+
 export '../api_prototype/compiler_options.dart' show CompilerOptions;
 
 export '../api_prototype/diagnostic_message.dart' show DiagnosticMessage;
@@ -71,6 +73,8 @@
 
 Future<InitializedCompilerState> initializeCompiler(
     InitializedCompilerState oldState,
+    bool compileSdk,
+    Uri sdkRoot,
     Uri sdkSummary,
     Uri packagesFile,
     Uri librariesSpecificationUri,
@@ -79,29 +83,14 @@
     {FileSystem fileSystem,
     Map<ExperimentalFlag, bool> experiments}) async {
   inputSummaries.sort((a, b) => a.toString().compareTo(b.toString()));
-  bool listEqual(List<Uri> a, List<Uri> b) {
-    if (a.length != b.length) return false;
-    for (int i = 0; i < a.length; ++i) {
-      if (a[i] != b[i]) return false;
-    }
-    return true;
-  }
-
-  bool mapEqual(Map<ExperimentalFlag, bool> a, Map<ExperimentalFlag, bool> b) {
-    if (a == null || b == null) return a == b;
-    if (a.length != b.length) return false;
-    for (var flag in a.keys) {
-      if (!b.containsKey(flag) || a[flag] != b[flag]) return false;
-    }
-    return true;
-  }
 
   if (oldState != null &&
+      oldState.options.compileSdk == compileSdk &&
       oldState.options.sdkSummary == sdkSummary &&
       oldState.options.packagesFileUri == packagesFile &&
       oldState.options.librariesSpecificationUri == librariesSpecificationUri &&
-      listEqual(oldState.options.inputSummaries, inputSummaries) &&
-      mapEqual(oldState.options.experimentalFlags, experiments)) {
+      equalLists(oldState.options.inputSummaries, inputSummaries) &&
+      equalMaps(oldState.options.experimentalFlags, experiments)) {
     // Reuse old state.
 
     // These libraries are marked external when compiling. If not un-marking
@@ -118,6 +107,8 @@
   }
 
   CompilerOptions options = new CompilerOptions()
+    ..compileSdk = compileSdk
+    ..sdkRoot = sdkRoot
     ..sdkSummary = sdkSummary
     ..packagesFileUri = packagesFile
     ..inputSummaries = inputSummaries
@@ -134,6 +125,8 @@
 Future<InitializedCompilerState> initializeIncrementalCompiler(
     InitializedCompilerState oldState,
     List<Component> doneInputSummaries,
+    bool compileSdk,
+    Uri sdkRoot,
     Uri sdkSummary,
     Uri packagesFile,
     Uri librariesSpecificationUri,
@@ -154,9 +147,12 @@
 
   if (oldState == null ||
       oldState.incrementalCompiler == null ||
+      oldState.options.compileSdk != compileSdk ||
       cachedSdkInput == null) {
     // No previous state.
     options = new CompilerOptions()
+      ..compileSdk = compileSdk
+      ..sdkRoot = sdkRoot
       ..sdkSummary = sdkSummary
       ..packagesFileUri = packagesFile
       ..inputSummaries = inputSummaries
@@ -165,6 +161,9 @@
       ..fileSystem = fileSystem ?? StandardFileSystem.instance;
     if (experiments != null) options.experimentalFlags = experiments;
 
+    // We'll load a new sdk, anything loaded already will have a wrong root.
+    workerInputCache.clear();
+
     processedOpts = new ProcessedOptions(options: options);
 
     cachedSdkInput = new WorkerInputComponent(null /* not compared anyway */,
@@ -180,17 +179,17 @@
     for (var lib in cachedSdkInput.component.libraries) {
       lib.isExternal = false;
     }
+    cachedSdkInput.component.adoptChildren();
     for (WorkerInputComponent cachedInput in workerInputCache.values) {
       cachedInput.component.adoptChildren();
     }
-    cachedSdkInput.component.unbindCanonicalNames();
-    cachedSdkInput.component.computeCanonicalNames();
 
     // Reuse the incremental compiler, but reset as needed.
     incrementalCompiler = oldState.incrementalCompiler;
     incrementalCompiler.invalidateAllSources();
     options.packagesFileUri = packagesFile;
     options.fileSystem = fileSystem;
+    processedOpts.clearFileSystemCache();
   }
   InitializedCompilerState compilerState = new InitializedCompilerState(
       options, processedOpts,
@@ -219,9 +218,6 @@
       for (var lib in component.libraries) {
         lib.isExternal = cachedInput.externalLibs.contains(lib.importUri);
       }
-      // We don't unbind as the root was unbound already. We do have to
-      // compute the canonical names though, to rebind everything in the
-      // component.
       component.computeCanonicalNames();
       doneInputSummaries[i] = component;
     }
@@ -232,7 +228,9 @@
     Uri summary = inputSummaries[index];
     List<int> data = await fileSystem.entityForUri(summary).readAsBytes();
     WorkerInputComponent cachedInput = WorkerInputComponent(
-        data, await compilerState.processedOpts.loadComponent(data, nameRoot));
+        data,
+        await compilerState.processedOpts
+            .loadComponent(data, nameRoot, alwaysCreateNewNamedNodes: true));
     workerInputCache[summary] = cachedInput;
     doneInputSummaries[index] = cachedInput.component;
   }
diff --git a/pkg/front_end/lib/src/api_unstable/util.dart b/pkg/front_end/lib/src/api_unstable/util.dart
new file mode 100644
index 0000000..146ddd0
--- /dev/null
+++ b/pkg/front_end/lib/src/api_unstable/util.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, 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.
+
+bool equalLists<T>(List<T> a, List<T> b) {
+  if (identical(a, b)) return true;
+  if (a == null || b == null) return false;
+  if (a.length != b.length) return false;
+  for (int i = 0; i < a.length; ++i) {
+    if (a[i] != b[i]) return false;
+  }
+  return true;
+}
+
+bool equalMaps<K, V>(Map<K, V> a, Map<K, V> b) {
+  if (identical(a, b)) return true;
+  if (a == null || b == null) return false;
+  if (a.length != b.length) return false;
+  for (K key in a.keys) {
+    if (!b.containsKey(key) || a[key] != b[key]) return false;
+  }
+  return true;
+}
diff --git a/pkg/front_end/lib/src/base/errors.dart b/pkg/front_end/lib/src/base/errors.dart
index 2fbd323..735fa5d 100644
--- a/pkg/front_end/lib/src/base/errors.dart
+++ b/pkg/front_end/lib/src/base/errors.dart
@@ -26,10 +26,10 @@
   final String correction;
 
   /**
-   * The URL of a page containing documentation for errors with this code, or
-   * `null` if there is no known documentation.
+   * Return `true` if diagnostics with this code have documentation for them
+   * that has been published.
    */
-  final String url;
+  final bool hasPublishedDocs;
 
   /**
    * Whether this error is caused by an unresolved identifier.
@@ -42,7 +42,8 @@
    * template. The correction associated with the error will be created from the
    * given [correction] template.
    */
-  const ErrorCode(this.name, this.message, [this.correction, this.url])
+  const ErrorCode(this.name, this.message,
+      [this.correction, this.hasPublishedDocs = false])
       : isUnresolvedIdentifier = false;
 
   /**
@@ -52,7 +53,9 @@
    * given [correction] template.
    */
   const ErrorCode.temporary(this.name, this.message,
-      {this.correction, this.isUnresolvedIdentifier: false, this.url});
+      {this.correction,
+      this.isUnresolvedIdentifier: false,
+      this.hasPublishedDocs = false});
 
   /**
    * The severity of the error.
@@ -69,6 +72,12 @@
    */
   String get uniqueName => "$runtimeType.$name";
 
+  /**
+   * Return a URL that can be used to access documentation for diagnostics with
+   * this code, or `null` if there is no published documentation.
+   */
+  String get url => null;
+
   @override
   String toString() => uniqueName;
 }
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 9cfba14..a3e6cbe 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -316,7 +316,6 @@
     assert(defaultExperimentalFlags.containsKey(flag),
         "No default value for $flag.");
     // TODO(askesc): Determine default flag value from specification file.
-    if (flag == ExperimentalFlag.setLiterals) return true;
     return _raw.experimentalFlags[flag] ?? defaultExperimentalFlags[flag];
   }
 
@@ -379,12 +378,16 @@
   }
 
   /// Helper to load a .dill file from [uri] using the existing [nameRoot].
-  Component loadComponent(List<int> bytes, CanonicalName nameRoot) {
+  Component loadComponent(List<int> bytes, CanonicalName nameRoot,
+      {bool alwaysCreateNewNamedNodes}) {
     Component component =
         target.configureComponent(new Component(nameRoot: nameRoot));
     // TODO(ahe): Pass file name to BinaryBuilder.
     // TODO(ahe): Control lazy loading via an option.
-    new BinaryBuilder(bytes, filename: null, disableLazyReading: false)
+    new BinaryBuilder(bytes,
+            filename: null,
+            disableLazyReading: false,
+            alwaysCreateNewNamedNodes: alwaysCreateNewNamedNodes)
         .readComponent(component);
     return component;
   }
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 05441e7..199e65c 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -77,6 +77,8 @@
     return library.partOfLibrary ?? library;
   }
 
+  void buildOutlineExpressions(LibraryBuilder library) {}
+
   /// Registers a constructor redirection for this class and returns true if
   /// this redirection gives rise to a cycle that has not been reported before.
   bool checkConstructorCyclic(String source, String target) {
@@ -124,7 +126,7 @@
     return constructors.lookup(name, charOffset, uri);
   }
 
-  void forEach(void f(String name, MemberBuilder builder)) {
+  void forEach(void f(String name, Declaration builder)) {
     scope.forEach(f);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
index f456149..33f875f 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -12,7 +12,7 @@
 }
 
 class EnumConstantInfo {
-  final List<MetadataBuilder<TypeBuilder>> metadata;
+  final List<MetadataBuilder> metadata;
   final String name;
   final int charOffset;
   final String documentationComment;
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index 9dbca65..51e0852 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -235,6 +235,8 @@
   }
 
   void recordAccess(int charOffset, int length, Uri fileUri) {}
+
+  void buildOutlineExpressions() {}
 }
 
 class LibraryLocalDeclarationIterator implements Iterator<Declaration> {
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 827fe5f..0b99bf5 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -37,6 +37,8 @@
     }
   }
 
+  void buildOutlineExpressions(LibraryBuilder library) {}
+
   @override
   String get fullNameForErrors => name;
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
index cb656b4..f43b4a6 100644
--- a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
@@ -4,54 +4,6 @@
 
 library fasta.metadata_builder;
 
-import 'builder.dart' show Declaration, TypeBuilder;
-
-import 'constructor_reference_builder.dart' show ConstructorReferenceBuilder;
-
-abstract class MetadataBuilder<T extends TypeBuilder> {
-  final int charOffset;
-
-  MetadataBuilder(Declaration parent, this.charOffset);
-
-  factory MetadataBuilder.fromConstructor(
-      ConstructorReferenceBuilder constructorReference,
-      List<Object> arguments,
-      Declaration parent,
-      int charOffset) {
-    return new ConstructorMetadataBuilder<T>(
-        constructorReference, arguments, parent, charOffset);
-  }
-
-  factory MetadataBuilder.fromExpression(
-      Object expression, String postfix, Declaration parent, int charOffset) {
-    return new ExpressionMetadataBuilder<T>(
-        expression, postfix, parent, charOffset);
-  }
-}
-
-class ConstructorMetadataBuilder<T extends TypeBuilder>
-    extends MetadataBuilder<T> {
-  final ConstructorReferenceBuilder constructorReference;
-
-  final List<Object> arguments;
-
-  ConstructorMetadataBuilder(this.constructorReference, this.arguments,
-      Declaration parent, int charOffset)
-      : super(parent, charOffset);
-}
-
-/// Expression metadata (without arguments).
-///
-/// Matches this grammar rule:
-///
-///    '@' qualified (‘.’ identifier)?
-class ExpressionMetadataBuilder<T extends TypeBuilder>
-    extends MetadataBuilder<T> {
-  final Object qualified;
-
-  final String identifier;
-
-  ExpressionMetadataBuilder(
-      this.qualified, this.identifier, Declaration parent, int charOffset)
-      : super(parent, charOffset);
+abstract class MetadataBuilder {
+  int get charOffset;
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 1a17041..9644f64 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -82,9 +82,11 @@
           typeName = name;
           typeNameOffset = charOffset;
         }
-        declaration = buildInvalidType(templateTypeArgumentsOnTypeVariable
-            .withArguments(typeName)
-            .withLocation(fileUri, typeNameOffset, typeName.length));
+        Message message =
+            templateTypeArgumentsOnTypeVariable.withArguments(typeName);
+        library.addProblem(message, typeNameOffset, typeName.length, fileUri);
+        declaration = buildInvalidType(
+            message.withLocation(fileUri, typeNameOffset, typeName.length));
       }
       return;
     } else if (member is TypeDeclarationBuilder) {
@@ -120,20 +122,22 @@
     }
     int length =
         name is Identifier ? name.endCharOffset - charOffset : flatName.length;
+    Message message = template.withArguments(flatName);
+    library.addProblem(message, charOffset, length, fileUri, context: context);
     declaration = buildInvalidType(
-        template
-            .withArguments(flatName)
-            .withLocation(fileUri, charOffset, length),
+        message.withLocation(fileUri, charOffset, length),
         context: context);
   }
 
   @override
-  void check(int charOffset, Uri fileUri) {
+  void check(LibraryBuilder library, int charOffset, Uri fileUri) {
     if (arguments != null &&
         arguments.length != declaration.typeVariablesCount) {
-      declaration = buildInvalidType(templateTypeArgumentMismatch
-          .withArguments(declaration.typeVariablesCount)
-          .withLocation(fileUri, charOffset, noLength));
+      Message message = templateTypeArgumentMismatch
+          .withArguments(declaration.typeVariablesCount);
+      library.addProblem(message, charOffset, noLength, fileUri);
+      declaration =
+          buildInvalidType(message.withLocation(fileUri, charOffset, noLength));
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
index e941212..c2e5255 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
@@ -19,7 +19,7 @@
   final List<TypeVariableBuilder<T, R>> typeVariables;
 
   TypeAliasBuilder(
-      List<MetadataBuilder<T>> metadata,
+      List<MetadataBuilder> metadata,
       String name,
       this.typeVariables,
       this.type,
diff --git a/pkg/front_end/lib/src/fasta/builder/type_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
index bebc060..0758872 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
@@ -18,7 +18,7 @@
       Scope scope, int charOffset, Uri fileUri, LibraryBuilder library) {}
 
   /// See `UnresolvedType.checkType`.
-  void check(int charOffset, Uri fileUri) {}
+  void check(LibraryBuilder library, int charOffset, Uri fileUri) {}
 
   /// See `UnresolvedType.normalizeType`.
   void normalize(int charOffset, Uri fileUri) {}
diff --git a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
index b28cf9f..32a5a31 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
@@ -14,7 +14,7 @@
 
 abstract class TypeDeclarationBuilder<T extends TypeBuilder, R>
     extends ModifierBuilder {
-  final List<MetadataBuilder<T>> metadata;
+  final List<MetadataBuilder> metadata;
 
   final int modifiers;
 
diff --git a/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart b/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
index c716335..9c8ce77 100644
--- a/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
+++ b/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
@@ -18,7 +18,9 @@
       builder.resolveIn(scope, charOffset, fileUri, library);
 
   /// Performs checks on the type after it's resolved.
-  void checkType() => builder.check(charOffset, fileUri);
+  void checkType(LibraryBuilder library) {
+    return builder.check(library, charOffset, fileUri);
+  }
 
   /// Normalizes the type arguments in accordance with Dart 1 semantics.
   void normalizeType() => builder.normalize(charOffset, fileUri);
diff --git a/pkg/front_end/lib/src/fasta/command_line_reporting.dart b/pkg/front_end/lib/src/fasta/command_line_reporting.dart
index fbfd9df..15778043 100644
--- a/pkg/front_end/lib/src/fasta/command_line_reporting.dart
+++ b/pkg/front_end/lib/src/fasta/command_line_reporting.dart
@@ -12,7 +12,7 @@
 
 import 'dart:typed_data' show Uint8List;
 
-import 'package:kernel/ast.dart' show Location;
+import 'package:kernel/ast.dart' show Location, TreeNode;
 
 import '../compute_platform_binaries_location.dart' show translateSdk;
 
@@ -77,6 +77,9 @@
       String path = relativizeUri(translateSdk(message.uri));
       int offset = message.charOffset;
       location ??= (offset == -1 ? null : getLocation(message.uri, offset));
+      if (location?.line == TreeNode.noOffset) {
+        location = null;
+      }
       String sourceLine = getSourceLine(location);
       if (sourceLine == null) {
         sourceLine = "";
@@ -110,7 +113,7 @@
         sourceLine = "\n$sourceLine\n$pointer";
       }
       String position =
-          location == null ? ":1" : ":${location.line}:${location.column}";
+          location == null ? "" : ":${location.line}:${location.column}";
       return "$path$position: $text$sourceLine";
     } else {
       return text;
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index c76a2bc..f1d4ff2 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -24,6 +24,7 @@
 import '../fasta_codes.dart'
     show
         Message,
+        noLength,
         templateDuplicatedDeclaration,
         templateTypeNotFound,
         templateUnspecified;
@@ -61,6 +62,8 @@
   /// [../kernel/kernel_library_builder.dart].
   Map<String, String> unserializableExports;
 
+  bool exportsAlreadyFinalized = false;
+
   DillLibraryBuilder(this.library, this.loader)
       : super(library.fileUri, new Scope.top(), new Scope.top());
 
@@ -160,11 +163,10 @@
     // mapping `k` to `d` is added to the exported namespace of `L` unless a
     // top-level declaration with the name `k` exists in `L`.
     if (builder.parent == this) return builder;
+    Message message = templateDuplicatedDeclaration.withArguments(name);
+    addProblem(message, charOffset, name.length, fileUri);
     return new KernelInvalidTypeBuilder(
-        name,
-        templateDuplicatedDeclaration
-            .withArguments(name)
-            .withLocation(fileUri, charOffset, name.length));
+        name, message.withLocation(fileUri, charOffset, name.length));
   }
 
   @override
@@ -173,6 +175,8 @@
   }
 
   void finalizeExports() {
+    if (exportsAlreadyFinalized) return;
+    exportsAlreadyFinalized = true;
     unserializableExports?.forEach((String name, String messageText) {
       Declaration declaration;
       switch (name) {
@@ -187,6 +191,7 @@
           Message message = messageText == null
               ? templateTypeNotFound.withArguments(name)
               : templateUnspecified.withArguments(messageText);
+          addProblem(message, -1, noLength, null);
           declaration =
               new KernelInvalidTypeBuilder(name, message.withoutLocation());
       }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
index cfd35fb..a648190 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
@@ -57,10 +57,8 @@
   }
 
   bool get isSynthetic {
-    // TODO(ahe): Kernel should eventually support a synthetic bit.
-    return isConstructor &&
-        name == "" &&
-        (charOffset == parent.charOffset || charOffset == -1);
+    final Member member = this.member;
+    return member is Constructor && member.isSynthetic;
   }
 
   bool get isField => member is Field;
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
index 6667e06..8247cbf 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
@@ -23,7 +23,7 @@
       : super(null, typedef.name, null, null, parent, typedef.fileOffset,
             typedef);
 
-  List<MetadataBuilder<KernelTypeBuilder>> get metadata {
+  List<MetadataBuilder> get metadata {
     return unimplemented("metadata", -1, null);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 668da04..e61cf1c 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -233,16 +233,6 @@
     message: r"""`assert` can't have more than two arguments.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAsyncAsIdentifier = messageAsyncAsIdentifier;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAsyncAsIdentifier = const MessageCode(
-    "AsyncAsIdentifier",
-    analyzerCodes: <String>["ASYNC_KEYWORD_USED_AS_IDENTIFIER"],
-    message:
-        r"""'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeAwaitAsIdentifier = messageAwaitAsIdentifier;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -273,6 +263,34 @@
     message: r"""'await' can only be used in 'async' or 'async*' methods.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, String name2)>
+    templateBadTypeVariableInSupertype =
+    const Template<Message Function(String name, String name2)>(
+        messageTemplate:
+            r"""Found unsupported uses of '#name' in supertype '#name2'.""",
+        withArguments: _withArgumentsBadTypeVariableInSupertype);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    codeBadTypeVariableInSupertype =
+    const Code<Message Function(String name, String name2)>(
+  "BadTypeVariableInSupertype",
+  templateBadTypeVariableInSupertype,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsBadTypeVariableInSupertype(String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeBadTypeVariableInSupertype,
+      message:
+          """Found unsupported uses of '${name}' in supertype '${name2}'.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         String name,
@@ -757,6 +775,36 @@
     tip: r"""Try replacing the colon with the keyword 'in'.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        String
+            string2)> templateConflictingModifiers = const Template<
+        Message Function(String string, String string2)>(
+    messageTemplate:
+        r"""Members can't be declared to be both '#string' and '#string2'.""",
+    tipTemplate: r"""Try removing one of the keywords.""",
+    withArguments: _withArgumentsConflictingModifiers);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeConflictingModifiers =
+    const Code<Message Function(String string, String string2)>(
+        "ConflictingModifiers", templateConflictingModifiers,
+        index: 59);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConflictingModifiers(String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeConflictingModifiers,
+      message:
+          """Members can't be declared to be both '${string}' and '${string2}'.""",
+      tip: """Try removing one of the keywords.""",
+      arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(String name)> templateConflictsWithConstructor =
     const Template<Message Function(String name)>(
         messageTemplate: r"""Conflicts with constructor '#name'.""",
@@ -920,17 +968,6 @@
     message: r"""This is the type variable.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstAndCovariant = messageConstAndCovariant;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstAndCovariant = const MessageCode(
-    "ConstAndCovariant",
-    index: 57,
-    message:
-        r"""Members can't be declared to be both 'const' and 'covariant'.""",
-    tip: r"""Try removing either the 'const' or 'covariant' keyword.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeConstAndFinal = messageConstAndFinal;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -940,15 +977,6 @@
     tip: r"""Try removing either the 'const' or 'final' keyword.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstAndVar = messageConstAndVar;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstAndVar = const MessageCode("ConstAndVar",
-    index: 59,
-    message: r"""Members can't be declared to be both 'const' and 'var'.""",
-    tip: r"""Try removing either the 'const' or 'var' keyword.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeConstClass = messageConstClass;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1476,36 +1504,6 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstEvalIterationInConstList =
-    messageConstEvalIterationInConstList;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstEvalIterationInConstList = const MessageCode(
-    "ConstEvalIterationInConstList",
-    analyzerCodes: <String>["NON_CONSTANT_LIST_ELEMENT"],
-    message: r"""Iteration can't be used in a constant list.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstEvalIterationInConstMap =
-    messageConstEvalIterationInConstMap;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstEvalIterationInConstMap = const MessageCode(
-    "ConstEvalIterationInConstMap",
-    analyzerCodes: <String>["NON_CONSTANT_MAP_ELEMENT"],
-    message: r"""Iteration can't be used in a constant map.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstEvalIterationInConstSet =
-    messageConstEvalIterationInConstSet;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstEvalIterationInConstSet = const MessageCode(
-    "ConstEvalIterationInConstSet",
-    analyzerCodes: <String>["NON_CONSTANT_SET_ELEMENT"],
-    message: r"""Iteration can't be used in a constant set.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(Constant _constant)>
     templateConstEvalKeyImplementsEqual =
     const Template<Message Function(Constant _constant)>(
@@ -1945,28 +1943,6 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCovariantAfterFinal = messageCovariantAfterFinal;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCovariantAfterFinal = const MessageCode(
-    "CovariantAfterFinal",
-    index: 65,
-    message:
-        r"""The modifier 'covariant' should be before the modifier 'final'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCovariantAfterVar = messageCovariantAfterVar;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCovariantAfterVar = const MessageCode(
-    "CovariantAfterVar",
-    index: 8,
-    message:
-        r"""The modifier 'covariant' should be before the modifier 'var'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeCovariantAndStatic = messageCovariantAndStatic;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2955,27 +2931,6 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedClassBodyToSkip =
-    const Template<Message Function(Token token)>(
-        messageTemplate:
-            r"""Expected a class or mixin body, but got '#lexeme'.""",
-        withArguments: _withArgumentsExpectedClassBodyToSkip);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Token token)> codeExpectedClassBodyToSkip =
-    const Code<Message Function(Token token)>(
-        "ExpectedClassBodyToSkip", templateExpectedClassBodyToSkip,
-        analyzerCodes: <String>["MISSING_CLASS_BODY"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedClassBodyToSkip(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeExpectedClassBodyToSkip,
-      message: """Expected a class or mixin body, but got '${lexeme}'.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(Token token)> templateExpectedClassMember =
     const Template<Message Function(Token token)>(
         messageTemplate: r"""Expected a class member, but got '#lexeme'.""",
@@ -2996,24 +2951,27 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedClassOrMixinBody =
-    const Template<Message Function(Token token)>(
+const Template<Message Function(String string)>
+    templateExpectedClassOrMixinBody =
+    const Template<Message Function(String string)>(
         messageTemplate:
-            r"""Expected a class or mixin body, but got '#lexeme'.""",
+            r"""A #string must have a body, even if it is empty.""",
+        tipTemplate: r"""Try adding an empty body.""",
         withArguments: _withArgumentsExpectedClassOrMixinBody);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Token token)> codeExpectedClassOrMixinBody =
-    const Code<Message Function(Token token)>(
+const Code<Message Function(String string)> codeExpectedClassOrMixinBody =
+    const Code<Message Function(String string)>(
         "ExpectedClassOrMixinBody", templateExpectedClassOrMixinBody,
-        analyzerCodes: <String>["MISSING_CLASS_BODY"]);
+        index: 8);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedClassOrMixinBody(Token token) {
-  String lexeme = token.lexeme;
+Message _withArgumentsExpectedClassOrMixinBody(String string) {
+  if (string.isEmpty) throw 'No string provided';
   return new Message(codeExpectedClassOrMixinBody,
-      message: """Expected a class or mixin body, but got '${lexeme}'.""",
-      arguments: {'token': token});
+      message: """A ${string} must have a body, even if it is empty.""",
+      tip: """Try adding an empty body.""",
+      arguments: {'string': string});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3042,7 +3000,7 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageExpectedElseOrComma = const MessageCode(
     "ExpectedElseOrComma",
-    index: 94,
+    index: 46,
     message: r"""Expected 'else' or comma.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3255,7 +3213,7 @@
 const Code<Message Function(String string)> codeExperimentNotEnabled =
     const Code<Message Function(String string)>(
         "ExperimentNotEnabled", templateExperimentNotEnabled,
-        index: 93);
+        index: 48);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsExperimentNotEnabled(String string) {
@@ -3358,39 +3316,6 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalAfterConst = messageExternalAfterConst;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalAfterConst = const MessageCode(
-    "ExternalAfterConst",
-    index: 46,
-    message:
-        r"""The modifier 'external' should be before the modifier 'const'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalAfterFactory = messageExternalAfterFactory;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalAfterFactory = const MessageCode(
-    "ExternalAfterFactory",
-    index: 47,
-    message:
-        r"""The modifier 'external' should be before the modifier 'factory'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalAfterStatic = messageExternalAfterStatic;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalAfterStatic = const MessageCode(
-    "ExternalAfterStatic",
-    index: 48,
-    message:
-        r"""The modifier 'external' should be before the modifier 'static'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeExternalClass = messageExternalClass;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6346,7 +6271,7 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageInvalidSuperInInitializer = const MessageCode(
     "InvalidSuperInInitializer",
-    index: 95,
+    index: 47,
     message:
         r"""Can only use 'super' in an initializer for calling the superclass constructor (e.g. 'super()' or 'super.namedConstructor()')""");
 
@@ -6366,7 +6291,7 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageInvalidThisInInitializer = const MessageCode(
     "InvalidThisInInitializer",
-    index: 96,
+    index: 65,
     message:
         r"""Can only use 'this' in an initializer for field initialization (e.g. 'this.x = something') and constructor redirection (e.g. 'this()' or 'this.namedConstructor())""");
 
@@ -7419,7 +7344,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageOnlyTry = const MessageCode("OnlyTry",
-    index: 92,
+    index: 20,
     message:
         r"""A try block must be followed by an 'on', 'catch', or 'finally' clause.""",
     tip:
@@ -8770,42 +8695,11 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageStackOverflow = const MessageCode("StackOverflow",
-    index: 91,
+    index: 19,
     message: r"""The file has too many nested expressions or statements.""",
     tip: r"""Try simplifying the code.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticAfterConst = messageStaticAfterConst;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticAfterConst = const MessageCode(
-    "StaticAfterConst",
-    index: 20,
-    message:
-        r"""The modifier 'static' should be before the modifier 'const'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticAfterFinal = messageStaticAfterFinal;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticAfterFinal = const MessageCode(
-    "StaticAfterFinal",
-    index: 19,
-    message:
-        r"""The modifier 'static' should be before the modifier 'final'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticAfterVar = messageStaticAfterVar;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticAfterVar = const MessageCode("StaticAfterVar",
-    index: 18,
-    message: r"""The modifier 'static' should be before the modifier 'var'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeStaticAndInstanceConflict =
     messageStaticAndInstanceConflict;
 
@@ -8878,7 +8772,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageSuperNullAware = const MessageCode("SuperNullAware",
-    index: 90,
+    index: 18,
     message:
         r"""The operator '?.' cannot be used with 'super' because 'super' cannot be null.""",
     tip: r"""Try replacing '?.' with '.'""");
@@ -9360,7 +9254,7 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageTypeBeforeFactory = const MessageCode(
     "TypeBeforeFactory",
-    index: 97,
+    index: 57,
     message: r"""Factory constructors cannot have a return type.""",
     tip: r"""Try removing the type appearing before 'factory'.""");
 
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 63f805f..87f7acd1 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -9,7 +9,11 @@
 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
 
 import 'package:kernel/binary/ast_from_binary.dart'
-    show BinaryBuilder, CanonicalNameError, InvalidKernelVersionError;
+    show
+        BinaryBuilder,
+        CanonicalNameError,
+        CanonicalNameSdkError,
+        InvalidKernelVersionError;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
@@ -96,6 +100,8 @@
   final Component componentToInitializeFrom;
   bool initializedFromDill = false;
   Uri previousPackagesUri;
+  Map<String, Uri> previousPackagesMap;
+  Map<String, Uri> currentPackagesMap;
   bool hasToCheckPackageUris = false;
   Map<Uri, List<DiagnosticMessageFromJson>> remainingComponentProblems =
       new Map<Uri, List<DiagnosticMessageFromJson>>();
@@ -137,6 +143,8 @@
       hasToCheckPackageUris = hasToCheckPackageUris || bypassCache;
       UriTranslator uriTranslator =
           await c.options.getUriTranslator(bypassCache: bypassCache);
+      previousPackagesMap = currentPackagesMap;
+      currentPackagesMap = uriTranslator.packages.asMap();
       ticker.logMs("Read packages file");
 
       if (dillLoadedData == null) {
@@ -157,7 +165,9 @@
               bytesLength =
                   prepareSummary(summaryBytes, uriTranslator, c, data);
 
-              if (e is InvalidKernelVersionError || e is PackageChangedError) {
+              if (e is InvalidKernelVersionError ||
+                  e is PackageChangedError ||
+                  e is CanonicalNameSdkError) {
                 // Don't report any warning.
               } else {
                 Uri gzInitializedFrom;
@@ -218,13 +228,30 @@
       List<LibraryBuilder> reusedLibraries = computeReusedLibraries(
           invalidatedUris, uriTranslator,
           notReused: notReusedLibraries);
-      Set<Uri> reusedLibraryUris =
-          new Set<Uri>.from(reusedLibraries.map((b) => b.uri));
-      for (Uri uri in new Set<Uri>.from(dillLoadedData.loader.builders.keys)
-        ..removeAll(reusedLibraryUris)) {
-        LibraryBuilder builder = dillLoadedData.loader.builders.remove(uri);
-        userBuilders?.remove(uri);
+
+      bool removedDillBuilders = false;
+      for (LibraryBuilder builder in notReusedLibraries) {
         CompilerContext.current.uriToSource.remove(builder.fileUri);
+
+        LibraryBuilder dillBuilder =
+            dillLoadedData.loader.builders.remove(builder.uri);
+        if (dillBuilder != null) {
+          removedDillBuilders = true;
+          userBuilders?.remove(builder.uri);
+        }
+
+        // Remove component problems for libraries we don't reuse.
+        if (remainingComponentProblems.isNotEmpty) {
+          Library lib = builder.target;
+          removeLibraryFromRemainingComponentProblems(lib, uriTranslator);
+        }
+      }
+
+      if (removedDillBuilders) {
+        dillLoadedData.loader.libraries.clear();
+        for (LibraryBuilder builder in dillLoadedData.loader.builders.values) {
+          dillLoadedData.loader.libraries.add(builder.target);
+        }
       }
 
       if (hasToCheckPackageUris) {
@@ -246,16 +273,6 @@
             .addAll(oldDillLoadedData.loader.libraries);
       }
 
-      for (LibraryBuilder builder in notReusedLibraries) {
-        Library lib = builder.target;
-        CompilerContext.current.uriToSource.remove(builder.fileUri);
-
-        // Remove component problems for libraries we don't reuse.
-        if (remainingComponentProblems.isNotEmpty) {
-          removeLibraryFromRemainingComponentProblems(lib, uriTranslator);
-        }
-      }
-
       if (hierarchy != null) {
         List<Library> removedLibraries = new List<Library>();
         for (LibraryBuilder builder in notReusedLibraries) {
@@ -271,7 +288,7 @@
             " of ${userCode.loader.builders.length} libraries");
       }
 
-      await loadEnsureLoadedComponents(reusedLibraryUris, reusedLibraries);
+      await loadEnsureLoadedComponents(reusedLibraries);
 
       KernelTarget userCodeOld = userCode;
       userCode = new KernelTarget(
@@ -389,13 +406,13 @@
 
   /// Internal method.
   Future loadEnsureLoadedComponents(
-      Set<Uri> reusedLibraryUris, List<LibraryBuilder> reusedLibraries) async {
+      List<LibraryBuilder> reusedLibraries) async {
     if (modulesToLoad != null) {
       bool loadedAnything = false;
       for (Component module in modulesToLoad) {
         bool usedComponent = false;
         for (Library lib in module.libraries) {
-          if (!reusedLibraryUris.contains(lib.importUri)) {
+          if (!dillLoadedData.loader.builders.containsKey(lib.importUri)) {
             dillLoadedData.loader.libraries.add(lib);
             dillLoadedData.addLibrary(lib);
             reusedLibraries.add(dillLoadedData.loader.read(lib.importUri, -1));
@@ -608,7 +625,7 @@
         c.options.fileSystem.entityForUri(initializeFromDillUri);
     if (await entity.exists()) {
       List<int> initializationBytes = await entity.readAsBytes();
-      if (initializationBytes != null) {
+      if (initializationBytes != null && initializationBytes.isNotEmpty) {
         ticker.logMs("Read $initializeFromDillUri");
         data.initializationBytes = initializationBytes;
 
@@ -730,8 +747,7 @@
           debugExprUri,
           userCode.loader,
           null,
-          library.scope.createNestedScope("expression"),
-          library.target);
+          library.scope.createNestedScope("expression"));
 
       if (library is DillLibraryBuilder) {
         for (LibraryDependency dependency in library.target.dependencies) {
@@ -792,6 +808,10 @@
       userCode.uriToSource.remove(debugExprUri);
       userCode.loader.sourceBytes.remove(debugExprUri);
 
+      // Make sure the library has a canonical name.
+      Component c = new Component(libraries: [debugLibrary.target]);
+      c.computeCanonicalNames();
+
       userCode.runProcedureTransformations(procedure);
 
       return procedure;
@@ -820,10 +840,21 @@
       if (importUri != fileUri && invalidatedUris.contains(fileUri)) {
         return true;
       }
-      if (hasToCheckPackageUris &&
-          importUri.scheme == "package" &&
-          uriTranslator.translate(importUri, false) != fileUri) {
-        return true;
+      if (hasToCheckPackageUris && importUri.scheme == "package") {
+        // Get package name, check if the base URI has changed for the package,
+        // if it has, translate the URI again,
+        // otherwise the URI cannot have changed.
+        String path = importUri.path;
+        int firstSlash = path.indexOf('/');
+        String packageName = path.substring(0, firstSlash);
+        if (previousPackagesMap == null ||
+            (previousPackagesMap[packageName] !=
+                currentPackagesMap[packageName])) {
+          Uri newFileUri = uriTranslator.translate(importUri, false);
+          if (newFileUri != fileUri) {
+            return true;
+          }
+        }
       }
       if (builders[importUri]?.isSynthetic ?? false) return true;
       return false;
@@ -859,9 +890,14 @@
       }
     }
 
-    userBuilders?.forEach(addBuilderAndInvalidateUris);
     if (userCode != null) {
+      // userCode already contains the builders from userBuilders.
       userCode.loader.builders.forEach(addBuilderAndInvalidateUris);
+    } else {
+      // userCode was null so we explicitly have to add the builders from
+      // userBuilders (which cannot be null as we checked initially that one of
+      // them was non-null).
+      userBuilders.forEach(addBuilderAndInvalidateUris);
     }
 
     recordInvalidatedImportUrisForTesting(invalidatedImportUris);
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 0430c9d..2599943 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -171,7 +171,7 @@
   @override
   final Uri uri;
 
-  final TypeInferrer _typeInferrer;
+  final TypeInferrer typeInferrer;
 
   @override
   final TypePromoter typePromoter;
@@ -262,7 +262,7 @@
       this.classBuilder,
       this.isInstanceMember,
       this.uri,
-      this._typeInferrer)
+      this.typeInferrer)
       : enableNative =
             library.loader.target.backendTarget.enableNative(library.uri),
         stringExpectedAfterNative =
@@ -271,7 +271,7 @@
             (library.uri.path == "_builtin" || library.uri.path == "ui"),
         needsImplicitSuperInitializer =
             coreTypes?.objectClass != classBuilder?.cls,
-        typePromoter = _typeInferrer?.typePromoter,
+        typePromoter = typeInferrer?.typePromoter,
         legacyMode = library.legacyMode,
         super(enclosingScope);
 
@@ -306,7 +306,7 @@
     return isInstanceMember || member is KernelConstructorBuilder;
   }
 
-  TypeEnvironment get typeEnvironment => _typeInferrer?.typeSchemaEnvironment;
+  TypeEnvironment get typeEnvironment => typeInferrer?.typeSchemaEnvironment;
 
   DartType get implicitTypeArgument =>
       legacyMode ? const DynamicType() : const ImplicitTypeArgument();
@@ -463,7 +463,7 @@
 
   void inferAnnotations(List<Expression> annotations) {
     if (annotations != null) {
-      _typeInferrer?.inferMetadata(this, annotations);
+      typeInferrer?.inferMetadata(this, annotations);
       library.loader.transformListPostInference(
           annotations, transformSetLiterals, transformCollections);
     }
@@ -509,7 +509,8 @@
       }
 
       ConstantContext savedConstantContext = pop();
-      if (expression is! StaticAccessGenerator) {
+      if (expression is! StaticAccessGenerator &&
+          expression is! VariableUseGenerator) {
         push(wrapInProblem(
             toValue(expression), fasta.messageExpressionNotMetadata, noLength));
       } else {
@@ -531,16 +532,26 @@
   }
 
   @override
-  void endTopLevelFields(Token staticToken, Token covariantToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
     debugEvent("TopLevelFields");
+    // TODO(danrubel): handle NNBD 'late' modifier
+    reportNonNullableModifierError(lateToken);
     push(count);
   }
 
   @override
-  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
-      int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     debugEvent("Fields");
+    // TODO(danrubel): handle NNBD 'late' modifier
+    reportNonNullableModifierError(lateToken);
     push(count);
   }
 
@@ -571,9 +582,13 @@
           // Duplicate definition. The field might not be the correct one,
           // so we skip inference of the initializer.
           // Error reporting and recovery is handled elsewhere.
+        } else if (field.target.initializer != null) {
+          // The initializer was already compiled (e.g., if it appear in the
+          // outline, like constant field initializers) so we do not need to
+          // perform type inference or transformations.
         } else {
           field.initializer = initializer;
-          _typeInferrer?.inferFieldInitializer(
+          typeInferrer?.inferFieldInitializer(
               this, field.builtType, initializer);
           library.loader.transformPostInference(
               field.target, transformSetLiterals, transformCollections);
@@ -590,23 +605,7 @@
       // `invalid-type`.
       buildDartType(pop()); // Type.
     }
-    List<Expression> annotations = pop();
-    if (annotations != null) {
-      inferAnnotations(annotations);
-      Field field = fields.first.target;
-      // The first (and often only field) will not get a clone.
-      for (int i = 0; i < annotations.length; i++) {
-        field.addAnnotation(annotations[i]);
-      }
-      for (int i = 1; i < fields.length; i++) {
-        // We have to clone the annotations on the remaining fields.
-        field = fields[i].target;
-        cloner ??= new CloneVisitor();
-        for (Expression annotation in annotations) {
-          field.addAnnotation(cloner.clone(annotation));
-        }
-      }
-    }
+    pop(); // Annotations.
 
     resolveRedirectingFactoryTargets();
     finishVariableMetadata();
@@ -716,7 +715,7 @@
       }
       initializer = buildInvalidInitializer(node, token.charOffset);
     }
-    _typeInferrer?.inferInitializer(this, initializer);
+    typeInferrer?.inferInitializer(this, initializer);
     if (member is KernelConstructorBuilder && !member.isExternal) {
       member.addInitializer(initializer, this);
     } else {
@@ -738,8 +737,8 @@
   }
 
   @override
-  void finishFunction(List<Expression> annotations, FormalParameters formals,
-      AsyncMarker asyncModifier, Statement body) {
+  void finishFunction(
+      FormalParameters formals, AsyncMarker asyncModifier, Statement body) {
     debugEvent("finishFunction");
     typePromoter?.finished();
 
@@ -757,7 +756,7 @@
                 null);
           }
           realParameter.initializer = initializer..parent = realParameter;
-          _typeInferrer?.inferParameterInitializer(
+          typeInferrer?.inferParameterInitializer(
               this, initializer, realParameter.type);
           library.loader.transformPostInference(
               realParameter, transformSetLiterals, transformCollections);
@@ -765,7 +764,7 @@
       }
     }
 
-    _typeInferrer?.inferFunctionBody(
+    typeInferrer?.inferFunctionBody(
         this, _computeReturnTypeContext(member), asyncModifier, body);
     if (body != null) {
       library.loader.transformPostInference(
@@ -890,11 +889,6 @@
           ..fileOffset = body.fileOffset;
       }
     }
-    Member target = builder.target;
-    inferAnnotations(annotations);
-    for (Expression annotation in annotations ?? const []) {
-      target.addAnnotation(annotation);
-    }
     if (builder is KernelConstructorBuilder) {
       finishConstructor(builder, asyncModifier);
     } else if (builder is KernelProcedureBuilder) {
@@ -917,7 +911,7 @@
       // set its inferredType field.  If type inference is disabled, reach to
       // the outtermost parent to check if the node is a dead code.
       if (invocation.parent == null) continue;
-      if (_typeInferrer != null) {
+      if (typeInferrer != null) {
         if (invocation is FactoryConstructorInvocationJudgment &&
             invocation.inferredType == null) {
           continue;
@@ -1128,7 +1122,7 @@
 
     ReturnJudgment fakeReturn = new ReturnJudgment(null, expression);
 
-    _typeInferrer?.inferFunctionBody(
+    typeInferrer?.inferFunctionBody(
         this, const DynamicType(), AsyncMarker.Sync, fakeReturn);
 
     return fakeReturn.expression;
@@ -1142,6 +1136,14 @@
     return expression;
   }
 
+  Expression parseAnnotation(Token token) {
+    Parser parser = new Parser(this);
+    token = parser.parseMetadata(parser.syntheticPreviousToken(token));
+    Expression annotation = pop();
+    checkEmpty(token.charOffset);
+    return annotation;
+  }
+
   void finishConstructor(
       KernelConstructorBuilder builder, AsyncMarker asyncModifier) {
     /// Quotes below are from [Dart Programming Language Specification, 4th
@@ -1489,7 +1491,7 @@
       int offset = candidate.fileOffset;
       Message contextMessage;
       int length = noLength;
-      if (offset == -1 && candidate is Constructor) {
+      if (candidate is Constructor && candidate.isSynthetic) {
         offset = candidate.enclosingClass.fileOffset;
         contextMessage = fasta.templateCandidateFoundIsDefaultConstructor
             .withArguments(candidate.enclosingClass.name);
@@ -1831,8 +1833,12 @@
         setter = declaration;
       } else if (declaration.isGetter) {
         setter = scope.lookupSetter(name, charOffset, uri);
-      } else if (declaration.isField && !declaration.isFinal) {
-        setter = declaration;
+      } else if (declaration.isField) {
+        if (declaration.isFinal || declaration.isConst) {
+          setter = scope.lookupSetter(name, charOffset, uri);
+        } else {
+          setter = declaration;
+        }
       }
       StaticAccessGenerator generator = new StaticAccessGenerator.fromBuilder(
           this, declaration, token, setter);
@@ -2130,8 +2136,11 @@
   }
 
   @override
-  void beginVariablesDeclaration(Token token, Token varFinalOrConst) {
+  void beginVariablesDeclaration(
+      Token token, Token lateToken, Token varFinalOrConst) {
     debugEvent("beginVariablesDeclaration");
+    // TODO(danrubel): handle NNBD 'late' modifier
+    reportNonNullableModifierError(lateToken);
     UnresolvedType<KernelTypeBuilder> type = pop();
     int modifiers = Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
     super.push(currentLocalVariableModifiers);
@@ -2317,8 +2326,7 @@
       return;
     }
 
-    if (constantContext != ConstantContext.none &&
-        !library.loader.target.enableConstantUpdate2018) {
+    if (constantContext != ConstantContext.none) {
       handleRecoverableError(
           fasta.templateCantUseControlFlowOrSpreadAsConstant
               .withArguments(forToken),
@@ -2691,14 +2699,15 @@
         String name = getNodeName(prefix);
         String displayName = debugName(name, suffix.lexeme);
         int offset = offsetForToken(beginToken);
+        Message message = fasta.templateNotAType.withArguments(displayName);
+        library.addProblem(
+            message, offset, lengthOfSpan(beginToken, suffix), uri);
         push(new UnresolvedType<KernelTypeBuilder>(
             new KernelNamedTypeBuilder(name, null)
               ..bind(new KernelInvalidTypeBuilder(
                   name,
-                  fasta.templateNotAType
-                      .withArguments(displayName)
-                      .withLocation(
-                          uri, offset, lengthOfSpan(beginToken, suffix)))),
+                  message.withLocation(
+                      uri, offset, lengthOfSpan(beginToken, suffix)))),
             offset,
             uri));
         return;
@@ -2717,6 +2726,8 @@
       }
     } else if (name is ProblemBuilder) {
       // TODO(ahe): Arguments could be passed here.
+      library.addProblem(
+          name.message, name.charOffset, name.name.length, name.fileUri);
       result = new KernelNamedTypeBuilder(name.name, null)
         ..bind(new KernelInvalidTypeBuilder(
             name.name,
@@ -2862,8 +2873,10 @@
   }
 
   @override
-  void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
-      Token varFinalOrConst) {
+  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+      Token covariantToken, Token varFinalOrConst) {
+    // TODO(danrubel): handle required token
+    reportNonNullableModifierError(requiredToken);
     push((covariantToken != null ? covariantMask : 0) |
         Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme));
   }
@@ -2974,7 +2987,7 @@
   }
 
   @override
-  void endFunctionTypedFormalParameter(Token nameToken) {
+  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
     debugEvent("FunctionTypedFormalParameter");
     if (inCatchClause || functionNestingLevel != 0) {
       exitLocalScope();
@@ -2982,6 +2995,7 @@
     FormalParameters formals = pop();
     UnresolvedType<KernelTypeBuilder> returnType = pop();
     List<KernelTypeVariableBuilder> typeVariables = pop();
+    reportErrorIfNullableType(question);
     UnresolvedType<KernelTypeBuilder> type =
         formals.toFunctionType(returnType, typeVariables);
     exitLocalScope();
@@ -4164,8 +4178,7 @@
       return;
     }
 
-    if (constantContext != ConstantContext.none &&
-        !library.loader.target.enableConstantUpdate2018) {
+    if (constantContext != ConstantContext.none) {
       handleRecoverableError(
           fasta.templateCantUseControlFlowOrSpreadAsConstant
               .withArguments(forToken),
@@ -5106,19 +5119,12 @@
     if (builder is KernelNamedTypeBuilder &&
         builder.declaration.isTypeVariable) {
       TypeParameter typeParameter = builder.declaration.target;
-      bool isConstant = constantContext != ConstantContext.none;
       LocatedMessage message;
-      bool suppressMessage = false;
       if (!isInstanceContext && typeParameter.parent is Class) {
         message = fasta.messageTypeVariableInStaticContext.withLocation(
             unresolved.fileUri,
             unresolved.charOffset,
             typeParameter.name.length);
-        if (!nonInstanceAccessIsError && !isConstant && legacyMode) {
-          // This is a warning in legacy mode.
-          addProblem(message.messageObject, message.charOffset, message.length);
-          suppressMessage = true;
-        }
       } else if (constantContext == ConstantContext.inferred) {
         message = fasta.messageTypeVariableInConstantContext.withLocation(
             unresolved.fileUri,
@@ -5127,10 +5133,10 @@
       } else {
         return unresolved;
       }
+      addProblem(message.messageObject, message.charOffset, message.length);
       return new UnresolvedType<KernelTypeBuilder>(
           new KernelNamedTypeBuilder(typeParameter.name, null)
-            ..bind(new KernelInvalidTypeBuilder(typeParameter.name, message,
-                suppressMessage: suppressMessage)),
+            ..bind(new KernelInvalidTypeBuilder(typeParameter.name, message)),
           unresolved.charOffset,
           unresolved.fileUri);
     }
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart b/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart
new file mode 100644
index 0000000..b3b7d64
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart
@@ -0,0 +1,273 @@
+// Copyright (c) 2019, 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 'constant_evaluator.dart';
+
+abstract class _ListOrSetConstantBuilder<L extends Expression> {
+  final ConstantEvaluator evaluator;
+  final Expression original;
+  final DartType elementType;
+
+  // Each element of [parts] is either a `List<Constant>` (containing fully
+  // evaluated constants) or a `Constant` (potentially unevaluated).
+  List<Object> parts = <Object>[<Constant>[]];
+
+  _ListOrSetConstantBuilder(this.original, this.elementType, this.evaluator);
+
+  L makeLiteral(List<Expression> elements);
+
+  /// Add an element to the constant list being built by this builder.
+  void add(Expression element) {
+    Constant constant = evaluator._evaluateSubexpression(element);
+    if (evaluator.shouldBeUnevaluated) {
+      parts.add(evaluator.unevaluated(
+          element, makeLiteral([evaluator.extract(constant)])));
+    } else {
+      addConstant(constant, element);
+    }
+  }
+
+  void addSpread(Expression spreadExpression) {
+    Constant spread =
+        evaluator.unlower(evaluator._evaluateSubexpression(spreadExpression));
+    if (evaluator.shouldBeUnevaluated) {
+      // Unevaluated spread
+      parts.add(spread);
+    } else if (spread == evaluator.nullConstant) {
+      // Null spread
+      evaluator.report(spreadExpression, messageConstEvalNullValue);
+    } else {
+      // Fully evaluated spread
+      List<Constant> entries;
+      if (spread is ListConstant) {
+        entries = spread.entries;
+      } else if (spread is SetConstant) {
+        entries = spread.entries;
+      } else {
+        // Not list or set in spread
+        return evaluator.report(
+            spreadExpression, messageConstEvalNotListOrSetInSpread);
+      }
+      for (Constant entry in entries) {
+        addConstant(entry, spreadExpression);
+      }
+    }
+  }
+
+  void addConstant(Constant constant, TreeNode context);
+
+  Constant build();
+}
+
+class ListConstantBuilder extends _ListOrSetConstantBuilder<ListLiteral> {
+  ListConstantBuilder(
+      Expression original, DartType elementType, ConstantEvaluator evaluator)
+      : super(original, elementType, evaluator);
+
+  @override
+  ListLiteral makeLiteral(List<Expression> elements) =>
+      new ListLiteral(elements, isConst: true);
+
+  @override
+  void addConstant(Constant constant, TreeNode context) {
+    List<Constant> lastPart;
+    if (parts.last is List<Constant>) {
+      lastPart = parts.last;
+    } else {
+      parts.add(lastPart = <Constant>[]);
+    }
+    lastPart.add(evaluator.ensureIsSubtype(constant, elementType, context));
+  }
+
+  @override
+  Constant build() {
+    if (parts.length == 1) {
+      // Fully evaluated
+      return evaluator
+          .lowerListConstant(new ListConstant(elementType, parts.single));
+    }
+    List<Expression> lists = <Expression>[];
+    for (Object part in parts) {
+      if (part is List<Constant>) {
+        lists.add(new ConstantExpression(new ListConstant(elementType, part)));
+      } else if (part is Constant) {
+        lists.add(evaluator.extract(part));
+      } else {
+        throw 'Non-constant in constant list';
+      }
+    }
+    return evaluator.unevaluated(
+        original, new ListConcatenation(lists, typeArgument: elementType));
+  }
+}
+
+class SetConstantBuilder extends _ListOrSetConstantBuilder<SetLiteral> {
+  final Set<Constant> seen = new Set<Constant>.identity();
+
+  SetConstantBuilder(
+      Expression original, DartType elementType, ConstantEvaluator evaluator)
+      : super(original, elementType, evaluator);
+
+  @override
+  SetLiteral makeLiteral(List<Expression> elements) =>
+      new SetLiteral(elements, isConst: true);
+
+  @override
+  void addConstant(Constant constant, TreeNode context) {
+    if (!evaluator.hasPrimitiveEqual(constant)) {
+      evaluator.report(context,
+          templateConstEvalElementImplementsEqual.withArguments(constant));
+    }
+    if (!seen.add(constant)) {
+      evaluator.report(
+          context, templateConstEvalDuplicateElement.withArguments(constant));
+    }
+
+    List<Constant> lastPart;
+    if (parts.last is List<Constant>) {
+      lastPart = parts.last;
+    } else {
+      parts.add(lastPart = <Constant>[]);
+    }
+    lastPart.add(evaluator.ensureIsSubtype(constant, elementType, context));
+  }
+
+  @override
+  Constant build() {
+    if (parts.length == 1) {
+      // Fully evaluated
+      List<Constant> entries = parts.single;
+      SetConstant result = new SetConstant(elementType, entries);
+      if (evaluator.desugarSets) {
+        final List<ConstantMapEntry> mapEntries =
+            new List<ConstantMapEntry>(entries.length);
+        for (int i = 0; i < entries.length; ++i) {
+          mapEntries[i] =
+              new ConstantMapEntry(entries[i], evaluator.nullConstant);
+        }
+        Constant map = evaluator.lowerMapConstant(new MapConstant(
+            elementType, evaluator.typeEnvironment.nullType, mapEntries));
+        return evaluator.lower(
+            result,
+            new InstanceConstant(
+                evaluator.unmodifiableSetMap.enclosingClass.reference, [
+              elementType
+            ], <Reference, Constant>{
+              evaluator.unmodifiableSetMap.reference: map
+            }));
+      } else {
+        return evaluator.lowerSetConstant(result);
+      }
+    }
+    List<Expression> sets = <Expression>[];
+    for (Object part in parts) {
+      if (part is List<Constant>) {
+        sets.add(new ConstantExpression(new SetConstant(elementType, part)));
+      } else if (part is Constant) {
+        sets.add(evaluator.extract(part));
+      } else {
+        throw 'Non-constant in constant set';
+      }
+    }
+    return evaluator.unevaluated(
+        original, new SetConcatenation(sets, typeArgument: elementType));
+  }
+}
+
+class MapConstantBuilder {
+  final ConstantEvaluator evaluator;
+  final Expression original;
+  final DartType keyType;
+  final DartType valueType;
+
+  /// Each element of [parts] is either a `List<ConstantMapEntry>` (containing
+  /// fully evaluated map entries) or a `Constant` (potentially unevaluated).
+  List<Object> parts = <Object>[<ConstantMapEntry>[]];
+
+  final Set<Constant> seenKeys = new Set<Constant>.identity();
+
+  MapConstantBuilder(
+      this.original, this.keyType, this.valueType, this.evaluator);
+
+  /// Add a map entry to the constant map being built by this builder
+  void add(MapEntry element) {
+    Constant key = evaluator._evaluateSubexpression(element.key);
+    Constant value = evaluator._evaluateSubexpression(element.value);
+    if (evaluator.shouldBeUnevaluated) {
+      parts.add(evaluator.unevaluated(
+          element.key,
+          new MapLiteral(
+              [new MapEntry(evaluator.extract(key), evaluator.extract(value))],
+              isConst: true)));
+    } else {
+      addConstant(key, value, element.key, element.value);
+    }
+  }
+
+  void addSpread(Expression spreadExpression) {
+    Constant spread =
+        evaluator.unlower(evaluator._evaluateSubexpression(spreadExpression));
+    if (evaluator.shouldBeUnevaluated) {
+      // Unevaluated spread
+      parts.add(spread);
+    } else if (spread == evaluator.nullConstant) {
+      // Null spread
+      evaluator.report(spreadExpression, messageConstEvalNullValue);
+    } else {
+      // Fully evaluated spread
+      if (spread is MapConstant) {
+        for (ConstantMapEntry entry in spread.entries) {
+          addConstant(
+              entry.key, entry.value, spreadExpression, spreadExpression);
+        }
+      } else {
+        // Not map in spread
+        return evaluator.report(
+            spreadExpression, messageConstEvalNotMapInSpread);
+      }
+    }
+  }
+
+  void addConstant(Constant key, Constant value, TreeNode keyContext,
+      TreeNode valueContext) {
+    List<ConstantMapEntry> lastPart;
+    if (parts.last is List<ConstantMapEntry>) {
+      lastPart = parts.last;
+    } else {
+      parts.add(lastPart = <ConstantMapEntry>[]);
+    }
+    if (!evaluator.hasPrimitiveEqual(key)) {
+      evaluator.report(
+          keyContext, templateConstEvalKeyImplementsEqual.withArguments(key));
+    }
+    if (!seenKeys.add(key)) {
+      evaluator.report(
+          keyContext, templateConstEvalDuplicateKey.withArguments(key));
+    }
+    lastPart.add(new ConstantMapEntry(
+        evaluator.ensureIsSubtype(key, keyType, keyContext),
+        evaluator.ensureIsSubtype(value, valueType, valueContext)));
+  }
+
+  Constant build() {
+    if (parts.length == 1) {
+      // Fully evaluated
+      return evaluator
+          .lowerMapConstant(new MapConstant(keyType, valueType, parts.single));
+    }
+    List<Expression> maps = <Expression>[];
+    for (Object part in parts) {
+      if (part is List<ConstantMapEntry>) {
+        maps.add(
+            new ConstantExpression(new MapConstant(keyType, valueType, part)));
+      } else if (part is Constant) {
+        maps.add(evaluator.extract(part));
+      } else {
+        throw 'Non-constant in constant map';
+      }
+    }
+    return evaluator.unevaluated(original,
+        new MapConcatenation(maps, keyType: keyType, valueType: valueType));
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index b35550c..b015270 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -39,9 +39,6 @@
         messageConstEvalCircularity,
         messageConstEvalContext,
         messageConstEvalFailedAssertion,
-        messageConstEvalIterationInConstList,
-        messageConstEvalIterationInConstSet,
-        messageConstEvalIterationInConstMap,
         messageConstEvalNotListOrSetInSpread,
         messageConstEvalNotMapInSpread,
         messageConstEvalNullValue,
@@ -67,16 +64,7 @@
         templateConstEvalNonConstantVariableGet,
         templateConstEvalZeroDivisor;
 
-import 'collections.dart'
-    show
-        ForElement,
-        ForInElement,
-        IfElement,
-        SpreadElement,
-        ForMapEntry,
-        ForInMapEntry,
-        IfMapEntry,
-        SpreadMapEntry;
+part 'constant_collection_builders.dart';
 
 Component transformComponent(Component component, ConstantsBackend backend,
     Map<String, String> environmentDefines, ErrorReporter errorReporter,
@@ -147,6 +135,7 @@
 }
 
 class ConstantsTransformer extends Transformer {
+  final ConstantsBackend backend;
   final ConstantEvaluator constantEvaluator;
   final TypeEnvironment typeEnvironment;
 
@@ -158,7 +147,7 @@
   final bool errorOnUnevaluatedConstant;
 
   ConstantsTransformer(
-      ConstantsBackend backend,
+      this.backend,
       Map<String, String> environmentDefines,
       this.keepFields,
       this.keepVariables,
@@ -312,18 +301,11 @@
       if (node.isConst) {
         final Constant constant = evaluateWithContext(node, node.initializer);
         constantEvaluator.env.addVariableValue(node, constant);
+        node.initializer = makeConstantExpression(constant, node.initializer)
+          ..parent = node;
 
-        if (keepVariables) {
-          // So the value of the variable is still available for debugging
-          // purposes we convert the constant variable to be a final variable
-          // initialized to the evaluated constant expression.
-          node.initializer = makeConstantExpression(constant, node.initializer)
-            ..parent = node;
-          node.isFinal = true;
-          node.isConst = false;
-        } else {
-          // Since we convert all use-sites of constants, the constant
-          // [VariableDeclaration] is unused and we'll therefore remove it.
+        // If this constant is inlined, remove it.
+        if (!keepVariables && shouldInline(node.initializer)) {
           return null;
         }
       } else {
@@ -336,20 +318,17 @@
   visitField(Field node) {
     return constantEvaluator.withNewEnvironment(() {
       if (node.isConst) {
-        // Since we convert all use-sites of constants, the constant [Field]
-        // cannot be referenced anymore.  We therefore get rid of it if
-        // [keepFields] was not specified.
-        if (!keepFields) {
-          return null;
-        }
-
-        // Otherwise we keep the constant [Field] and convert it's initializer.
         transformAnnotations(node.annotations, node);
         if (node.initializer != null) {
           node.initializer =
               evaluateAndTransformWithContext(node, node.initializer)
                 ..parent = node;
         }
+
+        // If this constant is inlined, remove it.
+        if (!keepFields && shouldInline(node.initializer)) {
+          return null;
+        }
       } else {
         transformAnnotations(node.annotations, node);
         if (node.initializer != null) {
@@ -369,7 +348,15 @@
   visitStaticGet(StaticGet node) {
     final Member target = node.target;
     if (target is Field && target.isConst) {
-      return evaluateAndTransformWithContext(node, node);
+      if (target.initializer != null) {
+        // Make sure the initializer is evaluated first.
+        target.initializer =
+            evaluateAndTransformWithContext(target, target.initializer)
+              ..parent = target;
+        if (shouldInline(target.initializer)) {
+          return evaluateAndTransformWithContext(node, node);
+        }
+      }
     } else if (target is Procedure && target.kind == ProcedureKind.Method) {
       return evaluateAndTransformWithContext(node, node);
     }
@@ -382,8 +369,14 @@
   }
 
   visitVariableGet(VariableGet node) {
-    if (node.variable.isConst) {
-      return evaluateAndTransformWithContext(node, node);
+    final VariableDeclaration variable = node.variable;
+    if (variable.isConst) {
+      variable.initializer =
+          evaluateAndTransformWithContext(variable, variable.initializer)
+            ..parent = variable;
+      if (shouldInline(variable.initializer)) {
+        return evaluateAndTransformWithContext(node, node);
+      }
     }
     return super.visitVariableGet(node);
   }
@@ -395,6 +388,10 @@
     return super.visitListLiteral(node);
   }
 
+  visitListConcatenation(ListConcatenation node) {
+    return evaluateAndTransformWithContext(node, node);
+  }
+
   visitSetLiteral(SetLiteral node) {
     if (node.isConst) {
       return evaluateAndTransformWithContext(node, node);
@@ -402,6 +399,10 @@
     return super.visitSetLiteral(node);
   }
 
+  visitSetConcatenation(SetConcatenation node) {
+    return evaluateAndTransformWithContext(node, node);
+  }
+
   visitMapLiteral(MapLiteral node) {
     if (node.isConst) {
       return evaluateAndTransformWithContext(node, node);
@@ -409,6 +410,10 @@
     return super.visitMapLiteral(node);
   }
 
+  visitMapConcatenation(MapConcatenation node) {
+    return evaluateAndTransformWithContext(node, node);
+  }
+
   visitConstructorInvocation(ConstructorInvocation node) {
     if (node.isConst) {
       return evaluateAndTransformWithContext(node, node);
@@ -456,6 +461,13 @@
     return new ConstantExpression(constant, node.getStaticType(typeEnvironment))
       ..fileOffset = node.fileOffset;
   }
+
+  bool shouldInline(Expression initializer) {
+    if (initializer is ConstantExpression) {
+      return backend.shouldInlineConstant(initializer);
+    }
+    return true;
+  }
 }
 
 class ConstantEvaluator extends RecursiveVisitor<Constant> {
@@ -765,220 +777,26 @@
     return canonicalize(result);
   }
 
-  /// Add an element (which is possibly a spread or an if element) to a
-  /// constant list or set represented as a list of (possibly unevaluated)
-  /// lists or sets to be concatenated.
-  /// Each element of [parts] is either a `List<Constant>` (containing fully
-  /// evaluated constants) or a `Constant` (potentially unevaluated).
-  /// Pass an identity set as [seen] for sets and omit it for lists.
-  void addToListOrSetConstant(
-      List<Object> parts, Expression element, DartType elementType,
-      [Set<Constant> seen]) {
-    bool isSet = seen != null;
-    if (element is SpreadElement) {
-      Constant spread = unlower(_evaluateSubexpression(element.expression));
-      if (shouldBeUnevaluated) {
-        // Unevaluated spread
-        if (element.isNullAware) {
-          VariableDeclaration temp =
-              new VariableDeclaration(null, initializer: extract(spread));
-          parts.add(unevaluated(
-              element.expression,
-              new Let(
-                  temp,
-                  new ConditionalExpression(
-                      new MethodInvocation(new VariableGet(temp),
-                          new Name('=='), new Arguments([new NullLiteral()])),
-                      new ListLiteral([], isConst: true),
-                      new VariableGet(temp),
-                      const DynamicType()))));
-        } else {
-          parts.add(spread);
-        }
-      } else if (spread == nullConstant) {
-        // Null spread
-        if (!element.isNullAware) {
-          report(element.expression, messageConstEvalNullValue);
-        }
-      } else {
-        // Fully evaluated spread
-        List<Constant> entries;
-        if (spread is ListConstant) {
-          entries = spread.entries;
-        } else if (spread is SetConstant) {
-          entries = spread.entries;
-        } else {
-          // Not list or set in spread
-          return report(
-              element.expression, messageConstEvalNotListOrSetInSpread);
-        }
-        for (Constant entry in entries) {
-          addToListOrSetConstant(
-              parts, new ConstantExpression(entry), elementType, seen);
-        }
-      }
-    } else if (element is IfElement) {
-      Constant condition = _evaluateSubexpression(element.condition);
-      if (shouldBeUnevaluated) {
-        // Unevaluated if
-        enterLazy();
-        Constant then = _evaluateSubexpression(isSet
-            ? new SetLiteral([cloner.clone(element.then)], isConst: true)
-            : new ListLiteral([cloner.clone(element.then)], isConst: true));
-        Constant otherwise;
-        if (element.otherwise != null) {
-          otherwise = _evaluateSubexpression(isSet
-              ? new SetLiteral([cloner.clone(element.otherwise)], isConst: true)
-              : new ListLiteral([cloner.clone(element.otherwise)],
-                  isConst: true));
-        } else {
-          otherwise = isSet
-              ? new SetConstant(const DynamicType(), [])
-              : new ListConstant(const DynamicType(), []);
-        }
-        leaveLazy();
-        parts.add(unevaluated(
-            element.condition,
-            new ConditionalExpression(extract(condition), extract(then),
-                extract(otherwise), const DynamicType())));
-      } else {
-        // Fully evaluated if
-        if (condition == trueConstant) {
-          addToListOrSetConstant(parts, element.then, elementType, seen);
-        } else if (condition == falseConstant) {
-          if (element.otherwise != null) {
-            addToListOrSetConstant(parts, element.otherwise, elementType, seen);
-          }
-        } else if (condition == nullConstant) {
-          report(element.condition, messageConstEvalNullValue);
-        } else {
-          report(
-              element.condition,
-              templateConstEvalInvalidType.withArguments(
-                  condition,
-                  typeEnvironment.boolType,
-                  condition.getType(typeEnvironment)));
-        }
-      }
-    } else if (element is ForElement || element is ForInElement) {
-      // For or for-in
-      report(
-          element,
-          isSet
-              ? messageConstEvalIterationInConstSet
-              : messageConstEvalIterationInConstList);
-    } else {
-      // Ordinary expresion element
-      Constant constant = _evaluateSubexpression(element);
-      if (shouldBeUnevaluated) {
-        parts.add(unevaluated(
-            element,
-            isSet
-                ? new SetLiteral([extract(constant)],
-                    typeArgument: elementType, isConst: true)
-                : new ListLiteral([extract(constant)],
-                    typeArgument: elementType, isConst: true)));
-      } else {
-        List<Constant> listOrSet;
-        if (parts.last is List<Constant>) {
-          listOrSet = parts.last;
-        } else {
-          parts.add(listOrSet = <Constant>[]);
-        }
-        if (isSet) {
-          if (!hasPrimitiveEqual(constant)) {
-            report(
-                element,
-                templateConstEvalElementImplementsEqual
-                    .withArguments(constant));
-          }
-          if (!seen.add(constant)) {
-            report(element,
-                templateConstEvalDuplicateElement.withArguments(constant));
-          }
-        }
-        listOrSet.add(ensureIsSubtype(constant, elementType, element));
-      }
-    }
-  }
-
-  Constant makeListConstantFromParts(
-      List<Object> parts, Expression node, DartType elementType) {
-    if (parts.length == 1) {
-      // Fully evaluated
-      return lowerListConstant(new ListConstant(elementType, parts.single));
-    }
-    List<Expression> lists = <Expression>[];
-    for (Object part in parts) {
-      if (part is List<Constant>) {
-        lists.add(new ConstantExpression(new ListConstant(elementType, part)));
-      } else if (part is Constant) {
-        lists.add(extract(part));
-      } else {
-        throw 'Non-constant in constant list';
-      }
-    }
-    return unevaluated(
-        node, new ListConcatenation(lists, typeArgument: elementType));
-  }
-
   visitListLiteral(ListLiteral node) {
     if (!node.isConst) {
       return report(
           node, templateConstEvalNonConstantLiteral.withArguments('List'));
     }
-    final List<Object> parts = <Object>[<Constant>[]];
+    final ListConstantBuilder builder =
+        new ListConstantBuilder(node, node.typeArgument, this);
     for (Expression element in node.expressions) {
-      addToListOrSetConstant(parts, element, node.typeArgument);
+      builder.add(element);
     }
-    return makeListConstantFromParts(parts, node, node.typeArgument);
+    return builder.build();
   }
 
   visitListConcatenation(ListConcatenation node) {
-    final List<Object> parts = <Object>[<Constant>[]];
+    final ListConstantBuilder builder =
+        new ListConstantBuilder(node, node.typeArgument, this);
     for (Expression list in node.lists) {
-      addToListOrSetConstant(parts,
-          new SpreadElement(cloner.clone(list), false), node.typeArgument);
+      builder.addSpread(list);
     }
-    return makeListConstantFromParts(parts, node, node.typeArgument);
-  }
-
-  Constant makeSetConstantFromParts(
-      List<Object> parts, Expression node, DartType elementType) {
-    if (parts.length == 1) {
-      // Fully evaluated
-      List<Constant> entries = parts.single;
-      SetConstant result = new SetConstant(elementType, entries);
-      if (desugarSets) {
-        final List<ConstantMapEntry> mapEntries =
-            new List<ConstantMapEntry>(entries.length);
-        for (int i = 0; i < entries.length; ++i) {
-          mapEntries[i] = new ConstantMapEntry(entries[i], nullConstant);
-        }
-        Constant map = lowerMapConstant(
-            new MapConstant(elementType, typeEnvironment.nullType, mapEntries));
-        return lower(
-            result,
-            new InstanceConstant(
-                unmodifiableSetMap.enclosingClass.reference,
-                [elementType],
-                <Reference, Constant>{unmodifiableSetMap.reference: map}));
-      } else {
-        return lowerSetConstant(result);
-      }
-    }
-    List<Expression> sets = <Expression>[];
-    for (Object part in parts) {
-      if (part is List<Constant>) {
-        sets.add(new ConstantExpression(new SetConstant(elementType, part)));
-      } else if (part is Constant) {
-        sets.add(extract(part));
-      } else {
-        throw 'Non-constant in constant set';
-      }
-    }
-    return unevaluated(
-        node, new SetConcatenation(sets, typeArgument: elementType));
+    return builder.build();
   }
 
   visitSetLiteral(SetLiteral node) {
@@ -986,169 +804,21 @@
       return report(
           node, templateConstEvalNonConstantLiteral.withArguments('Set'));
     }
-    final Set<Constant> seen = new Set<Constant>.identity();
-    final List<Object> parts = <Object>[<Constant>[]];
+    final SetConstantBuilder builder =
+        new SetConstantBuilder(node, node.typeArgument, this);
     for (Expression element in node.expressions) {
-      addToListOrSetConstant(parts, element, node.typeArgument, seen);
+      builder.add(element);
     }
-    return makeSetConstantFromParts(parts, node, node.typeArgument);
+    return builder.build();
   }
 
   visitSetConcatenation(SetConcatenation node) {
-    final Set<Constant> seen = new Set<Constant>.identity();
-    final List<Object> parts = <Object>[<Constant>[]];
+    final SetConstantBuilder builder =
+        new SetConstantBuilder(node, node.typeArgument, this);
     for (Expression set_ in node.sets) {
-      addToListOrSetConstant(
-          parts,
-          new SpreadElement(cloner.clone(set_), false),
-          node.typeArgument,
-          seen);
+      builder.addSpread(set_);
     }
-    return makeSetConstantFromParts(parts, node, node.typeArgument);
-  }
-
-  /// Add a map entry (which is possibly a spread or an if map entry) to a
-  /// constant map represented as a list of (possibly unevaluated)
-  /// maps to be concatenated.
-  /// Each element of [parts] is either a `List<ConstantMapEntry>` (containing
-  /// fully evaluated map entries) or a `Constant` (potentially unevaluated).
-  void addToMapConstant(List<Object> parts, MapEntry element, DartType keyType,
-      DartType valueType, Set<Constant> seenKeys) {
-    if (element is SpreadMapEntry) {
-      Constant spread = unlower(_evaluateSubexpression(element.expression));
-      if (shouldBeUnevaluated) {
-        // Unevaluated spread
-        if (element.isNullAware) {
-          VariableDeclaration temp =
-              new VariableDeclaration(null, initializer: extract(spread));
-          parts.add(unevaluated(
-              element.expression,
-              new Let(
-                  temp,
-                  new ConditionalExpression(
-                      new MethodInvocation(new VariableGet(temp),
-                          new Name('=='), new Arguments([new NullLiteral()])),
-                      new MapLiteral([], isConst: true),
-                      new VariableGet(temp),
-                      const DynamicType()))));
-        } else {
-          parts.add(spread);
-        }
-      } else if (spread == nullConstant) {
-        // Null spread
-        if (!element.isNullAware) {
-          report(element.expression, messageConstEvalNullValue);
-        }
-      } else {
-        // Fully evaluated spread
-        if (spread is MapConstant) {
-          for (ConstantMapEntry entry in spread.entries) {
-            addToMapConstant(
-                parts,
-                new MapEntry(new ConstantExpression(entry.key),
-                    new ConstantExpression(entry.value)),
-                keyType,
-                valueType,
-                seenKeys);
-          }
-        } else {
-          // Not map in spread
-          return report(element.expression, messageConstEvalNotMapInSpread);
-        }
-      }
-    } else if (element is IfMapEntry) {
-      Constant condition = _evaluateSubexpression(element.condition);
-      if (shouldBeUnevaluated) {
-        // Unevaluated if
-        enterLazy();
-        Constant then = _evaluateSubexpression(
-            new MapLiteral([cloner.clone(element.then)], isConst: true));
-        Constant otherwise;
-        if (element.otherwise != null) {
-          otherwise = _evaluateSubexpression(
-              new MapLiteral([cloner.clone(element.otherwise)], isConst: true));
-        } else {
-          otherwise =
-              new MapConstant(const DynamicType(), const DynamicType(), []);
-        }
-        leaveLazy();
-        parts.add(unevaluated(
-            element.condition,
-            new ConditionalExpression(extract(condition), extract(then),
-                extract(otherwise), const DynamicType())));
-      } else {
-        // Fully evaluated if
-        if (condition == trueConstant) {
-          addToMapConstant(parts, element.then, keyType, valueType, seenKeys);
-        } else if (condition == falseConstant) {
-          if (element.otherwise != null) {
-            addToMapConstant(
-                parts, element.otherwise, keyType, valueType, seenKeys);
-          }
-        } else if (condition == nullConstant) {
-          report(element.condition, messageConstEvalNullValue);
-        } else {
-          report(
-              element.condition,
-              templateConstEvalInvalidType.withArguments(
-                  condition,
-                  typeEnvironment.boolType,
-                  condition.getType(typeEnvironment)));
-        }
-      }
-    } else if (element is ForMapEntry || element is ForInMapEntry) {
-      // For or for-in
-      report(element, messageConstEvalIterationInConstMap);
-    } else {
-      // Ordinary map entry
-      Constant key = _evaluateSubexpression(element.key);
-      Constant value = _evaluateSubexpression(element.value);
-      if (shouldBeUnevaluated) {
-        parts.add(unevaluated(
-            element.key,
-            new MapLiteral([new MapEntry(extract(key), extract(value))],
-                isConst: true)));
-      } else {
-        List<ConstantMapEntry> entries;
-        if (parts.last is List<ConstantMapEntry>) {
-          entries = parts.last;
-        } else {
-          parts.add(entries = <ConstantMapEntry>[]);
-        }
-        if (!hasPrimitiveEqual(key)) {
-          report(
-              element, templateConstEvalKeyImplementsEqual.withArguments(key));
-        }
-        if (!seenKeys.add(key)) {
-          report(element.key, templateConstEvalDuplicateKey.withArguments(key));
-        }
-        entries.add(new ConstantMapEntry(
-            ensureIsSubtype(key, keyType, element.key),
-            ensureIsSubtype(value, valueType, element.value)));
-      }
-    }
-  }
-
-  Constant makeMapConstantFromParts(List<Object> parts, Expression node,
-      DartType keyType, DartType valueType) {
-    if (parts.length == 1) {
-      // Fully evaluated
-      return lowerMapConstant(
-          new MapConstant(keyType, valueType, parts.single));
-    }
-    List<Expression> maps = <Expression>[];
-    for (Object part in parts) {
-      if (part is List<ConstantMapEntry>) {
-        maps.add(
-            new ConstantExpression(new MapConstant(keyType, valueType, part)));
-      } else if (part is Constant) {
-        maps.add(extract(part));
-      } else {
-        throw 'Non-constant in constant map';
-      }
-    }
-    return unevaluated(node,
-        new MapConcatenation(maps, keyType: keyType, valueType: valueType));
+    return builder.build();
   }
 
   visitMapLiteral(MapLiteral node) {
@@ -1156,22 +826,21 @@
       return report(
           node, templateConstEvalNonConstantLiteral.withArguments('Map'));
     }
-    final Set<Constant> seen = new Set<Constant>.identity();
-    final List<Object> parts = <Object>[<ConstantMapEntry>[]];
+    final MapConstantBuilder builder =
+        new MapConstantBuilder(node, node.keyType, node.valueType, this);
     for (MapEntry element in node.entries) {
-      addToMapConstant(parts, element, node.keyType, node.valueType, seen);
+      builder.add(element);
     }
-    return makeMapConstantFromParts(parts, node, node.keyType, node.valueType);
+    return builder.build();
   }
 
   visitMapConcatenation(MapConcatenation node) {
-    final Set<Constant> seen = new Set<Constant>.identity();
-    final List<Object> parts = <Object>[<ConstantMapEntry>[]];
+    final MapConstantBuilder builder =
+        new MapConstantBuilder(node, node.keyType, node.valueType, this);
     for (Expression map in node.maps) {
-      addToMapConstant(parts, new SpreadMapEntry(cloner.clone(map), false),
-          node.keyType, node.valueType, seen);
+      builder.addSpread(map);
     }
-    return makeMapConstantFromParts(parts, node, node.keyType, node.valueType);
+    return builder.build();
   }
 
   visitFunctionExpression(FunctionExpression node) {
@@ -1840,7 +1509,7 @@
               extract(otherwise), node.staticType));
     } else {
       return report(
-          node,
+          node.condition,
           templateConstEvalInvalidType.withArguments(condition,
               typeEnvironment.boolType, condition.getType(typeEnvironment)));
     }
@@ -1934,6 +1603,7 @@
       } else {
         reportInvalid(
             node, 'No support for ${target.runtimeType} in a static-get.');
+        return null;
       }
     });
   }
@@ -2092,7 +1762,8 @@
   visitAsExpression(AsExpression node) {
     final Constant constant = _evaluateSubexpression(node.operand);
     if (shouldBeUnevaluated) {
-      return unevaluated(node, new AsExpression(extract(constant), node.type));
+      return unevaluated(node,
+          new AsExpression(extract(constant), env.subsituteType(node.type)));
     }
     return ensureIsSubtype(constant, evaluateDartType(node, node.type), node);
   }
@@ -2135,7 +1806,9 @@
     final Constant constant = _evaluateSubexpression(node.expression);
     if (shouldBeUnevaluated) {
       return unevaluated(
-          node, new Instantiation(extract(constant), node.typeArguments));
+          node,
+          new Instantiation(extract(constant),
+              node.typeArguments.map((t) => env.subsituteType(t)).toList()));
     }
     if (constant is TearOffConstant) {
       if (node.typeArguments.length ==
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index db33cf1..9b94ff4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -215,9 +215,11 @@
       List<UnresolvedType<KernelTypeBuilder>> arguments) {
     KernelNamedTypeBuilder result =
         new KernelNamedTypeBuilder(token.lexeme, null);
-    result.bind(result.buildInvalidType(templateNotAType
-        .withArguments(token.lexeme)
-        .withLocation(uri, offsetForToken(token), lengthForToken(token))));
+    Message message = templateNotAType.withArguments(token.lexeme);
+    helper.library
+        .addProblem(message, offsetForToken(token), lengthForToken(token), uri);
+    result.bind(result.buildInvalidType(message.withLocation(
+        uri, offsetForToken(token), lengthForToken(token))));
     return result;
   }
 
@@ -541,6 +543,8 @@
               uri, charOffset, lengthOfSpan(prefixGenerator.token, token));
     }
     KernelNamedTypeBuilder result = new KernelNamedTypeBuilder(name, null);
+    helper.library.addProblem(
+        message.messageObject, message.charOffset, message.length, message.uri);
     result.bind(result.buildInvalidType(message));
     return result;
   }
@@ -1161,10 +1165,14 @@
         : templateNotAPrefixInTypeAnnotation;
     KernelNamedTypeBuilder result =
         new KernelNamedTypeBuilder(plainNameForRead, null);
-    result.bind(result.buildInvalidType(template
-        .withArguments(prefixGenerator.token.lexeme, token.lexeme)
-        .withLocation(uri, offsetForToken(prefixGenerator.token),
-            lengthOfSpan(prefixGenerator.token, token))));
+    Message message =
+        template.withArguments(prefixGenerator.token.lexeme, token.lexeme);
+    helper.library.addProblem(message, offsetForToken(prefixGenerator.token),
+        lengthOfSpan(prefixGenerator.token, token), uri);
+    result.bind(result.buildInvalidType(message.withLocation(
+        uri,
+        offsetForToken(prefixGenerator.token),
+        lengthOfSpan(prefixGenerator.token, token))));
     return result;
   }
 
@@ -1250,6 +1258,7 @@
       List<UnresolvedType<KernelTypeBuilder>> arguments) {
     KernelNamedTypeBuilder result =
         new KernelNamedTypeBuilder(token.lexeme, null);
+    helper.library.addProblem(message, offsetForToken(token), noLength, uri);
     result.bind(result.buildInvalidType(
         message.withLocation(uri, offsetForToken(token), noLength)));
     return result;
diff --git a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
index 902db15..c82886b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
@@ -15,9 +15,9 @@
 
 class ImplicitFieldType extends DartType {
   final MemberBuilder member;
-  final Token initializerToken;
+  Token initializerToken;
 
-  const ImplicitFieldType(this.member, this.initializerToken);
+  ImplicitFieldType(this.member, this.initializerToken);
 
   accept(DartTypeVisitor<Object> v) {
     unsupported("accept", member.charOffset, member.fileUri);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
index 1886808..278e742 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
@@ -42,6 +42,27 @@
       : forest = const Fangorn(),
         super.forField(member, typeInferrer);
 
+  KernelBodyBuilder.forOutlineExpression(
+      KernelLibraryBuilder library,
+      KernelClassBuilder classBuilder,
+      ModifierBuilder member,
+      Scope scope,
+      Scope parameterScope,
+      Uri fileUri)
+      : forest = const Fangorn(),
+        super(
+            library,
+            member,
+            scope,
+            parameterScope,
+            library.loader.hierarchy,
+            library.loader.coreTypes,
+            classBuilder,
+            member?.isInstanceMember ?? false,
+            fileUri,
+            library.loader.typeInferenceEngine
+                ?.createLocalTypeInferrer(fileUri, null, library));
+
   @override
   void enterThenForTypePromotion(Expression condition) {
     typePromoter?.enterThen(condition);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
index afd74e5..0206595 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
@@ -34,6 +34,8 @@
 
 export 'kernel_library_builder.dart' show KernelLibraryBuilder;
 
+export 'kernel_metadata_builder.dart' show KernelMetadataBuilder;
+
 export 'kernel_mixin_application_builder.dart'
     show KernelMixinApplicationBuilder;
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 151c074..5e4ac3a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -105,6 +105,7 @@
         Declaration,
         KernelFunctionBuilder,
         KernelLibraryBuilder,
+        KernelMetadataBuilder,
         KernelNamedTypeBuilder,
         KernelProcedureBuilder,
         KernelRedirectingFactoryBuilder,
@@ -224,6 +225,19 @@
     }
   }
 
+  @override
+  void buildOutlineExpressions(LibraryBuilder library) {
+    void build(String ignore, Declaration declaration) {
+      MemberBuilder member = declaration;
+      member.buildOutlineExpressions(library);
+    }
+
+    KernelMetadataBuilder.buildAnnotations(
+        isPatch ? origin.target : cls, metadata, library, this, null, null);
+    constructors.forEach(build);
+    scope.forEach(build);
+  }
+
   void checkSupertypes(CoreTypes coreTypes) {
     // This method determines whether the class (that's being built) its super
     // class appears both in 'extends' and 'implements' clauses and whether any
@@ -338,7 +352,7 @@
     for (TypeParameter parameter in cls.typeParameters) {
       List<TypeArgumentIssue> issues = findTypeArgumentIssues(
           parameter.bound, typeEnvironment,
-          allowSuperBounded: false);
+          allowSuperBounded: true);
       if (issues != null) {
         for (TypeArgumentIssue issue in issues) {
           DartType argument = issue.argument;
@@ -923,9 +937,9 @@
       library.addProblem(
           templateOverrideTypeVariablesMismatch.withArguments(
               "${declaredMember.enclosingClass.name}."
-              "${declaredMember.name.name}",
+                  "${declaredMember.name.name}",
               "${interfaceMember.enclosingClass.name}."
-              "${interfaceMember.name.name}"),
+                  "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
           declaredMember.fileUri,
@@ -960,9 +974,9 @@
             library.addProblem(
                 templateOverrideTypeVariablesMismatch.withArguments(
                     "${declaredMember.enclosingClass.name}."
-                    "${declaredMember.name.name}",
+                        "${declaredMember.name.name}",
                     "${interfaceMember.enclosingClass.name}."
-                    "${interfaceMember.name.name}"),
+                        "${interfaceMember.name.name}"),
                 declaredMember.fileOffset,
                 noLength,
                 declaredMember.fileUri,
@@ -1103,9 +1117,9 @@
       library.addProblem(
           templateOverrideFewerPositionalArguments.withArguments(
               "${declaredMember.enclosingClass.name}."
-              "${declaredMember.name.name}",
+                  "${declaredMember.name.name}",
               "${interfaceMember.enclosingClass.name}."
-              "${interfaceMember.name.name}"),
+                  "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
           declaredMember.fileUri,
@@ -1122,9 +1136,9 @@
       library.addProblem(
           templateOverrideMoreRequiredArguments.withArguments(
               "${declaredMember.enclosingClass.name}."
-              "${declaredMember.name.name}",
+                  "${declaredMember.name.name}",
               "${interfaceMember.enclosingClass.name}."
-              "${interfaceMember.name.name}"),
+                  "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
           declaredMember.fileUri,
@@ -1164,9 +1178,9 @@
       library.addProblem(
           templateOverrideFewerNamedArguments.withArguments(
               "${declaredMember.enclosingClass.name}."
-              "${declaredMember.name.name}",
+                  "${declaredMember.name.name}",
               "${interfaceMember.enclosingClass.name}."
-              "${interfaceMember.name.name}"),
+                  "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
           declaredMember.fileUri,
@@ -1201,10 +1215,10 @@
           library.addProblem(
               templateOverrideMismatchNamedParameter.withArguments(
                   "${declaredMember.enclosingClass.name}."
-                  "${declaredMember.name.name}",
+                      "${declaredMember.name.name}",
                   interfaceNamedParameters.current.name,
                   "${interfaceMember.enclosingClass.name}."
-                  "${interfaceMember.name.name}"),
+                      "${interfaceMember.name.name}"),
               declaredMember.fileOffset,
               noLength,
               declaredMember.fileUri,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
index c2ca617..212281c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
@@ -1350,8 +1350,14 @@
           setter = declaration.findStaticBuilder(
               name.name, offsetForToken(token), uri, helper.library,
               isSetter: true);
-        } else if (member.isField && !member.isFinal) {
-          setter = member;
+        } else if (member.isField) {
+          if (member.isFinal || member.isConst) {
+            setter = declaration.findStaticBuilder(
+                name.name, offsetForToken(token), uri, helper.library,
+                isSetter: true);
+          } else {
+            setter = member;
+          }
         }
         generator = new StaticAccessGenerator.fromBuilder(
             helper, member, send.token, setter);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
index 904f47d..88a91b4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
@@ -7,10 +7,18 @@
 import 'package:kernel/ast.dart'
     show Class, DartType, DynamicType, Expression, Field, Name, NullLiteral;
 
+import '../constant_context.dart' show ConstantContext;
+
 import '../fasta_codes.dart' show messageInternalProblemAlreadyInitialized;
 
 import '../problems.dart' show internalProblem, unsupported;
 
+import '../scanner.dart' show Token;
+
+import '../scope.dart' show Scope;
+
+import '../source/source_loader.dart' show SourceLoader;
+
 import '../type_inference/type_inference_engine.dart'
     show IncludesTypeParametersCovariantly;
 
@@ -23,7 +31,9 @@
         FieldBuilder,
         ImplicitFieldType,
         KernelLibraryBuilder,
+        KernelMetadataBuilder,
         KernelTypeBuilder,
+        LibraryBuilder,
         MetadataBuilder;
 
 import 'kernel_shadow_ast.dart' show ShadowField;
@@ -32,6 +42,7 @@
   final ShadowField field;
   final List<MetadataBuilder> metadata;
   final KernelTypeBuilder type;
+  Token constInitializerToken;
 
   KernelFieldBuilder(this.metadata, this.type, String name, int modifiers,
       Declaration compilationUnit, int charOffset, int charEndOffset)
@@ -91,6 +102,32 @@
     return field;
   }
 
+  @override
+  void buildOutlineExpressions(LibraryBuilder library) {
+    ClassBuilder classBuilder = isClassMember ? parent : null;
+    KernelMetadataBuilder.buildAnnotations(
+        field, metadata, library, classBuilder, this, null);
+    if (constInitializerToken != null) {
+      Scope scope = classBuilder?.scope ?? library.scope;
+      KernelBodyBuilder bodyBuilder =
+          new KernelBodyBuilder.forOutlineExpression(
+              library, classBuilder, this, scope, null, fileUri);
+      bodyBuilder.constantContext =
+          isConst ? ConstantContext.inferred : ConstantContext.none;
+      initializer = bodyBuilder.parseFieldInitializer(constInitializerToken)
+        ..parent = field;
+      constInitializerToken = null;
+      bodyBuilder.typeInferrer
+          ?.inferFieldInitializer(bodyBuilder, field.type, field.initializer);
+      if (library.loader is SourceLoader) {
+        SourceLoader loader = library.loader;
+        loader.transformPostInference(field, bodyBuilder.transformSetLiterals,
+            bodyBuilder.transformCollections);
+      }
+      bodyBuilder.resolveRedirectingFactoryTargets();
+    }
+  }
+
   Field get target => field;
 
   void prepareTopLevelInference() {
@@ -107,8 +144,12 @@
       }
       ImplicitFieldType type = field.type;
       field.type = const DynamicType();
-      initializer = new KernelBodyBuilder.forField(this, typeInferrer)
-          .parseFieldInitializer(type.initializerToken);
+      KernelBodyBuilder bodyBuilder =
+          new KernelBodyBuilder.forField(this, typeInferrer);
+      bodyBuilder.constantContext =
+          isConst ? ConstantContext.inferred : ConstantContext.none;
+      initializer = bodyBuilder.parseFieldInitializer(type.initializerToken);
+      type.initializerToken = null;
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_invalid_type_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_invalid_type_builder.dart
index 60fba36..729323f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_invalid_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_invalid_type_builder.dart
@@ -21,7 +21,7 @@
   final bool suppressMessage;
 
   KernelInvalidTypeBuilder(String name, this.message,
-      {this.context, this.suppressMessage: false})
+      {this.context, this.suppressMessage: true})
       : super(name, message.charOffset, message.uri);
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index eac2a4a..1532c58 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -135,6 +135,7 @@
         KernelTypeAliasBuilder,
         KernelFunctionTypeBuilder,
         KernelInvalidTypeBuilder,
+        KernelMetadataBuilder,
         KernelMixinApplicationBuilder,
         KernelNamedTypeBuilder,
         KernelProcedureBuilder,
@@ -635,18 +636,18 @@
       String name,
       int charOffset,
       int charEndOffset,
-      Token initializerTokenForInference,
-      bool hasInitializer) {
+      Token initializerToken,
+      bool hasInitializer,
+      {Token constInitializerToken}) {
     if (hasInitializer) {
       modifiers |= hasInitializerMask;
     }
     KernelFieldBuilder field = new KernelFieldBuilder(
         metadata, type, name, modifiers, this, charOffset, charEndOffset);
+    field.constInitializerToken = constInitializerToken;
     addBuilder(name, field, charOffset);
-    if (initializerTokenForInference != null) {
-      assert(type == null);
-      field.target.type =
-          new ImplicitFieldType(field, initializerTokenForInference);
+    if (!legacyMode && type == null && initializerToken != null) {
+      field.target.type = new ImplicitFieldType(field, initializerToken);
     }
     loader.target.metadataCollector
         ?.setDocumentationComment(field.target, documentationComment);
@@ -902,6 +903,12 @@
   }
 
   @override
+  void buildOutlineExpressions() {
+    KernelMetadataBuilder.buildAnnotations(
+        library, metadata, this, null, null, null);
+  }
+
+  @override
   void buildBuilder(Declaration declaration, LibraryBuilder coreLibrary) {
     Class cls;
     Member member;
@@ -1139,16 +1146,18 @@
     var builderTemplate = isExport
         ? templateDuplicatedExportInType
         : templateDuplicatedImportInType;
-    return new KernelInvalidTypeBuilder(
+    message = builderTemplate.withArguments(
         name,
-        builderTemplate
-            .withArguments(
-                name,
-                // TODO(ahe): We should probably use a context object here
-                // instead of including URIs in this message.
-                uri,
-                otherUri)
-            .withLocation(fileUri, charOffset, name.length));
+        // TODO(ahe): We should probably use a context object here
+        // instead of including URIs in this message.
+        uri,
+        otherUri);
+    // We report the error lazily (setting suppressMessage to false) because the
+    // spec 18.1 states that 'It is not an error if N is introduced by two or
+    // more imports but never referred to.'
+    return new KernelInvalidTypeBuilder(
+        name, message.withLocation(fileUri, charOffset, name.length),
+        suppressMessage: false);
   }
 
   int finishDeferredLoadTearoffs() {
@@ -1382,7 +1391,13 @@
               unserializableExports ??= <String, String>{};
               unserializableExports[name] = member.message.message;
             } else {
-              library.additionalExports.add(member.target.reference);
+              // Eventually (in #buildBuilder) members aren't added to the
+              // library if the have 'next' pointers, so don't add them as
+              // additionalExports either. Add the last one only (the one that
+              // will eventually be added to the library).
+              Declaration memberLast = member;
+              while (memberLast.next != null) memberLast = memberLast.next;
+              library.additionalExports.add(memberLast.target.reference);
             }
         }
       }
@@ -1562,7 +1577,7 @@
       for (TypeParameter parameter in typeParameters) {
         checkBoundsInType(
             parameter.bound, typeEnvironment, parameter.fileOffset,
-            allowSuperBounded: false);
+            allowSuperBounded: true);
       }
     }
     if (positionalParameters != null) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart
new file mode 100644
index 0000000..1c9f1f0
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2019, 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 fasta.kernel_metadata_builder;
+
+import 'package:kernel/ast.dart' show Annotatable, Class, Library;
+
+import 'kernel_body_builder.dart' show KernelBodyBuilder;
+
+import 'kernel_builder.dart'
+    show
+        KernelClassBuilder,
+        KernelLibraryBuilder,
+        MetadataBuilder,
+        MemberBuilder;
+
+import '../scanner.dart' show Token;
+
+import '../scope.dart' show Scope;
+
+class KernelMetadataBuilder extends MetadataBuilder {
+  final Token beginToken;
+
+  int get charOffset => beginToken.charOffset;
+
+  KernelMetadataBuilder(this.beginToken);
+
+  static void buildAnnotations(
+      Annotatable parent,
+      List<MetadataBuilder> metadata,
+      KernelLibraryBuilder library,
+      KernelClassBuilder classBuilder,
+      MemberBuilder member,
+      Scope parameterScope) {
+    if (metadata == null) return;
+    Uri fileUri = member?.fileUri ?? classBuilder?.fileUri ?? library.fileUri;
+    Scope scope = parent is Library || parent is Class || classBuilder == null
+        ? library.scope
+        : classBuilder.scope;
+    KernelBodyBuilder bodyBuilder = new KernelBodyBuilder.forOutlineExpression(
+        library, classBuilder, member, scope, parameterScope, fileUri);
+    for (int i = 0; i < metadata.length; ++i) {
+      KernelMetadataBuilder annotationBuilder = metadata[i];
+      parent.addAnnotation(
+          bodyBuilder.parseAnnotation(annotationBuilder.beginToken));
+    }
+    bodyBuilder.inferAnnotations(parent.annotations);
+    bodyBuilder.resolveRedirectingFactoryTargets();
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
index 2434d09..0e9e42e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
@@ -65,6 +65,7 @@
         FormalParameterBuilder,
         KernelFormalParameterBuilder,
         KernelLibraryBuilder,
+        KernelMetadataBuilder,
         KernelTypeBuilder,
         KernelTypeVariableBuilder,
         LibraryBuilder,
@@ -361,6 +362,18 @@
     return procedure;
   }
 
+  @override
+  void buildOutlineExpressions(LibraryBuilder library) {
+    ClassBuilder classBuilder = isClassMember ? parent : null;
+    KernelMetadataBuilder.buildAnnotations(
+        target,
+        metadata,
+        library,
+        classBuilder,
+        this,
+        computeFormalParameterScope(classBuilder?.scope ?? library.scope));
+  }
+
   Procedure get target => origin.procedure;
 
   @override
@@ -483,6 +496,18 @@
     return constructor;
   }
 
+  @override
+  void buildOutlineExpressions(LibraryBuilder library) {
+    ClassBuilder classBuilder = isClassMember ? parent : null;
+    KernelMetadataBuilder.buildAnnotations(
+        target,
+        metadata,
+        library,
+        classBuilder,
+        this,
+        computeFormalParameterScope(classBuilder?.scope ?? library.scope));
+  }
+
   FunctionNode buildFunction(LibraryBuilder library) {
     // According to the specification §9.3 the return type of a constructor
     // function is its enclosing class.
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 4533ae4..5d67c40 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -279,6 +279,7 @@
       loader.checkRedirectingFactories(myClasses);
       loader.addNoSuchMethodForwarders(myClasses);
       loader.checkMixins(myClasses);
+      loader.buildOutlineExpressions();
       installAllComponentProblems(loader.allComponentProblems);
       loader.allComponentProblems.clear();
       return component;
@@ -651,10 +652,14 @@
           superTarget ??= defaultSuperConstructor(cls);
           Initializer initializer;
           if (superTarget == null) {
+            int offset = constructor.fileOffset;
+            if (offset == -1 && constructor.isSynthetic) {
+              offset = cls.fileOffset;
+            }
             builder.addProblem(
                 templateSuperclassHasNoDefaultConstructor
                     .withArguments(cls.superclass.name),
-                constructor.fileOffset,
+                offset,
                 noLength);
             initializer = new InvalidInitializer();
           } else {
@@ -770,6 +775,12 @@
   /// Run all transformations that are needed when building a bundle of
   /// libraries for the first time.
   void runBuildTransformations() {
+    backendTarget.performPreConstantEvaluationTransformations(
+        component,
+        loader.coreTypes,
+        loader.libraries,
+        new KernelDiagnosticReporter(loader),
+        logger: (String msg) => ticker.logMs(msg));
     if (loader.target.enableConstantUpdate2018) {
       TypeEnvironment environment =
           new TypeEnvironment(loader.coreTypes, loader.hierarchy);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
index e9c4064..f5daa9d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
@@ -44,7 +44,7 @@
   DartType thisType;
 
   KernelTypeAliasBuilder(
-      List<MetadataBuilder<KernelTypeBuilder>> metadata,
+      List<MetadataBuilder> metadata,
       String name,
       List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables,
       KernelFunctionTypeBuilder type,
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
index bbc7186..6cab740 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
@@ -13,6 +13,7 @@
         Block,
         BlockExpression,
         Class,
+        ConditionalExpression,
         DartType,
         DynamicType,
         Expression,
@@ -22,7 +23,10 @@
         ForStatement,
         IfStatement,
         InterfaceType,
+        Let,
+        ListConcatenation,
         ListLiteral,
+        MapConcatenation,
         MapEntry,
         MapLiteral,
         MethodInvocation,
@@ -31,6 +35,7 @@
         NullLiteral,
         Procedure,
         PropertyGet,
+        SetConcatenation,
         SetLiteral,
         Statement,
         StaticInvocation,
@@ -58,6 +63,8 @@
         SpreadElement,
         SpreadMapEntry;
 
+import '../problems.dart' show getFileUri, unhandled;
+
 import '../source/source_loader.dart' show SourceLoader;
 
 import 'redirecting_factory_body.dart' show RedirectingFactoryBody;
@@ -277,8 +284,10 @@
 
   @override
   TreeNode visitListLiteral(ListLiteral node) {
-    // Const collections are handled by the constant evaluator.
-    if (node.isConst) return node;
+    if (node.isConst) {
+      return _translateConstListOrSet(node, node.typeArgument, node.expressions,
+          isSet: false);
+    }
 
     return _translateListOrSet(node, node.typeArgument, node.expressions,
         isSet: false);
@@ -286,8 +295,10 @@
 
   @override
   TreeNode visitSetLiteral(SetLiteral node) {
-    // Const collections are handled by the constant evaluator.
-    if (node.isConst) return node;
+    if (node.isConst) {
+      return _translateConstListOrSet(node, node.typeArgument, node.expressions,
+          isSet: true);
+    }
 
     return _translateListOrSet(node, node.typeArgument, node.expressions,
         isSet: true);
@@ -295,8 +306,9 @@
 
   @override
   TreeNode visitMapLiteral(MapLiteral node) {
-    // Const collections are handled by the constant evaluator.
-    if (node.isConst) return node;
+    if (node.isConst) {
+      return _translateConstMap(node);
+    }
 
     // Translate entries in place up to the first control-flow entry, if any.
     int i = 0;
@@ -479,4 +491,150 @@
     }
     body.add(statement);
   }
+
+  TreeNode _translateConstListOrSet(
+      Expression node, DartType elementType, List<Expression> elements,
+      {bool isSet: false}) {
+    // Translate elements in place up to the first non-expression, if any.
+    int i = 0;
+    for (; i < elements.length; ++i) {
+      if (elements[i] is ControlFlowElement) break;
+      elements[i] = elements[i].accept(this)..parent = node;
+    }
+
+    // If there were only expressions, we are done.
+    if (i == elements.length) return node;
+
+    Expression makeLiteral(List<Expression> expressions) {
+      return isSet
+          ? new SetLiteral(expressions,
+              typeArgument: elementType, isConst: true)
+          : new ListLiteral(expressions,
+              typeArgument: elementType, isConst: true);
+    }
+
+    // Build a concatenation node.
+    List<Expression> parts = [];
+    List<Expression> currentPart = i > 0 ? elements.sublist(0, i) : null;
+
+    for (; i < elements.length; ++i) {
+      Expression element = elements[i];
+      if (element is SpreadElement) {
+        if (currentPart != null) {
+          parts.add(makeLiteral(currentPart));
+          currentPart = null;
+        }
+        Expression spreadExpression = element.expression.accept(this);
+        if (element.isNullAware) {
+          VariableDeclaration temp =
+              new VariableDeclaration(null, initializer: spreadExpression);
+          parts.add(new Let(
+              temp,
+              new ConditionalExpression(
+                  new MethodInvocation(new VariableGet(temp), new Name('=='),
+                      new Arguments([new NullLiteral()])),
+                  makeLiteral([]),
+                  new VariableGet(temp),
+                  const DynamicType())));
+        } else {
+          parts.add(spreadExpression);
+        }
+      } else if (element is IfElement) {
+        if (currentPart != null) {
+          parts.add(makeLiteral(currentPart));
+          currentPart = null;
+        }
+        Expression condition = element.condition.accept(this);
+        Expression then = makeLiteral([element.then]).accept(this);
+        Expression otherwise = element.otherwise != null
+            ? makeLiteral([element.otherwise]).accept(this)
+            : makeLiteral([]);
+        parts.add(new ConditionalExpression(
+            condition, then, otherwise, const DynamicType()));
+      } else if (element is ForElement || element is ForInElement) {
+        // Rejected earlier.
+        unhandled("${element.runtimeType}", "_translateConstListOrSet",
+            element.fileOffset, getFileUri(element));
+      } else {
+        currentPart ??= <Expression>[];
+        currentPart.add(element.accept(this));
+      }
+    }
+    if (currentPart != null) {
+      parts.add(makeLiteral(currentPart));
+    }
+    return isSet
+        ? new SetConcatenation(parts, typeArgument: elementType)
+        : new ListConcatenation(parts, typeArgument: elementType);
+  }
+
+  TreeNode _translateConstMap(MapLiteral node) {
+    // Translate entries in place up to the first control-flow entry, if any.
+    int i = 0;
+    for (; i < node.entries.length; ++i) {
+      if (node.entries[i] is ControlFlowMapEntry) break;
+      node.entries[i] = node.entries[i].accept(this)..parent = node;
+    }
+
+    // If there were no control-flow entries we are done.
+    if (i == node.entries.length) return node;
+
+    MapLiteral makeLiteral(List<MapEntry> entries) {
+      return new MapLiteral(entries,
+          keyType: node.keyType, valueType: node.valueType, isConst: true);
+    }
+
+    // Build a concatenation node.
+    List<Expression> parts = [];
+    List<MapEntry> currentPart = i > 0 ? node.entries.sublist(0, i) : null;
+
+    for (; i < node.entries.length; ++i) {
+      MapEntry entry = node.entries[i];
+      if (entry is SpreadMapEntry) {
+        if (currentPart != null) {
+          parts.add(makeLiteral(currentPart));
+          currentPart = null;
+        }
+        Expression spreadExpression = entry.expression.accept(this);
+        if (entry.isNullAware) {
+          VariableDeclaration temp =
+              new VariableDeclaration(null, initializer: spreadExpression);
+          parts.add(new Let(
+              temp,
+              new ConditionalExpression(
+                  new MethodInvocation(new VariableGet(temp), new Name('=='),
+                      new Arguments([new NullLiteral()])),
+                  makeLiteral([]),
+                  new VariableGet(temp),
+                  const DynamicType())));
+        } else {
+          parts.add(spreadExpression);
+        }
+      } else if (entry is IfMapEntry) {
+        if (currentPart != null) {
+          parts.add(makeLiteral(currentPart));
+          currentPart = null;
+        }
+        Expression condition = entry.condition.accept(this);
+        Expression then = makeLiteral([entry.then]).accept(this);
+        Expression otherwise = entry.otherwise != null
+            ? makeLiteral([entry.otherwise]).accept(this)
+            : makeLiteral([]);
+        parts.add(new ConditionalExpression(
+            condition, then, otherwise, const DynamicType()));
+      } else if (entry is ForMapEntry || entry is ForInMapEntry) {
+        // Rejected earlier.
+        unhandled("${entry.runtimeType}", "_translateConstMap",
+            entry.fileOffset, getFileUri(entry));
+      } else {
+        currentPart ??= <MapEntry>[];
+        currentPart.add(entry.accept(this));
+      }
+    }
+    if (currentPart != null) {
+      parts.add(makeLiteral(currentPart));
+    }
+    return new MapConcatenation(parts,
+        keyType: node.keyType, valueType: node.valueType);
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index d05e0d8..6c04afb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -19,6 +19,8 @@
 
 import 'package:kernel/type_algebra.dart' show containsTypeVariable;
 
+import 'package:kernel/src/bounds_checks.dart' show Variance;
+
 import 'package:kernel/util/graph.dart' show Graph, computeStrongComponents;
 
 import 'kernel_builder.dart'
@@ -31,6 +33,7 @@
         KernelFormalParameterBuilder,
         KernelFunctionTypeBuilder,
         KernelNamedTypeBuilder,
+        KernelTypeAliasBuilder,
         KernelTypeBuilder,
         KernelTypeVariableBuilder,
         NamedTypeBuilder,
@@ -51,6 +54,79 @@
         templateNonSimpleBoundViaReference,
         templateNonSimpleBoundViaVariable;
 
+export 'package:kernel/src/bounds_checks.dart' show Variance;
+
+// Computes the variance of a variable in a type.  The function can be run
+// before the types are resolved to compute variances of typedefs' type
+// variables.  For that case if the type has its declaration set to null and its
+// name matches that of the variable, it's interpreted as an occurrence of a
+// type variable.
+int computeVariance(
+    KernelTypeVariableBuilder variable, KernelTypeBuilder type) {
+  if (type is KernelNamedTypeBuilder) {
+    TypeDeclarationBuilder declaration = type.declaration;
+    if (declaration == null || declaration is KernelTypeVariableBuilder) {
+      if (type.name == variable.name) {
+        return Variance.covariant;
+      } else {
+        return Variance.unrelated;
+      }
+    } else {
+      if (declaration is KernelClassBuilder) {
+        int result = Variance.unrelated;
+        if (type.arguments != null) {
+          for (KernelTypeBuilder argument in type.arguments) {
+            result = Variance.meet(result, computeVariance(variable, argument));
+          }
+        }
+        return result;
+      } else if (declaration is KernelTypeAliasBuilder) {
+        int result = Variance.unrelated;
+        if (type.arguments != null) {
+          for (int i = 0; i < type.arguments.length; ++i) {
+            result = Variance.meet(
+                result,
+                Variance.combine(
+                    computeVariance(variable, type.arguments[i]),
+                    computeVariance(
+                        declaration.typeVariables[i], declaration.type)));
+          }
+        }
+        return result;
+      }
+    }
+  } else if (type is KernelFunctionTypeBuilder) {
+    int result = Variance.unrelated;
+    if (type.returnType != null) {
+      result =
+          Variance.meet(result, computeVariance(variable, type.returnType));
+    }
+    if (type.typeVariables != null) {
+      for (KernelTypeVariableBuilder typeVariable in type.typeVariables) {
+        // If [variable] is referenced in the bound at all, it makes the
+        // variance of [variable] in the entire type invariant.  The invocation
+        // of [computeVariance] below is made to simply figure out if [variable]
+        // occurs in the bound.
+        if (typeVariable.bound != null &&
+            computeVariance(variable, typeVariable.bound) !=
+                Variance.unrelated) {
+          result = Variance.invariant;
+        }
+      }
+    }
+    if (type.formals != null) {
+      for (KernelFormalParameterBuilder formal in type.formals) {
+        result = Variance.meet(
+            result,
+            Variance.combine(Variance.contravariant,
+                computeVariance(variable, formal.type)));
+      }
+    }
+    return result;
+  }
+  return Variance.unrelated;
+}
+
 KernelTypeBuilder substituteRange(
     KernelTypeBuilder type,
     Map<TypeVariableBuilder, KernelTypeBuilder> upperSubstitution,
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
index 43815bf..7b329bf 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
@@ -20,6 +20,7 @@
         InstanceConstant,
         IntConstant,
         InterfaceType,
+        Library,
         ListConstant,
         MapConstant,
         NullConstant,
@@ -29,6 +30,7 @@
         StringConstant,
         SymbolConstant,
         TearOffConstant,
+        TreeNode,
         TypedefType,
         TypeLiteralConstant,
         TypeParameter,
@@ -50,9 +52,8 @@
 /// distinguish different types with the same name. This is used in diagnostic
 /// messages to indicate the origins of types occurring in the message.
 class TypeLabeler implements DartTypeVisitor<void>, ConstantVisitor<void> {
-  List<LabeledClassName> names = <LabeledClassName>[];
-  Map<String, List<LabeledClassName>> nameMap =
-      <String, List<LabeledClassName>>{};
+  List<LabeledNode> names = <LabeledNode>[];
+  Map<String, List<LabeledNode>> nameMap = <String, List<LabeledNode>>{};
 
   List<Object> result;
 
@@ -84,7 +85,7 @@
   /// types and constants that have been pretty-printed using this labeler.
   String get originMessages {
     StringBuffer messages = new StringBuffer();
-    for (LabeledClassName name in names) {
+    for (LabeledNode name in names) {
       messages.write(name.originMessage);
     }
     return messages.toString();
@@ -99,25 +100,28 @@
     return false;
   }
 
-  LabeledClassName nameForClass(Class classNode) {
-    List<LabeledClassName> classesForName = nameMap[classNode.name];
-    if (classesForName == null) {
-      // First encountered class with this name
-      LabeledClassName name = new LabeledClassName(classNode, this);
+  LabeledNode nameForEntity(
+      TreeNode node, String nodeName, Uri importUri, Uri fileUri) {
+    List<LabeledNode> labelsForName = nameMap[nodeName];
+    if (labelsForName == null) {
+      // First encountered entity with this name
+      LabeledNode name =
+          new LabeledNode(node, nodeName, importUri, fileUri, this);
       names.add(name);
-      nameMap[classNode.name] = [name];
+      nameMap[nodeName] = [name];
       return name;
     } else {
-      for (LabeledClassName classForName in classesForName) {
-        if (classForName.classNode == classNode) {
-          // Previously encountered class
-          return classForName;
+      for (LabeledNode entityForName in labelsForName) {
+        if (entityForName.node == node) {
+          // Previously encountered entity
+          return entityForName;
         }
       }
-      // New class with name that was previously encountered
-      LabeledClassName name = new LabeledClassName(classNode, this);
+      // New entity with name that was previously encountered
+      LabeledNode name =
+          new LabeledNode(node, nodeName, importUri, fileUri, this);
       names.add(name);
-      classesForName.add(name);
+      labelsForName.add(name);
       return name;
     }
   }
@@ -144,7 +148,19 @@
   }
 
   void visitTypeParameterType(TypeParameterType node) {
-    result.add(node.parameter.name);
+    TreeNode parent = node.parameter;
+    while (parent is! Library && parent != null) {
+      parent = parent.parent;
+    }
+    // Note that this can be null if, for instance, the errornious code is not
+    // actually in the tree - then we don't know where it comes from!
+    Library enclosingLibrary = parent;
+
+    result.add(nameForEntity(
+        node.parameter,
+        node.parameter.name,
+        enclosingLibrary == null ? unknownUri : enclosingLibrary.importUri,
+        enclosingLibrary == null ? unknownUri : enclosingLibrary.fileUri));
   }
 
   void visitFunctionType(FunctionType node) {
@@ -201,7 +217,12 @@
   }
 
   void visitInterfaceType(InterfaceType node) {
-    result.add(nameForClass(node.classNode));
+    Class classNode = node.classNode;
+    result.add(nameForEntity(
+        classNode,
+        classNode.name,
+        classNode.enclosingLibrary.importUri,
+        classNode.enclosingLibrary.fileUri));
     if (node.typeArguments.isNotEmpty) {
       result.add("<");
       bool first = true;
@@ -301,7 +322,11 @@
     Procedure procedure = node.procedure;
     Class classNode = procedure.enclosingClass;
     if (classNode != null) {
-      result.add(nameForClass(classNode));
+      result.add(nameForEntity(
+          classNode,
+          classNode.name,
+          classNode.enclosingLibrary.importUri,
+          classNode.enclosingLibrary.fileUri));
       result.add(".");
     }
     result.add(procedure.name.name);
@@ -330,34 +355,44 @@
   }
 }
 
-class LabeledClassName {
-  Class classNode;
-  TypeLabeler typeLabeler;
+final Uri unknownUri = Uri.parse("unknown");
 
-  LabeledClassName(this.classNode, this.typeLabeler);
+class LabeledNode {
+  final TreeNode node;
+  final TypeLabeler typeLabeler;
+  final String name;
+  final Uri importUri;
+  final Uri fileUri;
+
+  LabeledNode(
+      this.node, this.name, this.importUri, this.fileUri, this.typeLabeler);
 
   String toString() {
-    String name = classNode.name;
-    List<LabeledClassName> classesForName = typeLabeler.nameMap[name];
-    if (classesForName.length == 1) {
+    List<LabeledNode> entityForName = typeLabeler.nameMap[name];
+    if (entityForName.length == 1) {
       return name;
     }
-    return "$name/*${classesForName.indexOf(this) + 1}*/";
+    return "$name/*${entityForName.indexOf(this) + 1}*/";
   }
 
   String get originMessage {
-    Uri importUri = classNode.enclosingLibrary.importUri;
     if (importUri.scheme == 'dart' && importUri.path == 'core') {
-      String name = classNode.name;
-      if (blacklistedCoreClasses.contains(name)) {
+      if (node is Class && blacklistedCoreClasses.contains(name)) {
         // Blacklisted core class. Only print if ambiguous.
-        List<LabeledClassName> classesForName = typeLabeler.nameMap[name];
-        if (classesForName.length == 1) {
+        List<LabeledNode> entityForName = typeLabeler.nameMap[name];
+        if (entityForName.length == 1) {
           return "";
         }
       }
     }
-    Uri fileUri = classNode.enclosingLibrary.fileUri;
+    if (importUri == unknownUri || node is! Class) {
+      // We don't know where it comes from and/or it's not a class.
+      // Only print if ambiguous.
+      List<LabeledNode> entityForName = typeLabeler.nameMap[name];
+      if (entityForName.length == 1) {
+        return "";
+      }
+    }
     Message message = (importUri == fileUri || importUri.scheme == 'dart')
         ? templateTypeOrigin.withArguments(toString(), importUri)
         : templateTypeOriginWithFileUri.withArguments(
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index 1b96164..c074608 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart
@@ -60,12 +60,15 @@
 
 /// Serialize the libraries in [component] that match [filter].
 List<int> serializeComponent(Component component,
-    {bool filter(Library library), bool includeSources: true}) {
+    {bool filter(Library library),
+    bool includeSources: true,
+    bool includeOffsets: true}) {
   ByteSink byteSink = new ByteSink();
   BinaryPrinter printer = filter == null
-      ? new BinaryPrinter(byteSink, includeSources: includeSources)
-      : new LimitedBinaryPrinter(
-          byteSink, filter ?? (_) => true, !includeSources);
+      ? new BinaryPrinter(byteSink,
+          includeSources: includeSources, includeOffsets: includeOffsets)
+      : new LimitedBinaryPrinter(byteSink, filter, !includeSources,
+          includeOffsets: includeOffsets);
   printer.writeComponentFile(component);
   return byteSink.builder.takeBytes();
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index 67ce675..26d6421 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -11,7 +11,6 @@
         Component,
         ExpressionStatement,
         Field,
-        InvalidInitializer,
         Let,
         Library,
         Member,
@@ -175,11 +174,6 @@
   }
 
   @override
-  visitInvalidInitializer(InvalidInitializer node) {
-    problem(node, "Invalid initializer.");
-  }
-
-  @override
   visitUnknownType(UnknownType node) {
     // Note: we can't pass [node] to [problem] because it's not a [TreeNode].
     problem(null, "Unexpected appearance of the unknown type.");
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index b63af14..64ec528 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -13,6 +13,11 @@
   ForwardingListener([this.listener]);
 
   @override
+  set suppressParseErrors(bool value) {
+    listener?.suppressParseErrors = value;
+  }
+
+  @override
   Uri get uri => listener?.uri;
 
   @override
@@ -61,13 +66,13 @@
   }
 
   @override
-  void beginClassOrMixinBody(Token token) {
-    listener?.beginClassOrMixinBody(token);
+  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+    listener?.beginClassDeclaration(begin, abstractToken, name);
   }
 
   @override
-  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
-    listener?.beginClassDeclaration(begin, abstractToken, name);
+  void beginClassOrMixinBody(Token token) {
+    listener?.beginClassOrMixinBody(token);
   }
 
   @override
@@ -86,6 +91,11 @@
   }
 
   @override
+  void beginConditionalExpression(Token question) {
+    listener?.beginConditionalExpression(question);
+  }
+
+  @override
   void beginConditionalUri(Token ifKeyword) {
     listener?.beginConditionalUri(ifKeyword);
   }
@@ -136,6 +146,11 @@
   }
 
   @override
+  void beginExtensionDeclaration(Token extensionKeyword, Token name) {
+    listener?.beginExtensionDeclaration(extensionKeyword, name);
+  }
+
+  @override
   void beginFactoryMethod(
       Token lastConsumed, Token externalToken, Token constToken) {
     listener?.beginFactoryMethod(lastConsumed, externalToken, constToken);
@@ -162,20 +177,15 @@
   }
 
   @override
-  void beginForStatement(Token token) {
-    listener?.beginForStatement(token);
-  }
-
-  @override
-  void beginForStatementBody(Token token) {
-    listener?.beginForStatementBody(token);
-  }
-
-  @override
-  void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
-      Token varFinalOrConst) {
+  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+      Token covariantToken, Token varFinalOrConst) {
     listener?.beginFormalParameter(
-        token, kind, covariantToken, varFinalOrConst);
+        token, kind, requiredToken, covariantToken, varFinalOrConst);
+  }
+
+  @override
+  void beginFormalParameterDefaultValueExpression() {
+    listener?.beginFormalParameterDefaultValueExpression();
   }
 
   @override
@@ -184,8 +194,13 @@
   }
 
   @override
-  void beginLocalFunctionDeclaration(Token token) {
-    listener?.beginLocalFunctionDeclaration(token);
+  void beginForStatement(Token token) {
+    listener?.beginForStatement(token);
+  }
+
+  @override
+  void beginForStatementBody(Token token) {
+    listener?.beginForStatementBody(token);
   }
 
   @override
@@ -224,13 +239,13 @@
   }
 
   @override
-  void beginThenControlFlow(Token token) {
-    listener?.beginThenControlFlow(token);
+  void beginIfStatement(Token token) {
+    listener?.beginIfStatement(token);
   }
 
   @override
-  void beginIfStatement(Token token) {
-    listener?.beginIfStatement(token);
+  void beginImplicitCreationExpression(Token token) {
+    listener?.beginImplicitCreationExpression(token);
   }
 
   @override
@@ -274,6 +289,11 @@
   }
 
   @override
+  void beginLocalFunctionDeclaration(Token token) {
+    listener?.beginLocalFunctionDeclaration(token);
+  }
+
+  @override
   void beginMember() {
     listener?.beginMember();
   }
@@ -367,6 +387,11 @@
   }
 
   @override
+  void beginThenControlFlow(Token token) {
+    listener?.beginThenControlFlow(token);
+  }
+
+  @override
   void beginThenStatement(Token token) {
     listener?.beginThenStatement(token);
   }
@@ -412,8 +437,9 @@
   }
 
   @override
-  void beginVariablesDeclaration(Token token, Token varFinalOrConst) {
-    listener?.beginVariablesDeclaration(token, varFinalOrConst);
+  void beginVariablesDeclaration(
+      Token token, Token lateToken, Token varFinalOrConst) {
+    listener?.beginVariablesDeclaration(token, lateToken, varFinalOrConst);
   }
 
   @override
@@ -484,13 +510,13 @@
   }
 
   @override
-  void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
-    listener?.endClassOrMixinBody(memberCount, beginToken, endToken);
+  void endClassDeclaration(Token beginToken, Token endToken) {
+    listener?.endClassDeclaration(beginToken, endToken);
   }
 
   @override
-  void endClassDeclaration(Token beginToken, Token endToken) {
-    listener?.endClassDeclaration(beginToken, endToken);
+  void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
+    listener?.endClassOrMixinBody(memberCount, beginToken, endToken);
   }
 
   @override
@@ -504,6 +530,11 @@
   }
 
   @override
+  void endConditionalExpression(Token question, Token colon) {
+    listener?.endConditionalExpression(question, colon);
+  }
+
+  @override
   void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
     listener?.endConditionalUri(ifKeyword, leftParen, equalSign);
   }
@@ -556,6 +587,11 @@
   }
 
   @override
+  void endExtensionDeclaration(Token onKeyword, Token token) {
+    listener?.endExtensionDeclaration(onKeyword, token);
+  }
+
+  @override
   void endFactoryMethod(
       Token beginToken, Token factoryKeyword, Token endToken) {
     listener?.endFactoryMethod(beginToken, factoryKeyword, endToken);
@@ -567,10 +603,10 @@
   }
 
   @override
-  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
-      int count, Token beginToken, Token endToken) {
-    listener?.endFields(staticToken, covariantToken, varFinalOrConst, count,
-        beginToken, endToken);
+  void endFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+    listener?.endFields(staticToken, covariantToken, lateToken, varFinalOrConst,
+        count, beginToken, endToken);
   }
 
   @override
@@ -579,11 +615,6 @@
   }
 
   @override
-  void endForInControlFlow(Token token) {
-    listener?.endForInControlFlow(token);
-  }
-
-  @override
   void endForIn(Token endToken) {
     listener?.endForIn(endToken);
   }
@@ -594,21 +625,16 @@
   }
 
   @override
+  void endForInControlFlow(Token token) {
+    listener?.endForInControlFlow(token);
+  }
+
+  @override
   void endForInExpression(Token token) {
     listener?.endForInExpression(token);
   }
 
   @override
-  void endForStatement(Token endToken) {
-    listener?.endForStatement(endToken);
-  }
-
-  @override
-  void endForStatementBody(Token token) {
-    listener?.endForStatementBody(token);
-  }
-
-  @override
   void endFormalParameter(Token thisKeyword, Token periodAfterThis,
       Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
     listener?.endFormalParameter(
@@ -616,14 +642,24 @@
   }
 
   @override
+  void endFormalParameterDefaultValueExpression() {
+    listener?.endFormalParameterDefaultValueExpression();
+  }
+
+  @override
   void endFormalParameters(
       int count, Token beginToken, Token endToken, MemberKind kind) {
     listener?.endFormalParameters(count, beginToken, endToken, kind);
   }
 
   @override
-  void endLocalFunctionDeclaration(Token endToken) {
-    listener?.endLocalFunctionDeclaration(endToken);
+  void endForStatement(Token endToken) {
+    listener?.endForStatement(endToken);
+  }
+
+  @override
+  void endForStatementBody(Token token) {
+    listener?.endForStatementBody(token);
   }
 
   @override
@@ -648,8 +684,8 @@
   }
 
   @override
-  void endFunctionTypedFormalParameter(Token nameToken) {
-    listener?.endFunctionTypedFormalParameter(nameToken);
+  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
+    listener?.endFunctionTypedFormalParameter(nameToken, question);
   }
 
   @override
@@ -673,6 +709,11 @@
   }
 
   @override
+  void endImplicitCreationExpression(Token token) {
+    listener?.endImplicitCreationExpression(token);
+  }
+
+  @override
   void endImport(Token importKeyword, Token semicolon) {
     listener?.endImport(importKeyword, semicolon);
   }
@@ -703,25 +744,6 @@
   }
 
   @override
-  void handleLiteralMapEntry(Token colon, Token endToken) {
-    listener?.handleLiteralMapEntry(colon, endToken);
-  }
-
-  @override
-  void handleLiteralSetOrMap(
-    int count,
-    Token leftBrace,
-    Token constKeyword,
-    Token rightBrace,
-    // TODO(danrubel): hasSetEntry parameter exists for replicating existing
-    // behavior and will be removed once unified collection has been enabled
-    bool hasSetEntry,
-  ) {
-    listener?.handleLiteralSetOrMap(
-        count, leftBrace, constKeyword, rightBrace, hasSetEntry);
-  }
-
-  @override
   void endLiteralString(int interpolationCount, Token endToken) {
     listener?.endLiteralString(interpolationCount, endToken);
   }
@@ -732,6 +754,11 @@
   }
 
   @override
+  void endLocalFunctionDeclaration(Token endToken) {
+    listener?.endLocalFunctionDeclaration(endToken);
+  }
+
+  @override
   void endMember() {
     listener?.endMember();
   }
@@ -846,10 +873,16 @@
   }
 
   @override
-  void endTopLevelFields(Token staticToken, Token covariantToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
-    listener?.endTopLevelFields(staticToken, covariantToken, varFinalOrConst,
-        count, beginToken, endToken);
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    listener?.endTopLevelFields(staticToken, covariantToken, lateToken,
+        varFinalOrConst, count, beginToken, endToken);
   }
 
   @override
@@ -976,21 +1009,11 @@
   }
 
   @override
-  void beginConditionalExpression(Token question) {
-    listener?.beginConditionalExpression(question);
-  }
-
-  @override
   void handleConditionalExpressionColon() {
     listener?.handleConditionalExpressionColon();
   }
 
   @override
-  void endConditionalExpression(Token question, Token colon) {
-    listener?.endConditionalExpression(question, colon);
-  }
-
-  @override
   void handleContinueStatement(
       bool hasTarget, Token continueKeyword, Token endToken) {
     listener?.handleContinueStatement(hasTarget, continueKeyword, endToken);
@@ -1007,28 +1030,18 @@
   }
 
   @override
-  void beginImplicitCreationExpression(Token token) {
-    listener?.beginImplicitCreationExpression(token);
-  }
-
-  @override
-  void endImplicitCreationExpression(Token token) {
-    listener?.endImplicitCreationExpression(token);
-  }
-
-  @override
   void handleElseControlFlow(Token elseToken) {
     listener?.handleElseControlFlow(elseToken);
   }
 
   @override
-  void handleEmptyStatement(Token token) {
-    listener?.handleEmptyStatement(token);
+  void handleEmptyFunctionBody(Token semicolon) {
+    listener?.handleEmptyFunctionBody(semicolon);
   }
 
   @override
-  void handleEmptyFunctionBody(Token semicolon) {
-    listener?.handleEmptyFunctionBody(semicolon);
+  void handleEmptyStatement(Token token) {
+    listener?.handleEmptyStatement(token);
   }
 
   @override
@@ -1057,6 +1070,35 @@
   }
 
   @override
+  void handleForInitializerEmptyStatement(Token token) {
+    listener?.handleForInitializerEmptyStatement(token);
+  }
+
+  @override
+  void handleForInitializerExpressionStatement(Token token) {
+    listener?.handleForInitializerExpressionStatement(token);
+  }
+
+  @override
+  void handleForInitializerLocalVariableDeclaration(Token token) {
+    listener?.handleForInitializerLocalVariableDeclaration(token);
+  }
+
+  @override
+  void handleForInLoopParts(Token awaitToken, Token forToken,
+      Token leftParenthesis, Token inKeyword) {
+    listener?.handleForInLoopParts(
+        awaitToken, forToken, leftParenthesis, inKeyword);
+  }
+
+  @override
+  void handleForLoopParts(Token forKeyword, Token leftParen,
+      Token leftSeparator, int updateExpressionCount) {
+    listener?.handleForLoopParts(
+        forKeyword, leftParen, leftSeparator, updateExpressionCount);
+  }
+
+  @override
   void handleFormalParameterWithoutValue(Token token) {
     listener?.handleFormalParameterWithoutValue(token);
   }
@@ -1077,8 +1119,8 @@
   }
 
   @override
-  void handleRecoverImport(Token semicolon) {
-    listener?.handleRecoverImport(semicolon);
+  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+    listener?.handleImportPrefix(deferredKeyword, asKeyword);
   }
 
   @override
@@ -1113,13 +1155,8 @@
   }
 
   @override
-  void handleInvalidTypeArguments(Token token) {
-    listener?.handleInvalidTypeArguments(token);
-  }
-
-  @override
-  void handleInvalidTypeReference(Token token) {
-    listener?.handleInvalidTypeReference(token);
+  void handleInvalidStatement(Token token, Message message) {
+    listener?.handleInvalidStatement(token, message);
   }
 
   void handleInvalidTopLevelBlock(Token token) {
@@ -1132,6 +1169,16 @@
   }
 
   @override
+  void handleInvalidTypeArguments(Token token) {
+    listener?.handleInvalidTypeArguments(token);
+  }
+
+  @override
+  void handleInvalidTypeReference(Token token) {
+    listener?.handleInvalidTypeReference(token);
+  }
+
+  @override
   void handleIsOperator(Token isOperator, Token not) {
     listener?.handleIsOperator(isOperator, not);
   }
@@ -1142,11 +1189,6 @@
   }
 
   @override
-  void handleLanguageVersion(Token commentToken, int major, int minor) {
-    listener?.handleLanguageVersion(commentToken, major, minor);
-  }
-
-  @override
   void handleLiteralBool(Token token) {
     listener?.handleLiteralBool(token);
   }
@@ -1168,11 +1210,30 @@
   }
 
   @override
+  void handleLiteralMapEntry(Token colon, Token endToken) {
+    listener?.handleLiteralMapEntry(colon, endToken);
+  }
+
+  @override
   void handleLiteralNull(Token token) {
     listener?.handleLiteralNull(token);
   }
 
   @override
+  void handleLiteralSetOrMap(
+    int count,
+    Token leftBrace,
+    Token constKeyword,
+    Token rightBrace,
+    // TODO(danrubel): hasSetEntry parameter exists for replicating existing
+    // behavior and will be removed once unified collection has been enabled
+    bool hasSetEntry,
+  ) {
+    listener?.handleLiteralSetOrMap(
+        count, leftBrace, constKeyword, rightBrace, hasSetEntry);
+  }
+
+  @override
   void handleMixinHeader(Token mixinKeyword) {
     listener?.handleMixinHeader(mixinKeyword);
   }
@@ -1228,35 +1289,6 @@
   }
 
   @override
-  void handleForInitializerEmptyStatement(Token token) {
-    listener?.handleForInitializerEmptyStatement(token);
-  }
-
-  @override
-  void handleForInitializerExpressionStatement(Token token) {
-    listener?.handleForInitializerExpressionStatement(token);
-  }
-
-  @override
-  void handleForInitializerLocalVariableDeclaration(Token token) {
-    listener?.handleForInitializerLocalVariableDeclaration(token);
-  }
-
-  @override
-  void handleForInLoopParts(Token awaitToken, Token forToken,
-      Token leftParenthesis, Token inKeyword) {
-    listener?.handleForInLoopParts(
-        awaitToken, forToken, leftParenthesis, inKeyword);
-  }
-
-  @override
-  void handleForLoopParts(Token forKeyword, Token leftParen,
-      Token leftSeparator, int updateExpressionCount) {
-    listener?.handleForLoopParts(
-        forKeyword, leftParen, leftSeparator, updateExpressionCount);
-  }
-
-  @override
   void handleNoFieldInitializer(Token token) {
     listener?.handleNoFieldInitializer(token);
   }
@@ -1277,13 +1309,13 @@
   }
 
   @override
-  void handleNonNullAssertExpression(Token bang) {
-    listener?.handleNonNullAssertExpression(bang);
+  void handleNoName(Token token) {
+    listener?.handleNoName(token);
   }
 
   @override
-  void handleNoName(Token token) {
-    listener?.handleNoName(token);
+  void handleNonNullAssertExpression(Token bang) {
+    listener?.handleNonNullAssertExpression(bang);
   }
 
   @override
@@ -1327,26 +1359,11 @@
   }
 
   @override
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
-    listener?.handleImportPrefix(deferredKeyword, asKeyword);
-  }
-
-  @override
   void handleQualified(Token period) {
     listener?.handleQualified(period);
   }
 
   @override
-  void handleRecoverClassHeader() {
-    listener?.handleRecoverClassHeader();
-  }
-
-  @override
-  void handleRecoverMixinHeader() {
-    listener?.handleRecoverMixinHeader();
-  }
-
-  @override
   void handleRecoverableError(
       Message message, Token startToken, Token endToken) {
     if (forwardErrors) {
@@ -1355,8 +1372,18 @@
   }
 
   @override
-  void handleInvalidStatement(Token token, Message message) {
-    listener?.handleInvalidStatement(token, message);
+  void handleRecoverClassHeader() {
+    listener?.handleRecoverClassHeader();
+  }
+
+  @override
+  void handleRecoverImport(Token semicolon) {
+    listener?.handleRecoverImport(semicolon);
+  }
+
+  @override
+  void handleRecoverMixinHeader() {
+    listener?.handleRecoverMixinHeader();
   }
 
   @override
@@ -1380,12 +1407,6 @@
   }
 
   @override
-  void handleUnescapeError(
-      Message message, Token location, int offset, int length) {
-    listener?.handleUnescapeError(message, location, offset, length);
-  }
-
-  @override
   void handleStringPart(Token token) {
     listener?.handleStringPart(token);
   }
@@ -1436,13 +1457,9 @@
   }
 
   @override
-  void beginFormalParameterDefaultValueExpression() {
-    listener?.beginFormalParameterDefaultValueExpression();
-  }
-
-  @override
-  void endFormalParameterDefaultValueExpression() {
-    listener?.endFormalParameterDefaultValueExpression();
+  void handleUnescapeError(
+      Message message, Token location, int offset, int length) {
+    listener?.handleUnescapeError(message, location, offset, length);
   }
 
   @override
@@ -1466,12 +1483,12 @@
   }
 
   @override
-  void reportNonNullAssertExpressionNotEnabled(Token bang) {
-    listener?.reportNonNullAssertExpressionNotEnabled(bang);
+  void reportNonNullableModifierError(Token modifierToken) {
+    listener?.reportNonNullableModifierError(modifierToken);
   }
 
   @override
-  set suppressParseErrors(bool value) {
-    listener?.suppressParseErrors = value;
+  void reportNonNullAssertExpressionNotEnabled(Token bang) {
+    listener?.reportNonNullAssertExpressionNotEnabled(bang);
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
index 460fec9..460dc1b 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -98,7 +98,8 @@
   /// Identifier is the name being declared by a class declaration, a mixin
   /// declaration, or a named mixin application, for example,
   /// `Foo` in `class Foo = X with Y;`.
-  static const classOrMixinDeclaration = const ClassOrMixinIdentifierContext();
+  static const classOrMixinOrExtensionDeclaration =
+      const ClassOrMixinOrExtensionIdentifierContext();
 
   /// Identifier is the name of a type variable being declared (e.g. `Foo` in
   /// `class C<Foo extends num> {}`).
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
index 0dd6638..0d0fccb 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -43,9 +43,9 @@
   }
 }
 
-/// See [IdentifierContext.classOrMixinDeclaration].
-class ClassOrMixinIdentifierContext extends IdentifierContext {
-  const ClassOrMixinIdentifierContext()
+/// See [IdentifierContext.classOrMixinOrExtensionDeclaration].
+class ClassOrMixinOrExtensionIdentifierContext extends IdentifierContext {
+  const ClassOrMixinOrExtensionIdentifierContext()
       : super('classOrMixinDeclaration',
             inDeclaration: true, isBuiltInIdentifierAllowed: false);
 
@@ -59,8 +59,8 @@
 
     // Recovery
     if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-        isOneOfOrEof(
-            identifier, const ['<', '{', 'extends', 'with', 'implements'])) {
+        isOneOfOrEof(identifier,
+            const ['<', '{', 'extends', 'with', 'implements', 'on'])) {
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: fasta.templateExpectedIdentifier.withArguments(identifier));
     } else if (identifier.type.isBuiltIn) {
@@ -940,8 +940,6 @@
       parser.reportRecoverableError(identifier, fasta.messageAwaitAsIdentifier);
     } else if (optional('yield', identifier)) {
       parser.reportRecoverableError(identifier, fasta.messageYieldAsIdentifier);
-    } else if (optional('async', identifier)) {
-      parser.reportRecoverableError(identifier, fasta.messageAsyncAsIdentifier);
     }
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 9cc581a..63d333f 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -151,7 +151,7 @@
     logEvent("MixinOn");
   }
 
-  /// Handle the header of a class declaration.  Substructures:
+  /// Handle the header of a mixin declaration.  Substructures:
   /// - metadata
   /// - mixin name
   /// - type variables
@@ -179,6 +179,20 @@
     logEvent("MixinDeclaration");
   }
 
+  /// Handle the beginning of an extension methods declaration.  Substructures:
+  /// - metadata
+  /// - extension name
+  /// - type variables
+  void beginExtensionDeclaration(Token extensionKeyword, Token name) {}
+
+  /// Handle the end of an extension methods declaration.  Substructures:
+  /// - substructures from [beginExtensionDeclaration]
+  /// - on type
+  /// - body
+  void endExtensionDeclaration(Token onKeyword, Token token) {
+    logEvent('ExtensionDeclaration');
+  }
+
   void beginCombinators(Token token) {}
 
   void endCombinators(int count) {
@@ -272,8 +286,8 @@
     logEvent("FactoryMethod");
   }
 
-  void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
-      Token varFinalOrConst) {}
+  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+      Token covariantToken, Token varFinalOrConst) {}
 
   void endFormalParameter(Token thisKeyword, Token periodAfterThis,
       Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
@@ -298,8 +312,8 @@
   /// - Variable declarations (count times)
   ///
   /// Doesn't have a corresponding begin event, use [beginMember] instead.
-  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
-      int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     logEvent("Fields");
   }
 
@@ -901,8 +915,14 @@
   ///   - Field initializer
   /// Doesn't have a corresponding begin event.
   /// Use [beginTopLevelMember] instead.
-  void endTopLevelFields(Token staticToken, Token covariantToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
     logEvent("TopLevelFields");
   }
 
@@ -968,6 +988,17 @@
   }
 
   // TODO(danrubel): Remove this once all listeners have been updated
+  // to properly handle nullable types
+  void reportNonNullableModifierError(Token modifierToken) {
+    if (modifierToken != null) {
+      handleRecoverableError(
+          templateExperimentNotEnabled.withArguments('non-nullable'),
+          modifierToken,
+          modifierToken);
+    }
+  }
+
+  // TODO(danrubel): Remove this once all listeners have been updated
   // to properly handle non-null assert expressions
   void reportNonNullAssertExpressionNotEnabled(Token bang) {
     handleRecoverableError(
@@ -1050,7 +1081,8 @@
   /// Handle the start of a variables declaration.  Substructures:
   /// - Metadata
   /// - Type
-  void beginVariablesDeclaration(Token token, Token varFinalOrConst) {}
+  void beginVariablesDeclaration(
+      Token token, Token lateToken, Token varFinalOrConst) {}
 
   void endVariablesDeclaration(int count, Token endToken) {
     logEvent("VariablesDeclaration");
@@ -1157,7 +1189,7 @@
   /// - type variables
   /// - return type
   /// - formal parameters
-  void endFunctionTypedFormalParameter(Token nameToken) {
+  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
     logEvent("FunctionTypedFormalParameter");
   }
 
@@ -1405,15 +1437,6 @@
     logEvent("Script");
   }
 
-  /// A language version comment was parsed of the form
-  /// // @dart = <major>.<minor>
-  ///
-  /// For more information, see
-  /// https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/language-versioning.md#individual-library-language-version-override
-  void handleLanguageVersion(Token commentToken, int major, int minor) {
-    // TODO(danrubel): Update listeners to handle this
-  }
-
   /// A type has been just parsed, and the parser noticed that the next token
   /// has a type substitution comment /*=T*. So, the type that has been just
   /// parsed should be discarded, and a new type should be parsed instead.
diff --git a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
index 3a5c8d1..93e717d 100644
--- a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
@@ -2,8 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import '../../scanner/token.dart' show Token;
+import '../../scanner/token.dart' show Keyword, Token;
 import '../messages.dart' as fasta;
+import 'formal_parameter_kind.dart';
 import 'member_kind.dart' show MemberKind;
 import 'parser.dart' show Parser;
 import 'util.dart' show optional;
@@ -11,17 +12,20 @@
 bool isModifier(Token token) {
   if (!token.isModifier) {
     return false;
-  }
-  if (token.type.isBuiltIn) {
-    // A built-in identifier can only be a modifier as long as it is
-    // followed by another modifier or an identifier. Otherwise, it is the
+  } else if (token.type.isBuiltIn) {
+    // A built-in keyword can only be a modifier as long as it is
+    // followed by another keyword or an identifier. Otherwise, it is the
     // identifier.
     //
     // For example, `external` is a modifier in this declaration:
     //   external Foo foo();
     // but is the identifier in this declaration
     //   external() => true;
-    if (!token.next.type.isKeyword && !token.next.isIdentifier) {
+    // and in
+    //   for (final external in list) { }
+    Token next = token.next;
+    Keyword keyword = next.keyword;
+    if (keyword == null && !next.isIdentifier || keyword == Keyword.IN) {
       return false;
     }
   }
@@ -37,8 +41,9 @@
   Token covariantToken;
   Token externalToken;
   Token finalToken;
+  Token lateToken;
+  Token requiredToken;
   Token staticToken;
-  Token varFinalOrConst;
   Token varToken;
 
   // Set `true` when parsing modifiers after the `factory` token.
@@ -49,31 +54,65 @@
 
   ModifierRecoveryContext(this.parser);
 
-  /// Parse modifiers for class methods and fields.
-  Token parseClassMemberModifiers(Token token,
-      {Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token varFinalOrConst}) {
-    token = parseModifiers(token,
-        externalToken: externalToken,
-        staticToken: staticToken,
-        covariantToken: covariantToken,
-        varFinalOrConst: varFinalOrConst);
+  set staticOrCovariant(Token staticOrCovariant) {
+    if (staticOrCovariant == null) {
+      covariantToken = null;
+      staticToken = null;
+    } else if (optional('covariant', staticOrCovariant)) {
+      covariantToken = staticOrCovariant;
+      staticToken = null;
+    } else if (optional('static', staticOrCovariant)) {
+      covariantToken = null;
+      staticToken = staticOrCovariant;
+    } else {
+      throw "Internal error: "
+          "Unexpected staticOrCovariant '$staticOrCovariant'.";
+    }
+  }
 
+  Token get varFinalOrConst => varToken ?? finalToken ?? constToken;
+
+  set varFinalOrConst(Token varFinalOrConst) {
+    if (varFinalOrConst == null) {
+      varToken = null;
+      finalToken = null;
+      constToken = null;
+    } else if (optional('var', varFinalOrConst)) {
+      varToken = varFinalOrConst;
+      finalToken = null;
+      constToken = null;
+    } else if (optional('final', varFinalOrConst)) {
+      varToken = null;
+      finalToken = varFinalOrConst;
+      constToken = null;
+    } else if (optional('const', varFinalOrConst)) {
+      varToken = null;
+      finalToken = null;
+      constToken = varFinalOrConst;
+    } else {
+      throw "Internal error: Unexpected varFinalOrConst '$varFinalOrConst'.";
+    }
+  }
+
+  /// Parse modifiers for class methods and fields.
+  Token parseClassMemberModifiers(Token token) {
+    token = parseModifiers(token);
     if (abstractToken != null) {
       parser.reportRecoverableError(
           abstractToken, fasta.messageAbstractClassMember);
     }
+    reportExtraneousModifier(requiredToken);
     return token;
   }
 
   /// Parse modifiers for formal parameters.
-  Token parseFormalParameterModifiers(Token token, MemberKind memberKind,
-      {Token covariantToken, Token varFinalOrConst}) {
-    token = parseModifiers(token,
-        covariantToken: covariantToken, varFinalOrConst: varFinalOrConst);
+  Token parseFormalParameterModifiers(
+      Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
+    token = parseModifiers(token);
 
+    if (parameterKind != FormalParameterKind.optionalNamed) {
+      reportExtraneousModifier(requiredToken);
+    }
     if (memberKind == MemberKind.StaticMethod ||
         memberKind == MemberKind.TopLevelMethod) {
       reportExtraneousModifier(this.covariantToken);
@@ -81,58 +120,49 @@
     }
     if (constToken != null) {
       reportExtraneousModifier(constToken);
-      varFinalOrConst = null;
     } else if (memberKind == MemberKind.GeneralizedFunctionType) {
       if (varFinalOrConst != null) {
         parser.reportRecoverableError(
             varFinalOrConst, fasta.messageFunctionTypedParameterVar);
-        varFinalOrConst = null;
-        finalToken = null;
-        varToken = null;
       }
     }
     reportExtraneousModifier(abstractToken);
     reportExtraneousModifier(externalToken);
+    reportExtraneousModifier(lateToken);
     reportExtraneousModifier(staticToken);
     return token;
   }
 
   /// Parse modifiers after the `factory` token.
-  Token parseModifiersAfterFactory(Token token,
-      {Token externalToken, Token staticOrCovariant, Token varFinalOrConst}) {
+  Token parseModifiersAfterFactory(Token token) {
     afterFactory = true;
-    token = parseModifiers(token,
-        externalToken: externalToken,
-        staticOrCovariant: staticOrCovariant,
-        varFinalOrConst: varFinalOrConst);
-
+    token = parseModifiers(token);
     if (abstractToken != null) {
       parser.reportRecoverableError(
           abstractToken, fasta.messageAbstractClassMember);
     }
+    reportExtraneousModifier(lateToken);
+    reportExtraneousModifier(requiredToken);
     return token;
   }
 
   /// Parse modifiers for top level functions and fields.
-  Token parseTopLevelModifiers(Token token,
-      {Token externalToken, Token varFinalOrConst}) {
-    token = parseModifiers(token,
-        externalToken: externalToken, varFinalOrConst: varFinalOrConst);
-
+  Token parseTopLevelModifiers(Token token) {
+    token = parseModifiers(token);
     reportExtraneousModifier(abstractToken);
     reportExtraneousModifier(covariantToken);
+    reportExtraneousModifier(requiredToken);
     reportExtraneousModifier(staticToken);
     return token;
   }
 
   /// Parse modifiers for variable declarations.
-  Token parseVariableDeclarationModifiers(Token token,
-      {Token varFinalOrConst}) {
-    token = parseModifiers(token, varFinalOrConst: varFinalOrConst);
-
+  Token parseVariableDeclarationModifiers(Token token) {
+    token = parseModifiers(token);
     reportExtraneousModifier(abstractToken);
     reportExtraneousModifier(covariantToken);
     reportExtraneousModifier(externalToken);
+    reportExtraneousModifier(requiredToken);
     reportExtraneousModifier(staticToken);
     return token;
   }
@@ -148,42 +178,7 @@
   /// `static` or `covariant`. The first non-null parameter of
   /// [staticOrCovariant], [staticToken], or [covariantToken] will be used,
   /// in that order, and the others ignored.
-  Token parseModifiers(Token token,
-      {Token externalToken,
-      Token staticToken,
-      Token staticOrCovariant,
-      Token covariantToken,
-      Token varFinalOrConst}) {
-    if (externalToken != null) {
-      this.externalToken = externalToken;
-    }
-    if (staticOrCovariant != null) {
-      if (optional('static', staticOrCovariant)) {
-        this.staticToken = staticOrCovariant;
-      } else if (optional('covariant', staticOrCovariant)) {
-        this.covariantToken = staticOrCovariant;
-      } else {
-        throw "Internal error: "
-            "Unexpected staticOrCovariant '$staticOrCovariant'.";
-      }
-    } else if (staticToken != null) {
-      this.staticToken = staticToken;
-    } else if (covariantToken != null) {
-      this.covariantToken = covariantToken;
-    }
-    if (varFinalOrConst != null) {
-      this.varFinalOrConst = varFinalOrConst;
-      if (optional('var', varFinalOrConst)) {
-        varToken = varFinalOrConst;
-      } else if (optional('final', varFinalOrConst)) {
-        finalToken = varFinalOrConst;
-      } else if (optional('const', varFinalOrConst)) {
-        constToken = varFinalOrConst;
-      } else {
-        throw "Internal error: Unexpected varFinalOrConst '$varFinalOrConst'.";
-      }
-    }
-
+  Token parseModifiers(Token token) {
     // Process invalid and out-of-order modifiers
     Token next = token.next;
     while (true) {
@@ -199,6 +194,10 @@
           token = parseExternal(token);
         } else if (identical('final', value)) {
           token = parseFinal(token);
+        } else if (identical('late', value)) {
+          token = parseLate(token);
+        } else if (identical('required', value)) {
+          token = parseRequired(token);
         } else if (identical('static', value)) {
           token = parseStatic(token);
         } else if (identical('var', value)) {
@@ -215,7 +214,6 @@
       }
       next = token.next;
     }
-
     return token;
   }
 
@@ -237,11 +235,12 @@
     Token next = token.next;
     assert(optional('const', next));
     if (varFinalOrConst == null && covariantToken == null) {
-      varFinalOrConst = constToken = next;
+      constToken = next;
 
       if (afterFactory) {
-        parser.reportRecoverableError(next,
-            fasta.templateModifierOutOfOrder.withArguments('const', 'factory'));
+        reportModifierOutOfOrder(next, 'factory');
+      } else if (lateToken != null) {
+        reportConflictingModifiers(next, lateToken);
       }
       return next;
     }
@@ -251,11 +250,11 @@
       parser.reportRecoverableErrorWithToken(
           next, fasta.templateDuplicatedModifier);
     } else if (covariantToken != null) {
-      parser.reportRecoverableError(next, fasta.messageConstAndCovariant);
+      reportConflictingModifiers(next, covariantToken);
     } else if (finalToken != null) {
       parser.reportRecoverableError(next, fasta.messageConstAndFinal);
     } else if (varToken != null) {
-      parser.reportRecoverableError(next, fasta.messageConstAndVar);
+      reportConflictingModifiers(next, varToken);
     } else {
       throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
     }
@@ -272,9 +271,11 @@
       covariantToken = next;
 
       if (varToken != null) {
-        parser.reportRecoverableError(next, fasta.messageCovariantAfterVar);
+        reportModifierOutOfOrder(next, varToken.lexeme);
       } else if (finalToken != null) {
-        parser.reportRecoverableError(next, fasta.messageCovariantAfterFinal);
+        reportModifierOutOfOrder(next, finalToken.lexeme);
+      } else if (lateToken != null) {
+        reportModifierOutOfOrder(next, lateToken.lexeme);
       }
       return next;
     }
@@ -286,7 +287,7 @@
     } else if (afterFactory) {
       reportExtraneousModifier(next);
     } else if (constToken != null) {
-      parser.reportRecoverableError(next, fasta.messageConstAndCovariant);
+      reportConflictingModifiers(next, constToken);
     } else if (staticToken != null) {
       parser.reportRecoverableError(next, fasta.messageCovariantAndStatic);
     } else {
@@ -302,11 +303,13 @@
       externalToken = next;
 
       if (afterFactory) {
-        parser.reportRecoverableError(next, fasta.messageExternalAfterFactory);
+        reportModifierOutOfOrder(next, 'factory');
       } else if (constToken != null) {
-        parser.reportRecoverableError(next, fasta.messageExternalAfterConst);
+        reportModifierOutOfOrder(next, constToken.lexeme);
       } else if (staticToken != null) {
-        parser.reportRecoverableError(next, fasta.messageExternalAfterStatic);
+        reportModifierOutOfOrder(next, staticToken.lexeme);
+      } else if (lateToken != null) {
+        reportModifierOutOfOrder(next, lateToken.lexeme);
       }
       return next;
     }
@@ -321,7 +324,7 @@
     Token next = token.next;
     assert(optional('final', next));
     if (varFinalOrConst == null && !afterFactory) {
-      varFinalOrConst = finalToken = next;
+      finalToken = next;
       return next;
     }
 
@@ -335,12 +338,60 @@
       parser.reportRecoverableError(next, fasta.messageConstAndFinal);
     } else if (varToken != null) {
       parser.reportRecoverableError(next, fasta.messageFinalAndVar);
+    } else if (lateToken != null) {
+      reportModifierOutOfOrder(next, lateToken.lexeme);
     } else {
       throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
     }
     return next;
   }
 
+  Token parseLate(Token token) {
+    Token next = token.next;
+    assert(optional('late', next));
+    if (lateToken == null) {
+      lateToken = next;
+
+      if (constToken != null) {
+        reportConflictingModifiers(next, constToken);
+      } else if (varToken != null) {
+        reportConflictingModifiers(next, varToken);
+      } else if (finalToken != null) {
+        reportModifierOutOfOrder(next, finalToken.lexeme);
+      }
+      return next;
+    }
+
+    // Recovery
+    parser.reportRecoverableErrorWithToken(
+        next, fasta.templateDuplicatedModifier);
+    return next;
+  }
+
+  Token parseRequired(Token token) {
+    Token next = token.next;
+    assert(optional('required', next));
+    if (requiredToken == null) {
+      requiredToken = next;
+
+      if (constToken != null) {
+        reportModifierOutOfOrder(requiredToken, constToken.lexeme);
+      } else if (covariantToken != null) {
+        reportModifierOutOfOrder(requiredToken, covariantToken.lexeme);
+      } else if (finalToken != null) {
+        reportModifierOutOfOrder(requiredToken, finalToken.lexeme);
+      } else if (varToken != null) {
+        reportModifierOutOfOrder(requiredToken, varToken.lexeme);
+      }
+      return next;
+    }
+
+    // Recovery
+    parser.reportRecoverableErrorWithToken(
+        next, fasta.templateDuplicatedModifier);
+    return next;
+  }
+
   Token parseStatic(Token token) {
     Token next = token.next;
     assert(optional('static', next));
@@ -348,11 +399,13 @@
       staticToken = next;
 
       if (constToken != null) {
-        parser.reportRecoverableError(next, fasta.messageStaticAfterConst);
+        reportModifierOutOfOrder(next, constToken.lexeme);
       } else if (finalToken != null) {
-        parser.reportRecoverableError(next, fasta.messageStaticAfterFinal);
+        reportModifierOutOfOrder(next, finalToken.lexeme);
       } else if (varToken != null) {
-        parser.reportRecoverableError(next, fasta.messageStaticAfterVar);
+        reportModifierOutOfOrder(next, varToken.lexeme);
+      } else if (lateToken != null) {
+        reportModifierOutOfOrder(next, lateToken.lexeme);
       }
       return next;
     }
@@ -375,7 +428,11 @@
     Token next = token.next;
     assert(optional('var', next));
     if (varFinalOrConst == null && !afterFactory) {
-      varFinalOrConst = varToken = next;
+      varToken = next;
+
+      if (lateToken != null) {
+        reportConflictingModifiers(next, lateToken);
+      }
       return next;
     }
 
@@ -386,7 +443,7 @@
     } else if (afterFactory) {
       reportExtraneousModifier(next);
     } else if (constToken != null) {
-      parser.reportRecoverableError(next, fasta.messageConstAndVar);
+      reportConflictingModifiers(next, constToken);
     } else if (finalToken != null) {
       parser.reportRecoverableError(next, fasta.messageFinalAndVar);
     } else {
@@ -395,10 +452,24 @@
     return next;
   }
 
-  void reportExtraneousModifier(Token token) {
-    if (token != null) {
+  void reportConflictingModifiers(Token modifier, Token earlierModifier) {
+    parser.reportRecoverableError(
+        modifier,
+        fasta.templateConflictingModifiers
+            .withArguments(modifier.lexeme, earlierModifier.lexeme));
+  }
+
+  void reportExtraneousModifier(Token modifier) {
+    if (modifier != null) {
       parser.reportRecoverableErrorWithToken(
-          token, fasta.templateExtraneousModifier);
+          modifier, fasta.templateExtraneousModifier);
     }
   }
+
+  void reportModifierOutOfOrder(Token modifier, String beforeModifier) {
+    parser.reportRecoverableError(
+        modifier,
+        fasta.templateModifierOutOfOrder
+            .withArguments(modifier.lexeme, beforeModifier));
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 4a616ac..3583dc6 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -10,14 +10,11 @@
 
 import '../scanner.dart' show ErrorToken, Token;
 
-import '../scanner/characters.dart' show $0, $9, $SPACE;
-
 import '../../scanner/token.dart'
     show
         ASSIGNMENT_PRECEDENCE,
         BeginToken,
         CASCADE_PRECEDENCE,
-        CommentToken,
         EQUALITY_PRECEDENCE,
         Keyword,
         POSTFIX_PRECEDENCE,
@@ -333,6 +330,11 @@
   /// ;
   /// ```
   Token parseUnit(Token token) {
+    // Skip over error tokens and report them at the end
+    // so that the parser has the chance to adjust the error location.
+    Token errorToken = token;
+    token = skipErrorTokens(errorToken);
+
     listener.beginCompilationUnit(token);
     int count = 0;
     DirectiveContext directiveState = new DirectiveContext();
@@ -341,7 +343,6 @@
       directiveState?.checkScriptTag(this, token.next);
       token = parseScript(token);
     }
-    parseLanguageVersionOpt(token);
     while (!token.next.isEof) {
       final Token start = token.next;
       token = parseTopLevelDeclarationImpl(token, directiveState);
@@ -362,80 +363,13 @@
       }
     }
     token = token.next;
+    reportAllErrorTokens(errorToken);
     listener.endCompilationUnit(count, token);
     // Clear fields that could lead to memory leak.
     cachedRewriter = null;
     return token;
   }
 
-  /// Parse the optional language version comment as specified in
-  /// https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/language-versioning.md#individual-library-language-version-override
-  void parseLanguageVersionOpt(Token token) {
-    // TODO(danrubel): Handle @dart version multi-line comments and dartdoc
-    // or update the spec to exclude them.
-    token = token.next.precedingComments;
-    while (token is CommentToken) {
-      if (parseLanguageVersionText(token)) {
-        break;
-      }
-      token = token.next;
-    }
-  }
-
-  bool parseLanguageVersionText(CommentToken token) {
-    String text = token.lexeme;
-    if (text == null || !text.startsWith('//')) {
-      return false;
-    }
-    int index = _skipSpaces(text, 2);
-    if (!text.startsWith('@dart', index)) {
-      return false;
-    }
-    index = _skipSpaces(text, index + 5);
-    if (!text.startsWith('=', index)) {
-      return false;
-    }
-    int start = index = _skipSpaces(text, index + 1);
-    index = _skipDigits(text, start);
-    if (start == index) {
-      return false;
-    }
-    int major = int.parse(text.substring(start, index));
-    if (!text.startsWith('.', index)) {
-      return false;
-    }
-    start = index + 1;
-    index = _skipDigits(text, start);
-    if (start == index) {
-      return false;
-    }
-    int minor = int.parse(text.substring(start, index));
-    index = _skipSpaces(text, index);
-    if (index != text.length) {
-      return false;
-    }
-    listener.handleLanguageVersion(token, major, minor);
-    return true;
-  }
-
-  int _skipSpaces(String text, int index) {
-    while (index < text.length && text.codeUnitAt(index) == $SPACE) {
-      ++index;
-    }
-    return index;
-  }
-
-  int _skipDigits(String text, int index) {
-    while (index < text.length) {
-      int code = text.codeUnitAt(index);
-      if (code < $0 || code > $9) {
-        break;
-      }
-      ++index;
-    }
-    return index;
-  }
-
   /// This method exists for analyzer compatibility only
   /// and will be removed once analyzer/fasta integration is complete.
   ///
@@ -535,6 +469,7 @@
     // Skip modifiers to find a top level keyword or identifier
     if (next.isModifier) {
       if (optional('var', next) ||
+          optional('late', next) ||
           ((optional('const', next) || optional('final', next)) &&
               // Ignore `const class` and `final class` so that it is reported
               // below as an invalid modifier on a class.
@@ -565,13 +500,8 @@
       reportRecoverableError(next, fasta.messageTopLevelOperator);
       // Insert a synthetic identifier
       // and continue parsing as a top level function.
-      rewriter.insertToken(
-          next,
-          new SyntheticStringToken(
-              TokenType.IDENTIFIER,
-              '#synthetic_function_${next.charOffset}',
-              next.next.charOffset,
-              0));
+      rewriter.insertSyntheticIdentifier(
+          next, '#synthetic_function_${next.charOffset}');
       return parseTopLevelMemberImpl(next);
     }
     // Ignore any preceding modifiers and just report the unexpected token
@@ -655,23 +585,26 @@
         return parseTopLevelMemberImpl(start);
       } else {
         parseTopLevelKeywordModifiers(start, keyword);
-        if (identical(value, 'mixin')) {
-          directiveState?.checkDeclaration();
-          return parseMixin(keyword);
-        } else if (identical(value, 'typedef')) {
-          directiveState?.checkDeclaration();
-          return parseTypedef(keyword);
-        } else if (identical(value, 'library')) {
-          directiveState?.checkLibrary(this, keyword);
-          return parseLibraryName(keyword);
-        } else if (identical(value, 'import')) {
+        if (identical(value, 'import')) {
           directiveState?.checkImport(this, keyword);
           return parseImport(keyword);
         } else if (identical(value, 'export')) {
           directiveState?.checkExport(this, keyword);
           return parseExport(keyword);
+        } else if (identical(value, 'typedef')) {
+          directiveState?.checkDeclaration();
+          return parseTypedef(keyword);
+        } else if (identical(value, 'mixin')) {
+          directiveState?.checkDeclaration();
+          return parseMixin(keyword);
+        } else if (identical(value, 'extension')) {
+          directiveState?.checkDeclaration();
+          return parseExtension(keyword);
         } else if (identical(value, 'part')) {
           return parsePartOrPartOf(keyword, directiveState);
+        } else if (identical(value, 'library')) {
+          directiveState?.checkLibrary(this, keyword);
+          return parseLibraryName(keyword);
         }
       }
     }
@@ -1174,9 +1107,7 @@
       // Recovery: Report an error and insert synthetic `with` clause.
       reportRecoverableError(
           withKeyword, fasta.templateExpectedButGot.withArguments('with'));
-      withKeyword =
-          new SyntheticKeywordToken(Keyword.WITH, withKeyword.charOffset);
-      rewriter.insertToken(token, withKeyword);
+      withKeyword = rewriter.insertSyntheticKeyword(token, Keyword.WITH);
       if (!isValidTypeReference(withKeyword.next)) {
         rewriter.insertSyntheticIdentifier(withKeyword);
       }
@@ -1379,42 +1310,60 @@
     final bool inFunctionType =
         memberKind == MemberKind.GeneralizedFunctionType;
 
+    Token requiredToken;
     Token covariantToken;
     Token varFinalOrConst;
     if (isModifier(next)) {
-      if (optional('covariant', next)) {
-        if (memberKind != MemberKind.StaticMethod &&
-            memberKind != MemberKind.TopLevelMethod) {
-          covariantToken = token = next;
+      if (optional('required', next)) {
+        if (parameterKind == FormalParameterKind.optionalNamed) {
+          requiredToken = token = next;
           next = token.next;
         }
       }
 
       if (isModifier(next)) {
-        if (!inFunctionType) {
-          if (optional('var', next)) {
-            varFinalOrConst = token = next;
-            next = token.next;
-          } else if (optional('final', next)) {
-            varFinalOrConst = token = next;
+        if (optional('covariant', next)) {
+          if (memberKind != MemberKind.StaticMethod &&
+              memberKind != MemberKind.TopLevelMethod) {
+            covariantToken = token = next;
             next = token.next;
           }
         }
 
         if (isModifier(next)) {
-          // Recovery
-          ModifierRecoveryContext context = new ModifierRecoveryContext(this);
-          token = context.parseFormalParameterModifiers(token, memberKind,
-              covariantToken: covariantToken, varFinalOrConst: varFinalOrConst);
-          covariantToken = context.covariantToken;
-          varFinalOrConst = context.varFinalOrConst;
-          context = null;
+          if (!inFunctionType) {
+            if (optional('var', next)) {
+              varFinalOrConst = token = next;
+              next = token.next;
+            } else if (optional('final', next)) {
+              varFinalOrConst = token = next;
+              next = token.next;
+            }
+          }
+
+          if (isModifier(next)) {
+            // Recovery
+            ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+              ..covariantToken = covariantToken
+              ..requiredToken = requiredToken
+              ..varFinalOrConst = varFinalOrConst;
+
+            token = context.parseFormalParameterModifiers(
+                token, parameterKind, memberKind);
+            next = token.next;
+
+            covariantToken = context.covariantToken;
+            requiredToken = context.requiredToken;
+            varFinalOrConst = context.varFinalOrConst;
+
+            context = null;
+          }
         }
       }
     }
 
     listener.beginFormalParameter(
-        start, memberKind, covariantToken, varFinalOrConst);
+        start, memberKind, requiredToken, covariantToken, varFinalOrConst);
 
     // Type is required in a generalized function type, but optional otherwise.
     final Token beforeType = token;
@@ -1496,7 +1445,12 @@
       token = typeInfo.parseType(beforeType, this);
       endInlineFunctionType = parseFormalParametersRequiredOpt(
           endInlineFunctionType, MemberKind.FunctionTypedParameter);
-      listener.endFunctionTypedFormalParameter(beforeInlineFunctionType);
+      Token question;
+      if (optional('?', endInlineFunctionType.next)) {
+        question = endInlineFunctionType = endInlineFunctionType.next;
+      }
+      listener.endFunctionTypedFormalParameter(
+          beforeInlineFunctionType, question);
 
       // Generalized function types don't allow inline function types.
       // The following isn't allowed:
@@ -1705,7 +1659,7 @@
 
   Token skipBlock(Token token) {
     // The scanner ensures that `{` always has a closing `}`.
-    return ensureBlock(token, null).endGroup;
+    return ensureBlock(token, null, null).endGroup;
   }
 
   /// ```
@@ -1764,7 +1718,8 @@
         }
       }
     } else {
-      leftBrace = ensureBlock(token, fasta.templateExpectedEnumBody);
+      // TODO(danrubel): merge this error message with missing class/mixin body
+      leftBrace = ensureBlock(token, fasta.templateExpectedEnumBody, null);
       token = leftBrace.endGroup;
     }
     assert(optional('}', token));
@@ -1778,7 +1733,7 @@
     Token begin = abstractToken ?? classKeyword;
     listener.beginClassOrNamedMixinApplication(begin);
     Token name = ensureIdentifier(
-        classKeyword, IdentifierContext.classOrMixinDeclaration);
+        classKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
     Token token = computeTypeParamOrArg(name, true).parseVariables(name, this);
     if (optional('=', token.next)) {
       listener.beginNamedMixinApplication(begin, abstractToken, name);
@@ -1823,7 +1778,7 @@
     if (!optional('{', token.next)) {
       // Recovery
       token = parseClassHeaderRecovery(start, begin, classKeyword);
-      ensureBlock(token, fasta.templateExpectedClassOrMixinBody);
+      ensureBlock(token, null, 'class declaration');
     }
     token = parseClassOrMixinBody(token);
     listener.endClassDeclaration(begin, token);
@@ -1981,7 +1936,7 @@
     assert(optional('mixin', mixinKeyword));
     listener.beginClassOrNamedMixinApplication(mixinKeyword);
     Token name = ensureIdentifier(
-        mixinKeyword, IdentifierContext.classOrMixinDeclaration);
+        mixinKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
     Token headerStart =
         computeTypeParamOrArg(name, true).parseVariables(name, this);
     listener.beginMixinDeclaration(mixinKeyword, name);
@@ -1989,7 +1944,7 @@
     if (!optional('{', token.next)) {
       // Recovery
       token = parseMixinHeaderRecovery(token, mixinKeyword, headerStart);
-      ensureBlock(token, fasta.templateExpectedClassOrMixinBody);
+      ensureBlock(token, null, 'mixin declaration');
     }
     token = parseClassOrMixinBody(token);
     listener.endMixinDeclaration(mixinKeyword, token);
@@ -2102,6 +2057,64 @@
     return token;
   }
 
+  /// ```
+  /// 'extension' <identifier><typeParameters>? 'on' <type> '?'?
+  //   `{'
+  //     <memberDeclaration>*
+  //   `}'
+  /// ```
+  Token parseExtension(Token extensionKeyword) {
+    assert(optional('extension', extensionKeyword));
+    Token name = ensureIdentifier(
+        extensionKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
+    Token token = computeTypeParamOrArg(name, true).parseVariables(name, this);
+    listener.beginExtensionDeclaration(extensionKeyword, name);
+    Token onKeyword = token.next;
+    if (!optional('on', onKeyword)) {
+      // Recovery
+      if (optional('extends', onKeyword) ||
+          optional('implements', onKeyword) ||
+          optional('with', onKeyword)) {
+        reportRecoverableError(
+            onKeyword, fasta.templateExpectedInstead.withArguments('on'));
+      } else {
+        reportRecoverableError(
+            token, fasta.templateExpectedAfterButGot.withArguments('on'));
+        onKeyword = rewriter.insertSyntheticKeyword(token, Keyword.ON);
+      }
+    }
+    TypeInfo typeInfo = computeType(onKeyword, true);
+    token = typeInfo.ensureTypeNotVoid(onKeyword, this);
+    if (!optional('{', token.next)) {
+      // Recovery
+      Token next = token.next;
+      while (!next.isEof) {
+        if (optional(',', next) ||
+            optional('extends', next) ||
+            optional('implements', next) ||
+            optional('on', next) ||
+            optional('with', next)) {
+          // Report an error and skip `,` or specific keyword
+          // optionally followed by an identifier
+          reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
+          token = next;
+          next = token.next;
+          if (next.isIdentifier) {
+            token = next;
+            next = token.next;
+          }
+        } else {
+          break;
+        }
+      }
+      ensureBlock(token, null, 'extension declaration');
+    }
+    // TODO(danrubel): Do not allow fields or constructors
+    token = parseClassOrMixinBody(token);
+    listener.endExtensionDeclaration(onKeyword, token);
+    return token;
+  }
+
   Token parseStringPart(Token token) {
     Token next = token.next;
     if (next.kind != STRING_TOKEN) {
@@ -2179,6 +2192,7 @@
     listener.beginTopLevelMember(next);
 
     Token externalToken;
+    Token lateToken;
     Token varFinalOrConst;
 
     if (isModifier(next)) {
@@ -2196,6 +2210,13 @@
         } else if (optional('const', next)) {
           varFinalOrConst = token = next;
           next = token.next;
+        } else if (optional('late', next)) {
+          lateToken = token = next;
+          next = token.next;
+          if (isModifier(next) && optional('final', next)) {
+            varFinalOrConst = token = next;
+            next = token.next;
+          }
         }
         if (isModifier(next)) {
           // Recovery
@@ -2206,13 +2227,18 @@
             // If another `var`, `final`, or `const` then fall through
             // to parse that as part of the next top level declaration.
           } else {
-            ModifierRecoveryContext context = new ModifierRecoveryContext(this);
-            token = context.parseTopLevelModifiers(token,
-                externalToken: externalToken, varFinalOrConst: varFinalOrConst);
+            ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+              ..externalToken = externalToken
+              ..lateToken = lateToken
+              ..varFinalOrConst = varFinalOrConst;
+
+            token = context.parseTopLevelModifiers(token);
             next = token.next;
 
             externalToken = context.externalToken;
+            lateToken = context.lateToken;
             varFinalOrConst = context.varFinalOrConst;
+
             context = null;
           }
         }
@@ -2257,13 +2283,8 @@
               token = next;
               next = token.next;
               if (optional('(', next.next)) {
-                rewriter.insertToken(
-                    next,
-                    new SyntheticStringToken(
-                        TokenType.IDENTIFIER,
-                        '#synthetic_identifier_${next.charOffset}',
-                        next.charOffset,
-                        0));
+                rewriter.insertSyntheticIdentifier(
+                    next, '#synthetic_identifier_${next.charOffset}');
               }
             }
           }
@@ -2304,6 +2325,9 @@
           reportRecoverableErrorWithToken(
               varFinalOrConst, fasta.templateExtraneousModifier);
         }
+      } else if (lateToken != null) {
+        reportRecoverableErrorWithToken(
+            lateToken, fasta.templateExtraneousModifier);
       }
       return parseTopLevelMethod(beforeStart, externalToken, beforeType,
           typeInfo, getOrSet, token.next);
@@ -2313,8 +2337,8 @@
       reportRecoverableErrorWithToken(
           getOrSet, fasta.templateExtraneousModifier);
     }
-    return parseFields(beforeStart, externalToken, null, null, varFinalOrConst,
-        beforeType, typeInfo, token.next, true);
+    return parseFields(beforeStart, externalToken, null, null, lateToken,
+        varFinalOrConst, beforeType, typeInfo, token.next, true);
   }
 
   Token parseFields(
@@ -2322,6 +2346,7 @@
       Token externalToken,
       Token staticToken,
       Token covariantToken,
+      Token lateToken,
       Token varFinalOrConst,
       Token beforeType,
       TypeInfo typeInfo,
@@ -2337,7 +2362,7 @@
       }
     }
     if (typeInfo == noType) {
-      if (varFinalOrConst == null) {
+      if (varFinalOrConst == null && lateToken == null) {
         reportRecoverableError(name, fasta.messageMissingConstFinalVarOrType);
       }
     } else {
@@ -2355,19 +2380,41 @@
     name = ensureIdentifier(token, context);
 
     int fieldCount = 1;
-    token = parseFieldInitializerOpt(name, name, varFinalOrConst, isTopLevel);
+    token = parseFieldInitializerOpt(
+        name, name, lateToken, varFinalOrConst, isTopLevel);
     while (optional(',', token.next)) {
       name = ensureIdentifier(token.next, context);
-      token = parseFieldInitializerOpt(name, name, varFinalOrConst, isTopLevel);
+      token = parseFieldInitializerOpt(
+          name, name, lateToken, varFinalOrConst, isTopLevel);
       ++fieldCount;
     }
-    token = ensureSemicolon(token);
-    if (isTopLevel) {
-      listener.endTopLevelFields(staticToken, covariantToken, varFinalOrConst,
-          fieldCount, beforeStart.next, token);
+    Token semicolon = token.next;
+    if (optional(';', semicolon)) {
+      token = semicolon;
     } else {
-      listener.endFields(staticToken, covariantToken, varFinalOrConst,
-          fieldCount, beforeStart.next, token);
+      // Recovery
+      if (isTopLevel &&
+          beforeType.next.isIdentifier &&
+          beforeType.next.lexeme == 'extension') {
+        // Looks like an extension method
+        // TODO(danrubel): Remove when extension methods are enabled by default
+        // because then 'extension' will be interpreted as a built-in
+        // and this code will never be executed
+        reportRecoverableError(
+            beforeType.next,
+            fasta.templateExperimentNotEnabled
+                .withArguments('extension-methods'));
+        token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
+      } else {
+        token = ensureSemicolon(token);
+      }
+    }
+    if (isTopLevel) {
+      listener.endTopLevelFields(staticToken, covariantToken, lateToken,
+          varFinalOrConst, fieldCount, beforeStart.next, token);
+    } else {
+      listener.endFields(staticToken, covariantToken, lateToken,
+          varFinalOrConst, fieldCount, beforeStart.next, token);
     }
     return token;
   }
@@ -2422,8 +2469,8 @@
     return token;
   }
 
-  Token parseFieldInitializerOpt(
-      Token token, Token name, Token varFinalOrConst, bool isTopLevel) {
+  Token parseFieldInitializerOpt(Token token, Token name, Token lateToken,
+      Token varFinalOrConst, bool isTopLevel) {
     Token next = token.next;
     if (optional('=', next)) {
       Token assignment = next;
@@ -2437,7 +2484,9 @@
               name,
               fasta.templateConstFieldWithoutInitializer
                   .withArguments(name.lexeme));
-        } else if (isTopLevel && optional("final", varFinalOrConst)) {
+        } else if (isTopLevel &&
+            optional("final", varFinalOrConst) &&
+            lateToken == null) {
           reportRecoverableError(
               name,
               fasta.templateFinalFieldWithoutInitializer
@@ -2522,8 +2571,7 @@
         // expecting one of `,` or `;` or `{`
         reportRecoverableError(
             token, fasta.templateExpectedAfterButGot.withArguments(','));
-        next = rewriter.insertToken(
-            token, new SyntheticToken(TokenType.COMMA, token.next.charOffset));
+        next = rewriter.insertSyntheticToken(token, TokenType.COMMA);
       }
     }
     mayParseFunctionExpressions = old;
@@ -2585,8 +2633,7 @@
         // `this.<fieldname>=` is expected.
         reportRecoverableError(
             next, fasta.templateExpectedButGot.withArguments('.'));
-        rewriter.insertToken(
-            token, new SyntheticToken(TokenType.PERIOD, next.offset));
+        rewriter.insertSyntheticToken(token, TokenType.PERIOD);
         token = rewriter.insertSyntheticIdentifier(token.next);
         next = token.next;
       }
@@ -2600,8 +2647,7 @@
       // then fall through to insert the LHS and `=` of the assignment,
       // otherwise insert an `=` and synthetic identifier.
       if (!next2.isOperator && !optional('.', next2)) {
-        token = rewriter.insertToken(
-            next, new SyntheticToken(TokenType.EQ, next2.offset));
+        token = rewriter.insertSyntheticToken(next, TokenType.EQ);
         token = insertSyntheticIdentifier(token, IdentifierContext.expression,
             message: fasta.messageMissingAssignmentInInitializer,
             messageOnToken: next);
@@ -2612,8 +2658,7 @@
       token = insertSyntheticIdentifier(
           token, IdentifierContext.fieldInitializer,
           message: fasta.messageExpectedAnInitializer, messageOnToken: token);
-      token = rewriter.insertToken(
-          token, new SyntheticToken(TokenType.EQ, token.offset));
+      token = rewriter.insertSyntheticToken(token, TokenType.EQ);
       token = rewriter.insertSyntheticIdentifier(token);
       return parseInitializerExpressionRest(beforeExpression);
     }
@@ -2626,7 +2671,7 @@
     token = insertSyntheticIdentifier(
         beforeExpression, IdentifierContext.fieldInitializer,
         message: fasta.messageMissingAssignmentInInitializer);
-    rewriter.insertToken(token, new SyntheticToken(TokenType.EQ, token.offset));
+    rewriter.insertSyntheticToken(token, TokenType.EQ);
     return parseInitializerExpressionRest(beforeExpression);
   }
 
@@ -2684,17 +2729,28 @@
   }
 
   /// If the next token is an opening curly brace, return it. Otherwise, use the
-  /// given [template] to report an error, insert an opening and a closing curly
-  /// brace, and return the newly inserted opening curly brace. If the
-  /// [template] is `null`, use a default error message instead.
-  Token ensureBlock(
-      Token token, Template<Message Function(Token token)> template) {
+  /// given [template] or [blockKind] to report an error, insert an opening and
+  /// a closing curly brace, and return the newly inserted opening curly brace.
+  /// If  [template] and [blockKind] are `null`, then use
+  /// a default error message instead.
+  Token ensureBlock(Token token,
+      Template<Message Function(Token token)> template, String blockKind) {
     Token next = token.next;
     if (optional('{', next)) return next;
-    Message message = template == null
-        ? fasta.templateExpectedButGot.withArguments('{')
-        : template.withArguments(next);
-    reportRecoverableError(next, message);
+    if (template == null) {
+      if (blockKind == null) {
+        // TODO(danrubel): rename ExpectedButGot to ExpectedBefore
+        reportRecoverableError(
+            next, fasta.templateExpectedButGot.withArguments('{'));
+      } else {
+        // TODO(danrubel): rename ExpectedClassOrMixinBody
+        //  to ExpectedDeclarationOrClauseBody
+        reportRecoverableError(token,
+            fasta.templateExpectedClassOrMixinBody.withArguments(blockKind));
+      }
+    } else {
+      reportRecoverableError(next, template.withArguments(next));
+    }
     return insertBlock(token);
   }
 
@@ -2771,9 +2827,7 @@
     // for users to understand and fix the error.
     reportRecoverableError(findPreviousNonZeroLengthToken(token),
         fasta.templateExpectedAfterButGot.withArguments(';'));
-
-    return rewriter.insertToken(
-        token, new SyntheticToken(TokenType.SEMICOLON, next.charOffset));
+    return rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
   }
 
   /// Report an error at the token after [token] that has the given [message].
@@ -2827,7 +2881,7 @@
 
   Token skipClassOrMixinBody(Token token) {
     // The scanner ensures that `{` always has a closing `}`.
-    return ensureBlock(token, fasta.templateExpectedClassOrMixinBody);
+    return ensureBlock(token, null, null);
   }
 
   /// ```
@@ -2882,6 +2936,7 @@
 
     Token covariantToken;
     Token externalToken;
+    Token lateToken;
     Token staticToken;
     Token varFinalOrConst;
 
@@ -2909,18 +2964,28 @@
           } else if (optional('const', next) && covariantToken == null) {
             varFinalOrConst = token = next;
             next = token.next;
+          } else if (optional('late', next)) {
+            lateToken = token = next;
+            next = token.next;
+            if (isModifier(next) && optional('final', next)) {
+              varFinalOrConst = token = next;
+              next = token.next;
+            }
           }
           if (isModifier(next)) {
-            ModifierRecoveryContext context = new ModifierRecoveryContext(this);
-            token = context.parseClassMemberModifiers(token,
-                externalToken: externalToken,
-                staticToken: staticToken,
-                covariantToken: covariantToken,
-                varFinalOrConst: varFinalOrConst);
+            ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+              ..covariantToken = covariantToken
+              ..externalToken = externalToken
+              ..lateToken = lateToken
+              ..staticToken = staticToken
+              ..varFinalOrConst = varFinalOrConst;
+
+            token = context.parseClassMemberModifiers(token);
             next = token.next;
 
             covariantToken = context.covariantToken;
             externalToken = context.externalToken;
+            lateToken = context.lateToken;
             staticToken = context.staticToken;
             varFinalOrConst = context.varFinalOrConst;
 
@@ -2969,6 +3034,7 @@
               externalToken,
               staticToken,
               covariantToken,
+              lateToken,
               varFinalOrConst,
               beforeType,
               typeInfo,
@@ -2982,8 +3048,14 @@
                 !optional('=', next2) &&
                 !optional('<', next2))) {
           // Recovery: Invalid operator
-          return parseInvalidOperatorDeclaration(beforeStart, externalToken,
-              staticToken, covariantToken, varFinalOrConst, beforeType);
+          return parseInvalidOperatorDeclaration(
+              beforeStart,
+              externalToken,
+              staticToken,
+              covariantToken,
+              lateToken,
+              varFinalOrConst,
+              beforeType);
         } else if (isUnaryMinus(next2)) {
           // Recovery
           token = parseMethod(
@@ -2991,6 +3063,7 @@
               externalToken,
               staticToken,
               covariantToken,
+              lateToken,
               varFinalOrConst,
               beforeType,
               typeInfo,
@@ -3011,6 +3084,7 @@
             externalToken,
             staticToken,
             covariantToken,
+            lateToken,
             varFinalOrConst,
             beforeType,
             typeInfo,
@@ -3024,8 +3098,14 @@
             identical(value, '{') ||
             identical(value, '=>')) {
           // Recovery: Missing `operator` keyword
-          return parseInvalidOperatorDeclaration(beforeStart, externalToken,
-              staticToken, covariantToken, varFinalOrConst, beforeType);
+          return parseInvalidOperatorDeclaration(
+              beforeStart,
+              externalToken,
+              staticToken,
+              covariantToken,
+              lateToken,
+              varFinalOrConst,
+              beforeType);
         }
       }
     }
@@ -3044,6 +3124,7 @@
           externalToken,
           staticToken,
           covariantToken,
+          lateToken,
           varFinalOrConst,
           beforeType,
           typeInfo,
@@ -3059,6 +3140,7 @@
           externalToken,
           staticToken,
           covariantToken,
+          lateToken,
           varFinalOrConst,
           beforeType,
           typeInfo,
@@ -3074,11 +3156,16 @@
       Token externalToken,
       Token staticToken,
       Token covariantToken,
+      Token lateToken,
       Token varFinalOrConst,
       Token beforeType,
       TypeInfo typeInfo,
       Token getOrSet,
       Token name) {
+    if (lateToken != null) {
+      reportRecoverableErrorWithToken(
+          lateToken, fasta.templateExtraneousModifier);
+    }
     bool isOperator = false;
     if (getOrSet == null && optional('operator', name)) {
       Token operator = name.next;
@@ -3184,15 +3271,18 @@
 
     if (!isValidTypeReference(token.next)) {
       // Recovery
-      ModifierRecoveryContext context = new ModifierRecoveryContext(this);
-      token = context.parseModifiersAfterFactory(token,
-          externalToken: externalToken,
-          staticOrCovariant: staticOrCovariant,
-          varFinalOrConst: varFinalOrConst);
+      ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+        ..externalToken = externalToken
+        ..staticOrCovariant = staticOrCovariant
+        ..varFinalOrConst = varFinalOrConst;
+
+      token = context.parseModifiersAfterFactory(token);
 
       externalToken = context.externalToken;
       staticOrCovariant = context.staticToken ?? context.covariantToken;
       varFinalOrConst = context.varFinalOrConst;
+
+      context = null;
     }
 
     if (staticOrCovariant != null) {
@@ -3505,7 +3595,7 @@
         begin = next = token.next;
         // Fall through to parse the block.
       } else {
-        token = ensureBlock(token, fasta.templateExpectedFunctionBody);
+        token = ensureBlock(token, fasta.templateExpectedFunctionBody, null);
         listener.handleInvalidFunctionBody(token);
         return token.endGroup;
       }
@@ -3622,21 +3712,29 @@
       if (optional(':', token.next.next)) {
         return parseLabeledStatement(token);
       }
-      return parseExpressionStatementOrDeclarationAfterModifiers(token, token);
+      return parseExpressionStatementOrDeclarationAfterModifiers(
+          token, token, null, null, null, false);
     }
     final value = token.next.stringValue;
     if (identical(value, '{')) {
-      return parseBlock(token);
+      // The scanner ensures that `{` always has a closing `}`.
+      return parseBlock(token, null);
     } else if (identical(value, 'return')) {
       return parseReturnStatement(token);
     } else if (identical(value, 'var') || identical(value, 'final')) {
       Token varOrFinal = token.next;
-      if (isModifier(varOrFinal.next)) {
-        return parseExpressionStatementOrDeclaration(token);
-      } else {
+      if (!isModifier(varOrFinal.next)) {
         return parseExpressionStatementOrDeclarationAfterModifiers(
-            varOrFinal, token, varOrFinal);
+            varOrFinal, token, null, varOrFinal, null, false);
       }
+      return parseExpressionStatementOrDeclaration(token);
+    } else if (identical(value, 'late')) {
+      Token lateToken = token.next;
+      if (!isModifier(lateToken.next)) {
+        return parseExpressionStatementOrDeclarationAfterModifiers(
+            lateToken, token, lateToken, null, null, false);
+      }
+      return parseExpressionStatementOrDeclaration(token);
     } else if (identical(value, 'if')) {
       return parseIfStatement(token);
     } else if (identical(value, 'await') && optional('for', token.next.next)) {
@@ -3869,7 +3967,7 @@
     }
     Token next = token.next;
     TokenType type = next.type;
-    int tokenLevel = _computePrecedence(type);
+    int tokenLevel = _computePrecedence(next);
     for (int level = tokenLevel; level >= precedence; --level) {
       int lastBinaryExpressionLevel = -1;
       while (identical(tokenLevel, level)) {
@@ -3918,10 +4016,14 @@
             rewriter.replaceTokenFollowing(token, replacement);
             replacement.endToken = replacement.next;
             token = parseArgumentOrIndexStar(token, noTypeParamOrArg);
+          } else if (identical(type, TokenType.BANG)) {
+            listener.handleNonNullAssertExpression(token.next);
+            token = next;
           } else {
             // Recovery
             reportRecoverableErrorWithToken(
                 token.next, fasta.templateUnexpectedToken);
+            token = next;
           }
         } else if (identical(type, TokenType.IS)) {
           token = parseIsOperatorRest(token);
@@ -3950,20 +4052,23 @@
         }
         next = token.next;
         type = next.type;
-        tokenLevel = _computePrecedence(type);
+        tokenLevel = _computePrecedence(next);
       }
     }
     return token;
   }
 
-  int _computePrecedence(TokenType type) {
+  int _computePrecedence(Token token) {
+    TokenType type = token.type;
     if (identical(type, TokenType.BANG)) {
       // The '!' has prefix precedence but here it's being used as a
       // postfix operator to assert the expression has a non-null value.
+      if (identical(token.next.type, TokenType.PERIOD)) {
+        return SELECTOR_PRECEDENCE;
+      }
       return POSTFIX_PRECEDENCE;
-    } else {
-      return type.precedence;
     }
+    return type.precedence;
   }
 
   Token parseCascadeExpression(Token token) {
@@ -4506,7 +4611,6 @@
     token = typeParamOrArg.parseArguments(start, this);
     if (optional('{', next)) {
       if (typeParamOrArg.typeArgumentCount > 2) {
-        // TODO(danrubel): remove code in listeners which report this error
         listener.handleRecoverableError(
             fasta.messageSetOrMapLiteralTooManyTypeArguments,
             start.next,
@@ -4518,8 +4622,7 @@
       // TODO(danrubel): Improve this error message.
       reportRecoverableError(
           next, fasta.templateExpectedButGot.withArguments('['));
-      rewriter.insertToken(
-          token, new SyntheticToken(TokenType.INDEX, next.charOffset));
+      rewriter.insertSyntheticToken(token, TokenType.INDEX);
     }
     return parseLiteralListSuffix(token, constKeyword);
   }
@@ -5052,7 +5155,7 @@
         }
       }
       return parseExpressionStatementOrDeclarationAfterModifiers(
-          constToken, start, constToken, typeInfo);
+          constToken, start, null, constToken, typeInfo, false);
     }
     return parseExpressionStatementOrDeclaration(start);
   }
@@ -5078,50 +5181,71 @@
       next = token.next;
     }
 
+    Token lateToken;
     Token varFinalOrConst;
+
     if (isModifier(next)) {
-      if (optional('var', next)) {
+      if (optional('var', next) ||
+          optional('final', next) ||
+          optional('const', next)) {
         varFinalOrConst = token = token.next;
         next = token.next;
-      } else if (optional('final', next) || optional('const', next)) {
-        varFinalOrConst = token = token.next;
+      } else if (optional('late', next)) {
+        lateToken = token = next;
         next = token.next;
+        if (isModifier(next) && optional('final', next)) {
+          varFinalOrConst = token = next;
+          next = token.next;
+        }
       }
 
       if (isModifier(next)) {
         // Recovery
-        ModifierRecoveryContext modifierContext =
-            new ModifierRecoveryContext(this);
-        token = modifierContext.parseVariableDeclarationModifiers(token,
-            varFinalOrConst: varFinalOrConst);
+        ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+          ..lateToken = lateToken
+          ..varFinalOrConst = varFinalOrConst;
+
+        token = context.parseVariableDeclarationModifiers(token);
         next = token.next;
 
-        varFinalOrConst = modifierContext.varFinalOrConst;
-        modifierContext = null;
+        lateToken = context.lateToken;
+        varFinalOrConst = context.varFinalOrConst;
+
+        context = null;
       }
     }
 
-    return parseExpressionStatementOrDeclarationAfterModifiers(
-        token, start, varFinalOrConst, null, onlyParseVariableDeclarationStart);
+    return parseExpressionStatementOrDeclarationAfterModifiers(token, start,
+        lateToken, varFinalOrConst, null, onlyParseVariableDeclarationStart);
   }
 
   /// See [parseExpressionStatementOrDeclaration]
   Token parseExpressionStatementOrDeclarationAfterModifiers(
-      final Token beforeType, final Token start,
-      [Token varFinalOrConst = null,
+      final Token beforeType,
+      final Token start,
+      final Token lateToken,
+      Token varFinalOrConst,
       TypeInfo typeInfo,
-      bool onlyParseVariableDeclarationStart = false]) {
+      bool onlyParseVariableDeclarationStart) {
     typeInfo ??= computeType(beforeType, false);
 
     Token token = typeInfo.skipType(beforeType);
     Token next = token.next;
 
-    if (!onlyParseVariableDeclarationStart) {
+    if (onlyParseVariableDeclarationStart) {
+      if (lateToken != null) {
+        reportRecoverableErrorWithToken(
+            lateToken, fasta.templateExtraneousModifier);
+      }
+    } else {
       if (looksLikeLocalFunction(next)) {
         // Parse a local function declaration.
         if (varFinalOrConst != null) {
           reportRecoverableErrorWithToken(
               varFinalOrConst, fasta.templateExtraneousModifier);
+        } else if (lateToken != null) {
+          reportRecoverableErrorWithToken(
+              lateToken, fasta.templateExtraneousModifier);
         }
         if (!optional('@', start.next)) {
           listener.beginMetadataStar(start.next);
@@ -5210,7 +5334,7 @@
       // identifier, then allow ensureIdentifier to report an error
       // and don't report errors here.
       if (varFinalOrConst == null) {
-        if (typeInfo == noType) {
+        if (typeInfo == noType && lateToken == null) {
           reportRecoverableError(next, fasta.messageMissingConstFinalVarOrType);
         }
       } else if (optional('var', varFinalOrConst)) {
@@ -5226,7 +5350,7 @@
     }
     token = typeInfo.parseType(beforeType, this);
     next = token.next;
-    listener.beginVariablesDeclaration(next, varFinalOrConst);
+    listener.beginVariablesDeclaration(next, lateToken, varFinalOrConst);
     if (!onlyParseVariableDeclarationStart) {
       token = parseVariablesDeclarationRest(token, true);
     }
@@ -5326,34 +5450,27 @@
       // Recovery
       reportRecoverableError(
           leftParenthesis, fasta.templateExpectedButGot.withArguments('('));
-      int offset = leftParenthesis.offset;
 
-      BeginToken openParen = forToken
-          .setNext(new SyntheticBeginToken(TokenType.OPEN_PAREN, offset));
+      BeginToken openParen = rewriter.insertToken(
+          forToken,
+          new SyntheticBeginToken(
+              TokenType.OPEN_PAREN, leftParenthesis.offset));
 
-      Token loopPart;
+      Token token;
       if (awaitToken != null) {
-        loopPart = openParen.setNext(
-            new SyntheticStringToken(TokenType.IDENTIFIER, '', offset));
-        loopPart =
-            loopPart.setNext(new SyntheticKeywordToken(Keyword.IN, offset));
-        loopPart = loopPart.setNext(
-            new SyntheticStringToken(TokenType.IDENTIFIER, '', offset));
+        token = rewriter.insertSyntheticIdentifier(openParen);
+        token = rewriter.insertSyntheticKeyword(token, Keyword.IN);
+        token = rewriter.insertSyntheticIdentifier(token);
       } else {
-        loopPart =
-            openParen.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
-        loopPart =
-            loopPart.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
+        token = rewriter.insertSyntheticToken(openParen, TokenType.SEMICOLON);
+        token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
       }
 
-      Token closeParen =
-          loopPart.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
-      openParen.endGroup = closeParen;
-      Token identifier = closeParen
-          .setNext(new SyntheticStringToken(TokenType.IDENTIFIER, '', offset));
-      Token semicolon =
-          identifier.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
-      semicolon.setNext(leftParenthesis);
+      openParen.endGroup = token = rewriter.insertToken(token,
+          new SyntheticToken(TokenType.CLOSE_PAREN, leftParenthesis.offset));
+
+      token = rewriter.insertSyntheticIdentifier(token);
+      rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
 
       leftParenthesis = openParen;
     }
@@ -5362,7 +5479,7 @@
     // parses the metadata, modifiers, and type of a local variable
     // declaration if it exists. This enables capturing [beforeIdentifier]
     // for later error reporting.
-    return parseExpressionStatementOrDeclaration(forToken.next, true);
+    return parseExpressionStatementOrDeclaration(leftParenthesis, true);
   }
 
   /// Parse the remainder of the local variable declaration
@@ -5548,8 +5665,7 @@
     if (!optional('while', whileToken)) {
       reportRecoverableError(
           whileToken, fasta.templateExpectedButGot.withArguments('while'));
-      whileToken = rewriter.insertToken(token,
-          new SyntheticKeywordToken(Keyword.WHILE, whileToken.charOffset));
+      whileToken = rewriter.insertSyntheticKeyword(token, Keyword.WHILE);
     }
     token = ensureParenthesizedCondition(whileToken);
     token = ensureSemicolon(token);
@@ -5562,8 +5678,8 @@
   ///   '{' statement* '}'
   /// ;
   /// ```
-  Token parseBlock(Token token) {
-    Token begin = token = ensureBlock(token, null);
+  Token parseBlock(Token token, String blockKind) {
+    Token begin = token = ensureBlock(token, null, blockKind);
     listener.beginBlock(begin);
     int statementCount = 0;
     Token startToken = token.next;
@@ -5592,7 +5708,8 @@
     // because an error has already been reported by the caller.
     Listener originalListener = listener;
     listener = new ForwardingListener(listener)..forwardErrors = false;
-    token = parseBlock(token);
+    // The scanner ensures that `{` always has a closing `}`.
+    token = parseBlock(token, null);
     listener = originalListener;
     listener.handleInvalidTopLevelBlock(begin);
     return token;
@@ -5707,7 +5824,7 @@
     Token tryKeyword = token.next;
     assert(optional('try', tryKeyword));
     listener.beginTryStatement(tryKeyword);
-    Token lastConsumed = parseBlock(tryKeyword);
+    Token lastConsumed = parseBlock(tryKeyword, 'try statement');
     token = lastConsumed.next;
     int catchCount = 0;
 
@@ -5775,8 +5892,8 @@
               rewriter.moveSynthetic(exceptionName, openParens.endGroup);
               comma = null;
             } else {
-              comma = rewriter.insertToken(exceptionName,
-                  new SyntheticToken(TokenType.COMMA, comma.charOffset));
+              comma =
+                  rewriter.insertSyntheticToken(exceptionName, TokenType.COMMA);
             }
           }
           if (comma != null) {
@@ -5802,7 +5919,7 @@
         token = lastConsumed.next;
       }
       listener.endCatchClause(token);
-      lastConsumed = parseBlock(lastConsumed);
+      lastConsumed = parseBlock(lastConsumed, 'catch clause');
       token = lastConsumed.next;
       ++catchCount;
       listener.handleCatchBlock(onKeyword, catchKeyword, comma);
@@ -5812,7 +5929,7 @@
     Token finallyKeyword = null;
     if (optional('finally', token)) {
       finallyKeyword = token;
-      lastConsumed = parseBlock(token);
+      lastConsumed = parseBlock(token, 'finally clause');
       token = lastConsumed.next;
       listener.handleFinallyBlock(finallyKeyword);
     } else {
@@ -5850,7 +5967,7 @@
   /// ;
   /// ```
   Token parseSwitchBlock(Token token) {
-    Token beginSwitch = token = ensureBlock(token, null);
+    Token beginSwitch = token = ensureBlock(token, null, 'switch statement');
     listener.beginSwitchBlock(beginSwitch);
     int caseCount = 0;
     Token defaultKeyword = null;
@@ -6118,6 +6235,7 @@
       Token externalToken,
       Token staticToken,
       Token covariantToken,
+      Token lateToken,
       Token varFinalOrConst,
       Token beforeType) {
     TypeInfo typeInfo = computeType(beforeType, true, true);
@@ -6129,8 +6247,7 @@
       next = next.next;
     } else {
       reportRecoverableError(next, fasta.messageMissingOperatorKeyword);
-      rewriter.insertToken(
-          beforeName, new SyntheticToken(Keyword.OPERATOR, next.offset));
+      rewriter.insertSyntheticKeyword(beforeName, Keyword.OPERATOR);
     }
 
     assert((next.isOperator && next.endGroup == null) ||
@@ -6142,6 +6259,7 @@
         externalToken,
         staticToken,
         covariantToken,
+        lateToken,
         varFinalOrConst,
         beforeType,
         typeInfo,
@@ -6160,6 +6278,7 @@
       Token externalToken,
       Token staticToken,
       Token covariantToken,
+      Token lateToken,
       Token varFinalOrConst,
       Token beforeType,
       TypeInfo typeInfo,
@@ -6175,7 +6294,7 @@
       return reportAndSkipTypedefInClass(next);
     } else if (next.isOperator && next.endGroup == null) {
       return parseInvalidOperatorDeclaration(beforeStart, externalToken,
-          staticToken, covariantToken, varFinalOrConst, beforeType);
+          staticToken, covariantToken, lateToken, varFinalOrConst, beforeType);
     }
 
     if (getOrSet != null ||
@@ -6187,6 +6306,7 @@
           externalToken,
           staticToken,
           covariantToken,
+          lateToken,
           varFinalOrConst,
           beforeType,
           typeInfo,
@@ -6206,6 +6326,7 @@
           externalToken,
           staticToken,
           covariantToken,
+          lateToken,
           varFinalOrConst,
           beforeType,
           typeInfo,
@@ -6222,9 +6343,7 @@
   Token recoverFromStackOverflow(Token token) {
     Token next = token.next;
     reportRecoverableError(next, fasta.messageStackOverflow);
-
-    next = new SyntheticToken(TokenType.SEMICOLON, token.offset);
-    rewriter.insertToken(token, next);
+    next = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
     listener.handleEmptyStatement(next);
 
     while (notEofOrValue('}', next)) {
@@ -6260,6 +6379,21 @@
     listener.handleErrorToken(token);
   }
 
+  Token reportAllErrorTokens(Token token) {
+    while (token is ErrorToken) {
+      reportErrorToken(token);
+      token = token.next;
+    }
+    return token;
+  }
+
+  Token skipErrorTokens(Token token) {
+    while (token is ErrorToken) {
+      token = token.next;
+    }
+    return token;
+  }
+
   Token parseInvalidTopLevelDeclaration(Token token) {
     Token next = token.next;
     reportRecoverableErrorWithToken(
diff --git a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
index 9a8b367..29ab789 100644
--- a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
+++ b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
@@ -7,8 +7,10 @@
 import '../../scanner/token.dart'
     show
         BeginToken,
+        Keyword,
         SimpleToken,
         SyntheticBeginToken,
+        SyntheticKeywordToken,
         SyntheticStringToken,
         SyntheticToken,
         Token,
@@ -17,7 +19,7 @@
 /// Provides the capability of inserting tokens into a token stream. This
 /// implementation does this by rewriting the previous token to point to the
 /// inserted token.
-class TokenStreamRewriter {
+class TokenStreamRewriter with _TokenStreamMixin {
   // TODO(brianwilkerson):
   //
   // When we get to the point of removing `token.previous`, the plan is to
@@ -59,14 +61,6 @@
     return leftParen;
   }
 
-  /// Insert a synthetic identifier after [token] and return the new identifier.
-  Token insertSyntheticIdentifier(Token token) {
-    return insertToken(
-        token,
-        new SyntheticStringToken(
-            TokenType.IDENTIFIER, '', token.next.charOffset, 0));
-  }
-
   /// Insert [newToken] after [token] and return [newToken].
   Token insertToken(Token token, Token newToken) {
     newToken.setNext(token.next);
@@ -141,7 +135,9 @@
 /// Provides the capability of adding tokens that lead into a token stream
 /// without modifying the original token stream and not setting the any token's
 /// `previous` field.
-class TokenStreamGhostWriter implements TokenStreamRewriter {
+class TokenStreamGhostWriter
+    with _TokenStreamMixin
+    implements TokenStreamRewriter {
   @override
   Token insertParens(Token token, bool includeIdentifier) {
     Token next = token.next;
@@ -161,14 +157,6 @@
     return leftParen;
   }
 
-  /// Insert a synthetic identifier after [token] and return the new identifier.
-  Token insertSyntheticIdentifier(Token token) {
-    return insertToken(
-        token,
-        new SyntheticStringToken(
-            TokenType.IDENTIFIER, '', token.next.charOffset, 0));
-  }
-
   @override
   Token insertToken(Token token, Token newToken) {
     newToken.next = token.next;
@@ -204,3 +192,28 @@
     return current;
   }
 }
+
+mixin _TokenStreamMixin {
+  /// Insert a synthetic identifier after [token] and return the new identifier.
+  Token insertSyntheticIdentifier(Token token, [String value]) {
+    return insertToken(
+        token,
+        new SyntheticStringToken(
+            TokenType.IDENTIFIER, value ?? '', token.next.charOffset, 0));
+  }
+
+  /// Insert a new synthetic [keyword] after [token] and return the new token.
+  Token insertSyntheticKeyword(Token token, Keyword keyword) => insertToken(
+      token, new SyntheticKeywordToken(keyword, token.next.charOffset));
+
+  /// Insert a new simple synthetic token of [newTokenType] after [token]
+  /// and return the new token.
+  Token insertSyntheticToken(Token token, TokenType newTokenType) {
+    assert(newTokenType is! Keyword, 'use insertSyntheticKeyword instead');
+    return insertToken(
+        token, new SyntheticToken(newTokenType, token.next.charOffset));
+  }
+
+  /// Insert [newToken] after [token] and return [newToken].
+  Token insertToken(Token token, Token newToken);
+}
diff --git a/pkg/front_end/lib/src/fasta/scanner.dart b/pkg/front_end/lib/src/fasta/scanner.dart
index 8f8e495..b80f201 100644
--- a/pkg/front_end/lib/src/fasta/scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner.dart
@@ -8,14 +8,21 @@
 
 import '../scanner/token.dart' show Token;
 
+import 'scanner/abstract_scanner.dart'
+    show LanguageVersionChanged, ScannerConfiguration;
+
 import 'scanner/string_scanner.dart' show StringScanner;
 
 import 'scanner/utf8_bytes_scanner.dart' show Utf8BytesScanner;
 
-import 'scanner/recover.dart' show defaultRecoveryStrategy;
+import 'scanner/recover.dart' show scannerRecovery;
+
+export 'scanner/abstract_scanner.dart'
+    show LanguageVersionChanged, ScannerConfiguration;
 
 export 'scanner/token.dart'
     show
+        LanguageVersionToken,
         StringToken,
         isBinaryOperator,
         isMinusOperator,
@@ -26,6 +33,8 @@
 export 'scanner/error_token.dart'
     show ErrorToken, buildUnexpectedCharacterToken;
 
+export 'scanner/token.dart' show LanguageVersionToken;
+
 export 'scanner/token_constants.dart' show EOF_TOKEN;
 
 export 'scanner/utf8_bytes_scanner.dart' show Utf8BytesScanner;
@@ -44,6 +53,9 @@
 
   List<int> get lineStarts;
 
+  /// Configure which tokens are produced.
+  set configuration(ScannerConfiguration config);
+
   Token tokenize();
 }
 
@@ -56,42 +68,39 @@
 }
 
 /// Scan/tokenize the given UTF8 [bytes].
-/// If [recover] is null, then the [defaultRecoveryStrategy] is used.
 ScannerResult scan(List<int> bytes,
-    {bool includeComments: false, Recover recover}) {
+    {ScannerConfiguration configuration,
+    bool includeComments: false,
+    LanguageVersionChanged languageVersionChanged}) {
   if (bytes.last != 0) {
     throw new ArgumentError("[bytes]: the last byte must be null.");
   }
-  Scanner scanner =
-      new Utf8BytesScanner(bytes, includeComments: includeComments);
-  return _tokenizeAndRecover(scanner, recover, bytes: bytes);
+  Scanner scanner = new Utf8BytesScanner(bytes,
+      configuration: configuration,
+      includeComments: includeComments,
+      languageVersionChanged: languageVersionChanged);
+  return _tokenizeAndRecover(scanner, bytes: bytes);
 }
 
 /// Scan/tokenize the given [source].
-/// If [recover] is null, then the [defaultRecoveryStrategy] is used.
 ScannerResult scanString(String source,
-    {bool enableGtGtGt: false,
-    bool enableGtGtGtEq: false,
+    {ScannerConfiguration configuration,
     bool includeComments: false,
-    bool scanLazyAssignmentOperators: false,
-    Recover recover}) {
-  // TODO(brianwilkerson): Remove the parameter `enableGtGtGt` after the feature
-  // has been anabled by default.
+    LanguageVersionChanged languageVersionChanged}) {
   assert(source != null, 'source must not be null');
-  StringScanner scanner =
-      new StringScanner(source, includeComments: includeComments);
-  scanner.enableGtGtGt = enableGtGtGt;
-  scanner.enableGtGtGtEq = enableGtGtGtEq;
-  return _tokenizeAndRecover(scanner, recover, source: source);
+  StringScanner scanner = new StringScanner(source,
+      configuration: configuration,
+      includeComments: includeComments,
+      languageVersionChanged: languageVersionChanged);
+  return _tokenizeAndRecover(scanner, source: source);
 }
 
-ScannerResult _tokenizeAndRecover(Scanner scanner, Recover recover,
+ScannerResult _tokenizeAndRecover(Scanner scanner,
     {List<int> bytes, String source}) {
   Token tokens = scanner.tokenize();
   if (scanner.hasErrors) {
     if (bytes == null) bytes = utf8.encode(source);
-    recover ??= defaultRecoveryStrategy;
-    tokens = recover(bytes, tokens, scanner.lineStarts);
+    tokens = scannerRecovery(bytes, tokens, scanner.lineStarts);
   }
   return new ScannerResult(tokens, scanner.lineStarts, scanner.hasErrors);
 }
diff --git a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
index ddbf88a..e59d613 100644
--- a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
@@ -26,12 +26,15 @@
 
 import 'keyword_state.dart' show KeywordState;
 
-import 'token.dart' show CommentToken, DartDocToken;
+import 'token.dart' show CommentToken, DartDocToken, LanguageVersionToken;
 
 import 'token_constants.dart';
 
 import 'characters.dart';
 
+typedef void LanguageVersionChanged(
+    Scanner scanner, LanguageVersionToken languageVersion);
+
 abstract class AbstractScanner implements Scanner {
   /**
    * A flag indicating whether character sequences `&&=` and `||=`
@@ -43,15 +46,22 @@
 
   final bool includeComments;
 
+  /// Called when the scanner detects a language version comment
+  /// so that the listener can update the scanner configuration
+  /// based upon the specified language version.
+  final LanguageVersionChanged languageVersionChanged;
+
+  /// Experimental flag for enabling scanning of the `extension` token.
+  bool _enableExtensionMethods = false;
+
+  /// Experimental flag for enabling scanning of NNBD tokens
+  /// such as 'required' and 'late'.
+  bool _enableNonNullable = false;
+
   /// Experimental flag for enabling scanning of `>>>`.
   /// See https://github.com/dart-lang/language/issues/61
   /// and https://github.com/dart-lang/language/issues/60
-  bool enableGtGtGt = false;
-
-  /// Experimental flag for enabling scanning of `>>>=`.
-  /// See https://github.com/dart-lang/language/issues/61
-  /// and https://github.com/dart-lang/language/issues/60
-  bool enableGtGtGtEq = false;
+  bool _enableTripleShift = false;
 
   /**
    * The string offset for the next token that will be created.
@@ -90,9 +100,21 @@
 
   final List<int> lineStarts;
 
-  AbstractScanner(this.includeComments, {int numberOfBytesHint})
+  AbstractScanner(ScannerConfiguration config, this.includeComments,
+      this.languageVersionChanged,
+      {int numberOfBytesHint})
       : lineStarts = new LineStarts(numberOfBytesHint) {
     this.tail = this.tokens;
+    this.configuration = config;
+  }
+
+  @override
+  set configuration(ScannerConfiguration config) {
+    if (config != null) {
+      _enableExtensionMethods = config.enableExtensionMethods;
+      _enableNonNullable = config.enableNonNullable;
+      _enableTripleShift = config.enableTripleShift;
+    }
   }
 
   /**
@@ -249,6 +271,13 @@
   DartDocToken createDartDocToken(TokenType type, int start, bool asciiOnly,
       [int extraOffset = 0]);
 
+  /**
+   * Returns a new language version token from the scan offset [start]
+   * to the current [scanOffset] similar to createCommentToken.
+   */
+  LanguageVersionToken createLanguageVersionToken(
+      int start, int major, int minor);
+
   /** Documentation in subclass [ArrayBasedScanner]. */
   void discardOpenLt();
 
@@ -261,6 +290,21 @@
   Token tokenize() {
     while (!atEndOfFile()) {
       int next = advance();
+
+      // Scan the header looking for a language version
+      if (!identical(next, $EOF)) {
+        Token oldTail = tail;
+        next = bigHeaderSwitch(next);
+        if (!identical(next, $EOF) && tail.kind == SCRIPT_TOKEN) {
+          oldTail = tail;
+          next = bigHeaderSwitch(next);
+        }
+        while (!identical(next, $EOF) && tail == oldTail) {
+          next = bigHeaderSwitch(next);
+        }
+        next = next;
+      }
+
       while (!identical(next, $EOF)) {
         next = bigSwitch(next);
       }
@@ -277,6 +321,17 @@
     return firstToken();
   }
 
+  int bigHeaderSwitch(int next) {
+    if (!identical(next, $SLASH)) {
+      return bigSwitch(next);
+    }
+    beginToken();
+    if (!identical($SLASH, peek())) {
+      return tokenizeSlashOrComment(next);
+    }
+    return tokenizeLanguageVersionOrSingleLineComment(next);
+  }
+
   int bigSwitch(int next) {
     beginToken();
     if (identical(next, $SPACE) ||
@@ -657,9 +712,9 @@
       if (identical($EQ, next)) {
         appendPrecedenceToken(TokenType.GT_GT_EQ);
         return advance();
-      } else if (enableGtGtGt && identical($GT, next)) {
+      } else if (_enableTripleShift && identical($GT, next)) {
         next = advance();
-        if (enableGtGtGtEq && identical($EQ, next)) {
+        if (_enableTripleShift && identical($EQ, next)) {
           appendPrecedenceToken(TokenType.GT_GT_GT_EQ);
           return advance();
         }
@@ -835,11 +890,111 @@
     }
   }
 
-  int tokenizeSingleLineComment(int next, int start) {
-    bool asciiOnly = true;
-    bool dartdoc = identical($SLASH, peek());
-    while (true) {
+  int tokenizeLanguageVersionOrSingleLineComment(int next) {
+    int start = scanOffset;
+    next = advance();
+
+    // Dart doc
+    if (identical($SLASH, peek())) {
+      return tokenizeSingleLineComment(next, start);
+    }
+
+    // "@dart"
+    next = advance();
+    while (identical($SPACE, next)) {
       next = advance();
+    }
+    if (!identical($AT, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+    if (!identical($d, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+    if (!identical($a, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+    if (!identical($r, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+    if (!identical($t, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+
+    // "="
+    while (identical($SPACE, next)) {
+      next = advance();
+    }
+    if (!identical($EQ, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+
+    // major
+    while (identical($SPACE, next)) {
+      next = advance();
+    }
+    int major = 0;
+    int majorStart = scanOffset;
+    while (isDigit(next)) {
+      major = major * 10 + next - $0;
+      next = advance();
+    }
+    if (scanOffset == majorStart) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+
+    // minor
+    if (!identical($PERIOD, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+    int minor = 0;
+    int minorStart = scanOffset;
+    while (isDigit(next)) {
+      minor = minor * 10 + next - $0;
+      next = advance();
+    }
+    if (scanOffset == minorStart) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+
+    // trailing spaces
+    while (identical($SPACE, next)) {
+      next = advance();
+    }
+    if (next != $LF && next != $CR && next != $EOF) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+
+    var languageVersion = createLanguageVersionToken(start, major, minor);
+    if (languageVersionChanged != null) {
+      // TODO(danrubel): make this required and remove the languageVersion field
+      languageVersionChanged(this, languageVersion);
+    } else {
+      // TODO(danrubel): remove this hack and require listener to update
+      // the scanner's configuration.
+      configuration = ScannerConfiguration.classic;
+    }
+    if (includeComments) {
+      _appendToCommentStream(languageVersion);
+    }
+    return next;
+  }
+
+  int tokenizeSingleLineComment(int next, int start) {
+    bool dartdoc = identical($SLASH, peek());
+    next = advance();
+    return tokenizeSingleLineCommentRest(next, start, dartdoc);
+  }
+
+  int tokenizeSingleLineCommentRest(int next, int start, bool dartdoc) {
+    bool asciiOnly = true;
+    while (true) {
       if (next > 127) asciiOnly = false;
       if (identical($LF, next) ||
           identical($CR, next) ||
@@ -852,6 +1007,7 @@
         }
         return next;
       }
+      next = advance();
     }
   }
 
@@ -983,6 +1139,13 @@
     if (state == null || state.keyword == null) {
       return tokenizeIdentifier(next, start, allowDollar);
     }
+    if (!_enableExtensionMethods && state.keyword == Keyword.EXTENSION) {
+      return tokenizeIdentifier(next, start, allowDollar);
+    }
+    if (!_enableNonNullable &&
+        (state.keyword == Keyword.LATE || state.keyword == Keyword.REQUIRED)) {
+      return tokenizeIdentifier(next, start, allowDollar);
+    }
     if (($A <= next && next <= $Z) ||
         ($0 <= next && next <= $9) ||
         identical(next, $_) ||
@@ -1370,3 +1533,30 @@
     array = newArray;
   }
 }
+
+/// [ScannerConfiguration] contains information for configuring which tokens
+/// the scanner produces based upon the Dart language level.
+class ScannerConfiguration {
+  static const classic = ScannerConfiguration();
+  static const nonNullable = ScannerConfiguration(enableNonNullable: true);
+
+  /// Experimental flag for enabling scanning of the `extension` keyword.
+  final bool enableExtensionMethods;
+
+  /// Experimental flag for enabling scanning of NNBD tokens
+  /// such as 'required' and 'late'
+  final bool enableNonNullable;
+
+  /// Experimental flag for enabling scanning of `>>>`.
+  /// See https://github.com/dart-lang/language/issues/61
+  /// and https://github.com/dart-lang/language/issues/60
+  final bool enableTripleShift;
+
+  const ScannerConfiguration({
+    bool enableExtensionMethods,
+    bool enableNonNullable,
+    bool enableTripleShift,
+  })  : this.enableExtensionMethods = enableExtensionMethods ?? false,
+        this.enableNonNullable = enableNonNullable ?? false,
+        this.enableTripleShift = enableTripleShift ?? false;
+}
diff --git a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
index b6e0f09..22df483 100644
--- a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
@@ -20,15 +20,22 @@
 
 import 'characters.dart' show $LF, $STX;
 
-import 'abstract_scanner.dart' show AbstractScanner, closeBraceInfoFor;
+import 'abstract_scanner.dart'
+    show
+        AbstractScanner,
+        LanguageVersionChanged,
+        ScannerConfiguration,
+        closeBraceInfoFor;
 
 import '../util/link.dart' show Link;
 
 abstract class ArrayBasedScanner extends AbstractScanner {
   bool hasErrors = false;
 
-  ArrayBasedScanner(bool includeComments, {int numberOfBytesHint})
-      : super(includeComments, numberOfBytesHint: numberOfBytesHint);
+  ArrayBasedScanner(ScannerConfiguration config, bool includeComments,
+      LanguageVersionChanged languageVersionChanged, {int numberOfBytesHint})
+      : super(config, includeComments, languageVersionChanged,
+            numberOfBytesHint: numberOfBytesHint);
 
   /**
    * The stack of open groups, e.g [: { ... ( .. :]
diff --git a/pkg/front_end/lib/src/fasta/scanner/characters.dart b/pkg/front_end/lib/src/fasta/scanner/characters.dart
index e9f1e6f..21edbe74 100644
--- a/pkg/front_end/lib/src/fasta/scanner/characters.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/characters.dart
@@ -116,6 +116,10 @@
 const int $LAST_SURROGATE = 0xdfff;
 const int $LAST_CODE_POINT = 0x10ffff;
 
+bool isDigit(int characterCode) {
+  return $0 <= characterCode && characterCode <= $9;
+}
+
 bool isHexDigit(int characterCode) {
   if (characterCode <= $9) return $0 <= characterCode;
   characterCode |= $a ^ $A;
diff --git a/pkg/front_end/lib/src/fasta/scanner/recover.dart b/pkg/front_end/lib/src/fasta/scanner/recover.dart
index 588e658..51b59d6 100644
--- a/pkg/front_end/lib/src/fasta/scanner/recover.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/recover.dart
@@ -30,8 +30,7 @@
 /// [bytes]. [lineStarts] are the beginning character offsets of lines, and
 /// must be updated if recovery is performed rewriting the original source
 /// code.
-Token defaultRecoveryStrategy(
-    List<int> bytes, Token tokens, List<int> lineStarts) {
+Token scannerRecovery(List<int> bytes, Token tokens, List<int> lineStarts) {
   // See [Parser.reportErrorToken](../parser/src/parser.dart) for how
   // it currently handles lexical errors. In addition, notice how the parser
   // calls [handleInvalidExpression], [handleInvalidFunctionBody], and
diff --git a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
index 952099d..7fa5203 100644
--- a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
@@ -8,9 +8,13 @@
 
 import '../../scanner/token.dart' as analyzer show StringToken;
 
+import 'abstract_scanner.dart'
+    show LanguageVersionChanged, ScannerConfiguration;
+
 import 'array_based_scanner.dart' show ArrayBasedScanner;
 
-import 'token.dart' show CommentToken, DartDocToken, StringToken;
+import 'token.dart'
+    show CommentToken, DartDocToken, LanguageVersionToken, StringToken;
 
 import 'error_token.dart' show ErrorToken;
 
@@ -25,9 +29,12 @@
   /** The current offset in [string]. */
   int scanOffset = -1;
 
-  StringScanner(String string, {bool includeComments: false})
+  StringScanner(String string,
+      {ScannerConfiguration configuration,
+      bool includeComments: false,
+      LanguageVersionChanged languageVersionChanged})
       : string = ensureZeroTermination(string),
-        super(includeComments);
+        super(configuration, includeComments, languageVersionChanged);
 
   static String ensureZeroTermination(String string) {
     return (string.isEmpty || string.codeUnitAt(string.length - 1) != 0)
@@ -84,5 +91,13 @@
         canonicalize: true);
   }
 
+  @override
+  LanguageVersionToken createLanguageVersionToken(
+      int start, int major, int minor) {
+    return new LanguageVersionToken.fromSubstring(
+        string, start, scanOffset, tokenStart, major, minor,
+        canonicalize: true);
+  }
+
   bool atEndOfFile() => scanOffset >= string.length - 1;
 }
diff --git a/pkg/front_end/lib/src/fasta/scanner/token.dart b/pkg/front_end/lib/src/fasta/scanner/token.dart
index 26ab536..e347dc2 100644
--- a/pkg/front_end/lib/src/fasta/scanner/token.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/token.dart
@@ -187,6 +187,41 @@
   }
 }
 
+/**
+ * A specialized comment token representing a language version
+ * (e.g. '// @dart = 2.1').
+ */
+class LanguageVersionToken extends CommentToken {
+  /**
+   * The major language version.
+   */
+  int major;
+
+  /**
+   * The minor language version.
+   */
+  int minor;
+
+  LanguageVersionToken.from(String text, int offset, this.major, this.minor)
+      : super.fromString(TokenType.SINGLE_LINE_COMMENT, text, offset);
+
+  LanguageVersionToken.fromSubstring(
+      String string, int start, int end, int tokenStart, this.major, this.minor,
+      {bool canonicalize})
+      : super.fromSubstring(
+            TokenType.SINGLE_LINE_COMMENT, string, start, end, tokenStart,
+            canonicalize: canonicalize);
+
+  LanguageVersionToken.fromUtf8Bytes(List<int> bytes, int start, int end,
+      int tokenStart, this.major, this.minor)
+      : super.fromUtf8Bytes(
+            TokenType.SINGLE_LINE_COMMENT, bytes, start, end, true, tokenStart);
+
+  @override
+  LanguageVersionToken copy() =>
+      new LanguageVersionToken.from(lexeme, offset, major, minor);
+}
+
 class DartDocToken extends CommentToken
     implements analyzer.DocumentationCommentToken {
   /**
diff --git a/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart
index eec14d4..e847390 100644
--- a/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart
@@ -12,7 +12,11 @@
 
 import '../scanner.dart' show unicodeReplacementCharacter;
 
-import 'token.dart' show CommentToken, DartDocToken, StringToken;
+import 'abstract_scanner.dart'
+    show LanguageVersionChanged, ScannerConfiguration;
+
+import 'token.dart'
+    show CommentToken, DartDocToken, LanguageVersionToken, StringToken;
 
 import 'array_based_scanner.dart' show ArrayBasedScanner;
 
@@ -81,8 +85,12 @@
    * array whose last element is '0' to signal the end of the file. If this
    * is not the case, the entire array is copied before scanning.
    */
-  Utf8BytesScanner(this.bytes, {bool includeComments: false})
-      : super(includeComments, numberOfBytesHint: bytes.length) {
+  Utf8BytesScanner(this.bytes,
+      {ScannerConfiguration configuration,
+      bool includeComments: false,
+      LanguageVersionChanged languageVersionChanged})
+      : super(configuration, includeComments, languageVersionChanged,
+            numberOfBytesHint: bytes.length) {
     assert(bytes.last == 0);
     // Skip a leading BOM.
     if (containsBomAt(0)) byteOffset += 3;
@@ -232,5 +240,12 @@
         type, bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart);
   }
 
+  @override
+  LanguageVersionToken createLanguageVersionToken(
+      int start, int major, int minor) {
+    return new LanguageVersionToken.fromUtf8Bytes(
+        bytes, start, byteOffset, tokenStart, major, minor);
+  }
+
   bool atEndOfFile() => byteOffset >= bytes.length - 1;
 }
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index 88edaba..cf3c27f 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -287,8 +287,8 @@
   }
 
   @override
-  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
-      int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     debugEvent("Fields");
     buildFields(count, beginToken, false);
   }
@@ -318,8 +318,14 @@
   }
 
   @override
-  void endTopLevelFields(Token staticToken, Token covariantToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
     debugEvent("TopLevelFields");
     buildFields(count, beginToken, true);
   }
@@ -357,10 +363,8 @@
   @override
   void endLibraryName(Token libraryKeyword, Token semicolon) {
     debugEvent("endLibraryName");
-    pop(); // name
-
-    Token metadata = pop();
-    parseMetadata(library, metadata, library.target);
+    pop(); // Name.
+    pop(); // Annotations.
   }
 
   @override
@@ -531,7 +535,6 @@
 
     ProcedureBuilder builder = lookupConstructor(beginToken, name);
     if (bodyToken == null || optional("=", bodyToken.endGroup.next)) {
-      parseMetadata(builder, metadata, builder.target);
       buildRedirectingFactoryMethod(
           bodyToken, builder, MemberKind.Factory, metadata);
     } else {
@@ -703,18 +706,14 @@
     debugEvent("beginClassOrMixinBody");
     Token beginToken = pop();
     Object name = pop();
-    Token metadata = pop();
+    pop(); // Annotation begin token.
     assert(currentClass == null);
     assert(memberScope == library.scope);
     if (name is ParserRecovery) {
       currentClassIsParserRecovery = true;
       return;
     }
-
-    Declaration classBuilder = lookupBuilder(beginToken, null, name);
-    parseMetadata(classBuilder, metadata, classBuilder.target);
-
-    currentClass = classBuilder;
+    currentClass = lookupBuilder(beginToken, null, name);
     memberScope = currentClass.scope;
   }
 
@@ -741,26 +740,9 @@
   @override
   void endEnum(Token enumKeyword, Token leftBrace, int count) {
     debugEvent("Enum");
-    List<Object> metadataAndValues =
-        const FixedNullableList<Object>().pop(stack, count * 2);
-    Object name = pop();
-    Token metadata = pop();
-    checkEmpty(enumKeyword.charOffset);
-    if (name is ParserRecovery) return;
-
-    ClassBuilder enumBuilder = lookupBuilder(enumKeyword, null, name);
-    parseMetadata(enumBuilder, metadata, enumBuilder.target);
-    if (metadataAndValues != null) {
-      for (int i = 0; i < metadataAndValues.length; i += 2) {
-        Token metadata = metadataAndValues[i];
-        String valueName = metadataAndValues[i + 1];
-        Declaration declaration = enumBuilder.scope.local[valueName];
-        if (metadata != null) {
-          parseMetadata(declaration, metadata, declaration.target);
-        }
-      }
-    }
-
+    const FixedNullableList<Object>().pop(stack, count * 2);
+    pop(); // Name.
+    pop(); // Annotations begin token.
     checkEmpty(enumKeyword.charOffset);
   }
 
@@ -769,20 +751,9 @@
       Token equals, Token implementsKeyword, Token endToken) {
     debugEvent("NamedMixinApplication");
 
-    Object name = pop();
-    Token metadata = pop();
+    pop(); // Name.
+    pop(); // Annotations begin token.
     checkEmpty(beginToken.charOffset);
-    if (name is ParserRecovery) return;
-
-    Declaration classBuilder = library.scopeBuilder[name];
-    if (classBuilder != null) {
-      // TODO(ahe): We shouldn't have to check for null here. The problem is
-      // that we don't create a named mixin application if the mixins or
-      // supertype are missing. Could we create a class instead? The nested
-      // declarations wouldn't match up.
-      parseMetadata(classBuilder, metadata, classBuilder.target);
-      checkEmpty(beginToken.charOffset);
-    }
   }
 
   AsyncMarker getAsyncMarker(StackListener listener) => listener.pop();
@@ -794,13 +765,11 @@
   void listenerFinishFunction(
       StackListener listener,
       Token token,
-      Token metadata,
       MemberKind kind,
-      List metadataConstants,
       dynamic formals,
       AsyncMarker asyncModifier,
       dynamic body) {
-    listener.finishFunction(metadataConstants, formals, asyncModifier, body);
+    listener.finishFunction(formals, asyncModifier, body);
   }
 
   /// Invokes the listener's [finishFields] method.
@@ -817,10 +786,9 @@
     Token token = startToken;
     try {
       Parser parser = new Parser(listener);
-      List metadataConstants;
       if (metadata != null) {
         parser.parseMetadataStar(parser.syntheticPreviousToken(metadata));
-        metadataConstants = listener.pop();
+        listener.pop(); // Annotations.
       }
       token = parser.parseFormalParametersOpt(
           parser.syntheticPreviousToken(token), kind);
@@ -834,8 +802,8 @@
       parser.parseFunctionBody(token, isExpression, allowAbstract);
       var body = listener.pop();
       listener.checkEmpty(token.charOffset);
-      listenerFinishFunction(listener, startToken, metadata, kind,
-          metadataConstants, formals, asyncModifier, body);
+      listenerFinishFunction(
+          listener, startToken, kind, formals, asyncModifier, body);
     } on DebugAbort {
       rethrow;
     } catch (e, s) {
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 0f4d72f..964646f 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -41,6 +41,7 @@
 // TODO(ahe): The outline isn't supposed to import kernel-specific builders.
 import '../kernel/kernel_builder.dart'
     show
+        KernelMetadataBuilder,
         KernelMixinApplicationBuilder,
         KernelNamedTypeBuilder,
         KernelTypeBuilder;
@@ -137,36 +138,23 @@
   @override
   void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
     debugEvent("Metadata");
-    List arguments = pop();
-    popIfNotNull(periodBeforeName); // charOffset.
-    String postfix = popIfNotNull(periodBeforeName);
-    List<TypeBuilder> typeArguments = pop();
-    if (arguments == null) {
-      pop(); // charOffset
-      Object expression = pop();
-      push(new MetadataBuilder<KernelTypeBuilder>.fromExpression(
-          expression, postfix, library, beginToken.charOffset));
-    } else {
-      int charOffset = pop();
-      Object typeName = pop();
-      if (typeName is ParserRecovery) {
-        push(typeName);
-      } else {
-        push(new MetadataBuilder<KernelTypeBuilder>.fromConstructor(
-            library.addConstructorReference(
-                typeName, typeArguments, postfix, charOffset),
-            arguments,
-            library,
-            beginToken.charOffset));
-      }
+    pop(); // arguments
+    if (periodBeforeName != null) {
+      pop(); // offset
+      pop(); // constructor name
     }
+    pop(); // type arguments
+    pop(); // offset
+    Object sentinel = pop(); // prefix or constructor
+    push(sentinel is ParserRecovery
+        ? sentinel
+        : new KernelMetadataBuilder(beginToken));
   }
 
   @override
   void endMetadataStar(int count) {
     debugEvent("MetadataStar");
-    push(const FixedNullableList<MetadataBuilder<KernelTypeBuilder>>()
-            .pop(stack, count) ??
+    push(const FixedNullableList<MetadataBuilder>().pop(stack, count) ??
         NullValue.Metadata);
   }
 
@@ -212,7 +200,7 @@
     List<Configuration> configurations = pop();
     int uriOffset = popCharOffset();
     String uri = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     library.addExport(metadata, uri, configurations, combinators,
         exportKeyword.charOffset, uriOffset);
     checkEmpty(exportKeyword.charOffset);
@@ -240,7 +228,7 @@
     List<Configuration> configurations = pop();
     int uriOffset = popCharOffset();
     String uri = pop(); // For a conditional import, this is the default URI.
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(importKeyword.charOffset);
     if (prefix is ParserRecovery) return;
     library.addImport(
@@ -304,7 +292,7 @@
     debugEvent("Part");
     int charOffset = popCharOffset();
     String uri = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     library.addPart(metadata, uri, charOffset);
     checkEmpty(partKeyword.charOffset);
   }
@@ -327,7 +315,7 @@
   void handleIdentifier(Token token, IdentifierContext context) {
     if (context == IdentifierContext.enumValueDeclaration) {
       debugEvent("handleIdentifier");
-      List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+      List<MetadataBuilder> metadata = pop();
       if (token.isSynthetic) {
         push(new ParserRecovery(token.charOffset));
       } else {
@@ -435,7 +423,7 @@
     popCharOffset();
     String documentationComment = getDocumentationComment(libraryKeyword);
     Object name = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     library.documentationComment = documentationComment;
     if (name is! ParserRecovery) {
       library.name = flattenName(name, offsetForToken(libraryKeyword), uri);
@@ -551,7 +539,7 @@
     if (typeVariables != null && supertype is MixinApplicationBuilder) {
       supertype.typeVariables = typeVariables;
     }
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
@@ -589,7 +577,7 @@
         pop(NullValue.TypeVariables);
     int nameOffset = pop();
     Object name = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop(NullValue.Metadata);
+    List<MetadataBuilder> metadata = pop(NullValue.Metadata);
     checkEmpty(mixinToken.charOffset);
     if (name is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
@@ -657,7 +645,7 @@
     if (isAbstract) {
       modifiers |= abstractMask;
     }
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(beginToken.charOffset);
     library
         .endNestedDeclaration("#method")
@@ -843,7 +831,7 @@
     }
     bool isConst = (modifiers & constMask) != 0;
     int varFinalOrConstOffset = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     String documentationComment = getDocumentationComment(beginToken);
     library
         .endNestedDeclaration("#method")
@@ -938,7 +926,7 @@
         pop();
     int charOffset = pop();
     Object name = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery || mixinApplication is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
@@ -1017,8 +1005,10 @@
   }
 
   @override
-  void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
-      Token varFinalOrConst) {
+  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+      Token covariantToken, Token varFinalOrConst) {
+    // TODO(danrubel): handle required token
+    reportNonNullableModifierError(requiredToken);
     push((covariantToken != null ? covariantMask : 0) |
         Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme));
   }
@@ -1031,7 +1021,7 @@
     Object name = pop();
     TypeBuilder type = nullIfParserRecovery(pop());
     int modifiers = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     if (name is ParserRecovery) {
       push(name);
     } else {
@@ -1183,7 +1173,7 @@
     int charOffset = pop(); // identifier char offset.
     int startCharOffset = enumKeyword.charOffset;
     Object name = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(enumKeyword.charOffset);
     if (name is ParserRecovery) return;
     library.addEnum(documentationComment, metadata, name, enumConstantInfos,
@@ -1221,13 +1211,14 @@
   }
 
   @override
-  void endFunctionTypedFormalParameter(Token nameToken) {
+  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
     debugEvent("FunctionTypedFormalParameter");
     List<FormalParameterBuilder> formals = pop();
     int formalsOffset = pop();
     TypeBuilder returnType = pop();
     List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables =
         pop();
+    reportErrorIfNullableType(question);
     push(library.addFunctionType(
         returnType, typeVariables, formals, formalsOffset));
   }
@@ -1280,22 +1271,30 @@
         addProblem(messageTypedefNotFunction, equals.charOffset, equals.length);
       }
     }
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(typedefKeyword.charOffset);
     library.addFunctionTypeAlias(documentationComment, metadata, name,
         typeVariables, functionType, charOffset);
   }
 
   @override
-  void endTopLevelFields(Token staticToken, Token covariantToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
     debugEvent("endTopLevelFields");
+    // TODO(danrubel): handle NNBD 'late' modifier
+    reportNonNullableModifierError(lateToken);
     List<FieldInfo> fieldInfos = popFieldInfos(count);
     TypeBuilder type = nullIfParserRecovery(pop());
     int modifiers = (staticToken != null ? staticMask : 0) |
         (covariantToken != null ? covariantMask : 0) |
         Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(beginToken.charOffset);
     if (fieldInfos == null) return;
     String documentationComment = getDocumentationComment(beginToken);
@@ -1304,9 +1303,11 @@
   }
 
   @override
-  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
-      int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     debugEvent("Fields");
+    // TODO(danrubel): handle NNBD 'late' modifier
+    reportNonNullableModifierError(lateToken);
     List<FieldInfo> fieldInfos = popFieldInfos(count);
     TypeBuilder type = pop();
     int modifiers = (staticToken != null ? staticMask : 0) |
@@ -1319,7 +1320,7 @@
           varFinalOrConst.length);
       modifiers &= ~constMask;
     }
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     if (fieldInfos == null) return;
     String documentationComment = getDocumentationComment(beginToken);
     library.addFields(
@@ -1449,7 +1450,7 @@
     debugEvent("endPartOf");
     int charOffset = popCharOffset();
     Object containingLibrary = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     if (hasName) {
       library.addPartOf(metadata,
           flattenName(containingLibrary, charOffset, uri), null, charOffset);
@@ -1499,7 +1500,7 @@
     int charOffset = pop();
     Object name = pop();
     int modifiers = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     if (name is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
       return;
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index be97aab..09cd1c9 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -11,7 +11,9 @@
 
 import '../fasta_codes.dart'
     show
+        Message,
         noLength,
+        templateBadTypeVariableInSupertype,
         templateConflictsWithConstructor,
         templateConflictsWithFactory,
         templateConflictsWithMember,
@@ -28,6 +30,7 @@
         KernelClassBuilder,
         KernelFieldBuilder,
         KernelFunctionBuilder,
+        KernelInvalidTypeBuilder,
         KernelLibraryBuilder,
         KernelNamedTypeBuilder,
         KernelTypeBuilder,
@@ -40,6 +43,8 @@
 
 import '../kernel/kernel_shadow_ast.dart' show ShadowClass;
 
+import '../kernel/type_algorithms.dart' show Variance, computeVariance;
+
 import '../problems.dart' show unexpected, unhandled;
 
 ShadowClass initializeClass(
@@ -144,6 +149,7 @@
 
     scope.forEach(buildBuilders);
     constructors.forEach(buildBuilders);
+    supertype = checkSupertype(supertype);
     actualCls.supertype =
         supertype?.buildSupertype(library, charOffset, fileUri);
     if (!isMixinDeclaration &&
@@ -160,16 +166,25 @@
           fileUri);
       actualCls.supertype = null;
     }
+    if (actualCls.supertype == null && supertype is! KernelNamedTypeBuilder) {
+      supertype = null;
+    }
+    mixedInType = checkSupertype(mixedInType);
     actualCls.mixedInType =
         mixedInType?.buildMixedInType(library, charOffset, fileUri);
+    if (actualCls.mixedInType == null &&
+        mixedInType is! KernelNamedTypeBuilder) {
+      mixedInType = null;
+    }
     actualCls.isMixinDeclaration = isMixinDeclaration;
     // TODO(ahe): If `cls.supertype` is null, and this isn't Object, report a
     // compile-time error.
     cls.isAbstract = isAbstract;
     if (interfaces != null) {
-      for (KernelTypeBuilder interface in interfaces) {
+      for (int i = 0; i < interfaces.length; ++i) {
+        interfaces[i] = checkSupertype(interfaces[i]);
         Supertype supertype =
-            interface.buildSupertype(library, charOffset, fileUri);
+            interfaces[i].buildSupertype(library, charOffset, fileUri);
         if (supertype != null) {
           // TODO(ahe): Report an error if supertype is null.
           actualCls.implementedTypes.add(supertype);
@@ -202,9 +217,10 @@
     scope.setters.forEach((String name, Declaration setter) {
       Declaration member = scopeBuilder[name];
       if (member == null ||
-          !(member.isField && !member.isFinal ||
-              member.isRegularMethod && member.isStatic && setter.isStatic))
+          !(member.isField && !member.isFinal && !member.isConst ||
+              member.isRegularMethod && member.isStatic && setter.isStatic)) {
         return;
+      }
       if (member.isInstanceMember == setter.isInstanceMember) {
         addProblem(templateConflictsWithMember.withArguments(name),
             setter.charOffset, noLength);
@@ -233,6 +249,26 @@
     return cls;
   }
 
+  KernelTypeBuilder checkSupertype(KernelTypeBuilder supertype) {
+    if (typeVariables == null || supertype == null) return supertype;
+    Message message;
+    for (int i = 0; i < typeVariables.length; ++i) {
+      int variance = computeVariance(typeVariables[i], supertype);
+      if (variance == Variance.contravariant ||
+          variance == Variance.invariant) {
+        message = templateBadTypeVariableInSupertype.withArguments(
+            typeVariables[i].name, supertype.name);
+        library.addProblem(message, charOffset, noLength, fileUri);
+      }
+    }
+    if (message != null) {
+      return new KernelNamedTypeBuilder(supertype.name, null)
+        ..bind(new KernelInvalidTypeBuilder(supertype.name,
+            message.withLocation(fileUri, charOffset, noLength)));
+    }
+    return supertype;
+  }
+
   void addSyntheticConstructor(Constructor constructor) {
     String name = constructor.name.name;
     cls.constructors.add(constructor);
@@ -276,7 +312,7 @@
 
   List<Declaration> computeDirectSupertypes(ClassBuilder objectClass) {
     final List<Declaration> result = <Declaration>[];
-    final KernelNamedTypeBuilder supertype = this.supertype;
+    final KernelTypeBuilder supertype = this.supertype;
     if (supertype != null) {
       result.add(supertype.declaration);
     } else if (objectClass != this) {
@@ -285,11 +321,11 @@
     final List<KernelTypeBuilder> interfaces = this.interfaces;
     if (interfaces != null) {
       for (int i = 0; i < interfaces.length; i++) {
-        KernelNamedTypeBuilder interface = interfaces[i];
+        KernelTypeBuilder interface = interfaces[i];
         result.add(interface.declaration);
       }
     }
-    final KernelNamedTypeBuilder mixedInType = this.mixedInType;
+    final KernelTypeBuilder mixedInType = this.mixedInType;
     if (mixedInType != null) {
       result.add(mixedInType.declaration);
     }
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 8d2b369..89abbb2 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -34,6 +34,8 @@
 
 import '../combinator.dart' show Combinator;
 
+import '../configuration.dart' show Configuration;
+
 import '../export.dart' show Export;
 
 import '../fasta_codes.dart'
@@ -69,7 +71,7 @@
 
 import '../import.dart' show Import;
 
-import '../configuration.dart' show Configuration;
+import '../modifier.dart' show constMask;
 
 import '../problems.dart' show unexpected, unhandled;
 
@@ -390,32 +392,29 @@
       String name,
       int charOffset,
       int charEndOffset,
-      Token initializerTokenForInference,
-      bool hasInitializer);
+      Token initializerToken,
+      bool hasInitializer,
+      {Token constInitializerToken});
 
   void addFields(String documentationComment, List<MetadataBuilder> metadata,
       int modifiers, T type, List<FieldInfo> fieldInfos) {
     for (FieldInfo info in fieldInfos) {
-      String name = info.name;
-      int charOffset = info.charOffset;
-      int charEndOffset = info.charEndOffset;
-      bool hasInitializer = info.initializerTokenForInference != null;
-      Token initializerTokenForInference =
-          type != null || legacyMode ? null : info.initializerTokenForInference;
-      if (initializerTokenForInference != null) {
-        Token beforeLast = info.beforeLast;
-        beforeLast.setNext(new Token.eof(beforeLast.next.offset));
+      bool isConst = modifiers & constMask != 0;
+      Token startToken;
+      if (isConst || (type == null && !legacyMode)) {
+        startToken = info.initializerToken;
       }
-      addField(
-          documentationComment,
-          metadata,
-          modifiers,
-          type,
-          name,
-          charOffset,
-          charEndOffset,
-          initializerTokenForInference,
-          hasInitializer);
+      if (startToken != null) {
+        // Extract only the tokens for the initializer expression from the
+        // token stream.
+        Token endToken = info.beforeLast;
+        endToken.setNext(new Token.eof(endToken.next.offset));
+        new Token.eof(startToken.previous.offset).setNext(startToken);
+      }
+      bool hasInitializer = info.initializerToken != null;
+      addField(documentationComment, metadata, modifiers, type, info.name,
+          info.charOffset, info.charEndOffset, startToken, hasInitializer,
+          constInitializerToken: isConst ? startToken : null);
     }
   }
 
@@ -618,7 +617,12 @@
 
     scope.setters.forEach((String name, Declaration setter) {
       Declaration member = scopeBuilder[name];
-      if (member == null || !member.isField || member.isFinal) return;
+      if (member == null ||
+          !member.isField ||
+          member.isFinal ||
+          member.isConst) {
+        return;
+      }
       addProblem(templateConflictsWithMember.withArguments(name),
           setter.charOffset, noLength, fileUri);
       // TODO(ahe): Context to previous message?
@@ -644,7 +648,7 @@
       // If [library] is null, we have already reported a problem that this
       // part is orphaned.
       List<LocatedMessage> context = <LocatedMessage>[
-        messagePartInPartLibraryContext.withLocation(library.fileUri, 0, 1),
+        messagePartInPartLibraryContext.withLocation(library.fileUri, -1, 1),
       ];
       for (int offset in partOffsets) {
         addProblem(messagePartInPart, offset, noLength, fileUri,
@@ -658,7 +662,7 @@
     parts.clear();
     if (exporters.isNotEmpty) {
       List<LocatedMessage> context = <LocatedMessage>[
-        messagePartExportContext.withLocation(fileUri, 0, 1),
+        messagePartExportContext.withLocation(fileUri, -1, 1),
       ];
       for (Export export in exporters) {
         export.exporter.addProblem(
@@ -849,7 +853,7 @@
     for (UnresolvedType<T> t in types) {
       t.resolveIn(scope, this);
       if (!loader.target.legacyMode) {
-        t.checkType();
+        t.checkType(this);
       } else {
         t.normalizeType();
       }
@@ -990,14 +994,16 @@
         parent.addType(type);
       } else if (nameOrQualified is QualifiedName) {
         // Attempt to use a member or type variable as a prefix.
-        type.builder.bind(type.builder.buildInvalidType(
-            templateNotAPrefixInTypeAnnotation
-                .withArguments(
-                    flattenName(nameOrQualified.qualifier, type.charOffset,
-                        type.fileUri),
-                    nameOrQualified.name)
-                .withLocation(type.fileUri, type.charOffset,
-                    nameOrQualified.endCharOffset - type.charOffset)));
+        Message message = templateNotAPrefixInTypeAnnotation.withArguments(
+            flattenName(
+                nameOrQualified.qualifier, type.charOffset, type.fileUri),
+            nameOrQualified.name);
+        library.addProblem(message, type.charOffset,
+            nameOrQualified.endCharOffset - type.charOffset, type.fileUri);
+        type.builder.bind(type.builder.buildInvalidType(message.withLocation(
+            type.fileUri,
+            type.charOffset,
+            nameOrQualified.endCharOffset - type.charOffset)));
       } else {
         scope ??= toScope(null).withTypeVariables(typeVariables);
         type.resolveIn(scope, library);
@@ -1014,10 +1020,10 @@
 class FieldInfo {
   final String name;
   final int charOffset;
-  final Token initializerTokenForInference;
+  final Token initializerToken;
   final Token beforeLast;
   final int charEndOffset;
 
-  const FieldInfo(this.name, this.charOffset, this.initializerTokenForInference,
+  const FieldInfo(this.name, this.charOffset, this.initializerToken,
       this.beforeLast, this.charEndOffset);
 }
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 4c3b6c9..c420708 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -82,6 +82,7 @@
         KernelProcedureBuilder,
         KernelTypeBuilder,
         LibraryBuilder,
+        MemberBuilder,
         NamedTypeBuilder,
         TypeBuilder;
 
@@ -103,7 +104,8 @@
 
 import '../problems.dart' show internalProblem;
 
-import '../scanner.dart' show ErrorToken, ScannerResult, Token, scan;
+import '../scanner.dart'
+    show ErrorToken, ScannerConfiguration, ScannerResult, Token, scan;
 
 import '../type_inference/interface_resolver.dart' show InterfaceResolver;
 
@@ -199,7 +201,10 @@
       byteCount += rawBytes.length;
     }
 
-    ScannerResult result = scan(bytes, includeComments: includeComments);
+    ScannerResult result = scan(bytes,
+        includeComments: includeComments,
+        configuration: new ScannerConfiguration(
+            enableTripleShift: target.enableTripleShift));
     Token token = result.tokens;
     if (!suppressLexicalErrors) {
       List<int> source = getSource(bytes);
@@ -947,6 +952,23 @@
     ticker.logMs("Checked mixin declaration applications");
   }
 
+  void buildOutlineExpressions() {
+    builders.forEach((Uri uri, LibraryBuilder library) {
+      if (library.loader == this) {
+        library.buildOutlineExpressions();
+        Iterator<Declaration> iterator = library.iterator;
+        while (iterator.moveNext()) {
+          Declaration declaration = iterator.current;
+          if (declaration is ClassBuilder) {
+            declaration.buildOutlineExpressions(library);
+          } else if (declaration is MemberBuilder) {
+            declaration.buildOutlineExpressions(library);
+          }
+        }
+      }
+    });
+  }
+
   ClassHierarchyBuilder buildClassHierarchy(
       List<SourceClassBuilder> sourceClasses, ClassBuilder objectClass) {
     ClassHierarchyBuilder hierarchy = ClassHierarchyBuilder.build(
@@ -1036,17 +1058,17 @@
 
   void transformListPostInference(List<TreeNode> list,
       bool transformSetLiterals, bool transformCollections) {
-    if (transformSetLiterals) {
-      SetLiteralTransformer transformer = setLiteralTransformer ??=
-          new SetLiteralTransformer(this,
-              transformConst: !target.enableConstantUpdate2018);
+    if (transformCollections) {
+      CollectionTransformer transformer =
+          collectionTransformer ??= new CollectionTransformer(this);
       for (int i = 0; i < list.length; ++i) {
         list[i] = list[i].accept(transformer);
       }
     }
-    if (transformCollections) {
-      CollectionTransformer transformer =
-          collectionTransformer ??= new CollectionTransformer(this);
+    if (transformSetLiterals) {
+      SetLiteralTransformer transformer = setLiteralTransformer ??=
+          new SetLiteralTransformer(this,
+              transformConst: !target.enableConstantUpdate2018);
       for (int i = 0; i < list.length; ++i) {
         list[i] = list[i].accept(transformer);
       }
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener.dart b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
index db6a7cd..443b623 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
@@ -86,8 +86,8 @@
 
   // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
   // and ast_builder.dart.
-  void finishFunction(covariant List<Object> annotations, covariant formals,
-      AsyncMarker asyncModifier, covariant body) {
+  void finishFunction(
+      covariant formals, AsyncMarker asyncModifier, covariant body) {
     return unsupported("finishFunction", -1, uri);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
index e6d7ef8..621a14e 100644
--- a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
@@ -550,8 +550,8 @@
   }
 
   @override
-  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
-      int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     debugEvent("Fields", staticToken);
     state.discard(count); // Field names.
     state.checkEmpty(endToken);
@@ -677,7 +677,7 @@
   }
 
   @override
-  void endFunctionTypedFormalParameter(Token nameToken) {
+  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
     debugEvent("FunctionTypedFormalParameter", nameToken);
   }
 
@@ -1238,8 +1238,14 @@
   }
 
   @override
-  void endTopLevelFields(Token staticToken, Token covariantToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
     debugEvent("TopLevelFields", staticToken);
     state.discard(count); // Field names.
     state.checkEmpty(endToken);
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 6e82a7d..2ca6f77 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -50,18 +50,27 @@
 
   bool enableConstantUpdate2018;
   bool enableControlFlowCollections;
+  bool enableExtensionMethods;
+  bool enableNonNullable;
   bool enableSetLiterals;
   bool enableSpreadCollections;
+  bool enableTripleShift;
 
   TargetImplementation(Ticker ticker, this.uriTranslator, this.backendTarget)
       : enableConstantUpdate2018 = CompilerContext.current.options
             .isExperimentEnabled(ExperimentalFlag.constantUpdate2018),
         enableControlFlowCollections = CompilerContext.current.options
             .isExperimentEnabled(ExperimentalFlag.controlFlowCollections),
+        enableExtensionMethods = CompilerContext.current.options
+            .isExperimentEnabled(ExperimentalFlag.extensionMethods),
+        enableNonNullable = CompilerContext.current.options
+            .isExperimentEnabled(ExperimentalFlag.nonNullable),
         enableSetLiterals = CompilerContext.current.options
             .isExperimentEnabled(ExperimentalFlag.setLiterals),
         enableSpreadCollections = CompilerContext.current.options
             .isExperimentEnabled(ExperimentalFlag.spreadCollections),
+        enableTripleShift = CompilerContext.current.options
+            .isExperimentEnabled(ExperimentalFlag.tripleShift),
         super(ticker);
 
   /// Creates a [LibraryBuilder] corresponding to [uri], if one doesn't exist
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 0a4fad1..f967227 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -35,19 +35,22 @@
 Future<CompilerResult> generateKernel(ProcessedOptions options,
     {bool buildSummary: false,
     bool buildComponent: true,
-    bool truncateSummary: false}) async {
+    bool truncateSummary: false,
+    bool includeOffsets: true}) async {
   return await CompilerContext.runWithOptions(options, (_) async {
     return await generateKernelInternal(
         buildSummary: buildSummary,
         buildComponent: buildComponent,
-        truncateSummary: truncateSummary);
+        truncateSummary: truncateSummary,
+        includeOffsets: includeOffsets);
   });
 }
 
 Future<CompilerResult> generateKernelInternal(
     {bool buildSummary: false,
     bool buildComponent: true,
-    bool truncateSummary: false}) async {
+    bool truncateSummary: false,
+    bool includeOffsets: true}) async {
   var options = CompilerContext.current.options;
   var fs = options.fileSystem;
 
@@ -138,8 +141,8 @@
         options.ticker.logMs("Transformed outline");
       }
       // Don't include source (but do add it above to include importUris).
-      summary =
-          serializeComponent(trimmedSummaryComponent, includeSources: false);
+      summary = serializeComponent(trimmedSummaryComponent,
+          includeSources: false, includeOffsets: includeOffsets);
       options.ticker.logMs("Generated outline");
     }
 
diff --git a/pkg/front_end/lib/src/scanner/token.dart b/pkg/front_end/lib/src/scanner/token.dart
index 62718b0..5947f80 100644
--- a/pkg/front_end/lib/src/scanner/token.dart
+++ b/pkg/front_end/lib/src/scanner/token.dart
@@ -173,6 +173,9 @@
 
   static const Keyword EXTENDS = const Keyword("extends", "EXTENDS");
 
+  static const Keyword EXTENSION = const Keyword("extension", "EXTENSION",
+      isBuiltIn: true, isTopLevelKeyword: true);
+
   static const Keyword EXTERNAL =
       const Keyword("external", "EXTERNAL", isBuiltIn: true, isModifier: true);
 
@@ -211,6 +214,8 @@
   static const Keyword IS =
       const Keyword("is", "IS", precedence: RELATIONAL_PRECEDENCE);
 
+  static const Keyword LATE = const Keyword("late", "LATE", isModifier: true);
+
   static const Keyword LIBRARY = const Keyword("library", "LIBRARY",
       isBuiltIn: true, isTopLevelKeyword: true);
 
@@ -236,6 +241,9 @@
 
   static const Keyword PATCH = const Keyword("patch", "PATCH", isPseudo: true);
 
+  static const Keyword REQUIRED =
+      const Keyword("required", "REQUIRED", isBuiltIn: true, isModifier: true);
+
   static const Keyword RETHROW = const Keyword("rethrow", "RETHROW");
 
   static const Keyword RETURN = const Keyword("return", "RETURN");
@@ -298,6 +306,7 @@
     ENUM,
     EXPORT,
     EXTENDS,
+    EXTENSION,
     EXTERNAL,
     FACTORY,
     FALSE,
@@ -313,6 +322,7 @@
     IN,
     INTERFACE,
     IS,
+    LATE,
     LIBRARY,
     MIXIN,
     NATIVE,
@@ -323,6 +333,7 @@
     OPERATOR,
     PART,
     PATCH,
+    REQUIRED,
     RETHROW,
     RETURN,
     SET,
@@ -1146,7 +1157,7 @@
       stringValue: null);
 
   static const TokenType IDENTIFIER = const TokenType(
-      'identifier', 'STRING_INT', NO_PRECEDENCE, IDENTIFIER_TOKEN,
+      'identifier', 'IDENTIFIER', NO_PRECEDENCE, IDENTIFIER_TOKEN,
       stringValue: null);
 
   static const TokenType INT = const TokenType(
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 844ba61..0fccb0c 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -21,6 +21,7 @@
 AsyncAsIdentifier/example: Fail
 AwaitAsIdentifier/example: Fail
 AwaitNotAsync/example: Fail
+BadTypeVariableInSupertype/analyzerCode: Fail
 BuiltInIdentifierAsType/example: Fail
 BuiltInIdentifierInDeclaration/example: Fail
 CannotAssignToParenthesizedExpression/example: Fail
@@ -42,6 +43,7 @@
 CantUseSuperBoundedTypeForInstanceCreation/analyzerCode: Fail
 CantUseSuperBoundedTypeForInstanceCreation/example: Fail
 ColonInPlaceOfIn/example: Fail
+ConflictingModifiers/script1: Fail
 ConflictsWithConstructor/example: Fail
 ConflictsWithFactory/analyzerCode: Fail
 ConflictsWithFactory/example: Fail
@@ -50,10 +52,8 @@
 ConflictsWithSetter/example: Fail
 ConflictsWithSetterWarning/example: Fail
 ConflictsWithTypeVariable/example: Fail
-ConstAndCovariant/script2: Fail
 ConstAndFinal/declaration3: Fail
 ConstAndFinal/declaration4: Fail
-ConstAndVar/script1: Fail
 ConstConstructorInSubclassOfMixinApplication/example: Fail
 ConstConstructorNonFinalField/example: Fail
 ConstConstructorRedirectionToNonConst/analyzerCode: Fail # The analyzer doesn't report this error.
@@ -102,8 +102,6 @@
 ContinueWithoutLabelInCase/script1: Fail
 CouldNotParseUri/analyzerCode: Fail
 CouldNotParseUri/example: Fail
-CovariantAfterFinal/script1: Fail
-CovariantAfterVar/script1: Fail
 CovariantAndStatic/script1: Fail
 CovariantAndStatic/script2: Fail
 CovariantMember/script1: Fail
@@ -361,7 +359,6 @@
 SpreadMapEntryTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
 SpreadTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
 StackOverflow/example: Fail
-StaticAfterConst/script1: Fail
 SuperAsExpression/example: Fail
 SuperAsIdentifier/example: Fail
 SuperNullAware/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index bc98cf9..8f1b921 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -181,18 +181,6 @@
   template: "Only maps can be used in spreads in constant maps."
   analyzerCode: CONST_SPREAD_EXPECTED_MAP
 
-ConstEvalIterationInConstList:
-  template: "Iteration can't be used in a constant list."
-  analyzerCode: NON_CONSTANT_LIST_ELEMENT
-
-ConstEvalIterationInConstSet:
-  template: "Iteration can't be used in a constant set."
-  analyzerCode: NON_CONSTANT_SET_ELEMENT
-
-ConstEvalIterationInConstMap:
-  template: "Iteration can't be used in a constant map."
-  analyzerCode: NON_CONSTANT_MAP_ELEMENT
-
 ConstEvalUnevaluated:
   template: "Could not evaluate constant expression."
 
@@ -220,7 +208,7 @@
   bytes: [255]
 
 ExperimentNotEnabled:
-  index: 93
+  index: 48
   template: "This requires the '#string' experiment to be enabled."
   tip: "Try enabling this experiment by adding it to the command line when compiling and running."
   analyzerCode: ParserErrorCode.EXPERIMENT_NOT_ENABLED
@@ -248,7 +236,7 @@
     }
 
 ExpectedElseOrComma:
-  index: 94
+  index: 46
   template: "Expected 'else' or comma."
   analyzerCode: ParserErrorCode.EXPECTED_ELSE_OR_COMMA
 
@@ -335,7 +323,7 @@
   #
   analyzerCode: ParserErrorCode.EXPECTED_INSTEAD
   script:
-    - "mixin A extends B { }"
+    - "class B {} mixin A extends B { }"
 
 MultipleLibraryDirectives:
   index: 27
@@ -362,7 +350,7 @@
   template: "The extends clause must be before the with clause."
   tip: "Try moving the extends clause before the with clause."
   analyzerCode: ParserErrorCode.WITH_BEFORE_EXTENDS
-  script: "class B {} class A with B extends C {}"
+  script: "class B {} class C {} class A with B extends C {}"
 
 ImplementsBeforeExtends:
   index: 44
@@ -425,10 +413,10 @@
       class A implements FutureOr<int> {}
 
 ExpectedClassOrMixinBody:
-  template: "Expected a class or mixin body, but got '#lexeme'."
-  analyzerCode: MISSING_CLASS_BODY
-
-ExpectedClassBodyToSkip: ExpectedClassOrMixinBody
+  index: 8
+  template: "A #string must have a body, even if it is empty."
+  tip: "Try adding an empty body."
+  analyzerCode: ParserErrorCode.EXPECTED_BODY
 
 ExpectedDeclaration:
   template: "Expected a declaration, but got '#lexeme'."
@@ -574,15 +562,6 @@
   analyzerCode: ParserErrorCode.CONST_CLASS
   script: "const class C {}"
 
-ConstAndCovariant:
-  index: 57
-  template: "Members can't be declared to be both 'const' and 'covariant'."
-  tip: "Try removing either the 'const' or 'covariant' keyword."
-  analyzerCode: ParserErrorCode.CONST_AND_COVARIANT
-  script:
-    - "class C { covariant const C f; }"
-    - "class C { const covariant C f; }"
-
 ConstAndFinal:
   index: 58
   template: "Members can't be declared to be both 'const' and 'final'."
@@ -594,11 +573,11 @@
     - "const final int x = 5;"
     - "final const int x = 5;"
 
-ConstAndVar:
+ConflictingModifiers:
   index: 59
-  template: "Members can't be declared to be both 'const' and 'var'."
-  tip: "Try removing either the 'const' or 'var' keyword."
-  analyzerCode: ParserErrorCode.CONST_AND_VAR
+  template: "Members can't be declared to be both '#string' and '#string2'."
+  tip: "Try removing one of the keywords."
+  analyzerCode: ParserErrorCode.CONFLICTING_MODIFIERS
   script:
     - "class C { const var x; }"
     - "class C { var const x; }"
@@ -639,9 +618,14 @@
   analyzerCode: ParserErrorCode.MODIFIER_OUT_OF_ORDER
   script:
     - "class C { factory const C() = prefix.B.foo; }"
+    - "class C { factory external C(); }"
+    - "class C { const external C(); }"
+    - "class C { static external f(); }"
+    - "class C { final static int f = 5; }"
+    - "class C { var static f; }"
 
 TypeBeforeFactory:
-  index: 97
+  index: 57
   template: "Factory constructors cannot have a return type."
   tip: "Try removing the type appearing before 'factory'."
   analyzerCode: ParserErrorCode.TYPE_BEFORE_FACTORY
@@ -663,22 +647,6 @@
   script:
     - "class C { const m() {} }"
 
-CovariantAfterFinal:
-  index: 65
-  template: "The modifier 'covariant' should be before the modifier 'final'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.COVARIANT_AFTER_FINAL
-  script:
-    - "final covariant f;"
-
-CovariantAfterVar:
-  index: 8
-  template: "The modifier 'covariant' should be before the modifier 'var'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.COVARIANT_AFTER_VAR
-  script:
-    - "var covariant f;"
-
 CovariantAndStatic:
   index: 66
   template: "Members can't be declared to be both 'covariant' and 'static'."
@@ -700,30 +668,6 @@
     - "class C { static static var m; }"
     - "class C { var var m; }"
 
-ExternalAfterConst:
-  index: 46
-  template: "The modifier 'external' should be before the modifier 'const'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.EXTERNAL_AFTER_CONST
-  script:
-    - "class C { const external C(); }"
-
-ExternalAfterFactory:
-  index: 47
-  template: "The modifier 'external' should be before the modifier 'factory'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.EXTERNAL_AFTER_FACTORY
-  script:
-    - "class C { factory external C(); }"
-
-ExternalAfterStatic:
-  index: 48
-  template: "The modifier 'external' should be before the modifier 'static'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.EXTERNAL_AFTER_STATIC
-  script:
-    - "class C { static external f(); }"
-
 ExternalConstructorWithBody:
   index: 87
   template: "External constructors can't have a body."
@@ -838,30 +782,6 @@
     - "class C { final var x = 5; }"
     - "class C { var final x = 5; }"
 
-StaticAfterConst:
-  index: 20
-  template: "The modifier 'static' should be before the modifier 'const'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.STATIC_AFTER_CONST
-  script:
-    - "class C { const static int f; }"
-
-StaticAfterFinal:
-  index: 19
-  template: "The modifier 'static' should be before the modifier 'final'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.STATIC_AFTER_FINAL
-  script:
-    - "class C { final static int f = 5; }"
-
-StaticAfterVar:
-  index: 18
-  template: "The modifier 'static' should be before the modifier 'var'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.STATIC_AFTER_VAR
-  script:
-    - "class C { var static f; }"
-
 StaticConstructor:
   index: 4
   template: "Constructors can't be static."
@@ -1072,7 +992,7 @@
       }
 
 StackOverflow:
-  index: 91
+  index: 19
   template: "The file has too many nested expressions or statements."
   tip: "Try simplifying the code."
   analyzerCode: ParserErrorCode.STACK_OVERFLOW
@@ -1194,10 +1114,6 @@
   template: "Abstract methods can't use 'async', 'async*', or 'sync*'."
   analyzerCode: NON_SYNC_ABSTRACT_METHOD
 
-AsyncAsIdentifier:
-  analyzerCode: ASYNC_KEYWORD_USED_AS_IDENTIFIER
-  template: "'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods."
-
 AwaitAsIdentifier:
   template: "'await' can't be used as an identifier in 'async', 'async*', or 'sync*' methods."
   analyzerCode: ASYNC_KEYWORD_USED_AS_IDENTIFIER
@@ -1255,7 +1171,7 @@
   analyzerCode: YIELD_IN_NON_GENERATOR
 
 OnlyTry:
-  index: 92
+  index: 20
   template: "A try block must be followed by an 'on', 'catch', or 'finally' clause."
   tip: "Try adding either a catch or finally clause, or remove the try statement."
   analyzerCode: ParserErrorCode.MISSING_CATCH_OR_FINALLY
@@ -1323,7 +1239,7 @@
     - "try {} catch (e, s, x) {}"
 
 SuperNullAware:
-  index: 90
+  index: 18
   template: "The operator '?.' cannot be used with 'super' because 'super' cannot be null."
   tip: "Try replacing '?.' with '.'"
   analyzerCode: ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
@@ -2571,12 +2487,12 @@
   tip: "Normally, the specification is a file named 'libraries.json' in the Dart SDK install location."
 
 InvalidSuperInInitializer:
-  index: 95
+  index: 47
   template: "Can only use 'super' in an initializer for calling the superclass constructor (e.g. 'super()' or 'super.namedConstructor()')"
   analyzerCode: ParserErrorCode.INVALID_SUPER_IN_INITIALIZER
 
 InvalidThisInInitializer:
-  index: 96
+  index: 65
   template: "Can only use 'this' in an initializer for field initialization (e.g. 'this.x = something') and constructor redirection (e.g. 'this()' or 'this.namedConstructor())"
   analyzerCode: ParserErrorCode.INVALID_THIS_IN_INITIALIZER
 
@@ -3641,3 +3557,9 @@
     main() {
       <int>[...null];
     }
+
+BadTypeVariableInSupertype:
+  template: "Found unsupported uses of '#name' in supertype '#name2'."
+  script: >
+    class A<X> {}
+    class B<Y> extends A<Function(Y)> {}
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index 1bfa71e..64e9958 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -1,19 +1,19 @@
 name: front_end
 # Currently, front_end API is not stable and users should not
 # depend on semver semantics when depending on this package.
-version: 0.1.15
+version: 0.1.18
 author: Dart Team <misc@dartlang.org>
 description: Front end for compilation of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/front_end
 environment:
   sdk: '>=2.1.0-dev.5.0 <3.0.0'
 dependencies:
-  kernel: 0.3.15
+  kernel: 0.3.18
   package_config: '^1.0.1'
   path: '^1.3.9'
   yaml: '^2.1.12'
 dev_dependencies:
-  analyzer: 0.36.0
+  analyzer: 0.36.3
   args: '>=0.13.0 <2.0.0'
   build_integration:
     path: ../build_integration
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index 6987266..7f59d4b 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -241,5 +241,6 @@
         "offset: 4, prefixGenerator: , isInitializer: false, isSuper: false)",
         new KernelUnexpectedQualifiedUseGenerator(
             helper, token, generator, false));
+    return Future<void>.value();
   });
 }
diff --git a/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart b/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
index fcaed11..08b25f7 100644
--- a/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
@@ -902,7 +902,9 @@
   }
 
   @override
-  void beginVariablesDeclaration(Token token, Token varFinalOrConst) {
+  void beginVariablesDeclaration(
+      Token token, Token lateToken, Token varFinalOrConst) {
+    // TODO(danrubel): update to include lateToken
     calls.add('beginVariablesDeclaration $token $varFinalOrConst');
   }
 
diff --git a/pkg/front_end/test/fasta/parser/parser.status b/pkg/front_end/test/fasta/parser/parser.status
index 3619aff..c43b22f 100644
--- a/pkg/front_end/test/fasta/parser/parser.status
+++ b/pkg/front_end/test/fasta/parser/parser.status
@@ -3,170 +3,6 @@
 # BSD-style license that can be found in the LICENSE.md file.
 
 pkg/analyzer_cli/test/data/file_with_error: Fail
-pkg/dev_compiler/test/codegen/corelib/from_environment_const_type_test: Fail
-pkg/dev_compiler/test/codegen/corelib/from_environment_const_type_undefined_test: Fail
-pkg/dev_compiler/test/codegen/corelib/symbol_reserved_word_test: Fail
-pkg/dev_compiler/test/codegen/destructuring: Fail
-pkg/dev_compiler/test/codegen/language/abstract_syntax_test: Fail
-pkg/dev_compiler/test/codegen/language/argument_definition_test: Fail
-pkg/dev_compiler/test/codegen/language/assign_instance_method_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/async_await_syntax_test: Fail
-pkg/dev_compiler/test/codegen/language/await_backwards_compatibility_test: Fail
-pkg/dev_compiler/test/codegen/language/bad_constructor_test: Fail
-pkg/dev_compiler/test/codegen/language/bad_initializer1_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/bad_initializer2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/bad_named_constructor_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/black_listed_test: Fail
-pkg/dev_compiler/test/codegen/language/body_less_constructor_wrong_arg_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/built_in_identifier_prefix_test: Fail
-pkg/dev_compiler/test/codegen/language/built_in_identifier_test: Fail
-pkg/dev_compiler/test/codegen/language/cascade_test: Fail
-pkg/dev_compiler/test/codegen/language/class_cycle2_test: Fail
-pkg/dev_compiler/test/codegen/language/class_keyword_test: Fail
-pkg/dev_compiler/test/codegen/language/class_syntax_test: Fail
-pkg/dev_compiler/test/codegen/language/closure_call_wrong_argument_count_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/compile_time_constant13_test: Fail
-pkg/dev_compiler/test/codegen/language/const_counter_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/const_native_factory_test: Fail
-pkg/dev_compiler/test/codegen/language/const_optional_args_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/constructor3_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/constructor_call_wrong_argument_count_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/constructor_initializer_test: Fail
-pkg/dev_compiler/test/codegen/language/constructor_name_test: Fail
-pkg/dev_compiler/test/codegen/language/constructor_redirect1_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/constructor_redirect2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/constructor_setter_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/cyclic_typedef_test: Fail
-pkg/dev_compiler/test/codegen/language/deferred_type_dependency_test: Fail
-pkg/dev_compiler/test/codegen/language/duplicate_export_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/duplicate_interface_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/enum_is_keyword_test: Fail
-pkg/dev_compiler/test/codegen/language/enum_syntax_test: Fail
-pkg/dev_compiler/test/codegen/language/export_ambiguous_main_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/extend_type_parameter2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/extend_type_parameter_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/external_test: Fail
-pkg/dev_compiler/test/codegen/language/factory2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/factory_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/field1_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/field2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/field3a_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/field4_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/field5_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/field6_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/field6a_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/field_method4_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/function_syntax_test: Fail
-pkg/dev_compiler/test/codegen/language/function_type_parameter2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/function_type_parameter_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/get_set_syntax_test: Fail
-pkg/dev_compiler/test/codegen/language/getter_declaration_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/illegal_declaration_test: Fail
-pkg/dev_compiler/test/codegen/language/import_combinators_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/inst_field_initializer1_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/instance_call_wrong_argument_count_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/instance_method2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/instance_method_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/interface2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/interface_cycle_test: Fail
-pkg/dev_compiler/test/codegen/language/interface_static_non_final_fields_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/keyword_type_expression_test: Fail
-pkg/dev_compiler/test/codegen/language/label2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/label3_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/label5_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/label6_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/library_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/list_literal2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/list_literal_syntax_test: Fail
-pkg/dev_compiler/test/codegen/language/literal_unary_plus_test: Fail
-pkg/dev_compiler/test/codegen/language/main_test: Fail
-pkg/dev_compiler/test/codegen/language/malformed_inheritance_test: Fail
-pkg/dev_compiler/test/codegen/language/malformed_test: Fail
-pkg/dev_compiler/test/codegen/language/map_literal2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/metadata_test: Fail
-pkg/dev_compiler/test/codegen/language/method_override2_test: Fail
-pkg/dev_compiler/test/codegen/language/mixin_forwarding_constructor4_test: Fail
-pkg/dev_compiler/test/codegen/language/mixin_illegal_syntax_test: Fail
-pkg/dev_compiler/test/codegen/language/mixin_invalid_inheritance1_test: Fail
-pkg/dev_compiler/test/codegen/language/named_constructor_test: Fail
-pkg/dev_compiler/test/codegen/language/named_parameters_aggregated_test: Fail
-pkg/dev_compiler/test/codegen/language/no_such_method_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/non_const_super_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/null_test: Fail
-pkg/dev_compiler/test/codegen/language/number_identifier_test: Fail
-pkg/dev_compiler/test/codegen/language/override_field_method1_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/override_field_method2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/override_field_method4_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/override_field_method5_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/override_inheritance_generic_test: Fail
-pkg/dev_compiler/test/codegen/language/parameter_default_test: Fail
-pkg/dev_compiler/test/codegen/language/parameter_initializer1_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/parameter_initializer2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/parameter_initializer3_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/parameter_initializer4_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/parameter_initializer5_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/parameter_initializer6_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix10_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix11_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix12_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix13_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix15_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix1_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix3_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix4_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix5_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix6_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix7_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/prefix8_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/private_member1_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/private_member2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/private_member3_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/regress_23051_test: Fail
-pkg/dev_compiler/test/codegen/language/script1_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/script2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/source_self_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/static_call_wrong_argument_count_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/static_parameter_test: Fail
-pkg/dev_compiler/test/codegen/language/static_top_level_test: Fail
-pkg/dev_compiler/test/codegen/language/string_interpolation9_test: Fail
-pkg/dev_compiler/test/codegen/language/string_unicode1_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/string_unicode2_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/string_unicode3_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/string_unicode4_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/switch1_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/switch3_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/switch4_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/switch5_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/switch7_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/sync_generator2_test: Fail
-pkg/dev_compiler/test/codegen/language/syntax_test: Fail
-pkg/dev_compiler/test/codegen/language/tearoff_basic_test: Fail
-pkg/dev_compiler/test/codegen/language/tearoff_constructor_basic_test: Fail
-pkg/dev_compiler/test/codegen/language/try_catch_on_syntax_test: Fail
-pkg/dev_compiler/test/codegen/language/try_catch_syntax_test: Fail
-pkg/dev_compiler/test/codegen/language/type_variable_bounds2_test: Fail
-pkg/dev_compiler/test/codegen/language/type_variable_static_context_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/unbalanced_brace_test: Fail
-pkg/dev_compiler/test/codegen/language/unresolved_in_factory_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/unresolved_top_level_method_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/unresolved_top_level_var_negative_test: Fail
-pkg/dev_compiler/test/codegen/language/unsigned_right_shift_test: Fail
-pkg/dev_compiler/test/codegen/language/variable_declaration_metadata_test: Fail
-pkg/dev_compiler/test/codegen/lib/mirrors/metadata_allowed_values_test: Fail
-pkg/dev_compiler/test/codegen/lib/mirrors/metadata_scope_test: Fail
-pkg/dev_compiler/test/codegen/lib/mirrors/mirror_in_static_init_test: Fail
-pkg/dev_compiler/test/codegen/lib/mirrors/other_declarations_location_test: Fail
-pkg/dev_compiler/test/codegen/lib/mirrors/syntax_error_test: Fail
-pkg/dev_compiler/test/codegen/lib/mirrors/typevariable_mirror_metadata_test: Fail
-pkg/dev_compiler/tool/input_sdk/lib/html/dart2js/html_dart2js: Fail
-pkg/dev_compiler/tool/input_sdk/lib/indexed_db/dart2js/indexed_db_dart2js: Fail
-pkg/dev_compiler/tool/input_sdk/lib/svg/dart2js/svg_dart2js: Fail
-pkg/dev_compiler/tool/input_sdk/lib/web_audio/dart2js/web_audio_dart2js: Fail
-pkg/dev_compiler/tool/input_sdk/lib/web_gl/dart2js/web_gl_dart2js: Fail
-pkg/dev_compiler/tool/input_sdk/lib/web_sql/dart2js/web_sql_dart2js: Fail
-pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types: Fail
-pkg/dev_compiler/tool/input_sdk/private/native_typed_data: Fail
 pkg/front_end/test/fasta/rasta/bad_interpolation: Fail
 pkg/front_end/test/fasta/rasta/issue_000032: Fail
 pkg/front_end/test/fasta/rasta/issue_000035: Fail
@@ -245,6 +81,14 @@
 samples/sample_extension/sample_asynchronous_extension: Fail
 samples/sample_extension/sample_synchronous_extension: Fail
 sdk/lib/_blink/dartium/_blink_dartium: Fail
+sdk/lib/_internal/js_dev_runtime/lib/html/dart2js/html_dart2js: Fail
+sdk/lib/_internal/js_dev_runtime/lib/indexed_db/dart2js/indexed_db_dart2js: Fail
+sdk/lib/_internal/js_dev_runtime/lib/svg/dart2js/svg_dart2js: Fail
+sdk/lib/_internal/js_dev_runtime/lib/web_audio/dart2js/web_audio_dart2js: Fail
+sdk/lib/_internal/js_dev_runtime/lib/web_gl/dart2js/web_gl_dart2js: Fail
+sdk/lib/_internal/js_dev_runtime/lib/web_sql/dart2js/web_sql_dart2js: Fail
+sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types: Fail
+sdk/lib/_internal/js_dev_runtime/private/native_typed_data: Fail
 sdk/lib/_internal/js_runtime/lib/native_typed_data: Fail
 sdk/lib/html/dart2js/html_dart2js: Fail
 sdk/lib/indexed_db/dart2js/indexed_db_dart2js: Fail
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index 5c37a69..122a125 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -2,15 +2,12 @@
 // 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:convert';
-
 import 'package:front_end/src/fasta/messages.dart';
 import 'package:front_end/src/fasta/parser.dart';
 import 'package:front_end/src/fasta/parser/type_info.dart';
 import 'package:front_end/src/fasta/parser/type_info_impl.dart';
 import 'package:front_end/src/fasta/scanner.dart' hide scanString;
-import 'package:front_end/src/fasta/scanner/recover.dart'
-    show defaultRecoveryStrategy;
+import 'package:front_end/src/fasta/scanner.dart' as scanner;
 import 'package:front_end/src/scanner/token.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -33,34 +30,10 @@
   });
 }
 
-/// TODO(danrubel): Remove this and use scanner.dart scanString
-/// once support for `>>>` is permanently enabled.
-///
-/// Scan/tokenize the given [source].
-/// If [recover] is null, then the [defaultRecoveryStrategy] is used.
-ScannerResult scanString(String source,
-    {bool includeComments: false,
-    bool scanLazyAssignmentOperators: false,
-    Recover recover}) {
-  assert(source != null, 'source must not be null');
-  StringScanner scanner =
-      new StringScanner(source, includeComments: includeComments)
-        ..enableGtGtGt = true
-        ..enableGtGtGtEq = true;
-  return _tokenizeAndRecover(scanner, recover, source: source);
-}
-
-/// TODO(danrubel): Remove this once support for `>>>` is permanently enabled.
-ScannerResult _tokenizeAndRecover(Scanner scanner, Recover recover,
-    {List<int> bytes, String source}) {
-  Token tokens = scanner.tokenize();
-  if (scanner.hasErrors) {
-    if (bytes == null) bytes = utf8.encode(source);
-    recover ??= defaultRecoveryStrategy;
-    tokens = recover(bytes, tokens, scanner.lineStarts);
-  }
-  return new ScannerResult(tokens, scanner.lineStarts, scanner.hasErrors);
-}
+ScannerResult scanString(String source, {bool includeComments: false}) =>
+    scanner.scanString(source,
+        configuration: const ScannerConfiguration(enableTripleShift: true),
+        includeComments: includeComments);
 
 @reflectiveTest
 class NoTypeInfoTest {
@@ -2768,8 +2741,9 @@
   }
 
   @override
-  void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
-      Token varFinalOrConst) {
+  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+      Token covariantToken, Token varFinalOrConst) {
+    // TODO(danrubel): Update tests to include required and covariant
     calls.add('beginFormalParameter $token $kind');
   }
 
diff --git a/pkg/front_end/test/fasta/unlinked_scope_test.dart b/pkg/front_end/test/fasta/unlinked_scope_test.dart
index e58294c..fb933f8 100644
--- a/pkg/front_end/test/fasta/unlinked_scope_test.dart
+++ b/pkg/front_end/test/fasta/unlinked_scope_test.dart
@@ -108,5 +108,6 @@
     testExpression("unresolved");
     testExpression("a + b", "a.+(b)");
     testExpression("a = b");
+    return Future<void>.value();
   });
 }
diff --git a/pkg/front_end/test/incremental_load_from_dill_test.dart b/pkg/front_end/test/incremental_load_from_dill_test.dart
index 16125c3..a2ec791 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -33,7 +33,15 @@
 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
 
 import 'package:kernel/kernel.dart'
-    show Class, Component, EmptyStatement, Field, Library, Procedure;
+    show
+        Class,
+        Component,
+        EmptyStatement,
+        Field,
+        Library,
+        LibraryDependency,
+        Name,
+        Procedure;
 
 import 'package:kernel/target/targets.dart' show TargetFlags;
 
@@ -294,14 +302,11 @@
       for (Component c in moduleComponents.values) {
         c.adoptChildren();
       }
-      sdk.unbindCanonicalNames();
-      sdk.computeCanonicalNames();
 
       modulesToUse = new List<Component>();
       for (String moduleName in world["modules"]) {
         Component moduleComponent = moduleComponents[moduleName];
         if (moduleComponent != null) {
-          moduleComponent.computeCanonicalNames();
           modulesToUse.add(moduleComponent);
         }
       }
@@ -310,7 +315,9 @@
         if (moduleComponent == null) {
           moduleComponent = new Component(nameRoot: sdk.root);
           new BinaryBuilder(moduleData[moduleName],
-                  filename: null, disableLazyReading: false)
+                  filename: null,
+                  disableLazyReading: false,
+                  alwaysCreateNewNamedNodes: true)
               .readComponent(moduleComponent);
           moduleComponents[moduleName] = moduleComponent;
           modulesToUse.add(moduleComponent);
@@ -433,8 +440,8 @@
     Stopwatch stopwatch = new Stopwatch()..start();
     Component component = await compiler.computeDelta(
         entryPoints: entries,
-        fullComponent:
-            brandNewWorld ? false : (noFullComponent ? false : true));
+        fullComponent: brandNewWorld ? false : (noFullComponent ? false : true),
+        simulateTransformer: world["simulateTransformer"]);
     if (outlineOnly) {
       for (Library lib in component.libraries) {
         for (Class c in lib.classes) {
@@ -459,6 +466,24 @@
 
     checkExpectedContent(world, component);
 
+    if (!noFullComponent) {
+      Set<Library> allLibraries = new Set<Library>();
+      for (Library lib in component.libraries) {
+        computeAllReachableLibrariesFor(lib, allLibraries);
+      }
+      if (allLibraries.length != component.libraries.length) {
+        Expect.fail("Expected for the reachable stuff to be equal to "
+            "${component.libraries} but it was $allLibraries");
+      }
+      Set<Library> tooMany = allLibraries.toSet()
+        ..removeAll(component.libraries);
+      if (tooMany.isNotEmpty) {
+        Expect.fail("Expected for the reachable stuff to be equal to "
+            "${component.libraries} but these were there too: $tooMany "
+            "(and others were missing)");
+      }
+    }
+
     newestWholeComponentData = util.postProcess(component);
     newestWholeComponent = component;
     print("*****\n\ncomponent:\n"
@@ -542,7 +567,9 @@
       gotWarning = false;
       formattedWarnings.clear();
       Component component2 = await compiler.computeDelta(
-          entryPoints: entries, fullComponent: true);
+          entryPoints: entries,
+          fullComponent: true,
+          simulateTransformer: world["simulateTransformer"]);
       performErrorAndWarningCheck(
           world, gotError, formattedErrors, gotWarning, formattedWarnings);
       List<int> thisWholeComponent = util.postProcess(component2);
@@ -573,6 +600,29 @@
             "now had ${formattedWarnings}.");
       }
     }
+
+    if (world["expressionCompilation"] != null) {
+      Uri uri = base.resolve(world["expressionCompilation"]["uri"]);
+      String expression = world["expressionCompilation"]["expression"];
+      await compiler.compileExpression(expression, {}, [], "debugExpr", uri);
+    }
+  }
+}
+
+void computeAllReachableLibrariesFor(Library lib, Set<Library> allLibraries) {
+  Set<Library> libraries = new Set<Library>();
+  List<Library> workList = <Library>[];
+  allLibraries.add(lib);
+  libraries.add(lib);
+  workList.add(lib);
+  while (workList.isNotEmpty) {
+    Library library = workList.removeLast();
+    for (LibraryDependency dependency in library.dependencies) {
+      if (libraries.add(dependency.targetLibrary)) {
+        workList.add(dependency.targetLibrary);
+        allLibraries.add(dependency.targetLibrary);
+      }
+    }
   }
 }
 
@@ -858,7 +908,9 @@
 
   @override
   Future<Component> computeDelta(
-      {List<Uri> entryPoints, bool fullComponent = false}) async {
+      {List<Uri> entryPoints,
+      bool fullComponent = false,
+      bool simulateTransformer}) async {
     Component result = await super
         .computeDelta(entryPoints: entryPoints, fullComponent: fullComponent);
 
@@ -869,6 +921,39 @@
       throw "Loaders builder should contain the sdk, "
           "but didn't even contain dart:core.";
     }
+
+    if (simulateTransformer == true) {
+      doSimulateTransformer(result);
+    }
     return result;
   }
 }
+
+void doSimulateTransformer(Component c) {
+  for (Library lib in c.libraries) {
+    if (lib.fields
+        .where((f) => f.name.name == "lalala_SimulateTransformer")
+        .toList()
+        .isNotEmpty) continue;
+    Name fieldName = new Name("lalala_SimulateTransformer");
+    Field field = new Field(fieldName,
+        isFinal: true,
+        reference: lib.reference.canonicalName
+            ?.getChildFromFieldWithName(fieldName)
+            ?.reference);
+    lib.addMember(field);
+    for (Class c in lib.classes) {
+      if (c.fields
+          .where((f) => f.name.name == "lalala_SimulateTransformer")
+          .toList()
+          .isNotEmpty) continue;
+      fieldName = new Name("lalala_SimulateTransformer");
+      field = new Field(fieldName,
+          isFinal: true,
+          reference: c.reference.canonicalName
+              ?.getChildFromFieldWithName(fieldName)
+              ?.reference);
+      c.addMember(field);
+    }
+  }
+}
diff --git a/pkg/front_end/test/incremental_load_from_invalid_dill_test.dart b/pkg/front_end/test/incremental_load_from_invalid_dill_test.dart
index 9dc2941..0d9a84e 100644
--- a/pkg/front_end/test/incremental_load_from_invalid_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_invalid_dill_test.dart
@@ -40,7 +40,7 @@
 
 import 'package:front_end/src/fasta/severity.dart' show Severity;
 
-import 'package:kernel/kernel.dart' show Component;
+import 'package:kernel/kernel.dart' show Component, Library;
 
 import 'incremental_load_from_dill_test.dart' show getOptions;
 
@@ -56,24 +56,26 @@
   Uri sdkSummary;
   Uri initializeFrom;
   Uri helperFile;
+  Uri helper2File;
   Uri entryPoint;
+  Uri entryPointImportDartFoo;
   Uri platformUri;
   List<int> sdkSummaryData;
   List<DiagnosticMessage> errorMessages;
   List<DiagnosticMessage> warningMessages;
   MemoryFileSystem fs;
   CompilerOptions options;
+  IncrementalCompiler compiler;
 
-  compileExpectInitializeFailAndSpecificWarning(
+  void compileExpectInitializeFailAndSpecificWarning(
       Code expectedWarningCode, bool writeFileOnCrashReport) async {
     errorMessages.clear();
     warningMessages.clear();
     options.writeFileOnCrashReport = writeFileOnCrashReport;
-    DeleteTempFilesIncrementalCompiler compiler =
-        new DeleteTempFilesIncrementalCompiler(
-            new CompilerContext(
-                new ProcessedOptions(options: options, inputs: [entryPoint])),
-            initializeFrom);
+    compiler = new DeleteTempFilesIncrementalCompiler(
+        new CompilerContext(
+            new ProcessedOptions(options: options, inputs: [entryPoint])),
+        initializeFrom);
     await compiler.computeDelta();
     if (compiler.initializedFromDill) {
       Expect.fail("Expected to not be able to initialized from dill, but did.");
@@ -91,13 +93,40 @@
     }
   }
 
+  Future<Component> compileExpectOk(
+      bool initializedFromDill, Uri compileThis) async {
+    errorMessages.clear();
+    warningMessages.clear();
+    options.writeFileOnCrashReport = false;
+    compiler = new DeleteTempFilesIncrementalCompiler(
+        new CompilerContext(
+            new ProcessedOptions(options: options, inputs: [compileThis])),
+        initializeFrom);
+    Component component = await compiler.computeDelta();
+
+    if (compiler.initializedFromDill != initializedFromDill) {
+      Expect.fail("Expected initializedFromDill to be $initializedFromDill "
+          "but was ${compiler.initializedFromDill}");
+    }
+    if (errorMessages.isNotEmpty) {
+      Expect.fail("Got unexpected errors: " + joinMessages(errorMessages));
+    }
+    if (warningMessages.isNotEmpty) {
+      Expect.fail("Got unexpected warnings: " + joinMessages(warningMessages));
+    }
+
+    return component;
+  }
+
   initialize() async {
     sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
     base = Uri.parse("org-dartlang-test:///");
     sdkSummary = base.resolve("vm_platform.dill");
     initializeFrom = base.resolve("initializeFrom.dill");
     helperFile = base.resolve("helper.dart");
+    helper2File = base.resolve("helper2.dart");
     entryPoint = base.resolve("small.dart");
+    entryPointImportDartFoo = base.resolve("small_foo.dart");
     platformUri = sdkRoot.resolve("vm_platform_strong.dill");
     sdkSummaryData = await new File.fromUri(platformUri).readAsBytes();
     errorMessages = <DiagnosticMessage>[];
@@ -108,6 +137,7 @@
     options.fileSystem = fs;
     options.sdkRoot = null;
     options.sdkSummary = sdkSummary;
+    options.omitPlatform = true;
     options.onDiagnostic = (DiagnosticMessage message) {
       if (message.severity == Severity.error) {
         errorMessages.add(message);
@@ -122,16 +152,27 @@
     print("hello from foo");
 }
 """);
+    fs.entityForUri(helper2File).writeAsStringSync("""
+foo2() {
+    print("hello from foo2");
+}
+""");
     fs.entityForUri(entryPoint).writeAsStringSync("""
 import "helper.dart" as helper;
 main() {
     helper.foo();
 }
 """);
+    fs.entityForUri(entryPointImportDartFoo).writeAsStringSync("""
+import "dart:foo" as helper;
+main() {
+    helper.foo2();
+}
+""");
   }
 
   Future<Null> test() async {
-    IncrementalCompiler compiler = new IncrementalCompiler(
+    compiler = new IncrementalCompiler(
         new CompilerContext(
             new ProcessedOptions(options: options, inputs: [entryPoint])),
         initializeFrom);
@@ -140,23 +181,32 @@
     List<int> dataGood = serializeComponent(componentGood);
     fs.entityForUri(initializeFrom).writeAsBytesSync(dataGood);
 
-    // Initialize from good dill file should be ok.
+    // Create fake "dart:foo" library.
+    options.omitPlatform = false;
     compiler = new IncrementalCompiler(
         new CompilerContext(
-            new ProcessedOptions(options: options, inputs: [entryPoint])),
+            new ProcessedOptions(options: options, inputs: [helper2File])),
         initializeFrom);
-    compiler.invalidate(entryPoint);
-    Component component = await compiler.computeDelta();
-    if (!compiler.initializedFromDill) {
-      Expect.fail(
-          "Expected to have sucessfully initialized from dill, but didn't.");
+    Component componentHelper = await compiler.computeDelta();
+    Library helper2Lib = componentHelper.libraries
+        .firstWhere((lib) => lib.importUri == helper2File);
+    helper2Lib.importUri = new Uri(scheme: "dart", path: "foo");
+    List<int> sdkWithDartFoo = serializeComponent(componentHelper);
+    options.omitPlatform = true;
+
+    // Compile with our fake sdk with dart:foo should be ok.
+    List<int> orgSdkBytes = await fs.entityForUri(sdkSummary).readAsBytes();
+    fs.entityForUri(sdkSummary).writeAsBytesSync(sdkWithDartFoo);
+    Component component = await compileExpectOk(true, entryPointImportDartFoo);
+    fs.entityForUri(sdkSummary).writeAsBytesSync(orgSdkBytes);
+    if (component.libraries.length != 1) {
+      Expect.fail("Expected 1 library, got ${component.libraries.length}: "
+          "${component.libraries}");
     }
-    if (errorMessages.isNotEmpty) {
-      Expect.fail("Got unexpected errors: " + joinMessages(errorMessages));
-    }
-    if (warningMessages.isNotEmpty) {
-      Expect.fail("Got unexpected warnings: " + joinMessages(warningMessages));
-    }
+    List<int> dataLinkedToSdkWithFoo = serializeComponent(component);
+
+    // Initialize from good dill file should be ok.
+    await compileExpectOk(true, entryPoint);
 
     // Create a partial dill file.
     compiler.invalidate(entryPoint);
@@ -181,6 +231,11 @@
         codeInitializeFromDillUnknownProblem, true);
     await compileExpectInitializeFailAndSpecificWarning(
         codeInitializeFromDillUnknownProblemNoDump, false);
+
+    // Create a dill with a reference to a non-existing sdk thing:
+    // Should be ok (for now), but we shouldn't actually initialize from dill.
+    fs.entityForUri(initializeFrom).writeAsBytesSync(dataLinkedToSdkWithFoo);
+    await compileExpectOk(false, entryPoint);
   }
 }
 
diff --git a/pkg/front_end/test/scanner_fasta_test.dart b/pkg/front_end/test/scanner_fasta_test.dart
index 4345dd7..210e851 100644
--- a/pkg/front_end/test/scanner_fasta_test.dart
+++ b/pkg/front_end/test/scanner_fasta_test.dart
@@ -51,6 +51,29 @@
 
 @reflectiveTest
 class ScannerTest_Fasta_UTF8 extends ScannerTest_Fasta {
+  @override
+  Token scanWithListener(String source, ErrorListener listener,
+      {ScannerConfiguration configuration}) {
+    var bytes = utf8.encode(source).toList()..add(0);
+    var result =
+        scan(bytes, configuration: configuration, includeComments: true);
+    var token = result.tokens;
+
+    // Translate error tokens
+    if (result.hasErrors) {
+      while (token is ErrorToken) {
+        translateErrorToken(token,
+            (ScannerErrorCode errorCode, int offset, List<Object> arguments) {
+          listener.errors.add(new TestError(offset, errorCode, arguments));
+        });
+        token = token.next;
+      }
+    }
+
+    new Token.eof(-1)..setNext(token);
+    return token;
+  }
+
   test_invalid_utf8() {
     printBytes(List<int> bytes) {
       var hex = bytes.map((b) => '0x${b.toRadixString(16).toUpperCase()}');
@@ -86,8 +109,9 @@
 class ScannerTest_Fasta extends ScannerTestBase {
   @override
   Token scanWithListener(String source, ErrorListener listener,
-      {bool lazyAssignmentOperators: false}) {
-    var result = scanString(source, includeComments: true);
+      {ScannerConfiguration configuration}) {
+    var result =
+        scanString(source, configuration: configuration, includeComments: true);
     var token = result.tokens;
 
     // Translate error tokens
@@ -717,15 +741,26 @@
   ScannerResult scanSource(source, {includeComments: true}) {
     List<int> encoded = utf8.encode(source).toList(growable: true);
     encoded.add(0); // Ensure 0 terminted bytes for UTF8 scanner
-    return usedForFuzzTesting.scan(encoded, includeComments: includeComments);
+    return usedForFuzzTesting.scan(encoded,
+        includeComments: includeComments,
+        languageVersionChanged: languageVersionChanged);
   }
 }
 
 /// Scanner tests that exercise the Fasta scanner directly.
 @reflectiveTest
 class ScannerTest_Fasta_Direct extends ScannerTest_Fasta_Base {
+  LanguageVersionToken languageVersion;
+
+  void languageVersionChanged(
+      Scanner scanner, LanguageVersionToken languageVersion) {
+    this.languageVersion = languageVersion;
+  }
+
   ScannerResult scanSource(source, {includeComments: true}) =>
-      scanString(source, includeComments: includeComments);
+      scanString(source,
+          includeComments: includeComments,
+          languageVersionChanged: languageVersionChanged);
 
   @override
   Token scan(String source) {
@@ -744,6 +779,140 @@
     return first;
   }
 
+  void test_languageVersion_afterImport() {
+    var result = scanSource('''
+import 'foo.dart';
+// @dart = 2.3
+main() {}
+''');
+    expect(languageVersion, isNull);
+    expectComments(result.tokens, [], -1);
+  }
+
+  void test_languageVersion_beforeComment() {
+    var result = scanSource('''
+// some other comment
+// @dart = 2.3
+// yet another comment
+import 'foo.dart';
+main() {}
+''');
+    expect(languageVersion.major, 2);
+    expect(languageVersion.minor, 3);
+    expectComments(
+        result.tokens,
+        [
+          '// some other comment',
+          '// @dart = 2.3',
+          '// yet another comment',
+        ],
+        1);
+  }
+
+  void test_languageVersion_beforeFunction() {
+    var result = scanSource('''
+// @dart = 2.3
+main() {}
+''');
+    expect(languageVersion.major, 2);
+    expect(languageVersion.minor, 3);
+    expectComments(result.tokens, ['// @dart = 2.3'], 0);
+  }
+
+  void test_languageVersion_beforeFunction_trailingX() {
+    var result = scanSource('''
+// @dart = 2.3 x
+main() {}
+''');
+    expect(languageVersion, isNull);
+    expectComments(result.tokens, ['// @dart = 2.3 x'], -1);
+  }
+
+  void test_languageVersion_beforeFunction_noComments() {
+    var result = scanSource('''
+// @dart = 2.3
+main() {}
+''', includeComments: false);
+    expect(languageVersion.major, 2);
+    expect(languageVersion.minor, 3);
+    expectComments(result.tokens, [], -1);
+  }
+
+  void test_languageVersion_beforeImport() {
+    var result = scanSource('''
+// @dart = 2.3
+import 'foo.dart';
+main() {}
+''');
+    expect(languageVersion.major, 2);
+    expect(languageVersion.minor, 3);
+    expectComments(result.tokens, ['// @dart = 2.3'], 0);
+  }
+
+  void test_languageVersion_beforeImport_afterScript() {
+    var result = scanSource('''
+#!/bin/dart
+// @dart = 2.3
+import 'foo.dart';
+main() {}
+''');
+    expect(languageVersion.major, 2);
+    expect(languageVersion.minor, 3);
+    expectComments(result.tokens.next, ['// @dart = 2.3'], 0);
+  }
+
+  void test_languageVersion_beforeLibrary() {
+    var result = scanSource('''
+// @dart = 2.3
+library foo;
+main() {}
+''');
+    expect(languageVersion.major, 2);
+    expect(languageVersion.minor, 3);
+    expectComments(result.tokens, ['// @dart = 2.3'], 0);
+  }
+
+  void test_languageVersion_beforeLibrary_noSpaces() {
+    var result = scanSource('''
+// @dart=2.3
+library foo;
+main() {}
+''');
+    expect(languageVersion.major, 2);
+    expect(languageVersion.minor, 3);
+    expectComments(result.tokens, ['// @dart=2.3'], 0);
+  }
+
+  void test_languageVersion_incomplete_version() {
+    var result = scanSource('''
+// @dart = 2.
+library foo;
+main() {}
+''');
+    expect(languageVersion, isNull);
+    expectComments(result.tokens, ['// @dart = 2.'], -1);
+  }
+
+  void test_languageVersion_invalid_identifier() {
+    var result = scanSource('''
+// @dart = blat
+library foo;
+main() {}
+''');
+    expect(languageVersion, isNull);
+    expectComments(result.tokens, ['// @dart = blat'], -1);
+  }
+
+  void test_languageVersion_invalid_version() {
+    var result = scanSource('''
+// @dart = 2.x
+library foo;
+main() {}
+''');
+    expect(languageVersion, isNull);
+    expectComments(result.tokens, ['// @dart = 2.x'], -1);
+  }
+
   void test_linestarts() {
     var result = scanSource("var\r\ni\n=\n1;\n");
     var token = result.tokens;
@@ -791,4 +960,33 @@
       token = token.next;
     }
   }
+
+  void expectComments(
+      Token token, List<String> expectedComments, int versionIndex) {
+    int index = 0;
+    token = token.precedingComments;
+    while (token != null) {
+      if (index == versionIndex) {
+        if (token is! LanguageVersionToken) {
+          fail('Expected version comment at index $index');
+        }
+      } else {
+        if (token is LanguageVersionToken) {
+          fail('Did not expect version comment at index $index');
+        }
+      }
+      if (index >= expectedComments.length) {
+        fail('Unexpected comment at index $index');
+      }
+      if (token is CommentToken) {
+        expect(token.lexeme, expectedComments[index],
+            reason: 'comment at $index');
+      } else {
+        fail('Expected comment token at index $index');
+      }
+      ++index;
+      token = token.next;
+    }
+    expect(index, expectedComments.length, reason: 'unexpected comments');
+  }
 }
diff --git a/pkg/front_end/test/scanner_replacement_test.dart b/pkg/front_end/test/scanner_replacement_test.dart
index ea881a8..b0a979a 100644
--- a/pkg/front_end/test/scanner_replacement_test.dart
+++ b/pkg/front_end/test/scanner_replacement_test.dart
@@ -2,10 +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.
 
-import 'dart:convert' show utf8;
-
-import 'package:front_end/src/fasta/scanner/recover.dart'
-    show defaultRecoveryStrategy;
 import 'package:front_end/src/fasta/scanner.dart' as fasta;
 import 'package:front_end/src/fasta/scanner/token.dart' as fasta;
 import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta;
@@ -33,28 +29,17 @@
 class ScannerTest_Replacement extends ScannerTestBase {
   @override
   analyzer.Token scanWithListener(String source, ErrorListener listener,
-      {bool lazyAssignmentOperators: false}) {
+      {fasta.ScannerConfiguration configuration}) {
     // Process the source similar to
     // pkg/analyzer/lib/src/dart/scanner/scanner.dart
     // to simulate replacing the analyzer scanner
 
     fasta.ScannerResult result = fasta.scanString(source,
-        includeComments: true,
-        scanLazyAssignmentOperators: lazyAssignmentOperators,
-        recover: ((List<int> bytes, fasta.Token tokens, List<int> lineStarts) {
-      // perform recovery as a separate step
-      // so that the token stream can be validated before and after recovery
-      return tokens;
-    }));
+        configuration: configuration, includeComments: true);
 
     fasta.Token tokens = result.tokens;
-    assertValidTokenStream(tokens);
+    assertValidTokenStream(tokens, errorsFirst: true);
     assertValidBeginTokens(tokens);
-    if (result.hasErrors) {
-      List<int> bytes = utf8.encode(source);
-      tokens = defaultRecoveryStrategy(bytes, tokens, result.lineStarts);
-      assertValidTokenStream(tokens, errorsFirst: true);
-    }
 
     // fasta pretends there is an additional line at EOF
     result.lineStarts.removeLast();
@@ -200,10 +185,9 @@
     ]);
   }
 
-  analyzer.Token _scan(String source, {bool lazyAssignmentOperators: false}) {
+  analyzer.Token _scan(String source) {
     ErrorListener listener = new ErrorListener();
-    analyzer.Token token = scanWithListener(source, listener,
-        lazyAssignmentOperators: lazyAssignmentOperators);
+    analyzer.Token token = scanWithListener(source, listener);
     listener.assertNoErrors();
     return token;
   }
@@ -253,7 +237,7 @@
   /// that is in the stream.
   void assertValidBeginTokens(fasta.Token firstToken) {
     var openerStack = <analyzer.BeginToken>[];
-    analyzer.BeginToken lastClosedGroup;
+    var errorStack = <fasta.ErrorToken>[];
     fasta.Token token = firstToken;
     while (!token.isEof) {
       if (token is analyzer.BeginToken) {
@@ -261,17 +245,17 @@
           expect(token.endGroup, isNotNull, reason: token.lexeme);
         if (token.endGroup != null) openerStack.add(token);
       } else if (openerStack.isNotEmpty && openerStack.last.endGroup == token) {
-        lastClosedGroup = openerStack.removeLast();
-        expect(token.isSynthetic, token.next is fasta.UnmatchedToken,
-            reason: 'Expect synthetic closer then error token, '
-                'but found "$token" followed by "${token.next}"');
+        analyzer.BeginToken beginToken = openerStack.removeLast();
+        if (token.isSynthetic) {
+          fasta.ErrorToken errorToken = errorStack.removeAt(0);
+          expect(errorToken.begin, beginToken);
+        }
       } else if (token is fasta.UnmatchedToken) {
-        expect(lastClosedGroup?.endGroup?.next, same(token),
-            reason: 'Unexpected error token for group: $lastClosedGroup');
-        expect(token.begin, lastClosedGroup);
+        errorStack.add(token);
       }
       token = token.next;
     }
     expect(openerStack, isEmpty, reason: 'Missing closers');
+    expect(errorStack, isEmpty, reason: 'Extra error tokens');
   }
 }
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
index 3a0bf75..932d67a 100644
--- a/pkg/front_end/test/scanner_test.dart
+++ b/pkg/front_end/test/scanner_test.dart
@@ -4,7 +4,7 @@
 
 import 'package:front_end/src/base/errors.dart';
 import 'package:front_end/src/fasta/scanner/abstract_scanner.dart'
-    show AbstractScanner;
+    show AbstractScanner, ScannerConfiguration;
 import 'package:front_end/src/scanner/errors.dart';
 import 'package:front_end/src/scanner/reader.dart';
 import 'package:front_end/src/scanner/token.dart';
@@ -80,7 +80,7 @@
 
 abstract class ScannerTestBase {
   Token scanWithListener(String source, ErrorListener listener,
-      {bool lazyAssignmentOperators: false});
+      {ScannerConfiguration configuration});
 
   void test_ampersand() {
     _assertToken(TokenType.AMPERSAND, "&");
@@ -92,8 +92,7 @@
 
   void test_ampersand_ampersand_eq() {
     if (AbstractScanner.LAZY_ASSIGNMENT_ENABLED) {
-      _assertToken(TokenType.AMPERSAND_AMPERSAND_EQ, "&&=",
-          lazyAssignmentOperators: true);
+      _assertToken(TokenType.AMPERSAND_AMPERSAND_EQ, "&&=");
     }
   }
 
@@ -152,7 +151,7 @@
 
   void test_bar_bar_eq() {
     if (AbstractScanner.LAZY_ASSIGNMENT_ENABLED) {
-      _assertToken(TokenType.BAR_BAR_EQ, "||=", lazyAssignmentOperators: true);
+      _assertToken(TokenType.BAR_BAR_EQ, "||=");
     }
   }
 
@@ -444,6 +443,16 @@
     _assertKeywordToken("extends");
   }
 
+  void test_keyword_extension() {
+    _assertKeywordToken("extension",
+        configuration: ScannerConfiguration(enableExtensionMethods: true));
+  }
+
+  void test_keyword_extension_old() {
+    _assertNotKeywordToken("extension",
+        configuration: ScannerConfiguration(enableExtensionMethods: false));
+  }
+
   void test_keyword_factory() {
     _assertKeywordToken("factory");
   }
@@ -496,6 +505,16 @@
     _assertKeywordToken("is");
   }
 
+  void test_keyword_late() {
+    _assertKeywordToken("late",
+        configuration: ScannerConfiguration(enableNonNullable: true));
+  }
+
+  void test_keyword_late_old() {
+    _assertNotKeywordToken("late",
+        configuration: ScannerConfiguration(enableNonNullable: false));
+  }
+
   void test_keyword_library() {
     _assertKeywordToken("library");
   }
@@ -536,6 +555,16 @@
     _assertKeywordToken("patch");
   }
 
+  void test_keyword_required() {
+    _assertKeywordToken("required",
+        configuration: ScannerConfiguration(enableNonNullable: true));
+  }
+
+  void test_keyword_required_disabled() {
+    _assertNotKeywordToken("required",
+        configuration: ScannerConfiguration(enableNonNullable: false));
+  }
+
   void test_keyword_rethrow() {
     _assertKeywordToken("rethrow");
   }
@@ -1300,8 +1329,9 @@
    * Assert that when scanned the given [source] contains a single keyword token
    * with the same lexeme as the original source.
    */
-  void _assertKeywordToken(String source) {
-    Token token = _scan(source);
+  void _assertKeywordToken(String source,
+      {ScannerConfiguration configuration}) {
+    Token token = _scan(source, configuration: configuration);
     expect(token, isNotNull);
     expect(token.type.isKeyword, true);
     expect(token.offset, 0);
@@ -1310,7 +1340,7 @@
     Object value = token.value();
     expect(value is Keyword, isTrue);
     expect((value as Keyword).lexeme, source);
-    token = _scan(" $source ");
+    token = _scan(" $source ", configuration: configuration);
     expect(token, isNotNull);
     expect(token.type.isKeyword, true);
     expect(token.offset, 1);
@@ -1323,14 +1353,33 @@
   }
 
   /**
+   * Assert that when scanned the given [source] contains a single identifier token
+   * with the same lexeme as the original source.
+   */
+  void _assertNotKeywordToken(String source,
+      {ScannerConfiguration configuration}) {
+    Token token = _scan(source, configuration: configuration);
+    expect(token, isNotNull);
+    expect(token.type.isKeyword, false);
+    expect(token.offset, 0);
+    expect(token.length, source.length);
+    expect(token.lexeme, source);
+    token = _scan(" $source ", configuration: configuration);
+    expect(token, isNotNull);
+    expect(token.type.isKeyword, false);
+    expect(token.offset, 1);
+    expect(token.length, source.length);
+    expect(token.lexeme, source);
+    expect(token.next.type, TokenType.EOF);
+  }
+
+  /**
    * Assert that the token scanned from the given [source] has the
    * [expectedType].
    */
-  Token _assertToken(TokenType expectedType, String source,
-      {bool lazyAssignmentOperators: false}) {
+  Token _assertToken(TokenType expectedType, String source) {
     // Fasta generates errors for unmatched '{', '[', etc
-    Token originalToken = _scan(source,
-        lazyAssignmentOperators: lazyAssignmentOperators, ignoreErrors: true);
+    Token originalToken = _scan(source, ignoreErrors: true);
     expect(originalToken, isNotNull);
     expect(originalToken.type, expectedType);
     expect(originalToken.offset, 0);
@@ -1342,8 +1391,7 @@
       return originalToken;
     } else if (expectedType == TokenType.SINGLE_LINE_COMMENT) {
       // Adding space to an end-of-line comment changes the comment.
-      Token tokenWithSpaces = _scan(" $source",
-          lazyAssignmentOperators: lazyAssignmentOperators, ignoreErrors: true);
+      Token tokenWithSpaces = _scan(" $source", ignoreErrors: true);
       expect(tokenWithSpaces, isNotNull);
       expect(tokenWithSpaces.type, expectedType);
       expect(tokenWithSpaces.offset, 1);
@@ -1352,23 +1400,20 @@
       return originalToken;
     } else if (expectedType == TokenType.INT ||
         expectedType == TokenType.DOUBLE) {
-      Token tokenWithLowerD = _scan("${source}d",
-          lazyAssignmentOperators: lazyAssignmentOperators, ignoreErrors: true);
+      Token tokenWithLowerD = _scan("${source}d", ignoreErrors: true);
       expect(tokenWithLowerD, isNotNull);
       expect(tokenWithLowerD.type, expectedType);
       expect(tokenWithLowerD.offset, 0);
       expect(tokenWithLowerD.length, source.length);
       expect(tokenWithLowerD.lexeme, source);
-      Token tokenWithUpperD = _scan("${source}D",
-          lazyAssignmentOperators: lazyAssignmentOperators, ignoreErrors: true);
+      Token tokenWithUpperD = _scan("${source}D", ignoreErrors: true);
       expect(tokenWithUpperD, isNotNull);
       expect(tokenWithUpperD.type, expectedType);
       expect(tokenWithUpperD.offset, 0);
       expect(tokenWithUpperD.length, source.length);
       expect(tokenWithUpperD.lexeme, source);
     }
-    Token tokenWithSpaces = _scan(" $source ",
-        lazyAssignmentOperators: lazyAssignmentOperators, ignoreErrors: true);
+    Token tokenWithSpaces = _scan(" $source ", ignoreErrors: true);
     expect(tokenWithSpaces, isNotNull);
     expect(tokenWithSpaces.type, expectedType);
     expect(tokenWithSpaces.offset, 1);
@@ -1408,10 +1453,10 @@
   }
 
   Token _scan(String source,
-      {bool lazyAssignmentOperators: false, bool ignoreErrors: false}) {
+      {ScannerConfiguration configuration, bool ignoreErrors: false}) {
     ErrorListener listener = new ErrorListener();
-    Token token = scanWithListener(source, listener,
-        lazyAssignmentOperators: lazyAssignmentOperators);
+    Token token =
+        scanWithListener(source, listener, configuration: configuration);
     if (!ignoreErrors) {
       listener.assertNoErrors();
     }
diff --git a/pkg/front_end/test/src/base/processed_options_test.dart b/pkg/front_end/test/src/base/processed_options_test.dart
index 605b5ac..0abc4cb 100644
--- a/pkg/front_end/test/src/base/processed_options_test.dart
+++ b/pkg/front_end/test/src/base/processed_options_test.dart
@@ -22,6 +22,7 @@
     defineReflectiveSuite(() {
       defineReflectiveTests(ProcessedOptionsTest);
     });
+    return Future<void>.value();
   });
 }
 
diff --git a/pkg/front_end/test/token_test.dart b/pkg/front_end/test/token_test.dart
index 686c789..fa62c06 100644
--- a/pkg/front_end/test/token_test.dart
+++ b/pkg/front_end/test/token_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:front_end/src/fasta/scanner.dart' show ScannerConfiguration;
 import 'package:front_end/src/fasta/scanner/string_scanner.dart';
 import 'package:front_end/src/scanner/token.dart';
 import 'package:test/test.dart';
@@ -90,6 +91,7 @@
       Keyword.DEFERRED,
       Keyword.DYNAMIC,
       Keyword.EXPORT,
+      Keyword.EXTENSION,
       Keyword.EXTERNAL,
       Keyword.FACTORY,
       Keyword.GET,
@@ -100,6 +102,7 @@
       Keyword.MIXIN,
       Keyword.OPERATOR,
       Keyword.PART,
+      Keyword.REQUIRED,
       Keyword.SET,
       Keyword.STATIC,
       Keyword.TYPEDEF,
@@ -117,12 +120,16 @@
       Keyword.COVARIANT,
       Keyword.EXTERNAL,
       Keyword.FINAL,
+      Keyword.LATE,
+      Keyword.REQUIRED,
       Keyword.STATIC,
       Keyword.VAR,
     ]);
     for (Keyword keyword in Keyword.values) {
       var isModifier = modifierKeywords.contains(keyword);
-      var scanner = new StringScanner(keyword.lexeme, includeComments: true);
+      var scanner = new StringScanner(keyword.lexeme,
+          configuration: ScannerConfiguration.nonNullable,
+          includeComments: true);
       Token token = scanner.tokenize();
       expect(token.isModifier, isModifier, reason: keyword.name);
       if (isModifier) {
@@ -136,6 +143,7 @@
       Keyword.CLASS,
       Keyword.ENUM,
       Keyword.EXPORT,
+      //Keyword.EXTENSION, <-- when "extension methods" is enabled by default
       Keyword.IMPORT,
       Keyword.LIBRARY,
       Keyword.MIXIN,
@@ -153,6 +161,14 @@
     }
   }
 
+  void test_noPseudoModifiers() {
+    for (Keyword keyword in Keyword.values) {
+      if (keyword.isModifier) {
+        expect(keyword.isPseudo, isFalse, reason: keyword.lexeme);
+      }
+    }
+  }
+
   void test_pseudo_keywords() {
     var pseudoKeywords = new Set<Keyword>.from([
       Keyword.ASYNC,
diff --git a/pkg/front_end/testcases/DeltaBlue.dart.outline.expect b/pkg/front_end/testcases/DeltaBlue.dart.outline.expect
index 65edda0..85cc345 100644
--- a/pkg/front_end/testcases/DeltaBlue.dart.outline.expect
+++ b/pkg/front_end/testcases/DeltaBlue.dart.outline.expect
@@ -181,16 +181,16 @@
   method execute() → void
     ;
 }
-static const field dynamic REQUIRED;
-static const field dynamic STRONG_PREFERRED;
-static const field dynamic PREFERRED;
-static const field dynamic STRONG_DEFAULT;
-static const field dynamic NORMAL;
-static const field dynamic WEAK_DEFAULT;
-static const field dynamic WEAKEST;
-static const field core::int NONE;
-static const field core::int FORWARD;
-static const field core::int BACKWARD;
+static const field dynamic REQUIRED = const self::Strength::•(0, "required");
+static const field dynamic STRONG_PREFERRED = const self::Strength::•(1, "strongPreferred");
+static const field dynamic PREFERRED = const self::Strength::•(2, "preferred");
+static const field dynamic STRONG_DEFAULT = const self::Strength::•(3, "strongDefault");
+static const field dynamic NORMAL = const self::Strength::•(4, "normal");
+static const field dynamic WEAK_DEFAULT = const self::Strength::•(5, "weakDefault");
+static const field dynamic WEAKEST = const self::Strength::•(6, "weakest");
+static const field core::int NONE = 1;
+static const field core::int FORWARD = 2;
+static const field core::int BACKWARD = 0;
 static field self::Planner planner;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect b/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
index 319403e..c705421 100644
--- a/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
+++ b/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
@@ -11,7 +11,9 @@
   final field core::int index;
   final field core::String _name;
   static const field core::List<self::Foo> values = const <self::Foo>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
+  @self::hest
   static const field self::Foo bar = const self::Foo::•(0, "Foo.bar");
+  @self::Fisk::fisk<dynamic>(self::hest)
   static const field self::Foo baz = const self::Foo::•(1, "Foo.baz");
   static const field self::Foo cafebabe = const self::Foo::•(2, "Foo.cafebabe");
   const constructor •(core::int index, core::String _name) → self::Foo
@@ -20,6 +22,6 @@
   method toString() → core::String
     return this.{=self::Foo::_name};
 }
-static const field core::int hest;
+static const field core::int hest = 42;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/annotation_top.dart.outline.expect b/pkg/front_end/testcases/annotation_top.dart.outline.expect
index 6839b80..11b2fda 100644
--- a/pkg/front_end/testcases/annotation_top.dart.outline.expect
+++ b/pkg/front_end/testcases/annotation_top.dart.outline.expect
@@ -1,3 +1,5 @@
+@test::a
+@test::A::•(1)
 library test;
 import self as self;
 import "dart:core" as core;
@@ -8,12 +10,20 @@
   const constructor •(core::int value) → self::A
     ;
 }
+@self::a
+@self::A::•(2)
 class C extends core::Object {
   synthetic constructor •() → self::C
     ;
 }
-static const field core::Object a;
+static const field core::Object a = const core::Object::•();
+@self::a
+@self::A::•(3)
 static field core::int f1;
+@self::a
+@self::A::•(3)
 static field core::int f2;
+@self::a
+@self::A::•(4)
 static method main() → void
   ;
diff --git a/pkg/front_end/testcases/annotation_typedef_formals.dart.outline.expect b/pkg/front_end/testcases/annotation_typedef_formals.dart.outline.expect
index 945da25..1cdad69 100644
--- a/pkg/front_end/testcases/annotation_typedef_formals.dart.outline.expect
+++ b/pkg/front_end/testcases/annotation_typedef_formals.dart.outline.expect
@@ -4,8 +4,8 @@
 
 typedef F = (core::int, core::num, {w: core::Object, z: core::String}) → void;
 typedef G = (core::int, core::num, [core::String, core::Object]) → void;
-static const field core::int foo;
-static const field core::int bar;
-static const field core::int baz;
+static const field core::int foo = 21;
+static const field core::int bar = 42;
+static const field core::int baz = 84;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.outline.expect b/pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.outline.expect
index e9a1864..8aca7b0 100644
--- a/pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.outline.expect
+++ b/pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.outline.expect
@@ -3,6 +3,6 @@
 import "dart:core" as core;
 
 typedef F = (core::int) → core::int;
-static const field core::int app;
+static const field core::int app = 0;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/annotation_variable_declaration.dart.outline.expect b/pkg/front_end/testcases/annotation_variable_declaration.dart.outline.expect
index 3eb241b..faa7175 100644
--- a/pkg/front_end/testcases/annotation_variable_declaration.dart.outline.expect
+++ b/pkg/front_end/testcases/annotation_variable_declaration.dart.outline.expect
@@ -19,6 +19,6 @@
   method hest({dynamic named}) → dynamic
     ;
 }
-static const field core::int foo;
+static const field core::int foo = 42;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart
new file mode 100644
index 0000000..3816961
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2019, 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.
+
+typedef ContravariantUse<T> = Function(T);
+
+typedef InvariantUse<T> = T Function(T);
+
+class Empty {}
+
+class A<T> {}
+
+class B<T> extends A<Function(T)> {}
+
+class Bc<T> extends A<ContravariantUse<T>> {}
+
+class Bi<T> extends A<InvariantUse<T>> {}
+
+class C<T> implements A<Function(T)> {}
+
+class Cc<T> implements A<ContravariantUse<T>> {}
+
+class Ci<T> implements A<InvariantUse<T>> {}
+
+class D<T> = Object with A<Function(T)>;
+
+class Dc<T> = Object with A<ContravariantUse<T>>;
+
+class Di<T> = Object with A<InvariantUse<T>>;
+
+class E<T> = A<Function(T)> with Empty;
+
+class Ec<T> = A<ContravariantUse<T>> with Empty;
+
+class Ei<T> = A<InvariantUse<T>> with Empty;
+
+class F<T> extends Object with A<Function(T)> {}
+
+class Fc<T> extends Object with A<ContravariantUse<T>> {}
+
+class Fi<T> extends Object with A<InvariantUse<T>> {}
+
+class G<T> extends A<Function(T)> with Empty {}
+
+class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+
+class Gi<T> extends A<InvariantUse<T>> with Empty {}
+
+class Hff<T> extends A<Function(Function(T))> {}
+
+class Hfc<T> extends A<Function(ContravariantUse<T>)> {}
+
+class Hcf<T> extends A<ContravariantUse<Function(T)>> {}
+
+class Hcc<T> extends A<ContravariantUse<ContravariantUse<T>>> {}
+
+class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+
+class Iafc<T> extends A<A<Function(ContravariantUse<T>)>> {}
+
+class Iacf<T> extends A<A<ContravariantUse<Function(T)>>> {}
+
+class Ifac<T> extends A<Function(A<ContravariantUse<T>>)> {}
+
+class Ifca<T> extends A<Function(ContravariantUse<A<T>>)> {}
+
+class Icaf<T> extends A<ContravariantUse<A<Function(T)>>> {}
+
+class Icfa<T> extends A<ContravariantUse<Function(A<T>)>> {}
+
+class Jfff<T> extends A<Function(Function(Function(T)))> {}
+
+class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+
+class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+
+class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+
+class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+
+class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+
+class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+
+class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.hierarchy.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.hierarchy.expect
new file mode 100644
index 0000000..060d1ab
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.hierarchy.expect
@@ -0,0 +1,917 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Empty:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Bc:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Bi:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+C:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Cc:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Ci:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+D:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Dc:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Di:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+E:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Ec:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Ei:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Object with A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+F:
+  superclasses:
+    Object
+      -> _F&Object&A<T>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Object with A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Fc:
+  superclasses:
+    Object
+      -> _Fc&Object&A<T>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Object with A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Fi:
+  superclasses:
+    Object
+      -> _Fi&Object&A<T>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A with Empty:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+G:
+  Longest path to Object: 3
+  superclasses:
+    A
+      -> _G&A&Empty<T>
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+A with Empty:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Gc:
+  Longest path to Object: 3
+  superclasses:
+    A
+      -> _Gc&A&Empty<T>
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+A with Empty:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Gi:
+  Longest path to Object: 3
+  superclasses:
+    A
+      -> _Gi&A&Empty<T>
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Hff:
+  superclasses:
+    Object
+      -> A<(null) -> null>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Hfc:
+  superclasses:
+    Object
+      -> A<(null) -> null>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Hcf:
+  superclasses:
+    Object
+      -> A<ContravariantUse<(null) -> null>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Hcc:
+  superclasses:
+    Object
+      -> A<ContravariantUse<ContravariantUse<T>>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Hii:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Iafc:
+  superclasses:
+    Object
+      -> A<A<(null) -> null>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Iacf:
+  superclasses:
+    Object
+      -> A<A<ContravariantUse<(null) -> null>>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Ifac:
+  superclasses:
+    Object
+      -> A<(null) -> null>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Ifca:
+  superclasses:
+    Object
+      -> A<(null) -> null>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Icaf:
+  superclasses:
+    Object
+      -> A<ContravariantUse<A<(null) -> null>>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Icfa:
+  superclasses:
+    Object
+      -> A<ContravariantUse<(null) -> null>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jfff:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jffc:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jfcf:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jfcc:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jcff:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jcfc:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jccf:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jccc:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.expect
new file mode 100644
index 0000000..74cdea4
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+  synthetic constructor •() → self::Empty
+    : super core::Object::•()
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bc<self::Bc::T>
+    : super core::Object::•()
+    ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bi<self::Bi::T>
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Cc<self::Cc::T>
+    : super core::Object::•()
+    ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ci<self::Ci::T>
+    : super core::Object::•()
+    ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::D<self::D::T>
+    : super core::Object::•()
+    ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Dc<self::Dc::T>
+    : super core::Object::•()
+    ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Di<self::Di::T>
+    : super core::Object::•()
+    ;
+}
+class E<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::E<self::E::T>
+    : super core::Object::•()
+    ;
+}
+class Ec<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ec<self::Ec::T>
+    : super core::Object::•()
+    ;
+}
+class Ei<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ei<self::Ei::T>
+    : super core::Object::•()
+    ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+  synthetic constructor •() → self::F<self::F::T>
+    : super self::_F&Object&A::•()
+    ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+  synthetic constructor •() → self::Fc<self::Fc::T>
+    : super self::_Fc&Object&A::•()
+    ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+  synthetic constructor •() → self::Fi<self::Fi::T>
+    : super self::_Fi&Object&A::•()
+    ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+  synthetic constructor •() → self::G<self::G::T>
+    : super self::_G&A&Empty::•()
+    ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+  synthetic constructor •() → self::Gc<self::Gc::T>
+    : super self::_Gc&A&Empty::•()
+    ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+  synthetic constructor •() → self::Gi<self::Gi::T>
+    : super self::_Gi&A&Empty::•()
+    ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hff<self::Hff::T>
+    : super self::A::•()
+    ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hfc<self::Hfc::T>
+    : super self::A::•()
+    ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcf<self::Hcf::T>
+    : super self::A::•()
+    ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcc<self::Hcc::T>
+    : super self::A::•()
+    ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hii<self::Hii::T>
+    : super core::Object::•()
+    ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iafc<self::Iafc::T>
+    : super self::A::•()
+    ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iacf<self::Iacf::T>
+    : super self::A::•()
+    ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Ifac<self::Ifac::T>
+    : super self::A::•()
+    ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Ifca<self::Ifca::T>
+    : super self::A::•()
+    ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Icaf<self::Icaf::T>
+    : super self::A::•()
+    ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Icfa<self::Icfa::T>
+    : super self::A::•()
+    ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfff<self::Jfff::T>
+    : super core::Object::•()
+    ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jffc<self::Jffc::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+    : super core::Object::•()
+    ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcff<self::Jcff::T>
+    : super core::Object::•()
+    ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+    : super core::Object::•()
+    ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccf<self::Jccf::T>
+    : super core::Object::•()
+    ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccc<self::Jccc::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.transformed.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.transformed.expect
new file mode 100644
index 0000000..87ac80d7
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.transformed.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+  synthetic constructor •() → self::Empty
+    : super core::Object::•()
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bc<self::Bc::T>
+    : super core::Object::•()
+    ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bi<self::Bi::T>
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Cc<self::Cc::T>
+    : super core::Object::•()
+    ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ci<self::Ci::T>
+    : super core::Object::•()
+    ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::D<self::D::T>
+    : super core::Object::•()
+    ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Dc<self::Dc::T>
+    : super core::Object::•()
+    ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Di<self::Di::T>
+    : super core::Object::•()
+    ;
+}
+class E<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::E<self::E::T>
+    : super core::Object::•()
+    ;
+}
+class Ec<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::Ec<self::Ec::T>
+    : super core::Object::•()
+    ;
+}
+class Ei<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::Ei<self::Ei::T>
+    : super core::Object::•()
+    ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+  synthetic constructor •() → self::F<self::F::T>
+    : super self::_F&Object&A::•()
+    ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+  synthetic constructor •() → self::Fc<self::Fc::T>
+    : super self::_Fc&Object&A::•()
+    ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+  synthetic constructor •() → self::Fi<self::Fi::T>
+    : super self::_Fi&Object&A::•()
+    ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+  synthetic constructor •() → self::G<self::G::T>
+    : super self::_G&A&Empty::•()
+    ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+  synthetic constructor •() → self::Gc<self::Gc::T>
+    : super self::_Gc&A&Empty::•()
+    ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+  synthetic constructor •() → self::Gi<self::Gi::T>
+    : super self::_Gi&A&Empty::•()
+    ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hff<self::Hff::T>
+    : super self::A::•()
+    ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hfc<self::Hfc::T>
+    : super self::A::•()
+    ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcf<self::Hcf::T>
+    : super self::A::•()
+    ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcc<self::Hcc::T>
+    : super self::A::•()
+    ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hii<self::Hii::T>
+    : super core::Object::•()
+    ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iafc<self::Iafc::T>
+    : super self::A::•()
+    ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iacf<self::Iacf::T>
+    : super self::A::•()
+    ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Ifac<self::Ifac::T>
+    : super self::A::•()
+    ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Ifca<self::Ifca::T>
+    : super self::A::•()
+    ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Icaf<self::Icaf::T>
+    : super self::A::•()
+    ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Icfa<self::Icfa::T>
+    : super self::A::•()
+    ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfff<self::Jfff::T>
+    : super core::Object::•()
+    ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jffc<self::Jffc::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+    : super core::Object::•()
+    ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcff<self::Jcff::T>
+    : super core::Object::•()
+    ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+    : super core::Object::•()
+    ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccf<self::Jccf::T>
+    : super core::Object::•()
+    ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccc<self::Jccc::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.outline.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.outline.expect
new file mode 100644
index 0000000..86bc0e3
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.outline.expect
@@ -0,0 +1,305 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+  synthetic constructor •() → self::Empty
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bc<self::Bc::T>
+    ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bi<self::Bi::T>
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Cc<self::Cc::T>
+    ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ci<self::Ci::T>
+    ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::D<self::D::T>
+    : super core::Object::•()
+    ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Dc<self::Dc::T>
+    : super core::Object::•()
+    ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Di<self::Di::T>
+    : super core::Object::•()
+    ;
+}
+class E<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::E<self::E::T>
+    ;
+}
+class Ec<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ec<self::Ec::T>
+    ;
+}
+class Ei<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ei<self::Ei::T>
+    ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+  synthetic constructor •() → self::F<self::F::T>
+    ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+  synthetic constructor •() → self::Fc<self::Fc::T>
+    ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+  synthetic constructor •() → self::Fi<self::Fi::T>
+    ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+    ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+  synthetic constructor •() → self::G<self::G::T>
+    ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+    ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+  synthetic constructor •() → self::Gc<self::Gc::T>
+    ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+    ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+  synthetic constructor •() → self::Gi<self::Gi::T>
+    ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hff<self::Hff::T>
+    ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hfc<self::Hfc::T>
+    ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcf<self::Hcf::T>
+    ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcc<self::Hcc::T>
+    ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hii<self::Hii::T>
+    ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iafc<self::Iafc::T>
+    ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iacf<self::Iacf::T>
+    ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Ifac<self::Ifac::T>
+    ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Ifca<self::Ifca::T>
+    ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Icaf<self::Icaf::T>
+    ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Icfa<self::Icfa::T>
+    ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfff<self::Jfff::T>
+    ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jffc<self::Jffc::T>
+    ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+    ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+    ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcff<self::Jcff::T>
+    ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+    ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccf<self::Jccf::T>
+    ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccc<self::Jccc::T>
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.expect
new file mode 100644
index 0000000..74cdea4
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+  synthetic constructor •() → self::Empty
+    : super core::Object::•()
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bc<self::Bc::T>
+    : super core::Object::•()
+    ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bi<self::Bi::T>
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Cc<self::Cc::T>
+    : super core::Object::•()
+    ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ci<self::Ci::T>
+    : super core::Object::•()
+    ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::D<self::D::T>
+    : super core::Object::•()
+    ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Dc<self::Dc::T>
+    : super core::Object::•()
+    ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Di<self::Di::T>
+    : super core::Object::•()
+    ;
+}
+class E<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::E<self::E::T>
+    : super core::Object::•()
+    ;
+}
+class Ec<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ec<self::Ec::T>
+    : super core::Object::•()
+    ;
+}
+class Ei<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ei<self::Ei::T>
+    : super core::Object::•()
+    ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+  synthetic constructor •() → self::F<self::F::T>
+    : super self::_F&Object&A::•()
+    ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+  synthetic constructor •() → self::Fc<self::Fc::T>
+    : super self::_Fc&Object&A::•()
+    ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+  synthetic constructor •() → self::Fi<self::Fi::T>
+    : super self::_Fi&Object&A::•()
+    ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+  synthetic constructor •() → self::G<self::G::T>
+    : super self::_G&A&Empty::•()
+    ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+  synthetic constructor •() → self::Gc<self::Gc::T>
+    : super self::_Gc&A&Empty::•()
+    ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+  synthetic constructor •() → self::Gi<self::Gi::T>
+    : super self::_Gi&A&Empty::•()
+    ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hff<self::Hff::T>
+    : super self::A::•()
+    ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hfc<self::Hfc::T>
+    : super self::A::•()
+    ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcf<self::Hcf::T>
+    : super self::A::•()
+    ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcc<self::Hcc::T>
+    : super self::A::•()
+    ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hii<self::Hii::T>
+    : super core::Object::•()
+    ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iafc<self::Iafc::T>
+    : super self::A::•()
+    ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iacf<self::Iacf::T>
+    : super self::A::•()
+    ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Ifac<self::Ifac::T>
+    : super self::A::•()
+    ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Ifca<self::Ifca::T>
+    : super self::A::•()
+    ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Icaf<self::Icaf::T>
+    : super self::A::•()
+    ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Icfa<self::Icfa::T>
+    : super self::A::•()
+    ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfff<self::Jfff::T>
+    : super core::Object::•()
+    ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jffc<self::Jffc::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+    : super core::Object::•()
+    ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcff<self::Jcff::T>
+    : super core::Object::•()
+    ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+    : super core::Object::•()
+    ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccf<self::Jccf::T>
+    : super core::Object::•()
+    ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccc<self::Jccc::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
new file mode 100644
index 0000000..87ac80d7
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+  synthetic constructor •() → self::Empty
+    : super core::Object::•()
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bc<self::Bc::T>
+    : super core::Object::•()
+    ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bi<self::Bi::T>
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Cc<self::Cc::T>
+    : super core::Object::•()
+    ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ci<self::Ci::T>
+    : super core::Object::•()
+    ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::D<self::D::T>
+    : super core::Object::•()
+    ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Dc<self::Dc::T>
+    : super core::Object::•()
+    ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Di<self::Di::T>
+    : super core::Object::•()
+    ;
+}
+class E<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::E<self::E::T>
+    : super core::Object::•()
+    ;
+}
+class Ec<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::Ec<self::Ec::T>
+    : super core::Object::•()
+    ;
+}
+class Ei<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::Ei<self::Ei::T>
+    : super core::Object::•()
+    ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+  synthetic constructor •() → self::F<self::F::T>
+    : super self::_F&Object&A::•()
+    ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+  synthetic constructor •() → self::Fc<self::Fc::T>
+    : super self::_Fc&Object&A::•()
+    ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+  synthetic constructor •() → self::Fi<self::Fi::T>
+    : super self::_Fi&Object&A::•()
+    ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+  synthetic constructor •() → self::G<self::G::T>
+    : super self::_G&A&Empty::•()
+    ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+  synthetic constructor •() → self::Gc<self::Gc::T>
+    : super self::_Gc&A&Empty::•()
+    ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+  synthetic constructor •() → self::Gi<self::Gi::T>
+    : super self::_Gi&A&Empty::•()
+    ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hff<self::Hff::T>
+    : super self::A::•()
+    ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hfc<self::Hfc::T>
+    : super self::A::•()
+    ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcf<self::Hcf::T>
+    : super self::A::•()
+    ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcc<self::Hcc::T>
+    : super self::A::•()
+    ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hii<self::Hii::T>
+    : super core::Object::•()
+    ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iafc<self::Iafc::T>
+    : super self::A::•()
+    ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iacf<self::Iacf::T>
+    : super self::A::•()
+    ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Ifac<self::Ifac::T>
+    : super self::A::•()
+    ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Ifca<self::Ifca::T>
+    : super self::A::•()
+    ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Icaf<self::Icaf::T>
+    : super self::A::•()
+    ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Icfa<self::Icfa::T>
+    : super self::A::•()
+    ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfff<self::Jfff::T>
+    : super core::Object::•()
+    ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jffc<self::Jffc::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+    : super core::Object::•()
+    ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcff<self::Jcff::T>
+    : super core::Object::•()
+    ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+    : super core::Object::•()
+    ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccf<self::Jccf::T>
+    : super core::Object::•()
+    ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccc<self::Jccc::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bug33099.dart.outline.expect b/pkg/front_end/testcases/bug33099.dart.outline.expect
index 42a5b20..1753eb4 100644
--- a/pkg/front_end/testcases/bug33099.dart.outline.expect
+++ b/pkg/front_end/testcases/bug33099.dart.outline.expect
@@ -12,6 +12,7 @@
 class MyTest extends core::Object {
   synthetic constructor •() → self::MyTest
     ;
+  @self::failingTest
   method foo() → void
     ;
 }
@@ -24,7 +25,7 @@
   synthetic constructor •() → self::MyTest2
     ;
 }
-static const field self::_FailingTest failingTest;
+static const field self::_FailingTest failingTest = const self::_FailingTest::•();
 static method main() → dynamic
   ;
 static method _hasFailingTestAnnotation(mir::MethodMirror method) → core::bool
diff --git a/pkg/front_end/testcases/duplicated_declarations.dart.legacy.expect b/pkg/front_end/testcases/duplicated_declarations.dart.legacy.expect
index 86ec30f..522465d 100644
--- a/pkg/front_end/testcases/duplicated_declarations.dart.legacy.expect
+++ b/pkg/front_end/testcases/duplicated_declarations.dart.legacy.expect
@@ -299,6 +299,13 @@
 // typedef Typedef = Object Function();
 //         ^^^^^^^
 //
+// pkg/front_end/testcases/duplicated_declarations.dart:65:19: Warning: 'C' isn't a type.
+// class Sub extends C {
+//                   ^
+// pkg/front_end/testcases/duplicated_declarations.dart:65:19: Context: This isn't a type.
+// class Sub extends C {
+//                   ^
+//
 // pkg/front_end/testcases/duplicated_declarations.dart:65:19: Error: 'C' isn't a type.
 // class Sub extends C {
 //                   ^
diff --git a/pkg/front_end/testcases/duplicated_declarations.dart.legacy.transformed.expect b/pkg/front_end/testcases/duplicated_declarations.dart.legacy.transformed.expect
index 86ec30f..522465d 100644
--- a/pkg/front_end/testcases/duplicated_declarations.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/duplicated_declarations.dart.legacy.transformed.expect
@@ -299,6 +299,13 @@
 // typedef Typedef = Object Function();
 //         ^^^^^^^
 //
+// pkg/front_end/testcases/duplicated_declarations.dart:65:19: Warning: 'C' isn't a type.
+// class Sub extends C {
+//                   ^
+// pkg/front_end/testcases/duplicated_declarations.dart:65:19: Context: This isn't a type.
+// class Sub extends C {
+//                   ^
+//
 // pkg/front_end/testcases/duplicated_declarations.dart:65:19: Error: 'C' isn't a type.
 // class Sub extends C {
 //                   ^
diff --git a/pkg/front_end/testcases/duplicated_declarations.dart.outline.expect b/pkg/front_end/testcases/duplicated_declarations.dart.outline.expect
index 1933ac0..24178c0 100644
--- a/pkg/front_end/testcases/duplicated_declarations.dart.outline.expect
+++ b/pkg/front_end/testcases/duplicated_declarations.dart.outline.expect
@@ -299,6 +299,13 @@
 // typedef Typedef = Object Function();
 //         ^^^^^^^
 //
+// pkg/front_end/testcases/duplicated_declarations.dart:65:19: Warning: 'C' isn't a type.
+// class Sub extends C {
+//                   ^
+// pkg/front_end/testcases/duplicated_declarations.dart:65:19: Context: This isn't a type.
+// class Sub extends C {
+//                   ^
+//
 // pkg/front_end/testcases/duplicated_declarations.dart:65:19: Error: 'C' isn't a type.
 // class Sub extends C {
 //                   ^
diff --git a/pkg/front_end/testcases/duplicated_declarations.dart.strong.expect b/pkg/front_end/testcases/duplicated_declarations.dart.strong.expect
index 6e8d2d8..a34ac18 100644
--- a/pkg/front_end/testcases/duplicated_declarations.dart.strong.expect
+++ b/pkg/front_end/testcases/duplicated_declarations.dart.strong.expect
@@ -302,6 +302,13 @@
 // pkg/front_end/testcases/duplicated_declarations.dart:65:19: Error: 'C' isn't a type.
 // class Sub extends C {
 //                   ^
+// pkg/front_end/testcases/duplicated_declarations.dart:65:19: Context: This isn't a type.
+// class Sub extends C {
+//                   ^
+//
+// pkg/front_end/testcases/duplicated_declarations.dart:65:19: Error: 'C' isn't a type.
+// class Sub extends C {
+//                   ^
 //
 // pkg/front_end/testcases/duplicated_declarations.dart:34:3: Error: Can't use 'main' because it is declared more than once.
 //   main();
diff --git a/pkg/front_end/testcases/expression/from_vm_cc_linked_hash_map.expression.yaml b/pkg/front_end/testcases/expression/from_vm_cc_linked_hash_map.expression.yaml
new file mode 100644
index 0000000..9b5507b
--- /dev/null
+++ b/pkg/front_end/testcases/expression/from_vm_cc_linked_hash_map.expression.yaml
@@ -0,0 +1,30 @@
+# Copyright (c) 2018, 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.
+
+entry_point: "main.dart"
+definitions: [a, b]
+position: "dart:collection"
+expression: |
+  (a, b) {
+    if (a._usedData != b._usedData ||
+        a._deletedKeys != b._deletedKeys ||
+        a._hashMask != b._hashMask ||
+        a._index.length != b._index.length ||
+        a._data.length != b._data.length) {
+      return false;
+    }
+    for (var i = 0; i < a._index.length; ++i) {
+      if (a._index[i] != b._index[i]) {
+        return false;
+      }
+    }
+    for (var i = 0; i < a._data.length; ++i) {
+      var ad = a._data[i];
+      var bd = b._data[i];
+      if (!identical(ad, bd) && !(ad == a && bd == b)) {
+        return false;
+      }
+    }
+    return true;
+  }(a, b)
\ No newline at end of file
diff --git a/pkg/front_end/testcases/expression/from_vm_cc_linked_hash_map.expression.yaml.expect b/pkg/front_end/testcases/expression/from_vm_cc_linked_hash_map.expression.yaml.expect
new file mode 100644
index 0000000..ad666aa
--- /dev/null
+++ b/pkg/front_end/testcases/expression/from_vm_cc_linked_hash_map.expression.yaml.expect
@@ -0,0 +1,21 @@
+Errors: {
+}
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr(dynamic a, dynamic b) → dynamic
+  return ((dynamic a, dynamic b) → dart.core::bool {
+    if(!a._usedData.{dart.core::Object::==}(b._usedData) || !a._deletedKeys.{dart.core::Object::==}(b._deletedKeys) || !a._hashMask.{dart.core::Object::==}(b._hashMask) || !a._index.length.{dart.core::Object::==}(b._index.length) || !a._data.length.{dart.core::Object::==}(b._data.length)) {
+      return false;
+    }
+    for (dart.core::int i = 0; i.{dart.core::num::<}(a._index.length as{TypeError} dart.core::num); i = i.{dart.core::num::+}(1)) {
+      if(!a._index.[](i).{dart.core::Object::==}(b._index.[](i))) {
+        return false;
+      }
+    }
+    for (dart.core::int i = 0; i.{dart.core::num::<}(a._data.length as{TypeError} dart.core::num); i = i.{dart.core::num::+}(1)) {
+      dynamic ad = a._data.[](i);
+      dynamic bd = b._data.[](i);
+      if(!dart.core::identical(ad, bd) && !(ad.{dart.core::Object::==}(a) && bd.{dart.core::Object::==}(b))) {
+        return false;
+      }
+    }
+    return true;
+  }).call(a, b);
diff --git a/pkg/front_end/testcases/function_type_default_value.dart.legacy.expect b/pkg/front_end/testcases/function_type_default_value.dart.legacy.expect
index 17bf98f..5a6a508 100644
--- a/pkg/front_end/testcases/function_type_default_value.dart.legacy.expect
+++ b/pkg/front_end/testcases/function_type_default_value.dart.legacy.expect
@@ -10,6 +10,10 @@
 // void Function({obj: Object}) x;
 //                   ^
 //
+// pkg/front_end/testcases/function_type_default_value.dart:5:16: Warning: Type 'obj' not found.
+// void Function({obj: Object}) x;
+//                ^^^
+//
 // pkg/front_end/testcases/function_type_default_value.dart:5:16: Warning: 'obj' isn't a type.
 // void Function({obj: Object}) x;
 //                ^^^
diff --git a/pkg/front_end/testcases/function_type_default_value.dart.legacy.transformed.expect b/pkg/front_end/testcases/function_type_default_value.dart.legacy.transformed.expect
index 17bf98f..5a6a508 100644
--- a/pkg/front_end/testcases/function_type_default_value.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/function_type_default_value.dart.legacy.transformed.expect
@@ -10,6 +10,10 @@
 // void Function({obj: Object}) x;
 //                   ^
 //
+// pkg/front_end/testcases/function_type_default_value.dart:5:16: Warning: Type 'obj' not found.
+// void Function({obj: Object}) x;
+//                ^^^
+//
 // pkg/front_end/testcases/function_type_default_value.dart:5:16: Warning: 'obj' isn't a type.
 // void Function({obj: Object}) x;
 //                ^^^
diff --git a/pkg/front_end/testcases/function_type_default_value.dart.outline.expect b/pkg/front_end/testcases/function_type_default_value.dart.outline.expect
index ce8fac7..bff8898 100644
--- a/pkg/front_end/testcases/function_type_default_value.dart.outline.expect
+++ b/pkg/front_end/testcases/function_type_default_value.dart.outline.expect
@@ -10,6 +10,10 @@
 // void Function({obj: Object}) x;
 //                   ^
 //
+// pkg/front_end/testcases/function_type_default_value.dart:5:16: Warning: Type 'obj' not found.
+// void Function({obj: Object}) x;
+//                ^^^
+//
 import self as self;
 
 static field () → void x;
diff --git a/pkg/front_end/testcases/function_type_default_value.dart.strong.expect b/pkg/front_end/testcases/function_type_default_value.dart.strong.expect
index dd48e08..6f1c9a9 100644
--- a/pkg/front_end/testcases/function_type_default_value.dart.strong.expect
+++ b/pkg/front_end/testcases/function_type_default_value.dart.strong.expect
@@ -10,6 +10,10 @@
 // void Function({obj: Object}) x;
 //                   ^
 //
+// pkg/front_end/testcases/function_type_default_value.dart:5:16: Error: Type 'obj' not found.
+// void Function({obj: Object}) x;
+//                ^^^
+//
 // pkg/front_end/testcases/function_type_default_value.dart:5:16: Error: 'obj' isn't a type.
 // void Function({obj: Object}) x;
 //                ^^^
diff --git a/pkg/front_end/testcases/function_type_default_value.dart.strong.transformed.expect b/pkg/front_end/testcases/function_type_default_value.dart.strong.transformed.expect
index dd48e08..6f1c9a9 100644
--- a/pkg/front_end/testcases/function_type_default_value.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/function_type_default_value.dart.strong.transformed.expect
@@ -10,6 +10,10 @@
 // void Function({obj: Object}) x;
 //                   ^
 //
+// pkg/front_end/testcases/function_type_default_value.dart:5:16: Error: Type 'obj' not found.
+// void Function({obj: Object}) x;
+//                ^^^
+//
 // pkg/front_end/testcases/function_type_default_value.dart:5:16: Error: 'obj' isn't a type.
 // void Function({obj: Object}) x;
 //                ^^^
diff --git a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.outline.expect b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.outline.expect
index 8e3f873..8658511 100644
--- a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.outline.expect
+++ b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.outline.expect
@@ -3,10 +3,10 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  static const field dynamic constField;
+  static const field dynamic constField = 87;
   const constructor •(dynamic x) → self::C
     ;
 }
-static const field dynamic constTopLevelField;
+static const field dynamic constTopLevelField = 42;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_2.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_2.yaml
new file mode 100644
index 0000000..4d0a193
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_2.yaml
@@ -0,0 +1,73 @@
+# Copyright (c) 2019, 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.md file.
+
+# Compile an application with a number of modules.
+# Compile again with changing modules.
+
+type: newworld
+strong: true
+modules:
+  example_1:
+    example_1/a.dart: |
+      a() {}
+      var example = true;
+    example_1/.packages: |
+      example:.
+  example_2:
+    example_2/a.dart: |
+      a() {}
+      var example = true;
+    example_2/.packages: |
+      example:.
+  foo:
+    foo/foo.dart: |
+      export "package:example/a.dart";
+      var foo = true;
+    foo/.packages: |
+      foo:.
+      example:../example_1
+worlds:
+  - entry: main.dart
+    fromComponent: true
+    sources:
+      main.dart: |
+        import "package:foo/foo.dart";
+        main() {
+          print("hello");
+          a();
+        }
+      .packages: |
+        foo:foo
+        example:example_1
+    modules:
+      - foo
+      - example_1
+    expectedLibraryCount: 3
+    expectedContent:
+      org-dartlang-test:///main.dart:
+        - Procedure main
+      package:foo/foo.dart:
+        - Field foo
+      package:example/a.dart:
+        - Procedure a
+        - Field example
+  - entry: main.dart
+    worldType: updated
+    expectInitializeFromDill: false
+    sources:
+      .packages: |
+        foo:foo
+        example:example_2
+    modules:
+      - foo
+      - example_2
+    expectedLibraryCount: 3
+    expectedContent:
+      org-dartlang-test:///main.dart:
+        - Procedure main
+      package:foo/foo.dart:
+        - Field foo
+      package:example/a.dart:
+        - Procedure a
+        - Field example
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml
new file mode 100644
index 0000000..7e64c8c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_3.yaml
@@ -0,0 +1,64 @@
+# Copyright (c) 2019, 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.md file.
+
+# Compile an application with a number of modules.
+# Compile again with changing modules.
+
+type: newworld
+strong: true
+modules:
+  foo:
+    foo/foo.dart: |
+      var foo = true;
+    foo/.packages: |
+      foo:.
+  foo2:
+    foo2/foo.dart: |
+      var foo2 = true;
+    foo2/.packages: |
+      foo:.
+worlds:
+  - entry: main.dart
+    fromComponent: true
+    simulateTransformer: true
+    sources:
+      main.dart: |
+        import "package:foo/foo.dart";
+        main() {
+          print(foo);
+        }
+      .packages: |
+        foo:foo
+    modules:
+      - foo
+    expectedLibraryCount: 2
+    expectedContent:
+      org-dartlang-test:///main.dart:
+        - Procedure main
+        - Field lalala_SimulateTransformer
+      package:foo/foo.dart:
+        - Field foo
+        - Field lalala_SimulateTransformer
+  - entry: main.dart
+    worldType: updated
+    expectInitializeFromDill: false
+    simulateTransformer: true
+    sources:
+      main.dart: |
+        import "package:foo/foo.dart";
+        main() {
+          print(foo2);
+        }
+      .packages: |
+        foo:foo2
+    modules:
+      - foo2
+    expectedLibraryCount: 2
+    expectedContent:
+      org-dartlang-test:///main.dart:
+        - Procedure main
+        - Field lalala_SimulateTransformer
+      package:foo/foo.dart:
+        - Field foo2
+        - Field lalala_SimulateTransformer
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml
new file mode 100644
index 0000000..b426a33
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml
@@ -0,0 +1,27 @@
+# Copyright (c) 2019, 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.md file.
+
+# Compile a application.
+# Perform an expression calculation on it, where the expression gives a compile
+# time error.
+# Ask to compile again, and make sure we don't see the expression compilation
+# error.
+
+type: newworld
+strong: false
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        main() {
+          print("hello");
+        }
+    expectedLibraryCount: 1
+    expressionCompilation:
+      uri: main.dart
+      expression: foo()
+  - entry: main.dart
+    expectInitializeFromDill: false
+    worldType: updated
+    expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml
new file mode 100644
index 0000000..c5164e2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_5.yaml
@@ -0,0 +1,67 @@
+# Copyright (c) 2019, 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.md file.
+
+# Compile an application with errors in it, then - without fixing the errors -
+# recompile. Make sure we still get errors. As long as we don't fix the error,
+# we keep getting errors. Once we fix it, we no longer get errors.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      .packages: mypackage:mypackage
+      main.dart: |
+        import "package:mypackage/a.dart" as a;
+
+        main() {
+          a.main();
+        }
+      mypackage/a.dart: |
+        import "package:mypackage/b.dart";
+
+        main() {
+          foo();
+        }
+      mypackage/b.dart: |
+        foo() {
+          bar();
+        }
+    expectedLibraryCount: 3
+    errors: true
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    expectInitializeFromDill: false
+    expectedLibraryCount: 3
+  - entry: main.dart
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - package:mypackage/a.dart
+    sources:
+      mypackage/a.dart: |
+        import "package:mypackage/b.dart";
+
+        main() {
+          foo();
+          foo();
+        }
+    expectedLibraryCount: 3
+    errors: true
+  - entry: main.dart
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - package:mypackage/a.dart
+    sources:
+      mypackage/a.dart: |
+        main() {
+          foo();
+          foo();
+        }
+
+        foo() {}
+    expectedLibraryCount: 2
+    errors: false
\ No newline at end of file
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
index 459d870..6ddb363 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
@@ -8,10 +8,12 @@
   const constructor named(core::List<core::String> l) → self::Foo
     ;
 }
+@self::Foo::•(const <dynamic>[])
 class Bar extends core::Object {
   synthetic constructor •() → self::Bar
     ;
 }
+@self::Foo::named(const <dynamic>[])
 class Baz extends core::Object {
   synthetic constructor •() → self::Baz
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
index b4da95f..62d5559 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
@@ -7,9 +7,12 @@
     ;
 }
 abstract class Bar extends core::Object {
+  @self::Foo::•(const <dynamic>[])
   field dynamic x;
+  @self::Foo::•(const <dynamic>[])
   constructor •() → self::Bar
     ;
+  @self::Foo::•(const <dynamic>[])
   abstract method f() → void;
 }
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/inference/override_equals.dart.outline.expect b/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
index bf42edb..41bfd6e 100644
--- a/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
@@ -5,6 +5,7 @@
 class NullEquality extends core::Object {
   synthetic constructor •() → self::NullEquality
     ;
+  @core::override
   operator ==(core::Object other) → core::Null
     ;
 }
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.expect
index dbf94d5..ce101a2 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.expect
@@ -7,12 +7,6 @@
 // class Hest<X extends LinkedListEntry> {}
 //            ^
 //
-// pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart:15:12: Error: Type argument 'LinkedListEntry<dynamic>' doesn't conform to the bound 'LinkedListEntry<E>' of the type variable 'E' on 'LinkedListEntry'.
-//  - 'LinkedListEntry' is from 'dart:collection'.
-// Try changing type arguments so that they conform to the bounds.
-// class Hest<X extends LinkedListEntry> {}
-//            ^
-//
 import self as self;
 import "dart:collection" as col;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.transformed.expect
index dbf94d5..ce101a2 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.transformed.expect
@@ -7,12 +7,6 @@
 // class Hest<X extends LinkedListEntry> {}
 //            ^
 //
-// pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart:15:12: Error: Type argument 'LinkedListEntry<dynamic>' doesn't conform to the bound 'LinkedListEntry<E>' of the type variable 'E' on 'LinkedListEntry'.
-//  - 'LinkedListEntry' is from 'dart:collection'.
-// Try changing type arguments so that they conform to the bounds.
-// class Hest<X extends LinkedListEntry> {}
-//            ^
-//
 import self as self;
 import "dart:collection" as col;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart
new file mode 100644
index 0000000..8ecef66
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, 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.
+
+class A<X extends Comparable<X>> {}
+
+class B<Y extends A<dynamic>> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.hierarchy.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.hierarchy.expect
new file mode 100644
index 0000000..523e0f4
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.hierarchy.expect
@@ -0,0 +1,53 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.expect
new file mode 100644
index 0000000..6b8efb5
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Comparable<self::A::X> = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class B<Y extends self::A<dynamic> = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.transformed.expect
new file mode 100644
index 0000000..6b8efb5
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.transformed.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Comparable<self::A::X> = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class B<Y extends self::A<dynamic> = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.outline.expect
new file mode 100644
index 0000000..9a334ff
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.outline.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Comparable<self::A::X> = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    ;
+}
+class B<Y extends self::A<dynamic> = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::Y>
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.expect
new file mode 100644
index 0000000..88cbec9
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Comparable<self::A::X> = core::Comparable<dynamic>> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class B<Y extends self::A<dynamic> = self::A<dynamic>> extends core::Object {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.transformed.expect
new file mode 100644
index 0000000..88cbec9
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.transformed.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Comparable<self::A::X> = core::Comparable<dynamic>> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class B<Y extends self::A<dynamic> = self::A<dynamic>> extends core::Object {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart b/pkg/front_end/testcases/interface_contravariant_from_class.dart
new file mode 100644
index 0000000..0b50e14
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2017, 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;
+
+typedef void F<T>(T t);
+
+class B<T> {
+  T f(int x) {}
+}
+
+abstract class I<T> {
+  T f(Object x);
+}
+
+abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.hierarchy.expect
new file mode 100644
index 0000000..c84fdc2
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.hierarchy.expect
@@ -0,0 +1,72 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    B.f
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+I:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    I.f
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+C:
+  superclasses:
+    B
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.transformed.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.outline.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.outline.expect
new file mode 100644
index 0000000..31e0650
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.outline.expect
@@ -0,0 +1,33 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    ;
+  method f(core::int x) → self::B::T
+    ;
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    ;
+  abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    ;
+}
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.transformed.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart
new file mode 100644
index 0000000..a06fc2d
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2017, 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;
+
+typedef void F<T>(T t);
+
+class B<T> {
+  void f(F<T> x, int y) {}
+}
+
+abstract class I<T> {
+  void f(F<T> x, Object y);
+}
+
+abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.hierarchy.expect
new file mode 100644
index 0000000..c84fdc2
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.hierarchy.expect
@@ -0,0 +1,72 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    B.f
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+I:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    I.f
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+C:
+  superclasses:
+    B
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.transformed.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.outline.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.outline.expect
new file mode 100644
index 0000000..3e3646c
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.outline.expect
@@ -0,0 +1,33 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    ;
+  method f((self::B::T) → void x, core::int y) → void
+    ;
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    ;
+}
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.transformed.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart
new file mode 100644
index 0000000..010f354
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2017, 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;
+
+typedef void F<T>(T t);
+
+abstract class A<T> {
+  void f(T x, int y);
+}
+
+class B<T> implements A<F<T>> {
+  void f(F<T> x, int y) {}
+}
+
+abstract class I<T> implements A<F<T>> {
+  void f(F<T> x, Object y);
+}
+
+abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.hierarchy.expect
new file mode 100644
index 0000000..c43a8c7
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.hierarchy.expect
@@ -0,0 +1,90 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    A.f
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    B.f
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+I:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    I.f
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+C:
+  superclasses:
+    B
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+//       ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.transformed.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.transformed.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+//       ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.outline.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.outline.expect
new file mode 100644
index 0000000..c7028ce
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.outline.expect
@@ -0,0 +1,46 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+//       ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    ;
+  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    ;
+  method f((self::B::T) → void x, core::int y) → void
+    ;
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    ;
+}
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+//       ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.transformed.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.transformed.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+//       ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/issue37027.dart b/pkg/front_end/testcases/issue37027.dart
new file mode 100644
index 0000000..385e2a4
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, 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.
+class C {
+  final Set<int> s;
+  C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/issue37027.dart.hierarchy.expect b/pkg/front_end/testcases/issue37027.dart.hierarchy.expect
new file mode 100644
index 0000000..d7772a1
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.hierarchy.expect
@@ -0,0 +1,37 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+C:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    C.s
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/issue37027.dart.legacy.expect b/pkg/front_end/testcases/issue37027.dart.legacy.expect
new file mode 100644
index 0000000..653b194
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.legacy.expect
@@ -0,0 +1,22 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/issue37027.dart:6:46: Error: Unexpected token 'if'.
+//   C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+//                                              ^^
+//
+// pkg/front_end/testcases/issue37027.dart:6:27: Error: Unexpected token 'for'.
+//   C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+//                           ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  final field core::Set<core::int> s;
+  constructor •(core::List<core::int> ell) → self::C
+    : self::C::s = <dynamic, dynamic>{}, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue37027.dart.legacy.transformed.expect b/pkg/front_end/testcases/issue37027.dart.legacy.transformed.expect
new file mode 100644
index 0000000..653b194
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.legacy.transformed.expect
@@ -0,0 +1,22 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/issue37027.dart:6:46: Error: Unexpected token 'if'.
+//   C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+//                                              ^^
+//
+// pkg/front_end/testcases/issue37027.dart:6:27: Error: Unexpected token 'for'.
+//   C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+//                           ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  final field core::Set<core::int> s;
+  constructor •(core::List<core::int> ell) → self::C
+    : self::C::s = <dynamic, dynamic>{}, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue37027.dart.outline.expect b/pkg/front_end/testcases/issue37027.dart.outline.expect
new file mode 100644
index 0000000..dc4999b
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.outline.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  final field core::Set<core::int> s;
+  constructor •(core::List<core::int> ell) → self::C
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/issue37027.dart.strong.expect b/pkg/front_end/testcases/issue37027.dart.strong.expect
new file mode 100644
index 0000000..2387135
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C extends core::Object {
+  final field core::Set<core::int> s;
+  constructor •(core::List<core::int> ell) → self::C
+    : self::C::s = block {
+      final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>();
+      for (core::int e in ell)
+        if(e.{core::int::isOdd})
+          #t1.{core::Set::add}(2.{core::num::*}(e));
+    } =>#t1, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue37027.dart.strong.transformed.expect b/pkg/front_end/testcases/issue37027.dart.strong.transformed.expect
new file mode 100644
index 0000000..2387135
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C extends core::Object {
+  final field core::Set<core::int> s;
+  constructor •(core::List<core::int> ell) → self::C
+    : self::C::s = block {
+      final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>();
+      for (core::int e in ell)
+        if(e.{core::int::isOdd})
+          #t1.{core::Set::add}(2.{core::num::*}(e));
+    } =>#t1, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/legacy.status b/pkg/front_end/testcases/legacy.status
index 7fadc91..b1b1917 100644
--- a/pkg/front_end/testcases/legacy.status
+++ b/pkg/front_end/testcases/legacy.status
@@ -20,6 +20,7 @@
 inference/bug31436: RuntimeError # Test exercises Dart 2.0 semantics
 inference/constructors_too_many_positional_arguments: Fail
 inference/downwards_inference_annotations_locals: Fail # Issue #30031
+inference/downwards_inference_for_each: RuntimeError # Issue #36382
 inference/future_then_explicit_future: RuntimeError
 inference/generic_methods_infer_js_builtin: RuntimeError # Test attempts to access platform-private library leading to NSM.
 inference/infer_assign_to_index: Fail
@@ -114,6 +115,9 @@
 regress/issue_35260: RuntimeError # Expected
 regress/issue_35266: RuntimeError # Expected
 regress/issue_36400: RuntimeError
+regress/issue_36647: RuntimeError # Expected
+regress/issue_36647_2: RuntimeError # Expected
+regress/issue_36669: RuntimeError
 reject_generic_function_types_in_bounds: RuntimeError # Expected
 runtime_checks/implicit_downcast_constructor_initializer: RuntimeError # Test exercises strong mode semantics
 runtime_checks/implicit_downcast_do: RuntimeError # Test exercises strong mode semantics
@@ -129,6 +133,7 @@
 runtime_checks_new/stub_checked_via_target: RuntimeError # Test exercises strong mode semantics
 set_literals/disambiguation_rule: RuntimeError
 spread_collection: RuntimeError
+type_parameter_type_named_int: RuntimeError # Expected
 type_variable_as_super: Fail
 uninitialized_fields: Fail # Fasta and dartk disagree on static initializers
 void_methods: Fail # Bad return from setters.
diff --git a/pkg/front_end/testcases/metadata_enum.dart.outline.expect b/pkg/front_end/testcases/metadata_enum.dart.outline.expect
index 6fd993b..16c0355 100644
--- a/pkg/front_end/testcases/metadata_enum.dart.outline.expect
+++ b/pkg/front_end/testcases/metadata_enum.dart.outline.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+@self::a
 class E extends core::Object {
   final field core::int index;
   final field core::String _name;
@@ -15,6 +16,6 @@
   method toString() → core::String
     return this.{=self::E::_name};
 }
-static const field dynamic a;
+static const field dynamic a = null;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect b/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
index cec02ba..b3c6bd0 100644
--- a/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
+++ b/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+@self::a
 class C = self::D with self::E {
   synthetic constructor •() → self::C
     : super self::D::•()
@@ -15,6 +16,6 @@
   synthetic constructor •() → self::E
     ;
 }
-static const field dynamic a;
+static const field dynamic a = null;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/native_as_name.dart.outline.expect b/pkg/front_end/testcases/native_as_name.dart.outline.expect
index 6c2884c..b78f8ae 100644
--- a/pkg/front_end/testcases/native_as_name.dart.outline.expect
+++ b/pkg/front_end/testcases/native_as_name.dart.outline.expect
@@ -21,6 +21,7 @@
 class Y2 extends self::Y1 {
   synthetic constructor •() → self::Y2
     ;
+  @core::override
   get native() → core::String
     ;
 }
diff --git a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.outline.expect b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.outline.expect
index 2a8f6986..00b4657 100644
--- a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.outline.expect
+++ b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.outline.expect
@@ -18,6 +18,6 @@
   method fun() → dynamic
     ;
 }
-static const field core::int foo;
+static const field core::int foo = const core::int::fromEnvironment("fisk");
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/operator_method_not_found.dart.legacy.expect b/pkg/front_end/testcases/operator_method_not_found.dart.legacy.expect
index 0abf9ef..69ee9a4 100644
--- a/pkg/front_end/testcases/operator_method_not_found.dart.legacy.expect
+++ b/pkg/front_end/testcases/operator_method_not_found.dart.legacy.expect
@@ -2,6 +2,10 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/operator_method_not_found.dart:36:10: Warning: 'foo' isn't a type.
+//   print(<foo);
+//          ^^^
+//
 // pkg/front_end/testcases/operator_method_not_found.dart:36:10: Error: Expected '>' after this.
 //   print(<foo);
 //          ^^^
@@ -10,10 +14,6 @@
 //   print(<foo);
 //             ^
 //
-// pkg/front_end/testcases/operator_method_not_found.dart:36:10: Warning: 'foo' isn't a type.
-//   print(<foo);
-//          ^^^
-//
 // pkg/front_end/testcases/operator_method_not_found.dart:37:9: Error: Expected an identifier, but got '>'.
 //   print(>foo);
 //         ^
diff --git a/pkg/front_end/testcases/operator_method_not_found.dart.legacy.transformed.expect b/pkg/front_end/testcases/operator_method_not_found.dart.legacy.transformed.expect
index 0abf9ef..69ee9a4 100644
--- a/pkg/front_end/testcases/operator_method_not_found.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/operator_method_not_found.dart.legacy.transformed.expect
@@ -2,6 +2,10 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/operator_method_not_found.dart:36:10: Warning: 'foo' isn't a type.
+//   print(<foo);
+//          ^^^
+//
 // pkg/front_end/testcases/operator_method_not_found.dart:36:10: Error: Expected '>' after this.
 //   print(<foo);
 //          ^^^
@@ -10,10 +14,6 @@
 //   print(<foo);
 //             ^
 //
-// pkg/front_end/testcases/operator_method_not_found.dart:36:10: Warning: 'foo' isn't a type.
-//   print(<foo);
-//          ^^^
-//
 // pkg/front_end/testcases/operator_method_not_found.dart:37:9: Error: Expected an identifier, but got '>'.
 //   print(>foo);
 //         ^
diff --git a/pkg/front_end/testcases/operator_method_not_found.dart.strong.expect b/pkg/front_end/testcases/operator_method_not_found.dart.strong.expect
index ec89d36..5399098 100644
--- a/pkg/front_end/testcases/operator_method_not_found.dart.strong.expect
+++ b/pkg/front_end/testcases/operator_method_not_found.dart.strong.expect
@@ -2,6 +2,10 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/operator_method_not_found.dart:36:10: Error: 'foo' isn't a type.
+//   print(<foo);
+//          ^^^
+//
 // pkg/front_end/testcases/operator_method_not_found.dart:36:10: Error: Expected '>' after this.
 //   print(<foo);
 //          ^^^
@@ -10,10 +14,6 @@
 //   print(<foo);
 //             ^
 //
-// pkg/front_end/testcases/operator_method_not_found.dart:36:10: Error: 'foo' isn't a type.
-//   print(<foo);
-//          ^^^
-//
 // pkg/front_end/testcases/operator_method_not_found.dart:37:9: Error: Expected an identifier, but got '>'.
 //   print(>foo);
 //         ^
diff --git a/pkg/front_end/testcases/operator_method_not_found.dart.strong.transformed.expect b/pkg/front_end/testcases/operator_method_not_found.dart.strong.transformed.expect
index ec89d36..5399098 100644
--- a/pkg/front_end/testcases/operator_method_not_found.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/operator_method_not_found.dart.strong.transformed.expect
@@ -2,6 +2,10 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/operator_method_not_found.dart:36:10: Error: 'foo' isn't a type.
+//   print(<foo);
+//          ^^^
+//
 // pkg/front_end/testcases/operator_method_not_found.dart:36:10: Error: Expected '>' after this.
 //   print(<foo);
 //          ^^^
@@ -10,10 +14,6 @@
 //   print(<foo);
 //             ^
 //
-// pkg/front_end/testcases/operator_method_not_found.dart:36:10: Error: 'foo' isn't a type.
-//   print(<foo);
-//          ^^^
-//
 // pkg/front_end/testcases/operator_method_not_found.dart:37:9: Error: Expected an identifier, but got '>'.
 //   print(>foo);
 //         ^
diff --git a/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect b/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
index 9051099..cc16f53 100644
--- a/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
+++ b/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
@@ -14,6 +14,7 @@
 class Hest extends core::Object implements self::Bar {
   synthetic constructor •() → self::Hest
     ;
+  @core::override
   method fisk<U extends self::Foo<self::Hest::fisk::U> = dynamic>() → void
     ;
 }
diff --git a/pkg/front_end/testcases/qualified.dart.legacy.expect b/pkg/front_end/testcases/qualified.dart.legacy.expect
index bd70509..6afde2e 100644
--- a/pkg/front_end/testcases/qualified.dart.legacy.expect
+++ b/pkg/front_end/testcases/qualified.dart.legacy.expect
@@ -9,6 +9,10 @@
 // class Bad extends lib.Missing {
 //       ^^^
 //
+// pkg/front_end/testcases/qualified.dart:11:19: Warning: Type 'lib.Missing' not found.
+// class Bad extends lib.Missing {
+//                   ^^^^^^^^^^^
+//
 // pkg/front_end/testcases/qualified.dart:12:3: Warning: Type 'lib.Missing' not found.
 //   lib.Missing method() {}
 //   ^^^^^^^^^^^
diff --git a/pkg/front_end/testcases/qualified.dart.legacy.transformed.expect b/pkg/front_end/testcases/qualified.dart.legacy.transformed.expect
index df06d18..4da117d4c6 100644
--- a/pkg/front_end/testcases/qualified.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/qualified.dart.legacy.transformed.expect
@@ -9,6 +9,10 @@
 // class Bad extends lib.Missing {
 //       ^^^
 //
+// pkg/front_end/testcases/qualified.dart:11:19: Warning: Type 'lib.Missing' not found.
+// class Bad extends lib.Missing {
+//                   ^^^^^^^^^^^
+//
 // pkg/front_end/testcases/qualified.dart:12:3: Warning: Type 'lib.Missing' not found.
 //   lib.Missing method() {}
 //   ^^^^^^^^^^^
diff --git a/pkg/front_end/testcases/qualified.dart.outline.expect b/pkg/front_end/testcases/qualified.dart.outline.expect
index 0fca5f9..6df7d32 100644
--- a/pkg/front_end/testcases/qualified.dart.outline.expect
+++ b/pkg/front_end/testcases/qualified.dart.outline.expect
@@ -9,6 +9,10 @@
 // class Bad extends lib.Missing {
 //       ^^^
 //
+// pkg/front_end/testcases/qualified.dart:11:19: Warning: Type 'lib.Missing' not found.
+// class Bad extends lib.Missing {
+//                   ^^^^^^^^^^^
+//
 // pkg/front_end/testcases/qualified.dart:12:3: Warning: Type 'lib.Missing' not found.
 //   lib.Missing method() {}
 //   ^^^^^^^^^^^
diff --git a/pkg/front_end/testcases/qualified.dart.strong.expect b/pkg/front_end/testcases/qualified.dart.strong.expect
index 9bc943f..c145d18 100644
--- a/pkg/front_end/testcases/qualified.dart.strong.expect
+++ b/pkg/front_end/testcases/qualified.dart.strong.expect
@@ -9,14 +9,14 @@
 // class Bad extends lib.Missing {
 //       ^^^
 //
-// pkg/front_end/testcases/qualified.dart:12:3: Error: Type 'lib.Missing' not found.
-//   lib.Missing method() {}
-//   ^^^^^^^^^^^
-//
 // pkg/front_end/testcases/qualified.dart:11:19: Error: Type 'lib.Missing' not found.
 // class Bad extends lib.Missing {
 //                   ^^^^^^^^^^^
 //
+// pkg/front_end/testcases/qualified.dart:12:3: Error: Type 'lib.Missing' not found.
+//   lib.Missing method() {}
+//   ^^^^^^^^^^^
+//
 // pkg/front_end/testcases/qualified.dart:18:7: Error: The type 'lib.VoidFunction' can't be used as supertype.
 // class IllegalSupertype extends lib.VoidFunction {}
 //       ^
diff --git a/pkg/front_end/testcases/qualified.dart.strong.transformed.expect b/pkg/front_end/testcases/qualified.dart.strong.transformed.expect
index 197c0d8..5c3bf8c 100644
--- a/pkg/front_end/testcases/qualified.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/qualified.dart.strong.transformed.expect
@@ -9,14 +9,14 @@
 // class Bad extends lib.Missing {
 //       ^^^
 //
-// pkg/front_end/testcases/qualified.dart:12:3: Error: Type 'lib.Missing' not found.
-//   lib.Missing method() {}
-//   ^^^^^^^^^^^
-//
 // pkg/front_end/testcases/qualified.dart:11:19: Error: Type 'lib.Missing' not found.
 // class Bad extends lib.Missing {
 //                   ^^^^^^^^^^^
 //
+// pkg/front_end/testcases/qualified.dart:12:3: Error: Type 'lib.Missing' not found.
+//   lib.Missing method() {}
+//   ^^^^^^^^^^^
+//
 // pkg/front_end/testcases/qualified.dart:18:7: Error: The type 'lib.VoidFunction' can't be used as supertype.
 // class IllegalSupertype extends lib.VoidFunction {}
 //       ^
diff --git a/pkg/front_end/testcases/rasta/bad_default_constructor.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_default_constructor.dart.strong.expect
new file mode 100644
index 0000000..8ea402c
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_default_constructor.dart.strong.expect
@@ -0,0 +1,33 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/rasta/bad_default_constructor.dart:13:9: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B();
+//         ^
+//
+// pkg/front_end/testcases/rasta/bad_default_constructor.dart:9:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
+// class B extends A {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •(dynamic x) → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : invalid-initializer
+    ;
+}
+static method main() → dynamic {
+  new self::B::•();
+  invalid-expression "pkg/front_end/testcases/rasta/bad_default_constructor.dart:13:9: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B();
+        ^";
+}
diff --git a/pkg/front_end/testcases/rasta/bad_default_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_default_constructor.dart.strong.transformed.expect
new file mode 100644
index 0000000..8ea402c
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_default_constructor.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/rasta/bad_default_constructor.dart:13:9: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B();
+//         ^
+//
+// pkg/front_end/testcases/rasta/bad_default_constructor.dart:9:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
+// class B extends A {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •(dynamic x) → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : invalid-initializer
+    ;
+}
+static method main() → dynamic {
+  new self::B::•();
+  invalid-expression "pkg/front_end/testcases/rasta/bad_default_constructor.dart:13:9: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B();
+        ^";
+}
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect
index a6ec9b4..184037de 100644
--- a/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect
@@ -2,6 +2,18 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:5:17: Warning: Type 'Missing' not found.
+// class A extends Missing {}
+//                 ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:7:20: Warning: Type 'Missing' not found.
+// class B implements Missing {}
+//                    ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:9:23: Warning: Type 'Missing' not found.
+// class C = Object with Missing;
+//                       ^^^^^^^
+//
 // pkg/front_end/testcases/rasta/class_hierarchy.dart:9:7: Error: The type 'Missing' can't be mixed in.
 // class C = Object with Missing;
 //       ^
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect
index d874733..06d8f86 100644
--- a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect
@@ -2,10 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/rasta/class_hierarchy.dart:9:7: Error: The type 'Missing' can't be mixed in.
-// class C = Object with Missing;
-//       ^
-//
 // pkg/front_end/testcases/rasta/class_hierarchy.dart:5:17: Error: Type 'Missing' not found.
 // class A extends Missing {}
 //                 ^^^^^^^
@@ -18,6 +14,10 @@
 // class C = Object with Missing;
 //                       ^^^^^^^
 //
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:9:7: Error: The type 'Missing' can't be mixed in.
+// class C = Object with Missing;
+//       ^
+//
 // pkg/front_end/testcases/rasta/class_hierarchy.dart:12:17: Error: Couldn't find constructor 'Missing'.
 //   factory D() = Missing;
 //                 ^
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect
index 94f01e5..9184493 100644
--- a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect
@@ -2,10 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/rasta/class_hierarchy.dart:9:7: Error: The type 'Missing' can't be mixed in.
-// class C = Object with Missing;
-//       ^
-//
 // pkg/front_end/testcases/rasta/class_hierarchy.dart:5:17: Error: Type 'Missing' not found.
 // class A extends Missing {}
 //                 ^^^^^^^
@@ -18,6 +14,10 @@
 // class C = Object with Missing;
 //                       ^^^^^^^
 //
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:9:7: Error: The type 'Missing' can't be mixed in.
+// class C = Object with Missing;
+//       ^
+//
 // pkg/front_end/testcases/rasta/class_hierarchy.dart:12:17: Error: Couldn't find constructor 'Missing'.
 //   factory D() = Missing;
 //                 ^
diff --git a/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.outline.expect b/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.outline.expect
index 7c08d7a..c9b0d8b 100644
--- a/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.outline.expect
@@ -1,6 +1,6 @@
 library;
 import self as self;
 
-static const field dynamic c;
+static const field dynamic c = 1;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
index 6a28c0d..44fbbbc 100644
--- a/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
@@ -1,5 +1,15 @@
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/rasta/issue_000033.dart:5:2: Warning: Method not found: 'JS'.
+// @JS()
+//  ^^
+//
 import self as self;
 
+@invalid-expression "pkg/front_end/testcases/rasta/issue_000033.dart:5:2: Error: Method not found: 'JS'.
+@JS()
+ ^^"
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/rasta/issue_000039.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000039.dart.strong.expect
new file mode 100644
index 0000000..564c718
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000039.dart.strong.expect
@@ -0,0 +1,37 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got '}'.
+//   }
+//   ^
+//
+// pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got ''.
+//   }
+//   ^
+//
+// pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected ';' after this.
+//   }
+//   ^
+//
+// pkg/front_end/testcases/rasta/issue_000039.dart:13:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
+// class B extends A {
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic a = null;
+  constructor •(dynamic x) → self::A
+    : super core::Object::•() {
+    this.{self::A::a} = invalid-expression "pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got ''.
+  }
+  ^";
+  }
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : invalid-initializer
+    ;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000039.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000039.dart.strong.transformed.expect
new file mode 100644
index 0000000..564c718
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000039.dart.strong.transformed.expect
@@ -0,0 +1,37 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got '}'.
+//   }
+//   ^
+//
+// pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got ''.
+//   }
+//   ^
+//
+// pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected ';' after this.
+//   }
+//   ^
+//
+// pkg/front_end/testcases/rasta/issue_000039.dart:13:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
+// class B extends A {
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic a = null;
+  constructor •(dynamic x) → self::A
+    : super core::Object::•() {
+    this.{self::A::a} = invalid-expression "pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got ''.
+  }
+  ^";
+  }
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : invalid-initializer
+    ;
+}
diff --git a/pkg/front_end/testcases/rasta/static.dart.outline.expect b/pkg/front_end/testcases/rasta/static.dart.outline.expect
index 970c3bb..f9b177a 100644
--- a/pkg/front_end/testcases/rasta/static.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/static.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class Foo extends core::Object {
-  static const field dynamic staticConstant;
+  static const field dynamic staticConstant = 42;
   static field dynamic staticField;
   synthetic constructor •() → self::Foo
     ;
diff --git a/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect b/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
index 5b95c2b..4830e5f 100644
--- a/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
+++ b/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
@@ -6,11 +6,12 @@
   static field dynamic _redirecting# = <dynamic>[self::Foo::•];
   constructor named(dynamic p) → self::Foo
     ;
+  @self::forFactoryItself
   static factory •(dynamic p) → self::Foo
     let dynamic #redirecting_factory = self::Foo::named in invalid-expression;
 }
-static const field dynamic forParameter;
-static const field dynamic forFactoryItself;
-static const field dynamic anotherForParameter;
+static const field dynamic forParameter = 1;
+static const field dynamic forFactoryItself = 2;
+static const field dynamic anotherForParameter = 3;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_31188.dart.legacy.expect
index ee42a18..8220450 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.legacy.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.legacy.expect
@@ -14,14 +14,14 @@
 // type T = Map<A, B>
 // ^^^^
 //
-// pkg/front_end/testcases/regress/issue_31188.dart:7:14: Warning: Getter not found: 'A'.
-// type T = Map<A, B>
-//              ^
-//
 // pkg/front_end/testcases/regress/issue_31188.dart:7:1: Warning: 'type' isn't a type.
 // type T = Map<A, B>
 // ^^^^
 //
+// pkg/front_end/testcases/regress/issue_31188.dart:7:14: Warning: Getter not found: 'A'.
+// type T = Map<A, B>
+//              ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_31188.dart.legacy.transformed.expect
index ee42a18..8220450 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.legacy.transformed.expect
@@ -14,14 +14,14 @@
 // type T = Map<A, B>
 // ^^^^
 //
-// pkg/front_end/testcases/regress/issue_31188.dart:7:14: Warning: Getter not found: 'A'.
-// type T = Map<A, B>
-//              ^
-//
 // pkg/front_end/testcases/regress/issue_31188.dart:7:1: Warning: 'type' isn't a type.
 // type T = Map<A, B>
 // ^^^^
 //
+// pkg/front_end/testcases/regress/issue_31188.dart:7:14: Warning: Getter not found: 'A'.
+// type T = Map<A, B>
+//              ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
index 104418a..c0f1dea 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
@@ -14,6 +14,10 @@
 // type T = Map<A, B>
 // ^^^^
 //
+// pkg/front_end/testcases/regress/issue_31188.dart:7:1: Error: 'type' isn't a type.
+// type T = Map<A, B>
+// ^^^^
+//
 // pkg/front_end/testcases/regress/issue_31188.dart:7:14: Error: Getter not found: 'A'.
 // type T = Map<A, B>
 //              ^
@@ -24,10 +28,6 @@
 // type T = Map<A, B>
 //             ^
 //
-// pkg/front_end/testcases/regress/issue_31188.dart:7:1: Error: 'type' isn't a type.
-// type T = Map<A, B>
-// ^^^^
-//
 import self as self;
 
 static field invalid-type T = invalid-expression "pkg/front_end/testcases/regress/issue_31188.dart:7:13: Error: The method '<' isn't defined for the class 'Type'.
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
index 104418a..c0f1dea 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
@@ -14,6 +14,10 @@
 // type T = Map<A, B>
 // ^^^^
 //
+// pkg/front_end/testcases/regress/issue_31188.dart:7:1: Error: 'type' isn't a type.
+// type T = Map<A, B>
+// ^^^^
+//
 // pkg/front_end/testcases/regress/issue_31188.dart:7:14: Error: Getter not found: 'A'.
 // type T = Map<A, B>
 //              ^
@@ -24,10 +28,6 @@
 // type T = Map<A, B>
 //             ^
 //
-// pkg/front_end/testcases/regress/issue_31188.dart:7:1: Error: 'type' isn't a type.
-// type T = Map<A, B>
-// ^^^^
-//
 import self as self;
 
 static field invalid-type T = invalid-expression "pkg/front_end/testcases/regress/issue_31188.dart:7:13: Error: The method '<' isn't defined for the class 'Type'.
diff --git a/pkg/front_end/testcases/regress/issue_31190.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_31190.dart.legacy.expect
index 22dd31b..7bfc382 100644
--- a/pkg/front_end/testcases/regress/issue_31190.dart.legacy.expect
+++ b/pkg/front_end/testcases/regress/issue_31190.dart.legacy.expect
@@ -7,6 +7,10 @@
 //   T<U> v;
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_31190.dart:6:5: Warning: Type 'U' not found.
+//   T<U> v;
+//     ^
+//
 // pkg/front_end/testcases/regress/issue_31190.dart:6:5: Warning: 'U' isn't a type.
 //   T<U> v;
 //     ^
diff --git a/pkg/front_end/testcases/regress/issue_31190.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_31190.dart.legacy.transformed.expect
index 22dd31b..7bfc382 100644
--- a/pkg/front_end/testcases/regress/issue_31190.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31190.dart.legacy.transformed.expect
@@ -7,6 +7,10 @@
 //   T<U> v;
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_31190.dart:6:5: Warning: Type 'U' not found.
+//   T<U> v;
+//     ^
+//
 // pkg/front_end/testcases/regress/issue_31190.dart:6:5: Warning: 'U' isn't a type.
 //   T<U> v;
 //     ^
diff --git a/pkg/front_end/testcases/regress/issue_31190.dart.outline.expect b/pkg/front_end/testcases/regress/issue_31190.dart.outline.expect
index 1d72ade..5820107 100644
--- a/pkg/front_end/testcases/regress/issue_31190.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_31190.dart.outline.expect
@@ -7,6 +7,10 @@
 //   T<U> v;
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_31190.dart:6:5: Warning: Type 'U' not found.
+//   T<U> v;
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_31190.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31190.dart.strong.expect
index 20196d3..3ccd713 100644
--- a/pkg/front_end/testcases/regress/issue_31190.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31190.dart.strong.expect
@@ -7,6 +7,10 @@
 //   T<U> v;
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_31190.dart:6:5: Error: Type 'U' not found.
+//   T<U> v;
+//     ^
+//
 // pkg/front_end/testcases/regress/issue_31190.dart:6:5: Error: 'U' isn't a type.
 //   T<U> v;
 //     ^
diff --git a/pkg/front_end/testcases/regress/issue_31190.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31190.dart.strong.transformed.expect
index 20196d3..3ccd713 100644
--- a/pkg/front_end/testcases/regress/issue_31190.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31190.dart.strong.transformed.expect
@@ -7,6 +7,10 @@
 //   T<U> v;
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_31190.dart:6:5: Error: Type 'U' not found.
+//   T<U> v;
+//     ^
+//
 // pkg/front_end/testcases/regress/issue_31190.dart:6:5: Error: 'U' isn't a type.
 //   T<U> v;
 //     ^
diff --git a/pkg/front_end/testcases/regress/issue_34498.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_34498.dart.legacy.expect
index 6efe51f..0922a4f 100644
--- a/pkg/front_end/testcases/regress/issue_34498.dart.legacy.expect
+++ b/pkg/front_end/testcases/regress/issue_34498.dart.legacy.expect
@@ -13,15 +13,15 @@
 //   foo foo() {}
 //       ^^^
 //
-// pkg/front_end/testcases/regress/issue_34498.dart:12:3: Warning: Type 'Missing' not found.
-//   Missing bar() {}
-//   ^^^^^^^
-//
 // pkg/front_end/testcases/regress/issue_34498.dart:20:3: Warning: Can't use type arguments with type variable 'T'.
 // Try removing the type arguments.
 //   T<String> foo() {}
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_34498.dart:12:3: Warning: Type 'Missing' not found.
+//   Missing bar() {}
+//   ^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_34498.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_34498.dart.legacy.transformed.expect
index 6efe51f..0922a4f 100644
--- a/pkg/front_end/testcases/regress/issue_34498.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34498.dart.legacy.transformed.expect
@@ -13,15 +13,15 @@
 //   foo foo() {}
 //       ^^^
 //
-// pkg/front_end/testcases/regress/issue_34498.dart:12:3: Warning: Type 'Missing' not found.
-//   Missing bar() {}
-//   ^^^^^^^
-//
 // pkg/front_end/testcases/regress/issue_34498.dart:20:3: Warning: Can't use type arguments with type variable 'T'.
 // Try removing the type arguments.
 //   T<String> foo() {}
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_34498.dart:12:3: Warning: Type 'Missing' not found.
+//   Missing bar() {}
+//   ^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_34498.dart.outline.expect b/pkg/front_end/testcases/regress/issue_34498.dart.outline.expect
index 23a4800..9a8a1f8 100644
--- a/pkg/front_end/testcases/regress/issue_34498.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_34498.dart.outline.expect
@@ -13,15 +13,15 @@
 //   foo foo() {}
 //       ^^^
 //
-// pkg/front_end/testcases/regress/issue_34498.dart:12:3: Warning: Type 'Missing' not found.
-//   Missing bar() {}
-//   ^^^^^^^
-//
 // pkg/front_end/testcases/regress/issue_34498.dart:20:3: Warning: Can't use type arguments with type variable 'T'.
 // Try removing the type arguments.
 //   T<String> foo() {}
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_34498.dart:12:3: Warning: Type 'Missing' not found.
+//   Missing bar() {}
+//   ^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_34498.dart.strong.expect b/pkg/front_end/testcases/regress/issue_34498.dart.strong.expect
index f90b74b..a72249c 100644
--- a/pkg/front_end/testcases/regress/issue_34498.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_34498.dart.strong.expect
@@ -13,15 +13,15 @@
 //   foo foo() {}
 //       ^^^
 //
-// pkg/front_end/testcases/regress/issue_34498.dart:12:3: Error: Type 'Missing' not found.
-//   Missing bar() {}
-//   ^^^^^^^
-//
 // pkg/front_end/testcases/regress/issue_34498.dart:20:3: Error: Can't use type arguments with type variable 'T'.
 // Try removing the type arguments.
 //   T<String> foo() {}
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_34498.dart:12:3: Error: Type 'Missing' not found.
+//   Missing bar() {}
+//   ^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_34498.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_34498.dart.strong.transformed.expect
index f90b74b..a72249c 100644
--- a/pkg/front_end/testcases/regress/issue_34498.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34498.dart.strong.transformed.expect
@@ -13,15 +13,15 @@
 //   foo foo() {}
 //       ^^^
 //
-// pkg/front_end/testcases/regress/issue_34498.dart:12:3: Error: Type 'Missing' not found.
-//   Missing bar() {}
-//   ^^^^^^^
-//
 // pkg/front_end/testcases/regress/issue_34498.dart:20:3: Error: Can't use type arguments with type variable 'T'.
 // Try removing the type arguments.
 //   T<String> foo() {}
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_34498.dart:12:3: Error: Type 'Missing' not found.
+//   Missing bar() {}
+//   ^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.strong.expect b/pkg/front_end/testcases/regress/issue_34850.dart.strong.expect
index f3100e5..f79536d 100644
--- a/pkg/front_end/testcases/regress/issue_34850.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.strong.expect
@@ -27,6 +27,10 @@
 // Future<List<>> f3() async {
 //             ^^
 //
+// pkg/front_end/testcases/regress/issue_34850.dart:5:2: Error: Type 'foo' not found.
+// <foo<
+//  ^^^
+//
 // pkg/front_end/testcases/regress/issue_34850.dart:5:2: Error: Expected 0 type arguments.
 // <foo<
 //  ^
@@ -35,6 +39,13 @@
 // foo
 // ^^^
 //
+// pkg/front_end/testcases/regress/issue_34850.dart:14:1: Error: 'Future' isn't a type.
+// Future<List<>> f3() async {
+// ^^^^^^
+// pkg/front_end/testcases/regress/issue_34850.dart:12:1: Context: This isn't a type.
+// Future<List<int>> f2() async => null;
+// ^^^^^^
+//
 // pkg/front_end/testcases/regress/issue_34850.dart:14:1: Error: Expected 0 type arguments.
 // Future<List<>> f3() async {
 // ^
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect
index 22df880..b0cda7b 100644
--- a/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect
@@ -27,6 +27,10 @@
 // Future<List<>> f3() async {
 //             ^^
 //
+// pkg/front_end/testcases/regress/issue_34850.dart:5:2: Error: Type 'foo' not found.
+// <foo<
+//  ^^^
+//
 // pkg/front_end/testcases/regress/issue_34850.dart:5:2: Error: Expected 0 type arguments.
 // <foo<
 //  ^
@@ -35,6 +39,13 @@
 // foo
 // ^^^
 //
+// pkg/front_end/testcases/regress/issue_34850.dart:14:1: Error: 'Future' isn't a type.
+// Future<List<>> f3() async {
+// ^^^^^^
+// pkg/front_end/testcases/regress/issue_34850.dart:12:1: Context: This isn't a type.
+// Future<List<int>> f2() async => null;
+// ^^^^^^
+//
 // pkg/front_end/testcases/regress/issue_34850.dart:14:1: Error: Expected 0 type arguments.
 // Future<List<>> f3() async {
 // ^
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart b/pkg/front_end/testcases/regress/issue_36647.dart
new file mode 100644
index 0000000..3fcff27
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2019, 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 'issue_36647_lib1.dart';
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.hierarchy.expect b/pkg/front_end/testcases/regress/issue_36647.dart.hierarchy.expect
new file mode 100644
index 0000000..f111e00
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.hierarchy.expect
@@ -0,0 +1,36 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+xxx:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect
new file mode 100644
index 0000000..b965c9b
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect
@@ -0,0 +1,73 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///issue_36647_lib1.dart";
+
+
+library;
+import self as self2;
+import "issue_36647_lib2.dart" as iss;
+additionalExports = (iss::xxx)
+, iss::XXX)
+, iss::extends)
+
+
+export "org-dartlang-testcase:///issue_36647_lib2.dart";
+
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// class xxx xx XXX extends XXX {
+//       ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
+// class xxx xx XXX extends XXX {
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected an identifier, but got 'extends'.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected ';' after this.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// class xxx xx XXX extends XXX {
+//                          ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:26: Error: 'XXX' is already declared in this scope.
+// class xxx xx XXX extends XXX {
+//                          ^^^
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Context: Previous declaration of 'XXX'.
+// class xxx xx XXX extends XXX {
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Warning: Type 'xx' not found.
+// class xxx xx XXX extends XXX {
+//           ^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Warning: 'xx' isn't a type.
+// class xxx xx XXX extends XXX {
+//           ^^
+//
+import self as iss;
+import "dart:core" as core;
+
+class xxx extends core::Object {
+  synthetic constructor •() → iss::xxx
+    : super core::Object::•()
+    ;
+}
+static field invalid-type XXX;
+static field dynamic extends;
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect
new file mode 100644
index 0000000..b965c9b
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect
@@ -0,0 +1,73 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///issue_36647_lib1.dart";
+
+
+library;
+import self as self2;
+import "issue_36647_lib2.dart" as iss;
+additionalExports = (iss::xxx)
+, iss::XXX)
+, iss::extends)
+
+
+export "org-dartlang-testcase:///issue_36647_lib2.dart";
+
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// class xxx xx XXX extends XXX {
+//       ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
+// class xxx xx XXX extends XXX {
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected an identifier, but got 'extends'.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected ';' after this.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// class xxx xx XXX extends XXX {
+//                          ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:26: Error: 'XXX' is already declared in this scope.
+// class xxx xx XXX extends XXX {
+//                          ^^^
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Context: Previous declaration of 'XXX'.
+// class xxx xx XXX extends XXX {
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Warning: Type 'xx' not found.
+// class xxx xx XXX extends XXX {
+//           ^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Warning: 'xx' isn't a type.
+// class xxx xx XXX extends XXX {
+//           ^^
+//
+import self as iss;
+import "dart:core" as core;
+
+class xxx extends core::Object {
+  synthetic constructor •() → iss::xxx
+    : super core::Object::•()
+    ;
+}
+static field invalid-type XXX;
+static field dynamic extends;
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
new file mode 100644
index 0000000..69a888f
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
@@ -0,0 +1,68 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///issue_36647_lib1.dart";
+
+
+library;
+import self as self2;
+import "issue_36647_lib2.dart" as iss;
+additionalExports = (iss::xxx)
+, iss::XXX)
+, iss::extends)
+
+
+export "org-dartlang-testcase:///issue_36647_lib2.dart";
+
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// class xxx xx XXX extends XXX {
+//       ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
+// class xxx xx XXX extends XXX {
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected an identifier, but got 'extends'.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected ';' after this.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// class xxx xx XXX extends XXX {
+//                          ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:26: Error: 'XXX' is already declared in this scope.
+// class xxx xx XXX extends XXX {
+//                          ^^^
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Context: Previous declaration of 'XXX'.
+// class xxx xx XXX extends XXX {
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Warning: Type 'xx' not found.
+// class xxx xx XXX extends XXX {
+//           ^^
+//
+import self as iss;
+import "dart:core" as core;
+
+class xxx extends core::Object {
+  synthetic constructor •() → iss::xxx
+    ;
+}
+static field invalid-type XXX;
+static field dynamic extends;
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect b/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
new file mode 100644
index 0000000..b99e909
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
@@ -0,0 +1,73 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///issue_36647_lib1.dart";
+
+
+library;
+import self as self2;
+import "issue_36647_lib2.dart" as iss;
+additionalExports = (iss::xxx)
+, iss::XXX)
+, iss::extends)
+
+
+export "org-dartlang-testcase:///issue_36647_lib2.dart";
+
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// class xxx xx XXX extends XXX {
+//       ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
+// class xxx xx XXX extends XXX {
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected an identifier, but got 'extends'.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected ';' after this.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// class xxx xx XXX extends XXX {
+//                          ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:26: Error: 'XXX' is already declared in this scope.
+// class xxx xx XXX extends XXX {
+//                          ^^^
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Context: Previous declaration of 'XXX'.
+// class xxx xx XXX extends XXX {
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Type 'xx' not found.
+// class xxx xx XXX extends XXX {
+//           ^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: 'xx' isn't a type.
+// class xxx xx XXX extends XXX {
+//           ^^
+//
+import self as iss;
+import "dart:core" as core;
+
+class xxx extends core::Object {
+  synthetic constructor •() → iss::xxx
+    : super core::Object::•()
+    ;
+}
+static field invalid-type XXX;
+static field dynamic extends;
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
new file mode 100644
index 0000000..b99e909
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
@@ -0,0 +1,73 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///issue_36647_lib1.dart";
+
+
+library;
+import self as self2;
+import "issue_36647_lib2.dart" as iss;
+additionalExports = (iss::xxx)
+, iss::XXX)
+, iss::extends)
+
+
+export "org-dartlang-testcase:///issue_36647_lib2.dart";
+
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// class xxx xx XXX extends XXX {
+//       ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
+// class xxx xx XXX extends XXX {
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected an identifier, but got 'extends'.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected ';' after this.
+// class xxx xx XXX extends XXX {
+//                  ^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// class xxx xx XXX extends XXX {
+//                          ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:26: Error: 'XXX' is already declared in this scope.
+// class xxx xx XXX extends XXX {
+//                          ^^^
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Context: Previous declaration of 'XXX'.
+// class xxx xx XXX extends XXX {
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Type 'xx' not found.
+// class xxx xx XXX extends XXX {
+//           ^^
+//
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: 'xx' isn't a type.
+// class xxx xx XXX extends XXX {
+//           ^^
+//
+import self as iss;
+import "dart:core" as core;
+
+class xxx extends core::Object {
+  synthetic constructor •() → iss::xxx
+    : super core::Object::•()
+    ;
+}
+static field invalid-type XXX;
+static field dynamic extends;
diff --git a/pkg/front_end/testcases/regress/issue_36647_2.dart b/pkg/front_end/testcases/regress/issue_36647_2.dart
new file mode 100644
index 0000000..4096e59
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647_2.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2019, 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.
+
+export 'issue_36647_2_lib1.dart';
diff --git a/pkg/front_end/testcases/regress/issue_36647_2.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_36647_2.dart.legacy.expect
new file mode 100644
index 0000000..e040789
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647_2.dart.legacy.expect
@@ -0,0 +1,44 @@
+library;
+import self as self;
+import "issue_36647_2_lib1.dart" as iss;
+additionalExports = (iss::foo)
+, iss::bar)
+, iss::baz)
+
+
+export "org-dartlang-testcase:///issue_36647_2_lib1.dart";
+
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:6:5: Error: 'foo' is already declared in this scope.
+// int foo = 43;
+//     ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:5:5: Context: Previous declaration of 'foo'.
+// int foo = 42;
+//     ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:8:14: Error: 'bar' is already declared in this scope.
+// typedef bool bar();
+//              ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:7:14: Context: Previous declaration of 'bar'.
+// typedef bool bar();
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:13:5: Error: 'baz' is already declared in this scope.
+// int baz() {
+//     ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:9:5: Context: Previous declaration of 'baz'.
+// int baz() {
+//     ^^^
+//
+import self as iss;
+import "dart:core" as core;
+
+typedef bar = () → core::bool;
+static field core::int foo;
+static method baz() → core::int {
+  return 42;
+}
diff --git a/pkg/front_end/testcases/regress/issue_36647_2.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_36647_2.dart.legacy.transformed.expect
new file mode 100644
index 0000000..e040789
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647_2.dart.legacy.transformed.expect
@@ -0,0 +1,44 @@
+library;
+import self as self;
+import "issue_36647_2_lib1.dart" as iss;
+additionalExports = (iss::foo)
+, iss::bar)
+, iss::baz)
+
+
+export "org-dartlang-testcase:///issue_36647_2_lib1.dart";
+
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:6:5: Error: 'foo' is already declared in this scope.
+// int foo = 43;
+//     ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:5:5: Context: Previous declaration of 'foo'.
+// int foo = 42;
+//     ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:8:14: Error: 'bar' is already declared in this scope.
+// typedef bool bar();
+//              ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:7:14: Context: Previous declaration of 'bar'.
+// typedef bool bar();
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:13:5: Error: 'baz' is already declared in this scope.
+// int baz() {
+//     ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:9:5: Context: Previous declaration of 'baz'.
+// int baz() {
+//     ^^^
+//
+import self as iss;
+import "dart:core" as core;
+
+typedef bar = () → core::bool;
+static field core::int foo;
+static method baz() → core::int {
+  return 42;
+}
diff --git a/pkg/front_end/testcases/regress/issue_36647_2.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36647_2.dart.outline.expect
new file mode 100644
index 0000000..af81823
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647_2.dart.outline.expect
@@ -0,0 +1,43 @@
+library;
+import self as self;
+import "issue_36647_2_lib1.dart" as iss;
+additionalExports = (iss::foo)
+, iss::bar)
+, iss::baz)
+
+
+export "org-dartlang-testcase:///issue_36647_2_lib1.dart";
+
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:6:5: Error: 'foo' is already declared in this scope.
+// int foo = 43;
+//     ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:5:5: Context: Previous declaration of 'foo'.
+// int foo = 42;
+//     ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:8:14: Error: 'bar' is already declared in this scope.
+// typedef bool bar();
+//              ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:7:14: Context: Previous declaration of 'bar'.
+// typedef bool bar();
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:13:5: Error: 'baz' is already declared in this scope.
+// int baz() {
+//     ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:9:5: Context: Previous declaration of 'baz'.
+// int baz() {
+//     ^^^
+//
+import self as iss;
+import "dart:core" as core;
+
+typedef bar = () → core::bool;
+static field core::int foo;
+static method baz() → core::int
+  ;
diff --git a/pkg/front_end/testcases/regress/issue_36647_2.dart.strong.expect b/pkg/front_end/testcases/regress/issue_36647_2.dart.strong.expect
new file mode 100644
index 0000000..e040789
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647_2.dart.strong.expect
@@ -0,0 +1,44 @@
+library;
+import self as self;
+import "issue_36647_2_lib1.dart" as iss;
+additionalExports = (iss::foo)
+, iss::bar)
+, iss::baz)
+
+
+export "org-dartlang-testcase:///issue_36647_2_lib1.dart";
+
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:6:5: Error: 'foo' is already declared in this scope.
+// int foo = 43;
+//     ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:5:5: Context: Previous declaration of 'foo'.
+// int foo = 42;
+//     ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:8:14: Error: 'bar' is already declared in this scope.
+// typedef bool bar();
+//              ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:7:14: Context: Previous declaration of 'bar'.
+// typedef bool bar();
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:13:5: Error: 'baz' is already declared in this scope.
+// int baz() {
+//     ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:9:5: Context: Previous declaration of 'baz'.
+// int baz() {
+//     ^^^
+//
+import self as iss;
+import "dart:core" as core;
+
+typedef bar = () → core::bool;
+static field core::int foo;
+static method baz() → core::int {
+  return 42;
+}
diff --git a/pkg/front_end/testcases/regress/issue_36647_2.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_36647_2.dart.strong.transformed.expect
new file mode 100644
index 0000000..e040789
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647_2.dart.strong.transformed.expect
@@ -0,0 +1,44 @@
+library;
+import self as self;
+import "issue_36647_2_lib1.dart" as iss;
+additionalExports = (iss::foo)
+, iss::bar)
+, iss::baz)
+
+
+export "org-dartlang-testcase:///issue_36647_2_lib1.dart";
+
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:6:5: Error: 'foo' is already declared in this scope.
+// int foo = 43;
+//     ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:5:5: Context: Previous declaration of 'foo'.
+// int foo = 42;
+//     ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:8:14: Error: 'bar' is already declared in this scope.
+// typedef bool bar();
+//              ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:7:14: Context: Previous declaration of 'bar'.
+// typedef bool bar();
+//              ^^^
+//
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:13:5: Error: 'baz' is already declared in this scope.
+// int baz() {
+//     ^^^
+// pkg/front_end/testcases/regress/issue_36647_2_lib1.dart:9:5: Context: Previous declaration of 'baz'.
+// int baz() {
+//     ^^^
+//
+import self as iss;
+import "dart:core" as core;
+
+typedef bar = () → core::bool;
+static field core::int foo;
+static method baz() → core::int {
+  return 42;
+}
diff --git a/pkg/front_end/testcases/regress/issue_36647_2_lib1.dart b/pkg/front_end/testcases/regress/issue_36647_2_lib1.dart
new file mode 100644
index 0000000..b2d8d4b
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647_2_lib1.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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.
+
+int foo = 42;
+int foo = 43;
+typedef bool bar();
+typedef bool bar();
+int baz() {
+  return 42;
+}
+
+int baz() {
+  return 43;
+}
diff --git a/pkg/front_end/testcases/regress/issue_36647_lib1.dart b/pkg/front_end/testcases/regress/issue_36647_lib1.dart
new file mode 100644
index 0000000..4aef191
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647_lib1.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2019, 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.
+
+export 'issue_36647_lib2.dart';
diff --git a/pkg/front_end/testcases/regress/issue_36647_lib2.dart b/pkg/front_end/testcases/regress/issue_36647_lib2.dart
new file mode 100644
index 0000000..3960141
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647_lib2.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2019, 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.
+
+class xxx xx XXX extends XXX {
+}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart b/pkg/front_end/testcases/regress/issue_36669.dart
new file mode 100644
index 0000000..5aba8e6
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36669.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2019, 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.
+
+class NoUnnamedConstuctor {
+  NoUnnamedConstuctor._();
+}
+
+class MixMeIn {}
+
+class Foo extends NoUnnamedConstuctor with MixMeIn {}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.hierarchy.expect b/pkg/front_end/testcases/regress/issue_36669.dart.hierarchy.expect
new file mode 100644
index 0000000..b7c594c
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.hierarchy.expect
@@ -0,0 +1,114 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+NoUnnamedConstuctor:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+MixMeIn:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+NoUnnamedConstuctor with MixMeIn:
+  superclasses:
+    Object
+      -> NoUnnamedConstuctor
+  interfaces: MixMeIn
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Foo:
+  superclasses:
+    Object
+      -> NoUnnamedConstuctor
+        -> _Foo&NoUnnamedConstuctor&MixMeIn
+  interfaces: MixMeIn
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_36669.dart.legacy.expect
new file mode 100644
index 0000000..104dfea
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.legacy.expect
@@ -0,0 +1,31 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstuctor with MixMeIn', has no unnamed constructor that takes no arguments.
+// class Foo extends NoUnnamedConstuctor with MixMeIn {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class NoUnnamedConstuctor extends core::Object {
+  constructor _() → self::NoUnnamedConstuctor
+    : super core::Object::•()
+    ;
+}
+class MixMeIn extends core::Object {
+  synthetic constructor •() → self::MixMeIn
+    : super core::Object::•()
+    ;
+}
+abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn {
+  synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn
+    : super self::NoUnnamedConstuctor::_()
+    ;
+}
+class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+  synthetic constructor •() → self::Foo
+    : invalid-initializer
+    ;
+}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_36669.dart.legacy.transformed.expect
new file mode 100644
index 0000000..25e5cab
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.legacy.transformed.expect
@@ -0,0 +1,31 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstuctor with MixMeIn', has no unnamed constructor that takes no arguments.
+// class Foo extends NoUnnamedConstuctor with MixMeIn {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class NoUnnamedConstuctor extends core::Object {
+  constructor _() → self::NoUnnamedConstuctor
+    : super core::Object::•()
+    ;
+}
+class MixMeIn extends core::Object {
+  synthetic constructor •() → self::MixMeIn
+    : super core::Object::•()
+    ;
+}
+abstract class _Foo&NoUnnamedConstuctor&MixMeIn extends self::NoUnnamedConstuctor implements self::MixMeIn {
+  synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn
+    : super self::NoUnnamedConstuctor::_()
+    ;
+}
+class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+  synthetic constructor •() → self::Foo
+    : invalid-initializer
+    ;
+}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36669.dart.outline.expect
new file mode 100644
index 0000000..ea21227
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.outline.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class NoUnnamedConstuctor extends core::Object {
+  constructor _() → self::NoUnnamedConstuctor
+    ;
+}
+class MixMeIn extends core::Object {
+  synthetic constructor •() → self::MixMeIn
+    ;
+}
+abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn {
+  synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn
+    : super self::NoUnnamedConstuctor::_()
+    ;
+}
+class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+  synthetic constructor •() → self::Foo
+    ;
+}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.strong.expect b/pkg/front_end/testcases/regress/issue_36669.dart.strong.expect
new file mode 100644
index 0000000..104dfea
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.strong.expect
@@ -0,0 +1,31 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstuctor with MixMeIn', has no unnamed constructor that takes no arguments.
+// class Foo extends NoUnnamedConstuctor with MixMeIn {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class NoUnnamedConstuctor extends core::Object {
+  constructor _() → self::NoUnnamedConstuctor
+    : super core::Object::•()
+    ;
+}
+class MixMeIn extends core::Object {
+  synthetic constructor •() → self::MixMeIn
+    : super core::Object::•()
+    ;
+}
+abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn {
+  synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn
+    : super self::NoUnnamedConstuctor::_()
+    ;
+}
+class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+  synthetic constructor •() → self::Foo
+    : invalid-initializer
+    ;
+}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_36669.dart.strong.transformed.expect
new file mode 100644
index 0000000..25e5cab
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstuctor with MixMeIn', has no unnamed constructor that takes no arguments.
+// class Foo extends NoUnnamedConstuctor with MixMeIn {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class NoUnnamedConstuctor extends core::Object {
+  constructor _() → self::NoUnnamedConstuctor
+    : super core::Object::•()
+    ;
+}
+class MixMeIn extends core::Object {
+  synthetic constructor •() → self::MixMeIn
+    : super core::Object::•()
+    ;
+}
+abstract class _Foo&NoUnnamedConstuctor&MixMeIn extends self::NoUnnamedConstuctor implements self::MixMeIn {
+  synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn
+    : super self::NoUnnamedConstuctor::_()
+    ;
+}
+class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+  synthetic constructor •() → self::Foo
+    : invalid-initializer
+    ;
+}
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart b/pkg/front_end/testcases/regress/issue_36793.dart
new file mode 100644
index 0000000..1601a23
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36793.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, 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.
+
+const int y = 42;
+
+@y
+int x = 1;
+@y
+int x = 2;
+
+main() {
+  print(y);
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect
new file mode 100644
index 0000000..69ebf3f
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect
@@ -0,0 +1,20 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36793.dart:10:5: Error: 'x' is already declared in this scope.
+// int x = 2;
+//     ^
+// pkg/front_end/testcases/regress/issue_36793.dart:8:5: Context: Previous declaration of 'x'.
+// int x = 1;
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::int y = 42;
+@self::y
+static field core::int x;
+static method main() → dynamic {
+  core::print(self::y);
+}
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect
new file mode 100644
index 0000000..69ebf3f
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect
@@ -0,0 +1,20 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36793.dart:10:5: Error: 'x' is already declared in this scope.
+// int x = 2;
+//     ^
+// pkg/front_end/testcases/regress/issue_36793.dart:8:5: Context: Previous declaration of 'x'.
+// int x = 1;
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::int y = 42;
+@self::y
+static field core::int x;
+static method main() → dynamic {
+  core::print(self::y);
+}
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
new file mode 100644
index 0000000..bd4a7de
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
@@ -0,0 +1,19 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36793.dart:10:5: Error: 'x' is already declared in this scope.
+// int x = 2;
+//     ^
+// pkg/front_end/testcases/regress/issue_36793.dart:8:5: Context: Previous declaration of 'x'.
+// int x = 1;
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::int y = 42;
+@self::y
+static field core::int x;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect b/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect
new file mode 100644
index 0000000..69ebf3f
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect
@@ -0,0 +1,20 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36793.dart:10:5: Error: 'x' is already declared in this scope.
+// int x = 2;
+//     ^
+// pkg/front_end/testcases/regress/issue_36793.dart:8:5: Context: Previous declaration of 'x'.
+// int x = 1;
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::int y = 42;
+@self::y
+static field core::int x;
+static method main() → dynamic {
+  core::print(self::y);
+}
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect
new file mode 100644
index 0000000..69ebf3f
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect
@@ -0,0 +1,20 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_36793.dart:10:5: Error: 'x' is already declared in this scope.
+// int x = 2;
+//     ^
+// pkg/front_end/testcases/regress/issue_36793.dart:8:5: Context: Previous declaration of 'x'.
+// int x = 1;
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::int y = 42;
+@self::y
+static field core::int x;
+static method main() → dynamic {
+  core::print(self::y);
+}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart
deleted file mode 100644
index 7797a4a..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/*@testedFeatures=checks*/
-library test;
-
-typedef void F<T>(T t);
-
-void expectTypeError(void callback()) {
-  try {
-    callback();
-    throw 'Expected TypeError, did not occur';
-  } on TypeError {}
-}
-
-void expect(Object value, Object expected) {
-  if (value != expected) {
-    throw 'Expected $expected, got $value';
-  }
-}
-
-class B {
-  F<int> get x {
-    throw 'Should not be reached';
-  }
-
-  void set x(Object value) {
-    throw 'Should not be reached';
-  }
-}
-
-abstract class I<T> {
-  F<T> get x;
-  void set x(Object value);
-}
-
-abstract class M<T> {
-  T get x => f();
-  void set x(Object value) {
-    throw 'Should not be reached';
-  }
-
-  T f();
-}
-
-abstract class C<T> = B with M<F<T>> implements I<T>;
-
-class D extends C<int> {
-  F<int> f() => (int i) {
-        expect(i, 1);
-      };
-}
-
-void test(I<Object> iObj, I<int> iInt) {
-  expectTypeError(() {
-    // iObj.x is expected to return type (Object) -> void, but it returns
-    // (int) -> void (which is a supertype of (Object) -> void), so that's a
-    // type error.
-    var x = iObj. /*@checkReturn=(Object) -> void*/ x;
-  });
-  // iInt.x is expected to return type (int) -> void, and it does.
-  var x = iInt. /*@checkReturn=(int) -> void*/ x;
-  x(1);
-}
-
-void main() {
-  var d = new D();
-  test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.hierarchy.expect
deleted file mode 100644
index dc66ff9..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.hierarchy.expect
+++ /dev/null
@@ -1,150 +0,0 @@
-Object:
-  superclasses:
-  interfaces:
-  classMembers:
-    Object._haveSameRuntimeType
-    Object.toString
-    Object.runtimeType
-    Object._toString
-    Object._simpleInstanceOf
-    Object._hashCodeRnd
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._objectHashCode
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-B:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    Object.toString
-    B.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-    B.x
-
-I:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    Object.toString
-    I.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-    I.x
-
-M:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    M.f
-    Object.toString
-    M.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-    M.x
-
-C:
-  superclasses:
-    Object
-      -> B
-  interfaces: M<F<T>>, I<T>
-  classMembers:
-    M.f
-    Object.toString
-    M.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-    M.x
-  interfaceMembers:
-    M.f
-    Object.toString
-    M.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
-    M.x
-
-D:
-  superclasses:
-    Object
-      -> B
-        -> C<int>
-  interfaces: M<F<int>>, I<int>
-  classMembers:
-    D.f
-    Object.toString
-    M.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-    M.x
-  interfaceMembers:
-    D.f
-    Object.toString
-    M.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
-    M.x
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.expect
deleted file mode 100644
index 0546d0e..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.expect
+++ /dev/null
@@ -1,72 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
-  synthetic constructor •() → self::B
-    : super core::Object::•()
-    ;
-  get x() → (core::int) → void {
-    throw "Should not be reached";
-  }
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract get x() → (self::I::T) → void;
-  abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::M<self::M::T>
-    : super core::Object::•()
-    ;
-  get x() → self::M::T
-    return this.{self::M::f}();
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-  abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> = self::B with self::M<(self::C::T) → void> implements self::I<self::C::T> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-class D extends self::C<core::int> {
-  synthetic constructor •() → self::D
-    : super self::C::•()
-    ;
-  method f() → (core::int) → void
-    return (core::int i) → dynamic {
-      self::expect(i, 1);
-    };
-}
-static method expectTypeError(() → void callback) → void {
-  try {
-    callback.call();
-    throw "Expected TypeError, did not occur";
-  }
-  on core::TypeError catch(no-exception-var) {
-  }
-}
-static method expect(core::Object value, core::Object expected) → void {
-  if(!value.==(expected)) {
-    throw "Expected ${expected}, got ${value}";
-  }
-}
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void {
-  self::expectTypeError(() → dynamic {
-    dynamic x = iObj.x;
-  });
-  dynamic x = iInt.x;
-  x.call(1);
-}
-static method main() → void {
-  dynamic d = new self::D::•();
-  self::test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.transformed.expect
deleted file mode 100644
index 839a7dc..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,78 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
-  synthetic constructor •() → self::B
-    : super core::Object::•()
-    ;
-  get x() → (core::int) → void {
-    throw "Should not be reached";
-  }
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract get x() → (self::I::T) → void;
-  abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::M<self::M::T>
-    : super core::Object::•()
-    ;
-  get x() → self::M::T
-    return this.{self::M::f}();
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-  abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B implements self::I<self::C::T>, self::M<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  get x() → (self::C::T) → void
-    return this.{self::M::f}();
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-  abstract method f() → (self::C::T) → void;
-}
-class D extends self::C<core::int> {
-  synthetic constructor •() → self::D
-    : super self::C::•()
-    ;
-  method f() → (core::int) → void
-    return (core::int i) → dynamic {
-      self::expect(i, 1);
-    };
-}
-static method expectTypeError(() → void callback) → void {
-  try {
-    callback.call();
-    throw "Expected TypeError, did not occur";
-  }
-  on core::TypeError catch(no-exception-var) {
-  }
-}
-static method expect(core::Object value, core::Object expected) → void {
-  if(!value.==(expected)) {
-    throw "Expected ${expected}, got ${value}";
-  }
-}
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void {
-  self::expectTypeError(() → dynamic {
-    dynamic x = iObj.x;
-  });
-  dynamic x = iInt.x;
-  x.call(1);
-}
-static method main() → void {
-  dynamic d = new self::D::•();
-  self::test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.outline.expect
deleted file mode 100644
index e432df6..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.outline.expect
+++ /dev/null
@@ -1,47 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
-  synthetic constructor •() → self::B
-    ;
-  get x() → (core::int) → void
-    ;
-  set x(core::Object value) → void
-    ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    ;
-  abstract get x() → (self::I::T) → void;
-  abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::M<self::M::T>
-    ;
-  get x() → self::M::T
-    ;
-  set x(core::Object value) → void
-    ;
-  abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> = self::B with self::M<(self::C::T) → void> implements self::I<self::C::T> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-class D extends self::C<core::int> {
-  synthetic constructor •() → self::D
-    ;
-  method f() → (core::int) → void
-    ;
-}
-static method expectTypeError(() → void callback) → void
-  ;
-static method expect(core::Object value, core::Object expected) → void
-  ;
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void
-  ;
-static method main() → void
-  ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
deleted file mode 100644
index 450603a..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
+++ /dev/null
@@ -1,86 +0,0 @@
-library test;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:39:9: Error: The return type of the method 'M.x' is 'void Function(T)', which does not match the return type, 'void Function(int)', of the overridden method, 'B.x'.
-// Change to a subtype of 'void Function(int)'.
-//   T get x => f();
-//         ^
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:24:14: Context: This is the overridden method ('x').
-//   F<int> get x {
-//              ^
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:47:16: Context: Override was introduced in the mixin application class 'C'.
-// abstract class C<T> = B with M<F<T>> implements I<T>;
-//                ^
-//
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
-  synthetic constructor •() → self::B
-    : super core::Object::•()
-    ;
-  get x() → (core::int) → void {
-    throw "Should not be reached";
-  }
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract get x() → (self::I::T) → void;
-  abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::M<self::M::T>
-    : super core::Object::•()
-    ;
-  get x() → self::M::T
-    return this.{self::M::f}();
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-  abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> = self::B with self::M<(self::C::T) → void> implements self::I<self::C::T> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-class D extends self::C<core::int> {
-  synthetic constructor •() → self::D
-    : super self::C::•()
-    ;
-  method f() → (core::int) → void
-    return (core::int i) → core::Null {
-      self::expect(i, 1);
-    };
-}
-static method expectTypeError(() → void callback) → void {
-  try {
-    callback.call();
-    throw "Expected TypeError, did not occur";
-  }
-  on core::TypeError catch(no-exception-var) {
-  }
-}
-static method expect(core::Object value, core::Object expected) → void {
-  if(!value.{core::Object::==}(expected)) {
-    throw "Expected ${expected}, got ${value}";
-  }
-}
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void {
-  self::expectTypeError(() → core::Null {
-    (core::Object) → void x = iObj.{self::I::x} as{TypeError} (core::Object) → void;
-  });
-  (core::int) → void x = iInt.{self::I::x} as{TypeError} (core::int) → void;
-  x.call(1);
-}
-static method main() → void {
-  self::D d = new self::D::•();
-  self::test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart
deleted file mode 100644
index fc4ec48..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/*@testedFeatures=checks*/
-library test;
-
-typedef void F<T>(T t);
-
-class B<T> {
-  T f(int x) {}
-}
-
-abstract class I<T> {
-  T f(Object x);
-}
-
-abstract class C<T> extends B<F<T>> implements I<F<T>> {}
-
-void main() {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
deleted file mode 100644
index 6f7dc10..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
+++ /dev/null
@@ -1,87 +0,0 @@
-Object:
-  superclasses:
-  interfaces:
-  classMembers:
-    Object._haveSameRuntimeType
-    Object.toString
-    Object.runtimeType
-    Object._toString
-    Object._simpleInstanceOf
-    Object._hashCodeRnd
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._objectHashCode
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-B:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-I:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    I.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-C:
-  superclasses:
-    Object
-      -> B<F<T>>
-  interfaces: I<F<T>>
-  classMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-  interfaceMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.expect
deleted file mode 100644
index 7d32948..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.transformed.expect
deleted file mode 100644
index 7d32948..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.outline.expect
deleted file mode 100644
index 6b7705e..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.outline.expect
+++ /dev/null
@@ -1,22 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    ;
-  method f(core::int x) → self::B::T
-    ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    ;
-  abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    ;
-}
-static method main() → void
-  ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.expect
deleted file mode 100644
index c8ec998..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.expect
+++ /dev/null
@@ -1,24 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  abstract forwarding-stub method f(core::Object x) → (self::C::T) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.transformed.expect
deleted file mode 100644
index c8ec998..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.transformed.expect
+++ /dev/null
@@ -1,24 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  abstract forwarding-stub method f(core::Object x) → (self::C::T) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart
deleted file mode 100644
index bf9a66b..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/*@testedFeatures=checks*/
-library test;
-
-typedef void F<T>(T t);
-
-class B<T> {
-  void f(F<T> x, int y) {}
-}
-
-abstract class I<T> {
-  void f(F<T> x, Object y);
-}
-
-abstract class C<T> extends B<F<T>> implements I<F<T>> {}
-
-void main() {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.hierarchy.expect
deleted file mode 100644
index 6f7dc10..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.hierarchy.expect
+++ /dev/null
@@ -1,87 +0,0 @@
-Object:
-  superclasses:
-  interfaces:
-  classMembers:
-    Object._haveSameRuntimeType
-    Object.toString
-    Object.runtimeType
-    Object._toString
-    Object._simpleInstanceOf
-    Object._hashCodeRnd
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._objectHashCode
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-B:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-I:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    I.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-C:
-  superclasses:
-    Object
-      -> B<F<T>>
-  interfaces: I<F<T>>
-  classMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-  interfaceMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.expect
deleted file mode 100644
index 5e95811..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.transformed.expect
deleted file mode 100644
index 5e95811..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.outline.expect
deleted file mode 100644
index 5526106..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.outline.expect
+++ /dev/null
@@ -1,22 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    ;
-  method f((self::B::T) → void x, core::int y) → void
-    ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    ;
-}
-static method main() → void
-  ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.expect
deleted file mode 100644
index 14a514f..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.expect
+++ /dev/null
@@ -1,25 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void
-    return super.{self::B::f}(x, y);
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.transformed.expect
deleted file mode 100644
index 14a514f..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.transformed.expect
+++ /dev/null
@@ -1,25 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void
-    return super.{self::B::f}(x, y);
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart
deleted file mode 100644
index 3b2bac1..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/*@testedFeatures=checks*/
-library test;
-
-typedef void F<T>(T t);
-
-abstract class A<T> {
-  void f(T x, int y);
-}
-
-class B<T> implements A<F<T>> {
-  void f(F<T> x, int y) {}
-}
-
-abstract class I<T> implements A<F<T>> {
-  void f(F<T> x, Object y);
-}
-
-abstract class C<T> extends B<F<T>> implements I<F<T>> {}
-
-void main() {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect
deleted file mode 100644
index dfb9fc6..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect
+++ /dev/null
@@ -1,134 +0,0 @@
-Object:
-  superclasses:
-  interfaces:
-  classMembers:
-    Object._haveSameRuntimeType
-    Object.toString
-    Object.runtimeType
-    Object._toString
-    Object._simpleInstanceOf
-    Object._hashCodeRnd
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._objectHashCode
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-A:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    A.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-B:
-  Longest path to Object: 2
-  superclasses:
-    Object
-  interfaces: A<F<T>>
-  classMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-  interfaceMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
-
-I:
-  Longest path to Object: 2
-  superclasses:
-    Object
-  interfaces: A<F<T>>
-  classMembers:
-    I.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-  interfaceMembers:
-    I.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
-
-C:
-  Longest path to Object: 3
-  superclasses:
-    Object
-      -> B<F<T>>
-  interfaces: A<F<F<T>>>, I<F<T>>
-  classMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-  interfaceMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.expect
deleted file mode 100644
index df1249c..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.expect
+++ /dev/null
@@ -1,29 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.transformed.expect
deleted file mode 100644
index df1249c..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,29 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.outline.expect
deleted file mode 100644
index c638537..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.outline.expect
+++ /dev/null
@@ -1,27 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    ;
-  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
-  synthetic constructor •() → self::B<self::B::T>
-    ;
-  method f((self::B::T) → void x, core::int y) → void
-    ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
-  synthetic constructor •() → self::I<self::I::T>
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    ;
-}
-static method main() → void
-  ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.expect
deleted file mode 100644
index fd2002b..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.expect
+++ /dev/null
@@ -1,30 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(generic-covariant-impl (self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl (self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  abstract forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.transformed.expect
deleted file mode 100644
index fd2002b..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.transformed.expect
+++ /dev/null
@@ -1,30 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(generic-covariant-impl (self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl (self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  abstract forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 7b802de..79ac736 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -33,6 +33,7 @@
 inference/constructors_too_many_positional_arguments: InstrumentationMismatch # Issue #30040
 inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer: TypeCheckError
 inference/downwards_inference_annotations_type_variable: InstrumentationMismatch # Issue 28981
+inference/downwards_inference_for_each: RuntimeError # Issue #36382
 inference/downwards_inference_on_function_of_t_using_the_t: InstrumentationMismatch # Issue #29798
 inference/downwards_inference_on_list_literals_infer_downwards: RuntimeError
 inference/future_then_explicit_future: InstrumentationMismatch # Issue #30040
@@ -86,7 +87,7 @@
 rasta/abstract_constructor: RuntimeError
 rasta/bad_constructor_redirection: RuntimeError
 rasta/bad_continue: RuntimeError
-rasta/bad_default_constructor: VerificationError
+rasta/bad_default_constructor: RuntimeError
 rasta/bad_explicit_super_constructor: RuntimeError
 rasta/bad_implicit_super_constructor: RuntimeError
 rasta/bad_interpolation: RuntimeError
@@ -105,7 +106,7 @@
 rasta/issue_000032: RuntimeError
 rasta/issue_000034: RuntimeError
 rasta/issue_000036: RuntimeError
-rasta/issue_000039: VerificationError
+rasta/issue_000039: RuntimeError
 rasta/issue_000041: RuntimeError
 rasta/issue_000042: RuntimeError
 rasta/issue_000043: RuntimeError
@@ -142,6 +143,9 @@
 regress/issue_35260: RuntimeError # Expected
 regress/issue_35266: RuntimeError # Expected
 regress/issue_36400: RuntimeError
+regress/issue_36647: RuntimeError # Expected
+regress/issue_36647_2: RuntimeError # Expected
+regress/issue_36669: RuntimeError
 reject_generic_function_types_in_bounds: RuntimeError # Expected
 runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast: RuntimeError
 runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
@@ -150,6 +154,7 @@
 set_literals/disambiguation_rule: RuntimeError
 spread_collection: RuntimeError
 statements: Crash
+type_parameter_type_named_int: RuntimeError # Expected
 type_variable_as_super: RuntimeError
 unsound_promotion: RuntimeError
 void_methods: ExpectationFileMismatch
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 9da7144..a32cc66 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -25,6 +25,7 @@
 await: TextSerializationFailure # Was: Pass
 bad_setter_abstract: TextSerializationFailure # Was: Pass
 bad_store: TextSerializationFailure # Was: Pass
+bad_type_variable_uses_in_supertypes: TextSerializationFailure
 bounds_check_depends_on_inference: TextSerializationFailure # Was: Pass
 bug21938: TypeCheckError
 bug30695: TypeCheckError
@@ -660,6 +661,7 @@
 instantiate_to_bound/non_simple_variables_from_same: TextSerializationFailure # Was: Pass
 instantiate_to_bound/omitted_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/raw_in_bound: TextSerializationFailure # Was: Pass
+instantiate_to_bound/super_bounded_in_bound: TextSerializationFailure
 instantiate_to_bound/super_bounded_type: TextSerializationFailure # Was: Pass
 instantiate_to_bound/supertypes: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_instantiated_in_outline: TextSerializationFailure # Was: Pass
@@ -669,6 +671,9 @@
 instantiate_to_bound/typedef_omitted_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_raw_in_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_super_bounded_type: TextSerializationFailure # Was: Pass
+interface_contravariant_from_class: TextSerializationFailure
+interface_covariantImpl_from_class: TextSerializationFailure
+interface_covariantInterface_from_class: TextSerializationFailure
 invalid_assignment: TextSerializationFailure # Was: Pass
 invalid_cast: TextSerializationFailure # Was: Pass
 invalid_type: TypeCheckError
@@ -676,6 +681,7 @@
 issue34515: TextSerializationFailure
 issue34899: TypeCheckError
 issue35875: TextSerializationFailure
+issue37027: TextSerializationFailure
 literals: TextSerializationFailure # Was: Pass
 local_generic_function: TextSerializationFailure # Was: Pass
 magic_const: TextSerializationFailure # Was: Pass
@@ -752,7 +758,7 @@
 rasta/abstract_constructor: TextSerializationFailure # Was: RuntimeError
 rasta/bad_constructor_redirection: TextSerializationFailure # Was: RuntimeError
 rasta/bad_continue: TextSerializationFailure # Was: RuntimeError
-rasta/bad_default_constructor: VerificationError
+rasta/bad_default_constructor: TextSerializationFailure
 rasta/bad_explicit_super_constructor: TextSerializationFailure # Was: RuntimeError
 rasta/bad_implicit_super_constructor: TextSerializationFailure # Was: RuntimeError
 rasta/bad_interpolation: TextSerializationFailure # Was: RuntimeError
@@ -792,7 +798,7 @@
 rasta/issue_000035: TextSerializationFailure # Was: Pass
 rasta/issue_000035a: TextSerializationFailure # Was: Pass
 rasta/issue_000036: TextSerializationFailure # Was: RuntimeError
-rasta/issue_000039: VerificationError
+rasta/issue_000039: TextSerializationFailure
 rasta/issue_000041: TextSerializationFailure # Was: RuntimeError
 rasta/issue_000042: TextSerializationFailure # Was: RuntimeError
 rasta/issue_000043: TextSerializationFailure # Was: RuntimeError
@@ -920,6 +926,10 @@
 regress/issue_35266: TextSerializationFailure # Was: RuntimeError # Expected
 regress/issue_35900: TextSerializationFailure
 regress/issue_36400: TextSerializationFailure
+regress/issue_36647: TextSerializationFailure
+regress/issue_36647_2: TextSerializationFailure
+regress/issue_36669: TextSerializationFailure
+regress/issue_36793: TextSerializationFailure
 reject_generic_function_types_in_bounds: TextSerializationFailure # Was: RuntimeError # Expected
 return_with_unknown_type_in_context: TextSerializationFailure # Was: Pass
 runtime_checks/call_kinds: TextSerializationFailure # Was: Pass
@@ -1004,6 +1014,7 @@
 top_level_accessors_part: TextSerializationFailure # Was: Pass
 top_level_library_method: TextSerializationFailure # Was: Pass
 type_of_null: TextSerializationFailure
+type_parameter_type_named_int: TextSerializationFailure
 type_variable_as_super: TextSerializationFailure # Was: RuntimeError
 type_variable_prefix: TextSerializationFailure # Was: RuntimeError
 type_variable_uses: TextSerializationFailure # Was: Pass
diff --git a/pkg/front_end/testcases/type_parameter_type_named_int.dart b/pkg/front_end/testcases/type_parameter_type_named_int.dart
new file mode 100644
index 0000000..af96c11
--- /dev/null
+++ b/pkg/front_end/testcases/type_parameter_type_named_int.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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.
+
+abstract class Foo<T> {
+  List<T> get list;
+  void setList<T>(List<T> value);
+}
+
+class Bar implements Foo<int> {
+  List<int> list;
+  void setList<int>(List<int> value) {
+    list = value;
+  }
+}
diff --git a/pkg/front_end/testcases/type_parameter_type_named_int.dart.hierarchy.expect b/pkg/front_end/testcases/type_parameter_type_named_int.dart.hierarchy.expect
new file mode 100644
index 0000000..e128e2e
--- /dev/null
+++ b/pkg/front_end/testcases/type_parameter_type_named_int.dart.hierarchy.expect
@@ -0,0 +1,74 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Foo:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Foo.list
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Foo.setList
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Bar:
+  Longest path to Object: 2
+  superclasses:
+    Object
+  interfaces: Foo<int>
+  classMembers:
+    Bar.list
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Bar.setList
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+    Bar.list
+  interfaceMembers:
+    Bar.list
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Bar.setList
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+    Bar.list
diff --git a/pkg/front_end/testcases/type_parameter_type_named_int.dart.legacy.expect b/pkg/front_end/testcases/type_parameter_type_named_int.dart.legacy.expect
new file mode 100644
index 0000000..1e2cdd2
--- /dev/null
+++ b/pkg/front_end/testcases/type_parameter_type_named_int.dart.legacy.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Foo<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Foo<self::Foo::T>
+    : super core::Object::•()
+    ;
+  abstract get list() → core::List<self::Foo::T>;
+  abstract method setList<T extends core::Object = dynamic>(core::List<self::Foo::setList::T> value) → void;
+}
+class Bar extends core::Object implements self::Foo<core::int> {
+  field core::List<core::int> list = null;
+  synthetic constructor •() → self::Bar
+    : super core::Object::•()
+    ;
+  method setList<int extends core::Object = dynamic>(core::List<self::Bar::setList::int> value) → void {
+    this.{self::Bar::list} = value;
+  }
+}
diff --git a/pkg/front_end/testcases/type_parameter_type_named_int.dart.legacy.transformed.expect b/pkg/front_end/testcases/type_parameter_type_named_int.dart.legacy.transformed.expect
new file mode 100644
index 0000000..1e2cdd2
--- /dev/null
+++ b/pkg/front_end/testcases/type_parameter_type_named_int.dart.legacy.transformed.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Foo<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Foo<self::Foo::T>
+    : super core::Object::•()
+    ;
+  abstract get list() → core::List<self::Foo::T>;
+  abstract method setList<T extends core::Object = dynamic>(core::List<self::Foo::setList::T> value) → void;
+}
+class Bar extends core::Object implements self::Foo<core::int> {
+  field core::List<core::int> list = null;
+  synthetic constructor •() → self::Bar
+    : super core::Object::•()
+    ;
+  method setList<int extends core::Object = dynamic>(core::List<self::Bar::setList::int> value) → void {
+    this.{self::Bar::list} = value;
+  }
+}
diff --git a/pkg/front_end/testcases/type_parameter_type_named_int.dart.outline.expect b/pkg/front_end/testcases/type_parameter_type_named_int.dart.outline.expect
new file mode 100644
index 0000000..c6ca162
--- /dev/null
+++ b/pkg/front_end/testcases/type_parameter_type_named_int.dart.outline.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Foo<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Foo<self::Foo::T>
+    ;
+  abstract get list() → core::List<self::Foo::T>;
+  abstract method setList<T extends core::Object = dynamic>(core::List<self::Foo::setList::T> value) → void;
+}
+class Bar extends core::Object implements self::Foo<core::int> {
+  field core::List<core::int> list;
+  synthetic constructor •() → self::Bar
+    ;
+  method setList<int extends core::Object = dynamic>(core::List<self::Bar::setList::int> value) → void
+    ;
+}
diff --git a/pkg/front_end/testcases/type_parameter_type_named_int.dart.strong.expect b/pkg/front_end/testcases/type_parameter_type_named_int.dart.strong.expect
new file mode 100644
index 0000000..37066d6
--- /dev/null
+++ b/pkg/front_end/testcases/type_parameter_type_named_int.dart.strong.expect
@@ -0,0 +1,37 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/type_parameter_type_named_int.dart:13:12: Error: A value of type 'List<int/*1*/>' can't be assigned to a variable of type 'List<int/*2*/>'.
+//  - 'List' is from 'dart:core'.
+//  - 'int/*1*/' is from 'pkg/front_end/testcases/type_parameter_type_named_int.dart'.
+//  - 'int/*2*/' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'List<int/*2*/>'.
+//     list = value;
+//            ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Foo<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Foo<self::Foo::T>
+    : super core::Object::•()
+    ;
+  abstract get list() → core::List<self::Foo::T>;
+  abstract method setList<T extends core::Object = dynamic>(core::List<self::Foo::setList::T> value) → void;
+}
+class Bar extends core::Object implements self::Foo<core::int> {
+  field core::List<core::int> list = null;
+  synthetic constructor •() → self::Bar
+    : super core::Object::•()
+    ;
+  method setList<int extends core::Object = dynamic>(core::List<self::Bar::setList::int> value) → void {
+    this.{self::Bar::list} = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/type_parameter_type_named_int.dart:13:12: Error: A value of type 'List<int/*1*/>' can't be assigned to a variable of type 'List<int/*2*/>'.
+ - 'List' is from 'dart:core'.
+ - 'int/*1*/' is from 'pkg/front_end/testcases/type_parameter_type_named_int.dart'.
+ - 'int/*2*/' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'List<int/*2*/>'.
+    list = value;
+           ^" in value as{TypeError} core::List<core::int>;
+  }
+}
diff --git a/pkg/front_end/testcases/type_parameter_type_named_int.dart.strong.transformed.expect b/pkg/front_end/testcases/type_parameter_type_named_int.dart.strong.transformed.expect
new file mode 100644
index 0000000..37066d6
--- /dev/null
+++ b/pkg/front_end/testcases/type_parameter_type_named_int.dart.strong.transformed.expect
@@ -0,0 +1,37 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/type_parameter_type_named_int.dart:13:12: Error: A value of type 'List<int/*1*/>' can't be assigned to a variable of type 'List<int/*2*/>'.
+//  - 'List' is from 'dart:core'.
+//  - 'int/*1*/' is from 'pkg/front_end/testcases/type_parameter_type_named_int.dart'.
+//  - 'int/*2*/' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'List<int/*2*/>'.
+//     list = value;
+//            ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Foo<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Foo<self::Foo::T>
+    : super core::Object::•()
+    ;
+  abstract get list() → core::List<self::Foo::T>;
+  abstract method setList<T extends core::Object = dynamic>(core::List<self::Foo::setList::T> value) → void;
+}
+class Bar extends core::Object implements self::Foo<core::int> {
+  field core::List<core::int> list = null;
+  synthetic constructor •() → self::Bar
+    : super core::Object::•()
+    ;
+  method setList<int extends core::Object = dynamic>(core::List<self::Bar::setList::int> value) → void {
+    this.{self::Bar::list} = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/type_parameter_type_named_int.dart:13:12: Error: A value of type 'List<int/*1*/>' can't be assigned to a variable of type 'List<int/*2*/>'.
+ - 'List' is from 'dart:core'.
+ - 'int/*1*/' is from 'pkg/front_end/testcases/type_parameter_type_named_int.dart'.
+ - 'int/*2*/' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'List<int/*2*/>'.
+    list = value;
+           ^" in value as{TypeError} core::List<core::int>;
+  }
+}
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index a3cd069..18b7445 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -192,6 +192,7 @@
     // TODO(ahe): Extend this entry point so it can replace
     // batchEntryPoint.
     new IncrementalCompiler(c);
+    return Future<void>.value();
   });
 }
 
diff --git a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
new file mode 100644
index 0000000..355836a
--- /dev/null
+++ b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2019, 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:io';
+
+import 'dart:isolate';
+
+import 'package:yaml/yaml.dart' show YamlMap, loadYaml;
+
+import 'package:dart_style/dart_style.dart' show DartFormatter;
+
+import '../../lib/src/fasta/scanner/characters.dart' show $A, $MINUS, $a, $z;
+
+main(List<String> arguments) async {
+  var port = new ReceivePort();
+  await new File.fromUri(await computeGeneratedFile())
+      .writeAsString(await generateMessagesFile(), flush: true);
+  port.close();
+}
+
+Future<Uri> computeGeneratedFile() {
+  return Isolate.resolvePackageUri(
+      Uri.parse('package:front_end/src/api_prototype/experimental_flags.dart'));
+}
+
+Future<String> generateMessagesFile() async {
+  Uri messagesFile =
+      Platform.script.resolve("../../../../tools/experimental_features.yaml");
+  Map<dynamic, dynamic> yaml =
+      loadYaml(await new File.fromUri(messagesFile).readAsStringSync());
+  StringBuffer sb = new StringBuffer();
+
+  sb.write('''
+// Copyright (c) 2018, 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.
+
+// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Instead modify 'tools/experimental_features.yaml' and run
+// 'pkg/front_end/tool/fasta generate-experimental-flags' to update.
+''');
+
+  List<String> keys = yaml.keys.cast<String>().toList()..sort();
+
+  sb.write('''
+
+enum ExperimentalFlag {
+''');
+  for (var key in keys) {
+    sb.writeln('  ${keyToIdentifier(key)},');
+  }
+  sb.writeln('}');
+
+  sb.write('''
+
+ExperimentalFlag parseExperimentalFlag(String flag) {
+  switch (flag) {
+''');
+  for (var key in keys) {
+    sb.writeln('    case "$key":');
+    sb.writeln('     return ExperimentalFlag.${keyToIdentifier(key)};');
+  }
+  sb.write('''  }
+  return null;
+}
+''');
+
+  sb.write('''
+
+const Map<ExperimentalFlag, bool> defaultExperimentalFlags = {
+''');
+  for (var key in keys) {
+    bool shipped = (yaml[key] as YamlMap)['enabledIn'] != null;
+    sb.writeln('  ExperimentalFlag.${keyToIdentifier(key)}: ${shipped},');
+    if (shipped) {
+      var expired = (yaml[key] as YamlMap)['expired'];
+      if (expired == false) {
+        throw 'Cannot mark shipped feature as "expired: false"';
+      }
+    }
+  }
+  sb.writeln('};');
+
+  return new DartFormatter().format("$sb");
+}
+
+keyToIdentifier(String key) {
+  var identifier = StringBuffer();
+  for (int index = 0; index < key.length; ++index) {
+    var code = key.codeUnitAt(index);
+    if (code == $MINUS) {
+      ++index;
+      code = key.codeUnitAt(index);
+      if ($a <= code && code <= $z) {
+        code = code - $a + $A;
+      }
+    }
+    identifier.writeCharCode(code);
+  }
+  return identifier.toString();
+}
diff --git a/pkg/front_end/tool/_fasta/generate_experimental_flags_test.dart b/pkg/front_end/tool/_fasta/generate_experimental_flags_test.dart
new file mode 100644
index 0000000..81fdca0
--- /dev/null
+++ b/pkg/front_end/tool/_fasta/generate_experimental_flags_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2018, 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:io" show File;
+
+import "package:async_helper/async_helper.dart" show asyncTest;
+
+import "package:expect/expect.dart" show Expect;
+
+import "generate_experimental_flags.dart"
+    show computeGeneratedFile, generateMessagesFile;
+
+main() {
+  asyncTest(() async {
+    Uri generatedFile = await computeGeneratedFile();
+    String generated = await generateMessagesFile();
+    String actual = (await new File.fromUri(generatedFile).readAsString())
+        .replaceAll('\r\n', '\n');
+    Expect.stringEquals(
+        generated, actual, "${generatedFile.path} is out of date");
+  });
+}
diff --git a/pkg/front_end/tool/fasta b/pkg/front_end/tool/fasta
index 65b9ec4..aa970c3 100755
--- a/pkg/front_end/tool/fasta
+++ b/pkg/front_end/tool/fasta
@@ -55,6 +55,7 @@
     set -- "$@" "--config=${REPO_DIR}/pkg/front_end/testing.json"
     ;;
   generate-messages) SCRIPT="${TOOL_DIR}/generate_messages.dart";;
+  generate-experimental-flags) SCRIPT="${TOOL_DIR}/generate_experimental_flags.dart";;
   *)
     stop "'$1' isn't a valid subcommand."
     ;;
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index bd1ed2c..0ba6da6 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.dart
@@ -217,7 +217,7 @@
 
   // Note: this method converts the body to kernel, so we skip that here.
   @override
-  finishFunction(annotations, formals, asyncModifier, body) {}
+  finishFunction(formals, asyncModifier, body) {}
 }
 
 // Invoke the fasta kernel generator for the program starting in [entryUri]
diff --git a/pkg/front_end/tool/perf.dart b/pkg/front_end/tool/perf.dart
index 553ffc6..b216937 100644
--- a/pkg/front_end/tool/perf.dart
+++ b/pkg/front_end/tool/perf.dart
@@ -18,6 +18,7 @@
 import 'dart:async';
 import 'dart:io' show Directory, File, Platform, exit;
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/physical_file_system.dart'
@@ -100,9 +101,9 @@
 /// Uses the diet-parser to parse only directives in [source].
 CompilationUnit parseDirectives(Source source) {
   var token = tokenize(source);
-  // TODO(jcollins-g): Make parser work with Fasta
-  var parser =
-      new Parser(source, AnalysisErrorListener.NULL_LISTENER, useFasta: false);
+  var featureSet = FeatureSet.fromEnableFlags([]);
+  var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER,
+      featureSet: featureSet);
   return parser.parseDirectives(token);
 }
 
@@ -122,7 +123,9 @@
 CompilationUnit parseFull(Source source) {
   var token = tokenize(source);
   parseTimer.start();
-  var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
+  var featureSet = FeatureSet.fromEnableFlags([]);
+  var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER,
+      featureSet: featureSet);
   var unit = parser.parseCompilationUnit(token);
   parseTimer.stop();
   return unit;
diff --git a/pkg/js_ast/lib/src/builder.dart b/pkg/js_ast/lib/src/builder.dart
index 635549b..bf9e94a 100644
--- a/pkg/js_ast/lib/src/builder.dart
+++ b/pkg/js_ast/lib/src/builder.dart
@@ -1029,15 +1029,15 @@
     AsyncModifier asyncModifier;
     if (acceptString('async')) {
       if (acceptString('*')) {
-        asyncModifier = const AsyncModifier.asyncStar();
+        asyncModifier = AsyncModifier.asyncStar;
       } else {
-        asyncModifier = const AsyncModifier.async();
+        asyncModifier = AsyncModifier.async;
       }
     } else if (acceptString('sync')) {
       if (!acceptString('*')) error("Only sync* is valid - sync is implied");
-      asyncModifier = const AsyncModifier.syncStar();
+      asyncModifier = AsyncModifier.syncStar;
     } else {
-      asyncModifier = const AsyncModifier.sync();
+      asyncModifier = AsyncModifier.sync;
     }
     expectCategory(LBRACE);
     Block block = parseBlock();
diff --git a/pkg/js_ast/lib/src/nodes.dart b/pkg/js_ast/lib/src/nodes.dart
index 0bec49b..d2970d4 100644
--- a/pkg/js_ast/lib/src/nodes.dart
+++ b/pkg/js_ast/lib/src/nodes.dart
@@ -981,7 +981,7 @@
 /// In particular, there is no guarantee that implementations of [compareTo]
 /// will implement some form of lexicographic ordering like [String.compareTo].
 abstract class Name extends Literal
-    implements Declaration, Parameter, Comparable {
+    implements Declaration, Parameter, Comparable<Name> {
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitName(this);
 
   R accept1<R, A>(NodeVisitor1<R, A> visitor, A arg) =>
@@ -1448,7 +1448,7 @@
   final Block body;
   final AsyncModifier asyncModifier;
 
-  Fun(this.params, this.body, {this.asyncModifier: const AsyncModifier.sync()});
+  Fun(this.params, this.body, {this.asyncModifier: AsyncModifier.sync});
 
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitFun(this);
 
@@ -1471,27 +1471,26 @@
 }
 
 class AsyncModifier {
+  final int index;
   final bool isAsync;
   final bool isYielding;
   final String description;
 
-  const AsyncModifier.sync()
-      : isAsync = false,
-        isYielding = false,
-        description = "sync";
-  const AsyncModifier.async()
-      : isAsync = true,
-        isYielding = false,
-        description = "async";
-  const AsyncModifier.asyncStar()
-      : isAsync = true,
-        isYielding = true,
-        description = "async*";
-  const AsyncModifier.syncStar()
-      : isAsync = false,
-        isYielding = true,
-        description = "sync*";
-  toString() => description;
+  const AsyncModifier(this.index, this.description,
+      {this.isAsync, this.isYielding});
+
+  static const AsyncModifier sync =
+      const AsyncModifier(0, "sync", isAsync: false, isYielding: false);
+  static const AsyncModifier async =
+      const AsyncModifier(1, "async", isAsync: true, isYielding: false);
+  static const AsyncModifier asyncStar =
+      const AsyncModifier(2, "async*", isAsync: true, isYielding: true);
+  static const AsyncModifier syncStar =
+      const AsyncModifier(3, "sync*", isAsync: false, isYielding: true);
+
+  static const List<AsyncModifier> values = [sync, async, asyncStar, syncStar];
+
+  String toString() => description;
 }
 
 class PropertyAccess extends Expression {
@@ -1750,10 +1749,11 @@
 }
 
 class Property extends Node {
-  final Literal name;
+  final Expression name;
   final Expression value;
 
-  Property(this.name, this.value);
+  Property(this.name, this.value)
+      : assert(name is Literal || name is DeferredExpression);
 
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitProperty(this);
 
@@ -1987,3 +1987,9 @@
 
   void visitChildren1<R, A>(NodeVisitor1<R, A> visitor, A arg) {}
 }
+
+/// Returns the value of [node] if it is a [DeferredExpression]. Otherwise
+/// returns the [node] itself.
+Node undefer(Node node) {
+  return node is DeferredExpression ? undefer(node.value) : node;
+}
diff --git a/pkg/js_ast/lib/src/printer.dart b/pkg/js_ast/lib/src/printer.dart
index 9ff26a6..399ab56 100644
--- a/pkg/js_ast/lib/src/printer.dart
+++ b/pkg/js_ast/lib/src/printer.dart
@@ -12,7 +12,7 @@
   final bool preferSemicolonToNewlineInMinifiedOutput;
   final Renamer renamerForNames;
 
-  JavaScriptPrintingOptions(
+  const JavaScriptPrintingOptions(
       {this.shouldCompressOutput: false,
       this.minifyLocalVariables: false,
       this.preferSemicolonToNewlineInMinifiedOutput: false,
@@ -223,6 +223,9 @@
 
   void startNode(Node node) {
     currentNode = new EnterExitNode(currentNode, node);
+    if (node is DeferredExpression) {
+      startNode(node.value);
+    }
   }
 
   void enterNode() {
@@ -230,6 +233,9 @@
   }
 
   void endNode(Node node) {
+    if (node is DeferredExpression) {
+      endNode(node.value);
+    }
     assert(currentNode.node == node);
     currentNode = currentNode.exitNode(context, _charCount);
   }
@@ -614,17 +620,17 @@
     }
     out(")");
     switch (fun.asyncModifier) {
-      case const AsyncModifier.sync():
+      case AsyncModifier.sync:
         break;
-      case const AsyncModifier.async():
+      case AsyncModifier.async:
         out(' ', isWhitespace: true);
         out('async');
         break;
-      case const AsyncModifier.syncStar():
+      case AsyncModifier.syncStar:
         out(' ', isWhitespace: true);
         out('sync*');
         break;
-      case const AsyncModifier.asyncStar():
+      case AsyncModifier.asyncStar:
         out(' ', isWhitespace: true);
         out('async*');
         break;
@@ -715,7 +721,7 @@
 
   static bool _isSmallInitialization(Node node) {
     if (node is VariableInitialization) {
-      Node value = node.value;
+      Node value = undefer(node.value);
       if (value == null) return true;
       if (value is This) return true;
       if (value is LiteralNull) return true;
@@ -723,17 +729,79 @@
       if (value is LiteralString && value.value.length <= 8) return true;
       if (value is ObjectInitializer && value.properties.isEmpty) return true;
       if (value is ArrayInitializer && value.elements.isEmpty) return true;
+      if (value is Name && value.name.length <= 8) return true;
     }
     return false;
   }
 
+  void _outputIncDec(String op, Expression variable, [Expression alias]) {
+    if (op == '+') {
+      if (lastCharCode == charCodes.$PLUS) out(" ", isWhitespace: true);
+      out('++');
+    } else {
+      if (lastCharCode == charCodes.$MINUS) out(" ", isWhitespace: true);
+      out('--');
+    }
+    if (alias != null) startNode(alias);
+    visitNestedExpression(variable, UNARY,
+        newInForInit: inForInit, newAtStatementBegin: false);
+    if (alias != null) endNode(alias);
+  }
+
   @override
   visitAssignment(Assignment assignment) {
+    /// To print assignments like `a = a + 1` and `a = a + b` compactly as
+    /// `++a` and `a += b` in the face of [DeferredExpression]s we detect the
+    /// pattern of the undeferred assignment.
+    String op = assignment.op;
+    Node leftHandSide = undefer(assignment.leftHandSide);
+    Node rightHandSide = undefer(assignment.value);
+    if ((op == '+' || op == '-') &&
+        leftHandSide is VariableUse &&
+        rightHandSide is LiteralNumber &&
+        rightHandSide.value == "1") {
+      // Output 'a += 1' as '++a' and 'a -= 1' as '--a'.
+      _outputIncDec(op, assignment.leftHandSide);
+      return;
+    } else if (leftHandSide is VariableUse && rightHandSide is Binary) {
+      Node rLeft = undefer(rightHandSide.left);
+      Node rRight = undefer(rightHandSide.right);
+      String op = rightHandSide.op;
+      if (op == '+' ||
+          op == '-' ||
+          op == '/' ||
+          op == '*' ||
+          op == '%' ||
+          op == '^' ||
+          op == '&' ||
+          op == '|') {
+        if (rLeft is VariableUse && rLeft.name == leftHandSide.name) {
+          // Output 'a = a + 1' as '++a' and 'a = a - 1' as '--a'.
+          if ((op == '+' || op == '-') &&
+              rRight is LiteralNumber &&
+              rRight.value == "1") {
+            _outputIncDec(op, assignment.leftHandSide, rightHandSide.left);
+            return;
+          }
+          // Output 'a = a + b' as 'a += b'.
+          startNode(rightHandSide.left);
+          visitNestedExpression(assignment.leftHandSide, CALL,
+              newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
+          endNode(rightHandSide.left);
+          spaceOut();
+          out(op);
+          out("=");
+          spaceOut();
+          visitNestedExpression(rRight, ASSIGNMENT,
+              newInForInit: inForInit, newAtStatementBegin: false);
+          return;
+        }
+      }
+    }
     visitNestedExpression(assignment.leftHandSide, CALL,
         newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
     if (assignment.value != null) {
       spaceOut();
-      String op = assignment.op;
       if (op != null) out(op);
       out("=");
       spaceOut();
@@ -972,34 +1040,33 @@
   void visitAccess(PropertyAccess access) {
     visitNestedExpression(access.receiver, CALL,
         newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
-    Node selector = access.selector;
+    Node selector = undefer(access.selector);
     if (selector is LiteralString) {
-      LiteralString selectorString = selector;
-      String fieldWithQuotes = selectorString.value;
+      String fieldWithQuotes = selector.value;
       if (isValidJavaScriptId(fieldWithQuotes)) {
         if (access.receiver is LiteralNumber &&
             lastCharCode != charCodes.$CLOSE_PAREN) {
           out(" ", isWhitespace: true);
         }
         out(".");
-        startNode(selector);
+        startNode(access.selector);
         out(fieldWithQuotes.substring(1, fieldWithQuotes.length - 1));
-        endNode(selector);
+        endNode(access.selector);
         return;
       }
     } else if (selector is Name) {
-      if (access.receiver is LiteralNumber &&
-          lastCharCode != charCodes.$CLOSE_PAREN) {
+      Node receiver = undefer(access.receiver);
+      if (receiver is LiteralNumber && lastCharCode != charCodes.$CLOSE_PAREN) {
         out(" ", isWhitespace: true);
       }
       out(".");
-      startNode(selector);
+      startNode(access.selector);
       selector.accept(this);
-      endNode(selector);
+      endNode(access.selector);
       return;
     }
     out("[");
-    visitNestedExpression(selector, EXPRESSION,
+    visitNestedExpression(access.selector, EXPRESSION,
         newInForInit: false, newAtStatementBegin: false);
     out("]");
   }
@@ -1156,18 +1223,18 @@
   @override
   void visitProperty(Property node) {
     startNode(node.name);
-    if (node.name is LiteralString) {
-      LiteralString nameString = node.name;
-      String name = nameString.value;
-      if (isValidJavaScriptId(name)) {
-        out(name.substring(1, name.length - 1));
+    Node name = undefer(node.name);
+    if (name is LiteralString) {
+      String text = name.value;
+      if (isValidJavaScriptId(text)) {
+        out(text.substring(1, text.length - 1));
       } else {
-        out(name);
+        out(text);
       }
-    } else if (node.name is Name) {
+    } else if (name is Name) {
       node.name.accept(this);
     } else {
-      assert(node.name is LiteralNumber);
+      assert(name is LiteralNumber);
       LiteralNumber nameNumber = node.name;
       out(nameNumber.value);
     }
diff --git a/pkg/js_ast/lib/src/template.dart b/pkg/js_ast/lib/src/template.dart
index 0503e9f..a7dcf48 100644
--- a/pkg/js_ast/lib/src/template.dart
+++ b/pkg/js_ast/lib/src/template.dart
@@ -236,7 +236,7 @@
     var nameOrPosition = node.nameOrPosition;
     return (arguments) {
       var value = arguments[nameOrPosition];
-      if (value is Literal) return value;
+      if (value is Literal || value is DeferredExpression) return value;
       error('Interpolated value #$nameOrPosition is not a Literal: $value');
     };
   }
diff --git a/pkg/js_ast/test/deferred_expression_test.dart b/pkg/js_ast/test/deferred_expression_test.dart
new file mode 100644
index 0000000..397aaaa
--- /dev/null
+++ b/pkg/js_ast/test/deferred_expression_test.dart
@@ -0,0 +1,160 @@
+// Copyright (c) 2019, 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';
+import 'package:js_ast/js_ast.dart';
+
+main() {
+  Map<Expression, DeferredExpression> map = {};
+  VariableUse variableUse = new VariableUse('variable');
+  DeferredExpression deferred =
+      map[variableUse] = new _DeferredExpression(variableUse);
+  VariableUse variableUseAlias = new VariableUse('variable');
+  map[variableUseAlias] = new _DeferredExpression(variableUseAlias);
+
+  map[deferred] = new _DeferredExpression(deferred);
+  Literal literal = new LiteralString('"literal"');
+  map[literal] = new _DeferredExpression(literal);
+
+  test(map, '#', [variableUse], 'variable');
+  test(map, '#', [deferred], 'variable');
+  test(map, '{#: #}', [literal, variableUse], '{literal: variable}');
+  test(map, '{#: #}', [literal, deferred], '{literal: variable}');
+  test(map, '#.#', [variableUse, literal], 'variable.literal');
+  test(map, '#.#', [deferred, literal], 'variable.literal');
+  test(map, '# = # + 1', [variableUse, variableUseAlias], '++variable');
+  test(map, '# = # + 1', [deferred, variableUseAlias], '++variable');
+  test(map, '# = # - 1', [variableUse, variableUseAlias], '--variable');
+  test(map, '# = # - 1', [deferred, variableUseAlias], '--variable');
+  test(map, '# = # + 2', [variableUse, variableUseAlias], 'variable += 2');
+  test(map, '# = # + 2', [deferred, variableUseAlias], 'variable += 2');
+}
+
+void test(Map<Expression, DeferredExpression> map, String template,
+    List<Expression> arguments, String expectedOutput) {
+  Expression directExpression =
+      js.expressionTemplateFor(template).instantiate(arguments);
+  _Context directContext = new _Context();
+  Printer directPrinter =
+      new Printer(const JavaScriptPrintingOptions(), directContext);
+  directPrinter.visit(directExpression);
+  Expect.equals(expectedOutput, directContext.text);
+
+  Expression deferredExpression = js
+      .expressionTemplateFor(template)
+      .instantiate(arguments.map((e) => map[e]).toList());
+  _Context deferredContext = new _Context();
+  Printer deferredPrinter =
+      new Printer(const JavaScriptPrintingOptions(), deferredContext);
+  deferredPrinter.visit(deferredExpression);
+  Expect.equals(expectedOutput, deferredContext.text);
+
+  for (Expression argument in arguments) {
+    DeferredExpression deferred = map[argument];
+    Expect.isTrue(
+        directContext.enterPositions.containsKey(argument),
+        "Argument ${DebugPrint(argument)} not found in direct enter positions: "
+        "${directContext.enterPositions.keys}");
+    Expect.isTrue(
+        deferredContext.enterPositions.containsKey(argument),
+        "Argument ${DebugPrint(argument)} not found in "
+        "deferred enter positions: "
+        "${deferredContext.enterPositions.keys}");
+    Expect.isTrue(
+        deferredContext.enterPositions.containsKey(deferred),
+        "Argument ${DebugPrint(deferred)} not found in "
+        "deferred enter positions: "
+        "${deferredContext.enterPositions.keys}");
+    Expect.equals(directContext.enterPositions[argument],
+        deferredContext.enterPositions[argument]);
+    Expect.equals(directContext.enterPositions[argument],
+        deferredContext.enterPositions[deferred]);
+
+    Expect.isTrue(
+        directContext.exitPositions.containsKey(argument),
+        "Argument ${DebugPrint(argument)} not found in direct enter positions: "
+        "${directContext.exitPositions.keys}");
+    Expect.isTrue(
+        deferredContext.exitPositions.containsKey(argument),
+        "Argument ${DebugPrint(argument)} not found in "
+        "deferred enter positions: "
+        "${deferredContext.exitPositions.keys}");
+    Expect.isTrue(
+        deferredContext.exitPositions.containsKey(deferred),
+        "Argument ${DebugPrint(deferred)} not found in "
+        "deferred enter positions: "
+        "${deferredContext.exitPositions.keys}");
+    Expect.equals(directContext.exitPositions[argument],
+        deferredContext.exitPositions[argument]);
+    Expect.equals(directContext.exitPositions[argument],
+        deferredContext.exitPositions[deferred]);
+  }
+}
+
+class _DeferredExpression extends DeferredExpression {
+  final Expression value;
+
+  _DeferredExpression(this.value);
+
+  @override
+  int get precedenceLevel => value.precedenceLevel;
+}
+
+class _Context implements JavaScriptPrintingContext {
+  StringBuffer sb = new StringBuffer();
+  List<String> errors = [];
+  Map<Node, int> enterPositions = {};
+  Map<Node, _Position> exitPositions = {};
+
+  @override
+  void emit(String string) {
+    sb.write(string);
+  }
+
+  @override
+  void enterNode(Node node, int startPosition) {
+    enterPositions[node] = startPosition;
+  }
+
+  @override
+  void exitNode(
+      Node node, int startPosition, int endPosition, int closingPosition) {
+    exitPositions[node] =
+        new _Position(startPosition, endPosition, closingPosition);
+    Expect.equals(enterPositions[node], startPosition);
+  }
+
+  @override
+  void error(String message) {
+    errors.add(message);
+  }
+
+  String get text => sb.toString();
+}
+
+class _Position {
+  final int startPosition;
+  final int endPosition;
+  final int closingPosition;
+
+  _Position(this.startPosition, this.endPosition, this.closingPosition);
+
+  int get hashCode =>
+      13 * startPosition.hashCode +
+      17 * endPosition.hashCode +
+      19 * closingPosition.hashCode;
+
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return other is _Position &&
+        startPosition == other.startPosition &&
+        endPosition == other.endPosition &&
+        closingPosition == other.closingPosition;
+  }
+
+  String toString() {
+    return '_Position(start=$startPosition,'
+        'end=$endPosition,closing=$closingPosition)';
+  }
+}
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index d64034e..6b247af 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -87,7 +87,7 @@
 }
 
 type ConstantReference {
-  UInt index; // Index into the Component's constants.
+  UInt offset; // Byte offset into the Component's constants.
 }
 
 type SourceInfo {
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index f8709b7..0a9e01b 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -192,6 +192,11 @@
   Uri get fileUri;
 }
 
+abstract class Annotatable {
+  List<Expression> get annotations;
+  void addAnnotation(Expression node);
+}
+
 /// Indirection between a reference and its definition.
 ///
 /// There is only one reference object per [NamedNode].
@@ -267,7 +272,8 @@
 // ------------------------------------------------------------------------
 
 @coq
-class Library extends NamedNode implements Comparable<Library>, FileUriNode {
+class Library extends NamedNode
+    implements Annotatable, Comparable<Library>, FileUriNode {
   /// An import path to this library.
   ///
   /// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme.
@@ -721,7 +727,7 @@
 /// rule directly, as doing so can obstruct transformations.  It is possible to
 /// transform a mixin application to become a regular class, and vice versa.
 @coq
-class Class extends NamedNode implements FileUriNode {
+class Class extends NamedNode implements Annotatable, FileUriNode {
   /// Start offset of the class in the source file it comes from.
   ///
   /// Note that this includes annotations if any.
@@ -1086,7 +1092,7 @@
 // ------------------------------------------------------------------------
 
 @coq
-abstract class Member extends NamedNode implements FileUriNode {
+abstract class Member extends NamedNode implements Annotatable, FileUriNode {
   /// End offset in the source file it comes from.
   ///
   /// Valid values are from 0 and up, or -1 ([TreeNode.noOffset]) if the file
@@ -3215,9 +3221,9 @@
 ///
 /// If [lists] is empty then an empty list is returned.
 ///
-/// These arise from spread and control-flow elements in const list literals
-/// containing unevaluated subexpressions. They only ever occur within
-/// unevaluated constants in constant expressions.
+/// These arise from spread and control-flow elements in const list literals.
+/// They are only present before constant evaluation, or within unevaluated
+/// constants in constant expressions.
 class ListConcatenation extends Expression {
   DartType typeArgument;
   final List<Expression> lists;
@@ -3248,9 +3254,9 @@
 ///
 /// If [sets] is empty then an empty set is returned.
 ///
-/// These arise from spread and control-flow elements in const set literals
-/// containing unevaluated subexpressions. They only ever occur within
-/// unevaluated constants in constant expressions.
+/// These arise from spread and control-flow elements in const set literals.
+/// They are only present before constant evaluation, or within unevaluated
+/// constants in constant expressions.
 ///
 /// Duplicated values in or across the sets will result in a compile-time error
 /// during constant evaluation.
@@ -3284,9 +3290,9 @@
 ///
 /// If [maps] is empty then an empty map is returned.
 ///
-/// These arise from spread and control-flow elements in const map literals
-/// containing unevaluated subexpressions. They only ever occur within
-/// unevaluated constants in constant expressions.
+/// These arise from spread and control-flow elements in const map literals.
+/// They are only present before constant evaluation, or within unevaluated
+/// constants in constant expressions.
 ///
 /// Duplicated keys in or across the maps will result in a compile-time error
 /// during constant evaluation.
@@ -6022,8 +6028,11 @@
   /// Return the text corresponding to [line] which is a 1-based line
   /// number. The returned line contains no line separators.
   String getTextLine(int line) {
+    if (source == null ||
+        source.isEmpty ||
+        lineStarts == null ||
+        lineStarts.isEmpty) return null;
     RangeError.checkValueInInterval(line, 1, lineStarts.length, 'line');
-    if (source == null || source.isEmpty) return null;
 
     cachedText ??= utf8.decode(source, allowMalformed: true);
     // -1 as line numbers start at 1.
@@ -6047,6 +6056,9 @@
 
   /// Translates an offset to line and column numbers in the given file.
   Location getLocation(Uri file, int offset) {
+    if (lineStarts == null || lineStarts.isEmpty) {
+      return new Location(file, TreeNode.noOffset, TreeNode.noOffset);
+    }
     RangeError.checkValueInInterval(offset, 0, lineStarts.last, 'offset');
     int low = 0, high = lineStarts.length - 1;
     while (low < high) {
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 6526e31..905363a 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -39,6 +39,10 @@
   CanonicalNameError(this.message);
 }
 
+class CanonicalNameSdkError extends CanonicalNameError {
+  CanonicalNameSdkError(String message) : super(message);
+}
+
 class _ComponentIndex {
   static const numberOfFixedFields = 9;
 
@@ -76,14 +80,19 @@
   List<String> debugPath = <String>[];
 
   bool _isReadingLibraryImplementation = false;
+  final bool alwaysCreateNewNamedNodes;
 
   /// If binary contains metadata section with payloads referencing other nodes
   /// such Kernel binary can't be read lazily because metadata cross references
   /// will not be resolved correctly.
   bool _disableLazyReading = false;
 
-  BinaryBuilder(this._bytes, {this.filename, disableLazyReading = false})
-      : _disableLazyReading = disableLazyReading;
+  BinaryBuilder(this._bytes,
+      {this.filename,
+      bool disableLazyReading = false,
+      bool alwaysCreateNewNamedNodes})
+      : _disableLazyReading = disableLazyReading,
+        this.alwaysCreateNewNamedNodes = alwaysCreateNewNamedNodes ?? false;
 
   fail(String message) {
     throw ParseError(message,
@@ -523,8 +532,8 @@
               // OK then.
               checkReferenceNode = false;
             } else {
-              throw new CanonicalNameError(
-                  "Null reference (${child.name}) ($child).");
+              throw buildCanonicalNameError(
+                  "Null reference (${child.name}) ($child).", child);
             }
           }
           if (checkReferenceNode) {
@@ -533,8 +542,8 @@
                   "Canonical name and reference doesn't agree.");
             }
             if (child.reference.node == null) {
-              throw new CanonicalNameError(
-                  "Reference is null (${child.name}) ($child).");
+              throw buildCanonicalNameError(
+                  "Reference is null (${child.name}) ($child).", child);
             }
           }
         }
@@ -543,6 +552,17 @@
     }
   }
 
+  CanonicalNameError buildCanonicalNameError(
+      String message, CanonicalName problemNode) {
+    // Special-case missing sdk entries as that is probably a change to the
+    // platform - that's something we might want to react differently to.
+    String libraryUri = problemNode?.nonRootTop?.name ?? "";
+    if (libraryUri.startsWith("dart:")) {
+      return new CanonicalNameSdkError(message);
+    }
+    return new CanonicalNameError(message);
+  }
+
   _ComponentIndex _readComponentIndex(int componentFileSize) {
     int savedByteIndex = _byteOffset;
 
@@ -803,6 +823,9 @@
     var canonicalName = readCanonicalNameReference();
     Reference reference = canonicalName.getReference();
     Library library = reference.node;
+    if (alwaysCreateNewNamedNodes) {
+      library = null;
+    }
     bool shouldWriteData = library == null || _isReadingLibraryImplementation;
     if (library == null) {
       library =
@@ -923,6 +946,9 @@
     var canonicalName = readCanonicalNameReference();
     var reference = canonicalName.getReference();
     Typedef node = reference.node;
+    if (alwaysCreateNewNamedNodes) {
+      node = null;
+    }
     bool shouldWriteData = node == null || _isReadingLibraryImplementation;
     if (node == null) {
       node = new Typedef(null, null, reference: reference);
@@ -968,6 +994,9 @@
     var canonicalName = readCanonicalNameReference();
     var reference = canonicalName.getReference();
     Class node = reference.node;
+    if (alwaysCreateNewNamedNodes) {
+      node = null;
+    }
     bool shouldWriteData = node == null || _isReadingLibraryImplementation;
     if (node == null) {
       node = new Class(reference: reference)..level = ClassLevel.Temporary;
@@ -1040,6 +1069,9 @@
     var canonicalName = readCanonicalNameReference();
     var reference = canonicalName.getReference();
     Field node = reference.node;
+    if (alwaysCreateNewNamedNodes) {
+      node = null;
+    }
     bool shouldWriteData = node == null || _isReadingLibraryImplementation;
     if (node == null) {
       node = new Field(null, reference: reference);
@@ -1079,6 +1111,9 @@
     var canonicalName = readCanonicalNameReference();
     var reference = canonicalName.getReference();
     Constructor node = reference.node;
+    if (alwaysCreateNewNamedNodes) {
+      node = null;
+    }
     bool shouldWriteData = node == null || _isReadingLibraryImplementation;
     if (node == null) {
       node = new Constructor(null, reference: reference);
@@ -1125,6 +1160,9 @@
     var canonicalName = readCanonicalNameReference();
     var reference = canonicalName.getReference();
     Procedure node = reference.node;
+    if (alwaysCreateNewNamedNodes) {
+      node = null;
+    }
     bool shouldWriteData = node == null || _isReadingLibraryImplementation;
     if (node == null) {
       node = new Procedure(null, null, null, reference: reference);
@@ -1184,6 +1222,9 @@
     var canonicalName = readCanonicalNameReference();
     var reference = canonicalName.getReference();
     RedirectingFactoryConstructor node = reference.node;
+    if (alwaysCreateNewNamedNodes) {
+      node = null;
+    }
     bool shouldWriteData = node == null || _isReadingLibraryImplementation;
     if (node == null) {
       node = new RedirectingFactoryConstructor(null, reference: reference);
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 4b3434c..0292314 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -37,6 +37,7 @@
   BufferedSink _constantsSink;
   BufferedSink _sink;
   bool includeSources;
+  bool includeOffsets;
 
   List<int> libraryOffsets;
   List<int> classOffsets;
@@ -57,7 +58,9 @@
   /// The BinaryPrinter will use its own buffer, so the [sink] does not need
   /// one.
   BinaryPrinter(Sink<List<int>> sink,
-      {StringIndexer stringIndexer, this.includeSources = true})
+      {StringIndexer stringIndexer,
+      this.includeSources = true,
+      this.includeOffsets = true})
       : _mainSink = new BufferedSink(sink),
         _metadataSink = new BufferedSink(new BytesSink()),
         _constantsBytesSink = new BytesSink(),
@@ -875,7 +878,11 @@
     // TODO(jensj): Delta-encoding.
     // File offset ranges from -1 and up,
     // but is here saved as unsigned (thus the +1)
-    writeUInt30(offset + 1);
+    if (!includeOffsets) {
+      writeUInt30(0);
+    } else {
+      writeUInt30(offset + 1);
+    }
   }
 
   void writeClassReference(Class class_) {
diff --git a/pkg/kernel/lib/binary/limited_ast_to_binary.dart b/pkg/kernel/lib/binary/limited_ast_to_binary.dart
index 0cef7c7..104cfe6 100644
--- a/pkg/kernel/lib/binary/limited_ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/limited_ast_to_binary.dart
@@ -23,8 +23,11 @@
   final bool excludeUriToSource;
 
   LimitedBinaryPrinter(
-      Sink<List<int>> sink, this.predicate, this.excludeUriToSource)
-      : super(sink, includeSources: !excludeUriToSource);
+      Sink<List<int>> sink, this.predicate, this.excludeUriToSource,
+      {bool includeOffsets = true})
+      : super(sink,
+            includeSources: !excludeUriToSource,
+            includeOffsets: includeOffsets);
 
   @override
   void computeCanonicalNames(Component component) {
diff --git a/pkg/kernel/lib/canonical_name.dart b/pkg/kernel/lib/canonical_name.dart
index 20bf36c..76fd5d8 100644
--- a/pkg/kernel/lib/canonical_name.dart
+++ b/pkg/kernel/lib/canonical_name.dart
@@ -123,6 +123,10 @@
         .getChildFromQualifiedName(member.name);
   }
 
+  CanonicalName getChildFromFieldWithName(Name name) {
+    return getChild('@fields').getChildFromQualifiedName(name);
+  }
+
   CanonicalName getChildFromTypedef(Typedef typedef_) {
     return getChild('@typedefs').getChild(typedef_.name);
   }
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 51f0730..474f907 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -810,9 +810,23 @@
       _buildInterfaceMembers(class_, info, setters: false);
     }
 
+    assert(sanityCheckAlsoKnowsParentAndLibrary());
+
     return this;
   }
 
+  bool sanityCheckAlsoKnowsParentAndLibrary() {
+    for (Class c in _infoFor.keys) {
+      if (!knownLibraries.contains(c.enclosingLibrary)) {
+        throw new StateError("Didn't know library of $c (from ${c.fileUri})");
+      }
+      if (c.supertype != null && _infoFor[c.supertype.classNode] == null) {
+        throw new StateError("Didn't know parent of $c (from ${c.fileUri})");
+      }
+    }
+    return true;
+  }
+
   @override
   Supertype asInstantiationOf(Supertype type, Class superclass) {
     // This is similar to getTypeAsInstanceOf, except that it assumes that
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 47521ca..c5c5363 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -11,8 +11,9 @@
 
 class TargetFlags {
   final bool legacyMode;
+  final bool trackWidgetCreation;
 
-  TargetFlags({this.legacyMode: false});
+  TargetFlags({this.legacyMode = false, this.trackWidgetCreation = false});
 }
 
 typedef Target _TargetBuilder(TargetFlags flags);
@@ -56,6 +57,15 @@
 
   /// Number semantics to use for this backend.
   NumberSemantics get numberSemantics => NumberSemantics.vm;
+
+  /// Inline control of constant variables. The given constant expression
+  /// is the initializer of a [Field] or [VariableDeclaration] node.
+  /// If this method returns `true`, the variable will be inlined at all
+  /// points of reference and the variable itself removed (unless overridden
+  /// by the `keepFields` or `keepVariables` flag to the constant transformer).
+  /// This method must be deterministic, i.e. it must always return the same
+  /// value for the same constant value and place in the AST.
+  bool shouldInlineConstant(ConstantExpression initializer) => true;
 }
 
 /// A target provides backend-specific options for generating kernel IR.
@@ -115,6 +125,15 @@
   /// slowing down compilation.
   void performOutlineTransformations(Component component) {}
 
+  /// Perform target-specific transformations on the given libraries that must
+  /// run before constant evaluation.
+  void performPreConstantEvaluationTransformations(
+      Component component,
+      CoreTypes coreTypes,
+      List<Library> libraries,
+      DiagnosticReporter diagnosticReporter,
+      {void logger(String msg)}) {}
+
   /// Perform target-specific modular transformations on the given libraries.
   void performModularTransformationsOnLibraries(
       Component component,
diff --git a/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart b/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
new file mode 100644
index 0000000..13bde9a
--- /dev/null
+++ b/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
@@ -0,0 +1,562 @@
+// Copyright (c) 2019, 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 kernel.transformations.track_widget_constructor_locations;
+
+import 'package:meta/meta.dart';
+
+import '../ast.dart';
+
+// Parameter name used to track were widget constructor calls were made from.
+//
+// The parameter name contains a randomly generate hex string to avoid collision
+// with user generated parameters.
+const String _creationLocationParameterName =
+    r'$creationLocationd_0dea112b090073317d4';
+
+/// Name of private field added to the Widget class and any other classes that
+/// implement Widget.
+///
+/// Regardless of what library a class implementing Widget is defined in, the
+/// private field will always be defined in the context of the widget_inspector
+/// library ensuring no name conflicts with regular fields.
+const String _locationFieldName = r'_location';
+
+bool _hasNamedParameter(FunctionNode function, String name) {
+  return function.namedParameters
+      .any((VariableDeclaration parameter) => parameter.name == name);
+}
+
+bool _hasNamedArgument(Arguments arguments, String argumentName) {
+  return arguments.named
+      .any((NamedExpression argument) => argument.name == argumentName);
+}
+
+VariableDeclaration _getNamedParameter(
+  FunctionNode function,
+  String parameterName,
+) {
+  for (VariableDeclaration parameter in function.namedParameters) {
+    if (parameter.name == parameterName) {
+      return parameter;
+    }
+  }
+  return null;
+}
+
+// TODO(jacobr): find a solution that supports optional positional parameters.
+/// Add the creation location to the arguments list if possible.
+///
+/// Returns whether the creation location argument could be added. We cannot
+/// currently add the named argument for functions with optional positional
+/// parameters as the current scheme requires adding the creation location as a
+/// named parameter. Fortunately that is not a significant issue in practice as
+/// no Widget classes in package:flutter have optional positional parameters.
+/// This code degrades gracefully for constructors with optional positional
+/// parameters by skipping adding the creation location argument rather than
+/// failing.
+void _maybeAddCreationLocationArgument(
+  Arguments arguments,
+  FunctionNode function,
+  Expression creationLocation,
+  Class locationClass,
+) {
+  if (_hasNamedArgument(arguments, _creationLocationParameterName)) {
+    return;
+  }
+  if (!_hasNamedParameter(function, _creationLocationParameterName)) {
+    // TODO(jakemac): We don't apply the transformation to dependencies kernel
+    // outlines, so instead we just assume the named parameter exists.
+    //
+    // The only case in which it shouldn't exist is if the function has optional
+    // positional parameters so it cannot have optional named parameters.
+    if (function.requiredParameterCount !=
+        function.positionalParameters.length) {
+      return;
+    }
+  }
+
+  final NamedExpression namedArgument =
+      new NamedExpression(_creationLocationParameterName, creationLocation);
+  namedArgument.parent = arguments;
+  arguments.named.add(namedArgument);
+}
+
+/// Adds a named parameter to a function if the function does not already have
+/// a named parameter with the name or optional positional parameters.
+bool _maybeAddNamedParameter(
+  FunctionNode function,
+  VariableDeclaration variable,
+) {
+  if (_hasNamedParameter(function, _creationLocationParameterName)) {
+    // Gracefully handle if this method is called on a function that has already
+    // been transformed.
+    return false;
+  }
+  // Function has optional positional parameters so cannot have optional named
+  // parameters.
+  if (function.requiredParameterCount != function.positionalParameters.length) {
+    return false;
+  }
+  variable.parent = function;
+  function.namedParameters.add(variable);
+  return true;
+}
+
+/// Transformer that modifies all calls to Widget constructors to include
+/// a [DebugLocation] parameter specifying the location where the constructor
+/// call was made.
+///
+/// This transformer requires that all Widget constructors have already been
+/// transformed to have a named parameter with the name specified by
+/// `_locationParameterName`.
+class _WidgetCallSiteTransformer extends Transformer {
+  /// The [Widget] class defined in the `package:flutter` library.
+  ///
+  /// Used to perform instanceof checks to determine whether Dart constructor
+  /// calls are creating [Widget] objects.
+  Class _widgetClass;
+
+  /// The [DebugLocation] class defined in the `package:flutter` library.
+  Class _locationClass;
+
+  /// Current factory constructor that node being transformed is inside.
+  ///
+  /// Used to flow the location passed in as an argument to the factory to the
+  /// actual constructor call within the factory.
+  Procedure _currentFactory;
+
+  WidgetCreatorTracker _tracker;
+
+  _WidgetCallSiteTransformer(
+      {@required Class widgetClass,
+      @required Class locationClass,
+      @required WidgetCreatorTracker tracker})
+      : _widgetClass = widgetClass,
+        _locationClass = locationClass,
+        _tracker = tracker;
+
+  /// Builds a call to the const constructor of the [DebugLocation]
+  /// object specifying the location where a constructor call was made and
+  /// optionally the locations for all parameters passed in.
+  ///
+  /// Specifying the parameters passed in is an experimental feature. With
+  /// access to the source code of an application you could determine the
+  /// locations of the parameters passed in from the source location of the
+  /// constructor call but it is convenient to bundle the location and names
+  /// of the parameters passed in so that tools can show parameter locations
+  /// without re-parsing the source code.
+  ConstructorInvocation _constructLocation(
+    Location location, {
+    String name,
+    ListLiteral parameterLocations,
+    bool showFile: true,
+  }) {
+    final List<NamedExpression> arguments = <NamedExpression>[
+      new NamedExpression('line', new IntLiteral(location.line)),
+      new NamedExpression('column', new IntLiteral(location.column)),
+    ];
+    if (showFile) {
+      arguments.add(new NamedExpression(
+          'file', new StringLiteral(location.file.toString())));
+    }
+    if (name != null) {
+      arguments.add(new NamedExpression('name', new StringLiteral(name)));
+    }
+    if (parameterLocations != null) {
+      arguments
+          .add(new NamedExpression('parameterLocations', parameterLocations));
+    }
+    return new ConstructorInvocation(
+      _locationClass.constructors.first,
+      new Arguments(<Expression>[], named: arguments),
+      isConst: true,
+    );
+  }
+
+  @override
+  Procedure visitProcedure(Procedure node) {
+    if (node.isFactory) {
+      _currentFactory = node;
+      node.transformChildren(this);
+      _currentFactory = null;
+      return node;
+    }
+    return defaultTreeNode(node);
+  }
+
+  bool _isSubclassOfWidget(Class clazz) {
+    return _tracker._isSubclassOf(clazz, _widgetClass);
+  }
+
+  @override
+  StaticInvocation visitStaticInvocation(StaticInvocation node) {
+    node.transformChildren(this);
+    final Procedure target = node.target;
+    if (!target.isFactory) {
+      return node;
+    }
+    final Class constructedClass = target.enclosingClass;
+    if (!_isSubclassOfWidget(constructedClass)) {
+      return node;
+    }
+
+    _addLocationArgument(node, target.function, constructedClass);
+    return node;
+  }
+
+  void _addLocationArgument(InvocationExpression node, FunctionNode function,
+      Class constructedClass) {
+    _maybeAddCreationLocationArgument(
+      node.arguments,
+      function,
+      _computeLocation(node, function, constructedClass),
+      _locationClass,
+    );
+  }
+
+  @override
+  ConstructorInvocation visitConstructorInvocation(ConstructorInvocation node) {
+    node.transformChildren(this);
+
+    final Constructor constructor = node.target;
+    final Class constructedClass = constructor.enclosingClass;
+    if (!_isSubclassOfWidget(constructedClass)) {
+      return node;
+    }
+
+    _addLocationArgument(node, constructor.function, constructedClass);
+    return node;
+  }
+
+  Expression _computeLocation(InvocationExpression node, FunctionNode function,
+      Class constructedClass) {
+    // For factory constructors we need to use the location specified as an
+    // argument to the factory constructor rather than the location
+    if (_currentFactory != null &&
+        _tracker._isSubclassOf(
+            constructedClass, _currentFactory.enclosingClass)) {
+      final VariableDeclaration creationLocationParameter = _getNamedParameter(
+        _currentFactory.function,
+        _creationLocationParameterName,
+      );
+      if (creationLocationParameter != null) {
+        return new VariableGet(creationLocationParameter);
+      }
+    }
+
+    final Arguments arguments = node.arguments;
+    final Location location = node.location;
+    final List<ConstructorInvocation> parameterLocations =
+        <ConstructorInvocation>[];
+    final List<VariableDeclaration> parameters = function.positionalParameters;
+    for (int i = 0; i < arguments.positional.length; ++i) {
+      final Expression expression = arguments.positional[i];
+      final VariableDeclaration parameter = parameters[i];
+      parameterLocations.add(_constructLocation(
+        expression.location,
+        name: parameter.name,
+        showFile: false,
+      ));
+    }
+    for (NamedExpression expression in arguments.named) {
+      parameterLocations.add(_constructLocation(
+        expression.location,
+        name: expression.name,
+        showFile: false,
+      ));
+    }
+    return _constructLocation(
+      location,
+      parameterLocations: new ListLiteral(
+        parameterLocations,
+        typeArgument: _locationClass.thisType,
+        isConst: true,
+      ),
+    );
+  }
+}
+
+/// Rewrites all widget constructors and constructor invocations to add a
+/// parameter specifying the location the constructor was called from.
+///
+/// The creation location is stored as a private field named `_location`
+/// on the base widget class and flowed through the constructors using a named
+/// parameter.
+class WidgetCreatorTracker {
+  Class _widgetClass;
+  Class _locationClass;
+
+  /// Marker interface indicating that a private _location field is
+  /// available.
+  Class _hasCreationLocationClass;
+
+  WidgetCreatorTracker();
+
+  void _resolveFlutterClasses(Iterable<Library> libraries) {
+    // If the Widget or Debug location classes have been updated we need to get
+    // the latest version
+    for (Library library in libraries) {
+      final Uri importUri = library.importUri;
+      if (importUri != null && importUri.scheme == 'package') {
+        if (importUri.path == 'flutter/src/widgets/framework.dart' ||
+            importUri.path == 'flutter_web/src/widgets/framework.dart') {
+          for (Class class_ in library.classes) {
+            if (class_.name == 'Widget') {
+              _widgetClass = class_;
+            }
+          }
+        } else {
+          if (importUri.path == 'flutter/src/widgets/widget_inspector.dart' ||
+              importUri.path ==
+                  'flutter_web/src/widgets/widget_inspector.dart') {
+            for (Class class_ in library.classes) {
+              if (class_.name == '_HasCreationLocation') {
+                _hasCreationLocationClass = class_;
+              } else if (class_.name == '_Location') {
+                _locationClass = class_;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /// Modify [clazz] to add a field named [_locationFieldName] that is the
+  /// first parameter of all constructors of the class.
+  ///
+  /// This method should only be called for classes that implement but do not
+  /// extend [Widget].
+  void _transformClassImplementingWidget(Class clazz) {
+    if (clazz.fields
+        .any((Field field) => field.name.name == _locationFieldName)) {
+      // This class has already been transformed. Skip
+      return;
+    }
+    clazz.implementedTypes
+        .add(new Supertype(_hasCreationLocationClass, <DartType>[]));
+    // We intentionally use the library context of the _HasCreationLocation
+    // class for the private field even if [clazz] is in a different library
+    // so that all classes implementing Widget behave consistently.
+    final Name fieldName = new Name(
+      _locationFieldName,
+      _hasCreationLocationClass.enclosingLibrary,
+    );
+    final Field locationField = new Field(fieldName,
+        type: new InterfaceType(_locationClass),
+        isFinal: true,
+        reference: clazz.reference.canonicalName
+            ?.getChildFromFieldWithName(fieldName)
+            ?.reference);
+    clazz.addMember(locationField);
+
+    final Set<Constructor> _handledConstructors =
+        new Set<Constructor>.identity();
+
+    void handleConstructor(Constructor constructor) {
+      if (!_handledConstructors.add(constructor)) {
+        return;
+      }
+      assert(!_hasNamedParameter(
+        constructor.function,
+        _creationLocationParameterName,
+      ));
+      final VariableDeclaration variable = new VariableDeclaration(
+        _creationLocationParameterName,
+        type: _locationClass.thisType,
+      );
+      if (!_maybeAddNamedParameter(constructor.function, variable)) {
+        return;
+      }
+
+      bool hasRedirectingInitializer = false;
+      for (Initializer initializer in constructor.initializers) {
+        if (initializer is RedirectingInitializer) {
+          if (initializer.target.enclosingClass == clazz) {
+            // We need to handle this constructor first or the call to
+            // addDebugLocationArgument bellow will fail due to the named
+            // parameter not yet existing on the constructor.
+            handleConstructor(initializer.target);
+          }
+          _maybeAddCreationLocationArgument(
+            initializer.arguments,
+            initializer.target.function,
+            new VariableGet(variable),
+            _locationClass,
+          );
+          hasRedirectingInitializer = true;
+          break;
+        }
+      }
+      if (!hasRedirectingInitializer) {
+        constructor.initializers.add(new FieldInitializer(
+          locationField,
+          new VariableGet(variable),
+        ));
+        // TODO(jacobr): add an assert verifying the locationField is not
+        // null. Currently, we cannot safely add this assert because we do not
+        // handle Widget classes with optional positional arguments. There are
+        // no Widget classes in the flutter repo with optional positional
+        // arguments but it is possible users could add classes with optional
+        // positional arguments.
+        //
+        // constructor.initializers.add(new AssertInitializer(new AssertStatement(
+        //   new IsExpression(
+        //       new VariableGet(variable), _locationClass.thisType),
+        //   conditionStartOffset: constructor.fileOffset,
+        //   conditionEndOffset: constructor.fileOffset,
+        // )));
+      }
+    }
+
+    // Add named parameters to all constructors.
+    clazz.constructors.forEach(handleConstructor);
+  }
+
+  /// Transform the given [libraries].
+  void transform(Component module, List<Library> libraries) {
+    if (libraries.isEmpty) {
+      return;
+    }
+
+    _resolveFlutterClasses(module.libraries);
+
+    if (_widgetClass == null) {
+      // This application doesn't actually use the package:flutter library.
+      return;
+    }
+
+    final Set<Class> transformedClasses = new Set<Class>.identity();
+    final Set<Library> librariesToTransform = new Set<Library>.identity()
+      ..addAll(libraries);
+
+    for (Library library in libraries) {
+      if (library.isExternal) {
+        continue;
+      }
+      for (Class class_ in library.classes) {
+        _transformWidgetConstructors(
+          librariesToTransform,
+          transformedClasses,
+          class_,
+        );
+      }
+    }
+
+    // Transform call sites to pass the location parameter.
+    final _WidgetCallSiteTransformer callsiteTransformer =
+        new _WidgetCallSiteTransformer(
+            widgetClass: _widgetClass,
+            locationClass: _locationClass,
+            tracker: this);
+
+    for (Library library in libraries) {
+      if (library.isExternal) {
+        continue;
+      }
+      library.transformChildren(callsiteTransformer);
+    }
+  }
+
+  bool _isSubclassOfWidget(Class clazz) => _isSubclassOf(clazz, _widgetClass);
+
+  bool _isSubclassOf(Class a, Class b) {
+    // TODO(askesc): Cache results.
+    // TODO(askesc): Test for subtype rather than subclass.
+    Class current = a;
+    while (current != null) {
+      if (current == b) return true;
+      current = current.superclass;
+    }
+    return false;
+  }
+
+  void _transformWidgetConstructors(Set<Library> librariesToBeTransformed,
+      Set<Class> transformedClasses, Class clazz) {
+    if (!_isSubclassOfWidget(clazz) ||
+        !librariesToBeTransformed.contains(clazz.enclosingLibrary) ||
+        !transformedClasses.add(clazz)) {
+      return;
+    }
+
+    // Ensure super classes have been transformed before this class.
+    if (clazz.superclass != null &&
+        !transformedClasses.contains(clazz.superclass)) {
+      _transformWidgetConstructors(
+        librariesToBeTransformed,
+        transformedClasses,
+        clazz.superclass,
+      );
+    }
+
+    for (Procedure procedure in clazz.procedures) {
+      if (procedure.isFactory) {
+        _maybeAddNamedParameter(
+          procedure.function,
+          new VariableDeclaration(
+            _creationLocationParameterName,
+            type: _locationClass.thisType,
+          ),
+        );
+      }
+    }
+
+    // Handle the widget class and classes that implement but do not extend the
+    // widget class.
+    if (!_isSubclassOfWidget(clazz.superclass)) {
+      _transformClassImplementingWidget(clazz);
+      return;
+    }
+
+    final Set<Constructor> _handledConstructors =
+        new Set<Constructor>.identity();
+
+    void handleConstructor(Constructor constructor) {
+      if (!_handledConstructors.add(constructor)) {
+        return;
+      }
+
+      final VariableDeclaration variable = new VariableDeclaration(
+        _creationLocationParameterName,
+        type: _locationClass.thisType,
+      );
+      if (_hasNamedParameter(
+          constructor.function, _creationLocationParameterName)) {
+        // Constructor was already rewritten. TODO(jacobr): is this case actually hit?
+        return;
+      }
+      if (!_maybeAddNamedParameter(constructor.function, variable)) {
+        return;
+      }
+      for (Initializer initializer in constructor.initializers) {
+        if (initializer is RedirectingInitializer) {
+          if (initializer.target.enclosingClass == clazz) {
+            // We need to handle this constructor first or the call to
+            // addDebugLocationArgument could fail due to the named parameter
+            // not existing.
+            handleConstructor(initializer.target);
+          }
+
+          _maybeAddCreationLocationArgument(
+            initializer.arguments,
+            initializer.target.function,
+            new VariableGet(variable),
+            _locationClass,
+          );
+        } else if (initializer is SuperInitializer &&
+            _isSubclassOfWidget(initializer.target.enclosingClass)) {
+          _maybeAddCreationLocationArgument(
+            initializer.arguments,
+            initializer.target.function,
+            new VariableGet(variable),
+            _locationClass,
+          );
+        }
+      }
+    }
+
+    clazz.constructors.forEach(handleConstructor);
+  }
+}
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index 3cbab2e..eeb40cc 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -1,7 +1,7 @@
 name: kernel
 # Currently, kernel API is not stable and users should
 # not depend on semver semantics when depending on this package.
-version: 0.3.15
+version: 0.3.18
 author: Dart Team <misc@dartlang.org>
 description: Dart IR (Intermediate Representation)
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/kernel
diff --git a/pkg/modular_test/lib/src/find_sdk_root.dart b/pkg/modular_test/lib/src/find_sdk_root.dart
new file mode 100644
index 0000000..2b36550
--- /dev/null
+++ b/pkg/modular_test/lib/src/find_sdk_root.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2019, 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:io';
+
+/// Helper method to locate the root of the SDK repository.
+///
+/// The `modular_test` package is only intended to be used within the SDK at
+/// this time. We need the ability to find the sdk root in order to locate the
+/// default set of packages that are available to all modular tests.
+Future<Uri> findRoot() async {
+  Uri current = Platform.script;
+  while (true) {
+    var segments = current.pathSegments;
+    var index = segments.lastIndexOf('sdk');
+    if (index == -1) {
+      print("error: cannot find the root of the Dart SDK");
+      exitCode = 1;
+      return null;
+    }
+    current = current.resolve("../" * (segments.length - index - 1));
+    if (await File.fromUri(current.resolve("sdk/DEPS")).exists()) {
+      break;
+    }
+  }
+  return current.resolve("sdk/");
+}
diff --git a/pkg/modular_test/lib/src/generic_runner.dart b/pkg/modular_test/lib/src/generic_runner.dart
new file mode 100644
index 0000000..e7c3030
--- /dev/null
+++ b/pkg/modular_test/lib/src/generic_runner.dart
@@ -0,0 +1,164 @@
+// Copyright (c) 2019, 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.
+
+/// A generic test runner that executes a list of tests, logs test results, and
+/// adds sharding support.
+///
+/// This library contains no logic related to the modular_test framework. It is
+/// used to help integrate tests with our test infrastructure.
+// TODO(sigmund): this library should move somewhere else.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+/// A generic test.
+abstract class Test {
+  /// Unique test name.
+  String get name;
+
+  /// Run the actual test.
+  Future<void> run();
+}
+
+class RunnerOptions {
+  /// Name of the test suite being run.
+  String suiteName;
+
+  /// Configuration name to use when writing result logs.
+  String configurationName;
+
+  /// Filter used to only run tests that match the filter name.
+  String filter;
+
+  /// Where log files are emitted.
+  ///
+  /// Note that all shards currently emit the same filenames, so two shards
+  /// shouldn't be given the same [logDir] otherwise they will overwrite each
+  /// other's log files.
+  Uri logDir;
+
+  /// Of [shards], which shard is currently being executed.
+  int shard;
+
+  /// How many shards will be used to run a suite.
+  int shards;
+
+  /// Whether to print verbose information.
+  bool verbose;
+
+  /// Template used to help developers reproduce the issue.
+  ///
+  /// The following substitutions are made:
+  ///   * %executable is replaced with `Platform.executable`
+  ///   * %script is replaced with the current `Platform.script`
+  ///   * %name is replaced with the test name.
+  String reproTemplate;
+}
+
+class _TestOutcome {
+  /// Unique test name.
+  String name;
+
+  /// Whether, after running the test, the test matches its expectations. Null
+  /// before the test is executed.
+  bool matchedExpectations;
+
+  /// Additional output emitted by the test, only used when expectations don't
+  /// match and more details need to be provided.
+  String output;
+
+  /// Time used to run the test.
+  Duration elapsedTime;
+}
+
+Future<void> runSuite<T>(List<Test> tests, RunnerOptions options) async {
+  if (options.filter == null) {
+    if (options.logDir == null) {
+      print('warning: no output directory provided, logs wont be emitted.');
+    }
+    if (options.configurationName == null) {
+      print('warning: please provide a configuration name.');
+    }
+  }
+  var sortedTests = tests.toList()..sort((a, b) => a.name.compareTo(b.name));
+  List<_TestOutcome> testOutcomes = [];
+  int shard = options.shard;
+  int shards = options.shards;
+  for (int i = 0; i < sortedTests.length; i++) {
+    if (shards > 1 && i % shards != shard) continue;
+    var test = sortedTests[i];
+    var name = test.name;
+    if (options.verbose) stdout.write('$name: ');
+    if (options.filter != null && !name.contains(options.filter)) {
+      if (options.verbose) stdout.write('skipped\n');
+      continue;
+    }
+
+    var watch = new Stopwatch()..start();
+    var outcome = new _TestOutcome()..name = test.name;
+    try {
+      await test.run();
+      if (options.verbose) stdout.write('pass\n');
+      outcome.matchedExpectations = true;
+    } catch (e, st) {
+      var repro = options.reproTemplate
+          .replaceAll('%executable', Platform.resolvedExecutable)
+          .replaceAll('%script', Platform.script.path)
+          .replaceAll('%name', test.name);
+      outcome.matchedExpectations = false;
+      outcome.output = 'uncaught exception: $e\n$st\nTo repro run:\n  $repro';
+      if (options.verbose) stdout.write('fail\n${outcome.output}');
+    }
+    watch.stop();
+    outcome.elapsedTime = watch.elapsed;
+    testOutcomes.add(outcome);
+  }
+
+  if (options.logDir == null) {
+    // TODO(sigmund): delete. This is only added to ensure the bots show test
+    // failures until support for `--output-directory` is added to the test
+    // matrix.
+    if (testOutcomes.any((o) => !o.matchedExpectations)) {
+      exitCode = 1;
+    }
+    return;
+  }
+
+  List<String> results = [];
+  List<String> logs = [];
+  for (int i = 0; i < testOutcomes.length; i++) {
+    var test = testOutcomes[i];
+    final record = jsonEncode({
+      'name': '${options.suiteName}/${test.name}',
+      'configuration': options.configurationName,
+      'suite': options.suiteName,
+      'test_name': test.name,
+      'time_ms': test.elapsedTime.inMilliseconds,
+      'expected': 'Pass',
+      'result': test.matchedExpectations ? 'Pass' : 'Fail',
+      'matches': test.matchedExpectations,
+    });
+    results.add(record);
+    if (!test.matchedExpectations) {
+      final log = jsonEncode({
+        'name': '${options.suiteName}/${test.name}',
+        'configuration': options.configurationName,
+        'result': test.matchedExpectations ? 'Pass' : 'Fail',
+        'log': test.output,
+      });
+      logs.add(log);
+    }
+  }
+
+  // Ensure the directory URI ends with a path separator.
+  var logDir = Directory.fromUri(options.logDir).uri;
+  var resultJsonUri = logDir.resolve('results.json');
+  var logsJsonUri = logDir.resolve('logs.json');
+  File.fromUri(resultJsonUri)
+      .writeAsStringSync(results.map((s) => '$s\n').join(), flush: true);
+  File.fromUri(logsJsonUri)
+      .writeAsStringSync(logs.map((s) => '$s\n').join(), flush: true);
+  print('log files emitted to ${resultJsonUri} and ${logsJsonUri}');
+}
diff --git a/pkg/modular_test/lib/src/io_pipeline.dart b/pkg/modular_test/lib/src/io_pipeline.dart
new file mode 100644
index 0000000..21c57b6
--- /dev/null
+++ b/pkg/modular_test/lib/src/io_pipeline.dart
@@ -0,0 +1,168 @@
+// Copyright (c) 2019, 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.
+
+/// An implementation of [Pipeline] that runs using IO.
+///
+/// To define a step, implement [IOModularStep].
+import 'dart:io';
+
+import 'pipeline.dart';
+import 'suite.dart';
+
+/// Indicates where to read and write data produced by the pipeline.
+typedef ModuleDataToRelativeUri = Uri Function(Module, DataId);
+
+abstract class IOModularStep extends ModularStep {
+  /// Execute the step under [root].
+  ///
+  /// The [root] folder will hold all inputs and will be used to emit the output
+  /// of this step.
+  ///
+  /// Assets created on previous steps of the pipeline should be available under
+  /// `root.resolveUri(toUri(module, dataId))` and the output of this step
+  /// should be stored under `root.resolveUri(toUri(module, resultKind))`.
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags);
+}
+
+class IOPipeline extends Pipeline<IOModularStep> {
+  /// Folder that holds the results of each step during the run of the pipeline.
+  ///
+  /// This value is usually null before and after the pipeline runs, but will be
+  /// non-null in two cases:
+  ///
+  ///  * for testing purposes when using [saveIntermediateResultsForTesting].
+  ///
+  ///  * to share results across pipeline runs when using [cacheSharedModules].
+  ///
+  /// When using [cacheSharedModules] the pipeline will only reuse data for
+  /// modules that are known to be shared (e.g. shared packages and sdk
+  /// libraries), and not modules that are test specific. File names will be
+  /// specific enough so that we can keep separate the artifacts created from
+  /// running tools under different configurations (with different flags).
+  Uri _resultsFolderUri;
+  Uri get resultFolderUriForTesting => _resultsFolderUri;
+
+  /// A unique number to denote the current modular test configuration.
+  ///
+  /// When using [cacheSharedModules], a test can resuse the output of a
+  /// previous run of this pipeline if that output was generated with the same
+  /// configuration.
+  int _currentConfiguration;
+
+  final ConfigurationRegistry _registry;
+
+  /// Whether to keep alive the temporary folder used to store intermediate
+  /// results in order to inspect it later in test.
+  final bool saveIntermediateResultsForTesting;
+
+  IOPipeline(List<IOModularStep> steps,
+      {this.saveIntermediateResultsForTesting: false,
+      bool cacheSharedModules: false})
+      : _registry = cacheSharedModules ? new ConfigurationRegistry() : null,
+        super(steps, cacheSharedModules);
+
+  @override
+  Future<void> run(ModularTest test) async {
+    var resultsDir = null;
+    if (_resultsFolderUri == null) {
+      resultsDir = await Directory.systemTemp.createTemp('modular_test_res-');
+      _resultsFolderUri = resultsDir.uri;
+    }
+    if (cacheSharedModules) {
+      _currentConfiguration = _registry.computeConfigurationId(test);
+    }
+    await super.run(test);
+    if (resultsDir != null &&
+        !saveIntermediateResultsForTesting &&
+        !cacheSharedModules) {
+      await resultsDir.delete(recursive: true);
+      _resultsFolderUri = null;
+    }
+    if (!saveIntermediateResultsForTesting) {
+      _currentConfiguration = null;
+    }
+  }
+
+  /// Delete folders that were kept around either because of
+  /// [saveIntermediateResultsForTesting] or because of [cacheSharedModules].
+  Future<void> cleanup() async {
+    if (_resultsFolderUri == null) return;
+    if (saveIntermediateResultsForTesting || cacheSharedModules) {
+      await Directory.fromUri(_resultsFolderUri).delete(recursive: true);
+      _resultsFolderUri = null;
+    }
+  }
+
+  @override
+  Future<void> runStep(IOModularStep step, Module module,
+      Map<Module, Set<DataId>> visibleData, List<String> flags) async {
+    if (cacheSharedModules && module.isShared) {
+      // If all expected outputs are already available, skip the step.
+      bool allCachedResultsFound = true;
+      for (var dataId in step.resultData) {
+        var cachedFile = File.fromUri(_resultsFolderUri
+            .resolve(_toFileName(module, dataId, configSpecific: true)));
+        if (!await cachedFile.exists()) {
+          allCachedResultsFound = false;
+          break;
+        }
+      }
+      if (allCachedResultsFound) {
+        step.notifyCached(module);
+        return;
+      }
+    }
+
+    // Each step is executed in a separate folder.  To make it easier to debug
+    // issues, we include one of the step data ids in the name of the folder.
+    var stepId = step.resultData.first;
+    var stepFolder =
+        await Directory.systemTemp.createTemp('modular_test_${stepId}-');
+    for (var module in visibleData.keys) {
+      for (var dataId in visibleData[module]) {
+        var assetUri = _resultsFolderUri
+            .resolve(_toFileName(module, dataId, configSpecific: true));
+        await File.fromUri(assetUri).copy(
+            stepFolder.uri.resolve(_toFileName(module, dataId)).toFilePath());
+      }
+    }
+    if (step.needsSources) {
+      for (var uri in module.sources) {
+        var originalUri = module.rootUri.resolveUri(uri);
+        var copyUri = stepFolder.uri.resolveUri(uri);
+        await File.fromUri(copyUri).create(recursive: true);
+        await File.fromUri(originalUri).copy(copyUri.toFilePath());
+      }
+    }
+
+    await step.execute(module, stepFolder.uri,
+        (Module m, DataId id) => Uri.parse(_toFileName(m, id)), flags);
+
+    for (var dataId in step.resultData) {
+      var outputFile =
+          File.fromUri(stepFolder.uri.resolve(_toFileName(module, dataId)));
+      if (!await outputFile.exists()) {
+        throw StateError(
+            "Step '${step.runtimeType}' didn't produce an output file");
+      }
+      await outputFile.copy(_resultsFolderUri
+          .resolve(_toFileName(module, dataId, configSpecific: true))
+          .toFilePath());
+    }
+    await stepFolder.delete(recursive: true);
+  }
+
+  String _toFileName(Module module, DataId dataId,
+      {bool configSpecific: false}) {
+    var prefix =
+        cacheSharedModules && configSpecific && _currentConfiguration != null
+            ? _currentConfiguration
+            : '';
+    return "$prefix${module.name}.${dataId.name}";
+  }
+
+  String configSpecificResultFileNameForTesting(Module module, DataId dataId) =>
+      _toFileName(module, dataId, configSpecific: true);
+}
diff --git a/pkg/modular_test/lib/src/loader.dart b/pkg/modular_test/lib/src/loader.dart
new file mode 100644
index 0000000..e23d38e
--- /dev/null
+++ b/pkg/modular_test/lib/src/loader.dart
@@ -0,0 +1,313 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library defines how `modular_test` converts the contents of a folder
+/// into a modular test. At this time, the logic in this library assumes this is
+/// only used within the Dart SDK repo.
+///
+/// A modular test folder contains:
+///   * individual .dart files, each file is considered a module. A
+///   `main.dart` file is required as the entry point of the test.
+///   * subfolders: each considered a module with multiple files
+///   * (optional) a .packages file:
+///       * if this is not specified, the test will use [defaultPackagesInput]
+///       instead.
+///       * if specified, it will be extended with the definitions in
+///       [defaultPackagesInput]. The list of packages provided is expected to
+///       be disjoint with those in [defaultPackagesInput].
+///   * a modules.yaml file: a specification of dependencies between modules.
+///     The format is described in `test_specification_parser.dart`.
+import 'dart:io';
+import 'dart:convert';
+import 'suite.dart';
+import 'test_specification_parser.dart';
+import 'find_sdk_root.dart';
+
+import 'package:package_config/packages_file.dart' as package_config;
+
+/// Returns the [ModularTest] associated with a folder under [uri].
+///
+/// After scanning the contents of the folder, this method creates a
+/// [ModularTest] that contains only modules that are reachable from the main
+/// module.  This method runs several validations including that modules don't
+/// have conflicting names, that the default packages are always visible, and
+/// that modules do not contain cycles.
+Future<ModularTest> loadTest(Uri uri) async {
+  var folder = Directory.fromUri(uri);
+  var testUri = folder.uri; // normalized in case the trailing '/' was missing.
+  Uri root = await findRoot();
+  Map<String, Uri> defaultPackages =
+      package_config.parse(_defaultPackagesInput, root);
+  Module sdkModule = await _createSdkModule(root);
+  Map<String, Module> modules = {'sdk': sdkModule};
+  String specString;
+  Module mainModule;
+  Map<String, Uri> packages = {};
+  var entries = folder.listSync(recursive: false).toList()
+    // Sort to avoid dependency on file system order.
+    ..sort(_compareFileSystemEntity);
+  for (var entry in entries) {
+    var entryUri = entry.uri;
+    if (entry is File) {
+      var fileName = entryUri.path.substring(testUri.path.length);
+      if (fileName.endsWith('.dart')) {
+        var moduleName = fileName.substring(0, fileName.indexOf('.dart'));
+        if (moduleName == 'sdk') {
+          return _invalidTest("The file '$fileName' defines a module called "
+              "'$moduleName' which conflicts with the sdk module "
+              "that is provided by default.");
+        }
+        if (defaultPackages.containsKey(moduleName)) {
+          return _invalidTest("The file '$fileName' defines a module called "
+              "'$moduleName' which conflicts with a package by the same name "
+              "that is provided by default.");
+        }
+        if (modules.containsKey(moduleName)) {
+          return _moduleConflict(fileName, modules[moduleName], testUri);
+        }
+        var relativeUri = Uri.parse(fileName);
+        var isMain = moduleName == 'main';
+        var module = Module(moduleName, [], testUri, [relativeUri],
+            mainSource: isMain ? relativeUri : null,
+            isMain: isMain,
+            packageBase: Uri.parse('.'));
+        if (isMain) mainModule = module;
+        modules[moduleName] = module;
+      } else if (fileName == '.packages') {
+        List<int> packagesBytes = await entry.readAsBytes();
+        packages = package_config.parse(packagesBytes, entryUri);
+      } else if (fileName == 'modules.yaml') {
+        specString = await entry.readAsString();
+      }
+    } else {
+      assert(entry is Directory);
+      var path = entryUri.path;
+      var moduleName = path.substring(testUri.path.length, path.length - 1);
+      if (moduleName == 'sdk') {
+        return _invalidTest("The folder '$moduleName' defines a module "
+            "which conflicts with the sdk module "
+            "that is provided by default.");
+      }
+      if (defaultPackages.containsKey(moduleName)) {
+        return _invalidTest("The folder '$moduleName' defines a module "
+            "which conflicts with a package by the same name "
+            "that is provided by default.");
+      }
+      if (modules.containsKey(moduleName)) {
+        return _moduleConflict(moduleName, modules[moduleName], testUri);
+      }
+      var sources = await _listModuleSources(entryUri);
+      modules[moduleName] = Module(moduleName, [], testUri, sources,
+          packageBase: Uri.parse('$moduleName/'));
+    }
+  }
+  if (specString == null) {
+    return _invalidTest("modules.yaml file is missing");
+  }
+  if (mainModule == null) {
+    return _invalidTest("main module is missing");
+  }
+
+  _addDefaultPackageEntries(packages, defaultPackages);
+  await _addModulePerPackage(packages, modules);
+  TestSpecification spec = parseTestSpecification(specString);
+  _attachDependencies(spec.dependencies, modules);
+  _attachDependencies(
+      parseTestSpecification(_defaultPackagesSpec).dependencies, modules);
+  _addSdkDependencies(modules, sdkModule);
+  _detectCyclesAndRemoveUnreachable(modules, mainModule);
+  var sortedModules = modules.values.toList()
+    ..sort((a, b) => a.name.compareTo(b.name));
+  var sortedFlags = spec.flags.toList()..sort();
+  return new ModularTest(sortedModules, mainModule, sortedFlags);
+}
+
+/// Returns all source files recursively found in a folder as relative URIs.
+Future<List<Uri>> _listModuleSources(Uri root) async {
+  List<Uri> sources = [];
+  Directory folder = Directory.fromUri(root);
+  int baseUriPrefixLength = folder.parent.uri.path.length;
+  await for (var file in folder.list(recursive: true)) {
+    var path = file.uri.path;
+    if (path.endsWith('.dart')) {
+      sources.add(Uri.parse(path.substring(baseUriPrefixLength)));
+    }
+  }
+  return sources..sort((a, b) => a.path.compareTo(b.path));
+}
+
+/// Add links between modules based on the provided dependency map.
+void _attachDependencies(
+    Map<String, List<String>> dependencies, Map<String, Module> modules) {
+  dependencies.forEach((name, moduleDependencies) {
+    var module = modules[name];
+    if (module == null) {
+      _invalidTest(
+          "declared dependencies for a non existing module named '$name'");
+    }
+    if (module.dependencies.isNotEmpty) {
+      _invalidTest("Module dependencies have already been declared on $name.");
+    }
+    moduleDependencies.forEach((dependencyName) {
+      var moduleDependency = modules[dependencyName];
+      if (moduleDependency == null) {
+        _invalidTest("'$name' declares a dependency on a non existing module "
+            "named '$dependencyName'");
+      }
+      module.dependencies.add(moduleDependency);
+    });
+  });
+}
+
+/// Make every module depend on the sdk module.
+void _addSdkDependencies(Map<String, Module> modules, Module sdkModule) {
+  for (var module in modules.values) {
+    if (module != sdkModule) {
+      module.dependencies.add(sdkModule);
+    }
+  }
+}
+
+void _addDefaultPackageEntries(
+    Map<String, Uri> packages, Map<String, Uri> defaultPackages) {
+  for (var name in defaultPackages.keys) {
+    var existing = packages[name];
+    if (existing != null && existing != defaultPackages[name]) {
+      _invalidTest(
+          ".packages file defines an conflicting entry for package '$name'.");
+    }
+    packages[name] = defaultPackages[name];
+  }
+}
+
+/// Create a module for each package dependency.
+Future<void> _addModulePerPackage(
+    Map<String, Uri> packages, Map<String, Module> modules) async {
+  for (var packageName in packages.keys) {
+    var module = modules[packageName];
+    if (module != null) {
+      module.isPackage = true;
+    } else {
+      var packageLibUri = packages[packageName];
+      var rootUri = Directory.fromUri(packageLibUri).parent.uri;
+      var sources = await _listModuleSources(packageLibUri);
+      // TODO(sigmund): validate that we don't use a different alias for a
+      // module that is part of the test (package name and module name should
+      // match).
+      modules[packageName] = Module(packageName, [], rootUri, sources,
+          isPackage: true, packageBase: Uri.parse('lib/'), isShared: true);
+    }
+  }
+}
+
+Future<Module> _createSdkModule(Uri root) async {
+  List<Uri> sources = [Uri.parse('sdk/lib/libraries.json')];
+
+  // Include all dart2js, ddc, vm library sources and patch files.
+  // Note: we don't extract the list of files from the libraries.json because
+  // it doesn't list files that are transitively imported.
+  var sdkLibrariesAndPatchesRoots = [
+    'sdk/lib/',
+    'runtime/lib/',
+    'runtime/bin/',
+  ];
+  for (var path in sdkLibrariesAndPatchesRoots) {
+    var dir = Directory.fromUri(root.resolve(path));
+    await for (var file in dir.list(recursive: true)) {
+      if (file is File && file.path.endsWith(".dart")) {
+        sources.add(Uri.parse(file.uri.path.substring(root.path.length)));
+      }
+    }
+  }
+  sources..sort((a, b) => a.path.compareTo(b.path));
+  return Module('sdk', [], root, sources, isSdk: true, isShared: true);
+}
+
+/// Trim the set of modules, and detect cycles while we are at it.
+_detectCyclesAndRemoveUnreachable(Map<String, Module> modules, Module main) {
+  Set<Module> visiting = {};
+  Set<Module> visited = {};
+
+  helper(Module current) {
+    if (!visiting.add(current)) {
+      _invalidTest("module '${current.name}' has a dependency cycle.");
+    }
+    if (visited.add(current)) {
+      current.dependencies.forEach(helper);
+    }
+    visiting.remove(current);
+  }
+
+  helper(main);
+  Set<String> toKeep = visited.map((m) => m.name).toSet();
+  List<String> toRemove =
+      modules.keys.where((name) => !toKeep.contains(name)).toList();
+  toRemove.forEach(modules.remove);
+}
+
+/// Default entries for a .packages file with paths relative to the SDK root.
+List<int> _defaultPackagesInput = utf8.encode('''
+expect:pkg/expect/lib
+async_helper:pkg/async_helper/lib
+meta:pkg/meta/lib
+collection:third_party/pkg/collection/lib
+''');
+
+/// Specifies the dependencies of all packages in [_defaultPackagesInput]. This
+/// string needs to be updated if dependencies between those packages changes
+/// (which is rare).
+// TODO(sigmund): consider either computing this from the pubspec files or the
+// import graph, or adding tests that validate this is always up to date.
+String _defaultPackagesSpec = '''
+dependencies:
+  expect: meta
+  meta: []
+  async_helper: []
+  collection: []
+''';
+
+/// Report an conflict error.
+_moduleConflict(String name, Module existing, Uri root) {
+  var isFile = name.endsWith('.dart');
+  var entryType = isFile ? 'file' : 'folder';
+
+  var existingIsFile =
+      existing.packageBase.path == './' && existing.sources.length == 1;
+  var existingEntryType = existingIsFile ? 'file' : 'folder';
+
+  var existingName = existingIsFile
+      ? existing.sources.single.pathSegments.last
+      : existing.name;
+
+  return _invalidTest("The $entryType '$name' defines a module "
+      "which conflicts with the module defined by the $existingEntryType "
+      "'$existingName'.");
+}
+
+_invalidTest(String message) {
+  throw new InvalidTestError(message);
+}
+
+class InvalidTestError extends Error {
+  final String message;
+  InvalidTestError(this.message);
+  String toString() => "Invalid test: $message";
+}
+
+/// Comparator to sort directories before files.
+int _compareFileSystemEntity(FileSystemEntity a, FileSystemEntity b) {
+  if (a is Directory) {
+    if (b is Directory) {
+      return a.path.compareTo(b.path);
+    } else {
+      return -1;
+    }
+  } else {
+    if (b is Directory) {
+      return 1;
+    } else {
+      return a.path.compareTo(b.path);
+    }
+  }
+}
diff --git a/pkg/modular_test/lib/src/memory_pipeline.dart b/pkg/modular_test/lib/src/memory_pipeline.dart
new file mode 100644
index 0000000..d97586c
--- /dev/null
+++ b/pkg/modular_test/lib/src/memory_pipeline.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2019, 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.
+
+/// An implementation of [Pipeline] that runs in-memory.
+///
+/// To define a step, implement [MemoryModularStep].
+import 'pipeline.dart';
+import 'suite.dart';
+
+/// A hook to fetch data previously computed for a dependency.
+typedef ModuleDataProvider = Object Function(Module, DataId);
+typedef SourceProvider = String Function(Uri);
+
+abstract class MemoryModularStep extends ModularStep {
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags);
+}
+
+class MemoryPipeline extends Pipeline<MemoryModularStep> {
+  final Map<Uri, String> _sources;
+
+  /// Internal state to hold the current results as they are computed by the
+  /// pipeline. Expected to be null before and after the pipeline runs.
+  Map<Module, Map<DataId, Object>> _results;
+
+  /// A copy of [_result] at the time the pipeline last finished running.
+  Map<Module, Map<DataId, Object>> resultsForTesting;
+
+  final ConfigurationRegistry _registry;
+
+  /// Cache of results when [cacheSharedModules] is true
+  final List<Map<Module, Map<DataId, Object>>> _resultCache;
+
+  MemoryPipeline(this._sources, List<MemoryModularStep> steps,
+      {bool cacheSharedModules: false})
+      : _registry = cacheSharedModules ? new ConfigurationRegistry() : null,
+        _resultCache = cacheSharedModules ? [] : null,
+        super(steps, cacheSharedModules);
+
+  @override
+  Future<void> run(ModularTest test) async {
+    _results = {};
+    Map<Module, Map<DataId, Object>> cache = null;
+    if (cacheSharedModules) {
+      int id = _registry.computeConfigurationId(test);
+      if (id < _resultCache.length) {
+        cache = _resultCache[id];
+      } else {
+        assert(id == _resultCache.length);
+        _resultCache.add(cache = {});
+      }
+      _results.addAll(cache);
+    }
+    await super.run(test);
+    resultsForTesting = _results;
+    if (cacheSharedModules) {
+      for (var module in _results.keys) {
+        if (module.isShared) {
+          cache[module] = _results[module];
+        }
+      }
+    }
+    _results = null;
+  }
+
+  @override
+  Future<void> runStep(MemoryModularStep step, Module module,
+      Map<Module, Set<DataId>> visibleData, List<String> flags) async {
+    if (cacheSharedModules && module.isShared) {
+      bool allCachedResultsFound = true;
+      for (var dataId in step.resultData) {
+        if (_results[module] == null || _results[module][dataId] == null) {
+          allCachedResultsFound = false;
+          break;
+        }
+      }
+      if (allCachedResultsFound) {
+        step.notifyCached(module);
+        return;
+      }
+    }
+
+    Map<Module, Map<DataId, Object>> inputData = {};
+    visibleData.forEach((module, dataIdSet) {
+      inputData[module] = {};
+      for (var dataId in dataIdSet) {
+        inputData[module][dataId] = _results[module][dataId];
+      }
+    });
+    Map<Uri, String> inputSources = {};
+    if (step.needsSources) {
+      module.sources.forEach((relativeUri) {
+        var uri = module.rootUri.resolveUri(relativeUri);
+        inputSources[uri] = _sources[uri];
+      });
+    }
+    Map<DataId, Object> result = await step.execute(
+        module,
+        (Uri uri) => inputSources[uri],
+        (Module m, DataId id) => inputData[m][id],
+        flags);
+    for (var dataId in step.resultData) {
+      (_results[module] ??= {})[dataId] = result[dataId];
+    }
+  }
+}
diff --git a/pkg/modular_test/lib/src/pipeline.dart b/pkg/modular_test/lib/src/pipeline.dart
new file mode 100644
index 0000000..c55f2f9
--- /dev/null
+++ b/pkg/modular_test/lib/src/pipeline.dart
@@ -0,0 +1,173 @@
+// Copyright (c) 2019, 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.
+
+/// Abstraction for a compilation pipeline.
+///
+/// A pipeline defines how modular steps are excuted and ensures that a step
+/// only has access to the data it declares.
+///
+/// The abstract implementation validates how the data is declared, and the
+/// underlying implementations enforce the access to data in different ways.
+///
+/// The IO-based implementation ensures hermeticity by copying data to different
+/// directories. The memory-based implementation ensures hemeticity by filtering
+/// out the data before invoking the next step.
+import 'suite.dart';
+
+/// Describes a step in a modular compilation pipeline.
+class ModularStep {
+  /// Whether this step needs to read the source files in the module.
+  final bool needsSources;
+
+  /// Data that this step needs to read about dependencies.
+  ///
+  /// This can be data produced on a previous stage of the pipeline
+  /// or produced by this same step when it was run on a dependency.
+  ///
+  /// If this list includes any data from [resultData], then the modular-step
+  /// has to be run on dependencies before it is run on a module. Otherwise, it
+  /// could be run in parallel.
+  final List<DataId> dependencyDataNeeded;
+
+  /// Data that this step needs to read about the module itself.
+  ///
+  /// This is meant to be data produced in earlier stages of the modular
+  /// pipeline. It is an error to include any id from [resultData] in this list.
+  final List<DataId> moduleDataNeeded;
+
+  /// Data that this step produces.
+  final List<DataId> resultData;
+
+  /// Whether this step is only executed on the main module.
+  final bool onlyOnMain;
+
+  ModularStep(
+      {this.needsSources: true,
+      this.dependencyDataNeeded: const [],
+      this.moduleDataNeeded: const [],
+      this.resultData,
+      this.onlyOnMain: false});
+
+  /// Notifies that the step was not executed, but cached instead.
+  void notifyCached(Module module) {}
+}
+
+/// An object to uniquely identify modular data produced by a modular step.
+///
+/// Two modular steps on the same pipeline cannot emit the same data.
+class DataId {
+  final String name;
+
+  const DataId(this.name);
+
+  @override
+  String toString() => name;
+}
+
+abstract class Pipeline<S extends ModularStep> {
+  /// Whether to cache the result of shared modules (e.g. shard packages and sdk
+  /// libraries) when multiple tests are run by this pipeline.
+  final bool cacheSharedModules;
+
+  final List<S> steps;
+
+  Pipeline(this.steps, this.cacheSharedModules) {
+    _validate();
+  }
+
+  void _validate() {
+    // Ensure that steps consume only data that was produced by previous steps
+    // or by the same step on a dependency.
+    Map<DataId, S> previousKinds = {};
+    for (var step in steps) {
+      if (step.resultData == null || step.resultData.isEmpty) {
+        _validationError(
+            "'${step.runtimeType}' needs to declare what data it produces.");
+      }
+      for (var resultKind in step.resultData) {
+        if (previousKinds.containsKey(resultKind)) {
+          _validationError("Cannot produce the same data on two modular steps."
+              " '$resultKind' was previously produced by "
+              "'${previousKinds[resultKind].runtimeType}' but "
+              "'${step.runtimeType}' also produces the same data.");
+        }
+        previousKinds[resultKind] = step;
+        for (var dataId in step.dependencyDataNeeded) {
+          if (!previousKinds.containsKey(dataId)) {
+            _validationError(
+                "Step '${step.runtimeType}' needs data '${dataId}', but the "
+                "data is not produced by this or a preceding step.");
+          }
+        }
+        for (var dataId in step.moduleDataNeeded) {
+          if (!previousKinds.containsKey(dataId)) {
+            _validationError(
+                "Step '${step.runtimeType}' needs data '${dataId}', but the "
+                "data is not produced by a preceding step.");
+          }
+          if (dataId == resultKind) {
+            _validationError("Circular dependency on '$dataId' "
+                "in step '${step.runtimeType}'");
+          }
+        }
+      }
+    }
+  }
+
+  void _validationError(String s) => throw InvalidPipelineError(s);
+
+  Future<void> run(ModularTest test) async {
+    // TODO(sigmund): validate that [ModularTest] has no cycles.
+    Map<Module, Set<DataId>> computedData = {};
+    for (var step in steps) {
+      await _recursiveRun(step, test.mainModule, computedData, {}, test.flags);
+    }
+  }
+
+  Future<void> _recursiveRun(
+      S step,
+      Module module,
+      Map<Module, Set<DataId>> computedData,
+      Map<Module, Set<Module>> transitiveDependencies,
+      List<String> flags) async {
+    if (transitiveDependencies.containsKey(module)) return;
+    var deps = transitiveDependencies[module] = {};
+    for (var dependency in module.dependencies) {
+      await _recursiveRun(
+          step, dependency, computedData, transitiveDependencies, flags);
+      deps.add(dependency);
+      deps.addAll(transitiveDependencies[dependency]);
+    }
+
+    if (step.onlyOnMain && !module.isMain) return;
+    // Include only requested data from transitive dependencies.
+    Map<Module, Set<DataId>> visibleData = {};
+
+    deps.forEach((dep) {
+      visibleData[dep] = {};
+      for (var dataId in step.dependencyDataNeeded) {
+        if (computedData[dep].contains(dataId)) {
+          visibleData[dep].add(dataId);
+        }
+      }
+    });
+    visibleData[module] = {};
+    for (var dataId in step.moduleDataNeeded) {
+      if (computedData[module].contains(dataId)) {
+        visibleData[module].add(dataId);
+      }
+    }
+    await runStep(step, module, visibleData, flags);
+    (computedData[module] ??= {}).addAll(step.resultData);
+  }
+
+  Future<void> runStep(S step, Module module,
+      Map<Module, Set<DataId>> visibleData, List<String> flags);
+}
+
+class InvalidPipelineError extends Error {
+  final String message;
+  InvalidPipelineError(this.message);
+  String toString() => "Invalid pipeline: $message";
+}
diff --git a/pkg/modular_test/lib/src/runner.dart b/pkg/modular_test/lib/src/runner.dart
new file mode 100644
index 0000000..d3803bb
--- /dev/null
+++ b/pkg/modular_test/lib/src/runner.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2019, 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.
+
+/// A runner that executes a pipeline on a folder containing modular tests.
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:modular_test/src/io_pipeline.dart';
+import 'package:modular_test/src/loader.dart';
+import 'package:modular_test/src/suite.dart';
+
+import 'generic_runner.dart' as generic;
+
+Uri relativize(Uri uri, Uri base) {
+  return Uri.parse(uri.path.substring(base.path.length));
+}
+
+Future<void> runSuite(Uri suiteFolder, String suiteName, Options options,
+    IOPipeline pipeline) async {
+  var dir = Directory.fromUri(suiteFolder);
+  var entries = (await dir.list(recursive: false).toList())
+      .where((e) => e is Directory)
+      .map((e) => new _PipelineTest(e.uri, suiteFolder, options, pipeline))
+      .toList();
+
+  await generic.runSuite(
+      entries,
+      new generic.RunnerOptions()
+        ..suiteName = suiteName
+        ..configurationName = options.configurationName
+        ..filter = options.filter
+        ..logDir = options.outputDirectory
+        ..shard = options.shard
+        ..shards = options.shards
+        ..verbose = options.verbose
+        ..reproTemplate = '%executable %script --verbose --filter %name');
+  await pipeline.cleanup();
+}
+
+class _PipelineTest implements generic.Test {
+  final String name;
+  final Uri uri;
+  final Options options;
+  final IOPipeline pipeline;
+
+  _PipelineTest(this.uri, Uri suiteFolder, this.options, this.pipeline)
+      // Use the name of the folder as the test name by trimming out the prefix
+      // from the suite and the trailing `/`.
+      : name = uri.path.substring(suiteFolder.path.length, uri.path.length - 1);
+
+  Future<void> run() async {
+    ModularTest test = await loadTest(uri);
+    if (options.verbose) print(test.debugString());
+    await pipeline.run(test);
+  }
+}
+
+class Options {
+  bool showSkipped = false;
+  bool verbose = false;
+  String filter = null;
+  int shards = 1;
+  int shard = 1;
+  String configurationName;
+  Uri outputDirectory;
+  bool useSdk = false;
+
+  static Options parse(List<String> args) {
+    var parser = new ArgParser()
+      ..addFlag('verbose',
+          abbr: 'v',
+          defaultsTo: false,
+          help: 'print detailed information about the test and modular steps')
+      ..addFlag('show-skipped',
+          defaultsTo: false,
+          help: 'print the name of the tests skipped by the filtering option')
+      ..addFlag('use-sdk',
+          defaultsTo: false, help: 'whether to use snapshots from a built sdk')
+      ..addOption('filter',
+          help: 'only run tests containing this filter as a substring')
+      ..addOption('shards',
+          help: 'total number of shards a suite is going to be split into.',
+          defaultsTo: '1')
+      ..addOption('shard',
+          help: 'which shard this script is executing. This should be between 0'
+              ' and `shards - 1`.')
+      ..addOption('output-directory',
+          help: 'location where to emit the jsonl result and log files')
+      ..addOption('configuration-name',
+          help: 'configuration name to use for emitting jsonl result files.');
+    ArgResults argResults = parser.parse(args);
+    int shards = int.tryParse(argResults['shards']) ?? 1;
+    int shard;
+    if (shards > 1) {
+      shard = int.tryParse(argResults['shard']) ?? 1;
+      if (shard <= 0 || shard >= shards) {
+        print('Error: shard should be between 0 and ${shards - 1},'
+            ' but got $shard');
+        exit(1);
+      }
+    }
+    Uri toUri(s) => s == null ? null : Uri.base.resolve(s);
+    return Options()
+      ..showSkipped = argResults['show-skipped']
+      ..verbose = argResults['verbose']
+      ..useSdk = argResults['use-sdk']
+      ..filter = argResults['filter']
+      ..shards = shards
+      ..shard = shard
+      ..configurationName = argResults['configuration-name']
+      ..outputDirectory = toUri(argResults['output-directory']);
+  }
+}
diff --git a/pkg/modular_test/lib/src/suite.dart b/pkg/modular_test/lib/src/suite.dart
new file mode 100644
index 0000000..281c381
--- /dev/null
+++ b/pkg/modular_test/lib/src/suite.dart
@@ -0,0 +1,176 @@
+// Copyright (c) 2019, 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.
+
+/// Model for a modular test.
+
+/// A modular test declares the structure of the test code: what files are
+/// grouped as a module and how modules depend on one another.
+class ModularTest {
+  /// Modules that will be compiled by for modular test
+  final List<Module> modules;
+
+  /// The module containing the main entry method.
+  final Module mainModule;
+
+  /// Flags provided to tools that compile and execute the test.
+  final List<String> flags;
+
+  ModularTest(this.modules, this.mainModule, this.flags) {
+    if (mainModule == null) {
+      throw ArgumentError("main module was null");
+    }
+    if (flags == null) {
+      throw ArgumentError("flags was null");
+    }
+    if (modules == null || modules.length == 0) {
+      throw ArgumentError("modules cannot be null or empty");
+    }
+    for (var module in modules) {
+      module._validate();
+    }
+  }
+
+  String debugString() => modules.map((m) => m.debugString()).join('\n');
+}
+
+/// A single module in a modular test.
+class Module {
+  /// A short name to identify this module.
+  final String name;
+
+  /// Other modules that need to be compiled first and whose result may be
+  /// necessary in order to compile this module.
+  final List<Module> dependencies;
+
+  /// Root under which all sources in the module can be found.
+  final Uri rootUri;
+
+  /// Source files that are part of this module only. Stored as a relative [Uri]
+  /// from [rootUri].
+  final List<Uri> sources;
+
+  /// The file containing the main entry method, if any. Stored as a relative
+  /// [Uri] from [rootUri].
+  final Uri mainSource;
+
+  /// Whether this module is also available as a package import, where the
+  /// package name matches the module name.
+  bool isPackage;
+
+  /// Whether this module represents part of the sdk.
+  bool isSdk;
+
+  /// When [isPackage], the base where all package URIs are resolved against.
+  /// Stored as a relative [Uri] from [rootUri].
+  final Uri packageBase;
+
+  /// Whether this is the main entry module of a test.
+  bool isMain;
+
+  /// Whether this module is test specific or shared across tests. Usually this
+  /// will be true only for the SDK and shared packages like `package:expect`.
+  bool isShared;
+
+  Module(this.name, this.dependencies, this.rootUri, this.sources,
+      {this.mainSource,
+      this.isPackage: false,
+      this.isMain: false,
+      this.packageBase,
+      this.isShared: false,
+      this.isSdk: false}) {
+    if (!_validModuleName.hasMatch(name)) {
+      throw ArgumentError("invalid module name: $name");
+    }
+  }
+
+  void _validate() {
+    if (!isPackage && !isShared && !isSdk) return;
+
+    // Note: we validate this now and not in the constructor because loader.dart
+    // may update `isPackage` after the module is created.
+    if (isSdk && isPackage) {
+      throw InvalidModularTestError("invalid module: $name is an sdk "
+          "module but was also marked as a package module.");
+    }
+
+    for (var dependency in dependencies) {
+      if (isPackage && !dependency.isPackage && !dependency.isSdk) {
+        throw InvalidModularTestError("invalid dependency: $name is a package "
+            "but it depends on ${dependency.name}, which is not.");
+      }
+      if (isShared && !dependency.isShared) {
+        throw InvalidModularTestError(
+            "invalid dependency: $name is a shared module "
+            "but it depends on ${dependency.name}, which is not.");
+      }
+      if (isSdk) {
+        // TODO(sigmund): we should allow to split sdk modules in smaller
+        // pieces. This requires a bit of work:
+        // - allow to compile subsets of the sdk (see #30957 regarding
+        //   extraRequiredLibraries in CFE)
+        // - add logic to specify sdk dependencies.
+        throw InvalidModularTestError(
+            "invalid dependency: $name is an sdk module that depends on  "
+            "${dependency.name}, but sdk modules are not expected to "
+            "have dependencies.");
+      }
+    }
+  }
+
+  @override
+  String toString() => '[module $name]';
+
+  String debugString() {
+    var buffer = new StringBuffer();
+    buffer.write('   ');
+    buffer.write(name);
+    buffer.write(': ');
+    buffer.write(isPackage ? 'package' : '(not package)');
+    buffer.write(', deps: {${dependencies.map((d) => d.name).join(", ")}}');
+    if (isSdk) {
+      buffer.write(', sources: {...omitted ${sources.length} sources...}');
+    } else {
+      buffer.write(', sources: {${sources.map((u) => "$u").join(', ')}}');
+    }
+    return '$buffer';
+  }
+}
+
+final RegExp _validModuleName = new RegExp(r'^[a-zA-Z_][a-zA-Z0-9_]*$');
+
+/// Helper to compute transitive dependencies from [module].
+Set<Module> computeTransitiveDependencies(Module module) {
+  Set<Module> deps = {};
+  helper(Module m) {
+    if (deps.add(m)) m.dependencies.forEach(helper);
+  }
+
+  module.dependencies.forEach(helper);
+  return deps;
+}
+
+/// A registry that can map a test configuration to a simple id.
+///
+/// This is used to help determine whether two tests are run with the same set
+/// of flags (the same configuration), and thus pipelines could reuse the
+/// results of shared modules from the first test when running the second test.
+class ConfigurationRegistry {
+  Map<String, int> _configurationId = {};
+
+  /// Compute an id to identify the configuration of a modular test.
+  ///
+  /// A configuration is defined in terms of the set of flags provided to a
+  /// test. If two test provided to this registry share the same set of flags,
+  /// the resulting ids are the same. Similarly, if the flags are different,
+  /// their ids will be different as well.
+  int computeConfigurationId(ModularTest test) {
+    return _configurationId[test.flags.join(' ')] ??= _configurationId.length;
+  }
+}
+
+class InvalidModularTestError extends Error {
+  final String message;
+  InvalidModularTestError(this.message);
+  String toString() => "Invalid modular test: $message";
+}
diff --git a/pkg/modular_test/lib/src/test_specification_parser.dart b/pkg/modular_test/lib/src/test_specification_parser.dart
new file mode 100644
index 0000000..d0eed3d
--- /dev/null
+++ b/pkg/modular_test/lib/src/test_specification_parser.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library defines how to read a test specification from a Yaml
+/// file. We expect specifications written in this format:
+///
+///    dependencies:
+///      b: a
+///      main: [b, expect]
+///    flags:
+///      - constant-update-2018
+///
+/// Where the dependencies section describe how modules depend on one another,
+/// and the flags section show what flags are needed to run that specific test.
+///
+/// When defining dependencies:
+///   - Each name corresponds to a module.
+///   - Module names correlate to either a file, a folder, or a package.
+///   - A map entry contains all the dependencies of a module, if any.
+///   - If a module has a single dependency, it can be written as a single
+///     value.
+///
+/// The logic in this library mostly treats these names as strings, separately
+/// `loader.dart` is responsible for validating and attaching this dependency
+/// information to a set of module definitions.
+///
+/// The framework is agnostic of what the flags are, but at this time we only
+/// use the name of experimental language features. These are then used to
+/// decide what options to pass to the tools that compile and run the tests.
+import 'package:yaml/yaml.dart';
+
+/// Parses [contents] containing a module dependencies specification written in
+/// yaml, and returns a [TestSpecification].
+TestSpecification parseTestSpecification(String contents) {
+  var spec = loadYaml(contents);
+  if (spec is! YamlMap) {
+    return _invalidSpecification("spec is not a map");
+  }
+  var dependencies = spec['dependencies'];
+  if (dependencies == null) {
+    return _invalidSpecification("no dependencies section");
+  }
+  if (dependencies is! YamlMap) {
+    return _invalidSpecification("dependencies is not a map");
+  }
+
+  Map<String, List<String>> normalizedMap = {};
+  dependencies.forEach((key, value) {
+    if (key is! String) {
+      _invalidSpecification("key: '$key' is not a string");
+    }
+    normalizedMap[key] = [];
+    if (value is String) {
+      normalizedMap[key].add(value);
+    } else if (value is List) {
+      value.forEach((entry) {
+        if (entry is! String) {
+          _invalidSpecification("entry: '$entry' is not a string");
+        }
+        normalizedMap[key].add(entry);
+      });
+    } else {
+      _invalidSpecification(
+          "entry: '$value' is not a string or a list of strings");
+    }
+  });
+
+  List<String> normalizedFlags = [];
+  dynamic flags = spec['flags'];
+  if (flags is String) {
+    normalizedFlags.add(flags);
+  } else if (flags is List) {
+    normalizedFlags.addAll(flags.cast<String>());
+  } else if (flags != null) {
+    _invalidSpecification(
+        "flags: '$flags' expected to be string or list of strings");
+  }
+  return new TestSpecification(normalizedFlags, normalizedMap);
+}
+
+/// Data specifying details about a modular test including dependencies and
+/// flags that are necessary in order to properly run a test.
+///
+class TestSpecification {
+  /// Set of flags necessary to properly run a test.
+  ///
+  /// Usually this contains flags enabling language experiments.
+  final List<String> flags;
+
+  /// Dependencies of the modules that are expected to exist on the test.
+  ///
+  /// Note: some values in the map may not have a corresponding key. That may be
+  /// the case for modules that have no dependencies and modules that are not
+  /// specified explicitly because they are added automatically by the framework
+  /// (for instance, the module of `package:expect` or the sdk itself).
+  final Map<String, List<String>> dependencies;
+
+  TestSpecification(this.flags, this.dependencies);
+}
+
+_invalidSpecification(String message) {
+  throw new InvalidSpecificationError(message);
+}
+
+class InvalidSpecificationError extends Error {
+  final String message;
+  InvalidSpecificationError(this.message);
+  String toString() => "Invalid specification: $message";
+}
diff --git a/pkg/modular_test/pubspec.yaml b/pkg/modular_test/pubspec.yaml
new file mode 100644
index 0000000..39f65c8
--- /dev/null
+++ b/pkg/modular_test/pubspec.yaml
@@ -0,0 +1,16 @@
+name: modular_test
+publish_to: none
+description: >
+ Small framework to test modular pipelines.
+ This is used within the Dart SDK to define and validate modular tests, and to
+ execute them using the modular pipeline of different SDK tools.
+environment:
+  sdk: ">=2.2.1 <3.0.0"
+
+dependencies:
+  package_config: ^1.0.5
+  yaml: ^2.1.15
+
+dev_dependencies:
+  args: any
+  test: any
diff --git a/pkg/modular_test/test/find_sdk_root1_test.dart b/pkg/modular_test/test/find_sdk_root1_test.dart
new file mode 100644
index 0000000..2a5ac51
--- /dev/null
+++ b/pkg/modular_test/test/find_sdk_root1_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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:io';
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'package:modular_test/src/find_sdk_root.dart';
+
+main() {
+  asyncTest(() async {
+    Expect.equals(Platform.script.resolve("../../../"), await findRoot());
+  });
+}
diff --git a/pkg/modular_test/test/io_pipeline_test.dart b/pkg/modular_test/test/io_pipeline_test.dart
new file mode 100644
index 0000000..db980f8
--- /dev/null
+++ b/pkg/modular_test/test/io_pipeline_test.dart
@@ -0,0 +1,262 @@
+// Copyright (c) 2019, 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.
+
+/// Unit test for in-memory pipelines.
+import 'dart:io';
+
+import 'package:modular_test/src/io_pipeline.dart';
+
+import 'pipeline_common.dart';
+
+main() async {
+  var uri = Directory.systemTemp.uri.resolve("io_modular_test_root/");
+  int i = 0;
+  while (await Directory.fromUri(uri).exists()) {
+    uri = Directory.systemTemp.uri.resolve("io_modular_test_root$i/");
+    i++;
+  }
+  runPipelineTest(new IOPipelineTestStrategy(uri));
+}
+
+/// The strategy implementation to exercise the pipeline test on a
+/// [IOPipeline].
+class IOPipelineTestStrategy implements PipelineTestStrategy<IOModularStep> {
+  @override
+  final Uri testRootUri;
+
+  IOPipelineTestStrategy(this.testRootUri);
+
+  @override
+  Future<Pipeline<IOModularStep>> createPipeline(
+      Map<Uri, String> sources, List<IOModularStep> steps,
+      {bool cacheSharedModules: false}) async {
+    await Directory.fromUri(testRootUri).create();
+    for (var uri in sources.keys) {
+      var file = new File.fromUri(uri);
+      await file.create(recursive: true);
+      await file.writeAsStringSync(sources[uri]);
+    }
+    return new IOPipeline(steps,
+        saveIntermediateResultsForTesting: true,
+        cacheSharedModules: cacheSharedModules);
+  }
+
+  @override
+  IOModularStep createSourceOnlyStep(
+          {String Function(Map<Uri, String>) action,
+          DataId resultId,
+          bool requestSources: true}) =>
+      SourceOnlyStep(action, resultId, requestSources);
+
+  @override
+  IOModularStep createModuleDataStep(
+          {String Function(String) action,
+          DataId inputId,
+          DataId resultId,
+          bool requestModuleData: true}) =>
+      ModuleDataStep(action, inputId, resultId, requestModuleData);
+
+  @override
+  IOModularStep createLinkStep(
+          {String Function(String, List<String>) action,
+          DataId inputId,
+          DataId depId,
+          DataId resultId,
+          bool requestDependenciesData: true}) =>
+      LinkStep(action, inputId, depId, resultId, requestDependenciesData);
+
+  @override
+  IOModularStep createMainOnlyStep(
+          {String Function(String, List<String>) action,
+          DataId inputId,
+          DataId depId,
+          DataId resultId,
+          bool requestDependenciesData: true}) =>
+      MainOnlyStep(action, inputId, depId, resultId, requestDependenciesData);
+
+  @override
+  IOModularStep createTwoOutputStep(
+          {String Function(String) action1,
+          String Function(String) action2,
+          DataId inputId,
+          DataId result1Id,
+          DataId result2Id}) =>
+      TwoOutputStep(action1, action2, inputId, result1Id, result2Id);
+
+  @override
+  String getResult(covariant IOPipeline pipeline, Module m, DataId dataId) {
+    var folderUri = pipeline.resultFolderUriForTesting;
+    var file = File.fromUri(folderUri
+        .resolve(pipeline.configSpecificResultFileNameForTesting(m, dataId)));
+    return file.existsSync() ? file.readAsStringSync() : null;
+  }
+
+  @override
+  Future<void> cleanup(covariant IOPipeline pipeline) async {
+    pipeline.cleanup();
+    await Directory.fromUri(testRootUri).delete(recursive: true);
+  }
+}
+
+class SourceOnlyStep implements IOModularStep {
+  final String Function(Map<Uri, String>) action;
+  final DataId resultId;
+  final bool needsSources;
+  List<DataId> get dependencyDataNeeded => const [];
+  List<DataId> get moduleDataNeeded => const [];
+  List<DataId> get resultData => [resultId];
+  bool get onlyOnMain => false;
+
+  SourceOnlyStep(this.action, this.resultId, this.needsSources);
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    Map<Uri, String> sources = {};
+
+    for (var uri in module.sources) {
+      var file = File.fromUri(root.resolveUri(uri));
+      String data = await file.exists() ? await file.readAsString() : null;
+      sources[uri] = data;
+    }
+    await File.fromUri(root.resolveUri(toUri(module, resultId)))
+        .writeAsString(action(sources));
+  }
+
+  @override
+  void notifyCached(Module module) {}
+}
+
+class ModuleDataStep implements IOModularStep {
+  final String Function(String) action;
+  bool get needsSources => false;
+  List<DataId> get dependencyDataNeeded => const [];
+  final List<DataId> moduleDataNeeded;
+  List<DataId> get resultData => [resultId];
+  final DataId resultId;
+  final DataId inputId;
+  bool get onlyOnMain => false;
+
+  ModuleDataStep(this.action, this.inputId, this.resultId, bool requestInput)
+      : moduleDataNeeded = requestInput ? [inputId] : [];
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    var inputData = await _readHelper(module, root, inputId, toUri);
+    var result =
+        inputData == null ? "data for $module was null" : action(inputData);
+    await File.fromUri(root.resolveUri(toUri(module, resultId)))
+        .writeAsString(result);
+  }
+
+  @override
+  void notifyCached(Module module) {}
+}
+
+class TwoOutputStep implements IOModularStep {
+  final String Function(String) action1;
+  final String Function(String) action2;
+  bool get needsSources => false;
+  List<DataId> get dependencyDataNeeded => const [];
+  List<DataId> get moduleDataNeeded => [inputId];
+  List<DataId> get resultData => [result1Id, result2Id];
+  final DataId result1Id;
+  final DataId result2Id;
+  final DataId inputId;
+  bool get onlyOnMain => false;
+
+  TwoOutputStep(
+      this.action1, this.action2, this.inputId, this.result1Id, this.result2Id);
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    var inputData = await _readHelper(module, root, inputId, toUri);
+    var result1 =
+        inputData == null ? "data for $module was null" : action1(inputData);
+    var result2 =
+        inputData == null ? "data for $module was null" : action2(inputData);
+    await File.fromUri(root.resolveUri(toUri(module, result1Id)))
+        .writeAsString(result1);
+    await File.fromUri(root.resolveUri(toUri(module, result2Id)))
+        .writeAsString(result2);
+  }
+
+  @override
+  void notifyCached(Module module) {}
+}
+
+class LinkStep implements IOModularStep {
+  bool get needsSources => false;
+  final List<DataId> dependencyDataNeeded;
+  List<DataId> get moduleDataNeeded => [inputId];
+  List<DataId> get resultData => [resultId];
+  final String Function(String, List<String>) action;
+  final DataId inputId;
+  final DataId depId;
+  final DataId resultId;
+  bool get onlyOnMain => false;
+
+  LinkStep(this.action, this.inputId, this.depId, this.resultId,
+      bool requestDependencies)
+      : dependencyDataNeeded = requestDependencies ? [depId] : [];
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    List<String> depsData = [];
+    for (var dependency in module.dependencies) {
+      var depData = await _readHelper(dependency, root, depId, toUri);
+      depsData.add(depData);
+    }
+    var inputData = await _readHelper(module, root, inputId, toUri);
+    await File.fromUri(root.resolveUri(toUri(module, resultId)))
+        .writeAsString(action(inputData, depsData));
+  }
+
+  @override
+  void notifyCached(Module module) {}
+}
+
+class MainOnlyStep implements IOModularStep {
+  bool get needsSources => false;
+  final List<DataId> dependencyDataNeeded;
+  List<DataId> get moduleDataNeeded => [inputId];
+  List<DataId> get resultData => [resultId];
+  final String Function(String, List<String>) action;
+  final DataId inputId;
+  final DataId depId;
+  final DataId resultId;
+  bool get onlyOnMain => true;
+
+  MainOnlyStep(this.action, this.inputId, this.depId, this.resultId,
+      bool requestDependencies)
+      : dependencyDataNeeded = requestDependencies ? [depId] : [];
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    List<String> depsData = [];
+    for (var dependency in computeTransitiveDependencies(module)) {
+      var depData = await _readHelper(dependency, root, depId, toUri);
+      depsData.add(depData);
+    }
+    var inputData = await _readHelper(module, root, inputId, toUri);
+    await File.fromUri(root.resolveUri(toUri(module, resultId)))
+        .writeAsString(action(inputData, depsData));
+  }
+
+  @override
+  void notifyCached(Module module) {}
+}
+
+Future<String> _readHelper(Module module, Uri root, DataId dataId,
+    ModuleDataToRelativeUri toUri) async {
+  var file = File.fromUri(root.resolveUri(toUri(module, dataId)));
+  if (await file.exists()) {
+    return await file.readAsString();
+  }
+  return null;
+}
diff --git a/pkg/modular_test/test/loader/conflict_file_folder_error/expectation.txt b/pkg/modular_test/test/loader/conflict_file_folder_error/expectation.txt
new file mode 100644
index 0000000..4a83176
--- /dev/null
+++ b/pkg/modular_test/test/loader/conflict_file_folder_error/expectation.txt
@@ -0,0 +1,3 @@
+# This expectation file is generated by loader_test.dart
+
+Invalid test: The file 'm1.dart' defines a module which conflicts with the module defined by the folder 'm1'.
\ No newline at end of file
diff --git a/pkg/modular_test/test/loader/conflict_file_folder_error/m1.dart b/pkg/modular_test/test/loader/conflict_file_folder_error/m1.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/conflict_file_folder_error/m1.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/conflict_file_folder_error/m1/b.dart b/pkg/modular_test/test/loader/conflict_file_folder_error/m1/b.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/conflict_file_folder_error/m1/b.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/conflict_file_folder_error/modules.yaml b/pkg/modular_test/test/loader/conflict_file_folder_error/modules.yaml
new file mode 100644
index 0000000..c093387
--- /dev/null
+++ b/pkg/modular_test/test/loader/conflict_file_folder_error/modules.yaml
@@ -0,0 +1 @@
+dependencies: {}
diff --git a/pkg/modular_test/test/loader/conflict_file_package_error/expect.dart b/pkg/modular_test/test/loader/conflict_file_package_error/expect.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/conflict_file_package_error/expect.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/conflict_file_package_error/expectation.txt b/pkg/modular_test/test/loader/conflict_file_package_error/expectation.txt
new file mode 100644
index 0000000..cabe77c
--- /dev/null
+++ b/pkg/modular_test/test/loader/conflict_file_package_error/expectation.txt
@@ -0,0 +1,3 @@
+# This expectation file is generated by loader_test.dart
+
+Invalid test: The file 'expect.dart' defines a module called 'expect' which conflicts with a package by the same name that is provided by default.
\ No newline at end of file
diff --git a/pkg/modular_test/test/loader/conflict_file_package_error/modules.yaml b/pkg/modular_test/test/loader/conflict_file_package_error/modules.yaml
new file mode 100644
index 0000000..c093387
--- /dev/null
+++ b/pkg/modular_test/test/loader/conflict_file_package_error/modules.yaml
@@ -0,0 +1 @@
+dependencies: {}
diff --git a/pkg/modular_test/test/loader/conflict_folder_package_error/expect/a.dart b/pkg/modular_test/test/loader/conflict_folder_package_error/expect/a.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/conflict_folder_package_error/expect/a.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/conflict_folder_package_error/expectation.txt b/pkg/modular_test/test/loader/conflict_folder_package_error/expectation.txt
new file mode 100644
index 0000000..5118fc0
--- /dev/null
+++ b/pkg/modular_test/test/loader/conflict_folder_package_error/expectation.txt
@@ -0,0 +1,3 @@
+# This expectation file is generated by loader_test.dart
+
+Invalid test: The folder 'expect' defines a module which conflicts with a package by the same name that is provided by default.
\ No newline at end of file
diff --git a/pkg/modular_test/test/loader/conflict_folder_package_error/modules.yaml b/pkg/modular_test/test/loader/conflict_folder_package_error/modules.yaml
new file mode 100644
index 0000000..c093387
--- /dev/null
+++ b/pkg/modular_test/test/loader/conflict_folder_package_error/modules.yaml
@@ -0,0 +1 @@
+dependencies: {}
diff --git a/pkg/modular_test/test/loader/cycle_error/a.dart b/pkg/modular_test/test/loader/cycle_error/a.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/cycle_error/a.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/cycle_error/b.dart b/pkg/modular_test/test/loader/cycle_error/b.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/cycle_error/b.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/cycle_error/c.dart b/pkg/modular_test/test/loader/cycle_error/c.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/cycle_error/c.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/cycle_error/expectation.txt b/pkg/modular_test/test/loader/cycle_error/expectation.txt
new file mode 100644
index 0000000..3825548
--- /dev/null
+++ b/pkg/modular_test/test/loader/cycle_error/expectation.txt
@@ -0,0 +1,3 @@
+# This expectation file is generated by loader_test.dart
+
+Invalid test: module 'b' has a dependency cycle.
\ No newline at end of file
diff --git a/pkg/modular_test/test/loader/cycle_error/main.dart b/pkg/modular_test/test/loader/cycle_error/main.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/cycle_error/main.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/cycle_error/modules.yaml b/pkg/modular_test/test/loader/cycle_error/modules.yaml
new file mode 100644
index 0000000..b07465b
--- /dev/null
+++ b/pkg/modular_test/test/loader/cycle_error/modules.yaml
@@ -0,0 +1,5 @@
+dependencies:
+  a: b
+  b: c
+  c: a
+  main: b
diff --git a/pkg/modular_test/test/loader/dag/a.dart b/pkg/modular_test/test/loader/dag/a.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag/a.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag/b.dart b/pkg/modular_test/test/loader/dag/b.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag/b.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag/c.dart b/pkg/modular_test/test/loader/dag/c.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag/c.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag/d/d.dart b/pkg/modular_test/test/loader/dag/d/d.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag/d/d.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag/d/e.dart b/pkg/modular_test/test/loader/dag/d/e.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag/d/e.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag/expectation.txt b/pkg/modular_test/test/loader/dag/expectation.txt
new file mode 100644
index 0000000..38220ca
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag/expectation.txt
@@ -0,0 +1,45 @@
+# This expectation file is generated by loader_test.dart
+
+a
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: b, c, sdk
+  a.dart
+
+b
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: d, sdk
+  b.dart
+
+c
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
+  c.dart
+
+d
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
+  d/d.dart
+  d/e.dart
+
+main
+  **main module**
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: a, b, sdk
+  main.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/dag/main.dart b/pkg/modular_test/test/loader/dag/main.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag/main.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag/modules.yaml b/pkg/modular_test/test/loader/dag/modules.yaml
new file mode 100644
index 0000000..0a775d2
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag/modules.yaml
@@ -0,0 +1,4 @@
+dependencies:
+  a: [b, c]
+  b: d
+  main: [a, b]
diff --git a/pkg/modular_test/test/loader/dag_with_packages/.packages b/pkg/modular_test/test/loader/dag_with_packages/.packages
new file mode 100644
index 0000000..194aba9
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag_with_packages/.packages
@@ -0,0 +1,4 @@
+a:a/
+b:b/
+d:d/
+c:c/
diff --git a/pkg/modular_test/test/loader/dag_with_packages/a.dart b/pkg/modular_test/test/loader/dag_with_packages/a.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag_with_packages/a.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag_with_packages/b.dart b/pkg/modular_test/test/loader/dag_with_packages/b.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag_with_packages/b.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag_with_packages/c.dart b/pkg/modular_test/test/loader/dag_with_packages/c.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag_with_packages/c.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag_with_packages/d/d.dart b/pkg/modular_test/test/loader/dag_with_packages/d/d.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag_with_packages/d/d.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag_with_packages/d/e.dart b/pkg/modular_test/test/loader/dag_with_packages/d/e.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag_with_packages/d/e.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag_with_packages/expectation.txt b/pkg/modular_test/test/loader/dag_with_packages/expectation.txt
new file mode 100644
index 0000000..961d6b8
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag_with_packages/expectation.txt
@@ -0,0 +1,45 @@
+# This expectation file is generated by loader_test.dart
+
+a
+  is package? yes
+  is shared?  no
+  is sdk?  no
+  dependencies: b, c, sdk
+  a.dart
+
+b
+  is package? yes
+  is shared?  no
+  is sdk?  no
+  dependencies: d, sdk
+  b.dart
+
+c
+  is package? yes
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
+  c.dart
+
+d
+  is package? yes
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
+  d/d.dart
+  d/e.dart
+
+main
+  **main module**
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: a, b, sdk
+  main.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/dag_with_packages/main.dart b/pkg/modular_test/test/loader/dag_with_packages/main.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag_with_packages/main.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/dag_with_packages/modules.yaml b/pkg/modular_test/test/loader/dag_with_packages/modules.yaml
new file mode 100644
index 0000000..0a775d2
--- /dev/null
+++ b/pkg/modular_test/test/loader/dag_with_packages/modules.yaml
@@ -0,0 +1,4 @@
+dependencies:
+  a: [b, c]
+  b: d
+  main: [a, b]
diff --git a/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt b/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt
new file mode 100644
index 0000000..48e0849
--- /dev/null
+++ b/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt
@@ -0,0 +1,33 @@
+# This expectation file is generated by loader_test.dart
+
+expect
+  is package? yes
+  is shared?  yes
+  is sdk?  no
+  dependencies: meta, sdk
+  lib/expect.dart
+  lib/matchers_lite.dart
+  lib/minitest.dart
+
+main
+  **main module**
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: expect, sdk
+  main.dart
+
+meta
+  is package? yes
+  is shared?  yes
+  is sdk?  no
+  dependencies: sdk
+  lib/dart2js.dart
+  lib/meta.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/default_package_dependency_error/main.dart b/pkg/modular_test/test/loader/default_package_dependency_error/main.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/default_package_dependency_error/main.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/default_package_dependency_error/modules.yaml b/pkg/modular_test/test/loader/default_package_dependency_error/modules.yaml
new file mode 100644
index 0000000..a5864d3
--- /dev/null
+++ b/pkg/modular_test/test/loader/default_package_dependency_error/modules.yaml
@@ -0,0 +1,3 @@
+dependencies:
+  main:
+    - expect
diff --git a/pkg/modular_test/test/loader/invalid_module_name_error/bad.name.dart b/pkg/modular_test/test/loader/invalid_module_name_error/bad.name.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/invalid_module_name_error/bad.name.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/invalid_module_name_error/expectation.txt b/pkg/modular_test/test/loader/invalid_module_name_error/expectation.txt
new file mode 100644
index 0000000..631afff
--- /dev/null
+++ b/pkg/modular_test/test/loader/invalid_module_name_error/expectation.txt
@@ -0,0 +1,3 @@
+# This expectation file is generated by loader_test.dart
+
+Invalid argument(s): invalid module name: bad.name
\ No newline at end of file
diff --git a/pkg/modular_test/test/loader/invalid_module_name_error/modules.yaml b/pkg/modular_test/test/loader/invalid_module_name_error/modules.yaml
new file mode 100644
index 0000000..c093387
--- /dev/null
+++ b/pkg/modular_test/test/loader/invalid_module_name_error/modules.yaml
@@ -0,0 +1 @@
+dependencies: {}
diff --git a/pkg/modular_test/test/loader/invalid_packages_error/.packages b/pkg/modular_test/test/loader/invalid_packages_error/.packages
new file mode 100644
index 0000000..d8892ce
--- /dev/null
+++ b/pkg/modular_test/test/loader/invalid_packages_error/.packages
@@ -0,0 +1 @@
+expect:.
diff --git a/pkg/modular_test/test/loader/invalid_packages_error/expectation.txt b/pkg/modular_test/test/loader/invalid_packages_error/expectation.txt
new file mode 100644
index 0000000..6931c77
--- /dev/null
+++ b/pkg/modular_test/test/loader/invalid_packages_error/expectation.txt
@@ -0,0 +1,3 @@
+# This expectation file is generated by loader_test.dart
+
+Invalid test: .packages file defines an conflicting entry for package 'expect'.
\ No newline at end of file
diff --git a/pkg/modular_test/test/loader/invalid_packages_error/main.dart b/pkg/modular_test/test/loader/invalid_packages_error/main.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/invalid_packages_error/main.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/invalid_packages_error/modules.yaml b/pkg/modular_test/test/loader/invalid_packages_error/modules.yaml
new file mode 100644
index 0000000..a5864d3
--- /dev/null
+++ b/pkg/modular_test/test/loader/invalid_packages_error/modules.yaml
@@ -0,0 +1,3 @@
+dependencies:
+  main:
+    - expect
diff --git a/pkg/modular_test/test/loader/loader_test.dart b/pkg/modular_test/test/loader/loader_test.dart
new file mode 100644
index 0000000..39b3081
--- /dev/null
+++ b/pkg/modular_test/test/loader/loader_test.dart
@@ -0,0 +1,125 @@
+// Copyright (c) 2019, 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.
+
+/// Tests that the logic to load, parse, and validate modular tests.
+import 'dart:io';
+
+import 'package:test/test.dart';
+import 'package:modular_test/src/loader.dart';
+import 'package:modular_test/src/suite.dart';
+
+import 'package:args/args.dart';
+
+main(List<String> args) async {
+  var options = _Options.parse(args);
+  var baseUri = Platform.script.resolve('./');
+  var baseDir = Directory.fromUri(baseUri);
+  await for (var entry in baseDir.list(recursive: false)) {
+    if (entry is Directory) {
+      var dirName = entry.uri.path.substring(baseDir.path.length);
+      test(dirName, () => _runTest(entry.uri, dirName, options),
+          skip: options.filter != null && !dirName.contains(options.filter));
+    }
+  }
+}
+
+Future<void> _runTest(Uri uri, String dirName, _Options options) async {
+  String result;
+  String header =
+      "# This expectation file is generated by loader_test.dart\n\n";
+  try {
+    ModularTest test = await loadTest(uri);
+    result = '$header${_dumpAsText(test)}';
+  } on Error catch (e) {
+    result = '$header$e';
+  }
+
+  var file = File.fromUri(uri.resolve('expectation.txt'));
+  if (!options.updateExpectations) {
+    expect(await file.exists(), isTrue,
+        reason: "expectation.txt file is missing");
+    var expectation = await file.readAsString();
+    if (expectation != result) {
+      print("expectation.txt doesn't match the result of the test. "
+          "To update it, run:\n"
+          "   ${Platform.executable} ${Platform.script} "
+          "--update --show-update --filter $dirName");
+    }
+    expect(expectation, result);
+  } else if (await file.exists() && (await file.readAsString() == result)) {
+    print("  expectation matches result and was up to date.");
+  } else {
+    await file.writeAsString(result);
+    print("  updated ${file.uri}");
+    if (options.showResultOnUpdate) {
+      print('  new expectation is:\x1b[32m\n$result\x1b[0m');
+    }
+  }
+}
+
+String _dumpAsText(ModularTest test) {
+  var buffer = new StringBuffer();
+  bool isFirst = true;
+  for (var module in test.modules) {
+    if (isFirst) {
+      isFirst = false;
+    } else {
+      buffer.write('\n');
+    }
+    buffer.write(module.name);
+    if (module.isMain) {
+      expect(test.mainModule, module);
+      buffer.write('\n  **main module**');
+    }
+    buffer.write('\n  is package? ${module.isPackage ? 'yes' : 'no'}');
+    buffer.write('\n  is shared?  ${module.isShared ? 'yes' : 'no'}');
+    buffer.write('\n  is sdk?  ${module.isSdk ? 'yes' : 'no'}');
+    if (module.dependencies.isEmpty) {
+      buffer.write('\n  (no dependencies)');
+    } else {
+      buffer.write('\n  dependencies: '
+          '${module.dependencies.map((d) => d.name).join(", ")}');
+    }
+
+    if (module.sources.isEmpty) {
+      buffer.write('\n  (no sources)');
+    } else if (module.isSdk) {
+      buffer.write('\n  (sdk sources omitted)');
+    } else {
+      module.sources.forEach((uri) {
+        buffer.write('\n  $uri');
+      });
+    }
+
+    buffer.write('\n');
+  }
+  return '$buffer';
+}
+
+class _Options {
+  bool updateExpectations = false;
+  bool showResultOnUpdate = false;
+  String filter = null;
+
+  static _Options parse(List<String> args) {
+    var parser = new ArgParser()
+      ..addFlag('update',
+          abbr: 'u',
+          defaultsTo: false,
+          help: "update expectation files if the result don't match")
+      ..addFlag('show-update',
+          defaultsTo: false,
+          help: "print the result when updating expectation files")
+      ..addFlag('show-skipped',
+          defaultsTo: false,
+          help: "print the name of the tests skipped by the filtering option")
+      ..addOption('filter',
+          help: "only run tests containing this filter as a substring");
+    ArgResults argResults = parser.parse(args);
+    return _Options()
+      ..updateExpectations = argResults['update']
+      ..showResultOnUpdate = argResults['show-update']
+      ..filter = argResults['filter'];
+  }
+}
diff --git a/pkg/modular_test/test/loader/missing_dependency_module_error/expectation.txt b/pkg/modular_test/test/loader/missing_dependency_module_error/expectation.txt
new file mode 100644
index 0000000..7fc8c8b
--- /dev/null
+++ b/pkg/modular_test/test/loader/missing_dependency_module_error/expectation.txt
@@ -0,0 +1,3 @@
+# This expectation file is generated by loader_test.dart
+
+Invalid test: 'main' declares a dependency on a non existing module named 'foo'
\ No newline at end of file
diff --git a/pkg/modular_test/test/loader/missing_dependency_module_error/main.dart b/pkg/modular_test/test/loader/missing_dependency_module_error/main.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/missing_dependency_module_error/main.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/missing_dependency_module_error/modules.yaml b/pkg/modular_test/test/loader/missing_dependency_module_error/modules.yaml
new file mode 100644
index 0000000..ffd0987
--- /dev/null
+++ b/pkg/modular_test/test/loader/missing_dependency_module_error/modules.yaml
@@ -0,0 +1,3 @@
+dependencies:
+  main:
+    - foo
diff --git a/pkg/modular_test/test/loader/missing_module_error/expectation.txt b/pkg/modular_test/test/loader/missing_module_error/expectation.txt
new file mode 100644
index 0000000..6551c46
--- /dev/null
+++ b/pkg/modular_test/test/loader/missing_module_error/expectation.txt
@@ -0,0 +1,3 @@
+# This expectation file is generated by loader_test.dart
+
+Invalid test: declared dependencies for a non existing module named 'foo'
\ No newline at end of file
diff --git a/pkg/modular_test/test/loader/missing_module_error/main.dart b/pkg/modular_test/test/loader/missing_module_error/main.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/missing_module_error/main.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/missing_module_error/modules.yaml b/pkg/modular_test/test/loader/missing_module_error/modules.yaml
new file mode 100644
index 0000000..87e50e1
--- /dev/null
+++ b/pkg/modular_test/test/loader/missing_module_error/modules.yaml
@@ -0,0 +1,3 @@
+dependencies:
+  foo:
+    - expect
diff --git a/pkg/modular_test/test/loader/missing_yaml_error/a.dart b/pkg/modular_test/test/loader/missing_yaml_error/a.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/missing_yaml_error/a.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/missing_yaml_error/expectation.txt b/pkg/modular_test/test/loader/missing_yaml_error/expectation.txt
new file mode 100644
index 0000000..9dd6322
--- /dev/null
+++ b/pkg/modular_test/test/loader/missing_yaml_error/expectation.txt
@@ -0,0 +1,3 @@
+# This expectation file is generated by loader_test.dart
+
+Invalid test: modules.yaml file is missing
\ No newline at end of file
diff --git a/pkg/modular_test/test/loader/no_dependencies/expectation.txt b/pkg/modular_test/test/loader/no_dependencies/expectation.txt
new file mode 100644
index 0000000..8af18d5
--- /dev/null
+++ b/pkg/modular_test/test/loader/no_dependencies/expectation.txt
@@ -0,0 +1,16 @@
+# This expectation file is generated by loader_test.dart
+
+main
+  **main module**
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
+  main.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/no_dependencies/main.dart b/pkg/modular_test/test/loader/no_dependencies/main.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/no_dependencies/main.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/no_dependencies/modules.yaml b/pkg/modular_test/test/loader/no_dependencies/modules.yaml
new file mode 100644
index 0000000..c093387
--- /dev/null
+++ b/pkg/modular_test/test/loader/no_dependencies/modules.yaml
@@ -0,0 +1 @@
+dependencies: {}
diff --git a/pkg/modular_test/test/loader/no_main_error/a.dart b/pkg/modular_test/test/loader/no_main_error/a.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/no_main_error/a.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/no_main_error/expectation.txt b/pkg/modular_test/test/loader/no_main_error/expectation.txt
new file mode 100644
index 0000000..78e9711
--- /dev/null
+++ b/pkg/modular_test/test/loader/no_main_error/expectation.txt
@@ -0,0 +1,3 @@
+# This expectation file is generated by loader_test.dart
+
+Invalid test: main module is missing
\ No newline at end of file
diff --git a/pkg/modular_test/test/loader/no_main_error/modules.yaml b/pkg/modular_test/test/loader/no_main_error/modules.yaml
new file mode 100644
index 0000000..c093387
--- /dev/null
+++ b/pkg/modular_test/test/loader/no_main_error/modules.yaml
@@ -0,0 +1 @@
+dependencies: {}
diff --git a/pkg/modular_test/test/loader/readme.md b/pkg/modular_test/test/loader/readme.md
new file mode 100644
index 0000000..a3da9fa
--- /dev/null
+++ b/pkg/modular_test/test/loader/readme.md
@@ -0,0 +1,18 @@
+The `loader_test` folder contains a folder per test.
+
+Each test is focusing on part of the features of how tests folders are
+recognized and turned into a modular test specification by our libraries.  Note
+that all `.dart` source files in these tests are empty because we ignore their
+contents.
+
+Each folder contains a file named `expectation.txt` which shows a plain text
+summary of what we expect to extract or report from the test:
+
+ * for invalid inputs it shows the error mesage produced by the modular\_test
+   loader logic
+
+ * for valid inputs it shows the test layout, highlighting what each module
+   contents and dependencies are.
+
+In the future, modular tests will be written in the style of the non-error test
+cases.
diff --git a/pkg/modular_test/test/loader/tree/a.dart b/pkg/modular_test/test/loader/tree/a.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/tree/a.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/tree/b.dart b/pkg/modular_test/test/loader/tree/b.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/tree/b.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/tree/c.dart b/pkg/modular_test/test/loader/tree/c.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/tree/c.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/tree/d/d.dart b/pkg/modular_test/test/loader/tree/d/d.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/tree/d/d.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/tree/d/e.dart b/pkg/modular_test/test/loader/tree/d/e.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/tree/d/e.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/tree/expectation.txt b/pkg/modular_test/test/loader/tree/expectation.txt
new file mode 100644
index 0000000..d2c3d88
--- /dev/null
+++ b/pkg/modular_test/test/loader/tree/expectation.txt
@@ -0,0 +1,45 @@
+# This expectation file is generated by loader_test.dart
+
+a
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: b, c, sdk
+  a.dart
+
+b
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: d, sdk
+  b.dart
+
+c
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
+  c.dart
+
+d
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
+  d/d.dart
+  d/e.dart
+
+main
+  **main module**
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: a, sdk
+  main.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/tree/main.dart b/pkg/modular_test/test/loader/tree/main.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/tree/main.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/tree/modules.yaml b/pkg/modular_test/test/loader/tree/modules.yaml
new file mode 100644
index 0000000..b1254c0
--- /dev/null
+++ b/pkg/modular_test/test/loader/tree/modules.yaml
@@ -0,0 +1,4 @@
+dependencies:
+  a: [b, c]
+  b: d
+  main: a
diff --git a/pkg/modular_test/test/loader/valid_packages/.packages b/pkg/modular_test/test/loader/valid_packages/.packages
new file mode 100644
index 0000000..d8e718b
--- /dev/null
+++ b/pkg/modular_test/test/loader/valid_packages/.packages
@@ -0,0 +1 @@
+js:../../../../js/lib
diff --git a/pkg/modular_test/test/loader/valid_packages/expectation.txt b/pkg/modular_test/test/loader/valid_packages/expectation.txt
new file mode 100644
index 0000000..4ef3034
--- /dev/null
+++ b/pkg/modular_test/test/loader/valid_packages/expectation.txt
@@ -0,0 +1,42 @@
+# This expectation file is generated by loader_test.dart
+
+expect
+  is package? yes
+  is shared?  yes
+  is sdk?  no
+  dependencies: meta, sdk
+  lib/expect.dart
+  lib/matchers_lite.dart
+  lib/minitest.dart
+
+js
+  is package? yes
+  is shared?  yes
+  is sdk?  no
+  dependencies: sdk
+  lib/js.dart
+  lib/js_util.dart
+  lib/src/varargs.dart
+
+main
+  **main module**
+  is package? no
+  is shared?  no
+  is sdk?  no
+  dependencies: js, expect, sdk
+  main.dart
+
+meta
+  is package? yes
+  is shared?  yes
+  is sdk?  no
+  dependencies: sdk
+  lib/dart2js.dart
+  lib/meta.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/valid_packages/main.dart b/pkg/modular_test/test/loader/valid_packages/main.dart
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pkg/modular_test/test/loader/valid_packages/main.dart
@@ -0,0 +1 @@
+
diff --git a/pkg/modular_test/test/loader/valid_packages/modules.yaml b/pkg/modular_test/test/loader/valid_packages/modules.yaml
new file mode 100644
index 0000000..2ad9483
--- /dev/null
+++ b/pkg/modular_test/test/loader/valid_packages/modules.yaml
@@ -0,0 +1,4 @@
+dependencies:
+  main:
+    - js
+    - expect
diff --git a/pkg/modular_test/test/memory_pipeline_test.dart b/pkg/modular_test/test/memory_pipeline_test.dart
new file mode 100644
index 0000000..1d4da36
--- /dev/null
+++ b/pkg/modular_test/test/memory_pipeline_test.dart
@@ -0,0 +1,230 @@
+// Copyright (c) 2019, 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.
+
+/// Unit test for in-memory pipelines.
+import 'dart:async';
+
+import 'package:modular_test/src/memory_pipeline.dart';
+
+import 'pipeline_common.dart';
+
+main() {
+  runPipelineTest(new MemoryPipelineTestStrategy());
+}
+
+/// The strategy implementation to exercise the pipeline test on a
+/// [MemoryPipeline].
+class MemoryPipelineTestStrategy
+    implements PipelineTestStrategy<MemoryModularStep> {
+  @override
+  Uri get testRootUri => Uri.parse('/');
+
+  @override
+  FutureOr<Pipeline<MemoryModularStep>> createPipeline(
+      Map<Uri, String> sources, List<MemoryModularStep> steps,
+      {bool cacheSharedModules: false}) {
+    return new MemoryPipeline(sources, steps,
+        cacheSharedModules: cacheSharedModules);
+  }
+
+  @override
+  MemoryModularStep createSourceOnlyStep(
+          {String Function(Map<Uri, String>) action,
+          DataId resultId,
+          bool requestSources: true}) =>
+      SourceOnlyStep(action, resultId, requestSources);
+
+  @override
+  MemoryModularStep createModuleDataStep(
+          {String Function(String) action,
+          DataId inputId,
+          DataId resultId,
+          bool requestModuleData: true}) =>
+      ModuleDataStep(action, inputId, resultId, requestModuleData);
+
+  @override
+  MemoryModularStep createLinkStep(
+          {String Function(String, List<String>) action,
+          DataId inputId,
+          DataId depId,
+          DataId resultId,
+          bool requestDependenciesData: true}) =>
+      LinkStep(action, inputId, depId, resultId, requestDependenciesData);
+
+  @override
+  MemoryModularStep createMainOnlyStep(
+          {String Function(String, List<String>) action,
+          DataId inputId,
+          DataId depId,
+          DataId resultId,
+          bool requestDependenciesData: true}) =>
+      MainOnlyStep(action, inputId, depId, resultId, requestDependenciesData);
+
+  @override
+  MemoryModularStep createTwoOutputStep(
+          {String Function(String) action1,
+          String Function(String) action2,
+          DataId inputId,
+          DataId result1Id,
+          DataId result2Id}) =>
+      TwoOutputStep(action1, action2, inputId, result1Id, result2Id);
+
+  @override
+  String getResult(covariant MemoryPipeline pipeline, Module m, DataId dataId) {
+    return pipeline.resultsForTesting[m][dataId];
+  }
+
+  FutureOr<void> cleanup(Pipeline<MemoryModularStep> pipeline) => null;
+}
+
+class SourceOnlyStep implements MemoryModularStep {
+  final String Function(Map<Uri, String>) action;
+  final DataId resultId;
+  final bool needsSources;
+  List<DataId> get dependencyDataNeeded => const [];
+  List<DataId> get moduleDataNeeded => const [];
+  List<DataId> get resultData => [resultId];
+  bool get onlyOnMain => false;
+
+  SourceOnlyStep(this.action, this.resultId, this.needsSources);
+
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags) {
+    Map<Uri, String> sources = {};
+    for (var uri in module.sources) {
+      sources[uri] = sourceProvider(module.rootUri.resolveUri(uri));
+    }
+    return Future.value({resultId: action(sources)});
+  }
+
+  @override
+  void notifyCached(Module module) {}
+}
+
+class ModuleDataStep implements MemoryModularStep {
+  final String Function(String) action;
+  bool get needsSources => false;
+  List<DataId> get dependencyDataNeeded => const [];
+  final List<DataId> moduleDataNeeded;
+  List<DataId> get resultData => [resultId];
+  final DataId resultId;
+  final DataId inputId;
+  bool get onlyOnMain => false;
+
+  ModuleDataStep(this.action, this.inputId, this.resultId, bool requestInput)
+      : moduleDataNeeded = requestInput ? [inputId] : [];
+
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags) {
+    var inputData = dataProvider(module, inputId) as String;
+    if (inputData == null)
+      return Future.value({resultId: "data for $module was null"});
+    return Future.value({resultId: action(inputData)});
+  }
+
+  @override
+  void notifyCached(Module module) {}
+}
+
+class TwoOutputStep implements MemoryModularStep {
+  final String Function(String) action1;
+  final String Function(String) action2;
+  bool get needsSources => false;
+  List<DataId> get dependencyDataNeeded => const [];
+  List<DataId> get moduleDataNeeded => [inputId];
+  List<DataId> get resultData => [result1Id, result2Id];
+  final DataId result1Id;
+  final DataId result2Id;
+  final DataId inputId;
+  bool get onlyOnMain => false;
+
+  TwoOutputStep(
+      this.action1, this.action2, this.inputId, this.result1Id, this.result2Id);
+
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags) {
+    var inputData = dataProvider(module, inputId) as String;
+    if (inputData == null)
+      return Future.value({
+        result1Id: "data for $module was null",
+        result2Id: "data for $module was null",
+      });
+    return Future.value(
+        {result1Id: action1(inputData), result2Id: action2(inputData)});
+  }
+
+  @override
+  void notifyCached(Module module) {}
+}
+
+class LinkStep implements MemoryModularStep {
+  bool get needsSources => false;
+  final List<DataId> dependencyDataNeeded;
+  List<DataId> get moduleDataNeeded => [inputId];
+  final String Function(String, List<String>) action;
+  final DataId inputId;
+  final DataId depId;
+  final DataId resultId;
+  List<DataId> get resultData => [resultId];
+  bool get onlyOnMain => false;
+
+  LinkStep(this.action, this.inputId, this.depId, this.resultId,
+      bool requestDependencies)
+      : dependencyDataNeeded = requestDependencies ? [depId] : [];
+
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags) {
+    List<String> depsData = module.dependencies
+        .map((d) => dataProvider(d, depId) as String)
+        .toList();
+    var inputData = dataProvider(module, inputId) as String;
+    return Future.value({resultId: action(inputData, depsData)});
+  }
+
+  @override
+  void notifyCached(Module module) {}
+}
+
+class MainOnlyStep implements MemoryModularStep {
+  bool get needsSources => false;
+  final List<DataId> dependencyDataNeeded;
+  List<DataId> get moduleDataNeeded => [inputId];
+  final String Function(String, List<String>) action;
+  final DataId inputId;
+  final DataId depId;
+  final DataId resultId;
+  List<DataId> get resultData => [resultId];
+  bool get onlyOnMain => true;
+
+  MainOnlyStep(this.action, this.inputId, this.depId, this.resultId,
+      bool requestDependencies)
+      : dependencyDataNeeded = requestDependencies ? [depId] : [];
+
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags) {
+    List<String> depsData = computeTransitiveDependencies(module)
+        .map((d) => dataProvider(d, depId) as String)
+        .toList();
+    var inputData = dataProvider(module, inputId) as String;
+    return Future.value({resultId: action(inputData, depsData)});
+  }
+
+  @override
+  void notifyCached(Module module) {}
+}
diff --git a/pkg/modular_test/test/pipeline_common.dart b/pkg/modular_test/test/pipeline_common.dart
new file mode 100644
index 0000000..7bfbf77
--- /dev/null
+++ b/pkg/modular_test/test/pipeline_common.dart
@@ -0,0 +1,438 @@
+// Copyright (c) 2019, 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.
+
+/// Defines the abstract skeleton of the memory and io pipeline tests.
+///
+/// The idea is to ensure that pipelines are evaluated in the expected order
+/// and that steps are hermetic in that they are only provided the data they
+/// request.
+///
+/// We place most of the logic here to guarantee that the two different pipeline
+/// implementations are consistent with each other.
+import 'dart:async';
+
+import 'package:test/test.dart';
+import 'package:modular_test/src/suite.dart';
+import 'package:modular_test/src/pipeline.dart';
+
+export 'package:modular_test/src/suite.dart';
+export 'package:modular_test/src/pipeline.dart';
+
+/// A strategy to create the steps and pipelines used by the pipeline test. This
+/// is implemented in `memory_pipeline_test.dart` and `io_pipeline_test.dart`.
+abstract class PipelineTestStrategy<S extends ModularStep> {
+  /// Root URI where test sources are found.
+  Uri get testRootUri;
+
+  /// Creates a pipeline with the given sources and steps. Steps will be created
+  /// by other methods in this strategy to ensure they are compatible with to
+  /// the pipeline created here.
+  FutureOr<Pipeline<S>> createPipeline(Map<Uri, String> sources, List<S> steps,
+      {bool cacheSharedModules: false});
+
+  /// Create a step that applies [action] on all input files of the module, and
+  /// emits a result with the given [id]
+  S createSourceOnlyStep(
+      {String Function(Map<Uri, String>) action,
+      DataId resultId,
+      bool requestSources: true});
+
+  /// Create a step that applies [action] on the module [inputId] data, and
+  /// emits a result with the given [resultId].
+  S createModuleDataStep(
+      {String Function(String) action,
+      DataId inputId,
+      DataId resultId,
+      bool requestModuleData: true});
+
+  /// Create a step that applies [action] on the module [inputId] data and the
+  /// the [depId] data of dependencies and finally emits a result with the given
+  /// [resultId].
+  ///
+  /// [depId] may be the same as [resultId] or [inputId].
+  S createLinkStep(
+      {String Function(String, List<String>) action,
+      DataId inputId,
+      DataId depId,
+      DataId resultId,
+      bool requestDependenciesData: true});
+
+  /// Create a step that applies [action] only on the main module [inputId] data
+  /// and the the [depId] data of transitive dependencies and finally emits a
+  /// result with the given [resultId].
+  ///
+  /// [depId] may be the same as [inputId] but not [resultId] since this action
+  /// is only applied on the main module.
+  S createMainOnlyStep(
+      {String Function(String, List<String>) action,
+      DataId inputId,
+      DataId depId,
+      DataId resultId,
+      bool requestDependenciesData: true});
+
+  /// Create a step that applies [action1] and [action2] on the module [inputId]
+  /// data, and emits two results with the given [result1Id] and [result2Id].
+  S createTwoOutputStep(
+      {String Function(String) action1,
+      String Function(String) action2,
+      DataId inputId,
+      DataId result1Id,
+      DataId result2Id});
+
+  /// Return the result data produced by a modular step.
+  String getResult(Pipeline<S> pipeline, Module m, DataId dataId);
+
+  /// Do any cleanup work needed after pipeline is completed. Needed because
+  /// some implementations retain data around to be able to answer [getResult]
+  /// queries.
+  FutureOr<void> cleanup(Pipeline<S> pipeline);
+}
+
+runPipelineTest<S extends ModularStep>(PipelineTestStrategy<S> testStrategy) {
+  var sources = {
+    testStrategy.testRootUri.resolve("a1.dart"): 'A1',
+    testStrategy.testRootUri.resolve("a2.dart"): 'A2',
+    testStrategy.testRootUri.resolve("b/b1.dart"): 'B1',
+    testStrategy.testRootUri.resolve("b/b2.dart"): 'B2',
+    testStrategy.testRootUri.resolve("c.dart"): 'C0',
+  };
+
+  var m1 = Module("a", const [], testStrategy.testRootUri,
+      [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+      isShared: true);
+  var m2 = Module("b", [m1], testStrategy.testRootUri,
+      [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")]);
+  var m3 = Module("c", [m2], testStrategy.testRootUri, [Uri.parse("c.dart")],
+      isMain: true);
+
+  var singleModuleInput = ModularTest([m1], m1, []);
+  var twoModuleInput = ModularTest([m1, m2], m2, []);
+  var threeModuleInput = ModularTest([m1, m2, m3], m3, []);
+
+  test('can read source data if requested', () async {
+    var concatStep =
+        testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+    var pipeline = await testStrategy.createPipeline(sources, <S>[concatStep]);
+    await pipeline.run(singleModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, _concatId),
+        "a1.dart: A1\na2.dart: A2\n");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('cannot read source data if not requested', () async {
+    var concatStep = testStrategy.createSourceOnlyStep(
+        action: _concat, resultId: _concatId, requestSources: false);
+    var pipeline = await testStrategy.createPipeline(sources, <S>[concatStep]);
+    await pipeline.run(singleModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, _concatId),
+        "a1.dart: null\na2.dart: null\n");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('step is applied to all modules', () async {
+    var concatStep =
+        testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+    var pipeline = await testStrategy.createPipeline(sources, <S>[concatStep]);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, _concatId),
+        "a1.dart: A1\na2.dart: A2\n");
+    expect(testStrategy.getResult(pipeline, m2, _concatId),
+        "b/b1.dart: B1\nb/b2.dart: B2\n");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('can read previous step results if requested', () async {
+    var concatStep =
+        testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+    var lowercaseStep = testStrategy.createModuleDataStep(
+        action: _lowercase, inputId: _concatId, resultId: _lowercaseId);
+    var pipeline = await testStrategy
+        .createPipeline(sources, <S>[concatStep, lowercaseStep]);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, _lowercaseId),
+        "a1.dart: a1\na2.dart: a2\n");
+    expect(testStrategy.getResult(pipeline, m2, _lowercaseId),
+        "b/b1.dart: b1\nb/b2.dart: b2\n");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('cannot read previous step results if not requested', () async {
+    var concatStep =
+        testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+    var lowercaseStep = testStrategy.createModuleDataStep(
+        action: _lowercase,
+        inputId: _concatId,
+        resultId: _lowercaseId,
+        requestModuleData: false);
+    var pipeline = await testStrategy
+        .createPipeline(sources, <S>[concatStep, lowercaseStep]);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, _lowercaseId),
+        "data for [module a] was null");
+    expect(testStrategy.getResult(pipeline, m2, _lowercaseId),
+        "data for [module b] was null");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('all outputs of a step are created together', () async {
+    var concatStep =
+        testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+    var twoOutputStep = testStrategy.createTwoOutputStep(
+        action1: _lowercase,
+        action2: _uppercase,
+        inputId: _concatId,
+        result1Id: _lowercaseId,
+        result2Id: _uppercaseId);
+    var pipeline = await testStrategy
+        .createPipeline(sources, <S>[concatStep, twoOutputStep]);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m2, _lowercaseId),
+        "b/b1.dart: b1\nb/b2.dart: b2\n");
+    expect(testStrategy.getResult(pipeline, m2, _uppercaseId),
+        "B/B1.DART: B1\nB/B2.DART: B2\n");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('can read same-step results of dependencies if requested', () async {
+    var concatStep =
+        testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+    var lowercaseStep = testStrategy.createModuleDataStep(
+        action: _lowercase, inputId: _concatId, resultId: _lowercaseId);
+    var replaceJoinStep = testStrategy.createLinkStep(
+        action: _replaceAndJoin,
+        inputId: _lowercaseId,
+        depId: _joinId,
+        resultId: _joinId);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[concatStep, lowercaseStep, replaceJoinStep]);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, _joinId), "a1 a1\na2 a2\n");
+    expect(testStrategy.getResult(pipeline, m2, _joinId),
+        "a1 a1\na2 a2\n\nb/b1 b1\nb/b2 b2\n");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('cannot read same-step results of dependencies if not requested',
+      () async {
+    var concatStep =
+        testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+    var lowercaseStep = testStrategy.createModuleDataStep(
+        action: _lowercase, inputId: _concatId, resultId: _lowercaseId);
+    var replaceJoinStep = testStrategy.createLinkStep(
+        action: _replaceAndJoin,
+        inputId: _lowercaseId,
+        depId: _joinId,
+        resultId: _joinId,
+        requestDependenciesData: false);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[concatStep, lowercaseStep, replaceJoinStep]);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, _joinId), "a1 a1\na2 a2\n");
+    expect(testStrategy.getResult(pipeline, m2, _joinId),
+        "null\nb/b1 b1\nb/b2 b2\n");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('can read prior step results of dependencies if requested', () async {
+    var concatStep =
+        testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+    var lowercaseStep = testStrategy.createModuleDataStep(
+        action: _lowercase, inputId: _concatId, resultId: _lowercaseId);
+    var replaceJoinStep = testStrategy.createLinkStep(
+        action: _replaceAndJoin,
+        inputId: _lowercaseId,
+        depId: _lowercaseId,
+        resultId: _joinId);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[concatStep, lowercaseStep, replaceJoinStep]);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, _joinId), "a1 a1\na2 a2\n");
+    expect(testStrategy.getResult(pipeline, m2, _joinId),
+        "a1.dart: a1\na2.dart: a2\n\nb/b1 b1\nb/b2 b2\n");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('cannot read prior step results of dependencies if not requested',
+      () async {
+    var concatStep =
+        testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+    var lowercaseStep = testStrategy.createModuleDataStep(
+        action: _lowercase, inputId: _concatId, resultId: _lowercaseId);
+    var replaceJoinStep = testStrategy.createLinkStep(
+        action: _replaceAndJoin,
+        inputId: _lowercaseId,
+        depId: _lowercaseId,
+        resultId: _joinId,
+        requestDependenciesData: false);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[concatStep, lowercaseStep, replaceJoinStep]);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, _joinId), "a1 a1\na2 a2\n");
+    expect(testStrategy.getResult(pipeline, m2, _joinId),
+        "null\nb/b1 b1\nb/b2 b2\n");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('only main applies to main module', () async {
+    var concatStep =
+        testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+    var lowercaseStep = testStrategy.createModuleDataStep(
+        action: _lowercase, inputId: _concatId, resultId: _lowercaseId);
+    var replaceJoinStep = testStrategy.createMainOnlyStep(
+        action: _replaceAndJoin,
+        inputId: _lowercaseId,
+        depId: _lowercaseId,
+        resultId: _joinId,
+        requestDependenciesData: true);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[concatStep, lowercaseStep, replaceJoinStep]);
+    await pipeline.run(threeModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, _joinId), null);
+    expect(testStrategy.getResult(pipeline, m3, _joinId),
+        "b/b1.dart: b1\nb/b2.dart: b2\n\na1.dart: a1\na2.dart: a2\n\nc c0\n");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('only main also needs to request transitive dependencies', () async {
+    var concatStep =
+        testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+    var lowercaseStep = testStrategy.createModuleDataStep(
+        action: _lowercase, inputId: _concatId, resultId: _lowercaseId);
+    var replaceJoinStep = testStrategy.createMainOnlyStep(
+        action: _replaceAndJoin,
+        inputId: _lowercaseId,
+        depId: _lowercaseId,
+        resultId: _joinId,
+        requestDependenciesData: false);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[concatStep, lowercaseStep, replaceJoinStep]);
+    await pipeline.run(threeModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, _joinId), null);
+    expect(testStrategy.getResult(pipeline, m3, _joinId), "null\nnull\nc c0\n");
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('no reuse of existing results if not caching', () async {
+    int i = 1;
+    const counterId = const DataId("counter");
+    const linkId = const DataId("link");
+    // This step is not idempotent, we do this purposely to test whether caching
+    // is taking place.
+    var counterStep = testStrategy.createSourceOnlyStep(
+        action: (_) => '${i++}', resultId: counterId);
+    var linkStep = testStrategy.createLinkStep(
+        action: (String m, List<String> deps) => "${deps.join(',')},$m",
+        inputId: counterId,
+        depId: counterId,
+        resultId: linkId,
+        requestDependenciesData: true);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[counterStep, linkStep],
+        cacheSharedModules: false);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "1");
+    expect(testStrategy.getResult(pipeline, m2, counterId), "2");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "1,2");
+
+    await pipeline.run(threeModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "3");
+    expect(testStrategy.getResult(pipeline, m2, counterId), "4");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "3,4");
+    expect(testStrategy.getResult(pipeline, m3, counterId), "5");
+    expect(testStrategy.getResult(pipeline, m3, linkId), "4,5");
+
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('caching reuses existing results for the same configuration', () async {
+    int i = 1;
+    const counterId = const DataId("counter");
+    const linkId = const DataId("link");
+    var counterStep = testStrategy.createSourceOnlyStep(
+        action: (_) => '${i++}', resultId: counterId);
+    var linkStep = testStrategy.createLinkStep(
+        action: (String m, List<String> deps) => "${deps.join(',')},$m",
+        inputId: counterId,
+        depId: counterId,
+        resultId: linkId,
+        requestDependenciesData: true);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[counterStep, linkStep],
+        cacheSharedModules: true);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "1");
+    expect(testStrategy.getResult(pipeline, m2, counterId), "2");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "1,2");
+
+    await pipeline.run(threeModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "1"); // cached!
+    expect(testStrategy.getResult(pipeline, m2, counterId), "3");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "1,3");
+    expect(testStrategy.getResult(pipeline, m3, counterId), "4");
+    expect(testStrategy.getResult(pipeline, m3, linkId), "3,4");
+
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('no reuse of existing results on different configurations', () async {
+    int i = 1;
+    const counterId = const DataId("counter");
+    const linkId = const DataId("link");
+    // This step is not idempotent, we do this purposely to test whether caching
+    // is taking place.
+    var counterStep = testStrategy.createSourceOnlyStep(
+        action: (_) => '${i++}', resultId: counterId);
+    var linkStep = testStrategy.createLinkStep(
+        action: (String m, List<String> deps) => "${deps.join(',')},$m",
+        inputId: counterId,
+        depId: counterId,
+        resultId: linkId,
+        requestDependenciesData: true);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[counterStep, linkStep],
+        cacheSharedModules: true);
+    var input1 = ModularTest([m1, m2], m2, []);
+    var input2 = ModularTest([m1, m2], m2, ['--foo']);
+    var input3 = ModularTest([m1, m2], m2, ['--foo']);
+    await pipeline.run(input1);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "1");
+    expect(testStrategy.getResult(pipeline, m2, counterId), "2");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "1,2");
+
+    await pipeline.run(input2);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "3"); // no cache!
+    expect(testStrategy.getResult(pipeline, m2, counterId), "4");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "3,4");
+
+    await pipeline.run(input3);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "3"); // same config
+    expect(testStrategy.getResult(pipeline, m2, counterId), "5");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "3,5");
+
+    await testStrategy.cleanup(pipeline);
+  });
+}
+
+DataId _concatId = const DataId("concat");
+DataId _lowercaseId = const DataId("lowercase");
+DataId _uppercaseId = const DataId("uppercase");
+DataId _joinId = const DataId("join");
+
+String _concat(Map<Uri, String> sources) {
+  var buffer = new StringBuffer();
+  sources.forEach((uri, contents) {
+    buffer.write("$uri: $contents\n");
+  });
+  return '$buffer';
+}
+
+String _lowercase(String contents) => contents.toLowerCase();
+String _uppercase(String contents) => contents.toUpperCase();
+
+String _replaceAndJoin(String moduleData, List<String> depContents) {
+  var buffer = new StringBuffer();
+  depContents.forEach(buffer.writeln);
+  buffer.write(moduleData.replaceAll(".dart:", ""));
+  return '$buffer';
+}
diff --git a/pkg/modular_test/test/specification_parser_test.dart b/pkg/modular_test/test/specification_parser_test.dart
new file mode 100644
index 0000000..6940d5e9
--- /dev/null
+++ b/pkg/modular_test/test/specification_parser_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2019, 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:test/test.dart';
+import 'package:modular_test/src/test_specification_parser.dart';
+
+main() {
+  test('require dependencies section', () {
+    expect(() => parseTestSpecification(""),
+        throwsA(TypeMatcher<InvalidSpecificationError>()));
+  });
+
+  test('dependencies is a map', () {
+    expect(() => parseTestSpecification("dependencies: []"),
+        throwsA(TypeMatcher<InvalidSpecificationError>()));
+  });
+
+  test('dependencies can be a string or list of strings', () {
+    parseTestSpecification('''
+          dependencies:
+            a: b
+          ''');
+
+    parseTestSpecification('''
+          dependencies:
+            a: [b, c]
+          ''');
+
+    expect(() => parseTestSpecification('''
+          dependencies:
+            a: 1
+          '''), throwsA(TypeMatcher<InvalidSpecificationError>()));
+
+    expect(() => parseTestSpecification('''
+          dependencies:
+            a: true
+          '''), throwsA(TypeMatcher<InvalidSpecificationError>()));
+
+    expect(() => parseTestSpecification('''
+          dependencies:
+            a: [false]
+          '''), throwsA(TypeMatcher<InvalidSpecificationError>()));
+
+    expect(() => parseTestSpecification('''
+          dependencies:
+            a:
+               c: d
+          '''), throwsA(TypeMatcher<InvalidSpecificationError>()));
+  });
+
+  test('result map is normalized', () {
+    expect(
+        parseTestSpecification('''
+          dependencies:
+            a: [b, c]
+            b: d
+            ''').dependencies,
+        equals({
+          'a': ['b', 'c'],
+          'b': ['d'],
+        }));
+  });
+
+  test('flags are normalized', () {
+    expect(parseTestSpecification('''
+          dependencies: {}
+          flags: "a"
+            ''').flags, equals(["a"]));
+
+    expect(parseTestSpecification('''
+          dependencies: {}
+          flags: ["a"]
+            ''').flags, equals(["a"]));
+  });
+}
diff --git a/pkg/modular_test/test/src/find_sdk_root2_test.dart b/pkg/modular_test/test/src/find_sdk_root2_test.dart
new file mode 100644
index 0000000..0bfbeb6
--- /dev/null
+++ b/pkg/modular_test/test/src/find_sdk_root2_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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:io';
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'package:modular_test/src/find_sdk_root.dart';
+
+main() {
+  asyncTest(() async {
+    Expect.equals(Platform.script.resolve("../../../../"), await findRoot());
+  });
+}
diff --git a/pkg/modular_test/test/validate_pipeline_test.dart b/pkg/modular_test/test/validate_pipeline_test.dart
new file mode 100644
index 0000000..a0b5759
--- /dev/null
+++ b/pkg/modular_test/test/validate_pipeline_test.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2019, 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.
+
+/// Unit test for validation of modular steps in a pipeline.
+import 'package:test/test.dart';
+import 'package:modular_test/src/suite.dart';
+import 'package:modular_test/src/pipeline.dart';
+
+main() {
+  test('no steps is OK', () {
+    validateSteps([]);
+  });
+
+  test('no errors', () {
+    var id1 = DataId("data_a");
+    var id2 = DataId("data_b");
+    var id3 = DataId("data_c");
+    validateSteps([
+      ModularStep(
+          needsSources: true, dependencyDataNeeded: [id1], resultData: [id1]),
+      ModularStep(moduleDataNeeded: [id1], resultData: [id2]),
+      ModularStep(
+          moduleDataNeeded: [id2],
+          dependencyDataNeeded: [id1, id3],
+          resultData: [id3]),
+    ]);
+  });
+
+  test('circular step dependency is not allowed', () {
+    var id1 = DataId("data_a");
+    expect(
+        () => validateSteps([
+              ModularStep(moduleDataNeeded: [id1], resultData: [id1]),
+            ]),
+        throwsA(TypeMatcher<InvalidPipelineError>()));
+  });
+
+  test('some results must be declared', () {
+    expect(() => validateSteps([ModularStep()]),
+        throwsA(TypeMatcher<InvalidPipelineError>()));
+    expect(() => validateSteps([ModularStep(resultData: [])]),
+        throwsA(TypeMatcher<InvalidPipelineError>()));
+  });
+
+  test('out of order dependencies are not allowed', () {
+    var id1 = DataId("data_a");
+    var id2 = DataId("data_b");
+    validateSteps([
+      // id1 must be produced before it is consumed.
+      ModularStep(resultData: [id1]),
+      ModularStep(dependencyDataNeeded: [id1], resultData: [id2]),
+    ]);
+
+    expect(
+        () => validateSteps([
+              ModularStep(dependencyDataNeeded: [id1], resultData: [id2]),
+              ModularStep(resultData: [id1]),
+            ]),
+        throwsA(TypeMatcher<InvalidPipelineError>()));
+  });
+
+  test('same data cannot be produced by two steps', () {
+    var id1 = DataId("data_a");
+    expect(
+        () => validateSteps([
+              ModularStep(resultData: [id1]),
+              ModularStep(resultData: [id1]),
+            ]),
+        throwsA(TypeMatcher<InvalidPipelineError>()));
+  });
+}
+
+validateSteps(List<ModularStep> steps) {
+  new _NoopPipeline(steps);
+}
+
+/// An implementation of [Pipeline] that simply validates the steps, but doesn't
+/// do anything else.
+class _NoopPipeline extends Pipeline {
+  _NoopPipeline(List<ModularStep> steps) : super(steps, false);
+
+  @override
+  Future<void> runStep(ModularStep step, Module module,
+          Map<Module, Set<DataId>> visibleData, List<String> flags) =>
+      null;
+}
diff --git a/pkg/modular_test/test/validate_suite_test.dart b/pkg/modular_test/test/validate_suite_test.dart
new file mode 100644
index 0000000..f335567
--- /dev/null
+++ b/pkg/modular_test/test/validate_suite_test.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2019, 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.
+
+/// Unit test for validation of modular steps in a pipeline.
+import 'package:test/test.dart';
+import 'package:modular_test/src/suite.dart';
+
+main() {
+  test('module test is not empty', () {
+    expect(
+        () => ModularTest([], null, []), throwsA(TypeMatcher<ArgumentError>()));
+
+    var m = Module("a", [], Uri.parse("app:/"), []);
+    expect(() => ModularTest([], m, []), throwsA(TypeMatcher<ArgumentError>()));
+  });
+
+  test('module test must have a main module', () {
+    var m = Module("a", [], Uri.parse("app:/"), []);
+    expect(() => ModularTest([m], null, []),
+        throwsA(TypeMatcher<ArgumentError>()));
+  });
+
+  test('package must depend on package', () {
+    var m1a = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isPackage: false);
+    var m1b = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isPackage: true);
+
+    var m2a = Module("b", [m1a], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isPackage: true);
+    var m2b = Module("b", [m1b], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isPackage: true);
+    expect(() => ModularTest([m1a, m2a], m2a, []),
+        throwsA(TypeMatcher<InvalidModularTestError>()));
+    expect(ModularTest([m1b, m2b], m2b, []), isNotNull);
+  });
+
+  test('shared module must depend on shared modules', () {
+    var m1a = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isShared: false);
+    var m1b = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isShared: true);
+
+    var m2a = Module("b", [m1a], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isShared: true);
+    var m2b = Module("b", [m1b], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isShared: true);
+    expect(() => ModularTest([m1a, m2a], m2a, []),
+        throwsA(TypeMatcher<InvalidModularTestError>()));
+    expect(ModularTest([m1b, m2b], m2b, []), isNotNull);
+  });
+
+  test('sdk module must not have dependencies', () {
+    var m1a = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isSdk: false);
+    var m1b = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isSdk: true);
+
+    var m2a = Module("b", [m1a], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isSdk: true);
+    var m2b = Module("b", [m1b], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isSdk: true);
+    expect(() => ModularTest([m1a, m2a], m2a, []),
+        throwsA(TypeMatcher<InvalidModularTestError>()));
+    expect(() => ModularTest([m1b, m2b], m2b, []),
+        throwsA(TypeMatcher<InvalidModularTestError>()));
+  });
+
+  test('sdk module cannot be package module', () {
+    var m = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isSdk: true);
+    expect(ModularTest([m], m, []), isNotNull);
+
+    m.isPackage = true;
+    expect(() => ModularTest([m], m, []),
+        throwsA(TypeMatcher<InvalidModularTestError>()));
+  });
+}
diff --git a/pkg/nnbd_migration/CHANGELOG.md b/pkg/nnbd_migration/CHANGELOG.md
new file mode 100644
index 0000000..aea8052
--- /dev/null
+++ b/pkg/nnbd_migration/CHANGELOG.md
@@ -0,0 +1,2 @@
+## 0.1.0-dev (not yet published)
+* Separated from analysis_server project.
diff --git a/pkg/nnbd_migration/LICENSE b/pkg/nnbd_migration/LICENSE
new file mode 100644
index 0000000..f75d7c2
--- /dev/null
+++ b/pkg/nnbd_migration/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2019, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/nnbd_migration/README.md b/pkg/nnbd_migration/README.md
new file mode 100644
index 0000000..b1d8f0a
--- /dev/null
+++ b/pkg/nnbd_migration/README.md
@@ -0,0 +1,4 @@
+# NNBD Migration Engine
+
+This package provides infrastructure for migrating code to be non-nullable by
+default.
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
new file mode 100644
index 0000000..33afb82
--- /dev/null
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2019, 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:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:meta/meta.dart';
+import 'package:nnbd_migration/src/nullability_migration_impl.dart';
+
+/// Kinds of fixes that might be performed by nullability migration.
+class NullabilityFixKind {
+  /// An import needs to be added.
+  static const addImport =
+      const NullabilityFixKind._(appliedMessage: 'Add an import');
+
+  /// A formal parameter needs to have a required annotation added.
+  static const addRequired =
+      const NullabilityFixKind._(appliedMessage: 'Add a required annotation');
+
+  /// An expression's value needs to be null-checked.
+  static const checkExpression = const NullabilityFixKind._(
+    appliedMessage: 'Added a null check to an expression',
+  );
+
+  /// An explicit type mentioned in the source program needs to be made
+  /// nullable.
+  static const makeTypeNullable = const NullabilityFixKind._(
+    appliedMessage: 'Changed a type to be nullable',
+  );
+
+  /// An if-test or conditional expression needs to have its "then" branch
+  /// discarded.
+  static const discardThen = const NullabilityFixKind._(
+    appliedMessage: 'Discarded an unreachable conditional then branch',
+  );
+
+  /// An if-test or conditional expression needs to have its "else" branch
+  /// discarded.
+  static const discardElse = const NullabilityFixKind._(
+    appliedMessage: 'Discarded an unreachable conditional else branch',
+  );
+
+  /// A message used by dartfix to indicate a fix has been applied.
+  final String appliedMessage;
+
+  const NullabilityFixKind._({@required this.appliedMessage});
+}
+
+/// Provisional API for DartFix to perform nullability migration.
+///
+/// Usage: pass each input source file to [prepareInput].  Then pass each input
+/// source file to [processInput].  Then call [finish] to obtain the
+/// modifications that need to be made to each source file.
+abstract class NullabilityMigration {
+  /// Prepares to perform nullability migration.
+  ///
+  /// If [permissive] is `true`, exception handling logic will try to proceed
+  /// as far as possible even though the migration algorithm is not yet
+  /// complete.  TODO(paulberry): remove this mode once the migration algorithm
+  /// is fully implemented.
+  factory NullabilityMigration(NullabilityMigrationListener listener,
+      {bool permissive}) = NullabilityMigrationImpl;
+
+  void finish();
+
+  void prepareInput(ResolvedUnitResult result);
+
+  void processInput(ResolvedUnitResult result);
+}
+
+/// [NullabilityMigrationListener] is used by [NullabilityMigration]
+/// to communicate source changes or "fixes" to the client.
+abstract class NullabilityMigrationListener {
+  /// Add the given [detail] to the list of details to be returned to the
+  /// client.
+  void addDetail(String detail);
+
+  /// [addEdit] is called once for each source edit, in the order in which they
+  /// appear in the source file.
+  void addEdit(SingleNullabilityFix fix, SourceEdit edit);
+
+  /// [addFix] is called once for each source change.
+  void addFix(SingleNullabilityFix fix);
+}
+
+/// Representation of a single conceptual change made by the nullability
+/// migration algorithm.  This change might require multiple source edits to
+/// achieve.
+abstract class SingleNullabilityFix {
+  /// What kind of fix this is.
+  NullabilityFixKind get kind;
+
+  /// Location of the change, for reporting to the user.
+  Location get location;
+
+  /// File to change.
+  Source get source;
+}
diff --git a/pkg/nnbd_migration/lib/src/conditional_discard.dart b/pkg/nnbd_migration/lib/src/conditional_discard.dart
new file mode 100644
index 0000000..144bd82
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/conditional_discard.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2019, 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:nnbd_migration/src/nullability_node.dart';
+
+/// Container for information gathered during nullability migration about a
+/// conditional check that might need to be discarded.
+///
+/// This information will be associated with an Expression in the input program
+/// whose boolean value influences control flow (e.g. the condition of an `if`
+/// statement).
+class ConditionalDiscard {
+  /// Nullability node that will be `nullable` if the code path that results
+  /// from the condition evaluating to `true` will be reachable after
+  /// nullability migration, and therefore should be kept.
+  ///
+  /// `null` if the code path should be kept regardless of the outcome of
+  /// migration.
+  final NullabilityNode trueGuard;
+
+  /// Nullability node that will be `nullable` if the code path that results
+  /// from the condition evaluating to `false` will be reachable after
+  /// nullability migration, and therefore should be kept.
+  ///
+  /// `null` if the code path should be kept regardless of the outcome of
+  /// migration.
+  final NullabilityNode falseGuard;
+
+  /// Indicates whether the condition is pure (free from side effects).
+  ///
+  /// For example, a condition like `x == null` is pure (assuming `x` is a local
+  /// variable or static variable), because evaluating it has no user-visible
+  /// effect other than returning a boolean value.
+  ///
+  /// If [pureCondition] is `false`, and either [trueGuard] or [falseGuard] is
+  /// `false`, that it is safe to delete the condition expression as well as the
+  /// dead code branch (e.g. it means that `if (x == null) f(); else g();` could
+  /// be changed to simply `g();`).
+  final bool pureCondition;
+
+  ConditionalDiscard(this.trueGuard, this.falseGuard, this.pureCondition);
+
+  /// Indicates whether the code path that results from the condition evaluating
+  /// to `false` is reachable after migration.
+  bool get keepFalse => falseGuard == null || falseGuard.isNullable;
+
+  /// Indicates whether the code path that results from the condition evaluating
+  /// to `true` is reachable after migration.
+  bool get keepTrue => trueGuard == null || trueGuard.isNullable;
+}
diff --git a/pkg/nnbd_migration/lib/src/decorated_type.dart b/pkg/nnbd_migration/lib/src/decorated_type.dart
new file mode 100644
index 0000000..a740c1c
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/decorated_type.dart
@@ -0,0 +1,183 @@
+// Copyright (c) 2019, 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:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceEdit;
+import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/potential_modification.dart';
+
+/// Representation of a type in the code to be migrated.  In addition to
+/// tracking the (unmigrated) [DartType], we track the [ConstraintVariable]s
+/// indicating whether the type, and the types that compose it, are nullable.
+class DecoratedType {
+  final DartType type;
+
+  final NullabilityNode node;
+
+  /// If `this` is a function type, the [DecoratedType] of its return type.
+  final DecoratedType returnType;
+
+  /// If `this` is a function type, the [DecoratedType] of each of its
+  /// positional parameters (including both required and optional positional
+  /// parameters).
+  final List<DecoratedType> positionalParameters;
+
+  /// If `this` is a function type, the [DecoratedType] of each of its named
+  /// parameters.
+  final Map<String, DecoratedType> namedParameters;
+
+  /// If `this` is a parameterized type, the [DecoratedType] of each of its
+  /// type parameters.
+  ///
+  /// TODO(paulberry): how should we handle generic typedefs?
+  final List<DecoratedType> typeArguments;
+
+  DecoratedType(this.type, this.node,
+      {this.returnType,
+      this.positionalParameters = const [],
+      this.namedParameters = const {},
+      this.typeArguments = const []}) {
+    assert(node != null);
+  }
+
+  /// Creates a [DecoratedType] corresponding to the given [element], which is
+  /// presumed to have come from code that is already migrated.
+  factory DecoratedType.forElement(Element element) {
+    DecoratedType decorate(DartType type) {
+      assert((type as TypeImpl).nullabilitySuffix ==
+          NullabilitySuffix.star); // TODO(paulberry)
+      if (type is FunctionType) {
+        var decoratedType = DecoratedType(type, NullabilityNode.never,
+            returnType: decorate(type.returnType), positionalParameters: []);
+        for (var parameter in type.parameters) {
+          assert(parameter.isPositional); // TODO(paulberry)
+          decoratedType.positionalParameters.add(decorate(parameter.type));
+        }
+        return decoratedType;
+      } else if (type is InterfaceType) {
+        assert(type.typeParameters.isEmpty); // TODO(paulberry)
+        return DecoratedType(type, NullabilityNode.never);
+      } else {
+        throw type.runtimeType; // TODO(paulberry)
+      }
+    }
+
+    DecoratedType decoratedType;
+    if (element is MethodElement) {
+      decoratedType = decorate(element.type);
+    } else if (element is PropertyAccessorElement) {
+      decoratedType = decorate(element.type);
+    } else {
+      throw element.runtimeType; // TODO(paulberry)
+    }
+    return decoratedType;
+  }
+
+  /// Apply the given [substitution] to this type.
+  ///
+  /// [undecoratedResult] is the result of the substitution, as determined by
+  /// the normal type system.
+  DecoratedType substitute(
+      Map<TypeParameterElement, DecoratedType> substitution,
+      DartType undecoratedResult) {
+    if (substitution.isEmpty) return this;
+    return _substitute(substitution, undecoratedResult);
+  }
+
+  @override
+  String toString() {
+    var trailing = node.debugSuffix;
+    var type = this.type;
+    if (type is TypeParameterType || type is VoidType) {
+      return '$type$trailing';
+    } else if (type is InterfaceType) {
+      var name = type.element.name;
+      var args = '';
+      if (type.typeArguments.isNotEmpty) {
+        args = '<${type.typeArguments.join(', ')}>';
+      }
+      return '$name$args$trailing';
+    } else if (type is FunctionType) {
+      assert(type.typeFormals.isEmpty); // TODO(paulberry)
+      assert(type.namedParameterTypes.isEmpty &&
+          namedParameters.isEmpty); // TODO(paulberry)
+      var args = positionalParameters.map((p) => p.toString()).join(', ');
+      return '$returnType Function($args)$trailing';
+    } else if (type is DynamicTypeImpl) {
+      return 'dynamic';
+    } else {
+      throw '$type'; // TODO(paulberry)
+    }
+  }
+
+  /// Creates a shallow copy of `this`, replacing the nullability node.
+  DecoratedType withNode(NullabilityNode node) => DecoratedType(type, node,
+      returnType: returnType,
+      positionalParameters: positionalParameters,
+      namedParameters: namedParameters,
+      typeArguments: typeArguments);
+
+  /// Internal implementation of [_substitute], used as a recursion target.
+  DecoratedType _substitute(
+      Map<TypeParameterElement, DecoratedType> substitution,
+      DartType undecoratedResult) {
+    var type = this.type;
+    if (type is FunctionType && undecoratedResult is FunctionType) {
+      assert(type.typeFormals.isEmpty); // TODO(paulberry)
+      var newPositionalParameters = <DecoratedType>[];
+      for (int i = 0; i < positionalParameters.length; i++) {
+        var numRequiredParameters =
+            undecoratedResult.normalParameterTypes.length;
+        var undecoratedParameterType = i < numRequiredParameters
+            ? undecoratedResult.normalParameterTypes[i]
+            : undecoratedResult
+                .optionalParameterTypes[i - numRequiredParameters];
+        newPositionalParameters.add(positionalParameters[i]
+            ._substitute(substitution, undecoratedParameterType));
+      }
+      return DecoratedType(undecoratedResult, node,
+          returnType: returnType._substitute(
+              substitution, undecoratedResult.returnType),
+          positionalParameters: newPositionalParameters);
+    } else if (type is TypeParameterType) {
+      var inner = substitution[type.element];
+      return DecoratedType(undecoratedResult,
+          NullabilityNode.forSubstitution(inner?.node, node));
+    } else if (type is VoidType) {
+      return this;
+    }
+    throw '$type.substitute($substitution)'; // TODO(paulberry)
+  }
+}
+
+/// A [DecoratedType] based on a type annotation appearing explicitly in the
+/// source code.
+///
+/// This class implements [PotentialModification] because it knows how to update
+/// the source code to reflect its nullability.
+class DecoratedTypeAnnotation extends DecoratedType
+    implements PotentialModification {
+  final int _offset;
+
+  DecoratedTypeAnnotation(
+      DartType type, NullabilityNode nullabilityNode, this._offset,
+      {List<DecoratedType> typeArguments = const [],
+      DecoratedType returnType,
+      List<DecoratedType> positionalParameters = const [],
+      Map<String, DecoratedType> namedParameters = const {}})
+      : super(type, nullabilityNode,
+            typeArguments: typeArguments,
+            returnType: returnType,
+            positionalParameters: positionalParameters,
+            namedParameters: namedParameters);
+
+  @override
+  bool get isEmpty => !node.isNullable;
+
+  @override
+  Iterable<SourceEdit> get modifications =>
+      isEmpty ? [] : [SourceEdit(_offset, 0, '?')];
+}
diff --git a/pkg/nnbd_migration/lib/src/decorated_type_operations.dart b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
new file mode 100644
index 0000000..b1e3fa8
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type_system.dart';
+import 'package:analyzer/src/dart/resolver/flow_analysis.dart';
+import 'package:nnbd_migration/src/decorated_type.dart';
+import 'package:nnbd_migration/src/node_builder.dart';
+
+/// [TypeOperations] that works with [DecoratedType]s.
+class DecoratedTypeOperations implements TypeOperations<DecoratedType> {
+  final TypeSystem _typeSystem;
+  final VariableRepository _variableRepository;
+
+  DecoratedTypeOperations(this._typeSystem, this._variableRepository);
+
+  @override
+  DecoratedType elementType(VariableElement element) {
+    return _variableRepository.decoratedElementType(element);
+  }
+
+  @override
+  bool isSubtypeOf(DecoratedType leftType, DecoratedType rightType) {
+    return _typeSystem.isSubtypeOf(leftType.type, rightType.type);
+  }
+}
diff --git a/pkg/nnbd_migration/lib/src/expression_checks.dart b/pkg/nnbd_migration/lib/src/expression_checks.dart
new file mode 100644
index 0000000..6dd34af
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/expression_checks.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2019, 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:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/potential_modification.dart';
+
+/// Container for information gathered during nullability migration about the
+/// set of runtime checks that might need to be performed on the value of an
+/// expression.
+///
+/// TODO(paulberry): the only check we support now is [nullCheck], which checks
+/// that the expression is not null.  We need to add other checks, e.g. to check
+/// that a List<int?> is actually a List<int>.
+class ExpressionChecks extends PotentialModification {
+  /// Source offset where a trailing `!` might need to be inserted.
+  final int offset;
+
+  /// Nullability node indicating whether the expression's value is nullable.
+  final NullabilityNode valueNode;
+
+  /// Nullability node indicating whether the expression's context requires a
+  /// nullable value.
+  final NullabilityNode contextNode;
+
+  /// Nullability nodes guarding execution of the expression.  If any of the
+  /// nodes in this list turns out to be non-nullable, the expression is dead
+  /// code and will be removed by the migration tool.
+  final List<NullabilityNode> guards;
+
+  ExpressionChecks(this.offset, this.valueNode, this.contextNode,
+      Iterable<NullabilityNode> guards)
+      : guards = guards.toList();
+
+  @override
+  bool get isEmpty {
+    for (var guard in guards) {
+      if (!guard.isNullable) return true;
+    }
+    return !valueNode.isNullable || contextNode.isNullable;
+  }
+
+  @override
+  Iterable<SourceEdit> get modifications =>
+      isEmpty ? [] : [SourceEdit(offset, 0, '!')];
+}
diff --git a/pkg/nnbd_migration/lib/src/graph_builder.dart b/pkg/nnbd_migration/lib/src/graph_builder.dart
new file mode 100644
index 0000000..cf3c46d
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/graph_builder.dart
@@ -0,0 +1,721 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:meta/meta.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
+import 'package:nnbd_migration/src/conditional_discard.dart';
+import 'package:nnbd_migration/src/decorated_type.dart';
+import 'package:nnbd_migration/src/expression_checks.dart';
+import 'package:nnbd_migration/src/node_builder.dart';
+import 'package:nnbd_migration/src/nullability_node.dart';
+
+/// Visitor that builds nullability graph edges by examining code to be
+/// migrated.
+///
+/// The return type of each `visit...` method is a [DecoratedType] indicating
+/// the static type of the visited expression, along with the constraint
+/// variables that will determine its nullability.  For `visit...` methods that
+/// don't visit expressions, `null` will be returned.
+class GraphBuilder extends GeneralizingAstVisitor<DecoratedType> {
+  /// The repository of constraint variables and decorated types (from a
+  /// previous pass over the source code).
+  final VariableRepository _variables;
+
+  final NullabilityMigrationListener /*?*/ listener;
+
+  final NullabilityGraph _graph;
+
+  /// The file being analyzed.
+  final Source _source;
+
+  /// For convenience, a [DecoratedType] representing non-nullable `Object`.
+  final DecoratedType _notNullType;
+
+  /// For convenience, a [DecoratedType] representing non-nullable `bool`.
+  final DecoratedType _nonNullableBoolType;
+
+  /// For convenience, a [DecoratedType] representing non-nullable `Type`.
+  final DecoratedType _nonNullableTypeType;
+
+  /// For convenience, a [DecoratedType] representing `Null`.
+  final DecoratedType _nullType;
+
+  /// The [DecoratedType] of the innermost function or method being visited, or
+  /// `null` if the visitor is not inside any function or method.
+  ///
+  /// This is needed to construct the appropriate nullability constraints for
+  /// return statements.
+  DecoratedType _currentFunctionType;
+
+  /// Information about the most recently visited binary expression whose
+  /// boolean value could possibly affect nullability analysis.
+  _ConditionInfo _conditionInfo;
+
+  /// The set of nullability nodes that would have to be `nullable` for the code
+  /// currently being visited to be reachable.
+  ///
+  /// Guard variables are attached to the left hand side of any generated
+  /// constraints, so that constraints do not take effect if they come from
+  /// code that can be proven unreachable by the migration tool.
+  final _guards = <NullabilityNode>[];
+
+  /// Indicates whether the statement or expression being visited is within
+  /// conditional control flow.  If `true`, this means that the enclosing
+  /// function might complete normally without executing the current statement
+  /// or expression.
+  bool _inConditionalControlFlow = false;
+
+  NullabilityNode _lastConditionalNode;
+
+  GraphBuilder(TypeProvider typeProvider, this._variables, this._graph,
+      this._source, this.listener)
+      : _notNullType =
+            DecoratedType(typeProvider.objectType, NullabilityNode.never),
+        _nonNullableBoolType =
+            DecoratedType(typeProvider.boolType, NullabilityNode.never),
+        _nonNullableTypeType =
+            DecoratedType(typeProvider.typeType, NullabilityNode.never),
+        _nullType =
+            DecoratedType(typeProvider.nullType, NullabilityNode.always);
+
+  /// Gets the decorated type of [element] from [_variables], performing any
+  /// necessary substitutions.
+  DecoratedType getOrComputeElementType(Element element,
+      {DecoratedType targetType}) {
+    Map<TypeParameterElement, DecoratedType> substitution;
+    Element baseElement;
+    if (element is Member) {
+      assert(targetType != null);
+      baseElement = element.baseElement;
+      var targetTypeType = targetType.type;
+      if (targetTypeType is InterfaceType &&
+          baseElement is ClassMemberElement) {
+        var enclosingClass = baseElement.enclosingElement;
+        assert(targetTypeType.element == enclosingClass); // TODO(paulberry)
+        substitution = <TypeParameterElement, DecoratedType>{};
+        assert(enclosingClass.typeParameters.length ==
+            targetTypeType.typeArguments.length); // TODO(paulberry)
+        for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
+          substitution[enclosingClass.typeParameters[i]] =
+              targetType.typeArguments[i];
+        }
+      }
+    } else {
+      baseElement = element;
+    }
+    DecoratedType decoratedBaseType;
+    if (baseElement is PropertyAccessorElement &&
+        baseElement.isSynthetic &&
+        !baseElement.variable.isSynthetic) {
+      var variable = baseElement.variable;
+      var decoratedElementType =
+          _variables.decoratedElementType(variable, create: true);
+      if (baseElement.isGetter) {
+        decoratedBaseType = DecoratedType(
+            baseElement.type, NullabilityNode.never,
+            returnType: decoratedElementType);
+      } else {
+        assert(baseElement.isSetter);
+        decoratedBaseType = DecoratedType(
+            baseElement.type, NullabilityNode.never,
+            positionalParameters: [decoratedElementType]);
+      }
+    } else {
+      decoratedBaseType =
+          _variables.decoratedElementType(baseElement, create: true);
+    }
+    if (substitution != null) {
+      DartType elementType;
+      if (element is MethodElement) {
+        elementType = element.type;
+      } else {
+        throw element.runtimeType; // TODO(paulberry)
+      }
+      return decoratedBaseType.substitute(substitution, elementType);
+    } else {
+      return decoratedBaseType;
+    }
+  }
+
+  @override
+  DecoratedType visitAssertStatement(AssertStatement node) {
+    _handleAssignment(_notNullType, node.condition);
+    if (identical(_conditionInfo?.condition, node.condition)) {
+      if (!_inConditionalControlFlow &&
+          _conditionInfo.trueDemonstratesNonNullIntent != null) {
+        _conditionInfo.trueDemonstratesNonNullIntent
+            ?.recordNonNullIntent(_guards, _graph);
+      }
+    }
+    node.message?.accept(this);
+    return null;
+  }
+
+  @override
+  DecoratedType visitAssignmentExpression(AssignmentExpression node) {
+    if (node.operator.type != TokenType.EQ) {
+      throw UnimplementedError('TODO(paulberry)');
+    }
+    var leftType = node.leftHandSide.accept(this);
+    var conditionalNode = _lastConditionalNode;
+    _lastConditionalNode = null;
+    var expressionType = _handleAssignment(leftType, node.rightHandSide);
+    if (_isConditionalExpression(node.leftHandSide)) {
+      expressionType = expressionType.withNode(
+          NullabilityNode.forLUB(conditionalNode, expressionType.node));
+      _variables.recordDecoratedExpressionType(node, expressionType);
+    }
+    return expressionType;
+  }
+
+  @override
+  DecoratedType visitBinaryExpression(BinaryExpression node) {
+    switch (node.operator.type) {
+      case TokenType.EQ_EQ:
+      case TokenType.BANG_EQ:
+        assert(node.leftOperand is! NullLiteral); // TODO(paulberry)
+        var leftType = node.leftOperand.accept(this);
+        node.rightOperand.accept(this);
+        if (node.rightOperand is NullLiteral) {
+          // TODO(paulberry): figure out what the rules for isPure should be.
+          // TODO(paulberry): only set falseChecksNonNull in unconditional
+          // control flow
+          bool isPure = node.leftOperand is SimpleIdentifier;
+          var conditionInfo = _ConditionInfo(node,
+              isPure: isPure,
+              trueGuard: leftType.node,
+              falseDemonstratesNonNullIntent: leftType.node);
+          _conditionInfo = node.operator.type == TokenType.EQ_EQ
+              ? conditionInfo
+              : conditionInfo.not(node);
+        }
+        return _nonNullableBoolType;
+      case TokenType.PLUS:
+        _handleAssignment(_notNullType, node.leftOperand);
+        var callee = node.staticElement;
+        assert(!(callee is ClassMemberElement &&
+            callee.enclosingElement.typeParameters
+                .isNotEmpty)); // TODO(paulberry)
+        assert(callee != null); // TODO(paulberry)
+        var calleeType = getOrComputeElementType(callee);
+        // TODO(paulberry): substitute if necessary
+        assert(calleeType.positionalParameters.length > 0); // TODO(paulberry)
+        _handleAssignment(
+            calleeType.positionalParameters[0], node.rightOperand);
+        return calleeType.returnType;
+      default:
+        assert(false); // TODO(paulberry)
+        return null;
+    }
+  }
+
+  @override
+  DecoratedType visitBooleanLiteral(BooleanLiteral node) {
+    return DecoratedType(node.staticType, NullabilityNode.never);
+  }
+
+  @override
+  DecoratedType visitCascadeExpression(CascadeExpression node) {
+    var type = node.target.accept(this);
+    node.cascadeSections.accept(this);
+    return type;
+  }
+
+  @override
+  DecoratedType visitClassDeclaration(ClassDeclaration node) {
+    node.members.accept(this);
+    return null;
+  }
+
+  @override
+  DecoratedType visitConditionalExpression(ConditionalExpression node) {
+    _handleAssignment(_notNullType, node.condition);
+    // TODO(paulberry): guard anything inside the true and false branches
+    var thenType = node.thenExpression.accept(this);
+    assert(_isSimple(thenType)); // TODO(paulberry)
+    var elseType = node.elseExpression.accept(this);
+    assert(_isSimple(elseType)); // TODO(paulberry)
+    var overallType = DecoratedType(
+        node.staticType, NullabilityNode.forLUB(thenType.node, elseType.node));
+    _variables.recordDecoratedExpressionType(node, overallType);
+    return overallType;
+  }
+
+  @override
+  DecoratedType visitDefaultFormalParameter(DefaultFormalParameter node) {
+    var defaultValue = node.defaultValue;
+    if (defaultValue == null) {
+      if (node.declaredElement.hasRequired) {
+        // Nothing to do; the implicit default value of `null` will never be
+        // reached.
+      } else {
+        NullabilityNode.recordAssignment(NullabilityNode.always,
+            getOrComputeElementType(node.declaredElement).node, _guards, _graph,
+            hard: false);
+      }
+    } else {
+      _handleAssignment(
+          getOrComputeElementType(node.declaredElement), defaultValue,
+          canInsertChecks: false);
+    }
+    return null;
+  }
+
+  @override
+  DecoratedType visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    _handleAssignment(_currentFunctionType.returnType, node.expression);
+    return null;
+  }
+
+  @override
+  DecoratedType visitFunctionDeclaration(FunctionDeclaration node) {
+    node.functionExpression.parameters?.accept(this);
+    assert(_currentFunctionType == null);
+    _currentFunctionType =
+        _variables.decoratedElementType(node.declaredElement);
+    _inConditionalControlFlow = false;
+    try {
+      node.functionExpression.body.accept(this);
+    } finally {
+      _currentFunctionType = null;
+    }
+    return null;
+  }
+
+  @override
+  DecoratedType visitIfStatement(IfStatement node) {
+    // TODO(paulberry): should the use of a boolean in an if-statement be
+    // treated like an implicit `assert(b != null)`?  Probably.
+    _handleAssignment(_notNullType, node.condition);
+    _inConditionalControlFlow = true;
+    NullabilityNode trueGuard;
+    NullabilityNode falseGuard;
+    if (identical(_conditionInfo?.condition, node.condition)) {
+      trueGuard = _conditionInfo.trueGuard;
+      falseGuard = _conditionInfo.falseGuard;
+      _variables.recordConditionalDiscard(_source, node,
+          ConditionalDiscard(trueGuard, falseGuard, _conditionInfo.isPure));
+    }
+    if (trueGuard != null) {
+      _guards.add(trueGuard);
+    }
+    try {
+      node.thenStatement.accept(this);
+    } finally {
+      if (trueGuard != null) {
+        _guards.removeLast();
+      }
+    }
+    if (falseGuard != null) {
+      _guards.add(falseGuard);
+    }
+    try {
+      node.elseStatement?.accept(this);
+    } finally {
+      if (falseGuard != null) {
+        _guards.removeLast();
+      }
+    }
+    return null;
+  }
+
+  @override
+  DecoratedType visitIndexExpression(IndexExpression node) {
+    DecoratedType targetType;
+    var target = node.realTarget;
+    if (target != null) {
+      targetType = _handleAssignment(_notNullType, target);
+    }
+    var callee = node.staticElement;
+    if (callee == null) {
+      throw new UnimplementedError('TODO(paulberry)');
+    }
+    var calleeType = getOrComputeElementType(callee, targetType: targetType);
+    // TODO(paulberry): substitute if necessary
+    _handleAssignment(calleeType.positionalParameters[0], node.index);
+    if (node.inSetterContext()) {
+      return calleeType.positionalParameters[1];
+    } else {
+      return calleeType.returnType;
+    }
+  }
+
+  @override
+  DecoratedType visitIntegerLiteral(IntegerLiteral node) {
+    return DecoratedType(node.staticType, NullabilityNode.never);
+  }
+
+  @override
+  DecoratedType visitMethodDeclaration(MethodDeclaration node) {
+    node.parameters?.accept(this);
+    assert(_currentFunctionType == null);
+    _currentFunctionType =
+        _variables.decoratedElementType(node.declaredElement);
+    _inConditionalControlFlow = false;
+    try {
+      node.body.accept(this);
+    } finally {
+      _currentFunctionType = null;
+    }
+    return null;
+  }
+
+  @override
+  DecoratedType visitMethodInvocation(MethodInvocation node) {
+    DecoratedType targetType;
+    var target = node.realTarget;
+    bool isConditional = _isConditionalExpression(node);
+    if (target != null) {
+      if (isConditional) {
+        targetType = target.accept(this);
+      } else {
+        _checkNonObjectMember(node.methodName.name); // TODO(paulberry)
+        targetType = _handleAssignment(_notNullType, target);
+      }
+    }
+    var callee = node.methodName.staticElement;
+    if (callee == null) {
+      throw new UnimplementedError('TODO(paulberry)');
+    }
+    var calleeType = getOrComputeElementType(callee, targetType: targetType);
+    // TODO(paulberry): substitute if necessary
+    var arguments = node.argumentList.arguments;
+    int i = 0;
+    var suppliedNamedParameters = Set<String>();
+    for (var expression in arguments) {
+      if (expression is NamedExpression) {
+        var name = expression.name.label.name;
+        var parameterType = calleeType.namedParameters[name];
+        assert(parameterType != null); // TODO(paulberry)
+        _handleAssignment(parameterType, expression.expression);
+        suppliedNamedParameters.add(name);
+      } else {
+        assert(calleeType.positionalParameters.length > i); // TODO(paulberry)
+        _handleAssignment(calleeType.positionalParameters[i++], expression);
+      }
+    }
+    // Any parameters not supplied must be optional.
+    for (var entry in calleeType.namedParameters.entries) {
+      if (suppliedNamedParameters.contains(entry.key)) continue;
+      entry.value.node.recordNamedParameterNotSupplied(_guards, _graph);
+    }
+    var expressionType = calleeType.returnType;
+    if (isConditional) {
+      expressionType = expressionType.withNode(
+          NullabilityNode.forLUB(targetType.node, expressionType.node));
+      _variables.recordDecoratedExpressionType(node, expressionType);
+    }
+    return expressionType;
+  }
+
+  @override
+  DecoratedType visitNode(AstNode node) {
+    if (listener != null) {
+      try {
+        return super.visitNode(node);
+      } catch (exception, stackTrace) {
+        listener.addDetail('''
+$exception
+
+$stackTrace''');
+        return null;
+      }
+    } else {
+      return super.visitNode(node);
+    }
+  }
+
+  @override
+  DecoratedType visitNullLiteral(NullLiteral node) {
+    return _nullType;
+  }
+
+  @override
+  DecoratedType visitParenthesizedExpression(ParenthesizedExpression node) {
+    return node.expression.accept(this);
+  }
+
+  @override
+  DecoratedType visitPrefixedIdentifier(PrefixedIdentifier node) {
+    if (node.prefix.staticElement is ImportElement) {
+      throw new UnimplementedError('TODO(paulberry)');
+    } else {
+      return _handlePropertyAccess(node, node.prefix, node.identifier);
+    }
+  }
+
+  @override
+  DecoratedType visitPropertyAccess(PropertyAccess node) {
+    return _handlePropertyAccess(node, node.realTarget, node.propertyName);
+  }
+
+  @override
+  DecoratedType visitReturnStatement(ReturnStatement node) {
+    if (node.expression == null) {
+      _checkAssignment(_currentFunctionType.returnType, _nullType, null);
+    } else {
+      _handleAssignment(_currentFunctionType.returnType, node.expression);
+    }
+    return null;
+  }
+
+  @override
+  DecoratedType visitSimpleIdentifier(SimpleIdentifier node) {
+    var staticElement = node.staticElement;
+    if (staticElement is ParameterElement ||
+        staticElement is LocalVariableElement) {
+      return getOrComputeElementType(staticElement);
+    } else if (staticElement is ClassElement) {
+      return _nonNullableTypeType;
+    } else {
+      // TODO(paulberry)
+      throw new UnimplementedError('${staticElement.runtimeType}');
+    }
+  }
+
+  @override
+  DecoratedType visitStringLiteral(StringLiteral node) {
+    return DecoratedType(node.staticType, NullabilityNode.never);
+  }
+
+  @override
+  DecoratedType visitThisExpression(ThisExpression node) {
+    return DecoratedType(node.staticType, NullabilityNode.never);
+  }
+
+  @override
+  DecoratedType visitThrowExpression(ThrowExpression node) {
+    node.expression.accept(this);
+    // TODO(paulberry): do we need to check the expression type?  I think not.
+    return DecoratedType(node.staticType, NullabilityNode.never);
+  }
+
+  @override
+  DecoratedType visitTypeName(TypeName typeName) {
+    var typeArguments = typeName.typeArguments?.arguments;
+    var element = typeName.name.staticElement;
+    if (typeArguments != null) {
+      for (int i = 0; i < typeArguments.length; i++) {
+        DecoratedType bound;
+        if (element is TypeParameterizedElement) {
+          bound = _variables.decoratedElementType(element.typeParameters[i],
+              create: true);
+        } else {
+          throw new UnimplementedError('TODO(paulberry)');
+        }
+        _checkAssignment(bound,
+            _variables.decoratedTypeAnnotation(_source, typeArguments[i]), null,
+            hard: true);
+      }
+    }
+    return DecoratedType(typeName.type, NullabilityNode.never);
+  }
+
+  @override
+  DecoratedType visitVariableDeclaration(VariableDeclaration node) {
+    var destinationType = getOrComputeElementType(node.declaredElement);
+    var initializer = node.initializer;
+    if (initializer == null) {
+      throw UnimplementedError('TODO(paulberry)');
+    } else {
+      _handleAssignment(destinationType, initializer);
+    }
+    return null;
+  }
+
+  /// Creates the necessary constraint(s) for an assignment from [sourceType] to
+  /// [destinationType].  [expression] is the expression whose type is
+  /// [sourceType]; it is the expression we will have to null-check in the case
+  /// where a nullable source is assigned to a non-nullable destination.
+  void _checkAssignment(DecoratedType destinationType, DecoratedType sourceType,
+      Expression expression,
+      {bool hard}) {
+    if (expression != null) {
+      _variables.recordExpressionChecks(
+          _source,
+          expression,
+          ExpressionChecks(
+              expression.end, sourceType.node, destinationType.node, _guards));
+    }
+    NullabilityNode.recordAssignment(
+        sourceType.node, destinationType.node, _guards, _graph,
+        hard: hard ??
+            (_isVariableOrParameterReference(expression) &&
+                !_inConditionalControlFlow));
+    // TODO(paulberry): it's a cheat to pass in expression=null for the
+    // recursive checks.  Really we want to unify all the checks in a single
+    // ExpressionChecks object.
+    expression = null;
+    // TODO(paulberry): generalize this.
+    if ((_isSimple(sourceType) || destinationType.type.isObject) &&
+        _isSimple(destinationType)) {
+      // Ok; nothing further to do.
+    } else if (sourceType.type is InterfaceType &&
+        destinationType.type is InterfaceType &&
+        sourceType.type.element == destinationType.type.element) {
+      assert(sourceType.typeArguments.length ==
+          destinationType.typeArguments.length);
+      for (int i = 0; i < sourceType.typeArguments.length; i++) {
+        _checkAssignment(destinationType.typeArguments[i],
+            sourceType.typeArguments[i], expression);
+      }
+    } else if (destinationType.type.isDynamic || sourceType.type.isDynamic) {
+      // ok; nothing further to do.
+    } else {
+      throw '$destinationType <= $sourceType'; // TODO(paulberry)
+    }
+  }
+
+  /// Double checks that [name] is not the name of a method or getter declared
+  /// on [Object].
+  ///
+  /// TODO(paulberry): get rid of this method and put the correct logic into the
+  /// call sites.
+  void _checkNonObjectMember(String name) {
+    assert(name != 'toString');
+    assert(name != 'hashCode');
+    assert(name != 'noSuchMethod');
+    assert(name != 'runtimeType');
+  }
+
+  /// Creates the necessary constraint(s) for an assignment of the given
+  /// [expression] to a destination whose type is [destinationType].
+  DecoratedType _handleAssignment(
+      DecoratedType destinationType, Expression expression,
+      {bool canInsertChecks = true}) {
+    var sourceType = expression.accept(this);
+    _checkAssignment(
+        destinationType, sourceType, canInsertChecks ? expression : null);
+    return sourceType;
+  }
+
+  DecoratedType _handlePropertyAccess(
+      Expression node, Expression target, SimpleIdentifier propertyName) {
+    DecoratedType targetType;
+    bool isConditional = _isConditionalExpression(node);
+    if (isConditional) {
+      targetType = target.accept(this);
+    } else {
+      _checkNonObjectMember(propertyName.name); // TODO(paulberry)
+      targetType = _handleAssignment(_notNullType, target);
+    }
+    var callee = propertyName.staticElement;
+    if (callee == null) {
+      throw new UnimplementedError('TODO(paulberry)');
+    }
+    var calleeType = getOrComputeElementType(callee, targetType: targetType);
+    // TODO(paulberry): substitute if necessary
+    if (propertyName.inSetterContext()) {
+      if (isConditional) {
+        _lastConditionalNode = targetType.node;
+      }
+      return calleeType.positionalParameters[0];
+    } else {
+      var expressionType = calleeType.returnType;
+      if (isConditional) {
+        expressionType = expressionType.withNode(
+            NullabilityNode.forLUB(targetType.node, expressionType.node));
+        _variables.recordDecoratedExpressionType(node, expressionType);
+      }
+      return expressionType;
+    }
+  }
+
+  bool _isConditionalExpression(Expression expression) {
+    Token token;
+    if (expression is MethodInvocation) {
+      token = expression.operator;
+      if (token == null) return false;
+    } else if (expression is PropertyAccess) {
+      token = expression.operator;
+    } else {
+      return false;
+    }
+    switch (token.type) {
+      case TokenType.PERIOD:
+      case TokenType.PERIOD_PERIOD:
+        return false;
+      case TokenType.QUESTION_PERIOD:
+        return true;
+      default:
+        throw new UnimplementedError('TODO(paulberry)');
+    }
+  }
+
+  /// Double checks that [type] is sufficiently simple for this naive prototype
+  /// implementation.
+  ///
+  /// TODO(paulberry): get rid of this method and put the correct logic into the
+  /// call sites.
+  bool _isSimple(DecoratedType type) {
+    if (type.type.isBottom) return true;
+    if (type.type.isVoid) return true;
+    if (type.type is TypeParameterType) return true;
+    if (type.type is! InterfaceType) return false;
+    if ((type.type as InterfaceType).typeParameters.isNotEmpty) return false;
+    return true;
+  }
+
+  bool _isVariableOrParameterReference(Expression expression) {
+    if (expression is SimpleIdentifier) {
+      var element = expression.staticElement;
+      if (element is LocalVariableElement) return true;
+      if (element is ParameterElement) return true;
+    }
+    return false;
+  }
+}
+
+/// Information about a binary expression whose boolean value could possibly
+/// affect nullability analysis.
+class _ConditionInfo {
+  /// The [expression] of interest.
+  final Expression condition;
+
+  /// Indicates whether [condition] is pure (free from side effects).
+  ///
+  /// For example, a condition like `x == null` is pure (assuming `x` is a local
+  /// variable or static variable), because evaluating it has no user-visible
+  /// effect other than returning a boolean value.
+  final bool isPure;
+
+  /// If not `null`, the [NullabilityNode] that would need to be nullable in
+  /// order for [condition] to evaluate to `true`.
+  final NullabilityNode trueGuard;
+
+  /// If not `null`, the [NullabilityNode] that would need to be nullable in
+  /// order for [condition] to evaluate to `false`.
+  final NullabilityNode falseGuard;
+
+  /// If not `null`, the [NullabilityNode] that should be asserted to have
+  //  /// non-null intent if [condition] is asserted to be `true`.
+  final NullabilityNode trueDemonstratesNonNullIntent;
+
+  /// If not `null`, the [NullabilityNode] that should be asserted to have
+  /// non-null intent if [condition] is asserted to be `false`.
+  final NullabilityNode falseDemonstratesNonNullIntent;
+
+  _ConditionInfo(this.condition,
+      {@required this.isPure,
+      this.trueGuard,
+      this.falseGuard,
+      this.trueDemonstratesNonNullIntent,
+      this.falseDemonstratesNonNullIntent});
+
+  /// Returns a new [_ConditionInfo] describing the boolean "not" of `this`.
+  _ConditionInfo not(Expression condition) => _ConditionInfo(condition,
+      isPure: isPure,
+      trueGuard: falseGuard,
+      falseGuard: trueGuard,
+      trueDemonstratesNonNullIntent: falseDemonstratesNonNullIntent,
+      falseDemonstratesNonNullIntent: trueDemonstratesNonNullIntent);
+}
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
new file mode 100644
index 0000000..44a7475
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -0,0 +1,329 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:front_end/src/scanner/token.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
+import 'package:nnbd_migration/src/conditional_discard.dart';
+import 'package:nnbd_migration/src/decorated_type.dart';
+import 'package:nnbd_migration/src/expression_checks.dart';
+import 'package:nnbd_migration/src/nullability_node.dart';
+
+/// Visitor that builds nullability nodes based on visiting code to be migrated.
+///
+/// The return type of each `visit...` method is a [DecoratedType] indicating
+/// the static type of the element declared by the visited node, along with the
+/// constraint variables that will determine its nullability.  For `visit...`
+/// methods that don't visit declarations, `null` will be returned.
+class NodeBuilder extends GeneralizingAstVisitor<DecoratedType> {
+  /// Constraint variables and decorated types are stored here.
+  final VariableRecorder _variables;
+
+  /// The file being analyzed.
+  final Source _source;
+
+  /// If the parameters of a function or method are being visited, the
+  /// [DecoratedType] of the corresponding function or method type.
+  ///
+  /// TODO(paulberry): should this be updated when we visit generic function
+  /// type syntax?  How about when we visit old-style function-typed formal
+  /// parameters?
+  DecoratedType _currentFunctionType;
+
+  final NullabilityMigrationListener /*?*/ listener;
+
+  final NullabilityGraph _graph;
+
+  final TypeProvider _typeProvider;
+
+  NodeBuilder(this._variables, this._source, this.listener, this._graph,
+      this._typeProvider);
+
+  /// Creates and stores a [DecoratedType] object corresponding to the given
+  /// [type] AST, and returns it.
+  DecoratedType decorateType(TypeAnnotation type, AstNode enclosingNode) {
+    return type == null
+        // TODO(danrubel): Return something other than this
+        // to indicate that we should insert a type for the declaration
+        // that is missing a type reference.
+        ? new DecoratedType(
+            DynamicTypeImpl.instance,
+            NullabilityNode.forInferredDynamicType(
+                _graph, enclosingNode.offset))
+        : type.accept(this);
+  }
+
+  @override
+  DecoratedType visitConstructorDeclaration(ConstructorDeclaration node) {
+    _handleExecutableDeclaration(
+        node.declaredElement, null, node.parameters, node.body, node);
+    return null;
+  }
+
+  @override
+  DecoratedType visitDefaultFormalParameter(DefaultFormalParameter node) {
+    var decoratedType = node.parameter.accept(this);
+    if (node.declaredElement.hasRequired || node.defaultValue != null) {
+      return null;
+    }
+    decoratedType.node.trackPossiblyOptional();
+    _variables.recordPossiblyOptional(_source, node, decoratedType.node);
+    return null;
+  }
+
+  @override
+  DecoratedType visitFormalParameter(FormalParameter node) {
+    // Do not visit children
+    // TODO(paulberry): handle all types of formal parameters
+    // - NormalFormalParameter
+    // - SimpleFormalParameter
+    // - FieldFormalParameter
+    // - FunctionTypedFormalParameter
+    // - DefaultFormalParameter
+    return null;
+  }
+
+  @override
+  DecoratedType visitFunctionDeclaration(FunctionDeclaration node) {
+    _handleExecutableDeclaration(node.declaredElement, node.returnType,
+        node.functionExpression.parameters, node.functionExpression.body, node);
+    return null;
+  }
+
+  @override
+  DecoratedType visitMethodDeclaration(MethodDeclaration node) {
+    _handleExecutableDeclaration(node.declaredElement, node.returnType,
+        node.parameters, node.body, node);
+    return null;
+  }
+
+  @override
+  DecoratedType visitNode(AstNode node) {
+    if (listener != null) {
+      try {
+        return super.visitNode(node);
+      } catch (exception, stackTrace) {
+        listener.addDetail('''
+$exception
+
+$stackTrace''');
+        return null;
+      }
+    } else {
+      return super.visitNode(node);
+    }
+  }
+
+  @override
+  DecoratedType visitSimpleFormalParameter(SimpleFormalParameter node) {
+    var type = decorateType(node.type, node);
+    var declaredElement = node.declaredElement;
+    _variables.recordDecoratedElementType(declaredElement, type);
+    if (declaredElement.isNamed) {
+      _currentFunctionType.namedParameters[declaredElement.name] = type;
+    } else {
+      _currentFunctionType.positionalParameters.add(type);
+    }
+    return type;
+  }
+
+  @override
+  DecoratedType visitTypeAnnotation(TypeAnnotation node) {
+    assert(node != null); // TODO(paulberry)
+    var type = node.type;
+    if (type.isVoid || type.isDynamic) {
+      var nullabilityNode = NullabilityNode.forTypeAnnotation(node.end);
+      _graph.connect(NullabilityNode.always, nullabilityNode);
+      var decoratedType =
+          DecoratedTypeAnnotation(type, nullabilityNode, node.offset);
+      _variables.recordDecoratedTypeAnnotation(_source, node, decoratedType,
+          potentialModification: false);
+      return decoratedType;
+    }
+    var typeArguments = const <DecoratedType>[];
+    DecoratedType returnType;
+    var positionalParameters = const <DecoratedType>[];
+    var namedParameters = const <String, DecoratedType>{};
+    if (type is InterfaceType && type.typeParameters.isNotEmpty) {
+      if (node is TypeName) {
+        assert(node.typeArguments != null);
+        typeArguments =
+            node.typeArguments.arguments.map((t) => t.accept(this)).toList();
+      } else {
+        assert(false); // TODO(paulberry): is this possible?
+      }
+    }
+    if (node is GenericFunctionType) {
+      returnType = decorateType(node.returnType, node);
+      if (node.typeParameters != null) {
+        throw UnimplementedError('TODO(paulberry)');
+      }
+      positionalParameters = <DecoratedType>[];
+      namedParameters = <String, DecoratedType>{};
+    }
+    var decoratedType = DecoratedTypeAnnotation(
+        type, NullabilityNode.forTypeAnnotation(node.end), node.end,
+        typeArguments: typeArguments,
+        returnType: returnType,
+        positionalParameters: positionalParameters,
+        namedParameters: namedParameters);
+    _variables.recordDecoratedTypeAnnotation(_source, node, decoratedType);
+    if (node is GenericFunctionType) {
+      var previousFunctionType = _currentFunctionType;
+      try {
+        _currentFunctionType = decoratedType;
+        node.parameters.accept(this);
+      } finally {
+        _currentFunctionType = previousFunctionType;
+      }
+    }
+    switch (_classifyComment(node.endToken.next.precedingComments)) {
+      case _NullabilityComment.bang:
+        _graph.connect(decoratedType.node, NullabilityNode.never, hard: true);
+        break;
+      case _NullabilityComment.question:
+        _graph.connect(NullabilityNode.always, decoratedType.node);
+        break;
+      case _NullabilityComment.none:
+        break;
+    }
+    return decoratedType;
+  }
+
+  @override
+  DecoratedType visitTypeName(TypeName node) => visitTypeAnnotation(node);
+
+  @override
+  DecoratedType visitTypeParameter(TypeParameter node) {
+    var element = node.declaredElement;
+    var decoratedBound = node.bound?.accept(this) ??
+        DecoratedType(element.bound ?? _typeProvider.objectType,
+            NullabilityNode.forInferredDynamicType(_graph, node.offset));
+    _variables.recordDecoratedElementType(element, decoratedBound);
+    return null;
+  }
+
+  @override
+  DecoratedType visitVariableDeclarationList(VariableDeclarationList node) {
+    var type = decorateType(node.type, node);
+    for (var variable in node.variables) {
+      _variables.recordDecoratedElementType(variable.declaredElement, type);
+    }
+    return null;
+  }
+
+  _NullabilityComment _classifyComment(Token token) {
+    if (token is CommentToken) {
+      if (token.lexeme == '/*!*/') return _NullabilityComment.bang;
+      if (token.lexeme == '/*?*/') return _NullabilityComment.question;
+    }
+    return _NullabilityComment.none;
+  }
+
+  /// Common handling of function and method declarations.
+  void _handleExecutableDeclaration(
+      ExecutableElement declaredElement,
+      TypeAnnotation returnType,
+      FormalParameterList parameters,
+      FunctionBody body,
+      AstNode enclosingNode) {
+    var decoratedReturnType = decorateType(returnType, enclosingNode);
+    var previousFunctionType = _currentFunctionType;
+    // TODO(paulberry): test that it's correct to use `null` for the nullability
+    // of the function type
+    var functionType = DecoratedType(
+        declaredElement.type, NullabilityNode.never,
+        returnType: decoratedReturnType,
+        positionalParameters: [],
+        namedParameters: {});
+    _currentFunctionType = functionType;
+    try {
+      parameters?.accept(this);
+      body?.accept(this);
+    } finally {
+      _currentFunctionType = previousFunctionType;
+    }
+    _variables.recordDecoratedElementType(declaredElement, functionType);
+  }
+}
+
+/// Repository of constraint variables and decorated types corresponding to the
+/// code being migrated.
+///
+/// This data structure records the results of the first pass of migration
+/// ([NodeBuilder], which finds all the variables that need to be
+/// constrained).
+abstract class VariableRecorder {
+  /// Associates decorated type information with the given [element].
+  void recordDecoratedElementType(Element element, DecoratedType type);
+
+  /// Associates decorated type information with the given [type] node.
+  void recordDecoratedTypeAnnotation(
+      Source source, TypeAnnotation node, DecoratedTypeAnnotation type,
+      {bool potentialModification: true});
+
+  /// Records that [node] is associated with the question of whether the named
+  /// [parameter] should be optional (should not have a `required`
+  /// annotation added to it).
+  void recordPossiblyOptional(
+      Source source, DefaultFormalParameter parameter, NullabilityNode node);
+}
+
+/// Repository of constraint variables and decorated types corresponding to the
+/// code being migrated.
+///
+/// This data structure allows the second pass of migration
+/// ([ConstraintGatherer], which builds all the constraints) to access the
+/// results of the first ([NodeBuilder], which finds all the
+/// variables that need to be constrained).
+abstract class VariableRepository {
+  /// Retrieves the [DecoratedType] associated with the static type of the given
+  /// [element].
+  ///
+  /// If [create] is `true`, and no decorated type is found for the given
+  /// element, one is synthesized using [DecoratedType.forElement].
+  DecoratedType decoratedElementType(Element element, {bool create: false});
+
+  /// Gets the [DecoratedType] associated with the given [typeAnnotation].
+  DecoratedType decoratedTypeAnnotation(
+      Source source, TypeAnnotation typeAnnotation);
+
+  /// Records conditional discard information for the given AST node (which is
+  /// an `if` statement or a conditional (`?:`) expression).
+  void recordConditionalDiscard(
+      Source source, AstNode node, ConditionalDiscard conditionalDiscard);
+
+  /// Associates decorated type information with the given [element].
+  ///
+  /// TODO(paulberry): why is this in both [VariableRecorder] and
+  /// [VariableRepository]?
+  void recordDecoratedElementType(Element element, DecoratedType type);
+
+  /// Associates decorated type information with the given expression [node].
+  void recordDecoratedExpressionType(Expression node, DecoratedType type);
+
+  /// Associates a set of nullability checks with the given expression [node].
+  void recordExpressionChecks(
+      Source source, Expression expression, ExpressionChecks checks);
+}
+
+/// Types of comments that can influence nullability
+enum _NullabilityComment {
+  /// The comment `/*!*/`, which indicates that the type should not have a `?`
+  /// appended.
+  bang,
+
+  /// The comment `/*?*/`, which indicates that the type should have a `?`
+  /// appended.
+  question,
+
+  /// No special comment.
+  none,
+}
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
new file mode 100644
index 0000000..a94f87b
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -0,0 +1,101 @@
+// Copyright (c) 2019, 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:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
+import 'package:nnbd_migration/src/decorated_type.dart';
+import 'package:nnbd_migration/src/expression_checks.dart';
+import 'package:nnbd_migration/src/graph_builder.dart';
+import 'package:nnbd_migration/src/node_builder.dart';
+import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/potential_modification.dart';
+import 'package:nnbd_migration/src/variables.dart';
+
+/// Implementation of the [NullabilityMigration] public API.
+class NullabilityMigrationImpl implements NullabilityMigration {
+  final NullabilityMigrationListener listener;
+
+  final _variables = Variables();
+
+  final _graph = NullabilityGraph();
+
+  final bool _permissive;
+
+  /// Prepares to perform nullability migration.
+  ///
+  /// If [permissive] is `true`, exception handling logic will try to proceed
+  /// as far as possible even though the migration algorithm is not yet
+  /// complete.  TODO(paulberry): remove this mode once the migration algorithm
+  /// is fully implemented.
+  NullabilityMigrationImpl(this.listener, {bool permissive: false})
+      : _permissive = permissive;
+
+  void finish() {
+    _graph.propagate();
+    for (var entry in _variables.getPotentialModifications().entries) {
+      var source = entry.key;
+      for (var potentialModification in entry.value) {
+        var fix = _SingleNullabilityFix(source, potentialModification);
+        listener.addFix(fix);
+        for (var edit in potentialModification.modifications) {
+          listener.addEdit(fix, edit);
+        }
+      }
+    }
+  }
+
+  void prepareInput(ResolvedUnitResult result) {
+    var unit = result.unit;
+    unit.accept(NodeBuilder(_variables, unit.declaredElement.source,
+        _permissive ? listener : null, _graph, result.typeProvider));
+  }
+
+  void processInput(ResolvedUnitResult result) {
+    var unit = result.unit;
+    unit.accept(GraphBuilder(result.typeProvider, _variables, _graph,
+        unit.declaredElement.source, _permissive ? listener : null));
+  }
+}
+
+/// Implementation of [SingleNullabilityFix] used internally by
+/// [NullabilityMigration].
+class _SingleNullabilityFix extends SingleNullabilityFix {
+  @override
+  final Source source;
+
+  @override
+  final NullabilityFixKind kind;
+
+  factory _SingleNullabilityFix(
+      Source source, PotentialModification potentialModification) {
+    // TODO(paulberry): once everything is migrated into the analysis server,
+    // the migration engine can just create SingleNullabilityFix objects
+    // directly and set their kind appropriately; we won't need to translate the
+    // kinds using a bunch of `is` checks.
+    NullabilityFixKind kind;
+    if (potentialModification is ExpressionChecks) {
+      kind = NullabilityFixKind.checkExpression;
+    } else if (potentialModification is DecoratedTypeAnnotation) {
+      kind = NullabilityFixKind.makeTypeNullable;
+    } else if (potentialModification is ConditionalModification) {
+      kind = potentialModification.discard.keepFalse
+          ? NullabilityFixKind.discardThen
+          : NullabilityFixKind.discardElse;
+    } else if (potentialModification is PotentiallyAddImport) {
+      kind = NullabilityFixKind.addImport;
+    } else if (potentialModification is PotentiallyAddRequired) {
+      kind = NullabilityFixKind.addRequired;
+    } else {
+      throw new UnimplementedError('TODO(paulberry)');
+    }
+    return _SingleNullabilityFix._(source, kind);
+  }
+
+  _SingleNullabilityFix._(this.source, this.kind);
+
+  /// TODO(paulberry): do something better
+  Location get location => null;
+}
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
new file mode 100644
index 0000000..4abbc72
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -0,0 +1,512 @@
+// Copyright (c) 2019, 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:meta/meta.dart';
+
+/// Data structure to keep track of the relationship from one [NullabilityNode]
+/// object to another [NullabilityNode] that is "downstream" from it (meaning
+/// that if the former node is nullable, then the latter node will either have
+/// to be nullable, or null checks will have to be added).
+class NullabilityEdge {
+  /// The node that is downstream.
+  final NullabilityNode destinationNode;
+
+  /// A set of source nodes.  By convention, the first node is the primary
+  /// source and the other nodes are "guards".  The destination node will only
+  /// need to be made nullable if all the source nodes are nullable.
+  final List<NullabilityNode> sources;
+
+  final bool hard;
+
+  NullabilityEdge(this.destinationNode, this.sources, this.hard);
+
+  Iterable<NullabilityNode> get guards => sources.skip(1);
+
+  NullabilityNode get primarySource => sources.first;
+}
+
+/// Data structure to keep track of the relationship between [NullabilityNode]
+/// objects.
+class NullabilityGraph {
+  /// Set this const to `true` to dump the nullability graph just before
+  /// propagation.
+  static const _debugBeforePropagation = false;
+
+  /// Set containing all [NullabilityNode]s that have been passed as the
+  /// `sourceNode` argument to [connect].
+  final _allSourceNodes = Set<NullabilityNode>.identity();
+
+  /// List of [NullabilityEdge] objects that are downstream from
+  /// [NullabilityNode.always].  (They can't be stored in
+  /// [NullabilityNode.always] directly because it is immutable).
+  final _downstreamFromAlways = <NullabilityEdge>[];
+
+  /// List of [NullabilityEdge] objects that are upstream from
+  /// [NullabilityNode.never] due to unconditional control flow.  (They can't be
+  /// stored in [NullabilityNode.never] directly because it is immutable).
+  final _upstreamFromNever = <NullabilityEdge>[];
+
+  /// List of [NullabilityNodeMutable] objects that were set into the nullable
+  /// state by a process other than nullability propagation.  The next time
+  /// nullability is propagated, the propagation algorithm will ensure that
+  /// edges originating at these nodes are examined.
+  final _pendingDownstreamNodes = <NullabilityNodeMutable>[];
+
+  /// Records that [sourceNode] is immediately upstream from [destinationNode].
+  void connect(NullabilityNode sourceNode, NullabilityNode destinationNode,
+      {bool hard: false, List<NullabilityNode> guards: const []}) {
+    var sources = [sourceNode]..addAll(guards);
+    var edge = NullabilityEdge(destinationNode, sources, hard);
+    for (var source in sources) {
+      _connectDownstream(source, edge);
+    }
+    if (destinationNode is NullabilityNodeMutable) {
+      destinationNode._upstreamEdges.add(edge);
+    } else if (destinationNode == NullabilityNode.never) {
+      _upstreamFromNever.add(edge);
+    } else {
+      // We don't need to track nodes that are upstream from `always` because
+      // `always` will never have non-null intent.
+      assert(destinationNode == NullabilityNode.always);
+    }
+  }
+
+  void debugDump() {
+    for (var source in _allSourceNodes) {
+      var edges = _getDownstreamEdges(source);
+      var destinations =
+          edges.where((edge) => edge.primarySource == source).map((edge) {
+        var suffixes = <Object>[];
+        if (edge.hard) {
+          suffixes.add('hard');
+        }
+        suffixes.addAll(edge.guards);
+        var suffix = suffixes.isNotEmpty ? ' (${suffixes.join(', ')})' : '';
+        return '${edge.destinationNode}$suffix';
+      });
+      var state = source._state;
+      print('$source ($state) -> ${destinations.join(', ')}');
+    }
+  }
+
+  /// Iterates through all nodes that are "upstream" of [node] due to
+  /// unconditional control flow.
+  ///
+  /// There is no guarantee of uniqueness of the iterated nodes.
+  Iterable<NullabilityEdge> getUpstreamEdges(NullabilityNode node) {
+    if (node is NullabilityNodeMutable) {
+      return node._upstreamEdges;
+    } else if (node == NullabilityNode.never) {
+      return _upstreamFromNever;
+    } else {
+      // No nodes are upstream from `always`.
+      assert(node == NullabilityNode.always);
+      return const [];
+    }
+  }
+
+  /// Iterates through all nodes that are "upstream" of [node] (i.e. if
+  /// any of the iterated nodes are nullable, then [node] will either have to be
+  /// nullable, or null checks will have to be added).
+  ///
+  /// There is no guarantee of uniqueness of the iterated nodes.
+  ///
+  /// This method is inefficent since it has to search the entire graph, so it
+  /// is for testing only.
+  @visibleForTesting
+  Iterable<NullabilityNode> getUpstreamNodesForTesting(
+      NullabilityNode node) sync* {
+    for (var source in _allSourceNodes) {
+      for (var edge in _getDownstreamEdges(source)) {
+        if (edge.destinationNode == node) {
+          yield source;
+        }
+      }
+    }
+  }
+
+  /// Determines the nullability of each node in the graph by propagating
+  /// nullability information from one node to another.
+  void propagate() {
+    if (_debugBeforePropagation) debugDump();
+    _propagateUpstream();
+    _propagateDownstream();
+  }
+
+  void _connectDownstream(NullabilityNode source, NullabilityEdge edge) {
+    _allSourceNodes.add(source);
+    if (source is NullabilityNodeMutable) {
+      source._downstreamEdges.add(edge);
+      if (source is _NullabilityNodeCompound) {
+        for (var component in source._components) {
+          _connectDownstream(component, edge);
+        }
+      }
+    } else if (source == NullabilityNode.always) {
+      _downstreamFromAlways.add(edge);
+    } else {
+      // We don't need to track nodes that are downstream from `never` because
+      // `never` will never be nullable.
+      assert(source == NullabilityNode.never);
+    }
+  }
+
+  Iterable<NullabilityEdge> _getDownstreamEdges(NullabilityNode node) {
+    if (node is NullabilityNodeMutable) {
+      return node._downstreamEdges;
+    } else if (node == NullabilityNode.always) {
+      return _downstreamFromAlways;
+    } else {
+      // No nodes are downstream from `never`.
+      assert(node == NullabilityNode.never);
+      return const [];
+    }
+  }
+
+  /// Propagates nullability downstream.
+  void _propagateDownstream() {
+    var pendingEdges = <NullabilityEdge>[]..addAll(_downstreamFromAlways);
+    for (var node in _pendingDownstreamNodes) {
+      pendingEdges.addAll(node._downstreamEdges);
+    }
+    _pendingDownstreamNodes.clear();
+    var pendingSubstitutions = <NullabilityNodeForSubstitution>[];
+    while (true) {
+      nextEdge:
+      while (pendingEdges.isNotEmpty) {
+        var edge = pendingEdges.removeLast();
+        var node = edge.destinationNode;
+        if (node._state == _NullabilityState.nonNullable) {
+          // Non-nullable nodes are never made nullable; a null check will need
+          // to be added instead.
+          continue;
+        }
+        for (var source in edge.sources) {
+          if (!source.isNullable) {
+            // Not all sources are nullable, so this edge doesn't apply yet.
+            continue nextEdge;
+          }
+        }
+        if (node is NullabilityNodeMutable && !node.isNullable) {
+          node._state = _NullabilityState.ordinaryNullable;
+          // Was not previously nullable, so we need to propagate.
+          pendingEdges.addAll(node._downstreamEdges);
+          if (node is NullabilityNodeForSubstitution) {
+            pendingSubstitutions.add(node);
+          }
+        }
+      }
+      if (pendingSubstitutions.isEmpty) break;
+      var node = pendingSubstitutions.removeLast();
+      if (node.innerNode.isNullable || node.outerNode.isNullable) {
+        // No further propagation is needed, since some other connection already
+        // propagated nullability to either the inner or outer node.
+        continue;
+      }
+      // Heuristically choose to propagate to the inner node since this seems
+      // to lead to better quality migrations.
+      pendingEdges.add(NullabilityEdge(node.innerNode, const [], false));
+    }
+  }
+
+  /// Propagates non-null intent upstream along unconditional control flow
+  /// lines.
+  void _propagateUpstream() {
+    var pendingEdges = <NullabilityEdge>[]..addAll(_upstreamFromNever);
+    while (pendingEdges.isNotEmpty) {
+      var edge = pendingEdges.removeLast();
+      if (!edge.hard) continue;
+      var node = edge.primarySource;
+      if (node is NullabilityNodeMutable &&
+          node._state == _NullabilityState.undetermined) {
+        node._state = _NullabilityState.nonNullable;
+        // Was not previously in the set of non-null intent nodes, so we need to
+        // propagate.
+        pendingEdges.addAll(node._upstreamEdges);
+      }
+    }
+  }
+}
+
+/// Representation of a single node in the nullability inference graph.
+///
+/// Initially, this is just a wrapper over constraint variables, and the
+/// nullability inference graph is encoded into the wrapped constraint
+/// variables.  Over time this will be replaced by a first class representation
+/// of the nullability inference graph.
+abstract class NullabilityNode {
+  /// [NullabilityNode] used for types that are known a priori to be nullable
+  /// (e.g. the type of the `null` literal).
+  static final NullabilityNode always =
+      _NullabilityNodeImmutable('always', true);
+
+  /// [NullabilityNode] used for types that are known a priori to be
+  /// non-nullable (e.g. the type of an integer literal).
+  static final NullabilityNode never =
+      _NullabilityNodeImmutable('never', false);
+
+  static final _debugNamesInUse = Set<String>();
+
+  bool _isPossiblyOptional = false;
+
+  String _debugName;
+
+  /// Creates a [NullabilityNode] representing the nullability of a variable
+  /// whose type is `dynamic` due to type inference.
+  ///
+  /// TODO(paulberry): this should go away; we should decorate the actual
+  /// inferred type rather than assuming `dynamic`.
+  factory NullabilityNode.forInferredDynamicType(
+      NullabilityGraph graph, int offset) {
+    var node = _NullabilityNodeSimple('inferredDynamic($offset)',
+        initialState: _NullabilityState.ordinaryNullable);
+    graph._pendingDownstreamNodes.add(node);
+    return node;
+  }
+
+  /// Creates a [NullabilityNode] representing the nullability of an
+  /// expression which is nullable iff both [a] and [b] are nullable.
+  ///
+  /// The constraint variable contained in the new node is created using the
+  /// [joinNullabilities] callback.  TODO(paulberry): this should become
+  /// unnecessary once constraint solving is performed directly using
+  /// [NullabilityNode] objects.
+  factory NullabilityNode.forLUB(NullabilityNode a, NullabilityNode b) =
+      NullabilityNodeForLUB._;
+
+  /// Creates a [NullabilityNode] representing the nullability of a type
+  /// substitution where [outerNode] is the nullability node for the type
+  /// variable being eliminated by the substitution, and [innerNode] is the
+  /// nullability node for the type being substituted in its place.
+  ///
+  /// [innerNode] may be `null`.  TODO(paulberry): when?
+  ///
+  /// Additional constraints are recorded in [constraints] as necessary to make
+  /// the new nullability node behave consistently with the old nodes.
+  /// TODO(paulberry): this should become unnecessary once constraint solving is
+  /// performed directly using [NullabilityNode] objects.
+  factory NullabilityNode.forSubstitution(
+          NullabilityNode innerNode, NullabilityNode outerNode) =
+      NullabilityNodeForSubstitution._;
+
+  /// Creates a [NullabilityNode] representing the nullability of a type
+  /// annotation appearing explicitly in the user's program.
+  factory NullabilityNode.forTypeAnnotation(int endOffset) =>
+      _NullabilityNodeSimple('type($endOffset)');
+
+  NullabilityNode._();
+
+  /// Gets a string that can be appended to a type name during debugging to help
+  /// annotate the nullability of that type.
+  String get debugSuffix =>
+      this == always ? '?' : this == never ? '' : '?($this)';
+
+  /// After nullability propagation, this getter can be used to query whether
+  /// the type associated with this node should be considered nullable.
+  bool get isNullable;
+
+  /// Indicates whether this node is associated with a named parameter for which
+  /// nullability migration needs to decide whether it is optional or required.
+  bool get isPossiblyOptional => _isPossiblyOptional;
+
+  String get _debugPrefix;
+
+  _NullabilityState get _state;
+
+  /// Records the fact that an invocation was made to a function with named
+  /// parameters, and the named parameter associated with this node was not
+  /// supplied.
+  void recordNamedParameterNotSupplied(
+      List<NullabilityNode> guards, NullabilityGraph graph) {
+    if (isPossiblyOptional) {
+      graph.connect(NullabilityNode.always, this, guards: guards);
+    }
+  }
+
+  void recordNonNullIntent(
+      List<NullabilityNode> guards, NullabilityGraph graph) {
+    graph.connect(this, NullabilityNode.never, hard: true);
+  }
+
+  String toString() {
+    if (_debugName == null) {
+      var prefix = _debugPrefix;
+      if (_debugNamesInUse.add(prefix)) {
+        _debugName = prefix;
+      } else {
+        for (int i = 0;; i++) {
+          var name = '${prefix}_$i';
+          if (_debugNamesInUse.add(name)) {
+            _debugName = name;
+            break;
+          }
+        }
+      }
+    }
+    return _debugName;
+  }
+
+  /// Tracks the possibility that this node is associated with a named parameter
+  /// for which nullability migration needs to decide whether it is optional or
+  /// required.
+  void trackPossiblyOptional() {
+    _isPossiblyOptional = true;
+  }
+
+  /// Connect the nullability nodes [sourceNode] and [destinationNode]
+  /// appopriately to account for an assignment in the source code being
+  /// analyzed.  Any constraints generated are recorded in [constraints].
+  ///
+  /// If [checkNotNull] is non-null, then it tracks the expression that may
+  /// require null-checking.
+  ///
+  /// [inConditionalControlFlow] indicates whether the assignment being analyzed
+  /// is reachable conditionally or unconditionally from the entry point of the
+  /// function; this affects how non-null intent is back-propagated.
+  static void recordAssignment(
+      NullabilityNode sourceNode,
+      NullabilityNode destinationNode,
+      List<NullabilityNode> guards,
+      NullabilityGraph graph,
+      {@required bool hard}) {
+    graph.connect(sourceNode, destinationNode, guards: guards, hard: hard);
+  }
+}
+
+/// Derived class for nullability nodes that arise from the least-upper-bound
+/// implied by a conditional expression.
+class NullabilityNodeForLUB extends _NullabilityNodeCompound {
+  final NullabilityNode left;
+
+  final NullabilityNode right;
+
+  NullabilityNodeForLUB._(this.left, this.right);
+
+  @override
+  Iterable<NullabilityNode> get _components => [left, right];
+
+  @override
+  String get _debugPrefix => 'LUB($left, $right)';
+}
+
+/// Derived class for nullability nodes that arise from type variable
+/// substitution.
+class NullabilityNodeForSubstitution extends _NullabilityNodeCompound {
+  /// Nullability node representing the inner type of the substitution.
+  ///
+  /// For example, if this NullabilityNode arose from substituting `int*` for
+  /// `T` in the type `T*`, [innerNode] is the nullability corresponding to the
+  /// `*` in `int*`.
+  final NullabilityNode innerNode;
+
+  /// Nullability node representing the outer type of the substitution.
+  ///
+  /// For example, if this NullabilityNode arose from substituting `int*` for
+  /// `T` in the type `T*`, [innerNode] is the nullability corresponding to the
+  /// `*` in `T*`.
+  final NullabilityNode outerNode;
+
+  NullabilityNodeForSubstitution._(this.innerNode, this.outerNode);
+
+  @override
+  Iterable<NullabilityNode> get _components => [innerNode, outerNode];
+
+  @override
+  String get _debugPrefix => 'Substituted($innerNode, $outerNode)';
+}
+
+/// Base class for nullability nodes whose state can be mutated safely.
+///
+/// Nearly all nullability nodes derive from this class; the only exceptions are
+/// the fixed nodes [NullabilityNode.always] and [NullabilityNode.never].
+abstract class NullabilityNodeMutable extends NullabilityNode {
+  _NullabilityState _state;
+
+  /// List of [NullabilityEdge] objects describing this node's relationship to
+  /// other nodes that are "downstream" from it (meaning that if a key node is
+  /// nullable, then all the nodes in the corresponding value will either have
+  /// to be nullable, or null checks will have to be added).
+  final _downstreamEdges = <NullabilityEdge>[];
+
+  /// List of nodes that are "upstream" from this node via unconditional control
+  /// flow (meaning that if a node in the list is nullable, then there exists
+  /// code that is unguarded by an "if" statement that indicates that this node
+  /// will have to be nullable, or null checks will have to be added).
+  final _upstreamEdges = <NullabilityEdge>[];
+
+  NullabilityNodeMutable._(
+      {_NullabilityState initialState: _NullabilityState.undetermined})
+      : _state = initialState,
+        super._();
+
+  @override
+  bool get isNullable => _state.isNullable;
+}
+
+abstract class _NullabilityNodeCompound extends NullabilityNodeMutable {
+  _NullabilityNodeCompound() : super._();
+
+  @override
+  bool get isNullable => _components.any((c) => c.isNullable);
+
+  Iterable<NullabilityNode> get _components;
+}
+
+class _NullabilityNodeImmutable extends NullabilityNode {
+  @override
+  final String _debugPrefix;
+
+  @override
+  final bool isNullable;
+
+  _NullabilityNodeImmutable(this._debugPrefix, this.isNullable) : super._();
+
+  @override
+  _NullabilityState get _state => isNullable
+      ? _NullabilityState.ordinaryNullable
+      : _NullabilityState.nonNullable;
+}
+
+class _NullabilityNodeSimple extends NullabilityNodeMutable {
+  @override
+  final String _debugPrefix;
+
+  _NullabilityNodeSimple(this._debugPrefix,
+      {_NullabilityState initialState: _NullabilityState.undetermined})
+      : super._(initialState: initialState);
+}
+
+/// State of a nullability node.
+class _NullabilityState {
+  /// State of a nullability node whose nullability hasn't been decided yet.
+  static const undetermined = _NullabilityState._('undetermined', false);
+
+  /// State of a nullability node that has been determined to be non-nullable
+  /// by propagating upstream.
+  static const nonNullable = _NullabilityState._('non-nullable', false);
+
+  /// State of a nullability node that has been determined to be nullable by
+  /// propagating downstream.
+  static const ordinaryNullable =
+      _NullabilityState._('ordinary nullable', true);
+
+  /// State of a nullability node that has been determined to be nullable by
+  /// propagating upstream from a contravariant use of a generic.
+  static const exactNullable = _NullabilityState._('exact nullable', true);
+
+  /// Name of the state (for use in debugging).
+  final String name;
+
+  /// Indicates whether the given state should be considered nullable.
+  ///
+  /// After propagation, any nodes that remain in the undetermined state are
+  /// considered to be non-nullable, so this field is returns `false` for nodes
+  /// in that state.
+  final bool isNullable;
+
+  const _NullabilityState._(this.name, this.isNullable);
+
+  @override
+  String toString() => name;
+}
diff --git a/pkg/nnbd_migration/lib/src/potential_modification.dart b/pkg/nnbd_migration/lib/src/potential_modification.dart
new file mode 100644
index 0000000..6bc0d16
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/potential_modification.dart
@@ -0,0 +1,169 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceEdit;
+import 'package:nnbd_migration/src/conditional_discard.dart';
+import 'package:nnbd_migration/src/nullability_node.dart';
+
+/// Records information about how a conditional expression or statement might
+/// need to be modified.
+class ConditionalModification extends PotentialModification {
+  final int offset;
+
+  final int end;
+
+  final bool isStatement;
+
+  final ConditionalDiscard discard;
+
+  final _KeepNode condition;
+
+  final _KeepNode thenStatement;
+
+  final _KeepNode elseStatement;
+
+  factory ConditionalModification(AstNode node, ConditionalDiscard discard) {
+    if (node is IfStatement) {
+      return ConditionalModification._(
+          node.offset,
+          node.end,
+          node is Statement,
+          discard,
+          _KeepNode(node.condition),
+          _KeepNode(node.thenStatement),
+          _KeepNode(node.elseStatement));
+    } else {
+      throw new UnimplementedError('TODO(paulberry)');
+    }
+  }
+
+  ConditionalModification._(this.offset, this.end, this.isStatement,
+      this.discard, this.condition, this.thenStatement, this.elseStatement);
+
+  @override
+  bool get isEmpty => discard.keepTrue && discard.keepFalse;
+
+  @override
+  Iterable<SourceEdit> get modifications {
+    if (isEmpty) return const [];
+    // TODO(paulberry): move the following logic into DartEditBuilder (see
+    // dartbug.com/35872).
+    var result = <SourceEdit>[];
+    var keepNodes = <_KeepNode>[];
+    if (!discard.pureCondition) {
+      keepNodes.add(condition); // TODO(paulberry): test
+    }
+    if (discard.keepTrue) {
+      keepNodes.add(thenStatement); // TODO(paulberry): test
+    }
+    if (discard.keepFalse) {
+      keepNodes.add(elseStatement); // TODO(paulberry): test
+    }
+    // TODO(paulberry): test thoroughly
+    for (int i = 0; i < keepNodes.length; i++) {
+      var keepNode = keepNodes[i];
+      if (i == 0 && keepNode.offset != offset) {
+        result.add(SourceEdit(offset, 0, '/* '));
+      }
+      if (i != 0 || keepNode.offset != offset) {
+        result.add(SourceEdit(keepNode.offset, 0, '*/ '));
+      }
+      if (i != keepNodes.length - 1 || keepNode.end != end) {
+        result.add(SourceEdit(keepNode.end, 0,
+            keepNode.isExpression && isStatement ? '; /*' : ' /*'));
+      }
+      if (i == keepNodes.length - 1 && keepNode.end != end) {
+        result.add(SourceEdit(end, 0, ' */'));
+      }
+    }
+    return result;
+  }
+}
+
+/// Records information about the possible addition of an import
+/// to the source code.
+class PotentiallyAddImport extends PotentialModification {
+  final _usages = <PotentialModification>[];
+
+  final int _offset;
+  final String _importPath;
+
+  PotentiallyAddImport(
+      AstNode beforeNode, this._importPath, PotentialModification usage)
+      : _offset = beforeNode.offset {
+    _usages.add(usage);
+  }
+
+  get importPath => _importPath;
+
+  @override
+  bool get isEmpty {
+    for (PotentialModification usage in _usages) {
+      if (!usage.isEmpty) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  // TODO(danrubel): change all of dartfix NNBD to use DartChangeBuilder
+  @override
+  Iterable<SourceEdit> get modifications =>
+      isEmpty ? const [] : [SourceEdit(_offset, 0, "import '$_importPath';\n")];
+
+  void addUsage(PotentialModification usage) {
+    _usages.add(usage);
+  }
+}
+
+/// Records information about the possible addition of a `@required` annotation
+/// to the source code.
+class PotentiallyAddRequired extends PotentialModification {
+  final NullabilityNode _node;
+
+  final int _offset;
+
+  PotentiallyAddRequired(DefaultFormalParameter parameter, this._node)
+      : _offset = parameter.offset;
+
+  @override
+  bool get isEmpty => _node.isNullable;
+
+  @override
+  Iterable<SourceEdit> get modifications =>
+      isEmpty ? const [] : [SourceEdit(_offset, 0, '@required ')];
+}
+
+/// Interface used by data structures representing potential modifications to
+/// the code being migrated.
+abstract class PotentialModification {
+  bool get isEmpty;
+
+  /// Gets the individual migrations that need to be done, considering the
+  /// solution to the constraint equations.
+  Iterable<SourceEdit> get modifications;
+}
+
+/// Helper object used by [ConditionalModification] to keep track of AST nodes
+/// within the conditional expression.
+class _KeepNode {
+  final int offset;
+
+  final int end;
+
+  final bool isExpression;
+
+  factory _KeepNode(AstNode node) {
+    int offset = node.offset;
+    int end = node.end;
+    if (node is Block && node.statements.isNotEmpty) {
+      offset = node.statements.beginToken.offset;
+      end = node.statements.endToken.end;
+    }
+    return _KeepNode._(offset, end, node is Expression);
+  }
+
+  _KeepNode._(this.offset, this.end, this.isExpression);
+}
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
new file mode 100644
index 0000000..df66005
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:nnbd_migration/src/conditional_discard.dart';
+import 'package:nnbd_migration/src/decorated_type.dart';
+import 'package:nnbd_migration/src/expression_checks.dart';
+import 'package:nnbd_migration/src/node_builder.dart';
+import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/potential_modification.dart';
+
+class Variables implements VariableRecorder, VariableRepository {
+  final _decoratedElementTypes = <Element, DecoratedType>{};
+
+  final _decoratedTypeAnnotations =
+      <Source, Map<int, DecoratedTypeAnnotation>>{};
+
+  final _potentialModifications = <Source, List<PotentialModification>>{};
+
+  @override
+  DecoratedType decoratedElementType(Element element, {bool create: false}) =>
+      _decoratedElementTypes[element] ??= create
+          ? DecoratedType.forElement(element)
+          : throw StateError('No element found');
+
+  @override
+  DecoratedType decoratedTypeAnnotation(
+      Source source, TypeAnnotation typeAnnotation) {
+    return _decoratedTypeAnnotations[source]
+        [_uniqueOffsetForTypeAnnotation(typeAnnotation)];
+  }
+
+  Map<Source, List<PotentialModification>> getPotentialModifications() =>
+      _potentialModifications;
+
+  @override
+  void recordConditionalDiscard(
+      Source source, AstNode node, ConditionalDiscard conditionalDiscard) {
+    _addPotentialModification(
+        source, ConditionalModification(node, conditionalDiscard));
+  }
+
+  void recordDecoratedElementType(Element element, DecoratedType type) {
+    _decoratedElementTypes[element] = type;
+  }
+
+  void recordDecoratedExpressionType(Expression node, DecoratedType type) {}
+
+  void recordDecoratedTypeAnnotation(
+      Source source, TypeAnnotation node, DecoratedTypeAnnotation type,
+      {bool potentialModification: true}) {
+    if (potentialModification) _addPotentialModification(source, type);
+    (_decoratedTypeAnnotations[source] ??=
+        {})[_uniqueOffsetForTypeAnnotation(node)] = type;
+  }
+
+  @override
+  void recordExpressionChecks(
+      Source source, Expression expression, ExpressionChecks checks) {
+    _addPotentialModification(source, checks);
+  }
+
+  @override
+  void recordPossiblyOptional(
+      Source source, DefaultFormalParameter parameter, NullabilityNode node) {
+    var modification = PotentiallyAddRequired(parameter, node);
+    _addPotentialModification(source, modification);
+    _addPotentialImport(
+        source, parameter, modification, 'package:meta/meta.dart');
+  }
+
+  void _addPotentialImport(Source source, AstNode node,
+      PotentialModification usage, String importPath) {
+    // Get the compilation unit - assume not null
+    while (node is! CompilationUnit) {
+      node = node.parent;
+    }
+    var unit = node as CompilationUnit;
+
+    // Find an existing import
+    for (var directive in unit.directives) {
+      if (directive is ImportDirective) {
+        if (directive.uri.stringValue == importPath) {
+          return;
+        }
+      }
+    }
+
+    // Add the usage to an existing modification if possible
+    for (var modification in (_potentialModifications[source] ??= [])) {
+      if (modification is PotentiallyAddImport) {
+        if (modification.importPath == importPath) {
+          modification.addUsage(usage);
+          return;
+        }
+      }
+    }
+
+    // Create a new import modification
+    AstNode beforeNode;
+    for (var directive in unit.directives) {
+      if (directive is ImportDirective || directive is ExportDirective) {
+        beforeNode = directive;
+        break;
+      }
+    }
+    if (beforeNode == null) {
+      for (var declaration in unit.declarations) {
+        beforeNode = declaration;
+        break;
+      }
+    }
+    _addPotentialModification(
+        source, PotentiallyAddImport(beforeNode, importPath, usage));
+  }
+
+  void _addPotentialModification(
+      Source source, PotentialModification potentialModification) {
+    (_potentialModifications[source] ??= []).add(potentialModification);
+  }
+
+  int _uniqueOffsetForTypeAnnotation(TypeAnnotation typeAnnotation) =>
+      typeAnnotation is GenericFunctionType
+          ? typeAnnotation.functionKeyword.offset
+          : typeAnnotation.offset;
+}
diff --git a/pkg/nnbd_migration/pubspec.yaml b/pkg/nnbd_migration/pubspec.yaml
new file mode 100644
index 0000000..bacb556
--- /dev/null
+++ b/pkg/nnbd_migration/pubspec.yaml
@@ -0,0 +1,6 @@
+name: nnbd_migration
+publish_to: none
+environment:
+  sdk: '>=2.2.2 <3.0.0'
+dependencies:
+  analyzer: ^0.36.3
diff --git a/pkg/nnbd_migration/test/abstract_context.dart b/pkg/nnbd_migration/test/abstract_context.dart
new file mode 100644
index 0000000..a9f80a5
--- /dev/null
+++ b/pkg/nnbd_migration/test/abstract_context.dart
@@ -0,0 +1,140 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/overlay_file_system.dart';
+import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/test_utilities/mock_sdk.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+
+/// TODO(paulberry): this logic is duplicated from other packages.  Find a way
+/// share it, or avoid relying on it.
+class AbstractContextTest with ResourceProviderMixin {
+  OverlayResourceProvider overlayResourceProvider;
+
+  AnalysisContextCollection _analysisContextCollection;
+  AnalysisDriver _driver;
+
+  AnalysisDriver get driver => _driver;
+
+  AnalysisSession get session => driver.currentSession;
+
+  void addMetaPackage() {
+    addPackageFile('meta', 'meta.dart', r'''
+library meta;
+
+const Required required = const Required();
+
+class Required {
+  final String reason;
+  const Required([this.reason]);
+}
+''');
+  }
+
+  /// Add a new file with the given [pathInLib] to the package with the
+  /// given [packageName].  Then ensure that the test package depends on the
+  /// [packageName].
+  File addPackageFile(String packageName, String pathInLib, String content) {
+    var packagePath = '/.pub-cache/$packageName';
+    _addTestPackageDependency(packageName, packagePath);
+    return newFile('$packagePath/lib/$pathInLib', content: content);
+  }
+
+  Source addSource(String path, String content, [Uri uri]) {
+    File file = newFile(path, content: content);
+    Source source = file.createSource(uri);
+    driver.addFile(file.path);
+    driver.changeFile(file.path);
+    return source;
+  }
+
+  /// Create all analysis contexts in `/home`.
+  void createAnalysisContexts() {
+    _analysisContextCollection = AnalysisContextCollectionImpl(
+      includedPaths: [convertPath('/home')],
+      enableIndex: true,
+      resourceProvider: overlayResourceProvider,
+      sdkPath: convertPath('/sdk'),
+    );
+
+    var testPath = convertPath('/home/test');
+    _driver = getDriver(testPath);
+  }
+
+  /// Return the existing analysis context that should be used to analyze the
+  /// given [path], or throw [StateError] if the [path] is not analyzed in any
+  /// of the created analysis contexts.
+  AnalysisContext getContext(String path) {
+    path = convertPath(path);
+    return _analysisContextCollection.contextFor(path);
+  }
+
+  /// Return the existing analysis driver that should be used to analyze the
+  /// given [path], or throw [StateError] if the [path] is not analyzed in any
+  /// of the created analysis contexts.
+  AnalysisDriver getDriver(String path) {
+    DriverBasedAnalysisContext context =
+        getContext(path) as DriverBasedAnalysisContext;
+    return context.driver;
+  }
+
+  void setUp() {
+    setupResourceProvider();
+    overlayResourceProvider = OverlayResourceProvider(resourceProvider);
+
+    new MockSdk(resourceProvider: resourceProvider);
+
+    newFolder('/home/test');
+    newFile('/home/test/.packages', content: r'''
+test:file:///home/test/lib
+''');
+
+    createAnalysisContexts();
+  }
+
+  void setupResourceProvider() {}
+
+  void tearDown() {
+    AnalysisEngine.instance.clearCaches();
+    AnalysisEngine.instance.logger = null;
+  }
+
+  void _addTestPackageDependency(String name, String rootPath) {
+    var packagesFile = getFile('/home/test/.packages');
+    var packagesContent = packagesFile.readAsStringSync();
+
+    // Ignore if there is already the same package dependency.
+    if (packagesContent.contains('$name:file://')) {
+      return;
+    }
+
+    packagesContent += '$name:${toUri('$rootPath/lib')}\n';
+
+    packagesFile.writeAsStringSync(packagesContent);
+
+    _createDriver();
+  }
+
+  void _createDriver() {
+    var collection = AnalysisContextCollectionImpl(
+      includedPaths: [convertPath('/home')],
+      enableIndex: true,
+      resourceProvider: resourceProvider,
+      sdkPath: convertPath('/sdk'),
+    );
+
+    var testPath = convertPath('/home/test');
+    var context = collection.contextFor(testPath) as DriverBasedAnalysisContext;
+
+    _driver = context.driver;
+  }
+}
diff --git a/pkg/nnbd_migration/test/abstract_single_unit.dart b/pkg/nnbd_migration/test/abstract_single_unit.dart
new file mode 100644
index 0000000..25c5f87
--- /dev/null
+++ b/pkg/nnbd_migration/test/abstract_single_unit.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
+import 'package:test/test.dart';
+
+import 'abstract_context.dart';
+
+/// TODO(paulberry): this logic is duplicated from other packages.  Find a way
+/// share it, or avoid relying on it.
+class AbstractSingleUnitTest extends AbstractContextTest {
+  bool verifyNoTestUnitErrors = true;
+
+  String testCode;
+  String testFile;
+  Source testSource;
+  ResolvedUnitResult testAnalysisResult;
+  CompilationUnit testUnit;
+  CompilationUnitElement testUnitElement;
+  LibraryElement testLibraryElement;
+  FindNode findNode;
+
+  void addTestSource(String code, [Uri uri]) {
+    testCode = code;
+    testSource = addSource(testFile, code, uri);
+  }
+
+  Future<void> resolveTestUnit(String code) async {
+    addTestSource(code);
+    testAnalysisResult = await session.getResolvedUnit(testFile);
+    testUnit = testAnalysisResult.unit;
+    if (verifyNoTestUnitErrors) {
+      expect(testAnalysisResult.errors.where((AnalysisError error) {
+        return error.errorCode != HintCode.DEAD_CODE &&
+            error.errorCode != HintCode.UNUSED_CATCH_CLAUSE &&
+            error.errorCode != HintCode.UNUSED_CATCH_STACK &&
+            error.errorCode != HintCode.UNUSED_ELEMENT &&
+            error.errorCode != HintCode.UNUSED_FIELD &&
+            error.errorCode != HintCode.UNUSED_IMPORT &&
+            error.errorCode != HintCode.UNUSED_LOCAL_VARIABLE;
+      }), isEmpty);
+    }
+    testUnitElement = testUnit.declaredElement;
+    testLibraryElement = testUnitElement.library;
+    findNode = FindNode(code, testUnit);
+  }
+
+  @override
+  void setUp() {
+    super.setUp();
+    testFile = convertPath('/home/test/lib/test.dart');
+  }
+}
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
new file mode 100644
index 0000000..8f3e7d7
--- /dev/null
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -0,0 +1,1331 @@
+// Copyright (c) 2019, 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:analyzer/src/generated/source.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'abstract_context.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(_ProvisionalApiTest);
+    defineReflectiveTests(_ProvisionalApiTestPermissive);
+    defineReflectiveTests(_ProvisionalApiTestWithReset);
+  });
+}
+
+/// Tests of the provisional API.
+@reflectiveTest
+class _ProvisionalApiTest extends _ProvisionalApiTestBase
+    with _ProvisionalApiTestCases {
+  @override
+  bool get _usePermissiveMode => false;
+}
+
+/// Base class for provisional API tests.
+abstract class _ProvisionalApiTestBase extends AbstractContextTest {
+  bool get _usePermissiveMode;
+
+  /// Hook invoked after calling `prepareInput` on each input.
+  void _afterPrepare() {}
+
+  /// Verifies that migration of the files in [input] produces the output in
+  /// [expectedOutput].
+  Future<void> _checkMultipleFileChanges(
+      Map<String, String> input, Map<String, String> expectedOutput) async {
+    for (var path in input.keys) {
+      newFile(path, content: input[path]);
+    }
+    var listener = new _TestMigrationListener();
+    var migration =
+        NullabilityMigration(listener, permissive: _usePermissiveMode);
+    for (var path in input.keys) {
+      migration.prepareInput(await session.getResolvedUnit(path));
+    }
+    _afterPrepare();
+    for (var path in input.keys) {
+      migration.processInput(await session.getResolvedUnit(path));
+    }
+    migration.finish();
+    var sourceEdits = <String, List<SourceEdit>>{};
+    for (var entry in listener._edits.entries) {
+      var path = entry.key.fullName;
+      expect(expectedOutput.keys, contains(path));
+      sourceEdits[path] = entry.value;
+    }
+    for (var path in expectedOutput.keys) {
+      var sourceEditsForPath = sourceEdits[path] ?? [];
+      sourceEditsForPath.sort((a, b) => b.offset.compareTo(a.offset));
+      expect(SourceEdit.applySequence(input[path], sourceEditsForPath),
+          expectedOutput[path]);
+    }
+  }
+
+  /// Verifies that migraiton of the single file with the given [content]
+  /// produces the [expected] output.
+  Future<void> _checkSingleFileChanges(String content, String expected) async {
+    var sourcePath = convertPath('/home/test/lib/test.dart');
+    await _checkMultipleFileChanges(
+        {sourcePath: content}, {sourcePath: expected});
+  }
+}
+
+/// Mixin containing test cases for the provisional API.
+mixin _ProvisionalApiTestCases on _ProvisionalApiTestBase {
+  test_comment_bang_implies_non_null_intent() async {
+    var content = '''
+void f(int/*!*/ i) {}
+void g(bool b, int i) {
+  if (b) f(i);
+}
+main() {
+  g(false, null);
+}
+''';
+    var expected = '''
+void f(int/*!*/ i) {}
+void g(bool b, int? i) {
+  if (b) f(i!);
+}
+main() {
+  g(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_comment_question_implies_nullable() async {
+    var content = '''
+void _f() {
+  int/*?*/ i = 0;
+}
+''';
+    var expected = '''
+void _f() {
+  int?/*?*/ i = 0;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_conditional_assert_statement_does_not_imply_non_null_intent() async {
+    var content = '''
+void f(bool b, int i) {
+  if (b) return;
+  assert(i != null);
+}
+void g(bool b, int i) {
+  if (b) f(b, i);
+}
+main() {
+  g(true, null);
+}
+''';
+    var expected = '''
+void f(bool b, int? i) {
+  if (b) return;
+  assert(i != null);
+}
+void g(bool b, int? i) {
+  if (b) f(b, i);
+}
+main() {
+  g(true, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_conditional_dereference_does_not_imply_non_null_intent() async {
+    var content = '''
+void f(bool b, int i) {
+  if (b) i.abs();
+}
+void g(bool b, int i) {
+  if (b) f(b, i);
+}
+main() {
+  g(false, null);
+}
+''';
+    var expected = '''
+void f(bool b, int? i) {
+  if (b) i!.abs();
+}
+void g(bool b, int? i) {
+  if (b) f(b, i);
+}
+main() {
+  g(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_conditional_non_null_usage_does_not_imply_non_null_intent() async {
+    var content = '''
+void f(bool b, int i, int j) {
+  if (b) i.gcd(j);
+}
+void g(bool b, int i, int j) {
+  if (b) f(b, i, j);
+}
+main() {
+  g(false, 0, null);
+}
+''';
+    var expected = '''
+void f(bool b, int i, int? j) {
+  if (b) i.gcd(j!);
+}
+void g(bool b, int i, int? j) {
+  if (b) f(b, i, j);
+}
+main() {
+  g(false, 0, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_conditional_usage_does_not_propagate_non_null_intent() async {
+    var content = '''
+void f(int i) {
+  assert(i != null);
+}
+void g(bool b, int i) {
+  if (b) f(i);
+}
+void h(bool b1, bool b2, int i) {
+  if (b1) g(b2, i);
+}
+main() {
+  h(true, false, null);
+}
+''';
+    var expected = '''
+void f(int i) {
+  assert(i != null);
+}
+void g(bool b, int? i) {
+  if (b) f(i!);
+}
+void h(bool b1, bool b2, int? i) {
+  if (b1) g(b2, i);
+}
+main() {
+  h(true, false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_constructorDeclaration_namedParameter() async {
+    var content = '''
+class C {
+  C({Key key});
+}
+class Key {}
+''';
+    var expected = '''
+class C {
+  C({Key? key});
+}
+class Key {}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_assignment_field() async {
+    var content = '''
+class C {
+  int x = 0;
+}
+void f(C c) {
+  c.x = null;
+}
+''';
+    var expected = '''
+class C {
+  int? x = 0;
+}
+void f(C c) {
+  c.x = null;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_assignment_field_in_cascade() async {
+    var content = '''
+class C {
+  int x = 0;
+}
+void f(C c) {
+  c..x = null;
+}
+''';
+    var expected = '''
+class C {
+  int? x = 0;
+}
+void f(C c) {
+  c..x = null;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_assignment_local() async {
+    var content = '''
+void main() {
+  int i = 0;
+  i = null;
+}
+''';
+    var expected = '''
+void main() {
+  int? i = 0;
+  i = null;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_assignment_setter() async {
+    var content = '''
+class C {
+  void set s(int value) {}
+}
+void f(C c) {
+  c.s = null;
+}
+''';
+    var expected = '''
+class C {
+  void set s(int? value) {}
+}
+void f(C c) {
+  c.s = null;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_field_read() async {
+    var content = '''
+class C {
+  int/*?*/ f = 0;
+}
+int f(C c) => c.f;
+''';
+    var expected = '''
+class C {
+  int?/*?*/ f = 0;
+}
+int? f(C c) => c.f;
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_generic_contravariant_inward() async {
+    var content = '''
+class C<T> {
+  void f(T t) {}
+}
+void g(C<int> c, int i) {
+  c.f(i);
+}
+void test(C<int> c) {
+  g(c, null);
+}
+''';
+
+    // Default behavior is to add nullability at the call site.  Rationale: this
+    // is correct in the common case where the generic parameter represents the
+    // type of an item in a container.  Also, if there are many callers that are
+    // largely independent, adding nullability to the callee would likely
+    // propagate to a field in the class, and thence (via return values of other
+    // methods) to most users of the class.  Whereas if we add nullability at
+    // the call site it's possible that other call sites won't need it.
+    //
+    // TODO(paulberry): possible improvement: detect that since C uses T in a
+    // contravariant way, and deduce that test should change to
+    // `void test(C<int?> c)`
+    var expected = '''
+class C<T> {
+  void f(T t) {}
+}
+void g(C<int?> c, int? i) {
+  c.f(i);
+}
+void test(C<int> c) {
+  g(c, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_generic_covariant_outward() async {
+    var content = '''
+class C<T> {
+  T getValue() => null;
+}
+int f(C<int> x) => x.getValue();
+''';
+    var expected = '''
+class C<T> {
+  T? getValue() => null;
+}
+int? f(C<int> x) => x.getValue();
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_generic_covariant_substituted() async {
+    var content = '''
+abstract class C<T> {
+  T getValue();
+}
+int f(C<int/*?*/> x) => x.getValue();
+''';
+    var expected = '''
+abstract class C<T> {
+  T getValue();
+}
+int? f(C<int?/*?*/> x) => x.getValue();
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_indexed_get_index_value() async {
+    var content = '''
+class C {
+  int operator[](int i) => 1;
+}
+int f(C c) => c[null];
+''';
+    var expected = '''
+class C {
+  int operator[](int? i) => 1;
+}
+int f(C c) => c[null];
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_indexed_get_value() async {
+    var content = '''
+class C {
+  int operator[](int i) => null;
+}
+int f(C c) => c[0];
+''';
+    var expected = '''
+class C {
+  int? operator[](int i) => null;
+}
+int? f(C c) => c[0];
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_indexed_set_index_value() async {
+    var content = '''
+class C {
+  void operator[]=(int i, int j) {}
+}
+void f(C c) {
+  c[null] = 0;
+}
+''';
+    var expected = '''
+class C {
+  void operator[]=(int? i, int j) {}
+}
+void f(C c) {
+  c[null] = 0;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_indexed_set_index_value_in_cascade() async {
+    var content = '''
+class C {
+  void operator[]=(int i, int j) {}
+}
+void f(C c) {
+  c..[null] = 0;
+}
+''';
+    var expected = '''
+class C {
+  void operator[]=(int? i, int j) {}
+}
+void f(C c) {
+  c..[null] = 0;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_indexed_set_value() async {
+    var content = '''
+class C {
+  void operator[]=(int i, int j) {}
+}
+void f(C c) {
+  c[0] = null;
+}
+''';
+    var expected = '''
+class C {
+  void operator[]=(int i, int? j) {}
+}
+void f(C c) {
+  c[0] = null;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_inward() async {
+    var content = '''
+int f(int i) => 0;
+int g(int i) => f(i);
+void test() {
+  g(null);
+}
+''';
+
+    var expected = '''
+int f(int? i) => 0;
+int g(int? i) => f(i);
+void test() {
+  g(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_inward_missing_type() async {
+    var content = '''
+int f(int i) => 0;
+int g(i) => f(i); // TODO(danrubel): suggest type
+void test() {
+  g(null);
+}
+''';
+
+    var expected = '''
+int f(int? i) => 0;
+int g(i) => f(i); // TODO(danrubel): suggest type
+void test() {
+  g(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_local_declaration() async {
+    var content = '''
+void f(int i) {
+  int j = i;
+}
+main() {
+  f(null);
+}
+''';
+    var expected = '''
+void f(int? i) {
+  int? j = i;
+}
+main() {
+  f(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_local_reference() async {
+    var content = '''
+void f(int i) {}
+void g(int i) {
+  int j = i;
+  f(i);
+}
+main() {
+  g(null);
+}
+''';
+    var expected = '''
+void f(int? i) {}
+void g(int? i) {
+  int? j = i;
+  f(i);
+}
+main() {
+  g(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_method_call_in_cascade() async {
+    var content = '''
+class C {
+  void m(int x) {}
+}
+void f(C c) {
+  c..m(null);
+}
+''';
+    var expected = '''
+class C {
+  void m(int? x) {}
+}
+void f(C c) {
+  c..m(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_outward() async {
+    var content = '''
+int f(int i) => null;
+int g(int i) => f(i);
+''';
+
+    var expected = '''
+int? f(int i) => null;
+int? g(int i) => f(i);
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_outward_missing_type() async {
+    var content = '''
+f(int i) => null; // TODO(danrubel): suggest type
+int g(int i) => f(i);
+''';
+
+    var expected = '''
+f(int i) => null; // TODO(danrubel): suggest type
+int? g(int i) => f(i);
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_discard_simple_condition() async {
+    var content = '''
+int f(int i) {
+  if (i == null) {
+    return null;
+  } else {
+    return i + 1;
+  }
+}
+''';
+
+    var expected = '''
+int f(int i) {
+  /* if (i == null) {
+    return null;
+  } else {
+    */ return i + 1; /*
+  } */
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_getter_topLevel() async {
+    var content = '''
+int get g => 0;
+''';
+    var expected = '''
+int get g => 0;
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_no_default_unused() async {
+    var content = '''
+void f({String s}) {}
+main() {
+  f();
+}
+''';
+    var expected = '''
+void f({String? s}) {}
+main() {
+  f();
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_no_default_unused_propagate() async {
+    var content = '''
+void f(String s) {}
+void g({String s}) {
+  f(s);
+}
+main() {
+  g();
+}
+''';
+    var expected = '''
+void f(String? s) {}
+void g({String? s}) {
+  f(s);
+}
+main() {
+  g();
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_no_default_unused_required() async {
+    // The `@required` annotation overrides the assumption of nullability.
+    // The call at `f()` is presumed to be in error.
+    addMetaPackage();
+    var content = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+main() {
+  f();
+}
+''';
+    var expected = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+main() {
+  f();
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_no_default_used_non_null() async {
+    var content = '''
+void f({String s}) {}
+main() {
+  f(s: 'x');
+}
+''';
+    var expected = '''
+void f({String? s}) {}
+main() {
+  f(s: 'x');
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_no_default_used_non_null_propagate() async {
+    var content = '''
+void f(String s) {}
+void g({String s}) {
+  f(s);
+}
+main() {
+  g(s: 'x');
+}
+''';
+    var expected = '''
+void f(String? s) {}
+void g({String? s}) {
+  f(s);
+}
+main() {
+  g(s: 'x');
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_no_default_used_null_option2() async {
+    var content = '''
+void f({String s}) {}
+main() {
+  f(s: null);
+}
+''';
+    var expected = '''
+void f({String? s}) {}
+main() {
+  f(s: null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_no_default_used_null_required() async {
+    // Explicitly passing `null` forces the parameter to be nullable even though
+    // it is required.
+    addMetaPackage();
+    var content = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+main() {
+  f(s: null);
+}
+''';
+    var expected = '''
+import 'package:meta/meta.dart';
+void f({@required String? s}) {}
+main() {
+  f(s: null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_with_non_null_default_unused_option2() async {
+    var content = '''
+void f({String s: 'foo'}) {}
+main() {
+  f();
+}
+''';
+    var expected = '''
+void f({String s: 'foo'}) {}
+main() {
+  f();
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_with_non_null_default_used_non_null_option2() async {
+    var content = '''
+void f({String s: 'foo'}) {}
+main() {
+  f(s: 'bar');
+}
+''';
+    var expected = '''
+void f({String s: 'foo'}) {}
+main() {
+  f(s: 'bar');
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_with_non_null_default_used_null_option2() async {
+    var content = '''
+void f({String s: 'foo'}) {}
+main() {
+  f(s: null);
+}
+''';
+    var expected = '''
+void f({String? s: 'foo'}) {}
+main() {
+  f(s: null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_with_null_default_unused_option2() async {
+    var content = '''
+void f({String s: null}) {}
+main() {
+  f();
+}
+''';
+    var expected = '''
+void f({String? s: null}) {}
+main() {
+  f();
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_non_null_assertion() async {
+    var content = '''
+int f(int i, [int j]) {
+  if (i == 0) return i;
+  return i + j;
+}
+''';
+
+    var expected = '''
+int f(int i, [int? j]) {
+  if (i == 0) return i;
+  return i + j!;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_null_aware_getter_invocation() async {
+    var content = '''
+bool f(int i) => i?.isEven;
+main() {
+  f(null);
+}
+''';
+    var expected = '''
+bool? f(int? i) => i?.isEven;
+main() {
+  f(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_null_aware_method_invocation() async {
+    var content = '''
+int f(int i) => i?.abs();
+main() {
+  f(null);
+}
+''';
+    var expected = '''
+int? f(int? i) => i?.abs();
+main() {
+  f(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_null_aware_setter_invocation_null_target() async {
+    var content = '''
+class C {
+  void set x(int value);
+}
+int f(C c) => c?.x = 1;
+main() {
+  f(null);
+}
+''';
+    var expected = '''
+class C {
+  void set x(int value);
+}
+int? f(C? c) => c?.x = 1;
+main() {
+  f(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_null_aware_setter_invocation_null_value() async {
+    var content = '''
+class C {
+  void set x(int value);
+}
+int f(C c) => c?.x = 1;
+main() {
+  f(null);
+}
+''';
+    var expected = '''
+class C {
+  void set x(int value);
+}
+int? f(C? c) => c?.x = 1;
+main() {
+  f(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_parameter_genericFunctionType() async {
+    var content = '''
+int f(int x, int Function(int i) g) {
+  return g(x);
+}
+''';
+    var expected = '''
+int f(int x, int Function(int i) g) {
+  return g(x);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_single_file_multiple_changes() async {
+    var content = '''
+int f() => null;
+int g() => null;
+''';
+    var expected = '''
+int? f() => null;
+int? g() => null;
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_single_file_single_change() async {
+    var content = '''
+int f() => null;
+''';
+    var expected = '''
+int? f() => null;
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_two_files() async {
+    var root = '/home/test/lib';
+    var path1 = convertPath('$root/file1.dart');
+    var file1 = '''
+import 'file2.dart';
+int f() => null;
+int h() => g();
+''';
+    var expected1 = '''
+import 'file2.dart';
+int? f() => null;
+int? h() => g();
+''';
+    var path2 = convertPath('$root/file2.dart');
+    var file2 = '''
+import 'file1.dart';
+int g() => f();
+''';
+    var expected2 = '''
+import 'file1.dart';
+int? g() => f();
+''';
+    await _checkMultipleFileChanges(
+        {path1: file1, path2: file2}, {path1: expected1, path2: expected2});
+  }
+
+  test_type_argument_flows_to_bound() async {
+    // The inference of C<int?> forces class C to be declared as
+    // C<T extends Object?>.
+    var content = '''
+class C<T extends Object> {
+  void m(T t);
+}
+class D<T extends Object> {
+  void m(T t);
+}
+f(C<int> c, D<int> d) {
+  c.m(null);
+}
+''';
+    var expected = '''
+class C<T extends Object?> {
+  void m(T t);
+}
+class D<T extends Object> {
+  void m(T t);
+}
+f(C<int?> c, D<int> d) {
+  c.m(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_unconditional_assert_statement_implies_non_null_intent() async {
+    var content = '''
+void f(int i) {
+  assert(i != null);
+}
+void g(bool b, int i) {
+  if (b) f(i);
+}
+main() {
+  g(false, null);
+}
+''';
+    var expected = '''
+void f(int i) {
+  assert(i != null);
+}
+void g(bool b, int? i) {
+  if (b) f(i!);
+}
+main() {
+  g(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_unconditional_binary_expression_implies_non_null_intent() async {
+    var content = '''
+void f(int i) {
+  i + 1;
+}
+void g(bool b, int i) {
+  if (b) f(i);
+}
+main() {
+  g(false, null);
+}
+''';
+    var expected = '''
+void f(int i) {
+  i + 1;
+}
+void g(bool b, int? i) {
+  if (b) f(i!);
+}
+main() {
+  g(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_unconditional_cascaded_indexed_set_implies_non_null_intent() async {
+    var content = '''
+class C {
+  operator[]=(int i, int j) {}
+}
+void f(C c) {
+  c..[1] = 2;
+}
+void g(bool b, C c) {
+  if (b) f(c);
+}
+main() {
+  g(false, null);
+}
+''';
+    var expected = '''
+class C {
+  operator[]=(int i, int j) {}
+}
+void f(C c) {
+  c..[1] = 2;
+}
+void g(bool b, C? c) {
+  if (b) f(c!);
+}
+main() {
+  g(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_unconditional_cascaded_method_call_implies_non_null_intent() async {
+    var content = '''
+void f(int i) {
+  i..abs();
+}
+void g(bool b, int i) {
+  if (b) f(i);
+}
+main() {
+  g(false, null);
+}
+''';
+    var expected = '''
+void f(int i) {
+  i..abs();
+}
+void g(bool b, int? i) {
+  if (b) f(i!);
+}
+main() {
+  g(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_unconditional_cascaded_property_set_implies_non_null_intent() async {
+    var content = '''
+class C {
+  int x = 0;
+}
+void f(C c) {
+  c..x = 1;
+}
+void g(bool b, C c) {
+  if (b) f(c);
+}
+main() {
+  g(false, null);
+}
+''';
+    var expected = '''
+class C {
+  int x = 0;
+}
+void f(C c) {
+  c..x = 1;
+}
+void g(bool b, C? c) {
+  if (b) f(c!);
+}
+main() {
+  g(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_unconditional_method_call_implies_non_null_intent() async {
+    var content = '''
+void f(int i) {
+  i.abs();
+}
+void g(bool b, int i) {
+  if (b) f(i);
+}
+main() {
+  g(false, null);
+}
+''';
+    var expected = '''
+void f(int i) {
+  i.abs();
+}
+void g(bool b, int? i) {
+  if (b) f(i!);
+}
+main() {
+  g(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_unconditional_non_null_usage_implies_non_null_intent() async {
+    var content = '''
+void f(int i, int j) {
+  i.gcd(j);
+}
+void g(bool b, int i, int j) {
+  if (b) f(i, j);
+}
+main() {
+  g(false, 0, null);
+}
+''';
+    var expected = '''
+void f(int i, int j) {
+  i.gcd(j);
+}
+void g(bool b, int i, int? j) {
+  if (b) f(i, j!);
+}
+main() {
+  g(false, 0, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_unconditional_property_access_implies_non_null_intent() async {
+    var content = '''
+void f(int i) {
+  i.isEven;
+}
+void g(bool b, int i) {
+  if (b) f(i);
+}
+main() {
+  g(false, null);
+}
+''';
+    var expected = '''
+void f(int i) {
+  i.isEven;
+}
+void g(bool b, int? i) {
+  if (b) f(i!);
+}
+main() {
+  g(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_unconditional_usage_propagates_non_null_intent() async {
+    var content = '''
+void f(int i) {
+  assert(i != null);
+}
+void g(int i) {
+  f(i);
+}
+void h(bool b, int i) {
+  if (b) g(i);
+}
+main() {
+  h(false, null);
+}
+''';
+    var expected = '''
+void f(int i) {
+  assert(i != null);
+}
+void g(int i) {
+  f(i);
+}
+void h(bool b, int? i) {
+  if (b) g(i!);
+}
+main() {
+  h(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+}
+
+@reflectiveTest
+class _ProvisionalApiTestPermissive extends _ProvisionalApiTestBase
+    with _ProvisionalApiTestCases {
+  @override
+  bool get _usePermissiveMode => true;
+}
+
+/// Tests of the provisional API, where the driver is reset between calls to
+/// `prepareInput` and `processInput`, ensuring that the migration algorithm
+/// sees different AST and element objects during different phases.
+@reflectiveTest
+class _ProvisionalApiTestWithReset extends _ProvisionalApiTestBase
+    with _ProvisionalApiTestCases {
+  @override
+  bool get _usePermissiveMode => false;
+
+  @override
+  void _afterPrepare() {
+    driver.resetUriResolution();
+  }
+}
+
+class _TestMigrationListener implements NullabilityMigrationListener {
+  final _edits = <Source, List<SourceEdit>>{};
+
+  List<String> details = [];
+
+  @override
+  void addDetail(String detail) {
+    details.add(detail);
+  }
+
+  @override
+  void addEdit(SingleNullabilityFix fix, SourceEdit edit) {
+    (_edits[fix.source] ??= []).add(edit);
+  }
+
+  @override
+  void addFix(SingleNullabilityFix fix) {}
+}
diff --git a/pkg/nnbd_migration/test/migration_visitor_test.dart b/pkg/nnbd_migration/test/migration_visitor_test.dart
new file mode 100644
index 0000000..27969b5
--- /dev/null
+++ b/pkg/nnbd_migration/test/migration_visitor_test.dart
@@ -0,0 +1,1566 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:meta/meta.dart';
+import 'package:nnbd_migration/src/conditional_discard.dart';
+import 'package:nnbd_migration/src/decorated_type.dart';
+import 'package:nnbd_migration/src/expression_checks.dart';
+import 'package:nnbd_migration/src/graph_builder.dart';
+import 'package:nnbd_migration/src/node_builder.dart';
+import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/variables.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'abstract_single_unit.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(GraphBuilderTest);
+    defineReflectiveTests(NodeBuilderTest);
+  });
+}
+
+@reflectiveTest
+class GraphBuilderTest extends MigrationVisitorTestBase {
+  /// Analyzes the given source code, producing constraint variables and
+  /// constraints for it.
+  @override
+  Future<CompilationUnit> analyze(String code) async {
+    var unit = await super.analyze(code);
+    unit.accept(
+        GraphBuilder(typeProvider, _variables, graph, testSource, null));
+    return unit;
+  }
+
+  void assertConditional(
+      NullabilityNode node, NullabilityNode left, NullabilityNode right) {
+    var conditionalNode = node as NullabilityNodeForLUB;
+    expect(conditionalNode.left, same(left));
+    expect(conditionalNode.right, same(right));
+  }
+
+  /// Checks that there are no nullability nodes upstream from [node] that could
+  /// cause it to become nullable.
+  void assertNoUpstreamNullability(NullabilityNode node) {
+    // NullabilityNode.never can never become nullable, even if it has nodes
+    // upstream from it.
+    if (node == NullabilityNode.never) return;
+
+    for (var upstreamNode in graph.getUpstreamNodesForTesting(node)) {
+      expect(upstreamNode, NullabilityNode.never);
+    }
+  }
+
+  /// Verifies that a null check will occur under the proper circumstances.
+  ///
+  /// [expressionChecks] is the object tracking whether or not a null check is
+  /// needed.  [valueNode] is the node representing the possibly-nullable value
+  /// that is the source of the assignment or use.  [contextNode] is the node
+  /// representing the possibly-nullable value that is the destination of the
+  /// assignment (if the value is being assigned), or `null` if the value is
+  /// being used in a circumstance where `null` is not permitted.  [guards] is
+  /// a list of nullability nodes for which there are enclosing if statements
+  /// checking that the corresponding values are non-null.
+  void assertNullCheck(
+      ExpressionChecks expressionChecks, NullabilityNode valueNode,
+      {NullabilityNode contextNode, List<NullabilityNode> guards = const []}) {
+    expect(expressionChecks.valueNode, same(valueNode));
+    if (contextNode == null) {
+      expect(expressionChecks.contextNode, same(NullabilityNode.never));
+    } else {
+      expect(expressionChecks.contextNode, same(contextNode));
+    }
+    expect(expressionChecks.guards, guards);
+  }
+
+  /// Gets the [ExpressionChecks] associated with the expression whose text
+  /// representation is [text], or `null` if the expression has no
+  /// [ExpressionChecks] associated with it.
+  ExpressionChecks checkExpression(String text) {
+    return _variables.checkExpression(findNode.expression(text));
+  }
+
+  /// Gets the [DecoratedType] associated with the expression whose text
+  /// representation is [text], or `null` if the expression has no
+  /// [DecoratedType] associated with it.
+  DecoratedType decoratedExpressionType(String text) {
+    return _variables.decoratedExpressionType(findNode.expression(text));
+  }
+
+  test_always() async {
+    await analyze('');
+
+    expect(NullabilityNode.always.isNullable, isTrue);
+  }
+
+  test_assert_demonstrates_non_null_intent() async {
+    await analyze('''
+void f(int i) {
+  assert(i != null);
+}
+''');
+
+    assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
+  }
+
+  test_assignmentExpression_field() async {
+    await analyze('''
+class C {
+  int x = 0;
+}
+void f(C c, int i) {
+  c.x = i;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int i').node,
+        decoratedTypeAnnotation('int x').node,
+        hard: true);
+  }
+
+  test_assignmentExpression_field_cascaded() async {
+    await analyze('''
+class C {
+  int x = 0;
+}
+void f(C c, int i) {
+  c..x = i;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int i').node,
+        decoratedTypeAnnotation('int x').node,
+        hard: true);
+  }
+
+  test_assignmentExpression_field_target_check() async {
+    await analyze('''
+class C {
+  int x = 0;
+}
+void f(C c, int i) {
+  c.x = i;
+}
+''');
+    assertNullCheck(
+        checkExpression('c.x'), decoratedTypeAnnotation('C c').node);
+  }
+
+  test_assignmentExpression_field_target_check_cascaded() async {
+    await analyze('''
+class C {
+  int x = 0;
+}
+void f(C c, int i) {
+  c..x = i;
+}
+''');
+    assertNullCheck(
+        checkExpression('c..x'), decoratedTypeAnnotation('C c').node);
+  }
+
+  test_assignmentExpression_indexExpression_index() async {
+    await analyze('''
+class C {
+  void operator[]=(int a, int b) {}
+}
+void f(C c, int i, int j) {
+  c[i] = j;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int i').node,
+        decoratedTypeAnnotation('int a').node,
+        hard: true);
+  }
+
+  test_assignmentExpression_indexExpression_return_value() async {
+    await analyze('''
+class C {
+  void operator[]=(int a, int b) {}
+}
+int f(C c, int i, int j) => c[i] = j;
+''');
+    assertEdge(decoratedTypeAnnotation('int j').node,
+        decoratedTypeAnnotation('int f').node,
+        hard: false);
+  }
+
+  test_assignmentExpression_indexExpression_target_check() async {
+    await analyze('''
+class C {
+  void operator[]=(int a, int b) {}
+}
+void f(C c, int i, int j) {
+  c[i] = j;
+}
+''');
+    assertNullCheck(checkExpression('c['), decoratedTypeAnnotation('C c').node);
+  }
+
+  test_assignmentExpression_indexExpression_value() async {
+    await analyze('''
+class C {
+  void operator[]=(int a, int b) {}
+}
+void f(C c, int i, int j) {
+  c[i] = j;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int j').node,
+        decoratedTypeAnnotation('int b').node,
+        hard: true);
+  }
+
+  test_assignmentExpression_operands() async {
+    await analyze('''
+void f(int i, int j) {
+  i = j;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int j').node,
+        decoratedTypeAnnotation('int i').node,
+        hard: true);
+  }
+
+  test_assignmentExpression_return_value() async {
+    await analyze('''
+void f(int i, int j) {
+  g(i = j);
+}
+void g(int k) {}
+''');
+    assertEdge(decoratedTypeAnnotation('int j').node,
+        decoratedTypeAnnotation('int k').node,
+        hard: false);
+  }
+
+  test_assignmentExpression_setter() async {
+    await analyze('''
+class C {
+  void set s(int value) {}
+}
+void f(C c, int i) {
+  c.s = i;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int i').node,
+        decoratedTypeAnnotation('int value').node,
+        hard: true);
+  }
+
+  test_assignmentExpression_setter_null_aware() async {
+    await analyze('''
+class C {
+  void set s(int value) {}
+}
+int f(C c, int i) => (c?.s = i);
+''');
+    var lubNode =
+        decoratedExpressionType('(c?.s = i)').node as NullabilityNodeForLUB;
+    expect(lubNode.left, same(decoratedTypeAnnotation('C c').node));
+    expect(lubNode.right, same(decoratedTypeAnnotation('int i').node));
+    assertEdge(lubNode, decoratedTypeAnnotation('int f').node, hard: false);
+  }
+
+  test_assignmentExpression_setter_target_check() async {
+    await analyze('''
+class C {
+  void set s(int value) {}
+}
+void f(C c, int i) {
+  c.s = i;
+}
+''');
+    assertNullCheck(
+        checkExpression('c.s'), decoratedTypeAnnotation('C c').node);
+  }
+
+  test_binaryExpression_add_left_check() async {
+    await analyze('''
+int f(int i, int j) => i + j;
+''');
+
+    assertNullCheck(
+        checkExpression('i +'), decoratedTypeAnnotation('int i').node);
+  }
+
+  test_binaryExpression_add_left_check_custom() async {
+    await analyze('''
+class Int {
+  Int operator+(Int other) => this;
+}
+Int f(Int i, Int j) => i + j;
+''');
+
+    assertNullCheck(
+        checkExpression('i +'), decoratedTypeAnnotation('Int i').node);
+  }
+
+  test_binaryExpression_add_result_custom() async {
+    await analyze('''
+class Int {
+  Int operator+(Int other) => this;
+}
+Int f(Int i, Int j) => (i + j);
+''');
+
+    assertNullCheck(checkExpression('(i + j)'),
+        decoratedTypeAnnotation('Int operator+').node,
+        contextNode: decoratedTypeAnnotation('Int f').node);
+  }
+
+  test_binaryExpression_add_result_not_null() async {
+    await analyze('''
+int f(int i, int j) => i + j;
+''');
+
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int f').node);
+  }
+
+  test_binaryExpression_add_right_check() async {
+    await analyze('''
+int f(int i, int j) => i + j;
+''');
+
+    assertNullCheck(
+        checkExpression('j;'), decoratedTypeAnnotation('int j').node);
+  }
+
+  test_binaryExpression_add_right_check_custom() async {
+    await analyze('''
+class Int {
+  Int operator+(Int other) => this;
+}
+Int f(Int i, Int j) => i + j/*check*/;
+''');
+
+    assertNullCheck(
+        checkExpression('j/*check*/'), decoratedTypeAnnotation('Int j').node,
+        contextNode: decoratedTypeAnnotation('Int other').node);
+  }
+
+  test_binaryExpression_equal() async {
+    await analyze('''
+bool f(int i, int j) => i == j;
+''');
+
+    assertNoUpstreamNullability(decoratedTypeAnnotation('bool f').node);
+  }
+
+  test_boolLiteral() async {
+    await analyze('''
+bool f() {
+  return true;
+}
+''');
+    assertNoUpstreamNullability(decoratedTypeAnnotation('bool').node);
+  }
+
+  test_cascadeExpression() async {
+    await analyze('''
+class C {
+  int x = 0;
+}
+C f(C c, int i) => c..x = i;
+''');
+    assertEdge(decoratedTypeAnnotation('C c').node,
+        decoratedTypeAnnotation('C f').node,
+        hard: false);
+  }
+
+  test_conditionalExpression_condition_check() async {
+    await analyze('''
+int f(bool b, int i, int j) {
+  return (b ? i : j);
+}
+''');
+
+    var nullable_b = decoratedTypeAnnotation('bool b').node;
+    var check_b = checkExpression('b ?');
+    assertNullCheck(check_b, nullable_b);
+  }
+
+  test_conditionalExpression_general() async {
+    await analyze('''
+int f(bool b, int i, int j) {
+  return (b ? i : j);
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_j = decoratedTypeAnnotation('int j').node;
+    var nullable_conditional = decoratedExpressionType('(b ?').node;
+    assertConditional(nullable_conditional, nullable_i, nullable_j);
+    var nullable_return = decoratedTypeAnnotation('int f').node;
+    assertNullCheck(checkExpression('(b ? i : j)'), nullable_conditional,
+        contextNode: nullable_return);
+  }
+
+  test_conditionalExpression_left_non_null() async {
+    await analyze('''
+int f(bool b, int i) {
+  return (b ? (throw i) : i);
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_conditional =
+        decoratedExpressionType('(b ?').node as NullabilityNodeForLUB;
+    var nullable_throw = nullable_conditional.left;
+    assertNoUpstreamNullability(nullable_throw);
+    assertConditional(nullable_conditional, nullable_throw, nullable_i);
+  }
+
+  test_conditionalExpression_left_null() async {
+    await analyze('''
+int f(bool b, int i) {
+  return (b ? null : i);
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_conditional = decoratedExpressionType('(b ?').node;
+    assertConditional(nullable_conditional, NullabilityNode.always, nullable_i);
+  }
+
+  test_conditionalExpression_right_non_null() async {
+    await analyze('''
+int f(bool b, int i) {
+  return (b ? i : (throw i));
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_conditional =
+        decoratedExpressionType('(b ?').node as NullabilityNodeForLUB;
+    var nullable_throw = nullable_conditional.right;
+    assertNoUpstreamNullability(nullable_throw);
+    assertConditional(nullable_conditional, nullable_i, nullable_throw);
+  }
+
+  test_conditionalExpression_right_null() async {
+    await analyze('''
+int f(bool b, int i) {
+  return (b ? i : null);
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_conditional = decoratedExpressionType('(b ?').node;
+    assertConditional(nullable_conditional, nullable_i, NullabilityNode.always);
+  }
+
+  test_functionDeclaration_expression_body() async {
+    await analyze('''
+int/*1*/ f(int/*2*/ i) => i/*3*/;
+''');
+
+    assertNullCheck(
+        checkExpression('i/*3*/'), decoratedTypeAnnotation('int/*2*/').node,
+        contextNode: decoratedTypeAnnotation('int/*1*/').node);
+  }
+
+  test_functionDeclaration_parameter_named_default_notNull() async {
+    await analyze('''
+void f({int i = 1}) {}
+''');
+
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
+  }
+
+  test_functionDeclaration_parameter_named_default_null() async {
+    await analyze('''
+void f({int i = null}) {}
+''');
+
+    assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+        hard: false);
+  }
+
+  test_functionDeclaration_parameter_named_no_default() async {
+    await analyze('''
+void f({int i}) {}
+''');
+
+    assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+        hard: false);
+  }
+
+  test_functionDeclaration_parameter_named_no_default_required() async {
+    addMetaPackage();
+    await analyze('''
+import 'package:meta/meta.dart';
+void f({@required int i}) {}
+''');
+
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
+  }
+
+  test_functionDeclaration_parameter_positionalOptional_default_notNull() async {
+    await analyze('''
+void f([int i = 1]) {}
+''');
+
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
+  }
+
+  test_functionDeclaration_parameter_positionalOptional_default_null() async {
+    await analyze('''
+void f([int i = null]) {}
+''');
+
+    assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+        hard: false);
+  }
+
+  test_functionDeclaration_parameter_positionalOptional_no_default() async {
+    await analyze('''
+void f([int i]) {}
+''');
+
+    assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+        hard: false);
+  }
+
+  test_functionDeclaration_resets_unconditional_control_flow() async {
+    await analyze('''
+void f(bool b, int i, int j) {
+  assert(i != null);
+  if (b) return;
+  assert(j != null);
+}
+void g(int k) {
+  assert(k != null);
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
+    assertNoEdge(always, decoratedTypeAnnotation('int j').node);
+    assertEdge(decoratedTypeAnnotation('int k').node, never, hard: true);
+  }
+
+  test_functionInvocation_parameter_fromLocalParameter() async {
+    await analyze('''
+void f(int/*1*/ i) {}
+void test(int/*2*/ i) {
+  f(i/*3*/);
+}
+''');
+
+    var int_1 = decoratedTypeAnnotation('int/*1*/');
+    var int_2 = decoratedTypeAnnotation('int/*2*/');
+    var i_3 = checkExpression('i/*3*/');
+    assertNullCheck(i_3, int_2.node, contextNode: int_1.node);
+    assertEdge(int_2.node, int_1.node, hard: true);
+  }
+
+  test_functionInvocation_parameter_named() async {
+    await analyze('''
+void f({int i: 0}) {}
+void g(int j) {
+  f(i: j/*check*/);
+}
+''');
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_j = decoratedTypeAnnotation('int j').node;
+    assertNullCheck(checkExpression('j/*check*/'), nullable_j,
+        contextNode: nullable_i);
+  }
+
+  test_functionInvocation_parameter_named_missing() async {
+    await analyze('''
+void f({int i}) {}
+void g() {
+  f();
+}
+''');
+    var optional_i = possiblyOptionalParameter('int i');
+    expect(getEdges(NullabilityNode.always, optional_i), isNotEmpty);
+  }
+
+  test_functionInvocation_parameter_named_missing_required() async {
+    addMetaPackage();
+    verifyNoTestUnitErrors = false;
+    await analyze('''
+import 'package:meta/meta.dart';
+void f({@required int i}) {}
+void g() {
+  f();
+}
+''');
+    // The call at `f()` is presumed to be in error; no constraint is recorded.
+    var optional_i = possiblyOptionalParameter('int i');
+    expect(optional_i, isNull);
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    assertNoUpstreamNullability(nullable_i);
+  }
+
+  test_functionInvocation_parameter_null() async {
+    await analyze('''
+void f(int i) {}
+void test() {
+  f(null);
+}
+''');
+
+    assertNullCheck(checkExpression('null'), NullabilityNode.always,
+        contextNode: decoratedTypeAnnotation('int').node);
+  }
+
+  test_functionInvocation_return() async {
+    await analyze('''
+int/*1*/ f() => 0;
+int/*2*/ g() {
+  return (f());
+}
+''');
+
+    assertNullCheck(
+        checkExpression('(f())'), decoratedTypeAnnotation('int/*1*/').node,
+        contextNode: decoratedTypeAnnotation('int/*2*/').node);
+  }
+
+  test_if_condition() async {
+    await analyze('''
+void f(bool b) {
+  if (b) {}
+}
+''');
+
+    assertNullCheck(
+        checkExpression('b) {}'), decoratedTypeAnnotation('bool b').node);
+  }
+
+  test_if_conditional_control_flow_after() async {
+    // Asserts after ifs don't demonstrate non-null intent.
+    // TODO(paulberry): if both branches complete normally, they should.
+    await analyze('''
+void f(bool b, int i) {
+  if (b) return;
+  assert(i != null);
+}
+''');
+
+    assertNoEdge(always, decoratedTypeAnnotation('int i').node);
+  }
+
+  test_if_conditional_control_flow_within() async {
+    // Asserts inside ifs don't demonstrate non-null intent.
+    await analyze('''
+void f(bool b, int i) {
+  if (b) {
+    assert(i != null);
+  } else {
+    assert(i != null);
+  }
+}
+''');
+
+    assertNoEdge(always, decoratedTypeAnnotation('int i').node);
+  }
+
+  test_if_guard_equals_null() async {
+    await analyze('''
+int f(int i, int j, int k) {
+  if (i == null) {
+    return j/*check*/;
+  } else {
+    return k/*check*/;
+  }
+}
+''');
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_j = decoratedTypeAnnotation('int j').node;
+    var nullable_k = decoratedTypeAnnotation('int k').node;
+    var nullable_return = decoratedTypeAnnotation('int f').node;
+    assertNullCheck(checkExpression('j/*check*/'), nullable_j,
+        contextNode: nullable_return, guards: [nullable_i]);
+    assertNullCheck(checkExpression('k/*check*/'), nullable_k,
+        contextNode: nullable_return);
+    var discard = statementDiscard('if (i == null)');
+    expect(discard.trueGuard, same(nullable_i));
+    expect(discard.falseGuard, null);
+    expect(discard.pureCondition, true);
+  }
+
+  test_if_simple() async {
+    await analyze('''
+int f(bool b, int i, int j) {
+  if (b) {
+    return i/*check*/;
+  } else {
+    return j/*check*/;
+  }
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_j = decoratedTypeAnnotation('int j').node;
+    var nullable_return = decoratedTypeAnnotation('int f').node;
+    assertNullCheck(checkExpression('i/*check*/'), nullable_i,
+        contextNode: nullable_return);
+    assertNullCheck(checkExpression('j/*check*/'), nullable_j,
+        contextNode: nullable_return);
+  }
+
+  test_if_without_else() async {
+    await analyze('''
+int f(bool b, int i) {
+  if (b) {
+    return i/*check*/;
+  }
+  return 0;
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_return = decoratedTypeAnnotation('int f').node;
+    assertNullCheck(checkExpression('i/*check*/'), nullable_i,
+        contextNode: nullable_return);
+  }
+
+  test_indexExpression_index() async {
+    await analyze('''
+class C {
+  int operator[](int i) => 1;
+}
+int f(C c, int j) => c[j];
+''');
+    assertEdge(decoratedTypeAnnotation('int j').node,
+        decoratedTypeAnnotation('int i').node,
+        hard: true);
+  }
+
+  test_indexExpression_index_cascaded() async {
+    await analyze('''
+class C {
+  int operator[](int i) => 1;
+}
+C f(C c, int j) => c..[j];
+''');
+    assertEdge(decoratedTypeAnnotation('int j').node,
+        decoratedTypeAnnotation('int i').node,
+        hard: true);
+  }
+
+  test_indexExpression_return_type() async {
+    await analyze('''
+class C {
+  int operator[](int i) => 1;
+}
+int f(C c) => c[0];
+''');
+    assertEdge(decoratedTypeAnnotation('int operator').node,
+        decoratedTypeAnnotation('int f').node,
+        hard: false);
+  }
+
+  test_indexExpression_target_check() async {
+    await analyze('''
+class C {
+  int operator[](int i) => 1;
+}
+int f(C c) => c[0];
+''');
+    assertNullCheck(checkExpression('c['), decoratedTypeAnnotation('C c').node);
+  }
+
+  test_indexExpression_target_check_cascaded() async {
+    await analyze('''
+class C {
+  int operator[](int i) => 1;
+}
+C f(C c) => c..[0];
+''');
+    assertNullCheck(
+        checkExpression('c..['), decoratedTypeAnnotation('C c').node);
+  }
+
+  test_indexExpression_target_demonstrates_non_null_intent() async {
+    await analyze('''
+class C {
+  int operator[](int i) => 1;
+}
+int f(C c) => c[0];
+''');
+    assertEdge(decoratedTypeAnnotation('C c').node, never, hard: true);
+  }
+
+  test_indexExpression_target_demonstrates_non_null_intent_cascaded() async {
+    await analyze('''
+class C {
+  int operator[](int i) => 1;
+}
+C f(C c) => c..[0];
+''');
+    assertEdge(decoratedTypeAnnotation('C c').node, never, hard: true);
+  }
+
+  test_intLiteral() async {
+    await analyze('''
+int f() {
+  return 0;
+}
+''');
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
+  }
+
+  test_methodDeclaration_resets_unconditional_control_flow() async {
+    await analyze('''
+class C {
+  void f(bool b, int i, int j) {
+    assert(i != null);
+    if (b) return;
+    assert(j != null);
+  }
+  void g(int k) {
+    assert(k != null);
+  }
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
+    assertNoEdge(always, decoratedTypeAnnotation('int j').node);
+    assertEdge(decoratedTypeAnnotation('int k').node, never, hard: true);
+  }
+
+  test_methodInvocation_parameter_contravariant() async {
+    await analyze('''
+class C<T> {
+  void f(T t) {}
+}
+void g(C<int> c, int i) {
+  c.f(i/*check*/);
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_c_t = decoratedTypeAnnotation('C<int>').typeArguments[0].node;
+    var nullable_t = decoratedTypeAnnotation('T t').node;
+    var check_i = checkExpression('i/*check*/');
+    var nullable_c_t_or_nullable_t =
+        check_i.contextNode as NullabilityNodeForSubstitution;
+    expect(nullable_c_t_or_nullable_t.innerNode, same(nullable_c_t));
+    expect(nullable_c_t_or_nullable_t.outerNode, same(nullable_t));
+    assertNullCheck(check_i, nullable_i,
+        contextNode: nullable_c_t_or_nullable_t);
+  }
+
+  test_methodInvocation_parameter_generic() async {
+    await analyze('''
+class C<T> {}
+void f(C<int/*1*/>/*2*/ c) {}
+void g(C<int/*3*/>/*4*/ c) {
+  f(c/*check*/);
+}
+''');
+
+    assertEdge(decoratedTypeAnnotation('int/*3*/').node,
+        decoratedTypeAnnotation('int/*1*/').node,
+        hard: false);
+    assertNullCheck(checkExpression('c/*check*/'),
+        decoratedTypeAnnotation('C<int/*3*/>/*4*/').node,
+        contextNode: decoratedTypeAnnotation('C<int/*1*/>/*2*/').node);
+  }
+
+  test_methodInvocation_parameter_named() async {
+    await analyze('''
+class C {
+  void f({int i: 0}) {}
+}
+void g(C c, int j) {
+  c.f(i: j/*check*/);
+}
+''');
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_j = decoratedTypeAnnotation('int j').node;
+    assertNullCheck(checkExpression('j/*check*/'), nullable_j,
+        contextNode: nullable_i);
+  }
+
+  test_methodInvocation_return_type() async {
+    await analyze('''
+class C {
+  bool m() => true;
+}
+bool f(C c) => c.m();
+''');
+    assertEdge(decoratedTypeAnnotation('bool m').node,
+        decoratedTypeAnnotation('bool f').node,
+        hard: false);
+  }
+
+  test_methodInvocation_return_type_null_aware() async {
+    await analyze('''
+class C {
+  bool m() => true;
+}
+bool f(C c) => (c?.m());
+''');
+    var lubNode =
+        decoratedExpressionType('(c?.m())').node as NullabilityNodeForLUB;
+    expect(lubNode.left, same(decoratedTypeAnnotation('C c').node));
+    expect(lubNode.right, same(decoratedTypeAnnotation('bool m').node));
+    assertEdge(lubNode, decoratedTypeAnnotation('bool f').node, hard: false);
+  }
+
+  test_methodInvocation_target_check() async {
+    await analyze('''
+class C {
+  void m() {}
+}
+void test(C c) {
+  c.m();
+}
+''');
+
+    assertNullCheck(
+        checkExpression('c.m'), decoratedTypeAnnotation('C c').node);
+  }
+
+  test_methodInvocation_target_check_cascaded() async {
+    await analyze('''
+class C {
+  void m() {}
+}
+void test(C c) {
+  c..m();
+}
+''');
+
+    assertNullCheck(
+        checkExpression('c..m'), decoratedTypeAnnotation('C c').node);
+  }
+
+  test_methodInvocation_target_demonstrates_non_null_intent() async {
+    await analyze('''
+class C {
+  void m() {}
+}
+void test(C c) {
+  c.m();
+}
+''');
+
+    assertEdge(decoratedTypeAnnotation('C c').node, never, hard: true);
+  }
+
+  test_methodInvocation_target_demonstrates_non_null_intent_cascaded() async {
+    await analyze('''
+class C {
+  void m() {}
+}
+void test(C c) {
+  c..m();
+}
+''');
+
+    assertEdge(decoratedTypeAnnotation('C c').node, never, hard: true);
+  }
+
+  test_never() async {
+    await analyze('');
+
+    expect(NullabilityNode.never.isNullable, isFalse);
+  }
+
+  test_parenthesizedExpression() async {
+    await analyze('''
+int f() {
+  return (null);
+}
+''');
+
+    assertNullCheck(checkExpression('(null)'), NullabilityNode.always,
+        contextNode: decoratedTypeAnnotation('int').node);
+  }
+
+  test_prefixedIdentifier_field_type() async {
+    await analyze('''
+class C {
+  bool b = true;
+}
+bool f(C c) => c.b;
+''');
+    assertEdge(decoratedTypeAnnotation('bool b').node,
+        decoratedTypeAnnotation('bool f').node,
+        hard: false);
+  }
+
+  test_prefixedIdentifier_getter_type() async {
+    await analyze('''
+class C {
+  bool get b => true;
+}
+bool f(C c) => c.b;
+''');
+    assertEdge(decoratedTypeAnnotation('bool get').node,
+        decoratedTypeAnnotation('bool f').node,
+        hard: false);
+  }
+
+  test_prefixedIdentifier_target_check() async {
+    await analyze('''
+class C {
+  int get x => 1;
+}
+void test(C c) {
+  c.x;
+}
+''');
+
+    assertNullCheck(
+        checkExpression('c.x'), decoratedTypeAnnotation('C c').node);
+  }
+
+  test_prefixedIdentifier_target_demonstrates_non_null_intent() async {
+    await analyze('''
+class C {
+  int get x => 1;
+}
+void test(C c) {
+  c.x;
+}
+''');
+
+    assertEdge(decoratedTypeAnnotation('C c').node, never, hard: true);
+  }
+
+  test_propertyAccess_return_type() async {
+    await analyze('''
+class C {
+  bool get b => true;
+}
+bool f(C c) => (c).b;
+''');
+    assertEdge(decoratedTypeAnnotation('bool get').node,
+        decoratedTypeAnnotation('bool f').node,
+        hard: false);
+  }
+
+  test_propertyAccess_return_type_null_aware() async {
+    await analyze('''
+class C {
+  bool get b => true;
+}
+bool f(C c) => (c?.b);
+''');
+    var lubNode =
+        decoratedExpressionType('(c?.b)').node as NullabilityNodeForLUB;
+    expect(lubNode.left, same(decoratedTypeAnnotation('C c').node));
+    expect(lubNode.right, same(decoratedTypeAnnotation('bool get b').node));
+    assertEdge(lubNode, decoratedTypeAnnotation('bool f').node, hard: false);
+  }
+
+  test_propertyAccess_target_check() async {
+    await analyze('''
+class C {
+  int get x => 1;
+}
+void test(C c) {
+  (c).x;
+}
+''');
+
+    assertNullCheck(
+        checkExpression('c).x'), decoratedTypeAnnotation('C c').node);
+  }
+
+  test_return_implicit_null() async {
+    verifyNoTestUnitErrors = false;
+    await analyze('''
+int f() {
+  return;
+}
+''');
+
+    assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+        hard: false);
+  }
+
+  test_return_null() async {
+    await analyze('''
+int f() {
+  return null;
+}
+''');
+
+    assertNullCheck(checkExpression('null'), NullabilityNode.always,
+        contextNode: decoratedTypeAnnotation('int').node);
+  }
+
+  test_return_null_generic() async {
+    await analyze('''
+class C<T> {
+  T f() {
+    return null;
+  }
+}
+''');
+    var tNode = decoratedTypeAnnotation('T f').node;
+    assertEdge(always, tNode, hard: false);
+    assertNullCheck(checkExpression('null'), always, contextNode: tNode);
+  }
+
+  test_simpleIdentifier_local() async {
+    await analyze('''
+main() {
+  int i = 0;
+  int j = i;
+}
+''');
+
+    assertEdge(decoratedTypeAnnotation('int i').node,
+        decoratedTypeAnnotation('int j').node,
+        hard: true);
+  }
+
+  test_soft_edge_for_non_variable_reference() async {
+    // Edges originating in things other than variable references should be
+    // soft.
+    await analyze('''
+int f() => null;
+''');
+    assertEdge(always, decoratedTypeAnnotation('int').node, hard: false);
+  }
+
+  test_stringLiteral() async {
+    // TODO(paulberry): also test string interpolations
+    await analyze('''
+String f() {
+  return 'x';
+}
+''');
+    assertNoUpstreamNullability(decoratedTypeAnnotation('String').node);
+  }
+
+  test_thisExpression() async {
+    await analyze('''
+class C {
+  C f() => this;
+}
+''');
+
+    assertNoUpstreamNullability(decoratedTypeAnnotation('C f').node);
+  }
+
+  test_throwExpression() async {
+    await analyze('''
+int f() {
+  return throw null;
+}
+''');
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
+  }
+
+  test_type_argument_explicit_bound() async {
+    await analyze('''
+class C<T extends Object> {}
+void f(C<int> c) {}
+''');
+    assertEdge(decoratedTypeAnnotation('int>').node,
+        decoratedTypeAnnotation('Object>').node,
+        hard: true);
+  }
+
+  test_typeName() async {
+    await analyze('''
+Type f() {
+  return int;
+}
+''');
+    assertNoUpstreamNullability(decoratedTypeAnnotation('Type').node);
+  }
+
+  test_variableDeclaration() async {
+    await analyze('''
+void f(int i) {
+  int j = i;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int i').node,
+        decoratedTypeAnnotation('int j').node,
+        hard: true);
+  }
+}
+
+class MigrationVisitorTestBase extends AbstractSingleUnitTest {
+  final _Variables _variables;
+
+  final NullabilityGraph graph;
+
+  MigrationVisitorTestBase() : this._(NullabilityGraph());
+
+  MigrationVisitorTestBase._(this.graph) : _variables = _Variables();
+
+  NullabilityNode get always => NullabilityNode.always;
+
+  NullabilityNode get never => NullabilityNode.never;
+
+  TypeProvider get typeProvider => testAnalysisResult.typeProvider;
+
+  Future<CompilationUnit> analyze(String code) async {
+    await resolveTestUnit(code);
+    testUnit
+        .accept(NodeBuilder(_variables, testSource, null, graph, typeProvider));
+    return testUnit;
+  }
+
+  void assertEdge(NullabilityNode source, NullabilityNode destination,
+      {@required bool hard}) {
+    var edges = getEdges(source, destination);
+    if (edges.length == 0) {
+      fail('Expected edge $source -> $destination, found none');
+    } else if (edges.length != 1) {
+      fail('Found multiple edges $source -> $destination');
+    } else {
+      var edge = edges[0];
+      expect(edge.hard, hard);
+    }
+  }
+
+  void assertNoEdge(NullabilityNode source, NullabilityNode destination) {
+    var edges = getEdges(source, destination);
+    if (edges.isNotEmpty) {
+      fail('Expected no edge $source -> $destination, found ${edges.length}');
+    }
+  }
+
+  /// Gets the [DecoratedType] associated with the generic function type
+  /// annotation whose text is [text].
+  DecoratedType decoratedGenericFunctionTypeAnnotation(String text) {
+    return _variables.decoratedTypeAnnotation(
+        testSource, findNode.genericFunctionType(text));
+  }
+
+  /// Gets the [DecoratedType] associated with the type annotation whose text
+  /// is [text].
+  DecoratedType decoratedTypeAnnotation(String text) {
+    return _variables.decoratedTypeAnnotation(
+        testSource, findNode.typeAnnotation(text));
+  }
+
+  List<NullabilityEdge> getEdges(
+          NullabilityNode source, NullabilityNode destination) =>
+      graph
+          .getUpstreamEdges(destination)
+          .where((e) => e.primarySource == source)
+          .toList();
+
+  NullabilityNode possiblyOptionalParameter(String text) {
+    return _variables
+        .possiblyOptionalParameter(findNode.defaultParameter(text));
+  }
+
+  /// Gets the [ConditionalDiscard] information associated with the statement
+  /// whose text is [text].
+  ConditionalDiscard statementDiscard(String text) {
+    return _variables.conditionalDiscard(findNode.statement(text));
+  }
+}
+
+@reflectiveTest
+class NodeBuilderTest extends MigrationVisitorTestBase {
+  /// Gets the [DecoratedType] associated with the function declaration whose
+  /// name matches [search].
+  DecoratedType decoratedFunctionType(String search) =>
+      _variables.decoratedElementType(
+          findNode.functionDeclaration(search).declaredElement);
+
+  DecoratedType decoratedTypeParameterBound(String search) => _variables
+      .decoratedElementType(findNode.typeParameter(search).declaredElement);
+
+  test_dynamic_type() async {
+    await analyze('''
+dynamic f() {}
+''');
+    var decoratedType = decoratedTypeAnnotation('dynamic');
+    expect(decoratedFunctionType('f').returnType, same(decoratedType));
+    assertEdge(always, decoratedType.node, hard: false);
+  }
+
+  test_field_type_simple() async {
+    await analyze('''
+class C {
+  int f = 0;
+}
+''');
+    var decoratedType = decoratedTypeAnnotation('int');
+    expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
+    expect(
+        _variables.decoratedElementType(
+            findNode.fieldDeclaration('f').fields.variables[0].declaredElement),
+        same(decoratedType));
+  }
+
+  test_genericFunctionType_namedParameterType() async {
+    await analyze('''
+void f(void Function({int y}) x) {}
+''');
+    var decoratedType =
+        decoratedGenericFunctionTypeAnnotation('void Function({int y})');
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedType));
+    expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
+    var decoratedIntType = decoratedTypeAnnotation('int');
+    expect(decoratedType.namedParameters['y'], same(decoratedIntType));
+    expect(decoratedIntType.node, isNotNull);
+    expect(decoratedIntType.node, isNot(NullabilityNode.never));
+  }
+
+  test_genericFunctionType_returnType() async {
+    await analyze('''
+void f(int Function() x) {}
+''');
+    var decoratedType =
+        decoratedGenericFunctionTypeAnnotation('int Function()');
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedType));
+    expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
+    var decoratedIntType = decoratedTypeAnnotation('int');
+    expect(decoratedType.returnType, same(decoratedIntType));
+    expect(decoratedIntType.node, isNotNull);
+    expect(decoratedIntType.node, isNot(NullabilityNode.never));
+  }
+
+  test_genericFunctionType_unnamedParameterType() async {
+    await analyze('''
+void f(void Function(int) x) {}
+''');
+    var decoratedType =
+        decoratedGenericFunctionTypeAnnotation('void Function(int)');
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedType));
+    expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
+    var decoratedIntType = decoratedTypeAnnotation('int');
+    expect(decoratedType.positionalParameters[0], same(decoratedIntType));
+    expect(decoratedIntType.node, isNotNull);
+    expect(decoratedIntType.node, isNot(NullabilityNode.never));
+  }
+
+  test_interfaceType_typeParameter() async {
+    await analyze('''
+void f(List<int> x) {}
+''');
+    var decoratedListType = decoratedTypeAnnotation('List<int>');
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedListType));
+    expect(decoratedListType.node, isNotNull);
+    expect(decoratedListType.node, isNot(NullabilityNode.never));
+    var decoratedIntType = decoratedTypeAnnotation('int');
+    expect(decoratedListType.typeArguments[0], same(decoratedIntType));
+    expect(decoratedIntType.node, isNotNull);
+    expect(decoratedIntType.node, isNot(NullabilityNode.never));
+  }
+
+  test_topLevelFunction_parameterType_implicit_dynamic() async {
+    await analyze('''
+void f(x) {}
+''');
+    var decoratedType =
+        _variables.decoratedElementType(findNode.simple('x').staticElement);
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedType));
+    expect(decoratedType.type.isDynamic, isTrue);
+    expect(decoratedType.node.isNullable, isTrue);
+  }
+
+  test_topLevelFunction_parameterType_named_no_default() async {
+    await analyze('''
+void f({String s}) {}
+''');
+    var decoratedType = decoratedTypeAnnotation('String');
+    var functionType = decoratedFunctionType('f');
+    expect(functionType.namedParameters['s'], same(decoratedType));
+    expect(decoratedType.node, isNotNull);
+    expect(decoratedType.node, isNot(NullabilityNode.never));
+    expect(decoratedType.node, isNot(NullabilityNode.always));
+    expect(functionType.namedParameters['s'].node.isPossiblyOptional, true);
+  }
+
+  test_topLevelFunction_parameterType_named_no_default_required() async {
+    addMetaPackage();
+    await analyze('''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+''');
+    var decoratedType = decoratedTypeAnnotation('String');
+    var functionType = decoratedFunctionType('f');
+    expect(functionType.namedParameters['s'], same(decoratedType));
+    expect(decoratedType.node, isNotNull);
+    expect(decoratedType.node, isNot(NullabilityNode.never));
+    expect(decoratedType.node, isNot(NullabilityNode.always));
+    expect(functionType.namedParameters['s'].node.isPossiblyOptional, false);
+  }
+
+  test_topLevelFunction_parameterType_named_with_default() async {
+    await analyze('''
+void f({String s: 'x'}) {}
+''');
+    var decoratedType = decoratedTypeAnnotation('String');
+    var functionType = decoratedFunctionType('f');
+    expect(functionType.namedParameters['s'], same(decoratedType));
+    expect(decoratedType.node, isNotNull);
+    expect(decoratedType.node, isNot(NullabilityNode.never));
+    expect(functionType.namedParameters['s'].node.isPossiblyOptional, false);
+  }
+
+  test_topLevelFunction_parameterType_positionalOptional() async {
+    await analyze('''
+void f([int i]) {}
+''');
+    var decoratedType = decoratedTypeAnnotation('int');
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedType));
+    expect(decoratedType.node, isNotNull);
+    expect(decoratedType.node, isNot(NullabilityNode.never));
+  }
+
+  test_topLevelFunction_parameterType_simple() async {
+    await analyze('''
+void f(int i) {}
+''');
+    var decoratedType = decoratedTypeAnnotation('int');
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedType));
+    expect(decoratedType.node, isNotNull);
+    expect(decoratedType.node, isNot(NullabilityNode.never));
+  }
+
+  test_topLevelFunction_returnType_implicit_dynamic() async {
+    await analyze('''
+f() {}
+''');
+    var decoratedType = decoratedFunctionType('f').returnType;
+    expect(decoratedType.type.isDynamic, isTrue);
+    expect(decoratedType.node.isNullable, isTrue);
+  }
+
+  test_topLevelFunction_returnType_simple() async {
+    await analyze('''
+int f() => 0;
+''');
+    var decoratedType = decoratedTypeAnnotation('int');
+    expect(decoratedFunctionType('f').returnType, same(decoratedType));
+    expect(decoratedType.node, isNotNull);
+    expect(decoratedType.node, isNot(NullabilityNode.never));
+  }
+
+  test_type_comment_bang() async {
+    await analyze('''
+void f(int/*!*/ i) {}
+''');
+    assertEdge(decoratedTypeAnnotation('int').node, never, hard: true);
+  }
+
+  test_type_comment_question() async {
+    await analyze('''
+void f(int/*?*/ i) {}
+''');
+    assertEdge(always, decoratedTypeAnnotation('int').node, hard: false);
+  }
+
+  test_type_parameter_explicit_bound() async {
+    await analyze('''
+class C<T extends Object> {}
+''');
+    var bound = decoratedTypeParameterBound('T');
+    expect(decoratedTypeAnnotation('Object'), same(bound));
+    expect(bound.node, isNot(NullabilityNode.always));
+    expect(bound.type, typeProvider.objectType);
+  }
+
+  test_type_parameter_implicit_bound() async {
+    // The implicit bound of `T` is automatically `Object?`.  TODO(paulberry):
+    // consider making it possible for type inference to infer an explicit bound
+    // of `Object`.
+    await analyze('''
+class C<T> {}
+''');
+    var bound = decoratedTypeParameterBound('T');
+    expect(bound.node.isNullable, isTrue);
+    expect(bound.type, same(typeProvider.objectType));
+  }
+
+  test_variableDeclaration_type_simple() async {
+    await analyze('''
+main() {
+  int i;
+}
+''');
+    var decoratedType = decoratedTypeAnnotation('int');
+    expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
+  }
+
+  test_void_type() async {
+    await analyze('''
+void f() {}
+''');
+    var decoratedType = decoratedTypeAnnotation('void');
+    expect(decoratedFunctionType('f').returnType, same(decoratedType));
+    assertEdge(always, decoratedType.node, hard: false);
+  }
+}
+
+/// Mock representation of constraint variables.
+class _Variables extends Variables {
+  final _conditionalDiscard = <AstNode, ConditionalDiscard>{};
+
+  final _decoratedExpressionTypes = <Expression, DecoratedType>{};
+
+  final _expressionChecks = <Expression, ExpressionChecks>{};
+
+  final _possiblyOptional = <DefaultFormalParameter, NullabilityNode>{};
+
+  /// Gets the [ExpressionChecks] associated with the given [expression].
+  ExpressionChecks checkExpression(Expression expression) =>
+      _expressionChecks[_normalizeExpression(expression)];
+
+  /// Gets the [conditionalDiscard] associated with the given [expression].
+  ConditionalDiscard conditionalDiscard(AstNode node) =>
+      _conditionalDiscard[node];
+
+  /// Gets the [DecoratedType] associated with the given [expression].
+  DecoratedType decoratedExpressionType(Expression expression) =>
+      _decoratedExpressionTypes[_normalizeExpression(expression)];
+
+  /// Gets the [NullabilityNode] associated with the possibility that
+  /// [parameter] may be optional.
+  NullabilityNode possiblyOptionalParameter(DefaultFormalParameter parameter) =>
+      _possiblyOptional[parameter];
+
+  @override
+  void recordConditionalDiscard(
+      Source source, AstNode node, ConditionalDiscard conditionalDiscard) {
+    _conditionalDiscard[node] = conditionalDiscard;
+    super.recordConditionalDiscard(source, node, conditionalDiscard);
+  }
+
+  void recordDecoratedExpressionType(Expression node, DecoratedType type) {
+    super.recordDecoratedExpressionType(node, type);
+    _decoratedExpressionTypes[_normalizeExpression(node)] = type;
+  }
+
+  @override
+  void recordExpressionChecks(
+      Source source, Expression expression, ExpressionChecks checks) {
+    super.recordExpressionChecks(source, expression, checks);
+    _expressionChecks[_normalizeExpression(expression)] = checks;
+  }
+
+  @override
+  void recordPossiblyOptional(
+      Source source, DefaultFormalParameter parameter, NullabilityNode node) {
+    _possiblyOptional[parameter] = node;
+    super.recordPossiblyOptional(source, parameter, node);
+  }
+
+  /// Unwraps any parentheses surrounding [expression].
+  Expression _normalizeExpression(Expression expression) {
+    while (expression is ParenthesizedExpression) {
+      expression = (expression as ParenthesizedExpression).expression;
+    }
+    return expression;
+  }
+}
diff --git a/pkg/nnbd_migration/test/test_all.dart b/pkg/nnbd_migration/test/test_all.dart
new file mode 100644
index 0000000..8f19fb9
--- /dev/null
+++ b/pkg/nnbd_migration/test/test_all.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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:test_reflective_loader/test_reflective_loader.dart';
+
+import 'api_test.dart' as api_test;
+import 'migration_visitor_test.dart' as migration_visitor_test;
+
+main() {
+  defineReflectiveSuite(() {
+    migration_visitor_test.main();
+    api_test.main();
+  });
+}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index d26e5ee..367542c 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -24,6 +24,7 @@
 analyzer/test/src/summary/resynthesize_kernel_test: Slow, Pass
 analyzer/test/src/task/strong/checker_test: Slow, Pass
 analyzer_plugin/test/plugin/folding_mixin_test: Slow, Pass
+dev_compiler/test/modular/*: Slow, Pass
 dev_compiler/test/options/*: Skip # test needs fixes
 dev_compiler/test/sourcemap/*: SkipByDesign # Skip sourcemap tests
 dev_compiler/test/sourcemap/testfiles/*: SkipByDesign # Skip dev_compiler codegen tests
@@ -77,6 +78,7 @@
 dartfix/test/*: SkipByDesign # Only meant to run on vm
 front_end/test/*: SkipByDesign # Only meant to run on vm, most use dart:mirrors and dart:io
 front_end/tool/*: SkipByDesign # Only meant to run on vm
+nnbd_migration/test/*: SkipByDesign # Uses mirrors
 smith/test/*: SkipByDesign # Only meant to run on vm
 status_file/test/normalize_test: SkipByDesign # Uses dart:io
 status_file/test/parse_and_normalize_test: SkipByDesign # Uses dart:io
@@ -176,9 +178,13 @@
 analyzer/test/*: Skip # Issue 26813
 analyzer/tool/*: Skip # Issue 26813
 
-# Analyze dev_compiler but only run its tests on the vm
 [ $compiler != dart2analyzer && $runtime != vm ]
 dev_compiler/test/*: Skip
+modular_test/test/find_sdk_root1_test: SkipByDesign
+modular_test/test/io_pipeline_test: SkipByDesign
+modular_test/test/loader/loader_test: SkipByDesign
+modular_test/test/specification_parser_test: SkipByDesign
+modular_test/test/src/find_sdk_root2_test: SkipByDesign
 
 [ $compiler == dart2js && $runtime == chrome && $system == macos ]
 third_party/di_tests/di_test: Pass, Slow # Issue 22896
diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart
index 1b1c268..9fc946a 100644
--- a/pkg/smith/lib/configuration.dart
+++ b/pkg/smith/lib/configuration.dart
@@ -8,7 +8,7 @@
 // - "windows" -> "win".
 // - "macos" -> "mac".
 // - toString() on enum classes is just name.
-// - builderTag defaults to empty string, not null.
+// - builderTag and babel default to empty string, not null.
 // Need to migrate test.dart to not expect the above before it can use this.
 
 // READ ME! If you add a new field to this, make sure to add it to
@@ -247,6 +247,7 @@
 
     var configuration = Configuration(
         name, architecture, compiler, mode, runtime, system,
+        babel: stringOption("babel"),
         builderTag: stringOption("builder-tag"),
         vmOptions: stringListOption("vm-options"),
         dart2jsOptions: stringListOption("dart2js-options"),
@@ -260,6 +261,7 @@
         useAnalyzerCfe: boolOption("use-cfe"),
         useAnalyzerFastaParser: boolOption("analyzer-use-fasta-parser"),
         useBlobs: boolOption("use-blobs"),
+        useElf: boolOption("use-elf"),
         useHotReload: boolOption("hot-reload"),
         useHotReloadRollback: boolOption("hot-reload-rollback"),
         useSdk: boolOption("use-sdk"));
@@ -284,13 +286,15 @@
 
   final System system;
 
+  final String babel;
+
   final String builderTag;
 
   final List<String> vmOptions;
 
   final List<String> dart2jsOptions;
 
-  int timeout;
+  final int timeout;
 
   final bool enableAsserts;
 
@@ -313,6 +317,7 @@
 
   // TODO(rnystrom): What is this?
   final bool useBlobs;
+  final bool useElf;
 
   final bool useHotReload;
   final bool useHotReloadRollback;
@@ -321,7 +326,8 @@
 
   Configuration(this.name, this.architecture, this.compiler, this.mode,
       this.runtime, this.system,
-      {String builderTag,
+      {String babel,
+      String builderTag,
       List<String> vmOptions,
       List<String> dart2jsOptions,
       int timeout,
@@ -334,13 +340,15 @@
       bool useAnalyzerCfe,
       bool useAnalyzerFastaParser,
       bool useBlobs,
+      bool useElf,
       bool useHotReload,
       bool useHotReloadRollback,
       bool useSdk})
-      : builderTag = builderTag ?? "",
+      : babel = babel ?? "",
+        builderTag = builderTag ?? "",
         vmOptions = vmOptions ?? <String>[],
         dart2jsOptions = dart2jsOptions ?? <String>[],
-        timeout = timeout,
+        timeout = timeout ?? -1,
         enableAsserts = enableAsserts ?? false,
         isChecked = isChecked ?? false,
         isCsp = isCsp ?? false,
@@ -350,6 +358,7 @@
         useAnalyzerCfe = useAnalyzerCfe ?? false,
         useAnalyzerFastaParser = useAnalyzerFastaParser ?? false,
         useBlobs = useBlobs ?? false,
+        useElf = useElf ?? false,
         useHotReload = useHotReload ?? false,
         useHotReloadRollback = useHotReloadRollback ?? false,
         useSdk = useSdk ?? false;
@@ -362,6 +371,7 @@
       mode == other.mode &&
       runtime == other.runtime &&
       system == other.system &&
+      babel == other.babel &&
       builderTag == other.builderTag &&
       vmOptions.join(" & ") == other.vmOptions.join(" & ") &&
       dart2jsOptions.join(" & ") == other.dart2jsOptions.join(" & ") &&
@@ -375,6 +385,7 @@
       useAnalyzerCfe == other.useAnalyzerCfe &&
       useAnalyzerFastaParser == other.useAnalyzerFastaParser &&
       useBlobs == other.useBlobs &&
+      useElf == other.useElf &&
       useHotReload == other.useHotReload &&
       useHotReloadRollback == other.useHotReloadRollback &&
       useSdk == other.useSdk;
@@ -392,6 +403,7 @@
       mode.hashCode ^
       runtime.hashCode ^
       system.hashCode ^
+      babel.hashCode ^
       builderTag.hashCode ^
       vmOptions.join(" & ").hashCode ^
       dart2jsOptions.join(" & ").hashCode ^
@@ -406,6 +418,7 @@
         useAnalyzerCfe,
         useAnalyzerFastaParser,
         useBlobs,
+        useElf,
         useHotReload,
         useHotReloadRollback,
         useSdk
@@ -423,11 +436,13 @@
     fields.add("runtime: $runtime");
     fields.add("system: $system");
 
-    if (builderTag != "") fields.add("builder-tag: $builderTag");
-    if (vmOptions != "") fields.add("vm-options: [${vmOptions.join(", ")}]");
-    if (dart2jsOptions != "")
+    if (babel.isNotEmpty) fields.add("babel: $babel");
+    if (builderTag.isNotEmpty) fields.add("builder-tag: $builderTag");
+    if (vmOptions.isNotEmpty)
+      fields.add("vm-options: [${vmOptions.join(", ")}]");
+    if (dart2jsOptions.isNotEmpty)
       fields.add("dart2js-options: [${dart2jsOptions.join(", ")}]");
-    if (timeout != 0) fields.add("timeout: $timeout");
+    if (timeout > 0) fields.add("timeout: $timeout");
     if (enableAsserts) fields.add("enable-asserts");
     if (isChecked) fields.add("checked");
     if (isCsp) fields.add("csp");
@@ -458,20 +473,25 @@
     fields.add("runtime: $runtime ${other.runtime}");
     fields.add("system: $system ${other.system}");
 
-    if (builderTag != "" || other.builderTag != "") {
-      var tag = builderTag == "" ? "(none)" : builderTag;
-      var otherTag = other.builderTag == "" ? "(none)" : other.builderTag;
-      fields.add("builder-tag: $tag $otherTag");
+    if (babel.isNotEmpty || other.babel.isNotEmpty) {
+      var ours = babel == "" ? "(none)" : babel;
+      var theirs = other.babel == "" ? "(none)" : other.babel;
+      fields.add("babel: $ours $theirs");
     }
-    if (vmOptions != "" || other.vmOptions != "") {
-      var tag = "[${vmOptions.join(", ")}]";
-      var otherTag = "[${other.vmOptions.join(", ")}]";
-      fields.add("vm-options: $tag $otherTag");
+    if (builderTag.isNotEmpty || other.builderTag.isNotEmpty) {
+      var ours = builderTag == "" ? "(none)" : builderTag;
+      var theirs = other.builderTag == "" ? "(none)" : other.builderTag;
+      fields.add("builder-tag: $ours $theirs");
     }
-    if (dart2jsOptions != "" || other.dart2jsOptions != "") {
-      var tag = "[${dart2jsOptions.join(", ")}]";
-      var otherTag = "[${other.dart2jsOptions.join(", ")}]";
-      fields.add("dart2js-options: $tag $otherTag");
+    if (vmOptions.isNotEmpty || other.vmOptions.isNotEmpty) {
+      var ours = "[${vmOptions.join(", ")}]";
+      var theirs = "[${other.vmOptions.join(", ")}]";
+      fields.add("vm-options: $ours $theirs");
+    }
+    if (dart2jsOptions.isNotEmpty || other.dart2jsOptions.isNotEmpty) {
+      var ours = "[${dart2jsOptions.join(", ")}]";
+      var theirs = "[${other.dart2jsOptions.join(", ")}]";
+      fields.add("dart2js-options: $ours $theirs");
     }
     fields.add("timeout: $timeout ${other.timeout}");
     if (enableAsserts || other.enableAsserts) {
@@ -636,6 +656,9 @@
         return const [
           Runtime.none,
           Runtime.chrome,
+          Runtime.edge,
+          Runtime.firefox,
+          Runtime.safari,
         ];
 
       case Compiler.dart2analyzer:
diff --git a/pkg/status_file/test/data/standalone_2_vm.status b/pkg/status_file/test/data/standalone_2_vm.status
index fd09ed8..01c5b89 100644
--- a/pkg/status_file/test/data/standalone_2_vm.status
+++ b/pkg/status_file/test/data/standalone_2_vm.status
@@ -48,7 +48,6 @@
 io/test_extension_test: Skip # Platform.executable
 io/test_extension_fail_test: Skip # Platform.executable
 io/platform_test: Skip # Platform.executable
-io/code_collection_test: Skip # Platform.executable
 full_coverage_test: Skip # Platform.executable
 regress_26031_test: Skip # Platform.resolvedExecutable
 
diff --git a/pkg/status_file/test/data/vm.status b/pkg/status_file/test/data/vm.status
index 227c4ac..bf2543f 100644
--- a/pkg/status_file/test/data/vm.status
+++ b/pkg/status_file/test/data/vm.status
@@ -17,9 +17,6 @@
 cc/Fail1: Fail # These tests are expected to crash on all platforms.
 cc/Fail2: Fail # These tests are expected to crash on all platforms.
 
-cc/Dart2JSCompileAll: Fail, Crash # Issue 27369
-cc/Dart2JSCompilerStats: Fail, Crash # Issue 27369
-
 cc/Profiler_InliningIntervalBoundry: Skip # Differences in ia32, debug, release
 
 cc/Sleep: Skip # Flaky # Flaky on buildbot. Issue 5133 and 10409.
@@ -138,9 +135,6 @@
 dart/spawn_shutdown_test: Skip  # VM Shutdown test
 dart/hello_fuchsia_test: SkipByDesign # This is a test for fuchsia OS
 
-[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $builder_tag == asan ]
-cc/Dart2JSCompileAll: SkipSlow  # Timeout.
-
 [ $builder_tag == asan ]
 cc/CodeImmutability: Fail,OK # Address Sanitizer turns a crash into a failure.
 cc/IsolateReload_DanglingGetter_Class: Fail # Issue 28349
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 619c943..be1e4ee 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -146,7 +146,10 @@
       if (options.bytecode && errors.isEmpty) {
         await runWithFrontEndCompilerContext(script, options, component, () {
           // TODO(alexmarkov): pass environment defines
-          generateBytecode(component);
+          // TODO(alexmarkov): disable source positions and local variables
+          // in VM PRODUCT mode.
+          generateBytecode(component,
+              emitSourcePositions: true, emitLocalVarInfo: true);
         });
       }
 
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
index cfb843e..387db94 100644
--- a/pkg/vm/lib/bytecode/assembler.dart
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -4,12 +4,11 @@
 
 library vm.bytecode.assembler;
 
-import 'dart:typed_data';
-
 import 'package:kernel/ast.dart' show TreeNode;
 
 import 'dbc.dart';
 import 'exceptions.dart' show ExceptionsTable;
+import 'local_variable_table.dart' show LocalVariableTable;
 import 'source_positions.dart' show SourcePositions;
 
 class Label {
@@ -26,8 +25,8 @@
       if (offset <= jumpOffset && !allowsBackwardJumps) {
         throw 'Backward jump to this label is not allowed';
       }
-      // Jump instruction takes an offset in DBC words.
-      return (offset - jumpOffset) >> BytecodeAssembler.kLog2BytesPerBytecode;
+      // Jump instruction takes a relative offset.
+      return offset - jumpOffset;
     }
     _jumps.add(jumpOffset);
     return 0;
@@ -43,32 +42,31 @@
 }
 
 class BytecodeAssembler {
-  static const int kBitsPerInt = 64;
-  static const int kLog2BytesPerBytecode = 2;
+  static const int kByteMask = 0xFF;
+  static const int kUint32Mask = 0xFFFFFFFF;
+  static const int kMinInt8 = -0x80;
+  static const int kMaxInt8 = 0x7F;
+  static const int kMinInt24 = -0x800000;
+  static const int kMaxInt24 = 0x7FFFFF;
+  static const int kMinInt32 = -0x80000000;
+  static const int kMaxInt32 = 0x7FFFFFFF;
 
   // TODO(alexmarkov): figure out more efficient storage for generated bytecode.
   final List<int> bytecode = new List<int>();
-  final Uint32List _encodeBufferIn;
-  final Uint8List _encodeBufferOut;
   final ExceptionsTable exceptionsTable = new ExceptionsTable();
+  final LocalVariableTable localVariableTable = new LocalVariableTable();
   final SourcePositions sourcePositions = new SourcePositions();
   bool isUnreachable = false;
   int currentSourcePosition = TreeNode.noOffset;
 
-  BytecodeAssembler._(this._encodeBufferIn, this._encodeBufferOut);
-
-  factory BytecodeAssembler() {
-    final buf = new Uint32List(1);
-    return new BytecodeAssembler._(buf, new Uint8List.view(buf.buffer));
-  }
+  BytecodeAssembler();
 
   int get offset => bytecode.length;
-  int get offsetInWords => bytecode.length >> kLog2BytesPerBytecode;
 
   void bind(Label label) {
     final List<int> jumps = label.bind(offset);
     for (int jumpOffset in jumps) {
-      patchJump(jumpOffset, label.jumpOperand(jumpOffset));
+      _patchJump(jumpOffset, label.jumpOperand(jumpOffset));
     }
     if (jumps.isNotEmpty || label.allowsBackwardJumps) {
       isUnreachable = false;
@@ -77,360 +75,454 @@
 
   void emitSourcePosition() {
     if (currentSourcePosition != TreeNode.noOffset && !isUnreachable) {
-      sourcePositions.add(offsetInWords, currentSourcePosition);
+      sourcePositions.add(offset, currentSourcePosition);
     }
   }
 
-  void emitWord(int word) {
+  void _emitByte(int abyte) {
+    assert(_isUint8(abyte));
+    bytecode.add(abyte);
+  }
+
+  void _emitBytes2(int b0, int b1) {
+    assert(_isUint8(b0) && _isUint8(b1));
+    bytecode.add(b0);
+    bytecode.add(b1);
+  }
+
+  void _emitBytes3(int b0, int b1, int b2) {
+    assert(_isUint8(b0) && _isUint8(b1) && _isUint8(b2));
+    bytecode.add(b0);
+    bytecode.add(b1);
+    bytecode.add(b2);
+  }
+
+  void _emitBytes4(int b0, int b1, int b2, int b3) {
+    assert(_isUint8(b0) && _isUint8(b1) && _isUint8(b2) && _isUint8(b3));
+    bytecode.add(b0);
+    bytecode.add(b1);
+    bytecode.add(b2);
+    bytecode.add(b3);
+  }
+
+  void _emitBytes5(int b0, int b1, int b2, int b3, int b4) {
+    assert(_isUint8(b0) &&
+        _isUint8(b1) &&
+        _isUint8(b2) &&
+        _isUint8(b3) &&
+        _isUint8(b4));
+    bytecode.add(b0);
+    bytecode.add(b1);
+    bytecode.add(b2);
+    bytecode.add(b3);
+    bytecode.add(b4);
+  }
+
+  void _emitBytes6(int b0, int b1, int b2, int b3, int b4, int b5) {
+    assert(_isUint8(b0) &&
+        _isUint8(b1) &&
+        _isUint8(b2) &&
+        _isUint8(b3) &&
+        _isUint8(b4) &&
+        _isUint8(b5));
+    bytecode.add(b0);
+    bytecode.add(b1);
+    bytecode.add(b2);
+    bytecode.add(b3);
+    bytecode.add(b4);
+    bytecode.add(b5);
+  }
+
+  int _byteAt(int pos) {
+    return bytecode[pos];
+  }
+
+  void _setByteAt(int pos, int value) {
+    assert(_isUint8(value));
+    bytecode[pos] = value;
+  }
+
+  int _byte0(int v) => v & kByteMask;
+  int _byte1(int v) => (v >> 8) & kByteMask;
+  int _byte2(int v) => (v >> 16) & kByteMask;
+  int _byte3(int v) => (v >> 24) & kByteMask;
+
+  bool _isInt8(int v) => (kMinInt8 <= v) && (v <= kMaxInt8);
+  bool _isInt24(int v) => (kMinInt24 <= v) && (v <= kMaxInt24);
+  bool _isInt32(int v) => (kMinInt32 <= v) && (v <= kMaxInt32);
+  bool _isUint8(int v) => (v & kByteMask) == v;
+  bool _isUint32(int v) => (v & kUint32Mask) == v;
+
+  void _emitInstruction0(Opcode opcode) {
     if (isUnreachable) {
       return;
     }
-    _encodeBufferIn[0] = word; // TODO(alexmarkov): Which endianness to use?
-    bytecode.addAll(_encodeBufferOut);
+    _emitByte(opcode.index);
   }
 
-  int _getOpcodeAt(int pos) {
-    return bytecode[pos]; // TODO(alexmarkov): Take endianness into account.
-  }
-
-  void _setWord(int pos, int word) {
-    _encodeBufferIn[0] = word; // TODO(alexmarkov): Which endianness to use?
-    bytecode.setRange(pos, pos + _encodeBufferOut.length, _encodeBufferOut);
-  }
-
-  int _unsigned(int v, int bits) {
-    assert(bits < kBitsPerInt);
-    final int mask = (1 << bits) - 1;
-    if ((v & mask) != v) {
-      throw 'Value $v is out of unsigned $bits-bit range';
+  void _emitInstructionA(Opcode opcode, int ra) {
+    if (isUnreachable) {
+      return;
     }
-    return v;
+    _emitBytes2(opcode.index, ra);
   }
 
-  int _signed(int v, int bits) {
-    assert(bits < kBitsPerInt);
-    final int shift = kBitsPerInt - bits;
-    if (((v << shift) >> shift) != v) {
-      throw 'Value $v is out of signed $bits-bit range';
+  void _emitInstructionD(Opcode opcode, int rd) {
+    if (isUnreachable) {
+      return;
     }
-    final int mask = (1 << bits) - 1;
-    return v & mask;
+    if (_isUint8(rd)) {
+      _emitBytes2(opcode.index, rd);
+    } else {
+      assert(_isUint32(rd));
+      _emitBytes5(opcode.index + kWideModifier, _byte0(rd), _byte1(rd),
+          _byte2(rd), _byte3(rd));
+    }
   }
 
-  int _uint8(int v) => _unsigned(v, 8);
-  int _uint16(int v) => _unsigned(v, 16);
+  void _emitInstructionX(Opcode opcode, int rx) {
+    if (isUnreachable) {
+      return;
+    }
+    if (_isInt8(rx)) {
+      _emitBytes2(opcode.index, rx & kByteMask);
+    } else {
+      assert(_isInt32(rx));
+      _emitBytes5(opcode.index + kWideModifier, _byte0(rx), _byte1(rx),
+          _byte2(rx), _byte3(rx));
+    }
+  }
 
-//  int _int8(int v) => _signed(v, 8);
-  int _int16(int v) => _signed(v, 16);
-  int _int24(int v) => _signed(v, 24);
+  void _emitInstructionAE(Opcode opcode, int ra, int re) {
+    if (isUnreachable) {
+      return;
+    }
+    if (_isUint8(re)) {
+      _emitBytes3(opcode.index, ra, re);
+    } else {
+      assert(_isUint32(re));
+      _emitBytes6(opcode.index + kWideModifier, ra, _byte0(re), _byte1(re),
+          _byte2(re), _byte3(re));
+    }
+  }
 
-  int _encode0(Opcode opcode) => _uint8(opcode.index);
+  void _emitInstructionAY(Opcode opcode, int ra, int ry) {
+    if (isUnreachable) {
+      return;
+    }
+    if (_isInt8(ry)) {
+      _emitBytes3(opcode.index, ra, ry & kByteMask);
+    } else {
+      assert(_isInt32(ry));
+      _emitBytes6(opcode.index + kWideModifier, ra, _byte0(ry), _byte1(ry),
+          _byte2(ry), _byte3(ry));
+    }
+  }
 
-  int _encodeA(Opcode opcode, int ra) =>
-      _uint8(opcode.index) | (_uint8(ra) << 8);
+  void _emitInstructionDF(Opcode opcode, int rd, int rf) {
+    if (isUnreachable) {
+      return;
+    }
+    if (_isUint8(rd)) {
+      _emitBytes3(opcode.index, rd, rf);
+    } else {
+      assert(_isUint32(rd));
+      _emitBytes6(opcode.index + kWideModifier, _byte0(rd), _byte1(rd),
+          _byte2(rd), _byte3(rd), rf);
+    }
+  }
 
-  int _encodeAD(Opcode opcode, int ra, int rd) =>
-      _uint8(opcode.index) | (_uint8(ra) << 8) | (_uint16(rd) << 16);
+  void _emitInstructionABC(Opcode opcode, int ra, int rb, int rc) {
+    if (isUnreachable) {
+      return;
+    }
+    _emitBytes4(opcode.index, ra, rb, rc);
+  }
 
-  int _encodeAX(Opcode opcode, int ra, int rx) =>
-      _uint8(opcode.index) | (_uint8(ra) << 8) | (_int16(rx) << 16);
-
-  int _encodeD(Opcode opcode, int rd) =>
-      _uint8(opcode.index) | (_uint16(rd) << 16);
-
-  int _encodeX(Opcode opcode, int rx) =>
-      _uint8(opcode.index) | (_int16(rx) << 16);
-
-  int _encodeABC(Opcode opcode, int ra, int rb, int rc) =>
-      _uint8(opcode.index) |
-      (_uint8(ra) << 8) |
-      (_uint8(rb) << 16) |
-      (_uint8(rc) << 24);
-
-// TODO(alexmarkov) This format is currently unused. Restore it if needed, or
-// remove it once bytecode instruction set is finalized.
-//
-//  int _encodeABY(Opcode opcode, int ra, int rb, int ry) =>
-//      _uint8(opcode.index) |
-//      (_uint8(ra) << 8) |
-//      (_uint8(rb) << 16) |
-//      (_int8(ry) << 24);
-
-  int _encodeT(Opcode opcode, int rt) =>
-      _uint8(opcode.index) | (_int24(rt) << 8);
-
-  void emitBytecode0(Opcode opcode) {
+  void emitSpecializedBytecode(Opcode opcode) {
     assert(BytecodeFormats[opcode].encoding == Encoding.k0);
     emitSourcePosition();
-    emitWord(_encode0(opcode));
+    _emitInstruction0(opcode);
   }
 
-  void _emitJumpBytecode(Opcode opcode, Label label) {
+  void _emitJumpInstruction(Opcode opcode, Label label) {
     assert(isJump(opcode));
-    if (!isUnreachable) {
-      // Do not use label if not generating instruction.
-      emitWord(_encodeT(opcode, label.jumpOperand(offset)));
+    if (isUnreachable) {
+      return;
     }
+    final int target = label.jumpOperand(offset);
+    // Use compact representation only for backwards jumps.
+    // TODO(alexmarkov): generate compact forward jumps as well.
+    if (label.isBound && _isInt8(target)) {
+      _emitBytes2(opcode.index, target & kByteMask);
+    } else {
+      assert(_isInt24(target));
+      _emitBytes4(opcode.index + kWideModifier, _byte0(target), _byte1(target),
+          _byte2(target));
+    }
+  }
+
+  void _patchJump(int pos, int rt) {
+    final Opcode opcode = Opcode.values[_byteAt(pos) - kWideModifier];
+    assert(hasWideVariant(opcode));
+    assert(isJump(opcode));
+    assert(_isInt24(rt));
+    _setByteAt(pos + 1, _byte0(rt));
+    _setByteAt(pos + 2, _byte1(rt));
+    _setByteAt(pos + 3, _byte2(rt));
   }
 
   void emitTrap() {
-    emitWord(_encode0(Opcode.kTrap));
+    _emitInstruction0(Opcode.kTrap);
     isUnreachable = true;
   }
 
   void emitDrop1() {
-    emitWord(_encode0(Opcode.kDrop1));
+    _emitInstruction0(Opcode.kDrop1);
   }
 
   void emitJump(Label label) {
-    _emitJumpBytecode(Opcode.kJump, label);
+    emitSourcePosition();
+    _emitJumpInstruction(Opcode.kJump, label);
     isUnreachable = true;
   }
 
   void emitJumpIfNoAsserts(Label label) {
-    _emitJumpBytecode(Opcode.kJumpIfNoAsserts, label);
+    _emitJumpInstruction(Opcode.kJumpIfNoAsserts, label);
   }
 
   void emitJumpIfNotZeroTypeArgs(Label label) {
-    _emitJumpBytecode(Opcode.kJumpIfNotZeroTypeArgs, label);
+    _emitJumpInstruction(Opcode.kJumpIfNotZeroTypeArgs, label);
   }
 
   void emitJumpIfEqStrict(Label label) {
-    _emitJumpBytecode(Opcode.kJumpIfEqStrict, label);
+    _emitJumpInstruction(Opcode.kJumpIfEqStrict, label);
   }
 
   void emitJumpIfNeStrict(Label label) {
-    _emitJumpBytecode(Opcode.kJumpIfNeStrict, label);
+    _emitJumpInstruction(Opcode.kJumpIfNeStrict, label);
   }
 
   void emitJumpIfTrue(Label label) {
-    _emitJumpBytecode(Opcode.kJumpIfTrue, label);
+    _emitJumpInstruction(Opcode.kJumpIfTrue, label);
   }
 
   void emitJumpIfFalse(Label label) {
-    _emitJumpBytecode(Opcode.kJumpIfFalse, label);
+    _emitJumpInstruction(Opcode.kJumpIfFalse, label);
   }
 
   void emitJumpIfNull(Label label) {
-    _emitJumpBytecode(Opcode.kJumpIfNull, label);
+    _emitJumpInstruction(Opcode.kJumpIfNull, label);
   }
 
   void emitJumpIfNotNull(Label label) {
-    _emitJumpBytecode(Opcode.kJumpIfNotNull, label);
-  }
-
-  void patchJump(int pos, int rt) {
-    final Opcode opcode = Opcode.values[_getOpcodeAt(pos)];
-    assert(isJump(opcode));
-    _setWord(pos, _encodeT(opcode, rt));
+    _emitJumpInstruction(Opcode.kJumpIfNotNull, label);
   }
 
   void emitReturnTOS() {
-    emitWord(_encode0(Opcode.kReturnTOS));
+    emitSourcePosition();
+    _emitInstruction0(Opcode.kReturnTOS);
     isUnreachable = true;
   }
 
   void emitPush(int rx) {
-    emitWord(_encodeX(Opcode.kPush, rx));
+    _emitInstructionX(Opcode.kPush, rx);
   }
 
-  void emitLoadConstant(int ra, int rd) {
-    emitWord(_encodeAD(Opcode.kLoadConstant, ra, rd));
+  void emitLoadConstant(int ra, int re) {
+    _emitInstructionAE(Opcode.kLoadConstant, ra, re);
   }
 
   void emitPushConstant(int rd) {
-    emitWord(_encodeD(Opcode.kPushConstant, rd));
+    _emitInstructionD(Opcode.kPushConstant, rd);
   }
 
   void emitPushNull() {
-    emitWord(_encode0(Opcode.kPushNull));
+    _emitInstruction0(Opcode.kPushNull);
   }
 
   void emitPushTrue() {
-    emitWord(_encode0(Opcode.kPushTrue));
+    _emitInstruction0(Opcode.kPushTrue);
   }
 
   void emitPushFalse() {
-    emitWord(_encode0(Opcode.kPushFalse));
+    _emitInstruction0(Opcode.kPushFalse);
   }
 
   void emitPushInt(int rx) {
-    emitWord(_encodeX(Opcode.kPushInt, rx));
+    _emitInstructionX(Opcode.kPushInt, rx);
   }
 
   void emitStoreLocal(int rx) {
-    emitWord(_encodeX(Opcode.kStoreLocal, rx));
+    emitSourcePosition();
+    _emitInstructionX(Opcode.kStoreLocal, rx);
   }
 
   void emitPopLocal(int rx) {
-    emitWord(_encodeX(Opcode.kPopLocal, rx));
+    emitSourcePosition();
+    _emitInstructionX(Opcode.kPopLocal, rx);
   }
 
-  void emitIndirectStaticCall(int ra, int rd) {
+  void emitDirectCall(int rd, int rf) {
     emitSourcePosition();
-    emitWord(_encodeAD(Opcode.kIndirectStaticCall, ra, rd));
+    _emitInstructionDF(Opcode.kDirectCall, rd, rf);
   }
 
-  void emitDirectCall(int ra, int rd) {
+  void emitInterfaceCall(int rd, int rf) {
     emitSourcePosition();
-    emitWord(_encodeAD(Opcode.kDirectCall, ra, rd));
+    _emitInstructionDF(Opcode.kInterfaceCall, rd, rf);
   }
 
-  void emitInterfaceCall(int ra, int rd) {
+  void emitUncheckedInterfaceCall(int rd, int rf) {
     emitSourcePosition();
-    emitWord(_encodeAD(Opcode.kInterfaceCall, ra, rd));
+    _emitInstructionDF(Opcode.kUncheckedInterfaceCall, rd, rf);
   }
 
-  void emitUncheckedInterfaceCall(int ra, int rd) {
+  void emitDynamicCall(int rd, int rf) {
     emitSourcePosition();
-    emitWord(_encodeAD(Opcode.kUncheckedInterfaceCall, ra, rd));
-  }
-
-  void emitDynamicCall(int ra, int rd) {
-    emitSourcePosition();
-    emitWord(_encodeAD(Opcode.kDynamicCall, ra, rd));
+    _emitInstructionDF(Opcode.kDynamicCall, rd, rf);
   }
 
   void emitNativeCall(int rd) {
     emitSourcePosition();
-    emitWord(_encodeD(Opcode.kNativeCall, rd));
+    _emitInstructionD(Opcode.kNativeCall, rd);
   }
 
   void emitStoreStaticTOS(int rd) {
     emitSourcePosition();
-    emitWord(_encodeD(Opcode.kStoreStaticTOS, rd));
+    _emitInstructionD(Opcode.kStoreStaticTOS, rd);
   }
 
   void emitPushStatic(int rd) {
-    emitWord(_encodeD(Opcode.kPushStatic, rd));
+    _emitInstructionD(Opcode.kPushStatic, rd);
   }
 
   void emitCreateArrayTOS() {
-    emitWord(_encode0(Opcode.kCreateArrayTOS));
+    _emitInstruction0(Opcode.kCreateArrayTOS);
   }
 
   void emitAllocate(int rd) {
     emitSourcePosition();
-    emitWord(_encodeD(Opcode.kAllocate, rd));
+    _emitInstructionD(Opcode.kAllocate, rd);
   }
 
   void emitAllocateT() {
     emitSourcePosition();
-    emitWord(_encode0(Opcode.kAllocateT));
+    _emitInstruction0(Opcode.kAllocateT);
   }
 
   void emitStoreIndexedTOS() {
-    emitWord(_encode0(Opcode.kStoreIndexedTOS));
+    _emitInstruction0(Opcode.kStoreIndexedTOS);
   }
 
   void emitStoreFieldTOS(int rd) {
     emitSourcePosition();
-    emitWord(_encodeD(Opcode.kStoreFieldTOS, rd));
+    _emitInstructionD(Opcode.kStoreFieldTOS, rd);
   }
 
   void emitStoreContextParent() {
-    emitWord(_encode0(Opcode.kStoreContextParent));
+    _emitInstruction0(Opcode.kStoreContextParent);
   }
 
-  void emitStoreContextVar(int ra, int rd) {
-    emitWord(_encodeAD(Opcode.kStoreContextVar, ra, rd));
+  void emitStoreContextVar(int ra, int re) {
+    _emitInstructionAE(Opcode.kStoreContextVar, ra, re);
   }
 
   void emitLoadFieldTOS(int rd) {
-    emitWord(_encodeD(Opcode.kLoadFieldTOS, rd));
+    _emitInstructionD(Opcode.kLoadFieldTOS, rd);
   }
 
   void emitLoadTypeArgumentsField(int rd) {
-    emitWord(_encodeD(Opcode.kLoadTypeArgumentsField, rd));
+    _emitInstructionD(Opcode.kLoadTypeArgumentsField, rd);
   }
 
   void emitLoadContextParent() {
-    emitWord(_encode0(Opcode.kLoadContextParent));
+    _emitInstruction0(Opcode.kLoadContextParent);
   }
 
-  void emitLoadContextVar(int ra, int rd) {
-    emitWord(_encodeAD(Opcode.kLoadContextVar, ra, rd));
+  void emitLoadContextVar(int ra, int re) {
+    _emitInstructionAE(Opcode.kLoadContextVar, ra, re);
   }
 
   void emitBooleanNegateTOS() {
-    emitWord(_encode0(Opcode.kBooleanNegateTOS));
+    _emitInstruction0(Opcode.kBooleanNegateTOS);
   }
 
   void emitThrow(int ra) {
     emitSourcePosition();
-    emitWord(_encodeA(Opcode.kThrow, ra));
+    _emitInstructionA(Opcode.kThrow, ra);
     isUnreachable = true;
   }
 
   void emitEntry(int rd) {
-    emitWord(_encodeD(Opcode.kEntry, rd));
+    _emitInstructionD(Opcode.kEntry, rd);
   }
 
   void emitFrame(int rd) {
-    emitWord(_encodeD(Opcode.kFrame, rd));
+    _emitInstructionD(Opcode.kFrame, rd);
   }
 
   void emitSetFrame(int ra) {
-    emitWord(_encodeA(Opcode.kSetFrame, ra));
+    _emitInstructionA(Opcode.kSetFrame, ra);
   }
 
-  void emitAllocateContext(int ra, int rd) {
-    emitWord(_encodeAD(Opcode.kAllocateContext, ra, rd));
+  void emitAllocateContext(int ra, int re) {
+    _emitInstructionAE(Opcode.kAllocateContext, ra, re);
   }
 
-  void emitCloneContext(int ra, int rd) {
-    emitWord(_encodeAD(Opcode.kCloneContext, ra, rd));
+  void emitCloneContext(int ra, int re) {
+    _emitInstructionAE(Opcode.kCloneContext, ra, re);
   }
 
-  void emitMoveSpecial(SpecialIndex ra, int rx) {
-    emitWord(_encodeAX(Opcode.kMoveSpecial, ra.index, rx));
+  void emitMoveSpecial(SpecialIndex ra, int ry) {
+    _emitInstructionAY(Opcode.kMoveSpecial, ra.index, ry);
   }
 
   void emitInstantiateType(int rd) {
     emitSourcePosition();
-    emitWord(_encodeD(Opcode.kInstantiateType, rd));
+    _emitInstructionD(Opcode.kInstantiateType, rd);
   }
 
-  void emitInstantiateTypeArgumentsTOS(int ra, int rd) {
+  void emitInstantiateTypeArgumentsTOS(int ra, int re) {
     emitSourcePosition();
-    emitWord(_encodeAD(Opcode.kInstantiateTypeArgumentsTOS, ra, rd));
+    _emitInstructionAE(Opcode.kInstantiateTypeArgumentsTOS, ra, re);
   }
 
-  void emitAssertAssignable(int ra, int rd) {
+  void emitAssertAssignable(int ra, int re) {
     emitSourcePosition();
-    emitWord(_encodeAD(Opcode.kAssertAssignable, ra, rd));
+    _emitInstructionAE(Opcode.kAssertAssignable, ra, re);
   }
 
   void emitAssertSubtype() {
     emitSourcePosition();
-    emitWord(_encode0(Opcode.kAssertSubtype));
+    _emitInstruction0(Opcode.kAssertSubtype);
   }
 
   void emitAssertBoolean(int ra) {
     emitSourcePosition();
-    emitWord(_encodeA(Opcode.kAssertBoolean, ra));
+    _emitInstructionA(Opcode.kAssertBoolean, ra);
   }
 
   void emitCheckStack(int ra) {
     emitSourcePosition();
-    emitWord(_encodeA(Opcode.kCheckStack, ra));
+    _emitInstructionA(Opcode.kCheckStack, ra);
   }
 
-  void emitCheckFunctionTypeArgs(int ra, int rd) {
+  void emitCheckFunctionTypeArgs(int ra, int re) {
     emitSourcePosition();
-    emitWord(_encodeAD(Opcode.kCheckFunctionTypeArgs, ra, rd));
+    _emitInstructionAE(Opcode.kCheckFunctionTypeArgs, ra, re);
   }
 
-  void emitEntryFixed(int ra, int rd) {
-    emitWord(_encodeAD(Opcode.kEntryFixed, ra, rd));
+  void emitEntryFixed(int ra, int re) {
+    _emitInstructionAE(Opcode.kEntryFixed, ra, re);
   }
 
   void emitEntryOptional(int ra, int rb, int rc) {
-    emitWord(_encodeABC(Opcode.kEntryOptional, ra, rb, rc));
+    _emitInstructionABC(Opcode.kEntryOptional, ra, rb, rc);
   }
 
   void emitAllocateClosure(int rd) {
     emitSourcePosition();
-    emitWord(_encodeD(Opcode.kAllocateClosure, rd));
+    _emitInstructionD(Opcode.kAllocateClosure, rd);
   }
 }
diff --git a/pkg/vm/lib/bytecode/bytecode_serialization.dart b/pkg/vm/lib/bytecode/bytecode_serialization.dart
index 4845307..db9fa71 100644
--- a/pkg/vm/lib/bytecode/bytecode_serialization.dart
+++ b/pkg/vm/lib/bytecode/bytecode_serialization.dart
@@ -386,15 +386,42 @@
   return buf.getFloat64(0, Endian.little);
 }
 
-class NamedEntryStatistics {
-  final String name;
-  int size = 0;
-  int count = 0;
+class PackedUInt30DeltaEncoder {
+  int _last = 0;
 
-  NamedEntryStatistics(this.name);
+  void write(BufferedWriter write, int value) {
+    write.writePackedUInt30(value - _last);
+    _last = value;
+  }
+}
 
-  String toString() => "${name.padRight(40)}:    ${size.toString().padLeft(10)}"
-      "  (count: ${count.toString().padLeft(8)})";
+class PackedUInt30DeltaDecoder {
+  int _last = 0;
+
+  int read(BufferedReader reader) {
+    int value = reader.readPackedUInt30() + _last;
+    _last = value;
+    return value;
+  }
+}
+
+class SLEB128DeltaEncoder {
+  int _last = 0;
+
+  void write(BufferedWriter writer, int value) {
+    writer.writeSLEB128(value - _last);
+    _last = value;
+  }
+}
+
+class SLEB128DeltaDecoder {
+  int _last = 0;
+
+  int read(BufferedReader reader) {
+    int value = reader.readSLEB128() + _last;
+    _last = value;
+    return value;
+  }
 }
 
 class LinkWriter {
@@ -428,6 +455,17 @@
   }
 }
 
+class NamedEntryStatistics {
+  final String name;
+  int size = 0;
+  int count = 0;
+
+  NamedEntryStatistics(this.name);
+
+  String toString() => "${name.padRight(40)}:    ${size.toString().padLeft(10)}"
+      "  (count: ${count.toString().padLeft(8)})";
+}
+
 class BytecodeSizeStatistics {
   static int componentSize = 0;
   static int objectTableSize = 0;
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index 730ee69..351a3e7 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -10,99 +10,299 @@
 /// Before bumping current bytecode version format, make sure that
 /// all users have switched to a VM which is able to consume new
 /// version of bytecode.
-const int currentBytecodeFormatVersion = 6;
+const int currentBytecodeFormatVersion = 9;
 
 /// Version of experimental / bleeding edge bytecode format.
 /// Produced by bytecode generator when --use-future-bytecode-format
 /// option is enabled.
 const int futureBytecodeFormatVersion = currentBytecodeFormatVersion + 1;
 
-/// Alignment of bytecode instructions.
-const int bytecodeInstructionsAlignment = 4;
-
 enum Opcode {
+  // Old instructions, used before bytecode v7.
+  // TODO(alexmarkov): remove
+
+  kTrap_Old,
+
+  // Prologue and stack management.
+  kEntry_Old,
+  kEntryFixed_Old,
+  kEntryOptional_Old,
+  kLoadConstant_Old,
+  kFrame_Old,
+  kCheckFunctionTypeArgs_Old,
+  kCheckStack_Old,
+
+  // Object allocation.
+  kAllocate_Old,
+  kAllocateT_Old,
+  kCreateArrayTOS_Old,
+
+  // Context allocation and access.
+  kAllocateContext_Old,
+  kCloneContext_Old,
+  kLoadContextParent_Old,
+  kStoreContextParent_Old,
+  kLoadContextVar_Old,
+  kStoreContextVar_Old,
+
+  // Constants.
+  kPushConstant_Old,
+  kPushNull_Old,
+  kPushTrue_Old,
+  kPushFalse_Old,
+  kPushInt_Old,
+
+  // Locals and expression stack.
+  kDrop1_Old,
+  kPush_Old,
+  kPopLocal_Old,
+  kStoreLocal_Old,
+
+  // Instance fields and arrays.
+  kLoadFieldTOS_Old,
+  kStoreFieldTOS_Old,
+  kStoreIndexedTOS_Old,
+
+  // Static fields.
+  kPushStatic_Old,
+  kStoreStaticTOS_Old,
+
+  // Jumps.
+  kJump_Old,
+  kJumpIfNoAsserts_Old,
+  kJumpIfNotZeroTypeArgs_Old,
+  kJumpIfEqStrict_Old,
+  kJumpIfNeStrict_Old,
+  kJumpIfTrue_Old,
+  kJumpIfFalse_Old,
+  kJumpIfNull_Old,
+  kJumpIfNotNull_Old,
+
+  // Calls.
+  kUnused00_Old,
+  kInterfaceCall_Old,
+  kDynamicCall_Old,
+  kNativeCall_Old,
+  kReturnTOS_Old,
+
+  // Types and type checks.
+  kAssertAssignable_Old,
+  kAssertBoolean_Old,
+  kAssertSubtype_Old,
+  kLoadTypeArgumentsField_Old,
+  kInstantiateType_Old,
+  kInstantiateTypeArgumentsTOS_Old,
+
+  // Exception handling.
+  kThrow_Old,
+  kMoveSpecial_Old,
+  kSetFrame_Old,
+
+  // Bool operations.
+  kBooleanNegateTOS_Old,
+
+  // Null operations.
+  kEqualsNull_Old,
+
+  // Int operations.
+  kNegateInt_Old,
+  kAddInt_Old,
+  kSubInt_Old,
+  kMulInt_Old,
+  kTruncDivInt_Old,
+  kModInt_Old,
+  kBitAndInt_Old,
+  kBitOrInt_Old,
+  kBitXorInt_Old,
+  kShlInt_Old,
+  kShrInt_Old,
+  kCompareIntEq_Old,
+  kCompareIntGt_Old,
+  kCompareIntLt_Old,
+  kCompareIntGe_Old,
+  kCompareIntLe_Old,
+
+  kDirectCall_Old,
+
+  kAllocateClosure_Old,
+
+  kUncheckedInterfaceCall_Old,
+
+  // Double operations.
+  kNegateDouble_Old,
+  kAddDouble_Old,
+  kSubDouble_Old,
+  kMulDouble_Old,
+  kDivDouble_Old,
+  kCompareDoubleEq_Old,
+  kCompareDoubleGt_Old,
+  kCompareDoubleLt_Old,
+  kCompareDoubleGe_Old,
+  kCompareDoubleLe_Old,
+
+  // Bytecode instructions since bytecode format v7:
+
   kTrap,
 
   // Prologue and stack management.
   kEntry,
+  kEntry_Wide,
   kEntryFixed,
+  kEntryFixed_Wide,
   kEntryOptional,
+  kUnused00, // Reserved for EntryNoLocals.
   kLoadConstant,
+  kLoadConstant_Wide,
   kFrame,
+  kFrame_Wide,
   kCheckFunctionTypeArgs,
+  kCheckFunctionTypeArgs_Wide,
   kCheckStack,
+  kUnused01,
+  kUnused02, // Reserved for CheckParameterTypes
+  kUnused03, // Reserved for CheckParameterTypes_Wide
 
   // Object allocation.
   kAllocate,
+  kAllocate_Wide,
   kAllocateT,
   kCreateArrayTOS,
+  kAllocateClosure,
+  kAllocateClosure_Wide,
 
   // Context allocation and access.
   kAllocateContext,
+  kAllocateContext_Wide,
   kCloneContext,
+  kCloneContext_Wide,
   kLoadContextParent,
   kStoreContextParent,
   kLoadContextVar,
+  kLoadContextVar_Wide,
+  kUnused04, // Reserved for LoadContextVar0
+  kUnused05,
   kStoreContextVar,
+  kStoreContextVar_Wide,
 
   // Constants.
   kPushConstant,
-  kPushNull,
+  kPushConstant_Wide,
+  kUnused06, // Reserved for PushConstant0
+  kUnused07,
   kPushTrue,
   kPushFalse,
   kPushInt,
+  kPushInt_Wide,
+  kUnused08, // Reserved for PushInt0
+  kUnused09, // Reserved for PushInt1
+  kUnused10, // Reserved for PushInt2
+  kUnused11,
+  kPushNull,
 
   // Locals and expression stack.
   kDrop1,
   kPush,
+  kPush_Wide,
+  kUnused12, // Reserved for PushLocal0
+  kUnused13, // Reserved for PushLocal1
+  kUnused14, // Reserved for PushLocal2
+  kUnused15, // Reserved for PushLocal3
+  kUnused16, // Reserved for PushParamLast0
+  kUnused17, // Reserved for PushParamLast1
   kPopLocal,
+  kPopLocal_Wide,
+  kUnused18, // Reserved for PopLocal0
+  kUnused19,
   kStoreLocal,
+  kStoreLocal_Wide,
 
   // Instance fields and arrays.
   kLoadFieldTOS,
+  kLoadFieldTOS_Wide,
   kStoreFieldTOS,
+  kStoreFieldTOS_Wide,
   kStoreIndexedTOS,
+  kUnused20,
 
   // Static fields.
   kPushStatic,
+  kPushStatic_Wide,
   kStoreStaticTOS,
+  kStoreStaticTOS_Wide,
 
   // Jumps.
   kJump,
+  kJump_Wide,
   kJumpIfNoAsserts,
+  kJumpIfNoAsserts_Wide,
   kJumpIfNotZeroTypeArgs,
+  kJumpIfNotZeroTypeArgs_Wide,
   kJumpIfEqStrict,
+  kJumpIfEqStrict_Wide,
   kJumpIfNeStrict,
+  kJumpIfNeStrict_Wide,
   kJumpIfTrue,
+  kJumpIfTrue_Wide,
   kJumpIfFalse,
+  kJumpIfFalse_Wide,
   kJumpIfNull,
+  kJumpIfNull_Wide,
   kJumpIfNotNull,
+  kJumpIfNotNull_Wide,
 
   // Calls.
-  kIndirectStaticCall,
+  kDirectCall,
+  kDirectCall_Wide,
+  kUnused21, // Reserved for DirectCall1
+  kUnused22, // Reserved for DirectCall1_Wide
   kInterfaceCall,
+  kInterfaceCall_Wide,
+  kUnused23, // Reserved for InterfaceCall1
+  kUnused24, // Reserved for InterfaceCall1_Wide
+  kUnused25, // Reserved for InterfaceCall2
+  kUnused26, // Reserved for InterfaceCall2_Wide
+  kUnused27, // Reserved for InterfaceCall3
+  kUnused28, // Reserved for InterfaceCall3_Wide
+  kUncheckedInterfaceCall,
+  kUncheckedInterfaceCall_Wide,
   kDynamicCall,
+  kDynamicCall_Wide,
   kNativeCall,
+  kNativeCall_Wide,
   kReturnTOS,
+  kUnused29,
 
   // Types and type checks.
   kAssertAssignable,
+  kAssertAssignable_Wide,
+  kUnused30, // Reserved for AsSimpleType
+  kUnused31, // Reserved for AsSimpleType_Wide
   kAssertBoolean,
   kAssertSubtype,
   kLoadTypeArgumentsField,
+  kLoadTypeArgumentsField_Wide,
   kInstantiateType,
+  kInstantiateType_Wide,
   kInstantiateTypeArgumentsTOS,
+  kInstantiateTypeArgumentsTOS_Wide,
+  kUnused32, // Reserved for IsType
+  kUnused33, // Reserved for IsType_Wide
+  kUnused34, // Reserved for IsSimpleType
+  kUnused35, // Reserved for IsSimpleType_Wide
 
   // Exception handling.
   kThrow,
-  kMoveSpecial,
   kSetFrame,
+  kMoveSpecial,
+  kMoveSpecial_Wide,
 
   // Bool operations.
   kBooleanNegateTOS,
 
   // Null operations.
   kEqualsNull,
+  kUnused36, // Reserved for CheckNull
+  kUnused37, // Reserved for CheckNull_Wide
 
   // Int operations.
   kNegateInt,
@@ -122,12 +322,6 @@
   kCompareIntGe,
   kCompareIntLe,
 
-  kDirectCall,
-
-  kAllocateClosure,
-
-  kUncheckedInterfaceCall,
-
   // Double operations.
   kNegateDouble,
   kAddDouble,
@@ -141,16 +335,47 @@
   kCompareDoubleLe,
 }
 
+/// Compact variants of opcodes are always even.
+/// Wide variant = opcode + kWideModifier.
+const int kWideModifier = 1;
+
+/// Opcode should fit into 1 byte.
+const int kMaxOpcodes = 256;
+
 enum Encoding {
-  k0,
-  kA,
-  kAD,
-  kAX,
-  kD,
-  kX,
-  kABC,
-  kABY,
-  kT,
+  k0, // No operands.
+  kA, // 1 operand: A = 8-bit unsigned.
+  kD, // 1 operand: D = 8/32-bit unsigned.
+  kX, // 1 operand: X = 8/32-bit signed.
+  kT, // 1 operand: T = 8/24-bit signed.
+  kAE, // 2 operands: A = 8-bit unsigned, E = 8/32-bit unsigned
+  kAY, // 2 operands: A = 8-bit unsigned, Y = 8/32-bit signed
+  kDF, // 2 operands: D = 8/32-bit unsigned, F = 8-bit unsigned
+  kABC, // 3 operands: A, B, C - 8-bit unsigned.
+}
+
+int instructionSize(Encoding encoding, bool isWide) {
+  switch (encoding) {
+    case Encoding.k0:
+      return 1;
+    case Encoding.kA:
+      return 2;
+    case Encoding.kD:
+      return isWide ? 5 : 2;
+    case Encoding.kX:
+      return isWide ? 5 : 2;
+    case Encoding.kT:
+      return isWide ? 4 : 2;
+    case Encoding.kAE:
+      return isWide ? 6 : 3;
+    case Encoding.kAY:
+      return isWide ? 6 : 3;
+    case Encoding.kDF:
+      return isWide ? 6 : 3;
+    case Encoding.kABC:
+      return 4;
+  }
+  throw 'Unexpected instruction encoding $encoding';
 }
 
 enum Operand {
@@ -175,15 +400,15 @@
   Opcode.kEntry: const Format(
       Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
   Opcode.kEntryFixed: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+      Encoding.kAE, const [Operand.imm, Operand.imm, Operand.none]),
   Opcode.kEntryOptional: const Format(
       Encoding.kABC, const [Operand.imm, Operand.imm, Operand.imm]),
   Opcode.kLoadConstant: const Format(
-      Encoding.kAD, const [Operand.reg, Operand.lit, Operand.none]),
+      Encoding.kAE, const [Operand.reg, Operand.lit, Operand.none]),
   Opcode.kFrame: const Format(
       Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
   Opcode.kCheckFunctionTypeArgs: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.reg, Operand.none]),
+      Encoding.kAE, const [Operand.imm, Operand.reg, Operand.none]),
   Opcode.kCheckStack: const Format(
       Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
   Opcode.kAllocate: const Format(
@@ -193,17 +418,17 @@
   Opcode.kCreateArrayTOS: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
   Opcode.kAllocateContext: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+      Encoding.kAE, const [Operand.imm, Operand.imm, Operand.none]),
   Opcode.kCloneContext: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+      Encoding.kAE, const [Operand.imm, Operand.imm, Operand.none]),
   Opcode.kLoadContextParent: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
   Opcode.kStoreContextParent: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
   Opcode.kLoadContextVar: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+      Encoding.kAE, const [Operand.imm, Operand.imm, Operand.none]),
   Opcode.kStoreContextVar: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+      Encoding.kAE, const [Operand.imm, Operand.imm, Operand.none]),
   Opcode.kPushConstant: const Format(
       Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
   Opcode.kPushNull: const Format(
@@ -250,18 +475,16 @@
       Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
   Opcode.kJumpIfNotNull: const Format(
       Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
-  Opcode.kIndirectStaticCall: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
   Opcode.kInterfaceCall: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+      Encoding.kDF, const [Operand.lit, Operand.imm, Operand.none]),
   Opcode.kDynamicCall: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+      Encoding.kDF, const [Operand.lit, Operand.imm, Operand.none]),
   Opcode.kNativeCall: const Format(
       Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
   Opcode.kReturnTOS: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
   Opcode.kAssertAssignable: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+      Encoding.kAE, const [Operand.imm, Operand.lit, Operand.none]),
   Opcode.kAssertBoolean: const Format(
       Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
   Opcode.kAssertSubtype: const Format(
@@ -271,11 +494,11 @@
   Opcode.kInstantiateType: const Format(
       Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
   Opcode.kInstantiateTypeArgumentsTOS: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+      Encoding.kAE, const [Operand.imm, Operand.lit, Operand.none]),
   Opcode.kThrow: const Format(
       Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
   Opcode.kMoveSpecial: const Format(
-      Encoding.kAX, const [Operand.spe, Operand.xeg, Operand.none]),
+      Encoding.kAY, const [Operand.spe, Operand.xeg, Operand.none]),
   Opcode.kSetFrame: const Format(
       Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
   Opcode.kBooleanNegateTOS: const Format(
@@ -315,11 +538,11 @@
   Opcode.kCompareIntLe: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
   Opcode.kDirectCall: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+      Encoding.kDF, const [Operand.lit, Operand.imm, Operand.none]),
   Opcode.kAllocateClosure: const Format(
       Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
   Opcode.kUncheckedInterfaceCall: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+      Encoding.kDF, const [Operand.lit, Operand.imm, Operand.none]),
   Opcode.kNegateDouble: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
   Opcode.kAddDouble: const Format(
@@ -350,18 +573,80 @@
   stackTrace,
 }
 
+/// Returns [true] if there is a wide variant for the given opcode.
+bool hasWideVariant(Opcode opcode) {
+  final encoding = BytecodeFormats[opcode].encoding;
+  switch (encoding) {
+    case Encoding.k0:
+    case Encoding.kA:
+    case Encoding.kABC:
+      return false;
+    case Encoding.kD:
+    case Encoding.kX:
+    case Encoding.kT:
+    case Encoding.kAE:
+    case Encoding.kAY:
+    case Encoding.kDF:
+      return true;
+  }
+  throw 'Unexpected instruction encoding $encoding';
+}
+
+bool isWideOpcode(Opcode opcode) {
+  return (BytecodeFormats[opcode] == null) &&
+      hasWideVariant(Opcode.values[opcode.index - kWideModifier]);
+}
+
+Opcode fromWideOpcode(Opcode opcode) {
+  assert(isWideOpcode(opcode));
+  return Opcode.values[opcode.index - kWideModifier];
+}
+
+void verifyBytecodeInstructionDeclarations() {
+  const String kWideSuffix = '_Wide';
+  for (Opcode opcode in Opcode.values) {
+    final format = BytecodeFormats[opcode];
+    if (opcode.toString().endsWith(kWideSuffix)) {
+      if (format != null) {
+        throw 'Bytecode format should not be defined for wide opcode $opcode.';
+      }
+      final Opcode compact = Opcode.values[opcode.index - kWideModifier];
+      if (compact.toString() + kWideSuffix != opcode.toString()) {
+        throw 'Wide opcode $opcode should immediately follow its compact opcode (previous opcode is $compact).';
+      }
+      if (!hasWideVariant(compact)) {
+        throw 'Wide opcode $opcode should not be defined for opcode $compact with encoding ${BytecodeFormats[compact].encoding}.';
+      }
+    }
+    if (format == null) {
+      continue;
+    }
+    if (hasWideVariant(opcode)) {
+      if (Opcode.values[opcode.index + kWideModifier].toString() !=
+          opcode.toString() + kWideSuffix) {
+        throw 'Opcode $opcode$kWideSuffix should immedialy follow $opcode.';
+      }
+      if (opcode.index.isOdd) {
+        throw 'Opcode $opcode (${format.encoding}) has a wide variant and should be even';
+      }
+    }
+  }
+  if (Opcode.values.length > kMaxOpcodes) {
+    throw 'Too many opcodes';
+  }
+}
+
 bool isJump(Opcode opcode) => BytecodeFormats[opcode].encoding == Encoding.kT;
 
 bool isThrow(Opcode opcode) => opcode == Opcode.kThrow;
 
 bool isCall(Opcode opcode) {
   switch (opcode) {
-    case Opcode.kIndirectStaticCall:
+    case Opcode.kDirectCall:
     case Opcode.kInterfaceCall:
     case Opcode.kUncheckedInterfaceCall:
     case Opcode.kDynamicCall:
     case Opcode.kNativeCall:
-    case Opcode.kDirectCall:
       return true;
     default:
       return false;
@@ -389,14 +674,14 @@
 }
 
 // Bytecode instructions reference constant pool indices using
-// unsigned 16-bit operands.
-const int constantPoolIndexLimit = 1 << 16;
+// unsigned 32-bit operands.
+const int constantPoolIndexLimit = 1 << 32;
 
-// Local variables are referenced using 16-bit signed operands.
-const int localVariableIndexLimit = 1 << 15;
+// Local variables are referenced using 32-bit signed operands.
+const int localVariableIndexLimit = 1 << 31;
 
-// Captured variables are referenced using 16-bit unsigned operands.
-const int capturedVariableIndexLimit = 1 << 16;
+// Captured variables are referenced using 32-bit unsigned operands.
+const int capturedVariableIndexLimit = 1 << 32;
 
 // Context IDs are referenced using 8-bit unsigned operands.
 const int contextIdLimit = 1 << 8;
diff --git a/pkg/vm/lib/bytecode/declarations.dart b/pkg/vm/lib/bytecode/declarations.dart
index a028f6e..1d8cfc5 100644
--- a/pkg/vm/lib/bytecode/declarations.dart
+++ b/pkg/vm/lib/bytecode/declarations.dart
@@ -9,12 +9,10 @@
     show BufferedWriter, BufferedReader, BytecodeSizeStatistics, StringTable;
 import 'constant_pool.dart' show ConstantPool;
 import 'dbc.dart'
-    show
-        currentBytecodeFormatVersion,
-        futureBytecodeFormatVersion,
-        bytecodeInstructionsAlignment;
+    show currentBytecodeFormatVersion, futureBytecodeFormatVersion;
 import 'disassembler.dart' show BytecodeDisassembler;
 import 'exceptions.dart' show ExceptionsTable;
+import 'local_variable_table.dart' show LocalVariableTable;
 import 'object_table.dart' show ObjectTable, ObjectHandle, NameAndType;
 import 'source_positions.dart' show SourcePositions;
 
@@ -143,10 +141,10 @@
         ((flags & hasCustomScriptFlag) != 0) ? reader.readPackedObject() : null;
     final position = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readPackedUInt30() - 1
-        : 0;
+        : TreeNode.noOffset;
     final endPosition = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readPackedUInt30() - 1
-        : 0;
+        : TreeNode.noOffset;
     final initializerCode =
         ((flags & hasInitializerFlag) != 0 && (flags & isStaticFlag) != 0)
             ? reader.readLinkOffset<Code>()
@@ -301,10 +299,10 @@
         ((flags & hasCustomScriptFlag) != 0) ? reader.readPackedObject() : null;
     final position = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readPackedUInt30() - 1
-        : 0;
+        : TreeNode.noOffset;
     final endPosition = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readPackedUInt30() - 1
-        : 0;
+        : TreeNode.noOffset;
     final typeParameters = ((flags & hasTypeParamsFlag) != 0)
         ? new TypeParametersDeclaration.read(reader)
         : null;
@@ -494,11 +492,13 @@
   static const hasParameterFlagsFlag = 1 << 4;
   static const hasForwardingStubTargetFlag = 1 << 5;
   static const hasDefaultFunctionTypeArgsFlag = 1 << 6;
+  static const hasLocalVariablesFlag = 1 << 7;
 
   final ConstantPool constantPool;
   final List<int> bytecodes;
   final ExceptionsTable exceptionsTable;
   final SourcePositions sourcePositions;
+  final LocalVariableTable localVariables;
   final List<ObjectHandle> nullableFields;
   final List<ClosureDeclaration> closures;
   final List<int> parameterFlags;
@@ -508,6 +508,8 @@
   bool get hasExceptionsTable => exceptionsTable.blocks.isNotEmpty;
   bool get hasSourcePositions =>
       sourcePositions != null && sourcePositions.mapping.isNotEmpty;
+  bool get hasLocalVariables =>
+      localVariables != null && localVariables.isNotEmpty;
   bool get hasNullableFields => nullableFields.isNotEmpty;
   bool get hasClosures => closures.isNotEmpty;
 
@@ -520,13 +522,15 @@
       (forwardingStubTargetCpIndex != null ? hasForwardingStubTargetFlag : 0) |
       (defaultFunctionTypeArgsCpIndex != null
           ? hasDefaultFunctionTypeArgsFlag
-          : 0);
+          : 0) |
+      (hasLocalVariables ? hasLocalVariablesFlag : 0);
 
   Code(
       this.constantPool,
       this.bytecodes,
       this.exceptionsTable,
       this.sourcePositions,
+      this.localVariables,
       this.nullableFields,
       this.closures,
       this.parameterFlags,
@@ -558,6 +562,9 @@
     if (hasSourcePositions) {
       writer.writeLinkOffset(sourcePositions);
     }
+    if (hasLocalVariables) {
+      writer.writeLinkOffset(localVariables);
+    }
     if (hasNullableFields) {
       writer.writePackedList(nullableFields);
     }
@@ -593,6 +600,9 @@
     final sourcePositions = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readLinkOffset<SourcePositions>()
         : null;
+    final localVariables = ((flags & hasLocalVariablesFlag) != 0)
+        ? reader.readLinkOffset<LocalVariableTable>()
+        : null;
     final List<ObjectHandle> nullableFields =
         ((flags & hasNullableFieldsFlag) != 0)
             ? reader.readPackedList<ObjectHandle>()
@@ -605,6 +615,7 @@
         bytecodes,
         exceptionsTable,
         sourcePositions,
+        localVariables,
         nullableFields,
         closures,
         parameterFlags,
@@ -619,6 +630,9 @@
       "${new BytecodeDisassembler().disassemble(bytecodes, exceptionsTable, annotations: [
         hasSourcePositions
             ? sourcePositions.getBytecodeAnnotations()
+            : const <int, String>{},
+        hasLocalVariables
+            ? localVariables.getBytecodeAnnotations()
             : const <int, String>{}
       ])}}\n"
       "$exceptionsTable"
@@ -631,12 +645,15 @@
 }
 
 class ClosureDeclaration {
-  static const int flagHasOptionalPositionalParams = 1 << 0;
-  static const int flagHasOptionalNamedParams = 1 << 1;
-  static const int flagHasTypeParams = 1 << 2;
+  static const int hasOptionalPositionalParamsFlag = 1 << 0;
+  static const int hasOptionalNamedParamsFlag = 1 << 1;
+  static const int hasTypeParamsFlag = 1 << 2;
+  static const int hasSourcePositionsFlag = 1 << 3;
 
   final ObjectHandle parent;
   final ObjectHandle name;
+  final int position;
+  final int endPosition;
   final List<NameAndType> typeParams;
   final int numRequiredParams;
   final int numNamedParams;
@@ -647,6 +664,8 @@
   ClosureDeclaration(
       this.parent,
       this.name,
+      this.position,
+      this.endPosition,
       this.typeParams,
       this.numRequiredParams,
       this.numNamedParams,
@@ -657,19 +676,27 @@
     int flags = 0;
     if (numRequiredParams != parameters.length) {
       if (numNamedParams > 0) {
-        flags |= flagHasOptionalNamedParams;
+        flags |= hasOptionalNamedParamsFlag;
       } else {
-        flags |= flagHasOptionalPositionalParams;
+        flags |= hasOptionalPositionalParamsFlag;
       }
     }
     if (typeParams.isNotEmpty) {
-      flags |= flagHasTypeParams;
+      flags |= hasTypeParamsFlag;
+    }
+    if (position != TreeNode.noOffset) {
+      flags |= hasSourcePositionsFlag;
     }
     writer.writePackedUInt30(flags);
     writer.writePackedObject(parent);
     writer.writePackedObject(name);
 
-    if (flags & flagHasTypeParams != 0) {
+    if (flags & hasSourcePositionsFlag != 0) {
+      writer.writePackedUInt30(position + 1);
+      writer.writePackedUInt30(endPosition + 1);
+    }
+
+    if (flags & hasTypeParamsFlag != 0) {
       writer.writePackedUInt30(typeParams.length);
       for (var tp in typeParams) {
         writer.writePackedObject(tp.name);
@@ -680,7 +707,7 @@
     }
     writer.writePackedUInt30(parameters.length);
     if (flags &
-            (flagHasOptionalPositionalParams | flagHasOptionalNamedParams) !=
+            (hasOptionalPositionalParamsFlag | hasOptionalNamedParamsFlag) !=
         0) {
       writer.writePackedUInt30(numRequiredParams);
     }
@@ -695,8 +722,14 @@
     final int flags = reader.readPackedUInt30();
     final parent = reader.readPackedObject();
     final name = reader.readPackedObject();
+    final position = ((flags & hasSourcePositionsFlag) != 0)
+        ? reader.readPackedUInt30() - 1
+        : TreeNode.noOffset;
+    final endPosition = ((flags & hasSourcePositionsFlag) != 0)
+        ? reader.readPackedUInt30() - 1
+        : TreeNode.noOffset;
     List<NameAndType> typeParams;
-    if ((flags & flagHasTypeParams) != 0) {
+    if ((flags & hasTypeParamsFlag) != 0) {
       final int numTypeParams = reader.readPackedUInt30();
       List<ObjectHandle> names = new List<ObjectHandle>.generate(
           numTypeParams, (_) => reader.readPackedObject());
@@ -709,12 +742,12 @@
     }
     final numParams = reader.readPackedUInt30();
     final numRequiredParams = (flags &
-                (flagHasOptionalPositionalParams |
-                    flagHasOptionalNamedParams) !=
+                (hasOptionalPositionalParamsFlag |
+                    hasOptionalNamedParamsFlag) !=
             0)
         ? reader.readPackedUInt30()
         : numParams;
-    final numNamedParams = (flags & flagHasOptionalNamedParams != 0)
+    final numNamedParams = (flags & hasOptionalNamedParamsFlag != 0)
         ? (numParams - numRequiredParams)
         : 0;
     final List<NameAndType> parameters = new List<NameAndType>.generate(
@@ -722,14 +755,17 @@
         (_) => new NameAndType(
             reader.readPackedObject(), reader.readPackedObject()));
     final returnType = reader.readPackedObject();
-    return new ClosureDeclaration(parent, name, typeParams, numRequiredParams,
-        numNamedParams, parameters, returnType);
+    return new ClosureDeclaration(parent, name, position, endPosition,
+        typeParams, numRequiredParams, numNamedParams, parameters, returnType);
   }
 
   @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('Closure $parent::$name');
+    if (position != TreeNode.noOffset) {
+      sb.write(' pos = $position, end-pos = $endPosition');
+    }
     if (typeParams.isNotEmpty) {
       sb.write(' <${typeParams.join(', ')}>');
     }
@@ -757,19 +793,28 @@
 /// Bytecode of a nested function (closure).
 /// Closures share the constant pool of a top-level member.
 class ClosureCode {
+  static const hasExceptionsTableFlag = 1 << 0;
+  static const hasSourcePositionsFlag = 1 << 1;
+  static const hasLocalVariablesFlag = 1 << 2;
+
   final List<int> bytecodes;
   final ExceptionsTable exceptionsTable;
   final SourcePositions sourcePositions;
+  final LocalVariableTable localVariables;
 
   bool get hasExceptionsTable => exceptionsTable.blocks.isNotEmpty;
   bool get hasSourcePositions =>
       sourcePositions != null && sourcePositions.mapping.isNotEmpty;
+  bool get hasLocalVariables =>
+      localVariables != null && localVariables.isNotEmpty;
 
   int get flags =>
-      (hasExceptionsTable ? Code.hasExceptionsTableFlag : 0) |
-      (hasSourcePositions ? Code.hasSourcePositionsFlag : 0);
+      (hasExceptionsTable ? hasExceptionsTableFlag : 0) |
+      (hasSourcePositions ? hasSourcePositionsFlag : 0) |
+      (hasLocalVariables ? hasLocalVariablesFlag : 0);
 
-  ClosureCode(this.bytecodes, this.exceptionsTable, this.sourcePositions);
+  ClosureCode(this.bytecodes, this.exceptionsTable, this.sourcePositions,
+      this.localVariables);
 
   void write(BufferedWriter writer) {
     writer.writePackedUInt30(flags);
@@ -780,18 +825,25 @@
     if (hasSourcePositions) {
       writer.writeLinkOffset(sourcePositions);
     }
+    if (hasLocalVariables) {
+      writer.writeLinkOffset(localVariables);
+    }
   }
 
   factory ClosureCode.read(BufferedReader reader) {
     final int flags = reader.readPackedUInt30();
     final List<int> bytecodes = _readBytecodeInstructions(reader);
-    final exceptionsTable = ((flags & Code.hasExceptionsTableFlag) != 0)
+    final exceptionsTable = ((flags & hasExceptionsTableFlag) != 0)
         ? new ExceptionsTable.read(reader)
         : new ExceptionsTable();
-    final sourcePositions = ((flags & Code.hasSourcePositionsFlag) != 0)
+    final sourcePositions = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readLinkOffset<SourcePositions>()
         : null;
-    return new ClosureCode(bytecodes, exceptionsTable, sourcePositions);
+    final localVariables = ((flags & hasLocalVariablesFlag) != 0)
+        ? reader.readLinkOffset<LocalVariableTable>()
+        : null;
+    return new ClosureCode(
+        bytecodes, exceptionsTable, sourcePositions, localVariables);
   }
 
   @override
@@ -802,6 +854,9 @@
         .disassemble(bytecodes, exceptionsTable, annotations: [
       hasSourcePositions
           ? sourcePositions.getBytecodeAnnotations()
+          : const <int, String>{},
+      hasLocalVariables
+          ? localVariables.getBytecodeAnnotations()
           : const <int, String>{}
     ]));
     sb.writeln('}');
@@ -821,7 +876,7 @@
 
 class Component {
   static const int magicValue = 0x44424332; // 'DBC2'
-  static const int numSections = 7;
+  static const int numSections = 8;
   static const int sectionAlignment = 4;
 
   //  UInt32 magic, version, numSections x (numItems, offset)
@@ -833,6 +888,7 @@
   List<Members> members = <Members>[];
   List<Code> codes = <Code>[];
   List<SourcePositions> sourcePositions = <SourcePositions>[];
+  List<LocalVariableTable> localVariables = <LocalVariableTable>[];
   List<ObjectHandle> annotations = <ObjectHandle>[];
   ObjectHandle mainLibrary;
 
@@ -853,6 +909,13 @@
       annotationsWriter.writePackedObject(annot);
     }
 
+    final BufferedWriter localVariablesWriter =
+        new BufferedWriter.fromWriter(writer);
+    for (var lv in localVariables) {
+      writer.linkWriter.put(lv, localVariablesWriter.offset);
+      lv.write(localVariablesWriter);
+    }
+
     final BufferedWriter sourcePositionsWriter =
         new BufferedWriter.fromWriter(writer);
     for (var sp in sourcePositions) {
@@ -891,6 +954,7 @@
       new _Section(members.length, membersWriter),
       new _Section(codes.length, codesWriter),
       new _Section(sourcePositions.length, sourcePositionsWriter),
+      new _Section(localVariables.length, localVariablesWriter),
       new _Section(annotations.length, annotationsWriter),
     ];
     assert(sections.length == numSections);
@@ -959,6 +1023,9 @@
     final sourcePositionsNum = reader.readUInt32();
     final sourcePositionsOffset = reader.readUInt32();
 
+    final localVariablesNum = reader.readUInt32();
+    final localVariablesOffset = reader.readUInt32();
+
     final annotationsNum = reader.readUInt32();
     final annotationsOffset = reader.readUInt32();
 
@@ -991,6 +1058,15 @@
       sourcePositions.add(sp);
     }
 
+    final localVariablesStart = start + localVariablesOffset;
+    reader.offset = localVariablesStart;
+    for (int i = 0; i < localVariablesNum; ++i) {
+      int offset = reader.offset - localVariablesStart;
+      LocalVariableTable lv = new LocalVariableTable.read(reader);
+      reader.linkReader.setOffset(lv, offset);
+      localVariables.add(lv);
+    }
+
     final codesStart = start + codesOffset;
     reader.offset = codesStart;
     for (int i = 0; i < codesNum; ++i) {
@@ -1029,13 +1105,11 @@
 
 void _writeBytecodeInstructions(BufferedWriter writer, List<int> bytecodes) {
   writer.writePackedUInt30(bytecodes.length);
-  writer.align(bytecodeInstructionsAlignment);
   writer.writeBytes(bytecodes);
   BytecodeSizeStatistics.instructionsSize += bytecodes.length;
 }
 
 List<int> _readBytecodeInstructions(BufferedReader reader) {
   int len = reader.readPackedUInt30();
-  reader.align(bytecodeInstructionsAlignment);
   return reader.readBytesAsUint8List(len);
 }
diff --git a/pkg/vm/lib/bytecode/disassembler.dart b/pkg/vm/lib/bytecode/disassembler.dart
index 153e837..5d53446 100644
--- a/pkg/vm/lib/bytecode/disassembler.dart
+++ b/pkg/vm/lib/bytecode/disassembler.dart
@@ -13,8 +13,15 @@
 
 class Instruction {
   final Opcode opcode;
+  final bool isWide;
   final List<int> operands;
-  Instruction(this.opcode, this.operands);
+  final int pc;
+
+  Instruction(this.opcode, this.isWide, this.operands, this.pc);
+
+  Format get format => BytecodeFormats[opcode];
+
+  int get length => instructionSize(format.encoding, isWide);
 
   @override
   int get hashCode => opcode.index.hashCode ^ listHashCode(operands);
@@ -28,9 +35,7 @@
 }
 
 class BytecodeDisassembler {
-  static const int kOpcodeMask = 0xFF;
-  static const int kBitsPerInt = 64;
-
+  Uint8List _bytecode;
   List<Instruction> _instructions;
   int _labelCount;
   Map<int, String> _labels;
@@ -47,14 +52,19 @@
     return _disasm();
   }
 
-  void _init(List<int> bytecode) {
-    final uint8list = new Uint8List.fromList(bytecode);
-    // TODO(alexmarkov): endianness?
-    Uint32List words = uint8list.buffer.asUint32List();
+  List<Instruction> decode(Uint8List bytecode) {
+    _init(bytecode);
+    return _instructions;
+  }
 
-    _instructions = new List<Instruction>(words.length);
-    for (int i = 0; i < words.length; i++) {
-      _instructions[i] = decodeInstruction(words[i]);
+  void _init(List<int> bytecode) {
+    _bytecode = new Uint8List.fromList(bytecode);
+
+    _instructions = new List<Instruction>();
+    for (int pos = 0; pos < _bytecode.length;) {
+      final instr = decodeInstructionAt(pos);
+      _instructions.add(instr);
+      pos += instr.length;
     }
 
     _labelCount = 0;
@@ -62,58 +72,73 @@
     _markers = <int, List<String>>{};
   }
 
-  Instruction decodeInstruction(int word) {
-    final opcode = Opcode.values[word & kOpcodeMask];
+  Instruction decodeInstructionAt(int pos) {
+    Opcode opcode = Opcode.values[_bytecode[pos]];
+    bool isWide = isWideOpcode(opcode);
+    if (isWide) {
+      opcode = fromWideOpcode(opcode);
+    }
+
     final format = BytecodeFormats[opcode];
-    return new Instruction(opcode, _decodeOperands(format, word));
+    final operands = _decodeOperands(format, pos, isWide);
+    return new Instruction(opcode, isWide, operands, pos);
   }
 
-  List<int> _decodeOperands(Format format, int word) {
+  List<int> _decodeOperands(Format format, int pos, bool isWide) {
     switch (format.encoding) {
       case Encoding.k0:
         return const [];
       case Encoding.kA:
-        return [_unsigned(word, 8, 8)];
-      case Encoding.kAD:
-        return [_unsigned(word, 8, 8), _unsigned(word, 16, 16)];
-      case Encoding.kAX:
-        return [_unsigned(word, 8, 8), _signed(word, 16, 16)];
+        return [_bytecode[pos + 1]];
       case Encoding.kD:
-        return [_unsigned(word, 16, 16)];
+        return isWide ? [_decodeUint32At(pos + 1)] : [_bytecode[pos + 1]];
       case Encoding.kX:
-        return [_signed(word, 16, 16)];
-      case Encoding.kABC:
-        return [
-          _unsigned(word, 8, 8),
-          _unsigned(word, 16, 8),
-          _unsigned(word, 24, 8)
-        ];
-      case Encoding.kABY:
-        return [
-          _unsigned(word, 8, 8),
-          _unsigned(word, 16, 8),
-          _signed(word, 24, 8)
-        ];
+        return isWide
+            ? [_decodeUint32At(pos + 1).toSigned(32)]
+            : [_bytecode[pos + 1].toSigned(8)];
       case Encoding.kT:
-        return [_signed(word, 8, 24)];
+        return isWide
+            ? [
+                (_bytecode[pos + 1] +
+                        (_bytecode[pos + 2] << 8) +
+                        (_bytecode[pos + 3] << 16))
+                    .toSigned(24)
+              ]
+            : [_bytecode[pos + 1].toSigned(8)];
+      case Encoding.kAE:
+        return [
+          _bytecode[pos + 1],
+          isWide ? _decodeUint32At(pos + 2) : _bytecode[pos + 2],
+        ];
+      case Encoding.kAY:
+        return [
+          _bytecode[pos + 1],
+          isWide
+              ? _decodeUint32At(pos + 2).toSigned(32)
+              : _bytecode[pos + 2].toSigned(8)
+        ];
+      case Encoding.kDF:
+        return isWide
+            ? [_decodeUint32At(pos + 1), _bytecode[pos + 5]]
+            : [_bytecode[pos + 1], _bytecode[pos + 2]];
+      case Encoding.kABC:
+        return [_bytecode[pos + 1], _bytecode[pos + 2], _bytecode[pos + 3]];
     }
     throw 'Unexpected format $format';
   }
 
-  int _unsigned(int word, int pos, int bits) =>
-      (word >> pos) & ((1 << bits) - 1);
-
-  int _signed(int word, int pos, int bits) =>
-      _unsigned(word, pos, bits) <<
-      (kBitsPerInt - bits) >>
-      (kBitsPerInt - bits);
+  _decodeUint32At(int pos) =>
+      _bytecode[pos] +
+      (_bytecode[pos + 1] << 8) +
+      (_bytecode[pos + 2] << 16) +
+      (_bytecode[pos + 3] << 24);
 
   void _scanForJumpTargets() {
     for (int i = 0; i < _instructions.length; i++) {
       final instr = _instructions[i];
       if (isJump(instr.opcode)) {
-        final target = i + instr.operands[0];
-        assert(0 <= target && target < _instructions.length);
+        final target = instr.pc + instr.operands[0];
+        assert(0 <= target && target < _bytecode.length);
         if (!_labels.containsKey(target)) {
           final label = 'L${++_labelCount}';
           _labels[target] = label;
@@ -147,17 +172,17 @@
 
   String _disasm() {
     StringBuffer out = new StringBuffer();
-    for (int i = 0; i < _instructions.length; i++) {
-      List<String> markers = _markers[i];
+    for (Instruction instr in _instructions) {
+      List<String> markers = _markers[instr.pc];
       if (markers != null) {
         markers.forEach(out.writeln);
       }
-      writeInstruction(out, i, _instructions[i]);
+      writeInstruction(out, instr);
     }
     return out.toString();
   }
 
-  void writeInstruction(StringBuffer out, int bci, Instruction instr) {
+  void writeInstruction(StringBuffer out, Instruction instr) {
     final format = BytecodeFormats[instr.opcode];
     assert(format != null);
 
@@ -184,14 +209,14 @@
         out.write(', ');
       }
       final operand =
-          _formatOperand(bci, format.operands[i], instr.operands[i]);
+          _formatOperand(instr.pc, format.operands[i], instr.operands[i]);
       out.write(operand);
     }
 
     out.writeln();
   }
 
-  String _formatOperand(int bci, Operand fmt, int value) {
+  String _formatOperand(int pc, Operand fmt, int value) {
     switch (fmt) {
       case Operand.none:
         break;
@@ -206,7 +231,7 @@
       case Operand.tgt:
         return (_labels == null)
             ? value.toString()
-            : _labels[bci + value] ?? (throw 'Label not found');
+            : _labels[pc + value] ?? (throw 'Label not found');
       case Operand.spe:
         return SpecialIndex.values[value]
             .toString()
diff --git a/pkg/vm/lib/bytecode/exceptions.dart b/pkg/vm/lib/bytecode/exceptions.dart
index 2147790..3ae6e1c 100644
--- a/pkg/vm/lib/bytecode/exceptions.dart
+++ b/pkg/vm/lib/bytecode/exceptions.dart
@@ -11,7 +11,7 @@
 In kernel binary, try blocks are encoded in the following way
 (using notation from pkg/kernel/binary.md):
 
-// Offset of a bytecode instruction, in DBC words.
+// Offset of a bytecode instruction.
 type BytecodeOffset = UInt;
 
 type TryBlock {
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index f8ae346..ba4f75e 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -35,6 +35,7 @@
         hasFreeTypeParameters,
         hasInstantiatorTypeArguments,
         isUncheckedCall;
+import 'local_variable_table.dart' show LocalVariableTable;
 import 'local_vars.dart' show LocalVariables;
 import 'nullability_detector.dart' show NullabilityDetector;
 import 'object_table.dart' show ObjectHandle, ObjectTable, NameAndType;
@@ -43,6 +44,8 @@
 import '../constants_error_reporter.dart' show ForwardConstantEvaluationErrors;
 import '../metadata/bytecode.dart';
 
+import 'dart:math' as math;
+
 // This symbol is used as the name in assert assignable's to indicate it comes
 // from an explicit 'as' check.  This will cause the runtime to throw the right
 // exception.
@@ -50,17 +53,21 @@
 
 void generateBytecode(
   ast.Component component, {
+  bool enableAsserts: true,
   bool emitSourcePositions: false,
+  bool emitLocalVarInfo: false,
   bool emitAnnotations: false,
   bool omitAssertSourcePositions: false,
   bool useFutureBytecodeFormat: false,
   Map<String, String> environmentDefines: const <String, String>{},
   ErrorReporter errorReporter,
   List<Library> libraries,
+  ClassHierarchy hierarchy,
 }) {
+  verifyBytecodeInstructionDeclarations();
   final coreTypes = new CoreTypes(component);
   void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
-  final hierarchy = new ClassHierarchy(component,
+  hierarchy ??= new ClassHierarchy(component,
       onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
   final typeEnvironment = new TypeEnvironment(coreTypes, hierarchy);
   final constantsBackend = new VmConstantsBackend(coreTypes);
@@ -73,7 +80,9 @@
       typeEnvironment,
       constantsBackend,
       environmentDefines,
+      enableAsserts,
       emitSourcePositions,
+      emitLocalVarInfo,
       emitAnnotations,
       omitAssertSourcePositions,
       useFutureBytecodeFormat,
@@ -89,7 +98,9 @@
   final TypeEnvironment typeEnvironment;
   final ConstantsBackend constantsBackend;
   final Map<String, String> environmentDefines;
+  final bool enableAsserts;
   final bool emitSourcePositions;
+  final bool emitLocalVarInfo;
   final bool emitAnnotations;
   final bool omitAssertSourcePositions;
   final bool useFutureBytecodeFormat;
@@ -129,6 +140,8 @@
   List<BytecodeAssembler> savedAssemblers;
   bool hasErrors;
   int currentLoopDepth;
+  List<int> savedMaxSourcePositions;
+  int maxSourcePosition;
 
   BytecodeGenerator(
       ast.Component component,
@@ -137,7 +150,9 @@
       this.typeEnvironment,
       this.constantsBackend,
       this.environmentDefines,
+      this.enableAsserts,
       this.emitSourcePositions,
+      this.emitLocalVarInfo,
       this.emitAnnotations,
       this.omitAssertSourcePositions,
       this.useFutureBytecodeFormat,
@@ -658,10 +673,11 @@
       _asyncAwaitCompleterGetFuture ??= libraryIndex.getMember(
           'dart:async', '_AsyncAwaitCompleter', 'get:future');
 
-  void _recordSourcePosition(TreeNode node) {
+  void _recordSourcePosition(int fileOffset) {
     if (emitSourcePositions) {
-      asm.currentSourcePosition = node.fileOffset;
+      asm.currentSourcePosition = fileOffset;
     }
+    maxSourcePosition = math.max(maxSourcePosition, fileOffset);
   }
 
   void _generateNode(TreeNode node) {
@@ -669,7 +685,7 @@
       return;
     }
     final savedSourcePosition = asm.currentSourcePosition;
-    _recordSourcePosition(node);
+    _recordSourcePosition(node.fileOffset);
     node.accept(this);
     asm.currentSourcePosition = savedSourcePosition;
   }
@@ -738,6 +754,9 @@
   }
 
   void _genPushInt(int value) {
+    // TODO(alexmarkov): relax this constraint as PushInt instruction can
+    // hold up to 32-bit signed operand (note that interpreter assumes
+    // it is Smi).
     if (value.bitLength + 1 <= 16) {
       asm.emitPushInt(value);
     } else {
@@ -785,7 +804,7 @@
         : (isSet ? InvocationKind.setter : InvocationKind.method);
     final cpIndex = cp.addDirectCall(kind, target, argDesc);
 
-    asm.emitDirectCall(totalArgCount, cpIndex);
+    asm.emitDirectCall(cpIndex, totalArgCount);
   }
 
   void _genDirectCallWithArgs(Member target, Arguments args,
@@ -1064,7 +1083,7 @@
       final argDesc = objectTable.getArgDescHandle(2);
       final cpIndex = cp.addInterfaceCall(
           InvocationKind.method, objectSimpleInstanceOf, argDesc);
-      asm.emitInterfaceCall(2, cpIndex);
+      asm.emitInterfaceCall(cpIndex, 2);
       return;
     }
 
@@ -1078,7 +1097,7 @@
     final argDesc = objectTable.getArgDescHandle(4);
     final cpIndex =
         cp.addInterfaceCall(InvocationKind.method, objectInstanceOf, argDesc);
-    asm.emitInterfaceCall(4, cpIndex);
+    asm.emitInterfaceCall(cpIndex, 4);
   }
 
   void start(Member node) {
@@ -1119,12 +1138,8 @@
       functionTypeParametersSet = functionTypeParameters.toSet();
     }
     // TODO(alexmarkov): improve caching in ConstantEvaluator and reuse it
-    constantEvaluator = new ConstantEvaluator(
-        constantsBackend,
-        environmentDefines,
-        typeEnvironment,
-        /* enableAsserts = */ true,
-        errorReporter)
+    constantEvaluator = new ConstantEvaluator(constantsBackend,
+        environmentDefines, typeEnvironment, enableAsserts, errorReporter)
       ..env = new EvaluationEnvironment();
 
     if (node.isAbstract || node is Field && !hasInitializerCode(node)) {
@@ -1144,12 +1159,14 @@
     asm = new BytecodeAssembler();
     savedAssemblers = <BytecodeAssembler>[];
     currentLoopDepth = 0;
+    savedMaxSourcePositions = <int>[];
+    maxSourcePosition = node.fileOffset;
 
-    locals = new LocalVariables(node);
+    locals = new LocalVariables(node, enableAsserts);
     locals.enterScope(node);
     assert(!locals.isSyncYieldingFrame);
 
-    _recordSourcePosition(node);
+    _recordSourcePosition(node.fileOffset);
     _genPrologue(node, node.function);
     _setupInitialContext(node.function);
     if (node is Procedure && node.isInstanceMember) {
@@ -1181,6 +1198,12 @@
     if (!hasErrors) {
       Code code;
       if (hasCode) {
+        if (emitLocalVarInfo && node.function != null) {
+          // Leave the scope which was entered in _setupInitialContext.
+          asm.localVariableTable
+              .leaveScope(asm.offset, node.function.fileEndOffset);
+        }
+
         List<int> parameterFlags = null;
         int forwardingStubTargetCpIndex = null;
         int defaultFunctionTypeArgsCpIndex = null;
@@ -1203,6 +1226,7 @@
             asm.bytecode,
             asm.exceptionsTable,
             finalizeSourcePositions(),
+            finalizeLocalVariables(),
             nullableFields,
             closures,
             parameterFlags,
@@ -1252,6 +1276,16 @@
     return asm.sourcePositions;
   }
 
+  LocalVariableTable finalizeLocalVariables() {
+    final localVariables = asm.localVariableTable;
+    assert(!localVariables.hasActiveScopes);
+    if (localVariables.isEmpty) {
+      return null;
+    }
+    bytecodeComponent.localVariables.add(localVariables);
+    return localVariables;
+  }
+
   void _genPrologue(Node node, FunctionNode function) {
     if (locals.hasOptionalParameters) {
       final int numOptionalPositional = function.positionalParameters.length -
@@ -1376,6 +1410,25 @@
   void _setupInitialContext(FunctionNode function) {
     _allocateContextIfNeeded();
 
+    if (emitLocalVarInfo && function != null) {
+      // Open scope after allocating context.
+      asm.localVariableTable.enterScope(
+          asm.offset, locals.currentContextLevel, function.fileOffset);
+      if (locals.hasContextVar) {
+        asm.localVariableTable
+            .recordContextVariable(asm.offset, locals.contextVarIndexInFrame);
+      }
+      if (locals.hasReceiver) {
+        _declareLocalVariable(locals.receiverVar, function.fileOffset);
+      }
+      for (var v in function.positionalParameters) {
+        _declareLocalVariable(v, function.fileOffset);
+      }
+      for (var v in locals.sortedNamedParameters) {
+        _declareLocalVariable(v, function.fileOffset);
+      }
+    }
+
     if (locals.hasCapturedParameters) {
       // Copy captured parameters to their respective locations in the context.
       if (!isClosure) {
@@ -1403,6 +1456,22 @@
     }
   }
 
+  void _declareLocalVariable(
+      VariableDeclaration variable, int initializedPosition) {
+    assert(variable.name != null);
+    bool isCaptured = locals.isCaptured(variable);
+    asm.localVariableTable.declareVariable(
+        asm.offset,
+        isCaptured,
+        isCaptured
+            ? locals.getVarIndexInContext(variable)
+            : locals.getVarIndexInFrame(variable),
+        cp.addString(variable.name),
+        cp.addType(variable.type),
+        variable.fileOffset,
+        initializedPosition);
+  }
+
   // TODO(alexmarkov): Revise if we need to AOT-compile from bytecode.
   bool get canSkipTypeChecksForNonCovariantArguments =>
       !isClosure && enclosingMember.name.name != 'call';
@@ -1613,6 +1682,15 @@
     final savedLoopDepth = currentLoopDepth;
     currentLoopDepth = 0;
 
+    int position = TreeNode.noOffset;
+    int endPosition = TreeNode.noOffset;
+    if (emitSourcePositions) {
+      position = (node is ast.FunctionDeclaration)
+          ? node.fileOffset
+          : function.fileOffset;
+      endPosition = function.fileEndOffset;
+    }
+
     if (function.typeParameters.isNotEmpty) {
       functionTypeParameters ??= new List<TypeParameter>();
       functionTypeParameters.addAll(function.typeParameters);
@@ -1639,6 +1717,8 @@
         objectTable
             .getHandle(savedIsClosure ? parentFunction : enclosingMember),
         objectTable.getNameHandle(null, name),
+        position,
+        endPosition,
         function.typeParameters
             .map((tp) => new NameAndType(
                 objectTable.getNameHandle(null, tp.name),
@@ -1652,6 +1732,7 @@
 
     final int closureFunctionIndex = cp.addClosureFunction(closureIndex);
 
+    _recordSourcePosition(function.fileOffset);
     _genPrologue(node, function);
 
     Label continuationSwitchLabel;
@@ -1673,12 +1754,18 @@
     // BytecodeAssembler eliminates this bytecode if it is unreachable.
     asm.emitPushNull();
     _genReturnTOS();
+    _recordSourcePosition(function.fileEndOffset);
 
     if (locals.isSyncYieldingFrame) {
       _genSyncYieldingEpilogue(
           function, continuationSwitchLabel, continuationSwitchVar);
     }
 
+    if (emitLocalVarInfo) {
+      // Leave the scope which was entered in _setupInitialContext.
+      asm.localVariableTable.leaveScope(asm.offset, function.fileEndOffset);
+    }
+
     cp.addEndClosureFunctionScope();
 
     if (function.typeParameters.isNotEmpty) {
@@ -1693,8 +1780,8 @@
 
     locals.leaveScope();
 
-    closure.code = new ClosureCode(
-        asm.bytecode, asm.exceptionsTable, finalizeSourcePositions());
+    closure.code = new ClosureCode(asm.bytecode, asm.exceptionsTable,
+        finalizeSourcePositions(), finalizeLocalVariables());
 
     _popAssemblerState();
     yieldPoints = savedYieldPoints;
@@ -1798,15 +1885,35 @@
   void _enterScope(TreeNode node) {
     locals.enterScope(node);
     _allocateContextIfNeeded();
+    if (emitLocalVarInfo) {
+      asm.localVariableTable
+          .enterScope(asm.offset, locals.currentContextLevel, node.fileOffset);
+      _startRecordingMaxPosition(node.fileOffset);
+    }
   }
 
   void _leaveScope() {
+    if (emitLocalVarInfo) {
+      asm.localVariableTable.leaveScope(asm.offset, _endRecordingMaxPosition());
+    }
     if (locals.currentContextSize > 0) {
       _genUnwindContext(locals.currentContextLevel - 1);
     }
     locals.leaveScope();
   }
 
+  void _startRecordingMaxPosition(int fileOffset) {
+    savedMaxSourcePositions.add(maxSourcePosition);
+    maxSourcePosition = fileOffset;
+  }
+
+  int _endRecordingMaxPosition() {
+    int localMax = maxSourcePosition;
+    maxSourcePosition =
+        math.max(localMax, savedMaxSourcePositions.removeLast());
+    return localMax;
+  }
+
   void _genUnwindContext(int targetContextLevel) {
     int currentContextLevel = locals.currentContextLevel;
     assert(currentContextLevel >= targetContextLevel);
@@ -2289,18 +2396,18 @@
         throw 'Unexpected specialized bytecode $opcode';
     }
 
-    asm.emitBytecode0(opcode);
+    asm.emitSpecializedBytecode(opcode);
   }
 
   void _genInstanceCall(
       int totalArgCount, int callCpIndex, bool isDynamic, bool isUnchecked) {
     if (isDynamic) {
       assert(!isUnchecked);
-      asm.emitDynamicCall(totalArgCount, callCpIndex);
+      asm.emitDynamicCall(callCpIndex, totalArgCount);
     } else if (isUnchecked) {
-      asm.emitUncheckedInterfaceCall(totalArgCount, callCpIndex);
+      asm.emitUncheckedInterfaceCall(callCpIndex, totalArgCount);
     } else {
-      asm.emitInterfaceCall(totalArgCount, callCpIndex);
+      asm.emitInterfaceCall(callCpIndex, totalArgCount);
     }
   }
 
@@ -2681,6 +2788,10 @@
 
   @override
   visitAssertStatement(AssertStatement node) {
+    if (!enableAsserts) {
+      return;
+    }
+
     final Label done = new Label();
     asm.emitJumpIfNoAsserts(done);
 
@@ -2710,6 +2821,10 @@
 
   @override
   visitAssertBlock(AssertBlock node) {
+    if (!enableAsserts) {
+      return;
+    }
+
     final Label done = new Label();
     asm.emitJumpIfNoAsserts(done);
 
@@ -2793,9 +2908,9 @@
     // Front-end inserts implicit cast (type check) which ensures that
     // result of iterable expression is Iterable<dynamic>.
     asm.emitInterfaceCall(
-        1,
         cp.addInterfaceCall(InvocationKind.getter, iterableIterator,
-            objectTable.getArgDescHandle(1)));
+            objectTable.getArgDescHandle(1)),
+        1);
 
     final iteratorTemp = locals.tempIndexInFrame(node);
     asm.emitPopLocal(iteratorTemp);
@@ -2827,9 +2942,9 @@
     }
 
     asm.emitInterfaceCall(
-        1,
         cp.addInterfaceCall(InvocationKind.method, iteratorMoveNext,
-            objectTable.getArgDescHandle(1)));
+            objectTable.getArgDescHandle(1)),
+        1);
     _genJumpIfFalse(/* negated = */ false, done);
 
     _enterScope(node);
@@ -2838,9 +2953,9 @@
 
     asm.emitPush(iteratorTemp);
     asm.emitInterfaceCall(
-        1,
         cp.addInterfaceCall(InvocationKind.getter, iteratorCurrent,
-            objectTable.getArgDescHandle(1)));
+            objectTable.getArgDescHandle(1)),
+        1);
 
     _genStoreVar(node.variable);
 
@@ -2997,9 +3112,9 @@
           asm.emitPush(temp);
           _genPushConstExpr(expr);
           asm.emitInterfaceCall(
-              2,
-              cp.addInterfaceCall(InvocationKind.method, coreTypes.objectEquals,
-                  equalsArgDesc));
+              cp.addInterfaceCall(
+                  InvocationKind.method, coreTypes.objectEquals, equalsArgDesc),
+              2);
           _genJumpIfTrue(/* negated = */ false, caseLabel);
         }
       }
@@ -3087,13 +3202,13 @@
 
     _saveContextForTryBlock(node);
 
-    return asm.exceptionsTable.enterTryBlock(asm.offsetInWords);
+    return asm.exceptionsTable.enterTryBlock(asm.offset);
   }
 
   /// End try block and start its handler.
   void _endTryBlock(TreeNode node, TryBlock tryBlock) {
-    tryBlock.endPC = asm.offsetInWords;
-    tryBlock.handlerPC = asm.offsetInWords;
+    tryBlock.endPC = asm.offset;
+    tryBlock.handlerPC = asm.offset;
 
     // Exception handlers are reachable although there are no labels or jumps.
     asm.isUnreachable = false;
@@ -3258,11 +3373,17 @@
       if (isCaptured) {
         _genPushContextForVariable(node);
       }
+      int maxInitializerPosition = node.fileOffset;
       if (node.initializer != null) {
+        _startRecordingMaxPosition(node.fileOffset);
         _generateNode(node.initializer);
+        maxInitializerPosition = _endRecordingMaxPosition();
       } else {
         asm.emitPushNull();
       }
+      if (emitLocalVarInfo && !asm.isUnreachable && node.name != null) {
+        _declareLocalVariable(node, maxInitializerPosition + 1);
+      }
       _genStoreVar(node);
     }
   }
diff --git a/pkg/vm/lib/bytecode/local_variable_table.dart b/pkg/vm/lib/bytecode/local_variable_table.dart
new file mode 100644
index 0000000..fc49225
--- /dev/null
+++ b/pkg/vm/lib/bytecode/local_variable_table.dart
@@ -0,0 +1,234 @@
+// Copyright (c) 2019, 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.bytecode.local_variable_table;
+
+import 'bytecode_serialization.dart';
+
+enum LocalVariableEntryKind {
+  invalid,
+  scope,
+  variableDeclaration,
+  contextVariable,
+}
+
+abstract class LocalVariableEntry {
+  static const KindMask = 0x0F;
+  static const IsCapturedFlag = 1 << 4;
+
+  LocalVariableEntryKind get kind;
+  int get flags => 0;
+  final int startPC;
+  void writeContents(BufferedWriter writer);
+
+  LocalVariableEntry(this.startPC);
+}
+
+class Scope extends LocalVariableEntry {
+  int endPC;
+  int contextLevel;
+  int position;
+  int endPosition;
+  final List<VariableDeclaration> variables = <VariableDeclaration>[];
+
+  Scope(int startPC, this.endPC, this.contextLevel, this.position,
+      this.endPosition)
+      : super(startPC);
+
+  @override
+  LocalVariableEntryKind get kind => LocalVariableEntryKind.scope;
+
+  @override
+  void writeContents(BufferedWriter writer) {
+    if (endPC == null) {
+      throw '$this is not closed';
+    }
+    writer.writePackedUInt30(endPC - startPC);
+    writer.writeSLEB128(contextLevel);
+    writer.writePackedUInt30(position + 1);
+    writer.writePackedUInt30(endPosition + 1);
+  }
+
+  Scope.readContents(BufferedReader reader, int startPC) : super(startPC) {
+    endPC = startPC = reader.readPackedUInt30();
+    contextLevel = reader.readSLEB128();
+    position = reader.readPackedUInt30() - 1;
+    endPosition = reader.readPackedUInt30() - 1;
+  }
+
+  @override
+  String toString() =>
+      'scope (pc $startPC-$endPC pos $position-$endPosition context-level $contextLevel)';
+}
+
+class VariableDeclaration extends LocalVariableEntry {
+  bool isCaptured;
+  int index;
+  int name;
+  int type;
+  int position;
+  int initializedPosition;
+
+  VariableDeclaration(int startPC, this.isCaptured, this.index, this.name,
+      this.type, this.position, this.initializedPosition)
+      : super(startPC);
+
+  @override
+  LocalVariableEntryKind get kind => LocalVariableEntryKind.variableDeclaration;
+
+  @override
+  int get flags => (isCaptured ? LocalVariableEntry.IsCapturedFlag : 0);
+
+  @override
+  void writeContents(BufferedWriter writer) {
+    writer.writeSLEB128(index);
+    writer.writePackedUInt30(name);
+    writer.writePackedUInt30(type);
+    writer.writePackedUInt30(position + 1);
+    writer.writePackedUInt30(initializedPosition + 1);
+  }
+
+  VariableDeclaration.readContents(
+      BufferedReader reader, int startPC, int flags)
+      : super(startPC) {
+    isCaptured = (flags & LocalVariableEntry.IsCapturedFlag) != 0;
+    index = reader.readSLEB128();
+    name = reader.readPackedUInt30();
+    type = reader.readPackedUInt30();
+    position = reader.readPackedUInt30() - 1;
+    initializedPosition = reader.readPackedUInt30() - 1;
+  }
+
+  @override
+  String toString() =>
+      'variable $index${isCaptured ? ' (captured)' : ''} pc $startPC, name CP#$name, type CP#$type, pos $position, init-pos $initializedPosition';
+}
+
+class ContextVariable extends LocalVariableEntry {
+  int index;
+
+  ContextVariable(int startPC, this.index) : super(startPC);
+
+  @override
+  LocalVariableEntryKind get kind => LocalVariableEntryKind.contextVariable;
+
+  @override
+  void writeContents(BufferedWriter writer) {
+    writer.writeSLEB128(index);
+  }
+
+  ContextVariable.readContents(BufferedReader reader, int startPC)
+      : super(startPC) {
+    index = reader.readSLEB128();
+  }
+
+  @override
+  String toString() => 'context variable $index';
+}
+
+/// Keeps information about declared local variables.
+class LocalVariableTable {
+  final scopes = <Scope>[];
+  final activeScopes = <Scope>[];
+  ContextVariable contextVariable;
+
+  LocalVariableTable();
+
+  void enterScope(int pc, int contextLevel, int position) {
+    final scope = new Scope(pc, null, contextLevel, position, null);
+    activeScopes.add(scope);
+    scopes.add(scope);
+  }
+
+  void declareVariable(int pc, bool isCaptured, int index, int nameCpIndex,
+      int typeCpIndex, int position, int initializedPosition) {
+    final variable = new VariableDeclaration(pc, isCaptured, index, nameCpIndex,
+        typeCpIndex, position, initializedPosition);
+    activeScopes.last.variables.add(variable);
+  }
+
+  void leaveScope(int pc, int endPosition) {
+    final scope = activeScopes.removeLast();
+    scope.endPC = pc;
+    scope.endPosition = endPosition;
+    if (scope.variables.isEmpty) {
+      scopes.remove(scope);
+    }
+  }
+
+  void recordContextVariable(int pc, int index) {
+    assert(contextVariable == null);
+    contextVariable = new ContextVariable(pc, index);
+  }
+
+  bool get isEmpty => scopes.isEmpty && contextVariable == null;
+
+  bool get isNotEmpty => !isEmpty;
+
+  bool get hasActiveScopes => activeScopes.isNotEmpty;
+
+  List<LocalVariableEntry> getEntries() {
+    final entries = <LocalVariableEntry>[];
+    if (contextVariable != null) {
+      entries.add(contextVariable);
+    }
+    for (Scope scope in scopes) {
+      entries.add(scope);
+      entries.addAll(scope.variables);
+    }
+    return entries;
+  }
+
+  void write(BufferedWriter writer) {
+    final entries = getEntries();
+    writer.writePackedUInt30(entries.length);
+    final encodeStartPC = new SLEB128DeltaEncoder();
+    for (var entry in entries) {
+      writer.writeByte(entry.kind.index | entry.flags);
+      encodeStartPC.write(writer, entry.startPC);
+      entry.writeContents(writer);
+    }
+  }
+
+  LocalVariableTable.read(BufferedReader reader) {
+    final int numEntries = reader.readPackedUInt30();
+    final decodeStartPC = new SLEB128DeltaDecoder();
+    Scope scope;
+    for (int i = 0; i < numEntries; ++i) {
+      final int kindAndFlags = reader.readByte();
+      final LocalVariableEntryKind kind = LocalVariableEntryKind
+          .values[kindAndFlags & LocalVariableEntry.KindMask];
+      final int flags = kindAndFlags & ~LocalVariableEntry.KindMask;
+      final int startPC = decodeStartPC.read(reader);
+      switch (kind) {
+        case LocalVariableEntryKind.scope:
+          scope = new Scope.readContents(reader, startPC);
+          scopes.add(scope);
+          break;
+        case LocalVariableEntryKind.variableDeclaration:
+          scope.variables.add(
+              new VariableDeclaration.readContents(reader, startPC, flags));
+          break;
+        case LocalVariableEntryKind.contextVariable:
+          contextVariable = new ContextVariable.readContents(reader, startPC);
+          break;
+        default:
+          throw 'Unexpected entry kind ${kind}';
+      }
+    }
+  }
+
+  Map<int, String> getBytecodeAnnotations() {
+    final map = <int, String>{};
+    for (var entry in getEntries()) {
+      final pc = entry.startPC;
+      if (map[pc] == null) {
+        map[pc] = entry.toString();
+      } else {
+        map[pc] = "${map[pc]}; $entry";
+      }
+    }
+    return map;
+  }
+}
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index 5d3862d..c321b4e 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -24,6 +24,7 @@
       <TreeNode, VariableDeclaration>{};
   final Map<ForInStatement, VariableDeclaration> _capturedIteratorVars =
       <ForInStatement, VariableDeclaration>{};
+  final bool enableAsserts;
 
   Scope _currentScope;
   Frame _currentFrame;
@@ -175,7 +176,7 @@
   List<VariableDeclaration> get sortedNamedParameters =>
       _currentFrame.sortedNamedParameters;
 
-  LocalVariables(Member node) {
+  LocalVariables(Member node, this.enableAsserts) {
     final scopeBuilder = new _ScopeBuilder(this);
     node.accept(scopeBuilder);
 
@@ -608,7 +609,18 @@
   }
 
   @override
+  visitAssertStatement(AssertStatement node) {
+    if (!locals.enableAsserts) {
+      return;
+    }
+    super.visitAssertStatement(node);
+  }
+
+  @override
   visitAssertBlock(AssertBlock node) {
+    if (!locals.enableAsserts) {
+      return;
+    }
     _visitWithScope(node);
   }
 
@@ -838,6 +850,9 @@
           (_currentScope.tempsUsed + count) - _currentFrame.temporaries.length;
       int local = _currentScope.localsUsed;
       _currentScope.localsUsed += newSlots;
+      if (_currentScope.localsUsed > localVariableIndexLimit) {
+        throw new LocalVariableIndexOverflowException();
+      }
       _updateFrameSize();
       for (int i = 0; i < newSlots; i++) {
         _currentFrame.temporaries.add(local + i);
@@ -1056,7 +1071,18 @@
   }
 
   @override
+  visitAssertStatement(AssertStatement node) {
+    if (!locals.enableAsserts) {
+      return;
+    }
+    super.visitAssertStatement(node);
+  }
+
+  @override
   visitAssertBlock(AssertBlock node) {
+    if (!locals.enableAsserts) {
+      return;
+    }
     _visit(node, scope: true);
   }
 
diff --git a/pkg/vm/lib/bytecode/ngrams.dart b/pkg/vm/lib/bytecode/ngrams.dart
index 040b51b..54e028b 100644
--- a/pkg/vm/lib/bytecode/ngrams.dart
+++ b/pkg/vm/lib/bytecode/ngrams.dart
@@ -16,16 +16,9 @@
 
 class NGram {
   List<Instruction> instrs;
-  List<int> _words;
   BytecodeDisassembler _disassembler;
 
-  NGram(List<int> words, {bool mergePushes = false}) {
-    _disassembler = new BytecodeDisassembler();
-    _words = words;
-    instrs = new List<Instruction>(words.length);
-    for (int i = 0; i < instrs.length; i++) {
-      instrs[i] = _disassembler.decodeInstruction(words[i]);
-    }
+  NGram(this.instrs, {bool mergePushes = false}) {
     if (mergePushes) {
       _mergePushes(instrs);
     }
@@ -48,7 +41,7 @@
   String toString() {
     StringBuffer out = new StringBuffer();
     for (var instr in instrs) {
-      _disassembler.writeInstruction(out, 0, instr);
+      _disassembler.writeInstruction(out, instr);
     }
     return out.toString();
   }
@@ -57,7 +50,7 @@
   static void _mergePushes(List<Instruction> instrs) {
     for (int i = 0; i < instrs.length; i++) {
       if (isPush(instrs[i].opcode)) {
-        instrs[i] = new Instruction(Opcode.kPush, <int>[0]);
+        instrs[i] = new Instruction(Opcode.kPush, false, <int>[0], 0);
       }
     }
   }
@@ -104,14 +97,15 @@
 }
 
 class NGramReader {
-  Uint32List _words;
+  List<Instruction> _instructions;
 
   Map<NGram, int> _ngramCounts = <NGram, int>{};
 
   NGramReader(String traceFilename) {
     File traceFile = File(traceFilename);
-    Uint8List data = traceFile.readAsBytesSync();
-    _words = Uint32List.view(data.buffer);
+    Uint8List bytecode = traceFile.readAsBytesSync();
+    final disassembler = new BytecodeDisassembler();
+    _instructions = disassembler.decode(bytecode);
   }
 
   Map<NGram, int> get ngramCounts => _ngramCounts;
@@ -119,8 +113,9 @@
   void readAllNGrams(int windowSize,
       {bool basicBlocks: true, bool mergePushes: false}) {
     int offset = 0;
-    while (offset + windowSize < _words.length) {
-      Uint32List window = _words.sublist(offset, offset + windowSize);
+    while (offset + windowSize < _instructions.length) {
+      List<Instruction> window =
+          _instructions.sublist(offset, offset + windowSize);
       offset += 1;
       NGram ngram = new NGram(window, mergePushes: mergePushes);
       if (basicBlocks && ngram.controlFlowIsNotLast) {
diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart
index 9c3f530..80324cc 100644
--- a/pkg/vm/lib/bytecode/object_table.dart
+++ b/pkg/vm/lib/bytecode/object_table.dart
@@ -1379,7 +1379,9 @@
     ObjectHandle handle = _nodeCache[node];
     if (handle == null) {
       handle = node.accept(_nodeVisitor);
-      _nodeCache[node] = handle;
+      if (handle != null && handle.isCacheable) {
+        _nodeCache[node] = handle;
+      }
     } else {
       ++handle._useCount;
     }
diff --git a/pkg/vm/lib/bytecode/source_positions.dart b/pkg/vm/lib/bytecode/source_positions.dart
index 22ed3b1..f0bef3d 100644
--- a/pkg/vm/lib/bytecode/source_positions.dart
+++ b/pkg/vm/lib/bytecode/source_positions.dart
@@ -4,7 +4,14 @@
 
 library vm.bytecode.source_positions;
 
-import 'bytecode_serialization.dart' show BufferedWriter, BufferedReader;
+import 'bytecode_serialization.dart'
+    show
+        BufferedWriter,
+        BufferedReader,
+        PackedUInt30DeltaEncoder,
+        PackedUInt30DeltaDecoder,
+        SLEB128DeltaEncoder,
+        SLEB128DeltaDecoder;
 
 /// Maintains mapping between bytecode instructions and source positions.
 class SourcePositions {
@@ -53,41 +60,3 @@
         new MapEntry(pc, 'source position $fileOffset'));
   }
 }
-
-class PackedUInt30DeltaEncoder {
-  int _last = 0;
-
-  void write(BufferedWriter write, int value) {
-    write.writePackedUInt30(value - _last);
-    _last = value;
-  }
-}
-
-class PackedUInt30DeltaDecoder {
-  int _last = 0;
-
-  int read(BufferedReader reader) {
-    int value = reader.readPackedUInt30() + _last;
-    _last = value;
-    return value;
-  }
-}
-
-class SLEB128DeltaEncoder {
-  int _last = 0;
-
-  void write(BufferedWriter writer, int value) {
-    writer.writeSLEB128(value - _last);
-    _last = value;
-  }
-}
-
-class SLEB128DeltaDecoder {
-  int _last = 0;
-
-  int read(BufferedReader reader) {
-    int value = reader.readSLEB128() + _last;
-    _last = value;
-    return value;
-  }
-}
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index 6685160..bce696d 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -56,6 +56,9 @@
       help:
           'Enable global type flow analysis and related transformations in AOT mode.',
       defaultsTo: false)
+  ..addFlag('protobuf-tree-shaker',
+      help: 'Enable protobuf tree shaker transformation in AOT mode.',
+      defaultsTo: false)
   ..addFlag('link-platform',
       help:
           'When in batch mode, link platform kernel file into result kernel file.'
@@ -110,6 +113,9 @@
           'improved speed.',
       defaultsTo: false,
       hide: true)
+  ..addFlag('track-widget-creation',
+      help: 'Run a kernel transformer to track creation locations for widgets.',
+      defaultsTo: false)
   ..addMultiOption('enable-experiment',
       help: 'Comma separated list of experimental features, eg set-literals.',
       hide: true);
@@ -316,7 +322,10 @@
       return false;
     }
 
-    compilerOptions.target = createFrontEndTarget(options['target']);
+    compilerOptions.target = createFrontEndTarget(
+      options['target'],
+      trackWidgetCreation: options['track-widget-creation'],
+    );
     if (compilerOptions.target == null) {
       print('Failed to create front-end target ${options['target']}.');
       return false;
@@ -351,7 +360,8 @@
           _mainSource, compilerOptions,
           aot: options['aot'],
           useGlobalTypeFlowAnalysis: options['tfa'],
-          environmentDefines: environmentDefines));
+          environmentDefines: environmentDefines,
+          useProtobufTreeShaker: options['protobuf-tree-shaker']));
     }
     if (component != null) {
       if (transformer != null) {
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 452e2ca..0dd2962 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -113,6 +113,9 @@
   args.addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: false);
   args.addFlag('emit-bytecode-source-positions',
       help: 'Emit source positions in bytecode', defaultsTo: false);
+  args.addFlag('emit-bytecode-local-var-info',
+      help: 'Emit information about local variables in bytecode',
+      defaultsTo: false);
   args.addFlag('emit-bytecode-annotations',
       help: 'Emit Dart annotations in bytecode', defaultsTo: false);
   args.addFlag('drop-ast',
@@ -166,6 +169,7 @@
   final bool genBytecode = options['gen-bytecode'];
   final bool emitBytecodeSourcePositions =
       options['emit-bytecode-source-positions'];
+  final bool emitBytecodeLocalVarInfo = options['emit-bytecode-local-var-info'];
   final bool emitBytecodeAnnotations = options['emit-bytecode-annotations'];
   final bool dropAST = options['drop-ast'];
   final bool useFutureBytecodeFormat = options['use-future-bytecode-format'];
@@ -226,6 +230,7 @@
       environmentDefines: environmentDefines,
       genBytecode: genBytecode,
       emitBytecodeSourcePositions: emitBytecodeSourcePositions,
+      emitBytecodeLocalVarInfo: emitBytecodeLocalVarInfo,
       emitBytecodeAnnotations: emitBytecodeAnnotations,
       dropAST: dropAST && !splitOutputByPackages,
       useFutureBytecodeFormat: useFutureBytecodeFormat,
@@ -264,7 +269,9 @@
       outputFileName,
       environmentDefines: environmentDefines,
       genBytecode: genBytecode,
+      enableAsserts: enableAsserts,
       emitBytecodeSourcePositions: emitBytecodeSourcePositions,
+      emitBytecodeLocalVarInfo: emitBytecodeLocalVarInfo,
       emitBytecodeAnnotations: emitBytecodeAnnotations,
       dropAST: dropAST,
       showBytecodeSizeStat: showBytecodeSizeStat,
@@ -286,6 +293,7 @@
     Map<String, String> environmentDefines,
     bool genBytecode: false,
     bool emitBytecodeSourcePositions: false,
+    bool emitBytecodeLocalVarInfo: false,
     bool emitBytecodeAnnotations: false,
     bool dropAST: false,
     bool useFutureBytecodeFormat: false,
@@ -317,7 +325,9 @@
   if (genBytecode && !errorDetector.hasCompilationErrors && component != null) {
     await runWithFrontEndCompilerContext(source, options, component, () {
       generateBytecode(component,
+          enableAsserts: enableAsserts,
           emitSourcePositions: emitBytecodeSourcePositions,
+          emitLocalVarInfo: emitBytecodeLocalVarInfo,
           emitAnnotations: emitBytecodeAnnotations,
           useFutureBytecodeFormat: useFutureBytecodeFormat,
           environmentDefines: environmentDefines);
@@ -532,11 +542,13 @@
 }
 
 /// Create front-end target with given name.
-Target createFrontEndTarget(String targetName) {
+Target createFrontEndTarget(String targetName,
+    {bool trackWidgetCreation = false}) {
   // Make sure VM-specific targets are available.
   installAdditionalTargets();
 
-  final TargetFlags targetFlags = new TargetFlags();
+  final TargetFlags targetFlags =
+      new TargetFlags(trackWidgetCreation: trackWidgetCreation);
   return getTarget(targetName, targetFlags);
 }
 
@@ -612,6 +624,10 @@
   }
   // file:///a/b/x/y/main.dart -> package:x.y/main.dart
   for (var line in packages) {
+    if (line.isEmpty || line.startsWith("#")) {
+      continue;
+    }
+
     final colon = line.indexOf(':');
     if (colon == -1) {
       continue;
@@ -646,7 +662,9 @@
   String outputFileName, {
   Map<String, String> environmentDefines,
   bool genBytecode: false,
+  bool enableAsserts: true,
   bool emitBytecodeSourcePositions: false,
+  bool emitBytecodeLocalVarInfo: false,
   bool emitBytecodeAnnotations: false,
   bool dropAST: false,
   bool showBytecodeSizeStat: false,
@@ -678,6 +696,14 @@
     BytecodeSizeStatistics.reset();
   }
 
+  ClassHierarchy hierarchy;
+  if (genBytecode) {
+    // Calculating class hierarchy is an expensive operation.
+    // Calculate it once and reuse while generating bytecode for each package.
+    hierarchy =
+        new ClassHierarchy(component, onAmbiguousSupertypes: (cls, a, b) {});
+  }
+
   await runWithFrontEndCompilerContext(source, compilerOptions, component,
       () async {
     for (String package in packages) {
@@ -698,7 +724,10 @@
             .toList();
         generateBytecode(component,
             libraries: libraries,
+            hierarchy: hierarchy,
+            enableAsserts: enableAsserts,
             emitSourcePositions: emitBytecodeSourcePositions,
+            emitLocalVarInfo: emitBytecodeLocalVarInfo,
             emitAnnotations: emitBytecodeAnnotations,
             useFutureBytecodeFormat: useFutureBytecodeFormat,
             environmentDefines: environmentDefines);
diff --git a/pkg/vm/lib/target/flutter.dart b/pkg/vm/lib/target/flutter.dart
index 1faa9a2..02673e7 100644
--- a/pkg/vm/lib/target/flutter.dart
+++ b/pkg/vm/lib/target/flutter.dart
@@ -3,7 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 library vm.target.flutter;
 
+import 'package:kernel/ast.dart' show Component, Library;
+import 'package:kernel/core_types.dart' show CoreTypes;
 import 'package:kernel/target/targets.dart';
+import 'package:kernel/transformations/track_widget_constructor_locations.dart';
 import 'package:vm/target/vm.dart' show VmTarget;
 
 class FlutterTarget extends VmTarget {
@@ -41,4 +44,16 @@
         'dart:ui',
         'dart:vmservice_io',
       ];
+
+  @override
+  void performPreConstantEvaluationTransformations(
+      Component component,
+      CoreTypes coreTypes,
+      List<Library> libraries,
+      DiagnosticReporter diagnosticReporter,
+      {void logger(String msg)}) {
+    if (flags.trackWidgetCreation) {
+      new WidgetCreatorTracker().transform(component, libraries);
+    }
+  }
 }
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 4b40caf..d61ca95 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -275,9 +275,10 @@
   }
 
   bool _isStatic(Expression node) {
-    if (node is! StaticGet) return false;
-
-    return (node as StaticGet).target is Procedure;
+    if (node is StaticGet) {
+      return node.target is Procedure;
+    }
+    return node is ConstantExpression;
   }
 }
 
diff --git a/pkg/vm/lib/transformations/pragma.dart b/pkg/vm/lib/transformations/pragma.dart
index 0fa7432..ff3431b 100644
--- a/pkg/vm/lib/transformations/pragma.dart
+++ b/pkg/vm/lib/transformations/pragma.dart
@@ -50,14 +50,10 @@
     if (annotation is ConstantExpression) {
       Constant constant = annotation.constant;
       if (constant is InstanceConstant) {
-        if (constant.classNode == coreTypes.pragmaClass) {
+        if (constant.classReference.node == coreTypes.pragmaClass) {
           pragmaConstant = constant;
         }
-      } else if (constant is UnevaluatedConstant) {
-        throw 'Error: unevaluated constant $constant';
       }
-    } else {
-      throw 'Error: non-constant annotation $annotation';
     }
     if (pragmaConstant == null) return null;
 
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 23f8d8b..724a2e3 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -592,8 +592,7 @@
           param.defaultValue =
               constantAllocationCollector.typeFor(initializer.constant);
         } else {
-          param.defaultValue =
-              new Type.fromStatic(initializer.getStaticType(_environment));
+          param.defaultValue = _staticType(initializer);
         }
       } else {
         param.defaultValue = _nullType;
@@ -673,8 +672,18 @@
     }
   }
 
+  DartType _staticDartType(Expression node) {
+    // TODO(dartbug.com/34496): Remove this try/catch once
+    // getStaticType() is reliable.
+    try {
+      return node.getStaticType(_environment);
+    } catch (e) {
+      return const DynamicType();
+    }
+  }
+
   Type _staticType(Expression node) =>
-      new Type.fromStatic(node.getStaticType(_environment));
+      new Type.fromStatic(_staticDartType(node));
 
   Type _cachedBoolType;
   Type get _boolType =>
@@ -772,7 +781,7 @@
   TypeExpr visitConditionalExpression(ConditionalExpression node) {
     _addUse(_visit(node.condition));
 
-    Join v = new Join(null, node.getStaticType(_environment));
+    Join v = new Join(null, _staticDartType(node));
     _summary.add(v);
     v.values.add(_visit(node.then));
     v.values.add(_visit(node.otherwise));
@@ -926,7 +935,7 @@
         return new Type.nullable(_boolType);
       }
       if (node.name.name == 'call') {
-        final recvType = node.receiver.getStaticType(_environment);
+        final recvType = _staticDartType(node.receiver);
         if ((recvType is FunctionType) ||
             (recvType == _environment.rawFunctionType)) {
           // Call to a Function.
diff --git a/pkg/vm/lib/v8_snapshot_profile.dart b/pkg/vm/lib/v8_snapshot_profile.dart
index ec01774..efda4c1 100644
--- a/pkg/vm/lib/v8_snapshot_profile.dart
+++ b/pkg/vm/lib/v8_snapshot_profile.dart
@@ -85,9 +85,37 @@
     Expect.equals(snapshot["node_count"], _parseNodes(top["nodes"]));
     Expect.equals(snapshot["edge_count"], _parseEdges(top["edges"]));
 
+    _verifyRoot();
+
     _calculateFromEdges();
   }
 
+  void _verifyRoot() {
+    // HeapSnapshotWorker.HeapSnapshot.calculateDistances (from HeapSnapshot.js)
+    // assumes that the root does not have more than one edge to any other node
+    // (most likely an oversight).
+    final Set<int> roots = <int>{};
+    for (final edge in _toEdges[root]) {
+      final int to = edge.nodeOffset;
+      Expect.isTrue(!roots.contains(to));
+      roots.add(to);
+    }
+
+    // Check that all nodes are reachable from the root (offset 0).
+    final Set<int> enqueued = {root};
+    final dfs = <int>[root];
+    while (!dfs.isEmpty) {
+      final next = dfs.removeLast();
+      for (final edge in _toEdges[next]) {
+        if (!enqueued.contains(edge.nodeOffset)) {
+          enqueued.add(edge.nodeOffset);
+          dfs.add(edge.nodeOffset);
+        }
+      }
+    }
+    Expect.equals(enqueued.length, nodeCount);
+  }
+
   void _parseMetadata(Map meta) {
     final List nodeFields = meta["node_fields"];
     nodeFields.forEach(_nodeFields.add);
@@ -160,7 +188,8 @@
         final int nameOrIndex = edges[edgeOffset + nameOrIndexIndex];
         if (_edgeTypes[type] == "property") {
           Expect.isTrue(0 <= nameOrIndex && nameOrIndex < _strings.length);
-        } else if (_edgeTypes[type] == "element") {
+        } else if (_edgeTypes[type] == "element" ||
+            _edgeTypes[type] == "context") {
           Expect.isTrue(nameOrIndex >= 0);
         }
 
diff --git a/pkg/vm/test/common_test_utils.dart b/pkg/vm/test/common_test_utils.dart
index 9a496a8..755524b 100644
--- a/pkg/vm/test/common_test_utils.dart
+++ b/pkg/vm/test/common_test_utils.dart
@@ -41,7 +41,6 @@
   final options = new CompilerOptions()
     ..target = target
     ..linkedDependencies = <Uri>[platformKernel]
-    ..environmentDefines = <String, String>{}
     ..onDiagnostic = (DiagnosticMessage message) {
       fail("Compilation error: ${message.plainTextFormatted.join('\n')}");
     };
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index 5310517..a56d500 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -83,11 +83,12 @@
           new StreamController<List<int>>();
       final ReceivePort compileCalled = new ReceivePort();
       when(compiler.compile(any, any, generator: anyNamed('generator')))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         expect(invocation.positionalArguments[0], equals('server.dart'));
         expect(
             invocation.positionalArguments[1]['sdk-root'], equals('sdkroot'));
         compileCalled.sendPort.send(true);
+        return true;
       });
 
       Future<int> result = starter(
@@ -116,11 +117,12 @@
           new StreamController<List<int>>();
       final ReceivePort compileCalled = new ReceivePort();
       when(compiler.compile(any, any, generator: anyNamed('generator')))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         expect(invocation.positionalArguments[0], equals('server.dart'));
         expect(
             invocation.positionalArguments[1]['sdk-root'], equals('sdkroot'));
         compileCalled.sendPort.send(true);
+        return true;
       });
 
       Future<int> result = starter(
@@ -141,12 +143,13 @@
       final ReceivePort compileCalled = new ReceivePort();
       int counter = 1;
       when(compiler.compile(any, any, generator: anyNamed('generator')))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         expect(invocation.positionalArguments[0],
             equals('server${counter++}.dart'));
         expect(
             invocation.positionalArguments[1]['sdk-root'], equals('sdkroot'));
         compileCalled.sendPort.send(true);
+        return true;
       });
 
       Future<int> result = starter(
@@ -180,7 +183,7 @@
       final ReceivePort recompileCalled = new ReceivePort();
 
       when(compiler.recompileDelta(entryPoint: null))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         recompileCalled.sendPort.send(true);
       });
       Future<int> result = starter(
@@ -208,7 +211,7 @@
       final ReceivePort recompileCalled = new ReceivePort();
 
       when(compiler.recompileDelta(entryPoint: 'file2.dart'))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         recompileCalled.sendPort.send(true);
       });
       Future<int> result = starter(
@@ -275,7 +278,7 @@
       final ReceivePort recompileCalled = new ReceivePort();
 
       when(compiler.recompileDelta(entryPoint: null))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         recompileCalled.sendPort.send(true);
       });
       Future<int> result = starter(
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 2b714ec..b223aaf 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -296,7 +296,7 @@
       await compileAndSerialize(mainDill, libDill, compiler);
 
       var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
-      list.writeAsStringSync("#@dill\n../main.dart.dill\n../lib.dart.dill\n");
+      list.writeAsStringSync("#@dill\nmain.dart.dill\nlib.dart.dill\n");
       Directory runFrom = new Directory(dir.path + "/runFrom")..createSync();
       vm = await Process.start(Platform.resolvedExecutable, <String>[list.path],
           workingDirectory: runFrom.path);
diff --git a/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
index 66d662e..ec3e99d 100644
--- a/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
+++ b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
@@ -52,7 +52,7 @@
 
     ProcessResult result =
         Process.runSync(Platform.resolvedExecutable, [file.path]);
-    expect(result.exitCode, 0);
+    expect(result.exitCode, 0, reason: '${result.stderr}\n${result.stdout}');
   } finally {
     if (file.existsSync()) {
       file.deleteSync();
diff --git a/pkg/vm/test/transformations/type_flow/annotation_matcher.dart b/pkg/vm/test/transformations/type_flow/annotation_matcher.dart
new file mode 100644
index 0000000..2b7f278
--- /dev/null
+++ b/pkg/vm/test/transformations/type_flow/annotation_matcher.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2018, 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:kernel/ast.dart';
+import 'package:kernel/core_types.dart';
+import 'package:vm/transformations/type_flow/utils.dart';
+import 'package:vm/transformations/pragma.dart';
+
+// Since we don't run the constants transformation in this test, we can't
+// recognize all pragma annotations precisely. Instead, we pattern match on
+// annotations which look like a pragma and assume that their options field
+// evaluates to true.
+class ExpressionPragmaAnnotationParser extends PragmaAnnotationParser {
+  final CoreTypes coreTypes;
+
+  ExpressionPragmaAnnotationParser(this.coreTypes);
+
+  ParsedPragma parsePragma(Expression annotation) {
+    assertx(annotation is! ConstantExpression);
+
+    String pragmaName;
+    Expression options;
+
+    if (annotation is ConstructorInvocation) {
+      if (annotation.constructedType.classNode != coreTypes.pragmaClass) {
+        return null;
+      }
+
+      if (annotation.arguments.types.length != 0 ||
+          (annotation.arguments.positional.length != 1 &&
+              annotation.arguments.positional.length != 2) ||
+          annotation.arguments.named.length != 0) {
+        throw "Cannot evaluate pragma annotation $annotation";
+      }
+
+      var arguments = annotation.arguments.positional;
+      var nameArg = arguments[0];
+      if (nameArg is StringLiteral) {
+        pragmaName = nameArg.value;
+      } else {
+        return null;
+      }
+
+      options = arguments.length > 1 ? arguments[1] : new NullLiteral();
+    }
+
+    switch (pragmaName) {
+      case kEntryPointPragmaName:
+        // We ignore the option because we can't properly evaluate it, assume
+        // it's true.
+        return new ParsedEntryPointPragma(PragmaEntryPointType.Default);
+      case kExactResultTypePragmaName:
+        if (options is TypeLiteral) {
+          return new ParsedResultTypeByTypePragma(options.type);
+        } else if (options is StringLiteral) {
+          return new ParsedResultTypeByPathPragma(options.value);
+        }
+        throw "Could not recognize option to $kExactResultTypePragmaName";
+      default:
+        return null;
+    }
+  }
+}
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
index 4ab863b..022c7e1 100644
--- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -9,11 +9,10 @@
 import 'package:kernel/core_types.dart';
 import 'package:kernel/type_environment.dart';
 import 'package:test/test.dart';
-import 'package:vm/transformations/pragma.dart'
-    show ConstantPragmaAnnotationParser;
 import 'package:vm/transformations/type_flow/native_code.dart';
 import 'package:vm/transformations/type_flow/summary_collector.dart';
 import 'package:vm/transformations/type_flow/analysis.dart';
+import 'annotation_matcher.dart';
 import 'package:kernel/target/targets.dart';
 
 import '../../common_test_utils.dart';
@@ -32,7 +31,7 @@
             hierarchy,
             new EmptyEntryPointsListener(),
             new NativeCodeOracle(
-                null, new ConstantPragmaAnnotationParser(coreTypes)),
+                null, new ExpressionPragmaAnnotationParser(coreTypes)),
             new GenericInterfacesInfoImpl(hierarchy));
 
   String print(TreeNode node) {
diff --git a/pkg/vm/test/transformations/type_flow/transformer_test.dart b/pkg/vm/test/transformations/type_flow/transformer_test.dart
index 4d1effb..d031f10 100644
--- a/pkg/vm/test/transformations/type_flow/transformer_test.dart
+++ b/pkg/vm/test/transformations/type_flow/transformer_test.dart
@@ -11,6 +11,7 @@
 import 'package:test/test.dart';
 import 'package:vm/transformations/type_flow/transformer.dart'
     show transformComponent;
+import 'annotation_matcher.dart';
 
 import '../../common_test_utils.dart';
 
@@ -23,7 +24,8 @@
 
   final coreTypes = new CoreTypes(component);
 
-  component = transformComponent(target, coreTypes, component);
+  component = transformComponent(target, coreTypes, component,
+      new ExpressionPragmaAnnotationParser(coreTypes));
 
   final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
 
diff --git a/pkg/vm/testcases/bytecode/asserts.dart.expect b/pkg/vm/testcases/bytecode/asserts.dart.expect
index de42a48..8bfc0e9 100644
--- a/pkg/vm/testcases/bytecode/asserts.dart.expect
+++ b/pkg/vm/testcases/bytecode/asserts.dart.expect
@@ -26,7 +26,7 @@
   PushInt              0
   PushInt              0
   PushNull
-  DirectCall           3, CP#0
+  DirectCall           CP#0, 3
   Drop1
 L1:
   PushNull
@@ -48,14 +48,14 @@
   CheckStack           0
   JumpIfNoAsserts      L1
   Push                 FP[-6]
-  DynamicCall          1, CP#1
+  DynamicCall          CP#1, 1
   AssertBoolean        0
   JumpIfTrue           L1
   PushInt              0
   PushInt              0
   Push                 FP[-5]
-  DynamicCall          1, CP#2
-  DirectCall           3, CP#3
+  DynamicCall          CP#2, 1
+  DirectCall           CP#3, 3
   Drop1
 L1:
   PushNull
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index cce2837..4805482 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -101,7 +101,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  DirectCall           1, CP#8
+  DirectCall           CP#8, 1
   Drop1
   StoreContextVar      0, 1
   Push                 r0
@@ -145,27 +145,27 @@
   StoreContextVar      0, 8
   Push                 r0
   LoadContextVar       0, 8
-  DirectCall           1, CP#29
+  DirectCall           CP#29, 1
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  DirectCall           1, CP#31
+  DirectCall           CP#31, 1
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  DirectCall           1, CP#33
+  DirectCall           CP#33, 1
   StoreContextVar      0, 4
   Push                 r0
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 8
-  DynamicCall          2, CP#36
+  DynamicCall          CP#36, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InterfaceCall        1, CP#37
+  InterfaceCall        CP#37, 1
   ReturnTOS
 
 }
@@ -204,7 +204,7 @@
   LoadContextVar       0, 4
   Push                 r4
   LoadContextVar       0, 8
-  DirectCall           4, CP#12
+  DirectCall           CP#12, 4
   PopLocal             r8
   PushNull
   ReturnTOS
@@ -221,7 +221,7 @@
   LoadContextVar       0, 1
   Push                 r4
   LoadContextVar       0, 2
-  DirectCall           2, CP#14
+  DirectCall           CP#14, 2
   Drop1
   PushNull
   ReturnTOS
@@ -244,7 +244,7 @@
   LoadContextVar       0, 1
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#17
+  InterfaceCall        CP#17, 3
   Drop1
   Jump                 L3
 L3:
@@ -275,7 +275,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  DirectCall           1, CP#2
+  DirectCall           CP#2, 1
   Drop1
   StoreContextVar      0, 0
   Push                 r0
@@ -312,22 +312,22 @@
   StoreFieldTOS        CP#6
   PopLocal             r6
   Push                 r6
-  DirectCall           1, CP#23
+  DirectCall           CP#23, 1
   PopLocal             r3
   Push                 r6
-  DirectCall           1, CP#25
+  DirectCall           CP#25, 1
   PopLocal             r4
   Push                 r6
-  DirectCall           1, CP#27
+  DirectCall           CP#27, 1
   PopLocal             r5
   Push                 r0
   LoadContextVar       0, 0
   Push                 r6
-  DynamicCall          2, CP#30
+  DynamicCall          CP#30, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 0
-  InterfaceCall        1, CP#31
+  InterfaceCall        CP#31, 1
   ReturnTOS
 }
 ConstantPool {
@@ -393,7 +393,7 @@
   LoadContextVar       0, 0
   Push                 r4
   LoadContextVar       0, 1
-  DirectCall           2, CP#8
+  DirectCall           CP#8, 2
   Drop1
   PushNull
   ReturnTOS
@@ -412,7 +412,7 @@
   LoadContextVar       0, 0
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#11
+  InterfaceCall        CP#11, 3
   Drop1
   Jump                 L3
 L3:
@@ -446,7 +446,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  DirectCall           1, CP#2
+  DirectCall           CP#2, 1
   Drop1
   StoreContextVar      0, 2
   Push                 r0
@@ -493,27 +493,27 @@
   StoreContextVar      0, 10
   Push                 r0
   LoadContextVar       0, 10
-  DirectCall           1, CP#27
+  DirectCall           CP#27, 1
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  DirectCall           1, CP#29
+  DirectCall           CP#29, 1
   StoreContextVar      0, 4
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  DirectCall           1, CP#31
+  DirectCall           CP#31, 1
   StoreContextVar      0, 5
   Push                 r0
   LoadContextVar       0, 2
   Push                 r0
   LoadContextVar       0, 10
-  DynamicCall          2, CP#34
+  DynamicCall          CP#34, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 2
-  InterfaceCall        1, CP#35
+  InterfaceCall        CP#35, 1
   ReturnTOS
 }
 ConstantPool {
@@ -589,7 +589,7 @@
   LoadContextVar       0, 5
   Push                 r4
   LoadContextVar       0, 10
-  DirectCall           4, CP#8
+  DirectCall           CP#8, 4
   PopLocal             r8
   PushNull
   ReturnTOS
@@ -617,7 +617,7 @@
   LoadContextVar       0, 5
   Push                 r4
   LoadContextVar       0, 10
-  DirectCall           4, CP#8
+  DirectCall           CP#8, 4
   PopLocal             r9
   PushNull
   ReturnTOS
@@ -632,7 +632,7 @@
   Push                 r4
   LoadContextVar       0, 9
   Push                 r1
-  InterfaceCall        2, CP#10
+  InterfaceCall        CP#10, 2
   StoreContextVar      0, 3
   Jump                 L4
 L4:
@@ -640,7 +640,7 @@
   LoadContextVar       0, 2
   Push                 r4
   LoadContextVar       0, 3
-  DirectCall           2, CP#12
+  DirectCall           CP#12, 2
   Drop1
   PushNull
   ReturnTOS
@@ -663,7 +663,7 @@
   LoadContextVar       0, 2
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#15
+  InterfaceCall        CP#15, 3
   Drop1
   Jump                 L5
 L5:
@@ -700,7 +700,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  DirectCall           1, CP#2
+  DirectCall           CP#2, 1
   Drop1
   StoreContextVar      0, 1
   Push                 r0
@@ -750,27 +750,27 @@
   StoreContextVar      0, 10
   Push                 r0
   LoadContextVar       0, 10
-  DirectCall           1, CP#35
+  DirectCall           CP#35, 1
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  DirectCall           1, CP#37
+  DirectCall           CP#37, 1
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  DirectCall           1, CP#39
+  DirectCall           CP#39, 1
   StoreContextVar      0, 4
   Push                 r0
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 10
-  DynamicCall          2, CP#42
+  DynamicCall          CP#42, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InterfaceCall        1, CP#43
+  InterfaceCall        CP#43, 1
   ReturnTOS
 }
 ConstantPool {
@@ -869,7 +869,7 @@
   LoadContextParent
   LoadContextParent
   LoadContextVar       0, 0
-  InterfaceCall        1, CP#8
+  InterfaceCall        CP#8, 1
   PopLocal             r8
   Push                 r4
   Push                 r8
@@ -879,7 +879,7 @@
   Push                 r4
   LoadContextVar       2, 1
   StoreLocal           r8
-  InterfaceCall        1, CP#10
+  InterfaceCall        CP#10, 1
   JumpIfFalse          L3
   AllocateContext      3, 1
   StoreLocal           r5
@@ -889,7 +889,7 @@
   PopLocal             r4
   Push                 r4
   Push                 r8
-  InterfaceCall        1, CP#12
+  InterfaceCall        CP#12, 1
   StoreContextVar      3, 0
   Push                 r4
   LoadContextParent
@@ -923,7 +923,7 @@
   LoadContextParent
   Push                 r4
   StoreContextVar      0, 6
-  DirectCall           0, CP#14
+  DirectCall           CP#14, 0
   Push                 r4
   LoadContextParent
   LoadContextParent
@@ -939,7 +939,7 @@
   LoadContextParent
   LoadContextParent
   LoadContextVar       0, 10
-  DirectCall           4, CP#16
+  DirectCall           CP#16, 4
   PopLocal             r10
   PushNull
   ReturnTOS
@@ -964,8 +964,8 @@
   LoadContextParent
   LoadContextVar       0, 8
   Push                 r1
-  InterfaceCall        2, CP#18
-  InterfaceCall        2, CP#18
+  InterfaceCall        CP#18, 2
+  InterfaceCall        CP#18, 2
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1024,7 +1024,7 @@
   LoadContextVar       0, 1
   Push                 r4
   LoadContextVar       0, 2
-  DirectCall           2, CP#20
+  DirectCall           CP#20, 2
   Drop1
   PushNull
   ReturnTOS
@@ -1047,7 +1047,7 @@
   LoadContextVar       0, 1
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#23
+  InterfaceCall        CP#23, 3
   Drop1
   Jump                 L10
 L10:
@@ -1087,7 +1087,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  DirectCall           1, CP#2
+  DirectCall           CP#2, 1
   Drop1
   StoreContextVar      0, 3
   Push                 r0
@@ -1152,27 +1152,27 @@
   StoreContextVar      0, 17
   Push                 r0
   LoadContextVar       0, 17
-  DirectCall           1, CP#33
+  DirectCall           CP#33, 1
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 17
-  DirectCall           1, CP#35
+  DirectCall           CP#35, 1
   StoreContextVar      0, 5
   Push                 r0
   Push                 r0
   LoadContextVar       0, 17
-  DirectCall           1, CP#37
+  DirectCall           CP#37, 1
   StoreContextVar      0, 6
   Push                 r0
   LoadContextVar       0, 3
   Push                 r0
   LoadContextVar       0, 17
-  DynamicCall          2, CP#40
+  DynamicCall          CP#40, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 3
-  InterfaceCall        1, CP#41
+  InterfaceCall        CP#41, 1
   ReturnTOS
 }
 ConstantPool {
@@ -1284,7 +1284,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 17
-  DirectCall           4, CP#8
+  DirectCall           CP#8, 4
   PopLocal             r13
   PushNull
   ReturnTOS
@@ -1300,7 +1300,7 @@
   LoadContextParent
   LoadContextVar       0, 14
   Push                 r1
-  InterfaceCall        2, CP#10
+  InterfaceCall        CP#10, 2
   StoreContextVar      1, 0
   Jump                 L3
 Try #2 end:
@@ -1328,7 +1328,7 @@
   Push                 r4
   LoadContextVar       1, 1
   PushConstant         CP#13
-  InterfaceCall        2, CP#14
+  InterfaceCall        CP#14, 2
   JumpIfFalse          L4
   Push                 r4
   LoadContextParent
@@ -1361,7 +1361,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 17
-  DirectCall           4, CP#8
+  DirectCall           CP#8, 4
   PopLocal             r13
   PushNull
   ReturnTOS
@@ -1377,7 +1377,7 @@
   LoadContextParent
   LoadContextVar       0, 15
   Push                 r1
-  InterfaceCall        2, CP#10
+  InterfaceCall        CP#10, 2
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1408,7 +1408,7 @@
   Push                 r9
   StoreContextVar      0, 13
   PushConstant         CP#16
-  DirectCall           1, CP#17
+  DirectCall           CP#17, 1
   Drop1
   Push                 r4
   LoadContextParent
@@ -1435,7 +1435,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 17
-  DirectCall           4, CP#8
+  DirectCall           CP#8, 4
   PopLocal             r12
   PushNull
   ReturnTOS
@@ -1451,7 +1451,7 @@
   LoadContextParent
   LoadContextVar       0, 16
   Push                 r1
-  InterfaceCall        2, CP#10
+  InterfaceCall        CP#10, 2
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1470,7 +1470,7 @@
   LoadContextVar       0, 10
   PopLocal             r4
   PushConstant         CP#16
-  DirectCall           1, CP#17
+  DirectCall           CP#17, 1
   Drop1
   Push                 r4
   LoadContextParent
@@ -1497,7 +1497,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 17
-  DirectCall           4, CP#8
+  DirectCall           CP#8, 4
   PopLocal             r12
   PushNull
   ReturnTOS
@@ -1513,7 +1513,7 @@
   LoadContextParent
   LoadContextVar       0, 16
   Push                 r1
-  InterfaceCall        2, CP#10
+  InterfaceCall        CP#10, 2
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1532,7 +1532,7 @@
   LoadContextVar       0, 10
   PopLocal             r4
   PushConstant         CP#16
-  DirectCall           1, CP#17
+  DirectCall           CP#17, 1
   Drop1
   Push                 r4
   LoadContextParent
@@ -1559,7 +1559,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 17
-  DirectCall           4, CP#8
+  DirectCall           CP#8, 4
   PopLocal             r12
   PushNull
   ReturnTOS
@@ -1575,7 +1575,7 @@
   LoadContextParent
   LoadContextVar       0, 16
   Push                 r1
-  InterfaceCall        2, CP#10
+  InterfaceCall        CP#10, 2
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1591,7 +1591,7 @@
   LoadContextVar       0, 3
   Push                 r4
   LoadContextVar       0, 4
-  DirectCall           2, CP#19
+  DirectCall           CP#19, 2
   Drop1
   PushNull
   ReturnTOS
@@ -1614,7 +1614,7 @@
   LoadContextVar       0, 3
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#21
+  InterfaceCall        CP#21, 3
   Drop1
   Jump                 L12
 L12:
@@ -1739,7 +1739,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  DirectCall           1, CP#5
+  DirectCall           CP#5, 1
   Drop1
   StoreContextVar      1, 0
   Push                 r0
@@ -1786,27 +1786,27 @@
   StoreContextVar      1, 8
   Push                 r0
   LoadContextVar       1, 8
-  DirectCall           1, CP#29
+  DirectCall           CP#29, 1
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       1, 8
-  DirectCall           1, CP#31
+  DirectCall           CP#31, 1
   StoreContextVar      1, 2
   Push                 r0
   Push                 r0
   LoadContextVar       1, 8
-  DirectCall           1, CP#33
+  DirectCall           CP#33, 1
   StoreContextVar      1, 3
   Push                 r0
   LoadContextVar       1, 0
   Push                 r0
   LoadContextVar       1, 8
-  DynamicCall          2, CP#36
+  DynamicCall          CP#36, 2
   Drop1
   Push                 r0
   LoadContextVar       1, 0
-  InterfaceCall        1, CP#37
+  InterfaceCall        CP#37, 1
   ReturnTOS
 
 }
@@ -1871,7 +1871,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       1, 8
-  DirectCall           4, CP#9
+  DirectCall           CP#9, 4
   PopLocal             r11
   PushNull
   ReturnTOS
@@ -1908,7 +1908,7 @@
   MoveSpecial          exception, r8
   MoveSpecial          stackTrace, r9
   PushConstant         CP#12
-  DirectCall           1, CP#13
+  DirectCall           CP#13, 1
   Drop1
   Push                 r8
   Push                 r9
@@ -1921,7 +1921,7 @@
   LoadContextVar       1, 7
   PopLocal             r4
   PushConstant         CP#12
-  DirectCall           1, CP#13
+  DirectCall           CP#13, 1
   Drop1
   Push                 r4
   LoadContextParent
@@ -1932,7 +1932,7 @@
   LoadContextVar       1, 0
   Push                 r4
   LoadContextVar       1, 1
-  DirectCall           2, CP#15
+  DirectCall           CP#15, 2
   Drop1
   PushNull
   ReturnTOS
@@ -1955,7 +1955,7 @@
   LoadContextVar       1, 0
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#17
+  InterfaceCall        CP#17, 3
   Drop1
   Jump                 L5
 L5:
@@ -1989,7 +1989,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  DirectCall           1, CP#2
+  DirectCall           CP#2, 1
   Drop1
   StoreContextVar      0, 1
   Push                 r0
@@ -2033,27 +2033,27 @@
   StoreContextVar      0, 8
   Push                 r0
   LoadContextVar       0, 8
-  DirectCall           1, CP#29
+  DirectCall           CP#29, 1
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  DirectCall           1, CP#31
+  DirectCall           CP#31, 1
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  DirectCall           1, CP#33
+  DirectCall           CP#33, 1
   StoreContextVar      0, 4
   Push                 r0
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 8
-  DynamicCall          2, CP#36
+  DynamicCall          CP#36, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InterfaceCall        1, CP#37
+  InterfaceCall        CP#37, 1
   ReturnTOS
 }
 ConstantPool {
@@ -2132,7 +2132,7 @@
   LoadContextVar       0, 4
   Push                 r4
   LoadContextVar       0, 8
-  DirectCall           4, CP#8
+  DirectCall           CP#8, 4
   PopLocal             r8
   PushNull
   ReturnTOS
@@ -2146,13 +2146,13 @@
   JumpIfNoAsserts      L2
   Push                 r1
   PushInt              42
-  InterfaceCall        2, CP#10
+  InterfaceCall        CP#10, 2
   AssertBoolean        0
   JumpIfTrue           L2
   PushInt              0
   PushInt              0
   PushNull
-  DirectCall           3, CP#12
+  DirectCall           CP#12, 3
   Drop1
 L2:
   Push                 r4
@@ -2164,7 +2164,7 @@
   LoadContextVar       0, 1
   Push                 r4
   LoadContextVar       0, 2
-  DirectCall           2, CP#14
+  DirectCall           CP#14, 2
   Drop1
   PushNull
   ReturnTOS
@@ -2187,7 +2187,7 @@
   LoadContextVar       0, 1
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#17
+  InterfaceCall        CP#17, 3
   Drop1
   Jump                 L5
 L5:
diff --git a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
index fe17198..e80bb9b 100644
--- a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
+++ b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
@@ -51,8 +51,8 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  InterfaceCall        1, CP#0
-  DirectCall           1, CP#2
+  InterfaceCall        CP#0, 1
+  DirectCall           CP#2, 1
   Drop1
   PushNull
   ReturnTOS
@@ -134,13 +134,13 @@
   PushConstant         CP#0
   PushStatic           CP#0
   PushConstant         CP#1
-  InterfaceCall        2, CP#2
+  InterfaceCall        CP#2, 2
   AssertBoolean        0
   JumpIfTrue           L1
   PushConstant         CP#0
   PushStatic           CP#0
   PushConstant         CP#4
-  InterfaceCall        2, CP#2
+  InterfaceCall        CP#2, 2
   AssertBoolean        0
   PopLocal             r1
   Jump                 L2
@@ -153,7 +153,7 @@
   PushConstant         CP#0
   PushStatic           CP#0
   PushConstant         CP#5
-  InterfaceCall        2, CP#2
+  InterfaceCall        CP#2, 2
   AssertBoolean        0
   PopLocal             r0
   Jump                 L4
@@ -165,15 +165,15 @@
   JumpIfFalse          L5
   PushConstant         CP#0
   PushStatic           CP#0
-  DirectCall           1, CP#6
+  DirectCall           CP#6, 1
   ReturnTOS
 L5:
-  DirectCall           0, CP#8
+  DirectCall           CP#8, 0
   PushNull
   PushConstant         CP#0
   PushStatic           CP#0
-  DirectCall           2, CP#10
-  InterfaceCall        2, CP#12
+  DirectCall           CP#10, 2
+  InterfaceCall        CP#12, 2
   ReturnTOS
 }
 ConstantPool {
@@ -203,7 +203,7 @@
   Entry                1
   CheckStack           0
   PushConstant         CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushNull
   ReturnTOS
@@ -229,7 +229,7 @@
   JumpIfFalse          L1
   PushConstant         CP#1
   PushStatic           CP#1
-  DirectCall           1, CP#2
+  DirectCall           CP#2, 1
   StoreLocal           r1
   Push                 r1
   StoreStaticTOS       CP#0
@@ -289,7 +289,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -324,7 +324,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -397,10 +397,10 @@
   Allocate             CP#0
   StoreLocal           r1
   Push                 r1
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Push                 FP[-5]
-  DirectCall           2, CP#3
+  DirectCall           CP#3, 2
   StoreStaticTOS       CP#5
   PushNull
   ReturnTOS
@@ -430,10 +430,10 @@
   Allocate             CP#1
   StoreLocal           r1
   Push                 r1
-  DirectCall           1, CP#2
+  DirectCall           CP#2, 1
   Drop1
-  DirectCall           0, CP#4
-  DirectCall           2, CP#6
+  DirectCall           CP#4, 0
+  DirectCall           CP#6, 2
   StoreStaticTOS       CP#0
 L1:
   PushConstant         CP#0
@@ -460,8 +460,8 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  DirectCall           0, CP#0
-  DirectCall           1, CP#2
+  DirectCall           CP#0, 0
+  DirectCall           CP#2, 1
   ReturnTOS
 }
 ConstantPool {
@@ -479,11 +479,11 @@
     constructor _() → #lib::_NamespaceImpl
       : super dart.core::Object::•()
       ;
-    @#C2
+    @dart._internal::ExternalName::•("Namespace_Create")
     external static method _create(#lib::_NamespaceImpl namespace, dynamic n) → #lib::_NamespaceImpl;
-    @#C4
+    @dart._internal::ExternalName::•("Namespace_GetPointer")
     external static method _getPointer(#lib::_NamespaceImpl namespace) → dart.core::int;
-    @#C6
+    @dart._internal::ExternalName::•("Namespace_GetDefault")
     external static method _getDefault() → dart.core::int;
     static method _setupNamespace(dynamic namespace) → void {
       #lib::_NamespaceImpl::_cachedNamespace = #lib::_NamespaceImpl::_create(new #lib::_NamespaceImpl::_(), namespace);
@@ -511,7 +511,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -531,7 +531,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -550,7 +550,7 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  DirectCall           0, CP#0
+  DirectCall           CP#0, 0
   ReturnTOS
 }
 ConstantPool {
@@ -567,7 +567,7 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  DirectCall           0, CP#0
+  DirectCall           CP#0, 0
   ReturnTOS
 }
 ConstantPool {
@@ -636,7 +636,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -694,7 +694,7 @@
   JumpIfFalse          L3
   PushConstant         CP#1
   PushStatic           CP#1
-  DynamicCall          1, CP#3
+  DynamicCall          CP#3, 1
   StoreStaticTOS       CP#0
 L3:
   PushConstant         CP#0
@@ -751,7 +751,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -783,7 +783,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -823,13 +823,13 @@
   static field dart.core::int _stderrFD = 2;
   static field dart.core::String _rawScript;
   static field #lib::Stdin _stdin;
-  @#C8
+  @dart._internal::ExternalName::•("Builtin_PrintString")
   external static method _printString(dart.core::String s) → void;
   static method _print(dynamic arg) → void {
     #lib::_printString(arg.{dart.core::Object::toString}());
   }
   static method _getPrintClosure() → dynamic
-    return #C9;
+    return #lib::_print;
   static method _setScheduleImmediateClosure((() → void) → void closure) → void {
     #lib::_ScheduleImmediate::_closure = closure;
   }
@@ -847,7 +847,7 @@
     }
   }
   static method _setupHooks() → dynamic {
-    #lib::VMLibraryHooks::platformScript = #C10;
+    #lib::VMLibraryHooks::platformScript = #lib::_scriptUri;
   }
   static get stdin() → #lib::Stdin {
     #lib::_stdin.{dart.core::Object::==}(null) ?{#lib::Stdin} #lib::_stdin = #lib::_StdIOUtils::_getStdioInputStream(#lib::_stdinFD) : null;
@@ -855,15 +855,3 @@
   }
   static method main() → dynamic {}
 }
-constants  {
-  #C1 = "Namespace_Create"
-  #C2 = dart._internal::ExternalName {name: #C1}
-  #C3 = "Namespace_GetPointer"
-  #C4 = dart._internal::ExternalName {name: #C3}
-  #C5 = "Namespace_GetDefault"
-  #C6 = dart._internal::ExternalName {name: #C5}
-  #C7 = "Builtin_PrintString"
-  #C8 = dart._internal::ExternalName {name: #C7}
-  #C9 = TearOffConstant(#lib::_print)
-  #C10 = TearOffConstant(#lib::_scriptUri)
-}
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index c168ee6..465e333 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -44,7 +44,7 @@
   PopLocal             r2
   Push                 r2
   PushInt              3
-  DynamicCall          2, CP#17
+  DynamicCall          CP#17, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 0
@@ -160,8 +160,8 @@
   Push                 r0
   InstantiateType      CP#8
   StoreIndexedTOS
-  DirectCall           2, CP#9
-  DirectCall           1, CP#11
+  DirectCall           CP#9, 2
+  DirectCall           CP#11, 1
   Drop1
   PushNull
   ReturnTOS
@@ -197,9 +197,9 @@
   AllocateT
   StoreLocal           r0
   Push                 r0
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
-  InterfaceCall        2, CP#5
+  InterfaceCall        CP#5, 2
   Drop1
   PushConstant         CP#7
   PushConstant         CP#2
@@ -207,9 +207,9 @@
   AllocateT
   StoreLocal           r0
   Push                 r0
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
-  InterfaceCall        2, CP#5
+  InterfaceCall        CP#5, 2
   Drop1
   PushConstant         CP#7
   PushConstant         CP#8
@@ -217,9 +217,9 @@
   AllocateT
   StoreLocal           r0
   Push                 r0
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
-  InterfaceCall        2, CP#5
+  InterfaceCall        CP#5, 2
   Drop1
   PushNull
   ReturnTOS
@@ -267,7 +267,7 @@
   StoreLocal           r3
   PushConstant         CP#18
   StoreLocal           r6
-  DirectCall           2, CP#19
+  DirectCall           CP#19, 2
   Drop1
   Allocate             CP#21
   StoreLocal           r5
@@ -340,7 +340,7 @@
   LoadFieldTOS         CP#6
   PushInt              0
   PushInt              1
-  DirectCall           4, CP#8
+  DirectCall           CP#8, 4
   PopLocal             r0
   Push                 FP[-5]
   PushConstant         CP#10
@@ -389,7 +389,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -421,7 +421,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -453,7 +453,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -485,7 +485,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -517,7 +517,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -549,7 +549,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -581,7 +581,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -613,7 +613,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -645,7 +645,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -692,11 +692,11 @@
   PopLocal             r3
   PushConstant         CP#43
   Push                 r3
-  DynamicCall          2, CP#44
+  DynamicCall          CP#44, 2
   Drop1
   PushConstant         CP#45
   Push                 r3
-  DynamicCall          2, CP#46
+  DynamicCall          CP#46, 2
   Drop1
   PushNull
   ReturnTOS
@@ -772,7 +772,7 @@
   LoadFieldTOS         CP#6
   PushInt              2
   PushInt              4
-  DirectCall           4, CP#8
+  DirectCall           CP#8, 4
   PopLocal             r0
   AllocateClosure      CP#10
   StoreLocal           r4
@@ -796,11 +796,11 @@
   PopLocal             r3
   PushConstant         CP#37
   Push                 r3
-  DynamicCall          2, CP#39
+  DynamicCall          CP#39, 2
   Drop1
   PushConstant         CP#40
   Push                 r3
-  DynamicCall          2, CP#41
+  DynamicCall          CP#41, 2
   Drop1
   PushNull
   ReturnTOS
@@ -829,7 +829,7 @@
   LoadFieldTOS         CP#6
   PushInt              4
   PushInt              6
-  DirectCall           4, CP#8
+  DirectCall           CP#8, 4
   PopLocal             r0
   AllocateClosure      CP#11
   StoreLocal           r4
@@ -852,7 +852,7 @@
   StoreFieldTOS        CP#1
   PopLocal             r3
   Push                 r3
-  DynamicCall          1, CP#35
+  DynamicCall          CP#35, 1
   Drop1
   PushNull
   ReturnTOS
@@ -927,15 +927,15 @@
   Push                 r0
   InstantiateType      CP#21
   StoreIndexedTOS
-  DirectCall           2, CP#22
-  DirectCall           1, CP#24
+  DirectCall           CP#22, 2
+  DirectCall           CP#24, 1
   Drop1
   Push                 r1
   LoadContextVar       0, 0
   LoadTypeArgumentsField CP#14
   Push                 r0
   InstantiateTypeArgumentsTOS 0, CP#26
-  DirectCall           1, CP#27
+  DirectCall           CP#27, 1
   Drop1
   PushNull
   ReturnTOS
@@ -981,7 +981,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -1034,22 +1034,22 @@
   PopLocal             r3
   Push                 r3
   PushInt              10
-  DynamicCall          2, CP#25
+  DynamicCall          CP#25, 2
   Drop1
   Push                 r3
   PushInt              11
-  DynamicCall          2, CP#26
+  DynamicCall          CP#26, 2
   Drop1
   Push                 r2
-  DirectCall           1, CP#21
+  DirectCall           CP#21, 1
   Drop1
   Push                 r0
   LoadContextVar       0, 2
-  DirectCall           1, CP#21
+  DirectCall           CP#21, 1
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  DirectCall           1, CP#21
+  DirectCall           CP#21, 1
   Drop1
   Push                 r0
   PushInt              42
@@ -1073,7 +1073,7 @@
   StoreFieldTOS        CP#1
   PopLocal             r2
   Push                 r2
-  DynamicCall          1, CP#31
+  DynamicCall          CP#31, 1
   Drop1
   PushNull
   ReturnTOS
@@ -1170,11 +1170,11 @@
   StoreFieldTOS        CP#1
   PopLocal             r3
   Push                 r3
-  DynamicCall          1, CP#20
+  DynamicCall          CP#20, 1
   Drop1
   Push                 r0
   LoadContextVar       1, 1
-  DirectCall           1, CP#21
+  DirectCall           CP#21, 1
   Drop1
 L1:
   PushNull
@@ -1201,7 +1201,7 @@
   Push                 r0
   LoadContextParent
   LoadContextVar       0, 0
-  InterfaceCall        1, CP#7
+  InterfaceCall        CP#7, 1
   Push                 r0
   LoadContextVar       1, 0
   AddInt
@@ -1222,7 +1222,7 @@
   LoadContextVar       0, 0
   Push                 r0
   LoadContextVar       0, 3
-  InterfaceCall        2, CP#28
+  InterfaceCall        CP#28, 2
   Drop1
   PushNull
   ReturnTOS
@@ -1285,7 +1285,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -1311,11 +1311,11 @@
   StoreContextVar      0, 0
   PushConstant         CP#0
   PushConstant         CP#1
-  DirectCall           2, CP#2
+  DirectCall           CP#2, 2
   PopLocal             r2
   PushConstant         CP#0
   PushConstant         CP#1
-  DirectCall           2, CP#2
+  DirectCall           CP#2, 2
   PopLocal             r4
   AllocateContext      1, 1
   StoreLocal           r1
@@ -1351,7 +1351,7 @@
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
-  InterfaceCall        2, CP#17
+  InterfaceCall        CP#17, 2
   Drop1
   Push                 r4
   AllocateClosure      CP#19
@@ -1371,7 +1371,7 @@
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
-  InterfaceCall        2, CP#17
+  InterfaceCall        CP#17, 2
   Drop1
   Push                 r0
   CloneContext         1, 1
@@ -1475,18 +1475,18 @@
   Entry                5
   CheckStack           0
   Push                 FP[-5]
-  InterfaceCall        1, CP#0
+  InterfaceCall        CP#0, 1
   PopLocal             r2
 L2:
   CheckStack           1
   Push                 r2
-  InterfaceCall        1, CP#2
+  InterfaceCall        CP#2, 1
   JumpIfFalse          L1
   AllocateContext      0, 1
   PopLocal             r0
   Push                 r0
   Push                 r2
-  InterfaceCall        1, CP#4
+  InterfaceCall        CP#4, 1
   StoreContextVar      0, 0
   AllocateClosure      CP#6
   StoreLocal           r4
@@ -1507,11 +1507,11 @@
   StoreFieldTOS        CP#7
   PopLocal             r3
   Push                 r3
-  DynamicCall          1, CP#20
+  DynamicCall          CP#20, 1
   Drop1
   Push                 r0
   LoadContextVar       0, 0
-  DirectCall           1, CP#21
+  DirectCall           CP#21, 1
   Drop1
   Push                 r0
   LoadContextParent
@@ -1606,7 +1606,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -1773,7 +1773,7 @@
   StoreFieldTOS        CP#1
   PopLocal             r2
   Push                 r2
-  DynamicCall          1, CP#16
+  DynamicCall          CP#16, 1
   Drop1
   PushNull
   ReturnTOS
diff --git a/pkg/vm/testcases/bytecode/deferred_lib.dart.expect b/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
index 3974030..f4ef7c3 100644
--- a/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
+++ b/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
@@ -20,9 +20,9 @@
   Entry                1
   CheckStack           0
   PushNull
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   PopLocal             r0
-  DirectCall           0, CP#2
+  DirectCall           CP#2, 0
   ReturnTOS
 }
 ConstantPool {
@@ -42,7 +42,7 @@
   Entry                0
   CheckStack           0
   PushNull
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   ReturnTOS
 }
 ConstantPool {
diff --git a/pkg/vm/testcases/bytecode/field_initializers.dart.expect b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
index 1a25aa9..ee724e8 100644
--- a/pkg/vm/testcases/bytecode/field_initializers.dart.expect
+++ b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
@@ -70,7 +70,7 @@
   PushInt              44
   StoreFieldTOS        CP#2
   Push                 FP[-6]
-  DirectCall           1, CP#6
+  DirectCall           CP#6, 1
   Drop1
   PushNull
   ReturnTOS
@@ -111,7 +111,7 @@
   AddInt
   StoreFieldTOS        CP#2
   Push                 FP[-7]
-  DirectCall           1, CP#6
+  DirectCall           CP#6, 1
   Drop1
   PushNull
   ReturnTOS
@@ -139,7 +139,7 @@
   CheckStack           0
   Push                 FP[-5]
   PushInt              45
-  DirectCall           2, CP#0
+  DirectCall           CP#0, 2
   Drop1
   PushNull
   ReturnTOS
@@ -163,7 +163,7 @@
   Push                 FP[-6]
   Push                 FP[-5]
   MulInt
-  DirectCall           3, CP#0
+  DirectCall           CP#0, 3
   Drop1
   PushNull
   ReturnTOS
@@ -221,7 +221,7 @@
   StoreFieldTOS        CP#0
   Push                 FP[-5]
   PushInt              49
-  DirectCall           2, CP#2
+  DirectCall           CP#2, 2
   Drop1
   PushNull
   ReturnTOS
@@ -252,7 +252,7 @@
   Push                 FP[-6]
   Push                 FP[-5]
   PushInt              51
-  DirectCall           4, CP#2
+  DirectCall           CP#2, 4
   Drop1
   PushNull
   ReturnTOS
@@ -270,7 +270,7 @@
 ]  class B extends #lib::A {
     field dart.core::int foo6 = 46;
     static field dart.core::int foo7 = 47;
-    static const field dart.core::int foo8 = #C1;
+    static const field dart.core::int foo8 = 48;
     constructor •() → #lib::B
       : super #lib::A::•(49)
       ;
@@ -280,6 +280,3 @@
   }
   static method main() → dynamic {}
 }
-constants  {
-  #C1 = 48
-}
diff --git a/pkg/vm/testcases/bytecode/hello.dart.expect b/pkg/vm/testcases/bytecode/hello.dart.expect
index ce754e8..aa15b42 100644
--- a/pkg/vm/testcases/bytecode/hello.dart.expect
+++ b/pkg/vm/testcases/bytecode/hello.dart.expect
@@ -20,7 +20,7 @@
   Entry                0
   CheckStack           0
   PushConstant         CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushNull
   ReturnTOS
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index 2a98dd2..7243ab2 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -23,7 +23,7 @@
   StoreLocal           r0
   Push                 r0
   PushConstant         CP#1
-  DirectCall           2, CP#2
+  DirectCall           CP#2, 2
   Drop1
   ReturnTOS
 }
@@ -49,7 +49,7 @@
   StoreLocal           r0
   Push                 r0
   PushConstant         CP#2
-  DirectCall           2, CP#3
+  DirectCall           CP#3, 2
   Drop1
   Drop1
   PushConstant         CP#6
@@ -57,7 +57,7 @@
   AllocateT
   StoreLocal           r0
   Push                 r0
-  DirectCall           1, CP#7
+  DirectCall           CP#7, 1
   Drop1
   Drop1
   PushNull
@@ -93,7 +93,7 @@
   AllocateT
   StoreLocal           r1
   Push                 r1
-  DirectCall           1, CP#2
+  DirectCall           CP#2, 1
   Drop1
   Drop1
   PushNull
@@ -116,7 +116,7 @@
   Entry                0
   CheckStack           0
   PushConstant         CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushNull
   ReturnTOS
@@ -137,11 +137,11 @@
   Entry                0
   CheckStack           0
   PushNull
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   PushInt              42
-  DirectCall           2, CP#2
+  DirectCall           CP#2, 2
   Drop1
   PushNull
   ReturnTOS
@@ -164,7 +164,7 @@
   CheckStack           0
   PushConstant         CP#0
   PushInt              0
-  DirectCall           2, CP#1
+  DirectCall           CP#1, 2
   ReturnTOS
 }
 ConstantPool {
@@ -184,7 +184,7 @@
   CheckStack           0
   PushConstant         CP#0
   Push                 FP[-5]
-  DirectCall           2, CP#1
+  DirectCall           CP#1, 2
   ReturnTOS
 }
 ConstantPool {
@@ -202,12 +202,12 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  DirectCall           0, CP#0
+  DirectCall           CP#0, 0
   Drop1
-  DirectCall           0, CP#2
+  DirectCall           CP#2, 0
   Drop1
   PushConstant         CP#4
-  DirectCall           1, CP#5
+  DirectCall           CP#5, 1
   Drop1
   PushNull
   ReturnTOS
@@ -246,7 +246,7 @@
   Entry                1
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   PushInt              4
@@ -274,8 +274,8 @@
   PushNull
   InstantiateType      CP#6
   StoreIndexedTOS
-  DirectCall           1, CP#7
-  DirectCall           1, CP#9
+  DirectCall           CP#7, 1
+  DirectCall           CP#9, 1
   Drop1
   PushNull
   ReturnTOS
@@ -320,7 +320,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-6]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -352,7 +352,7 @@
   Entry                1
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   PushInt              2
@@ -369,8 +369,8 @@
   PushNull
   InstantiateType      CP#3
   StoreIndexedTOS
-  DirectCall           1, CP#5
-  DirectCall           1, CP#7
+  DirectCall           CP#5, 1
+  DirectCall           CP#7, 1
   Drop1
   PushNull
   ReturnTOS
@@ -410,7 +410,7 @@
   Entry                1
   CheckStack           0
   Push                 FP[-6]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   PushInt              2
@@ -424,8 +424,8 @@
   PushInt              1
   Push                 FP[-5]
   StoreIndexedTOS
-  DirectCall           1, CP#3
-  DirectCall           1, CP#5
+  DirectCall           CP#3, 1
+  DirectCall           CP#5, 1
   Drop1
   PushNull
   ReturnTOS
@@ -463,7 +463,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -484,7 +484,7 @@
   CheckStack           0
   Push                 FP[-5]
   LoadTypeArgumentsField CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   ReturnTOS
 }
 ConstantPool {
@@ -517,7 +517,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -538,7 +538,7 @@
   CheckStack           0
   Push                 FP[-5]
   LoadTypeArgumentsField CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   ReturnTOS
 }
 ConstantPool {
@@ -571,7 +571,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -598,7 +598,7 @@
   AllocateT
   StoreLocal           r0
   Push                 r0
-  DirectCall           1, CP#2
+  DirectCall           CP#2, 1
   Drop1
   ReturnTOS
 }
@@ -633,7 +633,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -665,7 +665,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-6]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -691,7 +691,7 @@
   StoreLocal           r2
   Push                 r2
   Push                 r1
-  DirectCall           2, CP#3
+  DirectCall           CP#3, 2
   Drop1
   ReturnTOS
 }
@@ -710,7 +710,7 @@
     constructor •(dynamic param) → #lib::I
       : super dart.core::Object::•()
       ;
-    static factory test_factory2({dynamic param = #C1}) → #lib::I
+    static factory test_factory2({dynamic param = null}) → #lib::I
       return new #lib::I::•(param);
   }
 [@vm.bytecode=
@@ -738,7 +738,7 @@
 
 }
 ]  class J extends dart.core::Object {
-    @#C3
+    @dart._internal::ExternalName::•("agent_J")
     external static factory •() → #lib::J;
   }
 [@vm.bytecode=
@@ -760,7 +760,7 @@
   AllocateT
   StoreLocal           r0
   Push                 r0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   ReturnTOS
 }
@@ -791,7 +791,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -835,8 +835,3 @@
     #lib::foo3<dart.core::String>();
   }
 }
-constants  {
-  #C1 = null
-  #C2 = "agent_J"
-  #C3 = dart._internal::ExternalName {name: #C2}
-}
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index 3449af2..290438e 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -67,19 +67,19 @@
   Entry                0
   CheckStack           0
   PushConstant         CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushConstant         CP#3
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushInt              6
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushConstant         CP#4
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushConstant         CP#5
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushNull
   ReturnTOS
@@ -103,22 +103,22 @@
   Entry                0
   CheckStack           0
   PushInt              42
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushConstant         CP#2
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushConstant         CP#3
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushConstant         CP#4
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushConstant         CP#5
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushConstant         CP#6
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -160,8 +160,8 @@
   PushInt              2
   PushInt              3
   StoreIndexedTOS
-  DirectCall           2, CP#1
-  DirectCall           1, CP#3
+  DirectCall           CP#1, 2
+  DirectCall           CP#3, 1
   Drop1
   PushConstant         CP#5
   StoreLocal           r0
@@ -176,14 +176,14 @@
   Push                 r0
   PushInt              1
   Push                 FP[-5]
-  InterfaceCall        1, CP#7
+  InterfaceCall        CP#7, 1
   StoreIndexedTOS
   Push                 r0
   PushInt              2
   PushConstant         CP#9
   StoreIndexedTOS
-  DirectCall           2, CP#1
-  DirectCall           1, CP#3
+  DirectCall           CP#1, 2
+  DirectCall           CP#3, 1
   Drop1
   PushNull
   ReturnTOS
@@ -233,8 +233,8 @@
   PushInt              3
   PushInt              2
   StoreIndexedTOS
-  DirectCall           2, CP#2
-  DirectCall           1, CP#4
+  DirectCall           CP#2, 2
+  DirectCall           CP#4, 1
   Drop1
   PushConstant         CP#6
   PushConstant         CP#1
@@ -252,21 +252,21 @@
   Push                 r1
   PushInt              2
   Push                 FP[-6]
-  InterfaceCall        1, CP#8
+  InterfaceCall        CP#8, 1
   StoreIndexedTOS
   Push                 r1
   PushInt              3
   PushInt              3
   StoreIndexedTOS
-  DirectCall           2, CP#2
-  DirectCall           1, CP#4
+  DirectCall           CP#2, 2
+  DirectCall           CP#4, 1
   Drop1
   PushNull
   Push                 r0
   InstantiateTypeArgumentsTOS 0, CP#10
   PushConstant         CP#11
-  DirectCall           2, CP#2
-  DirectCall           1, CP#4
+  DirectCall           CP#2, 2
+  DirectCall           CP#4, 1
   Drop1
   PushNull
   Push                 r0
@@ -283,8 +283,8 @@
   PushInt              1
   PushInt              4
   StoreIndexedTOS
-  DirectCall           2, CP#2
-  DirectCall           1, CP#4
+  DirectCall           CP#2, 2
+  DirectCall           CP#4, 1
   Drop1
   PushNull
   ReturnTOS
@@ -315,10 +315,10 @@
   Entry                0
   CheckStack           0
   PushConstant         CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushConstant         CP#3
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushNull
   ReturnTOS
@@ -342,12 +342,12 @@
   CheckStack           0
   CheckFunctionTypeArgs 1, r0
   PushConstant         CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushNull
   Push                 r0
   InstantiateType      CP#3
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushNull
   ReturnTOS
@@ -519,7 +519,7 @@
   Push                 FP[-5]
   StoreFieldTOS        CP#2
   Push                 FP[-7]
-  DirectCall           1, CP#4
+  DirectCall           CP#4, 1
   Drop1
   PushNull
   ReturnTOS
@@ -543,7 +543,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   ReturnTOS
 }
 ConstantPool {
@@ -557,11 +557,11 @@
 ]  class A extends dart.core::Object {
     final field dart.core::int index;
     final field dart.core::String _name;
-    static const field dart.core::List<#lib::A> values = #C13;
-    static const field #lib::A elem1 = #C3;
-    static const field #lib::A elem2 = #C6;
-    static const field #lib::A elem3 = #C9;
-    static const field #lib::A elem4 = #C12;
+    static const field dart.core::List<#lib::A> values = const <#lib::A>[#lib::A::elem1, #lib::A::elem2, #lib::A::elem3, #lib::A::elem4];
+    static const field #lib::A elem1 = const #lib::A::•(0, "A.elem1");
+    static const field #lib::A elem2 = const #lib::A::•(1, "A.elem2");
+    static const field #lib::A elem3 = const #lib::A::•(2, "A.elem3");
+    static const field #lib::A elem4 = const #lib::A::•(3, "A.elem4");
     const constructor •(dart.core::int index, dart.core::String _name) → #lib::A
       : #lib::A::index = index, #lib::A::_name = _name, super dart.core::Object::•()
       ;
@@ -587,7 +587,7 @@
   Push                 FP[-5]
   StoreFieldTOS        CP#0
   Push                 FP[-6]
-  DirectCall           1, CP#2
+  DirectCall           CP#2, 1
   Drop1
   PushNull
   ReturnTOS
@@ -632,7 +632,7 @@
   Push                 FP[-5]
   PushInt              5
   MulInt
-  DirectCall           2, CP#2
+  DirectCall           CP#2, 2
   Drop1
   PushNull
   ReturnTOS
@@ -680,7 +680,7 @@
   Push                 r2
   StoreFieldTOS        CP#3
   Push                 r0
-  DirectCall           1, CP#5
+  DirectCall           CP#5, 1
   Drop1
   PushNull
   ReturnTOS
@@ -701,7 +701,7 @@
 ]  class D extends dart.core::Object {
     final field dynamic x;
     final field dynamic y;
-    const constructor •(dynamic x, [dynamic y = #C14]) → #lib::D
+    const constructor •(dynamic x, [dynamic y = null]) → #lib::D
       : #lib::D::x = x, #lib::D::y = y, super dart.core::Object::•()
       ;
   }
@@ -719,7 +719,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -751,7 +751,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -769,26 +769,26 @@
       : super #lib::E::•()
       ;
   }
-  static const field #lib::A c1 = #C9;
-  static const field dart.core::String c2 = #C15;
-  static const field dart.core::int c3 = #C16;
-  static const field #lib::C c4 = #C18;
-  static const field #lib::D c5 = #C21;
+  static const field #lib::A c1 = #lib::A::elem3;
+  static const field dart.core::String c2 = "hello!";
+  static const field dart.core::int c3 = #lib::c2.{dart.core::String::length};
+  static const field #lib::C c4 = const #lib::C::•(1, 2, 3);
+  static const field #lib::D c5 = const #lib::D::•(const #lib::B::•(4));
   static field dart.core::double fieldWithDoubleLiteralInitializer = 1.0;
   static method test_constants1() → void {
-    dart.core::print(#C9);
-    dart.core::print(#C15);
-    dart.core::print(#C16);
-    dart.core::print(#C18);
-    dart.core::print(#C21);
+    dart.core::print(#lib::c1);
+    dart.core::print(#lib::c2);
+    dart.core::print(#lib::c3);
+    dart.core::print(#lib::c4);
+    dart.core::print(#lib::c5);
   }
   static method test_constants2() → void {
     dart.core::print(42);
     dart.core::print("foo");
-    dart.core::print(#C6);
-    dart.core::print(#C25);
-    dart.core::print(#C29);
-    dart.core::print(#C37);
+    dart.core::print(#lib::A::elem2);
+    dart.core::print(const <dart.core::Object>[42, "foo", dart.core::int]);
+    dart.core::print(const <dart.core::String, #lib::A>{"E2": #lib::A::elem2, "E4": #lib::A::elem4});
+    dart.core::print(const #lib::D::•(const #lib::C::•(4, 5, 6), const <dart.core::String, dart.core::Object>{"foo": 42, "bar": const #lib::B::•(#lib::c2.{dart.core::String::length})}));
   }
   static method test_list_literal(dart.core::int a) → void {
     dart.core::print(<dart.core::int>[1, a, 3]);
@@ -801,60 +801,18 @@
     dart.core::print(<#lib::test_map_literal::T, dart.core::int>{c: 4});
   }
   static method test_symbol() → void {
-    dart.core::print(#C38);
-    dart.core::print(#C39);
+    dart.core::print(#test_symbol);
+    dart.core::print(#_private_symbol);
   }
   static method test_type_literal<T extends dart.core::Object = dynamic>() → void {
     dart.core::print(dart.core::String);
     dart.core::print(#lib::test_type_literal::T);
   }
   static method testGenericConstInstance() → dynamic
-    return #C40;
+    return const #lib::F::•<dart.core::int, dart.core::String>();
   static method testGenericFunctionTypeLiteral() → dynamic
     return <X extends dart.core::Object = dynamic>(X) → X;
   static method testFieldWithDoubleLiteralInitializer() → dynamic
     return #lib::fieldWithDoubleLiteralInitializer;
   static method main() → dynamic {}
 }
-constants  {
-  #C1 = 0
-  #C2 = "A.elem1"
-  #C3 = #lib::A {index: #C1, #lib::_name: #C2}
-  #C4 = 1
-  #C5 = "A.elem2"
-  #C6 = #lib::A {index: #C4, #lib::_name: #C5}
-  #C7 = 2
-  #C8 = "A.elem3"
-  #C9 = #lib::A {index: #C7, #lib::_name: #C8}
-  #C10 = 3
-  #C11 = "A.elem4"
-  #C12 = #lib::A {index: #C10, #lib::_name: #C11}
-  #C13 = ListConstant<#lib::A>(#C3, #C6, #C9, #C12)
-  #C14 = null
-  #C15 = "hello!"
-  #C16 = 6
-  #C17 = 15
-  #C18 = #lib::C {j: #C10, i: #C17}
-  #C19 = 4
-  #C20 = #lib::B {i: #C19}
-  #C21 = #lib::D {x: #C20, y: #C14}
-  #C22 = 42
-  #C23 = "foo"
-  #C24 = TypeLiteralConstant(dart.core::int)
-  #C25 = ListConstant<dart.core::Object>(#C22, #C23, #C24)
-  #C26 = "E2"
-  #C27 = "E4"
-  #C28 = ListConstant<dynamic>(#C26, #C6, #C27, #C12)
-  #C29 = dart.core::_ImmutableMap<dart.core::String, #lib::A> {dart.core::_kvPairs: #C28}
-  #C30 = 9
-  #C31 = 30
-  #C32 = #lib::C {j: #C30, i: #C31}
-  #C33 = "bar"
-  #C34 = #lib::B {i: #C16}
-  #C35 = ListConstant<dynamic>(#C23, #C22, #C33, #C34)
-  #C36 = dart.core::_ImmutableMap<dart.core::String, dart.core::Object> {dart.core::_kvPairs: #C35}
-  #C37 = #lib::D {x: #C32, y: #C36}
-  #C38 = #test_symbol
-  #C39 = ##lib::_private_symbol
-  #C40 = #lib::F<dart.core::int, dart.core::String> {}
-}
diff --git a/pkg/vm/testcases/bytecode/loops.dart.expect b/pkg/vm/testcases/bytecode/loops.dart.expect
index d4b5acb..99ac193 100644
--- a/pkg/vm/testcases/bytecode/loops.dart.expect
+++ b/pkg/vm/testcases/bytecode/loops.dart.expect
@@ -27,13 +27,13 @@
   CheckStack           1
   Push                 r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#0
+  InterfaceCall        CP#0, 1
   CompareIntLt
   JumpIfFalse          L1
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InterfaceCall        2, CP#2
+  InterfaceCall        CP#2, 2
   AddInt
   PopLocal             r0
   Push                 r1
@@ -74,7 +74,7 @@
   JumpIfFalse          L1
   Push                 r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#0
+  InterfaceCall        CP#0, 1
   CompareIntGe
   JumpIfFalse          L2
   Jump                 L1
@@ -82,7 +82,7 @@
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InterfaceCall        2, CP#2
+  InterfaceCall        CP#2, 2
   AddInt
   PopLocal             r0
   Push                 r1
@@ -120,7 +120,7 @@
   CheckStack           1
   Push                 r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#0
+  InterfaceCall        CP#0, 1
   CompareIntLt
   JumpIfFalse          L1
   Push                 r1
@@ -132,7 +132,7 @@
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InterfaceCall        2, CP#2
+  InterfaceCall        CP#2, 2
   AddInt
   PopLocal             r0
 L3:
@@ -170,7 +170,7 @@
   CheckStack           1
   Push                 r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#0
+  InterfaceCall        CP#0, 1
   CompareIntLt
   JumpIfFalse          L1
   Push                 r0
@@ -183,7 +183,7 @@
   StoreLocal           r1
   PopLocal             r3
   Push                 r2
-  InterfaceCall        2, CP#2
+  InterfaceCall        CP#2, 2
   AddInt
   PopLocal             r0
   Jump                 L2
@@ -216,7 +216,7 @@
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   AddInt
   PopLocal             r0
   Push                 r1
@@ -225,7 +225,7 @@
   PopLocal             r1
   Push                 r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#2
+  InterfaceCall        CP#2, 1
   CompareIntLt
   JumpIfTrue           L1
   Push                 r0
@@ -250,15 +250,15 @@
   PushInt              0
   PopLocal             r0
   Push                 FP[-5]
-  InterfaceCall        1, CP#0
+  InterfaceCall        CP#0, 1
   PopLocal             r1
 L2:
   CheckStack           1
   Push                 r1
-  InterfaceCall        1, CP#2
+  InterfaceCall        CP#2, 1
   JumpIfFalse          L1
   Push                 r1
-  InterfaceCall        1, CP#4
+  InterfaceCall        CP#4, 1
   PopLocal             r2
   Push                 r0
   Push                 r2
@@ -292,15 +292,15 @@
   PushInt              42
   PopLocal             r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#0
+  InterfaceCall        CP#0, 1
   PopLocal             r2
 L2:
   CheckStack           1
   Push                 r2
-  InterfaceCall        1, CP#2
+  InterfaceCall        CP#2, 1
   JumpIfFalse          L1
   Push                 r2
-  InterfaceCall        1, CP#4
+  InterfaceCall        CP#4, 1
   PopLocal             r3
   Push                 r3
   PopLocal             r1
diff --git a/pkg/vm/testcases/bytecode/optional_params.dart.expect b/pkg/vm/testcases/bytecode/optional_params.dart.expect
index 4fcf451..49156f2 100644
--- a/pkg/vm/testcases/bytecode/optional_params.dart.expect
+++ b/pkg/vm/testcases/bytecode/optional_params.dart.expect
@@ -34,8 +34,8 @@
   PushInt              1
   Push                 r0
   StoreIndexedTOS
-  DirectCall           1, CP#3
-  DirectCall           1, CP#5
+  DirectCall           CP#3, 1
+  DirectCall           CP#5, 1
   Drop1
   PushNull
   PushInt              2
@@ -49,8 +49,8 @@
   PushInt              1
   Push                 r1
   StoreIndexedTOS
-  DirectCall           1, CP#3
-  DirectCall           1, CP#5
+  DirectCall           CP#3, 1
+  DirectCall           CP#5, 1
   Drop1
   PushNull
   PushInt              2
@@ -64,8 +64,8 @@
   PushInt              1
   Push                 r2
   StoreIndexedTOS
-  DirectCall           1, CP#3
-  DirectCall           1, CP#5
+  DirectCall           CP#3, 1
+  DirectCall           CP#5, 1
   Drop1
   PushNull
   ReturnTOS
@@ -110,8 +110,8 @@
   PushInt              1
   Push                 r0
   StoreIndexedTOS
-  DirectCall           1, CP#7
-  DirectCall           1, CP#9
+  DirectCall           CP#7, 1
+  DirectCall           CP#9, 1
   Drop1
   PushNull
   PushInt              2
@@ -125,8 +125,8 @@
   PushInt              1
   Push                 r1
   StoreIndexedTOS
-  DirectCall           1, CP#7
-  DirectCall           1, CP#9
+  DirectCall           CP#7, 1
+  DirectCall           CP#9, 1
   Drop1
   PushNull
   PushInt              2
@@ -140,8 +140,8 @@
   PushInt              1
   Push                 r2
   StoreIndexedTOS
-  DirectCall           1, CP#7
-  DirectCall           1, CP#9
+  DirectCall           CP#7, 1
+  DirectCall           CP#9, 1
   Drop1
   PushNull
   PushInt              2
@@ -155,8 +155,8 @@
   PushInt              1
   Push                 r3
   StoreIndexedTOS
-  DirectCall           1, CP#7
-  DirectCall           1, CP#9
+  DirectCall           CP#7, 1
+  DirectCall           CP#9, 1
   Drop1
   PushNull
   PushInt              2
@@ -170,8 +170,8 @@
   PushInt              1
   Push                 r4
   StoreIndexedTOS
-  DirectCall           1, CP#7
-  DirectCall           1, CP#9
+  DirectCall           CP#7, 1
+  DirectCall           CP#9, 1
   Drop1
   PushNull
   ReturnTOS
@@ -213,13 +213,13 @@
   PushNull
   Push                 r4
   InstantiateType      CP#4
-  DirectCall           1, CP#5
+  DirectCall           CP#5, 1
   Drop1
   Push                 r1
-  DirectCall           1, CP#5
+  DirectCall           CP#5, 1
   Drop1
   Push                 r3
-  DirectCall           1, CP#5
+  DirectCall           CP#5, 1
   Drop1
   PushNull
   ReturnTOS
@@ -245,12 +245,12 @@
   CheckStack           0
   PushConstant         CP#0
   PushConstant         CP#1
-  DirectCall           2, CP#2
+  DirectCall           CP#2, 2
   Drop1
   PushConstant         CP#4
   PushConstant         CP#5
   PushConstant         CP#1
-  DirectCall           3, CP#6
+  DirectCall           CP#6, 3
   Drop1
   PushNull
   ReturnTOS
@@ -271,19 +271,19 @@
 }
 ]library #lib from "#lib" as #lib {
 
-  static method foo1(dynamic x, [dynamic a = #C1, dynamic b = #C2]) → void {
+  static method foo1(dynamic x, [dynamic a = "default_a", dynamic b = "default_b"]) → void {
     dart.core::print("x = ${x}");
     dart.core::print("a = ${a}");
     dart.core::print("b = ${b}");
   }
-  static method foo2(dynamic y, dynamic z, {dynamic c = #C3, dynamic a = #C4, dynamic b = #C5}) → void {
+  static method foo2(dynamic y, dynamic z, {dynamic c = "default_c", dynamic a = 42, dynamic b = const <dart.core::String>["default_b"]}) → void {
     dart.core::print("y = ${y}");
     dart.core::print("z = ${z}");
     dart.core::print("a = ${a}");
     dart.core::print("b = ${b}");
     dart.core::print("c = ${c}");
   }
-  static method foo3<P extends dart.core::Object = dynamic, Q extends dart.core::Object = dynamic>(dynamic z, dynamic y, {dart.core::bool a = #C6, dart.core::Map<#lib::foo3::P, #lib::foo3::Q> b = #C7}) → void {
+  static method foo3<P extends dart.core::Object = dynamic, Q extends dart.core::Object = dynamic>(dynamic z, dynamic y, {dart.core::bool a = false, dart.core::Map<#lib::foo3::P, #lib::foo3::Q> b = null}) → void {
     dart.core::print(#lib::foo3::P);
     dart.core::print(y);
     dart.core::print(b);
@@ -293,12 +293,3 @@
     #lib::foo2("fixed_y", "fixed_z", a: "concrete_a");
   }
 }
-constants  {
-  #C1 = "default_a"
-  #C2 = "default_b"
-  #C3 = "default_c"
-  #C4 = 42
-  #C5 = ListConstant<dart.core::String>(#C2)
-  #C6 = false
-  #C7 = null
-}
diff --git a/pkg/vm/testcases/bytecode/super_calls.dart.expect b/pkg/vm/testcases/bytecode/super_calls.dart.expect
index 286cf41..31ff703 100644
--- a/pkg/vm/testcases/bytecode/super_calls.dart.expect
+++ b/pkg/vm/testcases/bytecode/super_calls.dart.expect
@@ -44,7 +44,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -127,7 +127,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -150,7 +150,7 @@
   Push                 FP[-6]
   PushConstant         CP#1
   PushInt              2
-  DirectCall           4, CP#2
+  DirectCall           CP#2, 4
   ReturnTOS
 }
 ConstantPool {
@@ -170,7 +170,7 @@
   Entry                1
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   ReturnTOS
 }
 ConstantPool {
@@ -188,7 +188,7 @@
   Entry                1
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   ReturnTOS
 }
 ConstantPool {
@@ -207,9 +207,9 @@
   CheckStack           0
   PushConstant         CP#0
   Push                 FP[-5]
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   PushConstant         CP#3
-  DynamicCall          3, CP#5
+  DynamicCall          CP#5, 3
   ReturnTOS
 }
 ConstantPool {
@@ -232,7 +232,7 @@
   CheckStack           0
   Push                 FP[-5]
   PushInt              3
-  DirectCall           2, CP#0
+  DirectCall           CP#0, 2
   Drop1
   PushNull
   ReturnTOS
@@ -275,7 +275,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -323,7 +323,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -370,8 +370,8 @@
   PushInt              5
   StoreIndexedTOS
   PushTrue
-  DirectCall           4, CP#6
-  DirectCall           2, CP#8
+  DirectCall           CP#6, 4
+  DirectCall           CP#8, 2
   ReturnTOS
 }
 ConstantPool {
@@ -408,8 +408,8 @@
   Push                 FP[-5]
   StoreIndexedTOS
   PushTrue
-  DirectCall           4, CP#3
-  DirectCall           2, CP#5
+  DirectCall           CP#3, 4
+  DirectCall           CP#5, 2
   ReturnTOS
 }
 ConstantPool {
@@ -443,8 +443,8 @@
   Push                 FP[-5]
   StoreIndexedTOS
   PushTrue
-  DirectCall           4, CP#3
-  DirectCall           2, CP#5
+  DirectCall           CP#3, 4
+  DirectCall           CP#5, 2
   ReturnTOS
 }
 ConstantPool {
@@ -479,10 +479,10 @@
   Push                 FP[-5]
   StoreIndexedTOS
   PushTrue
-  DirectCall           4, CP#4
-  DirectCall           2, CP#6
+  DirectCall           CP#4, 4
+  DirectCall           CP#6, 2
   PushConstant         CP#8
-  DynamicCall          3, CP#10
+  DynamicCall          CP#10, 3
   ReturnTOS
 }
 ConstantPool {
@@ -524,8 +524,8 @@
   PushInt              3
   StoreIndexedTOS
   PushTrue
-  DirectCall           4, CP#3
-  DirectCall           2, CP#5
+  DirectCall           CP#3, 4
+  DirectCall           CP#5, 2
   Drop1
   PushNull
   ReturnTOS
diff --git a/pkg/vm/testcases/bytecode/switch.dart.expect b/pkg/vm/testcases/bytecode/switch.dart.expect
index adea1f5a..80a1682 100644
--- a/pkg/vm/testcases/bytecode/switch.dart.expect
+++ b/pkg/vm/testcases/bytecode/switch.dart.expect
@@ -25,15 +25,15 @@
   PopLocal             r1
   Push                 r1
   PushInt              1
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L1
   Push                 r1
   PushInt              2
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L2
   Push                 r1
   PushInt              3
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L3
   Jump                 L4
 L1:
@@ -72,27 +72,27 @@
   PopLocal             r1
   Push                 r1
   PushInt              1
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L1
   Push                 r1
   PushInt              2
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L1
   Push                 r1
   PushInt              3
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L1
   Push                 r1
   PushInt              4
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L2
   Push                 r1
   PushInt              5
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L2
   Push                 r1
   PushInt              6
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L2
   Jump                 L3
 L1:
@@ -130,27 +130,27 @@
   PopLocal             r1
   Push                 r1
   PushInt              1
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L1
   Push                 r1
   PushInt              2
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L1
   Push                 r1
   PushInt              3
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L1
   Push                 r1
   PushInt              4
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L2
   Push                 r1
   PushInt              5
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L2
   Push                 r1
   PushInt              6
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L2
   Jump                 L3
 L1:
@@ -198,19 +198,19 @@
     #L1:
     switch(x) {
       #L2:
-      case #C1:
+      case 1:
         {
           y = 11;
           break #L1;
         }
       #L3:
-      case #C2:
+      case 2:
         {
           y = 22;
           break #L1;
         }
       #L4:
-      case #C3:
+      case 3:
         {
           y = 33;
           break #L1;
@@ -223,17 +223,17 @@
     #L5:
     switch(x) {
       #L6:
-      case #C1:
-      case #C2:
-      case #C3:
+      case 1:
+      case 2:
+      case 3:
         {
           y = 11;
           break #L5;
         }
       #L7:
-      case #C4:
-      case #C5:
-      case #C6:
+      case 4:
+      case 5:
+      case 6:
         {
           y = 22;
           break #L5;
@@ -250,17 +250,17 @@
     dart.core::int y;
     switch(x) {
       #L9:
-      case #C1:
-      case #C2:
-      case #C3:
+      case 1:
+      case 2:
+      case 3:
         {
           y = 11;
           continue #L10;
         }
       #L10:
-      case #C4:
-      case #C5:
-      case #C6:
+      case 4:
+      case 5:
+      case 6:
         {
           y = 22;
           return 42;
@@ -275,11 +275,3 @@
   }
   static method main() → dynamic {}
 }
-constants  {
-  #C1 = 1
-  #C2 = 2
-  #C3 = 3
-  #C4 = 4
-  #C5 = 5
-  #C6 = 6
-}
diff --git a/pkg/vm/testcases/bytecode/try_blocks.dart.expect b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
index b6575db..3527e207 100644
--- a/pkg/vm/testcases/bytecode/try_blocks.dart.expect
+++ b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
@@ -21,7 +21,7 @@
   CheckStack           0
 Try #0 start:
   PushConstant         CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L1
 Try #0 end:
@@ -43,8 +43,8 @@
   PushInt              1
   Push                 r2
   StoreIndexedTOS
-  DirectCall           1, CP#5
-  DirectCall           1, CP#1
+  DirectCall           CP#5, 1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L1
 L1:
@@ -52,7 +52,7 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 2, end 6, handler 6, types [CP#3]
+  try-index 0, outer -1, start 4, end 14, handler 14, types [CP#3]
 }
 ConstantPool {
   [0] = ObjectRef 'danger!'
@@ -75,7 +75,7 @@
   CheckStack           0
 Try #0 start:
   PushConstant         CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L1
 Try #0 end:
@@ -85,16 +85,16 @@
   MoveSpecial          stackTrace, r1
   Push                 r0
   PushConstant         CP#3
-  InterfaceCall        2, CP#4
+  InterfaceCall        CP#4, 2
   JumpIfFalse          L2
   PushConstant         CP#6
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L1
 L2:
   Push                 r0
   PushConstant         CP#7
-  InterfaceCall        2, CP#4
+  InterfaceCall        CP#4, 2
   JumpIfFalse          L3
   Push                 r0
   PopLocal             r2
@@ -110,14 +110,14 @@
   PushInt              1
   Push                 r2
   StoreIndexedTOS
-  DirectCall           1, CP#9
-  DirectCall           1, CP#1
+  DirectCall           CP#9, 1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L1
 L3:
   Push                 r0
   PushConstant         CP#11
-  InterfaceCall        2, CP#4
+  InterfaceCall        CP#4, 2
   JumpIfFalse          L4
   Push                 r0
   PopLocal             r2
@@ -143,8 +143,8 @@
   PushInt              3
   Push                 r3
   StoreIndexedTOS
-  DirectCall           1, CP#9
-  DirectCall           1, CP#1
+  DirectCall           CP#9, 1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L1
 L4:
@@ -172,8 +172,8 @@
   PushInt              3
   Push                 r3
   StoreIndexedTOS
-  DirectCall           1, CP#9
-  DirectCall           1, CP#1
+  DirectCall           CP#9, 1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L1
 L1:
@@ -181,7 +181,7 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 2, end 6, handler 6, needs-stack-trace, types [CP#3, CP#7, CP#11, CP#14]
+  try-index 0, outer -1, start 4, end 14, handler 14, needs-stack-trace, types [CP#3, CP#7, CP#11, CP#14]
 }
 ConstantPool {
   [0] = ObjectRef 'danger!'
@@ -241,11 +241,11 @@
   StoreFieldTOS        CP#1
   PopLocal             r4
   Push                 r4
-  DynamicCall          1, CP#18
+  DynamicCall          CP#18, 1
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  DirectCall           1, CP#4
+  DirectCall           CP#4, 1
   Drop1
   Jump                 L1
 Try #0 end:
@@ -281,8 +281,8 @@
   Push                 r0
   LoadContextVar       0, 2
   StoreIndexedTOS
-  DirectCall           1, CP#21
-  DirectCall           1, CP#4
+  DirectCall           CP#21, 1
+  DirectCall           CP#4, 1
   Drop1
   AllocateClosure      CP#23
   StoreLocal           r5
@@ -312,7 +312,7 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 9, end 38, handler 38, needs-stack-trace, types [CP#6]
+  try-index 0, outer -1, start 20, end 80, handler 80, needs-stack-trace, types [CP#6]
 }
 ConstantPool {
   [0] = ClosureFunction 0
@@ -358,7 +358,7 @@
   PopLocal             r2
 Try #0 start:
   PushConstant         CP#3
-  DirectCall           1, CP#4
+  DirectCall           CP#4, 1
   Drop1
   Jump                 L1
 Try #0 end:
@@ -372,7 +372,7 @@
   PopLocal             r4
   Push                 r0
   LoadContextVar       0, 0
-  DirectCall           1, CP#4
+  DirectCall           CP#4, 1
   Drop1
   Push                 r0
   PushInt              3
@@ -395,7 +395,7 @@
   PopLocal             r2
 Try #0 start:
   PushConstant         CP#24
-  DirectCall           1, CP#4
+  DirectCall           CP#4, 1
   Drop1
   Jump                 L1
 Try #0 end:
@@ -407,7 +407,7 @@
   MoveSpecial          stackTrace, r3
   Push                 r2
   PushConstant         CP#25
-  InterfaceCall        2, CP#26
+  InterfaceCall        CP#26, 2
   JumpIfFalse          L2
   Push                 r2
   PopLocal             r4
@@ -432,8 +432,8 @@
   Push                 r0
   LoadContextVar       0, 2
   StoreIndexedTOS
-  DirectCall           1, CP#21
-  DirectCall           1, CP#4
+  DirectCall           CP#21, 1
+  DirectCall           CP#4, 1
   Drop1
   Jump                 L1
 L2:
@@ -458,7 +458,7 @@
 Try #0 start:
 Try #1 start:
   PushConstant         CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L1
 Try #1 end:
@@ -470,7 +470,7 @@
   PopLocal             r4
 Try #2 start:
   PushConstant         CP#4
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Push                 FP[-5]
   AssertBoolean        0
@@ -488,7 +488,7 @@
   Push                 r5
   PopLocal             r7
   PushConstant         CP#5
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L3
 L3:
@@ -505,10 +505,10 @@
   Push                 r1
   PopLocal             r3
   PushConstant         CP#6
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Push                 r3
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L4
 L4:
@@ -516,9 +516,9 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 2, end 32, handler 32, needs-stack-trace, types [CP#3]
-  try-index 1, outer 0, start 2, end 6, handler 6, needs-stack-trace, types [CP#3]
-  try-index 2, outer 0, start 11, end 21, handler 21, types [CP#3]
+  try-index 0, outer -1, start 4, end 80, handler 80, needs-stack-trace, types [CP#3]
+  try-index 1, outer 0, start 4, end 14, handler 14, needs-stack-trace, types [CP#3]
+  try-index 2, outer 0, start 26, end 50, handler 50, types [CP#3]
 }
 ConstantPool {
   [0] = ObjectRef 'try 1 > try 2'
@@ -561,19 +561,19 @@
   MoveSpecial          exception, r1
   MoveSpecial          stackTrace, r2
   Push                 r0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Push                 r1
   Push                 r2
   Throw                1
 L3:
   Push                 r0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L1
 L4:
   Push                 r0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Push                 r0
   PushInt              1
@@ -586,7 +586,7 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 9, end 15, handler 15, needs-stack-trace, types [CP#0]
+  try-index 0, outer -1, start 19, end 36, handler 36, needs-stack-trace, types [CP#0]
 }
 ConstantPool {
   [0] = Type dynamic
@@ -613,11 +613,11 @@
   PopLocal             r2
   Push                 r2
   PushInt              1
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L1
   Push                 r2
   PushInt              2
-  InterfaceCall        2, CP#0
+  InterfaceCall        CP#0, 2
   JumpIfTrue           L2
   Jump                 L3
 L1:
@@ -625,7 +625,7 @@
   PopLocal             r3
 Try #0 start:
   PushConstant         CP#2
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Push                 r0
   PushInt              3
@@ -634,7 +634,7 @@
   PopLocal             r5
 Try #1 start:
   PushConstant         CP#5
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   AllocateClosure      CP#6
   StoreLocal           r8
@@ -655,7 +655,7 @@
   StoreFieldTOS        CP#7
   PopLocal             r7
   Push                 r7
-  DynamicCall          1, CP#20
+  DynamicCall          CP#20, 1
   Drop1
   Jump                 L4
 Try #1 end:
@@ -666,7 +666,7 @@
   MoveSpecial          exception, r5
   MoveSpecial          stackTrace, r6
   PushConstant         CP#22
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Push                 r5
   Push                 r6
@@ -675,7 +675,7 @@
   Push                 r5
   PopLocal             r0
   PushConstant         CP#22
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Jump                 L5
 Try #0 end:
@@ -686,7 +686,7 @@
   MoveSpecial          exception, r3
   MoveSpecial          stackTrace, r4
   PushConstant         CP#24
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Push                 r3
   Push                 r4
@@ -695,12 +695,12 @@
   Push                 r3
   PopLocal             r0
   PushConstant         CP#24
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Jump                 L2
 L2:
   PushConstant         CP#25
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Jump                 L3
 L3:
@@ -708,8 +708,8 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 21, end 71, handler 71, needs-stack-trace, types [CP#21]
-  try-index 1, outer 0, start 29, end 54, handler 54, needs-stack-trace, types [CP#21]
+  try-index 0, outer -1, start 53, end 158, handler 158, needs-stack-trace, types [CP#21]
+  try-index 1, outer 0, start 70, end 120, handler 120, needs-stack-trace, types [CP#21]
 }
 ConstantPool {
   [0] = InterfaceCall 'dart:core::Object::==', ArgDesc num-args 2, num-type-args 0, names []
@@ -748,11 +748,11 @@
   PopLocal             r0
   Push                 r0
   LoadContextVar       0, 0
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   PushNull
   ReturnTOS
@@ -806,10 +806,10 @@
   MoveSpecial          stackTrace, r4
   Push                 r0
   LoadContextVar       0, 0
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Push                 r2
-  DynamicCall          1, CP#19
+  DynamicCall          CP#19, 1
   Drop1
   Push                 r3
   Push                 r4
@@ -819,10 +819,10 @@
   PopLocal             r0
   Push                 r0
   LoadContextVar       0, 0
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Push                 r2
-  DynamicCall          1, CP#20
+  DynamicCall          CP#20, 1
   Drop1
   Push                 r0
   LoadContextParent
@@ -831,7 +831,7 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 11, end 30, handler 30, needs-stack-trace, types [CP#6]
+  try-index 0, outer -1, start 23, end 61, handler 61, needs-stack-trace, types [CP#6]
 }
 ConstantPool {
   [0] = ClosureFunction 0
@@ -865,13 +865,13 @@
   PopLocal             r0
   Push                 r0
   LoadContextVar       0, 0
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Push                 r0
   PopLocal             r2
 Try #0 start:
   PushConstant         CP#5
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Jump                 L1
 Try #0 end:
@@ -885,7 +885,7 @@
   PopLocal             r4
 Try #1 start:
   PushConstant         CP#7
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Jump                 L2
 Try #1 end:
@@ -897,7 +897,7 @@
   MoveSpecial          stackTrace, r5
   Push                 r0
   LoadContextVar       0, 0
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Push                 r4
   Push                 r5
@@ -907,7 +907,7 @@
   PopLocal             r0
   Push                 r0
   LoadContextVar       0, 0
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   PushInt              43
   ReturnTOS
@@ -918,7 +918,7 @@
   PopLocal             r4
 Try #2 start:
   PushConstant         CP#7
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Jump                 L3
 Try #2 end:
@@ -930,7 +930,7 @@
   MoveSpecial          stackTrace, r5
   Push                 r0
   LoadContextVar       0, 0
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   Push                 r4
   Push                 r5
@@ -940,7 +940,7 @@
   PopLocal             r0
   Push                 r0
   LoadContextVar       0, 0
-  DirectCall           1, CP#3
+  DirectCall           CP#3, 1
   Drop1
   PushInt              43
   ReturnTOS
@@ -959,7 +959,7 @@
 Try #0 start:
 Try #1 start:
   PushConstant         CP#0
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L1
 Try #1 end:
@@ -970,7 +970,7 @@
   Push                 r2
   PopLocal             r4
   PushConstant         CP#4
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Jump                 L1
 L1:
@@ -981,21 +981,21 @@
   MoveSpecial          exception, r0
   MoveSpecial          stackTrace, r1
   PushConstant         CP#5
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   Push                 r0
   Push                 r1
   Throw                1
 L2:
   PushConstant         CP#5
-  DirectCall           1, CP#1
+  DirectCall           CP#1, 1
   Drop1
   PushNull
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 2, end 16, handler 16, needs-stack-trace, types [CP#3]
-  try-index 1, outer 0, start 2, end 6, handler 6, types [CP#3]
+  try-index 0, outer -1, start 4, end 40, handler 40, needs-stack-trace, types [CP#3]
+  try-index 1, outer 0, start 4, end 14, handler 14, types [CP#3]
 }
 ConstantPool {
   [0] = ObjectRef 'try'
@@ -1119,7 +1119,7 @@
     #L2:
     switch(x) {
       #L3:
-      case #C1:
+      case 1:
         {
           try {
             dart.core::print("before try 1");
@@ -1144,7 +1144,7 @@
           break #L2;
         }
       #L4:
-      case #C2:
+      case 2:
         {
           dart.core::print("case 2");
           break #L2;
@@ -1191,7 +1191,3 @@
   }
   static method main() → dynamic {}
 }
-constants  {
-  #C1 = 1
-  #C2 = 2
-}
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index 22da680..ca572e8 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -23,20 +23,20 @@
   CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#0
-  InterfaceCall        2, CP#1
+  InterfaceCall        CP#1, 2
   JumpIfFalse          L1
   PushConstant         CP#3
-  DirectCall           1, CP#4
+  DirectCall           CP#4, 1
   Drop1
 L1:
   Push                 FP[-5]
   PushNull
   PushNull
   PushConstant         CP#6
-  InterfaceCall        4, CP#7
+  InterfaceCall        CP#7, 4
   JumpIfFalse          L2
   PushConstant         CP#9
-  DirectCall           1, CP#4
+  DirectCall           CP#4, 1
   Drop1
 L2:
   Push                 FP[-5]
@@ -123,7 +123,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -155,7 +155,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -187,7 +187,7 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           1, CP#0
+  DirectCall           CP#0, 1
   Drop1
   PushNull
   ReturnTOS
@@ -230,7 +230,7 @@
   AssertAssignable     0, CP#3
   StoreFieldTOS        CP#4
   Push                 FP[-6]
-  DirectCall           1, CP#6
+  DirectCall           CP#6, 1
   Drop1
   PushNull
   ReturnTOS
@@ -260,10 +260,10 @@
   LoadTypeArgumentsField CP#0
   PushNull
   PushConstant         CP#1
-  InterfaceCall        4, CP#2
+  InterfaceCall        CP#2, 4
   JumpIfFalse          L1
   PushConstant         CP#4
-  DirectCall           1, CP#5
+  DirectCall           CP#5, 1
   Drop1
 L1:
   Push                 FP[-5]
@@ -271,10 +271,10 @@
   LoadTypeArgumentsField CP#0
   PushNull
   PushConstant         CP#7
-  InterfaceCall        4, CP#2
+  InterfaceCall        CP#2, 4
   JumpIfFalse          L2
   PushConstant         CP#8
-  DirectCall           1, CP#5
+  DirectCall           CP#5, 1
   Drop1
 L2:
   Push                 FP[-6]
@@ -285,7 +285,7 @@
   PushNull
   PushConstant         CP#10
   AssertAssignable     0, CP#11
-  UncheckedInterfaceCall 2, CP#12
+  UncheckedInterfaceCall CP#12, 2
   Drop1
   PushNull
   ReturnTOS
@@ -322,10 +322,10 @@
   PushNull
   Push                 r0
   PushConstant         CP#0
-  InterfaceCall        4, CP#1
+  InterfaceCall        CP#1, 4
   JumpIfFalse          L1
   PushConstant         CP#3
-  DirectCall           1, CP#4
+  DirectCall           CP#4, 1
   Drop1
 L1:
   Push                 FP[-5]
@@ -333,10 +333,10 @@
   LoadTypeArgumentsField CP#6
   Push                 r0
   PushConstant         CP#7
-  InterfaceCall        4, CP#1
+  InterfaceCall        CP#1, 4
   JumpIfFalse          L2
   PushConstant         CP#8
-  DirectCall           1, CP#4
+  DirectCall           CP#4, 1
   Drop1
 L2:
   Push                 FP[-5]
@@ -346,7 +346,7 @@
   Push                 r0
   PushConstant         CP#10
   AssertAssignable     0, CP#11
-  InterfaceCall        1, CP#12
+  InterfaceCall        CP#12, 1
   ReturnTOS
 }
 ConstantPool {
@@ -394,7 +394,7 @@
   PushConstant         CP#3
   AssertAssignable     0, CP#4
   StoreIndexedTOS
-  DirectCall           2, CP#5
+  DirectCall           CP#5, 2
   PopLocal             r0
   Push                 FP[-5]
   PushConstant         CP#2
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/freeze_test.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/freeze_test.dart
new file mode 100644
index 0000000..0529e4a
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/freeze_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, 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:test/test.dart';
+
+import 'generated/foo.pb.dart';
+
+main() {
+  FooKeep foo = FooKeep()
+    ..barKeep = (BarKeep()..aKeep = 5)
+    ..mapKeep['foo'] = (BarKeep()..aKeep = 2)
+    ..aKeep = 43;
+  test('Freezing a message works', () {
+    foo.freeze();
+    expect(foo.barKeep.aKeep, 5);
+    expect(foo.mapKeep['foo'].aKeep, 2);
+    expect(foo.hasHasKeep(), false);
+    expect(foo.aKeep, 43);
+    expect(() => foo.clearClearKeep(),
+        throwsA(const TypeMatcher<UnsupportedError>()));
+  });
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
index 16476c9..ea11fc1 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
@@ -2,37 +2,44 @@
 import self as self;
 import "dart:core" as core;
 
-@#C5
+@self::TypedefAnnotation::•(const <core::int>[1, 2, 3])
 typedef SomeType<T extends core::Object = dynamic> = (core::List<T>) → void;
 abstract class ClassAnnotation2 extends core::Object {
+[@vm.unreachable.metadata=]  const constructor •() → self::ClassAnnotation2
+    throw "Attempt to execute method removed by Dart AOT compiler (TFA)";
 }
 abstract class MethodAnnotation extends core::Object {
-[@vm.unreachable.metadata=]  final field core::int x;
+[@vm.unreachable.metadata=]  const constructor •(core::int x) → self::MethodAnnotation
+    throw "Attempt to execute method removed by Dart AOT compiler (TFA)";
 }
 abstract class TypedefAnnotation extends core::Object {
-[@vm.unreachable.metadata=]  final field core::List<core::int> list;
+[@vm.unreachable.metadata=]  const constructor •(core::List<core::int> list) → self::TypedefAnnotation
+    throw "Attempt to execute method removed by Dart AOT compiler (TFA)";
 }
 abstract class VarAnnotation extends core::Object {
+[@vm.unreachable.metadata=]  const constructor •() → self::VarAnnotation
+    throw "Attempt to execute method removed by Dart AOT compiler (TFA)";
 }
 abstract class ParametrizedAnnotation<T extends core::Object = dynamic> extends core::Object {
-[@vm.unreachable.metadata=]  final field self::ParametrizedAnnotation::T foo;
+[@vm.unreachable.metadata=]  const constructor •(self::ParametrizedAnnotation::T foo) → self::ParametrizedAnnotation<self::ParametrizedAnnotation::T>
+    throw "Attempt to execute method removed by Dart AOT compiler (TFA)";
 }
 abstract class A extends core::Object {
   static method staticMethod() → void {}
 }
-@#C6
+@self::ClassAnnotation2::•()
 class B extends core::Object {
   synthetic constructor •() → self::B
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  @#C8
+[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  @self::MethodAnnotation::•(42)
   method instanceMethod() → void {}
 }
 static method foo([@vm.inferred-type.metadata=dart.core::Null?] (core::List<core::int>) → void a) → core::int {
-  @#C9 core::int x = 2;
-  return [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int (skip check)] x.{core::num::+}(2);
+  @self::VarAnnotation::•() core::int x = 2;
+  return [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int? (skip check)] x.{core::num::+}(2);
 }
-@#C11
+@self::ParametrizedAnnotation::•<core::Null>(null)
 static method main(core::List<core::String> args) → dynamic {
   self::A::staticMethod();
   [@vm.direct-call.metadata=#lib::B::instanceMethod] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::instanceMethod}();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect
index fa9c87b..ffdd14f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect
@@ -3,21 +3,21 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-static method isPrime([@vm.inferred-type.metadata=int] dynamic n) → core::bool {
-  if(_in::unsafeCast<core::bool>([@vm.direct-call.metadata=dart.core::_IntegerImplementation::<] [@vm.inferred-type.metadata=dart.core::bool] n.<(2)))
+static method isPrime([@vm.inferred-type.metadata=int?] dynamic n) → core::bool {
+  if(_in::unsafeCast<core::bool>([@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] [@vm.inferred-type.metadata=dart.core::bool] n.<(2)))
     return false;
-  for (core::int i = 2; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<=] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation::*] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::*}(i).{core::num::<=}(_in::unsafeCast<core::num>(n)); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1)) {
-    if([@vm.direct-call.metadata=dart.core::_IntegerImplementation::==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation::%] [@vm.inferred-type.metadata=int] n.%(i).{core::Object::==}(0))
+  for (core::int i = 2; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<=??] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation::*??] [@vm.inferred-type.metadata=int? (skip check)] i.{core::num::*}(i).{core::num::<=}(_in::unsafeCast<core::num>(n)); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int? (skip check)] i.{core::num::+}(1)) {
+    if([@vm.inferred-type.metadata=dart.core::bool] [@vm.direct-call.metadata=dart.core::_IntegerImplementation::%??] [@vm.inferred-type.metadata=int?] n.%(i).{core::Object::==}(0))
       return false;
   }
   return true;
 }
 static method nThPrimeNumber([@vm.inferred-type.metadata=dart.core::_Smi] core::int n) → core::int {
   core::int counter = 0;
-  for (core::int i = 1; ; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1)) {
+  for (core::int i = 1; ; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int? (skip check)] i.{core::num::+}(1)) {
     if([@vm.inferred-type.metadata=dart.core::bool] self::isPrime(i))
-      counter = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int (skip check)] counter.{core::num::+}(1);
-    if([@vm.direct-call.metadata=dart.core::_IntegerImplementation::==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] counter.{core::num::==}(n)) {
+      counter = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int? (skip check)] counter.{core::num::+}(1);
+    if([@vm.inferred-type.metadata=dart.core::bool] counter.{core::num::==}(n)) {
       return i;
     }
   }
@@ -31,7 +31,7 @@
 }
 static method main(core::List<core::String> args) → dynamic {
   core::Stopwatch timer = let final core::Stopwatch #t1 = new core::Stopwatch::•() in let final dynamic #t2 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] [@vm.inferred-type.metadata=!? (skip check)] #t1.{core::Stopwatch::start}() in #t1;
-  for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1)) {
+  for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int? (skip check)] i.{core::num::+}(1)) {
     self::run();
   }
   [@vm.direct-call.metadata=dart.core::Stopwatch::stop] [@vm.inferred-type.metadata=!? (skip check)] timer.{core::Stopwatch::stop}();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
index 7fa4e1f..fb2975e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -12,14 +12,14 @@
   constructor •([@vm.inferred-type.metadata=dart.core::_Smi] core::int size) → self::_Vector
     : self::_Vector::_offset = 0, self::_Vector::_length = size, self::_Vector::_elements = [@vm.inferred-type.metadata=dart.typed_data::_Float64List] typ::Float64List::•(size), super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=hasTearOffUses:false]  operator []([@vm.inferred-type.metadata=!] core::int i) → core::double
-    return [@vm.direct-call.metadata=dart.typed_data::_Float64List::[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector::_elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}.{core::List::[]}([@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector::_offset] [@vm.inferred-type.metadata=dart.core::_Smi] this.{self::_Vector::_offset}));
+[@vm.procedure-attributes.metadata=hasTearOffUses:false]  operator [](core::int i) → core::double
+    return [@vm.direct-call.metadata=dart.typed_data::_Float64List::[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector::_elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}.{core::List::[]}([@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int? (skip check)] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector::_offset] [@vm.inferred-type.metadata=dart.core::_Smi] this.{self::_Vector::_offset}));
 [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  operator []=([@vm.inferred-type.metadata=dart.core::_OneByteString] core::int i, core::double value) → void {
     let dynamic #t1 = [@vm.direct-call.metadata=#lib::_Vector::_elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements} in let dynamic #t2 = i in let dynamic #t3 = [@vm.direct-call.metadata=#lib::_Vector::_offset] [@vm.inferred-type.metadata=dart.core::_Smi] this.{self::_Vector::_offset} in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
   }
 [@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  operator *([@vm.inferred-type.metadata=#lib::_Vector?] self::_Vector a) → core::double {
     core::double result = 0.0;
-    for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=dart.core::_Smi] this.{self::_Vector::_length}); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1))
+    for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=dart.core::_Smi] this.{self::_Vector::_length}); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int? (skip check)] i.{core::num::+}(1))
       result = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double::*] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] this.{self::_Vector::[]}(i).{core::double::*}([@vm.direct-call.metadata=#lib::_Vector::[]??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] a.{self::_Vector::[]}(i)));
     return result;
   }
@@ -28,7 +28,7 @@
 [@vm.inferred-type.metadata=dart.core::_Double?]static field core::double x = 0.0;
 static method main(core::List<core::String> args) → dynamic {
   core::Stopwatch timer = let final core::Stopwatch #t4 = new core::Stopwatch::•() in let final dynamic #t5 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] [@vm.inferred-type.metadata=!? (skip check)] #t4.{core::Stopwatch::start}() in #t4;
-  for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100000000); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1)) {
+  for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100000000); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int? (skip check)] i.{core::num::+}(1)) {
     self::x = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=dart.core::_Double?] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector::*??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=#lib::_Vector?] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector?] self::v));
   }
   [@vm.direct-call.metadata=dart.core::Stopwatch::stop] [@vm.inferred-type.metadata=!? (skip check)] timer.{core::Stopwatch::stop}();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
index d508c60..aee6417 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
@@ -42,7 +42,7 @@
 static method callerA2([@vm.inferred-type.metadata=#lib::B] self::A aa) → void {
   [@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}();
 }
-static method callerA3({[@vm.inferred-type.metadata=#lib::C] self::A aa = #C1}) → void {
+static method callerA3({[@vm.inferred-type.metadata=#lib::C] self::A aa = null}) → void {
   [@vm.direct-call.metadata=#lib::C::foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}();
 }
 static method callerA4([@vm.inferred-type.metadata=#lib::D?] self::A aa) → void {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
index 1762eb3..999e779 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
@@ -21,13 +21,13 @@
   synthetic constructor •() → self::Stream
     : super core::Object::•()
     ;
-  abstract method foobar((dynamic) → void onData, {core::Function onError = #C1}) → self::StreamSubscription;
+  abstract method foobar((dynamic) → void onData, {core::Function onError = null}) → self::StreamSubscription;
 }
 abstract class _StreamImpl extends self::Stream {
   synthetic constructor •() → self::_StreamImpl
     : super self::Stream::•()
     ;
-[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  method foobar([@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData, {[@vm.inferred-type.metadata=dart.core::Null?] core::Function onError = #C1}) → self::StreamSubscription {
+[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  method foobar([@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData, {[@vm.inferred-type.metadata=dart.core::Null?] core::Function onError = null}) → self::StreamSubscription {
     return [@vm.inferred-type.metadata=!] this.{self::_StreamImpl::_createSubscription}();
   }
 [@vm.procedure-attributes.metadata=hasDynamicUses:false,hasNonThisUses:false,hasTearOffUses:false]  method _createSubscription() → self::StreamSubscription {
@@ -52,7 +52,7 @@
   constructor •([@vm.inferred-type.metadata=!] self::Stream stream) → self::StreamView
     : self::StreamView::_stream = stream, super self::Stream::•()
     ;
-[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasTearOffUses:false]  method foobar([@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData, {[@vm.inferred-type.metadata=dart.core::Null?] core::Function onError = #C1}) → self::StreamSubscription {
+[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasTearOffUses:false]  method foobar([@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData, {[@vm.inferred-type.metadata=dart.core::Null?] core::Function onError = null}) → self::StreamSubscription {
     return [@vm.direct-call.metadata=#lib::StreamView::_stream] [@vm.inferred-type.metadata=!] this.{self::StreamView::_stream}.{self::Stream::foobar}(onData, onError: onError);
   }
 }
@@ -66,7 +66,7 @@
 [@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  method super_foobar2([@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData) → dynamic {
     super.{self::StreamView::foobar}(onData);
   }
-[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  method super_foobar3({[@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData = #C1, [@vm.inferred-type.metadata=dart.core::Null?] core::Function onError = #C1}) → dynamic {
+[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  method super_foobar3({[@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData = null, [@vm.inferred-type.metadata=dart.core::Null?] core::Function onError = null}) → dynamic {
     super.{self::StreamView::foobar}(onData, onError: onError);
   }
   get super_stream() → self::Stream
@@ -80,23 +80,23 @@
 static method round0() → void {
   new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
 }
-static method round1({[@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData = #C1}) → void {
+static method round1({[@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData = null}) → void {
   self::ByteStream x = new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
   [@vm.direct-call.metadata=#lib::ByteStream::super_foobar1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar1}(onData);
 }
-static method round2({[@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData = #C1, [@vm.inferred-type.metadata=dart.core::Null?] core::Function onError = #C1}) → void {
+static method round2({[@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData = null, [@vm.inferred-type.metadata=dart.core::Null?] core::Function onError = null}) → void {
   new self::_ControllerStream::•();
   self::Stream x = new self::_GeneratedStreamImpl::•();
   x = new self::ByteStream::•(x);
   x.{self::Stream::foobar}(onData, onError: onError);
 }
-static method round3({[@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData = #C1, [@vm.inferred-type.metadata=dart.core::Null?] core::Function onError = #C1}) → void {
+static method round3({[@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData = null, [@vm.inferred-type.metadata=dart.core::Null?] core::Function onError = null}) → void {
   self::Stream x = new self::_GeneratedStreamImpl::•();
   x = new self::ByteStream::•(x);
   x = new self::_ControllerStream::•();
   x.{self::Stream::foobar}(onData, onError: onError);
 }
-static method round4({[@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData = #C1}) → void {
+static method round4({[@vm.inferred-type.metadata=dart.core::Null?] (dynamic) → void onData = null}) → void {
   self::ByteStream x = new self::ByteStream::•(new self::_ControllerStream::•());
   self::Stream y = [@vm.direct-call.metadata=#lib::ByteStream::super_stream] [@vm.inferred-type.metadata=!] x.{self::ByteStream::super_stream};
   self::Stream z = [@vm.direct-call.metadata=#lib::StreamView::_stream] [@vm.inferred-type.metadata=!] x.{self::StreamView::_stream};
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
index 1b22241..5fc9b87 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
@@ -39,27 +39,27 @@
     ;
   abstract method foo() → dynamic;
   abstract get bar() → dynamic;
-  abstract method bazz(dynamic a1, dynamic a2, dynamic a3, [dynamic a4 = #C1, dynamic a5 = #C1]) → dynamic;
+  abstract method bazz(dynamic a1, dynamic a2, dynamic a3, [dynamic a4 = null, dynamic a5 = null]) → dynamic;
 }
 class B extends self::A {
   synthetic constructor •() → self::B
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasTearOffUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
+[@vm.procedure-attributes.metadata=hasDynamicUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T1::•();
   }
   no-such-method-forwarder get bar() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B::noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(#C5))));
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B::noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#bar, 1, const <core::Type>[], const <dynamic>[], [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))));
 [@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  no-such-method-forwarder method foo() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B::noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(#C5))));
-[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi] dynamic a3, [[@vm.inferred-type.metadata=dart.core::_Smi] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::Null?] dynamic a5 = #C1]) → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B::noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, a5]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(#C5))));
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B::noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type>[], const <dynamic>[], [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))));
+[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi] dynamic a3, [[@vm.inferred-type.metadata=dart.core::_Smi] dynamic a4 = null, [@vm.inferred-type.metadata=dart.core::Null?] dynamic a5 = null]) → dynamic
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B::noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#bazz, 0, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, a5]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))));
 }
 abstract class C extends core::Object {
   synthetic constructor •() → self::C
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasTearOffUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
+[@vm.procedure-attributes.metadata=hasDynamicUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T2::•();
   }
 }
@@ -68,27 +68,27 @@
     : super self::C::•()
     ;
   no-such-method-forwarder get bar() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C::noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(#C5))));
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C::noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#bar, 1, const <core::Type>[], const <dynamic>[], [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))));
 [@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  no-such-method-forwarder method foo() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C::noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(#C5))));
-[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi] dynamic a3, [[@vm.inferred-type.metadata=dart.core::_Smi] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::Null?] dynamic a5 = #C1]) → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C::noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, a5]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(#C5))));
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C::noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type>[], const <dynamic>[], [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))));
+[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi] dynamic a3, [[@vm.inferred-type.metadata=dart.core::_Smi] dynamic a4 = null, [@vm.inferred-type.metadata=dart.core::Null?] dynamic a5 = null]) → dynamic
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C::noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#bazz, 0, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, a5]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))));
 }
 class E extends core::Object implements self::A {
   synthetic constructor •() → self::E
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasTearOffUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
+[@vm.procedure-attributes.metadata=hasDynamicUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T4::•();
   }
   no-such-method-forwarder get bar() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::E::noSuchMethod] [@vm.inferred-type.metadata=#lib::T4 (skip check)] this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(#C5))));
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::E::noSuchMethod] [@vm.inferred-type.metadata=#lib::T4 (skip check)] this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#bar, 1, const <core::Type>[], const <dynamic>[], [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol, dynamic>] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))));
 }
 class F extends core::Object {
   synthetic constructor •() → self::F
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
+[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T2::•();
   }
 }
@@ -96,7 +96,7 @@
   synthetic constructor •() → self::G
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
+[@vm.procedure-attributes.metadata=hasThisUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T5::•();
   }
 }
@@ -104,9 +104,9 @@
   synthetic constructor •() → self::H
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method foo({[@vm.inferred-type.metadata=dart.core::_Smi] dynamic left = #C1, [@vm.inferred-type.metadata=dart.core::_Smi] dynamic right = #C1}) → dynamic
+[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method foo({[@vm.inferred-type.metadata=dart.core::_Smi] dynamic left = null, [@vm.inferred-type.metadata=dart.core::_Smi] dynamic right = null}) → dynamic
     return new self::T6::•();
-[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
+[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T7::•();
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
index 7f64259..472fbbd 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
@@ -54,7 +54,7 @@
   return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call(x);
 static method main(core::List<core::String> args) → dynamic {
   self::func1(self::getDynamic() as{TypeError} self::T0);
-  self::use(#C1);
+  self::use(self::func2);
   self::use(new self::A::•().{self::A::method1});
   self::B bb = self::getDynamic() as{TypeError} self::B;
   [@vm.direct-call.metadata=#lib::C::method2??] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B::method2}(self::getDynamic());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
index 36dbf0d..0630a2a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
@@ -19,7 +19,7 @@
   synthetic constructor •() → self::A1
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=#lib::T1?] dynamic a5 = #C1]) → void {
+[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method call([dynamic a1 = null, dynamic a2 = null, dynamic a3 = null, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = null, [@vm.inferred-type.metadata=#lib::T1?] dynamic a5 = null]) → void {
     [@vm.direct-call.metadata=#lib::A1::foo] this.{self::A1::foo} = _in::unsafeCast<self::T1>(a5);
   }
 }
@@ -42,7 +42,7 @@
   synthetic constructor •() → self::A2
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=#lib::T2?] dynamic a6 = #C1]) → void {
+[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method call([dynamic a1 = null, dynamic a2 = null, dynamic a3 = null, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = null, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = null, [@vm.inferred-type.metadata=#lib::T2?] dynamic a6 = null]) → void {
     [@vm.direct-call.metadata=#lib::A2::foo] this.{self::A2::foo} = a6;
   }
 }
@@ -75,7 +75,7 @@
   synthetic constructor •() → self::A3
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=#lib::T3?] dynamic a7 = #C1]) → void {
+[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method call([dynamic a1 = null, dynamic a2 = null, dynamic a3 = null, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = null, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = null, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = null, [@vm.inferred-type.metadata=#lib::T3?] dynamic a7 = null]) → void {
     [@vm.direct-call.metadata=#lib::A3::foo] this.{self::A3::foo} = a7;
   }
 }
@@ -98,7 +98,7 @@
   synthetic constructor •() → self::A4
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a7 = #C1, [@vm.inferred-type.metadata=#lib::T4?] dynamic a8 = #C1]) → void {
+[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method call([dynamic a1 = null, dynamic a2 = null, dynamic a3 = null, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = null, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = null, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = null, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a7 = null, [@vm.inferred-type.metadata=#lib::T4?] dynamic a8 = null]) → void {
     [@vm.direct-call.metadata=#lib::A4::foo] this.{self::A4::foo} = a8;
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
index 3c1beb0..2c96882 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
@@ -12,7 +12,7 @@
     : super self::A::•()
     ;
 [@vm.procedure-attributes.metadata=hasThisUses:false]  method foo() → core::int
-    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=! (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
+    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=!? (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
 }
 class TearOffDynamicMethod extends core::Object {
 [@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false]  field dynamic bazz;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
index ccb925f..66af620 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
@@ -14,7 +14,7 @@
     : super self::A::•()
     ;
 [@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasNonThisUses:false]  method foo() → core::int
-    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B::bar] [@vm.inferred-type.metadata=dart.core::_Smi] [@vm.inferred-type.metadata=#lib::B] self::knownResult().bar())));
+    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int? (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B::bar] [@vm.inferred-type.metadata=dart.core::_Smi] [@vm.inferred-type.metadata=#lib::B] self::knownResult().bar())));
 [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method bar() → core::int
     return 3;
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
index b147844..950a81d 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
@@ -14,14 +14,14 @@
     : super self::A::•()
     ;
 [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false]  method foo() → core::int
-    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=int?] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo())));
+    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int? (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=int?] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo())));
 }
 abstract class Base extends core::Object {
   synthetic constructor •() → self::Base
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasNonThisUses:false]  method foo() → core::int
-    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int (skip check)] 3.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=int?] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo())));
+    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int? (skip check)] 3.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=int?] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo())));
 [@vm.procedure-attributes.metadata=hasDynamicUses:false,hasNonThisUses:false,hasTearOffUses:false]  method doCall(dynamic x) → core::int
     return [@vm.call-site-attributes.metadata=receiverType:dynamic] x.call() as{TypeError} core::int;
 }
diff --git a/pkg/vm/tool/test_bytecode b/pkg/vm/tool/test_bytecode
deleted file mode 100755
index 9f800ab..0000000
--- a/pkg/vm/tool/test_bytecode
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) 2018, 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.
-
-# Script for generating bytecode in a kernel file using Dart 2 pipeline and
-# interpreting the resulting bytecode.
-
-# Usage
-# pkg/vm/tool/test_bytecode ~/foo.dart
-
-set -e
-
-# Pick the architecture and mode to test.
-BUILD_FLAGS="-m release -a x64"
-BUILD_SUBDIR="ReleaseX64"
-
-function follow_links() {
-  file="$1"
-  while [ -h "$file" ]; do
-    # On Mac OS, readlink -f doesn't work.
-    file="$(readlink "$file")"
-  done
-  echo "$file"
-}
-
-# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-
-# Handle the case where dart-sdk/bin has been symlinked to.
-CUR_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-
-SDK_DIR="$CUR_DIR/../../.."
-BUILD_DIR="$SDK_DIR/out/$BUILD_SUBDIR"
-
-# Regenerate vm_platform_strong.dill to contain bytecode if needed:
-# $SDK_DIR/tools/gn.py $BUILD_FLAGS --bytecode
-# $SDK_DIR/tools/build.py $BUILD_FLAGS runtime
-
-# Generate dill file containing bytecode for input dart source.
-$CUR_DIR/gen_kernel --platform $BUILD_DIR/vm_platform_strong.dill \
-  --gen-bytecode $@ -o $BUILD_DIR/test_bytecode.dill
-
-# Dump bytecode in generated vm_platform_strong.dill file to platform.txt.
-# $BUILD_DIR/dart $SDK_DIR/pkg/vm/bin/dump_kernel.dart \
-#   $BUILD_DIR/vm_platform_strong.dill $BUILD_DIR/platform.txt
-
-# Dump bytecode in generated test_bytecode.dill file to test_bytecode.txt.
-# $BUILD_DIR/dart $SDK_DIR/pkg/vm/bin/dump_kernel.dart \
-#   $BUILD_DIR/test_bytecode.dill $BUILD_DIR/test_bytecode.txt
-
-# Required flag.
-DART_VM_FLAGS="--enable-interpreter $DART_VM_FLAGS"
-
-# Optional flags examples. Uncomment as needed.
-# DART_VM_FLAGS="--compilation-counter-threshold=-1 $DART_VM_FLAGS"
-# DART_VM_FLAGS="--force-log-flush --isolate-log-filter=\"\" $DART_VM_FLAGS"
-# DART_VM_FLAGS="--dump-kernel-bytecode $DART_VM_FLAGS"
-# DART_VM_FLAGS="--trace-interpreter-after=0 $DART_VM_FLAGS"
-
-# Execute dill file.
-exec $BUILD_DIR/dart $DART_VM_FLAGS $BUILD_DIR/test_bytecode.dill
-
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 9ef4444..20419e7 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -6,6 +6,10 @@
 import("configs.gni")
 import("runtime_args.gni")
 
+if (is_fuchsia) {
+  import("//build/fuchsia/sdk.gni")
+}
+
 config("dart_public_config") {
   include_dirs = [
     ".",
@@ -143,7 +147,16 @@
   }
 
   if (is_fuchsia) {
-    include_dirs += [ "//zircon/system/ulib/zx/include" ]
+    if (using_fuchsia_sdk) {
+      # TODO(chinmaygarde): Currenty these targets need to be build in the
+      # Fuchsia tree as well as outside it using the SDK. However, not all
+      # Fuchsia features are available in the SDK. As these features are added,
+      # the guards can be removed. Eventually, only SDK builds will be present.
+      # Then, this flag can be removed completely.
+      defines += [ "FUCHSIA_SDK" ]
+    } else {
+      include_dirs += [ "//zircon/system/ulib/zx/include" ]
+    }
   }
 
   if (!is_win) {
@@ -202,6 +215,12 @@
   }
 }
 
+config("dart_libfuzzer_config") {
+  defines = [ "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" ]
+  cflags = [ "-fsanitize=address,fuzzer-no-link" ]
+  ldflags = [ "-fsanitize=address,fuzzer" ]
+}
+
 source_set("dart_api") {
   public_configs = [ ":dart_public_config" ]
   sources = [
@@ -218,10 +237,14 @@
     ":generate_version_cc_file",
   ]
   if (is_fuchsia) {
-    extra_deps += [
-      "//zircon/public/lib/fbl",
-      "//zircon/public/lib/trace-engine",
-    ]
+    if (using_fuchsia_sdk) {
+      extra_deps += [ "$fuchsia_sdk_root/pkg:fdio" ]
+    } else {
+      extra_deps += [
+        "//zircon/public/lib/fbl",
+        "//zircon/public/lib/trace-engine",
+      ]
+    }
   }
   configurable_deps = [
     "platform:libdart_platform",
diff --git a/runtime/PRESUBMIT.py b/runtime/PRESUBMIT.py
index 44c53df..e790a8b 100644
--- a/runtime/PRESUBMIT.py
+++ b/runtime/PRESUBMIT.py
@@ -21,7 +21,7 @@
   match = re.search('\\bmemcpy\\b', content)
   if match:
     line_number = content[0:match.start()].count('\n') + 1
-    print "%s:%d: use of memcpy is forbidden" % (filename, line_number)
+    print("%s:%d: use of memcpy is forbidden" % (filename, line_number))
     return 1
   return 0
 
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index a13c951..5b5cacc 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -14,6 +14,10 @@
 import("io_impl_sources.gni")
 import("io_sources.gni")
 
+if (is_fuchsia) {
+  import("//build/fuchsia/sdk.gni")
+}
+
 config("libdart_builtin_config") {
   if (!is_win) {
     libs = [ "dl" ]
@@ -31,33 +35,30 @@
   if (defined(invoker.extra_configs)) {
     extra_configs += invoker.extra_configs
   }
-  static_library(target_name) {
+  source_set(target_name) {
     configs += [
                  "..:dart_arch_config",
                  "..:dart_config",
                ] + extra_configs
-    if (is_fuchsia) {
-      configs -= [ "//build/config:symbol_visibility_hidden" ]
-    }
     public_configs = [ ":libdart_builtin_config" ]
     deps = []
     if (is_fuchsia) {
-      public_deps = [
-        "//zircon/public/lib/fdio",
-      ]
+      if (using_fuchsia_sdk) {
+        public_deps = [
+          "$fuchsia_sdk_root/pkg:fdio",
+        ]
+      } else {
+        public_deps = [
+          "//zircon/public/lib/fdio",
+        ]
+      }
     }
     include_dirs = [ ".." ]
     set_sources_assignment_filter([
                                     "*_test.cc",
                                     "*_test.h",
                                   ])
-    sources = [
-                "log_android.cc",
-                "log_fuchsia.cc",
-                "log_linux.cc",
-                "log_macos.cc",
-                "log_win.cc",
-              ] + builtin_impl_sources
+    sources = builtin_impl_sources
   }
 }
 
@@ -96,9 +97,6 @@
     "..:dart_product_config",
     "..:dart_os_fuchsia_config",
   ]
-  if (is_fuchsia) {
-    configs -= [ "//build/config:symbol_visibility_hidden" ]
-  }
   include_dirs = [ ".." ]
   sources = [
     "crashpad.cc",
@@ -133,9 +131,6 @@
                  "..:dart_config",
                  "..:dart_precompiler_config",
                ] + extra_configs
-    if (is_fuchsia) {
-      configs -= [ "//build/config:symbol_visibility_hidden" ]
-    }
     deps = [ ":generate_abi_version_cc_file" ] + extra_deps
 
     defines = [ "EXCLUDE_CFE_AND_KERNEL_PLATFORM" ]
@@ -155,7 +150,6 @@
 
       # Very limited native resolver provided.
       "$target_gen_dir/abi_version.cc",
-      "builtin_common.cc",
       "builtin_gen_snapshot.cc",
       "dfe.cc",
       "dfe.h",
@@ -210,6 +204,7 @@
   extra_deps = [
     ":gen_snapshot_dart_io",
     ":libdart_builtin",
+    "../platform:libdart_platform_nosnapshot_with_precompiler",
     "..:libdart_nosnapshot_with_precompiler",
   ]
 }
@@ -222,6 +217,7 @@
   extra_deps = [
     ":gen_snapshot_dart_io_product",
     ":libdart_builtin_product",
+    "../platform:libdart_platform_nosnapshot_with_precompiler_product",
     "..:libdart_nosnapshot_with_precompiler_product",
   ]
 }
@@ -234,6 +230,7 @@
   extra_deps = [
     ":gen_snapshot_dart_io_fuchsia",
     ":libdart_builtin_fuchsia",
+    "../platform:libdart_platform_nosnapshot_with_precompiler_fuchsia",
     "..:libdart_nosnapshot_with_precompiler_fuchsia",
   ]
 }
@@ -246,6 +243,7 @@
   extra_deps = [
     ":gen_snapshot_dart_io_product_fuchsia",
     ":libdart_builtin_product_fuchsia",
+    "../platform:libdart_platform_nosnapshot_with_precompiler_product_fuchsia",
     "..:libdart_nosnapshot_with_precompiler_product_fuchsia",
   ]
 }
@@ -266,11 +264,17 @@
     deps = []
 
     if (is_fuchsia) {
-      deps += [ "//garnet/public/lib/netstack/c" ]
-      public_deps = [
-        "//zircon/public/lib/fdio",
-      ]
-      configs -= [ "//build/config:symbol_visibility_hidden" ]
+      if (using_fuchsia_sdk) {
+        deps += [ "$fuchsia_sdk_root/pkg/lib/netstack/c" ]
+        public_deps = [
+          "$fuchsia_sdk_root/pkg:fdio",
+        ]
+      } else {
+        deps += [ "//garnet/public/lib/netstack/c" ]
+        public_deps = [
+          "//zircon/public/lib/fdio",
+        ]
+      }
     }
 
     deps += [ "//third_party/zlib" ]
@@ -278,9 +282,6 @@
     custom_sources_filter = [
       "*_test.cc",
       "*_test.h",
-      "builtin.cc",
-      "builtin_common.cc",
-      "builtin_gen_snapshot.cc",
     ]
     if (!is_mac && !is_ios) {
       # Dart tree uses *_macos.* instead of *_mac.*
@@ -293,7 +294,7 @@
 
     defines = [ "DART_IO_SECURE_SOCKET_DISABLED" ]
 
-    sources = io_impl_sources + builtin_impl_sources + cli_impl_sources
+    sources = io_impl_sources + cli_impl_sources
     sources += [
       "io_natives.cc",
       "io_natives.h",
@@ -344,6 +345,10 @@
   if (defined(invoker.extra_sources)) {
     extra_sources += invoker.extra_sources
   }
+  extra_deps = []
+  if (defined(invoker.extra_deps)) {
+    extra_deps += invoker.extra_deps
+  }
   source_set(target_name) {
     configs += [
                  "..:dart_arch_config",
@@ -351,9 +356,6 @@
                  "..:dart_os_config",
                ] + extra_configs
     public_configs = [ "..:dart_public_config" ]
-    if (is_fuchsia) {
-      configs -= [ "//build/config:symbol_visibility_hidden" ]
-    }
     custom_sources_filter = [
       "*_test.cc",
       "*_test.h",
@@ -369,9 +371,7 @@
     set_sources_assignment_filter(custom_sources_filter)
 
     defines = []
-    deps = [
-      "//third_party/zlib",
-    ]
+    deps = [ "//third_party/zlib" ] + extra_deps
     if (is_mac || is_ios) {
       libs = [
         "CoreFoundation.framework",
@@ -386,22 +386,24 @@
     deps += [ "//third_party/boringssl" ]
 
     if (is_fuchsia) {
-      deps += [ "//garnet/public/lib/netstack/c" ]
-      public_deps = [
-        "//zircon/public/lib/fdio",
-      ]
+      if (using_fuchsia_sdk) {
+        deps += [ "$fuchsia_sdk_root/pkg/lib/netstack/c" ]
+        public_deps = [
+          "$fuchsia_sdk_root/pkg:fdio",
+        ]
+      } else {
+        deps += [ "//garnet/public/lib/netstack/c" ]
+        public_deps = [
+          "//zircon/public/lib/fdio",
+        ]
+      }
     }
 
-    sources = io_impl_sources + builtin_impl_sources + cli_impl_sources
+    sources = io_impl_sources + cli_impl_sources
     sources += [
                  "builtin_natives.cc",
                  "io_natives.cc",
                  "io_natives.h",
-                 "log_android.cc",
-                 "log_linux.cc",
-                 "log_macos.cc",
-                 "log_win.cc",
-                 "log.h",
                ] + extra_sources
 
     if (is_linux || is_win || is_fuchsia) {
@@ -426,6 +428,7 @@
     "dart_io_api_impl.cc",
     "../include/bin/dart_io_api.h",
   ]
+  extra_deps = [ ":libdart_builtin" ]
 }
 
 dart_io("dart_io_api_product") {
@@ -435,11 +438,13 @@
     "dart_io_api_impl.cc",
     "../include/bin/dart_io_api.h",
   ]
+  extra_deps = [ ":libdart_builtin_product" ]
 }
 
 dart_io("standalone_dart_io") {
   extra_configs = [ "..:dart_maybe_product_config" ]
   extra_sources = []
+  extra_deps = [ ":libdart_builtin" ]
 }
 
 gen_snapshot_action("generate_snapshot_bin") {
@@ -697,6 +702,10 @@
   if (defined(invoker.extra_sources)) {
     extra_sources += invoker.extra_sources
   }
+  extra_ldflags = []
+  if (defined(invoker.extra_ldflags)) {
+    extra_ldflags = invoker.extra_ldflags
+  }
   target_type = "executable"
   if (defined(invoker.target_type)) {
     target_type = invoker.target_type
@@ -708,9 +717,6 @@
                  "..:dart_os_config",
                  "..:dart_maybe_product_config",
                ] + extra_configs
-    if (is_fuchsia) {
-      configs -= [ "//build/config:symbol_visibility_hidden" ]
-    }
     if (target_os != current_os && target_os == "fuchsia") {
       # We already have these in the standalone build, but Fuchsia doesn't
       # have them. They are needed for running Fuchsia binaries built for the
@@ -724,7 +730,6 @@
 
     deps = [
              ":standalone_dart_io",
-             ":libdart_builtin",
              "//third_party/boringssl",
              "//third_party/zlib",
              ":crashpad",
@@ -749,7 +754,6 @@
                 "dart_embedder_api_impl.cc",
                 "error_exit.cc",
                 "error_exit.h",
-                "main.cc",
                 "main_options.cc",
                 "main_options.h",
                 "options.cc",
@@ -770,6 +774,8 @@
       ldflags = [ "-rdynamic" ]
     }
 
+    ldflags += extra_ldflags
+
     if (is_win) {
       libs = [
         "iphlpapi.lib",
@@ -786,6 +792,7 @@
 dart_executable("dart") {
   extra_deps = [
     "..:libdart_jit",
+    "../platform:libdart_platform_jit",
     ":dart_snapshot_cc",
   ]
   if (dart_runtime_mode != "release") {
@@ -795,10 +802,11 @@
     "builtin.cc",
     "dfe.cc",
     "dfe.h",
-    "loader.cc",
-    "loader.h",
     "gzip.cc",
     "gzip.h",
+    "loader.cc",
+    "loader.h",
+    "main.cc",
   ]
   if (dart_runtime_mode == "release") {
     extra_sources += [ "observatory_assets_empty.cc" ]
@@ -810,55 +818,42 @@
 
 dart_executable("dart_precompiled_runtime") {
   extra_configs = [ "..:dart_precompiled_runtime_config" ]
-  extra_deps = [ "..:libdart_precompiled_runtime" ]
+  extra_deps = [
+    "..:libdart_precompiled_runtime",
+    "../platform:libdart_platform_precompiled_runtime",
+  ]
   if (dart_runtime_mode != "release") {
     extra_deps += [ "../observatory:standalone_observatory_archive" ]
   }
   extra_sources = [
     "builtin.cc",
-    "snapshot_empty.cc",
-    "loader.cc",
-    "loader.h",
     "gzip.cc",
     "gzip.h",
+    "loader.cc",
+    "loader.h",
+    "main.cc",
+    "snapshot_empty.cc",
   ]
   if (dart_runtime_mode == "release") {
     extra_sources += [ "observatory_assets_empty.cc" ]
   }
 }
 
-dart_executable("dart_precompiled_runtime_for_linking") {
-  extra_configs = [ "..:dart_precompiled_runtime_config" ]
-  extra_deps = [ "..:libdart_precompiled_runtime" ]
-  if (dart_runtime_mode != "release") {
-    extra_deps += [ "../observatory:standalone_observatory_archive" ]
-  }
-  extra_sources = [
-    "builtin.cc",
-    "snapshot_empty.cc",
-    "loader.cc",
-    "loader.h",
-    "gzip.cc",
-    "gzip.h",
-  ]
-  if (dart_runtime_mode == "release") {
-    extra_sources += [ "observatory_assets_empty.cc" ]
-  }
-  extra_defines = [ "DART_LINK_APP_SNAPSHOT" ]
-  target_type = "static_library"
-}
-
 dart_executable("dartaotruntime") {
   extra_configs = [ "..:dart_precompiled_runtime_config" ]
-  extra_deps = [ "..:libdart_precompiled_runtime" ]
+  extra_deps = [
+    "..:libdart_precompiled_runtime",
+    "../platform:libdart_platform_precompiled_runtime",
+  ]
   extra_sources = [
     "builtin.cc",
-    "snapshot_empty.cc",
-    "loader.cc",
-    "loader.h",
     "gzip.cc",
     "gzip.h",
+    "loader.cc",
+    "loader.h",
+    "main.cc",
     "observatory_assets_empty.cc",
+    "snapshot_empty.cc",
   ]
 }
 
@@ -917,9 +912,6 @@
   if (dart_target_arch != "ia32") {
     configs += [ "..:dart_precompiler_config" ]
   }
-  if (is_fuchsia) {
-    configs -= [ "//build/config:symbol_visibility_hidden" ]
-  }
 
   deps = [
     ":crashpad",
@@ -927,7 +919,6 @@
     ":dart_snapshot_cc",
     ":gen_kernel_bytecode_dill",
     ":generate_abi_version_cc_file",
-    ":libdart_builtin",
     ":standalone_dart_io",
     "..:libdart_nosnapshot_with_precompiler",
     "//third_party/zlib",
@@ -944,7 +935,9 @@
   }
 
   if (is_fuchsia) {
-    deps += [ "//zircon/public/lib/trace" ]
+    if (!using_fuchsia_sdk) {
+      deps += [ "//zircon/public/lib/trace" ]
+    }
   }
 
   # The VM sources are already included in libdart, so we just want to add in
@@ -1096,3 +1089,21 @@
     ldflags = [ "/LIBPATH:$abs_root_out_dir" ]
   }
 }
+
+# DartLibFuzzer only "exists" for restricted configurations.
+if (defined(is_linux) && is_linux && defined(is_asan) && is_asan &&
+    (dart_target_arch == "x64" || dart_target_arch == "arm64")) {
+  dart_executable("dart_libfuzzer") {
+    extra_ldflags = [ "-fsanitize=address,fuzzer" ]
+    extra_deps = [ "..:libdart_libfuzzer" ]
+    extra_sources = [
+      "../vm/libfuzzer/dart_libfuzzer.cc",
+      "builtin.cc",
+      "dfe.cc",
+      "dfe.h",
+    ]
+    if (!exclude_kernel_service) {
+      extra_deps += [ ":dart_kernel_platform_cc" ]
+    }
+  }
+}
diff --git a/runtime/bin/cli_sources.gni b/runtime/bin/cli_sources.gni
index 532fbba..ed72a04 100644
--- a/runtime/bin/cli_sources.gni
+++ b/runtime/bin/cli_sources.gni
@@ -3,4 +3,4 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # This file contains all sources for the dart:cli library.
-cli_runtime_sources = [ "cli_patch.dart" ]
+cli_runtime_dart_files = [ "cli_patch.dart" ]
diff --git a/runtime/bin/crashpad.cc b/runtime/bin/crashpad.cc
index 184dba1..18ed3f5 100644
--- a/runtime/bin/crashpad.cc
+++ b/runtime/bin/crashpad.cc
@@ -14,8 +14,8 @@
 #endif
 
 #include "bin/error_exit.h"
-#include "bin/log.h"
 #include "bin/platform.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
@@ -66,7 +66,7 @@
   SetStdHandle(STD_ERROR_HANDLE, original_stderr);
 
   if (!success) {
-    Log::PrintErr("Failed to start the crash handler!\n");
+    Syslog::PrintErr("Failed to start the crash handler!\n");
     Platform::Exit(kErrorExitCode);
   }
   crashpad::CrashpadInfo::GetCrashpadInfo()
diff --git a/runtime/bin/crypto_android.cc b/runtime/bin/crypto_android.cc
index 6af505f..6db66eb 100644
--- a/runtime/bin/crypto_android.cc
+++ b/runtime/bin/crypto_android.cc
@@ -17,8 +17,8 @@
 
 bool Crypto::GetRandomBytes(intptr_t count, uint8_t* buffer) {
   ThreadSignalBlocker signal_blocker(SIGPROF);
-  intptr_t fd =
-      TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(open("/dev/urandom", O_RDONLY));
+  intptr_t fd = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
+      open("/dev/urandom", O_RDONLY | O_CLOEXEC));
   if (fd < 0) {
     return false;
   }
diff --git a/runtime/bin/crypto_linux.cc b/runtime/bin/crypto_linux.cc
index 9a14ee3..d3af9e0 100644
--- a/runtime/bin/crypto_linux.cc
+++ b/runtime/bin/crypto_linux.cc
@@ -17,8 +17,8 @@
 
 bool Crypto::GetRandomBytes(intptr_t count, uint8_t* buffer) {
   ThreadSignalBlocker signal_blocker(SIGPROF);
-  intptr_t fd =
-      TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(open("/dev/urandom", O_RDONLY));
+  intptr_t fd = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
+      open("/dev/urandom", O_RDONLY | O_CLOEXEC));
   if (fd < 0) {
     return false;
   }
diff --git a/runtime/bin/crypto_macos.cc b/runtime/bin/crypto_macos.cc
index 5d0690e..e5bf130 100644
--- a/runtime/bin/crypto_macos.cc
+++ b/runtime/bin/crypto_macos.cc
@@ -17,8 +17,8 @@
 
 bool Crypto::GetRandomBytes(intptr_t count, uint8_t* buffer) {
   ThreadSignalBlocker signal_blocker(SIGPROF);
-  intptr_t fd =
-      TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(open("/dev/urandom", O_RDONLY));
+  intptr_t fd = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
+      open("/dev/urandom", O_RDONLY | O_CLOEXEC));
   if (fd < 0) {
     return false;
   }
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index edf14c4..36efb0d 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -16,7 +16,6 @@
 #include "bin/utils.h"
 #include "include/dart_tools_api.h"
 #include "platform/utils.h"
-#include "vm/os.h"
 
 extern "C" {
 #if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
@@ -137,23 +136,22 @@
 
     // Look in the old abi version directory.
     char* script_uri =
-        OS::SCreate(NULL, "%s%s/%d/%s", dir_prefix.get(), kAbiVersionsDir,
-                    target_abi_version, kPlatformStrongDillFile);
+        Utils::SCreate("%s%s/%d/%s", dir_prefix.get(), kAbiVersionsDir,
+                       target_abi_version, kPlatformStrongDillFile);
     if (!TryReadKernelFile(script_uri,
                            const_cast<uint8_t**>(&platform_strong_dill_),
                            &platform_strong_dill_size_)) {
-      Log::PrintErr("Can't find old ABI dill file: %s\n", script_uri);
+      Syslog::PrintErr("Can't find old ABI dill file: %s\n", script_uri);
       free(script_uri);
       return false;
     }
     free(script_uri);
-    script_uri =
-        OS::SCreate(NULL, "%s%s/%d/%s", dir_prefix.get(), kAbiVersionsDir,
-                    target_abi_version, kKernelServiceDillFile);
+    script_uri = Utils::SCreate("%s%s/%d/%s", dir_prefix.get(), kAbiVersionsDir,
+                                target_abi_version, kKernelServiceDillFile);
     if (!TryReadKernelFile(script_uri,
                            const_cast<uint8_t**>(&kernel_service_dill_),
                            &kernel_service_dill_size_)) {
-      Log::PrintErr("Can't find old ABI dill file: %s\n", script_uri);
+      Syslog::PrintErr("Can't find old ABI dill file: %s\n", script_uri);
       free(script_uri);
       return false;
     } else {
@@ -164,7 +162,7 @@
 
   // Look for the frontend snapshot next to the executable.
   frontend_filename_ =
-      OS::SCreate(NULL, "%s%s", dir_prefix.get(), kKernelServiceSnapshot);
+      Utils::SCreate("%s%s", dir_prefix.get(), kKernelServiceSnapshot);
   if (File::Exists(NULL, frontend_filename_)) {
     return true;
   }
@@ -174,8 +172,8 @@
   // If the frontend snapshot is not found next to the executable, then look for
   // it in the "snapshots" directory.
   frontend_filename_ =
-      OS::SCreate(NULL, "%s%s%s%s", dir_prefix.get(), kSnapshotsDirectory,
-                  File::PathSeparator(), kKernelServiceSnapshot);
+      Utils::SCreate("%s%s%s%s", dir_prefix.get(), kSnapshotsDirectory,
+                     File::PathSeparator(), kKernelServiceSnapshot);
   if (File::Exists(NULL, frontend_filename_)) {
     return true;
   }
@@ -409,20 +407,34 @@
   DISALLOW_COPY_AND_ASSIGN(KernelIRNode);
 };
 
+class StringPointer {
+ public:
+  explicit StringPointer(char* c_str) : c_str_(c_str) {}
+  ~StringPointer() { free(c_str_); }
+
+  const char* c_str() { return c_str_; }
+
+ private:
+  char* c_str_;
+  DISALLOW_COPY_AND_ASSIGN(StringPointer);
+};
+
 // Supports "kernel list" files as input.
 // Those are text files that start with '#@dill' on new line, followed
 // by absolute paths to kernel files or relative paths, that are relative
-// to dart process working directory.
+// to [script_uri] "kernel list" file.
 // Below is an example of valid kernel list file:
 // ```
 // #@dill
 // /projects/mytest/build/bin/main.vm.dill
 // /projects/mytest/build/packages/mytest/lib.vm.dill
 // ```
-static bool TryReadKernelListBuffer(uint8_t* buffer,
+static bool TryReadKernelListBuffer(const char* script_uri,
+                                    uint8_t* buffer,
                                     intptr_t buffer_size,
                                     uint8_t** kernel_ir,
                                     intptr_t* kernel_ir_size) {
+  const char* kernel_list_dirname = DartUtils::DirName(script_uri);
   KernelIRNode* kernel_ir_head = NULL;
   KernelIRNode* kernel_ir_tail = NULL;
   // Add all kernels to the linked list
@@ -434,7 +446,13 @@
     *tail = '\0';
     intptr_t this_kernel_size;
     uint8_t* this_buffer;
-    if (!TryReadFile(filename, &this_buffer, &this_kernel_size)) {
+
+    StringPointer absolute_filename(
+        File::IsAbsolutePath(filename)
+            ? strdup(filename)
+            : Utils::SCreate("%s%s", kernel_list_dirname, filename));
+    if (!TryReadFile(absolute_filename.c_str(), &this_buffer,
+                     &this_kernel_size)) {
       return false;
     }
 
@@ -474,8 +492,8 @@
   DartUtils::MagicNumber magic_number =
       DartUtils::SniffForMagicNumber(buffer, *kernel_ir_size);
   if (magic_number == DartUtils::kKernelListMagicNumber) {
-    return TryReadKernelListBuffer(buffer, *kernel_ir_size, kernel_ir,
-                                   kernel_ir_size);
+    return TryReadKernelListBuffer(script_uri, buffer, *kernel_ir_size,
+                                   kernel_ir, kernel_ir_size);
   }
   return TryReadSimpleKernelBuffer(buffer, kernel_ir, kernel_ir_size);
 }
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index 362a955..6b3ce66 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -9,12 +9,12 @@
 
 #include "bin/dartutils.h"
 #include "bin/io_buffer.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "bin/typed_data_utils.h"
 #include "bin/utils.h"
 #include "include/dart_api.h"
 #include "platform/assert.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc
index 5a6f8ef..5303e47 100644
--- a/runtime/bin/directory_win.cc
+++ b/runtime/bin/directory_win.cc
@@ -12,10 +12,10 @@
 
 #include "bin/dartutils.h"
 #include "bin/file.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
+#include "platform/syslog.h"
 
 #undef DeleteFile
 
diff --git a/runtime/bin/error_exit.cc b/runtime/bin/error_exit.cc
index 617da04..c6355e8 100644
--- a/runtime/bin/error_exit.cc
+++ b/runtime/bin/error_exit.cc
@@ -5,12 +5,12 @@
 #include "bin/error_exit.h"
 
 #include "bin/eventhandler.h"
-#include "bin/log.h"
 #include "bin/platform.h"
 #include "bin/process.h"
 #include "include/dart_api.h"
 #include "platform/assert.h"
 #include "platform/globals.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
@@ -18,7 +18,7 @@
 void ErrorExit(int exit_code, const char* format, ...) {
   va_list arguments;
   va_start(arguments, format);
-  Log::VPrintErr(format, arguments);
+  Syslog::VPrintErr(format, arguments);
   va_end(arguments);
 
   Dart_ShutdownIsolate();
@@ -28,7 +28,7 @@
 
   char* error = Dart_Cleanup();
   if (error != NULL) {
-    Log::PrintErr("VM cleanup failed: %s\n", error);
+    Syslog::PrintErr("VM cleanup failed: %s\n", error);
     free(error);
   }
 
diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc
index 4fe2832..91e6cd8 100644
--- a/runtime/bin/eventhandler_android.cc
+++ b/runtime/bin/eventhandler_android.cc
@@ -20,11 +20,11 @@
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/socket.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
 #include "platform/hashmap.h"
+#include "platform/syslog.h"
 #include "platform/utils.h"
 
 // Android doesn't define EPOLLRDHUP.
@@ -269,33 +269,33 @@
 
 #ifdef DEBUG_POLL
 static void PrintEventMask(intptr_t fd, intptr_t events) {
-  Log::Print("%d ", fd);
+  Syslog::Print("%d ", fd);
   if ((events & EPOLLIN) != 0) {
-    Log::Print("EPOLLIN ");
+    Syslog::Print("EPOLLIN ");
   }
   if ((events & EPOLLPRI) != 0) {
-    Log::Print("EPOLLPRI ");
+    Syslog::Print("EPOLLPRI ");
   }
   if ((events & EPOLLOUT) != 0) {
-    Log::Print("EPOLLOUT ");
+    Syslog::Print("EPOLLOUT ");
   }
   if ((events & EPOLLERR) != 0) {
-    Log::Print("EPOLLERR ");
+    Syslog::Print("EPOLLERR ");
   }
   if ((events & EPOLLHUP) != 0) {
-    Log::Print("EPOLLHUP ");
+    Syslog::Print("EPOLLHUP ");
   }
   if ((events & EPOLLRDHUP) != 0) {
-    Log::Print("EPOLLRDHUP ");
+    Syslog::Print("EPOLLRDHUP ");
   }
   int all_events =
       EPOLLIN | EPOLLPRI | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
   if ((events & ~all_events) != 0) {
-    Log::Print("(and %08x) ", events & ~all_events);
+    Syslog::Print("(and %08x) ", events & ~all_events);
   }
-  Log::Print("(available %d) ", FDUtils::AvailableBytes(fd));
+  Syslog::Print("(available %d) ", FDUtils::AvailableBytes(fd));
 
-  Log::Print("\n");
+  Syslog::Print("\n");
 }
 #endif
 
diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc
index 9f3b1df..bae6f32 100644
--- a/runtime/bin/eventhandler_fuchsia.cc
+++ b/runtime/bin/eventhandler_fuchsia.cc
@@ -24,11 +24,11 @@
 
 #include "bin/fdutils.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/socket.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
 #include "platform/hashmap.h"
+#include "platform/syslog.h"
 #include "platform/utils.h"
 
 // The EventHandler for Fuchsia uses its "ports v2" API:
@@ -56,14 +56,14 @@
 #define LOG_ERR(msg, ...)                                                      \
   {                                                                            \
     int err = errno;                                                           \
-    Log::PrintErr("Dart EventHandler ERROR: %s:%d: " msg, __FILE__, __LINE__,  \
-                  ##__VA_ARGS__);                                              \
+    Syslog::PrintErr("Dart EventHandler ERROR: %s:%d: " msg, __FILE__,         \
+                     __LINE__, ##__VA_ARGS__);                                 \
     errno = err;                                                               \
   }
 #if defined(EVENTHANDLER_LOG_INFO)
 #define LOG_INFO(msg, ...)                                                     \
-  Log::Print("Dart EventHandler INFO: %s:%d: " msg, __FILE__, __LINE__,        \
-             ##__VA_ARGS__)
+  Syslog::Print("Dart EventHandler INFO: %s:%d: " msg, __FILE__, __LINE__,     \
+                ##__VA_ARGS__)
 #else
 #define LOG_INFO(msg, ...)
 #endif  // defined(EVENTHANDLER_LOG_INFO)
@@ -76,7 +76,7 @@
 namespace bin {
 
 intptr_t IOHandle::Read(void* buffer, intptr_t num_bytes) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   const ssize_t read_bytes = NO_RETRY_EXPECTED(read(fd_, buffer, num_bytes));
   const int err = errno;
   LOG_INFO("IOHandle::Read: fd = %ld. read %ld bytes\n", fd_, read_bytes);
@@ -105,7 +105,7 @@
 }
 
 intptr_t IOHandle::Write(const void* buffer, intptr_t num_bytes) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   const ssize_t written_bytes =
       NO_RETRY_EXPECTED(write(fd_, buffer, num_bytes));
   const int err = errno;
@@ -122,7 +122,7 @@
 }
 
 intptr_t IOHandle::Accept(struct sockaddr* addr, socklen_t* addrlen) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   const intptr_t socket = NO_RETRY_EXPECTED(accept(fd_, addr, addrlen));
   const int err = errno;
   LOG_INFO("IOHandle::Accept: fd = %ld. socket = %ld\n", fd_, socket);
@@ -138,7 +138,7 @@
 }
 
 intptr_t IOHandle::AvailableBytes() {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   ASSERT(fd_ >= 0);
   intptr_t available = FDUtils::AvailableBytes(fd_);
   LOG_INFO("IOHandle::AvailableBytes(): fd = %ld, bytes = %ld\n", fd_,
@@ -153,12 +153,12 @@
 }
 
 void IOHandle::Close() {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   VOID_NO_RETRY_EXPECTED(close(fd_));
 }
 
 uint32_t IOHandle::MaskToEpollEvents(intptr_t mask) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   // Do not ask for POLLERR and POLLHUP explicitly as they are
   // triggered anyway.
   uint32_t events = POLLRDHUP;
@@ -230,12 +230,12 @@
 }
 
 bool IOHandle::AsyncWait(zx_handle_t port, uint32_t events, uint64_t key) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   return AsyncWaitLocked(port, events, key);
 }
 
 void IOHandle::CancelWait(zx_handle_t port, uint64_t key) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   LOG_INFO("IOHandle::CancelWait: fd = %ld\n", fd_);
   ASSERT(port != ZX_HANDLE_INVALID);
   ASSERT(handle_ != ZX_HANDLE_INVALID);
@@ -246,14 +246,15 @@
 }
 
 uint32_t IOHandle::WaitEnd(zx_signals_t observed) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   uint32_t events = 0;
   fdio_unsafe_wait_end(fdio_, observed, &events);
+  LOG_INFO("IOHandle::WaitEnd: fd = %ld, events = %x\n", fd_, events);
   return events;
 }
 
 intptr_t IOHandle::ToggleEvents(intptr_t event_mask) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   if (!write_events_enabled_) {
     LOG_INFO("IOHandle::ToggleEvents: fd = %ld de-asserting write\n", fd_);
     event_mask = event_mask & ~(1 << kOutEvent);
diff --git a/runtime/bin/eventhandler_fuchsia.h b/runtime/bin/eventhandler_fuchsia.h
index 0ff514b..07acef97 100644
--- a/runtime/bin/eventhandler_fuchsia.h
+++ b/runtime/bin/eventhandler_fuchsia.h
@@ -31,7 +31,7 @@
  public:
   explicit IOHandle(intptr_t fd)
       : ReferenceCounted(),
-        mutex_(new Mutex()),
+        mutex_(),
         write_events_enabled_(true),
         read_events_enabled_(true),
         fd_(fd),
@@ -65,13 +65,12 @@
     if (fdio_ != NULL) {
       fdio_unsafe_release(fdio_);
     }
-    delete mutex_;
   }
 
   bool AsyncWaitLocked(zx_handle_t port, uint32_t events, uint64_t key);
 
   // Mutex that protects the state here.
-  Mutex* mutex_;
+  Mutex mutex_;
   bool write_events_enabled_;
   bool read_events_enabled_;
   // Bytes remaining to be read from the socket. Read events should only be
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index 142f0b1..8ae3151 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -21,9 +21,9 @@
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/socket.h"
 #include "bin/thread.h"
+#include "platform/syslog.h"
 #include "platform/utils.h"
 
 namespace dart {
@@ -290,33 +290,33 @@
 
 #ifdef DEBUG_POLL
 static void PrintEventMask(intptr_t fd, intptr_t events) {
-  Log::Print("%d ", fd);
+  Syslog::Print("%d ", fd);
   if ((events & EPOLLIN) != 0) {
-    Log::Print("EPOLLIN ");
+    Syslog::Print("EPOLLIN ");
   }
   if ((events & EPOLLPRI) != 0) {
-    Log::Print("EPOLLPRI ");
+    Syslog::Print("EPOLLPRI ");
   }
   if ((events & EPOLLOUT) != 0) {
-    Log::Print("EPOLLOUT ");
+    Syslog::Print("EPOLLOUT ");
   }
   if ((events & EPOLLERR) != 0) {
-    Log::Print("EPOLLERR ");
+    Syslog::Print("EPOLLERR ");
   }
   if ((events & EPOLLHUP) != 0) {
-    Log::Print("EPOLLHUP ");
+    Syslog::Print("EPOLLHUP ");
   }
   if ((events & EPOLLRDHUP) != 0) {
-    Log::Print("EPOLLRDHUP ");
+    Syslog::Print("EPOLLRDHUP ");
   }
   int all_events =
       EPOLLIN | EPOLLPRI | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
   if ((events & ~all_events) != 0) {
-    Log::Print("(and %08x) ", events & ~all_events);
+    Syslog::Print("(and %08x) ", events & ~all_events);
   }
-  Log::Print("(available %d) ", FDUtils::AvailableBytes(fd));
+  Syslog::Print("(available %d) ", FDUtils::AvailableBytes(fd));
 
-  Log::Print("\n");
+  Syslog::Print("\n");
 }
 #endif
 
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index e3d5a9a..1a2b20e 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -19,11 +19,11 @@
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/socket.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
 #include "platform/hashmap.h"
+#include "platform/syslog.h"
 #include "platform/utils.h"
 
 namespace dart {
@@ -284,37 +284,38 @@
 
 #ifdef DEBUG_KQUEUE
 static void PrintEventMask(intptr_t fd, struct kevent* event) {
-  Log::Print("%d ", static_cast<int>(fd));
+  Syslog::Print("%d ", static_cast<int>(fd));
 
-  Log::Print("filter=0x%x:", event->filter);
+  Syslog::Print("filter=0x%x:", event->filter);
   if (event->filter == EVFILT_READ) {
-    Log::Print("EVFILT_READ ");
+    Syslog::Print("EVFILT_READ ");
   }
   if (event->filter == EVFILT_WRITE) {
-    Log::Print("EVFILT_WRITE ");
+    Syslog::Print("EVFILT_WRITE ");
   }
 
-  Log::Print("flags: %x: ", event->flags);
+  Syslog::Print("flags: %x: ", event->flags);
   if ((event->flags & EV_EOF) != 0) {
-    Log::Print("EV_EOF ");
+    Syslog::Print("EV_EOF ");
   }
   if ((event->flags & EV_ERROR) != 0) {
-    Log::Print("EV_ERROR ");
+    Syslog::Print("EV_ERROR ");
   }
   if ((event->flags & EV_CLEAR) != 0) {
-    Log::Print("EV_CLEAR ");
+    Syslog::Print("EV_CLEAR ");
   }
   if ((event->flags & EV_ADD) != 0) {
-    Log::Print("EV_ADD ");
+    Syslog::Print("EV_ADD ");
   }
   if ((event->flags & EV_DELETE) != 0) {
-    Log::Print("EV_DELETE ");
+    Syslog::Print("EV_DELETE ");
   }
 
-  Log::Print("- fflags: %d ", event->fflags);
-  Log::Print("- data: %ld ", event->data);
-  Log::Print("(available %d) ", static_cast<int>(FDUtils::AvailableBytes(fd)));
-  Log::Print("\n");
+  Syslog::Print("- fflags: %d ", event->fflags);
+  Syslog::Print("- data: %ld ", event->data);
+  Syslog::Print("(available %d) ",
+                static_cast<int>(FDUtils::AvailableBytes(fd)));
+  Syslog::Print("\n");
 }
 #endif
 
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index e328f72..37b4f28 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -17,10 +17,10 @@
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/socket.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
+#include "platform/syslog.h"
 
 #include "platform/utils.h"
 
@@ -116,10 +116,9 @@
       read_thread_handle_(NULL),
       read_thread_starting_(false),
       read_thread_finished_(false),
-      monitor_(new Monitor()) {}
+      monitor_() {}
 
 Handle::~Handle() {
-  delete monitor_;
 }
 
 bool Handle::CreateCompletionPort(HANDLE completion_port) {
@@ -133,7 +132,7 @@
 }
 
 void Handle::Close() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (!SupportsOverlappedIO()) {
     // If the handle uses synchronous I/O (e.g. stdin), cancel any pending
     // operation before closing the handle, so the read thread is not blocked.
@@ -174,7 +173,7 @@
 }
 
 void Handle::WaitForReadThreadStarted() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   while (read_thread_starting_) {
     ml.Wait();
   }
@@ -183,7 +182,7 @@
 void Handle::WaitForReadThreadFinished() {
   HANDLE to_join = NULL;
   {
-    MonitorLocker ml(monitor_);
+    MonitorLocker ml(&monitor_);
     if (read_thread_id_ != Thread::kInvalidThreadId) {
       while (!read_thread_finished_) {
         ml.Wait();
@@ -205,7 +204,7 @@
 void Handle::ReadComplete(OverlappedBuffer* buffer) {
   WaitForReadThreadStarted();
   {
-    MonitorLocker ml(monitor_);
+    MonitorLocker ml(&monitor_);
     // Currently only one outstanding read at the time.
     ASSERT(pending_read_ == buffer);
     ASSERT(data_ready_ == NULL);
@@ -224,7 +223,7 @@
 }
 
 void Handle::WriteComplete(OverlappedBuffer* buffer) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   // Currently only one outstanding write at the time.
   ASSERT(pending_write_ == buffer);
   OverlappedBuffer::DisposeBuffer(buffer);
@@ -237,7 +236,7 @@
 }
 
 void Handle::NotifyReadThreadStarted() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   ASSERT(read_thread_starting_);
   ASSERT(read_thread_id_ == Thread::kInvalidThreadId);
   read_thread_id_ = Thread::GetCurrentThreadId();
@@ -247,7 +246,7 @@
 }
 
 void Handle::NotifyReadThreadFinished() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   ASSERT(!read_thread_finished_);
   ASSERT(read_thread_id_ != Thread::kInvalidThreadId);
   read_thread_finished_ = true;
@@ -315,7 +314,7 @@
 }
 
 bool Handle::IssueWrite() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   ASSERT(type_ != kListenSocket);
   ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
   ASSERT(HasPendingWrite());
@@ -365,7 +364,7 @@
 }
 
 void FileHandle::EnsureInitialized(EventHandlerImplementation* event_handler) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   event_handler_ = event_handler;
   if (completion_port_ == INVALID_HANDLE_VALUE) {
     if (SupportsOverlappedIO()) {
@@ -386,7 +385,7 @@
 
 void DirectoryWatchHandle::EnsureInitialized(
     EventHandlerImplementation* event_handler) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   event_handler_ = event_handler;
   if (completion_port_ == INVALID_HANDLE_VALUE) {
     CreateCompletionPort(event_handler_->completion_port());
@@ -418,7 +417,7 @@
 }
 
 void DirectoryWatchHandle::Stop() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   // Stop the outstanding read, so we can close the handle.
 
   if (HasPendingRead()) {
@@ -450,7 +449,7 @@
 }
 
 bool ListenSocket::IssueAccept() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
 
   // For AcceptEx there needs to be buffer storage for address
   // information for two addresses (local and remote address). The
@@ -485,7 +484,7 @@
 
 void ListenSocket::AcceptComplete(OverlappedBuffer* buffer,
                                   HANDLE completion_port) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (!IsClosing()) {
     // Update the accepted socket to support the full range of API calls.
     SOCKET s = socket();
@@ -556,12 +555,12 @@
 }
 
 bool ListenSocket::CanAccept() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   return accepted_head_ != NULL;
 }
 
 ClientSocket* ListenSocket::Accept() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
 
   ClientSocket* result = NULL;
 
@@ -589,7 +588,7 @@
 
 void ListenSocket::EnsureInitialized(
     EventHandlerImplementation* event_handler) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (AcceptEx_ == NULL) {
     ASSERT(completion_port_ == INVALID_HANDLE_VALUE);
     ASSERT(event_handler_ == NULL);
@@ -604,7 +603,7 @@
 }
 
 intptr_t Handle::Available() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (data_ready_ == NULL) {
     return 0;
   }
@@ -613,7 +612,7 @@
 }
 
 intptr_t Handle::Read(void* buffer, intptr_t num_bytes) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (data_ready_ == NULL) {
     return 0;
   }
@@ -633,7 +632,7 @@
                           intptr_t num_bytes,
                           struct sockaddr* sa,
                           socklen_t sa_len) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (data_ready_ == NULL) {
     return 0;
   }
@@ -658,7 +657,7 @@
 }
 
 intptr_t Handle::Write(const void* buffer, intptr_t num_bytes) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (HasPendingWrite()) {
     return 0;
   }
@@ -682,7 +681,7 @@
                         intptr_t num_bytes,
                         struct sockaddr* sa,
                         socklen_t sa_len) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (HasPendingWrite()) {
     return 0;
   }
@@ -718,7 +717,7 @@
 }
 
 void StdHandle::RunWriteLoop() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   write_thread_running_ = true;
   thread_id_ = Thread::GetCurrentThreadId();
   thread_handle_ = OpenThread(SYNCHRONIZE, false, thread_id_);
@@ -757,7 +756,7 @@
 }
 
 intptr_t StdHandle::Write(const void* buffer, intptr_t num_bytes) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (HasPendingWrite()) {
     return 0;
   }
@@ -803,7 +802,7 @@
 
 void StdHandle::DoClose() {
   {
-    MonitorLocker ml(monitor_);
+    MonitorLocker ml(&monitor_);
     if (write_thread_exists_) {
       write_thread_running_ = false;
       ml.Notify();
@@ -859,7 +858,7 @@
 }
 
 bool ClientSocket::IssueRead() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
   ASSERT(!HasPendingRead());
 
@@ -882,7 +881,7 @@
 }
 
 bool ClientSocket::IssueWrite() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
   ASSERT(HasPendingWrite());
   ASSERT(pending_write_->operation() == OverlappedBuffer::kWrite);
@@ -950,7 +949,7 @@
 
 void ClientSocket::EnsureInitialized(
     EventHandlerImplementation* event_handler) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (completion_port_ == INVALID_HANDLE_VALUE) {
     ASSERT(event_handler_ == NULL);
     event_handler_ = event_handler;
@@ -963,7 +962,7 @@
 }
 
 bool DatagramSocket::IssueSendTo(struct sockaddr* sa, socklen_t sa_len) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
   ASSERT(HasPendingWrite());
   ASSERT(pending_write_->operation() == OverlappedBuffer::kSendTo);
@@ -980,7 +979,7 @@
 }
 
 bool DatagramSocket::IssueRecvFrom() {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
   ASSERT(!HasPendingRead());
 
@@ -1004,7 +1003,7 @@
 
 void DatagramSocket::EnsureInitialized(
     EventHandlerImplementation* event_handler) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (completion_port_ == INVALID_HANDLE_VALUE) {
     ASSERT(event_handler_ == NULL);
     event_handler_ = event_handler;
@@ -1045,7 +1044,7 @@
       ListenSocket* listen_socket = reinterpret_cast<ListenSocket*>(handle);
       listen_socket->EnsureInitialized(this);
 
-      MonitorLocker ml(listen_socket->monitor_);
+      MonitorLocker ml(&listen_socket->monitor_);
 
       if (IS_COMMAND(msg->data, kReturnTokenCommand)) {
         listen_socket->ReturnTokens(msg->dart_port, TOKEN_COUNT(msg->data));
@@ -1077,7 +1076,7 @@
       }
     } else {
       handle->EnsureInitialized(this);
-      MonitorLocker ml(handle->monitor_);
+      MonitorLocker ml(&handle->monitor_);
 
       if (IS_COMMAND(msg->data, kReturnTokenCommand)) {
         handle->ReturnTokens(msg->dart_port, TOKEN_COUNT(msg->data));
@@ -1151,7 +1150,7 @@
   listen_socket->AcceptComplete(buffer, completion_port_);
 
   {
-    MonitorLocker ml(listen_socket->monitor_);
+    MonitorLocker ml(&listen_socket->monitor_);
     TryDispatchingPendingAccepts(listen_socket);
   }
 
@@ -1346,7 +1345,6 @@
 }
 
 EventHandlerImplementation::EventHandlerImplementation() {
-  startup_monitor_ = new Monitor();
   handler_thread_id_ = Thread::kInvalidThreadId;
   handler_thread_handle_ = NULL;
   completion_port_ =
@@ -1362,7 +1360,6 @@
   DWORD res = WaitForSingleObject(handler_thread_handle_, INFINITE);
   CloseHandle(handler_thread_handle_);
   ASSERT(res == WAIT_OBJECT_0);
-  delete startup_monitor_;
   CloseHandle(completion_port_);
 }
 
@@ -1395,7 +1392,7 @@
   ASSERT(handler_impl != NULL);
 
   {
-    MonitorLocker ml(handler_impl->startup_monitor_);
+    MonitorLocker ml(&handler_impl->startup_monitor_);
     handler_impl->handler_thread_id_ = Thread::GetCurrentThreadId();
     handler_impl->handler_thread_handle_ =
         OpenThread(SYNCHRONIZE, false, handler_impl->handler_thread_id_);
@@ -1420,7 +1417,7 @@
     if (!ok && (overlapped == NULL)) {
       if (GetLastError() == ERROR_ABANDONED_WAIT_0) {
         // The completion port should never be closed.
-        Log::Print("Completion port closed\n");
+        Syslog::Print("Completion port closed\n");
         UNREACHABLE();
       } else {
         // Timeout is signalled by false result and NULL in overlapped.
@@ -1469,7 +1466,7 @@
   }
 
   {
-    MonitorLocker ml(startup_monitor_);
+    MonitorLocker ml(&startup_monitor_);
     while (handler_thread_id_ == Thread::kInvalidThreadId) {
       ml.Wait();
     }
diff --git a/runtime/bin/eventhandler_win.h b/runtime/bin/eventhandler_win.h
index 2833f13..bbd2179 100644
--- a/runtime/bin/eventhandler_win.h
+++ b/runtime/bin/eventhandler_win.h
@@ -262,7 +262,7 @@
 
   virtual void HandleIssueError();
 
-  Monitor* monitor_;
+  Monitor monitor_;
   Type type_;
   HANDLE handle_;
   HANDLE completion_port_;
@@ -558,7 +558,7 @@
   HANDLE completion_port() { return completion_port_; }
 
  private:
-  Monitor* startup_monitor_;
+  Monitor startup_monitor_;
   ThreadId handler_thread_id_;
   HANDLE handler_thread_handle_;
 
diff --git a/runtime/bin/ffi_test_functions.cc b/runtime/bin/ffi_test_functions.cc
index 1f07257..52b4512 100644
--- a/runtime/bin/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test_functions.cc
@@ -7,8 +7,8 @@
 #include <stddef.h>
 #include <stdlib.h>
 #include <sys/types.h>
+#include <csignal>
 
-#include "platform/assert.h"
 #include "platform/globals.h"
 #if defined(HOST_OS_WINDOWS)
 #include <psapi.h>
@@ -16,13 +16,19 @@
 #include <unistd.h>
 #endif
 
+#include <setjmp.h>
+#include <signal.h>
 #include <iostream>
 #include <limits>
 
 #include "include/dart_api.h"
+#include "include/dart_native_api.h"
 
 namespace dart {
 
+////////////////////////////////////////////////////////////////////////////////
+// Tests for Dart -> native calls.
+
 // Sums two ints and adds 42.
 // Simple function to test trampolines.
 // Also used for testing argument exception on passing null instead of a Dart
@@ -85,7 +91,7 @@
 }
 
 DART_EXPORT intptr_t TakeMinInt32(int32_t x) {
-  const int64_t expected = -(int32_t)0x80000000;
+  const int64_t expected = kMinInt32;
   const int64_t received = x;
   return expected == received ? 1 : 0;
 }
@@ -449,45 +455,43 @@
   return retval;
 }
 
-// Functions for stress-testing GC by returning values that require boxing.
+////////////////////////////////////////////////////////////////////////////////
+// Functions for stress-testing.
 
 DART_EXPORT int64_t MinInt64() {
+  Dart_ExecuteInternalCommand("gc-on-next-allocation");
   return 0x8000000000000000;
 }
 
 DART_EXPORT int64_t MinInt32() {
+  Dart_ExecuteInternalCommand("gc-on-next-allocation");
   return 0x80000000;
 }
 
 DART_EXPORT double SmallDouble() {
+  Dart_ExecuteInternalCommand("gc-on-next-allocation");
   return 0x80000000 * -1.0;
 }
 
 // Requires boxing on 32-bit and 64-bit systems, even if the top 32-bits are
 // truncated.
 DART_EXPORT void* LargePointer() {
+  Dart_ExecuteInternalCommand("gc-on-next-allocation");
   uint64_t origin = 0x8100000082000000;
-  return *reinterpret_cast<void**>(&origin);
+  return reinterpret_cast<void*>(origin);
 }
 
-// Allocates 'count'-many Mint boxes, to stress-test GC during an FFI call.
-DART_EXPORT void AllocateMints(uint64_t count) {
-  Dart_EnterScope();
-  for (uint64_t i = 0; i < count; ++i) {
-    Dart_NewInteger(0x8000000000000001);
-  }
-  Dart_ExitScope();
+DART_EXPORT void TriggerGC(uint64_t count) {
+  Dart_ExecuteInternalCommand("gc-now");
 }
 
 // Calls a Dart function to allocate 'count' objects.
 // Used for stress-testing GC when re-entering the API.
-DART_EXPORT void AllocateThroughDart(uint64_t count) {
+DART_EXPORT void AllocateThroughDart() {
   Dart_EnterScope();
   Dart_Handle root = Dart_RootLibrary();
-  Dart_Handle arguments[1] = {Dart_NewIntegerFromUint64(count)};
   Dart_Handle result = Dart_Invoke(
-      root, Dart_NewStringFromCString("testAllocationsInDartHelper"), 1,
-      arguments);
+      root, Dart_NewStringFromCString("testAllocationsInDartHelper"), 0, NULL);
   const char* error;
   if (Dart_IsError(result)) {
     Dart_StringToCString(Dart_ToString(result), &error);
@@ -500,14 +504,212 @@
   Dart_ExitScope();
 }
 
-#if !defined(_WIN32)
-DART_EXPORT int RedirectStderr() {
-  char filename[256];
-  snprintf(filename, sizeof(filename), "/tmp/captured_stderr_%d", getpid());
-  freopen(filename, "w", stderr);
-  printf("Got file %s\n", filename);
-  return getpid();
+////////////////////////////////////////////////////////////////////////////////
+// Tests for callbacks.
+
+#define CHECK(X)                                                               \
+  if (!(X)) {                                                                  \
+    fprintf(stderr, "%s\n", "Check failed: " #X);                              \
+    return 1;                                                                  \
+  }
+
+#define CHECK_EQ(X, Y) CHECK((X) == (Y))
+
+// Sanity test.
+DART_EXPORT int TestSimpleAddition(int (*add)(int, int)) {
+  CHECK_EQ(add(10, 20), 30);
+  return 0;
 }
-#endif
+
+//// Following tests are copied from above, with the role of Dart and C++ code
+//// reversed.
+
+DART_EXPORT int TestIntComputation(
+    int64_t (*fn)(int8_t, int16_t, int32_t, int64_t)) {
+  CHECK_EQ(fn(125, 250, 500, 1000), 625);
+  CHECK_EQ(0x7FFFFFFFFFFFFFFFLL, fn(0, 0, 0, 0x7FFFFFFFFFFFFFFFLL));
+  CHECK_EQ(((int64_t)-0x8000000000000000LL),
+           fn(0, 0, 0, -0x8000000000000000LL));
+  return 0;
+}
+
+DART_EXPORT int TestUintComputation(
+    uint64_t (*fn)(uint8_t, uint16_t, uint32_t, uint64_t)) {
+  CHECK_EQ(0x7FFFFFFFFFFFFFFFLL, fn(0, 0, 0, 0x7FFFFFFFFFFFFFFFLL));
+  CHECK_EQ(-0x8000000000000000LL, fn(0, 0, 0, -0x8000000000000000LL));
+  CHECK_EQ(-1, (int64_t)fn(0, 0, 0, -1));
+  return 0;
+}
+
+DART_EXPORT int TestSimpleMultiply(double (*fn)(double)) {
+  CHECK_EQ(fn(2.0), 2.0 * 1.337);
+  return 0;
+}
+
+DART_EXPORT int TestSimpleMultiplyFloat(float (*fn)(float)) {
+  CHECK(std::abs(fn(2.0) - 2.0 * 1.337) < 0.001);
+  return 0;
+}
+
+DART_EXPORT int TestManyInts(intptr_t (*fn)(intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t)) {
+  CHECK_EQ(55, fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+  return 0;
+}
+
+DART_EXPORT int TestManyDoubles(double (*fn)(double,
+                                             double,
+                                             double,
+                                             double,
+                                             double,
+                                             double,
+                                             double,
+                                             double,
+                                             double,
+                                             double)) {
+  CHECK_EQ(55, fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+  return 0;
+}
+
+DART_EXPORT int TestManyArgs(double (*fn)(intptr_t a,
+                                          float b,
+                                          intptr_t c,
+                                          double d,
+                                          intptr_t e,
+                                          float f,
+                                          intptr_t g,
+                                          double h,
+                                          intptr_t i,
+                                          float j,
+                                          intptr_t k,
+                                          double l,
+                                          intptr_t m,
+                                          float n,
+                                          intptr_t o,
+                                          double p,
+                                          intptr_t q,
+                                          float r,
+                                          intptr_t s,
+                                          double t)) {
+  CHECK(210.0 == fn(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13, 14.0,
+                    15, 16.0, 17, 18.0, 19, 20.0));
+  return 0;
+}
+
+DART_EXPORT int TestStore(int64_t* (*fn)(int64_t* a)) {
+  int64_t p[2] = {42, 1000};
+  int64_t* result = fn(p);
+  CHECK_EQ(*result, 1337);
+  CHECK_EQ(p[1], 1337);
+  CHECK_EQ(result, p + 1);
+  return 0;
+}
+
+DART_EXPORT int TestReturnNull(int32_t fn()) {
+  CHECK_EQ(fn(), 0);
+  return 0;
+}
+
+DART_EXPORT int TestNullPointers(int64_t* (*fn)(int64_t* ptr)) {
+  CHECK_EQ(fn(nullptr), nullptr);
+  int64_t p[2] = {0};
+  CHECK_EQ(fn(p), p + 1);
+  return 0;
+}
+
+struct CallbackTestData {
+  int success;
+  void (*callback)();
+};
+
+#if defined(TARGET_OS_LINUX)
+
+thread_local sigjmp_buf buf;
+void CallbackTestSignalHandler(int) {
+  siglongjmp(buf, 1);
+}
+
+int ExpectAbort(void (*fn)()) {
+  fprintf(stderr, "**** EXPECT STACKTRACE TO FOLLOW. THIS IS OK. ****\n");
+
+  struct sigaction old_action;
+  int result = __sigsetjmp(buf, /*savesigs=*/1);
+  if (result == 0) {
+    // Install signal handler.
+    struct sigaction handler;
+    handler.sa_handler = CallbackTestSignalHandler;
+    sigemptyset(&handler.sa_mask);
+    handler.sa_flags = 0;
+
+    sigaction(SIGABRT, &handler, &old_action);
+
+    fn();
+  } else {
+    // Caught the setjmp.
+    sigaction(SIGABRT, &old_action, NULL);
+    exit(0);
+  }
+  fprintf(stderr, "Expected abort!!!\n");
+  exit(1);
+}
+
+void* TestCallbackOnThreadOutsideIsolate(void* parameter) {
+  CallbackTestData* data = reinterpret_cast<CallbackTestData*>(parameter);
+  data->success = ExpectAbort(data->callback);
+  return NULL;
+}
+
+int TestCallbackOtherThreadHelper(void* (*tester)(void*), void (*fn)()) {
+  CallbackTestData data = {1, fn};
+  pthread_attr_t attr;
+  int result = pthread_attr_init(&attr);
+  CHECK_EQ(result, 0);
+
+  pthread_t tid;
+  result = pthread_create(&tid, &attr, tester, &data);
+  CHECK_EQ(result, 0);
+
+  result = pthread_attr_destroy(&attr);
+  CHECK_EQ(result, 0);
+
+  void* retval;
+  result = pthread_join(tid, &retval);
+
+  // Doesn't actually return because the other thread will exit when the test is
+  // finished.
+  return 1;
+}
+
+// Run a callback on another thread and verify that it triggers SIGABRT.
+DART_EXPORT int TestCallbackWrongThread(void (*fn)()) {
+  return TestCallbackOtherThreadHelper(&TestCallbackOnThreadOutsideIsolate, fn);
+}
+
+// Verify that we get SIGABRT when invoking a native callback outside an
+// isolate.
+DART_EXPORT int TestCallbackOutsideIsolate(void (*fn)()) {
+  Dart_Isolate current = Dart_CurrentIsolate();
+
+  Dart_ExitIsolate();
+  CallbackTestData data = {1, fn};
+  TestCallbackOnThreadOutsideIsolate(&data);
+  Dart_EnterIsolate(current);
+
+  return data.success;
+}
+
+DART_EXPORT int TestCallbackWrongIsolate(void (*fn)()) {
+  return ExpectAbort(fn);
+}
+
+#endif  // defined(TARGET_OS_LINUX)
 
 }  // namespace dart
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 7bc55e0..a3347c0 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -12,9 +12,9 @@
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "bin/reference_counting.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index 0ef2414..ef983f3 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -20,9 +20,9 @@
 
 #include "bin/builtin.h"
 #include "bin/fdutils.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "platform/signal_blocker.h"
+#include "platform/syslog.h"
 #include "platform/utils.h"
 
 namespace dart {
@@ -62,7 +62,7 @@
     if (err != 0) {
       const int kBufferSize = 1024;
       char error_buf[kBufferSize];
-      Log::PrintErr("%s\n", Utils::StrError(errno, error_buf, kBufferSize));
+      Syslog::PrintErr("%s\n", Utils::StrError(errno, error_buf, kBufferSize));
     }
   }
   handle_->set_fd(kClosedFd);
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
index 9b480d5..74e3c50 100644
--- a/runtime/bin/file_fuchsia.cc
+++ b/runtime/bin/file_fuchsia.cc
@@ -19,9 +19,9 @@
 
 #include "bin/builtin.h"
 #include "bin/fdutils.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "platform/signal_blocker.h"
+#include "platform/syslog.h"
 #include "platform/utils.h"
 
 namespace dart {
@@ -61,7 +61,7 @@
     if (err != 0) {
       const int kBufferSize = 1024;
       char error_buf[kBufferSize];
-      Log::PrintErr("%s\n", Utils::StrError(errno, error_buf, kBufferSize));
+      Syslog::PrintErr("%s\n", Utils::StrError(errno, error_buf, kBufferSize));
     }
   }
   handle_->set_fd(kClosedFd);
@@ -255,9 +255,8 @@
   if (NO_RETRY_EXPECTED(fstatat(ns.fd(), ns.path(), &st, 0)) == 0) {
     // Everything but a directory and a link is a file to Dart.
     return !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode);
-  } else {
-    return false;
   }
+  return false;
 }
 
 bool File::Create(Namespace* namespc, const char* name) {
@@ -265,14 +264,17 @@
   const int fd = NO_RETRY_EXPECTED(
       openat(ns.fd(), ns.path(), O_RDONLY | O_CREAT | O_CLOEXEC, 0666));
   if (fd < 0) {
+    Syslog::PrintErr("File::Create() openat(%ld, %s) failed: %s\n", ns.fd(),
+                     ns.path(), strerror(errno));
     return false;
   }
   // File.create returns a File, so we shouldn't be giving the illusion that the
   // call has created a file or that a file already exists if there is already
   // an entity at the same path that is a directory or a link.
-  bool is_file = true;
+  bool is_file = false;
   struct stat st;
   if (NO_RETRY_EXPECTED(fstat(fd, &st)) == 0) {
+    is_file = true;
     if (S_ISDIR(st.st_mode)) {
       errno = EISDIR;
       is_file = false;
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index 3346d64..f53d69a 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -19,9 +19,9 @@
 
 #include "bin/builtin.h"
 #include "bin/fdutils.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "platform/signal_blocker.h"
+#include "platform/syslog.h"
 #include "platform/utils.h"
 
 namespace dart {
@@ -61,7 +61,7 @@
     if (err != 0) {
       const int kBufferSize = 1024;
       char error_buf[kBufferSize];
-      Log::PrintErr("%s\n", Utils::StrError(errno, error_buf, kBufferSize));
+      Syslog::PrintErr("%s\n", Utils::StrError(errno, error_buf, kBufferSize));
     }
   }
   handle_->set_fd(kClosedFd);
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 3320491..a80071a 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -19,9 +19,9 @@
 
 #include "bin/builtin.h"
 #include "bin/fdutils.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "platform/signal_blocker.h"
+#include "platform/syslog.h"
 #include "platform/utils.h"
 
 namespace dart {
@@ -62,7 +62,7 @@
       const int kBufferSize = 1024;
       char error_message[kBufferSize];
       Utils::StrError(errno, error_message, kBufferSize);
-      Log::PrintErr("%s\n", error_message);
+      Syslog::PrintErr("%s\n", error_message);
     }
   }
   handle_->set_fd(kClosedFd);
diff --git a/runtime/bin/file_system_watcher_win.cc b/runtime/bin/file_system_watcher_win.cc
index d66f6da..33654c4 100644
--- a/runtime/bin/file_system_watcher_win.cc
+++ b/runtime/bin/file_system_watcher_win.cc
@@ -11,9 +11,9 @@
 
 #include "bin/builtin.h"
 #include "bin/eventhandler.h"
-#include "bin/log.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 0b59b20..d0011be 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -18,10 +18,10 @@
 
 #include "bin/builtin.h"
 #include "bin/directory.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
+#include "platform/syslog.h"
 #include "platform/utils.h"
 
 namespace dart {
@@ -59,7 +59,7 @@
   } else {
     int err = close(closing_fd);
     if (err != 0) {
-      Log::PrintErr("%s\n", strerror(errno));
+      Syslog::PrintErr("%s\n", strerror(errno));
     }
   }
   handle_->set_fd(kClosedFd);
@@ -91,13 +91,13 @@
 
   void* addr = VirtualAlloc(NULL, length, MEM_COMMIT | MEM_RESERVE, prot_alloc);
   if (addr == NULL) {
-    Log::PrintErr("VirtualAlloc failed %d\n", GetLastError());
+    Syslog::PrintErr("VirtualAlloc failed %d\n", GetLastError());
     return NULL;
   }
 
   SetPosition(position);
   if (!ReadFully(addr, length)) {
-    Log::PrintErr("ReadFully failed %d\n", GetLastError());
+    Syslog::PrintErr("ReadFully failed %d\n", GetLastError());
     VirtualFree(addr, 0, MEM_RELEASE);
     return NULL;
   }
@@ -105,7 +105,7 @@
   DWORD old_prot;
   bool result = VirtualProtect(addr, length, prot_final, &old_prot);
   if (!result) {
-    Log::PrintErr("VirtualProtect failed %d\n", GetLastError());
+    Syslog::PrintErr("VirtualProtect failed %d\n", GetLastError());
     VirtualFree(addr, 0, MEM_RELEASE);
     return NULL;
   }
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 6632130..fbd41ce 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -18,13 +18,13 @@
 #include "bin/eventhandler.h"
 #include "bin/file.h"
 #include "bin/loader.h"
-#include "bin/log.h"
 #include "bin/options.h"
 #include "bin/platform.h"
 #include "bin/snapshot_utils.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
 #include "bin/vmservice_impl.h"
+#include "platform/syslog.h"
 
 #include "include/dart_api.h"
 #include "include/dart_tools_api.h"
@@ -46,7 +46,7 @@
 #define CHECK_RESULT(result)                                                   \
   if (Dart_IsError(result)) {                                                  \
     intptr_t exit_code = 0;                                                    \
-    Log::PrintErr("Error: %s\n", Dart_GetError(result));                       \
+    Syslog::PrintErr("Error: %s\n", Dart_GetError(result));                    \
     if (Dart_IsCompilationError(result)) {                                     \
       exit_code = kCompilationErrorExitCode;                                   \
     } else if (Dart_IsApiError(result)) {                                      \
@@ -83,6 +83,7 @@
   kAppJIT,
   kAppAOTBlobs,
   kAppAOTAssembly,
+  kAppAOTElf,
   kVMAOTAssembly,
 };
 static SnapshotKind snapshot_kind = kCore;
@@ -96,6 +97,7 @@
     "app-jit",
     "app-aot-blobs",
     "app-aot-assembly",
+    "app-aot-elf",
     "vm-aot-assembly",
     NULL,
     // clang-format on
@@ -117,17 +119,19 @@
   V(reused_instructions, reused_instructions_filename)                         \
   V(blobs_container_filename, blobs_container_filename)                        \
   V(assembly, assembly_filename)                                               \
+  V(elf, elf_filename)                                                         \
   V(load_compilation_trace, load_compilation_trace_filename)                   \
   V(load_type_feedback, load_type_feedback_filename)                           \
   V(save_obfuscation_map, obfuscation_map_filename)
 
 #define BOOL_OPTIONS_LIST(V)                                                   \
-  V(read_all_bytecode, read_all_bytecode)                                      \
   V(compile_all, compile_all)                                                  \
+  V(help, help)                                                                \
   V(obfuscate, obfuscate)                                                      \
+  V(read_all_bytecode, read_all_bytecode)                                      \
+  V(strip, strip)                                                              \
   V(verbose, verbose)                                                          \
-  V(version, version)                                                          \
-  V(help, help)
+  V(version, version)
 
 #define STRING_OPTION_DEFINITION(flag, variable)                               \
   static const char* variable = NULL;                                          \
@@ -146,13 +150,13 @@
 
 static bool IsSnapshottingForPrecompilation() {
   return (snapshot_kind == kAppAOTBlobs) ||
-         (snapshot_kind == kAppAOTAssembly) ||
+         (snapshot_kind == kAppAOTAssembly) || (snapshot_kind == kAppAOTElf) ||
          (snapshot_kind == kVMAOTAssembly);
 }
 
 // clang-format off
 static void PrintUsage() {
-  Log::PrintErr(
+  Syslog::PrintErr(
 "Usage: gen_snapshot [<vm-flags>] [<options>] <dart-kernel-file>             \n"
 "                                                                            \n"
 "Common options:                                                             \n"
@@ -186,6 +190,14 @@
 "[--save-obfuscation-map=<map-filename>]                                     \n"
 "<dart-kernel-file>                                                          \n"
 "                                                                            \n"
+"To create an AOT application snapshot as an ELF shared library:             \n"
+"--snapshot_kind=app-aot-elf                                                 \n"
+"--elf=<output-file>                                                         \n"
+"[--strip]                                                                   \n"
+"[--obfuscate]                                                               \n"
+"[--save-obfuscation-map=<map-filename>]                                     \n"
+"<dart-kernel-file>                                                          \n"
+"                                                                            \n"
 "AOT snapshots can be obfuscated: that is all identifiers will be renamed    \n"
 "during compilation. This mode is enabled with --obfuscate flag. Mapping     \n"
 "between original and obfuscated names can be serialized as a JSON array     \n"
@@ -194,7 +206,7 @@
 "                                                                            \n"
 "\n");
   if (verbose) {
-    Log::PrintErr(
+    Syslog::PrintErr(
 "The following options are only used for VM development and may\n"
 "be changed in any future version:\n");
     const char* print_flags = "--print_flags";
@@ -237,13 +249,13 @@
     PrintUsage();
     Platform::Exit(0);
   } else if (version) {
-    Log::PrintErr("Dart VM version: %s\n", Dart_VersionString());
+    Syslog::PrintErr("Dart VM version: %s\n", Dart_VersionString());
     Platform::Exit(0);
   }
 
   // Verify consistency of arguments.
   if (inputs->count() < 1) {
-    Log::PrintErr("At least one input is required\n");
+    Syslog::PrintErr("At least one input is required\n");
     return -1;
   }
 
@@ -251,7 +263,7 @@
     case kCore: {
       if ((vm_snapshot_data_filename == NULL) ||
           (isolate_snapshot_data_filename == NULL)) {
-        Log::PrintErr(
+        Syslog::PrintErr(
             "Building a core snapshot requires specifying output files for "
             "--vm_snapshot_data and --isolate_snapshot_data.\n\n");
         return -1;
@@ -263,7 +275,7 @@
           (vm_snapshot_instructions_filename == NULL) ||
           (isolate_snapshot_data_filename == NULL) ||
           (isolate_snapshot_instructions_filename == NULL)) {
-        Log::PrintErr(
+        Syslog::PrintErr(
             "Building a core JIT snapshot requires specifying output "
             "files for --vm_snapshot_data, --vm_snapshot_instructions, "
             "--isolate_snapshot_data and --isolate_snapshot_instructions.\n\n");
@@ -277,7 +289,7 @@
           (isolate_snapshot_data_filename == NULL) ||
           ((isolate_snapshot_instructions_filename == NULL) &&
            (reused_instructions_filename == NULL))) {
-        Log::PrintErr(
+        Syslog::PrintErr(
             "Building an app JIT snapshot requires specifying input files for "
             "--load_vm_snapshot_data and --load_vm_snapshot_instructions, an "
             " output file for --isolate_snapshot_data, and either an output "
@@ -293,7 +305,7 @@
            (vm_snapshot_instructions_filename == NULL) ||
            (isolate_snapshot_data_filename == NULL) ||
            (isolate_snapshot_instructions_filename == NULL))) {
-        Log::PrintErr(
+        Syslog::PrintErr(
             "Building an AOT snapshot as blobs requires specifying output "
             "file for --blobs_container_filename or "
             "files for --vm_snapshot_data, --vm_snapshot_instructions, "
@@ -305,7 +317,7 @@
            (vm_snapshot_instructions_filename != NULL) ||
            (isolate_snapshot_data_filename != NULL) ||
            (isolate_snapshot_instructions_filename != NULL))) {
-        Log::PrintErr(
+        Syslog::PrintErr(
             "Building an AOT snapshot as blobs requires specifying output "
             "file for --blobs_container_filename or "
             "files for --vm_snapshot_data, --vm_snapshot_instructions, "
@@ -315,18 +327,19 @@
       }
       break;
     }
-    case kAppAOTAssembly: {
-      if (assembly_filename == NULL) {
-        Log::PrintErr(
+    case kAppAOTElf: {
+      if (elf_filename == NULL) {
+        Syslog::PrintErr(
             "Building an AOT snapshot as assembly requires specifying "
-            "an output file for --assembly.\n\n");
+            "an output file for --elf.\n\n");
         return -1;
       }
       break;
     }
+    case kAppAOTAssembly:
     case kVMAOTAssembly: {
       if (assembly_filename == NULL) {
-        Log::PrintErr(
+        Syslog::PrintErr(
             "Building an AOT snapshot as assembly requires specifying "
             "an output file for --assembly.\n\n");
         return -1;
@@ -336,14 +349,14 @@
   }
 
   if (!obfuscate && obfuscation_map_filename != NULL) {
-    Log::PrintErr(
+    Syslog::PrintErr(
         "--obfuscation_map=<...> should only be specified when obfuscation is "
         "enabled by --obfuscate flag.\n\n");
     return -1;
   }
 
   if (obfuscate && !IsSnapshottingForPrecompilation()) {
-    Log::PrintErr(
+    Syslog::PrintErr(
         "Obfuscation can only be enabled when building AOT snapshot.\n\n");
     return -1;
   }
@@ -354,7 +367,7 @@
 static File* OpenFile(const char* filename) {
   File* file = File::Open(NULL, filename, File::kWriteTruncate);
   if (file == NULL) {
-    Log::PrintErr("Error: Unable to write file: %s\n\n", filename);
+    Syslog::PrintErr("Error: Unable to write file: %s\n\n", filename);
     Dart_ExitScope();
     Dart_ShutdownIsolate();
     exit(kErrorExitCode);
@@ -368,7 +381,7 @@
   File* file = OpenFile(filename);
   RefCntReleaseScope<File> rs(file);
   if (!file->WriteFully(buffer, size)) {
-    Log::PrintErr("Error: Unable to write file: %s\n\n", filename);
+    Syslog::PrintErr("Error: Unable to write file: %s\n\n", filename);
     Dart_ExitScope();
     Dart_ShutdownIsolate();
     exit(kErrorExitCode);
@@ -378,7 +391,7 @@
 static void ReadFile(const char* filename, uint8_t** buffer, intptr_t* size) {
   File* file = File::Open(NULL, filename, File::kRead);
   if (file == NULL) {
-    Log::PrintErr("Unable to open file %s\n", filename);
+    Syslog::PrintErr("Unable to open file %s\n", filename);
     Dart_ExitScope();
     Dart_ShutdownIsolate();
     exit(kErrorExitCode);
@@ -387,7 +400,7 @@
   *size = file->Length();
   *buffer = reinterpret_cast<uint8_t*>(malloc(*size));
   if (!file->ReadFully(*buffer, *size)) {
-    Log::PrintErr("Unable to read file %s\n", filename);
+    Syslog::PrintErr("Unable to read file %s\n", filename);
     Dart_ExitScope();
     Dart_ShutdownIsolate();
     exit(kErrorExitCode);
@@ -420,10 +433,18 @@
 
   if ((load_compilation_trace_filename != NULL) &&
       ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) {
+    // Finalize all classes. This ensures that there are no non-finalized
+    // classes in the gaps between cid ranges. Such classes prevent merging of
+    // cid ranges.
+    Dart_Handle result = Dart_FinalizeAllClasses();
+    CHECK_RESULT(result);
+    // Sort classes to have better cid ranges.
+    result = Dart_SortClasses();
+    CHECK_RESULT(result);
     uint8_t* buffer = NULL;
     intptr_t size = 0;
     ReadFile(load_compilation_trace_filename, &buffer, &size);
-    Dart_Handle result = Dart_LoadCompilationTrace(buffer, size);
+    result = Dart_LoadCompilationTrace(buffer, size);
     free(buffer);
     CHECK_RESULT(result);
   }
@@ -479,7 +500,7 @@
                                              const uint8_t** buffer) {
   File* file = File::Open(NULL, filename, File::kRead);
   if (file == NULL) {
-    Log::PrintErr("Failed to open: %s\n", filename);
+    Syslog::PrintErr("Failed to open: %s\n", filename);
     exit(kErrorExitCode);
   }
   RefCntReleaseScope<File> rs(file);
@@ -491,7 +512,7 @@
   }
   MappedMemory* mapping = file->Map(type, 0, length);
   if (mapping == NULL) {
-    Log::PrintErr("Failed to read: %s\n", filename);
+    Syslog::PrintErr("Failed to read: %s\n", filename);
     exit(kErrorExitCode);
   }
   *buffer = reinterpret_cast<const uint8_t*>(mapping->address());
@@ -597,7 +618,7 @@
                                    intptr_t size) {
   File* file = reinterpret_cast<File*>(callback_data);
   if (!file->WriteFully(buffer, size)) {
-    Log::PrintErr("Error: Unable to write snapshot file\n\n");
+    Syslog::PrintErr("Error: Unable to write snapshot file\n\n");
     Dart_ExitScope();
     Dart_ShutdownIsolate();
     exit(kErrorExitCode);
@@ -613,26 +634,33 @@
   CHECK_RESULT(result);
 
   // Create a precompiled snapshot.
-  bool as_assembly = assembly_filename != NULL;
-  if (as_assembly) {
-    ASSERT(snapshot_kind == kAppAOTAssembly);
+  if (snapshot_kind == kAppAOTAssembly) {
     File* file = OpenFile(assembly_filename);
     RefCntReleaseScope<File> rs(file);
     result = Dart_CreateAppAOTSnapshotAsAssembly(StreamingWriteCallback, file);
     CHECK_RESULT(result);
-  } else {
-    ASSERT(snapshot_kind == kAppAOTBlobs);
-
+  } else if (snapshot_kind == kAppAOTElf) {
+    if (strip) {
+      Syslog::PrintErr(
+          "Warning: Generating ELF library without DWARF debugging"
+          " information.\n");
+    }
+    File* file = OpenFile(elf_filename);
+    RefCntReleaseScope<File> rs(file);
+    result =
+        Dart_CreateAppAOTSnapshotAsElf(StreamingWriteCallback, file, strip);
+    CHECK_RESULT(result);
+  } else if (snapshot_kind == kAppAOTBlobs) {
     const uint8_t* shared_data = NULL;
     const uint8_t* shared_instructions = NULL;
     std::unique_ptr<MappedMemory> mapped_shared_data;
     std::unique_ptr<MappedMemory> mapped_shared_instructions;
     if (shared_blobs_filename != NULL) {
       AppSnapshot* shared_blobs = NULL;
-      Log::PrintErr("Shared blobs in gen_snapshot are for testing only.\n");
+      Syslog::PrintErr("Shared blobs in gen_snapshot are for testing only.\n");
       shared_blobs = Snapshot::TryReadAppSnapshot(shared_blobs_filename);
       if (shared_blobs == NULL) {
-        Log::PrintErr("Failed to load: %s\n", shared_blobs_filename);
+        Syslog::PrintErr("Failed to load: %s\n", shared_blobs_filename);
         Dart_ExitScope();
         Dart_ShutdownIsolate();
         exit(kErrorExitCode);
@@ -686,6 +714,8 @@
                 isolate_snapshot_instructions_buffer,
                 isolate_snapshot_instructions_size);
     }
+  } else {
+    UNREACHABLE();
   }
 
   // Serialize obfuscation map if requested.
@@ -732,7 +762,7 @@
   }
   if (isolate == NULL) {
     delete isolate_data;
-    Log::PrintErr("%s\n", error);
+    Syslog::PrintErr("%s\n", error);
     free(error);
     return kErrorExitCode;
   }
@@ -777,8 +807,9 @@
     case kAppJIT:
       CreateAndWriteAppJITSnapshot();
       break;
-    case kAppAOTBlobs:
     case kAppAOTAssembly:
+    case kAppAOTBlobs:
+    case kAppAOTElf:
       CreateAndWritePrecompiledSnapshot();
       break;
     case kVMAOTAssembly: {
@@ -821,7 +852,7 @@
   DartUtils::SetEnvironment(environment);
 
   if (!Platform::Initialize()) {
-    Log::PrintErr("Initialization failed\n");
+    Syslog::PrintErr("Initialization failed\n");
     return kErrorExitCode;
   }
   Console::SaveConfig();
@@ -843,14 +874,11 @@
 #if !defined(TARGET_ARCH_IA32)
     vm_options.AddArgument("--link_natives_lazily");
 #endif
-#if !defined(PRODUCT)
-    vm_options.AddArgument("--collect_code=false");
-#endif
   }
 
   char* error = Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
   if (error != NULL) {
-    Log::PrintErr("Setting VM flags failed: %s\n", error);
+    Syslog::PrintErr("Setting VM flags failed: %s\n", error);
     free(error);
     return kErrorExitCode;
   }
@@ -892,7 +920,7 @@
 
   error = Dart_Initialize(&init_params);
   if (error != NULL) {
-    Log::PrintErr("VM initialization failed: %s\n", error);
+    Syslog::PrintErr("VM initialization failed: %s\n", error);
     free(error);
     return kErrorExitCode;
   }
@@ -904,7 +932,7 @@
 
   error = Dart_Cleanup();
   if (error != NULL) {
-    Log::PrintErr("VM cleanup failed: %s\n", error);
+    Syslog::PrintErr("VM cleanup failed: %s\n", error);
     free(error);
   }
   EventHandler::Stop();
diff --git a/runtime/bin/ifaddrs-android.cc b/runtime/bin/ifaddrs-android.cc
new file mode 100644
index 0000000..bd4c5f5
--- /dev/null
+++ b/runtime/bin/ifaddrs-android.cc
@@ -0,0 +1,232 @@
+// Copyright (c) 2019, 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(ANDROID) && __ANDROID_API__ < 24
+
+#include "bin/ifaddrs-android.h"
+
+#include <errno.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+#include "bin/fdutils.h"
+#include "platform/signal_blocker.h"
+
+namespace dart {
+namespace bin {
+
+const int kMaxReadSize = 2048;
+
+static bool SetIfName(struct ifaddrs* ifaddr, int interface) {
+  char buf[IFNAMSIZ] = {0};
+  char* name = if_indextoname(interface, buf);
+  if (name == NULL) {
+    return false;
+  }
+  ifaddr->ifa_name = new char[strlen(name) + 1];
+  strncpy(ifaddr->ifa_name, name, strlen(name) + 1);
+  return true;
+}
+
+static void SetFlags(struct ifaddrs* ifaddr, int flag) {
+  ifaddr->ifa_flags = flag;
+}
+
+static void SetAddresses(struct ifaddrs* ifaddr,
+                         int family,
+                         int index,
+                         void* data,
+                         size_t len) {
+  if (family == AF_INET6) {
+    sockaddr_in6* socketaddr = new sockaddr_in6;
+    socketaddr->sin6_family = AF_INET6;
+    socketaddr->sin6_scope_id = index;
+    memmove(&socketaddr->sin6_addr, data, len);
+    ifaddr->ifa_addr = reinterpret_cast<sockaddr*>(socketaddr);
+    return;
+  }
+  ASSERT(family == AF_INET);
+  sockaddr_in* socketaddr = new sockaddr_in;
+  socketaddr->sin_family = AF_INET;
+  memmove(&socketaddr->sin_addr, data, len);
+  ifaddr->ifa_addr = reinterpret_cast<sockaddr*>(socketaddr);
+}
+
+static void SetNetmask(struct ifaddrs* ifaddr, int family) {
+  if (family == AF_INET6) {
+    sockaddr_in6* mask = new sockaddr_in6;
+    mask->sin6_family = AF_INET6;
+    memset(&mask->sin6_addr, 0, sizeof(mask->sin6_addr));
+    ifaddr->ifa_netmask = reinterpret_cast<sockaddr*>(mask);
+    return;
+  }
+  ASSERT(family == AF_INET);
+  sockaddr_in* mask = new sockaddr_in;
+  mask->sin_family = AF_INET;
+  memset(&mask->sin_addr, 0, sizeof(mask->sin_addr));
+  ifaddr->ifa_netmask = reinterpret_cast<sockaddr*>(mask);
+}
+
+static bool SetIfAddrsFromAddrMsg(struct ifaddrs* ifaddr,
+                                  ifaddrmsg* msg,
+                                  void* bytes,
+                                  size_t len,
+                                  nlmsghdr* header) {
+  SetAddresses(ifaddr, msg->ifa_family, msg->ifa_index, bytes, len);
+  SetNetmask(ifaddr, msg->ifa_family);
+  SetFlags(ifaddr, msg->ifa_flags);
+  return SetIfName(ifaddr, msg->ifa_index);
+}
+
+static bool SetIfAddrsFromInfoMsg(struct ifaddrs* ifaddr,
+                                  ifinfomsg* ifi,
+                                  void* bytes,
+                                  size_t len,
+                                  nlmsghdr* header) {
+  SetAddresses(ifaddr, ifi->ifi_family, ifi->ifi_index, bytes, len);
+  SetNetmask(ifaddr, ifi->ifi_family);
+  SetFlags(ifaddr, ifi->ifi_flags);
+  return SetIfName(ifaddr, ifi->ifi_index);
+}
+
+static int SendRequest() {
+  int file_descriptor =
+      NO_RETRY_EXPECTED(socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE));
+  if (file_descriptor < 0) {
+    return -1;
+  }
+  nlmsghdr header;
+  memset(&header, 0, sizeof(header));
+  header.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
+  header.nlmsg_type = RTM_GETADDR;
+  header.nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrmsg));
+  ssize_t num =
+      TEMP_FAILURE_RETRY(send(file_descriptor, &header, header.nlmsg_len, 0));
+  if (static_cast<size_t>(num) != header.nlmsg_len) {
+    FDUtils::SaveErrorAndClose(file_descriptor);
+    return -1;
+  }
+  return file_descriptor;
+}
+
+static int FailAndExit(int fd, ifaddrs* head) {
+  FDUtils::SaveErrorAndClose(fd);
+  freeifaddrs(head);
+  return -1;
+}
+
+int getifaddrs(struct ifaddrs** result) {
+  int file_descriptor = SendRequest();
+  if (file_descriptor < 0) {
+    return -1;
+  }
+  struct ifaddrs* head = NULL;
+  struct ifaddrs* cur = NULL;
+  char buf[kMaxReadSize];
+  ssize_t amount_read;
+  while (true) {
+    amount_read =
+        TEMP_FAILURE_RETRY(recv(file_descriptor, &buf, kMaxReadSize, 0));
+    if (amount_read <= 0) {
+      break;
+    }
+    nlmsghdr* header = reinterpret_cast<nlmsghdr*>(&buf[0]);
+    size_t header_size = static_cast<size_t>(amount_read);
+    for (; NLMSG_OK(header, header_size);
+         header = NLMSG_NEXT(header, header_size)) {
+      switch (header->nlmsg_type) {
+        case RTM_NEWADDR: {
+          ifaddrmsg* address_msg =
+              reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(header));
+          ssize_t payload_len = IFA_PAYLOAD(header);
+          for (rtattr* rta = IFA_RTA(address_msg); RTA_OK(rta, payload_len);
+               rta = RTA_NEXT(rta, payload_len)) {
+            if (rta->rta_type != IFA_ADDRESS) {
+              continue;
+            }
+            int family = address_msg->ifa_family;
+            if (family != AF_INET && family != AF_INET6) {
+              continue;
+            }
+            ifaddrs* next = new ifaddrs;
+            memset(next, 0, sizeof(*next));
+            if (cur != NULL) {
+              cur->ifa_next = next;
+            } else {
+              head = next;
+            }
+            if (!SetIfAddrsFromAddrMsg(next, address_msg, RTA_DATA(rta),
+                                       RTA_PAYLOAD(rta), header)) {
+              return FailAndExit(file_descriptor, head);
+            }
+            cur = next;
+          }
+          break;
+        }
+        case RTM_NEWLINK: {
+          ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(header));
+          ssize_t payload_len = IFLA_PAYLOAD(header);
+          for (rtattr* rta = IFLA_RTA(ifi); RTA_OK(rta, payload_len);
+               rta = RTA_NEXT(rta, payload_len)) {
+            if (rta->rta_type != IFA_ADDRESS) {
+              continue;
+            }
+            int family = ifi->ifi_family;
+            if (family != AF_INET && family != AF_INET6) {
+              continue;
+            }
+            ifaddrs* next = new ifaddrs;
+            memset(next, 0, sizeof(*next));
+            if (cur != NULL) {
+              cur->ifa_next = next;
+            } else {
+              head = next;
+            }
+            if (!SetIfAddrsFromInfoMsg(next, ifi, RTA_DATA(rta),
+                                       RTA_PAYLOAD(rta), header)) {
+              return FailAndExit(file_descriptor, head);
+            }
+            cur = next;
+          }
+          break;
+        }
+        case NLMSG_DONE:
+          *result = head;
+          FDUtils::SaveErrorAndClose(file_descriptor);
+          return 0;
+        case NLMSG_ERROR:
+          return FailAndExit(file_descriptor, head);
+      }
+    }
+  }
+  return FailAndExit(file_descriptor, head);
+}
+
+void freeifaddrs(struct ifaddrs* addrs) {
+  int err = errno;
+  struct ifaddrs* previous = NULL;
+  while (addrs != NULL) {
+    delete[] addrs->ifa_name;
+    delete addrs->ifa_addr;
+    delete addrs->ifa_netmask;
+    previous = addrs;
+    addrs = addrs->ifa_next;
+    delete previous;
+  }
+  errno = err;
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(ANDROID) && __ANDROID_API__ < 24
diff --git a/runtime/bin/ifaddrs-android.h b/runtime/bin/ifaddrs-android.h
new file mode 100644
index 0000000..ec0ecd2
--- /dev/null
+++ b/runtime/bin/ifaddrs-android.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_BIN_IFADDRS_ANDROID_H_
+#define RUNTIME_BIN_IFADDRS_ANDROID_H_
+
+#if defined(ANDROID) && __ANDROID_API__ < 24
+#include <sys/socket.h>
+
+namespace dart {
+namespace bin {
+
+struct ifaddrs {
+  struct ifaddrs* ifa_next;
+  char* ifa_name;
+  unsigned int ifa_flags;
+  struct sockaddr* ifa_addr;
+  struct sockaddr* ifa_netmask;
+  union {
+    struct sockaddr* ifu_broadaddr;
+    struct sockaddr* ifu_dstaddr;
+  } ifa_ifu;
+  void* ifa_data;
+};
+
+void freeifaddrs(struct ifaddrs* __ptr);
+int getifaddrs(struct ifaddrs** __list_ptr);
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(ANDROID) && __ANDROID_API__ < 24
+#endif  // RUNTIME_BIN_IFADDRS_ANDROID_H_
diff --git a/runtime/bin/io_impl_sources.gni b/runtime/bin/io_impl_sources.gni
index a476664..e40832d 100644
--- a/runtime/bin/io_impl_sources.gni
+++ b/runtime/bin/io_impl_sources.gni
@@ -29,6 +29,8 @@
   "file_system_watcher_win.cc",
   "filter.cc",
   "filter.h",
+  "ifaddrs-android.cc",
+  "ifaddrs-android.h",
   "io_service.cc",
   "io_service.h",
   "io_service_no_ssl.cc",
diff --git a/runtime/bin/io_sources.gni b/runtime/bin/io_sources.gni
index 4bc7c1d..56de0e7 100644
--- a/runtime/bin/io_sources.gni
+++ b/runtime/bin/io_sources.gni
@@ -3,7 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # This file contains all sources for the dart:io library.
-io_runtime_sources = [
+io_runtime_dart_files = [
   "common_patch.dart",
   "directory_patch.dart",
   "eventhandler_patch.dart",
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index e335ca5..a56cdc2 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -33,14 +33,13 @@
     : port_(ILLEGAL_PORT),
       isolate_data_(isolate_data),
       error_(Dart_Null()),
-      monitor_(NULL),
+      monitor_(),
       pending_operations_(0),
       results_(NULL),
       results_length_(0),
       results_capacity_(0),
       payload_(NULL),
       payload_length_(0) {
-  monitor_ = new Monitor();
   ASSERT(isolate_data_ != NULL);
   port_ = Dart_NewNativePort("Loader", Loader::NativeMessageHandler, false);
   isolate_data_->set_loader(this);
@@ -51,15 +50,13 @@
   ASSERT(port_ != ILLEGAL_PORT);
   // Enter the monitor while we close the Dart port. After the Dart port is
   // closed, no more results can be queued.
-  monitor_->Enter();
+  monitor_.Enter();
   Dart_CloseNativePort(port_);
-  monitor_->Exit();
+  monitor_.Exit();
   RemoveLoader(port_);
   port_ = ILLEGAL_PORT;
   isolate_data_->set_loader(NULL);
   isolate_data_ = NULL;
-  delete monitor_;
-  monitor_ = NULL;
   for (intptr_t i = 0; i < results_length_; i++) {
     results_[i].Cleanup();
   }
@@ -182,7 +179,7 @@
   Dart_ListSetAt(request, 5, library_url);
 
   if (Dart_Post(loader_port, request)) {
-    MonitorLocker ml(monitor_);
+    MonitorLocker ml(&monitor_);
     pending_operations_++;
   }
 }
@@ -205,13 +202,13 @@
   Dart_ListSetAt(request, 5, library_url);
 
   if (Dart_Post(loader_port, request)) {
-    MonitorLocker ml(monitor_);
+    MonitorLocker ml(&monitor_);
     pending_operations_++;
   }
 }
 
 void Loader::QueueMessage(Dart_CObject* message) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
   if (results_length_ == results_capacity_) {
     // Grow to an initial capacity or double in size.
     results_capacity_ = (results_capacity_ == 0) ? 4 : results_capacity_ * 2;
@@ -227,7 +224,7 @@
 }
 
 void Loader::BlockUntilComplete(ProcessResult process_result) {
-  MonitorLocker ml(monitor_);
+  MonitorLocker ml(&monitor_);
 
   while (true) {
     // If |ProcessQueueLocked| returns false, we've hit an error and should
@@ -292,7 +289,7 @@
     Dart_Handle result =
         Loader::ResolveAsFilePath(uri, &file_path, &file_path_length);
     if (Dart_IsError(result)) {
-      Log::Print("Error resolving dependency: %s\n", Dart_GetError(result));
+      Syslog::Print("Error resolving dependency: %s\n", Dart_GetError(result));
       return;
     }
 
diff --git a/runtime/bin/loader.h b/runtime/bin/loader.h
index 2e94033..4142c89 100644
--- a/runtime/bin/loader.h
+++ b/runtime/bin/loader.h
@@ -49,7 +49,7 @@
   Dart_Handle error_;
   // This monitor is used to protect the pending operations count and the
   // I/O result queue.
-  Monitor* monitor_;
+  Monitor monitor_;
 
   // The number of operations dispatched to the service isolate for loading.
   // Must be accessed with monitor_ held.
diff --git a/runtime/bin/log.h b/runtime/bin/log.h
deleted file mode 100644
index 022dd1b..0000000
--- a/runtime/bin/log.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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.
-
-#ifndef RUNTIME_BIN_LOG_H_
-#define RUNTIME_BIN_LOG_H_
-
-#include <stdarg.h>
-
-#include "platform/globals.h"
-
-namespace dart {
-namespace bin {
-
-class Log {
- public:
-  // Print formatted output for debugging.
-  static void Print(const char* format, ...) PRINTF_ATTRIBUTE(1, 2) {
-    va_list args;
-    va_start(args, format);
-    VPrint(format, args);
-    va_end(args);
-  }
-
-  static void VPrint(const char* format, va_list args);
-
-  static void PrintErr(const char* format, ...) PRINTF_ATTRIBUTE(1, 2) {
-    va_list args;
-    va_start(args, format);
-    VPrintErr(format, args);
-    va_end(args);
-  }
-
-  static void VPrintErr(const char* format, va_list args);
-
- private:
-  DISALLOW_ALLOCATION();
-  DISALLOW_IMPLICIT_CONSTRUCTORS(Log);
-};
-
-}  // namespace bin
-}  // namespace dart
-
-#endif  // RUNTIME_BIN_LOG_H_
diff --git a/runtime/bin/log_android.cc b/runtime/bin/log_android.cc
deleted file mode 100644
index 164db7f..0000000
--- a/runtime/bin/log_android.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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.
-
-#include "platform/globals.h"
-#if defined(HOST_OS_ANDROID)
-
-#include "bin/log.h"
-
-#include <android/log.h>  // NOLINT
-#include <stdio.h>        // NOLINT
-
-namespace dart {
-namespace bin {
-
-// TODO(gram): We should be buffering the data and only outputting
-// it when we see a '\n'.
-
-void Log::VPrint(const char* format, va_list args) {
-  // If we launch the DartVM inside "adb shell" we will only get messages
-  // (critical ones or not) if we print them to stdout/stderr.
-  // We also log using android's logging system.
-  vprintf(format, args);
-  fflush(stdout);
-  __android_log_vprint(ANDROID_LOG_INFO, "Dart", format, args);
-}
-
-void Log::VPrintErr(const char* format, va_list args) {
-  // If we launch the DartVM inside "adb shell" we will only get messages
-  // (critical ones or not) if we print them to stdout/stderr.
-  // We also log using android's logging system.
-  vfprintf(stderr, format, args);
-  fflush(stderr);
-  __android_log_vprint(ANDROID_LOG_ERROR, "Dart", format, args);
-}
-
-}  // namespace bin
-}  // namespace dart
-
-#endif  // defined(HOST_OS_ANDROID)
diff --git a/runtime/bin/log_fuchsia.cc b/runtime/bin/log_fuchsia.cc
deleted file mode 100644
index f84fc49..0000000
--- a/runtime/bin/log_fuchsia.cc
+++ /dev/null
@@ -1,28 +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.
-
-#include "platform/globals.h"
-#if defined(HOST_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(stderr);
-}
-
-}  // namespace bin
-}  // namespace dart
-
-#endif  // defined(HOST_OS_FUCHSIA)
diff --git a/runtime/bin/log_linux.cc b/runtime/bin/log_linux.cc
deleted file mode 100644
index 2844a17..0000000
--- a/runtime/bin/log_linux.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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.
-
-#include "platform/globals.h"
-#if defined(HOST_OS_LINUX)
-
-#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(stderr);
-}
-
-}  // namespace bin
-}  // namespace dart
-
-#endif  // defined(HOST_OS_LINUX)
diff --git a/runtime/bin/log_macos.cc b/runtime/bin/log_macos.cc
deleted file mode 100644
index 4044acf..0000000
--- a/runtime/bin/log_macos.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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.
-
-#include "platform/globals.h"
-#if defined(HOST_OS_MACOS)
-
-#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(stderr);
-}
-
-}  // namespace bin
-}  // namespace dart
-
-#endif  // defined(HOST_OS_MACOS)
diff --git a/runtime/bin/log_win.cc b/runtime/bin/log_win.cc
deleted file mode 100644
index 650e47e..0000000
--- a/runtime/bin/log_win.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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.
-
-#include "platform/globals.h"
-#if defined(HOST_OS_WINDOWS)
-
-#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(stderr);
-}
-
-}  // namespace bin
-}  // namespace dart
-
-#endif  // defined(HOST_OS_WINDOWS)
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 2d09c17..c9edf66 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -26,7 +26,6 @@
 #include "bin/gzip.h"
 #include "bin/isolate_data.h"
 #include "bin/loader.h"
-#include "bin/log.h"
 #include "bin/main_options.h"
 #include "bin/platform.h"
 #include "bin/process.h"
@@ -37,6 +36,7 @@
 #include "platform/globals.h"
 #include "platform/growable_array.h"
 #include "platform/hashmap.h"
+#include "platform/syslog.h"
 #include "platform/text_buffer.h"
 
 extern "C" {
@@ -46,15 +46,6 @@
 extern const uint8_t kDartCoreIsolateSnapshotInstructions[];
 }
 
-#if defined(DART_LINK_APP_SNAPSHOT)
-extern "C" {
-extern const uint8_t _kDartVmSnapshotData[];
-extern const uint8_t _kDartVmSnapshotInstructions[];
-extern const uint8_t _kDartIsolateSnapshotData[];
-extern const uint8_t _kDartIsolateSnapshotInstructions[];
-}
-#endif
-
 namespace dart {
 namespace bin {
 
@@ -186,7 +177,7 @@
 
 static void OnExitHook(int64_t exit_code) {
   if (Dart_CurrentIsolate() != main_isolate) {
-    Log::PrintErr(
+    Syslog::PrintErr(
         "A snapshot was requested, but a secondary isolate "
         "performed a hard exit (%" Pd64 ").\n",
         exit_code);
@@ -450,7 +441,7 @@
   }
 
   if (isolate == NULL) {
-    Log::PrintErr("%s\n", *error);
+    Syslog::PrintErr("%s\n", *error);
     delete isolate_data;
     return NULL;
   }
@@ -698,7 +689,7 @@
 
   Dart_Handle sticky_error = Dart_GetStickyError();
   if (!Dart_IsNull(sticky_error) && !Dart_IsFatalError(sticky_error)) {
-    Log::PrintErr("%s\n", Dart_GetError(sticky_error));
+    Syslog::PrintErr("%s\n", Dart_GetError(sticky_error));
   }
 
   IsolateData* isolate_data = reinterpret_cast<IsolateData*>(callback_data);
@@ -812,13 +803,13 @@
       &exit_code);
 
   if (isolate == NULL) {
-    Log::PrintErr("%s\n", error);
+    Syslog::PrintErr("%s\n", error);
     free(error);
     error = NULL;
     Process::TerminateExitCodeHandler();
     error = Dart_Cleanup();
     if (error != NULL) {
-      Log::PrintErr("VM cleanup failed: %s\n", error);
+      Syslog::PrintErr("VM cleanup failed: %s\n", error);
       free(error);
     }
     Process::ClearAllSignalHandlers();
@@ -838,7 +829,8 @@
       reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
   if (Options::gen_snapshot_kind() == kKernel) {
     if (vm_run_app_snapshot) {
-      Log::PrintErr("Cannot create a script snapshot from an app snapshot.\n");
+      Syslog::PrintErr(
+          "Cannot create a script snapshot from an app snapshot.\n");
       // The snapshot would contain references to the app snapshot instead of
       // the core snapshot.
       Platform::Exit(kErrorExitCode);
@@ -977,7 +969,7 @@
 
   // Perform platform specific initialization.
   if (!Platform::Initialize()) {
-    Log::PrintErr("Initialization failed\n");
+    Syslog::PrintErr("Initialization failed\n");
     Platform::Exit(kErrorExitCode);
   }
 
@@ -1018,7 +1010,7 @@
       // script was specified on the command line.
       char* error = Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
       if (error != NULL) {
-        Log::PrintErr("Setting VM flags failed: %s\n", error);
+        Syslog::PrintErr("Setting VM flags failed: %s\n", error);
         free(error);
         Platform::Exit(kErrorExitCode);
       }
@@ -1038,20 +1030,15 @@
 
   Loader::InitOnce();
 
-#if defined(DART_LINK_APP_SNAPSHOT)
-  vm_run_app_snapshot = true;
-  vm_snapshot_data = _kDartVmSnapshotData;
-  vm_snapshot_instructions = _kDartVmSnapshotInstructions;
-  app_isolate_snapshot_data = _kDartIsolateSnapshotData;
-  app_isolate_snapshot_instructions = _kDartIsolateSnapshotInstructions;
-#else
   AppSnapshot* shared_blobs = NULL;
   if (Options::shared_blobs_filename() != NULL) {
-    Log::PrintErr("Shared blobs in the standalone VM are for testing only.\n");
+    Syslog::PrintErr(
+        "Shared blobs in the standalone VM are for testing only.\n");
     shared_blobs =
         Snapshot::TryReadAppSnapshot(Options::shared_blobs_filename());
     if (shared_blobs == NULL) {
-      Log::PrintErr("Failed to load: %s\n", Options::shared_blobs_filename());
+      Syslog::PrintErr("Failed to load: %s\n",
+                       Options::shared_blobs_filename());
       Platform::Exit(kErrorExitCode);
     }
     const uint8_t* ignored;
@@ -1065,7 +1052,6 @@
                              &app_isolate_snapshot_data,
                              &app_isolate_snapshot_instructions);
   }
-#endif
 
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   // Constant true if PRODUCT or DART_PRECOMPILED_RUNTIME.
@@ -1076,9 +1062,6 @@
 
   if (Options::gen_snapshot_kind() == kAppJIT) {
     vm_options.AddArgument("--fields_may_be_reset");
-#if !defined(PRODUCT)
-    vm_options.AddArgument("--collect_code=false");
-#endif
   }
 #if defined(DART_PRECOMPILED_RUNTIME)
   vm_options.AddArgument("--precompilation");
@@ -1092,14 +1075,14 @@
 
   char* error = nullptr;
   if (!dart::embedder::InitOnce(&error)) {
-    Log::PrintErr("Stanalone embedder initialization failed: %s\n", error);
+    Syslog::PrintErr("Stanalone embedder initialization failed: %s\n", error);
     free(error);
     Platform::Exit(kErrorExitCode);
   }
 
   error = Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
   if (error != NULL) {
-    Log::PrintErr("Setting VM flags failed: %s\n", error);
+    Syslog::PrintErr("Setting VM flags failed: %s\n", error);
     free(error);
     Platform::Exit(kErrorExitCode);
   }
@@ -1145,7 +1128,7 @@
   error = Dart_Initialize(&init_params);
   if (error != NULL) {
     EventHandler::Stop();
-    Log::PrintErr("VM initialization failed: %s\n", error);
+    Syslog::PrintErr("VM initialization failed: %s\n", error);
     free(error);
     Platform::Exit(kErrorExitCode);
   }
@@ -1157,7 +1140,7 @@
 
   // Run the main isolate until we aren't told to restart.
   while (RunMainIsolate(script_name, &dart_options)) {
-    Log::PrintErr("Restarting VM\n");
+    Syslog::PrintErr("Restarting VM\n");
   }
 
   // Terminate process exit-code handler.
@@ -1165,16 +1148,14 @@
 
   error = Dart_Cleanup();
   if (error != NULL) {
-    Log::PrintErr("VM cleanup failed: %s\n", error);
+    Syslog::PrintErr("VM cleanup failed: %s\n", error);
     free(error);
   }
   Process::ClearAllSignalHandlers();
   EventHandler::Stop();
 
-#if !defined(DART_LINK_APP_SNAPSHOT)
   delete app_snapshot;
   delete shared_blobs;
-#endif
   free(app_script_uri);
 
   // Free copied argument strings if converted.
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 0826fa1..b356da5 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -9,9 +9,9 @@
 #include <string.h>
 
 #include "bin/abi_version.h"
-#include "bin/log.h"
 #include "bin/options.h"
 #include "bin/platform.h"
+#include "platform/syslog.h"
 #if !defined(DART_IO_SECURE_SOCKET_DISABLED)
 #include "bin/security_context.h"
 #endif  // !defined(DART_IO_SECURE_SOCKET_DISABLED)
@@ -114,19 +114,19 @@
                       hot_reload_rollback_test_mode_callback);
 
 void Options::PrintVersion() {
-  Log::PrintErr("Dart VM version: %s\n", Dart_VersionString());
+  Syslog::PrintErr("Dart VM version: %s\n", Dart_VersionString());
 }
 
 // clang-format off
 void Options::PrintUsage() {
-  Log::PrintErr(
+  Syslog::PrintErr(
       "Usage: dart [<vm-flags>] <dart-script-file> [<script-arguments>]\n"
       "\n"
       "Executes the Dart script <dart-script-file> with "
       "the given list of <script-arguments>.\n"
       "\n");
   if (!Options::verbose_option()) {
-    Log::PrintErr(
+    Syslog::PrintErr(
 "Common VM flags:\n"
 "--enable-asserts\n"
 "  Enable assert statements.\n"
@@ -157,7 +157,7 @@
 "--version\n"
 "  Print the VM version.\n");
   } else {
-    Log::PrintErr(
+    Syslog::PrintErr(
 "Supported options:\n"
 "--enable-asserts\n"
 "  Enable assert statements.\n"
@@ -294,7 +294,7 @@
   if (!ExtractPortAndAddress(
           value, &vm_service_server_port_, &vm_service_server_ip_,
           DEFAULT_VM_SERVICE_SERVER_PORT, DEFAULT_VM_SERVICE_SERVER_IP)) {
-    Log::PrintErr(
+    Syslog::PrintErr(
         "unrecognized --enable-vm-service option syntax. "
         "Use --enable-vm-service[=<port number>[/<bind address>]]\n");
     return false;
@@ -315,7 +315,7 @@
   if (!ExtractPortAndAddress(
           value, &vm_service_server_port_, &vm_service_server_ip_,
           DEFAULT_VM_SERVICE_SERVER_PORT, DEFAULT_VM_SERVICE_SERVER_IP)) {
-    Log::PrintErr(
+    Syslog::PrintErr(
         "unrecognized --observe option syntax. "
         "Use --observe[=<port number>[/<bind address>]]\n");
     return false;
@@ -344,14 +344,15 @@
     if (value[i] >= '0' && value[i] <= '9') {
       ver = (ver * 10) + value[i] - '0';
     } else {
-      Log::PrintErr("--use_abi_version must be an int\n");
+      Syslog::PrintErr("--use_abi_version must be an int\n");
       return false;
     }
   }
   if (ver < AbiVersion::GetOldestSupported() ||
       ver > AbiVersion::GetCurrent()) {
-    Log::PrintErr("--use_abi_version must be between %d and %d inclusive\n",
-                  AbiVersion::GetOldestSupported(), AbiVersion::GetCurrent());
+    Syslog::PrintErr("--use_abi_version must be between %d and %d inclusive\n",
+                     AbiVersion::GetOldestSupported(),
+                     AbiVersion::GetCurrent());
     return false;
   }
   target_abi_version_ = ver;
@@ -422,9 +423,6 @@
   // The arguments to the VM are at positions 1 through i-1 in argv.
   Platform::SetExecutableArguments(i, argv);
 
-#if defined(DART_LINK_APP_SNAPSHOT)
-  *script_name = argv[0];
-#else
   // Get the script name.
   if (i < argc) {
     *script_name = argv[i];
@@ -432,7 +430,6 @@
   } else {
     return -1;
   }
-#endif
 
   // Parse out options to be passed to dart main.
   while (i < argc) {
@@ -444,7 +441,7 @@
 
   // snapshot_depfile is an alias for depfile. Passing them both is an error.
   if ((snapshot_deps_filename_ != NULL) && (depfile_ != NULL)) {
-    Log::PrintErr("Specify only one of --depfile and --snapshot_depfile\n");
+    Syslog::PrintErr("Specify only one of --depfile and --snapshot_depfile\n");
     return -1;
   }
   if (snapshot_deps_filename_ != NULL) {
@@ -453,32 +450,34 @@
   }
 
   if ((Options::package_root() != NULL) && (packages_file_ != NULL)) {
-    Log::PrintErr(
+    Syslog::PrintErr(
         "Specifying both a packages directory and a packages "
         "file is invalid.\n");
     return -1;
   }
   if ((Options::package_root() != NULL) &&
       (strlen(Options::package_root()) == 0)) {
-    Log::PrintErr("Empty package root specified.\n");
+    Syslog::PrintErr("Empty package root specified.\n");
     return -1;
   }
   if ((packages_file_ != NULL) && (strlen(packages_file_) == 0)) {
-    Log::PrintErr("Empty package file name specified.\n");
+    Syslog::PrintErr("Empty package file name specified.\n");
     return -1;
   }
   if ((gen_snapshot_kind_ != kNone) && (snapshot_filename_ == NULL)) {
-    Log::PrintErr("Generating a snapshot requires a filename (--snapshot).\n");
+    Syslog::PrintErr(
+        "Generating a snapshot requires a filename (--snapshot).\n");
     return -1;
   }
   if ((gen_snapshot_kind_ == kNone) && (depfile_ != NULL) &&
       (snapshot_filename_ == NULL) && (depfile_output_filename_ == NULL)) {
-    Log::PrintErr("Generating a depfile requires an output filename"
-                  " (--depfile-output-filename or --snapshot).\n");
+    Syslog::PrintErr(
+        "Generating a depfile requires an output filename"
+        " (--depfile-output-filename or --snapshot).\n");
     return -1;
   }
   if ((gen_snapshot_kind_ != kNone) && vm_run_app_snapshot) {
-    Log::PrintErr(
+    Syslog::PrintErr(
         "Specifying an option to generate a snapshot and"
         " run using a snapshot is invalid.\n");
     return -1;
diff --git a/runtime/bin/namespace.h b/runtime/bin/namespace.h
index c85a29b..cc9e57a 100644
--- a/runtime/bin/namespace.h
+++ b/runtime/bin/namespace.h
@@ -7,8 +7,8 @@
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
-#include "bin/log.h"
 #include "bin/reference_counting.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
diff --git a/runtime/bin/namespace_fuchsia.cc b/runtime/bin/namespace_fuchsia.cc
index 843e8b2..6e93bcb 100644
--- a/runtime/bin/namespace_fuchsia.cc
+++ b/runtime/bin/namespace_fuchsia.cc
@@ -22,20 +22,32 @@
 
 NamespaceImpl::NamespaceImpl(fdio_ns_t* fdio_ns)
       : fdio_ns_(fdio_ns),
-        rootfd_(fdio_ns_opendir(fdio_ns)),
         cwd_(strdup("/")) {
-  ASSERT(rootfd_ > 0);
+  rootfd_ = fdio_ns_opendir(fdio_ns);
+  if (rootfd_ < 0) {
+    FATAL2("Failed to open file descriptor for namespace: errno=%d: %s", errno,
+           strerror(errno));
+  }
   cwdfd_ = dup(rootfd_);
-  ASSERT(cwdfd_ > 0);
+  if (cwdfd_ < 0) {
+    FATAL2("Failed to dup() namespace file descriptor: errno=%d: %s", errno,
+           strerror(errno));
+  }
 }
 
 NamespaceImpl::NamespaceImpl(const char* path)
       : fdio_ns_(NULL),
-        rootfd_(TEMP_FAILURE_RETRY(open(path, O_DIRECTORY))),
         cwd_(strdup("/")) {
-  ASSERT(rootfd_ > 0);
+  rootfd_ = TEMP_FAILURE_RETRY(open(path, O_DIRECTORY));
+  if (rootfd_ < 0) {
+    FATAL2("Failed to open file descriptor for namespace: errno=%d: %s", errno,
+           strerror(errno));
+  }
   cwdfd_ = dup(rootfd_);
-  ASSERT(cwdfd_ > 0);
+  if (cwdfd_ < 0) {
+    FATAL2("Failed to dup() namespace file descriptor: errno=%d: %s", errno,
+           strerror(errno));
+  }
 }
 
 NamespaceImpl::~NamespaceImpl() {
@@ -45,7 +57,7 @@
   if (fdio_ns_ != NULL) {
     zx_status_t status = fdio_ns_destroy(fdio_ns_);
     if (status != ZX_OK) {
-      Log::PrintErr("fdio_ns_destroy: %s\n", zx_status_get_string(status));
+      Syslog::PrintErr("fdio_ns_destroy: %s\n", zx_status_get_string(status));
     }
   }
 }
@@ -54,7 +66,7 @@
   NamespaceScope ns(namespc, new_path);
   const intptr_t new_cwdfd =
       TEMP_FAILURE_RETRY(openat(ns.fd(), ns.path(), O_DIRECTORY));
-  if (new_cwdfd != 0) {
+  if (new_cwdfd < 0) {
     return false;
   }
 
diff --git a/runtime/bin/options.cc b/runtime/bin/options.cc
index f9652c6..573bd63 100644
--- a/runtime/bin/options.cc
+++ b/runtime/bin/options.cc
@@ -69,12 +69,12 @@
   const char* equals_pos = strchr(arg, '=');
   if (equals_pos == NULL) {
     // No equal sign (name without value) currently not supported.
-    Log::PrintErr("No value given to -D option\n");
+    Syslog::PrintErr("No value given to -D option\n");
     return true;
   }
   int name_len = equals_pos - arg;
   if (name_len == 0) {
-    Log::PrintErr("No name given to -D option\n");
+    Syslog::PrintErr("No name given to -D option\n");
     return true;
   }
   // Split name=value into name and value.
diff --git a/runtime/bin/options.h b/runtime/bin/options.h
index 336d934..4bcd7de 100644
--- a/runtime/bin/options.h
+++ b/runtime/bin/options.h
@@ -6,9 +6,9 @@
 #define RUNTIME_BIN_OPTIONS_H_
 
 #include "bin/dartutils.h"
-#include "bin/log.h"
 #include "platform/globals.h"
 #include "platform/hashmap.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
@@ -68,7 +68,7 @@
         return false;                                                          \
       }                                                                        \
       if (*value == '\0') {                                                    \
-        Log::PrintErr("Empty value for option " #name "\n");                   \
+        Syslog::PrintErr("Empty value for option " #name "\n");                \
         return false;                                                          \
       }                                                                        \
       callback;                                                                \
@@ -89,12 +89,12 @@
         return true;                                                           \
       }                                                                        \
     }                                                                          \
-    Log::PrintErr(                                                             \
+    Syslog::PrintErr(                                                          \
         "Unrecognized value for " #name ": '%s'\nValid values are: ", value);  \
     for (intptr_t i = 0; kNames[i] != NULL; i++) {                             \
-      Log::PrintErr("%s%s", i > 0 ? ", " : "", kNames[i]);                     \
+      Syslog::PrintErr("%s%s", i > 0 ? ", " : "", kNames[i]);                  \
     }                                                                          \
-    Log::PrintErr("\n");                                                       \
+    Syslog::PrintErr("\n");                                                    \
   })
 
 #define DEFINE_BOOL_OPTION_CB(name, callback)                                  \
@@ -106,7 +106,7 @@
         return false;                                                          \
       }                                                                        \
       if (*value == '=') {                                                     \
-        Log::PrintErr("Non-empty value for option " #name "\n");               \
+        Syslog::PrintErr("Non-empty value for option " #name "\n");            \
         return false;                                                          \
       }                                                                        \
       if (*value != '\0') {                                                    \
@@ -127,7 +127,7 @@
         return false;                                                          \
       }                                                                        \
       if (*value == '=') {                                                     \
-        Log::PrintErr("Non-empty value for option " #name "\n");               \
+        Syslog::PrintErr("Non-empty value for option " #name "\n");            \
         return false;                                                          \
       }                                                                        \
       if (*value != '\0') {                                                    \
@@ -152,7 +152,7 @@
         return false;                                                          \
       }                                                                        \
       if (*value == '=') {                                                     \
-        Log::PrintErr("Non-empty value for option " #long_name "\n");          \
+        Syslog::PrintErr("Non-empty value for option " #long_name "\n");       \
         return false;                                                          \
       }                                                                        \
       if (*value != '\0') {                                                    \
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index 37240b9..db61adf 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -11,6 +11,7 @@
 #include <signal.h>       // NOLINT
 #include <string.h>       // NOLINT
 #include <sys/resource.h>
+#include <sys/system_properties.h>
 #include <sys/utsname.h>  // NOLINT
 #include <unistd.h>       // NOLINT
 
@@ -26,7 +27,7 @@
 char** Platform::argv_ = NULL;
 
 static void segv_handler(int signal, siginfo_t* siginfo, void* context) {
-  Log::PrintErr(
+  Syslog::PrintErr(
       "\n===== CRASH =====\n"
       "si_signo=%s(%d), si_code=%d, si_addr=%p\n",
       strsignal(siginfo->si_signo), siginfo->si_signo, siginfo->si_code,
@@ -96,24 +97,16 @@
 }
 
 const char* Platform::OperatingSystemVersion() {
-  struct utsname info;
-  int ret = uname(&info);
-  if (ret != 0) {
+  char os_version[PROP_VALUE_MAX + 1];
+  int os_version_length =
+      __system_property_get("ro.build.display.id", os_version);
+  if (os_version_length == 0) {
     return NULL;
   }
-  const char* kFormat = "%s %s %s";
-  int len =
-      snprintf(NULL, 0, kFormat, info.sysname, info.release, info.version);
-  if (len <= 0) {
-    return NULL;
-  }
-  char* result = DartUtils::ScopedCString(len + 1);
-  ASSERT(result != NULL);
-  len = snprintf(result, len + 1, kFormat, info.sysname, info.release,
-                 info.version);
-  if (len <= 0) {
-    return NULL;
-  }
+  ASSERT(os_version_length <= PROP_VALUE_MAX);
+  char* result = reinterpret_cast<char*>(
+      Dart_ScopeAllocate((os_version_length + 1) * sizeof(result)));
+  strncpy(result, os_version, (os_version_length + 1));
   return result;
 }
 
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index 6bc50aa..1d259ac 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -26,7 +26,7 @@
 char** Platform::argv_ = NULL;
 
 static void segv_handler(int signal, siginfo_t* siginfo, void* context) {
-  Log::PrintErr(
+  Syslog::PrintErr(
       "\n===== CRASH =====\n"
       "si_signo=%s(%d), si_code=%d, si_addr=%p\n",
       strsignal(siginfo->si_signo), siginfo->si_signo, siginfo->si_code,
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index ef3c90f..1a6688c 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -34,7 +34,7 @@
 char** Platform::argv_ = NULL;
 
 static void segv_handler(int signal, siginfo_t* siginfo, void* context) {
-  Log::PrintErr(
+  Syslog::PrintErr(
       "\n===== CRASH =====\n"
       "si_signo=%s(%d), si_code=%d, si_addr=%p\n",
       strsignal(siginfo->si_signo), siginfo->si_signo, siginfo->si_code,
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 9b2face..2b4eacc 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -12,7 +12,7 @@
 #include "bin/console.h"
 #include "bin/file.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
+#include "platform/syslog.h"
 #if !defined(PLATFORM_DISABLE_SOCKET)
 #include "bin/socket.h"
 #endif
@@ -73,7 +73,7 @@
          EXCEPTION_ACCESS_VIOLATION) ||
         (ExceptionInfo->ExceptionRecord->ExceptionCode ==
          EXCEPTION_ILLEGAL_INSTRUCTION)) {
-      Log::PrintErr(
+      Syslog::PrintErr(
           "\n===== CRASH =====\n"
           "ExceptionCode=%d, ExceptionFlags=%d, ExceptionAddress=%p\n",
           ExceptionInfo->ExceptionRecord->ExceptionCode,
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index ee3e4e31..b36364a 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -6,11 +6,11 @@
 
 #include "bin/dartutils.h"
 #include "bin/io_buffer.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "bin/platform.h"
 #include "bin/socket.h"
 #include "bin/utils.h"
+#include "platform/syslog.h"
 
 #include "include/dart_api.h"
 
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 5995e8a..bbb0afa 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -21,10 +21,10 @@
 #include "bin/fdutils.h"
 #include "bin/file.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "bin/reference_counting.h"
 #include "bin/thread.h"
+#include "platform/syslog.h"
 
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
index 3680f23..087d875 100644
--- a/runtime/bin/process_fuchsia.cc
+++ b/runtime/bin/process_fuchsia.cc
@@ -31,16 +31,16 @@
 #include "bin/fdutils.h"
 #include "bin/file.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "bin/namespace_fuchsia.h"
 #include "platform/signal_blocker.h"
+#include "platform/syslog.h"
 #include "platform/utils.h"
 
 // #define PROCESS_LOGGING 1
 #if defined(PROCESS_LOGGING)
-#define LOG_ERR(msg, ...) Log::PrintErr("Dart Process: " msg, ##__VA_ARGS__)
-#define LOG_INFO(msg, ...) Log::Print("Dart Process: " msg, ##__VA_ARGS__)
+#define LOG_ERR(msg, ...) Syslog::PrintErr("Dart Process: " msg, ##__VA_ARGS__)
+#define LOG_INFO(msg, ...) Syslog::Print("Dart Process: " msg, ##__VA_ARGS__)
 #else
 #define LOG_ERR(msg, ...)
 #define LOG_INFO(msg, ...)
@@ -207,8 +207,8 @@
     pkt.key = kShutdownPacketKey;
     zx_status_t status = zx_port_queue(port_, &pkt);
     if (status != ZX_OK) {
-      Log::PrintErr("ExitCodeHandler: zx_port_queue failed: %s\n",
-                    zx_status_get_string(status));
+      Syslog::PrintErr("ExitCodeHandler: zx_port_queue failed: %s\n",
+                       zx_status_get_string(status));
     }
   }
 
@@ -249,8 +249,8 @@
     zx_status_t status = zx_object_get_info(
         process, ZX_INFO_PROCESS, &proc_info, sizeof(proc_info), NULL, NULL);
     if (status != ZX_OK) {
-      Log::PrintErr("ExitCodeHandler: zx_object_get_info failed: %s\n",
-                    zx_status_get_string(status));
+      Syslog::PrintErr("ExitCodeHandler: zx_object_get_info failed: %s\n",
+                       zx_status_get_string(status));
     } else {
       return_code = proc_info.return_code;
     }
@@ -270,8 +270,8 @@
       ASSERT((result == -1) || (result == sizeof(exit_code_fd)));
       if ((result == -1) && (errno != EPIPE)) {
         int err = errno;
-        Log::PrintErr("Failed to write exit code for process %d: errno=%d\n",
-                      process, err);
+        Syslog::PrintErr("Failed to write exit code for process %d: errno=%d\n",
+                         process, err);
       }
       LOG_INFO("ExitCodeHandler thread wrote %ld bytes to fd %ld\n", result,
                exit_code_fd);
@@ -365,8 +365,8 @@
   zx_handle_t port;
   zx_status_t status = zx_port_create(0, &port);
   if (status != ZX_OK) {
-    Log::PrintErr("Process::Wait: zx_port_create failed: %s\n",
-                  zx_status_get_string(status));
+    Syslog::PrintErr("Process::Wait: zx_port_create failed: %s\n",
+                     zx_status_get_string(status));
     return false;
   }
 
@@ -390,8 +390,8 @@
     zx_port_packet_t pkt;
     status = zx_port_wait(port, ZX_TIME_INFINITE, &pkt);
     if (status != ZX_OK) {
-      Log::PrintErr("Process::Wait: zx_port_wait failed: %s\n",
-                    zx_status_get_string(status));
+      Syslog::PrintErr("Process::Wait: zx_port_wait failed: %s\n",
+                       zx_status_get_string(status));
       return false;
     }
     IOHandle* event_handle = reinterpret_cast<IOHandle*>(pkt.key);
@@ -434,7 +434,8 @@
         exit_tmp = NULL;
       }
     } else {
-      Log::PrintErr("Process::Wait: Unexpected wait key: %p\n", event_handle);
+      Syslog::PrintErr("Process::Wait: Unexpected wait key: %p\n",
+                       event_handle);
     }
     if (out_tmp != NULL) {
       if (!out_tmp->AsyncWait(port, events, out_key)) {
@@ -618,7 +619,7 @@
     LOG_INFO("ProcessStarter: Start() Calling fdio_spawn_vmo\n");
     zx_handle_t process = ZX_HANDLE_INVALID;
     char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
-    uint32_t flags = FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC;
+    uint32_t flags = FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_DEFAULT_LDSVC;
     status = fdio_spawn_vmo(ZX_HANDLE_INVALID, flags, vmo, program_arguments_,
                             program_environment_, actions_count, actions,
                             &process, err_msg);
@@ -677,7 +678,7 @@
 
   zx_status_t AddPipe(int target_fd, int* local_fd,
                       fdio_spawn_action_t* action) {
-    zx_status_t status = fdio_pipe_half2(local_fd, &action->h.handle);
+    zx_status_t status = fdio_pipe_half(local_fd, &action->h.handle);
     if (status != ZX_OK) return status;
     action->action = FDIO_SPAWN_ACTION_ADD_HANDLE;
     action->h.id = PA_HND(PA_HND_TYPE(PA_FD), target_fd);
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index d3df465..afc9667 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -22,9 +22,9 @@
 #include "bin/fdutils.h"
 #include "bin/file.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/reference_counting.h"
 #include "bin/thread.h"
+#include "platform/syslog.h"
 
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index d78db22..4463855 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -23,9 +23,9 @@
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/namespace.h"
 #include "bin/thread.h"
+#include "platform/syslog.h"
 
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 2a1ed8e..4c3c1de 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -14,11 +14,11 @@
 #include "bin/dartutils.h"
 #include "bin/eventhandler.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/socket.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
@@ -229,7 +229,7 @@
                          NULL);
 
     if (handles[kWriteHandle] == INVALID_HANDLE_VALUE) {
-      Log::PrintErr("CreateNamedPipe failed %d\n", GetLastError());
+      Syslog::PrintErr("CreateNamedPipe failed %d\n", GetLastError());
       return false;
     }
 
@@ -237,7 +237,7 @@
         CreateFileW(pipe_name, GENERIC_READ, 0, &inherit_handle, OPEN_EXISTING,
                     FILE_READ_ATTRIBUTES | FILE_FLAG_OVERLAPPED, NULL);
     if (handles[kReadHandle] == INVALID_HANDLE_VALUE) {
-      Log::PrintErr("CreateFile failed %d\n", GetLastError());
+      Syslog::PrintErr("CreateFile failed %d\n", GetLastError());
       return false;
     }
   } else {
@@ -252,7 +252,7 @@
                          NULL);
 
     if (handles[kReadHandle] == INVALID_HANDLE_VALUE) {
-      Log::PrintErr("CreateNamedPipe failed %d\n", GetLastError());
+      Syslog::PrintErr("CreateNamedPipe failed %d\n", GetLastError());
       return false;
     }
 
@@ -261,7 +261,7 @@
         (type == kInheritWrite) ? &inherit_handle : NULL, OPEN_EXISTING,
         FILE_WRITE_ATTRIBUTES | FILE_FLAG_OVERLAPPED, NULL);
     if (handles[kWriteHandle] == INVALID_HANDLE_VALUE) {
-      Log::PrintErr("CreateFile failed %d\n", GetLastError());
+      Syslog::PrintErr("CreateFile failed %d\n", GetLastError());
       return false;
     }
   }
@@ -272,7 +272,7 @@
   for (int i = kReadHandle; i < kWriteHandle; i++) {
     if (handles[i] != INVALID_HANDLE_VALUE) {
       if (!CloseHandle(handles[i])) {
-        Log::PrintErr("CloseHandle failed %d\n", GetLastError());
+        Syslog::PrintErr("CloseHandle failed %d\n", GetLastError());
       }
       handles[i] = INVALID_HANDLE_VALUE;
     }
@@ -307,7 +307,7 @@
   HANDLE nul = CreateFile(L"NUL", GENERIC_READ | GENERIC_WRITE, 0,
                           &inherit_handle, OPEN_EXISTING, 0, NULL);
   if (nul == INVALID_HANDLE_VALUE) {
-    Log::PrintErr("CloseHandle failed %d\n", GetLastError());
+    Syslog::PrintErr("CloseHandle failed %d\n", GetLastError());
   }
   return nul;
 }
@@ -560,7 +560,7 @@
         reinterpret_cast<STARTUPINFOW*>(&startup_info), &process_info);
 
     if (result == 0) {
-      Log::PrintErr("CreateProcessW failed %d\n", GetLastError());
+      Syslog::PrintErr("CreateProcessW failed %d\n", GetLastError());
       return CleanupAndReturnError();
     }
 
@@ -605,7 +605,7 @@
     int status = GenerateNames<4>(pipe_names);
     if (status != 0) {
       SetOsErrorMessage(os_error_message_);
-      Log::PrintErr("UuidCreateSequential failed %d\n", status);
+      Syslog::PrintErr("UuidCreateSequential failed %d\n", status);
       return status;
     }
 
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index aa36a87..70022e8 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -53,15 +53,15 @@
 static int run_matches = 0;
 
 void TestCase::Run() {
-  bin::Log::Print("Running test: %s\n", name());
+  Syslog::Print("Running test: %s\n", name());
   (*run_)();
-  bin::Log::Print("Done: %s\n", name());
+  Syslog::Print("Done: %s\n", name());
 }
 
 void RawTestCase::Run() {
-  bin::Log::Print("Running raw test: %s\n", name());
+  Syslog::Print("Running raw test: %s\n", name());
   (*run_)();
-  bin::Log::Print("Done: %s\n", name());
+  Syslog::Print("Done: %s\n", name());
 }
 
 void TestCaseBase::RunTest() {
@@ -69,7 +69,7 @@
     this->Run();
     run_matches++;
   } else if (run_filter == kList) {
-    bin::Log::Print("%s\n", this->name());
+    Syslog::Print("%s %s\n", this->name(), this->expectation());
     run_matches++;
   }
 }
@@ -78,17 +78,17 @@
   if ((run_filter == kAllBenchmarks) ||
       (strcmp(run_filter, this->name()) == 0)) {
     this->Run();
-    bin::Log::Print("%s(%s): %" Pd64 "\n", this->name(), this->score_kind(),
-                    this->score());
+    Syslog::Print("%s(%s): %" Pd64 "\n", this->name(), this->score_kind(),
+                  this->score());
     run_matches++;
   } else if (run_filter == kList) {
-    bin::Log::Print("%s\n", this->name());
+    Syslog::Print("%s Pass\n", this->name());
     run_matches++;
   }
 }
 
 static void PrintUsage() {
-  bin::Log::PrintErr(
+  Syslog::PrintErr(
       "Usage: one of the following\n"
       "  run_vm_tests --list\n"
       "  run_vm_tests [--dfe=<snapshot file name>] --benchmarks\n"
@@ -235,7 +235,7 @@
 
   // Perform platform specific initialization.
   if (!dart::bin::Platform::Initialize()) {
-    bin::Log::PrintErr("Initialization failed\n");
+    Syslog::PrintErr("Initialization failed\n");
     return 1;
   }
 
@@ -278,7 +278,7 @@
   if (strncmp(argv[arg_pos], "--dfe", strlen("--dfe")) == 0) {
     const char* delim = strstr(argv[arg_pos], "=");
     if (delim == NULL || strlen(delim + 1) == 0) {
-      bin::Log::PrintErr("Invalid value for the option: %s\n", argv[arg_pos]);
+      Syslog::PrintErr("Invalid value for the option: %s\n", argv[arg_pos]);
       PrintUsage();
       return 1;
     }
@@ -304,7 +304,7 @@
 
   char* error = Flags::ProcessCommandLineFlags(dart_argc, dart_argv);
   if (error != NULL) {
-    bin::Log::PrintErr("Failed to parse flags: %s\n", error);
+    Syslog::PrintErr("Failed to parse flags: %s\n", error);
     free(error);
     return 1;
   }
@@ -324,7 +324,7 @@
       nullptr /* entropy_source */, nullptr /* get_service_assets */,
       start_kernel_isolate);
   if (error != nullptr) {
-    bin::Log::PrintErr("Failed to initialize VM: %s\n", error);
+    Syslog::PrintErr("Failed to initialize VM: %s\n", error);
     free(error);
     return 1;
   }
@@ -336,7 +336,7 @@
 
   error = Dart::Cleanup();
   if (error != nullptr) {
-    bin::Log::PrintErr("Failed shutdown VM: %s\n", error);
+    Syslog::PrintErr("Failed shutdown VM: %s\n", error);
     free(error);
     return 1;
   }
@@ -347,7 +347,7 @@
 
   // Print a warning message if no tests or benchmarks were matched.
   if (run_matches == 0) {
-    bin::Log::PrintErr("No tests matched: %s\n", run_filter);
+    Syslog::PrintErr("No tests matched: %s\n", run_filter);
     return 1;
   }
   if (Expect::failed()) {
diff --git a/runtime/bin/secure_socket_filter.cc b/runtime/bin/secure_socket_filter.cc
index c6ac6bb..63305bc 100644
--- a/runtime/bin/secure_socket_filter.cc
+++ b/runtime/bin/secure_socket_filter.cc
@@ -11,9 +11,9 @@
 #include <openssl/x509.h>
 
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/secure_socket_utils.h"
 #include "bin/security_context.h"
+#include "platform/syslog.h"
 #include "platform/text_buffer.h"
 
 // Return the error from the containing function if handle is an error handle.
@@ -492,25 +492,25 @@
   if (is_server_) {
     status = SSL_accept(ssl_);
     if (SSL_LOG_STATUS) {
-      Log::Print("SSL_accept status: %d\n", status);
+      Syslog::Print("SSL_accept status: %d\n", status);
     }
     if (status != 1) {
       // TODO(whesse): expect a needs-data error here.  Handle other errors.
       error = SSL_get_error(ssl_, status);
       if (SSL_LOG_STATUS) {
-        Log::Print("SSL_accept error: %d\n", error);
+        Syslog::Print("SSL_accept error: %d\n", error);
       }
     }
   } else {
     status = SSL_connect(ssl_);
     if (SSL_LOG_STATUS) {
-      Log::Print("SSL_connect status: %d\n", status);
+      Syslog::Print("SSL_connect status: %d\n", status);
     }
     if (status != 1) {
       // TODO(whesse): expect a needs-data error here.  Handle other errors.
       error = SSL_get_error(ssl_, status);
       if (SSL_LOG_STATUS) {
-        Log::Print("SSL_connect error: %d\n", error);
+        Syslog::Print("SSL_connect error: %d\n", error);
       }
     }
   }
@@ -542,10 +542,10 @@
     //    should give us the hostname check.
     int result = SSL_get_verify_result(ssl_);
     if (SSL_LOG_STATUS) {
-      Log::Print("Handshake verification status: %d\n", result);
+      Syslog::Print("Handshake verification status: %d\n", result);
       X509* peer_certificate = SSL_get_peer_certificate(ssl_);
       if (peer_certificate == NULL) {
-        Log::Print("No peer certificate received\n");
+        Syslog::Print("No peer certificate received\n");
       } else {
         X509_NAME* s_name = X509_get_subject_name(peer_certificate);
         printf("Peer certificate SN: ");
@@ -655,7 +655,7 @@
       SSL_write(ssl_, buffers_[kWritePlaintext] + start, length);
   if (bytes_processed < 0) {
     if (SSL_LOG_DATA) {
-      Log::Print("SSL_write returned error %d\n", bytes_processed);
+      Syslog::Print("SSL_write returned error %d\n", bytes_processed);
     }
     return 0;
   }
@@ -666,7 +666,8 @@
 int SSLFilter::ProcessReadEncryptedBuffer(int start, int end) {
   int length = end - start;
   if (SSL_LOG_DATA)
-    Log::Print("Entering ProcessReadEncryptedBuffer with %d bytes\n", length);
+    Syslog::Print("Entering ProcessReadEncryptedBuffer with %d bytes\n",
+                  length);
   int bytes_processed = 0;
   if (length > 0) {
     bytes_processed =
@@ -675,14 +676,14 @@
       bool retry = BIO_should_retry(socket_side_);
       if (!retry) {
         if (SSL_LOG_DATA)
-          Log::Print("BIO_write failed in ReadEncryptedBuffer\n");
+          Syslog::Print("BIO_write failed in ReadEncryptedBuffer\n");
       }
       bytes_processed = 0;
     }
   }
   if (SSL_LOG_DATA)
-    Log::Print("Leaving ProcessReadEncryptedBuffer wrote %d bytes\n",
-               bytes_processed);
+    Syslog::Print("Leaving ProcessReadEncryptedBuffer wrote %d bytes\n",
+                  bytes_processed);
   return bytes_processed;
 }
 
@@ -694,13 +695,13 @@
         BIO_read(socket_side_, buffers_[kWriteEncrypted] + start, length);
     if (bytes_processed < 0) {
       if (SSL_LOG_DATA)
-        Log::Print("WriteEncrypted BIO_read returned error %d\n",
-                   bytes_processed);
+        Syslog::Print("WriteEncrypted BIO_read returned error %d\n",
+                      bytes_processed);
       return 0;
     } else {
       if (SSL_LOG_DATA)
-        Log::Print("WriteEncrypted  BIO_read wrote %d bytes\n",
-                   bytes_processed);
+        Syslog::Print("WriteEncrypted  BIO_read wrote %d bytes\n",
+                      bytes_processed);
     }
   }
   return bytes_processed;
diff --git a/runtime/bin/secure_socket_utils.cc b/runtime/bin/secure_socket_utils.cc
index 078d764..362e891 100644
--- a/runtime/bin/secure_socket_utils.cc
+++ b/runtime/bin/secure_socket_utils.cc
@@ -12,9 +12,9 @@
 #include "platform/globals.h"
 
 #include "bin/file.h"
-#include "bin/log.h"
 #include "bin/secure_socket_filter.h"
 #include "bin/security_context.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
@@ -75,10 +75,10 @@
   }
   if (SSL_LOG_STATUS) {
     int error = ERR_get_error();
-    Log::PrintErr("Failed: %s status %d", message, status);
+    Syslog::PrintErr("Failed: %s status %d", message, status);
     char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE];
     ERR_error_string_n(error, error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE);
-    Log::PrintErr("ERROR: %d %s\n", error, error_string);
+    Syslog::PrintErr("ERROR: %d %s\n", error, error_string);
   }
   SecureSocketUtils::ThrowIOException(status, type, message, ssl);
 }
diff --git a/runtime/bin/security_context.cc b/runtime/bin/security_context.cc
index dd92a40..ffcda3db 100644
--- a/runtime/bin/security_context.cc
+++ b/runtime/bin/security_context.cc
@@ -16,9 +16,9 @@
 
 #include "bin/directory.h"
 #include "bin/file.h"
-#include "bin/log.h"
 #include "bin/secure_socket_filter.h"
 #include "bin/secure_socket_utils.h"
+#include "platform/syslog.h"
 
 // Return the error from the containing function if handle is an error handle.
 #define RETURN_IF_ERROR(handle)                                                \
@@ -324,7 +324,7 @@
 
 void SSLCertContext::LoadRootCertFile(const char* file) {
   if (SSL_LOG_STATUS) {
-    Log::Print("Looking for trusted roots in %s\n", file);
+    Syslog::Print("Looking for trusted roots in %s\n", file);
   }
   if (!File::Exists(NULL, file)) {
     SecureSocketUtils::ThrowIOException(-1, "TlsException",
@@ -334,14 +334,14 @@
   SecureSocketUtils::CheckStatus(status, "TlsException",
                                  "Failure trusting builtin roots");
   if (SSL_LOG_STATUS) {
-    Log::Print("Trusting roots from: %s\n", file);
+    Syslog::Print("Trusting roots from: %s\n", file);
   }
 }
 
 void SSLCertContext::AddCompiledInCerts() {
   if (root_certificates_pem == NULL) {
     if (SSL_LOG_STATUS) {
-      Log::Print("Missing compiled-in roots\n");
+      Syslog::Print("Missing compiled-in roots\n");
     }
     return;
   }
@@ -370,7 +370,7 @@
 
 void SSLCertContext::LoadRootCertCache(const char* cache) {
   if (SSL_LOG_STATUS) {
-    Log::Print("Looking for trusted roots in %s\n", cache);
+    Syslog::Print("Looking for trusted roots in %s\n", cache);
   }
   if (Directory::Exists(NULL, cache) != Directory::EXISTS) {
     SecureSocketUtils::ThrowIOException(-1, "TlsException",
@@ -380,7 +380,7 @@
   SecureSocketUtils::CheckStatus(status, "TlsException",
                                  "Failure trusting builtin roots");
   if (SSL_LOG_STATUS) {
-    Log::Print("Trusting roots from: %s\n", cache);
+    Syslog::Print("Trusting roots from: %s\n", cache);
   }
 }
 
@@ -778,7 +778,7 @@
   M_ASN1_UTCTIME_free(epoch_start);
   if (result != 1) {
     // TODO(whesse): Propagate an error to Dart.
-    Log::PrintErr("ASN1Time error %d\n", result);
+    Syslog::PrintErr("ASN1Time error %d\n", result);
   }
   return Dart_NewInteger((86400LL * days + seconds) * 1000LL);
 }
diff --git a/runtime/bin/security_context_android.cc b/runtime/bin/security_context_android.cc
index 852d174..d474999 100644
--- a/runtime/bin/security_context_android.cc
+++ b/runtime/bin/security_context_android.cc
@@ -15,9 +15,9 @@
 
 #include "bin/directory.h"
 #include "bin/file.h"
-#include "bin/log.h"
 #include "bin/secure_socket_filter.h"
 #include "bin/secure_socket_utils.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
diff --git a/runtime/bin/security_context_fuchsia.cc b/runtime/bin/security_context_fuchsia.cc
index e83c86d..f66500e 100644
--- a/runtime/bin/security_context_fuchsia.cc
+++ b/runtime/bin/security_context_fuchsia.cc
@@ -15,9 +15,9 @@
 
 #include "bin/directory.h"
 #include "bin/file.h"
-#include "bin/log.h"
 #include "bin/secure_socket_filter.h"
 #include "bin/secure_socket_utils.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
diff --git a/runtime/bin/security_context_linux.cc b/runtime/bin/security_context_linux.cc
index b4babfb..8ca9049 100644
--- a/runtime/bin/security_context_linux.cc
+++ b/runtime/bin/security_context_linux.cc
@@ -15,9 +15,9 @@
 
 #include "bin/directory.h"
 #include "bin/file.h"
-#include "bin/log.h"
 #include "bin/secure_socket_filter.h"
 #include "bin/secure_socket_utils.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
@@ -60,7 +60,7 @@
   // Fall back on the compiled-in certs if the standard locations don't exist,
   // or we aren't on Linux.
   if (SSL_LOG_STATUS) {
-    Log::Print("Trusting compiled-in roots\n");
+    Syslog::Print("Trusting compiled-in roots\n");
   }
   AddCompiledInCerts();
 }
diff --git a/runtime/bin/security_context_macos.cc b/runtime/bin/security_context_macos.cc
index 2964d67..024f1ad 100644
--- a/runtime/bin/security_context_macos.cc
+++ b/runtime/bin/security_context_macos.cc
@@ -38,8 +38,18 @@
   T* ptr() { return &obj_; }
   const T get() const { return obj_; }
 
+  DART_WARN_UNUSED_RESULT T release() {
+    T temp = obj_;
+    obj_ = NULL;
+    return temp;
+  }
+
   void set(T obj) { obj_ = obj; }
 
+  bool operator==(T other) { return other == get(); }
+
+  bool operator!=(T other) { return other != get(); }
+
  private:
   T obj_;
 
@@ -47,6 +57,20 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedCFType);
 };
 
+static void releaseObjects(const void* val, void* context) {
+  CFRelease(val);
+}
+
+template <>
+ScopedCFType<CFMutableArrayRef>::~ScopedCFType() {
+  if (obj_ != NULL) {
+    CFIndex count = 0;
+    CFArrayApplyFunction(obj_, CFRangeMake(0, CFArrayGetCount(obj_)),
+                         releaseObjects, &count);
+    CFRelease(obj_);
+  }
+}
+
 typedef ScopedCFType<CFMutableArrayRef> ScopedCFMutableArrayRef;
 typedef ScopedCFType<CFDataRef> ScopedCFDataRef;
 typedef ScopedCFType<CFStringRef> ScopedCFStringRef;
@@ -60,8 +84,10 @@
   }
   int length = i2d_X509(cert, NULL);
   if (length < 0) {
-    return 0;
+    return NULL;
   }
+  // This can be `std::make_unique<unsigned char[]>(length)` in C++14
+  // But the Mac toolchain is still using C++11.
   auto deb_cert = std::unique_ptr<unsigned char[]>(new unsigned char[length]);
   unsigned char* temp = deb_cert.get();
   if (i2d_X509(cert, &temp) != length) {
@@ -72,12 +98,7 @@
   // Implementation here:
   // https://opensource.apple.com/source/libsecurity_keychain/libsecurity_keychain-55050.2/lib/SecCertificate.cpp.auto.html
   ScopedCFDataRef cert_buf(CFDataCreate(NULL, deb_cert.get(), length));
-  SecCertificateRef auth_cert =
-      SecCertificateCreateWithData(NULL, cert_buf.get());
-  if (auth_cert == NULL) {
-    return NULL;
-  }
-  return auth_cert;
+  return SecCertificateCreateWithData(NULL, cert_buf.get());
 }
 
 static int CertificateVerificationCallback(X509_STORE_CTX* ctx, void* arg) {
@@ -93,11 +114,11 @@
     cert_chain.set(CFArrayCreateMutable(NULL, num_certs, NULL));
     X509* ca;
     while ((ca = sk_X509_shift(user_provided_certs)) != NULL) {
-      SecCertificateRef cert = CreateSecCertificateFromX509(ca);
+      ScopedSecCertificateRef cert(CreateSecCertificateFromX509(ca));
       if (cert == NULL) {
         return ctx->verify_cb(0, ctx);
       }
-      CFArrayAppendValue(cert_chain.get(), cert);
+      CFArrayAppendValue(cert_chain.get(), cert.release());
       ++current_cert;
 
       if (current_cert == num_certs) {
@@ -115,11 +136,11 @@
   if (store->objs != NULL) {
     for (uintptr_t i = 0; i < sk_X509_OBJECT_num(store->objs); ++i) {
       X509* ca = sk_X509_OBJECT_value(store->objs, i)->data.x509;
-      SecCertificateRef cert = CreateSecCertificateFromX509(ca);
+      ScopedSecCertificateRef cert(CreateSecCertificateFromX509(ca));
       if (cert == NULL) {
         return ctx->verify_cb(0, ctx);
       }
-      CFArrayAppendValue(trusted_certs.get(), cert);
+      CFArrayAppendValue(trusted_certs.get(), cert.release());
     }
   }
 
diff --git a/runtime/bin/security_context_win.cc b/runtime/bin/security_context_win.cc
index 85d63bb..0e4325b 100644
--- a/runtime/bin/security_context_win.cc
+++ b/runtime/bin/security_context_win.cc
@@ -15,9 +15,9 @@
 
 #include "bin/directory.h"
 #include "bin/file.h"
-#include "bin/log.h"
 #include "bin/secure_socket_filter.h"
 #include "bin/secure_socket_utils.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
@@ -43,7 +43,7 @@
   // Fall back on the compiled-in certs if the standard locations don't exist,
   // or we aren't on Linux.
   if (SSL_LOG_STATUS) {
-    Log::Print("Trusting compiled-in roots\n");
+    Syslog::Print("Trusting compiled-in roots\n");
   }
   AddCompiledInCerts();
 }
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index abcb7ba..2a07139 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -293,7 +293,7 @@
 
   file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
   if (LOG_SECTION_BOUNDARIES) {
-    Log::PrintErr("%" Px64 ": VM Data\n", file->Position());
+    Syslog::PrintErr("%" Px64 ": VM Data\n", file->Position());
   }
   if (!file->WriteFully(vm_data_buffer, vm_data_size)) {
     ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename);
@@ -302,7 +302,7 @@
   if (vm_instructions_size != 0) {
     file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
     if (LOG_SECTION_BOUNDARIES) {
-      Log::PrintErr("%" Px64 ": VM Instructions\n", file->Position());
+      Syslog::PrintErr("%" Px64 ": VM Instructions\n", file->Position());
     }
     if (!file->WriteFully(vm_instructions_buffer, vm_instructions_size)) {
       ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n",
@@ -312,7 +312,7 @@
 
   file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
   if (LOG_SECTION_BOUNDARIES) {
-    Log::PrintErr("%" Px64 ": Isolate Data\n", file->Position());
+    Syslog::PrintErr("%" Px64 ": Isolate Data\n", file->Position());
   }
   if (!file->WriteFully(isolate_data_buffer, isolate_data_size)) {
     ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename);
@@ -321,7 +321,7 @@
   if (isolate_instructions_size != 0) {
     file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
     if (LOG_SECTION_BOUNDARIES) {
-      Log::PrintErr("%" Px64 ": Isolate Instructions\n", file->Position());
+      Syslog::PrintErr("%" Px64 ": Isolate Instructions\n", file->Position());
     }
     if (!file->WriteFully(isolate_instructions_buffer,
                           isolate_instructions_size)) {
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index 113ea22..b706482 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -94,7 +94,7 @@
                                                       intptr_t backlog,
                                                       bool v6_only,
                                                       bool shared) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
 
   OSSocket* first_os_socket = NULL;
   intptr_t port = SocketAddress::GetAddrPort(addr);
@@ -195,7 +195,7 @@
 
 bool ListeningSocketRegistry::CloseOneSafe(OSSocket* os_socket,
                                            bool update_hash_maps) {
-  ASSERT(!mutex_->TryLock());
+  ASSERT(!mutex_.TryLock());
   ASSERT(os_socket != NULL);
   ASSERT(os_socket->ref_count > 0);
   os_socket->ref_count--;
@@ -232,7 +232,7 @@
 }
 
 void ListeningSocketRegistry::CloseAllSafe() {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
 
   for (SimpleHashMap::Entry* cursor = sockets_by_fd_.Start(); cursor != NULL;
        cursor = sockets_by_fd_.Next(cursor)) {
@@ -241,7 +241,7 @@
 }
 
 bool ListeningSocketRegistry::CloseSafe(Socket* socketfd) {
-  ASSERT(!mutex_->TryLock());
+  ASSERT(!mutex_.TryLock());
   OSSocket* os_socket = LookupByFd(socketfd);
   if (os_socket != NULL) {
     return CloseOneSafe(os_socket, true);
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index 24d95b9..a23ff65 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -155,12 +155,10 @@
   ListeningSocketRegistry()
       : sockets_by_port_(SameIntptrValue, kInitialSocketsCount),
         sockets_by_fd_(SameIntptrValue, kInitialSocketsCount),
-        mutex_(new Mutex()) {}
+        mutex_() {}
 
   ~ListeningSocketRegistry() {
     CloseAllSafe();
-    delete mutex_;
-    mutex_ = NULL;
   }
 
   static void Initialize();
@@ -187,7 +185,7 @@
   // this function.
   bool CloseSafe(Socket* socketfd);
 
-  Mutex* mutex() { return mutex_; }
+  Mutex* mutex() { return &mutex_; }
 
  private:
   struct OSSocket {
@@ -254,7 +252,7 @@
   SimpleHashMap sockets_by_port_;
   SimpleHashMap sockets_by_fd_;
 
-  Mutex* mutex_;
+  Mutex mutex_;
 
   DISALLOW_COPY_AND_ASSIGN(ListeningSocketRegistry);
 };
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index 42fd447..5547672 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -10,8 +10,8 @@
 #include <errno.h>  // NOLINT
 
 #include "bin/fdutils.h"
-#include "bin/log.h"
 #include "platform/signal_blocker.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
@@ -104,7 +104,7 @@
 
   if (reusePort) {
     // ignore reusePort - not supported on this platform.
-    Log::PrintErr(
+    Syslog::PrintErr(
         "Dart Socket ERROR: %s:%d: `reusePort` not supported for "
         "Android.",
         __FILE__, __LINE__);
diff --git a/runtime/bin/socket_base_android.cc b/runtime/bin/socket_base_android.cc
index 084ab2f..c72c276 100644
--- a/runtime/bin/socket_base_android.cc
+++ b/runtime/bin/socket_base_android.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2019, 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.
 
@@ -7,16 +7,19 @@
 
 #include "bin/socket_base.h"
 
-#include <errno.h>        // NOLINT
-#include <netinet/tcp.h>  // NOLINT
-#include <stdio.h>        // NOLINT
-#include <stdlib.h>       // NOLINT
-#include <string.h>       // NOLINT
-#include <sys/stat.h>     // NOLINT
-#include <unistd.h>       // NOLINT
+#include <errno.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <netinet/tcp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "bin/fdutils.h"
 #include "bin/file.h"
+#include "bin/ifaddrs-android.h"
 #include "bin/socket_base_android.h"
 #include "platform/signal_blocker.h"
 
@@ -241,21 +244,57 @@
   return (result == 1);
 }
 
+static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) {
+  if (ifa->ifa_addr == NULL) {
+    // OpenVPN's virtual device tun0.
+    return false;
+  }
+  int family = ifa->ifa_addr->sa_family;
+  return ((lookup_family == family) ||
+          (((lookup_family == AF_UNSPEC) &&
+            ((family == AF_INET) || (family == AF_INET6)))));
+}
+
 bool SocketBase::ListInterfacesSupported() {
-  return false;
+  return true;
 }
 
 AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces(
     int type,
     OSError** os_error) {
-  // The ifaddrs.h header is not provided on Android.  An Android
-  // implementation would have to use IOCTL or netlink.
-  ASSERT(*os_error == NULL);
-  *os_error = new OSError(-1,
-                          "Listing interfaces is not supported "
-                          "on this platform",
-                          OSError::kSystem);
-  return NULL;
+  struct ifaddrs* ifaddr;
+
+  int status = NO_RETRY_EXPECTED(getifaddrs(&ifaddr));
+  if (status != 0) {
+    ASSERT(*os_error == NULL);
+    *os_error =
+        new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
+    return NULL;
+  }
+
+  int lookup_family = SocketAddress::FromType(type);
+
+  intptr_t count = 0;
+  for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+    if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
+      count++;
+    }
+  }
+
+  AddressList<InterfaceSocketAddress>* addresses =
+      new AddressList<InterfaceSocketAddress>(count);
+  int i = 0;
+  for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+    if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
+      char* ifa_name = DartUtils::ScopedCopyCString(ifa->ifa_name);
+      addresses->SetAt(
+          i, new InterfaceSocketAddress(ifa->ifa_addr, ifa_name,
+                                        if_nametoindex(ifa->ifa_name)));
+      i++;
+    }
+  }
+  freeifaddrs(ifaddr);
+  return addresses;
 }
 
 void SocketBase::Close(intptr_t fd) {
diff --git a/runtime/bin/socket_base_fuchsia.cc b/runtime/bin/socket_base_fuchsia.cc
index 7191a64..a08257d 100644
--- a/runtime/bin/socket_base_fuchsia.cc
+++ b/runtime/bin/socket_base_fuchsia.cc
@@ -37,13 +37,14 @@
 #define LOG_ERR(msg, ...)                                                      \
   {                                                                            \
     int err = errno;                                                           \
-    Log::PrintErr("Dart Socket ERROR: %s:%d: " msg, __FILE__, __LINE__,        \
-                  ##__VA_ARGS__);                                              \
+    Syslog::PrintErr("Dart Socket ERROR: %s:%d: " msg, __FILE__, __LINE__,     \
+                     ##__VA_ARGS__);                                           \
     errno = err;                                                               \
   }
 #if defined(SOCKET_LOG_INFO)
 #define LOG_INFO(msg, ...)                                                     \
-  Log::Print("Dart Socket INFO: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__)
+  Syslog::Print("Dart Socket INFO: %s:%d: " msg, __FILE__, __LINE__,           \
+                ##__VA_ARGS__)
 #else
 #define LOG_INFO(msg, ...)
 #endif  // defined(SOCKET_LOG_INFO)
@@ -180,7 +181,13 @@
 }
 
 void SocketBase::GetError(intptr_t fd, OSError* os_error) {
-  errno = ENOSYS;
+  IOHandle* handle = reinterpret_cast<IOHandle*>(fd);
+  ASSERT(handle->fd() >= 0);
+  int len = sizeof(errno);
+  int err = 0;
+  VOID_NO_RETRY_EXPECTED(getsockopt(handle->fd(), SOL_SOCKET, SO_ERROR, &err,
+                                    reinterpret_cast<socklen_t*>(&len)));
+  errno = err;
   os_error->SetCodeAndMessage(OSError::kSystem, errno);
 }
 
diff --git a/runtime/bin/socket_base_win.cc b/runtime/bin/socket_base_win.cc
index 69d566b..6aaef24 100644
--- a/runtime/bin/socket_base_win.cc
+++ b/runtime/bin/socket_base_win.cc
@@ -11,11 +11,11 @@
 #include "bin/eventhandler.h"
 #include "bin/file.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/socket_base_win.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
@@ -51,7 +51,7 @@
   if (err == 0) {
     socket_initialized = true;
   } else {
-    Log::PrintErr("Unable to initialize Winsock: %d\n", WSAGetLastError());
+    Syslog::PrintErr("Unable to initialize Winsock: %d\n", WSAGetLastError());
   }
   return (err == 0);
 }
diff --git a/runtime/bin/socket_fuchsia.cc b/runtime/bin/socket_fuchsia.cc
index 4af64a6..5454c7e 100644
--- a/runtime/bin/socket_fuchsia.cc
+++ b/runtime/bin/socket_fuchsia.cc
@@ -11,8 +11,8 @@
 
 #include "bin/eventhandler.h"
 #include "bin/fdutils.h"
-#include "bin/log.h"
 #include "platform/signal_blocker.h"
+#include "platform/syslog.h"
 
 // #define SOCKET_LOG_INFO 1
 // #define SOCKET_LOG_ERROR 1
@@ -24,13 +24,14 @@
 #define LOG_ERR(msg, ...)                                                      \
   {                                                                            \
     int err = errno;                                                           \
-    Log::PrintErr("Dart Socket ERROR: %s:%d: " msg, __FILE__, __LINE__,        \
-                  ##__VA_ARGS__);                                              \
+    Syslog::PrintErr("Dart Socket ERROR: %s:%d: " msg, __FILE__, __LINE__,     \
+                     ##__VA_ARGS__);                                           \
     errno = err;                                                               \
   }
 #if defined(SOCKET_LOG_INFO)
 #define LOG_INFO(msg, ...)                                                     \
-  Log::Print("Dart Socket INFO: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__)
+  Syslog::Print("Dart Socket INFO: %s:%d: " msg, __FILE__, __LINE__,           \
+                ##__VA_ARGS__)
 #else
 #define LOG_INFO(msg, ...)
 #endif  // defined(SOCKET_LOG_INFO)
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 979db01..f2bb4aa 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -10,8 +10,8 @@
 #include <errno.h>  // NOLINT
 
 #include "bin/fdutils.h"
-#include "bin/log.h"
 #include "platform/signal_blocker.h"
+#include "platform/syslog.h"
 #include "platform/utils.h"
 
 namespace dart {
@@ -105,11 +105,11 @@
       }
       const int kBufferSize = 1024;
       char error_buf[kBufferSize];
-      Log::PrintErr("Dart Socket ERROR: %s:%d: %s.", __FILE__, __LINE__,
-                    Utils::StrError(errno, error_buf, kBufferSize));
+      Syslog::PrintErr("Dart Socket ERROR: %s:%d: %s.", __FILE__, __LINE__,
+                       Utils::StrError(errno, error_buf, kBufferSize));
     }
 #else   // !defined SO_REUSEPORT
-    Log::PrintErr(
+    Syslog::PrintErr(
         "Dart Socket ERROR: %s:%d: `reusePort` not available on this Linux "
         "version.",
         __FILE__, __LINE__);
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 870179c..4a87275 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -504,9 +504,21 @@
           // indicate that the socket is fully connected.
           socket.setHandlers(write: () {
             timer.cancel();
+            connecting.remove(socket);
+            // From 'man 2 connect':
+            // After select(2) indicates writability, use getsockopt(2) to read
+            // the SO_ERROR option at level SOL_SOCKET to determine whether
+            // connect() completed successfully (SO_ERROR is zero) or
+            // unsuccessfully.
+            OSError osError = socket.nativeGetError();
+            if (osError.errorCode != 0) {
+              socket.close();
+              if (error == null) error = osError;
+              if (connecting.isEmpty) connectNext();
+              return;
+            }
             socket.setListening(read: false, write: false);
             completer.complete(socket);
-            connecting.remove(socket);
             connecting.forEach((s, t) {
               t.cancel();
               s.close();
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index 957ac92..79820da 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -9,12 +9,12 @@
 #include "bin/eventhandler.h"
 #include "bin/file.h"
 #include "bin/lockers.h"
-#include "bin/log.h"
 #include "bin/socket.h"
 #include "bin/socket_base_win.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
@@ -171,7 +171,7 @@
 
   if (reusePort) {
     // ignore reusePort - not supported on this platform.
-    Log::PrintErr(
+    Syslog::PrintErr(
         "Dart Socket ERROR: %s:%d: `reusePort` not supported for "
         "Windows.",
         __FILE__, __LINE__);
diff --git a/runtime/bin/utils_fuchsia.cc b/runtime/bin/utils_fuchsia.cc
index 4c8b208..c7bbe08 100644
--- a/runtime/bin/utils_fuchsia.cc
+++ b/runtime/bin/utils_fuchsia.cc
@@ -77,7 +77,7 @@
 }
 
 int64_t TimerUtils::GetCurrentMonotonicMicros() {
-  int64_t ticks = zx_clock_get(ZX_CLOCK_MONOTONIC);
+  zx_time_t ticks = zx_clock_get_monotonic();
   return ticks / kNanosecondsPerMicrosecond;
 }
 
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index f4764b4..f73bd20 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -8,10 +8,10 @@
 #include <errno.h>  // NOLINT
 #include <time.h>   // NOLINT
 
-#include "bin/log.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
 #include "platform/assert.h"
+#include "platform/syslog.h"
 
 namespace dart {
 namespace bin {
@@ -22,8 +22,8 @@
       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, buffer_length, NULL);
   if (message_size == 0) {
     if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-      Log::PrintErr("FormatMessage failed for error code %d (error %d)\n", code,
-                    GetLastError());
+      Syslog::PrintErr("FormatMessage failed for error code %d (error %d)\n",
+                       code, GetLastError());
     }
     _snwprintf(buffer, buffer_length, L"OS Error %d", code);
   }
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index 40d7def..b003c6a 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -216,14 +216,15 @@
     return false;
   }
 
-  /// Checks the [requestUri] for the service auth token and returns the path.
-  /// If the service auth token check fails, returns null.
-  String _checkAuthTokenAndGetPath(Uri requestUri) {
+  /// Checks the [requestUri] for the service auth token and returns the path
+  /// as a String. If the service auth token check fails, returns null.
+  /// Returns a Uri if a redirect is required.
+  dynamic _checkAuthTokenAndGetPath(Uri requestUri) {
     if (_authCodesDisabled) {
       return requestUri.path == '/' ? ROOT_REDIRECT_PATH : requestUri.path;
     }
     final List<String> requestPathSegments = requestUri.pathSegments;
-    if (requestPathSegments.length < 2) {
+    if (requestPathSegments.isEmpty) {
       // Malformed.
       return null;
     }
@@ -233,6 +234,18 @@
       // Malformed.
       return null;
     }
+    // Missing a trailing '/'. We'll need to redirect to serve
+    // ROOT_REDIRECT_PATH correctly, otherwise the response is misinterpreted.
+    if (requestPathSegments.length == 1) {
+      // requestPathSegments is unmodifiable. Copy it.
+      final List<String> pathSegments = <String>[]..addAll(requestPathSegments);
+
+      // Adding an empty string to the path segments results in the path having
+      // a trailing '/'.
+      pathSegments.add('');
+
+      return requestUri.replace(pathSegments: pathSegments);
+    }
     // Construct the actual request path by chopping off the auth token.
     return (requestPathSegments[1] == '')
         ? ROOT_REDIRECT_PATH
@@ -305,16 +318,24 @@
       return;
     }
 
-    final String path = _checkAuthTokenAndGetPath(request.uri);
-    if (path == null) {
+    final dynamic result = _checkAuthTokenAndGetPath(request.uri);
+    if (result == null) {
       // Either no authentication code was provided when one was expected or an
       // incorrect authentication code was provided.
       request.response.statusCode = HttpStatus.forbidden;
       request.response.write("missing or invalid authentication code");
       request.response.close();
       return;
+    } else if (result is Uri) {
+      // The URI contains the valid auth token but is missing a trailing '/'.
+      // Redirect to the same URI with the trailing '/' to correctly serve
+      // index.html.
+      request.response.redirect(result as Uri);
+      request.response.close();
+      return;
     }
 
+    final String path = result;
     if (path == WEBSOCKET_PATH) {
       WebSocketTransformer.upgrade(request).then((WebSocket webSocket) {
         new WebSocketClient(webSocket, _service);
@@ -338,7 +359,8 @@
     }
     // HTTP based service request.
     final client = new HttpRequestClient(request, _service);
-    final message = new Message.fromUri(client, Uri.parse(path));
+    final message = new Message.fromUri(
+        client, Uri(path: path, queryParameters: request.uri.queryParameters));
     client.onRequest(message); // exception free, no need to try catch
   }
 
diff --git a/runtime/configs.gni b/runtime/configs.gni
index a476622..a638887 100644
--- a/runtime/configs.gni
+++ b/runtime/configs.gni
@@ -24,6 +24,10 @@
 
 _jit_product_config = _base_config + _product
 
+_base_libfuzzer_config = [ "$_dart_runtime:dart_libfuzzer_config" ]
+
+_libfuzzer_config = _base_config + _base_libfuzzer_config
+
 _precompiled_runtime_config =
     _base_config + [
       "$_dart_runtime:dart_maybe_product_config",
@@ -94,6 +98,11 @@
     configs = _nosnapshot_with_precompiler_product_fuchsia_config
     snapshot = false
   },
+  {
+    suffix = "_libfuzzer"
+    configs = _libfuzzer_config
+    snapshot = true
+  },
 ]
 
 # This template creates a target for each of the configurations listed above.
@@ -156,9 +165,6 @@
                                "extra_deps",
                                "configurable_deps",
                              ])
-      if (is_fuchsia) {
-        configs -= [ "//build/config:symbol_visibility_hidden" ]
-      }
       configs += conf.configs + extra_configs
       configured_deps = []
       foreach(dep, configurable_deps) {
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 18714e5..31a7d1b 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -913,6 +913,13 @@
 DART_EXPORT Dart_Handle Dart_DebugName();
 
 /**
+ * Returns the ID for an isolate which is used to query the service protocol.
+ *
+ * It is the responsibility of the caller to free the returned ID.
+ */
+DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate);
+
+/**
  * Enters an isolate. After calling this function,
  * the current isolate will be set to the provided isolate.
  *
@@ -976,6 +983,16 @@
 DART_EXPORT void Dart_ThreadEnableProfiling();
 
 /**
+ * Register symbol information for the Dart VM's profiler and crash dumps.
+ *
+ * This consumes the output of //topaz/runtime/dart/profiler_symbols, which
+ * should be treated as opaque.
+ */
+DART_EXPORT void Dart_AddSymbols(const char* dso_name,
+                                 void* buffer,
+                                 intptr_t buffer_size);
+
+/**
  * Exits an isolate. After this call, Dart_CurrentIsolate will
  * return NULL.
  *
@@ -3256,7 +3273,7 @@
  *  Running this snapshot requires a VM compiled with DART_PRECOMPILED_SNAPSHOT.
  *  The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to
  *  Dart_Initialize. The kDartIsolateSnapshotData and
- *  kDartIsoalteSnapshotInstructions should be passed to Dart_CreateIsolate.
+ *  kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate.
  *
  *  The callback will be invoked one or more times to provide the assembly code.
  *
@@ -3267,6 +3284,32 @@
                                     void* callback_data);
 
 /**
+ *  Creates a precompiled snapshot.
+ *   - A root library must have been loaded.
+ *   - Dart_Precompile must have been called.
+ *
+ *  Outputs an ELF shared library defining the symbols
+ *   - kDartVmSnapshotData
+ *   - kDartVmSnapshotInstructions
+ *   - kDartIsolateSnapshotData
+ *   - kDartIsolateSnapshotInstructions
+ *
+ *  The shared library should be dynamically loaded by the embedder.
+ *  Running this snapshot requires a VM compiled with DART_PRECOMPILED_SNAPSHOT.
+ *  The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to
+ *  Dart_Initialize. The kDartIsolateSnapshotData and
+ *  kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate.
+ *
+ *  The callback will be invoked one or more times to provide the binary output.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback,
+                               void* callback_data,
+                               bool stripped);
+
+/**
  *  Like Dart_CreateAppAOTSnapshotAsAssembly, but only includes
  *  kDartVmSnapshotData and kDartVmSnapshotInstructions.
  */
diff --git a/runtime/include/dart_native_api.h b/runtime/include/dart_native_api.h
index 39b29ff..e45c010 100644
--- a/runtime/include/dart_native_api.h
+++ b/runtime/include/dart_native_api.h
@@ -170,4 +170,15 @@
 
 DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_ReadAllBytecode();
 
+/**
+ * Finalizes all classes.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeAllClasses();
+
+/*  This function is intentionally undocumented.
+ *
+ *  It should not be used outside internal tests.
+ */
+DART_EXPORT void Dart_ExecuteInternalCommand(const char* command);
+
 #endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */
diff --git a/runtime/lib/async_sources.gni b/runtime/lib/async_sources.gni
index 914aa9b..d3fef9a 100644
--- a/runtime/lib/async_sources.gni
+++ b/runtime/lib/async_sources.gni
@@ -12,5 +12,3 @@
   "schedule_microtask_patch.dart",
   "timer_patch.dart",
 ]
-
-async_runtime_sources = async_runtime_cc_files + async_runtime_dart_files
diff --git a/runtime/lib/bigint_patch.dart b/runtime/lib/bigint_patch.dart
index 2046284..19c1919 100644
--- a/runtime/lib/bigint_patch.dart
+++ b/runtime/lib/bigint_patch.dart
@@ -1986,6 +1986,7 @@
         _rsh(uDigits, maxUsed, 1, uDigits);
         if (ac) {
           if (((aDigits[0] & 1) == 1) || ((bDigits[0] & 1) == 1)) {
+            // a += y
             if (aIsNegative) {
               if ((aDigits[maxUsed] != 0) ||
                   (_compareDigits(aDigits, maxUsed, yDigits, maxUsed)) > 0) {
@@ -1997,6 +1998,7 @@
             } else {
               _absAdd(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
             }
+            // b -= x
             if (bIsNegative) {
               _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
             } else if ((bDigits[maxUsed] != 0) ||
@@ -2009,6 +2011,7 @@
           }
           _rsh(aDigits, abcdUsed, 1, aDigits);
         } else if ((bDigits[0] & 1) == 1) {
+          // b -= x
           if (bIsNegative) {
             _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
           } else if ((bDigits[maxUsed] != 0) ||
@@ -2025,6 +2028,7 @@
         _rsh(vDigits, maxUsed, 1, vDigits);
         if (ac) {
           if (((cDigits[0] & 1) == 1) || ((dDigits[0] & 1) == 1)) {
+            // c += y
             if (cIsNegative) {
               if ((cDigits[maxUsed] != 0) ||
                   (_compareDigits(cDigits, maxUsed, yDigits, maxUsed) > 0)) {
@@ -2036,6 +2040,7 @@
             } else {
               _absAdd(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
             }
+            // d -= x
             if (dIsNegative) {
               _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
             } else if ((dDigits[maxUsed] != 0) ||
@@ -2048,6 +2053,7 @@
           }
           _rsh(cDigits, abcdUsed, 1, cDigits);
         } else if ((dDigits[0] & 1) == 1) {
+          // d -= x
           if (dIsNegative) {
             _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
           } else if ((dDigits[maxUsed] != 0) ||
@@ -2061,8 +2067,10 @@
         _rsh(dDigits, abcdUsed, 1, dDigits);
       }
       if (_compareDigits(uDigits, maxUsed, vDigits, maxUsed) >= 0) {
+        // u -= v
         _absSub(uDigits, maxUsed, vDigits, maxUsed, uDigits);
         if (ac) {
+          // a -= c
           if (aIsNegative == cIsNegative) {
             var a_cmp_c = _compareDigits(aDigits, abcdUsed, cDigits, abcdUsed);
             if (a_cmp_c > 0) {
@@ -2075,6 +2083,7 @@
             _absAdd(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
           }
         }
+        // b -= d
         if (bIsNegative == dIsNegative) {
           var b_cmp_d = _compareDigits(bDigits, abcdUsed, dDigits, abcdUsed);
           if (b_cmp_d > 0) {
@@ -2087,8 +2096,10 @@
           _absAdd(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
         }
       } else {
+        // v -= u
         _absSub(vDigits, maxUsed, uDigits, maxUsed, vDigits);
         if (ac) {
+          // c -= a
           if (cIsNegative == aIsNegative) {
             var c_cmp_a = _compareDigits(cDigits, abcdUsed, aDigits, abcdUsed);
             if (c_cmp_a > 0) {
@@ -2101,6 +2112,7 @@
             _absAdd(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
           }
         }
+        // d -= b
         if (dIsNegative == bIsNegative) {
           var d_cmp_b = _compareDigits(dDigits, abcdUsed, bDigits, abcdUsed);
           if (d_cmp_b > 0) {
@@ -2132,25 +2144,18 @@
     }
 
     if (dIsNegative) {
-      if ((dDigits[maxUsed] != 0) ||
+      while ((dDigits[maxUsed] != 0) ||
           (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+        // d += x, d still negative
         _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        if ((dDigits[maxUsed] != 0) ||
-            (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-          _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        } else {
-          _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-          dIsNegative = false;
-        }
-      } else {
-        _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-        dIsNegative = false;
       }
-    } else if ((dDigits[maxUsed] != 0) ||
-        (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-      _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-      if ((dDigits[maxUsed] != 0) ||
-          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+      // d += x
+      _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+      dIsNegative = false;
+    } else {
+      while ((dDigits[maxUsed] != 0) ||
+          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) >= 0)) {
+        // d -= x
         _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
       }
     }
diff --git a/runtime/lib/collection_sources.gni b/runtime/lib/collection_sources.gni
index 1fa63d3..c3c15fc 100644
--- a/runtime/lib/collection_sources.gni
+++ b/runtime/lib/collection_sources.gni
@@ -10,6 +10,3 @@
   "collection_patch.dart",
   "compact_hash.dart",
 ]
-
-collection_runtime_sources =
-    collection_runtime_cc_files + collection_runtime_dart_files
diff --git a/runtime/lib/convert_sources.gni b/runtime/lib/convert_sources.gni
index e37c017..123db64 100644
--- a/runtime/lib/convert_sources.gni
+++ b/runtime/lib/convert_sources.gni
@@ -2,4 +2,4 @@
 # 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.
 
-convert_runtime_sources = [ "convert_patch.dart" ]
+convert_runtime_dart_files = [ "convert_patch.dart" ]
diff --git a/runtime/lib/core_sources.gni b/runtime/lib/core_sources.gni
index 4c57dc4..825663a 100644
--- a/runtime/lib/core_sources.gni
+++ b/runtime/lib/core_sources.gni
@@ -59,5 +59,3 @@
   "uri_patch.dart",
   "weak_property.dart",
 ]
-
-core_runtime_sources = core_runtime_cc_files + core_runtime_dart_files
diff --git a/runtime/lib/developer.cc b/runtime/lib/developer.cc
index defe884..f1eab3a 100644
--- a/runtime/lib/developer.cc
+++ b/runtime/lib/developer.cc
@@ -130,8 +130,8 @@
 
 static void SendNull(const SendPort& port) {
   const Dart_Port destination_port_id = port.Id();
-  PortMap::PostMessage(new Message(destination_port_id, Object::null(),
-                                   Message::kNormalPriority));
+  PortMap::PostMessage(Message::New(destination_port_id, Object::null(),
+                                    Message::kNormalPriority));
 }
 
 DEFINE_NATIVE_ENTRY(Developer_getServerInfo, 0, 1) {
diff --git a/runtime/lib/developer.dart b/runtime/lib/developer.dart
index 12ad8b7..cb35073 100644
--- a/runtime/lib/developer.dart
+++ b/runtime/lib/developer.dart
@@ -131,7 +131,7 @@
   assert(id != null);
   StringBuffer sb = new StringBuffer();
   sb.write('{"jsonrpc":"2.0",');
-  if (response._isError()) {
+  if (response.isError()) {
     if (trace_service) {
       print("vm-service: posting error response for request $id");
     }
diff --git a/runtime/lib/developer_sources.gni b/runtime/lib/developer_sources.gni
index 61f02f62..a613da7 100644
--- a/runtime/lib/developer_sources.gni
+++ b/runtime/lib/developer_sources.gni
@@ -16,6 +16,3 @@
   "profiler.dart",
   "timeline.dart",
 ]
-
-developer_runtime_sources =
-    developer_runtime_cc_files + developer_runtime_dart_files
diff --git a/runtime/lib/errors.cc b/runtime/lib/errors.cc
index 54e61eb..2bf8799 100644
--- a/runtime/lib/errors.cc
+++ b/runtime/lib/errors.cc
@@ -34,11 +34,11 @@
     if (stack_frame->is_interpreted()) {
       func = stack_frame->LookupDartFunction();
     } else {
-      code ^= stack_frame->LookupDartCode();
+      code = stack_frame->LookupDartCode();
       if (code.is_optimized()) {
         InlinedFunctionsIterator inlined_iterator(code, stack_frame->pc());
         while (!inlined_iterator.Done()) {
-          func ^= inlined_iterator.function();
+          func = inlined_iterator.function();
           if (hit_assertion_error) {
             return func.script();
           }
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 7bdca63..5dd4367 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -2,11 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#include "vm/compiler/ffi.h"
+#include "lib/ffi.h"
+
 #include "include/dart_api.h"
 #include "vm/bootstrap_natives.h"
 #include "vm/class_finalizer.h"
 #include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/ffi.h"
+#include "vm/compiler/jit/compiler.h"
 #include "vm/exceptions.h"
 #include "vm/log.h"
 #include "vm/native_arguments.h"
@@ -42,9 +45,9 @@
       Class::Handle(Isolate::Current()->object_store()->ffi_pointer_class());
   AbstractType& pointer_type =
       AbstractType::Handle(pointer_class.DeclarationType());
-  pointer_type ^= pointer_type.InstantiateFrom(Object::null_type_arguments(),
-                                               Object::null_type_arguments(),
-                                               kNoneFree, NULL, Heap::kNew);
+  pointer_type = pointer_type.InstantiateFrom(Object::null_type_arguments(),
+                                              Object::null_type_arguments(),
+                                              kNoneFree, NULL, Heap::kNew);
   ASSERT(pointer_type.IsInstantiated());
   ASSERT(type.IsInstantiated());
   return type.IsSubtypeOf(pointer_type, Heap::kNew);
@@ -544,57 +547,72 @@
   return raw_closure;
 }
 
-// Generates assembly to trampoline from C++ back into Dart.
-static void* GenerateFfiInverseTrampoline(const Function& signature,
-                                          void* dart_entry_point) {
+// Generates assembly to trampoline from native code into Dart.
+static uword CompileNativeCallback(const Function& c_signature,
+                                   const Function& dart_target) {
 #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
   UNREACHABLE();
-#elif !defined(TARGET_ARCH_X64)
+#elif defined(TARGET_ARCH_DBC)
   // https://github.com/dart-lang/sdk/issues/35774
-  UNREACHABLE();
-#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS) &&                \
-    !defined(TARGET_OS_WINDOWS)
-  // https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
-  // https://github.com/dart-lang/sdk/issues/35772 Arm64
-  // https://github.com/dart-lang/sdk/issues/35773 DBC
-  UNREACHABLE();
+  // FFI is supported, but callbacks are not.
+  Exceptions::ThrowUnsupportedError(
+      "FFI callbacks are not yet supported on DBC.");
 #else
+  Thread* const thread = Thread::Current();
+  const int32_t callback_id = thread->AllocateFfiCallbackId();
 
-  // TODO(dacoharkes): Implement this.
-  // https://github.com/dart-lang/sdk/issues/35761
-  // Look at StubCode::GenerateInvokeDartCodeStub.
-  UNREACHABLE();
+  // Create a new Function named 'FfiCallback' and stick it in the 'dart:ffi'
+  // library. Note that these functions will never be invoked by Dart, so it
+  // doesn't matter that they all have the same name.
+  Zone* const Z = thread->zone();
+  const String& name =
+      String::ZoneHandle(Symbols::New(Thread::Current(), "FfiCallback"));
+  const Library& lib = Library::Handle(Library::FfiLibrary());
+  const Class& owner_class = Class::Handle(lib.toplevel_class());
+  const Function& function =
+      Function::Handle(Z, Function::New(name, RawFunction::kFfiTrampoline,
+                                        /*is_static=*/true,
+                                        /*is_const=*/false,
+                                        /*is_abstract=*/false,
+                                        /*is_external=*/false,
+                                        /*is_native=*/false, owner_class,
+                                        TokenPosition::kMinSource));
+  function.set_is_debuggable(false);
+
+  // Set callback-specific fields which the flow-graph builder needs to generate
+  // the body.
+  function.SetFfiCSignature(c_signature);
+  function.SetFfiCallbackId(callback_id);
+  function.SetFfiCallbackTarget(dart_target);
+
+  // We compile the callback immediately because we need to return a pointer to
+  // the entry-point. Native calls do not use patching like Dart calls, so we
+  // cannot compile it lazily.
+  const Object& result =
+      Object::Handle(Z, Compiler::CompileOptimizedFunction(thread, function));
+  if (result.IsError()) {
+    Exceptions::PropagateError(Error::Cast(result));
+  }
+  ASSERT(result.IsCode());
+  const Code& code = Code::Cast(result);
+
+  thread->SetFfiCallbackCode(callback_id, code);
+
+  return code.EntryPoint();
 #endif
 }
 
-// TODO(dacoharkes): Implement this feature.
-// https://github.com/dart-lang/sdk/issues/35761
-// For now, it always returns Pointer with address 0.
 DEFINE_NATIVE_ENTRY(Ffi_fromFunction, 1, 1) {
   GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Closure, closure, arguments->NativeArgAt(0));
 
-  Function& c_signature = Function::Handle(((Type&)type_arg).signature());
-
+  const Function& native_signature =
+      Function::Handle(((Type&)type_arg).signature());
   Function& func = Function::Handle(closure.function());
-  Code& code = Code::Handle(func.EnsureHasCode());
-  void* entryPoint = reinterpret_cast<void*>(code.EntryPoint());
-
-  THR_Print("Ffi_fromFunction: %s\n", type_arg.ToCString());
-  THR_Print("Ffi_fromFunction: %s\n", c_signature.ToCString());
-  THR_Print("Ffi_fromFunction: %s\n", closure.ToCString());
-  THR_Print("Ffi_fromFunction: %s\n", func.ToCString());
-  THR_Print("Ffi_fromFunction: %s\n", code.ToCString());
-  THR_Print("Ffi_fromFunction: %p\n", entryPoint);
-  THR_Print("Ffi_fromFunction: %" Pd "\n", code.Size());
-
-  intptr_t address = reinterpret_cast<intptr_t>(
-      GenerateFfiInverseTrampoline(c_signature, entryPoint));
-
   TypeArguments& type_args = TypeArguments::Handle(zone);
   type_args = TypeArguments::New(1);
   type_args.SetTypeAt(Pointer::kNativeTypeArgPos, type_arg);
-  type_args ^= type_args.Canonicalize();
+  type_args = type_args.Canonicalize();
 
   Class& native_function_class = Class::Handle(
       Isolate::Current()->class_table()->At(kFfiNativeFunctionCid));
@@ -606,12 +624,131 @@
       ClassFinalizer::FinalizeType(Class::Handle(), native_function_type);
   native_function_type ^= native_function_type.Canonicalize();
 
-  address = 0;  // https://github.com/dart-lang/sdk/issues/35761
+  // The FE verifies that the target of a 'fromFunction' is a static method, so
+  // the value we see here must be a static tearoff. See ffi_use_sites.dart for
+  // details.
+  //
+  // TODO(36748): Define hot-reload semantics of native callbacks. We may need
+  // to look up the target by name.
+  ASSERT(func.IsImplicitClosureFunction());
+  func = func.parent_function();
+  ASSERT(func.is_static());
 
-  Pointer& result = Pointer::Handle(Pointer::New(
+  const uword address = CompileNativeCallback(native_signature, func);
+
+  const Pointer& result = Pointer::Handle(Pointer::New(
       native_function_type, Integer::Handle(zone, Integer::New(address))));
 
   return result.raw();
 }
 
+#if defined(TARGET_ARCH_DBC)
+
+void FfiMarshalledArguments::SetFunctionAddress(uint64_t value) const {
+  data_[kOffsetFunctionAddress] = value;
+}
+
+static intptr_t ArgumentHostRegisterIndex(host::Register reg) {
+  for (intptr_t i = 0; i < host::CallingConventions::kNumArgRegs; i++) {
+    if (host::CallingConventions::ArgumentRegisters[i] == reg) {
+      return i;
+    }
+  }
+  UNREACHABLE();
+}
+
+void FfiMarshalledArguments::SetRegister(host::Register reg,
+                                         uint64_t value) const {
+  const intptr_t reg_index = ArgumentHostRegisterIndex(reg);
+  ASSERT(host::CallingConventions::ArgumentRegisters[reg_index] == reg);
+  const intptr_t index = kOffsetRegisters + reg_index;
+  data_[index] = value;
+}
+
+void FfiMarshalledArguments::SetFpuRegister(host::FpuRegister reg,
+                                            uint64_t value) const {
+  const intptr_t fpu_index = static_cast<intptr_t>(reg);
+  ASSERT(host::CallingConventions::FpuArgumentRegisters[fpu_index] == reg);
+  const intptr_t index = kOffsetFpuRegisters + fpu_index;
+  data_[index] = value;
+}
+
+void FfiMarshalledArguments::SetNumStackSlots(intptr_t num_args) const {
+  data_[kOffsetNumStackSlots] = num_args;
+}
+
+intptr_t FfiMarshalledArguments::GetNumStackSlots() const {
+  return data_[kOffsetNumStackSlots];
+}
+
+void FfiMarshalledArguments::SetStackSlotValue(intptr_t index,
+                                               uint64_t value) const {
+  ASSERT(0 <= index && index < GetNumStackSlots());
+  data_[kOffsetStackSlotValues + index] = value;
+}
+
+uint64_t* FfiMarshalledArguments::New(
+    const compiler::ffi::FfiSignatureDescriptor& signature,
+    const uint64_t* arg_values) {
+  const intptr_t num_stack_slots = signature.num_stack_slots();
+  const intptr_t size =
+      FfiMarshalledArguments::kOffsetStackSlotValues + num_stack_slots;
+  uint64_t* data = Thread::Current()->GetFfiMarshalledArguments(size);
+  const auto& descr = FfiMarshalledArguments(data);
+
+  descr.SetFunctionAddress(arg_values[compiler::ffi::kFunctionAddressRegister]);
+  const intptr_t num_args = signature.length();
+  descr.SetNumStackSlots(num_stack_slots);
+  for (int i = 0; i < num_args; i++) {
+    uint64_t arg_value = arg_values[compiler::ffi::kFirstArgumentRegister + i];
+    HostLocation loc = signature.LocationAt(i);
+    // TODO(36809): For 32 bit, support pair locations.
+    if (loc.IsRegister()) {
+      descr.SetRegister(loc.reg(), arg_value);
+    } else if (loc.IsFpuRegister()) {
+      descr.SetFpuRegister(loc.fpu_reg(), arg_value);
+    } else {
+      ASSERT(loc.IsStackSlot() || loc.IsDoubleStackSlot());
+      ASSERT(loc.stack_index() < num_stack_slots);
+      descr.SetStackSlotValue(loc.stack_index(), arg_value);
+    }
+  }
+
+  return data;
+}
+
+#if defined(DEBUG)
+void FfiMarshalledArguments::Print() const {
+  OS::PrintErr("FfiMarshalledArguments data_ 0x%" Pp "\n",
+               reinterpret_cast<intptr_t>(data_));
+  OS::PrintErr("  00 0x%016" Px64 " (function address, int result)\n",
+               data_[0]);
+  for (intptr_t i = 0; i < host::CallingConventions::kNumArgRegs; i++) {
+    const intptr_t index = kOffsetRegisters + i;
+    const char* result_str = i == 0 ? ", float result" : "";
+    OS::PrintErr("  %02" Pd " 0x%016" Px64 " (%s%s)\n", index, data_[index],
+                 RegisterNames::RegisterName(
+                     host::CallingConventions::ArgumentRegisters[i]),
+                 result_str);
+  }
+  for (intptr_t i = 0; i < host::CallingConventions::kNumFpuArgRegs; i++) {
+    const intptr_t index = kOffsetFpuRegisters + i;
+    OS::PrintErr("  %02" Pd " 0x%016" Px64 " (%s)\n", index, data_[index],
+                 RegisterNames::FpuRegisterName(
+                     host::CallingConventions::FpuArgumentRegisters[i]));
+  }
+  const intptr_t index = kOffsetNumStackSlots;
+  const intptr_t num_stack_slots = data_[index];
+  OS::PrintErr("  %02" Pd " 0x%" Pp " (number of stack slots)\n", index,
+               num_stack_slots);
+  for (intptr_t i = 0; i < num_stack_slots; i++) {
+    const intptr_t index = kOffsetStackSlotValues + i;
+    OS::PrintErr("  %02" Pd " 0x%016" Px64 " (stack slot %" Pd ")\n", index,
+                 data_[index], i);
+  }
+}
+#endif  // defined(DEBUG)
+
+#endif  // defined(TARGET_ARCH_DBC)
+
 }  // namespace dart
diff --git a/runtime/lib/ffi.h b/runtime/lib/ffi.h
new file mode 100644
index 0000000..00c527f
--- /dev/null
+++ b/runtime/lib/ffi.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_LIB_FFI_H_
+#define RUNTIME_LIB_FFI_H_
+
+#if defined(TARGET_ARCH_DBC)
+
+#include <platform/globals.h>
+
+#include "vm/class_id.h"
+#include "vm/compiler/backend/locations.h"
+#include "vm/compiler/ffi.h"
+#include "vm/object.h"
+#include "vm/raw_object.h"
+
+namespace dart {
+
+// This structure contains all data required for an ffi call.
+// It consists of the function address, all calling convention argument
+// register values, argument fpu register values, number of stack arguments,
+// and stack argument values. The generic DBC trampoline reads its arguments
+// from this structure.
+//
+// Moreover, the DBC trampoline also stores the integer and floating point
+// result registers in the first two slots when returning.
+class FfiMarshalledArguments : public ValueObject {
+ public:
+  explicit FfiMarshalledArguments(uint64_t* data) : data_(data) {}
+
+  // Copies ffi trampoline arguments (including target address) from stack into
+  // a signature agnostic data structure (FfiMarshalledArguments) using the
+  // signature and the stack address of the first argument. (Note that this
+  // only works on DBC as the stack grows upwards in DBC.)
+  static uint64_t* New(const compiler::ffi::FfiSignatureDescriptor& signature,
+                       const uint64_t* arg_values);
+
+  uint64_t IntResult() const { return data_[kOffsetIntResult]; }
+  uint64_t DoubleResult() const { return data_[kOffsetDoubleResult]; }
+
+#if defined(DEBUG)
+  void Print() const;
+#endif
+
+ private:
+  void SetFunctionAddress(uint64_t value) const;
+  void SetRegister(::dart::host::Register reg, uint64_t value) const;
+  void SetFpuRegister(::dart::host::FpuRegister reg, uint64_t value) const;
+  void SetNumStackSlots(intptr_t num_args) const;
+  intptr_t GetNumStackSlots() const;
+  void SetStackSlotValue(intptr_t index, uint64_t value) const;
+
+  // TODO(36809): Replace this with uword. On 32 bit architecture,
+  // this should be 32 bits, as the DBC stack itself is 32 bits.
+  uint64_t* data_;
+
+  static const intptr_t kOffsetFunctionAddress = 0;
+  static const intptr_t kOffsetRegisters = 1;
+  static const intptr_t kOffsetFpuRegisters =
+      kOffsetRegisters + ::dart::host::CallingConventions::kNumArgRegs;
+  static const intptr_t kOffsetNumStackSlots =
+      kOffsetFpuRegisters + ::dart::host::CallingConventions::kNumFpuArgRegs;
+  static const intptr_t kOffsetStackSlotValues = kOffsetNumStackSlots + 1;
+
+  static const intptr_t kOffsetIntResult = 0;
+  static const intptr_t kOffsetDoubleResult = 1;
+};
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_DBC)
+
+#endif  // RUNTIME_LIB_FFI_H_
diff --git a/runtime/lib/ffi_dynamic_library.cc b/runtime/lib/ffi_dynamic_library.cc
index 4bd67e2..102e1b3 100644
--- a/runtime/lib/ffi_dynamic_library.cc
+++ b/runtime/lib/ffi_dynamic_library.cc
@@ -2,8 +2,14 @@
 // 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(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS) &&                  \
-    !defined(TARGET_OS_ANDROID)
+#include "include/dart_api.h"
+#include "vm/bootstrap_natives.h"
+#include "vm/exceptions.h"
+#include "vm/globals.h"
+#include "vm/native_entry.h"
+
+#if !defined(HOST_OS_LINUX) && !defined(HOST_OS_MACOS) &&                      \
+    !defined(HOST_OS_ANDROID)
 // TODO(dacoharkes): Implement dynamic libraries for other targets & merge the
 // implementation with:
 // - runtime/bin/extensions.h
@@ -13,16 +19,11 @@
 #else
 #include <dlfcn.h>
 #endif
-#include "include/dart_api.h"
-#include "vm/bootstrap_natives.h"
-#include "vm/exceptions.h"
-#include "vm/native_entry.h"
 
 namespace dart {
 
 static void* LoadExtensionLibrary(const char* library_file) {
-#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS) ||                    \
-    defined(TARGET_OS_ANDROID)
+#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
   void* handle = dlopen(library_file, RTLD_LAZY);
   if (handle == nullptr) {
     char* error = dlerror();
@@ -32,7 +33,7 @@
   }
 
   return handle;
-#elif defined(TARGET_OS_WINDOWS)
+#elif defined(HOST_OS_WINDOWS)
   SetLastError(0);  // Clear any errors.
 
   // Convert to wchar_t string.
@@ -70,8 +71,7 @@
 }
 
 static void* ResolveSymbol(void* handle, const char* symbol) {
-#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS) ||                    \
-    defined(TARGET_OS_ANDROID)
+#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
   dlerror();  // Clear any errors.
   void* pointer = dlsym(handle, symbol);
   if (pointer == nullptr) {
@@ -81,7 +81,7 @@
     Exceptions::ThrowArgumentError(msg);
   }
   return pointer;
-#elif defined(TARGET_OS_WINDOWS)
+#elif defined(HOST_OS_WINDOWS)
   SetLastError(0);
   void* pointer = GetProcAddress(reinterpret_cast<HMODULE>(handle), symbol);
   if (pointer == nullptr) {
diff --git a/runtime/lib/ffi_patch.dart b/runtime/lib/ffi_patch.dart
index c8fde6c..6915d51 100644
--- a/runtime/lib/ffi_patch.dart
+++ b/runtime/lib/ffi_patch.dart
@@ -53,3 +53,21 @@
   @patch
   void free() native "Ffi_free";
 }
+
+// This method gets called when an exception bubbles up to the native -> Dart
+// boundary from an FFI native callback. Since native code does not have any
+// concept of exceptions, the exception cannot be propagated any further.
+// Instead, print a warning with the exception and return 0/0.0 from the
+// callback.
+//
+// TODO(36856): Iron out the story behind exceptions.
+@pragma("vm:entry-point")
+void _handleExposedException(dynamic exception, dynamic stackTrace) {
+  print(
+      "==================== UNHANDLED EXCEPTION FROM FFI CALLBACK ====================");
+  print(
+      """ ** Native callbacks should not throw exceptions because they cannot be
+    propagated into native code. **""");
+  print("EXCEPTION: $exception");
+  print(stackTrace);
+}
diff --git a/runtime/lib/ffi_sources.gni b/runtime/lib/ffi_sources.gni
index fd625f4..9936dd2 100644
--- a/runtime/lib/ffi_sources.gni
+++ b/runtime/lib/ffi_sources.gni
@@ -13,5 +13,3 @@
   "ffi_dynamic_library_patch.dart",
   "ffi_native_type_patch.dart",
 ]
-
-ffi_runtime_sources = ffi_runtime_cc_files + ffi_runtime_dart_files
diff --git a/runtime/lib/internal_sources.gni b/runtime/lib/internal_sources.gni
index d5550bc..7c173ab 100644
--- a/runtime/lib/internal_sources.gni
+++ b/runtime/lib/internal_sources.gni
@@ -13,6 +13,3 @@
   "print_patch.dart",
   "symbol_patch.dart",
 ]
-
-internal_runtime_sources =
-    internal_runtime_cc_files + internal_runtime_dart_files
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 55c61f8..84c2aed 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -4,6 +4,7 @@
 
 #include "include/dart_native_api.h"
 #include "platform/assert.h"
+#include "platform/unicode.h"
 #include "vm/bootstrap_natives.h"
 #include "vm/class_finalizer.h"
 #include "vm/dart.h"
@@ -21,7 +22,6 @@
 #include "vm/service.h"
 #include "vm/snapshot.h"
 #include "vm/symbols.h"
-#include "vm/unicode.h"
 
 namespace dart {
 
@@ -95,7 +95,7 @@
 
   if (ApiObjectConverter::CanConvert(obj.raw())) {
     PortMap::PostMessage(
-        new Message(destination_port_id, obj.raw(), Message::kNormalPriority));
+        Message::New(destination_port_id, obj.raw(), Message::kNormalPriority));
   } else {
     MessageWriter writer(can_send_any_object);
     // TODO(turnidge): Throw an exception when the return value is false?
@@ -113,14 +113,22 @@
 
 class SpawnIsolateTask : public ThreadPool::Task {
  public:
-  explicit SpawnIsolateTask(IsolateSpawnState* state) : state_(state) {}
+  SpawnIsolateTask(Isolate* parent_isolate, IsolateSpawnState* state)
+      : parent_isolate_(parent_isolate), state_(state) {
+    parent_isolate->IncrementSpawnCount();
+  }
 
-  virtual void Run() {
+  ~SpawnIsolateTask() override {
+    if (parent_isolate_) {
+      parent_isolate_->DecrementSpawnCount();
+    }
+  }
+
+  void Run() override {
     // Create a new isolate.
     char* error = NULL;
     Dart_IsolateCreateCallback callback = Isolate::CreateCallback();
     if (callback == NULL) {
-      state_->DecrementSpawnCount();
       ReportError(
           "Isolate spawn is not supported by this Dart implementation\n");
       delete state_;
@@ -135,9 +143,10 @@
     ASSERT(name != NULL);
 
     Isolate* isolate = reinterpret_cast<Isolate*>((callback)(
-        state_->script_url(), name, state_->package_root(),
-        state_->package_config(), &api_flags, state_->init_data(), &error));
-    state_->DecrementSpawnCount();
+        state_->script_url(), name, nullptr, state_->package_config(),
+        &api_flags, parent_isolate_->init_callback_data(), &error));
+    parent_isolate_->DecrementSpawnCount();
+    parent_isolate_ = nullptr;
     if (isolate == NULL) {
       ReportError(error);
       delete state_;
@@ -152,7 +161,7 @@
       isolate->set_origin_id(state_->origin_id());
     }
     MutexLocker ml(isolate->mutex());
-    state_->set_isolate(reinterpret_cast<Isolate*>(isolate));
+    state_->set_isolate(isolate);
     isolate->set_spawn_state(state_);
     state_ = NULL;
     if (isolate->is_runnable()) {
@@ -171,6 +180,7 @@
     }
   }
 
+  Isolate* parent_isolate_;
   IsolateSpawnState* state_;
 
   DISALLOW_COPY_AND_ASSIGN(SpawnIsolateTask);
@@ -223,29 +233,23 @@
             message, ILLEGAL_PORT, Message::kNormalPriority));
       }
 
-      // TODO(mfairhurst) remove package_root, as it no longer does anything.
-      const char* utf8_package_root = NULL;
       const char* utf8_package_config =
           packageConfig.IsNull() ? NULL : String2UTF8(packageConfig);
       const char* utf8_debug_name =
           debugName.IsNull() ? NULL : String2UTF8(debugName);
 
       IsolateSpawnState* state = new IsolateSpawnState(
-          port.Id(), isolate->origin_id(), isolate->init_callback_data(),
-          String2UTF8(script_uri), func, &message_buffer,
-          isolate->spawn_count_monitor(), isolate->spawn_count(),
-          utf8_package_root, utf8_package_config, paused.value(), fatal_errors,
+          port.Id(), isolate->origin_id(), String2UTF8(script_uri), func,
+          &message_buffer, utf8_package_config, paused.value(), fatal_errors,
           on_exit_port, on_error_port, utf8_debug_name);
 
       // Since this is a call to Isolate.spawn, copy the parent isolate's code.
       state->isolate_flags()->copy_parent_code = true;
 
-      ThreadPool::Task* spawn_task = new SpawnIsolateTask(state);
+      ThreadPool::Task* spawn_task = new SpawnIsolateTask(isolate, state);
 
-      isolate->IncrementSpawnCount();
       if (!Dart::thread_pool()->Run(spawn_task)) {
         // Running on the thread pool failed. Clean up everything.
-        state->DecrementSpawnCount();
         delete state;
         state = NULL;
         delete spawn_task;
@@ -351,19 +355,15 @@
     ThrowIsolateSpawnException(msg);
   }
 
-  // TODO(mfairhurst) remove package_root, as it no longer does anything.
-  const char* utf8_package_root = NULL;
   const char* utf8_package_config =
       packageConfig.IsNull() ? NULL : String2UTF8(packageConfig);
   const char* utf8_debug_name =
       debugName.IsNull() ? NULL : String2UTF8(debugName);
 
   IsolateSpawnState* state = new IsolateSpawnState(
-      port.Id(), isolate->init_callback_data(), canonical_uri,
-      utf8_package_root, utf8_package_config, &arguments_buffer,
-      &message_buffer, isolate->spawn_count_monitor(), isolate->spawn_count(),
-      paused.value(), fatal_errors, on_exit_port, on_error_port,
-      utf8_debug_name);
+      port.Id(), canonical_uri, utf8_package_config, &arguments_buffer,
+      &message_buffer, paused.value(), fatal_errors, on_exit_port,
+      on_error_port, utf8_debug_name);
 
   // If we were passed a value then override the default flags state for
   // checked mode.
@@ -375,12 +375,10 @@
   // Since this is a call to Isolate.spawnUri, don't copy the parent's code.
   state->isolate_flags()->copy_parent_code = false;
 
-  ThreadPool::Task* spawn_task = new SpawnIsolateTask(state);
+  ThreadPool::Task* spawn_task = new SpawnIsolateTask(isolate, state);
 
-  isolate->IncrementSpawnCount();
   if (!Dart::thread_pool()->Run(spawn_task)) {
     // Running on the thread pool failed. Clean up everything.
-    state->DecrementSpawnCount();
     delete state;
     state = NULL;
     delete spawn_task;
@@ -436,4 +434,120 @@
   return Object::null();
 }
 
+static void ExternalTypedDataFinalizer(void* isolate_callback_data,
+                                       Dart_WeakPersistentHandle handle,
+                                       void* peer) {
+  free(peer);
+}
+
+static intptr_t GetUint8SizeOrThrow(const Instance& instance) {
+  // From the Dart side we are guaranteed that the type of [instance] is a
+  // subtype of TypedData.
+  if (instance.IsTypedDataBase()) {
+    return TypedDataBase::Cast(instance).LengthInBytes();
+  }
+
+  // This can happen if [instance] is `null` or an instance of a 3rd party class
+  // which implements [TypedData].
+  Exceptions::ThrowArgumentError(instance);
+}
+
+DEFINE_NATIVE_ENTRY(TransferableTypedData_factory, 0, 2) {
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
+
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, array_instance,
+                               arguments->NativeArgAt(1));
+
+  Array& array = Array::Handle();
+  intptr_t array_length;
+  if (array_instance.IsGrowableObjectArray()) {
+    const auto& growable_array = GrowableObjectArray::Cast(array_instance);
+    array ^= growable_array.data();
+    array_length = growable_array.Length();
+  } else if (array_instance.IsArray()) {
+    array ^= Array::Cast(array_instance).raw();
+    array_length = array.Length();
+  } else {
+    Exceptions::ThrowArgumentError(array_instance);
+    UNREACHABLE();
+  }
+  Instance& instance = Instance::Handle();
+  unsigned long long total_bytes = 0;
+  const unsigned long kMaxBytes =
+      TypedData::MaxElements(kTypedDataUint8ArrayCid);
+  for (intptr_t i = 0; i < array_length; i++) {
+    instance ^= array.At(i);
+    total_bytes += GetUint8SizeOrThrow(instance);
+    if (total_bytes > kMaxBytes) {
+      const Array& error_args = Array::Handle(Array::New(3));
+      error_args.SetAt(0, array);
+      error_args.SetAt(1, String::Handle(String::New("data")));
+      error_args.SetAt(2,
+                       String::Handle(String::NewFormatted(
+                           "Aggregated list exceeds max size %ld", kMaxBytes)));
+      Exceptions::ThrowByType(Exceptions::kArgumentValue, error_args);
+      UNREACHABLE();
+    }
+  }
+
+  uint8_t* data = reinterpret_cast<uint8_t*>(malloc(total_bytes));
+  if (data == nullptr) {
+    const Instance& exception =
+        Instance::Handle(thread->isolate()->object_store()->out_of_memory());
+    Exceptions::Throw(thread, exception);
+    UNREACHABLE();
+  }
+  intptr_t offset = 0;
+  for (intptr_t i = 0; i < array_length; i++) {
+    instance ^= array.At(i);
+
+    {
+      NoSafepointScope no_safepoint;
+      const auto& typed_data = TypedDataBase::Cast(instance);
+      const intptr_t length_in_bytes = typed_data.LengthInBytes();
+
+      void* source = typed_data.DataAddr(0);
+      // The memory does not overlap.
+      memcpy(data + offset, source, length_in_bytes);
+      offset += length_in_bytes;
+    }
+  }
+  ASSERT(static_cast<unsigned long>(offset) == total_bytes);
+  return TransferableTypedData::New(data, total_bytes);
+}
+
+DEFINE_NATIVE_ENTRY(TransferableTypedData_materialize, 0, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(TransferableTypedData, t,
+                               arguments->NativeArgAt(0));
+
+  void* peer;
+  {
+    NoSafepointScope no_safepoint;
+    peer = thread->heap()->GetPeer(t.raw());
+    // Assume that object's Peer is only used to track transferrability state.
+    ASSERT(peer != nullptr);
+  }
+
+  TransferableTypedDataPeer* tpeer =
+      reinterpret_cast<TransferableTypedDataPeer*>(peer);
+  const intptr_t length = tpeer->length();
+  uint8_t* data = tpeer->data();
+  if (data == nullptr) {
+    const auto& error = String::Handle(String::New(
+        "Attempt to materialize object that was transferred already."));
+    Exceptions::ThrowArgumentError(error);
+    UNREACHABLE();
+  }
+  tpeer->ClearData();
+
+  const ExternalTypedData& typed_data = ExternalTypedData::Handle(
+      ExternalTypedData::New(kExternalTypedDataUint8ArrayCid, data, length,
+                             thread->heap()->SpaceForExternal(length)));
+  FinalizablePersistentHandle::New(thread->isolate(), typed_data,
+                                   /* peer= */ data,
+                                   &ExternalTypedDataFinalizer, length);
+  return typed_data.raw();
+}
+
 }  // namespace dart
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index cdd5394..7c28e91 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -7,12 +7,13 @@
 /// used by patches of that library. We plan to change this when we have a
 /// shared front end and simply use parts.
 
-import "dart:_internal" show VMLibraryHooks, patch;
+import "dart:_internal" show ClassID, VMLibraryHooks, patch;
 
 import "dart:async"
     show Completer, Future, Stream, StreamController, StreamSubscription, Timer;
 
 import "dart:collection" show HashMap;
+import "dart:typed_data" show ByteBuffer, TypedData, Uint8List;
 
 /// These are the additional parts of this patch library:
 // part "timer_impl.dart";
@@ -671,3 +672,33 @@
 
   static String _getCurrentRootUriStr() native "Isolate_getCurrentRootUriStr";
 }
+
+@patch
+abstract class TransferableTypedData {
+  @patch
+  factory TransferableTypedData.fromList(List<TypedData> chunks) {
+    if (chunks == null) {
+      throw ArgumentError(chunks);
+    }
+    final int cid = ClassID.getID(chunks);
+    if (cid != ClassID.cidArray &&
+        cid != ClassID.cidGrowableObjectArray &&
+        cid != ClassID.cidImmutableArray) {
+      chunks = List.unmodifiable(chunks);
+    }
+    return _TransferableTypedDataImpl(chunks);
+  }
+}
+
+@pragma("vm:entry-point")
+class _TransferableTypedDataImpl implements TransferableTypedData {
+  factory _TransferableTypedDataImpl(List<TypedData> list)
+      native "TransferableTypedData_factory";
+
+  ByteBuffer materialize() {
+    return _materializeIntoUint8List().buffer;
+  }
+
+  Uint8List _materializeIntoUint8List()
+      native "TransferableTypedData_materialize";
+}
diff --git a/runtime/lib/isolate_sources.gni b/runtime/lib/isolate_sources.gni
index 021e4eb..1495aaf 100644
--- a/runtime/lib/isolate_sources.gni
+++ b/runtime/lib/isolate_sources.gni
@@ -9,5 +9,3 @@
   "isolate_patch.dart",
   "timer_impl.dart",
 ]
-
-isolate_runtime_sources = isolate_runtime_cc_files + isolate_runtime_dart_files
diff --git a/runtime/lib/math_sources.gni b/runtime/lib/math_sources.gni
index 33f089e..986010d 100644
--- a/runtime/lib/math_sources.gni
+++ b/runtime/lib/math_sources.gni
@@ -5,5 +5,3 @@
 math_runtime_cc_files = [ "math.cc" ]
 
 math_runtime_dart_files = [ "math_patch.dart" ]
-
-math_runtime_sources = math_runtime_cc_files + math_runtime_dart_files
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 916649f..beb978b 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -159,14 +159,14 @@
   args.SetAt(2, owner_mirror);
 
   if (!has_extra_parameter_info) {
-    is_final ^= Bool::True().raw();
+    is_final = Bool::True().raw();
     default_value = Object::null();
     metadata = Object::null();
   }
 
   for (intptr_t i = 0; i < non_implicit_param_count; i++) {
-    pos ^= Smi::New(i);
-    name ^= func.ParameterNameAt(implicit_param_count + i);
+    pos = Smi::New(i);
+    name = func.ParameterNameAt(implicit_param_count + i);
     if (has_extra_parameter_info) {
       is_final ^= param_descriptor.At(i * Parser::kParameterEntrySize +
                                       Parser::kParameterIsFinalOffset);
@@ -186,7 +186,7 @@
     args.SetAt(6, is_final);
     args.SetAt(7, default_value);
     args.SetAt(8, metadata);
-    param ^= CreateMirror(Symbols::_LocalParameterMirror(), args);
+    param = CreateMirror(Symbols::_LocalParameterMirror(), args);
     results.SetAt(i, param);
   }
   results.MakeImmutable();
@@ -216,7 +216,7 @@
     type ^= args.TypeAt(i);
     ASSERT(type.IsTypeParameter());
     ASSERT(type.IsFinalized());
-    name ^= type.name();
+    name = type.name();
     result.SetAt(2 * i, name);
     result.SetAt(2 * i + 1, type);
   }
@@ -331,6 +331,23 @@
   return CreateMirror(Symbols::_LocalClassMirror(), args);
 }
 
+static bool IsCensoredLibrary(const String& url) {
+  static const char* const censored_libraries[] = {
+      "dart:_builtin",
+      "dart:_vmservice",
+      "dart:vmservice_io",
+  };
+  for (const char* censored_library : censored_libraries) {
+    if (url.Equals(censored_library)) {
+      return true;
+    }
+  }
+  if (!Api::IsFfiEnabled() && url.Equals(Symbols::DartFfi())) {
+    return true;
+  }
+  return false;
+}
+
 static RawInstance* CreateLibraryMirror(Thread* thread, const Library& lib) {
   Zone* zone = thread->zone();
   ASSERT(!lib.IsNull());
@@ -340,17 +357,9 @@
   str = lib.name();
   args.SetAt(1, str);
   str = lib.url();
-  const char* censored_libraries[] = {
-      "dart:_builtin",
-      "dart:_vmservice",
-      "dart:vmservice_io",
-      NULL,
-  };
-  for (intptr_t i = 0; censored_libraries[i] != NULL; i++) {
-    if (str.Equals(censored_libraries[i])) {
-      // Censored library (grumble).
-      return Instance::null();
-    }
+  if (IsCensoredLibrary(str)) {
+    // Censored library (grumble).
+    return Instance::null();
   }
   args.SetAt(2, str);
   return CreateMirror(Symbols::_LocalLibraryMirror(), args);
@@ -756,7 +765,7 @@
 
   intptr_t num_expected_type_arguments = args.Length();
   TypeArguments& type_args_obj = TypeArguments::Handle();
-  type_args_obj ^= TypeArguments::New(num_expected_type_arguments);
+  type_args_obj = TypeArguments::New(num_expected_type_arguments);
   AbstractType& type_arg = AbstractType::Handle();
   Instance& instance = Instance::Handle();
   for (intptr_t i = 0; i < args.Length(); i++) {
@@ -824,7 +833,7 @@
       // TODO(regis): Fully support generic functions.
       return Object::empty_array().raw();
     }
-    klass ^= TypeParameter::Cast(decl).parameterized_class();
+    klass = TypeParameter::Cast(decl).parameterized_class();
     library = klass.library();
   } else {
     return Object::empty_array().raw();
@@ -1117,8 +1126,8 @@
   // arguments have been provided, or all arguments are dynamic. Return a list
   // of typemirrors on dynamic in this case.
   if (args.IsNull()) {
-    arg_type ^= Object::dynamic_type().raw();
-    type_mirror ^= CreateTypeMirror(arg_type);
+    arg_type = Object::dynamic_type().raw();
+    type_mirror = CreateTypeMirror(arg_type);
     for (intptr_t i = 0; i < num_params; i++) {
       result.SetAt(i, type_mirror);
     }
@@ -1128,7 +1137,7 @@
   ASSERT(args.Length() >= num_params);
   const intptr_t num_inherited_args = args.Length() - num_params;
   for (intptr_t i = 0; i < num_params; i++) {
-    arg_type ^= args.TypeAt(i + num_inherited_args);
+    arg_type = args.TypeAt(i + num_inherited_args);
     type_mirror = CreateTypeMirror(arg_type);
     result.SetAt(i, type_mirror);
   }
@@ -1500,7 +1509,7 @@
   // We handle constructors in Dart code.
   ASSERT(!func.IsGenerativeConstructor());
   AbstractType& type = AbstractType::Handle(func.result_type());
-  type ^= type.Canonicalize();  // Instantiated signatures are not canonical.
+  type = type.Canonicalize();  // Instantiated signatures are not canonical.
   return InstantiateType(type, instantiator);
 }
 
@@ -1580,7 +1589,9 @@
   }
 
   ASSERT(!script.IsNull());
-  ASSERT(token_pos != TokenPosition::kNoSource);
+  if (token_pos == TokenPosition::kNoSource) {
+    return Instance::null();
+  }
 
   const String& uri = String::Handle(zone, script.url());
   intptr_t from_line = 0;
@@ -1616,7 +1627,7 @@
   const Function& func = Function::Handle(ref.GetFunctionReferent());
   AbstractType& type = AbstractType::Handle(
       func.ParameterTypeAt(func.NumImplicitParameters() + pos.Value()));
-  type ^= type.Canonicalize();  // Instantiated signatures are not canonical.
+  type = type.Canonicalize();  // Instantiated signatures are not canonical.
   return InstantiateType(type, instantiator);
 }
 
diff --git a/runtime/lib/mirrors_sources.gni b/runtime/lib/mirrors_sources.gni
index c3a51c5..e92dcf0 100644
--- a/runtime/lib/mirrors_sources.gni
+++ b/runtime/lib/mirrors_sources.gni
@@ -15,5 +15,3 @@
   "mirrors_impl.dart",
   "mirror_reference.dart",
 ]
-
-mirrors_runtime_sources = mirrors_runtime_cc_files + mirrors_runtime_dart_files
diff --git a/runtime/lib/profiler_sources.gni b/runtime/lib/profiler_sources.gni
index b27bc88..b2ff2ca 100644
--- a/runtime/lib/profiler_sources.gni
+++ b/runtime/lib/profiler_sources.gni
@@ -3,4 +3,4 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # Sources list to keep vm/BUILD.gn generate_core_libraries happy.
-profiler_runtime_sources = [ "empty_source.dart" ]
+profiler_runtime_dart_files = [ "empty_source.dart" ]
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index 4dba76e..eb4237c 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -14,7 +14,7 @@
 
 namespace dart {
 
-DEFINE_NATIVE_ENTRY(RegExp_factory, 0, 4) {
+DEFINE_NATIVE_ENTRY(RegExp_factory, 0, 6) {
   ASSERT(
       TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(1));
@@ -22,17 +22,30 @@
                                arguments->NativeArgAt(2));
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, handle_case_sensitive,
                                arguments->NativeArgAt(3));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, handle_unicode,
+                               arguments->NativeArgAt(4));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, handle_dot_all,
+                               arguments->NativeArgAt(5));
   bool ignore_case = handle_case_sensitive.raw() != Bool::True().raw();
   bool multi_line = handle_multi_line.raw() == Bool::True().raw();
+  bool unicode = handle_unicode.raw() == Bool::True().raw();
+  bool dot_all = handle_dot_all.raw() == Bool::True().raw();
+
+  RegExpFlags flags;
+
+  if (ignore_case) flags.SetIgnoreCase();
+  if (multi_line) flags.SetMultiLine();
+  if (unicode) flags.SetUnicode();
+  if (dot_all) flags.SetDotAll();
 
   // Parse the pattern once in order to throw any format exceptions within
   // the factory constructor. It is parsed again upon compilation.
   RegExpCompileData compileData;
   // Throws an exception on parsing failure.
-  RegExpParser::ParseRegExp(pattern, multi_line, &compileData);
+  RegExpParser::ParseRegExp(pattern, flags, &compileData);
 
   // Create a RegExp object containing only the initial parameters.
-  return RegExpEngine::CreateRegExp(thread, pattern, multi_line, ignore_case);
+  return RegExpEngine::CreateRegExp(thread, pattern, flags);
 }
 
 DEFINE_NATIVE_ENTRY(RegExp_getPattern, 0, 1) {
@@ -44,13 +57,25 @@
 DEFINE_NATIVE_ENTRY(RegExp_getIsMultiLine, 0, 1) {
   const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
-  return Bool::Get(regexp.is_multi_line()).raw();
+  return Bool::Get(regexp.flags().IsMultiLine()).raw();
+}
+
+DEFINE_NATIVE_ENTRY(RegExp_getIsUnicode, 0, 1) {
+  const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
+  ASSERT(!regexp.IsNull());
+  return Bool::Get(regexp.flags().IsUnicode()).raw();
+}
+
+DEFINE_NATIVE_ENTRY(RegExp_getIsDotAll, 0, 1) {
+  const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
+  ASSERT(!regexp.IsNull());
+  return Bool::Get(regexp.flags().IsDotAll()).raw();
 }
 
 DEFINE_NATIVE_ENTRY(RegExp_getIsCaseSensitive, 0, 1) {
   const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
-  return Bool::Get(!regexp.is_ignore_case()).raw();
+  return Bool::Get(!regexp.flags().IgnoreCase()).raw();
 }
 
 DEFINE_NATIVE_ENTRY(RegExp_getGroupCount, 0, 1) {
diff --git a/runtime/lib/regexp_patch.dart b/runtime/lib/regexp_patch.dart
index 4eac446..35a13b1 100644
--- a/runtime/lib/regexp_patch.dart
+++ b/runtime/lib/regexp_patch.dart
@@ -8,8 +8,12 @@
 class RegExp {
   @patch
   factory RegExp(String source,
-      {bool multiLine: false, bool caseSensitive: true}) {
-    _RegExpHashKey key = new _RegExpHashKey(source, multiLine, caseSensitive);
+      {bool multiLine: false,
+      bool caseSensitive: true,
+      bool unicode: false,
+      bool dotAll: false}) {
+    _RegExpHashKey key =
+        new _RegExpHashKey(source, multiLine, caseSensitive, unicode, dotAll);
     _RegExpHashValue value = _cache[key];
 
     if (value == null) {
@@ -21,7 +25,10 @@
 
       value = new _RegExpHashValue(
           new _RegExp(source,
-              multiLine: multiLine, caseSensitive: caseSensitive),
+              multiLine: multiLine,
+              caseSensitive: caseSensitive,
+              unicode: unicode,
+              dotAll: dotAll),
           key);
       _cache[key] = value;
     } else {
@@ -114,15 +121,20 @@
   final String pattern;
   final bool multiLine;
   final bool caseSensitive;
+  final bool unicode;
+  final bool dotAll;
 
-  _RegExpHashKey(this.pattern, this.multiLine, this.caseSensitive);
+  _RegExpHashKey(this.pattern, this.multiLine, this.caseSensitive, this.unicode,
+      this.dotAll);
 
   int get hashCode => pattern.hashCode;
   bool operator ==(that) {
     return (that is _RegExpHashKey) &&
         (this.pattern == that.pattern) &&
         (this.multiLine == that.multiLine) &&
-        (this.caseSensitive == that.caseSensitive);
+        (this.caseSensitive == that.caseSensitive) &&
+        (this.unicode == that.unicode) &&
+        (this.dotAll == that.dotAll);
   }
 }
 
@@ -200,9 +212,11 @@
 class _RegExp implements RegExp {
   factory _RegExp(String pattern,
       {bool multiLine: false,
-      bool caseSensitive: true}) native "RegExp_factory";
+      bool caseSensitive: true,
+      bool unicode: false,
+      bool dotAll: false}) native "RegExp_factory";
 
-  Match firstMatch(String str) {
+  RegExpMatch firstMatch(String str) {
     if (str is! String) throw new ArgumentError(str);
     List match = _ExecuteMatch(str, 0);
     if (match == null) {
@@ -211,7 +225,7 @@
     return new _RegExpMatch(this, str, match);
   }
 
-  Iterable<Match> allMatches(String string, [int start = 0]) {
+  Iterable<RegExpMatch> allMatches(String string, [int start = 0]) {
     if (string is! String) throw new ArgumentError(string);
     if (start is! int) throw new ArgumentError(start);
     if (0 > start || start > string.length) {
@@ -220,7 +234,7 @@
     return new _AllMatchesIterable(this, string, start);
   }
 
-  Match matchAsPrefix(String string, [int start = 0]) {
+  RegExpMatch matchAsPrefix(String string, [int start = 0]) {
     if (string is! String) throw new ArgumentError(string);
     if (start is! int) throw new ArgumentError(start);
     if (start < 0 || start > string.length) {
@@ -252,6 +266,10 @@
 
   bool get isCaseSensitive native "RegExp_getIsCaseSensitive";
 
+  bool get isUnicode native "RegExp_getIsUnicode";
+
+  bool get isDotAll native "RegExp_getIsDotAll";
+
   int get _groupCount native "RegExp_getGroupCount";
 
   // Returns a List [String, int, String, int, ...] where each
@@ -327,25 +345,34 @@
       native "RegExp_ExecuteMatchSticky";
 }
 
-class _AllMatchesIterable extends IterableBase<Match> {
+class _AllMatchesIterable extends IterableBase<RegExpMatch> {
   final _RegExp _re;
   final String _str;
   final int _start;
 
   _AllMatchesIterable(this._re, this._str, this._start);
 
-  Iterator<Match> get iterator => new _AllMatchesIterator(_re, _str, _start);
+  Iterator<RegExpMatch> get iterator =>
+      new _AllMatchesIterator(_re, _str, _start);
 }
 
-class _AllMatchesIterator implements Iterator<Match> {
+class _AllMatchesIterator implements Iterator<RegExpMatch> {
   final String _str;
   int _nextIndex;
   _RegExp _re;
-  Match _current;
+  RegExpMatch _current;
 
   _AllMatchesIterator(this._re, this._str, this._nextIndex);
 
-  Match get current => _current;
+  RegExpMatch get current => _current;
+
+  static bool _isLeadSurrogate(int c) {
+    return c >= 0xd800 && c <= 0xdbff;
+  }
+
+  static bool _isTrailSurrogate(int c) {
+    return c >= 0xdc00 && c <= 0xdfff;
+  }
 
   bool moveNext() {
     if (_re == null) return false; // Cleared after a failed match.
@@ -355,7 +382,15 @@
         _current = new _RegExpMatch(_re, _str, match);
         _nextIndex = _current.end;
         if (_nextIndex == _current.start) {
-          // Zero-width match. Advance by one more.
+          // Zero-width match. Advance by one more, unless the regexp
+          // is in unicode mode and it would put us within a surrogate
+          // pair. In that case, advance past the code point as a whole.
+          if (_re.isUnicode &&
+              _nextIndex + 1 < _str.length &&
+              _isLeadSurrogate(_str.codeUnitAt(_nextIndex)) &&
+              _isTrailSurrogate(_str.codeUnitAt(_nextIndex + 1))) {
+            _nextIndex++;
+          }
           _nextIndex++;
         }
         return true;
diff --git a/runtime/lib/stacktrace.cc b/runtime/lib/stacktrace.cc
index 0a412f2..b32490e 100644
--- a/runtime/lib/stacktrace.cc
+++ b/runtime/lib/stacktrace.cc
@@ -139,32 +139,37 @@
 static void AppendFrames(const GrowableObjectArray& code_list,
                          const GrowableObjectArray& pc_offset_list,
                          int skip_frames) {
-  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
-                            Thread::Current(),
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, thread,
                             StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
   ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
-  Code& code = Code::Handle();
-  Bytecode& bytecode = Bytecode::Handle();
-  Smi& offset = Smi::Handle();
-  while (frame != NULL) {
-    if (frame->IsDartFrame()) {
-      if (skip_frames > 0) {
-        skip_frames--;
-      } else {
-        if (frame->is_interpreted()) {
-          bytecode = frame->LookupDartBytecode();
-          offset = Smi::New(frame->pc() - bytecode.PayloadStart());
-          code_list.Add(bytecode);
-        } else {
-          code = frame->LookupDartCode();
-          offset = Smi::New(frame->pc() - code.PayloadStart());
-          code_list.Add(code);
-        }
-        pc_offset_list.Add(offset);
-      }
+  Code& code = Code::Handle(zone);
+  Bytecode& bytecode = Bytecode::Handle(zone);
+  Smi& offset = Smi::Handle(zone);
+  for (; frame != NULL; frame = frames.NextFrame()) {
+    if (!frame->IsDartFrame()) {
+      continue;
     }
-    frame = frames.NextFrame();
+    if (skip_frames > 0) {
+      skip_frames--;
+      continue;
+    }
+
+    if (frame->is_interpreted()) {
+      bytecode = frame->LookupDartBytecode();
+      if (bytecode.function() == Function::null()) {
+        continue;
+      }
+      offset = Smi::New(frame->pc() - bytecode.PayloadStart());
+      code_list.Add(bytecode);
+    } else {
+      code = frame->LookupDartCode();
+      offset = Smi::New(frame->pc() - code.PayloadStart());
+      code_list.Add(code);
+    }
+    pc_offset_list.Add(offset);
   }
 }
 
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 5402def..201fe2c 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -5,6 +5,7 @@
 #include "vm/bootstrap_natives.h"
 
 #include "include/dart_api.h"
+#include "platform/unicode.h"
 #include "vm/dart_api_impl.h"
 #include "vm/exceptions.h"
 #include "vm/isolate.h"
@@ -12,7 +13,6 @@
 #include "vm/object.h"
 #include "vm/object_store.h"
 #include "vm/symbols.h"
-#include "vm/unicode.h"
 
 namespace dart {
 
@@ -37,10 +37,10 @@
   intptr_t length;
   if (list.IsGrowableObjectArray()) {
     const GrowableObjectArray& growableArray = GrowableObjectArray::Cast(list);
-    a ^= growableArray.data();
+    a = growableArray.data();
     length = growableArray.Length();
   } else if (list.IsArray()) {
-    a ^= Array::Cast(list).raw();
+    a = Array::Cast(list).raw();
     length = a.Length();
   } else {
     Exceptions::ThrowArgumentError(list);
@@ -188,9 +188,9 @@
   const intptr_t base_length = base.Length();
   String& result = String::Handle(zone);
   if (is_onebyte) {
-    result ^= OneByteString::New(length, Heap::kNew);
+    result = OneByteString::New(length, Heap::kNew);
   } else {
-    result ^= TwoByteString::New(length, Heap::kNew);
+    result = TwoByteString::New(length, Heap::kNew);
   }
   Instance& object = Instance::Handle(zone);
   intptr_t write_index = 0;
diff --git a/runtime/lib/typed_data_sources.gni b/runtime/lib/typed_data_sources.gni
index 9892c8f..b10a829 100644
--- a/runtime/lib/typed_data_sources.gni
+++ b/runtime/lib/typed_data_sources.gni
@@ -9,6 +9,3 @@
 ]
 
 typed_data_runtime_dart_files = [ "typed_data_patch.dart" ]
-
-typed_data_runtime_sources =
-    typed_data_runtime_cc_files + typed_data_runtime_dart_files
diff --git a/runtime/lib/vmservice_sources.gni b/runtime/lib/vmservice_sources.gni
index a5e1131..b39e99b 100644
--- a/runtime/lib/vmservice_sources.gni
+++ b/runtime/lib/vmservice_sources.gni
@@ -3,4 +3,4 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # Sources that patch the library "dart:_vmservice".
-vmservice_runtime_sources = [ "vmservice.cc" ]
+vmservice_runtime_cc_files = [ "vmservice.cc" ]
diff --git a/runtime/observatory/lib/elements.dart b/runtime/observatory/lib/elements.dart
index 25ef536..5a57241 100644
--- a/runtime/observatory/lib/elements.dart
+++ b/runtime/observatory/lib/elements.dart
@@ -1,107 +1,5 @@
 library observatory_elements;
 
-import 'dart:async';
-
-import 'package:observatory/src/elements/allocation_profile.dart';
-import 'package:observatory/src/elements/class_allocation_profile.dart';
-import 'package:observatory/src/elements/class_instances.dart';
-import 'package:observatory/src/elements/class_ref.dart';
-import 'package:observatory/src/elements/class_tree.dart';
-import 'package:observatory/src/elements/class_view.dart';
-import 'package:observatory/src/elements/code_ref.dart';
-import 'package:observatory/src/elements/code_view.dart';
-import 'package:observatory/src/elements/containers/search_bar.dart';
-import 'package:observatory/src/elements/containers/virtual_collection.dart';
-import 'package:observatory/src/elements/containers/virtual_tree.dart';
-import 'package:observatory/src/elements/context_ref.dart';
-import 'package:observatory/src/elements/context_view.dart';
-import 'package:observatory/src/elements/cpu_profile.dart';
-import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
-import 'package:observatory/src/elements/cpu_profile_table.dart';
-import 'package:observatory/src/elements/curly_block.dart';
-import 'package:observatory/src/elements/debugger.dart';
-import 'package:observatory/src/elements/error_ref.dart';
-import 'package:observatory/src/elements/error_view.dart';
-import 'package:observatory/src/elements/eval_box.dart';
-import 'package:observatory/src/elements/field_ref.dart';
-import 'package:observatory/src/elements/field_view.dart';
-import 'package:observatory/src/elements/flag_list.dart';
-import 'package:observatory/src/elements/function_ref.dart';
-import 'package:observatory/src/elements/function_view.dart';
-import 'package:observatory/src/elements/general_error.dart';
-import 'package:observatory/src/elements/heap_map.dart';
-import 'package:observatory/src/elements/heap_snapshot.dart';
-import 'package:observatory/src/elements/icdata_ref.dart';
-import 'package:observatory/src/elements/icdata_view.dart';
-import 'package:observatory/src/elements/instance_ref.dart';
-import 'package:observatory/src/elements/instance_view.dart';
-import 'package:observatory/src/elements/isolate/counter_chart.dart';
-import 'package:observatory/src/elements/isolate/location.dart';
-import 'package:observatory/src/elements/isolate/run_state.dart';
-import 'package:observatory/src/elements/isolate/shared_summary.dart';
-import 'package:observatory/src/elements/isolate/summary.dart';
-import 'package:observatory/src/elements/isolate_reconnect.dart';
-import 'package:observatory/src/elements/isolate_ref.dart';
-import 'package:observatory/src/elements/isolate_view.dart';
-import 'package:observatory/src/elements/json_view.dart';
-import 'package:observatory/src/elements/library_ref.dart';
-import 'package:observatory/src/elements/library_view.dart';
-import 'package:observatory/src/elements/local_var_descriptors_ref.dart';
-import 'package:observatory/src/elements/logging.dart';
-import 'package:observatory/src/elements/megamorphiccache_ref.dart';
-import 'package:observatory/src/elements/megamorphiccache_view.dart';
-import 'package:observatory/src/elements/memory/dashboard.dart';
-import 'package:observatory/src/elements/memory/graph.dart';
-import 'package:observatory/src/elements/metric/details.dart';
-import 'package:observatory/src/elements/metric/graph.dart';
-import 'package:observatory/src/elements/metrics.dart';
-import 'package:observatory/src/elements/native_memory_profiler.dart';
-import 'package:observatory/src/elements/nav/class_menu.dart';
-import 'package:observatory/src/elements/nav/isolate_menu.dart';
-import 'package:observatory/src/elements/nav/library_menu.dart';
-import 'package:observatory/src/elements/nav/menu_item.dart';
-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';
-import 'package:observatory/src/elements/nav/refresh.dart';
-import 'package:observatory/src/elements/nav/top_menu.dart';
-import 'package:observatory/src/elements/nav/vm_menu.dart';
-import 'package:observatory/src/elements/object_common.dart';
-import 'package:observatory/src/elements/object_view.dart';
-import 'package:observatory/src/elements/objectpool_ref.dart';
-import 'package:observatory/src/elements/objectpool_view.dart';
-import 'package:observatory/src/elements/objectstore_view.dart';
-import 'package:observatory/src/elements/observatory_application.dart';
-import 'package:observatory/src/elements/pc_descriptors_ref.dart';
-import 'package:observatory/src/elements/persistent_handles.dart';
-import 'package:observatory/src/elements/ports.dart';
-import 'package:observatory/src/elements/sample_buffer_control.dart';
-import 'package:observatory/src/elements/script_inset.dart';
-import 'package:observatory/src/elements/script_ref.dart';
-import 'package:observatory/src/elements/script_view.dart';
-import 'package:observatory/src/elements/sentinel_value.dart';
-import 'package:observatory/src/elements/sentinel_view.dart';
-import 'package:observatory/src/elements/singletargetcache_ref.dart';
-import 'package:observatory/src/elements/singletargetcache_view.dart';
-import 'package:observatory/src/elements/source_inset.dart';
-import 'package:observatory/src/elements/source_link.dart';
-import 'package:observatory/src/elements/stack_trace_tree_config.dart';
-import 'package:observatory/src/elements/strongly_reachable_instances.dart';
-import 'package:observatory/src/elements/subtypetestcache_ref.dart';
-import 'package:observatory/src/elements/subtypetestcache_view.dart';
-import 'package:observatory/src/elements/timeline_page.dart';
-import 'package:observatory/src/elements/timeline/dashboard.dart';
-import 'package:observatory/src/elements/type_arguments_ref.dart';
-import 'package:observatory/src/elements/unknown_ref.dart';
-import 'package:observatory/src/elements/unlinkedcall_ref.dart';
-import 'package:observatory/src/elements/unlinkedcall_view.dart';
-import 'package:observatory/src/elements/view_footer.dart';
-import 'package:observatory/src/elements/vm_connect.dart';
-import 'package:observatory/src/elements/vm_connect_target.dart';
-import 'package:observatory/src/elements/vm_view.dart';
-
-export 'package:observatory/src/elements/helpers/rendering_queue.dart';
-
 export 'package:observatory/src/elements/allocation_profile.dart';
 export 'package:observatory/src/elements/class_allocation_profile.dart';
 export 'package:observatory/src/elements/class_instances.dart';
@@ -131,6 +29,7 @@
 export 'package:observatory/src/elements/general_error.dart';
 export 'package:observatory/src/elements/heap_map.dart';
 export 'package:observatory/src/elements/heap_snapshot.dart';
+export 'package:observatory/src/elements/helpers/rendering_queue.dart';
 export 'package:observatory/src/elements/icdata_ref.dart';
 export 'package:observatory/src/elements/icdata_view.dart';
 export 'package:observatory/src/elements/instance_ref.dart';
@@ -189,8 +88,8 @@
 export 'package:observatory/src/elements/strongly_reachable_instances.dart';
 export 'package:observatory/src/elements/subtypetestcache_ref.dart';
 export 'package:observatory/src/elements/subtypetestcache_view.dart';
-export 'package:observatory/src/elements/timeline_page.dart';
 export 'package:observatory/src/elements/timeline/dashboard.dart';
+export 'package:observatory/src/elements/timeline_page.dart';
 export 'package:observatory/src/elements/type_arguments_ref.dart';
 export 'package:observatory/src/elements/unknown_ref.dart';
 export 'package:observatory/src/elements/unlinkedcall_ref.dart';
@@ -199,112 +98,3 @@
 export 'package:observatory/src/elements/vm_connect.dart';
 export 'package:observatory/src/elements/vm_connect_target.dart';
 export 'package:observatory/src/elements/vm_view.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 {
-  AllocationProfileElement.tag.ensureRegistration();
-  ClassAllocationProfileElement.tag.ensureRegistration();
-  ClassInstancesElement.tag.ensureRegistration();
-  ClassRefElement.tag.ensureRegistration();
-  ClassTreeElement.tag.ensureRegistration();
-  ClassViewElement.tag.ensureRegistration();
-  CodeRefElement.tag.ensureRegistration();
-  CodeViewElement.tag.ensureRegistration();
-  ContextRefElement.tag.ensureRegistration();
-  ContextViewElement.tag.ensureRegistration();
-  CpuProfileElement.tag.ensureRegistration();
-  CpuProfileTableElement.tag.ensureRegistration();
-  CpuProfileVirtualTreeElement.tag.ensureRegistration();
-  CurlyBlockElement.tag.ensureRegistration();
-  DebuggerConsoleElement.tag.ensureRegistration();
-  DebuggerFrameElement.tag.ensureRegistration();
-  DebuggerInputElement.tag.ensureRegistration();
-  DebuggerMessageElement.tag.ensureRegistration();
-  DebuggerPageElement.tag.ensureRegistration();
-  DebuggerStackElement.tag.ensureRegistration();
-  ErrorRefElement.tag.ensureRegistration();
-  ErrorViewElement.tag.ensureRegistration();
-  EvalBoxElement.tag.ensureRegistration();
-  FieldRefElement.tag.ensureRegistration();
-  FieldViewElement.tag.ensureRegistration();
-  FlagListElement.tag.ensureRegistration();
-  FunctionRefElement.tag.ensureRegistration();
-  FunctionViewElement.tag.ensureRegistration();
-  GeneralErrorElement.tag.ensureRegistration();
-  HeapMapElement.tag.ensureRegistration();
-  HeapSnapshotElement.tag.ensureRegistration();
-  ICDataRefElement.tag.ensureRegistration();
-  ICDataViewElement.tag.ensureRegistration();
-  InstanceRefElement.tag.ensureRegistration();
-  InstanceViewElement.tag.ensureRegistration();
-  IsolateCounterChartElement.tag.ensureRegistration();
-  IsolateLocationElement.tag.ensureRegistration();
-  IsolateReconnectElement.tag.ensureRegistration();
-  IsolateRefElement.tag.ensureRegistration();
-  IsolateRunStateElement.tag.ensureRegistration();
-  IsolateSharedSummaryElement.tag.ensureRegistration();
-  IsolateSummaryElement.tag.ensureRegistration();
-  IsolateViewElement.tag.ensureRegistration();
-  JSONViewElement.tag.ensureRegistration();
-  LibraryRefElement.tag.ensureRegistration();
-  LibraryViewElement.tag.ensureRegistration();
-  LocalVarDescriptorsRefElement.tag.ensureRegistration();
-  LoggingPageElement.tag.ensureRegistration();
-  MegamorphicCacheRefElement.tag.ensureRegistration();
-  MegamorphicCacheViewElement.tag.ensureRegistration();
-  MemoryDashboardElement.tag.ensureRegistration();
-  MemoryGraphElement.tag.ensureRegistration();
-  MetricDetailsElement.tag.ensureRegistration();
-  MetricGraphElement.tag.ensureRegistration();
-  MetricsPageElement.tag.ensureRegistration();
-  NativeMemoryProfileElement.tag.ensureRegistration();
-  NavClassMenuElement.tag.ensureRegistration();
-  NavIsolateMenuElement.tag.ensureRegistration();
-  NavLibraryMenuElement.tag.ensureRegistration();
-  NavMenuItemElement.tag.ensureRegistration();
-  NavNotifyElement.tag.ensureRegistration();
-  NavNotifyEventElement.tag.ensureRegistration();
-  NavNotifyExceptionElement.tag.ensureRegistration();
-  NavRefreshElement.tag.ensureRegistration();
-  NavTopMenuElement.tag.ensureRegistration();
-  NavVMMenuElement.tag.ensureRegistration();
-  ObjectCommonElement.tag.ensureRegistration();
-  ObjectPoolRefElement.tag.ensureRegistration();
-  ObjectPoolViewElement.tag.ensureRegistration();
-  ObjectStoreViewElement.tag.ensureRegistration();
-  ObjectViewElement.tag.ensureRegistration();
-  ObservatoryApplicationElement.tag.ensureRegistration();
-  PcDescriptorsRefElement.tag.ensureRegistration();
-  PersistentHandlesPageElement.tag.ensureRegistration();
-  PortsElement.tag.ensureRegistration();
-  SampleBufferControlElement.tag.ensureRegistration();
-  ScriptInsetElement.tag.ensureRegistration();
-  ScriptRefElement.tag.ensureRegistration();
-  ScriptViewElement.tag.ensureRegistration();
-  SearchBarElement.tag.ensureRegistration();
-  SentinelValueElement.tag.ensureRegistration();
-  SentinelViewElement.tag.ensureRegistration();
-  SingleTargetCacheRefElement.tag.ensureRegistration();
-  SingleTargetCacheViewElement.tag.ensureRegistration();
-  SourceInsetElement.tag.ensureRegistration();
-  SourceLinkElement.tag.ensureRegistration();
-  StackTraceTreeConfigElement.tag.ensureRegistration();
-  StronglyReachableInstancesElement.tag.ensureRegistration();
-  SubtypeTestCacheRefElement.tag.ensureRegistration();
-  SubtypeTestCacheViewElement.tag.ensureRegistration();
-  TimelinePageElement.tag.ensureRegistration();
-  TimelineDashboardElement.tag.ensureRegistration();
-  TypeArgumentsRefElement.tag.ensureRegistration();
-  UnknownObjectRefElement.tag.ensureRegistration();
-  UnlinkedCallRefElement.tag.ensureRegistration();
-  UnlinkedCallViewElement.tag.ensureRegistration();
-  VMConnectElement.tag.ensureRegistration();
-  VMConnectTargetElement.tag.ensureRegistration();
-  VMViewElement.tag.ensureRegistration();
-  ViewFooterElement.tag.ensureRegistration();
-  VirtualCollectionElement.tag.ensureRegistration();
-  VirtualCollectionElement.tag.ensureRegistration();
-  VirtualTreeElement.tag.ensureRegistration();
-  VirtualTreeElement.tag.ensureRegistration();
-}
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 526e182..c03847f 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -133,7 +133,8 @@
   void onInstall() {
     if (element == null) {
       // Lazily create page.
-      element = new GeneralErrorElement(app.notifications, queue: app.queue);
+      element =
+          new GeneralErrorElement(app.notifications, queue: app.queue).element;
     }
   }
 
@@ -173,8 +174,9 @@
       VM vm = serviceObject;
       container.children = <Element>[
         new VMViewElement(vm, _vmrepository, app.events, app.notifications,
-            new IsolateRepository(app.vm), _scriptRepository,
-            queue: app.queue)
+                new IsolateRepository(app.vm), _scriptRepository,
+                queue: app.queue)
+            .element
       ];
     }).catchError((e, stack) {
       Logger.root.severe('VMPage visit error: $e');
@@ -190,8 +192,9 @@
   @override
   onInstall() {
     element = new FlagListElement(
-        app.vm, app.events, new FlagsRepository(app.vm), app.notifications,
-        queue: app.queue);
+            app.vm, app.events, new FlagsRepository(app.vm), app.notifications,
+            queue: app.queue)
+        .element;
   }
 
   void _visit(Uri uri) {
@@ -206,8 +209,9 @@
   onInstall() {
     if (element == null) {
       element = new NativeMemoryProfileElement(app.vm, app.events,
-          app.notifications, _nativeMemorySampleProfileRepository,
-          queue: app.queue);
+              app.notifications, _nativeMemorySampleProfileRepository,
+              queue: app.queue)
+          .element;
     }
     assert(element != null);
   }
@@ -247,247 +251,261 @@
     if (obj is Class) {
       container.children = <Element>[
         new ClassViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _classRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _fieldRepository,
-            _scriptRepository,
-            _objectRepository,
-            _evalRepository,
-            _stronglyReachangleInstancesRepository,
-            _topRetainingInstancesRepository,
-            _classSampleProfileRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _classRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _fieldRepository,
+                _scriptRepository,
+                _objectRepository,
+                _evalRepository,
+                _stronglyReachangleInstancesRepository,
+                _topRetainingInstancesRepository,
+                _classSampleProfileRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is Code) {
       await obj.loadScript();
       container.children = <Element>[
         new CodeViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _objectRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is Context) {
       container.children = <Element>[
         new ContextViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _contextRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _objectRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _contextRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is DartError) {
       container.children = <Element>[
-        new ErrorViewElement(app.notifications, obj, queue: app.queue)
+        new ErrorViewElement(app.notifications, obj, queue: app.queue).element
       ];
     } else if (obj is Field) {
       container.children = <Element>[
         new FieldViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _fieldRepository,
-            _classRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _scriptRepository,
-            _objectRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _fieldRepository,
+                _classRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _scriptRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is Instance) {
       container.children = <Element>[
         new InstanceViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _objectRepository,
-            _classRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _scriptRepository,
-            _evalRepository,
-            _typeArgumentsRepository,
-            _breakpointRepository,
-            _functionRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _objectRepository,
+                _classRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _scriptRepository,
+                _evalRepository,
+                _typeArgumentsRepository,
+                _breakpointRepository,
+                _functionRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is Isolate) {
       container.children = <Element>[
         new IsolateViewElement(
-            app.vm,
-            obj,
-            app.events,
-            app.notifications,
-            new IsolateRepository(app.vm),
-            _scriptRepository,
-            _functionRepository,
-            _libraryRepository,
-            _objectRepository,
-            _evalRepository,
-            queue: app.queue)
+                app.vm,
+                obj,
+                app.events,
+                app.notifications,
+                new IsolateRepository(app.vm),
+                _scriptRepository,
+                _functionRepository,
+                _libraryRepository,
+                _objectRepository,
+                _evalRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is ServiceFunction) {
       container.children = <Element>[
         new FunctionViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _functionRepository,
-            _classRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _scriptRepository,
-            _objectRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _functionRepository,
+                _classRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _scriptRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is ICData) {
       container.children = <Element>[
         new ICDataViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _icdataRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _objectRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _icdataRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is SingleTargetCache) {
       container.children = <Element>[
         new SingleTargetCacheViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _singleTargetCacheRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _objectRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _singleTargetCacheRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is SubtypeTestCache) {
       container.children = <Element>[
         new SubtypeTestCacheViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _subtypeTestCacheRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _objectRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _subtypeTestCacheRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is UnlinkedCall) {
       container.children = <Element>[
         new UnlinkedCallViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _unlinkedCallRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _objectRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _unlinkedCallRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is Library) {
       container.children = <Element>[
         new LibraryViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _libraryRepository,
-            _fieldRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _scriptRepository,
-            _objectRepository,
-            _evalRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _libraryRepository,
+                _fieldRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _scriptRepository,
+                _objectRepository,
+                _evalRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is MegamorphicCache) {
       container.children = <Element>[
         new MegamorphicCacheViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _megamorphicCacheRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _objectRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _megamorphicCacheRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is ObjectPool) {
       container.children = <Element>[
         new ObjectPoolViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _objectPoolRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _objectRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _objectPoolRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is Script) {
       var pos;
@@ -498,44 +516,47 @@
       }
       container.children = <Element>[
         new ScriptViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _scriptRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            _objectRepository,
-            pos: pos,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _scriptRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                pos: pos,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is HeapObject) {
       container.children = <Element>[
         new ObjectViewElement(
-            app.vm,
-            obj.isolate,
-            obj,
-            app.events,
-            app.notifications,
-            _objectRepository,
-            _retainedSizeRepository,
-            _reachableSizeRepository,
-            _inboundReferencesRepository,
-            _retainingPathRepository,
-            queue: app.queue)
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _objectRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                queue: app.queue)
+            .element
       ];
     } else if (obj is Sentinel) {
       container.children = <Element>[
         new SentinelViewElement(
-            app.vm, obj.isolate, obj, app.events, app.notifications,
-            queue: app.queue)
+                app.vm, obj.isolate, obj, app.events, app.notifications,
+                queue: app.queue)
+            .element
       ];
     } else {
       container.children = <Element>[
-        new JSONViewElement(obj, app.notifications, queue: app.queue)
+        new JSONViewElement(obj, app.notifications, queue: app.queue).element
       ];
     }
   }
@@ -556,8 +577,9 @@
     super._visit(uri);
     getIsolate(uri).then((isolate) {
       container.children = <Element>[
-        new ClassTreeElement(
-            app.vm, isolate, app.events, app.notifications, _classRepository)
+        new ClassTreeElement(app.vm, isolate, app.events, app.notifications,
+                _classRepository)
+            .element
       ];
     });
   }
@@ -573,7 +595,8 @@
     getIsolate(uri).then((isolate) async {
       container.children = <Element>[
         new DebuggerPageElement(
-            isolate, _objectRepository, _scriptRepository, app.events)
+                isolate, _objectRepository, _scriptRepository, app.events)
+            .element
       ];
     });
   }
@@ -602,7 +625,8 @@
     getIsolate(uri).then((isolate) async {
       container.children = <Element>[
         new ObjectStoreViewElement(isolate.vm, isolate, app.events,
-            app.notifications, _objectstoreRepository, _objectRepository)
+                app.notifications, _objectstoreRepository, _objectRepository)
+            .element
       ];
     });
   }
@@ -625,7 +649,8 @@
     getIsolate(uri).then((isolate) {
       container.children = <Element>[
         new CpuProfileElement(isolate.vm, isolate, app.events,
-            app.notifications, _isolateSampleProfileRepository)
+                app.notifications, _isolateSampleProfileRepository)
+            .element
       ];
     });
   }
@@ -648,7 +673,8 @@
     getIsolate(uri).then((isolate) {
       container.children = <Element>[
         new CpuProfileTableElement(isolate.vm, isolate, app.events,
-            app.notifications, _isolateSampleProfileRepository)
+                app.notifications, _isolateSampleProfileRepository)
+            .element
       ];
     });
   }
@@ -671,8 +697,9 @@
     getIsolate(uri).then((isolate) {
       container.children = <Element>[
         new AllocationProfileElement(isolate.vm, isolate, app.events,
-            app.notifications, _allocationProfileRepository,
-            queue: app.queue)
+                app.notifications, _allocationProfileRepository,
+                queue: app.queue)
+            .element
       ];
     });
   }
@@ -712,16 +739,17 @@
       await Future.wait(vm.isolates.map((i) => i.load()));
       container.children = <Element>[
         new MemoryDashboardElement(
-            vm,
-            _vmrepository,
-            new IsolateRepository(vm),
-            editor,
-            _allocationProfileRepository,
-            _heapSnapshotRepository,
-            _objectRepository,
-            app.events,
-            app.notifications,
-            queue: app.queue)
+                vm,
+                _vmrepository,
+                new IsolateRepository(vm),
+                editor,
+                _allocationProfileRepository,
+                _heapSnapshotRepository,
+                _objectRepository,
+                app.events,
+                app.notifications,
+                queue: app.queue)
+            .element
       ];
     }).catchError((e, stack) {
       Logger.root.severe('MemoryDashboard visit error: $e');
@@ -755,8 +783,9 @@
     getIsolate(uri).then((isolate) {
       container.children = <Element>[
         new PortsElement(isolate.vm, isolate, app.events, app.notifications,
-            _portsRepository, _objectRepository,
-            queue: app.queue)
+                _portsRepository, _objectRepository,
+                queue: app.queue)
+            .element
       ];
     });
   }
@@ -777,9 +806,15 @@
     super._visit(uri);
     getIsolate(uri).then((isolate) {
       container.children = <Element>[
-        new PersistentHandlesPageElement(isolate.vm, isolate, app.events,
-            app.notifications, _persistentHandlesRepository, _objectRepository,
-            queue: app.queue)
+        new PersistentHandlesPageElement(
+                isolate.vm,
+                isolate,
+                app.events,
+                app.notifications,
+                _persistentHandlesRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
       ];
     });
   }
@@ -801,7 +836,8 @@
     getIsolate(uri).then((isolate) {
       container.children = <Element>[
         new HeapMapElement(isolate.vm, isolate, app.events, app.notifications,
-            queue: app.queue)
+                queue: app.queue)
+            .element
       ];
     });
   }
@@ -823,8 +859,9 @@
     getIsolate(uri).then((isolate) {
       container.children = <Element>[
         new HeapSnapshotElement(isolate.vm, isolate, app.events,
-            app.notifications, _heapSnapshotRepository, _objectRepository,
-            queue: app.queue)
+                app.notifications, _heapSnapshotRepository, _objectRepository,
+                queue: app.queue)
+            .element
       ];
     });
   }
@@ -861,7 +898,8 @@
     getIsolate(uri).then((isolate) {
       container.children = <Element>[
         new LoggingPageElement(app.vm, isolate, app.events, app.notifications,
-            queue: app.queue)
+                queue: app.queue)
+            .element
       ];
     });
   }
@@ -872,8 +910,9 @@
 
   void onInstall() {
     element = new ErrorViewElement(
-        app.notifications, app.lastErrorOrException as DartError,
-        queue: app.queue);
+            app.notifications, app.lastErrorOrException as DartError,
+            queue: app.queue)
+        .element;
   }
 
   void _visit(Uri uri) {
@@ -891,8 +930,9 @@
   void onInstall() {
     if (element == null) {
       element = new VMConnectElement(ObservatoryApplication.app.targets,
-          ObservatoryApplication.app.notifications,
-          queue: ObservatoryApplication.app.queue);
+              ObservatoryApplication.app.notifications,
+              queue: ObservatoryApplication.app.queue)
+          .element;
     }
     assert(element != null);
   }
@@ -918,11 +958,12 @@
     app.vm.reload();
     container.children = <Element>[
       new IsolateReconnectElement(
-          app.vm,
-          app.events,
-          app.notifications,
-          uri.queryParameters['isolateId'],
-          Uri.parse(uri.queryParameters['originalUri']))
+              app.vm,
+              app.events,
+              app.notifications,
+              uri.queryParameters['isolateId'],
+              Uri.parse(uri.queryParameters['originalUri']))
+          .element
     ];
     assert(element != null);
     assert(canVisit(uri));
@@ -946,8 +987,9 @@
       await _metricRepository.startSampling(isolate);
       container.children = <Element>[
         new MetricsPageElement(isolate.vm, isolate, app.events,
-            app.notifications, _metricRepository,
-            queue: app.queue)
+                app.notifications, _metricRepository,
+                queue: app.queue)
+            .element
       ];
     });
   }
@@ -971,8 +1013,9 @@
 
   void onInstall() {
     element = new TimelinePageElement(
-        app.vm, _timelineRepository, app.events, app.notifications,
-        queue: app.queue);
+            app.vm, _timelineRepository, app.events, app.notifications,
+            queue: app.queue)
+        .element;
   }
 
   void _visit(Uri uri) {
@@ -998,8 +1041,9 @@
     app.vm.load().then((_) {
       container.children = <Element>[
         new TimelineDashboardElement(
-            app.vm, _timelineRepository, app.notifications,
-            queue: app.queue)
+                app.vm, _timelineRepository, app.notifications,
+                queue: app.queue)
+            .element
       ];
     });
   }
diff --git a/runtime/observatory/lib/src/elements/allocation_profile.dart b/runtime/observatory/lib/src/elements/allocation_profile.dart
index d1e4f86..b4ddc92 100644
--- a/runtime/observatory/lib/src/elements/allocation_profile.dart
+++ b/runtime/observatory/lib/src/elements/allocation_profile.dart
@@ -38,7 +38,7 @@
 
 enum _SortingDirection { ascending, descending }
 
-class AllocationProfileElement extends HtmlElement implements Renderable {
+class AllocationProfileElement extends CustomElement implements Renderable {
   static const tag = const Tag<AllocationProfileElement>('allocation-profile',
       dependencies: const [
         ClassRefElement.tag,
@@ -83,7 +83,7 @@
     assert(events != null);
     assert(notifications != null);
     assert(repository != null);
-    AllocationProfileElement e = document.createElement(tag.name);
+    AllocationProfileElement e = new AllocationProfileElement.created();
     e._r = new RenderingScheduler<AllocationProfileElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -93,7 +93,7 @@
     return e;
   }
 
-  AllocationProfileElement.created() : super.created();
+  AllocationProfileElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -118,19 +118,23 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('allocation profile'),
-        new NavRefreshElement(
-            label: 'Download', disabled: _profile == null, queue: _r.queue)
-          ..onRefresh.listen((_) => _downloadCSV()),
-        new NavRefreshElement(label: 'Reset Accumulator', queue: _r.queue)
-          ..onRefresh.listen((_) => _refresh(reset: true)),
-        new NavRefreshElement(label: 'GC', queue: _r.queue)
-          ..onRefresh.listen((_) => _refresh(gc: true)),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((_) => _refresh()),
+        (new NavRefreshElement(
+                label: 'Download', disabled: _profile == null, queue: _r.queue)
+              ..onRefresh.listen((_) => _downloadCSV()))
+            .element,
+        (new NavRefreshElement(label: 'Reset Accumulator', queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh(reset: true)))
+            .element,
+        (new NavRefreshElement(label: 'GC', queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh(gc: true)))
+            .element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh()))
+            .element,
         new DivElement()
           ..classes = ['nav-option']
           ..children = <Element>[
@@ -142,7 +146,7 @@
               ..htmlFor = 'allocation-profile-auto-refresh'
               ..text = 'Auto-refresh on GC'
           ],
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -252,11 +256,12 @@
           ..classes = _isCompacted ? ['collection', 'expanded'] : ['collection']
           ..children = <Element>[
             new VirtualCollectionElement(
-                _createCollectionLine, _updateCollectionLine,
-                createHeader: _createCollectionHeader,
-                search: _search,
-                items: _profile.members.toList()..sort(_createSorter()),
-                queue: _r.queue)
+                    _createCollectionLine, _updateCollectionLine,
+                    createHeader: _createCollectionHeader,
+                    search: _search,
+                    items: _profile.members.toList()..sort(_createSorter()),
+                    queue: _r.queue)
+                .element
           ]
       ]);
       _renderGraph(newChartHost, newChartLegend, _profile.newSpace);
@@ -476,6 +481,7 @@
     e.children[10].text = Utils.formatSize(_getOldCurrentSize(item));
     e.children[11].text = '${_getOldCurrentInstances(item)}';
     e.children[12] = new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
+        .element
       ..classes = ['name'];
   }
 
diff --git a/runtime/observatory/lib/src/elements/class_allocation_profile.dart b/runtime/observatory/lib/src/elements/class_allocation_profile.dart
index 60dadc3..f9d3e2e 100644
--- a/runtime/observatory/lib/src/elements/class_allocation_profile.dart
+++ b/runtime/observatory/lib/src/elements/class_allocation_profile.dart
@@ -11,7 +11,8 @@
 import 'package:observatory/src/elements/sample_buffer_control.dart';
 import 'package:observatory/src/elements/stack_trace_tree_config.dart';
 
-class ClassAllocationProfileElement extends HtmlElement implements Renderable {
+class ClassAllocationProfileElement extends CustomElement
+    implements Renderable {
   static const tag = const Tag<ClassAllocationProfileElement>(
       'class-allocation-profile',
       dependencies: const [
@@ -45,7 +46,8 @@
     assert(isolate != null);
     assert(cls != null);
     assert(profiles != null);
-    ClassAllocationProfileElement e = document.createElement(tag.name);
+    ClassAllocationProfileElement e =
+        new ClassAllocationProfileElement.created();
     e._r =
         new RenderingScheduler<ClassAllocationProfileElement>(e, queue: queue);
     e._vm = vm;
@@ -55,7 +57,7 @@
     return e;
   }
 
-  ClassAllocationProfileElement.created() : super.created();
+  ClassAllocationProfileElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -77,31 +79,34 @@
       return;
     }
     final content = <HtmlElement>[
-      new SampleBufferControlElement(_vm, _progress, _progressStream,
-          selectedTag: _tag, queue: _r.queue)
-        ..onTagChange.listen((e) {
-          _tag = e.element.selectedTag;
-          _request(forceFetch: true);
-        })
+      (new SampleBufferControlElement(_vm, _progress, _progressStream,
+              selectedTag: _tag, queue: _r.queue)
+            ..onTagChange.listen((e) {
+              _tag = e.element.selectedTag;
+              _request(forceFetch: true);
+            }))
+          .element
     ];
     if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
       CpuProfileVirtualTreeElement tree;
       content.addAll([
         new BRElement(),
-        new StackTraceTreeConfigElement(
-            mode: _mode,
-            direction: _direction,
-            showFilter: false,
-            queue: _r.queue)
-          ..onModeChange.listen((e) {
-            _mode = tree.mode = e.element.mode;
-          })
-          ..onDirectionChange.listen((e) {
-            _direction = tree.direction = e.element.direction;
-          }),
+        (new StackTraceTreeConfigElement(
+                mode: _mode,
+                direction: _direction,
+                showFilter: false,
+                queue: _r.queue)
+              ..onModeChange.listen((e) {
+                _mode = tree.mode = e.element.mode;
+              })
+              ..onDirectionChange.listen((e) {
+                _direction = tree.direction = e.element.direction;
+              }))
+            .element,
         new BRElement(),
-        tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
-            queue: _r.queue)
+        (tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
+                queue: _r.queue))
+            .element
       ]);
     }
     children = content;
diff --git a/runtime/observatory/lib/src/elements/class_instances.dart b/runtime/observatory/lib/src/elements/class_instances.dart
index beb1049..0ddb4e0 100644
--- a/runtime/observatory/lib/src/elements/class_instances.dart
+++ b/runtime/observatory/lib/src/elements/class_instances.dart
@@ -15,7 +15,7 @@
 import 'package:observatory/src/elements/top_retaining_instances.dart';
 import 'package:observatory/utils.dart';
 
-class ClassInstancesElement extends HtmlElement implements Renderable {
+class ClassInstancesElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<ClassInstancesElement>('class-instances', dependencies: const [
     ClassRefElement.tag,
@@ -59,7 +59,7 @@
     assert(stronglyReachableInstances != null);
     assert(topRetainingInstances != null);
     assert(objects != null);
-    ClassInstancesElement e = document.createElement(tag.name);
+    ClassInstancesElement e = new ClassInstancesElement.created();
     e._r = new RenderingScheduler<ClassInstancesElement>(e, queue: queue);
     e._isolate = isolate;
     e._cls = cls;
@@ -71,7 +71,7 @@
     return e;
   }
 
-  ClassInstancesElement.created() : super.created();
+  ClassInstancesElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -100,8 +100,8 @@
             queue: _r.queue);
     final instanceCount =
         _cls.newSpace.current.instances + _cls.oldSpace.current.instances;
-    final size = Utils
-        .formatSize(_cls.newSpace.current.bytes + _cls.oldSpace.current.bytes);
+    final size = Utils.formatSize(
+        _cls.newSpace.current.bytes + _cls.oldSpace.current.bytes);
     children = <Element>[
       new DivElement()
         ..classes = ['memberList']
@@ -124,7 +124,7 @@
                 ..text = 'strongly reachable ',
               new DivElement()
                 ..classes = ['memberValue']
-                ..children = <Element>[_strong]
+                ..children = <Element>[_strong.element]
             ],
           new DivElement()
             ..classes = ['memberItem']
@@ -158,7 +158,7 @@
                 ..text = 'toplist by retained memory ',
               new DivElement()
                 ..classes = ['memberValue']
-                ..children = <Element>[_topRetainig]
+                ..children = <Element>[_topRetainig.element]
             ]
         ]
     ];
@@ -168,12 +168,13 @@
     final content = <Element>[];
     if (_reachableSize != null) {
       if (_reachableSize.isSentinel) {
-        content.add(new SentinelValueElement(_reachableSize.asSentinel,
-            queue: _r.queue));
+        content.add(
+            new SentinelValueElement(_reachableSize.asSentinel, queue: _r.queue)
+                .element);
       } else {
         content.add(new SpanElement()
-          ..text = Utils
-              .formatSize(int.parse(_reachableSize.asValue.valueAsString)));
+          ..text = Utils.formatSize(
+              int.parse(_reachableSize.asValue.valueAsString)));
       }
     } else {
       content.add(new SpanElement()..text = '...');
@@ -196,8 +197,9 @@
     final content = <Element>[];
     if (_retainedSize != null) {
       if (_retainedSize.isSentinel) {
-        content.add(new SentinelValueElement(_retainedSize.asSentinel,
-            queue: _r.queue));
+        content.add(
+            new SentinelValueElement(_retainedSize.asSentinel, queue: _r.queue)
+                .element);
       } else {
         content.add(new SpanElement()
           ..text =
diff --git a/runtime/observatory/lib/src/elements/class_ref.dart b/runtime/observatory/lib/src/elements/class_ref.dart
index eee3cb6..409dddb 100644
--- a/runtime/observatory/lib/src/elements/class_ref.dart
+++ b/runtime/observatory/lib/src/elements/class_ref.dart
@@ -9,7 +9,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class ClassRefElement extends HtmlElement implements Renderable {
+class ClassRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<ClassRefElement>('class-ref');
 
   RenderingScheduler<ClassRefElement> _r;
@@ -25,14 +25,14 @@
   factory ClassRefElement(M.IsolateRef isolate, M.ClassRef cls,
       {RenderingQueue queue}) {
     assert(cls != null);
-    ClassRefElement e = document.createElement(tag.name);
+    ClassRefElement e = new ClassRefElement.created();
     e._r = new RenderingScheduler<ClassRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._class = cls;
     return e;
   }
 
-  ClassRefElement.created() : super.created();
+  ClassRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/class_tree.dart b/runtime/observatory/lib/src/elements/class_tree.dart
index 505eef9..83c3182 100644
--- a/runtime/observatory/lib/src/elements/class_tree.dart
+++ b/runtime/observatory/lib/src/elements/class_tree.dart
@@ -18,7 +18,7 @@
 import 'package:observatory/src/elements/nav/top_menu.dart';
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 
-class ClassTreeElement extends HtmlElement implements Renderable {
+class ClassTreeElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<ClassTreeElement>('class-tree', dependencies: const [
     ClassRefElement.tag,
@@ -54,7 +54,7 @@
     assert(events != null);
     assert(notifications != null);
     assert(classes != null);
-    ClassTreeElement e = document.createElement(tag.name);
+    ClassTreeElement e = new ClassTreeElement.created();
     e._r = new RenderingScheduler<ClassTreeElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -64,7 +64,7 @@
     return e;
   }
 
-  ClassTreeElement.created() : super.created();
+  ClassTreeElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -85,11 +85,11 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('class hierarchy'),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered']
@@ -109,7 +109,7 @@
     _tree = new VirtualTreeElement(_create, _update, _children,
         items: [_object], search: _search, queue: _r.queue);
     _tree.expand(_object, autoExpandSingleChildNodes: true);
-    return _tree;
+    return _tree.element;
   }
 
   Future _refresh() async {
@@ -164,7 +164,7 @@
       el.children[1].text = _tree.isExpanded(cls) ? '▼' : '►';
     }
     el.children[2].children = <Element>[
-      new ClassRefElement(_isolate, cls, queue: _r.queue)
+      new ClassRefElement(_isolate, cls, queue: _r.queue).element
     ];
     if (_mixins[cls.id] != null) {
       el.children[2].children.addAll(_createMixins(_mixins[cls.id]));
@@ -183,7 +183,8 @@
               type.typeClass == null
                   ? (new SpanElement()..text = type.name.split('<').first)
                   : new ClassRefElement(_isolate, type.typeClass,
-                      queue: _r.queue)
+                          queue: _r.queue)
+                      .element
             ])
         .toList();
     children.first.text = ' with ';
diff --git a/runtime/observatory/lib/src/elements/class_view.dart b/runtime/observatory/lib/src/elements/class_view.dart
index f2ceec0..fc8254e 100644
--- a/runtime/observatory/lib/src/elements/class_view.dart
+++ b/runtime/observatory/lib/src/elements/class_view.dart
@@ -32,7 +32,7 @@
 import 'package:observatory/src/elements/source_link.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class ClassViewElement extends HtmlElement implements Renderable {
+class ClassViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<ClassViewElement>('class-view', dependencies: const [
     ClassInstancesElement.tag,
@@ -120,7 +120,7 @@
     assert(stronglyReachable != null);
     assert(topRetained != null);
     assert(profiles != null);
-    ClassViewElement e = document.createElement(tag.name);
+    ClassViewElement e = new ClassViewElement.created();
     e._r = new RenderingScheduler<ClassViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -142,7 +142,7 @@
     return e;
   }
 
-  ClassViewElement.created() : super.created();
+  ClassViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -186,34 +186,36 @@
     }
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
-        new NavClassMenuElement(_isolate, _cls, queue: _r.queue),
-        new NavRefreshElement(
-            label: 'Refresh Allocation Profile', queue: _r.queue)
-          ..onRefresh.listen((e) {
-            e.element.disabled = true;
-            _loadProfile = true;
-            _r.dirty();
-          }),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) {
-            e.element.disabled = true;
-            _common = null;
-            _classInstances = null;
-            _fieldsExpanded = null;
-            _functionsExpanded = null;
-            _refresh();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        new NavClassMenuElement(_isolate, _cls, queue: _r.queue).element,
+        (new NavRefreshElement(
+                label: 'Refresh Allocation Profile', queue: _r.queue)
+              ..onRefresh.listen((e) {
+                e.element.disabled = true;
+                _loadProfile = true;
+                _r.dirty();
+              }))
+            .element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) {
+                e.element.disabled = true;
+                _common = null;
+                _classInstances = null;
+                _fieldsExpanded = null;
+                _functionsExpanded = null;
+                _refresh();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
         ..children = <Element>[
           new HeadingElement.h2()..text = '$header class ${_cls.name}',
           new HRElement(),
-          _common,
+          _common.element,
           new BRElement(),
           new DivElement()
             ..classes = ['memberList']
@@ -223,10 +225,11 @@
                 ? const []
                 : [
                     new HRElement(),
-                    new ErrorRefElement(_cls.error, queue: _r.queue)
+                    new ErrorRefElement(_cls.error, queue: _r.queue).element
                   ],
           new HRElement(),
-          new EvalBoxElement(_isolate, _cls, _objects, _eval, queue: _r.queue),
+          new EvalBoxElement(_isolate, _cls, _objects, _eval, queue: _r.queue)
+              .element,
           new HRElement(),
           new HeadingElement.h2()..text = 'Fields & Functions',
           new DivElement()
@@ -235,7 +238,8 @@
           new HRElement(),
           new HeadingElement.h2()..text = 'Instances',
           new DivElement()
-            ..children = _cls.hasAllocations ? [_classInstances] : const [],
+            ..children =
+                _cls.hasAllocations ? [_classInstances.element] : const [],
           new HRElement(),
           new HeadingElement.h2()..text = 'Allocations',
           new DivElement()
@@ -273,21 +277,23 @@
             ..children = _loadProfile
                 ? [
                     new ClassAllocationProfileElement(
-                        _vm, _isolate, _cls, _profiles,
-                        queue: _r.queue)
+                            _vm, _isolate, _cls, _profiles,
+                            queue: _r.queue)
+                        .element
                   ]
                 : const [],
           new DivElement()
             ..children = _cls.location != null
                 ? [
                     new HRElement(),
-                    new SourceInsetElement(
-                        _isolate, _cls.location, _scripts, _objects, _events,
-                        queue: _r.queue)
+                    new SourceInsetElement(_isolate, _cls.location, _scripts,
+                            _objects, _events,
+                            queue: _r.queue)
+                        .element
                   ]
                 : const [],
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
@@ -308,6 +314,7 @@
             ..classes = ['memberValue']
             ..children = <Element>[
               new LibraryRefElement(_isolate, _cls.library, queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -322,7 +329,8 @@
             ..classes = ['memberValue']
             ..children = <Element>[
               new SourceLinkElement(_isolate, _cls.location, _scripts,
-                  queue: _r.queue)
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -337,6 +345,7 @@
             ..classes = ['memberValue']
             ..children = <Element>[
               new ClassRefElement(_isolate, _cls.superclass, queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -351,7 +360,8 @@
             ..classes = ['memberValue']
             ..children = <Element>[
               new InstanceRefElement(_isolate, _cls.superType, _objects,
-                  queue: _r.queue)
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -366,7 +376,8 @@
             ..classes = ['memberValue']
             ..children = <Element>[
               new InstanceRefElement(_isolate, _cls.mixin, _objects,
-                  queue: _r.queue)
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -381,7 +392,8 @@
             ..classes = ['memberValue']
             ..children = (_cls.subclasses
                 .expand((subcls) => <Element>[
-                      new ClassRefElement(_isolate, subcls, queue: _r.queue),
+                      new ClassRefElement(_isolate, subcls, queue: _r.queue)
+                          .element,
                       new SpanElement()..text = ', '
                     ])
                 .toList()
@@ -403,7 +415,8 @@
             ..children = (_cls.interfaces
                 .expand((interf) => <Element>[
                       new InstanceRefElement(_isolate, interf, _objects,
-                          queue: _r.queue),
+                              queue: _r.queue)
+                          .element,
                       new SpanElement()..text = ', '
                     ])
                 .toList()
@@ -439,32 +452,36 @@
           new DivElement()
             ..classes = ['memberValue']
             ..children = <Element>[
-              new CurlyBlockElement(expanded: _fieldsExpanded)
-                ..onToggle.listen((e) => _fieldsExpanded = e.control.expanded)
-                ..content = <Element>[
-                  new DivElement()
-                    ..classes = ['memberList']
-                    ..children = (fields
-                        .map<Element>((f) => new DivElement()
-                          ..classes = ['memberItem']
-                          ..children = <Element>[
-                            new DivElement()
-                              ..classes = ['memberName']
+              (new CurlyBlockElement(expanded: _fieldsExpanded)
+                    ..onToggle
+                        .listen((e) => _fieldsExpanded = e.control.expanded)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = (fields
+                            .map<Element>((f) => new DivElement()
+                              ..classes = ['memberItem']
                               ..children = <Element>[
-                                new FieldRefElement(_isolate, f, _objects,
-                                    queue: _r.queue)
-                              ],
-                            new DivElement()
-                              ..classes = ['memberValue']
-                              ..children = f.staticValue == null
-                                  ? const []
-                                  : [
-                                      anyRef(_isolate, f.staticValue, _objects,
-                                          queue: _r.queue)
-                                    ]
-                          ])
-                        .toList())
-                ]
+                                new DivElement()
+                                  ..classes = ['memberName']
+                                  ..children = <Element>[
+                                    new FieldRefElement(_isolate, f, _objects,
+                                            queue: _r.queue)
+                                        .element
+                                  ],
+                                new DivElement()
+                                  ..classes = ['memberValue']
+                                  ..children = f.staticValue == null
+                                      ? const []
+                                      : [
+                                          anyRef(
+                                              _isolate, f.staticValue, _objects,
+                                              queue: _r.queue)
+                                        ]
+                              ])
+                            .toList())
+                    ])
+                  .element
             ]
         ]);
     }
@@ -481,16 +498,18 @@
           new DivElement()
             ..classes = ['memberValue']
             ..children = <Element>[
-              new CurlyBlockElement(expanded: _functionsExpanded)
-                ..onToggle
-                    .listen((e) => _functionsExpanded = e.control.expanded)
-                ..content = (functions
-                    .map<Element>((f) => new DivElement()
-                      ..classes = ['indent']
-                      ..children = <Element>[
-                        new FunctionRefElement(_isolate, f, queue: _r.queue)
-                      ])
-                    .toList())
+              (new CurlyBlockElement(expanded: _functionsExpanded)
+                    ..onToggle
+                        .listen((e) => _functionsExpanded = e.control.expanded)
+                    ..content = (functions
+                        .map<Element>((f) => new DivElement()
+                          ..classes = ['indent']
+                          ..children = <Element>[
+                            new FunctionRefElement(_isolate, f, queue: _r.queue)
+                                .element
+                          ])
+                        .toList()))
+                  .element
             ]
         ]);
     }
diff --git a/runtime/observatory/lib/src/elements/code_ref.dart b/runtime/observatory/lib/src/elements/code_ref.dart
index fc35ef8..f6c7f03 100644
--- a/runtime/observatory/lib/src/elements/code_ref.dart
+++ b/runtime/observatory/lib/src/elements/code_ref.dart
@@ -12,7 +12,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class CodeRefElement extends HtmlElement implements Renderable {
+class CodeRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<CodeRefElement>('code-ref');
 
   RenderingScheduler<CodeRefElement> _r;
@@ -28,14 +28,14 @@
   factory CodeRefElement(M.IsolateRef isolate, M.CodeRef code,
       {RenderingQueue queue}) {
     assert(code != null);
-    CodeRefElement e = document.createElement(tag.name);
+    CodeRefElement e = new CodeRefElement.created();
     e._r = new RenderingScheduler<CodeRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._code = code;
     return e;
   }
 
-  CodeRefElement.created() : super.created();
+  CodeRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/code_view.dart b/runtime/observatory/lib/src/elements/code_view.dart
index b943be5..c5061ad 100644
--- a/runtime/observatory/lib/src/elements/code_view.dart
+++ b/runtime/observatory/lib/src/elements/code_view.dart
@@ -36,7 +36,7 @@
   InlineTable(columns) : super(columns);
 }
 
-class CodeViewElement extends HtmlElement implements Renderable {
+class CodeViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<CodeViewElement>('code-view', dependencies: const [
     CurlyBlockElement.tag,
@@ -97,7 +97,7 @@
     assert(reachableSizes != null);
     assert(references != null);
     assert(retainingPaths != null);
-    CodeViewElement e = document.createElement(tag.name);
+    CodeViewElement e = new CodeViewElement.created();
     e._r = new RenderingScheduler<CodeViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -112,7 +112,7 @@
     return e;
   }
 
-  CodeViewElement.created() : super.created() {
+  CodeViewElement.created() : super.created(tag) {
     var columns = [
       new SortedTableColumn('Address'),
       new SortedTableColumn('Inclusive'),
@@ -200,21 +200,23 @@
     final S.Code code = _code as S.Code;
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu(_code.name),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _refresh();
-          }),
-        new NavRefreshElement(label: 'refresh ticks', queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _refreshTicks();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _refresh();
+              }))
+            .element,
+        (new NavRefreshElement(label: 'refresh ticks', queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _refreshTicks();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -225,8 +227,9 @@
                 : 'Code for ${_code.name}',
           new HRElement(),
           new ObjectCommonElement(_isolate, _code, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new BRElement(),
           new DivElement()
             ..classes = ['memberList']
@@ -263,7 +266,8 @@
                     ..classes = ['memberValue']
                     ..children = <Element>[
                       new FunctionRefElement(_isolate, _code.function,
-                          queue: _r.queue)
+                              queue: _r.queue)
+                          .element
                     ]
                 ],
               new DivElement()
@@ -300,7 +304,8 @@
                     ..classes = ['memberValue']
                     ..children = <Element>[
                       new ObjectPoolRefElement(_isolate, _code.objectPool,
-                          queue: _r.queue)
+                              queue: _r.queue)
+                          .element
                     ]
                 ],
               new DivElement()
@@ -315,14 +320,16 @@
                         new DivElement()
                           ..classes = ['memberValue']
                           ..children = <Element>[
-                            new CurlyBlockElement(
-                                expanded: inlinedFunctions.length < 8,
-                                queue: _r.queue)
-                              ..content = inlinedFunctions
-                                  .map<Element>((f) => new FunctionRefElement(
-                                      _isolate, f,
-                                      queue: _r.queue))
-                                  .toList()
+                            (new CurlyBlockElement(
+                                    expanded: inlinedFunctions.length < 8,
+                                    queue: _r.queue)
+                                  ..content = inlinedFunctions
+                                      .map<Element>((f) =>
+                                          new FunctionRefElement(_isolate, f,
+                                                  queue: _r.queue)
+                                              .element)
+                                      .toList())
+                                .element
                           ]
                       ]
             ],
@@ -593,7 +600,7 @@
     functionsCell.children.clear();
     for (var func in functions) {
       functionsCell.children
-          .add(new FunctionRefElement(_isolate, func, queue: _r.queue));
+          .add(new FunctionRefElement(_isolate, func, queue: _r.queue).element);
       var gap = new SpanElement();
       gap.style.minWidth = '1em';
       gap.text = ' ';
diff --git a/runtime/observatory/lib/src/elements/containers/search_bar.dart b/runtime/observatory/lib/src/elements/containers/search_bar.dart
index c07c495..593956a 100644
--- a/runtime/observatory/lib/src/elements/containers/search_bar.dart
+++ b/runtime/observatory/lib/src/elements/containers/search_bar.dart
@@ -16,7 +16,7 @@
 
 typedef Iterable<dynamic> SearchBarSearchCallback(Pattern pattern);
 
-class SearchBarElement extends HtmlElement implements Renderable {
+class SearchBarElement extends CustomElement implements Renderable {
   static const tag = const Tag<SearchBarElement>('search-bar');
 
   RenderingScheduler<SearchBarElement> _r;
@@ -58,7 +58,7 @@
       {bool isOpen: false, Element workspace, RenderingQueue queue}) {
     assert(search != null);
     assert(isOpen != null);
-    SearchBarElement e = document.createElement(tag.name);
+    SearchBarElement e = new SearchBarElement.created();
     e._r = new RenderingScheduler<SearchBarElement>(e, queue: queue);
     e._search = search;
     e._isOpen = isOpen;
@@ -66,7 +66,7 @@
     return e;
   }
 
-  SearchBarElement.created() : super.created();
+  SearchBarElement.created() : super.created(tag);
 
   @override
   attached() {
diff --git a/runtime/observatory/lib/src/elements/containers/virtual_collection.dart b/runtime/observatory/lib/src/elements/containers/virtual_collection.dart
index b1a9169..f921c44 100644
--- a/runtime/observatory/lib/src/elements/containers/virtual_collection.dart
+++ b/runtime/observatory/lib/src/elements/containers/virtual_collection.dart
@@ -15,7 +15,7 @@
     HtmlElement el, dynamic item, int index);
 typedef bool VirtualCollectionSearchCallback(Pattern pattern, dynamic item);
 
-class VirtualCollectionElement extends HtmlElement implements Renderable {
+class VirtualCollectionElement extends CustomElement implements Renderable {
   static const tag = const Tag<VirtualCollectionElement>('virtual-collection',
       dependencies: const [SearchBarElement.tag]);
 
@@ -53,7 +53,7 @@
     assert(create != null);
     assert(update != null);
     assert(items != null);
-    VirtualCollectionElement e = document.createElement(tag.name);
+    VirtualCollectionElement e = new VirtualCollectionElement.created();
     e._r = new RenderingScheduler<VirtualCollectionElement>(e, queue: queue);
     e._create = create;
     e._createHeader = createHeader;
@@ -63,7 +63,7 @@
     return e;
   }
 
-  VirtualCollectionElement.created() : super.created();
+  VirtualCollectionElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -91,13 +91,23 @@
   final DivElement _spacer = new DivElement()..classes = ['spacer'];
   final DivElement _buffer = new DivElement()..classes = ['buffer'];
 
+  static int safeFloor(double x) {
+    if (x.isNaN) return 0;
+    return x.floor();
+  }
+
+  static int safeCeil(double x) {
+    if (x.isNaN) return 0;
+    return x.ceil();
+  }
+
   dynamic getItemFromElement(HtmlElement element) {
     final el_index = _buffer.children.indexOf(element);
     if (el_index < 0) {
       return null;
     }
     final item_index =
-        _top + el_index - (_buffer.children.length * _inverse_preload).floor();
+        _top + el_index - safeFloor(_buffer.children.length * _inverse_preload);
     if (0 <= item_index && item_index < items.length) {
       return _items[item_index];
     }
@@ -141,7 +151,7 @@
               ..onSearchResultSelected.listen((e) {
                 takeIntoView(e.item);
               });
-        children.insert(0, _searcher);
+        children.insert(0, _searcher.element);
       }
       if (_createHeader != null) {
         _header = new DivElement()
@@ -164,15 +174,15 @@
         final minScrollTop = _itemHeight * (index + 1) - _height;
         final maxScrollTop = _itemHeight * index;
         _viewport.scrollTop =
-            ((maxScrollTop - minScrollTop) / 2 + minScrollTop).floor();
+            safeFloor((maxScrollTop - minScrollTop) / 2 + minScrollTop);
       }
       _takeIntoView = null;
     }
 
-    final top = (_viewport.scrollTop / _itemHeight).floor();
+    final top = safeFloor(_viewport.scrollTop / _itemHeight);
 
-    _spacer.style.height = '${_itemHeight*(_items.length)}px';
-    final tail_length = (_height / _itemHeight / _preload).ceil();
+    _spacer.style.height = '${_itemHeight * (_items.length)}px';
+    final tail_length = safeCeil(_height / _itemHeight / _preload);
     final length = tail_length * 2 + tail_length * _preload;
 
     if (_buffer.children.length < length) {
@@ -185,7 +195,7 @@
     }
 
     if ((_top == null) || ((top - _top).abs() >= tail_length)) {
-      _buffer.style.top = '${_itemHeight*(top-tail_length)}px';
+      _buffer.style.top = '${_itemHeight * (top - tail_length)}px';
       int i = top - tail_length;
       for (final HtmlElement e in _buffer.children) {
         if (0 <= i && i < _items.length) {
diff --git a/runtime/observatory/lib/src/elements/containers/virtual_tree.dart b/runtime/observatory/lib/src/elements/containers/virtual_tree.dart
index 0c9b38b..09690d6 100644
--- a/runtime/observatory/lib/src/elements/containers/virtual_tree.dart
+++ b/runtime/observatory/lib/src/elements/containers/virtual_tree.dart
@@ -26,7 +26,7 @@
   }
 }
 
-class VirtualTreeElement extends HtmlElement implements Renderable {
+class VirtualTreeElement extends CustomElement implements Renderable {
   static const tag = const Tag<VirtualTreeElement>('virtual-tree',
       dependencies: const [VirtualCollectionElement.tag]);
 
@@ -56,7 +56,7 @@
     assert(update != null);
     assert(children != null);
     assert(items != null);
-    VirtualTreeElement e = document.createElement(tag.name);
+    VirtualTreeElement e = new VirtualTreeElement.created();
     e._r = new RenderingScheduler<VirtualTreeElement>(e, queue: queue);
     e._children = children;
     e._collection = new VirtualCollectionElement(() {
@@ -82,7 +82,7 @@
     return e;
   }
 
-  VirtualTreeElement.created() : super.created();
+  VirtualTreeElement.created() : super.created(tag);
 
   bool isExpanded(item) {
     return _expanded.contains(item);
@@ -151,7 +151,7 @@
 
   void render() {
     if (children.length == 0) {
-      children = <Element>[_collection];
+      children = <Element>[_collection.element];
     }
 
     final items = [];
diff --git a/runtime/observatory/lib/src/elements/context_ref.dart b/runtime/observatory/lib/src/elements/context_ref.dart
index c4c06b2..1f92a48 100644
--- a/runtime/observatory/lib/src/elements/context_ref.dart
+++ b/runtime/observatory/lib/src/elements/context_ref.dart
@@ -11,7 +11,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class ContextRefElement extends HtmlElement implements Renderable {
+class ContextRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<ContextRefElement>('context-ref',
       dependencies: const [CurlyBlockElement.tag]);
 
@@ -35,7 +35,7 @@
     assert(isolate != null);
     assert(context != null);
     assert(objects != null);
-    ContextRefElement e = document.createElement(tag.name);
+    ContextRefElement e = new ContextRefElement.created();
     e._r = new RenderingScheduler<ContextRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._context = context;
@@ -44,7 +44,7 @@
     return e;
   }
 
-  ContextRefElement.created() : super.created();
+  ContextRefElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -77,20 +77,21 @@
     if (_expandable) {
       children.addAll([
         new SpanElement()..text = ' ',
-        new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
-          ..content = <Element>[
-            new DivElement()
-              ..classes = ['indent']
-              ..children = _createValue()
-          ]
-          ..onToggle.listen((e) async {
-            _expanded = e.control.expanded;
-            if (_expanded) {
-              e.control.disabled = true;
-              await _refresh();
-              e.control.disabled = false;
-            }
-          })
+        (new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
+              ..content = <Element>[
+                new DivElement()
+                  ..classes = ['indent']
+                  ..children = _createValue()
+              ]
+              ..onToggle.listen((e) async {
+                _expanded = e.control.expanded;
+                if (_expanded) {
+                  e.control.disabled = true;
+                  await _refresh();
+                  e.control.disabled = false;
+                }
+              }))
+            .element
       ]);
     }
     this.children = children;
@@ -112,8 +113,9 @@
             ..classes = ['memberName']
             ..children = <Element>[
               new ContextRefElement(
-                  _isolate, _loadedContext.parentContext, _objects,
-                  queue: _r.queue)
+                      _isolate, _loadedContext.parentContext, _objects,
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
diff --git a/runtime/observatory/lib/src/elements/context_view.dart b/runtime/observatory/lib/src/elements/context_view.dart
index 15dd1a6..b85b315 100644
--- a/runtime/observatory/lib/src/elements/context_view.dart
+++ b/runtime/observatory/lib/src/elements/context_view.dart
@@ -21,7 +21,7 @@
 import 'package:observatory/src/elements/object_common.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class ContextViewElement extends HtmlElement implements Renderable {
+class ContextViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<ContextViewElement>('context-view', dependencies: const [
     ContextRefElement.tag,
@@ -81,7 +81,7 @@
     assert(references != null);
     assert(retainingPaths != null);
     assert(objects != null);
-    ContextViewElement e = document.createElement(tag.name);
+    ContextViewElement e = new ContextViewElement.created();
     e._r = new RenderingScheduler<ContextViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -97,7 +97,7 @@
     return e;
   }
 
-  ContextViewElement.created() : super.created();
+  ContextViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -115,18 +115,20 @@
   void render() {
     var content = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
-        new NavClassMenuElement(_isolate, _context.clazz, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        new NavClassMenuElement(_isolate, _context.clazz, queue: _r.queue)
+            .element,
         navMenu('instance'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _context = await _contexts.get(_isolate, _context.id);
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _context = await _contexts.get(_isolate, _context.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -134,8 +136,9 @@
           new HeadingElement.h2()..text = 'Context',
           new HRElement(),
           new ObjectCommonElement(_isolate, _context, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue)
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element
         ]
     ];
     if (_context.parentContext != null) {
@@ -157,8 +160,9 @@
                       ..classes = ['memberName']
                       ..children = <Element>[
                         new ContextRefElement(
-                            _isolate, _context.parentContext, _objects,
-                            queue: _r.queue)
+                                _isolate, _context.parentContext, _objects,
+                                queue: _r.queue)
+                            .element
                       ]
                   ]
               ]
@@ -173,32 +177,33 @@
           ..classes = ['content-centered-big']
           ..children = <Element>[
             new SpanElement()..text = 'Variables ',
-            new CurlyBlockElement(expanded: true, queue: _r.queue)
-              ..content = <Element>[
-                new DivElement()
-                  ..classes = ['memberList']
-                  ..children = _context.variables
-                      .map<Element>((variable) => new DivElement()
-                        ..classes = ['memberItem']
-                        ..children = <Element>[
-                          new DivElement()
-                            ..classes = ['memberName']
-                            ..text = '[ ${++index} ]',
-                          new DivElement()
-                            ..classes = ['memberName']
+            (new CurlyBlockElement(expanded: true, queue: _r.queue)
+                  ..content = <Element>[
+                    new DivElement()
+                      ..classes = ['memberList']
+                      ..children = _context.variables
+                          .map<Element>((variable) => new DivElement()
+                            ..classes = ['memberItem']
                             ..children = <Element>[
-                              anyRef(_isolate, variable.value, _objects,
-                                  queue: _r.queue)
-                            ]
-                        ])
-                      .toList()
-              ]
+                              new DivElement()
+                                ..classes = ['memberName']
+                                ..text = '[ ${++index} ]',
+                              new DivElement()
+                                ..classes = ['memberName']
+                                ..children = <Element>[
+                                  anyRef(_isolate, variable.value, _objects,
+                                      queue: _r.queue)
+                                ]
+                            ])
+                          .toList()
+                  ])
+                .element
           ]
       ]);
     }
     content.add(new DivElement()
       ..classes = ['content-centered-big']
-      ..children = <Element>[new ViewFooterElement(queue: _r.queue)]);
+      ..children = <Element>[new ViewFooterElement(queue: _r.queue).element]);
     children = content;
   }
 }
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.dart b/runtime/observatory/lib/src/elements/cpu_profile.dart
index 4c8bc31..320a7603 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile.dart
@@ -21,7 +21,7 @@
 import 'package:observatory/src/elements/sample_buffer_control.dart';
 import 'package:observatory/src/elements/stack_trace_tree_config.dart';
 
-class CpuProfileElement extends HtmlElement implements Renderable {
+class CpuProfileElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<CpuProfileElement>('cpu-profile', dependencies: const [
     NavTopMenuElement.tag,
@@ -67,7 +67,7 @@
     assert(events != null);
     assert(notifications != null);
     assert(profiles != null);
-    CpuProfileElement e = document.createElement(tag.name);
+    CpuProfileElement e = new CpuProfileElement.created();
     e._r = new RenderingScheduler<CpuProfileElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -77,7 +77,7 @@
     return e;
   }
 
-  CpuProfileElement.created() : super.created();
+  CpuProfileElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -96,54 +96,59 @@
   void render() {
     var content = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('cpu profile', link: Uris.cpuProfiler(_isolate)),
-        new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh),
-        new NavRefreshElement(label: 'Clear', queue: _r.queue)
-          ..onRefresh.listen(_clearCpuProfile),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh))
+            .element,
+        (new NavRefreshElement(label: 'Clear', queue: _r.queue)
+              ..onRefresh.listen(_clearCpuProfile))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
     ];
     if (_progress == null) {
       children = content;
       return;
     }
-    content.add(new SampleBufferControlElement(_vm, _progress, _progressStream,
-        selectedTag: _tag, queue: _r.queue)
-      ..onTagChange.listen((e) {
-        _tag = e.element.selectedTag;
-        _request(forceFetch: true);
-      }));
+    content.add((new SampleBufferControlElement(_vm, _progress, _progressStream,
+            selectedTag: _tag, queue: _r.queue)
+          ..onTagChange.listen((e) {
+            _tag = e.element.selectedTag;
+            _request(forceFetch: true);
+          }))
+        .element);
     if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
       CpuProfileVirtualTreeElement tree;
       content.addAll([
         new BRElement(),
-        new StackTraceTreeConfigElement(
-            mode: _mode,
-            direction: _direction,
-            filter: _filter,
-            queue: _r.queue)
-          ..onModeChange.listen((e) {
-            _mode = tree.mode = e.element.mode;
-          })
-          ..onFilterChange.listen((e) {
-            _filter = e.element.filter.trim();
-            tree.filters = _filter.isNotEmpty
-                ? [
-                    (node) {
-                      return node.name.contains(_filter);
-                    }
-                  ]
-                : const [];
-          })
-          ..onDirectionChange.listen((e) {
-            _direction = tree.direction = e.element.direction;
-          }),
+        (new StackTraceTreeConfigElement(
+                mode: _mode,
+                direction: _direction,
+                filter: _filter,
+                queue: _r.queue)
+              ..onModeChange.listen((e) {
+                _mode = tree.mode = e.element.mode;
+              })
+              ..onFilterChange.listen((e) {
+                _filter = e.element.filter.trim();
+                tree.filters = _filter.isNotEmpty
+                    ? [
+                        (node) {
+                          return node.name.contains(_filter);
+                        }
+                      ]
+                    : const [];
+              })
+              ..onDirectionChange.listen((e) {
+                _direction = tree.direction = e.element.direction;
+              }))
+            .element,
         new BRElement(),
-        tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
-            queue: _r.queue)
+        (tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
+                queue: _r.queue))
+            .element
       ]);
     }
     children = content;
diff --git a/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
index 3ee7325..77de515 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
@@ -18,7 +18,7 @@
 export 'package:observatory/src/elements/stack_trace_tree_config.dart'
     show ProfileTreeMode;
 
-class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable {
+class CpuProfileVirtualTreeElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<CpuProfileVirtualTreeElement>('cpu-profile-virtual-tree');
 
@@ -57,8 +57,9 @@
     assert(profile != null);
     assert(mode != null);
     assert(direction != null);
-    CpuProfileVirtualTreeElement e = document.createElement(tag.name);
-    e._r = new RenderingScheduler<CpuProfileVirtualTreeElement>(e, queue: queue);
+    CpuProfileVirtualTreeElement e = new CpuProfileVirtualTreeElement.created();
+    e._r =
+        new RenderingScheduler<CpuProfileVirtualTreeElement>(e, queue: queue);
     e._isolate = owner;
     e._profile = profile;
     e._mode = mode;
@@ -67,7 +68,7 @@
     return e;
   }
 
-  CpuProfileVirtualTreeElement.created() : super.created();
+  CpuProfileVirtualTreeElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -143,7 +144,7 @@
     } else if (tree.root.children.length == 1) {
       _tree.expand(tree.root.children.first, autoExpandSingleChildNodes: true);
     }
-    children = <Element>[_tree];
+    children = <Element>[_tree.element];
   }
 
   static HtmlElement _createCpuRow(toggle) {
@@ -196,13 +197,12 @@
   static const String _expandedIcon = '▼';
   static const String _collapsedIcon = '►';
 
-  void _updateCpuFunctionRow(
-      HtmlElement element, itemDynamic, int depth) {
+  void _updateCpuFunctionRow(HtmlElement element, itemDynamic, int depth) {
     M.FunctionCallTreeNode item = itemDynamic;
-    element.children[0].text = Utils
-        .formatPercentNormalized(item.profileFunction.normalizedInclusiveTicks);
-    element.children[1].text = Utils
-        .formatPercentNormalized(item.profileFunction.normalizedExclusiveTicks);
+    element.children[0].text = Utils.formatPercentNormalized(
+        item.profileFunction.normalizedInclusiveTicks);
+    element.children[1].text = Utils.formatPercentNormalized(
+        item.profileFunction.normalizedExclusiveTicks);
     _updateLines(element.children[2].children, depth);
     if (item.children.isNotEmpty) {
       element.children[3].text =
@@ -211,14 +211,14 @@
       element.children[3].text = '';
     }
     element.children[4].text = Utils.formatPercentNormalized(item.percentage);
-    element.children[5] = new FunctionRefElement(
-        _isolate, item.profileFunction.function,
-        queue: _r.queue)
-      ..classes = ['name'];
+    element.children[5] = (new FunctionRefElement(
+            _isolate, item.profileFunction.function,
+            queue: _r.queue)
+          ..classes = ['name'])
+        .element;
   }
 
-  void _updateMemoryFunctionRow(
-      HtmlElement element, itemDynamic, int depth) {
+  void _updateMemoryFunctionRow(HtmlElement element, itemDynamic, int depth) {
     M.FunctionCallTreeNode item = itemDynamic;
     element.children[0].text =
         Utils.formatSize(item.inclusiveNativeAllocations);
@@ -236,24 +236,26 @@
       element.children[3].text = '';
     }
     element.children[4].text = Utils.formatPercentNormalized(item.percentage);
-    element.children[5] = new FunctionRefElement(
-        null, item.profileFunction.function,
-        queue: _r.queue)
-      ..classes = ['name'];
+    element.children[5] = (new FunctionRefElement(
+            null, item.profileFunction.function,
+            queue: _r.queue)
+          ..classes = ['name'])
+        .element;
   }
 
   bool _searchFunction(Pattern pattern, itemDynamic) {
     M.FunctionCallTreeNode item = itemDynamic;
-    return M.getFunctionFullName(item.profileFunction.function).contains(pattern);
+    return M
+        .getFunctionFullName(item.profileFunction.function)
+        .contains(pattern);
   }
 
-  void _updateCpuCodeRow(
-      HtmlElement element, itemDynamic, int depth) {
+  void _updateCpuCodeRow(HtmlElement element, itemDynamic, int depth) {
     M.CodeCallTreeNode item = itemDynamic;
-    element.children[0].text = Utils
-        .formatPercentNormalized(item.profileCode.normalizedInclusiveTicks);
-    element.children[1].text = Utils
-        .formatPercentNormalized(item.profileCode.normalizedExclusiveTicks);
+    element.children[0].text = Utils.formatPercentNormalized(
+        item.profileCode.normalizedInclusiveTicks);
+    element.children[1].text = Utils.formatPercentNormalized(
+        item.profileCode.normalizedExclusiveTicks);
     _updateLines(element.children[2].children, depth);
     if (item.children.isNotEmpty) {
       element.children[3].text =
@@ -263,12 +265,12 @@
     }
     element.children[4].text = Utils.formatPercentNormalized(item.percentage);
     element.children[5] =
-        new CodeRefElement(_isolate, item.profileCode.code, queue: _r.queue)
-          ..classes = ['name'];
+        (new CodeRefElement(_isolate, item.profileCode.code, queue: _r.queue)
+              ..classes = ['name'])
+            .element;
   }
 
-  void _updateMemoryCodeRow(
-      HtmlElement element, itemDynamic, int depth) {
+  void _updateMemoryCodeRow(HtmlElement element, itemDynamic, int depth) {
     M.CodeCallTreeNode item = itemDynamic;
     element.children[0].text =
         Utils.formatSize(item.inclusiveNativeAllocations);
@@ -287,8 +289,9 @@
     }
     element.children[4].text = Utils.formatPercentNormalized(item.percentage);
     element.children[5] =
-        new CodeRefElement(null, item.profileCode.code, queue: _r.queue)
-          ..classes = ['name'];
+        (new CodeRefElement(null, item.profileCode.code, queue: _r.queue)
+              ..classes = ['name'])
+            .element;
   }
 
   bool _searchCode(Pattern pattern, itemDynamic) {
diff --git a/runtime/observatory/lib/src/elements/cpu_profile_table.dart b/runtime/observatory/lib/src/elements/cpu_profile_table.dart
index b1a9160..cd07545 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile_table.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile_table.dart
@@ -29,7 +29,7 @@
 
 enum _SortingDirection { ascending, descending }
 
-class CpuProfileTableElement extends HtmlElement implements Renderable {
+class CpuProfileTableElement extends CustomElement implements Renderable {
   static const tag = const Tag<CpuProfileTableElement>('cpu-profile-table',
       dependencies: const [
         FunctionRefElement.tag,
@@ -84,7 +84,7 @@
     assert(events != null);
     assert(notifications != null);
     assert(profiles != null);
-    CpuProfileTableElement e = document.createElement(tag.name);
+    CpuProfileTableElement e = new CpuProfileTableElement.created();
     e._r = new RenderingScheduler<CpuProfileTableElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -94,7 +94,7 @@
     return e;
   }
 
-  CpuProfileTableElement.created() : super.created();
+  CpuProfileTableElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -113,14 +113,16 @@
   void render() {
     var content = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('cpu profile (table)'),
-        new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh),
-        new NavRefreshElement(label: 'Clear', queue: _r.queue)
-          ..onRefresh.listen(_clearCpuProfile),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh))
+            .element,
+        (new NavRefreshElement(label: 'Clear', queue: _r.queue)
+              ..onRefresh.listen(_clearCpuProfile))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
     ];
     if (_progress == null) {
@@ -128,7 +130,8 @@
       return;
     }
     content.add(new SampleBufferControlElement(_vm, _progress, _progressStream,
-        showTag: false, queue: _r.queue));
+            showTag: false, queue: _r.queue)
+        .element);
     if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
       content.add(new BRElement());
       content.addAll(_createTables());
@@ -177,24 +180,25 @@
         ..children = <Element>[
           new DivElement()
             ..classes = ['profile-trees-all']
-            ..children = <Element>[_functions],
+            ..children = <Element>[_functions.element],
           new DivElement()
             ..classes = ['profile-trees-current']
             ..children = <Element>[
               new DivElement()
                 ..classes = ['profile-trees-caller']
-                ..children = <Element>[_callers],
+                ..children = <Element>[_callers.element],
               new DivElement()
                 ..classes = ['profile-trees-selected']
                 ..children = _selected == null
                     ? [new SpanElement()..text = 'No element selected']
                     : [
                         new FunctionRefElement(_isolate, _selected.function,
-                            queue: _r.queue)
+                                queue: _r.queue)
+                            .element
                       ],
               new DivElement()
                 ..classes = ['profile-trees-callee']
-                ..children = <Element>[_callees]
+                ..children = <Element>[_callees.element]
             ]
         ]
     ];
@@ -370,37 +374,39 @@
   List<Element> _createTree() {
     CpuProfileVirtualTreeElement tree;
     return [
-      new StackTraceTreeConfigElement(
-          showMode: false,
-          showDirection: false,
-          mode: ProfileTreeMode.function,
-          direction: M.ProfileTreeDirection.exclusive,
-          filter: _filter,
-          queue: _r.queue)
-        ..onFilterChange.listen((e) {
-          _filter = e.element.filter.trim();
-          tree.filters = _filter.isNotEmpty
-              ? [
-                  _filterTree,
-                  (node) {
-                    return node.name.contains(_filter);
-                  }
-                ]
-              : [_filterTree];
-        }),
+      (new StackTraceTreeConfigElement(
+              showMode: false,
+              showDirection: false,
+              mode: ProfileTreeMode.function,
+              direction: M.ProfileTreeDirection.exclusive,
+              filter: _filter,
+              queue: _r.queue)
+            ..onFilterChange.listen((e) {
+              _filter = e.element.filter.trim();
+              tree.filters = _filter.isNotEmpty
+                  ? [
+                      _filterTree,
+                      (node) {
+                        return node.name.contains(_filter);
+                      }
+                    ]
+                  : [_filterTree];
+            }))
+          .element,
       new BRElement(),
-      tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
-          mode: ProfileTreeMode.function,
-          direction: M.ProfileTreeDirection.exclusive,
-          queue: _r.queue)
-        ..filters = _filter.isNotEmpty
-            ? [
-                _filterTree,
-                (node) {
-                  return node.name.contains(_filter);
-                }
-              ]
-            : [_filterTree]
+      (tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
+              mode: ProfileTreeMode.function,
+              direction: M.ProfileTreeDirection.exclusive,
+              queue: _r.queue)
+            ..filters = _filter.isNotEmpty
+                ? [
+                    _filterTree,
+                    (node) {
+                      return node.name.contains(_filter);
+                    }
+                  ]
+                : [_filterTree])
+          .element
     ];
   }
 
diff --git a/runtime/observatory/lib/src/elements/css/shared.css b/runtime/observatory/lib/src/elements/css/shared.css
index 397de98..218cc7f 100644
--- a/runtime/observatory/lib/src/elements/css/shared.css
+++ b/runtime/observatory/lib/src/elements/css/shared.css
@@ -397,22 +397,22 @@
 
 /* allocation-profile */
 
-allocation-profile .heap-space {
+.allocation-profile .heap-space {
   display: inline-block;
   width: 50%;
 }
 
-allocation-profile .heap-space.right,
-allocation-profile .heap-space.right .memberList,
-allocation-profile .heap-space.right .legend * {
+.allocation-profile .heap-space.right,
+.allocation-profile .heap-space.right .memberList,
+.allocation-profile .heap-space.right .legend * {
   direction: rtl;
 }
 
-allocation-profile .compactable {
+.allocation-profile .compactable {
   position: relative;
 }
 
-allocation-profile .compact {
+.allocation-profile .compact {
   position: absolute;
   bottom: 20px;
   left: 50%;
@@ -420,45 +420,45 @@
   margin-left: -4em;
 }
 
-allocation-profile .heap-space.right * {
+.allocation-profile .heap-space.right * {
   direction: ltr;
   text-align: right;
 }
 
-allocation-profile div.chart {
+.allocation-profile div.chart {
   display: block;
   position: relative;
   height: 150px;
 }
-allocation-profile div.chart > div.host {
+.allocation-profile div.chart > div.host {
   display: inline-block;
   position: absolute;
   bottom: 0px;
   top: 0;
 }
-allocation-profile div.chart > div.legend {
+.allocation-profile div.chart > div.legend {
   position: absolute;
   width: 150px;
   top: 25px;
   bottom: 0;
   overflow-y: auto;
 }
-allocation-profile .heap-space.left div.host {
+.allocation-profile .heap-space.left div.host {
   left: 200px;
   width: 180px;
 }
-allocation-profile .heap-space.right div.host {
+.allocation-profile .heap-space.right div.host {
   right: 150px;
   width: 180px;
 }
-allocation-profile .heap-space.left div.legend {
+.allocation-profile .heap-space.left div.legend {
   left: 0;
 }
-allocation-profile .heap-space.right div.legend {
+.allocation-profile .heap-space.right div.legend {
   right: 0;
 }
 
-allocation-profile .collection {
+.allocation-profile .collection {
   position: absolute;
   bottom: 0;
   left: 0;
@@ -466,63 +466,63 @@
   top: 560px;
 }
 
-allocation-profile .collection.expanded {
+.allocation-profile .collection.expanded {
   top: 160px;
 }
 
-allocation-profile .container {
+.allocation-profile .container {
   padding-left: 5%;
   padding-right: 5%;
 }
 
-allocation-profile .collection-item {
+.allocation-profile .collection-item {
   background-color: #FFFFFF;
   box-sizing: border-box;
   line-height: 20px;
 }
 
-allocation-profile .collection-item:hover {
+.allocation-profile .collection-item:hover {
   background-color: #d2e7fe;
 }
 
-allocation-profile .header .collection-item:hover {
+.allocation-profile .header .collection-item:hover {
   background-color: #FFFFFF;
 }
 
-allocation-profile .header .collection-item:last-child {
+.allocation-profile .header .collection-item:last-child {
   margin-bottom: -3px;
   border-bottom: solid 1px #AAAAAA;
 }
 
-allocation-profile .header .collection-item span {
+.allocation-profile .header .collection-item span {
   font-weight: bolder;
 }
 
-allocation-profile .collection-item :nth-child(2n+2).group,
-allocation-profile .collection-item :nth-child(4n+3),
-allocation-profile .collection-item :nth-child(4n+4) {
+.allocation-profile .collection-item :nth-child(2n+2).group,
+.allocation-profile .collection-item :nth-child(4n+3),
+.allocation-profile .collection-item :nth-child(4n+4) {
   background-color: #EEEEEE;
 }
 
-allocation-profile .collection-item:hover :nth-child(2n+2).group,
-allocation-profile .collection-item:hover :nth-child(4n+3),
-allocation-profile .collection-item:hover :nth-child(4n+4) {
+.allocation-profile .collection-item:hover :nth-child(2n+2).group,
+.allocation-profile .collection-item:hover :nth-child(4n+3),
+.allocation-profile .collection-item:hover :nth-child(4n+4) {
   background-color: #afd5fd;
 }
 
-allocation-profile .header .collection-item :nth-child(2n+1).group,
-allocation-profile .header .collection-item :nth-child(4n+1),
-allocation-profile .header .collection-item :nth-child(4n+2) {
+.allocation-profile .header .collection-item :nth-child(2n+1).group,
+.allocation-profile .header .collection-item :nth-child(4n+1),
+.allocation-profile .header .collection-item :nth-child(4n+2) {
   background-color: #FFFFFF;
 }
 
-allocation-profile .header .collection-item :nth-child(2n+2).group,
-allocation-profile .header .collection-item :nth-child(4n+3),
-allocation-profile .header .collection-item :nth-child(4n+4) {
+.allocation-profile .header .collection-item :nth-child(2n+2).group,
+.allocation-profile .header .collection-item :nth-child(4n+3),
+.allocation-profile .header .collection-item :nth-child(4n+4) {
   background-color: #DDDDDD;
 }
 
-allocation-profile .collection-item .group {
+.allocation-profile .collection-item .group {
   display: inline-block;
   width: 12em;
   text-align: right;
@@ -531,7 +531,7 @@
   border-right: solid 1px #AAAAAA;
 }
 
-allocation-profile .collection-item .bytes {
+.allocation-profile .collection-item .bytes {
   display: inline-block;
   width: 6em;
   text-align: right;
@@ -539,7 +539,7 @@
   padding-right: 0.5em;
 }
 
-allocation-profile .collection-item .instances {
+.allocation-profile .collection-item .instances {
   display: inline-block;
   width: 6em;
   text-align: right;
@@ -548,56 +548,56 @@
   border-right: solid 1px #AAAAAA;
 }
 
-allocation-profile .collection-item .name {
+.allocation-profile .collection-item .name {
   padding-left: 0.5em;
   padding-right: 0.5em;
   display: inline-block;
 }
 
-allocation-profile .collection-item > button,
-allocation-profile .collection-item > button:active {
+.allocation-profile .collection-item > button,
+.allocation-profile .collection-item > button:active {
   background-color: transparent;
   color: #0489c3;
   border-style: none;
 }
 
-allocation-profile .collection-item > button:hover {
+.allocation-profile .collection-item > button:hover {
   text-decoration: underline;
 }
 
 /* class-ref */
 
-class-ref > a[href]:hover {
+.class-ref > a[href]:hover {
     text-decoration: underline;
 }
-class-ref > a[href] {
+.class-ref > a[href] {
     color: #0489c3;
     text-decoration: none;
 }
 
 /* code-ref */
 
-code-ref > a[href]:hover {
+.code-ref > a[href]:hover {
   text-decoration: underline;
 }
-code-ref > a[href] {
+.code-ref > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-code-ref .emphasize {
+.code-ref .emphasize {
   font-style: italic;
 }
 
 
 /* class-tree */
 
-class-tree {
+.class-tree {
   position: relative;
   display: block;
   height: 100%;
 }
 
-class-tree virtual-tree {
+.class-tree .virtual-tree {
   position: absolute;
   height: auto;
   top: 60px;
@@ -606,47 +606,47 @@
   right: 0;
 }
 
-class-tree virtual-tree .container {
+.class-tree .virtual-tree .container {
   padding-left: 10%;
   padding-right: 10%;
 }
 
-class-tree virtual-tree .class-tree-item {
+.class-tree .virtual-tree .class-tree-item {
   line-height: 25px;
   height: 25px;
 }
 
-class-tree virtual-tree .class-tree-item .name {
+.class-tree .virtual-tree .class-tree-item .name {
   margin-left: 0.5em;
   margin-right: 0.5em;
 }
 
 /* code-view */
 
-code-view .table {
+.code-view .table {
   table-layout: fixed;
 }
 
-code-view th:nth-of-type(1),
-code-view td:nth-of-type(1) {
+.code-view th:nth-of-type(1),
+.code-view td:nth-of-type(1) {
   min-width: 10em;
   text-align: left;
 }
 
-code-view th:nth-of-type(2),
-code-view td:nth-of-type(2) {
+.code-view th:nth-of-type(2),
+.code-view td:nth-of-type(2) {
   min-width: 8em;
   text-align: left;
 }
 
-code-view th:nth-of-type(3),
-code-view td:nth-of-type(3) {
+.code-view th:nth-of-type(3),
+.code-view td:nth-of-type(3) {
   min-width: 8em;
   text-align: left;
 }
 
-code-view th:nth-of-type(4),
-code-view td:nth-of-type(4) {
+.code-view th:nth-of-type(4),
+.code-view td:nth-of-type(4) {
   text-align: left;
   overflow: visible;
   white-space: pre;
@@ -654,47 +654,47 @@
   width: 1px;
 }
 
-code-view th:nth-of-type(5),
-code-view td:nth-of-type(5) {
+.code-view th:nth-of-type(5),
+.code-view td:nth-of-type(5) {
   text-align: left;
   overflow: visible;
 }
 
-code-view tr:hover > td {
+.code-view tr:hover > td {
   background-color: #F4C7C3;
 }
 
-code-view .code-comment {
+.code-view .code-comment {
   color: grey;
   font-style: italic;
 }
 
 /* context-ref */
 
-context-ref > a[href]:hover {
+.context-ref > a[href]:hover {
   text-decoration: underline;
 }
-context-ref > a[href] {
+.context-ref > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-context-ref > a[href] * {
+.context-ref > a[href] * {
   color: inherit;
 }
-context-ref .emphasize {
+.context-ref .emphasize {
   font-style: italic;
 }
 
 
 /* cpu-profile */
 
-cpu-profile {
+.cpu-profile {
   position: relative;
   display: block;
   height: 100%;
 }
 
-cpu-profile > cpu-profile-virtual-tree {
+.cpu-profile > .cpu-profile-virtual-tree {
   position: absolute;
   height: auto;
   top: 320px;
@@ -705,18 +705,18 @@
 
 /* cpu-profile-table */
 
-cpu-profile-table {
+.cpu-profile-table {
   position: relative;
   display: block;
   height: 100%;
 }
-cpu-profile-table cpu-profile-virtual-tree {
+.cpu-profile-table .cpu-profile-virtual-tree {
   height: 100%;
   min-height: 600px;
   padding-top: 250px;
   margin-top: -250px;
 }
-cpu-profile-table .profile-trees {
+.cpu-profile-table .profile-trees {
   vertical-align: text-top;
   min-width: 100%;
   height: 100%;
@@ -728,26 +728,26 @@
   padding-right: 5%;
   min-height: 600px;
 }
-cpu-profile-table .profile-trees virtual-collection {
+.cpu-profile-table .profile-trees .virtual-collection {
   height: 100%;
   width: 100%;
   border: solid 1px #888888;
   box-shadow: 2px 2px 5px #888888;
 }
-cpu-profile-table .profile-trees > .profile-trees-all {
+.cpu-profile-table .profile-trees > .profile-trees-all {
   vertical-align: text-top;
   display: inline-block;
   width: 50%;
   height: 100%;
   padding: 5px;
 }
-cpu-profile-table .profile-trees > .profile-trees-current {
+.cpu-profile-table .profile-trees > .profile-trees-current {
   vertical-align: text-top;
   display: inline-block;
   width: 50%;
   height: 100%;
 }
-cpu-profile-table .profile-trees .profile-trees-caller {
+.cpu-profile-table .profile-trees .profile-trees-caller {
   vertical-align: text-top;
   display: inline-block;
   width: 100%;
@@ -756,7 +756,7 @@
   margin-top: -17px;
   padding-top: 22px;
 }
-cpu-profile-table .profile-trees .profile-trees-selected {
+.cpu-profile-table .profile-trees .profile-trees-selected {
   vertical-align: text-top;
   display: block;
   height: 24px;
@@ -767,14 +767,14 @@
   padding-left: 5px;
   padding-right: 5px;
 }
-cpu-profile-table .profile-trees .profile-trees-selected > * {
+.cpu-profile-table .profile-trees .profile-trees-selected > * {
   white-space: nowrap;
   text-overflow: ellipsis;
   overflow: hidden;
   display: inline-block;
   width: 100%;
 }
-cpu-profile-table .profile-trees .profile-trees-callee {
+.cpu-profile-table .profile-trees .profile-trees-callee {
   vertical-align: text-top;
   display: inline-block;
   width: 100%;
@@ -783,68 +783,68 @@
   margin-bottom: -17px;
   padding-bottom: 22px;
 }
-cpu-profile-table .function-item {
+.cpu-profile-table .function-item {
   box-sizing: border-box;
   line-height: 20px;
 }
-cpu-profile-table .header {
+.cpu-profile-table .header {
   box-sizing: border-box;
   line-height: 20px;
 }
-cpu-profile-table .header .function-item:last-child {
+.cpu-profile-table .header .function-item:last-child {
   margin-bottom: -3px;
   border-bottom: solid 1px #AAAAAA;
 }
-cpu-profile-table .function-item .inclusive,
-cpu-profile-table .function-item .exclusive {
+.cpu-profile-table .function-item .inclusive,
+.cpu-profile-table .function-item .exclusive {
   display: inline-block;
   width: 7em;
   text-align: right;
   padding-right: 0.5em;
   line-height: 20px;
 }
-cpu-profile-table .buffer .function-item .inclusive {
+.cpu-profile-table .buffer .function-item .inclusive {
   background-color: #EEEEEE;
 }
-cpu-profile-table .buffer .function-item.selected .inclusive {
+.cpu-profile-table .buffer .function-item.selected .inclusive {
   background-color: #51a3fb;
 }
-cpu-profile-table .buffer .function-item:hover .inclusive {
+.cpu-profile-table .buffer .function-item:hover .inclusive {
   background-color: #afd5fd;
 }
-cpu-profile-table .header .function-item .inclusive {
+.cpu-profile-table .header .function-item .inclusive {
   background-color: #DDDDDD;
 }
-cpu-profile-table .buffer .function-item.selected {
+.cpu-profile-table .buffer .function-item.selected {
   background-color: #60abfb;
 }
-cpu-profile-table .buffer .function-item:hover {
+.cpu-profile-table .buffer .function-item:hover {
   background-color: #d2e7fe;
 }
-cpu-profile-table .function-item .exclusive {
+.cpu-profile-table .function-item .exclusive {
 }
-cpu-profile-table .function-item .name {
+.cpu-profile-table .function-item .name {
   padding-left: 0.5em;
   padding-left: 0.5em;
 }
-cpu-profile-table .function-item > button,
-cpu-profile-table .function-item > button:active {
+.cpu-profile-table .function-item > button,
+.cpu-profile-table .function-item > button:active {
   background-color: transparent;
   color: #0489c3;
   border-style: none;
 }
-cpu-profile-table .function-item > button:hover {
+.cpu-profile-table .function-item > button:hover {
   text-decoration: underline;
 }
 
 /* cpu-profile-virtual-tree */
 
-cpu-profile-virtual-tree {
+.cpu-profile-virtual-tree {
   display: block;
   height: 600px;
 }
 
-cpu-profile-virtual-tree .tree-item {
+.cpu-profile-virtual-tree .tree-item {
   box-sizing: border-box;
   line-height: 30px;
   height: 30px;
@@ -852,9 +852,9 @@
   padding-right: 5%;
 }
 
-cpu-profile-virtual-tree .tree-item > .inclusive,
-cpu-profile-virtual-tree .tree-item > .exclusive,
-cpu-profile-virtual-tree .tree-item > .percentage {
+.cpu-profile-virtual-tree .tree-item > .inclusive,
+.cpu-profile-virtual-tree .tree-item > .exclusive,
+.cpu-profile-virtual-tree .tree-item > .percentage {
   display: inline-block;
   text-align: right;
   width: 4em;
@@ -862,11 +862,11 @@
   margin-right: 0.25em;
 }
 
-cpu-profile-virtual-tree .tree-item > .exclusive {
+.cpu-profile-virtual-tree .tree-item > .exclusive {
   margin-right: 1.5em;
 }
 
-cpu-profile-virtual-tree .tree-item > .name {
+.cpu-profile-virtual-tree .tree-item > .name {
   display: inline;
   margin-left: 0.5em;
   margin-right: 0.5em;
@@ -874,116 +874,116 @@
 
 /* curly-block */
 
-curly-block span.curly-block {
+.curly-block span.curly-block {
   color: #0489c3;
   cursor: pointer;
 }
-curly-block span.curly-block.disabled {
+.curly-block span.curly-block.disabled {
   color: white;
   cursor: wait;
 }
 
 /* debugger-console */
 
-debugger-console {
+.debugger-console {
   display: block;
   margin: 0px 20px 10px 20px;
 }
-debugger-console .normal {
+.debugger-console .normal {
   font: normal 14px consolas, courier, monospace;
   white-space: pre;
   line-height: 125%;
 }
-debugger-console .bold {
+.debugger-console .bold {
   font: bold 14px consolas, courier, monospace;
   white-space: pre;
   line-height: 125%;
 }
-debugger-console .red {
+.debugger-console .red {
   font: normal 14px consolas, courier, monospace;
   white-space: pre;
   line-height: 125%;
   color: red;
 }
-debugger-console .green {
+.debugger-console .green {
   font: normal 14px consolas, courier, monospace;
   white-space: pre;
   line-height: 125%;
   color: green;
 }
-debugger-console .spacer {
+.debugger-console .spacer {
   height: 20px;
 }
 
 /* debugger-frame */
 
-debugger-frame {
+.debugger-frame {
   display: block;
   position: relative;
   padding: 5px;
   border: 1px solid white;
 }
-debugger-frame:hover {
+.debugger-frame:hover {
   border: 1px solid #e0e0e0;
 }
-debugger-frame.shadow {
+.debugger-frame.shadow {
   box-shadow:  0 2px 10px 0 rgba(0, 0, 0, 0.16),
                0 2px 5px 0 rgba(0, 0, 0, 0.26);
 }
-debugger-frame.causalFrame {
+.debugger-frame.causalFrame {
   background-color: #D7CCC8;
 }
-debugger-frame.current {
+.debugger-frame.current {
   box-shadow:  0 2px 10px 0 rgba(0, 0, 0, 0.26),
                0 2px 5px 0 rgba(0, 0, 0, 0.46);
   border: 1px solid #444;
 }
-debugger-frame > button {
+.debugger-frame > button {
   display: block;
   width: 100%;
   text-align: left;
   background-color: transparent;
   border: none;
 }
-debugger-frame .frameSummaryText {
+.debugger-frame .frameSummaryText {
   display: inline-block;
   padding: 5px;
 }
-debugger-frame .frameId {
+.debugger-frame .frameId {
   display: inline-block;
   width: 60px;
 }
-debugger-frame .frameExpander {
+.debugger-frame .frameExpander {
   position: absolute;
   right: 5px;
   top: 5px;
   display: none;
 }
-debugger-frame:hover .frameExpander{
+.debugger-frame:hover .frameExpander{
   display: inline-block;
 }
-debugger-frame .frameContractor {
+.debugger-frame .frameContractor {
   position: absolute;
   right: 5px;
   bottom: 5px;
   display: inline-block;
 }
-debugger-frame .frameContractor > button {
+.debugger-frame .frameContractor > button {
   background-color: transparent;
   border: none;
 }
-debugger-frame .flex-item-script {
+.debugger-frame .flex-item-script {
   flex-grow: 1;
   flex-shrink: 1;
   flex-basis: 765px;
 }
-debugger-frame .flex-item-vars {
+.debugger-frame .flex-item-vars {
   flex-grow: 5;
   flex-shrink: 0;
   flex-basis: 250px;
   overflow-x: hidden;
 }
-debugger-frame .frameVars {
+.debugger-frame .frameVars {
   position: relative;
   top: 5px;
   padding-left:2em;
@@ -992,20 +992,20 @@
 
 /* debugger-input */
 
-debugger-input .container {
+.debugger-input .container {
   height: 100%;
   display: flex;
   flex-direction: row;
   justify-content: space-between;
 }
-debugger-input .textBox {
+.debugger-input .textBox {
   flex: 1 1 auto;
   margin: 20px;
   padding: 5px;
   font: 400 16px consolas, courier, monospace;
   width: 95%;
 }
-debugger-input .modalPrompt {
+.debugger-input .modalPrompt {
   flex: 0 0 auto;
   margin-top: 20px;
   margin-left: 20px;
@@ -1013,70 +1013,70 @@
   font: 400 16px consolas, courier, monospace;
   color: red;
 }
-debugger-input .modalPrompt.hidden {
+.debugger-input .modalPrompt.hidden {
   display: none;
 }
 
 /* debugger-message */
 
-debugger-message {
+.debugger-message {
   display: block;
   position: relative;
   padding: 5px;
   border: 1px solid white;
 }
-debugger-message:hover {
+.debugger-message:hover {
   border: 1px solid #e0e0e0;
 }
-debugger-message.shadow {
+.debugger-message.shadow {
   box-shadow:  0 2px 10px 0 rgba(0, 0, 0, 0.16),
   0 2px 5px 0 rgba(0, 0, 0, 0.26);
 }
-debugger-message.current {
+.debugger-message.current {
   box-shadow:  0 2px 10px 0 rgba(0, 0, 0, 0.26),
   0 2px 5px 0 rgba(0, 0, 0, 0.46);
   border: 1px solid #444;
 }
-debugger-message > button {
+.debugger-message > button {
   display: block;
   width: 100%;
   text-align: left;
   background-color: transparent;
   border: none;
 }
-debugger-message .messageSummaryText {
+.debugger-message .messageSummaryText {
   display: inline-block;
   padding: 5px;
 }
-debugger-message .messageId {
+.debugger-message .messageId {
   display: inline-block;
   font-weight: bold;
   width: 100px;
 }
-debugger-message .messageExpander {
+.debugger-message .messageExpander {
   position: absolute;
   right: 5px;
   top: 5px;
   display: none;
 }
-debugger-message:hover .messageExpander {
+.debugger-message:hover .messageExpander {
   display: inline-block;
 }
-debugger-message.shadow:hover .messageExpander {
+.debugger-message.shadow:hover .messageExpander {
   display: none;
 }
-debugger-message .messageContractor {
+.debugger-message .messageContractor {
   position: absolute;
   right: 5px;
   bottom: 5px;
   display: inline-block;
 }
-debugger-message .flex-item-script {
+.debugger-message .flex-item-script {
   flex-grow: 1;
   flex-shrink: 1;
   flex-basis: 765px;
 }
-debugger-message .flex-item-vars {
+.debugger-message .flex-item-vars {
   flex-grow: 5;
   flex-shrink: 0;
   flex-basis: 225px;
@@ -1084,77 +1084,77 @@
 
 /* debugger-page */
 
-debugger-page {
+.debugger-page {
   height: 100%;
 }
-debugger-page .variable {
+.debugger-page .variable {
   height: 100%;
   margin-bottom: -75px;
   padding-bottom: 75px;
 }
-debugger-page .stack {
+.debugger-page .stack {
   flex: 0 0 auto;
   overflow-y: auto;
   height: 62%;
 }
-debugger-page .splitter {
+.debugger-page .splitter {
   height: 0px;
   margin: 0px;
   font-size: 1px;
   border-bottom: 1px solid #888;
 }
-debugger-page .console {
+.debugger-page .console {
   flex: 1 1 auto;
   overflow-x: auto;
   overflow-y: auto;
   height: 38%;
 }
-debugger-page .commandline {
+.debugger-page .commandline {
   flex: 0 0 auto;
 }
 
 /* debugger-stack */
 
-debugger-stack {
+.debugger-stack {
   position: relative;
 }
-debugger-stack .sampledMessage {
+.debugger-stack .sampledMessage {
   margin: 0px 20px 10px 20px;
   font: 400 14px 'Montserrat', sans-serif;
   line-height: 125%;
 }
-debugger-stack .sampledMessage > button {
+.debugger-stack .sampledMessage > button {
   background-color: transparent;
   border: none;
   color: #0489c3;
   text-decoration: none;
   margin-right: 1em;
 }
-debugger-stack .sampledMessage > button:hover {
+.debugger-stack .sampledMessage > button:hover {
     text-decoration: underline;
 }
-debugger-stack .splitter {
+.debugger-stack .splitter {
   height: 0px;
   margin: 0px;
   font-size: 1px;
   border-bottom: 1px dashed #888;
 }
-debugger-stack .noMessages,
-debugger-stack .noStack {
+.debugger-stack .noMessages,
+.debugger-stack .noStack {
   margin: 10px 0px 10px 25px;
   font: bold 14px 'Montserrat', sans-serif;
   line-height: 125%;
 }
 
-debugger-stack .sampledMessage.hidden,
-debugger-stack .noMessages.hidden,
-debugger-stack .noStack.hidden {
+.debugger-stack .sampledMessage.hidden,
+.debugger-stack .noMessages.hidden,
+.debugger-stack .noStack.hidden {
   display: none;
 }
 
 /* error-ref */
 
-error-ref > pre {
+.error-ref > pre {
   background-color: #f5f5f5;
   border: 1px solid #ccc;
   padding-left: 10px;
@@ -1167,19 +1167,19 @@
 
 /* eval-box */
 
-eval-box a[href]:hover {
+.eval-box a[href]:hover {
     text-decoration: underline;
 }
-eval-box a[href] {
+.eval-box a[href] {
     color: #0489c3;
     text-decoration: none;
 }
-eval-box .quicks > button:hover {
+.eval-box .quicks > button:hover {
   background-color: transparent;
   border: none;
   text-decoration: underline;
 }
-eval-box .quicks > button {
+.eval-box .quicks > button {
   background-color: transparent;
   border: none;
   color: #0489c3;
@@ -1187,15 +1187,15 @@
   margin-right: 1em;
   text-decoration: none;
 }
-eval-box .emphasize {
+.eval-box .emphasize {
   font-style: italic;
 }
-eval-box .indent {
+.eval-box .indent {
   margin-left: 1.5em;
   font: 400 14px 'Montserrat', sans-serif;
   line-height: 150%;
 }
-eval-box .stackTraceBox {
+.eval-box .stackTraceBox {
   margin-left: 1.5em;
   background-color: #f5f5f5;
   border: 1px solid #ccc;
@@ -1205,7 +1205,7 @@
   white-space: pre;
   overflow-x: auto;
 }
-eval-box .heading {
+.eval-box .heading {
   line-height: 30px;
   position: relative;
   box-sizing: border-box;
@@ -1213,24 +1213,24 @@
   min-width: 450px;
   padding-right: 150px;
 }
-eval-box .heading .textbox {
+.eval-box .heading .textbox {
   width: 100%;
   min-width: 300px;
 }
-eval-box .heading .buttons {
+.eval-box .heading .buttons {
   position: absolute;
   top: 0;
   right: 0px;
 }
-eval-box .heading .buttons button{
+.eval-box .heading .buttons button{
   margin-right: 1em;
 }
-eval-box.historyExpr,
-eval-box .historyValue {
+.eval-box.historyExpr,
+.eval-box .historyValue {
   vertical-align: text-top;
   font: 400 14px 'Montserrat', sans-serif;
 }
-eval-box .historyExpr button {
+.eval-box .historyExpr button {
   display: block;
   color: black;
   border: none;
@@ -1240,14 +1240,14 @@
   cursor: pointer;
   white-space: pre-line;
 }
-eval-box .historyExpr button:hover {
+.eval-box .historyExpr button:hover {
   background-color: #fff3e3;
 }
-eval-box .historyValue {
+.eval-box .historyValue {
   display: block;
   padding: 6px 6px;
 }
-eval-box .historyDelete button {
+.eval-box .historyDelete button {
   border: none;
   background: none;
 }
@@ -1257,48 +1257,48 @@
 
 /* flag-list */
 
-flag-list .comment {
+.flag-list .comment {
   color: #aaa;
 }
 
-flag-list .flag {
+.flag-list .flag {
   padding: 3px 0;
 }
 
-flag-list .name {
+.flag-list .name {
   font-weight: bold;
   margin-right: 0.7em;
 }
 
-flag-list .value {
+.flag-list .value {
   margin-left: 0.7em;
 }
 
 /* function-ref */
 
-function-ref > a[href]:hover {
+.function-ref > a[href]:hover {
   text-decoration: underline;
 }
-function-ref > a[href] {
+.function-ref > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-function-ref .emphasize {
+.function-ref .emphasize {
   font-style: italic;
 }
 
 
 /* heap-snapshot */
 
-heap-snapshot .statusMessage {
+.heap-snapshot .statusMessage {
   font-size: 150%;
   font-weight: bold;
 }
-heap-snapshot .statusBox {
+.heap-snapshot .statusBox {
   height: 100%;
   padding: 1em;
 }
-heap-snapshot .explanation {
+.heap-snapshot .explanation {
   display: block;
   display: -webkit-box;
   -webkit-line-clamp: 4;
@@ -1307,7 +1307,7 @@
   overflow: hidden;
   text-overflow: ellipsis;
 }
-heap-snapshot virtual-tree {
+.heap-snapshot .virtual-tree {
   position: absolute;
   height: auto;
   top: 250px;
@@ -1315,15 +1315,15 @@
   left: 0;
   right: 0;
 }
-heap-snapshot .tree-item {
+.heap-snapshot .tree-item {
   box-sizing: border-box;
   line-height: 30px;
   height: 30px;
   padding-left: 5%;
   padding-right: 5%;
 }
-heap-snapshot .tree-item > .size,
-heap-snapshot .tree-item > .percentage {
+.heap-snapshot .tree-item > .size,
+.heap-snapshot .tree-item > .percentage {
   display: inline-block;
   text-align: right;
   width: 4em;
@@ -1331,7 +1331,7 @@
   margin-right: 0.25em;
 }
 
-heap-snapshot .tree-item > .name {
+.heap-snapshot .tree-item > .name {
   display: inline;
   margin-left: 0.5em;
   margin-right: 0.5em;
@@ -1340,37 +1340,37 @@
 
 /* icdata-ref */
 
-icdata-ref > a[href]:hover {
+.icdata-ref > a[href]:hover {
   text-decoration: underline;
 }
-icdata-ref > a[href] {
+.icdata-ref > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-icdata-ref > a[href] * {
+.icdata-ref > a[href] * {
   color: inherit;
 }
-icdata-ref .emphasize {
+.icdata-ref .emphasize {
   font-style: italic;
 }
 
 
 /* inbound-reference */
 
-inbound-reference > a[href]:hover {
+.inbound-reference > a[href]:hover {
   text-decoration: underline;
 }
-inbound-reference > a[href] {
+.inbound-reference > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
 
-inbound-reference .indent {
+.inbound-reference .indent {
   margin-left: 1.5em;
   font: 400 14px 'Montserrat', sans-serif;
   line-height: 150%;
 }
-inbound-reference .stackTraceBox {
+.inbound-reference .stackTraceBox {
   margin-left: 1.5em;
   background-color: #f5f5f5;
   border: 1px solid #ccc;
@@ -1383,25 +1383,25 @@
 
 /* instance-ref */
 
-instance-ref > a[href]:hover {
+.instance-ref > a[href]:hover {
   text-decoration: underline;
 }
-instance-ref > a[href] {
+.instance-ref > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-instance-ref > a[href] * {
+.instance-ref > a[href] * {
   color: inherit;
 }
-instance-ref .emphasize {
+.instance-ref .emphasize {
   font-style: italic;
 }
-instance-ref .indent {
+.instance-ref .indent {
   margin-left: 1.5em;
   font: 400 14px 'Montserrat', sans-serif;
   line-height: 150%;
 }
-instance-ref .stackTraceBox {
+.instance-ref .stackTraceBox {
   margin-left: 1.5em;
   background-color: #f5f5f5;
   border: 1px solid #ccc;
@@ -1414,20 +1414,20 @@
 
 /* isolate-counter-chart */
 
-isolate-counter-chart {
+.isolate-counter-chart {
   display: block;
   position: relative;
   height: 300px;
   min-width: 350px;
 }
-isolate-counter-chart > div.host {
+.isolate-counter-chart > div.host {
   position: absolute;
   left: 0;
   bottom: 20px;
   top: 5px;
   right: 250px;
 }
-isolate-counter-chart > div.legend {
+.isolate-counter-chart > div.legend {
   position: absolute;
   width: 250px;
   top: 0;
@@ -1438,42 +1438,42 @@
 
 /* isolate-location */
 
-isolate-location > span {
+.isolate-location > span {
   font-weight: bold;
 }
-isolate-location > a[href] {
+.isolate-location > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-isolate-location > a[href]:hover {
+.isolate-location > a[href]:hover {
   text-decoration: underline;
 }
 
 /* isolate-reconnect */
 
-isolate-reconnect div.doubleSpaced {
+.isolate-reconnect div.doubleSpaced {
   line-height: 2em;
 }
 
 /* isolate-ref */
 
-isolate-ref > a[href]:hover {
+.isolate-ref > a[href]:hover {
   text-decoration: underline;
 }
-isolate-ref > a[href] {
+.isolate-ref > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
 
 /* isolate-run-state */
 
-isolate-run-state > span {
+.isolate-run-state > span {
   font-weight: bold;
 }
 
 /* isolate-shared-summary */
 
-isolate-shared-summary {
+.isolate-shared-summary {
   display: block;
 }
 
@@ -1487,23 +1487,23 @@
   min-width: 18ex;
 }
 
-isolate-shared-summary > .summary {
+.isolate-shared-summary > .summary {
   height: 300px;
   position: relative;
 }
-isolate-shared-summary .menu {
+.isolate-shared-summary .menu {
   float: right;
   top: 0;
   right: 0;
 }
-isolate-shared-summary isolate-counter-chart {
+.isolate-shared-summary .isolate-counter-chart {
   position: absolute;
   left: 0;
   top: 0;
   right: 230px;
   clear: both;
 }
-isolate-shared-summary .errorBox {
+.isolate-shared-summary .errorBox {
   background-color: #f5f5f5;
   border: 1px solid #ccc;
   padding: 2em;
@@ -1515,14 +1515,14 @@
 
 /* library-ref */
 
-library-ref > a[href]:hover {
+.library-ref > a[href]:hover {
   text-decoration: underline;
 }
-library-ref > a[href] {
+.library-ref > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-library-ref .emphasize {
+.library-ref .emphasize {
   font-style: italic;
 }
 
@@ -1539,103 +1539,103 @@
 
 /* logging-list */
 
-logging-list .outlined {
+.logging-list .outlined {
   -webkit-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
   -moz-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
   box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
   margin: 4px;
 }
-logging-list .logItem {
+.logging-list .logItem {
   display: inline-block;
   font: normal 14px consolas, courier, monospace;
   white-space: pre;
   line-height: 125%;
   width: 100%;
 }
-logging-list .level {
+.logging-list .level {
   display: inline-block;
   width: 5em;
 }
-logging-list .time {
+.logging-list .time {
   display: inline-block;
   width: 12em;
 }
-logging-list .FINEST {
+.logging-list .FINEST {
   background-color: #FAFAFA;
 }
-logging-list .FINER {
+.logging-list .FINER {
   background-color: #ECEFF1;
 }
-logging-list .FINE {
+.logging-list .FINE {
   background-color: #EFEBE9;
 }
-logging-list .CONFIG {
+.logging-list .CONFIG {
   background-color: #FFF3E0;
 }
-logging-list .INFO {
+.logging-list .INFO {
   background-color: #F1F8E9;
 }
-logging-list .WARNING {
+.logging-list .WARNING {
   background-color: #FFE0B2;
 }
-logging-list .SEVERE {
+.logging-list .SEVERE {
   background-color: #FFCCBC;
 }
-logging-list .SHOUT {
+.logging-list .SHOUT {
   background-color: #FFCDD2;
 }
 
 /* memory-graph */
 
-memory-graph .chart-legend-row,
-memory-graph .chart-legend-row div {
+.memory-graph .chart-legend-row,
+.memory-graph .chart-legend-row div {
   display: inline;
 }
 
-memory-graph .chart-legend-row div.chart-legend-color {
+.memory-graph .chart-legend-row div.chart-legend-color {
   display: inline-block;
   margin: auto 8px;
 }
 
-memory-graph .chart-legend-row:nth-child(2n) div.chart-legend-color {
+.memory-graph .chart-legend-row:nth-child(2n) div.chart-legend-color {
   display: none;
 }
 
 /* megamorphic-cache-ref */
 
-megamorphic-cache-ref > a[href]:hover {
+.megamorphic-cache-ref > a[href]:hover {
     text-decoration: underline;
 }
-megamorphic-cache-ref > a[href] {
+.megamorphic-cache-ref > a[href] {
     color: #0489c3;
     text-decoration: none;
 }
-megamorphic-cache-ref > a[href] * {
+.megamorphic-cache-ref > a[href] * {
     color: inherit;
 }
-megamorphic-ref .emphasize {
+.megamorphic-ref .emphasize {
   font-style: italic;
 }
 
 /* dashboards common */
 
-memory-dashboard,
-timeline-dashboard {
+.memory-dashboard,
+.timeline-dashboard {
   display: block;
   height: 100%;
   margin-top: -30px;
 }
 
-memory-profile > div > h1,
-timeline-dashboard > div > h1 {
+.memory-profile > div > h1,
+.timeline-dashboard > div > h1 {
   overflow: hidden;
   border-bottom: 1px solid #d5d5d5;
 }
 
-memory-dashboard button:disabled,
-timeline-dashboard button:disabled,
-memory-dashboard button:disabled:hover,
-timeline-dashboard button:disabled:hover {
+.memory-dashboard button:disabled,
+.timeline-dashboard button:disabled,
+.memory-dashboard button:disabled:hover,
+.timeline-dashboard button:disabled:hover {
   text-decoration: none;
   background-color: #eee;
   background-image: linear-gradient(#eee, #eee);
@@ -1644,14 +1644,14 @@
   cursor: default;
 }
 
-timeline-dashboard p {
+.timeline-dashboard p {
   margin-top: 0.4em;
 }
 
-memory-dashboard button,
-timeline-dashboard button,
-memory-dashboard button:active,
-timeline-dashboard button:active {
+.memory-dashboard button,
+.timeline-dashboard button,
+.memory-dashboard button:active,
+.timeline-dashboard button:active {
   text-decoration: none;
   background-color: #ddd;
   background-image: linear-gradient(#eee, #ddd);
@@ -1660,23 +1660,23 @@
   cursor: pointer;
 }
 
-memory-dashboard button:hover,
-timeline-dashboard button:hover {
+.memory-dashboard button:hover,
+.timeline-dashboard button:hover {
   text-decoration: none;
   background-color: #ccc;
   background-image: linear-gradient(#ddd, #ccc);
   border-color: #c7c7c7;
 }
 
-memory-profile .header_button,
-timeline-dashboard .header_button {
+.memory-profile .header_button,
+.timeline-dashboard .header_button {
   padding: 3px 5px;
   margin: 0px 1px;
   min-width: 130px;
 }
 
-memory-profile .header_button,
-timeline-dashboard .header_button {
+.memory-profile .header_button,
+.timeline-dashboard .header_button {
   margin-left: 6px;
 }
 
@@ -1684,32 +1684,32 @@
   margin-left: 75px;
 }
 
-memory-profile .header_button:first-child,
-timeline-dashboard .header_button:first-child {
+.memory-profile .header_button:first-child,
+.timeline-dashboard .header_button:first-child {
   margin-left: 30px;
 }
 
-memory-profile .tab_buttons,
-timeline-dashboard .tab_buttons {
+.memory-profile .tab_buttons,
+.timeline-dashboard .tab_buttons {
   position: relative;
   top: 1px;
   float: right;
 }
 
-memory-profile .tab_buttons button,
-timeline-dashboard .tab_buttons button {
+.memory-profile .tab_buttons button,
+.timeline-dashboard .tab_buttons button {
   padding: 5px 5px;
   min-width: 100px
 }
 
-memory-profile .tab_buttons button:not(:first-child),
-timeline-dashboard .tab_buttons button:not(:first-child) {
+.memory-profile .tab_buttons button:not(:first-child),
+.timeline-dashboard .tab_buttons button:not(:first-child) {
   border-top-left-radius: 0px;
   border-bottom-left-radius: 0px;
 }
 
-memory-profile .tab_buttons button:not(:last-child),
-timeline-dashboard  .tab_buttons button:not(:last-child) {
+.memory-profile .tab_buttons button:not(:last-child),
+.timeline-dashboard  .tab_buttons button:not(:last-child) {
   border-top-right-radius: 0px;
   border-bottom-right-radius: 0px;
 }
@@ -1717,11 +1717,11 @@
 
 /* memory-dashboard */
 
-memory-dashboard memory-graph {
+.memory-dashboard .memory-graph {
   height: 350px;
 }
 
-memory-dashboard memory-profile {
+.memory-dashboard .memory-profile {
   position: absolute;
   bottom: 20px;
   left: 0;
@@ -1729,7 +1729,7 @@
   top: 300px;
 }
 
-memory-dashboard memory-profile memory-allocations {
+.memory-dashboard .memory-profile .memory-allocations {
   position: absolute;
   bottom: 0;
   left: 0;
@@ -1737,7 +1737,7 @@
   top: 39px;
 }
 
-memory-dashboard memory-profile memory-snapshot {
+.memory-dashboard .memory-profile .memory-snapshot {
   position: absolute;
   bottom: 0;
   left: 0;
@@ -1747,76 +1747,76 @@
 
 /* metric-graph */
 
-metric-graph {
+.metric-graph {
   display: block;
 }
 
-metric-graph .graph {
+.metric-graph .graph {
   height: 100%;
   margin-top: -30px;
   padding: 20px;
   padding-top: 60px;
 }
 
-metric-graph .graph > div {
+.metric-graph .graph > div {
   height: 100%;
 }
 
 /* memory-allocations */
 
-memory-allocations .container {
+.memory-allocations .container {
   padding-left: 5%;
   padding-right: 5%;
 }
 
-memory-allocations .collection-item {
+.memory-allocations .collection-item {
   background-color: #FFFFFF;
   box-sizing: border-box;
   line-height: 20px;
 }
 
-memory-allocations .collection-item:hover {
+.memory-allocations .collection-item:hover {
   background-color: #d2e7fe;
 }
 
-memory-allocations .header .collection-item:hover {
+.memory-allocations .header .collection-item:hover {
   background-color: #FFFFFF;
 }
 
-memory-allocations .header .collection-item:last-child {
+.memory-allocations .header .collection-item:last-child {
   margin-bottom: -3px;
   border-bottom: solid 1px #AAAAAA;
 }
 
-memory-allocations .header .collection-item span {
+.memory-allocations .header .collection-item span {
   font-weight: bolder;
 }
 
-memory-allocations .collection-item :nth-child(2n+2).group,
-memory-allocations .collection-item :nth-child(4n+3),
-memory-allocations .collection-item :nth-child(4n+4) {
+.memory-allocations .collection-item :nth-child(2n+2).group,
+.memory-allocations .collection-item :nth-child(4n+3),
+.memory-allocations .collection-item :nth-child(4n+4) {
   background-color: #EEEEEE;
 }
 
-memory-allocations .collection-item:hover :nth-child(2n+2).group,
-memory-allocations .collection-item:hover :nth-child(4n+3),
-memory-allocations .collection-item:hover :nth-child(4n+4) {
+.memory-allocations .collection-item:hover :nth-child(2n+2).group,
+.memory-allocations .collection-item:hover :nth-child(4n+3),
+.memory-allocations .collection-item:hover :nth-child(4n+4) {
   background-color: #afd5fd;
 }
 
-memory-allocations .header .collection-item :nth-child(2n+1).group,
-memory-allocations .header .collection-item :nth-child(4n+1),
-memory-allocations .header .collection-item :nth-child(4n+2) {
+.memory-allocations .header .collection-item :nth-child(2n+1).group,
+.memory-allocations .header .collection-item :nth-child(4n+1),
+.memory-allocations .header .collection-item :nth-child(4n+2) {
   background-color: #FFFFFF;
 }
 
-memory-allocations .header .collection-item :nth-child(2n+2).group,
-memory-allocations .header .collection-item :nth-child(4n+3),
-memory-allocations .header .collection-item :nth-child(4n+4) {
+.memory-allocations .header .collection-item :nth-child(2n+2).group,
+.memory-allocations .header .collection-item :nth-child(4n+3),
+.memory-allocations .header .collection-item :nth-child(4n+4) {
   background-color: #DDDDDD;
 }
 
-memory-allocations .collection-item .group {
+.memory-allocations .collection-item .group {
   display: inline-block;
   width: 12em;
   text-align: right;
@@ -1825,7 +1825,7 @@
   border-right: solid 1px #AAAAAA;
 }
 
-memory-allocations .collection-item .bytes {
+.memory-allocations .collection-item .bytes {
   display: inline-block;
   width: 6em;
   text-align: right;
@@ -1833,7 +1833,7 @@
   padding-right: 0.5em;
 }
 
-memory-allocations .collection-item .instances {
+.memory-allocations .collection-item .instances {
   display: inline-block;
   width: 6em;
   text-align: right;
@@ -1842,16 +1842,16 @@
   border-right: solid 1px #AAAAAA;
 }
 
-memory-allocations .collection-item .name {
+.memory-allocations .collection-item .name {
   padding-left: 0.5em;
   padding-right: 0.5em;
   display: inline-block;
 }
 
-memory-allocations .collection-item > button,
-memory-allocations .collection-item > button:active,
-memory-allocations .collection-item .group button,
-memory-allocations .collection-item .group button:active {
+.memory-allocations .collection-item > button,
+.memory-allocations .collection-item > button:active,
+.memory-allocations .collection-item .group button,
+.memory-allocations .collection-item .group button:active {
   background: transparent;
   color: #0489c3;
   border: 0px none;
@@ -1859,8 +1859,8 @@
   padding: 0;
 }
 
-memory-allocations .collection-item > button:hover,
-memory-allocations .collection-item .group button:hover {
+.memory-allocations .collection-item > button:hover,
+.memory-allocations .collection-item .group button:hover {
   text-decoration: underline;
   border-radius: 0px;
 }
@@ -1868,15 +1868,15 @@
 
 /* memory-snapshot */
 
-memory-snapshot .statusMessage {
+.memory-snapshot .statusMessage {
   font-size: 150%;
   font-weight: bold;
 }
-memory-snapshot .statusBox {
+.memory-snapshot .statusBox {
   height: 100%;
   padding: 1em;
 }
-memory-snapshot .explanation {
+.memory-snapshot .explanation {
   display: block;
   display: -webkit-box;
   -webkit-line-clamp: 4;
@@ -1885,7 +1885,7 @@
   overflow: hidden;
   text-overflow: ellipsis;
 }
-memory-snapshot virtual-tree {
+.memory-snapshot .virtual-tree {
   position: absolute;
   height: auto;
   top: 50px;
@@ -1893,15 +1893,15 @@
   left: 0;
   right: 0;
 }
-memory-snapshot .tree-item {
+.memory-snapshot .tree-item {
   box-sizing: border-box;
   line-height: 30px;
   height: 30px;
   padding-left: 5%;
   padding-right: 5%;
 }
-memory-snapshot .tree-item > .size,
-memory-snapshot .tree-item > .percentage {
+.memory-snapshot .tree-item > .size,
+.memory-snapshot .tree-item > .percentage {
   display: inline-block;
   text-align: right;
   width: 4em;
@@ -1909,19 +1909,19 @@
   margin-right: 0.25em;
 }
 
-memory-snapshot .tree-item > .name {
+.memory-snapshot .tree-item > .name {
   display: inline;
   margin-left: 0.5em;
 }
 
 /* metric-graph */
 
-metrics-page > div {
+.metrics-page > div {
   display: block;
   height: 100%;
 }
 
-metrics-page > div > .graph {
+.metrics-page > div > .graph {
   display: block;
   height: 100%;
   margin-top: -300px;
@@ -1958,7 +1958,7 @@
   margin-right: 0.5em;
 }
 nav.nav-bar > ul *:first-child li.nav-menu:before,
-nav.nav-bar > ul nav-reload > li:before {
+nav.nav-bar > ul .nav-reload > li:before {
   content: '';
   margin-left: 0;
   margin-right: 0;
@@ -1997,21 +1997,21 @@
 
 /* nav-menu-item */
 
-nav-menu-item li.nav-menu-item {
+.nav-menu-item li.nav-menu-item {
   float: none;
   border-top: 1px solid #677;
   border-bottom: 1px solid #556; position: relative;
 }
-nav-menu-item li.nav-menu-item:hover {
+.nav-menu-item li.nav-menu-item:hover {
   background: #455;
 }
-nav-menu-item li.nav-menu-item > a {
+.nav-menu-item li.nav-menu-item > a {
   display: block;
   padding: 12px 12px;
   color: white;
   text-decoration: none;
 }
-nav-menu-item li.nav-menu-item > ul {
+.nav-menu-item li.nav-menu-item > ul {
   display: none;
   position: absolute;
   top:0;
@@ -2025,19 +2025,19 @@
   color: white;
   background: #567;
 }
-nav-menu-item li.nav-menu-item > ul:after {
+.nav-menu-item li.nav-menu-item > ul:after {
   content: ""; clear: both; display: block;
 }
-nav-menu-item li.nav-menu-item:hover > ul {
+.nav-menu-item li.nav-menu-item:hover > ul {
   display: block;
 }
 
 /* nav-notify */
 
-nav-notify > div {
+.nav-notify > div {
   float: right;
 }
-nav-notify > div > div {
+.nav-notify > div > div {
   display: block;
   position: absolute;
   top: 98%;
@@ -2051,7 +2051,7 @@
 
 /* nav-exception & nav-event */
 
-nav-exception > div, nav-event > div {
+.nav-exception > div, .nav-event > div {
   position: relative;
   padding: 16px;
   margin-top: 10px;
@@ -2066,28 +2066,28 @@
   animation: fadein 1s;
 }
 
-nav-exception *, nav-event * {
+.nav-exception *, .nav-event * {
   color: #ddd;
   font-size: 12px;
 }
 
-nav-exception > div > a[href],
-nav-event > div > a[href] {
+.nav-exception > div > a[href],
+.nav-event > div > a[href] {
   color: white;
   text-decoration: none;
 }
 
-nav-exception > div > a[href]:hover,
-nav-event > div > a[href]:hover {
+.nav-exception > div > a[href]:hover,
+.nav-event > div > a[href]:hover {
   text-decoration: underline;
 }
 
-nav-exception > div > div {
+.nav-exception > div > div {
   margin-left:20px;
   white-space: pre
 }
 
-nav-exception > div > button, nav-event > div > button {
+.nav-exception > div > button, .nav-event > div > button {
   background: transparent;
   border: none;
   position: absolute;
@@ -2104,13 +2104,13 @@
   text-align: center;
 }
 
-nav-exception > div > button:hover, nav-event > div > button:hover {
+.nav-exception > div > button:hover, .nav-event > div > button:hover {
   background: rgba(255,255,255,0.5);
 }
 
 /* nav-refresh */
 
-nav-refresh > li > button {
+.nav-refresh > li > button {
   color: #000;
   margin: 3px;
   padding: 8px;
@@ -2119,18 +2119,18 @@
   font-size: 13px;
   font: 400 'Montserrat', sans-serif;
 }
-nav-refresh > li > button[disabled] {
+.nav-refresh > li > button[disabled] {
   color: #aaa;
   cursor: wait;
 }
-nav-refresh > li {
+.nav-refresh > li {
   float: right;
   margin: 0;
 }
 
 /* nav-refresh */
 
-nav-reload > li > button {
+.nav-reload > li > button {
   color: #000;
   margin: 3px;
   padding: 8px;
@@ -2139,36 +2139,36 @@
   font-size: 13px;
   font: 400 'Montserrat', sans-serif;
 }
-nav-reload ul > li {
+.nav-reload ul > li {
   display: block;
   width: 100%;
   padding: 2px;
 }
-nav-reload ul > li > button {
+.nav-reload ul > li > button {
   display: inline-block;
   padding: 8px;
   width: 100%;
 }
-nav-reload > li > button[disabled],
-nav-reload ul > li > button[disabled] {
+.nav-reload > li > button[disabled],
+.nav-reload ul > li > button[disabled] {
   color: #aaa;
   cursor: wait;
 }
-nav-reload > li {
+.nav-reload > li {
   float: right;
   margin: 0;
 }
 
 /* object-common && class-instances */
 
-class-instances button:hover,
-object-common button:hover {
+.class-instances button:hover,
+.object-common button:hover {
   background-color: transparent;
   border: none;
   text-decoration: underline;
 }
-class-instances button,
-object-common button {
+.class-instances button,
+.object-common button {
   background-color: transparent;
   border: none;
   color: #0489c3;
@@ -2180,126 +2180,126 @@
 
 /* object-pool-ref */
 
-object-pool-ref > a[href]:hover {
+.object-pool-ref > a[href]:hover {
   text-decoration: underline;
 }
 
-object-pool-ref > a[href] {
+.object-pool-ref > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-object-pool-ref > a[href] * {
+.object-pool-ref > a[href] * {
   color: inherit;
 }
-object-pool-ref .emphasize {
+.object-pool-ref .emphasize {
   font-style: italic;
 }
 
 /* object-pool-view */
 
-object-pool-view .hexadecimal {
+.object-pool-view .hexadecimal {
   font-family: monospace;
 }
 
 /* observatory-application */
 
-observatory-application {
+.observatory-application {
   display: block;
   height: 100%;
 }
 
-observatory-application > div {
+.observatory-application > div {
   display: block;
   height: 100%;
 }
 
 /* persistent-handles-page */
 
-persistent-handles-page {
+.persistent-handles-page {
   display: block;
   height: 100%;
 }
-persistent-handles-page .persistent-handles,
-persistent-handles-page .weak-persistent-handles {
+.persistent-handles-page .persistent-handles,
+.persistent-handles-page .weak-persistent-handles {
   margin-top: -70px;
   padding-top: 70px;
   height: 50%;
 }
-persistent-handles-page .weak-item,
-persistent-handles-page .collection-item {
+.persistent-handles-page .weak-item,
+.persistent-handles-page .collection-item {
   box-sizing: border-box;
   line-height: 20px;
   padding-left: 5%;
   padding-right: 5%;
 }
-persistent-handles-page .header {
+.persistent-handles-page .header {
   box-sizing: border-box;
   line-height: 20px;
 }
-persistent-handles-page .header .weak-item:last-child {
+.persistent-handles-page .header .weak-item:last-child {
   margin-bottom: -3px;
   border-bottom: solid 1px #AAAAAA;
 }
-persistent-handles-page .weak-item .external-size,
-persistent-handles-page .weak-item .peer,
-persistent-handles-page .weak-item .object {
+.persistent-handles-page .weak-item .external-size,
+.persistent-handles-page .weak-item .peer,
+.persistent-handles-page .weak-item .object {
   display: inline-block;
   width: 7em;
   text-align: right;
   padding-right: 0.5em;
   line-height: 20px;
 }
-persistent-handles-page .weak-item .peer {
+.persistent-handles-page .weak-item .peer {
   width: 11em;
   font-family: monospace;
 }
-persistent-handles-page .weak-item .object {
+.persistent-handles-page .weak-item .object {
   text-align: left;
   width: 25em;
 }
-persistent-handles-page .buffer .weak-item:hover {
+.persistent-handles-page .buffer .weak-item:hover {
   background-color: #d2e7fe;
 }
-persistent-handles-page .weak-item .finalizer {
+.persistent-handles-page .weak-item .finalizer {
   padding-left: 0.5em;
 }
-persistent-handles-page .weak-item > button,
-persistent-handles-page .weak-item > button:active {
+.persistent-handles-page .weak-item > button,
+.persistent-handles-page .weak-item > button:active {
   background-color: transparent;
   color: #0489c3;
   border-style: none;
 }
-persistent-handles-page .weak-item > button:hover {
+.persistent-handles-page .weak-item > button:hover {
   text-decoration: underline;
 }
 
 /* ports-page */
 
-ports-page .port-number {
+.ports-page .port-number {
   font-weight: bold;
 }
 
 /* script-ref */
 
-script-ref > a[href]:hover {
+.script-ref > a[href]:hover {
   text-decoration: underline;
 }
-script-ref > a[href] {
+.script-ref > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-script-ref .emphasize {
+.script-ref .emphasize {
   font-style: italic;
 }
 
 
 /* source-link */
 
-source-link > a[href]:hover {
+.source-link > a[href]:hover {
     text-decoration: underline;
 }
 
-source-link > a[href] {
+.source-link > a[href] {
     color: #0489c3;
     text-decoration: none;
 }
@@ -2307,57 +2307,57 @@
 
 /* observatory-application */
 
-observatory-application {
+.observatory-application {
   display: block;
   height: 100%;
 }
 
-observatory-application > div {
+.observatory-application > div {
   display: block;
   height: 100%;
 }
 
 /* sample-buffer-control */
 
-sample-buffer-control {
+.sample-buffer-control {
   white-space: nowrap;
 }
 
-sample-buffer-control .statusMessage {
+.sample-buffer-control .statusMessage {
   font-size: 150%;
   font-weight: bold;
 }
 
-sample-buffer-control .statusBox {
+.sample-buffer-control .statusBox {
   height: 100%;
   padding: 1em;
 }
 
-sample-buffer-control .center {
+.sample-buffer-control .center {
   align-items: center;
   justify-content: center;
 }
 
-sample-buffer-control .notice {
+.sample-buffer-control .notice {
   background-color: #fcf8e3;
 }
 
-sample-buffer-control .red {
+.sample-buffer-control .red {
   background-color: #f2dede;
 }
 
-sample-buffer-control .shadow {
+.sample-buffer-control .shadow {
   box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.16),
               0 2px 5px 0 rgba(0, 0, 0, 0.26);
 }
 
 /* script-inset */
 
-script-inset {
+.script-inset {
   position: relative;
 }
-script-inset button.refresh,
-script-inset button.toggle-profile {
+.script-inset button.refresh,
+.script-inset button.toggle-profile {
   background-color: transparent;
   padding: 0;
   margin: 0;
@@ -2366,29 +2366,29 @@
   display: inline-block;
   top: 5px;
 }
-script-inset button.refresh > svg,
-script-inset button.toggle-profile > svg {
+.script-inset button.refresh > svg,
+.script-inset button.toggle-profile > svg {
   fill: #888888;
 }
-script-inset button.refresh {
+.script-inset button.refresh {
   right: 5px;
 }
-script-inset button.toggle-profile {
+.script-inset button.toggle-profile {
   right: 30px;
 }
-script-inset button.toggle-profile.enabled > svg {
+.script-inset button.toggle-profile.enabled > svg {
   fill: #BB3322;
 }
-script-inset a {
+.script-inset a {
   color: #0489c3;
   text-decoration: none;
 }
-script-inset a:hover {
+.script-inset a:hover {
   text-decoration: underline;
 }
-script-inset .sourceInset {
+.script-inset .sourceInset {
 }
-script-inset .sourceTable {
+.script-inset .sourceTable {
   position: relative;
   background-color: #f5f5f5;
   border: 1px solid #ccc;
@@ -2397,31 +2397,31 @@
   box-sizing: border-box;
   overflow-x: scroll;
 }
-script-inset .sourceRow {
+.script-inset .sourceRow {
   display: flex;
   flex-direction: row;
   width: 100%;
 }
-script-inset .sourceItem,
-script-inset .sourceItemCurrent {
+.script-inset .sourceItem,
+.script-inset .sourceItemCurrent {
   vertical-align: top;
   font: 400 14px consolas, courier, monospace;
   line-height: 125%;
   white-space: pre;
   max-width: 0;
 }
-script-inset .currentLine {
+.script-inset .currentLine {
   background-color: #fff;
 }
-script-inset .currentCol {
+.script-inset .currentCol {
   background-color: #6cf;
 }
-script-inset .hitsCurrent,
-script-inset .hitsNone,
-script-inset .hitsNotExecuted,
-script-inset .hitsExecuted,
-script-inset .hitsCompiled,
-script-inset .hitsNotCompiled {
+.script-inset .hitsCurrent,
+.script-inset .hitsNone,
+.script-inset .hitsNotExecuted,
+.script-inset .hitsExecuted,
+.script-inset .hitsCompiled,
+.script-inset .hitsNotCompiled {
   display: table-cell;
   vertical-align: top;
   font: 400 14px consolas, courier, monospace;
@@ -2430,28 +2430,28 @@
   text-align: right;
   color: #a8a8a8;
 }
-script-inset .hitsCurrent {
+.script-inset .hitsCurrent {
   background-color: #6cf;
   color: black;
 }
-script-inset .hitsNotExecuted {
+.script-inset .hitsNotExecuted {
   background-color: #faa;
 }
-script-inset .hitsExecuted {
+.script-inset .hitsExecuted {
   background-color: #aea;
 }
-script-inset .hitsCompiled {
+.script-inset .hitsCompiled {
   background-color: #e0e0e0;
 }
-script-inset .hitsNotCompiled {
+.script-inset .hitsNotCompiled {
   background-color: #f0c5c5;
 }
-script-inset .noCopy {}
-script-inset .emptyBreakpoint,
-script-inset .possibleBreakpoint,
-script-inset .busyBreakpoint,
-script-inset .unresolvedBreakpoint,
-script-inset .resolvedBreakpoint  {
+.script-inset .noCopy {}
+.script-inset .emptyBreakpoint,
+.script-inset .possibleBreakpoint,
+.script-inset .busyBreakpoint,
+.script-inset .unresolvedBreakpoint,
+.script-inset .resolvedBreakpoint  {
   display: table-cell;
   vertical-align: top;
   font: 400 14px consolas, courier, monospace;
@@ -2459,39 +2459,39 @@
   text-align: center;
   cursor: pointer;
 }
-script-inset .possibleBreakpoint {
+.script-inset .possibleBreakpoint {
   color: #e0e0e0;
 }
-script-inset .possibleBreakpoint:hover {
+.script-inset .possibleBreakpoint:hover {
   color: white;
   background-color: #777;
 }
-script-inset .busyBreakpoint {
+.script-inset .busyBreakpoint {
   color: white;
   background-color: black;
   cursor: wait;
 }
-script-inset .unresolvedBreakpoint {
+.script-inset .unresolvedBreakpoint {
   color: white;
   background-color: #cac;
 }
-script-inset .resolvedBreakpoint {
+.script-inset .resolvedBreakpoint {
   color: white;
   background-color: #e66;
 }
-script-inset .unresolvedBreakAnnotation {
+.script-inset .unresolvedBreakAnnotation {
   color: white;
   background-color: #cac;
 }
-script-inset .resolvedBreakAnnotation {
+.script-inset .resolvedBreakAnnotation {
   color: white;
   background-color: #e66;
 }
-script-inset .notSourceProfile,
-script-inset .noProfile,
-script-inset .coldProfile,
-script-inset .mediumProfile,
-script-inset .hotProfile {
+.script-inset .notSourceProfile,
+.script-inset .noProfile,
+.script-inset .coldProfile,
+.script-inset .mediumProfile,
+.script-inset .hotProfile {
   display: table-cell;
   vertical-align: top;
   font: 400 14px consolas, courier, monospace;
@@ -2501,28 +2501,28 @@
   margin-left: 5px;
   margin-right: 5px;
 }
-script-inset .notSourceProfile {
+.script-inset .notSourceProfile {
 }
-script-inset .noProfile {
+.script-inset .noProfile {
   background-color: #e0e0e0;
 }
-script-inset .coldProfile {
+.script-inset .coldProfile {
   background-color: #aea;
 }
-script-inset .mediumProfile {
+.script-inset .mediumProfile {
   background-color: #fe9;
 }
-script-inset .hotProfile {
+.script-inset .hotProfile {
   background-color: #faa;
 }
 
 /* search-bar */
 
-search-bar {
+.search-bar {
   background: white;
   padding: 5px;
 }
-search-bar > input {
+.search-bar > input {
   width: 300px;
   line-height: 20px;
   border-color: #DDDDDD;
@@ -2530,11 +2530,11 @@
   padding-right: 2px;
 }
 
-search-bar button:enabled,
-search-bar button:enabled:hover,
-search-bar button:disabled,
-search-bar button:disabled:hover,
-search-bar button:active {
+.search-bar button:enabled,
+.search-bar button:enabled:hover,
+.search-bar button:disabled,
+.search-bar button:disabled:hover,
+.search-bar button:active {
   border: none;
   background: none;
   background-color: transparent;
@@ -2544,40 +2544,40 @@
   outline: none;
 }
 
-search-bar button:disabled,
-search-bar button:disabled:hover {
+.search-bar button:disabled,
+.search-bar button:disabled:hover {
   color: #DDDDDD;
 }
 
-search-bar button:enabled,
-search-bar button:enabled:active {
+.search-bar button:enabled,
+.search-bar button:enabled:active {
   color: #BBBBBB;
 }
 
-search-bar button:enabled:hover {
+.search-bar button:enabled:hover {
   color: #AAAAAA;
   text-shadow: 1px 1px 2px #dddddd;
 }
 
 /* stack-trace-tree-config */
 
-stack-trace-tree-config {
+.stack-trace-tree-config {
   white-space: nowrap;
 }
 
 /* timeline-dashboard */
 
-timeline-dashboard .iframe {
+.timeline-dashboard .iframe {
   position: absolute;
   top: 90px;
   bottom: 0;
   left: 0;
   right: 0;
 }
-timeline-dashboard h1 {
+.timeline-dashboard h1 {
   margin-bottom: 5px;
 }
-timeline-dashboard .iframe iframe {
+.timeline-dashboard .iframe iframe {
   width: 100%;
   height: 100%;
   border: none;
@@ -2585,13 +2585,13 @@
 
 /* timeline-page */
 
-timeline-page .iframe {
+.timeline-page .iframe {
   height: 100%;
   width: 100%;
   margin-top: -120px;
   padding-top: 120px;
 }
-timeline-page .iframe iframe {
+.timeline-page .iframe iframe {
   width: 100%;
   height: 100%;
   border: none;
@@ -2599,59 +2599,59 @@
 
 /* type-arguments-ref */
 
-type-arguments-ref a[href]:hover {
+.type-arguments-ref a[href]:hover {
   text-decoration: underline;
 }
-type-arguments-ref a[href] {
+.type-arguments-ref a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-type-arguments-ref .emphasize {
+.type-arguments-ref .emphasize {
   font-style: italic;
 }
 
 
 /* token-stream-ref */
 
-token-stream-ref a[href]:hover {
+.token-stream-ref a[href]:hover {
   text-decoration: underline;
 }
-token-stream-ref a[href] {
+.token-stream-ref a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-token-stream-ref .emphasize {
+.token-stream-ref .emphasize {
   font-style: italic;
 }
 
 
 /* unknown-ref */
 
-unknown-ref > a[href]:hover {
+.unknown-ref > a[href]:hover {
   text-decoration: underline;
 }
-unknown-ref > a[href] {
+.unknown-ref > a[href] {
   color: #0489c3;
   text-decoration: none;
 }
-unknown-ref > a[href] * {
+.unknown-ref > a[href] * {
   color: inherit;
 }
-unknown-ref .emphasize {
+.unknown-ref .emphasize {
   font-style: italic;
 }
 
 
 /* view-footer */
 
-view-footer {
+.view-footer {
   padding: 1em;
   padding-top: 10.3em;
   float: right;
   align-content: right;
 }
 
-view-footer > a {
+.view-footer > a {
   margin-bottom: 0.17em;
   font-size: 90%;
   float: right;
@@ -2661,7 +2661,7 @@
 
 /* virtual-collection */
 
-virtual-collection {
+.virtual-collection {
   position: relative;
   display: block;
   overflow-x: hidden;
@@ -2669,7 +2669,7 @@
   height: 100%;
 }
 
-virtual-collection .viewport {
+.virtual-collection .viewport {
   position: absolute;
   display: block;
   overflow-y: auto;
@@ -2680,14 +2680,14 @@
   left: 0;
 }
 
-virtual-collection .header {
+.virtual-collection .header {
   background: white;
   position: relative;
   display: block;
   z-index: +1;
 }
 
-virtual-collection search-bar {
+.virtual-collection .search-bar {
   position: relative;
   display: block;
   z-index: +1;
@@ -2699,45 +2699,45 @@
   box-shadow: 0px 1px 2px #AAAAAA;
 }
 
-virtual-collection .spacer {
+.virtual-collection .spacer {
   overflow: hidden;
   background: transparent;
   display: inline-block;
   min-width: 100%;
 }
 
-virtual-collection .buffer {
+.virtual-collection .buffer {
   background: transparent;
   position: relative;
   display: inline-block;
   min-width: 100%;
 }
 
-virtual-collection .header > div,
-virtual-collection .buffer > div {
+.virtual-collection .header > div,
+.virtual-collection .buffer > div {
   white-space: nowrap;
 }
 
-virtual-collection .header.attached > div,
-virtual-collection .buffer > div {
+.virtual-collection .header.attached > div,
+.virtual-collection .buffer > div {
   display: inline-block;
 }
 
-virtual-collection .buffer > div {
+.virtual-collection .buffer > div {
   min-width: 100%;
   white-space: nowrap;
 }
 
-virtual-collection .marked,
-virtual-collection .marked * {
+.virtual-collection .marked,
+.virtual-collection .marked * {
   background: yellow !important;
 }
 
 /* virtual-tree */
 
-virtual-tree .expander,
-virtual-tree .expander:hover,
-virtual-tree .expander:active {
+.virtual-tree .expander,
+.virtual-tree .expander:hover,
+.virtual-tree .expander:active {
   display: inline-block;
   text-align: center;
   font-weight: bold;
@@ -2748,74 +2748,74 @@
   padding: 0;
 }
 
-virtual-tree .expander:focus {
+.virtual-tree .expander:focus {
   outline: none;
 }
 
-virtual-tree .lines,
-virtual-tree .lines > span {
+.virtual-tree .lines,
+.virtual-tree .lines > span {
   display: inline-block;
   vertical-align: top;
   height: 100%;
   line-height: 100%;
 }
 
-virtual-tree .lines:before,
-virtual-tree .lines > span:before {
+.virtual-tree .lines:before,
+.virtual-tree .lines > span:before {
   display: inline-block;
   content: '';
 }
 
-virtual-tree .lines > span {
+.virtual-tree .lines > span {
   width: 3px;
   margin-left: 8px;
   margin-right: 8px;
 }
 
-virtual-tree .lines > span:nth-child(5n) {
+.virtual-tree .lines > span:nth-child(5n) {
   background-color: #673AB7;
 }
 
-virtual-tree .lines > span:nth-child(5n+1) {
+.virtual-tree .lines > span:nth-child(5n+1) {
   background-color: #F44336;
 }
 
-virtual-tree .lines > span:nth-child(5n+2) {
+.virtual-tree .lines > span:nth-child(5n+2) {
   background-color: #4CAF50;
 }
 
-virtual-tree .lines > span:nth-child(5n+3) {
+.virtual-tree .lines > span:nth-child(5n+3) {
   background-color: #3F51B5;
 }
 
-virtual-tree .lines > span:nth-child(5n+4) {
+.virtual-tree .lines > span:nth-child(5n+4) {
   background-color: #FF9800;
 }
 
 /* vm-connect-target */
 
-vm-connect-target > a {
+.vm-connect-target > a {
   color: #0489c3;
   text-decoration: none;
 }
 
-vm-connect-target > a:hover {
+.vm-connect-target > a:hover {
   text-decoration: underline;
 }
 
-vm-connect-target > button.delete-button {
+.vm-connect-target > button.delete-button {
   margin-left: 0.28em;
   padding: 4px;
   background: transparent;
   border: none !important;
 }
 
-vm-connect-target > button.delete-button:hover {
+.vm-connect-target > button.delete-button:hover {
   background: #ff0000;
 }
 
 /* vm-connect */
 
-vm-connect ul {
+.vm-connect ul {
   list-style-type: none;
 }
diff --git a/runtime/observatory/lib/src/elements/curly_block.dart b/runtime/observatory/lib/src/elements/curly_block.dart
index 3d88727..7bb7084 100644
--- a/runtime/observatory/lib/src/elements/curly_block.dart
+++ b/runtime/observatory/lib/src/elements/curly_block.dart
@@ -15,7 +15,7 @@
   CurlyBlockToggleEvent(this.control);
 }
 
-class CurlyBlockElement extends HtmlElement implements Renderable {
+class CurlyBlockElement extends CustomElement implements Renderable {
   static const tag = const Tag<CurlyBlockElement>('curly-block');
 
   RenderingScheduler<CurlyBlockElement> _r;
@@ -48,14 +48,14 @@
       {bool expanded: false, bool disabled: false, RenderingQueue queue}) {
     assert(expanded != null);
     assert(disabled != null);
-    CurlyBlockElement e = document.createElement(tag.name);
+    CurlyBlockElement e = new CurlyBlockElement.created();
     e._r = new RenderingScheduler<CurlyBlockElement>(e, queue: queue);
     e._expanded = expanded;
     e._disabled = disabled;
     return e;
   }
 
-  CurlyBlockElement.created() : super.created();
+  CurlyBlockElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 053bab8..6355605 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -36,7 +36,8 @@
 abstract class DebuggerCommand extends Command {
   ObservatoryDebugger debugger;
 
-  DebuggerCommand(this.debugger, name, List<Command> children) : super(name, children);
+  DebuggerCommand(this.debugger, name, List<Command> children)
+      : super(name, children);
 
   String get helpShort;
   String get helpLong;
@@ -129,7 +130,8 @@
 }
 
 class HelpHotkeysCommand extends DebuggerCommand {
-  HelpHotkeysCommand(Debugger debugger) : super(debugger, 'hotkeys', <Command>[]);
+  HelpHotkeysCommand(Debugger debugger)
+      : super(debugger, 'hotkeys', <Command>[]);
 
   Future run(List<String> args) {
     var con = debugger.console;
@@ -213,7 +215,8 @@
       debugger.downFrame(count);
       debugger.console.print('frame = ${debugger.currentFrame}');
     } catch (e) {
-      debugger.console.print('frame must be in range [${e.start}..${e.end-1}]');
+      debugger.console
+          .print('frame must be in range [${e.start}..${e.end - 1}]');
     }
     return new Future.value(null);
   }
@@ -247,7 +250,8 @@
       debugger.upFrame(count);
       debugger.console.print('frame = ${debugger.currentFrame}');
     } on RangeError catch (e) {
-      debugger.console.print('frame must be in range [${e.start}..${e.end-1}]');
+      debugger.console
+          .print('frame must be in range [${e.start}..${e.end - 1}]');
     }
     return new Future.value(null);
   }
@@ -283,7 +287,8 @@
       debugger.currentFrame = frame;
       debugger.console.print('frame = ${debugger.currentFrame}');
     } on RangeError catch (e) {
-      debugger.console.print('frame must be in range [${e.start}..${e.end-1}]');
+      debugger.console
+          .print('frame must be in range [${e.start}..${e.end - 1}]');
     }
     return new Future.value(null);
   }
@@ -313,7 +318,8 @@
 }
 
 class ContinueCommand extends DebuggerCommand {
-  ContinueCommand(Debugger debugger) : super(debugger, 'continue', <Command>[]) {
+  ContinueCommand(Debugger debugger)
+      : super(debugger, 'continue', <Command>[]) {
     alias = 'c';
   }
 
@@ -354,7 +360,8 @@
 }
 
 class SyncNextCommand extends DebuggerCommand {
-  SyncNextCommand(Debugger debugger) : super(debugger, 'next-sync', <Command>[]);
+  SyncNextCommand(Debugger debugger)
+      : super(debugger, 'next-sync', <Command>[]);
 
   Future run(List<String> args) {
     return debugger.syncNext();
@@ -370,7 +377,8 @@
 }
 
 class AsyncNextCommand extends DebuggerCommand {
-  AsyncNextCommand(Debugger debugger) : super(debugger, 'next-async', <Command>[]);
+  AsyncNextCommand(Debugger debugger)
+      : super(debugger, 'next-async', <Command>[]);
 
   Future run(List<String> args) {
     return debugger.asyncNext();
@@ -1162,7 +1170,8 @@
 }
 
 class RefreshStackCommand extends DebuggerCommand {
-  RefreshStackCommand(Debugger debugger) : super(debugger, 'stack', <Command>[]);
+  RefreshStackCommand(Debugger debugger)
+      : super(debugger, 'stack', <Command>[]);
 
   Future run(List<String> args) {
     return debugger.refreshStack();
@@ -2001,7 +2010,7 @@
   }
 }
 
-class DebuggerPageElement extends HtmlElement implements Renderable {
+class DebuggerPageElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<DebuggerPageElement>('debugger-page', dependencies: const [
     NavTopMenuElement.tag,
@@ -2022,7 +2031,7 @@
     assert(objects != null);
     assert(scripts != null);
     assert(events != null);
-    final DebuggerPageElement e = document.createElement(tag.name);
+    final DebuggerPageElement e = new DebuggerPageElement.created();
     final debugger = new ObservatoryDebugger(isolate);
     debugger.page = e;
     debugger.objects = objects;
@@ -2034,7 +2043,7 @@
     return e;
   }
 
-  DebuggerPageElement.created() : super.created();
+  DebuggerPageElement.created() : super.created(tag);
 
   Future<StreamSubscription> _vmSubscriptionFuture;
   Future<StreamSubscription> _isolateSubscriptionFuture;
@@ -2056,23 +2065,25 @@
     final stackDiv = new DivElement()..classes = ['stack'];
     final stackElement = new DebuggerStackElement(
         _isolate, _debugger, stackDiv, _objects, _scripts, _events);
-    stackDiv.children = <Element>[stackElement];
+    stackDiv.children = <Element>[stackElement.element];
     final consoleDiv = new DivElement()
       ..classes = ['console']
-      ..children = <Element>[consoleElement];
+      ..children = <Element>[consoleElement.element];
     final commandElement = new DebuggerInputElement(_isolate, _debugger);
     final commandDiv = new DivElement()
       ..classes = ['commandline']
-      ..children = <Element>[commandElement];
+      ..children = <Element>[commandElement.element];
 
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: app.queue),
-        new NavVMMenuElement(app.vm, app.events, queue: app.queue),
-        new NavIsolateMenuElement(_isolate, app.events, queue: app.queue),
+        new NavTopMenuElement(queue: app.queue).element,
+        new NavVMMenuElement(app.vm, app.events, queue: app.queue).element,
+        new NavIsolateMenuElement(_isolate, app.events, queue: app.queue)
+            .element,
         navMenu('debugger'),
         new NavNotifyElement(app.notifications,
-            notifyOnPause: false, queue: app.queue)
+                notifyOnPause: false, queue: app.queue)
+            .element
       ]),
       new DivElement()
         ..classes = ['variable']
@@ -2163,7 +2174,7 @@
   }
 }
 
-class DebuggerStackElement extends HtmlElement implements Renderable {
+class DebuggerStackElement extends CustomElement implements Renderable {
   static const tag = const Tag<DebuggerStackElement>('debugger-stack');
 
   S.Isolate _isolate;
@@ -2213,7 +2224,7 @@
     assert(objects != null);
     assert(scripts != null);
     assert(events != null);
-    final DebuggerStackElement e = document.createElement(tag.name);
+    final DebuggerStackElement e = new DebuggerStackElement.created();
     e._isolate = isolate;
     e._debugger = debugger;
     e._scroller = scroller;
@@ -2286,7 +2297,7 @@
 
     var li = new LIElement();
     li.classes.add('list-group-item');
-    li.children.insert(0, frameElement);
+    li.children.insert(0, frameElement.element);
 
     frameList.insert(0, li);
   }
@@ -2298,7 +2309,7 @@
 
     var li = new LIElement();
     li.classes.add('list-group-item');
-    li.children.insert(0, messageElement);
+    li.children.insert(0, messageElement.element);
 
     messageList.add(li);
   }
@@ -2323,7 +2334,9 @@
     int oldPos = frameElements.length - 1;
     int newPos = newFrames.length - 1;
     while (oldPos >= 0 && newPos >= 0) {
-      if (!frameElements[oldPos].children[0].matchFrame(newFrames[newPos])) {
+      DebuggerFrameElement dbgFrameElement =
+          CustomElement.reverse(frameElements[oldPos].children[0]);
+      if (!dbgFrameElement.matchFrame(newFrames[newPos])) {
         // The rest of the frame elements no longer match.  Remove them.
         for (int i = 0; i <= oldPos; i++) {
           // NOTE(turnidge): removeRange is missing, sadly.
@@ -2357,7 +2370,9 @@
 
     if (frameElements.isNotEmpty) {
       for (int i = newCount; i < frameElements.length; i++) {
-        frameElements[i].children[0].updateFrame(newFrames[i]);
+        DebuggerFrameElement dbgFrameElement =
+            CustomElement.reverse(frameElements[i].children[0]);
+        dbgFrameElement.updateFrame(newFrames[i]);
       }
     }
 
@@ -2389,7 +2404,8 @@
     if (messageElements.isNotEmpty) {
       // Update old messages.
       for (int i = 0; i < newStartingIndex; i++) {
-        DebuggerMessageElement e = messageElements[i].children[0];
+        DebuggerMessageElement e =
+            CustomElement.reverse(messageElements[i].children[0]);
         e.updateMessage(newMessages[i]);
       }
     }
@@ -2407,7 +2423,8 @@
     currentFrame = value;
     List frameElements = _frameList.children;
     for (var frameElement in frameElements) {
-      DebuggerFrameElement dbgFrameElement = frameElement.children[0];
+      DebuggerFrameElement dbgFrameElement =
+          CustomElement.reverse(frameElement.children[0]);
       if (dbgFrameElement.frame.index == currentFrame) {
         dbgFrameElement.setCurrent(true);
       } else {
@@ -2416,10 +2433,10 @@
     }
   }
 
-  DebuggerStackElement.created() : super.created();
+  DebuggerStackElement.created() : super.created(tag);
 }
 
-class DebuggerFrameElement extends HtmlElement implements Renderable {
+class DebuggerFrameElement extends CustomElement implements Renderable {
   static const tag = const Tag<DebuggerFrameElement>('debugger-frame');
 
   RenderingScheduler<DebuggerFrameElement> _r;
@@ -2476,7 +2493,7 @@
     assert(objects != null);
     assert(scripts != null);
     assert(events != null);
-    final DebuggerFrameElement e = document.createElement(tag.name);
+    final DebuggerFrameElement e = new DebuggerFrameElement.created();
     e._r = new RenderingScheduler<DebuggerFrameElement>(e, queue: queue);
     e._isolate = isolate;
     e._frame = frame;
@@ -2487,7 +2504,7 @@
     return e;
   }
 
-  DebuggerFrameElement.created() : super.created();
+  DebuggerFrameElement.created() : super.created(tag);
 
   void render() {
     if (_pinned) {
@@ -2545,16 +2562,17 @@
                   ..children = _frame.function?.location == null
                       ? const []
                       : [
-                          new SourceInsetElement(
-                              _isolate,
-                              _frame.function.location,
-                              _scripts,
-                              _objects,
-                              _events,
-                              currentPos: _frame.location.tokenPos,
-                              variables: _frame.variables,
-                              inDebuggerContext: true,
-                              queue: _r.queue)
+                          (new SourceInsetElement(
+                                  _isolate,
+                                  _frame.function.location,
+                                  _scripts,
+                                  _objects,
+                                  _events,
+                                  currentPos: _frame.location.tokenPos,
+                                  variables: _frame.variables,
+                                  inDebuggerContext: true,
+                                  queue: _r.queue))
+                              .element
                         ],
                 new DivElement()
                   ..classes = ['flex-item-vars']
@@ -2643,7 +2661,8 @@
                 ? const []
                 : [
                     new FunctionRefElement(_isolate, _frame.function,
-                        queue: _r.queue)
+                            queue: _r.queue)
+                        .element
                   ],
           new SpanElement()..text = ' ( ',
           new SpanElement()
@@ -2651,8 +2670,9 @@
                 ? const []
                 : [
                     new SourceLinkElement(
-                        _isolate, _frame.function.location, _scripts,
-                        queue: _r.queue)
+                            _isolate, _frame.function.location, _scripts,
+                            queue: _r.queue)
+                        .element
                   ],
           new SpanElement()..text = ' )'
         ]
@@ -2778,7 +2798,7 @@
   }
 }
 
-class DebuggerMessageElement extends HtmlElement implements Renderable {
+class DebuggerMessageElement extends CustomElement implements Renderable {
   static const tag = const Tag<DebuggerMessageElement>('debugger-message');
 
   RenderingScheduler<DebuggerMessageElement> _r;
@@ -2811,7 +2831,7 @@
     assert(message != null);
     assert(objects != null);
     assert(events != null);
-    final DebuggerMessageElement e = document.createElement(tag.name);
+    final DebuggerMessageElement e = new DebuggerMessageElement.created();
     e._r = new RenderingScheduler<DebuggerMessageElement>(e, queue: queue);
     e._isolate = isolate;
     e._message = message;
@@ -2821,7 +2841,7 @@
     return e;
   }
 
-  DebuggerMessageElement.created() : super.created();
+  DebuggerMessageElement.created() : super.created(tag);
 
   void render() {
     if (_pinned) {
@@ -2863,13 +2883,14 @@
                       ? const []
                       : [
                           new SourceInsetElement(
-                              _isolate,
-                              _message.handler.location,
-                              _scripts,
-                              _objects,
-                              _events,
-                              inDebuggerContext: true,
-                              queue: _r.queue)
+                                  _isolate,
+                                  _message.handler.location,
+                                  _scripts,
+                                  _objects,
+                                  _events,
+                                  inDebuggerContext: true,
+                                  queue: _r.queue)
+                              .element
                         ],
                 new DivElement()
                   ..classes = ['flex-item-vars']
@@ -2931,7 +2952,8 @@
                 ? const []
                 : [
                     new FunctionRefElement(_isolate, _message.handler,
-                        queue: _r.queue)
+                            queue: _r.queue)
+                        .element
                   ],
           new SpanElement()..text = ' ( ',
           new SpanElement()
@@ -2939,7 +2961,8 @@
                 ? const []
                 : [
                     new SourceLinkElement(_isolate, _message.location, _scripts,
-                        queue: _r.queue)
+                            queue: _r.queue)
+                        .element
                   ],
           new SpanElement()..text = ' )'
         ]
@@ -2998,16 +3021,16 @@
   }
 }
 
-class DebuggerConsoleElement extends HtmlElement implements Renderable {
+class DebuggerConsoleElement extends CustomElement implements Renderable {
   static const tag = const Tag<DebuggerConsoleElement>('debugger-console');
 
   factory DebuggerConsoleElement() {
-    final DebuggerConsoleElement e = document.createElement(tag.name);
+    final DebuggerConsoleElement e = new DebuggerConsoleElement.created();
     e.children = <Element>[new BRElement()];
     return e;
   }
 
-  DebuggerConsoleElement.created() : super.created();
+  DebuggerConsoleElement.created() : super.created(tag);
 
   /// Is [container] scrolled to the within [threshold] pixels of the bottom?
   static bool _isScrolledToBottom(DivElement container, [int threshold = 2]) {
@@ -3086,7 +3109,8 @@
 
   void printRef(S.Isolate isolate, S.Instance ref, M.ObjectRepository objects,
       {bool newline: true}) {
-    _append(new InstanceRefElement(isolate, ref, objects, queue: app.queue));
+    _append(new InstanceRefElement(isolate, ref, objects, queue: app.queue)
+        .element);
     if (newline) {
       this.newline();
     }
@@ -3107,7 +3131,7 @@
   ObservatoryApplication get app => ObservatoryApplication.app;
 }
 
-class DebuggerInputElement extends HtmlElement implements Renderable {
+class DebuggerInputElement extends CustomElement implements Renderable {
   static const tag = const Tag<DebuggerInputElement>('debugger-input');
 
   S.Isolate _isolate;
@@ -3134,14 +3158,14 @@
 
   factory DebuggerInputElement(
       S.Isolate isolate, ObservatoryDebugger debugger) {
-    final DebuggerInputElement e = document.createElement(tag.name);
+    final DebuggerInputElement e = new DebuggerInputElement.created();
     e.children = <Element>[e._modalPromptDiv, e._textBox];
     e._textBox.select();
     e._textBox.onKeyDown.listen(e._onKeyDown);
     return e;
   }
 
-  DebuggerInputElement.created() : super.created();
+  DebuggerInputElement.created() : super.created(tag);
 
   void _onKeyDown(KeyboardEvent e) {
     if (_busy) {
@@ -3321,9 +3345,9 @@
       ..setAttribute(
           'd',
           'M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
-          '2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
-          '2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
-          '2-2-.9-2-2-2z')
+              '2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
+              '2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
+              '2-2-.9-2-2-2z')
   ];
 
 final SvgSvgElement iconVerticalThreeDot = new SvgSvgElement()
@@ -3334,9 +3358,9 @@
       ..setAttribute(
           'd',
           'M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 '
-          '2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
-          '2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 '
-          '2-.9 2-2-.9-2-2-2z')
+              '2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
+              '2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 '
+              '2-.9 2-2-.9-2-2-2z')
   ];
 
 final SvgSvgElement iconInfo = new SvgSvgElement()
@@ -3347,7 +3371,7 @@
       ..setAttribute(
           'd',
           'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 '
-          '10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z')
+              '10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z')
   ];
 
 final SvgSvgElement iconInfoOutline = new SvgSvgElement()
@@ -3358,7 +3382,7 @@
       ..setAttribute(
           'd',
           'M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 '
-          '10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 '
-          '0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 '
-          '9h2V7h-2v2z')
+              '10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 '
+              '0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 '
+              '9h2V7h-2v2z')
   ];
diff --git a/runtime/observatory/lib/src/elements/error_ref.dart b/runtime/observatory/lib/src/elements/error_ref.dart
index ef7f04a..2e25096 100644
--- a/runtime/observatory/lib/src/elements/error_ref.dart
+++ b/runtime/observatory/lib/src/elements/error_ref.dart
@@ -10,7 +10,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 
-class ErrorRefElement extends HtmlElement implements Renderable {
+class ErrorRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<ErrorRefElement>('error-ref');
 
   RenderingScheduler<ErrorRefElement> _r;
@@ -23,13 +23,13 @@
 
   factory ErrorRefElement(ErrorRef error, {RenderingQueue queue}) {
     assert(error != null);
-    ErrorRefElement e = document.createElement(tag.name);
+    ErrorRefElement e = new ErrorRefElement.created();
     e._r = new RenderingScheduler<ErrorRefElement>(e, queue: queue);
     e._error = error;
     return e;
   }
 
-  ErrorRefElement.created() : super.created();
+  ErrorRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/error_view.dart b/runtime/observatory/lib/src/elements/error_view.dart
index 0d1d9b8..010f4cc 100644
--- a/runtime/observatory/lib/src/elements/error_view.dart
+++ b/runtime/observatory/lib/src/elements/error_view.dart
@@ -14,7 +14,7 @@
 import 'package:observatory/src/elements/nav/top_menu.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class ErrorViewElement extends HtmlElement implements Renderable {
+class ErrorViewElement extends CustomElement implements Renderable {
   static const tag = const Tag<ErrorViewElement>('error-view',
       dependencies: const [
         NavTopMenuElement.tag,
@@ -36,14 +36,14 @@
       {RenderingQueue queue}) {
     assert(error != null);
     assert(notifications != null);
-    ErrorViewElement e = document.createElement(tag.name);
+    ErrorViewElement e = new ErrorViewElement.created();
     e._r = new RenderingScheduler<ErrorViewElement>(e, queue: queue);
     e._error = error;
     e._notifications = notifications;
     return e;
   }
 
-  ErrorViewElement.created() : super.created();
+  ErrorViewElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -61,8 +61,8 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered']
@@ -74,7 +74,7 @@
             ..classes = ['well']
             ..children = <Element>[new PreElement()..text = error.message]
         ],
-      new ViewFooterElement(queue: _r.queue)
+      new ViewFooterElement(queue: _r.queue).element
     ];
   }
 
diff --git a/runtime/observatory/lib/src/elements/eval_box.dart b/runtime/observatory/lib/src/elements/eval_box.dart
index 0bf7b0c..db8ce82 100644
--- a/runtime/observatory/lib/src/elements/eval_box.dart
+++ b/runtime/observatory/lib/src/elements/eval_box.dart
@@ -12,7 +12,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/instance_ref.dart';
 
-class EvalBoxElement extends HtmlElement implements Renderable {
+class EvalBoxElement extends CustomElement implements Renderable {
   static const tag = const Tag<EvalBoxElement>('eval-box',
       dependencies: const [InstanceRefElement.tag]);
 
@@ -43,7 +43,7 @@
     assert(eval != null);
     assert(multiline != null);
     assert(quickExpressions != null);
-    EvalBoxElement e = document.createElement(tag.name);
+    EvalBoxElement e = new EvalBoxElement.created();
     e._r = new RenderingScheduler<EvalBoxElement>(e, queue: queue);
     e._isolate = isolate;
     e._context = context;
@@ -54,7 +54,7 @@
     return e;
   }
 
-  EvalBoxElement.created() : super.created();
+  EvalBoxElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/field_ref.dart b/runtime/observatory/lib/src/elements/field_ref.dart
index ab4f170..8074d44 100644
--- a/runtime/observatory/lib/src/elements/field_ref.dart
+++ b/runtime/observatory/lib/src/elements/field_ref.dart
@@ -10,7 +10,7 @@
 import 'package:observatory/src/elements/helpers/uris.dart';
 import 'package:observatory/src/elements/instance_ref.dart';
 
-class FieldRefElement extends HtmlElement implements Renderable {
+class FieldRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<FieldRefElement>('field-ref',
       dependencies: const [InstanceRefElement.tag]);
 
@@ -32,7 +32,7 @@
     assert(isolate != null);
     assert(field != null);
     assert(objects != null);
-    FieldRefElement e = document.createElement(tag.name);
+    FieldRefElement e = new FieldRefElement.created();
     e._r = new RenderingScheduler<FieldRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._field = field;
@@ -41,7 +41,7 @@
     return e;
   }
 
-  FieldRefElement.created() : super.created();
+  FieldRefElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -82,7 +82,8 @@
       children = <Element>[
         new SpanElement()..text = header,
         new InstanceRefElement(_isolate, _field.declaredType, _objects,
-            queue: _r.queue, expandable: _expandable),
+                queue: _r.queue, expandable: _expandable)
+            .element,
         new SpanElement()..text = ' ',
         new AnchorElement(href: Uris.inspect(_isolate, object: _field))
           ..text = _field.name
diff --git a/runtime/observatory/lib/src/elements/field_view.dart b/runtime/observatory/lib/src/elements/field_view.dart
index 27422a4..30b5c7c 100644
--- a/runtime/observatory/lib/src/elements/field_view.dart
+++ b/runtime/observatory/lib/src/elements/field_view.dart
@@ -26,7 +26,7 @@
 import 'package:observatory/src/elements/source_link.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class FieldViewElement extends HtmlElement implements Renderable {
+class FieldViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<FieldViewElement>('field-view', dependencies: const [
     ClassRefElement.tag,
@@ -96,7 +96,7 @@
     assert(retainingPaths != null);
     assert(scripts != null);
     assert(objects != null);
-    FieldViewElement e = document.createElement(tag.name);
+    FieldViewElement e = new FieldViewElement.created();
     e._r = new RenderingScheduler<FieldViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -117,7 +117,7 @@
     return e;
   }
 
-  FieldViewElement.created() : super.created();
+  FieldViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -160,8 +160,9 @@
           new HeadingElement.h2()..text = '$header ${field.name}',
           new HRElement(),
           new ObjectCommonElement(_isolate, _field, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new BRElement(),
           new DivElement()
             ..classes = ['memberList']
@@ -172,36 +173,40 @@
                 ? const []
                 : [
                     new ScriptInsetElement(_isolate, _field.location.script,
-                        _scripts, _objects, _events,
-                        startPos: field.location.tokenPos,
-                        endPos: field.location.tokenPos,
-                        queue: _r.queue)
+                            _scripts, _objects, _events,
+                            startPos: field.location.tokenPos,
+                            endPos: field.location.tokenPos,
+                            queue: _r.queue)
+                        .element
                   ],
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
 
   List<Element> _createMenu() {
     final menu = <Element>[
-      new NavTopMenuElement(queue: _r.queue),
-      new NavVMMenuElement(_vm, _events, queue: _r.queue),
-      new NavIsolateMenuElement(_isolate, _events, queue: _r.queue)
+      new NavTopMenuElement(queue: _r.queue).element,
+      new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+      new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element
     ];
     if (_library != null) {
-      menu.add(new NavLibraryMenuElement(_isolate, _library, queue: _r.queue));
+      menu.add(new NavLibraryMenuElement(_isolate, _library, queue: _r.queue)
+          .element);
     } else if (_field.dartOwner is M.ClassRef) {
       menu.add(
-          new NavClassMenuElement(_isolate, _field.dartOwner, queue: _r.queue));
+          new NavClassMenuElement(_isolate, _field.dartOwner, queue: _r.queue)
+              .element);
     }
     menu.addAll(<Element>[
       navMenu(_field.name),
-      new NavRefreshElement(queue: _r.queue)
-        ..onRefresh.listen((e) {
-          e.element.disabled = true;
-          _refresh();
-        }),
-      new NavNotifyElement(_notifications, queue: _r.queue)
+      (new NavRefreshElement(queue: _r.queue)
+            ..onRefresh.listen((e) {
+              e.element.disabled = true;
+              _refresh();
+            }))
+          .element,
+      new NavNotifyElement(_notifications, queue: _r.queue).element
     ]);
     return menu;
   }
@@ -233,7 +238,8 @@
             ..classes = ['memberName']
             ..children = <Element>[
               new SourceLinkElement(_isolate, field.location, _scripts,
-                  queue: _r.queue)
+                      queue: _r.queue)
+                  .element
             ]
         ]
     ];
@@ -280,7 +286,8 @@
         break;
       case M.GuardClassKind.single:
         guard.add(
-            new ClassRefElement(_isolate, _field.guardClass, queue: _r.queue));
+            new ClassRefElement(_isolate, _field.guardClass, queue: _r.queue)
+                .element);
         break;
     }
     guard.add(new SpanElement()
diff --git a/runtime/observatory/lib/src/elements/flag_list.dart b/runtime/observatory/lib/src/elements/flag_list.dart
index b0ca6e1..7aa02fd 100644
--- a/runtime/observatory/lib/src/elements/flag_list.dart
+++ b/runtime/observatory/lib/src/elements/flag_list.dart
@@ -18,7 +18,7 @@
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class FlagListElement extends HtmlElement implements Renderable {
+class FlagListElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<FlagListElement>('flag-list', dependencies: const [
     NavNotifyElement.tag,
@@ -47,7 +47,7 @@
     assert(events != null);
     assert(repository != null);
     assert(notifications != null);
-    FlagListElement e = document.createElement(tag.name);
+    FlagListElement e = new FlagListElement.created();
     e._r = new RenderingScheduler<FlagListElement>(e, queue: queue);
     e._vm = vm;
     e._events = events;
@@ -56,7 +56,7 @@
     return e;
   }
 
-  FlagListElement.created() : super.created();
+  FlagListElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -99,24 +99,25 @@
 
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
         navMenu('flags', link: Uris.flags()),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            try {
-              await _refresh();
-            } finally {
-              e.element.disabled = false;
-            }
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                try {
+                  await _refresh();
+                } finally {
+                  e.element.disabled = false;
+                }
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered']
         ..children = content,
-      new ViewFooterElement(queue: _r.queue)
+      new ViewFooterElement(queue: _r.queue).element
     ];
   }
 
diff --git a/runtime/observatory/lib/src/elements/function_ref.dart b/runtime/observatory/lib/src/elements/function_ref.dart
index 54ace9e..702eb39 100644
--- a/runtime/observatory/lib/src/elements/function_ref.dart
+++ b/runtime/observatory/lib/src/elements/function_ref.dart
@@ -19,7 +19,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class FunctionRefElement extends HtmlElement implements Renderable {
+class FunctionRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<FunctionRefElement>('function-ref');
 
   RenderingScheduler<FunctionRefElement> _r;
@@ -38,7 +38,7 @@
       {bool qualified: true, RenderingQueue queue}) {
     assert(function != null);
     assert(qualified != null);
-    FunctionRefElement e = document.createElement(tag.name);
+    FunctionRefElement e = new FunctionRefElement.created();
     e._r = new RenderingScheduler<FunctionRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._function = function;
@@ -46,7 +46,7 @@
     return e;
   }
 
-  FunctionRefElement.created() : super.created();
+  FunctionRefElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -87,7 +87,7 @@
       if (owner is M.ClassRef) {
         content.addAll([
           new SpanElement()..text = '.',
-          new ClassRefElement(_isolate, owner, queue: _r.queue)
+          new ClassRefElement(_isolate, owner, queue: _r.queue).element
         ]);
       }
     }
diff --git a/runtime/observatory/lib/src/elements/function_view.dart b/runtime/observatory/lib/src/elements/function_view.dart
index 6b73ba8..3be3b2b 100644
--- a/runtime/observatory/lib/src/elements/function_view.dart
+++ b/runtime/observatory/lib/src/elements/function_view.dart
@@ -29,7 +29,7 @@
 import 'package:observatory/src/elements/source_link.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class FunctionViewElement extends HtmlElement implements Renderable {
+class FunctionViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<FunctionViewElement>('function-view', dependencies: const [
     ClassRefElement.tag,
@@ -102,7 +102,7 @@
     assert(retainingPaths != null);
     assert(scripts != null);
     assert(objects != null);
-    FunctionViewElement e = document.createElement(tag.name);
+    FunctionViewElement e = new FunctionViewElement.created();
     e._r = new RenderingScheduler<FunctionViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -123,7 +123,7 @@
     return e;
   }
 
-  FunctionViewElement.created() : super.created();
+  FunctionViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -148,8 +148,9 @@
           new HeadingElement.h2()..text = 'Function ${_function.name}',
           new HRElement(),
           new ObjectCommonElement(_isolate, _function, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new BRElement(),
           new DivElement()
             ..classes = ['memberList']
@@ -160,35 +161,38 @@
                 ? const []
                 : [
                     new SourceInsetElement(_isolate, _function.location,
-                        _scripts, _objects, _events,
-                        queue: _r.queue)
+                            _scripts, _objects, _events,
+                            queue: _r.queue)
+                        .element
                   ],
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
 
   List<Element> _createMenu() {
     final menu = <Element>[
-      new NavTopMenuElement(queue: _r.queue),
-      new NavVMMenuElement(_vm, _events, queue: _r.queue),
-      new NavIsolateMenuElement(_isolate, _events, queue: _r.queue)
+      new NavTopMenuElement(queue: _r.queue).element,
+      new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+      new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element
     ];
     if (_library != null) {
-      menu.add(new NavLibraryMenuElement(_isolate, _library,
-          queue: _r.queue));
+      menu.add(new NavLibraryMenuElement(_isolate, _library, queue: _r.queue)
+          .element);
     } else if (_function.dartOwner is M.ClassRef) {
       menu.add(new NavClassMenuElement(_isolate, _function.dartOwner,
-          queue: _r.queue));
+              queue: _r.queue)
+          .element);
     }
     menu.addAll(<Element>[
       navMenu(_function.name),
-      new NavRefreshElement(queue: _r.queue)
-        ..onRefresh.listen((e) {
-          e.element.disabled = true;
-          _refresh();
-        }),
-      new NavNotifyElement(_notifications, queue: _r.queue)
+      (new NavRefreshElement(queue: _r.queue)
+            ..onRefresh.listen((e) {
+              e.element.disabled = true;
+              _refresh();
+            }))
+          .element,
+      new NavNotifyElement(_notifications, queue: _r.queue).element
     ]);
     return menu;
   }
@@ -205,8 +209,8 @@
             ..classes = ['memberName']
             ..children = <Element>[
               new SpanElement()
-                ..text = '${_function.isStatic ? "static ": ""}'
-                    '${_function.isConst ? "const ": ""}'
+                ..text = '${_function.isStatic ? "static " : ""}'
+                    '${_function.isConst ? "const " : ""}'
                     '${_functionKindToString(_function.kind)}'
             ]
         ],
@@ -237,7 +241,8 @@
             ..classes = ['memberName']
             ..children = <Element>[
               new FieldRefElement(_isolate, _function.field, _objects,
-                  queue: _r.queue)
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -251,7 +256,8 @@
           ..classes = ['memberName']
           ..children = <Element>[
             new SourceLinkElement(_isolate, _function.location, _scripts,
-                queue: _r.queue)
+                    queue: _r.queue)
+                .element
           ]
       ]);
     if (_function.code != null) {
@@ -265,6 +271,7 @@
             ..classes = ['memberName']
             ..children = <Element>[
               new CodeRefElement(_isolate, _function.code, queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -279,12 +286,13 @@
             ..classes = ['memberName']
             ..children = <Element>[
               new CodeRefElement(_isolate, _function.unoptimizedCode,
-                  queue: _r.queue),
+                      queue: _r.queue)
+                  .element,
               new SpanElement()
                 ..title = 'This count is used to determine when a function '
                     'will be optimized.  It is a combination of call '
                     'counts and other factors.'
-                ..text = ' (usage count: ${function.usageCounter })'
+                ..text = ' (usage count: ${function.usageCounter})'
             ]
         ]);
     }
@@ -298,8 +306,8 @@
           new DivElement()
             ..classes = ['memberName']
             ..children = <Element>[
-              new CodeRefElement(_isolate, _function.bytecode,
-                  queue: _r.queue),
+              new CodeRefElement(_isolate, _function.bytecode, queue: _r.queue)
+                  .element,
             ]
         ]);
     }
@@ -318,7 +326,8 @@
             ..classes = ['memberName']
             ..children = <Element>[
               new InstanceRefElement(_isolate, _function.icDataArray, _objects,
-                  queue: _r.queue)
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -426,8 +435,8 @@
         return 'implicit getter';
       case M.FunctionKind.implicitSetter:
         return 'implicit setter';
-      case M.FunctionKind.implicitStaticFinalGetter:
-        return 'implicit static final getter';
+      case M.FunctionKind.implicitStaticGetter:
+        return 'implicit static getter';
       case M.FunctionKind.staticFieldInitializer:
         return 'field initializer';
       case M.FunctionKind.irregexpFunction:
@@ -442,6 +451,8 @@
         return 'collected';
       case M.FunctionKind.native:
         return 'native';
+      case M.FunctionKind.ffiTrampoline:
+        return 'ffi trampoline';
       case M.FunctionKind.stub:
         return 'stub';
       case M.FunctionKind.tag:
diff --git a/runtime/observatory/lib/src/elements/general_error.dart b/runtime/observatory/lib/src/elements/general_error.dart
index 152df99..f94872b 100644
--- a/runtime/observatory/lib/src/elements/general_error.dart
+++ b/runtime/observatory/lib/src/elements/general_error.dart
@@ -13,7 +13,7 @@
 import 'package:observatory/src/elements/nav/notify.dart';
 import 'package:observatory/src/elements/nav/top_menu.dart';
 
-class GeneralErrorElement extends HtmlElement implements Renderable {
+class GeneralErrorElement extends CustomElement implements Renderable {
   static const tag = const Tag<GeneralErrorElement>('general-error',
       dependencies: const [NavTopMenuElement.tag, NavNotifyElement.tag]);
 
@@ -32,14 +32,14 @@
       {String message: '', RenderingQueue queue}) {
     assert(notifications != null);
     assert(message != null);
-    GeneralErrorElement e = document.createElement(tag.name);
+    GeneralErrorElement e = new GeneralErrorElement.created();
     e._r = new RenderingScheduler<GeneralErrorElement>(e, queue: queue);
     e._message = message;
     e._notifications = notifications;
     return e;
   }
 
-  GeneralErrorElement.created() : super.created();
+  GeneralErrorElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -57,8 +57,8 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered']
diff --git a/runtime/observatory/lib/src/elements/heap_map.dart b/runtime/observatory/lib/src/elements/heap_map.dart
index 6db1ce8..51373bfc 100644
--- a/runtime/observatory/lib/src/elements/heap_map.dart
+++ b/runtime/observatory/lib/src/elements/heap_map.dart
@@ -20,7 +20,7 @@
 import 'package:observatory/src/elements/nav/top_menu.dart';
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 
-class HeapMapElement extends HtmlElement implements Renderable {
+class HeapMapElement extends CustomElement implements Renderable {
   static const tag = const Tag<HeapMapElement>('heap-map', dependencies: const [
     NavTopMenuElement.tag,
     NavVMMenuElement.tag,
@@ -48,7 +48,7 @@
     assert(isolate != null);
     assert(events != null);
     assert(notifications != null);
-    HeapMapElement e = document.createElement(tag.name);
+    HeapMapElement e = new HeapMapElement.created();
     e._r = new RenderingScheduler<HeapMapElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -57,7 +57,7 @@
     return e;
   }
 
-  HeapMapElement.created() : super.created();
+  HeapMapElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -104,19 +104,23 @@
 
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('heap map'),
-        new NavRefreshElement(label: 'Mark-Compact', queue: _r.queue)
-          ..onRefresh.listen((_) => _refresh(gc: "mark-compact")),
-        new NavRefreshElement(label: 'Mark-Sweep', queue: _r.queue)
-          ..onRefresh.listen((_) => _refresh(gc: "mark-sweep")),
-        new NavRefreshElement(label: 'Scavenge', queue: _r.queue)
-          ..onRefresh.listen((_) => _refresh(gc: "scavenge")),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((_) => _refresh()),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(label: 'Mark-Compact', queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh(gc: "mark-compact")))
+            .element,
+        (new NavRefreshElement(label: 'Mark-Sweep', queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh(gc: "mark-sweep")))
+            .element,
+        (new NavRefreshElement(label: 'Scavenge', queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh(gc: "scavenge")))
+            .element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh()))
+            .element,
+        (new NavNotifyElement(_notifications, queue: _r.queue)).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
diff --git a/runtime/observatory/lib/src/elements/heap_snapshot.dart b/runtime/observatory/lib/src/elements/heap_snapshot.dart
index 3e6e455..2b32375 100644
--- a/runtime/observatory/lib/src/elements/heap_snapshot.dart
+++ b/runtime/observatory/lib/src/elements/heap_snapshot.dart
@@ -32,7 +32,7 @@
   groupByClass
 }
 
-class HeapSnapshotElement extends HtmlElement implements Renderable {
+class HeapSnapshotElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<HeapSnapshotElement>('heap-snapshot', dependencies: const [
     ClassRefElement.tag,
@@ -79,7 +79,7 @@
     assert(notifications != null);
     assert(snapshots != null);
     assert(objects != null);
-    HeapSnapshotElement e = document.createElement(tag.name);
+    HeapSnapshotElement e = new HeapSnapshotElement.created();
     e._r = new RenderingScheduler<HeapSnapshotElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -90,7 +90,7 @@
     return e;
   }
 
-  HeapSnapshotElement.created() : super.created();
+  HeapSnapshotElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -109,16 +109,17 @@
   void render() {
     final content = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('heap snapshot'),
-        new NavRefreshElement(queue: _r.queue)
-          ..disabled = M.isHeapSnapshotProgressRunning(_progress?.status)
-          ..onRefresh.listen((e) {
-            _refresh();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..disabled = M.isHeapSnapshotProgressRunning(_progress?.status)
+              ..onRefresh.listen((e) {
+                _refresh();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
     ];
     if (_progress == null) {
@@ -275,7 +276,7 @@
           new DivElement()
             ..classes = ['content-centered-big', 'explanation']
             ..text = text,
-          _tree
+          _tree.element
         ]);
         break;
       case HeapSnapshotTreeMode.mergedDominatorTree:
@@ -290,7 +291,7 @@
           new DivElement()
             ..classes = ['content-centered-big', 'explanation']
             ..text = text,
-          _tree
+          _tree.element
         ]);
         break;
       case HeapSnapshotTreeMode.ownershipTable:
@@ -308,7 +309,7 @@
           new DivElement()
             ..classes = ['content-centered-big', 'explanation']
             ..text = text,
-          _tree
+          _tree.element
         ]);
         break;
       case HeapSnapshotTreeMode.groupByClass:
@@ -318,7 +319,7 @@
             _createGroup, _updateGroup, _getChildrenGroup,
             items: items, queue: _r.queue);
         _tree.expand(_snapshot.dominatorTree);
-        report.add(_tree);
+        report.add(_tree.element);
         break;
       default:
         break;
@@ -504,8 +505,9 @@
       element.children[2].text = _tree.isExpanded(item) ? '▼' : '►';
       element.children[3].text = '${item.instances} instances of ';
       element.children[4] =
-          new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
-            ..classes = ['name'];
+          (new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
+                ..classes = ['name'])
+              .element;
     } else if (item is Iterable) {
       element.children[0].text = '';
       if (item.isNotEmpty) {
@@ -536,12 +538,12 @@
         element.children[3].text =
             '${item.count} references from instances of ';
         element.children[4].children = <Element>[
-          new ClassRefElement(_isolate, item.source, queue: _r.queue)
+          new ClassRefElement(_isolate, item.source, queue: _r.queue).element
         ];
       } else if (item is M.HeapSnapshotClassOutbound) {
         element.children[3]..text = '${item.count} references to instances of ';
         element.children[4].children = <Element>[
-          new ClassRefElement(_isolate, item.target, queue: _r.queue)
+          new ClassRefElement(_isolate, item.target, queue: _r.queue).element
         ];
       }
     }
@@ -556,8 +558,9 @@
       ..classes = ['name']
       ..children = <Element>[
         new SpanElement()..text = ' instances of ',
-        new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
-          ..classes = ['name']
+        (new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
+              ..classes = ['name'])
+            .element
       ];
   }
 
diff --git a/runtime/observatory/lib/src/elements/helpers/any_ref.dart b/runtime/observatory/lib/src/elements/helpers/any_ref.dart
index 693fe7e..e69b983 100644
--- a/runtime/observatory/lib/src/elements/helpers/any_ref.dart
+++ b/runtime/observatory/lib/src/elements/helpers/any_ref.dart
@@ -39,52 +39,57 @@
     }
   } else if (ref is M.ObjectRef) {
     if (ref is M.ClassRef) {
-      return new ClassRefElement(isolate, ref, queue: queue);
+      return new ClassRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.CodeRef) {
-      return new CodeRefElement(isolate, ref, queue: queue);
+      return new CodeRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.ContextRef) {
       return new ContextRefElement(isolate, ref, objects,
-          queue: queue, expandable: expandable);
+              queue: queue, expandable: expandable)
+          .element;
     } else if (ref is M.Error) {
-      return new ErrorRefElement(ref, queue: queue);
+      return new ErrorRefElement(ref, queue: queue).element;
     } else if (ref is M.FieldRef) {
       return new FieldRefElement(isolate, ref, objects,
-          queue: queue, expandable: expandable);
+              queue: queue, expandable: expandable)
+          .element;
     } else if (ref is M.FunctionRef) {
-      return new FunctionRefElement(isolate, ref, queue: queue);
+      return new FunctionRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.ICDataRef) {
-      return new ICDataRefElement(isolate, ref, queue: queue);
+      return new ICDataRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.InstanceRef) {
       return new InstanceRefElement(isolate, ref, objects,
-          queue: queue, expandable: expandable);
+              queue: queue, expandable: expandable)
+          .element;
     } else if (ref is M.LibraryRef) {
-      return new LibraryRefElement(isolate, ref, queue: queue);
+      return new LibraryRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.LocalVarDescriptorsRef) {
-      return new LocalVarDescriptorsRefElement(isolate, ref, queue: queue);
+      return new LocalVarDescriptorsRefElement(isolate, ref, queue: queue)
+          .element;
     } else if (ref is M.MegamorphicCacheRef) {
-      return new MegamorphicCacheRefElement(isolate, ref, queue: queue);
+      return new MegamorphicCacheRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.ObjectPoolRef) {
-      return new ObjectPoolRefElement(isolate, ref, queue: queue);
+      return new ObjectPoolRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.PcDescriptorsRef) {
-      return new PcDescriptorsRefElement(isolate, ref, queue: queue);
+      return new PcDescriptorsRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.ScriptRef) {
-      return new ScriptRefElement(isolate, ref, queue: queue);
+      return new ScriptRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.SingleTargetCacheRef) {
-      return new SingleTargetCacheRefElement(isolate, ref, queue: queue);
+      return new SingleTargetCacheRefElement(isolate, ref, queue: queue)
+          .element;
     } else if (ref is M.SubtypeTestCacheRef) {
-      return new SubtypeTestCacheRefElement(isolate, ref, queue: queue);
+      return new SubtypeTestCacheRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.TypeArgumentsRef) {
-      return new TypeArgumentsRefElement(isolate, ref, queue: queue);
+      return new TypeArgumentsRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.UnknownObjectRef) {
-      return new UnknownObjectRefElement(isolate, ref, queue: queue);
+      return new UnknownObjectRefElement(isolate, ref, queue: queue).element;
     } else if (ref is M.UnlinkedCallRef) {
-      return new UnlinkedCallRefElement(isolate, ref, queue: queue);
+      return new UnlinkedCallRefElement(isolate, ref, queue: queue).element;
     } else {
       return new AnchorElement(href: Uris.inspect(isolate, object: ref))
         ..text = 'object';
     }
   } else if (ref is M.Sentinel) {
-    return new SentinelValueElement(ref, queue: queue);
+    return new SentinelValueElement(ref, queue: queue).element;
   }
   throw new Exception('Unknown ref type (${ref.runtimeType})');
 }
diff --git a/runtime/observatory/lib/src/elements/helpers/tag.dart b/runtime/observatory/lib/src/elements/helpers/tag.dart
index 0d488c1..1ad74c7 100644
--- a/runtime/observatory/lib/src/elements/helpers/tag.dart
+++ b/runtime/observatory/lib/src/elements/helpers/tag.dart
@@ -2,10 +2,91 @@
 // 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';
 
+HtmlElement element(CustomElement e) => e.element;
+
+class CustomElement {
+  static Expando reverseElements = new Expando();
+  static CustomElement reverse(HtmlElement element) => reverseElements[element];
+
+  static List<CustomElement> toBeAttached = new List<CustomElement>();
+  static void drainAttached() {
+    // Send 'attached' to elements that have been attached to the document.
+    bool fired = false;
+    var connectedElements = toBeAttached
+        .where((CustomElement element) => element.element.isConnected)
+        .toList();
+    for (CustomElement element in connectedElements) {
+      toBeAttached.remove(element);
+      element.attached();
+      fired = true;
+    }
+
+    if (toBeAttached.isEmpty) {
+      return; // Done.
+    }
+
+    if (fired) {
+      // The 'attached' events above may have scheduled microtasks that will
+      // will add more CustomElements to be document, e.g. 'render'.
+      scheduleMicrotask(() => drainAttached());
+    }
+
+    while (!toBeAttached.isEmpty) {
+      // Either this element will never be attached or it will be attached
+      // after a turn of the outer event loop. Fire 'attached' in case it is
+      // the latter, since firing it out of order is preferrable to not firing
+      // it at all.
+      CustomElement element = toBeAttached.removeLast();
+      print("Warning: created but not in document: $element");
+      element.attached();
+    }
+  }
+
+  final HtmlElement element;
+  CustomElement.created(Tag tag) : element = document.createElement("shadow") {
+    reverseElements[element] = this;
+    element.classes = [tag.name];
+
+    if (toBeAttached.isEmpty) {
+      scheduleMicrotask(() => drainAttached());
+    }
+    toBeAttached.add(this);
+  }
+
+  void attached() {}
+  void detached() {}
+
+  Element get parent => element.parent;
+
+  List<Element> get children => element.children;
+  set children(List<Element> c) => element.children = c;
+
+  CssClassSet get classes => element.classes;
+  set classes(dynamic c) => element.classes = c;
+
+  String get title => element.title;
+  set title(String t) => element.title = t;
+
+  String get text => element.text;
+  set text(String t) => element.text = t;
+
+  CssStyleDeclaration get style => element.style;
+
+  ElementStream<MouseEvent> get onClick => element.onClick;
+
+  Rectangle getBoundingClientRect() => element.getBoundingClientRect();
+
+  List<Node> getElementsByClassName(String c) =>
+      element.getElementsByClassName(c);
+
+  void scrollIntoView() => element.scrollIntoView();
+}
+
 /// Utility class for Custom Tags registration.
-class Tag<T extends HtmlElement> {
+class Tag<T extends CustomElement> {
   /// Tag name.
   final String name;
 
@@ -13,25 +94,4 @@
   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/icdata_ref.dart b/runtime/observatory/lib/src/elements/icdata_ref.dart
index 5a4f4d7..bcf1c04 100644
--- a/runtime/observatory/lib/src/elements/icdata_ref.dart
+++ b/runtime/observatory/lib/src/elements/icdata_ref.dart
@@ -9,7 +9,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class ICDataRefElement extends HtmlElement implements Renderable {
+class ICDataRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<ICDataRefElement>('icdata-ref');
 
   RenderingScheduler<ICDataRefElement> _r;
@@ -26,14 +26,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(icdata != null);
-    ICDataRefElement e = document.createElement(tag.name);
+    ICDataRefElement e = new ICDataRefElement.created();
     e._r = new RenderingScheduler<ICDataRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._icdata = icdata;
     return e;
   }
 
-  ICDataRefElement.created() : super.created();
+  ICDataRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/icdata_view.dart b/runtime/observatory/lib/src/elements/icdata_view.dart
index 3729a73..f089e5b 100644
--- a/runtime/observatory/lib/src/elements/icdata_view.dart
+++ b/runtime/observatory/lib/src/elements/icdata_view.dart
@@ -19,7 +19,7 @@
 import 'package:observatory/src/elements/object_common.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class ICDataViewElement extends HtmlElement implements Renderable {
+class ICDataViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<ICDataViewElement>('icdata-view', dependencies: const [
     CurlyBlockElement.tag,
@@ -77,7 +77,7 @@
     assert(references != null);
     assert(retainingPaths != null);
     assert(objects != null);
-    ICDataViewElement e = document.createElement(tag.name);
+    ICDataViewElement e = new ICDataViewElement.created();
     e._r = new RenderingScheduler<ICDataViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -93,7 +93,7 @@
     return e;
   }
 
-  ICDataViewElement.created() : super.created();
+  ICDataViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -111,17 +111,18 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('icdata'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _icdata = await _icdatas.get(_isolate, _icdata.id);
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _icdata = await _icdatas.get(_isolate, _icdata.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -129,8 +130,9 @@
           new HeadingElement.h2()..text = 'ICData',
           new HRElement(),
           new ObjectCommonElement(_isolate, _icdata, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new DivElement()
             ..classes = ['memberList']
             ..children = <Element>[
@@ -192,7 +194,7 @@
                 ]
             ],
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/inbound_references.dart b/runtime/observatory/lib/src/elements/inbound_references.dart
index bfd9d29..a1e24f6 100644
--- a/runtime/observatory/lib/src/elements/inbound_references.dart
+++ b/runtime/observatory/lib/src/elements/inbound_references.dart
@@ -11,7 +11,7 @@
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 import 'package:observatory/src/elements/helpers/tag.dart';
 
-class InboundReferencesElement extends HtmlElement implements Renderable {
+class InboundReferencesElement extends CustomElement implements Renderable {
   static const tag = const Tag<InboundReferencesElement>('inbound-references',
       dependencies: const [CurlyBlockElement.tag, InstanceRefElement.tag]);
 
@@ -37,7 +37,7 @@
     assert(object != null);
     assert(references != null);
     assert(objects != null);
-    InboundReferencesElement e = document.createElement(tag.name);
+    InboundReferencesElement e = new InboundReferencesElement.created();
     e._r = new RenderingScheduler<InboundReferencesElement>(e, queue: queue);
     e._isolate = isolate;
     e._object = object;
@@ -46,7 +46,7 @@
     return e;
   }
 
-  InboundReferencesElement.created() : super.created();
+  InboundReferencesElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -73,7 +73,7 @@
               e.control.disabled = false;
             }
           });
-    children = <Element>[curlyBlock];
+    children = <Element>[curlyBlock.element];
     _r.waitFor([curlyBlock.onRendered.first]);
   }
 
@@ -109,8 +109,9 @@
     content.addAll([
       anyRef(_isolate, reference.source, _objects, queue: _r.queue),
       new InboundReferencesElement(
-          _isolate, reference.source, _references, _objects,
-          queue: _r.queue)
+              _isolate, reference.source, _references, _objects,
+              queue: _r.queue)
+          .element
     ]);
 
     return new DivElement()
diff --git a/runtime/observatory/lib/src/elements/instance_ref.dart b/runtime/observatory/lib/src/elements/instance_ref.dart
index 6ee4dfd..96db281 100644
--- a/runtime/observatory/lib/src/elements/instance_ref.dart
+++ b/runtime/observatory/lib/src/elements/instance_ref.dart
@@ -13,7 +13,7 @@
 import 'package:observatory/src/elements/helpers/uris.dart';
 import 'package:observatory/utils.dart';
 
-class InstanceRefElement extends HtmlElement implements Renderable {
+class InstanceRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<InstanceRefElement>('instance-ref',
       dependencies: const [CurlyBlockElement.tag]);
 
@@ -37,7 +37,7 @@
     assert(isolate != null);
     assert(instance != null);
     assert(objects != null);
-    InstanceRefElement e = document.createElement(tag.name);
+    InstanceRefElement e = new InstanceRefElement.created();
     e._r = new RenderingScheduler<InstanceRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._instance = instance;
@@ -46,7 +46,7 @@
     return e;
   }
 
-  InstanceRefElement.created() : super.created();
+  InstanceRefElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -67,20 +67,21 @@
     if (_expandable && _hasValue()) {
       content.addAll([
         new SpanElement()..text = ' ',
-        new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
-          ..content = <Element>[
-            new DivElement()
-              ..classes = ['indent']
-              ..children = _createValue()
-          ]
-          ..onToggle.listen((e) async {
-            _expanded = e.control.expanded;
-            if (_expanded) {
-              e.control.disabled = true;
-              await _refresh();
-              e.control.disabled = false;
-            }
-          })
+        (new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
+              ..content = <Element>[
+                new DivElement()
+                  ..classes = ['indent']
+                  ..children = _createValue()
+              ]
+              ..onToggle.listen((e) async {
+                _expanded = e.control.expanded;
+                if (_expanded) {
+                  e.control.disabled = true;
+                  await _refresh();
+                  e.control.disabled = false;
+                }
+              }))
+            .element
       ]);
     }
 
@@ -268,8 +269,8 @@
         return _loadedInstance.fields
             .map<Element>((f) => new DivElement()
               ..children = <Element>[
-                new FieldRefElement(_isolate, f.decl, _objects,
-                    queue: _r.queue),
+                new FieldRefElement(_isolate, f.decl, _objects, queue: _r.queue)
+                    .element,
                 new SpanElement()..text = ' = ',
                 anyRef(_isolate, f.value, _objects, queue: _r.queue)
               ])
@@ -329,11 +330,13 @@
         return [
           new SpanElement()..text = '<key> : ',
           new InstanceRefElement(_isolate, _loadedInstance.key, _objects,
-              queue: _r.queue),
+                  queue: _r.queue)
+              .element,
           new BRElement(),
           new SpanElement()..text = '<value> : ',
           new InstanceRefElement(_isolate, _loadedInstance.value, _objects,
-              queue: _r.queue),
+                  queue: _r.queue)
+              .element,
         ];
       default:
         return [];
diff --git a/runtime/observatory/lib/src/elements/instance_view.dart b/runtime/observatory/lib/src/elements/instance_view.dart
index 174af31..6540562 100644
--- a/runtime/observatory/lib/src/elements/instance_view.dart
+++ b/runtime/observatory/lib/src/elements/instance_view.dart
@@ -32,7 +32,7 @@
 import 'package:observatory/src/elements/view_footer.dart';
 import 'package:observatory/utils.dart';
 
-class InstanceViewElement extends HtmlElement implements Renderable {
+class InstanceViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<InstanceViewElement>('instance-view', dependencies: const [
     ClassRefElement.tag,
@@ -117,7 +117,7 @@
     assert(arguments != null);
     assert(breakpoints != null);
     assert(functions != null);
-    InstanceViewElement e = document.createElement(tag.name);
+    InstanceViewElement e = new InstanceViewElement.created();
     e._r = new RenderingScheduler<InstanceViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -138,7 +138,7 @@
     return e;
   }
 
-  InstanceViewElement.created() : super.created();
+  InstanceViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -162,25 +162,29 @@
             : 'instance of ${_instance.clazz.name}',
       new HRElement(),
       new ObjectCommonElement(_isolate, _instance, _retainedSizes,
-          _reachableSizes, _references, _retainingPaths, _objects,
-          queue: _r.queue),
+              _reachableSizes, _references, _retainingPaths, _objects,
+              queue: _r.queue)
+          .element,
       new BRElement(),
       new DivElement()
         ..classes = ['memberList']
         ..children = _createMembers(),
       new HRElement(),
       new EvalBoxElement(_isolate, _instance, _objects, _eval,
-          quickExpressions: const ['toString()', 'runtimeType'],
-          queue: _r.queue)
+              quickExpressions: const ['toString()', 'runtimeType'],
+              queue: _r.queue)
+          .element
     ];
     if (_location != null) {
       content.addAll([
         new HRElement(),
         new SourceInsetElement(_isolate, _location, _scripts, _objects, _events,
-            queue: _r.queue)
+                queue: _r.queue)
+            .element
       ]);
     }
-    content.addAll([new HRElement(), new ViewFooterElement(queue: _r.queue)]);
+    content.addAll(
+        [new HRElement(), new ViewFooterElement(queue: _r.queue).element]);
     children = <Element>[
       navBar(_createMenu()),
       new DivElement()
@@ -191,22 +195,25 @@
 
   List<Element> _createMenu() {
     final menu = <Element>[
-      new NavTopMenuElement(queue: _r.queue),
-      new NavVMMenuElement(_vm, _events, queue: _r.queue),
-      new NavIsolateMenuElement(_isolate, _events, queue: _r.queue)
+      new NavTopMenuElement(queue: _r.queue).element,
+      new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+      new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element
     ];
     if (_library != null) {
-      menu.add(new NavLibraryMenuElement(_isolate, _library, queue: _r.queue));
+      menu.add(new NavLibraryMenuElement(_isolate, _library, queue: _r.queue)
+          .element);
     }
     menu.addAll(<Element>[
-      new NavClassMenuElement(_isolate, _instance.clazz, queue: _r.queue),
+      new NavClassMenuElement(_isolate, _instance.clazz, queue: _r.queue)
+          .element,
       navMenu('instance'),
-      new NavRefreshElement(queue: _r.queue)
-        ..onRefresh.listen((e) {
-          e.element.disabled = true;
-          _refresh();
-        }),
-      new NavNotifyElement(_notifications, queue: _r.queue)
+      (new NavRefreshElement(queue: _r.queue)
+            ..onRefresh.listen((e) {
+              e.element.disabled = true;
+              _refresh();
+            }))
+          .element,
+      new NavNotifyElement(_notifications, queue: _r.queue).element
     ]);
     return menu;
   }
@@ -241,7 +248,8 @@
             ..classes = ['memberValue']
             ..children = <Element>[
               new ClassRefElement(_isolate, _instance.typeClass,
-                  queue: _r.queue)
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -257,7 +265,8 @@
             ..children = ([new SpanElement()..text = '< ']
               ..addAll(_typeArguments.types.expand((type) => [
                     new InstanceRefElement(_isolate, type, _objects,
-                        queue: _r.queue),
+                            queue: _r.queue)
+                        .element,
                     new SpanElement()..text = ', '
                   ]))
               ..removeLast()
@@ -275,7 +284,8 @@
             ..classes = ['memberValue']
             ..children = <Element>[
               new ClassRefElement(_isolate, _instance.parameterizedClass,
-                  queue: _r.queue)
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -302,7 +312,8 @@
             ..classes = ['memberValue']
             ..children = <Element>[
               new InstanceRefElement(_isolate, _instance.targetType, _objects,
-                  queue: _r.queue)
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -317,7 +328,8 @@
             ..classes = ['memberValue']
             ..children = <Element>[
               new InstanceRefElement(_isolate, _instance.bound, _objects,
-                  queue: _r.queue)
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -332,7 +344,8 @@
             ..classes = ['memberValue']
             ..children = <Element>[
               new FunctionRefElement(_isolate, _instance.closureFunction,
-                  queue: _r.queue)
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -347,8 +360,9 @@
             ..classes = ['memberValue']
             ..children = <Element>[
               new ContextRefElement(
-                  _isolate, _instance.closureContext, _objects,
-                  queue: _r.queue)
+                      _isolate, _instance.closureContext, _objects,
+                      queue: _r.queue)
+                  .element
             ]
         ]);
     }
@@ -386,25 +400,26 @@
           new DivElement()
             ..classes = ['memberName']
             ..children = <Element>[
-              new CurlyBlockElement(
-                  expanded: _instance.nativeFields.length <= 100,
-                  queue: _r.queue)
-                ..content = <Element>[
-                  new DivElement()
-                    ..classes = ['memberList']
-                    ..children = _instance.nativeFields
-                        .map<Element>((f) => new DivElement()
-                          ..classes = ['memberItem']
-                          ..children = <Element>[
-                            new DivElement()
-                              ..classes = ['memberName']
-                              ..text = '[ ${i++} ]',
-                            new DivElement()
-                              ..classes = ['memberValue']
-                              ..text = '[ ${f.value} ]'
-                          ])
-                        .toList()
-                ]
+              (new CurlyBlockElement(
+                      expanded: _instance.nativeFields.length <= 100,
+                      queue: _r.queue)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = _instance.nativeFields
+                            .map<Element>((f) => new DivElement()
+                              ..classes = ['memberItem']
+                              ..children = <Element>[
+                                new DivElement()
+                                  ..classes = ['memberName']
+                                  ..text = '[ ${i++} ]',
+                                new DivElement()
+                                  ..classes = ['memberValue']
+                                  ..text = '[ ${f.value} ]'
+                              ])
+                            .toList()
+                    ])
+                  .element
             ]
         ]);
     }
@@ -420,31 +435,34 @@
           new DivElement()
             ..classes = ['memberName']
             ..children = <Element>[
-              new CurlyBlockElement(
-                  expanded: fields.length <= 100, queue: _r.queue)
-                ..content = <Element>[
-                  new DivElement()
-                    ..classes = ['memberList']
-                    ..children = fields
-                        .map<Element>((f) => new DivElement()
-                          ..classes = ['memberItem']
-                          ..children = <Element>[
-                            new DivElement()
-                              ..classes = ['memberName']
+              (new CurlyBlockElement(
+                      expanded: fields.length <= 100, queue: _r.queue)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = fields
+                            .map<Element>((f) => new DivElement()
+                              ..classes = ['memberItem']
                               ..children = <Element>[
-                                new FieldRefElement(_isolate, f.decl, _objects,
-                                    queue: _r.queue)
-                              ],
-                            new DivElement()
-                              ..classes = ['memberValue']
-                              ..children = <Element>[
-                                new SpanElement()..text = ' = ',
-                                anyRef(_isolate, f.value, _objects,
-                                    queue: _r.queue)
-                              ]
-                          ])
-                        .toList()
-                ]
+                                new DivElement()
+                                  ..classes = ['memberName']
+                                  ..children = <Element>[
+                                    new FieldRefElement(
+                                            _isolate, f.decl, _objects,
+                                            queue: _r.queue)
+                                        .element
+                                  ],
+                                new DivElement()
+                                  ..classes = ['memberValue']
+                                  ..children = <Element>[
+                                    new SpanElement()..text = ' = ',
+                                    anyRef(_isolate, f.value, _objects,
+                                        queue: _r.queue)
+                                  ]
+                              ])
+                            .toList()
+                    ])
+                  .element
             ]
         ]);
     }
@@ -461,27 +479,28 @@
           new DivElement()
             ..classes = ['memberValue']
             ..children = <Element>[
-              new CurlyBlockElement(
-                  expanded: elements.length <= 100, queue: _r.queue)
-                ..content = <Element>[
-                  new DivElement()
-                    ..classes = ['memberList']
-                    ..children = elements
-                        .map<Element>((element) => new DivElement()
-                          ..classes = ['memberItem']
-                          ..children = <Element>[
-                            new DivElement()
-                              ..classes = ['memberName']
-                              ..text = '[ ${i++} ]',
-                            new DivElement()
-                              ..classes = ['memberValue']
+              (new CurlyBlockElement(
+                      expanded: elements.length <= 100, queue: _r.queue)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = elements
+                            .map<Element>((element) => new DivElement()
+                              ..classes = ['memberItem']
                               ..children = <Element>[
-                                anyRef(_isolate, element, _objects,
-                                    queue: _r.queue)
-                              ]
-                          ])
-                        .toList()
-                ]
+                                new DivElement()
+                                  ..classes = ['memberName']
+                                  ..text = '[ ${i++} ]',
+                                new DivElement()
+                                  ..classes = ['memberValue']
+                                  ..children = <Element>[
+                                    anyRef(_isolate, element, _objects,
+                                        queue: _r.queue)
+                                  ]
+                              ])
+                            .toList()
+                    ])
+                  .element
             ]
         ]);
       if (_instance.length != elements.length) {
@@ -509,32 +528,33 @@
           new DivElement()
             ..classes = ['memberName']
             ..children = <Element>[
-              new CurlyBlockElement(
-                  expanded: associations.length <= 100, queue: _r.queue)
-                ..content = <Element>[
-                  new DivElement()
-                    ..classes = ['memberList']
-                    ..children = associations
-                        .map<Element>((a) => new DivElement()
-                          ..classes = ['memberItem']
-                          ..children = <Element>[
-                            new DivElement()
-                              ..classes = ['memberName']
+              (new CurlyBlockElement(
+                      expanded: associations.length <= 100, queue: _r.queue)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = associations
+                            .map<Element>((a) => new DivElement()
+                              ..classes = ['memberItem']
                               ..children = <Element>[
-                                new SpanElement()..text = '[ ',
-                                anyRef(_isolate, a.key, _objects,
-                                    queue: _r.queue),
-                                new SpanElement()..text = ' ]',
-                              ],
-                            new DivElement()
-                              ..classes = ['memberValue']
-                              ..children = <Element>[
-                                anyRef(_isolate, a.value, _objects,
-                                    queue: _r.queue)
-                              ]
-                          ])
-                        .toList()
-                ]
+                                new DivElement()
+                                  ..classes = ['memberName']
+                                  ..children = <Element>[
+                                    new SpanElement()..text = '[ ',
+                                    anyRef(_isolate, a.key, _objects,
+                                        queue: _r.queue),
+                                    new SpanElement()..text = ' ]',
+                                  ],
+                                new DivElement()
+                                  ..classes = ['memberValue']
+                                  ..children = <Element>[
+                                    anyRef(_isolate, a.value, _objects,
+                                        queue: _r.queue)
+                                  ]
+                              ])
+                            .toList()
+                    ])
+                  .element
             ]
         ]);
       if (_instance.length != associations.length) {
@@ -564,24 +584,25 @@
           new DivElement()
             ..classes = ['memberValue']
             ..children = <Element>[
-              new CurlyBlockElement(
-                  expanded: typedElements.length <= 100, queue: _r.queue)
-                ..content = <Element>[
-                  new DivElement()
-                    ..classes = ['memberList']
-                    ..children = typedElements
-                        .map<Element>((e) => new DivElement()
-                          ..classes = ['memberItem']
-                          ..children = <Element>[
-                            new DivElement()
-                              ..classes = ['memberName']
-                              ..text = '[ ${i++} ]',
-                            new DivElement()
-                              ..classes = ['memberValue']
-                              ..text = '$e'
-                          ])
-                        .toList()
-                ]
+              (new CurlyBlockElement(
+                      expanded: typedElements.length <= 100, queue: _r.queue)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = typedElements
+                            .map<Element>((e) => new DivElement()
+                              ..classes = ['memberItem']
+                              ..children = <Element>[
+                                new DivElement()
+                                  ..classes = ['memberName']
+                                  ..text = '[ ${i++} ]',
+                                new DivElement()
+                                  ..classes = ['memberValue']
+                                  ..text = '$e'
+                              ])
+                            .toList()
+                    ])
+                  .element
             ]
         ]);
       if (_instance.length != typedElements.length) {
@@ -643,7 +664,8 @@
               ..classes = ['memberValue']
               ..children = <Element>[
                 new FunctionRefElement(_isolate, _instance.oneByteFunction,
-                    queue: _r.queue)
+                        queue: _r.queue)
+                    .element
               ]
           ],
         new DivElement()
@@ -656,7 +678,8 @@
               ..classes = ['memberValue']
               ..children = <Element>[
                 new FunctionRefElement(_isolate, _instance.twoByteFunction,
-                    queue: _r.queue)
+                        queue: _r.queue)
+                    .element
               ]
           ],
         new DivElement()
@@ -669,8 +692,9 @@
               ..classes = ['memberValue']
               ..children = <Element>[
                 new FunctionRefElement(
-                    _isolate, _instance.externalOneByteFunction,
-                    queue: _r.queue)
+                        _isolate, _instance.externalOneByteFunction,
+                        queue: _r.queue)
+                    .element
               ]
           ],
         new DivElement()
@@ -683,8 +707,9 @@
               ..classes = ['memberValue']
               ..children = <Element>[
                 new FunctionRefElement(
-                    _isolate, _instance.externalTwoByteFunction,
-                    queue: _r.queue)
+                        _isolate, _instance.externalTwoByteFunction,
+                        queue: _r.queue)
+                    .element
               ]
           ],
         new DivElement()
@@ -697,8 +722,9 @@
               ..classes = ['memberValue']
               ..children = <Element>[
                 new InstanceRefElement(
-                    _isolate, _instance.oneByteBytecode, _objects,
-                    queue: _r.queue)
+                        _isolate, _instance.oneByteBytecode, _objects,
+                        queue: _r.queue)
+                    .element
               ]
           ],
         new DivElement()
@@ -711,8 +737,9 @@
               ..classes = ['memberValue']
               ..children = <Element>[
                 new InstanceRefElement(
-                    _isolate, _instance.twoByteBytecode, _objects,
-                    queue: _r.queue)
+                        _isolate, _instance.twoByteBytecode, _objects,
+                        queue: _r.queue)
+                    .element
               ]
           ]
       ]);
@@ -744,7 +771,8 @@
               ..classes = ['memberValue']
               ..children = <Element>[
                 new InstanceRefElement(_isolate, _instance.key, _objects,
-                    queue: _r.queue),
+                        queue: _r.queue)
+                    .element,
               ]
           ],
         new DivElement()
@@ -757,7 +785,8 @@
               ..classes = ['memberValue']
               ..children = <Element>[
                 new InstanceRefElement(_isolate, _instance.value, _objects,
-                    queue: _r.queue),
+                        queue: _r.queue)
+                    .element,
               ]
           ]
       ]);
diff --git a/runtime/observatory/lib/src/elements/isolate/counter_chart.dart b/runtime/observatory/lib/src/elements/isolate/counter_chart.dart
index 37f8098..8cdd325 100644
--- a/runtime/observatory/lib/src/elements/isolate/counter_chart.dart
+++ b/runtime/observatory/lib/src/elements/isolate/counter_chart.dart
@@ -9,7 +9,7 @@
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 import 'package:observatory/src/elements/helpers/tag.dart';
 
-class IsolateCounterChartElement extends HtmlElement implements Renderable {
+class IsolateCounterChartElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<IsolateCounterChartElement>('isolate-counter-chart');
 
@@ -23,13 +23,13 @@
 
   factory IsolateCounterChartElement(Map counters, {RenderingQueue queue}) {
     assert(counters != null);
-    IsolateCounterChartElement e = document.createElement(tag.name);
+    IsolateCounterChartElement e = new IsolateCounterChartElement.created();
     e._r = new RenderingScheduler<IsolateCounterChartElement>(e, queue: queue);
     e._counters = counters;
     return e;
   }
 
-  IsolateCounterChartElement.created() : super.created();
+  IsolateCounterChartElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/isolate/location.dart b/runtime/observatory/lib/src/elements/isolate/location.dart
index 161917e..e10e3d2 100644
--- a/runtime/observatory/lib/src/elements/isolate/location.dart
+++ b/runtime/observatory/lib/src/elements/isolate/location.dart
@@ -10,7 +10,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/source_link.dart';
 
-class IsolateLocationElement extends HtmlElement implements Renderable {
+class IsolateLocationElement extends CustomElement implements Renderable {
   static const tag = const Tag<IsolateLocationElement>('isolate-location',
       dependencies: const [FunctionRefElement.tag, SourceLinkElement.tag]);
 
@@ -30,7 +30,7 @@
     assert(isolate != null);
     assert(events != null);
     assert(scripts != null);
-    IsolateLocationElement e = document.createElement(tag.name);
+    IsolateLocationElement e = new IsolateLocationElement.created();
     e._r = new RenderingScheduler<IsolateLocationElement>(e, queue: queue);
     e._isolate = isolate;
     e._events = events;
@@ -38,7 +38,7 @@
     return e;
   }
 
-  IsolateLocationElement.created() : super.created();
+  IsolateLocationElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -66,12 +66,14 @@
         children = <Element>[
           new SpanElement()..text = 'at ',
           new FunctionRefElement(
-              _isolate, M.topFrame(_isolate.pauseEvent).function,
-              queue: _r.queue),
+                  _isolate, M.topFrame(_isolate.pauseEvent).function,
+                  queue: _r.queue)
+              .element,
           new SpanElement()..text = ' (',
           new SourceLinkElement(
-              _isolate, M.topFrame(_isolate.pauseEvent).location, _scripts,
-              queue: _r.queue),
+                  _isolate, M.topFrame(_isolate.pauseEvent).location, _scripts,
+                  queue: _r.queue)
+              .element,
           new SpanElement()..text = ') '
         ];
         break;
@@ -93,12 +95,14 @@
             content.addAll([
               new SpanElement()..text = ' at ',
               new FunctionRefElement(
-                  _isolate, M.topFrame(_isolate.pauseEvent).function,
-                  queue: _r.queue),
+                      _isolate, M.topFrame(_isolate.pauseEvent).function,
+                      queue: _r.queue)
+                  .element,
               new SpanElement()..text = ' (',
-              new SourceLinkElement(
-                  _isolate, M.topFrame(_isolate.pauseEvent).location, _scripts,
-                  queue: _r.queue),
+              new SourceLinkElement(_isolate,
+                      M.topFrame(_isolate.pauseEvent).location, _scripts,
+                      queue: _r.queue)
+                  .element,
               new SpanElement()..text = ') '
             ]);
           }
diff --git a/runtime/observatory/lib/src/elements/isolate/run_state.dart b/runtime/observatory/lib/src/elements/isolate/run_state.dart
index 6dfc005..77ff052 100644
--- a/runtime/observatory/lib/src/elements/isolate/run_state.dart
+++ b/runtime/observatory/lib/src/elements/isolate/run_state.dart
@@ -8,7 +8,7 @@
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 import 'package:observatory/src/elements/helpers/tag.dart';
 
-class IsolateRunStateElement extends HtmlElement implements Renderable {
+class IsolateRunStateElement extends CustomElement implements Renderable {
   static const tag = const Tag<IsolateRunStateElement>('isolate-run-state');
 
   RenderingScheduler<IsolateRunStateElement> _r;
@@ -24,14 +24,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(events != null);
-    IsolateRunStateElement e = document.createElement(tag.name);
+    IsolateRunStateElement e = new IsolateRunStateElement.created();
     e._r = new RenderingScheduler<IsolateRunStateElement>(e, queue: queue);
     e._isolate = isolate;
     e._events = events;
     return e;
   }
 
-  IsolateRunStateElement.created() : super.created();
+  IsolateRunStateElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/isolate/shared_summary.dart b/runtime/observatory/lib/src/elements/isolate/shared_summary.dart
index be163f2..652c96c 100644
--- a/runtime/observatory/lib/src/elements/isolate/shared_summary.dart
+++ b/runtime/observatory/lib/src/elements/isolate/shared_summary.dart
@@ -11,7 +11,7 @@
 import 'package:observatory/src/elements/helpers/uris.dart';
 import 'package:observatory/src/elements/isolate/counter_chart.dart';
 
-class IsolateSharedSummaryElement extends HtmlElement implements Renderable {
+class IsolateSharedSummaryElement extends CustomElement implements Renderable {
   static const tag = const Tag<IsolateSharedSummaryElement>(
       'isolate-shared-summary',
       dependencies: const [IsolateCounterChartElement.tag]);
@@ -30,14 +30,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(events != null);
-    IsolateSharedSummaryElement e = document.createElement(tag.name);
+    IsolateSharedSummaryElement e = new IsolateSharedSummaryElement.created();
     e._r = new RenderingScheduler<IsolateSharedSummaryElement>(e, queue: queue);
     e._isolate = isolate;
     e._events = events;
     return e;
   }
 
-  IsolateSharedSummaryElement.created() : super.created();
+  IsolateSharedSummaryElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -150,7 +150,7 @@
               new AnchorElement(href: Uris.logging(_isolate))..text = 'logging'
             ]
         ],
-      new IsolateCounterChartElement(_isolate.counters, queue: _r.queue)
+      new IsolateCounterChartElement(_isolate.counters, queue: _r.queue).element
     ];
     if (_isolate.error != null) {
       children = <Element>[
diff --git a/runtime/observatory/lib/src/elements/isolate/summary.dart b/runtime/observatory/lib/src/elements/isolate/summary.dart
index 434e1fa..88c91a0 100644
--- a/runtime/observatory/lib/src/elements/isolate/summary.dart
+++ b/runtime/observatory/lib/src/elements/isolate/summary.dart
@@ -13,7 +13,7 @@
 import 'package:observatory/src/elements/isolate/run_state.dart';
 import 'package:observatory/src/elements/isolate/shared_summary.dart';
 
-class IsolateSummaryElement extends HtmlElement implements Renderable {
+class IsolateSummaryElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<IsolateSummaryElement>('isolate-summary', dependencies: const [
     IsolateRefElement.tag,
@@ -42,7 +42,7 @@
     assert(isolates != null);
     assert(events != null);
     assert(scripts != null);
-    IsolateSummaryElement e = document.createElement(tag.name);
+    IsolateSummaryElement e = new IsolateSummaryElement.created();
     e._r = new RenderingScheduler<IsolateSummaryElement>(e, queue: queue);
     e._isolate = isolate;
     e._isolates = isolates;
@@ -51,7 +51,7 @@
     return e;
   }
 
-  IsolateSummaryElement.created() : super.created();
+  IsolateSummaryElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -71,7 +71,7 @@
     if (_loadedIsolate == null) {
       children = <Element>[
         new SpanElement()..text = 'loading ',
-        new IsolateRefElement(_isolate, _events, queue: _r.queue)
+        new IsolateRefElement(_isolate, _events, queue: _r.queue).element
       ];
     } else {
       children = <Element>[
@@ -82,14 +82,17 @@
               ..classes = ['isolate-ref-container']
               ..children = <Element>[
                 new IsolateRefElement(_isolate, _events, queue: _r.queue)
+                    .element
               ],
             new DivElement()..style.flex = '1',
             new DivElement()
               ..classes = ['flex-row', 'isolate-state-container']
               ..children = <Element>[
-                new IsolateRunStateElement(_isolate, _events, queue: _r.queue),
+                new IsolateRunStateElement(_isolate, _events, queue: _r.queue)
+                    .element,
                 new IsolateLocationElement(_isolate, _events, _scripts,
-                    queue: _r.queue),
+                        queue: _r.queue)
+                    .element,
                 new SpanElement()..text = ' [',
                 new AnchorElement(href: Uris.debugger(_isolate))
                   ..text = 'debug',
@@ -98,6 +101,7 @@
           ],
         new BRElement(),
         new IsolateSharedSummaryElement(_isolate, _events, queue: _r.queue)
+            .element
       ];
     }
   }
diff --git a/runtime/observatory/lib/src/elements/isolate_reconnect.dart b/runtime/observatory/lib/src/elements/isolate_reconnect.dart
index 0820d41..bf72f2f 100644
--- a/runtime/observatory/lib/src/elements/isolate_reconnect.dart
+++ b/runtime/observatory/lib/src/elements/isolate_reconnect.dart
@@ -15,7 +15,7 @@
 import 'package:observatory/src/elements/nav/top_menu.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class IsolateReconnectElement extends HtmlElement implements Renderable {
+class IsolateReconnectElement extends CustomElement implements Renderable {
   static const tag = const Tag<IsolateReconnectElement>('isolate-reconnect',
       dependencies: const [
         NavTopMenuElement.tag,
@@ -47,7 +47,7 @@
     assert(missing != null);
     assert(uri != null);
     assert(notifications != null);
-    IsolateReconnectElement e = document.createElement(tag.name);
+    IsolateReconnectElement e = new IsolateReconnectElement.created();
     e._r = new RenderingScheduler<IsolateReconnectElement>(e, queue: queue);
     e._vm = vm;
     e._events = events;
@@ -57,7 +57,7 @@
     return e;
   }
 
-  IsolateReconnectElement.created() : super.created();
+  IsolateReconnectElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -80,8 +80,8 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered']
@@ -111,7 +111,7 @@
                   new AnchorElement(href: Uris.vm())..text = 'isolates summary',
                 ]))
         ],
-      new ViewFooterElement(queue: _r.queue)
+      new ViewFooterElement(queue: _r.queue).element
     ];
   }
 }
diff --git a/runtime/observatory/lib/src/elements/isolate_ref.dart b/runtime/observatory/lib/src/elements/isolate_ref.dart
index 49a2182..32e32a4 100644
--- a/runtime/observatory/lib/src/elements/isolate_ref.dart
+++ b/runtime/observatory/lib/src/elements/isolate_ref.dart
@@ -11,7 +11,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class IsolateRefElement extends HtmlElement implements Renderable {
+class IsolateRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<IsolateRefElement>('isolate-ref');
 
   RenderingScheduler<IsolateRefElement> _r;
@@ -28,14 +28,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(events != null);
-    IsolateRefElement e = document.createElement(tag.name);
+    IsolateRefElement e = new IsolateRefElement.created();
     e._r = new RenderingScheduler<IsolateRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._events = events;
     return e;
   }
 
-  IsolateRefElement.created() : super.created();
+  IsolateRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/isolate_view.dart b/runtime/observatory/lib/src/elements/isolate_view.dart
index 01f5b60..9db502b 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.dart
+++ b/runtime/observatory/lib/src/elements/isolate_view.dart
@@ -30,7 +30,7 @@
 import 'package:observatory/src/elements/view_footer.dart';
 import 'package:observatory/utils.dart';
 
-class IsolateViewElement extends HtmlElement implements Renderable {
+class IsolateViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<IsolateViewElement>('isolate-view', dependencies: const [
     CurlyBlockElement.tag,
@@ -95,7 +95,7 @@
     assert(objects != null);
     assert(eval != null);
     assert(libraries != null);
-    IsolateViewElement e = document.createElement(tag.name);
+    IsolateViewElement e = new IsolateViewElement.created();
     e._r = new RenderingScheduler<IsolateViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -110,7 +110,7 @@
     return e;
   }
 
-  IsolateViewElement.created() : super.created();
+  IsolateViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -139,23 +139,25 @@
     final List<M.Thread> threads = _isolate.threads;
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
-        new NavReloadElement(_isolate, _isolates, _events, queue: _r.queue)
-          ..onReload.listen((_) async {
-            _isolate = await _isolates.get(_isolate);
-            await _loadExtraData();
-            _r.dirty();
-          }),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _isolate = await _isolates.get(_isolate);
-            await _loadExtraData();
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        (new NavReloadElement(_isolate, _isolates, _events, queue: _r.queue)
+              ..onReload.listen((_) async {
+                _isolate = await _isolates.get(_isolate);
+                await _loadExtraData();
+                _r.dirty();
+              }))
+            .element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _isolate = await _isolates.get(_isolate);
+                await _loadExtraData();
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -168,10 +170,11 @@
               new DivElement()..style.flex = '1',
               new DivElement()
                 ..children = <Element>[
-                  new IsolateRunStateElement(_isolate, _events,
-                      queue: _r.queue),
+                  new IsolateRunStateElement(_isolate, _events, queue: _r.queue)
+                      .element,
                   new IsolateLocationElement(_isolate, _events, _scripts,
-                      queue: _r.queue),
+                          queue: _r.queue)
+                      .element,
                   new SpanElement()..text = ' [',
                   new AnchorElement(href: Uris.debugger(_isolate))
                     ..text = 'debug',
@@ -182,16 +185,20 @@
             ..children = _function != null
                 ? [
                     new BRElement(),
-                    new SourceInsetElement(_isolate, _function.location,
-                        _scripts, _objects, _events,
-                        currentPos:
-                            M.topFrame(isolate.pauseEvent).location.tokenPos,
-                        queue: _r.queue)
-                      ..classes = ['header_inset']
+                    (new SourceInsetElement(_isolate, _function.location,
+                            _scripts, _objects, _events,
+                            currentPos: M
+                                .topFrame(isolate.pauseEvent)
+                                .location
+                                .tokenPos,
+                            queue: _r.queue)
+                          ..classes = ['header_inset'])
+                        .element
                   ]
                 : const [],
           new HRElement(),
-          new IsolateSharedSummaryElement(_isolate, _events, queue: _r.queue),
+          new IsolateSharedSummaryElement(_isolate, _events, queue: _r.queue)
+              .element,
           new HRElement(),
           new DivElement()
             ..classes = ['memberList']
@@ -228,8 +235,9 @@
                       _isolate.rootLibrary == null
                           ? (new SpanElement()..text = 'loading...')
                           : new LibraryRefElement(
-                              _isolate, _isolate.rootLibrary,
-                              queue: _r.queue)
+                                  _isolate, _isolate.rootLibrary,
+                                  queue: _r.queue)
+                              .element
                     ]
                 ],
               new DivElement()
@@ -243,7 +251,8 @@
                           ..classes = ['memberValue']
                           ..children = <Element>[
                             new FunctionRefElement(_isolate, _isolate.entry,
-                                queue: _r.queue)
+                                    queue: _r.queue)
+                                .element
                           ]
                       ]
                     : const [],
@@ -323,14 +332,16 @@
                   new DivElement()
                     ..classes = ['memberValue']
                     ..children = <Element>[
-                      new CurlyBlockElement(queue: _r.queue)
-                        ..content = libraries
-                            .map<Element>((l) => new DivElement()
-                              ..children = <Element>[
-                                new LibraryRefElement(_isolate, l,
-                                    queue: _r.queue)
-                              ])
-                            .toList()
+                      (new CurlyBlockElement(queue: _r.queue)
+                            ..content = libraries
+                                .map<Element>((l) => new DivElement()
+                                  ..children = <Element>[
+                                    new LibraryRefElement(_isolate, l,
+                                            queue: _r.queue)
+                                        .element
+                                  ])
+                                .toList())
+                          .element
                     ]
                 ],
               new DivElement()
@@ -342,25 +353,29 @@
                   new DivElement()
                     ..classes = ['memberValue']
                     ..children = <Element>[
-                      new CurlyBlockElement(queue: _r.queue)
-                        ..content = threads.map<Element>(_populateThreadInfo)
+                      (new CurlyBlockElement(queue: _r.queue)
+                            ..content =
+                                threads.map<Element>(_populateThreadInfo))
+                          .element
                     ]
                 ]
             ],
           new HRElement(),
           new EvalBoxElement(_isolate, _isolate.rootLibrary, _objects, _eval,
-              queue: _r.queue),
+                  queue: _r.queue)
+              .element,
           new DivElement()
             ..children = _rootScript != null
                 ? [
                     new HRElement(),
                     new ScriptInsetElement(
-                        _isolate, _rootScript, _scripts, _objects, _events,
-                        queue: _r.queue)
+                            _isolate, _rootScript, _scripts, _objects, _events,
+                            queue: _r.queue)
+                        .element
                   ]
                 : const [],
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
@@ -370,22 +385,23 @@
       ..classes = ['indent']
       ..children = <Element>[
         new SpanElement()..text = '${t.id} ',
-        new CurlyBlockElement(queue: _r.queue)
-          ..content = <Element>[
-            new DivElement()
-              ..classes = ['indent']
-              ..text = 'kind ${t.kindString}',
-            new DivElement()
-              ..classes = ['indent']
-              ..title = '${t.zoneHighWatermark}B'
-              ..text = 'zone capacity high watermark '
-                  '${Utils.formatSize(t.zoneHighWatermark)}',
-            new DivElement()
-              ..classes = ['indent']
-              ..title = '${t.zoneCapacity}B'
-              ..text = 'current zone capacity ' +
-                  '${Utils.formatSize(t.zoneCapacity)}',
-          ]
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = <Element>[
+                new DivElement()
+                  ..classes = ['indent']
+                  ..text = 'kind ${t.kindString}',
+                new DivElement()
+                  ..classes = ['indent']
+                  ..title = '${t.zoneHighWatermark}B'
+                  ..text = 'zone capacity high watermark '
+                      '${Utils.formatSize(t.zoneHighWatermark)}',
+                new DivElement()
+                  ..classes = ['indent']
+                  ..title = '${t.zoneCapacity}B'
+                  ..text = 'current zone capacity ' +
+                      '${Utils.formatSize(t.zoneCapacity)}',
+              ])
+            .element
       ];
   }
 
diff --git a/runtime/observatory/lib/src/elements/json_view.dart b/runtime/observatory/lib/src/elements/json_view.dart
index 6b452ef..7f1474b 100644
--- a/runtime/observatory/lib/src/elements/json_view.dart
+++ b/runtime/observatory/lib/src/elements/json_view.dart
@@ -14,7 +14,7 @@
 import 'package:observatory/src/elements/nav/top_menu.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class JSONViewElement extends HtmlElement implements Renderable {
+class JSONViewElement extends CustomElement implements Renderable {
   static const tag = const Tag<JSONViewElement>('json-view',
       dependencies: const [
         NavTopMenuElement.tag,
@@ -36,14 +36,14 @@
       {RenderingQueue queue}) {
     assert(notifications != null);
     assert(map != null);
-    JSONViewElement e = document.createElement(tag.name);
+    JSONViewElement e = new JSONViewElement.created();
     e._r = new RenderingScheduler<JSONViewElement>(e, queue: queue);
     e._notifications = notifications;
     e._map = map;
     return e;
   }
 
-  JSONViewElement.created() : super.created();
+  JSONViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -61,8 +61,8 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -71,7 +71,7 @@
           new HRElement(),
           new PreElement()..text = JSONPretty.stringify(_map),
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/library_ref.dart b/runtime/observatory/lib/src/elements/library_ref.dart
index dcfe17a..a6d3ba8 100644
--- a/runtime/observatory/lib/src/elements/library_ref.dart
+++ b/runtime/observatory/lib/src/elements/library_ref.dart
@@ -11,7 +11,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class LibraryRefElement extends HtmlElement implements Renderable {
+class LibraryRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<LibraryRefElement>('library-ref');
 
   RenderingScheduler<LibraryRefElement> _r;
@@ -28,14 +28,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(library != null);
-    LibraryRefElement e = document.createElement(tag.name);
+    LibraryRefElement e = new LibraryRefElement.created();
     e._r = new RenderingScheduler<LibraryRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._library = library;
     return e;
   }
 
-  LibraryRefElement.created() : super.created();
+  LibraryRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/library_view.dart b/runtime/observatory/lib/src/elements/library_view.dart
index 2f9f2d4..c452e4d 100644
--- a/runtime/observatory/lib/src/elements/library_view.dart
+++ b/runtime/observatory/lib/src/elements/library_view.dart
@@ -28,7 +28,7 @@
 import 'package:observatory/src/elements/script_inset.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class LibraryViewElement extends HtmlElement implements Renderable {
+class LibraryViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<LibraryViewElement>('library-view', dependencies: const [
     ClassRefElement.tag,
@@ -104,7 +104,7 @@
     assert(scripts != null);
     assert(objects != null);
     assert(eval != null);
-    LibraryViewElement e = document.createElement(tag.name);
+    LibraryViewElement e = new LibraryViewElement.created();
     e._r = new RenderingScheduler<LibraryViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -123,7 +123,7 @@
     return e;
   }
 
-  LibraryViewElement.created() : super.created();
+  LibraryViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -142,16 +142,17 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
-        new NavLibraryMenuElement(_isolate, _library, queue: _r.queue),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _refresh();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        new NavLibraryMenuElement(_isolate, _library, queue: _r.queue).element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _refresh();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -159,8 +160,9 @@
           new HeadingElement.h2()..text = 'Library',
           new HRElement(),
           new ObjectCommonElement(_isolate, _library, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new DivElement()
             ..classes = ['memberList']
             ..children = <Element>[
@@ -187,7 +189,8 @@
             ],
           new HRElement(),
           new EvalBoxElement(_isolate, _library, _objects, _eval,
-              queue: _r.queue),
+                  queue: _r.queue)
+              .element,
           new HRElement(),
           _createDependencies(),
           new BRElement(),
@@ -200,10 +203,11 @@
           _createFunctions(),
           new HRElement(),
           new ScriptInsetElement(
-              _isolate, _library.rootScript, _scripts, _objects, _events,
-              queue: _r.queue),
+                  _isolate, _library.rootScript, _scripts, _objects, _events,
+                  queue: _r.queue)
+              .element,
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
@@ -225,18 +229,21 @@
     return new DivElement()
       ..children = <Element>[
         new SpanElement()..text = 'dependencies (${dependencies.length}) ',
-        new CurlyBlockElement(queue: _r.queue)
-          ..content = dependencies
-              .map<Element>((d) => new DivElement()
-                ..classes = ['indent']
-                ..children = <Element>[
-                  new SpanElement()..text = d.isImport ? 'import ' : 'export ',
-                  new LibraryRefElement(_isolate, d.target, queue: _r.queue),
-                  new SpanElement()
-                    ..text = d.prefix == null ? '' : ' as ${d.prefix}',
-                  new SpanElement()..text = d.isDeferred ? ' deferred' : '',
-                ])
-              .toList()
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = dependencies
+                  .map<Element>((d) => new DivElement()
+                    ..classes = ['indent']
+                    ..children = <Element>[
+                      new SpanElement()
+                        ..text = d.isImport ? 'import ' : 'export ',
+                      new LibraryRefElement(_isolate, d.target, queue: _r.queue)
+                          .element,
+                      new SpanElement()
+                        ..text = d.prefix == null ? '' : ' as ${d.prefix}',
+                      new SpanElement()..text = d.isDeferred ? ' deferred' : '',
+                    ])
+                  .toList())
+            .element
       ];
   }
 
@@ -248,14 +255,15 @@
     return new DivElement()
       ..children = <Element>[
         new SpanElement()..text = 'scripts (${scripts.length}) ',
-        new CurlyBlockElement(queue: _r.queue)
-          ..content = scripts
-              .map<Element>((s) => new DivElement()
-                ..classes = ['indent']
-                ..children = <Element>[
-                  new ScriptRefElement(_isolate, s, queue: _r.queue)
-                ])
-              .toList()
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = scripts
+                  .map<Element>((s) => new DivElement()
+                    ..classes = ['indent']
+                    ..children = <Element>[
+                      new ScriptRefElement(_isolate, s, queue: _r.queue).element
+                    ])
+                  .toList())
+            .element
       ];
   }
 
@@ -267,14 +275,15 @@
     return new DivElement()
       ..children = <Element>[
         new SpanElement()..text = 'classes (${classes.length}) ',
-        new CurlyBlockElement(queue: _r.queue)
-          ..content = classes
-              .map<Element>((c) => new DivElement()
-                ..classes = ['indent']
-                ..children = <Element>[
-                  new ClassRefElement(_isolate, c, queue: _r.queue)
-                ])
-              .toList()
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = classes
+                  .map<Element>((c) => new DivElement()
+                    ..classes = ['indent']
+                    ..children = <Element>[
+                      new ClassRefElement(_isolate, c, queue: _r.queue).element
+                    ])
+                  .toList())
+            .element
       ];
   }
 
@@ -286,32 +295,34 @@
     return new DivElement()
       ..children = <Element>[
         new SpanElement()..text = 'variables (${variables.length}) ',
-        new CurlyBlockElement(queue: _r.queue)
-          ..content = <Element>[
-            _variables == null
-                ? (new SpanElement()..text = 'loading...')
-                : (new DivElement()
-                  ..classes = ['indent', 'memberList']
-                  ..children = _variables
-                      .map<Element>((f) => new DivElement()
-                        ..classes = ['memberItem']
-                        ..children = <Element>[
-                          new DivElement()
-                            ..classes = ['memberName']
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = <Element>[
+                _variables == null
+                    ? (new SpanElement()..text = 'loading...')
+                    : (new DivElement()
+                      ..classes = ['indent', 'memberList']
+                      ..children = _variables
+                          .map<Element>((f) => new DivElement()
+                            ..classes = ['memberItem']
                             ..children = <Element>[
-                              new FieldRefElement(_isolate, f, _objects,
-                                  queue: _r.queue)
-                            ],
-                          new DivElement()
-                            ..classes = ['memberValue']
-                            ..children = <Element>[
-                              new SpanElement()..text = ' = ',
-                              anyRef(_isolate, f.staticValue, _objects,
-                                  queue: _r.queue)
-                            ]
-                        ])
-                      .toList())
-          ]
+                              new DivElement()
+                                ..classes = ['memberName']
+                                ..children = <Element>[
+                                  new FieldRefElement(_isolate, f, _objects,
+                                          queue: _r.queue)
+                                      .element
+                                ],
+                              new DivElement()
+                                ..classes = ['memberValue']
+                                ..children = <Element>[
+                                  new SpanElement()..text = ' = ',
+                                  anyRef(_isolate, f.staticValue, _objects,
+                                      queue: _r.queue)
+                                ]
+                            ])
+                          .toList())
+              ])
+            .element
       ];
   }
 
@@ -323,14 +334,16 @@
     return new DivElement()
       ..children = <Element>[
         new SpanElement()..text = 'functions (${functions.length}) ',
-        new CurlyBlockElement(queue: _r.queue)
-          ..content = functions
-              .map<Element>((f) => new DivElement()
-                ..classes = ['indent']
-                ..children = <Element>[
-                  new FunctionRefElement(_isolate, f, queue: _r.queue)
-                ])
-              .toList()
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = functions
+                  .map<Element>((f) => new DivElement()
+                    ..classes = ['indent']
+                    ..children = <Element>[
+                      new FunctionRefElement(_isolate, f, queue: _r.queue)
+                          .element
+                    ])
+                  .toList())
+            .element
       ];
   }
 }
diff --git a/runtime/observatory/lib/src/elements/local_var_descriptors_ref.dart b/runtime/observatory/lib/src/elements/local_var_descriptors_ref.dart
index 578a148..e5afd63 100644
--- a/runtime/observatory/lib/src/elements/local_var_descriptors_ref.dart
+++ b/runtime/observatory/lib/src/elements/local_var_descriptors_ref.dart
@@ -10,7 +10,8 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class LocalVarDescriptorsRefElement extends HtmlElement implements Renderable {
+class LocalVarDescriptorsRefElement extends CustomElement
+    implements Renderable {
   static const tag = const Tag<LocalVarDescriptorsRefElement>('var-ref');
 
   RenderingScheduler<LocalVarDescriptorsRefElement> _r;
@@ -29,7 +30,8 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(localVar != null);
-    LocalVarDescriptorsRefElement e = document.createElement(tag.name);
+    LocalVarDescriptorsRefElement e =
+        new LocalVarDescriptorsRefElement.created();
     e._r =
         new RenderingScheduler<LocalVarDescriptorsRefElement>(e, queue: queue);
     e._isolate = isolate;
@@ -37,7 +39,7 @@
     return e;
   }
 
-  LocalVarDescriptorsRefElement.created() : super.created();
+  LocalVarDescriptorsRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/logging.dart b/runtime/observatory/lib/src/elements/logging.dart
index 8e168fa..5237010 100644
--- a/runtime/observatory/lib/src/elements/logging.dart
+++ b/runtime/observatory/lib/src/elements/logging.dart
@@ -21,7 +21,7 @@
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class LoggingPageElement extends HtmlElement implements Renderable {
+class LoggingPageElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<LoggingPageElement>('logging-page', dependencies: const [
     LoggingListElement.tag,
@@ -55,7 +55,7 @@
     assert(isolate != null);
     assert(events != null);
     assert(notifications != null);
-    LoggingPageElement e = document.createElement(tag.name);
+    LoggingPageElement e = new LoggingPageElement.created();
     e._r = new RenderingScheduler<LoggingPageElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -64,7 +64,7 @@
     return e;
   }
 
-  LoggingPageElement.created() : super.created();
+  LoggingPageElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -86,17 +86,18 @@
     _logs.level = _level;
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('logging'),
-        new NavRefreshElement(label: 'clear', queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _logs = null;
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(label: 'clear', queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _logs = null;
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -105,7 +106,7 @@
           new SpanElement()..text = 'Show messages with severity ',
           _createLevelSelector(),
           new HRElement(),
-          _logs
+          _logs.element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/logging_list.dart b/runtime/observatory/lib/src/elements/logging_list.dart
index ac9c728..4f935ee 100644
--- a/runtime/observatory/lib/src/elements/logging_list.dart
+++ b/runtime/observatory/lib/src/elements/logging_list.dart
@@ -10,7 +10,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/utils.dart';
 
-class LoggingListElement extends HtmlElement implements Renderable {
+class LoggingListElement extends CustomElement implements Renderable {
   static const tag = const Tag<LoggingListElement>('logging-list');
 
   RenderingScheduler<LoggingListElement> _r;
@@ -32,14 +32,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(events != null);
-    LoggingListElement e = document.createElement(tag.name);
+    LoggingListElement e = new LoggingListElement.created();
     e._r = new RenderingScheduler<LoggingListElement>(e, queue: queue);
     e._isolate = isolate;
     e._events = events;
     return e;
   }
 
-  LoggingListElement.created() : super.created();
+  LoggingListElement.created() : super.created(tag);
 
   @override
   attached() {
diff --git a/runtime/observatory/lib/src/elements/megamorphiccache_ref.dart b/runtime/observatory/lib/src/elements/megamorphiccache_ref.dart
index b7eb6c2..d93696e 100644
--- a/runtime/observatory/lib/src/elements/megamorphiccache_ref.dart
+++ b/runtime/observatory/lib/src/elements/megamorphiccache_ref.dart
@@ -10,7 +10,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class MegamorphicCacheRefElement extends HtmlElement implements Renderable {
+class MegamorphicCacheRefElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<MegamorphicCacheRefElement>('megamorphic-cache-ref');
 
@@ -30,14 +30,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(cache != null);
-    MegamorphicCacheRefElement e = document.createElement(tag.name);
+    MegamorphicCacheRefElement e = new MegamorphicCacheRefElement.created();
     e._r = new RenderingScheduler<MegamorphicCacheRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._cache = cache;
     return e;
   }
 
-  MegamorphicCacheRefElement.created() : super.created();
+  MegamorphicCacheRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/megamorphiccache_view.dart b/runtime/observatory/lib/src/elements/megamorphiccache_view.dart
index 5a35092..698ea59 100644
--- a/runtime/observatory/lib/src/elements/megamorphiccache_view.dart
+++ b/runtime/observatory/lib/src/elements/megamorphiccache_view.dart
@@ -22,7 +22,7 @@
 import 'package:observatory/src/elements/object_common.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class MegamorphicCacheViewElement extends HtmlElement implements Renderable {
+class MegamorphicCacheViewElement extends CustomElement implements Renderable {
   static const tag = const Tag<MegamorphicCacheViewElement>(
       'megamorphiccache-view',
       dependencies: const [
@@ -83,7 +83,7 @@
     assert(references != null);
     assert(retainingPaths != null);
     assert(objects != null);
-    MegamorphicCacheViewElement e = document.createElement(tag.name);
+    MegamorphicCacheViewElement e = new MegamorphicCacheViewElement.created();
     e._r = new RenderingScheduler<MegamorphicCacheViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -99,7 +99,7 @@
     return e;
   }
 
-  MegamorphicCacheViewElement.created() : super.created();
+  MegamorphicCacheViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -117,17 +117,18 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('megamorphic inline cache'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _cache = await _caches.get(_isolate, _cache.id);
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _cache = await _caches.get(_isolate, _cache.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -135,8 +136,9 @@
           new HeadingElement.h2()..text = 'Megamorphic Cache',
           new HRElement(),
           new ObjectCommonElement(_isolate, _cache, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new BRElement(),
           new DivElement()
             ..classes = ['memberList']
@@ -189,7 +191,7 @@
                 ]
             ],
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/memory/allocations.dart b/runtime/observatory/lib/src/elements/memory/allocations.dart
index 1d8c4ba..11ff282 100644
--- a/runtime/observatory/lib/src/elements/memory/allocations.dart
+++ b/runtime/observatory/lib/src/elements/memory/allocations.dart
@@ -30,7 +30,7 @@
 
 enum _SortingDirection { ascending, descending }
 
-class MemoryAllocationsElement extends HtmlElement implements Renderable {
+class MemoryAllocationsElement extends CustomElement implements Renderable {
   static const tag = const Tag<MemoryAllocationsElement>('memory-allocations',
       dependencies: const [ClassRefElement.tag, VirtualCollectionElement.tag]);
 
@@ -54,7 +54,7 @@
     assert(isolate != null);
     assert(editor != null);
     assert(repository != null);
-    MemoryAllocationsElement e = document.createElement(tag.name);
+    MemoryAllocationsElement e = new MemoryAllocationsElement.created();
     e._r = new RenderingScheduler<MemoryAllocationsElement>(e, queue: queue);
     e._isolate = isolate;
     e._editor = editor;
@@ -62,7 +62,7 @@
     return e;
   }
 
-  MemoryAllocationsElement.created() : super.created();
+  MemoryAllocationsElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -92,18 +92,19 @@
     } else {
       children = <Element>[
         new VirtualCollectionElement(
-            _createCollectionLine, _updateCollectionLine,
-            createHeader: _createCollectionHeader,
-            search: _search,
-            items: _profile.members
-                .where((member) =>
-                    member.newSpace.accumulated.instances != 0 ||
-                    member.newSpace.current.instances != 0 ||
-                    member.oldSpace.accumulated.instances != 0 ||
-                    member.oldSpace.current.instances != 0)
-                .toList()
-                  ..sort(_createSorter()),
-            queue: _r.queue)
+                _createCollectionLine, _updateCollectionLine,
+                createHeader: _createCollectionHeader,
+                search: _search,
+                items: _profile.members
+                    .where((member) =>
+                        member.newSpace.accumulated.instances != 0 ||
+                        member.newSpace.current.instances != 0 ||
+                        member.oldSpace.accumulated.instances != 0 ||
+                        member.oldSpace.current.instances != 0)
+                    .toList()
+                      ..sort(_createSorter()),
+                queue: _r.queue)
+            .element
       ];
     }
   }
@@ -239,8 +240,9 @@
         ..classes = ['name'];
       return;
     }
-    e.children[4] = new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
-      ..classes = ['name'];
+    e.children[4] = (new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
+          ..classes = ['name'])
+        .element;
     Element.clickEvent.forTarget(e.children[4], useCapture: true).listen((e) {
       if (_editor.isAvailable) {
         e.preventDefault();
diff --git a/runtime/observatory/lib/src/elements/memory/dashboard.dart b/runtime/observatory/lib/src/elements/memory/dashboard.dart
index 802bed5..c0af46d 100644
--- a/runtime/observatory/lib/src/elements/memory/dashboard.dart
+++ b/runtime/observatory/lib/src/elements/memory/dashboard.dart
@@ -28,7 +28,7 @@
 import 'package:observatory/src/elements/memory/graph.dart';
 import 'package:observatory/src/elements/memory/profile.dart';
 
-class MemoryDashboardElement extends HtmlElement implements Renderable {
+class MemoryDashboardElement extends CustomElement implements Renderable {
   static const tag = const Tag<MemoryDashboardElement>('memory-dashboard',
       dependencies: const [
         NavNotifyElement.tag,
@@ -71,7 +71,7 @@
     assert(allocations != null);
     assert(events != null);
     assert(notifications != null);
-    MemoryDashboardElement e = document.createElement(tag.name);
+    MemoryDashboardElement e = new MemoryDashboardElement.created();
     e._r = new RenderingScheduler<MemoryDashboardElement>(e, queue: queue);
     e._vm = vm;
     e._vms = vms;
@@ -85,7 +85,7 @@
     return e;
   }
 
-  MemoryDashboardElement.created() : super.created();
+  MemoryDashboardElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -111,13 +111,15 @@
             ..onIsolateSelected.listen(_onIsolateSelected);
     }
     children = <Element>[
-      navBar(<Element>[new NavNotifyElement(_notifications, queue: _r.queue)]),
+      navBar(<Element>[
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
       new DivElement()
         ..classes = ['content-centered-big']
         ..children = <Element>[
           new HeadingElement.h2()..text = 'Memory Dashboard',
           new HRElement(),
-          _graph,
+          _graph.element,
           new HRElement(),
         ],
     ];
@@ -129,7 +131,8 @@
         ]);
     } else {
       children.add(new MemoryProfileElement(
-          _isolate, _editor, _allocations, _snapshots, _objects));
+              _isolate, _editor, _allocations, _snapshots, _objects)
+          .element);
     }
   }
 
diff --git a/runtime/observatory/lib/src/elements/memory/graph.dart b/runtime/observatory/lib/src/elements/memory/graph.dart
index 30b18ac..5f0fd9d 100644
--- a/runtime/observatory/lib/src/elements/memory/graph.dart
+++ b/runtime/observatory/lib/src/elements/memory/graph.dart
@@ -29,7 +29,7 @@
   const IsolateSelectedEvent([this.isolate]);
 }
 
-class MemoryGraphElement extends HtmlElement implements Renderable {
+class MemoryGraphElement extends CustomElement implements Renderable {
   static const tag = const Tag<MemoryGraphElement>('memory-graph');
 
   RenderingScheduler<MemoryGraphElement> _r;
@@ -59,7 +59,7 @@
     assert(vms != null);
     assert(isolates != null);
     assert(events != null);
-    MemoryGraphElement e = document.createElement(tag.name);
+    MemoryGraphElement e = new MemoryGraphElement.created();
     e._r = new RenderingScheduler<MemoryGraphElement>(e, queue: queue);
     e._vm = vm;
     e._vms = vms;
@@ -68,7 +68,7 @@
     return e;
   }
 
-  MemoryGraphElement.created() : super.created() {
+  MemoryGraphElement.created() : super.created(tag) {
     final now = new DateTime.now();
     var sample = now.subtract(_window);
     while (sample.isBefore(now)) {
@@ -455,7 +455,7 @@
 
   StyleElement get style => new StyleElement()
     ..text = '''
-memory-graph svg .stacked-line-rdr-line:nth-child(2n+${_offset+1})
+memory-graph svg .stacked-line-rdr-line:nth-child(2n+${_offset + 1})
   path:nth-child(1) {
   filter: url(#stroke-grid);
 }''';
diff --git a/runtime/observatory/lib/src/elements/memory/profile.dart b/runtime/observatory/lib/src/elements/memory/profile.dart
index 2c72042..7d86456 100644
--- a/runtime/observatory/lib/src/elements/memory/profile.dart
+++ b/runtime/observatory/lib/src/elements/memory/profile.dart
@@ -23,7 +23,7 @@
 
 enum _Analysis { allocations, dominatorTree }
 
-class MemoryProfileElement extends HtmlElement implements Renderable {
+class MemoryProfileElement extends CustomElement implements Renderable {
   static const tag = const Tag<MemoryProfileElement>('memory-profile',
       dependencies: const [
         MemoryAllocationsElement.tag,
@@ -56,7 +56,7 @@
     assert(allocations != null);
     assert(snapshots != null);
     assert(objects != null);
-    MemoryProfileElement e = document.createElement(tag.name);
+    MemoryProfileElement e = new MemoryProfileElement.created();
     e._r = new RenderingScheduler<MemoryProfileElement>(e, queue: queue);
     e._isolate = isolate;
     e._editor = editor;
@@ -66,7 +66,7 @@
     return e;
   }
 
-  MemoryProfileElement.created() : super.created();
+  MemoryProfileElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -88,13 +88,13 @@
       case _Analysis.allocations:
         final MemoryAllocationsElement allocations =
             new MemoryAllocationsElement(_isolate, _editor, _allocations);
-        current = allocations;
+        current = allocations.element;
         reload = ({bool gc: false}) => allocations.reload(gc: gc);
         break;
       case _Analysis.dominatorTree:
         final MemorySnapshotElement snapshot =
             new MemorySnapshotElement(_isolate, _editor, _snapshots, _objects);
-        current = snapshot;
+        current = snapshot.element;
         reload = ({bool gc: false}) => snapshot.reload(gc: gc);
         break;
     }
diff --git a/runtime/observatory/lib/src/elements/memory/snapshot.dart b/runtime/observatory/lib/src/elements/memory/snapshot.dart
index 816a772..b518e96 100644
--- a/runtime/observatory/lib/src/elements/memory/snapshot.dart
+++ b/runtime/observatory/lib/src/elements/memory/snapshot.dart
@@ -14,7 +14,7 @@
 import 'package:observatory/src/elements/helpers/uris.dart';
 import 'package:observatory/utils.dart';
 
-class MemorySnapshotElement extends HtmlElement implements Renderable {
+class MemorySnapshotElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<MemorySnapshotElement>('memory-snapshot', dependencies: const [
     ClassRefElement.tag,
@@ -42,7 +42,7 @@
     assert(editor != null);
     assert(snapshots != null);
     assert(objects != null);
-    MemorySnapshotElement e = document.createElement(tag.name);
+    MemorySnapshotElement e = new MemorySnapshotElement.created();
     e._r = new RenderingScheduler<MemorySnapshotElement>(e, queue: queue);
     e._isolate = isolate;
     e._editor = editor;
@@ -51,7 +51,7 @@
     return e;
   }
 
-  MemorySnapshotElement.created() : super.created();
+  MemorySnapshotElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -161,7 +161,7 @@
         ..classes = ['content-centered-big', 'explanation']
         ..text = text
         ..title = text,
-      _tree
+      _tree.element
     ];
   }
 
diff --git a/runtime/observatory/lib/src/elements/metric/details.dart b/runtime/observatory/lib/src/elements/metric/details.dart
index 458d12b..72d218e 100644
--- a/runtime/observatory/lib/src/elements/metric/details.dart
+++ b/runtime/observatory/lib/src/elements/metric/details.dart
@@ -8,7 +8,7 @@
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 import 'package:observatory/src/elements/helpers/tag.dart';
 
-class MetricDetailsElement extends HtmlElement implements Renderable {
+class MetricDetailsElement extends CustomElement implements Renderable {
   static const tag = const Tag<MetricDetailsElement>('metric-details');
 
   RenderingScheduler<MetricDetailsElement> _r;
@@ -28,7 +28,7 @@
     assert(isolate != null);
     assert(metric != null);
     assert(metrics != null);
-    MetricDetailsElement e = document.createElement(tag.name);
+    MetricDetailsElement e = new MetricDetailsElement.created();
     e._r = new RenderingScheduler<MetricDetailsElement>(e, queue: queue);
     e._isolate = isolate;
     e._metric = metric;
@@ -36,7 +36,7 @@
     return e;
   }
 
-  MetricDetailsElement.created() : super.created();
+  MetricDetailsElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/metric/graph.dart b/runtime/observatory/lib/src/elements/metric/graph.dart
index 608a936..24406a2 100644
--- a/runtime/observatory/lib/src/elements/metric/graph.dart
+++ b/runtime/observatory/lib/src/elements/metric/graph.dart
@@ -9,7 +9,7 @@
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 import 'package:observatory/src/elements/helpers/tag.dart';
 
-class MetricGraphElement extends HtmlElement implements Renderable {
+class MetricGraphElement extends CustomElement implements Renderable {
   static const tag = const Tag<MetricGraphElement>('metric-graph');
 
   RenderingScheduler<MetricGraphElement> _r;
@@ -30,7 +30,7 @@
     assert(isolate != null);
     assert(metric != null);
     assert(metrics != null);
-    MetricGraphElement e = document.createElement(tag.name);
+    MetricGraphElement e = new MetricGraphElement.created();
     e._r = new RenderingScheduler<MetricGraphElement>(e, queue: queue);
     e._isolate = isolate;
     e._metric = metric;
@@ -38,7 +38,7 @@
     return e;
   }
 
-  MetricGraphElement.created() : super.created();
+  MetricGraphElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/metrics.dart b/runtime/observatory/lib/src/elements/metrics.dart
index ce8b91a..50e2da0 100644
--- a/runtime/observatory/lib/src/elements/metrics.dart
+++ b/runtime/observatory/lib/src/elements/metrics.dart
@@ -19,7 +19,7 @@
 import 'package:observatory/src/elements/nav/top_menu.dart';
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 
-class MetricsPageElement extends HtmlElement implements Renderable {
+class MetricsPageElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<MetricsPageElement>('metrics-page', dependencies: const [
     MetricDetailsElement.tag,
@@ -58,7 +58,7 @@
     assert(isolate != null);
     assert(events != null);
     assert(notifications != null);
-    MetricsPageElement e = document.createElement(tag.name);
+    MetricsPageElement e = new MetricsPageElement.created();
     e._r = new RenderingScheduler<MetricsPageElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -68,7 +68,7 @@
     return e;
   }
 
-  MetricsPageElement.created() : super.created();
+  MetricsPageElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -87,16 +87,17 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('metrics'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) {
-            e.element.disabled = true;
-            _refresh();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) {
+                e.element.disabled = true;
+                _refresh();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -125,7 +126,8 @@
                 ? const []
                 : [
                     new MetricDetailsElement(_isolate, _selected, _metrics,
-                        queue: _r.queue)
+                            queue: _r.queue)
+                        .element
                   ],
           new HRElement(),
           new DivElement()
@@ -134,7 +136,8 @@
                 ? const []
                 : [
                     new MetricGraphElement(_isolate, _selected, _metrics,
-                        queue: _r.queue)
+                            queue: _r.queue)
+                        .element
                   ]
         ],
     ];
diff --git a/runtime/observatory/lib/src/elements/native_memory_profiler.dart b/runtime/observatory/lib/src/elements/native_memory_profiler.dart
index b32f2d2..8936b31 100644
--- a/runtime/observatory/lib/src/elements/native_memory_profiler.dart
+++ b/runtime/observatory/lib/src/elements/native_memory_profiler.dart
@@ -20,7 +20,7 @@
 import 'package:observatory/src/elements/sample_buffer_control.dart';
 import 'package:observatory/src/elements/stack_trace_tree_config.dart';
 
-class NativeMemoryProfileElement extends HtmlElement implements Renderable {
+class NativeMemoryProfileElement extends CustomElement implements Renderable {
   static const tag = const Tag<NativeMemoryProfileElement>(
       'native-memory-profile',
       dependencies: const [
@@ -62,7 +62,7 @@
     assert(events != null);
     assert(notifications != null);
     assert(profiles != null);
-    NativeMemoryProfileElement e = document.createElement(tag.name);
+    NativeMemoryProfileElement e = new NativeMemoryProfileElement.created();
     e._r = new RenderingScheduler<NativeMemoryProfileElement>(e, queue: queue);
     e._vm = vm;
     e._events = events;
@@ -71,7 +71,7 @@
     return e;
   }
 
-  NativeMemoryProfileElement.created() : super.created();
+  NativeMemoryProfileElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -90,51 +90,55 @@
   void render() {
     var content = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
         navMenu('native memory profile', link: Uris.nativeMemory()),
-        new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
     ];
     if (_progress == null) {
       children = content;
       return;
     }
-    content.add(new SampleBufferControlElement(_vm, _progress, _progressStream,
-        selectedTag: _tag, queue: _r.queue)
-      ..onTagChange.listen((e) {
-        _tag = e.element.selectedTag;
-        _request(forceFetch: true);
-      }));
+    content.add((new SampleBufferControlElement(_vm, _progress, _progressStream,
+            selectedTag: _tag, queue: _r.queue)
+          ..onTagChange.listen((e) {
+            _tag = e.element.selectedTag;
+            _request(forceFetch: true);
+          }))
+        .element);
     if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
       CpuProfileVirtualTreeElement tree;
       content.addAll([
         new BRElement(),
-        new StackTraceTreeConfigElement(
-            mode: _mode,
-            direction: _direction,
-            filter: _filter,
-            queue: _r.queue)
-          ..onModeChange.listen((e) {
-            _mode = tree.mode = e.element.mode;
-          })
-          ..onFilterChange.listen((e) {
-            _filter = e.element.filter.trim();
-            tree.filters = _filter.isNotEmpty
-                ? [
-                    (node) {
-                      return node.name.contains(_filter);
-                    }
-                  ]
-                : const [];
-          })
-          ..onDirectionChange.listen((e) {
-            _direction = tree.direction = e.element.direction;
-          }),
+        (new StackTraceTreeConfigElement(
+                mode: _mode,
+                direction: _direction,
+                filter: _filter,
+                queue: _r.queue)
+              ..onModeChange.listen((e) {
+                _mode = tree.mode = e.element.mode;
+              })
+              ..onFilterChange.listen((e) {
+                _filter = e.element.filter.trim();
+                tree.filters = _filter.isNotEmpty
+                    ? [
+                        (node) {
+                          return node.name.contains(_filter);
+                        }
+                      ]
+                    : const [];
+              })
+              ..onDirectionChange.listen((e) {
+                _direction = tree.direction = e.element.direction;
+              }))
+            .element,
         new BRElement(),
-        tree = new CpuProfileVirtualTreeElement(null, _progress.profile,
-            queue: _r.queue, type: M.SampleProfileType.memory)
+        (tree = new CpuProfileVirtualTreeElement(null, _progress.profile,
+                queue: _r.queue, type: M.SampleProfileType.memory))
+            .element,
       ]);
     }
     children = content;
diff --git a/runtime/observatory/lib/src/elements/nav/class_menu.dart b/runtime/observatory/lib/src/elements/nav/class_menu.dart
index 3844443..c388eb3 100644
--- a/runtime/observatory/lib/src/elements/nav/class_menu.dart
+++ b/runtime/observatory/lib/src/elements/nav/class_menu.dart
@@ -10,7 +10,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class NavClassMenuElement extends HtmlElement implements Renderable {
+class NavClassMenuElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavClassMenuElement>('nav-class-menu');
 
   RenderingScheduler _r;
@@ -34,14 +34,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(cls != null);
-    NavClassMenuElement e = document.createElement(tag.name);
+    NavClassMenuElement e = new NavClassMenuElement.created();
     e._r = new RenderingScheduler<NavClassMenuElement>(e, queue: queue);
     e._isolate = isolate;
     e._cls = cls;
     return e;
   }
 
-  NavClassMenuElement.created() : super.created();
+  NavClassMenuElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/nav/isolate_menu.dart b/runtime/observatory/lib/src/elements/nav/isolate_menu.dart
index 5a1cfed..9b94daf 100644
--- a/runtime/observatory/lib/src/elements/nav/isolate_menu.dart
+++ b/runtime/observatory/lib/src/elements/nav/isolate_menu.dart
@@ -11,7 +11,7 @@
 import 'package:observatory/src/elements/helpers/uris.dart';
 import 'package:observatory/src/elements/nav/menu_item.dart';
 
-class NavIsolateMenuElement extends HtmlElement implements Renderable {
+class NavIsolateMenuElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavIsolateMenuElement>('nav-isolate-menu',
       dependencies: const [NavMenuItemElement.tag]);
 
@@ -36,14 +36,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(events != null);
-    NavIsolateMenuElement e = document.createElement(tag.name);
+    NavIsolateMenuElement e = new NavIsolateMenuElement.created();
     e._r = new RenderingScheduler<NavIsolateMenuElement>(e, queue: queue);
     e._isolate = isolate;
     e._events = events;
     return e;
   }
 
-  NavIsolateMenuElement.created() : super.created();
+  NavIsolateMenuElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -70,27 +70,38 @@
   void render() {
     final content = <Element>[
       new NavMenuItemElement('debugger',
-          queue: _r.queue, link: Uris.debugger(isolate)),
+              queue: _r.queue, link: Uris.debugger(isolate))
+          .element,
       new NavMenuItemElement('class hierarchy',
-          queue: _r.queue, link: Uris.classTree(isolate)),
+              queue: _r.queue, link: Uris.classTree(isolate))
+          .element,
       new NavMenuItemElement('cpu profile',
-          queue: _r.queue, link: Uris.cpuProfiler(isolate)),
+              queue: _r.queue, link: Uris.cpuProfiler(isolate))
+          .element,
       new NavMenuItemElement('cpu profile (table)',
-          queue: _r.queue, link: Uris.cpuProfilerTable(isolate)),
+              queue: _r.queue, link: Uris.cpuProfilerTable(isolate))
+          .element,
       new NavMenuItemElement('allocation profile',
-          queue: _r.queue, link: Uris.allocationProfiler(isolate)),
+              queue: _r.queue, link: Uris.allocationProfiler(isolate))
+          .element,
       new NavMenuItemElement('heap snapshot',
-          queue: _r.queue, link: Uris.heapSnapshot(isolate)),
+              queue: _r.queue, link: Uris.heapSnapshot(isolate))
+          .element,
       new NavMenuItemElement('heap map',
-          queue: _r.queue, link: Uris.heapMap(isolate)),
+              queue: _r.queue, link: Uris.heapMap(isolate))
+          .element,
       new NavMenuItemElement('metrics',
-          queue: _r.queue, link: Uris.metrics(isolate)),
+              queue: _r.queue, link: Uris.metrics(isolate))
+          .element,
       new NavMenuItemElement('persistent handles',
-          queue: _r.queue, link: Uris.persistentHandles(isolate)),
+              queue: _r.queue, link: Uris.persistentHandles(isolate))
+          .element,
       new NavMenuItemElement('ports',
-          queue: _r.queue, link: Uris.ports(isolate)),
+              queue: _r.queue, link: Uris.ports(isolate))
+          .element,
       new NavMenuItemElement('logging',
-          queue: _r.queue, link: Uris.logging(isolate)),
+              queue: _r.queue, link: Uris.logging(isolate))
+          .element,
     ]..addAll(_content);
     children = <Element>[
       navMenu(isolate.name, content: content, link: Uris.inspect(isolate))
diff --git a/runtime/observatory/lib/src/elements/nav/library_menu.dart b/runtime/observatory/lib/src/elements/nav/library_menu.dart
index 8750d5e..2ef6f15 100644
--- a/runtime/observatory/lib/src/elements/nav/library_menu.dart
+++ b/runtime/observatory/lib/src/elements/nav/library_menu.dart
@@ -10,7 +10,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class NavLibraryMenuElement extends HtmlElement implements Renderable {
+class NavLibraryMenuElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavLibraryMenuElement>('nav-library-menu');
 
   RenderingScheduler _r;
@@ -34,14 +34,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(library != null);
-    NavLibraryMenuElement e = document.createElement(tag.name);
+    NavLibraryMenuElement e = new NavLibraryMenuElement.created();
     e._r = new RenderingScheduler<NavLibraryMenuElement>(e, queue: queue);
     e._isolate = isolate;
     e._library = library;
     return e;
   }
 
-  NavLibraryMenuElement.created() : super.created();
+  NavLibraryMenuElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/nav/menu_item.dart b/runtime/observatory/lib/src/elements/nav/menu_item.dart
index b196b4f..5df68a9 100644
--- a/runtime/observatory/lib/src/elements/nav/menu_item.dart
+++ b/runtime/observatory/lib/src/elements/nav/menu_item.dart
@@ -7,7 +7,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 
-class NavMenuItemElement extends HtmlElement implements Renderable {
+class NavMenuItemElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavMenuItemElement>('nav-menu-item');
 
   RenderingScheduler _r;
@@ -32,14 +32,14 @@
   factory NavMenuItemElement(String label,
       {String link, RenderingQueue queue}) {
     assert(label != null);
-    NavMenuItemElement e = document.createElement(tag.name);
+    NavMenuItemElement e = new NavMenuItemElement.created();
     e._r = new RenderingScheduler<NavMenuItemElement>(e, queue: queue);
     e._label = label;
     e._link = link;
     return e;
   }
 
-  NavMenuItemElement.created() : super.created();
+  NavMenuItemElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/nav/notify.dart b/runtime/observatory/lib/src/elements/nav/notify.dart
index 6b22f32..a33d800 100644
--- a/runtime/observatory/lib/src/elements/nav/notify.dart
+++ b/runtime/observatory/lib/src/elements/nav/notify.dart
@@ -10,7 +10,7 @@
 import 'package:observatory/src/elements/nav/notify_event.dart';
 import 'package:observatory/src/elements/nav/notify_exception.dart';
 
-class NavNotifyElement extends HtmlElement implements Renderable {
+class NavNotifyElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavNotifyElement>('nav-notify',
       dependencies: const [
         NavNotifyEventElement.tag,
@@ -35,14 +35,14 @@
       {bool notifyOnPause: true, RenderingQueue queue}) {
     assert(repository != null);
     assert(notifyOnPause != null);
-    NavNotifyElement e = document.createElement(tag.name);
+    NavNotifyElement e = new NavNotifyElement.created();
     e._r = new RenderingScheduler<NavNotifyElement>(e, queue: queue);
     e._repository = repository;
     e._notifyOnPause = notifyOnPause;
     return e;
   }
 
-  NavNotifyElement.created() : super.created();
+  NavNotifyElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -82,12 +82,14 @@
 
   Element _toElement(M.Notification notification) {
     if (notification is M.EventNotification) {
-      return new NavNotifyEventElement(notification.event, queue: _r.queue)
-        ..onDelete.listen((_) => _repository.delete(notification));
+      return (new NavNotifyEventElement(notification.event, queue: _r.queue)
+            ..onDelete.listen((_) => _repository.delete(notification)))
+          .element;
     } else if (notification is M.ExceptionNotification) {
-      return new NavNotifyExceptionElement(notification.exception,
-          stacktrace: notification.stacktrace, queue: _r.queue)
-        ..onDelete.listen((_) => _repository.delete(notification));
+      return (new NavNotifyExceptionElement(notification.exception,
+              stacktrace: notification.stacktrace, queue: _r.queue)
+            ..onDelete.listen((_) => _repository.delete(notification)))
+          .element;
     } 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
index a75e723..fc9defc 100644
--- a/runtime/observatory/lib/src/elements/nav/notify_event.dart
+++ b/runtime/observatory/lib/src/elements/nav/notify_event.dart
@@ -14,7 +14,7 @@
   EventDeleteEvent(this.event);
 }
 
-class NavNotifyEventElement extends HtmlElement implements Renderable {
+class NavNotifyEventElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavNotifyEventElement>('nav-event');
 
   RenderingScheduler _r;
@@ -31,13 +31,13 @@
 
   factory NavNotifyEventElement(M.Event event, {RenderingQueue queue}) {
     assert(event != null);
-    NavNotifyEventElement e = document.createElement(tag.name);
+    NavNotifyEventElement e = new NavNotifyEventElement.created();
     e._r = new RenderingScheduler<NavNotifyEventElement>(e, queue: queue);
     e._event = event;
     return e;
   }
 
-  NavNotifyEventElement.created() : super.created();
+  NavNotifyEventElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/nav/notify_exception.dart b/runtime/observatory/lib/src/elements/nav/notify_exception.dart
index 3c84af7..9a746f0 100644
--- a/runtime/observatory/lib/src/elements/nav/notify_exception.dart
+++ b/runtime/observatory/lib/src/elements/nav/notify_exception.dart
@@ -16,7 +16,7 @@
   ExceptionDeleteEvent(this.exception, {this.stacktrace});
 }
 
-class NavNotifyExceptionElement extends HtmlElement implements Renderable {
+class NavNotifyExceptionElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavNotifyExceptionElement>('nav-exception');
 
   RenderingScheduler _r;
@@ -37,14 +37,14 @@
   factory NavNotifyExceptionElement(dynamic exception,
       {StackTrace stacktrace: null, RenderingQueue queue}) {
     assert(exception != null);
-    NavNotifyExceptionElement e = document.createElement(tag.name);
+    NavNotifyExceptionElement e = new NavNotifyExceptionElement.created();
     e._r = new RenderingScheduler<NavNotifyExceptionElement>(e, queue: queue);
     e._exception = exception;
     e._stacktrace = stacktrace;
     return e;
   }
 
-  NavNotifyExceptionElement.created() : super.created();
+  NavNotifyExceptionElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/nav/refresh.dart b/runtime/observatory/lib/src/elements/nav/refresh.dart
index da859a5..1d918fb 100644
--- a/runtime/observatory/lib/src/elements/nav/refresh.dart
+++ b/runtime/observatory/lib/src/elements/nav/refresh.dart
@@ -12,7 +12,7 @@
   RefreshEvent(this.element);
 }
 
-class NavRefreshElement extends HtmlElement implements Renderable {
+class NavRefreshElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavRefreshElement>('nav-refresh');
 
   RenderingScheduler _r;
@@ -36,14 +36,14 @@
       {String label: 'Refresh', bool disabled: false, RenderingQueue queue}) {
     assert(label != null);
     assert(disabled != null);
-    NavRefreshElement e = document.createElement(tag.name);
+    NavRefreshElement e = new NavRefreshElement.created();
     e._r = new RenderingScheduler<NavRefreshElement>(e, queue: queue);
     e._label = label;
     e._disabled = disabled;
     return e;
   }
 
-  NavRefreshElement.created() : super.created();
+  NavRefreshElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/nav/reload.dart b/runtime/observatory/lib/src/elements/nav/reload.dart
index 86c8225..64534d3 100644
--- a/runtime/observatory/lib/src/elements/nav/reload.dart
+++ b/runtime/observatory/lib/src/elements/nav/reload.dart
@@ -15,7 +15,7 @@
   ReloadEvent(this.element);
 }
 
-class NavReloadElement extends HtmlElement implements Renderable {
+class NavReloadElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavReloadElement>('nav-reload');
 
   RenderingScheduler _r;
@@ -38,7 +38,7 @@
     assert(isolate == null);
     assert(isolates == null);
     assert(events == null);
-    NavReloadElement e = document.createElement(tag.name);
+    NavReloadElement e = new NavReloadElement.created();
     e._r = new RenderingScheduler<NavReloadElement>(e, queue: queue);
     e._isolate = isolate;
     e._isolates = isolates;
@@ -46,7 +46,7 @@
     return e;
   }
 
-  NavReloadElement.created() : super.created();
+  NavReloadElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/nav/top_menu.dart b/runtime/observatory/lib/src/elements/nav/top_menu.dart
index 285be91..eb8cf97 100644
--- a/runtime/observatory/lib/src/elements/nav/top_menu.dart
+++ b/runtime/observatory/lib/src/elements/nav/top_menu.dart
@@ -10,7 +10,7 @@
 import 'package:observatory/src/elements/helpers/uris.dart';
 import 'package:observatory/src/elements/nav/menu_item.dart';
 
-class NavTopMenuElement extends HtmlElement implements Renderable {
+class NavTopMenuElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavTopMenuElement>('nav-top-menu',
       dependencies: const [NavMenuItemElement.tag]);
 
@@ -28,12 +28,12 @@
   }
 
   factory NavTopMenuElement({RenderingQueue queue}) {
-    NavTopMenuElement e = document.createElement(tag.name);
+    NavTopMenuElement e = new NavTopMenuElement.created();
     e._r = new RenderingScheduler<NavTopMenuElement>(e, queue: queue);
     return e;
   }
 
-  NavTopMenuElement.created() : super.created();
+  NavTopMenuElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -50,7 +50,7 @@
 
   void render() {
     final content = (<Element>[
-      new NavMenuItemElement('Connect to a VM', link: Uris.vmConnect()),
+      new NavMenuItemElement('Connect to a VM', link: Uris.vmConnect()).element,
     ]..addAll(_content));
     children = <Element>[
       navMenu('Observatory', link: Uris.vm(), content: content)
diff --git a/runtime/observatory/lib/src/elements/nav/vm_menu.dart b/runtime/observatory/lib/src/elements/nav/vm_menu.dart
index af1f8c4..38fbdf7 100644
--- a/runtime/observatory/lib/src/elements/nav/vm_menu.dart
+++ b/runtime/observatory/lib/src/elements/nav/vm_menu.dart
@@ -11,7 +11,7 @@
 import 'package:observatory/src/elements/helpers/uris.dart';
 import 'package:observatory/src/elements/nav/menu_item.dart';
 
-class NavVMMenuElement extends HtmlElement implements Renderable {
+class NavVMMenuElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavVMMenuElement>('nav-vm-menu',
       dependencies: const [NavMenuItemElement.tag]);
 
@@ -36,14 +36,14 @@
       {RenderingQueue queue}) {
     assert(vm != null);
     assert(events != null);
-    NavVMMenuElement e = document.createElement(tag.name);
+    NavVMMenuElement e = new NavVMMenuElement.created();
     e._r = new RenderingScheduler<NavVMMenuElement>(e, queue: queue);
     e._vm = vm;
     e._events = events;
     return e;
   }
 
-  NavVMMenuElement.created() : super.created();
+  NavVMMenuElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -66,7 +66,8 @@
   void render() {
     final content = (_vm.isolates.map<Element>((isolate) {
       return new NavMenuItemElement(isolate.name,
-          queue: _r.queue, link: Uris.inspect(isolate));
+              queue: _r.queue, link: Uris.inspect(isolate))
+          .element;
     }).toList()
       ..addAll(_content));
     children = <Element>[
diff --git a/runtime/observatory/lib/src/elements/object_common.dart b/runtime/observatory/lib/src/elements/object_common.dart
index 4df6eba..c2fd2c3 100644
--- a/runtime/observatory/lib/src/elements/object_common.dart
+++ b/runtime/observatory/lib/src/elements/object_common.dart
@@ -13,7 +13,7 @@
 import 'package:observatory/src/elements/sentinel_value.dart';
 import 'package:observatory/utils.dart';
 
-class ObjectCommonElement extends HtmlElement implements Renderable {
+class ObjectCommonElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<ObjectCommonElement>('object-common', dependencies: const [
     ClassRefElement.tag,
@@ -57,7 +57,7 @@
     assert(references != null);
     assert(retainingPaths != null);
     assert(objects != null);
-    ObjectCommonElement e = document.createElement(tag.name);
+    ObjectCommonElement e = new ObjectCommonElement.created();
     e._r = new RenderingScheduler<ObjectCommonElement>(e, queue: queue);
     e._isolate = isolate;
     e._object = object;
@@ -69,7 +69,7 @@
     return e;
   }
 
-  ObjectCommonElement.created() : super.created();
+  ObjectCommonElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -110,7 +110,8 @@
                   _object.clazz == null
                       ? (new SpanElement()..text = '...')
                       : new ClassRefElement(_isolate, _object.clazz,
-                          queue: _r.queue)
+                              queue: _r.queue)
+                          .element
                 ]
             ],
           new DivElement()
@@ -156,7 +157,7 @@
                 ..text = 'Retaining path ',
               new DivElement()
                 ..classes = ['memberValue']
-                ..children = <Element>[_path]
+                ..children = <Element>[_path.element]
             ],
           new DivElement()
             ..classes = ['memberItem']
@@ -167,7 +168,7 @@
                 ..text = 'Inbound references ',
               new DivElement()
                 ..classes = ['memberValue']
-                ..children = <Element>[_inbounds]
+                ..children = <Element>[_inbounds.element]
             ]
         ]
     ];
@@ -177,12 +178,13 @@
     final content = <Element>[];
     if (_reachableSize != null) {
       if (_reachableSize.isSentinel) {
-        content.add(new SentinelValueElement(_reachableSize.asSentinel,
-            queue: _r.queue));
+        content.add(
+            new SentinelValueElement(_reachableSize.asSentinel, queue: _r.queue)
+                .element);
       } else {
         content.add(new SpanElement()
-          ..text = Utils
-              .formatSize(int.parse(_reachableSize.asValue.valueAsString)));
+          ..text = Utils.formatSize(
+              int.parse(_reachableSize.asValue.valueAsString)));
       }
     } else {
       content.add(new SpanElement()..text = '...');
@@ -205,8 +207,9 @@
     final content = <Element>[];
     if (_retainedSize != null) {
       if (_retainedSize.isSentinel) {
-        content.add(new SentinelValueElement(_retainedSize.asSentinel,
-            queue: _r.queue));
+        content.add(
+            new SentinelValueElement(_retainedSize.asSentinel, queue: _r.queue)
+                .element);
       } else {
         content.add(new SpanElement()
           ..text =
diff --git a/runtime/observatory/lib/src/elements/object_view.dart b/runtime/observatory/lib/src/elements/object_view.dart
index d2a7237..2d7620f 100644
--- a/runtime/observatory/lib/src/elements/object_view.dart
+++ b/runtime/observatory/lib/src/elements/object_view.dart
@@ -19,7 +19,7 @@
 import 'package:observatory/src/elements/object_common.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class ObjectViewElement extends HtmlElement implements Renderable {
+class ObjectViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<ObjectViewElement>('object-view', dependencies: const [
     ContextRefElement.tag,
@@ -75,7 +75,7 @@
     assert(reachableSizes != null);
     assert(references != null);
     assert(retainingPaths != null);
-    ObjectViewElement e = document.createElement(tag.name);
+    ObjectViewElement e = new ObjectViewElement.created();
     e._r = new RenderingScheduler<ObjectViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -90,7 +90,7 @@
     return e;
   }
 
-  ObjectViewElement.created() : super.created();
+  ObjectViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -108,17 +108,18 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('object'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _object = await _objects.get(_isolate, _object.id);
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _object = await _objects.get(_isolate, _object.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -126,10 +127,11 @@
           new HeadingElement.h2()..text = 'Object',
           new HRElement(),
           new ObjectCommonElement(_isolate, _object, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/objectpool_ref.dart b/runtime/observatory/lib/src/elements/objectpool_ref.dart
index 9c77445..cd9902a 100644
--- a/runtime/observatory/lib/src/elements/objectpool_ref.dart
+++ b/runtime/observatory/lib/src/elements/objectpool_ref.dart
@@ -9,7 +9,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class ObjectPoolRefElement extends HtmlElement implements Renderable {
+class ObjectPoolRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<ObjectPoolRefElement>('object-pool-ref');
 
   RenderingScheduler<ObjectPoolRefElement> _r;
@@ -26,14 +26,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(pool != null);
-    ObjectPoolRefElement e = document.createElement(tag.name);
+    ObjectPoolRefElement e = new ObjectPoolRefElement.created();
     e._r = new RenderingScheduler<ObjectPoolRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._pool = pool;
     return e;
   }
 
-  ObjectPoolRefElement.created() : super.created();
+  ObjectPoolRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/objectpool_view.dart b/runtime/observatory/lib/src/elements/objectpool_view.dart
index 71ce7a0..0d4c232 100644
--- a/runtime/observatory/lib/src/elements/objectpool_view.dart
+++ b/runtime/observatory/lib/src/elements/objectpool_view.dart
@@ -22,7 +22,7 @@
 import 'package:observatory/src/elements/object_common.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class ObjectPoolViewElement extends HtmlElement implements Renderable {
+class ObjectPoolViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<ObjectPoolViewElement>('object-pool-view', dependencies: const [
     ContextRefElement.tag,
@@ -81,7 +81,7 @@
     assert(references != null);
     assert(retainingPaths != null);
     assert(objects != null);
-    ObjectPoolViewElement e = document.createElement(tag.name);
+    ObjectPoolViewElement e = new ObjectPoolViewElement.created();
     e._r = new RenderingScheduler<ObjectPoolViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -97,7 +97,7 @@
     return e;
   }
 
-  ObjectPoolViewElement.created() : super.created();
+  ObjectPoolViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -115,17 +115,18 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('instance'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _pool = await _pools.get(_isolate, _pool.id);
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _pool = await _pools.get(_isolate, _pool.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -133,8 +134,9 @@
           new HeadingElement.h2()..text = 'ObjectPool',
           new HRElement(),
           new ObjectCommonElement(_isolate, _pool, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new HRElement(),
           new HeadingElement.h3()..text = 'entries (${_pool.entries.length})',
           new DivElement()
@@ -152,7 +154,7 @@
                   ])
                 .toList(),
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/objectstore_view.dart b/runtime/observatory/lib/src/elements/objectstore_view.dart
index a7b31c9..66b50dc 100644
--- a/runtime/observatory/lib/src/elements/objectstore_view.dart
+++ b/runtime/observatory/lib/src/elements/objectstore_view.dart
@@ -19,7 +19,7 @@
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class ObjectStoreViewElement extends HtmlElement implements Renderable {
+class ObjectStoreViewElement extends CustomElement implements Renderable {
   static const tag = const Tag<ObjectStoreViewElement>('objectstore-view',
       dependencies: const [
         InstanceRefElement.tag,
@@ -61,7 +61,7 @@
     assert(notifications != null);
     assert(stores != null);
     assert(objects != null);
-    ObjectStoreViewElement e = document.createElement(tag.name);
+    ObjectStoreViewElement e = new ObjectStoreViewElement.created();
     e._r = new RenderingScheduler<ObjectStoreViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -72,7 +72,7 @@
     return e;
   }
 
-  ObjectStoreViewElement.created() : super.created();
+  ObjectStoreViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -92,12 +92,13 @@
     final fields = _store?.fields?.toList(growable: false);
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
-        new NavRefreshElement(disabled: _store == null, queue: _r.queue)
-          ..onRefresh.listen((e) => _refresh()),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        (new NavRefreshElement(disabled: _store == null, queue: _r.queue)
+              ..onRefresh.listen((e) => _refresh()))
+            .element,
+        (new NavNotifyElement(_notifications, queue: _r.queue).element)
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -126,7 +127,7 @@
                           ]
                       ])
                     .toList()),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/observatory_application.dart b/runtime/observatory/lib/src/elements/observatory_application.dart
index 0e85692..49e1665 100644
--- a/runtime/observatory/lib/src/elements/observatory_application.dart
+++ b/runtime/observatory/lib/src/elements/observatory_application.dart
@@ -4,20 +4,19 @@
 
 library observatory_application_element;
 
-import 'dart:html';
 import 'package:observatory/app.dart';
 import 'package:observatory/src/elements/helpers/tag.dart';
 
 /// Main application tag. Responsible for instantiating an instance of
 /// [ObservatoryApplication] which is passed declaratively to all child
 /// elements.
-class ObservatoryApplicationElement extends HtmlElement {
+class ObservatoryApplicationElement extends CustomElement {
   static const tag =
       const Tag<ObservatoryApplicationElement>('observatory-application');
 
   ObservatoryApplication app;
 
-  ObservatoryApplicationElement.created() : super.created();
+  ObservatoryApplicationElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/pc_descriptors_ref.dart b/runtime/observatory/lib/src/elements/pc_descriptors_ref.dart
index 2629b9f..fa43bbe 100644
--- a/runtime/observatory/lib/src/elements/pc_descriptors_ref.dart
+++ b/runtime/observatory/lib/src/elements/pc_descriptors_ref.dart
@@ -9,7 +9,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class PcDescriptorsRefElement extends HtmlElement implements Renderable {
+class PcDescriptorsRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<PcDescriptorsRefElement>('pc-ref');
 
   RenderingScheduler<PcDescriptorsRefElement> _r;
@@ -28,14 +28,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(descriptors != null);
-    PcDescriptorsRefElement e = document.createElement(tag.name);
+    PcDescriptorsRefElement e = new PcDescriptorsRefElement.created();
     e._r = new RenderingScheduler<PcDescriptorsRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._descriptors = descriptors;
     return e;
   }
 
-  PcDescriptorsRefElement.created() : super.created();
+  PcDescriptorsRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/persistent_handles.dart b/runtime/observatory/lib/src/elements/persistent_handles.dart
index 57f6196..9a0d15d 100644
--- a/runtime/observatory/lib/src/elements/persistent_handles.dart
+++ b/runtime/observatory/lib/src/elements/persistent_handles.dart
@@ -25,7 +25,7 @@
 
 enum _SortingDirection { ascending, descending }
 
-class PersistentHandlesPageElement extends HtmlElement implements Renderable {
+class PersistentHandlesPageElement extends CustomElement implements Renderable {
   static const tag = const Tag<PersistentHandlesPageElement>(
       'persistent-handles-page',
       dependencies: const [
@@ -71,7 +71,7 @@
     assert(notifications != null);
     assert(repository != null);
     assert(objects != null);
-    PersistentHandlesPageElement e = document.createElement(tag.name);
+    PersistentHandlesPageElement e = new PersistentHandlesPageElement.created();
     e._r =
         new RenderingScheduler<PersistentHandlesPageElement>(e, queue: queue);
     e._vm = vm;
@@ -83,7 +83,7 @@
     return e;
   }
 
-  PersistentHandlesPageElement.created() : super.created();
+  PersistentHandlesPageElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -102,13 +102,14 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('persistent handles'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((_) => _refresh()),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh()))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ])
     ]
       ..addAll(_createHandlers('Persistent Handles',
@@ -142,7 +143,8 @@
                 ..classes = ['content-centered-big']
                 ..text = 'Loading...')
               : new VirtualCollectionElement(create, update,
-                  items: items, createHeader: createHeader, queue: _r.queue)
+                      items: items, createHeader: createHeader, queue: _r.queue)
+                  .element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/ports.dart b/runtime/observatory/lib/src/elements/ports.dart
index 59d7952..6561ffe 100644
--- a/runtime/observatory/lib/src/elements/ports.dart
+++ b/runtime/observatory/lib/src/elements/ports.dart
@@ -18,7 +18,7 @@
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class PortsElement extends HtmlElement implements Renderable {
+class PortsElement extends CustomElement implements Renderable {
   static const tag = const Tag<PortsElement>('ports-page', dependencies: const [
     NavTopMenuElement.tag,
     NavVMMenuElement.tag,
@@ -60,7 +60,7 @@
     assert(notifications != null);
     assert(ports != null);
     assert(objects != null);
-    PortsElement e = document.createElement(tag.name);
+    PortsElement e = new PortsElement.created();
     e._r = new RenderingScheduler<PortsElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -71,7 +71,7 @@
     return e;
   }
 
-  PortsElement.created() : super.created();
+  PortsElement.created() : super.created(tag);
 
   int get portCount {
     return _isolatePorts == null ? 0 : _isolatePorts.elements.length;
@@ -94,13 +94,14 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('ports'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((_) => _refresh()),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh()))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered']
@@ -110,7 +111,7 @@
           new BRElement(),
           new DivElement()..children = _createList(),
         ],
-      new ViewFooterElement(queue: _r.queue)
+      new ViewFooterElement(queue: _r.queue).element
     ];
   }
 
diff --git a/runtime/observatory/lib/src/elements/retaining_path.dart b/runtime/observatory/lib/src/elements/retaining_path.dart
index a72c728..0adfca5 100644
--- a/runtime/observatory/lib/src/elements/retaining_path.dart
+++ b/runtime/observatory/lib/src/elements/retaining_path.dart
@@ -11,7 +11,7 @@
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 import 'package:observatory/src/elements/helpers/tag.dart';
 
-class RetainingPathElement extends HtmlElement implements Renderable {
+class RetainingPathElement extends CustomElement implements Renderable {
   static const tag = const Tag<RetainingPathElement>('retaining-path',
       dependencies: const [CurlyBlockElement.tag, InstanceRefElement.tag]);
 
@@ -36,7 +36,7 @@
     assert(object != null);
     assert(retainingPaths != null);
     assert(objects != null);
-    RetainingPathElement e = document.createElement(tag.name);
+    RetainingPathElement e = new RetainingPathElement.created();
     e._r = new RenderingScheduler<RetainingPathElement>(e, queue: queue);
     e._isolate = isolate;
     e._object = object;
@@ -45,7 +45,7 @@
     return e;
   }
 
-  RetainingPathElement.created() : super.created();
+  RetainingPathElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -72,7 +72,7 @@
               e.control.disabled = false;
             }
           });
-    children = <Element>[curlyBlock];
+    children = <Element>[curlyBlock.element];
     _r.waitFor([curlyBlock.onRendered.first]);
   }
 
diff --git a/runtime/observatory/lib/src/elements/sample_buffer_control.dart b/runtime/observatory/lib/src/elements/sample_buffer_control.dart
index 0d5b38c..97adb22 100644
--- a/runtime/observatory/lib/src/elements/sample_buffer_control.dart
+++ b/runtime/observatory/lib/src/elements/sample_buffer_control.dart
@@ -14,7 +14,7 @@
   SampleBufferControlChangedElement(this.element);
 }
 
-class SampleBufferControlElement extends HtmlElement implements Renderable {
+class SampleBufferControlElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<SampleBufferControlElement>('sample-buffer-control');
 
@@ -57,7 +57,7 @@
     assert(progressStream != null);
     assert(selectedTag != null);
     assert(showTag != null);
-    SampleBufferControlElement e = document.createElement(tag.name);
+    SampleBufferControlElement e = new SampleBufferControlElement.created();
     e._r = new RenderingScheduler<SampleBufferControlElement>(e, queue: queue);
     e._vm = vm;
     e._progress = progress;
@@ -67,7 +67,7 @@
     return e;
   }
 
-  SampleBufferControlElement.created() : super.created();
+  SampleBufferControlElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -220,7 +220,11 @@
   List<Element> _createTagSelect() {
     var values = M.SampleProfileTag.values;
     if (!_profileVM) {
-      values = const [M.SampleProfileTag.userOnly, M.SampleProfileTag.vmOnly, M.SampleProfileTag.none];
+      values = const [
+        M.SampleProfileTag.userOnly,
+        M.SampleProfileTag.vmOnly,
+        M.SampleProfileTag.none
+      ];
     }
     var s;
     return [
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index c386824..9c5ca8f 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -16,7 +16,7 @@
 import 'package:observatory/src/elements/helpers/uris.dart';
 import 'package:observatory/utils.dart';
 
-class ScriptInsetElement extends HtmlElement implements Renderable {
+class ScriptInsetElement extends CustomElement implements Renderable {
   static const tag = const Tag<ScriptInsetElement>('script-inset');
 
   RenderingScheduler _r;
@@ -58,7 +58,7 @@
     assert(events != null);
     assert(inDebuggerContext != null);
     assert(variables != null);
-    ScriptInsetElement e = document.createElement(tag.name);
+    ScriptInsetElement e = new ScriptInsetElement.created();
     e._r = new RenderingScheduler<ScriptInsetElement>(e, queue: queue);
     e._isolate = isolate;
     e._script = script;
@@ -73,7 +73,7 @@
     return e;
   }
 
-  ScriptInsetElement.created() : super.created();
+  ScriptInsetElement.created() : super.created(tag);
 
   bool get noSource => _startPos == -1 || _loadedScript.source == null;
 
@@ -84,8 +84,8 @@
     _subscription = _events.onDebugEvent
         .where((e) => e is M.BreakpointEvent)
         .map((e) => (e as M.BreakpointEvent).breakpoint)
-        .listen((M.Breakpoint b) {
-      final loc = b.location;
+        .listen((M.Breakpoint b) async {
+      final M.Location loc = b.location;
       int line;
       if (loc.script.id == script.id) {
         if (loc.tokenPos != null) {
@@ -94,7 +94,14 @@
           line = (loc as dynamic).line;
         }
       } else {
-        line = (loc as dynamic).line;
+        try {
+          line = (loc as dynamic).line;
+        } on NoSuchMethodError {
+          if (loc.tokenPos != null) {
+            M.Script scriptUsed = await _scripts.get(_isolate, loc.script.id);
+            line = scriptUsed.tokenToLine(loc.tokenPos);
+          }
+        }
       }
       if ((line == null) || ((line >= _startLine) && (line <= _endLine))) {
         _r.dirty();
@@ -832,7 +839,8 @@
 
   Element lineNumberElement(S.ScriptLine line, int lineNumPad) {
     var lineNumber = line == null ? "..." : line.line;
-    var e = span("$nbsp${lineNumber.toString().padLeft(lineNumPad,nbsp)}$nbsp");
+    var e =
+        span("$nbsp${lineNumber.toString().padLeft(lineNumPad, nbsp)}$nbsp");
     e.classes.add('noCopy');
     if (lineNumber == _currentLine) {
       hitsCurrent(e);
@@ -1374,10 +1382,10 @@
       ..setAttribute(
           'd',
           'M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 '
-          '3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 '
-          '7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 '
-          '0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 '
-          '1.78L13 11h7V4l-2.35 2.35z')
+              '3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 '
+              '7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 '
+              '0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 '
+              '1.78L13 11h7V4l-2.35 2.35z')
   ];
 
 final SvgSvgElement _iconWhatsHot = new SvgSvgElement()
@@ -1388,10 +1396,10 @@
       ..setAttribute(
           'd',
           'M13.5.67s.74 2.65.74 4.8c0 2.06-1.35 3.73-3.41 '
-          '3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 '
-          '4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 '
-          '17.41 3.8 13.5.67zM11.71 19c-1.78 '
-          '0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 '
-          '1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 '
-          '4.04 0 2.65-2.15 4.8-4.8 4.8z')
+              '3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 '
+              '4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 '
+              '17.41 3.8 13.5.67zM11.71 19c-1.78 '
+              '0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 '
+              '1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 '
+              '4.04 0 2.65-2.15 4.8-4.8 4.8z')
   ];
diff --git a/runtime/observatory/lib/src/elements/script_ref.dart b/runtime/observatory/lib/src/elements/script_ref.dart
index eb1cc99..1ed7453c 100644
--- a/runtime/observatory/lib/src/elements/script_ref.dart
+++ b/runtime/observatory/lib/src/elements/script_ref.dart
@@ -11,7 +11,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class ScriptRefElement extends HtmlElement implements Renderable {
+class ScriptRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<ScriptRefElement>('script-ref');
 
   RenderingScheduler _r;
@@ -28,14 +28,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(script != null);
-    ScriptRefElement e = document.createElement(tag.name);
+    ScriptRefElement e = new ScriptRefElement.created();
     e._r = new RenderingScheduler<ScriptRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._script = script;
     return e;
   }
 
-  ScriptRefElement.created() : super.created();
+  ScriptRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/script_view.dart b/runtime/observatory/lib/src/elements/script_view.dart
index c797360..7be611b 100644
--- a/runtime/observatory/lib/src/elements/script_view.dart
+++ b/runtime/observatory/lib/src/elements/script_view.dart
@@ -23,7 +23,7 @@
 import 'package:observatory/src/elements/script_inset.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class ScriptViewElement extends HtmlElement implements Renderable {
+class ScriptViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<ScriptViewElement>('script-view', dependencies: const [
     ContextRefElement.tag,
@@ -86,7 +86,7 @@
     assert(references != null);
     assert(retainingPaths != null);
     assert(objects != null);
-    ScriptViewElement e = document.createElement(tag.name);
+    ScriptViewElement e = new ScriptViewElement.created();
     e._r = new RenderingScheduler<ScriptViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -103,7 +103,7 @@
     return e;
   }
 
-  ScriptViewElement.created() : super.created();
+  ScriptViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -121,18 +121,20 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
-        new NavLibraryMenuElement(_isolate, _script.library, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        new NavLibraryMenuElement(_isolate, _script.library, queue: _r.queue)
+            .element,
         navMenu('object'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _script = await _scripts.get(_isolate, _script.id);
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _script = await _scripts.get(_isolate, _script.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -140,8 +142,9 @@
           new HeadingElement.h2()..text = 'Script',
           new HRElement(),
           new ObjectCommonElement(_isolate, _script, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new BRElement(),
           new DivElement()
             ..classes = ['memberList']
@@ -159,8 +162,9 @@
             ],
           new HRElement(),
           new ScriptInsetElement(_isolate, _script, _scripts, _objects, _events,
-              currentPos: _pos, queue: _r.queue),
-          new ViewFooterElement(queue: _r.queue)
+                  currentPos: _pos, queue: _r.queue)
+              .element,
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/sentinel_value.dart b/runtime/observatory/lib/src/elements/sentinel_value.dart
index 70ea4a3..b646d9e 100644
--- a/runtime/observatory/lib/src/elements/sentinel_value.dart
+++ b/runtime/observatory/lib/src/elements/sentinel_value.dart
@@ -2,13 +2,13 @@
 // 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 Sentinel, SentinelKind;
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 import 'package:observatory/src/elements/helpers/tag.dart';
 
-class SentinelValueElement extends HtmlElement implements Renderable {
+class SentinelValueElement extends CustomElement implements Renderable {
   static const tag = const Tag<SentinelValueElement>('sentinel-value');
 
   RenderingScheduler<SentinelValueElement> _r;
@@ -21,13 +21,13 @@
 
   factory SentinelValueElement(M.Sentinel sentinel, {RenderingQueue queue}) {
     assert(sentinel != null);
-    SentinelValueElement e = document.createElement(tag.name);
+    SentinelValueElement e = new SentinelValueElement.created();
     e._r = new RenderingScheduler<SentinelValueElement>(e, queue: queue);
     e._sentinel = sentinel;
     return e;
   }
 
-  SentinelValueElement.created() : super.created();
+  SentinelValueElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/sentinel_view.dart b/runtime/observatory/lib/src/elements/sentinel_view.dart
index 9d9a2ad..496c930 100644
--- a/runtime/observatory/lib/src/elements/sentinel_view.dart
+++ b/runtime/observatory/lib/src/elements/sentinel_view.dart
@@ -15,7 +15,7 @@
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class SentinelViewElement extends HtmlElement implements Renderable {
+class SentinelViewElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<SentinelViewElement>('sentinel-view', dependencies: const [
     NavTopMenuElement.tag,
@@ -49,7 +49,7 @@
     assert(sentinel != null);
     assert(events != null);
     assert(notifications != null);
-    SentinelViewElement e = document.createElement(tag.name);
+    SentinelViewElement e = new SentinelViewElement.created();
     e._r = new RenderingScheduler<SentinelViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -59,7 +59,7 @@
     return e;
   }
 
-  SentinelViewElement.created() : super.created();
+  SentinelViewElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -78,11 +78,11 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('sentinel'),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -92,7 +92,7 @@
           new HRElement(),
           new DivElement()..text = _sentinelKindToDescription(_sentinel.kind),
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/singletargetcache_ref.dart b/runtime/observatory/lib/src/elements/singletargetcache_ref.dart
index 1e2e3dd..9b8dd33 100644
--- a/runtime/observatory/lib/src/elements/singletargetcache_ref.dart
+++ b/runtime/observatory/lib/src/elements/singletargetcache_ref.dart
@@ -10,7 +10,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class SingleTargetCacheRefElement extends HtmlElement implements Renderable {
+class SingleTargetCacheRefElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<SingleTargetCacheRefElement>('singletargetcache-ref');
 
@@ -30,14 +30,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(singleTargetCache != null);
-    SingleTargetCacheRefElement e = document.createElement(tag.name);
+    SingleTargetCacheRefElement e = new SingleTargetCacheRefElement.created();
     e._r = new RenderingScheduler<SingleTargetCacheRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._singleTargetCache = singleTargetCache;
     return e;
   }
 
-  SingleTargetCacheRefElement.created() : super.created();
+  SingleTargetCacheRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/singletargetcache_view.dart b/runtime/observatory/lib/src/elements/singletargetcache_view.dart
index 651c9ff..05a306a 100644
--- a/runtime/observatory/lib/src/elements/singletargetcache_view.dart
+++ b/runtime/observatory/lib/src/elements/singletargetcache_view.dart
@@ -19,7 +19,7 @@
 import 'package:observatory/src/elements/object_common.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class SingleTargetCacheViewElement extends HtmlElement implements Renderable {
+class SingleTargetCacheViewElement extends CustomElement implements Renderable {
   static const tag = const Tag<SingleTargetCacheViewElement>(
       'singletargetcache-view',
       dependencies: const [
@@ -79,7 +79,7 @@
     assert(references != null);
     assert(retainingPaths != null);
     assert(objects != null);
-    SingleTargetCacheViewElement e = document.createElement(tag.name);
+    SingleTargetCacheViewElement e = new SingleTargetCacheViewElement.created();
     e._r =
         new RenderingScheduler<SingleTargetCacheViewElement>(e, queue: queue);
     e._vm = vm;
@@ -96,7 +96,7 @@
     return e;
   }
 
-  SingleTargetCacheViewElement.created() : super.created();
+  SingleTargetCacheViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -114,18 +114,19 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('singleTargetCache'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _singleTargetCache =
-                await _singleTargetCaches.get(_isolate, _singleTargetCache.id);
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _singleTargetCache = await _singleTargetCaches.get(
+                    _isolate, _singleTargetCache.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -133,8 +134,9 @@
           new HeadingElement.h2()..text = 'SingleTargetCache',
           new HRElement(),
           new ObjectCommonElement(_isolate, _singleTargetCache, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new DivElement()
             ..classes = ['memberList']
             ..children = <Element>[
@@ -179,7 +181,7 @@
                 ]
             ],
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/source_inset.dart b/runtime/observatory/lib/src/elements/source_inset.dart
index 210ce2e..42d3d2b 100644
--- a/runtime/observatory/lib/src/elements/source_inset.dart
+++ b/runtime/observatory/lib/src/elements/source_inset.dart
@@ -11,7 +11,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/script_inset.dart';
 
-class SourceInsetElement extends HtmlElement implements Renderable {
+class SourceInsetElement extends CustomElement implements Renderable {
   static const tag = const Tag<SourceInsetElement>('source-inset');
 
   RenderingScheduler _r;
@@ -47,7 +47,7 @@
     assert(events != null);
     assert(inDebuggerContext != null);
     assert(variables != null);
-    SourceInsetElement e = document.createElement(tag.name);
+    SourceInsetElement e = new SourceInsetElement.created();
     e._r = new RenderingScheduler<SourceInsetElement>(e, queue: queue);
     e._isolate = isolate;
     e._location = location;
@@ -60,7 +60,7 @@
     return e;
   }
 
-  SourceInsetElement.created() : super.created();
+  SourceInsetElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -78,13 +78,14 @@
   void render() {
     children = <Element>[
       new ScriptInsetElement(
-          _isolate, _location.script, _scripts, _objects, _events,
-          startPos: _location.tokenPos,
-          endPos: _location.endTokenPos,
-          currentPos: _currentPos,
-          inDebuggerContext: _inDebuggerContext,
-          variables: _variables,
-          queue: _r.queue)
+              _isolate, _location.script, _scripts, _objects, _events,
+              startPos: _location.tokenPos,
+              endPos: _location.endTokenPos,
+              currentPos: _currentPos,
+              inDebuggerContext: _inDebuggerContext,
+              variables: _variables,
+              queue: _r.queue)
+          .element
     ];
   }
 }
diff --git a/runtime/observatory/lib/src/elements/source_link.dart b/runtime/observatory/lib/src/elements/source_link.dart
index a08adbd..c6f816e 100644
--- a/runtime/observatory/lib/src/elements/source_link.dart
+++ b/runtime/observatory/lib/src/elements/source_link.dart
@@ -12,7 +12,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class SourceLinkElement extends HtmlElement implements Renderable {
+class SourceLinkElement extends CustomElement implements Renderable {
   static const tag = const Tag<SourceLinkElement>('source-link');
 
   RenderingScheduler _r;
@@ -32,7 +32,7 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(location != null);
-    SourceLinkElement e = document.createElement(tag.name);
+    SourceLinkElement e = new SourceLinkElement.created();
     e._r = new RenderingScheduler<SourceLinkElement>(e, queue: queue);
     e._isolate = isolate;
     e._location = location;
@@ -40,7 +40,7 @@
     return e;
   }
 
-  SourceLinkElement.created() : super.created();
+  SourceLinkElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/stack_trace_tree_config.dart b/runtime/observatory/lib/src/elements/stack_trace_tree_config.dart
index 9aedfc6..396b938 100644
--- a/runtime/observatory/lib/src/elements/stack_trace_tree_config.dart
+++ b/runtime/observatory/lib/src/elements/stack_trace_tree_config.dart
@@ -18,7 +18,7 @@
   StackTraceTreeConfigChangedEvent(this.element);
 }
 
-class StackTraceTreeConfigElement extends HtmlElement implements Renderable {
+class StackTraceTreeConfigElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<StackTraceTreeConfigElement>('stack-trace-tree-config');
 
@@ -78,7 +78,7 @@
     assert(mode != null);
     assert(direction != null);
     assert(filter != null);
-    StackTraceTreeConfigElement e = document.createElement(tag.name);
+    StackTraceTreeConfigElement e = new StackTraceTreeConfigElement.created();
     e._r = new RenderingScheduler<StackTraceTreeConfigElement>(e, queue: queue);
     e._showMode = showMode;
     e._showDirection = showDirection;
@@ -89,7 +89,7 @@
     return e;
   }
 
-  StackTraceTreeConfigElement.created() : super.created();
+  StackTraceTreeConfigElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/strongly_reachable_instances.dart b/runtime/observatory/lib/src/elements/strongly_reachable_instances.dart
index 8319596..73c0f9e 100644
--- a/runtime/observatory/lib/src/elements/strongly_reachable_instances.dart
+++ b/runtime/observatory/lib/src/elements/strongly_reachable_instances.dart
@@ -11,7 +11,7 @@
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 import 'package:observatory/src/elements/helpers/tag.dart';
 
-class StronglyReachableInstancesElement extends HtmlElement
+class StronglyReachableInstancesElement extends CustomElement
     implements Renderable {
   static const tag = const Tag<StronglyReachableInstancesElement>(
       'strongly-reachable-instances',
@@ -42,7 +42,8 @@
     assert(cls != null);
     assert(stronglyReachable != null);
     assert(objects != null);
-    StronglyReachableInstancesElement e = document.createElement(tag.name);
+    StronglyReachableInstancesElement e =
+        new StronglyReachableInstancesElement.created();
     e._r = new RenderingScheduler<StronglyReachableInstancesElement>(e,
         queue: queue);
     e._isolate = isolate;
@@ -52,7 +53,7 @@
     return e;
   }
 
-  StronglyReachableInstancesElement.created() : super.created();
+  StronglyReachableInstancesElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -69,14 +70,15 @@
 
   void render() {
     children = <Element>[
-      new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
-        ..content = _createContent()
-        ..onToggle.listen((e) async {
-          _expanded = e.control.expanded;
-          e.control.disabled = true;
-          await _refresh();
-          e.control.disabled = false;
-        })
+      (new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
+            ..content = _createContent()
+            ..onToggle.listen((e) async {
+              _expanded = e.control.expanded;
+              e.control.disabled = true;
+              await _refresh();
+              e.control.disabled = false;
+            }))
+          .element
     ];
   }
 
diff --git a/runtime/observatory/lib/src/elements/subtypetestcache_ref.dart b/runtime/observatory/lib/src/elements/subtypetestcache_ref.dart
index fb7cf89..6d7085b 100644
--- a/runtime/observatory/lib/src/elements/subtypetestcache_ref.dart
+++ b/runtime/observatory/lib/src/elements/subtypetestcache_ref.dart
@@ -10,7 +10,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class SubtypeTestCacheRefElement extends HtmlElement implements Renderable {
+class SubtypeTestCacheRefElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<SubtypeTestCacheRefElement>('subtypetestcache-ref');
 
@@ -30,14 +30,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(subtypeTestCache != null);
-    SubtypeTestCacheRefElement e = document.createElement(tag.name);
+    SubtypeTestCacheRefElement e = new SubtypeTestCacheRefElement.created();
     e._r = new RenderingScheduler<SubtypeTestCacheRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._subtypeTestCache = subtypeTestCache;
     return e;
   }
 
-  SubtypeTestCacheRefElement.created() : super.created();
+  SubtypeTestCacheRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/subtypetestcache_view.dart b/runtime/observatory/lib/src/elements/subtypetestcache_view.dart
index 80c14fd..b53cb43 100644
--- a/runtime/observatory/lib/src/elements/subtypetestcache_view.dart
+++ b/runtime/observatory/lib/src/elements/subtypetestcache_view.dart
@@ -19,7 +19,7 @@
 import 'package:observatory/src/elements/object_common.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class SubtypeTestCacheViewElement extends HtmlElement implements Renderable {
+class SubtypeTestCacheViewElement extends CustomElement implements Renderable {
   static const tag = const Tag<SubtypeTestCacheViewElement>(
       'subtypetestcache-view',
       dependencies: const [
@@ -79,7 +79,7 @@
     assert(references != null);
     assert(retainingPaths != null);
     assert(objects != null);
-    SubtypeTestCacheViewElement e = document.createElement(tag.name);
+    SubtypeTestCacheViewElement e = new SubtypeTestCacheViewElement.created();
     e._r = new RenderingScheduler<SubtypeTestCacheViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -95,7 +95,7 @@
     return e;
   }
 
-  SubtypeTestCacheViewElement.created() : super.created();
+  SubtypeTestCacheViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -113,18 +113,19 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('subtypeTestCache'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _subtypeTestCache =
-                await _subtypeTestCaches.get(_isolate, _subtypeTestCache.id);
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _subtypeTestCache = await _subtypeTestCaches.get(
+                    _isolate, _subtypeTestCache.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -132,8 +133,9 @@
           new HeadingElement.h2()..text = 'SubtypeTestCache',
           new HRElement(),
           new ObjectCommonElement(_isolate, _subtypeTestCache, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new DivElement()
             ..classes = ['memberList']
             ..children = <Element>[
@@ -152,7 +154,7 @@
                 ]
             ],
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/timeline/dashboard.dart b/runtime/observatory/lib/src/elements/timeline/dashboard.dart
index dbac222..584d8b8 100644
--- a/runtime/observatory/lib/src/elements/timeline/dashboard.dart
+++ b/runtime/observatory/lib/src/elements/timeline/dashboard.dart
@@ -33,7 +33,7 @@
 ///   overlapping the related events.
 enum _TimelineView { strict, frame }
 
-class TimelineDashboardElement extends HtmlElement implements Renderable {
+class TimelineDashboardElement extends CustomElement implements Renderable {
   static const tag = const Tag<TimelineDashboardElement>('timeline-dashboard',
       dependencies: const [NavNotifyElement.tag]);
 
@@ -57,7 +57,7 @@
     assert(vm != null);
     assert(repository != null);
     assert(notifications != null);
-    TimelineDashboardElement e = document.createElement(tag.name);
+    TimelineDashboardElement e = new TimelineDashboardElement.created();
     e._r = new RenderingScheduler<TimelineDashboardElement>(e, queue: queue);
     e._vm = vm;
     e._repository = repository;
@@ -68,7 +68,7 @@
     return e;
   }
 
-  TimelineDashboardElement.created() : super.created();
+  TimelineDashboardElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -105,12 +105,13 @@
             ? 'Logical view of the computation involved in each frame '
                 '(timestamps may not be preserved)'
             : 'Sequence of events generated during the execution '
-            '(timestamps are preserved)')
+                '(timestamps are preserved)')
     ];
     if (children.isEmpty) {
       children = <Element>[
-        navBar(
-            <Element>[new NavNotifyElement(_notifications, queue: _r.queue)]),
+        navBar(<Element>[
+          new NavNotifyElement(_notifications, queue: _r.queue).element
+        ]),
         _content,
         new DivElement()
           ..classes = ['iframe']
diff --git a/runtime/observatory/lib/src/elements/timeline_page.dart b/runtime/observatory/lib/src/elements/timeline_page.dart
index 5a51145..f912239 100644
--- a/runtime/observatory/lib/src/elements/timeline_page.dart
+++ b/runtime/observatory/lib/src/elements/timeline_page.dart
@@ -18,7 +18,7 @@
 import 'package:observatory/src/elements/nav/top_menu.dart';
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 
-class TimelinePageElement extends HtmlElement implements Renderable {
+class TimelinePageElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<TimelinePageElement>('timeline-page', dependencies: const [
     NavTopMenuElement.tag,
@@ -50,7 +50,7 @@
     assert(repository != null);
     assert(events != null);
     assert(notifications != null);
-    TimelinePageElement e = document.createElement(tag.name);
+    TimelinePageElement e = new TimelinePageElement.created();
     e._r = new RenderingScheduler<TimelinePageElement>(e, queue: queue);
     e._vm = vm;
     e._repository = repository;
@@ -59,7 +59,7 @@
     return e;
   }
 
-  TimelinePageElement.created() : super.created();
+  TimelinePageElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -132,34 +132,38 @@
 
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(vm, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(vm, _events, queue: _r.queue).element,
         navMenu('timeline', link: Uris.timeline()),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            await _refresh();
-            e.element.disabled = !usingVMRecorder;
-          }),
-        new NavRefreshElement(label: 'clear', queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            await _clear();
-            e.element.disabled = !usingVMRecorder;
-          }),
-        new NavRefreshElement(label: 'save', queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            await _save();
-            e.element.disabled = !usingVMRecorder;
-          }),
-        new NavRefreshElement(label: 'load', queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            await _load();
-            e.element.disabled = !usingVMRecorder;
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                await _refresh();
+                e.element.disabled = !usingVMRecorder;
+              }))
+            .element,
+        (new NavRefreshElement(label: 'clear', queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                await _clear();
+                e.element.disabled = !usingVMRecorder;
+              }))
+            .element,
+        (new NavRefreshElement(label: 'save', queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                await _save();
+                e.element.disabled = !usingVMRecorder;
+              }))
+            .element,
+        (new NavRefreshElement(label: 'load', queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                await _load();
+                e.element.disabled = !usingVMRecorder;
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       _content,
       _createIFrameOrMessage(),
diff --git a/runtime/observatory/lib/src/elements/top_retaining_instances.dart b/runtime/observatory/lib/src/elements/top_retaining_instances.dart
index 4d63dde..31a84a5 100644
--- a/runtime/observatory/lib/src/elements/top_retaining_instances.dart
+++ b/runtime/observatory/lib/src/elements/top_retaining_instances.dart
@@ -12,7 +12,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/utils.dart';
 
-class TopRetainingInstancesElement extends HtmlElement implements Renderable {
+class TopRetainingInstancesElement extends CustomElement implements Renderable {
   static const tag = const Tag<TopRetainingInstancesElement>(
       'top-retainig-instances',
       dependencies: const [CurlyBlockElement.tag, InstanceRefElement.tag]);
@@ -42,7 +42,7 @@
     assert(cls != null);
     assert(topRetainingInstances != null);
     assert(objects != null);
-    TopRetainingInstancesElement e = document.createElement(tag.name);
+    TopRetainingInstancesElement e = new TopRetainingInstancesElement.created();
     e._r =
         new RenderingScheduler<TopRetainingInstancesElement>(e, queue: queue);
     e._isolate = isolate;
@@ -52,7 +52,7 @@
     return e;
   }
 
-  TopRetainingInstancesElement.created() : super.created();
+  TopRetainingInstancesElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -69,20 +69,21 @@
 
   void render() {
     children = <Element>[
-      new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
-        ..content = <Element>[
-          new DivElement()
-            ..classes = ['memberList']
-            ..children = _createContent()
-        ]
-        ..onToggle.listen((e) async {
-          _expanded = e.control.expanded;
-          if (_expanded) {
-            e.control.disabled = true;
-            await _refresh();
-            e.control.disabled = false;
-          }
-        })
+      (new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
+            ..content = <Element>[
+              new DivElement()
+                ..classes = ['memberList']
+                ..children = _createContent()
+            ]
+            ..onToggle.listen((e) async {
+              _expanded = e.control.expanded;
+              if (_expanded) {
+                e.control.disabled = true;
+                await _refresh();
+                e.control.disabled = false;
+              }
+            }))
+          .element
     ];
   }
 
diff --git a/runtime/observatory/lib/src/elements/type_arguments_ref.dart b/runtime/observatory/lib/src/elements/type_arguments_ref.dart
index f29e560..c0c7ed1 100644
--- a/runtime/observatory/lib/src/elements/type_arguments_ref.dart
+++ b/runtime/observatory/lib/src/elements/type_arguments_ref.dart
@@ -9,7 +9,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class TypeArgumentsRefElement extends HtmlElement implements Renderable {
+class TypeArgumentsRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<TypeArgumentsRefElement>('type-arguments-ref');
 
   RenderingScheduler<TypeArgumentsRefElement> _r;
@@ -27,14 +27,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(args != null);
-    TypeArgumentsRefElement e = document.createElement(tag.name);
+    TypeArgumentsRefElement e = new TypeArgumentsRefElement.created();
     e._r = new RenderingScheduler<TypeArgumentsRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._arguments = args;
     return e;
   }
 
-  TypeArgumentsRefElement.created() : super.created();
+  TypeArgumentsRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/unknown_ref.dart b/runtime/observatory/lib/src/elements/unknown_ref.dart
index ff287c0..cad1136 100644
--- a/runtime/observatory/lib/src/elements/unknown_ref.dart
+++ b/runtime/observatory/lib/src/elements/unknown_ref.dart
@@ -9,7 +9,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class UnknownObjectRefElement extends HtmlElement implements Renderable {
+class UnknownObjectRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<UnknownObjectRefElement>('unknown-ref');
 
   RenderingScheduler<UnknownObjectRefElement> _r;
@@ -27,14 +27,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(obj != null);
-    UnknownObjectRefElement e = document.createElement(tag.name);
+    UnknownObjectRefElement e = new UnknownObjectRefElement.created();
     e._r = new RenderingScheduler<UnknownObjectRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._obj = obj;
     return e;
   }
 
-  UnknownObjectRefElement.created() : super.created();
+  UnknownObjectRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/unlinkedcall_ref.dart b/runtime/observatory/lib/src/elements/unlinkedcall_ref.dart
index 02a4434..9a13575 100644
--- a/runtime/observatory/lib/src/elements/unlinkedcall_ref.dart
+++ b/runtime/observatory/lib/src/elements/unlinkedcall_ref.dart
@@ -9,7 +9,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/uris.dart';
 
-class UnlinkedCallRefElement extends HtmlElement implements Renderable {
+class UnlinkedCallRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<UnlinkedCallRefElement>('unlinkedcall-ref');
 
   RenderingScheduler<UnlinkedCallRefElement> _r;
@@ -27,14 +27,14 @@
       {RenderingQueue queue}) {
     assert(isolate != null);
     assert(unlinkedcall != null);
-    UnlinkedCallRefElement e = document.createElement(tag.name);
+    UnlinkedCallRefElement e = new UnlinkedCallRefElement.created();
     e._r = new RenderingScheduler<UnlinkedCallRefElement>(e, queue: queue);
     e._isolate = isolate;
     e._unlinkedcall = unlinkedcall;
     return e;
   }
 
-  UnlinkedCallRefElement.created() : super.created();
+  UnlinkedCallRefElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/unlinkedcall_view.dart b/runtime/observatory/lib/src/elements/unlinkedcall_view.dart
index d46f170..315c58b 100644
--- a/runtime/observatory/lib/src/elements/unlinkedcall_view.dart
+++ b/runtime/observatory/lib/src/elements/unlinkedcall_view.dart
@@ -19,7 +19,7 @@
 import 'package:observatory/src/elements/object_common.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 
-class UnlinkedCallViewElement extends HtmlElement implements Renderable {
+class UnlinkedCallViewElement extends CustomElement implements Renderable {
   static const tag = const Tag<UnlinkedCallViewElement>('unlinkedcall-view',
       dependencies: const [
         CurlyBlockElement.tag,
@@ -78,7 +78,7 @@
     assert(references != null);
     assert(retainingPaths != null);
     assert(objects != null);
-    UnlinkedCallViewElement e = document.createElement(tag.name);
+    UnlinkedCallViewElement e = new UnlinkedCallViewElement.created();
     e._r = new RenderingScheduler<UnlinkedCallViewElement>(e, queue: queue);
     e._vm = vm;
     e._isolate = isolate;
@@ -94,7 +94,7 @@
     return e;
   }
 
-  UnlinkedCallViewElement.created() : super.created();
+  UnlinkedCallViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -112,18 +112,19 @@
   void render() {
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
         navMenu('unlinkedcall'),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _unlinkedcall =
-                await _unlinkedcalls.get(_isolate, _unlinkedcall.id);
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _unlinkedcall =
+                    await _unlinkedcalls.get(_isolate, _unlinkedcall.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -131,8 +132,9 @@
           new HeadingElement.h2()..text = 'UnlinkedCall',
           new HRElement(),
           new ObjectCommonElement(_isolate, _unlinkedcall, _retainedSizes,
-              _reachableSizes, _references, _retainingPaths, _objects,
-              queue: _r.queue),
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
           new DivElement()
             ..classes = ['memberList']
             ..children = <Element>[
@@ -164,7 +166,7 @@
                 ]
             ],
           new HRElement(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/elements/view_footer.dart b/runtime/observatory/lib/src/elements/view_footer.dart
index a1a039b..d401bde 100644
--- a/runtime/observatory/lib/src/elements/view_footer.dart
+++ b/runtime/observatory/lib/src/elements/view_footer.dart
@@ -9,7 +9,7 @@
 import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 
-class ViewFooterElement extends HtmlElement implements Renderable {
+class ViewFooterElement extends CustomElement implements Renderable {
   static const tag = const Tag<ViewFooterElement>('view-footer');
 
   RenderingScheduler _r;
@@ -17,12 +17,12 @@
   Stream<RenderedEvent<ViewFooterElement>> get onRendered => _r.onRendered;
 
   factory ViewFooterElement({RenderingQueue queue}) {
-    ViewFooterElement e = document.createElement(tag.name);
+    ViewFooterElement e = new ViewFooterElement.created();
     e._r = new RenderingScheduler<ViewFooterElement>(e, queue: queue);
     return e;
   }
 
-  ViewFooterElement.created() : super.created();
+  ViewFooterElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/vm_connect.dart b/runtime/observatory/lib/src/elements/vm_connect.dart
index c8cac11..576aa76 100644
--- a/runtime/observatory/lib/src/elements/vm_connect.dart
+++ b/runtime/observatory/lib/src/elements/vm_connect.dart
@@ -4,19 +4,19 @@
 
 library vm_connect_element;
 
-import 'dart:html';
 import 'dart:async';
-import 'dart:convert';
+import 'dart:html';
+
 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/helpers/nav_bar.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
 import 'package:observatory/src/elements/nav/notify.dart';
 import 'package:observatory/src/elements/nav/top_menu.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 import 'package:observatory/src/elements/vm_connect_target.dart';
 
-class VMConnectElement extends HtmlElement implements Renderable {
+class VMConnectElement extends CustomElement implements Renderable {
   static const tag =
       const Tag<VMConnectElement>('vm-connect', dependencies: const [
     NavTopMenuElement.tag,
@@ -41,7 +41,7 @@
     assert(address != null);
     assert(notifications != null);
     assert(targets != null);
-    VMConnectElement e = document.createElement(tag.name);
+    VMConnectElement e = new VMConnectElement.created();
     e._r = new RenderingScheduler<VMConnectElement>(e, queue: queue);
     e._address = address;
     e._notifications = notifications;
@@ -49,7 +49,7 @@
     return e;
   }
 
-  VMConnectElement.created() : super.created();
+  VMConnectElement.created() : super.created(tag);
 
   @override
   void attached() {
@@ -71,8 +71,8 @@
     final port = window.location.port;
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered']
@@ -93,10 +93,11 @@
                       final bool current = _targets.isConnectedVMTarget(target);
                       return new LIElement()
                         ..children = <Element>[
-                          new VMConnectTargetElement(target,
-                              current: current, queue: _r.queue)
-                            ..onConnect.listen(_connect)
-                            ..onDelete.listen(_delete)
+                          (new VMConnectTargetElement(target,
+                                  current: current, queue: _r.queue)
+                                ..onConnect.listen(_connect)
+                                ..onDelete.listen(_delete))
+                              .element
                         ];
                     }).toList(),
                   new HRElement(),
@@ -121,7 +122,7 @@
               new DivElement()..classes = ['flex-item-20-percent'],
             ],
         ],
-      new ViewFooterElement(queue: _r.queue)
+      new ViewFooterElement(queue: _r.queue).element
     ];
   }
 
diff --git a/runtime/observatory/lib/src/elements/vm_connect_target.dart b/runtime/observatory/lib/src/elements/vm_connect_target.dart
index 2a2dd81..0f6575b 100644
--- a/runtime/observatory/lib/src/elements/vm_connect_target.dart
+++ b/runtime/observatory/lib/src/elements/vm_connect_target.dart
@@ -14,7 +14,7 @@
   TargetEvent(this.target);
 }
 
-class VMConnectTargetElement extends HtmlElement implements Renderable {
+class VMConnectTargetElement extends CustomElement implements Renderable {
   static const tag = const Tag<VMConnectTargetElement>('vm-connect-target');
 
   RenderingScheduler<VMConnectTargetElement> _r;
@@ -38,14 +38,14 @@
       {bool current: false, RenderingQueue queue}) {
     assert(target != null);
     assert(current != null);
-    VMConnectTargetElement e = document.createElement(tag.name);
+    VMConnectTargetElement e = new VMConnectTargetElement.created();
     e._r = new RenderingScheduler<VMConnectTargetElement>(e, queue: queue);
     e._target = target;
     e._current = current;
     return e;
   }
 
-  VMConnectTargetElement.created() : super.created();
+  VMConnectTargetElement.created() : super.created(tag);
 
   @override
   void attached() {
diff --git a/runtime/observatory/lib/src/elements/vm_view.dart b/runtime/observatory/lib/src/elements/vm_view.dart
index 4e79116..f5f5609 100644
--- a/runtime/observatory/lib/src/elements/vm_view.dart
+++ b/runtime/observatory/lib/src/elements/vm_view.dart
@@ -19,7 +19,7 @@
 import 'package:observatory/src/elements/view_footer.dart';
 import 'package:observatory/utils.dart';
 
-class VMViewElement extends HtmlElement implements Renderable {
+class VMViewElement extends CustomElement implements Renderable {
   static const tag = const Tag<VMViewElement>('vm-view', dependencies: const [
     IsolateSummaryElement.tag,
     NavTopMenuElement.tag,
@@ -60,7 +60,7 @@
     assert(notifications != null);
     assert(isolates != null);
     assert(scripts != null);
-    VMViewElement e = document.createElement(tag.name);
+    VMViewElement e = new VMViewElement.created();
     e._r = new RenderingScheduler<VMViewElement>(e, queue: queue);
     e._vm = vm;
     e._vms = vms;
@@ -71,7 +71,7 @@
     return e;
   }
 
-  VMViewElement.created() : super.created();
+  VMViewElement.created() : super.created(tag);
 
   @override
   attached() {
@@ -100,15 +100,16 @@
     final isolates = _vm.isolates.toList();
     children = <Element>[
       navBar(<Element>[
-        new NavTopMenuElement(queue: _r.queue),
-        new NavVMMenuElement(_vm, _events, queue: _r.queue),
-        new NavRefreshElement(queue: _r.queue)
-          ..onRefresh.listen((e) async {
-            e.element.disabled = true;
-            _vm = await _vms.get(_vm);
-            _r.dirty();
-          }),
-        new NavNotifyElement(_notifications, queue: _r.queue)
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _vm = await _vms.get(_vm);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
       ]),
       new DivElement()
         ..classes = ['content-centered-big']
@@ -291,13 +292,14 @@
                         ..classes = ['list-group-item']
                         ..children = <Element>[
                           new IsolateSummaryElement(
-                              i, _isolates, _events, _scripts,
-                              queue: _r.queue)
+                                  i, _isolates, _events, _scripts,
+                                  queue: _r.queue)
+                              .element
                         ],
                       new HRElement()
                     ])
                 .toList(),
-          new ViewFooterElement(queue: _r.queue)
+          new ViewFooterElement(queue: _r.queue).element
         ]
     ];
   }
diff --git a/runtime/observatory/lib/src/models/objects/function.dart b/runtime/observatory/lib/src/models/objects/function.dart
index 777f57d..098003b 100644
--- a/runtime/observatory/lib/src/models/objects/function.dart
+++ b/runtime/observatory/lib/src/models/objects/function.dart
@@ -13,7 +13,7 @@
   constructor,
   implicitGetter,
   implicitSetter,
-  implicitStaticFinalGetter,
+  implicitStaticGetter,
   staticFieldInitializer,
   irregexpFunction,
   methodExtractor,
@@ -21,6 +21,7 @@
   invokeFieldDispatcher,
   collected,
   native,
+  ffiTrampoline,
   stub,
   tag,
   signatureFunction,
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 99e84be..dace8a9 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1225,7 +1225,7 @@
 
 /// State for a running isolate.
 class Isolate extends ServiceObjectOwner implements M.Isolate {
-  static const kLoggingStream = '_Logging';
+  static const kLoggingStream = 'Logging';
   static const kExtensionStream = 'Extension';
 
   VM get vm => owner;
@@ -2104,7 +2104,7 @@
   static const kInspect = 'Inspect';
   static const kDebuggerSettingsUpdate = '_DebuggerSettingsUpdate';
   static const kConnectionClosed = 'ConnectionClosed';
-  static const kLogging = '_Logging';
+  static const kLogging = 'Logging';
   static const kExtension = 'Extension';
   static const kServiceRegistered = 'ServiceRegistered';
   static const kServiceUnregistered = 'ServiceUnregistered';
@@ -3020,8 +3020,8 @@
       return M.FunctionKind.implicitGetter;
     case 'ImplicitSetter':
       return M.FunctionKind.implicitSetter;
-    case 'ImplicitStaticFinalGetter':
-      return M.FunctionKind.implicitStaticFinalGetter;
+    case 'ImplicitStaticGetter':
+      return M.FunctionKind.implicitStaticGetter;
     case 'StaticFieldInitializer':
       return M.FunctionKind.staticFieldInitializer;
     case 'IrregexpFunction':
@@ -3036,6 +3036,8 @@
       return M.FunctionKind.collected;
     case 'Native':
       return M.FunctionKind.native;
+    case 'FfiTrampoline':
+      return M.FunctionKind.ffiTrampoline;
     case 'Stub':
       return M.FunctionKind.stub;
     case 'Tag':
diff --git a/runtime/observatory/pubspec.yaml b/runtime/observatory/pubspec.yaml
index 76e6219..2059c3d 100644
--- a/runtime/observatory/pubspec.yaml
+++ b/runtime/observatory/pubspec.yaml
@@ -1,3 +1,3 @@
 name: observatory
 environment:
-  sdk: '>=2.0.0 <3.0.0'
+  sdk: '>=2.2.0 <3.0.0'
diff --git a/runtime/observatory/tests/observatory_ui/allocation_profile/element_test.dart b/runtime/observatory/tests/observatory_ui/allocation_profile/element_test.dart
deleted file mode 100644
index 3673da4..0000000
--- a/runtime/observatory/tests/observatory_ui/allocation_profile/element_test.dart
+++ /dev/null
@@ -1,184 +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.
-
-import 'dart:html';
-import 'dart:async';
-import 'package:test/test.dart';
-import 'package:observatory/models.dart' as M;
-import 'package:observatory/src/elements/allocation_profile.dart';
-import 'package:observatory/src/elements/class_ref.dart';
-import 'package:observatory/src/elements/containers/virtual_collection.dart';
-import 'package:observatory/src/elements/nav/refresh.dart';
-import '../mocks.dart';
-
-main() {
-  AllocationProfileElement.tag.ensureRegistration();
-
-  final cTag = ClassRefElement.tag.name;
-  final rTag = NavRefreshElement.tag.name;
-  final vTag = VirtualCollectionElement.tag.name;
-
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notif = new NotificationRepositoryMock();
-  test('instantiation', () {
-    final repo = new AllocationProfileRepositoryMock();
-    final e = new AllocationProfileElement(vm, isolate, events, notif, repo);
-    expect(e, isNotNull, reason: 'element correctly created');
-  });
-  test('elements created', () async {
-    final completer = new Completer<AllocationProfileMock>();
-    final repo = new AllocationProfileRepositoryMock(
-        getter:
-            expectAsync4((M.IsolateRef i, bool gc, bool reset, bool combine) {
-      expect(i, equals(isolate));
-      expect(gc, isFalse);
-      expect(reset, isFalse);
-      expect(combine, isFalse);
-      return completer.future;
-    }, count: 1));
-    final e = new AllocationProfileElement(vm, isolate, events, notif, repo);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelectorAll(vTag).length, isZero);
-    completer.complete(const AllocationProfileMock());
-    await e.onRendered.first;
-    expect(e.querySelectorAll(vTag).length, equals(1));
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-  group('reacts', () {
-    test('to refresh', () async {
-      final completer = new Completer<AllocationProfileMock>();
-      int step = 0;
-      final repo = new AllocationProfileRepositoryMock(
-          getter:
-              expectAsync4((M.IsolateRef i, bool gc, bool reset, bool combine) {
-        expect(i, equals(isolate));
-        expect(combine, isFalse);
-        switch (step) {
-          case 0:
-            expect(gc, isFalse);
-            expect(reset, isFalse);
-            break;
-          case 1:
-            expect(gc, isFalse);
-            expect(reset, isTrue);
-            break;
-          case 2:
-            expect(gc, isTrue);
-            expect(reset, isFalse);
-            break;
-          case 3:
-            expect(gc, isFalse);
-            expect(reset, isFalse);
-            break;
-        }
-        step++;
-        return completer.future;
-      }, count: 4));
-      final e = new AllocationProfileElement(vm, isolate, events, notif, repo);
-      document.body.append(e);
-      await e.onRendered.first;
-      completer.complete(const AllocationProfileMock());
-      await e.onRendered.first;
-      e
-          .querySelectorAll(rTag)
-          .sublist(1, 4)
-          .forEach((e) => (e as NavRefreshElement).refresh());
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-    test('to gc', () async {
-      final events = new EventRepositoryMock();
-      final completer = new Completer<AllocationProfileMock>();
-      int count = 0;
-      final repo = new AllocationProfileRepositoryMock(
-          getter:
-              expectAsync4((M.IsolateRef i, bool gc, bool reset, bool combine) {
-        expect(i, equals(isolate));
-        expect(gc, isFalse);
-        expect(reset, isFalse);
-        expect(combine, isFalse);
-        count++;
-        return completer.future;
-      }, count: 2));
-      final e = new AllocationProfileElement(vm, isolate, events, notif, repo);
-      document.body.append(e);
-      await e.onRendered.first;
-      completer.complete(const AllocationProfileMock());
-      await e.onRendered.first;
-      e.querySelector('input[type=\'checkbox\']').click();
-      expect(events.onGCEventHasListener, isTrue);
-      events.add(new GCEventMock(isolate: isolate));
-      await e.onRendered.first;
-      expect(count, equals(2));
-      // shouldn't trigger
-      events.add(new GCEventMock(isolate: new IsolateRefMock(id: 'another')));
-      await (() async {}());
-      e.querySelector('input[type=\'checkbox\']').click();
-      // shouldn't trigger
-      events.add(new GCEventMock(isolate: isolate));
-      await (() async {}());
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-    test('to sort change', () async {
-      const clazz1 = const ClassRefMock(name: 'class1');
-      const clazz2 = const ClassRefMock(name: 'class2');
-      const clazz3 = const ClassRefMock(name: 'class3');
-      const profile = const AllocationProfileMock(members: const [
-        const ClassHeapStatsMock(clazz: clazz1),
-        const ClassHeapStatsMock(
-            clazz: clazz2,
-            newSpace: const AllocationsMock(
-                current: const AllocationCountMock(bytes: 10)),
-            oldSpace: const AllocationsMock(
-                current: const AllocationCountMock(bytes: 2))),
-        const ClassHeapStatsMock(
-            clazz: clazz3,
-            newSpace: const AllocationsMock(
-                current: const AllocationCountMock(bytes: 5)),
-            oldSpace: const AllocationsMock(
-                current: const AllocationCountMock(bytes: 3)))
-      ]);
-      final completer = new Completer<AllocationProfileMock>();
-      final repo = new AllocationProfileRepositoryMock(
-          getter:
-              expectAsync4((M.IsolateRef i, bool gc, bool reset, bool combine) {
-        expect(i, equals(isolate));
-        expect(gc, isFalse);
-        expect(reset, isFalse);
-        expect(combine, isFalse);
-        return completer.future;
-      }, count: 1));
-      final e = new AllocationProfileElement(vm, isolate, events, notif, repo);
-      document.body.append(e);
-      await e.onRendered.first;
-      completer.complete(profile);
-      await e.onRendered.first;
-      expect((e.querySelector(cTag) as ClassRefElement).cls, equals(clazz2));
-      e.querySelector('button.name').click();
-      await e.onRendered.first;
-      expect((e.querySelector(cTag) as ClassRefElement).cls, equals(clazz1));
-      e.querySelector('button.name').click();
-      await e.onRendered.first;
-      expect((e.querySelector(cTag) as ClassRefElement).cls, equals(clazz3));
-      e.querySelectorAll('button.bytes').last.click();
-      await e.onRendered.first;
-      expect((e.querySelector(cTag) as ClassRefElement).cls, equals(clazz3));
-      e.querySelectorAll('button.bytes').last.click();
-      await e.onRendered.first;
-      expect((e.querySelector(cTag) as ClassRefElement).cls, equals(clazz1));
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/allocation_profile/element_test.html b/runtime/observatory/tests/observatory_ui/allocation_profile/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/allocation_profile/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/app_test.dart b/runtime/observatory/tests/observatory_ui/app_test.dart
new file mode 100644
index 0000000..0fab60c
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/app_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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:logging/logging.dart';
+import 'package:observatory/elements.dart';
+import 'package:stack_trace/stack_trace.dart';
+
+main() async {
+  Chain.capture(() async {
+    Logger.root.level = Level.INFO;
+    Logger.root.onRecord.listen((LogRecord rec) {
+      print('${rec.level.name}: ${rec.time}: ${rec.message}');
+    });
+    Logger.root.info('Starting Observatory');
+    document.body.children
+        .insert(0, new ObservatoryApplicationElement.created().element);
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart
deleted file mode 100644
index 3baccf5..0000000
--- a/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/class_ref.dart';
-import '../mocks.dart';
-
-main() {
-  ClassRefElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock();
-  const cls = const ClassRefMock();
-  test('instantiation', () {
-    final e = new ClassRefElement(isolate, cls);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.cls, equals(cls));
-  });
-  test('elements created after attachment', () async {
-    final e = new ClassRefElement(isolate, cls);
-    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/class_ref/element_test.html b/runtime/observatory/tests/observatory_ui/class_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/class_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/class_tree/element_test.dart b/runtime/observatory/tests/observatory_ui/class_tree/element_test.dart
deleted file mode 100644
index ed05811..0000000
--- a/runtime/observatory/tests/observatory_ui/class_tree/element_test.dart
+++ /dev/null
@@ -1,75 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/class_tree.dart';
-import 'package:observatory/src/elements/nav/notify.dart';
-import '../mocks.dart';
-
-main() {
-  ClassTreeElement.tag.ensureRegistration();
-
-  final nTag = NavNotifyElement.tag.name;
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notifications = new NotificationRepositoryMock();
-
-  group('instantiation', () {
-    test('default', () {
-      final e = new ClassTreeElement(
-          vm, isolate, events, notifications, new ClassRepositoryMock());
-      expect(e, isNotNull, reason: 'element correctly created');
-    });
-  });
-  group('elements', () {
-    test('created after attachment', () async {
-      const child2_id = 'c2-id';
-      const child1_1_id = 'c1_1-id';
-      const child1_id = 'c1-id';
-      const child2 = const ClassMock(id: child2_id);
-      const child1_1 = const ClassMock(id: child1_1_id);
-      const child1 =
-          const ClassMock(id: child1_id, subclasses: const [child1_1]);
-      const object =
-          const ClassMock(id: 'o-id', subclasses: const [child1, child2]);
-      const ids = const [child1_id, child1_1_id, child2_id];
-      bool rendered = false;
-      final e = new ClassTreeElement(
-          vm,
-          isolate,
-          events,
-          notifications,
-          new ClassRepositoryMock(
-              object: expectAsync1((i) async {
-                expect(i, equals(isolate));
-                expect(rendered, isFalse);
-                return object;
-              }, count: 1),
-              getter: expectAsync2((i, id) async {
-                expect(i, equals(isolate));
-                expect(ids.contains(id), isTrue);
-                switch (id) {
-                  case child1_id:
-                    return child1;
-                  case child1_1_id:
-                    return child1_1;
-                  case child2_id:
-                    return child2;
-                  default:
-                    return null;
-                }
-              }, count: 3)));
-      document.body.append(e);
-      await e.onRendered.first;
-      rendered = true;
-      expect(e.children.length, isNonZero, reason: 'has elements');
-      expect(e.querySelectorAll(nTag).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/class_tree/element_test.html b/runtime/observatory/tests/observatory_ui/class_tree/element_test.html
deleted file mode 100644
index bc26958..0000000
--- a/runtime/observatory/tests/observatory_ui/class_tree/element_test.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!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;}
-     class-tree virtual-tree .class-tree-item {
-       line-height: 25px;
-       height: 25px;
-       padding-left: 10%;
-       padding-right: 10%;
-     }
-  </style>
-</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/code_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart
deleted file mode 100644
index 4f9e229..0000000
--- a/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/code_ref.dart';
-import '../mocks.dart';
-
-main() {
-  CodeRefElement.tag.ensureRegistration();
-
-  final isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
-  final code = new CodeRefMock(id: 'c-id', name: 'c-name');
-  test('instantiation', () {
-    final e = new CodeRefElement(isolate, code);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.code, equals(code));
-  });
-  test('elements created after attachment', () async {
-    final e = new CodeRefElement(isolate, code);
-    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/code_ref/element_test.html b/runtime/observatory/tests/observatory_ui/code_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/code_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/context_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/context_ref/element_test.dart
deleted file mode 100644
index 857f99b..0000000
--- a/runtime/observatory/tests/observatory_ui/context_ref/element_test.dart
+++ /dev/null
@@ -1,32 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/context_ref.dart';
-import '../mocks.dart';
-
-main() {
-  ContextRefElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock();
-  const context = const ContextRefMock();
-  final objects = new ObjectRepositoryMock();
-
-  test('instantiation', () {
-    final e = new ContextRefElement(isolate, context, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.context, equals(context));
-  });
-  test('elements created after attachment', () async {
-    final e = new ContextRefElement(isolate, context, objects);
-    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/context_ref/element_test.html b/runtime/observatory/tests/observatory_ui/context_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/context_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/context_view/element_test.dart b/runtime/observatory/tests/observatory_ui/context_view/element_test.dart
deleted file mode 100644
index f2552d3..0000000
--- a/runtime/observatory/tests/observatory_ui/context_view/element_test.dart
+++ /dev/null
@@ -1,55 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/context_view.dart';
-import 'package:observatory/src/elements/nav/refresh.dart';
-import 'package:observatory/src/elements/object_common.dart';
-import '../mocks.dart';
-
-main() {
-  ContextViewElement.tag.ensureRegistration();
-
-  final cTag = ObjectCommonElement.tag.name;
-  final rTag = NavRefreshElement.tag.name;
-
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notifs = new NotificationRepositoryMock();
-  final context = const ContextMock();
-  final contexts = new ContextRepositoryMock();
-  final reachableSizes = new ReachableSizeRepositoryMock();
-  final retainedSizes = new RetainedSizeRepositoryMock();
-  final inbounds = new InboundReferencesRepositoryMock();
-  final paths = new RetainingPathRepositoryMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new ContextViewElement(vm, isolate, context, events, notifs,
-        contexts, retainedSizes, reachableSizes, inbounds, paths, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.context, equals(context));
-  });
-  test('elements created after attachment', () async {
-    final contexts = new ContextRepositoryMock(
-        getter: expectAsync2((i, id) async {
-      expect(i, equals(isolate));
-      expect(id, equals(context.id));
-      return context;
-    }, count: 1));
-    final e = new ContextViewElement(vm, isolate, context, events, notifs,
-        contexts, retainedSizes, reachableSizes, inbounds, paths, objects);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelectorAll(cTag).length, equals(1));
-    (e.querySelector(rTag) as NavRefreshElement).refresh();
-    await e.onRendered.first;
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/context_view/element_test.html b/runtime/observatory/tests/observatory_ui/context_view/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/context_view/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/cpu_profile/element_test.dart b/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.dart
deleted file mode 100644
index a596684..0000000
--- a/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.dart
+++ /dev/null
@@ -1,72 +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.
-
-import 'dart:html';
-import 'dart:async';
-import 'package:test/test.dart';
-import 'package:observatory/models.dart' as M;
-import 'package:observatory/src/elements/cpu_profile.dart';
-import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
-import 'package:observatory/src/elements/stack_trace_tree_config.dart';
-import 'package:observatory/src/elements/sample_buffer_control.dart';
-import '../mocks.dart';
-
-main() {
-  CpuProfileElement.tag.ensureRegistration();
-
-  final sTag = SampleBufferControlElement.tag.name;
-  final cTag = StackTraceTreeConfigElement.tag.name;
-  final tTag = CpuProfileVirtualTreeElement.tag.name;
-
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notifs = new NotificationRepositoryMock();
-  test('instantiation', () {
-    final profiles = new IsolateSampleProfileRepositoryMock();
-    final e = new CpuProfileElement(vm, isolate, events, notifs, profiles);
-    expect(e, isNotNull, reason: 'element correctly created');
-  });
-  test('elements created', () async {
-    final controller =
-        new StreamController<M.SampleProfileLoadingProgressEvent>.broadcast();
-    final profiles = new IsolateSampleProfileRepositoryMock(getter:
-        (M.IsolateRef i, M.SampleProfileTag t, bool clear, bool forceFetch) {
-      expect(i, equals(isolate));
-      expect(t, isNotNull);
-      expect(clear, isFalse);
-      expect(forceFetch, isFalse);
-      return controller.stream;
-    });
-    final e = new CpuProfileElement(vm, isolate, events, notifs, profiles);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelectorAll(sTag).length, isZero);
-    expect(e.querySelectorAll(cTag).length, isZero);
-    expect(e.querySelectorAll(tTag).length, isZero);
-    controller.add(new SampleProfileLoadingProgressEventMock(
-        progress: new SampleProfileLoadingProgressMock(
-            status: M.SampleProfileLoadingStatus.fetching)));
-    await e.onRendered.first;
-    expect(e.querySelectorAll(sTag).length, equals(1));
-    expect(e.querySelectorAll(cTag).length, isZero);
-    expect(e.querySelectorAll(tTag).length, isZero);
-    controller.add(new SampleProfileLoadingProgressEventMock(
-        progress: new SampleProfileLoadingProgressMock(
-            status: M.SampleProfileLoadingStatus.loading)));
-    controller.add(new SampleProfileLoadingProgressEventMock(
-        progress: new SampleProfileLoadingProgressMock(
-            status: M.SampleProfileLoadingStatus.loaded,
-            profile: new SampleProfileMock())));
-    controller.close();
-    await e.onRendered.first;
-    expect(e.querySelectorAll(sTag).length, equals(1));
-    expect(e.querySelectorAll(cTag).length, equals(1));
-    expect(e.querySelectorAll(tTag).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/cpu_profile/element_test.html b/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/cpu_profile/virtual-tree/element_test.dart b/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.dart
deleted file mode 100644
index 1f15445..0000000
--- a/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.dart
+++ /dev/null
@@ -1,53 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/models.dart' as M;
-import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
-import '../../mocks.dart';
-
-main() {
-  CpuProfileVirtualTreeElement.tag.ensureRegistration();
-  const isolate = const IsolateRefMock();
-  group('instantiation', () {
-    final profile = new SampleProfileMock();
-    test('default', () {
-      final e = new CpuProfileVirtualTreeElement(isolate, profile);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.isolate, equals(isolate));
-      expect(e.profile, equals(profile));
-      expect(e.mode, equals(ProfileTreeMode.function));
-      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
-    });
-    test('mode', () {
-      final e = new CpuProfileVirtualTreeElement(isolate, profile,
-          mode: ProfileTreeMode.code);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.isolate, equals(isolate));
-      expect(e.profile, equals(profile));
-      expect(e.mode, equals(ProfileTreeMode.code));
-      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
-    });
-    test('direction', () {
-      final e = new CpuProfileVirtualTreeElement(isolate, profile,
-          direction: M.ProfileTreeDirection.inclusive);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.isolate, equals(isolate));
-      expect(e.profile, equals(profile));
-      expect(e.mode, equals(ProfileTreeMode.function));
-      expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
-    });
-  });
-  test('elements created after attachment', () async {
-    final profile = new SampleProfileMock();
-    final e = new CpuProfileVirtualTreeElement(isolate, profile);
-    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/cpu_profile/virtual-tree/element_test.html b/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/cpu_profile_table/element_test.dart b/runtime/observatory/tests/observatory_ui/cpu_profile_table/element_test.dart
deleted file mode 100644
index 9857f12..0000000
--- a/runtime/observatory/tests/observatory_ui/cpu_profile_table/element_test.dart
+++ /dev/null
@@ -1,72 +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.
-
-import 'dart:html';
-import 'dart:async';
-import 'package:test/test.dart';
-import 'package:observatory/models.dart' as M;
-import 'package:observatory/src/elements/cpu_profile_table.dart';
-import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
-import 'package:observatory/src/elements/stack_trace_tree_config.dart';
-import 'package:observatory/src/elements/sample_buffer_control.dart';
-import '../mocks.dart';
-
-main() {
-  CpuProfileTableElement.tag.ensureRegistration();
-
-  final sTag = SampleBufferControlElement.tag.name;
-  final cTag = StackTraceTreeConfigElement.tag.name;
-  final tTag = CpuProfileVirtualTreeElement.tag.name;
-
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notifs = new NotificationRepositoryMock();
-  test('instantiation', () {
-    final profiles = new IsolateSampleProfileRepositoryMock();
-    final e = new CpuProfileTableElement(vm, isolate, events, notifs, profiles);
-    expect(e, isNotNull, reason: 'element correctly created');
-  });
-  test('elements created', () async {
-    final controller =
-        new StreamController<M.SampleProfileLoadingProgressEvent>.broadcast();
-    final profiles = new IsolateSampleProfileRepositoryMock(getter:
-        (M.IsolateRef i, M.SampleProfileTag t, bool clear, bool forceFetch) {
-      expect(i, equals(isolate));
-      expect(t, isNotNull);
-      expect(clear, isFalse);
-      expect(forceFetch, isFalse);
-      return controller.stream;
-    });
-    final e = new CpuProfileTableElement(vm, isolate, events, notifs, profiles);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelectorAll(sTag).length, isZero);
-    expect(e.querySelectorAll(cTag).length, isZero);
-    expect(e.querySelectorAll(tTag).length, isZero);
-    controller.add(new SampleProfileLoadingProgressEventMock(
-        progress: new SampleProfileLoadingProgressMock(
-            status: M.SampleProfileLoadingStatus.fetching)));
-    await e.onRendered.first;
-    expect(e.querySelectorAll(sTag).length, equals(1));
-    expect(e.querySelectorAll(cTag).length, isZero);
-    expect(e.querySelectorAll(tTag).length, isZero);
-    controller.add(new SampleProfileLoadingProgressEventMock(
-        progress: new SampleProfileLoadingProgressMock(
-            status: M.SampleProfileLoadingStatus.loading)));
-    controller.add(new SampleProfileLoadingProgressEventMock(
-        progress: new SampleProfileLoadingProgressMock(
-            status: M.SampleProfileLoadingStatus.loaded,
-            profile: new SampleProfileMock())));
-    controller.close();
-    await e.onRendered.first;
-    expect(e.querySelectorAll(sTag).length, equals(1));
-    expect(e.querySelectorAll(cTag).length, equals(1));
-    expect(e.querySelectorAll(tTag).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/cpu_profile_table/element_test.html b/runtime/observatory/tests/observatory_ui/cpu_profile_table/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/cpu_profile_table/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/curly_block/element_test.dart b/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart
deleted file mode 100644
index e647e5f..0000000
--- a/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart
+++ /dev/null
@@ -1,176 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/curly_block.dart';
-
-main() {
-  CurlyBlockElement.tag.ensureRegistration();
-
-  group('instantiation', () {
-    test('default', () {
-      final e = new CurlyBlockElement();
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.expanded, isFalse);
-      expect(e.disabled, isFalse);
-    });
-    test('not expanded', () {
-      final 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 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 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 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 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 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 e = new CurlyBlockElement(disabled: false);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.expanded, isFalse);
-      expect(e.disabled, isFalse);
-    });
-    test('disabled', () {
-      final 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 e = new CurlyBlockElement();
-    expect(e.children, isEmpty, reason: 'is empty');
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children, isNotEmpty, reason: 'has elements');
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children, isEmpty, reason: 'is empty');
-  });
-  group('content', () {
-    CurlyBlockElement e;
-    setUp(() async {
-      e = new CurlyBlockElement();
-      e.content = <Element>[document.createElement('content')];
-      document.body.append(e);
-      await e.onRendered.first;
-    });
-    tearDown(() {
-      e.remove();
-    });
-    test('toggles visibility', () async {
-      expect(e.querySelector('content'), isNull);
-      e.toggle();
-      await e.onRendered.first;
-      expect(e.querySelector('content'), isNotNull);
-      e.toggle();
-      await e.onRendered.first;
-      expect(e.querySelector('content'), isNull);
-      e.remove();
-    });
-    test('toggles visibility (manually)', () async {
-      expect(e.querySelector('content'), isNull);
-      e.expanded = true;
-      await e.onRendered.first;
-      expect(e.querySelector('content'), isNotNull);
-      e.expanded = false;
-      await e.onRendered.first;
-      expect(e.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.querySelector('content'), isNull);
-      e.toggle();
-      await e.onRendered.first;
-      expect(e.expanded, isFalse);
-      expect(e.querySelector('content'), isNull);
-      e.disabled = false;
-      e.toggle();
-      await e.onRendered.first;
-      expect(e.expanded, isTrue);
-      expect(e.querySelector('content'), isNotNull);
-      e.disabled = true;
-      e.toggle();
-      await e.onRendered.first;
-      expect(e.expanded, isTrue);
-      expect(e.querySelector('content'), isNotNull);
-      e.remove();
-    });
-    test('toggles visibility (manually) if disabled', () async {
-      e.disabled = true;
-      await e.onRendered.first;
-      expect(e.querySelector('content'), isNull);
-      e.expanded = true;
-      await e.onRendered.first;
-      expect(e.querySelector('content'), isNotNull);
-      e.expanded = false;
-      await e.onRendered.first;
-      expect(e.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(expectAsync1((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(expectAsync1((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(expectAsync1((_) {}, 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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/curly_block/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/error_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart
deleted file mode 100644
index 867b5f2..0000000
--- a/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/error_ref.dart';
-import '../mocks.dart';
-
-main() {
-  ErrorRefElement.tag.ensureRegistration();
-
-  final ref = new ErrorRefMock(id: 'id', message: 'fixed-error-m');
-  test('instantiation', () {
-    final ErrorRefElement e = new ErrorRefElement(ref);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.error, equals(ref));
-  });
-  test('elements created after attachment', () async {
-    final ErrorRefElement e = new ErrorRefElement(ref);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.innerHtml.contains(ref.message), isTrue,
-        reason: 'no message in the component');
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/error_ref/element_test.html b/runtime/observatory/tests/observatory_ui/error_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/error_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/error_view/element_test.dart b/runtime/observatory/tests/observatory_ui/error_view/element_test.dart
deleted file mode 100644
index e69fec7..0000000
--- a/runtime/observatory/tests/observatory_ui/error_view/element_test.dart
+++ /dev/null
@@ -1,29 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/error_view.dart';
-import '../mocks.dart';
-
-main() {
-  ErrorViewElement.tag.ensureRegistration();
-
-  final notifs = new NotificationRepositoryMock();
-  final error = const ErrorMock();
-  test('instantiation', () {
-    final e = new ErrorViewElement(notifs, error);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.error, equals(error));
-  });
-  test('elements created after attachment', () async {
-    final e = new ErrorViewElement(notifs, error);
-    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/error_view/element_test.html b/runtime/observatory/tests/observatory_ui/error_view/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/error_view/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/field_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/field_ref/element_test.dart
deleted file mode 100644
index 75df874..0000000
--- a/runtime/observatory/tests/observatory_ui/field_ref/element_test.dart
+++ /dev/null
@@ -1,51 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/models.dart' as M;
-import 'package:observatory/src/elements/field_ref.dart';
-import 'package:observatory/src/elements/instance_ref.dart';
-import '../mocks.dart';
-
-main() {
-  FieldRefElement.tag.ensureRegistration();
-
-  final iTag = InstanceRefElement.tag.name;
-
-  const isolate = const IsolateRefMock();
-  const field = const FieldRefMock();
-  const declaredType =
-      const InstanceMock(kind: M.InstanceKind.type, name: 'CustomObject');
-  const field_non_dynamic = const FieldRefMock(declaredType: declaredType);
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new FieldRefElement(isolate, field, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.field, equals(field));
-  });
-  group('elements', () {
-    test('created after attachment (dynamic)', () async {
-      final e = new FieldRefElement(isolate, field, objects);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.children.length, isNonZero, reason: 'has elements');
-      expect(e.querySelectorAll(iTag).length, isZero);
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-    test('created after attachment (non dynamic)', () async {
-      final e = new FieldRefElement(isolate, field_non_dynamic, objects);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.children.length, isNonZero, reason: 'has elements');
-      expect(e.querySelectorAll(iTag).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/field_ref/element_test.html b/runtime/observatory/tests/observatory_ui/field_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/field_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/flag_list/element_test.dart b/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
deleted file mode 100644
index 023f08a..0000000
--- a/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
+++ /dev/null
@@ -1,59 +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.
-
-import 'dart:html';
-import 'package:observatory/models.dart' as M;
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/flag_list.dart';
-import 'package:observatory/src/elements/nav/notify.dart';
-import '../mocks.dart';
-
-main() {
-  FlagListElement.tag.ensureRegistration();
-
-  final nTag = NavNotifyElement.tag.name;
-  const vm = const VMMock();
-  final events = new EventRepositoryMock();
-  final notifications = new NotificationRepositoryMock();
-
-  group('instantiation', () {
-    test('default', () {
-      final e = new FlagListElement(
-          vm, events, new FlagsRepositoryMock(), notifications);
-      expect(e, isNotNull, reason: 'element correctly created');
-    });
-  });
-  group('elements', () {
-    test('created after attachment', () async {
-      const modified = const [
-        const FlagMock(name: 'f1', comment: 'c1', modified: true),
-      ];
-      const unmodifed = const [
-        const FlagMock(name: 'f2', comment: 'c2', modified: false),
-        const FlagMock(name: 'f3', comment: 'c3', modified: false),
-      ];
-      final flags = <M.Flag>[]..addAll(modified)..addAll(unmodifed);
-      final repository = new FlagsRepositoryMock(list: flags);
-      final e = new FlagListElement(vm, events, repository, notifications);
-      document.body.append(e);
-      expect(repository.isListInvoked, isFalse);
-      await e.onRendered.first;
-      expect(repository.isListInvoked, isTrue);
-      expect(e.children.length, isNonZero, reason: 'has elements');
-      expect(e.querySelectorAll(nTag).length, equals(1));
-      expect(e.querySelectorAll('.flag').length, equals(flags.length));
-      expect(
-          e.querySelectorAll('.flag.modified').length, equals(modified.length));
-      expect(e.querySelectorAll('.flag.unmodified').length,
-          equals(unmodifed.length));
-      expect(e.querySelectorAll('.flag').length, equals(flags.length));
-      expect(e.querySelectorAll('.comment').length, equals(flags.length));
-      expect(e.querySelectorAll('.name').length, equals(flags.length));
-      expect(e.querySelectorAll('.value').length, equals(flags.length));
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/flag_list/element_test.html b/runtime/observatory/tests/observatory_ui/flag_list/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/flag_list/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/function_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart
deleted file mode 100644
index 516b9d5..0000000
--- a/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/function_ref.dart';
-import '../mocks.dart';
-
-main() {
-  FunctionRefElement.tag.ensureRegistration();
-
-  final isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
-  final function = new FunctionRefMock(id: 'f-id', name: 'f-name');
-  test('instantiation', () {
-    final e = new FunctionRefElement(isolate, function);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.function, equals(function));
-  });
-  test('elements created after attachment', () async {
-    final e = new FunctionRefElement(isolate, function);
-    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/function_ref/element_test.html b/runtime/observatory/tests/observatory_ui/function_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/function_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/general_error/element_test.dart b/runtime/observatory/tests/observatory_ui/general_error/element_test.dart
deleted file mode 100644
index 2509c92..0000000
--- a/runtime/observatory/tests/observatory_ui/general_error/element_test.dart
+++ /dev/null
@@ -1,61 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/general_error.dart';
-import 'package:observatory/src/elements/nav/notify.dart';
-import '../mocks.dart';
-
-main() {
-  GeneralErrorElement.tag.ensureRegistration();
-
-  final nTag = NavNotifyElement.tag.name;
-  final notifications = new NotificationRepositoryMock();
-  final String message = 'content-of-the-message';
-
-  group('instantiation', () {
-    test('default', () {
-      final GeneralErrorElement e = new GeneralErrorElement(notifications);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.message, isNotNull, reason: 'message should not be null');
-      expect(e.message, equals(''), reason: 'message should be empty');
-    });
-    test('message', () {
-      final GeneralErrorElement e =
-          new GeneralErrorElement(notifications, message: message);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.message, isNotNull, reason: 'message should not be null');
-      expect(e.message, equals(message), reason: 'message should be the same');
-    });
-  });
-  group('elements', () {
-    test('created after attachment', () async {
-      final GeneralErrorElement e = new GeneralErrorElement(notifications);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.children.length, isNonZero, reason: 'has elements');
-      expect(e.querySelectorAll(nTag).length, equals(1));
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-    test('react to message change', () async {
-      final GeneralErrorElement e = new GeneralErrorElement(notifications);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.innerHtml.contains(message), isFalse,
-          reason: 'should not contain');
-      e.message = message;
-      await e.onRendered.first;
-      expect(e.innerHtml.contains(message), isTrue, reason: 'should contain');
-      e.message = '';
-      await e.onRendered.first;
-      expect(e.innerHtml.contains(message), isFalse,
-          reason: 'should not contain');
-      e.remove();
-      await e.onRendered.first;
-    });
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/general_error/element_test.html b/runtime/observatory/tests/observatory_ui/general_error/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/general_error/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/heap_snapshot/element_test.dart b/runtime/observatory/tests/observatory_ui/heap_snapshot/element_test.dart
deleted file mode 100644
index 1907d27..0000000
--- a/runtime/observatory/tests/observatory_ui/heap_snapshot/element_test.dart
+++ /dev/null
@@ -1,63 +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.
-
-import 'dart:html';
-import 'dart:async';
-import 'package:test/test.dart';
-import 'package:observatory/models.dart' as M;
-import 'package:observatory/src/elements/containers/virtual_tree.dart';
-import 'package:observatory/src/elements/heap_snapshot.dart';
-import '../mocks.dart';
-
-main() {
-  HeapSnapshotElement.tag.ensureRegistration();
-
-  final tTag = VirtualTreeElement.tag.name;
-
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notifs = new NotificationRepositoryMock();
-  final snapshots = new HeapSnapshotRepositoryMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new HeapSnapshotElement(
-        vm, isolate, events, notifs, snapshots, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-  });
-  test('elements created', () async {
-    final controller =
-        new StreamController<M.HeapSnapshotLoadingProgressEvent>.broadcast();
-    final snapshots =
-        new HeapSnapshotRepositoryMock(getter: (M.IsolateRef i, bool gc) {
-      expect(i, equals(isolate));
-      expect(gc, isFalse);
-      return controller.stream;
-    });
-    final e = new HeapSnapshotElement(
-        vm, isolate, events, notifs, snapshots, objects);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelectorAll(tTag).length, isZero);
-    controller.add(const HeapSnapshotLoadingProgressEventMock(
-        progress: const HeapSnapshotLoadingProgressMock(
-            status: M.HeapSnapshotLoadingStatus.fetching)));
-    await e.onRendered.first;
-    expect(e.querySelectorAll(tTag).length, isZero);
-    controller.add(const HeapSnapshotLoadingProgressEventMock(
-        progress: const HeapSnapshotLoadingProgressMock(
-            status: M.HeapSnapshotLoadingStatus.loading)));
-    controller.add(new HeapSnapshotLoadingProgressEventMock(
-        progress: new HeapSnapshotLoadingProgressMock(
-            status: M.HeapSnapshotLoadingStatus.loaded,
-            snapshot: new HeapSnapshotMock(timestamp: new DateTime.now()))));
-    controller.close();
-    await e.onRendered.first;
-    expect(e.querySelectorAll(tTag).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/heap_snapshot/element_test.html b/runtime/observatory/tests/observatory_ui/heap_snapshot/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/heap_snapshot/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/icdata_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/icdata_ref/element_test.dart
deleted file mode 100644
index 263c4fb..0000000
--- a/runtime/observatory/tests/observatory_ui/icdata_ref/element_test.dart
+++ /dev/null
@@ -1,31 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/instance_ref.dart';
-import '../mocks.dart';
-
-main() {
-  InstanceRefElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock();
-  const instance = const InstanceRefMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new InstanceRefElement(isolate, instance, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.instance, equals(instance));
-  });
-  test('elements created after attachment', () async {
-    final e = new InstanceRefElement(isolate, instance, objects);
-    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/icdata_ref/element_test.html b/runtime/observatory/tests/observatory_ui/icdata_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/icdata_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/icdata_view/element_test.dart b/runtime/observatory/tests/observatory_ui/icdata_view/element_test.dart
deleted file mode 100644
index 3e4907b..0000000
--- a/runtime/observatory/tests/observatory_ui/icdata_view/element_test.dart
+++ /dev/null
@@ -1,55 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/icdata_view.dart';
-import 'package:observatory/src/elements/nav/refresh.dart';
-import 'package:observatory/src/elements/object_common.dart';
-import '../mocks.dart';
-
-main() {
-  ICDataViewElement.tag.ensureRegistration();
-
-  final cTag = ObjectCommonElement.tag.name;
-  final rTag = NavRefreshElement.tag.name;
-
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notifs = new NotificationRepositoryMock();
-  final icdata = const ICDataMock();
-  final icdatas = new ICDataRepositoryMock();
-  final reachableSizes = new ReachableSizeRepositoryMock();
-  final retainedSizes = new RetainedSizeRepositoryMock();
-  final inbounds = new InboundReferencesRepositoryMock();
-  final paths = new RetainingPathRepositoryMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new ICDataViewElement(vm, isolate, icdata, events, notifs,
-        icdatas, retainedSizes, reachableSizes, inbounds, paths, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.icdata, equals(icdata));
-  });
-  test('elements created after attachment', () async {
-    final icdatas = new ICDataRepositoryMock(
-        getter: expectAsync2((i, id) async {
-      expect(i, equals(isolate));
-      expect(id, equals(icdata.id));
-      return icdata;
-    }, count: 1));
-    final e = new ICDataViewElement(vm, isolate, icdata, events, notifs,
-        icdatas, retainedSizes, reachableSizes, inbounds, paths, objects);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelectorAll(cTag).length, equals(1));
-    (e.querySelector(rTag) as NavRefreshElement).refresh();
-    await e.onRendered.first;
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/icdata_view/element_test.html b/runtime/observatory/tests/observatory_ui/icdata_view/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/icdata_view/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/inbound_references/element_test.dart b/runtime/observatory/tests/observatory_ui/inbound_references/element_test.dart
deleted file mode 100644
index aa0eac2..0000000
--- a/runtime/observatory/tests/observatory_ui/inbound_references/element_test.dart
+++ /dev/null
@@ -1,57 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/curly_block.dart';
-import 'package:observatory/src/elements/inbound_references.dart';
-import 'package:observatory/src/elements/instance_ref.dart';
-import '../mocks.dart';
-
-main() {
-  InboundReferencesElement.tag.ensureRegistration();
-
-  final cTag = CurlyBlockElement.tag.name;
-  final iTag = InstanceRefElement.tag.name;
-  final rTag = InboundReferencesElement.tag.name;
-
-  const isolate = const IsolateRefMock();
-  const object = const InstanceRefMock();
-  final inbounds = new InboundReferencesRepositoryMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new InboundReferencesElement(isolate, object, inbounds, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.object, equals(object));
-  });
-  test('elements created after attachment', () async {
-    const source = const InstanceRefMock(id: 'source-id', name: 'source_name');
-    const references = const InboundReferencesMock(
-        elements: const [const InboundReferenceMock(source: source)]);
-    bool invoked = false;
-    final inbounds = new InboundReferencesRepositoryMock(
-        getter: expectAsync2((i, id) async {
-      expect(i, equals(isolate));
-      expect(id, equals(object.id));
-      invoked = true;
-      return references;
-    }, count: 1));
-    final objects = new ObjectRepositoryMock();
-    final e = new InboundReferencesElement(isolate, object, inbounds, objects);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(invoked, isFalse);
-    expect(e.children, isNotEmpty, reason: 'has elements');
-    expect(e.querySelectorAll(iTag).length, isZero);
-    (e.querySelector(cTag) as CurlyBlockElement).toggle();
-    await e.onRendered.first;
-    expect(invoked, isTrue);
-    expect(e.querySelectorAll(iTag).length, equals(1));
-    expect(e.querySelectorAll(rTag).length, equals(1));
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children, isEmpty, reason: 'is empty');
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/inbound_references/element_test.html b/runtime/observatory/tests/observatory_ui/inbound_references/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/inbound_references/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/instance_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/instance_ref/element_test.dart
deleted file mode 100644
index bbec367..0000000
--- a/runtime/observatory/tests/observatory_ui/instance_ref/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/icdata_ref.dart';
-import '../mocks.dart';
-
-main() {
-  ICDataRefElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock();
-  const icdata = const ICDataRefMock();
-  test('instantiation', () {
-    final e = new ICDataRefElement(isolate, icdata);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.icdata, equals(icdata));
-  });
-  test('elements created after attachment', () async {
-    final e = new ICDataRefElement(isolate, icdata);
-    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/instance_ref/element_test.html b/runtime/observatory/tests/observatory_ui/instance_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/instance_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/isolate/counter_chart/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.dart
deleted file mode 100644
index af3b05f..0000000
--- a/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.dart
+++ /dev/null
@@ -1,25 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/isolate/counter_chart.dart';
-
-main() {
-  IsolateCounterChartElement.tag.ensureRegistration();
-
-  test('instantiation', () {
-    final e = new IsolateCounterChartElement({});
-    expect(e, isNotNull, reason: 'element correctly created');
-  });
-  test('elements created', () async {
-    final e = new IsolateCounterChartElement({});
-    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/isolate/counter_chart/element_test.html b/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/isolate/isolate-shared-summary/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.dart
deleted file mode 100644
index fbbfaf1..0000000
--- a/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.dart
+++ /dev/null
@@ -1,32 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/isolate/counter_chart.dart';
-import 'package:observatory/src/elements/isolate/shared_summary.dart';
-import '../../mocks.dart';
-
-main() {
-  IsolateSharedSummaryElement.tag.ensureRegistration();
-
-  final cTag = IsolateCounterChartElement.tag.name;
-
-  const isolate = const IsolateMock();
-  final events = new EventRepositoryMock();
-  test('instantiation', () {
-    final e = new IsolateSharedSummaryElement(isolate, events);
-    expect(e, isNotNull, reason: 'element correctly created');
-  });
-  test('elements created', () async {
-    final e = new IsolateSharedSummaryElement(isolate, events);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelectorAll(cTag).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/isolate/isolate-shared-summary/element_test.html b/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/isolate_reconnect/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.dart
deleted file mode 100644
index 10ba984..0000000
--- a/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.dart
+++ /dev/null
@@ -1,83 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/isolate_reconnect.dart';
-import 'package:observatory/src/elements/nav/notify.dart';
-import '../mocks.dart';
-
-main() {
-  IsolateReconnectElement.tag.ensureRegistration();
-
-  final nTag = NavNotifyElement.tag.name;
-
-  EventRepositoryMock events;
-  NotificationRepositoryMock notifications;
-  Uri uri;
-  const vm = const VMMock(isolates: const [
-    const IsolateMock(id: 'i-1-id'),
-    const IsolateMock(id: 'i-2-id')
-  ]);
-  const missing = 'missing-id';
-  setUp(() {
-    events = new EventRepositoryMock();
-    notifications = new NotificationRepositoryMock();
-    uri = new Uri(path: 'path');
-  });
-  test('instantiation', () {
-    final e =
-        new IsolateReconnectElement(vm, events, notifications, missing, uri);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.vm, equals(vm));
-    expect(e.missing, equals(missing));
-    expect(e.uri, equals(uri));
-  });
-  test('elements created after attachment', () async {
-    final e =
-        new IsolateReconnectElement(vm, events, notifications, missing, uri);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelector(nTag), isNotNull, reason: 'has notifications');
-    expect(
-        e.querySelectorAll('.isolate-link').length, equals(vm.isolates.length),
-        reason: 'has links');
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-  group('updates', () {
-    test('are correctly listen', () async {
-      final e =
-          new IsolateReconnectElement(vm, events, notifications, missing, uri);
-      expect(events.onVMUpdateHasListener, isFalse);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(events.onVMUpdateHasListener, isTrue);
-      e.remove();
-      await e.onRendered.first;
-      expect(events.onVMUpdateHasListener, isFalse);
-    });
-    test('have effects', () async {
-      final e =
-          new IsolateReconnectElement(vm, events, notifications, missing, uri);
-      const vm2 = const VMMock(isolates: const [
-        const IsolateMock(id: 'i-1-id'),
-        const IsolateMock(id: 'i-2-id'),
-        const IsolateMock(id: 'i-3-id')
-      ]);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.querySelectorAll('.isolate-link').length,
-          equals(vm.isolates.length));
-      events.add(new VMUpdateEventMock(vm: vm2));
-      await e.onRendered.first;
-      expect(e.querySelectorAll('.isolate-link').length,
-          equals(vm2.isolates.length));
-      e.remove();
-      await e.onRendered.first;
-    });
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.html b/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/isolate_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart
deleted file mode 100644
index 7dd81cc..0000000
--- a/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart
+++ /dev/null
@@ -1,60 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/isolate_ref.dart';
-import '../mocks.dart';
-
-main() {
-  IsolateRefElement.tag.ensureRegistration();
-
-  final ref = new IsolateRefMock(id: 'id', name: 'old-name');
-  final events = new EventRepositoryMock();
-  final obj = new IsolateMock(id: 'id', name: 'new-name');
-  group('instantiation', () {
-    test('IsolateRef', () {
-      final e = new IsolateRefElement(ref, events);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.isolate, equals(ref));
-    });
-    test('Isolate', () {
-      final e = new IsolateRefElement(obj, events);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.isolate, equals(obj));
-    });
-  });
-  test('elements created after attachment', () async {
-    final e = new IsolateRefElement(ref, events);
-    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('updates', () {
-    test('are correctly listen', () async {
-      final e = new IsolateRefElement(ref, events);
-      expect(events.onIsolateUpdateHasListener, isFalse);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(events.onIsolateUpdateHasListener, isTrue);
-      e.remove();
-      await e.onRendered.first;
-      expect(events.onIsolateUpdateHasListener, isFalse);
-    });
-    test('have effects', () async {
-      final e = new IsolateRefElement(ref, events);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.innerHtml.contains(ref.id), isTrue);
-      events.add(new IsolateUpdateEventMock(isolate: obj));
-      await e.onRendered.first;
-      expect(e.innerHtml.contains(ref.name), isFalse);
-      expect(e.innerHtml.contains(obj.name), isTrue);
-      e.remove();
-    });
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.html b/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/library_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart
deleted file mode 100644
index 53d176d..0000000
--- a/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/library_ref.dart';
-import '../mocks.dart';
-
-main() {
-  LibraryRefElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock(id: 'i-id', name: 'i-name');
-  const library = const LibraryRefMock(id: 'c-id', name: 'c-name');
-  test('instantiation', () {
-    final e = new LibraryRefElement(isolate, library);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.library, equals(library));
-  });
-  test('elements created after attachment', () async {
-    final e = new LibraryRefElement(isolate, library);
-    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/library_ref/element_test.html b/runtime/observatory/tests/observatory_ui/library_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/library_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/local_var_descriptor_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/local_var_descriptor_ref/element_test.dart
deleted file mode 100644
index eeae150..0000000
--- a/runtime/observatory/tests/observatory_ui/local_var_descriptor_ref/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/local_var_descriptors_ref.dart';
-import '../mocks.dart';
-
-main() {
-  LocalVarDescriptorsRefElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock();
-  const localVar = const LocalVarDescriptorsRefMock();
-  test('instantiation', () {
-    final e = new LocalVarDescriptorsRefElement(isolate, localVar);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.localVar, equals(localVar));
-  });
-  test('elements created after attachment', () async {
-    final e = new LocalVarDescriptorsRefElement(isolate, localVar);
-    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/local_var_descriptor_ref/element_test.html b/runtime/observatory/tests/observatory_ui/local_var_descriptor_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/local_var_descriptor_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/megamorphiccache_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/megamorphiccache_ref/element_test.dart
deleted file mode 100644
index 7a48808..0000000
--- a/runtime/observatory/tests/observatory_ui/megamorphiccache_ref/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/megamorphiccache_ref.dart';
-import '../mocks.dart';
-
-main() {
-  MegamorphicCacheRefElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock();
-  const cache = const MegamorphicCacheRefMock();
-  test('instantiation', () {
-    final e = new MegamorphicCacheRefElement(isolate, cache);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.cache, equals(cache));
-  });
-  test('elements created after attachment', () async {
-    final e = new MegamorphicCacheRefElement(isolate, cache);
-    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/megamorphiccache_ref/element_test.html b/runtime/observatory/tests/observatory_ui/megamorphiccache_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/megamorphiccache_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/megamorphiccache_view/element_test.dart b/runtime/observatory/tests/observatory_ui/megamorphiccache_view/element_test.dart
deleted file mode 100644
index 81dc1cd..0000000
--- a/runtime/observatory/tests/observatory_ui/megamorphiccache_view/element_test.dart
+++ /dev/null
@@ -1,75 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/megamorphiccache_view.dart';
-import 'package:observatory/src/elements/nav/refresh.dart';
-import 'package:observatory/src/elements/object_common.dart';
-import '../mocks.dart';
-
-main() {
-  MegamorphicCacheViewElement.tag.ensureRegistration();
-
-  final cTag = ObjectCommonElement.tag.name;
-  final rTag = NavRefreshElement.tag.name;
-
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notifs = new NotificationRepositoryMock();
-  final cache = const MegamorphicCacheMock();
-  final caches = new MegamorphicCacheRepositoryMock();
-  final reachableSizes = new ReachableSizeRepositoryMock();
-  final retainedSizes = new RetainedSizeRepositoryMock();
-  final inbounds = new InboundReferencesRepositoryMock();
-  final paths = new RetainingPathRepositoryMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new MegamorphicCacheViewElement(
-        vm,
-        isolate,
-        cache,
-        events,
-        notifs,
-        caches,
-        retainedSizes,
-        reachableSizes,
-        inbounds,
-        paths,
-        objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.cache, equals(cache));
-  });
-  test('elements created after attachment', () async {
-    final caches = new MegamorphicCacheRepositoryMock(
-        getter: expectAsync2((i, id) async {
-      expect(i, equals(isolate));
-      expect(id, equals(cache.id));
-      return cache;
-    }, count: 1));
-    final e = new MegamorphicCacheViewElement(
-        vm,
-        isolate,
-        cache,
-        events,
-        notifs,
-        caches,
-        retainedSizes,
-        reachableSizes,
-        inbounds,
-        paths,
-        objects);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelectorAll(cTag).length, equals(1));
-    (e.querySelector(rTag) as NavRefreshElement).refresh();
-    await e.onRendered.first;
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/megamorphiccache_view/element_test.html b/runtime/observatory/tests/observatory_ui/megamorphiccache_view/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/megamorphiccache_view/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/mocks.dart b/runtime/observatory/tests/observatory_ui/mocks.dart
deleted file mode 100644
index 23efa86..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks.dart
+++ /dev/null
@@ -1,71 +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 mocks;
-
-import 'dart:async';
-
-import 'package:observatory/models.dart' as M;
-
-part 'mocks/exceptions/connection_exception.dart';
-
-part 'mocks/objects/allocation_profile.dart';
-part 'mocks/objects/error.dart';
-part 'mocks/objects/code.dart';
-part 'mocks/objects/context.dart';
-part 'mocks/objects/event.dart';
-part 'mocks/objects/class.dart';
-part 'mocks/objects/field.dart';
-part 'mocks/objects/flag.dart';
-part 'mocks/objects/function.dart';
-part 'mocks/objects/guarded.dart';
-part 'mocks/objects/heap_snapshot.dart';
-part 'mocks/objects/heap_space.dart';
-part 'mocks/objects/icdata.dart';
-part 'mocks/objects/inbound_references.dart';
-part 'mocks/objects/instance.dart';
-part 'mocks/objects/isolate.dart';
-part 'mocks/objects/library.dart';
-part 'mocks/objects/local_var_descriptors.dart';
-part 'mocks/objects/megamorphiccache.dart';
-part 'mocks/objects/notification.dart';
-part 'mocks/objects/objectpool.dart';
-part 'mocks/objects/objectstore.dart';
-part 'mocks/objects/pc_descriptors.dart';
-part 'mocks/objects/persistent_handles.dart';
-part 'mocks/objects/ports.dart';
-part 'mocks/objects/retaining_path.dart';
-part 'mocks/objects/sample_profile.dart';
-part 'mocks/objects/script.dart';
-part 'mocks/objects/sentinel.dart';
-part 'mocks/objects/source_location.dart';
-part 'mocks/objects/target.dart';
-part 'mocks/objects/unknown.dart';
-part 'mocks/objects/vm.dart';
-
-part 'mocks/repositories/allocation_profile.dart';
-part 'mocks/repositories/class.dart';
-part 'mocks/repositories/context.dart';
-part 'mocks/repositories/event.dart';
-part 'mocks/repositories/eval.dart';
-part 'mocks/repositories/field.dart';
-part 'mocks/repositories/flag.dart';
-part 'mocks/repositories/heap_snapshot.dart';
-part 'mocks/repositories/icdata.dart';
-part 'mocks/repositories/inbound_references.dart';
-part 'mocks/repositories/instance.dart';
-part 'mocks/repositories/library.dart';
-part 'mocks/repositories/megamorphiccache.dart';
-part 'mocks/repositories/notification.dart';
-part 'mocks/repositories/object.dart';
-part 'mocks/repositories/objectpool.dart';
-part 'mocks/repositories/objectstore.dart';
-part 'mocks/repositories/ports.dart';
-part 'mocks/repositories/persistent_handles.dart';
-part 'mocks/repositories/reachable_size.dart';
-part 'mocks/repositories/retained_size.dart';
-part 'mocks/repositories/retaining_path.dart';
-part 'mocks/repositories/sample_profile.dart';
-part 'mocks/repositories/script.dart';
-part 'mocks/repositories/target.dart';
diff --git a/runtime/observatory/tests/observatory_ui/mocks/exceptions/connection_exception.dart b/runtime/observatory/tests/observatory_ui/mocks/exceptions/connection_exception.dart
deleted file mode 100644
index d036951..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/exceptions/connection_exception.dart
+++ /dev/null
@@ -1,10 +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.
-
-part of mocks;
-
-class ConnectionExceptionMock implements M.ConnectionException {
-  final String message;
-  const ConnectionExceptionMock({this.message});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/allocation_profile.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/allocation_profile.dart
deleted file mode 100644
index c61989e..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/allocation_profile.dart
+++ /dev/null
@@ -1,53 +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
-
-part of mocks;
-
-class AllocationProfileMock implements M.AllocationProfile {
-  final DateTime lastServiceGC;
-  final DateTime lastAccumulatorReset;
-  final M.HeapSpace newSpace;
-  final M.HeapSpace oldSpace;
-  final Iterable<M.ClassHeapStats> members;
-
-  const AllocationProfileMock(
-      {this.lastServiceGC,
-      this.lastAccumulatorReset,
-      this.newSpace: const HeapSpaceMock(),
-      this.oldSpace: const HeapSpaceMock(),
-      this.members: const []});
-}
-
-class ClassHeapStatsMock implements M.ClassHeapStats {
-  final M.ClassRef clazz;
-  final String displayName;
-  final M.Allocations newSpace;
-  final M.Allocations oldSpace;
-  final int promotedInstances;
-  final int promotedBytes;
-
-  const ClassHeapStatsMock(
-      {this.clazz: const ClassRefMock(),
-      this.displayName: null,
-      this.newSpace: const AllocationsMock(),
-      this.oldSpace: const AllocationsMock(),
-      this.promotedInstances: 0,
-      this.promotedBytes: 0});
-}
-
-class AllocationsMock implements M.Allocations {
-  final M.AllocationCount accumulated;
-  final M.AllocationCount current;
-
-  const AllocationsMock(
-      {this.accumulated: const AllocationCountMock(),
-      this.current: const AllocationCountMock()});
-}
-
-class AllocationCountMock implements M.AllocationCount {
-  final int instances;
-  final int bytes;
-
-  const AllocationCountMock({this.instances: 0, this.bytes: 0});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/class.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/class.dart
deleted file mode 100644
index 22febf2..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/class.dart
+++ /dev/null
@@ -1,60 +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.
-
-part of mocks;
-
-class ClassRefMock implements M.ClassRef {
-  final String id;
-  final String name;
-  const ClassRefMock({this.id, this.name});
-}
-
-class ClassMock implements M.Class {
-  final String id;
-  final String name;
-  final String vmName;
-  final M.ClassRef clazz;
-  final int size;
-  final M.ErrorRef error;
-  final bool isAbstract;
-  final bool isConst;
-  final bool isPatch;
-  final M.LibraryRef library;
-  final M.SourceLocation location;
-  final M.ClassRef superclass;
-  final M.InstanceRef superType;
-  final Iterable<M.InstanceRef> interfaces;
-  final Iterable<M.FieldRef> fields;
-  final Iterable<M.FunctionRef> functions;
-  final M.InstanceRef mixin;
-  final Iterable<M.ClassRef> subclasses;
-  final M.Allocations newSpace;
-  final M.Allocations oldSpace;
-  final bool hasAllocations;
-  bool get hasNoAllocations => !hasAllocations;
-  final bool traceAllocations;
-  const ClassMock(
-      {this.id: 'c-id',
-      this.name: 'c-name',
-      this.vmName: 'c-name',
-      this.clazz,
-      this.size,
-      this.error,
-      this.isAbstract: false,
-      this.isConst: false,
-      this.isPatch: false,
-      this.library,
-      this.location,
-      this.superclass,
-      this.superType,
-      this.interfaces: const [],
-      this.fields: const [],
-      this.functions: const [],
-      this.mixin,
-      this.subclasses: const [],
-      this.hasAllocations: false,
-      this.newSpace,
-      this.oldSpace,
-      this.traceAllocations: false});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/code.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/code.dart
deleted file mode 100644
index 4bfd950..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/code.dart
+++ /dev/null
@@ -1,39 +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.
-
-part of mocks;
-
-class CodeRefMock implements M.CodeRef {
-  final String id;
-  final String name;
-  final M.CodeKind kind;
-  final bool isOptimized;
-
-  const CodeRefMock({this.id, this.name, this.kind, this.isOptimized: false});
-}
-
-class CodeMock implements M.Code {
-  final String id;
-  final String name;
-  final String vmName;
-  final M.ClassRef clazz;
-  final int size;
-  final M.CodeKind kind;
-  final bool isOptimized;
-  final M.FunctionRef function;
-  final M.ObjectPoolRef objectPool;
-  final Iterable<M.FunctionRef> inlinedFunctions;
-
-  const CodeMock(
-      {this.id: 'code-id',
-      this.name: 'code-name',
-      this.vmName: 'code-vmName',
-      this.clazz,
-      this.size,
-      this.kind: M.CodeKind.dart,
-      this.isOptimized: false,
-      this.function: const FunctionRefMock(),
-      this.objectPool: const ObjectPoolRefMock(),
-      this.inlinedFunctions: const []});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/context.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/context.dart
deleted file mode 100644
index 529ac68..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/context.dart
+++ /dev/null
@@ -1,38 +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.
-
-part of mocks;
-
-class ContextRefMock implements M.ContextRef {
-  final String id;
-  final int length;
-
-  const ContextRefMock({this.id: 'context-id', this.length});
-}
-
-class ContextMock implements M.Context {
-  final String id;
-  final M.ClassRef clazz;
-  final String vmName;
-  final int size;
-  final int length;
-  final M.Context parentContext;
-  final Iterable<M.ContextElement> variables;
-
-  const ContextMock(
-      {this.id: 'context-id',
-      this.vmName: 'context-vmName',
-      this.clazz: const ClassMock(),
-      this.size: 0,
-      this.length,
-      this.parentContext,
-      this.variables: const []});
-}
-
-class ContextElementMock implements M.ContextElement {
-  final GuardedMock<M.InstanceRef> value;
-
-  const ContextElementMock(
-      {this.value: const GuardedMock.fromValue(const InstanceRefMock())});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/error.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/error.dart
deleted file mode 100644
index 5c76981..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/error.dart
+++ /dev/null
@@ -1,33 +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.
-
-part of mocks;
-
-class ErrorRefMock implements M.ErrorRef {
-  final String id;
-  final M.ErrorKind kind;
-  final String message;
-
-  const ErrorRefMock(
-      {this.id: 'error-ref',
-      this.kind: M.ErrorKind.internalError,
-      this.message: 'Error Message'});
-}
-
-class ErrorMock implements M.Error {
-  final String id;
-  final M.ClassRef clazz;
-  final String vmName;
-  final int size;
-  final M.ErrorKind kind;
-  final String message;
-
-  const ErrorMock(
-      {this.id: 'error-id',
-      this.vmName: 'error-vmName',
-      this.clazz: const ClassMock(),
-      this.size: 0,
-      this.kind: M.ErrorKind.internalError,
-      this.message: 'Error Message'});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/event.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/event.dart
deleted file mode 100644
index 5e9e470..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/event.dart
+++ /dev/null
@@ -1,175 +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.
-
-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 DebuggerSettingsUpdateEventMock implements M.PauseStartEvent {
-  final DateTime timestamp;
-  final M.IsolateRef isolate;
-  const DebuggerSettingsUpdateEventMock({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;
-  final M.Frame topFrame;
-  const ResumeEventMock({this.timestamp, this.isolate, this.topFrame});
-}
-
-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/tests/observatory_ui/mocks/objects/field.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/field.dart
deleted file mode 100644
index ec3b8f5..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/field.dart
+++ /dev/null
@@ -1,24 +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
-
-part of mocks;
-
-class FieldRefMock implements M.FieldRef {
-  final String id;
-  final String name;
-  final M.ObjectRef dartOwner;
-  final M.InstanceRef declaredType;
-  final bool isConst;
-  final bool isFinal;
-  final bool isStatic;
-
-  const FieldRefMock(
-      {this.id: 'field-id',
-      this.name: 'field-name',
-      this.dartOwner,
-      this.declaredType: const InstanceRefMock(name: 'dynamic'),
-      this.isConst: false,
-      this.isFinal: false,
-      this.isStatic: false});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/flag.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/flag.dart
deleted file mode 100644
index 1b250ff..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/flag.dart
+++ /dev/null
@@ -1,14 +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
-
-part of mocks;
-
-class FlagMock implements M.Flag {
-  final String name;
-  final String comment;
-  final bool modified;
-  final String valueAsString;
-
-  const FlagMock({this.name, this.comment, this.modified, this.valueAsString});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/function.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/function.dart
deleted file mode 100644
index 00f3ca5..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/function.dart
+++ /dev/null
@@ -1,71 +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.
-
-part of mocks;
-
-class FunctionRefMock implements M.FunctionRef {
-  final String id;
-  final String name;
-  final M.ObjectRef dartOwner;
-  final bool isStatic;
-  final bool isConst;
-  final M.FunctionKind kind;
-
-  const FunctionRefMock(
-      {this.id,
-      this.name,
-      this.dartOwner,
-      this.isStatic: false,
-      this.isConst: false,
-      this.kind});
-}
-
-class FunctionMock implements M.ServiceFunction {
-  final String id;
-  final String name;
-  final M.ClassRef clazz;
-  final int size;
-  final M.ObjectRef dartOwner;
-  final bool isStatic;
-  final bool isConst;
-  final M.FunctionKind kind;
-  final M.SourceLocation location;
-  final M.CodeRef code;
-  final M.CodeRef unoptimizedCode;
-  final M.CodeRef bytecode;
-  final M.FieldRef field;
-  final int usageCounter;
-  final M.InstanceRef icDataArray;
-  final int deoptimizations;
-  final bool isOptimizable;
-  final bool isInlinable;
-  final bool hasIntrinsic;
-  final bool isRecognized;
-  final bool isNative;
-  final String vmName;
-  const FunctionMock({
-    this.id,
-    this.name,
-    this.clazz,
-    this.size,
-    this.dartOwner,
-    this.isStatic: false,
-    this.isConst: false,
-    this.kind,
-    this.location,
-    this.code,
-    this.unoptimizedCode,
-    this.bytecode,
-    this.field,
-    this.usageCounter: 0,
-    this.icDataArray: const InstanceRefMock(),
-    this.deoptimizations: 0,
-    this.isOptimizable: false,
-    this.isInlinable: false,
-    this.hasIntrinsic: false,
-    this.isRecognized: false,
-    this.isNative: false,
-    this.vmName: 'function-vm-name',
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/guarded.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/guarded.dart
deleted file mode 100644
index 8e4ccc0..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/guarded.dart
+++ /dev/null
@@ -1,16 +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.
-
-part of mocks;
-
-class GuardedMock<T> implements M.Guarded<T> {
-  bool get isSentinel => asSentinel != null;
-  bool get isValue => asValue != null;
-  final T asValue;
-  final M.Sentinel asSentinel;
-
-  const GuardedMock.fromValue(this.asValue) : asSentinel = null;
-
-  const GuardedMock.fromSentinel(this.asSentinel) : asValue = null;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/heap_snapshot.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/heap_snapshot.dart
deleted file mode 100644
index 0b32af1..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/heap_snapshot.dart
+++ /dev/null
@@ -1,81 +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.
-
-part of mocks;
-
-class HeapSnapshotMock implements M.HeapSnapshot {
-  final DateTime timestamp;
-  final int objects;
-  final int references;
-  final int size;
-  final M.HeapSnapshotDominatorNode dominatorTree;
-  final M.HeapSnapshotMergedDominatorNode mergedDominatorTree = null;
-  final Iterable<M.HeapSnapshotClassReferences> classReferences;
-  final Iterable<M.HeapSnapshotOwnershipClass> ownershipClasses;
-
-  const HeapSnapshotMock(
-      {this.timestamp,
-      this.objects: 0,
-      this.references: 0,
-      this.size: 0,
-      this.dominatorTree: const HeapSnapshotDominatorNodeMock(),
-      this.classReferences: const [],
-      this.ownershipClasses: const []});
-}
-
-class HeapSnapshotDominatorNodeMock implements M.HeapSnapshotDominatorNode {
-  final int shallowSize;
-  final int retainedSize;
-  final bool isStack = false;
-  final Future<M.ObjectRef> object;
-  final Iterable<M.HeapSnapshotDominatorNode> children;
-
-  const HeapSnapshotDominatorNodeMock(
-      {this.shallowSize: 1,
-      this.retainedSize: 1,
-      this.object,
-      this.children: const []});
-}
-
-class HeapSnapshotClassReferencesMock implements M.HeapSnapshotClassReferences {
-  final M.ClassRef clazz;
-  final int instances;
-  final int shallowSize;
-  final int retainedSize;
-  final Iterable<M.HeapSnapshotClassInbound> inbounds;
-  final Iterable<M.HeapSnapshotClassOutbound> outbounds;
-
-  const HeapSnapshotClassReferencesMock(
-      {this.clazz: const ClassRefMock(),
-      this.instances: 1,
-      this.shallowSize: 1,
-      this.retainedSize: 2,
-      this.inbounds: const [],
-      this.outbounds: const []});
-}
-
-class HeapSnapshotClassInboundMock implements M.HeapSnapshotClassInbound {
-  final M.ClassRef source;
-  final int count;
-  final int shallowSize;
-  final int retainedSize;
-
-  const HeapSnapshotClassInboundMock(
-      {this.source: const ClassRefMock(),
-      this.count: 1,
-      this.shallowSize: 1,
-      this.retainedSize: 2});
-}
-
-class HeapSnapshotClassOutboundMock implements M.HeapSnapshotClassOutbound {
-  final M.ClassRef target;
-  final int count;
-  final int shallowSize;
-  final int retainedSize;
-  const HeapSnapshotClassOutboundMock(
-      {this.target: const ClassRefMock(),
-      this.count: 1,
-      this.shallowSize: 1,
-      this.retainedSize: 2});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/heap_space.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/heap_space.dart
deleted file mode 100644
index da930a1..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/heap_space.dart
+++ /dev/null
@@ -1,23 +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.
-
-part of mocks;
-
-class HeapSpaceMock implements M.HeapSpace {
-  final int used;
-  final int capacity;
-  final int collections;
-  final int external;
-  final Duration avgCollectionTime;
-  final Duration totalCollectionTime;
-  final Duration avgCollectionPeriod;
-  const HeapSpaceMock(
-      {this.used: 0,
-      this.capacity: 1,
-      this.collections: 0,
-      this.external: 1,
-      this.avgCollectionTime: const Duration(),
-      this.totalCollectionTime: const Duration(),
-      this.avgCollectionPeriod: const Duration()});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/icdata.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/icdata.dart
deleted file mode 100644
index d1474e3..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/icdata.dart
+++ /dev/null
@@ -1,33 +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.
-
-part of mocks;
-
-class ICDataRefMock implements M.ICDataRef {
-  final String id;
-  final String selector;
-
-  const ICDataRefMock({this.id: 'icdata-id', this.selector});
-}
-
-class ICDataMock implements M.ICData {
-  final String id;
-  final M.ClassRef clazz;
-  final String vmName;
-  final int size;
-  final String selector;
-  final M.ObjectRef dartOwner;
-  final M.InstanceRef argumentsDescriptor;
-  final M.InstanceRef entries;
-
-  const ICDataMock(
-      {this.id: 'icdata-id',
-      this.vmName: 'icdata-vmName',
-      this.clazz: const ClassRefMock(),
-      this.size: 0,
-      this.selector,
-      this.dartOwner,
-      this.argumentsDescriptor,
-      this.entries});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/inbound_references.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/inbound_references.dart
deleted file mode 100644
index 34f0479..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/inbound_references.dart
+++ /dev/null
@@ -1,24 +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.
-
-part of mocks;
-
-class InboundReferencesMock implements M.InboundReferences {
-  final Iterable<M.InboundReference> elements;
-
-  const InboundReferencesMock({this.elements: const []});
-}
-
-class InboundReferenceMock implements M.InboundReference {
-  final M.ObjectRef source;
-  final M.ObjectRef parentField;
-  final int parentListIndex;
-  final int parentWordOffset;
-
-  const InboundReferenceMock(
-      {this.source: const InstanceRefMock(),
-      this.parentField,
-      this.parentListIndex,
-      this.parentWordOffset});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/instance.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/instance.dart
deleted file mode 100644
index df07d2c..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/instance.dart
+++ /dev/null
@@ -1,113 +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.
-
-part of mocks;
-
-class InstanceRefMock implements M.InstanceRef {
-  final String id;
-  final String name;
-  final M.InstanceKind kind;
-  final M.ClassRef clazz;
-  final String valueAsString;
-  final bool valueAsStringIsTruncated;
-  final int length;
-  final M.ClassRef typeClass;
-  final M.ClassRef parameterizedClass;
-  final M.InstanceRef pattern;
-  final M.FunctionRef closureFunction;
-  final M.ContextRef closureContext;
-
-  const InstanceRefMock(
-      {this.id: 'instance-id',
-      this.name: 'instance-name',
-      this.kind: M.InstanceKind.vNull,
-      this.clazz,
-      this.valueAsString: 'null',
-      this.valueAsStringIsTruncated,
-      this.length,
-      this.typeClass,
-      this.parameterizedClass,
-      this.pattern,
-      this.closureFunction,
-      this.closureContext});
-}
-
-class InstanceMock implements M.Instance {
-  final String id;
-  final String name;
-  final String vmName;
-  final M.InstanceKind kind;
-  final M.ClassRef clazz;
-  final int size;
-  final String valueAsString;
-  final bool valueAsStringIsTruncated;
-  final int length;
-  final M.ClassRef typeClass;
-  final M.ClassRef parameterizedClass;
-  final M.InstanceRef pattern;
-  final M.FunctionRef closureFunction;
-  final M.ContextRef closureContext;
-  final int offset;
-  final int count;
-  final List<dynamic> typedElements;
-  final Iterable<M.BoundField> fields;
-  final Iterable<M.NativeField> nativeFields;
-  final Iterable<M.Guarded<M.ObjectRef>> elements;
-  final Iterable<M.MapAssociation> associations;
-  final M.InstanceRef key;
-  final M.InstanceRef value;
-  final M.InstanceRef referent;
-  final M.TypeArguments typeArguments;
-  final int parameterIndex;
-  final M.InstanceRef targetType;
-  final M.InstanceRef bound;
-  final M.Breakpoint activationBreakpoint;
-  final bool isCaseSensitive;
-  final bool isMultiLine;
-  final M.FunctionRef oneByteFunction;
-  final M.FunctionRef twoByteFunction;
-  final M.FunctionRef externalOneByteFunction;
-  final M.FunctionRef externalTwoByteFunction;
-  final M.InstanceRef oneByteBytecode;
-  final M.InstanceRef twoByteBytecode;
-
-  const InstanceMock(
-      {this.id: 'instance-id',
-      this.name: 'instance-name',
-      this.vmName: 'instance-vmName',
-      this.kind: M.InstanceKind.vNull,
-      this.clazz: const ClassRefMock(),
-      this.size: 0,
-      this.valueAsString: 'null',
-      this.valueAsStringIsTruncated,
-      this.length,
-      this.typeClass,
-      this.parameterizedClass,
-      this.pattern,
-      this.closureFunction,
-      this.closureContext,
-      this.offset,
-      this.count,
-      this.typedElements,
-      this.fields,
-      this.nativeFields,
-      this.elements,
-      this.associations,
-      this.key,
-      this.value,
-      this.referent,
-      this.typeArguments,
-      this.parameterIndex,
-      this.targetType,
-      this.bound,
-      this.activationBreakpoint,
-      this.isCaseSensitive,
-      this.isMultiLine,
-      this.oneByteFunction,
-      this.twoByteFunction,
-      this.externalOneByteFunction,
-      this.externalTwoByteFunction,
-      this.oneByteBytecode,
-      this.twoByteBytecode});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/isolate.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/isolate.dart
deleted file mode 100644
index 310e8fb..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/isolate.dart
+++ /dev/null
@@ -1,60 +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.
-
-part of mocks;
-
-class IsolateRefMock implements M.IsolateRef {
-  final String id;
-  final int number;
-  final String name;
-
-  const IsolateRefMock({this.id: 'i-id', this.number, this.name: 'i-name'});
-
-  Future collectAllGarbage() async {
-    throw "Unimplemented";
-  }
-}
-
-class IsolateMock implements M.Isolate {
-  final String id;
-  final int number;
-  final String name;
-  final DateTime startTime;
-  final bool runnable;
-  final Iterable<M.LibraryRef> libraries;
-  final M.Error error;
-  final Iterable<String> extensionRPCs;
-  final Map counters;
-  final M.HeapSpace newSpace;
-  final M.HeapSpace oldSpace;
-  final M.IsolateStatus status;
-  final M.DebugEvent pauseEvent;
-  final M.LibraryRef rootLibrary;
-  final M.FunctionRef entry;
-  final Iterable<M.Thread> threads = null;
-  final int zoneHighWatermark = 0;
-  final int numZoneHandles = 0;
-  final int numScopedHandles = 0;
-
-  const IsolateMock(
-      {this.id: 'i-id',
-      this.number,
-      this.name: 'i-name',
-      this.startTime,
-      this.runnable: true,
-      this.libraries: const [],
-      this.error,
-      this.extensionRPCs: const [],
-      this.counters: const {},
-      this.newSpace: const HeapSpaceMock(),
-      this.oldSpace: const HeapSpaceMock(),
-      this.status: M.IsolateStatus.loading,
-      this.pauseEvent,
-      this.rootLibrary,
-      this.entry});
-
-  Future collectAllGarbage() async {
-    throw "Unimplemented";
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/library.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/library.dart
deleted file mode 100644
index 4d4f67f..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/library.dart
+++ /dev/null
@@ -1,43 +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.
-
-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 vmName;
-  final M.ClassRef clazz;
-  final int size;
-  final String uri;
-  final bool debuggable;
-  final Iterable<M.LibraryDependency> dependencies;
-  final Iterable<M.ScriptRef> scripts;
-  final Iterable<M.ClassRef> classes;
-  final Iterable<M.FieldRef> variables;
-  final Iterable<M.FunctionRef> functions;
-  final M.ScriptRef rootScript;
-
-  const LibraryMock(
-      {this.id: 'library-id',
-      this.name: 'library-name',
-      this.vmName: 'library-vmName',
-      this.clazz,
-      this.size,
-      this.uri,
-      this.debuggable,
-      this.dependencies: const [],
-      this.scripts: const [],
-      this.classes: const [],
-      this.variables: const [],
-      this.functions: const [],
-      this.rootScript: const ScriptRefMock()});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/local_var_descriptors.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/local_var_descriptors.dart
deleted file mode 100644
index b60e505..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/local_var_descriptors.dart
+++ /dev/null
@@ -1,12 +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.
-
-part of mocks;
-
-class LocalVarDescriptorsRefMock implements M.LocalVarDescriptorsRef {
-  final String id;
-  final String name;
-  const LocalVarDescriptorsRefMock(
-      {this.id: 'local-var-id', this.name: 'local_var_name'});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/megamorphiccache.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/megamorphiccache.dart
deleted file mode 100644
index 4e077f2..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/megamorphiccache.dart
+++ /dev/null
@@ -1,34 +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.
-
-part of mocks;
-
-class MegamorphicCacheRefMock implements M.MegamorphicCacheRef {
-  final String id;
-  final String selector;
-
-  const MegamorphicCacheRefMock(
-      {this.id: 'megamorphiccache-id', this.selector: 'selector'});
-}
-
-class MegamorphicCacheMock implements M.MegamorphicCache {
-  final String id;
-  final M.ClassRef clazz;
-  final String vmName;
-  final int size;
-  final String selector;
-  final int mask;
-  final M.InstanceRef buckets;
-  final M.InstanceRef argumentsDescriptor;
-
-  const MegamorphicCacheMock(
-      {this.id: 'megamorphiccache-id',
-      this.vmName: 'megamorphiccache-vmName',
-      this.clazz: const ClassRefMock(),
-      this.size: 1,
-      this.selector: 'selector',
-      this.mask: 0,
-      this.buckets: const InstanceRefMock(),
-      this.argumentsDescriptor: const InstanceRefMock()});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/notification.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/notification.dart
deleted file mode 100644
index d452cee..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/notification.dart
+++ /dev/null
@@ -1,16 +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.
-
-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/tests/observatory_ui/mocks/objects/objectpool.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/objectpool.dart
deleted file mode 100644
index 3b6c115..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/objectpool.dart
+++ /dev/null
@@ -1,42 +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.
-
-part of mocks;
-
-class ObjectPoolRefMock implements M.ObjectPoolRef {
-  final String id;
-  final int length;
-
-  const ObjectPoolRefMock({this.id: 'objectpool-id', this.length: 0});
-}
-
-class ObjectPoolMock implements M.ObjectPool {
-  final String id;
-  final M.ClassRef clazz;
-  final String vmName;
-  final int size;
-  final int length;
-  final Iterable<M.ObjectPoolEntry> entries;
-
-  const ObjectPoolMock(
-      {this.id: 'objectpool-id',
-      this.vmName: 'objpool-vmName',
-      this.clazz: const ClassRefMock(),
-      this.size: 1,
-      this.length: 0,
-      this.entries: const []});
-}
-
-class ObjectPoolEntryMock implements M.ObjectPoolEntry {
-  final int offset;
-  final M.ObjectPoolEntryKind kind;
-  final M.ObjectRef asObject;
-  final int asInteger;
-
-  const ObjectPoolEntryMock(
-      {this.offset: 0,
-      this.kind: M.ObjectPoolEntryKind.object,
-      this.asObject: const InstanceRefMock(),
-      this.asInteger: null});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/objectstore.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/objectstore.dart
deleted file mode 100644
index 7cd62a7..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/objectstore.dart
+++ /dev/null
@@ -1,19 +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.
-
-part of mocks;
-
-class ObjectStoreMock implements M.ObjectStore {
-  final Iterable<M.NamedField> fields;
-
-  const ObjectStoreMock({this.fields: const []});
-}
-
-class NamedFieldMock implements M.NamedField {
-  final String name;
-  final M.ObjectRef value;
-
-  const NamedFieldMock(
-      {this.name: 'field-name', this.value: const InstanceRefMock()});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/pc_descriptors.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/pc_descriptors.dart
deleted file mode 100644
index 563704c..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/pc_descriptors.dart
+++ /dev/null
@@ -1,13 +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.
-
-part of mocks;
-
-class PcDescriptorsRefMock implements M.PcDescriptorsRef {
-  final String id;
-  final String name;
-
-  const PcDescriptorsRefMock(
-      {this.id: 'pcdescriptors-id', this.name: 'pcdescriptors-name'});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/persistent_handles.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/persistent_handles.dart
deleted file mode 100644
index 6926449..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/persistent_handles.dart
+++ /dev/null
@@ -1,34 +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.
-
-part of mocks;
-
-class PersistentHandlesMock implements M.PersistentHandles {
-  final Iterable<M.PersistentHandle> elements;
-  final Iterable<M.WeakPersistentHandle> weakElements;
-
-  const PersistentHandlesMock(
-      {this.elements: const [], this.weakElements: const []});
-}
-
-class PersistentHandleMock implements M.PersistentHandle {
-  final M.ObjectRef object;
-
-  const PersistentHandleMock({this.object: const InstanceRefMock()});
-}
-
-class WeakPersistentHandleMock implements M.WeakPersistentHandle {
-  final M.ObjectRef object;
-  final int externalSize;
-  final String peer;
-  final String callbackSymbolName;
-  final String callbackAddress;
-
-  const WeakPersistentHandleMock(
-      {this.object: const InstanceRefMock(),
-      this.externalSize: 0,
-      this.peer: '0x0',
-      this.callbackSymbolName: 'dart::Something()',
-      this.callbackAddress: '0x123456'});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/ports.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/ports.dart
deleted file mode 100644
index 2149a4f..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/ports.dart
+++ /dev/null
@@ -1,26 +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.
-
-part of mocks;
-
-class PortsAndHandlesMock implements M.Ports, M.PersistentHandles {
-  final Iterable<PortMock> elements;
-
-  const PortsAndHandlesMock({this.elements: const []});
-
-  @override
-  Iterable<M.WeakPersistentHandle> get weakElements =>
-      throw new UnimplementedError();
-}
-
-class PortMock implements M.Port, M.PersistentHandle {
-  final String name;
-  final M.ObjectRef handler;
-
-  const PortMock(
-      {this.name: 'port-name', this.handler: const InstanceRefMock()});
-
-  @override
-  M.ObjectRef get object => throw new UnimplementedError();
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/retaining_path.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/retaining_path.dart
deleted file mode 100644
index 36b7b68..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/retaining_path.dart
+++ /dev/null
@@ -1,24 +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.
-
-part of mocks;
-
-class RetainingPathMock implements M.RetainingPath {
-  final Iterable<M.RetainingPathItem> elements;
-
-  const RetainingPathMock({this.elements: const []});
-}
-
-class RetainingPathItemMock implements M.RetainingPathItem {
-  final M.ObjectRef source;
-  final M.ObjectRef parentField;
-  final int parentListIndex;
-  final int parentWordOffset;
-
-  const RetainingPathItemMock(
-      {this.source: const InstanceRefMock(),
-      this.parentField,
-      this.parentListIndex,
-      this.parentWordOffset});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/sample_profile.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/sample_profile.dart
deleted file mode 100644
index 9dd386e..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/sample_profile.dart
+++ /dev/null
@@ -1,48 +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
-
-part of mocks;
-
-typedef M.FunctionCallTree SampleProfileMockLoadFunctionTreeCallback(
-    M.ProfileTreeDirection direction);
-typedef M.CodeCallTree SampleProfileMockLoadCodeTreeCallback(
-    M.ProfileTreeDirection direction);
-
-class SampleProfileMock implements M.SampleProfile {
-  final SampleProfileMockLoadFunctionTreeCallback _loadFunctionTree;
-  final SampleProfileMockLoadCodeTreeCallback _loadCodeTree;
-
-  final int sampleCount;
-  final int stackDepth;
-  final double sampleRate;
-  final double timeSpan;
-  final Iterable<M.ProfileCode> codes;
-  final Iterable<M.ProfileFunction> functions;
-
-  M.FunctionCallTree loadFunctionTree(M.ProfileTreeDirection direction) {
-    if (_loadFunctionTree != null) {
-      return _loadFunctionTree(direction);
-    }
-    return null;
-  }
-
-  M.CodeCallTree loadCodeTree(M.ProfileTreeDirection direction) {
-    if (_loadCodeTree != null) {
-      return _loadCodeTree(direction);
-    }
-    return null;
-  }
-
-  SampleProfileMock(
-      {this.sampleCount: 0,
-      this.stackDepth: 0,
-      this.sampleRate: 1.0,
-      this.timeSpan: 1.0,
-      this.codes: const [],
-      this.functions: const [],
-      SampleProfileMockLoadFunctionTreeCallback loadFunctionTree,
-      SampleProfileMockLoadCodeTreeCallback loadCodeTree})
-      : _loadFunctionTree = loadFunctionTree,
-        _loadCodeTree = loadCodeTree;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/script.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/script.dart
deleted file mode 100644
index 699ec59..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/script.dart
+++ /dev/null
@@ -1,54 +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.
-
-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 M.ClassRef clazz;
-  final String vmName;
-  final int size;
-  final String uri;
-  final String source;
-  final M.LibraryRef library;
-
-  final TokenToInt _tokenToLine;
-  final TokenToInt _tokenToCol;
-
-  final DateTime loadTime;
-  final int firstTokenPos;
-  final int lastTokenPos;
-  final int lineOffset;
-  final int columnOffset;
-
-  int tokenToLine(int token) => _tokenToLine(token);
-  int tokenToCol(int token) => _tokenToCol(token);
-
-  const ScriptMock(
-      {this.id: 'script-id',
-      this.vmName: 'script-vmNmae',
-      this.clazz,
-      this.size,
-      this.uri,
-      this.source,
-      this.library: const LibraryRefMock(),
-      TokenToInt tokenToLine,
-      TokenToInt tokenToCol,
-      this.loadTime,
-      this.firstTokenPos,
-      this.lastTokenPos,
-      this.lineOffset,
-      this.columnOffset})
-      : _tokenToLine = tokenToLine,
-        _tokenToCol = tokenToCol;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/sentinel.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/sentinel.dart
deleted file mode 100644
index 8ca0b41..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/sentinel.dart
+++ /dev/null
@@ -1,14 +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.
-
-part of mocks;
-
-class SentinelMock implements M.Sentinel {
-  final M.SentinelKind kind;
-  final String valueAsString;
-
-  const SentinelMock(
-      {this.kind: M.SentinelKind.collected,
-      this.valueAsString: 'sentinel-value'});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/source_location.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/source_location.dart
deleted file mode 100644
index a795589..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/source_location.dart
+++ /dev/null
@@ -1,13 +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.
-
-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/tests/observatory_ui/mocks/objects/target.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/target.dart
deleted file mode 100644
index 0d15e5c..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/target.dart
+++ /dev/null
@@ -1,10 +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.
-
-part of mocks;
-
-class TargetMock implements M.Target {
-  final String name;
-  const TargetMock({this.name});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/unknown.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/unknown.dart
deleted file mode 100644
index 05730a3..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/unknown.dart
+++ /dev/null
@@ -1,12 +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.
-
-part of mocks;
-
-class UnknownObjectRefMock implements M.UnknownObjectRef {
-  final String id;
-  final String vmType;
-  const UnknownObjectRefMock(
-      {this.id: 'literal-token-id', this.vmType: 'vmType'});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/vm.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/vm.dart
deleted file mode 100644
index c19ba56..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/vm.dart
+++ /dev/null
@@ -1,51 +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.
-
-part of mocks;
-
-class VMRefMock implements M.VMRef {
-  final String name;
-  final String displayName;
-  const VMRefMock({this.name: 'vm-name', this.displayName: 'vm-display-name'});
-}
-
-class VMMock implements M.VM {
-  final String name;
-  final String displayName;
-  final int architectureBits;
-  final String targetCPU;
-  final String hostCPU;
-  final String version;
-  final String embedder;
-  final int pid;
-  final int maxRSS;
-  final int currentRSS;
-  final DateTime startTime;
-  final Iterable<M.IsolateRef> isolates;
-  final int nativeZoneMemoryUsage = 0;
-  final int heapAllocatedMemoryUsage = 0;
-  final int heapAllocationCount = 0;
-
-  Future<dynamic> invokeRpc(String method, Map params) {
-    return null;
-  }
-
-  Future enableProfiler() {
-    return null;
-  }
-
-  const VMMock(
-      {this.name: 'vm-name',
-      this.displayName: 'vm-display-name',
-      this.architectureBits,
-      this.targetCPU,
-      this.hostCPU,
-      this.version,
-      this.embedder,
-      this.pid: 0,
-      this.maxRSS: 0,
-      this.currentRSS: 0,
-      this.startTime,
-      this.isolates: const []});
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/allocation_profile.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/allocation_profile.dart
deleted file mode 100644
index 8e9f278..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/allocation_profile.dart
+++ /dev/null
@@ -1,26 +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.
-
-part of mocks;
-
-typedef Future<
-    M
-        .AllocationProfile> AllocationProfileRepositoryMockGetterCallback(
-    M.Isolate id, bool gc, bool force, bool combine);
-
-class AllocationProfileRepositoryMock implements M.AllocationProfileRepository {
-  final AllocationProfileRepositoryMockGetterCallback _get;
-
-  AllocationProfileRepositoryMock(
-      {AllocationProfileRepositoryMockGetterCallback getter})
-      : _get = getter;
-
-  Future<M.AllocationProfile> get(M.IsolateRef id,
-      {bool gc: false, bool reset: false, bool combine: false}) {
-    if (_get != null) {
-      return _get(id, gc, reset, combine);
-    }
-    return new Future.value(null);
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/class.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/class.dart
deleted file mode 100644
index b798fca..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/class.dart
+++ /dev/null
@@ -1,34 +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.
-
-part of mocks;
-
-typedef Future<M.Class> ClassRepositoryMockObjectCallback(M.Isolate isolate);
-typedef Future<M.Class> ClassRepositoryMockGetterCallback(
-    M.Isolate isolate, String id);
-
-class ClassRepositoryMock implements M.ClassRepository {
-  final ClassRepositoryMockObjectCallback _object;
-  final ClassRepositoryMockGetterCallback _get;
-
-  ClassRepositoryMock(
-      {ClassRepositoryMockObjectCallback object,
-      ClassRepositoryMockGetterCallback getter})
-      : _object = object,
-        _get = getter;
-
-  Future<M.Class> getObject(M.IsolateRef i) {
-    if (_object != null) {
-      return _object(i);
-    }
-    return new Future.value(null);
-  }
-
-  Future<M.Class> get(M.IsolateRef i, String id) {
-    if (_get != null) {
-      return _get(i, id);
-    }
-    return new Future.value(null);
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/context.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/context.dart
deleted file mode 100644
index bf0c9e9..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/context.dart
+++ /dev/null
@@ -1,21 +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.
-
-part of mocks;
-
-typedef Future<M.Context> ContextRepositoryMockCallback(
-    M.IsolateRef isolate, String id);
-
-class ContextRepositoryMock implements M.ContextRepository {
-  final ContextRepositoryMockCallback _get;
-
-  ContextRepositoryMock({ContextRepositoryMockCallback getter}) : _get = getter;
-
-  Future<M.Context> get(M.IsolateRef isolate, String id) {
-    if (_get != null) {
-      return _get(isolate, id);
-    }
-    return new Future.value(null);
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/eval.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/eval.dart
deleted file mode 100644
index 0b7a072..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/eval.dart
+++ /dev/null
@@ -1,25 +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.
-
-part of mocks;
-
-typedef Future<M.Object> EvalRepositoryMockCallback(
-    M.IsolateRef isolate, M.ObjectRef context, String expression,
-    {bool disableBreakpoints});
-
-class EvalRepositoryMock implements M.EvalRepository {
-  final EvalRepositoryMockCallback _get;
-
-  EvalRepositoryMock({EvalRepositoryMockCallback getter}) : _get = getter;
-
-  Future<M.Object> evaluate(
-      M.IsolateRef isolate, M.ObjectRef context, String expression,
-      {bool disableBreakpoints: false}) {
-    if (_get != null) {
-      return _get(isolate, context, expression,
-          disableBreakpoints: disableBreakpoints);
-    }
-    return new Future.value(null);
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/event.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/event.dart
deleted file mode 100644
index 8b74218..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/event.dart
+++ /dev/null
@@ -1,209 +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.
-
-part of mocks;
-
-class EventRepositoryMock implements M.EventRepository {
-  final _onEvent = new StreamController<M.Event>.broadcast();
-  Stream<M.Event> get onEvent => _onEvent.stream;
-  get onEventHasListener => _onEvent.hasListener;
-
-  final _onVMEvent = new StreamController<M.VMEvent>.broadcast();
-  Stream<M.VMEvent> get onVMEvent => _onVMEvent.stream;
-  get onVMEventHasListener => _onVMEvent.hasListener;
-
-  final _onVMUpdate = new StreamController<M.VMUpdateEvent>.broadcast();
-  Stream<M.VMUpdateEvent> get onVMUpdate => _onVMUpdate.stream;
-  get onVMUpdateHasListener => _onVMUpdate.hasListener;
-
-  final _onIsolateEvent = new StreamController<M.IsolateEvent>.broadcast();
-  Stream<M.IsolateEvent> get onIsolateEvent => _onIsolateEvent.stream;
-  get onIsolateEventHasListener => _onIsolateEvent.hasListener;
-
-  final _onIsolateStart = new StreamController<M.IsolateStartEvent>.broadcast();
-  Stream<M.IsolateStartEvent> get onIsolateStart => _onIsolateStart.stream;
-  get onIsolateStartHasListener => _onIsolateStart.hasListener;
-
-  final _onIsolateRunnable =
-      new StreamController<M.IsolateRunnableEvent>.broadcast();
-  Stream<M.IsolateRunnableEvent> get onIsolateRunnable =>
-      _onIsolateRunnable.stream;
-  get onIsolateRunnableHasListener => _onIsolateRunnable.hasListener;
-
-  final _onIsolateExit = new StreamController<M.IsolateExitEvent>.broadcast();
-  Stream<M.IsolateExitEvent> get onIsolateExit => _onIsolateExit.stream;
-  get onIsolateExitHasListener => _onIsolateExit.hasListener;
-
-  final _onIsolateUpdate =
-      new StreamController<M.IsolateUpdateEvent>.broadcast();
-  Stream<M.IsolateUpdateEvent> get onIsolateUpdate => _onIsolateUpdate.stream;
-  get onIsolateUpdateHasListener => _onIsolateUpdate.hasListener;
-
-  final _onIsolateReload =
-      new StreamController<M.IsolateReloadEvent>.broadcast();
-  Stream<M.IsolateReloadEvent> get onIsolateReload => _onIsolateReload.stream;
-  get onIsolateReloadHasListener => _onIsolateReload.hasListener;
-
-  final _onServiceExtensionAdded =
-      new StreamController<M.ServiceExtensionAddedEvent>.broadcast();
-  Stream<M.ServiceExtensionAddedEvent> get onServiceExtensionAdded =>
-      _onServiceExtensionAdded.stream;
-  get onServiceExtensionAddedHasListener =>
-      _onServiceExtensionAdded.hasListener;
-
-  final _onDebugEvent = new StreamController<M.DebugEvent>.broadcast();
-  Stream<M.DebugEvent> get onDebugEvent => _onDebugEvent.stream;
-  get onDebugEventHasListener => _onDebugEvent.hasListener;
-
-  final _onPauseStart = new StreamController<M.PauseStartEvent>.broadcast();
-  Stream<M.PauseStartEvent> get onPauseStart => _onPauseStart.stream;
-  get onPauseStartHasListener => _onPauseStart.hasListener;
-
-  final _onPauseExit = new StreamController<M.PauseExitEvent>.broadcast();
-  Stream<M.PauseExitEvent> get onPauseExit => _onPauseExit.stream;
-  get onPauseExitHasListener => _onPauseExit.hasListener;
-
-  final _onPauseBreakpoint =
-      new StreamController<M.PauseBreakpointEvent>.broadcast();
-  Stream<M.PauseBreakpointEvent> get onPauseBreakpoint =>
-      _onPauseBreakpoint.stream;
-  get onPauseBreakpointHasListener => _onPauseBreakpoint.hasListener;
-
-  final _onPauseInterrupted =
-      new StreamController<M.PauseInterruptedEvent>.broadcast();
-  Stream<M.PauseInterruptedEvent> get onPauseInterrupted =>
-      _onPauseInterrupted.stream;
-  get onPauseInterruptedHasListener => _onPauseInterrupted.hasListener;
-
-  final _onPauseException =
-      new StreamController<M.PauseExceptionEvent>.broadcast();
-  Stream<M.PauseExceptionEvent> get onPauseException =>
-      _onPauseException.stream;
-  get onPauseExceptionHasListener => _onPauseException.hasListener;
-
-  final _onResume = new StreamController<M.ResumeEvent>.broadcast();
-  Stream<M.ResumeEvent> get onResume => _onResume.stream;
-  get onResumeHasListener => _onResume.hasListener;
-
-  final _onBreakpointAdded =
-      new StreamController<M.BreakpointAddedEvent>.broadcast();
-  Stream<M.BreakpointAddedEvent> get onBreakpointAdded =>
-      _onBreakpointAdded.stream;
-  get onBreakpointAddedHasListener => _onBreakpointAdded.hasListener;
-
-  final _onBreakpointResolved =
-      new StreamController<M.BreakpointResolvedEvent>.broadcast();
-  Stream<M.BreakpointResolvedEvent> get onBreakpointResolved =>
-      _onBreakpointResolved.stream;
-  get onBreakpointResolvedHasListener => _onBreakpointResolved.hasListener;
-
-  final _onBreakpointRemoved =
-      new StreamController<M.BreakpointRemovedEvent>.broadcast();
-  Stream<M.BreakpointRemovedEvent> get onBreakpointRemoved =>
-      _onBreakpointRemoved.stream;
-  get onBreakpointRemovedHasListener => _onBreakpointRemoved.hasListener;
-
-  final _onInspect = new StreamController<M.InspectEvent>.broadcast();
-  Stream<M.InspectEvent> get onInspect => _onInspect.stream;
-  get onInspectHasListener => _onInspect.hasListener;
-
-  final _onGCEvent = new StreamController<M.GCEvent>.broadcast();
-  Stream<M.GCEvent> get onGCEvent => _onGCEvent.stream;
-  get onGCEventHasListener => _onGCEvent.hasListener;
-
-  final _onLoggingEvent = new StreamController<M.LoggingEvent>.broadcast();
-  Stream<M.LoggingEvent> get onLoggingEvent => _onLoggingEvent.stream;
-  get onLoggingEventHasListener => _onLoggingEvent.hasListener;
-
-  final _onExtensionEvent = new StreamController<M.ExtensionEvent>.broadcast();
-  Stream<M.ExtensionEvent> get onExtensionEvent => _onExtensionEvent.stream;
-  get onExtensionEventHasListener => _onExtensionEvent.hasListener;
-
-  final _onTimelineEvents =
-      new StreamController<M.TimelineEventsEvent>.broadcast();
-  Stream<M.TimelineEventsEvent> get onTimelineEvents =>
-      _onTimelineEvents.stream;
-  get onTimelineEventsEventHasListener => _onTimelineEvents.hasListener;
-
-  final _onConnectionClosed =
-      new StreamController<M.ConnectionClosedEvent>.broadcast();
-  Stream<M.ConnectionClosedEvent> get onConnectionClosed =>
-      _onConnectionClosed.stream;
-  get onConnectionClosedHasListener => _onConnectionClosed.hasListener;
-
-  final _onServiceEvent = new StreamController<M.ServiceEvent>.broadcast();
-  Stream<M.ServiceEvent> get onServiceEvent => _onServiceEvent.stream;
-  get onServiceEventHasListener => _onServiceEvent.hasListener;
-
-  final _onServiceRegistered =
-      new StreamController<M.ServiceRegisteredEvent>.broadcast();
-  Stream<M.ServiceRegisteredEvent> get onServiceRegistered =>
-      _onServiceRegistered.stream;
-  get onServiceRegisteredHasListener => _onServiceRegistered.hasListener;
-
-  final _onServiceUnregistered =
-      new StreamController<M.ServiceUnregisteredEvent>.broadcast();
-  Stream<M.ServiceUnregisteredEvent> get onServiceUnregistered =>
-      _onServiceUnregistered.stream;
-  get onServiceUnregisteredHasListener => _onServiceUnregistered.hasListener;
-
-  void add(M.Event event) {
-    _onEvent.add(event);
-    if (event is M.VMEvent) {
-      _onVMEvent.add(event);
-      if (event is M.VMUpdateEvent) {
-        _onVMUpdate.add(event);
-      }
-    } else if (event is M.IsolateEvent) {
-      _onIsolateEvent.add(event);
-      if (event is M.IsolateStartEvent) {
-        _onIsolateStart.add(event);
-      } else if (event is M.IsolateRunnableEvent) {
-        _onIsolateRunnable.add(event);
-      } else if (event is M.IsolateExitEvent) {
-        _onIsolateExit.add(event);
-      } else if (event is M.IsolateUpdateEvent) {
-        _onIsolateUpdate.add(event);
-      } else if (event is M.ServiceExtensionAddedEvent) {
-        _onServiceExtensionAdded.add(event);
-      }
-    } else if (event is M.DebugEvent) {
-      _onDebugEvent.add(event);
-      if (event is M.PauseStartEvent) {
-        _onPauseStart.add(event);
-      } else if (event is M.PauseExitEvent) {
-        _onPauseExit.add(event);
-      } else if (event is M.PauseBreakpointEvent) {
-        _onPauseBreakpoint.add(event);
-      } else if (event is M.PauseInterruptedEvent) {
-        _onPauseInterrupted.add(event);
-      } else if (event is M.PauseExceptionEvent) {
-        _onPauseException.add(event);
-      } else if (event is M.ResumeEvent) {
-        _onResume.add(event);
-      } else if (event is M.BreakpointAddedEvent) {
-        _onBreakpointAdded.add(event);
-      } else if (event is M.BreakpointResolvedEvent) {
-        _onBreakpointResolved.add(event);
-      } else if (event is M.BreakpointRemovedEvent) {
-        _onBreakpointRemoved.add(event);
-      } else if (event is M.InspectEvent) {
-        _onInspect.add(event);
-      }
-    } else if (event is M.GCEvent) {
-      _onGCEvent.add(event);
-    } else if (event is M.ExtensionEvent) {
-      _onExtensionEvent.add(event);
-    } else if (event is M.TimelineEventsEvent) {
-      _onTimelineEvents.add(event);
-    } else if (event is M.ServiceEvent) {
-      _onServiceEvent.add(event);
-      if (event is M.ServiceRegisteredEvent) {
-        _onServiceRegistered.add(event);
-      } else if (event is M.ServiceUnregisteredEvent) {
-        _onServiceUnregistered.add(event);
-      }
-    }
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/field.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/field.dart
deleted file mode 100644
index 8e8a038..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/field.dart
+++ /dev/null
@@ -1,21 +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.
-
-part of mocks;
-
-typedef Future<M.Field> FieldRepositoryMockCallback(
-    M.IsolateRef isolate, String id);
-
-class FieldRepositoryMock implements M.FieldRepository {
-  final FieldRepositoryMockCallback _get;
-
-  FieldRepositoryMock({FieldRepositoryMockCallback getter}) : _get = getter;
-
-  Future<M.Field> get(M.IsolateRef isolate, String id) {
-    if (_get != null) {
-      return _get(isolate, id);
-    }
-    return new Future.value(null);
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/flag.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/flag.dart
deleted file mode 100644
index 578c034..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/flag.dart
+++ /dev/null
@@ -1,19 +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
-
-part of mocks;
-
-class FlagsRepositoryMock implements M.FlagsRepository {
-  final Iterable<M.Flag> _list;
-  bool isListInvoked = false;
-
-  Future<Iterable<M.Flag>> list() async {
-    await null;
-    isListInvoked = true;
-    return _list;
-  }
-
-  FlagsRepositoryMock({Iterable<M.Flag> list: const []})
-      : _list = new List.unmodifiable(list);
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/heap_snapshot.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/heap_snapshot.dart
deleted file mode 100644
index de7dec0..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/heap_snapshot.dart
+++ /dev/null
@@ -1,50 +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
-
-part of mocks;
-
-class HeapSnapshotLoadingProgressEventMock
-    implements M.HeapSnapshotLoadingProgressEvent {
-  final M.HeapSnapshotLoadingProgress progress;
-
-  const HeapSnapshotLoadingProgressEventMock(
-      {this.progress: const HeapSnapshotLoadingProgressMock()});
-}
-
-class HeapSnapshotLoadingProgressMock implements M.HeapSnapshotLoadingProgress {
-  final M.HeapSnapshotLoadingStatus status;
-  final String stepDescription;
-  final double progress;
-  final Duration fetchingTime;
-  final Duration loadingTime;
-  final M.HeapSnapshot snapshot;
-
-  const HeapSnapshotLoadingProgressMock(
-      {this.status: M.HeapSnapshotLoadingStatus.fetching,
-      this.progress: 0.0,
-      this.stepDescription: '',
-      this.fetchingTime,
-      this.loadingTime,
-      this.snapshot});
-}
-
-typedef Stream<
-    M
-        .HeapSnapshotLoadingProgressEvent> HeapSnapshotRepositoryMockCallback(
-    M.IsolateRef cls, bool gc);
-
-class HeapSnapshotRepositoryMock implements M.HeapSnapshotRepository {
-  final HeapSnapshotRepositoryMockCallback _get;
-
-  Stream<M.HeapSnapshotLoadingProgressEvent> get(M.IsolateRef isolate,
-      {M.HeapSnapshotRoots roots: M.HeapSnapshotRoots.vm, bool gc: false}) {
-    if (_get != null) {
-      return _get(isolate, gc);
-    }
-    return null;
-  }
-
-  HeapSnapshotRepositoryMock({HeapSnapshotRepositoryMockCallback getter})
-      : _get = getter;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/icdata.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/icdata.dart
deleted file mode 100644
index ae440ef..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/icdata.dart
+++ /dev/null
@@ -1,21 +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.
-
-part of mocks;
-
-typedef Future<M.ICData> ICDataRepositoryMockCallback(
-    M.IsolateRef isolate, String id);
-
-class ICDataRepositoryMock implements M.ICDataRepository {
-  final ICDataRepositoryMockCallback _get;
-
-  ICDataRepositoryMock({ICDataRepositoryMockCallback getter}) : _get = getter;
-
-  Future<M.ICData> get(M.IsolateRef isolate, String id, {int count}) {
-    if (_get != null) {
-      return _get(isolate, id);
-    }
-    return new Future.value(null);
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/inbound_references.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/inbound_references.dart
deleted file mode 100644
index 9920048..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/inbound_references.dart
+++ /dev/null
@@ -1,23 +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
-
-part of mocks;
-
-typedef Future<M.InboundReferences> InboundReferencesRepositoryMockGetter(
-    M.IsolateRef i, String id);
-
-class InboundReferencesRepositoryMock implements M.InboundReferencesRepository {
-  final InboundReferencesRepositoryMockGetter _getter;
-
-  Future<M.InboundReferences> get(M.IsolateRef i, String id) {
-    if (_getter != null) {
-      return _getter(i, id);
-    }
-    return new Future.value(new InboundReferencesMock());
-  }
-
-  InboundReferencesRepositoryMock(
-      {InboundReferencesRepositoryMockGetter getter})
-      : _getter = getter;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/instance.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/instance.dart
deleted file mode 100644
index 7e13055..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/instance.dart
+++ /dev/null
@@ -1,22 +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.
-
-part of mocks;
-
-typedef Future<M.Instance> InstanceRepositoryMockCallback(
-    M.IsolateRef isolate, String id);
-
-class InstanceRepositoryMock implements M.InstanceRepository {
-  final InstanceRepositoryMockCallback _get;
-
-  InstanceRepositoryMock({InstanceRepositoryMockCallback getter})
-      : _get = getter;
-
-  Future<M.Instance> get(M.IsolateRef isolate, String id, {int count}) {
-    if (_get != null) {
-      return _get(isolate, id);
-    }
-    return new Future.value(null);
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/library.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/library.dart
deleted file mode 100644
index 9dc51b1..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/library.dart
+++ /dev/null
@@ -1,21 +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.
-
-part of mocks;
-
-typedef Future<M.Library> LibraryRepositoryMockCallback(
-    M.IsolateRef isolate, String id);
-
-class LibraryRepositoryMock implements M.LibraryRepository {
-  final LibraryRepositoryMockCallback _get;
-
-  LibraryRepositoryMock({LibraryRepositoryMockCallback getter}) : _get = getter;
-
-  Future<M.Library> get(M.IsolateRef isolate, String id) {
-    if (_get != null) {
-      return _get(isolate, id);
-    }
-    return new Future.value(null);
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/megamorphiccache.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/megamorphiccache.dart
deleted file mode 100644
index aabdf90..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/megamorphiccache.dart
+++ /dev/null
@@ -1,23 +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.
-
-part of mocks;
-
-typedef Future<M.MegamorphicCache> MegamorphicCacheRepositoryMockCallback(
-    M.IsolateRef isolate, String id);
-
-class MegamorphicCacheRepositoryMock implements M.MegamorphicCacheRepository {
-  final MegamorphicCacheRepositoryMockCallback _get;
-
-  MegamorphicCacheRepositoryMock(
-      {MegamorphicCacheRepositoryMockCallback getter})
-      : _get = getter;
-
-  Future<M.MegamorphicCache> get(M.IsolateRef isolate, String id, {int count}) {
-    if (_get != null) {
-      return _get(isolate, id);
-    }
-    return new Future.value(null);
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/notification.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/notification.dart
deleted file mode 100644
index 8855d92..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/notification.dart
+++ /dev/null
@@ -1,60 +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.
-
-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/tests/observatory_ui/mocks/repositories/object.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/object.dart
deleted file mode 100644
index f965665..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/object.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2017, 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;
-
-typedef Future<M.Object> ObjectRepositoryMockCallback(
-    M.IsolateRef isolate, String id);
-
-class ObjectRepositoryMock implements M.ObjectRepository {
-  final ObjectRepositoryMockCallback _get;
-
-  ObjectRepositoryMock({ObjectRepositoryMockCallback getter}) : _get = getter;
-
-  Future<M.Object> get(M.IsolateRef isolate, String id, {int count}) {
-    if (_get != null) {
-      return _get(isolate, id);
-    }
-    return new Future.value(null);
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/objectpool.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/objectpool.dart
deleted file mode 100644
index 2cbf99c..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/objectpool.dart
+++ /dev/null
@@ -1,22 +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
-
-part of mocks;
-
-typedef Future<M.ObjectPool> ObjectPoolRepositoryMockGetter(
-    M.IsolateRef i, String id);
-
-class ObjectPoolRepositoryMock implements M.ObjectPoolRepository {
-  final ObjectPoolRepositoryMockGetter _getter;
-
-  Future<M.ObjectPool> get(M.IsolateRef i, String id) {
-    if (_getter != null) {
-      return _getter(i, id);
-    }
-    return new Future.value(new ObjectPoolMock());
-  }
-
-  ObjectPoolRepositoryMock({ObjectPoolRepositoryMockGetter getter})
-      : _getter = getter;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/objectstore.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/objectstore.dart
deleted file mode 100644
index 373e872..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/objectstore.dart
+++ /dev/null
@@ -1,21 +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
-
-part of mocks;
-
-typedef Future<M.ObjectStore> ObjectStoreRepositoryMockGetter(M.IsolateRef i);
-
-class ObjectStoreRepositoryMock implements M.ObjectStoreRepository {
-  final ObjectStoreRepositoryMockGetter _getter;
-
-  Future<M.ObjectStore> get(M.IsolateRef i) {
-    if (_getter != null) {
-      return _getter(i);
-    }
-    return new Future.value(new ObjectStoreMock());
-  }
-
-  ObjectStoreRepositoryMock({ObjectStoreRepositoryMockGetter getter})
-      : _getter = getter;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/persistent_handles.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/persistent_handles.dart
deleted file mode 100644
index 518381d..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/persistent_handles.dart
+++ /dev/null
@@ -1,23 +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
-
-part of mocks;
-
-typedef Future<M.PersistentHandles> PersistentHandlesRepositoryMockGetter(
-    M.IsolateRef i);
-
-class PersistentHandlesRepositoryMock implements M.PersistentHandlesRepository {
-  final PersistentHandlesRepositoryMockGetter _getter;
-
-  Future<M.PersistentHandles> get(M.IsolateRef i) {
-    if (_getter != null) {
-      return _getter(i);
-    }
-    return new Future.value(new PortsAndHandlesMock());
-  }
-
-  PersistentHandlesRepositoryMock(
-      {PersistentHandlesRepositoryMockGetter getter})
-      : _getter = getter;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/ports.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/ports.dart
deleted file mode 100644
index 8bdbe4d..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/ports.dart
+++ /dev/null
@@ -1,20 +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
-
-part of mocks;
-
-typedef Future<M.Ports> PortsRepositoryMockGetter(M.IsolateRef i);
-
-class PortsRepositoryMock implements M.PortsRepository {
-  final PortsRepositoryMockGetter _getter;
-
-  Future<M.Ports> get(M.IsolateRef i) {
-    if (_getter != null) {
-      return _getter(i);
-    }
-    return new Future.value(new PortsAndHandlesMock());
-  }
-
-  PortsRepositoryMock({PortsRepositoryMockGetter getter}) : _getter = getter;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/reachable_size.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/reachable_size.dart
deleted file mode 100644
index 786e719..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/reachable_size.dart
+++ /dev/null
@@ -1,23 +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
-
-part of mocks;
-
-typedef Future<M.Guarded<M.Instance>> ReachableSizeRepositoryMockGetter(
-    M.IsolateRef i, String id);
-
-class ReachableSizeRepositoryMock implements M.ReachableSizeRepository {
-  final ReachableSizeRepositoryMockGetter _getter;
-
-  Future<M.Guarded<M.Instance>> get(M.IsolateRef i, String id) {
-    if (_getter != null) {
-      return _getter(i, id);
-    }
-    return new Future.value(
-        new GuardedMock<M.Instance>.fromSentinel(new SentinelMock()));
-  }
-
-  ReachableSizeRepositoryMock({ReachableSizeRepositoryMockGetter getter})
-      : _getter = getter;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/retained_size.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/retained_size.dart
deleted file mode 100644
index d5dba6f..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/retained_size.dart
+++ /dev/null
@@ -1,23 +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
-
-part of mocks;
-
-typedef Future<M.Guarded<M.Instance>> RetainedSizeRepositoryMockGetter(
-    M.IsolateRef i, String id);
-
-class RetainedSizeRepositoryMock implements M.RetainedSizeRepository {
-  final RetainedSizeRepositoryMockGetter _getter;
-
-  Future<M.Guarded<M.Instance>> get(M.IsolateRef i, String id) {
-    if (_getter != null) {
-      return _getter(i, id);
-    }
-    return new Future.value(
-        new GuardedMock<M.Instance>.fromSentinel(new SentinelMock()));
-  }
-
-  RetainedSizeRepositoryMock({RetainedSizeRepositoryMockGetter getter})
-      : _getter = getter;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/retaining_path.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/retaining_path.dart
deleted file mode 100644
index 5fef44a..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/retaining_path.dart
+++ /dev/null
@@ -1,22 +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
-
-part of mocks;
-
-typedef Future<M.RetainingPath> RetainingPathRepositoryMockGetter(
-    M.IsolateRef i, String id);
-
-class RetainingPathRepositoryMock implements M.RetainingPathRepository {
-  final RetainingPathRepositoryMockGetter _getter;
-
-  Future<M.RetainingPath> get(M.IsolateRef i, String id) {
-    if (_getter != null) {
-      return _getter(i, id);
-    }
-    return new Future.value(new RetainingPathMock());
-  }
-
-  RetainingPathRepositoryMock({RetainingPathRepositoryMockGetter getter})
-      : _getter = getter;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart
deleted file mode 100644
index 0beeaea..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart
+++ /dev/null
@@ -1,99 +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
-
-part of mocks;
-
-class SampleProfileLoadingProgressEventMock
-    implements M.SampleProfileLoadingProgressEvent {
-  final M.SampleProfileLoadingProgress progress;
-  SampleProfileLoadingProgressEventMock({this.progress});
-}
-
-class SampleProfileLoadingProgressMock
-    implements M.SampleProfileLoadingProgress {
-  final M.SampleProfileLoadingStatus status;
-  final double progress;
-  final Duration fetchingTime;
-  final Duration loadingTime;
-  final M.SampleProfile profile;
-
-  const SampleProfileLoadingProgressMock(
-      {this.status: M.SampleProfileLoadingStatus.disabled,
-      this.progress: 0.0,
-      this.fetchingTime: const Duration(),
-      this.loadingTime: const Duration(),
-      this.profile});
-}
-
-typedef Stream<
-    M
-        .SampleProfileLoadingProgressEvent> ClassSampleProfileRepositoryMockCallback(
-    M.Isolate isolate,
-    M.ClassRef cls,
-    M.SampleProfileTag tag,
-    bool clear,
-    bool forceFetch);
-typedef Future ClassSampleProfileRepositoryMockToggleCallback(
-    M.Isolate isolate, M.ClassRef cls);
-
-class ClassSampleProfileRepositoryMock
-    implements M.ClassSampleProfileRepository {
-  final ClassSampleProfileRepositoryMockCallback _get;
-  final ClassSampleProfileRepositoryMockToggleCallback _enable;
-  final ClassSampleProfileRepositoryMockToggleCallback _disable;
-
-  Stream<M.SampleProfileLoadingProgressEvent> get(
-      covariant M.Isolate isolate, M.ClassRef cls, M.SampleProfileTag tag,
-      {bool clear: false, bool forceFetch: false}) {
-    if (_get != null) {
-      return _get(isolate, cls, tag, clear, forceFetch);
-    }
-    return null;
-  }
-
-  Future enable(covariant M.Isolate isolate, M.ClassRef cls) {
-    if (_enable != null) {
-      return _enable(isolate, cls);
-    }
-    return new Future.value();
-  }
-
-  Future disable(covariant M.Isolate isolate, M.ClassRef cls) {
-    if (_disable != null) {
-      return _disable(isolate, cls);
-    }
-    return new Future.value();
-  }
-
-  ClassSampleProfileRepositoryMock(
-      {ClassSampleProfileRepositoryMockCallback getter,
-      ClassSampleProfileRepositoryMockToggleCallback enable,
-      ClassSampleProfileRepositoryMockToggleCallback disable})
-      : _get = getter,
-        _enable = enable,
-        _disable = disable;
-}
-
-typedef Stream<
-    M
-        .SampleProfileLoadingProgressEvent> IsolateampleProfileRepositoryMockCallback(
-    M.IsolateRef cls, M.SampleProfileTag tag, bool clear, bool forceFetch);
-
-class IsolateSampleProfileRepositoryMock
-    implements M.IsolateSampleProfileRepository {
-  final IsolateampleProfileRepositoryMockCallback _get;
-
-  Stream<M.SampleProfileLoadingProgressEvent> get(
-      M.IsolateRef isolate, M.SampleProfileTag tag,
-      {bool clear: false, bool forceFetch: false}) {
-    if (_get != null) {
-      return _get(isolate, tag, clear, forceFetch);
-    }
-    return null;
-  }
-
-  IsolateSampleProfileRepositoryMock(
-      {IsolateampleProfileRepositoryMockCallback getter})
-      : _get = getter;
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/script.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/script.dart
deleted file mode 100644
index efa60ae..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/script.dart
+++ /dev/null
@@ -1,21 +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.
-
-part of mocks;
-
-typedef Future<M.Script> ScriptRepositoryMockCallback(
-    M.IsolateRef isolate, String id);
-
-class ScriptRepositoryMock implements M.ScriptRepository {
-  final ScriptRepositoryMockCallback _get;
-
-  ScriptRepositoryMock({ScriptRepositoryMockCallback getter}) : _get = getter;
-
-  Future<M.Script> get(M.IsolateRef isolate, String id) {
-    if (_get != null) {
-      return _get(isolate, id);
-    }
-    return new Future.value(null);
-  }
-}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/target.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/target.dart
deleted file mode 100644
index c6b5187..0000000
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/target.dart
+++ /dev/null
@@ -1,83 +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.
-
-part of mocks;
-
-class TargetChangeEventMock implements M.TargetChangeEvent {
-  final TargetRepositoryMock repository;
-  const TargetChangeEventMock({this.repository});
-}
-
-typedef void TargetRepositoryMockStringCallback(String notification);
-typedef void TargetRepositoryMockTargetCallback(M.Target notification);
-
-class TargetRepositoryMock implements M.TargetRepository {
-  final StreamController<M.TargetChangeEvent> _onChange =
-      new StreamController<M.TargetChangeEvent>.broadcast();
-  Stream<M.TargetChangeEvent> get onChange => _onChange.stream;
-
-  bool get hasListeners => _onChange.hasListener;
-
-  final M.Target _current;
-  final Iterable<M.Target> _list;
-  final TargetRepositoryMockStringCallback _add;
-  final TargetRepositoryMockTargetCallback _setCurrent;
-  final TargetRepositoryMockTargetCallback _delete;
-
-  bool currentInvoked = false;
-  bool addInvoked = false;
-  bool listInvoked = false;
-  bool setCurrentInvoked = false;
-  bool deleteInvoked = false;
-
-  M.Target get current {
-    currentInvoked = true;
-    return _current;
-  }
-
-  void add(String val) {
-    addInvoked = true;
-    if (_add != null) _add(val);
-  }
-
-  Iterable<M.Target> list() {
-    listInvoked = true;
-    return _list;
-  }
-
-  void setCurrent(M.Target target) {
-    setCurrentInvoked = true;
-    if (_setCurrent != null) _setCurrent(target);
-  }
-
-  void delete(M.Target target) {
-    deleteInvoked = true;
-    if (_delete != null) _delete(target);
-  }
-
-  void triggerChangeEvent() {
-    _onChange.add(new TargetChangeEventMock(repository: this));
-  }
-
-  M.Target find(String networkAddress) {
-    return const TargetMock();
-  }
-
-  @override
-  bool isConnectedVMTarget(M.Target target) {
-    return false;
-  }
-
-  TargetRepositoryMock(
-      {M.Target current,
-      Iterable<M.Target> list: const [],
-      TargetRepositoryMockStringCallback add,
-      TargetRepositoryMockTargetCallback setCurrent,
-      TargetRepositoryMockTargetCallback delete})
-      : _current = current,
-        _list = list,
-        _add = add,
-        _setCurrent = setCurrent,
-        _delete = delete;
-}
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
deleted file mode 100644
index ba755bc..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.dart
+++ /dev/null
@@ -1,31 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/nav/class_menu.dart';
-import '../../mocks.dart';
-
-main() {
-  NavClassMenuElement.tag.ensureRegistration();
-
-  final i_ref = const IsolateRefMock(id: 'i-id', name: 'i-name');
-  final c_ref = const ClassRefMock(id: 'c-id', name: 'c-name');
-  test('instantiation', () {
-    final 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 e = new NavClassMenuElement(i_ref, c_ref);
-    e.content = <Element>[document.createElement('content')];
-    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/nav/class-menu/element_test.html b/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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
deleted file mode 100644
index 80d3e70..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart
+++ /dev/null
@@ -1,65 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/nav/isolate_menu.dart';
-import '../../mocks.dart';
-
-main() {
-  NavIsolateMenuElement.tag.ensureRegistration();
-
-  final tag = '.nav-menu_label > a';
-
-  EventRepositoryMock events;
-  final ref = const IsolateRefMock(id: 'i-id', name: 'old-name');
-  final obj = const IsolateMock(id: 'i-id', name: 'new-name');
-  setUp(() {
-    events = new EventRepositoryMock();
-  });
-  group('instantiation', () {
-    test('IsolateRef', () {
-      final e = new NavIsolateMenuElement(ref, events);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.isolate, equals(ref));
-    });
-    test('Isolate', () {
-      final e = new NavIsolateMenuElement(obj, events);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.isolate, equals(obj));
-    });
-  });
-  test('elements created after attachment', () async {
-    final e = new NavIsolateMenuElement(ref, events);
-    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('updates', () {
-    test('are correctly listen', () async {
-      final e = new NavIsolateMenuElement(ref, events);
-      expect(events.onIsolateUpdateHasListener, isFalse);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(events.onIsolateUpdateHasListener, isTrue);
-      e.remove();
-      await e.onRendered.first;
-      expect(events.onIsolateUpdateHasListener, isFalse);
-    });
-    test('have effects', () async {
-      final e = new NavIsolateMenuElement(ref, events);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.querySelector(tag).text.contains(ref.name), isTrue);
-      events.add(new IsolateUpdateEventMock(isolate: obj));
-      await e.onRendered.first;
-      expect(e.querySelector(tag).text.contains(ref.name), isFalse);
-      expect(e.querySelector(tag).text.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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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
deleted file mode 100644
index 59c59b6..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/nav/library_menu.dart';
-import '../../mocks.dart';
-
-main() {
-  NavLibraryMenuElement.tag.ensureRegistration();
-
-  final i_ref = const IsolateRefMock(id: 'i-id', name: 'i-name');
-  final l_ref = const LibraryRefMock(id: 'l-id', name: 'l-name');
-  test('instantiation', () {
-    final 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 e = new NavLibraryMenuElement(i_ref, l_ref);
-    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/nav/library-menu/element_test.html b/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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
deleted file mode 100644
index 8f77748..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart
+++ /dev/null
@@ -1,72 +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.
-
-import 'dart:html';
-import 'package:test/test.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 e = new NavMenuItemElement(label);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.label, equals(label), reason: 'element correctly created');
-    });
-    test('label', () {
-      final 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 e = new NavMenuItemElement(label);
-      e.content = <Element>[document.createElement('content')];
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.children.length, isNonZero, reason: 'has elements');
-      expect(e.querySelector('content'), isNotNull,
-          reason: 'has content elements');
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-    test('react to label change', () async {
-      final label1 = 'custom-label-1';
-      final label2 = 'custom-label-2';
-      final e = new NavMenuItemElement(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(label1), isFalse);
-      expect(e.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 e = new NavMenuItemElement(label, link: link1);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.innerHtml.contains(link1), isTrue);
-      expect(e.innerHtml.contains(link2), isFalse);
-      e.link = link2;
-      await e.onRendered.first;
-      expect(e.innerHtml.contains(link1), isFalse);
-      expect(e.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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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
deleted file mode 100644
index 3fafd60..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart
+++ /dev/null
@@ -1,118 +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.
-
-import 'dart:html' hide Notification, NotificationEvent;
-import 'package:test/test.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';
-import '../../mocks.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', () {
-    NotificationRepositoryMock repository;
-    setUp(() {
-      repository = new NotificationRepositoryMock();
-    });
-    test('default', () {
-      final e = new NavNotifyElement(repository);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.notifyOnPause, isTrue, reason: 'notifyOnPause is default');
-    });
-    test('notify on pause', () {
-      final e = new NavNotifyElement(repository, 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 e = new NavNotifyElement(repository, notifyOnPause: false);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.notifyOnPause, isFalse, reason: 'notifyOnPause is the same');
-    });
-  });
-  test('is correctly listening', () async {
-    final repository = new NotificationRepositoryMock();
-    final 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 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 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 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 repository = new NotificationRepositoryMock(list: list);
-      final 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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/notify/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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
deleted file mode 100644
index 557a278..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart
+++ /dev/null
@@ -1,66 +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.
-
-import 'dart:html';
-import 'dart:async';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/nav/notify_event.dart';
-import '../../mocks.dart';
-
-main() {
-  NavNotifyEventElement.tag.ensureRegistration();
-
-  final event = new PauseStartEventMock(
-      isolate: new IsolateMock(id: 'isolate-id', name: 'isolate-name'));
-  group('instantiation', () {
-    test('default', () {
-      final e = new NavNotifyEventElement(event);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.event, equals(event));
-    });
-  });
-  group('elements', () {
-    test('created after attachment', () async {
-      final 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(expectAsync1((_) {}, count: 1, reason: 'event is fired'));
-      e.querySelector('a').click();
-    });
-    test('onDelete events (DOM)', () async {
-      sub = e.onDelete.listen(expectAsync1((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(expectAsync1((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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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
deleted file mode 100644
index 473ab77..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart
+++ /dev/null
@@ -1,64 +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.
-
-import 'dart:html';
-import 'dart:async';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/nav/notify_exception.dart';
-import '../../mocks.dart';
-
-main() {
-  NavNotifyExceptionElement.tag.ensureRegistration();
-
-  final exception = new ConnectionExceptionMock(message: 'message');
-  test('instantiation', () {
-    final e = new NavNotifyExceptionElement(exception);
-    expect(e, isNotNull, reason: 'element correctly created');
-  });
-  test('elements created after attachment', () async {
-    final 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(expectAsync1((_) {}, count: 1, reason: 'event is fired'));
-      e.querySelector('a').click();
-    });
-    test('onDelete events (DOM)', () async {
-      sub = e.onDelete.listen(expectAsync1((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(expectAsync1((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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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
deleted file mode 100644
index d521aa2..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart
+++ /dev/null
@@ -1,91 +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.
-
-import 'dart:html';
-import 'dart:async';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/nav/notify_exception.dart';
-
-main() {
-  NavNotifyExceptionElement.tag.ensureRegistration();
-
-  final st = new StackTrace.fromString('stacktrace string');
-  group('normal exception', () {
-    final ex = new Exception('exception message');
-    group('instantiation', () {
-      test('no stacktrace', () {
-        final e = new NavNotifyExceptionElement(ex);
-        expect(e, isNotNull, reason: 'element correctly created');
-        expect(e.exception, equals(ex));
-        expect(e.stacktrace, isNull);
-      });
-      test('with stacktrace', () {
-        final e = new NavNotifyExceptionElement(ex, stacktrace: st);
-        expect(e, isNotNull, reason: 'element correctly created');
-        expect(e.exception, equals(ex));
-        expect(e.stacktrace, equals(st));
-      });
-    });
-    group('elements', () {
-      test('created after attachment (no stacktrace)', () async {
-        final e = new NavNotifyExceptionElement(ex);
-        document.body.append(e);
-        await e.onRendered.first;
-        expect(e.children.length, isNonZero, reason: 'has elements');
-        expect(e.innerHtml.contains(ex.toString()), isTrue);
-        expect(e.innerHtml.contains(st.toString()), isFalse);
-        e.remove();
-        await e.onRendered.first;
-        expect(e.children.length, isZero, reason: 'is empty');
-      });
-      test('created after attachment (with stacktrace)', () async {
-        final e = new NavNotifyExceptionElement(ex, stacktrace: st);
-        document.body.append(e);
-        await e.onRendered.first;
-        expect(e.children.length, isNonZero, reason: 'has elements');
-        expect(e.innerHtml.contains(ex.toString()), isTrue);
-        expect(e.innerHtml.contains(st.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(ex, stacktrace: st);
-        document.body.append(e);
-        await e.onRendered.first;
-      });
-      tearDown(() {
-        sub.cancel();
-        e.remove();
-      });
-      test('navigation after connect', () async {
-        sub = window.onPopState
-            .listen(expectAsync1((_) {}, count: 1, reason: 'event is fired'));
-        e.querySelector('a').click();
-      });
-      test('onDelete events (DOM)', () async {
-        sub = e.onDelete.listen(expectAsync1((ExceptionDeleteEvent event) {
-          expect(event, isNotNull, reason: 'event is passed');
-          expect(event.exception, equals(ex), reason: 'exception is the same');
-          expect(event.stacktrace, equals(st),
-              reason: 'stacktrace is the same');
-        }, count: 1, reason: 'event is fired'));
-        e.querySelector('button').click();
-      });
-      test('onDelete events (code)', () async {
-        sub = e.onDelete.listen(expectAsync1((ExceptionDeleteEvent event) {
-          expect(event, isNotNull, reason: 'event is passed');
-          expect(event.exception, equals(ex), reason: 'exception is the same');
-          expect(event.stacktrace, equals(st),
-              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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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
deleted file mode 100644
index 6880244..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart
+++ /dev/null
@@ -1,124 +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.
-
-import 'dart:html';
-import 'dart:async';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/nav/refresh.dart';
-
-main() {
-  NavRefreshElement.tag.ensureRegistration();
-
-  group('instantiation', () {
-    test('no parameters', () {
-      final 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 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 e = new NavRefreshElement(disabled: false);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.disabled, isFalse, reason: 'element correctly created');
-    });
-    test('disabled', () {
-      final 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 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 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 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 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(expectAsync1((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(expectAsync1((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(expectAsync1((_) {}, count: 0));
-      e.refresh();
-    });
-    test('does not fires on click if disabled', () async {
-      e.disabled = true;
-      sub = e.onRefresh.listen(expectAsync1((_) {}, 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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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
deleted file mode 100644
index 7ddd2ca..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/top_menu/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/nav/top_menu.dart';
-
-main() {
-  NavTopMenuElement.tag.ensureRegistration();
-
-  test('instantiation', () {
-    final e = new NavTopMenuElement();
-    expect(e, isNotNull, reason: 'element correctly created');
-  });
-  group('elements', () {
-    test('created', () async {
-      final e = new NavTopMenuElement();
-      e.content = <Element>[document.createElement('content')];
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.children.length, isNonZero, reason: 'has elements');
-      expect(e.querySelector('content'), isNotNull,
-          reason: 'has content elements');
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-  });
-}
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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/top_menu/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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
deleted file mode 100644
index be95c7a..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart
+++ /dev/null
@@ -1,70 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/nav/menu_item.dart';
-import 'package:observatory/src/elements/nav/vm_menu.dart';
-import '../../mocks.dart';
-
-main() {
-  NavVMMenuElement.tag.ensureRegistration();
-
-  final mTag = '.nav-menu_label > a';
-  final miTag = NavMenuItemElement.tag.name;
-
-  EventRepositoryMock events;
-  final vm1 = const VMMock(
-      name: 'vm-name-1',
-      displayName: 'display-name-1',
-      isolates: const [const IsolateRefMock(id: 'i-id-1', name: 'i-name-1')]);
-  final vm2 = const VMMock(
-      name: 'vm-name-2',
-      displayName: 'display-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(() {
-    events = new EventRepositoryMock();
-  });
-  test('instantiation', () {
-    final e = new NavVMMenuElement(vm1, events);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.vm, equals(vm1));
-  });
-  test('elements created after attachment', () async {
-    final e = new NavVMMenuElement(vm1, events);
-    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('updates', () {
-    test('are correctly listen', () async {
-      final e = new NavVMMenuElement(vm1, events);
-      expect(events.onVMUpdateHasListener, isFalse);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(events.onVMUpdateHasListener, isTrue);
-      e.remove();
-      await e.onRendered.first;
-      expect(events.onVMUpdateHasListener, isFalse);
-    });
-    test('have effects', () async {
-      final e = new NavVMMenuElement(vm1, events);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.querySelectorAll(mTag).single.text, equals(vm1.displayName));
-      expect(e.querySelectorAll(miTag).length, equals(vm1.isolates.length));
-      events.add(new VMUpdateEventMock(vm: vm2));
-      await e.onRendered.first;
-      expect(e.querySelectorAll(mTag).single.text, equals(vm2.displayName));
-      expect(e.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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/object_common/element_test.dart b/runtime/observatory/tests/observatory_ui/object_common/element_test.dart
deleted file mode 100644
index c589cbf..0000000
--- a/runtime/observatory/tests/observatory_ui/object_common/element_test.dart
+++ /dev/null
@@ -1,103 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/class_ref.dart';
-import 'package:observatory/src/elements/inbound_references.dart';
-import 'package:observatory/src/elements/object_common.dart';
-import 'package:observatory/src/elements/retaining_path.dart';
-import '../mocks.dart';
-
-main() {
-  ObjectCommonElement.tag.ensureRegistration();
-
-  final cTag = ClassRefElement.tag.name;
-  final iTag = InboundReferencesElement.tag.name;
-  final rTag = RetainingPathElement.tag.name;
-
-  const isolate = const IsolateRefMock();
-  const object = const InstanceMock();
-  final reachableSizes = new ReachableSizeRepositoryMock();
-  final retainedSizes = new RetainedSizeRepositoryMock();
-  final inbounds = new InboundReferencesRepositoryMock();
-  final paths = new RetainingPathRepositoryMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new ObjectCommonElement(isolate, object, retainedSizes,
-        reachableSizes, inbounds, paths, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.object, equals(object));
-  });
-  group('elements', () {
-    test('created after attachment', () async {
-      final e = new ObjectCommonElement(isolate, object, retainedSizes,
-          reachableSizes, inbounds, paths, objects);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.children.length, isNonZero, reason: 'has elements');
-      expect(e.querySelectorAll(cTag).length, equals(1));
-      expect(e.querySelectorAll(iTag).length, equals(1));
-      expect(e.querySelectorAll(rTag).length, equals(1));
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-    test('created after attachment', () async {
-      const value = const GuardedMock<InstanceMock>.fromValue(
-          const InstanceMock(valueAsString: '10'));
-      bool invoked = false;
-      final reachableSizes = new ReachableSizeRepositoryMock(
-          getter: expectAsync2((i, id) async {
-        expect(i, equals(isolate));
-        expect(id, equals(object.id));
-        invoked = true;
-        return value;
-      }, count: 1));
-      final e = new ObjectCommonElement(isolate, object, retainedSizes,
-          reachableSizes, inbounds, paths, objects);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(invoked, isFalse);
-      expect(e.children.length, isNonZero, reason: 'has elements');
-      expect(e.querySelectorAll(cTag).length, equals(1));
-      expect(e.querySelectorAll(iTag).length, equals(1));
-      expect(e.querySelectorAll(rTag).length, equals(1));
-      e.querySelector('.reachable_size').click();
-      await e.onRendered.first;
-      expect(invoked, isTrue);
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-    test('created after attachment', () async {
-      const value = const GuardedMock<InstanceMock>.fromValue(
-          const InstanceMock(valueAsString: '10'));
-      bool invoked = false;
-      final retainedSizes = new RetainedSizeRepositoryMock(
-          getter: expectAsync2((i, id) async {
-        expect(i, equals(isolate));
-        expect(id, equals(object.id));
-        invoked = true;
-        return value;
-      }, count: 1));
-      final e = new ObjectCommonElement(isolate, object, retainedSizes,
-          reachableSizes, inbounds, paths, objects);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(invoked, isFalse);
-      expect(e.children.length, isNonZero, reason: 'has elements');
-      expect(e.querySelectorAll(cTag).length, equals(1));
-      expect(e.querySelectorAll(iTag).length, equals(1));
-      expect(e.querySelectorAll(rTag).length, equals(1));
-      e.querySelector('.retained_size').click();
-      await e.onRendered.first;
-      expect(invoked, isTrue);
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/object_common/element_test.html b/runtime/observatory/tests/observatory_ui/object_common/element_test.html
deleted file mode 100644
index 39c5683..0000000
--- a/runtime/observatory/tests/observatory_ui/object_common/element_test.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
-<!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>
-</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/objectpool_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/objectpool_ref/element_test.dart
deleted file mode 100644
index 5c5ec9d..0000000
--- a/runtime/observatory/tests/observatory_ui/objectpool_ref/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/objectpool_ref.dart';
-import '../mocks.dart';
-
-main() {
-  ObjectPoolRefElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock();
-  const pool = const ObjectPoolRefMock();
-  test('instantiation', () {
-    final e = new ObjectPoolRefElement(isolate, pool);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.pool, equals(pool));
-  });
-  test('elements created after attachment', () async {
-    final e = new ObjectPoolRefElement(isolate, pool);
-    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/objectpool_ref/element_test.html b/runtime/observatory/tests/observatory_ui/objectpool_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/objectpool_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/objectpool_view/element_test.dart b/runtime/observatory/tests/observatory_ui/objectpool_view/element_test.dart
deleted file mode 100644
index a8c1d4a..0000000
--- a/runtime/observatory/tests/observatory_ui/objectpool_view/element_test.dart
+++ /dev/null
@@ -1,55 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/nav/refresh.dart';
-import 'package:observatory/src/elements/object_common.dart';
-import 'package:observatory/src/elements/objectpool_view.dart';
-import '../mocks.dart';
-
-main() {
-  ObjectPoolViewElement.tag.ensureRegistration();
-
-  final cTag = ObjectCommonElement.tag.name;
-  final rTag = NavRefreshElement.tag.name;
-
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notifs = new NotificationRepositoryMock();
-  final pool = const ObjectPoolMock();
-  final pools = new ObjectPoolRepositoryMock();
-  final reachableSizes = new ReachableSizeRepositoryMock();
-  final retainedSizes = new RetainedSizeRepositoryMock();
-  final inbounds = new InboundReferencesRepositoryMock();
-  final paths = new RetainingPathRepositoryMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new ObjectPoolViewElement(vm, isolate, pool, events, notifs,
-        pools, retainedSizes, reachableSizes, inbounds, paths, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.pool, equals(pool));
-  });
-  test('elements created after attachment', () async {
-    final pools = new ObjectPoolRepositoryMock(
-        getter: expectAsync2((i, id) async {
-      expect(i, equals(isolate));
-      expect(id, equals(pool.id));
-      return pool;
-    }, count: 1));
-    final e = new ObjectPoolViewElement(vm, isolate, pool, events, notifs,
-        pools, retainedSizes, reachableSizes, inbounds, paths, objects);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelectorAll(cTag).length, equals(1));
-    (e.querySelector(rTag) as NavRefreshElement).refresh();
-    await e.onRendered.first;
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/objectpool_view/element_test.html b/runtime/observatory/tests/observatory_ui/objectpool_view/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/objectpool_view/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/objectstore_view/element_test.dart b/runtime/observatory/tests/observatory_ui/objectstore_view/element_test.dart
deleted file mode 100644
index 1c8ca9b..0000000
--- a/runtime/observatory/tests/observatory_ui/objectstore_view/element_test.dart
+++ /dev/null
@@ -1,49 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/objectstore_view.dart';
-import '../mocks.dart';
-
-main() {
-  ObjectStoreViewElement.tag.ensureRegistration();
-
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notifs = new NotificationRepositoryMock();
-  final stores = new ObjectStoreRepositoryMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new ObjectStoreViewElement(
-        vm, isolate, events, notifs, stores, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-  });
-  test('elements created after attachment', () async {
-    const fields = const [
-      const NamedFieldMock(name: 'field-1'),
-      const NamedFieldMock(name: 'field-2'),
-      const NamedFieldMock(name: 'field-3')
-    ];
-    const store = const ObjectStoreMock(fields: fields);
-    final stores = new ObjectStoreRepositoryMock(
-        getter: expectAsync1((i) async {
-      expect(i, equals(isolate));
-      return store;
-    }, count: 1));
-    final objects = new ObjectRepositoryMock();
-    final e = new ObjectStoreViewElement(
-        vm, isolate, events, notifs, stores, objects);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    await e.onRendered.first;
-    expect(e.querySelectorAll('.memberItem').length, equals(fields.length));
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/objectstore_view/element_test.html b/runtime/observatory/tests/observatory_ui/objectstore_view/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/objectstore_view/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/pc_descriptors_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/pc_descriptors_ref/element_test.dart
deleted file mode 100644
index 4b5c081..0000000
--- a/runtime/observatory/tests/observatory_ui/pc_descriptors_ref/element_test.dart
+++ /dev/null
@@ -1,28 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/sentinel_value.dart';
-import '../mocks.dart';
-
-main() {
-  SentinelValueElement.tag.ensureRegistration();
-
-  const sentinel = const SentinelMock();
-  test('instantiation', () {
-    final e = new SentinelValueElement(sentinel);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.sentinel, equals(sentinel));
-  });
-  test('elements created after attachment', () async {
-    final e = new SentinelValueElement(sentinel);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.text, isNotEmpty, reason: 'has text');
-    expect(e.title, isNotEmpty, reason: 'has title');
-    e.remove();
-    await e.onRendered.first;
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/pc_descriptors_ref/element_test.html b/runtime/observatory/tests/observatory_ui/pc_descriptors_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/pc_descriptors_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/persistent_handles_page/element_test.dart b/runtime/observatory/tests/observatory_ui/persistent_handles_page/element_test.dart
deleted file mode 100644
index 75cafc5..0000000
--- a/runtime/observatory/tests/observatory_ui/persistent_handles_page/element_test.dart
+++ /dev/null
@@ -1,41 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/persistent_handles.dart';
-import '../mocks.dart';
-
-main() {
-  PersistentHandlesPageElement.tag.ensureRegistration();
-
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notifs = new NotificationRepositoryMock();
-  final repository = new PersistentHandlesRepositoryMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new PersistentHandlesPageElement(
-        vm, isolate, events, notifs, repository, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-  });
-  test('elements created after attachment', () async {
-    final repository = new PersistentHandlesRepositoryMock(
-        getter: expectAsync1((i) async {
-      expect(i, equals(isolate));
-      return const PersistentHandlesMock();
-    }, count: 1));
-    final objects = new ObjectRepositoryMock();
-    final e = new PersistentHandlesPageElement(
-        vm, isolate, events, notifs, repository, objects);
-    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/persistent_handles_page/element_test.html b/runtime/observatory/tests/observatory_ui/persistent_handles_page/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/persistent_handles_page/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/ports/element_test.dart b/runtime/observatory/tests/observatory_ui/ports/element_test.dart
deleted file mode 100644
index 876f0db..0000000
--- a/runtime/observatory/tests/observatory_ui/ports/element_test.dart
+++ /dev/null
@@ -1,48 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/ports.dart';
-import '../mocks.dart';
-
-main() {
-  PortsElement.tag.ensureRegistration();
-
-  const vm = const VMMock();
-  const isolate = const IsolateRefMock();
-  final events = new EventRepositoryMock();
-  final notifs = new NotificationRepositoryMock();
-  final ports = new PortsRepositoryMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new PortsElement(vm, isolate, events, notifs, ports, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.ports, equals(ports));
-  });
-  test('elements created after attachment', () async {
-    const elements = const [
-      const PortMock(name: 'port-1'),
-      const PortMock(name: 'port-2'),
-      const PortMock(name: 'port-3')
-    ];
-    const isolatePorts = const PortsAndHandlesMock(elements: elements);
-    final ports = new PortsRepositoryMock(
-        getter: expectAsync1((i) async {
-      expect(i, equals(isolate));
-      return isolatePorts;
-    }, count: 1));
-    final objects = new ObjectRepositoryMock();
-    final e = new PortsElement(vm, isolate, events, notifs, ports, objects);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    await e.onRendered.first;
-    expect(e.querySelectorAll('.port-number').length, equals(elements.length));
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/ports/element_test.html b/runtime/observatory/tests/observatory_ui/ports/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/ports/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/retaining_path/element_test.dart b/runtime/observatory/tests/observatory_ui/retaining_path/element_test.dart
deleted file mode 100644
index 2f10ece..0000000
--- a/runtime/observatory/tests/observatory_ui/retaining_path/element_test.dart
+++ /dev/null
@@ -1,55 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/curly_block.dart';
-import 'package:observatory/src/elements/instance_ref.dart';
-import 'package:observatory/src/elements/retaining_path.dart';
-import '../mocks.dart';
-
-main() {
-  RetainingPathElement.tag.ensureRegistration();
-
-  final cTag = CurlyBlockElement.tag.name;
-  final iTag = InstanceRefElement.tag.name;
-
-  const isolate = const IsolateRefMock();
-  const object = const InstanceRefMock();
-  final paths = new RetainingPathRepositoryMock();
-  final objects = new ObjectRepositoryMock();
-  test('instantiation', () {
-    final e = new RetainingPathElement(isolate, object, paths, objects);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.object, equals(object));
-  });
-  test('elements created after attachment', () async {
-    const source = const InstanceRefMock(id: 'source-id', name: 'source_name');
-    const path = const RetainingPathMock(
-        elements: const [const RetainingPathItemMock(source: source)]);
-    bool invoked = false;
-    final paths = new RetainingPathRepositoryMock(
-        getter: expectAsync2((i, id) async {
-      expect(i, equals(isolate));
-      expect(id, equals(object.id));
-      invoked = true;
-      return path;
-    }, count: 1));
-    final objects = new ObjectRepositoryMock();
-    final e = new RetainingPathElement(isolate, object, paths, objects);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(invoked, isFalse);
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelectorAll(iTag).length, isZero);
-    (e.querySelector(cTag) as CurlyBlockElement).toggle();
-    await e.onRendered.first;
-    expect(invoked, isTrue);
-    expect(e.querySelectorAll(iTag).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/retaining_path/element_test.html b/runtime/observatory/tests/observatory_ui/retaining_path/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/retaining_path/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/sample_buffer_control/element_test.dart b/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.dart
deleted file mode 100644
index 9820989..0000000
--- a/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.dart
+++ /dev/null
@@ -1,166 +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.
-
-import 'dart:html';
-import 'dart:async';
-import 'package:test/test.dart';
-import 'package:observatory/models.dart' as M;
-import 'package:observatory/src/elements/sample_buffer_control.dart';
-import '../mocks.dart';
-
-main() {
-  SampleBufferControlElement.tag.ensureRegistration();
-
-  const vm = const VMMock();
-
-  group('instantiation', () {
-    SampleProfileLoadingProgressMock progress;
-    StreamController<SampleProfileLoadingProgressEventMock> events;
-    setUp(() {
-      progress = new SampleProfileLoadingProgressMock();
-      events = new StreamController<SampleProfileLoadingProgressEventMock>();
-    });
-    test('no additional parameters', () {
-      final e = new SampleBufferControlElement(vm, progress, events.stream);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.progress, equals(progress));
-      expect(e.selectedTag, equals(M.SampleProfileTag.none));
-      expect(e.showTag, isTrue);
-    });
-    test('selected tag', () {
-      const tag = M.SampleProfileTag.userOnly;
-      final e = new SampleBufferControlElement(vm, progress, events.stream,
-          selectedTag: tag);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.progress, equals(progress));
-      expect(e.selectedTag, equals(tag));
-      expect(e.showTag, isTrue);
-    });
-    test('show tag (true)', () {
-      final e = new SampleBufferControlElement(vm, progress, events.stream,
-          showTag: true);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.progress, equals(progress));
-      expect(e.selectedTag, equals(M.SampleProfileTag.none));
-      expect(e.showTag, isTrue);
-    });
-    test('show tag (false)', () {
-      final e = new SampleBufferControlElement(vm, progress, events.stream,
-          showTag: false);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.progress, equals(progress));
-      expect(e.selectedTag, equals(M.SampleProfileTag.none));
-      expect(e.showTag, isFalse);
-    });
-  });
-  group('elements', () {
-    SampleProfileLoadingProgressMock progress;
-    StreamController<SampleProfileLoadingProgressEventMock> events;
-    setUp(() {
-      progress = new SampleProfileLoadingProgressMock();
-      events = new StreamController<SampleProfileLoadingProgressEventMock>();
-    });
-    test('created after attachment', () async {
-      final e = new SampleBufferControlElement(vm, progress, events.stream);
-      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('listen for status changes', () async {
-      final e = new SampleBufferControlElement(vm, progress, events.stream);
-      expect(events.hasListener, isFalse);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(events.hasListener, isTrue);
-      events.add(new SampleProfileLoadingProgressEventMock(progress: progress));
-      events.close();
-      await e.onRendered.first;
-      e.remove();
-      await e.onRendered.first;
-    });
-    test('follow updates changes', () async {
-      final e = new SampleBufferControlElement(vm, progress, events.stream);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.querySelector('select'), isNull);
-      events.add(new SampleProfileLoadingProgressEventMock(
-          progress: new SampleProfileLoadingProgressMock(
-              status: M.SampleProfileLoadingStatus.fetching)));
-      await e.onRendered.first;
-      expect(e.querySelector('select'), isNull);
-      events.add(new SampleProfileLoadingProgressEventMock(
-          progress: new SampleProfileLoadingProgressMock(
-              status: M.SampleProfileLoadingStatus.loading)));
-      await e.onRendered.first;
-      expect(e.querySelector('select'), isNull);
-      events.add(new SampleProfileLoadingProgressEventMock(
-          progress: new SampleProfileLoadingProgressMock(
-              status: M.SampleProfileLoadingStatus.loaded,
-              profile: new SampleProfileMock())));
-      events.close();
-      await e.onRendered.first;
-      expect(e.querySelector('select'), isNotNull);
-      e.remove();
-      await e.onRendered.first;
-    });
-    test('follow updates changes (no tag)', () async {
-      final e = new SampleBufferControlElement(vm, progress, events.stream,
-          showTag: false);
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.querySelector('select'), isNull);
-      events.add(new SampleProfileLoadingProgressEventMock(
-          progress: new SampleProfileLoadingProgressMock(
-              status: M.SampleProfileLoadingStatus.fetching)));
-      await e.onRendered.first;
-      expect(e.querySelector('select'), isNull);
-      events.add(new SampleProfileLoadingProgressEventMock(
-          progress: new SampleProfileLoadingProgressMock(
-              status: M.SampleProfileLoadingStatus.loading)));
-      await e.onRendered.first;
-      expect(e.querySelector('select'), isNull);
-      events.add(new SampleProfileLoadingProgressEventMock(
-          progress: new SampleProfileLoadingProgressMock(
-              status: M.SampleProfileLoadingStatus.loaded,
-              profile: new SampleProfileMock())));
-      await e.onRendered.first;
-      expect(e.querySelector('select'), isNull);
-      e.remove();
-      await e.onRendered.first;
-    });
-  });
-  group('events', () {
-    SampleProfileLoadingProgressMock progress;
-    StreamController<SampleProfileLoadingProgressEventMock> events;
-    setUp(() {
-      progress = new SampleProfileLoadingProgressMock();
-      events = new StreamController<SampleProfileLoadingProgressEventMock>();
-    });
-    test('onModeChange', () async {
-      final e = new SampleBufferControlElement(vm, progress, events.stream);
-      document.body.append(e);
-      await e.onRendered.first;
-      events.add(new SampleProfileLoadingProgressEventMock(
-          progress: new SampleProfileLoadingProgressMock(
-              status: M.SampleProfileLoadingStatus.loaded,
-              profile: new SampleProfileMock())));
-      await e.onRendered.first;
-      expect(e.selectedTag, equals(M.SampleProfileTag.none));
-      e.onTagChange.listen(expectAsync1((_) {
-        expect(e.selectedTag, equals(M.SampleProfileTag.userOnly));
-      }, count: 1));
-      final select = (e.querySelector('.tag-select') as SelectElement);
-      select.selectedIndex = select.options.indexOf((select.options.toSet()
-            ..removeAll(select.selectedOptions))
-          .toList()
-          .first);
-      select.dispatchEvent(new Event("change"));
-      e.remove();
-      await e.onRendered.first;
-    });
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.html b/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/script_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart
deleted file mode 100644
index ae6d7f5..0000000
--- a/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart
+++ /dev/null
@@ -1,37 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/script_ref.dart';
-import '../mocks.dart';
-
-main() {
-  ScriptRefElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock(id: 'isolate-id');
-  const file = 'filename.dart';
-  const ref = const ScriptRefMock(id: 'script-id', uri: 'package/$file');
-  group('instantiation', () {
-    test('no position', () {
-      final e = new ScriptRefElement(isolate, ref);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.isolate, equals(isolate));
-      expect(e.script, equals(ref));
-    });
-  });
-  test('elements created after attachment', () async {
-    final e = new ScriptRefElement(isolate, ref);
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.innerHtml.contains(isolate.id), isTrue,
-        reason: 'no message in the component');
-    expect(e.innerHtml.contains(file), isTrue,
-        reason: 'no message in the component');
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/script_ref/element_test.html b/runtime/observatory/tests/observatory_ui/script_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/script_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/sentinel_value/element_test.dart b/runtime/observatory/tests/observatory_ui/sentinel_value/element_test.dart
deleted file mode 100644
index 69d3b11..0000000
--- a/runtime/observatory/tests/observatory_ui/sentinel_value/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/pc_descriptors_ref.dart';
-import '../mocks.dart';
-
-main() {
-  PcDescriptorsRefElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock();
-  const descriptors = const PcDescriptorsRefMock();
-  test('instantiation', () {
-    final e = new PcDescriptorsRefElement(isolate, descriptors);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.descriptors, equals(descriptors));
-  });
-  test('elements created after attachment', () async {
-    final e = new PcDescriptorsRefElement(isolate, descriptors);
-    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/sentinel_value/element_test.html b/runtime/observatory/tests/observatory_ui/sentinel_value/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/sentinel_value/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/source_link/element_test.dart b/runtime/observatory/tests/observatory_ui/source_link/element_test.dart
deleted file mode 100644
index a6c10bb..0000000
--- a/runtime/observatory/tests/observatory_ui/source_link/element_test.dart
+++ /dev/null
@@ -1,51 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/source_link.dart';
-import '../mocks.dart';
-
-main() {
-  SourceLinkElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock(id: 'isolate-id');
-  const script_id = 'script-id';
-  const file = 'filename.dart';
-  final script = new ScriptMock(
-      id: script_id,
-      uri: 'package/$file',
-      tokenToLine: (int token) => 1,
-      tokenToCol: (int token) => 2);
-  final location =
-      new SourceLocationMock(script: script, tokenPos: 0, endTokenPos: 1);
-  final repository = new ScriptRepositoryMock();
-  test('instantiation', () {
-    final e = new SourceLinkElement(isolate, location, repository);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.location, equals(location));
-  });
-  test('elements created after attachment', () async {
-    bool rendered = false;
-    final repository = new ScriptRepositoryMock(
-        getter: expectAsync2((isolate, id) async {
-      expect(rendered, isFalse);
-      expect(id, equals(script_id));
-      return script;
-    }, count: 1));
-    final e = new SourceLinkElement(isolate, location, repository);
-    document.body.append(e);
-    await e.onRendered.first;
-    rendered = true;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.innerHtml.contains(isolate.id), isTrue,
-        reason: 'no message in the component');
-    expect(e.innerHtml.contains(file), isTrue,
-        reason: 'no message in the component');
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/source_link/element_test.html b/runtime/observatory/tests/observatory_ui/source_link/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/source_link/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/stack_trace_tree_config/element_test.dart b/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.dart
deleted file mode 100644
index 3649041..0000000
--- a/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.dart
+++ /dev/null
@@ -1,185 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/models.dart' as M;
-import 'package:observatory/src/elements/stack_trace_tree_config.dart';
-
-main() {
-  StackTraceTreeConfigElement.tag.ensureRegistration();
-
-  group('instantiation', () {
-    test('default', () {
-      final e = new StackTraceTreeConfigElement();
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.showMode, isTrue);
-      expect(e.showDirection, isTrue);
-      expect(e.showFilter, isTrue);
-      expect(e.filter, equals(''));
-      expect(e.mode, equals(ProfileTreeMode.function));
-      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
-    });
-    test('showMode', () {
-      final e = new StackTraceTreeConfigElement(showMode: false);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.showMode, isFalse);
-      expect(e.showDirection, isTrue);
-      expect(e.showFilter, isTrue);
-      expect(e.filter, equals(''));
-      expect(e.mode, equals(ProfileTreeMode.function));
-      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
-    });
-    test('showDirection', () {
-      final e = new StackTraceTreeConfigElement(showDirection: false);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.showMode, isTrue);
-      expect(e.showDirection, isFalse);
-      expect(e.showFilter, isTrue);
-      expect(e.filter, equals(''));
-      expect(e.mode, equals(ProfileTreeMode.function));
-      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
-    });
-    test('showFilter', () {
-      final e = new StackTraceTreeConfigElement(showFilter: false);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.showMode, isTrue);
-      expect(e.showDirection, isTrue);
-      expect(e.showFilter, isFalse);
-      expect(e.filter, equals(''));
-      expect(e.mode, equals(ProfileTreeMode.function));
-      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
-    });
-    test('filter', () {
-      final filter = 'filter-string';
-      final e = new StackTraceTreeConfigElement(filter: filter);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.showMode, isTrue);
-      expect(e.showDirection, isTrue);
-      expect(e.showFilter, isTrue);
-      expect(e.filter, equals(filter));
-      expect(e.mode, equals(ProfileTreeMode.function));
-      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
-    });
-    test('mode', () {
-      final e = new StackTraceTreeConfigElement(mode: ProfileTreeMode.code);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.showMode, isTrue);
-      expect(e.showDirection, isTrue);
-      expect(e.showFilter, isTrue);
-      expect(e.filter, equals(''));
-      expect(e.mode, equals(ProfileTreeMode.code));
-      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
-    });
-    test('default', () {
-      final e = new StackTraceTreeConfigElement(
-          direction: M.ProfileTreeDirection.inclusive);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.showMode, isTrue);
-      expect(e.showDirection, isTrue);
-      expect(e.showFilter, isTrue);
-      expect(e.filter, equals(''));
-      expect(e.mode, equals(ProfileTreeMode.function));
-      expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
-    });
-  });
-  group('elements', () {
-    test('created after attachment', () async {
-      final e = new StackTraceTreeConfigElement();
-      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('react to mode change', () async {
-      final e = new StackTraceTreeConfigElement();
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.mode, equals(ProfileTreeMode.function));
-      e.mode = ProfileTreeMode.code;
-      await e.onRendered.first;
-      expect(e.mode, equals(ProfileTreeMode.code));
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-    test('react to direction change', () async {
-      final e = new StackTraceTreeConfigElement();
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
-      e.direction = M.ProfileTreeDirection.inclusive;
-      await e.onRendered.first;
-      expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-    test('react to filter change', () async {
-      final filter = 'filter-string';
-      final e = new StackTraceTreeConfigElement();
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.filter, equals(''));
-      e.filter = filter;
-      await e.onRendered.first;
-      expect(e.filter, equals(filter));
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-  });
-  group('events', () {
-    test('onModeChange', () async {
-      final e = new StackTraceTreeConfigElement();
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.mode, equals(ProfileTreeMode.function));
-      e.onModeChange.listen(expectAsync1((_) {
-        expect(e.mode, equals(ProfileTreeMode.code));
-      }, count: 1));
-      final select = (e.querySelector('.mode-select') as SelectElement);
-      select.selectedIndex = select.options.indexOf((select.options.toSet()
-            ..removeAll(select.selectedOptions))
-          .toList()
-          .first);
-      select.dispatchEvent(new Event("change"));
-      e.remove();
-      await e.onRendered.first;
-    });
-    test('onDirectionChange', () async {
-      final e = new StackTraceTreeConfigElement();
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
-      e.onDirectionChange.listen(expectAsync1((_) {
-        expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
-      }, count: 1));
-      final select = (e.querySelector('.direction-select') as SelectElement);
-      select.selectedIndex = select.options.indexOf((select.options.toSet()
-            ..removeAll(select.selectedOptions))
-          .toList()
-          .first);
-      select.dispatchEvent(new Event("change"));
-      e.remove();
-      await e.onRendered.first;
-    });
-    test('onFilterChange', () async {
-      final e = new StackTraceTreeConfigElement();
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
-      e.onFilterChange.listen(expectAsync1((_) {
-        expect(e.filter, equals('value'));
-      }, count: 1));
-      var input = (e.querySelector('input') as TextInputElement);
-      input.value = 'value';
-      input.dispatchEvent(new Event("change"));
-      e.remove();
-      await e.onRendered.first;
-    });
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.html b/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/unknown_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/unknown_ref/element_test.dart
deleted file mode 100644
index 66f907d..0000000
--- a/runtime/observatory/tests/observatory_ui/unknown_ref/element_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/unknown_ref.dart';
-import '../mocks.dart';
-
-main() {
-  UnknownObjectRefElement.tag.ensureRegistration();
-
-  const isolate = const IsolateRefMock();
-  const obj = const UnknownObjectRefMock();
-  test('instantiation', () {
-    final e = new UnknownObjectRefElement(isolate, obj);
-    expect(e, isNotNull, reason: 'element correctly created');
-    expect(e.isolate, equals(isolate));
-    expect(e.obj, equals(obj));
-  });
-  test('elements created after attachment', () async {
-    final e = new UnknownObjectRefElement(isolate, obj);
-    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/unknown_ref/element_test.html b/runtime/observatory/tests/observatory_ui/unknown_ref/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/unknown_ref/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/view_footer/element_test.dart b/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart
deleted file mode 100644
index cc0e635..0000000
--- a/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart
+++ /dev/null
@@ -1,25 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/src/elements/view_footer.dart';
-
-main() {
-  ViewFooterElement.tag.ensureRegistration();
-
-  test('instantiation', () {
-    final e = new ViewFooterElement();
-    expect(e, isNotNull, reason: 'element correctly created');
-  });
-  test('elements created', () async {
-    final 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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/view_footer/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/virtual_tree/element_test.dart b/runtime/observatory/tests/observatory_ui/virtual_tree/element_test.dart
deleted file mode 100644
index 2520f74..0000000
--- a/runtime/observatory/tests/observatory_ui/virtual_tree/element_test.dart
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2017, 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:test/test.dart';
-import 'package:observatory/src/elements/containers/virtual_collection.dart';
-import 'package:observatory/src/elements/containers/virtual_tree.dart';
-
-main() {
-  VirtualTreeElement.tag.ensureRegistration();
-
-  final cTag = VirtualCollectionElement.tag.name;
-
-  var container;
-  setUp(() {
-    container = document.body.getElementsByClassName('test_container').first;
-  });
-  group('instantiation', () {
-    test('default', () {
-      final e = new VirtualTreeElement((_) {}, (_1, _2, _3) {}, (_) {});
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.items, isNotNull, reason: 'items not null');
-      expect(e.items, isEmpty, reason: 'no items');
-    });
-    test('items: []', () {
-      final items = ["1", 2, {}];
-      final e =
-          new VirtualTreeElement((_) {}, (_1, _2, _3) {}, (_) {}, items: items);
-      expect(e, isNotNull, reason: 'element correctly created');
-      expect(e.items, isNot(same(items)), reason: 'avoid side effect');
-      expect(e.items, equals(items), reason: 'same items');
-    });
-  });
-  test('elements created after attachment', () async {
-    final create = (toggle) => new DivElement()..classes = ['test_item'];
-    final update = (HtmlElement el, item, depth) {
-      el.text = item.toString();
-    };
-    final children = (item) => [];
-    final items = ["1", 2, {}];
-    final e = new VirtualTreeElement(create, update, children);
-    container.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    expect(e.querySelectorAll(cTag).length, same(1));
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-  test('expand single child', () async {
-    const max_depth = 100000;
-    final create = (toggle) => new DivElement()..classes = ['test_item'];
-    final update = (HtmlElement el, item, depth) {
-      el.text = item.toString();
-    };
-    final children = (item) => item >= max_depth ? [] : [item + 1];
-    final items = [0];
-    final e = new VirtualTreeElement(create, update, children, items: items);
-    container.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    final VirtualCollectionElement collection = e.querySelectorAll(cTag).first;
-    expect(collection.items.length, equals(1), reason: 'begin');
-    e.expand(0, autoExpandSingleChildNodes: true);
-    await e.onRendered.first;
-    expect(collection.items.length, equals(max_depth + 1), reason: 'expanded');
-    e.collapse(0, autoCollapseSingleChildNodes: true);
-    await e.onRendered.first;
-    expect(collection.items.length, equals(1), reason: 'collapsed');
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-
-  test('expand whole tree', () async {
-    const max_depth = 100000;
-    final create = (toggle) => new DivElement()..classes = ['test_item'];
-    final update = (HtmlElement el, item, depth) {
-      el.text = item.toString();
-    };
-    // We want to generated a tree that doesn't collapse to a chain of items
-    // while avoiding to generate an exponential number of items
-    final children = (item) {
-      if (item < 2 * max_depth) {
-        if (item % 200 == 0) {
-          return [item + 1, item + 2];
-        } else if (item % 2 == 0) {
-          return [item + 2];
-        }
-      }
-      return [];
-    };
-    final items = [0];
-    final e = new VirtualTreeElement(create, update, children, items: items);
-    container.append(e);
-    await e.onRendered.first;
-    expect(e.children.length, isNonZero, reason: 'has elements');
-    final VirtualCollectionElement collection = e.querySelectorAll(cTag).first;
-    expect(collection.items.length, equals(1), reason: 'begin');
-    e.expand(0, autoExpandWholeTree: true);
-    await e.onRendered.first;
-    expect(collection.items.length, equals(max_depth + max_depth / 100 + 1),
-        reason: 'expanded');
-    e.collapse(0, autoCollapseWholeTree: true);
-    await e.onRendered.first;
-    expect(collection.items.length, equals(1), reason: 'collapsed');
-    e.remove();
-    await e.onRendered.first;
-    expect(e.children.length, isZero, reason: 'is empty');
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/virtual_tree/element_test.html b/runtime/observatory/tests/observatory_ui/virtual_tree/element_test.html
deleted file mode 100644
index 92c3180..0000000
--- a/runtime/observatory/tests/observatory_ui/virtual_tree/element_test.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="dart.unittest" content="full-stack-traces">
-  <link rel="stylesheet" href="packages/observatory/src/elements/css/shared.css">
-  <style>
-     .unittest-table { font-family:monospace; border:1px; }
-     .unittest-pass { background: #6b3;}
-     .unittest-fail { background: #d55;}
-     .unittest-error { background: #a11;}
-
-     .test_container {
-       height: 100px;
-       width: 100%;
-     }
-
-     .test_item {
-       height: 20px;
-     }
-  </style>
-</head>
-<body>
-  <div class="test_container">
-  </div>
-  <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/element_test.dart b/runtime/observatory/tests/observatory_ui/vm_connect/element_test.dart
deleted file mode 100644
index 1f5d1b6..0000000
--- a/runtime/observatory/tests/observatory_ui/vm_connect/element_test.dart
+++ /dev/null
@@ -1,115 +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.
-
-import 'dart:html';
-import 'package:test/test.dart';
-import 'package:observatory/models.dart' as M;
-import 'package:observatory/src/elements/nav/notify.dart';
-import 'package:observatory/src/elements/vm_connect_target.dart';
-import 'package:observatory/src/elements/vm_connect.dart';
-import '../mocks.dart';
-
-main() {
-  VMConnectElement.tag.ensureRegistration();
-
-  final nTag = NavNotifyElement.tag.name;
-  final tTag = VMConnectTargetElement.tag.name;
-
-  group('instantiation', () {
-    test('default', () {
-      final e = new VMConnectElement(
-          new TargetRepositoryMock(), new NotificationRepositoryMock());
-      expect(e, isNotNull, reason: 'element correctly created');
-    });
-  });
-  test('is correctly listening', () async {
-    final targets = new TargetRepositoryMock();
-    final e = new VMConnectElement(targets, new NotificationRepositoryMock());
-    document.body.append(e);
-    await e.onRendered.first;
-    expect(targets.hasListeners, isTrue, reason: 'is listening');
-    e.remove();
-    await e.onRendered.first;
-    expect(targets.hasListeners, isFalse, reason: 'is no more listening');
-  });
-  group('elements', () {
-    test('created after attachment', () async {
-      final targets = new TargetRepositoryMock(list: const [
-        const TargetMock(name: 't-1'),
-        const TargetMock(name: 't-2'),
-      ]);
-      final e = new VMConnectElement(targets, new NotificationRepositoryMock());
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(targets.listInvoked, isTrue, reason: 'should invoke list()');
-      expect(e.children.length, isNonZero, reason: 'has elements');
-      expect(e.querySelectorAll(nTag).length, equals(1));
-      expect(e.querySelectorAll(tTag).length, equals(2));
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-    test('react to update event', () async {
-      final list = <TargetMock>[const TargetMock(name: 't-1')];
-      final targets = new TargetRepositoryMock(list: list);
-      final e = new VMConnectElement(targets, new NotificationRepositoryMock());
-      document.body.append(e);
-      await e.onRendered.first;
-      expect(e.querySelectorAll(tTag).length, equals(1));
-      list.add(const TargetMock(name: 't-2'));
-      targets.triggerChangeEvent();
-      await e.onRendered.first;
-      expect(e.querySelectorAll(tTag).length, equals(2));
-      e.remove();
-      await e.onRendered.first;
-      expect(e.children.length, isZero, reason: 'is empty');
-    });
-  });
-  group('invokes', () {
-    test('add on click', () async {
-      final address = 'ws://host:1234/ws';
-      final list = <TargetMock>[const TargetMock(name: 't-1')];
-      final targets = new TargetRepositoryMock(
-          list: list,
-          add: expectAsync1((String val) {
-            expect(val, equals(address));
-          }, count: 1, reason: 'should be invoked'));
-      final e = new VMConnectElement(targets, new NotificationRepositoryMock(),
-          address: address);
-      document.body.append(e);
-      await e.onRendered.first;
-      (e.querySelector('button.vm_connect') as ButtonElement).click();
-      e.remove();
-      await e.onRendered.first;
-    });
-    test('connect', () async {
-      final list = <TargetMock>[const TargetMock(name: 't-1')];
-      final targets = new TargetRepositoryMock(
-          list: list,
-          setCurrent: expectAsync1((M.Target t) {
-            expect(t, equals(list[0]));
-          }, count: 1, reason: 'should be invoked'));
-      final e = new VMConnectElement(targets, new NotificationRepositoryMock());
-      document.body.append(e);
-      await e.onRendered.first;
-      (e.querySelector(tTag) as VMConnectTargetElement).connect();
-      e.remove();
-      await e.onRendered.first;
-    });
-    test('delete', () async {
-      final list = <TargetMock>[const TargetMock(name: 't-1')];
-      final targets = new TargetRepositoryMock(
-          list: list,
-          delete: expectAsync1((M.Target t) {
-            expect(t, equals(list[0]));
-          }, count: 1, reason: 'should be invoked'));
-      final e = new VMConnectElement(targets, new NotificationRepositoryMock());
-      document.body.append(e);
-      await e.onRendered.first;
-      (e.querySelector(tTag) as VMConnectTargetElement).delete();
-      e.remove();
-      await e.onRendered.first;
-    });
-  });
-}
diff --git a/runtime/observatory/tests/observatory_ui/vm_connect/element_test.html b/runtime/observatory/tests/observatory_ui/vm_connect/element_test.html
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/vm_connect/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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
deleted file mode 100644
index 79003c8..0000000
--- a/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart
+++ /dev/null
@@ -1,86 +0,0 @@
-// 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:test/test.dart';
-import 'package:observatory/src/elements/vm_connect_target.dart';
-import '../mocks.dart';
-
-main() {
-  VMConnectTargetElement.tag.ensureRegistration();
-
-  TargetMock t;
-  setUp(() {
-    t = new TargetMock(name: "a network address");
-  });
-  group('instantiation', () {
-    test('no other parameters', () {
-      final 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 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 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 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(expectAsync1((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(expectAsync1((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(expectAsync1((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(expectAsync1((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
deleted file mode 100644
index f548be4..0000000
--- a/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!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>
-</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/add_breakpoint_rpc_kernel_test.dart b/runtime/observatory/tests/service/add_breakpoint_rpc_kernel_test.dart
index cd57be6..6d5f293 100644
--- a/runtime/observatory/tests/service/add_breakpoint_rpc_kernel_test.dart
+++ b/runtime/observatory/tests/service/add_breakpoint_rpc_kernel_test.dart
@@ -88,10 +88,10 @@
       int resolvedLine = await bpt.location.getLine();
       int resolvedCol = await bpt.location.getColumn();
       print('$LINE_A:${col} -> ${resolvedLine}:${resolvedCol}');
-      if (col <= 10) {
+      if (col <= 12) {
         expect(resolvedLine, equals(LINE_A));
         expect(resolvedCol, equals(3));
-      } else if (col <= 19) {
+      } else if (col <= 36) {
         expect(resolvedLine, equals(LINE_A));
         expect(resolvedCol, equals(12));
       } else {
diff --git a/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart b/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
index ffb7db6..4c2c388 100644
--- a/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
+++ b/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
@@ -6,11 +6,10 @@
 import 'package:unittest/unittest.dart';
 import 'service_test_common.dart';
 import 'test_helper.dart';
-import 'deferred_library.dart' deferred as deferredLib;
 import 'dart:async';
 
-const int LINE_A = 24;
-const int LINE_B = 26;
+const int LINE_A = 22;
+const int LINE_B = 24;
 
 int value = 0;
 
@@ -23,9 +22,6 @@
   incValue(incValue(1)); // line A.
 
   incValue(incValue(1)); // line B.
-
-  await deferredLib.loadLibrary();
-  deferredLib.deferredTest();
 }
 
 var tests = <IsolateTest>[
@@ -102,82 +98,6 @@
         (await isolate.removeBreakpoint(futureBpt2)).type, equals('Success'));
   },
 
-  // Test breakpoints in deferred libraries (latent breakpoints).
-  (Isolate isolate) async {
-    var rootLib = isolate.rootLibrary;
-    var uri = rootLib.scripts[0].uri;
-    var lastSlashPos = uri.lastIndexOf('/');
-    var deferredUri = uri.substring(0, lastSlashPos) + '/deferred_library.dart';
-
-    // Latent breakpoint.
-    var latentBpt1 = await isolate.addBreakpointByScriptUri(deferredUri, 15);
-    expect(latentBpt1.number, equals(3));
-    expect(latentBpt1.resolved, isFalse);
-    expect(await latentBpt1.location.getLine(), equals(15));
-    expect(await latentBpt1.location.getColumn(), equals(null));
-
-    // Latent breakpoint with specific column.
-    var latentBpt2 = await isolate.addBreakpointByScriptUri(deferredUri, 15, 3);
-    expect(latentBpt2.number, equals(4));
-    expect(latentBpt2.resolved, isFalse);
-    expect(await latentBpt2.location.getLine(), equals(15));
-    expect(await latentBpt2.location.getColumn(), equals(3));
-
-    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
-    Completer completer = new Completer();
-    var subscription;
-    var resolvedCount = 0;
-    subscription = stream.listen((ServiceEvent event) async {
-      if (event.kind == ServiceEvent.kBreakpointResolved) {
-        resolvedCount++;
-      }
-      if (event.kind == ServiceEvent.kPauseBreakpoint) {
-        subscription.cancel();
-        completer.complete();
-      }
-    });
-    await isolate.resume();
-    await completer.future;
-
-    // After resolution the breakpoints have assigned line & column.
-    expect(resolvedCount, equals(2));
-    expect(latentBpt1.resolved, isTrue);
-    expect(await latentBpt1.location.getLine(), equals(15));
-    expect(await latentBpt1.location.getColumn(), equals(12));
-    expect(latentBpt2.resolved, isTrue);
-    expect(await latentBpt2.location.getLine(), equals(15));
-    expect(await latentBpt2.location.getColumn(), equals(3));
-
-    // The first breakpoint hits before value is modified.
-    expect(
-        ((await rootLib.evaluate('deferredLib.value')) as Instance)
-            .valueAsString,
-        equals('0'));
-
-    stream = await isolate.vm.getEventStream(VM.kDebugStream);
-    completer = new Completer();
-    subscription = stream.listen((ServiceEvent event) async {
-      if (event.kind == ServiceEvent.kPauseBreakpoint) {
-        subscription.cancel();
-        completer.complete();
-      }
-    });
-    await isolate.resume();
-    await completer.future;
-
-    // The second breakpoint hits after value has been modified once.
-    expect(
-        ((await rootLib.evaluate('deferredLib.value')) as Instance)
-            .valueAsString,
-        equals('-1'));
-
-    // Remove the breakpoints.
-    expect(
-        (await isolate.removeBreakpoint(latentBpt1)).type, equals('Success'));
-    expect(
-        (await isolate.removeBreakpoint(latentBpt2)).type, equals('Success'));
-  },
-
   // Test resolution of column breakpoints.
   (Isolate isolate) async {
     var script = isolate.rootLibrary.scripts[0];
@@ -188,10 +108,10 @@
       int resolvedLine = await bpt.location.getLine();
       int resolvedCol = await bpt.location.getColumn();
       print('20:${col} -> ${resolvedLine}:${resolvedCol}');
-      if (col <= 10) {
+      if (col <= 12) {
         expect(resolvedLine, equals(LINE_A));
         expect(resolvedCol, equals(3));
-      } else if (col <= 19) {
+      } else if (col <= 36) {
         expect(resolvedLine, equals(LINE_A));
         expect(resolvedCol, equals(12));
       } else {
diff --git a/runtime/observatory/tests/service/breakpoint_async_break_test.dart b/runtime/observatory/tests/service/breakpoint_async_break_test.dart
new file mode 100644
index 0000000..c33d670
--- /dev/null
+++ b/runtime/observatory/tests/service/breakpoint_async_break_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2019, 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/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+const int LINE = 17;
+
+// Issue: https://github.com/dart-lang/sdk/issues/36622
+Future<void> testMain() async {
+  for (int i = 0; i < 2; i++) {
+    if (i > 0) {
+      break; // breakpoint here
+    }
+    await Future.delayed(Duration(seconds: 1));
+  }
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+
+  // Test future breakpoints.
+  (Isolate isolate) async {
+    var rootLib = isolate.rootLibrary;
+    await rootLib.load();
+    var script = rootLib.scripts[0];
+
+    // Future breakpoint.
+    var futureBpt = await isolate.addBreakpoint(script, LINE);
+    expect(futureBpt.number, 1);
+    expect(futureBpt.resolved, isFalse);
+    expect(await futureBpt.location.getLine(), LINE);
+    expect(await futureBpt.location.getColumn(), null);
+
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    Completer completer = new Completer();
+    var subscription;
+    var resolvedCount = 0;
+    subscription = stream.listen((ServiceEvent event) async {
+      if (event.kind == ServiceEvent.kBreakpointResolved) {
+        resolvedCount++;
+      }
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+    await isolate.resume();
+    await hasStoppedAtBreakpoint(isolate);
+
+    // After resolution the breakpoints have assigned line & column.
+    expect(resolvedCount, 1);
+    expect(futureBpt.resolved, isTrue);
+    expect(await futureBpt.location.getLine(), LINE);
+    expect(await futureBpt.location.getColumn(), 7);
+
+    // Remove the breakpoints.
+    expect((await isolate.removeBreakpoint(futureBpt)).type, 'Success');
+  },
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, pause_on_start: true);
diff --git a/runtime/observatory/tests/service/column_breakpoint_test.dart b/runtime/observatory/tests/service/column_breakpoint_test.dart
new file mode 100644
index 0000000..146c54b
--- /dev/null
+++ b/runtime/observatory/tests/service/column_breakpoint_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+code() {
+  var b = [1, 2].map((i) => i == 0).toList();
+  print(b.length);
+}
+
+const int LINE = 9;
+const int COLUMN = 29;
+const String shortFile = "column_breakpoint_test.dart";
+const String breakpointFile =
+    "package:observatory_test_package/column_breakpoint_test.dart";
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$shortFile:${LINE + 0}:23", // on 'i == 0'
+  "$shortFile:${LINE + 0}:23", // iterate twice
+  "$shortFile:${LINE + 1}:3" //on 'b.length'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLineColumn(LINE, COLUMN), // on 'i == 0'
+  setBreakpointAtLineColumn(LINE + 1, 9), // on 'b.length'
+  resumeProgramRecordingStops(stops, false),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/eval_skip_breakpoint.dart b/runtime/observatory/tests/service/eval_skip_breakpoint.dart
index 447852f..c2d7029 100644
--- a/runtime/observatory/tests/service/eval_skip_breakpoint.dart
+++ b/runtime/observatory/tests/service/eval_skip_breakpoint.dart
@@ -3,11 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 // VMOptions=--verbose_debug
 
+import 'dart:developer';
+
 import 'package:observatory/service_io.dart';
-import 'package:unittest/unittest.dart';
+
 import 'service_test_common.dart';
 import 'test_helper.dart';
-import 'dart:developer';
 
 const int LINE_A = 21;
 const int LINE_B = 16;
diff --git a/runtime/observatory/tests/service/evaluate_function_type_parameters_test.dart b/runtime/observatory/tests/service/evaluate_function_type_parameters_test.dart
index 9648807..9e63186 100644
--- a/runtime/observatory/tests/service/evaluate_function_type_parameters_test.dart
+++ b/runtime/observatory/tests/service/evaluate_function_type_parameters_test.dart
@@ -11,11 +11,11 @@
 topLevel<S>() {
   debugger();
 
-  void inner1<T>(T x) {
+  void inner1<TBool, TString, TDouble, TInt>(TInt x) {
     debugger();
   }
 
-  inner1<int>(3);
+  inner1<bool, String, double, int>(3);
 
   void inner2() {
     debugger();
@@ -25,7 +25,7 @@
 }
 
 class A {
-  foo<T>() {
+  foo<T, S>() {
     debugger();
   }
 
@@ -36,7 +36,7 @@
 
 void testMain() {
   topLevel<String>();
-  (new A()).foo<int>();
+  (new A()).foo<int, bool>();
   (new A()).bar<dynamic>(42);
 }
 
@@ -62,7 +62,19 @@
     expect(stack.type, equals('Stack'));
     expect(await stack['frames'][topFrame].location.getLine(), 16);
 
-    Instance result = await isolate.evalFrame(topFrame, "T.toString()");
+    Instance result = await isolate.evalFrame(topFrame, "TBool.toString()");
+    print(result);
+    expect(result.valueAsString, equals("bool"));
+
+    result = await isolate.evalFrame(topFrame, "TString.toString()");
+    print(result);
+    expect(result.valueAsString, equals("String"));
+
+    result = await isolate.evalFrame(topFrame, "TDouble.toString()");
+    print(result);
+    expect(result.valueAsString, equals("double"));
+
+    result = await isolate.evalFrame(topFrame, "TInt.toString()");
     print(result);
     expect(result.valueAsString, equals("int"));
 
@@ -99,6 +111,10 @@
     Instance result = await isolate.evalFrame(topFrame, "T.toString()");
     print(result);
     expect(result.valueAsString, equals("int"));
+
+    result = await isolate.evalFrame(topFrame, "S.toString()");
+    print(result);
+    expect(result.valueAsString, equals("bool"));
   },
   resumeIsolate,
   hasStoppedAtBreakpoint,
diff --git a/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart b/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart
index 9285dbe..537a69d 100644
--- a/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart
@@ -15,40 +15,62 @@
 
 testeeDo() {
   print("Testee doing something.");
-  fib(25);
+  fib(30);
   print("Testee did something.");
 }
 
+Future checkTimeline(Isolate isolate, Map params) async {
+  print(params);
+  var result =
+      await isolate.invokeRpcNoUpgrade('_getCpuProfileTimeline', params);
+  print(result);
+  expect(result['type'], equals('_CpuProfileTimeline'));
+
+  var isString = new isInstanceOf<String>();
+  var isInt = new isInstanceOf<int>();
+  Map frames = result['stackFrames'];
+  expect(frames.length, greaterThan(10), reason: "Should have many samples");
+  for (Map frame in frames.values) {
+    expect(frame['category'], isString);
+    expect(frame['name'], isString);
+    if (frame['resolvedUrl'] != null) {
+      expect(frame['resolvedUrl'], isString);
+    }
+    if (frame['parent'] != null) {
+      expect(frames.containsKey(frame['parent']), isTrue);
+    }
+  }
+
+  List events = result['traceEvents'];
+  expect(events.length, greaterThan(10), reason: "Should have many samples");
+  for (Map event in events) {
+    expect(event['ph'], equals('P'));
+    expect(event['pid'], isInt);
+    expect(event['tid'], isInt);
+    expect(event['ts'], isInt);
+    expect(event['cat'], equals("Dart"));
+    expect(frames.containsKey(event['sf']), isTrue);
+  }
+}
+
 var tests = <IsolateTest>[
-  (Isolate isolate) async {
-    var params = {'tags': 'VMUser'};
-    var result =
-        await isolate.invokeRpcNoUpgrade('_getCpuProfileTimeline', params);
-    print(result);
-    expect(result['type'], equals('_CpuProfileTimeline'));
-
-    var isString = new isInstanceOf<String>();
-    var isInt = new isInstanceOf<int>();
-
-    Map frames = result['stackFrames'];
-    for (Map frame in frames.values) {
-      expect(frame['category'], isString);
-      expect(frame['name'], isString);
-      if (frame['parent'] != null) {
-        expect(frames.containsKey(frame['parent']), isTrue);
-      }
-    }
-
-    List events = result['traceEvents'];
-    for (Map event in events) {
-      expect(event['ph'], equals('P'));
-      expect(event['pid'], isInt);
-      expect(event['tid'], isInt);
-      expect(event['ts'], isInt);
-      expect(event['cat'], equals("Dart"));
-      expect(frames.containsKey(event['sf']), isTrue);
-    }
-  },
+  (Isolate i) => checkTimeline(i, {'tags': 'VMUser'}),
+  (Isolate i) => checkTimeline(i, {'tags': 'VMUser', 'code': true}),
+  (Isolate i) => checkTimeline(i, {'tags': 'VMUser', 'code': false}),
+  (Isolate i) => checkTimeline(i, {'tags': 'VMOnly'}),
+  (Isolate i) => checkTimeline(i, {'tags': 'VMOnly', 'code': true}),
+  (Isolate i) => checkTimeline(i, {'tags': 'VMOnly', 'code': false}),
+  (Isolate i) => checkTimeline(i, {'tags': 'None'}),
+  (Isolate i) => checkTimeline(i, {'tags': 'None', 'code': true}),
+  (Isolate i) => checkTimeline(i, {'tags': 'None', 'code': false}),
 ];
 
-main(args) async => runIsolateTests(args, tests, testeeBefore: testeeDo);
+var vmArgs = [
+  '--profiler=true',
+  '--profile-vm=false', // So this also works with DBC and KBC.
+  '--timeline_recorder=ring',
+  '--timeline_streams=Profiler'
+];
+
+main(args) async =>
+    runIsolateTests(args, tests, testeeBefore: testeeDo, extraArgs: vmArgs);
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index ca2028a..f5eb252 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     var result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], equals('Version'));
     expect(result['major'], equals(3));
-    expect(result['minor'], equals(14));
+    expect(result['minor'], equals(17));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/observatory/tests/service/http_auth_get_isolate_rpc_test.dart b/runtime/observatory/tests/service/http_auth_get_isolate_rpc_test.dart
new file mode 100644
index 0000000..5b0b5f6
--- /dev/null
+++ b/runtime/observatory/tests/service/http_auth_get_isolate_rpc_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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 'http_get_isolate_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true,
+      useAuthToken: true);
+}
diff --git a/runtime/observatory/tests/service/http_auth_get_vm_rpc_test.dart b/runtime/observatory/tests/service/http_auth_get_vm_rpc_test.dart
new file mode 100644
index 0000000..8eff61f
--- /dev/null
+++ b/runtime/observatory/tests/service/http_auth_get_vm_rpc_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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 'http_get_vm_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true,
+      useAuthToken: true);
+}
diff --git a/runtime/observatory/tests/service/http_get_isolate_rpc_common.dart b/runtime/observatory/tests/service/http_get_isolate_rpc_common.dart
new file mode 100644
index 0000000..30a0112
--- /dev/null
+++ b/runtime/observatory/tests/service/http_get_isolate_rpc_common.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2019, 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:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'package:observatory/service_io.dart' as S;
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+Future<String> getIsolateId(io.HttpClient httpClient, Uri serverUri) async {
+  // Build the request.
+  final pathSegments = <String>[]..addAll(serverUri.pathSegments);
+  String method = 'getVM';
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = serverUri.replace(pathSegments: pathSegments);
+  var request = await httpClient.getUrl(requestUri);
+  Map response = await (await request.close())
+      .transform(utf8.decoder)
+      .transform(json.decoder)
+      .first;
+  Map result = response['result'];
+  return result['isolates'][0]['id'];
+}
+
+Future<Null> testeeBefore() async {
+  print('testee before');
+  print(await Service.getInfo());
+  // Start the web server.
+  ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+  expect(info.serverUri, isNotNull);
+  var httpClient = new io.HttpClient();
+
+  // Build the request.
+  final params = <String, String>{
+    'isolateId': await getIsolateId(httpClient, info.serverUri),
+  };
+
+  String method = 'getIsolate';
+  final pathSegments = <String>[]..addAll(info.serverUri.pathSegments);
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = info.serverUri
+      .replace(pathSegments: pathSegments, queryParameters: params);
+
+  try {
+    var request = await httpClient.getUrl(requestUri);
+    Map response = await (await request.close())
+        .transform(utf8.decoder)
+        .transform(json.decoder)
+        .first;
+    Map result = response['result'];
+    expect(result['type'], equals('Isolate'));
+    expect(result['id'], startsWith('isolates/'));
+    expect(result['number'], new isInstanceOf<String>());
+    expect(result['_originNumber'], equals(result['number']));
+    expect(result['startTime'], isPositive);
+    expect(result['livePorts'], isPositive);
+    expect(result['pauseOnExit'], isFalse);
+    expect(result['pauseEvent']['type'], equals('Event'));
+    expect(result['error'], isNull);
+    expect(result['_numZoneHandles'], isPositive);
+    expect(result['_numScopedHandles'], isPositive);
+    expect(result['rootLib']['type'], equals('@Library'));
+    expect(result['libraries'].length, isPositive);
+    expect(result['libraries'][0]['type'], equals('@Library'));
+    expect(result['breakpoints'].length, isZero);
+    expect(result['_heaps']['new']['type'], equals('HeapSpace'));
+    expect(result['_heaps']['old']['type'], equals('HeapSpace'));
+  } catch (e) {
+    fail('invalid request: $e');
+  }
+}
+
+var tests = <IsolateTest>[
+  (S.Isolate isolate) async {
+    await isolate.reload();
+    // Just getting here means that the testee enabled the service protocol
+    // web server.
+    expect(true, true);
+  }
+];
diff --git a/runtime/observatory/tests/service/http_get_isolate_rpc_test.dart b/runtime/observatory/tests/service/http_get_isolate_rpc_test.dart
new file mode 100644
index 0000000..261fa26
--- /dev/null
+++ b/runtime/observatory/tests/service/http_get_isolate_rpc_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, 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 'http_get_isolate_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true);
+}
diff --git a/runtime/observatory/tests/service/http_get_vm_rpc_common.dart b/runtime/observatory/tests/service/http_get_vm_rpc_common.dart
new file mode 100644
index 0000000..b193dc9
--- /dev/null
+++ b/runtime/observatory/tests/service/http_get_vm_rpc_common.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, 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:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'package:observatory/service_io.dart' as S;
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+Future<Null> testeeBefore() async {
+  print('testee before');
+  print(await Service.getInfo());
+  // Start the web server.
+  ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+  expect(info.serverUri, isNotNull);
+  var httpClient = new io.HttpClient();
+
+  // Build the request.
+  final pathSegments = <String>[]..addAll(info.serverUri.pathSegments);
+  String method = 'getVM';
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = info.serverUri.replace(pathSegments: pathSegments);
+
+  try {
+    var request = await httpClient.getUrl(requestUri);
+    Map response = await (await request.close())
+        .transform(utf8.decoder)
+        .transform(json.decoder)
+        .first;
+    Map result = response['result'];
+    expect(result['type'], equals('VM'));
+    expect(result['name'], equals('vm'));
+    expect(result['architectureBits'], isPositive);
+    expect(result['targetCPU'], new isInstanceOf<String>());
+    expect(result['hostCPU'], new isInstanceOf<String>());
+    expect(result['version'], new isInstanceOf<String>());
+    expect(result['pid'], new isInstanceOf<int>());
+    expect(result['startTime'], isPositive);
+    expect(result['isolates'].length, isPositive);
+    expect(result['isolates'][0]['type'], equals('@Isolate'));
+  } catch (e) {
+    fail('invalid request: $e');
+  }
+}
+
+var tests = <IsolateTest>[
+  (S.Isolate isolate) async {
+    await isolate.reload();
+    // Just getting here means that the testee enabled the service protocol
+    // web server.
+    expect(true, true);
+  }
+];
diff --git a/runtime/observatory/tests/service/http_get_vm_rpc_test.dart b/runtime/observatory/tests/service/http_get_vm_rpc_test.dart
new file mode 100644
index 0000000..5484c5e
--- /dev/null
+++ b/runtime/observatory/tests/service/http_get_vm_rpc_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, 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 'http_get_vm_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true);
+}
diff --git a/runtime/observatory/tests/service/regress_34841_lib.dart b/runtime/observatory/tests/service/regress_34841_lib.dart
index 304f6f5..60eb3e4 100644
--- a/runtime/observatory/tests/service/regress_34841_lib.dart
+++ b/runtime/observatory/tests/service/regress_34841_lib.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 class Foo {
+  String baz() => StackTrace.current.toString();
   final String foo = () {
     return StackTrace.current.toString();
   }();
diff --git a/runtime/observatory/tests/service/regress_34841_test.dart b/runtime/observatory/tests/service/regress_34841_test.dart
index 69acbad..c53a9e9 100644
--- a/runtime/observatory/tests/service/regress_34841_test.dart
+++ b/runtime/observatory/tests/service/regress_34841_test.dart
@@ -19,6 +19,7 @@
 void testFunction() {
   Bar bar = new Bar();
   print(bar.foo);
+  print(bar.baz());
   debugger();
 }
 
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 7012181..cea771c 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -77,7 +77,6 @@
 [ $arch == simdbc64 && $compiler == dartk ]
 eval_test: RuntimeError, Timeout # Issue #34736
 evaluate_in_frame_rpc_test: RuntimeError, Timeout # Issue #34736
-get_cpu_profile_timeline_rpc_test: Pass, RuntimeError # http://dartbug.com/31794
 
 [ $arch == simdbc64 && $compiler == dartk && $mode == debug ]
 eval_test: Pass, Slow
diff --git a/runtime/observatory/tests/service/service_test_common.dart b/runtime/observatory/tests/service/service_test_common.dart
index e9add47..3be2f4d 100644
--- a/runtime/observatory/tests/service/service_test_common.dart
+++ b/runtime/observatory/tests/service/service_test_common.dart
@@ -249,6 +249,19 @@
   };
 }
 
+IsolateTest setBreakpointAtLineColumn(int line, int column) {
+  return (Isolate isolate) async {
+    print("Setting breakpoint for line $line column $column");
+    Library lib = await isolate.rootLibrary.load();
+    Script script = lib.scripts.single;
+
+    Breakpoint bpt = await isolate.addBreakpoint(script, line, column);
+    print("Breakpoint is $bpt");
+    expect(bpt, isNotNull);
+    expect(bpt is Breakpoint, isTrue);
+  };
+}
+
 IsolateTest setBreakpointAtUriAndLine(String uri, int line) {
   return (Isolate isolate) async {
     print("Setting breakpoint for line $line in $uri");
diff --git a/runtime/observatory/tests/service/unused_changes_in_last_reload/v2/main.dart b/runtime/observatory/tests/service/unused_changes_in_last_reload/v2/main.dart
index 48682e2..910904f 100644
--- a/runtime/observatory/tests/service/unused_changes_in_last_reload/v2/main.dart
+++ b/runtime/observatory/tests/service/unused_changes_in_last_reload/v2/main.dart
@@ -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.
 
-import 'dart:isolate';
-
 unchangedFunction() => "unchanged";
 var unchangedField = "unchanged".toString();
 
diff --git a/runtime/observatory/tests/service/write_cpu_profile_timeline_rpc_test.dart b/runtime/observatory/tests/service/write_cpu_profile_timeline_rpc_test.dart
new file mode 100644
index 0000000..ea0a6ef
--- /dev/null
+++ b/runtime/observatory/tests/service/write_cpu_profile_timeline_rpc_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2019, 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/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+import 'test_helper.dart';
+
+fib(n) {
+  if (n < 0) return 0;
+  if (n == 0) return 1;
+  return fib(n - 1) + fib(n - 2);
+}
+
+testeeDo() {
+  print("Testee doing something.");
+  fib(30);
+  print("Testee did something.");
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    var params = {'tags': 'None'};
+    var result =
+        await isolate.invokeRpcNoUpgrade('_writeCpuProfileTimeline', params);
+    print(result);
+    expect(result['type'], equals('Success'));
+
+    result = await isolate.vm.invokeRpcNoUpgrade('_getVMTimeline', {});
+    expect(result['type'], equals('_Timeline'));
+    expect(result['traceEvents'], new isInstanceOf<List>());
+
+    var events = result['traceEvents'];
+    print(events);
+    var profilerSampleEvents = result['traceEvents'].where((event) {
+      return event['name'] == "Dart CPU sample";
+    }).toList();
+
+    var isString = new isInstanceOf<String>();
+    var isInt = new isInstanceOf<int>();
+
+    expect(profilerSampleEvents.length, greaterThan(10),
+        reason: "Should have many samples");
+    for (Map event in profilerSampleEvents) {
+      print(event);
+
+      // Sadly this is an "Instant" event because there is no way to add a
+      // proper "Sample" event in Fuchsia's tracing.
+      expect(event['ph'], equals('i'));
+
+      expect(event['pid'], isInt);
+      expect(event['tid'], isInt);
+      expect(event['ts'], isInt);
+      expect(event['cat'], equals("Profiler"));
+      expect(event['args']['backtrace'], isString);
+    }
+  },
+];
+
+var vmArgs = [
+  '--profiler=true',
+  '--profile-vm=false', // So this also works with DBC and KBC.
+  '--timeline_recorder=ring',
+  '--timeline_streams=Profiler'
+];
+
+main(args) async =>
+    runIsolateTests(args, tests, testeeBefore: testeeDo, extraArgs: vmArgs);
diff --git a/runtime/observatory/web/main.dart b/runtime/observatory/web/main.dart
index 07fcb1a..b09362d 100644
--- a/runtime/observatory/web/main.dart
+++ b/runtime/observatory/web/main.dart
@@ -13,9 +13,8 @@
     Logger.root.onRecord.listen((LogRecord rec) {
       print('${rec.level.name}: ${rec.time}: ${rec.message}');
     });
-    await initElements();
     Logger.root.info('Starting Observatory');
     document.body.children
-        .insert(0, document.createElement('observatory-application'));
+        .insert(0, new ObservatoryApplicationElement.created().element);
   });
 }
diff --git a/runtime/observatory/web/timeline.js b/runtime/observatory/web/timeline.js
index 9e92ad4..16d8592 100644
--- a/runtime/observatory/web/timeline.js
+++ b/runtime/observatory/web/timeline.js
@@ -622,6 +622,7 @@
                      parser.hostname +
                      ':' +
                      parser.port +
+                     parser.pathname.replace(/\/ws$/, "") +
                      '/_getCpuProfileTimeline?tags=None&isolateId=' +
                      isolateId +
                      '&timeOriginMicros=' + timeOrigin +
@@ -646,6 +647,7 @@
                    parser.hostname +
                    ':' +
                    parser.port +
+                   parser.pathname.replace(/\/ws$/, "") +
                    '/_getVMTimeline';
   fetchUri(requestUri, function(event) {
     // Grab the response.
diff --git a/runtime/platform/BUILD.gn b/runtime/platform/BUILD.gn
index 6f2cdf9..9a2905c 100644
--- a/runtime/platform/BUILD.gn
+++ b/runtime/platform/BUILD.gn
@@ -6,7 +6,7 @@
 import("platform_sources.gni")
 
 library_for_all_configs("libdart_platform") {
-  target_type = "static_library"
+  target_type = "source_set"
   public_configs = [ "../vm:libdart_vm_config" ]
   sources = platform_sources
   include_dirs = [ ".." ]
diff --git a/runtime/platform/assert.cc b/runtime/platform/assert.cc
index deac89e..b1dbd65 100644
--- a/runtime/platform/assert.cc
+++ b/runtime/platform/assert.cc
@@ -6,7 +6,7 @@
 
 #include "include/dart_api.h"
 #include "platform/globals.h"
-#include "vm/os.h"
+#include "platform/syslog.h"
 
 namespace dart {
 
@@ -29,7 +29,7 @@
             sizeof(buffer) - file_and_line_length, format, arguments);
 
   // Print the buffer on stderr and/or syslog.
-  OS::PrintErr("%s\n", buffer);
+  Syslog::PrintErr("%s\n", buffer);
 }
 
 void Assert::Fail(const char* format, ...) {
@@ -40,7 +40,8 @@
 
   // Abort right away.
   Dart_DumpNativeStackTrace(NULL);
-  OS::Abort();
+  Dart_PrepareToAbort();
+  abort();
 }
 
 void Expect::Fail(const char* format, ...) {
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 7815569..a3632e8 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -318,6 +318,20 @@
 #endif
 #endif
 
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
+#define TARGET_ARCH_IS_32_BIT 1
+#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
+#define TARGET_ARCH_IS_64_BIT 1
+#elif defined(TARGET_ARCH_DBC)
+#if defined(ARCH_IS_32_BIT)
+#define TARGET_ARCH_IS_32_BIT 1
+#else
+#define TARGET_ARCH_IS_64_BIT 1
+#endif
+#else
+#error Automatic target architecture detection failed.
+#endif
+
 // Verify that host and target architectures match, we cannot
 // have a 64 bit Dart VM generating 32 bit code or vice-versa.
 #if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
diff --git a/runtime/platform/platform_sources.gni b/runtime/platform/platform_sources.gni
index cf85469..9d53c4b 100644
--- a/runtime/platform/platform_sources.gni
+++ b/runtime/platform/platform_sources.gni
@@ -27,8 +27,16 @@
   "memory_sanitizer.h",
   "safe_stack.h",
   "signal_blocker.h",
+  "syslog.h",
+  "syslog_android.cc",
+  "syslog_fuchsia.cc",
+  "syslog_linux.cc",
+  "syslog_macos.cc",
+  "syslog_win.cc",
   "text_buffer.cc",
   "text_buffer.h",
+  "unicode.cc",
+  "unicode.h",
   "utils.cc",
   "utils.h",
   "utils_android.cc",
diff --git a/runtime/platform/splay-tree-inl.h b/runtime/platform/splay-tree-inl.h
new file mode 100644
index 0000000..1b73135
--- /dev/null
+++ b/runtime/platform/splay-tree-inl.h
@@ -0,0 +1,271 @@
+// Copyright (c) 2010, 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.
+//
+// The original file can be found at:
+// https://github.com/v8/v8/blob/master/src/splay-tree-inl.h
+
+#ifndef RUNTIME_PLATFORM_SPLAY_TREE_INL_H_
+#define RUNTIME_PLATFORM_SPLAY_TREE_INL_H_
+
+#include <vector>
+
+#include "platform/splay-tree.h"
+
+namespace dart {
+
+template <typename Config, class B, class Allocator>
+SplayTree<Config, B, Allocator>::~SplayTree() {
+  NodeDeleter deleter;
+  ForEachNode(&deleter);
+}
+
+template <typename Config, class B, class Allocator>
+bool SplayTree<Config, B, Allocator>::Insert(const Key& key, Locator* locator) {
+  if (is_empty()) {
+    // If the tree is empty, insert the new node.
+    root_ = new (allocator_) Node(key, Config::NoValue());
+  } else {
+    // Splay on the key to move the last node on the search path
+    // for the key to the root of the tree.
+    Splay(key);
+    // Ignore repeated insertions with the same key.
+    int cmp = Config::Compare(key, root_->key_);
+    if (cmp == 0) {
+      locator->bind(root_);
+      return false;
+    }
+    // Insert the new node.
+    Node* node = new (allocator_) Node(key, Config::NoValue());
+    InsertInternal(cmp, node);
+  }
+  locator->bind(root_);
+  return true;
+}
+
+template <typename Config, class B, class Allocator>
+void SplayTree<Config, B, Allocator>::InsertInternal(int cmp, Node* node) {
+  if (cmp > 0) {
+    node->left_ = root_;
+    node->right_ = root_->right_;
+    root_->right_ = nullptr;
+  } else {
+    node->right_ = root_;
+    node->left_ = root_->left_;
+    root_->left_ = nullptr;
+  }
+  root_ = node;
+}
+
+template <typename Config, class B, class Allocator>
+bool SplayTree<Config, B, Allocator>::FindInternal(const Key& key) {
+  if (is_empty()) return false;
+  Splay(key);
+  return Config::Compare(key, root_->key_) == 0;
+}
+
+template <typename Config, class B, class Allocator>
+bool SplayTree<Config, B, Allocator>::Contains(const Key& key) {
+  return FindInternal(key);
+}
+
+template <typename Config, class B, class Allocator>
+bool SplayTree<Config, B, Allocator>::Find(const Key& key, Locator* locator) {
+  if (FindInternal(key)) {
+    locator->bind(root_);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+template <typename Config, class B, class Allocator>
+bool SplayTree<Config, B, Allocator>::FindGreatestLessThan(const Key& key,
+                                                           Locator* locator) {
+  if (is_empty()) return false;
+  // Splay on the key to move the node with the given key or the last
+  // node on the search path to the top of the tree.
+  Splay(key);
+  // Now the result is either the root node or the greatest node in
+  // the left subtree.
+  int cmp = Config::Compare(root_->key_, key);
+  if (cmp <= 0) {
+    locator->bind(root_);
+    return true;
+  } else {
+    Node* temp = root_;
+    root_ = root_->left_;
+    bool result = FindGreatest(locator);
+    root_ = temp;
+    return result;
+  }
+}
+
+template <typename Config, class B, class Allocator>
+bool SplayTree<Config, B, Allocator>::FindLeastGreaterThan(const Key& key,
+                                                           Locator* locator) {
+  if (is_empty()) return false;
+  // Splay on the key to move the node with the given key or the last
+  // node on the search path to the top of the tree.
+  Splay(key);
+  // Now the result is either the root node or the least node in
+  // the right subtree.
+  int cmp = Config::Compare(root_->key_, key);
+  if (cmp >= 0) {
+    locator->bind(root_);
+    return true;
+  } else {
+    Node* temp = root_;
+    root_ = root_->right_;
+    bool result = FindLeast(locator);
+    root_ = temp;
+    return result;
+  }
+}
+
+template <typename Config, class B, class Allocator>
+bool SplayTree<Config, B, Allocator>::FindGreatest(Locator* locator) {
+  if (is_empty()) return false;
+  Node* current = root_;
+  while (current->right_ != nullptr)
+    current = current->right_;
+  locator->bind(current);
+  return true;
+}
+
+template <typename Config, class B, class Allocator>
+bool SplayTree<Config, B, Allocator>::FindLeast(Locator* locator) {
+  if (is_empty()) return false;
+  Node* current = root_;
+  while (current->left_ != nullptr)
+    current = current->left_;
+  locator->bind(current);
+  return true;
+}
+
+template <typename Config, class B, class Allocator>
+bool SplayTree<Config, B, Allocator>::Move(const Key& old_key,
+                                           const Key& new_key) {
+  if (!FindInternal(old_key)) return false;
+  Node* node_to_move = root_;
+  RemoveRootNode(old_key);
+  Splay(new_key);
+  int cmp = Config::Compare(new_key, root_->key_);
+  if (cmp == 0) {
+    // A node with the target key already exists.
+    delete node_to_move;
+    return false;
+  }
+  node_to_move->key_ = new_key;
+  InsertInternal(cmp, node_to_move);
+  return true;
+}
+
+template <typename Config, class B, class Allocator>
+bool SplayTree<Config, B, Allocator>::Remove(const Key& key) {
+  if (!FindInternal(key)) return false;
+  Node* node_to_remove = root_;
+  RemoveRootNode(key);
+  delete node_to_remove;
+  return true;
+}
+
+template <typename Config, class B, class Allocator>
+void SplayTree<Config, B, Allocator>::RemoveRootNode(const Key& key) {
+  if (root_->left_ == nullptr) {
+    // No left child, so the new tree is just the right child.
+    root_ = root_->right_;
+  } else {
+    // Left child exists.
+    Node* right = root_->right_;
+    // Make the original left child the new root.
+    root_ = root_->left_;
+    // Splay to make sure that the new root has an empty right child.
+    Splay(key);
+    // Insert the original right child as the right child of the new
+    // root.
+    root_->right_ = right;
+  }
+}
+
+template <typename Config, class B, class Allocator>
+void SplayTree<Config, B, Allocator>::Splay(const Key& key) {
+  if (is_empty()) return;
+  Node dummy_node(Config::kNoKey, Config::NoValue());
+  // Create a dummy node.  The use of the dummy node is a bit
+  // counter-intuitive: The right child of the dummy node will hold
+  // the L tree of the algorithm.  The left child of the dummy node
+  // will hold the R tree of the algorithm.  Using a dummy node, left
+  // and right will always be nodes and we avoid special cases.
+  Node* dummy = &dummy_node;
+  Node* left = dummy;
+  Node* right = dummy;
+  Node* current = root_;
+  while (true) {
+    int cmp = Config::Compare(key, current->key_);
+    if (cmp < 0) {
+      if (current->left_ == nullptr) break;
+      if (Config::Compare(key, current->left_->key_) < 0) {
+        // Rotate right.
+        Node* temp = current->left_;
+        current->left_ = temp->right_;
+        temp->right_ = current;
+        current = temp;
+        if (current->left_ == nullptr) break;
+      }
+      // Link right.
+      right->left_ = current;
+      right = current;
+      current = current->left_;
+    } else if (cmp > 0) {
+      if (current->right_ == nullptr) break;
+      if (Config::Compare(key, current->right_->key_) > 0) {
+        // Rotate left.
+        Node* temp = current->right_;
+        current->right_ = temp->left_;
+        temp->left_ = current;
+        current = temp;
+        if (current->right_ == nullptr) break;
+      }
+      // Link left.
+      left->right_ = current;
+      left = current;
+      current = current->right_;
+    } else {
+      break;
+    }
+  }
+  // Assemble.
+  left->right_ = current->left_;
+  right->left_ = current->right_;
+  current->left_ = dummy->right_;
+  current->right_ = dummy->left_;
+  root_ = current;
+}
+
+template <typename Config, class B, class Allocator>
+template <class Callback>
+void SplayTree<Config, B, Allocator>::ForEach(Callback* callback) {
+  NodeToPairAdaptor<Callback> callback_adaptor(callback);
+  ForEachNode(&callback_adaptor);
+}
+
+template <typename Config, class B, class Allocator>
+template <class Callback>
+void SplayTree<Config, B, Allocator>::ForEachNode(Callback* callback) {
+  if (root_ == nullptr) return;
+  // Pre-allocate some space for tiny trees.
+  std::vector<Node*> nodes_to_visit;
+  nodes_to_visit.push_back(root_);
+  size_t pos = 0;
+  while (pos < nodes_to_visit.size()) {
+    Node* node = nodes_to_visit[pos++];
+    if (node->left() != nullptr) nodes_to_visit.push_back(node->left());
+    if (node->right() != nullptr) nodes_to_visit.push_back(node->right());
+    callback->Call(node);
+  }
+}
+
+}  // namespace dart
+
+#endif  // RUNTIME_PLATFORM_SPLAY_TREE_INL_H_
diff --git a/runtime/platform/splay-tree.h b/runtime/platform/splay-tree.h
new file mode 100644
index 0000000..d318cda
--- /dev/null
+++ b/runtime/platform/splay-tree.h
@@ -0,0 +1,170 @@
+// Copyright (c) 2010, 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.
+//
+// The original file can be found at:
+// https://github.com/v8/v8/blob/master/src/splay-tree.h
+
+#ifndef RUNTIME_PLATFORM_SPLAY_TREE_H_
+#define RUNTIME_PLATFORM_SPLAY_TREE_H_
+
+#include "platform/allocation.h"
+
+namespace dart {
+
+// A splay tree.  The config type parameter encapsulates the different
+// configurations of a concrete splay tree:
+//
+//   typedef Key: the key type
+//   typedef Value: the value type
+//   static const Key kNoKey: the dummy key used when no key is set
+//   static Value kNoValue(): the dummy value used to initialize nodes
+//   static int (Compare)(Key& a, Key& b) -> {-1, 0, 1}: comparison function
+//
+// The tree is also parameterized by an allocation policy
+// (Allocator). The policy is used for allocating lists in the C free
+// store or the zone; see zone.h.
+
+template <typename Config, class B, class Allocator>
+class SplayTree : public B {
+ public:
+  typedef typename Config::Key Key;
+  typedef typename Config::Value Value;
+
+  class Locator;
+
+  explicit SplayTree(Allocator* allocator)
+      : root_(nullptr), allocator_(allocator) {}
+  ~SplayTree();
+
+  Allocator* allocator() { return allocator_; }
+
+  // Checks if there is a mapping for the key.
+  bool Contains(const Key& key);
+
+  // Inserts the given key in this tree with the given value.  Returns
+  // true if a node was inserted, otherwise false.  If found the locator
+  // is enabled and provides access to the mapping for the key.
+  bool Insert(const Key& key, Locator* locator);
+
+  // Looks up the key in this tree and returns true if it was found,
+  // otherwise false.  If the node is found the locator is enabled and
+  // provides access to the mapping for the key.
+  bool Find(const Key& key, Locator* locator);
+
+  // Finds the mapping with the greatest key less than or equal to the
+  // given key.
+  bool FindGreatestLessThan(const Key& key, Locator* locator);
+
+  // Find the mapping with the greatest key in this tree.
+  bool FindGreatest(Locator* locator);
+
+  // Finds the mapping with the least key greater than or equal to the
+  // given key.
+  bool FindLeastGreaterThan(const Key& key, Locator* locator);
+
+  // Find the mapping with the least key in this tree.
+  bool FindLeast(Locator* locator);
+
+  // Move the node from one key to another.
+  bool Move(const Key& old_key, const Key& new_key);
+
+  // Remove the node with the given key from the tree.
+  bool Remove(const Key& key);
+
+  // Remove all keys from the tree.
+  void Clear() { ResetRoot(); }
+
+  bool is_empty() { return root_ == nullptr; }
+
+  // Perform the splay operation for the given key. Moves the node with
+  // the given key to the top of the tree.  If no node has the given
+  // key, the last node on the search path is moved to the top of the
+  // tree.
+  void Splay(const Key& key);
+
+  class Node : public B {
+   public:
+    Node(const Key& key, const Value& value)
+        : key_(key), value_(value), left_(nullptr), right_(nullptr) {}
+
+    Key key() { return key_; }
+    Value value() { return value_; }
+    Node* left() { return left_; }
+    Node* right() { return right_; }
+
+   private:
+    friend class SplayTree;
+    friend class Locator;
+    Key key_;
+    Value value_;
+    Node* left_;
+    Node* right_;
+  };
+
+  // A locator provides access to a node in the tree without actually
+  // exposing the node.
+  class Locator : public B {
+   public:
+    explicit Locator(Node* node) : node_(node) {}
+    Locator() : node_(nullptr) {}
+    const Key& key() { return node_->key_; }
+    Value& value() { return node_->value_; }
+    void set_value(const Value& value) { node_->value_ = value; }
+    inline void bind(Node* node) { node_ = node; }
+
+   private:
+    Node* node_;
+  };
+
+  template <class Callback>
+  void ForEach(Callback* callback);
+
+ protected:
+  // Resets tree root. Existing nodes become unreachable.
+  void ResetRoot() { root_ = nullptr; }
+
+ private:
+  // Search for a node with a given key. If found, root_ points
+  // to the node.
+  bool FindInternal(const Key& key);
+
+  // Inserts a node assuming that root_ is already set up.
+  void InsertInternal(int cmp, Node* node);
+
+  // Removes root_ node.
+  void RemoveRootNode(const Key& key);
+
+  template <class Callback>
+  class NodeToPairAdaptor : public B {
+   public:
+    explicit NodeToPairAdaptor(Callback* callback) : callback_(callback) {}
+    void Call(Node* node) { callback_->Call(node->key(), node->value()); }
+
+   private:
+    Callback* callback_;
+
+    DISALLOW_COPY_AND_ASSIGN(NodeToPairAdaptor);
+  };
+
+  class NodeDeleter : public B {
+   public:
+    NodeDeleter() = default;
+    void Call(Node* node) { delete node; }
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(NodeDeleter);
+  };
+
+  template <class Callback>
+  void ForEachNode(Callback* callback);
+
+  Node* root_;
+  Allocator* allocator_;
+
+  DISALLOW_COPY_AND_ASSIGN(SplayTree);
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_PLATFORM_SPLAY_TREE_H_
diff --git a/runtime/platform/syslog.h b/runtime/platform/syslog.h
new file mode 100644
index 0000000..d48c10b
--- /dev/null
+++ b/runtime/platform/syslog.h
@@ -0,0 +1,42 @@
+// 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.
+
+#ifndef RUNTIME_PLATFORM_SYSLOG_H_
+#define RUNTIME_PLATFORM_SYSLOG_H_
+
+#include <stdarg.h>
+
+#include "platform/globals.h"
+
+namespace dart {
+
+class Syslog {
+ public:
+  // Print formatted output for debugging.
+  static void Print(const char* format, ...) PRINTF_ATTRIBUTE(1, 2) {
+    va_list args;
+    va_start(args, format);
+    VPrint(format, args);
+    va_end(args);
+  }
+
+  static void VPrint(const char* format, va_list args);
+
+  static void PrintErr(const char* format, ...) PRINTF_ATTRIBUTE(1, 2) {
+    va_list args;
+    va_start(args, format);
+    VPrintErr(format, args);
+    va_end(args);
+  }
+
+  static void VPrintErr(const char* format, va_list args);
+
+ private:
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Syslog);
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_PLATFORM_SYSLOG_H_
diff --git a/runtime/platform/syslog_android.cc b/runtime/platform/syslog_android.cc
new file mode 100644
index 0000000..9aa77c0
--- /dev/null
+++ b/runtime/platform/syslog_android.cc
@@ -0,0 +1,38 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_ANDROID)
+
+#include "platform/syslog.h"
+
+#include <android/log.h>  // NOLINT
+#include <stdio.h>        // NOLINT
+
+namespace dart {
+
+// TODO(gram): We should be buffering the data and only outputting
+// it when we see a '\n'.
+
+void Syslog::VPrint(const char* format, va_list args) {
+  // If we launch the DartVM inside "adb shell" we will only get messages
+  // (critical ones or not) if we print them to stdout/stderr.
+  // We also log using android's logging system.
+  vprintf(format, args);
+  fflush(stdout);
+  __android_log_vprint(ANDROID_LOG_INFO, "Dart", format, args);
+}
+
+void Syslog::VPrintErr(const char* format, va_list args) {
+  // If we launch the DartVM inside "adb shell" we will only get messages
+  // (critical ones or not) if we print them to stdout/stderr.
+  // We also log using android's logging system.
+  vfprintf(stderr, format, args);
+  fflush(stderr);
+  __android_log_vprint(ANDROID_LOG_ERROR, "Dart", format, args);
+}
+
+}  // namespace dart
+
+#endif  // defined(HOST_OS_ANDROID)
diff --git a/runtime/platform/syslog_fuchsia.cc b/runtime/platform/syslog_fuchsia.cc
new file mode 100644
index 0000000..85e4c80
--- /dev/null
+++ b/runtime/platform/syslog_fuchsia.cc
@@ -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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_FUCHSIA)
+
+#include "platform/syslog.h"
+
+#include <stdio.h>  // NOLINT
+
+namespace dart {
+
+void Syslog::VPrint(const char* format, va_list args) {
+  vfprintf(stdout, format, args);
+  fflush(stdout);
+}
+
+void Syslog::VPrintErr(const char* format, va_list args) {
+  vfprintf(stderr, format, args);
+  fflush(stderr);
+}
+
+}  // namespace dart
+
+#endif  // defined(HOST_OS_FUCHSIA)
diff --git a/runtime/platform/syslog_linux.cc b/runtime/platform/syslog_linux.cc
new file mode 100644
index 0000000..269bc9f2
--- /dev/null
+++ b/runtime/platform/syslog_linux.cc
@@ -0,0 +1,26 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_LINUX)
+
+#include "platform/syslog.h"
+
+#include <stdio.h>  // NOLINT
+
+namespace dart {
+
+void Syslog::VPrint(const char* format, va_list args) {
+  vfprintf(stdout, format, args);
+  fflush(stdout);
+}
+
+void Syslog::VPrintErr(const char* format, va_list args) {
+  vfprintf(stderr, format, args);
+  fflush(stderr);
+}
+
+}  // namespace dart
+
+#endif  // defined(HOST_OS_LINUX)
diff --git a/runtime/platform/syslog_macos.cc b/runtime/platform/syslog_macos.cc
new file mode 100644
index 0000000..f01bfbf
--- /dev/null
+++ b/runtime/platform/syslog_macos.cc
@@ -0,0 +1,26 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_MACOS)
+
+#include "platform/syslog.h"
+
+#include <stdio.h>  // NOLINT
+
+namespace dart {
+
+void Syslog::VPrint(const char* format, va_list args) {
+  vfprintf(stdout, format, args);
+  fflush(stdout);
+}
+
+void Syslog::VPrintErr(const char* format, va_list args) {
+  vfprintf(stderr, format, args);
+  fflush(stderr);
+}
+
+}  // namespace dart
+
+#endif  // defined(HOST_OS_MACOS)
diff --git a/runtime/platform/syslog_win.cc b/runtime/platform/syslog_win.cc
new file mode 100644
index 0000000..07ab815
--- /dev/null
+++ b/runtime/platform/syslog_win.cc
@@ -0,0 +1,26 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_WINDOWS)
+
+#include "platform/syslog.h"
+
+#include <stdio.h>  // NOLINT
+
+namespace dart {
+
+void Syslog::VPrint(const char* format, va_list args) {
+  vfprintf(stdout, format, args);
+  fflush(stdout);
+}
+
+void Syslog::VPrintErr(const char* format, va_list args) {
+  vfprintf(stderr, format, args);
+  fflush(stderr);
+}
+
+}  // namespace dart
+
+#endif  // defined(HOST_OS_WINDOWS)
diff --git a/runtime/platform/text_buffer.cc b/runtime/platform/text_buffer.cc
index ec42113..ed2c640 100644
--- a/runtime/platform/text_buffer.cc
+++ b/runtime/platform/text_buffer.cc
@@ -6,8 +6,8 @@
 
 #include "platform/assert.h"
 #include "platform/globals.h"
+#include "platform/unicode.h"
 #include "platform/utils.h"
-#include "vm/unicode.h"
 
 namespace dart {
 
@@ -135,7 +135,7 @@
 void TextBuffer::EnsureCapacity(intptr_t len) {
   intptr_t remaining = buf_size_ - msg_len_;
   if (remaining <= len) {
-    intptr_t new_size = buf_size_ + Utils::Maximum(buf_size_, len);
+    intptr_t new_size = buf_size_ + Utils::Maximum(buf_size_, len + 1);
     char* new_buf = reinterpret_cast<char*>(realloc(buf_, new_size));
     if (new_buf == NULL) {
       OUT_OF_MEMORY();
diff --git a/runtime/platform/unicode.cc b/runtime/platform/unicode.cc
new file mode 100644
index 0000000..e45caf2
--- /dev/null
+++ b/runtime/platform/unicode.cc
@@ -0,0 +1,280 @@
+// 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.
+
+#include "platform/unicode.h"
+
+#include "platform/allocation.h"
+#include "platform/globals.h"
+#include "platform/syslog.h"
+
+namespace dart {
+
+// clang-format off
+const int8_t Utf8::kTrailBytes[256] = {
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+  4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0
+};
+// clang-format on
+
+const uint32_t Utf8::kMagicBits[7] = {0,  // Padding.
+                                      0x00000000, 0x00003080, 0x000E2080,
+                                      0x03C82080, 0xFA082080, 0x82082080};
+
+// Minimum values of code points used to check shortest form.
+const uint32_t Utf8::kOverlongMinimum[7] = {0,  // Padding.
+                                            0x0,     0x80,       0x800,
+                                            0x10000, 0xFFFFFFFF, 0xFFFFFFFF};
+
+// Returns the most restricted coding form in which the sequence of utf8
+// characters in 'utf8_array' can be represented in, and the number of
+// code units needed in that form.
+intptr_t Utf8::CodeUnitCount(const uint8_t* utf8_array,
+                             intptr_t array_len,
+                             Type* type) {
+  intptr_t len = 0;
+  Type char_type = kLatin1;
+  for (intptr_t i = 0; i < array_len; i++) {
+    uint8_t code_unit = utf8_array[i];
+    if (!IsTrailByte(code_unit)) {
+      ++len;
+      if (!IsLatin1SequenceStart(code_unit)) {          // > U+00FF
+        if (IsSupplementarySequenceStart(code_unit)) {  // >= U+10000
+          char_type = kSupplementary;
+          ++len;
+        } else if (char_type == kLatin1) {
+          char_type = kBMP;
+        }
+      }
+    }
+  }
+  *type = char_type;
+  return len;
+}
+
+// Returns true if str is a valid NUL-terminated UTF-8 string.
+bool Utf8::IsValid(const uint8_t* utf8_array, intptr_t array_len) {
+  intptr_t i = 0;
+  while (i < array_len) {
+    uint32_t ch = utf8_array[i] & 0xFF;
+    intptr_t j = 1;
+    if (ch >= 0x80) {
+      int8_t num_trail_bytes = kTrailBytes[ch];
+      bool is_malformed = false;
+      for (; j < num_trail_bytes; ++j) {
+        if ((i + j) < array_len) {
+          uint8_t code_unit = utf8_array[i + j];
+          is_malformed |= !IsTrailByte(code_unit);
+          ch = (ch << 6) + code_unit;
+        } else {
+          return false;
+        }
+      }
+      ch -= kMagicBits[num_trail_bytes];
+      if (!((is_malformed == false) && (j == num_trail_bytes) &&
+            !Utf::IsOutOfRange(ch) && !IsNonShortestForm(ch, j))) {
+        return false;
+      }
+    }
+    i += j;
+  }
+  return true;
+}
+
+intptr_t Utf8::Length(int32_t ch) {
+  if (ch <= kMaxOneByteChar) {
+    return 1;
+  } else if (ch <= kMaxTwoByteChar) {
+    return 2;
+  } else if (ch <= kMaxThreeByteChar) {
+    return 3;
+  }
+  ASSERT(ch <= kMaxFourByteChar);
+  return 4;
+}
+
+intptr_t Utf8::Encode(int32_t ch, char* dst) {
+  static const int kMask = ~(1 << 6);
+  if (ch <= kMaxOneByteChar) {
+    dst[0] = ch;
+    return 1;
+  }
+  if (ch <= kMaxTwoByteChar) {
+    dst[0] = 0xC0 | (ch >> 6);
+    dst[1] = 0x80 | (ch & kMask);
+    return 2;
+  }
+  if (ch <= kMaxThreeByteChar) {
+    dst[0] = 0xE0 | (ch >> 12);
+    dst[1] = 0x80 | ((ch >> 6) & kMask);
+    dst[2] = 0x80 | (ch & kMask);
+    return 3;
+  }
+  ASSERT(ch <= kMaxFourByteChar);
+  dst[0] = 0xF0 | (ch >> 18);
+  dst[1] = 0x80 | ((ch >> 12) & kMask);
+  dst[2] = 0x80 | ((ch >> 6) & kMask);
+  dst[3] = 0x80 | (ch & kMask);
+  return 4;
+}
+
+intptr_t Utf8::Decode(const uint8_t* utf8_array,
+                      intptr_t array_len,
+                      int32_t* dst) {
+  uint32_t ch = utf8_array[0] & 0xFF;
+  intptr_t i = 1;
+  if (ch >= 0x80) {
+    intptr_t num_trail_bytes = kTrailBytes[ch];
+    bool is_malformed = false;
+    for (; i < num_trail_bytes; ++i) {
+      if (i < array_len) {
+        uint8_t code_unit = utf8_array[i];
+        is_malformed |= !IsTrailByte(code_unit);
+        ch = (ch << 6) + code_unit;
+      } else {
+        *dst = -1;
+        return 0;
+      }
+    }
+    ch -= kMagicBits[num_trail_bytes];
+    if (!((is_malformed == false) && (i == num_trail_bytes) &&
+          !Utf::IsOutOfRange(ch) && !IsNonShortestForm(ch, i))) {
+      *dst = -1;
+      return 0;
+    }
+  }
+  *dst = ch;
+  return i;
+}
+intptr_t Utf8::ReportInvalidByte(const uint8_t* utf8_array,
+                                 intptr_t array_len,
+                                 intptr_t len) {
+  intptr_t i = 0;
+  intptr_t j = 0;
+  intptr_t num_bytes;
+  for (; (i < array_len) && (j < len); i += num_bytes, ++j) {
+    int32_t ch;
+    bool is_supplementary = IsSupplementarySequenceStart(utf8_array[i]);
+    num_bytes = Utf8::Decode(&utf8_array[i], (array_len - i), &ch);
+    if (ch == -1) {
+      break;  // Invalid input.
+    }
+    if (is_supplementary) {
+      j = j + 1;
+    }
+  }
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+  // Remain silent while libFuzzer is active, since
+  // the output only slows down the in-process fuzzing.
+#else
+  Syslog::PrintErr("Invalid UTF8 sequence encountered, ");
+  for (intptr_t idx = 0; idx < 10 && (i + idx) < array_len; idx++) {
+    Syslog::PrintErr("(Error Code: %X + idx: %" Pd " )", utf8_array[idx + i],
+                     (idx + i));
+  }
+  Syslog::PrintErr("\n");
+#endif
+  return i;
+}
+
+bool Utf8::DecodeToLatin1(const uint8_t* utf8_array,
+                          intptr_t array_len,
+                          uint8_t* dst,
+                          intptr_t len) {
+  intptr_t i = 0;
+  intptr_t j = 0;
+  intptr_t num_bytes;
+  for (; (i < array_len) && (j < len); i += num_bytes, ++j) {
+    int32_t ch;
+    ASSERT(IsLatin1SequenceStart(utf8_array[i]));
+    num_bytes = Utf8::Decode(&utf8_array[i], (array_len - i), &ch);
+    if (ch == -1) {
+      return false;  // Invalid input.
+    }
+    ASSERT(Utf::IsLatin1(ch));
+    dst[j] = ch;
+  }
+  if ((i < array_len) && (j == len)) {
+    return false;  // Output overflow.
+  }
+  return true;  // Success.
+}
+
+bool Utf8::DecodeToUTF16(const uint8_t* utf8_array,
+                         intptr_t array_len,
+                         uint16_t* dst,
+                         intptr_t len) {
+  intptr_t i = 0;
+  intptr_t j = 0;
+  intptr_t num_bytes;
+  for (; (i < array_len) && (j < len); i += num_bytes, ++j) {
+    int32_t ch;
+    bool is_supplementary = IsSupplementarySequenceStart(utf8_array[i]);
+    num_bytes = Utf8::Decode(&utf8_array[i], (array_len - i), &ch);
+    if (ch == -1) {
+      return false;  // Invalid input.
+    }
+    if (is_supplementary) {
+      if (j == (len - 1)) return false;  // Output overflow.
+      Utf16::Encode(ch, &dst[j]);
+      j = j + 1;
+    } else {
+      dst[j] = ch;
+    }
+  }
+  if ((i < array_len) && (j == len)) {
+    return false;  // Output overflow.
+  }
+  return true;  // Success.
+}
+
+bool Utf8::DecodeToUTF32(const uint8_t* utf8_array,
+                         intptr_t array_len,
+                         int32_t* dst,
+                         intptr_t len) {
+  intptr_t i = 0;
+  intptr_t j = 0;
+  intptr_t num_bytes;
+  for (; (i < array_len) && (j < len); i += num_bytes, ++j) {
+    int32_t ch;
+    num_bytes = Utf8::Decode(&utf8_array[i], (array_len - i), &ch);
+    if (ch == -1) {
+      return false;  // Invalid input.
+    }
+    dst[j] = ch;
+  }
+  if ((i < array_len) && (j == len)) {
+    return false;  // Output overflow.
+  }
+  return true;  // Success.
+}
+
+bool Utf8::DecodeCStringToUTF32(const char* str, int32_t* dst, intptr_t len) {
+  ASSERT(str != NULL);
+  intptr_t array_len = strlen(str);
+  const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(str);
+  return Utf8::DecodeToUTF32(utf8_array, array_len, dst, len);
+}
+
+void Utf16::Encode(int32_t codepoint, uint16_t* dst) {
+  ASSERT(codepoint > Utf16::kMaxCodeUnit);
+  ASSERT(dst != NULL);
+  dst[0] = (Utf16::kLeadSurrogateOffset + (codepoint >> 10));
+  dst[1] = (0xDC00 + (codepoint & 0x3FF));
+}
+
+}  // namespace dart
diff --git a/runtime/platform/unicode.h b/runtime/platform/unicode.h
new file mode 100644
index 0000000..b784823
--- /dev/null
+++ b/runtime/platform/unicode.h
@@ -0,0 +1,251 @@
+// 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.
+
+#ifndef RUNTIME_PLATFORM_UNICODE_H_
+#define RUNTIME_PLATFORM_UNICODE_H_
+
+#include "platform/allocation.h"
+#include "platform/globals.h"
+
+namespace dart {
+
+class String;
+
+class Utf : AllStatic {
+ public:
+  static const int32_t kMaxCodePoint = 0x10FFFF;
+  static const int32_t kInvalidChar = 0xFFFFFFFF;
+
+  static bool IsLatin1(int32_t code_point) {
+    return (code_point >= 0) && (code_point <= 0xFF);
+  }
+
+  static bool IsBmp(int32_t code_point) {
+    return (code_point >= 0) && (code_point <= 0xFFFF);
+  }
+
+  static bool IsSupplementary(int32_t code_point) {
+    return (code_point > 0xFFFF) && (code_point <= kMaxCodePoint);
+  }
+
+  // Returns true if the code point value is above Plane 17.
+  static bool IsOutOfRange(int32_t code_point) {
+    return (code_point < 0) || (code_point > kMaxCodePoint);
+  }
+};
+
+class Utf8 : AllStatic {
+ public:
+  enum Type {
+    kLatin1 = 0,     // Latin-1 code point [U+0000, U+00FF].
+    kBMP,            // Basic Multilingual Plane code point [U+0000, U+FFFF].
+    kSupplementary,  // Supplementary code point [U+010000, U+10FFFF].
+  };
+
+  // Returns the most restricted coding form in which the sequence of utf8
+  // characters in 'utf8_array' can be represented in, and the number of
+  // code units needed in that form.
+  static intptr_t CodeUnitCount(const uint8_t* utf8_array,
+                                intptr_t array_len,
+                                Type* type);
+
+  // Returns true if 'utf8_array' is a valid UTF-8 string.
+  static bool IsValid(const uint8_t* utf8_array, intptr_t array_len);
+
+  static intptr_t Length(int32_t ch);
+  static intptr_t Length(const String& str);
+
+  static intptr_t Encode(int32_t ch, char* dst);
+  static intptr_t Encode(const String& src, char* dst, intptr_t len);
+
+  static intptr_t Decode(const uint8_t* utf8_array,
+                         intptr_t array_len,
+                         int32_t* ch);
+
+  static bool DecodeToLatin1(const uint8_t* utf8_array,
+                             intptr_t array_len,
+                             uint8_t* dst,
+                             intptr_t len);
+  static bool DecodeToUTF16(const uint8_t* utf8_array,
+                            intptr_t array_len,
+                            uint16_t* dst,
+                            intptr_t len);
+  static bool DecodeToUTF32(const uint8_t* utf8_array,
+                            intptr_t array_len,
+                            int32_t* dst,
+                            intptr_t len);
+  static intptr_t ReportInvalidByte(const uint8_t* utf8_array,
+                                    intptr_t array_len,
+                                    intptr_t len);
+  static bool DecodeCStringToUTF32(const char* str, int32_t* dst, intptr_t len);
+
+  static const int32_t kMaxOneByteChar = 0x7F;
+  static const int32_t kMaxTwoByteChar = 0x7FF;
+  static const int32_t kMaxThreeByteChar = 0xFFFF;
+  static const int32_t kMaxFourByteChar = Utf::kMaxCodePoint;
+
+ private:
+  static bool IsTrailByte(uint8_t code_unit) {
+    return (code_unit & 0xC0) == 0x80;
+  }
+
+  static bool IsNonShortestForm(uint32_t code_point, size_t num_code_units) {
+    return code_point < kOverlongMinimum[num_code_units];
+  }
+
+  static bool IsLatin1SequenceStart(uint8_t code_unit) {
+    // Check if utf8 sequence is the start of a codepoint <= U+00FF
+    return (code_unit <= 0xC3);
+  }
+
+  static bool IsSupplementarySequenceStart(uint8_t code_unit) {
+    // Check if utf8 sequence is the start of a codepoint >= U+10000.
+    return (code_unit >= 0xF0);
+  }
+
+  static const int8_t kTrailBytes[];
+  static const uint32_t kMagicBits[];
+  static const uint32_t kOverlongMinimum[];
+};
+
+class Utf16 : AllStatic {
+ public:
+  // Returns the length of the code point in UTF-16 code units.
+  static intptr_t Length(int32_t ch) {
+    return (ch <= Utf16::kMaxCodeUnit) ? 1 : 2;
+  }
+
+  // Returns true if ch is a lead or trail surrogate.
+  static bool IsSurrogate(uint32_t ch) { return (ch & 0xFFFFF800) == 0xD800; }
+
+  // Returns true if ch is a lead surrogate.
+  static bool IsLeadSurrogate(uint32_t ch) {
+    return (ch & 0xFFFFFC00) == 0xD800;
+  }
+
+  // Returns true if ch is a low surrogate.
+  static bool IsTrailSurrogate(uint32_t ch) {
+    return (ch & 0xFFFFFC00) == 0xDC00;
+  }
+
+  // Returns the character at i and advances i to the next character
+  // boundary.
+  static int32_t Next(const uint16_t* characters, intptr_t* i, intptr_t len) {
+    int32_t ch = characters[*i];
+    if (Utf16::IsLeadSurrogate(ch) && (*i < (len - 1))) {
+      int32_t ch2 = characters[*i + 1];
+      if (Utf16::IsTrailSurrogate(ch2)) {
+        ch = Utf16::Decode(ch, ch2);
+        *i += 1;
+      }
+    }
+    *i += 1;
+    return ch;
+  }
+
+  // Decodes a surrogate pair into a supplementary code point.
+  static int32_t Decode(uint16_t lead, uint16_t trail) {
+    return 0x10000 + ((lead & 0x000003FF) << 10) + (trail & 0x3FF);
+  }
+
+  // Encodes a single code point.
+  static void Encode(int32_t codepoint, uint16_t* dst);
+
+  static const int32_t kMaxCodeUnit = 0xFFFF;
+  static const int32_t kLeadSurrogateStart = 0xD800;
+  static const int32_t kLeadSurrogateEnd = 0xDBFF;
+  static const int32_t kTrailSurrogateStart = 0xDC00;
+  static const int32_t kTrailSurrogateEnd = 0xDFFF;
+
+ private:
+  static const int32_t kLeadSurrogateOffset = (0xD800 - (0x10000 >> 10));
+
+  static const int32_t kSurrogateOffset = (0x10000 - (0xD800 << 10) - 0xDC00);
+};
+
+class CaseMapping : AllStatic {
+ public:
+  // Maps a code point to uppercase.
+  static int32_t ToUpper(int32_t code_point) {
+    return Convert(code_point, kUppercase);
+  }
+
+  // Maps a code point to lowercase.
+  static int32_t ToLower(int32_t code_point) {
+    return Convert(code_point, kLowercase);
+  }
+
+ private:
+  // Property is a delta to the uppercase mapping.
+  static const int32_t kUppercase = 1;
+
+  // Property is a delta to the uppercase mapping.
+  static const int32_t kLowercase = 2;
+
+  // Property is an index into the exception table.
+  static const int32_t kException = 3;
+
+  // Type bit-field parameters
+  static const int32_t kTypeShift = 2;
+  static const int32_t kTypeMask = 3;
+
+  // The size of the stage 1 index.
+  // TODO(cshapiro): improve indexing so this value is unnecessary.
+  static const intptr_t kStage1Size = 261;
+
+  // The size of a stage 2 block in bytes.
+  static const intptr_t kBlockSizeLog2 = 8;
+  static const intptr_t kBlockSize = 1 << kBlockSizeLog2;
+
+  static int32_t Convert(int32_t ch, int32_t mapping) {
+    if (Utf::IsLatin1(ch)) {
+      int32_t info = stage2_[ch];
+      if ((info & kTypeMask) == mapping) {
+        ch += info >> kTypeShift;
+      }
+    } else if (ch <= (kStage1Size << kBlockSizeLog2)) {
+      int16_t offset = stage1_[ch >> kBlockSizeLog2] << kBlockSizeLog2;
+      int32_t info = stage2_[offset + (ch & (kBlockSize - 1))];
+      int32_t type = info & kTypeMask;
+      if (type == mapping) {
+        ch += (info >> kTypeShift);
+      } else if (type == kException) {
+        ch += stage2_exception_[info >> kTypeShift][mapping - 1];
+      }
+    }
+    return ch;
+  }
+
+  // Index into the data array.
+  static const uint8_t stage1_[];
+
+  // Data for small code points with one mapping
+  static const int16_t stage2_[];
+
+  // Data for large code points or code points with both mappings.
+  static const int32_t stage2_exception_[][2];
+};
+
+class Latin1 {
+ public:
+  static const int32_t kMaxChar = 0xff;
+  // Convert the character to Latin-1 case equivalent if possible.
+  static inline uint16_t TryConvertToLatin1(uint16_t c) {
+    switch (c) {
+      // This are equivalent characters in unicode.
+      case 0x39c:
+      case 0x3bc:
+        return 0xb5;
+      // This is an uppercase of a Latin-1 character
+      // outside of Latin-1.
+      case 0x178:
+        return 0xff;
+    }
+    return c;
+  }
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_PLATFORM_UNICODE_H_
diff --git a/runtime/platform/utils.cc b/runtime/platform/utils.cc
index ee982dc..2193a05 100644
--- a/runtime/platform/utils.cc
+++ b/runtime/platform/utils.cc
@@ -108,4 +108,30 @@
   return static_cast<uint32_t>(a);
 }
 
+char* Utils::SCreate(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  char* buffer = VSCreate(format, args);
+  va_end(args);
+  return buffer;
+}
+
+char* Utils::VSCreate(const char* format, va_list args) {
+  // 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 = 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;
+}
+
 }  // namespace dart
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 2951d43..993ff26 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -203,7 +203,14 @@
     return (static_cast<int64_t>(high) << 32) | (low & 0x0ffffffffLL);
   }
 
-  static bool IsDecimalDigit(char c) { return ('0' <= c) && (c <= '9'); }
+  static inline constexpr bool IsAlphaNumeric(uint32_t c) {
+    return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
+           IsDecimalDigit(c);
+  }
+
+  static inline constexpr bool IsDecimalDigit(uint32_t c) {
+    return ('0' <= c) && (c <= '9');
+  }
 
   static bool IsHexDigit(char c) {
     return IsDecimalDigit(c) || (('A' <= c) && (c <= 'F')) ||
@@ -386,6 +393,10 @@
   static int SNPrint(char* str, size_t size, const char* format, ...)
       PRINTF_ATTRIBUTE(3, 4);
   static int VSNPrint(char* str, size_t size, const char* format, va_list args);
+
+  // Allocate a string and print formatted output into a malloc'd buffer.
+  static char* SCreate(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
+  static char* VSCreate(const char* format, va_list args);
 };
 
 }  // namespace dart
diff --git a/runtime/tests/vm/dart/data_uri_import_test.dart b/runtime/tests/vm/dart/data_uri_import_test.dart
index 8ce4e1a..576f302 100644
--- a/runtime/tests/vm/dart/data_uri_import_test.dart
+++ b/runtime/tests/vm/dart/data_uri_import_test.dart
@@ -6,13 +6,13 @@
 import 'data:application/dart;charset=utf-8,foo%28%29%20%3D%3E%2042%3B';  /// percentencoded: ok
 import 'data:text/plain;charset=utf-8,foo%28%29%20%3D%3E%2042%3B';  /// wrongmime: ok
 import 'data:;charset=utf-8,foo%28%29%20%3D%3E%2042%3B';  /// nomime: ok
-import 'data:application/dart;charset=utf-16,foo%28%29%20%3D%3E%2042%3B';  /// utf16: runtime error
+import 'data:application/dart;charset=utf-16,foo%28%29%20%3D%3E%2042%3B';  /// utf16: ok
 import 'data:application/dart,foo%28%29%20%3D%3E%2042%3B';  /// nocharset: ok
-import 'data:application/dart;charset=utf-8,foo?%9g';  /// badencodeddate: runtime error
+import 'data:application/dart;charset=utf-8,foo?%9g';  /// badencodeddate: compile-time error
 import 'data:application/dart;charset=utf-8;base64,Zm9vKCkgPT4gNDI7';  /// base64: ok
 
 import "package:expect/expect.dart";
 
 main() {
   Expect.equals(42, foo());
-}
\ No newline at end of file
+}
diff --git a/runtime/tests/vm/dart/issue_31959_31960_test.dart b/runtime/tests/vm/dart/issue_31959_31960_test.dart
new file mode 100644
index 0000000..3990fb6
--- /dev/null
+++ b/runtime/tests/vm/dart/issue_31959_31960_test.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2019, 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:isolate';
+import 'dart:math';
+import 'dart:typed_data';
+
+import 'package:async_helper/async_helper.dart' show asyncStart, asyncEnd;
+import 'package:expect/expect.dart';
+
+Uint8List generateSampleList(final size) {
+  final list = Uint8List(size);
+  for (int i = 0; i < size; i++) {
+    list[i] = i % 243;
+  }
+  return list;
+}
+
+void validateReceivedList(final expectedSize, final list) {
+  Expect.equals(expectedSize, list.length);
+  // probe few elements
+  for (int i = 0; i < list.length; i += max<num>(1, expectedSize ~/ 1000)) {
+    Expect.equals(i % 243, list[i]);
+  }
+}
+
+Future<Null> testSend(
+    bool transferable, int toIsolateSize, int fromIsolateSize) async {
+  asyncStart();
+  final port = ReceivePort();
+  final inbox = StreamIterator(port);
+  await Isolate.spawn(isolateMain,
+      [transferable, toIsolateSize, fromIsolateSize, port.sendPort]);
+  await inbox.moveNext();
+  final outbox = inbox.current;
+  final workWatch = Stopwatch();
+  final data = generateSampleList(toIsolateSize);
+  int count = 10;
+  workWatch.start();
+  while (count-- > 0) {
+    outbox.send(transferable ? TransferableTypedData.fromList([data]) : data);
+    await inbox.moveNext();
+    validateReceivedList(
+        fromIsolateSize,
+        transferable
+            ? inbox.current.materialize().asUint8List()
+            : inbox.current);
+  }
+  print('total ${workWatch.elapsedMilliseconds}ms');
+  outbox.send(null);
+  port.close();
+  asyncEnd();
+}
+
+main() async {
+  asyncStart();
+  int bignum = 100 * 1000 * 1000;
+  await testSend(false, bignum, 1); // none
+  await testSend(true, bignum, 1); // 31959tr
+  await testSend(false, bignum, 1); // 31960
+  await testSend(true, bignum, 1); // 31960tr
+  asyncEnd();
+}
+
+Future<Null> isolateMain(List config) async {
+  bool transferable = config[0];
+  int toIsolateSize = config[1];
+  int fromIsolateSize = config[2];
+  SendPort outbox = config[3];
+
+  final port = ReceivePort();
+  final inbox = StreamIterator(port);
+  outbox.send(port.sendPort);
+  final data = generateSampleList(fromIsolateSize);
+  while (true) {
+    await inbox.moveNext();
+    if (inbox.current == null) {
+      break;
+    }
+    validateReceivedList(
+        toIsolateSize,
+        transferable
+            ? inbox.current.materialize().asUint8List()
+            : inbox.current);
+    outbox.send(transferable ? TransferableTypedData.fromList([data]) : data);
+  }
+  port.close();
+}
diff --git a/runtime/tests/vm/dart/regress36953_test.dart b/runtime/tests/vm/dart/regress36953_test.dart
new file mode 100644
index 0000000..617049b
--- /dev/null
+++ b/runtime/tests/vm/dart/regress36953_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dartbug.com/36953: check that phi is inserted correctly
+// when try block has no normal exit.
+
+// VMOptions=--optimization_counter_threshold=10 --deterministic
+
+import "package:expect/expect.dart";
+
+void testBody() {
+  var v;
+  do {
+    try {} catch (e, st) {
+      continue;
+    }
+
+    try {
+      v = 10;
+      throw "";
+    } catch (e, st) {}
+  } while (v++ < 10);
+  Expect.equals(11, v);
+}
+
+void main() {
+  testBody();
+  testBody();
+}
diff --git a/runtime/tests/vm/dart/regress_36636_test.dart b/runtime/tests/vm/dart/regress_36636_test.dart
new file mode 100644
index 0000000..1daf616
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_36636_test.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, 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=--intrinsify=false --no-use-vfp
+
+main() {}
diff --git a/runtime/tests/vm/dart/spawn_shutdown_test.dart b/runtime/tests/vm/dart/spawn_shutdown_test.dart
index 235a0d8..6e42f3e 100644
--- a/runtime/tests/vm/dart/spawn_shutdown_test.dart
+++ b/runtime/tests/vm/dart/spawn_shutdown_test.dart
@@ -1,6 +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=--enable-asserts
 
 import 'dart:async';
 import 'dart:io';
@@ -16,7 +17,7 @@
 
 trySpawn(Function f, Object o) async {
   try {
-    await Isolate.spawn(f, o);
+    await Isolate.spawn<SendPort>(f, o);
   } catch (e) {
     // Isolate spawning may fail if the program is ending.
     assert(e is IsolateSpawnException);
diff --git a/runtime/tests/vm/dart/transferable_test.dart b/runtime/tests/vm/dart/transferable_test.dart
new file mode 100644
index 0000000..a9a97d7
--- /dev/null
+++ b/runtime/tests/vm/dart/transferable_test.dart
@@ -0,0 +1,130 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that validates that transferables are faster than regular typed data.
+
+import 'dart:async';
+import 'dart:isolate';
+import 'dart:typed_data';
+
+import "package:expect/expect.dart";
+
+const int toIsolateSize = 100 * 1024 * 1024;
+const int fromIsolateSize = 100 * 1024 * 1024;
+
+const int nIterations = 5;
+
+int iteration;
+bool keepTimerRunning;
+
+main() async {
+  keepTimerRunning = true;
+
+  print('--- standard');
+  iteration = nIterations;
+  final stopwatch = new Stopwatch()..start();
+  await runBatch(useTransferable: false);
+  final standard = stopwatch.elapsedMilliseconds;
+
+  print('--- transferable');
+  iteration = nIterations;
+  stopwatch.reset();
+  await runBatch(useTransferable: true);
+  final transferable = stopwatch.elapsedMilliseconds;
+  print(
+      'standard($standard ms)/transferable($transferable ms): ${standard / transferable}x');
+  Expect.isTrue(standard / transferable > 1.2);
+  keepTimerRunning = false;
+}
+
+packageList(Uint8List data, bool useTransferable) {
+  return useTransferable
+      ? TransferableTypedData.fromList(<Uint8List>[data])
+      : data;
+}
+
+packageByteData(ByteData data, bool useTransferable) {
+  return useTransferable
+      ? TransferableTypedData.fromList(<Uint8List>[data.buffer.asUint8List()])
+      : data;
+}
+
+class StartMessage {
+  final SendPort sendPort;
+  final bool useTransferable;
+
+  StartMessage(this.sendPort, this.useTransferable);
+}
+
+runBatch({bool useTransferable}) async {
+  Timer.run(idleTimer);
+  final port = ReceivePort();
+  final inbox = StreamIterator<dynamic>(port);
+  final worker = await Isolate.spawn(
+      isolateMain, StartMessage(port.sendPort, useTransferable),
+      paused: true);
+  final workerCompleted = Completer<bool>();
+  final workerExitedPort = ReceivePort()
+    ..listen((_) => workerCompleted.complete(true));
+  worker.addOnExitListener(workerExitedPort.sendPort);
+  worker.resume(worker.pauseCapability);
+
+  await inbox.moveNext();
+  final outbox = inbox.current;
+  final workWatch = new Stopwatch();
+  final data = new Uint8List(toIsolateSize);
+
+  while (iteration-- > 0) {
+    final packagedData = packageList(data, useTransferable);
+    workWatch.start();
+    outbox.send(packagedData);
+    await inbox.moveNext();
+
+    final received = inbox.current;
+    final receivedData =
+        received is TransferableTypedData ? received.materialize() : received;
+    int time = workWatch.elapsedMilliseconds;
+    print('${time}ms for round-trip');
+    workWatch.reset();
+  }
+  outbox.send(null);
+
+  await workerCompleted.future;
+  workerExitedPort.close();
+  port.close();
+}
+
+Future<Null> isolateMain(StartMessage startMessage) async {
+  final port = new ReceivePort();
+  final inbox = new StreamIterator<dynamic>(port);
+  startMessage.sendPort.send(port.sendPort);
+  final data = Uint8List.view(new Uint8List(fromIsolateSize).buffer);
+  while (true) {
+    await inbox.moveNext();
+    final received = inbox.current;
+    if (received == null) {
+      break;
+    }
+    final receivedData =
+        received is TransferableTypedData ? received.materialize() : received;
+
+    final packagedData = packageList(data, startMessage.useTransferable);
+
+    startMessage.sendPort.send(packagedData);
+  }
+  port.close();
+}
+
+final Stopwatch idleWatch = new Stopwatch();
+
+void idleTimer() {
+  idleWatch.stop();
+  final time = idleWatch.elapsedMilliseconds;
+  if (time > 5) print('${time}ms since last checkin');
+  idleWatch.reset();
+  idleWatch.start();
+  if (keepTimerRunning) {
+    Timer.run(idleTimer);
+  }
+}
diff --git a/runtime/tests/vm/dart/transferable_throws_oom_test.dart b/runtime/tests/vm/dart/transferable_throws_oom_test.dart
new file mode 100644
index 0000000..c1b21f0
--- /dev/null
+++ b/runtime/tests/vm/dart/transferable_throws_oom_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that ensures correct exception when running out of memory for
+// really large transferable.
+
+import 'dart:async';
+import 'dart:collection';
+import 'dart:core';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:typed_data';
+import 'dart:math';
+
+import "package:expect/expect.dart";
+
+main() {
+  // Attempt to create total 1tb uint8list which should fail on 32 and 64-bit
+  // platforms.
+  final bytes100MB = Uint8List(100 * 1024 * 1024);
+  final total1TB = List<Uint8List>.filled(10000, bytes100MB);
+  // Try to make a 1 TB transferable.
+  Expect.throws(() => TransferableTypedData.fromList(total1TB));
+}
diff --git a/runtime/tests/vm/dart/transferable_throws_test.dart b/runtime/tests/vm/dart/transferable_throws_test.dart
new file mode 100644
index 0000000..860965a
--- /dev/null
+++ b/runtime/tests/vm/dart/transferable_throws_test.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that ensures correct exceptions are thrown when misusing
+// [TransferableTypedData].
+
+import 'dart:async';
+import 'dart:collection';
+import 'dart:core';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:typed_data';
+import 'dart:math';
+
+import "package:expect/expect.dart";
+
+throwsIfMaterializeAfterSend() async {
+  final completer = Completer<bool>();
+  final rp = ReceivePort()
+    ..listen((e) {
+      completer.complete(true);
+    });
+  final transferable = TransferableTypedData.fromList([Uint8List(1024)]);
+  rp.sendPort.send(transferable);
+  Expect.throwsArgumentError(() => transferable.materialize());
+  await completer.future;
+  rp.close();
+}
+
+throwsIfSendMoreThanOnce() async {
+  final completer = Completer<bool>();
+  final rp = ReceivePort()
+    ..listen((e) {
+      completer.complete(true);
+    });
+  final bytes = Uint8List(1024);
+  final transferable = TransferableTypedData.fromList([bytes]);
+  rp.sendPort.send(transferable);
+  Expect.throwsArgumentError(() => rp.sendPort.send(transferable));
+  await completer.future;
+  rp.close();
+}
+
+throwsIfMaterializeMoreThanOnce() {
+  final transferable = TransferableTypedData.fromList([Uint8List(1024)]);
+  transferable.materialize();
+  Expect.throwsArgumentError(() => transferable.materialize());
+}
+
+throwsIfReceiverMaterializesMoreThanOnce() async {
+  final completer = Completer<List>();
+  final isolateErrors = ReceivePort()..listen((e) => completer.complete(e));
+  await Isolate.spawn(
+      receiver, TransferableTypedData.fromList([Uint8List(1024)]),
+      onError: isolateErrors.sendPort);
+  final error = await completer.future;
+  Expect.equals(
+      error[0],
+      "Invalid argument(s): Attempt to materialize object that was"
+      " transferred already.");
+  isolateErrors.close();
+}
+
+void receiver(final transferable) {
+  transferable.materialize();
+  transferable.materialize();
+}
+
+throwsIfCummulativeListIsTooLargeOn32bitPlatform() {
+  try {
+    int maxUint8ListSize = pow(2, 30);
+    // Check whether we are on 32-bit or 64-bit platform.
+    new Uint8List(maxUint8ListSize);
+    // On 64-bit platform we will have difficulty allocating large enough
+    // Uint8List to verify "too large" use case, so do nothing.
+    return;
+  } catch (_) {}
+
+  var halfmax = new Uint8List(pow(2, 29) - 1);
+  Expect.throwsArgumentError(
+      () => TransferableTypedData.fromList([halfmax, halfmax, Uint8List(2)]));
+}
+
+class MyList<T> extends ListBase<T> {
+  @override
+  int length;
+
+  @override
+  T operator [](int index) => null;
+  @override
+  void operator []=(int index, T value) {}
+}
+
+class MyTypedData implements TypedData {
+  noSuchMethod(_) {}
+}
+
+main() async {
+  await throwsIfMaterializeAfterSend();
+  await throwsIfSendMoreThanOnce();
+  throwsIfMaterializeMoreThanOnce();
+  await throwsIfReceiverMaterializesMoreThanOnce();
+  throwsIfCummulativeListIsTooLargeOn32bitPlatform();
+
+  Expect.throwsArgumentError(() => TransferableTypedData.fromList(null));
+  Expect.throwsArgumentError(() => TransferableTypedData.fromList([null]));
+  Expect.throwsArgumentError(
+      () => TransferableTypedData.fromList(MyList<Uint8List>()));
+  Expect.throwsArgumentError(
+      () => TransferableTypedData.fromList([MyTypedData()]));
+}
diff --git a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
index 266adde..fa99a62 100644
--- a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
@@ -149,6 +149,11 @@
 
     match = matchComplete(field, line);
     if (match != null && currentClass != null) {
+      if (fields[currentClass] == null) {
+        hasMissingFields = true;
+        print("$currentClass is missing entirely.");
+        continue;
+      }
       if (!fields[currentClass].contains(match.group(2))) {
         hasMissingFields = true;
         print("$currentClass is missing ${match.group(2)}.");
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 195b548..5b8bc01 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -2,12 +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.
 
-cc/AllocGeneric_Overflow: Crash, Fail # These tests are expected to crash on all platforms.
-cc/ArrayNew_Overflow_Crash: Crash, Fail # These tests are expected to crash on all platforms.
-cc/CodeExecutability: Crash, Fail # These tests are expected to crash on all platforms.
-cc/CodeImmutability: Crash, Fail # These tests are expected to crash on all platforms.
-cc/Dart2JSCompileAll: Fail, Crash # Issue 27369
-cc/Dart2JSCompilerStats: Fail, Crash # Issue 27369
 cc/Fail0: Fail # These tests are expected to crash on all platforms.
 cc/Fail1: Fail # These tests are expected to crash on all platforms.
 cc/Fail2: Fail # These tests are expected to crash on all platforms.
@@ -18,32 +12,29 @@
 cc/IsolateReload_PendingUnqualifiedCall_InstanceToStatic: Fail # Issue 32981
 cc/IsolateReload_PendingUnqualifiedCall_StaticToInstance: Fail # Issue 32981
 cc/IsolateReload_RunNewFieldInitializersWithGenerics: Fail # Issue 32299
-cc/SNPrint_BadArgs: Crash, Fail # These tests are expected to crash on all platforms.
 dart/data_uri_import_test/none: SkipByDesign
 dart/snapshot_version_test: Skip # This test is a Dart1 test (script snapshot)
 dart/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
 dart/stack_overflow_shared_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
 dart/use_bare_instructions_flag_test: Pass, Slow # Spawns several subprocesses
 
+cc/Profiler_StringInterpolation: Fail # Issue 37208
+
 [ $mode == debug ]
 dart/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
 
-[ $builder_tag == asan ]
-cc/CodeExecutability: Fail, OK # Address Sanitizer turns a crash into a failure.
-cc/CodeImmutability: Fail, OK # Address Sanitizer turns a crash into a failure.
-
 [ $builder_tag == optimization_counter_threshold ]
 dart/appjit*: SkipByDesign # Test needs to a particular opt-counter value
 dart/kernel_determinism_test: SkipSlow
 
 [ $compiler == app_jitk ]
-dart/data_uri_import_test/utf16: MissingRuntimeError
 dart/redirection_type_shuffling_test/none: RuntimeError
 dart/snapshot_version_test: RuntimeError
 
 [ $hot_reload || $hot_reload_rollback ]
 dart/compilation_trace_test: Pass, Slow
 dart/type_feedback_test: Pass, Slow
+dart/issue_31959_31960_test: SkipSlow
 
 [ $compiler != dartk || ($arch != x64 && $arch != simarm && $arch != arm) || $hot_reload || $hot_reload_rollback ]
 dart/entrypoints/jit/*: SkipByDesign  # Only supported in the Dart 2 JIT and AOT, and test optimizations - hence disabled on hotreload bots.
@@ -65,6 +56,12 @@
 [ $runtime != vm && $runtime != dart_precompiled ]
 dart/catch_entry_state: SkipByDesign
 
+[ $builder_tag == asan ]
+dart/transferable_throws_oom_test: SkipByDesign # This test tries to allocate too much memory on purpose. Still dartbug.com/37188
+
+[ $system == macos ]
+dart/transferable_throws_oom_test: SkipByDesign # Allocating too much memory to cause OOM doesn't work on mac
+
 [ $compiler != dartk && $compiler != dartkb ]
 cc/IsolateReload_KernelIncrementalCompile: SkipByDesign
 cc/IsolateReload_KernelIncrementalCompileAppAndLib: SkipByDesign
@@ -92,7 +89,7 @@
 [ $runtime == vm && $mode == product && $compiler == dartk ]
 cc/CorelibIsolateStartup: Timeout, Pass
 
-[ $runtime != vm ]
+[ $runtime != vm && $runtime != dart_precompiled ]
 dart/*: SkipByDesign # VM specific tests
 
 [ $runtime != dart_precompiled  || $system == android ]
@@ -115,7 +112,7 @@
 cc/GenKernelKernelMaxRSS: Skip  # Issue 34393.
 dart/appjit_bytecode_simple_test: Skip  # Issue 34393.
 
-[ $arch == simarm || $arch == simarm64 || $arch == simdbc || $arch == simdbc64 || $arch == ia32 || $arch == arm ]
+[ $arch == simarm || $arch == simdbc || $arch == simdbc64 || $arch == ia32 || $arch == arm ]
 cc/GenKernelKernelLoadKernel: SkipByDesign  # No interpreter support.
 cc/GenKernelKernelReadAllBytecode: SkipByDesign  # No interpreter support.
 cc/GenKernelKernelCombined: SkipByDesign  # No interpreter support.
@@ -135,9 +132,6 @@
 dart/data_uri_import_test/utf16: Crash
 dart/data_uri_import_test/wrongmime: Crash
 
-[ $builder_tag == asan && $mode == debug && ($runtime == dart_precompiled || $runtime == vm) ]
-cc/Dart2JSCompileAll: SkipSlow # Timeout.
-
 # Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
 # batch mode.
@@ -161,7 +155,6 @@
 cc/Debugger_SetBreakpointInPartOfLibrary: Crash
 cc/IsolateReload_NotTypedefToTypedef: Fail
 cc/IsolateReload_TypedefToNotTypedef: Fail
-dart/data_uri_import_test/utf16: MissingRuntimeError
 dart/spawn_shutdown_test: SkipSlow
 
 [ ($compiler == dartk || $compiler == dartkb) && $runtime == vm && $system == macos ]
@@ -186,6 +179,7 @@
 
 [ ($compiler == dartk || $compiler == dartkb) && ($arch == simarm || $arch == simarm64 || $arch == simdbc || $arch == simdbc64) ]
 dart/appjit*: SkipSlow # DFE too slow
+dart/issue_31959_31960_test: SkipSlow
 
 # Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
@@ -203,7 +197,6 @@
 dart/kernel_determinism_test: SkipByDesign # Test needs to run from source
 
 [ $compiler == dartkp && ($runtime == dart_precompiled || $runtime == vm) ]
-dart/data_uri_import_test/utf16: MissingRuntimeError # UTF-16 data URIs work in dartk
 dart/issue32950_test: SkipByDesign # uses spawnUri.
 dart/redirection_type_shuffling_test: SkipByDesign # Includes dart:mirrors.
 dart/spawn_shutdown_test: SkipSlow
@@ -268,18 +261,6 @@
 [ $compiler == dart2analyzer || $compiler == dart2js ]
 dart/data_uri*test: Skip # Data uri's not supported by dart2js or the analyzer.
 
-# Tests that use functionality not supported in Dart 2.
-[ ($compiler == dartk || $compiler == dartkb) || $compiler == dartkp ]
-cc/DartAPI_IsolateSetCheckedMode: SkipByDesign # Checked mode is not relevant for dart 2?
-cc/CompileFunction: SkipByDesign
-cc/InvokeDynamic_CompileError: SkipByDesign
-cc/InvokeStatic_CompileError: SkipByDesign
-cc/DartEntry: SkipByDesign
-cc/FindCodeObject: SkipByDesign
-cc/DartDynamicResolve: SkipByDesign
-cc/DartStaticResolve: SkipByDesign
-cc/CompileScript: SkipByDesign
-
 [ $compiler == precompiler || $mode == product ]
 cc/CoreSnapshotSize: SkipByDesign # Imports dart:mirrors
 cc/CreateMirrorSystem: SkipByDesign # Imports dart:mirrors
diff --git a/runtime/third_party/double-conversion/src/BUILD.gn b/runtime/third_party/double-conversion/src/BUILD.gn
index be055c4..e790868 100644
--- a/runtime/third_party/double-conversion/src/BUILD.gn
+++ b/runtime/third_party/double-conversion/src/BUILD.gn
@@ -2,15 +2,12 @@
 # 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.
 
-static_library("libdouble_conversion") {
+source_set("libdouble_conversion") {
   configs += [
     "../../..:dart_arch_config",
     "../../..:dart_config",
     "../../..:dart_os_config",
   ]
-  if (is_fuchsia) {
-    configs -= [ "//build/config:symbol_visibility_hidden" ]
-  }
   sources = [
     "bignum-dtoa.cc",
     "bignum-dtoa.h",
diff --git a/runtime/tools/dartfuzz/README.md b/runtime/tools/dartfuzz/README.md
index 14398d7..49c89c6 100644
--- a/runtime/tools/dartfuzz/README.md
+++ b/runtime/tools/dartfuzz/README.md
@@ -87,14 +87,22 @@
 Over the years, fuzz testing has gained popularity as a testing technique for
 discovering such lingering bugs, including bugs that can bring down a system
 in an unexpected way. Fuzzing refers to feeding a large amount of random data
-as input to a system in an attempt to find bugs or make it crash. Generation-
-based fuzz testing constructs random, but properly formatted input data.
-Mutation-based fuzz testing applies small random changes to existing inputs
-in order to detect shortcomings in a system. Profile-guided or coverage-guided
-fuzz testing adds a direction to the way these random changes are applied.
-Multi-layered approaches generate random inputs that are subsequently mutated
-at various stages of execution.
+as input to a system in an attempt to find bugs or make it crash.
+Generation-based fuzz testing constructs random, but properly formatted input
+data. Mutation-based fuzz testing applies small random changes to existing
+inputs in order to detect shortcomings in a system. Profile-guided or
+coverage-guided fuzz testing adds a direction to the way these random changes
+are applied. Multi-layered approaches generate random inputs that are
+subsequently mutated at various stages of execution.
 
 The randomness of fuzz testing implies that the size and scope of testing is
 no longer bounded. Every new run can potentially discover bugs and crashes
 that were hereto undetected.
+
+Links
+=====
+
+* [Dart bugs found with fuzzing](https://github.com/dart-lang/sdk/issues?utf8=%E2%9C%93&q=label%3Adartfuzz+)
+* [DartFuzz](https://github.com/dart-lang/sdk/tree/master/runtime/tools/dartfuzz)
+* [DartLibFuzzer](https://github.com/dart-lang/sdk/tree/master/runtime/vm/libfuzzer)
+* [LibFuzzer](https://llvm.org/docs/LibFuzzer.html)
diff --git a/runtime/tools/dartfuzz/dartfuzz.dart b/runtime/tools/dartfuzz/dartfuzz.dart
index 879e669..01dc871 100644
--- a/runtime/tools/dartfuzz/dartfuzz.dart
+++ b/runtime/tools/dartfuzz/dartfuzz.dart
@@ -13,10 +13,11 @@
 // Version of DartFuzz. Increase this each time changes are made
 // to preserve the property that a given version of DartFuzz yields
 // the same fuzzed program for a deterministic random seed.
-const String version = '1.9';
+const String version = '1.13';
 
-// Restriction on statement and expression depths.
-const int stmtDepth = 2;
+// Restriction on statements and expressions.
+const int stmtLength = 2;
+const int stmtDepth = 1;
 const int exprDepth = 2;
 
 // Naming conventions.
@@ -130,7 +131,7 @@
     indent += 2;
     emitLn('new X${classFields.length - 1}().run();');
     indent -= 2;
-    emitLn('} catch (e) {');
+    emitLn('} catch (exception, stackTrace) {');
     indent += 2;
     emitLn("print('throws');");
     indent -= 2;
@@ -410,7 +411,7 @@
     indent += 2;
     emitStatements(depth + 1);
     indent -= 2;
-    emitLn('} catch (e) {');
+    emitLn('} catch (exception, stackTrace) {');
     indent += 2;
     emitStatements(depth + 1);
     indent -= 2;
@@ -471,7 +472,7 @@
 
   // Emit statements. Returns true if code may fall-through.
   bool emitStatements(int depth) {
-    int s = 1 + rand.nextInt(4);
+    int s = 1 + rand.nextInt(stmtLength);
     for (int i = 0; i < s; i++) {
       if (!emitStatement(depth)) {
         return false; // rest would be dead code
diff --git a/runtime/tools/dartfuzz/dartfuzz_api_table.dart b/runtime/tools/dartfuzz/dartfuzz_api_table.dart
index 787e324..59d99d3 100644
--- a/runtime/tools/dartfuzz/dartfuzz_api_table.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_api_table.dart
@@ -57,7 +57,6 @@
     DartLib('JsonUtf8Encoder.DEFAULT_BUFFER_SIZE', 'Vv'),
     DartLib('unicodeReplacementCharacterRune', 'Vv'),
     DartLib('unicodeBomCharacterRune', 'Vv'),
-    DartLib('hashCode', 'Bv'),
     DartLib('DateTime.monday', 'Vv'),
     DartLib('DateTime.tuesday', 'Vv'),
     DartLib('DateTime.wednesday', 'Vv'),
@@ -126,11 +125,9 @@
     DartLib('ceil', 'DV'),
     DartLib('truncate', 'DV'),
     DartLib('toInt', 'DV'),
-    DartLib('hashCode', 'Dv'),
     DartLib('codeUnitAt', 'SI'),
     DartLib('compareTo', 'SS'),
     DartLib('length', 'Sv'),
-    DartLib('hashCode', 'Sv'),
     DartLib('OSError.noErrorCode', 'Vv'),
     DartLib('ZLibOption.minWindowBits', 'Vv'),
     DartLib('ZLibOption.MIN_WINDOW_BITS', 'Vv'),
@@ -790,7 +787,7 @@
     DartLib('FileSystemEntity.parentOf', 'VS'),
   ];
   static const listLibs = [
-    DartLib('List.filled', 'VII'),
+    DartLib('List.filled', 'ViI'),
     DartLib('sublist', 'LII'),
     DartLib('codeUnits', 'Sv'),
     DartLib('Uri.parseIPv4Address', 'VS'),
diff --git a/runtime/tools/dartfuzz/gen_api_table.dart b/runtime/tools/dartfuzz/gen_api_table.dart
index 05a5000..8b9504c 100755
--- a/runtime/tools/dartfuzz/gen_api_table.dart
+++ b/runtime/tools/dartfuzz/gen_api_table.dart
@@ -252,17 +252,21 @@
   if (ret.contains('?') || proto.contains('?')) {
     return;
   }
-  // Restrict parameters for a few hardcoded cases,
-  // for example, to avoid excessive runtime or memory
-  // allocation in the generated fuzzing program or to
-  // avoid false divergences.
-  if (name == 'padLeft' || name == 'padRight') {
-    proto = proto.replaceAll('I', 'i');
-  } else if (name == 'pid' ||
+  // Avoid some obvious false divergences.
+  if (name == 'pid' ||
+      name == 'hashCode' ||
       name == 'Platform.executable' ||
       name == 'Platform.resolvedExecutable') {
     return;
   }
+  // Restrict parameters for a few hardcoded cases,
+  // for example, to avoid excessive runtime or memory
+  // allocation in the generated fuzzing program.
+  if (name == 'padLeft' || name == 'padRight') {
+    proto = proto.replaceAll('I', 'i');
+  } else if (name == 'List.filled') {
+    proto = proto.replaceFirst('I', 'i');
+  }
   // Add to table.
   getTable(ret).add(DartLib(name, proto));
 }
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index 680ab84..6b9f82f 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -38,6 +38,10 @@
 import("heap/heap_sources.gni")
 import("vm_sources.gni")
 
+if (is_fuchsia) {
+  import("//build/fuchsia/sdk.gni")
+}
+
 config("libdart_vm_config") {
   if (is_fuchsia) {
     libs = [ "zircon" ]
@@ -60,16 +64,21 @@
 
 library_for_all_configs("libdart_vm") {
   target_type = "source_set"
+  extra_deps = [ "//third_party/icu" ]
   if (is_fuchsia) {
-    extra_deps = [
-      # TODO(US-399): Remove time_service specific code when it is no longer
-      # necessary.
-      "//sdk/lib/sys/cpp",
-      "//sdk/fidl/fuchsia.timezone",
+    if (using_fuchsia_sdk) {
+      extra_deps += [ "$fuchsia_sdk_root/pkg/lib/sys/cpp" ]
+    } else {
+      extra_deps += [
+        # TODO(US-399): Remove time_service specific code when it is no longer
+        # necessary.
+        "//sdk/lib/sys/cpp",
+        "//sdk/fidl/fuchsia.timezone",
 
-      "//zircon/public/lib/fbl",
-      "//zircon/public/lib/trace-engine",
-    ]
+        "//zircon/public/lib/fbl",
+        "//zircon/public/lib/trace-engine",
+      ]
+    }
   }
   public_configs = [ ":libdart_vm_config" ]
   set_sources_assignment_filter([
@@ -84,19 +93,20 @@
 library_for_all_configs("libdart_lib") {
   target_type = "source_set"
   if (is_fuchsia) {
-    extra_deps = [
-      "//zircon/public/lib/fbl",
-      "//zircon/public/lib/trace-engine",
-    ]
+    if (!using_fuchsia_sdk) {
+      extra_deps = [
+        "//zircon/public/lib/fbl",
+        "//zircon/public/lib/trace-engine",
+      ]
+    }
   }
   include_dirs = [ ".." ]
-  allsources =
-      async_runtime_sources + collection_runtime_sources +
-      convert_runtime_sources + core_runtime_sources +
-      developer_runtime_sources + internal_runtime_sources +
-      isolate_runtime_sources + math_runtime_sources + mirrors_runtime_sources +
-      profiler_runtime_sources + typed_data_runtime_sources +
-      vmservice_runtime_sources + ffi_runtime_sources
+  allsources = async_runtime_cc_files + collection_runtime_cc_files +
+               core_runtime_cc_files + developer_runtime_cc_files +
+               internal_runtime_cc_files + isolate_runtime_cc_files +
+               math_runtime_cc_files + mirrors_runtime_cc_files +
+               typed_data_runtime_cc_files + vmservice_runtime_cc_files +
+               ffi_runtime_cc_files
   sources = [ "bootstrap.cc" ] + rebase_path(allsources, ".", "../lib")
   snapshot_sources = []
   nosnapshot_sources = []
@@ -167,3 +177,15 @@
     ":vm_platform_stripped",
   ]
 }
+
+executable("offsets_extractor") {
+  configs += [
+    "..:dart_arch_config",
+    "..:dart_config",
+    ":libdart_vm_config",
+  ]
+  sources = [
+    "compiler/offsets_extractor.cc",
+  ]
+  include_dirs = [ ".." ]
+}
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 10ddc29..738478b 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -26,62 +26,6 @@
 Benchmark* Benchmark::tail_ = NULL;
 const char* Benchmark::executable_ = NULL;
 
-//
-// Measure compile of all dart2js(compiler) functions.
-//
-static char* ComputeDart2JSPath(const char* arg) {
-  char buffer[2048];
-  char* dart2js_path = strdup(File::GetCanonicalPath(NULL, arg));
-  const char* compiler_path = "%s%spkg%scompiler%slib%scompiler.dart";
-  const char* path_separator = File::PathSeparator();
-  ASSERT(path_separator != NULL && strlen(path_separator) == 1);
-  char* ptr = strrchr(dart2js_path, *path_separator);
-  while (ptr != NULL) {
-    *ptr = '\0';
-    Utils::SNPrint(buffer, 2048, compiler_path, dart2js_path, path_separator,
-                   path_separator, path_separator, path_separator,
-                   path_separator);
-    if (File::Exists(NULL, buffer)) {
-      break;
-    }
-    ptr = strrchr(dart2js_path, *path_separator);
-  }
-  if (ptr == NULL) {
-    free(dart2js_path);
-    dart2js_path = NULL;
-  }
-  return dart2js_path;
-}
-
-static void func(Dart_NativeArguments args) {}
-
-static Dart_NativeFunction NativeResolver(Dart_Handle name,
-                                          int arg_count,
-                                          bool* auto_setup_scope) {
-  ASSERT(auto_setup_scope != NULL);
-  *auto_setup_scope = false;
-  return &func;
-}
-
-static void SetupDart2JSPackagePath() {
-  bool worked = bin::DartUtils::SetOriginalWorkingDirectory();
-  EXPECT(worked);
-
-  Dart_Handle result = bin::DartUtils::PrepareForScriptLoading(false, false);
-  EXPECT_VALID(result);
-
-  // Setup package root.
-  char buffer[2048];
-  char* executable_path =
-      strdup(File::GetCanonicalPath(NULL, Benchmark::Executable()));
-  const char* packages_path = "%s%s..%spackages";
-  const char* path_separator = File::PathSeparator();
-  Utils::SNPrint(buffer, 2048, packages_path, executable_path, path_separator,
-                 path_separator);
-  result = bin::DartUtils::SetupPackageRoot(buffer, NULL);
-  EXPECT_VALID(result);
-}
-
 void Benchmark::RunAll(const char* executable) {
   SetExecutable(executable);
   Benchmark* benchmark = first_;
@@ -114,6 +58,32 @@
   benchmark->set_score(elapsed_time);
 }
 
+// This file is created by the target //runtime/bin:dart_kernel_platform_cc
+// which is depended on by run_vm_tests.
+static char* ComputeKernelServicePath(const char* arg) {
+  char buffer[2048];
+  char* kernel_service_path = strdup(File::GetCanonicalPath(NULL, arg));
+  EXPECT(kernel_service_path != NULL);
+  const char* compiler_path = "%s%sgen%skernel_service.dill";
+  const char* path_separator = File::PathSeparator();
+  ASSERT(path_separator != NULL && strlen(path_separator) == 1);
+  char* ptr = strrchr(kernel_service_path, *path_separator);
+  while (ptr != NULL) {
+    *ptr = '\0';
+    Utils::SNPrint(buffer, ARRAY_SIZE(buffer), compiler_path,
+                   kernel_service_path, path_separator, path_separator);
+    if (File::Exists(NULL, buffer)) {
+      break;
+    }
+    ptr = strrchr(kernel_service_path, *path_separator);
+  }
+  free(kernel_service_path);
+  if (ptr == NULL) {
+    return NULL;
+  }
+  return strdup(buffer);
+}
+
 // This file is created by the target //runtime/bin:gen_kernel_bytecode_dill
 // which is depended on by run_vm_tests.
 static char* ComputeGenKernelKernelPath(const char* arg) {
@@ -158,8 +128,12 @@
   bool read_fully = file->ReadFully(kernel_buffer, kernel_buffer_size);
   EXPECT(read_fully);
 
-  bool enable_interpreter_orig = FLAG_enable_interpreter;
-  FLAG_enable_interpreter = true;
+  // Enable bytecode compiler in order to read bytecode.
+  // Enabling interpreter also does the trick, but it causes flaky crashes
+  // as unoptimized background compiler (which is required for interpreter)
+  // was not initialized when isolate was created.
+  const bool use_bytecode_compiler_orig = FLAG_use_bytecode_compiler;
+  FLAG_use_bytecode_compiler = true;
 
   Timer timer(true, name);
   if (benchmark_load) {
@@ -184,7 +158,7 @@
 
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
-  FLAG_enable_interpreter = enable_interpreter_orig;
+  FLAG_use_bytecode_compiler = use_bytecode_compiler_orig;
   free(dill_path);
   free(kernel_buffer);
   return elapsed_time;
@@ -376,33 +350,51 @@
   benchmark->set_score(elapsed_time);
 }
 
-BENCHMARK(Dart2JSCompileAll) {
+static void vmservice_resolver(Dart_NativeArguments args) {}
+
+static Dart_NativeFunction NativeResolver(Dart_Handle name,
+                                          int arg_count,
+                                          bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
+  return &vmservice_resolver;
+}
+
+//
+// Measure compile of all kernel Service(CFE) functions.
+//
+BENCHMARK(KernelServiceCompileAll) {
   bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
   bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
   bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
-  SetupDart2JSPackagePath();
-  char* dart_root = ComputeDart2JSPath(Benchmark::Executable());
-  char* script = NULL;
-  if (dart_root != NULL) {
-    HANDLESCOPE(thread);
-    script = OS::SCreate(NULL, "import '%s/pkg/compiler/lib/compiler.dart';",
-                         dart_root);
-    Dart_Handle lib = TestCase::LoadTestScript(
-        script, reinterpret_cast<Dart_NativeEntryResolver>(NativeResolver));
-    EXPECT_VALID(lib);
-  } else {
-    Dart_Handle lib = TestCase::LoadTestScript(
-        "import 'pkg/compiler/lib/compiler.dart';",
-        reinterpret_cast<Dart_NativeEntryResolver>(NativeResolver));
-    EXPECT_VALID(lib);
-  }
-  Timer timer(true, "Compile all of dart2js benchmark");
+  char* dill_path = ComputeKernelServicePath(Benchmark::Executable());
+  File* file = File::Open(NULL, dill_path, File::kRead);
+  EXPECT(file != NULL);
+  bin::RefCntReleaseScope<File> rs(file);
+  intptr_t kernel_buffer_size = file->Length();
+  uint8_t* kernel_buffer =
+      reinterpret_cast<uint8_t*>(malloc(kernel_buffer_size));
+  EXPECT(kernel_buffer != NULL);
+  bool read_fully = file->ReadFully(kernel_buffer, kernel_buffer_size);
+  EXPECT(read_fully);
+  Dart_Handle result =
+      Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
+  EXPECT_VALID(result);
+  Dart_Handle service_lib = Dart_LookupLibrary(NewString("dart:vmservice_io"));
+  ASSERT(!Dart_IsError(service_lib));
+  Dart_SetNativeResolver(
+      service_lib, reinterpret_cast<Dart_NativeEntryResolver>(NativeResolver),
+      NULL);
+  result = Dart_FinalizeLoading(false);
+  EXPECT_VALID(result);
+
+  Timer timer(true, "Compile all of kernel service benchmark");
   timer.Start();
 #if !defined(PRODUCT)
   const bool old_flag = FLAG_background_compilation;
   FLAG_background_compilation = false;
 #endif
-  Dart_Handle result = Dart_CompileAll();
+  result = Dart_CompileAll();
 #if !defined(PRODUCT)
   FLAG_background_compilation = old_flag;
 #endif
@@ -410,8 +402,8 @@
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
   benchmark->set_score(elapsed_time);
-  free(dart_root);
-  free(script);
+  free(dill_path);
+  free(kernel_buffer);
 }
 
 //
@@ -652,13 +644,12 @@
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
     MessageWriter writer(true);
-    Message* message = writer.WriteMessage(null_object, ILLEGAL_PORT,
-                                           Message::kNormalPriority);
+    std::unique_ptr<Message> message = writer.WriteMessage(
+        null_object, ILLEGAL_PORT, Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message, thread);
+    MessageSnapshotReader reader(message.get(), thread);
     reader.ReadObject();
-    delete message;
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
@@ -676,13 +667,12 @@
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
     MessageWriter writer(true);
-    Message* message =
+    std::unique_ptr<Message> message =
         writer.WriteMessage(smi_object, ILLEGAL_PORT, Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message, thread);
+    MessageSnapshotReader reader(message.get(), thread);
     reader.ReadObject();
-    delete message;
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
@@ -702,13 +692,12 @@
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
     MessageWriter writer(true);
-    Message* message = writer.WriteMessage(array_object, ILLEGAL_PORT,
-                                           Message::kNormalPriority);
+    std::unique_ptr<Message> message = writer.WriteMessage(
+        array_object, ILLEGAL_PORT, Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message, thread);
+    MessageSnapshotReader reader(message.get(), thread);
     reader.ReadObject();
-    delete message;
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
@@ -737,13 +726,12 @@
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
     MessageWriter writer(true);
-    Message* message =
+    std::unique_ptr<Message> message =
         writer.WriteMessage(map, ILLEGAL_PORT, Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message, thread);
+    MessageSnapshotReader reader(message.get(), thread);
     reader.ReadObject();
-    delete message;
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index da1dc36..98c6129 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -98,10 +98,12 @@
   V(Double_toStringAsExponential, 2)                                           \
   V(Double_toStringAsPrecision, 2)                                             \
   V(Double_flipSignBit, 1)                                                     \
-  V(RegExp_factory, 4)                                                         \
+  V(RegExp_factory, 6)                                                         \
   V(RegExp_getPattern, 1)                                                      \
   V(RegExp_getIsMultiLine, 1)                                                  \
   V(RegExp_getIsCaseSensitive, 1)                                              \
+  V(RegExp_getIsUnicode, 1)                                                    \
+  V(RegExp_getIsDotAll, 1)                                                     \
   V(RegExp_getGroupCount, 1)                                                   \
   V(RegExp_getGroupNameMap, 1)                                                 \
   V(RegExp_ExecuteMatch, 3)                                                    \
@@ -385,7 +387,9 @@
   V(Ffi_fromFunction, 1)                                                       \
   V(Ffi_dl_open, 1)                                                            \
   V(Ffi_dl_lookup, 2)                                                          \
-  V(Ffi_dl_getHandle, 1)
+  V(Ffi_dl_getHandle, 1)                                                       \
+  V(TransferableTypedData_factory, 2)                                          \
+  V(TransferableTypedData_materialize, 1)
 
 // List of bootstrap native entry points used in the dart:mirror library.
 #define MIRRORS_BOOTSTRAP_NATIVE_LIST(V)                                       \
diff --git a/runtime/vm/catch_entry_moves_test.cc b/runtime/vm/catch_entry_moves_test.cc
index faa41f6..7ca32ef 100644
--- a/runtime/vm/catch_entry_moves_test.cc
+++ b/runtime/vm/catch_entry_moves_test.cc
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include <functional>
+#include <memory>
 #include <utility>
 
 #include "platform/assert.h"
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index ba2dc60..5b3fe6d 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -86,7 +86,7 @@
   super_type = cls.super_type();
   if (!super_type.IsNull()) {
     if (super_type.HasTypeClass()) {
-      cls ^= super_type.type_class();
+      cls = super_type.type_class();
       if (cls.is_finalized()) {
         AddSuperType(super_type, finalized_super_classes);
       }
@@ -128,7 +128,7 @@
       if (!array->IsNull()) {
         for (intptr_t i = 0; i < array->Length(); ++i) {
           *type ^= array->At(i);
-          *interface_class ^= class_table_->At(type->type_class_id());
+          *interface_class = class_table_->At(type->type_class_id());
           FindAllInterfaces(*interface_class);
         }
       }
@@ -156,7 +156,7 @@
   for (intptr_t i = 0; i < interfaces.Length(); ++i) {
     type ^= interfaces.At(i);
     if (!type.HasTypeClass()) continue;
-    ifc ^= type.type_class();
+    ifc = type.type_class();
     for (intptr_t j = 0; j < cids->length(); ++j) {
       if ((*cids)[j] == ifc.id()) {
         // Already added.
@@ -191,15 +191,15 @@
     class_array = object_store->pending_classes();
     ASSERT(!class_array.IsNull());
     Class& cls = Class::Handle();
-    // Mark all classes as cycle-free (should be checked by front-end).
-    // TODO(alexmarkov): Cleanup is_cycle_free bit on classes.
+
+#if defined(DEBUG)
     for (intptr_t i = 0; i < class_array.Length(); i++) {
       cls ^= class_array.At(i);
-      if (!cls.is_cycle_free()) {
-        cls.set_is_cycle_free();
-      }
+      ASSERT(cls.is_declaration_loaded());
     }
-    // Finalize all classes.
+#endif
+
+    // Finalize types in all classes.
     for (intptr_t i = 0; i < class_array.Length(); i++) {
       cls ^= class_array.At(i);
       FinalizeTypesInClass(cls);
@@ -557,10 +557,8 @@
     const Class& super_class = Class::Handle(super_type.type_class());
     const intptr_t num_super_type_params = super_class.NumTypeParameters();
     const intptr_t num_super_type_args = super_class.NumTypeArguments();
-    ASSERT(num_super_type_args ==
-           (cls.NumTypeArguments() - cls.NumOwnTypeArguments()));
     if (!super_type.IsFinalized() && !super_type.IsBeingFinalized()) {
-      super_type ^= FinalizeType(cls, super_type, kFinalize, pending_types);
+      super_type = FinalizeType(cls, super_type, kFinalize, pending_types);
       cls.set_super_type(super_type);
     }
     TypeArguments& super_type_args =
@@ -585,7 +583,7 @@
             super_type_args.SetTypeAt(i, super_type_arg);
           } else {
             if (!super_type_arg.IsFinalized()) {
-              super_type_arg ^=
+              super_type_arg =
                   FinalizeType(cls, super_type_arg, kFinalize, pending_types);
               super_type_args.SetTypeAt(i, super_type_arg);
               // Note that super_type_arg may still not be finalized here, in
@@ -1005,6 +1003,7 @@
 void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
   Thread* thread = Thread::Current();
   HANDLESCOPE(thread);
+  ASSERT(cls.is_declaration_loaded());
   if (cls.is_type_finalized()) {
     return;
   }
@@ -1242,75 +1241,31 @@
                                       ->object_store()
                                       ->pending_unevaluated_const_fields());
 
-  if (enum_cls.kernel_offset() > 0) {
-    Error& error = Error::Handle(zone);
-    for (intptr_t i = 0; i < fields.Length(); i++) {
-      field = Field::RawCast(fields.At(i));
-      if (!field.is_static() || !field.is_const() ||
-          (sentinel.raw() == field.raw())) {
-        continue;
-      }
-      // The eager evaluation of the enum values is required for hot-reload (see
-      // commit e3ecc87). However, while busy loading the constant table, we
-      // need to postpone this evaluation until table is done.
-      if (!FLAG_precompiled_mode) {
-        if (field.IsUninitialized()) {
-          if (pending_unevaluated_const_fields.IsNull()) {
-            // Evaluate right away.
-            error = field.Initialize();
-            if (!error.IsNull()) {
-              ReportError(error);
-            }
-          } else {
-            // Postpone evaluation until we have a constant table.
-            pending_unevaluated_const_fields.Add(field);
+  ASSERT(enum_cls.kernel_offset() > 0);
+  Error& error = Error::Handle(zone);
+  for (intptr_t i = 0; i < fields.Length(); i++) {
+    field = Field::RawCast(fields.At(i));
+    if (!field.is_static() || !field.is_const() ||
+        (sentinel.raw() == field.raw())) {
+      continue;
+    }
+    // The eager evaluation of the enum values is required for hot-reload (see
+    // commit e3ecc87). However, while busy loading the constant table, we
+    // need to postpone this evaluation until table is done.
+    if (!FLAG_precompiled_mode) {
+      if (field.IsUninitialized()) {
+        if (pending_unevaluated_const_fields.IsNull()) {
+          // Evaluate right away.
+          error = field.Initialize();
+          if (!error.IsNull()) {
+            ReportError(error);
           }
+        } else {
+          // Postpone evaluation until we have a constant table.
+          pending_unevaluated_const_fields.Add(field);
         }
       }
     }
-  } else {
-    const String& name_prefix =
-        String::Handle(String::Concat(enum_name, Symbols::Dot()));
-    Instance& ordinal_value = Instance::Handle(zone);
-    Array& values_list = Array::Handle(zone);
-    const Field& values_field =
-        Field::Handle(zone, enum_cls.LookupStaticField(Symbols::Values()));
-    ASSERT(!values_field.IsNull());
-    ASSERT(Instance::Handle(zone, values_field.StaticValue()).IsArray());
-    values_list = Array::RawCast(values_field.StaticValue());
-    const Array& fields = Array::Handle(zone, enum_cls.fields());
-    for (intptr_t i = 0; i < fields.Length(); i++) {
-      field = Field::RawCast(fields.At(i));
-      if (!field.is_static()) continue;
-      ordinal_value = field.StaticValue();
-      // The static fields that need to be initialized with enum instances
-      // 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);
-      enum_value = enum_value.CheckAndCanonicalize(thread, &error_msg);
-      ASSERT(!enum_value.IsNull());
-      ASSERT(enum_value.IsCanonical());
-      field.SetStaticValue(enum_value, true);
-      field.RecordStore(enum_value);
-      intptr_t ord = Smi::Cast(ordinal_value).Value();
-      ASSERT(ord < values_list.Length());
-      values_list.SetAt(ord, enum_value);
-    }
-    values_list.MakeImmutable();
-    values_list ^= values_list.CheckAndCanonicalize(thread, &error_msg);
-    ASSERT(!values_list.IsNull());
   }
 }
 
@@ -1427,7 +1382,7 @@
   cls = class_table.At(kFfiPointerCid);
   error = cls.EnsureIsFinalized(thread);
   ASSERT(error.IsNull());
-  ASSERT(cls.NumOwnTypeArguments() == 1);
+  ASSERT(cls.NumTypeParameters() == 1);
   type_param ^= TypeParameter::RawCast(
       TypeArguments::Handle(cls.type_parameters()).TypeAt(0));
   ASSERT(Pointer::kNativeTypeArgPos == type_param.index());
diff --git a/runtime/vm/class_finalizer_test.cc b/runtime/vm/class_finalizer_test.cc
index a1440d2..7768c44 100644
--- a/runtime/vm/class_finalizer_test.cc
+++ b/runtime/vm/class_finalizer_test.cc
@@ -16,6 +16,7 @@
   const Class& cls = Class::Handle(Class::New(
       Library::Handle(), class_name, script, TokenPosition::kNoSource));
   cls.set_interfaces(Object::empty_array());
+  cls.set_is_declaration_loaded();
   cls.SetFunctions(Object::empty_array());
   cls.SetFields(Object::empty_array());
   return cls.raw();
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 9acabba..f95d77f 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -78,7 +78,8 @@
   V(WeakProperty)                                                              \
   V(MirrorReference)                                                           \
   V(LinkedHashMap)                                                             \
-  V(UserTag)
+  V(UserTag)                                                                   \
+  V(TransferableTypedData)
 
 #define CLASS_LIST_ARRAYS(V)                                                   \
   V(Array)                                                                     \
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 70ad37c..3d4ab6c 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -464,19 +464,14 @@
   }
 }
 
-intptr_t ClassTable::TableOffsetFor(intptr_t cid) {
-  return OFFSET_OF(ClassTable, class_heap_stats_table_);
-}
-
 intptr_t ClassTable::ClassOffsetFor(intptr_t cid) {
   return cid * sizeof(ClassHeapStats);  // NOLINT
 }
 
-intptr_t ClassTable::CounterOffsetFor(intptr_t cid, bool is_new_space) {
+intptr_t ClassTable::NewSpaceCounterOffsetFor(intptr_t cid) {
   const intptr_t class_offset = ClassOffsetFor(cid);
   const intptr_t count_field_offset =
-      is_new_space ? ClassHeapStats::allocated_since_gc_new_space_offset()
-                   : ClassHeapStats::allocated_since_gc_old_space_offset();
+      ClassHeapStats::allocated_since_gc_new_space_offset();
   return class_offset + count_field_offset;
 }
 
@@ -484,11 +479,10 @@
   return ClassOffsetFor(cid) + ClassHeapStats::state_offset();
 }
 
-intptr_t ClassTable::SizeOffsetFor(intptr_t cid, bool is_new_space) {
+intptr_t ClassTable::NewSpaceSizeOffsetFor(intptr_t cid) {
   const uword class_offset = ClassOffsetFor(cid);
   const uword size_field_offset =
-      is_new_space ? ClassHeapStats::allocated_size_since_gc_new_space_offset()
-                   : ClassHeapStats::allocated_size_since_gc_old_space_offset();
+      ClassHeapStats::allocated_size_since_gc_new_space_offset();
   return class_offset + size_field_offset;
 }
 
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index fd2bdc1..c851ef9 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -36,16 +36,9 @@
   intptr_t size_;
 
   friend class ClassTable;
+  friend class IsolateReloadContext;  // For VisitObjectPointers.
 };
 
-#if defined(ARCH_IS_32_BIT)
-const int kSizeOfClassPairLog2 = 3;
-#else
-const int kSizeOfClassPairLog2 = 4;
-#endif
-
-COMPILE_ASSERT((1 << kSizeOfClassPairLog2) == sizeof(ClassAndSize));
-
 #ifndef PRODUCT
 template <typename T>
 class AllocStats {
@@ -260,6 +253,24 @@
   static intptr_t ClassOffsetFor(intptr_t cid);
 
 #ifndef PRODUCT
+  // Describes layout of heap stats for code generation. See offset_extractor.cc
+  struct ArrayLayout {
+    static intptr_t elements_start_offset() { return 0; }
+
+    static constexpr intptr_t kElementSize = sizeof(ClassHeapStats);
+  };
+#endif
+
+#if defined(ARCH_IS_32_BIT)
+  static constexpr int kSizeOfClassPairLog2 = 3;
+#else
+  static constexpr int kSizeOfClassPairLog2 = 4;
+#endif
+  static_assert(
+      (1 << kSizeOfClassPairLog2) == sizeof(ClassAndSize),
+      "Mismatch between sizeof(ClassAndSize) and kSizeOfClassPairLog2");
+
+#ifndef PRODUCT
   // Called whenever a class is allocated in the runtime.
   void UpdateAllocatedNew(intptr_t cid, intptr_t size) {
     ClassHeapStats* stats = PreliminaryStatsAt(cid);
@@ -285,16 +296,18 @@
   void UpdatePromoted();
 
   // Used by the generated code.
-  static intptr_t TableOffsetFor(intptr_t cid);
+  static intptr_t class_heap_stats_table_offset() {
+    return OFFSET_OF(ClassTable, class_heap_stats_table_);
+  }
 
   // Used by the generated code.
-  static intptr_t CounterOffsetFor(intptr_t cid, bool is_new_space);
+  static intptr_t NewSpaceCounterOffsetFor(intptr_t cid);
 
   // Used by the generated code.
   static intptr_t StateOffsetFor(intptr_t cid);
 
   // Used by the generated code.
-  static intptr_t SizeOffsetFor(intptr_t cid, bool is_new_space);
+  static intptr_t NewSpaceSizeOffsetFor(intptr_t cid);
 
   ClassHeapStats* StatsWithUpdatedSize(intptr_t cid);
 
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 5f0accb..a71b9cb 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -7,6 +7,7 @@
 #include "platform/assert.h"
 #include "vm/bootstrap.h"
 #include "vm/compiler/backend/code_statistics.h"
+#include "vm/compiler/frontend/bytecode_reader.h"
 #include "vm/compiler/relocation.h"
 #include "vm/dart.h"
 #include "vm/heap/heap.h"
@@ -181,11 +182,10 @@
     s->Write<int32_t>(cls->ptr()->instance_size_in_words_);
     s->Write<int32_t>(cls->ptr()->next_field_offset_in_words_);
     s->Write<int32_t>(cls->ptr()->type_arguments_field_offset_in_words_);
-    s->Write<uint16_t>(cls->ptr()->num_type_arguments_);
-    s->Write<uint16_t>(cls->ptr()->has_pragma_and_num_own_type_arguments_);
+    s->Write<int16_t>(cls->ptr()->num_type_arguments_);
     s->Write<uint16_t>(cls->ptr()->num_native_fields_);
     s->WriteTokenPosition(cls->ptr()->token_pos_);
-    s->Write<uint16_t>(cls->ptr()->state_bits_);
+    s->Write<uint32_t>(cls->ptr()->state_bits_);
   }
 
  private:
@@ -243,11 +243,10 @@
         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()->has_pragma_and_num_own_type_arguments_ = d->Read<uint16_t>();
+      cls->ptr()->num_type_arguments_ = d->Read<int16_t>();
       cls->ptr()->num_native_fields_ = d->Read<uint16_t>();
       cls->ptr()->token_pos_ = d->ReadTokenPosition();
-      cls->ptr()->state_bits_ = d->Read<uint16_t>();
+      cls->ptr()->state_bits_ = d->Read<uint32_t>();
     }
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -270,11 +269,10 @@
       cls->ptr()->instance_size_in_words_ = d->Read<int32_t>();
       cls->ptr()->next_field_offset_in_words_ = d->Read<int32_t>();
       cls->ptr()->type_arguments_field_offset_in_words_ = d->Read<int32_t>();
-      cls->ptr()->num_type_arguments_ = d->Read<uint16_t>();
-      cls->ptr()->has_pragma_and_num_own_type_arguments_ = d->Read<uint16_t>();
+      cls->ptr()->num_type_arguments_ = d->Read<int16_t>();
       cls->ptr()->num_native_fields_ = d->Read<uint16_t>();
       cls->ptr()->token_pos_ = d->ReadTokenPosition();
-      cls->ptr()->state_bits_ = d->Read<uint16_t>();
+      cls->ptr()->state_bits_ = d->Read<uint32_t>();
 
       table->AllocateIndex(class_id);
       table->SetAt(class_id, cls);
@@ -601,7 +599,7 @@
       Code& code = Code::Handle(zone);
       for (intptr_t i = start_index_; i < stop_index_; i++) {
         func ^= refs.At(i);
-        code ^= func.CurrentCode();
+        code = func.CurrentCode();
         if (func.HasCode() && !code.IsDisabled()) {
           func.SetInstructions(code);  // Set entrypoint.
           func.SetWasCompiled(true);
@@ -1291,6 +1289,14 @@
       info.set_libraries_cache(array);
       array = HashTables::New<UnorderedHashMap<SmiTraits>>(16, Heap::kOld);
       info.set_classes_cache(array);
+
+      static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 7,
+                    "Cleanup support for old bytecode format versions");
+      array = info.bytecode_component();
+      if (!array.IsNull()) {
+        kernel::BytecodeReader::UseBytecodeVersion(
+            kernel::BytecodeComponentData(array).GetVersion());
+      }
     }
   }
 };
@@ -1543,6 +1549,8 @@
       WriteFromTo(bytecode);
       s->Write<int32_t>(bytecode->ptr()->instructions_binary_offset_);
       s->Write<int32_t>(bytecode->ptr()->source_positions_binary_offset_);
+      NOT_IN_PRODUCT(
+          s->Write<int32_t>(bytecode->ptr()->local_variables_binary_offset_));
     }
   }
 
@@ -1577,6 +1585,8 @@
       ReadFromTo(bytecode);
       bytecode->ptr()->instructions_binary_offset_ = d->Read<int32_t>();
       bytecode->ptr()->source_positions_binary_offset_ = d->Read<int32_t>();
+      NOT_IN_PRODUCT(bytecode->ptr()->local_variables_binary_offset_ =
+                         d->Read<int32_t>());
     }
   }
 
@@ -1805,7 +1815,8 @@
       s->TraceDataOffset(offset);
       ASSERT(Utils::IsAligned(offset, kObjectAlignment));
       ASSERT(offset > running_offset);
-      s->WriteUnsigned((offset - running_offset) >> kObjectAlignmentLog2);
+      s->WriteUnsigned((offset - running_offset) >>
+                       compiler::target::ObjectAlignment::kObjectAlignmentLog2);
       running_offset = offset;
       s->TraceEndWritingObject();
     }
@@ -3630,7 +3641,8 @@
       RawRegExp* regexp = objects_[i];
       AutoTraceObject(regexp);
       WriteFromTo(regexp);
-      s->Write<int32_t>(regexp->ptr()->num_registers_);
+      s->Write<int32_t>(regexp->ptr()->num_one_byte_registers_);
+      s->Write<int32_t>(regexp->ptr()->num_two_byte_registers_);
       s->Write<int8_t>(regexp->ptr()->type_flags_);
     }
   }
@@ -3661,7 +3673,8 @@
       Deserializer::InitializeHeader(regexp, kRegExpCid,
                                      RegExp::InstanceSize());
       ReadFromTo(regexp);
-      regexp->ptr()->num_registers_ = d->Read<int32_t>();
+      regexp->ptr()->num_one_byte_registers_ = d->Read<int32_t>();
+      regexp->ptr()->num_two_byte_registers_ = d->Read<int32_t>();
       regexp->ptr()->type_flags_ = d->Read<int8_t>();
     }
   }
@@ -4689,8 +4702,16 @@
                 "<implicit getter>");
   AddBaseObject(Object::implicit_setter_bytecode().raw(), "Bytecode",
                 "<implicit setter>");
+  AddBaseObject(Object::implicit_static_getter_bytecode().raw(), "Bytecode",
+                "<implicit static getter>");
   AddBaseObject(Object::method_extractor_bytecode().raw(), "Bytecode",
                 "<method extractor>");
+  AddBaseObject(Object::invoke_closure_bytecode().raw(), "Bytecode",
+                "<invoke closure>");
+  AddBaseObject(Object::invoke_field_bytecode().raw(), "Bytecode",
+                "<invoke field>");
+  AddBaseObject(Object::nsm_dispatcher_bytecode().raw(), "Bytecode",
+                "<nsm dispatcher>");
 
   for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
     AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i],
@@ -5148,7 +5169,11 @@
   AddBaseObject(Object::empty_exception_handlers().raw());
   AddBaseObject(Object::implicit_getter_bytecode().raw());
   AddBaseObject(Object::implicit_setter_bytecode().raw());
+  AddBaseObject(Object::implicit_static_getter_bytecode().raw());
   AddBaseObject(Object::method_extractor_bytecode().raw());
+  AddBaseObject(Object::invoke_closure_bytecode().raw());
+  AddBaseObject(Object::invoke_field_bytecode().raw());
+  AddBaseObject(Object::nsm_dispatcher_bytecode().raw());
 
   for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
     AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i]);
diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
index 84d9882..7d1b764 100644
--- a/runtime/vm/code_descriptors.cc
+++ b/runtime/vm/code_descriptors.cc
@@ -19,7 +19,7 @@
 
   // When precompiling, we only use pc descriptors for exceptions.
   if (!FLAG_precompiled_mode || try_index != -1) {
-    intptr_t merged_kind_try =
+    int32_t merged_kind_try =
         RawPcDescriptors::MergedKindTry::Encode(kind, try_index);
 
     PcDescriptors::EncodeInteger(&encoded_data_, merged_kind_try);
diff --git a/runtime/vm/code_patcher_arm.cc b/runtime/vm/code_patcher_arm.cc
index 258b035..362b8b0 100644
--- a/runtime/vm/code_patcher_arm.cc
+++ b/runtime/vm/code_patcher_arm.cc
@@ -49,7 +49,7 @@
   ASSERT(code.ContainsInstructionAt(return_address));
   CallPattern static_call(return_address, code);
   ICData& ic_data = ICData::Handle();
-  ic_data ^= static_call.IcData();
+  ic_data = static_call.IcData();
   if (ic_data_result != NULL) {
     *ic_data_result = ic_data.raw();
   }
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index 48db21c..af8d622 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -365,11 +365,6 @@
     return Object::null();
   }
 
-  // Prevent premature code collection due to major GC during startup.
-  if (function.usage_counter() < Function::kGraceUsageCounter) {
-    function.set_usage_counter(Function::kGraceUsageCounter);
-  }
-
   error_ = Compiler::CompileFunction(thread_, function);
   if (error_.IsError()) {
     return error_.raw();
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 07d879f..b3c2ea3 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -431,7 +431,7 @@
     return nullptr;  // non-smi mask
   }
   const int64_t modulus = Utils::Abs(value);
-  if (!Utils::IsPowerOfTwo(modulus) || !Smi::IsValid(modulus - 1)) {
+  if (!Utils::IsPowerOfTwo(modulus) || !compiler::target::IsSmi(modulus - 1)) {
     return nullptr;
   }
 
@@ -1145,8 +1145,10 @@
     InsertBefore(call, invoke_call->PushArgumentAt(i), NULL,
                  FlowGraph::kEffect);
   }
-  // Remove original PushArguments from the graph.
+  // Replace original PushArguments in the graph (mainly env uses).
+  ASSERT(call->ArgumentCount() == invoke_call->ArgumentCount());
   for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
+    call->PushArgumentAt(i)->ReplaceUsesWith(invoke_call->PushArgumentAt(i));
     call->PushArgumentAt(i)->RemoveFromGraph();
   }
 
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 58750f8..9fa7585 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -4,6 +4,7 @@
 
 #include "vm/compiler/aot/precompiler.h"
 
+#include "platform/unicode.h"
 #include "vm/class_finalizer.h"
 #include "vm/code_patcher.h"
 #include "vm/compiler/aot/aot_call_specializer.h"
@@ -49,7 +50,6 @@
 #include "vm/timer.h"
 #include "vm/type_table.h"
 #include "vm/type_testing_stubs.h"
-#include "vm/unicode.h"
 #include "vm/version.h"
 
 namespace dart {
@@ -72,7 +72,6 @@
 DECLARE_FLAG(bool, trace_compiler);
 DECLARE_FLAG(bool, trace_optimizing_compiler);
 DECLARE_FLAG(bool, trace_bailout);
-DECLARE_FLAG(bool, verify_compiler);
 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size);
 DECLARE_FLAG(bool, trace_failed_optimization_attempts);
 DECLARE_FLAG(bool, trace_inlining_intervals);
@@ -495,7 +494,7 @@
         cids.Clear();
         if (CHA::ConcreteSubclasses(cls, &cids)) {
           for (intptr_t j = 0; j < cids.length(); ++j) {
-            subcls ^= I->class_table()->At(cids[j]);
+            subcls = I->class_table()->At(cids[j]);
             if (subcls.is_allocated()) {
               // Add dispatcher to cls.
               dispatcher = subcls.GetInvocationDispatcher(
@@ -1080,7 +1079,7 @@
             }
           }
         }
-        if (function.kind() == RawFunction::kImplicitStaticFinalGetter &&
+        if (function.kind() == RawFunction::kImplicitStaticGetter &&
             !implicit_static_getters.IsNull()) {
           for (intptr_t i = 0; i < implicit_static_getters.Length(); ++i) {
             field ^= implicit_static_getters.At(i);
@@ -1947,7 +1946,7 @@
             // stub.
             auto& fun = Function::Cast(target_);
             ASSERT(fun.HasCode());
-            target_code_ ^= fun.CurrentCode();
+            target_code_ = fun.CurrentCode();
             uword pc = pc_offset + code_.PayloadStart();
             CodePatcher::PatchStaticCallAt(pc, code_, target_code_);
           }
@@ -2173,32 +2172,9 @@
 }
 
 void Precompiler::FinalizeAllClasses() {
-  Library& lib = Library::Handle(Z);
-  Class& cls = Class::Handle(Z);
-
-  for (intptr_t i = 0; i < libraries_.Length(); i++) {
-    lib ^= libraries_.At(i);
-    if (!lib.Loaded()) {
-      String& uri = String::Handle(Z, lib.url());
-      String& msg = String::Handle(
-          Z,
-          String::NewFormatted("Library '%s' is not loaded. "
-                               "Did you forget to call Dart_FinalizeLoading?",
-                               uri.ToCString()));
-      Jump(Error::Handle(Z, ApiError::New(msg)));
-    }
-
-    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
-    while (it.HasNext()) {
-      cls = it.GetNextClass();
-      if (cls.IsDynamicClass()) {
-        continue;  // class 'dynamic' is in the read-only VM isolate.
-      }
-      error_ = cls.EnsureIsFinalized(T);
-      if (!error_.IsNull()) {
-        Jump(error_);
-      }
-    }
+  error_ = Library::FinalizeAllClasses();
+  if (!error_.IsNull()) {
+    Jump(error_);
   }
   I->set_all_classes_finalized(true);
 }
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index 2da017e..bb2cb37 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -430,7 +430,7 @@
   ASSERT(kSmiTagShift == 1);
   ASSERT(kSmiTag == 0);
   TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ CompareImmediate(R0, target::ToRawSmi(target::Smi::kBits));
+  __ CompareImmediate(R0, target::ToRawSmi(target::kSmiBits));
   __ b(normal_ir_body, HI);
 
   __ SmiUntag(R0);
@@ -1450,7 +1450,7 @@
   __ ldr(R0, FieldAddress(R1, target::Double::value_offset()));
   __ ldr(R1, FieldAddress(R1, target::Double::value_offset() + 4));
   __ eor(R0, R0, Operand(R1));
-  __ AndImmediate(R0, R0, kSmiMax);
+  __ AndImmediate(R0, R0, target::kSmiMax);
   __ SmiTag(R0);
   __ Ret();
 
@@ -1495,7 +1495,7 @@
   // Receiver.
   __ ldr(R0, Address(SP, 0 * target::kWordSize));
   // Field '_state'.
-  __ ldr(R1, FieldAddress(R0, LookupFieldOffsetInBytes(state_field)));
+  __ ldr(R1, FieldAddress(R0, target::Field::OffsetOf(state_field)));
   // Addresses of _state[0] and _state[1].
 
   const int64_t disp_0 =
@@ -1608,8 +1608,7 @@
 
   __ Bind(&use_declaration_type);
   __ LoadClassById(R2, R1);  // Overwrites R1.
-  __ ldrh(R3, FieldAddress(
-                  R2, target::Class::num_type_arguments_offset_in_bytes()));
+  __ ldrh(R3, FieldAddress(R2, target::Class::num_type_arguments_offset()));
   __ CompareImmediate(R3, 0);
   __ b(normal_ir_body, NE);
 
@@ -1644,8 +1643,7 @@
   // Check if there are no type arguments. In this case we can return true.
   // Otherwise fall through into the runtime to handle comparison.
   __ LoadClassById(R3, R1);
-  __ ldrh(R3, FieldAddress(
-                  R3, target::Class::num_type_arguments_offset_in_bytes()));
+  __ ldrh(R3, FieldAddress(R3, target::Class::num_type_arguments_offset()));
   __ CompareImmediate(R3, 0);
   __ b(normal_ir_body, NE);
 
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index 6c63421..1551dfc 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -430,7 +430,7 @@
   const Register result = R0;
 
   TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ CompareImmediate(right, target::ToRawSmi(target::Smi::kBits));
+  __ CompareImmediate(right, target::ToRawSmi(target::kSmiBits));
   __ b(normal_ir_body, CS);
 
   // Left is not a constant.
@@ -1520,7 +1520,7 @@
   __ Bind(&double_hash);
   __ fmovrd(R0, V0);
   __ eor(R0, R0, Operand(R0, LSR, 32));
-  __ AndImmediate(R0, R0, kSmiMax);
+  __ AndImmediate(R0, R0, target::kSmiMax);
   __ SmiTag(R0);
   __ ret();
 
@@ -1669,8 +1669,7 @@
 
   __ Bind(&use_declaration_type);
   __ LoadClassById(R2, R1);  // Overwrites R1.
-  __ ldr(R3,
-         FieldAddress(R2, target::Class::num_type_arguments_offset_in_bytes()),
+  __ ldr(R3, FieldAddress(R2, target::Class::num_type_arguments_offset()),
          kHalfword);
   __ CompareImmediate(R3, 0);
   __ b(normal_ir_body, NE);
@@ -1706,8 +1705,7 @@
   // Check if there are no type arguments. In this case we can return true.
   // Otherwise fall through into the runtime to handle comparison.
   __ LoadClassById(R3, R1);  // Overwrites R1.
-  __ ldr(R3,
-         FieldAddress(R3, target::Class::num_type_arguments_offset_in_bytes()),
+  __ ldr(R3, FieldAddress(R3, target::Class::num_type_arguments_offset()),
          kHalfword);
   __ CompareImmediate(R3, 0);
   __ b(normal_ir_body, NE);
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index d26494d..690df69 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -440,7 +440,7 @@
   Label overflow;
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // Shift value is in EAX. Compare with tagged Smi.
-  __ cmpl(EAX, Immediate(target::ToRawSmi(target::Smi::kBits)));
+  __ cmpl(EAX, Immediate(target::ToRawSmi(target::kSmiBits)));
   __ j(ABOVE_EQUAL, normal_ir_body, Assembler::kNearJump);
 
   __ SmiUntag(EAX);
@@ -1553,7 +1553,7 @@
   __ movl(EAX, FieldAddress(ECX, target::Double::value_offset()));
   __ movl(ECX, FieldAddress(ECX, target::Double::value_offset() + 4));
   __ xorl(EAX, ECX);
-  __ andl(EAX, Immediate(kSmiMax));
+  __ andl(EAX, Immediate(target::kSmiMax));
   __ SmiTag(EAX);
   __ ret();
 
@@ -1711,8 +1711,7 @@
   // Object is neither double, nor integer, nor string.
   __ Bind(&use_declaration_type);
   __ LoadClassById(EBX, EDI);
-  __ movzxw(EDI, FieldAddress(
-                     EBX, target::Class::num_type_arguments_offset_in_bytes()));
+  __ movzxw(EDI, FieldAddress(EBX, target::Class::num_type_arguments_offset()));
   __ cmpl(EDI, Immediate(0));
   __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
   __ movl(EAX, FieldAddress(EBX, target::Class::declaration_type_offset()));
@@ -1747,8 +1746,7 @@
   // Check if there are no type arguments. In this case we can return true.
   // Otherwise fall through into the runtime to handle comparison.
   __ LoadClassById(EBX, EDI);
-  __ movzxw(EBX, FieldAddress(
-                     EBX, target::Class::num_type_arguments_offset_in_bytes()));
+  __ movzxw(EBX, FieldAddress(EBX, target::Class::num_type_arguments_offset()));
   __ cmpl(EBX, Immediate(0));
   __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
 
@@ -2206,8 +2204,7 @@
   __ xorl(ECX, ECX);
 
   // Tail-call the function.
-  __ movl(EDI, FieldAddress(EAX, target::Function::entry_point_offset()));
-  __ jmp(EDI);
+  __ jmp(FieldAddress(EAX, target::Function::entry_point_offset()));
 }
 
 // On stack: user tag (+1), return-address (+0).
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 76618bc..d210d67 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -494,7 +494,7 @@
   Label overflow;
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // Shift value is in RAX. Compare with tagged Smi.
-  __ cmpq(RAX, Immediate(target::ToRawSmi(target::Smi::kBits)));
+  __ cmpq(RAX, Immediate(target::ToRawSmi(target::kSmiBits)));
   __ j(ABOVE_EQUAL, normal_ir_body, Assembler::kNearJump);
 
   __ SmiUntag(RAX);
@@ -1465,7 +1465,7 @@
   __ movq(RCX, RAX);
   __ shrq(RCX, Immediate(32));
   __ xorq(RAX, RCX);
-  __ andq(RAX, Immediate(kSmiMax));
+  __ andq(RAX, Immediate(target::kSmiMax));
   __ SmiTag(RAX);
   __ ret();
 
@@ -1623,8 +1623,7 @@
   // Object is neither double, nor integer, nor string.
   __ Bind(&use_declaration_type);
   __ LoadClassById(RDI, RCX);
-  __ movzxw(RCX, FieldAddress(
-                     RDI, target::Class::num_type_arguments_offset_in_bytes()));
+  __ movzxw(RCX, FieldAddress(RDI, target::Class::num_type_arguments_offset()));
   __ cmpq(RCX, Immediate(0));
   __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
   __ movq(RAX, FieldAddress(RDI, target::Class::declaration_type_offset()));
@@ -1659,8 +1658,7 @@
   // Check if there are no type arguments. In this case we can return true.
   // Otherwise fall through into the runtime to handle comparison.
   __ LoadClassById(RDI, RCX);
-  __ movzxw(RCX, FieldAddress(
-                     RDI, target::Class::num_type_arguments_offset_in_bytes()));
+  __ movzxw(RCX, FieldAddress(RDI, target::Class::num_type_arguments_offset()));
   __ cmpq(RCX, Immediate(0));
   __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index b3debf1..fa570c5 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -24,6 +24,7 @@
 DECLARE_FLAG(bool, check_code_pointer);
 DECLARE_FLAG(bool, inline_alloc);
 DECLARE_FLAG(bool, precompiled_mode);
+DECLARE_FLAG(bool, use_slow_path);
 
 namespace compiler {
 
@@ -548,17 +549,19 @@
 }
 
 void Assembler::TransitionGeneratedToNative(Register destination_address,
+                                            Register exit_frame_fp,
                                             Register addr,
                                             Register state) {
   // Save exit frame information to enable stack walking.
-  StoreToOffset(kWord, FP, THR, Thread::top_exit_frame_info_offset());
+  StoreToOffset(kWord, exit_frame_fp, THR,
+                Thread::top_exit_frame_info_offset());
 
   // Mark that the thread is executing native code.
   StoreToOffset(kWord, destination_address, THR, Thread::vm_tag_offset());
   LoadImmediate(state, compiler::target::Thread::native_execution_state());
   StoreToOffset(kWord, state, THR, Thread::execution_state_offset());
 
-  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
+  if (FLAG_use_slow_path || TargetCPUFeatures::arm_version() == ARMv5TE) {
     EnterSafepointSlowly();
   } else {
     Label slow_path, done, retry;
@@ -590,7 +593,7 @@
 }
 
 void Assembler::TransitionNativeToGenerated(Register addr, Register state) {
-  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
+  if (FLAG_use_slow_path || TargetCPUFeatures::arm_version() == ARMv5TE) {
     ExitSafepointSlowly();
   } else {
     Label slow_path, done, retry;
@@ -1387,7 +1390,9 @@
       code = 4 | (idx << 3);
       break;
     }
-    default: { break; }
+    default: {
+      break;
+    }
   }
 
   EmitSIMDddd(B24 | B23 | B11 | B10 | B6, kWordPair,
@@ -1597,9 +1602,9 @@
   } else if (CanLoadFromObjectPool(object)) {
     // Make sure that class CallPattern is able to decode this load from the
     // object pool.
-    const int32_t offset = ObjectPool::element_offset(
-        is_unique ? object_pool_builder().AddObject(object)
-                  : object_pool_builder().FindObject(object));
+    const auto index = is_unique ? object_pool_builder().AddObject(object)
+                                 : object_pool_builder().FindObject(object);
+    const int32_t offset = ObjectPool::element_offset(index);
     LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, pp, cond);
   } else {
     UNREACHABLE();
@@ -1616,14 +1621,6 @@
   LoadObjectHelper(rd, object, cond, /* is_unique = */ true, PP);
 }
 
-void Assembler::LoadFunctionFromCalleePool(Register dst,
-                                           const Function& function,
-                                           Register new_pp) {
-  const int32_t offset = ObjectPool::element_offset(
-      object_pool_builder().FindObject(ToObject(function)));
-  LoadWordFromPoolOffset(dst, offset - kHeapObjectTag, new_pp, AL);
-}
-
 void Assembler::LoadNativeEntry(Register rd,
                                 const ExternalLabel* label,
                                 ObjectPoolBuilderEntry::Patchability patchable,
@@ -2504,6 +2501,33 @@
   }
 }
 
+void Assembler::PushNativeCalleeSavedRegisters() {
+  // Save new context and C++ ABI callee-saved registers.
+  PushList(kAbiPreservedCpuRegs);
+
+  const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
+  if (TargetCPUFeatures::vfp_supported()) {
+    ASSERT(2 * kAbiPreservedFpuRegCount < 16);
+    // Save FPU registers. 2 D registers per Q register.
+    vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
+  } else {
+    sub(SP, SP, Operand(kAbiPreservedFpuRegCount * kFpuRegisterSize));
+  }
+}
+
+void Assembler::PopNativeCalleeSavedRegisters() {
+  const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
+  // Restore C++ ABI callee-saved registers.
+  if (TargetCPUFeatures::vfp_supported()) {
+    // Restore FPU registers. 2 D registers per Q register.
+    vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
+  } else {
+    AddImmediate(SP, kAbiPreservedFpuRegCount * kFpuRegisterSize);
+  }
+  // Restore CPU registers.
+  PopList(kAbiPreservedCpuRegs);
+}
+
 void Assembler::MoveRegister(Register rd, Register rm, Condition cond) {
   if (rd != rm) {
     mov(rd, Operand(rm), cond);
@@ -3165,8 +3189,8 @@
     sdiv(result, left, right);
   } else {
     ASSERT(TargetCPUFeatures::vfp_supported());
-    SRegister stmpl = static_cast<SRegister>(2 * tmpl);
-    SRegister stmpr = static_cast<SRegister>(2 * tmpr);
+    SRegister stmpl = EvenSRegisterOf(tmpl);
+    SRegister stmpr = EvenSRegisterOf(tmpr);
     vmovsr(stmpl, left);
     vcvtdi(tmpl, stmpl);  // left is in tmpl.
     vmovsr(stmpr, right);
@@ -3223,6 +3247,23 @@
   }
 }
 
+void Assembler::EmitEntryFrameVerification(Register scratch) {
+#if defined(DEBUG)
+  Label done;
+  ASSERT(!constant_pool_allowed());
+  LoadImmediate(scratch,
+                compiler::target::frame_layout.exit_link_slot_from_entry_fp *
+                    compiler::target::kWordSize);
+  add(scratch, scratch, Operand(FPREG));
+  cmp(scratch, Operand(SPREG));
+  b(&done, EQ);
+
+  Breakpoint();
+
+  Bind(&done);
+#endif
+}
+
 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) {
   Comment("EnterCallRuntimeFrame");
   // Preserve volatile CPU registers and PP.
@@ -3392,8 +3433,8 @@
   ASSERT(cid > 0);
   const intptr_t class_offset = ClassTable::ClassOffsetFor(cid);
   LoadIsolate(dest);
-  intptr_t table_offset =
-      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  intptr_t table_offset = Isolate::class_table_offset() +
+                          ClassTable::class_heap_stats_table_offset();
   ldr(dest, Address(dest, table_offset));
   AddImmediate(dest, class_offset);
 }
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 3f37cbd6..ceb1820 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -510,9 +510,12 @@
   void ldrex(Register rd, Register rn, Condition cond = AL);
   void strex(Register rd, Register rt, Register rn, Condition cond = AL);
 
-  // Requires two temporary registers 'scratch0' and 'scratch1' (in addition to
-  // TMP).
+  // Emit code to transition between generated and native modes.
+  //
+  // These require that CSP and SP are equal and aligned and require two scratch
+  // registers (in addition to TMP).
   void TransitionGeneratedToNative(Register destination_address,
+                                   Register exit_frame_fp,
                                    Register scratch0,
                                    Register scratch1);
   void TransitionNativeToGenerated(Register scratch0, Register scratch1);
@@ -758,9 +761,6 @@
 
   void LoadObject(Register rd, const Object& object, Condition cond = AL);
   void LoadUniqueObject(Register rd, const Object& object, Condition cond = AL);
-  void LoadFunctionFromCalleePool(Register dst,
-                                  const Function& function,
-                                  Register new_pp);
   void LoadNativeEntry(Register dst,
                        const ExternalLabel* label,
                        ObjectPoolBuilderEntry::Patchability patchable,
@@ -920,6 +920,12 @@
   void PushRegisters(const RegisterSet& regs);
   void PopRegisters(const RegisterSet& regs);
 
+  // Push all registers which are callee-saved according to the ARM ABI.
+  void PushNativeCalleeSavedRegisters();
+
+  // Pop all registers which are callee-saved according to the ARM ABI.
+  void PopNativeCalleeSavedRegisters();
+
   void CompareRegisters(Register rn, Register rm) { cmp(rn, Operand(rm)); }
   void BranchIf(Condition condition, Label* label) { b(label, condition); }
 
@@ -1006,6 +1012,13 @@
   void Ret();
   void ReserveAlignedFrameSpace(intptr_t frame_space);
 
+  // In debug mode, this generates code to check that:
+  //   FP + kExitLinkSlotFromEntryFp == SP
+  // or triggers breakpoint otherwise.
+  //
+  // Requires a scratch register in addition to the assembler temporary.
+  void EmitEntryFrameVerification(Register scratch);
+
   // Create a frame for calling into runtime that preserves all volatile
   // registers.  Frame's SP is guaranteed to be correctly aligned and
   // frame_space bytes are reserved under it.
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index c88687fc..5c1b902 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -18,6 +18,7 @@
 DECLARE_FLAG(bool, check_code_pointer);
 DECLARE_FLAG(bool, inline_alloc);
 DECLARE_FLAG(bool, precompiled_mode);
+DECLARE_FLAG(bool, use_slow_path);
 
 DEFINE_FLAG(bool, use_far_branches, false, "Always use far branches");
 
@@ -495,17 +496,6 @@
   }
 }
 
-void Assembler::LoadFunctionFromCalleePool(Register dst,
-                                           const Function& function,
-                                           Register new_pp) {
-  ASSERT(!constant_pool_allowed());
-  ASSERT(new_pp != PP);
-  const int32_t offset = ObjectPool::element_offset(
-      object_pool_builder().FindObject(ToObject(function)));
-  ASSERT(Address::CanHoldOffset(offset));
-  ldr(dst, Address(new_pp, offset));
-}
-
 void Assembler::LoadObject(Register dst, const Object& object) {
   LoadObjectHelper(dst, object, false);
 }
@@ -1175,6 +1165,23 @@
   }
 }
 
+void Assembler::EmitEntryFrameVerification() {
+#if defined(DEBUG)
+  Label done;
+  ASSERT(!constant_pool_allowed());
+  LoadImmediate(TMP,
+                compiler::target::frame_layout.exit_link_slot_from_entry_fp *
+                    compiler::target::kWordSize);
+  add(TMP, TMP, Operand(FPREG));
+  cmp(TMP, Operand(SPREG));
+  b(&done, EQ);
+
+  Breakpoint();
+
+  Bind(&done);
+#endif
+}
+
 void Assembler::RestoreCodePointer() {
   ldr(CODE_REG, Address(FP, compiler::target::frame_layout.code_from_fp *
                                 target::kWordSize));
@@ -1306,11 +1313,13 @@
 }
 
 void Assembler::TransitionGeneratedToNative(Register destination,
+                                            Register new_exit_frame,
                                             Register state) {
   Register addr = TMP2;
+  ASSERT(addr != state);
 
   // Save exit frame information to enable stack walking.
-  StoreToOffset(FPREG, THR,
+  StoreToOffset(new_exit_frame, THR,
                 compiler::target::Thread::top_exit_frame_info_offset());
 
   // Mark that the thread is executing native code.
@@ -1319,17 +1328,20 @@
   StoreToOffset(state, THR, compiler::target::Thread::execution_state_offset());
 
   Label slow_path, done, retry;
-  movz(addr, Immediate(compiler::target::Thread::safepoint_state_offset()), 0);
-  add(addr, THR, Operand(addr));
-  Bind(&retry);
-  ldxr(state, addr);
-  cmp(state, Operand(Thread::safepoint_state_unacquired()));
-  b(&slow_path, NE);
+  if (!FLAG_use_slow_path) {
+    movz(addr, Immediate(compiler::target::Thread::safepoint_state_offset()),
+         0);
+    add(addr, THR, Operand(addr));
+    Bind(&retry);
+    ldxr(state, addr);
+    cmp(state, Operand(Thread::safepoint_state_unacquired()));
+    b(&slow_path, NE);
 
-  movz(state, Immediate(Thread::safepoint_state_acquired()), 0);
-  stxr(TMP, state, addr);
-  cbz(&done, TMP);  // 0 means stxr was successful.
-  b(&retry);
+    movz(state, Immediate(Thread::safepoint_state_acquired()), 0);
+    stxr(TMP, state, addr);
+    cbz(&done, TMP);  // 0 means stxr was successful.
+    b(&retry);
+  }
 
   Bind(&slow_path);
   ldr(addr,
@@ -1342,24 +1354,28 @@
 
 void Assembler::TransitionNativeToGenerated(Register state) {
   Register addr = TMP2;
+  ASSERT(addr != state);
 
   Label slow_path, done, retry;
-  movz(addr, Immediate(compiler::target::Thread::safepoint_state_offset()), 0);
-  add(addr, THR, Operand(addr));
-  Bind(&retry);
-  ldxr(state, addr);
-  cmp(state, Operand(Thread::safepoint_state_acquired()));
-  b(&slow_path, NE);
+  if (!FLAG_use_slow_path) {
+    movz(addr, Immediate(compiler::target::Thread::safepoint_state_offset()),
+         0);
+    add(addr, THR, Operand(addr));
+    Bind(&retry);
+    ldxr(state, addr);
+    cmp(state, Operand(Thread::safepoint_state_acquired()));
+    b(&slow_path, NE);
 
-  movz(state, Immediate(Thread::safepoint_state_unacquired()), 0);
-  stxr(TMP, state, addr);
-  cbz(&done, TMP);  // 0 means stxr was successful.
-  b(&retry);
+    movz(state, Immediate(Thread::safepoint_state_unacquired()), 0);
+    stxr(TMP, state, addr);
+    cbz(&done, TMP);  // 0 means stxr was successful.
+    b(&retry);
+  }
 
   Bind(&slow_path);
   ldr(addr,
       Address(THR, compiler::target::Thread::exit_safepoint_stub_offset()));
-  ldr(addr, FieldAddress(TMP, compiler::target::Code::entry_point_offset()));
+  ldr(addr, FieldAddress(addr, compiler::target::Code::entry_point_offset()));
   blr(addr);
 
   Bind(&done);
@@ -1453,19 +1469,21 @@
   bool saved_use_far_branches = use_far_branches();
   set_use_far_branches(false);
 
+  const intptr_t start = CodeSize();
+
   Label immediate, miss;
   Bind(&miss);
   ldr(IP0, Address(THR, Thread::monomorphic_miss_entry_offset()));
   br(IP0);
 
   Comment("MonomorphicCheckedEntry");
-  ASSERT(CodeSize() == Instructions::kPolymorphicEntryOffset);
+  ASSERT(CodeSize() - start == Instructions::kPolymorphicEntryOffset);
   LoadClassIdMayBeSmi(IP0, R0);
   cmp(R5, Operand(IP0, LSL, 1));
   b(&miss, NE);
 
   // Fall through to unchecked entry.
-  ASSERT(CodeSize() == Instructions::kMonomorphicEntryOffset);
+  ASSERT(CodeSize() - start == Instructions::kMonomorphicEntryOffset);
 
   set_use_far_branches(saved_use_far_branches);
 }
@@ -1477,8 +1495,8 @@
   ASSERT(cid > 0);
   intptr_t state_offset = ClassTable::StateOffsetFor(cid);
   LoadIsolate(temp_reg);
-  intptr_t table_offset =
-      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  intptr_t table_offset = Isolate::class_table_offset() +
+                          ClassTable::class_heap_stats_table_offset();
   ldr(temp_reg, Address(temp_reg, table_offset));
   AddImmediate(temp_reg, state_offset);
   ldr(temp_reg, Address(temp_reg, 0));
@@ -1488,10 +1506,10 @@
 
 void Assembler::UpdateAllocationStats(intptr_t cid) {
   ASSERT(cid > 0);
-  intptr_t counter_offset = ClassTable::CounterOffsetFor(cid, /*is_new=*/true);
+  intptr_t counter_offset = target::ClassTable::NewSpaceCounterOffsetFor(cid);
   LoadIsolate(TMP2);
-  intptr_t table_offset =
-      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  intptr_t table_offset = Isolate::class_table_offset() +
+                          ClassTable::class_heap_stats_table_offset();
   ldr(TMP, Address(TMP2, table_offset));
   AddImmediate(TMP2, TMP, counter_offset);
   ldr(TMP, Address(TMP2, 0));
@@ -1507,8 +1525,8 @@
   const uword size_field_offset =
       ClassHeapStats::allocated_size_since_gc_new_space_offset();
   LoadIsolate(TMP2);
-  intptr_t table_offset =
-      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  intptr_t table_offset = Isolate::class_table_offset() +
+                          ClassTable::class_heap_stats_table_offset();
   ldr(TMP, Address(TMP2, table_offset));
   AddImmediate(TMP2, TMP, class_offset);
   ldr(TMP, Address(TMP2, count_field_offset));
@@ -1835,6 +1853,41 @@
   }
 }
 
+void Assembler::PushNativeCalleeSavedRegisters() {
+  // Save the callee-saved registers.
+  for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) {
+    const Register r = static_cast<Register>(i);
+    // We use str instead of the Push macro because we will be pushing the PP
+    // register when it is not holding a pool-pointer since we are coming from
+    // C++ code.
+    str(r, Address(SP, -1 * target::kWordSize, Address::PreIndex));
+  }
+
+  // Save the bottom 64-bits of callee-saved V registers.
+  for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) {
+    const VRegister r = static_cast<VRegister>(i);
+    PushDouble(r);
+  }
+}
+
+void Assembler::PopNativeCalleeSavedRegisters() {
+  // Restore the bottom 64-bits of callee-saved V registers.
+  for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) {
+    const VRegister r = static_cast<VRegister>(i);
+    PopDouble(r);
+  }
+
+  // Restore C++ ABI callee-saved registers.
+  for (int i = kAbiLastPreservedCpuReg; i >= kAbiFirstPreservedCpuReg; i--) {
+    Register r = static_cast<Register>(i);
+    // We use ldr instead of the Pop macro because we will be popping the PP
+    // register when it is not holding a pool-pointer since we are returning to
+    // C++ code. We also skip the dart stack pointer SP, since we are still
+    // using it as the stack pointer.
+    ldr(r, Address(SP, 1 * target::kWordSize, Address::PostIndex));
+  }
+}
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 1ff5ac9..cb9af12 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -438,6 +438,12 @@
   void PushRegisters(const RegisterSet& registers);
   void PopRegisters(const RegisterSet& registers);
 
+  // Push all registers which are callee-saved according to the ARM64 ABI.
+  void PushNativeCalleeSavedRegisters();
+
+  // Pop all registers which are callee-saved according to the ARM64 ABI.
+  void PopNativeCalleeSavedRegisters();
+
   void MoveRegister(Register rd, Register rn) {
     if (rd != rn) {
       mov(rd, rn);
@@ -481,6 +487,11 @@
 
   void ReserveAlignedFrameSpace(intptr_t frame_space);
 
+  // In debug mode, this generates code to check that:
+  //   FP + kExitLinkSlotFromEntryFp == SP
+  // or triggers breakpoint otherwise.
+  void EmitEntryFrameVerification();
+
   // Instruction pattern from entrypoint is used in Dart frame prologs
   // to set up the frame and save a PC which can be used to figure out the
   // RawInstruction object corresponding to the code running in the frame.
@@ -1485,9 +1496,6 @@
   void LoadNativeEntry(Register dst,
                        const ExternalLabel* label,
                        ObjectPoolBuilderEntry::Patchability patchable);
-  void LoadFunctionFromCalleePool(Register dst,
-                                  const Function& function,
-                                  Register new_pp);
   void LoadIsolate(Register dst);
   void LoadObject(Register dst, const Object& obj);
   void LoadUniqueObject(Register dst, const Object& obj);
@@ -1527,9 +1535,13 @@
   void LeaveFrame();
   void Ret() { ret(LR); }
 
-  // These require that CSP and SP are equal and aligned.
-  // These require a scratch register (in addition to TMP/TMP2).
+  // Emit code to transition between generated mode and native mode.
+  //
+  // These require that CSP and SP are equal and aligned and require a scratch
+  // register (in addition to TMP/TMP2).
+
   void TransitionGeneratedToNative(Register destination_address,
+                                   Register new_exit_frame,
                                    Register scratch);
   void TransitionNativeToGenerated(Register scratch);
 
@@ -1537,7 +1549,7 @@
   void RestoreCodePointer();
 
   void EnterDartFrame(intptr_t frame_size, Register new_pp = kNoRegister);
-  void EnterOsrFrame(intptr_t extra_size, Register new_pp);
+  void EnterOsrFrame(intptr_t extra_size, Register new_pp = kNoRegister);
   void LeaveDartFrame(RestorePP restore_pp = kRestoreCallerPP);
 
   void EnterCallRuntimeFrame(intptr_t frame_size);
diff --git a/runtime/vm/compiler/assembler/assembler_dbc.h b/runtime/vm/compiler/assembler/assembler_dbc.h
index 253fdc1..b88795f 100644
--- a/runtime/vm/compiler/assembler/assembler_dbc.h
+++ b/runtime/vm/compiler/assembler/assembler_dbc.h
@@ -39,6 +39,8 @@
   // Misc. functionality
   intptr_t prologue_offset() const { return 0; }
 
+  void MonomorphicCheckedEntry() {}
+
   // Debugging and bringup support.
   void Stop(const char* message) override;
 
diff --git a/runtime/vm/compiler/assembler/assembler_dbc_test.cc b/runtime/vm/compiler/assembler/assembler_dbc_test.cc
index 1b192b5..562fb4c 100644
--- a/runtime/vm/compiler/assembler/assembler_dbc_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_dbc_test.cc
@@ -6,6 +6,7 @@
 #if defined(TARGET_ARCH_DBC)
 
 #include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/backend/locations.h"
 #include "vm/compiler/compiler_state.h"
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
@@ -32,6 +33,8 @@
 #define EXECUTE_TEST_CODE_OBJECT(code) Object::Handle(ExecuteTest(code))
 #define EXECUTE_TEST_CODE_DOUBLE(code)                                         \
   bit_cast<double, RawObject*>(ExecuteTest(code))
+#define EXECUTE_TEST_CODE_INTPTR_UNBOXED(code)                                 \
+  reinterpret_cast<intptr_t>(ExecuteTest(code))
 
 #define __ assembler->
 
@@ -2313,6 +2316,261 @@
   EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
 }
 
+//  - UnboxInt32 rA, rB, C
+//
+//    Unboxes the integer in FP[rB] into FP[rA]. If C == 1, the value may be
+//    truncated. If FP[rA] is successfully unboxed the following instruction is
+//    skipped.
+ASSEMBLER_TEST_GENERATE(UnboxInt32NoTrunctateSuccess, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(1234)));
+  __ UnboxInt32(1, 0, /*may_truncate=*/0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
+  __ Return(1);
+}
+
+ASSEMBLER_TEST_RUN(UnboxInt32NoTrunctateSuccess, test) {
+  EXPECT_EQ(1234, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
+}
+
+ASSEMBLER_TEST_GENERATE(UnboxInt32NoTrunctateFail, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Integer::Handle(Integer::New(Smi::kMaxValue + 1)));
+  __ UnboxInt32(1, 0, /*may_truncate=*/0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
+  __ Return(1);
+}
+
+ASSEMBLER_TEST_RUN(UnboxInt32NoTrunctateFail, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+ASSEMBLER_TEST_GENERATE(UnboxInt32TrunctateSuccess, assembler) {
+  __ Frame(2);
+  __ LoadConstant(
+      0, Integer::Handle(Integer::New(static_cast<int64_t>(kMaxInt32) + 1)));
+  __ UnboxInt32(1, 0, /*may_truncate=*/1);
+  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
+  __ Return(1);
+}
+
+ASSEMBLER_TEST_RUN(UnboxInt32TrunctateSuccess, test) {
+  EXPECT_EQ(static_cast<int64_t>(kMaxInt32) + 1,
+            EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
+}
+
+//  - BoxInt32 rA, rD
+//
+//    Boxes the unboxed signed 32-bit integer in FP[rD] into FP[rA].
+ASSEMBLER_TEST_GENERATE(BoxInt32, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ UnboxInt32(1, 0, /*may_truncate=*/0);
+  __ Nop(0);  // Unboxing succeeds.
+  __ BoxInt32(2, 1);
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(BoxInt32, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+//  - BoxUint32 rA, rD
+//
+//    Boxes the unboxed unsigned 32-bit integer in FP[rD] into FP[rA].
+ASSEMBLER_TEST_GENERATE(BoxUint32, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ UnboxInt32(1, 0, /*may_truncate=*/0);
+  __ Nop(0);  // Unboxing succeeds.
+  __ BoxUint32(2, 1);
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(BoxUint32, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+//  - UnboxInt64 rA, rD
+//
+//    Unboxes the integer in FP[rD] into FP[rA].
+ASSEMBLER_TEST_GENERATE(UnboxInt64MaxMint, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt64)));
+  __ UnboxInt64(1, 0);
+  __ Return(1);
+}
+
+ASSEMBLER_TEST_RUN(UnboxInt64MaxMint, test) {
+  EXPECT_EQ(kMaxInt64, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
+}
+
+ASSEMBLER_TEST_GENERATE(UnboxInt64MinMint, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Integer::Handle(Integer::New(kMinInt64)));
+  __ UnboxInt64(1, 0);
+  __ Return(1);
+}
+
+ASSEMBLER_TEST_RUN(UnboxInt64MinMint, test) {
+  EXPECT_EQ(kMinInt64, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
+}
+
+ASSEMBLER_TEST_GENERATE(UnboxInt64Smi, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ UnboxInt64(1, 0);
+  __ Return(1);
+}
+
+ASSEMBLER_TEST_RUN(UnboxInt64Smi, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
+}
+
+//  - BoxInt64 rA, rD
+//
+//    Boxes the unboxed signed 64-bit integer in FP[rD] into FP[rA]. If the
+//    value does not fit into a Smi the following instruction is skipped. (The
+//    following instruction should be a jump to a label after the slow path
+//    allocating a Mint box and writing into the Mint box.)
+ASSEMBLER_TEST_GENERATE(BoxInt64Smi, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ UnboxInt64(1, 0);
+  __ BoxInt64(2, 1);
+  __ Nop(0);
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(BoxInt64Smi, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+ASSEMBLER_TEST_GENERATE(BoxInt64MintFails, assembler) {
+  Label done;
+  __ Frame(3);
+  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt64)));
+  __ UnboxInt64(1, 0);
+  __ BoxInt64(2, 1);  // Boxing into Smi fails.
+  __ Jump(&done);
+  // Faking a slow path, with a different Mint value.
+  __ LoadConstant(2, Integer::Handle(Integer::New(kMaxInt64 - 42)));
+  __ Bind(&done);
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(BoxInt64MintFails, test) {
+  const Object& obj = EXECUTE_TEST_CODE_OBJECT(test->code());
+  EXPECT(obj.IsMint());
+  EXPECT_EQ(kMaxInt64 - 42, Mint::Cast(obj).value());
+}
+
+ASSEMBLER_TEST_GENERATE(WriteIntoMint, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt64)));
+  __ UnboxInt64(1, 0);
+  __ LoadConstant(2, Integer::Handle(Integer::New(kMaxInt64 - 42)));
+  __ WriteIntoMint(2, 1);  // Transplant unboxed value into an existing box.
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(WriteIntoMint, test) {
+  const Object& obj = EXECUTE_TEST_CODE_OBJECT(test->code());
+  EXPECT(obj.IsMint());
+  EXPECT_EQ(kMaxInt64, Mint::Cast(obj).value());
+}
+
+//  - UnboxedWidthExtender rA rB C
+//
+//    Sign- or zero-extends an unboxed integer in FP[rB] into an unboxed
+//    integer in FP[rA]. C contains SmallRepresentation which determines how
+//    the integer is extended.
+ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt8Positive, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt8 + 0xFFFFFF00)));
+  __ UnboxInt64(1, 0);
+  // The lower bits contain 0x7F, overwrite the upper bits with 0.
+  __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt8);
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt8Positive, test) {
+  EXPECT_EQ(static_cast<uint32_t>(kMaxInt8),
+            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
+}
+
+ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt8Negative, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt32)));
+  __ UnboxInt64(1, 0);
+  // The lower bits contain 0xFF, overwrite the upper bits with 1.
+  __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt8);
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt8Negative, test) {
+  // least significant 32 bits set to 1.
+  EXPECT_EQ(kMaxUint32,
+            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
+}
+
+ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderUint8, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxUint32)));
+  __ UnboxInt64(1, 0);
+  // The lower bits contain 0xFF, overwrite the upper bits with 0.
+  __ UnboxedWidthExtender(2, 1, kSmallUnboxedUint8);
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(UnboxedWidthExtenderUint8, test) {
+  EXPECT_EQ(kMaxUint8,
+            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
+}
+
+ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt16Positive, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt16 + 0xFFFF0000)));
+  __ UnboxInt64(1, 0);
+  // The lower bits contain 0x7FFF, overwrite the upper bits with 0.
+  __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt16);
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt16Positive, test) {
+  EXPECT_EQ(static_cast<uint32_t>(kMaxInt16),
+            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
+}
+
+ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt16Negative, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt32)));
+  __ UnboxInt64(1, 0);
+  // The lower bits contain 0xFFFF, overwrite the upper bits with 1.
+  __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt16);
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt16Negative, test) {
+  // least significant 32 bits set to 1.
+  EXPECT_EQ(kMaxUint32,
+            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
+}
+
+ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderUint16, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxUint32)));
+  __ UnboxInt64(1, 0);
+  // The lower bits contain 0xFFFF, overwrite the upper bits with 0.
+  __ UnboxedWidthExtender(2, 1, kSmallUnboxedUint16);
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(UnboxedWidthExtenderUint16, test) {
+  EXPECT_EQ(kMaxUint16,
+            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
+}
+
 #if defined(ARCH_IS_64_BIT)
 //  - UnboxDouble rA, rD
 //
@@ -2323,14 +2581,14 @@
 //    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) {
+ASSEMBLER_TEST_GENERATE(UnboxDouble, assembler) {
   __ Frame(2);
   __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
   __ UnboxDouble(1, 0);
   __ Return(1);
 }
 
-ASSEMBLER_TEST_RUN(Unbox, test) {
+ASSEMBLER_TEST_RUN(UnboxDouble, test) {
   EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
 }
 
@@ -2346,6 +2604,21 @@
   EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
 }
 
+ASSEMBLER_TEST_GENERATE(WriteIntoDouble, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
+  __ UnboxDouble(1, 0);
+  __ LoadConstant(2, Double::Handle(Double::New(0.0, Heap::kOld)));
+  __ WriteIntoDouble(2, 1);  // Transplant unboxed value into an existing box.
+  __ Return(2);
+}
+
+ASSEMBLER_TEST_RUN(WriteIntoDouble, test) {
+  const Object& obj = EXECUTE_TEST_CODE_OBJECT(test->code());
+  EXPECT(obj.IsDouble());
+  EXPECT_EQ(42.0, Double::Cast(obj).value());
+}
+
 ASSEMBLER_TEST_GENERATE(CheckedUnboxSmi, assembler) {
   __ Frame(2);
   __ LoadConstant(0, Smi::Handle(Smi::New(42)));
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 4ca49e3..7311298 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -16,6 +16,7 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 DECLARE_FLAG(bool, inline_alloc);
+DECLARE_FLAG(bool, use_slow_path);
 #endif
 
 namespace compiler {
@@ -1667,6 +1668,12 @@
   EmitRegisterOperand(4, reg);
 }
 
+void Assembler::jmp(const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xFF);
+  EmitOperand(4, address);
+}
+
 void Assembler::jmp(Label* label, bool near) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   if (label->IsBound()) {
@@ -2078,10 +2085,23 @@
   }
 }
 
+void Assembler::EmitEntryFrameVerification() {
+#if defined(DEBUG)
+  Label ok;
+  leal(EAX, Address(EBP, target::frame_layout.exit_link_slot_from_entry_fp *
+                             target::kWordSize));
+  cmpl(EAX, ESP);
+  j(EQUAL, &ok);
+  Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
+  Bind(&ok);
+#endif
+}
+
 void Assembler::TransitionGeneratedToNative(Register destination_address,
+                                            Register new_exit_frame,
                                             Register scratch) {
   // Save exit frame information to enable stack walking.
-  movl(Address(THR, Thread::top_exit_frame_info_offset()), FPREG);
+  movl(Address(THR, Thread::top_exit_frame_info_offset()), new_exit_frame);
 
   // Mark that the thread is executing native code.
   movl(VMTagAddress(), destination_address);
@@ -2090,16 +2110,17 @@
 
   // Compare and swap the value at Thread::safepoint_state from unacquired to
   // acquired. On success, jump to 'success'; otherwise, fallthrough.
-  pushl(EAX);
-  movl(EAX, Immediate(Thread::safepoint_state_unacquired()));
-  movl(scratch, Immediate(Thread::safepoint_state_acquired()));
-  LockCmpxchgl(Address(THR, Thread::safepoint_state_offset()), scratch);
-  movl(scratch, EAX);
-  popl(EAX);
-  cmpl(scratch, Immediate(Thread::safepoint_state_unacquired()));
-
   Label done;
-  j(EQUAL, &done);
+  if (!FLAG_use_slow_path) {
+    pushl(EAX);
+    movl(EAX, Immediate(Thread::safepoint_state_unacquired()));
+    movl(scratch, Immediate(Thread::safepoint_state_acquired()));
+    LockCmpxchgl(Address(THR, Thread::safepoint_state_offset()), scratch);
+    movl(scratch, EAX);
+    popl(EAX);
+    cmpl(scratch, Immediate(Thread::safepoint_state_unacquired()));
+    j(EQUAL, &done);
+  }
 
   movl(scratch,
        Address(THR, compiler::target::Thread::enter_safepoint_stub_offset()));
@@ -2113,18 +2134,20 @@
 void Assembler::TransitionNativeToGenerated(Register scratch) {
   // Compare and swap the value at Thread::safepoint_state from acquired to
   // unacquired. On success, jump to 'success'; otherwise, fallthrough.
-  pushl(EAX);
-  movl(EAX, Immediate(compiler::target::Thread::safepoint_state_acquired()));
-  movl(scratch,
-       Immediate(compiler::target::Thread::safepoint_state_unacquired()));
-  LockCmpxchgl(Address(THR, compiler::target::Thread::safepoint_state_offset()),
-               scratch);
-  movl(scratch, EAX);
-  popl(EAX);
-  cmpl(scratch, Immediate(Thread::safepoint_state_acquired()));
-
   Label done;
-  j(EQUAL, &done);
+  if (!FLAG_use_slow_path) {
+    pushl(EAX);
+    movl(EAX, Immediate(compiler::target::Thread::safepoint_state_acquired()));
+    movl(scratch,
+         Immediate(compiler::target::Thread::safepoint_state_unacquired()));
+    LockCmpxchgl(
+        Address(THR, compiler::target::Thread::safepoint_state_offset()),
+        scratch);
+    movl(scratch, EAX);
+    popl(EAX);
+    cmpl(scratch, Immediate(Thread::safepoint_state_acquired()));
+    j(EQUAL, &done);
+  }
 
   movl(scratch,
        Address(THR, compiler::target::Thread::exit_safepoint_stub_offset()));
@@ -2262,6 +2285,11 @@
   label->BindTo(bound);
 }
 
+void Assembler::MoveMemoryToMemory(Address dst, Address src, Register tmp) {
+  movl(tmp, src);
+  movl(dst, tmp);
+}
+
 #ifndef PRODUCT
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Register temp_reg,
@@ -2272,8 +2300,8 @@
   intptr_t state_offset = ClassTable::StateOffsetFor(cid);
   ASSERT(temp_reg != kNoRegister);
   LoadIsolate(temp_reg);
-  intptr_t table_offset =
-      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  intptr_t table_offset = Isolate::class_table_offset() +
+                          ClassTable::class_heap_stats_table_offset();
   movl(temp_reg, Address(temp_reg, table_offset));
   state_address = Address(temp_reg, state_offset);
   testb(state_address,
@@ -2285,12 +2313,11 @@
 
 void Assembler::UpdateAllocationStats(intptr_t cid, Register temp_reg) {
   ASSERT(cid > 0);
-  intptr_t counter_offset =
-      ClassTable::CounterOffsetFor(cid, /*is_new_space=*/true);
+  intptr_t counter_offset = ClassTable::NewSpaceCounterOffsetFor(cid);
   ASSERT(temp_reg != kNoRegister);
   LoadIsolate(temp_reg);
-  intptr_t table_offset =
-      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  intptr_t table_offset = Isolate::class_table_offset() +
+                          ClassTable::class_heap_stats_table_offset();
   movl(temp_reg, Address(temp_reg, table_offset));
   incl(Address(temp_reg, counter_offset));
 }
@@ -2301,7 +2328,7 @@
   ASSERT(cid > 0);
   ASSERT(cid < kNumPredefinedCids);
   UpdateAllocationStats(cid, temp_reg);
-  intptr_t size_offset = ClassTable::SizeOffsetFor(cid, /*is_new_space=*/true);
+  intptr_t size_offset = ClassTable::NewSpaceSizeOffsetFor(cid);
   addl(Address(temp_reg, size_offset), size_reg);
 }
 
@@ -2311,7 +2338,7 @@
   ASSERT(cid > 0);
   ASSERT(cid < kNumPredefinedCids);
   UpdateAllocationStats(cid, temp_reg);
-  intptr_t size_offset = ClassTable::SizeOffsetFor(cid, /*is_new_space=*/true);
+  intptr_t size_offset = ClassTable::NewSpaceSizeOffsetFor(cid);
   addl(Address(temp_reg, size_offset), Immediate(size_in_bytes));
 }
 #endif  // !PRODUCT
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index 91fa1c2..ad6149b 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -549,6 +549,7 @@
   void j(Condition condition, const ExternalLabel* label);
 
   void jmp(Register reg);
+  void jmp(const Address& address);
   void jmp(Label* label, bool near = kFarJump);
   void jmp(const ExternalLabel* label);
 
@@ -645,9 +646,25 @@
   void LeaveFrame();
   void ReserveAlignedFrameSpace(intptr_t frame_space);
 
+  void MonomorphicCheckedEntry() {}
+
+  // In debug mode, this generates code to check that:
+  //   FP + kExitLinkSlotFromEntryFp == SP
+  // or triggers breakpoint otherwise.
+  //
+  // Clobbers EAX.
+  void EmitEntryFrameVerification();
+
+  // Transitions safepoint and Thread state between generated and native code.
+  // Updates top-exit-frame info, VM tag and execution-state. Leaves/enters a
+  // safepoint.
+  //
   // Require a temporary register 'tmp'.
   // Clobber all non-CPU registers (e.g. XMM registers and the "FPU stack").
+  // However XMM0 is saved for convenience.
+
   void TransitionGeneratedToNative(Register destination_address,
+                                   Register new_exit_frame,
                                    Register scratch);
   void TransitionNativeToGenerated(Register scratch);
 
@@ -723,6 +740,10 @@
   void Bind(Label* label);
   void Jump(Label* label) { jmp(label); }
 
+  // Moves one word from the memory at [from] to the memory at [to].
+  // Needs a temporary register.
+  void MoveMemoryToMemory(Address to, Address from, Register tmp);
+
   bool has_single_entry_point() const { return true; }
 
   // Set up a Dart frame on entry with a frame pointer and PC information to
@@ -822,6 +843,9 @@
   // We consider 16-bit integers, powers of two and corresponding masks
   // as safe values that can be emdedded into the code object.
   static bool IsSafeSmi(const Object& object) {
+    if (!target::IsSmi(object)) {
+      return false;
+    }
     int64_t value;
     if (HasIntegerValue(object, &value)) {
       return Utils::IsInt(16, value) || Utils::IsPowerOfTwo(value) ||
diff --git a/runtime/vm/compiler/assembler/assembler_ia32_test.cc b/runtime/vm/compiler/assembler/assembler_ia32_test.cc
index 26d3784..ca0ab3a 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32_test.cc
@@ -326,6 +326,51 @@
       "ret\n");
 }
 
+struct JumpAddress {
+  uword filler1;
+  uword filler2;
+  uword filler3;
+  uword filler4;
+  uword filler5;
+  uword target;
+  uword filler6;
+  uword filler7;
+  uword filler8;
+};
+static JumpAddress jump_address;
+static uword jump_address_offset;
+
+ASSEMBLER_TEST_GENERATE(JumpAddress, assembler) {
+  __ movl(EAX, Address(ESP, 4));
+  __ jmp(Address(EAX, OFFSET_OF(JumpAddress, target)));
+  __ int3();
+  __ int3();
+  __ int3();
+  __ int3();
+  __ int3();
+  jump_address_offset = __ CodeSize();
+  __ movl(EAX, Immediate(42));
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(JumpAddress, test) {
+  memset(&jump_address, 0, sizeof(jump_address));
+  jump_address.target = test->entry() + jump_address_offset;
+
+  typedef int (*TestCode)(void*);
+  EXPECT_EQ(42, reinterpret_cast<TestCode>(test->entry())(&jump_address));
+  EXPECT_DISASSEMBLY(
+      "mov eax,[esp+0x4]\n"
+      "jmp [eax+0x14]\n"
+      "int3\n"
+      "int3\n"
+      "int3\n"
+      "int3\n"
+      "int3\n"
+      "mov eax,0x2a\n"
+      "ret\n");
+}
+
 ASSEMBLER_TEST_GENERATE(Increment, assembler) {
   __ movl(EAX, Immediate(0));
   __ pushl(EAX);
@@ -480,14 +525,14 @@
       "ret\n");
 }
 
-ASSEMBLER_TEST_GENERATE(BitScanReverse, assembler) {
+ASSEMBLER_TEST_GENERATE(BitScanReverseTest, assembler) {
   __ movl(ECX, Address(ESP, target::kWordSize));
   __ movl(EAX, Immediate(666));  // Marker for conditional write.
   __ bsrl(EAX, ECX);
   __ ret();
 }
 
-ASSEMBLER_TEST_RUN(BitScanReverse, test) {
+ASSEMBLER_TEST_RUN(BitScanReverseTest, test) {
   typedef int (*Bsr)(int input);
   Bsr call = reinterpret_cast<Bsr>(test->entry());
   EXPECT_EQ(666, call(0));
@@ -4669,7 +4714,7 @@
   __ ret();
 }
 
-ASSEMBLER_TEST_GENERATE(BitTest, assembler) {
+ASSEMBLER_TEST_GENERATE(BitTestTest, assembler) {
   __ movl(EAX, Immediate(4));
   __ movl(ECX, Immediate(2));
   __ bt(EAX, ECX);
@@ -4681,7 +4726,7 @@
   __ ret();
 }
 
-ASSEMBLER_TEST_RUN(BitTest, test) {
+ASSEMBLER_TEST_RUN(BitTestTest, test) {
   typedef int (*BitTest)();
   EXPECT_EQ(1, reinterpret_cast<BitTest>(test->entry())());
   EXPECT_DISASSEMBLY(
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 64f3d7ed..1a6596e 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -18,6 +18,7 @@
 DECLARE_FLAG(bool, check_code_pointer);
 DECLARE_FLAG(bool, inline_alloc);
 DECLARE_FLAG(bool, precompiled_mode);
+DECLARE_FLAG(bool, use_slow_path);
 #endif
 
 namespace compiler {
@@ -164,9 +165,10 @@
   EmitUint8(0xC0 + (dst & 0x07));
 }
 
-void Assembler::TransitionGeneratedToNative(Register destination_address) {
+void Assembler::TransitionGeneratedToNative(Register destination_address,
+                                            Register new_exit_frame) {
   // Save exit frame information to enable stack walking.
-  movq(Address(THR, Thread::top_exit_frame_info_offset()), FPREG);
+  movq(Address(THR, Thread::top_exit_frame_info_offset()), new_exit_frame);
 
   movq(Assembler::VMTagAddress(), destination_address);
   movq(Address(THR, compiler::target::Thread::execution_state_offset()),
@@ -175,19 +177,23 @@
   // Compare and swap the value at Thread::safepoint_state from unacquired to
   // acquired. If the CAS fails, go to a slow-path stub.
   Label done;
-  pushq(RAX);
-  movq(RAX, Immediate(Thread::safepoint_state_unacquired()));
-  movq(TMP, Immediate(Thread::safepoint_state_acquired()));
-  LockCmpxchgq(Address(THR, Thread::safepoint_state_offset()), TMP);
-  movq(TMP, RAX);
-  popq(RAX);
-  cmpq(TMP, Immediate(Thread::safepoint_state_unacquired()));
-  j(EQUAL, &done);
+  if (!FLAG_use_slow_path) {
+    pushq(RAX);
+    movq(RAX, Immediate(Thread::safepoint_state_unacquired()));
+    movq(TMP, Immediate(Thread::safepoint_state_acquired()));
+    LockCmpxchgq(Address(THR, Thread::safepoint_state_offset()), TMP);
+    movq(TMP, RAX);
+    popq(RAX);
+    cmpq(TMP, Immediate(Thread::safepoint_state_unacquired()));
+    j(EQUAL, &done);
+  }
 
   movq(TMP,
        Address(THR, compiler::target::Thread::enter_safepoint_stub_offset()));
   movq(TMP, FieldAddress(TMP, compiler::target::Code::entry_point_offset()));
-  CallCFunction(TMP);
+  // Use call instead of CFunctionCall to prevent having to clean up shadow
+  // space afterwards. This is possible because safepoint stub has no arguments.
+  call(TMP);
 
   Bind(&done);
 }
@@ -196,19 +202,23 @@
   // Compare and swap the value at Thread::safepoint_state from acquired to
   // unacquired. On success, jump to 'success'; otherwise, fallthrough.
   Label done;
-  pushq(RAX);
-  movq(RAX, Immediate(Thread::safepoint_state_acquired()));
-  movq(TMP, Immediate(Thread::safepoint_state_unacquired()));
-  LockCmpxchgq(Address(THR, Thread::safepoint_state_offset()), TMP);
-  movq(TMP, RAX);
-  popq(RAX);
-  cmpq(TMP, Immediate(Thread::safepoint_state_acquired()));
-  j(EQUAL, &done);
+  if (!FLAG_use_slow_path) {
+    pushq(RAX);
+    movq(RAX, Immediate(Thread::safepoint_state_acquired()));
+    movq(TMP, Immediate(Thread::safepoint_state_unacquired()));
+    LockCmpxchgq(Address(THR, Thread::safepoint_state_offset()), TMP);
+    movq(TMP, RAX);
+    popq(RAX);
+    cmpq(TMP, Immediate(Thread::safepoint_state_acquired()));
+    j(EQUAL, &done);
+  }
 
   movq(TMP,
        Address(THR, compiler::target::Thread::exit_safepoint_stub_offset()));
   movq(TMP, FieldAddress(TMP, compiler::target::Code::entry_point_offset()));
-  CallCFunction(TMP);
+  // Use call instead of CFunctionCall to prevent having to clean up shadow
+  // space afterwards. This is possible because safepoint stub has no arguments.
+  call(TMP);
 
   Bind(&done);
 
@@ -996,7 +1006,7 @@
   const intptr_t idx = object_pool_builder().AddObject(
       ToObject(target), ObjectPoolBuilderEntry::kPatchable);
   const int32_t offset = target::ObjectPool::element_offset(idx);
-  movq(CODE_REG, Address::AddressBaseImm32(pp, offset - kHeapObjectTag));
+  movq(CODE_REG, Address(pp, offset - kHeapObjectTag));
   movq(TMP, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   jmp(TMP);
 }
@@ -1007,8 +1017,7 @@
       ToObject(target), ObjectPoolBuilderEntry::kNotPatchable);
   const int32_t offset = target::ObjectPool::element_offset(idx);
   movq(CODE_REG, FieldAddress(pp, offset));
-  movq(TMP, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
-  jmp(TMP);
+  jmp(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
 }
 
 void Assembler::CompareRegisters(Register a, Register b) {
@@ -1182,7 +1191,7 @@
                                  bool is_unique) {
   ASSERT(IsOriginalObject(object));
 
-  target::word offset_from_thread;
+  intptr_t offset_from_thread;
   if (target::CanLoadFromThread(object, &offset_from_thread)) {
     movq(dst, Address(THR, offset_from_thread));
   } else if (CanLoadFromObjectPool(object)) {
@@ -1196,17 +1205,6 @@
   }
 }
 
-void Assembler::LoadFunctionFromCalleePool(Register dst,
-                                           const Function& function,
-                                           Register new_pp) {
-  ASSERT(!constant_pool_allowed());
-  ASSERT(new_pp != PP);
-  const intptr_t idx = object_pool_builder().FindObject(
-      ToObject(function), ObjectPoolBuilderEntry::kNotPatchable);
-  const int32_t offset = target::ObjectPool::element_offset(idx);
-  movq(dst, Address::AddressBaseImm32(new_pp, offset - kHeapObjectTag));
-}
-
 void Assembler::LoadObject(Register dst, const Object& object) {
   LoadObjectHelper(dst, object, false);
 }
@@ -1218,7 +1216,7 @@
 void Assembler::StoreObject(const Address& dst, const Object& object) {
   ASSERT(IsOriginalObject(object));
 
-  target::word offset_from_thread;
+  intptr_t offset_from_thread;
   if (target::CanLoadFromThread(object, &offset_from_thread)) {
     movq(TMP, Address(THR, offset_from_thread));
     movq(dst, TMP);
@@ -1234,7 +1232,7 @@
 void Assembler::PushObject(const Object& object) {
   ASSERT(IsOriginalObject(object));
 
-  target::word offset_from_thread;
+  intptr_t offset_from_thread;
   if (target::CanLoadFromThread(object, &offset_from_thread)) {
     pushq(Address(THR, offset_from_thread));
   } else if (CanLoadFromObjectPool(object)) {
@@ -1249,7 +1247,7 @@
 void Assembler::CompareObject(Register reg, const Object& object) {
   ASSERT(IsOriginalObject(object));
 
-  target::word offset_from_thread;
+  intptr_t offset_from_thread;
   if (target::CanLoadFromThread(object, &offset_from_thread)) {
     cmpq(reg, Address(THR, offset_from_thread));
   } else if (CanLoadFromObjectPool(object)) {
@@ -1529,6 +1527,18 @@
   }
 }
 
+void Assembler::EmitEntryFrameVerification() {
+#if defined(DEBUG)
+  Label ok;
+  leaq(RAX, Address(RBP, target::frame_layout.exit_link_slot_from_entry_fp *
+                             target::kWordSize));
+  cmpq(RAX, RSP);
+  j(EQUAL, &ok);
+  Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
+  Bind(&ok);
+#endif
+}
+
 void Assembler::PushRegisters(intptr_t cpu_register_set,
                               intptr_t xmm_register_set) {
   const intptr_t xmm_regs_count = RegisterSet::RegisterCount(xmm_register_set);
@@ -1732,19 +1742,15 @@
   LeaveDartFrame();
 }
 
-// RDI receiver, RBX guarded cid as Smi.
+// RDX receiver, RBX guarded cid as Smi.
 // Preserve R10 (ARGS_DESC_REG), not required today, but maybe later.
 void Assembler::MonomorphicCheckedEntry() {
   has_single_entry_point_ = false;
   intptr_t start = CodeSize();
-  Label immediate, have_cid, miss;
+  Label have_cid, miss;
   Bind(&miss);
   jmp(Address(THR, Thread::monomorphic_miss_entry_offset()));
 
-  Bind(&immediate);
-  movq(TMP, Immediate(kSmiCid));
-  jmp(&have_cid, kNearJump);
-
   // Ensure the monomorphic entry is 2-byte aligned (so GC can see them if we
   // store them in ICData / MegamorphicCache arrays)
   nop(1);
@@ -1753,17 +1759,20 @@
   ASSERT(CodeSize() - start == Instructions::kPolymorphicEntryOffset);
   ASSERT((CodeSize() & kSmiTagMask) == kSmiTag);
 
+  movq(RAX, Immediate(kSmiCid));
   SmiUntag(RBX);
-  testq(RDI, Immediate(kSmiTagMask));
-  j(ZERO, &immediate, kNearJump);
-  nop(1);
-
-  LoadClassId(TMP, RDI);
-
+  testq(RDX, Immediate(kSmiTagMask));
+  j(ZERO, &have_cid, kNearJump);
+  LoadClassId(RAX, RDX);
   Bind(&have_cid);
-  cmpq(TMP, RBX);
+
+  cmpq(RAX, RBX);
   j(NOT_EQUAL, &miss, Assembler::kNearJump);
 
+  // Ensure the unchecked entry is 2-byte aligned (so GC can see them if we
+  // store them in ICData / MegamorphicCache arrays).
+  nop(1);
+
   // Fall through to unchecked entry.
   ASSERT(CodeSize() - start == Instructions::kMonomorphicEntryOffset);
   ASSERT(((CodeSize() - start) & kSmiTagMask) == kSmiTag);
@@ -1777,8 +1786,8 @@
   intptr_t state_offset = ClassTable::StateOffsetFor(cid);
   Register temp_reg = TMP;
   LoadIsolate(temp_reg);
-  intptr_t table_offset =
-      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  intptr_t table_offset = Isolate::class_table_offset() +
+                          ClassTable::class_heap_stats_table_offset();
   movq(temp_reg, Address(temp_reg, table_offset));
   testb(Address(temp_reg, state_offset),
         Immediate(target::ClassHeapStats::TraceAllocationMask()));
@@ -1789,12 +1798,11 @@
 
 void Assembler::UpdateAllocationStats(intptr_t cid) {
   ASSERT(cid > 0);
-  intptr_t counter_offset =
-      ClassTable::CounterOffsetFor(cid, /*is_new_space=*/true);
+  intptr_t counter_offset = ClassTable::NewSpaceCounterOffsetFor(cid);
   Register temp_reg = TMP;
   LoadIsolate(temp_reg);
-  intptr_t table_offset =
-      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  intptr_t table_offset = Isolate::class_table_offset() +
+                          ClassTable::class_heap_stats_table_offset();
   movq(temp_reg, Address(temp_reg, table_offset));
   incq(Address(temp_reg, counter_offset));
 }
@@ -1804,7 +1812,7 @@
   ASSERT(cid < kNumPredefinedCids);
   UpdateAllocationStats(cid);
   Register temp_reg = TMP;
-  intptr_t size_offset = ClassTable::SizeOffsetFor(cid, /*is_new_space=*/true);
+  intptr_t size_offset = ClassTable::NewSpaceSizeOffsetFor(cid);
   addq(Address(temp_reg, size_offset), size_reg);
 }
 
@@ -1814,7 +1822,7 @@
   ASSERT(cid < kNumPredefinedCids);
   UpdateAllocationStats(cid);
   Register temp_reg = TMP;
-  intptr_t size_offset = ClassTable::SizeOffsetFor(cid, /*is_new_space=*/true);
+  intptr_t size_offset = ClassTable::NewSpaceSizeOffsetFor(cid);
   addq(Address(temp_reg, size_offset), Immediate(size_in_bytes));
 }
 #endif  // !PRODUCT
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 0ef1efe..4df9250 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -306,7 +306,8 @@
 
   void setcc(Condition condition, ByteRegister dst);
 
-  void TransitionGeneratedToNative(Register destination_address);
+  void TransitionGeneratedToNative(Register destination_address,
+                                   Register new_exit_frame);
   void TransitionNativeToGenerated();
 
 // Register-register, register-address and address-register instructions.
@@ -696,9 +697,6 @@
   void LoadNativeEntry(Register dst,
                        const ExternalLabel* label,
                        ObjectPoolBuilderEntry::Patchability patchable);
-  void LoadFunctionFromCalleePool(Register dst,
-                                  const Function& function,
-                                  Register new_pp);
   void JmpPatchable(const Code& code, Register pp);
   void Jmp(const Code& code, Register pp = PP);
   void J(Condition condition, const Code& code, Register pp);
@@ -780,6 +778,13 @@
   void LeaveFrame();
   void ReserveAlignedFrameSpace(intptr_t frame_space);
 
+  // In debug mode, generates code to verify that:
+  //   FP + kExitLinkSlotFromFp == SP
+  //
+  // Triggers breakpoint otherwise.
+  // Clobbers RAX.
+  void EmitEntryFrameVerification();
+
   // Create a frame for calling into runtime that preserves all volatile
   // registers.  Frame's RSP is guaranteed to be correctly aligned and
   // frame_space bytes are reserved under it.
@@ -856,7 +861,7 @@
   //   ...
   //   pushq r15
   //   .....
-  void EnterDartFrame(intptr_t frame_size, Register new_pp);
+  void EnterDartFrame(intptr_t frame_size, Register new_pp = kNoRegister);
   void LeaveDartFrame(RestorePP restore_pp = kRestoreCallerPP);
 
   // Set up a Dart frame for a function compiled for on-stack replacement.
diff --git a/runtime/vm/compiler/assembler/assembler_x64_test.cc b/runtime/vm/compiler/assembler/assembler_x64_test.cc
index 9e380a4..92aa14d 100644
--- a/runtime/vm/compiler/assembler/assembler_x64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64_test.cc
@@ -670,6 +670,49 @@
       "ret\n");
 }
 
+struct JumpAddress {
+  uword filler1;
+  uword filler2;
+  uword filler3;
+  uword filler4;
+  uword filler5;
+  uword target;
+  uword filler6;
+  uword filler7;
+  uword filler8;
+};
+static JumpAddress jump_address;
+static uword jump_address_offset;
+
+ASSEMBLER_TEST_GENERATE(JumpAddress, assembler) {
+  __ jmp(Address(CallingConventions::kArg1Reg, OFFSET_OF(JumpAddress, target)));
+  __ int3();
+  __ int3();
+  __ int3();
+  __ int3();
+  __ int3();
+  jump_address_offset = __ CodeSize();
+  __ movl(RAX, Immediate(42));
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(JumpAddress, test) {
+  memset(&jump_address, 0, sizeof(jump_address));
+  jump_address.target = test->entry() + jump_address_offset;
+
+  typedef int (*TestCode)(void*);
+  EXPECT_EQ(42, reinterpret_cast<TestCode>(test->entry())(&jump_address));
+  EXPECT_DISASSEMBLY_NOT_WINDOWS(
+      "jmp [rdi+0x28]\n"
+      "int3\n"
+      "int3\n"
+      "int3\n"
+      "int3\n"
+      "int3\n"
+      "movl rax,0x2a\n"
+      "ret\n");
+}
+
 ASSEMBLER_TEST_GENERATE(Increment, assembler) {
   __ movq(RAX, Immediate(0));
   __ pushq(RAX);
@@ -1085,7 +1128,7 @@
       "ret\n");
 }
 
-ASSEMBLER_TEST_GENERATE(BitScanReverse, assembler) {
+ASSEMBLER_TEST_GENERATE(BitScanReverseTest, assembler) {
   __ pushq(CallingConventions::kArg1Reg);
   __ movq(RCX, Address(RSP, 0));
   __ movq(RAX, Immediate(666));  // Marker for conditional write.
@@ -1094,7 +1137,7 @@
   __ ret();
 }
 
-ASSEMBLER_TEST_RUN(BitScanReverse, test) {
+ASSEMBLER_TEST_RUN(BitScanReverseTest, test) {
   typedef int (*Bsr)(int input);
   Bsr call = reinterpret_cast<Bsr>(test->entry());
   EXPECT_EQ(666, call(0));
@@ -5484,7 +5527,7 @@
       "ret\n");
 }
 
-ASSEMBLER_TEST_GENERATE(BitTest, assembler) {
+ASSEMBLER_TEST_GENERATE(BitTestTest, assembler) {
   __ movq(RAX, Immediate(4));
   __ movq(R11, Immediate(2));
   __ btq(RAX, R11);
@@ -5496,7 +5539,7 @@
   __ ret();
 }
 
-ASSEMBLER_TEST_RUN(BitTest, test) {
+ASSEMBLER_TEST_RUN(BitTestTest, test) {
   typedef int (*BitTest)();
   EXPECT_EQ(1, reinterpret_cast<BitTest>(test->entry())());
   EXPECT_DISASSEMBLY(
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index 8cf7adc..a2fe6a1 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -318,11 +318,24 @@
       ExceptionHandlers::Handle(zone, code.exception_handlers());
   THR_Print("%s}\n", handlers.ToCString());
 
-  if (instructions.unchecked_entrypoint_pc_offset() != 0) {
-    THR_Print("Unchecked entrypoint at offset 0x%" Px "\n",
-              Instructions::UncheckedEntryPoint(instructions.raw()));
-  } else {
-    THR_Print("No unchecked entrypoint.\n");
+  {
+    THR_Print("Entry points for function '%s' {\n", function_fullname);
+    THR_Print("  [code+0x%02" Px "] %" Px " kNormal\n",
+              Code::entry_point_offset(CodeEntryKind::kNormal) - kHeapObjectTag,
+              Instructions::EntryPoint(instructions.raw()));
+    THR_Print(
+        "  [code+0x%02" Px "] %" Px " kUnchecked\n",
+        Code::entry_point_offset(CodeEntryKind::kUnchecked) - kHeapObjectTag,
+        Instructions::UncheckedEntryPoint(instructions.raw()));
+    THR_Print(
+        "  [code+0x%02" Px "] %" Px " kMonomorphic\n",
+        Code::entry_point_offset(CodeEntryKind::kMonomorphic) - kHeapObjectTag,
+        Instructions::MonomorphicEntryPoint(instructions.raw()));
+    THR_Print("  [code+0x%02" Px "] %" Px " kMonomorphicUnchecked\n",
+              Code::entry_point_offset(CodeEntryKind::kMonomorphicUnchecked) -
+                  kHeapObjectTag,
+              Instructions::MonomorphicUncheckedEntryPoint(instructions.raw()));
+    THR_Print("}\n");
   }
 
   {
diff --git a/runtime/vm/compiler/assembler/disassembler_kbc.cc b/runtime/vm/compiler/assembler/disassembler_kbc.cc
index c0b9538..edd8506 100644
--- a/runtime/vm/compiler/assembler/disassembler_kbc.cc
+++ b/runtime/vm/compiler/assembler/disassembler_kbc.cc
@@ -8,6 +8,7 @@
 #include "vm/compiler/assembler/disassembler_kbc.h"
 
 #include "platform/assert.h"
+#include "vm/compiler/frontend/bytecode_reader.h"
 #include "vm/constants_kbc.h"
 #include "vm/cpu.h"
 #include "vm/instructions.h"
@@ -15,19 +16,23 @@
 namespace dart {
 
 static const char* kOpcodeNames[] = {
-#define BYTECODE_NAME(name, encoding, op1, op2, op3) #name,
+#define BYTECODE_NAME(name, encoding, kind, op1, op2, op3) #name,
     KERNEL_BYTECODES_LIST(BYTECODE_NAME)
 #undef BYTECODE_NAME
 };
 
 static const size_t kOpcodeCount =
     sizeof(kOpcodeNames) / sizeof(kOpcodeNames[0]);
+static_assert(kOpcodeCount <= 256, "Opcode should fit into a byte");
 
 typedef void (*BytecodeFormatter)(char* buffer,
                                   intptr_t size,
-                                  uword pc,
-                                  uint32_t bc);
-typedef void (*Fmt)(char** buf, intptr_t* size, uword pc, int32_t value);
+                                  KernelBytecode::Opcode opcode,
+                                  const KBCInstr* instr);
+typedef void (*Fmt)(char** buf,
+                    intptr_t* size,
+                    const KBCInstr* instr,
+                    int32_t value);
 
 template <typename ValueType>
 void FormatOperand(char** buf,
@@ -43,35 +48,53 @@
   }
 }
 
-static void Fmt___(char** buf, intptr_t* size, uword pc, int32_t value) {}
+static void Fmt___(char** buf,
+                   intptr_t* size,
+                   const KBCInstr* instr,
+                   int32_t value) {}
 
-static void Fmttgt(char** buf, intptr_t* size, uword pc, int32_t value) {
-  FormatOperand(buf, size, "-> %" Px, pc + (value << 2));
+static void Fmttgt(char** buf,
+                   intptr_t* size,
+                   const KBCInstr* instr,
+                   int32_t value) {
+  FormatOperand(buf, size, "-> %" Px, instr + value);
 }
 
-static void Fmtlit(char** buf, intptr_t* size, uword pc, int32_t value) {
+static void Fmtlit(char** buf,
+                   intptr_t* size,
+                   const KBCInstr* instr,
+                   int32_t value) {
   FormatOperand(buf, size, "k%d", value);
 }
 
-static void Fmtreg(char** buf, intptr_t* size, uword pc, int32_t value) {
+static void Fmtreg(char** buf,
+                   intptr_t* size,
+                   const KBCInstr* instr,
+                   int32_t value) {
   FormatOperand(buf, size, "r%d", value);
 }
 
-static void Fmtxeg(char** buf, intptr_t* size, uword pc, int32_t value) {
+static void Fmtxeg(char** buf,
+                   intptr_t* size,
+                   const KBCInstr* instr,
+                   int32_t value) {
   if (value < 0) {
     FormatOperand(buf, size, "FP[%d]", value);
   } else {
-    Fmtreg(buf, size, pc, value);
+    Fmtreg(buf, size, instr, value);
   }
 }
 
-static void Fmtnum(char** buf, intptr_t* size, uword pc, int32_t value) {
+static void Fmtnum(char** buf,
+                   intptr_t* size,
+                   const KBCInstr* instr,
+                   int32_t value) {
   FormatOperand(buf, size, "#%d", value);
 }
 
 static void Apply(char** buf,
                   intptr_t* size,
-                  uword pc,
+                  const KBCInstr* instr,
                   Fmt fmt,
                   int32_t value,
                   const char* suffix) {
@@ -79,7 +102,7 @@
     return;
   }
 
-  fmt(buf, size, pc, value);
+  fmt(buf, size, instr, value);
   if (*size > 0) {
     FormatOperand(buf, size, "%s", suffix);
   }
@@ -87,154 +110,209 @@
 
 static void Format0(char* buf,
                     intptr_t size,
-                    uword pc,
-                    uint32_t op,
+                    KernelBytecode::Opcode opcode,
+                    const KBCInstr* instr,
                     Fmt op1,
                     Fmt op2,
                     Fmt op3) {}
 
-static void FormatT(char* buf,
-                    intptr_t size,
-                    uword pc,
-                    uint32_t op,
-                    Fmt op1,
-                    Fmt op2,
-                    Fmt op3) {
-  const int32_t x = static_cast<int32_t>(op) >> 8;
-  Apply(&buf, &size, pc, op1, x, "");
-}
-
 static void FormatA(char* buf,
                     intptr_t size,
-                    uword pc,
-                    uint32_t op,
+                    KernelBytecode::Opcode opcode,
+                    const KBCInstr* instr,
                     Fmt op1,
                     Fmt op2,
                     Fmt op3) {
-  const int32_t a = (op & 0xFF00) >> 8;
-  Apply(&buf, &size, pc, op1, a, "");
-}
-
-static void FormatA_D(char* buf,
-                      intptr_t size,
-                      uword pc,
-                      uint32_t op,
-                      Fmt op1,
-                      Fmt op2,
-                      Fmt op3) {
-  const int32_t a = (op & 0xFF00) >> 8;
-  const int32_t bc = op >> 16;
-  Apply(&buf, &size, pc, op1, a, ", ");
-  Apply(&buf, &size, pc, op2, bc, "");
-}
-
-static void FormatA_X(char* buf,
-                      intptr_t size,
-                      uword pc,
-                      uint32_t op,
-                      Fmt op1,
-                      Fmt op2,
-                      Fmt op3) {
-  const int32_t a = (op & 0xFF00) >> 8;
-  const int32_t bc = static_cast<int32_t>(op) >> 16;
-  Apply(&buf, &size, pc, op1, a, ", ");
-  Apply(&buf, &size, pc, op2, bc, "");
-}
-
-static void FormatX(char* buf,
-                    intptr_t size,
-                    uword pc,
-                    uint32_t op,
-                    Fmt op1,
-                    Fmt op2,
-                    Fmt op3) {
-  const int32_t bc = static_cast<int32_t>(op) >> 16;
-  Apply(&buf, &size, pc, op1, bc, "");
+  const int32_t a = KernelBytecode::DecodeA(instr);
+  Apply(&buf, &size, instr, op1, a, "");
 }
 
 static void FormatD(char* buf,
                     intptr_t size,
-                    uword pc,
-                    uint32_t op,
+                    KernelBytecode::Opcode opcode,
+                    const KBCInstr* instr,
                     Fmt op1,
                     Fmt op2,
                     Fmt op3) {
-  const int32_t bc = op >> 16;
-  Apply(&buf, &size, pc, op1, bc, "");
+  const int32_t bc = KernelBytecode::DecodeD(instr);
+  Apply(&buf, &size, instr, op1, bc, "");
+}
+
+static void FormatX(char* buf,
+                    intptr_t size,
+                    KernelBytecode::Opcode opcode,
+                    const KBCInstr* instr,
+                    Fmt op1,
+                    Fmt op2,
+                    Fmt op3) {
+  const int32_t bc = KernelBytecode::DecodeX(instr);
+  Apply(&buf, &size, instr, op1, bc, "");
+}
+
+static void FormatT(char* buf,
+                    intptr_t size,
+                    KernelBytecode::Opcode opcode,
+                    const KBCInstr* instr,
+                    Fmt op1,
+                    Fmt op2,
+                    Fmt op3) {
+  const int32_t x = KernelBytecode::DecodeT(instr);
+  Apply(&buf, &size, instr, op1, x, "");
+}
+
+static void FormatA_D(char* buf,
+                      intptr_t size,
+                      KernelBytecode::Opcode opcode,
+                      const KBCInstr* instr,
+                      Fmt op1,
+                      Fmt op2,
+                      Fmt op3) {
+  const int32_t a = KernelBytecode::DecodeA(instr);
+  const int32_t bc = KernelBytecode::DecodeD(instr);
+  Apply(&buf, &size, instr, op1, a, ", ");
+  Apply(&buf, &size, instr, op2, bc, "");
+}
+
+static void FormatA_X(char* buf,
+                      intptr_t size,
+                      KernelBytecode::Opcode opcode,
+                      const KBCInstr* instr,
+                      Fmt op1,
+                      Fmt op2,
+                      Fmt op3) {
+  const int32_t a = KernelBytecode::DecodeA(instr);
+  const int32_t bc = KernelBytecode::DecodeX(instr);
+  Apply(&buf, &size, instr, op1, a, ", ");
+  Apply(&buf, &size, instr, op2, bc, "");
+}
+
+static void FormatA_E(char* buf,
+                      intptr_t size,
+                      KernelBytecode::Opcode opcode,
+                      const KBCInstr* instr,
+                      Fmt op1,
+                      Fmt op2,
+                      Fmt op3) {
+  const int32_t a = KernelBytecode::DecodeA(instr);
+  const int32_t e = KernelBytecode::DecodeE(instr);
+  Apply(&buf, &size, instr, op1, a, ", ");
+  Apply(&buf, &size, instr, op2, e, "");
+}
+
+static void FormatA_Y(char* buf,
+                      intptr_t size,
+                      KernelBytecode::Opcode opcode,
+                      const KBCInstr* instr,
+                      Fmt op1,
+                      Fmt op2,
+                      Fmt op3) {
+  const int32_t a = KernelBytecode::DecodeA(instr);
+  const int32_t y = KernelBytecode::DecodeY(instr);
+  Apply(&buf, &size, instr, op1, a, ", ");
+  Apply(&buf, &size, instr, op2, y, "");
+}
+
+static void FormatD_F(char* buf,
+                      intptr_t size,
+                      KernelBytecode::Opcode opcode,
+                      const KBCInstr* instr,
+                      Fmt op1,
+                      Fmt op2,
+                      Fmt op3) {
+  const int32_t d = KernelBytecode::DecodeD(instr);
+  const int32_t f = KernelBytecode::DecodeF(instr);
+  Apply(&buf, &size, instr, op1, d, ", ");
+  Apply(&buf, &size, instr, op2, f, "");
 }
 
 static void FormatA_B_C(char* buf,
                         intptr_t size,
-                        uword pc,
-                        uint32_t op,
+                        KernelBytecode::Opcode opcode,
+                        const KBCInstr* instr,
                         Fmt op1,
                         Fmt op2,
                         Fmt op3) {
-  const int32_t a = (op >> 8) & 0xFF;
-  const int32_t b = (op >> 16) & 0xFF;
-  const int32_t c = (op >> 24) & 0xFF;
-  Apply(&buf, &size, pc, op1, a, ", ");
-  Apply(&buf, &size, pc, op2, b, ", ");
-  Apply(&buf, &size, pc, op3, c, "");
+  const int32_t a = KernelBytecode::DecodeA(instr);
+  const int32_t b = KernelBytecode::DecodeB(instr);
+  const int32_t c = KernelBytecode::DecodeC(instr);
+  Apply(&buf, &size, instr, op1, a, ", ");
+  Apply(&buf, &size, instr, op2, b, ", ");
+  Apply(&buf, &size, instr, op3, c, "");
 }
 
-// TODO(alexmarkov) This format is currently unused. Restore it if needed, or
-// remove it once bytecode instruction set is finalized.
-//
-// static void FormatA_B_Y(char* buf,
-//                        intptr_t size,
-//                        uword pc,
-//                        uint32_t op,
-//                        Fmt op1,
-//                        Fmt op2,
-//                        Fmt op3) {
-//  const int32_t a = (op >> 8) & 0xFF;
-//  const int32_t b = (op >> 16) & 0xFF;
-//  const int32_t y = static_cast<int8_t>((op >> 24) & 0xFF);
-//  Apply(&buf, &size, pc, op1, a, ", ");
-//  Apply(&buf, &size, pc, op2, b, ", ");
-//  Apply(&buf, &size, pc, op3, y, "");
-// }
-
-#define BYTECODE_FORMATTER(name, encoding, op1, op2, op3)                      \
-  static void Format##name(char* buf, intptr_t size, uword pc, uint32_t op) {  \
-    Format##encoding(buf, size, pc, op, Fmt##op1, Fmt##op2, Fmt##op3);         \
+#define BYTECODE_FORMATTER(name, encoding, kind, op1, op2, op3)                \
+  static void Format##name(char* buf, intptr_t size,                           \
+                           KernelBytecode::Opcode opcode,                      \
+                           const KBCInstr* instr) {                            \
+    Format##encoding(buf, size, opcode, instr, Fmt##op1, Fmt##op2, Fmt##op3);  \
   }
 KERNEL_BYTECODES_LIST(BYTECODE_FORMATTER)
 #undef BYTECODE_FORMATTER
 
 static const BytecodeFormatter kFormatters[] = {
-#define BYTECODE_FORMATTER(name, encoding, op1, op2, op3) &Format##name,
+#define BYTECODE_FORMATTER(name, encoding, kind, op1, op2, op3) &Format##name,
     KERNEL_BYTECODES_LIST(BYTECODE_FORMATTER)
 #undef BYTECODE_FORMATTER
 };
 
-static bool HasLoadFromPool(KBCInstr instr) {
+static intptr_t GetConstantPoolIndex(const KBCInstr* instr) {
   switch (KernelBytecode::DecodeOpcode(instr)) {
+    case KernelBytecode::kLoadConstant_Old:
+    case KernelBytecode::kInstantiateTypeArgumentsTOS_Old:
+    case KernelBytecode::kAssertAssignable_Old:
+    case KernelBytecode::kPushConstant_Old:
+    case KernelBytecode::kStoreStaticTOS_Old:
+    case KernelBytecode::kPushStatic_Old:
+    case KernelBytecode::kAllocate_Old:
+    case KernelBytecode::kAllocateClosure_Old:
+    case KernelBytecode::kInstantiateType_Old:
+    case KernelBytecode::kDirectCall_Old:
+    case KernelBytecode::kInterfaceCall_Old:
+    case KernelBytecode::kUncheckedInterfaceCall_Old:
+    case KernelBytecode::kDynamicCall_Old:
+      return KernelBytecode::DecodeD(instr);
+
     case KernelBytecode::kLoadConstant:
-    case KernelBytecode::kPushConstant:
-    case KernelBytecode::kIndirectStaticCall:
-    case KernelBytecode::kInterfaceCall:
-    case KernelBytecode::kUncheckedInterfaceCall:
-    case KernelBytecode::kDynamicCall:
-    case KernelBytecode::kStoreStaticTOS:
-    case KernelBytecode::kPushStatic:
-    case KernelBytecode::kAllocate:
-    case KernelBytecode::kInstantiateType:
+    case KernelBytecode::kLoadConstant_Wide:
     case KernelBytecode::kInstantiateTypeArgumentsTOS:
+    case KernelBytecode::kInstantiateTypeArgumentsTOS_Wide:
     case KernelBytecode::kAssertAssignable:
-      return true;
+    case KernelBytecode::kAssertAssignable_Wide:
+      return KernelBytecode::DecodeE(instr);
+
+    case KernelBytecode::kPushConstant:
+    case KernelBytecode::kPushConstant_Wide:
+    case KernelBytecode::kStoreStaticTOS:
+    case KernelBytecode::kStoreStaticTOS_Wide:
+    case KernelBytecode::kPushStatic:
+    case KernelBytecode::kPushStatic_Wide:
+    case KernelBytecode::kAllocate:
+    case KernelBytecode::kAllocate_Wide:
+    case KernelBytecode::kAllocateClosure:
+    case KernelBytecode::kAllocateClosure_Wide:
+    case KernelBytecode::kInstantiateType:
+    case KernelBytecode::kInstantiateType_Wide:
+    case KernelBytecode::kDirectCall:
+    case KernelBytecode::kDirectCall_Wide:
+    case KernelBytecode::kInterfaceCall:
+    case KernelBytecode::kInterfaceCall_Wide:
+    case KernelBytecode::kUncheckedInterfaceCall:
+    case KernelBytecode::kUncheckedInterfaceCall_Wide:
+    case KernelBytecode::kDynamicCall:
+    case KernelBytecode::kDynamicCall_Wide:
+      return KernelBytecode::DecodeD(instr);
+
     default:
-      return false;
+      return -1;
   }
 }
 
 static bool GetLoadedObjectAt(uword pc,
                               const ObjectPool& object_pool,
                               Object* obj) {
-  KBCInstr instr = KernelBytecode::At(pc);
-  if (HasLoadFromPool(instr)) {
-    uint16_t index = KernelBytecode::DecodeD(instr);
+  const KBCInstr* instr = reinterpret_cast<const KBCInstr*>(pc);
+  const intptr_t index = GetConstantPoolIndex(instr);
+  if (index >= 0) {
     if (object_pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject) {
       *obj = object_pool.ObjectAt(index);
       return true;
@@ -251,19 +329,25 @@
                                                    const Bytecode& bytecode,
                                                    Object** object,
                                                    uword pc) {
-  const uint32_t instr = *reinterpret_cast<uint32_t*>(pc);
-  const uint8_t opcode = instr & 0xFF;
-  ASSERT(opcode < kOpcodeCount);
+  const KBCInstr* instr = reinterpret_cast<const KBCInstr*>(pc);
+  const KernelBytecode::Opcode opcode = KernelBytecode::DecodeOpcode(instr);
+  const intptr_t instr_size = KernelBytecode::kInstructionSize[opcode];
+
   size_t name_size =
       Utils::SNPrint(human_buffer, human_size, "%-10s\t", kOpcodeNames[opcode]);
-
   human_buffer += name_size;
   human_size -= name_size;
-  kFormatters[opcode](human_buffer, human_size, pc, instr);
+  kFormatters[opcode](human_buffer, human_size, opcode, instr);
 
-  Utils::SNPrint(hex_buffer, hex_size, "%08x", instr);
+  const intptr_t kCharactersPerByte = 3;
+  if (hex_size > instr_size * kCharactersPerByte) {
+    for (intptr_t i = 0; i < instr_size; ++i) {
+      Utils::SNPrint(hex_buffer + (i * kCharactersPerByte),
+                     hex_size - (i * kCharactersPerByte), " %02x", instr[i]);
+    }
+  }
   if (out_instr_size) {
-    *out_instr_size = sizeof(uint32_t);
+    *out_instr_size = instr_size;
   }
 
   *object = NULL;
@@ -325,10 +409,35 @@
       PcDescriptors::Handle(zone, bytecode.pc_descriptors());
   THR_Print("%s}\n", descriptors.ToCString());
 
+  if (bytecode.HasSourcePositions()) {
+    THR_Print("Source positions for function '%s' {\n", function_fullname);
+    // 4 bits per hex digit + 2 for "0x".
+    const int addr_width = (kBitsPerWord / 4) + 2;
+    // "*" in a printf format specifier tells it to read the field width from
+    // the printf argument list.
+    THR_Print("%-*s\ttok-ix\n", addr_width, "pc");
+    kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
+    while (iter.MoveNext()) {
+      THR_Print("%#-*" Px "\t%s\n", addr_width,
+                bytecode.PayloadStart() + iter.PcOffset(),
+                iter.TokenPos().ToCString());
+    }
+    THR_Print("}\n");
+  }
+
   THR_Print("Exception Handlers for function '%s' {\n", function_fullname);
   const ExceptionHandlers& handlers =
       ExceptionHandlers::Handle(zone, bytecode.exception_handlers());
   THR_Print("%s}\n", handlers.ToCString());
+
+  if (FLAG_print_variable_descriptors) {
+    THR_Print("Local variable descriptors for function '%s' {\n",
+              function_fullname);
+    const auto& var_descriptors =
+        LocalVarDescriptors::Handle(zone, bytecode.GetLocalVarDescriptors());
+    THR_Print("%s\n}\n", var_descriptors.ToCString());
+  }
+
 #else
   UNREACHABLE();
 #endif
diff --git a/runtime/vm/compiler/backend/block_builder.h b/runtime/vm/compiler/backend/block_builder.h
index 22557d7..94b566a 100644
--- a/runtime/vm/compiler/backend/block_builder.h
+++ b/runtime/vm/compiler/backend/block_builder.h
@@ -54,8 +54,9 @@
   }
 
   Definition* AddParameter(intptr_t index, bool with_frame) {
-    return AddToInitialDefinitions(new ParameterInstr(
-        index, flow_graph_->graph_entry(), with_frame ? FPREG : SPREG));
+    auto normal_entry = flow_graph_->graph_entry()->normal_entry();
+    return AddToInitialDefinitions(
+        new ParameterInstr(index, normal_entry, with_frame ? FPREG : SPREG));
   }
 
   TokenPosition TokenPos() { return flow_graph_->function().token_pos(); }
diff --git a/runtime/vm/compiler/backend/block_scheduler.cc b/runtime/vm/compiler/backend/block_scheduler.cc
index af57dfd..51eceea 100644
--- a/runtime/vm/compiler/backend/block_scheduler.cc
+++ b/runtime/vm/compiler/backend/block_scheduler.cc
@@ -219,13 +219,23 @@
     Union(&chains, source_chain, target_chain);
   }
 
+  // Ensure the checked entry remains first to avoid needing another offset on
+  // Instructions, compare Code::EntryPoint.
+  GraphEntryInstr* graph_entry = flow_graph()->graph_entry();
+  flow_graph()->CodegenBlockOrder(true)->Add(graph_entry);
+  FunctionEntryInstr* checked_entry = graph_entry->normal_entry();
+  if (checked_entry != nullptr) {
+    flow_graph()->CodegenBlockOrder(true)->Add(checked_entry);
+  }
   // Build a new block order.  Emit each chain when its first block occurs
   // in the original reverse postorder ordering (which gives a topological
   // sort of the blocks).
   for (intptr_t i = block_count - 1; i >= 0; --i) {
     if (chains[i]->first->block == flow_graph()->postorder()[i]) {
       for (Link* link = chains[i]->first; link != NULL; link = link->next) {
-        flow_graph()->CodegenBlockOrder(true)->Add(link->block);
+        if ((link->block != checked_entry) && (link->block != graph_entry)) {
+          flow_graph()->CodegenBlockOrder(true)->Add(link->block);
+        }
       }
     }
   }
@@ -274,20 +284,20 @@
     }
   }
 
-  // Emit code in reverse postorder but move any throwing blocks to the very
-  // end.
+  // Emit code in reverse postorder but move any throwing blocks (except the
+  // function entry, which needs to come first) to the very end.
   auto& codegen_order = *flow_graph()->CodegenBlockOrder(true);
   for (intptr_t i = 0; i < block_count; ++i) {
     auto block = reverse_postorder[i];
     const intptr_t preorder_nr = block->preorder_number();
-    if (!is_terminating[preorder_nr]) {
+    if (!is_terminating[preorder_nr] || block->IsFunctionEntry()) {
       codegen_order.Add(block);
     }
   }
   for (intptr_t i = 0; i < block_count; ++i) {
     auto block = reverse_postorder[i];
     const intptr_t preorder_nr = block->preorder_number();
-    if (is_terminating[preorder_nr]) {
+    if (is_terminating[preorder_nr] && !block->IsFunctionEntry()) {
       codegen_order.Add(block);
     }
   }
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index d27b6e2..dc78a0e 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -142,6 +142,10 @@
   }
 }
 
+void ConstantPropagator::VisitNativeEntry(NativeEntryInstr* block) {
+  VisitFunctionEntry(block);
+}
+
 void ConstantPropagator::VisitOsrEntry(OsrEntryInstr* block) {
   for (auto def : *block->initial_definitions()) {
     def->Accept(this);
@@ -192,6 +196,10 @@
   // Nothing to do.
 }
 
+void ConstantPropagator::VisitNativeReturn(NativeReturnInstr* instr) {
+  // Nothing to do.
+}
+
 void ConstantPropagator::VisitThrow(ThrowInstr* instr) {
   // Nothing to do.
 }
@@ -365,6 +373,10 @@
   SetValue(instr, non_constant_);
 }
 
+void ConstantPropagator::VisitNativeParameter(NativeParameterInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
 void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) {
   if (SetValue(instr, instr->value()->definition()->constant_value())) {
     // The worklist implementation breaks down around push arguments,
@@ -844,12 +856,20 @@
 }
 
 void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) {
+  // This first part duplicates the work done in LoadClassIdInstr::Canonicalize,
+  // which replaces uses of LoadClassIdInstr where the object has a concrete
+  // type with a Constant. Canonicalize runs before the ConstantPropagation
+  // pass, so if that was all, this wouldn't be needed.
+  //
+  // However, the ConstantPropagator also runs as part of OptimizeBranches, and
+  // TypePropagation runs between it and the previous Canonicalize. Thus, the
+  // type may have become concrete and we should take that into account. Not
+  // doing so led to some benchmark regressions.
   intptr_t cid = instr->object()->Type()->ToCid();
   if (cid != kDynamicCid) {
     SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid)));
     return;
   }
-
   const Object& object = instr->object()->definition()->constant_value();
   if (IsConstant(object)) {
     cid = object.GetClassId();
@@ -1272,8 +1292,8 @@
   }
 }
 
-void ConstantPropagator::VisitCaseInsensitiveCompareUC16(
-    CaseInsensitiveCompareUC16Instr* instr) {
+void ConstantPropagator::VisitCaseInsensitiveCompare(
+    CaseInsensitiveCompareInstr* instr) {
   SetValue(instr, non_constant_);
 }
 
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 40eac02..0a590a3 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -27,7 +27,6 @@
 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass.");
 #endif
 DEFINE_FLAG(bool, prune_dead_locals, true, "optimize dead locals away");
-DECLARE_FLAG(bool, verify_compiler);
 
 // Quick access to the current zone.
 #define Z (zone())
@@ -154,6 +153,9 @@
 void FlowGraph::AddToInitialDefinitions(BlockEntryWithInitialDefs* entry,
                                         Definition* defn) {
   defn->set_previous(entry);
+  if (auto par = defn->AsParameter()) {
+    par->set_block(entry);  // set cached block
+  }
   entry->initial_definitions()->Add(defn);
 }
 
@@ -299,80 +301,6 @@
   if (changed) DiscoverBlocks();
 }
 
-// Debugging code to verify the construction of use lists.
-static intptr_t MembershipCount(Value* use, Value* list) {
-  intptr_t count = 0;
-  while (list != NULL) {
-    if (list == use) ++count;
-    list = list->next_use();
-  }
-  return count;
-}
-
-static void VerifyUseListsInInstruction(Instruction* instr) {
-  ASSERT(instr != NULL);
-  ASSERT(!instr->IsJoinEntry());
-  for (intptr_t i = 0; i < instr->InputCount(); ++i) {
-    Value* use = instr->InputAt(i);
-    ASSERT(use->definition() != NULL);
-    ASSERT((use->definition() != instr) || use->definition()->IsPhi() ||
-           use->definition()->IsMaterializeObject());
-    ASSERT(use->instruction() == instr);
-    ASSERT(use->use_index() == i);
-    ASSERT(!FLAG_verify_compiler ||
-           (1 == MembershipCount(use, use->definition()->input_use_list())));
-  }
-  if (instr->env() != NULL) {
-    intptr_t use_index = 0;
-    for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
-      Value* use = it.CurrentValue();
-      ASSERT(use->definition() != NULL);
-      ASSERT((use->definition() != instr) || use->definition()->IsPhi());
-      ASSERT(use->instruction() == instr);
-      ASSERT(use->use_index() == use_index++);
-      ASSERT(!FLAG_verify_compiler ||
-             (1 == MembershipCount(use, use->definition()->env_use_list())));
-    }
-  }
-  Definition* defn = instr->AsDefinition();
-  if (defn != NULL) {
-    // Used definitions must have an SSA name.  We use the name to index
-    // into bit vectors during analyses.  Some definitions without SSA names
-    // (e.g., PushArgument) have environment uses.
-    ASSERT((defn->input_use_list() == NULL) || defn->HasSSATemp());
-    Value* prev = NULL;
-    Value* curr = defn->input_use_list();
-    while (curr != NULL) {
-      ASSERT(prev == curr->previous_use());
-      ASSERT(defn == curr->definition());
-      Instruction* instr = curr->instruction();
-      // The instruction should not be removed from the graph.
-      ASSERT((instr->IsPhi() && instr->AsPhi()->is_alive()) ||
-             (instr->previous() != NULL));
-      ASSERT(curr == instr->InputAt(curr->use_index()));
-      prev = curr;
-      curr = curr->next_use();
-    }
-
-    prev = NULL;
-    curr = defn->env_use_list();
-    while (curr != NULL) {
-      ASSERT(prev == curr->previous_use());
-      ASSERT(defn == curr->definition());
-      Instruction* instr = curr->instruction();
-      ASSERT(curr == instr->env()->ValueAtUseIndex(curr->use_index()));
-      // BlockEntry instructions have environments attached to them but
-      // have no reliable way to verify if they are still in the graph.
-      // Thus we just assume they are.
-      ASSERT(instr->IsBlockEntry() ||
-             (instr->IsPhi() && instr->AsPhi()->is_alive()) ||
-             (instr->previous() != NULL));
-      prev = curr;
-      curr = curr->next_use();
-    }
-  }
-}
-
 void FlowGraph::ComputeIsReceiverRecursive(
     PhiInstr* phi,
     GrowableArray<PhiInstr*>* unmark) const {
@@ -574,31 +502,6 @@
   InsertBefore(call, guard, call->env(), FlowGraph::kEffect);
 }
 
-bool FlowGraph::VerifyUseLists() {
-  // Verify the initial definitions.
-  for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) {
-    VerifyUseListsInInstruction((*graph_entry_->initial_definitions())[i]);
-  }
-
-  // Verify phis in join entries and the instructions in each block.
-  for (intptr_t i = 0; i < preorder_.length(); ++i) {
-    BlockEntryInstr* entry = preorder_[i];
-    JoinEntryInstr* join = entry->AsJoinEntry();
-    if (join != NULL) {
-      for (PhiIterator it(join); !it.Done(); it.Advance()) {
-        PhiInstr* phi = it.Current();
-        ASSERT(phi != NULL);
-        VerifyUseListsInInstruction(phi);
-      }
-    }
-    for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
-      VerifyUseListsInInstruction(it.Current());
-    }
-  }
-
-  return true;  // Return true so we can ASSERT validation.
-}
-
 // Verify that a redefinition dominates all uses of the redefined value.
 bool FlowGraph::VerifyRedefinitions() {
   for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
@@ -853,10 +756,12 @@
     // to the kill set.
     const bool is_function_entry = block->IsFunctionEntry();
     const bool is_osr_entry = block->IsOsrEntry();
-    if (is_function_entry || is_osr_entry || block->IsCatchBlockEntry()) {
+    const bool is_catch_block_entry = block->IsCatchBlockEntry();
+    if (is_function_entry || is_osr_entry || is_catch_block_entry) {
       const intptr_t parameter_count =
-          is_osr_entry ? flow_graph_->variable_count()
-                       : flow_graph_->num_direct_parameters();
+          (is_osr_entry || is_catch_block_entry)
+              ? flow_graph_->variable_count()
+              : flow_graph_->num_direct_parameters();
       for (intptr_t i = 0; i < parameter_count; ++i) {
         live_in->Remove(i);
         kill->Add(i);
@@ -1240,7 +1145,7 @@
 
     param->set_ssa_temp_index(alloc_ssa_temp_index());  // New SSA temp.
     (*env)[i] = param;
-    catch_entry->initial_definitions()->Add(param);
+    AddToInitialDefinitions(catch_entry, param);
   }
 }
 
@@ -1595,11 +1500,11 @@
                                                  Definition* original,
                                                  CompileType compile_type) {
   RedefinitionInstr* first = prev->next()->AsRedefinition();
-  if (first != NULL && (first->constrained_type() != NULL)) {
+  if (first != nullptr && (first->constrained_type() != nullptr)) {
     if ((first->value()->definition() == original) &&
         first->constrained_type()->IsEqualTo(&compile_type)) {
       // Already redefined. Do nothing.
-      return NULL;
+      return nullptr;
     }
   }
   RedefinitionInstr* redef = new RedefinitionInstr(new Value(original));
@@ -1610,8 +1515,17 @@
     redef->set_constrained_type(new CompileType(compile_type));
   }
 
-  InsertAfter(prev, redef, NULL, FlowGraph::kValue);
+  InsertAfter(prev, redef, nullptr, FlowGraph::kValue);
   RenameDominatedUses(original, redef, redef);
+
+  if (redef->input_use_list() == nullptr) {
+    // There are no dominated uses, so the newly added Redefinition is useless.
+    // Remove Redefinition to avoid interfering with
+    // BranchSimplifier::Simplify which needs empty blocks.
+    redef->RemoveFromGraph();
+    return nullptr;
+  }
+
   return redef;
 }
 
diff --git a/runtime/vm/compiler/backend/flow_graph.h b/runtime/vm/compiler/backend/flow_graph.h
index 67f47ce..abbfcac 100644
--- a/runtime/vm/compiler/backend/flow_graph.h
+++ b/runtime/vm/compiler/backend/flow_graph.h
@@ -264,8 +264,7 @@
   void ComputeSSA(intptr_t next_virtual_register_number,
                   ZoneGrowableArray<Definition*>* inlining_parameters);
 
-  // Verification methods for debugging.
-  bool VerifyUseLists();
+  // Verification method for debugging.
   bool VerifyRedefinitions();
 
   void DiscoverBlocks();
diff --git a/runtime/vm/compiler/backend/flow_graph_checker.cc b/runtime/vm/compiler/backend/flow_graph_checker.cc
index 3b9481f..4660d82 100644
--- a/runtime/vm/compiler/backend/flow_graph_checker.cc
+++ b/runtime/vm/compiler/backend/flow_graph_checker.cc
@@ -13,6 +13,22 @@
 
 namespace dart {
 
+DECLARE_FLAG(bool, trace_compiler);
+
+DEFINE_FLAG(int,
+            verify_definitions_threshold,
+            250,
+            "Definition count threshold for extensive instruction checks");
+
+// Returns true for the "optimized out" and "null" constant.
+static bool IsSpecialConstant(Definition* def) {
+  if (auto c = def->AsConstant()) {
+    return c->value().raw() == Symbols::OptimizedOut().raw() ||
+           c->value().raw() == Object::ZoneHandle().raw();
+  }
+  return false;
+}
+
 // Returns true if block is a predecessor of succ.
 static bool IsPred(BlockEntryInstr* block, BlockEntryInstr* succ) {
   for (intptr_t i = 0, n = succ->PredecessorCount(); i < n; ++i) {
@@ -44,6 +60,42 @@
   return false;
 }
 
+// Returns true if instruction appears in use list.
+static bool IsInUseList(Value* use, Instruction* instruction) {
+  for (; use != nullptr; use = use->next_use()) {
+    if (use->instruction() == instruction) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Returns true if definition dominates instruction. Note that this
+// helper is required to account for some situations that are not
+// accounted for in the IR methods that compute dominance.
+static bool DefDominatesUse(Definition* def, Instruction* instruction) {
+  if (instruction->IsPhi()) {
+    // A phi use is not necessarily dominated by a definition.
+    // Proper dominance relation on the input values of Phis is
+    // checked by the Phi visitor below.
+    return true;
+  } else if (def->IsMaterializeObject() || instruction->IsMaterializeObject()) {
+    // These instructions reside outside the IR.
+    return true;
+  } else if (auto entry =
+                 instruction->GetBlock()->AsBlockEntryWithInitialDefs()) {
+    // An initial definition in the same block.
+    // TODO(ajcbik): use an initial def too?
+    for (auto idef : *entry->initial_definitions()) {
+      if (idef == def) {
+        return true;
+      }
+    }
+  }
+  // Use the standard IR method for dominance.
+  return instruction->IsDominatedBy(def);
+}
+
 // Returns true if instruction forces control flow.
 static bool IsControlFlow(Instruction* instruction) {
   return instruction->IsBranch() || instruction->IsGoto() ||
@@ -97,24 +149,45 @@
     // Visit all instructions in this block.
     VisitInstructions(block);
   }
-
-  // Flow graph built-in verification.
-  // TODO(ajcbik): migrate actual code into checker too?
-  ASSERT(flow_graph_->VerifyUseLists());
 }
 
 void FlowGraphChecker::VisitInstructions(BlockEntryInstr* block) {
   // To avoid excessive runtimes, skip the instructions check if there
   // are many definitions (as happens in e.g. an initialization block).
-  if (flow_graph_->current_ssa_temp_index() > 10000) {
+  if (flow_graph_->current_ssa_temp_index() >
+      FLAG_verify_definitions_threshold) {
     return;
   }
   // Give all visitors quick access.
   current_block_ = block;
+  // Visit initial definitions.
+  if (auto entry = block->AsBlockEntryWithInitialDefs()) {
+    for (auto def : *entry->initial_definitions()) {
+      ASSERT(def != nullptr);
+      ASSERT(def->IsConstant() || def->IsParameter() ||
+             def->IsSpecialParameter());
+      // Special constants reside outside the IR.
+      if (IsSpecialConstant(def)) continue;
+      // Make sure block lookup agrees.
+      ASSERT(def->GetBlock() == entry);
+      // Initial definitions are partially linked into graph.
+      ASSERT(def->next() == nullptr);
+      ASSERT(def->previous() == entry);
+      // Visit the initial definition as instruction.
+      VisitInstruction(def);
+    }
+  }
   // Visit phis in join.
-  if (auto join_entry = block->AsJoinEntry()) {
-    for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
-      VisitInstruction(it.Current());
+  if (auto entry = block->AsJoinEntry()) {
+    for (PhiIterator it(entry); !it.Done(); it.Advance()) {
+      PhiInstr* phi = it.Current();
+      // Make sure block lookup agrees.
+      ASSERT(phi->GetBlock() == entry);
+      // Phis are never linked into graph.
+      ASSERT(phi->next() == nullptr);
+      ASSERT(phi->previous() == nullptr);
+      // Visit the phi as instruction.
+      VisitInstruction(phi);
     }
   }
   // Visit regular instructions.
@@ -132,9 +205,11 @@
     prev = instruction;
     // Make sure control flow makes sense.
     ASSERT(IsControlFlow(instruction) == (instruction == last));
-    // Perform instruction specific checks.
+    ASSERT(!instruction->IsPhi());
+    // Visit the instruction.
     VisitInstruction(instruction);
   }
+  ASSERT(prev->next() == nullptr);
   ASSERT(prev == last);
   // Make sure loop information, when up-to-date, agrees.
   if (flow_graph_->loop_hierarchy_ != nullptr) {
@@ -146,6 +221,18 @@
 }
 
 void FlowGraphChecker::VisitInstruction(Instruction* instruction) {
+  ASSERT(!instruction->IsBlockEntry());
+  // Check all regular inputs.
+  for (intptr_t i = 0, n = instruction->InputCount(); i < n; ++i) {
+    VisitUseDef(instruction, instruction->InputAt(i), i, /*is_env*/ false);
+  }
+  // Check all environment inputs.
+  intptr_t i = 0;
+  for (Environment::DeepIterator it(instruction->env()); !it.Done();
+       it.Advance()) {
+    VisitUseDef(instruction, it.CurrentValue(), i++, /*is_env*/ true);
+  }
+  // Visit specific instructions (definitions and anything with Visit()).
   if (auto def = instruction->AsDefinition()) {
     VisitDefinition(def);
   }
@@ -153,37 +240,125 @@
 }
 
 void FlowGraphChecker::VisitDefinition(Definition* def) {
-  // Make sure each outgoing use is dominated by this def, or is a
-  // Phi instruction (note that the proper dominance relation on
-  // the input values of Phis are checked by the Phi visitor below).
+  // Used definitions must have an SSA name.
+  ASSERT(def->HasSSATemp() || def->input_use_list() == nullptr);
+  // Check all regular uses.
+  Value* prev = nullptr;
   for (Value* use = def->input_use_list(); use != nullptr;
        use = use->next_use()) {
-    Instruction* use_instr = use->instruction();
-    ASSERT(use_instr != nullptr);
-    ASSERT(use_instr->IsPhi() ||
-           use_instr->IsMaterializeObject() ||  // not in graph
-           use_instr->IsDominatedBy(def));
+    VisitDefUse(def, use, prev, /*is_env*/ false);
+    prev = use;
+  }
+  // Check all environment uses.
+  prev = nullptr;
+  for (Value* use = def->env_use_list(); use != nullptr;
+       use = use->next_use()) {
+    VisitDefUse(def, use, prev, /*is_env*/ true);
+    prev = use;
+  }
+}
+
+void FlowGraphChecker::VisitUseDef(Instruction* instruction,
+                                   Value* use,
+                                   intptr_t index,
+                                   bool is_env) {
+  ASSERT(use->instruction() == instruction);
+  ASSERT(use->use_index() == index);
+  // Get definition.
+  Definition* def = use->definition();
+  ASSERT(def != nullptr);
+  ASSERT(def != instruction || def->IsPhi() || def->IsMaterializeObject());
+  // Make sure each input is properly defined in the graph by something
+  // that dominates the input (note that the proper dominance relation
+  // on the input values of Phis is checked by the Phi visitor below).
+  bool test_def = def->HasSSATemp();
+  if (def->IsPhi()) {
+    ASSERT(def->GetBlock()->IsJoinEntry());
+    // Phis are never linked into graph.
+    ASSERT(def->next() == nullptr);
+    ASSERT(def->previous() == nullptr);
+  } else if (def->IsConstant() || def->IsParameter() ||
+             def->IsSpecialParameter()) {
+    // Initial definitions are partially linked into graph, but some
+    // constants are fully linked into graph (so no next() assert).
+    ASSERT(def->previous() != nullptr);
+  } else {
+    // Others are fully linked into graph.
+    ASSERT(def->next() != nullptr);
+    ASSERT(def->previous() != nullptr);
+  }
+  if (test_def) {
+    ASSERT(is_env ||  // TODO(dartbug.com/36899)
+           DefDominatesUse(def, instruction));
+    if (is_env) {
+      ASSERT(IsInUseList(def->env_use_list(), instruction));
+    } else {
+      ASSERT(IsInUseList(def->input_use_list(), instruction));
+    }
+  }
+}
+
+void FlowGraphChecker::VisitDefUse(Definition* def,
+                                   Value* use,
+                                   Value* prev,
+                                   bool is_env) {
+  ASSERT(use->definition() == def);
+  ASSERT(use->previous_use() == prev);
+  // Get using instruction.
+  Instruction* instruction = use->instruction();
+  ASSERT(instruction != nullptr);
+  ASSERT(def != instruction || def->IsPhi() || def->IsMaterializeObject());
+  if (is_env) {
+    ASSERT(instruction->env()->ValueAtUseIndex(use->use_index()) == use);
+  } else {
+    ASSERT(instruction->InputAt(use->use_index()) == use);
+  }
+  // Make sure each use appears in the graph and is properly dominated
+  // by the defintion (note that the proper dominance relation on the
+  // input values of Phis is checked by the Phi visitor below).
+  if (instruction->IsPhi()) {
+    ASSERT(instruction->AsPhi()->is_alive());
+    ASSERT(instruction->GetBlock()->IsJoinEntry());
+    // Phis are never linked into graph.
+    ASSERT(instruction->next() == nullptr);
+    ASSERT(instruction->previous() == nullptr);
+  } else if (instruction->IsBlockEntry()) {
+    // BlockEntry instructions have environments attached to them but
+    // have no reliable way to verify if they are still in the graph.
+    ASSERT(is_env);
+  } else {
+    // Others are fully linked into graph.
+    ASSERT(IsControlFlow(instruction) || instruction->next() != nullptr);
+    ASSERT(instruction->previous() != nullptr);
+    ASSERT(is_env ||  // TODO(dartbug.com/36899)
+           DefDominatesUse(def, instruction));
   }
 }
 
 void FlowGraphChecker::VisitConstant(ConstantInstr* constant) {
-  // TODO(ajcbik): Is this a property we eventually want (all constants
-  // generated by utility that queries pool and put in the graph entry
-  // when seen first)? The inliner still creates some direct constants.
+  // Range check on smi.
+  const Object& value = constant->value();
+  if (value.IsSmi()) {
+    const int64_t smi_value = Integer::Cast(value).AsInt64Value();
+    ASSERT(compiler::target::kSmiMin <= smi_value);
+    ASSERT(smi_value <= compiler::target::kSmiMax);
+  }
+  // Any constant involved in SSA should appear in the entry (making it more
+  // likely it was inserted by the utility that avoids duplication).
+  //
+  // TODO(dartbug.com/36894)
+  //
   // ASSERT(constant->GetBlock() == flow_graph_->graph_entry());
 }
 
 void FlowGraphChecker::VisitPhi(PhiInstr* phi) {
-  ASSERT(phi->next() == nullptr);
-  ASSERT(phi->previous() == nullptr);
-  // Make sure each incoming input value of a Phi is dominated
-  // on the corresponding incoming edge, as defined by order.
+  // Make sure the definition of each input value of a Phi dominates
+  // the corresponding incoming edge, as defined by order.
   ASSERT(phi->InputCount() == current_block_->PredecessorCount());
   for (intptr_t i = 0, n = phi->InputCount(); i < n; ++i) {
-    Definition* input_def = phi->InputAt(i)->definition();
+    Definition* def = phi->InputAt(i)->definition();
     BlockEntryInstr* edge = current_block_->PredecessorAt(i);
-    ASSERT(input_def->IsConstant() ||  // some constants are in initial defs
-           edge->last_instruction()->IsDominatedBy(input_def));
+    ASSERT(DefDominatesUse(def, edge->last_instruction()));
   }
 }
 
@@ -199,8 +374,15 @@
   ASSERT(branch->SuccessorCount() == 2);
 }
 
+void FlowGraphChecker::VisitRedefinition(RedefinitionInstr* def) {
+  ASSERT(def->value()->definition() != def);
+}
+
 // Main entry point of graph checker.
-void FlowGraphChecker::Check() {
+void FlowGraphChecker::Check(const char* pass_name) {
+  if (FLAG_trace_compiler) {
+    THR_Print("Running checker after %s\n", pass_name);
+  }
   ASSERT(flow_graph_ != nullptr);
   VisitBlocks();
 }
diff --git a/runtime/vm/compiler/backend/flow_graph_checker.h b/runtime/vm/compiler/backend/flow_graph_checker.h
index fba159f..088ad3e 100644
--- a/runtime/vm/compiler/backend/flow_graph_checker.h
+++ b/runtime/vm/compiler/backend/flow_graph_checker.h
@@ -35,7 +35,7 @@
         current_block_(nullptr) {}
 
   // Performs a sanity check on the flow graph.
-  void Check();
+  void Check(const char* pass_name);
 
  private:
   // Custom-made visitors.
@@ -43,6 +43,11 @@
   void VisitInstructions(BlockEntryInstr* block);
   void VisitInstruction(Instruction* instruction);
   void VisitDefinition(Definition* def);
+  void VisitUseDef(Instruction* instruction,
+                   Value* use,
+                   intptr_t index,
+                   bool is_env);
+  void VisitDefUse(Definition* def, Value* use, Value* prev, bool is_env);
 
   // Instruction visitors.
   void VisitConstant(ConstantInstr* constant) override;
@@ -50,6 +55,7 @@
   void VisitGoto(GotoInstr* jmp) override;
   void VisitIndirectGoto(IndirectGotoInstr* jmp) override;
   void VisitBranch(BranchInstr* branch) override;
+  void VisitRedefinition(RedefinitionInstr* def) override;
 
   FlowGraph* const flow_graph_;
   BlockEntryInstr* current_block_;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 9e5377b..cd2a8db 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -42,6 +42,8 @@
             false,
             "Inlining interval diagnostics");
 
+DEFINE_FLAG(bool, enable_peephole, true, "Enable peephole optimization");
+
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
 DEFINE_FLAG(bool,
@@ -321,16 +323,6 @@
 }
 
 intptr_t FlowGraphCompiler::UncheckedEntryOffset() const {
-// On ARM64 we cannot use the position of the label bound in the
-// FunctionEntryInstr, because `FunctionEntryInstr::EmitNativeCode` does not
-// emit the monomorphic entry and frame entry (instead on ARM64 this is done
-// in FlowGraphCompiler::CompileGraph()).
-//
-// See http://dartbug.com/34162
-#if defined(TARGET_ARCH_ARM64)
-  return 0;
-#endif
-
   BlockEntryInstr* entry = flow_graph().graph_entry()->unchecked_entry();
   if (entry == nullptr) {
     entry = flow_graph().graph_entry()->normal_entry();
@@ -345,12 +337,11 @@
     return target->Position();
   }
 
-// Intrinsification happened.
-#ifdef DART_PRECOMPILER
+  // Intrinsification happened.
   if (parsed_function().function().IsDynamicFunction()) {
     return Instructions::kMonomorphicEntryOffset;
   }
-#endif
+
   return 0;
 }
 
@@ -522,6 +513,35 @@
                        line.ToCString());
 }
 
+#if !defined(TARGET_ARCH_DBC)
+
+static bool IsPusher(Instruction* instr) {
+  if (auto def = instr->AsDefinition()) {
+    return def->HasTemp();
+  }
+  return false;
+}
+
+static bool IsPopper(Instruction* instr) {
+  // TODO(ajcbik): even allow deopt targets by making environment aware?
+  if (!instr->CanBecomeDeoptimizationTarget()) {
+    return !instr->IsPushArgument() && instr->ArgumentCount() == 0 &&
+           instr->InputCount() > 0;
+  }
+  return false;
+}
+
+#endif
+
+bool FlowGraphCompiler::IsPeephole(Instruction* instr) const {
+#if !defined(TARGET_ARCH_DBC)
+  if (FLAG_enable_peephole && !is_optimizing()) {
+    return IsPusher(instr) && IsPopper(instr->next());
+  }
+#endif
+  return false;
+}
+
 void FlowGraphCompiler::VisitBlocks() {
   CompactBlocks();
   if (Assembler::EmittingComments()) {
@@ -529,6 +549,13 @@
     flow_graph().ComputeLoops();
   }
 
+  // In precompiled mode, we require the function entry to come first (after the
+  // graph entry), since the polymorphic check is performed in the function
+  // entry (see Instructions::EntryPoint).
+  if (FLAG_precompiled_mode) {
+    ASSERT(block_order()[1] == flow_graph().graph_entry()->normal_entry());
+  }
+
   for (intptr_t i = 0; i < block_order().length(); ++i) {
     // Compile the block entry.
     BlockEntryInstr* entry = block_order()[i];
@@ -561,9 +588,7 @@
     pending_deoptimization_env_ = NULL;
     EndCodeSourceRange(entry->token_pos());
 
-    // The function was fully intrinsified, so there's no need to generate any
-    // more code.
-    if (fully_intrinsified_) {
+    if (skip_body_compilation()) {
       ASSERT(entry == flow_graph().graph_entry()->normal_entry());
       break;
     }
@@ -591,7 +616,12 @@
         pending_deoptimization_env_ = instr->env();
         instr->EmitNativeCode(this);
         pending_deoptimization_env_ = NULL;
-        EmitInstructionEpilogue(instr);
+        if (IsPeephole(instr)) {
+          ASSERT(top_of_stack_ == nullptr);
+          top_of_stack_ = instr->AsDefinition();
+        } else {
+          EmitInstructionEpilogue(instr);
+        }
         EndCodeSourceRange(instr->token_pos());
       }
 
@@ -794,7 +824,8 @@
 
     RegisterSet* registers = locs->live_registers();
     ASSERT(registers != NULL);
-    const intptr_t kFpuRegisterSpillFactor = kFpuRegisterSize / kWordSize;
+    const intptr_t kFpuRegisterSpillFactor =
+        kFpuRegisterSize / compiler::target::kWordSize;
     intptr_t saved_registers_size = 0;
     const bool using_shared_stub = locs->call_on_shared_slow_path();
     if (using_shared_stub) {
@@ -935,7 +966,8 @@
   RegisterSet* regs = instruction->locs()->live_registers();
   intptr_t fpu_reg_slots[kNumberOfFpuRegisters];
   intptr_t cpu_reg_slots[kNumberOfCpuRegisters];
-  const intptr_t kFpuRegisterSpillFactor = kFpuRegisterSize / kWordSize;
+  const intptr_t kFpuRegisterSpillFactor =
+      kFpuRegisterSize / compiler::target::kWordSize;
   // FPU registers are spilled first from highest to lowest register number.
   for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) {
     FpuRegister reg = static_cast<FpuRegister>(i);
@@ -1081,22 +1113,19 @@
 #if defined(PRODUCT)
 // No debugger: no var descriptors.
 #else
-  // TODO(alexmarkov): revise local vars descriptors when compiling bytecode
-  if (code.is_optimized() ||
-      flow_graph().function().is_declared_in_bytecode() ||
-      flow_graph().function().HasBytecode()) {
+  if (code.is_optimized()) {
     // Optimized code does not need variable descriptors. They are
     // only stored in the unoptimized version.
     code.set_var_descriptors(Object::empty_var_descriptors());
     return;
   }
   LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle();
-  if (parsed_function().node_sequence() == NULL) {
+  if (flow_graph().IsIrregexpFunction()) {
     // Eager local var descriptors computation for Irregexp function as it is
     // complicated to factor out.
     // TODO(srdjan): Consider canonicalizing and reusing the local var
     // descriptor for IrregexpFunction.
-    ASSERT(flow_graph().IsIrregexpFunction());
+    ASSERT(parsed_function().node_sequence() == nullptr);
     var_descs = LocalVarDescriptors::New(1);
     RawLocalVarDescriptors::VarInfo info;
     info.set_kind(RawLocalVarDescriptors::kSavedCurrentContext);
@@ -1191,15 +1220,23 @@
     // them even in checked mode and strong mode.
     switch (parsed_function().function().kind()) {
       case RawFunction::kImplicitGetter: {
-        const Field& field = Field::Handle(function().accessor_field());
+        Field& field = Field::Handle(function().accessor_field());
         ASSERT(!field.IsNull());
+#if defined(DEBUG)
+        // HACK: Clone the field to ignore assertion in Field::guarded_cid().
+        // The assertion is intended to ensure that the background compiler sees
+        // consistent cids, but that's not important in this case because
+        // IsPotentialUnboxedField can go from true to false, but not false to
+        // true, and we only do this optimisation if it is false.
+        field = field.CloneFromOriginal();
+#endif
 
         // Only intrinsify getter if the field cannot contain a mutable double.
         // Reading from a mutable double box requires allocating a fresh double.
         if (field.is_instance() &&
             (FLAG_precompiled_mode || !IsPotentialUnboxedField(field))) {
           SpecialStatsBegin(CombinedCodeStatistics::kTagIntrinsics);
-          GenerateGetterIntrinsic(field.Offset());
+          GenerateGetterIntrinsic(compiler::target::Field::OffsetOf(field));
           SpecialStatsEnd(CombinedCodeStatistics::kTagIntrinsics);
           return !isolate()->use_field_guards();
         }
@@ -1207,13 +1244,18 @@
       }
       case RawFunction::kImplicitSetter: {
         if (!isolate()->argument_type_checks()) {
-          const Field& field = Field::Handle(function().accessor_field());
+          Field& field = Field::Handle(function().accessor_field());
           ASSERT(!field.IsNull());
+#if defined(DEBUG)
+          // HACK: Clone the field to ignore assertion in Field::guarded_cid().
+          // The same reasons as above apply, but we only check if it's dynamic.
+          field = field.CloneFromOriginal();
+#endif
 
           if (field.is_instance() &&
               (FLAG_precompiled_mode || field.guarded_cid() == kDynamicCid)) {
             SpecialStatsBegin(CombinedCodeStatistics::kTagIntrinsics);
-            GenerateSetterIntrinsic(field.Offset());
+            GenerateSetterIntrinsic(compiler::target::Field::OffsetOf(field));
             SpecialStatsEnd(CombinedCodeStatistics::kTagIntrinsics);
             return !isolate()->use_field_guards();
           }
@@ -1227,8 +1269,9 @@
             parsed_function().function().extracted_method_closure());
         auto& klass = Class::Handle(extracted_method.Owner());
         const intptr_t type_arguments_field_offset =
-            klass.NumTypeArguments() > 0
-                ? (klass.type_arguments_field_offset() - kHeapObjectTag)
+            compiler::target::Class::HasTypeArgumentsField(klass)
+                ? (compiler::target::Class::TypeArgumentsFieldOffset(klass) -
+                   kHeapObjectTag)
                 : 0;
 
         SpecialStatsBegin(CombinedCodeStatistics::kTagIntrinsics);
@@ -1357,7 +1400,7 @@
                                : ic_data.arguments_descriptor());
   ASSERT(ArgumentsDescriptor(arguments_descriptor).TypeArgsLen() ==
          args_info.type_args_len);
-  if (is_optimizing()) {
+  if (is_optimizing() && !ForcedOptimization()) {
     EmitOptimizedStaticCall(function, arguments_descriptor,
                             args_info.count_with_type_args, deopt_id, token_pos,
                             locs, entry_kind);
@@ -1463,6 +1506,21 @@
 
   bool blocked_registers[kNumberOfCpuRegisters];
 
+  // Connect input with peephole output for some special cases. All other
+  // cases are handled by simply allocating registers and generating code.
+  if (top_of_stack_ != nullptr) {
+    const intptr_t p = locs->input_count() - 1;
+    Location peephole = top_of_stack_->locs()->out(0);
+    if (locs->in(p).IsUnallocated() || locs->in(p).IsConstant()) {
+      // If input is unallocated, match with an output register, if set. Also,
+      // if input is a direct constant, but the peephole output is a register,
+      // use that register to avoid wasting the already generated code.
+      if (peephole.IsRegister()) {
+        locs->set_in(p, Location::RegisterLocation(peephole.reg()));
+      }
+    }
+  }
+
   // Block all registers globally reserved by the assembler, etc and mark
   // the rest as free.
   for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
@@ -1511,10 +1569,17 @@
     }
     ASSERT(reg != kNoRegister || loc.IsConstant());
 
-    // Inputs are consumed from the simulated frame. In case of a call argument
-    // we leave it until the call instruction.
+    // Inputs are consumed from the simulated frame (or a peephole push/pop).
+    // In case of a call argument we leave it until the call instruction.
     if (should_pop) {
-      if (loc.IsConstant()) {
+      if (top_of_stack_ != nullptr) {
+        if (!loc.IsConstant()) {
+          // Moves top of stack location of the peephole into the required
+          // input. None of the required moves needs a temp register allocator.
+          EmitMove(locs->in(i), top_of_stack_->locs()->out(0), nullptr);
+        }
+        top_of_stack_ = nullptr;  // consumed!
+      } else if (loc.IsConstant()) {
         assembler()->Drop(1);
       } else {
         assembler()->PopRegister(reg);
@@ -1668,6 +1733,30 @@
   compiler_->EndCodeSourceRange(TokenPosition::kParallelMove);
 }
 
+#if !defined(TARGET_ARCH_DBC)
+void ParallelMoveResolver::EmitMove(int index) {
+  MoveOperands* const move = moves_[index];
+  const Location dst = move->dest();
+  if (dst.IsStackSlot() || dst.IsDoubleStackSlot()) {
+    ASSERT((dst.base_reg() != FPREG) ||
+           ((-compiler::target::frame_layout.VariableIndexForFrameSlot(
+                dst.stack_index())) < compiler_->StackSize()));
+  }
+  const Location src = move->src();
+  ParallelMoveResolver::TemporaryAllocator temp(this, /*blocked=*/kNoRegister);
+  compiler_->EmitMove(dst, src, &temp);
+#if defined(DEBUG)
+  // Allocating a scratch register here may cause stack spilling. Neither the
+  // source nor destination register should be SP-relative in that case.
+  for (const Location loc : {dst, src}) {
+    ASSERT(!temp.DidAllocateTemporary() || !loc.HasStackIndex() ||
+           loc.base_reg() != SPREG);
+  }
+#endif
+  move->Eliminate();
+}
+#endif
+
 bool ParallelMoveResolver::IsScratchLocation(Location loc) {
   for (int i = 0; i < moves_.length(); ++i) {
     if (moves_[i]->Blocks(loc)) {
@@ -1740,12 +1829,19 @@
   }
 }
 
-ParallelMoveResolver::ScratchRegisterScope::ScratchRegisterScope(
+ParallelMoveResolver::TemporaryAllocator::TemporaryAllocator(
     ParallelMoveResolver* resolver,
     Register blocked)
-    : resolver_(resolver), reg_(kNoRegister), spilled_(false) {
-  uword blocked_mask = RegMaskBit(blocked) | kReservedCpuRegisters;
-  if (resolver->compiler_->intrinsic_mode()) {
+    : resolver_(resolver),
+      blocked_(blocked),
+      reg_(kNoRegister),
+      spilled_(false) {}
+
+Register ParallelMoveResolver::TemporaryAllocator::AllocateTemporary() {
+  ASSERT(reg_ == kNoRegister);
+
+  uword blocked_mask = RegMaskBit(blocked_) | kReservedCpuRegisters;
+  if (resolver_->compiler_->intrinsic_mode()) {
     // Block additional registers that must be preserved for intrinsics.
     blocked_mask |= RegMaskBit(ARGS_DESC_REG);
 #if !defined(TARGET_ARCH_IA32)
@@ -1759,14 +1855,29 @@
                                          kNumberOfCpuRegisters - 1, &spilled_));
 
   if (spilled_) {
-    resolver->SpillScratch(reg_);
+    resolver_->SpillScratch(reg_);
   }
+
+  DEBUG_ONLY(allocated_ = true;)
+  return reg_;
 }
 
-ParallelMoveResolver::ScratchRegisterScope::~ScratchRegisterScope() {
+void ParallelMoveResolver::TemporaryAllocator::ReleaseTemporary() {
   if (spilled_) {
     resolver_->RestoreScratch(reg_);
   }
+  reg_ = kNoRegister;
+}
+
+ParallelMoveResolver::ScratchRegisterScope::ScratchRegisterScope(
+    ParallelMoveResolver* resolver,
+    Register blocked)
+    : allocator_(resolver, blocked) {
+  reg_ = allocator_.AllocateTemporary();
+}
+
+ParallelMoveResolver::ScratchRegisterScope::~ScratchRegisterScope() {
+  allocator_.ReleaseTemporary();
 }
 
 const ICData* FlowGraphCompiler::GetOrAddInstanceCallICData(
@@ -1936,7 +2047,7 @@
       Function::Handle(zone, Resolver::ResolveDynamicForReceiverClass(
                                  cls, name, args_desc, allow_add));
   if (target_function.IsNull()) return false;
-  *fn_return ^= target_function.raw();
+  *fn_return = target_function.raw();
   return true;
 }
 
@@ -1994,6 +2105,7 @@
                                         intptr_t total_ic_calls,
                                         Code::EntryKind entry_kind) {
   ASSERT(is_optimizing());
+  ASSERT(complete || (failed != nullptr));  // Complete calls can't fail.
 
   const Array& arguments_descriptor =
       Array::ZoneHandle(zone(), args_info.ToArgumentsDescriptor());
@@ -2028,8 +2140,13 @@
 
   if (smi_case != kNoCase) {
     Label after_smi_test;
-    EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test,
-                             /* jump_if_smi= */ false);
+    // If the call is complete and there are no other possible receiver
+    // classes - then receiver can only be a smi value and we don't need
+    // to check if it is a smi.
+    if (!(complete && non_smi_length == 0)) {
+      EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test,
+                               /* jump_if_smi= */ false);
+    }
 
     // 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.
@@ -2194,8 +2311,9 @@
     __ CompareObject(kTypeArgumentsReg, Object::null_object());
     __ BranchIf(EQUAL, done);
     __ LoadField(dst_type_reg,
-                 FieldAddress(kTypeArgumentsReg, TypeArguments::type_at_offset(
-                                                     type_param.index())));
+                 FieldAddress(kTypeArgumentsReg,
+                              compiler::target::TypeArguments::type_at_offset(
+                                  type_param.index())));
     if (type_usage_info != NULL) {
       type_usage_info->UseTypeInAssertAssignable(dst_type);
     }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 56046747..28c369b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -28,6 +28,32 @@
 class ParsedFunction;
 class SpeculativeInliningPolicy;
 
+// Used in methods which need conditional access to a temporary register.
+// May only be used to allocate a single temporary register.
+class TemporaryRegisterAllocator : public ValueObject {
+ public:
+  virtual ~TemporaryRegisterAllocator() {}
+  virtual Register AllocateTemporary() = 0;
+  virtual void ReleaseTemporary() = 0;
+};
+
+class ConstantTemporaryAllocator : public TemporaryRegisterAllocator {
+ public:
+  explicit ConstantTemporaryAllocator(Register tmp) : tmp_(tmp) {}
+
+  Register AllocateTemporary() override { return tmp_; }
+  void ReleaseTemporary() override {}
+
+ private:
+  Register const tmp_;
+};
+
+class NoTemporaryAllocator : public TemporaryRegisterAllocator {
+ public:
+  Register AllocateTemporary() override { UNREACHABLE(); }
+  void ReleaseTemporary() override { UNREACHABLE(); }
+};
+
 class ParallelMoveResolver : public ValueObject {
  public:
   explicit ParallelMoveResolver(FlowGraphCompiler* compiler);
@@ -50,6 +76,24 @@
     bool spilled_;
   };
 
+  class TemporaryAllocator : public TemporaryRegisterAllocator {
+   public:
+    TemporaryAllocator(ParallelMoveResolver* resolver, Register blocked);
+
+    Register AllocateTemporary() override;
+    void ReleaseTemporary() override;
+    DEBUG_ONLY(bool DidAllocateTemporary() { return allocated_; })
+
+    virtual ~TemporaryAllocator() { ASSERT(reg_ == kNoRegister); }
+
+   private:
+    ParallelMoveResolver* const resolver_;
+    const Register blocked_;
+    Register reg_;
+    bool spilled_;
+    DEBUG_ONLY(bool allocated_ = false);
+  };
+
   class ScratchRegisterScope : public ValueObject {
    public:
     ScratchRegisterScope(ParallelMoveResolver* resolver, Register blocked);
@@ -58,9 +102,8 @@
     Register reg() const { return reg_; }
 
    private:
-    ParallelMoveResolver* resolver_;
+    TemporaryAllocator allocator_;
     Register reg_;
-    bool spilled_;
   };
 
   bool IsScratchLocation(Location loc);
@@ -366,6 +409,11 @@
     return block_order_;
   }
 
+  // If 'ForcedOptimization()' returns 'true', we are compiling in optimized
+  // mode for a function which cannot deoptimize. Certain optimizations, e.g.
+  // speculative optimizations and call patching are disabled.
+  bool ForcedOptimization() const { return function().ForceOptimize(); }
+
   const FlowGraph& flow_graph() const { return flow_graph_; }
 
   BlockEntryInstr* current_block() const { return current_block_; }
@@ -375,6 +423,15 @@
   bool CanOSRFunction() const;
   bool is_optimizing() const { return is_optimizing_; }
 
+  // The function was fully intrinsified, so the body is unreachable.
+  //
+  // We still need to compile the body in unoptimized mode because the
+  // 'ICData's are added to the function's 'ic_data_array_' when instance
+  // calls are compiled.
+  bool skip_body_compilation() const {
+    return fully_intrinsified_ && is_optimizing();
+  }
+
   void EnterIntrinsicMode();
   void ExitIntrinsicMode();
   bool intrinsic_mode() const { return intrinsic_mode_; }
@@ -427,6 +484,9 @@
   // Returns 'true' if regular code generation should be skipped.
   bool TryIntrinsify();
 
+  // Emits code for a generic move from a location 'src' to a location 'dst'.
+  void EmitMove(Location dst, Location src, TemporaryRegisterAllocator* temp);
+
   void GenerateAssertAssignable(TokenPosition token_pos,
                                 intptr_t deopt_id,
                                 const AbstractType& dst_type,
@@ -970,6 +1030,10 @@
   void FrameStateClear();
 #endif
 
+  // Returns true if instruction lookahead (window size one)
+  // is amenable to a peephole optimization.
+  bool IsPeephole(Instruction* instr) const;
+
   // This struct contains either function or code, the other one being NULL.
   class StaticCallsStruct : public ZoneAllocated {
    public:
@@ -1034,6 +1098,11 @@
   bool fully_intrinsified_ = false;
   CodeStatistics* stats_;
 
+  // The definition whose value is supposed to be at the top of the
+  // expression stack. Used by peephole optimization (window size one)
+  // to eliminate redundant push/pop pairs.
+  Definition* top_of_stack_ = nullptr;
+
   const Class& double_class_;
   const Class& mint_class_;
   const Class& float32x4_class_;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 04a4a85..9018e54 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -196,7 +196,7 @@
   }
 
   ASSERT(deopt_env() != NULL);
-  __ ldr(LR, Address(THR, Thread::deoptimize_entry_offset()));
+  __ ldr(LR, Address(THR, compiler::target::Thread::deoptimize_entry_offset()));
   __ blx(LR);
   ASSERT(kReservedCpuRegisters & (1 << LR));
   set_pc_offset(assembler->CodeSize());
@@ -431,8 +431,8 @@
   __ LoadClassById(R1, R2);
   // R1: instance class.
   // Check immediate superclass equality.
-  __ ldr(R2, FieldAddress(R1, Class::super_type_offset()));
-  __ ldr(R2, FieldAddress(R2, Type::type_class_id_offset()));
+  __ ldr(R2, FieldAddress(R1, compiler::target::Class::super_type_offset()));
+  __ ldr(R2, FieldAddress(R2, compiler::target::Type::type_class_id_offset()));
   __ CompareImmediate(R2, Smi::RawValue(type_class.id()));
   __ b(is_instance_lbl, EQ);
 
@@ -475,7 +475,8 @@
     __ CompareObject(kTypeArgumentsReg, Object::null_object());
     __ b(is_instance_lbl, EQ);
     __ ldr(R3, FieldAddress(kTypeArgumentsReg,
-                            TypeArguments::type_at_offset(type_param.index())));
+                            compiler::target::TypeArguments::type_at_offset(
+                                type_param.index())));
     // R3: concrete type of type.
     // Check if type argument is dynamic, Object, or void.
     __ CompareObject(R3, Object::dynamic_type());
@@ -772,15 +773,18 @@
   const intptr_t sub_type_cache_index = __ object_pool_builder().AddObject(
       Object::null_object(), ObjectPool::Patchability::kPatchable);
   const intptr_t sub_type_cache_offset =
-      ObjectPool::element_offset(sub_type_cache_index) - kHeapObjectTag;
+      compiler::target::ObjectPool::element_offset(sub_type_cache_index) -
+      kHeapObjectTag;
   const intptr_t dst_name_index = __ object_pool_builder().AddObject(
       dst_name, ObjectPool::Patchability::kPatchable);
   ASSERT((sub_type_cache_index + 1) == dst_name_index);
   ASSERT(__ constant_pool_allowed());
 
-  __ LoadField(R9,
-               FieldAddress(kDstTypeReg,
-                            AbstractType::type_test_stub_entry_point_offset()));
+  __ LoadField(
+      R9,
+      FieldAddress(
+          kDstTypeReg,
+          compiler::target::AbstractType::type_test_stub_entry_point_offset()));
   __ LoadWordFromPoolOffset(kSubtypeTestCacheReg, sub_type_cache_offset, PP,
                             AL);
   __ blx(R9);
@@ -822,15 +826,17 @@
     kPoolReg = PP;
   } else {
     __ LoadFieldFromOffset(kWord, kPoolReg, CODE_REG,
-                           Code::object_pool_offset());
+                           compiler::target::Code::object_pool_offset());
   }
   __ LoadImmediate(R4, type_arguments_field_offset);
-  __ LoadFieldFromOffset(kWord, R1, kPoolReg,
-                         ObjectPool::element_offset(function_index));
-  __ LoadFieldFromOffset(kWord, CODE_REG, kPoolReg,
-                         ObjectPool::element_offset(stub_index));
-  __ Branch(FieldAddress(
-      CODE_REG, Code::entry_point_offset(Code::EntryKind::kUnchecked)));
+  __ LoadFieldFromOffset(
+      kWord, R1, kPoolReg,
+      compiler::target::ObjectPool::element_offset(function_index));
+  __ LoadFieldFromOffset(
+      kWord, CODE_REG, kPoolReg,
+      compiler::target::ObjectPool::element_offset(stub_index));
+  __ Branch(FieldAddress(CODE_REG, compiler::target::Code::entry_point_offset(
+                                       Code::EntryKind::kUnchecked)));
 }
 
 void FlowGraphCompiler::GenerateGetterIntrinsic(intptr_t offset) {
@@ -838,7 +844,7 @@
   // SP: receiver.
   // Sequence node has one return node, its input is load field node.
   __ Comment("Inlined Getter");
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * compiler::target::kWordSize));
   __ LoadFieldFromOffset(kWord, R0, R0, offset);
   __ Ret();
 }
@@ -849,49 +855,44 @@
   // SP+0: value.
   // Sequence node has one store node and one return NULL node.
   __ Comment("Inlined Setter");
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // Receiver.
-  __ ldr(R1, Address(SP, 0 * kWordSize));  // Value.
+  __ ldr(R0, Address(SP, 1 * compiler::target::kWordSize));  // Receiver.
+  __ ldr(R1, Address(SP, 0 * compiler::target::kWordSize));  // Value.
   __ StoreIntoObjectOffset(R0, offset, R1);
   __ LoadObject(R0, Object::null_object());
   __ Ret();
 }
 
-static const Register new_pp = NOTFP;
-
 void FlowGraphCompiler::EmitFrameEntry() {
   const Function& function = parsed_function().function();
   if (CanOptimizeFunction() && function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
     __ Comment("Invocation Count Check");
     const Register function_reg = R8;
-    if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
-      // The pool pointer is not setup before entering the Dart frame.
-      // Temporarily setup pool pointer for this dart function.
-      __ LoadPoolPointer(new_pp);
-    }
-    // Load function object from object pool.
-    __ LoadFunctionFromCalleePool(function_reg, function, new_pp);
-
-    __ ldr(R3, FieldAddress(function_reg, Function::usage_counter_offset()));
+    __ ldr(function_reg,
+           FieldAddress(CODE_REG, compiler::target::Code::owner_offset()));
+    __ ldr(R3,
+           FieldAddress(function_reg,
+                        compiler::target::Function::usage_counter_offset()));
     // Reoptimization of an optimized function is triggered by counting in
     // IC stubs, but not at the entry of the function.
     if (!is_optimizing()) {
       __ add(R3, R3, Operand(1));
-      __ str(R3, FieldAddress(function_reg, Function::usage_counter_offset()));
+      __ str(R3,
+             FieldAddress(function_reg,
+                          compiler::target::Function::usage_counter_offset()));
     }
     __ CompareImmediate(R3, GetOptimizationThreshold());
     ASSERT(function_reg == R8);
-    __ Branch(StubCode::OptimizeFunction(),
-              compiler::ObjectPoolBuilderEntry::kNotPatchable, new_pp, GE);
+    __ Branch(Address(THR, Thread::optimize_entry_offset()), GE);
   }
   __ Comment("Enter frame");
   if (flow_graph().IsCompiledForOsr()) {
     const intptr_t extra_slots = ExtraStackSlotsOnOsrEntry();
     ASSERT(extra_slots >= 0);
-    __ EnterOsrFrame(extra_slots * kWordSize);
+    __ EnterOsrFrame(extra_slots * compiler::target::kWordSize);
   } else {
     ASSERT(StackSize() >= 0);
-    __ EnterDartFrame(StackSize() * kWordSize);
+    __ EnterDartFrame(StackSize() * compiler::target::kWordSize);
   }
 }
 
@@ -917,7 +918,8 @@
       const intptr_t slot_index =
           compiler::target::frame_layout.FrameSlotForVariableIndex(-i);
       Register value_reg = slot_index == args_desc_slot ? ARGS_DESC_REG : R0;
-      __ StoreToOffset(kWord, value_reg, FP, slot_index * kWordSize);
+      __ StoreToOffset(kWord, value_reg, FP,
+                       slot_index * compiler::target::kWordSize);
     }
   }
 
@@ -944,7 +946,7 @@
 
   __ bkpt(0);
 
-  if (!fully_intrinsified_) {
+  if (!skip_body_compilation()) {
     ASSERT(assembler()->constant_pool_allowed());
     GenerateDeferredCode();
   }
@@ -1031,9 +1033,11 @@
   bool old_use_far_branches = assembler_->use_far_branches();
   assembler_->set_use_far_branches(true);
 #endif  // DEBUG
-  __ LoadFieldFromOffset(kWord, R1, R0, Array::element_offset(edge_id));
+  __ LoadFieldFromOffset(kWord, R1, R0,
+                         compiler::target::Array::element_offset(edge_id));
   __ add(R1, R1, Operand(Smi::RawValue(1)));
-  __ StoreIntoObjectNoBarrierOffset(R0, Array::element_offset(edge_id), R1);
+  __ StoreIntoObjectNoBarrierOffset(
+      R0, compiler::target::Array::element_offset(edge_id), R1);
 #if defined(DEBUG)
   assembler_->set_use_far_branches(old_use_far_branches);
 #endif  // DEBUG
@@ -1054,6 +1058,8 @@
   // Pass the function explicitly, it is used in IC stub.
 
   __ LoadObject(R8, parsed_function().function());
+  __ LoadFromOffset(kWord, R0, SP,
+                    (ic_data.CountWithoutTypeArgs() - 1) * kWordSize);
   __ LoadUniqueObject(R9, ic_data);
   GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs,
                    entry_kind);
@@ -1066,8 +1072,11 @@
                                          TokenPosition token_pos,
                                          LocationSummary* locs) {
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
+  __ LoadFromOffset(kWord, R0, SP,
+                    (ic_data.CountWithoutTypeArgs() - 1) * kWordSize);
   __ LoadUniqueObject(R9, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs,
+                   Code::EntryKind::kMonomorphic);
   __ Drop(ic_data.CountWithTypeArgs());
 }
 
@@ -1087,9 +1096,14 @@
 
   __ Comment("MegamorphicCall");
   // Load receiver into R0.
-  __ LoadFromOffset(kWord, R0, SP, (args_desc.Count() - 1) * kWordSize);
+  __ LoadFromOffset(kWord, R0, SP,
+                    (args_desc.Count() - 1) * compiler::target::kWordSize);
   __ LoadObject(R9, cache);
-  __ ldr(LR, Address(THR, Thread::megamorphic_call_checked_entry_offset()));
+  __ ldr(
+      LR,
+      Address(
+          THR,
+          compiler::target::Thread::megamorphic_call_checked_entry_offset()));
   __ blx(LR);
 
   RecordSafepoint(locs, slow_path_argument_count);
@@ -1126,8 +1140,9 @@
   const Code& initial_stub = StubCode::ICCallThroughFunction();
 
   __ Comment("SwitchableCall");
-  __ LoadFromOffset(kWord, R0, SP,
-                    (ic_data.CountWithoutTypeArgs() - 1) * kWordSize);
+  __ LoadFromOffset(
+      kWord, R0, SP,
+      (ic_data.CountWithoutTypeArgs() - 1) * compiler::target::kWordSize);
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     // The AOT runtime will replace the slot in the object pool with the
     // entrypoint address - see clustered_snapshot.cc.
@@ -1136,8 +1151,10 @@
     __ LoadUniqueObject(CODE_REG, initial_stub);
     const intptr_t entry_point_offset =
         entry_kind == Code::EntryKind::kNormal
-            ? Code::entry_point_offset(Code::EntryKind::kMonomorphic)
-            : Code::entry_point_offset(Code::EntryKind::kMonomorphicUnchecked);
+            ? compiler::target::Code::entry_point_offset(
+                  Code::EntryKind::kMonomorphic)
+            : compiler::target::Code::entry_point_offset(
+                  Code::EntryKind::kMonomorphicUnchecked);
     __ ldr(LR, FieldAddress(CODE_REG, entry_point_offset));
   }
   __ LoadUniqueObject(R9, ic_data);
@@ -1270,7 +1287,9 @@
     const Array& arguments_descriptor) {
   __ Comment("EmitTestAndCall");
   // Load receiver into R0.
-  __ LoadFromOffset(kWord, R0, SP, (count_without_type_args - 1) * kWordSize);
+  __ LoadFromOffset(
+      kWord, R0, SP,
+      (count_without_type_args - 1) * compiler::target::kWordSize);
   __ LoadObject(R4, arguments_descriptor);
 }
 
@@ -1309,12 +1328,12 @@
 }
 
 #undef __
-#define __ compiler_->assembler()->
+#define __ assembler()->
 
-void ParallelMoveResolver::EmitMove(int index) {
-  MoveOperands* move = moves_[index];
-  const Location source = move->src();
-  const Location destination = move->dest();
+void FlowGraphCompiler::EmitMove(Location destination,
+                                 Location source,
+                                 TemporaryRegisterAllocator* allocator) {
+  if (destination.Equals(source)) return;
 
   if (source.IsRegister()) {
     if (destination.IsRegister()) {
@@ -1347,24 +1366,32 @@
         __ vmovd(EvenDRegisterOf(destination.fpu_reg()),
                  EvenDRegisterOf(source.fpu_reg()));
       }
+    } else if (destination.IsStackSlot()) {
+      // 32-bit float
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      const SRegister src = EvenSRegisterOf(EvenDRegisterOf(source.fpu_reg()));
+      __ StoreSToOffset(src, destination.base_reg(), dest_offset);
+    } else if (destination.IsDoubleStackSlot()) {
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      DRegister src = EvenDRegisterOf(source.fpu_reg());
+      __ StoreDToOffset(src, destination.base_reg(), dest_offset);
     } else {
-      if (destination.IsDoubleStackSlot()) {
-        const intptr_t dest_offset = destination.ToStackSlotOffset();
-        DRegister src = EvenDRegisterOf(source.fpu_reg());
-        __ StoreDToOffset(src, destination.base_reg(), dest_offset);
-      } else {
-        ASSERT(destination.IsQuadStackSlot());
-        const intptr_t dest_offset = destination.ToStackSlotOffset();
-        const DRegister dsrc0 = EvenDRegisterOf(source.fpu_reg());
-        __ StoreMultipleDToOffset(dsrc0, 2, destination.base_reg(),
-                                  dest_offset);
-      }
+      ASSERT(destination.IsQuadStackSlot());
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      const DRegister dsrc0 = EvenDRegisterOf(source.fpu_reg());
+      __ StoreMultipleDToOffset(dsrc0, 2, destination.base_reg(), dest_offset);
     }
   } else if (source.IsDoubleStackSlot()) {
     if (destination.IsFpuRegister()) {
       const intptr_t source_offset = source.ToStackSlotOffset();
       const DRegister dst = EvenDRegisterOf(destination.fpu_reg());
       __ LoadDFromOffset(dst, source.base_reg(), source_offset);
+    } else if (destination.IsStackSlot()) {
+      // 32-bit float
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      __ LoadSFromOffset(STMP, source.base_reg(), source_offset);
+      __ StoreSToOffset(STMP, destination.base_reg(), dest_offset);
     } else {
       ASSERT(destination.IsDoubleStackSlot());
       const intptr_t source_offset = source.ToStackSlotOffset();
@@ -1385,22 +1412,27 @@
       __ LoadMultipleDFromOffset(dtmp0, 2, source.base_reg(), source_offset);
       __ StoreMultipleDToOffset(dtmp0, 2, destination.base_reg(), dest_offset);
     }
+  } else if (source.IsPairLocation()) {
+    ASSERT(destination.IsPairLocation());
+    for (intptr_t i : {0, 1}) {
+      EmitMove(destination.Component(i), source.Component(i), allocator);
+    }
   } else {
     ASSERT(source.IsConstant());
-
     if (destination.IsFpuRegister() || destination.IsDoubleStackSlot() ||
         destination.IsStackSlot()) {
-      ScratchRegisterScope scratch(this, kNoRegister);
-      source.constant_instruction()->EmitMoveToLocation(compiler_, destination,
-                                                        scratch.reg());
+      Register tmp = allocator->AllocateTemporary();
+      source.constant_instruction()->EmitMoveToLocation(this, destination, tmp);
+      allocator->ReleaseTemporary();
     } else {
-      source.constant_instruction()->EmitMoveToLocation(compiler_, destination);
+      source.constant_instruction()->EmitMoveToLocation(this, destination);
     }
   }
-
-  move->Eliminate();
 }
 
+#undef __
+#define __ compiler_->assembler()->
+
 void ParallelMoveResolver::EmitSwap(int index) {
   MoveOperands* move = moves_[index];
   const Location source = move->src();
@@ -1424,12 +1456,14 @@
     if (TargetCPUFeatures::neon_supported()) {
       const QRegister dst = destination.fpu_reg();
       const QRegister src = source.fpu_reg();
+      ASSERT(dst != QTMP && src != QTMP);
       __ vmovq(QTMP, src);
       __ vmovq(src, dst);
       __ vmovq(dst, QTMP);
     } else {
       const DRegister dst = EvenDRegisterOf(destination.fpu_reg());
       const DRegister src = EvenDRegisterOf(source.fpu_reg());
+      ASSERT(dst != DTMP && src != DTMP);
       __ vmovd(DTMP, src);
       __ vmovd(src, dst);
       __ vmovd(dst, DTMP);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 943aaec..505a96a 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -837,20 +837,11 @@
 
 void FlowGraphCompiler::EmitFrameEntry() {
   const Function& function = parsed_function().function();
-  Register new_pp = kNoRegister;
   if (CanOptimizeFunction() && function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
     __ Comment("Invocation Count Check");
     const Register function_reg = R6;
-    new_pp = R13;
-    if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
-      // The pool pointer is not setup before entering the Dart frame.
-      // Temporarily setup pool pointer for this dart function.
-      __ LoadPoolPointer(new_pp);
-    }
-
-    // Load function object using the callee's pool pointer.
-    __ LoadFunctionFromCalleePool(function_reg, function, new_pp);
+    __ ldr(function_reg, FieldAddress(CODE_REG, Code::owner_offset()));
 
     __ LoadFieldFromOffset(R7, function_reg, Function::usage_counter_offset(),
                            kWord);
@@ -865,48 +856,22 @@
     ASSERT(function_reg == R6);
     Label dont_optimize;
     __ b(&dont_optimize, LT);
-    __ Branch(StubCode::OptimizeFunction(), new_pp);
+    __ ldr(TMP, Address(THR, Thread::optimize_entry_offset()));
+    __ br(TMP);
     __ Bind(&dont_optimize);
   }
   __ Comment("Enter frame");
   if (flow_graph().IsCompiledForOsr()) {
     const intptr_t extra_slots = ExtraStackSlotsOnOsrEntry();
     ASSERT(extra_slots >= 0);
-    __ EnterOsrFrame(extra_slots * kWordSize, new_pp);
+    __ EnterOsrFrame(extra_slots * kWordSize);
   } else {
     ASSERT(StackSize() >= 0);
-    __ EnterDartFrame(StackSize() * kWordSize, new_pp);
+    __ EnterDartFrame(StackSize() * kWordSize);
   }
 }
 
-// Input parameters:
-//   LR: return address.
-//   SP: address of last argument.
-//   FP: caller's frame pointer.
-//   PP: caller's pool pointer.
-//   R4: arguments descriptor array.
-void FlowGraphCompiler::CompileGraph() {
-  InitCompiler();
-
-  if (FLAG_precompiled_mode) {
-    const Function& function = parsed_function().function();
-    if (function.IsDynamicFunction()) {
-      SpecialStatsBegin(CombinedCodeStatistics::kTagCheckedEntry);
-      __ MonomorphicCheckedEntry();
-      SpecialStatsEnd(CombinedCodeStatistics::kTagCheckedEntry);
-    }
-  }
-
-  // For JIT we have multiple entrypoints functionality which moved the
-  // intrinsification as well as the setup of the frame to the
-  // [TargetEntryInstr::EmitNativeCode].
-  //
-  // Though this has not been implemented on ARM64, which is why this code here
-  // is outside the "ifdef DART_PRECOMPILER".
-  if (TryIntrinsify()) {
-    // Skip regular code generation.
-    return;
-  }
+void FlowGraphCompiler::EmitPrologue() {
   EmitFrameEntry();
   ASSERT(assembler()->constant_pool_allowed());
 
@@ -933,11 +898,32 @@
   }
 
   EndCodeSourceRange(TokenPosition::kDartCodePrologue);
+}
+
+// Input parameters:
+//   LR: return address.
+//   SP: address of last argument.
+//   FP: caller's frame pointer.
+//   PP: caller's pool pointer.
+//   R4: arguments descriptor array.
+void FlowGraphCompiler::CompileGraph() {
+  InitCompiler();
+
+  // For JIT we have multiple entrypoints functionality which moved the frame
+  // setup into the [TargetEntryInstr] (which will set the constant pool
+  // allowed bit to true).  Despite this we still have to set the
+  // constant pool allowed bit to true here as well, because we can generate
+  // code for [CatchEntryInstr]s, which need the pool.
+  __ set_constant_pool_allowed(true);
+
   VisitBlocks();
 
   __ brk(0);
-  ASSERT(assembler()->constant_pool_allowed());
-  GenerateDeferredCode();
+
+  if (!skip_body_compilation()) {
+    ASSERT(assembler()->constant_pool_allowed());
+    GenerateDeferredCode();
+  }
 }
 
 void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
@@ -1040,6 +1026,7 @@
   // Pass the function explicitly, it is used in IC stub.
 
   __ LoadObject(R6, parsed_function().function());
+  __ LoadFromOffset(R0, SP, (ic_data.CountWithoutTypeArgs() - 1) * kWordSize);
   __ LoadUniqueObject(R5, ic_data);
   GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.CountWithTypeArgs());
@@ -1051,8 +1038,10 @@
                                          TokenPosition token_pos,
                                          LocationSummary* locs) {
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
+  __ LoadFromOffset(R0, SP, (ic_data.CountWithoutTypeArgs() - 1) * kWordSize);
   __ LoadUniqueObject(R5, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs,
+                   Code::EntryKind::kMonomorphic);
   __ Drop(ic_data.CountWithTypeArgs());
 }
 
@@ -1171,8 +1160,8 @@
   }
   // 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, token_pos,
-                         RawPcDescriptors::kOther, locs, function);
+  GenerateStaticDartCall(deopt_id, token_pos, RawPcDescriptors::kOther, locs,
+                         function);
   __ Drop(count_with_type_args);
 }
 
@@ -1303,12 +1292,12 @@
 }
 
 #undef __
-#define __ compiler_->assembler()->
+#define __ assembler()->
 
-void ParallelMoveResolver::EmitMove(int index) {
-  MoveOperands* move = moves_[index];
-  const Location source = move->src();
-  const Location destination = move->dest();
+void FlowGraphCompiler::EmitMove(Location destination,
+                                 Location source,
+                                 TemporaryRegisterAllocator* allocator) {
+  if (destination.Equals(source)) return;
 
   if (source.IsRegister()) {
     if (destination.IsRegister()) {
@@ -1322,19 +1311,25 @@
     if (destination.IsRegister()) {
       const intptr_t source_offset = source.ToStackSlotOffset();
       __ LoadFromOffset(destination.reg(), source.base_reg(), source_offset);
+    } else if (destination.IsFpuRegister()) {
+      const intptr_t src_offset = source.ToStackSlotOffset();
+      VRegister dst = destination.fpu_reg();
+      __ LoadDFromOffset(dst, source.base_reg(), src_offset);
     } else {
       ASSERT(destination.IsStackSlot());
       const intptr_t source_offset = source.ToStackSlotOffset();
       const intptr_t dest_offset = destination.ToStackSlotOffset();
-      ScratchRegisterScope tmp(this, kNoRegister);
-      __ LoadFromOffset(tmp.reg(), source.base_reg(), source_offset);
-      __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset);
+      Register tmp = allocator->AllocateTemporary();
+      __ LoadFromOffset(tmp, source.base_reg(), source_offset);
+      __ StoreToOffset(tmp, destination.base_reg(), dest_offset);
+      allocator->ReleaseTemporary();
     }
   } else if (source.IsFpuRegister()) {
     if (destination.IsFpuRegister()) {
       __ vmov(destination.fpu_reg(), source.fpu_reg());
     } else {
-      if (destination.IsDoubleStackSlot()) {
+      if (destination.IsStackSlot() /*32-bit float*/ ||
+          destination.IsDoubleStackSlot()) {
         const intptr_t dest_offset = destination.ToStackSlotOffset();
         VRegister src = source.fpu_reg();
         __ StoreDToOffset(src, destination.base_reg(), dest_offset);
@@ -1351,7 +1346,8 @@
       const VRegister dst = destination.fpu_reg();
       __ LoadDFromOffset(dst, source.base_reg(), source_offset);
     } else {
-      ASSERT(destination.IsDoubleStackSlot());
+      ASSERT(destination.IsDoubleStackSlot() ||
+             destination.IsStackSlot() /*32-bit float*/);
       const intptr_t source_offset = source.ToStackSlotOffset();
       const intptr_t dest_offset = destination.ToStackSlotOffset();
       __ LoadDFromOffset(VTMP, source.base_reg(), source_offset);
@@ -1372,17 +1368,18 @@
   } else {
     ASSERT(source.IsConstant());
     if (destination.IsStackSlot()) {
-      ScratchRegisterScope scratch(this, kNoRegister);
-      source.constant_instruction()->EmitMoveToLocation(compiler_, destination,
-                                                        scratch.reg());
+      Register tmp = allocator->AllocateTemporary();
+      source.constant_instruction()->EmitMoveToLocation(this, destination, tmp);
+      allocator->ReleaseTemporary();
     } else {
-      source.constant_instruction()->EmitMoveToLocation(compiler_, destination);
+      source.constant_instruction()->EmitMoveToLocation(this, destination);
     }
   }
-
-  move->Eliminate();
 }
 
+#undef __
+#define __ compiler_->assembler()->
+
 void ParallelMoveResolver::EmitSwap(int index) {
   MoveOperands* move = moves_[index];
   const Location source = move->src();
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc b/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc
index 892cdb5..e3729c7 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc
@@ -340,15 +340,12 @@
   }
 }
 
+void FlowGraphCompiler::EmitPrologue() {
+  EmitFrameEntry();
+}
+
 void FlowGraphCompiler::CompileGraph() {
   InitCompiler();
-
-  if (TryIntrinsify()) {
-    // Skip regular code generation.
-    return;
-  }
-
-  EmitFrameEntry();
   VisitBlocks();
 }
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index dfa2fc7..4cea80a 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -775,7 +775,10 @@
     __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()),
             Immediate(GetOptimizationThreshold()));
     ASSERT(function_reg == EBX);
-    __ J(GREATER_EQUAL, StubCode::OptimizeFunction());
+    Label dont_optimize;
+    __ j(LESS, &dont_optimize, Assembler::kNearJump);
+    __ jmp(Address(THR, Thread::optimize_entry_offset()));
+    __ Bind(&dont_optimize);
   }
   __ Comment("Enter frame");
   if (flow_graph().IsCompiledForOsr()) {
@@ -788,14 +791,7 @@
   }
 }
 
-void FlowGraphCompiler::CompileGraph() {
-  InitCompiler();
-
-  if (TryIntrinsify()) {
-    // Skip regular code generation.
-    return;
-  }
-
+void FlowGraphCompiler::EmitPrologue() {
   EmitFrameEntry();
 
   // In unoptimized code, initialize (non-argument) stack allocated slots.
@@ -823,11 +819,18 @@
   }
 
   EndCodeSourceRange(TokenPosition::kDartCodePrologue);
+}
+
+void FlowGraphCompiler::CompileGraph() {
+  InitCompiler();
+
   ASSERT(!block_order().is_empty());
   VisitBlocks();
 
-  __ int3();
-  GenerateDeferredCode();
+  if (!skip_body_compilation()) {
+    __ int3();
+    GenerateDeferredCode();
+  }
 }
 
 void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
@@ -911,7 +914,9 @@
   // top-level function (parsed_function().function()) which could be
   // reoptimized and which counter needs to be incremented.
   // Pass the function explicitly, it is used in IC stub.
-  __ LoadObject(EBX, parsed_function().function());
+  __ LoadObject(EAX, parsed_function().function());
+  // Load receiver into EBX.
+  __ movl(EBX, Address(ESP, (ic_data.CountWithoutTypeArgs() - 1) * kWordSize));
   __ LoadObject(ECX, ic_data);
   GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.CountWithTypeArgs());
@@ -923,8 +928,11 @@
                                          TokenPosition token_pos,
                                          LocationSummary* locs) {
   ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
+  // Load receiver into EBX.
+  __ movl(EBX, Address(ESP, (ic_data.CountWithoutTypeArgs() - 1) * kWordSize));
   __ LoadObject(ECX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs,
+                   Code::EntryKind::kMonomorphic);
   __ Drop(ic_data.CountWithTypeArgs());
 }
 
@@ -947,7 +955,6 @@
   __ movl(EBX, Address(ESP, (args_desc.Count() - 1) * kWordSize));
   __ LoadObject(ECX, cache);
   __ call(Address(THR, Thread::megamorphic_call_checked_entry_offset()));
-  __ call(EBX);
 
   AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone, token_pos);
   RecordSafepoint(locs, slow_path_argument_count);
@@ -1170,12 +1177,12 @@
 }
 
 #undef __
-#define __ compiler_->assembler()->
+#define __ assembler()->
 
-void ParallelMoveResolver::EmitMove(int index) {
-  MoveOperands* move = moves_[index];
-  const Location source = move->src();
-  const Location destination = move->dest();
+void FlowGraphCompiler::EmitMove(Location destination,
+                                 Location source,
+                                 TemporaryRegisterAllocator* tmp) {
+  if (destination.Equals(source)) return;
 
   if (source.IsRegister()) {
     if (destination.IsRegister()) {
@@ -1187,10 +1194,15 @@
   } else if (source.IsStackSlot()) {
     if (destination.IsRegister()) {
       __ movl(destination.reg(), LocationToStackSlotAddress(source));
+    } else if (destination.IsFpuRegister()) {
+      // 32-bit float
+      __ movss(destination.fpu_reg(), LocationToStackSlotAddress(source));
     } else {
       ASSERT(destination.IsStackSlot());
-      MoveMemoryToMemory(LocationToStackSlotAddress(destination),
-                         LocationToStackSlotAddress(source));
+      Register scratch = tmp->AllocateTemporary();
+      __ MoveMemoryToMemory(LocationToStackSlotAddress(destination),
+                            LocationToStackSlotAddress(source), scratch);
+      tmp->ReleaseTemporary();
     }
   } else if (source.IsFpuRegister()) {
     if (destination.IsFpuRegister()) {
@@ -1200,6 +1212,9 @@
     } else {
       if (destination.IsDoubleStackSlot()) {
         __ movsd(LocationToStackSlotAddress(destination), source.fpu_reg());
+      } else if (destination.IsStackSlot()) {
+        // 32-bit float
+        __ movss(LocationToStackSlotAddress(destination), source.fpu_reg());
       } else {
         ASSERT(destination.IsQuadStackSlot());
         __ movups(LocationToStackSlotAddress(destination), source.fpu_reg());
@@ -1208,27 +1223,37 @@
   } else if (source.IsDoubleStackSlot()) {
     if (destination.IsFpuRegister()) {
       __ movsd(destination.fpu_reg(), LocationToStackSlotAddress(source));
+    } else if (destination.IsStackSlot()) {
+      // Source holds a 32-bit float, take only the lower 32-bits
+      __ movss(FpuTMP, LocationToStackSlotAddress(source));
+      __ movss(LocationToStackSlotAddress(destination), FpuTMP);
     } else {
       ASSERT(destination.IsDoubleStackSlot());
-      __ movsd(XMM0, LocationToStackSlotAddress(source));
-      __ movsd(LocationToStackSlotAddress(destination), XMM0);
+      __ movsd(FpuTMP, LocationToStackSlotAddress(source));
+      __ movsd(LocationToStackSlotAddress(destination), FpuTMP);
     }
   } else if (source.IsQuadStackSlot()) {
     if (destination.IsFpuRegister()) {
       __ movups(destination.fpu_reg(), LocationToStackSlotAddress(source));
     } else {
       ASSERT(destination.IsQuadStackSlot());
-      __ movups(XMM0, LocationToStackSlotAddress(source));
-      __ movups(LocationToStackSlotAddress(destination), XMM0);
+      __ movups(FpuTMP, LocationToStackSlotAddress(source));
+      __ movups(LocationToStackSlotAddress(destination), FpuTMP);
+    }
+  } else if (source.IsPairLocation()) {
+    ASSERT(destination.IsPairLocation());
+    for (intptr_t i : {0, 1}) {
+      EmitMove(destination.Component(i), source.Component(i), tmp);
     }
   } else {
     ASSERT(source.IsConstant());
-    source.constant_instruction()->EmitMoveToLocation(compiler_, destination);
+    source.constant_instruction()->EmitMoveToLocation(this, destination);
   }
-
-  move->Eliminate();
 }
 
+#undef __
+#define __ compiler_->assembler()->
+
 void ParallelMoveResolver::EmitSwap(int index) {
   MoveOperands* move = moves_[index];
   const Location source = move->src();
@@ -1244,9 +1269,9 @@
     Exchange(LocationToStackSlotAddress(destination),
              LocationToStackSlotAddress(source));
   } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
-    __ movaps(XMM0, source.fpu_reg());
+    __ movaps(FpuTMP, source.fpu_reg());
     __ movaps(source.fpu_reg(), destination.fpu_reg());
-    __ movaps(destination.fpu_reg(), XMM0);
+    __ movaps(destination.fpu_reg(), FpuTMP);
   } else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
     ASSERT(destination.IsDoubleStackSlot() || destination.IsQuadStackSlot() ||
            source.IsDoubleStackSlot() || source.IsQuadStackSlot());
@@ -1259,32 +1284,32 @@
                                       : LocationToStackSlotAddress(source);
 
     if (double_width) {
-      __ movsd(XMM0, slot_address);
+      __ movsd(FpuTMP, slot_address);
       __ movsd(slot_address, reg);
     } else {
-      __ movups(XMM0, slot_address);
+      __ movups(FpuTMP, slot_address);
       __ movups(slot_address, reg);
     }
-    __ movaps(reg, XMM0);
+    __ movaps(reg, FpuTMP);
   } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
     const Address& source_slot_address = LocationToStackSlotAddress(source);
     const Address& destination_slot_address =
         LocationToStackSlotAddress(destination);
 
-    ScratchFpuRegisterScope ensure_scratch(this, XMM0);
-    __ movsd(XMM0, source_slot_address);
+    ScratchFpuRegisterScope ensure_scratch(this, FpuTMP);
+    __ movsd(FpuTMP, source_slot_address);
     __ movsd(ensure_scratch.reg(), destination_slot_address);
-    __ movsd(destination_slot_address, XMM0);
+    __ movsd(destination_slot_address, FpuTMP);
     __ movsd(source_slot_address, ensure_scratch.reg());
   } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
     const Address& source_slot_address = LocationToStackSlotAddress(source);
     const Address& destination_slot_address =
         LocationToStackSlotAddress(destination);
 
-    ScratchFpuRegisterScope ensure_scratch(this, XMM0);
-    __ movups(XMM0, source_slot_address);
+    ScratchFpuRegisterScope ensure_scratch(this, FpuTMP);
+    __ movups(FpuTMP, source_slot_address);
     __ movups(ensure_scratch.reg(), destination_slot_address);
-    __ movups(destination_slot_address, XMM0);
+    __ movups(destination_slot_address, FpuTMP);
     __ movups(source_slot_address, ensure_scratch.reg());
   } else {
     UNREACHABLE();
@@ -1310,8 +1335,7 @@
 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
                                               const Address& src) {
   ScratchRegisterScope ensure_scratch(this, kNoRegister);
-  __ movl(ensure_scratch.reg(), src);
-  __ movl(dst, ensure_scratch.reg());
+  __ MoveMemoryToMemory(dst, src, ensure_scratch.reg());
 }
 
 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 192a903..5542b19 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -858,18 +858,12 @@
     ASSERT(extra_slots >= 0);
     __ EnterOsrFrame(extra_slots * kWordSize);
   } else {
-    const Register new_pp = R13;
-    if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
-      __ LoadPoolPointer(new_pp);
-    }
-
     const Function& function = parsed_function().function();
     if (CanOptimizeFunction() && function.IsOptimizable() &&
         (!is_optimizing() || may_reoptimize())) {
       __ Comment("Invocation Count Check");
       const Register function_reg = RDI;
-      // Load function object using the callee's pool pointer.
-      __ LoadFunctionFromCalleePool(function_reg, function, new_pp);
+      __ movq(function_reg, FieldAddress(CODE_REG, Code::owner_offset()));
 
       // Reoptimization of an optimized function is triggered by counting in
       // IC stubs, but not at the entry of the function.
@@ -879,11 +873,14 @@
       __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()),
               Immediate(GetOptimizationThreshold()));
       ASSERT(function_reg == RDI);
-      __ J(GREATER_EQUAL, StubCode::OptimizeFunction(), new_pp);
+      Label dont_optimize;
+      __ j(LESS, &dont_optimize, Assembler::kNearJump);
+      __ jmp(Address(THR, Thread::optimize_entry_offset()));
+      __ Bind(&dont_optimize);
     }
     ASSERT(StackSize() >= 0);
     __ Comment("Enter frame");
-    __ EnterDartFrame(StackSize() * kWordSize, new_pp);
+    __ EnterDartFrame(StackSize() * kWordSize);
   }
 }
 
@@ -933,7 +930,7 @@
 
   __ int3();
 
-  if (!fully_intrinsified_) {
+  if (!skip_body_compilation()) {
     ASSERT(assembler()->constant_pool_allowed());
     GenerateDeferredCode();
   }
@@ -1046,6 +1043,8 @@
   // reoptimized and which counter needs to be incremented.
   // Pass the function explicitly, it is used in IC stub.
   __ LoadObject(RDI, parsed_function().function());
+  // Load receiver into RDX.
+  __ movq(RDX, Address(RSP, (ic_data.CountWithoutTypeArgs() - 1) * kWordSize));
   __ LoadUniqueObject(RBX, ic_data);
   GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs,
                    entry_kind);
@@ -1058,8 +1057,11 @@
                                          TokenPosition token_pos,
                                          LocationSummary* locs) {
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
+  // Load receiver into RDX.
+  __ movq(RDX, Address(RSP, (ic_data.CountWithoutTypeArgs() - 1) * kWordSize));
   __ LoadUniqueObject(RBX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs,
+                   Code::EntryKind::kMonomorphic);
   __ Drop(ic_data.CountWithTypeArgs(), RCX);
 }
 
@@ -1077,8 +1079,8 @@
       zone(),
       MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
   __ Comment("MegamorphicCall");
-  // Load receiver into RDI.
-  __ movq(RDI, Address(RSP, (args_desc.Count() - 1) * kWordSize));
+  // Load receiver into RDX.
+  __ movq(RDX, Address(RSP, (args_desc.Count() - 1) * kWordSize));
   __ LoadObject(RBX, cache);
   __ call(Address(THR, Thread::megamorphic_call_checked_entry_offset()));
 
@@ -1116,7 +1118,7 @@
   const Code& initial_stub = StubCode::ICCallThroughFunction();
 
   __ Comment("SwitchableCall");
-  __ movq(RDI, Address(RSP, (ic_data.CountWithoutTypeArgs() - 1) * kWordSize));
+  __ movq(RDX, Address(RSP, (ic_data.CountWithoutTypeArgs() - 1) * kWordSize));
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     // The AOT runtime will replace the slot in the object pool with the
     // entrypoint address - see clustered_snapshot.cc.
@@ -1296,33 +1298,31 @@
 }
 
 #undef __
-#define __ compiler_->assembler()->
+#define __ assembler()->
 
-void ParallelMoveResolver::EmitMove(int index) {
-  MoveOperands* move = moves_[index];
-  const Location source = move->src();
-  const Location destination = move->dest();
+void FlowGraphCompiler::EmitMove(Location destination,
+                                 Location source,
+                                 TemporaryRegisterAllocator* tmp) {
+  if (destination.Equals(source)) return;
 
   if (source.IsRegister()) {
     if (destination.IsRegister()) {
       __ movq(destination.reg(), source.reg());
     } else {
       ASSERT(destination.IsStackSlot());
-      ASSERT((destination.base_reg() != FPREG) ||
-             ((-compiler::target::frame_layout.VariableIndexForFrameSlot(
-                  destination.stack_index())) < compiler_->StackSize()));
       __ movq(LocationToStackSlotAddress(destination), source.reg());
     }
   } else if (source.IsStackSlot()) {
-    ASSERT((source.base_reg() != FPREG) ||
-           ((-compiler::target::frame_layout.VariableIndexForFrameSlot(
-                source.stack_index())) < compiler_->StackSize()));
     if (destination.IsRegister()) {
       __ movq(destination.reg(), LocationToStackSlotAddress(source));
+    } else if (destination.IsFpuRegister()) {
+      // 32-bit float
+      __ movq(TMP, LocationToStackSlotAddress(source));
+      __ movq(destination.fpu_reg(), TMP);
     } else {
       ASSERT(destination.IsStackSlot());
-      MoveMemoryToMemory(LocationToStackSlotAddress(destination),
-                         LocationToStackSlotAddress(source));
+      __ MoveMemoryToMemory(LocationToStackSlotAddress(destination),
+                            LocationToStackSlotAddress(source));
     }
   } else if (source.IsFpuRegister()) {
     if (destination.IsFpuRegister()) {
@@ -1341,32 +1341,35 @@
     if (destination.IsFpuRegister()) {
       __ movsd(destination.fpu_reg(), LocationToStackSlotAddress(source));
     } else {
-      ASSERT(destination.IsDoubleStackSlot());
-      __ movsd(XMM0, LocationToStackSlotAddress(source));
-      __ movsd(LocationToStackSlotAddress(destination), XMM0);
+      ASSERT(destination.IsDoubleStackSlot() ||
+             destination.IsStackSlot() /*32-bit float*/);
+      __ movsd(FpuTMP, LocationToStackSlotAddress(source));
+      __ movsd(LocationToStackSlotAddress(destination), FpuTMP);
     }
   } else if (source.IsQuadStackSlot()) {
     if (destination.IsFpuRegister()) {
       __ movups(destination.fpu_reg(), LocationToStackSlotAddress(source));
     } else {
       ASSERT(destination.IsQuadStackSlot());
-      __ movups(XMM0, LocationToStackSlotAddress(source));
-      __ movups(LocationToStackSlotAddress(destination), XMM0);
+      __ movups(FpuTMP, LocationToStackSlotAddress(source));
+      __ movups(LocationToStackSlotAddress(destination), FpuTMP);
     }
   } else {
     ASSERT(source.IsConstant());
     if (destination.IsFpuRegister() || destination.IsDoubleStackSlot()) {
-      ScratchRegisterScope scratch(this, kNoRegister);
-      source.constant_instruction()->EmitMoveToLocation(compiler_, destination,
-                                                        scratch.reg());
+      Register scratch = tmp->AllocateTemporary();
+      source.constant_instruction()->EmitMoveToLocation(this, destination,
+                                                        scratch);
+      tmp->ReleaseTemporary();
     } else {
-      source.constant_instruction()->EmitMoveToLocation(compiler_, destination);
+      source.constant_instruction()->EmitMoveToLocation(this, destination);
     }
   }
-
-  move->Eliminate();
 }
 
+#undef __
+#define __ compiler_->assembler()->
+
 void ParallelMoveResolver::EmitSwap(int index) {
   MoveOperands* move = moves_[index];
   const Location source = move->src();
@@ -1382,9 +1385,9 @@
     Exchange(LocationToStackSlotAddress(destination),
              LocationToStackSlotAddress(source));
   } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
-    __ movaps(XMM0, source.fpu_reg());
+    __ movaps(FpuTMP, source.fpu_reg());
     __ movaps(source.fpu_reg(), destination.fpu_reg());
-    __ movaps(destination.fpu_reg(), XMM0);
+    __ movaps(destination.fpu_reg(), FpuTMP);
   } else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
     ASSERT(destination.IsDoubleStackSlot() || destination.IsQuadStackSlot() ||
            source.IsDoubleStackSlot() || source.IsQuadStackSlot());
@@ -1397,32 +1400,32 @@
                                : LocationToStackSlotAddress(source);
 
     if (double_width) {
-      __ movsd(XMM0, slot_address);
+      __ movsd(FpuTMP, slot_address);
       __ movsd(slot_address, reg);
     } else {
-      __ movups(XMM0, slot_address);
+      __ movups(FpuTMP, slot_address);
       __ movups(slot_address, reg);
     }
-    __ movaps(reg, XMM0);
+    __ movaps(reg, FpuTMP);
   } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
     const Address& source_slot_address = LocationToStackSlotAddress(source);
     const Address& destination_slot_address =
         LocationToStackSlotAddress(destination);
 
-    ScratchFpuRegisterScope ensure_scratch(this, XMM0);
-    __ movsd(XMM0, source_slot_address);
+    ScratchFpuRegisterScope ensure_scratch(this, FpuTMP);
+    __ movsd(FpuTMP, source_slot_address);
     __ movsd(ensure_scratch.reg(), destination_slot_address);
-    __ movsd(destination_slot_address, XMM0);
+    __ movsd(destination_slot_address, FpuTMP);
     __ movsd(source_slot_address, ensure_scratch.reg());
   } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
     const Address& source_slot_address = LocationToStackSlotAddress(source);
     const Address& destination_slot_address =
         LocationToStackSlotAddress(destination);
 
-    ScratchFpuRegisterScope ensure_scratch(this, XMM0);
-    __ movups(XMM0, source_slot_address);
+    ScratchFpuRegisterScope ensure_scratch(this, FpuTMP);
+    __ movups(FpuTMP, source_slot_address);
     __ movups(ensure_scratch.reg(), destination_slot_address);
-    __ movups(destination_slot_address, XMM0);
+    __ movups(destination_slot_address, FpuTMP);
     __ movups(source_slot_address, ensure_scratch.reg());
   } else {
     UNREACHABLE();
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 92b725f..6c06e20 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -27,6 +27,7 @@
 #include "vm/regexp_assembler_ir.h"
 #include "vm/resolver.h"
 #include "vm/scopes.h"
+#include "vm/stack_frame.h"
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
 #include "vm/type_testing_stubs.h"
@@ -649,24 +650,75 @@
   return cids;
 }
 
-Cids* Cids::Create(Zone* zone, const ICData& ic_data, int argument_number) {
+Cids* Cids::CreateAndExpand(Zone* zone,
+                            const ICData& ic_data,
+                            int argument_number) {
   Cids* cids = new (zone) Cids(zone);
   cids->CreateHelper(zone, ic_data, argument_number,
                      /* include_targets = */ false);
   cids->Sort(OrderById);
 
   // Merge adjacent class id ranges.
-  int dest = 0;
-  for (int src = 1; src < cids->length(); src++) {
-    if (cids->cid_ranges_[dest]->cid_end + 1 >=
-        cids->cid_ranges_[src]->cid_start) {
-      cids->cid_ranges_[dest]->cid_end = cids->cid_ranges_[src]->cid_end;
-    } else {
-      dest++;
-      if (src != dest) cids->cid_ranges_[dest] = cids->cid_ranges_[src];
+  {
+    int dest = 0;
+    for (int src = 1; src < cids->length(); src++) {
+      if (cids->cid_ranges_[dest]->cid_end + 1 >=
+          cids->cid_ranges_[src]->cid_start) {
+        cids->cid_ranges_[dest]->cid_end = cids->cid_ranges_[src]->cid_end;
+      } else {
+        dest++;
+        if (src != dest) cids->cid_ranges_[dest] = cids->cid_ranges_[src];
+      }
+    }
+    cids->SetLength(dest + 1);
+  }
+
+  // Merging/extending cid ranges is also done in CallTargets::CreateAndExpand.
+  // If changing this code, consider also adjusting CallTargets code.
+
+  if (cids->length() > 1 && argument_number == 0 && ic_data.HasOneTarget()) {
+    // Try harder to merge ranges if method lookups in the gaps result in the
+    // same target method.
+    const Function& target = Function::Handle(zone, ic_data.GetTargetAt(0));
+    if (!MethodRecognizer::PolymorphicTarget(target)) {
+      const auto& args_desc_array =
+          Array::Handle(zone, ic_data.arguments_descriptor());
+      ArgumentsDescriptor args_desc(args_desc_array);
+      const auto& name = String::Handle(zone, ic_data.target_name());
+      auto& fn = Function::Handle(zone);
+
+      intptr_t dest = 0;
+      for (intptr_t src = 1; src < cids->length(); src++) {
+        // Inspect all cids in the gap and see if they all resolve to the same
+        // target.
+        bool can_merge = true;
+        for (intptr_t cid = cids->cid_ranges_[dest]->cid_end + 1,
+                      end = cids->cid_ranges_[src]->cid_start;
+             cid < end; ++cid) {
+          bool class_is_abstract = false;
+          if (FlowGraphCompiler::LookupMethodFor(cid, name, args_desc, &fn,
+                                                 &class_is_abstract)) {
+            if (fn.raw() == target.raw()) {
+              continue;
+            }
+            if (class_is_abstract) {
+              continue;
+            }
+          }
+          can_merge = false;
+          break;
+        }
+
+        if (can_merge) {
+          cids->cid_ranges_[dest]->cid_end = cids->cid_ranges_[src]->cid_end;
+        } else {
+          dest++;
+          if (src != dest) cids->cid_ranges_[dest] = cids->cid_ranges_[src];
+        }
+      }
+      cids->SetLength(dest + 1);
     }
   }
-  cids->SetLength(dest + 1);
 
   return cids;
 }
@@ -771,7 +823,7 @@
 
   intptr_t min = cids.ComputeLowestCid();
   intptr_t max = cids.ComputeHighestCid();
-  return (max - min) < kBitsPerWord;
+  return (max - min) < compiler::target::kBitsPerWord;
 }
 
 bool CheckClassInstr::IsBitTest() const {
@@ -785,7 +837,7 @@
   for (intptr_t i = 0; i < cids_.length(); ++i) {
     intptr_t run;
     uintptr_t range = 1ul + cids_[i].Extent();
-    if (range >= static_cast<uintptr_t>(kBitsPerWord)) {
+    if (range >= static_cast<uintptr_t>(compiler::target::kBitsPerWord)) {
       run = -1;
     } else {
       run = (1 << range) - 1;
@@ -1173,9 +1225,6 @@
   // immediate objects (Smis) or permanent objects (vm-isolate heap or
   // image pages). Here we choose to skip the barrier for any constant on
   // the assumption it will remain reachable through the object pool.
-  // TODO(concurrent-marking): Consider ensuring marking is not in progress
-  // when code is disabled or only omitting the barrier if code collection
-  // is disabled.
 
   return !BindsToConstant();
 }
@@ -1263,6 +1312,7 @@
     while (next != NULL) {
       current = next;
       current->set_definition(other);
+      current->RefineReachingType(other->Type());
       next = current->next_use();
     }
 
@@ -1281,6 +1331,7 @@
     while (next != NULL) {
       current = next;
       current->set_definition(other);
+      current->RefineReachingType(other->Type());
       next = current->next_use();
     }
     next = other->env_use_list();
@@ -1784,7 +1835,7 @@
   }
   const intptr_t value_cid = value()->Type()->ToCid();
   if (value_cid == kSmiCid) {
-    return (kSmiBits > 32) && !is_truncating() &&
+    return (compiler::target::kSmiBits > 32) && !is_truncating() &&
            !RangeUtils::Fits(value()->definition()->range(),
                              RangeBoundary::kRangeBoundaryInt32);
   } else if (value_cid == kMintCid) {
@@ -1793,7 +1844,7 @@
                              RangeBoundary::kRangeBoundaryInt32);
   } else if (is_truncating() && value()->definition()->IsBoxInteger()) {
     return false;
-  } else if ((kSmiBits < 32) && value()->Type()->IsInt()) {
+  } else if ((compiler::target::kSmiBits < 32) && value()->Type()->IsInt()) {
     return !RangeUtils::Fits(value()->definition()->range(),
                              RangeBoundary::kRangeBoundaryInt32);
   } else {
@@ -1884,7 +1935,7 @@
 static intptr_t RepresentationBits(Representation r) {
   switch (r) {
     case kTagged:
-      return kBitsPerWord - 1;
+      return compiler::target::kBitsPerWord - 1;
     case kUnboxedInt32:
     case kUnboxedUint32:
       return 32;
@@ -2635,6 +2686,30 @@
   }
 }
 
+bool LoadFieldInstr::IsTypedDataViewFactory(const Function& function) {
+  auto kind = MethodRecognizer::RecognizeKind(function);
+  switch (kind) {
+    case MethodRecognizer::kTypedData_ByteDataView_factory:
+    case MethodRecognizer::kTypedData_Int8ArrayView_factory:
+    case MethodRecognizer::kTypedData_Uint8ArrayView_factory:
+    case MethodRecognizer::kTypedData_Uint8ClampedArrayView_factory:
+    case MethodRecognizer::kTypedData_Int16ArrayView_factory:
+    case MethodRecognizer::kTypedData_Uint16ArrayView_factory:
+    case MethodRecognizer::kTypedData_Int32ArrayView_factory:
+    case MethodRecognizer::kTypedData_Uint32ArrayView_factory:
+    case MethodRecognizer::kTypedData_Int64ArrayView_factory:
+    case MethodRecognizer::kTypedData_Uint64ArrayView_factory:
+    case MethodRecognizer::kTypedData_Float32ArrayView_factory:
+    case MethodRecognizer::kTypedData_Float64ArrayView_factory:
+    case MethodRecognizer::kTypedData_Float32x4ArrayView_factory:
+    case MethodRecognizer::kTypedData_Int32x4ArrayView_factory:
+    case MethodRecognizer::kTypedData_Float64x2ArrayView_factory:
+      return true;
+    default:
+      return false;
+  }
+}
+
 Definition* ConstantInstr::Canonicalize(FlowGraph* flow_graph) {
   return HasUses() ? this : NULL;
 }
@@ -2706,6 +2781,21 @@
       if (call->is_known_list_constructor() &&
           IsFixedLengthArrayCid(call->Type()->ToCid())) {
         return call->ArgumentAt(1);
+      } else if (call->function().recognized_kind() ==
+                 MethodRecognizer::kByteDataFactory) {
+        // Similarly, we check for the ByteData constructor and forward its
+        // explicit length argument appropriately.
+        return call->ArgumentAt(1);
+      } else if (IsTypedDataViewFactory(call->function())) {
+        // Typed data view factories all take three arguments (after
+        // the implicit type arguments parameter):
+        //
+        // 1) _TypedList buffer -- the underlying data for the view
+        // 2) int offsetInBytes -- the offset into the buffer to start viewing
+        // 3) int length        -- the number of elements in the view
+        //
+        // Here, we forward the third.
+        return call->ArgumentAt(3);
       }
     } else if (CreateArrayInstr* create_array = array->AsCreateArray()) {
       if (slot().kind() == Slot::Kind::kArray_length) {
@@ -2722,15 +2812,44 @@
         }
       }
     }
+  } else if (slot().kind() == Slot::Kind::kTypedDataView_data) {
+    // This case cover the first explicit argument to typed data view
+    // factories, the data (buffer).
+    Definition* array = instance()->definition()->OriginalDefinition();
+    if (StaticCallInstr* call = array->AsStaticCall()) {
+      if (IsTypedDataViewFactory(call->function())) {
+        return call->ArgumentAt(1);
+      }
+    }
+  } else if (slot().kind() == Slot::Kind::kTypedDataView_offset_in_bytes) {
+    // This case cover the second explicit argument to typed data view
+    // factories, the offset into the buffer.
+    Definition* array = instance()->definition()->OriginalDefinition();
+    if (StaticCallInstr* call = array->AsStaticCall()) {
+      if (IsTypedDataViewFactory(call->function())) {
+        return call->ArgumentAt(2);
+      } else if (call->function().recognized_kind() ==
+                 MethodRecognizer::kByteDataFactory) {
+        // A _ByteDataView returned from the ByteData constructor always
+        // has an offset of 0.
+        return flow_graph->GetConstant(Smi::Handle(Smi::New(0)));
+      }
+    }
   } else if (slot().IsTypeArguments()) {
     Definition* array = instance()->definition()->OriginalDefinition();
     if (StaticCallInstr* call = array->AsStaticCall()) {
       if (call->is_known_list_constructor()) {
         return call->ArgumentAt(0);
-      } else if (call->function().recognized_kind() ==
-                 MethodRecognizer::kLinkedHashMap_getData) {
+      } else if (IsTypedDataViewFactory(call->function())) {
         return flow_graph->constant_null();
       }
+      switch (call->function().recognized_kind()) {
+        case MethodRecognizer::kByteDataFactory:
+        case MethodRecognizer::kLinkedHashMap_getData:
+          return flow_graph->constant_null();
+        default:
+          break;
+      }
     } else if (CreateArrayInstr* create_array = array->AsCreateArray()) {
       return create_array->element_type()->definition();
     } else if (LoadFieldInstr* load_array = array->AsLoadField()) {
@@ -3065,7 +3184,7 @@
 // (on simdbc64 the [UnboxedConstantInstr] handling is only implemented for
 //  doubles and causes a bailout for everthing else)
 #if !defined(TARGET_ARCH_DBC)
-  if (kBitsPerWord == 64) {
+  if (compiler::target::kBitsPerWord == 64) {
     ConstantInstr* c = value()->definition()->AsConstant();
     if (c != NULL && (c->value().IsSmi() || c->value().IsMint())) {
       UnboxedConstantInstr* uc =
@@ -3365,6 +3484,15 @@
   return cids().HasClassId(value_cid) ? NULL : this;
 }
 
+Definition* LoadClassIdInstr::Canonicalize(FlowGraph* flow_graph) {
+  const intptr_t cid = object()->Type()->ToCid();
+  if (cid != kDynamicCid) {
+    const auto& smi = Smi::ZoneHandle(flow_graph->zone(), Smi::New(cid));
+    return flow_graph->GetConstant(smi);
+  }
+  return this;
+}
+
 Instruction* CheckClassIdInstr::Canonicalize(FlowGraph* flow_graph) {
   if (value()->BindsToConstant()) {
     const Object& constant_value = value()->BoundConstant();
@@ -3464,6 +3592,11 @@
   if (call->is_known_list_constructor() &&
       LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) {
     length = call->ArgumentAt(1)->AsConstant();
+  } else if (call->function().recognized_kind() ==
+             MethodRecognizer::kByteDataFactory) {
+    length = call->ArgumentAt(1)->AsConstant();
+  } else if (LoadFieldInstr::IsTypedDataViewFactory(call->function())) {
+    length = call->ArgumentAt(3)->AsConstant();
   }
   if ((length != NULL) && length->value().IsSmi() &&
       Smi::Cast(length->value()).Value() == expected_length) {
@@ -3593,6 +3726,9 @@
 
   intptr_t length = targets.length();
 
+  // Merging/extending cid ranges is also done in Cids::CreateAndExpand.
+  // If changing this code, consider also adjusting Cids code.
+
   // Spread class-ids to preceding classes where a lookup yields the same
   // method.  A polymorphic target is not really the same method since its
   // behaviour depends on the receiver class-id, so we don't spread the
@@ -3767,27 +3903,34 @@
     __ nop();
   }
 #endif
-  __ Bind(compiler->GetJumpLabel(this));
+  if (tag() == Instruction::kFunctionEntry) {
+    __ Bind(compiler->GetJumpLabel(this));
+  }
 
 // In the AOT compiler we want to reduce code size, so generate no
 // fall-through code in [FlowGraphCompiler::CompileGraph()].
 // (As opposed to here where we don't check for the return value of
 // [Intrinsify]).
-#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM)
-  if (FLAG_precompiled_mode) {
-    const Function& function = compiler->parsed_function().function();
-    if (function.IsDynamicFunction()) {
-      compiler->SpecialStatsBegin(CombinedCodeStatistics::kTagCheckedEntry);
-      __ MonomorphicCheckedEntry();
-      compiler->SpecialStatsEnd(CombinedCodeStatistics::kTagCheckedEntry);
-    }
+  const Function& function = compiler->parsed_function().function();
+  if (function.IsDynamicFunction()) {
+    compiler->SpecialStatsBegin(CombinedCodeStatistics::kTagCheckedEntry);
+    __ MonomorphicCheckedEntry();
+    compiler->SpecialStatsEnd(CombinedCodeStatistics::kTagCheckedEntry);
   }
-  // NOTE: Because in X64/ARM mode the graph can have multiple entrypoints, we
-  // generate several times the same intrinsification & frame setup. That's why
-  // we cannot rely on the constant pool being `false` when we come in here.
+
+  // NOTE: Because of the presence of multiple entry-points, we generate several
+  // times the same intrinsification & frame setup. That's why we cannot rely on
+  // the constant pool being `false` when we come in here.
+#if defined(TARGET_USES_OBJECT_POOL)
   __ set_constant_pool_allowed(false);
-  if (compiler->TryIntrinsify()) return;
+#endif
+
+  if (compiler->TryIntrinsify() && compiler->skip_body_compilation()) {
+    return;
+  }
   compiler->EmitPrologue();
+
+#if defined(TARGET_USES_OBJECT_POOL)
   ASSERT(__ constant_pool_allowed());
 #endif
 
@@ -3814,6 +3957,11 @@
   }
 }
 
+LocationSummary* NativeEntryInstr::MakeLocationSummary(Zone* zone,
+                                                       bool optimizing) const {
+  UNREACHABLE();
+}
+
 LocationSummary* OsrEntryInstr::MakeLocationSummary(Zone* zone,
                                                     bool optimizing) const {
   UNREACHABLE();
@@ -3825,13 +3973,16 @@
   ASSERT(compiler->is_optimizing());
   __ Bind(compiler->GetJumpLabel(this));
 
-#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM)
-  // NOTE: Because in JIT X64/ARM mode the graph can have multiple
-  // entrypoints, so we generate several times the same intrinsification &
-  // frame setup.  That's why we cannot rely on the constant pool being
-  // `false` when we come in here.
+  // NOTE: Because the graph can have multiple entrypoints, we generate several
+  // times the same intrinsification & frame setup. That's why we cannot rely on
+  // the constant pool being `false` when we come in here.
+#if defined(TARGET_USES_OBJECT_POOL)
   __ set_constant_pool_allowed(false);
+#endif
+
   compiler->EmitPrologue();
+
+#if defined(TARGET_USES_OBJECT_POOL)
   ASSERT(__ constant_pool_allowed());
 #endif
 
@@ -3916,6 +4067,43 @@
   UNREACHABLE();
 }
 
+void NativeParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if !defined(TARGET_ARCH_DBC)
+  // The native entry frame has size -kExitLinkSlotFromFp. In order to access
+  // the top of stack from above the entry frame, we add a constant to account
+  // for the the two frame pointers and two return addresses of the entry frame.
+  constexpr intptr_t kEntryFramePadding = 4;
+  FrameRebase rebase(/*old_base=*/SPREG, /*new_base=*/FPREG,
+                     -kExitLinkSlotFromEntryFp + kEntryFramePadding);
+  const Location dst = locs()->out(0);
+  const Location src = rebase.Rebase(loc_);
+  NoTemporaryAllocator no_temp;
+  compiler->EmitMove(dst, src, &no_temp);
+#else
+  UNREACHABLE();
+#endif
+}
+
+LocationSummary* NativeParameterInstr::MakeLocationSummary(Zone* zone,
+                                                           bool opt) const {
+#if !defined(TARGET_ARCH_DBC)
+  ASSERT(opt);
+  Location input = Location::Any();
+  if (representation() == kUnboxedInt64 && compiler::target::kWordSize < 8) {
+    input = Location::Pair(Location::RequiresRegister(),
+                           Location::RequiresFpuRegister());
+  } else {
+    input = RegisterKindForResult() == Location::kRegister
+                ? Location::RequiresRegister()
+                : Location::RequiresFpuRegister();
+  }
+  return LocationSummary::Make(zone, /*num_inputs=*/0, input,
+                               LocationSummary::kNoCall);
+#else
+  UNREACHABLE();
+#endif
+}
+
 bool ParallelMoveInstr::IsRedundant() const {
   for (intptr_t i = 0; i < moves_.length(); i++) {
     if (!moves_[i]->IsRedundant()) {
@@ -4051,8 +4239,8 @@
   switch (kind) {
     case Token::kADD:
       return StubCode::SmiAddInlineCache().raw();
-    case Token::kSUB:
-      return StubCode::SmiSubInlineCache().raw();
+    case Token::kLT:
+      return StubCode::SmiLessInlineCache().raw();
     case Token::kEQ:
       return StubCode::SmiEqualInlineCache().raw();
     default:
@@ -4211,7 +4399,7 @@
 }
 
 bool InstanceCallInstr::MatchesCoreName(const String& name) {
-  return function_name().raw() == Library::PrivateCoreLibName(name).raw();
+  return Library::IsPrivateCoreLibName(function_name(), name);
 }
 
 RawFunction* InstanceCallInstr::ResolveForReceiverClass(
@@ -4265,7 +4453,7 @@
   const intptr_t len = targets_.length();
   Function& target = Function::Handle();
   for (intptr_t i = 0; i < len; i++) {
-    target ^= targets_.TargetAt(i)->target->raw();
+    target = targets_.TargetAt(i)->target->raw();
     if (!target.IsDispatcherOrImplicitAccessor()) {
       return false;
     }
@@ -4905,18 +5093,18 @@
   if (RawObject::IsTypedDataClassId(class_id) ||
       RawObject::IsTypedDataViewClassId(class_id) ||
       RawObject::IsExternalTypedDataClassId(class_id)) {
-    return TypedDataBase::length_offset();
+    return compiler::target::TypedDataBase::length_offset();
   }
 
   switch (class_id) {
     case kGrowableObjectArrayCid:
-      return GrowableObjectArray::length_offset();
+      return compiler::target::GrowableObjectArray::length_offset();
     case kOneByteStringCid:
     case kTwoByteStringCid:
-      return String::length_offset();
+      return compiler::target::String::length_offset();
     case kArrayCid:
     case kImmutableArrayCid:
-      return Array::length_offset();
+      return compiler::target::Array::length_offset();
     default:
       UNREACHABLE();
       return -1;
@@ -5164,10 +5352,6 @@
   return "";
 }
 
-const RuntimeEntry& CaseInsensitiveCompareUC16Instr::TargetFunction() const {
-  return kCaseInsensitiveCompareUC16RuntimeEntry;
-}
-
 TruncDivModInstr::TruncDivModInstr(Value* lhs, Value* rhs, intptr_t deopt_id)
     : TemplateDefinition(deopt_id) {
   SetInputAt(0, lhs);
@@ -5227,10 +5411,6 @@
 
 #endif  // defined(TARGET_ARCH_ARM)
 
-#if !defined(TARGET_ARCH_DBC)
-
-#define Z zone_
-
 Representation FfiCallInstr::RequiredInputRepresentation(intptr_t idx) const {
   if (idx == TargetAddressIndex()) {
     return kUnboxedFfiIntPtr;
@@ -5239,6 +5419,10 @@
   }
 }
 
+#if !defined(TARGET_ARCH_DBC)
+
+#define Z zone_
+
 LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
                                                    bool is_optimizing) const {
   // The temporary register needs to be callee-saved and not an argument
@@ -5292,10 +5476,6 @@
   return summary;
 }
 
-Representation FfiCallInstr::representation() const {
-  return compiler::ffi::ResultRepresentation(signature_);
-}
-
 Location FfiCallInstr::UnallocateStackSlots(Location in, bool is_atomic) {
   if (in.IsPairLocation()) {
     ASSERT(!is_atomic);
@@ -5312,25 +5492,48 @@
   }
 }
 
+LocationSummary* NativeReturnInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(0, result_location_);
+  return locs;
+}
+
 #undef Z
 
 #else
 
-Representation FfiCallInstr::RequiredInputRepresentation(intptr_t idx) const {
-  UNREACHABLE();
-}
-
 LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
                                                    bool is_optimizing) const {
-  UNREACHABLE();
-}
+  LocationSummary* summary =
+      new (zone) LocationSummary(zone, /*num_inputs=*/InputCount(),
+                                 /*num_temps=*/0, LocationSummary::kCall);
 
-Representation FfiCallInstr::representation() const {
-  UNREACHABLE();
+  summary->set_in(
+      TargetAddressIndex(),
+      Location::RegisterLocation(compiler::ffi::kFunctionAddressRegister));
+  for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
+    summary->set_in(i, arg_locations_[i]);
+  }
+  summary->set_out(0, compiler::ffi::ResultLocation(
+                          compiler::ffi::ResultHostRepresentation(signature_)));
+
+  return summary;
 }
 
 #endif  // !defined(TARGET_ARCH_DBC)
 
+Representation FfiCallInstr::representation() const {
+#if !defined(TARGET_ARCH_DBC)
+  return compiler::ffi::ResultRepresentation(signature_);
+#else
+  return compiler::ffi::ResultHostRepresentation(signature_);
+#endif  // !defined(TARGET_ARCH_DBC)
+}
+
 // SIMD
 
 SimdOpInstr* SimdOpInstr::CreateFromCall(Zone* zone,
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 3ce025c..757c185 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -18,6 +18,7 @@
 #include "vm/native_entry.h"
 #include "vm/object.h"
 #include "vm/parser.h"
+#include "vm/runtime_entry.h"
 #include "vm/static_type_exactness_state.h"
 #include "vm/token_position.h"
 
@@ -335,18 +336,21 @@
   M(JoinEntry, kNoGC)                                                          \
   M(TargetEntry, kNoGC)                                                        \
   M(FunctionEntry, kNoGC)                                                      \
+  M(NativeEntry, kNoGC)                                                        \
   M(OsrEntry, kNoGC)                                                           \
   M(IndirectEntry, kNoGC)                                                      \
   M(CatchBlockEntry, kNoGC)                                                    \
   M(Phi, kNoGC)                                                                \
   M(Redefinition, kNoGC)                                                       \
   M(Parameter, kNoGC)                                                          \
+  M(NativeParameter, kNoGC)                                                    \
   M(LoadIndexedUnsafe, kNoGC)                                                  \
   M(StoreIndexedUnsafe, kNoGC)                                                 \
   M(TailCall, kNoGC)                                                           \
   M(ParallelMove, kNoGC)                                                       \
   M(PushArgument, kNoGC)                                                       \
   M(Return, kNoGC)                                                             \
+  M(NativeReturn, kNoGC)                                                       \
   M(Throw, kNoGC)                                                              \
   M(ReThrow, kNoGC)                                                            \
   M(Stop, _)                                                                   \
@@ -422,7 +426,7 @@
   M(Unbox, kNoGC)                                                              \
   M(BoxInt64, _)                                                               \
   M(UnboxInt64, kNoGC)                                                         \
-  M(CaseInsensitiveCompareUC16, _)                                             \
+  M(CaseInsensitiveCompare, _)                                                 \
   M(BinaryInt64Op, kNoGC)                                                      \
   M(ShiftInt64Op, kNoGC)                                                       \
   M(SpeculativeShiftInt64Op, kNoGC)                                            \
@@ -554,7 +558,11 @@
   explicit Cids(Zone* zone) : zone_(zone) {}
   // Creates the off-heap Cids object that reflects the contents
   // of the on-VM-heap IC data.
-  static Cids* Create(Zone* zone, const ICData& ic_data, int argument_number);
+  // Ranges of Cids are merged if there is only one target function and
+  // it is used for all cids in the gaps between ranges.
+  static Cids* CreateAndExpand(Zone* zone,
+                               const ICData& ic_data,
+                               int argument_number);
   static Cids* CreateMonomorphic(Zone* zone, intptr_t cid);
 
   bool Equals(const Cids& other) const;
@@ -915,6 +923,28 @@
 
   virtual bool UseSharedSlowPathStub(bool is_optimizing) const { return false; }
 
+  // 'RegisterKindForResult()' returns the register kind necessary to hold the
+  // result.
+  //
+  // This is not virtual because instructions should override representation()
+  // instead.
+  Location::Kind RegisterKindForResult() const {
+    const Representation rep = representation();
+#if !defined(TARGET_ARCH_DBC)
+    if ((rep == kUnboxedFloat) || (rep == kUnboxedDouble) ||
+        (rep == kUnboxedFloat32x4) || (rep == kUnboxedInt32x4) ||
+        (rep == kUnboxedFloat64x2)) {
+      return Location::kFpuRegister;
+    }
+#else
+    // DBC supports only unboxed doubles and does not have distinguished FPU
+    // registers.
+    ASSERT((rep != kUnboxedFloat32x4) && (rep != kUnboxedInt32x4) &&
+           (rep != kUnboxedFloat64x2));
+#endif
+    return Location::kRegister;
+  }
+
  protected:
   // GetDeoptId and/or CopyDeoptIdFrom.
   friend class CallSiteInliner;
@@ -934,8 +964,8 @@
   }
 
  private:
-  friend class BranchInstr;      // For RawSetInputAt.
-  friend class IfThenElseInstr;  // For RawSetInputAt.
+  friend class BranchInstr;          // For RawSetInputAt.
+  friend class IfThenElseInstr;      // For RawSetInputAt.
   friend class CheckConditionInstr;  // For RawSetInputAt.
 
   virtual void RawSetInputAt(intptr_t i, Value* value) = 0;
@@ -1377,8 +1407,7 @@
 
 class GraphEntryInstr : public BlockEntryWithInitialDefs {
  public:
-  GraphEntryInstr(const ParsedFunction& parsed_function,
-                  intptr_t osr_id);
+  GraphEntryInstr(const ParsedFunction& parsed_function, intptr_t osr_id);
 
   DECLARE_INSTRUCTION(GraphEntry)
 
@@ -1614,6 +1643,33 @@
   DISALLOW_COPY_AND_ASSIGN(FunctionEntryInstr);
 };
 
+// Represents entry into a function from native code.
+//
+// Native entries are not allowed to have regular parameters. They should use
+// NativeParameter instead (which doesn't count as an initial definition).
+class NativeEntryInstr : public FunctionEntryInstr {
+ public:
+  NativeEntryInstr(const ZoneGrowableArray<Location>* argument_locations,
+                   GraphEntryInstr* graph_entry,
+                   intptr_t block_id,
+                   intptr_t try_index,
+                   intptr_t deopt_id,
+                   intptr_t callback_id)
+      : FunctionEntryInstr(graph_entry, block_id, try_index, deopt_id),
+        callback_id_(callback_id),
+        argument_locations_(argument_locations) {}
+
+  DECLARE_INSTRUCTION(NativeEntry)
+
+  PRINT_TO_SUPPORT
+
+ private:
+  void SaveArgument(FlowGraphCompiler* compiler, Location loc) const;
+
+  const intptr_t callback_id_;
+  const ZoneGrowableArray<Location>* const argument_locations_;
+};
+
 // Represents an OSR entrypoint to a function.
 //
 // The OSR entry has it's own initial definitions.
@@ -1835,12 +1891,12 @@
   bool HasSSATemp() const { return ssa_temp_index_ >= 0; }
   void ClearSSATempIndex() { ssa_temp_index_ = -1; }
   bool HasPairRepresentation() const {
-#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
-    return representation() == kPairOfTagged;
-#else
-    return (representation() == kPairOfTagged) ||
-           (representation() == kUnboxedInt64);
-#endif
+    if (compiler::target::kWordSize == 8) {
+      return representation() == kPairOfTagged;
+    } else {
+      return (representation() == kPairOfTagged) ||
+             (representation() == kUnboxedInt64);
+    }
   }
 
   // Compile time type of the definition, which may be requested before type
@@ -2160,6 +2216,7 @@
 
   // Get the block entry for that instruction.
   virtual BlockEntryInstr* GetBlock() { return block_; }
+  void set_block(BlockEntryInstr* block) { block_ = block; }
 
   intptr_t InputCount() const { return 0; }
   Value* InputAt(intptr_t i) const {
@@ -2192,6 +2249,57 @@
   DISALLOW_COPY_AND_ASSIGN(ParameterInstr);
 };
 
+// Native parameters are not treated as initial definitions because they cannot
+// be inlined and are only usable in optimized code. The location must be a
+// stack location relative to the position of the stack (SPREG) after
+// register-based arguments have been saved on entry to a native call. See
+// NativeEntryInstr::EmitNativeCode for more details.
+//
+// TOOD(33549): Unify with ParameterInstr.
+class NativeParameterInstr : public Definition {
+ public:
+  NativeParameterInstr(Location loc, Representation representation)
+      : loc_(loc), representation_(representation) {
+    if (loc.IsPairLocation()) {
+      for (intptr_t i : {0, 1}) {
+        ASSERT(loc_.Component(i).HasStackIndex() &&
+               loc_.Component(i).base_reg() == SPREG);
+      }
+    } else {
+      ASSERT(loc_.HasStackIndex() && loc_.base_reg() == SPREG);
+    }
+  }
+
+  DECLARE_INSTRUCTION(NativeParameter)
+
+  virtual Representation representation() const { return representation_; }
+
+  intptr_t InputCount() const { return 0; }
+  Value* InputAt(intptr_t i) const {
+    UNREACHABLE();
+    return NULL;
+  }
+
+  virtual bool ComputeCanDeoptimize() const { return false; }
+
+  virtual bool HasUnknownSideEffects() const { return false; }
+
+  // TODO(sjindel): We can make this more precise.
+  virtual CompileType ComputeType() const { return CompileType::Dynamic(); }
+
+  virtual bool MayThrow() const { return false; }
+
+  PRINT_OPERANDS_TO_SUPPORT
+
+ private:
+  virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
+
+  const Location loc_;
+  const Representation representation_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeParameterInstr);
+};
+
 // Stores a tagged pointer to a slot accessible from a fixed register.  It has
 // the form:
 //
@@ -2255,8 +2363,11 @@
 // the frame.  This is asserted via `inliner.cc::CalleeGraphValidator`.
 class LoadIndexedUnsafeInstr : public TemplateDefinition<1, NoThrow> {
  public:
-  LoadIndexedUnsafeInstr(Value* index, intptr_t offset, CompileType result_type)
-      : offset_(offset) {
+  LoadIndexedUnsafeInstr(Value* index,
+                         intptr_t offset,
+                         CompileType result_type,
+                         Representation representation = kTagged)
+      : offset_(offset), representation_(representation) {
     UpdateType(result_type);
     SetInputAt(0, index);
   }
@@ -2267,7 +2378,6 @@
     ASSERT(index == 0);
     return kTagged;
   }
-  virtual Representation representation() const { return kTagged; }
   virtual bool ComputeCanDeoptimize() const { return false; }
   virtual bool HasUnknownSideEffects() const { return false; }
 
@@ -2283,6 +2393,7 @@
 
  private:
   const intptr_t offset_;
+  const Representation representation_;
 
   DISALLOW_COPY_AND_ASSIGN(LoadIndexedUnsafeInstr);
 };
@@ -2392,6 +2503,40 @@
   DISALLOW_COPY_AND_ASSIGN(ReturnInstr);
 };
 
+// Represents a return from a Dart function into native code.
+class NativeReturnInstr : public ReturnInstr {
+ public:
+  NativeReturnInstr(TokenPosition token_pos,
+                    Value* value,
+                    Representation rep,
+                    Location result_location,
+                    intptr_t deopt_id)
+      : ReturnInstr(token_pos, value, deopt_id),
+        result_representation_(rep),
+        result_location_(result_location) {}
+
+  DECLARE_INSTRUCTION(NativeReturn)
+
+  PRINT_OPERANDS_TO_SUPPORT
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT(idx == 0);
+    return result_representation_;
+  }
+
+  virtual bool CanBecomeDeoptimizationTarget() const {
+    // Unlike ReturnInstr, NativeReturnInstr cannot be inlined (because it's
+    // returning into native code).
+    return false;
+  }
+
+ private:
+  const Representation result_representation_;
+  const Location result_location_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeReturnInstr);
+};
+
 class ThrowInstr : public TemplateInstruction<0, Throws> {
  public:
   explicit ThrowInstr(TokenPosition token_pos, intptr_t deopt_id)
@@ -2873,6 +3018,8 @@
 
   const Object& value() const { return value_; }
 
+  bool IsSmi() const { return compiler::target::IsSmi(value()); }
+
   virtual bool ComputeCanDeoptimize() const { return false; }
 
   virtual void InferRange(RangeAnalysis* analysis, Range* range);
@@ -4162,13 +4309,15 @@
                intptr_t deopt_id,
                const Function& signature,
                const ZoneGrowableArray<Representation>& arg_reps,
-               const ZoneGrowableArray<Location>& arg_locs)
+               const ZoneGrowableArray<Location>& arg_locs,
+               const ZoneGrowableArray<HostLocation>* arg_host_locs = nullptr)
       : Definition(deopt_id),
         zone_(zone),
         signature_(signature),
         inputs_(arg_reps.length() + 1),
         arg_representations_(arg_reps),
-        arg_locations_(arg_locs) {
+        arg_locations_(arg_locs),
+        arg_host_locations_(arg_host_locs) {
     inputs_.FillWith(nullptr, 0, arg_reps.length() + 1);
     ASSERT(signature.IsZoneHandle());
   }
@@ -4208,6 +4357,7 @@
   GrowableArray<Value*> inputs_;
   const ZoneGrowableArray<Representation>& arg_representations_;
   const ZoneGrowableArray<Location>& arg_locations_;
+  const ZoneGrowableArray<HostLocation>* arg_host_locations_;
 
   DISALLOW_COPY_AND_ASSIGN(FfiCallInstr);
 };
@@ -4627,7 +4777,11 @@
 
   Value* array() const { return inputs_[0]; }
   Value* index() const { return inputs_[1]; }
-  intptr_t index_scale() const { return Instance::ElementSizeFor(class_id_); }
+
+  intptr_t index_scale() const {
+    return compiler::target::Instance::ElementSizeFor(class_id_);
+  }
+
   intptr_t class_id() const { return class_id_; }
   intptr_t element_count() const { return element_count_; }
 
@@ -4922,7 +5076,7 @@
 
   const Function& closure_function() const { return closure_function_; }
   void set_closure_function(const Function& function) {
-    closure_function_ ^= function.raw();
+    closure_function_ = function.raw();
   }
 
   virtual bool ComputeCanDeoptimize() const { return false; }
@@ -4979,6 +5133,7 @@
   }
 
   static bool WillAllocateNewOrRemembered(intptr_t num_context_variables) {
+    if (!Context::IsValidLength(num_context_variables)) return false;
     return Heap::IsAllocatableInNewSpace(
         Context::InstanceSize(num_context_variables));
   }
@@ -5133,12 +5288,11 @@
     if (!num_elements()->BindsToConstant()) return false;
     const Object& length = num_elements()->BoundConstant();
     if (!length.IsSmi()) return false;
-    const intptr_t value = Smi::Cast(length).Value();
-    if (value < 0) return false;
-    return WillAllocateNewOrRemembered(value);
+    return WillAllocateNewOrRemembered(Smi::Cast(length).Value());
   }
 
   static bool WillAllocateNewOrRemembered(const intptr_t length) {
+    if (!Array::IsValidLength(length)) return false;
     return !Array::UseCardMarkingForAllocation(length);
   }
 
@@ -5243,6 +5397,8 @@
   DECLARE_INSTRUCTION(LoadClassId)
   virtual CompileType ComputeType() const;
 
+  virtual Definition* Canonicalize(FlowGraph* flow_graph);
+
   Value* object() const { return inputs_[0]; }
 
   virtual bool ComputeCanDeoptimize() const { return false; }
@@ -5303,6 +5459,7 @@
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
   static bool IsFixedLengthArrayCid(intptr_t cid);
+  static bool IsTypedDataViewFactory(const Function& function);
 
   virtual bool AllowsCSE() const { return slot_.is_immutable(); }
   virtual bool HasUnknownSideEffects() const { return false; }
@@ -5429,6 +5586,7 @@
   }
 
   static bool WillAllocateNewOrRemembered(intptr_t num_context_variables) {
+    if (!Context::IsValidLength(num_context_variables)) return false;
     return Heap::IsAllocatableInNewSpace(
         Context::InstanceSize(num_context_variables));
   }
@@ -5620,6 +5778,10 @@
     SetInputAt(0, value);
   }
 
+#if defined(TARGET_ARCH_DBC)
+  void EmitAllocateBox(FlowGraphCompiler* compiler);
+#endif
+
  private:
   intptr_t ValueOffset() const {
     return Boxing::ValueOffset(from_representation());
@@ -5786,6 +5948,8 @@
 
   bool is_truncating() const { return is_truncating_; }
 
+  void mark_truncating() { is_truncating_ = true; }
+
   virtual CompileType ComputeType() const;
 
   virtual bool AttributesEqual(Instruction* other) const {
@@ -5951,18 +6115,18 @@
 // Calls into the runtime and performs a case-insensitive comparison of the
 // UTF16 strings (i.e. TwoByteString or ExternalTwoByteString) located at
 // str[lhs_index:lhs_index + length] and str[rhs_index:rhs_index + length].
-//
-// TODO(zerny): Remove this once (if) functions inherited from unibrow
-// are moved to dart code.
-class CaseInsensitiveCompareUC16Instr
+// Depending on the runtime entry passed, we will treat the strings as either
+// UCS2 (no surrogate handling) or UTF16 (surrogates handled appropriately).
+class CaseInsensitiveCompareInstr
     : public TemplateDefinition<4, NoThrow, Pure> {
  public:
-  CaseInsensitiveCompareUC16Instr(Value* str,
-                                  Value* lhs_index,
-                                  Value* rhs_index,
-                                  Value* length,
-                                  intptr_t cid)
-      : cid_(cid) {
+  CaseInsensitiveCompareInstr(Value* str,
+                              Value* lhs_index,
+                              Value* rhs_index,
+                              Value* length,
+                              const RuntimeEntry& entry,
+                              intptr_t cid)
+      : entry_(entry), cid_(cid) {
     ASSERT(cid == kTwoByteStringCid || cid == kExternalTwoByteStringCid);
     ASSERT(index_scale() == 2);
     SetInputAt(0, str);
@@ -5976,26 +6140,30 @@
   Value* rhs_index() const { return inputs_[2]; }
   Value* length() const { return inputs_[3]; }
 
-  const RuntimeEntry& TargetFunction() const;
+  const RuntimeEntry& TargetFunction() const { return entry_; }
   bool IsExternal() const { return cid_ == kExternalTwoByteStringCid; }
   intptr_t class_id() const { return cid_; }
-  intptr_t index_scale() const { return Instance::ElementSizeFor(cid_); }
+
+  intptr_t index_scale() const {
+    return compiler::target::Instance::ElementSizeFor(cid_);
+  }
 
   virtual bool ComputeCanDeoptimize() const { return false; }
 
   virtual Representation representation() const { return kTagged; }
 
-  DECLARE_INSTRUCTION(CaseInsensitiveCompareUC16)
+  DECLARE_INSTRUCTION(CaseInsensitiveCompare)
   virtual CompileType ComputeType() const;
 
   virtual bool AttributesEqual(Instruction* other) const {
-    return other->AsCaseInsensitiveCompareUC16()->cid_ == cid_;
+    return other->AsCaseInsensitiveCompare()->cid_ == cid_;
   }
 
  private:
+  const RuntimeEntry& entry_;
   const intptr_t cid_;
 
-  DISALLOW_COPY_AND_ASSIGN(CaseInsensitiveCompareUC16Instr);
+  DISALLOW_COPY_AND_ASSIGN(CaseInsensitiveCompareInstr);
 };
 
 // Represents Math's static min and max functions.
@@ -7535,6 +7703,8 @@
 
   bool IsRedundant(const RangeBoundary& length);
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(GenericCheckBoundInstr);
 };
@@ -7631,6 +7801,8 @@
            (converter->is_truncating() == is_truncating());
   }
 
+  virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
+
   virtual void InferRange(RangeAnalysis* analysis, Range* range);
 
   virtual CompileType ComputeType() const {
@@ -7660,10 +7832,10 @@
         from_representation_(from),
         to_representation_(to) {
     ASSERT(from != to);
-    ASSERT(to == kUnboxedInt32 && from == kUnboxedFloat ||
-           to == kUnboxedFloat && from == kUnboxedInt32 ||
-           to == kUnboxedInt64 && from == kUnboxedDouble ||
-           to == kUnboxedDouble && from == kUnboxedInt64);
+    ASSERT((to == kUnboxedInt32 && from == kUnboxedFloat) ||
+           (to == kUnboxedFloat && from == kUnboxedInt32) ||
+           (to == kUnboxedInt64 && from == kUnboxedDouble) ||
+           (to == kUnboxedDouble && from == kUnboxedInt64));
     SetInputAt(0, value);
   }
 
@@ -7712,12 +7884,14 @@
  public:
   UnboxedWidthExtenderInstr(Value* value,
                             Representation rep,
-                            intptr_t from_width_bytes)
+                            SmallRepresentation from_rep)
       : TemplateDefinition(DeoptId::kNone),
         representation_(rep),
-        from_width_bytes_(from_width_bytes) {
-    ASSERT(from_width_bytes == 1 || from_width_bytes == 2);
-    ASSERT(rep == kUnboxedInt32 || rep == kUnboxedUint32);
+        from_representation_(from_rep) {
+    ASSERT(rep == kUnboxedInt32 && (from_rep == kSmallUnboxedInt8 ||
+                                    from_rep == kSmallUnboxedInt16) ||
+           rep == kUnboxedUint32 && (from_rep == kSmallUnboxedUint8 ||
+                                     from_rep == kSmallUnboxedUint16));
     SetInputAt(0, value);
   }
 
@@ -7725,6 +7899,10 @@
 
   Representation representation() const { return representation_; }
 
+  SmallRepresentation from_representation() const {
+    return from_representation_;
+  }
+
   bool ComputeCanDeoptimize() const { return false; }
 
   virtual Representation RequiredInputRepresentation(intptr_t idx) const {
@@ -7736,7 +7914,7 @@
     ASSERT(other->IsUnboxedWidthExtender());
     const UnboxedWidthExtenderInstr* ext = other->AsUnboxedWidthExtender();
     return ext->representation() == representation() &&
-           ext->from_width_bytes_ == from_width_bytes_;
+           ext->from_representation_ == from_representation_;
   }
 
   virtual CompileType ComputeType() const { return CompileType::Int(); }
@@ -7746,8 +7924,18 @@
   PRINT_OPERANDS_TO_SUPPORT
 
  private:
+  intptr_t from_width_bytes() const {
+    if (from_representation_ == kSmallUnboxedInt8 ||
+        from_representation_ == kSmallUnboxedUint8) {
+      return 1;
+    }
+    ASSERT(from_representation_ == kSmallUnboxedInt16 ||
+           from_representation_ == kSmallUnboxedUint16);
+    return 2;
+  }
+
   const Representation representation_;
-  const intptr_t from_width_bytes_;
+  const SmallRepresentation from_representation_;
 
   DISALLOW_COPY_AND_ASSIGN(UnboxedWidthExtenderInstr);
 };
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index d7dc61d..c687ec4 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -64,7 +64,8 @@
                 Temp<Register> temp)) {
   __ LoadObject(CODE_REG, instr->code());
   __ LeaveDartFrame();  // The arguments are still on the stack.
-  __ Branch(FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ Branch(
+      FieldAddress(CODE_REG, compiler::target::Code::entry_point_offset()));
 
   // Even though the TailCallInstr will be the last instruction in a basic
   // block, the flow graph compiler will emit native code for other blocks after
@@ -129,7 +130,7 @@
   const intptr_t fp_sp_dist =
       (compiler::target::frame_layout.first_local_from_fp + 1 -
        compiler->StackSize()) *
-      kWordSize;
+      compiler::target::kWordSize;
   ASSERT(fp_sp_dist <= 0);
   __ sub(R2, SP, Operand(FP));
   __ CompareImmediate(R2, fp_sp_dist);
@@ -234,10 +235,11 @@
     __ Lsl(result, result, Operand(shift + kSmiTagSize));
   } else {
     __ sub(result, result, Operand(1));
-    const int32_t val = Smi::RawValue(true_value) - Smi::RawValue(false_value);
+    const int32_t val = compiler::target::ToRawSmi(true_value) -
+                        compiler::target::ToRawSmi(false_value);
     __ AndImmediate(result, result, val);
     if (false_value != 0) {
-      __ AddImmediate(result, Smi::RawValue(false_value));
+      __ AddImmediate(result, compiler::target::ToRawSmi(false_value));
     }
   }
 }
@@ -263,8 +265,10 @@
   // R4: Arguments descriptor.
   // R0: Function.
   ASSERT(locs()->in(0).reg() == R0);
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-  __ ldr(R2, FieldAddress(R0, Code::function_entry_point_offset(entry_kind())));
+  __ ldr(CODE_REG, FieldAddress(R0, compiler::target::Function::code_offset()));
+  __ ldr(R2,
+         FieldAddress(R0, compiler::target::Code::function_entry_point_offset(
+                              entry_kind())));
 
   // R2: instructions entry point.
   // R9: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
@@ -320,7 +324,10 @@
                                        Register tmp) {
   if (destination.IsRegister()) {
     if (representation() == kUnboxedInt32) {
-      __ LoadImmediate(destination.reg(), Smi::Cast(value_).Value());
+      int64_t v;
+      const bool ok = compiler::HasIntegerValue(value_, &v);
+      RELEASE_ASSERT(ok);
+      __ LoadImmediate(destination.reg(), v);
     } else {
       ASSERT(representation() == kTagged);
       __ LoadObject(destination.reg(), value_);
@@ -350,7 +357,10 @@
     ASSERT(tmp != kNoRegister);
     const intptr_t dest_offset = destination.ToStackSlotOffset();
     if (representation() == kUnboxedInt32) {
-      __ LoadImmediate(tmp, Smi::Cast(value_).Value());
+      int64_t v;
+      const bool ok = compiler::HasIntegerValue(value_, &v);
+      RELEASE_ASSERT(ok);
+      __ LoadImmediate(tmp, v);
     } else {
       __ LoadObject(tmp, value_);
     }
@@ -803,8 +813,8 @@
   const Register left = locs()->in(0).reg();
   Location right = locs()->in(1);
   if (right.IsConstant()) {
-    ASSERT(right.constant().IsSmi());
-    const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw());
+    ASSERT(compiler::target::IsSmi(right.constant()));
+    const int32_t imm = compiler::target::ToRawSmi(right.constant());
     __ TestImmediate(left, imm);
   } else {
     __ tst(left, Operand(right.reg()));
@@ -933,7 +943,7 @@
   __ PushObject(Object::null_object());
 
   // Pass a pointer to the first argument in R2.
-  __ add(R2, SP, Operand(ArgumentCount() * kWordSize));
+  __ add(R2, SP, Operand(ArgumentCount() * compiler::target::kWordSize));
 
   // Compute the effective address. When running under the simulator,
   // this is a redirection address that forces the simulator to call
@@ -1002,45 +1012,13 @@
   __ ReserveAlignedFrameSpace(compiler::ffi::NumStackSlots(arg_locations_) *
                               kWordSize);
 
-  // Load a 32-bit argument, or a 32-bit component of a 64-bit argument.
-  auto load_single_slot = [&](Location from, Location to) {
-    if (!to.IsStackSlot()) return;
-    if (from.IsRegister()) {
-      __ str(from.reg(), LocationToStackSlotAddress(to));
-    } else if (from.IsFpuRegister()) {
-      __ vstrs(EvenSRegisterOf(EvenDRegisterOf(from.fpu_reg())),
-               LocationToStackSlotAddress(to));
-    } else if (from.IsStackSlot() || from.IsDoubleStackSlot()) {
-      ASSERT(from.base_reg() == FPREG);
-      __ ldr(TMP, Address(saved_fp, from.ToStackSlotOffset()));
-      __ str(TMP, LocationToStackSlotAddress(to));
-    } else {
-      UNREACHABLE();
-    }
-  };
-
+  FrameRebase rebase(/*old_base=*/FPREG, /*new_base=*/saved_fp,
+                     /*stack_delta=*/0);
   for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
-    Location origin = locs()->in(i);
-    Location target = arg_locations_[i];
-
-    if (target.IsStackSlot()) {
-      load_single_slot(origin, target);
-    } else if (target.IsDoubleStackSlot()) {
-      if (origin.IsFpuRegister()) {
-        __ vstrd(EvenDRegisterOf(origin.fpu_reg()),
-                 LocationToStackSlotAddress(target));
-      } else {
-        ASSERT(origin.IsDoubleStackSlot() && origin.base_reg() == FPREG);
-        __ vldrd(DTMP, Address(saved_fp, origin.ToStackSlotOffset()));
-        __ vstrd(DTMP, LocationToStackSlotAddress(target));
-      }
-    } else if (target.IsPairLocation()) {
-      ASSERT(origin.IsPairLocation());
-      load_single_slot(origin.AsPairLocation()->At(0),
-                       target.AsPairLocation()->At(0));
-      load_single_slot(origin.AsPairLocation()->At(1),
-                       target.AsPairLocation()->At(1));
-    }
+    const Location origin = rebase.Rebase(locs()->in(i));
+    const Location target = arg_locations_[i];
+    NoTemporaryAllocator no_temp;
+    compiler->EmitMove(target, origin, &no_temp);
   }
 
   // We need to copy the return address up into the dummy stack frame so the
@@ -1055,7 +1033,8 @@
                                  RawPcDescriptors::Kind::kOther, locs());
 
   // Update information in the thread object and enter a safepoint.
-  __ TransitionGeneratedToNative(branch, saved_fp, locs()->temp(1).reg());
+  __ TransitionGeneratedToNative(branch, FPREG, saved_fp,
+                                 locs()->temp(1).reg());
 
   __ blx(branch);
 
@@ -1076,6 +1055,176 @@
   __ PopRegister(TMP);
 }
 
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ LeaveDartFrame();
+
+  // The dummy return address is in LR, no need to pop it as on Intel.
+
+  // These can be anything besides the return registers (R0 and R1) and THR
+  // (R10).
+  const Register vm_tag_reg = R2, old_exit_frame_reg = R3, tmp = R4, tmp1 = R5;
+
+  __ Pop(old_exit_frame_reg);
+
+  // Restore top_resource.
+  __ Pop(tmp);
+  __ StoreToOffset(kWord, tmp, THR,
+                   compiler::target::Thread::top_resource_offset());
+
+  __ Pop(vm_tag_reg);
+
+  // Reset the exit frame info to
+  // old_exit_frame_reg *before* entering the safepoint.
+  __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg, tmp, tmp1);
+
+  __ PopNativeCalleeSavedRegisters();
+
+  // Leave the entry frame.
+  __ LeaveFrame(1 << LR | 1 << FP);
+
+  // Leave the dummy frame holding the pushed arguments.
+  __ LeaveFrame(1 << LR | 1 << FP);
+
+  __ Ret();
+
+  // For following blocks.
+  __ set_constant_pool_allowed(true);
+}
+
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+                                    Location loc) const {
+  if (loc.IsPairLocation()) {
+    // Save higher-order component first, so bytes are in little-endian layout
+    // overall.
+    for (intptr_t i : {1, 0}) {
+      SaveArgument(compiler, loc.Component(i));
+    }
+    return;
+  }
+
+  if (loc.HasStackIndex()) return;
+
+  if (loc.IsRegister()) {
+    __ Push(loc.reg());
+  } else if (loc.IsFpuRegister()) {
+    const DRegister src = EvenDRegisterOf(loc.fpu_reg());
+    __ SubImmediateSetFlags(SPREG, SPREG, 8, AL);
+    __ StoreDToOffset(src, SPREG, 0);
+  } else {
+    UNREACHABLE();
+  }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (FLAG_precompiled_mode) {
+    UNREACHABLE();
+  }
+
+  // Constant pool cannot be used until we enter the actual Dart frame.
+  __ set_constant_pool_allowed(false);
+
+  __ Bind(compiler->GetJumpLabel(this));
+
+  // Create a dummy frame holding the pushed arguments. This simplifies
+  // NativeReturnInstr::EmitNativeCode.
+  __ EnterFrame((1 << FP) | (1 << LR), 0);
+
+  // Save the argument registers, in reverse order.
+  for (intptr_t i = argument_locations_->length(); i-- > 0;) {
+    SaveArgument(compiler, argument_locations_->At(i));
+  }
+
+  // Enter the entry frame.
+  __ EnterFrame((1 << FP) | (1 << LR), 0);
+
+  // Save a space for the code object.
+  __ PushImmediate(0);
+
+  __ PushNativeCalleeSavedRegisters();
+
+  // Load the thread object.
+  // TODO(35765): Fix linking issue on AOT.
+  // TOOD(35934): Exclude native callbacks from snapshots.
+  //
+  // Create another frame to align the frame before continuing in "native" code.
+  {
+    __ EnterFrame(1 << FP, 0);
+    __ ReserveAlignedFrameSpace(0);
+
+    __ LoadImmediate(
+        R0, reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback));
+    __ blx(R0);
+    __ mov(THR, Operand(R0));
+
+    __ LeaveFrame(1 << FP);
+  }
+
+  // Save the current VMTag on the stack.
+  __ LoadFromOffset(kWord, R0, THR, compiler::target::Thread::vm_tag_offset());
+  __ Push(R0);
+
+  // Save top resource.
+  const intptr_t top_resource_offset =
+      compiler::target::Thread::top_resource_offset();
+  __ LoadFromOffset(kWord, R0, THR, top_resource_offset);
+  __ Push(R0);
+  __ LoadImmediate(R0, 0);
+  __ StoreToOffset(kWord, R0, THR, top_resource_offset);
+
+  // Save top exit frame info. Don't set it to 0 yet --
+  // TransitionNativeToGenerated will handle that *after* leaving the safepoint.
+  __ LoadFromOffset(kWord, R0, THR,
+                    compiler::target::Thread::top_exit_frame_info_offset());
+  __ Push(R0);
+
+  __ EmitEntryFrameVerification(R0);
+
+  __ TransitionNativeToGenerated(/*scratch0=*/R0, /*scratch1=*/R1);
+
+  // Now that the safepoint has ended, we can touch Dart objects without
+  // handles.
+
+  // Otherwise we'll clobber the argument sent from the caller.
+  ASSERT(CallingConventions::ArgumentRegisters[0] != TMP &&
+         CallingConventions::ArgumentRegisters[0] != TMP2 &&
+         CallingConventions::ArgumentRegisters[0] != R1);
+  __ LoadImmediate(CallingConventions::ArgumentRegisters[0], callback_id_);
+  __ LoadFromOffset(kWord, R1, THR,
+                    compiler::target::Thread::verify_callback_entry_offset());
+  __ blx(R1);
+
+  // Load the code object.
+  __ LoadFromOffset(kWord, R0, THR,
+                    compiler::target::Thread::callback_code_offset());
+  __ LoadFieldFromOffset(kWord, R0, R0,
+                         compiler::target::GrowableObjectArray::data_offset());
+  __ LoadFieldFromOffset(kWord, CODE_REG, R0,
+                         compiler::target::Array::data_offset() +
+                             callback_id_ * compiler::target::kWordSize);
+
+  // Put the code object in the reserved slot.
+  __ StoreToOffset(kWord, CODE_REG, FPREG,
+                   kPcMarkerSlotFromFp * compiler::target::kWordSize);
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    __ ldr(PP,
+           Address(THR, compiler::target::Thread::global_object_pool_offset()));
+  } else {
+    __ LoadImmediate(PP, 0);  // GC safe value into PP.
+  }
+
+  // Load a GC-safe value for the arguments descriptor (unused but tagged).
+  __ LoadImmediate(ARGS_DESC_REG, 0);
+
+  // Load a dummy return address which suggests that we are inside of
+  // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+  __ LoadFromOffset(kWord, LR, THR,
+                    compiler::target::Thread::invoke_dart_code_stub_offset());
+  __ LoadFieldFromOffset(kWord, LR, LR,
+                         compiler::target::Code::entry_point_offset());
+
+  FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -1091,8 +1240,12 @@
   const Register char_code = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
 
-  __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset()));
-  __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize);
+  __ ldr(
+      result,
+      Address(THR,
+              compiler::target::Thread::predefined_symbols_address_offset()));
+  __ AddImmediate(
+      result, Symbols::kNullCharCodeSymbolOffset * compiler::target::kWordSize);
   __ ldr(result, Address(result, char_code, LSL, 1));  // Char code is a smi.
 }
 
@@ -1107,10 +1260,12 @@
   ASSERT(cid_ == kOneByteStringCid);
   const Register str = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-  __ ldr(result, FieldAddress(str, String::length_offset()));
-  __ cmp(result, Operand(Smi::RawValue(1)));
+  __ ldr(result, FieldAddress(str, compiler::target::String::length_offset()));
+  __ cmp(result, Operand(compiler::target::ToRawSmi(1)));
   __ LoadImmediate(result, -1, NE);
-  __ ldrb(result, FieldAddress(str, OneByteString::data_offset()), EQ);
+  __ ldrb(result,
+          FieldAddress(str, compiler::target::OneByteString::data_offset()),
+          EQ);
   __ SmiTag(result);
 }
 
@@ -1225,18 +1380,19 @@
   switch (class_id_) {
     case kArrayCid:
     case kImmutableArrayCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
+      return kTagged;
     case kOneByteStringCid:
     case kTwoByteStringCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kTypedDataUint16ArrayCid:
     case kExternalOneByteStringCid:
     case kExternalTwoByteStringCid:
-      return kTagged;
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1275,8 +1431,8 @@
   if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) {
     return false;
   }
-  const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
-  const intptr_t scale = Instance::ElementSizeFor(cid);
+  const int64_t index = compiler::target::SmiValue(constant->value());
+  const intptr_t scale = compiler::target::Instance::ElementSizeFor(cid);
   const intptr_t base_offset =
       (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   const int64_t offset = index * scale + base_offset;
@@ -1326,26 +1482,19 @@
       (representation() == kUnboxedInt32x4) ||
       (representation() == kUnboxedFloat64x2)) {
     if (class_id() == kTypedDataFloat32ArrayCid) {
-      // Need register <= Q7 for float operations.
+      // Need register < Q7 for float operations.
       // TODO(fschneider): Add a register policy to specify a subset of
       // registers.
-      locs->set_out(0, Location::FpuRegisterLocation(Q7));
+      locs->set_out(0, Location::FpuRegisterLocation(Q6));
     } else {
       locs->set_out(0, Location::RequiresFpuRegister());
     }
-  } else if (representation() == kUnboxedUint32) {
-    ASSERT(class_id() == kTypedDataUint32ArrayCid);
-    locs->set_out(0, Location::RequiresRegister());
-  } else if (representation() == kUnboxedInt32) {
-    ASSERT(class_id() == kTypedDataInt32ArrayCid);
-    locs->set_out(0, Location::RequiresRegister());
   } else if (representation() == kUnboxedInt64) {
     ASSERT(class_id() == kTypedDataInt64ArrayCid ||
            class_id() == kTypedDataUint64ArrayCid);
     locs->set_out(0, Location::Pair(Location::RequiresRegister(),
                                     Location::RequiresRegister()));
   } else {
-    ASSERT(representation() == kTagged);
     locs->set_out(0, Location::RequiresRegister());
   }
   if (!directly_addressable) {
@@ -1376,7 +1525,7 @@
                           : __ ElementAddressForIntIndex(
                                 true,  // Load.
                                 IsExternal(), class_id(), index_scale(), array,
-                                Smi::Cast(index.constant()).Value(),
+                                compiler::target::SmiValue(index.constant()),
                                 IP);  // Temp register.
     // Warning: element_address may use register IP as base.
   } else {
@@ -1386,11 +1535,11 @@
                                        IsExternal(), class_id(), index_scale(),
                                        array, index.reg());
     } else {
-      __ LoadElementAddressForIntIndex(address,
-                                       true,  // Load.
-                                       IsExternal(), class_id(), index_scale(),
-                                       array,
-                                       Smi::Cast(index.constant()).Value());
+      __ LoadElementAddressForIntIndex(
+          address,
+          true,  // Load.
+          IsExternal(), class_id(), index_scale(), array,
+          compiler::target::SmiValue(index.constant()));
     }
   }
 
@@ -1438,94 +1587,95 @@
     return;
   }
 
-  if ((representation() == kUnboxedUint32) ||
-      (representation() == kUnboxedInt32)) {
-    Register result = locs()->out(0).reg();
-    switch (class_id()) {
-      case kTypedDataInt32ArrayCid:
-        ASSERT(representation() == kUnboxedInt32);
-        if (aligned()) {
-          __ ldr(result, element_address);
-        } else {
-          __ LoadWordUnaligned(result, address, TMP);
-        }
-        break;
-      case kTypedDataUint32ArrayCid:
-        ASSERT(representation() == kUnboxedUint32);
-        if (aligned()) {
-          __ ldr(result, element_address);
-        } else {
-          __ LoadWordUnaligned(result, address, TMP);
-        }
-        break;
-      default:
-        UNREACHABLE();
-    }
-    return;
-  }
-
-  if (representation() == kUnboxedInt64) {
-    ASSERT(!directly_addressable);  // need to add to register
-    ASSERT(class_id() == kTypedDataInt64ArrayCid ||
-           class_id() == kTypedDataUint64ArrayCid);
-    ASSERT(locs()->out(0).IsPairLocation());
-    PairLocation* result_pair = locs()->out(0).AsPairLocation();
-    Register result_lo = result_pair->At(0).reg();
-    Register result_hi = result_pair->At(1).reg();
-    if (aligned()) {
-      __ ldr(result_lo, Address(address));
-      __ ldr(result_hi, Address(address, kWordSize));
-    } else {
-      __ LoadWordUnaligned(result_lo, address, TMP);
-      __ AddImmediate(address, address, kWordSize);
-      __ LoadWordUnaligned(result_hi, address, TMP);
-    }
-    return;
-  }
-
-  ASSERT(representation() == kTagged);
-
-  const Register result = locs()->out(0).reg();
   switch (class_id()) {
-    case kTypedDataInt8ArrayCid:
+    case kTypedDataInt32ArrayCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedInt32);
+      if (aligned()) {
+        __ ldr(result, element_address);
+      } else {
+        __ LoadWordUnaligned(result, address, TMP);
+      }
+      break;
+    }
+    case kTypedDataUint32ArrayCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedUint32);
+      if (aligned()) {
+        __ ldr(result, element_address);
+      } else {
+        __ LoadWordUnaligned(result, address, TMP);
+      }
+      break;
+    }
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid: {
+      ASSERT(representation() == kUnboxedInt64);
+      ASSERT(!directly_addressable);  // need to add to register
+      ASSERT(locs()->out(0).IsPairLocation());
+      PairLocation* result_pair = locs()->out(0).AsPairLocation();
+      const Register result_lo = result_pair->At(0).reg();
+      const Register result_hi = result_pair->At(1).reg();
+      if (aligned()) {
+        __ ldr(result_lo, Address(address));
+        __ ldr(result_hi, Address(address, compiler::target::kWordSize));
+      } else {
+        __ LoadWordUnaligned(result_lo, address, TMP);
+        __ AddImmediate(address, address, compiler::target::kWordSize);
+        __ LoadWordUnaligned(result_hi, address, TMP);
+      }
+      break;
+    }
+    case kTypedDataInt8ArrayCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedIntPtr);
       ASSERT(index_scale() == 1);
       ASSERT(aligned());
       __ ldrsb(result, element_address);
-      __ SmiTag(result);
       break;
+    }
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
     case kOneByteStringCid:
-    case kExternalOneByteStringCid:
+    case kExternalOneByteStringCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedIntPtr);
       ASSERT(index_scale() == 1);
       ASSERT(aligned());
       __ ldrb(result, element_address);
-      __ SmiTag(result);
       break;
-    case kTypedDataInt16ArrayCid:
+    }
+    case kTypedDataInt16ArrayCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedIntPtr);
       if (aligned()) {
         __ ldrsh(result, element_address);
       } else {
         __ LoadHalfWordUnaligned(result, address, TMP);
       }
-      __ SmiTag(result);
       break;
+    }
     case kTypedDataUint16ArrayCid:
     case kTwoByteStringCid:
-    case kExternalTwoByteStringCid:
+    case kExternalTwoByteStringCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedIntPtr);
       if (aligned()) {
         __ ldrh(result, element_address);
       } else {
         __ LoadHalfWordUnsignedUnaligned(result, address, TMP);
       }
-      __ SmiTag(result);
       break;
-    default:
+    }
+    default: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kTagged);
       ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
       __ ldr(result, element_address);
       break;
+    }
   }
 }
 
@@ -1537,15 +1687,16 @@
   ASSERT(idx == 2);
   switch (class_id_) {
     case kArrayCid:
+      return kTagged;
     case kOneByteStringCid:
     case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
     case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
     case kTypedDataUint16ArrayCid:
-      return kTagged;
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1635,8 +1786,8 @@
                                      Location::RequiresRegister()));
       break;
     case kTypedDataFloat32ArrayCid:
-      // Need low register (<= Q7).
-      locs->set_in(2, Location::FpuRegisterLocation(Q7));
+      // Need low register (< Q7).
+      locs->set_in(2, Location::FpuRegisterLocation(Q6));
       break;
     case kTypedDataFloat64ArrayCid:  // TODO(srdjan): Support Float64 constants.
     case kTypedDataInt32x4ArrayCid:
@@ -1666,15 +1817,16 @@
 
   Address element_address(kNoRegister);
   if (directly_addressable) {
-    element_address = index.IsRegister()
-                          ? __ ElementAddressForRegIndex(
-                                false,  // Store.
-                                IsExternal(), class_id(), index_scale(), array,
-                                index.reg())
-                          : __ ElementAddressForIntIndex(
-                                false,  // Store.
-                                IsExternal(), class_id(), index_scale(), array,
-                                Smi::Cast(index.constant()).Value(), temp);
+    element_address =
+        index.IsRegister()
+            ? __ ElementAddressForRegIndex(false,  // Store.
+                                           IsExternal(), class_id(),
+                                           index_scale(), array,
+                                           index.reg())
+            : __ ElementAddressForIntIndex(
+                  false,  // Store.
+                  IsExternal(), class_id(), index_scale(), array,
+                  compiler::target::SmiValue(index.constant()), temp);
   } else {
     if (index.IsRegister()) {
       __ LoadElementAddressForRegIndex(temp,
@@ -1682,11 +1834,11 @@
                                        IsExternal(), class_id(), index_scale(),
                                        array, index.reg());
     } else {
-      __ LoadElementAddressForIntIndex(temp,
-                                       false,  // Store.
-                                       IsExternal(), class_id(), index_scale(),
-                                       array,
-                                       Smi::Cast(index.constant()).Value());
+      __ LoadElementAddressForIntIndex(
+          temp,
+          false,  // Store.
+          IsExternal(), class_id(), index_scale(), array,
+          compiler::target::SmiValue(index.constant()));
     }
   }
 
@@ -1708,22 +1860,22 @@
     case kTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ArrayCid:
     case kOneByteStringCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       if (locs()->in(2).IsConstant()) {
-        const Smi& constant = Smi::Cast(locs()->in(2).constant());
-        __ LoadImmediate(IP, static_cast<int8_t>(constant.Value()));
+        __ LoadImmediate(IP,
+                         compiler::target::SmiValue(locs()->in(2).constant()));
         __ strb(IP, element_address);
       } else {
         const Register value = locs()->in(2).reg();
-        __ SmiUntag(IP, value);
-        __ strb(IP, element_address);
+        __ strb(value, element_address);
       }
       break;
     }
     case kTypedDataUint8ClampedArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       if (locs()->in(2).IsConstant()) {
-        const Smi& constant = Smi::Cast(locs()->in(2).constant());
-        intptr_t value = constant.Value();
+        intptr_t value = compiler::target::SmiValue(locs()->in(2).constant());
         // Clamp to 0x0 or 0xFF respectively.
         if (value > 0xFF) {
           value = 0xFF;
@@ -1734,24 +1886,23 @@
         __ strb(IP, element_address);
       } else {
         const Register value = locs()->in(2).reg();
-        __ LoadImmediate(IP, 0x1FE);  // Smi 0xFF.
-        __ cmp(value, Operand(IP));   // Compare Smi value and smi 0xFF.
         // Clamp to 0x00 or 0xFF respectively.
-        __ mov(IP, Operand(0), LE);      // IP = value <= 0x1FE ? 0 : 0x1FE.
+        __ LoadImmediate(IP, 0xFF);
+        __ cmp(value, Operand(IP));      // Compare Smi value and smi 0xFF.
+        __ mov(IP, Operand(0), LE);      // IP = value <= 0xFF ? 0 : 0xFF.
         __ mov(IP, Operand(value), LS);  // IP = value in range ? value : IP.
-        __ SmiUntag(IP);
         __ strb(IP, element_address);
       }
       break;
     }
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       const Register value = locs()->in(2).reg();
-      __ SmiUntag(IP, value);
       if (aligned()) {
-        __ strh(IP, element_address);
+        __ strh(value, element_address);
       } else {
-        __ StoreHalfWordUnaligned(IP, temp, temp2);
+        __ StoreHalfWordUnaligned(value, temp, temp2);
       }
       break;
     }
@@ -1774,10 +1925,10 @@
       Register value_hi = value_pair->At(1).reg();
       if (aligned()) {
         __ str(value_lo, Address(temp));
-        __ str(value_hi, Address(temp, kWordSize));
+        __ str(value_hi, Address(temp, compiler::target::kWordSize));
       } else {
         __ StoreWordUnaligned(value_lo, temp, temp2);
-        __ AddImmediate(temp, temp, kWordSize);
+        __ AddImmediate(temp, temp, compiler::target::kWordSize);
         __ StoreWordUnaligned(value_hi, temp, temp2);
       }
       break;
@@ -1865,13 +2016,6 @@
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
 
   if (field_cid == kDynamicCid) {
-    if (Compiler::IsBackgroundCompilation()) {
-      // Field state changed while compiling.
-      Compiler::AbortBackgroundCompilation(
-          deopt_id(),
-          "GuardFieldClassInstr: field state changed while compiling");
-    }
-    ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
@@ -1904,9 +2048,10 @@
   if (emit_full_guard) {
     __ LoadObject(field_reg, Field::ZoneHandle(field().Original()));
 
-    FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
-    FieldAddress field_nullability_operand(field_reg,
-                                           Field::is_nullable_offset());
+    FieldAddress field_cid_operand(
+        field_reg, compiler::target::Field::guarded_cid_offset());
+    FieldAddress field_nullability_operand(
+        field_reg, compiler::target::Field::is_nullable_offset());
 
     if (value_cid == kDynamicCid) {
       LoadValueCid(compiler, value_cid_reg, value_reg);
@@ -1953,7 +2098,8 @@
       ASSERT(!compiler->is_optimizing());
       __ Bind(fail);
 
-      __ ldrh(IP, FieldAddress(field_reg, Field::guarded_cid_offset()));
+      __ ldrh(IP, FieldAddress(field_reg,
+                               compiler::target::Field::guarded_cid_offset()));
       __ CompareImmediate(IP, kDynamicCid);
       __ b(&ok, EQ);
 
@@ -2025,13 +2171,6 @@
 
 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   if (field().guarded_list_length() == Field::kNoFixedLength) {
-    if (Compiler::IsBackgroundCompilation()) {
-      // Field state changed while compiling.
-      Compiler::AbortBackgroundCompilation(
-          deopt_id(),
-          "GuardFieldLengthInstr: field state changed while compiling");
-    }
-    ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
@@ -2052,12 +2191,13 @@
 
     __ LoadObject(field_reg, Field::ZoneHandle(field().Original()));
 
-    __ ldrsb(
-        offset_reg,
-        FieldAddress(field_reg,
-                     Field::guarded_list_length_in_object_offset_offset()));
+    __ ldrsb(offset_reg,
+             FieldAddress(field_reg,
+                          compiler::target::Field::
+                              guarded_list_length_in_object_offset_offset()));
     __ ldr(length_reg,
-           FieldAddress(field_reg, Field::guarded_list_length_offset()));
+           FieldAddress(field_reg,
+                        compiler::target::Field::guarded_list_length_offset()));
 
     __ tst(offset_reg, Operand(offset_reg));
     __ b(&ok, MI);
@@ -2092,8 +2232,8 @@
     __ ldr(length_reg,
            FieldAddress(value_reg,
                         field().guarded_list_length_in_object_offset()));
-    __ CompareImmediate(length_reg,
-                        Smi::RawValue(field().guarded_list_length()));
+    __ CompareImmediate(
+        length_reg, compiler::target::ToRawSmi(field().guarded_list_length()));
     __ b(deopt, NE);
   }
 }
@@ -2265,9 +2405,10 @@
                                       result, temp);
       __ eor(temp, temp, Operand(temp));
       __ StoreToOffset(kWord, value, result,
-                       Mint::value_offset() - kHeapObjectTag);
+                       compiler::target::Mint::value_offset() - kHeapObjectTag);
       __ StoreToOffset(kWord, temp, result,
-                       Mint::value_offset() - kHeapObjectTag + kWordSize);
+                       compiler::target::Mint::value_offset() - kHeapObjectTag +
+                           compiler::target::kWordSize);
       __ Bind(&done);
     }
   }
@@ -2365,17 +2506,21 @@
     switch (cid) {
       case kDoubleCid:
         __ Comment("UnboxedDoubleStoreInstanceFieldInstr");
-        __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag);
+        __ StoreDToOffset(
+            value, temp,
+            compiler::target::Double::value_offset() - kHeapObjectTag);
         break;
       case kFloat32x4Cid:
         __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
-        __ StoreMultipleDToOffset(value, 2, temp,
-                                  Float32x4::value_offset() - kHeapObjectTag);
+        __ StoreMultipleDToOffset(
+            value, 2, temp,
+            compiler::target::Float32x4::value_offset() - kHeapObjectTag);
         break;
       case kFloat64x2Cid:
         __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr");
-        __ StoreMultipleDToOffset(value, 2, temp,
-                                  Float64x2::value_offset() - kHeapObjectTag);
+        __ StoreMultipleDToOffset(
+            value, 2, temp,
+            compiler::target::Float64x2::value_offset() - kHeapObjectTag);
         break;
       default:
         UNREACHABLE();
@@ -2403,23 +2548,28 @@
 
     __ LoadObject(temp, Field::ZoneHandle(Z, slot().field().Original()));
 
-    __ ldrh(temp2, FieldAddress(temp, Field::is_nullable_offset()));
+    __ ldrh(temp2,
+            FieldAddress(temp, compiler::target::Field::is_nullable_offset()));
     __ CompareImmediate(temp2, kNullCid);
     __ b(&store_pointer, EQ);
 
-    __ ldrb(temp2, FieldAddress(temp, Field::kind_bits_offset()));
+    __ ldrb(temp2,
+            FieldAddress(temp, compiler::target::Field::kind_bits_offset()));
     __ tst(temp2, Operand(1 << Field::kUnboxingCandidateBit));
     __ b(&store_pointer, EQ);
 
-    __ ldrh(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
+    __ ldrh(temp2,
+            FieldAddress(temp, compiler::target::Field::guarded_cid_offset()));
     __ CompareImmediate(temp2, kDoubleCid);
     __ b(&store_double, EQ);
 
-    __ ldrh(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
+    __ ldrh(temp2,
+            FieldAddress(temp, compiler::target::Field::guarded_cid_offset()));
     __ CompareImmediate(temp2, kFloat32x4Cid);
     __ b(&store_float32x4, EQ);
 
-    __ ldrh(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
+    __ ldrh(temp2,
+            FieldAddress(temp, compiler::target::Field::guarded_cid_offset()));
     __ CompareImmediate(temp2, kFloat64x2Cid);
     __ b(&store_float64x2, EQ);
 
@@ -2499,7 +2649,8 @@
 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register field = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-  __ LoadFieldFromOffset(kWord, result, field, Field::static_value_offset());
+  __ LoadFieldFromOffset(kWord, result, field,
+                         compiler::target::Field::static_value_offset());
 }
 
 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone,
@@ -2519,12 +2670,16 @@
 
   __ LoadObject(temp, Field::ZoneHandle(Z, field().Original()));
   if (this->value()->NeedsWriteBarrier()) {
-    __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()),
-                       value, CanValueBeSmi(),
-                       /*lr_reserved=*/!compiler->intrinsic_mode());
+    __ StoreIntoObject(
+        temp,
+        FieldAddress(temp, compiler::target::Field::static_value_offset()),
+        value, CanValueBeSmi(),
+        /*lr_reserved=*/!compiler->intrinsic_mode());
   } else {
     __ StoreIntoObjectNoBarrier(
-        temp, FieldAddress(temp, Field::static_value_offset()), value);
+        temp,
+        FieldAddress(temp, compiler::target::Field::static_value_offset()),
+        value);
   }
 }
 
@@ -2581,11 +2736,13 @@
 
   // Store the type argument field.
   __ StoreIntoObjectNoBarrier(
-      R0, FieldAddress(R0, Array::type_arguments_offset()), kElemTypeReg);
+      R0, FieldAddress(R0, compiler::target::Array::type_arguments_offset()),
+      kElemTypeReg);
 
   // Set the length field.
-  __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, Array::length_offset()),
-                              kLengthReg);
+  __ StoreIntoObjectNoBarrier(
+      R0, FieldAddress(R0, compiler::target::Array::length_offset()),
+      kLengthReg);
 
   // Initialize all array elements to raw_null.
   // R0: new object start as a tagged pointer.
@@ -2605,9 +2762,9 @@
 #endif  // DEBUG
     }
     __ AddImmediate(R6, R0, sizeof(RawArray) - kHeapObjectTag);
-    if (array_size < (kInlineArraySize * kWordSize)) {
-      __ InitializeFieldsNoBarrierUnrolled(R0, R6, 0, num_elements * kWordSize,
-                                           R8, R9);
+    if (array_size < (kInlineArraySize * compiler::target::kWordSize)) {
+      __ InitializeFieldsNoBarrierUnrolled(
+          R0, R6, 0, num_elements * compiler::target::kWordSize, R8, R9);
     } else {
       __ InitializeFieldsNoBarrier(R0, R6, R3, R8, R9);
     }
@@ -2633,9 +2790,10 @@
 
   if (compiler->is_optimizing() && !FLAG_precompiled_mode &&
       num_elements()->BindsToConstant() &&
-      num_elements()->BoundConstant().IsSmi()) {
-    const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value();
-    if ((length >= 0) && (length <= Array::kMaxElements)) {
+      compiler::target::IsSmi(num_elements()->BoundConstant())) {
+    const intptr_t length =
+        compiler::target::SmiValue(num_elements()->BoundConstant());
+    if (Array::IsValidLength(length)) {
       Label slow_path, done;
       InlineArrayAllocation(compiler, length, &slow_path, &done);
       __ Bind(&slow_path);
@@ -2693,18 +2851,21 @@
     switch (cid) {
       case kDoubleCid:
         __ Comment("UnboxedDoubleLoadFieldInstr");
-        __ LoadDFromOffset(result, temp,
-                           Double::value_offset() - kHeapObjectTag);
+        __ LoadDFromOffset(
+            result, temp,
+            compiler::target::Double::value_offset() - kHeapObjectTag);
         break;
       case kFloat32x4Cid:
         __ Comment("UnboxedFloat32x4LoadFieldInstr");
-        __ LoadMultipleDFromOffset(result, 2, temp,
-                                   Float32x4::value_offset() - kHeapObjectTag);
+        __ LoadMultipleDFromOffset(
+            result, 2, temp,
+            compiler::target::Float32x4::value_offset() - kHeapObjectTag);
         break;
       case kFloat64x2Cid:
         __ Comment("UnboxedFloat64x2LoadFieldInstr");
-        __ LoadMultipleDFromOffset(result, 2, temp,
-                                   Float64x2::value_offset() - kHeapObjectTag);
+        __ LoadMultipleDFromOffset(
+            result, 2, temp,
+            compiler::target::Float64x2::value_offset() - kHeapObjectTag);
         break;
       default:
         UNREACHABLE();
@@ -2726,9 +2887,10 @@
 
     __ LoadObject(result_reg, Field::ZoneHandle(slot().field().Original()));
 
-    FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset());
-    FieldAddress field_nullability_operand(result_reg,
-                                           Field::is_nullable_offset());
+    FieldAddress field_cid_operand(
+        result_reg, compiler::target::Field::guarded_cid_offset());
+    FieldAddress field_nullability_operand(
+        result_reg, compiler::target::Field::is_nullable_offset());
 
     __ ldrh(temp, field_nullability_operand);
     __ CompareImmediate(temp, kNullCid);
@@ -2860,25 +3022,38 @@
   // TODO(regis): Consider moving this into a shared stub to reduce
   // generated code size.
   __ LoadObject(R3, type_arguments());
-  __ ldr(R3, FieldAddress(R3, TypeArguments::instantiations_offset()));
-  __ AddImmediate(R3, Array::data_offset() - kHeapObjectTag);
+  __ ldr(R3, FieldAddress(
+                 R3, compiler::target::TypeArguments::instantiations_offset()));
+  __ AddImmediate(R3, compiler::target::Array::data_offset() - kHeapObjectTag);
   // The instantiations cache is initialized with Object::zero_array() and is
   // therefore guaranteed to contain kNoInstantiator. No length check needed.
   Label loop, next, found, slow_case;
   __ Bind(&loop);
-  __ ldr(R2, Address(R3, 0 * kWordSize));  // Cached instantiator type args.
+  __ ldr(
+      R2,
+      Address(
+          R3,
+          0 * compiler::target::kWordSize));  // Cached instantiator type args.
   __ cmp(R2, Operand(instantiator_type_args_reg));
   __ b(&next, NE);
-  __ ldr(IP, Address(R3, 1 * kWordSize));  // Cached function type args.
+  __ ldr(
+      IP,
+      Address(R3,
+              1 * compiler::target::kWordSize));  // Cached function type args.
   __ cmp(IP, Operand(function_type_args_reg));
   __ b(&found, EQ);
   __ Bind(&next);
-  __ AddImmediate(R3, StubCode::kInstantiationSizeInWords * kWordSize);
-  __ CompareImmediate(R2, Smi::RawValue(StubCode::kNoInstantiator));
+  __ AddImmediate(
+      R3, StubCode::kInstantiationSizeInWords * compiler::target::kWordSize);
+  __ CompareImmediate(R2,
+                      compiler::target::ToRawSmi(StubCode::kNoInstantiator));
   __ b(&loop, NE);
   __ b(&slow_case);
   __ Bind(&found);
-  __ ldr(result_reg, Address(R3, 2 * kWordSize));  // Cached instantiated args.
+  __ ldr(
+      result_reg,
+      Address(R3,
+              2 * compiler::target::kWordSize));  // Cached instantiated args.
   __ b(&type_arguments_instantiated);
 
   __ Bind(&slow_case);
@@ -2954,7 +3129,8 @@
 
   // Setup up number of context variables field.
   __ LoadImmediate(temp0, num_context_variables());
-  __ str(temp0, FieldAddress(result, Context::num_variables_offset()));
+  __ str(temp0, FieldAddress(
+                    result, compiler::target::Context::num_variables_offset()));
 
   __ Bind(slow_path->exit_label());
 }
@@ -2995,7 +3171,8 @@
   Register temp = locs()->temp(0).reg();
   Label call_runtime, no_call;
 
-  __ ldr(temp, FieldAddress(field, Field::static_value_offset()));
+  __ ldr(temp,
+         FieldAddress(field, compiler::target::Field::static_value_offset()));
   __ CompareObject(temp, Object::sentinel());
   __ b(&call_runtime, EQ);
 
@@ -3064,7 +3241,7 @@
   const intptr_t fp_sp_dist =
       (compiler::target::frame_layout.first_local_from_fp + 1 -
        compiler->StackSize()) *
-      kWordSize;
+      compiler::target::kWordSize;
   ASSERT(fp_sp_dist <= 0);
   __ AddImmediate(SP, FP, fp_sp_dist);
 
@@ -3110,7 +3287,9 @@
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
       __ LoadImmediate(value, Thread::kOsrRequest);
-      __ str(value, Address(THR, Thread::stack_overflow_flags_offset()));
+      __ str(value,
+             Address(THR,
+                     compiler::target::Thread::stack_overflow_flags_offset()));
     }
     __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
@@ -3127,8 +3306,8 @@
     compiler->pending_deoptimization_env_ = env;
 
     if (using_shared_stub) {
-      const uword entry_point_offset =
-          Thread::stack_overflow_shared_stub_entry_point_offset(
+      const uword entry_point_offset = compiler::target::Thread::
+          stack_overflow_shared_stub_entry_point_offset(
               instruction()->locs()->live_registers()->FpuRegisterCount() > 0);
       __ ldr(LR, Address(THR, entry_point_offset));
       __ blx(LR);
@@ -3168,7 +3347,7 @@
 };
 
 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ ldr(IP, Address(THR, Thread::stack_limit_offset()));
+  __ ldr(IP, Address(THR, compiler::target::Thread::stack_limit_offset()));
   __ cmp(SP, Operand(IP));
 
   auto object_store = compiler->isolate()->object_store();
@@ -3205,7 +3384,8 @@
     __ LoadObject(temp, compiler->parsed_function().function());
     intptr_t threshold =
         FLAG_optimization_counter_threshold * (loop_depth() + 1);
-    __ ldr(temp, FieldAddress(temp, Function::usage_counter_offset()));
+    __ ldr(temp, FieldAddress(
+                     temp, compiler::target::Function::usage_counter_offset()));
     __ CompareImmediate(temp, threshold);
     __ b(slow_path->osr_entry_label(), GE);
   }
@@ -3226,10 +3406,10 @@
                      : NULL;
   if (locs.in(1).IsConstant()) {
     const Object& constant = locs.in(1).constant();
-    ASSERT(constant.IsSmi());
+    ASSERT(compiler::target::IsSmi(constant));
     // Immediate shift operation takes 5 bits for the count.
     const intptr_t kCountLimit = 0x1F;
-    const intptr_t value = Smi::Cast(constant).Value();
+    const intptr_t value = compiler::target::SmiValue(constant);
     ASSERT((0 < value) && (value < kCountLimit));
     if (shift_left->can_overflow()) {
       // Check for overflow (preserve left).
@@ -3249,19 +3429,20 @@
     // TODO(srdjan): Implement code below for is_truncating().
     // If left is constant, we know the maximal allowed size for right.
     const Object& obj = shift_left->left()->BoundConstant();
-    if (obj.IsSmi()) {
-      const intptr_t left_int = Smi::Cast(obj).Value();
+    if (compiler::target::IsSmi(obj)) {
+      const intptr_t left_int = compiler::target::SmiValue(obj);
       if (left_int == 0) {
         __ cmp(right, Operand(0));
         __ b(deopt, MI);
         __ mov(result, Operand(0));
         return;
       }
-      const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
+      const intptr_t max_right =
+          compiler::target::kSmiBits - Utils::HighestBit(left_int);
       const bool right_needs_check =
           !RangeUtils::IsWithin(right_range, 0, max_right - 1);
       if (right_needs_check) {
-        __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(max_right))));
+        __ cmp(right, Operand(compiler::target::ToRawSmi(max_right)));
         __ b(deopt, CS);
       }
       __ SmiUntag(IP, right);
@@ -3271,7 +3452,7 @@
   }
 
   const bool right_needs_check =
-      !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1));
+      !RangeUtils::IsWithin(right_range, 0, (compiler::target::kSmiBits - 1));
   if (!shift_left->can_overflow()) {
     if (right_needs_check) {
       if (!RangeUtils::IsPositive(right_range)) {
@@ -3280,7 +3461,8 @@
         __ b(deopt, MI);
       }
 
-      __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
+      __ cmp(right,
+             Operand(compiler::target::ToRawSmi(compiler::target::kSmiBits)));
       __ mov(result, Operand(0), CS);
       __ SmiUntag(IP, right, CC);  // SmiUntag right into IP if CC.
       __ Lsl(result, left, IP, CC);
@@ -3291,7 +3473,8 @@
   } else {
     if (right_needs_check) {
       ASSERT(shift_left->CanDeoptimize());
-      __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
+      __ cmp(right,
+             Operand(compiler::target::ToRawSmi(compiler::target::kSmiBits)));
       __ b(deopt, CS);
     }
     // Left is not a constant.
@@ -3413,7 +3596,8 @@
     case Token::kSHL:
       ASSERT(result != left);
       ASSERT(result != right);
-      __ CompareImmediate(right, Smi::RawValue(Smi::kBits));
+      __ CompareImmediate(
+          right, compiler::target::ToRawSmi(compiler::target::kSmiBits));
       __ b(slow_path->entry_label(), HI);
 
       __ SmiUntag(TMP, right);
@@ -3426,7 +3610,8 @@
     case Token::kSHR:
       ASSERT(result != left);
       ASSERT(result != right);
-      __ CompareImmediate(right, Smi::RawValue(Smi::kBits));
+      __ CompareImmediate(
+          right, compiler::target::ToRawSmi(compiler::target::kSmiBits));
       __ b(slow_path->entry_label(), HI);
 
       __ SmiUntag(result, right);
@@ -3600,7 +3785,8 @@
     } else {
       summary->set_in(1, Location::RequiresRegister());
       summary->set_temp(0, Location::RequiresRegister());
-      summary->set_temp(1, Location::RequiresFpuRegister());
+      // Request register that overlaps with S0..S31.
+      summary->set_temp(1, Location::FpuRegisterLocation(Q0));
     }
     summary->set_out(0, Location::RequiresRegister());
     return summary;
@@ -3609,7 +3795,8 @@
     summary->set_in(0, Location::RequiresRegister());
     summary->set_in(1, Location::RequiresRegister());
     summary->set_temp(0, Location::RequiresRegister());
-    summary->set_temp(1, Location::RequiresFpuRegister());
+    // Request register that overlaps with S0..S31.
+    summary->set_temp(1, Location::FpuRegisterLocation(Q0));
     summary->set_out(0, Location::RequiresRegister());
     return summary;
   }
@@ -3640,8 +3827,8 @@
 
   if (locs()->in(1).IsConstant()) {
     const Object& constant = locs()->in(1).constant();
-    ASSERT(constant.IsSmi());
-    const int32_t imm = reinterpret_cast<int32_t>(constant.raw());
+    ASSERT(compiler::target::IsSmi(constant));
+    const int32_t imm = compiler::target::ToRawSmi(constant);
     switch (op_kind()) {
       case Token::kADD: {
         if (deopt == NULL) {
@@ -3665,7 +3852,7 @@
       }
       case Token::kMUL: {
         // Keep left value tagged and untag right value.
-        const intptr_t value = Smi::Cast(constant).Value();
+        const intptr_t value = compiler::target::SmiValue(constant);
         if (deopt == NULL) {
           __ LoadImmediate(IP, value);
           __ mul(result, left, IP);
@@ -3679,7 +3866,7 @@
         break;
       }
       case Token::kTRUNCDIV: {
-        const intptr_t value = Smi::Cast(constant).Value();
+        const intptr_t value = compiler::target::SmiValue(constant);
         ASSERT(value != kIntptrMin);
         ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value)));
         const intptr_t shift_count =
@@ -3735,7 +3922,7 @@
       case Token::kSHR: {
         // sarl operation masks the count to 5 bits.
         const intptr_t kCountLimit = 0x1F;
-        intptr_t value = Smi::Cast(constant).Value();
+        intptr_t value = compiler::target::SmiValue(constant);
         __ Asr(result, left,
                Operand(Utils::Minimum(value + kSmiTagSize, kCountLimit)));
         __ SmiTag(result);
@@ -3899,10 +4086,10 @@
                      : NULL;
   ASSERT(locs.in(1).IsConstant());
   const Object& constant = locs.in(1).constant();
-  ASSERT(constant.IsSmi());
+  ASSERT(compiler::target::IsSmi(constant));
   // Immediate shift operation takes 5 bits for the count.
   const intptr_t kCountLimit = 0x1F;
-  const intptr_t value = Smi::Cast(constant).Value();
+  const intptr_t value = compiler::target::SmiValue(constant);
   ASSERT((0 < value) && (value < kCountLimit));
   if (shift_left->can_overflow()) {
     // Check for overflow (preserve left).
@@ -3952,8 +4139,8 @@
 
   if (locs()->in(1).IsConstant()) {
     const Object& constant = locs()->in(1).constant();
-    ASSERT(constant.IsSmi());
-    const intptr_t value = Smi::Cast(constant).Value();
+    ASSERT(compiler::target::IsSmi(constant));
+    const intptr_t value = compiler::target::SmiValue(constant);
     switch (op_kind()) {
       case Token::kADD: {
         if (deopt == NULL) {
@@ -4194,7 +4381,7 @@
       ASSERT(result->At(0).reg() != box);
       __ LoadFieldFromOffset(kWord, result->At(0).reg(), box, ValueOffset());
       __ LoadFieldFromOffset(kWord, result->At(1).reg(), box,
-                             ValueOffset() + kWordSize);
+                             ValueOffset() + compiler::target::kWordSize);
       break;
     }
 
@@ -4256,7 +4443,8 @@
   const Register result = locs()->out(0).reg();
   Label done;
   __ SmiUntag(result, value, &done);
-  __ LoadFieldFromOffset(kWord, result, value, Mint::value_offset());
+  __ LoadFieldFromOffset(kWord, result, value,
+                         compiler::target::Mint::value_offset());
   __ Bind(&done);
 }
 
@@ -4311,14 +4499,16 @@
     BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
                                     temp);
     if (from_representation() == kUnboxedInt32) {
-      __ Asr(temp, value, Operand(kBitsPerWord - 1));
+      __ Asr(temp, value, Operand(compiler::target::kBitsPerWord - 1));
     } else {
       ASSERT(from_representation() == kUnboxedUint32);
       __ eor(temp, temp, Operand(temp));
     }
-    __ StoreToOffset(kWord, value, out, Mint::value_offset() - kHeapObjectTag);
+    __ StoreToOffset(kWord, value, out,
+                     compiler::target::Mint::value_offset() - kHeapObjectTag);
     __ StoreToOffset(kWord, temp, out,
-                     Mint::value_offset() - kHeapObjectTag + kWordSize);
+                     compiler::target::Mint::value_offset() - kHeapObjectTag +
+                         compiler::target::kWordSize);
     __ Bind(&done);
   }
 }
@@ -4364,9 +4554,10 @@
   BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
                                   out_reg, tmp);
   __ StoreToOffset(kWord, value_lo, out_reg,
-                   Mint::value_offset() - kHeapObjectTag);
+                   compiler::target::Mint::value_offset() - kHeapObjectTag);
   __ StoreToOffset(kWord, value_hi, out_reg,
-                   Mint::value_offset() - kHeapObjectTag + kWordSize);
+                   compiler::target::Mint::value_offset() - kHeapObjectTag +
+                       compiler::target::kWordSize);
   __ Bind(&done);
 }
 
@@ -4375,10 +4566,13 @@
                               Register result,
                               Register temp,
                               Label* deopt) {
-  __ LoadFieldFromOffset(kWord, result, mint, Mint::value_offset());
+  __ LoadFieldFromOffset(kWord, result, mint,
+                         compiler::target::Mint::value_offset());
   if (deopt != NULL) {
-    __ LoadFieldFromOffset(kWord, temp, mint, Mint::value_offset() + kWordSize);
-    __ cmp(temp, Operand(result, ASR, kBitsPerWord - 1));
+    __ LoadFieldFromOffset(
+        kWord, temp, mint,
+        compiler::target::Mint::value_offset() + compiler::target::kWordSize);
+    __ cmp(temp, Operand(result, ASR, compiler::target::kBitsPerWord - 1));
     __ b(deopt, NE);
   }
 }
@@ -5149,7 +5343,7 @@
   }
 }
 
-LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary(
+LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
   const intptr_t kNumTemps = 0;
@@ -5163,8 +5357,7 @@
   return summary;
 }
 
-void CaseInsensitiveCompareUC16Instr::EmitNativeCode(
-    FlowGraphCompiler* compiler) {
+void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   // Call the function.
   __ CallRuntime(TargetFunction(), TargetFunction().argument_count());
 }
@@ -5366,7 +5559,8 @@
   const Register value_obj = locs()->in(0).reg();
   ASSERT(result == R0);
   ASSERT(result != value_obj);
-  __ LoadDFromOffset(DTMP, value_obj, Double::value_offset() - kHeapObjectTag);
+  __ LoadDFromOffset(DTMP, value_obj,
+                     compiler::target::Double::value_offset() - kHeapObjectTag);
 
   Label done, do_call;
   // First check for NaN. Checking for minint after the conversion doesn't work
@@ -5445,9 +5639,9 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* result = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  // Low (<= Q7) Q registers are needed for the conversion instructions.
+  // Low (< Q7) Q registers are needed for the conversion instructions.
   result->set_in(0, Location::RequiresFpuRegister());
-  result->set_out(0, Location::FpuRegisterLocation(Q7));
+  result->set_out(0, Location::FpuRegisterLocation(Q6));
   return result;
 }
 
@@ -5464,8 +5658,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* result = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  // Low (<= Q7) Q registers are needed for the conversion instructions.
-  result->set_in(0, Location::FpuRegisterLocation(Q7));
+  // Low (< Q7) Q registers are needed for the conversion instructions.
+  result->set_in(0, Location::FpuRegisterLocation(Q6));
   result->set_out(0, Location::RequiresFpuRegister());
   return result;
 }
@@ -5723,7 +5917,8 @@
   summary->set_in(0, Location::RequiresRegister());
   summary->set_in(1, Location::RequiresRegister());
   summary->set_temp(0, Location::RequiresRegister());
-  summary->set_temp(1, Location::RequiresFpuRegister());
+  // Request register that overlaps with S0..S31.
+  summary->set_temp(1, Location::FpuRegisterLocation(Q0));
   // Output is a pair of registers.
   summary->set_out(0, Location::Pair(Location::RequiresRegister(),
                                      Location::RequiresRegister()));
@@ -5942,11 +6137,11 @@
   Register value = locs()->in(0).reg();
   Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
   if (cids_.IsSingleCid()) {
-    __ CompareImmediate(value, Smi::RawValue(cids_.cid_start));
+    __ CompareImmediate(value, compiler::target::ToRawSmi(cids_.cid_start));
     __ b(deopt, NE);
   } else {
-    __ AddImmediate(value, -Smi::RawValue(cids_.cid_start));
-    __ CompareImmediate(value, Smi::RawValue(cids_.Extent()));
+    __ AddImmediate(value, -compiler::target::ToRawSmi(cids_.cid_start));
+    __ CompareImmediate(value, compiler::target::ToRawSmi(cids_.Extent()));
     __ b(deopt, HI);  // Unsigned higher.
   }
 }
@@ -5972,9 +6167,11 @@
   Location index_loc = locs()->in(kIndexPos);
 
   if (length_loc.IsConstant() && index_loc.IsConstant()) {
-    ASSERT((Smi::Cast(length_loc.constant()).Value() <=
-            Smi::Cast(index_loc.constant()).Value()) ||
-           (Smi::Cast(index_loc.constant()).Value() < 0));
+#ifdef DEBUG
+    const int32_t length = compiler::target::SmiValue(length_loc.constant());
+    const int32_t index = compiler::target::SmiValue(index_loc.constant());
+    ASSERT((length <= index) || (index < 0));
+#endif
     // Unconditionally deoptimize for constant bounds checks because they
     // only occur only when index is out-of-bounds.
     __ b(deopt);
@@ -5984,20 +6181,21 @@
   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());
-    __ CompareImmediate(length, reinterpret_cast<int32_t>(index.raw()));
+    __ CompareImmediate(length,
+                        compiler::target::ToRawSmi(index_loc.constant()));
     __ b(deopt, LS);
   } 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) {
+    if (compiler::target::SmiValue(length_loc.constant()) ==
+        compiler::target::kSmiMax) {
       __ tst(index, Operand(index));
       __ b(deopt, MI);
     } else {
-      __ CompareImmediate(index, reinterpret_cast<int32_t>(length.raw()));
+      __ CompareImmediate(index,
+                          compiler::target::ToRawSmi(length_loc.constant()));
       __ b(deopt, CS);
     }
   } else {
@@ -6229,7 +6427,8 @@
 
     switch (instruction()->AsShiftInt64Op()->op_kind()) {
       case Token::kSHR:
-        __ Asr(out_hi, left_hi, Operand(kBitsPerWord - 1), GE);
+        __ Asr(out_hi, left_hi, Operand(compiler::target::kBitsPerWord - 1),
+               GE);
         __ mov(out_lo, Operand(out_hi), GE);
         break;
       case Token::kSHL: {
@@ -6248,10 +6447,13 @@
     // The unboxed int64 argument is passed through a dedicated slot in Thread.
     // TODO(dartbug.com/33549): Clean this up when unboxed values
     // could be passed as arguments.
-    __ StoreToOffset(kWord, right_lo, THR,
-                     Thread::unboxed_int64_runtime_arg_offset());
-    __ StoreToOffset(kWord, right_hi, THR,
-                     Thread::unboxed_int64_runtime_arg_offset() + kWordSize);
+    __ StoreToOffset(
+        kWord, right_lo, THR,
+        compiler::target::Thread::unboxed_int64_runtime_arg_offset());
+    __ StoreToOffset(
+        kWord, right_hi, THR,
+        compiler::target::Thread::unboxed_int64_runtime_arg_offset() +
+            compiler::target::kWordSize);
   }
 };
 
@@ -6389,10 +6591,13 @@
     // The unboxed int64 argument is passed through a dedicated slot in Thread.
     // TODO(dartbug.com/33549): Clean this up when unboxed values
     // could be passed as arguments.
-    __ StoreToOffset(kWord, right_lo, THR,
-                     Thread::unboxed_int64_runtime_arg_offset());
-    __ StoreToOffset(kWord, right_hi, THR,
-                     Thread::unboxed_int64_runtime_arg_offset() + kWordSize);
+    __ StoreToOffset(
+        kWord, right_lo, THR,
+        compiler::target::Thread::unboxed_int64_runtime_arg_offset());
+    __ StoreToOffset(
+        kWord, right_hi, THR,
+        compiler::target::Thread::unboxed_int64_runtime_arg_offset() +
+            compiler::target::kWordSize);
   }
 };
 
@@ -6685,7 +6890,7 @@
       Label* deopt =
           compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
       ASSERT(to() == kUnboxedInt32);
-      __ cmp(in_hi, Operand(in_lo, ASR, kBitsPerWord - 1));
+      __ cmp(in_hi, Operand(in_lo, ASR, compiler::target::kBitsPerWord - 1));
       __ b(deopt, NE);
     }
   } else if (from() == kUnboxedUint32 || from() == kUnboxedInt32) {
@@ -6700,7 +6905,7 @@
       __ eor(out_hi, out_hi, Operand(out_hi));
     } else {
       ASSERT(from() == kUnboxedInt32);
-      __ mov(out_hi, Operand(in, ASR, kBitsPerWord - 1));
+      __ mov(out_hi, Operand(in, ASR, compiler::target::kBitsPerWord - 1));
     }
   } else {
     UNREACHABLE();
@@ -6723,7 +6928,8 @@
   Register reg = locs()->in(0).reg();
   // There are no builtin sign- or zero-extension instructions, so we'll have to
   // use shifts instead.
-  const intptr_t shift_length = (kWordSize - from_width_bytes_) * kBitsPerByte;
+  const intptr_t shift_length =
+      (compiler::target::kWordSize - from_width_bytes()) * kBitsPerByte;
   __ Lsl(reg, reg, Operand(shift_length));
   switch (representation_) {
     case kUnboxedInt32:  // Sign extend operand.
@@ -6845,10 +7051,15 @@
 
 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BlockEntryInstr* entry = normal_entry();
-  if (entry == nullptr) entry = osr_entry();
-
-  if (!compiler->CanFallThroughTo(entry)) {
-    __ b(compiler->GetJumpLabel(entry));
+  if (entry != nullptr) {
+    if (!compiler->CanFallThroughTo(entry)) {
+      FATAL("Checked function entry must have no offset");
+    }
+  } else {
+    entry = osr_entry();
+    if (!compiler->CanFallThroughTo(entry)) {
+      __ b(compiler->GetJumpLabel(entry));
+    }
   }
 }
 
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 5ba37ca..1b5b2c3 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -894,24 +894,13 @@
   __ ReserveAlignedFrameSpace(compiler::ffi::NumStackSlots(arg_locations_) *
                               kWordSize);
 
+  FrameRebase rebase(/*old_base=*/FPREG, /*new_base=*/saved_fp,
+                     /*stack_delta=*/0);
   for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
-    Location origin = locs()->in(i);
-    Location target = arg_locations_[i];
-
-    if (target.IsStackSlot()) {
-      if (origin.IsRegister()) {
-        __ StoreToOffset(origin.reg(), SPREG, target.ToStackSlotOffset());
-      } else if (origin.IsFpuRegister()) {
-        __ StoreDToOffset(origin.fpu_reg(), SPREG, target.ToStackSlotOffset());
-      } else if (origin.IsStackSlot() || origin.IsDoubleStackSlot()) {
-        // The base register cannot be SPREG because we've moved it.
-        ASSERT(origin.base_reg() == FPREG);
-        __ LoadFromOffset(TMP, saved_fp, origin.ToStackSlotOffset());
-        __ StoreToOffset(TMP, SPREG, target.ToStackSlotOffset());
-      }
-    } else {
-      ASSERT(origin.Equals(target));
-    }
+    const Location origin = rebase.Rebase(locs()->in(i));
+    const Location target = arg_locations_[i];
+    ConstantTemporaryAllocator temp_alloc(temp);
+    compiler->EmitMove(target, origin, &temp_alloc);
   }
 
   // We need to copy a dummy return address up into the dummy stack frame so the
@@ -927,7 +916,7 @@
   __ mov(CSP, SP);
 
   // Update information in the thread object and enter a safepoint.
-  __ TransitionGeneratedToNative(branch, temp);
+  __ TransitionGeneratedToNative(branch, FPREG, temp);
 
   __ blr(branch);
 
@@ -955,6 +944,179 @@
   __ set_constant_pool_allowed(true);
 }
 
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ LeaveDartFrame();
+
+  // The dummy return address is in LR, no need to pop it as on Intel.
+
+  // These can be anything besides the return register (R0) and THR (R26).
+  const Register vm_tag_reg = R1, old_exit_frame_reg = R2, tmp = R3;
+
+  __ Pop(old_exit_frame_reg);
+
+  // Restore top_resource.
+  __ Pop(tmp);
+  __ StoreToOffset(tmp, THR, compiler::target::Thread::top_resource_offset());
+
+  __ Pop(vm_tag_reg);
+
+  // Reset the exit frame info to
+  // old_exit_frame_reg *before* entering the safepoint.
+  __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg, tmp);
+
+  __ PopNativeCalleeSavedRegisters();
+
+  // Leave the entry frame.
+  __ LeaveFrame();
+
+  // Leave the dummy frame holding the pushed arguments.
+  __ LeaveFrame();
+
+  // Restore the actual stack pointer from SPREG.
+  __ RestoreCSP();
+
+  __ Ret();
+
+  // For following blocks.
+  __ set_constant_pool_allowed(true);
+}
+
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+                                    Location loc) const {
+  ASSERT(!loc.IsPairLocation());
+
+  if (loc.HasStackIndex()) return;
+
+  if (loc.IsRegister()) {
+    __ Push(loc.reg());
+  } else if (loc.IsFpuRegister()) {
+    __ PushDouble(loc.fpu_reg());
+  } else {
+    UNREACHABLE();
+  }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (FLAG_precompiled_mode) {
+    UNREACHABLE();
+  }
+
+  // Constant pool cannot be used until we enter the actual Dart frame.
+  __ set_constant_pool_allowed(false);
+
+  __ Bind(compiler->GetJumpLabel(this));
+
+  // We don't use the regular stack pointer in ARM64, so we have to copy the
+  // native stack pointer into the Dart stack pointer.
+  __ SetupDartSP();
+
+  // Create a dummy frame holding the pushed arguments. This simplifies
+  // NativeReturnInstr::EmitNativeCode.
+  __ EnterFrame(0);
+
+  // Save the argument registers, in reverse order.
+  for (intptr_t i = argument_locations_->length(); i-- > 0;) {
+    SaveArgument(compiler, argument_locations_->At(i));
+  }
+
+  // Enter the entry frame.
+  __ EnterFrame(0);
+
+  // Save a space for the code object.
+  __ PushImmediate(0);
+
+  __ PushNativeCalleeSavedRegisters();
+
+  // Load the thread object.
+  // TODO(35765): Fix linking issue on AOT.
+  // TOOD(35934): Exclude native callbacks from snapshots.
+  //
+  // Create another frame to align the frame before continuing in "native" code.
+  {
+    __ EnterFrame(0);
+    __ ReserveAlignedFrameSpace(0);
+
+    __ LoadImmediate(
+        R0, reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback));
+    __ blr(R0);
+    __ mov(THR, R0);
+
+    __ LeaveFrame();
+  }
+
+  // Refresh write barrier mask.
+  __ ldr(BARRIER_MASK,
+         Address(THR, compiler::target::Thread::write_barrier_mask_offset()));
+
+  // Save the current VMTag on the stack.
+  __ LoadFromOffset(R0, THR, compiler::target::Thread::vm_tag_offset());
+  __ Push(R0);
+
+  // Save the top resource.
+  __ LoadFromOffset(R0, THR, compiler::target::Thread::top_resource_offset());
+  __ Push(R0);
+  __ StoreToOffset(ZR, THR, compiler::target::Thread::top_resource_offset());
+
+  // Save the top exit frame info. We don't set it to 0 yet in Thread because we
+  // need to leave the safepoint first.
+  __ LoadFromOffset(R0, THR,
+                    compiler::target::Thread::top_exit_frame_info_offset());
+  __ Push(R0);
+
+  // In debug mode, verify that we've pushed the top exit frame info at the
+  // correct offset from FP.
+  __ EmitEntryFrameVerification();
+
+  // TransitionNativeToGenerated will reset top exit frame info to 0 *after*
+  // leaving the safepoint.
+  __ TransitionNativeToGenerated(R0);
+
+  // Now that the safepoint has ended, we can touch Dart objects without
+  // handles.
+
+  // Otherwise we'll clobber the argument sent from the caller.
+  ASSERT(CallingConventions::ArgumentRegisters[0] != TMP &&
+         CallingConventions::ArgumentRegisters[0] != TMP2 &&
+         CallingConventions::ArgumentRegisters[0] != R1);
+  __ LoadImmediate(CallingConventions::ArgumentRegisters[0], callback_id_);
+  __ LoadFromOffset(R1, THR,
+                    compiler::target::Thread::verify_callback_entry_offset());
+  __ blr(R1);
+
+  // Load the code object.
+  __ LoadFromOffset(R0, THR, compiler::target::Thread::callback_code_offset());
+  __ LoadFieldFromOffset(R0, R0,
+                         compiler::target::GrowableObjectArray::data_offset());
+  __ LoadFieldFromOffset(CODE_REG, R0,
+                         compiler::target::Array::data_offset() +
+                             callback_id_ * compiler::target::kWordSize);
+
+  // Put the code object in the reserved slot.
+  __ StoreToOffset(CODE_REG, FPREG,
+                   kPcMarkerSlotFromFp * compiler::target::kWordSize);
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    __ ldr(PP,
+           Address(THR, compiler::target::Thread::global_object_pool_offset()));
+    __ sub(PP, PP, Operand(kHeapObjectTag));  // Pool in PP is untagged!
+  } else {
+    // We now load the pool pointer (PP) with a GC safe value as we are about to
+    // invoke dart code. We don't need a real object pool here.
+    // Smi zero does not work because ARM64 assumes PP to be untagged.
+    __ LoadObject(PP, compiler::NullObject());
+  }
+
+  // Load a GC-safe value for the arguments descriptor (unused but tagged).
+  __ mov(ARGS_DESC_REG, ZR);
+
+  // Load a dummy return address which suggests that we are inside of
+  // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+  __ LoadFromOffset(LR, THR,
+                    compiler::target::Thread::invoke_dart_code_stub_offset());
+  __ LoadFieldFromOffset(LR, LR, compiler::target::Code::entry_point_offset());
+
+  FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -1105,18 +1267,19 @@
   switch (class_id_) {
     case kArrayCid:
     case kImmutableArrayCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
+      return kTagged;
     case kOneByteStringCid:
     case kTwoByteStringCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kTypedDataUint16ArrayCid:
     case kExternalOneByteStringCid:
     case kExternalTwoByteStringCid:
-      return kTagged;
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1248,51 +1411,37 @@
     return;
   }
 
-  if ((representation() == kUnboxedInt32) ||
-      (representation() == kUnboxedUint32)) {
-    const Register result = locs()->out(0).reg();
-    switch (class_id()) {
-      case kTypedDataInt32ArrayCid:
-        ASSERT(representation() == kUnboxedInt32);
-        if (aligned()) {
-          __ ldr(result, element_address, kWord);
-        } else {
-          __ LoadUnaligned(result, address, TMP, kWord);
-        }
-        break;
-      case kTypedDataUint32ArrayCid:
-        ASSERT(representation() == kUnboxedUint32);
-        if (aligned()) {
-          __ ldr(result, element_address, kUnsignedWord);
-        } else {
-          __ LoadUnaligned(result, address, TMP, kUnsignedWord);
-        }
-        break;
-      default:
-        UNREACHABLE();
-    }
-    return;
-  }
-
-  if (representation() == kUnboxedInt64) {
-    ASSERT(class_id() == kTypedDataInt64ArrayCid ||
-           class_id() == kTypedDataUint64ArrayCid);
-    Register result = locs()->out(0).reg();
-    if (aligned()) {
-      __ ldr(result, element_address, kDoubleWord);
-    } else {
-      __ LoadUnaligned(result, address, TMP, kDoubleWord);
-    }
-    return;
-  }
-
-  ASSERT(representation() == kTagged);
   const Register result = locs()->out(0).reg();
   switch (class_id()) {
+    case kTypedDataInt32ArrayCid:
+      ASSERT(representation() == kUnboxedInt32);
+      if (aligned()) {
+        __ ldr(result, element_address, kWord);
+      } else {
+        __ LoadUnaligned(result, address, TMP, kWord);
+      }
+      break;
+    case kTypedDataUint32ArrayCid:
+      ASSERT(representation() == kUnboxedUint32);
+      if (aligned()) {
+        __ ldr(result, element_address, kUnsignedWord);
+      } else {
+        __ LoadUnaligned(result, address, TMP, kUnsignedWord);
+      }
+      break;
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid:
+      ASSERT(representation() == kUnboxedInt64);
+      if (aligned()) {
+        __ ldr(result, element_address, kDoubleWord);
+      } else {
+        __ LoadUnaligned(result, address, TMP, kDoubleWord);
+      }
+      break;
     case kTypedDataInt8ArrayCid:
+      ASSERT(representation() == kUnboxedIntPtr);
       ASSERT(index_scale() == 1);
       __ ldr(result, element_address, kByte);
-      __ SmiTag(result);
       break;
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
@@ -1300,29 +1449,30 @@
     case kExternalTypedDataUint8ClampedArrayCid:
     case kOneByteStringCid:
     case kExternalOneByteStringCid:
+      ASSERT(representation() == kUnboxedIntPtr);
       ASSERT(index_scale() == 1);
       __ ldr(result, element_address, kUnsignedByte);
-      __ SmiTag(result);
       break;
     case kTypedDataInt16ArrayCid:
+      ASSERT(representation() == kUnboxedIntPtr);
       if (aligned()) {
         __ ldr(result, element_address, kHalfword);
       } else {
         __ LoadUnaligned(result, address, TMP, kHalfword);
       }
-      __ SmiTag(result);
       break;
     case kTypedDataUint16ArrayCid:
     case kTwoByteStringCid:
     case kExternalTwoByteStringCid:
+      ASSERT(representation() == kUnboxedIntPtr);
       if (aligned()) {
         __ ldr(result, element_address, kUnsignedHalfword);
       } else {
         __ LoadUnaligned(result, address, TMP, kUnsignedHalfword);
       }
-      __ SmiTag(result);
       break;
     default:
+      ASSERT(representation() == kTagged);
       ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
       ASSERT(aligned());
       __ ldr(result, element_address);
@@ -1398,15 +1548,16 @@
   ASSERT(idx == 2);
   switch (class_id_) {
     case kArrayCid:
+      return kTagged;
     case kOneByteStringCid:
     case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
     case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
     case kTypedDataUint16ArrayCid:
-      return kTagged;
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1522,6 +1673,7 @@
     case kTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ArrayCid:
     case kOneByteStringCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       ASSERT(aligned());
       if (locs()->in(2).IsConstant()) {
         const Smi& constant = Smi::Cast(locs()->in(2).constant());
@@ -1529,13 +1681,13 @@
         __ str(TMP, Address(address), kUnsignedByte);
       } else {
         const Register value = locs()->in(2).reg();
-        __ SmiUntag(TMP, value);
-        __ str(TMP, Address(address), kUnsignedByte);
+        __ str(value, Address(address), kUnsignedByte);
       }
       break;
     }
     case kTypedDataUint8ClampedArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       ASSERT(aligned());
       if (locs()->in(2).IsConstant()) {
         const Smi& constant = Smi::Cast(locs()->in(2).constant());
@@ -1550,23 +1702,22 @@
         __ str(TMP, Address(address), kUnsignedByte);
       } else {
         const Register value = locs()->in(2).reg();
-        __ CompareImmediate(value, 0x1FE);  // Smi value and smi 0xFF.
         // Clamp to 0x00 or 0xFF respectively.
-        __ csetm(TMP, GT);             // TMP = value > 0x1FE ? -1 : 0.
+        __ CompareImmediate(value, 0xFF);
+        __ csetm(TMP, GT);             // TMP = value > 0xFF ? -1 : 0.
         __ csel(TMP, value, TMP, LS);  // TMP = value in range ? value : TMP.
-        __ SmiUntag(TMP);
         __ str(TMP, Address(address), kUnsignedByte);
       }
       break;
     }
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       const Register value = locs()->in(2).reg();
-      __ SmiUntag(TMP, value);
       if (aligned()) {
-        __ str(TMP, Address(address), kUnsignedHalfword);
+        __ str(value, Address(address), kUnsignedHalfword);
       } else {
-        __ StoreUnaligned(TMP, address, scratch, kUnsignedHalfword);
+        __ StoreUnaligned(value, address, scratch, kUnsignedHalfword);
       }
       break;
     }
@@ -1679,13 +1830,6 @@
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
 
   if (field_cid == kDynamicCid) {
-    if (Compiler::IsBackgroundCompilation()) {
-      // Field state changed while compiling.
-      Compiler::AbortBackgroundCompilation(
-          deopt_id(),
-          "GuardFieldClassInstr: field state changed while compiling");
-    }
-    ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
@@ -1836,13 +1980,6 @@
 
 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   if (field().guarded_list_length() == Field::kNoFixedLength) {
-    if (Compiler::IsBackgroundCompilation()) {
-      // Field state changed while compiling.
-      Compiler::AbortBackgroundCompilation(
-          deopt_id(),
-          "GuardFieldLengthInstr: field state changed while compiling");
-    }
-    ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
@@ -2320,7 +2457,7 @@
       num_elements()->BindsToConstant() &&
       num_elements()->BoundConstant().IsSmi()) {
     const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value();
-    if ((length >= 0) && (length <= Array::kMaxElements)) {
+    if (Array::IsValidLength(length)) {
       Label slow_path, done;
       InlineArrayAllocation(compiler, length, &slow_path, &done);
       __ Bind(&slow_path);
@@ -2806,7 +2943,7 @@
     if (using_shared_stub) {
       auto object_store = compiler->isolate()->object_store();
       const bool live_fpu_regs = locs->live_registers()->FpuRegisterCount() > 0;
-      const auto& stub = Code::Handle(
+      const auto& stub = Code::ZoneHandle(
           compiler->zone(),
           live_fpu_regs
               ? object_store->stack_overflow_stub_with_fpu_regs_stub()
@@ -4375,7 +4512,7 @@
   }
 }
 
-LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary(
+LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
   const intptr_t kNumTemps = 0;
@@ -4389,8 +4526,7 @@
   return summary;
 }
 
-void CaseInsensitiveCompareUC16Instr::EmitNativeCode(
-    FlowGraphCompiler* compiler) {
+void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   // Call the function.
   __ CallRuntime(TargetFunction(), TargetFunction().argument_count());
 }
@@ -5099,7 +5235,7 @@
 
   const bool live_fpu_regs = locs->live_registers()->FpuRegisterCount() > 0;
   auto object_store = compiler->isolate()->object_store();
-  const auto& stub = Code::Handle(
+  const auto& stub = Code::ZoneHandle(
       compiler->zone(),
       live_fpu_regs ? object_store->null_error_stub_with_fpu_regs_stub()
                     : object_store->null_error_stub_without_fpu_regs_stub());
@@ -5942,30 +6078,18 @@
 
 void UnboxedWidthExtenderInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register reg = locs()->in(0).reg();
-  switch (representation_) {
-    case kUnboxedInt32:  // Sign extend operand.
-      switch (from_width_bytes_) {
-        case 1:
-          __ sxtb(reg, reg);
-          break;
-        case 2:
-          __ sxth(reg, reg);
-          break;
-        default:
-          UNREACHABLE();
-      }
+  switch (from_representation()) {
+    case kSmallUnboxedInt8:  // Sign extend operand.
+      __ sxtb(reg, reg);
       break;
-    case kUnboxedUint32:  // Zero extend operand.
-      switch (from_width_bytes_) {
-        case 1:
-          __ uxtb(reg, reg);
-          break;
-        case 2:
-          __ uxth(reg, reg);
-          break;
-        default:
-          UNREACHABLE();
-      }
+    case kSmallUnboxedInt16:
+      __ sxth(reg, reg);
+      break;
+    case kSmallUnboxedUint8:  // Zero extend operand.
+      __ uxtb(reg, reg);
+      break;
+    case kSmallUnboxedUint16:
+      __ uxth(reg, reg);
       break;
     default:
       UNREACHABLE();
@@ -6003,10 +6127,15 @@
 
 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BlockEntryInstr* entry = normal_entry();
-  if (entry == nullptr) entry = osr_entry();
-
-  if (!compiler->CanFallThroughTo(entry)) {
-    __ b(compiler->GetJumpLabel(entry));
+  if (entry != nullptr) {
+    if (!compiler->CanFallThroughTo(entry)) {
+      FATAL("Checked function entry must have no offset");
+    }
+  } else {
+    entry = osr_entry();
+    if (!compiler->CanFallThroughTo(entry)) {
+      __ b(compiler->GetJumpLabel(entry));
+    }
   }
 }
 
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index e75bfef..c869600 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -32,7 +32,6 @@
 #define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M)                                  \
   M(BinaryInt32Op)                                                             \
   M(BinaryUint32Op)                                                            \
-  M(BoxInt64)                                                                  \
   M(CheckCondition)                                                            \
   M(DoubleToInteger)                                                           \
   M(ExtractNthOutput)                                                          \
@@ -46,8 +45,7 @@
   M(SpeculativeShiftUint32Op)                                                  \
   M(TruncDivMod)                                                               \
   M(UnaryUint32Op)                                                             \
-  M(IntConverter)                                                              \
-  M(UnboxedWidthExtender)
+  M(IntConverter)
 
 // List of instructions that are not used by DBC.
 // Things we aren't planning to implement for DBC:
@@ -56,7 +54,7 @@
 // - Optimized RegExps,
 // - Precompilation.
 #define FOR_EACH_UNREACHABLE_INSTRUCTION(M)                                    \
-  M(CaseInsensitiveCompareUC16)                                                \
+  M(CaseInsensitiveCompare)                                                    \
   M(GenericCheckBound)                                                         \
   M(IndirectGoto)                                                              \
   M(Int64ToDouble)                                                             \
@@ -66,7 +64,8 @@
   M(UnaryInt64Op)                                                              \
   M(CheckedSmiOp)                                                              \
   M(CheckedSmiComparison)                                                      \
-  M(SimdOp)
+  M(SimdOp)                                                                    \
+  M(NativeReturn)
 
 // Location summaries actually are not used by the unoptimizing DBC compiler
 // because we don't allocate any registers.
@@ -994,7 +993,20 @@
 }
 
 void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
+  const Representation result_rep =
+      compiler::ffi::ResultHostRepresentation(signature_);
+  // TODO(36809): In 32 bit we'll need a result location as well.
+  const TypedData& signature_descriptor =
+      TypedData::Handle(compiler::ffi::FfiSignatureDescriptor::New(
+          *arg_host_locations_, result_rep));
+
+  const intptr_t sigdesc_kidx = __ AddConstant(signature_descriptor);
+
+  __ FfiCall(sigdesc_kidx);
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
+                                 token_pos());
+  compiler->RecordAfterCallHelper(token_pos(), deopt_id(), 0,
+                                  FlowGraphCompiler::kHasResult, locs());
 }
 
 EMIT_NATIVE_CODE(NativeCall,
@@ -1327,10 +1339,15 @@
 
 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BlockEntryInstr* entry = normal_entry();
-  if (entry == nullptr) entry = osr_entry();
-
-  if (!compiler->CanFallThroughTo(entry)) {
-    __ Jump(compiler->GetJumpLabel(entry));
+  if (entry != nullptr) {
+    if (!compiler->CanFallThroughTo(entry)) {
+      FATAL("Checked function entry must have no offset");
+    }
+  } else {
+    entry = osr_entry();
+    if (!compiler->CanFallThroughTo(entry)) {
+      __ Jump(compiler->GetJumpLabel(entry));
+    }
   }
 }
 
@@ -1380,18 +1397,23 @@
     case kTypedDataUint8ClampedArrayCid:
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
+
     case kOneByteStringCid:
     case kTwoByteStringCid:
     case kExternalOneByteStringCid:
-    case kExternalTwoByteStringCid:
       return CompileType::FromCid(kSmiCid);
 
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
       return CompileType::Int();
 
+    // These are unsupported on DBC and will cause a bailout during
+    // EmitNativeCode.
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kExternalTwoByteStringCid:
+      return CompileType::FromCid(kSmiCid);
+
     default:
       UNREACHABLE();
       return CompileType::Dynamic();
@@ -1402,18 +1424,16 @@
   switch (class_id_) {
     case kArrayCid:
     case kImmutableArrayCid:
+      return kTagged;
+    case kOneByteStringCid:
+    case kTwoByteStringCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
+    case kExternalOneByteStringCid:
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kExternalOneByteStringCid:
-    case kExternalTwoByteStringCid:
-      return kTagged;
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1427,6 +1447,14 @@
       return kUnboxedFloat32x4;
     case kTypedDataFloat64x2ArrayCid:
       return kUnboxedFloat64x2;
+
+    // These are unsupported on DBC and will cause a bailout during
+    // EmitNativeCode.
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kExternalTwoByteStringCid:
+      return kUnboxedIntPtr;
+
     default:
       UNREACHABLE();
       return kTagged;
@@ -1445,18 +1473,13 @@
   ASSERT(idx == 2);
   switch (class_id_) {
     case kArrayCid:
+      return kTagged;
     case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kExternalOneByteStringCid:
-    case kExternalTwoByteStringCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
+    case kExternalOneByteStringCid:
     case kExternalTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
-      return kTagged;
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1470,6 +1493,14 @@
       return kUnboxedInt32x4;
     case kTypedDataFloat64x2ArrayCid:
       return kUnboxedFloat64x2;
+
+    // These are unsupported on DBC and will cause a bailout during
+    // EmitNativeCode.
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+      return kUnboxedIntPtr;
     default:
       UNREACHABLE();
       return kTagged;
@@ -1681,51 +1712,72 @@
   }
 }
 
-EMIT_NATIVE_CODE(Box, 1, Location::RequiresRegister(), LocationSummary::kCall) {
-  ASSERT(from_representation() == kUnboxedDouble);
-  const Register value = locs()->in(0).reg();
+void BoxInstr::EmitAllocateBox(FlowGraphCompiler* compiler) {
   const Register out = locs()->out(0).reg();
-  const intptr_t instance_size = compiler->double_class().instance_size();
+  const Class& box_class = compiler->BoxClassFor(from_representation());
+  const intptr_t instance_size = box_class.instance_size();
   Isolate* isolate = Isolate::Current();
   ASSERT(Heap::IsAllocatableInNewSpace(instance_size));
-  if (!compiler->double_class().TraceAllocation(isolate)) {
+  if (!box_class.TraceAllocation(isolate)) {
     uword tags = 0;
     tags = RawObject::SizeTag::update(instance_size, tags);
-    tags = RawObject::ClassIdTag::update(compiler->double_class().id(), tags);
+    tags = RawObject::ClassIdTag::update(box_class.id(), tags);
     // tags also has the initial zero hash code on 64 bit.
     if (Smi::IsValid(tags)) {
       const intptr_t tags_kidx = __ AddConstant(Smi::Handle(Smi::New(tags)));
       __ AllocateOpt(out, tags_kidx);
     }
   }
-  const intptr_t kidx = __ AddConstant(compiler->double_class());
+  const intptr_t kidx = __ AddConstant(box_class);
   __ Allocate(kidx);
   compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
                                  token_pos());
   compiler->RecordSafepoint(locs());
   __ PopLocal(out);
+}
+
+EMIT_NATIVE_CODE(Box, 1, Location::RequiresRegister(), LocationSummary::kCall) {
+  ASSERT(from_representation() == kUnboxedDouble ||
+         from_representation() == kUnboxedFloat);
+  const Register value = locs()->in(0).reg();
+  const Register out = locs()->out(0).reg();
+  if (from_representation() == kUnboxedFloat) {
+    __ FloatToDouble(value, value);
+  }
+  EmitAllocateBox(compiler);
   __ WriteIntoDouble(out, value);
 }
 
 EMIT_NATIVE_CODE(Unbox, 1, Location::RequiresRegister()) {
-  ASSERT(representation() == kUnboxedDouble);
+  if (representation() == kUnboxedInt64) {
+    EmitLoadInt64FromBoxOrSmi(compiler);
+    return;
+  }
+  ASSERT(representation() == kUnboxedDouble ||
+         representation() == kUnboxedFloat);
   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) {
+  if (value_cid == box_cid ||
+      (speculative_mode() == kNotSpeculative && value_cid != kSmiCid)) {
     __ 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);
+    ASSERT(CanDeoptimize());
     compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass);
     __ UnboxDouble(result, box);
   } else {
     __ CheckedUnboxDouble(result, box);
+    ASSERT(CanDeoptimize());
     compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass);
   }
+  if (representation() == kUnboxedFloat) {
+    __ DoubleToFloat(result, result);
+  }
 }
 
 EMIT_NATIVE_CODE(UnboxInteger32, 1, Location::RequiresRegister()) {
@@ -1761,6 +1813,39 @@
 #endif  // defined(ARCH_IS_64_BIT)
 }
 
+EMIT_NATIVE_CODE(BoxInt64, 1, Location::RequiresRegister()) {
+#if defined(ARCH_IS_64_BIT)
+  Label done;
+  const Register value = locs()->in(0).reg();
+  const Register out = locs()->out(0).reg();
+  __ BoxInt64(out, value);
+  __ Jump(&done);
+  EmitAllocateBox(compiler);
+  __ WriteIntoMint(out, value);
+  __ Bind(&done);
+#else
+  Unsupported(compiler);
+  UNREACHABLE();
+#endif  // defined(ARCH_IS_64_BIT)
+}
+
+void UnboxInstr::EmitLoadInt64FromBoxOrSmi(FlowGraphCompiler* compiler) {
+#if defined(ARCH_IS_64_BIT)
+  const Register out = locs()->out(0).reg();
+  const Register value = locs()->in(0).reg();
+  __ UnboxInt64(out, value);
+#else
+  Unsupported(compiler);
+  UNREACHABLE();
+#endif  // defined(ARCH_IS_64_BIT)
+}
+
+EMIT_NATIVE_CODE(UnboxedWidthExtender, 1, Location::RequiresRegister()) {
+  const Register out = locs()->out(0).reg();
+  const Register value = locs()->in(0).reg();
+  __ UnboxedWidthExtender(out, value, from_representation());
+}
+
 EMIT_NATIVE_CODE(DoubleToSmi, 1, Location::RequiresRegister()) {
   const Register value = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
@@ -2084,6 +2169,10 @@
                           (licm_hoisted_ ? ICData::kHoisted : 0));
 }
 
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNREACHABLE();
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 88ce5ba..7268abe 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+#include "platform/globals.h"
 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_IA32.
 #if defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -134,6 +135,65 @@
   __ ret();
 }
 
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  bool return_in_st0 = false;
+  if (result_representation_ == kUnboxedFloat ||
+      result_representation_ == kUnboxedDouble) {
+    ASSERT(locs()->in(0).IsFpuRegister() && locs()->in(0).fpu_reg() == XMM0);
+    return_in_st0 = true;
+  }
+
+  // Leave Dart frame.
+  __ LeaveFrame();
+
+  // EDI is the only sane choice for a temporary register here because:
+  //
+  // EDX is used for large return values.
+  // ESI == THR.
+  // Could be EBX or ECX, but that would make code below confusing.
+  const Register tmp = EDI;
+
+  // Pop dummy return address.
+  __ popl(tmp);
+
+  // Anything besides the return register(s!). Callee-saved registers will be
+  // restored later.
+  const Register vm_tag_reg = EBX, old_exit_frame_reg = ECX;
+
+  __ popl(old_exit_frame_reg);
+
+  // Restore top_resource.
+  __ popl(tmp);
+  __ movl(Address(THR, compiler::target::Thread::top_resource_offset()), tmp);
+
+  __ popl(vm_tag_reg);
+
+  // This will reset the exit frame info to old_exit_frame_reg *before* entering
+  // the safepoint.
+  __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg, tmp);
+
+  // Move XMM0 into ST0 if needed.
+  if (return_in_st0) {
+    if (result_representation_ == kUnboxedDouble) {
+      __ movsd(Address(SPREG, -8), XMM0);
+      __ fldl(Address(SPREG, -8));
+    } else {
+      __ movss(Address(SPREG, -4), XMM0);
+      __ flds(Address(SPREG, -4));
+    }
+  }
+
+  // Restore C++ ABI callee-saved registers.
+  __ popl(EDI);
+  __ popl(ESI);
+  __ popl(EBX);
+
+  // Leave the entry frame.
+  __ LeaveFrame();
+
+  __ ret();
+}
+
 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone,
                                                      bool opt) const {
   const intptr_t kNumInputs = 0;
@@ -217,14 +277,14 @@
     if (addr == 0) {
       __ pushl(EAX);
       __ LoadObject(EAX, value_);
-      __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
+      __ movsd(FpuTMP, FieldAddress(EAX, Double::value_offset()));
       __ popl(EAX);
     } else if (Utils::DoublesBitEqual(value_as_double, 0.0)) {
-      __ xorps(XMM0, XMM0);
+      __ xorps(FpuTMP, FpuTMP);
     } else {
-      __ movsd(XMM0, Address::Absolute(addr));
+      __ movsd(FpuTMP, Address::Absolute(addr));
     }
-    __ movsd(LocationToStackSlotAddress(destination), XMM0);
+    __ movsd(LocationToStackSlotAddress(destination), FpuTMP);
   } else {
     ASSERT(destination.IsStackSlot());
     if (value_.IsSmi() && representation() == kUnboxedInt32) {
@@ -846,9 +906,9 @@
 }
 
 void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register saved_fp = locs()->temp(0).reg();  // volatile
-  Register branch = locs()->in(TargetAddressIndex()).reg();
-  Register tmp = locs()->temp(1).reg();  // callee-saved
+  const Register saved_fp = locs()->temp(0).reg();  // volatile
+  const Register branch = locs()->in(TargetAddressIndex()).reg();
+  const Register tmp = locs()->temp(1).reg();  // callee-saved
 
   // Save frame pointer because we're going to update it when we enter the exit
   // frame.
@@ -866,45 +926,13 @@
     __ andl(SPREG, Immediate(~(OS::ActivationFrameAlignment() - 1)));
   }
 
-  // Load a 32-bit argument, or a 32-bit component of a 64-bit argument.
-  auto load_single_slot = [&](Location from, Location to) {
-    ASSERT(to.IsStackSlot());
-    if (from.IsRegister()) {
-      __ movl(LocationToStackSlotAddress(to), from.reg());
-    } else if (from.IsFpuRegister()) {
-      __ movss(LocationToStackSlotAddress(to), from.fpu_reg());
-    } else if (from.IsStackSlot() || from.IsDoubleStackSlot()) {
-      ASSERT(from.base_reg() == FPREG);
-      __ movl(tmp, Address(saved_fp, from.ToStackSlotOffset()));
-      __ movl(LocationToStackSlotAddress(to), tmp);
-    } else {
-      UNREACHABLE();
-    }
-  };
-
+  FrameRebase rebase(/*old_base=*/FPREG, /*new_base=*/saved_fp,
+                     /*stack_delta=*/0);
   for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
-    Location origin = locs()->in(i);
-    Location target = arg_locations_[i];
-
-    if (target.IsStackSlot()) {
-      load_single_slot(origin, target);
-    } else if (target.IsDoubleStackSlot()) {
-      if (origin.IsFpuRegister()) {
-        __ movsd(LocationToStackSlotAddress(target), origin.fpu_reg());
-      } else {
-        ASSERT(origin.IsDoubleStackSlot() && origin.base_reg() == FPREG);
-        __ movl(tmp, Address(saved_fp, origin.ToStackSlotOffset()));
-        __ movl(LocationToStackSlotAddress(target), tmp);
-        __ movl(tmp, Address(saved_fp, origin.ToStackSlotOffset() + 4));
-        __ movl(Address(SPREG, target.ToStackSlotOffset() + 4), tmp);
-      }
-    } else if (target.IsPairLocation()) {
-      ASSERT(origin.IsPairLocation());
-      load_single_slot(origin.AsPairLocation()->At(0),
-                       target.AsPairLocation()->At(0));
-      load_single_slot(origin.AsPairLocation()->At(1),
-                       target.AsPairLocation()->At(1));
-    }
+    const Location origin = rebase.Rebase(locs()->in(i));
+    const Location target = arg_locations_[i];
+    ConstantTemporaryAllocator tmp_alloc(tmp);
+    compiler->EmitMove(target, origin, &tmp_alloc);
   }
 
   // We need to copy a dummy return address up into the dummy stack frame so the
@@ -918,32 +946,22 @@
   __ popl(tmp);
   __ movl(Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), tmp);
 
-  __ TransitionGeneratedToNative(branch, tmp);
+  __ TransitionGeneratedToNative(branch, FPREG, tmp);
   __ call(branch);
 
   // The x86 calling convention requires floating point values to be returned on
   // the "floating-point stack" (aka. register ST0). We don't use the
   // floating-point stack in Dart, so we need to move the return value back into
   // an XMM register.
-  if (representation() == kUnboxedDouble || representation() == kUnboxedFloat) {
-    __ subl(SPREG, Immediate(8));
-    __ fstpl(Address(SPREG, 0));
-    __ TransitionNativeToGenerated(tmp);
-    __ fldl(Address(SPREG, 0));
-    __ addl(SPREG, Immediate(8));
-  } else {
-    __ TransitionNativeToGenerated(tmp);
+  if (representation() == kUnboxedDouble) {
+    __ fstpl(Address(SPREG, -kDoubleSize));
+    __ movsd(XMM0, Address(SPREG, -kDoubleSize));
+  } else if (representation() == kUnboxedFloat) {
+    __ fstps(Address(SPREG, -kFloatSize));
+    __ movss(XMM0, Address(SPREG, -kFloatSize));
   }
 
-  if (representation() == kUnboxedDouble) {
-    __ subl(SPREG, Immediate(8));
-    __ fstpl(Address(SPREG, 0));
-    __ movsd(XMM0, Address(SPREG, 0));
-  } else if (representation() == kUnboxedFloat) {
-    __ subl(SPREG, Immediate(4));
-    __ fstps(Address(SPREG, 0));
-    __ movss(XMM0, Address(SPREG, 0));
-  }
+  __ TransitionNativeToGenerated(tmp);
 
   // Leave dummy exit frame.
   __ LeaveFrame();
@@ -952,6 +970,117 @@
   __ popl(tmp);
 }
 
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+                                    Location loc) const {
+  if (loc.IsPairLocation()) {
+    // Save the components in reverse order so that they will be in
+    // little-endian order on the stack.
+    for (intptr_t i : {1, 0}) {
+      SaveArgument(compiler, loc.Component(i));
+    }
+    return;
+  }
+
+  if (loc.HasStackIndex()) return;
+
+  if (loc.IsRegister()) {
+    __ pushl(loc.reg());
+  } else if (loc.IsFpuRegister()) {
+    __ subl(SPREG, Immediate(8));
+    __ movsd(Address(SPREG, 0), loc.fpu_reg());
+  } else {
+    UNREACHABLE();
+  }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ Bind(compiler->GetJumpLabel(this));
+
+  // Enter the entry frame.
+  __ EnterFrame(0);
+
+  // Save a space for the code object.
+  __ xorl(EAX, EAX);
+  __ pushl(EAX);
+
+  // Save ABI callee-saved registers.
+  __ pushl(EBX);
+  __ pushl(ESI);
+  __ pushl(EDI);
+
+  // Load the thread object.
+  // TOOD(35934): Exclude native callbacks from snapshots.
+  // Linking in AOT is not relevant here since we don't support AOT for IA32.
+  // Create another frame to align the frame before continuing in "native" code.
+  {
+    __ EnterFrame(0);
+    __ ReserveAlignedFrameSpace(0);
+
+    __ movl(
+        EAX,
+        Immediate(reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback)));
+    __ call(EAX);
+    __ movl(THR, EAX);
+
+    __ LeaveFrame();
+  }
+
+  // Save the current VMTag on the stack.
+  __ movl(ECX, Assembler::VMTagAddress());
+  __ pushl(ECX);
+
+  // Save top resource.
+  __ pushl(Address(THR, compiler::target::Thread::top_resource_offset()));
+  __ movl(Address(THR, compiler::target::Thread::top_resource_offset()),
+          Immediate(0));
+
+  // Save top exit frame info. Stack walker expects it to be here.
+  __ pushl(
+      Address(THR, compiler::target::Thread::top_exit_frame_info_offset()));
+
+  // In debug mode, verify that we've pushed the top exit frame info at the
+  // correct offset from FP.
+  __ EmitEntryFrameVerification();
+
+  // TransitionNativeToGenerated will reset top exit frame info to 0 *after*
+  // leaving the safepoint.
+  __ TransitionNativeToGenerated(EAX);
+
+  // Now that the safepoint has ended, we can hold Dart objects with bare hands.
+  // TODO(35934): fix linking issue
+  __ pushl(Immediate(callback_id_));
+  __ movl(
+      EAX,
+      Address(THR, compiler::target::Thread::verify_callback_entry_offset()));
+  __ call(EAX);
+  __ popl(EAX);
+
+  // Load the code object.
+  __ movl(EAX, Address(THR, compiler::target::Thread::callback_code_offset()));
+  __ movl(EAX, FieldAddress(
+                   EAX, compiler::target::GrowableObjectArray::data_offset()));
+  __ movl(CODE_REG,
+          FieldAddress(EAX, compiler::target::Array::data_offset() +
+                                callback_id_ * compiler::target::kWordSize));
+
+  // Put the code object in the reserved slot.
+  __ movl(Address(FPREG, kPcMarkerSlotFromFp * compiler::target::kWordSize),
+          CODE_REG);
+
+  // Load a GC-safe value for the arguments descriptor (unused but tagged).
+  __ xorl(ARGS_DESC_REG, ARGS_DESC_REG);
+
+  // Push a dummy return address which suggests that we are inside of
+  // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+  __ movl(
+      EAX,
+      Address(THR, compiler::target::Thread::invoke_dart_code_stub_offset()));
+  __ pushl(FieldAddress(EAX, compiler::target::Code::entry_point_offset()));
+
+  // Continue with Dart frame setup.
+  FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
 static bool CanBeImmediateIndex(Value* value, intptr_t cid) {
   ConstantInstr* constant = value->definition()->AsConstant();
   if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) {
@@ -1129,18 +1258,19 @@
   switch (class_id_) {
     case kArrayCid:
     case kImmutableArrayCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
+      return kTagged;
     case kOneByteStringCid:
     case kTwoByteStringCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kTypedDataUint16ArrayCid:
     case kExternalOneByteStringCid:
     case kExternalTwoByteStringCid:
-      return kTagged;
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1184,19 +1314,12 @@
       (representation() == kUnboxedInt32x4) ||
       (representation() == kUnboxedFloat64x2)) {
     locs->set_out(0, Location::RequiresFpuRegister());
-  } else if (representation() == kUnboxedUint32) {
-    ASSERT(class_id() == kTypedDataUint32ArrayCid);
-    locs->set_out(0, Location::RequiresRegister());
-  } else if (representation() == kUnboxedInt32) {
-    ASSERT(class_id() == kTypedDataInt32ArrayCid);
-    locs->set_out(0, Location::RequiresRegister());
   } else if (representation() == kUnboxedInt64) {
     ASSERT(class_id() == kTypedDataInt64ArrayCid ||
            class_id() == kTypedDataUint64ArrayCid);
     locs->set_out(0, Location::Pair(Location::RequiresRegister(),
                                     Location::RequiresRegister()));
   } else {
-    ASSERT(representation() == kTagged);
     locs->set_out(0, Location::RequiresRegister());
   }
   return locs;
@@ -1215,14 +1338,19 @@
                 IsExternal(), class_id(), index_scale(), array,
                 Smi::Cast(index.constant()).Value());
 
+  if (index_scale() == 1) {
+    if (index.IsRegister()) {
+      __ SmiUntag(index.reg());
+    } else {
+      ASSERT(index.IsConstant());
+    }
+  }
+
   if ((representation() == kUnboxedDouble) ||
       (representation() == kUnboxedFloat32x4) ||
       (representation() == kUnboxedInt32x4) ||
       (representation() == kUnboxedFloat64x2)) {
     XmmRegister result = locs()->out(0).fpu_reg();
-    if ((index_scale() == 1) && index.IsRegister()) {
-      __ SmiUntag(index.reg());
-    }
     switch (class_id()) {
       case kTypedDataFloat32ArrayCid:
         __ movss(result, element_address);
@@ -1241,85 +1369,80 @@
     return;
   }
 
-  if ((representation() == kUnboxedUint32) ||
-      (representation() == kUnboxedInt32)) {
-    Register result = locs()->out(0).reg();
-    if ((index_scale() == 1) && index.IsRegister()) {
-      __ SmiUntag(index.reg());
-    }
-    switch (class_id()) {
-      case kTypedDataInt32ArrayCid:
-        ASSERT(representation() == kUnboxedInt32);
-        __ movl(result, element_address);
-        break;
-      case kTypedDataUint32ArrayCid:
-        ASSERT(representation() == kUnboxedUint32);
-        __ movl(result, element_address);
-        break;
-      default:
-        UNREACHABLE();
-    }
-    return;
-  }
-
-  if (representation() == kUnboxedInt64) {
-    ASSERT(locs()->out(0).IsPairLocation());
-    PairLocation* result_pair = locs()->out(0).AsPairLocation();
-    Register result_lo = result_pair->At(0).reg();
-    Register result_hi = result_pair->At(1).reg();
-    if ((index_scale() == 1) && index.IsRegister()) {
-      __ SmiUntag(index.reg());
-    }
-    ASSERT(class_id() == kTypedDataInt64ArrayCid ||
-           class_id() == kTypedDataUint64ArrayCid);
-    __ movl(result_lo, element_address);
-    element_address = index.IsRegister()
-                          ? Assembler::ElementAddressForRegIndex(
-                                IsExternal(), class_id(), index_scale(), array,
-                                index.reg(), kWordSize)
-                          : Assembler::ElementAddressForIntIndex(
-                                IsExternal(), class_id(), index_scale(), array,
-                                Smi::Cast(index.constant()).Value(), kWordSize);
-    __ movl(result_hi, element_address);
-    return;
-  }
-
-  ASSERT(representation() == kTagged);
-
-  Register result = locs()->out(0).reg();
-  if ((index_scale() == 1) && index.IsRegister()) {
-    __ SmiUntag(index.reg());
-  }
   switch (class_id()) {
-    case kTypedDataInt8ArrayCid:
+    case kTypedDataInt32ArrayCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedInt32);
+      __ movl(result, element_address);
+      break;
+    }
+    case kTypedDataUint32ArrayCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedUint32);
+      __ movl(result, element_address);
+      break;
+    }
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid: {
+      ASSERT(representation() == kUnboxedInt64);
+      ASSERT(locs()->out(0).IsPairLocation());
+      PairLocation* result_pair = locs()->out(0).AsPairLocation();
+      const Register result_lo = result_pair->At(0).reg();
+      const Register result_hi = result_pair->At(1).reg();
+      ASSERT(class_id() == kTypedDataInt64ArrayCid ||
+             class_id() == kTypedDataUint64ArrayCid);
+      __ movl(result_lo, element_address);
+      element_address =
+          index.IsRegister()
+              ? Assembler::ElementAddressForRegIndex(IsExternal(), class_id(),
+                                                     index_scale(), array,
+                                                     index.reg(), kWordSize)
+              : Assembler::ElementAddressForIntIndex(
+                    IsExternal(), class_id(), index_scale(), array,
+                    Smi::Cast(index.constant()).Value(), kWordSize);
+      __ movl(result_hi, element_address);
+      break;
+    }
+    case kTypedDataInt8ArrayCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedIntPtr);
       ASSERT(index_scale() == 1);
       __ movsxb(result, element_address);
-      __ SmiTag(result);
       break;
+    }
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
     case kOneByteStringCid:
-    case kExternalOneByteStringCid:
+    case kExternalOneByteStringCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedIntPtr);
       ASSERT(index_scale() == 1);
       __ movzxb(result, element_address);
-      __ SmiTag(result);
       break;
-    case kTypedDataInt16ArrayCid:
+    }
+    case kTypedDataInt16ArrayCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedIntPtr);
       __ movsxw(result, element_address);
-      __ SmiTag(result);
       break;
+    }
     case kTypedDataUint16ArrayCid:
     case kTwoByteStringCid:
-    case kExternalTwoByteStringCid:
+    case kExternalTwoByteStringCid: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kUnboxedIntPtr);
       __ movzxw(result, element_address);
-      __ SmiTag(result);
       break;
-    default:
+    }
+    default: {
+      const Register result = locs()->out(0).reg();
+      ASSERT(representation() == kTagged);
       ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
       __ movl(result, element_address);
       break;
+    }
   }
 }
 
@@ -1331,15 +1454,16 @@
   ASSERT(idx == 2);
   switch (class_id_) {
     case kArrayCid:
+      return kTagged;
     case kOneByteStringCid:
     case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
     case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
     case kTypedDataUint16ArrayCid:
-      return kTagged;
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1465,18 +1589,19 @@
     case kTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ArrayCid:
     case kOneByteStringCid:
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       if (locs()->in(2).IsConstant()) {
         const Smi& constant = Smi::Cast(locs()->in(2).constant());
         __ movb(element_address,
                 Immediate(static_cast<int8_t>(constant.Value())));
       } else {
         ASSERT(locs()->in(2).reg() == EAX);
-        __ SmiUntag(EAX);
         __ movb(element_address, AL);
       }
       break;
     case kTypedDataUint8ClampedArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       if (locs()->in(2).IsConstant()) {
         const Smi& constant = Smi::Cast(locs()->in(2).constant());
         intptr_t value = constant.Value();
@@ -1490,7 +1615,6 @@
       } else {
         ASSERT(locs()->in(2).reg() == EAX);
         Label store_value, store_0xff;
-        __ SmiUntag(EAX);
         __ cmpl(EAX, Immediate(0xFF));
         __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump);
         // Clamp to 0x0 or 0xFF respectively.
@@ -1506,8 +1630,8 @@
     }
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid: {
-      Register value = locs()->in(2).reg();
-      __ SmiUntag(value);
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
+      const Register value = locs()->in(2).reg();
       __ movw(element_address, value);
       break;
     }
@@ -1519,8 +1643,8 @@
     case kTypedDataUint64ArrayCid: {
       ASSERT(locs()->in(2).IsPairLocation());
       PairLocation* value_pair = locs()->in(2).AsPairLocation();
-      Register value_lo = value_pair->At(0).reg();
-      Register value_hi = value_pair->At(1).reg();
+      const Register value_lo = value_pair->At(0).reg();
+      const Register value_hi = value_pair->At(1).reg();
       __ movl(element_address, value_lo);
       element_address =
           index.IsRegister()
@@ -1590,13 +1714,6 @@
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
 
   if (field_cid == kDynamicCid) {
-    if (Compiler::IsBackgroundCompilation()) {
-      // Field state changed while compiling.
-      Compiler::AbortBackgroundCompilation(
-          deopt_id(),
-          "GuardFieldClassInstr: field state changed while compiling");
-    }
-    ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
@@ -1619,10 +1736,10 @@
 
   Label ok, fail_label;
 
-  Label* deopt =
-      compiler->is_optimizing()
-          ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField)
-          : NULL;
+  Label* deopt = nullptr;
+  if (compiler->is_optimizing()) {
+    deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField);
+  }
 
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
@@ -1751,13 +1868,6 @@
 
 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   if (field().guarded_list_length() == Field::kNoFixedLength) {
-    if (Compiler::IsBackgroundCompilation()) {
-      // Field state changed while compiling.
-      Compiler::AbortBackgroundCompilation(
-          deopt_id(),
-          "GuardFieldLengthInstr: field state changed while compiling");
-    }
-    ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
@@ -2228,7 +2338,7 @@
   if (compiler->is_optimizing() && num_elements()->BindsToConstant() &&
       num_elements()->BoundConstant().IsSmi()) {
     const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value();
-    if ((length >= 0) && (length <= Array::kMaxElements)) {
+    if (Array::IsValidLength(length)) {
       Label slow_path, done;
       InlineArrayAllocation(compiler, length, &slow_path, &done);
       __ Bind(&slow_path);
@@ -3783,9 +3893,10 @@
   Register value = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
   const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister;
-  Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub(
-                                       GetDeoptId(), ICData::kDeoptUnboxInteger)
-                                 : NULL;
+  Label* deopt = nullptr;
+  if (CanDeoptimize()) {
+    deopt = compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger);
+  }
   Label* out_of_range = !is_truncating() ? deopt : NULL;
 
   const intptr_t lo_offset = Mint::value_offset();
@@ -4473,7 +4584,7 @@
   }
 }
 
-LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary(
+LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
   const intptr_t kNumTemps = 0;
@@ -4487,8 +4598,7 @@
   return summary;
 }
 
-void CaseInsensitiveCompareUC16Instr::EmitNativeCode(
-    FlowGraphCompiler* compiler) {
+void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   // Save ESP. EDI is chosen because it is callee saved so we do not need to
   // back it up before calling into the runtime.
   static const Register kSavedSPReg = EDI;
@@ -4503,7 +4613,7 @@
   // Call the function.
   __ CallRuntime(TargetFunction(), TargetFunction().argument_count());
 
-  // Restore ESP.
+  // Restore ESP and pop the old value off the stack.
   __ movl(ESP, kSavedSPReg);
 }
 
@@ -4719,7 +4829,7 @@
 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register result = locs()->out(0).reg();
   Register value_obj = locs()->in(0).reg();
-  XmmRegister value_double = XMM0;
+  XmmRegister value_double = FpuTMP;
   ASSERT(result == EAX);
   ASSERT(result != value_obj);
   __ movsd(value_double, FieldAddress(value_obj, Double::value_offset()));
@@ -4832,7 +4942,7 @@
                                                                bool opt) const {
   ASSERT((InputCount() == 1) || (InputCount() == 2));
   const intptr_t kNumTemps =
-      (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1;
+      (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 4 : 1;
   LocationSummary* result = new (zone)
       LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall);
   // EDI is chosen because it is callee saved so we do not need to back it
@@ -4847,6 +4957,8 @@
     result->set_temp(1, Location::RegisterLocation(EAX));
     // Temp index 2.
     result->set_temp(2, Location::FpuRegisterLocation(XMM4));
+    // We need to block XMM0 for the floating-point calling convention.
+    result->set_temp(3, Location::FpuRegisterLocation(XMM0));
   }
   result->set_out(0, Location::FpuRegisterLocation(XMM3));
   return result;
@@ -6076,30 +6188,18 @@
 }
 
 void UnboxedWidthExtenderInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  switch (representation_) {
-    case kUnboxedInt32:  // Sign-extend operand.
-      switch (from_width_bytes_) {
-        case 1:
-          __ movsxb(EAX, AL);
-          break;
-        case 2:
-          __ movsxw(EAX, EAX);
-          break;
-        default:
-          UNREACHABLE();
-      }
+  switch (from_representation()) {
+    case kSmallUnboxedInt8:  // Sign extend operand.
+      __ movsxb(EAX, AL);
       break;
-    case kUnboxedUint32:  // Zero-extend operand.
-      switch (from_width_bytes_) {
-        case 1:
-          __ movzxb(EAX, AL);
-          break;
-        case 2:
-          __ movzxw(EAX, EAX);
-          break;
-        default:
-          UNREACHABLE();
-      }
+    case kSmallUnboxedInt16:
+      __ movsxw(EAX, EAX);
+      break;
+    case kSmallUnboxedUint8:  // Zero extend operand.
+      __ movzxb(EAX, AL);
+      break;
+    case kSmallUnboxedUint16:
+      __ movzxw(EAX, EAX);
       break;
     default:
       UNREACHABLE();
@@ -6137,10 +6237,15 @@
 
 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BlockEntryInstr* entry = normal_entry();
-  if (entry == nullptr) entry = osr_entry();
-
-  if (!compiler->CanFallThroughTo(entry)) {
-    __ jmp(compiler->GetJumpLabel(entry));
+  if (entry != nullptr) {
+    if (!compiler->CanFallThroughTo(entry)) {
+      FATAL("Checked function entry must have no offset");
+    }
+  } else {
+    entry = osr_entry();
+    if (!compiler->CanFallThroughTo(entry)) {
+      __ jmp(compiler->GetJumpLabel(entry));
+    }
   }
 }
 
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index 19b2aed..a2f841d 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -192,7 +192,7 @@
     const CidRange& range = targets[i];
     const auto target_info = targets.TargetAt(i);
     const intptr_t count = target_info->count;
-    target ^= target_info->target->raw();
+    target = target_info->target->raw();
     if (i > 0) {
       f->Print(" | ");
     }
@@ -524,12 +524,10 @@
 void FfiCallInstr::PrintOperandsTo(BufferFormatter* f) const {
   f->Print(" pointer=");
   InputAt(TargetAddressIndex())->PrintTo(f);
-  f->Print(" signature=%s",
-           Type::Handle(signature_.SignatureType()).ToCString());
   for (intptr_t i = 0, n = InputCount(); i < n - 1; ++i) {
     f->Print(", ");
     InputAt(i)->PrintTo(f);
-    f->Print(" (at %s) ", arg_locations_[i].ToCString());
+    f->Print(" (@%s)", arg_locations_[i].ToCString());
   }
 }
 
@@ -1001,7 +999,7 @@
 }
 
 void UnboxedWidthExtenderInstr::PrintOperandsTo(BufferFormatter* f) const {
-  f->Print("%" Pd " -> 4 (%s), ", from_width_bytes_,
+  f->Print("%" Pd " -> 4 (%s), ", from_width_bytes(),
            RepresentationToCString(representation()));
   Definition::PrintOperandsTo(f);
 }
@@ -1063,6 +1061,24 @@
   BlockEntryWithInitialDefs::PrintInitialDefinitionsTo(f);
 }
 
+void NativeEntryInstr::PrintTo(BufferFormatter* f) const {
+  f->Print("B%" Pd "[native function entry]:%" Pd, block_id(), GetDeoptId());
+  if (HasParallelMove()) {
+    f->Print("\n");
+    parallel_move()->PrintTo(f);
+  }
+  BlockEntryWithInitialDefs::PrintInitialDefinitionsTo(f);
+}
+
+void NativeReturnInstr::PrintOperandsTo(BufferFormatter* f) const {
+  value()->PrintTo(f);
+}
+
+void NativeParameterInstr::PrintOperandsTo(BufferFormatter* f) const {
+  f->Print("%s as %s", loc_.ToCString(),
+           RepresentationToCString(representation_));
+}
+
 void CatchBlockEntryInstr::PrintTo(BufferFormatter* f) const {
   f->Print("B%" Pd "[target catch try_idx %" Pd " catch_try_idx %" Pd "]",
            block_id(), try_index(), catch_try_index());
diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc
index 4315c29..a219c2a 100644
--- a/runtime/vm/compiler/backend/il_test_helper.cc
+++ b/runtime/vm/compiler/backend/il_test_helper.cc
@@ -28,6 +28,7 @@
   {
     TransitionVMToNative transition(Thread::Current());
     api_lib = TestCase::LoadTestScript(script, resolver, lib_uri);
+    EXPECT_VALID(api_lib);
   }
   auto& lib = Library::Handle();
   lib ^= Api::UnwrapHandle(api_lib);
@@ -177,9 +178,16 @@
   }
 }
 
-bool ILMatcher::TryMatch(std::initializer_list<MatchCode> match_codes) {
+bool ILMatcher::TryMatch(std::initializer_list<MatchCode> match_codes,
+                         MatchOpCode insert_before) {
   std::vector<MatchCode> qcodes = match_codes;
 
+  if (insert_before != kInvalidMatchOpCode) {
+    for (auto pos = qcodes.begin(); pos < qcodes.end(); pos++) {
+      pos = qcodes.insert(pos, insert_before) + 1;
+    }
+  }
+
   if (trace_) {
     OS::PrintErr("ILMatcher: Matching the following graph\n");
     FlowGraphPrinter::PrintGraph("ILMatcher", flow_graph_);
diff --git a/runtime/vm/compiler/backend/il_test_helper.h b/runtime/vm/compiler/backend/il_test_helper.h
index dc6385d..0cad91f 100644
--- a/runtime/vm/compiler/backend/il_test_helper.h
+++ b/runtime/vm/compiler/backend/il_test_helper.h
@@ -114,6 +114,10 @@
 
   // Moves forward until the next match code matches.
   kMoveGlob,
+
+  // Invalid match opcode used as default [insert_before] argument to TryMatch
+  // to signal that no insertions should occur.
+  kInvalidMatchOpCode,
 };
 
 // Match codes used for [ILMatcher], see below.
@@ -179,7 +183,11 @@
   //
   // Returns `true` if the match was successful and cursor has been updated,
   // otherwise returns `false`.
-  bool TryMatch(std::initializer_list<MatchCode> match_codes);
+  //
+  // If [insert_before] is a valid match opcode, then it will be inserted
+  // before each MatchCode in [match_codes] prior to matching.
+  bool TryMatch(std::initializer_list<MatchCode> match_codes,
+                MatchOpCode insert_before = kInvalidMatchOpCode);
 
  private:
   Instruction* MatchInternal(std::vector<MatchCode> match_codes,
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index af182c4..c0d1f41 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -139,6 +139,43 @@
   __ set_constant_pool_allowed(true);
 }
 
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ LeaveDartFrame();
+
+  // Pop dummy return address.
+  __ popq(TMP);
+
+  // Anything besides the return register.
+  const Register vm_tag_reg = RBX, old_exit_frame_reg = RCX;
+
+  __ popq(old_exit_frame_reg);
+
+  // Restore top_resource.
+  __ popq(TMP);
+  __ movq(Address(THR, compiler::target::Thread::top_resource_offset()), TMP);
+
+  __ popq(vm_tag_reg);
+
+  // TransitionGeneratedToNative will reset the exit frame info to
+  // old_exit_frame_reg *before* entering the safepoint.
+  __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg);
+
+  // Restore C++ ABI callee-saved registers.
+  __ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters,
+                  CallingConventions::kCalleeSaveXmmRegisters);
+
+  // Leave the entry frame.
+  __ LeaveFrame();
+
+  // Leave the dummy frame holding the pushed arguments.
+  __ LeaveFrame();
+
+  __ ret();
+
+  // For following blocks.
+  __ set_constant_pool_allowed(true);
+}
+
 static Condition NegateCondition(Condition condition) {
   switch (condition) {
     case EQUAL:
@@ -315,13 +352,13 @@
     }
   } else if (destination.IsDoubleStackSlot()) {
     if (Utils::DoublesBitEqual(Double::Cast(value_).value(), 0.0)) {
-      __ xorps(XMM0, XMM0);
+      __ xorps(FpuTMP, FpuTMP);
     } else {
       ASSERT(tmp != kNoRegister);
       __ LoadObject(tmp, value_);
-      __ movsd(XMM0, FieldAddress(tmp, Double::value_offset()));
+      __ movsd(FpuTMP, FieldAddress(tmp, Double::value_offset()));
     }
-    __ movsd(LocationToStackSlotAddress(destination), XMM0);
+    __ movsd(LocationToStackSlotAddress(destination), FpuTMP);
   } else {
     ASSERT(destination.IsStackSlot());
     if (representation() == kUnboxedInt32 ||
@@ -902,25 +939,13 @@
     __ andq(SPREG, Immediate(~(OS::ActivationFrameAlignment() - 1)));
   }
 
+  FrameRebase rebase(/*old_base=*/FPREG, /*new_base=*/saved_fp,
+                     /*stack_delta=*/0);
   for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
-    Location origin = locs()->in(i);
-    Location target = arg_locations_[i];
-
-    if (target.IsStackSlot()) {
-      if (origin.IsRegister()) {
-        __ movq(LocationToStackSlotAddress(target), origin.reg());
-      } else if (origin.IsFpuRegister()) {
-        __ movq(TMP, origin.fpu_reg());
-        __ movq(LocationToStackSlotAddress(target), TMP);
-      } else if (origin.IsStackSlot() || origin.IsDoubleStackSlot()) {
-        // The base register cannot be SPREG because we've moved it.
-        ASSERT(origin.base_reg() == FPREG);
-        __ movq(TMP, Address(saved_fp, origin.ToStackSlotOffset()));
-        __ movq(LocationToStackSlotAddress(target), TMP);
-      }
-    } else {
-      ASSERT(origin.Equals(target));
-    }
+    const Location origin = rebase.Rebase(locs()->in(i));
+    const Location target = arg_locations_[i];
+    NoTemporaryAllocator temp;
+    compiler->EmitMove(target, rebase.Rebase(origin), &temp);
   }
 
   // We need to copy a dummy return address up into the dummy stack frame so the
@@ -933,7 +958,7 @@
   __ movq(Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), TMP);
 
   // Update information in the thread object and enter a safepoint.
-  __ TransitionGeneratedToNative(target_address);
+  __ TransitionGeneratedToNative(target_address, FPREG);
 
   __ CallCFunction(target_address);
 
@@ -955,6 +980,136 @@
   __ popq(TMP);
 }
 
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+                                    Location loc) const {
+  ASSERT(!loc.IsPairLocation());
+
+  if (loc.HasStackIndex()) return;
+
+  if (loc.IsRegister()) {
+    __ pushq(loc.reg());
+  } else if (loc.IsFpuRegister()) {
+    __ movq(TMP, loc.fpu_reg());
+    __ pushq(TMP);
+  } else {
+    UNREACHABLE();
+  }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (FLAG_precompiled_mode) {
+    UNREACHABLE();
+  }
+
+  __ Bind(compiler->GetJumpLabel(this));
+
+  // Create a dummy frame holding the pushed arguments. This simplifies
+  // NativeReturnInstr::EmitNativeCode.
+  __ EnterFrame(0);
+
+  // Save the argument registers, in reverse order.
+  for (intptr_t i = argument_locations_->length(); i-- > 0;) {
+    SaveArgument(compiler, argument_locations_->At(i));
+  }
+
+  // Enter the entry frame. Push a dummy return address for consistency with
+  // EnterFrame on ARM(64).
+  __ PushImmediate(Immediate(0));
+  __ EnterFrame(0);
+
+  // Save a space for the code object.
+  __ PushImmediate(Immediate(0));
+
+  // InvokeDartCodeStub saves the arguments descriptor here. We don't have one,
+  // but we need to follow the same frame layout for the stack walker.
+  __ PushImmediate(Immediate(0));
+
+  // Save ABI callee-saved registers.
+  __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters,
+                   CallingConventions::kCalleeSaveXmmRegisters);
+
+  // Load the thread object.
+  // TODO(35765): Fix linking issue on AOT.
+  // TOOD(35934): Exclude native callbacks from snapshots.
+  //
+  // Create another frame to align the frame before continuing in "native" code.
+  {
+    __ EnterFrame(0);
+    __ ReserveAlignedFrameSpace(0);
+
+    __ movq(
+        RAX,
+        Immediate(reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback)));
+    __ call(RAX);
+    __ movq(THR, RAX);
+
+    __ LeaveFrame();
+  }
+
+  // Save the current VMTag on the stack.
+  __ movq(RAX, Assembler::VMTagAddress());
+  __ pushq(RAX);
+
+  // Save top resource.
+  __ pushq(Address(THR, compiler::target::Thread::top_resource_offset()));
+  __ movq(Address(THR, compiler::target::Thread::top_resource_offset()),
+          Immediate(0));
+
+  // Save top exit frame info. Stack walker expects it to be here.
+  __ pushq(
+      Address(THR, compiler::target::Thread::top_exit_frame_info_offset()));
+
+  // In debug mode, verify that we've pushed the top exit frame info at the
+  // correct offset from FP.
+  __ EmitEntryFrameVerification();
+
+  // TransitionNativeToGenerated will reset top exit frame info to 0 *after*
+  // leaving the safepoint.
+  __ TransitionNativeToGenerated();
+
+  // Now that the safepoint has ended, we can touch Dart objects without
+  // handles.
+  // Otherwise we'll clobber the argument sent from the caller.
+  COMPILE_ASSERT(RAX != CallingConventions::kArg1Reg);
+  __ movq(CallingConventions::kArg1Reg, Immediate(callback_id_));
+  __ movq(
+      RAX,
+      Address(THR, compiler::target::Thread::verify_callback_entry_offset()));
+  __ call(RAX);
+
+  // Load the code object.
+  __ movq(RAX, Address(THR, compiler::target::Thread::callback_code_offset()));
+  __ movq(RAX, FieldAddress(
+                   RAX, compiler::target::GrowableObjectArray::data_offset()));
+  __ movq(CODE_REG,
+          FieldAddress(RAX, compiler::target::Array::data_offset() +
+                                callback_id_ * compiler::target::kWordSize));
+
+  // Put the code object in the reserved slot.
+  __ movq(Address(FPREG, kPcMarkerSlotFromFp * compiler::target::kWordSize),
+          CODE_REG);
+
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    __ movq(PP, Address(THR,
+                        compiler::target::Thread::global_object_pool_offset()));
+  } else {
+    __ xorq(PP, PP);  // GC-safe value into PP.
+  }
+
+  // Load a GC-safe value for arguments descriptor (unused but tagged).
+  __ xorq(ARGS_DESC_REG, ARGS_DESC_REG);
+
+  // Push a dummy return address which suggests that we are inside of
+  // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+  __ movq(
+      RAX,
+      Address(THR, compiler::target::Thread::invoke_dart_code_stub_offset()));
+  __ pushq(FieldAddress(RAX, compiler::target::Code::entry_point_offset()));
+
+  // Continue with Dart frame setup.
+  FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
 static bool CanBeImmediateIndex(Value* index, intptr_t cid) {
   if (!index->definition()->IsConstant()) return false;
   const Object& constant = index->definition()->AsConstant()->value();
@@ -1183,18 +1338,19 @@
   switch (class_id_) {
     case kArrayCid:
     case kImmutableArrayCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
+      return kTagged;
     case kOneByteStringCid:
     case kTwoByteStringCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kTypedDataUint16ArrayCid:
     case kExternalOneByteStringCid:
     case kExternalTwoByteStringCid:
-      return kTagged;
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1261,14 +1417,18 @@
                 IsExternal(), class_id(), index_scale(), array,
                 Smi::Cast(index.constant()).Value());
 
-  if ((representation() == kUnboxedDouble) ||
-      (representation() == kUnboxedFloat32x4) ||
-      (representation() == kUnboxedInt32x4) ||
-      (representation() == kUnboxedFloat64x2)) {
-    if ((index_scale() == 1) && index.IsRegister()) {
+  if (index_scale() == 1) {
+    if (index.IsRegister()) {
       __ SmiUntag(index.reg());
+    } else {
+      ASSERT(index.IsConstant());
     }
+  }
 
+  if (representation() == kUnboxedDouble ||
+      representation() == kUnboxedFloat32x4 ||
+      representation() == kUnboxedInt32x4 ||
+      representation() == kUnboxedFloat64x2) {
     XmmRegister result = locs()->out(0).fpu_reg();
     if (class_id() == kTypedDataFloat32ArrayCid) {
       // Load single precision float.
@@ -1284,48 +1444,24 @@
     return;
   }
 
-  if ((representation() == kUnboxedUint32) ||
-      (representation() == kUnboxedInt32)) {
-    if ((index_scale() == 1) && index.IsRegister()) {
-      __ SmiUntag(index.reg());
-    }
-    Register result = locs()->out(0).reg();
-    switch (class_id()) {
-      case kTypedDataInt32ArrayCid:
-        ASSERT(representation() == kUnboxedInt32);
-        __ movsxd(result, element_address);
-        break;
-      case kTypedDataUint32ArrayCid:
-        ASSERT(representation() == kUnboxedUint32);
-        __ movl(result, element_address);
-        break;
-      default:
-        UNREACHABLE();
-    }
-    return;
-  }
-
-  if (representation() == kUnboxedInt64) {
-    ASSERT(class_id() == kTypedDataInt64ArrayCid ||
-           class_id() == kTypedDataUint64ArrayCid);
-    if ((index_scale() == 1) && index.IsRegister()) {
-      __ SmiUntag(index.reg());
-    }
-    Register result = locs()->out(0).reg();
-    __ movq(result, element_address);
-    return;
-  }
-
-  ASSERT(representation() == kTagged);
-
-  if ((index_scale() == 1) && index.IsRegister()) {
-    __ SmiUntag(index.reg());
-  }
   Register result = locs()->out(0).reg();
   switch (class_id()) {
+    case kTypedDataInt32ArrayCid:
+      ASSERT(representation() == kUnboxedInt32);
+      __ movsxd(result, element_address);
+      break;
+    case kTypedDataUint32ArrayCid:
+      ASSERT(representation() == kUnboxedUint32);
+      __ movl(result, element_address);
+      break;
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid:
+      ASSERT(representation() == kUnboxedInt64);
+      __ movq(result, element_address);
+      break;
     case kTypedDataInt8ArrayCid:
+      ASSERT(representation() == kUnboxedIntPtr);
       __ movsxb(result, element_address);
-      __ SmiTag(result);
       break;
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
@@ -1333,20 +1469,21 @@
     case kExternalTypedDataUint8ClampedArrayCid:
     case kOneByteStringCid:
     case kExternalOneByteStringCid:
+      ASSERT(representation() == kUnboxedIntPtr);
       __ movzxb(result, element_address);
-      __ SmiTag(result);
       break;
     case kTypedDataInt16ArrayCid:
+      ASSERT(representation() == kUnboxedIntPtr);
       __ movsxw(result, element_address);
-      __ SmiTag(result);
       break;
     case kTypedDataUint16ArrayCid:
     case kTwoByteStringCid:
     case kExternalTwoByteStringCid:
+      ASSERT(representation() == kUnboxedIntPtr);
       __ movzxw(result, element_address);
-      __ SmiTag(result);
       break;
     default:
+      ASSERT(representation() == kTagged);
       ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
       __ movq(result, element_address);
       break;
@@ -1425,15 +1562,16 @@
   ASSERT(idx == 2);
   switch (class_id_) {
     case kArrayCid:
+      return kTagged;
     case kOneByteStringCid:
     case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
     case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
     case kTypedDataUint16ArrayCid:
-      return kTagged;
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1556,22 +1694,23 @@
         __ StoreIntoObjectNoBarrier(array, element_address, value);
       }
       break;
+    case kOneByteStringCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ArrayCid:
-    case kOneByteStringCid:
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       if (locs()->in(2).IsConstant()) {
         const Smi& constant = Smi::Cast(locs()->in(2).constant());
         __ movb(element_address,
                 Immediate(static_cast<int8_t>(constant.Value())));
       } else {
         ASSERT(locs()->in(2).reg() == RAX);
-        __ SmiUntag(RAX);
         __ movb(element_address, RAX);
       }
       break;
     case kTypedDataUint8ClampedArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       if (locs()->in(2).IsConstant()) {
         const Smi& constant = Smi::Cast(locs()->in(2).constant());
         intptr_t value = constant.Value();
@@ -1585,7 +1724,6 @@
       } else {
         ASSERT(locs()->in(2).reg() == RAX);
         Label store_value, store_0xff;
-        __ SmiUntag(RAX);
         __ CompareImmediate(RAX, Immediate(0xFF));
         __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump);
         // Clamp to 0x0 or 0xFF respectively.
@@ -1601,8 +1739,8 @@
     }
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       Register value = locs()->in(2).reg();
-      __ SmiUntag(value);
       __ movw(element_address, value);
       break;
     }
@@ -1672,13 +1810,6 @@
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
 
   if (field_cid == kDynamicCid) {
-    if (Compiler::IsBackgroundCompilation()) {
-      // Field state changed while compiling.
-      Compiler::AbortBackgroundCompilation(
-          deopt_id(),
-          "GuardFieldClassInstr: field state changed while compiling");
-    }
-    ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
@@ -1701,10 +1832,10 @@
 
   Label ok, fail_label;
 
-  Label* deopt =
-      compiler->is_optimizing()
-          ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField)
-          : NULL;
+  Label* deopt = NULL;
+  if (compiler->is_optimizing()) {
+    deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField);
+  }
 
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
@@ -1823,13 +1954,6 @@
 
 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   if (field().guarded_list_length() == Field::kNoFixedLength) {
-    if (Compiler::IsBackgroundCompilation()) {
-      // Field state changed while compiling.
-      Compiler::AbortBackgroundCompilation(
-          deopt_id(),
-          "GuardFieldLengthInstr: field state changed while compiling");
-    }
-    ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
@@ -1909,12 +2033,6 @@
     // Nothing to do: we only need to perform checks for trivially invariant
     // fields. If optimizing Canonicalize pass should have removed
     // this instruction.
-    if (Compiler::IsBackgroundCompilation()) {
-      Compiler::AbortBackgroundCompilation(
-          deopt_id(),
-          "GuardFieldTypeInstr: field state changed during compilation");
-    }
-    ASSERT(!compiler->is_optimizing());
     return;
   }
 
@@ -2331,7 +2449,7 @@
       num_elements()->BindsToConstant() &&
       num_elements()->BoundConstant().IsSmi()) {
     const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value();
-    if ((length >= 0) && (length <= Array::kMaxElements)) {
+    if (Array::IsValidLength(length)) {
       Label slow_path, done;
       InlineArrayAllocation(compiler, length, &slow_path, &done);
       __ Bind(&slow_path);
@@ -4531,7 +4649,7 @@
   }
 }
 
-LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary(
+LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
   const intptr_t kNumTemps = 0;
@@ -4545,8 +4663,7 @@
   return summary;
 }
 
-void CaseInsensitiveCompareUC16Instr::EmitNativeCode(
-    FlowGraphCompiler* compiler) {
+void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   // Save RSP. R13 is chosen because it is callee saved so we do not need to
   // back it up before calling into the runtime.
   static const Register kSavedSPReg = R13;
@@ -4746,7 +4863,7 @@
   Register result = locs()->out(0).reg();
   Register value_obj = locs()->in(0).reg();
   Register temp = locs()->temp(0).reg();
-  XmmRegister value_double = XMM0;
+  XmmRegister value_double = FpuTMP;
   ASSERT(result == RAX);
   ASSERT(result != value_obj);
   ASSERT(result != temp);
@@ -4866,13 +4983,13 @@
 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
                                                                bool opt) const {
   // Calling convention on x64 uses XMM0 and XMM1 to pass the first two
-  // double arguments and XMM0 to return the result. Unfortunately
-  // currently we can't specify these registers because ParallelMoveResolver
-  // assumes that XMM0 is free at all times.
-  // TODO(vegorov): allow XMM0 to be used.
+  // double arguments and XMM0 to return the result.
+  //
+  // TODO(sjindel): allow XMM0 to be used. Requires refactoring InvokeDoublePow
+  // to allow input 1/output register to be equal.
   ASSERT((InputCount() == 1) || (InputCount() == 2));
   const intptr_t kNumTemps =
-      (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1;
+      (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 4 : 1;
   LocationSummary* result = new (zone)
       LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall);
   ASSERT(R13 != CALLEE_SAVED_TEMP);
@@ -4887,6 +5004,8 @@
     result->set_temp(1, Location::RegisterLocation(RAX));
     // Temp index 2.
     result->set_temp(2, Location::FpuRegisterLocation(XMM4));
+    // Block XMM0 for the calling convention.
+    result->set_temp(3, Location::FpuRegisterLocation(XMM0));
   }
   result->set_out(0, Location::FpuRegisterLocation(XMM3));
   return result;
@@ -6229,30 +6348,18 @@
 }
 
 void UnboxedWidthExtenderInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  switch (representation_) {
-    case kUnboxedInt32:  // Sign extend operand.
-      switch (from_width_bytes_) {
-        case 1:
-          __ movsxb(RAX, RAX);
-          break;
-        case 2:
-          __ movsxw(RAX, RAX);
-          break;
-        default:
-          UNREACHABLE();
-      }
+  switch (from_representation()) {
+    case kSmallUnboxedInt8:  // Sign extend operand.
+      __ movsxb(RAX, RAX);
       break;
-    case kUnboxedUint32:  // Zero extend operand.
-      switch (from_width_bytes_) {
-        case 1:
-          __ movzxb(RAX, RAX);
-          break;
-        case 2:
-          __ movzxw(RAX, RAX);
-          break;
-        default:
-          UNREACHABLE();
-      }
+    case kSmallUnboxedInt16:
+      __ movsxw(RAX, RAX);
+      break;
+    case kSmallUnboxedUint8:  // Zero extend operand.
+      __ movzxb(RAX, RAX);
+      break;
+    case kSmallUnboxedUint16:
+      __ movzxw(RAX, RAX);
       break;
     default:
       UNREACHABLE();
@@ -6290,10 +6397,15 @@
 
 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BlockEntryInstr* entry = normal_entry();
-  if (entry == nullptr) entry = osr_entry();
-
-  if (!compiler->CanFallThroughTo(entry)) {
-    __ jmp(compiler->GetJumpLabel(entry));
+  if (entry != nullptr) {
+    if (!compiler->CanFallThroughTo(entry)) {
+      FATAL("Checked function entry must have no offset");
+    }
+  } else {
+    entry = osr_entry();
+    if (!compiler->CanFallThroughTo(entry)) {
+      __ jmp(compiler->GetJumpLabel(entry));
+    }
   }
 }
 
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 8a7550f..5235005 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -101,7 +101,6 @@
 DECLARE_FLAG(int, max_deoptimization_counter_threshold);
 DECLARE_FLAG(bool, print_flow_graph);
 DECLARE_FLAG(bool, print_flow_graph_optimized);
-DECLARE_FLAG(bool, verify_compiler);
 
 // Quick access to the current zone.
 #define Z (zone())
@@ -415,11 +414,11 @@
         if (current->IsPolymorphicInstanceCall()) {
           PolymorphicInstanceCallInstr* instance_call =
               current->AsPolymorphicInstanceCall();
-          target ^= instance_call->targets().FirstTarget().raw();
+          target = instance_call->targets().FirstTarget().raw();
           call = instance_call;
         } else if (current->IsStaticCall()) {
           StaticCallInstr* static_call = current->AsStaticCall();
-          target ^= static_call->function().raw();
+          target = static_call->function().raw();
           call = static_call;
         } else if (current->IsClosureCall()) {
           // TODO(srdjan): Add data for closure calls.
@@ -738,9 +737,6 @@
       }
     }
   }
-
-  // Check that inlining maintains use lists.
-  DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph->VerifyUseLists());
 }
 
 class CallSiteInliner : public ValueObject {
@@ -1062,11 +1058,9 @@
             entry_kind == Code::EntryKind::kUnchecked);
         {
           callee_graph = builder.BuildGraph();
-
 #if defined(DEBUG)
-          FlowGraphChecker(callee_graph).Check();
+          FlowGraphChecker(callee_graph).Check("Builder (callee)");
 #endif
-
           CalleeGraphValidator::Validate(callee_graph);
         }
 #if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
@@ -1149,7 +1143,9 @@
           // Compute SSA on the callee graph, catching bailouts.
           callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(),
                                    param_stubs);
-          DEBUG_ASSERT(callee_graph->VerifyUseLists());
+#if defined(DEBUG)
+          FlowGraphChecker(callee_graph).Check("SSA (callee)");
+#endif
         }
 
         if (FLAG_support_il_printer && trace_inlining() &&
@@ -1170,21 +1166,10 @@
                                                 callee_graph,
                                                 inliner_->speculative_policy_);
 
-            call_specializer.ApplyClassIds();
-            DEBUG_ASSERT(callee_graph->VerifyUseLists());
-
-            FlowGraphTypePropagator::Propagate(callee_graph);
-            DEBUG_ASSERT(callee_graph->VerifyUseLists());
-
-            call_specializer.ApplyICData();
-            DEBUG_ASSERT(callee_graph->VerifyUseLists());
-
-            // Optimize (a << b) & c patterns, merge instructions. Must occur
-            // before 'SelectRepresentations' which inserts conversion nodes.
-            callee_graph->TryOptimizePatterns();
-            DEBUG_ASSERT(callee_graph->VerifyUseLists());
-
-            callee_graph->Canonicalize();
+            CompilerPassState state(Thread::Current(), callee_graph,
+                                    inliner_->speculative_policy_);
+            state.call_specializer = &call_specializer;
+            CompilerPass::RunInliningPipeline(CompilerPass::kAOT, &state);
 #else
             UNREACHABLE();
 #endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&           \
@@ -1193,21 +1178,10 @@
             JitCallSpecializer call_specializer(callee_graph,
                                                 inliner_->speculative_policy_);
 
-            call_specializer.ApplyClassIds();
-            DEBUG_ASSERT(callee_graph->VerifyUseLists());
-
-            FlowGraphTypePropagator::Propagate(callee_graph);
-            DEBUG_ASSERT(callee_graph->VerifyUseLists());
-
-            call_specializer.ApplyICData();
-            DEBUG_ASSERT(callee_graph->VerifyUseLists());
-
-            // Optimize (a << b) & c patterns, merge instructions. Must occur
-            // before 'SelectRepresentations' which inserts conversion nodes.
-            callee_graph->TryOptimizePatterns();
-            DEBUG_ASSERT(callee_graph->VerifyUseLists());
-
-            callee_graph->Canonicalize();
+            CompilerPassState state(Thread::Current(), callee_graph,
+                                    inliner_->speculative_policy_);
+            state.call_specializer = &call_specializer;
+            CompilerPass::RunInliningPipeline(CompilerPass::kJIT, &state);
           }
         }
 
@@ -1521,12 +1495,12 @@
           call->Receiver()->definition()->OriginalDefinition();
       if (AllocateObjectInstr* alloc = receiver->AsAllocateObject()) {
         if (!alloc->closure_function().IsNull()) {
-          target ^= alloc->closure_function().raw();
+          target = alloc->closure_function().raw();
           ASSERT(alloc->cls().IsClosureClass());
         }
       } else if (ConstantInstr* constant = receiver->AsConstant()) {
         if (constant->value().IsClosure()) {
-          target ^= Closure::Cast(constant->value()).function();
+          target = Closure::Cast(constant->value()).function();
         }
       }
 
@@ -1757,6 +1731,11 @@
           BlockEntryInstr* block = old_target->dominated_blocks()[j];
           new_join->AddDominatedBlock(block);
         }
+        // Since we are reusing the same inlined body across multiple cids,
+        // reset the type information on the redefinition of the receiver
+        // in case it was originally given a concrete type.
+        ASSERT(new_join->next()->IsRedefinition());
+        new_join->next()->AsRedefinition()->UpdateType(CompileType::Dynamic());
         // Create a new target with the join as unconditional successor.
         TargetEntryInstr* new_target = new TargetEntryInstr(
             AllocateBlockId(), old_target->try_index(), DeoptId::kNone);
@@ -2412,7 +2391,8 @@
 static bool CanUnboxInt32() {
   // Int32/Uint32 can be unboxed if it fits into a smi or the platform
   // supports unboxed mints.
-  return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedInt64();
+  return (compiler::target::kSmiBits >= 32) ||
+         FlowGraphCompiler::SupportsUnboxedInt64();
 }
 
 // Quick access to the current one.
@@ -2444,8 +2424,9 @@
     *array = elements;
     array_cid = kArrayCid;
   } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
-    LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
-        new (Z) Value(*array), ExternalTypedData::data_offset());
+    LoadUntaggedInstr* elements = new (Z)
+        LoadUntaggedInstr(new (Z) Value(*array),
+                          compiler::target::TypedDataBase::data_field_offset());
     *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
     *array = elements;
   }
@@ -2477,24 +2458,38 @@
   if ((array_cid == kTypedDataInt32ArrayCid) ||
       (array_cid == kTypedDataUint32ArrayCid)) {
     // Deoptimization may be needed if result does not always fit in a Smi.
-    deopt_id = (kSmiBits >= 32) ? DeoptId::kNone : call->deopt_id();
+    deopt_id =
+        (compiler::target::kSmiBits >= 32) ? DeoptId::kNone : call->deopt_id();
   }
 
   // Array load and return.
-  intptr_t index_scale = Instance::ElementSizeFor(array_cid);
+  intptr_t index_scale = compiler::target::Instance::ElementSizeFor(array_cid);
   LoadIndexedInstr* load = new (Z)
       LoadIndexedInstr(new (Z) Value(array), new (Z) Value(index), index_scale,
                        array_cid, kAlignedAccess, deopt_id, call->token_pos());
+
   *last = load;
   cursor = flow_graph->AppendTo(cursor, load,
                                 deopt_id != DeoptId::kNone ? call->env() : NULL,
                                 FlowGraph::kValue);
 
+  const bool value_needs_boxing =
+      array_cid == kTypedDataInt8ArrayCid ||
+      array_cid == kTypedDataInt16ArrayCid ||
+      array_cid == kTypedDataUint8ArrayCid ||
+      array_cid == kTypedDataUint8ClampedArrayCid ||
+      array_cid == kTypedDataUint16ArrayCid ||
+      array_cid == kExternalTypedDataUint8ArrayCid ||
+      array_cid == kExternalTypedDataUint8ClampedArrayCid;
+
   if (array_cid == kTypedDataFloat32ArrayCid) {
     *last = new (Z) FloatToDoubleInstr(new (Z) Value(load), deopt_id);
     flow_graph->AppendTo(cursor, *last,
                          deopt_id != DeoptId::kNone ? call->env() : NULL,
                          FlowGraph::kValue);
+  } else if (value_needs_boxing) {
+    *last = BoxInstr::Create(kUnboxedIntPtr, new Value(load));
+    flow_graph->AppendTo(cursor, *last, nullptr, FlowGraph::kValue);
   }
   *result = (*last)->AsDefinition();
   return true;
@@ -2634,10 +2629,17 @@
           ? kNoStoreBarrier
           : kEmitStoreBarrier;
 
-  // No need to class check stores to Int32 and Uint32 arrays because
-  // we insert unboxing instructions below which include a class check.
-  if ((array_cid != kTypedDataUint32ArrayCid) &&
-      (array_cid != kTypedDataInt32ArrayCid) && value_check != NULL) {
+  const bool value_needs_unboxing =
+      array_cid == kTypedDataInt8ArrayCid ||
+      array_cid == kTypedDataInt16ArrayCid ||
+      array_cid == kTypedDataUint8ArrayCid ||
+      array_cid == kTypedDataUint8ClampedArrayCid ||
+      array_cid == kTypedDataUint16ArrayCid ||
+      array_cid == kExternalTypedDataUint8ArrayCid ||
+      array_cid == kExternalTypedDataUint8ClampedArrayCid ||
+      array_cid == kTypedDataUint32ArrayCid;
+
+  if (value_check != NULL) {
     // No store barrier needed because checked value is a smi, an unboxed mint,
     // an unboxed double, an unboxed Float32x4, or unboxed Int32x4.
     needs_store_barrier = kNoStoreBarrier;
@@ -2652,21 +2654,36 @@
         DoubleToFloatInstr(new (Z) Value(stored_value), call->deopt_id());
     cursor =
         flow_graph->AppendTo(cursor, stored_value, NULL, FlowGraph::kValue);
-  } else if (array_cid == kTypedDataInt32ArrayCid) {
-    stored_value =
-        new (Z) UnboxInt32Instr(UnboxInt32Instr::kTruncate,
-                                new (Z) Value(stored_value), call->deopt_id());
-    cursor = flow_graph->AppendTo(cursor, stored_value, call->env(),
-                                  FlowGraph::kValue);
-  } else if (array_cid == kTypedDataUint32ArrayCid) {
-    stored_value =
-        new (Z) UnboxUint32Instr(new (Z) Value(stored_value), call->deopt_id());
-    ASSERT(stored_value->AsUnboxInteger()->is_truncating());
+  } else if (value_needs_unboxing) {
+    Representation representation = kNoRepresentation;
+    switch (array_cid) {
+      case kUnboxedInt32:
+        representation = kUnboxedInt32;
+        break;
+      case kTypedDataUint32ArrayCid:
+        representation = kUnboxedUint32;
+        break;
+      case kTypedDataInt8ArrayCid:
+      case kTypedDataInt16ArrayCid:
+      case kTypedDataUint8ArrayCid:
+      case kTypedDataUint8ClampedArrayCid:
+      case kTypedDataUint16ArrayCid:
+      case kExternalTypedDataUint8ArrayCid:
+      case kExternalTypedDataUint8ClampedArrayCid:
+        representation = kUnboxedIntPtr;
+        break;
+      default:
+        UNREACHABLE();
+    }
+    stored_value = UnboxInstr::Create(
+        representation, new (Z) Value(stored_value), call->deopt_id());
+    stored_value->AsUnboxInteger()->mark_truncating();
     cursor = flow_graph->AppendTo(cursor, stored_value, call->env(),
                                   FlowGraph::kValue);
   }
 
-  const intptr_t index_scale = Instance::ElementSizeFor(array_cid);
+  const intptr_t index_scale =
+      compiler::target::Instance::ElementSizeFor(array_cid);
   *last = new (Z) StoreIndexedInstr(
       new (Z) Value(array), new (Z) Value(index), new (Z) Value(stored_value),
       needs_store_barrier, index_scale, array_cid, kAlignedAccess,
@@ -2822,7 +2839,7 @@
       call->token_pos());
   *cursor = flow_graph->AppendTo(*cursor, length, NULL, FlowGraph::kValue);
 
-  intptr_t element_size = Instance::ElementSizeFor(array_cid);
+  intptr_t element_size = compiler::target::Instance::ElementSizeFor(array_cid);
   ConstantInstr* bytes_per_element =
       flow_graph->GetConstant(Smi::Handle(Z, Smi::New(element_size)));
   BinarySmiOpInstr* len_in_bytes = new (Z)
@@ -2833,7 +2850,8 @@
 
   // adjusted_length = len_in_bytes - (element_size - 1).
   Definition* adjusted_length = len_in_bytes;
-  intptr_t adjustment = Instance::ElementSizeFor(view_cid) - 1;
+  intptr_t adjustment =
+      compiler::target::Instance::ElementSizeFor(view_cid) - 1;
   if (adjustment > 0) {
     ConstantInstr* length_adjustment =
         flow_graph->GetConstant(Smi::Handle(Z, Smi::New(adjustment)));
@@ -2874,8 +2892,9 @@
   if (array_cid == kDynamicCid ||
       RawObject::IsExternalTypedDataClassId(array_cid)) {
     // Internal or External typed data: load untagged.
-    auto elements = new (Z) LoadUntaggedInstr(
-        new (Z) Value(*array), TypedDataBase::data_field_offset());
+    auto elements = new (Z)
+        LoadUntaggedInstr(new (Z) Value(*array),
+                          compiler::target::TypedDataBase::data_field_offset());
     *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
     *array = elements;
   } else {
@@ -3032,7 +3051,7 @@
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
       // On 64-bit platforms assume that stored value is always a smi.
-      if (kSmiBits >= 32) {
+      if (compiler::target::kSmiBits >= 32) {
         value_check = Cids::CreateMonomorphic(Z, kSmiCid);
       }
       break;
@@ -3109,24 +3128,50 @@
     }
   }
 
-  // Handle conversions and special unboxing.
-  if (view_cid == kTypedDataFloat32ArrayCid) {
-    stored_value = new (Z)
-        DoubleToFloatInstr(new (Z) Value(stored_value), call->deopt_id());
-    cursor =
-        flow_graph->AppendTo(cursor, stored_value, nullptr, FlowGraph::kValue);
-  } else if (view_cid == kTypedDataInt32ArrayCid) {
-    stored_value =
-        new (Z) UnboxInt32Instr(UnboxInt32Instr::kTruncate,
-                                new (Z) Value(stored_value), call->deopt_id());
-    cursor = flow_graph->AppendTo(cursor, stored_value, call->env(),
-                                  FlowGraph::kValue);
-  } else if (view_cid == kTypedDataUint32ArrayCid) {
-    stored_value =
-        new (Z) UnboxUint32Instr(new (Z) Value(stored_value), call->deopt_id());
-    ASSERT(stored_value->AsUnboxInteger()->is_truncating());
-    cursor = flow_graph->AppendTo(cursor, stored_value, call->env(),
-                                  FlowGraph::kValue);
+  // Handle conversions and special unboxing (to ensure unboxing instructions
+  // are marked as truncating, since [SelectRepresentations] does not take care
+  // of that).
+  switch (view_cid) {
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid: {
+      stored_value =
+          UnboxInstr::Create(kUnboxedIntPtr, new (Z) Value(stored_value),
+                             call->deopt_id(), Instruction::kNotSpeculative);
+      stored_value->AsUnboxInteger()->mark_truncating();
+      cursor = flow_graph->AppendTo(cursor, stored_value, call->env(),
+                                    FlowGraph::kValue);
+      break;
+    }
+    case kTypedDataFloat32ArrayCid: {
+      stored_value = new (Z)
+          DoubleToFloatInstr(new (Z) Value(stored_value), call->deopt_id());
+      cursor = flow_graph->AppendTo(cursor, stored_value, nullptr,
+                                    FlowGraph::kValue);
+      break;
+    }
+    case kTypedDataInt32ArrayCid: {
+      stored_value = new (Z)
+          UnboxInt32Instr(UnboxInt32Instr::kTruncate,
+                          new (Z) Value(stored_value), call->deopt_id());
+      cursor = flow_graph->AppendTo(cursor, stored_value, call->env(),
+                                    FlowGraph::kValue);
+      break;
+    }
+    case kTypedDataUint32ArrayCid: {
+      stored_value = new (Z)
+          UnboxUint32Instr(new (Z) Value(stored_value), call->deopt_id());
+      ASSERT(stored_value->AsUnboxInteger()->is_truncating());
+      cursor = flow_graph->AppendTo(cursor, stored_value, call->env(),
+                                    FlowGraph::kValue);
+      break;
+    }
+    default:
+      break;
   }
 
   // Generates a template for the store, either a dynamic conditional
@@ -3170,22 +3215,28 @@
 
   // For external strings: Load backing store.
   if (cid == kExternalOneByteStringCid) {
-    str = new LoadUntaggedInstr(new Value(str),
-                                ExternalOneByteString::external_data_offset());
+    str = new LoadUntaggedInstr(
+        new Value(str),
+        compiler::target::ExternalOneByteString::external_data_offset());
     cursor = flow_graph->AppendTo(cursor, str, NULL, FlowGraph::kValue);
   } else if (cid == kExternalTwoByteStringCid) {
-    str = new LoadUntaggedInstr(new Value(str),
-                                ExternalTwoByteString::external_data_offset());
+    str = new LoadUntaggedInstr(
+        new Value(str),
+        compiler::target::ExternalTwoByteString::external_data_offset());
     cursor = flow_graph->AppendTo(cursor, str, NULL, FlowGraph::kValue);
   }
 
-  LoadIndexedInstr* load_indexed = new (Z) LoadIndexedInstr(
-      new (Z) Value(str), new (Z) Value(index), Instance::ElementSizeFor(cid),
-      cid, kAlignedAccess, DeoptId::kNone, call->token_pos());
-
+  LoadIndexedInstr* load_indexed = new (Z)
+      LoadIndexedInstr(new (Z) Value(str), new (Z) Value(index),
+                       compiler::target::Instance::ElementSizeFor(cid), cid,
+                       kAlignedAccess, DeoptId::kNone, call->token_pos());
   cursor = flow_graph->AppendTo(cursor, load_indexed, NULL, FlowGraph::kValue);
-  ASSERT(cursor == load_indexed);
-  return load_indexed;
+
+  auto box = BoxInstr::Create(kUnboxedIntPtr, new Value(load_indexed));
+  cursor = flow_graph->AppendTo(cursor, box, nullptr, FlowGraph::kValue);
+
+  ASSERT(box == cursor);
+  return box;
 }
 
 static bool InlineStringBaseCharAt(FlowGraph* flow_graph,
@@ -3285,10 +3336,10 @@
     // Insert receiver class or null check if needed.
     switch (check) {
       case FlowGraph::ToCheck::kCheckCid: {
-        Instruction* check_class =
-            flow_graph->CreateCheckClass(call->Receiver()->definition(),
-                                         *Cids::Create(Z, *call->ic_data(), 0),
-                                         call->deopt_id(), call->token_pos());
+        Instruction* check_class = flow_graph->CreateCheckClass(
+            call->Receiver()->definition(),
+            *Cids::CreateAndExpand(Z, *call->ic_data(), 0), call->deopt_id(),
+            call->token_pos());
         flow_graph->InsertBefore(call, check_class, call->env(),
                                  FlowGraph::kEffect);
         break;
@@ -4065,7 +4116,7 @@
       Value* num_elements = new (Z) Value(call->ArgumentAt(1));
       intptr_t length = 0;
       if (IsSmiValue(num_elements, &length)) {
-        if (length >= 0 && length <= Array::kMaxElements) {
+        if (Array::IsValidLength(length)) {
           Value* type = new (Z) Value(call->ArgumentAt(0));
           *entry = new (Z)
               FunctionEntryInstr(graph_entry, flow_graph->allocate_block_id(),
@@ -4107,12 +4158,16 @@
             FunctionEntryInstr(graph_entry, flow_graph->allocate_block_id(),
                                call->GetBlock()->try_index(), DeoptId::kNone);
         (*entry)->InheritDeoptTarget(Z, call);
-        *last = new (Z) ConstantInstr(type);
+        ConstantInstr* ctype = flow_graph->GetConstant(type);
+        // Create a synthetic (re)definition for return to flag insertion.
+        // TODO(ajcbik): avoid this mechanism altogether
+        RedefinitionInstr* redef =
+            new (Z) RedefinitionInstr(new (Z) Value(ctype));
         flow_graph->AppendTo(
-            *entry, *last,
+            *entry, redef,
             call->deopt_id() != DeoptId::kNone ? call->env() : NULL,
             FlowGraph::kValue);
-        *result = (*last)->AsDefinition();
+        *last = *result = redef;
         return true;
       }
       return false;
@@ -4128,16 +4183,25 @@
       Definition* str = call->ArgumentAt(0);
       Definition* index = call->ArgumentAt(1);
       Definition* value = call->ArgumentAt(2);
+
+      auto env = call->deopt_id() != DeoptId::kNone ? call->env() : nullptr;
+
+      // Insert explicit unboxing instructions with truncation to avoid relying
+      // on [SelectRepresentations] which doesn't mark them as truncating.
+      value =
+          UnboxInstr::Create(kUnboxedIntPtr, new (Z) Value(value),
+                             call->deopt_id(), Instruction::kNotSpeculative);
+      value->AsUnboxInteger()->mark_truncating();
+      flow_graph->AppendTo(*entry, value, env, FlowGraph::kValue);
+
       *last =
           new (Z) StoreIndexedInstr(new (Z) Value(str), new (Z) Value(index),
                                     new (Z) Value(value), kNoStoreBarrier,
                                     1,  // Index scale
                                     kOneByteStringCid, kAlignedAccess,
                                     call->deopt_id(), call->token_pos());
-      flow_graph->AppendTo(
-          *entry, *last,
-          call->deopt_id() != DeoptId::kNone ? call->env() : NULL,
-          FlowGraph::kEffect);
+      flow_graph->AppendTo(value, *last, env, FlowGraph::kEffect);
+
       // We need a return value to replace uses of the original definition.
       // The final instruction is a use of 'void operator[]=()', so we use null.
       *result = flow_graph->constant_null();
diff --git a/runtime/vm/compiler/backend/inliner_test.cc b/runtime/vm/compiler/backend/inliner_test.cc
new file mode 100644
index 0000000..75609a4
--- /dev/null
+++ b/runtime/vm/compiler/backend/inliner_test.cc
@@ -0,0 +1,137 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/compiler/backend/inliner.h"
+
+#include "vm/compiler/backend/il.h"
+#include "vm/compiler/backend/il_printer.h"
+#include "vm/compiler/backend/il_test_helper.h"
+#include "vm/compiler/compiler_pass.h"
+#include "vm/object.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+// Test that the redefinition for an inlined polymorphic function used with
+// multiple receiver cids does not have a concrete type.
+ISOLATE_UNIT_TEST_CASE(Inliner_PolyInliningRedefinition) {
+  const char* kScript = R"(
+    abstract class A {
+      String toInline() { return "A"; }
+    }
+
+    class B extends A {}
+    class C extends A {
+      @override
+      String toInline() { return "C";}
+    }
+    class D extends A {}
+
+    testInlining(A arg) {
+      arg.toInline();
+    }
+
+    main() {
+      for (var i = 0; i < 10; i++) {
+        testInlining(B());
+        testInlining(C());
+        testInlining(D());
+      }
+    }
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& function =
+      Function::Handle(GetFunction(root_library, "testInlining"));
+
+  Invoke(root_library, "main");
+
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({
+      CompilerPass::kComputeSSA,
+      CompilerPass::kApplyICData,
+      CompilerPass::kTryOptimizePatterns,
+      CompilerPass::kSetOuterInliningId,
+      CompilerPass::kTypePropagation,
+      CompilerPass::kApplyClassIds,
+      CompilerPass::kInlining,
+  });
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  EXPECT(entry->initial_definitions()->length() == 1);
+  EXPECT(entry->initial_definitions()->At(0)->IsParameter());
+  ParameterInstr* param = entry->initial_definitions()->At(0)->AsParameter();
+
+  // First we find the start of the prelude for the inlined instruction,
+  // and also keep a reference to the LoadClassId instruction for later.
+  LoadClassIdInstr* lcid = nullptr;
+  BranchInstr* prelude = nullptr;
+
+  ILMatcher cursor(flow_graph, entry);
+  RELEASE_ASSERT(cursor.TryMatch(
+      {
+          {kMatchLoadClassId, &lcid},
+          {kMatchBranch, &prelude},
+      },
+      /*insert_before=*/kMoveGlob));
+
+  const Class& cls = Class::Handle(
+      root_library.LookupLocalClass(String::Handle(Symbols::New(thread, "B"))));
+
+  Definition* cid_B = flow_graph->GetConstant(Smi::Handle(Smi::New(cls.id())));
+  Instruction* current = prelude;
+
+  // We walk false branches until we either reach a branch instruction that uses
+  // B's cid for comparison to the value returned from the LCID instruction
+  // above, or a default case if there was no branch instruction for B's cid.
+  while (true) {
+    EXPECT(current->IsBranch());
+    const ComparisonInstr* check = current->AsBranch()->comparison();
+    EXPECT(check->left()->definition() == lcid);
+    if (check->right()->definition() == cid_B) break;
+    current = current->SuccessorAt(1);
+    // By following false paths, we should be walking a series of blocks that
+    // looks like:
+    // B#[target]:#
+    //   Branch if <check on class ID>
+    // If we end up not finding a branch, then we're in a default case
+    // that contains a class check.
+    current = current->next();
+    if (!current->IsBranch()) {
+      break;
+    }
+  }
+  // If we found a branch that checks against the class ID, we follow the true
+  // branch to a block that contains only a goto to the desired join block.
+  if (current->IsBranch()) {
+    current = current->SuccessorAt(0);
+  } else {
+    // We're in the default case, which will check the class ID to make sure
+    // it's the one expected for the fallthrough. That check will be followed
+    // by a goto to the desired join block.
+    EXPECT(current->IsRedefinition());
+    const auto redef = current->AsRedefinition();
+    EXPECT(redef->value()->definition() == lcid);
+    current = current->next();
+    EXPECT(current->IsCheckClassId());
+    EXPECT(current->AsCheckClassId()->value()->definition() == redef);
+  }
+  current = current->next();
+  EXPECT(current->IsGoto());
+  current = current->AsGoto()->successor();
+  // Now we should be at a block that starts like:
+  // BY[join]:# pred(...)
+  //    vW <- Redefinition(vV)
+  //
+  // where vV is a reference to the function parameter (the receiver of
+  // the inlined function).
+  current = current->next();
+  EXPECT(current->IsRedefinition());
+  EXPECT(current->AsRedefinition()->value()->definition() == param);
+  EXPECT(current->AsRedefinition()->Type()->ToCid() == kDynamicCid);
+}
+
+}  // namespace dart
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index 4f5473c..b5fea9c 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -824,25 +824,6 @@
   }
 }
 
-static Location::Kind RegisterKindForResult(Instruction* instr) {
-  const Representation rep = instr->representation();
-#if !defined(TARGET_ARCH_DBC)
-  if ((rep == kUnboxedFloat) || (rep == kUnboxedDouble) ||
-      (rep == kUnboxedFloat32x4) || (rep == kUnboxedInt32x4) ||
-      (rep == kUnboxedFloat64x2)) {
-    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));
-  return Location::kRegister;
-#endif
-}
-
 //
 // When describing shape of live ranges in comments below we are going to use
 // the following notation:
@@ -991,11 +972,11 @@
     // All phi resolution moves are connected. Phi's live range is
     // complete.
     AssignSafepoints(phi, range);
-    CompleteRange(range, RegisterKindForResult(phi));
+    CompleteRange(range, phi->RegisterKindForResult());
     if (is_pair_phi) {
       LiveRange* second_range = GetLiveRange(ToSecondPairVreg(vreg));
       AssignSafepoints(phi, second_range);
-      CompleteRange(second_range, RegisterKindForResult(phi));
+      CompleteRange(second_range, phi->RegisterKindForResult());
     }
 
     move_idx += is_pair_phi ? 2 : 1;
@@ -1303,7 +1284,7 @@
   }
 
   AssignSafepoints(def, range);
-  CompleteRange(range, RegisterKindForResult(def));
+  CompleteRange(range, def->RegisterKindForResult());
 }
 
 // Create and update live ranges corresponding to instruction's inputs,
diff --git a/runtime/vm/compiler/backend/linearscan.h b/runtime/vm/compiler/backend/linearscan.h
index 7c1a93e..9655f32 100644
--- a/runtime/vm/compiler/backend/linearscan.h
+++ b/runtime/vm/compiler/backend/linearscan.h
@@ -52,7 +52,8 @@
 class FlowGraphAllocator : public ValueObject {
  public:
   // Number of stack slots needed for a fpu register spill slot.
-  static const intptr_t kDoubleSpillFactor = kDoubleSize / kWordSize;
+  static const intptr_t kDoubleSpillFactor =
+      kDoubleSize / compiler::target::kWordSize;
 
   explicit FlowGraphAllocator(const FlowGraph& flow_graph,
                               bool intrinsic_mode = false);
@@ -525,16 +526,16 @@
   Location spill_slot() const { return spill_slot_; }
 
   bool HasOnlyUnconstrainedUsesInLoop(intptr_t loop_id) const {
-    if (loop_id < kBitsPerWord) {
-      const intptr_t mask = static_cast<intptr_t>(1) << loop_id;
+    if (loop_id < kMaxLoops) {
+      const uint64_t mask = static_cast<uint64_t>(1) << loop_id;
       return (has_only_any_uses_in_loops_ & mask) != 0;
     }
     return false;
   }
 
   void MarkHasOnlyUnconstrainedUsesInLoop(intptr_t loop_id) {
-    if (loop_id < kBitsPerWord) {
-      has_only_any_uses_in_loops_ |= static_cast<intptr_t>(1) << loop_id;
+    if (loop_id < kMaxLoops) {
+      has_only_any_uses_in_loops_ |= static_cast<uint64_t>(1) << loop_id;
     }
   }
 
@@ -576,7 +577,8 @@
 
   LiveRange* next_sibling_;
 
-  intptr_t has_only_any_uses_in_loops_;
+  static constexpr intptr_t kMaxLoops = sizeof(uint64_t) * kBitsPerByte;
+  uint64_t has_only_any_uses_in_loops_;
   bool is_loop_phi_;
 
   AllocationFinger finger_;
diff --git a/runtime/vm/compiler/backend/locations.cc b/runtime/vm/compiler/backend/locations.cc
index f705a15..34f8223 100644
--- a/runtime/vm/compiler/backend/locations.cc
+++ b/runtime/vm/compiler/backend/locations.cc
@@ -145,7 +145,7 @@
 
 template <class Register, class FpuRegister>
 intptr_t TemplateLocation<Register, FpuRegister>::ToStackSlotOffset() const {
-  return stack_index() * kWordSize;
+  return stack_index() * compiler::target::kWordSize;
 }
 
 template <class Register, class FpuRegister>
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index 513d61b..9147a6a 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -10,6 +10,7 @@
 #include "vm/bitmap.h"
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/constants.h"
+#include "vm/cpu.h"
 
 namespace dart {
 
@@ -37,6 +38,16 @@
   kNumRepresentations
 };
 
+// The representation of 8 and 16 bit integers in 32 bit. SmallRepresentation
+// tracks the real representation of these small integers.
+enum SmallRepresentation {
+  kNoSmallRepresentation,
+  kSmallUnboxedInt8,
+  kSmallUnboxedUint8,
+  kSmallUnboxedInt16,
+  kSmallUnboxedUint16,
+};
+
 // 'UnboxedFfiIntPtr' should be able to hold a pointer of the target word-size.
 // On a 32-bit platform, it's an unsigned 32-bit int because it should be
 // zero-extended to 64-bits, not sign-extended (pointers are inherently
@@ -51,6 +62,8 @@
 static constexpr Representation kUnboxedIntPtr =
     compiler::target::kWordSize == 4 ? kUnboxedInt32 : kUnboxedInt64;
 
+class FrameRebase;
+
 // Location objects are used to connect register allocator and code generator.
 // Instruction templates used by code generator have a corresponding
 // LocationSummary object which specifies expected location for every input
@@ -207,6 +220,11 @@
   TemplatePairLocation<TemplateLocation<Register, FpuRegister>>*
   AsPairLocation() const;
 
+  // For pair locations, returns the ith component (for i in {0, 1}).
+  TemplateLocation<Register, FpuRegister> Component(intptr_t i) const {
+    return AsPairLocation()->At(i);
+  }
+
   // Unallocated locations.
   enum Policy {
     kAny,
@@ -389,14 +407,31 @@
 
   TemplateLocation Copy() const;
 
+  static TemplateLocation read(uword value) { return TemplateLocation(value); }
+  uword write() const { return value_; }
+
  private:
   explicit TemplateLocation(uword value) : value_(value) {}
 
+  void set_stack_index(intptr_t index) {
+    ASSERT(HasStackIndex());
+    value_ = PayloadField::update(
+        StackIndexField::update(EncodeStackIndex(index), payload()), value_);
+  }
+
+  void set_base_reg(Register reg) {
+    ASSERT(HasStackIndex());
+    value_ = PayloadField::update(StackSlotBaseField::update(reg, payload()),
+                                  value_);
+  }
+
   TemplateLocation(Kind kind, uword payload)
       : value_(KindField::encode(kind) | PayloadField::encode(payload)) {}
 
   uword payload() const { return PayloadField::decode(value_); }
 
+  friend class FrameRebase;
+
   class KindField : public BitField<uword, Kind, kKindBitsPos, kKindBitsSize> {
   };
   class PayloadField
@@ -562,9 +597,15 @@
       Add(Location::RegisterLocation(reg));
     }
 
-    for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) {
-      Add(Location::FpuRegisterLocation(static_cast<FpuRegister>(i)));
+#if defined(TARGET_ARCH_ARM)
+    if (TargetCPUFeatures::vfp_supported()) {
+#endif
+      for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) {
+        Add(Location::FpuRegisterLocation(static_cast<FpuRegister>(i)));
+      }
+#if defined(TARGET_ARCH_ARM)
     }
+#endif
   }
 
   void Add(Location loc, Representation rep = kTagged) {
@@ -788,6 +829,36 @@
 #endif
 };
 
+// Describes a change of stack frame where the stack or base register or stack
+// offset may change. This class allows easily rebasing stack locations across
+// frame manipulations.
+//
+// If the stack offset register matches 'old_base', it is changed to 'new_base'
+// and 'stack_delta' (# of slots) is applied.
+class FrameRebase : public ValueObject {
+ public:
+  FrameRebase(Register old_base, Register new_base, intptr_t stack_delta)
+      : old_base_(old_base), new_base_(new_base), stack_delta_(stack_delta) {}
+
+  Location Rebase(Location loc) {
+    if (loc.IsPairLocation()) {
+      return Location::Pair(Rebase(loc.Component(0)), Rebase(loc.Component(1)));
+    }
+    if (!loc.HasStackIndex() || loc.base_reg() != old_base_) {
+      return loc;
+    }
+
+    loc.set_base_reg(new_base_);
+    loc.set_stack_index(loc.stack_index() + stack_delta_);
+    return loc;
+  }
+
+ private:
+  Register old_base_;
+  Register new_base_;
+  intptr_t stack_delta_;
+};
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_COMPILER_BACKEND_LOCATIONS_H_
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index c2bd37b..28f3b2d 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -816,8 +816,8 @@
     // AOT should only see non-deopting GenericCheckBound.
     ASSERT(!FLAG_precompiled_mode);
 
-    ConstantInstr* max_smi =
-        flow_graph_->GetConstant(Smi::Handle(Smi::New(Smi::kMaxValue)));
+    ConstantInstr* max_smi = flow_graph_->GetConstant(
+        Smi::Handle(Smi::New(compiler::target::kSmiMax)));
     for (intptr_t i = 0; i < non_positive_symbols.length(); i++) {
       CheckArrayBoundInstr* precondition = new CheckArrayBoundInstr(
           new Value(max_smi), new Value(non_positive_symbols[i]),
@@ -1075,7 +1075,7 @@
 
         c = left_const + right_const;
         if (Utils::WillAddOverflow(left_const, right_const) ||
-            !Smi::IsValid(c)) {
+            !compiler::target::IsSmi(c)) {
           return false;  // Abort.
         }
 
@@ -1120,7 +1120,7 @@
 
         c = (left_const - right_const);
         if (Utils::WillSubOverflow(left_const, right_const) ||
-            !Smi::IsValid(c)) {
+            !compiler::target::IsSmi(c)) {
           return false;  // Abort.
         }
 
@@ -1180,7 +1180,7 @@
       }
     } else if ((*defn)->IsConstant()) {
       ConstantInstr* constant_defn = (*defn)->AsConstant();
-      if ((constant != NULL) && constant_defn->value().IsSmi()) {
+      if ((constant != NULL) && constant_defn->IsSmi()) {
         *defn = NULL;
         *constant = Smi::Cast(constant_defn->value()).Value();
       }
@@ -1195,7 +1195,7 @@
                               Definition* defn) {
     if (defn->IsConstant()) {
       const Object& value = defn->AsConstant()->value();
-      return value.IsSmi() && (Smi::Cast(value).Value() >= 0);
+      return compiler::target::IsSmi(value) && (Smi::Cast(value).Value() >= 0);
     } else if (defn->HasSSATemp()) {
       if (!RangeUtils::IsPositive(defn->range())) {
         symbols->Add(defn);
@@ -1679,12 +1679,11 @@
                 replacement->ToCString());
     }
     defn->ReplaceWith(replacement, NULL);
-    ASSERT(flow_graph_->VerifyUseLists());
   }
 }
 
 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, int64_t offs) {
-  if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) {
+  if (defn->IsConstant() && defn->AsConstant()->IsSmi()) {
     return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs);
   }
   ASSERT(IsValidOffsetForSymbolicRangeBoundary(offs));
@@ -2290,7 +2289,8 @@
 
   const int64_t left_max = ConstantAbsMax(left_range);
   const int64_t right_max = ConstantAbsMax(right_range);
-  if ((left_max <= -kSmiMin) && (right_max <= -kSmiMin) &&
+  if ((left_max <= -compiler::target::kSmiMin) &&
+      (right_max <= -compiler::target::kSmiMin) &&
       ((left_max == 0) || (right_max <= kMaxInt64 / left_max))) {
     // Product of left and right max values stays in 64 bit range.
     const int64_t mul_max = left_max * right_max;
@@ -2626,8 +2626,9 @@
   switch (slot().kind()) {
     case Slot::Kind::kArray_length:
     case Slot::Kind::kGrowableObjectArray_length:
-      *range = Range(RangeBoundary::FromConstant(0),
-                     RangeBoundary::FromConstant(Array::kMaxElements));
+      *range = Range(
+          RangeBoundary::FromConstant(0),
+          RangeBoundary::FromConstant(compiler::target::Array::kMaxElements));
       break;
 
     case Slot::Kind::kTypedDataBase_length:
@@ -2636,8 +2637,9 @@
       break;
 
     case Slot::Kind::kString_length:
-      *range = Range(RangeBoundary::FromConstant(0),
-                     RangeBoundary::FromConstant(String::kMaxElements));
+      *range = Range(
+          RangeBoundary::FromConstant(0),
+          RangeBoundary::FromConstant(compiler::target::String::kMaxElements));
       break;
 
     case Slot::Kind::kDartField:
@@ -2930,7 +2932,8 @@
 
   // Range of the index is unknown can't decide if the check is redundant.
   if (index_range == NULL) {
-    if (!(index()->BindsToConstant() && index()->BoundConstant().IsSmi())) {
+    if (!(index()->BindsToConstant() &&
+          compiler::target::IsSmi(index()->BoundConstant()))) {
       return false;
     }
 
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index a16ea2b..e34d230 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -64,7 +64,8 @@
   static RangeBoundary FromDefinition(Definition* defn, int64_t offs = 0);
 
   static bool IsValidOffsetForSymbolicRangeBoundary(int64_t offset) {
-    if ((offset > (kMaxInt64 - kSmiMax)) || (offset < (kMinInt64 - kSmiMin))) {
+    if ((offset > (kMaxInt64 - compiler::target::kSmiMax)) ||
+        (offset < (kMinInt64 - compiler::target::kSmiMin))) {
       // Avoid creating symbolic range boundaries which can wrap around.
       return false;
     }
@@ -72,16 +73,20 @@
   }
 
   // Construct a RangeBoundary for the constant MinSmi value.
-  static RangeBoundary MinSmi() { return FromConstant(Smi::kMinValue); }
+  static RangeBoundary MinSmi() {
+    return FromConstant(compiler::target::kSmiMin);
+  }
 
   // Construct a RangeBoundary for the constant MaxSmi value.
-  static RangeBoundary MaxSmi() { return FromConstant(Smi::kMaxValue); }
+  static RangeBoundary MaxSmi() {
+    return FromConstant(compiler::target::kSmiMax);
+  }
 
   // Construct a RangeBoundary for the constant kMin value.
   static RangeBoundary MinConstant(RangeSize size) {
     switch (size) {
       case kRangeBoundarySmi:
-        return FromConstant(Smi::kMinValue);
+        return FromConstant(compiler::target::kSmiMin);
       case kRangeBoundaryInt32:
         return FromConstant(kMinInt32);
       case kRangeBoundaryInt64:
@@ -94,7 +99,7 @@
   static RangeBoundary MaxConstant(RangeSize size) {
     switch (size) {
       case kRangeBoundarySmi:
-        return FromConstant(Smi::kMaxValue);
+        return FromConstant(compiler::target::kSmiMax);
       case kRangeBoundaryInt32:
         return FromConstant(kMaxInt32);
       case kRangeBoundaryInt64:
@@ -138,7 +143,8 @@
 
   // Returns true when this is a constant that is outside of Smi range.
   bool OverflowedSmi() const {
-    return (IsConstant() && !Smi::IsValid(ConstantValue())) || IsInfinity();
+    return (IsConstant() && !compiler::target::IsSmi(ConstantValue())) ||
+           IsInfinity();
   }
 
   bool Overflowed(RangeBoundary::RangeSize size) const {
diff --git a/runtime/vm/compiler/backend/range_analysis_test.cc b/runtime/vm/compiler/backend/range_analysis_test.cc
index c67708f..81b1467 100644
--- a/runtime/vm/compiler/backend/range_analysis_test.cc
+++ b/runtime/vm/compiler/backend/range_analysis_test.cc
@@ -67,15 +67,18 @@
   TEST_RANGE_OP(Range::Shl, -1, 1, 63, 63, RangeBoundary(kMinInt64),
                 RangeBoundary::PositiveInfinity());
   if (kBitsPerWord == 64) {
-    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62, RangeBoundary(kSmiMin),
-                      RangeBoundary(kSmiMax));
+    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62,
+                      RangeBoundary(compiler::target::kSmiMin),
+                      RangeBoundary(compiler::target::kSmiMax));
     TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30, RangeBoundary(-(1 << 30)),
                       RangeBoundary(1 << 30));
   } else {
-    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30, RangeBoundary(kSmiMin),
-                      RangeBoundary(kSmiMax));
-    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62, RangeBoundary(kSmiMin),
-                      RangeBoundary(kSmiMax));
+    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30,
+                      RangeBoundary(compiler::target::kSmiMin),
+                      RangeBoundary(compiler::target::kSmiMax));
+    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62,
+                      RangeBoundary(compiler::target::kSmiMin),
+                      RangeBoundary(compiler::target::kSmiMax));
   }
   TEST_RANGE_OP(Range::Shl, 0, 100, 0, 64, RangeBoundary(0),
                 RangeBoundary::PositiveInfinity());
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index f29815c..1144be8 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -310,6 +310,23 @@
                  RoundByteOffset(to, index_constant_));
   }
 
+  // Given alias X[ByteOffs|S], smaller element size S' and index from 0 to
+  // S/S' - 1 return alias X[ByteOffs + S'*index|S'] - this is the byte offset
+  // of a smaller typed array element which is contained within this typed
+  // array element.
+  // For example X[8|kInt32] contains inside X[8|kInt16] (index is 0) and
+  // X[10|kInt16] (index is 1).
+  Place ToSmallerElement(ElementSize to, intptr_t index) const {
+    ASSERT(kind() == kConstantIndexed);
+    ASSERT(element_size() != kNoSize);
+    ASSERT(element_size() > to);
+    ASSERT(index >= 0);
+    ASSERT(index <
+           ElementSizeMultiplier(element_size()) / ElementSizeMultiplier(to));
+    return Place(ElementSizeBits::update(to, flags_), instance_,
+                 ByteOffsetToSmallerElement(to, index, index_constant_));
+  }
+
   intptr_t id() const { return id_; }
 
   Kind kind() const { return KindBits::decode(flags_); }
@@ -548,6 +565,12 @@
     return offset & ~(ElementSizeMultiplier(size) - 1);
   }
 
+  static intptr_t ByteOffsetToSmallerElement(ElementSize size,
+                                             intptr_t index,
+                                             intptr_t base_offset) {
+    return base_offset + index * ElementSizeMultiplier(size);
+  }
+
   class KindBits : public BitField<uword, Kind, 0, 3> {};
   class RepresentationBits
       : public BitField<uword, Representation, KindBits::kNextBit, 11> {};
@@ -890,13 +913,42 @@
 
             // X[C|S] aliases with X[RoundDown(C, S')|S'] and likewise
             // *[C|S] aliases with *[RoundDown(C, S')|S'].
-            const Place larger_alias =
-                alias->ToLargerElement(static_cast<Place::ElementSize>(i));
-            CrossAlias(alias, larger_alias);
-            if (has_aliased_instance) {
-              // If X is an aliased instance then X[C|S] aliases
-              // with *[RoundDown(C, S')|S'].
-              CrossAlias(alias, larger_alias.CopyWithoutInstance());
+            CrossAlias(alias, alias->ToLargerElement(
+                                  static_cast<Place::ElementSize>(i)));
+          }
+
+          if (has_aliased_instance) {
+            // If X is an aliased instance then X[C|S] aliases *[C'|S'] for all
+            // related combinations of C' and S'.
+            // Caveat: this propagation is not symmetric (we would not know
+            // to propagate aliasing from *[C'|S'] to X[C|S] when visiting
+            // *[C'|S']) and thus we need to handle both element sizes smaller
+            // and larger than S.
+            const Place no_instance_alias = alias->CopyWithoutInstance();
+            for (intptr_t i = Place::kInt8; i <= Place::kLargestElementSize;
+                 i++) {
+              // Skip element sizes that a guaranteed to have no
+              // representatives.
+              if (!typed_data_access_sizes_.Contains(alias->element_size())) {
+                continue;
+              }
+
+              const auto other_size = static_cast<Place::ElementSize>(i);
+              if (other_size > alias->element_size()) {
+                // X[C|S] aliases all larger elements which cover it:
+                // *[RoundDown(C, S')|S'] for S' > S.
+                CrossAlias(alias,
+                           no_instance_alias.ToLargerElement(other_size));
+              } else if (other_size < alias->element_size()) {
+                // X[C|S] aliases all sub-elements of smaller size:
+                // *[C+j*S'|S'] for S' < S and j from 0 to S/S' - 1.
+                const auto num_smaller_elements =
+                    1 << (alias->element_size() - other_size);
+                for (intptr_t j = 0; j < num_smaller_elements; j++) {
+                  CrossAlias(alias,
+                             no_instance_alias.ToSmallerElement(other_size, j));
+                }
+              }
             }
           }
         }
@@ -1673,10 +1725,9 @@
               Definition* forward_def = graph_->constant_null();
               if (alloc->ArgumentCount() > 0) {
                 ASSERT(alloc->ArgumentCount() == 1);
-                intptr_t type_args_offset =
-                    alloc->cls().type_arguments_field_offset();
-                if (load->slot().IsTypeArguments() &&
-                    load->slot().offset_in_bytes() == type_args_offset) {
+                const Slot& type_args_slot = Slot::GetTypeArgumentsSlotFor(
+                    graph_->thread(), alloc->cls());
+                if (load->slot().IsIdentical(type_args_slot)) {
                   forward_def = alloc->PushArgumentAt(0)->value()->definition();
                 }
               }
@@ -3497,6 +3548,7 @@
             new (flow_graph_->zone()) ConstantInstr(orig->value());
         copy->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
         old->ReplaceUsesWith(copy);
+        copy->set_previous(old->previous());  // partial link
         (*idefs)[j] = copy;
       }
     }
diff --git a/runtime/vm/compiler/backend/redundancy_elimination_test.cc b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
index e06aca3..e22f5e4 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination_test.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
@@ -551,4 +551,194 @@
                        /* make_host_escape= */ true, MakeAssertAssignable);
 }
 
+// This test verifies behavior of load forwarding when an alias for an
+// allocation A is created after forwarded due to an eliminated load. That is,
+// allocation A is stored and later retrieved via load B, B is used in store C
+// (with a different constant index/index_scale than in B but that overlaps),
+// and then A is retrieved again (with the same index as in B) in load D.
+//
+// When B gets eliminated and replaced with in C and D with A, the store in C
+// should stop the load D from being eliminated. This is a scenario that came
+// up when forwarding typed data view factory arguments.
+//
+// Here, the entire scenario happens within a single basic block.
+ISOLATE_UNIT_TEST_CASE(LoadOptimizer_AliasingViaLoadElimination_SingleBlock) {
+  const char* kScript = R"(
+    import 'dart:typed_data';
+
+    testViewAliasing1() {
+      final f64 = new Float64List(1);
+      final f32 = new Float32List.view(f64.buffer);
+      f64[0] = 1.0; // Should not be forwarded.
+      f32[1] = 2.0; // upper 32bits for 2.0f and 2.0 are the same
+      return f64[0];
+    }
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& function =
+      Function::Handle(GetFunction(root_library, "testViewAliasing1"));
+
+  Invoke(root_library, "testViewAliasing1");
+
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({});
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  StaticCallInstr* list_factory = nullptr;
+  UnboxedConstantInstr* double_one = nullptr;
+  StoreIndexedInstr* first_store = nullptr;
+  StoreIndexedInstr* second_store = nullptr;
+  LoadIndexedInstr* final_load = nullptr;
+  BoxInstr* boxed_result = nullptr;
+
+  ILMatcher cursor(flow_graph, entry);
+  RELEASE_ASSERT(cursor.TryMatch(
+      {
+          {kMatchAndMoveStaticCall, &list_factory},
+          {kMatchAndMoveUnboxedConstant, &double_one},
+          {kMatchAndMoveStoreIndexed, &first_store},
+          {kMatchAndMoveStoreIndexed, &second_store},
+          {kMatchAndMoveLoadIndexed, &final_load},
+          {kMatchAndMoveBox, &boxed_result},
+          kMatchReturn,
+      },
+      /*insert_before=*/kMoveGlob));
+
+  EXPECT(first_store->array()->definition() == list_factory);
+  EXPECT(second_store->array()->definition() == list_factory);
+  EXPECT(boxed_result->value()->definition() != double_one);
+  EXPECT(boxed_result->value()->definition() == final_load);
+}
+
+// This test verifies behavior of load forwarding when an alias for an
+// allocation A is created after forwarded due to an eliminated load. That is,
+// allocation A is stored and later retrieved via load B, B is used in store C
+// (with a different constant index/index_scale than in B but that overlaps),
+// and then A is retrieved again (with the same index as in B) in load D.
+//
+// When B gets eliminated and replaced with in C and D with A, the store in C
+// should stop the load D from being eliminated. This is a scenario that came
+// up when forwarding typed data view factory arguments.
+//
+// Here, the scenario is split across basic blocks. This is a cut-down version
+// of language_2/vm/load_to_load_forwarding_vm_test.dart with just enough extra
+// to keep testViewAliasing1 from being optimized into a single basic block.
+// Thus, this test may be brittler than the other, if future work causes it to
+// end up compiled into a single basic block (or a simpler set of basic blocks).
+ISOLATE_UNIT_TEST_CASE(LoadOptimizer_AliasingViaLoadElimination_AcrossBlocks) {
+  const char* kScript = R"(
+    import 'dart:typed_data';
+
+    class Expect {
+      static void equals(var a, var b) {}
+      static void listEquals(var a, var b) {}
+    }
+
+    testViewAliasing1() {
+      final f64 = new Float64List(1);
+      final f32 = new Float32List.view(f64.buffer);
+      f64[0] = 1.0; // Should not be forwarded.
+      f32[1] = 2.0; // upper 32bits for 2.0f and 2.0 are the same
+      return f64[0];
+    }
+
+    testViewAliasing2() {
+      final f64 = new Float64List(2);
+      final f64v = new Float64List.view(f64.buffer,
+                                        Float64List.bytesPerElement);
+      f64[1] = 1.0; // Should not be forwarded.
+      f64v[0] = 2.0;
+      return f64[1];
+    }
+
+    testViewAliasing3() {
+      final u8 = new Uint8List(Float64List.bytesPerElement * 2);
+      final f64 = new Float64List.view(u8.buffer, Float64List.bytesPerElement);
+      f64[0] = 1.0; // Should not be forwarded.
+      u8[15] = 0x40;
+      u8[14] = 0x00;
+      return f64[0];
+    }
+
+    main() {
+      for (var i = 0; i < 20; i++) {
+        Expect.equals(2.0, testViewAliasing1());
+        Expect.equals(2.0, testViewAliasing2());
+        Expect.equals(2.0, testViewAliasing3());
+      }
+    }
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& function =
+      Function::Handle(GetFunction(root_library, "testViewAliasing1"));
+
+  Invoke(root_library, "main");
+
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  // Recent changes actually compile the function into a single basic
+  // block, so we need to test right after the load optimizer has been run.
+  // Have checked that this test still fails appropriately using the load
+  // optimizer prior to the fix (commit 2a237327).
+  FlowGraph* flow_graph = pipeline.RunPasses({
+      CompilerPass::kComputeSSA,
+      CompilerPass::kApplyICData,
+      CompilerPass::kTryOptimizePatterns,
+      CompilerPass::kSetOuterInliningId,
+      CompilerPass::kTypePropagation,
+      CompilerPass::kApplyClassIds,
+      CompilerPass::kInlining,
+      CompilerPass::kTypePropagation,
+      CompilerPass::kApplyClassIds,
+      CompilerPass::kTypePropagation,
+      CompilerPass::kApplyICData,
+      CompilerPass::kCanonicalize,
+      CompilerPass::kBranchSimplify,
+      CompilerPass::kIfConvert,
+      CompilerPass::kCanonicalize,
+      CompilerPass::kConstantPropagation,
+      CompilerPass::kOptimisticallySpecializeSmiPhis,
+      CompilerPass::kTypePropagation,
+      CompilerPass::kWidenSmiToInt32,
+      CompilerPass::kSelectRepresentations,
+      CompilerPass::kCSE,
+  });
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  StaticCallInstr* list_factory = nullptr;
+  UnboxedConstantInstr* double_one = nullptr;
+  StoreIndexedInstr* first_store = nullptr;
+  StoreIndexedInstr* second_store = nullptr;
+  LoadIndexedInstr* final_load = nullptr;
+  BoxInstr* boxed_result = nullptr;
+
+  ILMatcher cursor(flow_graph, entry);
+  RELEASE_ASSERT(cursor.TryMatch(
+      {
+          {kMatchAndMoveStaticCall, &list_factory},
+          kMatchAndMoveBranchTrue,
+          kMatchAndMoveBranchTrue,
+          kMatchAndMoveBranchFalse,
+          kMatchAndMoveBranchFalse,
+          {kMatchAndMoveUnboxedConstant, &double_one},
+          {kMatchAndMoveStoreIndexed, &first_store},
+          kMatchAndMoveBranchFalse,
+          {kMatchAndMoveStoreIndexed, &second_store},
+          {kMatchAndMoveLoadIndexed, &final_load},
+          {kMatchAndMoveBox, &boxed_result},
+          kMatchReturn,
+      },
+      /*insert_before=*/kMoveGlob));
+
+  EXPECT(first_store->array()->definition() == list_factory);
+  EXPECT(second_store->array()->definition() == list_factory);
+  EXPECT(boxed_result->value()->definition() != double_one);
+  EXPECT(boxed_result->value()->definition() == final_load);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index df6904b..bb0c918 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -54,7 +54,8 @@
 #define FIELD_VAR (0)
 #define DEFINE_NATIVE_FIELD(ClassName, FieldName, cid, mutability)             \
   Slot(Kind::k##ClassName##_##FieldName, FIELD_##mutability, k##cid##Cid,      \
-       ClassName::FieldName##_offset(), #ClassName "." #FieldName, nullptr),
+       compiler::target::ClassName::FieldName##_offset(),                      \
+       #ClassName "." #FieldName, nullptr),
 
       NATIVE_SLOTS_LIST(DEFINE_NATIVE_FIELD)
 
@@ -102,7 +103,8 @@
 }
 
 const Slot& Slot::GetTypeArgumentsSlotFor(Thread* thread, const Class& cls) {
-  return GetTypeArgumentsSlotAt(thread, cls.type_arguments_field_offset());
+  return GetTypeArgumentsSlotAt(
+      thread, compiler::target::Class::TypeArgumentsFieldOffset(cls));
 }
 
 const Slot& Slot::GetContextVariableSlotFor(Thread* thread,
@@ -115,7 +117,8 @@
   return SlotCache::Instance(thread).Canonicalize(Slot(
       Kind::kCapturedVariable,
       IsImmutableBit::encode(variable.is_final()) | IsNullableBit::encode(true),
-      kDynamicCid, Context::variable_offset(variable.index().value()),
+      kDynamicCid,
+      compiler::target::Context::variable_offset(variable.index().value()),
       &variable.name(), /*static_type=*/nullptr));
 }
 
@@ -156,7 +159,7 @@
            IsImmutableBit::encode(field.is_final() || field.is_const()) |
                IsNullableBit::encode(is_nullable) |
                IsGuardedBit::encode(used_guarded_state),
-           nullable_cid, field.Offset(), &field,
+           nullable_cid, compiler::target::Field::OffsetOf(field), &field,
            &AbstractType::ZoneHandle(zone, field.type())));
 
   // If properties of this slot were based on the guarded state make sure
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index ef6a408..46141a9 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -168,6 +168,8 @@
   bool Equals(const Slot* other) const;
   intptr_t Hashcode() const;
 
+  bool IsIdentical(const Slot& other) const { return this == &other; }
+
  private:
   Slot(Kind kind,
        int8_t bits,
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 0dec0c9..413f0d7 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -987,17 +987,11 @@
     return CompileType::Dynamic();
   }
 
-  if (function.HasBytecode() &&
-      graph_entry->parsed_function().node_sequence() == nullptr) {
-    // TODO(alexmarkov): Consider adding node_sequence() and scope.
-    return CompileType::Dynamic();
-  }
-
   // Parameter is the receiver.
   if ((index() == 0) &&
       (function.IsDynamicFunction() || function.IsGenerativeConstructor())) {
     const AbstractType& type =
-        graph_entry->parsed_function().ParameterVariable(index())->type();
+        graph_entry->parsed_function().RawParameterVariable(0)->type();
     if (type.IsObjectType() || type.IsNullType()) {
       // Receiver can be null.
       return CompileType::FromAbstractType(type, CompileType::kNullable);
@@ -1036,6 +1030,12 @@
     return CompileType(CompileType::kNonNullable, cid, &type);
   }
 
+  if (function.HasBytecode() &&
+      graph_entry->parsed_function().node_sequence() == nullptr) {
+    // TODO(alexmarkov): Consider adding node_sequence() and scope.
+    return CompileType::Dynamic();
+  }
+
   const bool is_unchecked_entry_param =
       graph_entry->unchecked_entry() == block_;
 
@@ -1515,7 +1515,7 @@
   return CompileType::FromCid(result_cid_);
 }
 
-CompileType CaseInsensitiveCompareUC16Instr::ComputeType() const {
+CompileType CaseInsensitiveCompareInstr::ComputeType() const {
   return CompileType::FromCid(kBoolCid);
 }
 
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index c141850..de3c1b5 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -366,7 +366,8 @@
 void CallSpecializer::AddChecksForArgNr(InstanceCallInstr* call,
                                         Definition* instr,
                                         int argument_number) {
-  const Cids* cids = Cids::Create(Z, *call->ic_data(), argument_number);
+  const Cids* cids =
+      Cids::CreateAndExpand(Z, *call->ic_data(), argument_number);
   AddCheckClass(instr, *cids, call->deopt_id(), call->env(), call);
 }
 
@@ -509,7 +510,7 @@
 }
 
 static bool SmiFitsInDouble() {
-  return kSmiBits < 53;
+  return compiler::target::kSmiBits < 53;
 }
 
 bool CallSpecializer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
@@ -1502,7 +1503,7 @@
                 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(),
                 result_cid);
             const Cids* cids =
-                Cids::Create(Z, ic_data, /* argument_number =*/0);
+                Cids::CreateAndExpand(Z, ic_data, /* argument_number =*/0);
             AddCheckClass(min_max->left()->definition(), *cids,
                           call->deopt_id(), call->env(), call);
             AddCheckClass(min_max->right()->definition(), *cids,
@@ -1835,8 +1836,9 @@
   const intptr_t element_size = TypedDataBase::ElementSizeFor(cid);
   const intptr_t index_scale = element_size;
 
-  auto data = new (Z) LoadUntaggedInstr(new (Z) Value(array),
-                                        TypedDataBase::data_field_offset());
+  auto data = new (Z)
+      LoadUntaggedInstr(new (Z) Value(array),
+                        compiler::target::TypedDataBase::data_field_offset());
   flow_graph_->InsertBefore(call, data, call->env(), FlowGraph::kValue);
 
   Definition* load = new (Z)
@@ -1862,24 +1864,59 @@
 
   const auto deopt_id = call->deopt_id();
 
-  if (cid == kTypedDataFloat32ArrayCid) {
-    value = new (Z) DoubleToFloatInstr(new (Z) Value(value), deopt_id,
-                                       Instruction::kNotSpeculative);
-    flow_graph_->InsertBefore(call, value, call->env(), FlowGraph::kValue);
-  } else if (cid == kTypedDataInt32ArrayCid) {
-    value = new (Z)
-        UnboxInt32Instr(UnboxInt32Instr::kTruncate, new (Z) Value(value),
-                        deopt_id, Instruction::kNotSpeculative);
-    flow_graph_->InsertBefore(call, value, call->env(), FlowGraph::kValue);
-  } else if (cid == kTypedDataUint32ArrayCid) {
-    value = new (Z) UnboxUint32Instr(new (Z) Value(value), deopt_id,
-                                     Instruction::kNotSpeculative);
-    ASSERT(value->AsUnboxInteger()->is_truncating());
-    flow_graph_->InsertBefore(call, value, call->env(), FlowGraph::kValue);
+  switch (cid) {
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid: {
+      // Insert explicit unboxing instructions with truncation to avoid relying
+      // on [SelectRepresentations] which doesn't mark them as truncating.
+      value = UnboxInstr::Create(kUnboxedIntPtr, new (Z) Value(value), deopt_id,
+                                 Instruction::kNotSpeculative);
+      flow_graph_->InsertBefore(call, value, call->env(), FlowGraph::kValue);
+      break;
+    }
+    case kTypedDataInt32ArrayCid: {
+      // Insert explicit unboxing instructions with truncation to avoid relying
+      // on [SelectRepresentations] which doesn't mark them as truncating.
+      value = UnboxInstr::Create(kUnboxedInt32, new (Z) Value(value), deopt_id,
+                                 Instruction::kNotSpeculative);
+      flow_graph_->InsertBefore(call, value, call->env(), FlowGraph::kValue);
+      break;
+    }
+    case kTypedDataUint32ArrayCid: {
+      // Insert explicit unboxing instructions with truncation to avoid relying
+      // on [SelectRepresentations] which doesn't mark them as truncating.
+      value = UnboxInstr::Create(kUnboxedUint32, new (Z) Value(value), deopt_id,
+                                 Instruction::kNotSpeculative);
+      flow_graph_->InsertBefore(call, value, call->env(), FlowGraph::kValue);
+      break;
+    }
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid: {
+      // Insert explicit unboxing instructions with truncation to avoid relying
+      // on [SelectRepresentations] which doesn't mark them as truncating.
+      value = UnboxInstr::Create(kUnboxedInt64, new (Z) Value(value),
+                                 DeoptId::kNone, Instruction::kNotSpeculative);
+      flow_graph_->InsertBefore(call, value, call->env(), FlowGraph::kValue);
+      break;
+    }
+    case kTypedDataFloat32ArrayCid: {
+      value = new (Z) DoubleToFloatInstr(new (Z) Value(value), deopt_id,
+                                         Instruction::kNotSpeculative);
+      flow_graph_->InsertBefore(call, value, call->env(), FlowGraph::kValue);
+      break;
+    }
+    default:
+      break;
   }
 
-  auto data = new (Z) LoadUntaggedInstr(new (Z) Value(array),
-                                        TypedDataBase::data_field_offset());
+  auto data = new (Z)
+      LoadUntaggedInstr(new (Z) Value(array),
+                        compiler::target::TypedDataBase::data_field_offset());
   flow_graph_->InsertBefore(call, data, call->env(), FlowGraph::kValue);
 
   auto store = new (Z) StoreIndexedInstr(
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 3e08c06..340b149 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -178,7 +178,7 @@
       repeat = DoBody(state);
       thread->CheckForSafepoint();
 #if defined(DEBUG)
-      FlowGraphChecker(state->flow_graph).Check();
+      FlowGraphChecker(state->flow_graph).Check(name());
 #endif
     }
     PrintGraph(state, kTraceAfter, round);
@@ -207,6 +207,21 @@
 #define INVOKE_PASS(Name)                                                      \
   CompilerPass::Get(CompilerPass::k##Name)->Run(pass_state);
 
+void CompilerPass::RunGraphIntrinsicPipeline(CompilerPassState* pass_state) {
+  INVOKE_PASS(AllocateRegistersForGraphIntrinsic);
+}
+
+void CompilerPass::RunInliningPipeline(PipelineMode mode,
+                                       CompilerPassState* pass_state) {
+  INVOKE_PASS(ApplyClassIds);
+  INVOKE_PASS(TypePropagation);
+  INVOKE_PASS(ApplyICData);
+  INVOKE_PASS(Canonicalize);
+  // Optimize (a << b) & c patterns, merge instructions. Must occur
+  // before 'SelectRepresentations' which inserts conversion nodes.
+  INVOKE_PASS(TryOptimizePatterns);
+}
+
 void CompilerPass::RunPipeline(PipelineMode mode,
                                CompilerPassState* pass_state) {
   INVOKE_PASS(ComputeSSA);
@@ -412,6 +427,14 @@
   allocator.AllocateRegisters();
 });
 
+COMPILER_PASS(AllocateRegistersForGraphIntrinsic, {
+  // Ensure loop hierarchy has been computed.
+  flow_graph->GetLoopHierarchy();
+  // Perform register allocation on the SSA graph.
+  FlowGraphAllocator allocator(*flow_graph, /*intrinsic_mode=*/true);
+  allocator.AllocateRegisters();
+});
+
 COMPILER_PASS(ReorderBlocks, {
   if (state->reorder_blocks) {
     state->block_scheduler->ReorderBlocks();
@@ -425,8 +448,8 @@
     Definition* last_allocated = nullptr;
     for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
       Instruction* current = it.Current();
-      if (StoreInstanceFieldInstr* instr = current->AsStoreInstanceField()) {
-        if (!current->CanTriggerGC()) {
+      if (!current->CanTriggerGC()) {
+        if (StoreInstanceFieldInstr* instr = current->AsStoreInstanceField()) {
           if (instr->instance()->definition() == last_allocated) {
             instr->set_emit_store_barrier(kNoStoreBarrier);
           }
@@ -434,10 +457,11 @@
         }
       }
 
-      AllocationInstr* alloc = current->AsAllocation();
-      if (alloc != nullptr && alloc->WillAllocateNewOrRemembered()) {
-        last_allocated = alloc;
-        continue;
+      if (AllocationInstr* alloc = current->AsAllocation()) {
+        if (alloc->WillAllocateNewOrRemembered()) {
+          last_allocated = alloc;
+          continue;
+        }
       }
 
       if (current->CanTriggerGC()) {
diff --git a/runtime/vm/compiler/compiler_pass.h b/runtime/vm/compiler/compiler_pass.h
index e5aa823..0cfca3f 100644
--- a/runtime/vm/compiler/compiler_pass.h
+++ b/runtime/vm/compiler/compiler_pass.h
@@ -17,6 +17,7 @@
 
 #define COMPILER_PASS_LIST(V)                                                  \
   V(AllocateRegisters)                                                         \
+  V(AllocateRegistersForGraphIntrinsic)                                        \
   V(AllocationSinking_DetachMaterializations)                                  \
   V(AllocationSinking_Sink)                                                    \
   V(ApplyClassIds)                                                             \
@@ -142,6 +143,10 @@
 
   enum PipelineMode { kJIT, kAOT };
 
+  static void RunGraphIntrinsicPipeline(CompilerPassState* state);
+
+  static void RunInliningPipeline(PipelineMode mode, CompilerPassState* state);
+
   static void RunPipeline(PipelineMode mode, CompilerPassState* state);
 
   static void RunPipelineWithPasses(
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index f388295..bac526c 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -146,6 +146,17 @@
   "stub_code_compiler_x64.cc",
 ]
 
+# The most common way to include assembly files in C projects is to have
+# separate assembly files per architecture and operating system (for example
+# boringssl).
+#
+# Not that this diverges from our convention to build every file on every OS
+# but have ifdef guards which make the files empty on some configurations.
+if (is_linux || is_mac) {
+  # MASM on Windows does not support c preproccesor style flags.
+  compiler_sources += [ "ffi_dbc_trampoline_x64_linux_mac.S" ]
+}
+
 compiler_sources_tests = [
   "assembler/assembler_arm64_test.cc",
   "assembler/assembler_arm_test.cc",
@@ -157,6 +168,7 @@
   "backend/il_test.cc",
   "backend/il_test_helper.h",
   "backend/il_test_helper.cc",
+  "backend/inliner_test.cc",
   "backend/locations_helpers_test.cc",
   "backend/loops_test.cc",
   "backend/range_analysis_test.cc",
diff --git a/runtime/vm/compiler/ffi.cc b/runtime/vm/compiler/ffi.cc
index 8d8d136..665382a 100644
--- a/runtime/vm/compiler/ffi.cc
+++ b/runtime/vm/compiler/ffi.cc
@@ -3,9 +3,14 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/compiler/ffi.h"
+
 #include <algorithm>
+
 #include "platform/globals.h"
+#include "vm/compiler/backend/locations.h"
 #include "vm/compiler/runtime_api.h"
+#include "vm/growable_array.h"
+#include "vm/stack_frame.h"
 
 namespace dart {
 
@@ -13,8 +18,6 @@
 
 namespace ffi {
 
-#if !defined(TARGET_ARCH_DBC)
-
 static const size_t kSizeUnknown = 0;
 
 static const intptr_t kNumElementSizes = kFfiVoidCid - kFfiPointerCid + 1;
@@ -73,6 +76,21 @@
   }
 }
 
+SmallRepresentation TypeSmallRepresentation(const AbstractType& ffi_type) {
+  switch (ffi_type.type_class_id()) {
+    case kFfiInt8Cid:
+      return kSmallUnboxedInt8;
+    case kFfiInt16Cid:
+      return kSmallUnboxedInt16;
+    case kFfiUint8Cid:
+      return kSmallUnboxedUint8;
+    case kFfiUint16Cid:
+      return kSmallUnboxedUint16;
+    default:
+      return kNoSmallRepresentation;
+  }
+}
+
 bool NativeTypeIsVoid(const AbstractType& result_type) {
   return result_type.type_class_id() == kFfiVoidCid;
 }
@@ -100,7 +118,8 @@
 
 // Converts a Ffi [signature] to a list of Representations.
 // Note that this ignores first argument (receiver) which is dynamic.
-ZoneGrowableArray<Representation>* ArgumentRepresentations(
+template <class CallingConventions>
+ZoneGrowableArray<Representation>* ArgumentRepresentationsBase(
     const Function& signature) {
   intptr_t num_arguments = signature.num_fixed_parameters() - 1;
   auto result = new ZoneGrowableArray<Representation>(num_arguments);
@@ -108,6 +127,8 @@
     AbstractType& arg_type =
         AbstractType::Handle(signature.ParameterTypeAt(i + 1));
     Representation rep = TypeRepresentation(arg_type);
+    // In non simulator mode host::CallingConventions == CallingConventions.
+    // In simulator mode convert arguments to host representation.
     if (rep == kUnboxedFloat && CallingConventions::kAbiSoftFP) {
       rep = kUnboxedInt32;
     } else if (rep == kUnboxedDouble && CallingConventions::kAbiSoftFP) {
@@ -118,10 +139,52 @@
   return result;
 }
 
+template <class CallingConventions>
+Representation ResultRepresentationBase(const Function& signature) {
+  AbstractType& arg_type = AbstractType::Handle(signature.result_type());
+  Representation rep = TypeRepresentation(arg_type);
+  if (rep == kUnboxedFloat && CallingConventions::kAbiSoftFP) {
+    rep = kUnboxedInt32;
+  } else if (rep == kUnboxedDouble && CallingConventions::kAbiSoftFP) {
+    rep = kUnboxedInt64;
+  }
+  return rep;
+}
+
+#if !defined(TARGET_ARCH_DBC)
+
+ZoneGrowableArray<Representation>* ArgumentRepresentations(
+    const Function& signature) {
+  return ArgumentRepresentationsBase<CallingConventions>(signature);
+}
+
+Representation ResultRepresentation(const Function& signature) {
+  return ResultRepresentationBase<CallingConventions>(signature);
+}
+
+#endif  // !defined(TARGET_ARCH_DBC)
+
+#if defined(USING_SIMULATOR)
+
+ZoneGrowableArray<Representation>* ArgumentHostRepresentations(
+    const Function& signature) {
+  return ArgumentRepresentationsBase<host::CallingConventions>(signature);
+}
+
+Representation ResultHostRepresentation(const Function& signature) {
+  return ResultRepresentationBase<host::CallingConventions>(signature);
+}
+
+#endif  // defined(USING_SIMULATOR)
+
 // Represents the state of a stack frame going into a call, between allocations
 // of argument locations. Acts like a register allocator but for arguments in
 // the native ABI.
-class ArgumentFrameState : public ValueObject {
+template <class CallingConventions,
+          class Location,
+          class Register,
+          class FpuRegister>
+class ArgumentAllocator : public ValueObject {
  public:
   Location AllocateArgument(Representation rep) {
     switch (rep) {
@@ -146,9 +209,13 @@
     }
 
     // Argument must be spilled.
-    if ((rep == kUnboxedInt64 || rep == kUnboxedDouble) &&
-        compiler::target::kWordSize == 4) {
+    if (rep == kUnboxedInt64 && compiler::target::kWordSize == 4) {
       return AllocateAlignedStackSlots(rep);
+    } else if (rep == kUnboxedDouble) {
+      // By convention, we always use DoubleStackSlot for doubles, even on
+      // 64-bit systems.
+      ASSERT(!CallingConventions::kAlignArguments);
+      return AllocateDoubleStackSlot();
     } else {
       return AllocateStackSlot();
     }
@@ -156,7 +223,15 @@
 
  private:
   Location AllocateStackSlot() {
-    return Location::StackSlot(stack_height_in_slots++, SPREG);
+    return Location::StackSlot(stack_height_in_slots++,
+                               CallingConventions::kStackPointerRegister);
+  }
+
+  Location AllocateDoubleStackSlot() {
+    const Location result = Location::DoubleStackSlot(
+        stack_height_in_slots, CallingConventions::kStackPointerRegister);
+    stack_height_in_slots += 8 / compiler::target::kWordSize;
+    return result;
   }
 
   // Allocates a pair of stack slots where the first stack slot is aligned to an
@@ -169,7 +244,8 @@
 
     Location result;
     if (rep == kUnboxedDouble) {
-      result = Location::DoubleStackSlot(stack_height_in_slots, SPREG);
+      result = Location::DoubleStackSlot(
+          stack_height_in_slots, CallingConventions::kStackPointerRegister);
       stack_height_in_slots += 2;
     } else {
       const Location low = AllocateStackSlot();
@@ -224,15 +300,82 @@
   intptr_t stack_height_in_slots = 0;
 };
 
+ZoneGrowableArray<Location>*
+CallbackArgumentTranslator::TranslateArgumentLocations(
+    const ZoneGrowableArray<Location>& arg_locs) {
+  auto& pushed_locs = *(new ZoneGrowableArray<Location>(arg_locs.length()));
+
+  CallbackArgumentTranslator translator;
+  for (intptr_t i = 0, n = arg_locs.length(); i < n; i++) {
+    translator.AllocateArgument(arg_locs[i]);
+  }
+  for (intptr_t i = 0, n = arg_locs.length(); i < n; ++i) {
+    pushed_locs.Add(translator.TranslateArgument(arg_locs[i]));
+  }
+
+  return &pushed_locs;
+}
+
+void CallbackArgumentTranslator::AllocateArgument(Location arg) {
+  if (arg.IsPairLocation()) {
+    AllocateArgument(arg.Component(0));
+    AllocateArgument(arg.Component(1));
+    return;
+  }
+  if (arg.HasStackIndex()) return;
+  ASSERT(arg.IsRegister() || arg.IsFpuRegister());
+  if (arg.IsRegister()) {
+    argument_slots_required_++;
+  } else {
+    argument_slots_required_ += 8 / compiler::target::kWordSize;
+  }
+}
+
+Location CallbackArgumentTranslator::TranslateArgument(Location arg) {
+  if (arg.IsPairLocation()) {
+    const Location low = TranslateArgument(arg.Component(0));
+    const Location high = TranslateArgument(arg.Component(1));
+    return Location::Pair(low, high);
+  }
+
+  if (arg.HasStackIndex()) {
+    // Add extra slots after the saved arguments for the return address and
+    // frame pointer of the dummy arguments frame, which will be between the
+    // saved argument registers and stack arguments. Also add slots for the
+    // shadow space if present (factored into
+    // kCallbackSlotsBeforeSavedArguments).
+    FrameRebase rebase(
+        /*old_base=*/SPREG, /*new_base=*/SPREG,
+        /*stack_delta=*/argument_slots_required_ +
+            kCallbackSlotsBeforeSavedArguments);
+    return rebase.Rebase(arg);
+  }
+
+  if (arg.IsRegister()) {
+    return Location::StackSlot(argument_slots_used_++, SPREG);
+  }
+
+  ASSERT(arg.IsFpuRegister());
+  const Location result =
+      Location::DoubleStackSlot(argument_slots_used_, SPREG);
+  argument_slots_used_ += 8 / compiler::target::kWordSize;
+  return result;
+}
+
 // Takes a list of argument representations, and converts it to a list of
 // argument locations based on calling convention.
-ZoneGrowableArray<Location>* ArgumentLocations(
+template <class CallingConventions,
+          class Location,
+          class Register,
+          class FpuRegister>
+ZoneGrowableArray<Location>* ArgumentLocationsBase(
     const ZoneGrowableArray<Representation>& arg_reps) {
   intptr_t num_arguments = arg_reps.length();
   auto result = new ZoneGrowableArray<Location>(num_arguments);
 
   // Loop through all arguments and assign a register or a stack location.
-  ArgumentFrameState frame_state;
+  ArgumentAllocator<CallingConventions, Location, Register, FpuRegister>
+      frame_state;
   for (intptr_t i = 0; i < num_arguments; i++) {
     Representation rep = arg_reps[i];
     result->Add(frame_state.AllocateArgument(rep));
@@ -240,18 +383,35 @@
   return result;
 }
 
-Representation ResultRepresentation(const Function& signature) {
-  AbstractType& arg_type = AbstractType::Handle(signature.result_type());
-  Representation rep = TypeRepresentation(arg_type);
-  if (rep == kUnboxedFloat && CallingConventions::kAbiSoftFP) {
-    rep = kUnboxedInt32;
-  } else if (rep == kUnboxedDouble && CallingConventions::kAbiSoftFP) {
-    rep = kUnboxedInt64;
+ZoneGrowableArray<Location>* ArgumentLocations(
+    const ZoneGrowableArray<Representation>& arg_reps) {
+#if !defined(TARGET_ARCH_DBC)
+  return ArgumentLocationsBase<dart::CallingConventions, Location,
+                               dart::Register, dart::FpuRegister>(arg_reps);
+#else
+  intptr_t next_free_register = compiler::ffi::kFirstArgumentRegister;
+  intptr_t num_arguments = arg_reps.length();
+  auto result = new ZoneGrowableArray<Location>(num_arguments);
+  for (intptr_t i = 0; i < num_arguments; i++) {
+    // TODO(dacoharkes): In 32 bits, use pair locations.
+    result->Add(Location::RegisterLocation(next_free_register));
+    next_free_register++;
   }
-  return rep;
+  return result;
+#endif
 }
 
+#if defined(TARGET_ARCH_DBC)
+ZoneGrowableArray<HostLocation>* HostArgumentLocations(
+    const ZoneGrowableArray<Representation>& arg_reps) {
+  return ArgumentLocationsBase<dart::host::CallingConventions, HostLocation,
+                               dart::host::Register, dart::host::FpuRegister>(
+      arg_reps);
+}
+#endif
+
 Location ResultLocation(Representation result_rep) {
+#ifndef TARGET_ARCH_DBC
   switch (result_rep) {
     case kUnboxedFloat:
     case kUnboxedDouble:
@@ -276,10 +436,15 @@
     default:
       UNREACHABLE();
   }
+#else
+  // TODO(dacoharkes): Support 64 bit result values on 32 bit DBC.
+  return Location::RegisterLocation(0);
+#endif
 }
 
 // Accounts for alignment, where some stack slots are used as padding.
-intptr_t NumStackSlots(const ZoneGrowableArray<Location>& locations) {
+template <class Location>
+intptr_t TemplateNumStackSlots(const ZoneGrowableArray<Location>& locations) {
   intptr_t num_arguments = locations.length();
   intptr_t max_height_in_slots = 0;
   for (intptr_t i = 0; i < num_arguments; i++) {
@@ -299,15 +464,90 @@
   return max_height_in_slots;
 }
 
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
-
-#else
-
-size_t ElementSizeInBytes(intptr_t class_id) {
-  UNREACHABLE();
+intptr_t NumStackSlots(const ZoneGrowableArray<Location>& locations) {
+  return TemplateNumStackSlots(locations);
 }
 
-#endif  // !defined(TARGET_ARCH_DBC)
+#if defined(TARGET_ARCH_DBC)
+
+static RawTypedData* typed_data_new_uintptr(intptr_t length) {
+#if defined(ARCH_IS_32_BIT)
+  return TypedData::New(kTypedDataUint32ArrayCid, length);
+#else
+  return TypedData::New(kTypedDataUint64ArrayCid, length);
+#endif
+}
+
+static void typed_data_set_uintptr(const TypedData& typed_data,
+                                   intptr_t index,
+                                   uintptr_t value) {
+#if defined(ARCH_IS_32_BIT)
+  typed_data.SetUint32(target::kWordSize * index, value);
+#else
+  typed_data.SetUint64(target::kWordSize * index, value);
+#endif
+}
+
+static uintptr_t typed_data_get_uintptr(const TypedData& typed_data,
+                                        intptr_t index) {
+#if defined(ARCH_IS_32_BIT)
+  return typed_data.GetUint32(target::kWordSize * index);
+#else
+  return typed_data.GetUint64(target::kWordSize * index);
+#endif
+}
+
+// Number of host stack slots used in 'locations'.
+static intptr_t HostNumStackSlots(
+    const ZoneGrowableArray<HostLocation>& locations) {
+  return TemplateNumStackSlots(locations);
+}
+
+RawTypedData* FfiSignatureDescriptor::New(
+    const ZoneGrowableArray<HostLocation>& arg_host_locations,
+    const Representation result_representation) {
+  const uintptr_t num_arguments = arg_host_locations.length();
+  const uintptr_t num_stack_slots = HostNumStackSlots(arg_host_locations);
+
+  const TypedData& result = TypedData::Handle(
+      typed_data_new_uintptr(kOffsetArgumentLocations + num_arguments));
+
+  typed_data_set_uintptr(result, kOffsetNumArguments, num_arguments);
+  typed_data_set_uintptr(result, kOffsetNumStackSlots, num_stack_slots);
+  typed_data_set_uintptr(result, kOffsetResultRepresentation,
+                         result_representation);
+
+  for (uintptr_t i = 0; i < num_arguments; i++) {
+    typed_data_set_uintptr(result, kOffsetArgumentLocations + i,
+                           arg_host_locations.At(i).write());
+  }
+
+  return result.raw();
+}
+
+intptr_t FfiSignatureDescriptor::length() const {
+  return typed_data_get_uintptr(typed_data_, kOffsetNumArguments);
+}
+
+intptr_t FfiSignatureDescriptor::num_stack_slots() const {
+  return typed_data_get_uintptr(typed_data_, kOffsetNumStackSlots);
+}
+
+HostLocation FfiSignatureDescriptor::LocationAt(intptr_t index) const {
+  return HostLocation::read(
+      typed_data_get_uintptr(typed_data_, kOffsetArgumentLocations + index));
+}
+
+Representation FfiSignatureDescriptor::ResultRepresentation() const {
+  uintptr_t result_int =
+      typed_data_get_uintptr(typed_data_, kOffsetResultRepresentation);
+  ASSERT(result_int < kNumRepresentations);
+  return static_cast<Representation>(result_int);
+}
+
+#endif  // defined(TARGET_ARCH_DBC)
+
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 }  // namespace ffi
 
diff --git a/runtime/vm/compiler/ffi.h b/runtime/vm/compiler/ffi.h
index efed0cc..846775a 100644
--- a/runtime/vm/compiler/ffi.h
+++ b/runtime/vm/compiler/ffi.h
@@ -28,22 +28,41 @@
 // Unboxed representation of an FFI type (extends 'ffi.NativeType').
 Representation TypeRepresentation(const AbstractType& result_type);
 
+// Unboxed representation of an FFI type (extends 'ffi.NativeType') for 8 and 16
+// bit integers.
+SmallRepresentation TypeSmallRepresentation(const AbstractType& result_type);
+
 // Whether a type which extends 'ffi.NativeType' also extends 'ffi.Pointer'.
 bool NativeTypeIsPointer(const AbstractType& result_type);
 
 // Whether a type is 'ffi.Void'.
 bool NativeTypeIsVoid(const AbstractType& result_type);
 
-// Unboxed representation of the result of a C signature function.
-Representation ResultRepresentation(const Function& signature);
-
 // Location for the result of a C signature function.
 Location ResultLocation(Representation result_rep);
 
+#if !defined(TARGET_ARCH_DBC)
+
 // Unboxed representations of the arguments to a C signature function.
 ZoneGrowableArray<Representation>* ArgumentRepresentations(
     const Function& signature);
 
+// Unboxed representation of the result of a C signature function.
+Representation ResultRepresentation(const Function& signature);
+
+#endif  // !defined(TARGET_ARCH_DBC)
+
+#if defined(USING_SIMULATOR)
+
+// Unboxed host representations of the arguments to a C signature function.
+ZoneGrowableArray<Representation>* ArgumentHostRepresentations(
+    const Function& signature);
+
+// Unboxed host representation of the result of a C signature function.
+Representation ResultHostRepresentation(const Function& signature);
+
+#endif  // defined(USING_SIMULATOR)
+
 // Location for the arguments of a C signature function.
 ZoneGrowableArray<Location>* ArgumentLocations(
     const ZoneGrowableArray<Representation>& arg_reps);
@@ -51,6 +70,69 @@
 // Number of stack slots used in 'locations'.
 intptr_t NumStackSlots(const ZoneGrowableArray<Location>& locations);
 
+#if defined(TARGET_ARCH_DBC)
+
+// The first argument to a ffi trampoline is the function address, the arguments
+// to the call follow the function address.
+const intptr_t kFunctionAddressRegister = 0;
+const intptr_t kFirstArgumentRegister = 1;
+
+// Location in host for the arguments of a C signature function.
+ZoneGrowableArray<HostLocation>* HostArgumentLocations(
+    const ZoneGrowableArray<Representation>& arg_reps);
+
+// A signature descriptor consists of the signature length, argument locations,
+// and result representation.
+class FfiSignatureDescriptor : public ValueObject {
+ public:
+  explicit FfiSignatureDescriptor(const TypedData& typed_data)
+      : typed_data_(typed_data) {}
+
+  static RawTypedData* New(
+      const ZoneGrowableArray<HostLocation>& arg_host_locations,
+      const Representation result_representation);
+
+  intptr_t length() const;
+  intptr_t num_stack_slots() const;
+  HostLocation LocationAt(intptr_t index) const;
+  Representation ResultRepresentation() const;
+
+ private:
+  const TypedData& typed_data_;
+
+  static const intptr_t kOffsetNumArguments = 0;
+  static const intptr_t kOffsetNumStackSlots = 1;
+  static const intptr_t kOffsetResultRepresentation = 2;
+  static const intptr_t kOffsetArgumentLocations = 3;
+};
+
+#endif  // defined(TARGET_ARCH_DBC)
+
+// This classes translates the ABI location of arguments into the locations they
+// will inhabit after entry-frame setup in the invocation of a native callback.
+//
+// Native -> Dart callbacks must push all the arguments before executing any
+// Dart code because the reading the Thread from TLS requires calling a native
+// stub, and the argument registers are volatile on all ABIs we support.
+//
+// To avoid complicating initial definitions, all callback arguments are read
+// off the stack from their pushed locations, so this class updates the argument
+// positions to account for this.
+//
+// See 'NativeEntryInstr::EmitNativeCode' for details.
+class CallbackArgumentTranslator : public ValueObject {
+ public:
+  static ZoneGrowableArray<Location>* TranslateArgumentLocations(
+      const ZoneGrowableArray<Location>& arg_locs);
+
+ private:
+  void AllocateArgument(Location arg);
+  Location TranslateArgument(Location arg);
+
+  intptr_t argument_slots_used_ = 0;
+  intptr_t argument_slots_required_ = 0;
+};
+
 }  // namespace ffi
 
 }  // namespace compiler
diff --git a/runtime/vm/compiler/ffi_dbc_trampoline.h b/runtime/vm/compiler/ffi_dbc_trampoline.h
new file mode 100644
index 0000000..656d1e1
--- /dev/null
+++ b/runtime/vm/compiler/ffi_dbc_trampoline.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_COMPILER_FFI_DBC_TRAMPOLINE_H_
+#define RUNTIME_VM_COMPILER_FFI_DBC_TRAMPOLINE_H_
+
+#include "vm/globals.h"
+
+namespace dart {
+
+#if defined(HOST_ARCH_X64) && !defined(HOST_OS_WINDOWS)
+
+// Generic Trampoline for DBC dart:ffi calls. Argument needs to be layed out as
+// a FfiMarshalledArguments.
+extern "C" void FfiTrampolineCall(uint64_t* ffi_marshalled_args);
+
+#else
+
+void FfiTrampolineCall(uint64_t* ffi_marshalled_args) {
+  UNREACHABLE();
+}
+
+#endif  //  defined(HOST_ARCH_X64) && !defined(HOST_OS_WINDOWS)
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_COMPILER_FFI_DBC_TRAMPOLINE_H_
diff --git a/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S b/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S
new file mode 100644
index 0000000..e8d1918
--- /dev/null
+++ b/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S
@@ -0,0 +1,63 @@
+#if defined(_M_X64) || defined(__x86_64__) /* HOST_ARCH_X64 */
+
+.intel_syntax noprefix
+.text
+
+#if defined(__linux__) || defined(__FreeBSD__) /* HOST_OS_LINUX */
+.globl FfiTrampolineCall
+.type FfiTrampolineCall, @function
+FfiTrampolineCall:
+#else /* HOST_OS_MACOS */
+.globl _FfiTrampolineCall
+_FfiTrampolineCall:
+#endif
+
+push  rbx
+mov   rbx,  rdi        /* Save argument in scratch register. */
+
+/* Copy stack arguments. */
+mov   rax,  [rbx+0x78] /* Load number of stack arguments. */
+cmp   rax,  0x0        /* Check if number of stack arguments is 0. */
+jz    .done            /* Skip loop if no stack arguments. */
+add   rbx,  0x78       /* Offset RBX to point to stack arguments */
+.loop:                 /* Copy stack arguments loop. */
+push  [rbx+0x8*rax]    /* Push stack argument. */
+sub   rax,  0x1        /* Decrement stack argument iterator. */
+cmp   rax,  0x0        /* Compare iterator with 0 */
+jnz   .loop            /* Loop while iterator is not 0 */
+sub   rbx,  0x78       /* Restore RBX to original value. */
+.done:                 /* End stack arguments loop. */
+
+/* Copy registers and fpu registers. */
+mov   rdi,  [rbx+0x8]  /* kArg1Reg */
+mov   rsi,  [rbx+0x10] /* kArg2Reg */
+mov   rdx,  [rbx+0x18] /* kArg3Reg */
+mov   rcx,  [rbx+0x20] /* kArg4Reg */
+mov   r8,   [rbx+0x28] /* kArg5Reg */
+mov   r9,   [rbx+0x30] /* kArg6Reg */
+movsd xmm0, [rbx+0x38]
+movsd xmm1, [rbx+0x40]
+movsd xmm2, [rbx+0x48]
+movsd xmm3, [rbx+0x50]
+movsd xmm4, [rbx+0x58]
+movsd xmm5, [rbx+0x60]
+movsd xmm6, [rbx+0x68]
+movsd xmm7, [rbx+0x70]
+
+/* Do call. */
+mov   rax,  [rbx] /* function address */
+call  rax         /* Call the function. */
+
+/* Copy results back. */
+mov   [rbx],   rax  /* Move integer result in kOffsetIntResult */
+movsd [rbx+8], xmm0 /* Move double result in kOffsetDoubleResult */
+
+/* Clean up stack arguments. */
+mov   rax,  [rbx+0x78] /* Load number of stack arguments. */
+imul  rax,  0x8        /* Multiply by stack argument size. */
+add   rsp,  rax        /* Clean up the stack. */
+
+pop   rbx
+ret
+
+#endif /* HOST_ARCH_X64 */
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 07ac0b0..c133f75 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -485,8 +485,19 @@
     LocalVariable* store_expression = MakeTemporary();
     instructions += LoadLocal(store_expression);
     instructions += GuardFieldClass(field_clone, GetNextDeoptId());
-    instructions += LoadLocal(store_expression);
-    instructions += GuardFieldLength(field_clone, GetNextDeoptId());
+
+    // Field length guard can be omitted if it is not needed.
+    // However, it is possible that we were tracking list length previously,
+    // and generated length guards in the past. We need to generate same IL
+    // to keep deopt ids stable, but we can discard generated IL fragment
+    // if length guard is not needed.
+    Fragment length_guard;
+    length_guard += LoadLocal(store_expression);
+    length_guard += GuardFieldLength(field_clone, GetNextDeoptId());
+
+    if (field_clone.needs_length_check()) {
+      instructions += length_guard;
+    }
 
     // If we are tracking exactness of the static type of the field then
     // emit appropriate guard.
@@ -528,8 +539,9 @@
       value->BindsToConstant() ? kNoStoreBarrier : kEmitStoreBarrier;
   StoreIndexedInstr* store = new (Z) StoreIndexedInstr(
       Pop(),  // Array.
-      index, value, emit_store_barrier, Instance::ElementSizeFor(class_id),
-      class_id, kAlignedAccess, DeoptId::kNone, TokenPosition::kNoSource);
+      index, value, emit_store_barrier,
+      compiler::target::Instance::ElementSizeFor(class_id), class_id,
+      kAlignedAccess, DeoptId::kNone, TokenPosition::kNoSource);
   return Fragment(store);
 }
 
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 19b94e1..82204fd 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -26,7 +26,6 @@
 
 namespace kernel {
 
-// 8-bit unsigned operand at bits 8-15.
 BytecodeFlowGraphBuilder::Operand BytecodeFlowGraphBuilder::DecodeOperandA() {
   if (is_generating_interpreter()) {
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
@@ -36,7 +35,6 @@
   }
 }
 
-// 8-bit unsigned operand at bits 16-23.
 BytecodeFlowGraphBuilder::Operand BytecodeFlowGraphBuilder::DecodeOperandB() {
   if (is_generating_interpreter()) {
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
@@ -46,7 +44,6 @@
   }
 }
 
-// 8-bit unsigned operand at bits 24-31.
 BytecodeFlowGraphBuilder::Operand BytecodeFlowGraphBuilder::DecodeOperandC() {
   if (is_generating_interpreter()) {
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
@@ -56,7 +53,6 @@
   }
 }
 
-// 16-bit unsigned operand at bits 16-31.
 BytecodeFlowGraphBuilder::Operand BytecodeFlowGraphBuilder::DecodeOperandD() {
   if (is_generating_interpreter()) {
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
@@ -66,7 +62,24 @@
   }
 }
 
-// 16-bit signed operand at bits 16-31.
+BytecodeFlowGraphBuilder::Operand BytecodeFlowGraphBuilder::DecodeOperandE() {
+  if (is_generating_interpreter()) {
+    UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
+  } else {
+    intptr_t value = KernelBytecode::DecodeE(bytecode_instr_);
+    return Operand(value);
+  }
+}
+
+BytecodeFlowGraphBuilder::Operand BytecodeFlowGraphBuilder::DecodeOperandF() {
+  if (is_generating_interpreter()) {
+    UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
+  } else {
+    intptr_t value = KernelBytecode::DecodeF(bytecode_instr_);
+    return Operand(value);
+  }
+}
+
 BytecodeFlowGraphBuilder::Operand BytecodeFlowGraphBuilder::DecodeOperandX() {
   if (is_generating_interpreter()) {
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
@@ -76,7 +89,15 @@
   }
 }
 
-// 24-bit signed operand at bits 8-31.
+BytecodeFlowGraphBuilder::Operand BytecodeFlowGraphBuilder::DecodeOperandY() {
+  if (is_generating_interpreter()) {
+    UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
+  } else {
+    intptr_t value = KernelBytecode::DecodeY(bytecode_instr_);
+    return Operand(value);
+  }
+}
+
 BytecodeFlowGraphBuilder::Operand BytecodeFlowGraphBuilder::DecodeOperandT() {
   if (is_generating_interpreter()) {
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
@@ -86,22 +107,6 @@
   }
 }
 
-KBCInstr BytecodeFlowGraphBuilder::InstructionAt(
-    intptr_t pc,
-    KernelBytecode::Opcode expect_opcode) {
-  ASSERT(!is_generating_interpreter());
-  ASSERT((0 <= pc) && (pc < bytecode_length_));
-
-  const KBCInstr instr = raw_bytecode_[pc];
-  if (KernelBytecode::DecodeOpcode(instr) != expect_opcode) {
-    FATAL3("Expected bytecode instruction %s, but found %s at %" Pd "",
-           KernelBytecode::NameOf(KernelBytecode::Encode(expect_opcode)),
-           KernelBytecode::NameOf(instr), pc);
-  }
-
-  return instr;
-}
-
 BytecodeFlowGraphBuilder::Constant BytecodeFlowGraphBuilder::ConstantAt(
     Operand entry_index,
     intptr_t add_index) {
@@ -369,17 +374,50 @@
 
 void BytecodeFlowGraphBuilder::BuildInstruction(KernelBytecode::Opcode opcode) {
   switch (opcode) {
-#define BUILD_BYTECODE_CASE(name, encoding, op1, op2, op3)                     \
+#define WIDE_CASE(name) case KernelBytecode::k##name##_Wide:
+#define WIDE_CASE_0(name)
+#define WIDE_CASE_A(name)
+#define WIDE_CASE_D(name) WIDE_CASE(name)
+#define WIDE_CASE_X(name) WIDE_CASE(name)
+#define WIDE_CASE_T(name) WIDE_CASE(name)
+#define WIDE_CASE_A_E(name) WIDE_CASE(name)
+#define WIDE_CASE_A_Y(name) WIDE_CASE(name)
+#define WIDE_CASE_D_F(name) WIDE_CASE(name)
+#define WIDE_CASE_A_B_C(name)
+
+#define BUILD_BYTECODE_CASE(name, encoding, kind, op1, op2, op3)               \
+  BUILD_BYTECODE_CASE_##kind(name, encoding)
+
+#define BUILD_BYTECODE_CASE_OLD(name, encoding)
+#define BUILD_BYTECODE_CASE_WIDE(name, encoding)
+#define BUILD_BYTECODE_CASE_RESV(name, encoding)
+#define BUILD_BYTECODE_CASE_ORDN(name, encoding)                               \
   case KernelBytecode::k##name:                                                \
-    Build##name();                                                             \
+  case KernelBytecode::k##name##_Old:                                          \
+    WIDE_CASE_##encoding(name) Build##name();                                  \
     break;
 
     PUBLIC_KERNEL_BYTECODES_LIST(BUILD_BYTECODE_CASE)
 
+#undef WIDE_CASE
+#undef WIDE_CASE_0
+#undef WIDE_CASE_A
+#undef WIDE_CASE_D
+#undef WIDE_CASE_X
+#undef WIDE_CASE_T
+#undef WIDE_CASE_A_E
+#undef WIDE_CASE_A_Y
+#undef WIDE_CASE_D_F
+#undef WIDE_CASE_A_B_C
 #undef BUILD_BYTECODE_CASE
+#undef BUILD_BYTECODE_CASE_OLD
+#undef BUILD_BYTECODE_CASE_WIDE
+#undef BUILD_BYTECODE_CASE_RESV
+#undef BUILD_BYTECODE_CASE_ORDN
+
     default:
       FATAL1("Unsupported bytecode instruction %s\n",
-             KernelBytecode::NameOf(bytecode_instr_));
+             KernelBytecode::NameOf(opcode));
   }
 }
 
@@ -396,7 +434,7 @@
   const intptr_t num_fixed_params = DecodeOperandA().value();
   ASSERT(num_fixed_params == function().num_fixed_parameters());
 
-  AllocateLocalVariables(DecodeOperandD());
+  AllocateLocalVariables(DecodeOperandE());
   AllocateFixedParameters();
 
   Fragment check_args;
@@ -444,8 +482,12 @@
   ASSERT((num_opt_pos_params == 0) || (num_opt_named_params == 0));
   const intptr_t num_load_const = num_opt_pos_params + 2 * num_opt_named_params;
 
-  const KBCInstr frame_instr =
-      InstructionAt(pc_ + 1 + num_load_const, KernelBytecode::kFrame);
+  const KBCInstr* instr = KernelBytecode::Next(bytecode_instr_);
+  const KBCInstr* frame_instr = instr;
+  for (intptr_t i = 0; i < num_load_const; ++i) {
+    frame_instr = KernelBytecode::Next(frame_instr);
+  }
+  ASSERT(KernelBytecode::IsFrameOpcode(frame_instr));
   const intptr_t num_extra_locals = KernelBytecode::DecodeD(frame_instr);
   const intptr_t num_params =
       num_fixed_params + num_opt_pos_params + num_opt_named_params;
@@ -467,11 +509,12 @@
   }
 
   for (intptr_t i = 0; i < num_opt_pos_params; ++i, ++param) {
-    const KBCInstr load_value_instr =
-        InstructionAt(pc_ + 1 + i, KernelBytecode::kLoadConstant);
-    const Object& default_value =
-        ConstantAt(Operand(KernelBytecode::DecodeD(load_value_instr))).value();
+    const KBCInstr* load_value_instr = instr;
+    instr = KernelBytecode::Next(instr);
+    ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value_instr));
     ASSERT(KernelBytecode::DecodeA(load_value_instr) == param);
+    const Object& default_value =
+        ConstantAt(Operand(KernelBytecode::DecodeE(load_value_instr))).value();
 
     LocalVariable* param_var = AllocateParameter(param, VariableIndex(-param));
     raw_parameters->Add(param_var);
@@ -487,16 +530,17 @@
     temp_var = scratch_var_;
 
     for (intptr_t i = 0; i < num_opt_named_params; ++i, ++param) {
-      const KBCInstr load_name_instr =
-          InstructionAt(pc_ + 1 + i * 2, KernelBytecode::kLoadConstant);
-      const KBCInstr load_value_instr =
-          InstructionAt(pc_ + 1 + i * 2 + 1, KernelBytecode::kLoadConstant);
+      const KBCInstr* load_name_instr = instr;
+      const KBCInstr* load_value_instr = KernelBytecode::Next(load_name_instr);
+      instr = KernelBytecode::Next(load_value_instr);
+      ASSERT(KernelBytecode::IsLoadConstantOpcode(load_name_instr));
+      ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value_instr));
       const String& param_name = String::Cast(
-          ConstantAt(Operand(KernelBytecode::DecodeD(load_name_instr)))
+          ConstantAt(Operand(KernelBytecode::DecodeE(load_name_instr)))
               .value());
       ASSERT(param_name.IsSymbol());
       const Object& default_value =
-          ConstantAt(Operand(KernelBytecode::DecodeD(load_value_instr)))
+          ConstantAt(Operand(KernelBytecode::DecodeE(load_value_instr)))
               .value();
 
       intptr_t param_index = num_fixed_params;
@@ -521,6 +565,8 @@
     }
   }
 
+  ASSERT(instr == frame_instr);
+
   parsed_function()->set_default_parameter_values(default_values);
   parsed_function()->SetRawParameters(raw_parameters);
 
@@ -556,7 +602,7 @@
       PrologueInfo(prologue_entry->block_id(), prologue_exit->block_id() - 1);
 
   // Skip LoadConstant and Frame instructions.
-  pc_ += num_load_const + 1;
+  next_pc_ = pc_ + (KernelBytecode::Next(instr) - bytecode_instr_);
 
   ASSERT(IsStackEmpty());
 }
@@ -585,7 +631,7 @@
   }
 
   const intptr_t expected_num_type_args = DecodeOperandA().value();
-  LocalVariable* type_args_var = LocalVariableAt(DecodeOperandD().value());
+  LocalVariable* type_args_var = LocalVariableAt(DecodeOperandE().value());
   ASSERT(function().IsGeneric());
 
   if (throw_no_such_method_ == nullptr) {
@@ -628,7 +674,8 @@
     store_type_args += B->LoadArgDescriptor();
     store_type_args += B->LoadNativeField(Slot::ArgumentsDescriptor_count());
     store_type_args += B->LoadFpRelativeSlot(
-        kWordSize * (1 + compiler::target::frame_layout.param_end_from_fp),
+        compiler::target::kWordSize *
+            (1 + compiler::target::frame_layout.param_end_from_fp),
         CompileType::CreateNullable(/*is_nullable=*/true, kTypeArgumentsCid));
     store_type_args +=
         B->StoreLocalRaw(TokenPosition::kNoSource, type_args_var);
@@ -710,42 +757,13 @@
   LoadLocal(local_index);
 }
 
-void BytecodeFlowGraphBuilder::BuildIndirectStaticCall() {
-  if (is_generating_interpreter()) {
-    UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
-  }
-
-  const ICData& icdata = ICData::Cast(PopConstant().value());
-
-  const Function& target = Function::ZoneHandle(Z, icdata.GetTargetAt(0));
-  const ArgumentsDescriptor arg_desc(
-      Array::Cast(ConstantAt(DecodeOperandD()).value()));
-  intptr_t argc = DecodeOperandA().value();
-  ASSERT(ic_data_array_->At(icdata.deopt_id())->Original() == icdata.raw());
-
-  ArgumentArray arguments = GetArguments(argc);
-
-  // TODO(alexmarkov): pass ICData::kSuper for super calls
-  // (need to distinguish them in bytecode).
-  StaticCallInstr* call = new (Z) StaticCallInstr(
-      position_, target, arg_desc.TypeArgsLen(),
-      Array::ZoneHandle(Z, arg_desc.GetArgumentNames()), arguments,
-      *ic_data_array_, icdata.deopt_id(), ICData::kStatic);
-
-  // TODO(alexmarkov): add type info
-  // SetResultTypeForStaticCall(call, target, argument_count, result_type);
-
-  code_ <<= call;
-  B->Push(call);
-}
-
 void BytecodeFlowGraphBuilder::BuildDirectCall() {
   if (is_generating_interpreter()) {
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
   }
 
   const Function& target = Function::Cast(ConstantAt(DecodeOperandD()).value());
-  const intptr_t argc = DecodeOperandA().value();
+  const intptr_t argc = DecodeOperandF().value();
 
   // Recognize identical() call.
   // Note: similar optimization is performed in AST flow graph builder - see
@@ -795,18 +813,20 @@
       Array::Cast(ConstantAt(DecodeOperandD(), 1).value());
   const ArgumentsDescriptor arg_desc(arg_desc_array);
 
-  const intptr_t argc = DecodeOperandA().value();
+  const intptr_t argc = DecodeOperandF().value();
   Token::Kind token_kind = MethodTokenRecognizer::RecognizeTokenKind(name);
 
   intptr_t checked_argument_count = 1;
-  if ((token_kind != Token::kILLEGAL) ||
-      (name.raw() ==
-       Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()).raw())) {
+  if (token_kind != Token::kILLEGAL) {
     intptr_t argument_count = arg_desc.Count();
     ASSERT(argument_count <= 2);
     checked_argument_count = argument_count;
-  } else if (name.raw() ==
-             Library::PrivateCoreLibName(Symbols::_instanceOf()).raw()) {
+  } else if (Library::IsPrivateCoreLibName(name,
+                                           Symbols::_simpleInstanceOf())) {
+    ASSERT(arg_desc.Count() == 2);
+    checked_argument_count = 2;
+    token_kind = Token::kIS;
+  } else if (Library::IsPrivateCoreLibName(name, Symbols::_instanceOf())) {
     token_kind = Token::kIS;
   }
 
@@ -843,7 +863,7 @@
   const ICData& icdata = ICData::Cast(ConstantAt(DecodeOperandD()).value());
   ASSERT(ic_data_array_->At(icdata.deopt_id())->Original() == icdata.raw());
 
-  const intptr_t argc = DecodeOperandA().value();
+  const intptr_t argc = DecodeOperandF().value();
   const ArgumentsDescriptor arg_desc(
       Array::Handle(Z, icdata.arguments_descriptor()));
 
@@ -1103,7 +1123,7 @@
   }
 
   const intptr_t context_id = DecodeOperandA().value();
-  const intptr_t num_context_vars = DecodeOperandD().value();
+  const intptr_t num_context_vars = DecodeOperandE().value();
 
   auto& context_variables = CompilerState::Current().GetDummyContextVariables(
       context_id, num_context_vars);
@@ -1117,7 +1137,7 @@
 
   LoadStackSlots(1);
   const intptr_t context_id = DecodeOperandA().value();
-  const intptr_t num_context_vars = DecodeOperandD().value();
+  const intptr_t num_context_vars = DecodeOperandE().value();
 
   auto& context_variables = CompilerState::Current().GetDummyContextVariables(
       context_id, num_context_vars);
@@ -1213,7 +1233,7 @@
 
   LoadStackSlots(2);
   const intptr_t context_id = DecodeOperandA().value();
-  const intptr_t var_index = DecodeOperandD().value();
+  const intptr_t var_index = DecodeOperandE().value();
 
   auto var =
       CompilerState::Current().GetDummyCapturedVariable(context_id, var_index);
@@ -1228,7 +1248,7 @@
 
   LoadStackSlots(1);
   const intptr_t context_id = DecodeOperandA().value();
-  const intptr_t var_index = DecodeOperandD().value();
+  const intptr_t var_index = DecodeOperandE().value();
 
   auto var =
       CompilerState::Current().GetDummyCapturedVariable(context_id, var_index);
@@ -1298,7 +1318,7 @@
   }
 
   const TypeArguments& type_args =
-      TypeArguments::Cast(ConstantAt(DecodeOperandD()).value());
+      TypeArguments::Cast(ConstantAt(DecodeOperandE()).value());
 
   LoadStackSlots(2);
   code_ += B->InstantiateTypeArguments(type_args);
@@ -1372,9 +1392,8 @@
     // (if it contains jumps) and generated. The problem is that generated
     // code may expect values left on the stack from unreachable
     // (and not generated) code which immediately follows this Jump.
-    const intptr_t target_pc = pc_ + DecodeOperandT().value();
-    ASSERT(target_pc > pc_);
-    pc_ = target_pc - 1;
+    next_pc_ = pc_ + DecodeOperandT().value();
+    ASSERT(next_pc_ > pc_);
   }
 }
 
@@ -1407,24 +1426,22 @@
 
   LoadStackSlots(2);
 
-  TargetEntryInstr* eq_branch = nullptr;
-  TargetEntryInstr* ne_branch = nullptr;
-  code_ += B->BranchIfStrictEqual(&eq_branch, &ne_branch);
-
-  TargetEntryInstr* then_entry =
-      (cmp_kind == Token::kEQ) ? eq_branch : ne_branch;
-  TargetEntryInstr* else_entry =
-      (cmp_kind == Token::kEQ) ? ne_branch : eq_branch;
+  // Fallthrough should correspond to 'then' branch target.
+  // This results in a slightly better regalloc.
+  TargetEntryInstr* then_entry = nullptr;
+  TargetEntryInstr* else_entry = nullptr;
+  code_ += B->BranchIfEqual(&then_entry, &else_entry,
+                            /* negate = */ (cmp_kind == Token::kEQ));
 
   const intptr_t target_pc = pc_ + DecodeOperandT().value();
   JoinEntryInstr* join = jump_targets_.Lookup(target_pc);
   ASSERT(join != nullptr);
 
-  code_ = Fragment(then_entry);
+  code_ = Fragment(else_entry);
   code_ += B->Goto(join);
   PropagateStackState(target_pc);
 
-  code_ = Fragment(else_entry);
+  code_ = Fragment(then_entry);
 }
 
 void BytecodeFlowGraphBuilder::BuildJumpIfEqStrict() {
@@ -1522,7 +1539,7 @@
   }
 
   code_ += B->LoadLocal(special_var);
-  StoreLocal(DecodeOperandX());
+  StoreLocal(DecodeOperandY());
   code_ += B->Drop();
 }
 
@@ -1784,15 +1801,22 @@
   return join;
 }
 
-bool BytecodeFlowGraphBuilder::RequiresScratchVar(KBCInstr instr) {
+bool BytecodeFlowGraphBuilder::RequiresScratchVar(const KBCInstr* instr) {
   switch (KernelBytecode::DecodeOpcode(instr)) {
     case KernelBytecode::kEntryOptional:
+    case KernelBytecode::kEntryOptional_Old:
       return KernelBytecode::DecodeC(instr) > 0;
+
     case KernelBytecode::kEqualsNull:
+    case KernelBytecode::kEqualsNull_Old:
       return true;
+
     case KernelBytecode::kNativeCall:
+    case KernelBytecode::kNativeCall_Wide:
+    case KernelBytecode::kNativeCall_Old:
       return MethodRecognizer::RecognizeKind(function()) ==
              MethodRecognizer::kListFactory;
+
     default:
       return false;
   }
@@ -1802,14 +1826,13 @@
     const PcDescriptors& descriptors,
     const ExceptionHandlers& handlers,
     GraphEntryInstr* graph_entry) {
-  for (intptr_t pc = 0; pc < bytecode_length_; ++pc) {
-    const KBCInstr instr = raw_bytecode_[pc];
+  for (intptr_t pc = 0; pc < bytecode_length_;) {
+    const KBCInstr* instr = &(raw_bytecode_[pc]);
 
     if (KernelBytecode::IsJumpOpcode(instr)) {
       const intptr_t target = pc + KernelBytecode::DecodeT(instr);
       EnsureControlFlowJoin(descriptors, target);
-    } else if ((KernelBytecode::DecodeOpcode(instr) ==
-                KernelBytecode::kCheckStack) &&
+    } else if (KernelBytecode::IsCheckStackOpcode(instr) &&
                (KernelBytecode::DecodeA(instr) != 0)) {
       // (dartbug.com/36590) BlockEntryInstr::FindOsrEntryAndRelink assumes
       // that CheckStackOverflow instruction is at the beginning of a join
@@ -1822,6 +1845,8 @@
           LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                         Symbols::ExprTemp(), Object::dynamic_type());
     }
+
+    pc += (KernelBytecode::Next(instr) - instr);
   }
 
   PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
@@ -1858,7 +1883,7 @@
     JoinEntryInstr* join = EnsureControlFlowJoin(descriptors, handler_pc);
 
     // Make sure exception handler starts with SetFrame bytecode instruction.
-    InstructionAt(handler_pc, KernelBytecode::kSetFrame);
+    ASSERT(KernelBytecode::IsSetFrameOpcode(&(raw_bytecode_[handler_pc])));
 
     const Array& handler_types =
         Array::ZoneHandle(Z, handlers.GetHandledTypes(try_index));
@@ -1879,7 +1904,7 @@
   const Bytecode& bytecode = Bytecode::Handle(Z, function().bytecode());
 
   object_pool_ = bytecode.object_pool();
-  raw_bytecode_ = reinterpret_cast<KBCInstr*>(bytecode.PayloadStart());
+  raw_bytecode_ = reinterpret_cast<const KBCInstr*>(bytecode.PayloadStart());
   bytecode_length_ = bytecode.Size() / sizeof(KBCInstr);
 
   ProcessICDataInObjectPool(object_pool_);
@@ -1902,8 +1927,9 @@
 
   code_ = Fragment(normal_entry);
 
-  for (pc_ = 0; pc_ < bytecode_length_; ++pc_) {
-    bytecode_instr_ = raw_bytecode_[pc_];
+  for (pc_ = 0; pc_ < bytecode_length_; pc_ = next_pc_) {
+    bytecode_instr_ = &(raw_bytecode_[pc_]);
+    next_pc_ = pc_ + (KernelBytecode::Next(bytecode_instr_) - bytecode_instr_);
 
     JoinEntryInstr* join = jump_targets_.Lookup(pc_);
     if (join != nullptr) {
@@ -1926,7 +1952,7 @@
     }
 
     while (update_position &&
-           pc_ >= source_pos_iter.BytecodeInstructionIndex()) {
+           static_cast<uword>(pc_) >= source_pos_iter.PcOffset()) {
       position_ = source_pos_iter.TokenPos();
       update_position = source_pos_iter.MoveNext();
     }
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h
index c085374..833deb2 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h
@@ -31,10 +31,8 @@
         parsed_function_(parsed_function),
         ic_data_array_(ic_data_array),
         object_pool_(ObjectPool::Handle(zone_)),
-        raw_bytecode_(nullptr),
         bytecode_length_(0),
         pc_(0),
-        bytecode_instr_(KernelBytecode::kTrap),
         position_(TokenPosition::kNoSource),
         local_vars_(zone_, 0),
         parameters_(zone_, 0),
@@ -110,9 +108,11 @@
   Operand DecodeOperandB();
   Operand DecodeOperandC();
   Operand DecodeOperandD();
+  Operand DecodeOperandE();
+  Operand DecodeOperandF();
   Operand DecodeOperandX();
+  Operand DecodeOperandY();
   Operand DecodeOperandT();
-  KBCInstr InstructionAt(intptr_t pc, KernelBytecode::Opcode expect_opcode);
   Constant ConstantAt(Operand entry_index, intptr_t add_index = 0);
   void PushConstant(Constant constant);
   Constant PopConstant();
@@ -142,7 +142,8 @@
 
   void BuildInstruction(KernelBytecode::Opcode opcode);
 
-#define DECLARE_BUILD_METHOD(name, encoding, op1, op2, op3) void Build##name();
+#define DECLARE_BUILD_METHOD(name, encoding, kind, op1, op2, op3)              \
+  void Build##name();
   KERNEL_BYTECODES_LIST(DECLARE_BUILD_METHOD)
 #undef DECLARE_BUILD_METHOD
 
@@ -150,7 +151,7 @@
   intptr_t GetTryIndex(const PcDescriptors& descriptors, intptr_t pc);
   JoinEntryInstr* EnsureControlFlowJoin(const PcDescriptors& descriptors,
                                         intptr_t pc);
-  bool RequiresScratchVar(KBCInstr instr);
+  bool RequiresScratchVar(const KBCInstr* instr);
   void CollectControlFlow(const PcDescriptors& descriptors,
                           const ExceptionHandlers& handlers,
                           GraphEntryInstr* graph_entry);
@@ -173,10 +174,11 @@
   ParsedFunction* parsed_function_;
   ZoneGrowableArray<const ICData*>* ic_data_array_;
   ObjectPool& object_pool_;
-  KBCInstr* raw_bytecode_;
+  const KBCInstr* raw_bytecode_ = nullptr;
   intptr_t bytecode_length_;
   intptr_t pc_;
-  KBCInstr bytecode_instr_;
+  intptr_t next_pc_ = -1;
+  const KBCInstr* bytecode_instr_ = nullptr;
   TokenPosition position_;  // TODO(alexmarkov): Set/update.
   Fragment code_;
   ZoneGrowableArray<LocalVariable*> local_vars_;
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index c2a6590..c180689 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -12,9 +12,11 @@
 #include "vm/compiler/frontend/bytecode_scope_builder.h"
 #include "vm/constants_kbc.h"
 #include "vm/dart_entry.h"
+#include "vm/debugger.h"
 #include "vm/longjump.h"
 #include "vm/object_store.h"
 #include "vm/reusable_handles.h"
+#include "vm/stack_frame_kbc.h"
 #include "vm/timeline.h"
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -34,61 +36,6 @@
     : MetadataHelper(helper, tag(), /* precompiler_only = */ false),
       active_class_(active_class) {}
 
-bool BytecodeMetadataHelper::HasBytecode(intptr_t node_offset) {
-  const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
-  return (md_offset >= 0);
-}
-
-void BytecodeMetadataHelper::ReadMetadata(const Function& function) {
-#if defined(SUPPORT_TIMELINE)
-  TimelineDurationScope tds(Thread::Current(), Timeline::GetCompilerStream(),
-                            "BytecodeMetadataHelper::ReadMetadata");
-  // This increases bytecode reading time by ~7%, so only keep it around for
-  // debugging.
-#if defined(DEBUG)
-  tds.SetNumArguments(1);
-  tds.CopyArgument(0, "Function", function.ToQualifiedCString());
-#endif  // defined(DEBUG)
-#endif  // !defined(SUPPORT_TIMELINE)
-
-  switch (function.kind()) {
-    case RawFunction::kImplicitGetter:
-      function.AttachBytecode(Object::implicit_getter_bytecode());
-      return;
-    case RawFunction::kImplicitSetter:
-      function.AttachBytecode(Object::implicit_setter_bytecode());
-      return;
-    case RawFunction::kMethodExtractor:
-      function.AttachBytecode(Object::method_extractor_bytecode());
-      return;
-    default: {
-    }
-  }
-
-  intptr_t code_offset = 0;
-  if (function.is_declared_in_bytecode()) {
-    code_offset = function.bytecode_offset();
-    if (code_offset == 0) {
-      return;
-    }
-  } else {
-    const intptr_t node_offset = function.kernel_offset();
-    code_offset = GetNextMetadataPayloadOffset(node_offset);
-    if (code_offset < 0) {
-      return;
-    }
-  }
-
-  ASSERT(Thread::Current()->IsMutatorThread());
-
-  BytecodeComponentData bytecode_component(
-      Array::Handle(helper_->zone_, GetBytecodeComponent()));
-  BytecodeReaderHelper bytecode_reader(helper_, active_class_,
-                                       &bytecode_component);
-
-  bytecode_reader.ReadCode(function, code_offset);
-}
-
 void BytecodeMetadataHelper::ParseBytecodeFunction(
     ParsedFunction* parsed_function) {
   TIMELINE_DURATION(Thread::Current(), CompilerVerbose,
@@ -103,14 +50,16 @@
   if (function.HasBytecode() &&
       (function.kind() != RawFunction::kImplicitGetter) &&
       (function.kind() != RawFunction::kImplicitSetter) &&
-      (function.kind() != RawFunction::kMethodExtractor)) {
+      (function.kind() != RawFunction::kImplicitStaticGetter) &&
+      (function.kind() != RawFunction::kMethodExtractor) &&
+      (function.kind() != RawFunction::kInvokeFieldDispatcher) &&
+      (function.kind() != RawFunction::kNoSuchMethodDispatcher)) {
     return;
   }
 
   BytecodeComponentData bytecode_component(
       Array::Handle(helper_->zone_, GetBytecodeComponent()));
-  BytecodeReaderHelper bytecode_reader(helper_, active_class_,
-                                       &bytecode_component);
+  BytecodeReaderHelper bytecode_reader(&H, active_class_, &bytecode_component);
 
   bytecode_reader.ParseBytecodeFunction(parsed_function, function);
 }
@@ -131,33 +80,17 @@
 
   BytecodeComponentData bytecode_component(
       Array::Handle(helper_->zone_, GetBytecodeComponent()));
-  BytecodeReaderHelper bytecode_reader(helper_, active_class_,
-                                       &bytecode_component);
+  BytecodeReaderHelper bytecode_reader(&H, active_class_, &bytecode_component);
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
+  AlternativeReadingScope alt(&bytecode_reader.reader(), md_offset);
 
-  intptr_t members_offset = helper_->reader_.ReadUInt();
+  intptr_t members_offset = bytecode_reader.reader().ReadUInt();
 
   bytecode_reader.ReadMembers(cls, members_offset, discard_fields);
 
   return true;
 }
 
-RawObject* BytecodeMetadataHelper::ReadAnnotation(intptr_t annotation_offset) {
-  ASSERT(Thread::Current()->IsMutatorThread());
-
-  BytecodeComponentData bytecode_component(
-      Array::Handle(helper_->zone_, GetBytecodeComponent()));
-  BytecodeReaderHelper bytecode_reader(helper_, active_class_,
-                                       &bytecode_component);
-
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              annotation_offset);
-
-  return bytecode_reader.ReadObject();
-}
-
 RawLibrary* BytecodeMetadataHelper::GetMainLibrary() {
   const intptr_t md_offset = GetComponentMetadataPayloadOffset();
   if (md_offset < 0) {
@@ -171,10 +104,8 @@
     return Library::null();
   }
 
-  BytecodeReaderHelper bytecode_reader(helper_, active_class_,
-                                       &bytecode_component);
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              main_offset);
+  BytecodeReaderHelper bytecode_reader(&H, active_class_, &bytecode_component);
+  AlternativeReadingScope alt(&bytecode_reader.reader(), main_offset);
   return bytecode_reader.ReadMain();
 }
 
@@ -193,22 +124,23 @@
     return Array::null();
   }
 
-  BytecodeReaderHelper component_reader(helper_, nullptr, nullptr);
+  BytecodeReaderHelper component_reader(&H, nullptr, nullptr);
   return component_reader.ReadBytecodeComponent(md_offset);
 }
 
 BytecodeReaderHelper::BytecodeReaderHelper(
-    KernelReaderHelper* helper,
+    TranslationHelper* translation_helper,
     ActiveClass* active_class,
     BytecodeComponentData* bytecode_component)
-    : helper_(helper),
-      translation_helper_(helper->translation_helper_),
+    : reader_(translation_helper->metadata_payloads()),
+      translation_helper_(*translation_helper),
       active_class_(active_class),
-      zone_(helper_->zone_),
+      thread_(translation_helper->thread()),
+      zone_(translation_helper->zone()),
       bytecode_component_(bytecode_component),
-      scoped_function_(Function::Handle(helper_->zone_)),
-      scoped_function_name_(String::Handle(helper_->zone_)),
-      scoped_function_class_(Class::Handle(helper_->zone_)) {}
+      scoped_function_(Function::Handle(translation_helper->zone())),
+      scoped_function_name_(String::Handle(translation_helper->zone())),
+      scoped_function_class_(Class::Handle(translation_helper->zone())) {}
 
 void BytecodeReaderHelper::ReadCode(const Function& function,
                                     intptr_t code_offset) {
@@ -217,14 +149,14 @@
          !function.IsImplicitSetterFunction());
   ASSERT(code_offset > 0);
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              code_offset);
+  AlternativeReadingScope alt(&reader_, code_offset);
 
-  const intptr_t flags = helper_->reader_.ReadUInt();
+  const intptr_t flags = reader_.ReadUInt();
   const bool has_exceptions_table =
       (flags & Code::kHasExceptionsTableFlag) != 0;
   const bool has_source_positions =
       (flags & Code::kHasSourcePositionsFlag) != 0;
+  const bool has_local_variables = (flags & Code::kHasLocalVariablesFlag) != 0;
   const bool has_nullable_fields = (flags & Code::kHasNullableFieldsFlag) != 0;
   const bool has_closures = (flags & Code::kHasClosuresFlag) != 0;
   const bool has_parameters_flags = (flags & Code::kHasParameterFlagsFlag) != 0;
@@ -234,23 +166,23 @@
       (flags & Code::kHasDefaultFunctionTypeArgsFlag) != 0;
 
   if (has_parameters_flags) {
-    intptr_t num_params = helper_->reader_.ReadUInt();
+    intptr_t num_params = reader_.ReadUInt();
     ASSERT(num_params ==
            function.NumParameters() - function.NumImplicitParameters());
     for (intptr_t i = 0; i < num_params; ++i) {
-      helper_->reader_.ReadUInt();
+      reader_.ReadUInt();
     }
   }
   if (has_forwarding_stub_target) {
-    helper_->reader_.ReadUInt();
+    reader_.ReadUInt();
   }
   if (has_default_function_type_args) {
-    helper_->reader_.ReadUInt();
+    reader_.ReadUInt();
   }
 
   intptr_t num_closures = 0;
   if (has_closures) {
-    num_closures = helper_->ReadListLength();
+    num_closures = reader_.ReadListLength();
     closures_ = &Array::Handle(Z, Array::New(num_closures));
     for (intptr_t i = 0; i < num_closures; i++) {
       ReadClosureDeclaration(function, i);
@@ -258,7 +190,7 @@
   }
 
   // Create object pool and read pool entries.
-  const intptr_t obj_count = helper_->reader_.ReadListLength();
+  const intptr_t obj_count = reader_.ReadListLength();
   const ObjectPool& pool = ObjectPool::Handle(Z, ObjectPool::New(obj_count));
 
   {
@@ -266,7 +198,7 @@
     // ICData objects.
     //
     // TODO(alexmarkov): allocate deopt_ids for closures separately
-    DeoptIdScope deopt_id_scope(H.thread(), 0);
+    DeoptIdScope deopt_id_scope(thread_, 0);
 
     ReadConstantPool(function, pool);
   }
@@ -274,12 +206,14 @@
   // Read bytecode and attach to function.
   const Bytecode& bytecode = Bytecode::Handle(Z, ReadBytecode(pool));
   function.AttachBytecode(bytecode);
-  ASSERT(bytecode.GetBinary(Z) == helper_->reader_.typed_data()->raw());
+  ASSERT(bytecode.GetBinary(Z) == reader_.typed_data()->raw());
 
   ReadExceptionsTable(bytecode, has_exceptions_table);
 
   ReadSourcePositions(bytecode, has_source_positions);
 
+  ReadLocalVariables(bytecode, has_local_variables);
+
   if (FLAG_dump_kernel_bytecode) {
     KernelBytecodeDisassembler::Disassemble(function);
   }
@@ -288,7 +222,7 @@
   // Record the corresponding stores if field guards are enabled.
   if (has_nullable_fields) {
     ASSERT(function.IsGenerativeConstructor());
-    const intptr_t num_fields = helper_->ReadListLength();
+    const intptr_t num_fields = reader_.ReadListLength();
     if (I->use_field_guards()) {
       Field& field = Field::Handle(Z);
       for (intptr_t i = 0; i < num_fields; i++) {
@@ -309,21 +243,25 @@
     for (intptr_t i = 0; i < num_closures; i++) {
       closure ^= closures_->At(i);
 
-      const intptr_t flags = helper_->reader_.ReadUInt();
+      const intptr_t flags = reader_.ReadUInt();
       const bool has_exceptions_table =
-          (flags & Code::kHasExceptionsTableFlag) != 0;
+          (flags & ClosureCode::kHasExceptionsTableFlag) != 0;
       const bool has_source_positions =
-          (flags & Code::kHasSourcePositionsFlag) != 0;
+          (flags & ClosureCode::kHasSourcePositionsFlag) != 0;
+      const bool has_local_variables =
+          (flags & ClosureCode::kHasLocalVariablesFlag) != 0;
 
       // Read closure bytecode and attach to closure function.
       closure_bytecode = ReadBytecode(pool);
       closure.AttachBytecode(closure_bytecode);
-      ASSERT(bytecode.GetBinary(Z) == helper_->reader_.typed_data()->raw());
+      ASSERT(bytecode.GetBinary(Z) == reader_.typed_data()->raw());
 
       ReadExceptionsTable(closure_bytecode, has_exceptions_table);
 
       ReadSourcePositions(closure_bytecode, has_source_positions);
 
+      ReadLocalVariables(closure_bytecode, has_local_variables);
+
       if (FLAG_dump_kernel_bytecode) {
         KernelBytecodeDisassembler::Disassemble(closure);
       }
@@ -333,11 +271,14 @@
 
 void BytecodeReaderHelper::ReadClosureDeclaration(const Function& function,
                                                   intptr_t closureIndex) {
-  const int kHasOptionalPositionalParams = 1 << 0;
-  const int kHasOptionalNamedParams = 1 << 1;
-  const int kHasTypeParams = 1 << 2;
+  // Closure flags, must be in sync with ClosureDeclaration constants in
+  // pkg/vm/lib/bytecode/declarations.dart.
+  const int kHasOptionalPositionalParamsFlag = 1 << 0;
+  const int kHasOptionalNamedParamsFlag = 1 << 1;
+  const int kHasTypeParamsFlag = 1 << 2;
+  const int kHasSourcePositionsFlag = 1 << 3;
 
-  const intptr_t flags = helper_->reader_.ReadUInt();
+  const intptr_t flags = reader_.ReadUInt();
 
   Object& parent = Object::Handle(Z, ReadObject());
   if (!parent.IsFunction()) {
@@ -350,18 +291,27 @@
   String& name = String::CheckedHandle(Z, ReadObject());
   ASSERT(name.IsSymbol());
 
+  TokenPosition position = TokenPosition::kNoSource;
+  TokenPosition end_position = TokenPosition::kNoSource;
+  if ((flags & kHasSourcePositionsFlag) != 0) {
+    position = reader_.ReadPosition();
+    end_position = reader_.ReadPosition();
+  }
+
   const Function& closure = Function::Handle(
-      Z, Function::NewClosureFunction(name, Function::Cast(parent),
-                                      TokenPosition::kNoSource));
+      Z, Function::NewClosureFunction(name, Function::Cast(parent), position));
+
+  closure.set_is_declared_in_bytecode(true);
+  closure.set_end_token_pos(end_position);
 
   closures_->SetAt(closureIndex, closure);
 
-  Type& signature_type =
-      Type::Handle(Z, ReadFunctionSignature(
-                          closure, (flags & kHasOptionalPositionalParams) != 0,
-                          (flags & kHasOptionalNamedParams) != 0,
-                          (flags & kHasTypeParams) != 0,
-                          /* has_positional_param_names = */ true));
+  Type& signature_type = Type::Handle(
+      Z, ReadFunctionSignature(closure,
+                               (flags & kHasOptionalPositionalParamsFlag) != 0,
+                               (flags & kHasOptionalNamedParamsFlag) != 0,
+                               (flags & kHasTypeParamsFlag) != 0,
+                               /* has_positional_param_names = */ true));
 
   closure.SetSignatureType(signature_type);
 }
@@ -376,17 +326,14 @@
 
   if (has_type_params) {
     ReadTypeParametersDeclaration(Class::Handle(Z), func);
-    function_type_type_parameters_ =
-        &TypeArguments::Handle(Z, func.type_parameters());
   }
 
   const intptr_t kImplicitClosureParam = 1;
-  const intptr_t num_params =
-      kImplicitClosureParam + helper_->reader_.ReadUInt();
+  const intptr_t num_params = kImplicitClosureParam + reader_.ReadUInt();
 
   intptr_t num_required_params = num_params;
   if (has_optional_positional_params || has_optional_named_params) {
-    num_required_params = kImplicitClosureParam + helper_->reader_.ReadUInt();
+    num_required_params = kImplicitClosureParam + reader_.ReadUInt();
   }
 
   func.set_num_fixed_parameters(num_required_params);
@@ -423,7 +370,7 @@
 
   // Finalize function type.
   type = func.SignatureType();
-  type ^= ClassFinalizer::FinalizeType(*(active_class_->klass), type);
+  type = ClassFinalizer::FinalizeType(*(active_class_->klass), type);
   return Type::Cast(type).raw();
 }
 
@@ -432,7 +379,7 @@
     const Function& parameterized_function) {
   ASSERT(parameterized_class.IsNull() != parameterized_function.IsNull());
 
-  const intptr_t num_type_params = helper_->reader_.ReadUInt();
+  const intptr_t num_type_params = reader_.ReadUInt();
   ASSERT(num_type_params > 0);
 
   // First setup the type parameters, so if any of the following code uses it
@@ -459,6 +406,7 @@
     // Do not set type parameters for factories, as VM uses class type
     // parameters instead.
     parameterized_function.set_type_parameters(type_parameters);
+    function_type_type_parameters_ = &type_parameters;
   }
 
   // Step b) Fill in the bounds of all [TypeParameter]s.
@@ -527,18 +475,18 @@
   const String* simpleInstanceOf = nullptr;
   const intptr_t obj_count = pool.Length();
   for (intptr_t i = 0; i < obj_count; ++i) {
-    const intptr_t tag = helper_->ReadTag();
+    const intptr_t tag = reader_.ReadTag();
     switch (tag) {
       case ConstantPoolTag::kInvalid:
         UNREACHABLE();
       case ConstantPoolTag::kICData: {
-        intptr_t flags = helper_->ReadByte();
+        intptr_t flags = reader_.ReadByte();
         InvocationKind kind =
             static_cast<InvocationKind>(flags & kInvocationKindMask);
         bool isDynamic = (flags & kFlagDynamic) != 0;
         name ^= ReadObject();
         ASSERT(name.IsSymbol());
-        intptr_t arg_desc_index = helper_->ReadUInt();
+        intptr_t arg_desc_index = reader_.ReadUInt();
         ASSERT(arg_desc_index < i);
         array ^= pool.ObjectAt(arg_desc_index);
         if (simpleInstanceOf == nullptr) {
@@ -568,7 +516,7 @@
         obj =
             ICData::New(function, name,
                         array,  // Arguments descriptor.
-                        H.thread()->compiler_state().GetNextDeoptId(),
+                        thread_->compiler_state().GetNextDeoptId(),
                         checked_argument_count, ICData::RebindRule::kInstance);
       } break;
       case ConstantPoolTag::kStaticField:
@@ -601,7 +549,7 @@
         ASSERT(obj.IsAbstractType());
         break;
       case ConstantPoolTag::kClosureFunction: {
-        intptr_t closure_index = helper_->ReadUInt();
+        intptr_t closure_index = reader_.ReadUInt();
         obj = closures_->At(closure_index);
         ASSERT(obj.IsFunction());
       } break;
@@ -666,11 +614,18 @@
   TIMELINE_DURATION(Thread::Current(), CompilerVerbose,
                     "BytecodeReaderHelper::ReadBytecode");
 #endif  // defined(SUPPORT_TIMELINE)
-  intptr_t size = helper_->ReadUInt();
-  intptr_t offset = Utils::RoundUp(helper_->reader_.offset(), sizeof(KBCInstr));
-  const uint8_t* data = helper_->reader_.BufferAt(offset);
-  ASSERT(Utils::IsAligned(data, sizeof(KBCInstr)));
-  helper_->reader_.set_offset(offset + size);
+  intptr_t size = reader_.ReadUInt();
+  intptr_t offset = reader_.offset();
+
+  static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 7,
+                "Cleanup support for old bytecode format versions");
+  if (bytecode_component_->GetVersion() < 7) {
+    const intptr_t kAlignment = 4;
+    offset = Utils::RoundUp(offset, kAlignment);
+  }
+
+  const uint8_t* data = reader_.BufferAt(offset);
+  reader_.set_offset(offset + size);
 
   // Create and return bytecode object.
   return Bytecode::New(reinterpret_cast<uword>(data), size, offset, pool);
@@ -684,7 +639,7 @@
 #endif
 
   const intptr_t try_block_count =
-      has_exceptions_table ? helper_->reader_.ReadListLength() : 0;
+      has_exceptions_table ? reader_.ReadListLength() : 0;
   if (try_block_count > 0) {
     const ObjectPool& pool = ObjectPool::Handle(Z, bytecode.object_pool());
     AbstractType& handler_type = AbstractType::Handle(Z);
@@ -693,28 +648,35 @@
     ExceptionHandlerList* exception_handlers_list =
         new (Z) ExceptionHandlerList();
 
+    static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 7,
+                  "Cleanup support for old bytecode format versions");
+    const int kPCShifter = (bytecode_component_->GetVersion() < 7) ? 2 : 0;
+
     // Encoding of ExceptionsTable is described in
     // pkg/vm/lib/bytecode/exceptions.dart.
     for (intptr_t try_index = 0; try_index < try_block_count; try_index++) {
-      intptr_t outer_try_index_plus1 = helper_->reader_.ReadUInt();
+      intptr_t outer_try_index_plus1 = reader_.ReadUInt();
       intptr_t outer_try_index = outer_try_index_plus1 - 1;
       // PcDescriptors are expressed in terms of return addresses.
-      intptr_t start_pc = KernelBytecode::BytecodePcToOffset(
-          helper_->reader_.ReadUInt(), /* is_return_address = */ true);
-      intptr_t end_pc = KernelBytecode::BytecodePcToOffset(
-          helper_->reader_.ReadUInt(), /* is_return_address = */ true);
-      intptr_t handler_pc = KernelBytecode::BytecodePcToOffset(
-          helper_->reader_.ReadUInt(), /* is_return_address = */ false);
-      uint8_t flags = helper_->reader_.ReadByte();
+      intptr_t start_pc =
+          KernelBytecode::BytecodePcToOffset(reader_.ReadUInt() << kPCShifter,
+                                             /* is_return_address = */ true);
+      intptr_t end_pc =
+          KernelBytecode::BytecodePcToOffset(reader_.ReadUInt() << kPCShifter,
+                                             /* is_return_address = */ true);
+      intptr_t handler_pc =
+          KernelBytecode::BytecodePcToOffset(reader_.ReadUInt() << kPCShifter,
+                                             /* is_return_address = */ false);
+      uint8_t flags = reader_.ReadByte();
       const uint8_t kFlagNeedsStackTrace = 1 << 0;
       const uint8_t kFlagIsSynthetic = 1 << 1;
       const bool needs_stacktrace = (flags & kFlagNeedsStackTrace) != 0;
       const bool is_generated = (flags & kFlagIsSynthetic) != 0;
-      intptr_t type_count = helper_->reader_.ReadListLength();
+      intptr_t type_count = reader_.ReadListLength();
       ASSERT(type_count > 0);
       handler_types = Array::New(type_count, Heap::kOld);
       for (intptr_t i = 0; i < type_count; i++) {
-        intptr_t type_index = helper_->reader_.ReadUInt();
+        intptr_t type_index = reader_.ReadUInt();
         ASSERT(type_index < pool.Length());
         handler_type ^= pool.ObjectAt(type_index);
         handler_types.SetAt(i, handler_type);
@@ -749,11 +711,26 @@
     return;
   }
 
-  intptr_t offset = helper_->reader_.ReadUInt();
+  intptr_t offset = reader_.ReadUInt();
   bytecode.set_source_positions_binary_offset(
       bytecode_component_->GetSourcePositionsOffset() + offset);
 }
 
+void BytecodeReaderHelper::ReadLocalVariables(const Bytecode& bytecode,
+                                              bool has_local_variables) {
+  if (!has_local_variables) {
+    return;
+  }
+
+  intptr_t offset = reader_.ReadUInt();
+  USE(offset);
+
+#if !defined(PRODUCT)
+  bytecode.set_local_variables_binary_offset(
+      bytecode_component_->GetLocalVariablesOffset() + offset);
+#endif
+}
+
 RawTypedData* BytecodeReaderHelper::NativeEntry(const Function& function,
                                                 const String& external_name) {
   MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
@@ -824,17 +801,16 @@
 RawArray* BytecodeReaderHelper::ReadBytecodeComponent(intptr_t md_offset) {
   ASSERT(Thread::Current()->IsMutatorThread());
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
+  AlternativeReadingScope alt(&reader_, md_offset);
 
-  const intptr_t start_offset = helper_->reader_.offset();
+  const intptr_t start_offset = reader_.offset();
 
-  intptr_t magic = helper_->reader_.ReadUInt32();
+  intptr_t magic = reader_.ReadUInt32();
   if (magic != KernelBytecode::kMagicValue) {
-    return ReadBytecodeComponentV2(md_offset);
+    FATAL1("Unexpected Dart bytecode magic %" Px, magic);
   }
 
-  const intptr_t version = helper_->reader_.ReadUInt32();
+  const intptr_t version = reader_.ReadUInt32();
   if ((version < KernelBytecode::kMinSupportedBytecodeFormatVersion) ||
       (version > KernelBytecode::kMaxSupportedBytecodeFormatVersion)) {
     FATAL3("Unsupported Dart bytecode format version %" Pd
@@ -844,115 +820,66 @@
            version, KernelBytecode::kMinSupportedBytecodeFormatVersion,
            KernelBytecode::kMaxSupportedBytecodeFormatVersion);
   }
+  BytecodeReader::UseBytecodeVersion(version);
 
-  helper_->reader_.ReadUInt32();  // Skip stringTable.numItems
-  const intptr_t string_table_offset =
-      start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip stringTable.numItems
+  const intptr_t string_table_offset = start_offset + reader_.ReadUInt32();
 
-  helper_->reader_.ReadUInt32();  // Skip objectTable.numItems
-  const intptr_t object_table_offset =
-      start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip objectTable.numItems
+  const intptr_t object_table_offset = start_offset + reader_.ReadUInt32();
 
-  helper_->reader_.ReadUInt32();  // Skip main.numItems
-  const intptr_t main_offset = start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip main.numItems
+  const intptr_t main_offset = start_offset + reader_.ReadUInt32();
 
-  helper_->reader_.ReadUInt32();  // Skip members.numItems
-  const intptr_t members_offset = start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip members.numItems
+  const intptr_t members_offset = start_offset + reader_.ReadUInt32();
 
-  helper_->reader_.ReadUInt32();  // Skip codes.numItems
-  const intptr_t codes_offset = start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip codes.numItems
+  const intptr_t codes_offset = start_offset + reader_.ReadUInt32();
 
-  helper_->reader_.ReadUInt32();  // Skip sourcePositions.numItems
-  const intptr_t sources_positions_offset =
-      start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip sourcePositions.numItems
+  const intptr_t sources_positions_offset = start_offset + reader_.ReadUInt32();
 
-  helper_->reader_.ReadUInt32();  // Skip annotations.numItems
-  const intptr_t annotations_offset =
-      start_offset + helper_->reader_.ReadUInt32();
+  intptr_t local_variables_offset = 0;
+  static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 9,
+                "Cleanup condition");
+  if (version >= 9) {
+    reader_.ReadUInt32();  // Skip localVariables.numItems
+    local_variables_offset = start_offset + reader_.ReadUInt32();
+  }
+
+  reader_.ReadUInt32();  // Skip annotations.numItems
+  const intptr_t annotations_offset = start_offset + reader_.ReadUInt32();
 
   // Read header of string table.
-  helper_->reader_.set_offset(string_table_offset);
-  const intptr_t num_one_byte_strings = helper_->reader_.ReadUInt32();
-  const intptr_t num_two_byte_strings = helper_->reader_.ReadUInt32();
+  reader_.set_offset(string_table_offset);
+  const intptr_t num_one_byte_strings = reader_.ReadUInt32();
+  const intptr_t num_two_byte_strings = reader_.ReadUInt32();
   const intptr_t strings_contents_offset =
-      helper_->reader_.offset() +
-      (num_one_byte_strings + num_two_byte_strings) * 4;
+      reader_.offset() + (num_one_byte_strings + num_two_byte_strings) * 4;
 
   // Read header of object table.
-  helper_->reader_.set_offset(object_table_offset);
-  const intptr_t num_objects = helper_->reader_.ReadUInt();
-  const intptr_t objects_size = helper_->reader_.ReadUInt();
+  reader_.set_offset(object_table_offset);
+  const intptr_t num_objects = reader_.ReadUInt();
+  const intptr_t objects_size = reader_.ReadUInt();
 
   // Skip over contents of objects.
-  const intptr_t objects_contents_offset = helper_->reader_.offset();
-  helper_->reader_.set_offset(objects_contents_offset + objects_size);
+  const intptr_t objects_contents_offset = reader_.offset();
+  reader_.set_offset(objects_contents_offset + objects_size);
 
   const Array& bytecode_component_array = Array::Handle(
-      Z,
-      BytecodeComponentData::New(
-          Z, version, num_objects, string_table_offset, strings_contents_offset,
-          objects_contents_offset, main_offset, members_offset, codes_offset,
-          sources_positions_offset, annotations_offset, Heap::kOld));
+      Z, BytecodeComponentData::New(
+             Z, version, num_objects, string_table_offset,
+             strings_contents_offset, objects_contents_offset, main_offset,
+             members_offset, codes_offset, sources_positions_offset,
+             local_variables_offset, annotations_offset, Heap::kOld));
 
   BytecodeComponentData bytecode_component(bytecode_component_array);
 
   // Read object offsets.
   Smi& offs = Smi::Handle(Z);
   for (intptr_t i = 0; i < num_objects; ++i) {
-    offs = Smi::New(helper_->reader_.ReadUInt());
-    bytecode_component.SetObject(i, offs);
-  }
-
-  H.SetBytecodeComponent(bytecode_component_array);
-
-  return bytecode_component_array.raw();
-}
-
-// TODO(alexmarkov): obsolete, remove when dropping support for old bytecode
-// format version.
-RawArray* BytecodeReaderHelper::ReadBytecodeComponentV2(intptr_t md_offset) {
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
-
-  const intptr_t kMinVersion = 1;
-  const intptr_t kMaxVersion = 2;
-
-  const intptr_t version = helper_->reader_.ReadUInt();
-  if ((version < kMinVersion) || (version > kMaxVersion)) {
-    FATAL1("Unsupported Dart bytecode format version %" Pd ".", version);
-  }
-
-  const intptr_t strings_size = helper_->reader_.ReadUInt();
-  helper_->reader_.ReadUInt();  // Objects table size.
-
-  // Read header of strings table.
-  const intptr_t strings_header_offset = helper_->reader_.offset();
-  const intptr_t num_one_byte_strings = helper_->reader_.ReadUInt32();
-  const intptr_t num_two_byte_strings = helper_->reader_.ReadUInt32();
-  const intptr_t strings_contents_offset =
-      helper_->reader_.offset() +
-      (num_one_byte_strings + num_two_byte_strings) * 4;
-
-  // Read header of objects table.
-  helper_->reader_.set_offset(strings_header_offset + strings_size);
-  const intptr_t num_objects = helper_->reader_.ReadUInt();
-  const intptr_t objects_size = helper_->reader_.ReadUInt();
-
-  // Skip over contents of objects.
-  const intptr_t objects_contents_offset = helper_->reader_.offset();
-  helper_->reader_.set_offset(objects_contents_offset + objects_size);
-
-  const Array& bytecode_component_array =
-      Array::Handle(Z, BytecodeComponentData::New(
-                           Z, version, num_objects, strings_header_offset,
-                           strings_contents_offset, objects_contents_offset, 0,
-                           0, 0, 0, 0, Heap::kOld));
-  BytecodeComponentData bytecode_component(bytecode_component_array);
-
-  // Read object offsets.
-  Smi& offs = Smi::Handle(Z);
-  for (intptr_t i = 0; i < num_objects; ++i) {
-    offs = Smi::New(helper_->reader_.ReadUInt());
+    offs = Smi::New(reader_.ReadUInt());
     bytecode_component.SetObject(i, offs);
   }
 
@@ -962,7 +889,7 @@
 }
 
 RawObject* BytecodeReaderHelper::ReadObject() {
-  uint32_t header = helper_->reader_.ReadUInt();
+  uint32_t header = reader_.ReadUInt();
   if ((header & kReferenceBit) != 0) {
     intptr_t index = header >> kIndexShift;
     if (index == 0) {
@@ -975,16 +902,14 @@
     // Object is not loaded yet.
     intptr_t offset = bytecode_component_->GetObjectsContentsOffset() +
                       Smi::Value(Smi::RawCast(obj));
-    AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                                offset);
-    header = helper_->reader_.ReadUInt();
+    AlternativeReadingScope alt(&reader_, offset);
+    header = reader_.ReadUInt();
 
     obj = ReadObjectContents(header);
     ASSERT(obj->IsHeapObject());
     {
-      Thread* thread = H.thread();
-      REUSABLE_OBJECT_HANDLESCOPE(thread);
-      Object& obj_handle = thread->ObjectHandle();
+      REUSABLE_OBJECT_HANDLESCOPE(thread_);
+      Object& obj_handle = thread_->ObjectHandle();
       obj_handle = obj;
       bytecode_component_->SetObject(index, obj_handle);
     }
@@ -1000,7 +925,7 @@
   pieces.Add(String::Handle(Z, cls.Name()));
   pieces.Add(Symbols::Dot());
   pieces.Add(name);
-  return Symbols::FromConcatAll(H.thread(), pieces);
+  return Symbols::FromConcatAll(thread_, pieces);
 }
 
 RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) {
@@ -1055,7 +980,7 @@
       break;
     case kLibrary: {
       const String& uri = String::Handle(Z, ReadString());
-      RawLibrary* library = Library::LookupLibrary(H.thread(), uri);
+      RawLibrary* library = Library::LookupLibrary(thread_, uri);
       if (library == Library::null()) {
         FATAL1("Unable to find library %s", uri.ToCString());
       }
@@ -1115,7 +1040,7 @@
     }
     case kClosure: {
       ReadObject();  // Skip enclosing member.
-      const intptr_t closure_index = helper_->reader_.ReadUInt();
+      const intptr_t closure_index = reader_.ReadUInt();
       return closures_->At(closure_index);
     }
     case kSimpleType: {
@@ -1132,7 +1057,7 @@
     }
     case kTypeParameter: {
       Object& parent = Object::Handle(Z, ReadObject());
-      const intptr_t index_in_parent = helper_->reader_.ReadUInt();
+      const intptr_t index_in_parent = reader_.ReadUInt();
       TypeArguments& type_parameters = TypeArguments::Handle(Z);
       if (parent.IsClass()) {
         type_parameters = Class::Cast(parent).type_parameters();
@@ -1206,13 +1131,13 @@
       return ReadConstObject(tag);
     }
     case kArgDesc: {
-      const intptr_t num_arguments = helper_->ReadUInt();
+      const intptr_t num_arguments = reader_.ReadUInt();
       const intptr_t num_type_args =
-          ((flags & kFlagHasTypeArgs) != 0) ? helper_->ReadUInt() : 0;
+          ((flags & kFlagHasTypeArgs) != 0) ? reader_.ReadUInt() : 0;
       if ((flags & kFlagHasNamedArgs) == 0) {
         return ArgumentsDescriptor::New(num_type_args, num_arguments);
       } else {
-        const intptr_t num_arg_names = helper_->ReadListLength();
+        const intptr_t num_arg_names = reader_.ReadListLength();
         const Array& array = Array::Handle(Z, Array::New(num_arg_names));
         String& name = String::Handle(Z);
         for (intptr_t i = 0; i < num_arg_names; ++i) {
@@ -1257,7 +1182,7 @@
             TypeArguments::Handle(Z, type.arguments());
         obj.SetTypeArguments(type_args);
       }
-      const intptr_t num_fields = helper_->ReadUInt();
+      const intptr_t num_fields = reader_.ReadUInt();
       Field& field = Field::Handle(Z);
       Object& value = Object::Handle(Z);
       for (intptr_t i = 0; i < num_fields; ++i) {
@@ -1268,7 +1193,7 @@
       return H.Canonicalize(obj);
     }
     case kInt: {
-      const int64_t value = helper_->reader_.ReadSLEB128AsInt64();
+      const int64_t value = reader_.ReadSLEB128AsInt64();
       if (Smi::IsValid(value)) {
         return Smi::New(static_cast<intptr_t>(value));
       }
@@ -1276,7 +1201,7 @@
       return H.Canonicalize(obj);
     }
     case kDouble: {
-      const int64_t bits = helper_->reader_.ReadSLEB128AsInt64();
+      const int64_t bits = reader_.ReadSLEB128AsInt64();
       double value = bit_cast<double, int64_t>(bits);
       const Double& obj = Double::Handle(Z, Double::New(value, Heap::kOld));
       return H.Canonicalize(obj);
@@ -1284,7 +1209,7 @@
     case kList: {
       const AbstractType& elem_type =
           AbstractType::CheckedHandle(Z, ReadObject());
-      const intptr_t length = helper_->ReadUInt();
+      const intptr_t length = reader_.ReadUInt();
       const Array& array = Array::Handle(Z, Array::New(length, elem_type));
       Object& value = Object::Handle(Z);
       for (intptr_t i = 0; i < length; ++i) {
@@ -1304,7 +1229,7 @@
       return H.Canonicalize(Instance::Cast(obj));
     }
     case kBool: {
-      bool is_true = helper_->ReadByte() != 0;
+      bool is_true = reader_.ReadByte() != 0;
       return is_true ? Bool::True().raw() : Bool::False().raw();
     }
     case kSymbol: {
@@ -1344,21 +1269,21 @@
   const int kHeaderFields = 2;
   const int kUInt32Size = 4;
 
-  uint32_t ref = helper_->reader_.ReadUInt();
+  uint32_t ref = reader_.ReadUInt();
   const bool isOneByteString = (ref & kFlagTwoByteString) == 0;
   intptr_t index = ref >> 1;
 
   if (!isOneByteString) {
-    const uint32_t num_one_byte_strings = helper_->reader_.ReadUInt32At(
-        bytecode_component_->GetStringsHeaderOffset());
+    const uint32_t num_one_byte_strings =
+        reader_.ReadUInt32At(bytecode_component_->GetStringsHeaderOffset());
     index += num_one_byte_strings;
   }
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
+  AlternativeReadingScope alt(&reader_,
                               bytecode_component_->GetStringsHeaderOffset() +
                                   (kHeaderFields + index - 1) * kUInt32Size);
-  intptr_t start_offs = helper_->ReadUInt32();
-  intptr_t end_offs = helper_->ReadUInt32();
+  intptr_t start_offs = reader_.ReadUInt32();
+  intptr_t end_offs = reader_.ReadUInt32();
   if (index == 0) {
     // For the 0-th string we read a header field instead of end offset of
     // the previous string.
@@ -1368,14 +1293,14 @@
   // Bytecode strings reside in ExternalTypedData which is not movable by GC,
   // so it is OK to take a direct pointer to string characters even if
   // symbol allocation triggers GC.
-  const uint8_t* data = helper_->reader_.BufferAt(
+  const uint8_t* data = reader_.BufferAt(
       bytecode_component_->GetStringsContentsOffset() + start_offs);
 
   if (is_canonical) {
     if (isOneByteString) {
-      return Symbols::FromLatin1(H.thread(), data, end_offs - start_offs);
+      return Symbols::FromLatin1(thread_, data, end_offs - start_offs);
     } else {
-      return Symbols::FromUTF16(H.thread(),
+      return Symbols::FromUTF16(thread_,
                                 reinterpret_cast<const uint16_t*>(data),
                                 (end_offs - start_offs) >> 1);
     }
@@ -1391,7 +1316,7 @@
 
 RawTypeArguments* BytecodeReaderHelper::ReadTypeArguments(
     const Class& instantiator) {
-  const intptr_t length = helper_->reader_.ReadUInt();
+  const intptr_t length = reader_.ReadUInt();
   TypeArguments& type_arguments =
       TypeArguments::ZoneHandle(Z, TypeArguments::New(length));
   AbstractType& type = AbstractType::Handle(Z);
@@ -1414,7 +1339,7 @@
   // finalize the argument types.
   // (This can for example make the [type_arguments] vector larger)
   type = Type::New(instantiator, type_arguments, TokenPosition::kNoSource);
-  type ^= ClassFinalizer::FinalizeType(*active_class_->klass, type);
+  type = ClassFinalizer::FinalizeType(*active_class_->klass, type);
   return type.arguments();
 }
 
@@ -1427,10 +1352,9 @@
 
   const intptr_t offset =
       bytecode_component_->GetMembersOffset() + members_offset;
-  AlternativeReadingScope alt_md(&helper_->reader_, &H.metadata_payloads(),
-                                 offset);
+  AlternativeReadingScope alt_md(&reader_, offset);
 
-  const intptr_t num_functions = helper_->reader_.ReadUInt();
+  const intptr_t num_functions = reader_.ReadUInt();
   functions_ = &Array::Handle(Z, Array::New(num_functions, Heap::kOld));
   function_index_ = 0;
 
@@ -1458,7 +1382,7 @@
   const int kHasPragmaFlag = 1 << 11;
   const int kHasCustomScriptFlag = 1 << 12;
 
-  const int num_fields = helper_->ReadListLength();
+  const int num_fields = reader_.ReadListLength();
   if ((num_fields == 0) && !cls.is_enum_class()) {
     return;
   }
@@ -1472,7 +1396,7 @@
   Function& function = Function::Handle(Z);
 
   for (intptr_t i = 0; i < num_fields; ++i) {
-    intptr_t flags = helper_->reader_.ReadUInt();
+    intptr_t flags = reader_.ReadUInt();
 
     const bool is_static = (flags & kIsStaticFlag) != 0;
     const bool is_final = (flags & kIsFinalFlag) != 0;
@@ -1493,8 +1417,8 @@
     TokenPosition position = TokenPosition::kNoSource;
     TokenPosition end_position = TokenPosition::kNoSource;
     if ((flags & kHasSourcePositionsFlag) != 0) {
-      position = helper_->ReadPosition();
-      end_position = helper_->ReadPosition();
+      position = reader_.ReadPosition();
+      end_position = reader_.ReadPosition();
     }
 
     field = Field::New(name, is_static, is_final, is_const,
@@ -1528,7 +1452,7 @@
     }
 
     if (has_initializer && is_static) {
-      const intptr_t code_offset = helper_->reader_.ReadUInt();
+      const intptr_t code_offset = reader_.ReadUInt();
       field.set_bytecode_offset(code_offset +
                                 bytecode_component_->GetCodesOffset());
       field.SetStaticValue(Object::sentinel(), true);
@@ -1536,15 +1460,14 @@
 
     if ((flags & kHasGetterFlag) != 0) {
       name ^= ReadObject();
-      function =
-          Function::New(name,
-                        is_static ? RawFunction::kImplicitStaticFinalGetter
-                                  : RawFunction::kImplicitGetter,
-                        is_static, is_const,
-                        false,  // is_abstract
-                        false,  // is_external
-                        false,  // is_native
-                        script_class, position);
+      function = Function::New(name,
+                               is_static ? RawFunction::kImplicitStaticGetter
+                                         : RawFunction::kImplicitGetter,
+                               is_static, is_const,
+                               false,  // is_abstract
+                               false,  // is_external
+                               false,  // is_native
+                               script_class, position);
       function.set_end_token_pos(end_position);
       function.set_result_type(type);
       function.set_is_debuggable(false);
@@ -1577,8 +1500,8 @@
     }
 
     if ((flags & kHasAnnotationsFlag) != 0) {
-      intptr_t annotations_offset = helper_->reader_.ReadUInt() +
-                                    bytecode_component_->GetAnnotationsOffset();
+      intptr_t annotations_offset =
+          reader_.ReadUInt() + bytecode_component_->GetAnnotationsOffset();
       ASSERT(annotations_offset > 0);
 
       if (FLAG_enable_mirrors || has_pragma) {
@@ -1588,9 +1511,8 @@
         if (has_pragma) {
           // TODO(alexmarkov): read annotations right away using
           //  annotations_offset.
-          Thread* thread = H.thread();
-          NoOOBMessageScope no_msg_scope(thread);
-          NoReloadScope no_reload_scope(thread->isolate(), thread);
+          NoOOBMessageScope no_msg_scope(thread_);
+          NoReloadScope no_reload_scope(thread_->isolate(), thread_);
           library.GetMetadata(field);
         }
       }
@@ -1666,7 +1588,7 @@
   const int kHasPragmaFlag = 1 << 21;
   const int kHasCustomScriptFlag = 1 << 22;
 
-  const intptr_t num_functions = helper_->ReadListLength();
+  const intptr_t num_functions = reader_.ReadListLength();
   ASSERT(function_index_ + num_functions == functions_->Length());
 
   if (function_index_ + num_functions == 0) {
@@ -1681,7 +1603,7 @@
   AbstractType& type = AbstractType::Handle(Z);
 
   for (intptr_t i = 0; i < num_functions; ++i) {
-    intptr_t flags = helper_->reader_.ReadUInt();
+    intptr_t flags = reader_.ReadUInt();
 
     const bool is_static = (flags & kIsStaticFlag) != 0;
     const bool is_factory = (flags & kIsFactoryFlag) != 0;
@@ -1700,8 +1622,8 @@
     TokenPosition position = TokenPosition::kNoSource;
     TokenPosition end_position = TokenPosition::kNoSource;
     if ((flags & kHasSourcePositionsFlag) != 0) {
-      position = helper_->ReadPosition();
-      end_position = helper_->ReadPosition();
+      position = reader_.ReadPosition();
+      end_position = reader_.ReadPosition();
     }
 
     RawFunction::Kind kind = RawFunction::kRegularFunction;
@@ -1751,13 +1673,12 @@
     }
 
     const intptr_t num_implicit_params = (!is_static || is_factory) ? 1 : 0;
-    const intptr_t num_params =
-        num_implicit_params + helper_->reader_.ReadUInt();
+    const intptr_t num_params = num_implicit_params + reader_.ReadUInt();
 
     intptr_t num_required_params = num_params;
     if ((flags & (kHasOptionalPositionalParamsFlag |
                   kHasOptionalNamedParamsFlag)) != 0) {
-      num_required_params = num_implicit_params + helper_->reader_.ReadUInt();
+      num_required_params = num_implicit_params + reader_.ReadUInt();
     }
 
     function.set_num_fixed_parameters(num_required_params);
@@ -1799,15 +1720,14 @@
     }
 
     if ((flags & kIsAbstractFlag) == 0) {
-      const intptr_t code_offset = helper_->reader_.ReadUInt();
+      const intptr_t code_offset = reader_.ReadUInt();
       function.set_bytecode_offset(code_offset +
                                    bytecode_component_->GetCodesOffset());
     }
 
     if ((flags & kHasAnnotationsFlag) != 0) {
       const intptr_t annotations_offset =
-          helper_->reader_.ReadUInt() +
-          bytecode_component_->GetAnnotationsOffset();
+          reader_.ReadUInt() + bytecode_component_->GetAnnotationsOffset();
       ASSERT(annotations_offset > 0);
 
       if (FLAG_enable_mirrors || has_pragma) {
@@ -1862,17 +1782,16 @@
   ASSERT(is_covariant->length() == num_params);
   ASSERT(is_generic_covariant_impl->length() == num_params);
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              function.bytecode_offset());
+  AlternativeReadingScope alt(&reader_, function.bytecode_offset());
 
-  const intptr_t code_flags = helper_->reader_.ReadUInt();
+  const intptr_t code_flags = reader_.ReadUInt();
   if ((code_flags & Code::kHasParameterFlagsFlag) != 0) {
-    const intptr_t num_explicit_params = helper_->reader_.ReadUInt();
+    const intptr_t num_explicit_params = reader_.ReadUInt();
     ASSERT(num_params ==
            function.NumImplicitParameters() + num_explicit_params);
 
     for (intptr_t i = function.NumImplicitParameters(); i < num_params; ++i) {
-      const intptr_t flags = helper_->reader_.ReadUInt();
+      const intptr_t flags = reader_.ReadUInt();
 
       if ((flags & Parameter::kIsCovariantFlag) != 0) {
         is_covariant->Add(i);
@@ -1902,7 +1821,7 @@
     case RawFunction::kImplicitSetter:
       BytecodeScopeBuilder(parsed_function).BuildScopes();
       break;
-    case RawFunction::kImplicitStaticFinalGetter: {
+    case RawFunction::kImplicitStaticGetter: {
       if (IsStaticFieldGetterGeneratedAsInitializer(function, Z)) {
         ReadCode(function, function.bytecode_offset());
       } else {
@@ -1957,10 +1876,9 @@
   const auto& target_bytecode = Bytecode::Handle(Z, target.bytecode());
   const auto& obj_pool = ObjectPool::Handle(Z, target_bytecode.object_pool());
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              target.bytecode_offset());
+  AlternativeReadingScope alt(&reader_, target.bytecode_offset());
 
-  const intptr_t flags = helper_->reader_.ReadUInt();
+  const intptr_t flags = reader_.ReadUInt();
   const bool has_parameters_flags = (flags & Code::kHasParameterFlagsFlag) != 0;
   const bool has_forwarding_stub_target =
       (flags & Code::kHasForwardingStubTargetFlag) != 0;
@@ -1968,10 +1886,10 @@
       (flags & Code::kHasDefaultFunctionTypeArgsFlag) != 0;
 
   if (has_parameters_flags) {
-    const intptr_t num_params = helper_->reader_.ReadUInt();
+    const intptr_t num_params = reader_.ReadUInt();
     const intptr_t num_implicit_params = function.NumImplicitParameters();
     for (intptr_t i = 0; i < num_params; ++i) {
-      const intptr_t flags = helper_->reader_.ReadUInt();
+      const intptr_t flags = reader_.ReadUInt();
 
       bool is_covariant = (flags & Parameter::kIsCovariantFlag) != 0;
       bool is_generic_covariant_impl =
@@ -1996,7 +1914,7 @@
   }
 
   if (has_forwarding_stub_target) {
-    const intptr_t cp_index = helper_->reader_.ReadUInt();
+    const intptr_t cp_index = reader_.ReadUInt();
     const auto& forwarding_stub_target =
         Function::CheckedZoneHandle(Z, obj_pool.ObjectAt(cp_index));
     parsed_function->MarkForwardingStub(&forwarding_stub_target);
@@ -2004,7 +1922,7 @@
 
   if (has_default_function_type_args) {
     ASSERT(function.IsGeneric());
-    const intptr_t cp_index = helper_->reader_.ReadUInt();
+    const intptr_t cp_index = reader_.ReadUInt();
     const auto& type_args =
         TypeArguments::CheckedHandle(Z, obj_pool.ObjectAt(cp_index));
     parsed_function->SetDefaultFunctionTypeArguments(type_args);
@@ -2012,10 +1930,10 @@
 
   if (function.HasOptionalParameters()) {
     const KBCInstr* raw_bytecode =
-        reinterpret_cast<KBCInstr*>(target_bytecode.PayloadStart());
-    KBCInstr entry = raw_bytecode[0];
-    ASSERT(KernelBytecode::DecodeOpcode(entry) ==
-           KernelBytecode::kEntryOptional);
+        reinterpret_cast<const KBCInstr*>(target_bytecode.PayloadStart());
+    const KBCInstr* entry = raw_bytecode;
+    raw_bytecode = KernelBytecode::Next(raw_bytecode);
+    ASSERT(KernelBytecode::IsEntryOptionalOpcode(entry));
     ASSERT(KernelBytecode::DecodeB(entry) ==
            function.NumOptionalPositionalParameters());
     ASSERT(KernelBytecode::DecodeC(entry) ==
@@ -2028,11 +1946,11 @@
     if (function.HasOptionalPositionalParameters()) {
       for (intptr_t i = 0, n = function.NumOptionalPositionalParameters();
            i < n; ++i) {
-        const KBCInstr load = raw_bytecode[1 + i];
-        ASSERT(KernelBytecode::DecodeOpcode(load) ==
-               KernelBytecode::kLoadConstant);
+        const KBCInstr* load = raw_bytecode;
+        raw_bytecode = KernelBytecode::Next(raw_bytecode);
+        ASSERT(KernelBytecode::IsLoadConstantOpcode(load));
         const auto& value = Instance::CheckedZoneHandle(
-            Z, obj_pool.ObjectAt(KernelBytecode::DecodeD(load)));
+            Z, obj_pool.ObjectAt(KernelBytecode::DecodeE(load)));
         default_values->Add(&value);
       }
     } else {
@@ -2040,15 +1958,14 @@
       auto& param_name = String::Handle(Z);
       default_values->EnsureLength(num_opt_params, nullptr);
       for (intptr_t i = 0; i < num_opt_params; ++i) {
-        const KBCInstr load_name = raw_bytecode[1 + 2 * i];
-        const KBCInstr load_value = raw_bytecode[1 + 2 * i + 1];
-        ASSERT(KernelBytecode::DecodeOpcode(load_name) ==
-               KernelBytecode::kLoadConstant);
-        ASSERT(KernelBytecode::DecodeOpcode(load_value) ==
-               KernelBytecode::kLoadConstant);
-        param_name ^= obj_pool.ObjectAt(KernelBytecode::DecodeD(load_name));
+        const KBCInstr* load_name = raw_bytecode;
+        const KBCInstr* load_value = KernelBytecode::Next(load_name);
+        raw_bytecode = KernelBytecode::Next(load_value);
+        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_name));
+        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value));
+        param_name ^= obj_pool.ObjectAt(KernelBytecode::DecodeE(load_name));
         const auto& value = Instance::CheckedZoneHandle(
-            Z, obj_pool.ObjectAt(KernelBytecode::DecodeD(load_value)));
+            Z, obj_pool.ObjectAt(KernelBytecode::DecodeE(load_value)));
 
         const intptr_t num_params = function.NumParameters();
         intptr_t param_index = num_fixed_params;
@@ -2103,6 +2020,10 @@
   return Smi::Value(Smi::RawCast(data_.At(kSourcePositionsOffset)));
 }
 
+intptr_t BytecodeComponentData::GetLocalVariablesOffset() const {
+  return Smi::Value(Smi::RawCast(data_.At(kLocalVariablesOffset)));
+}
+
 intptr_t BytecodeComponentData::GetAnnotationsOffset() const {
   return Smi::Value(Smi::RawCast(data_.At(kAnnotationsOffset)));
 }
@@ -2125,6 +2046,7 @@
                                      intptr_t members_offset,
                                      intptr_t codes_offset,
                                      intptr_t source_positions_offset,
+                                     intptr_t local_variables_offset,
                                      intptr_t annotations_offset,
                                      Heap::Space space) {
   const Array& data =
@@ -2155,6 +2077,9 @@
   smi_handle = Smi::New(source_positions_offset);
   data.SetAt(kSourcePositionsOffset, smi_handle);
 
+  smi_handle = Smi::New(local_variables_offset);
+  data.SetAt(kLocalVariablesOffset, smi_handle);
+
   smi_handle = Smi::New(annotations_offset);
   data.SetAt(kAnnotationsOffset, smi_handle);
 
@@ -2170,37 +2095,93 @@
 
   VMTagScope tagScope(thread, VMTag::kLoadBytecodeTagId);
 
+#if defined(SUPPORT_TIMELINE)
+  TimelineDurationScope tds(Thread::Current(), Timeline::GetCompilerStream(),
+                            "BytecodeReader::ReadFunctionBytecode");
+  // This increases bytecode reading time by ~7%, so only keep it around for
+  // debugging.
+#if defined(DEBUG)
+  tds.SetNumArguments(1);
+  tds.CopyArgument(0, "Function", function.ToQualifiedCString());
+#endif  // defined(DEBUG)
+#endif  // !defined(SUPPORT_TIMELINE)
+
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     StackZone stack_zone(thread);
     Zone* const zone = stack_zone.GetZone();
     HANDLESCOPE(thread);
-    CompilerState compiler_state(thread);
 
-    const Script& script = Script::Handle(zone, function.script());
-    TranslationHelper translation_helper(thread);
-    translation_helper.InitFromScript(script);
+    auto& bytecode = Bytecode::Handle(zone);
 
-    KernelReaderHelper reader_helper(
-        zone, &translation_helper, script,
-        ExternalTypedData::Handle(zone, function.KernelData()),
-        function.KernelDataProgramOffset());
-    ActiveClass active_class;
+    switch (function.kind()) {
+      case RawFunction::kImplicitGetter:
+        bytecode = Object::implicit_getter_bytecode().raw();
+        break;
+      case RawFunction::kImplicitSetter:
+        bytecode = Object::implicit_setter_bytecode().raw();
+        break;
+      case RawFunction::kImplicitStaticGetter:
+        if (!IsStaticFieldGetterGeneratedAsInitializer(function, zone)) {
+          bytecode = Object::implicit_static_getter_bytecode().raw();
+        }
+        break;
+      case RawFunction::kMethodExtractor:
+        bytecode = Object::method_extractor_bytecode().raw();
+        break;
+      case RawFunction::kInvokeFieldDispatcher:
+        if (Class::Handle(function.Owner()).id() == kClosureCid) {
+          bytecode = Object::invoke_closure_bytecode().raw();
+        } else {
+          bytecode = Object::invoke_field_bytecode().raw();
+        }
+        break;
+      case RawFunction::kNoSuchMethodDispatcher:
+        bytecode = Object::nsm_dispatcher_bytecode().raw();
+        break;
+      default:
+        break;
+    }
 
-    BytecodeMetadataHelper bytecode_metadata_helper(&reader_helper,
-                                                    &active_class);
+    if (!bytecode.IsNull()) {
+      function.AttachBytecode(bytecode);
+    } else if (function.is_declared_in_bytecode()) {
+      const intptr_t code_offset = function.bytecode_offset();
+      if (code_offset != 0) {
+        CompilerState compiler_state(thread);
 
-    // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
-    // e.g. for type translation.
-    const Class& klass = Class::Handle(zone, function.Owner());
-    Function& outermost_function =
-        Function::Handle(zone, function.GetOutermostFunction());
+        const Script& script = Script::Handle(zone, function.script());
+        TranslationHelper translation_helper(thread);
+        translation_helper.InitFromScript(script);
 
-    ActiveClassScope active_class_scope(&active_class, &klass);
-    ActiveMemberScope active_member(&active_class, &outermost_function);
-    ActiveTypeParametersScope active_type_params(&active_class, function, zone);
+        ActiveClass active_class;
 
-    bytecode_metadata_helper.ReadMetadata(function);
+        // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be
+        // used e.g. for type translation.
+        const Class& klass = Class::Handle(zone, function.Owner());
+        Function& outermost_function =
+            Function::Handle(zone, function.GetOutermostFunction());
+
+        ActiveClassScope active_class_scope(&active_class, &klass);
+        ActiveMemberScope active_member(&active_class, &outermost_function);
+        ActiveTypeParametersScope active_type_params(&active_class, function,
+                                                     zone);
+
+        BytecodeComponentData bytecode_component(
+            Array::Handle(zone, translation_helper.GetBytecodeComponent()));
+        ASSERT(!bytecode_component.IsNull());
+        BytecodeReaderHelper bytecode_reader(&translation_helper, &active_class,
+                                             &bytecode_component);
+
+        bytecode_reader.ReadCode(function, code_offset);
+      }
+    }
+
+#if !defined(PRODUCT)
+    if (function.HasBytecode()) {
+      thread->isolate()->debugger()->NotifyBytecodeLoaded(function);
+    }
+#endif
 
     return Error::null();
   } else {
@@ -2219,22 +2200,147 @@
   TranslationHelper translation_helper(thread);
   translation_helper.InitFromScript(script);
 
-  KernelReaderHelper reader_helper(
-      zone, &translation_helper, script,
-      ExternalTypedData::Handle(zone, annotation_field.KernelData()),
-      annotation_field.KernelDataProgramOffset());
   ActiveClass active_class;
 
-  BytecodeMetadataHelper bytecode_metadata_helper(&reader_helper,
-                                                  &active_class);
+  BytecodeComponentData bytecode_component(
+      Array::Handle(zone, translation_helper.GetBytecodeComponent()));
+  ASSERT(!bytecode_component.IsNull());
+  BytecodeReaderHelper bytecode_reader(&translation_helper, &active_class,
+                                       &bytecode_component);
 
-  return bytecode_metadata_helper.ReadAnnotation(
-      annotation_field.bytecode_offset());
+  AlternativeReadingScope alt(&bytecode_reader.reader(),
+                              annotation_field.bytecode_offset());
+
+  return bytecode_reader.ReadObject();
+}
+
+#if !defined(PRODUCT)
+RawLocalVarDescriptors* BytecodeReader::ComputeLocalVarDescriptors(
+    Zone* zone,
+    const Function& function,
+    const Bytecode& bytecode) {
+  ASSERT(function.is_declared_in_bytecode());
+  ASSERT(function.HasBytecode());
+  ASSERT(!bytecode.IsNull());
+  ASSERT(function.bytecode() == bytecode.raw());
+
+  struct VarDesc {
+    const String* name;
+    RawLocalVarDescriptors::VarInfo info;
+  };
+  GrowableArray<VarDesc> vars(8);
+
+  if (function.IsLocalFunction()) {
+    const auto& parent = Function::Handle(zone, function.parent_function());
+    ASSERT(parent.is_declared_in_bytecode() && parent.HasBytecode());
+    const auto& parent_bytecode = Bytecode::Handle(zone, parent.bytecode());
+    const auto& parent_vars = LocalVarDescriptors::Handle(
+        zone, parent_bytecode.GetLocalVarDescriptors());
+    for (intptr_t i = 0; i < parent_vars.Length(); ++i) {
+      RawLocalVarDescriptors::VarInfo var_info;
+      parent_vars.GetInfo(i, &var_info);
+      // Include parent's context variable if variable's scope
+      // intersects with the local function range.
+      // It is not enough to check if local function is declared within the
+      // scope of variable, because in case of async functions closure has
+      // the same range as original function.
+      if (var_info.kind() == RawLocalVarDescriptors::kContextVar &&
+          ((var_info.begin_pos <= function.token_pos() &&
+            function.token_pos() <= var_info.end_pos) ||
+           (function.token_pos() <= var_info.begin_pos &&
+            var_info.begin_pos <= function.end_token_pos()))) {
+        vars.Add(
+            VarDesc{&String::Handle(zone, parent_vars.GetName(i)), var_info});
+      }
+    }
+  }
+
+  if (bytecode.HasLocalVariablesInfo()) {
+    intptr_t scope_id = 0;
+    intptr_t context_level = -1;
+    BytecodeLocalVariablesIterator local_vars(zone, bytecode);
+    while (local_vars.MoveNext()) {
+      switch (local_vars.Kind()) {
+        case BytecodeLocalVariablesIterator::kScope: {
+          ++scope_id;
+          context_level = local_vars.ContextLevel();
+        } break;
+        case BytecodeLocalVariablesIterator::kVariableDeclaration: {
+          VarDesc desc;
+          desc.name = &String::Handle(zone, local_vars.Name());
+          if (local_vars.IsCaptured()) {
+            desc.info.set_kind(RawLocalVarDescriptors::kContextVar);
+            desc.info.scope_id = context_level;
+            desc.info.set_index(local_vars.Index());
+          } else {
+            desc.info.set_kind(RawLocalVarDescriptors::kStackVar);
+            desc.info.scope_id = scope_id;
+            if (local_vars.Index() < 0) {
+              // Parameter
+              desc.info.set_index(-local_vars.Index() - kKBCParamEndSlotFromFp);
+            } else {
+              desc.info.set_index(-local_vars.Index());
+            }
+          }
+          desc.info.declaration_pos = local_vars.DeclarationTokenPos();
+          desc.info.begin_pos = local_vars.StartTokenPos();
+          desc.info.end_pos = local_vars.EndTokenPos();
+          vars.Add(desc);
+        } break;
+        case BytecodeLocalVariablesIterator::kContextVariable: {
+          ASSERT(local_vars.Index() >= 0);
+          const intptr_t context_variable_index = -local_vars.Index();
+          VarDesc desc;
+          desc.name = &Symbols::CurrentContextVar();
+          desc.info.set_kind(RawLocalVarDescriptors::kSavedCurrentContext);
+          desc.info.scope_id = 0;
+          desc.info.declaration_pos = TokenPosition::kMinSource;
+          desc.info.begin_pos = TokenPosition::kMinSource;
+          desc.info.end_pos = TokenPosition::kMinSource;
+          desc.info.set_index(context_variable_index);
+          vars.Add(desc);
+        } break;
+      }
+    }
+  }
+
+  if (vars.is_empty()) {
+    return Object::empty_var_descriptors().raw();
+  }
+  const LocalVarDescriptors& var_desc = LocalVarDescriptors::Handle(
+      zone, LocalVarDescriptors::New(vars.length()));
+  for (intptr_t i = 0; i < vars.length(); i++) {
+    var_desc.SetVar(i, *(vars[i].name), &vars[i].info);
+  }
+  return var_desc.raw();
+}
+#endif  // !defined(PRODUCT)
+
+static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 7,
+              "Cleanup support for old bytecode format versions");
+void BytecodeReader::UseBytecodeVersion(intptr_t version) {
+  Isolate* isolate = Isolate::Current();
+  bool using_old = isolate->is_using_old_bytecode_instructions();
+  bool using_new = isolate->is_using_new_bytecode_instructions();
+  if (version < 7) {
+    using_old = true;
+    isolate->set_is_using_old_bytecode_instructions(true);
+  } else {
+    using_new = true;
+    isolate->set_is_using_new_bytecode_instructions(true);
+  }
+
+  if (using_old && using_new) {
+    FATAL1(
+        "Unable to use both new and old bytecode instructions in the same Dart "
+        "isolate (%s)",
+        isolate->name());
+  }
 }
 
 bool IsStaticFieldGetterGeneratedAsInitializer(const Function& function,
                                                Zone* zone) {
-  ASSERT(function.kind() == RawFunction::kImplicitStaticFinalGetter);
+  ASSERT(function.kind() == RawFunction::kImplicitStaticGetter);
 
   const auto& field = Field::Handle(zone, function.accessor_field());
   return field.is_declared_in_bytecode() && field.is_const() &&
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h
index bb858c3..753bff9 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.h
+++ b/runtime/vm/compiler/frontend/bytecode_reader.h
@@ -24,10 +24,6 @@
   explicit BytecodeMetadataHelper(KernelReaderHelper* helper,
                                   ActiveClass* active_class);
 
-  bool HasBytecode(intptr_t node_offset);
-
-  void ReadMetadata(const Function& function);
-
   void ParseBytecodeFunction(ParsedFunction* parsed_function);
   void ParseBytecodeImplicitClosureFunction(ParsedFunction* parsed_function);
 
@@ -36,9 +32,6 @@
   // Returns true if class members are loaded.
   bool ReadMembers(intptr_t node_offset, const Class& cls, bool discard_fields);
 
-  // Read annotation at given offset.
-  RawObject* ReadAnnotation(intptr_t annotation_offset);
-
   RawLibrary* GetMainLibrary();
 
   RawArray* GetBytecodeComponent();
@@ -53,10 +46,12 @@
 // Helper class for reading bytecode.
 class BytecodeReaderHelper : public ValueObject {
  public:
-  explicit BytecodeReaderHelper(KernelReaderHelper* helper,
+  explicit BytecodeReaderHelper(TranslationHelper* translation_helper,
                                 ActiveClass* active_class,
                                 BytecodeComponentData* bytecode_component);
 
+  Reader& reader() { return reader_; }
+
   void ReadCode(const Function& function, intptr_t code_offset);
 
   void ReadMembers(const Class& cls,
@@ -72,7 +67,6 @@
   RawLibrary* ReadMain();
 
   RawArray* ReadBytecodeComponent(intptr_t md_offset);
-  RawArray* ReadBytecodeComponentV2(intptr_t md_offset);
 
   // Fills in [is_covariant] and [is_generic_covariant_impl] vectors
   // according to covariance attributes of [function] parameters.
@@ -110,6 +104,15 @@
     static const int kHasParameterFlagsFlag = 1 << 4;
     static const int kHasForwardingStubTargetFlag = 1 << 5;
     static const int kHasDefaultFunctionTypeArgsFlag = 1 << 6;
+    static const int kHasLocalVariablesFlag = 1 << 7;
+  };
+
+  // Closure code flags, must be in sync with ClosureCode constants in
+  // pkg/vm/lib/bytecode/declarations.dart.
+  struct ClosureCode {
+    static const int kHasExceptionsTableFlag = 1 << 0;
+    static const int kHasSourcePositionsFlag = 1 << 1;
+    static const int kHasLocalVariablesFlag = 1 << 2;
   };
 
   // Parameter flags, must be in sync with ParameterDeclaration constants in
@@ -132,7 +135,7 @@
 
    private:
     BytecodeReaderHelper* bytecode_reader_;
-    TypeArguments* const saved_type_parameters_;
+    const TypeArguments* const saved_type_parameters_;
   };
 
   class FunctionScope : public ValueObject {
@@ -174,6 +177,7 @@
   RawBytecode* ReadBytecode(const ObjectPool& pool);
   void ReadExceptionsTable(const Bytecode& bytecode, bool has_exceptions_table);
   void ReadSourcePositions(const Bytecode& bytecode, bool has_source_positions);
+  void ReadLocalVariables(const Bytecode& bytecode, bool has_local_variables);
   RawTypedData* NativeEntry(const Function& function,
                             const String& external_name);
   RawString* ConstructorName(const Class& cls, const String& name);
@@ -187,13 +191,14 @@
                               const Function& function,
                               const Function& target);
 
-  KernelReaderHelper* const helper_;
+  Reader reader_;
   TranslationHelper& translation_helper_;
   ActiveClass* const active_class_;
+  Thread* const thread_;
   Zone* const zone_;
   BytecodeComponentData* const bytecode_component_;
   Array* closures_ = nullptr;
-  TypeArguments* function_type_type_parameters_ = nullptr;
+  const TypeArguments* function_type_type_parameters_ = nullptr;
   PatchClass* patch_class_ = nullptr;
   Array* functions_ = nullptr;
   intptr_t function_index_ = 0;
@@ -215,6 +220,7 @@
     kMembersOffset,
     kCodesOffset,
     kSourcePositionsOffset,
+    kLocalVariablesOffset,
     kAnnotationsOffset,
     kNumFields
   };
@@ -229,6 +235,7 @@
   intptr_t GetMembersOffset() const;
   intptr_t GetCodesOffset() const;
   intptr_t GetSourcePositionsOffset() const;
+  intptr_t GetLocalVariablesOffset() const;
   intptr_t GetAnnotationsOffset() const;
   void SetObject(intptr_t index, const Object& obj) const;
   RawObject* GetObject(intptr_t index) const;
@@ -245,6 +252,7 @@
                        intptr_t members_offset,
                        intptr_t codes_offset,
                        intptr_t source_positions_offset,
+                       intptr_t local_variables_offset,
                        intptr_t annotations_offset,
                        Heap::Space space);
 
@@ -261,18 +269,28 @@
 
   // Read annotation for the given annotation field.
   static RawObject* ReadAnnotation(const Field& annotation_field);
+
+#if !defined(PRODUCT)
+  // Compute local variable descriptors for [function] with [bytecode].
+  static RawLocalVarDescriptors* ComputeLocalVarDescriptors(
+      Zone* zone,
+      const Function& function,
+      const Bytecode& bytecode);
+#endif
+
+  static void UseBytecodeVersion(intptr_t version);
 };
 
 class BytecodeSourcePositionsIterator : ValueObject {
  public:
   BytecodeSourcePositionsIterator(Zone* zone, const Bytecode& bytecode)
-      : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))),
-        pairs_remaining_(0),
-        cur_bci_(0),
-        cur_token_pos_(TokenPosition::kNoSource.value()) {
+      : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))) {
     if (bytecode.HasSourcePositions()) {
       reader_.set_offset(bytecode.source_positions_binary_offset());
       pairs_remaining_ = reader_.ReadUInt();
+      if (Isolate::Current()->is_using_old_bytecode_instructions()) {
+        pc_shifter_ = 2;
+      }
     }
   }
 
@@ -282,27 +300,135 @@
     }
     ASSERT(pairs_remaining_ > 0);
     --pairs_remaining_;
-    cur_bci_ += reader_.ReadUInt();
+    cur_bci_ += reader_.ReadUInt() << pc_shifter_;
     cur_token_pos_ += reader_.ReadSLEB128();
     return true;
   }
 
-  intptr_t BytecodeInstructionIndex() const { return cur_bci_; }
-
-  uword PcOffset() const {
-    return KernelBytecode::BytecodePcToOffset(BytecodeInstructionIndex(),
-                                              /* is_return_address = */ true);
-  }
+  uword PcOffset() const { return cur_bci_; }
 
   TokenPosition TokenPos() const { return TokenPosition(cur_token_pos_); }
 
  private:
   Reader reader_;
-  intptr_t pairs_remaining_;
-  intptr_t cur_bci_;
-  intptr_t cur_token_pos_;
+  intptr_t pairs_remaining_ = 0;
+  intptr_t pc_shifter_ = 0;
+  intptr_t cur_bci_ = 0;
+  intptr_t cur_token_pos_ = 0;
 };
 
+#if !defined(PRODUCT)
+class BytecodeLocalVariablesIterator : ValueObject {
+ public:
+  // These constants should match corresponding constants in
+  // pkg/vm/lib/bytecode/local_variable_table.dart.
+  enum {
+    kInvalid,
+    kScope,
+    kVariableDeclaration,
+    kContextVariable,
+  };
+
+  static const intptr_t kKindMask = 0xF;
+  static const intptr_t kIsCapturedFlag = 1 << 4;
+
+  BytecodeLocalVariablesIterator(Zone* zone, const Bytecode& bytecode)
+      : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))),
+        object_pool_(ObjectPool::Handle(zone, bytecode.object_pool())) {
+    if (bytecode.HasLocalVariablesInfo()) {
+      reader_.set_offset(bytecode.local_variables_binary_offset());
+      entries_remaining_ = reader_.ReadUInt();
+    }
+  }
+
+  bool MoveNext() {
+    if (entries_remaining_ == 0) {
+      return false;
+    }
+    ASSERT(entries_remaining_ > 0);
+    --entries_remaining_;
+    cur_kind_and_flags_ = reader_.ReadByte();
+    cur_start_pc_ += reader_.ReadSLEB128();
+    switch (Kind()) {
+      case kScope:
+        cur_end_pc_ = cur_start_pc_ + reader_.ReadUInt();
+        cur_index_ = reader_.ReadSLEB128();
+        cur_token_pos_ = reader_.ReadPosition();
+        cur_end_token_pos_ = reader_.ReadPosition();
+        break;
+      case kVariableDeclaration:
+        cur_index_ = reader_.ReadSLEB128();
+        cur_name_ = reader_.ReadUInt();
+        cur_type_ = reader_.ReadUInt();
+        cur_declaration_token_pos_ = reader_.ReadPosition();
+        cur_token_pos_ = reader_.ReadPosition();
+        break;
+      case kContextVariable:
+        cur_index_ = reader_.ReadSLEB128();
+        break;
+    }
+    return true;
+  }
+
+  intptr_t Kind() const { return cur_kind_and_flags_ & kKindMask; }
+  bool IsScope() const { return Kind() == kScope; }
+  bool IsVariableDeclaration() const { return Kind() == kVariableDeclaration; }
+  bool IsContextVariable() const { return Kind() == kContextVariable; }
+
+  intptr_t StartPC() const { return cur_start_pc_; }
+  intptr_t EndPC() const {
+    ASSERT(IsScope() || IsVariableDeclaration());
+    return cur_end_pc_;
+  }
+  intptr_t ContextLevel() const {
+    ASSERT(IsScope());
+    return cur_index_;
+  }
+  TokenPosition StartTokenPos() const {
+    ASSERT(IsScope() || IsVariableDeclaration());
+    return cur_token_pos_;
+  }
+  TokenPosition EndTokenPos() const {
+    ASSERT(IsScope() || IsVariableDeclaration());
+    return cur_end_token_pos_;
+  }
+  intptr_t Index() const {
+    ASSERT(IsVariableDeclaration() || IsContextVariable());
+    return cur_index_;
+  }
+  RawString* Name() const {
+    ASSERT(IsVariableDeclaration());
+    return String::RawCast(object_pool_.ObjectAt(cur_name_));
+  }
+  RawAbstractType* Type() const {
+    ASSERT(IsVariableDeclaration());
+    return AbstractType::RawCast(object_pool_.ObjectAt(cur_type_));
+  }
+  TokenPosition DeclarationTokenPos() const {
+    ASSERT(IsVariableDeclaration());
+    return cur_declaration_token_pos_;
+  }
+  bool IsCaptured() const {
+    ASSERT(IsVariableDeclaration());
+    return (cur_kind_and_flags_ & kIsCapturedFlag) != 0;
+  }
+
+ private:
+  Reader reader_;
+  const ObjectPool& object_pool_;
+  intptr_t entries_remaining_ = 0;
+  intptr_t cur_kind_and_flags_ = 0;
+  intptr_t cur_start_pc_ = 0;
+  intptr_t cur_end_pc_ = 0;
+  intptr_t cur_index_ = -1;
+  intptr_t cur_name_ = -1;
+  intptr_t cur_type_ = -1;
+  TokenPosition cur_token_pos_ = TokenPosition::kNoSource;
+  TokenPosition cur_declaration_token_pos_ = TokenPosition::kNoSource;
+  TokenPosition cur_end_token_pos_ = TokenPosition::kNoSource;
+};
+#endif  // !defined(PRODUCT)
+
 bool IsStaticFieldGetterGeneratedAsInitializer(const Function& function,
                                                Zone* zone);
 
diff --git a/runtime/vm/compiler/frontend/bytecode_scope_builder.cc b/runtime/vm/compiler/frontend/bytecode_scope_builder.cc
index 5143ae9..d31e00a 100644
--- a/runtime/vm/compiler/frontend/bytecode_scope_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_scope_builder.cc
@@ -106,7 +106,7 @@
       }
       break;
     }
-    case RawFunction::kImplicitStaticFinalGetter:
+    case RawFunction::kImplicitStaticGetter:
       ASSERT(!IsStaticFieldGetterGeneratedAsInitializer(function, Z));
       break;
     case RawFunction::kDynamicInvocationForwarder: {
diff --git a/runtime/vm/compiler/frontend/constant_evaluator.cc b/runtime/vm/compiler/frontend/constant_evaluator.cc
index 182e47d..a69ee37 100644
--- a/runtime/vm/compiler/frontend/constant_evaluator.cc
+++ b/runtime/vm/compiler/frontend/constant_evaluator.cc
@@ -579,7 +579,7 @@
     result_ ^= result.raw();
   } else {
     ASSERT(!receiver->IsNull());
-    result_ ^= (*receiver).raw();
+    result_ = (*receiver).raw();
   }
   if (I->obfuscate() &&
       (result_.clazz() == I->object_store()->symbol_class())) {
@@ -589,7 +589,7 @@
 }
 
 void ConstantEvaluator::EvaluateNot() {
-  result_ ^= Bool::Get(!EvaluateBooleanExpressionHere()).raw();
+  result_ = Bool::Get(!EvaluateBooleanExpressionHere()).raw();
 }
 
 void ConstantEvaluator::EvaluateLogicalExpression() {
@@ -1050,7 +1050,7 @@
   if (!IsBuildingFlowGraph()) return false;
 
   const Function& function = flow_graph_builder_->parsed_function_->function();
-  if ((function.kind() == RawFunction::kImplicitStaticFinalGetter ||
+  if ((function.kind() == RawFunction::kImplicitStaticGetter ||
        function.kind() == RawFunction::kStaticFieldInitializer) &&
       !I->CanOptimizeImmediately()) {
     // Don't cache constants in initializer expressions. They get
@@ -1083,7 +1083,7 @@
   if (!IsBuildingFlowGraph()) return;
 
   const Function& function = flow_graph_builder_->parsed_function_->function();
-  if ((function.kind() == RawFunction::kImplicitStaticFinalGetter ||
+  if ((function.kind() == RawFunction::kImplicitStaticGetter ||
        function.kind() == RawFunction::kStaticFieldInitializer) &&
       !I->CanOptimizeImmediately()) {
     // Don't cache constants in initializer expressions. They get
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 935ae39..706d2e6 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -165,13 +165,21 @@
       Field::ZoneHandle(Z, H.LookupFieldByKernelField(canonical_name));
   if (PeekTag() == kNullLiteral) {
     SkipExpression();  // read past the null literal.
-    field.RecordStore(Object::null_object());
+    if (H.thread()->IsMutatorThread()) {
+      field.RecordStore(Object::null_object());
+    } else {
+      ASSERT(field.is_nullable(/* silence_assert = */ true));
+    }
     return Fragment();
   }
 
   Fragment instructions;
   instructions += LoadLocal(parsed_function()->receiver_var());
+  // All closures created inside BuildExpression will have
+  // field.RawOwner() as its owner.
+  closure_owner_ = field.RawOwner();
   instructions += BuildExpression();
+  closure_owner_ = Object::null();
   instructions += flow_graph_builder_->StoreInstanceFieldGuarded(field, true);
   return instructions;
 }
@@ -936,7 +944,7 @@
       case RawFunction::kImplicitGetter:
       case RawFunction::kImplicitSetter:
         return B->BuildGraphOfFieldAccessor(function);
-      case RawFunction::kImplicitStaticFinalGetter: {
+      case RawFunction::kImplicitStaticGetter: {
         if (IsStaticFieldGetterGeneratedAsInitializer(function, Z)) {
           break;
         }
@@ -946,6 +954,8 @@
         return B->BuildGraphOfDynamicInvocationForwarder(function);
       case RawFunction::kMethodExtractor:
         return B->BuildGraphOfMethodExtractor(function);
+      case RawFunction::kNoSuchMethodDispatcher:
+        return B->BuildGraphOfNoSuchMethodDispatcher(function);
       default:
         break;
     }
@@ -957,24 +967,15 @@
     return bytecode_compiler.BuildGraph();
   }
 
-  // This is the legacy code path to handle bytecode attached to kernel AST
-  // members.
-  // TODO(alexmarkov): clean this up after dropping old format versions.
-  if ((FLAG_use_bytecode_compiler || FLAG_enable_interpreter) &&
-      function.IsBytecodeAllowed(Z)) {
-    if (!function.HasBytecode()) {
-      bytecode_metadata_helper_.ReadMetadata(function);
-    }
-    if (function.HasBytecode() &&
-        (function.kind() != RawFunction::kImplicitGetter) &&
-        (function.kind() != RawFunction::kImplicitSetter) &&
-        (function.kind() != RawFunction::kMethodExtractor)) {
-      BytecodeFlowGraphBuilder bytecode_compiler(
-          flow_graph_builder_, parsed_function(),
-          &(flow_graph_builder_->ic_data_array_));
-      return bytecode_compiler.BuildGraph();
-    }
-  }
+  // Certain special functions could have a VM-internal bytecode
+  // attached to them.
+  ASSERT((!function.HasBytecode()) ||
+         (function.kind() == RawFunction::kImplicitGetter) ||
+         (function.kind() == RawFunction::kImplicitSetter) ||
+         (function.kind() == RawFunction::kImplicitStaticGetter) ||
+         (function.kind() == RawFunction::kMethodExtractor) ||
+         (function.kind() == RawFunction::kInvokeFieldDispatcher) ||
+         (function.kind() == RawFunction::kNoSuchMethodDispatcher));
 
   ParseKernelASTFunction();
 
@@ -991,7 +992,7 @@
       return BuildGraphOfFunction(!function.IsFactory());
     }
     case RawFunction::kImplicitGetter:
-    case RawFunction::kImplicitStaticFinalGetter:
+    case RawFunction::kImplicitStaticGetter:
     case RawFunction::kImplicitSetter: {
       const Field& field = Field::Handle(Z, function.accessor_field());
       if (field.is_const() && field.IsUninitialized()) {
@@ -1053,7 +1054,7 @@
     case RawFunction::kClosureFunction:
     case RawFunction::kConstructor:
     case RawFunction::kImplicitGetter:
-    case RawFunction::kImplicitStaticFinalGetter:
+    case RawFunction::kImplicitStaticGetter:
     case RawFunction::kImplicitSetter:
     case RawFunction::kStaticFieldInitializer:
     case RawFunction::kMethodExtractor:
@@ -1977,7 +1978,7 @@
   // List of named.
   list_length = ReadListLength();  // read list length.
   if (argument_names != NULL && list_length > 0) {
-    *argument_names ^= Array::New(list_length, Heap::kOld);
+    *argument_names = Array::New(list_length, Heap::kOld);
   }
   for (intptr_t i = 0; i < list_length; ++i) {
     String& name =
@@ -2907,7 +2908,7 @@
 
     SkipListOfExpressions();
     intptr_t named_list_length = ReadListLength();
-    argument_names ^= Array::New(named_list_length, H.allocation_space());
+    argument_names = Array::New(named_list_length, H.allocation_space());
     for (intptr_t i = 0; i < named_list_length; i++) {
       const String& arg_name = H.DartSymbolObfuscate(ReadStringReference());
       argument_names.SetAt(i, arg_name);
@@ -4015,12 +4016,14 @@
       target_index, &outer_finally, &target_context_depth);
 
   Fragment instructions;
+  // Break statement should pause before manipulation of context, which
+  // will possibly cause debugger having incorrect context object.
+  if (NeedsDebugStepCheck(parsed_function()->function(), position)) {
+    instructions += DebugStepCheck(position);
+  }
   instructions +=
       TranslateFinallyFinalizers(outer_finally, target_context_depth);
   if (instructions.is_open()) {
-    if (NeedsDebugStepCheck(parsed_function()->function(), position)) {
-      instructions += DebugStepCheck(position);
-    }
     instructions += Goto(destination);
   }
   return instructions;
@@ -4903,8 +4906,14 @@
         name = &Symbols::AnonymousClosure();
       }
       // NOTE: This is not TokenPosition in the general sense!
-      function = Function::NewClosureFunction(
-          *name, parsed_function()->function(), position);
+      if (!closure_owner_.IsNull()) {
+        function = Function::NewClosureFunctionWithKind(
+            RawFunction::kClosureFunction, *name, parsed_function()->function(),
+            position, closure_owner_);
+      } else {
+        function = Function::NewClosureFunction(
+            *name, parsed_function()->function(), position);
+      }
 
       function.set_is_debuggable(function_node_helper.dart_async_marker_ ==
                                  FunctionNodeHelper::kSync);
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index edf29ea..2006924 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -43,7 +43,8 @@
         direct_call_metadata_helper_(this),
         inferred_type_metadata_helper_(this),
         procedure_attributes_metadata_helper_(this),
-        call_site_attributes_metadata_helper_(this, &type_translator_) {}
+        call_site_attributes_metadata_helper_(this, &type_translator_),
+        closure_owner_(Object::Handle(flow_graph_builder->zone_)) {}
 
   virtual ~StreamingFlowGraphBuilder() {}
 
@@ -358,6 +359,7 @@
   InferredTypeMetadataHelper inferred_type_metadata_helper_;
   ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_;
   CallSiteAttributesMetadataHelper call_site_attributes_metadata_helper_;
+  Object& closure_owner_;
 
   friend class KernelLoader;
 
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 848365d..6da7494 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -82,7 +82,6 @@
   }
   helper.SetJustRead(ConstructorHelper::kInitializers);
   BuildHash(helper.flags_);
-  BuildHash(helper.annotation_count_);
 }
 
 void KernelFingerprintHelper::CalculateArgumentsFingerprint() {
@@ -795,9 +794,9 @@
   uint32_t hash = 0;
   hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash());
 
-  type ^= klass.super_type();
+  type = klass.super_type();
   if (!type.IsNull()) {
-    name ^= type.Name();
+    name = type.Name();
     hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash());
   }
 
@@ -820,7 +819,7 @@
   // Calculate fingerprint for the interfaces.
   for (intptr_t i = 0; i < interfaces.Length(); ++i) {
     type ^= interfaces.At(i);
-    name ^= type.Name();
+    name = type.Name();
     hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash());
   }
 
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index ba7ab1b..b8be355 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -3,11 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/compiler/frontend/kernel_to_il.h"
-#include "vm/compiler/aot/precompiler.h"
-#include "vm/compiler/backend/locations.h"
 
+#include "platform/assert.h"
+#include "vm/compiler/aot/precompiler.h"
 #include "vm/compiler/backend/il.h"
 #include "vm/compiler/backend/il_printer.h"
+#include "vm/compiler/backend/locations.h"
 #include "vm/compiler/ffi.h"
 #include "vm/compiler/frontend/kernel_binary_flowgraph.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
@@ -15,6 +16,7 @@
 #include "vm/compiler/jit/compiler.h"
 #include "vm/kernel_loader.h"
 #include "vm/longjump.h"
+#include "vm/native_entry.h"
 #include "vm/object_store.h"
 #include "vm/report.h"
 #include "vm/resolver.h"
@@ -388,11 +390,12 @@
 Fragment FlowGraphBuilder::FfiCall(
     const Function& signature,
     const ZoneGrowableArray<Representation>& arg_reps,
-    const ZoneGrowableArray<Location>& arg_locs) {
+    const ZoneGrowableArray<Location>& arg_locs,
+    const ZoneGrowableArray<HostLocation>* arg_host_locs) {
   Fragment body;
 
-  FfiCallInstr* call =
-      new (Z) FfiCallInstr(Z, GetNextDeoptId(), signature, arg_reps, arg_locs);
+  FfiCallInstr* const call = new (Z) FfiCallInstr(
+      Z, GetNextDeoptId(), signature, arg_reps, arg_locs, arg_host_locs);
 
   for (intptr_t i = call->InputCount() - 1; i >= 0; --i) {
     call->SetInputAt(i, Pop());
@@ -1030,13 +1033,13 @@
   // instructions!
   body += LoadLocal(view_object);
   body += LoadLocal(typed_data);
-  body += LoadUntagged(TypedDataBase::data_field_offset());
+  body += LoadUntagged(compiler::target::TypedDataBase::data_field_offset());
   body += ConvertUntaggedToIntptr();
   body += LoadLocal(offset_in_bytes);
   body += UnboxSmiToIntptr();
   body += AddIntptrIntegers();
   body += ConvertIntptrToUntagged();
-  body += StoreUntagged(TypedDataView::data_field_offset());
+  body += StoreUntagged(compiler::target::TypedDataBase::data_field_offset());
 
   return body;
 }
@@ -1769,9 +1772,10 @@
     loop_body += LoadLocal(argument_count);
     loop_body += LoadLocal(index);
     loop_body += SmiBinaryOp(Token::kSUB, /*truncate=*/true);
-    loop_body += LoadFpRelativeSlot(
-        kWordSize * compiler::target::frame_layout.param_end_from_fp,
-        CompileType::Dynamic());
+    loop_body +=
+        LoadFpRelativeSlot(compiler::target::kWordSize *
+                               compiler::target::frame_layout.param_end_from_fp,
+                           CompileType::Dynamic());
     loop_body += StoreIndexed(kArrayCid);
 
     // ++i
@@ -1799,9 +1803,9 @@
           Function::ZoneHandle(Z, function.parent_function());
       const Class& owner = Class::ZoneHandle(Z, parent.Owner());
       AbstractType& type = AbstractType::ZoneHandle(Z);
-      type ^= Type::New(owner, TypeArguments::Handle(Z), owner.token_pos(),
-                        Heap::kOld);
-      type ^= ClassFinalizer::FinalizeType(owner, type);
+      type = Type::New(owner, TypeArguments::Handle(Z), owner.token_pos(),
+                       Heap::kOld);
+      type = ClassFinalizer::FinalizeType(owner, type);
       body += Constant(type);
     } else {
       body += LoadLocal(parsed_function_->current_context_var());
@@ -1949,14 +1953,9 @@
     function = owner.LookupFunction(func_name);
   }
 
-  auto& tmp = Object::Handle(Z);
-  tmp = function.Owner();
-  tmp = Class::Cast(tmp).library();
-  auto& library = Library::Cast(tmp);
-
   Object& options = Object::Handle(Z);
-  if (!library.FindPragma(thread_, function, Symbols::vm_trace_entrypoints(),
-                          &options) ||
+  if (!Library::FindPragma(thread_, /*only_core=*/false, function,
+                           Symbols::vm_trace_entrypoints(), &options) ||
       options.IsNull() || !options.IsClosure()) {
     return Drop();
   }
@@ -2433,16 +2432,41 @@
 
 Fragment FlowGraphBuilder::FfiUnboxedExtend(Representation representation,
                                             const AbstractType& ffi_type) {
-  const intptr_t width =
-      compiler::ffi::ElementSizeInBytes(ffi_type.type_class_id());
-  if (width >= compiler::ffi::kMinimumArgumentWidth) return {};
+  const SmallRepresentation from_representation =
+      compiler::ffi::TypeSmallRepresentation(ffi_type);
+  if (from_representation == kNoSmallRepresentation) return {};
 
-  auto* extend =
-      new (Z) UnboxedWidthExtenderInstr(Pop(), representation, width);
+  auto* extend = new (Z)
+      UnboxedWidthExtenderInstr(Pop(), representation, from_representation);
   Push(extend);
   return Fragment(extend);
 }
 
+Fragment FlowGraphBuilder::FfiExceptionalReturnValue(
+    const AbstractType& result_type,
+    Representation representation) {
+  ASSERT(optimizing_);
+  Object& result = Object::ZoneHandle(Z, Object::null());
+  if (representation == kUnboxedFloat || representation == kUnboxedDouble) {
+    result = Double::New(0.0, Heap::kOld);
+  } else {
+    result = Integer::New(0, Heap::kOld);
+  }
+  Fragment code;
+  code += Constant(result);
+  code += UnboxTruncate(representation);
+  return code;
+}
+
+#if !defined(TARGET_ARCH_DBC)
+Fragment FlowGraphBuilder::NativeReturn(Representation result) {
+  auto* instr = new (Z)
+      NativeReturnInstr(TokenPosition::kNoSource, Pop(), result,
+                        compiler::ffi::ResultLocation(result), DeoptId::kNone);
+  return Fragment(instr);
+}
+#endif
+
 Fragment FlowGraphBuilder::FfiPointerFromAddress(const Type& result_type) {
   Fragment test;
   TargetEntryInstr* null_entry;
@@ -2468,6 +2492,9 @@
   Fragment box(not_null_entry);
   {
     Class& result_class = Class::ZoneHandle(Z, result_type.type_class());
+    // This class might only be instantiated as a return type of ffi calls.
+    result_class.EnsureIsFinalized(thread_);
+
     TypeArguments& args = TypeArguments::ZoneHandle(Z, result_type.arguments());
 
     // A kernel transform for FFI in the front-end ensures that type parameters
@@ -2501,9 +2528,69 @@
   return Fragment(instr);
 }
 
+Fragment FlowGraphBuilder::FfiConvertArgumentToDart(
+    const AbstractType& ffi_type,
+    const Representation native_representation) {
+  Fragment body;
+  if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+    body += Box(kUnboxedFfiIntPtr);
+    body += FfiPointerFromAddress(Type::Cast(ffi_type));
+  } else if (compiler::ffi::NativeTypeIsVoid(ffi_type)) {
+    body += Drop();
+    body += NullConstant();
+  } else {
+    const Representation from_rep = native_representation;
+    const Representation to_rep = compiler::ffi::TypeRepresentation(ffi_type);
+    if (from_rep != to_rep) {
+      body += BitCast(from_rep, to_rep);
+    } else {
+      body += FfiUnboxedExtend(from_rep, ffi_type);
+    }
+    body += Box(to_rep);
+  }
+  return body;
+}
+
+Fragment FlowGraphBuilder::FfiConvertArgumentToNative(
+    const Function& function,
+    const AbstractType& ffi_type,
+    const Representation native_representation) {
+  Fragment body;
+  // Check for 'null'. Only ffi.Pointers are allowed to be null.
+  if (!compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+    body += LoadLocal(MakeTemporary());
+    body <<=
+        new (Z) CheckNullInstr(Pop(), String::ZoneHandle(Z, function.name()),
+                               GetNextDeoptId(), TokenPosition::kNoSource);
+  }
+
+  if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+    body += LoadAddressFromFfiPointer();
+    body += UnboxTruncate(kUnboxedFfiIntPtr);
+  } else {
+    Representation from_rep = compiler::ffi::TypeRepresentation(ffi_type);
+    body += UnboxTruncate(from_rep);
+
+    Representation to_rep = native_representation;
+    if (from_rep != to_rep) {
+      body += BitCast(from_rep, to_rep);
+    } else {
+      body += FfiUnboxedExtend(from_rep, ffi_type);
+    }
+  }
+  return body;
+}
+
 FlowGraph* FlowGraphBuilder::BuildGraphOfFfiTrampoline(
     const Function& function) {
-#if !defined(TARGET_ARCH_DBC)
+  if (function.FfiCallbackTarget() != Function::null()) {
+    return BuildGraphOfFfiCallback(function);
+  } else {
+    return BuildGraphOfFfiNative(function);
+  }
+}
+
+FlowGraph* FlowGraphBuilder::BuildGraphOfFfiNative(const Function& function) {
   graph_entry_ =
       new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
 
@@ -2519,7 +2606,13 @@
   body += CheckStackOverflowInPrologue(function.token_pos());
 
   const Function& signature = Function::ZoneHandle(Z, function.FfiCSignature());
+#if !defined(TARGET_ARCH_DBC)
   const auto& arg_reps = *compiler::ffi::ArgumentRepresentations(signature);
+  const ZoneGrowableArray<HostLocation>* arg_host_locs = nullptr;
+#else
+  const auto& arg_reps = *compiler::ffi::ArgumentHostRepresentations(signature);
+  const auto* arg_host_locs = compiler::ffi::HostArgumentLocations(arg_reps);
+#endif
   const auto& arg_locs = *compiler::ffi::ArgumentLocations(arg_reps);
 
   BuildArgumentTypeChecks(TypeChecksToBuild::kCheckAllTypeParameterBounds,
@@ -2530,29 +2623,7 @@
   for (intptr_t pos = 1; pos < function.num_fixed_parameters(); pos++) {
     body += LoadLocal(parsed_function_->ParameterVariable(pos));
     ffi_type = signature.ParameterTypeAt(pos);
-
-    // Check for 'null'. Only ffi.Pointers are allowed to be null.
-    if (!compiler::ffi::NativeTypeIsPointer(ffi_type)) {
-      body += LoadLocal(parsed_function_->ParameterVariable(pos));
-      body <<=
-          new (Z) CheckNullInstr(Pop(), String::ZoneHandle(Z, function.name()),
-                                 GetNextDeoptId(), TokenPosition::kNoSource);
-    }
-
-    if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
-      body += LoadAddressFromFfiPointer();
-      body += UnboxTruncate(kUnboxedFfiIntPtr);
-    } else {
-      Representation from_rep = compiler::ffi::TypeRepresentation(ffi_type);
-      body += UnboxTruncate(from_rep);
-
-      Representation to_rep = arg_reps[pos - 1];
-      if (from_rep != to_rep) {
-        body += BitCast(from_rep, to_rep);
-      } else {
-        body += FfiUnboxedExtend(from_rep, ffi_type);
-      }
-    }
+    body += FfiConvertArgumentToNative(function, ffi_type, arg_reps[pos - 1]);
   }
 
   // Push the function pointer, which is stored (boxed) in the first slot of the
@@ -2564,30 +2635,107 @@
                     Z, Class::Handle(I->object_store()->ffi_pointer_class()))
                     ->context_variables()[0]));
   body += UnboxTruncate(kUnboxedFfiIntPtr);
-  body += FfiCall(signature, arg_reps, arg_locs);
+  body += FfiCall(signature, arg_reps, arg_locs, arg_host_locs);
 
   ffi_type = signature.result_type();
-  if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
-    body += Box(kUnboxedFfiIntPtr);
-    body += FfiPointerFromAddress(Type::Cast(ffi_type));
-  } else if (compiler::ffi::NativeTypeIsVoid(ffi_type)) {
-    body += Drop();
-    body += NullConstant();
-  } else {
-    Representation from_rep = compiler::ffi::ResultRepresentation(signature);
-    Representation to_rep = compiler::ffi::TypeRepresentation(ffi_type);
-    if (from_rep != to_rep) {
-      body += BitCast(from_rep, to_rep);
-    } else {
-      body += FfiUnboxedExtend(from_rep, ffi_type);
-    }
-    body += Box(to_rep);
-  }
-
+#if !defined(TARGET_ARCH_DBC)
+  const Representation from_rep =
+      compiler::ffi::ResultRepresentation(signature);
+#else
+  const Representation from_rep =
+      compiler::ffi::ResultHostRepresentation(signature);
+#endif  // !defined(TARGET_ARCH_DBC)
+  body += FfiConvertArgumentToDart(ffi_type, from_rep);
   body += Return(TokenPosition::kNoSource);
 
   return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
                            prologue_info);
+}
+
+FlowGraph* FlowGraphBuilder::BuildGraphOfFfiCallback(const Function& function) {
+#if !defined(TARGET_ARCH_DBC)
+  const Function& signature = Function::ZoneHandle(Z, function.FfiCSignature());
+  const auto& arg_reps = *compiler::ffi::ArgumentRepresentations(signature);
+  const auto& arg_locs = *compiler::ffi::ArgumentLocations(arg_reps);
+  const auto& callback_locs =
+      *compiler::ffi::CallbackArgumentTranslator::TranslateArgumentLocations(
+          arg_locs);
+
+  graph_entry_ =
+      new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
+
+  auto* const native_entry = new (Z) NativeEntryInstr(
+      &arg_locs, graph_entry_, AllocateBlockId(), CurrentTryIndex(),
+      GetNextDeoptId(), function.FfiCallbackId());
+
+  graph_entry_->set_normal_entry(native_entry);
+
+  Fragment function_body(native_entry);
+  function_body += CheckStackOverflowInPrologue(function.token_pos());
+
+  // Wrap the entire method in a big try/catch. This is important to ensure that
+  // the VM does not crash if the callback throws an exception.
+  const intptr_t try_handler_index = AllocateTryIndex();
+  Fragment body = TryCatch(try_handler_index);
+  ++try_depth_;
+
+  // Box and push the arguments.
+  AbstractType& ffi_type = AbstractType::Handle(Z);
+  for (intptr_t i = 0, n = callback_locs.length(); i < n; ++i) {
+    ffi_type = signature.ParameterTypeAt(i + 1);
+    auto* parameter =
+        new (Z) NativeParameterInstr(callback_locs[i], arg_reps[i]);
+    Push(parameter);
+    body <<= parameter;
+    body += FfiConvertArgumentToDart(ffi_type, arg_reps[i]);
+    body += PushArgument();
+  }
+
+  // Call the target.
+  //
+  // TODO(36748): Determine the hot-reload semantics of callbacks and update the
+  // rebind-rule accordingly.
+  body += StaticCall(TokenPosition::kNoSource,
+                     Function::ZoneHandle(Z, function.FfiCallbackTarget()),
+                     callback_locs.length(), Array::empty_array(),
+                     ICData::kNoRebind);
+
+  ffi_type = signature.result_type();
+  const Representation result_rep =
+      compiler::ffi::ResultRepresentation(signature);
+  body += FfiConvertArgumentToNative(function, ffi_type, result_rep);
+  body += NativeReturn(result_rep);
+
+  --try_depth_;
+  function_body += body;
+
+  ++catch_depth_;
+  Fragment catch_body =
+      CatchBlockEntry(Array::empty_array(), try_handler_index,
+                      /*needs_stacktrace=*/true, /*is_synthesized=*/true);
+
+  catch_body += LoadLocal(CurrentException());
+  catch_body += PushArgument();
+  catch_body += LoadLocal(CurrentStackTrace());
+  catch_body += PushArgument();
+
+  // Find '_handleExposedException(e, st)' from ffi_patch.dart and call it.
+  const Library& ffi_lib =
+      Library::Handle(Z, Library::LookupLibrary(thread_, Symbols::DartFfi()));
+  const Function& handler = Function::ZoneHandle(
+      Z, ffi_lib.LookupFunctionAllowPrivate(Symbols::HandleExposedException()));
+  ASSERT(!handler.IsNull());
+  catch_body += StaticCall(TokenPosition::kNoSource, handler, /*num_args=*/2,
+                           /*arg_names=*/Array::empty_array(), ICData::kStatic);
+  catch_body += Drop();
+
+  catch_body += FfiExceptionalReturnValue(ffi_type, result_rep);
+  catch_body += NativeReturn(result_rep);
+  --catch_depth_;
+
+  PrologueInfo prologue_info(-1, -1);
+  return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
+                           prologue_info);
 #else
   UNREACHABLE();
 #endif
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 0b18641..9ccc1a94 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -101,6 +101,8 @@
   FlowGraph* BuildGraphOfNoSuchMethodDispatcher(const Function& function);
   FlowGraph* BuildGraphOfInvokeFieldDispatcher(const Function& function);
   FlowGraph* BuildGraphOfFfiTrampoline(const Function& function);
+  FlowGraph* BuildGraphOfFfiCallback(const Function& function);
+  FlowGraph* BuildGraphOfFfiNative(const Function& function);
 
   Fragment NativeFunctionBody(const Function& function,
                               LocalVariable* first_parameter);
@@ -151,9 +153,12 @@
                        intptr_t argument_count,
                        const Array& argument_names,
                        bool use_unchecked_entry = false);
-  Fragment FfiCall(const Function& signature,
-                   const ZoneGrowableArray<Representation>& arg_reps,
-                   const ZoneGrowableArray<Location>& arg_locs);
+
+  Fragment FfiCall(
+      const Function& signature,
+      const ZoneGrowableArray<Representation>& arg_reps,
+      const ZoneGrowableArray<Location>& arg_locs,
+      const ZoneGrowableArray<HostLocation>* arg_host_locs = nullptr);
 
   Fragment RethrowException(TokenPosition position, int catch_try_index);
   Fragment LoadLocal(LocalVariable* variable);
@@ -233,6 +238,26 @@
   // the pointer.
   Fragment FfiPointerFromAddress(const Type& result_type);
 
+  // Pushes an (unboxed) bogus value returned when a native -> Dart callback
+  // throws an exception.
+  Fragment FfiExceptionalReturnValue(const AbstractType& result_type,
+                                     const Representation target);
+
+  // Pops a Dart object and push the unboxed native version, according to the
+  // semantics of FFI argument translation.
+  Fragment FfiConvertArgumentToNative(
+      const Function& function,
+      const AbstractType& ffi_type,
+      const Representation native_representation);
+
+  // Reverse of 'FfiConvertArgumentToNative'.
+  Fragment FfiConvertArgumentToDart(const AbstractType& ffi_type,
+                                    const Representation native_representation);
+
+  // Return from a native -> Dart callback. Can only be used in conjunction with
+  // NativeEntry and NativeParameter are used.
+  Fragment NativeReturn(Representation result);
+
   // Bit-wise cast between representations.
   // Pops the input and pushes the converted result.
   // Currently only works with equal sizes and floating point <-> integer.
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 6f46ea7..b999e21 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -922,14 +922,11 @@
 }
 
 FieldHelper::FieldHelper(KernelReaderHelper* helper, intptr_t offset)
-    : helper_(helper),
-      next_read_(kStart),
-      has_function_literal_initializer_(false) {
+    : helper_(helper), next_read_(kStart) {
   helper_->SetOffset(offset);
 }
 
-void FieldHelper::ReadUntilExcluding(Field field,
-                                     bool detect_function_literal_initializer) {
+void FieldHelper::ReadUntilExcluding(Field field) {
   if (field <= next_read_) return;
 
   // Ordered with fall-through.
@@ -982,20 +979,6 @@
       FALL_THROUGH;
     case kInitializer:
       if (helper_->ReadTag() == kSomething) {
-        if (detect_function_literal_initializer &&
-            helper_->PeekTag() == kFunctionExpression) {
-          AlternativeReadingScope alt(&helper_->reader_);
-          Tag tag = helper_->ReadTag();
-          ASSERT(tag == kFunctionExpression);
-          helper_->ReadPosition();  // read position.
-
-          FunctionNodeHelper helper(helper_);
-          helper.ReadUntilIncluding(FunctionNodeHelper::kEndPosition);
-
-          has_function_literal_initializer_ = true;
-          function_literal_start_ = helper.position_;
-          function_literal_end_ = helper.end_position_;
-        }
         helper_->SkipExpression();  // read initializer.
       }
       if (++next_read_ == field) return;
@@ -1367,6 +1350,55 @@
   }
 }
 
+#if defined(DEBUG)
+
+void MetadataHelper::VerifyMetadataMappings(
+    const ExternalTypedData& metadata_mappings) {
+  const intptr_t kUInt32Size = 4;
+  Reader reader(metadata_mappings);
+  if (reader.size() == 0) {
+    return;
+  }
+
+  // Scan through metadata mappings in reverse direction.
+
+  // Read metadataMappings length.
+  intptr_t offset = reader.size() - kUInt32Size;
+  const intptr_t metadata_num = reader.ReadUInt32At(offset);
+
+  if (metadata_num == 0) {
+    ASSERT(metadata_mappings.LengthInBytes() == kUInt32Size);
+    return;
+  }
+
+  // Read metadataMappings elements.
+  for (intptr_t i = 0; i < metadata_num; ++i) {
+    // Read nodeOffsetToMetadataOffset length.
+    offset -= kUInt32Size;
+    const intptr_t mappings_num = reader.ReadUInt32At(offset);
+
+    // Skip nodeOffsetToMetadataOffset.
+    offset -= mappings_num * 2 * kUInt32Size;
+
+    // Verify that node offsets are sorted.
+    intptr_t prev_node_offset = -1;
+    reader.set_offset(offset);
+    for (intptr_t j = 0; j < mappings_num; ++j) {
+      const intptr_t node_offset = reader.ReadUInt32();
+      const intptr_t md_offset = reader.ReadUInt32();
+
+      ASSERT(node_offset >= 0 && md_offset >= 0);
+      ASSERT(node_offset > prev_node_offset);
+      prev_node_offset = node_offset;
+    }
+
+    // Skip tag.
+    offset -= kUInt32Size;
+  }
+}
+
+#endif  // defined(DEBUG)
+
 MetadataHelper::MetadataHelper(KernelReaderHelper* helper,
                                const char* tag,
                                bool precompiler_only)
@@ -1386,25 +1418,6 @@
   ASSERT((mappings_offset != 0) && (mappings_num != 0));
   mappings_offset_ = mappings_offset;
   mappings_num_ = mappings_num;
-
-#ifdef DEBUG
-  // Verify that node offsets are sorted.
-  {
-    Reader reader(H.metadata_mappings());
-    reader.set_offset(mappings_offset);
-
-    intptr_t prev_node_offset = -1;
-    for (intptr_t i = 0; i < mappings_num; ++i) {
-      intptr_t node_offset = reader.ReadUInt32();
-      intptr_t md_offset = reader.ReadUInt32();
-
-      ASSERT((node_offset >= 0) && (md_offset >= 0));
-      ASSERT(node_offset > prev_node_offset);
-      prev_node_offset = node_offset;
-    }
-  }
-#endif  // DEBUG
-
   last_node_offset_ = kIntptrMax;
   last_mapping_index_ = 0;
 }
@@ -2899,7 +2912,7 @@
   if (parameter_index < class_types.Length()) {
     // The index of the type parameter in [parameters] is
     // the same index into the `klass->type_parameters()` array.
-    result_ ^= class_types.TypeAt(parameter_index);
+    result_ = class_types.TypeAt(parameter_index);
     return;
   }
   parameter_index -= class_types.Length();
@@ -2924,7 +2937,7 @@
       //   }
       //
       if (class_types.Length() > parameter_index) {
-        result_ ^= class_types.TypeAt(parameter_index);
+        result_ = class_types.TypeAt(parameter_index);
         return;
       }
       parameter_index -= class_types.Length();
@@ -2936,7 +2949,7 @@
             : 0;
     if (procedure_type_parameter_count > 0) {
       if (procedure_type_parameter_count > parameter_index) {
-        result_ ^=
+        result_ =
             TypeArguments::Handle(Z, active_class_->member->type_parameters())
                 .TypeAt(parameter_index);
         if (finalize_) {
@@ -2951,7 +2964,7 @@
 
   if (active_class_->local_type_parameters != NULL) {
     if (parameter_index < active_class_->local_type_parameters->Length()) {
-      result_ ^= active_class_->local_type_parameters->TypeAt(parameter_index);
+      result_ = active_class_->local_type_parameters->TypeAt(parameter_index);
       if (finalize_) {
         result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_);
       }
@@ -2963,7 +2976,7 @@
   if (type_parameter_scope_ != NULL &&
       parameter_index < type_parameter_scope_->outer_parameter_count() +
                             type_parameter_scope_->parameter_count()) {
-    result_ ^= Type::DynamicType();
+    result_ = Type::DynamicType();
     return;
   }
 
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 9508b70..ad4898c 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -262,8 +262,8 @@
   TokenPosition end_position_;
   AsyncMarker async_marker_;
   AsyncMarker dart_async_marker_;
-  intptr_t total_parameter_count_;
-  intptr_t required_parameter_count_;
+  intptr_t total_parameter_count_ = 0;
+  intptr_t required_parameter_count_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -314,7 +314,7 @@
   }
 
   TokenPosition position_;
-  uint8_t flags_;
+  uint8_t flags_ = 0;
   StringIndex name_index_;
 
  private:
@@ -373,9 +373,9 @@
 
   TokenPosition position_;
   TokenPosition equals_position_;
-  uint8_t flags_;
+  uint8_t flags_ = 0;
   StringIndex name_index_;
-  intptr_t annotation_count_;
+  intptr_t annotation_count_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -416,9 +416,7 @@
   };
 
   explicit FieldHelper(KernelReaderHelper* helper)
-      : helper_(helper),
-        next_read_(kStart),
-        has_function_literal_initializer_(false) {}
+      : helper_(helper), next_read_(kStart) {}
 
   FieldHelper(KernelReaderHelper* helper, intptr_t offset);
 
@@ -426,8 +424,7 @@
     ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1));
   }
 
-  void ReadUntilExcluding(Field field,
-                          bool detect_function_literal_initializer = false);
+  void ReadUntilExcluding(Field field);
 
   void SetNext(Field field) { next_read_ = field; }
   void SetJustRead(Field field) { next_read_ = field + 1; }
@@ -440,30 +437,17 @@
     return (flags_ & kIsGenericCovariantImpl) != 0;
   }
 
-  bool FieldHasFunctionLiteralInitializer(TokenPosition* start,
-                                          TokenPosition* end) {
-    if (has_function_literal_initializer_) {
-      *start = function_literal_start_;
-      *end = function_literal_end_;
-    }
-    return has_function_literal_initializer_;
-  }
-
   NameIndex canonical_name_;
   TokenPosition position_;
   TokenPosition end_position_;
-  uint8_t flags_;
-  intptr_t source_uri_index_;
-  intptr_t annotation_count_;
+  uint8_t flags_ = 0;
+  intptr_t source_uri_index_ = 0;
+  intptr_t annotation_count_ = 0;
 
  private:
   KernelReaderHelper* helper_;
   intptr_t next_read_;
 
-  bool has_function_literal_initializer_;
-  TokenPosition function_literal_start_;
-  TokenPosition function_literal_end_;
-
   DISALLOW_COPY_AND_ASSIGN(FieldHelper);
 };
 
@@ -542,9 +526,9 @@
   TokenPosition position_;
   TokenPosition end_position_;
   Kind kind_;
-  uint8_t flags_;
-  intptr_t source_uri_index_;
-  intptr_t annotation_count_;
+  uint8_t flags_ = 0;
+  intptr_t source_uri_index_ = 0;
+  intptr_t annotation_count_ = 0;
 
   // Only valid if the 'isForwardingStub' flag is set.
   NameIndex forwarding_stub_super_target_;
@@ -606,9 +590,9 @@
   TokenPosition start_position_;
   TokenPosition position_;
   TokenPosition end_position_;
-  uint8_t flags_;
-  intptr_t source_uri_index_;
-  intptr_t annotation_count_;
+  uint8_t flags_ = 0;
+  intptr_t source_uri_index_ = 0;
+  intptr_t annotation_count_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -679,10 +663,10 @@
   TokenPosition position_;
   TokenPosition end_position_;
   StringIndex name_index_;
-  intptr_t source_uri_index_;
-  intptr_t annotation_count_;
-  intptr_t procedure_count_;
-  uint8_t flags_;
+  intptr_t source_uri_index_ = 0;
+  intptr_t annotation_count_ = 0;
+  intptr_t procedure_count_ = 0;
+  uint8_t flags_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -741,10 +725,10 @@
   bool IsExternal() const { return (flags_ & kExternal) != 0; }
   bool IsSynthetic() const { return (flags_ & kSynthetic) != 0; }
 
-  uint8_t flags_;
+  uint8_t flags_ = 0;
   NameIndex canonical_name_;
   StringIndex name_index_;
-  intptr_t source_uri_index_;
+  intptr_t source_uri_index_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -775,7 +759,7 @@
   };
 
   explicit LibraryDependencyHelper(KernelReaderHelper* helper)
-      : annotation_count_(0), helper_(helper), next_read_(kFileOffset) {}
+      : helper_(helper), next_read_(kFileOffset) {}
 
   void ReadUntilIncluding(Field field) {
     ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1));
@@ -783,10 +767,10 @@
 
   void ReadUntilExcluding(Field field);
 
-  uint8_t flags_;
+  uint8_t flags_ = 0;
   StringIndex name_index_;
   NameIndex target_library_canonical_name_;
-  intptr_t annotation_count_;
+  intptr_t annotation_count_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -803,6 +787,11 @@
                  const char* tag,
                  bool precompiler_only);
 
+#if defined(DEBUG)
+  static void VerifyMetadataMappings(
+      const ExternalTypedData& metadata_mappings);
+#endif
+
  protected:
   // Look for metadata mapping with node offset greater or equal than the given.
   intptr_t FindMetadataMapping(intptr_t node_offset);
diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc
index f0cb2cf..d4f7829 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.cc
+++ b/runtime/vm/compiler/frontend/prologue_builder.cc
@@ -190,8 +190,9 @@
   for (; param < num_fixed_params; ++param) {
     copy_args_prologue += LoadLocal(optional_count_var);
     copy_args_prologue += LoadFpRelativeSlot(
-        kWordSize * (compiler::target::frame_layout.param_end_from_fp +
-                     num_fixed_params - param),
+        compiler::target::kWordSize *
+            (compiler::target::frame_layout.param_end_from_fp +
+             num_fixed_params - param),
         ParameterType(ParameterVariable(param)));
     copy_args_prologue +=
         StoreLocalRaw(TokenPosition::kNoSource, ParameterVariable(param));
@@ -211,8 +212,9 @@
       Fragment good(supplied);
       good += LoadLocal(optional_count_var);
       good += LoadFpRelativeSlot(
-          kWordSize * (compiler::target::frame_layout.param_end_from_fp +
-                       num_fixed_params - param),
+          compiler::target::kWordSize *
+              (compiler::target::frame_layout.param_end_from_fp +
+               num_fixed_params - param),
           ParameterType(ParameterVariable(param)));
       good += StoreLocalRaw(TokenPosition::kNoSource, ParameterVariable(param));
       good += Drop();
@@ -249,7 +251,8 @@
     ASSERT(num_opt_named_params > 0);
 
     const intptr_t first_name_offset =
-        ArgumentsDescriptor::first_named_entry_offset() - Array::data_offset();
+        compiler::target::ArgumentsDescriptor::first_named_entry_offset() -
+        compiler::target::Array::data_offset();
 
     // Start by alphabetically sorting the names of the optional parameters.
     int* opt_param_position = Z->Alloc<int>(num_opt_named_params);
@@ -266,19 +269,23 @@
     for (intptr_t i = 0; param < num_params; ++param, ++i) {
       JoinEntryInstr* join = BuildJoinEntry();
 
-      copy_args_prologue +=
-          IntConstant(ArgumentsDescriptor::named_entry_size() / kWordSize);
+      copy_args_prologue += IntConstant(
+          compiler::target::ArgumentsDescriptor::named_entry_size() /
+          compiler::target::kWordSize);
       copy_args_prologue += LoadLocal(optional_count_vars_processed);
       copy_args_prologue += SmiBinaryOp(Token::kMUL, /* truncate= */ true);
       LocalVariable* tuple_diff = MakeTemporary();
 
       // name = arg_desc[names_offset + arg_desc_name_index + nameOffset]
       copy_args_prologue += LoadArgDescriptor();
-      copy_args_prologue += IntConstant(
-          (first_name_offset + ArgumentsDescriptor::name_offset()) / kWordSize);
+      copy_args_prologue +=
+          IntConstant((first_name_offset +
+                       compiler::target::ArgumentsDescriptor::name_offset()) /
+                      compiler::target::kWordSize);
       copy_args_prologue += LoadLocal(tuple_diff);
       copy_args_prologue += SmiBinaryOp(Token::kADD, /* truncate= */ true);
-      copy_args_prologue += LoadIndexed(/* index_scale = */ kWordSize);
+      copy_args_prologue +=
+          LoadIndexed(/* index_scale = */ compiler::target::kWordSize);
 
       // first name in sorted list of all names
       const String& param_name = String::ZoneHandle(
@@ -303,15 +310,17 @@
           // pos = arg_desc[names_offset + arg_desc_name_index + positionOffset]
           good += LoadArgDescriptor();
           good += IntConstant(
-              (first_name_offset + ArgumentsDescriptor::position_offset()) /
-              kWordSize);
+              (first_name_offset +
+               compiler::target::ArgumentsDescriptor::position_offset()) /
+              compiler::target::kWordSize);
           good += LoadLocal(tuple_diff);
           good += SmiBinaryOp(Token::kADD, /* truncate= */ true);
-          good += LoadIndexed(/* index_scale = */ kWordSize);
+          good += LoadIndexed(/* index_scale = */ compiler::target::kWordSize);
         }
         good += SmiBinaryOp(Token::kSUB, /* truncate= */ true);
         good += LoadFpRelativeSlot(
-            kWordSize * compiler::target::frame_layout.param_end_from_fp,
+            compiler::target::kWordSize *
+                compiler::target::frame_layout.param_end_from_fp,
             ParameterType(ParameterVariable(opt_param_position[i])));
 
         // Copy down.
@@ -417,7 +426,8 @@
   store_type_args += LoadArgDescriptor();
   store_type_args += LoadNativeField(Slot::ArgumentsDescriptor_count());
   store_type_args += LoadFpRelativeSlot(
-      kWordSize * (1 + compiler::target::frame_layout.param_end_from_fp),
+      compiler::target::kWordSize *
+          (1 + compiler::target::frame_layout.param_end_from_fp),
       CompileType::CreateNullable(/*is_nullable=*/true, kTypeArgumentsCid));
   store_type_args += StoreLocal(TokenPosition::kNoSource, type_args_var);
   store_type_args += Drop();
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 268e3d9..10f5dd6 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -306,7 +306,7 @@
       }
       break;
     }
-    case RawFunction::kImplicitStaticFinalGetter: {
+    case RawFunction::kImplicitStaticGetter: {
       ASSERT(helper_.PeekTag() == kField);
       ASSERT(function.IsStaticFunction());
       // In addition to static field initializers, scopes/local variables
@@ -390,6 +390,18 @@
                                             : Object::dynamic_type().raw()));
         scope_->InsertParameterAt(i, variable);
       }
+      // Callbacks need try/catch variables.
+      if (function.IsFfiTrampoline() &&
+          function.FfiCallbackTarget() != Function::null()) {
+        current_function_async_marker_ = FunctionNodeHelper::kSync;
+        ++depth_.try_;
+        AddTryVariables();
+        --depth_.try_;
+        ++depth_.catch_;
+        AddCatchVariables();
+        FinalizeCatchVariables();
+        --depth_.catch_;
+      }
       break;
     case RawFunction::kSignatureFunction:
     case RawFunction::kIrregexpFunction:
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index 85b9e11..5c51441 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -12,7 +12,10 @@
 #include "vm/compiler/backend/flow_graph_compiler.h"
 #include "vm/compiler/backend/il.h"
 #include "vm/compiler/backend/il_printer.h"
+#include "vm/compiler/backend/inliner.h"
 #include "vm/compiler/backend/linearscan.h"
+#include "vm/compiler/backend/range_analysis.h"
+#include "vm/compiler/compiler_pass.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/cpu.h"
 
@@ -97,14 +100,14 @@
   // Prepare for register allocation (cf. FinalizeGraph).
   graph->RemoveRedefinitions();
 
-  // Ensure loop hierarchy has been computed.
+  // Ensure dominators are re-computed. Normally this is done during SSA
+  // construction (which we don't do for graph intrinsics).
   GrowableArray<BitVector*> dominance_frontier;
   graph->ComputeDominators(&dominance_frontier);
-  graph->GetLoopHierarchy();
 
-  // Perform register allocation on the SSA graph.
-  FlowGraphAllocator allocator(*graph, true);  // Intrinsic mode.
-  allocator.AllocateRegisters();
+  CompilerPassState state(parsed_function.thread(), graph,
+                          /*speculative_inlining_policy*/ nullptr);
+  CompilerPass::RunGraphIntrinsicPipeline(&state);
 
   if (FLAG_support_il_printer && FLAG_print_flow_graph &&
       FlowGraphPrinter::ShouldPrint(function)) {
@@ -166,13 +169,38 @@
 
   if (RawObject::IsExternalTypedDataClassId(array_cid)) {
     array = builder.AddDefinition(new LoadUntaggedInstr(
-        new Value(array), ExternalTypedData::data_offset()));
+        new Value(array), target::TypedDataBase::data_field_offset()));
   }
 
   Definition* result = builder.AddDefinition(new LoadIndexedInstr(
       new Value(array), new Value(index),
-      Instance::ElementSizeFor(array_cid),  // index scale
+      target::Instance::ElementSizeFor(array_cid),  // index scale
       array_cid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+
+  // We don't perform [RangeAnalysis] for graph intrinsics. To inform the
+  // following boxing instruction about a more precise range we attach it here
+  // manually.
+  // http://dartbug.com/36632
+  const bool known_range =
+      array_cid == kTypedDataInt8ArrayCid ||
+      array_cid == kTypedDataUint8ArrayCid ||
+      array_cid == kTypedDataUint8ClampedArrayCid ||
+      array_cid == kExternalTypedDataUint8ArrayCid ||
+      array_cid == kExternalTypedDataUint8ClampedArrayCid ||
+      array_cid == kTypedDataInt16ArrayCid ||
+      array_cid == kTypedDataUint16ArrayCid ||
+      array_cid == kTypedDataInt32ArrayCid ||
+      array_cid == kTypedDataUint32ArrayCid || array_cid == kOneByteStringCid ||
+      array_cid == kTwoByteStringCid;
+
+  bool clear_environment = false;
+  if (known_range) {
+    Range range;
+    result->InferRange(/*range_analysis=*/nullptr, &range);
+    result->set_range(range);
+    clear_environment = range.Fits(RangeBoundary::kRangeBoundarySmi);
+  }
+
   // Box and/or convert result if necessary.
   switch (array_cid) {
     case kTypedDataInt32ArrayCid:
@@ -207,15 +235,18 @@
       break;
     case kArrayCid:
     case kImmutableArrayCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
       // Nothing to do.
       break;
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      result = builder.AddDefinition(
+          BoxInstr::Create(kUnboxedIntPtr, new Value(result)));
+      break;
     case kTypedDataInt64ArrayCid:
     case kTypedDataUint64ArrayCid:
       result = builder.AddDefinition(
@@ -225,6 +256,9 @@
       UNREACHABLE();
       break;
   }
+  if (clear_environment) {
+    result->AsBoxInteger()->ClearEnv();
+  }
   builder.AddReturn(new Value(result));
   return true;
 }
@@ -245,14 +279,15 @@
   // Value check/conversion.
   switch (array_cid) {
     case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
     case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
     case kTypedDataUint16ArrayCid:
-      builder.AddInstruction(new CheckSmiInstr(new Value(value), DeoptId::kNone,
-                                               builder.TokenPos()));
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      value = builder.AddUnboxInstr(kUnboxedIntPtr, new Value(value),
+                                    /* is_checked = */ false);
+      value->AsUnboxInteger()->mark_truncating();
       break;
     case kTypedDataInt32ArrayCid:
     case kExternalTypedDataInt32ArrayCid:
@@ -312,14 +347,14 @@
 
   if (RawObject::IsExternalTypedDataClassId(array_cid)) {
     array = builder.AddDefinition(new LoadUntaggedInstr(
-        new Value(array), ExternalTypedData::data_offset()));
+        new Value(array), target::TypedDataBase::data_field_offset()));
   }
   // No store barrier.
   ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) ||
          RawObject::IsTypedDataClassId(array_cid));
   builder.AddInstruction(new StoreIndexedInstr(
       new Value(array), new Value(index), new Value(value), kNoStoreBarrier,
-      Instance::ElementSizeFor(array_cid),  // index scale
+      target::Instance::ElementSizeFor(array_cid),  // index scale
       array_cid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
   // Return null.
   Definition* null_def = builder.AddNullDefinition();
@@ -447,15 +482,28 @@
   // For external strings: Load external data.
   if (cid == kExternalOneByteStringCid) {
     str = builder.AddDefinition(new LoadUntaggedInstr(
-        new Value(str), ExternalOneByteString::external_data_offset()));
+        new Value(str), target::ExternalOneByteString::external_data_offset()));
   } else if (cid == kExternalTwoByteStringCid) {
     str = builder.AddDefinition(new LoadUntaggedInstr(
-        new Value(str), ExternalTwoByteString::external_data_offset()));
+        new Value(str), target::ExternalTwoByteString::external_data_offset()));
   }
 
-  Definition* result = builder.AddDefinition(new LoadIndexedInstr(
-      new Value(str), new Value(index), Instance::ElementSizeFor(cid), cid,
-      kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+  Definition* load = builder.AddDefinition(new LoadIndexedInstr(
+      new Value(str), new Value(index), target::Instance::ElementSizeFor(cid),
+      cid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+
+  // We don't perform [RangeAnalysis] for graph intrinsics. To inform the
+  // following boxing instruction about a more precise range we attach it here
+  // manually.
+  // http://dartbug.com/36632
+  Range range;
+  load->InferRange(/*range_analysis=*/nullptr, &range);
+  load->set_range(range);
+
+  Definition* result =
+      builder.AddDefinition(BoxInstr::Create(kUnboxedIntPtr, new Value(load)));
+  result->AsBoxInteger()->ClearEnv();
+
   builder.AddReturn(new Value(result));
   return true;
 }
@@ -639,7 +687,7 @@
                          Slot::GrowableObjectArray_data(), builder.TokenPos()));
   Definition* result = builder.AddDefinition(new LoadIndexedInstr(
       new Value(backing_store), new Value(index),
-      Instance::ElementSizeFor(kArrayCid),  // index scale
+      target::Instance::ElementSizeFor(kArrayCid),  // index scale
       kArrayCid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
   builder.AddReturn(new Value(result));
   return true;
@@ -668,7 +716,7 @@
 
   builder.AddInstruction(new StoreIndexedInstr(
       new Value(array), new Value(index), new Value(value), kEmitStoreBarrier,
-      Instance::ElementSizeFor(kArrayCid),  // index scale
+      target::Instance::ElementSizeFor(kArrayCid),  // index scale
       kArrayCid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
   // Return null.
   Definition* null_def = builder.AddNullDefinition();
@@ -703,7 +751,7 @@
   builder.AddInstruction(new StoreIndexedInstr(
       new Value(backing_store), new Value(index), new Value(value),
       kEmitStoreBarrier,
-      Instance::ElementSizeFor(kArrayCid),  // index scale
+      target::Instance::ElementSizeFor(kArrayCid),  // index scale
       kArrayCid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
   // Return null.
   Definition* null_def = builder.AddNullDefinition();
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index ee1649f..84b3baf 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -59,7 +59,8 @@
     case MethodRecognizer::kUint64ArrayGetIndexed:
     case MethodRecognizer::kUint64ArraySetIndexed:
       // TODO(ajcbik): consider 32-bit as well.
-      if (kBitsPerWord == 64 && FlowGraphCompiler::SupportsUnboxedInt64()) {
+      if (target::kBitsPerWord == 64 &&
+          FlowGraphCompiler::SupportsUnboxedInt64()) {
         break;
       }
       if (FLAG_trace_intrinsifier) {
@@ -186,7 +187,7 @@
     return compiler->intrinsic_slow_path_label()->IsUnused();
   }
 
-#if !defined(HASH_IN_OBJECT_HEADER)
+#if !defined(TARGET_HASH_IN_OBJECT_HEADER)
   // These two are more complicated on 32 bit platforms, where the
   // identity hash is not stored in the header of the object.  We
   // therefore don't intrinsify them, falling back on the native C++
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 412e6b0..d42a3cc 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -84,10 +84,6 @@
             false,
             "Trace only optimizing compiler operations.");
 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler.");
-DEFINE_FLAG(bool,
-            verify_compiler,
-            false,
-            "Enable compiler verification assertions");
 
 DECLARE_FLAG(bool, enable_interpreter);
 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size);
@@ -101,7 +97,6 @@
 #endif
 
     FLAG_background_compilation = false;
-    FLAG_collect_code = false;
     FLAG_enable_mirrors = false;
     // TODO(dacoharkes): Ffi support in AOT
     // https://github.com/dart-lang/sdk/issues/35765
@@ -167,11 +162,10 @@
   RegExp& regexp = RegExp::Handle(parsed_function->function().regexp());
 
   const String& pattern = String::Handle(regexp.pattern());
-  const bool multiline = regexp.is_multi_line();
 
   RegExpCompileData* compile_data = new (zone) RegExpCompileData();
   // Parsing failures are handled in the RegExp factory constructor.
-  RegExpParser::ParseRegExp(pattern, multiline, compile_data);
+  RegExpParser::ParseRegExp(pattern, regexp.flags(), compile_data);
 
   regexp.set_num_bracket_expressions(compile_data->capture_count);
   regexp.set_capture_name_map(compile_data->capture_name_map);
@@ -264,9 +258,7 @@
 
 bool Compiler::CanOptimizeFunction(Thread* thread, const Function& function) {
 #if !defined(PRODUCT)
-  Isolate* isolate = thread->isolate();
-  if (isolate->debugger()->IsStepping() ||
-      isolate->debugger()->HasBreakpoint(function, thread->zone())) {
+  if (Debugger::IsDebugging(thread, function)) {
     // We cannot set breakpoints and single step in optimized code,
     // so do not optimize the function. Bump usage counter down to avoid
     // repeatedly entering the runtime for an optimization attempt.
@@ -427,12 +419,6 @@
   }
 #endif  // !defined(PRODUCT)
 
-  if (function.is_intrinsic() &&
-      (function.usage_counter() < Function::kGraceUsageCounter)) {
-    // Intrinsic functions may execute without incrementing their usage counter.
-    // Give them a non-zero initial usage to prevent premature code collection.
-    function.set_usage_counter(Function::kGraceUsageCounter);
-  }
   if (!function.IsOptimizable()) {
     // A function with huge unoptimized code can become non-optimizable
     // after generating unoptimized code.
@@ -786,7 +772,6 @@
         }
         done = true;
       }
-
     }
   }
   return result->raw();
@@ -794,7 +779,7 @@
 
 static RawObject* CompileFunctionHelper(CompilationPipeline* pipeline,
                                         const Function& function,
-                                        bool optimized,
+                                        volatile bool optimized,
                                         intptr_t osr_id) {
   ASSERT(!FLAG_precompiled_mode);
   ASSERT(!optimized || function.WasCompiled() || function.ForceOptimize());
@@ -894,6 +879,8 @@
       if (optimized) {
         if (error.IsLanguageError() &&
             LanguageError::Cast(error).kind() == Report::kBailout) {
+          // Functions which cannot deoptimize should never bail out.
+          ASSERT(!function.ForceOptimize());
           // Optimizer bailed out. Disable optimizations and never try again.
           if (trace_compiler) {
             THR_Print("--> disabling optimizations for '%s'\n",
@@ -1121,16 +1108,27 @@
 void Compiler::ComputeLocalVarDescriptors(const Code& code) {
   ASSERT(!code.is_optimized());
   const Function& function = Function::Handle(code.function());
-  ParsedFunction* parsed_function = new ParsedFunction(
-      Thread::Current(), Function::ZoneHandle(function.raw()));
   ASSERT(code.var_descriptors() == Object::null());
   // IsIrregexpFunction have eager var descriptors generation.
   ASSERT(!function.IsIrregexpFunction());
+  if (function.is_declared_in_bytecode()) {
+    auto& var_descs = LocalVarDescriptors::Handle();
+    if (function.HasBytecode()) {
+      const auto& bytecode = Bytecode::Handle(function.bytecode());
+      var_descs = bytecode.GetLocalVarDescriptors();
+    } else {
+      var_descs = Object::empty_var_descriptors().raw();
+    }
+    code.set_var_descriptors(var_descs);
+    return;
+  }
   // In background compilation, parser can produce 'errors": bailouts
   // if state changed while compiling in background.
   CompilerState state(Thread::Current());
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
+    ParsedFunction* parsed_function = new ParsedFunction(
+        Thread::Current(), Function::ZoneHandle(function.raw()));
     ZoneGrowableArray<const ICData*>* ic_data_array =
         new ZoneGrowableArray<const ICData*>();
     ZoneGrowableArray<intptr_t>* context_level_array =
@@ -1169,8 +1167,8 @@
   for (int i = 0; i < functions.Length(); i++) {
     func ^= functions.At(i);
     ASSERT(!func.IsNull());
-    if (!func.HasCode() &&
-        !func.is_abstract() && !func.IsRedirectingFactory()) {
+    if (!func.HasCode() && !func.is_abstract() &&
+        !func.IsRedirectingFactory()) {
       result = CompileFunction(thread, func);
       if (result.IsError()) {
         return Error::Cast(result).raw();
@@ -1404,18 +1402,16 @@
 
 BackgroundCompiler::BackgroundCompiler(Isolate* isolate)
     : isolate_(isolate),
-      queue_monitor_(new Monitor()),
+      queue_monitor_(),
       function_queue_(new BackgroundCompilationQueue()),
-      done_monitor_(new Monitor()),
+      done_monitor_(),
       running_(false),
       done_(true),
       disabled_depth_(0) {}
 
 // Fields all deleted in ::Stop; here clear them.
 BackgroundCompiler::~BackgroundCompiler() {
-  delete queue_monitor_;
   delete function_queue_;
-  delete done_monitor_;
 }
 
 void BackgroundCompiler::Run() {
@@ -1431,7 +1427,7 @@
       HANDLESCOPE(thread);
       Function& function = Function::Handle(zone);
       {
-        MonitorLocker ml(queue_monitor_);
+        MonitorLocker ml(&queue_monitor_);
         function = function_queue()->PeekFunction();
       }
       while (running_ && !function.IsNull()) {
@@ -1448,7 +1444,7 @@
 
         QueueElement* qelem = NULL;
         {
-          MonitorLocker ml(queue_monitor_);
+          MonitorLocker ml(&queue_monitor_);
           if (function_queue()->IsEmpty()) {
             // We are shutting down, queue was cleared.
             function = Function::null();
@@ -1477,7 +1473,7 @@
     Thread::ExitIsolateAsHelper();
     {
       // Wait to be notified when the work queue is not empty.
-      MonitorLocker ml(queue_monitor_);
+      MonitorLocker ml(&queue_monitor_);
       while (function_queue()->IsEmpty() && running_) {
         ml.Wait();
       }
@@ -1486,7 +1482,7 @@
 
   {
     // Notify that the thread is done.
-    MonitorLocker ml_done(done_monitor_);
+    MonitorLocker ml_done(&done_monitor_);
     done_ = true;
     ml_done.Notify();
   }
@@ -1500,7 +1496,7 @@
     isolate_->heap()->CollectMostGarbage();
   }
   {
-    MonitorLocker ml(queue_monitor_);
+    MonitorLocker ml(&queue_monitor_);
     ASSERT(running_);
     if (function_queue()->ContainsObj(function)) {
       return;
@@ -1534,7 +1530,7 @@
   ASSERT(thread->IsMutatorThread());
   ASSERT(!thread->IsAtSafepoint());
 
-  MonitorLocker ml(done_monitor_);
+  MonitorLocker ml(&done_monitor_);
   if (running_ || !done_) return;
   running_ = true;
   done_ = false;
@@ -1552,14 +1548,14 @@
   ASSERT(!thread->IsAtSafepoint());
 
   {
-    MonitorLocker ml(queue_monitor_);
+    MonitorLocker ml(&queue_monitor_);
     running_ = false;
     function_queue_->Clear();
     ml.Notify();  // Stop waiting for the queue.
   }
 
   {
-    MonitorLocker ml_done(done_monitor_);
+    MonitorLocker ml_done(&done_monitor_);
     while (!done_) {
       ml_done.WaitWithSafepointCheck(thread);
     }
diff --git a/runtime/vm/compiler/jit/compiler.h b/runtime/vm/compiler/jit/compiler.h
index c7e6412..b804a70 100644
--- a/runtime/vm/compiler/jit/compiler.h
+++ b/runtime/vm/compiler/jit/compiler.h
@@ -226,10 +226,10 @@
 
   Isolate* isolate_;
 
-  Monitor* queue_monitor_;  // Controls access to the queue.
+  Monitor queue_monitor_;  // Controls access to the queue.
   BackgroundCompilationQueue* function_queue_;
 
-  Monitor* done_monitor_;   // Notify/wait that the thread is done.
+  Monitor done_monitor_;    // Notify/wait that the thread is done.
   bool running_;            // While true, will try to read queue and compile.
   bool done_;               // True if the thread is done.
 
diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc
index 0973fed..e36397c 100644
--- a/runtime/vm/compiler/method_recognizer.cc
+++ b/runtime/vm/compiler/method_recognizer.cc
@@ -37,56 +37,40 @@
 
 intptr_t MethodRecognizer::ResultCidFromPragma(
     const Object& function_or_field) {
-  // TODO(vm-team): The caller should only call us if the
-  // function_or_field.has_pragma(). If this method turns out to be a
-  // performance problem nonetheless, we could consider adding a cache.
   auto T = Thread::Current();
   auto Z = T->zone();
-  auto& klass = Class::Handle(Z);
-  if (function_or_field.IsFunction()) {
-    auto& function = Function::Cast(function_or_field);
-    ASSERT(function.has_pragma());
-    klass = function.Owner();
-  } else {
-    auto& field = Field::Cast(function_or_field);
-    ASSERT(field.has_pragma());
-    klass = field.Owner();
-  }
-  auto& library = Library::Handle(Z, klass.library());
-  const bool can_use_pragma = library.IsAnyCoreLibrary();
-  if (can_use_pragma) {
-    auto& option = Object::Handle(Z);
-    if (library.FindPragma(T, function_or_field,
-                           Symbols::vm_exact_result_type(), &option)) {
-      if (option.IsType()) {
-        return Type::Cast(option).type_class_id();
-      } else if (option.IsString()) {
-        auto& str = String::Cast(option);
-        // 'str' should match the pattern '([^#]+)#([^#\?]+)' where group 1
-        // is the library URI and group 2 is the class name.
-        bool parse_failure = false;
-        intptr_t library_end = -1;
-        for (intptr_t i = 0; i < str.Length(); ++i) {
-          if (str.CharAt(i) == '#') {
-            if (library_end != -1) {
-              parse_failure = true;
-              break;
-            } else {
-              library_end = i;
-            }
+  auto& option = Object::Handle(Z);
+  if (Library::FindPragma(T, /*only_core=*/true, function_or_field,
+                          Symbols::vm_exact_result_type(), &option)) {
+    if (option.IsType()) {
+      return Type::Cast(option).type_class_id();
+    } else if (option.IsString()) {
+      auto& str = String::Cast(option);
+      // 'str' should match the pattern '([^#]+)#([^#\?]+)' where group 1
+      // is the library URI and group 2 is the class name.
+      bool parse_failure = false;
+      intptr_t library_end = -1;
+      for (intptr_t i = 0; i < str.Length(); ++i) {
+        if (str.CharAt(i) == '#') {
+          if (library_end != -1) {
+            parse_failure = true;
+            break;
+          } else {
+            library_end = i;
           }
         }
-        if (!parse_failure && library_end > 0) {
-          auto& tmp = String::Handle(Z);
-          tmp = String::SubString(str, 0, library_end, Heap::kOld);
-          library = Library::LookupLibrary(Thread::Current(), tmp);
-          if (!library.IsNull()) {
-            tmp = String::SubString(str, library_end + 1,
-                                    str.Length() - library_end - 1, Heap::kOld);
-            klass = library.LookupClassAllowPrivate(tmp);
-            if (!klass.IsNull()) {
-              return klass.id();
-            }
+      }
+      if (!parse_failure && library_end > 0) {
+        auto& tmp =
+            String::Handle(String::SubString(str, 0, library_end, Heap::kOld));
+        const auto& library = Library::Handle(Library::LookupLibrary(T, tmp));
+        if (!library.IsNull()) {
+          tmp = String::SubString(str, library_end + 1,
+                                  str.Length() - library_end - 1, Heap::kOld);
+          const auto& klass =
+              Class::Handle(library.LookupClassAllowPrivate(tmp));
+          if (!klass.IsNull()) {
+            return klass.id();
           }
         }
       }
@@ -100,24 +84,10 @@
     const Object& function_or_field) {
   auto T = Thread::Current();
   auto Z = T->zone();
-  auto& klass = Class::Handle(Z);
-  if (function_or_field.IsFunction()) {
-    auto& function = Function::Cast(function_or_field);
-    ASSERT(function.has_pragma());
-    klass = function.Owner();
-  } else {
-    auto& field = Field::Cast(function_or_field);
-    ASSERT(field.has_pragma());
-    klass = field.Owner();
-  }
-  auto& library = Library::Handle(Z, klass.library());
-  const bool can_use_pragma = library.IsAnyCoreLibrary();
-  if (can_use_pragma) {
-    auto& option = Object::Handle(Z);
-    if (library.FindPragma(T, function_or_field,
-                           Symbols::vm_non_nullable_result_type(), &option)) {
-      return true;
-    }
+  auto& option = Object::Handle(Z);
+  if (Library::FindPragma(T, /*only_core=*/true, function_or_field,
+                          Symbols::vm_non_nullable_result_type(), &option)) {
+    return true;
   }
 
   // If nothing said otherwise, the return type is nullable.
diff --git a/runtime/vm/compiler/offsets_extractor.cc b/runtime/vm/compiler/offsets_extractor.cc
new file mode 100644
index 0000000..0262779
--- /dev/null
+++ b/runtime/vm/compiler/offsets_extractor.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2019, 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 <iostream>
+
+#include "vm/compiler/runtime_api.h"
+#include "vm/compiler/runtime_offsets_list.h"
+#include "vm/dart_entry.h"
+#include "vm/longjump.h"
+#include "vm/native_arguments.h"
+#include "vm/native_entry.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/runtime_entry.h"
+#include "vm/symbols.h"
+#include "vm/timeline.h"
+
+#if defined(TARGET_ARCH_ARM)
+#define ARCH_DEF "defined(TARGET_ARCH_ARM)"
+#elif defined(TARGET_ARCH_X64)
+#define ARCH_DEF "defined(TARGET_ARCH_X64)"
+#elif defined(TARGET_ARCH_IA32)
+#define ARCH_DEF "defined(TARGET_ARCH_IA32)"
+#elif defined(TARGET_ARCH_ARM64)
+#define ARCH_DEF "defined(TARGET_ARCH_ARM64)"
+#elif defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
+#define ARCH_DEF "defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)"
+#elif defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
+#define ARCH_DEF "defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)"
+#else
+#error Unknown architecture
+#endif
+
+namespace dart {
+
+void Assert::Fail(const char* format, ...) {
+  abort();
+}
+
+class OffsetsExtractor : public AllStatic {
+ public:
+  static void DumpOffsets() {
+#define PRINT_FIELD_OFFSET(Class, Name)                                        \
+  std::cout << "static constexpr dart::compiler::target::word " #Class         \
+               "_" #Name " = "                                                 \
+            << Class::Name() << ";\n";
+
+#define PRINT_ARRAY_LAYOUT(Class, Name)                                        \
+  std::cout << "static constexpr dart::compiler::target::word " #Class         \
+               "_elements_start_offset = "                                     \
+            << Class::ArrayLayout::elements_start_offset() << ";\n";           \
+  std::cout << "static constexpr dart::compiler::target::word " #Class         \
+               "_element_size = "                                              \
+            << Class::ArrayLayout::kElementSize << ";\n";
+
+#define PRINT_ARRAY_STRUCTFIELD_OFFSET(Class, Name, ElementOffsetName,         \
+                                       FieldOffset)
+
+#define PRINT_SIZEOF(Class, Name, What)                                        \
+  std::cout << "static constexpr dart::compiler::target::word " #Class         \
+               "_" #Name " = "                                                 \
+            << sizeof(What) << ";\n";
+
+#define PRINT_RANGE(Class, Name, Type, First, Last, Filter)                    \
+  {                                                                            \
+    auto filter = Filter;                                                      \
+    bool comma = false;                                                        \
+    std::cout << "static dart::compiler::target::word " #Class "_" #Name       \
+                 "[] = {";                                                     \
+    for (intptr_t i = static_cast<intptr_t>(First);                            \
+         i <= static_cast<intptr_t>(Last); i++) {                              \
+      auto v = static_cast<Type>(i);                                           \
+      std::cout << (comma ? ", " : "") << (filter(v) ? Class::Name(v) : -1);   \
+      comma = true;                                                            \
+    }                                                                          \
+    std::cout << "};\n";                                                       \
+  }
+
+#define PRINT_CONSTANT(Class, Name)                                            \
+  std::cout << "static constexpr dart::compiler::target::word " #Class         \
+               "_" #Name " = "                                                 \
+            << Class::Name << ";\n";
+
+#define PRECOMP_NO_CHECK(Code) Code
+
+    OFFSETS_LIST(PRINT_FIELD_OFFSET, PRINT_ARRAY_LAYOUT,
+                 PRINT_ARRAY_STRUCTFIELD_OFFSET, PRINT_SIZEOF, PRINT_RANGE,
+                 PRINT_CONSTANT, PRECOMP_NO_CHECK)
+
+#undef PRINT_FIELD_OFFSET
+#undef PRINT_ARRAY_LAYOUT
+#undef PRINT_ARRAY_STRUCTFIELD_OFFSET
+#undef PRINT_SIZEOF
+#undef PRINT_RANGE
+#undef PRINT_CONSTANT
+#undef PRECOMP_NO_CHECK
+  }
+};
+
+}  // namespace dart
+
+int main(int argc, char* argv[]) {
+  std::cout << "#if " << ARCH_DEF << std::endl;
+  dart::OffsetsExtractor::DumpOffsets();
+  std::cout << "#endif  // " << ARCH_DEF << std::endl;
+  return 0;
+}
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 6fc48f4..ffd7255 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -42,6 +42,7 @@
   V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x38a80b0d)              \
   V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x40052c4e)          \
   V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x07b89f54)              \
+  V(ByteData, ., ByteDataFactory, 0x0)                                         \
   V(_ByteDataView, get:offsetInBytes, ByteDataViewOffsetInBytes, 0x0)          \
   V(_ByteDataView, get:_typedData, ByteDataViewTypedData, 0x0)                 \
   V(_TypedListView, get:offsetInBytes, TypedDataViewOffsetInBytes, 0x0)        \
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index 5d4d35f..aec5b3e 100644
--- a/runtime/vm/compiler/relocation.cc
+++ b/runtime/vm/compiler/relocation.cc
@@ -107,7 +107,8 @@
 
   for (intptr_t i = 0; i < code_objects_->length(); ++i) {
     current_caller = (*code_objects_)[i];
-    const intptr_t size = current_caller.instructions()->HeapSize();
+    const intptr_t size =
+        ImageWriter::SizeInSnapshot(current_caller.instructions());
     if (size > max_instructions_size_) {
       max_instructions_size_ = size;
     }
@@ -182,7 +183,7 @@
   }
   text_offsets_.Insert({instructions, next_text_offset_});
   commands_->Add(ImageWriterCommand(next_text_offset_, code));
-  next_text_offset_ += instructions->HeapSize();
+  next_text_offset_ += ImageWriter::SizeInSnapshot(instructions);
 
   return true;
 }
diff --git a/runtime/vm/compiler/relocation.h b/runtime/vm/compiler/relocation.h
index 80ca95a..91ed48c 100644
--- a/runtime/vm/compiler/relocation.h
+++ b/runtime/vm/compiler/relocation.h
@@ -34,7 +34,9 @@
         offset_into_target(offset_into_target) {}
 
   UnresolvedCall(const UnresolvedCall& other)
-      : caller(other.caller),
+      : IntrusiveDListEntry<UnresolvedCall>(),
+        IntrusiveDListEntry<UnresolvedCall, 2>(),
+        caller(other.caller),
         call_offset(other.call_offset),
         text_offset(other.text_offset),
         callee(other.callee),
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 8f927b8..79fff9b 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -4,8 +4,19 @@
 
 #include "vm/compiler/runtime_api.h"
 
+namespace dart {
+namespace compiler {
+namespace target {
+
+#include "vm/compiler/runtime_offsets_extracted.h"
+
+}  // namespace target
+}  // namespace compiler
+}  // namespace dart
+
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
+#include "vm/compiler/runtime_offsets_list.h"
 #include "vm/dart_entry.h"
 #include "vm/longjump.h"
 #include "vm/native_arguments.h"
@@ -20,6 +31,11 @@
 namespace compiler {
 
 bool IsSameObject(const Object& a, const Object& b) {
+  if (a.IsMint() && b.IsMint()) {
+    return Mint::Cast(a).value() == Mint::Cast(b).value();
+  } else if (a.IsDouble() && b.IsDouble()) {
+    return Double::Cast(a).value() == Double::Cast(b).value();
+  }
   return a.raw() == b.raw();
 }
 
@@ -49,7 +65,7 @@
 #undef DO
 
 bool IsInOldSpace(const Object& obj) {
-  return obj.IsOld();
+  return obj.IsSmi() || obj.IsOld();
 }
 
 intptr_t ObjectHash(const Object& obj) {
@@ -162,7 +178,8 @@
 }
 
 word TypedDataMaxNewSpaceElements(classid_t cid) {
-  return dart::TypedData::MaxNewSpaceElements(cid);
+  return (dart::Heap::kNewAllocatableSize - target::TypedData::InstanceSize()) /
+         TypedDataElementSizeInBytes(cid);
 }
 
 const Field& LookupMathRandomStateFieldOffset() {
@@ -215,23 +232,29 @@
 }
 
 word RuntimeEntry::OffsetFromThread() const {
-  return dart::Thread::OffsetFromThread(runtime_entry_);
+  return target::Thread::OffsetFromThread(runtime_entry_);
 }
 
 namespace target {
 
 const word kPageSize = dart::kPageSize;
-const word kPageSizeInWords = dart::kPageSizeInWords;
+const word kPageSizeInWords = dart::kPageSize / kWordSize;
 const word kPageMask = dart::kPageMask;
 
+static word TranslateOffsetInWordsToHost(word offset) {
+  RELEASE_ASSERT((offset % kWordSize) == 0);
+  return (offset / kWordSize) * dart::kWordSize;
+}
+
 uint32_t MakeTagWordForNewSpaceObject(classid_t cid, uword instance_size) {
-  return dart::RawObject::SizeTag::encode(instance_size) |
+  return dart::RawObject::SizeTag::encode(
+             TranslateOffsetInWordsToHost(instance_size)) |
          dart::RawObject::ClassIdTag::encode(cid) |
          dart::RawObject::NewBit::encode(true);
 }
 
 word Object::tags_offset() {
-  return dart::Object::tags_offset();
+  return 0;
 }
 
 const word RawObject::kCardRememberedBit = dart::RawObject::kCardRememberedBit;
@@ -247,7 +270,8 @@
 const word RawObject::kClassIdTagSize = dart::RawObject::kClassIdTagSize;
 
 const word RawObject::kSizeTagMaxSizeTag =
-    dart::RawObject::SizeTag::kMaxSizeTag;
+    dart::RawObject::SizeTag::kMaxSizeTagInUnitsOfAlignment *
+    ObjectAlignment::kObjectAlignment;
 
 const word RawObject::kTagBitsSizeTagPos =
     dart::RawObject::TagBits::kSizeTagPos;
@@ -262,21 +286,6 @@
   return dart::RawObject::IsTypedDataClassId(cid);
 }
 
-intptr_t ObjectPool::element_offset(intptr_t index) {
-  return dart::ObjectPool::element_offset(index);
-}
-
-word Class::type_arguments_field_offset_in_words_offset() {
-  return dart::Class::type_arguments_field_offset_in_words_offset();
-}
-
-word Class::declaration_type_offset() {
-  return dart::Class::declaration_type_offset();
-}
-
-word Class::num_type_arguments_offset_in_bytes() {
-  return dart::Class::num_type_arguments_offset();
-}
 
 const word Class::kNoTypeArguments = dart::Class::kNoTypeArguments;
 
@@ -284,8 +293,59 @@
   return handle.id();
 }
 
+static word TranslateOffsetInWords(word offset) {
+  RELEASE_ASSERT((offset % dart::kWordSize) == 0);
+  return (offset / dart::kWordSize) * kWordSize;
+}
+
+static uword GetInstanceSizeImpl(const dart::Class& handle) {
+  switch (handle.id()) {
+    case kMintCid:
+      return Mint::InstanceSize();
+    case kDoubleCid:
+      return Double::InstanceSize();
+    case kInt32x4Cid:
+      return Int32x4::InstanceSize();
+    case kFloat32x4Cid:
+      return Float32x4::InstanceSize();
+    case kFloat64x2Cid:
+      return Float64x2::InstanceSize();
+    case kObjectCid:
+      return Object::InstanceSize();
+    case kInstanceCid:
+      return Instance::InstanceSize();
+    case kGrowableObjectArrayCid:
+      return GrowableObjectArray::InstanceSize();
+    case kClosureCid:
+      return Closure::InstanceSize();
+    case kTypedDataBaseCid:
+      return TypedDataBase::InstanceSize();
+    case kLinkedHashMapCid:
+      return LinkedHashMap::InstanceSize();
+    case kByteBufferCid:
+    case kByteDataViewCid:
+    case kFfiPointerCid:
+#define HANDLE_CASE(clazz)                                                     \
+  case kTypedData##clazz##Cid:                                                 \
+  case kTypedData##clazz##ViewCid:                                             \
+  case kExternalTypedData##clazz##Cid:
+      CLASS_LIST_TYPED_DATA(HANDLE_CASE)
+#undef HANDLE_CASE
+      return TranslateOffsetInWords(handle.instance_size());
+    default:
+      if (handle.id() >= kNumPredefinedCids) {
+        return TranslateOffsetInWords(handle.instance_size());
+      }
+  }
+  FATAL3("Unsupported class for size translation: %s (id=%" Pd
+         ", kNumPredefinedCids=%d)\n",
+         handle.ToCString(), handle.id(), kNumPredefinedCids);
+  return -1;
+}
+
 uword Class::GetInstanceSize(const dart::Class& handle) {
-  return handle.instance_size();
+  return Utils::RoundUp(GetInstanceSizeImpl(handle),
+                        ObjectAlignment::kObjectAlignment);
 }
 
 intptr_t Class::NumTypeArguments(const dart::Class& klass) {
@@ -297,11 +357,7 @@
 }
 
 intptr_t Class::TypeArgumentsFieldOffset(const dart::Class& klass) {
-  return klass.type_arguments_field_offset();
-}
-
-intptr_t Class::InstanceSize(const dart::Class& klass) {
-  return klass.instance_size();
+  return TranslateOffsetInWords(klass.type_arguments_field_offset());
 }
 
 bool Class::TraceAllocation(const dart::Class& klass) {
@@ -309,57 +365,60 @@
 }
 
 word Instance::first_field_offset() {
-  return dart::Instance::NextFieldOffset();
+  return TranslateOffsetInWords(dart::Instance::NextFieldOffset());
 }
 
 word Instance::DataOffsetFor(intptr_t cid) {
-  return dart::Instance::DataOffsetFor(cid);
+  if (dart::RawObject::IsExternalTypedDataClassId(cid) ||
+      dart::RawObject::IsExternalStringClassId(cid)) {
+    // Elements start at offset 0 of the external data.
+    return 0;
+  }
+  if (dart::RawObject::IsTypedDataClassId(cid)) {
+    return TypedData::data_offset();
+  }
+  switch (cid) {
+    case kArrayCid:
+    case kImmutableArrayCid:
+      return Array::data_offset();
+    case kOneByteStringCid:
+      return OneByteString::data_offset();
+    case kTwoByteStringCid:
+      return TwoByteString::data_offset();
+    default:
+      UNIMPLEMENTED();
+      return Array::data_offset();
+  }
 }
 
 word Instance::ElementSizeFor(intptr_t cid) {
-  return dart::Instance::ElementSizeFor(cid);
-}
-
-word Function::code_offset() {
-  return dart::Function::code_offset();
-}
-
-word Function::entry_point_offset() {
-  return dart::Function::entry_point_offset();
-}
-
-word Function::usage_counter_offset() {
-  return dart::Function::usage_counter_offset();
-}
-
-word Function::unchecked_entry_point_offset() {
-  return dart::Function::unchecked_entry_point_offset();
+  if (dart::RawObject::IsExternalTypedDataClassId(cid) ||
+      dart::RawObject::IsTypedDataClassId(cid) ||
+      dart::RawObject::IsTypedDataViewClassId(cid)) {
+    return dart::TypedDataBase::ElementSizeInBytes(cid);
+  }
+  switch (cid) {
+    case kArrayCid:
+    case kImmutableArrayCid:
+      return kWordSize;
+    case kOneByteStringCid:
+      return dart::OneByteString::kBytesPerElement;
+    case kTwoByteStringCid:
+      return dart::TwoByteString::kBytesPerElement;
+    case kExternalOneByteStringCid:
+      return dart::ExternalOneByteString::kBytesPerElement;
+    case kExternalTwoByteStringCid:
+      return dart::ExternalTwoByteString::kBytesPerElement;
+    default:
+      UNIMPLEMENTED();
+      return 0;
+  }
 }
 
 word ICData::CodeIndexFor(word num_args) {
   return dart::ICData::CodeIndexFor(num_args);
 }
 
-word ICData::owner_offset() {
-  return dart::ICData::owner_offset();
-}
-
-word ICData::arguments_descriptor_offset() {
-  return dart::ICData::arguments_descriptor_offset();
-}
-
-word ICData::entries_offset() {
-  return dart::ICData::entries_offset();
-}
-
-word ICData::receivers_static_type_offset() {
-  return dart::ICData::receivers_static_type_offset();
-}
-
-word ICData::state_bits_offset() {
-  return dart::ICData::state_bits_offset();
-}
-
 word ICData::CountIndexFor(word num_args) {
   return dart::ICData::CountIndexFor(num_args);
 }
@@ -368,8 +427,8 @@
   return dart::ICData::TargetIndexFor(num_args);
 }
 
-word ICData::ExactnessOffsetFor(word num_args) {
-  return dart::ICData::ExactnessOffsetFor(num_args);
+word ICData::ExactnessIndexFor(word num_args) {
+  return dart::ICData::ExactnessIndexFor(num_args);
 }
 
 word ICData::TestEntryLengthFor(word num_args, bool exactness_check) {
@@ -380,143 +439,74 @@
   return dart::ICData::EntryPointIndexFor(num_args);
 }
 
-word ICData::NumArgsTestedShift() {
-  return dart::ICData::NumArgsTestedShift();
-}
-
-word ICData::NumArgsTestedMask() {
-  return dart::ICData::NumArgsTestedMask();
-}
-
 const word MegamorphicCache::kSpreadFactor =
     dart::MegamorphicCache::kSpreadFactor;
 
-word MegamorphicCache::mask_offset() {
-  return dart::MegamorphicCache::mask_offset();
-}
-word MegamorphicCache::buckets_offset() {
-  return dart::MegamorphicCache::buckets_offset();
-}
-word MegamorphicCache::arguments_descriptor_offset() {
-  return dart::MegamorphicCache::arguments_descriptor_offset();
-}
-
-word SingleTargetCache::lower_limit_offset() {
-  return dart::SingleTargetCache::lower_limit_offset();
-}
-word SingleTargetCache::upper_limit_offset() {
-  return dart::SingleTargetCache::upper_limit_offset();
-}
-word SingleTargetCache::entry_point_offset() {
-  return dart::SingleTargetCache::entry_point_offset();
-}
-word SingleTargetCache::target_offset() {
-  return dart::SingleTargetCache::target_offset();
-}
-
-const word Array::kMaxNewSpaceElements = dart::Array::kMaxNewSpaceElements;
-
 word Context::InstanceSize(word n) {
-  return dart::Context::InstanceSize(n);
+  return TranslateOffsetInWords(dart::Context::InstanceSize(n));
 }
 
 word Context::variable_offset(word n) {
-  return dart::Context::variable_offset(n);
+  return TranslateOffsetInWords(dart::Context::variable_offset(n));
 }
 
-word TypedData::InstanceSize() {
-  return sizeof(RawTypedData);
+#define DEFINE_FIELD(clazz, name)                                              \
+  word clazz::name() { return clazz##_##name; }
+
+#define DEFINE_ARRAY(clazz, name)                                              \
+  word clazz::name(intptr_t index) {                                           \
+    return clazz##_elements_start_offset + index * clazz##_element_size;       \
+  }
+
+#define DEFINE_ARRAY_STRUCTFIELD(clazz, name, element_offset, field_offset)
+
+#define DEFINE_SIZEOF(clazz, name, what)                                       \
+  word clazz::name() { return clazz##_##name; }
+
+#define DEFINE_RANGE(Class, Getter, Type, First, Last, Filter)                 \
+  word Class::Getter(Type index) {                                             \
+    return Class##_##Getter[static_cast<intptr_t>(index) -                     \
+                            static_cast<intptr_t>(First)];                     \
+  }
+
+#define DEFINE_CONSTANT(Class, Name) const word Class::Name = Class##_##Name;
+
+#define PRECOMP_NO_CHECK(Code) Code
+
+OFFSETS_LIST(DEFINE_FIELD,
+             DEFINE_ARRAY,
+             DEFINE_ARRAY_STRUCTFIELD,
+             DEFINE_SIZEOF,
+             DEFINE_RANGE,
+             DEFINE_CONSTANT,
+             PRECOMP_NO_CHECK)
+
+#undef DEFINE_FIELD
+#undef DEFINE_ARRAY
+#undef DEFINE_ARRAY_STRUCTFIELD
+#undef DEFINE_SIZEOF
+#undef DEFINE_RANGE
+#undef DEFINE_CONSTANT
+#undef PRECOMP_NO_CHECK
+
+const word StoreBufferBlock::kSize = dart::StoreBufferBlock::kSize;
+
+const word MarkingStackBlock::kSize = dart::MarkingStackBlock::kSize;
+
+word Instructions::HeaderSize() {
+  intptr_t alignment = OS::PreferredCodeAlignment();
+  intptr_t aligned_size =
+      Utils::RoundUp(Instructions::UnalignedHeaderSize(), alignment);
+  ASSERT(aligned_size == alignment);
+  return aligned_size;
 }
 
-word Array::header_size() {
-  return sizeof(dart::RawArray);
+#if !defined(TARGET_ARCH_DBC)
+word Thread::stack_overflow_shared_stub_entry_point_offset(bool fpu_regs) {
+  return fpu_regs ? stack_overflow_shared_with_fpu_regs_entry_point_offset()
+                  : stack_overflow_shared_without_fpu_regs_entry_point_offset();
 }
-
-#define CLASS_NAME_LIST(V)                                                     \
-  V(AbstractType, type_test_stub_entry_point_offset)                           \
-  V(ArgumentsDescriptor, count_offset)                                         \
-  V(ArgumentsDescriptor, type_args_len_offset)                                 \
-  V(Array, data_offset)                                                        \
-  V(Array, length_offset)                                                      \
-  V(Array, tags_offset)                                                        \
-  V(Array, type_arguments_offset)                                              \
-  V(ClassTable, table_offset)                                                  \
-  V(Closure, context_offset)                                                   \
-  V(Closure, delayed_type_arguments_offset)                                    \
-  V(Closure, function_offset)                                                  \
-  V(Closure, function_type_arguments_offset)                                   \
-  V(Closure, instantiator_type_arguments_offset)                               \
-  V(Code, object_pool_offset)                                                  \
-  V(Code, saved_instructions_offset)                                           \
-  V(Context, num_variables_offset)                                             \
-  V(Context, parent_offset)                                                    \
-  V(Double, value_offset)                                                      \
-  V(Float32x4, value_offset)                                                   \
-  V(Float64x2, value_offset)                                                   \
-  V(GrowableObjectArray, data_offset)                                          \
-  V(GrowableObjectArray, length_offset)                                        \
-  V(GrowableObjectArray, type_arguments_offset)                                \
-  V(HeapPage, card_table_offset)                                               \
-  V(Isolate, class_table_offset)                                               \
-  V(Isolate, current_tag_offset)                                               \
-  V(Isolate, default_tag_offset)                                               \
-  V(Isolate, ic_miss_code_offset)                                              \
-  V(Isolate, object_store_offset)                                              \
-  V(Isolate, user_tag_offset)                                                  \
-  V(MarkingStackBlock, pointers_offset)                                        \
-  V(MarkingStackBlock, top_offset)                                             \
-  V(Mint, value_offset)                                                        \
-  V(NativeArguments, argc_tag_offset)                                          \
-  V(NativeArguments, argv_offset)                                              \
-  V(NativeArguments, retval_offset)                                            \
-  V(NativeArguments, thread_offset)                                            \
-  V(ObjectStore, double_type_offset)                                           \
-  V(ObjectStore, int_type_offset)                                              \
-  V(ObjectStore, string_type_offset)                                           \
-  V(OneByteString, data_offset)                                                \
-  V(StoreBufferBlock, pointers_offset)                                         \
-  V(StoreBufferBlock, top_offset)                                              \
-  V(String, hash_offset)                                                       \
-  V(String, length_offset)                                                     \
-  V(SubtypeTestCache, cache_offset)                                            \
-  V(Thread, active_exception_offset)                                           \
-  V(Thread, active_stacktrace_offset)                                          \
-  V(Thread, async_stack_trace_offset)                                          \
-  V(Thread, auto_scope_native_wrapper_entry_point_offset)                      \
-  V(Thread, bool_false_offset)                                                 \
-  V(Thread, bool_true_offset)                                                  \
-  V(Thread, dart_stream_offset)                                                \
-  V(Thread, end_offset)                                                        \
-  V(Thread, global_object_pool_offset)                                         \
-  V(Thread, isolate_offset)                                                    \
-  V(Thread, marking_stack_block_offset)                                        \
-  V(Thread, no_scope_native_wrapper_entry_point_offset)                        \
-  V(Thread, object_null_offset)                                                \
-  V(Thread, predefined_symbols_address_offset)                                 \
-  V(Thread, resume_pc_offset)                                                  \
-  V(Thread, store_buffer_block_offset)                                         \
-  V(Thread, top_exit_frame_info_offset)                                        \
-  V(Thread, top_offset)                                                        \
-  V(Thread, top_resource_offset)                                               \
-  V(Thread, vm_tag_offset)                                                     \
-  V(Thread, safepoint_state_offset)                                            \
-  V(TimelineStream, enabled_offset)                                            \
-  V(TwoByteString, data_offset)                                                \
-  V(Type, arguments_offset)                                                    \
-  V(TypedDataBase, data_field_offset)                                          \
-  V(TypedDataBase, length_offset)                                              \
-  V(TypedData, data_offset)                                                    \
-  V(Type, hash_offset)                                                         \
-  V(TypeRef, type_offset)                                                      \
-  V(Type, signature_offset)                                                    \
-  V(Type, type_state_offset)                                                   \
-  V(UserTag, tag_offset)
-
-#define DEFINE_FORWARDER(clazz, name)                                          \
-  word clazz::name() { return dart::clazz::name(); }
-
-CLASS_NAME_LIST(DEFINE_FORWARDER)
-#undef DEFINE_FORWARDER
+#endif  // !defined(TARGET_ARCH_DBC)
 
 uword Thread::safepoint_state_unacquired() {
   return dart::Thread::safepoint_state_unacquired();
@@ -526,280 +516,83 @@
   return dart::Thread::safepoint_state_acquired();
 }
 
-const word HeapPage::kBytesPerCardLog2 = dart::HeapPage::kBytesPerCardLog2;
-
-const word String::kHashBits = dart::String::kHashBits;
-
-word String::InstanceSize() {
-  return sizeof(dart::RawString);
-}
-
-bool Heap::IsAllocatableInNewSpace(intptr_t instance_size) {
-  return dart::Heap::IsAllocatableInNewSpace(instance_size);
-}
-
-#if !defined(TARGET_ARCH_DBC)
-word Thread::write_barrier_code_offset() {
-  return dart::Thread::write_barrier_code_offset();
-}
-
-word Thread::array_write_barrier_code_offset() {
-  return dart::Thread::array_write_barrier_code_offset();
-}
-
-word Thread::fix_callers_target_code_offset() {
-  return dart::Thread::fix_callers_target_code_offset();
-}
-
-word Thread::fix_allocation_stub_code_offset() {
-  return dart::Thread::fix_allocation_stub_code_offset();
-}
-
-word Thread::call_to_runtime_entry_point_offset() {
-  return dart::Thread::call_to_runtime_entry_point_offset();
-}
-
-word Thread::null_error_shared_with_fpu_regs_entry_point_offset() {
-  return dart::Thread::null_error_shared_with_fpu_regs_entry_point_offset();
-}
-
-word Thread::null_error_shared_without_fpu_regs_entry_point_offset() {
-  return dart::Thread::null_error_shared_without_fpu_regs_entry_point_offset();
-}
-
-word Thread::monomorphic_miss_entry_offset() {
-  return dart::Thread::monomorphic_miss_entry_offset();
-}
-
-word Thread::write_barrier_mask_offset() {
-  return dart::Thread::write_barrier_mask_offset();
-}
-
-word Thread::write_barrier_entry_point_offset() {
-  return dart::Thread::write_barrier_entry_point_offset();
-}
-
-word Thread::array_write_barrier_entry_point_offset() {
-  return dart::Thread::array_write_barrier_entry_point_offset();
-}
-#endif  // !defined(TARGET_ARCH_DBC)
-
-#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
-    defined(TARGET_ARCH_X64)
-word Thread::write_barrier_wrappers_thread_offset(intptr_t regno) {
-  return dart::Thread::write_barrier_wrappers_thread_offset(
-      static_cast<Register>(regno));
-}
-#endif
-
-#if !defined(TARGET_ARCH_DBC)
-
-word Thread::monomorphic_miss_stub_offset() {
-  return dart::Thread::monomorphic_miss_stub_offset();
-}
-
-word Thread::ic_lookup_through_code_stub_offset() {
-  return dart::Thread::ic_lookup_through_code_stub_offset();
-}
-
-word Thread::lazy_specialize_type_test_stub_offset() {
-  return dart::Thread::lazy_specialize_type_test_stub_offset();
-}
-
-word Thread::slow_type_test_stub_offset() {
-  return dart::Thread::slow_type_test_stub_offset();
-}
-
-word Thread::call_to_runtime_stub_offset() {
-  return dart::Thread::call_to_runtime_stub_offset();
-}
-
-word Thread::invoke_dart_code_stub_offset() {
-  return dart::Thread::invoke_dart_code_stub_offset();
-}
-
-word Thread::interpret_call_entry_point_offset() {
-  return dart::Thread::interpret_call_entry_point_offset();
-}
-
-word Thread::invoke_dart_code_from_bytecode_stub_offset() {
-  return dart::Thread::invoke_dart_code_from_bytecode_stub_offset();
-}
-
-word Thread::null_error_shared_without_fpu_regs_stub_offset() {
-  return dart::Thread::null_error_shared_without_fpu_regs_stub_offset();
-}
-
-word Thread::null_error_shared_with_fpu_regs_stub_offset() {
-  return dart::Thread::null_error_shared_with_fpu_regs_stub_offset();
-}
-
-word Thread::stack_overflow_shared_without_fpu_regs_stub_offset() {
-  return dart::Thread::stack_overflow_shared_without_fpu_regs_stub_offset();
-}
-
-word Thread::stack_overflow_shared_with_fpu_regs_stub_offset() {
-  return dart::Thread::stack_overflow_shared_with_fpu_regs_stub_offset();
-}
-
-word Thread::lazy_deopt_from_return_stub_offset() {
-  return dart::Thread::lazy_deopt_from_return_stub_offset();
-}
-
-word Thread::lazy_deopt_from_throw_stub_offset() {
-  return dart::Thread::lazy_deopt_from_throw_stub_offset();
-}
-
-word Thread::deoptimize_stub_offset() {
-  return dart::Thread::deoptimize_stub_offset();
-}
-
-word Thread::enter_safepoint_stub_offset() {
-  return dart::Thread::enter_safepoint_stub_offset();
-}
-
-word Thread::exit_safepoint_stub_offset() {
-  return dart::Thread::exit_safepoint_stub_offset();
-}
-
-word Thread::execution_state_offset() {
-  return dart::Thread::execution_state_offset();
+uword Thread::generated_execution_state() {
+  return dart::Thread::ExecutionState::kThreadInGenerated;
 }
 
 uword Thread::native_execution_state() {
   return dart::Thread::ExecutionState::kThreadInNative;
 }
 
-uword Thread::generated_execution_state() {
-  return dart::Thread::ExecutionState::kThreadInGenerated;
-}
-
 uword Thread::vm_tag_compiled_id() {
   return dart::VMTag::kDartCompiledTagId;
 }
 
-#endif  // !defined(TARGET_ARCH_DBC)
-
-#define DECLARE_CONSTANT_OFFSET_GETTER(name)                                   \
-  word Thread::name##_address_offset() {                                       \
-    return dart::Thread::name##_address_offset();                              \
-  }
-THREAD_XMM_CONSTANT_LIST(DECLARE_CONSTANT_OFFSET_GETTER)
-#undef DECLARE_CONSTANT_OFFSET_GETTER
-
 word Thread::OffsetFromThread(const dart::Object& object) {
-  return dart::Thread::OffsetFromThread(object);
+  auto host_offset = dart::Thread::OffsetFromThread(object);
+  return object_null_offset() +
+         TranslateOffsetInWords(host_offset -
+                                dart::Thread::object_null_offset());
 }
 
-const word StoreBufferBlock::kSize = dart::StoreBufferBlock::kSize;
+intptr_t Thread::OffsetFromThread(const dart::RuntimeEntry* runtime_entry) {
+  auto host_offset = dart::Thread::OffsetFromThread(runtime_entry);
+  return AllocateArray_entry_point_offset() +
+         TranslateOffsetInWords(
+             host_offset - dart::Thread::AllocateArray_entry_point_offset());
+}
 
-const word MarkingStackBlock::kSize = dart::MarkingStackBlock::kSize;
+bool CanLoadFromThread(const dart::Object& object,
+                       intptr_t* offset /* = nullptr */) {
+  if (dart::Thread::CanLoadFromThread(object)) {
+    if (offset != nullptr) {
+      *offset = Thread::OffsetFromThread(object);
+    }
+    return true;
+  }
+  return false;
+}
 
 #if !defined(PRODUCT)
-word Isolate::single_step_offset() {
-  return dart::Isolate::single_step_offset();
-}
-#endif  // !defined(PRODUCT)
-
-#if !defined(PRODUCT)
-word ClassTable::ClassOffsetFor(intptr_t cid) {
-  return dart::ClassTable::ClassOffsetFor(cid);
-}
-
 word ClassTable::StateOffsetFor(intptr_t cid) {
   return dart::ClassTable::StateOffsetFor(cid);
 }
 
-word ClassTable::TableOffsetFor(intptr_t cid) {
-  return dart::ClassTable::TableOffsetFor(cid);
+word ClassTable::NewSpaceCounterOffsetFor(intptr_t index) {
+  return ClassOffsetFor(index) +
+         ClassHeapStats::allocated_since_gc_new_space_offset();
 }
 
-word ClassTable::CounterOffsetFor(intptr_t cid, bool is_new) {
-  return dart::ClassTable::CounterOffsetFor(cid, is_new);
-}
-
-word ClassTable::SizeOffsetFor(intptr_t cid, bool is_new) {
-  return dart::ClassTable::SizeOffsetFor(cid, is_new);
+word ClassTable::NewSpaceSizeOffsetFor(intptr_t index) {
+  return ClassOffsetFor(index) +
+         ClassHeapStats::allocated_size_since_gc_new_space_offset();
 }
 #endif  // !defined(PRODUCT)
 
-const word ClassTable::kSizeOfClassPairLog2 = dart::kSizeOfClassPairLog2;
+static_assert(
+    kSmiBits <= dart::kSmiBits,
+    "Expected that size of Smi on HOST is at least as large as on target.");
 
-const intptr_t Instructions::kPolymorphicEntryOffset =
-    dart::Instructions::kPolymorphicEntryOffset;
-
-const intptr_t Instructions::kMonomorphicEntryOffset =
-    dart::Instructions::kMonomorphicEntryOffset;
-
-intptr_t Instructions::HeaderSize() {
-  return dart::Instructions::HeaderSize();
-}
-
-intptr_t Code::entry_point_offset(CodeEntryKind kind) {
-  return dart::Code::entry_point_offset(kind);
-}
-
-const word SubtypeTestCache::kTestEntryLength =
-    dart::SubtypeTestCache::kTestEntryLength;
-const word SubtypeTestCache::kInstanceClassIdOrFunction =
-    dart::SubtypeTestCache::kInstanceClassIdOrFunction;
-const word SubtypeTestCache::kInstanceTypeArguments =
-    dart::SubtypeTestCache::kInstanceTypeArguments;
-const word SubtypeTestCache::kInstantiatorTypeArguments =
-    dart::SubtypeTestCache::kInstantiatorTypeArguments;
-const word SubtypeTestCache::kFunctionTypeArguments =
-    dart::SubtypeTestCache::kFunctionTypeArguments;
-const word SubtypeTestCache::kInstanceParentFunctionTypeArguments =
-    dart::SubtypeTestCache::kInstanceParentFunctionTypeArguments;
-const word SubtypeTestCache::kInstanceDelayedFunctionTypeArguments =
-    dart::SubtypeTestCache::kInstanceDelayedFunctionTypeArguments;
-const word SubtypeTestCache::kTestResult = dart::SubtypeTestCache::kTestResult;
-
-word Context::header_size() {
-  return sizeof(dart::RawContext);
-}
-
-#if !defined(PRODUCT)
-word ClassHeapStats::TraceAllocationMask() {
-  return dart::ClassHeapStats::TraceAllocationMask();
-}
-
-word ClassHeapStats::state_offset() {
-  return dart::ClassHeapStats::state_offset();
-}
-
-word ClassHeapStats::allocated_since_gc_new_space_offset() {
-  return dart::ClassHeapStats::allocated_since_gc_new_space_offset();
-}
-
-word ClassHeapStats::allocated_size_since_gc_new_space_offset() {
-  return dart::ClassHeapStats::allocated_size_since_gc_new_space_offset();
-}
-#endif  // !defined(PRODUCT)
-
-const word Smi::kBits = dart::Smi::kBits;
 bool IsSmi(const dart::Object& a) {
-  return a.IsSmi();
+  return a.IsSmi() && Utils::IsInt(kSmiBits + 1, dart::Smi::Cast(a).Value());
+}
+
+bool IsSmi(int64_t v) {
+  return Utils::IsInt(kSmiBits + 1, v);
 }
 
 word ToRawSmi(const dart::Object& a) {
-  ASSERT(a.IsSmi());
-  return reinterpret_cast<word>(a.raw());
+  RELEASE_ASSERT(IsSmi(a));
+  return static_cast<word>(reinterpret_cast<intptr_t>(a.raw()));
 }
 
 word ToRawSmi(intptr_t value) {
   return dart::Smi::RawValue(value);
 }
 
-bool CanLoadFromThread(const dart::Object& object,
-                       word* offset /* = nullptr */) {
-  if (dart::Thread::CanLoadFromThread(object)) {
-    if (offset != nullptr) {
-      *offset = dart::Thread::OffsetFromThread(object);
-    }
-    return true;
-  }
-  return false;
+word SmiValue(const dart::Object& a) {
+  RELEASE_ASSERT(IsSmi(a));
+  return static_cast<word>(dart::Smi::Cast(a).Value());
 }
 
 #if defined(TARGET_ARCH_IA32)
@@ -822,15 +615,8 @@
 }
 #endif  // defined(TARGET_ARCH_IA32)
 
-const word NativeEntry::kNumCallWrapperArguments =
-    dart::NativeEntry::kNumCallWrapperArguments;
-
-word NativeArguments::StructSize() {
-  return sizeof(dart::NativeArguments);
-}
-
 word RegExp::function_offset(classid_t cid, bool sticky) {
-  return dart::RegExp::function_offset(cid, sticky);
+  return TranslateOffsetInWords(dart::RegExp::function_offset(cid, sticky));
 }
 
 const word Symbols::kNumberOfOneCharCodeSymbols =
@@ -838,6 +624,28 @@
 const word Symbols::kNullCharCodeSymbolOffset =
     dart::Symbols::kNullCharCodeSymbolOffset;
 
+const word String::kHashBits = dart::String::kHashBits;
+
+bool Heap::IsAllocatableInNewSpace(intptr_t instance_size) {
+  return dart::Heap::IsAllocatableInNewSpace(instance_size);
+}
+
+word Field::OffsetOf(const dart::Field& field) {
+  return TranslateOffsetInWords(field.Offset());
+}
+
+}  // namespace target
+}  // namespace compiler
+}  // namespace dart
+
+#else
+
+namespace dart {
+namespace compiler {
+namespace target {
+
+const word Array::kMaxElements = Array_kMaxElements;
+
 }  // namespace target
 }  // namespace compiler
 }  // namespace dart
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index d910575..57f4312 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -23,6 +23,7 @@
 #include "vm/bitfield.h"
 #include "vm/class_id.h"
 #include "vm/code_entry_kind.h"
+#include "vm/constants.h"
 #include "vm/frame_layout.h"
 #include "vm/pointer_tagging.h"
 #include "vm/runtime_entry_list.h"
@@ -64,12 +65,16 @@
 class InvalidClass {};
 extern InvalidClass kWordSize;
 extern InvalidClass kWordSizeLog2;
+extern InvalidClass kBitsPerWord;
 extern InvalidClass kNewObjectAlignmentOffset;
 extern InvalidClass kOldObjectAlignmentOffset;
 extern InvalidClass kNewObjectBitPosition;
 extern InvalidClass kObjectAlignment;
 extern InvalidClass kObjectAlignmentLog2;
 extern InvalidClass kObjectAlignmentMask;
+extern InvalidClass kSmiBits;
+extern InvalidClass kSmiMin;
+extern InvalidClass kSmiMax;
 
 static constexpr intptr_t kHostWordSize = dart::kWordSize;
 static constexpr intptr_t kHostWordSizeLog2 = dart::kWordSizeLog2;
@@ -252,21 +257,30 @@
 //    - sizes of structures
 namespace target {
 
-// Currently we define target::word to match dart::word which represents
-// host word.
-//
-// Once refactoring of the compiler is complete we will switch target::word
-// to be independent from host word.
-typedef dart::word word;
-typedef dart::uword uword;
+#if defined(TARGET_ARCH_IS_32_BIT)
+typedef int32_t word;
+typedef uint32_t uword;
+static constexpr word kWordSize = 4;
+static constexpr word kWordSizeLog2 = 2;
+#elif defined(TARGET_ARCH_IS_64_BIT)
+typedef int64_t word;
+typedef uint64_t uword;
+static constexpr word kWordSize = 8;
+static constexpr word kWordSizeLog2 = 3;
+#else
+#error "Unsupported architecture"
+#endif
 
-static constexpr word kWordSize = dart::kWordSize;
-static constexpr word kWordSizeLog2 = dart::kWordSizeLog2;
+static constexpr word kBitsPerWord = 8 * kWordSize;
 static_assert((1 << kWordSizeLog2) == kWordSize,
               "kWordSizeLog2 should match kWordSize");
 
 using ObjectAlignment = dart::ObjectAlignment<kWordSize, kWordSizeLog2>;
 
+const intptr_t kSmiBits = kBitsPerWord - 2;
+const intptr_t kSmiMax = (static_cast<intptr_t>(1) << kSmiBits) - 1;
+const intptr_t kSmiMin = -(static_cast<intptr_t>(1) << kSmiBits);
+
 // Information about heap pages.
 extern const word kPageSize;
 extern const word kPageSizeInWords;
@@ -291,10 +305,14 @@
 // Target specific information about objects.
 //
 
-// Returns true if the given object can be represented as a Smi on the
-// target platform.
+// Returns true if the given object can be represented as a Smi on the target
+// platform.
 bool IsSmi(const dart::Object& a);
 
+// Returns true if the given value can be represented as a Smi on the target
+// platform.
+bool IsSmi(int64_t value);
+
 // Return raw Smi representation of the given object for the target platform.
 word ToRawSmi(const dart::Object& a);
 
@@ -305,10 +323,12 @@
 // as a Smi.
 word ToRawSmi(intptr_t value);
 
+word SmiValue(const dart::Object& a);
+
 // If the given object can be loaded from the thread on the target then
 // return true and set offset (if provided) to the offset from the
 // thread pointer to a field that contains the object.
-bool CanLoadFromThread(const dart::Object& object, word* offset = nullptr);
+bool CanLoadFromThread(const dart::Object& object, intptr_t* offset = nullptr);
 
 // On IA32 we can embed raw pointers into generated code.
 #if defined(TARGET_ARCH_IA32)
@@ -350,12 +370,13 @@
  public:
   // Offset of the tags word.
   static word tags_offset();
+  static word InstanceSize();
 };
 
 class ObjectPool : public AllStatic {
  public:
   // Return offset to the element with the given [index] in the object pool.
-  static intptr_t element_offset(intptr_t index);
+  static word element_offset(intptr_t index);
 };
 
 class Class : public AllStatic {
@@ -364,8 +385,10 @@
 
   static word declaration_type_offset();
 
+  static word super_type_offset();
+
   // The offset of the RawObject::num_type_arguments_ field in bytes.
-  static word num_type_arguments_offset_in_bytes();
+  static word num_type_arguments_offset();
 
   // The value used if no type arguments vector is present.
   static const word kNoTypeArguments;
@@ -385,9 +408,6 @@
   // Returns the offset (in bytes) of the type arguments vector.
   static intptr_t TypeArgumentsFieldOffset(const dart::Class& klass);
 
-  // Returns the instance size (in bytes).
-  static intptr_t InstanceSize(const dart::Class& klass);
-
   // Whether to trace allocation for this klass.
   static bool TraceAllocation(const dart::Class& klass);
 };
@@ -398,6 +418,7 @@
   static word first_field_offset();
   static word DataOffsetFor(intptr_t cid);
   static word ElementSizeFor(intptr_t cid);
+  static word InstanceSize();
 };
 
 class Function : public AllStatic {
@@ -419,7 +440,7 @@
   static word CodeIndexFor(word num_args);
   static word CountIndexFor(word num_args);
   static word TargetIndexFor(word num_args);
-  static word ExactnessOffsetFor(word num_args);
+  static word ExactnessIndexFor(word num_args);
   static word TestEntryLengthFor(word num_args, bool exactness_check);
   static word EntryPointIndexFor(word num_args);
   static word NumArgsTestedShift();
@@ -449,7 +470,9 @@
   static word data_offset();
   static word type_arguments_offset();
   static word length_offset();
+  static word element_offset(intptr_t index);
 
+  static const word kMaxElements;
   static const word kMaxNewSpaceElements;
 };
 
@@ -458,12 +481,14 @@
   static word data_offset();
   static word type_arguments_offset();
   static word length_offset();
+  static word InstanceSize();
 };
 
 class TypedDataBase : public AllStatic {
  public:
   static word data_field_offset();
   static word length_offset();
+  static word InstanceSize();
 };
 
 class TypedData : public AllStatic {
@@ -472,10 +497,41 @@
   static word InstanceSize();
 };
 
+class ExternalTypedData : public AllStatic {
+ public:
+  static word data_offset();
+};
+
+class TypedDataView : public AllStatic {
+ public:
+  static word offset_in_bytes_offset();
+  static word data_offset();
+};
+
+class LinkedHashMap : public AllStatic {
+ public:
+  static word index_offset();
+  static word data_offset();
+  static word hash_mask_offset();
+  static word used_data_offset();
+  static word deleted_keys_offset();
+  static word InstanceSize();
+};
+
 class ArgumentsDescriptor : public AllStatic {
  public:
+  static word first_named_entry_offset();
+  static word named_entry_size();
+  static word position_offset();
+  static word name_offset();
   static word count_offset();
   static word type_args_len_offset();
+  static word positional_count_offset();
+};
+
+class Pointer : public AllStatic {
+ public:
+  static word c_memory_address_offset();
 };
 
 class AbstractType : public AllStatic {
@@ -489,6 +545,7 @@
   static word type_state_offset();
   static word arguments_offset();
   static word signature_offset();
+  static word type_class_id_offset();
 };
 
 class TypeRef : public AllStatic {
@@ -499,21 +556,19 @@
 class Double : public AllStatic {
  public:
   static word value_offset();
-};
-
-class Smi : public AllStatic {
- public:
-  static const word kBits;
+  static word InstanceSize();
 };
 
 class Mint : public AllStatic {
  public:
   static word value_offset();
+  static word InstanceSize();
 };
 
 class String : public AllStatic {
  public:
   static const word kHashBits;
+  static const word kMaxElements;
   static word hash_offset();
   static word length_offset();
   static word InstanceSize();
@@ -529,14 +584,31 @@
   static word data_offset();
 };
 
+class ExternalOneByteString : public AllStatic {
+ public:
+  static word external_data_offset();
+};
+
+class ExternalTwoByteString : public AllStatic {
+ public:
+  static word external_data_offset();
+};
+
+class Int32x4 : public AllStatic {
+ public:
+  static word InstanceSize();
+};
+
 class Float32x4 : public AllStatic {
  public:
   static word value_offset();
+  static word InstanceSize();
 };
 
 class Float64x2 : public AllStatic {
  public:
   static word value_offset();
+  static word InstanceSize();
 };
 
 class TimelineStream : public AllStatic {
@@ -544,12 +616,18 @@
   static word enabled_offset();
 };
 
+class VMHandles : public AllStatic {
+ public:
+  static constexpr intptr_t kOffsetOfRawPtrInHandle = kWordSize;
+};
+
 class Thread : public AllStatic {
  public:
   static word dart_stream_offset();
   static word async_stack_trace_offset();
   static word predefined_symbols_address_offset();
-
+  static word deoptimize_entry_offset();
+  static word megamorphic_call_checked_entry_offset();
   static word active_exception_offset();
   static word active_stacktrace_offset();
   static word resume_pc_offset();
@@ -569,9 +647,10 @@
   static word null_error_shared_without_fpu_regs_entry_point_offset();
   static word write_barrier_mask_offset();
   static word monomorphic_miss_entry_offset();
-  static word write_barrier_wrappers_thread_offset(intptr_t regno);
+  static word write_barrier_wrappers_thread_offset(Register regno);
   static word array_write_barrier_entry_point_offset();
   static word write_barrier_entry_point_offset();
+  static word verify_callback_entry_offset();
   static word vm_tag_offset();
   static uword vm_tag_compiled_id();
 
@@ -582,7 +661,14 @@
   static word execution_state_offset();
   static uword native_execution_state();
   static uword generated_execution_state();
+  static word stack_overflow_flags_offset();
+  static word stack_overflow_shared_stub_entry_point_offset(bool fpu_regs);
+  static word stack_limit_offset();
+  static word unboxed_int64_runtime_arg_offset();
 
+  static word callback_code_offset();
+
+  static word AllocateArray_entry_point_offset();
 #if !defined(TARGET_ARCH_DBC)
   static word write_barrier_code_offset();
   static word array_write_barrier_code_offset();
@@ -599,7 +685,9 @@
   static word invoke_dart_code_from_bytecode_stub_offset();
   static word null_error_shared_without_fpu_regs_stub_offset();
   static word null_error_shared_with_fpu_regs_stub_offset();
+  static word stack_overflow_shared_without_fpu_regs_entry_point_offset();
   static word stack_overflow_shared_without_fpu_regs_stub_offset();
+  static word stack_overflow_shared_with_fpu_regs_entry_point_offset();
   static word stack_overflow_shared_with_fpu_regs_stub_offset();
   static word lazy_deopt_from_return_stub_offset();
   static word lazy_deopt_from_throw_stub_offset();
@@ -625,6 +713,7 @@
 #undef DECLARE_CONSTANT_OFFSET_GETTER
 
   static word OffsetFromThread(const dart::Object& object);
+  static intptr_t OffsetFromThread(const dart::RuntimeEntry* runtime_entry);
 };
 
 class StoreBufferBlock : public AllStatic {
@@ -667,9 +756,9 @@
 #if !defined(PRODUCT)
   static word ClassOffsetFor(intptr_t cid);
   static word StateOffsetFor(intptr_t cid);
-  static word TableOffsetFor(intptr_t cid);
-  static word CounterOffsetFor(intptr_t cid, bool is_new);
-  static word SizeOffsetFor(intptr_t cid, bool is_new);
+  static word class_heap_stats_table_offset();
+  static word NewSpaceCounterOffsetFor(intptr_t cid);
+  static word NewSpaceSizeOffsetFor(intptr_t cid);
 #endif  // !defined(PRODUCT)
   static const word kSizeOfClassPairLog2;
 };
@@ -686,9 +775,10 @@
 
 class Instructions : public AllStatic {
  public:
-  static const intptr_t kPolymorphicEntryOffset;
-  static const intptr_t kMonomorphicEntryOffset;
-  static intptr_t HeaderSize();
+  static const word kPolymorphicEntryOffset;
+  static const word kMonomorphicEntryOffset;
+  static word HeaderSize();
+  static word UnalignedHeaderSize();
 };
 
 class Code : public AllStatic {
@@ -697,10 +787,11 @@
   static uword EntryPointOf(const dart::Code& code);
 #endif  // defined(TARGET_ARCH_IA32)
 
-  static intptr_t object_pool_offset();
-  static intptr_t entry_point_offset(
-      CodeEntryKind kind = CodeEntryKind::kNormal);
-  static intptr_t saved_instructions_offset();
+  static word object_pool_offset();
+  static word entry_point_offset(CodeEntryKind kind = CodeEntryKind::kNormal);
+  static word function_entry_point_offset(CodeEntryKind kind);
+  static word saved_instructions_offset();
+  static word owner_offset();
 };
 
 class SubtypeTestCache : public AllStatic {
@@ -733,6 +824,8 @@
   static word function_offset();
   static word function_type_arguments_offset();
   static word instantiator_type_arguments_offset();
+  static word hash_offset();
+  static word InstanceSize();
 };
 
 class HeapPage : public AllStatic {
@@ -780,6 +873,24 @@
   static const word kNullCharCodeSymbolOffset;
 };
 
+class Field : public AllStatic {
+ public:
+  static word OffsetOf(const dart::Field& field);
+
+  static word guarded_cid_offset();
+  static word guarded_list_length_in_object_offset_offset();
+  static word guarded_list_length_offset();
+  static word is_nullable_offset();
+  static word static_value_offset();
+  static word kind_bits_offset();
+};
+
+class TypeArguments : public AllStatic {
+ public:
+  static word instantiations_offset();
+  static word type_at_offset(intptr_t i);
+};
+
 }  // namespace target
 }  // namespace compiler
 }  // namespace dart
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
new file mode 100644
index 0000000..761b30f
--- /dev/null
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -0,0 +1,1969 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+#ifndef RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_
+#define RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_
+
+#include "platform/globals.h"
+
+// The constants below correspond to the macros in runtime_offsets_list.h.
+
+// This file was generated by run_offsets_extractor.sh. It's checked in, rather
+// than being generated as part of the build, because simarm_x64 needs 32-bit
+// arm offsets, but is built on a 64-bit machine and offsets_extractor only
+// extracts offsets for the host architecture. This file needs to be regenerated
+// when the offsets change, which is usually detected by CheckOffsets() in
+// dart.cc.
+
+#if defined(TARGET_ARCH_ARM)
+static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
+    8;
+static constexpr dart::compiler::target::word ObjectPool_element_size = 4;
+static constexpr dart::compiler::target::word Array_kMaxElements = 268435455;
+static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
+    65533;
+static constexpr dart::compiler::target::word ClassTable_kSizeOfClassPairLog2 =
+    3;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffset = 20;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::compiler::target::word HeapPage_kBytesPerCardLog2 = 9;
+static constexpr dart::compiler::target::word
+    NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word String_kMaxElements = 536870911;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::compiler::target::word
+    AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
+    16;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_first_named_entry_offset = 24;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
+    0;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_positional_count_offset = 20;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::compiler::target::word Array_data_offset = 12;
+static constexpr dart::compiler::target::word Array_length_offset = 8;
+static constexpr dart::compiler::target::word Array_tags_offset = 0;
+static constexpr dart::compiler::target::word Array_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word Class_declaration_type_offset =
+    56;
+static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
+    102;
+static constexpr dart::compiler::target::word Class_super_type_offset = 44;
+static constexpr dart::compiler::target::word
+    Class_type_arguments_field_offset_in_words_offset = 92;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_since_gc_new_space_offset = 48;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
+static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 160;
+static constexpr dart::compiler::target::word ClassTable_table_offset = 8;
+static constexpr dart::compiler::target::word Closure_context_offset = 20;
+static constexpr dart::compiler::target::word
+    Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::compiler::target::word Closure_function_offset = 16;
+static constexpr dart::compiler::target::word
+    Closure_function_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Closure_hash_offset = 24;
+static constexpr dart::compiler::target::word
+    Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
+static constexpr dart::compiler::target::word Code_saved_instructions_offset =
+    24;
+static constexpr dart::compiler::target::word Code_owner_offset = 28;
+static constexpr dart::compiler::target::word Context_num_variables_offset = 4;
+static constexpr dart::compiler::target::word Context_parent_offset = 8;
+static constexpr dart::compiler::target::word Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word Field_guarded_cid_offset = 48;
+static constexpr dart::compiler::target::word
+    Field_guarded_list_length_in_object_offset_offset = 56;
+static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
+    28;
+static constexpr dart::compiler::target::word Field_is_nullable_offset = 50;
+static constexpr dart::compiler::target::word Field_static_value_offset = 16;
+static constexpr dart::compiler::target::word Field_kind_bits_offset = 58;
+static constexpr dart::compiler::target::word Function_code_offset = 44;
+static constexpr dart::compiler::target::word Function_entry_point_offset = 4;
+static constexpr dart::compiler::target::word
+    Function_unchecked_entry_point_offset = 8;
+static constexpr dart::compiler::target::word Function_usage_counter_offset =
+    76;
+static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
+    12;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_length_offset = 8;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word HeapPage_card_table_offset = 20;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word
+    ICData_arguments_descriptor_offset = 12;
+static constexpr dart::compiler::target::word ICData_entries_offset = 4;
+static constexpr dart::compiler::target::word ICData_owner_offset = 20;
+static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
+static constexpr dart::compiler::target::word
+    ICData_receivers_static_type_offset = 16;
+static constexpr dart::compiler::target::word Isolate_class_table_offset = 24;
+static constexpr dart::compiler::target::word Isolate_current_tag_offset = 8;
+static constexpr dart::compiler::target::word Isolate_default_tag_offset = 12;
+static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 16;
+static constexpr dart::compiler::target::word Isolate_object_store_offset = 20;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 44;
+static constexpr dart::compiler::target::word Isolate_user_tag_offset = 4;
+static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
+static constexpr dart::compiler::target::word
+    LinkedHashMap_deleted_keys_offset = 24;
+static constexpr dart::compiler::target::word LinkedHashMap_hash_mask_offset =
+    12;
+static constexpr dart::compiler::target::word LinkedHashMap_index_offset = 8;
+static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
+    20;
+static constexpr dart::compiler::target::word
+    MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
+static constexpr dart::compiler::target::word
+    MegamorphicCache_arguments_descriptor_offset = 16;
+static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
+    4;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 8;
+static constexpr dart::compiler::target::word Mint_value_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
+    4;
+static constexpr dart::compiler::target::word NativeArguments_argv_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_retval_offset =
+    12;
+static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
+    64;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 32;
+static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
+    80;
+static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
+static constexpr dart::compiler::target::word Pointer_c_memory_address_offset =
+    8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
+    4;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
+    8;
+static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4;
+static constexpr dart::compiler::target::word String_hash_offset = 8;
+static constexpr dart::compiler::target::word String_length_offset = 4;
+static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
+static constexpr dart::compiler::target::word
+    Thread_AllocateArray_entry_point_offset = 284;
+static constexpr dart::compiler::target::word Thread_active_exception_offset =
+    612;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    616;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_code_offset = 112;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_entry_point_offset = 196;
+static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
+    84;
+static constexpr dart::compiler::target::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 244;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 104;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 100;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_entry_point_offset = 200;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_stub_offset = 132;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 644;
+static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
+    232;
+static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
+    164;
+static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
+    264;
+static constexpr dart::compiler::target::word
+    Thread_double_negate_address_offset = 260;
+static constexpr dart::compiler::target::word Thread_end_offset = 60;
+static constexpr dart::compiler::target::word
+    Thread_enter_safepoint_stub_offset = 184;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    628;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 120;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 116;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 276;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 272;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    268;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 280;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
+    620;
+static constexpr dart::compiler::target::word
+    Thread_ic_lookup_through_code_stub_offset = 156;
+static constexpr dart::compiler::target::word
+    Thread_interpret_call_entry_point_offset = 248;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_from_bytecode_stub_offset = 128;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_stub_offset = 124;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 48;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_return_stub_offset = 168;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_throw_stub_offset = 172;
+static constexpr dart::compiler::target::word
+    Thread_lazy_specialize_type_test_stub_offset = 180;
+static constexpr dart::compiler::target::word
+    Thread_marking_stack_block_offset = 72;
+static constexpr dart::compiler::target::word
+    Thread_megamorphic_call_checked_entry_offset = 220;
+static constexpr dart::compiler::target::word
+    Thread_monomorphic_miss_entry_offset = 224;
+static constexpr dart::compiler::target::word
+    Thread_monomorphic_miss_stub_offset = 152;
+static constexpr dart::compiler::target::word
+    Thread_no_scope_native_wrapper_entry_point_offset = 240;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 208;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 140;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 204;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 136;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 96;
+static constexpr dart::compiler::target::word
+    Thread_predefined_symbols_address_offset = 252;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 624;
+static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
+    632;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_stub_offset = 176;
+static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_flags_offset = 40;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 216;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 212;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
+static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
+    68;
+static constexpr dart::compiler::target::word
+    Thread_top_exit_frame_info_offset = 64;
+static constexpr dart::compiler::target::word Thread_top_offset = 56;
+static constexpr dart::compiler::target::word Thread_top_resource_offset = 24;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_int64_runtime_arg_offset = 88;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 80;
+static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
+    108;
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_entry_point_offset = 192;
+static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
+    44;
+static constexpr dart::compiler::target::word
+    Thread_verify_callback_entry_offset = 236;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 636;
+static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
+static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
+static constexpr dart::compiler::target::word Type_arguments_offset = 16;
+static constexpr dart::compiler::target::word Type_hash_offset = 20;
+static constexpr dart::compiler::target::word Type_signature_offset = 24;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 12;
+static constexpr dart::compiler::target::word Type_type_state_offset = 32;
+static constexpr dart::compiler::target::word
+    TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
+static constexpr dart::compiler::target::word TypedDataBase_data_field_offset =
+    4;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
+static constexpr dart::compiler::target::word
+    TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::compiler::target::word TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word UserTag_tag_offset = 8;
+static constexpr dart::compiler::target::word Array_elements_start_offset = 12;
+static constexpr dart::compiler::target::word Array_element_size = 4;
+static constexpr dart::compiler::target::word
+    TypeArguments_elements_start_offset = 16;
+static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
+static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
+    0;
+static constexpr dart::compiler::target::word ClassTable_element_size = 168;
+static constexpr dart::compiler::target::word
+    ClassTable_class_heap_stats_table_offset = 16;
+static dart::compiler::target::word Code_entry_point_offset[] = {4, 12, 8, 16};
+static dart::compiler::target::word Code_function_entry_point_offset[] = {4, 8};
+static dart::compiler::target::word
+    Thread_write_barrier_wrappers_thread_offset[] = {
+        576, 580, 584, 588, 592, -1, 596, 600,
+        604, 608, -1,  -1,  -1,  -1, -1,  -1};
+static constexpr dart::compiler::target::word Array_header_size = 12;
+static constexpr dart::compiler::target::word Context_header_size = 12;
+static constexpr dart::compiler::target::word Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
+    16;
+static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word NativeArguments_StructSize = 16;
+static constexpr dart::compiler::target::word String_InstanceSize = 12;
+static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
+static constexpr dart::compiler::target::word Object_InstanceSize = 4;
+static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
+static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
+static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
+static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28;
+#endif  // defined(TARGET_ARCH_ARM)
+
+#if defined(TARGET_ARCH_X64)
+static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
+    16;
+static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
+static constexpr dart::compiler::target::word Array_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
+    32765;
+static constexpr dart::compiler::target::word ClassTable_kSizeOfClassPairLog2 =
+    4;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffset = 32;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffset = 8;
+static constexpr dart::compiler::target::word HeapPage_kBytesPerCardLog2 = 10;
+static constexpr dart::compiler::target::word
+    NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word String_kMaxElements =
+    2305843009213693951;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::compiler::target::word
+    AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
+    32;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_first_named_entry_offset = 48;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
+    0;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_positional_count_offset = 40;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::compiler::target::word Array_data_offset = 24;
+static constexpr dart::compiler::target::word Array_length_offset = 16;
+static constexpr dart::compiler::target::word Array_tags_offset = 0;
+static constexpr dart::compiler::target::word Array_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Class_declaration_type_offset =
+    112;
+static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
+    186;
+static constexpr dart::compiler::target::word Class_super_type_offset = 88;
+static constexpr dart::compiler::target::word
+    Class_type_arguments_field_offset_in_words_offset = 176;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_since_gc_new_space_offset = 96;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
+static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 272;
+static constexpr dart::compiler::target::word ClassTable_table_offset = 16;
+static constexpr dart::compiler::target::word Closure_context_offset = 40;
+static constexpr dart::compiler::target::word
+    Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::compiler::target::word Closure_function_offset = 32;
+static constexpr dart::compiler::target::word
+    Closure_function_type_arguments_offset = 16;
+static constexpr dart::compiler::target::word Closure_hash_offset = 48;
+static constexpr dart::compiler::target::word
+    Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
+static constexpr dart::compiler::target::word Code_saved_instructions_offset =
+    48;
+static constexpr dart::compiler::target::word Code_owner_offset = 56;
+static constexpr dart::compiler::target::word Context_num_variables_offset = 8;
+static constexpr dart::compiler::target::word Context_parent_offset = 16;
+static constexpr dart::compiler::target::word Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word Field_guarded_cid_offset = 88;
+static constexpr dart::compiler::target::word
+    Field_guarded_list_length_in_object_offset_offset = 96;
+static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
+    56;
+static constexpr dart::compiler::target::word Field_is_nullable_offset = 90;
+static constexpr dart::compiler::target::word Field_static_value_offset = 32;
+static constexpr dart::compiler::target::word Field_kind_bits_offset = 98;
+static constexpr dart::compiler::target::word Function_code_offset = 88;
+static constexpr dart::compiler::target::word Function_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    Function_unchecked_entry_point_offset = 16;
+static constexpr dart::compiler::target::word Function_usage_counter_offset =
+    132;
+static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
+    24;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_length_offset = 16;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word HeapPage_card_table_offset = 40;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word
+    ICData_arguments_descriptor_offset = 24;
+static constexpr dart::compiler::target::word ICData_entries_offset = 8;
+static constexpr dart::compiler::target::word ICData_owner_offset = 40;
+static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
+static constexpr dart::compiler::target::word
+    ICData_receivers_static_type_offset = 32;
+static constexpr dart::compiler::target::word Isolate_class_table_offset = 48;
+static constexpr dart::compiler::target::word Isolate_current_tag_offset = 16;
+static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
+static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32;
+static constexpr dart::compiler::target::word Isolate_object_store_offset = 40;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
+static constexpr dart::compiler::target::word Isolate_user_tag_offset = 8;
+static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
+static constexpr dart::compiler::target::word
+    LinkedHashMap_deleted_keys_offset = 48;
+static constexpr dart::compiler::target::word LinkedHashMap_hash_mask_offset =
+    24;
+static constexpr dart::compiler::target::word LinkedHashMap_index_offset = 16;
+static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
+    40;
+static constexpr dart::compiler::target::word
+    MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
+static constexpr dart::compiler::target::word
+    MegamorphicCache_arguments_descriptor_offset = 32;
+static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
+    8;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
+static constexpr dart::compiler::target::word Mint_value_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
+    8;
+static constexpr dart::compiler::target::word NativeArguments_argv_offset = 16;
+static constexpr dart::compiler::target::word NativeArguments_retval_offset =
+    24;
+static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
+    128;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 64;
+static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
+    160;
+static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
+static constexpr dart::compiler::target::word Pointer_c_memory_address_offset =
+    16;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
+    8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
+    16;
+static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8;
+static constexpr dart::compiler::target::word String_hash_offset = 4;
+static constexpr dart::compiler::target::word String_length_offset = 8;
+static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
+static constexpr dart::compiler::target::word
+    Thread_AllocateArray_entry_point_offset = 560;
+static constexpr dart::compiler::target::word Thread_active_exception_offset =
+    1232;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1240;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_code_offset = 216;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_entry_point_offset = 384;
+static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
+    168;
+static constexpr dart::compiler::target::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 480;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 200;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 192;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_entry_point_offset = 392;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_stub_offset = 256;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1296;
+static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
+    456;
+static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
+    320;
+static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
+    520;
+static constexpr dart::compiler::target::word
+    Thread_double_negate_address_offset = 512;
+static constexpr dart::compiler::target::word Thread_end_offset = 120;
+static constexpr dart::compiler::target::word
+    Thread_enter_safepoint_stub_offset = 360;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    1264;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 368;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 232;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 224;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 544;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 536;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    528;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 552;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
+    1248;
+static constexpr dart::compiler::target::word
+    Thread_ic_lookup_through_code_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    Thread_interpret_call_entry_point_offset = 488;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_from_bytecode_stub_offset = 248;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_stub_offset = 240;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 96;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_return_stub_offset = 328;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_throw_stub_offset = 336;
+static constexpr dart::compiler::target::word
+    Thread_lazy_specialize_type_test_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    Thread_marking_stack_block_offset = 144;
+static constexpr dart::compiler::target::word
+    Thread_megamorphic_call_checked_entry_offset = 432;
+static constexpr dart::compiler::target::word
+    Thread_monomorphic_miss_entry_offset = 440;
+static constexpr dart::compiler::target::word
+    Thread_monomorphic_miss_stub_offset = 296;
+static constexpr dart::compiler::target::word
+    Thread_no_scope_native_wrapper_entry_point_offset = 472;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 408;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 272;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 400;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 264;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 184;
+static constexpr dart::compiler::target::word
+    Thread_predefined_symbols_address_offset = 496;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1256;
+static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
+    1272;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_stub_offset = 344;
+static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_flags_offset = 80;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 424;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 416;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
+static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
+    136;
+static constexpr dart::compiler::target::word
+    Thread_top_exit_frame_info_offset = 128;
+static constexpr dart::compiler::target::word Thread_top_offset = 112;
+static constexpr dart::compiler::target::word Thread_top_resource_offset = 48;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_int64_runtime_arg_offset = 176;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 160;
+static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
+    208;
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_entry_point_offset = 376;
+static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
+    88;
+static constexpr dart::compiler::target::word
+    Thread_verify_callback_entry_offset = 464;
+static constexpr dart::compiler::target::word Thread_callback_code_offset =
+    1280;
+static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
+    16;
+static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
+static constexpr dart::compiler::target::word Type_arguments_offset = 32;
+static constexpr dart::compiler::target::word Type_hash_offset = 40;
+static constexpr dart::compiler::target::word Type_signature_offset = 48;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
+static constexpr dart::compiler::target::word Type_type_state_offset = 60;
+static constexpr dart::compiler::target::word
+    TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_data_field_offset =
+    8;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word
+    TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word UserTag_tag_offset = 16;
+static constexpr dart::compiler::target::word Array_elements_start_offset = 24;
+static constexpr dart::compiler::target::word Array_element_size = 8;
+static constexpr dart::compiler::target::word
+    TypeArguments_elements_start_offset = 32;
+static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
+static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
+    0;
+static constexpr dart::compiler::target::word ClassTable_element_size = 288;
+static constexpr dart::compiler::target::word
+    ClassTable_class_heap_stats_table_offset = 32;
+static dart::compiler::target::word Code_entry_point_offset[] = {8, 24, 16, 32};
+static dart::compiler::target::word Code_function_entry_point_offset[] = {8,
+                                                                          16};
+static dart::compiler::target::word
+    Thread_write_barrier_wrappers_thread_offset[] = {
+        1144, 1152, 1160, 1168, -1,   -1,   1176, 1184,
+        1192, 1200, 1208, -1,   1216, 1224, -1,   -1};
+static constexpr dart::compiler::target::word Array_header_size = 24;
+static constexpr dart::compiler::target::word Context_header_size = 24;
+static constexpr dart::compiler::target::word Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
+    24;
+static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word NativeArguments_StructSize = 32;
+static constexpr dart::compiler::target::word String_InstanceSize = 16;
+static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
+static constexpr dart::compiler::target::word Object_InstanceSize = 8;
+static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
+static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
+    32;
+static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
+static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
+#endif  // defined(TARGET_ARCH_X64)
+
+#if defined(TARGET_ARCH_IA32)
+static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
+    8;
+static constexpr dart::compiler::target::word ObjectPool_element_size = 4;
+static constexpr dart::compiler::target::word Array_kMaxElements = 268435455;
+static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
+    65533;
+static constexpr dart::compiler::target::word ClassTable_kSizeOfClassPairLog2 =
+    3;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffset = 0;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::compiler::target::word HeapPage_kBytesPerCardLog2 = 9;
+static constexpr dart::compiler::target::word
+    NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word String_kMaxElements = 536870911;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::compiler::target::word
+    AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
+    16;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_first_named_entry_offset = 24;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
+    0;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_positional_count_offset = 20;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::compiler::target::word Array_data_offset = 12;
+static constexpr dart::compiler::target::word Array_length_offset = 8;
+static constexpr dart::compiler::target::word Array_tags_offset = 0;
+static constexpr dart::compiler::target::word Array_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word Class_declaration_type_offset =
+    56;
+static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
+    102;
+static constexpr dart::compiler::target::word Class_super_type_offset = 44;
+static constexpr dart::compiler::target::word
+    Class_type_arguments_field_offset_in_words_offset = 92;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_since_gc_new_space_offset = 48;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
+static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 160;
+static constexpr dart::compiler::target::word ClassTable_table_offset = 8;
+static constexpr dart::compiler::target::word Closure_context_offset = 20;
+static constexpr dart::compiler::target::word
+    Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::compiler::target::word Closure_function_offset = 16;
+static constexpr dart::compiler::target::word
+    Closure_function_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Closure_hash_offset = 24;
+static constexpr dart::compiler::target::word
+    Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
+static constexpr dart::compiler::target::word Code_saved_instructions_offset =
+    24;
+static constexpr dart::compiler::target::word Code_owner_offset = 28;
+static constexpr dart::compiler::target::word Context_num_variables_offset = 4;
+static constexpr dart::compiler::target::word Context_parent_offset = 8;
+static constexpr dart::compiler::target::word Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word Field_guarded_cid_offset = 48;
+static constexpr dart::compiler::target::word
+    Field_guarded_list_length_in_object_offset_offset = 56;
+static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
+    28;
+static constexpr dart::compiler::target::word Field_is_nullable_offset = 50;
+static constexpr dart::compiler::target::word Field_static_value_offset = 16;
+static constexpr dart::compiler::target::word Field_kind_bits_offset = 58;
+static constexpr dart::compiler::target::word Function_code_offset = 44;
+static constexpr dart::compiler::target::word Function_entry_point_offset = 4;
+static constexpr dart::compiler::target::word
+    Function_unchecked_entry_point_offset = 8;
+static constexpr dart::compiler::target::word Function_usage_counter_offset =
+    76;
+static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
+    12;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_length_offset = 8;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word HeapPage_card_table_offset = 20;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word
+    ICData_arguments_descriptor_offset = 12;
+static constexpr dart::compiler::target::word ICData_entries_offset = 4;
+static constexpr dart::compiler::target::word ICData_owner_offset = 20;
+static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
+static constexpr dart::compiler::target::word
+    ICData_receivers_static_type_offset = 16;
+static constexpr dart::compiler::target::word Isolate_class_table_offset = 24;
+static constexpr dart::compiler::target::word Isolate_current_tag_offset = 8;
+static constexpr dart::compiler::target::word Isolate_default_tag_offset = 12;
+static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 16;
+static constexpr dart::compiler::target::word Isolate_object_store_offset = 20;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 44;
+static constexpr dart::compiler::target::word Isolate_user_tag_offset = 4;
+static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
+static constexpr dart::compiler::target::word
+    LinkedHashMap_deleted_keys_offset = 24;
+static constexpr dart::compiler::target::word LinkedHashMap_hash_mask_offset =
+    12;
+static constexpr dart::compiler::target::word LinkedHashMap_index_offset = 8;
+static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
+    20;
+static constexpr dart::compiler::target::word
+    MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
+static constexpr dart::compiler::target::word
+    MegamorphicCache_arguments_descriptor_offset = 16;
+static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
+    4;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 8;
+static constexpr dart::compiler::target::word Mint_value_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
+    4;
+static constexpr dart::compiler::target::word NativeArguments_argv_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_retval_offset =
+    12;
+static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
+    64;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 32;
+static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
+    80;
+static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
+static constexpr dart::compiler::target::word Pointer_c_memory_address_offset =
+    8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
+    4;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
+    8;
+static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4;
+static constexpr dart::compiler::target::word String_hash_offset = 8;
+static constexpr dart::compiler::target::word String_length_offset = 4;
+static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
+static constexpr dart::compiler::target::word
+    Thread_AllocateArray_entry_point_offset = 284;
+static constexpr dart::compiler::target::word Thread_active_exception_offset =
+    576;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    580;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_code_offset = 112;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_entry_point_offset = 196;
+static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
+    84;
+static constexpr dart::compiler::target::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 244;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 104;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 100;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_entry_point_offset = 200;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_stub_offset = 132;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 608;
+static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
+    232;
+static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
+    164;
+static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
+    264;
+static constexpr dart::compiler::target::word
+    Thread_double_negate_address_offset = 260;
+static constexpr dart::compiler::target::word Thread_end_offset = 60;
+static constexpr dart::compiler::target::word
+    Thread_enter_safepoint_stub_offset = 184;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    592;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 120;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 116;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 276;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 272;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    268;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 280;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
+    584;
+static constexpr dart::compiler::target::word
+    Thread_ic_lookup_through_code_stub_offset = 156;
+static constexpr dart::compiler::target::word
+    Thread_interpret_call_entry_point_offset = 248;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_from_bytecode_stub_offset = 128;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_stub_offset = 124;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 48;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_return_stub_offset = 168;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_throw_stub_offset = 172;
+static constexpr dart::compiler::target::word
+    Thread_lazy_specialize_type_test_stub_offset = 180;
+static constexpr dart::compiler::target::word
+    Thread_marking_stack_block_offset = 72;
+static constexpr dart::compiler::target::word
+    Thread_megamorphic_call_checked_entry_offset = 220;
+static constexpr dart::compiler::target::word
+    Thread_monomorphic_miss_entry_offset = 224;
+static constexpr dart::compiler::target::word
+    Thread_monomorphic_miss_stub_offset = 152;
+static constexpr dart::compiler::target::word
+    Thread_no_scope_native_wrapper_entry_point_offset = 240;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 208;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 140;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 204;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 136;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 96;
+static constexpr dart::compiler::target::word
+    Thread_predefined_symbols_address_offset = 252;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 588;
+static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
+    596;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_stub_offset = 176;
+static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_flags_offset = 40;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 216;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 212;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
+static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
+    68;
+static constexpr dart::compiler::target::word
+    Thread_top_exit_frame_info_offset = 64;
+static constexpr dart::compiler::target::word Thread_top_offset = 56;
+static constexpr dart::compiler::target::word Thread_top_resource_offset = 24;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_int64_runtime_arg_offset = 88;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 80;
+static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
+    108;
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_entry_point_offset = 192;
+static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
+    44;
+static constexpr dart::compiler::target::word
+    Thread_verify_callback_entry_offset = 236;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 600;
+static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
+static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
+static constexpr dart::compiler::target::word Type_arguments_offset = 16;
+static constexpr dart::compiler::target::word Type_hash_offset = 20;
+static constexpr dart::compiler::target::word Type_signature_offset = 24;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 12;
+static constexpr dart::compiler::target::word Type_type_state_offset = 32;
+static constexpr dart::compiler::target::word
+    TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
+static constexpr dart::compiler::target::word TypedDataBase_data_field_offset =
+    4;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
+static constexpr dart::compiler::target::word
+    TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::compiler::target::word TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word UserTag_tag_offset = 8;
+static constexpr dart::compiler::target::word Array_elements_start_offset = 12;
+static constexpr dart::compiler::target::word Array_element_size = 4;
+static constexpr dart::compiler::target::word
+    TypeArguments_elements_start_offset = 16;
+static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
+static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
+    0;
+static constexpr dart::compiler::target::word ClassTable_element_size = 168;
+static constexpr dart::compiler::target::word
+    ClassTable_class_heap_stats_table_offset = 16;
+static dart::compiler::target::word Code_entry_point_offset[] = {4, 12, 8, 16};
+static dart::compiler::target::word Code_function_entry_point_offset[] = {4, 8};
+static constexpr dart::compiler::target::word Array_header_size = 12;
+static constexpr dart::compiler::target::word Context_header_size = 12;
+static constexpr dart::compiler::target::word Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
+    16;
+static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word NativeArguments_StructSize = 16;
+static constexpr dart::compiler::target::word String_InstanceSize = 12;
+static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
+static constexpr dart::compiler::target::word Object_InstanceSize = 4;
+static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
+static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
+static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
+static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28;
+#endif  // defined(TARGET_ARCH_IA32)
+
+#if defined(TARGET_ARCH_ARM64)
+static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
+    16;
+static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
+static constexpr dart::compiler::target::word Array_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
+    32765;
+static constexpr dart::compiler::target::word ClassTable_kSizeOfClassPairLog2 =
+    4;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffset = 28;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffset = 8;
+static constexpr dart::compiler::target::word HeapPage_kBytesPerCardLog2 = 10;
+static constexpr dart::compiler::target::word
+    NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word String_kMaxElements =
+    2305843009213693951;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::compiler::target::word
+    AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
+    32;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_first_named_entry_offset = 48;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
+    0;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_positional_count_offset = 40;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::compiler::target::word Array_data_offset = 24;
+static constexpr dart::compiler::target::word Array_length_offset = 16;
+static constexpr dart::compiler::target::word Array_tags_offset = 0;
+static constexpr dart::compiler::target::word Array_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Class_declaration_type_offset =
+    112;
+static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
+    186;
+static constexpr dart::compiler::target::word Class_super_type_offset = 88;
+static constexpr dart::compiler::target::word
+    Class_type_arguments_field_offset_in_words_offset = 176;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_since_gc_new_space_offset = 96;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
+static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 272;
+static constexpr dart::compiler::target::word ClassTable_table_offset = 16;
+static constexpr dart::compiler::target::word Closure_context_offset = 40;
+static constexpr dart::compiler::target::word
+    Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::compiler::target::word Closure_function_offset = 32;
+static constexpr dart::compiler::target::word
+    Closure_function_type_arguments_offset = 16;
+static constexpr dart::compiler::target::word Closure_hash_offset = 48;
+static constexpr dart::compiler::target::word
+    Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
+static constexpr dart::compiler::target::word Code_saved_instructions_offset =
+    48;
+static constexpr dart::compiler::target::word Code_owner_offset = 56;
+static constexpr dart::compiler::target::word Context_num_variables_offset = 8;
+static constexpr dart::compiler::target::word Context_parent_offset = 16;
+static constexpr dart::compiler::target::word Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word Field_guarded_cid_offset = 88;
+static constexpr dart::compiler::target::word
+    Field_guarded_list_length_in_object_offset_offset = 96;
+static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
+    56;
+static constexpr dart::compiler::target::word Field_is_nullable_offset = 90;
+static constexpr dart::compiler::target::word Field_static_value_offset = 32;
+static constexpr dart::compiler::target::word Field_kind_bits_offset = 98;
+static constexpr dart::compiler::target::word Function_code_offset = 88;
+static constexpr dart::compiler::target::word Function_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    Function_unchecked_entry_point_offset = 16;
+static constexpr dart::compiler::target::word Function_usage_counter_offset =
+    132;
+static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
+    24;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_length_offset = 16;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word HeapPage_card_table_offset = 40;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word
+    ICData_arguments_descriptor_offset = 24;
+static constexpr dart::compiler::target::word ICData_entries_offset = 8;
+static constexpr dart::compiler::target::word ICData_owner_offset = 40;
+static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
+static constexpr dart::compiler::target::word
+    ICData_receivers_static_type_offset = 32;
+static constexpr dart::compiler::target::word Isolate_class_table_offset = 48;
+static constexpr dart::compiler::target::word Isolate_current_tag_offset = 16;
+static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
+static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32;
+static constexpr dart::compiler::target::word Isolate_object_store_offset = 40;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
+static constexpr dart::compiler::target::word Isolate_user_tag_offset = 8;
+static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
+static constexpr dart::compiler::target::word
+    LinkedHashMap_deleted_keys_offset = 48;
+static constexpr dart::compiler::target::word LinkedHashMap_hash_mask_offset =
+    24;
+static constexpr dart::compiler::target::word LinkedHashMap_index_offset = 16;
+static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
+    40;
+static constexpr dart::compiler::target::word
+    MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
+static constexpr dart::compiler::target::word
+    MegamorphicCache_arguments_descriptor_offset = 32;
+static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
+    8;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
+static constexpr dart::compiler::target::word Mint_value_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
+    8;
+static constexpr dart::compiler::target::word NativeArguments_argv_offset = 16;
+static constexpr dart::compiler::target::word NativeArguments_retval_offset =
+    24;
+static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
+    128;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 64;
+static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
+    160;
+static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
+static constexpr dart::compiler::target::word Pointer_c_memory_address_offset =
+    16;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
+    8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
+    16;
+static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8;
+static constexpr dart::compiler::target::word String_hash_offset = 4;
+static constexpr dart::compiler::target::word String_length_offset = 8;
+static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
+static constexpr dart::compiler::target::word
+    Thread_AllocateArray_entry_point_offset = 560;
+static constexpr dart::compiler::target::word Thread_active_exception_offset =
+    1320;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1328;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_code_offset = 216;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_entry_point_offset = 384;
+static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
+    168;
+static constexpr dart::compiler::target::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 480;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 200;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 192;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_entry_point_offset = 392;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_stub_offset = 256;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1384;
+static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
+    456;
+static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
+    320;
+static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
+    520;
+static constexpr dart::compiler::target::word
+    Thread_double_negate_address_offset = 512;
+static constexpr dart::compiler::target::word Thread_end_offset = 120;
+static constexpr dart::compiler::target::word
+    Thread_enter_safepoint_stub_offset = 360;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    1352;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 368;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 232;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 224;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 544;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 536;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    528;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 552;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
+    1336;
+static constexpr dart::compiler::target::word
+    Thread_ic_lookup_through_code_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    Thread_interpret_call_entry_point_offset = 488;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_from_bytecode_stub_offset = 248;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_stub_offset = 240;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 96;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_return_stub_offset = 328;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_throw_stub_offset = 336;
+static constexpr dart::compiler::target::word
+    Thread_lazy_specialize_type_test_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    Thread_marking_stack_block_offset = 144;
+static constexpr dart::compiler::target::word
+    Thread_megamorphic_call_checked_entry_offset = 432;
+static constexpr dart::compiler::target::word
+    Thread_monomorphic_miss_entry_offset = 440;
+static constexpr dart::compiler::target::word
+    Thread_monomorphic_miss_stub_offset = 296;
+static constexpr dart::compiler::target::word
+    Thread_no_scope_native_wrapper_entry_point_offset = 472;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 408;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 272;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 400;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 264;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 184;
+static constexpr dart::compiler::target::word
+    Thread_predefined_symbols_address_offset = 496;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1344;
+static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
+    1360;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_stub_offset = 344;
+static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_flags_offset = 80;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 424;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 416;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
+static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
+    136;
+static constexpr dart::compiler::target::word
+    Thread_top_exit_frame_info_offset = 128;
+static constexpr dart::compiler::target::word Thread_top_offset = 112;
+static constexpr dart::compiler::target::word Thread_top_resource_offset = 48;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_int64_runtime_arg_offset = 176;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 160;
+static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
+    208;
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_entry_point_offset = 376;
+static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
+    88;
+static constexpr dart::compiler::target::word
+    Thread_verify_callback_entry_offset = 464;
+static constexpr dart::compiler::target::word Thread_callback_code_offset =
+    1368;
+static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
+    16;
+static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
+static constexpr dart::compiler::target::word Type_arguments_offset = 32;
+static constexpr dart::compiler::target::word Type_hash_offset = 40;
+static constexpr dart::compiler::target::word Type_signature_offset = 48;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
+static constexpr dart::compiler::target::word Type_type_state_offset = 60;
+static constexpr dart::compiler::target::word
+    TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_data_field_offset =
+    8;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word
+    TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word UserTag_tag_offset = 16;
+static constexpr dart::compiler::target::word Array_elements_start_offset = 24;
+static constexpr dart::compiler::target::word Array_element_size = 8;
+static constexpr dart::compiler::target::word
+    TypeArguments_elements_start_offset = 32;
+static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
+static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
+    0;
+static constexpr dart::compiler::target::word ClassTable_element_size = 288;
+static constexpr dart::compiler::target::word
+    ClassTable_class_heap_stats_table_offset = 32;
+static dart::compiler::target::word Code_entry_point_offset[] = {8, 24, 16, 32};
+static dart::compiler::target::word Code_function_entry_point_offset[] = {8,
+                                                                          16};
+static dart::compiler::target::word
+    Thread_write_barrier_wrappers_thread_offset[] = {
+        1144, 1152, 1160, 1168, 1176, 1184, 1192, 1200, 1208, 1216, 1224,
+        1232, 1240, 1248, 1256, -1,   -1,   -1,   -1,   1264, 1272, 1280,
+        1288, 1296, 1304, 1312, -1,   -1,   -1,   -1,   -1,   -1};
+static constexpr dart::compiler::target::word Array_header_size = 24;
+static constexpr dart::compiler::target::word Context_header_size = 24;
+static constexpr dart::compiler::target::word Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
+    24;
+static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word NativeArguments_StructSize = 32;
+static constexpr dart::compiler::target::word String_InstanceSize = 16;
+static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
+static constexpr dart::compiler::target::word Object_InstanceSize = 8;
+static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
+static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
+    32;
+static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
+static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
+#endif  // defined(TARGET_ARCH_ARM64)
+
+#if defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
+static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
+    16;
+static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
+static constexpr dart::compiler::target::word Array_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
+    32765;
+static constexpr dart::compiler::target::word ClassTable_kSizeOfClassPairLog2 =
+    4;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffset = 0;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::compiler::target::word HeapPage_kBytesPerCardLog2 = 10;
+static constexpr dart::compiler::target::word
+    NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word String_kMaxElements =
+    2305843009213693951;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::compiler::target::word
+    AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
+    32;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_first_named_entry_offset = 48;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
+    0;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_positional_count_offset = 40;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::compiler::target::word Array_data_offset = 24;
+static constexpr dart::compiler::target::word Array_length_offset = 16;
+static constexpr dart::compiler::target::word Array_tags_offset = 0;
+static constexpr dart::compiler::target::word Array_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Class_declaration_type_offset =
+    112;
+static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
+    186;
+static constexpr dart::compiler::target::word Class_super_type_offset = 88;
+static constexpr dart::compiler::target::word
+    Class_type_arguments_field_offset_in_words_offset = 176;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_since_gc_new_space_offset = 96;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
+static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 272;
+static constexpr dart::compiler::target::word ClassTable_table_offset = 16;
+static constexpr dart::compiler::target::word Closure_context_offset = 40;
+static constexpr dart::compiler::target::word
+    Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::compiler::target::word Closure_function_offset = 32;
+static constexpr dart::compiler::target::word
+    Closure_function_type_arguments_offset = 16;
+static constexpr dart::compiler::target::word Closure_hash_offset = 48;
+static constexpr dart::compiler::target::word
+    Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
+static constexpr dart::compiler::target::word Code_saved_instructions_offset =
+    48;
+static constexpr dart::compiler::target::word Code_owner_offset = 56;
+static constexpr dart::compiler::target::word Context_num_variables_offset = 8;
+static constexpr dart::compiler::target::word Context_parent_offset = 16;
+static constexpr dart::compiler::target::word Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word Field_guarded_cid_offset = 88;
+static constexpr dart::compiler::target::word
+    Field_guarded_list_length_in_object_offset_offset = 96;
+static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
+    56;
+static constexpr dart::compiler::target::word Field_is_nullable_offset = 90;
+static constexpr dart::compiler::target::word Field_static_value_offset = 32;
+static constexpr dart::compiler::target::word Field_kind_bits_offset = 98;
+static constexpr dart::compiler::target::word Function_code_offset = 88;
+static constexpr dart::compiler::target::word Function_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    Function_unchecked_entry_point_offset = 16;
+static constexpr dart::compiler::target::word Function_usage_counter_offset =
+    132;
+static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
+    24;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_length_offset = 16;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word HeapPage_card_table_offset = 40;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word
+    ICData_arguments_descriptor_offset = 24;
+static constexpr dart::compiler::target::word ICData_entries_offset = 8;
+static constexpr dart::compiler::target::word ICData_owner_offset = 40;
+static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
+static constexpr dart::compiler::target::word
+    ICData_receivers_static_type_offset = 32;
+static constexpr dart::compiler::target::word Isolate_class_table_offset = 48;
+static constexpr dart::compiler::target::word Isolate_current_tag_offset = 16;
+static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
+static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32;
+static constexpr dart::compiler::target::word Isolate_object_store_offset = 40;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
+static constexpr dart::compiler::target::word Isolate_user_tag_offset = 8;
+static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
+static constexpr dart::compiler::target::word
+    LinkedHashMap_deleted_keys_offset = 48;
+static constexpr dart::compiler::target::word LinkedHashMap_hash_mask_offset =
+    24;
+static constexpr dart::compiler::target::word LinkedHashMap_index_offset = 16;
+static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
+    40;
+static constexpr dart::compiler::target::word
+    MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
+static constexpr dart::compiler::target::word
+    MegamorphicCache_arguments_descriptor_offset = 32;
+static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
+    8;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
+static constexpr dart::compiler::target::word Mint_value_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
+    8;
+static constexpr dart::compiler::target::word NativeArguments_argv_offset = 16;
+static constexpr dart::compiler::target::word NativeArguments_retval_offset =
+    24;
+static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
+    128;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 64;
+static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
+    160;
+static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
+static constexpr dart::compiler::target::word Pointer_c_memory_address_offset =
+    16;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
+    8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
+    16;
+static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8;
+static constexpr dart::compiler::target::word String_hash_offset = 4;
+static constexpr dart::compiler::target::word String_length_offset = 8;
+static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
+static constexpr dart::compiler::target::word
+    Thread_AllocateArray_entry_point_offset = 296;
+static constexpr dart::compiler::target::word Thread_active_exception_offset =
+    880;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    888;
+static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
+    168;
+static constexpr dart::compiler::target::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 216;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 200;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 192;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 944;
+static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
+    256;
+static constexpr dart::compiler::target::word
+    Thread_double_negate_address_offset = 248;
+static constexpr dart::compiler::target::word Thread_end_offset = 120;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    912;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 280;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 272;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    264;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 288;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
+    896;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 96;
+static constexpr dart::compiler::target::word
+    Thread_marking_stack_block_offset = 144;
+static constexpr dart::compiler::target::word
+    Thread_no_scope_native_wrapper_entry_point_offset = 208;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 184;
+static constexpr dart::compiler::target::word
+    Thread_predefined_symbols_address_offset = 232;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 904;
+static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
+    920;
+static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_flags_offset = 80;
+static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
+    136;
+static constexpr dart::compiler::target::word
+    Thread_top_exit_frame_info_offset = 128;
+static constexpr dart::compiler::target::word Thread_top_offset = 112;
+static constexpr dart::compiler::target::word Thread_top_resource_offset = 48;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_int64_runtime_arg_offset = 176;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 160;
+static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
+    88;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 928;
+static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
+    16;
+static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
+static constexpr dart::compiler::target::word Type_arguments_offset = 32;
+static constexpr dart::compiler::target::word Type_hash_offset = 40;
+static constexpr dart::compiler::target::word Type_signature_offset = 48;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
+static constexpr dart::compiler::target::word Type_type_state_offset = 60;
+static constexpr dart::compiler::target::word
+    TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_data_field_offset =
+    8;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word
+    TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word UserTag_tag_offset = 16;
+static constexpr dart::compiler::target::word Array_elements_start_offset = 24;
+static constexpr dart::compiler::target::word Array_element_size = 8;
+static constexpr dart::compiler::target::word
+    TypeArguments_elements_start_offset = 32;
+static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
+static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
+    0;
+static constexpr dart::compiler::target::word ClassTable_element_size = 288;
+static constexpr dart::compiler::target::word
+    ClassTable_class_heap_stats_table_offset = 32;
+static dart::compiler::target::word Code_entry_point_offset[] = {8, 24, 16, 32};
+static dart::compiler::target::word Code_function_entry_point_offset[] = {8,
+                                                                          16};
+static constexpr dart::compiler::target::word Array_header_size = 24;
+static constexpr dart::compiler::target::word Context_header_size = 24;
+static constexpr dart::compiler::target::word Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
+    24;
+static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word NativeArguments_StructSize = 32;
+static constexpr dart::compiler::target::word String_InstanceSize = 16;
+static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
+static constexpr dart::compiler::target::word Object_InstanceSize = 8;
+static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
+static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
+    32;
+static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
+static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
+#endif  // defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
+
+#if defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
+static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
+    8;
+static constexpr dart::compiler::target::word ObjectPool_element_size = 4;
+static constexpr dart::compiler::target::word Array_kMaxElements = 268435455;
+static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
+    65533;
+static constexpr dart::compiler::target::word ClassTable_kSizeOfClassPairLog2 =
+    3;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffset = 0;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::compiler::target::word HeapPage_kBytesPerCardLog2 = 9;
+static constexpr dart::compiler::target::word
+    NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word String_kMaxElements = 536870911;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::compiler::target::word
+    AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
+    16;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_first_named_entry_offset = 24;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
+    0;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_positional_count_offset = 20;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::compiler::target::word Array_data_offset = 12;
+static constexpr dart::compiler::target::word Array_length_offset = 8;
+static constexpr dart::compiler::target::word Array_tags_offset = 0;
+static constexpr dart::compiler::target::word Array_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word Class_declaration_type_offset =
+    56;
+static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
+    102;
+static constexpr dart::compiler::target::word Class_super_type_offset = 44;
+static constexpr dart::compiler::target::word
+    Class_type_arguments_field_offset_in_words_offset = 92;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_since_gc_new_space_offset = 48;
+static constexpr dart::compiler::target::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
+static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 160;
+static constexpr dart::compiler::target::word ClassTable_table_offset = 8;
+static constexpr dart::compiler::target::word Closure_context_offset = 20;
+static constexpr dart::compiler::target::word
+    Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::compiler::target::word Closure_function_offset = 16;
+static constexpr dart::compiler::target::word
+    Closure_function_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Closure_hash_offset = 24;
+static constexpr dart::compiler::target::word
+    Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
+static constexpr dart::compiler::target::word Code_saved_instructions_offset =
+    24;
+static constexpr dart::compiler::target::word Code_owner_offset = 28;
+static constexpr dart::compiler::target::word Context_num_variables_offset = 4;
+static constexpr dart::compiler::target::word Context_parent_offset = 8;
+static constexpr dart::compiler::target::word Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word Field_guarded_cid_offset = 48;
+static constexpr dart::compiler::target::word
+    Field_guarded_list_length_in_object_offset_offset = 56;
+static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
+    28;
+static constexpr dart::compiler::target::word Field_is_nullable_offset = 50;
+static constexpr dart::compiler::target::word Field_static_value_offset = 16;
+static constexpr dart::compiler::target::word Field_kind_bits_offset = 58;
+static constexpr dart::compiler::target::word Function_code_offset = 44;
+static constexpr dart::compiler::target::word Function_entry_point_offset = 4;
+static constexpr dart::compiler::target::word
+    Function_unchecked_entry_point_offset = 8;
+static constexpr dart::compiler::target::word Function_usage_counter_offset =
+    76;
+static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
+    12;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_length_offset = 8;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word HeapPage_card_table_offset = 20;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word
+    ICData_arguments_descriptor_offset = 12;
+static constexpr dart::compiler::target::word ICData_entries_offset = 4;
+static constexpr dart::compiler::target::word ICData_owner_offset = 20;
+static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
+static constexpr dart::compiler::target::word
+    ICData_receivers_static_type_offset = 16;
+static constexpr dart::compiler::target::word Isolate_class_table_offset = 24;
+static constexpr dart::compiler::target::word Isolate_current_tag_offset = 8;
+static constexpr dart::compiler::target::word Isolate_default_tag_offset = 12;
+static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 16;
+static constexpr dart::compiler::target::word Isolate_object_store_offset = 20;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 44;
+static constexpr dart::compiler::target::word Isolate_user_tag_offset = 4;
+static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
+static constexpr dart::compiler::target::word
+    LinkedHashMap_deleted_keys_offset = 24;
+static constexpr dart::compiler::target::word LinkedHashMap_hash_mask_offset =
+    12;
+static constexpr dart::compiler::target::word LinkedHashMap_index_offset = 8;
+static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
+    20;
+static constexpr dart::compiler::target::word
+    MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
+static constexpr dart::compiler::target::word
+    MegamorphicCache_arguments_descriptor_offset = 16;
+static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
+    4;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 8;
+static constexpr dart::compiler::target::word Mint_value_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
+    4;
+static constexpr dart::compiler::target::word NativeArguments_argv_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_retval_offset =
+    12;
+static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
+    64;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 32;
+static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
+    80;
+static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
+static constexpr dart::compiler::target::word Pointer_c_memory_address_offset =
+    8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
+    4;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
+    8;
+static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4;
+static constexpr dart::compiler::target::word String_hash_offset = 8;
+static constexpr dart::compiler::target::word String_length_offset = 4;
+static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
+static constexpr dart::compiler::target::word
+    Thread_AllocateArray_entry_point_offset = 152;
+static constexpr dart::compiler::target::word Thread_active_exception_offset =
+    444;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    448;
+static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
+    84;
+static constexpr dart::compiler::target::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 112;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 104;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 100;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 476;
+static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
+    132;
+static constexpr dart::compiler::target::word
+    Thread_double_negate_address_offset = 128;
+static constexpr dart::compiler::target::word Thread_end_offset = 60;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    460;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 144;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 140;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    136;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 148;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
+    452;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 48;
+static constexpr dart::compiler::target::word
+    Thread_marking_stack_block_offset = 72;
+static constexpr dart::compiler::target::word
+    Thread_no_scope_native_wrapper_entry_point_offset = 108;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 96;
+static constexpr dart::compiler::target::word
+    Thread_predefined_symbols_address_offset = 120;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 456;
+static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
+    464;
+static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_flags_offset = 40;
+static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
+    68;
+static constexpr dart::compiler::target::word
+    Thread_top_exit_frame_info_offset = 64;
+static constexpr dart::compiler::target::word Thread_top_offset = 56;
+static constexpr dart::compiler::target::word Thread_top_resource_offset = 24;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_int64_runtime_arg_offset = 88;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 80;
+static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
+    44;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 468;
+static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
+static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
+static constexpr dart::compiler::target::word Type_arguments_offset = 16;
+static constexpr dart::compiler::target::word Type_hash_offset = 20;
+static constexpr dart::compiler::target::word Type_signature_offset = 24;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 12;
+static constexpr dart::compiler::target::word Type_type_state_offset = 32;
+static constexpr dart::compiler::target::word
+    TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
+static constexpr dart::compiler::target::word TypedDataBase_data_field_offset =
+    4;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
+static constexpr dart::compiler::target::word
+    TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::compiler::target::word TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word UserTag_tag_offset = 8;
+static constexpr dart::compiler::target::word Array_elements_start_offset = 12;
+static constexpr dart::compiler::target::word Array_element_size = 4;
+static constexpr dart::compiler::target::word
+    TypeArguments_elements_start_offset = 16;
+static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
+static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
+    0;
+static constexpr dart::compiler::target::word ClassTable_element_size = 168;
+static constexpr dart::compiler::target::word
+    ClassTable_class_heap_stats_table_offset = 16;
+static dart::compiler::target::word Code_entry_point_offset[] = {4, 12, 8, 16};
+static dart::compiler::target::word Code_function_entry_point_offset[] = {4, 8};
+static constexpr dart::compiler::target::word Array_header_size = 12;
+static constexpr dart::compiler::target::word Context_header_size = 12;
+static constexpr dart::compiler::target::word Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
+    16;
+static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word NativeArguments_StructSize = 16;
+static constexpr dart::compiler::target::word String_InstanceSize = 12;
+static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
+static constexpr dart::compiler::target::word Object_InstanceSize = 4;
+static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
+static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
+static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
+static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28;
+#endif  // defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
+
+#endif  // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
new file mode 100644
index 0000000..007773a
--- /dev/null
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -0,0 +1,273 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_LIST_H_
+#define RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_LIST_H_
+
+// Macro list of all constants that differ based on whether the architecture is
+// 32-bit or 64-bit. They are used to allow the target architecture to differ
+// from the host, like this:
+// 1) The macros correspond to constants defined throughout the VM that are
+//    sized based on the *host* architecture.
+// 2) offsets_extractor.cc prints these values to runtime_offsets_extracted.h,
+//    for both 32 and 64 bit architectures.
+// 3) runtime_api.h presents the runtime_offsets_extracted.h constants in a way
+//    designed to look like the original constants from 1), but now namespaced
+//    to dart::compiler::target, and sized based on the *target* architecture.
+// 4) Users of the constants from 1) can now just add the namespace from 3) to
+//    get all their constants sized based on the target rather than the host.
+
+// FIELD(Class, Name) Offset of a field within a class.
+// ARRAY(Class, Name) Offset of the first element and the size of the elements
+//     in an array of this class.
+// ARRAY_STRUCTFIELD(Class, Name, Element, Field) Offset of a field within a
+//     struct in an array of that struct, relative to the start of the array.
+// SIZEOF(Class, Name, What) Size of an object.
+// RANGE(Class, Name, Type, First, Last, Filter) An array of offsets generated
+//     by passing a value of the given Type in the range from First to Last to
+//     Class::Name() if Filter returns true for that value.
+// CONSTANT(Class, Name) Miscellaneous constant.
+// PRECOMP_NO_CHECK(Code) Don't check this offset in the precompiled runtime.
+#define OFFSETS_LIST(FIELD, ARRAY, ARRAY_STRUCTFIELD, SIZEOF, RANGE, CONSTANT, \
+                     PRECOMP_NO_CHECK)                                         \
+  ARRAY(ObjectPool, element_offset)                                            \
+  CONSTANT(Array, kMaxElements)                                                \
+  CONSTANT(Array, kMaxNewSpaceElements)                                        \
+  CONSTANT(ClassTable, kSizeOfClassPairLog2)                                   \
+  CONSTANT(Instructions, kMonomorphicEntryOffset)                              \
+  CONSTANT(Instructions, kPolymorphicEntryOffset)                              \
+  CONSTANT(HeapPage, kBytesPerCardLog2)                                        \
+  CONSTANT(NativeEntry, kNumCallWrapperArguments)                              \
+  CONSTANT(String, kMaxElements)                                               \
+  CONSTANT(SubtypeTestCache, kFunctionTypeArguments)                           \
+  CONSTANT(SubtypeTestCache, kInstanceClassIdOrFunction)                       \
+  CONSTANT(SubtypeTestCache, kInstanceDelayedFunctionTypeArguments)            \
+  CONSTANT(SubtypeTestCache, kInstanceParentFunctionTypeArguments)             \
+  CONSTANT(SubtypeTestCache, kInstanceTypeArguments)                           \
+  CONSTANT(SubtypeTestCache, kInstantiatorTypeArguments)                       \
+  CONSTANT(SubtypeTestCache, kTestEntryLength)                                 \
+  CONSTANT(SubtypeTestCache, kTestResult)                                      \
+  FIELD(AbstractType, type_test_stub_entry_point_offset)                       \
+  FIELD(ArgumentsDescriptor, count_offset)                                     \
+  FIELD(ArgumentsDescriptor, first_named_entry_offset)                         \
+  FIELD(ArgumentsDescriptor, named_entry_size)                                 \
+  FIELD(ArgumentsDescriptor, name_offset)                                      \
+  FIELD(ArgumentsDescriptor, position_offset)                                  \
+  FIELD(ArgumentsDescriptor, positional_count_offset)                          \
+  FIELD(ArgumentsDescriptor, type_args_len_offset)                             \
+  FIELD(Array, data_offset)                                                    \
+  FIELD(Array, length_offset)                                                  \
+  FIELD(Array, tags_offset)                                                    \
+  FIELD(Array, type_arguments_offset)                                          \
+  FIELD(Class, declaration_type_offset)                                        \
+  FIELD(Class, num_type_arguments_offset)                                      \
+  FIELD(Class, super_type_offset)                                              \
+  FIELD(Class, type_arguments_field_offset_in_words_offset)                    \
+  NOT_IN_PRODUCT(FIELD(ClassHeapStats, TraceAllocationMask))                   \
+  NOT_IN_PRODUCT(FIELD(ClassHeapStats, allocated_since_gc_new_space_offset))   \
+  NOT_IN_PRODUCT(                                                              \
+      FIELD(ClassHeapStats, allocated_size_since_gc_new_space_offset))         \
+  NOT_IN_PRODUCT(FIELD(ClassHeapStats, state_offset))                          \
+  FIELD(ClassTable, table_offset)                                              \
+  FIELD(Closure, context_offset)                                               \
+  FIELD(Closure, delayed_type_arguments_offset)                                \
+  FIELD(Closure, function_offset)                                              \
+  FIELD(Closure, function_type_arguments_offset)                               \
+  FIELD(Closure, hash_offset)                                                  \
+  FIELD(Closure, instantiator_type_arguments_offset)                           \
+  FIELD(Code, object_pool_offset)                                              \
+  FIELD(Code, saved_instructions_offset)                                       \
+  FIELD(Code, owner_offset)                                                    \
+  FIELD(Context, num_variables_offset)                                         \
+  FIELD(Context, parent_offset)                                                \
+  FIELD(Double, value_offset)                                                  \
+  FIELD(ExternalOneByteString, external_data_offset)                           \
+  FIELD(ExternalTwoByteString, external_data_offset)                           \
+  FIELD(Float32x4, value_offset)                                               \
+  FIELD(Float64x2, value_offset)                                               \
+  PRECOMP_NO_CHECK(FIELD(Field, guarded_cid_offset))                           \
+  PRECOMP_NO_CHECK(FIELD(Field, guarded_list_length_in_object_offset_offset))  \
+  PRECOMP_NO_CHECK(FIELD(Field, guarded_list_length_offset))                   \
+  PRECOMP_NO_CHECK(FIELD(Field, is_nullable_offset))                           \
+  FIELD(Field, static_value_offset)                                            \
+  PRECOMP_NO_CHECK(FIELD(Field, kind_bits_offset))                             \
+  FIELD(Function, code_offset)                                                 \
+  FIELD(Function, entry_point_offset)                                          \
+  FIELD(Function, unchecked_entry_point_offset)                                \
+  PRECOMP_NO_CHECK(FIELD(Function, usage_counter_offset))                      \
+  FIELD(GrowableObjectArray, data_offset)                                      \
+  FIELD(GrowableObjectArray, length_offset)                                    \
+  FIELD(GrowableObjectArray, type_arguments_offset)                            \
+  FIELD(HeapPage, card_table_offset)                                           \
+  FIELD(ICData, NumArgsTestedMask)                                             \
+  FIELD(ICData, NumArgsTestedShift)                                            \
+  FIELD(ICData, arguments_descriptor_offset)                                   \
+  FIELD(ICData, entries_offset)                                                \
+  PRECOMP_NO_CHECK(FIELD(ICData, owner_offset))                                \
+  PRECOMP_NO_CHECK(FIELD(ICData, state_bits_offset))                           \
+  NOT_IN_PRECOMPILED_RUNTIME(FIELD(ICData, receivers_static_type_offset))      \
+  FIELD(Isolate, class_table_offset)                                           \
+  FIELD(Isolate, current_tag_offset)                                           \
+  FIELD(Isolate, default_tag_offset)                                           \
+  FIELD(Isolate, ic_miss_code_offset)                                          \
+  FIELD(Isolate, object_store_offset)                                          \
+  NOT_IN_PRODUCT(FIELD(Isolate, single_step_offset))                           \
+  FIELD(Isolate, user_tag_offset)                                              \
+  FIELD(LinkedHashMap, data_offset)                                            \
+  FIELD(LinkedHashMap, deleted_keys_offset)                                    \
+  FIELD(LinkedHashMap, hash_mask_offset)                                       \
+  FIELD(LinkedHashMap, index_offset)                                           \
+  FIELD(LinkedHashMap, used_data_offset)                                       \
+  FIELD(MarkingStackBlock, pointers_offset)                                    \
+  FIELD(MarkingStackBlock, top_offset)                                         \
+  FIELD(MegamorphicCache, arguments_descriptor_offset)                         \
+  FIELD(MegamorphicCache, buckets_offset)                                      \
+  FIELD(MegamorphicCache, mask_offset)                                         \
+  FIELD(Mint, value_offset)                                                    \
+  FIELD(NativeArguments, argc_tag_offset)                                      \
+  FIELD(NativeArguments, argv_offset)                                          \
+  FIELD(NativeArguments, retval_offset)                                        \
+  FIELD(NativeArguments, thread_offset)                                        \
+  FIELD(ObjectStore, double_type_offset)                                       \
+  FIELD(ObjectStore, int_type_offset)                                          \
+  FIELD(ObjectStore, string_type_offset)                                       \
+  FIELD(OneByteString, data_offset)                                            \
+  FIELD(Pointer, c_memory_address_offset)                                      \
+  FIELD(SingleTargetCache, entry_point_offset)                                 \
+  FIELD(SingleTargetCache, lower_limit_offset)                                 \
+  FIELD(SingleTargetCache, target_offset)                                      \
+  FIELD(SingleTargetCache, upper_limit_offset)                                 \
+  FIELD(StoreBufferBlock, pointers_offset)                                     \
+  FIELD(StoreBufferBlock, top_offset)                                          \
+  FIELD(String, hash_offset)                                                   \
+  FIELD(String, length_offset)                                                 \
+  FIELD(SubtypeTestCache, cache_offset)                                        \
+  FIELD(Thread, AllocateArray_entry_point_offset)                              \
+  FIELD(Thread, active_exception_offset)                                       \
+  FIELD(Thread, active_stacktrace_offset)                                      \
+  NOT_IN_DBC(FIELD(Thread, array_write_barrier_code_offset))                   \
+  NOT_IN_DBC(FIELD(Thread, array_write_barrier_entry_point_offset))            \
+  FIELD(Thread, async_stack_trace_offset)                                      \
+  FIELD(Thread, auto_scope_native_wrapper_entry_point_offset)                  \
+  FIELD(Thread, bool_false_offset)                                             \
+  FIELD(Thread, bool_true_offset)                                              \
+  NOT_IN_DBC(FIELD(Thread, call_to_runtime_entry_point_offset))                \
+  NOT_IN_DBC(FIELD(Thread, call_to_runtime_stub_offset))                       \
+  FIELD(Thread, dart_stream_offset)                                            \
+  NOT_IN_DBC(FIELD(Thread, deoptimize_entry_offset))                           \
+  NOT_IN_DBC(FIELD(Thread, deoptimize_stub_offset))                            \
+  FIELD(Thread, double_abs_address_offset)                                     \
+  FIELD(Thread, double_negate_address_offset)                                  \
+  FIELD(Thread, end_offset)                                                    \
+  NOT_IN_DBC(FIELD(Thread, enter_safepoint_stub_offset))                       \
+  FIELD(Thread, execution_state_offset)                                        \
+  NOT_IN_DBC(FIELD(Thread, exit_safepoint_stub_offset))                        \
+  NOT_IN_DBC(FIELD(Thread, fix_allocation_stub_code_offset))                   \
+  NOT_IN_DBC(FIELD(Thread, fix_callers_target_code_offset))                    \
+  FIELD(Thread, float_absolute_address_offset)                                 \
+  FIELD(Thread, float_negate_address_offset)                                   \
+  FIELD(Thread, float_not_address_offset)                                      \
+  FIELD(Thread, float_zerow_address_offset)                                    \
+  FIELD(Thread, global_object_pool_offset)                                     \
+  NOT_IN_DBC(FIELD(Thread, ic_lookup_through_code_stub_offset))                \
+  NOT_IN_DBC(FIELD(Thread, interpret_call_entry_point_offset))                 \
+  NOT_IN_DBC(FIELD(Thread, invoke_dart_code_from_bytecode_stub_offset))        \
+  NOT_IN_DBC(FIELD(Thread, invoke_dart_code_stub_offset))                      \
+  FIELD(Thread, isolate_offset)                                                \
+  NOT_IN_DBC(FIELD(Thread, lazy_deopt_from_return_stub_offset))                \
+  NOT_IN_DBC(FIELD(Thread, lazy_deopt_from_throw_stub_offset))                 \
+  NOT_IN_DBC(FIELD(Thread, lazy_specialize_type_test_stub_offset))             \
+  FIELD(Thread, marking_stack_block_offset)                                    \
+  NOT_IN_DBC(FIELD(Thread, megamorphic_call_checked_entry_offset))             \
+  NOT_IN_DBC(FIELD(Thread, monomorphic_miss_entry_offset))                     \
+  NOT_IN_DBC(FIELD(Thread, monomorphic_miss_stub_offset))                      \
+  FIELD(Thread, no_scope_native_wrapper_entry_point_offset)                    \
+  NOT_IN_DBC(                                                                  \
+      FIELD(Thread, null_error_shared_with_fpu_regs_entry_point_offset))       \
+  NOT_IN_DBC(FIELD(Thread, null_error_shared_with_fpu_regs_stub_offset))       \
+  NOT_IN_DBC(                                                                  \
+      FIELD(Thread, null_error_shared_without_fpu_regs_entry_point_offset))    \
+  NOT_IN_DBC(FIELD(Thread, null_error_shared_without_fpu_regs_stub_offset))    \
+  FIELD(Thread, object_null_offset)                                            \
+  FIELD(Thread, predefined_symbols_address_offset)                             \
+  FIELD(Thread, resume_pc_offset)                                              \
+  FIELD(Thread, safepoint_state_offset)                                        \
+  NOT_IN_DBC(FIELD(Thread, slow_type_test_stub_offset))                        \
+  FIELD(Thread, stack_limit_offset)                                            \
+  FIELD(Thread, stack_overflow_flags_offset)                                   \
+  NOT_IN_DBC(                                                                  \
+      FIELD(Thread, stack_overflow_shared_with_fpu_regs_entry_point_offset))   \
+  NOT_IN_DBC(FIELD(Thread, stack_overflow_shared_with_fpu_regs_stub_offset))   \
+  NOT_IN_DBC(FIELD(Thread,                                                     \
+                   stack_overflow_shared_without_fpu_regs_entry_point_offset)) \
+  NOT_IN_DBC(                                                                  \
+      FIELD(Thread, stack_overflow_shared_without_fpu_regs_stub_offset))       \
+  FIELD(Thread, store_buffer_block_offset)                                     \
+  FIELD(Thread, top_exit_frame_info_offset)                                    \
+  FIELD(Thread, top_offset)                                                    \
+  FIELD(Thread, top_resource_offset)                                           \
+  FIELD(Thread, unboxed_int64_runtime_arg_offset)                              \
+  FIELD(Thread, vm_tag_offset)                                                 \
+  NOT_IN_DBC(FIELD(Thread, write_barrier_code_offset))                         \
+  NOT_IN_DBC(FIELD(Thread, write_barrier_entry_point_offset))                  \
+  FIELD(Thread, write_barrier_mask_offset)                                     \
+  NOT_IN_DBC(FIELD(Thread, verify_callback_entry_offset))                      \
+  FIELD(Thread, callback_code_offset)                                          \
+  FIELD(TimelineStream, enabled_offset)                                        \
+  FIELD(TwoByteString, data_offset)                                            \
+  FIELD(Type, arguments_offset)                                                \
+  FIELD(Type, hash_offset)                                                     \
+  FIELD(Type, signature_offset)                                                \
+  FIELD(Type, type_class_id_offset)                                            \
+  FIELD(Type, type_state_offset)                                               \
+  FIELD(TypeArguments, instantiations_offset)                                  \
+  FIELD(TypeRef, type_offset)                                                  \
+  FIELD(TypedDataBase, data_field_offset)                                      \
+  FIELD(TypedDataBase, length_offset)                                          \
+  FIELD(TypedDataView, data_offset)                                            \
+  FIELD(TypedDataView, offset_in_bytes_offset)                                 \
+  FIELD(TypedData, data_offset)                                                \
+  FIELD(UserTag, tag_offset)                                                   \
+  ARRAY(Array, element_offset)                                                 \
+  ARRAY(TypeArguments, type_at_offset)                                         \
+  NOT_IN_PRODUCT(ARRAY(ClassTable, ClassOffsetFor))                            \
+  NOT_IN_PRODUCT(ARRAY_STRUCTFIELD(                                            \
+      ClassTable, NewSpaceCounterOffsetFor, ClassOffsetFor,                    \
+      ClassHeapStats::allocated_since_gc_new_space_offset()))                  \
+  NOT_IN_PRODUCT(ARRAY_STRUCTFIELD(                                            \
+      ClassTable, StateOffsetFor, ClassOffsetFor,                              \
+      ClassHeapStats::allocated_since_gc_new_space_offset()))                  \
+  NOT_IN_PRODUCT(ARRAY_STRUCTFIELD(                                            \
+      ClassTable, NewSpaceSizeOffsetFor, ClassOffsetFor,                       \
+      ClassHeapStats::allocated_size_since_gc_new_space_offset()))             \
+  NOT_IN_PRODUCT(FIELD(ClassTable, class_heap_stats_table_offset))             \
+  RANGE(Code, entry_point_offset, CodeEntryKind, CodeEntryKind::kNormal,       \
+        CodeEntryKind::kMonomorphicUnchecked,                                  \
+        [](CodeEntryKind value) { return true; })                              \
+  RANGE(Code, function_entry_point_offset, CodeEntryKind,                      \
+        CodeEntryKind::kNormal, CodeEntryKind::kUnchecked,                     \
+        [](CodeEntryKind value) { return true; })                              \
+  ONLY_IN_ARM_ARM64_X64(RANGE(                                                 \
+      Thread, write_barrier_wrappers_thread_offset, Register, 0,               \
+      kNumberOfCpuRegisters - 1,                                               \
+      [](Register reg) { return (kDartAvailableCpuRegs & (1 << reg)) != 0; })) \
+  SIZEOF(Array, header_size, RawArray)                                         \
+  SIZEOF(Context, header_size, RawContext)                                     \
+  SIZEOF(Double, InstanceSize, RawDouble)                                      \
+  SIZEOF(Float32x4, InstanceSize, RawFloat32x4)                                \
+  SIZEOF(Float64x2, InstanceSize, RawFloat64x2)                                \
+  SIZEOF(Instructions, UnalignedHeaderSize, RawInstructions)                   \
+  SIZEOF(Int32x4, InstanceSize, RawInt32x4)                                    \
+  SIZEOF(Mint, InstanceSize, RawMint)                                          \
+  SIZEOF(NativeArguments, StructSize, NativeArguments)                         \
+  SIZEOF(String, InstanceSize, RawString)                                      \
+  SIZEOF(TypedData, InstanceSize, RawTypedData)                                \
+  SIZEOF(Object, InstanceSize, RawObject)                                      \
+  SIZEOF(TypedDataBase, InstanceSize, RawTypedDataBase)                        \
+  SIZEOF(Closure, InstanceSize, RawClosure)                                    \
+  SIZEOF(GrowableObjectArray, InstanceSize, RawGrowableObjectArray)            \
+  SIZEOF(Instance, InstanceSize, RawInstance)                                  \
+  SIZEOF(LinkedHashMap, InstanceSize, RawLinkedHashMap)
+
+#endif  // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_LIST_H_
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index c227889..b7d0332 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -41,13 +41,27 @@
   static void GenerateMegamorphicMissStub(Assembler* assembler);
   static void GenerateAllocationStubForClass(Assembler* assembler,
                                              const Class& cls);
+
+  enum Optimized {
+    kUnoptimized,
+    kOptimized,
+  };
+  enum CallType {
+    kInstanceCall,
+    kStaticCall,
+  };
+  enum Exactness {
+    kCheckExactness,
+    kIgnoreExactness,
+  };
   static void GenerateNArgsCheckInlineCacheStub(
       Assembler* assembler,
       intptr_t num_args,
       const RuntimeEntry& handle_ic_miss,
       Token::Kind kind,
-      bool optimized = false,
-      bool exactness_check = false);
+      Optimized optimized,
+      CallType type,
+      Exactness exactness);
   static void GenerateUsageCounterIncrement(Assembler* assembler,
                                             Register temp_reg);
   static void GenerateOptimizedUsageCounterIncrement(Assembler* assembler);
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 7024fd8..bdf0ec4 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -274,8 +274,13 @@
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
+
+  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  __ ReserveAlignedFrameSpace(0);
   __ ldr(R0, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
   __ blx(R0);
+  __ LeaveFrame((1 << FP) | (1 << LR), 0);
+
   __ PopRegisters(all_registers);
   __ Ret();
 }
@@ -284,12 +289,35 @@
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
+
+  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  __ ReserveAlignedFrameSpace(0);
   __ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
   __ blx(R0);
+  __ LeaveFrame((1 << FP) | (1 << LR), 0);
+
   __ PopRegisters(all_registers);
   __ Ret();
 }
 
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+  __ EnterFrame(1 << FP | 1 << LR, 0);
+  __ ReserveAlignedFrameSpace(0);
+
+  // First argument is already set up by the caller.
+  //
+  // Second argument is the return address of the caller.
+  __ mov(CallingConventions::ArgumentRegisters[1], Operand(LR));
+  ASSERT(R2 != CallingConventions::ArgumentRegisters[0] &&
+         R2 != CallingConventions::ArgumentRegisters[1]);
+  __ LoadFromOffset(kWord, R2, THR,
+                    kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread());
+  __ blx(R2);
+
+  __ LeaveFrame(1 << FP | 1 << LR);
+  __ Ret();
+}
+
 void StubCodeCompiler::GenerateNullErrorSharedWithoutFPURegsStub(
     Assembler* assembler) {
   GenerateSharedStub(
@@ -837,7 +865,7 @@
   // R2: Smi-tagged arguments array length.
   PushArrayOfArguments(assembler);
   const intptr_t kNumArgs = 4;
-  __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
+  __ CallRuntime(kNoSuchMethodFromCallStubRuntimeEntry, kNumArgs);
   __ Drop(4);
   __ Pop(R0);  // Return value.
   __ LeaveStubFrame();
@@ -1031,17 +1059,7 @@
   __ ldr(IP, Address(R3, target::Thread::invoke_dart_code_stub_offset()));
   __ Push(IP);
 
-  // Save new context and C++ ABI callee-saved registers.
-  __ PushList(kAbiPreservedCpuRegs);
-
-  const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
-  if (TargetCPUFeatures::vfp_supported()) {
-    ASSERT(2 * kAbiPreservedFpuRegCount < 16);
-    // Save FPU registers. 2 D registers per Q register.
-    __ vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
-  } else {
-    __ sub(SP, SP, Operand(kAbiPreservedFpuRegCount * kFpuRegisterSize));
-  }
+  __ PushNativeCalleeSavedRegisters();
 
   // Set up THR, which caches the current thread in Dart code.
   if (THR != R3) {
@@ -1072,13 +1090,15 @@
 #endif
   __ Push(R9);
 
+  __ EmitEntryFrameVerification(R9);
+
   // Mark that the thread is executing Dart code. Do this after initializing the
   // exit link for the profiler.
   __ LoadImmediate(R9, VMTag::kDartCompiledTagId);
   __ StoreToOffset(kWord, R9, THR, target::Thread::vm_tag_offset());
 
   // Load arguments descriptor array into R4, which is passed to Dart code.
-  __ ldr(R4, Address(R1, VMHandles::kOffsetOfRawPtrInHandle));
+  __ ldr(R4, Address(R1, target::VMHandles::kOffsetOfRawPtrInHandle));
 
   // Load number of arguments into R9 and adjust count for type arguments.
   __ ldr(R3,
@@ -1090,7 +1110,7 @@
   __ SmiUntag(R9);
 
   // Compute address of 'arguments array' data area into R2.
-  __ ldr(R2, Address(R2, VMHandles::kOffsetOfRawPtrInHandle));
+  __ ldr(R2, Address(R2, target::VMHandles::kOffsetOfRawPtrInHandle));
   __ AddImmediate(R2, target::Array::data_offset() - kHeapObjectTag);
 
   // Set up arguments for the Dart call.
@@ -1114,7 +1134,7 @@
   } else {
     __ LoadImmediate(PP, 0);  // GC safe value into PP.
   }
-  __ ldr(CODE_REG, Address(R0, VMHandles::kOffsetOfRawPtrInHandle));
+  __ ldr(CODE_REG, Address(R0, target::VMHandles::kOffsetOfRawPtrInHandle));
   __ ldr(R0, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ blx(R0);  // R4 is the arguments descriptor array.
 
@@ -1135,15 +1155,8 @@
   __ Pop(R4);
   __ StoreToOffset(kWord, R4, THR, target::Thread::vm_tag_offset());
 
-  // Restore C++ ABI callee-saved registers.
-  if (TargetCPUFeatures::vfp_supported()) {
-    // Restore FPU registers. 2 D registers per Q register.
-    __ vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
-  } else {
-    __ AddImmediate(SP, kAbiPreservedFpuRegCount * kFpuRegisterSize);
-  }
-  // Restore CPU registers.
-  __ PopList(kAbiPreservedCpuRegs);
+  __ PopNativeCalleeSavedRegisters();
+
   __ set_constant_pool_allowed(false);
 
   // Restore the frame pointer and return.
@@ -1655,7 +1668,7 @@
   // when the object initialization should be done as a loop or as
   // straight line code.
   const int kInlineInstanceSize = 12;
-  const intptr_t instance_size = target::Class::InstanceSize(cls);
+  const intptr_t instance_size = target::Class::GetInstanceSize(cls);
   ASSERT(instance_size > 0);
   ASSERT(instance_size % target::ObjectAlignment::kObjectAlignment == 0);
   if (is_cls_parameterized) {
@@ -1748,7 +1761,7 @@
     EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
   }
 
-  __ LeaveDartFrameAndReturn();         // Restores correct SP.
+  __ LeaveDartFrameAndReturn();  // Restores correct SP.
 }
 
 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
@@ -1768,11 +1781,14 @@
   __ ldr(R8, Address(IP, target::frame_layout.param_end_from_fp *
                              target::kWordSize));
 
+  // Load the function.
+  __ ldr(R6, FieldAddress(R8, target::Closure::function_offset()));
+
   // Push space for the return value.
   // Push the receiver.
   // Push arguments descriptor array.
   __ LoadImmediate(IP, 0);
-  __ PushList((1 << R4) | (1 << R8) | (1 << IP));
+  __ PushList((1 << R4) | (1 << R6) | (1 << R8) | (1 << IP));
 
   // Adjust arguments count.
   __ ldr(R3,
@@ -1784,8 +1800,8 @@
   // R2: Smi-tagged arguments array length.
   PushArrayOfArguments(assembler);
 
-  const intptr_t kNumArgs = 3;
-  __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs);
+  const intptr_t kNumArgs = 4;
+  __ CallRuntime(kNoSuchMethodFromPrologueRuntimeEntry, kNumArgs);
   // noSuchMethod on closures always throws an error, so it will never return.
   __ bkpt(0);
 }
@@ -1841,8 +1857,8 @@
                           intptr_t num_args,
                           Label* not_smi_or_overflow) {
   __ Comment("Fast Smi op");
-  __ ldr(R0, Address(SP, 0 * target::kWordSize));
-  __ ldr(R1, Address(SP, 1 * target::kWordSize));
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));  // Left.
+  __ ldr(R1, Address(SP, 0 * target::kWordSize));  // Right.
   __ orr(TMP, R0, Operand(R1));
   __ tst(TMP, Operand(kSmiTagMask));
   __ b(not_smi_or_overflow, NE);
@@ -1852,9 +1868,10 @@
       __ b(not_smi_or_overflow, VS);  // Branch if overflow.
       break;
     }
-    case Token::kSUB: {
-      __ subs(R0, R1, Operand(R0));   // Subtract.
-      __ b(not_smi_or_overflow, VS);  // Branch if overflow.
+    case Token::kLT: {
+      __ cmp(R0, Operand(R1));
+      __ LoadObject(R0, CastHandle<Object>(TrueObject()), LT);
+      __ LoadObject(R0, CastHandle<Object>(FalseObject()), GE);
       break;
     }
     case Token::kEQ: {
@@ -1897,8 +1914,9 @@
 }
 
 // Generate inline cache check for 'num_args'.
-//  LR: return address.
-//  R9: inline cache data object.
+//  R0: receiver (if instance call)
+//  R9: ICData
+//  LR: return address
 // Control flow:
 // - If receiver is null -> jump to IC miss.
 // - If receiver is Smi -> load Smi class.
@@ -1911,9 +1929,10 @@
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
     Token::Kind kind,
-    bool optimized,
-    bool exactness_check /* = false */) {
-  ASSERT(!exactness_check);
+    Optimized optimized,
+    CallType type,
+    Exactness exactness) {
+  ASSERT(exactness == kIgnoreExactness);  // Unimplemented.
   __ CheckCodePointer();
   ASSERT(num_args == 1 || num_args == 2);
 #if defined(DEBUG)
@@ -1933,7 +1952,7 @@
 
 #if !defined(PRODUCT)
   Label stepping, done_stepping;
-  if (!optimized) {
+  if (optimized == kUnoptimized) {
     __ Comment("Check single stepping");
     __ LoadIsolate(R8);
     __ ldrb(R8, Address(R8, target::Isolate::single_step_offset()));
@@ -1950,31 +1969,50 @@
   __ Bind(&not_smi_or_overflow);
 
   __ Comment("Extract ICData initial values and receiver cid");
-  // Load arguments descriptor into R4.
-  __ ldr(R4, FieldAddress(R9, target::ICData::arguments_descriptor_offset()));
-  // Loop that checks if there is an IC data match.
-  Label loop, found, miss;
   // R9: IC data object (preserved).
   __ ldr(R8, FieldAddress(R9, target::ICData::entries_offset()));
   // R8: ic_data_array with check entries: classes and target functions.
   const int kIcDataOffset = target::Array::data_offset() - kHeapObjectTag;
   // R8: points at the IC data array.
 
-  // Get the receiver's class ID (first read number of arguments from
-  // arguments descriptor array and then access the receiver from the stack).
-  __ ldr(NOTFP, FieldAddress(R4, target::ArgumentsDescriptor::count_offset()));
-  __ sub(NOTFP, NOTFP, Operand(target::ToRawSmi(1)));
-  // NOTFP: argument_count - 1 (smi).
+  if (type == kInstanceCall) {
+    __ LoadTaggedClassIdMayBeSmi(R0, R0);
+    __ ldr(R4, FieldAddress(R9, target::ICData::arguments_descriptor_offset()));
+    if (num_args == 2) {
+      __ ldr(NOTFP,
+             FieldAddress(R4, target::ArgumentsDescriptor::count_offset()));
+      __ sub(R1, NOTFP, Operand(target::ToRawSmi(2)));
+      __ ldr(R1, Address(SP, R1, LSL, 1));  // R1 (argument_count - 2) is Smi.
+      __ LoadTaggedClassIdMayBeSmi(R1, R1);
+    }
+  } else {
+    // Load arguments descriptor into R4.
+    __ ldr(R4, FieldAddress(R9, target::ICData::arguments_descriptor_offset()));
 
-  __ Comment("ICData loop");
+    // Get the receiver's class ID (first read number of arguments from
+    // arguments descriptor array and then access the receiver from the stack).
+    __ ldr(NOTFP,
+           FieldAddress(R4, target::ArgumentsDescriptor::count_offset()));
+    __ sub(NOTFP, NOTFP, Operand(target::ToRawSmi(1)));
+    // NOTFP: argument_count - 1 (smi).
 
-  __ ldr(R0, Address(SP, NOTFP, LSL, 1));  // NOTFP (argument_count - 1) is Smi.
-  __ LoadTaggedClassIdMayBeSmi(R0, R0);
-  if (num_args == 2) {
-    __ sub(R1, NOTFP, Operand(target::ToRawSmi(1)));
-    __ ldr(R1, Address(SP, R1, LSL, 1));  // R1 (argument_count - 2) is Smi.
-    __ LoadTaggedClassIdMayBeSmi(R1, R1);
+    __ ldr(R0,
+           Address(SP, NOTFP, LSL, 1));  // NOTFP (argument_count - 1) is Smi.
+    __ LoadTaggedClassIdMayBeSmi(R0, R0);
+
+    if (num_args == 2) {
+      __ sub(R1, NOTFP, Operand(target::ToRawSmi(1)));
+      __ ldr(R1, Address(SP, R1, LSL, 1));  // R1 (argument_count - 2) is Smi.
+      __ LoadTaggedClassIdMayBeSmi(R1, R1);
+    }
   }
+  // R0: first argument class ID as Smi.
+  // R1: second argument class ID as Smi.
+  // R4: args descriptor
+
+  // Loop that checks if there is an IC data match.
+  Label loop, found, miss;
+  __ Comment("ICData loop");
 
   // We unroll the generic one that is generated once more than the others.
   const bool optimize = kind == Token::kILLEGAL;
@@ -1994,9 +2032,9 @@
 
     __ Bind(&update);
 
-    const intptr_t entry_size =
-        target::ICData::TestEntryLengthFor(num_args, exactness_check) *
-        target::kWordSize;
+    const intptr_t entry_size = target::ICData::TestEntryLengthFor(
+                                    num_args, exactness == kCheckExactness) *
+                                target::kWordSize;
     __ AddImmediate(R8, entry_size);  // Next entry.
 
     __ CompareImmediate(R2, target::ToRawSmi(kIllegalCid));  // Done?
@@ -2010,6 +2048,8 @@
   __ Bind(&miss);
   __ Comment("IC miss");
   // Compute address of arguments.
+  __ ldr(NOTFP, FieldAddress(R4, target::ArgumentsDescriptor::count_offset()));
+  __ sub(NOTFP, NOTFP, Operand(target::ToRawSmi(1)));
   // NOTFP: argument_count - 1 (smi).
   __ add(NOTFP, SP, Operand(NOTFP, LSL, 1));  // NOTFP is Smi.
   // NOTFP: address of receiver.
@@ -2065,12 +2105,18 @@
   __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
 
 #if !defined(PRODUCT)
-  if (!optimized) {
+  if (optimized == kUnoptimized) {
     __ Bind(&stepping);
     __ EnterStubFrame();
+    if (type == kInstanceCall) {
+      __ Push(R0);  // Preserve receiver.
+    }
     __ Push(R9);  // Preserve IC data.
     __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
     __ Pop(R9);
+    if (type == kInstanceCall) {
+      __ Pop(R0);
+    }
     __ RestoreCodePointer();
     __ LeaveStubFrame();
     __ b(&done_stepping);
@@ -2078,82 +2124,105 @@
 #endif
 }
 
-// Use inline cache data array to invoke the target or continue in inline
-// cache miss handler. Stub for 1-argument check (receiver class).
-//  LR: return address.
-//  R9: inline cache data object.
-// Inline cache data object structure:
-// 0: function-name
-// 1: N, number of arguments checked.
-// 2 .. (length - 1): group of checks, each check containing:
-//   - N classes.
-//   - 1 target function.
+//  R0: receiver
+//  R9: ICData
+//  LR: return address
 void StubCodeCompiler::GenerateOneArgCheckInlineCacheStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R8);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R8);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
+      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+//  R0: receiver
+//  R9: ICData
+//  LR: return address
 void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
     Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
+//  R0: receiver
+//  R9: ICData
+//  LR: return address
 void StubCodeCompiler::GenerateTwoArgsCheckInlineCacheStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R8);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-                                    kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-                                    Token::kILLEGAL);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R8);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+//  R0: receiver
+//  R9: ICData
+//  LR: return address
 void StubCodeCompiler::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R8);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R8);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
-void StubCodeCompiler::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R8);
+//  R0: receiver
+//  R9: ICData
+//  LR: return address
+void StubCodeCompiler::GenerateSmiLessInlineCacheStub(Assembler* assembler) {
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R8);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kLT,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+//  R0: receiver
+//  R9: ICData
+//  LR: return address
 void StubCodeCompiler::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R8);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R8);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+//  R0: receiver
+//  R9: ICData
+//  R8: Function
+//  LR: return address
 void StubCodeCompiler::GenerateOneArgOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
-  GenerateOptimizedUsageCounterIncrement(assembler);
-  GenerateNArgsCheckInlineCacheStub(assembler, 1,
-                                    kInlineCacheMissHandlerOneArgRuntimeEntry,
-                                    Token::kILLEGAL, true /* optimized */);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R8);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kOptimized, kInstanceCall, kIgnoreExactness);
 }
 
+//  R0: receiver
+//  R9: ICData
+//  R8: Function
+//  LR: return address
 void StubCodeCompiler::
     GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
         Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
+//  R0: receiver
+//  R9: ICData
+//  R8: Function
+//  LR: return address
 void StubCodeCompiler::GenerateTwoArgsOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-                                    kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-                                    Token::kILLEGAL, true /* optimized */);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kOptimized, kInstanceCall, kIgnoreExactness);
 }
 
-// Intermediary stub between a static call and its target. ICData contains
-// the target function and the call count.
-// R9: ICData
+//  R9: ICData
+//  LR: return address
 void StubCodeCompiler::GenerateZeroArgsUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R8);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R8);
 #if defined(DEBUG)
   {
     Label ok;
@@ -2216,18 +2285,24 @@
 #endif
 }
 
+//  R9: ICData
+//  LR: return address
 void StubCodeCompiler::GenerateOneArgUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R8);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R8);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
+      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kStaticCall, kIgnoreExactness);
 }
 
+//  R9: ICData
+//  LR: return address
 void StubCodeCompiler::GenerateTwoArgsUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R8);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R8);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
+      assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kStaticCall, kIgnoreExactness);
 }
 
 // Stub for compiling a function and jumping to the compiled code.
@@ -2327,13 +2402,14 @@
   __ Stop("No debugging in PRODUCT mode");
 #else
   __ EnterStubFrame();
-  __ LoadImmediate(R0, 0);
-  // Preserve arguments descriptor and make room for result.
-  __ PushList((1 << R0) | (1 << R9));
+  __ Push(R0);          // Preserve receiver.
+  __ Push(R9);          // Preserve IC data.
+  __ PushImmediate(0);  // Space for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
-  __ PopList((1 << R0) | (1 << R9));
+  __ Pop(CODE_REG);  // Original stub.
+  __ Pop(R9);        // Restore IC data.
+  __ Pop(R0);        // Restore receiver.
   __ LeaveStubFrame();
-  __ mov(CODE_REG, Operand(R0));
   __ Branch(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
 #endif  // defined(PRODUCT)
 }
@@ -2842,6 +2918,7 @@
 // R8: function to be reoptimized.
 // R4: argument descriptor (preserved).
 void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) {
+  __ ldr(CODE_REG, Address(THR, Thread::optimize_stub_offset()));
   __ EnterStubFrame();
   __ Push(R4);
   __ LoadImmediate(IP, 0);
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 2205c2b..31e9286 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -209,12 +209,14 @@
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
-  __ mov(CallingConventions::kFirstCalleeSavedCpuReg, SP);
+
+  __ EnterFrame(0);
   __ ReserveAlignedFrameSpace(0);
   __ mov(CSP, SP);
   __ ldr(R0, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
   __ blr(R0);
-  __ mov(SP, CallingConventions::kFirstCalleeSavedCpuReg);
+  __ LeaveFrame();
+
   __ PopRegisters(all_registers);
   __ mov(CSP, SP);
   __ Ret();
@@ -224,17 +226,37 @@
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
-  __ mov(CallingConventions::kFirstCalleeSavedCpuReg, SP);
+
+  __ EnterFrame(0);
   __ ReserveAlignedFrameSpace(0);
   __ mov(CSP, SP);
   __ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
   __ blr(R0);
-  __ mov(SP, CallingConventions::kFirstCalleeSavedCpuReg);
+  __ LeaveFrame();
+
   __ PopRegisters(all_registers);
   __ mov(CSP, SP);
   __ Ret();
 }
 
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
+
+  // First argument is already set up by the caller.
+  //
+  // Second argument is the return address of the caller.
+  __ mov(CallingConventions::ArgumentRegisters[1], LR);
+  __ LoadFromOffset(R2, THR,
+                    kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread());
+  __ mov(CSP, SP);
+  __ blr(R2);
+  __ mov(SP, CSP);
+
+  __ LeaveFrame();
+  __ Ret();
+}
+
 // R1: The extracted method.
 // R4: The type_arguments_field_offset (or 0)
 void StubCodeCompiler::GenerateBuildMethodExtractorStub(
@@ -887,7 +909,7 @@
   // R2: Smi-tagged arguments array length.
   PushArrayOfArguments(assembler);
   const intptr_t kNumArgs = 4;
-  __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
+  __ CallRuntime(kNoSuchMethodFromCallStubRuntimeEntry, kNumArgs);
   __ Drop(4);
   __ Pop(R0);  // Return value.
   __ LeaveStubFrame();
@@ -1111,20 +1133,7 @@
   __ ldr(TMP, Address(R3, target::Thread::invoke_dart_code_stub_offset()));
   __ Push(TMP);
 
-  // Save the callee-saved registers.
-  for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) {
-    const Register r = static_cast<Register>(i);
-    // We use str instead of the Push macro because we will be pushing the PP
-    // register when it is not holding a pool-pointer since we are coming from
-    // C++ code.
-    __ str(r, Address(SP, -1 * target::kWordSize, Address::PreIndex));
-  }
-
-  // Save the bottom 64-bits of callee-saved V registers.
-  for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) {
-    const VRegister r = static_cast<VRegister>(i);
-    __ PushDouble(r);
-  }
+  __ PushNativeCalleeSavedRegisters();
 
   // Set up THR, which caches the current thread in Dart code.
   if (THR != R3) {
@@ -1218,21 +1227,7 @@
   __ Pop(R4);
   __ StoreToOffset(R4, THR, target::Thread::vm_tag_offset());
 
-  // Restore the bottom 64-bits of callee-saved V registers.
-  for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) {
-    const VRegister r = static_cast<VRegister>(i);
-    __ PopDouble(r);
-  }
-
-  // Restore C++ ABI callee-saved registers.
-  for (int i = kAbiLastPreservedCpuReg; i >= kAbiFirstPreservedCpuReg; i--) {
-    Register r = static_cast<Register>(i);
-    // We use ldr instead of the Pop macro because we will be popping the PP
-    // register when it is not holding a pool-pointer since we are returning to
-    // C++ code. We also skip the dart stack pointer SP, since we are still
-    // using it as the stack pointer.
-    __ ldr(r, Address(SP, 1 * target::kWordSize, Address::PostIndex));
-  }
+  __ PopNativeCalleeSavedRegisters();
 
   // Restore the frame pointer and C stack pointer and return.
   __ LeaveFrame();
@@ -1737,7 +1732,7 @@
   // when the object initialization should be done as a loop or as
   // straight line code.
   const int kInlineInstanceSize = 12;
-  const intptr_t instance_size = target::Class::InstanceSize(cls);
+  const intptr_t instance_size = target::Class::GetInstanceSize(cls);
   ASSERT(instance_size > 0);
   if (is_cls_parameterized) {
     __ ldr(kTypeArgumentsReg, Address(SP));
@@ -1806,7 +1801,7 @@
     // ensure that the object is in new-space or has remembered bit set.
     EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
   }
-  __ LeaveStubFrame();                  // Restores correct SP.
+  __ LeaveStubFrame();  // Restores correct SP.
   __ ret();
 }
 
@@ -1827,12 +1822,13 @@
   __ LoadFromOffset(R6, TMP,
                     target::frame_layout.param_end_from_fp * target::kWordSize);
 
-  // Push space for the return value.
-  // Push the receiver.
-  // Push arguments descriptor array.
-  __ Push(ZR);
-  __ Push(R6);
-  __ Push(R4);
+  // Load the function.
+  __ LoadFieldFromOffset(TMP, R6, target::Closure::function_offset());
+
+  __ Push(ZR);   // Result slot.
+  __ Push(R6);   // Receiver.
+  __ Push(TMP);  // Function
+  __ Push(R4);   // Arguments descriptor.
 
   // Adjust arguments count.
   __ LoadFieldFromOffset(R3, R4,
@@ -1844,8 +1840,8 @@
   // R2: Smi-tagged arguments array length.
   PushArrayOfArguments(assembler);
 
-  const intptr_t kNumArgs = 3;
-  __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs);
+  const intptr_t kNumArgs = 4;
+  __ CallRuntime(kNoSuchMethodFromPrologueRuntimeEntry, kNumArgs);
   // noSuchMethod on closures always throws an error, so it will never return.
   __ brk(0);
 }
@@ -1903,8 +1899,8 @@
                           intptr_t num_args,
                           Label* not_smi_or_overflow) {
   __ Comment("Fast Smi op");
-  __ ldr(R0, Address(SP, +0 * target::kWordSize));  // Right.
-  __ ldr(R1, Address(SP, +1 * target::kWordSize));  // Left.
+  __ ldr(R0, Address(SP, +1 * target::kWordSize));  // Left.
+  __ ldr(R1, Address(SP, +0 * target::kWordSize));  // Right.
   __ orr(TMP, R0, Operand(R1));
   __ BranchIfNotSmi(TMP, not_smi_or_overflow);
   switch (kind) {
@@ -1913,16 +1909,18 @@
       __ b(not_smi_or_overflow, VS);  // Branch if overflow.
       break;
     }
-    case Token::kSUB: {
-      __ subs(R0, R1, Operand(R0));   // Subtract.
-      __ b(not_smi_or_overflow, VS);  // Branch if overflow.
+    case Token::kLT: {
+      __ CompareRegisters(R0, R1);
+      __ LoadObject(R0, CastHandle<Object>(TrueObject()));
+      __ LoadObject(R1, CastHandle<Object>(FalseObject()));
+      __ csel(R0, R0, R1, LT);
       break;
     }
     case Token::kEQ: {
       __ CompareRegisters(R0, R1);
       __ LoadObject(R0, CastHandle<Object>(TrueObject()));
       __ LoadObject(R1, CastHandle<Object>(FalseObject()));
-      __ csel(R0, R1, R0, NE);
+      __ csel(R0, R0, R1, EQ);
       break;
     }
     default:
@@ -1961,8 +1959,9 @@
 }
 
 // Generate inline cache check for 'num_args'.
-//  LR: return address.
-//  R5: inline cache data object.
+//  R0: receiver (if instance call)
+//  R5: ICData
+//  LR: return address
 // Control flow:
 // - If receiver is null -> jump to IC miss.
 // - If receiver is Smi -> load Smi class.
@@ -1975,9 +1974,10 @@
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
     Token::Kind kind,
-    bool optimized,
-    bool exactness_check /* = false */) {
-  ASSERT(!exactness_check);
+    Optimized optimized,
+    CallType type,
+    Exactness exactness) {
+  ASSERT(exactness == kIgnoreExactness);  // Unimplemented.
   ASSERT(num_args == 1 || num_args == 2);
 #if defined(DEBUG)
   {
@@ -1998,7 +1998,7 @@
 
 #if !defined(PRODUCT)
   Label stepping, done_stepping;
-  if (!optimized) {
+  if (optimized == kUnoptimized) {
     __ Comment("Check single stepping");
     __ LoadIsolate(R6);
     __ LoadFromOffset(R6, R6, target::Isolate::single_step_offset(),
@@ -2016,37 +2016,54 @@
   __ Bind(&not_smi_or_overflow);
 
   __ Comment("Extract ICData initial values and receiver cid");
-  // Load arguments descriptor into R4.
-  __ LoadFieldFromOffset(R4, R5, target::ICData::arguments_descriptor_offset());
-  // Loop that checks if there is an IC data match.
-  Label loop, found, miss;
   // R5: IC data object (preserved).
   __ LoadFieldFromOffset(R6, R5, target::ICData::entries_offset());
   // R6: ic_data_array with check entries: classes and target functions.
   __ AddImmediate(R6, target::Array::data_offset() - kHeapObjectTag);
   // R6: points directly to the first ic data array element.
 
-  // Get the receiver's class ID (first read number of arguments from
-  // arguments descriptor array and then access the receiver from the stack).
-  __ LoadFieldFromOffset(R7, R4, target::ArgumentsDescriptor::count_offset());
-  __ SmiUntag(R7);  // Untag so we can use the LSL 3 addressing mode.
-  __ sub(R7, R7, Operand(1));
-
-  // R0 <- [SP + (R7 << 3)]
-  __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled));
-  __ LoadTaggedClassIdMayBeSmi(R0, R0);
-
-  if (num_args == 2) {
-    __ AddImmediate(R1, R7, -1);
-    // R1 <- [SP + (R1 << 3)]
-    __ ldr(R1, Address(SP, R1, UXTX, Address::Scaled));
-    __ LoadTaggedClassIdMayBeSmi(R1, R1);
+  if (type == kInstanceCall) {
+    __ LoadTaggedClassIdMayBeSmi(R0, R0);
+    __ LoadFieldFromOffset(R4, R5,
+                           target::ICData::arguments_descriptor_offset());
+    if (num_args == 2) {
+      __ LoadFieldFromOffset(R7, R4,
+                             target::ArgumentsDescriptor::count_offset());
+      __ SmiUntag(R7);  // Untag so we can use the LSL 3 addressing mode.
+      __ sub(R7, R7, Operand(2));
+      // R1 <- [SP + (R1 << 3)]
+      __ ldr(R1, Address(SP, R7, UXTX, Address::Scaled));
+      __ LoadTaggedClassIdMayBeSmi(R1, R1);
+    }
+  } else {
+    __ LoadFieldFromOffset(R4, R5,
+                           target::ICData::arguments_descriptor_offset());
+    // Get the receiver's class ID (first read number of arguments from
+    // arguments descriptor array and then access the receiver from the stack).
+    __ LoadFieldFromOffset(R7, R4, target::ArgumentsDescriptor::count_offset());
+    __ SmiUntag(R7);  // Untag so we can use the LSL 3 addressing mode.
+    __ sub(R7, R7, Operand(1));
+    // R0 <- [SP + (R7 << 3)]
+    __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled));
+    __ LoadTaggedClassIdMayBeSmi(R0, R0);
+    if (num_args == 2) {
+      __ AddImmediate(R1, R7, -1);
+      // R1 <- [SP + (R1 << 3)]
+      __ ldr(R1, Address(SP, R1, UXTX, Address::Scaled));
+      __ LoadTaggedClassIdMayBeSmi(R1, R1);
+    }
   }
+  // R0: first argument class ID as Smi.
+  // R1: second argument class ID as Smi.
+  // R4: args descriptor
 
   // We unroll the generic one that is generated once more than the others.
   const bool optimize = kind == Token::kILLEGAL;
 
+  // Loop that checks if there is an IC data match.
+  Label loop, found, miss;
   __ Comment("ICData loop");
+
   __ Bind(&loop);
   for (int unroll = optimize ? 4 : 2; unroll >= 0; unroll--) {
     Label update;
@@ -2062,9 +2079,9 @@
 
     __ Bind(&update);
 
-    const intptr_t entry_size =
-        target::ICData::TestEntryLengthFor(num_args, exactness_check) *
-        target::kWordSize;
+    const intptr_t entry_size = target::ICData::TestEntryLengthFor(
+                                    num_args, exactness == kCheckExactness) *
+                                target::kWordSize;
     __ AddImmediate(R6, entry_size);  // Next entry.
 
     __ CompareImmediate(R2, target::ToRawSmi(kIllegalCid));  // Done?
@@ -2077,7 +2094,11 @@
 
   __ Bind(&miss);
   __ Comment("IC miss");
+
   // Compute address of arguments.
+  __ LoadFieldFromOffset(R7, R4, target::ArgumentsDescriptor::count_offset());
+  __ SmiUntag(R7);  // Untag so we can use the LSL 3 addressing mode.
+  __ sub(R7, R7, Operand(1));
   // R7: argument_count - 1 (untagged).
   // R7 <- SP + (R7 << 3)
   __ add(R7, SP, Operand(R7, UXTX, 3));  // R7 is Untagged.
@@ -2142,9 +2163,15 @@
   if (!optimized) {
     __ Bind(&stepping);
     __ EnterStubFrame();
+    if (type == kInstanceCall) {
+      __ Push(R0);  // Preserve receiver.
+    }
     __ Push(R5);  // Preserve IC data.
     __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
     __ Pop(R5);
+    if (type == kInstanceCall) {
+      __ Pop(R0);
+    }
     __ RestoreCodePointer();
     __ LeaveStubFrame();
     __ b(&done_stepping);
@@ -2152,79 +2179,105 @@
 #endif
 }
 
-// Use inline cache data array to invoke the target or continue in inline
-// cache miss handler. Stub for 1-argument check (receiver class).
-//  LR: return address.
-//  R5: inline cache data object.
-// Inline cache data object structure:
-// 0: function-name
-// 1: N, number of arguments checked.
-// 2 .. (length - 1): group of checks, each check containing:
-//   - N classes.
-//   - 1 target function.
+// R0: receiver
+// R5: ICData
+// LR: return address
 void StubCodeCompiler::GenerateOneArgCheckInlineCacheStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R6);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R6);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
+      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+// R0: receiver
+// R5: ICData
+// LR: return address
 void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
     Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
+// R0: receiver
+// R5: ICData
+// LR: return address
 void StubCodeCompiler::GenerateTwoArgsCheckInlineCacheStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R6);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-                                    kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-                                    Token::kILLEGAL);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R6);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+// R0: receiver
+// R5: ICData
+// LR: return address
 void StubCodeCompiler::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R6);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R6);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
-void StubCodeCompiler::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R6);
+// R0: receiver
+// R5: ICData
+// LR: return address
+void StubCodeCompiler::GenerateSmiLessInlineCacheStub(Assembler* assembler) {
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R6);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kLT,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+// R0: receiver
+// R5: ICData
+// LR: return address
 void StubCodeCompiler::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R6);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R6);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+// R0: receiver
+// R5: ICData
+// R6: Function
+// LR: return address
 void StubCodeCompiler::GenerateOneArgOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
-  GenerateNArgsCheckInlineCacheStub(assembler, 1,
-                                    kInlineCacheMissHandlerOneArgRuntimeEntry,
-                                    Token::kILLEGAL, true /* optimized */);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kOptimized, kInstanceCall, kIgnoreExactness);
 }
 
+// R0: receiver
+// R5: ICData
+// R6: Function
+// LR: return address
 void StubCodeCompiler::
     GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
         Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
+// R0: receiver
+// R5: ICData
+// R6: Function
+// LR: return address
 void StubCodeCompiler::GenerateTwoArgsOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-                                    kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-                                    Token::kILLEGAL, true /* optimized */);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kOptimized, kInstanceCall, kIgnoreExactness);
 }
 
+// R5: ICData
+// LR: return address
 void StubCodeCompiler::GenerateZeroArgsUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R6);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R6);
 #if defined(DEBUG)
   {
     Label ok;
@@ -2291,18 +2344,24 @@
 #endif
 }
 
+// R5: ICData
+// LR: return address
 void StubCodeCompiler::GenerateOneArgUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R6);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R6);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
+      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kStaticCall, kIgnoreExactness);
 }
 
+// R5: ICData
+// LR: return address
 void StubCodeCompiler::GenerateTwoArgsUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R6);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ R6);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
+      assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kStaticCall, kIgnoreExactness);
 }
 
 // Stub for compiling a function and jumping to the compiled code.
@@ -2417,14 +2476,16 @@
   __ Stop("No debugging in PRODUCT mode");
 #else
   __ EnterStubFrame();
-  __ Push(R5);
+  __ Push(R0);  // Preserve receiver.
+  __ Push(R5);  // Preserve IC data.
   __ Push(ZR);  // Space for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
-  __ Pop(CODE_REG);
-  __ Pop(R5);
+  __ Pop(CODE_REG);  // Original stub.
+  __ Pop(R5);        // Restore IC data.
+  __ Pop(R0);        // Restore receiver.
   __ LeaveStubFrame();
-  __ LoadFieldFromOffset(R0, CODE_REG, target::Code::entry_point_offset());
-  __ br(R0);
+  __ LoadFieldFromOffset(TMP, CODE_REG, target::Code::entry_point_offset());
+  __ br(TMP);
 #endif  // defined(PRODUCT)
 }
 
@@ -2927,6 +2988,7 @@
 // R6: function to be re-optimized.
 // R4: argument descriptor (preserved).
 void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) {
+  __ LoadFromOffset(CODE_REG, THR, Thread::optimize_stub_offset());
   __ EnterStubFrame();
   __ Push(R4);
   // Setup space on stack for the return value.
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 12259cc..8e59855 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -140,20 +140,61 @@
 
 void StubCodeCompiler::GenerateEnterSafepointStub(Assembler* assembler) {
   __ pushal();
+  __ subl(SPREG, Immediate(8));
+  __ movsd(Address(SPREG, 0), XMM0);
+
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
   __ movl(EAX, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
   __ call(EAX);
+  __ LeaveFrame();
+
+  __ movsd(XMM0, Address(SPREG, 0));
+  __ addl(SPREG, Immediate(8));
   __ popal();
   __ ret();
 }
 
 void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
   __ pushal();
+  __ subl(SPREG, Immediate(8));
+  __ movsd(Address(SPREG, 0), XMM0);
+
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
   __ movl(EAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
   __ call(EAX);
+  __ LeaveFrame();
+
+  __ movsd(XMM0, Address(SPREG, 0));
+  __ addl(SPREG, Immediate(8));
   __ popal();
   __ ret();
 }
 
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
+
+  // The return address needs to be the second argument to
+  // VerifyCallbackIsolate.
+  __ movl(EAX, Address(FPREG, 4));
+  __ pushl(EAX);
+
+  // Argument to the stub is callback ID, which is also the first argument to
+  // VerifyCallbackIsolate.
+  __ movl(EAX, Address(FPREG, 8));
+  __ pushl(EAX);
+
+  // Call the VerifyCallbackIsolate runtime entry.
+  __ movl(EAX,
+          Address(THR, kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread()));
+  __ call(EAX);
+
+  __ LeaveFrame();
+  __ ret();
+}
+
 void StubCodeCompiler::GenerateNullErrorSharedWithoutFPURegsStub(
     Assembler* assembler) {
   __ Breakpoint();
@@ -359,8 +400,7 @@
   // Remove the stub frame as we are about to jump to the dart function.
   __ LeaveFrame();
 
-  __ movl(ECX, FieldAddress(EAX, target::Code::entry_point_offset()));
-  __ jmp(ECX);
+  __ jmp(FieldAddress(EAX, target::Code::entry_point_offset()));
 }
 
 // Called from a static call only when an invalid code has been entered
@@ -627,7 +667,7 @@
   // EDX: Smi-tagged arguments array length.
   PushArrayOfArguments(assembler);
   const intptr_t kNumArgs = 4;
-  __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
+  __ CallRuntime(kNoSuchMethodFromCallStubRuntimeEntry, kNumArgs);
   __ Drop(4);
   __ popl(EAX);  // Return value.
   __ LeaveFrame();
@@ -666,8 +706,7 @@
     __ Bind(&call_target_function);
   }
 
-  __ movl(EBX, FieldAddress(EAX, target::Function::entry_point_offset()));
-  __ jmp(EBX);
+  __ jmp(FieldAddress(EAX, target::Function::entry_point_offset()));
 }
 
 // Called for inline allocation of arrays.
@@ -860,6 +899,10 @@
   __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
           Immediate(0));
 
+  // In debug mode, verify that we've pushed the top exit frame info at the
+  // correct offset from FP.
+  __ EmitEntryFrameVerification();
+
   // Mark that the thread is executing Dart code. Do this after initializing the
   // exit link for the profiler.
   __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
@@ -1341,7 +1384,7 @@
   // when the object initialization should be done as a loop or as
   // straight line code.
   const int kInlineInstanceSize = 12;  // In words.
-  const intptr_t instance_size = target::Class::InstanceSize(cls);
+  const intptr_t instance_size = target::Class::GetInstanceSize(cls);
   ASSERT(instance_size > 0);
   if (is_cls_parameterized) {
     __ movl(EDX, Address(ESP, kObjectTypeArgumentsOffset));
@@ -1471,8 +1514,12 @@
           Address(EBP, EDI, TIMES_2,
                   target::frame_layout.param_end_from_fp * target::kWordSize));
 
+  // Load the function.
+  __ movl(EBX, FieldAddress(EAX, target::Closure::function_offset()));
+
   __ pushl(Immediate(0));  // Setup space on stack for result from noSuchMethod.
   __ pushl(EAX);           // Receiver.
+  __ pushl(EBX);           // Function.
   __ pushl(EDX);           // Arguments descriptor array.
 
   // Adjust arguments count.
@@ -1488,8 +1535,8 @@
   // EDX: Smi-tagged arguments array length.
   PushArrayOfArguments(assembler);
 
-  const intptr_t kNumArgs = 3;
-  __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs);
+  const intptr_t kNumArgs = 4;
+  __ CallRuntime(kNoSuchMethodFromPrologueRuntimeEntry, kNumArgs);
   // noSuchMethod on closures always throws an error, so it will never return.
   __ int3();
 }
@@ -1499,7 +1546,7 @@
 void StubCodeCompiler::GenerateOptimizedUsageCounterIncrement(
     Assembler* assembler) {
   Register ic_reg = ECX;
-  Register func_reg = EBX;
+  Register func_reg = EAX;
   if (FLAG_trace_optimized_ic_calls) {
     __ EnterStubFrame();
     __ pushl(func_reg);  // Preserve
@@ -1539,8 +1586,8 @@
                           Label* not_smi_or_overflow) {
   __ Comment("Fast Smi op");
   ASSERT(num_args == 2);
-  __ movl(EDI, Address(ESP, +1 * target::kWordSize));  // Right
   __ movl(EAX, Address(ESP, +2 * target::kWordSize));  // Left
+  __ movl(EDI, Address(ESP, +1 * target::kWordSize));  // Right
   __ movl(EBX, EDI);
   __ orl(EBX, EAX);
   __ testl(EBX, Immediate(kSmiTagMask));
@@ -1551,26 +1598,26 @@
       __ j(OVERFLOW, not_smi_or_overflow, Assembler::kNearJump);
       break;
     }
-    case Token::kSUB: {
-      __ subl(EAX, EDI);
-      __ j(OVERFLOW, not_smi_or_overflow, Assembler::kNearJump);
-      break;
-    }
-    case Token::kMUL: {
-      __ SmiUntag(EAX);
-      __ imull(EAX, EDI);
-      __ j(OVERFLOW, not_smi_or_overflow, Assembler::kNearJump);
+    case Token::kLT: {
+      Label done, is_true;
+      __ cmpl(EAX, EDI);
+      __ setcc(GREATER_EQUAL, AL);
+      __ movzxb(EAX, AL);  // EAX := EAX < EDI ? 0 : 1
+      __ movl(EAX,
+              Address(THR, EAX, TIMES_4, target::Thread::bool_true_offset()));
+      ASSERT(target::Thread::bool_true_offset() + 4 ==
+             target::Thread::bool_false_offset());
       break;
     }
     case Token::kEQ: {
       Label done, is_true;
       __ cmpl(EAX, EDI);
-      __ j(EQUAL, &is_true, Assembler::kNearJump);
-      __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
-      __ jmp(&done, Assembler::kNearJump);
-      __ Bind(&is_true);
-      __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
-      __ Bind(&done);
+      __ setcc(NOT_EQUAL, AL);
+      __ movzxb(EAX, AL);  // EAX := EAX == EDI ? 0 : 1
+      __ movl(EAX,
+              Address(THR, EAX, TIMES_4, target::Thread::bool_true_offset()));
+      ASSERT(target::Thread::bool_true_offset() + 4 ==
+             target::Thread::bool_false_offset());
       break;
     }
     default:
@@ -1603,8 +1650,9 @@
 }
 
 // Generate inline cache check for 'num_args'.
-//  ECX: Inline cache data object.
-//  TOS(0): return address
+//  EBX: receiver (if instance call)
+//  ECX: ICData
+//  ESP[0]: return address
 // Control flow:
 // - If receiver is null -> jump to IC miss.
 // - If receiver is Smi -> load Smi class.
@@ -1617,19 +1665,20 @@
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
     Token::Kind kind,
-    bool optimized,
-    bool exactness_check /* = false */) {
-  ASSERT(!exactness_check);  // Not supported.
+    Optimized optimized,
+    CallType type,
+    Exactness exactness) {
+  ASSERT(exactness == kIgnoreExactness);  // Unimplemented.
   ASSERT(num_args == 1 || num_args == 2);
 #if defined(DEBUG)
   {
     Label ok;
     // Check that the IC data array has NumArgsTested() == num_args.
     // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
-    __ movl(EBX, FieldAddress(ECX, target::ICData::state_bits_offset()));
+    __ movl(EAX, FieldAddress(ECX, target::ICData::state_bits_offset()));
     ASSERT(target::ICData::NumArgsTestedShift() == 0);  // No shift needed.
-    __ andl(EBX, Immediate(target::ICData::NumArgsTestedMask()));
-    __ cmpl(EBX, Immediate(num_args));
+    __ andl(EAX, Immediate(target::ICData::NumArgsTestedMask()));
+    __ cmpl(EAX, Immediate(num_args));
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Incorrect stub for IC data");
     __ Bind(&ok);
@@ -1638,7 +1687,7 @@
 
 #if !defined(PRODUCT)
   Label stepping, done_stepping;
-  if (!optimized) {
+  if (optimized == kUnoptimized) {
     __ Comment("Check single stepping");
     __ LoadIsolate(EAX);
     __ cmpb(Address(EAX, target::Isolate::single_step_offset()), Immediate(0));
@@ -1686,9 +1735,9 @@
       target::ICData::TargetIndexFor(num_args) * target::kWordSize;
   const intptr_t count_offset =
       target::ICData::CountIndexFor(num_args) * target::kWordSize;
-  const intptr_t entry_size =
-      target::ICData::TestEntryLengthFor(num_args, exactness_check) *
-      target::kWordSize;
+  const intptr_t entry_size = target::ICData::TestEntryLengthFor(
+                                  num_args, exactness == kCheckExactness) *
+                              target::kWordSize;
 
   __ Bind(&loop);
   for (int unroll = optimize ? 4 : 2; unroll >= 0; unroll--) {
@@ -1773,109 +1822,122 @@
   __ Bind(&call_target_function);
   __ Comment("Call target");
   // EAX: Target function.
-  __ movl(EBX, FieldAddress(EAX, target::Function::entry_point_offset()));
-  __ jmp(EBX);
+  __ jmp(FieldAddress(EAX, target::Function::entry_point_offset()));
 
 #if !defined(PRODUCT)
-  if (!optimized) {
+  if (optimized == kUnoptimized) {
     __ Bind(&stepping);
     __ EnterStubFrame();
-    __ pushl(ECX);
+    __ pushl(EBX);  // Preserve receiver.
+    __ pushl(ECX);  // Preserve ICData.
     __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
-    __ popl(ECX);
+    __ popl(ECX);  // Restore ICData.
+    __ popl(EBX);  // Restore receiver.
     __ LeaveFrame();
     __ jmp(&done_stepping);
   }
 #endif
 }
 
-// Use inline cache data array to invoke the target or continue in inline
-// cache miss handler. Stub for 1-argument check (receiver class).
-//  ECX: Inline cache data object.
-//  TOS(0): Return address.
-// Inline cache data object structure:
-// 0: function-name
-// 1: N, number of arguments checked.
-// 2 .. (length - 1): group of checks, each check containing:
-//   - N classes.
-//   - 1 target function.
+// EBX: receiver
+// ECX: ICData
+// ESP[0]: return address
 void StubCodeCompiler::GenerateOneArgCheckInlineCacheStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, EBX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ EAX);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
+      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+// EBX: receiver
+// ECX: ICData
+// ESP[0]: return address
 void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
     Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
+// EBX: receiver
+// ECX: ICData
+// ESP[0]: return address
 void StubCodeCompiler::GenerateTwoArgsCheckInlineCacheStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, EBX);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-                                    kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-                                    Token::kILLEGAL);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ EAX);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+// EBX: receiver
+// ECX: ICData
+// ESP[0]: return address
 void StubCodeCompiler::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, EBX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ EAX);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
-void StubCodeCompiler::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, EBX);
+// EBX: receiver
+// ECX: ICData
+// ESP[0]: return address
+void StubCodeCompiler::GenerateSmiLessInlineCacheStub(Assembler* assembler) {
+  GenerateUsageCounterIncrement(assembler, /* scratch */ EAX);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kLT,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+// EBX: receiver
+// ECX: ICData
+// ESP[0]: return address
 void StubCodeCompiler::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, EBX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ EAX);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
-// Use inline cache data array to invoke the target or continue in inline
-// cache miss handler. Stub for 1-argument check (receiver class).
-//  EDI: function which counter needs to be incremented.
-//  ECX: Inline cache data object.
-//  TOS(0): Return address.
-// Inline cache data object structure:
-// 0: function-name
-// 1: N, number of arguments checked.
-// 2 .. (length - 1): group of checks, each check containing:
-//   - N classes.
-//   - 1 target function.
+// EBX: receiver
+// ECX: ICData
+// EAX: Function
+// ESP[0]: return address
 void StubCodeCompiler::GenerateOneArgOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
-  GenerateNArgsCheckInlineCacheStub(assembler, 1,
-                                    kInlineCacheMissHandlerOneArgRuntimeEntry,
-                                    Token::kILLEGAL, true /* optimized */);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kOptimized, kInstanceCall, kIgnoreExactness);
 }
 
+// EBX: receiver
+// ECX: ICData
+// EAX: Function
+// ESP[0]: return address
 void StubCodeCompiler::
     GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
         Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
+// EBX: receiver
+// ECX: ICData
+// EAX: Function
+// ESP[0]: return address
 void StubCodeCompiler::GenerateTwoArgsOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-                                    kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-                                    Token::kILLEGAL, true /* optimized */);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kOptimized, kInstanceCall, kIgnoreExactness);
 }
 
-// Intermediary stub between a static call and its target. ICData contains
-// the target function and the call count.
 // ECX: ICData
+// ESP[0]: return address
 void StubCodeCompiler::GenerateZeroArgsUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, EBX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ EAX);
 
 #if defined(DEBUG)
   {
@@ -1922,8 +1984,7 @@
 
   // Get function and call it, if possible.
   __ movl(EAX, Address(EBX, target_offset));
-  __ movl(EBX, FieldAddress(EAX, target::Function::entry_point_offset()));
-  __ jmp(EBX);
+  __ jmp(FieldAddress(EAX, target::Function::entry_point_offset()));
 
 #if !defined(PRODUCT)
   __ Bind(&stepping);
@@ -1936,18 +1997,24 @@
 #endif
 }
 
+// ECX: ICData
+// ESP[0]: return address
 void StubCodeCompiler::GenerateOneArgUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, EBX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ EAX);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
+      assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kStaticCall, kIgnoreExactness);
 }
 
+// ECX: ICData
+// ESP[0]: return address
 void StubCodeCompiler::GenerateTwoArgsUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, EBX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ EAX);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
+      assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kStaticCall, kIgnoreExactness);
 }
 
 // Stub for compiling a function and jumping to the compiled code.
@@ -1964,8 +2031,7 @@
 
   // When using the interpreter, the function's code may now point to the
   // InterpretCall stub. Make sure EAX, ECX, and EDX are preserved.
-  __ movl(EBX, FieldAddress(EAX, target::Function::entry_point_offset()));
-  __ jmp(EBX);
+  __ jmp(FieldAddress(EAX, target::Function::entry_point_offset()));
 }
 
 // Stub for interpreting a function call.
@@ -2040,18 +2106,16 @@
   __ Stop("No debugging in PRODUCT mode");
 #else
   __ EnterStubFrame();
-  // Save IC data.
-  __ pushl(ECX);
-  // Room for result. Debugger stub returns address of the
-  // unpatched runtime stub.
+  __ pushl(EBX);           // Preserve receiver.
+  __ pushl(ECX);           // Preserve ICData.
   __ pushl(Immediate(0));  // Room for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ popl(EAX);  // Code of original stub.
-  __ popl(ECX);  // Restore IC data.
+  __ popl(ECX);  // Restore ICData.
+  __ popl(EBX);  // Restore receiver.
   __ LeaveFrame();
   // Jump to original stub.
-  __ movl(EAX, FieldAddress(EAX, target::Code::entry_point_offset()));
-  __ jmp(EAX);
+  __ jmp(FieldAddress(EAX, target::Code::entry_point_offset()));
 #endif  // defined(PRODUCT)
 }
 
@@ -2067,8 +2131,7 @@
   __ popl(EAX);  // Code of the original stub
   __ LeaveFrame();
   // Jump to original stub.
-  __ movl(EAX, FieldAddress(EAX, target::Code::entry_point_offset()));
-  __ jmp(EAX);
+  __ jmp(FieldAddress(EAX, target::Code::entry_point_offset()));
 #endif  // defined(PRODUCT)
 }
 
@@ -2386,6 +2449,7 @@
 // EBX: function to be reoptimized.
 // EDX: argument descriptor (preserved).
 void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) {
+  __ movl(CODE_REG, Address(THR, Thread::optimize_stub_offset()));
   __ EnterStubFrame();
   __ pushl(EDX);
   __ pushl(Immediate(0));  // Setup space on stack for return value.
@@ -2396,8 +2460,7 @@
   __ popl(EDX);  // Restore argument descriptor.
   __ LeaveFrame();
   __ movl(CODE_REG, FieldAddress(EAX, target::Function::code_offset()));
-  __ movl(EAX, FieldAddress(EAX, target::Function::entry_point_offset()));
-  __ jmp(EAX);
+  __ jmp(FieldAddress(EAX, target::Function::entry_point_offset()));
   __ int3();
 }
 
@@ -2558,8 +2621,7 @@
   __ movl(EDX,
           FieldAddress(
               ECX, target::MegamorphicCache::arguments_descriptor_offset()));
-  __ movl(EBX, FieldAddress(EAX, target::Function::entry_point_offset()));
-  __ ret();
+  __ jmp(FieldAddress(EAX, target::Function::entry_point_offset()));
 
   __ Bind(&probe_failed);
   // Probe failed, check if it is a miss.
@@ -2583,32 +2645,32 @@
 // Passed to target:
 //  EDX: arguments descriptor
 void StubCodeCompiler::GenerateICCallThroughFunctionStub(Assembler* assembler) {
-  __ int3();
+  __ int3();  // AOT only.
 }
 
 void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
-  __ int3();
+  __ int3();  // AOT only.
 }
 
 void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
-  __ int3();
+  __ int3();  // AOT only.
 }
 
 void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
-  __ int3();
+  __ int3();  // AOT only.
 }
 
 void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
-  __ int3();
+  __ int3();  // AOT only.
 }
 
 void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub(
     Assembler* assembler) {
-  __ int3();
+  __ int3();  // Marker stub.
 }
 
 void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
-  __ int3();
+  __ int3();  // Marker stub.
 }
 
 }  // namespace compiler
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 0df3f7a..77e894f 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -204,8 +204,13 @@
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers.cpu_registers(),
                    all_registers.fpu_registers());
+
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
   __ movq(RAX, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
   __ CallCFunction(RAX);
+  __ LeaveFrame();
+
   __ PopRegisters(all_registers.cpu_registers(), all_registers.fpu_registers());
   __ ret();
 }
@@ -215,12 +220,31 @@
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers.cpu_registers(),
                    all_registers.fpu_registers());
+
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
   __ movq(RAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
   __ CallCFunction(RAX);
+  __ LeaveFrame();
+
   __ PopRegisters(all_registers.cpu_registers(), all_registers.fpu_registers());
   __ ret();
 }
 
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+  // SP points to return address, which needs to be the second argument to
+  // VerifyCallbackIsolate.
+  __ movq(CallingConventions::kArg2Reg, Address(SPREG, 0));
+
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
+  __ movq(RAX,
+          Address(THR, kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread()));
+  __ CallCFunction(RAX);
+  __ LeaveFrame();
+  __ ret();
+}
+
 // RBX: The extracted method.
 // RDX: The type_arguments_field_offset (or 0)
 void StubCodeCompiler::GenerateBuildMethodExtractorStub(
@@ -847,7 +871,7 @@
   // R10: Smi-tagged arguments array length.
   PushArrayOfArguments(assembler);
   const intptr_t kNumArgs = 4;
-  __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
+  __ CallRuntime(kNoSuchMethodFromCallStubRuntimeEntry, kNumArgs);
   __ Drop(4);
   __ popq(RAX);  // Return value.
   __ LeaveStubFrame();
@@ -870,7 +894,7 @@
 
   // Space for the result of the runtime call.
   __ pushq(Immediate(0));
-  __ pushq(RAX);  // Receiver.
+  __ pushq(RDX);  // Receiver.
   __ pushq(RBX);  // IC data.
   __ pushq(R10);  // Arguments descriptor.
   __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
@@ -1086,19 +1110,8 @@
   __ pushq(RAX);
 
   // The constant target::frame_layout.exit_link_slot_from_entry_fp must be kept
-  // in sync with the code below.
-#if defined(DEBUG)
-  {
-    Label ok;
-    __ leaq(RAX,
-            Address(RBP, target::frame_layout.exit_link_slot_from_entry_fp *
-                             target::kWordSize));
-    __ cmpq(RAX, RSP);
-    __ j(EQUAL, &ok);
-    __ Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
-    __ Bind(&ok);
-  }
-#endif
+  // in sync with the code above.
+  __ EmitEntryFrameVerification();
 
   __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
           Immediate(0));
@@ -1669,7 +1682,7 @@
   // when the object initialization should be done as a loop or as
   // straight line code.
   const int kInlineInstanceSize = 12;  // In words.
-  const intptr_t instance_size = target::Class::InstanceSize(cls);
+  const intptr_t instance_size = target::Class::GetInstanceSize(cls);
   ASSERT(instance_size > 0);
   __ LoadObject(R9, NullObject());
   if (is_cls_parameterized) {
@@ -1762,7 +1775,7 @@
   // Create a stub frame.
   __ EnterStubFrame();  // Uses PP to access class object.
 
-  __ pushq(R9);         // Setup space on stack for return value.
+  __ pushq(R9);  // Setup space on stack for return value.
   __ PushObject(
       CastHandle<Object>(cls));  // Push class of object to be allocated.
   if (is_cls_parameterized) {
@@ -1804,8 +1817,12 @@
           Address(RBP, R13, TIMES_4,
                   target::frame_layout.param_end_from_fp * target::kWordSize));
 
+  // Load the function.
+  __ movq(RBX, FieldAddress(RAX, target::Closure::function_offset()));
+
   __ pushq(Immediate(0));  // Result slot.
   __ pushq(RAX);           // Receiver.
+  __ pushq(RBX);           // Function.
   __ pushq(R10);           // Arguments descriptor array.
 
   // Adjust arguments count.
@@ -1821,8 +1838,8 @@
   // R10: Smi-tagged arguments array length.
   PushArrayOfArguments(assembler);
 
-  const intptr_t kNumArgs = 3;
-  __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs);
+  const intptr_t kNumArgs = 4;
+  __ CallRuntime(kNoSuchMethodFromPrologueRuntimeEntry, kNumArgs);
   // noSuchMethod on closures always throws an error, so it will never return.
   __ int3();
 }
@@ -1872,8 +1889,8 @@
                           Label* not_smi_or_overflow) {
   __ Comment("Fast Smi op");
   ASSERT(num_args == 2);
-  __ movq(RCX, Address(RSP, +1 * target::kWordSize));  // Right
   __ movq(RAX, Address(RSP, +2 * target::kWordSize));  // Left.
+  __ movq(RCX, Address(RSP, +1 * target::kWordSize));  // Right
   __ movq(R13, RCX);
   __ orq(R13, RAX);
   __ testq(R13, Immediate(kSmiTagMask));
@@ -1884,20 +1901,24 @@
       __ j(OVERFLOW, not_smi_or_overflow);
       break;
     }
-    case Token::kSUB: {
-      __ subq(RAX, RCX);
-      __ j(OVERFLOW, not_smi_or_overflow);
+    case Token::kLT: {
+      __ cmpq(RAX, RCX);
+      __ setcc(GREATER_EQUAL, ByteRegisterOf(RAX));
+      __ movzxb(RAX, RAX);  // RAX := RAX < RCX ? 0 : 1
+      __ movq(RAX,
+              Address(THR, RAX, TIMES_8, target::Thread::bool_true_offset()));
+      ASSERT(target::Thread::bool_true_offset() + 8 ==
+             target::Thread::bool_false_offset());
       break;
     }
     case Token::kEQ: {
-      Label done, is_true;
       __ cmpq(RAX, RCX);
-      __ j(EQUAL, &is_true, Assembler::kNearJump);
-      __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
-      __ jmp(&done, Assembler::kNearJump);
-      __ Bind(&is_true);
-      __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
-      __ Bind(&done);
+      __ setcc(NOT_EQUAL, ByteRegisterOf(RAX));
+      __ movzxb(RAX, RAX);  // RAX := RAX == RCX ? 0 : 1
+      __ movq(RAX,
+              Address(THR, RAX, TIMES_8, target::Thread::bool_true_offset()));
+      ASSERT(target::Thread::bool_true_offset() + 8 ==
+             target::Thread::bool_false_offset());
       break;
     }
     default:
@@ -1933,8 +1954,9 @@
 }
 
 // Generate inline cache check for 'num_args'.
-//  RBX: Inline cache data object.
-//  TOS(0): return address
+//  RDX: receiver (if instance call)
+//  RBX: ICData
+//  RSP[0]: return address
 // Control flow:
 // - If receiver is null -> jump to IC miss.
 // - If receiver is Smi -> load Smi class.
@@ -1947,8 +1969,9 @@
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
     Token::Kind kind,
-    bool optimized,
-    bool exactness_check) {
+    Optimized optimized,
+    CallType type,
+    Exactness exactness) {
   ASSERT(num_args == 1 || num_args == 2);
 #if defined(DEBUG)
   {
@@ -1967,7 +1990,7 @@
 
 #if !defined(PRODUCT)
   Label stepping, done_stepping;
-  if (!optimized) {
+  if (optimized == kUnoptimized) {
     __ Comment("Check single stepping");
     __ LoadIsolate(RAX);
     __ cmpb(Address(RAX, target::Isolate::single_step_offset()), Immediate(0));
@@ -1983,30 +2006,40 @@
   __ Bind(&not_smi_or_overflow);
 
   __ Comment("Extract ICData initial values and receiver cid");
-  // Load arguments descriptor into R10.
-  __ movq(R10,
-          FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
-  // Loop that checks if there is an IC data match.
-  Label loop, found, miss;
   // RBX: IC data object (preserved).
   __ movq(R13, FieldAddress(RBX, target::ICData::entries_offset()));
   // R13: ic_data_array with check entries: classes and target functions.
   __ leaq(R13, FieldAddress(R13, target::Array::data_offset()));
   // R13: points directly to the first ic data array element.
 
-  // Get argument count as Smi into RCX.
-  __ movq(RCX, FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
-  // Load first argument into RDX.
-  __ movq(RDX, Address(RSP, RCX, TIMES_4, 0));
-  __ LoadTaggedClassIdMayBeSmi(RAX, RDX);
-  // RAX: first argument class ID as Smi.
-  if (num_args == 2) {
-    // Load second argument into R9.
-    __ movq(R9, Address(RSP, RCX, TIMES_4, -target::kWordSize));
-    __ LoadTaggedClassIdMayBeSmi(RCX, R9);
-    // RCX: second argument class ID (smi).
+  if (type == kInstanceCall) {
+    __ LoadTaggedClassIdMayBeSmi(RAX, RDX);
+    __ movq(R10,
+            FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
+    if (num_args == 2) {
+      __ movq(RCX,
+              FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
+      __ movq(R9, Address(RSP, RCX, TIMES_4, -target::kWordSize));
+      __ LoadTaggedClassIdMayBeSmi(RCX, R9);
+    }
+  } else {
+    __ movq(R10,
+            FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
+    __ movq(RCX,
+            FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
+    __ movq(RDX, Address(RSP, RCX, TIMES_4, 0));
+    __ LoadTaggedClassIdMayBeSmi(RAX, RDX);
+    if (num_args == 2) {
+      __ movq(R9, Address(RSP, RCX, TIMES_4, -target::kWordSize));
+      __ LoadTaggedClassIdMayBeSmi(RCX, R9);
+    }
   }
+  // RAX: first argument class ID as Smi.
+  // RCX: second argument class ID as Smi.
+  // R10: args descriptor
 
+  // Loop that checks if there is an IC data match.
+  Label loop, found, miss;
   __ Comment("ICData loop");
 
   // We unroll the generic one that is generated once more than the others.
@@ -2016,7 +2049,7 @@
   const intptr_t count_offset =
       target::ICData::CountIndexFor(num_args) * target::kWordSize;
   const intptr_t exactness_offset =
-      target::ICData::ExactnessOffsetFor(num_args) * target::kWordSize;
+      target::ICData::ExactnessIndexFor(num_args) * target::kWordSize;
 
   __ Bind(&loop);
   for (int unroll = optimize ? 4 : 2; unroll >= 0; unroll--) {
@@ -2033,9 +2066,9 @@
 
     __ Bind(&update);
 
-    const intptr_t entry_size =
-        target::ICData::TestEntryLengthFor(num_args, exactness_check) *
-        target::kWordSize;
+    const intptr_t entry_size = target::ICData::TestEntryLengthFor(
+                                    num_args, exactness == kCheckExactness) *
+                                target::kWordSize;
     __ addq(R13, Immediate(entry_size));  // Next entry.
 
     __ cmpq(R9, Immediate(target::ToRawSmi(kIllegalCid)));  // Done?
@@ -2082,7 +2115,7 @@
   __ Bind(&found);
   // R13: Pointer to an IC data check group.
   Label call_target_function_through_unchecked_entry;
-  if (exactness_check) {
+  if (exactness == kCheckExactness) {
     Label exactness_ok;
     ASSERT(num_args == 1);
     __ movq(RAX, Address(R13, exactness_offset));
@@ -2121,10 +2154,9 @@
   __ Bind(&call_target_function);
   // RAX: Target function.
   __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
-  __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
-  __ jmp(RCX);
+  __ jmp(FieldAddress(RAX, target::Function::entry_point_offset()));
 
-  if (exactness_check) {
+  if (exactness == kCheckExactness) {
     __ Bind(&call_target_function_through_unchecked_entry);
     if (FLAG_optimization_counter_threshold >= 0) {
       __ Comment("Update ICData counter");
@@ -2134,18 +2166,22 @@
     __ Comment("Call target (via unchecked entry point)");
     __ movq(RAX, Address(R13, target_offset));
     __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
-    __ movq(RCX, FieldAddress(
-                     RAX, target::Function::unchecked_entry_point_offset()));
-    __ jmp(RCX);
+    __ jmp(FieldAddress(RAX, target::Function::unchecked_entry_point_offset()));
   }
 
 #if !defined(PRODUCT)
-  if (!optimized) {
+  if (optimized == kUnoptimized) {
     __ Bind(&stepping);
     __ EnterStubFrame();
-    __ pushq(RBX);
+    if (type == kInstanceCall) {
+      __ pushq(RDX);  // Preserve receiver.
+    }
+    __ pushq(RBX);  // Preserve ICData.
     __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
-    __ popq(RBX);
+    __ popq(RBX);  // Restore ICData.
+    if (type == kInstanceCall) {
+      __ popq(RDX);  // Restore receiver.
+    }
     __ RestoreCodePointer();
     __ LeaveStubFrame();
     __ jmp(&done_stepping);
@@ -2153,100 +2189,111 @@
 #endif
 }
 
-// Use inline cache data array to invoke the target or continue in inline
-// cache miss handler. Stub for 1-argument check (receiver class).
-//  RBX: Inline cache data object.
-//  TOS(0): Return address.
-// Inline cache data object structure:
-// 0: function-name
-// 1: N, number of arguments checked.
-// 2 .. (length - 1): group of checks, each check containing:
-//   - N classes.
-//   - 1 target function.
+//  RDX: receiver
+//  RBX: ICData
+//  RSP[0]: return address
 void StubCodeCompiler::GenerateOneArgCheckInlineCacheStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, RCX);
-  GenerateNArgsCheckInlineCacheStub(
-      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
-}
-
-void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
-    Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, RCX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ RCX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
-      /*optimized=*/false, /*exactness_check=*/true);
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+//  RDX: receiver
+//  RBX: ICData
+//  RSP[0]: return address
+void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
+    Assembler* assembler) {
+  GenerateUsageCounterIncrement(assembler, /* scratch */ RCX);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kInstanceCall, kCheckExactness);
+}
+
+//  RDX: receiver
+//  RBX: ICData
+//  RSP[0]: return address
 void StubCodeCompiler::GenerateTwoArgsCheckInlineCacheStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, RCX);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-                                    kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-                                    Token::kILLEGAL);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ RCX);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+//  RDX: receiver
+//  RBX: ICData
+//  RSP[0]: return address
 void StubCodeCompiler::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, RCX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ RCX);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
-void StubCodeCompiler::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, RCX);
+//  RDX: receiver
+//  RBX: ICData
+//  RSP[0]: return address
+void StubCodeCompiler::GenerateSmiLessInlineCacheStub(Assembler* assembler) {
+  GenerateUsageCounterIncrement(assembler, /* scratch */ RCX);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kLT,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
+//  RDX: receiver
+//  RBX: ICData
+//  RSP[0]: return address
 void StubCodeCompiler::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, RCX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ RCX);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
 }
 
-// Use inline cache data array to invoke the target or continue in inline
-// cache miss handler. Stub for 1-argument check (receiver class).
-//  RDI: function which counter needs to be incremented.
-//  RBX: Inline cache data object.
-//  TOS(0): Return address.
-// Inline cache data object structure:
-// 0: function-name
-// 1: N, number of arguments checked.
-// 2 .. (length - 1): group of checks, each check containing:
-//   - N classes.
-//   - 1 target function.
+//  RDX: receiver
+//  RBX: ICData
+//  RDI: Function
+//  RSP[0]: return address
 void StubCodeCompiler::GenerateOneArgOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
-  GenerateNArgsCheckInlineCacheStub(assembler, 1,
-                                    kInlineCacheMissHandlerOneArgRuntimeEntry,
-                                    Token::kILLEGAL, /*optimized=*/true);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kOptimized, kInstanceCall, kIgnoreExactness);
 }
 
+//  RDX: receiver
+//  RBX: ICData
+//  RDI: Function
+//  RSP[0]: return address
 void StubCodeCompiler::
     GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
         Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
-  GenerateNArgsCheckInlineCacheStub(assembler, 1,
-                                    kInlineCacheMissHandlerOneArgRuntimeEntry,
-                                    Token::kILLEGAL, /*optimized=*/true,
-                                    /*exactness_check=*/true);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kOptimized, kInstanceCall, kCheckExactness);
 }
 
+//  RDX: receiver
+//  RBX: ICData
+//  RDI: Function
+//  RSP[0]: return address
 void StubCodeCompiler::GenerateTwoArgsOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-                                    kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-                                    Token::kILLEGAL, /*optimized=*/true);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kOptimized, kInstanceCall, kIgnoreExactness);
 }
 
-// Intermediary stub between a static call and its target. ICData contains
-// the target function and the call count.
-// RBX: ICData
+//  RBX: ICData
+//  RSP[0]: return address
 void StubCodeCompiler::GenerateZeroArgsUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, RCX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ RCX);
 #if defined(DEBUG)
   {
     Label ok;
@@ -2314,18 +2361,24 @@
 #endif
 }
 
+//  RBX: ICData
+//  RSP[0]: return address
 void StubCodeCompiler::GenerateOneArgUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, RCX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ RCX);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
+      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kStaticCall, kIgnoreExactness);
 }
 
+//  RBX: ICData
+//  RSP[0]: return address
 void StubCodeCompiler::GenerateTwoArgsUnoptimizedStaticCallStub(
     Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, RCX);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ RCX);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
+      assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kStaticCall, kIgnoreExactness);
 }
 
 // Stub for compiling a function and jumping to the compiled code.
@@ -2433,11 +2486,13 @@
   __ Stop("No debugging in PRODUCT mode");
 #else
   __ EnterStubFrame();
+  __ pushq(RDX);           // Preserve receiver.
   __ pushq(RBX);           // Preserve IC data.
   __ pushq(Immediate(0));  // Result slot.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ popq(CODE_REG);  // Original stub.
   __ popq(RBX);       // Restore IC data.
+  __ popq(RDX);       // Restore receiver.
   __ LeaveStubFrame();
 
   __ movq(RAX, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
@@ -2946,6 +3001,7 @@
 // RDI: function to be reoptimized.
 // R10: argument descriptor (preserved).
 void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) {
+  __ movq(CODE_REG, Address(THR, Thread::optimize_stub_offset()));
   __ EnterStubFrame();
   __ pushq(R10);           // Preserve args descriptor.
   __ pushq(Immediate(0));  // Result slot.
@@ -3053,7 +3109,7 @@
 }
 
 // Called from megamorphic calls.
-//  RDI: receiver
+//  RDX: receiver
 //  RBX: target::MegamorphicCache (preserved)
 // Passed to target:
 //  CODE_REG: target Code
@@ -3061,12 +3117,12 @@
 void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
   // Jump if receiver is a smi.
   Label smi_case;
-  __ testq(RDI, Immediate(kSmiTagMask));
+  __ testq(RDX, Immediate(kSmiTagMask));
   // Jump out of line for smi case.
   __ j(ZERO, &smi_case, Assembler::kNearJump);
 
   // Loads the cid of the object.
-  __ LoadClassId(RAX, RDI);
+  __ LoadClassId(RAX, RDX);
 
   Label cid_loaded;
   __ Bind(&cid_loaded);
@@ -3134,7 +3190,7 @@
 }
 
 // Called from switchable IC calls.
-//  RDI: receiver
+//  RDX: receiver
 //  RBX: ICData (preserved)
 // Passed to target:
 //  CODE_REG: target Code object
@@ -3146,7 +3202,7 @@
           FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
   __ leaq(R13, FieldAddress(R13, target::Array::data_offset()));
   // R13: first IC entry
-  __ LoadTaggedClassIdMayBeSmi(RAX, RDI);
+  __ LoadTaggedClassIdMayBeSmi(RAX, RDX);
   // RAX: receiver cid as Smi
 
   __ Bind(&loop);
@@ -3186,7 +3242,7 @@
           FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
   __ leaq(R13, FieldAddress(R13, target::Array::data_offset()));
   // R13: first IC entry
-  __ LoadTaggedClassIdMayBeSmi(RAX, RDI);
+  __ LoadTaggedClassIdMayBeSmi(RAX, RDX);
   // RAX: receiver cid as Smi
 
   __ Bind(&loop);
@@ -3221,21 +3277,21 @@
   __ jmp(RCX);
 }
 
-//  RDI: receiver
+//  RDX: receiver
 //  RBX: UnlinkedCall
 void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
   __ EnterStubFrame();
-  __ pushq(RDI);  // Preserve receiver.
+  __ pushq(RDX);  // Preserve receiver.
 
   __ pushq(Immediate(0));  // Result slot.
-  __ pushq(RDI);           // Arg0: Receiver
+  __ pushq(RDX);           // Arg0: Receiver
   __ pushq(RBX);           // Arg1: UnlinkedCall
   __ CallRuntime(kUnlinkedCallRuntimeEntry, 2);
   __ popq(RBX);
   __ popq(RBX);
   __ popq(RBX);  // result = IC
 
-  __ popq(RDI);  // Restore receiver.
+  __ popq(RDX);  // Restore receiver.
   __ LeaveStubFrame();
 
   __ movq(CODE_REG,
@@ -3246,13 +3302,13 @@
 }
 
 // Called from switchable IC calls.
-//  RDI: receiver
+//  RDX: receiver
 //  RBX: SingleTargetCache
 // Passed to target::
 //  CODE_REG: target Code object
 void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
   Label miss;
-  __ LoadClassIdMayBeSmi(RAX, RDI);
+  __ LoadClassIdMayBeSmi(RAX, RDX);
   __ movzxw(R9,
             FieldAddress(RBX, target::SingleTargetCache::lower_limit_offset()));
   __ movzxw(R10,
@@ -3269,15 +3325,15 @@
 
   __ Bind(&miss);
   __ EnterStubFrame();
-  __ pushq(RDI);  // Preserve receiver.
+  __ pushq(RDX);  // Preserve receiver.
 
   __ pushq(Immediate(0));  // Result slot.
-  __ pushq(RDI);           // Arg0: Receiver
+  __ pushq(RDX);           // Arg0: Receiver
   __ CallRuntime(kSingleTargetMissRuntimeEntry, 1);
   __ popq(RBX);
   __ popq(RBX);  // result = IC
 
-  __ popq(RDI);  // Restore receiver.
+  __ popq(RDX);  // Restore receiver.
   __ LeaveStubFrame();
 
   __ movq(CODE_REG,
@@ -3288,20 +3344,20 @@
 }
 
 // Called from the monomorphic checked entry.
-//  RDI: receiver
+//  RDX: receiver
 void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
   __ movq(CODE_REG,
           Address(THR, target::Thread::monomorphic_miss_stub_offset()));
   __ EnterStubFrame();
-  __ pushq(RDI);  // Preserve receiver.
+  __ pushq(RDX);  // Preserve receiver.
 
   __ pushq(Immediate(0));  // Result slot.
-  __ pushq(RDI);           // Arg0: Receiver
+  __ pushq(RDX);           // Arg0: Receiver
   __ CallRuntime(kMonomorphicMissRuntimeEntry, 1);
   __ popq(RBX);
   __ popq(RBX);  // result = IC
 
-  __ popq(RDI);  // Restore receiver.
+  __ popq(RDX);  // Restore receiver.
   __ LeaveStubFrame();
 
   __ movq(CODE_REG,
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index d10c8c4..8bf0e39 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -16,19 +16,6 @@
 
 namespace dart {
 
-ISOLATE_UNIT_TEST_CASE(CompileScript) {
-  const char* kScriptChars =
-      "class A {\n"
-      "  static foo() { return 42; }\n"
-      "}\n";
-  String& url = String::Handle(String::New("dart-test:CompileScript"));
-  String& source = String::Handle(String::New(kScriptChars));
-  Script& script =
-      Script::Handle(Script::New(url, source, RawScript::kScriptTag));
-  Library& lib = Library::Handle(Library::CoreLibrary());
-  EXPECT(CompilerTest::TestCompileScript(lib, script));
-}
-
 ISOLATE_UNIT_TEST_CASE(CompileFunction) {
   const char* kScriptChars =
       "class A {\n"
diff --git a/runtime/vm/constants_arm.cc b/runtime/vm/constants_arm.cc
index 0934c48..308ce00 100644
--- a/runtime/vm/constants_arm.cc
+++ b/runtime/vm/constants_arm.cc
@@ -7,6 +7,18 @@
 
 namespace arch_arm {
 
+const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+    "r0", "r1",  "r2", "r3", "r4", "r5", "r6", "r7",
+    "r8", "ctx", "pp", "fp", "ip", "sp", "lr", "pc",
+};
+
+const char* fpu_reg_names[kNumberOfFpuRegisters] = {
+    "q0", "q1", "q2",  "q3",  "q4",  "q5",  "q6",  "q7",
+#if defined(VFPv3_D32)
+    "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
+#endif
+};
+
 const Register CallingConventions::ArgumentRegisters[] = {R0, R1, R2, R3};
 
 // Although 'kFpuArgumentRegisters' is 0, we have to give this array at least
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index afbcb92..36ae1dc 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -265,17 +265,8 @@
 const int kNumberOfFpuRegisters = kNumberOfQRegisters;
 const FpuRegister kNoFpuRegister = kNoQRegister;
 
-static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
-    "r0", "r1",  "r2", "r3", "r4", "r5", "r6", "r7",
-    "r8", "ctx", "pp", "fp", "ip", "sp", "lr", "pc",
-};
-
-static const char* fpu_reg_names[kNumberOfFpuRegisters] = {
-    "q0", "q1", "q2",  "q3",  "q4",  "q5",  "q6",  "q7",
-#if defined(VFPv3_D32)
-    "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
-#endif
-};
+extern const char* cpu_reg_names[kNumberOfCpuRegisters];
+extern const char* fpu_reg_names[kNumberOfFpuRegisters];
 
 // Register aliases.
 const Register TMP = IP;            // Used as scratch register by assembler.
@@ -380,6 +371,7 @@
   static constexpr Register kFirstNonArgumentRegister = R8;
   static constexpr Register kSecondNonArgumentRegister = R9;
   static constexpr Register kFirstCalleeSavedCpuReg = NOTFP;
+  static constexpr Register kStackPointerRegister = SPREG;
 };
 
 #undef R
diff --git a/runtime/vm/constants_arm64.cc b/runtime/vm/constants_arm64.cc
index 9938d7c..95a52c0 100644
--- a/runtime/vm/constants_arm64.cc
+++ b/runtime/vm/constants_arm64.cc
@@ -7,6 +7,18 @@
 
 namespace arch_arm64 {
 
+const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",  "r8",  "r9",  "r10",
+    "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
+    "r22", "r23", "r24", "ip0", "ip1", "pp",  "ctx", "fp",  "lr",  "r31",
+};
+
+const char* fpu_reg_names[kNumberOfFpuRegisters] = {
+    "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",  "v8",  "v9",  "v10",
+    "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
+    "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
+};
+
 const Register CallingConventions::ArgumentRegisters[] = {
     R0, R1, R2, R3, R4, R5, R6, R7,
 };
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 9f3355a..75ecfea 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -108,17 +108,8 @@
 const int kNumberOfFpuRegisters = kNumberOfVRegisters;
 const FpuRegister kNoFpuRegister = kNoVRegister;
 
-static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
-    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",  "r8",  "r9",  "r10",
-    "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
-    "r22", "r23", "r24", "ip0", "ip1", "pp",  "ctx", "fp",  "lr",  "r31",
-};
-
-static const char* fpu_reg_names[kNumberOfFpuRegisters] = {
-    "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",  "v8",  "v9",  "v10",
-    "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
-    "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
-};
+extern const char* cpu_reg_names[kNumberOfCpuRegisters];
+extern const char* fpu_reg_names[kNumberOfFpuRegisters];
 
 // Register aliases.
 const Register TMP = R16;  // Used as scratch register by assembler.
@@ -222,6 +213,7 @@
   static constexpr Register kFirstCalleeSavedCpuReg = kAbiFirstPreservedCpuReg;
   static constexpr Register kFirstNonArgumentRegister = R8;
   static constexpr Register kSecondNonArgumentRegister = R9;
+  static constexpr Register kStackPointerRegister = SPREG;
 };
 
 #undef R
diff --git a/runtime/vm/constants_dbc.cc b/runtime/vm/constants_dbc.cc
new file mode 100644
index 0000000..abad6e5
--- /dev/null
+++ b/runtime/vm/constants_dbc.cc
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, 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.
+
+#define RUNTIME_VM_CONSTANTS_H_  // To work around include guard.
+#include "vm/constants_dbc.h"
+
+namespace dart {
+
+const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+    "R0",  "R1",  "R2",  "R3",  "R4",  "R5",  "R6",  "R7",  "R8",  "R9",  "R10",
+    "R11", "R12", "R13", "R14", "R15", "R16", "R17", "R18", "R19", "R20", "R21",
+    "R22", "R23", "R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31",
+#if defined(ARCH_IS_64_BIT)
+    "R32", "R33", "R34", "R35", "R36", "R37", "R38", "R39", "R40", "R41", "R42",
+    "R43", "R44", "R45", "R46", "R47", "R48", "R49", "R50", "R51", "R52", "R53",
+    "R54", "R55", "R56", "R57", "R58", "R59", "R60", "R61", "R62", "R63",
+#endif
+};
+
+const char* fpu_reg_names[kNumberOfFpuRegisters] = {
+    "F0",
+};
+
+}  // namespace dart
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index 2eb202d..6a8cd80 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -170,6 +170,11 @@
 //    Invoke native function at pool[ArgB] with argc_tag at pool[ArgC] using
 //    wrapper at pool[ArgA].
 //
+//  - FfiCall ArgD
+//
+//    Invoke foreign function with unboxed arguments using the signature
+//    descriptor PP[D].
+//
 //  - PushPolymorphicInstanceCall ArgC, D
 //
 //    Skips 2*D + 1 instructions and pushes a function object onto the stack
@@ -300,6 +305,27 @@
 //
 //    Boxes the unboxed unsigned 32-bit integer in FP[rD] into FP[rA].
 //
+//  - UnboxInt64 rA, rD
+//
+//    Unboxes the integer in FP[rD] into FP[rA].
+//
+//  - BoxInt64 rA, rD
+//
+//    Boxes the unboxed signed 64-bit integer in FP[rD] into FP[rA]. If the
+//    value does not fit into a Smi the following instruction is skipped. (The
+//    following instruction should be a jump to a label after the slow path
+//    allocating a Mint box and writing into the Mint box.)
+//
+//  - UnboxedWidthExtender rA rB C
+//
+//    Sign- or zero-extends an unboxed integer in FP[rB] into an unboxed
+//    integer in FP[rA]. C contains SmallRepresentation which determines how
+//    the integer is extended.
+//
+//  - WriteIntoMint rA, rD
+//
+//    Box the integer in FP[rD] using the Mint box in FP[rA].
+//
 //  - SmiToDouble rA, rD
 //
 //    Convert the Smi in FP[rD] to an unboxed double in FP[rA].
@@ -780,6 +806,7 @@
   V(PushPolymorphicInstanceCall,         A_D, num, num, ___) \
   V(PushPolymorphicInstanceCallByRange,  A_D, num, num, ___) \
   V(NativeCall,                        A_B_C, num, num, num) \
+  V(FfiCall,                               D, lit, ___, ___) \
   V(OneByteStringFromCharCode,           A_X, reg, xeg, ___) \
   V(StringToCharCode,                    A_X, reg, xeg, ___) \
   V(AddTOS,                                0, ___, ___, ___) \
@@ -810,11 +837,15 @@
   V(Min,                               A_B_C, reg, reg, reg) \
   V(Max,                               A_B_C, reg, reg, reg) \
   V(WriteIntoDouble,                     A_D, reg, reg, ___) \
+  V(WriteIntoMint,                       A_D, reg, reg, ___) \
   V(UnboxDouble,                         A_D, reg, reg, ___) \
   V(CheckedUnboxDouble,                  A_D, reg, reg, ___) \
   V(UnboxInt32,                        A_B_C, reg, reg, num) \
   V(BoxInt32,                            A_D, reg, reg, ___) \
   V(BoxUint32,                           A_D, reg, reg, ___) \
+  V(UnboxInt64,                          A_D, reg, reg, ___) \
+  V(BoxInt64,                            A_D, reg, reg, ___) \
+  V(UnboxedWidthExtender,              A_B_C, reg, reg, num) \
   V(SmiToDouble,                         A_D, reg, reg, ___) \
   V(DoubleToSmi,                         A_D, reg, reg, ___) \
   V(DAdd,                              A_B_C, reg, reg, reg) \
@@ -895,8 +926,8 @@
   V(LoadArgDescriptorOpt,                  A, reg, ___, ___) \
   V(LoadFpRelativeSlot,                    X, reg, ___, ___) \
   V(LoadFpRelativeSlotOpt,             A_B_Y, reg, reg, reg) \
-  V(StoreFpRelativeSlot,                    X, reg, ___, ___) \
-  V(StoreFpRelativeSlotOpt,             A_B_Y, reg, reg, reg) \
+  V(StoreFpRelativeSlot,                   X, reg, ___, ___) \
+  V(StoreFpRelativeSlotOpt,            A_B_Y, reg, reg, reg) \
   V(LoadIndexedTOS,                        0, ___, ___, ___) \
   V(LoadIndexed,                       A_B_C, reg, reg, reg) \
   V(LoadIndexedOneByteString,          A_B_C, reg, reg, reg) \
@@ -1111,20 +1142,8 @@
 const FpuRegister FpuTMP = kFakeFpuRegister;
 const intptr_t kNumberOfFpuRegisters = 1;
 
-static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
-    "R0",  "R1",  "R2",  "R3",  "R4",  "R5",  "R6",  "R7",  "R8",  "R9",  "R10",
-    "R11", "R12", "R13", "R14", "R15", "R16", "R17", "R18", "R19", "R20", "R21",
-    "R22", "R23", "R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31",
-#if defined(ARCH_IS_64_BIT)
-    "R32", "R33", "R34", "R35", "R36", "R37", "R38", "R39", "R40", "R41", "R42",
-    "R43", "R44", "R45", "R46", "R47", "R48", "R49", "R50", "R51", "R52", "R53",
-    "R54", "R55", "R56", "R57", "R58", "R59", "R60", "R61", "R62", "R63",
-#endif
-};
-
-static const char* fpu_reg_names[kNumberOfFpuRegisters] = {
-    "F0",
-};
+extern const char* cpu_reg_names[kNumberOfCpuRegisters];
+extern const char* fpu_reg_names[kNumberOfFpuRegisters];
 
 // After a comparison, the condition NEXT_IS_TRUE means the following
 // instruction is executed if the comparison is true and skipped over overwise.
diff --git a/runtime/vm/constants_ia32.cc b/runtime/vm/constants_ia32.cc
index a12af82..7b9124a 100644
--- a/runtime/vm/constants_ia32.cc
+++ b/runtime/vm/constants_ia32.cc
@@ -7,6 +7,12 @@
 
 namespace arch_ia32 {
 
+const char* cpu_reg_names[kNumberOfCpuRegisters] = {"eax", "ecx", "edx", "ebx",
+                                                    "esp", "ebp", "esi", "edi"};
+
+const char* fpu_reg_names[kNumberOfXmmRegisters] = {
+    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"};
+
 // Although 'kArgumentRegisters' and 'kFpuArgumentRegisters' are both 0, we have
 // to give these arrays at least one element to appease MSVC.
 
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index ce697b9..d2cbb93 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -53,15 +53,12 @@
 
 // Architecture independent aliases.
 typedef XmmRegister FpuRegister;
-const FpuRegister FpuTMP = XMM0;
+const FpuRegister FpuTMP = XMM7;
 const int kNumberOfFpuRegisters = kNumberOfXmmRegisters;
 const FpuRegister kNoFpuRegister = kNoXmmRegister;
 
-static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
-    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
-
-static const char* fpu_reg_names[kNumberOfXmmRegisters] = {
-    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"};
+extern const char* cpu_reg_names[kNumberOfCpuRegisters];
+extern const char* fpu_reg_names[kNumberOfXmmRegisters];
 
 // Register aliases.
 const Register TMP = kNoRegister;   // No scratch register used by assembler.
@@ -154,6 +151,7 @@
   static constexpr Register kFirstCalleeSavedCpuReg = EBX;
   static constexpr Register kFirstNonArgumentRegister = EAX;
   static constexpr Register kSecondNonArgumentRegister = ECX;
+  static constexpr Register kStackPointerRegister = SPREG;
 
   // Whether 64-bit arguments must be aligned to an even register or 8-byte
   // stack address. On IA32, 64-bit integers and floating-point values do *not*
diff --git a/runtime/vm/constants_kbc.cc b/runtime/vm/constants_kbc.cc
new file mode 100644
index 0000000..d5ed600
--- /dev/null
+++ b/runtime/vm/constants_kbc.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2019, 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.
+
+#define RUNTIME_VM_CONSTANTS_H_  // To work around include guard.
+#include "vm/constants_kbc.h"
+
+namespace dart {
+
+static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 7,
+              "Cleanup support for old bytecode format versions");
+static const intptr_t kOldInstructionSize = 4;
+
+static const intptr_t kInstructionSize0 = 1;
+static const intptr_t kInstructionSizeA = 2;
+static const intptr_t kInstructionSizeD = 2;
+static const intptr_t kInstructionSizeWideD = 5;
+static const intptr_t kInstructionSizeX = 2;
+static const intptr_t kInstructionSizeWideX = 5;
+static const intptr_t kInstructionSizeT = 2;
+static const intptr_t kInstructionSizeWideT = 4;
+static const intptr_t kInstructionSizeA_E = 3;
+static const intptr_t kInstructionSizeWideA_E = 6;
+static const intptr_t kInstructionSizeA_Y = 3;
+static const intptr_t kInstructionSizeWideA_Y = 6;
+static const intptr_t kInstructionSizeD_F = 3;
+static const intptr_t kInstructionSizeWideD_F = 6;
+static const intptr_t kInstructionSizeA_B_C = 4;
+
+const intptr_t KernelBytecode::kInstructionSize[] = {
+#define SIZE_OLD(encoding) kOldInstructionSize
+#define SIZE_ORDN(encoding) kInstructionSize##encoding
+#define SIZE_WIDE(encoding) kInstructionSizeWide##encoding
+#define SIZE_RESV(encoding) SIZE_ORDN(encoding)
+#define SIZE(name, encoding, kind, op1, op2, op3) SIZE_##kind(encoding),
+    KERNEL_BYTECODES_LIST(SIZE)
+#undef SIZE_OLD
+#undef SIZE_ORDN
+#undef SIZE_WIDE
+#undef SIZE_RESV
+#undef SIZE
+};
+
+#define DECLARE_INSTRUCTIONS(name, fmt, kind, fmta, fmtb, fmtc)                \
+  static const KBCInstr k##name##Instructions[] = {                            \
+      KernelBytecode::k##name,                                                 \
+      KernelBytecode::kReturnTOS,                                              \
+  };
+INTERNAL_KERNEL_BYTECODES_LIST(DECLARE_INSTRUCTIONS)
+#undef DECLARE_INSTRUCTIONS
+
+void KernelBytecode::GetVMInternalBytecodeInstructions(
+    Opcode opcode,
+    const KBCInstr** instructions,
+    intptr_t* instructions_size) {
+  switch (opcode) {
+#define CASE(name, fmt, kind, fmta, fmtb, fmtc)                                \
+  case k##name:                                                                \
+    *instructions = k##name##Instructions;                                     \
+    *instructions_size = sizeof(k##name##Instructions);                        \
+    return;
+
+    INTERNAL_KERNEL_BYTECODES_LIST(CASE)
+#undef CASE
+
+    default:
+      UNREACHABLE();
+  }
+}
+
+static const KBCInstr kNativeCallToGrowableListReturnTrampoline[] = {
+    KernelBytecode::kDirectCall,
+    0,                                              // target (doesn't matter)
+    KernelBytecode::kNativeCallToGrowableListArgc,  // number of arguments
+    KernelBytecode::kReturnTOS,
+};
+
+const KBCInstr* KernelBytecode::GetNativeCallToGrowableListReturnTrampoline() {
+  return KernelBytecode::Next(&kNativeCallToGrowableListReturnTrampoline[0]);
+}
+
+}  // namespace dart
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index dc8e954..811f106 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -40,44 +40,71 @@
 //
 // ENCODING
 //
-// Each instruction is a 32-bit integer with opcode stored in the least
-// significant byte. The following operand encodings are used:
+// Each instruction starts with opcode byte. Certain instructions have
+// wide encoding variant. In such case, the least significant bit of opcode is
+// not set for compact variant and set for wide variant.
 //
-//   0........8.......16.......24.......32
-//   +--------+--------+--------+--------+
-//   | opcode |~~~~~~~~~~~~~~~~~~~~~~~~~~|   0: no operands
-//   +--------+--------+--------+--------+
+// The following operand encodings are used:
+//
+//   0........8.......16.......24.......32.......40.......48
+//   +--------+
+//   | opcode |                              0: no operands
+//   +--------+
+//
+//   +--------+--------+
+//   | opcode |    A   |                     A: unsigned 8-bit operand
+//   +--------+--------+
+//
+//   +--------+--------+
+//   | opcode |   D    |                     D: unsigned 8/32-bit operand
+//   +--------+--------+
+//
+//   +--------+----------------------------------+
+//   | opcode |                D                 |            D (wide)
+//   +--------+----------------------------------+
+//
+//   +--------+--------+
+//   | opcode |   X    |                     X: signed 8/32-bit operand
+//   +--------+--------+
+//
+//   +--------+----------------------------------+
+//   | opcode |                X                 |            X (wide)
+//   +--------+----------------------------------+
+//
+//   +--------+--------+
+//   | opcode |    T   |                     T: signed 8/24-bit operand
+//   +--------+--------+
+//
+//   +--------+--------------------------+
+//   | opcode |            T             |   T (wide)
+//   +--------+--------------------------+
+//
+//   +--------+--------+--------+
+//   | opcode |    A   |   E    |            A_E: unsigned 8-bit operand and
+//   +--------+--------+--------+                 unsigned 8/32-bit operand
+//
+//   +--------+--------+----------------------------------+
+//   | opcode |    A   |                 E                |   A_E (wide)
+//   +--------+--------+----------------------------------+
+//
+//   +--------+--------+--------+
+//   | opcode |    A   |   Y    |            A_Y: unsigned 8-bit operand and
+//   +--------+--------+--------+                 signed 8/32-bit operand
+//
+//   +--------+--------+----------------------------------+
+//   | opcode |    A   |                 Y                |   A_Y (wide)
+//   +--------+--------+----------------------------------+
+//
+//   +--------+--------+--------+
+//   | opcode |    D   |   F    |            D_F: unsigned 8/32-bit operand and
+//   +--------+--------+--------+                 unsigned 8-bit operand
+//
+//   +--------+----------------------------------+--------+
+//   | opcode |                 D                |    F   |   D_F (wide)
+//   +--------+----------------------------------+--------+
 //
 //   +--------+--------+--------+--------+
-//   | opcode |    A   |~~~~~~~~~~~~~~~~~|   A: single unsigned 8-bit operand
-//   +--------+--------+--------+--------+
-//
-//   +--------+--------+--------+--------+
-//   | opcode |    A   |        D        | A_D: unsigned 8-bit operand and
-//   +--------+--------+--------+--------+      unsigned 16-bit operand
-//
-//   +--------+--------+--------+--------+
-//   | opcode |    A   |        X        | A_X: unsigned 8-bit operand and
-//   +--------+--------+--------+--------+      signed 16-bit operand
-//
-//   +--------+--------+--------+--------+
-//   | opcode |~~~~~~~~|        D        |   D: unsigned 16-bit operand
-//   +--------+--------+--------+--------+
-//
-//   +--------+--------+--------+--------+
-//   | opcode |~~~~~~~~|        X        |   X: signed 16-bit operand
-//   +--------+--------+--------+--------+
-//
-//   +--------+--------+--------+--------+
-//   | opcode |    A   |    B   |    C   | A_B_C: 3 unsigned 8-bit operands
-//   +--------+--------+--------+--------+
-//
-//   +--------+--------+--------+--------+
-//   | opcode |    A   |    B   |    Y   | A_B_Y: 2 unsigned 8-bit operands
-//   +--------+--------+--------+--------+        1 signed 8-bit operand
-//
-//   +--------+--------+--------+--------+
-//   | opcode |             T            |   T: signed 24-bit operand
+//   | opcode |    A   |    B   |    C   |   A_B_C: 3 unsigned 8-bit operands
 //   +--------+--------+--------+--------+
 //
 //
@@ -231,7 +258,7 @@
 //    Store SP[0] into array SP[-2] at index SP[-1]. No typechecking is done.
 //    SP[-2] is assumed to be a RawArray, SP[-1] to be a smi.
 //
-//  - PushStatic
+//  - PushStatic D
 //
 //    Pushes value of the static field PP[D] on to the stack.
 //
@@ -346,10 +373,12 @@
 //    Instantiate type PP[D] with instantiator type arguments SP[-1] and
 //    function type arguments SP[0].
 //
-//  - InstantiateTypeArgumentsTOS D
+//  - InstantiateTypeArgumentsTOS A, D
 //
 //    Instantiate type arguments PP[D] with instantiator type arguments SP[-1]
-//    and function type arguments SP[0].
+//    and function type arguments SP[0]. A != 0 indicates that resulting type
+//    arguments are all dynamic if both instantiator and function type
+//    arguments are all dynamic.
 //
 //  - Throw A
 //
@@ -421,12 +450,14 @@
 //
 // KernelBytecode list below is specified using the following format:
 //
-//     V(BytecodeName, OperandForm, Op1, Op2, Op3)
+//     V(BytecodeName, OperandForm, BytecodeKind, Op1, Op2, Op3)
 //
-// - OperandForm specifies operand encoding and should be one of 0, A, T, A_D,
-//   A_X, X, D (see ENCODING section above).
+// - OperandForm specifies operand encoding and should be one of 0, A, D, X, T,
+//   A_D (old), A_X (old), A_E, A_Y, D_F or A_B_C (see ENCODING section above).
 //
-// - Op1, Op2, Op2 specify operand meaning. Possible values:
+// - BytecodeKind is one of OLD, WIDE, RESV (reserved), ORDN (ordinary)
+//
+// - Op1, Op2, Op3 specify operand meaning. Possible values:
 //
 //     ___ ignored / non-existent operand
 //     num immediate operand
@@ -440,98 +471,266 @@
 //               and before decoding.
 //
 #define PUBLIC_KERNEL_BYTECODES_LIST(V)                                        \
-  V(Trap,                                  0, ___, ___, ___)                   \
-  V(Entry,                                 D, num, ___, ___)                   \
-  V(EntryFixed,                          A_D, num, num, ___)                   \
-  V(EntryOptional,                     A_B_C, num, num, num)                   \
-  V(LoadConstant,                        A_D, reg, lit, ___)                   \
-  V(Frame,                                 D, num, ___, ___)                   \
-  V(CheckFunctionTypeArgs,               A_D, num, reg, ___)                   \
-  V(CheckStack,                            A, num, ___, ___)                   \
-  V(Allocate,                              D, lit, ___, ___)                   \
-  V(AllocateT,                             0, ___, ___, ___)                   \
-  V(CreateArrayTOS,                        0, ___, ___, ___)                   \
-  V(AllocateContext,                       D, num, ___, ___)                   \
-  V(CloneContext,                          D, num, ___, ___)                   \
-  V(LoadContextParent,                     0, ___, ___, ___)                   \
-  V(StoreContextParent,                    0, ___, ___, ___)                   \
-  V(LoadContextVar,                        D, num, ___, ___)                   \
-  V(StoreContextVar,                       D, num, ___, ___)                   \
-  V(PushConstant,                          D, lit, ___, ___)                   \
-  V(PushNull,                              0, ___, ___, ___)                   \
-  V(PushTrue,                              0, ___, ___, ___)                   \
-  V(PushFalse,                             0, ___, ___, ___)                   \
-  V(PushInt,                               X, num, ___, ___)                   \
-  V(Drop1,                                 0, ___, ___, ___)                   \
-  V(Push,                                  X, xeg, ___, ___)                   \
-  V(PopLocal,                              X, xeg, ___, ___)                   \
-  V(StoreLocal,                            X, xeg, ___, ___)                   \
-  V(LoadFieldTOS,                          D, lit, ___, ___)                   \
-  V(StoreFieldTOS,                         D, lit, ___, ___)                   \
-  V(StoreIndexedTOS,                       0, ___, ___, ___)                   \
-  V(PushStatic,                            D, lit, ___, ___)                   \
-  V(StoreStaticTOS,                        D, lit, ___, ___)                   \
-  V(Jump,                                  T, tgt, ___, ___)                   \
-  V(JumpIfNoAsserts,                       T, tgt, ___, ___)                   \
-  V(JumpIfNotZeroTypeArgs,                 T, tgt, ___, ___)                   \
-  V(JumpIfEqStrict,                        T, tgt, ___, ___)                   \
-  V(JumpIfNeStrict,                        T, tgt, ___, ___)                   \
-  V(JumpIfTrue,                            T, tgt, ___, ___)                   \
-  V(JumpIfFalse,                           T, tgt, ___, ___)                   \
-  V(JumpIfNull,                            T, tgt, ___, ___)                   \
-  V(JumpIfNotNull,                         T, tgt, ___, ___)                   \
-  V(IndirectStaticCall,                  A_D, num, num, ___)                   \
-  V(InterfaceCall,                       A_D, num, num, ___)                   \
-  V(DynamicCall,                         A_D, num, num, ___)                   \
-  V(NativeCall,                            D, lit, ___, ___)                   \
-  V(ReturnTOS,                             0, ___, ___, ___)                   \
-  V(AssertAssignable,                    A_D, num, lit, ___)                   \
-  V(AssertBoolean,                         A, num, ___, ___)                   \
-  V(AssertSubtype,                         0, ___, ___, ___)                   \
-  V(LoadTypeArgumentsField,                D, lit, ___, ___)                   \
-  V(InstantiateType,                       D, lit, ___, ___)                   \
-  V(InstantiateTypeArgumentsTOS,         A_D, num, lit, ___)                   \
-  V(Throw,                                 A, num, ___, ___)                   \
-  V(MoveSpecial,                         A_X, num, xeg, ___)                   \
-  V(SetFrame,                              A, num, ___, num)                   \
-  V(BooleanNegateTOS,                      0, ___, ___, ___)                   \
-  V(EqualsNull,                            0, ___, ___, ___)                   \
-  V(NegateInt,                             0, ___, ___, ___)                   \
-  V(AddInt,                                0, ___, ___, ___)                   \
-  V(SubInt,                                0, ___, ___, ___)                   \
-  V(MulInt,                                0, ___, ___, ___)                   \
-  V(TruncDivInt,                           0, ___, ___, ___)                   \
-  V(ModInt,                                0, ___, ___, ___)                   \
-  V(BitAndInt,                             0, ___, ___, ___)                   \
-  V(BitOrInt,                              0, ___, ___, ___)                   \
-  V(BitXorInt,                             0, ___, ___, ___)                   \
-  V(ShlInt,                                0, ___, ___, ___)                   \
-  V(ShrInt,                                0, ___, ___, ___)                   \
-  V(CompareIntEq,                          0, ___, ___, ___)                   \
-  V(CompareIntGt,                          0, ___, ___, ___)                   \
-  V(CompareIntLt,                          0, ___, ___, ___)                   \
-  V(CompareIntGe,                          0, ___, ___, ___)                   \
-  V(CompareIntLe,                          0, ___, ___, ___)                   \
-  V(DirectCall,                          A_D, num, num, ___)                   \
-  V(AllocateClosure,                       D, lit, ___, ___)                   \
-  V(UncheckedInterfaceCall,              A_D, num, num, ___)                   \
-  V(NegateDouble,                          0, ___, ___, ___)                   \
-  V(AddDouble,                             0, ___, ___, ___)                   \
-  V(SubDouble,                             0, ___, ___, ___)                   \
-  V(MulDouble,                             0, ___, ___, ___)                   \
-  V(DivDouble,                             0, ___, ___, ___)                   \
-  V(CompareDoubleEq,                       0, ___, ___, ___)                   \
-  V(CompareDoubleGt,                       0, ___, ___, ___)                   \
-  V(CompareDoubleLt,                       0, ___, ___, ___)                   \
-  V(CompareDoubleGe,                       0, ___, ___, ___)                   \
-  V(CompareDoubleLe,                       0, ___, ___, ___)                   \
+  V(Trap_Old,                              0,  OLD, ___, ___, ___)             \
+  V(Entry_Old,                             D,  OLD, num, ___, ___)             \
+  V(EntryFixed_Old,                      A_D,  OLD, num, num, ___)             \
+  V(EntryOptional_Old,                 A_B_C,  OLD, num, num, num)             \
+  V(LoadConstant_Old,                    A_D,  OLD, reg, lit, ___)             \
+  V(Frame_Old,                             D,  OLD, num, ___, ___)             \
+  V(CheckFunctionTypeArgs_Old,           A_D,  OLD, num, reg, ___)             \
+  V(CheckStack_Old,                        A,  OLD, num, ___, ___)             \
+  V(Allocate_Old,                          D,  OLD, lit, ___, ___)             \
+  V(AllocateT_Old,                         0,  OLD, ___, ___, ___)             \
+  V(CreateArrayTOS_Old,                    0,  OLD, ___, ___, ___)             \
+  V(AllocateContext_Old,                   D,  OLD, num, ___, ___)             \
+  V(CloneContext_Old,                      D,  OLD, num, ___, ___)             \
+  V(LoadContextParent_Old,                 0,  OLD, ___, ___, ___)             \
+  V(StoreContextParent_Old,                0,  OLD, ___, ___, ___)             \
+  V(LoadContextVar_Old,                    D,  OLD, num, ___, ___)             \
+  V(StoreContextVar_Old,                   D,  OLD, num, ___, ___)             \
+  V(PushConstant_Old,                      D,  OLD, lit, ___, ___)             \
+  V(PushNull_Old,                          0,  OLD, ___, ___, ___)             \
+  V(PushTrue_Old,                          0,  OLD, ___, ___, ___)             \
+  V(PushFalse_Old,                         0,  OLD, ___, ___, ___)             \
+  V(PushInt_Old,                           X,  OLD, num, ___, ___)             \
+  V(Drop1_Old,                             0,  OLD, ___, ___, ___)             \
+  V(Push_Old,                              X,  OLD, xeg, ___, ___)             \
+  V(PopLocal_Old,                          X,  OLD, xeg, ___, ___)             \
+  V(StoreLocal_Old,                        X,  OLD, xeg, ___, ___)             \
+  V(LoadFieldTOS_Old,                      D,  OLD, lit, ___, ___)             \
+  V(StoreFieldTOS_Old,                     D,  OLD, lit, ___, ___)             \
+  V(StoreIndexedTOS_Old,                   0,  OLD, ___, ___, ___)             \
+  V(PushStatic_Old,                        D,  OLD, lit, ___, ___)             \
+  V(StoreStaticTOS_Old,                    D,  OLD, lit, ___, ___)             \
+  V(Jump_Old,                              T,  OLD, tgt, ___, ___)             \
+  V(JumpIfNoAsserts_Old,                   T,  OLD, tgt, ___, ___)             \
+  V(JumpIfNotZeroTypeArgs_Old,             T,  OLD, tgt, ___, ___)             \
+  V(JumpIfEqStrict_Old,                    T,  OLD, tgt, ___, ___)             \
+  V(JumpIfNeStrict_Old,                    T,  OLD, tgt, ___, ___)             \
+  V(JumpIfTrue_Old,                        T,  OLD, tgt, ___, ___)             \
+  V(JumpIfFalse_Old,                       T,  OLD, tgt, ___, ___)             \
+  V(JumpIfNull_Old,                        T,  OLD, tgt, ___, ___)             \
+  V(JumpIfNotNull_Old,                     T,  OLD, tgt, ___, ___)             \
+  V(Unused00_Old,                          0, RESV, num, num, ___)             \
+  V(InterfaceCall_Old,                   A_D,  OLD, num, num, ___)             \
+  V(DynamicCall_Old,                     A_D,  OLD, num, num, ___)             \
+  V(NativeCall_Old,                        D,  OLD, lit, ___, ___)             \
+  V(ReturnTOS_Old,                         0,  OLD, ___, ___, ___)             \
+  V(AssertAssignable_Old,                A_D,  OLD, num, lit, ___)             \
+  V(AssertBoolean_Old,                     A,  OLD, num, ___, ___)             \
+  V(AssertSubtype_Old,                     0,  OLD, ___, ___, ___)             \
+  V(LoadTypeArgumentsField_Old,            D,  OLD, lit, ___, ___)             \
+  V(InstantiateType_Old,                   D,  OLD, lit, ___, ___)             \
+  V(InstantiateTypeArgumentsTOS_Old,     A_D,  OLD, num, lit, ___)             \
+  V(Throw_Old,                             A,  OLD, num, ___, ___)             \
+  V(MoveSpecial_Old,                     A_X,  OLD, num, xeg, ___)             \
+  V(SetFrame_Old,                          A,  OLD, num, ___, num)             \
+  V(BooleanNegateTOS_Old,                  0,  OLD, ___, ___, ___)             \
+  V(EqualsNull_Old,                        0,  OLD, ___, ___, ___)             \
+  V(NegateInt_Old,                         0,  OLD, ___, ___, ___)             \
+  V(AddInt_Old,                            0,  OLD, ___, ___, ___)             \
+  V(SubInt_Old,                            0,  OLD, ___, ___, ___)             \
+  V(MulInt_Old,                            0,  OLD, ___, ___, ___)             \
+  V(TruncDivInt_Old,                       0,  OLD, ___, ___, ___)             \
+  V(ModInt_Old,                            0,  OLD, ___, ___, ___)             \
+  V(BitAndInt_Old,                         0,  OLD, ___, ___, ___)             \
+  V(BitOrInt_Old,                          0,  OLD, ___, ___, ___)             \
+  V(BitXorInt_Old,                         0,  OLD, ___, ___, ___)             \
+  V(ShlInt_Old,                            0,  OLD, ___, ___, ___)             \
+  V(ShrInt_Old,                            0,  OLD, ___, ___, ___)             \
+  V(CompareIntEq_Old,                      0,  OLD, ___, ___, ___)             \
+  V(CompareIntGt_Old,                      0,  OLD, ___, ___, ___)             \
+  V(CompareIntLt_Old,                      0,  OLD, ___, ___, ___)             \
+  V(CompareIntGe_Old,                      0,  OLD, ___, ___, ___)             \
+  V(CompareIntLe_Old,                      0,  OLD, ___, ___, ___)             \
+  V(DirectCall_Old,                      A_D,  OLD, num, num, ___)             \
+  V(AllocateClosure_Old,                   D,  OLD, lit, ___, ___)             \
+  V(UncheckedInterfaceCall_Old,          A_D,  OLD, num, num, ___)             \
+  V(NegateDouble_Old,                      0,  OLD, ___, ___, ___)             \
+  V(AddDouble_Old,                         0,  OLD, ___, ___, ___)             \
+  V(SubDouble_Old,                         0,  OLD, ___, ___, ___)             \
+  V(MulDouble_Old,                         0,  OLD, ___, ___, ___)             \
+  V(DivDouble_Old,                         0,  OLD, ___, ___, ___)             \
+  V(CompareDoubleEq_Old,                   0,  OLD, ___, ___, ___)             \
+  V(CompareDoubleGt_Old,                   0,  OLD, ___, ___, ___)             \
+  V(CompareDoubleLt_Old,                   0,  OLD, ___, ___, ___)             \
+  V(CompareDoubleGe_Old,                   0,  OLD, ___, ___, ___)             \
+  V(CompareDoubleLe_Old,                   0,  OLD, ___, ___, ___)             \
+  V(Trap,                                  0, ORDN, ___, ___, ___)             \
+  V(Entry,                                 D, ORDN, num, ___, ___)             \
+  V(Entry_Wide,                            D, WIDE, num, ___, ___)             \
+  V(EntryFixed,                          A_E, ORDN, num, num, ___)             \
+  V(EntryFixed_Wide,                     A_E, WIDE, num, num, ___)             \
+  V(EntryOptional,                     A_B_C, ORDN, num, num, num)             \
+  V(Unused00,                              0, RESV, ___, ___, ___)             \
+  V(LoadConstant,                        A_E, ORDN, reg, lit, ___)             \
+  V(LoadConstant_Wide,                   A_E, WIDE, reg, lit, ___)             \
+  V(Frame,                                 D, ORDN, num, ___, ___)             \
+  V(Frame_Wide,                            D, WIDE, num, ___, ___)             \
+  V(CheckFunctionTypeArgs,               A_E, ORDN, num, reg, ___)             \
+  V(CheckFunctionTypeArgs_Wide,          A_E, WIDE, num, reg, ___)             \
+  V(CheckStack,                            A, ORDN, num, ___, ___)             \
+  V(Unused01,                              0, RESV, ___, ___, ___)             \
+  V(Unused02,                              0, RESV, ___, ___, ___)             \
+  V(Unused03,                              0, RESV, ___, ___, ___)             \
+  V(Allocate,                              D, ORDN, lit, ___, ___)             \
+  V(Allocate_Wide,                         D, WIDE, lit, ___, ___)             \
+  V(AllocateT,                             0, ORDN, ___, ___, ___)             \
+  V(CreateArrayTOS,                        0, ORDN, ___, ___, ___)             \
+  V(AllocateClosure,                       D, ORDN, lit, ___, ___)             \
+  V(AllocateClosure_Wide,                  D, WIDE, lit, ___, ___)             \
+  V(AllocateContext,                     A_E, ORDN, num, ___, ___)             \
+  V(AllocateContext_Wide,                A_E, WIDE, num, ___, ___)             \
+  V(CloneContext,                        A_E, ORDN, num, ___, ___)             \
+  V(CloneContext_Wide,                   A_E, WIDE, num, ___, ___)             \
+  V(LoadContextParent,                     0, ORDN, ___, ___, ___)             \
+  V(StoreContextParent,                    0, ORDN, ___, ___, ___)             \
+  V(LoadContextVar,                      A_E, ORDN, num, ___, ___)             \
+  V(LoadContextVar_Wide,                 A_E, WIDE, num, ___, ___)             \
+  V(Unused04,                              0, RESV, ___, ___, ___)             \
+  V(Unused05,                              0, RESV, ___, ___, ___)             \
+  V(StoreContextVar,                     A_E, ORDN, num, ___, ___)             \
+  V(StoreContextVar_Wide,                A_E, WIDE, num, ___, ___)             \
+  V(PushConstant,                          D, ORDN, lit, ___, ___)             \
+  V(PushConstant_Wide,                     D, WIDE, lit, ___, ___)             \
+  V(Unused06,                              0, RESV, ___, ___, ___)             \
+  V(Unused07,                              0, RESV, ___, ___, ___)             \
+  V(PushTrue,                              0, ORDN, ___, ___, ___)             \
+  V(PushFalse,                             0, ORDN, ___, ___, ___)             \
+  V(PushInt,                               X, ORDN, num, ___, ___)             \
+  V(PushInt_Wide,                          X, WIDE, num, ___, ___)             \
+  V(Unused08,                              0, RESV, ___, ___, ___)             \
+  V(Unused09,                              0, RESV, ___, ___, ___)             \
+  V(Unused10,                              0, RESV, ___, ___, ___)             \
+  V(Unused11,                              0, RESV, ___, ___, ___)             \
+  V(PushNull,                              0, ORDN, ___, ___, ___)             \
+  V(Drop1,                                 0, ORDN, ___, ___, ___)             \
+  V(Push,                                  X, ORDN, xeg, ___, ___)             \
+  V(Push_Wide,                             X, WIDE, xeg, ___, ___)             \
+  V(Unused12,                              0, RESV, ___, ___, ___)             \
+  V(Unused13,                              0, RESV, ___, ___, ___)             \
+  V(Unused14,                              0, RESV, ___, ___, ___)             \
+  V(Unused15,                              0, RESV, ___, ___, ___)             \
+  V(Unused16,                              0, RESV, ___, ___, ___)             \
+  V(Unused17,                              0, RESV, ___, ___, ___)             \
+  V(PopLocal,                              X, ORDN, xeg, ___, ___)             \
+  V(PopLocal_Wide,                         X, WIDE, xeg, ___, ___)             \
+  V(Unused18,                              0, RESV, ___, ___, ___)             \
+  V(Unused19,                              0, RESV, ___, ___, ___)             \
+  V(StoreLocal,                            X, ORDN, xeg, ___, ___)             \
+  V(StoreLocal_Wide,                       X, WIDE, xeg, ___, ___)             \
+  V(LoadFieldTOS,                          D, ORDN, lit, ___, ___)             \
+  V(LoadFieldTOS_Wide,                     D, WIDE, lit, ___, ___)             \
+  V(StoreFieldTOS,                         D, ORDN, lit, ___, ___)             \
+  V(StoreFieldTOS_Wide,                    D, WIDE, lit, ___, ___)             \
+  V(StoreIndexedTOS,                       0, ORDN, ___, ___, ___)             \
+  V(Unused20,                              0, RESV, ___, ___, ___)             \
+  V(PushStatic,                            D, ORDN, lit, ___, ___)             \
+  V(PushStatic_Wide,                       D, WIDE, lit, ___, ___)             \
+  V(StoreStaticTOS,                        D, ORDN, lit, ___, ___)             \
+  V(StoreStaticTOS_Wide,                   D, WIDE, lit, ___, ___)             \
+  V(Jump,                                  T, ORDN, tgt, ___, ___)             \
+  V(Jump_Wide,                             T, WIDE, tgt, ___, ___)             \
+  V(JumpIfNoAsserts,                       T, ORDN, tgt, ___, ___)             \
+  V(JumpIfNoAsserts_Wide,                  T, WIDE, tgt, ___, ___)             \
+  V(JumpIfNotZeroTypeArgs,                 T, ORDN, tgt, ___, ___)             \
+  V(JumpIfNotZeroTypeArgs_Wide,            T, WIDE, tgt, ___, ___)             \
+  V(JumpIfEqStrict,                        T, ORDN, tgt, ___, ___)             \
+  V(JumpIfEqStrict_Wide,                   T, WIDE, tgt, ___, ___)             \
+  V(JumpIfNeStrict,                        T, ORDN, tgt, ___, ___)             \
+  V(JumpIfNeStrict_Wide,                   T, WIDE, tgt, ___, ___)             \
+  V(JumpIfTrue,                            T, ORDN, tgt, ___, ___)             \
+  V(JumpIfTrue_Wide,                       T, WIDE, tgt, ___, ___)             \
+  V(JumpIfFalse,                           T, ORDN, tgt, ___, ___)             \
+  V(JumpIfFalse_Wide,                      T, WIDE, tgt, ___, ___)             \
+  V(JumpIfNull,                            T, ORDN, tgt, ___, ___)             \
+  V(JumpIfNull_Wide,                       T, WIDE, tgt, ___, ___)             \
+  V(JumpIfNotNull,                         T, ORDN, tgt, ___, ___)             \
+  V(JumpIfNotNull_Wide,                    T, WIDE, tgt, ___, ___)             \
+  V(DirectCall,                          D_F, ORDN, num, num, ___)             \
+  V(DirectCall_Wide,                     D_F, WIDE, num, num, ___)             \
+  V(Unused21,                              0, RESV, ___, ___, ___)             \
+  V(Unused22,                              0, RESV, ___, ___, ___)             \
+  V(InterfaceCall,                       D_F, ORDN, num, num, ___)             \
+  V(InterfaceCall_Wide,                  D_F, WIDE, num, num, ___)             \
+  V(Unused23,                              0, RESV, ___, ___, ___)             \
+  V(Unused24,                              0, RESV, ___, ___, ___)             \
+  V(Unused25,                              0, RESV, ___, ___, ___)             \
+  V(Unused26,                              0, RESV, ___, ___, ___)             \
+  V(Unused27,                              0, RESV, ___, ___, ___)             \
+  V(Unused28,                              0, RESV, ___, ___, ___)             \
+  V(UncheckedInterfaceCall,              D_F, ORDN, num, num, ___)             \
+  V(UncheckedInterfaceCall_Wide,         D_F, WIDE, num, num, ___)             \
+  V(DynamicCall,                         D_F, ORDN, num, num, ___)             \
+  V(DynamicCall_Wide,                    D_F, WIDE, num, num, ___)             \
+  V(NativeCall,                            D, ORDN, lit, ___, ___)             \
+  V(NativeCall_Wide,                       D, WIDE, lit, ___, ___)             \
+  V(ReturnTOS,                             0, ORDN, ___, ___, ___)             \
+  V(Unused29,                              0, RESV, ___, ___, ___)             \
+  V(AssertAssignable,                    A_E, ORDN, num, lit, ___)             \
+  V(AssertAssignable_Wide,               A_E, WIDE, num, lit, ___)             \
+  V(Unused30,                              0, RESV, ___, ___, ___)             \
+  V(Unused31,                              0, RESV, ___, ___, ___)             \
+  V(AssertBoolean,                         A, ORDN, num, ___, ___)             \
+  V(AssertSubtype,                         0, ORDN, ___, ___, ___)             \
+  V(LoadTypeArgumentsField,                D, ORDN, lit, ___, ___)             \
+  V(LoadTypeArgumentsField_Wide,           D, WIDE, lit, ___, ___)             \
+  V(InstantiateType,                       D, ORDN, lit, ___, ___)             \
+  V(InstantiateType_Wide,                  D, WIDE, lit, ___, ___)             \
+  V(InstantiateTypeArgumentsTOS,         A_E, ORDN, num, lit, ___)             \
+  V(InstantiateTypeArgumentsTOS_Wide,    A_E, WIDE, num, lit, ___)             \
+  V(Unused32,                              0, RESV, ___, ___, ___)             \
+  V(Unused33,                              0, RESV, ___, ___, ___)             \
+  V(Unused34,                              0, RESV, ___, ___, ___)             \
+  V(Unused35,                              0, RESV, ___, ___, ___)             \
+  V(Throw,                                 A, ORDN, num, ___, ___)             \
+  V(SetFrame,                              A, ORDN, num, ___, num)             \
+  V(MoveSpecial,                         A_Y, ORDN, num, xeg, ___)             \
+  V(MoveSpecial_Wide,                    A_Y, WIDE, num, xeg, ___)             \
+  V(BooleanNegateTOS,                      0, ORDN, ___, ___, ___)             \
+  V(EqualsNull,                            0, ORDN, ___, ___, ___)             \
+  V(Unused36,                              0, RESV, ___, ___, ___)             \
+  V(Unused37,                              0, RESV, ___, ___, ___)             \
+  V(NegateInt,                             0, ORDN, ___, ___, ___)             \
+  V(AddInt,                                0, ORDN, ___, ___, ___)             \
+  V(SubInt,                                0, ORDN, ___, ___, ___)             \
+  V(MulInt,                                0, ORDN, ___, ___, ___)             \
+  V(TruncDivInt,                           0, ORDN, ___, ___, ___)             \
+  V(ModInt,                                0, ORDN, ___, ___, ___)             \
+  V(BitAndInt,                             0, ORDN, ___, ___, ___)             \
+  V(BitOrInt,                              0, ORDN, ___, ___, ___)             \
+  V(BitXorInt,                             0, ORDN, ___, ___, ___)             \
+  V(ShlInt,                                0, ORDN, ___, ___, ___)             \
+  V(ShrInt,                                0, ORDN, ___, ___, ___)             \
+  V(CompareIntEq,                          0, ORDN, ___, ___, ___)             \
+  V(CompareIntGt,                          0, ORDN, ___, ___, ___)             \
+  V(CompareIntLt,                          0, ORDN, ___, ___, ___)             \
+  V(CompareIntGe,                          0, ORDN, ___, ___, ___)             \
+  V(CompareIntLe,                          0, ORDN, ___, ___, ___)             \
+  V(NegateDouble,                          0, ORDN, ___, ___, ___)             \
+  V(AddDouble,                             0, ORDN, ___, ___, ___)             \
+  V(SubDouble,                             0, ORDN, ___, ___, ___)             \
+  V(MulDouble,                             0, ORDN, ___, ___, ___)             \
+  V(DivDouble,                             0, ORDN, ___, ___, ___)             \
+  V(CompareDoubleEq,                       0, ORDN, ___, ___, ___)             \
+  V(CompareDoubleGt,                       0, ORDN, ___, ___, ___)             \
+  V(CompareDoubleLt,                       0, ORDN, ___, ___, ___)             \
+  V(CompareDoubleGe,                       0, ORDN, ___, ___, ___)             \
+  V(CompareDoubleLe,                       0, ORDN, ___, ___, ___)             \
 
-  // These bytecodes are only generated within the VM. Reassinging their
+  // These bytecodes are only generated within the VM. Reassigning their
   // opcodes is not a breaking change.
 #define INTERNAL_KERNEL_BYTECODES_LIST(V)                                      \
-  V(VMInternal_ImplicitGetter,             0, ___, ___, ___)                   \
-  V(VMInternal_ImplicitSetter,             0, ___, ___, ___)                   \
-  V(VMInternal_MethodExtractor,            0, ___, ___, ___)                   \
+  V(VMInternal_ImplicitGetter,             0, ORDN, ___, ___, ___)             \
+  V(VMInternal_ImplicitSetter,             0, ORDN, ___, ___, ___)             \
+  V(VMInternal_ImplicitStaticGetter,       0, ORDN, ___, ___, ___)             \
+  V(VMInternal_MethodExtractor,            0, ORDN, ___, ___, ___)             \
+  V(VMInternal_InvokeClosure,              0, ORDN, ___, ___, ___)             \
+  V(VMInternal_InvokeField,                0, ORDN, ___, ___, ___)             \
+  V(VMInternal_ForwardDynamicInvocation,   0, ORDN, ___, ___, ___)             \
+  V(VMInternal_NoSuchMethodDispatcher,     0, ORDN, ___, ___, ___)             \
+  V(VMInternal_ImplicitStaticClosure,      0, ORDN, ___, ___, ___)             \
+  V(VMInternal_ImplicitInstanceClosure,    0, ORDN, ___, ___, ___)             \
 
 #define KERNEL_BYTECODES_LIST(V)                                               \
   PUBLIC_KERNEL_BYTECODES_LIST(V)                                              \
@@ -539,122 +738,180 @@
 
 // clang-format on
 
-typedef uint32_t KBCInstr;
+typedef uint8_t KBCInstr;
 
 class KernelBytecode {
  public:
   // Magic value of bytecode files.
   static const intptr_t kMagicValue = 0x44424332;  // 'DBC2'
   // Minimum bytecode format version supported by VM.
-  static const intptr_t kMinSupportedBytecodeFormatVersion = 2;
+  static const intptr_t kMinSupportedBytecodeFormatVersion = 3;
   // Maximum bytecode format version supported by VM.
   // The range of supported versions should include version produced by bytecode
   // generator (currentBytecodeFormatVersion in pkg/vm/lib/bytecode/dbc.dart).
-  static const intptr_t kMaxSupportedBytecodeFormatVersion = 6;
+  static const intptr_t kMaxSupportedBytecodeFormatVersion = 9;
 
   enum Opcode {
-#define DECLARE_BYTECODE(name, encoding, op1, op2, op3) k##name,
+#define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name,
     KERNEL_BYTECODES_LIST(DECLARE_BYTECODE)
 #undef DECLARE_BYTECODE
   };
 
-  static const char* NameOf(KBCInstr instr) {
+  static const char* NameOf(Opcode op) {
     const char* names[] = {
-#define NAME(name, encoding, op1, op2, op3) #name,
+#define NAME(name, encoding, kind, op1, op2, op3) #name,
         KERNEL_BYTECODES_LIST(NAME)
 #undef NAME
     };
-    return names[DecodeOpcode(instr)];
+    return names[op];
   }
 
+  static const intptr_t kInstructionSize[];
+
   enum SpecialIndex {
     kExceptionSpecialIndex,
     kStackTraceSpecialIndex,
     kSpecialIndexCount
   };
 
-  static const intptr_t kOpShift = 0;
-  static const intptr_t kAShift = 8;
-  static const intptr_t kAMask = 0xFF;
-  static const intptr_t kBShift = 16;
-  static const intptr_t kBMask = 0xFF;
-  static const intptr_t kCShift = 24;
-  static const intptr_t kCMask = 0xFF;
-  static const intptr_t kDShift = 16;
-  static const intptr_t kDMask = 0xFFFF;
-  static const intptr_t kYShift = 24;
-  static const intptr_t kYMask = 0xFF;
-  static const intptr_t kTShift = 8;
+ private:
+  static const intptr_t kWideModifier = 1;
 
-  static KBCInstr Encode(Opcode op, uintptr_t a, uintptr_t b, uintptr_t c) {
-    ASSERT((a & kAMask) == a);
-    ASSERT((b & kBMask) == b);
-    ASSERT((c & kCMask) == c);
-    return op | (a << kAShift) | (b << kBShift) | (c << kCShift);
+  static_assert(kMinSupportedBytecodeFormatVersion < 7,
+                "Cleanup support for old bytecode format versions");
+  DART_FORCE_INLINE static bool IsOld(const KBCInstr* instr) {
+    return DecodeOpcode(instr) < kTrap;
   }
 
-  static KBCInstr Encode(Opcode op, uintptr_t a, uintptr_t d) {
-    ASSERT((a & kAMask) == a);
-    ASSERT((d & kDMask) == d);
-    return op | (a << kAShift) | (d << kDShift);
+  // Should be used only on instructions with wide variants.
+  DART_FORCE_INLINE static bool IsWide(const KBCInstr* instr) {
+    return ((DecodeOpcode(instr) & kWideModifier) != 0);
   }
 
-  static KBCInstr EncodeSigned(Opcode op, uintptr_t a, intptr_t x) {
-    ASSERT((a & kAMask) == a);
-    ASSERT((x << kDShift) >> kDShift == x);
-    return op | (a << kAShift) | (x << kDShift);
+ public:
+  DART_FORCE_INLINE static uint8_t DecodeA(const KBCInstr* bc) { return bc[1]; }
+
+  DART_FORCE_INLINE static uint8_t DecodeB(const KBCInstr* bc) { return bc[2]; }
+
+  DART_FORCE_INLINE static uint8_t DecodeC(const KBCInstr* bc) { return bc[3]; }
+
+  DART_FORCE_INLINE static uint32_t DecodeD(const KBCInstr* bc) {
+    if (IsOld(bc)) {
+      return static_cast<uint16_t>(bc[2]) | (static_cast<uint16_t>(bc[3]) << 8);
+    } else if (IsWide(bc)) {
+      return static_cast<uint32_t>(bc[1]) |
+             (static_cast<uint32_t>(bc[2]) << 8) |
+             (static_cast<uint32_t>(bc[3]) << 16) |
+             (static_cast<uint32_t>(bc[4]) << 24);
+    } else {
+      return bc[1];
+    }
   }
 
-  static KBCInstr EncodeSigned(Opcode op, intptr_t x) {
-    ASSERT((x << kAShift) >> kAShift == x);
-    return op | (x << kAShift);
+  DART_FORCE_INLINE static int32_t DecodeX(const KBCInstr* bc) {
+    if (IsOld(bc)) {
+      return static_cast<int16_t>(static_cast<uint16_t>(bc[2]) |
+                                  (static_cast<uint16_t>(bc[3]) << 8));
+    } else if (IsWide(bc)) {
+      return static_cast<int32_t>(static_cast<uint32_t>(bc[1]) |
+                                  (static_cast<uint32_t>(bc[2]) << 8) |
+                                  (static_cast<uint32_t>(bc[3]) << 16) |
+                                  (static_cast<uint32_t>(bc[4]) << 24));
+    } else {
+      return static_cast<int8_t>(bc[1]);
+    }
   }
 
-  static KBCInstr Encode(Opcode op) { return op; }
-
-  DART_FORCE_INLINE static uint8_t DecodeA(KBCInstr bc) {
-    return (bc >> kAShift) & kAMask;
+  DART_FORCE_INLINE static int32_t DecodeT(const KBCInstr* bc) {
+    if (IsOld(bc)) {
+      return static_cast<int32_t>((static_cast<uint32_t>(bc[1]) << 8) |
+                                  (static_cast<uint32_t>(bc[2]) << 16) |
+                                  (static_cast<uint32_t>(bc[3]) << 24)) >>
+             (8 - 2);
+    } else if (IsWide(bc)) {
+      return static_cast<int32_t>((static_cast<uint32_t>(bc[1]) << 8) |
+                                  (static_cast<uint32_t>(bc[2]) << 16) |
+                                  (static_cast<uint32_t>(bc[3]) << 24)) >>
+             8;
+    } else {
+      return static_cast<int8_t>(bc[1]);
+    }
   }
 
-  DART_FORCE_INLINE static uint8_t DecodeB(KBCInstr bc) {
-    return (bc >> kBShift) & kBMask;
+  DART_FORCE_INLINE static uint32_t DecodeE(const KBCInstr* bc) {
+    if (IsOld(bc)) {
+      return static_cast<uint16_t>(bc[2]) | (static_cast<uint16_t>(bc[3]) << 8);
+    } else if (IsWide(bc)) {
+      return static_cast<uint32_t>(bc[2]) |
+             (static_cast<uint32_t>(bc[3]) << 8) |
+             (static_cast<uint32_t>(bc[4]) << 16) |
+             (static_cast<uint32_t>(bc[5]) << 24);
+    } else {
+      return bc[2];
+    }
   }
 
-  DART_FORCE_INLINE static uint8_t DecodeC(KBCInstr bc) {
-    return (bc >> kCShift) & kCMask;
+  DART_FORCE_INLINE static int32_t DecodeY(const KBCInstr* bc) {
+    if (IsOld(bc)) {
+      return static_cast<int16_t>(static_cast<uint16_t>(bc[2]) |
+                                  (static_cast<uint16_t>(bc[3]) << 8));
+    } else if (IsWide(bc)) {
+      return static_cast<int32_t>(static_cast<uint32_t>(bc[2]) |
+                                  (static_cast<uint32_t>(bc[3]) << 8) |
+                                  (static_cast<uint32_t>(bc[4]) << 16) |
+                                  (static_cast<uint32_t>(bc[5]) << 24));
+    } else {
+      return static_cast<int8_t>(bc[2]);
+    }
   }
 
-  DART_FORCE_INLINE static uint16_t DecodeD(KBCInstr bc) {
-    return (bc >> kDShift) & kDMask;
+  DART_FORCE_INLINE static uint8_t DecodeF(const KBCInstr* bc) {
+    if (IsOld(bc)) {
+      return bc[1];
+    } else if (IsWide(bc)) {
+      return bc[5];
+    } else {
+      return bc[2];
+    }
   }
 
-  DART_FORCE_INLINE static int16_t DecodeX(KBCInstr bc) {
-    return static_cast<int16_t>((bc >> kDShift) & kDMask);
+  DART_FORCE_INLINE static Opcode DecodeOpcode(const KBCInstr* bc) {
+    return static_cast<Opcode>(bc[0]);
   }
 
-  DART_FORCE_INLINE static int32_t DecodeT(KBCInstr bc) {
-    return static_cast<int32_t>(bc) >> kTShift;
+  DART_FORCE_INLINE static const KBCInstr* Next(const KBCInstr* bc) {
+    return bc + kInstructionSize[DecodeOpcode(bc)];
   }
 
-  DART_FORCE_INLINE static Opcode DecodeOpcode(KBCInstr bc) {
-    return static_cast<Opcode>(bc & 0xFF);
-  }
-
-  DART_FORCE_INLINE static bool IsTrap(KBCInstr instr) {
-    return DecodeOpcode(instr) == KernelBytecode::kTrap;
-  }
-
-  DART_FORCE_INLINE static bool IsJumpOpcode(KBCInstr instr) {
+  DART_FORCE_INLINE static bool IsJumpOpcode(const KBCInstr* instr) {
     switch (DecodeOpcode(instr)) {
+      case KernelBytecode::kJump_Old:
+      case KernelBytecode::kJumpIfNoAsserts_Old:
+      case KernelBytecode::kJumpIfNotZeroTypeArgs_Old:
+      case KernelBytecode::kJumpIfEqStrict_Old:
+      case KernelBytecode::kJumpIfNeStrict_Old:
+      case KernelBytecode::kJumpIfTrue_Old:
+      case KernelBytecode::kJumpIfFalse_Old:
+      case KernelBytecode::kJumpIfNull_Old:
+      case KernelBytecode::kJumpIfNotNull_Old:
       case KernelBytecode::kJump:
+      case KernelBytecode::kJump_Wide:
       case KernelBytecode::kJumpIfNoAsserts:
+      case KernelBytecode::kJumpIfNoAsserts_Wide:
       case KernelBytecode::kJumpIfNotZeroTypeArgs:
+      case KernelBytecode::kJumpIfNotZeroTypeArgs_Wide:
       case KernelBytecode::kJumpIfEqStrict:
+      case KernelBytecode::kJumpIfEqStrict_Wide:
       case KernelBytecode::kJumpIfNeStrict:
+      case KernelBytecode::kJumpIfNeStrict_Wide:
       case KernelBytecode::kJumpIfTrue:
+      case KernelBytecode::kJumpIfTrue_Wide:
       case KernelBytecode::kJumpIfFalse:
+      case KernelBytecode::kJumpIfFalse_Wide:
       case KernelBytecode::kJumpIfNull:
+      case KernelBytecode::kJumpIfNull_Wide:
       case KernelBytecode::kJumpIfNotNull:
+      case KernelBytecode::kJumpIfNotNull_Wide:
         return true;
 
       default:
@@ -662,15 +919,93 @@
     }
   }
 
-  DART_FORCE_INLINE static bool IsCallOpcode(KBCInstr instr) {
+  DART_FORCE_INLINE static bool IsLoadConstantOpcode(const KBCInstr* instr) {
     switch (DecodeOpcode(instr)) {
-      case KernelBytecode::kIndirectStaticCall:
+      case KernelBytecode::kLoadConstant:
+      case KernelBytecode::kLoadConstant_Wide:
+      case KernelBytecode::kLoadConstant_Old:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  DART_FORCE_INLINE static bool IsCheckStackOpcode(const KBCInstr* instr) {
+    switch (DecodeOpcode(instr)) {
+      case KernelBytecode::kCheckStack:
+      case KernelBytecode::kCheckStack_Old:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  DART_FORCE_INLINE static bool IsEntryOptionalOpcode(const KBCInstr* instr) {
+    switch (DecodeOpcode(instr)) {
+      case KernelBytecode::kEntryOptional:
+      case KernelBytecode::kEntryOptional_Old:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  DART_FORCE_INLINE static bool IsFrameOpcode(const KBCInstr* instr) {
+    switch (DecodeOpcode(instr)) {
+      case KernelBytecode::kFrame:
+      case KernelBytecode::kFrame_Wide:
+      case KernelBytecode::kFrame_Old:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  DART_FORCE_INLINE static bool IsSetFrameOpcode(const KBCInstr* instr) {
+    switch (DecodeOpcode(instr)) {
+      case KernelBytecode::kSetFrame:
+      case KernelBytecode::kSetFrame_Old:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  DART_FORCE_INLINE static bool IsCallOpcode_Old(const KBCInstr* instr) {
+    switch (DecodeOpcode(instr)) {
+      case KernelBytecode::kDirectCall_Old:
+      case KernelBytecode::kInterfaceCall_Old:
+      case KernelBytecode::kUncheckedInterfaceCall_Old:
+      case KernelBytecode::kDynamicCall_Old:
+        return true;
+
+      default:
+        return false;
+    }
+  }
+
+  DART_FORCE_INLINE static bool IsNativeCallOpcode(const KBCInstr* instr) {
+    switch (DecodeOpcode(instr)) {
+      case KernelBytecode::kNativeCall:
+      case KernelBytecode::kNativeCall_Wide:
+      case KernelBytecode::kNativeCall_Old:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  // The interpreter and this function must agree on the opcodes.
+  DART_FORCE_INLINE static bool IsDebugBreakCheckedOpcode(
+      const KBCInstr* instr) {
+    switch (DecodeOpcode(instr)) {
+      case KernelBytecode::kCheckStack:
+      case KernelBytecode::kDirectCall:
       case KernelBytecode::kInterfaceCall:
       case KernelBytecode::kUncheckedInterfaceCall:
       case KernelBytecode::kDynamicCall:
-      case KernelBytecode::kDirectCall:
+      case KernelBytecode::kReturnTOS:
         return true;
-
       default:
         return false;
     }
@@ -678,29 +1013,44 @@
 
   static const uint8_t kNativeCallToGrowableListArgc = 2;
 
-  DART_FORCE_INLINE static uint8_t DecodeArgc(KBCInstr call) {
-    if (DecodeOpcode(call) == KernelBytecode::kNativeCall) {
+  DART_FORCE_INLINE static uint8_t DecodeArgc_Old(const KBCInstr* ret_addr) {
+    const intptr_t kOldInstructionSize = 4;
+    const KBCInstr* call = ret_addr - kOldInstructionSize;
+    ASSERT(IsOld(call));
+    if (DecodeOpcode(call) == KernelBytecode::kNativeCall_Old) {
       // The only NativeCall redirecting to a bytecode function is the call
       // to new _GrowableList<E>(0).
       return kNativeCallToGrowableListArgc;
     }
-    ASSERT(IsCallOpcode(call));
-    return (call >> 8) & 0xFF;
+    ASSERT(IsCallOpcode_Old(call));
+    return DecodeA(call);
   }
 
-  static KBCInstr At(uword pc) { return *reinterpret_cast<KBCInstr*>(pc); }
+  // Returns a fake return address which points after the 2-argument
+  // bytecode call, followed by ReturnTOS instructions.
+  static const KBCInstr* GetNativeCallToGrowableListReturnTrampoline();
+
+  DART_FORCE_INLINE static uint8_t DecodeArgc(const KBCInstr* ret_addr) {
+    // All call instructions have DF encoding, with argc being the last byte
+    // regardless of whether the wide variant is used or not.
+    return ret_addr[-1];
+  }
 
   // Converts bytecode PC into an offset.
-  // For return addresses used in PcDescriptors, PC is also advanced to the
-  // next instruction.
+  // For return addresses used in PcDescriptors, PC is also augmented by 1.
+  // TODO(regis): Eliminate this correction.
   static intptr_t BytecodePcToOffset(uint32_t pc, bool is_return_address) {
-    return sizeof(KBCInstr) * (pc + (is_return_address ? 1 : 0));
+    return pc + (is_return_address ? 1 : 0);
   }
 
   static uint32_t OffsetToBytecodePc(intptr_t offset, bool is_return_address) {
-    return (offset / sizeof(KBCInstr)) - (is_return_address ? 1 : 0);
+    return offset - (is_return_address ? 1 : 0);
   }
 
+  static void GetVMInternalBytecodeInstructions(Opcode opcode,
+                                                const KBCInstr** instructions,
+                                                intptr_t* instructions_size);
+
  private:
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(KernelBytecode);
diff --git a/runtime/vm/constants_x64.cc b/runtime/vm/constants_x64.cc
index 8d80a33..71b43d6 100644
--- a/runtime/vm/constants_x64.cc
+++ b/runtime/vm/constants_x64.cc
@@ -7,6 +7,14 @@
 
 namespace arch_x64 {
 
+const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+    "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+    "r8",  "r9",  "r10", "r11", "r12", "r13", "thr", "pp"};
+
+const char* fpu_reg_names[kNumberOfXmmRegisters] = {
+    "xmm0", "xmm1", "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
+    "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"};
+
 #if defined(_WIN64)
 const Register CallingConventions::ArgumentRegisters[] = {
     CallingConventions::kArg1Reg, CallingConventions::kArg2Reg,
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index c9eea38..29a871a 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -90,17 +90,12 @@
 
 // Architecture independent aliases.
 typedef XmmRegister FpuRegister;
-const FpuRegister FpuTMP = XMM0;
+const FpuRegister FpuTMP = XMM15;
 const int kNumberOfFpuRegisters = kNumberOfXmmRegisters;
 const FpuRegister kNoFpuRegister = kNoXmmRegister;
 
-static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
-    "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
-    "r8",  "r9",  "r10", "r11", "r12", "r13", "thr", "pp"};
-
-static const char* fpu_reg_names[kNumberOfXmmRegisters] = {
-    "xmm0", "xmm1", "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
-    "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"};
+extern const char* cpu_reg_names[kNumberOfCpuRegisters];
+extern const char* fpu_reg_names[kNumberOfXmmRegisters];
 
 enum RexBits {
   REX_NONE = 0,
@@ -269,6 +264,7 @@
   static constexpr Register kFirstCalleeSavedCpuReg = RBX;
   static constexpr Register kFirstNonArgumentRegister = RAX;
   static constexpr Register kSecondNonArgumentRegister = RBX;
+  static constexpr Register kStackPointerRegister = SPREG;
 
   COMPILE_ASSERT(((R(kFirstCalleeSavedCpuReg)) & kCalleeSaveCpuRegisters) != 0);
 
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index ffb115e..bf929e9 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -6,6 +6,8 @@
 
 #include "vm/clustered_snapshot.h"
 #include "vm/code_observers.h"
+#include "vm/compiler/runtime_offsets_extracted.h"
+#include "vm/compiler/runtime_offsets_list.h"
 #include "vm/cpu.h"
 #include "vm/dart_api_state.h"
 #include "vm/dart_entry.h"
@@ -22,6 +24,7 @@
 #include "vm/malloc_hooks.h"
 #include "vm/message_handler.h"
 #include "vm/metrics.h"
+#include "vm/native_entry.h"
 #include "vm/object.h"
 #include "vm/object_id_ring.h"
 #include "vm/object_store.h"
@@ -84,36 +87,40 @@
 };
 
 static void CheckOffsets() {
+  // These offsets are embedded in precompiled instructions. We need the
+  // compiler and the runtime to agree.
   bool ok = true;
 #define CHECK_OFFSET(expr, offset)                                             \
   if ((expr) != (offset)) {                                                    \
-    OS::PrintErr("%s got %" Pd " expected %" Pd "\n", #expr, (expr),           \
+    OS::PrintErr("%s got %" Pd ", %s expected %" Pd "\n", #expr,               \
+                 static_cast<intptr_t>(expr), #offset,                         \
                  static_cast<intptr_t>(offset));                               \
     ok = false;                                                                \
   }
 
-#if defined(TARGET_ARCH_ARM)
-  // These offsets are embedded in precompiled instructions. We need simarm
-  // (compiler) and arm (runtime) to agree.
-  CHECK_OFFSET(Thread::stack_limit_offset(), 36);
-  CHECK_OFFSET(Thread::object_null_offset(), 96);
-  CHECK_OFFSET(SingleTargetCache::upper_limit_offset(), 14);
-  CHECK_OFFSET(Isolate::object_store_offset(), 20);
-  NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 168));
-#endif
-#if defined(TARGET_ARCH_ARM64)
-  // These offsets are embedded in precompiled instructions. We need simarm64
-  // (compiler) and arm64 (runtime) to agree.
-  CHECK_OFFSET(Thread::stack_limit_offset(), 72);
-  CHECK_OFFSET(Thread::object_null_offset(), 184);
-  CHECK_OFFSET(SingleTargetCache::upper_limit_offset(), 26);
-  CHECK_OFFSET(Isolate::object_store_offset(), 40);
-  NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 288));
-#endif
+#define CHECK_FIELD(Class, Name) CHECK_OFFSET(Class::Name(), Class##_##Name)
+#define CHECK_ARRAY(Class, Name)                                               \
+  CHECK_OFFSET(Class::ArrayLayout::elements_start_offset(),                    \
+               Class##_elements_start_offset)                                  \
+  CHECK_OFFSET(Class::ArrayLayout::kElementSize, Class##_element_size)
+#define CHECK_ARRAY_STRUCTFIELD(Class, Name, ElementOffsetName, FieldOffset)
+#define CHECK_SIZEOF(Class, Name, What)                                        \
+  CHECK_OFFSET(sizeof(What), Class##_##Name)
+#define CHECK_RANGE(Class, Name, Type, First, Last, Filter)
+#define CHECK_CONSTANT(Class, Name) CHECK_OFFSET(Class::Name, Class##_##Name)
+
+  OFFSETS_LIST(CHECK_FIELD, CHECK_ARRAY, CHECK_ARRAY_STRUCTFIELD, CHECK_SIZEOF,
+               CHECK_RANGE, CHECK_CONSTANT, NOT_IN_PRECOMPILED_RUNTIME)
 
   if (!ok) {
     FATAL("CheckOffsets failed.");
   }
+#undef CHECK_FIELD
+#undef CHECK_ARRAY
+#undef CHECK_ARRAY_STRUCTFIELD
+#undef CHECK_SIZEOF
+#undef CHECK_RANGE
+#undef CHECK_CONSTANT
 #undef CHECK_OFFSET
 }
 
@@ -379,8 +386,21 @@
 void Dart::WaitForApplicationIsolateShutdown() {
   ASSERT(!Isolate::creation_enabled_);
   MonitorLocker ml(Isolate::isolates_list_monitor_);
+  intptr_t num_attempts = 0;
   while (HasApplicationIsolateLocked()) {
-    ml.Wait();
+    Monitor::WaitResult retval = ml.Wait(1000);
+    if (retval == Monitor::kTimedOut) {
+      num_attempts += 1;
+      if (num_attempts > 10) {
+        for (Isolate* isolate = Isolate::isolates_list_head_; isolate != NULL;
+             isolate = isolate->next_) {
+          if (!Isolate::IsVMInternalIsolate(isolate)) {
+            OS::PrintErr("Attempt:%" Pd " waiting for isolate %s to check in\n",
+                         num_attempts, isolate->name_);
+          }
+        }
+      }
+    }
   }
 }
 
@@ -388,9 +408,19 @@
 void Dart::WaitForIsolateShutdown() {
   ASSERT(!Isolate::creation_enabled_);
   MonitorLocker ml(Isolate::isolates_list_monitor_);
+  intptr_t num_attempts = 0;
   while ((Isolate::isolates_list_head_ != NULL) &&
          (Isolate::isolates_list_head_->next_ != NULL)) {
-    ml.Wait();
+    Monitor::WaitResult retval = ml.Wait(1000);
+    if (retval == Monitor::kTimedOut) {
+      num_attempts += 1;
+      if (num_attempts > 10) {
+        for (Isolate* isolate = Isolate::isolates_list_head_; isolate != NULL;
+             isolate = isolate->next_)
+          OS::PrintErr("Attempt:%" Pd " waiting for isolate %s to check in\n",
+                       num_attempts, isolate->name_);
+      }
+    }
   }
   ASSERT(Isolate::isolates_list_head_ == Dart::vm_isolate());
 }
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 0f50b62..4ebdac9 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -17,9 +17,12 @@
 #include "vm/dart_api_state.h"
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
+#include "vm/dwarf.h"
+#include "vm/elf.h"
 #if !defined(DART_PRECOMPILED_RUNTIME)
 #include "vm/kernel_loader.h"
 #endif
+#include "platform/unicode.h"
 #include "vm/compiler/aot/precompiler.h"
 #include "vm/exceptions.h"
 #include "vm/flags.h"
@@ -32,6 +35,7 @@
 #include "vm/message.h"
 #include "vm/message_handler.h"
 #include "vm/native_entry.h"
+#include "vm/native_symbol.h"
 #include "vm/object.h"
 #include "vm/object_store.h"
 #include "vm/os.h"
@@ -49,7 +53,6 @@
 #include "vm/symbols.h"
 #include "vm/tags.h"
 #include "vm/thread_registry.h"
-#include "vm/unicode.h"
 #include "vm/uri.h"
 #include "vm/version.h"
 
@@ -271,17 +274,6 @@
                        current_func, field_count, num_fields);
 }
 
-Heap::Space SpaceForExternal(Thread* thread, intptr_t size) {
-  Heap* heap = thread->heap();
-  // If 'size' would be a significant fraction of new space, then use old.
-  static const int kExtNewRatio = 16;
-  if (size > (heap->CapacityInWords(Heap::kNew) * kWordSize) / kExtNewRatio) {
-    return Heap::kOld;
-  } else {
-    return Heap::kNew;
-  }
-}
-
 static RawObject* Send0Arg(const Instance& receiver, const String& selector) {
   const intptr_t kTypeArgsLen = 0;
   const intptr_t kNumArgs = 1;
@@ -1092,8 +1084,10 @@
     }
     return reinterpret_cast<Dart_Isolate>(NULL);
   }
+
+  Thread* T = Thread::Current();
+  bool success = false;
   {
-    Thread* T = Thread::Current();
     StackZone zone(T);
     HANDLESCOPE(T);
     // We enter an API scope here as InitializeIsolate could compile some
@@ -1111,25 +1105,27 @@
         Library::CheckFunctionFingerprints();
       }
 #endif  // defined(DART_NO_SNAPSHOT) && !defined(PRODUCT).
-      // We exit the API scope entered above.
-      T->ExitApiScope();
-      // A Thread structure has been associated to the thread, we do the
-      // safepoint transition explicitly here instead of using the
-      // TransitionXXX scope objects as the reverse transition happens
-      // outside this scope in Dart_ShutdownIsolate/Dart_ExitIsolate.
-      T->set_execution_state(Thread::kThreadInNative);
-      T->EnterSafepoint();
-      if (error != NULL) {
-        *error = NULL;
-      }
-      return Api::CastIsolate(I);
-    }
-    if (error != NULL) {
+      success = true;
+    } else if (error != NULL) {
       *error = strdup(error_obj.ToErrorCString());
     }
     // We exit the API scope entered above.
     T->ExitApiScope();
   }
+
+  if (success) {
+    // A Thread structure has been associated to the thread, we do the
+    // safepoint transition explicitly here instead of using the
+    // TransitionXXX scope objects as the reverse transition happens
+    // outside this scope in Dart_ShutdownIsolate/Dart_ExitIsolate.
+    T->set_execution_state(Thread::kThreadInNative);
+    T->EnterSafepoint();
+    if (error != NULL) {
+      *error = NULL;
+    }
+    return Api::CastIsolate(I);
+  }
+
   Dart::ShutdownIsolate();
   return reinterpret_cast<Dart_Isolate>(NULL);
 }
@@ -1227,6 +1223,15 @@
                               static_cast<int64_t>(I->main_port()), I->name()));
 }
 
+DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate) {
+  if (isolate == NULL) {
+    FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
+  }
+  Isolate* I = reinterpret_cast<Isolate*>(isolate);
+  int64_t main_port = static_cast<int64_t>(I->main_port());
+  return OS::SCreate(NULL, "isolates/%" Pd64, main_port);
+}
+
 DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate) {
   CHECK_NO_ISOLATE(Isolate::Current());
   // TODO(16615): Validate isolate parameter.
@@ -1280,6 +1285,12 @@
   os_thread->EnableThreadInterrupts();
 }
 
+DART_EXPORT void Dart_AddSymbols(const char* dso_name,
+                                 void* buffer,
+                                 intptr_t buffer_size) {
+  NativeSymbolResolver::AddSymbols(dso_name, buffer, buffer_size);
+}
+
 DART_EXPORT bool Dart_WriteProfileToTimeline(Dart_Port main_port,
                                              char** error) {
 #if defined(PRODUCT)
@@ -1294,12 +1305,18 @@
 
   const intptr_t kBufferLength = 512;
   char method[kBufferLength];
+
+  // clang-format off
   intptr_t method_length = snprintf(method, kBufferLength, "{"
       "\"jsonrpc\": \"2.0\","
       "\"method\": \"_writeCpuProfileTimeline\","
       "\"id\": \"\","
-      "\"params\": {\"isolateId\": \"isolates/%" Pd64 "\"}"
-    "}", main_port);
+      "\"params\": {"
+      "  \"isolateId\": \"isolates/%" Pd64 "\","
+      "  \"tags\": \"None\""
+      "}"
+  "}", main_port);
+  // clang-format on
   ASSERT(method_length <= kBufferLength);
 
   char* response = NULL;
@@ -1761,7 +1778,7 @@
   RawObject* raw_obj = Api::UnwrapHandle(handle);
   if (ApiObjectConverter::CanConvert(raw_obj)) {
     return PortMap::PostMessage(
-        new Message(port_id, raw_obj, Message::kNormalPriority));
+        Message::New(port_id, raw_obj, Message::kNormalPriority));
   }
 
   const Object& object = Object::Handle(Z, raw_obj);
@@ -2380,7 +2397,7 @@
     return Api::NewError(
         "function_name must be the name of a regular function.");
   }
-  func ^= func.ImplicitClosureFunction();
+  func = func.ImplicitClosureFunction();
   if (func.IsNull()) {
     return Dart_Null();
   }
@@ -2499,7 +2516,7 @@
   return Api::NewHandle(
       T,
       String::NewExternal(latin1_array, length, peer, external_allocation_size,
-                          callback, SpaceForExternal(T, length)));
+                          callback, T->heap()->SpaceForExternal(length)));
 }
 
 DART_EXPORT Dart_Handle
@@ -2521,7 +2538,7 @@
   return Api::NewHandle(
       T,
       String::NewExternal(utf16_array, length, peer, external_allocation_size,
-                          callback, SpaceForExternal(T, bytes)));
+                          callback, T->heap()->SpaceForExternal(bytes)));
 }
 
 DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object,
@@ -3405,8 +3422,9 @@
   Zone* zone = thread->zone();
   intptr_t bytes = length * ExternalTypedData::ElementSizeInBytes(cid);
   const ExternalTypedData& result = ExternalTypedData::Handle(
-      zone, ExternalTypedData::New(cid, reinterpret_cast<uint8_t*>(data),
-                                   length, SpaceForExternal(thread, bytes)));
+      zone,
+      ExternalTypedData::New(cid, reinterpret_cast<uint8_t*>(data), length,
+                             thread->heap()->SpaceForExternal(bytes)));
   if (callback != NULL) {
     AllocateFinalizableHandle(thread, result, peer, external_allocation_size,
                               callback);
@@ -3700,10 +3718,10 @@
     const auto& view_obj = Api::UnwrapTypedDataViewHandle(Z, object);
     ASSERT(!view_obj.IsNull());
     Smi& val = Smi::Handle();
-    val ^= view_obj.length();
+    val = view_obj.length();
     length = val.Value();
     size_in_bytes = length * TypedDataView::ElementSizeInBytes(class_id);
-    val ^= view_obj.offset_in_bytes();
+    val = view_obj.offset_in_bytes();
     intptr_t offset_in_bytes = val.Value();
     const auto& obj = Instance::Handle(view_obj.typed_data());
     T->IncrementNoSafepointScopeDepth();
@@ -5153,7 +5171,7 @@
           number_of_type_arguments, array.Length());
     }
     // Set up the type arguments array.
-    type_args_obj ^= TypeArguments::New(num_expected_type_arguments);
+    type_args_obj = TypeArguments::New(num_expected_type_arguments);
     AbstractType& type_arg = AbstractType::Handle();
     for (intptr_t i = 0; i < number_of_type_arguments; i++) {
       type_arg ^= array.At(i);
@@ -5515,7 +5533,7 @@
                      const char* package_config) {
   API_TIMELINE_DURATION(Thread::Current());
 
-  Dart_KernelCompilationResult result;
+  Dart_KernelCompilationResult result = {};
 #if defined(DART_PRECOMPILED_RUNTIME)
   result.status = Dart_KernelCompilationStatus_Unknown;
   result.error = strdup("Dart_CompileToKernel is unsupported.");
@@ -5547,7 +5565,7 @@
                             const char* package_config,
                             const char* multiroot_filepaths,
                             const char* multiroot_scheme) {
-  Dart_KernelCompilationResult result;
+  Dart_KernelCompilationResult result = {};
 #if defined(DART_PRECOMPILED_RUNTIME)
   result.status = Dart_KernelCompilationStatus_Unknown;
   result.error = strdup("Dart_CompileSourcesToKernel is unsupported.");
@@ -5569,7 +5587,7 @@
 }
 
 DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies() {
-  Dart_KernelCompilationResult result;
+  Dart_KernelCompilationResult result = {};
 #if defined(DART_PRECOMPILED_RUNTIME)
   result.status = Dart_KernelCompilationStatus_Unknown;
   result.error = strdup("Dart_KernelListDependencies is unsupported.");
@@ -5938,6 +5956,9 @@
   return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
 #else
   DARTSCOPE(Thread::Current());
+  // Prevent background compiler from running while code is being cleared and
+  // adding new code.
+  BackgroundCompiler::Stop(Isolate::Current());
   // We don't have mechanisms to change class-ids that are embedded in code and
   // ICData.
   ClassFinalizer::ClearAllCode();
@@ -6030,10 +6051,11 @@
   CHECK_NULL(callback);
 
   TIMELINE_DURATION(T, Isolate, "WriteVMAOTSnapshot");
-  AssemblyImageWriter image_writer(T, callback, callback_data, NULL, NULL);
-  uint8_t* vm_snapshot_data_buffer = NULL;
-  FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer, NULL,
-                            ApiReallocate, &image_writer, NULL);
+  AssemblyImageWriter image_writer(T, callback, callback_data, nullptr,
+                                   nullptr);
+  uint8_t* vm_snapshot_data_buffer = nullptr;
+  FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
+                            nullptr, ApiReallocate, &image_writer, nullptr);
 
   writer.WriteFullSnapshot();
 
@@ -6042,6 +6064,67 @@
 }
 
 DART_EXPORT Dart_Handle
+Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback,
+                               void* callback_data,
+                               bool strip) {
+#if defined(TARGET_ARCH_IA32)
+  return Api::NewError("AOT compilation is not supported on IA32.");
+#elif defined(TARGET_ARCH_DBC)
+  return Api::NewError("AOT compilation is not supported on DBC.");
+#elif defined(TARGET_OS_WINDOWS)
+  return Api::NewError("Windows cannot load ELF.");
+#elif defined(TARGET_OS_MACOS)
+  return Api::NewError("macOS/iOS cannot load ELF.");
+#elif !defined(DART_PRECOMPILER)
+  return Api::NewError(
+      "This VM was built without support for AOT compilation.");
+#else
+  DARTSCOPE(Thread::Current());
+  API_TIMELINE_DURATION(T);
+
+  uint8_t* vm_snapshot_data_buffer = nullptr;
+  uint8_t* vm_snapshot_instructions_buffer = nullptr;
+  uint8_t* isolate_snapshot_data_buffer = nullptr;
+  uint8_t* isolate_snapshot_instructions_buffer = nullptr;
+
+  NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
+                                            "WriteAppAOTSnapshot"));
+  StreamingWriteStream elf_stream(2 * MB, callback, callback_data);
+
+  Elf* elf = new (Z) Elf(Z, &elf_stream);
+  Dwarf* dwarf = nullptr;
+  if (!strip) {
+    dwarf = new (Z) Dwarf(Z, nullptr, elf);
+  }
+
+  BlobImageWriter vm_image_writer(T, &vm_snapshot_instructions_buffer,
+                                  ApiReallocate, /* initial_size= */ 2 * MB,
+                                  nullptr, nullptr, nullptr, elf, dwarf);
+  BlobImageWriter isolate_image_writer(
+      T, &isolate_snapshot_instructions_buffer, ApiReallocate,
+      /* initial_size= */ 2 * MB, /* shared_data_image= */ nullptr,
+      /* shared_instructions_image= */ nullptr, nullptr, elf, dwarf);
+  FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
+                            &isolate_snapshot_data_buffer, ApiReallocate,
+                            &vm_image_writer, &isolate_image_writer);
+
+  writer.WriteFullSnapshot();
+  elf->AddROData("_kDartVmSnapshotData", vm_snapshot_data_buffer,
+                 writer.VmIsolateSnapshotSize());
+  elf->AddROData("_kDartIsolateSnapshotData", isolate_snapshot_data_buffer,
+                 writer.IsolateSnapshotSize());
+  if (!strip) {
+    // TODO(rmacnak): Generate .debug_frame / .eh_frame / .arm.exidx to
+    // provide unwinding information.
+    dwarf->Write();
+  }
+  elf->Finalize();
+
+  return Api::Success();
+#endif
+}
+
+DART_EXPORT Dart_Handle
 Dart_CreateAppAOTSnapshotAsBlobs(uint8_t** vm_snapshot_data_buffer,
                                  intptr_t* vm_snapshot_data_size,
                                  uint8_t** vm_snapshot_instructions_buffer,
@@ -6133,7 +6216,7 @@
   ASSERT(!func.IsNull());
   Code& code = Code::Handle(zone);
   if (func.HasCode()) {
-    code ^= func.CurrentCode();
+    code = func.CurrentCode();
     ASSERT(!code.IsNull());
     code.DisableDartCode();
   }
@@ -6141,10 +6224,10 @@
   func.ClearICDataArray();
   ASSERT(!func.HasCode());
 
-  func ^= reg_exp_class.LookupFunctionAllowPrivate(execute_match_sticky_name);
+  func = reg_exp_class.LookupFunctionAllowPrivate(execute_match_sticky_name);
   ASSERT(!func.IsNull());
   if (func.HasCode()) {
-    code ^= func.CurrentCode();
+    code = func.CurrentCode();
     ASSERT(!code.IsNull());
     code.DisableDartCode();
   }
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index f2cd2e8..ca74fa7 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -297,8 +297,15 @@
 
   static bool IsFfiEnabled() {
     // dart:ffi is not implemented for the following configurations
-#if defined(TARGET_ARCH_DBC)
-    // https://github.com/dart-lang/sdk/issues/35773 DBC
+#if defined(TARGET_ARCH_DBC) && !defined(ARCH_IS_64_BIT)
+    // TODO(36809): Support SimDBC32.
+    return false;
+#elif defined(TARGET_ARCH_DBC) && !defined(HOST_ARCH_X64)
+    // TODO(35773): Support ia32, arm64, and arm.
+    return false;
+#elif defined(TARGET_ARCH_DBC) && defined(HOST_ARCH_X64) &&                    \
+    defined(HOST_OS_WINDOWS)
+    // TODO(35773): Support x64 Windows.
     return false;
 #elif defined(TARGET_ARCH_ARM) &&                                              \
     !(defined(TARGET_OS_ANDROID) || defined(TARGET_OS_MACOS_IOS))
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 406901a..e500239 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3469,8 +3469,8 @@
   ApiLocalScope* scope = thread->api_top_scope();
   Dart_Handle handles[300];
   {
-    StackZone zone(thread);
     TransitionNativeToVM transition1(thread);
+    StackZone zone(thread);
     HANDLESCOPE(thread);
     Smi& val = Smi::Handle();
     TransitionVMToNative transition2(thread);
@@ -3629,62 +3629,21 @@
   return Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
 }
 
-VM_UNIT_TEST_CASE(DartAPI_IsolateSetCheckedMode) {
-  const char* kScriptChars =
-      "int bad1() {\n"
-      "  int foo = 'string';\n"
-      "  return foo;\n"
-      "}\n"
-      "\n"
-      "int good1() {\n"
-      "  int five = 5;\n"
-      "  return five;"
-      "}\n";
-
-  // Create an isolate with checked mode flags.
-  Dart_IsolateFlags api_flags;
-  Isolate::FlagsInitialize(&api_flags);
-  api_flags.enable_asserts = true;
-  char* err;
-  Dart_Isolate isolate =
-      Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data,
-                         bin::core_isolate_snapshot_instructions, NULL, NULL,
-                         &api_flags, NULL, &err);
-  if (isolate == NULL) {
-    OS::PrintErr("Creation of isolate failed '%s'\n", err);
-    free(err);
-  }
-  EXPECT(isolate != NULL);
-
-  {
-    Dart_Handle result;
-    Dart_EnterScope();
-    Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
-    EXPECT_VALID(lib);
-    result = Dart_FinalizeLoading(false);
-    EXPECT_VALID(result);
-    result = Dart_Invoke(lib, NewString("bad1"), 0, NULL);
-    EXPECT_ERROR(result,
-                 "Unhandled exception:\n"
-                 "type 'String' is not a subtype of type 'int' of 'foo'");
-
-    result = Dart_Invoke(lib, NewString("good1"), 0, NULL);
-    EXPECT_VALID(result);
-    Dart_ExitScope();
-  }
-
-  EXPECT(isolate != NULL);
-
-  // Shutdown the isolate.
-  Dart_ShutdownIsolate();
-}
-
 TEST_CASE(DartAPI_DebugName) {
   Dart_Handle debug_name = Dart_DebugName();
   EXPECT_VALID(debug_name);
   EXPECT(Dart_IsString(debug_name));
 }
 
+TEST_CASE(DartAPI_IsolateServiceID) {
+  Dart_Isolate isolate = Dart_CurrentIsolate();
+  const char* id = Dart_IsolateServiceId(isolate);
+  EXPECT(id != NULL);
+  int64_t main_port = Dart_GetMainPortId();
+  EXPECT_STREQ(ZONE_STR("isolates/%" Pd64, main_port), id);
+  free(const_cast<char*>(id));
+}
+
 static void MyMessageNotifyCallback(Dart_Isolate dest_isolate) {}
 
 VM_UNIT_TEST_CASE(DartAPI_SetMessageCallbacks) {
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index 88c6c92..ee4aa1d 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -3,10 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/dart_api_message.h"
+#include "platform/unicode.h"
 #include "vm/object.h"
 #include "vm/snapshot_ids.h"
 #include "vm/symbols.h"
-#include "vm/unicode.h"
 
 namespace dart {
 
@@ -892,7 +892,7 @@
   Dart_CObject_Type type = object->type;
   if (type == Dart_CObject_kArray) {
     const intptr_t array_length = object->value.as_array.length;
-    if (array_length < 0 || array_length > Array::kMaxElements) {
+    if (!Array::IsValidLength(array_length)) {
       return false;
     }
 
@@ -925,7 +925,7 @@
   Dart_CObject_Type type = object->type;
   if (type == Dart_CObject_kArray) {
     const intptr_t array_length = object->value.as_array.length;
-    if (array_length < 0 || array_length > Array::kMaxElements) {
+    if (!Array::IsValidLength(array_length)) {
       return false;
     }
     // Write out the serialization header value for this object.
@@ -948,7 +948,7 @@
       static_cast<Dart_CObject_Type>(object->type & kDartCObjectTypeMask);
   ASSERT(type == Dart_CObject_kArray);
   const intptr_t array_length = object->value.as_array.length;
-  if (array_length < 0 || array_length > Array::kMaxElements) {
+  if (!Array::IsValidLength(array_length)) {
     return false;
   }
 
@@ -1132,14 +1132,15 @@
   return true;
 }
 
-Message* ApiMessageWriter::WriteCMessage(Dart_CObject* object,
-                                         Dart_Port dest_port,
-                                         Message::Priority priority) {
+std::unique_ptr<Message> ApiMessageWriter::WriteCMessage(
+    Dart_CObject* object,
+    Dart_Port dest_port,
+    Message::Priority priority) {
   bool success = WriteCObject(object);
   if (!success) {
     UnmarkAllCObjects(object);
     free(buffer());
-    return NULL;
+    return nullptr;
   }
 
   // Write out all objects that were added to the forward list and have
@@ -1150,15 +1151,15 @@
     if (!success) {
       UnmarkAllCObjects(object);
       free(buffer());
-      return NULL;
+      return nullptr;
     }
   }
 
   UnmarkAllCObjects(object);
   MessageFinalizableData* finalizable_data = finalizable_data_;
   finalizable_data_ = NULL;
-  return new Message(dest_port, buffer(), BytesWritten(), finalizable_data,
-                     priority);
+  return Message::New(dest_port, buffer(), BytesWritten(), finalizable_data,
+                      priority);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/dart_api_message.h b/runtime/vm/dart_api_message.h
index 082fc08..92a9a85 100644
--- a/runtime/vm/dart_api_message.h
+++ b/runtime/vm/dart_api_message.h
@@ -159,9 +159,9 @@
   ~ApiMessageWriter();
 
   // Writes a message with a single object.
-  Message* WriteCMessage(Dart_CObject* object,
-                         Dart_Port dest_port,
-                         Message::Priority priority);
+  std::unique_ptr<Message> WriteCMessage(Dart_CObject* object,
+                                         Dart_Port dest_port,
+                                         Message::Priority priority);
 
  private:
   static const intptr_t kDartCObjectTypeBits = 4;
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index a741a5e..4bd384c 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -236,7 +236,7 @@
     const String& getter_name = Symbols::GetCall();
     Class& cls = Class::Handle(zone, instance.clazz());
     while (!cls.IsNull()) {
-      function ^= cls.LookupDynamicFunction(getter_name);
+      function = cls.LookupDynamicFunction(getter_name);
       if (!function.IsNull()) {
         Isolate* isolate = thread->isolate();
         if (!OSThread::Current()->HasStackHeadroom()) {
@@ -312,7 +312,7 @@
     ASSERT(!FLAG_lazy_dispatchers);
     // If noSuchMethod(invocation) is not found, call Object::noSuchMethod.
     Thread* thread = Thread::Current();
-    function ^= Resolver::ResolveDynamicForReceiverClass(
+    function = Resolver::ResolveDynamicForReceiverClass(
         Class::Handle(thread->zone(),
                       thread->isolate()->object_store()->object_class()),
         Symbols::NoSuchMethod(), nsm_args_desc);
@@ -377,22 +377,6 @@
   return names.raw();
 }
 
-intptr_t ArgumentsDescriptor::type_args_len_offset() {
-  return Array::element_offset(kTypeArgsLenIndex);
-}
-
-intptr_t ArgumentsDescriptor::count_offset() {
-  return Array::element_offset(kCountIndex);
-}
-
-intptr_t ArgumentsDescriptor::positional_count_offset() {
-  return Array::element_offset(kPositionalCountIndex);
-}
-
-intptr_t ArgumentsDescriptor::first_named_entry_offset() {
-  return Array::element_offset(kFirstNamedEntryIndex);
-}
-
 RawArray* ArgumentsDescriptor::New(intptr_t type_args_len,
                                    intptr_t num_arguments,
                                    const Array& optional_arguments_names) {
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 23342d3..94764a3 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -49,10 +49,20 @@
   RawArray* GetArgumentNames() const;
 
   // Generated code support.
-  static intptr_t type_args_len_offset();
-  static intptr_t count_offset();
-  static intptr_t positional_count_offset();
-  static intptr_t first_named_entry_offset();
+  static intptr_t type_args_len_offset() {
+    return Array::element_offset(kTypeArgsLenIndex);
+  }
+
+  static intptr_t count_offset() { return Array::element_offset(kCountIndex); }
+
+  static intptr_t positional_count_offset() {
+    return Array::element_offset(kPositionalCountIndex);
+  }
+
+  static intptr_t first_named_entry_offset() {
+    return Array::element_offset(kFirstNamedEntryIndex);
+  }
+
   static intptr_t name_offset() { return kNameOffset * kWordSize; }
   static intptr_t position_offset() { return kPositionOffset * kWordSize; }
   static intptr_t named_entry_size() { return kNamedEntrySize * kWordSize; }
diff --git a/runtime/vm/dart_entry_test.cc b/runtime/vm/dart_entry_test.cc
deleted file mode 100644
index 496c1a0..0000000
--- a/runtime/vm/dart_entry_test.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// 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.
-
-#include "platform/globals.h"
-
-#include "platform/assert.h"
-#include "vm/class_finalizer.h"
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/object.h"
-#include "vm/resolver.h"
-#include "vm/symbols.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-ISOLATE_UNIT_TEST_CASE(DartEntry) {
-  const char* kScriptChars =
-      "class A {\n"
-      "  static foo() { return 42; }\n"
-      "}\n";
-  String& url = String::Handle(String::New("dart-test:DartEntry"));
-  String& source = String::Handle(String::New(kScriptChars));
-  Script& script =
-      Script::Handle(Script::New(url, source, RawScript::kScriptTag));
-  Library& lib = Library::Handle(Library::CoreLibrary());
-  EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
-  EXPECT(ClassFinalizer::ProcessPendingClasses());
-  Class& cls =
-      Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
-  EXPECT(!cls.IsNull());  // No ambiguity error expected.
-  String& name = String::Handle(String::New("foo"));
-  Function& function = Function::Handle(cls.LookupStaticFunction(name));
-  EXPECT(!function.IsNull());
-
-  EXPECT(CompilerTest::TestCompileFunction(function));
-  EXPECT(function.HasCode());
-  const Smi& retval = Smi::Handle(reinterpret_cast<RawSmi*>(
-      DartEntry::InvokeFunction(function, Object::empty_array())));
-  EXPECT_EQ(Smi::New(42), retval.raw());
-}
-
-ISOLATE_UNIT_TEST_CASE(InvokeStatic_CompileError) {
-  const char* kScriptChars =
-      "class A {\n"
-      "  static foo() { return ++++; }\n"
-      "}\n";
-  String& url = String::Handle(String::New("dart-test:DartEntry"));
-  String& source = String::Handle(String::New(kScriptChars));
-  Script& script =
-      Script::Handle(Script::New(url, source, RawScript::kScriptTag));
-  Library& lib = Library::Handle(Library::CoreLibrary());
-  EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
-  EXPECT(ClassFinalizer::ProcessPendingClasses());
-  Class& cls =
-      Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
-  EXPECT(!cls.IsNull());  // No ambiguity error expected.
-  String& name = String::Handle(String::New("foo"));
-  Function& function = Function::Handle(cls.LookupStaticFunction(name));
-  EXPECT(!function.IsNull());
-  const Object& retval = Object::Handle(
-      DartEntry::InvokeFunction(function, Object::empty_array()));
-  EXPECT(retval.IsError());
-  EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
-}
-
-ISOLATE_UNIT_TEST_CASE(InvokeDynamic_CompileError) {
-  const char* kScriptChars =
-      "class A {\n"
-      "  foo() { return ++++; }\n"
-      "}\n";
-  String& url = String::Handle(String::New("dart-test:DartEntry"));
-  String& source = String::Handle(String::New(kScriptChars));
-  Script& script =
-      Script::Handle(Script::New(url, source, RawScript::kScriptTag));
-  Library& lib = Library::Handle(Library::CoreLibrary());
-  EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
-  EXPECT(ClassFinalizer::ProcessPendingClasses());
-  Class& cls =
-      Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
-  EXPECT(!cls.IsNull());  // No ambiguity error expected.
-
-  // Invoke the constructor.
-  const Instance& instance = Instance::Handle(Instance::New(cls));
-  const Array& constructor_arguments = Array::Handle(Array::New(1));
-  constructor_arguments.SetAt(0, instance);
-  String& constructor_name = String::Handle(Symbols::New(thread, "A."));
-  Function& constructor =
-      Function::Handle(cls.LookupConstructor(constructor_name));
-  ASSERT(!constructor.IsNull());
-  DartEntry::InvokeFunction(constructor, constructor_arguments);
-
-  // Call foo.
-  String& name = String::Handle(String::New("foo"));
-  Function& function = Function::Handle(cls.LookupDynamicFunction(name));
-  EXPECT(!function.IsNull());
-  const Array& args = Array::Handle(Array::New(1));
-  args.SetAt(0, instance);
-  const Object& retval =
-      Object::Handle(DartEntry::InvokeFunction(function, args));
-  EXPECT(retval.IsError());
-  EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
-}
-
-}  // namespace dart
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index e117e1d..f79f581 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -10,11 +10,13 @@
 
 #include "vm/code_patcher.h"
 #include "vm/compiler/assembler/disassembler.h"
+#include "vm/compiler/frontend/bytecode_reader.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/dart_entry.h"
 #include "vm/deopt_instructions.h"
 #include "vm/flags.h"
 #include "vm/globals.h"
+#include "vm/interpreter.h"
 #include "vm/json_stream.h"
 #include "vm/kernel.h"
 #include "vm/longjump.h"
@@ -66,14 +68,13 @@
       url_(script.url()),
       token_pos_(token_pos),
       end_token_pos_(end_token_pos),
-      is_resolved_(false),
       next_(NULL),
       conditions_(NULL),
       requested_line_number_(requested_line_number),
       requested_column_number_(requested_column_number),
       function_(Function::null()),
-      line_number_(-1),
-      column_number_(-1) {
+      bytecode_token_pos_(TokenPosition::kNoSource),
+      code_token_pos_(TokenPosition::kNoSource) {
   ASSERT(!script.IsNull());
   ASSERT(token_pos_.IsReal());
 }
@@ -86,14 +87,13 @@
       url_(url.raw()),
       token_pos_(TokenPosition::kNoSource),
       end_token_pos_(TokenPosition::kNoSource),
-      is_resolved_(false),
       next_(NULL),
       conditions_(NULL),
       requested_line_number_(requested_line_number),
       requested_column_number_(requested_column_number),
       function_(Function::null()),
-      line_number_(-1),
-      column_number_(-1) {
+      bytecode_token_pos_(TokenPosition::kNoSource),
+      code_token_pos_(TokenPosition::kNoSource) {
   ASSERT(requested_line_number_ >= 0);
 }
 
@@ -110,7 +110,8 @@
   return breakpoints() != NULL;
 }
 
-void BreakpointLocation::SetResolved(const Function& func,
+void BreakpointLocation::SetResolved(bool in_bytecode,
+                                     const Function& func,
                                      TokenPosition token_pos) {
   ASSERT(!IsLatent());
   ASSERT(func.script() == script_);
@@ -120,53 +121,25 @@
   function_ = func.raw();
   token_pos_ = token_pos;
   end_token_pos_ = token_pos;
-  is_resolved_ = true;
+  if (in_bytecode) {
+    bytecode_token_pos_ = token_pos;
+  } else {
+    code_token_pos_ = token_pos;
+  }
 }
 
-// TODO(hausner): Get rid of library parameter. A source breakpoint location
-// does not imply a library, since the same source code can be included
-// in more than one library, e.g. the text location of mixin functions.
-void BreakpointLocation::GetCodeLocation(Library* lib,
-                                         Script* script,
+// Returned resolved pos is either in code or in bytecode.
+void BreakpointLocation::GetCodeLocation(Script* script,
                                          TokenPosition* pos) const {
   if (IsLatent()) {
-    *lib = Library::null();
     *script = Script::null();
     *pos = TokenPosition::kNoSource;
   } else {
     *script = this->script();
     *pos = token_pos_;
-    if (IsResolved()) {
-      const Function& func = Function::Handle(function_);
-      ASSERT(!func.IsNull());
-      const Class& cls = Class::Handle(func.origin());
-      *lib = cls.library();
-    } else {
-      *lib = Library::null();
-    }
   }
 }
 
-intptr_t BreakpointLocation::LineNumber() {
-  ASSERT(IsResolved());
-  // Compute line number lazily since it causes scanning of the script.
-  if (line_number_ < 0) {
-    const Script& script = Script::Handle(this->script());
-    script.GetTokenLocation(token_pos_, &line_number_, NULL);
-  }
-  return line_number_;
-}
-
-intptr_t BreakpointLocation::ColumnNumber() {
-  ASSERT(IsResolved());
-  // Compute column number lazily since it causes scanning of the script.
-  if (column_number_ < 0) {
-    const Script& script = Script::Handle(this->script());
-    script.GetTokenLocation(token_pos_, &line_number_, &column_number_);
-  }
-  return column_number_;
-}
-
 void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) {
   // Only latent breakpoints can be moved.
   ASSERT((new_bpt_location == NULL) || bpt_location_->IsLatent());
@@ -208,6 +181,7 @@
 
 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_));
+  visitor->VisitPointer(reinterpret_cast<RawObject**>(&bytecode_));
 #if !defined(TARGET_ARCH_DBC)
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_));
 #endif
@@ -225,6 +199,7 @@
       sp_(sp),
       ctx_(Context::ZoneHandle()),
       code_(Code::ZoneHandle(code.raw())),
+      bytecode_(Bytecode::ZoneHandle()),
       function_(Function::ZoneHandle(code.function())),
       live_frame_((kind == kRegular) || (kind == kAsyncActivation)),
       token_pos_initialized_(false),
@@ -237,11 +212,44 @@
       deopt_frame_(Array::ZoneHandle(deopt_frame.raw())),
       deopt_frame_offset_(deopt_frame_offset),
       kind_(kind),
-      is_interpreted_(false),  // TODO(regis): No bytecode debugging support.
       vars_initialized_(false),
       var_descriptors_(LocalVarDescriptors::ZoneHandle()),
       desc_indices_(8),
-      pc_desc_(PcDescriptors::ZoneHandle()) {}
+      pc_desc_(PcDescriptors::ZoneHandle()) {
+  ASSERT(!function_.IsNull());
+}
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ActivationFrame::ActivationFrame(uword pc,
+                                 uword fp,
+                                 uword sp,
+                                 const Bytecode& bytecode,
+                                 ActivationFrame::Kind kind)
+    : pc_(pc),
+      fp_(fp),
+      sp_(sp),
+      ctx_(Context::ZoneHandle()),
+      code_(Code::ZoneHandle()),
+      bytecode_(Bytecode::ZoneHandle(bytecode.raw())),
+      function_(Function::ZoneHandle(bytecode.function())),
+      live_frame_((kind == kRegular) || (kind == kAsyncActivation)),
+      token_pos_initialized_(false),
+      token_pos_(TokenPosition::kNoSource),
+      try_index_(-1),
+      deopt_id_(DeoptId::kNone),
+      line_number_(-1),
+      column_number_(-1),
+      context_level_(-1),
+      deopt_frame_(Array::ZoneHandle()),
+      deopt_frame_offset_(0),
+      kind_(kind),
+      vars_initialized_(false),
+      var_descriptors_(LocalVarDescriptors::ZoneHandle()),
+      desc_indices_(8),
+      pc_desc_(PcDescriptors::ZoneHandle()) {
+  ASSERT(!function_.IsNull());  // Frames with bytecode stubs should be skipped.
+}
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 ActivationFrame::ActivationFrame(Kind kind)
     : pc_(0),
@@ -249,6 +257,7 @@
       sp_(0),
       ctx_(Context::ZoneHandle()),
       code_(Code::ZoneHandle()),
+      bytecode_(Bytecode::ZoneHandle()),
       function_(Function::ZoneHandle()),
       live_frame_(kind == kRegular),
       token_pos_initialized_(false),
@@ -260,7 +269,6 @@
       deopt_frame_(Array::ZoneHandle()),
       deopt_frame_offset_(0),
       kind_(kind),
-      is_interpreted_(false),
       vars_initialized_(false),
       var_descriptors_(LocalVarDescriptors::ZoneHandle()),
       desc_indices_(8),
@@ -272,6 +280,7 @@
       sp_(0),
       ctx_(Context::ZoneHandle()),
       code_(Code::ZoneHandle()),
+      bytecode_(Bytecode::ZoneHandle()),
       function_(Function::ZoneHandle()),
       live_frame_(false),
       token_pos_initialized_(false),
@@ -283,15 +292,21 @@
       deopt_frame_(Array::ZoneHandle()),
       deopt_frame_offset_(0),
       kind_(kAsyncActivation),
-      is_interpreted_(false),
       vars_initialized_(false),
       var_descriptors_(LocalVarDescriptors::ZoneHandle()),
       desc_indices_(8),
       pc_desc_(PcDescriptors::ZoneHandle()) {
   // Extract the function and the code from the asynchronous activation.
   function_ = async_activation.function();
-  function_.EnsureHasCompiledUnoptimizedCode();
-  code_ = function_.unoptimized_code();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (!function_.HasCode() && function_.HasBytecode()) {
+    bytecode_ = function_.bytecode();
+  }
+#endif
+  if (bytecode_.IsNull()) {
+    function_.EnsureHasCompiledUnoptimizedCode();
+    code_ = function_.unoptimized_code();
+  }
   ctx_ = async_activation.context();
   ASSERT(fp_ == 0);
   ASSERT(!ctx_.IsNull());
@@ -445,7 +460,7 @@
   switch (func.kind()) {
     case RawFunction::kImplicitGetter:
     case RawFunction::kImplicitSetter:
-    case RawFunction::kImplicitStaticFinalGetter:
+    case RawFunction::kImplicitStaticGetter:
     case RawFunction::kStaticFieldInitializer:
     case RawFunction::kMethodExtractor:
     case RawFunction::kNoSuchMethodDispatcher:
@@ -462,7 +477,7 @@
 }
 
 bool Debugger::HasBreakpoint(const Function& func, Zone* zone) {
-  if (!func.HasCode()) {
+  if (!func.HasCode() && !func.HasBytecode()) {
     // If the function is not compiled yet, just check whether there
     // is a user-defined breakpoint that falls into the token
     // range of the function. This may be a false positive: the breakpoint
@@ -553,20 +568,26 @@
 }
 
 void ActivationFrame::GetPcDescriptors() {
+  ASSERT(!IsInterpreted());  // We need to set try_index_ simultaneously.
   if (pc_desc_.IsNull()) {
     pc_desc_ = code().pc_descriptors();
     ASSERT(!pc_desc_.IsNull());
   }
 }
 
-// Compute token_pos_ and try_index_ and token_pos_initialized_.
+// Compute token_pos_ and token_pos_initialized_.
+// If not IsInterpreted(), then also compute try_index_ and deopt_id_.
 TokenPosition ActivationFrame::TokenPos() {
   if (!token_pos_initialized_) {
     token_pos_initialized_ = true;
+    if (IsInterpreted()) {
+      token_pos_ = bytecode().GetTokenIndexOfPC(pc_);
+      return token_pos_;
+    }
     token_pos_ = TokenPosition::kNoSource;
     GetPcDescriptors();
     PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind);
-    uword pc_offset = pc_ - code().PayloadStart();
+    const uword pc_offset = pc_ - code().PayloadStart();
     while (iter.MoveNext()) {
       if (iter.PcOffset() == pc_offset) {
         try_index_ = iter.TryIndex();
@@ -580,6 +601,16 @@
 }
 
 intptr_t ActivationFrame::TryIndex() {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (IsInterpreted()) {
+    if (pc_desc_.IsNull()) {
+      ASSERT(try_index_ == -1);
+      pc_desc_ = bytecode().pc_descriptors();
+      try_index_ = bytecode().GetTryIndexAtPc(pc_);
+    }
+    return try_index_;
+  }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   if (!token_pos_initialized_) {
     TokenPos();  // Side effect: computes token_pos_initialized_, try_index_.
   }
@@ -587,6 +618,7 @@
 }
 
 intptr_t ActivationFrame::DeoptId() {
+  ASSERT(!IsInterpreted());
   if (!token_pos_initialized_) {
     TokenPos();  // Side effect: computes token_pos_initialized_, try_index_.
   }
@@ -619,7 +651,7 @@
 
 void ActivationFrame::GetVarDescriptors() {
   if (var_descriptors_.IsNull()) {
-    if (is_interpreted()) {
+    if (IsInterpreted()) {
       // TODO(regis): Kernel bytecode does not yet provide var descriptors.
       var_descriptors_ = Object::empty_var_descriptors().raw();
       return;
@@ -633,7 +665,7 @@
       if (!error.IsNull()) {
         Exceptions::PropagateError(error);
       }
-      unoptimized_code ^= function().unoptimized_code();
+      unoptimized_code = function().unoptimized_code();
     }
     ASSERT(!unoptimized_code.IsNull());
     var_descriptors_ = unoptimized_code.GetLocalVarDescriptors();
@@ -652,8 +684,13 @@
   OS::PrintErr("deopt_id_ %" Px "\n", deopt_id_);
   OS::PrintErr("context_level_ %" Px "\n", context_level_);
   DisassembleToStdout formatter;
-  code().Disassemble(&formatter);
-  PcDescriptors::Handle(code().pc_descriptors()).Print();
+  if (IsInterpreted()) {
+    bytecode().Disassemble(&formatter);
+    PcDescriptors::Handle(bytecode().pc_descriptors()).Print();
+  } else {
+    code().Disassemble(&formatter);
+    PcDescriptors::Handle(code().pc_descriptors()).Print();
+  }
   StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                             Thread::Current(),
                             StackFrameIterator::kNoCrossThreadIteration);
@@ -667,6 +704,9 @@
 
 // Calculate the context level at the current token index of the frame.
 intptr_t ActivationFrame::ContextLevel() {
+  // TODO(regis): get context level information using
+  //  BytecodeLocalVariablesIterator for interpreted frames and compiled frames
+  //  with a function coming from bytecode (function.is_declared_in_bytecode())
   const Context& ctx = GetSavedCurrentContext();
   if (context_level_ < 0 && !ctx.IsNull()) {
     ASSERT(!code_.is_optimized());
@@ -808,7 +848,11 @@
   AbstractType& type = Type::Handle();
   const bool is_async =
       function().IsAsyncClosure() || function().IsAsyncGenClosure();
-  handlers = code().exception_handlers();
+  if (IsInterpreted()) {
+    handlers = bytecode().exception_handlers();
+  } else {
+    handlers = code().exception_handlers();
+  }
   ASSERT(!handlers.IsNull());
   intptr_t num_handlers_checked = 0;
   while (try_index != kInvalidTryIndex) {
@@ -840,6 +884,10 @@
 
 void ActivationFrame::ExtractTokenPositionFromAsyncClosure() {
   // Attempt to determine the token position from the async closure.
+  if (IsInterpreted()) {
+    // TODO(regis): Implement.
+    return;
+  }
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   const Script& script = Script::Handle(zone, function().script());
@@ -960,9 +1008,9 @@
         ASSERT(function().name() == Symbols::Call().raw());
         ASSERT(function().IsInvokeFieldDispatcher());
         // Closure.call frames.
-        ctx_ ^= Closure::Cast(obj).context();
+        ctx_ = Closure::Cast(obj).context();
       } else if (obj.IsContext()) {
-        ctx_ ^= Context::Cast(obj).raw();
+        ctx_ = Context::Cast(obj).raw();
       } else {
         ASSERT(obj.IsNull());
       }
@@ -1367,15 +1415,22 @@
     TypeArguments& type_params = TypeArguments::Handle();
     TypeParameter& type_param = TypeParameter::Handle();
     Function& current = Function::Handle(function().raw());
+    intptr_t mapping_offset = num_vars;
     for (intptr_t i = 0; !current.IsNull(); i += current.NumTypeParameters(),
                   current = current.parent_function()) {
       type_params = current.type_parameters();
-      for (intptr_t j = 0; j < current.NumTypeParameters(); ++j) {
+      intptr_t size = current.NumTypeParameters();
+      ASSERT(mapping_offset >= size);
+      mapping_offset -= size;
+      for (intptr_t j = 0; j < size; ++j) {
         type_param = TypeParameter::RawCast(type_params.TypeAt(j));
         name = type_param.Name();
-        // Write the names in backwards so they match up with the order of the
-        // types in 'type_arguments'.
-        type_params_names.SetAt(num_vars - (i + j) - 1, name);
+        // Write the names in backwards in terms of chain of functions.
+        // But keep the order of names within the same function. so they
+        // match up with the order of the types in 'type_arguments'.
+        // Index:0 1 2 3 ...
+        //       |Names in Grandparent| |Names in Parent| ..|Names in Child|
+        type_params_names.SetAt(mapping_offset + j, name);
       }
     }
     if (!type_arguments.IsNull()) {
@@ -1429,7 +1484,11 @@
   const TokenPosition pos = TokenPos().SourcePosition();
   jsobj->AddLocation(script, pos);
   jsobj->AddProperty("function", function());
-  jsobj->AddProperty("code", code());
+  if (IsInterpreted()) {
+    jsobj->AddProperty("code", bytecode());
+  } else {
+    jsobj->AddProperty("code", code());
+  }
   {
     JSONArray jsvars(jsobj, "vars");
     const int num_vars = NumLocalVariables();
@@ -1469,7 +1528,11 @@
   const TokenPosition pos = TokenPos().SourcePosition();
   jsobj->AddLocation(script, pos);
   jsobj->AddProperty("function", function());
-  jsobj->AddProperty("code", code());
+  if (IsInterpreted()) {
+    jsobj->AddProperty("code", bytecode());
+  } else {
+    jsobj->AddProperty("code", code());
+  }
 }
 
 void ActivationFrame::PrintToJSONObjectAsyncSuspensionMarker(
@@ -1486,7 +1549,11 @@
   const TokenPosition pos = TokenPos().SourcePosition();
   jsobj->AddLocation(script, pos);
   jsobj->AddProperty("function", function());
-  jsobj->AddProperty("code", code());
+  if (IsInterpreted()) {
+    jsobj->AddProperty("code", bytecode());
+  } else {
+    jsobj->AddProperty("code", code());
+  }
 }
 
 static bool IsFunctionVisible(const Function& function) {
@@ -1509,6 +1576,14 @@
                                  ActivationFrame::kAsyncCausal));
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+void DebuggerStackTrace::AddAsyncCausalFrame(uword pc,
+                                             const Bytecode& bytecode) {
+  trace_.Add(
+      new ActivationFrame(pc, 0, 0, bytecode, ActivationFrame::kAsyncCausal));
+}
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall |
                                RawPcDescriptors::kUnoptStaticCall |
                                RawPcDescriptors::kRuntimeCall;
@@ -1518,6 +1593,7 @@
                                uword pc,
                                RawPcDescriptors::Kind kind)
     : code_(code.raw()),
+      bytecode_(Bytecode::null()),
       token_pos_(token_pos),
       pc_(pc),
       line_number_(-1),
@@ -1538,12 +1614,37 @@
   ASSERT((breakpoint_kind_ & kSafepointKind) != 0);
 }
 
+CodeBreakpoint::CodeBreakpoint(const Bytecode& bytecode,
+                               TokenPosition token_pos,
+                               uword pc)
+    : code_(Code::null()),
+      bytecode_(bytecode.raw()),
+      token_pos_(token_pos),
+      pc_(pc),
+      line_number_(-1),
+      is_enabled_(false),
+      bpt_location_(NULL),
+      next_(NULL),
+      breakpoint_kind_(RawPcDescriptors::kAnyKind),
+#if !defined(TARGET_ARCH_DBC)
+      saved_value_(Code::null())
+#else
+      saved_value_(SimulatorBytecode::kTrap),
+      saved_value_fastsmi_(SimulatorBytecode::kTrap)
+#endif
+{
+  ASSERT(!bytecode.IsNull());
+  ASSERT(token_pos_.IsReal());
+  ASSERT(pc_ != 0);
+}
+
 CodeBreakpoint::~CodeBreakpoint() {
   // Make sure we don't leave patched code behind.
   ASSERT(!IsEnabled());
 // Poison the data so we catch use after free errors.
 #ifdef DEBUG
   code_ = Code::null();
+  bytecode_ = Bytecode::null();
   pc_ = 0ul;
   bpt_location_ = NULL;
   next_ = NULL;
@@ -1552,7 +1653,12 @@
 }
 
 RawFunction* CodeBreakpoint::function() const {
-  return Code::Handle(code_).function();
+  if (IsInterpreted()) {
+    ASSERT(Bytecode::Handle(bytecode_).function() != Function::null());
+    return Bytecode::Handle(bytecode_).function();
+  } else {
+    return Code::Handle(code_).function();
+  }
 }
 
 RawScript* CodeBreakpoint::SourceCode() {
@@ -1576,14 +1682,30 @@
 
 void CodeBreakpoint::Enable() {
   if (!is_enabled_) {
-    PatchCode();
+    if (IsInterpreted()) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+      SetBytecodeBreakpoint();
+#else
+      UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+    } else {
+      PatchCode();
+    }
   }
   ASSERT(is_enabled_);
 }
 
 void CodeBreakpoint::Disable() {
   if (is_enabled_) {
-    RestoreCode();
+    if (IsInterpreted()) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+      UnsetBytecodeBreakpoint();
+#else
+      UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+    } else {
+      RestoreCode();
+    }
   }
   ASSERT(!is_enabled_);
 }
@@ -1627,20 +1749,20 @@
     return;
   }
   while (breakpoint_locations_ != NULL) {
-    BreakpointLocation* bpt = breakpoint_locations_;
+    BreakpointLocation* loc = breakpoint_locations_;
     breakpoint_locations_ = breakpoint_locations_->next();
-    delete bpt;
+    delete loc;
   }
   while (latent_locations_ != NULL) {
-    BreakpointLocation* bpt = latent_locations_;
+    BreakpointLocation* loc = latent_locations_;
     latent_locations_ = latent_locations_->next();
-    delete bpt;
+    delete loc;
   }
   while (code_breakpoints_ != NULL) {
-    CodeBreakpoint* bpt = code_breakpoints_;
+    CodeBreakpoint* cbpt = code_breakpoints_;
     code_breakpoints_ = code_breakpoints_->next();
-    bpt->Disable();
-    delete bpt;
+    cbpt->Disable();
+    delete cbpt;
   }
   if (NeedsIsolateEvents()) {
     ServiceEvent event(isolate_, ServiceEvent::kIsolateExit);
@@ -1789,6 +1911,18 @@
   }
 }
 
+void Debugger::NotifySingleStepping(bool value) const {
+  isolate_->set_single_step(value);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  // Do not call Interpreter::Current(), which may allocate an interpreter.
+  Interpreter* interpreter = Thread::Current()->interpreter();
+  if (interpreter != nullptr) {
+    // Do not reset is_debugging to false if bytecode debug breaks are enabled.
+    interpreter->set_is_debugging(value || HasEnabledBytecodeBreakpoints());
+  }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+}
+
 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
                                             uword pc,
                                             StackFrame* frame,
@@ -1811,6 +1945,24 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
+ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
+                                            uword pc,
+                                            StackFrame* frame,
+                                            const Bytecode& bytecode,
+                                            ActivationFrame::Kind kind) {
+  ASSERT(bytecode.ContainsInstructionAt(pc));
+  ActivationFrame* activation =
+      new ActivationFrame(pc, frame->fp(), frame->sp(), bytecode, kind);
+  if (FLAG_trace_debugger_stacktrace) {
+    const Context& ctx = activation->GetSavedCurrentContext();
+    OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString());
+  }
+  if (FLAG_trace_debugger_stacktrace) {
+    OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber());
+  }
+  return activation;
+}
+
 RawArray* Debugger::DeoptimizeToArray(Thread* thread,
                                       StackFrame* frame,
                                       const Code& code) {
@@ -1843,6 +1995,9 @@
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
   Code& code = Code::Handle(zone);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  Bytecode& bytecode = Bytecode::Handle(zone);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   Code& inlined_code = Code::Handle(zone);
   Array& deopt_frame = Array::Handle(zone);
 
@@ -1855,14 +2010,21 @@
     }
     if (frame->IsDartFrame()) {
       if (frame->is_interpreted()) {
-        // TODO(regis): Support debugging of interpreted frames.
-        // For now, do not abort, but skip the frame, as this code is run
-        // while handling a stack overflow. See HandleStackOverflowTestCases.
-        continue;
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        bytecode = frame->LookupDartBytecode();
+        if (bytecode.function() == Function::null()) {
+          continue;  // Skip bytecode stub frame.
+        }
+        stack_trace->AddActivation(
+            CollectDartFrame(isolate, frame->pc(), frame, bytecode));
+#else
+        UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+      } else {
+        code = frame->LookupDartCode();
+        AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
+                         &inlined_code, &deopt_frame);
       }
-      code = frame->LookupDartCode();
-      AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
-                       &inlined_code, &deopt_frame);
     }
   }
   return stack_trace;
@@ -1910,7 +2072,11 @@
   Isolate* isolate = thread->isolate();
   DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
 
+  Object& code_obj = Object::Handle(zone);
   Code& code = Code::Handle(zone);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  Bytecode& bytecode = Bytecode::Handle(zone);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   Smi& offset = Smi::Handle();
   Code& inlined_code = Code::Handle(zone);
   Array& deopt_frame = Array::Handle(zone);
@@ -1942,12 +2108,21 @@
     ASSERT(frame != NULL);
     if (frame->IsDartFrame()) {
       if (frame->is_interpreted()) {
-        // TODO(regis): Support debugging of interpreted frames.
-        UNIMPLEMENTED();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        bytecode = frame->LookupDartBytecode();
+        if (bytecode.function() == Function::null()) {
+          continue;  // Skip bytecode stub frame.
+        }
+        stack_trace->AddActivation(
+            CollectDartFrame(isolate, frame->pc(), frame, bytecode));
+#else
+        UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+      } else {
+        code = frame->LookupDartCode();
+        AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
+                         &inlined_code, &deopt_frame);
       }
-      code = frame->LookupDartCode();
-      AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
-                       &inlined_code, &deopt_frame);
       synchronous_stack_trace_length--;
     }
     frame = iterator.NextFrame();
@@ -1958,19 +2133,27 @@
   // activated.
   while (!async_stack_trace.IsNull()) {
     for (intptr_t i = 0; i < async_stack_trace.Length(); i++) {
-      if (async_stack_trace.CodeAtFrame(i) == Code::null()) {
+      code_obj = async_stack_trace.CodeAtFrame(i);
+      if (code_obj.IsNull()) {
         break;
       }
-      if (async_stack_trace.CodeAtFrame(i) ==
-          StubCode::AsynchronousGapMarker().raw()) {
+      if (code_obj.raw() == StubCode::AsynchronousGapMarker().raw()) {
         stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
         // The frame immediately below the asynchronous gap marker is the
         // identical to the frame above the marker. Skip the frame to enhance
         // the readability of the trace.
         i++;
       } else {
-        code = Code::RawCast(async_stack_trace.CodeAtFrame(i));
         offset = Smi::RawCast(async_stack_trace.PcOffsetAtFrame(i));
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        if (code_obj.IsBytecode()) {
+          bytecode ^= code_obj.raw();
+          uword pc = bytecode.PayloadStart() + offset.Value();
+          stack_trace->AddAsyncCausalFrame(pc, bytecode);
+          continue;
+        }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+        code ^= code_obj.raw();
         uword pc = code.PayloadStart() + offset.Value();
         if (code.is_optimized()) {
           for (InlinedFunctionsIterator it(code, pc); !it.Done();
@@ -2020,6 +2203,7 @@
                               StackFrameIterator::kNoCrossThreadIteration);
 
   Code& code = Code::Handle(zone);
+  Bytecode& bytecode = Bytecode::Handle(zone);
   Smi& offset = Smi::Handle(zone);
   Function& function = Function::Handle(zone);
   Code& inlined_code = Code::Handle(zone);
@@ -2041,76 +2225,14 @@
     }
     if (frame->IsDartFrame()) {
       if (frame->is_interpreted()) {
-        // TODO(regis): Support debugging of interpreted frames.
-        UNIMPLEMENTED();
-      }
-      code = frame->LookupDartCode();
-      if (code.is_optimized()) {
-        deopt_frame = DeoptimizeToArray(thread, frame, code);
-        bool found_async_awaiter = false;
-        bool abort_attempt_to_navigate_through_sync_async = false;
-        for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
-             it.Advance()) {
-          inlined_code = it.code();
-          function = it.function();
-
-          if (skip_sync_async_frames_count > 0) {
-            function_name ^= function.QualifiedScrubbedName();
-            if (CheckAndSkipAsync(skip_sync_async_frames_count,
-                                  function_name)) {
-              skip_sync_async_frames_count--;
-            } else {
-              // Unexpected function in sync async call
-              skip_sync_async_frames_count = -1;
-              abort_attempt_to_navigate_through_sync_async = true;
-              break;
-            }
-          }
-
-          if (FLAG_trace_debugger_stacktrace) {
-            ASSERT(!function.IsNull());
-            OS::PrintErr(
-                "CollectAwaiterReturnStackTrace: visiting inlined function: "
-                "%s\n",
-                function.ToFullyQualifiedCString());
-          }
-          intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
-          if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
-            ActivationFrame* activation = CollectDartFrame(
-                isolate, it.pc(), frame, inlined_code, deopt_frame,
-                deopt_frame_offset, ActivationFrame::kAsyncActivation);
-            ASSERT(activation != NULL);
-            stack_trace->AddActivation(activation);
-            stack_has_async_function = true;
-            // Grab the awaiter.
-            async_activation ^= activation->GetAsyncAwaiter();
-            found_async_awaiter = true;
-            // async function might have been called synchronously, in which
-            // case we need to keep going down the stack.
-            // To determine how we are called we peek few more frames further
-            // expecting to see Closure_call followed by
-            // AsyncAwaitCompleter_start.
-            // If we are able to see those functions we continue going down
-            // thestack, if we are not, we break out of the loop as we are
-            // not interested in exploring rest of the stack - there is only
-            // dart-internal code left.
-            skip_sync_async_frames_count = 2;
-          } else {
-            stack_trace->AddActivation(
-                CollectDartFrame(isolate, it.pc(), frame, inlined_code,
-                                 deopt_frame, deopt_frame_offset));
-          }
+        bytecode = frame->LookupDartBytecode();
+        function = bytecode.function();
+        if (function.IsNull()) {
+          continue;  // Skip bytecode stub frame.
         }
-        // Break out of outer loop.
-        if (found_async_awaiter ||
-            abort_attempt_to_navigate_through_sync_async) {
-          break;
-        }
-      } else {
-        function = code.function();
 
         if (skip_sync_async_frames_count > 0) {
-          function_name ^= function.QualifiedScrubbedName();
+          function_name = function.QualifiedScrubbedName();
           if (CheckAndSkipAsync(skip_sync_async_frames_count, function_name)) {
             skip_sync_async_frames_count--;
           } else {
@@ -2120,9 +2242,9 @@
         }
 
         if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
-          ActivationFrame* activation = CollectDartFrame(
-              isolate, frame->pc(), frame, code, Object::null_array(), 0,
-              ActivationFrame::kAsyncActivation);
+          ActivationFrame* activation =
+              CollectDartFrame(isolate, frame->pc(), frame, bytecode,
+                               ActivationFrame::kAsyncActivation);
           ASSERT(activation != NULL);
           stack_trace->AddActivation(activation);
           stack_has_async_function = true;
@@ -2133,8 +2255,103 @@
           // synchronously above.
           skip_sync_async_frames_count = 2;
         } else {
-          stack_trace->AddActivation(CollectDartFrame(
-              isolate, frame->pc(), frame, code, Object::null_array(), 0));
+          stack_trace->AddActivation(
+              CollectDartFrame(isolate, frame->pc(), frame, bytecode));
+        }
+      } else {
+        code = frame->LookupDartCode();
+        if (code.is_optimized()) {
+          deopt_frame = DeoptimizeToArray(thread, frame, code);
+          bool found_async_awaiter = false;
+          bool abort_attempt_to_navigate_through_sync_async = false;
+          for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
+               it.Advance()) {
+            inlined_code = it.code();
+            function = it.function();
+
+            if (skip_sync_async_frames_count > 0) {
+              function_name ^= function.QualifiedScrubbedName();
+              if (CheckAndSkipAsync(skip_sync_async_frames_count,
+                                    function_name)) {
+                skip_sync_async_frames_count--;
+              } else {
+                // Unexpected function in sync async call
+                skip_sync_async_frames_count = -1;
+                abort_attempt_to_navigate_through_sync_async = true;
+                break;
+              }
+            }
+
+            if (FLAG_trace_debugger_stacktrace) {
+              ASSERT(!function.IsNull());
+              OS::PrintErr(
+                  "CollectAwaiterReturnStackTrace: visiting inlined function: "
+                  "%s\n",
+                  function.ToFullyQualifiedCString());
+            }
+            intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
+            if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
+              ActivationFrame* activation = CollectDartFrame(
+                  isolate, it.pc(), frame, inlined_code, deopt_frame,
+                  deopt_frame_offset, ActivationFrame::kAsyncActivation);
+              ASSERT(activation != NULL);
+              stack_trace->AddActivation(activation);
+              stack_has_async_function = true;
+              // Grab the awaiter.
+              async_activation ^= activation->GetAsyncAwaiter();
+              found_async_awaiter = true;
+              // async function might have been called synchronously, in which
+              // case we need to keep going down the stack.
+              // To determine how we are called we peek few more frames further
+              // expecting to see Closure_call followed by
+              // AsyncAwaitCompleter_start.
+              // If we are able to see those functions we continue going down
+              // thestack, if we are not, we break out of the loop as we are
+              // not interested in exploring rest of the stack - there is only
+              // dart-internal code left.
+              skip_sync_async_frames_count = 2;
+            } else {
+              stack_trace->AddActivation(
+                  CollectDartFrame(isolate, it.pc(), frame, inlined_code,
+                                   deopt_frame, deopt_frame_offset));
+            }
+          }
+          // Break out of outer loop.
+          if (found_async_awaiter ||
+              abort_attempt_to_navigate_through_sync_async) {
+            break;
+          }
+        } else {
+          function = code.function();
+
+          if (skip_sync_async_frames_count > 0) {
+            function_name ^= function.QualifiedScrubbedName();
+            if (CheckAndSkipAsync(skip_sync_async_frames_count,
+                                  function_name)) {
+              skip_sync_async_frames_count--;
+            } else {
+              // Unexpected function in synchronous call of async function.
+              break;
+            }
+          }
+
+          if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
+            ActivationFrame* activation = CollectDartFrame(
+                isolate, frame->pc(), frame, code, Object::null_array(), 0,
+                ActivationFrame::kAsyncActivation);
+            ASSERT(activation != NULL);
+            stack_trace->AddActivation(activation);
+            stack_has_async_function = true;
+            // Grab the awaiter.
+            async_activation ^= activation->GetAsyncAwaiter();
+            async_stack_trace ^= activation->GetCausalStack();
+            // see comment regarding skipping frames of async functions called
+            // synchronously above.
+            skip_sync_async_frames_count = 2;
+          } else {
+            stack_trace->AddActivation(CollectDartFrame(
+                isolate, frame->pc(), frame, code, Object::null_array(), 0));
+          }
         }
       }
     }
@@ -2202,20 +2419,29 @@
   StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
-  StackFrame* frame = iterator.NextFrame();
-  while ((frame != NULL) && !frame->IsDartFrame()) {
+  StackFrame* frame;
+  while (true) {
     frame = iterator.NextFrame();
+    RELEASE_ASSERT(frame != nullptr);
+    if (!frame->IsDartFrame()) {
+      continue;
+    }
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    if (frame->is_interpreted()) {
+      Bytecode& bytecode = Bytecode::Handle(frame->LookupDartBytecode());
+      if (bytecode.function() == Function::null()) {
+        continue;  // Skip bytecode stub frame.
+      }
+      ActivationFrame* activation =
+          new ActivationFrame(frame->pc(), frame->fp(), frame->sp(), bytecode);
+      return activation;
+    }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+    Code& code = Code::Handle(frame->LookupDartCode());
+    ActivationFrame* activation = new ActivationFrame(
+        frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0);
+    return activation;
   }
-  ASSERT(frame != NULL);
-  if (frame->is_interpreted()) {
-    // TODO(regis): Support debugging of interpreted frames.
-    UNIMPLEMENTED();
-    return NULL;
-  }
-  Code& code = Code::Handle(frame->LookupDartCode());
-  ActivationFrame* activation = new ActivationFrame(
-      frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0);
-  return activation;
 }
 
 DebuggerStackTrace* Debugger::StackTrace() {
@@ -2249,6 +2475,9 @@
   Function& function = Function::Handle();
   Object& code_object = Object::Handle();
   Code& code = Code::Handle();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  Bytecode& bytecode = Bytecode::Handle();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
   const uword fp = 0;
   const uword sp = 0;
@@ -2264,36 +2493,50 @@
     // a shallow stack).
     if (!code_object.IsNull()) {
       if (code_object.IsBytecode()) {
-        // TODO(regis): Support debugging of interpreted frames.
-        UNIMPLEMENTED();
-      }
-      code ^= code_object.raw();
-      ASSERT(code.IsFunctionCode());
-      function = code.function();
-      if (function.is_visible()) {
-        ASSERT(function.raw() == code.function());
-        uword pc =
-            code.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
-        if (code.is_optimized() && ex_trace.expand_inlined()) {
-          // Traverse inlined frames.
-          for (InlinedFunctionsIterator it(code, pc); !it.Done();
-               it.Advance()) {
-            function = it.function();
-            code = it.code();
-            ASSERT(function.raw() == code.function());
-            uword pc = it.pc();
-            ASSERT(pc != 0);
-            ASSERT(code.PayloadStart() <= pc);
-            ASSERT(pc < (code.PayloadStart() + code.Size()));
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        bytecode ^= code_object.raw();
+        function = bytecode.function();
+        // Skip bytecode stub frames and frames with invisible function.
+        if (!function.IsNull() && function.is_visible()) {
+          ASSERT(function.raw() == bytecode.function());
+          uword pc =
+              bytecode.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
+          ActivationFrame* activation =
+              new ActivationFrame(pc, fp, sp, bytecode);
+          stack_trace->AddActivation(activation);
+        }
+#else
+        UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+      } else {
+        code ^= code_object.raw();
+        ASSERT(code.IsFunctionCode());
+        function = code.function();
+        if (function.is_visible()) {
+          ASSERT(function.raw() == code.function());
+          uword pc =
+              code.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
+          if (code.is_optimized() && ex_trace.expand_inlined()) {
+            // Traverse inlined frames.
+            for (InlinedFunctionsIterator it(code, pc); !it.Done();
+                 it.Advance()) {
+              function = it.function();
+              code = it.code();
+              ASSERT(function.raw() == code.function());
+              uword pc = it.pc();
+              ASSERT(pc != 0);
+              ASSERT(code.PayloadStart() <= pc);
+              ASSERT(pc < (code.PayloadStart() + code.Size()));
 
+              ActivationFrame* activation = new ActivationFrame(
+                  pc, fp, sp, code, deopt_frame, deopt_frame_offset);
+              stack_trace->AddActivation(activation);
+            }
+          } else {
             ActivationFrame* activation = new ActivationFrame(
                 pc, fp, sp, code, deopt_frame, deopt_frame_offset);
             stack_trace->AddActivation(activation);
           }
-        } else {
-          ActivationFrame* activation = new ActivationFrame(
-              pc, fp, sp, code, deopt_frame, deopt_frame_offset);
-          stack_trace->AddActivation(activation);
         }
       }
     }
@@ -2424,11 +2667,12 @@
 // algorithm, which would be simpler.  I believe that it only needs
 // two passes to support the recursive try-the-whole-function case.
 // Rewrite this later, once there are more tests in place.
-TokenPosition Debugger::ResolveBreakpointPos(const Function& func,
+TokenPosition Debugger::ResolveBreakpointPos(bool in_bytecode,
+                                             const Function& func,
                                              TokenPosition requested_token_pos,
                                              TokenPosition last_token_pos,
-                                             intptr_t requested_column) {
-  ASSERT(func.HasCode());
+                                             intptr_t requested_column,
+                                             TokenPosition exact_token_pos) {
   ASSERT(!func.HasOptimizedCode());
 
   if (requested_token_pos < func.token_pos()) {
@@ -2440,50 +2684,137 @@
 
   Zone* zone = Thread::Current()->zone();
   Script& script = Script::Handle(zone, func.script());
-  Code& code = Code::Handle(zone, func.unoptimized_code());
-  ASSERT(!code.IsNull());
-  PcDescriptors& desc = PcDescriptors::Handle(zone, code.pc_descriptors());
+  Code& code = Code::Handle(zone);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  Bytecode& bytecode = Bytecode::Handle(zone);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  PcDescriptors& desc = PcDescriptors::Handle(zone);
+  if (in_bytecode) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    ASSERT(func.HasBytecode());
+    bytecode = func.bytecode();
+    ASSERT(!bytecode.IsNull());
+#else
+    UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  } else {
+    ASSERT(func.HasCode());
+    code = func.unoptimized_code();
+    ASSERT(!code.IsNull());
+    desc = code.pc_descriptors();
+  }
 
   // First pass: find the safe point which is closest to the beginning
   // of the given token range.
   TokenPosition best_fit_pos = TokenPosition::kMaxSource;
   intptr_t best_column = INT_MAX;
   intptr_t best_line = INT_MAX;
-  PcDescriptors::Iterator iter(desc, kSafepointKind);
-  while (iter.MoveNext()) {
-    const TokenPosition pos = iter.TokenPos();
-    if ((!pos.IsReal()) || (pos < requested_token_pos) ||
-        (pos > last_token_pos)) {
-      // Token is not in the target range.
-      continue;
-    }
+  // best_token_pos and exact_token_pos are only used
+  // if column number is provided.
+  TokenPosition best_token_pos = TokenPosition::kNoSource;
 
-    intptr_t token_start_column = -1;
-    intptr_t token_line = -1;
-    if (requested_column >= 0) {
-      intptr_t token_len = -1;
-      // TODO(turnidge): GetTokenLocation is a very expensive
-      // operation, and this code will blow up when we are setting
-      // column breakpoints on, for example, a large, single-line
-      // program.  Consider rewriting this code so that it only scans
-      // the program code once and caches the token positions and
-      // lengths.
-      script.GetTokenLocation(pos, &token_line, &token_start_column,
-                              &token_len);
-      intptr_t token_end_column = token_start_column + token_len - 1;
-      if ((token_end_column < requested_column) ||
-          (token_start_column > best_column)) {
-        // Prefer the token with the lowest column number compatible
-        // with the requested column.
+  if (in_bytecode) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
+    while (iter.MoveNext()) {
+      const TokenPosition pos = iter.TokenPos();
+      if ((!pos.IsReal()) || (pos < requested_token_pos) ||
+          (pos > last_token_pos)) {
+        // Token is not in the target range.
         continue;
       }
-    }
 
-    // Prefer the lowest (first) token pos.
-    if (pos < best_fit_pos) {
-      best_fit_pos = pos;
-      best_line = token_line;
-      best_column = token_start_column;
+      intptr_t token_start_column = -1;
+      intptr_t token_line = -1;
+      if (requested_column >= 0) {
+        kernel::BytecodeSourcePositionsIterator iter2(zone, bytecode);
+        TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
+        while (iter2.MoveNext()) {
+          const TokenPosition next = iter2.TokenPos();
+          if (next < next_closest_token_position && next > pos) {
+            next_closest_token_position = next;
+          }
+        }
+
+        TokenPosition ignored;
+        TokenPosition end_of_line_pos;
+        script.GetTokenLocation(pos, &token_line, &token_start_column);
+        script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
+        TokenPosition token_end_pos =
+            (end_of_line_pos < next_closest_token_position)
+                ? end_of_line_pos
+                : next_closest_token_position;
+
+        if ((token_end_pos < exact_token_pos) ||
+            (token_start_column > best_column)) {
+          // Prefer the token with the lowest column number compatible
+          // with the requested column.
+          continue;
+        }
+      }
+
+      // Prefer the lowest (first) token pos.
+      if (pos < best_fit_pos) {
+        best_fit_pos = pos;
+        best_line = token_line;
+        best_column = token_start_column;
+        // best_token_pos is only used when column number is specified.
+        best_token_pos = TokenPosition(exact_token_pos.value() -
+                                       (requested_column - best_column));
+      }
+    }
+#else
+    UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  } else {
+    PcDescriptors::Iterator iter(desc, kSafepointKind);
+    while (iter.MoveNext()) {
+      const TokenPosition pos = iter.TokenPos();
+      if ((!pos.IsReal()) || (pos < requested_token_pos) ||
+          (pos > last_token_pos)) {
+        // Token is not in the target range.
+        continue;
+      }
+
+      intptr_t token_start_column = -1;
+      intptr_t token_line = -1;
+      if (requested_column >= 0) {
+        // Find next closest safepoint
+        PcDescriptors::Iterator iter2(desc, kSafepointKind);
+        TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
+        while (iter2.MoveNext()) {
+          const TokenPosition next = iter2.TokenPos();
+          if (next < next_closest_token_position && next > pos) {
+            next_closest_token_position = next;
+          }
+        }
+
+        TokenPosition ignored;
+        TokenPosition end_of_line_pos;
+        script.GetTokenLocation(pos, &token_line, &token_start_column);
+        script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
+        TokenPosition token_end_pos =
+            (end_of_line_pos < next_closest_token_position)
+                ? end_of_line_pos
+                : next_closest_token_position;
+
+        if ((token_end_pos < exact_token_pos) ||
+            (token_start_column > best_column)) {
+          // Prefer the token with the lowest column number compatible
+          // with the requested column.
+          continue;
+        }
+      }
+
+      // Prefer the lowest (first) token pos.
+      if (pos < best_fit_pos) {
+        best_fit_pos = pos;
+        best_line = token_line;
+        best_column = token_start_column;
+        // best_token_pos is only used when column number is specified.
+        best_token_pos = TokenPosition(exact_token_pos.value() -
+                                       (requested_column - best_column));
+      }
     }
   }
 
@@ -2511,29 +2842,51 @@
     }
 
     uword lowest_pc_offset = kUwordMax;
-    PcDescriptors::Iterator iter(desc, kSafepointKind);
-    while (iter.MoveNext()) {
-      const TokenPosition pos = iter.TokenPos();
-      if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
-        // Token is not on same line as best fit.
-        continue;
-      }
-
-      if (requested_column >= 0) {
-        intptr_t ignored = -1;
-        intptr_t token_start_column = -1;
-        // We look for other tokens at the best column in case there
-        // is more than one token at the same column offset.
-        script.GetTokenLocation(pos, &ignored, &token_start_column);
-        if (token_start_column != best_column) {
+    if (in_bytecode) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+      kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
+      while (iter.MoveNext()) {
+        const TokenPosition pos = iter.TokenPos();
+        if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
+          // Token is not on same line as best fit.
           continue;
         }
-      }
 
-      // Prefer the lowest pc offset.
-      if (iter.PcOffset() < lowest_pc_offset) {
-        lowest_pc_offset = iter.PcOffset();
-        best_fit_pos = pos;
+        if (requested_column >= 0) {
+          if (pos != best_token_pos) {
+            continue;
+          }
+        }
+
+        // Prefer the lowest pc offset.
+        if (iter.PcOffset() < lowest_pc_offset) {
+          lowest_pc_offset = iter.PcOffset();
+          best_fit_pos = pos;
+        }
+      }
+#else
+      UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+    } else {
+      PcDescriptors::Iterator iter(desc, kSafepointKind);
+      while (iter.MoveNext()) {
+        const TokenPosition pos = iter.TokenPos();
+        if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
+          // Token is not on same line as best fit.
+          continue;
+        }
+
+        if (requested_column >= 0) {
+          if (pos != best_token_pos) {
+            continue;
+          }
+        }
+
+        // Prefer the lowest pc offset.
+        if (iter.PcOffset() < lowest_pc_offset) {
+          lowest_pc_offset = iter.PcOffset();
+          best_fit_pos = pos;
+        }
       }
     }
     return best_fit_pos;
@@ -2544,54 +2897,129 @@
   // Since we have moved to the next line of the function, we no
   // longer are requesting a specific column number.
   if (last_token_pos < func.end_token_pos()) {
-    return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(),
-                                -1 /* no column */);
+    return ResolveBreakpointPos(in_bytecode, func, last_token_pos,
+                                func.end_token_pos(), -1 /* no column */,
+                                TokenPosition::kNoSource);
   }
   return TokenPosition::kNoSource;
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+// Find a 'debug break checked' bytecode in the range [pc..end_pc[ and return
+// the pc after it or nullptr.
+static const KBCInstr* FindBreakpointCheckedInstr(const KBCInstr* pc,
+                                                  const KBCInstr* end_pc) {
+  while ((pc < end_pc) && !KernelBytecode::IsDebugBreakCheckedOpcode(pc)) {
+    pc = KernelBytecode::Next(pc);
+  }
+  if (pc < end_pc) {
+    ASSERT(KernelBytecode::IsDebugBreakCheckedOpcode(pc));
+    // The checked debug break pc must point to the next bytecode.
+    return KernelBytecode::Next(pc);
+  }
+  // No 'debug break checked' bytecode in the range.
+  return nullptr;
+}
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
 void Debugger::MakeCodeBreakpointAt(const Function& func,
                                     BreakpointLocation* loc) {
   ASSERT(loc->token_pos_.IsReal());
   ASSERT((loc != NULL) && loc->IsResolved());
   ASSERT(!func.HasOptimizedCode());
-  Code& code = Code::Handle(func.unoptimized_code());
-  ASSERT(!code.IsNull());
-  PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
-  uword lowest_pc_offset = kUwordMax;
-  RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind;
-  // Find the safe point with the lowest compiled code address
-  // that maps to the token position of the source breakpoint.
-  PcDescriptors::Iterator iter(desc, kSafepointKind);
-  while (iter.MoveNext()) {
-    if (iter.TokenPos() == loc->token_pos_) {
-      if (iter.PcOffset() < lowest_pc_offset) {
-        lowest_pc_offset = iter.PcOffset();
-        lowest_kind = iter.Kind();
+  ASSERT(func.HasCode() || func.HasBytecode());
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (func.HasBytecode()) {
+    Bytecode& bytecode = Bytecode::Handle(func.bytecode());
+    ASSERT(!bytecode.IsNull());
+    const KBCInstr* pc = nullptr;
+    if (bytecode.HasSourcePositions()) {
+      kernel::BytecodeSourcePositionsIterator iter(Thread::Current()->zone(),
+                                                   bytecode);
+      bool check_range = false;
+      while (iter.MoveNext()) {
+        if (check_range) {
+          const KBCInstr* end_pc =
+              reinterpret_cast<const KBCInstr*>(bytecode.PayloadStart()) +
+              iter.PcOffset();
+          check_range = false;
+          // Find a 'debug break checked' bytecode in the range [pc..end_pc[.
+          pc = FindBreakpointCheckedInstr(pc, end_pc);
+          if (pc != nullptr) {
+            // TODO(regis): We may want to find all PCs for a token position,
+            // e.g. in the case of duplicated bytecode in finally clauses.
+            break;
+          }
+        }
+        if (iter.TokenPos() == loc->token_pos_) {
+          pc = reinterpret_cast<const KBCInstr*>(bytecode.PayloadStart()) +
+               iter.PcOffset();
+          check_range = true;
+        }
+      }
+      if (check_range) {
+        ASSERT(pc != nullptr);
+        // Use the end of the bytecode as the end of the range to check.
+        pc = FindBreakpointCheckedInstr(
+            pc, reinterpret_cast<const KBCInstr*>(bytecode.PayloadStart()) +
+                    bytecode.Size());
+      }
+    }
+    if (pc != nullptr) {
+      CodeBreakpoint* code_bpt = GetCodeBreakpoint(reinterpret_cast<uword>(pc));
+      if (code_bpt == NULL) {
+        // No code breakpoint for this code exists; create one.
+        code_bpt = new CodeBreakpoint(bytecode, loc->token_pos_,
+                                      reinterpret_cast<uword>(pc));
+        RegisterCodeBreakpoint(code_bpt);
+      }
+      code_bpt->set_bpt_location(loc);
+      if (loc->AnyEnabled()) {
+        code_bpt->Enable();
       }
     }
   }
-  if (lowest_pc_offset == kUwordMax) {
-    return;
-  }
-  uword lowest_pc = code.PayloadStart() + lowest_pc_offset;
-  CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
-  if (code_bpt == NULL) {
-    // No code breakpoint for this code exists; create one.
-    code_bpt =
-        new CodeBreakpoint(code, loc->token_pos_, lowest_pc, lowest_kind);
-    RegisterCodeBreakpoint(code_bpt);
-  }
-  code_bpt->set_bpt_location(loc);
-  if (loc->AnyEnabled()) {
-    code_bpt->Enable();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  if (func.HasCode()) {
+    Code& code = Code::Handle(func.unoptimized_code());
+    ASSERT(!code.IsNull());
+    PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
+    uword lowest_pc_offset = kUwordMax;
+    RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind;
+    // Find the safe point with the lowest compiled code address
+    // that maps to the token position of the source breakpoint.
+    PcDescriptors::Iterator iter(desc, kSafepointKind);
+    while (iter.MoveNext()) {
+      if (iter.TokenPos() == loc->token_pos_) {
+        if (iter.PcOffset() < lowest_pc_offset) {
+          lowest_pc_offset = iter.PcOffset();
+          lowest_kind = iter.Kind();
+        }
+      }
+    }
+    if (lowest_pc_offset != kUwordMax) {
+      uword lowest_pc = code.PayloadStart() + lowest_pc_offset;
+      CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
+      if (code_bpt == NULL) {
+        // No code breakpoint for this code exists; create one.
+        code_bpt =
+            new CodeBreakpoint(code, loc->token_pos_, lowest_pc, lowest_kind);
+        RegisterCodeBreakpoint(code_bpt);
+      }
+      code_bpt->set_bpt_location(loc);
+      if (loc->AnyEnabled()) {
+        code_bpt->Enable();
+      }
+    }
   }
 }
 
-void Debugger::FindCompiledFunctions(const Script& script,
-                                     TokenPosition start_pos,
-                                     TokenPosition end_pos,
-                                     GrowableObjectArray* function_list) {
+void Debugger::FindCompiledFunctions(
+    const Script& script,
+    TokenPosition start_pos,
+    TokenPosition end_pos,
+    GrowableObjectArray* bytecode_function_list,
+    GrowableObjectArray* code_function_list) {
   Zone* zone = Thread::Current()->zone();
   Class& cls = Class::Handle(zone);
   Array& functions = Array::Handle(zone);
@@ -2606,13 +3034,23 @@
     if ((function.token_pos() == start_pos) &&
         (function.end_token_pos() == end_pos) &&
         (function.script() == script.raw())) {
-      if (function.HasCode() && function.is_debuggable()) {
-        function_list->Add(function);
+      if (function.is_debuggable()) {
+        if (function.HasBytecode()) {
+          bytecode_function_list->Add(function);
+        }
+        if (function.HasCode()) {
+          code_function_list->Add(function);
+        }
       }
       if (function.HasImplicitClosureFunction()) {
         function = function.ImplicitClosureFunction();
-        if (function.HasCode() && function.is_debuggable()) {
-          function_list->Add(function);
+        if (function.is_debuggable()) {
+          if (function.HasBytecode()) {
+            bytecode_function_list->Add(function);
+          }
+          if (function.HasCode()) {
+            code_function_list->Add(function);
+          }
         }
       }
     }
@@ -2644,13 +3082,23 @@
           if ((function.token_pos() == start_pos) &&
               (function.end_token_pos() == end_pos) &&
               (function.script() == script.raw())) {
-            if (function.HasCode() && function.is_debuggable()) {
-              function_list->Add(function);
+            if (function.is_debuggable()) {
+              if (function.HasBytecode()) {
+                bytecode_function_list->Add(function);
+              }
+              if (function.HasCode()) {
+                code_function_list->Add(function);
+              }
             }
             if (function.HasImplicitClosureFunction()) {
               function = function.ImplicitClosureFunction();
-              if (function.HasCode() && function.is_debuggable()) {
-                function_list->Add(function);
+              if (function.is_debuggable()) {
+                if (function.HasBytecode()) {
+                  bytecode_function_list->Add(function);
+                }
+                if (function.HasCode()) {
+                  code_function_list->Add(function);
+                }
               }
             }
           }
@@ -2782,6 +3230,71 @@
   return false;
 }
 
+BreakpointLocation* Debugger::SetCodeBreakpoints(
+    bool in_bytecode,
+    BreakpointLocation* loc,
+    const Script& script,
+    TokenPosition token_pos,
+    TokenPosition last_token_pos,
+    intptr_t requested_line,
+    intptr_t requested_column,
+    TokenPosition exact_token_pos,
+    const GrowableObjectArray& functions) {
+  Function& function = Function::Handle();
+  function ^= functions.At(0);
+  TokenPosition breakpoint_pos =
+      ResolveBreakpointPos(in_bytecode, function, token_pos, last_token_pos,
+                           requested_column, exact_token_pos);
+  if (!breakpoint_pos.IsReal()) {
+    return NULL;
+  }
+  if (loc == NULL) {
+    // Find an existing resolved breakpoint location.
+    loc = GetBreakpointLocation(
+        script, TokenPosition::kNoSource,
+        /* requested_line = */ -1,
+        /* requested_column = */ -1,
+        in_bytecode ? breakpoint_pos : TokenPosition::kNoSource,
+        !in_bytecode ? breakpoint_pos : TokenPosition::kNoSource);
+  }
+  if (loc == NULL) {
+    // Find an existing unresolved breakpoint location.
+    loc = GetBreakpointLocation(script, token_pos, requested_line,
+                                requested_column);
+  }
+  if (loc == NULL) {
+    loc = new BreakpointLocation(script, breakpoint_pos, breakpoint_pos,
+                                 requested_line, requested_column);
+    RegisterBreakpointLocation(loc);
+  }
+  // A source breakpoint for this location may already exists, but it may
+  // not yet be resolved in both bytecode and code.
+  if (loc->IsResolved(in_bytecode)) {
+    return loc;
+  }
+  loc->SetResolved(in_bytecode, function, breakpoint_pos);
+
+  // Create code breakpoints for all compiled functions we found.
+  Function& func = Function::Handle();
+  const intptr_t num_functions = functions.Length();
+  for (intptr_t i = 0; i < num_functions; i++) {
+    func ^= functions.At(i);
+    ASSERT((in_bytecode && func.HasBytecode()) ||
+           (!in_bytecode && func.HasCode()));
+    MakeCodeBreakpointAt(func, loc);
+  }
+  if (FLAG_verbose_debug) {
+    intptr_t line_number;
+    intptr_t column_number;
+    script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
+    OS::PrintErr(
+        "Resolved BP for "
+        "function '%s' at line %" Pd " col %" Pd "\n",
+        func.ToFullyQualifiedCString(), line_number, column_number);
+  }
+  return loc;
+}
+
 BreakpointLocation* Debugger::SetBreakpoint(const Script& script,
                                             TokenPosition token_pos,
                                             TokenPosition last_token_pos,
@@ -2793,57 +3306,54 @@
     if (!FindBestFit(script, token_pos, last_token_pos, &func)) {
       return NULL;
     }
+    // If func was not set (still Null), the best fit is a field.
   } else {
     func = function.raw();
+    if (!func.token_pos().IsReal()) {
+      return NULL;  // Missing source positions in bytecode?
+    }
   }
-
   if (!func.IsNull()) {
     // There may be more than one function object for a given function
     // in source code. There may be implicit closure functions, and
     // there may be copies of mixin functions. Collect all compiled
     // functions whose source code range matches exactly the best fit
     // function we found.
-    GrowableObjectArray& functions =
+    GrowableObjectArray& bytecode_functions =
+        GrowableObjectArray::Handle(GrowableObjectArray::New());
+    GrowableObjectArray& code_functions =
         GrowableObjectArray::Handle(GrowableObjectArray::New());
     FindCompiledFunctions(script, func.token_pos(), func.end_token_pos(),
-                          &functions);
+                          &bytecode_functions, &code_functions);
 
-    if (functions.Length() > 0) {
+    if (bytecode_functions.Length() > 0 || code_functions.Length() > 0) {
       // One or more function object containing this breakpoint location
       // have already been compiled. We can resolve the breakpoint now.
-      DeoptimizeWorld();
-      func ^= functions.At(0);
-      TokenPosition breakpoint_pos = ResolveBreakpointPos(
-          func, token_pos, last_token_pos, requested_column);
-      if (breakpoint_pos.IsReal()) {
-        BreakpointLocation* bpt =
-            GetBreakpointLocation(script, breakpoint_pos, requested_column);
-        if (bpt != NULL) {
-          // A source breakpoint for this location already exists.
-          return bpt;
-        }
-        bpt = new BreakpointLocation(script, token_pos, last_token_pos,
-                                     requested_line, requested_column);
-        bpt->SetResolved(func, breakpoint_pos);
-        RegisterBreakpointLocation(bpt);
-
-        // Create code breakpoints for all compiled functions we found.
-        const intptr_t num_functions = functions.Length();
-        for (intptr_t i = 0; i < num_functions; i++) {
-          func ^= functions.At(i);
-          ASSERT(func.HasCode());
-          MakeCodeBreakpointAt(func, bpt);
-        }
-        if (FLAG_verbose_debug) {
-          intptr_t line_number;
-          intptr_t column_number;
-          script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
-          OS::PrintErr(
-              "Resolved BP for "
-              "function '%s' at line %" Pd " col %" Pd "\n",
-              func.ToFullyQualifiedCString(), line_number, column_number);
-        }
-        return bpt;
+      // If requested_column is larger than zero, [token_pos, last_token_pos]
+      // governs one single line of code.
+      TokenPosition exact_token_pos = TokenPosition(-1);
+      if (token_pos != last_token_pos && requested_column >= 0) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        exact_token_pos =
+            FindExactTokenPosition(script, token_pos, requested_column);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+      }
+      // Since source positions may differ in code and bytecode, process
+      // breakpoints in bytecode and code separately.
+      BreakpointLocation* loc = NULL;
+      if (bytecode_functions.Length() > 0) {
+        loc = SetCodeBreakpoints(true, loc, script, token_pos, last_token_pos,
+                                 requested_line, requested_column,
+                                 exact_token_pos, bytecode_functions);
+      }
+      if (code_functions.Length() > 0) {
+        DeoptimizeWorld();
+        loc = SetCodeBreakpoints(false, loc, script, token_pos, last_token_pos,
+                                 requested_line, requested_column,
+                                 exact_token_pos, code_functions);
+      }
+      if (loc != NULL) {
+        return loc;
       }
     }
   }
@@ -2866,14 +3376,14 @@
           func.ToFullyQualifiedCString(), line_number, column_number);
     }
   }
-  BreakpointLocation* bpt =
-      GetBreakpointLocation(script, token_pos, requested_column);
-  if (bpt == NULL) {
-    bpt = new BreakpointLocation(script, token_pos, last_token_pos,
+  BreakpointLocation* loc =
+      GetBreakpointLocation(script, token_pos, -1, requested_column);
+  if (loc == NULL) {
+    loc = new BreakpointLocation(script, token_pos, last_token_pos,
                                  requested_line, requested_column);
-    RegisterBreakpointLocation(bpt);
+    RegisterBreakpointLocation(loc);
   }
-  return bpt;
+  return loc;
 }
 
 // Synchronize the enabled/disabled state of all code breakpoints
@@ -3042,32 +3552,32 @@
     return NULL;
   }
 
-  BreakpointLocation* bpt = NULL;
+  BreakpointLocation* loc = NULL;
   ASSERT(first_token_idx <= last_token_idx);
-  while ((bpt == NULL) && (first_token_idx <= last_token_idx)) {
-    bpt = SetBreakpoint(script, first_token_idx, last_token_idx, line_number,
+  while ((loc == NULL) && (first_token_idx <= last_token_idx)) {
+    loc = SetBreakpoint(script, first_token_idx, last_token_idx, line_number,
                         column_number, Function::Handle());
     first_token_idx.Next();
   }
-  if ((bpt == NULL) && FLAG_verbose_debug) {
+  if ((loc == NULL) && FLAG_verbose_debug) {
     OS::PrintErr("No executable code at line %" Pd " in '%s'\n", line_number,
                  script_url.ToCString());
   }
-  return bpt;
+  return loc;
 }
 
 // static
 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   ASSERT(visitor != NULL);
-  BreakpointLocation* bpt = breakpoint_locations_;
-  while (bpt != NULL) {
-    bpt->VisitObjectPointers(visitor);
-    bpt = bpt->next();
+  BreakpointLocation* loc = breakpoint_locations_;
+  while (loc != NULL) {
+    loc->VisitObjectPointers(visitor);
+    loc = loc->next();
   }
-  bpt = latent_locations_;
-  while (bpt != NULL) {
-    bpt->VisitObjectPointers(visitor);
-    bpt = bpt->next();
+  loc = latent_locations_;
+  while (loc != NULL) {
+    loc->VisitObjectPointers(visitor);
+    loc = loc->next();
   }
   CodeBreakpoint* cbpt = code_breakpoints_;
   while (cbpt != NULL) {
@@ -3123,7 +3633,7 @@
 void Debugger::EnterSingleStepMode() {
   ResetSteppingFramePointers();
   DeoptimizeWorld();
-  isolate_->set_single_step(true);
+  NotifySingleStepping(true);
 }
 
 void Debugger::ResetSteppingFramePointers() {
@@ -3185,7 +3695,7 @@
     // as well.  We need to deoptimize the world in case we are about
     // to call an optimized function.
     DeoptimizeWorld();
-    isolate_->set_single_step(true);
+    NotifySingleStepping(true);
     skip_next_step_ = skip_next_step;
     SetAsyncSteppingFramePointer(stack_trace);
     if (FLAG_verbose_debug) {
@@ -3193,7 +3703,7 @@
     }
   } else if (resume_action_ == kStepOver) {
     DeoptimizeWorld();
-    isolate_->set_single_step(true);
+    NotifySingleStepping(true);
     skip_next_step_ = skip_next_step;
     SetSyncSteppingFramePointer(stack_trace);
     SetAsyncSteppingFramePointer(stack_trace);
@@ -3217,7 +3727,7 @@
     }
     // Fall through to synchronous stepping.
     DeoptimizeWorld();
-    isolate_->set_single_step(true);
+    NotifySingleStepping(true);
     // Find topmost caller that is debuggable.
     for (intptr_t i = 1; i < stack_trace->Length(); i++) {
       ActivationFrame* frame = stack_trace->FrameAt(i);
@@ -3498,10 +4008,16 @@
   return lib.IsDebuggable();
 }
 
+bool Debugger::IsDebugging(Thread* thread, const Function& func) {
+  Debugger* debugger = thread->isolate()->debugger();
+  return debugger->IsStepping() ||
+         debugger->HasBreakpoint(func, thread->zone());
+}
+
 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) {
   resume_action_ = kContinue;
   ResetSteppingFramePointers();
-  isolate_->set_single_step(false);
+  NotifySingleStepping(false);
   ASSERT(!IsPaused());
   if ((bpt != NULL) && bpt->IsSingleShot()) {
     RemoveBreakpoint(bpt->id());
@@ -3793,7 +4309,23 @@
   return best_fit.raw();
 }
 
-void Debugger::NotifyCompilation(const Function& func) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+// On single line of code with given column number,
+// Calculate exact tokenPosition
+TokenPosition Debugger::FindExactTokenPosition(const Script& script,
+                                               TokenPosition start_of_line,
+                                               intptr_t column_number) {
+  intptr_t line = -1;
+  intptr_t col = -1;
+  Zone* zone = Thread::Current()->zone();
+  kernel::KernelLineStartsReader line_starts_reader(
+      TypedData::Handle(zone, script.line_starts()), zone);
+  line_starts_reader.LocationForPosition(start_of_line.value(), &line, &col);
+  return TokenPosition(start_of_line.value() + (column_number - col));
+}
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
+void Debugger::HandleCodeChange(bool bytecode_loaded, const Function& func) {
   if (breakpoint_locations_ == NULL) {
     // Return with minimal overhead if there are no breakpoints.
     return;
@@ -3814,7 +4346,20 @@
     if (FunctionOverlaps(func, script, loc->token_pos(),
                          loc->end_token_pos())) {
       Function& inner_function = Function::Handle(zone);
-      inner_function = FindInnermostClosure(func, loc->token_pos());
+      TokenPosition token_pos = loc->token_pos();
+      TokenPosition end_token_pos = loc->end_token_pos();
+      if (token_pos != end_token_pos && loc->requested_column_number() >= 0) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        // Narrow down the token position range to a single value
+        // if requested column number is provided so that inner
+        // Closure won't be missed.
+        token_pos = FindExactTokenPosition(script, token_pos,
+                                           loc->requested_column_number());
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+      }
+      // TODO(regis): Bytecode closures are not currently added to
+      // object_store()->closure_functions(). Should they? Revisit.
+      inner_function = FindInnermostClosure(func, token_pos);
       if (!inner_function.IsNull()) {
         // The local function of a function we just compiled cannot
         // be compiled already.
@@ -3833,11 +4378,11 @@
       // There is no local function within func that contains the
       // breakpoint token position. Resolve the breakpoint if necessary
       // and set the code breakpoints.
-      if (!loc->IsResolved()) {
+      if (!loc->IsResolved(bytecode_loaded)) {
         // Resolve source breakpoint in the newly compiled function.
-        TokenPosition bp_pos =
-            ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(),
-                                 loc->requested_column_number());
+        TokenPosition bp_pos = ResolveBreakpointPos(
+            bytecode_loaded, func, loc->token_pos(), loc->end_token_pos(),
+            loc->requested_column_number(), token_pos);
         if (!bp_pos.IsDebugPause()) {
           if (FLAG_verbose_debug) {
             OS::PrintErr("Failed resolving breakpoint for function '%s'\n",
@@ -3847,34 +4392,28 @@
         }
         TokenPosition requested_pos = loc->token_pos();
         TokenPosition requested_end_pos = loc->end_token_pos();
-        loc->SetResolved(func, bp_pos);
+        loc->SetResolved(bytecode_loaded, func, bp_pos);
         Breakpoint* bpt = loc->breakpoints();
         while (bpt != NULL) {
           if (FLAG_verbose_debug) {
             OS::PrintErr(
                 "Resolved BP %" Pd
                 " to pos %s, "
-                "line %" Pd " col %" Pd
-                ", "
                 "function '%s' (requested range %s-%s, "
                 "requested col %" Pd ")\n",
-                bpt->id(), loc->token_pos().ToCString(), loc->LineNumber(),
-                loc->ColumnNumber(), func.ToFullyQualifiedCString(),
-                requested_pos.ToCString(), requested_end_pos.ToCString(),
-                loc->requested_column_number());
+                bpt->id(), loc->token_pos().ToCString(),
+                func.ToFullyQualifiedCString(), requested_pos.ToCString(),
+                requested_end_pos.ToCString(), loc->requested_column_number());
           }
           SendBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
           bpt = bpt->next();
         }
       }
-      ASSERT(loc->IsResolved());
+      ASSERT(loc->IsResolved(bytecode_loaded));
       if (FLAG_verbose_debug) {
         Breakpoint* bpt = loc->breakpoints();
         while (bpt != NULL) {
-          OS::PrintErr("Setting breakpoint %" Pd " at line %" Pd " col %" Pd
-                       ""
-                       " for %s '%s'\n",
-                       bpt->id(), loc->LineNumber(), loc->ColumnNumber(),
+          OS::PrintErr("Setting breakpoint %" Pd " for %s '%s'\n", bpt->id(),
                        func.IsClosureFunction() ? "closure" : "function",
                        String::Handle(func.name()).ToCString());
           bpt = bpt->next();
@@ -3944,7 +4483,7 @@
           // If there is one, assert in debug build but silently drop
           // the latent breakpoint in release build.
           BreakpointLocation* existing_loc =
-              GetBreakpointLocation(script, first_token_pos, column_number);
+              GetBreakpointLocation(script, first_token_pos, -1, column_number);
           ASSERT(existing_loc == NULL);
           if (existing_loc == NULL) {
             // Create and register a new source breakpoint for the
@@ -4004,25 +4543,25 @@
 // TODO(hausner): Could potentially make this faster by checking
 // whether the call target at pc is a debugger stub.
 bool Debugger::HasActiveBreakpoint(uword pc) {
-  CodeBreakpoint* bpt = GetCodeBreakpoint(pc);
-  return (bpt != NULL) && (bpt->IsEnabled());
+  CodeBreakpoint* cbpt = GetCodeBreakpoint(pc);
+  return (cbpt != NULL) && (cbpt->IsEnabled());
 }
 
 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) {
-  CodeBreakpoint* bpt = code_breakpoints_;
-  while (bpt != NULL) {
-    if (bpt->pc() == breakpoint_address) {
-      return bpt;
+  CodeBreakpoint* cbpt = code_breakpoints_;
+  while (cbpt != NULL) {
+    if (cbpt->pc() == breakpoint_address) {
+      return cbpt;
     }
-    bpt = bpt->next();
+    cbpt = cbpt->next();
   }
   return NULL;
 }
 
 RawCode* Debugger::GetPatchedStubAddress(uword breakpoint_address) {
-  CodeBreakpoint* bpt = GetCodeBreakpoint(breakpoint_address);
-  if (bpt != NULL) {
-    return bpt->OrigStubAddress();
+  CodeBreakpoint* cbpt = GetCodeBreakpoint(breakpoint_address);
+  if (cbpt != NULL) {
+    return cbpt->OrigStubAddress();
   }
   UNREACHABLE();
   return Code::null();
@@ -4147,16 +4686,28 @@
   needs_breakpoint_cleanup_ = false;
 }
 
-BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script,
-                                                    TokenPosition token_pos,
-                                                    intptr_t requested_column) {
-  BreakpointLocation* bpt = breakpoint_locations_;
-  while (bpt != NULL) {
-    if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos) &&
-        (bpt->requested_column_number_ == requested_column)) {
-      return bpt;
+BreakpointLocation* Debugger::GetBreakpointLocation(
+    const Script& script,
+    TokenPosition token_pos,
+    intptr_t requested_line,
+    intptr_t requested_column,
+    TokenPosition bytecode_token_pos,
+    TokenPosition code_token_pos) {
+  BreakpointLocation* loc = breakpoint_locations_;
+  while (loc != NULL) {
+    if (loc->script_ == script.raw() &&
+        (!token_pos.IsReal() || (loc->token_pos_ == token_pos)) &&
+        ((requested_line == -1) ||
+         (loc->requested_line_number_ == requested_line)) &&
+        ((requested_column == -1) ||
+         (loc->requested_column_number_ == requested_column)) &&
+        (!bytecode_token_pos.IsReal() ||
+         (loc->bytecode_token_pos_ == bytecode_token_pos)) &&
+        (!code_token_pos.IsReal() ||
+         (loc->code_token_pos_ == code_token_pos))) {
+      return loc;
     }
-    bpt = bpt->next();
+    loc = loc->next();
   }
   return NULL;
 }
@@ -4202,39 +4753,39 @@
   SetResumeAction(kContinue);
   stepping_fp_ = 0;
   async_stepping_fp_ = 0;
-  isolate_->set_single_step(false);
+  NotifySingleStepping(false);
 }
 
 BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url,
                                                   intptr_t line,
                                                   intptr_t column) {
-  BreakpointLocation* bpt = latent_locations_;
+  BreakpointLocation* loc = latent_locations_;
   String& bpt_url = String::Handle();
-  while (bpt != NULL) {
-    bpt_url = bpt->url();
-    if (bpt_url.Equals(url) && (bpt->requested_line_number() == line) &&
-        (bpt->requested_column_number() == column)) {
-      return bpt;
+  while (loc != NULL) {
+    bpt_url = loc->url();
+    if (bpt_url.Equals(url) && (loc->requested_line_number() == line) &&
+        (loc->requested_column_number() == column)) {
+      return loc;
     }
-    bpt = bpt->next();
+    loc = loc->next();
   }
   // No breakpoint for this location requested. Allocate new one.
-  bpt = new BreakpointLocation(url, line, column);
-  bpt->set_next(latent_locations_);
-  latent_locations_ = bpt;
-  return bpt;
+  loc = new BreakpointLocation(url, line, column);
+  loc->set_next(latent_locations_);
+  latent_locations_ = loc;
+  return loc;
 }
 
-void Debugger::RegisterBreakpointLocation(BreakpointLocation* bpt) {
-  ASSERT(bpt->next() == NULL);
-  bpt->set_next(breakpoint_locations_);
-  breakpoint_locations_ = bpt;
+void Debugger::RegisterBreakpointLocation(BreakpointLocation* loc) {
+  ASSERT(loc->next() == NULL);
+  loc->set_next(breakpoint_locations_);
+  breakpoint_locations_ = loc;
 }
 
-void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
-  ASSERT(bpt->next() == NULL);
-  bpt->set_next(code_breakpoints_);
-  code_breakpoints_ = bpt;
+void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* cbpt) {
+  ASSERT(cbpt->next() == NULL);
+  cbpt->set_next(code_breakpoints_);
+  code_breakpoints_ = cbpt;
 }
 
 #endif  // !PRODUCT
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index d15fbb9..39a2c89 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -7,6 +7,7 @@
 
 #include "include/dart_tools_api.h"
 
+#include "vm/constants_kbc.h"
 #include "vm/kernel_isolate.h"
 #include "vm/object.h"
 #include "vm/port.h"
@@ -140,12 +141,7 @@
   intptr_t requested_line_number() const { return requested_line_number_; }
   intptr_t requested_column_number() const { return requested_column_number_; }
 
-  intptr_t LineNumber();
-  intptr_t ColumnNumber();
-
-  void GetCodeLocation(Library* lib,
-                       Script* script,
-                       TokenPosition* token_pos) const;
+  void GetCodeLocation(Script* script, TokenPosition* token_pos) const;
 
   Breakpoint* AddRepeated(Debugger* dbg);
   Breakpoint* AddSingleShot(Debugger* dbg);
@@ -154,13 +150,21 @@
                             bool for_over_await);
 
   bool AnyEnabled() const;
-  bool IsResolved() const { return is_resolved_; }
+  bool IsResolved() const {
+    return bytecode_token_pos_.IsReal() || code_token_pos_.IsReal();
+  }
+  bool IsResolved(bool in_bytecode) const {
+    return in_bytecode ? bytecode_token_pos_.IsReal()
+                       : code_token_pos_.IsReal();
+  }
   bool IsLatent() const { return !token_pos_.IsReal(); }
 
  private:
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
-  void SetResolved(const Function& func, TokenPosition token_pos);
+  void SetResolved(bool in_bytecode,
+                   const Function& func,
+                   TokenPosition token_pos);
 
   BreakpointLocation* next() const { return this->next_; }
   void set_next(BreakpointLocation* value) { next_ = value; }
@@ -174,7 +178,6 @@
   RawString* url_;
   TokenPosition token_pos_;
   TokenPosition end_token_pos_;
-  bool is_resolved_;
   BreakpointLocation* next_;
   Breakpoint* conditions_;
   intptr_t requested_line_number_;
@@ -182,22 +185,23 @@
 
   // Valid for resolved breakpoints:
   RawFunction* function_;
-  intptr_t line_number_;
-  intptr_t column_number_;
+  TokenPosition bytecode_token_pos_;
+  TokenPosition code_token_pos_;
 
   friend class Debugger;
   DISALLOW_COPY_AND_ASSIGN(BreakpointLocation);
 };
 
-// CodeBreakpoint represents a location in compiled code. There may be
-// more than one CodeBreakpoint for one BreakpointLocation, e.g. when a
-// function gets compiled as a regular function and as a closure.
+// CodeBreakpoint represents a location in compiled or interpreted code.
+// There may be more than one CodeBreakpoint for one BreakpointLocation,
+// e.g. when a function gets compiled as a regular function and as a closure.
 class CodeBreakpoint {
  public:
   CodeBreakpoint(const Code& code,
                  TokenPosition token_pos,
                  uword pc,
                  RawPcDescriptors::Kind kind);
+  CodeBreakpoint(const Bytecode& bytecode, TokenPosition token_pos, uword pc);
   ~CodeBreakpoint();
 
   RawFunction* function() const;
@@ -211,6 +215,7 @@
   void Enable();
   void Disable();
   bool IsEnabled() const { return is_enabled_; }
+  bool IsInterpreted() const { return bytecode_ != Bytecode::null(); }
 
   RawCode* OrigStubAddress() const;
 
@@ -225,8 +230,11 @@
 
   void PatchCode();
   void RestoreCode();
+  void SetBytecodeBreakpoint();
+  void UnsetBytecodeBreakpoint();
 
   RawCode* code_;
+  RawBytecode* bytecode_;
   TokenPosition token_pos_;
   uword pc_;
   intptr_t line_number_;
@@ -271,6 +279,16 @@
 
   ActivationFrame(uword pc, const Code& code);
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  ActivationFrame(uword pc,
+                  uword fp,
+                  uword sp,
+                  const Bytecode& bytecode,
+                  Kind kind = kRegular);
+
+  ActivationFrame(uword pc, const Bytecode& bytecode);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
   explicit ActivationFrame(Kind kind);
 
   explicit ActivationFrame(const Closure& async_activation);
@@ -286,7 +304,11 @@
     ASSERT(!code_.IsNull());
     return code_;
   }
-  bool is_interpreted() const { return is_interpreted_; }
+  const Bytecode& bytecode() const {
+    ASSERT(!bytecode_.IsNull());
+    return bytecode_;
+  }
+  bool IsInterpreted() const { return !bytecode_.IsNull(); }
 
   RawString* QualifiedFunctionName();
   RawString* SourceUrl();
@@ -399,6 +421,7 @@
   // The anchor of the context chain for this function.
   Context& ctx_;
   Code& code_;
+  Bytecode& bytecode_;
   Function& function_;
   bool live_frame_;  // Is this frame a live frame?
   bool token_pos_initialized_;
@@ -416,7 +439,6 @@
 
   Kind kind_;
 
-  bool is_interpreted_;  // Running under kernel bytecode interpreter.
   bool vars_initialized_;
   LocalVarDescriptors& var_descriptors_;
   ZoneGrowableArray<intptr_t> desc_indices_;
@@ -442,6 +464,7 @@
   void AddActivation(ActivationFrame* frame);
   void AddMarker(ActivationFrame::Kind marker);
   void AddAsyncCausalFrame(uword pc, const Code& code);
+  void AddAsyncCausalFrame(uword pc, const Bytecode& bytecode);
 
   ZoneGrowableArray<ActivationFrame*> trace_;
 
@@ -476,7 +499,12 @@
 
   void OnIsolateRunnable();
 
-  void NotifyCompilation(const Function& func);
+  void NotifyCompilation(const Function& func) {
+    HandleCodeChange(/* bytecode_loaded = */ false, func);
+  }
+  void NotifyBytecodeLoaded(const Function& func) {
+    HandleCodeChange(/* bytecode_loaded = */ true, func);
+  }
   void NotifyDoneLoading();
 
   RawFunction* ResolveFunction(const Library& library,
@@ -524,6 +552,10 @@
     ignore_breakpoints_ = ignore_breakpoints;
   }
 
+  bool HasEnabledBytecodeBreakpoints() const;
+  // Called from the interpreter. Note that pc already points to next bytecode.
+  bool HasBytecodeBreakpointAt(const KBCInstr* next_pc) const;
+
   // Put the isolate into single stepping mode when Dart code next runs.
   //
   // This is used by the vm service to allow the user to step while
@@ -547,6 +579,7 @@
   // debugger's zone.
   bool HasBreakpoint(const Function& func, Zone* zone);
   bool HasBreakpoint(const Code& code);
+  // A Bytecode version of HasBreakpoint is not needed.
 
   // Returns true if the call at address pc is patched to point to
   // a debugger stub.
@@ -598,6 +631,7 @@
   void PrintSettingsToJSONObject(JSONObject* jsobj) const;
 
   static bool IsDebuggable(const Function& func);
+  static bool IsDebugging(Thread* thread, const Function& func);
 
   intptr_t limitBreakpointId() { return next_id_; }
 
@@ -626,18 +660,31 @@
   void FindCompiledFunctions(const Script& script,
                              TokenPosition start_pos,
                              TokenPosition end_pos,
-                             GrowableObjectArray* function_list);
+                             GrowableObjectArray* bytecode_function_list,
+                             GrowableObjectArray* code_function_list);
   bool FindBestFit(const Script& script,
                    TokenPosition token_pos,
                    TokenPosition last_token_pos,
                    Function* best_fit);
   RawFunction* FindInnermostClosure(const Function& function,
                                     TokenPosition token_pos);
-  TokenPosition ResolveBreakpointPos(const Function& func,
+  TokenPosition ResolveBreakpointPos(bool in_bytecode,
+                                     const Function& func,
                                      TokenPosition requested_token_pos,
                                      TokenPosition last_token_pos,
-                                     intptr_t requested_column);
+                                     intptr_t requested_column,
+                                     TokenPosition exact_token_pos);
   void DeoptimizeWorld();
+  void NotifySingleStepping(bool value) const;
+  BreakpointLocation* SetCodeBreakpoints(bool in_bytecode,
+                                         BreakpointLocation* loc,
+                                         const Script& script,
+                                         TokenPosition token_pos,
+                                         TokenPosition last_token_pos,
+                                         intptr_t requested_line,
+                                         intptr_t requested_column,
+                                         TokenPosition exact_token_pos,
+                                         const GrowableObjectArray& functions);
   BreakpointLocation* SetBreakpoint(const Script& script,
                                     TokenPosition token_pos,
                                     TokenPosition last_token_pos,
@@ -653,9 +700,13 @@
                                           intptr_t column);
   void RegisterBreakpointLocation(BreakpointLocation* bpt);
   void RegisterCodeBreakpoint(CodeBreakpoint* bpt);
-  BreakpointLocation* GetBreakpointLocation(const Script& script,
-                                            TokenPosition token_pos,
-                                            intptr_t requested_column);
+  BreakpointLocation* GetBreakpointLocation(
+      const Script& script,
+      TokenPosition token_pos,
+      intptr_t requested_line,
+      intptr_t requested_column,
+      TokenPosition bytecode_token_pos = TokenPosition::kNoSource,
+      TokenPosition code_token_pos = TokenPosition::kNoSource);
   void MakeCodeBreakpointAt(const Function& func, BreakpointLocation* bpt);
   // Returns NULL if no breakpoint exists for the given address.
   CodeBreakpoint* GetCodeBreakpoint(uword breakpoint_address);
@@ -664,6 +715,8 @@
   void PrintBreakpointsListToJSONArray(BreakpointLocation* sbpt,
                                        JSONArray* jsarr) const;
 
+  void HandleCodeChange(bool bytecode_loaded, const Function& func);
+
   ActivationFrame* TopDartFrame() const;
   static ActivationFrame* CollectDartFrame(
       Isolate* isolate,
@@ -674,9 +727,18 @@
       intptr_t deopt_frame_offset,
       ActivationFrame::Kind kind = ActivationFrame::kRegular);
 #if !defined(DART_PRECOMPILED_RUNTIME)
+  static ActivationFrame* CollectDartFrame(
+      Isolate* isolate,
+      uword pc,
+      StackFrame* frame,
+      const Bytecode& bytecode,
+      ActivationFrame::Kind kind = ActivationFrame::kRegular);
   static RawArray* DeoptimizeToArray(Thread* thread,
                                      StackFrame* frame,
                                      const Code& code);
+  TokenPosition FindExactTokenPosition(const Script& script,
+                                       TokenPosition start_of_line,
+                                       intptr_t column_number);
 #endif
   // Appends at least one stack frame. Multiple frames will be appended
   // if |code| at the frame's pc contains inlined functions.
diff --git a/runtime/vm/debugger_kbc.cc b/runtime/vm/debugger_kbc.cc
new file mode 100644
index 0000000..c07d8e9
--- /dev/null
+++ b/runtime/vm/debugger_kbc.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/debugger.h"
+#include "vm/instructions_kbc.h"
+#include "vm/interpreter.h"
+
+namespace dart {
+
+#ifndef PRODUCT
+void CodeBreakpoint::SetBytecodeBreakpoint() {
+  ASSERT(!is_enabled_);
+  is_enabled_ = true;
+  Interpreter::Current()->set_is_debugging(true);
+}
+
+void CodeBreakpoint::UnsetBytecodeBreakpoint() {
+  ASSERT(is_enabled_);
+  is_enabled_ = false;
+  if (!Isolate::Current()->single_step() &&
+      !Isolate::Current()->debugger()->HasEnabledBytecodeBreakpoints()) {
+    Interpreter::Current()->set_is_debugging(false);
+  }
+}
+
+bool Debugger::HasEnabledBytecodeBreakpoints() const {
+  CodeBreakpoint* cbpt = code_breakpoints_;
+  while (cbpt != nullptr) {
+    if (cbpt->IsEnabled() && cbpt->IsInterpreted()) {
+      return true;
+    }
+    cbpt = cbpt->next();
+  }
+  return false;
+}
+
+bool Debugger::HasBytecodeBreakpointAt(const KBCInstr* next_pc) const {
+  CodeBreakpoint* cbpt = code_breakpoints_;
+  while (cbpt != nullptr) {
+    if ((reinterpret_cast<uword>(next_pc)) == cbpt->pc_ && cbpt->IsEnabled()) {
+      ASSERT(cbpt->IsInterpreted());
+      return true;
+    }
+    cbpt = cbpt->next();
+  }
+  return false;
+}
+#endif  // !PRODUCT
+
+}  // namespace dart
+
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 0a48371..1a71bf6 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -919,7 +919,7 @@
   if (!error.IsNull()) {
     Exceptions::PropagateError(error);
   }
-  *code ^= function.unoptimized_code();
+  *code = function.unoptimized_code();
   ASSERT(!code->IsNull());
   uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(),
                                     RawPcDescriptors::kDeopt);
diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc
index ae71c84..29e5488 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -5,6 +5,7 @@
 #include "vm/dwarf.h"
 
 #include "vm/code_descriptors.h"
+#include "vm/elf.h"
 #include "vm/object_store.h"
 
 namespace dart {
@@ -51,26 +52,37 @@
   InliningNode* children_next;
 };
 
-Dwarf::Dwarf(Zone* zone, StreamingWriteStream* stream)
+Dwarf::Dwarf(Zone* zone, StreamingWriteStream* stream, Elf* elf)
     : zone_(zone),
-      stream_(stream),
+      elf_(elf),
+      asm_stream_(stream),
+      bin_stream_(nullptr),
       codes_(zone, 1024),
       code_to_index_(zone),
       functions_(zone, 1024),
       function_to_index_(zone),
       scripts_(zone, 1024),
       script_to_index_(zone),
-      temp_(0) {}
+      abstract_origins_(nullptr),
+      temp_(0) {
+  // Either assembler or direct to ELF.
+  RELEASE_ASSERT((stream == nullptr) != (elf == nullptr));
+}
 
 intptr_t Dwarf::AddCode(const Code& code) {
+  intptr_t index = codes_.length();
+  AddCode(code, index);
+  return index;
+}
+
+void Dwarf::AddCode(const Code& code, intptr_t offset) {
   RELEASE_ASSERT(!code.IsNull());
   CodeIndexPair* pair = code_to_index_.Lookup(&code);
   if (pair != NULL) {
-    return pair->index_;
+    return;  // UNREACHABLE?
   }
-  intptr_t index = codes_.length();
   const Code& zone_code = Code::ZoneHandle(zone_, code.raw());
-  code_to_index_.Insert(CodeIndexPair(&zone_code, index));
+  code_to_index_.Insert(CodeIndexPair(&zone_code, offset));
   codes_.Add(&zone_code);
   if (code.IsFunctionCode()) {
     const Function& function = Function::Handle(zone_, code.function());
@@ -85,7 +97,6 @@
       AddFunction(function);
     }
   }
-  return index;
 }
 
 intptr_t Dwarf::AddFunction(const Function& function) {
@@ -140,23 +151,36 @@
 void Dwarf::Print(const char* format, ...) {
   va_list args;
   va_start(args, format);
-  stream_->VPrint(format, args);
+  asm_stream_->VPrint(format, args);
   va_end(args);
 }
 
-void Dwarf::WriteAbbreviations() {
-// Dwarf data mostly takes the form of a tree, whose nodes are called
-// DIEs. Each DIE begins with an abbreviation code, and the abbreviation
-// describes the attributes of that DIE and their representation.
+static uint8_t* ZoneReallocate(uint8_t* ptr,
+                               intptr_t old_size,
+                               intptr_t new_size) {
+  return Thread::Current()->zone()->Realloc<uint8_t>(ptr, old_size, new_size);
+}
 
+void Dwarf::WriteAbbreviations() {
+  // Dwarf data mostly takes the form of a tree, whose nodes are called
+  // DIEs. Each DIE begins with an abbreviation code, and the abbreviation
+  // describes the attributes of that DIE and their representation.
+
+  uint8_t* buffer = nullptr;
+  WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
+
+  if (asm_stream_) {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
-  Print(".section __DWARF,__debug_abbrev,regular,debug\n");
+    Print(".section __DWARF,__debug_abbrev,regular,debug\n");
 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) ||                \
     defined(TARGET_OS_FUCHSIA)
-  Print(".section .debug_abbrev,\"\"\n");
+    Print(".section .debug_abbrev,\"\"\n");
 #else
-  UNIMPLEMENTED();
+    UNIMPLEMENTED();
 #endif
+  } else {
+    bin_stream_ = &stream;
+  }
 
   uleb128(kCompilationUnit);     // Abbrev code.
   uleb128(DW_TAG_compile_unit);  // Type.
@@ -219,25 +243,44 @@
   uleb128(0);  // End of attributes.
 
   uleb128(0);  // End of abbreviations.
+
+  if (elf_) {
+    elf_->AddDebug(".debug_abbrev", buffer, stream.bytes_written());
+    bin_stream_ = nullptr;
+  }
 }
 
 void Dwarf::WriteCompilationUnit() {
-// 7.5.1.1 Compilation Unit Header
+  uint8_t* buffer = nullptr;
+  WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
 
+  if (asm_stream_) {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
-  Print(".section __DWARF,__debug_info,regular,debug\n");
+    Print(".section __DWARF,__debug_info,regular,debug\n");
 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) ||                \
     defined(TARGET_OS_FUCHSIA)
-  Print(".section .debug_info,\"\"\n");
+    Print(".section .debug_info,\"\"\n");
 #else
-  UNIMPLEMENTED();
+    UNIMPLEMENTED();
 #endif
-  Print(".Ldebug_info:\n");
+    Print(".Ldebug_info:\n");
+  } else {
+    bin_stream_ = &stream;
+  }
+
+  // 7.5.1.1 Compilation Unit Header
 
   // Unit length. Assignment to temp works around buggy Mac assembler.
-  Print("Lcu_size = .Lcu_end - .Lcu_start\n");
-  Print(".4byte Lcu_size\n");
-  Print(".Lcu_start:\n");
+  intptr_t cu_size_fixup = 0;
+  intptr_t cu_start = 0;
+  if (asm_stream_) {
+    Print("Lcu_size = .Lcu_end - .Lcu_start\n");
+    Print(".4byte Lcu_size\n");
+    Print(".Lcu_start:\n");
+  } else {
+    cu_size_fixup = u4(0);
+    cu_start = position();
+  }
 
   u2(2);              // DWARF version 2
   u4(0);              // debug_abbrev_offset
@@ -250,24 +293,32 @@
   const Library& root_library = Library::Handle(
       zone_, Isolate::Current()->object_store()->root_library());
   const String& root_uri = String::Handle(zone_, root_library.url());
-  Print(".string \"%s\"\n", root_uri.ToCString());  // DW_AT_name
-  Print(".string \"Dart VM\"\n");                   // DW_AT_producer
-  Print(".string \"\"\n");                          // DW_AT_comp_dir
+  string(root_uri.ToCString());  // DW_AT_name
+  string("Dart VM");             // DW_AT_producer
+  string("");                    // DW_AT_comp_dir
 
   // DW_AT_low_pc
   // The lowest instruction address in this object file that is part of our
   // compilation unit. Dwarf consumers use this to quickly decide which
   // compilation unit DIE to consult for a given pc.
-  Print(FORM_ADDR " _kDartIsolateSnapshotInstructions\n");
+  if (asm_stream_) {
+    Print(FORM_ADDR " _kDartIsolateSnapshotInstructions\n");
+  } else {
+    addr(0);
+  }
 
   // DW_AT_high_pc
   // The highest instruction address in this object file that is part of our
   // compilation unit. Dwarf consumers use this to quickly decide which
   // compilation unit DIE to consult for a given pc.
-  intptr_t last_code_index = codes_.length() - 1;
-  const Code& last_code = *(codes_[last_code_index]);
-  Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", last_code_index,
-        last_code.Size());
+  if (asm_stream_) {
+    intptr_t last_code_index = codes_.length() - 1;
+    const Code& last_code = *(codes_[last_code_index]);
+    Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", last_code_index,
+          last_code.Size());
+  } else {
+    addr(elf_->NextMemoryOffset());
+  }
 
   // DW_AT_stmt_list (offset into .debug_line)
   // Indicates which line number program is associated with this compilation
@@ -280,12 +331,23 @@
   uleb128(0);  // End of children.
 
   uleb128(0);  // End of entries.
-  Print(".Lcu_end:\n");
+
+  if (asm_stream_) {
+    Print(".Lcu_end:\n");
+  } else {
+    fixup_u4(cu_size_fixup, position() - cu_start);
+
+    elf_->AddDebug(".debug_info", buffer, stream.bytes_written());
+    bin_stream_ = nullptr;
+  }
 }
 
 void Dwarf::WriteAbstractFunctions() {
   Script& script = Script::Handle(zone_);
   String& name = String::Handle(zone_);
+  if (!asm_stream_) {
+    abstract_origins_ = zone_->Alloc<uint32_t>(functions_.length());
+  }
   for (intptr_t i = 0; i < functions_.length(); i++) {
     const Function& function = *(functions_[i]);
     name = function.QualifiedUserVisibleName();
@@ -293,13 +355,18 @@
     intptr_t file = LookupScript(script);
     intptr_t line = 0;  // Not known. Script has already lost its token stream.
 
-    Print(".Lfunc%" Pd ":\n", i);  // Label for DW_AT_abstract_origin references
+    if (asm_stream_) {
+      Print(".Lfunc%" Pd ":\n",
+            i);  // Label for DW_AT_abstract_origin references
+    } else {
+      abstract_origins_[i] = position();
+    }
     uleb128(kAbstractFunction);
-    Print(".string \"%s\"\n", name.ToCString());  // DW_AT_name
-    uleb128(file);                                // DW_AT_decl_file
-    uleb128(line);                                // DW_AT_decl_line
-    uleb128(DW_INL_inlined);                      // DW_AT_inline
-    uleb128(0);                                   // End of children.
+    string(name.ToCString());  // DW_AT_name
+    uleb128(file);             // DW_AT_decl_file
+    uleb128(line);             // DW_AT_decl_line
+    uleb128(DW_INL_inlined);   // DW_AT_inline
+    uleb128(0);                // End of children.
   }
 }
 
@@ -312,6 +379,11 @@
     if (!code.IsFunctionCode()) {
       continue;
     }
+
+    CodeIndexPair* pair = code_to_index_.Lookup(&code);
+    RELEASE_ASSERT(pair != NULL);
+    intptr_t code_offset = pair->index_;
+
     function = code.function();
     intptr_t function_index = LookupFunction(function);
     script = function.script();
@@ -320,15 +392,27 @@
     // DW_AT_abstract_origin
     // References a node written above in WriteAbstractFunctions.
     // Assignment to temp works around buggy Mac assembler.
-    intptr_t temp = temp_++;
-    Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp,
-          function_index);
-    Print(".4byte Ltemp%" Pd "\n", temp);
+    if (asm_stream_) {
+      intptr_t temp = temp_++;
+      Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp,
+            function_index);
+      Print(".4byte Ltemp%" Pd "\n", temp);
+    } else {
+      u4(abstract_origins_[function_index]);
+    }
 
     // DW_AT_low_pc
-    Print(FORM_ADDR " .Lcode%" Pd "\n", i);
+    if (asm_stream_) {
+      Print(FORM_ADDR " .Lcode%" Pd "\n", i);
+    } else {
+      addr(code_offset);
+    }
     // DW_AT_high_pc
-    Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", i, code.Size());
+    if (asm_stream_) {
+      Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", i, code.Size());
+    } else {
+      addr(code_offset + code.Size());
+    }
 
     InliningNode* node = ExpandInliningTree(code);
     if (node != NULL) {
@@ -435,15 +519,28 @@
   // DW_AT_abstract_origin
   // References a node written above in WriteAbstractFunctions.
   // Assignment to temp works around buggy Mac assembler.
-  intptr_t temp = temp_++;
-  Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp, function_index);
-  Print(".4byte Ltemp%" Pd "\n", temp);
+  if (asm_stream_) {
+    intptr_t temp = temp_++;
+    Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp,
+          function_index);
+    Print(".4byte Ltemp%" Pd "\n", temp);
+  } else {
+    u4(abstract_origins_[function_index]);
+  }
   // DW_AT_low_pc
-  Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
-        node->start_pc_offset);
+  if (asm_stream_) {
+    Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
+          node->start_pc_offset);
+  } else {
+    addr(root_code_index + node->start_pc_offset);
+  }
   // DW_AT_high_pc
-  Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
-        node->end_pc_offset);
+  if (asm_stream_) {
+    Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
+          node->end_pc_offset);
+  } else {
+    addr(root_code_index + node->end_pc_offset);
+  }
   // DW_AT_call_file
   uleb128(file);
   // DW_AT_call_line
@@ -458,30 +555,50 @@
 }
 
 void Dwarf::WriteLines() {
+  uint8_t* buffer = nullptr;
+  WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
+
+  if (asm_stream_) {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
-  Print(".section __DWARF,__debug_line,regular,debug\n");
+    Print(".section __DWARF,__debug_line,regular,debug\n");
 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) ||                \
     defined(TARGET_OS_FUCHSIA)
-  Print(".section .debug_line,\"\"\n");
+    Print(".section .debug_line,\"\"\n");
 #else
-  UNIMPLEMENTED();
+    UNIMPLEMENTED();
 #endif
+  } else {
+    bin_stream_ = &stream;
+  }
 
   // 6.2.4 The Line Number Program Header
 
   // 1. unit_length. This encoding implies 32-bit DWARF.
-  Print("Lline_size = .Lline_end - .Lline_start\n");
-  Print(".4byte Lline_size\n");
-
-  Print(".Lline_start:\n");
+  intptr_t line_size_fixup = 0;
+  intptr_t line_start = 0;
+  if (asm_stream_) {
+    Print("Lline_size = .Lline_end - .Lline_start\n");
+    Print(".4byte Lline_size\n");
+    Print(".Lline_start:\n");
+  } else {
+    line_size_fixup = u4(0);
+    line_start = position();
+  }
 
   u2(2);  // 2. DWARF version 2
 
   // 3. header_length
   // Assignment to temp works around buggy Mac assembler.
-  Print("Llineheader_size = .Llineheader_end - .Llineheader_start\n");
-  Print(".4byte Llineheader_size\n");
-  Print(".Llineheader_start:\n");
+  intptr_t lineheader_size_fixup = 0;
+  intptr_t lineheader_start = 0;
+  if (asm_stream_) {
+    Print("Llineheader_size = .Llineheader_end - .Llineheader_start\n");
+    Print(".4byte Llineheader_size\n");
+    Print(".Llineheader_start:\n");
+  } else {
+    lineheader_size_fixup = u4(0);
+    lineheader_start = position();
+  }
 
   u1(1);   // 4. minimum_instruction_length
   u1(1);   // 5. default_is_stmt (true for compatibility with dsymutil).
@@ -511,21 +628,25 @@
   String& uri = String::Handle(zone_);
   for (intptr_t i = 0; i < scripts_.length(); i++) {
     const Script& script = *(scripts_[i]);
-    uri ^= script.url();
-    Print(".string \"%s\"\n", uri.ToCString());
+    uri = script.url();
+    string(uri.ToCString());  // NOLINT
     uleb128(0);  // Include directory index.
     uleb128(0);  // File modification time.
     uleb128(0);  // File length.
   }
   u1(0);  // End of file names.
 
-  Print(".Llineheader_end:\n");
+  if (asm_stream_) {
+    Print(".Llineheader_end:\n");
+  } else {
+    fixup_u4(lineheader_size_fixup, position() - lineheader_start);
+  }
 
   // 6.2.5 The Line Number Program
 
   intptr_t previous_file = 1;
   intptr_t previous_line = 1;
-  intptr_t previous_code_index = -1;
+  intptr_t previous_code_offset = -1;
   intptr_t previous_pc_offset = 0;
 
   Function& root_function = Function::Handle(zone_);
@@ -537,6 +658,11 @@
 
   for (intptr_t i = 0; i < codes_.length(); i++) {
     const Code& code = *(codes_[i]);
+
+    CodeIndexPair* pair = code_to_index_.Lookup(&code);
+    RELEASE_ASSERT(pair != NULL);
+    intptr_t current_code_offset = pair->index_;
+
     map = code.code_source_map();
     if (map.IsNull()) {
       continue;
@@ -591,18 +717,30 @@
           u1(DW_LNS_copy);
 
           // 4. Update LNP pc.
-          if (previous_code_index == -1) {
+          if (previous_code_offset == -1) {
             // This variant is relocatable.
             u1(0);                  // This is an extended opcode
             u1(1 + sizeof(void*));  // that is 5 or 9 bytes long
             u1(DW_LNE_set_address);
-            Print(FORM_ADDR " .Lcode%" Pd " + %d\n", i, current_pc_offset);
+            if (asm_stream_) {
+              Print(FORM_ADDR " .Lcode%" Pd " + %d\n", i, current_pc_offset);
+            } else {
+              addr(current_code_offset + current_pc_offset);
+            }
           } else {
             u1(DW_LNS_advance_pc);
-            Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", i,
-                  previous_code_index, current_pc_offset - previous_pc_offset);
+            if (asm_stream_) {
+              Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", i,
+                    previous_code_offset,
+                    current_pc_offset - previous_pc_offset);
+            } else {
+              intptr_t delta = current_code_offset - previous_code_offset +
+                               current_pc_offset - previous_pc_offset;
+              RELEASE_ASSERT(delta > 0);
+              uleb128(delta);
+            }
           }
-          previous_code_index = i;
+          previous_code_offset = current_code_offset;
           previous_pc_offset = current_pc_offset;
           break;
         }
@@ -635,16 +773,35 @@
   // Advance pc to end of the compilation unit.
   intptr_t last_code_index = codes_.length() - 1;
   const Code& last_code = *(codes_[last_code_index]);
+
+  CodeIndexPair* pair = code_to_index_.Lookup(&last_code);
+  RELEASE_ASSERT(pair != NULL);
+  intptr_t last_code_offset = pair->index_;
+
   u1(DW_LNS_advance_pc);
-  Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", last_code_index,
-        previous_code_index, last_code.Size() - previous_pc_offset);
+  if (asm_stream_) {
+    Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", last_code_index,
+          previous_code_offset, last_code.Size() - previous_pc_offset);
+  } else {
+    intptr_t delta = last_code_offset - previous_code_offset +
+                     last_code.Size() - previous_pc_offset;
+    RELEASE_ASSERT(delta >= 0);
+    uleb128(delta);
+  }
 
   // End of contiguous machine code.
   u1(0);  // This is an extended opcode
   u1(1);  // that is 1 byte long
   u1(DW_LNE_end_sequence);
 
-  Print(".Lline_end:\n");
+  if (asm_stream_) {
+    Print(".Lline_end:\n");
+  } else {
+    fixup_u4(line_size_fixup, position() - line_start);
+
+    elf_->AddDebug(".debug_line", buffer, stream.bytes_written());
+    bin_stream_ = nullptr;
+  }
 }
 
 #endif  // DART_PRECOMPILER
diff --git a/runtime/vm/dwarf.h b/runtime/vm/dwarf.h
index cd68542..7d4f5b7 100644
--- a/runtime/vm/dwarf.h
+++ b/runtime/vm/dwarf.h
@@ -14,6 +14,7 @@
 
 #ifdef DART_PRECOMPILER
 
+class Elf;
 class InliningNode;
 
 struct ScriptIndexPair {
@@ -117,8 +118,9 @@
 
 class Dwarf : public ZoneAllocated {
  public:
-  Dwarf(Zone* zone, StreamingWriteStream* stream);
+  Dwarf(Zone* zone, StreamingWriteStream* stream, Elf* elf);
 
+  void AddCode(const Code& code, intptr_t offset);
   intptr_t AddCode(const Code& code);
   intptr_t AddFunction(const Function& function);
   intptr_t AddScript(const Script& script);
@@ -181,11 +183,100 @@
   };
 
   void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
-  void sleb128(intptr_t value) { Print(".sleb128 %" Pd "\n", value); }
-  void uleb128(uintptr_t value) { Print(".uleb128 %" Pd "\n", value); }
-  void u1(uint8_t value) { Print(".byte %d\n", value); }
-  void u2(uint16_t value) { Print(".2byte %d\n", value); }
-  void u4(uint32_t value) { Print(".4byte %d\n", value); }
+  void sleb128(intptr_t value) {
+    if (asm_stream_) {
+      Print(".sleb128 %" Pd "\n", value);
+    } else {
+      bool is_last_part = false;
+      while (!is_last_part) {
+        uint8_t part = value & 0x7F;
+        value >>= 7;
+        if ((value == 0 && (part & 0x40) == 0) ||
+            (value == static_cast<intptr_t>(-1) && (part & 0x40) != 0)) {
+          is_last_part = true;
+        } else {
+          part |= 0x80;
+        }
+        bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&part),
+                                sizeof(part));
+      }
+    }
+  }
+  void uleb128(uintptr_t value) {
+    if (asm_stream_) {
+      Print(".uleb128 %" Pd "\n", value);
+    } else {
+      bool is_last_part = false;
+      while (!is_last_part) {
+        uint8_t part = value & 0x7F;
+        value >>= 7;
+        if (value == 0) {
+          is_last_part = true;
+        } else {
+          part |= 0x80;
+        }
+        bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&part),
+                                sizeof(part));
+      }
+    }
+  }
+  void u1(uint8_t value) {
+    if (asm_stream_) {
+      Print(".byte %d\n", value);
+    } else {
+      bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+                              sizeof(value));
+    }
+  }
+  void u2(uint16_t value) {
+    if (asm_stream_) {
+      Print(".2byte %d\n", value);
+    } else {
+      bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+                              sizeof(value));
+    }
+  }
+  intptr_t u4(uint32_t value) {
+    if (asm_stream_) {
+      Print(".4byte %d\n", value);
+      return -1;
+    } else {
+      intptr_t fixup = position();
+      bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+                              sizeof(value));
+      return fixup;
+    }
+  }
+  void fixup_u4(intptr_t position, uint32_t value) {
+    if (asm_stream_) {
+      UNREACHABLE();
+    } else {
+      memmove(bin_stream_->buffer() + position, &value, sizeof(value));
+    }
+  }
+  void addr(uword value) {
+    if (asm_stream_) {
+      UNREACHABLE();
+    } else {
+      bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+                              sizeof(value));
+    }
+  }
+  void string(const char* cstr) {  // NOLINT
+    if (asm_stream_) {
+      Print(".string \"%s\"\n", cstr);  // NOLINT
+    } else {
+      bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(cstr),
+                              strlen(cstr) + 1);
+    }
+  }
+  intptr_t position() {
+    if (asm_stream_) {
+      UNREACHABLE();
+    } else {
+      return bin_stream_->Position();
+    }
+  }
 
   void WriteAbbreviations();
   void WriteCompilationUnit();
@@ -198,13 +289,16 @@
   void WriteLines();
 
   Zone* const zone_;
-  StreamingWriteStream* stream_;
+  Elf* const elf_;
+  StreamingWriteStream* asm_stream_;
+  WriteStream* bin_stream_;
   ZoneGrowableArray<const Code*> codes_;
   CodeIndexMap code_to_index_;
   ZoneGrowableArray<const Function*> functions_;
   FunctionIndexMap function_to_index_;
   ZoneGrowableArray<const Script*> scripts_;
   ScriptIndexMap script_to_index_;
+  uint32_t* abstract_origins_;
   intptr_t temp_;
 };
 
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
new file mode 100644
index 0000000..6830f3b
--- /dev/null
+++ b/runtime/vm/elf.cc
@@ -0,0 +1,755 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/elf.h"
+
+#include "platform/text_buffer.h"
+#include "vm/cpu.h"
+#include "vm/thread.h"
+
+namespace dart {
+
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+
+static const intptr_t ELFDATA2LSB = 1;
+
+static const intptr_t ELFOSABI_SYSV = 0;
+
+#define EF_ARM_ABI_FLOAT_HARD 0x00000400
+#define EF_ARM_ABI_FLOAT_SOFT 0x00000200
+#define EF_ARM_ABI 0x05000000
+
+static const intptr_t ET_DYN = 3;
+
+#define EM_386 3
+#define EM_ARM 40
+#define EM_X86_64 62
+#define EM_AARCH64 183
+
+static const intptr_t EV_CURRENT = 1;
+
+static const intptr_t SHT_PROGBITS = 1;
+static const intptr_t SHT_STRTAB = 3;
+static const intptr_t SHT_HASH = 5;
+static const intptr_t SHT_DYNSYM = 11;
+static const intptr_t SHT_DYNAMIC = 6;
+
+static const intptr_t SHF_WRITE = 0x1;
+static const intptr_t SHF_ALLOC = 0x2;
+static const intptr_t SHF_EXECINSTR = 0x4;
+
+static const intptr_t SHN_UNDEF = 0;
+
+static const intptr_t STN_UNDEF = 0;
+
+static const intptr_t PT_LOAD = 1;
+static const intptr_t PT_DYNAMIC = 2;
+static const intptr_t PT_PHDR = 6;
+
+static const intptr_t PF_X = 1;
+static const intptr_t PF_W = 2;
+static const intptr_t PF_R = 4;
+
+static const intptr_t STB_GLOBAL = 1;
+
+static const intptr_t STT_OBJECT = 1;  // I.e., data.
+static const intptr_t STT_FUNC = 2;
+
+static const intptr_t DT_HASH = 4;
+static const intptr_t DT_STRTAB = 5;
+static const intptr_t DT_SYMTAB = 6;
+static const intptr_t DT_STRSZ = 10;
+static const intptr_t DT_SYMENT = 11;
+
+#if defined(TARGET_ARCH_IS_32_BIT)
+static const intptr_t kElfHeaderSize = 52;
+static const intptr_t kElfSectionTableEntrySize = 40;
+static const intptr_t kElfProgramTableEntrySize = 32;
+static const intptr_t kElfSymbolTableEntrySize = 16;
+static const intptr_t kElfDynamicTableEntrySize = 8;
+#else
+static const intptr_t kElfHeaderSize = 64;
+static const intptr_t kElfSectionTableEntrySize = 64;
+static const intptr_t kElfProgramTableEntrySize = 56;
+static const intptr_t kElfSymbolTableEntrySize = 24;
+static const intptr_t kElfDynamicTableEntrySize = 16;
+#endif
+
+static const intptr_t kPageSize = 4096;
+
+class Section : public ZoneAllocated {
+ public:
+  Section() {}
+
+  virtual ~Section() {}
+  virtual void Write(Elf* stream) = 0;
+
+  // Linker view.
+  intptr_t section_name = 0;  // Index into string table.
+  intptr_t section_type = 0;
+  intptr_t section_flags = 0;
+  intptr_t section_index = -1;
+  intptr_t section_link = SHN_UNDEF;
+  intptr_t section_info = 0;
+  intptr_t section_entry_size = 0;
+  intptr_t file_size = 0;
+  intptr_t file_offset = -1;
+
+  intptr_t alignment = 1;
+
+  // Loader view.
+  intptr_t segment_type = -1;
+  intptr_t segment_flags = 0;
+  intptr_t memory_size = 0;
+  intptr_t memory_offset = -1;
+};
+
+class ProgramBits : public Section {
+ public:
+  ProgramBits(bool allocate,
+              bool executable,
+              const uint8_t* bytes,
+              intptr_t size) {
+    section_type = SHT_PROGBITS;
+    if (allocate) {
+      section_flags = SHF_ALLOC;
+      if (executable) section_flags |= SHF_EXECINSTR;
+
+      segment_type = PT_LOAD;
+      segment_flags = PF_R;
+      if (executable) segment_flags |= PF_X;
+    }
+
+    bytes_ = bytes;
+    file_size = memory_size = size;
+  }
+
+  void Write(Elf* stream) { stream->WriteBytes(bytes_, memory_size); }
+
+  const uint8_t* bytes_;
+};
+
+class StringTable : public Section {
+ public:
+  StringTable() : text_(128) {
+    section_type = SHT_STRTAB;
+    section_flags = SHF_ALLOC;
+    segment_type = PT_LOAD;
+    segment_flags = PF_R;
+
+    text_.AddChar('\0');
+    memory_size = file_size = text_.length();
+  }
+
+  intptr_t AddString(const char* str) {
+    intptr_t offset = text_.length();
+    text_.AddString(str);
+    text_.AddChar('\0');
+    memory_size = file_size = text_.length();
+    return offset;
+  }
+
+  void Write(Elf* stream) {
+    stream->WriteBytes(reinterpret_cast<const uint8_t*>(text_.buf()),
+                       text_.length());
+  }
+
+  TextBuffer text_;
+};
+
+class Symbol : public ZoneAllocated {
+ public:
+  const char* cstr;
+  intptr_t name;
+  intptr_t info;
+  intptr_t section;
+  intptr_t offset;
+  intptr_t size;
+};
+
+class SymbolTable : public Section {
+ public:
+  SymbolTable() {
+    section_type = SHT_DYNSYM;
+    section_flags = SHF_ALLOC;
+    segment_type = PT_LOAD;
+    segment_flags = PF_R;
+
+    section_entry_size = kElfSymbolTableEntrySize;
+    AddSymbol(NULL);
+    section_info = 1;  // One "local" symbol, the reserved first entry.
+  }
+
+  void AddSymbol(Symbol* symbol) {
+    symbols_.Add(symbol);
+    memory_size += kElfSymbolTableEntrySize;
+    file_size += kElfSymbolTableEntrySize;
+  }
+
+  void Write(Elf* stream) {
+    // The first symbol table entry is reserved and must be all zeros.
+    {
+      const intptr_t start = stream->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+      stream->WriteWord(0);
+      stream->WriteAddr(0);
+      stream->WriteWord(0);
+      stream->WriteByte(0);
+      stream->WriteByte(0);
+      stream->WriteHalf(0);
+#else
+      stream->WriteWord(0);
+      stream->WriteByte(0);
+      stream->WriteByte(0);
+      stream->WriteHalf(0);
+      stream->WriteAddr(0);
+      stream->WriteXWord(0);
+#endif
+      const intptr_t end = stream->position();
+      ASSERT((end - start) == kElfSymbolTableEntrySize);
+    }
+
+    for (intptr_t i = 1; i < symbols_.length(); i++) {
+      Symbol* symbol = symbols_[i];
+      const intptr_t start = stream->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+      stream->WriteWord(symbol->name);
+      stream->WriteAddr(symbol->offset);
+      stream->WriteWord(symbol->size);
+      stream->WriteByte(symbol->info);
+      stream->WriteByte(0);
+      stream->WriteHalf(symbol->section);
+#else
+      stream->WriteWord(symbol->name);
+      stream->WriteByte(symbol->info);
+      stream->WriteByte(0);
+      stream->WriteHalf(symbol->section);
+      stream->WriteAddr(symbol->offset);
+      stream->WriteXWord(symbol->size);
+#endif
+      const intptr_t end = stream->position();
+      ASSERT((end - start) == kElfSymbolTableEntrySize);
+    }
+  }
+
+  intptr_t length() const { return symbols_.length(); }
+  Symbol* at(intptr_t i) const { return symbols_[i]; }
+
+  GrowableArray<Symbol*> symbols_;
+};
+
+static uint32_t ElfHash(const unsigned char* name) {
+  uint32_t h = 0;
+  while (*name) {
+    h = (h << 4) + *name++;
+    uint32_t g = h & 0xf0000000;
+    h ^= g;
+    h ^= g >> 24;
+  }
+  return h;
+}
+
+class SymbolHashTable : public Section {
+ public:
+  SymbolHashTable(StringTable* strtab, SymbolTable* symtab) {
+    section_type = SHT_HASH;
+    section_flags = SHF_ALLOC;
+    section_link = symtab->section_index;
+    segment_type = PT_LOAD;
+    segment_flags = PF_R;
+
+    nchain_ = symtab->length();
+    nbucket_ = symtab->length();
+
+    bucket_ = Thread::Current()->zone()->Alloc<int32_t>(nbucket_);
+    for (intptr_t i = 0; i < nbucket_; i++) {
+      bucket_[i] = STN_UNDEF;
+    }
+
+    chain_ = Thread::Current()->zone()->Alloc<int32_t>(nchain_);
+    for (intptr_t i = 0; i < nchain_; i++) {
+      chain_[i] = STN_UNDEF;
+    }
+
+    for (intptr_t i = 1; i < symtab->length(); i++) {
+      Symbol* symbol = symtab->at(i);
+      uint32_t hash = ElfHash((const unsigned char*)symbol->cstr);
+      uint32_t probe = hash % nbucket_;
+      chain_[i] = bucket_[probe];  // next = head
+      bucket_[probe] = i;          // head = symbol
+    }
+
+    memory_size = file_size = 4 * (nbucket_ + nchain_ + 2);
+  }
+
+  void Write(Elf* stream) {
+    stream->WriteWord(nbucket_);
+    stream->WriteWord(nchain_);
+    for (intptr_t i = 0; i < nbucket_; i++) {
+      stream->WriteWord(bucket_[i]);
+    }
+    for (intptr_t i = 0; i < nchain_; i++) {
+      stream->WriteWord(chain_[i]);
+    }
+  }
+
+ private:
+  int32_t nbucket_;
+  int32_t nchain_;
+  int32_t* bucket_;  // "Head"
+  int32_t* chain_;   // "Next"
+};
+
+class DynamicTable : public Section {
+ public:
+  DynamicTable(StringTable* strtab,
+               SymbolTable* symtab,
+               SymbolHashTable* hash) {
+    section_type = SHT_DYNAMIC;
+    section_link = strtab->section_index;
+    section_flags = SHF_ALLOC | SHF_WRITE;
+    section_entry_size = kElfDynamicTableEntrySize;
+
+    segment_type = PT_LOAD;
+    segment_flags = PF_R | PF_W;
+
+    AddEntry(DT_HASH, hash->memory_offset);
+    AddEntry(DT_STRTAB, strtab->memory_offset);
+    AddEntry(DT_STRSZ, strtab->memory_size);
+    AddEntry(DT_SYMTAB, symtab->memory_offset);
+    AddEntry(DT_SYMENT, kElfSymbolTableEntrySize);
+  }
+
+  void Write(Elf* stream) {
+    for (intptr_t i = 0; i < entries_.length(); i++) {
+      const intptr_t start = stream->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+      stream->WriteWord(entries_[i]->tag);
+      stream->WriteAddr(entries_[i]->value);
+#else
+      stream->WriteXWord(entries_[i]->tag);
+      stream->WriteAddr(entries_[i]->value);
+#endif
+      const intptr_t end = stream->position();
+      ASSERT((end - start) == kElfDynamicTableEntrySize);
+    }
+  }
+
+  class Entry {
+   public:
+    intptr_t tag;
+    intptr_t value;
+  };
+
+  void AddEntry(intptr_t tag, intptr_t value) {
+    Entry* entry = new Entry();
+    entry->tag = tag;
+    entry->value = value;
+    entries_.Add(entry);
+
+    memory_size += kElfDynamicTableEntrySize;
+    file_size += kElfDynamicTableEntrySize;
+  }
+
+ private:
+  GrowableArray<Entry*> entries_;
+};
+
+static uint8_t kNothing = 0;
+
+// The first section must be written out and contains only zeros.
+static const intptr_t kNumInvalidSections = 1;
+
+// Extra segments put in the program table that aren't reified in
+// Elf::segments_.
+static const intptr_t kNumImplicitSegments = 3;
+
+Elf::Elf(Zone* zone, StreamingWriteStream* stream)
+    : zone_(zone), stream_(stream), memory_offset_(0) {
+  // Assumed by various offset logic in this file.
+  ASSERT(stream_->position() == 0);
+
+  // All our strings would fit in a single page. However, we use separate
+  // .shstrtab and .dynstr to work around a bug in Android's strip utility.
+  shstrtab_ = new (zone_) StringTable();
+  shstrtab_->section_name = shstrtab_->AddString(".shstrtab");
+  AddSection(shstrtab_);
+
+  symstrtab_ = new (zone_) StringTable();
+  symstrtab_->section_name = shstrtab_->AddString(".dynstr");
+  AddSection(symstrtab_);
+
+  symtab_ = new (zone_) SymbolTable();
+  symtab_->section_name = shstrtab_->AddString(".dynsym");
+  symtab_->section_link = symstrtab_->section_index;
+  AddSection(symtab_);
+
+  // dlsym gets confused if a symbol's value is dso offset 0, treating this as a
+  // failed lookup instead of answering dso base + 0. dladdr answers the wrong
+  // dso base if we don't start allocating from 0 (answering the address of
+  // either the first or lowest PT_LOAD). Sacrifice the first page to work
+  // around these issues. (gcc places build metadata in the first page.)
+  AddROData("nothing", &kNothing, sizeof(kNothing));
+}
+
+void Elf::AddSection(Section* section) {
+  section->section_index = sections_.length() + kNumInvalidSections;
+  sections_.Add(section);
+}
+
+void Elf::AddSegment(Section* section) {
+  if (section->alignment < kPageSize) {
+    section->alignment = kPageSize;
+  }
+
+  memory_offset_ = Utils::RoundUp(memory_offset_, section->alignment);
+  section->memory_offset = memory_offset_;
+  memory_offset_ += section->memory_size;
+  segments_.Add(section);
+  memory_offset_ = Utils::RoundUp(memory_offset_, kPageSize);
+}
+
+intptr_t Elf::NextMemoryOffset() {
+  return memory_offset_;
+}
+
+intptr_t Elf::AddText(const char* name, const uint8_t* bytes, intptr_t size) {
+  ProgramBits* image = new (zone_) ProgramBits(true, true, bytes, size);
+  image->section_name = shstrtab_->AddString(".text");
+  AddSection(image);
+  AddSegment(image);
+
+  Symbol* symbol = new (zone_) Symbol();
+  symbol->cstr = name;
+  symbol->name = symstrtab_->AddString(name);
+  symbol->info = (STB_GLOBAL << 4) | STT_FUNC;
+  symbol->section = image->section_index;
+  // For shared libraries, this is the offset from the DSO base. For static
+  // libraries, this is section relative.
+  symbol->offset = image->memory_offset;
+  symbol->size = size;
+  symtab_->AddSymbol(symbol);
+
+  return symbol->offset;
+}
+
+intptr_t Elf::AddROData(const char* name, const uint8_t* bytes, intptr_t size) {
+  ProgramBits* image = new (zone_) ProgramBits(true, false, bytes, size);
+  image->section_name = shstrtab_->AddString(".rodata");
+  AddSection(image);
+  AddSegment(image);
+
+  Symbol* symbol = new (zone_) Symbol();
+  symbol->cstr = name;
+  symbol->name = symstrtab_->AddString(name);
+  symbol->info = (STB_GLOBAL << 4) | STT_OBJECT;
+  symbol->section = image->section_index;
+  // For shared libraries, this is the offset from the DSO base. For static
+  // libraries, this is section relative.
+  symbol->offset = image->memory_offset;
+  symbol->size = size;
+  symtab_->AddSymbol(symbol);
+
+  return symbol->offset;
+}
+
+void Elf::AddDebug(const char* name, const uint8_t* bytes, intptr_t size) {
+  ProgramBits* image = new (zone_) ProgramBits(false, false, bytes, size);
+  image->section_name = shstrtab_->AddString(name);
+  AddSection(image);
+}
+
+void Elf::Finalize() {
+  SymbolHashTable* hash = new (zone_) SymbolHashTable(symstrtab_, symtab_);
+  hash->section_name = shstrtab_->AddString(".hash");
+  AddSection(hash);
+  AddSegment(hash);
+
+  // Before finalizing the string table's memory size:
+  intptr_t name_dynamic = shstrtab_->AddString(".dynamic");
+
+  // Finalizes memory size of string and symbol tables.
+  AddSegment(shstrtab_);
+  AddSegment(symstrtab_);
+  AddSegment(symtab_);
+
+  dynamic_ = new (zone_) DynamicTable(symstrtab_, symtab_, hash);
+  dynamic_->section_name = name_dynamic;
+  AddSection(dynamic_);
+  AddSegment(dynamic_);
+
+  ComputeFileOffsets();
+
+  WriteHeader();
+  WriteProgramTable();
+  WriteSectionTable();
+  WriteSections();
+}
+
+void Elf::ComputeFileOffsets() {
+  intptr_t file_offset = kElfHeaderSize;
+
+  file_offset = Utils::RoundUp(file_offset, kPageSize);
+  program_table_file_offset_ = file_offset;
+  program_table_file_size_ =
+      (segments_.length() + kNumImplicitSegments) * kElfProgramTableEntrySize;
+  file_offset += program_table_file_size_;
+
+  section_table_file_offset_ = file_offset;
+  section_table_file_size_ =
+      (sections_.length() + kNumInvalidSections) * kElfSectionTableEntrySize;
+  file_offset += section_table_file_size_;
+
+  for (intptr_t i = 0; i < sections_.length(); i++) {
+    Section* section = sections_[i];
+    file_offset = Utils::RoundUp(file_offset, section->alignment);
+    section->file_offset = file_offset;
+    file_offset += section->file_size;
+    file_offset = Utils::RoundUp(file_offset, section->alignment);
+  }
+}
+
+void Elf::WriteHeader() {
+#if defined(TARGET_ARCH_IS_32_BIT)
+  uint8_t size = ELFCLASS32;
+#else
+  uint8_t size = ELFCLASS64;
+#endif
+  uint8_t e_ident[16] = {
+      0x7f, 'E', 'L', 'F', size, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
+      0,    0,   0,   0,   0,    0,           0,          0};
+  stream_->WriteBytes(e_ident, 16);
+
+  WriteHalf(ET_DYN);  // Shared library.
+
+#if defined(TARGET_ARCH_IA32)
+  WriteHalf(EM_386);
+#elif defined(TARGET_ARCH_X64)
+  WriteHalf(EM_X86_64);
+#elif defined(TARGET_ARCH_ARM)
+  WriteHalf(EM_ARM);
+#elif defined(TARGET_ARCH_ARM64)
+  WriteHalf(EM_AARCH64);
+#else
+  // E.g., DBC.
+  FATAL("Unknown ELF architecture");
+#endif
+
+  WriteWord(EV_CURRENT);  // Version
+  WriteAddr(0);           // "Entry point"
+  WriteOff(program_table_file_offset_);
+  WriteOff(section_table_file_offset_);
+
+#if defined(TARGET_ARCH_ARM)
+  uword flags = EF_ARM_ABI |
+                (TargetCPUFeatures::hardfp_supported() ? EF_ARM_ABI_FLOAT_HARD
+                                                       : EF_ARM_ABI_FLOAT_SOFT);
+#else
+  uword flags = 0;
+#endif
+  WriteWord(flags);
+
+  WriteHalf(kElfHeaderSize);
+  WriteHalf(kElfProgramTableEntrySize);
+  WriteHalf(segments_.length() + kNumImplicitSegments);
+  WriteHalf(kElfSectionTableEntrySize);
+  WriteHalf(sections_.length() + kNumInvalidSections);
+  WriteHalf(shstrtab_->section_index);
+
+  ASSERT(stream_->position() == kElfHeaderSize);
+}
+
+void Elf::WriteProgramTable() {
+  stream_->Align(kPageSize);
+
+  ASSERT(stream_->position() == program_table_file_offset_);
+
+  // Self-reference to program header table that Android wants for some reason.
+  // Must appear before any PT_LOAD entries.
+  {
+    ASSERT(kNumImplicitSegments == 3);
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(PT_PHDR);
+    WriteOff(program_table_file_offset_);
+    WriteAddr(memory_offset_);
+    WriteAddr(0);  // Physical address, not used.
+    WriteWord(program_table_file_size_);
+    WriteWord(program_table_file_size_);
+    WriteWord(PF_R);
+    WriteWord(kPageSize);
+#else
+    WriteWord(PT_PHDR);
+    WriteWord(PF_R);
+    WriteOff(program_table_file_offset_);
+    WriteAddr(memory_offset_);
+    WriteAddr(0);  // Physical address, not used.
+    WriteXWord(program_table_file_size_);
+    WriteXWord(program_table_file_size_);
+    WriteXWord(kPageSize);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfProgramTableEntrySize);
+  }
+
+  for (intptr_t i = 0; i < segments_.length(); i++) {
+    Section* section = segments_[i];
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(section->segment_type);
+    WriteOff(section->file_offset);
+    WriteAddr(section->memory_offset);
+    WriteAddr(0);  // Physical address, not used.
+    WriteWord(section->file_size);
+    WriteWord(section->memory_size);
+    WriteWord(section->segment_flags);
+    WriteWord(section->alignment);
+#else
+    WriteWord(section->segment_type);
+    WriteWord(section->segment_flags);
+    WriteOff(section->file_offset);
+    WriteAddr(section->memory_offset);
+    WriteAddr(0);  // Physical address, not used.
+    WriteXWord(section->file_size);
+    WriteXWord(section->memory_size);
+    WriteXWord(section->alignment);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfProgramTableEntrySize);
+  }
+
+  // Special case: the dynamic section requires both LOAD and DYNAMIC program
+  // header table entries.
+  {
+    ASSERT(kNumImplicitSegments == 3);
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(PT_DYNAMIC);
+    WriteOff(dynamic_->file_offset);
+    WriteAddr(dynamic_->memory_offset);
+    WriteAddr(0);  // Physical address, not used.
+    WriteWord(dynamic_->file_size);
+    WriteWord(dynamic_->memory_size);
+    WriteWord(dynamic_->segment_flags);
+    WriteWord(dynamic_->alignment);
+#else
+    WriteWord(PT_DYNAMIC);
+    WriteWord(dynamic_->segment_flags);
+    WriteOff(dynamic_->file_offset);
+    WriteAddr(dynamic_->memory_offset);
+    WriteAddr(0);  // Physical address, not used.
+    WriteXWord(dynamic_->file_size);
+    WriteXWord(dynamic_->memory_size);
+    WriteXWord(dynamic_->alignment);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfProgramTableEntrySize);
+  }
+
+  // Self-reference to program header table that Android wants for some reason.
+  {
+    ASSERT(kNumImplicitSegments == 3);
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(PT_LOAD);
+    WriteOff(program_table_file_offset_);
+    WriteAddr(memory_offset_);
+    WriteAddr(0);  // Physical address, not used.
+    WriteWord(program_table_file_size_);
+    WriteWord(program_table_file_size_);
+    WriteWord(PF_R);
+    WriteWord(kPageSize);
+#else
+    WriteWord(PT_LOAD);
+    WriteWord(PF_R);
+    WriteOff(program_table_file_offset_);
+    WriteAddr(memory_offset_);
+    WriteAddr(0);  // Physical address, not used.
+    WriteXWord(program_table_file_size_);
+    WriteXWord(program_table_file_size_);
+    WriteXWord(kPageSize);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfProgramTableEntrySize);
+  }
+}
+
+void Elf::WriteSectionTable() {
+  ASSERT(stream_->position() == section_table_file_offset_);
+
+  {
+    // The first entry in the section table is reserved and must be all zeros.
+    ASSERT(kNumInvalidSections == 1);
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(0);
+    WriteWord(0);
+    WriteWord(0);
+    WriteAddr(0);
+    WriteOff(0);
+    WriteWord(0);
+    WriteWord(0);
+    WriteWord(0);
+    WriteWord(0);
+    WriteWord(0);
+#else
+    WriteWord(0);
+    WriteWord(0);
+    WriteXWord(0);
+    WriteAddr(0);
+    WriteOff(0);
+    WriteXWord(0);
+    WriteWord(0);
+    WriteWord(0);
+    WriteXWord(0);
+    WriteXWord(0);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfSectionTableEntrySize);
+  }
+
+  for (intptr_t i = 0; i < sections_.length(); i++) {
+    Section* section = sections_[i];
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(section->section_name);
+    WriteWord(section->section_type);
+    WriteWord(section->section_flags);
+    WriteAddr(section->memory_offset);
+    WriteOff(section->file_offset);
+    WriteWord(section->file_size);  // Has different meaning for BSS.
+    WriteWord(section->section_link);
+    WriteWord(section->section_info);
+    WriteWord(section->alignment);
+    WriteWord(section->section_entry_size);
+#else
+    WriteWord(section->section_name);
+    WriteWord(section->section_type);
+    WriteXWord(section->section_flags);
+    WriteAddr(section->memory_offset);
+    WriteOff(section->file_offset);
+    WriteXWord(section->file_size);  // Has different meaning for BSS.
+    WriteWord(section->section_link);
+    WriteWord(section->section_info);
+    WriteXWord(section->alignment);
+    WriteXWord(section->section_entry_size);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfSectionTableEntrySize);
+  }
+}
+
+void Elf::WriteSections() {
+  for (intptr_t i = 0; i < sections_.length(); i++) {
+    Section* section = sections_[i];
+    stream_->Align(section->alignment);
+    ASSERT(stream_->position() == section->file_offset);
+    section->Write(this);
+    ASSERT(stream_->position() == section->file_offset + section->file_size);
+    stream_->Align(section->alignment);
+  }
+}
+
+}  // namespace dart
diff --git a/runtime/vm/elf.h b/runtime/vm/elf.h
new file mode 100644
index 0000000..aed4c66
--- /dev/null
+++ b/runtime/vm/elf.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_ELF_H_
+#define RUNTIME_VM_ELF_H_
+
+#include "vm/allocation.h"
+#include "vm/datastream.h"
+#include "vm/growable_array.h"
+#include "vm/zone.h"
+
+namespace dart {
+
+class DynamicTable;
+class Section;
+class StringTable;
+class Symbol;
+class SymbolTable;
+
+class Elf : public ZoneAllocated {
+ public:
+  Elf(Zone* zone, StreamingWriteStream* stream);
+
+  intptr_t NextMemoryOffset();
+  intptr_t AddText(const char* name, const uint8_t* bytes, intptr_t size);
+  intptr_t AddROData(const char* name, const uint8_t* bytes, intptr_t size);
+  void AddDebug(const char* name, const uint8_t* bytes, intptr_t size);
+
+  void Finalize();
+
+  intptr_t position() const { return stream_->position(); }
+  void WriteBytes(const uint8_t* b, intptr_t size) {
+    stream_->WriteBytes(b, size);
+  }
+  void WriteByte(uint8_t value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+  void WriteHalf(uint16_t value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+  void WriteWord(uint32_t value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+  void WriteAddr(uword value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+  void WriteOff(uword value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+#if defined(TARGET_ARCH_IS_64_BIT)
+  void WriteXWord(uint64_t value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+#endif
+
+ private:
+  void AddSection(Section* section);
+  void AddSegment(Section* section);
+
+  void ComputeFileOffsets();
+  void WriteHeader();
+  void WriteSectionTable();
+  void WriteProgramTable();
+  void WriteSections();
+
+  Zone* const zone_;
+  StreamingWriteStream* stream_;
+  GrowableArray<Section*> sections_;
+  GrowableArray<Section*> segments_;
+
+  intptr_t memory_offset_;
+  intptr_t section_table_file_offset_;
+  intptr_t section_table_file_size_;
+  intptr_t program_table_file_offset_;
+  intptr_t program_table_file_size_;
+  StringTable* shstrtab_;
+  StringTable* symstrtab_;
+  SymbolTable* symtab_;
+  DynamicTable* dynamic_;
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_ELF_H_
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 058d9c7..f40c90b 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -104,7 +104,7 @@
       dropped_frames_++;
     }
     // Encode the number of dropped frames into the pc offset.
-    frame_offset ^= Smi::New(dropped_frames_);
+    frame_offset = Smi::New(dropped_frames_);
     stacktrace_.SetPcOffsetAtFrame(null_slot, frame_offset);
     // Move frames one slot down so that we can accommodate the new frame.
     for (intptr_t i = start; i < StackTrace::kPreallocatedStackdepth; i++) {
@@ -130,21 +130,24 @@
   Code& code = Code::Handle();
   Bytecode& bytecode = Bytecode::Handle();
   Smi& offset = Smi::Handle();
-  while (frame != NULL) {
-    if (frame->IsDartFrame()) {
-      if (frame->is_interpreted()) {
-        bytecode = frame->LookupDartBytecode();
-        ASSERT(bytecode.ContainsInstructionAt(frame->pc()));
-        offset = Smi::New(frame->pc() - bytecode.PayloadStart());
-        builder->AddFrame(bytecode, offset);
-      } else {
-        code = frame->LookupDartCode();
-        ASSERT(code.ContainsInstructionAt(frame->pc()));
-        offset = Smi::New(frame->pc() - code.PayloadStart());
-        builder->AddFrame(code, offset);
-      }
+  for (; frame != NULL; frame = frames.NextFrame()) {
+    if (!frame->IsDartFrame()) {
+      continue;
     }
-    frame = frames.NextFrame();
+    if (frame->is_interpreted()) {
+      bytecode = frame->LookupDartBytecode();
+      ASSERT(bytecode.ContainsInstructionAt(frame->pc()));
+      if (bytecode.function() == Function::null()) {
+        continue;
+      }
+      offset = Smi::New(frame->pc() - bytecode.PayloadStart());
+      builder->AddFrame(bytecode, offset);
+    } else {
+      code = frame->LookupDartCode();
+      ASSERT(code.ContainsInstructionAt(frame->pc()));
+      offset = Smi::New(frame->pc() - code.PayloadStart());
+      builder->AddFrame(code, offset);
+    }
   }
 }
 
@@ -156,7 +159,7 @@
   // Iterate through the stack frames and try to find a frame with an
   // exception handler. Once found, set the pc, sp and fp so that execution
   // can continue in that frame. Sets 'needs_stacktrace' if there is no
-  // cath-all handler or if a stack-trace is specified in the catch.
+  // catch-all handler or if a stack-trace is specified in the catch.
   bool Find() {
     StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                               Thread::Current(),
@@ -368,15 +371,15 @@
 };
 
 CatchEntryMove CatchEntryMove::ReadFrom(ReadStream* stream) {
-  using Reader = ReadStream::Raw<sizeof(intptr_t), intptr_t>;
-  const intptr_t src = Reader::Read(stream);
-  const intptr_t dest_and_kind = Reader::Read(stream);
+  using Reader = ReadStream::Raw<sizeof(int32_t), int32_t>;
+  const int32_t src = Reader::Read(stream);
+  const int32_t dest_and_kind = Reader::Read(stream);
   return CatchEntryMove(src, dest_and_kind);
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 void CatchEntryMove::WriteTo(WriteStream* stream) {
-  using Writer = WriteStream::Raw<sizeof(intptr_t), intptr_t>;
+  using Writer = WriteStream::Raw<sizeof(int32_t), int32_t>;
   Writer::Write(stream, src_);
   Writer::Write(stream, dest_and_kind_);
 }
@@ -667,6 +670,15 @@
   DEBUG_ASSERT(thread->TopErrorHandlerIsExitFrame());
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
+#if !defined(PRODUCT)
+  // Do not notify debugger on stack overflow and out of memory exceptions.
+  // The VM would crash when the debugger calls back into the VM to
+  // get values of variables.
+  if (incoming_exception.raw() != isolate->object_store()->out_of_memory() &&
+      incoming_exception.raw() != isolate->object_store()->stack_overflow()) {
+    isolate->debugger()->PauseException(incoming_exception);
+  }
+#endif
   bool use_preallocated_stacktrace = false;
   Instance& exception = Instance::Handle(zone, incoming_exception.raw());
   if (exception.IsNull()) {
@@ -695,7 +707,7 @@
       thread->long_jump_base()->Jump(1, error);
       UNREACHABLE();
     }
-    stacktrace ^= isolate->object_store()->preallocated_stack_trace();
+    stacktrace = isolate->object_store()->preallocated_stack_trace();
     PreallocatedStackTraceBuilder frame_builder(stacktrace);
     ASSERT(existing_stacktrace.IsNull() ||
            (existing_stacktrace.raw() == stacktrace.raw()));
@@ -877,16 +889,6 @@
 }
 
 void Exceptions::Throw(Thread* thread, const Instance& exception) {
-  // Do not notify debugger on stack overflow and out of memory exceptions.
-  // The VM would crash when the debugger calls back into the VM to
-  // get values of variables.
-#if !defined(PRODUCT)
-  Isolate* isolate = thread->isolate();
-  if (exception.raw() != isolate->object_store()->out_of_memory() &&
-      exception.raw() != isolate->object_store()->stack_overflow()) {
-    isolate->debugger()->PauseException(exception);
-  }
-#endif
   // Null object is a valid exception object.
   ThrowExceptionHelper(thread, exception, StackTrace::Handle(thread->zone()),
                        false);
@@ -993,6 +995,12 @@
   Exceptions::ThrowByType(Exceptions::kRange, args);
 }
 
+void Exceptions::ThrowUnsupportedError(const char* msg) {
+  const Array& args = Array::Handle(Array::New(1));
+  args.SetAt(0, String::Handle(String::New(msg)));
+  Exceptions::ThrowByType(Exceptions::kUnsupported, args);
+}
+
 void Exceptions::ThrowRangeErrorMsg(const char* msg) {
   const Array& args = Array::Handle(Array::New(1));
   args.SetAt(0, String::Handle(String::New(msg)));
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 894f374..50d1a8f 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -84,6 +84,7 @@
                                             intptr_t expected_from,
                                             intptr_t expected_to);
   DART_NORETURN static void ThrowRangeErrorMsg(const char* msg);
+  DART_NORETURN static void ThrowUnsupportedError(const char* msg);
   DART_NORETURN static void ThrowCompileTimeError(const LanguageError& error);
 
   // Returns a RawInstance if the exception is successfully created,
@@ -202,21 +203,21 @@
 #endif
 
  private:
-  CatchEntryMove(intptr_t src, intptr_t dest_and_kind)
+  CatchEntryMove(int32_t src, int32_t dest_and_kind)
       : src_(src), dest_and_kind_(dest_and_kind) {}
 
   // Note: BitField helper does not work with signed values of size that does
   // not match the destination size - thus we don't use BitField for declaring
   // DestinationField and instead encode and decode it manually.
-  using SourceKindField = BitField<intptr_t, SourceKind, 0, 4>;
+  using SourceKindField = BitField<int32_t, SourceKind, 0, 4>;
 
-  static constexpr intptr_t kHalfSourceBits = kBitsPerWord / 2;
-  using LoSourceSlot = BitField<intptr_t, intptr_t, 0, kHalfSourceBits>;
+  static constexpr intptr_t kHalfSourceBits = 16;
+  using LoSourceSlot = BitField<int32_t, int32_t, 0, kHalfSourceBits>;
   using HiSourceSlot =
-      BitField<intptr_t, intptr_t, kHalfSourceBits, kHalfSourceBits>;
+      BitField<int32_t, int32_t, kHalfSourceBits, kHalfSourceBits>;
 
-  intptr_t src_;
-  intptr_t dest_and_kind_;
+  int32_t src_;
+  int32_t dest_and_kind_;
 };
 
 // A sequence of moves that needs to be executed to create a state expected
diff --git a/runtime/vm/finalizable_data.h b/runtime/vm/finalizable_data.h
index f4ae01a..df383d2 100644
--- a/runtime/vm/finalizable_data.h
+++ b/runtime/vm/finalizable_data.h
@@ -15,6 +15,7 @@
   void* data;
   void* peer;
   Dart_WeakPersistentHandleFinalizer callback;
+  Dart_WeakPersistentHandleFinalizer successful_write_callback;
 };
 
 class MessageFinalizableData {
@@ -23,18 +24,24 @@
 
   ~MessageFinalizableData() {
     for (intptr_t i = position_; i < records_.length(); i++) {
-      records_[i].callback(NULL, NULL, records_[i].peer);
+      records_[i].callback(nullptr, nullptr, records_[i].peer);
     }
   }
 
-  void Put(intptr_t external_size,
-           void* data,
-           void* peer,
-           Dart_WeakPersistentHandleFinalizer callback) {
+  /// If [successful_write_callback] is provided, it's invoked when message
+  /// was serialized successfully.
+  /// [callback] is invoked when serialization failed.
+  void Put(
+      intptr_t external_size,
+      void* data,
+      void* peer,
+      Dart_WeakPersistentHandleFinalizer callback,
+      Dart_WeakPersistentHandleFinalizer successful_write_callback = nullptr) {
     FinalizableData finalizable_data;
     finalizable_data.data = data;
     finalizable_data.peer = peer;
     finalizable_data.callback = callback;
+    finalizable_data.successful_write_callback = successful_write_callback;
     records_.Add(finalizable_data);
     external_size_ += external_size;
   }
@@ -44,6 +51,15 @@
     return records_[position_++];
   }
 
+  void SerializationSucceeded() {
+    for (intptr_t i = position_; i < records_.length(); i++) {
+      if (records_[i].successful_write_callback != nullptr) {
+        records_[i].successful_write_callback(nullptr, nullptr,
+                                              records_[i].peer);
+      }
+    }
+  }
+
   intptr_t external_size() const { return external_size_; }
 
  private:
diff --git a/runtime/vm/find_code_object_test.cc b/runtime/vm/find_code_object_test.cc
deleted file mode 100644
index 1fe3662..0000000
--- a/runtime/vm/find_code_object_test.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// 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.
-
-#include "platform/assert.h"
-#include "vm/class_finalizer.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/heap/pages.h"
-#include "vm/object.h"
-#include "vm/stack_frame.h"
-#include "vm/symbols.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
-static const int kScriptSize = 512 * KB;
-static const int kLoopCount = 50000;
-#elif defined(TARGET_ARCH_DBC)
-static const int kScriptSize = 1 * MB;
-static const int kLoopCount = 60000;
-#else
-static const int kScriptSize = 512 * KB;
-static const int kLoopCount = 25000;
-#endif
-static char scriptChars[kScriptSize];
-
-ISOLATE_UNIT_TEST_CASE(FindCodeObject) {
-  const int kNumFunctions = 1024;
-
-  // Get access to the code index table.
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != NULL);
-
-  StackZone zone(thread);
-  String& url = String::Handle(String::New("dart-test:FindCodeObject"));
-  String& source = String::Handle();
-  Script& script = Script::Handle();
-  Library& lib = Library::Handle();
-  Class& clsA = Class::Handle();
-  Class& clsB = Class::Handle();
-  String& function_name = String::Handle();
-  Function& function = Function::Handle();
-  char buffer[256];
-
-  lib = Library::CoreLibrary();
-
-  // Load up class A with 1024 functions.
-  int written = Utils::SNPrint(scriptChars, kScriptSize, "class A {");
-  for (int i = 0; i < kNumFunctions; i++) {
-    Utils::SNPrint(buffer, 256,
-                   "static foo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
-    written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
-                              "%s", buffer);
-  }
-  Utils::SNPrint((scriptChars + written), (kScriptSize - written), "}");
-  source = String::New(scriptChars);
-  script = Script::New(url, source, RawScript::kScriptTag);
-  EXPECT(CompilerTest::TestCompileScript(lib, script));
-  clsA = lib.LookupClass(String::Handle(Symbols::New(thread, "A")));
-  EXPECT(!clsA.IsNull());
-  ClassFinalizer::ProcessPendingClasses();
-  for (int i = 0; i < kNumFunctions; i++) {
-    Utils::SNPrint(buffer, 256, "foo%d", i);
-    function_name = String::New(buffer);
-    function = clsA.LookupStaticFunction(function_name);
-    EXPECT(!function.IsNull());
-    EXPECT(CompilerTest::TestCompileFunction(function));
-    const Code& code = Code::ZoneHandle(function.CurrentCode());
-    EXPECT(!code.IsNull())
-    EXPECT(function.HasCode());
-  }
-
-  // Now load up class B with 1024 functions.
-  written = Utils::SNPrint(scriptChars, kScriptSize, "class B {");
-  // Create one large function.
-  Utils::SNPrint(buffer, sizeof(buffer), "static moo0([var i=1]) { ");
-  written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
-                            "%s", buffer);
-  // Generate a large function so that the code for this function when
-  // compiled will reside in a large page.
-  for (int i = 0; i < kLoopCount; i++) {
-    Utils::SNPrint(buffer, sizeof(buffer), "i = i+i;");
-    written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
-                              "%s", buffer);
-  }
-  Utils::SNPrint(buffer, sizeof(buffer), "return i; }");
-  written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
-                            "%s", buffer);
-  for (int i = 1; i < kNumFunctions; i++) {
-    Utils::SNPrint(buffer, 256,
-                   "static moo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
-    written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
-                              "%s", buffer);
-  }
-  Utils::SNPrint((scriptChars + written), (kScriptSize - written), "}");
-  url = String::New("dart-test:FindCodeObject");
-  source = String::New(scriptChars);
-  script = Script::New(url, source, RawScript::kScriptTag);
-  EXPECT(CompilerTest::TestCompileScript(lib, script));
-  clsB = lib.LookupClass(String::Handle(Symbols::New(thread, "B")));
-  EXPECT(!clsB.IsNull());
-  ClassFinalizer::ProcessPendingClasses();
-  for (int i = 0; i < kNumFunctions; i++) {
-    Utils::SNPrint(buffer, 256, "moo%d", i);
-    function_name = String::New(buffer);
-    function = clsB.LookupStaticFunction(function_name);
-    EXPECT(!function.IsNull());
-    EXPECT(CompilerTest::TestCompileFunction(function));
-    const Code& code = Code::ZoneHandle(function.CurrentCode());
-    EXPECT(!code.IsNull());
-    EXPECT(function.HasCode());
-  }
-
-  // Now try and access these functions using the code index table.
-  Code& code = Code::Handle();
-  uword pc;
-  Utils::SNPrint(buffer, 256, "foo%d", 123);
-  function_name = String::New(buffer);
-  function = clsA.LookupStaticFunction(function_name);
-  EXPECT(!function.IsNull());
-  code = function.CurrentCode();
-  EXPECT(code.Size() > 16);
-  pc = code.PayloadStart() + 16;
-  EXPECT(Code::LookupCode(pc) == code.raw());
-
-  Utils::SNPrint(buffer, 256, "moo%d", 54);
-  function_name = String::New(buffer);
-  function = clsB.LookupStaticFunction(function_name);
-  EXPECT(!function.IsNull());
-  code = function.CurrentCode();
-  EXPECT(code.Size() > 16);
-  pc = code.PayloadStart() + 16;
-  EXPECT(Code::LookupCode(pc) == code.raw());
-
-  // Lookup the large function
-  Utils::SNPrint(buffer, 256, "moo%d", 0);
-  function_name = String::New(buffer);
-  function = clsB.LookupStaticFunction(function_name);
-  EXPECT(!function.IsNull());
-  code = function.CurrentCode();
-  EXPECT(code.Size() > 16);
-  pc = code.PayloadStart() + 16;
-  EXPECT(code.Size() > kPageSize);
-  EXPECT(Code::LookupCode(pc) == code.raw());
-  EXPECT(code.Size() > (1 * MB));
-  pc = code.PayloadStart() + (1 * MB);
-  EXPECT(Code::LookupCode(pc) == code.raw());
-}
-
-}  // namespace dart
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index d7b662d..a406f01 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -58,7 +58,7 @@
   P(background_compilation, bool, USING_MULTICORE,                             \
     "Run optimizing compilation in background")                                \
   P(causal_async_stacks, bool, !USING_PRODUCT, "Improved async stacks")        \
-  P(collect_code, bool, true, "Attempt to GC infrequently used code.")         \
+  P(collect_code, bool, false, "Attempt to GC infrequently used code.")        \
   P(collect_dynamic_function_names, bool, true,                                \
     "Collects all dynamic function names to identify unique targets")          \
   P(compactor_tasks, int, 2,                                                   \
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index ad33a42..1734984c 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -73,6 +73,25 @@
 #define NOT_IN_PRECOMPILED(code) code
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
+#if defined(TARGET_ARCH_DBC)
+#define NOT_IN_DBC(code)
+#else
+#define NOT_IN_DBC(code) code
+#endif  // defined(TARGET_ARCH_DBC)
+
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
+    defined(TARGET_ARCH_X64)
+#define ONLY_IN_ARM_ARM64_X64(code) code
+#else
+#define ONLY_IN_ARM_ARM64_X64(code)
+#endif
+
+#if defined(DART_PRECOMPILED_RUNTIME)
+#define NOT_IN_PRECOMPILED_RUNTIME(code)
+#else
+#define NOT_IN_PRECOMPILED_RUNTIME(code) code
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+
 #if !defined(PRODUCT) || defined(HOST_OS_FUCHSIA) || defined(TARGET_OS_FUCHSIA)
 #define SUPPORT_TIMELINE 1
 #endif
@@ -161,6 +180,17 @@
 
 #endif  // !defined(HOST_OS_WINDOWS))
 
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
+    defined(TARGET_ARCH_X64)
+#define TARGET_USES_OBJECT_POOL 1
+#endif
+
+#if defined(DART_PRECOMPILER) &&                                               \
+    (defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM) ||                   \
+     defined(TARGET_ARCH_ARM64))
+#define DART_SUPPORT_PRECOMPILATION 1
+#endif
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_GLOBALS_H_
diff --git a/runtime/vm/heap/freelist.cc b/runtime/vm/heap/freelist.cc
index 9c2aca1..c98af37 100644
--- a/runtime/vm/heap/freelist.cc
+++ b/runtime/vm/heap/freelist.cc
@@ -55,22 +55,20 @@
 }
 
 FreeList::FreeList()
-    : mutex_(new Mutex()),
-      freelist_search_budget_(kInitialFreeListSearchBudget) {
+    : mutex_(), freelist_search_budget_(kInitialFreeListSearchBudget) {
   Reset();
 }
 
 FreeList::~FreeList() {
-  delete mutex_;
 }
 
 uword FreeList::TryAllocate(intptr_t size, bool is_protected) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   return TryAllocateLocked(size, is_protected);
 }
 
 uword FreeList::TryAllocateLocked(intptr_t size, bool is_protected) {
-  DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
+  DEBUG_ASSERT(mutex_.IsOwnedByCurrentThread());
   // Precondition: is_protected is false or else all free list elements are
   // in non-writable pages.
 
@@ -176,12 +174,12 @@
 }
 
 void FreeList::Free(uword addr, intptr_t size) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   FreeLocked(addr, size);
 }
 
 void FreeList::FreeLocked(uword addr, intptr_t size) {
-  DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
+  DEBUG_ASSERT(mutex_.IsOwnedByCurrentThread());
   // Precondition required by AsElement and EnqueueElement: the (page
   // containing the) header of the freed block should be writable.  This is
   // the case when called for newly allocated pages because they are
@@ -194,7 +192,7 @@
 }
 
 void FreeList::Reset() {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   free_map_.Reset();
   last_free_small_size_ = -1;
   for (int i = 0; i < (kNumLists + 1); i++) {
@@ -214,7 +212,7 @@
 }
 
 intptr_t FreeList::LengthLocked(int index) const {
-  DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
+  DEBUG_ASSERT(mutex_.IsOwnedByCurrentThread());
   ASSERT(index >= 0);
   ASSERT(index < kNumLists);
   intptr_t result = 0;
@@ -306,7 +304,7 @@
 }
 
 void FreeList::Print() const {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   PrintSmall();
   PrintLarge();
 }
@@ -337,12 +335,12 @@
 }
 
 FreeListElement* FreeList::TryAllocateLarge(intptr_t minimum_size) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   return TryAllocateLargeLocked(minimum_size);
 }
 
 FreeListElement* FreeList::TryAllocateLargeLocked(intptr_t minimum_size) {
-  DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
+  DEBUG_ASSERT(mutex_.IsOwnedByCurrentThread());
   FreeListElement* previous = NULL;
   FreeListElement* current = free_lists_[kNumLists];
   // TODO(koda): Find largest.
diff --git a/runtime/vm/heap/freelist.h b/runtime/vm/heap/freelist.h
index 171ff1c..9fac19d 100644
--- a/runtime/vm/heap/freelist.h
+++ b/runtime/vm/heap/freelist.h
@@ -86,7 +86,7 @@
 
   void Print() const;
 
-  Mutex* mutex() { return mutex_; }
+  Mutex* mutex() { return &mutex_; }
   uword TryAllocateLocked(intptr_t size, bool is_protected);
   void FreeLocked(uword addr, intptr_t size);
 
@@ -97,7 +97,7 @@
   // Allocates locked and unprotected memory, but only from small elements
   // (i.e., fixed size lists).
   uword TryAllocateSmallLocked(intptr_t size) {
-    DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
+    DEBUG_ASSERT(mutex_.IsOwnedByCurrentThread());
     if (size > last_free_small_size_) {
       return 0;
     }
@@ -159,7 +159,7 @@
   void PrintLarge() const;
 
   // Lock protecting the free list data structures.
-  Mutex* mutex_;
+  mutable Mutex mutex_;
 
   BitSet<kNumLists> free_map_;
 
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 10f20bb..ca9aa44 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -39,11 +39,12 @@
     : isolate_(isolate),
       new_space_(this, max_new_gen_semi_words, kNewObjectAlignmentOffset),
       old_space_(this, max_old_gen_words),
-      barrier_(new Monitor()),
-      barrier_done_(new Monitor()),
+      barrier_(),
+      barrier_done_(),
       read_only_(false),
       gc_new_space_in_progress_(false),
-      gc_old_space_in_progress_(false) {
+      gc_old_space_in_progress_(false),
+      gc_on_next_allocation_(false) {
   UpdateGlobalMaxUsed();
   for (int sel = 0; sel < kNumWeakSelectors; sel++) {
     new_weak_tables_[sel] = new WeakTable();
@@ -53,9 +54,6 @@
 }
 
 Heap::~Heap() {
-  delete barrier_;
-  delete barrier_done_;
-
   for (int sel = 0; sel < kNumWeakSelectors; sel++) {
     delete new_weak_tables_[sel];
     delete old_weak_tables_[sel];
@@ -83,6 +81,7 @@
 
 uword Heap::AllocateNew(intptr_t size) {
   ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0);
+  CollectForDebugging();
   Thread* thread = Thread::Current();
   uword addr = new_space_.TryAllocateInTLAB(thread, size);
   if (addr != 0) {
@@ -128,6 +127,7 @@
 
 uword Heap::AllocateOld(intptr_t size, HeapPage::PageType type) {
   ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0);
+  CollectForDebugging();
   uword addr = old_space_.TryAllocate(size, type);
   if (addr != 0) {
     return addr;
@@ -655,6 +655,17 @@
   old_space_.AddRegionsToObjectSet(set);
 }
 
+void Heap::CollectOnNextAllocation() {
+  AbandonRemainingTLAB(Thread::Current());
+  gc_on_next_allocation_ = true;
+}
+
+void Heap::CollectForDebugging() {
+  if (!gc_on_next_allocation_) return;
+  CollectAllGarbage(kDebugging);
+  gc_on_next_allocation_ = false;
+}
+
 ObjectSet* Heap::CreateAllocatedObjectSet(
     Zone* zone,
     MarkExpectation mark_expectation) const {
@@ -1020,6 +1031,16 @@
 #endif  // !defined(PRODUCT)
 }
 
+Heap::Space Heap::SpaceForExternal(intptr_t size) const {
+  // If 'size' would be a significant fraction of new space, then use old.
+  static const int kExtNewRatio = 16;
+  if (size > (CapacityInWords(Heap::kNew) * kWordSize) / kExtNewRatio) {
+    return Heap::kOld;
+  } else {
+    return Heap::kNew;
+  }
+}
+
 NoHeapGrowthControlScope::NoHeapGrowthControlScope()
     : ThreadStackResource(Thread::Current()) {
   Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap();
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 628ab15..6f530b9 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -284,8 +284,8 @@
 
   Isolate* isolate() const { return isolate_; }
 
-  Monitor* barrier() const { return barrier_; }
-  Monitor* barrier_done() const { return barrier_done_; }
+  Monitor* barrier() const { return &barrier_; }
+  Monitor* barrier_done() const { return &barrier_done_; }
 
   void SetupImagePage(void* pointer, uword size, bool is_executable) {
     old_space_.SetupImagePage(pointer, size, is_executable);
@@ -301,6 +301,9 @@
   }
   void MakeTLABIterable(Thread* thread);
   void AbandonRemainingTLAB(Thread* thread);
+  Space SpaceForExternal(intptr_t size) const;
+
+  void CollectOnNextAllocation();
 
  private:
   class GCStats : public ValueObject {
@@ -373,6 +376,9 @@
 
   void AddRegionsToObjectSet(ObjectSet* set) const;
 
+  // Trigger major GC if 'gc_on_next_allocation_' is set.
+  void CollectForDebugging();
+
   Isolate* isolate_;
 
   // The different spaces used for allocation.
@@ -382,8 +388,8 @@
   WeakTable* new_weak_tables_[kNumWeakSelectors];
   WeakTable* old_weak_tables_[kNumWeakSelectors];
 
-  Monitor* barrier_;
-  Monitor* barrier_done_;
+  mutable Monitor barrier_;
+  mutable Monitor barrier_done_;
 
   // GC stats collection.
   GCStats stats_;
@@ -396,6 +402,11 @@
   bool gc_new_space_in_progress_;
   bool gc_old_space_in_progress_;
 
+  // Whether the next heap allocation (new or old) should trigger
+  // CollectAllGarbage. Used within unit tests for testing GC on certain
+  // sensitive codepaths.
+  bool gc_on_next_allocation_;
+
   friend class Become;       // VisitObjectPointers
   friend class GCCompactor;  // VisitObjectPointers
   friend class Precompiler;  // VisitObjects
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index 7ff24be..ec644c0 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -21,92 +21,6 @@
 
 namespace dart {
 
-// Collects a list of RawFunction whose code_ or unoptimized_code_ slots were
-// treated as weak (not visited) during marking because they had low usage.
-// These slots (and the corresponding entry_point_ caches) must be cleared after
-// marking if the target RawCode were not otherwise marked. (--collect-code)
-class SkippedCodeFunctions {
- public:
-  SkippedCodeFunctions() {}
-
-  void Add(RawFunction* func) {
-    // With concurrent mark, we hold raw pointers across safepoints.
-    ASSERT(func->IsOldObject());
-
-    skipped_code_functions_.Add(func);
-  }
-
-  void DetachCode() {
-#if defined(DART_PRECOMPILED_RUNTIME)
-    UNREACHABLE();
-#else
-    Thread* thread = Thread::Current();
-    StackZone zone(thread);  // For log prints.
-    HANDLESCOPE(thread);
-
-    intptr_t unoptimized_code_count = 0;
-    intptr_t current_code_count = 0;
-    for (int i = 0; i < skipped_code_functions_.length(); i++) {
-      RawFunction* func = skipped_code_functions_[i];
-      RawCode* code = func->ptr()->code_;
-      if (!code->IsMarked()) {
-        // If the code wasn't strongly visited through other references
-        // after skipping the function's code pointer, then we disconnect the
-        // code from the function.
-        if (FLAG_enable_interpreter && Function::HasBytecode(func)) {
-          func->StorePointer(&(func->ptr()->code_),
-                             StubCode::InterpretCall().raw());
-          uword entry_point = StubCode::InterpretCall().EntryPoint();
-          func->ptr()->entry_point_ = entry_point;
-          func->ptr()->unchecked_entry_point_ = entry_point;
-        } else {
-          func->StorePointer(&(func->ptr()->code_),
-                             StubCode::LazyCompile().raw());
-          uword entry_point = StubCode::LazyCompile().EntryPoint();
-          func->ptr()->entry_point_ = entry_point;
-          func->ptr()->unchecked_entry_point_ = entry_point;
-        }
-        if (FLAG_log_code_drop) {
-          // NOTE: This code runs while GC is in progress and runs within
-          // a NoHandleScope block. Hence it is not okay to use a regular Zone
-          // or Scope handle. We use a direct stack handle so the raw pointer in
-          // this handle is not traversed. The use of a handle is mainly to
-          // be able to reuse the handle based code and avoid having to add
-          // helper functions to the raw object interface.
-          String name;
-          name = func->ptr()->name_;
-          THR_Print("Detaching code: %s\n", name.ToCString());
-          current_code_count++;
-        }
-      }
-
-      code = func->ptr()->unoptimized_code_;
-      if (!code->IsMarked()) {
-        // If the code wasn't strongly visited through other references
-        // after skipping the function's code pointer, then we disconnect the
-        // code from the function.
-        func->StorePointer(&(func->ptr()->unoptimized_code_), Code::null());
-        if (FLAG_log_code_drop) {
-          unoptimized_code_count++;
-        }
-      }
-    }
-    if (FLAG_log_code_drop) {
-      THR_Print("  total detached current: %" Pd "\n", current_code_count);
-      THR_Print("  total detached unoptimized: %" Pd "\n",
-                unoptimized_code_count);
-    }
-    // Clean up.
-    skipped_code_functions_.Clear();
-#endif  // !DART_PRECOMPILED_RUNTIME
-  }
-
- private:
-  MallocGrowableArray<RawFunction*> skipped_code_functions_;
-
-  DISALLOW_COPY_AND_ASSIGN(SkippedCodeFunctions);
-};
-
 class MarkerWorkList : public ValueObject {
  public:
   explicit MarkerWorkList(MarkingStack* marking_stack)
@@ -172,8 +86,7 @@
   MarkingVisitorBase(Isolate* isolate,
                      PageSpace* page_space,
                      MarkingStack* marking_stack,
-                     MarkingStack* deferred_marking_stack,
-                     SkippedCodeFunctions* skipped_code_functions)
+                     MarkingStack* deferred_marking_stack)
       : ObjectPointerVisitor(isolate),
         thread_(Thread::Current()),
 #ifndef PRODUCT
@@ -185,7 +98,6 @@
         work_list_(marking_stack),
         deferred_work_list_(deferred_marking_stack),
         delayed_weak_properties_(NULL),
-        skipped_code_functions_(skipped_code_functions),
         marked_bytes_(0),
         marked_micros_(0) {
     ASSERT(thread_->isolate() == isolate);
@@ -198,7 +110,6 @@
   }
 
   ~MarkingVisitorBase() {
-    delete skipped_code_functions_;
 #ifndef PRODUCT
     delete[] class_stats_count_;
     delete[] class_stats_size_;
@@ -286,13 +197,6 @@
     }
   }
 
-  bool visit_function_code() const { return skipped_code_functions_ == NULL; }
-
-  virtual void add_skipped_code_function(RawFunction* func) {
-    ASSERT(!visit_function_code());
-    skipped_code_functions_->Add(func);
-  }
-
   void EnqueueWeakProperty(RawWeakProperty* raw_weak) {
     ASSERT(raw_weak->IsHeapObject());
     ASSERT(raw_weak->IsOldObject());
@@ -346,10 +250,6 @@
   // Called when all marking is complete.
   void Finalize() {
     work_list_.Finalize();
-    // Detach code from functions.
-    if (skipped_code_functions_ != NULL) {
-      skipped_code_functions_->DetachCode();
-    }
     // Clear pending weak properties.
     RawWeakProperty* cur_weak = delayed_weak_properties_;
     delayed_weak_properties_ = NULL;
@@ -447,7 +347,6 @@
   MarkerWorkList work_list_;
   MarkerWorkList deferred_work_list_;
   RawWeakProperty* delayed_weak_properties_;
-  SkippedCodeFunctions* skipped_code_functions_;
   uintptr_t marked_bytes_;
   int64_t marked_micros_;
 
@@ -881,7 +780,7 @@
   delete[] visitors_;
 }
 
-void GCMarker::StartConcurrentMark(PageSpace* page_space, bool collect_code) {
+void GCMarker::StartConcurrentMark(PageSpace* page_space) {
   isolate_->EnableIncrementalBarrier(&marking_stack_, &deferred_marking_stack_);
 
   const intptr_t num_tasks = FLAG_marker_tasks;
@@ -901,11 +800,8 @@
   ResetRootSlices();
   for (intptr_t i = 0; i < num_tasks; i++) {
     ASSERT(visitors_[i] == NULL);
-    SkippedCodeFunctions* skipped_code_functions =
-        collect_code ? new SkippedCodeFunctions() : NULL;
     visitors_[i] = new SyncMarkingVisitor(isolate_, page_space, &marking_stack_,
-                                          &deferred_marking_stack_,
-                                          skipped_code_functions);
+                                          &deferred_marking_stack_);
 
     // Begin marking on a helper thread.
     bool result = Dart::thread_pool()->Run(
@@ -920,7 +816,7 @@
   }
 }
 
-void GCMarker::MarkObjects(PageSpace* page_space, bool collect_code) {
+void GCMarker::MarkObjects(PageSpace* page_space) {
   if (isolate_->marking_stack() != NULL) {
     isolate_->DisableIncrementalBarrier();
   }
@@ -933,11 +829,8 @@
       TIMELINE_FUNCTION_GC_DURATION(thread, "Mark");
       int64_t start = OS::GetCurrentMonotonicMicros();
       // Mark everything on main thread.
-      SkippedCodeFunctions* skipped_code_functions =
-          collect_code ? new SkippedCodeFunctions() : NULL;
       UnsyncMarkingVisitor mark(isolate_, page_space, &marking_stack_,
-                                &deferred_marking_stack_,
-                                skipped_code_functions);
+                                &deferred_marking_stack_);
       ResetRootSlices();
       IterateRoots(&mark);
       mark.ProcessDeferredMarking();
@@ -965,11 +858,8 @@
           visitor = visitors_[i];
           visitors_[i] = NULL;
         } else {
-          SkippedCodeFunctions* skipped_code_functions =
-              collect_code ? new SkippedCodeFunctions() : NULL;
           visitor = new SyncMarkingVisitor(
-              isolate_, page_space, &marking_stack_, &deferred_marking_stack_,
-              skipped_code_functions);
+              isolate_, page_space, &marking_stack_, &deferred_marking_stack_);
         }
 
         bool result = Dart::thread_pool()->Run(new ParallelMarkTask(
diff --git a/runtime/vm/heap/marker.h b/runtime/vm/heap/marker.h
index 6108e21..9216445 100644
--- a/runtime/vm/heap/marker.h
+++ b/runtime/vm/heap/marker.h
@@ -35,11 +35,11 @@
   // Mark roots synchronously, then spawn tasks to concurrently drain the
   // marking queue. Only called when no marking or sweeping is in progress.
   // Marking must later be finalized by calling MarkObjects.
-  void StartConcurrentMark(PageSpace* page_space, bool collect_code);
+  void StartConcurrentMark(PageSpace* page_space);
 
   // (Re)mark roots, drain the marking queue and finalize weak references.
   // Does not required StartConcurrentMark to have been previously called.
-  void MarkObjects(PageSpace* page_space, bool collect_code);
+  void MarkObjects(PageSpace* page_space);
 
   intptr_t marked_words() const { return marked_bytes_ >> kWordSizeLog2; }
   intptr_t MarkedWordsPerMicro() const;
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 5ef2454..23c83dd 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -40,18 +40,6 @@
             print_free_list_after_gc,
             false,
             "Print free list statistics after a GC");
-DEFINE_FLAG(int,
-            code_collection_interval_in_us,
-            30000000,
-            "Time between attempts to collect unused code.");
-DEFINE_FLAG(bool,
-            log_code_drop,
-            false,
-            "Emit a log message when pointers to unused code are dropped.");
-DEFINE_FLAG(bool,
-            always_drop_code,
-            false,
-            "Always try to drop code if the function's usage counter is >= 0");
 DEFINE_FLAG(bool, log_growth, false, "Log PageSpace growth policy decisions.");
 
 HeapPage* HeapPage::Allocate(intptr_t size_in_words,
@@ -237,7 +225,7 @@
 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity_in_words)
     : freelist_(),
       heap_(heap),
-      pages_lock_(new Mutex()),
+      pages_lock_(),
       pages_(NULL),
       pages_tail_(NULL),
       exec_pages_(NULL),
@@ -249,7 +237,7 @@
       max_capacity_in_words_(max_capacity_in_words),
       usage_(),
       allocated_black_in_words_(0),
-      tasks_lock_(new Monitor()),
+      tasks_lock_(),
       tasks_(0),
       concurrent_marker_tasks_(0),
       phase_(kDone),
@@ -281,8 +269,6 @@
   FreePages(exec_pages_);
   FreePages(large_pages_);
   FreePages(image_pages_);
-  delete pages_lock_;
-  delete tasks_lock_;
   ASSERT(marker_ == NULL);
 }
 
@@ -294,7 +280,7 @@
 
 HeapPage* PageSpace::AllocatePage(HeapPage::PageType type, bool link) {
   {
-    MutexLocker ml(pages_lock_);
+    MutexLocker ml(&pages_lock_);
     if (!CanIncreaseCapacityInWordsLocked(kPageSizeInWords)) {
       return NULL;
     }
@@ -312,7 +298,7 @@
     return NULL;
   }
 
-  MutexLocker ml(pages_lock_);
+  MutexLocker ml(&pages_lock_);
   if (link) {
     if (!is_exec) {
       if (pages_ == NULL) {
@@ -348,7 +334,7 @@
 HeapPage* PageSpace::AllocateLargePage(intptr_t size, HeapPage::PageType type) {
   const intptr_t page_size_in_words = LargePageSizeInWordsFor(size);
   {
-    MutexLocker ml(pages_lock_);
+    MutexLocker ml(&pages_lock_);
     if (!CanIncreaseCapacityInWordsLocked(page_size_in_words)) {
       return NULL;
     }
@@ -391,7 +377,7 @@
 void PageSpace::FreePage(HeapPage* page, HeapPage* previous_page) {
   bool is_exec = (page->type() == HeapPage::kExecutable);
   {
-    MutexLocker ml(pages_lock_);
+    MutexLocker ml(&pages_lock_);
     IncreaseCapacityInWordsLocked(-(page->memory_->size() >> kWordSizeLog2));
     if (!is_exec) {
       // Remove the page from the list of data pages.
@@ -565,7 +551,7 @@
 class ExclusivePageIterator : ValueObject {
  public:
   explicit ExclusivePageIterator(const PageSpace* space)
-      : space_(space), ml_(space->pages_lock_) {
+      : space_(space), ml_(&space->pages_lock_) {
     space_->MakeIterable();
     list_ = kRegular;
     page_ = space_->pages_;
@@ -617,7 +603,7 @@
 class ExclusiveCodePageIterator : ValueObject {
  public:
   explicit ExclusiveCodePageIterator(const PageSpace* space)
-      : space_(space), ml_(space->pages_lock_) {
+      : space_(space), ml_(&space->pages_lock_) {
     space_->MakeIterable();
     page_ = space_->exec_pages_;
   }
@@ -639,7 +625,7 @@
 class ExclusiveLargePageIterator : ValueObject {
  public:
   explicit ExclusiveLargePageIterator(const PageSpace* space)
-      : space_(space), ml_(space->pages_lock_) {
+      : space_(space), ml_(&space->pages_lock_) {
     space_->MakeIterable();
     page_ = space_->large_pages_;
   }
@@ -896,7 +882,7 @@
     // {"object_start": "0x...", "objects": [size, class id, size, ...]}
     // TODO(19445): Use ExclusivePageIterator once HeapMap supports large pages.
     HeapIterationScope iteration(Thread::Current());
-    MutexLocker ml(pages_lock_);
+    MutexLocker ml(&pages_lock_);
     MakeIterable();
     JSONArray all_pages(&heap_map, "pages");
     for (HeapPage* page = pages_; page != NULL; page = page->next()) {
@@ -919,26 +905,9 @@
 }
 #endif  // PRODUCT
 
-bool PageSpace::ShouldCollectCode() {
-  // Try to collect code if enough time has passed since the last attempt.
-  const int64_t start = OS::GetCurrentMonotonicMicros();
-  const int64_t last_code_collection_in_us =
-      page_space_controller_.last_code_collection_in_us();
-
-  if ((start - last_code_collection_in_us) >
-      FLAG_code_collection_interval_in_us) {
-    if (FLAG_log_code_drop) {
-      OS::PrintErr("Trying to detach code.\n");
-    }
-    page_space_controller_.set_last_code_collection_in_us(start);
-    return true;
-  }
-  return false;
-}
-
 void PageSpace::WriteProtectCode(bool read_only) {
   if (FLAG_write_protect_code) {
-    MutexLocker ml(pages_lock_);
+    MutexLocker ml(&pages_lock_);
     NoSafepointScope no_safepoint;
     // No need to go through all of the data pages first.
     HeapPage* page = exec_pages_;
@@ -1107,13 +1076,6 @@
   SpaceUsage usage_before = GetCurrentUsage();
 
   // Mark all reachable old-gen objects.
-#if defined(PRODUCT)
-  bool collect_code = FLAG_collect_code && ShouldCollectCode();
-#else
-  bool collect_code = FLAG_collect_code && ShouldCollectCode() &&
-                      !isolate->HasAttemptedReload();
-#endif  // !defined(PRODUCT)
-
   if (marker_ == NULL) {
     ASSERT(phase() == kDone);
     marker_ = new GCMarker(isolate, heap_);
@@ -1123,12 +1085,12 @@
 
   if (!finalize) {
     ASSERT(phase() == kDone);
-    marker_->StartConcurrentMark(this, collect_code);
+    marker_->StartConcurrentMark(this);
     return;
   }
 
   NOT_IN_PRODUCT(isolate->class_table()->ResetCountersOld());
-  marker_->MarkObjects(this, collect_code);
+  marker_->MarkObjects(this);
   usage_.used_in_words = marker_->marked_words() + allocated_black_in_words_;
   allocated_black_in_words_ = 0;
   mark_words_per_micro_ = marker_->MarkedWordsPerMicro();
@@ -1272,7 +1234,7 @@
 void PageSpace::Compact(Thread* thread) {
   thread->isolate()->set_compaction_in_progress(true);
   GCCompactor compactor(thread, heap_);
-  compactor.Compact(pages_, &freelist_[HeapPage::kData], pages_lock_);
+  compactor.Compact(pages_, &freelist_[HeapPage::kData], &pages_lock_);
   thread->isolate()->set_compaction_in_progress(false);
 
   if (FLAG_verify_after_gc) {
@@ -1366,7 +1328,7 @@
     page->type_ = HeapPage::kData;
   }
 
-  MutexLocker ml(pages_lock_);
+  MutexLocker ml(&pages_lock_);
   page->next_ = image_pages_;
   image_pages_ = page;
 }
@@ -1393,7 +1355,6 @@
       desired_utilization_((100.0 - heap_growth_ratio) / 100.0),
       heap_growth_max_(heap_growth_max),
       garbage_collection_time_ratio_(garbage_collection_time_ratio),
-      last_code_collection_in_us_(OS::GetCurrentMonotonicMicros()),
       idle_gc_threshold_in_words_(0) {
   intptr_t grow_heap = heap_growth_max / 2;
   gc_threshold_in_words_ =
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 8844ee7..6eb1e32 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -15,8 +15,6 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, log_code_drop);
-DECLARE_FLAG(bool, always_drop_code);
 DECLARE_FLAG(bool, write_protect_code);
 
 // Forward declarations.
@@ -227,11 +225,6 @@
                                  int64_t end);
   void EvaluateAfterLoading(SpaceUsage after);
 
-  int64_t last_code_collection_in_us() { return last_code_collection_in_us_; }
-  void set_last_code_collection_in_us(int64_t t) {
-    last_code_collection_in_us_ = t;
-  }
-
   void set_last_usage(SpaceUsage current) { last_usage_ = current; }
 
   void Enable() { is_enabled_ = true; }
@@ -261,10 +254,6 @@
   // we grow the heap more aggressively.
   const int garbage_collection_time_ratio_;
 
-  // The time in microseconds of the last time we tried to collect unused
-  // code.
-  int64_t last_code_collection_in_us_;
-
   // Perform a synchronous GC when capacity exceeds this amount.
   intptr_t gc_threshold_in_words_;
 
@@ -309,15 +298,15 @@
 
   int64_t UsedInWords() const { return usage_.used_in_words; }
   int64_t CapacityInWords() const {
-    MutexLocker ml(pages_lock_);
+    MutexLocker ml(&pages_lock_);
     return usage_.capacity_in_words;
   }
   void IncreaseCapacityInWords(intptr_t increase_in_words) {
-    MutexLocker ml(pages_lock_);
+    MutexLocker ml(&pages_lock_);
     IncreaseCapacityInWordsLocked(increase_in_words);
   }
   void IncreaseCapacityInWordsLocked(intptr_t increase_in_words) {
-    DEBUG_ASSERT(pages_lock_->IsOwnedByCurrentThread());
+    DEBUG_ASSERT(pages_lock_.IsOwnedByCurrentThread());
     usage_.capacity_in_words += increase_in_words;
     UpdateMaxCapacityLocked();
   }
@@ -327,7 +316,7 @@
 
   int64_t ExternalInWords() const { return usage_.external_in_words; }
   SpaceUsage GetCurrentUsage() const {
-    MutexLocker ml(pages_lock_);
+    MutexLocker ml(&pages_lock_);
     return usage_;
   }
 
@@ -346,10 +335,6 @@
   RawObject* FindObject(FindObjectVisitor* visitor,
                         HeapPage::PageType type) const;
 
-  // Checks if enough time has elapsed since the last attempt to collect
-  // code.
-  bool ShouldCollectCode();
-
   // Collect the garbage in the page space using mark-sweep or mark-compact.
   void CollectGarbage(bool compact, bool finalize);
 
@@ -414,7 +399,7 @@
                                is_protected, is_locked);
   }
 
-  Monitor* tasks_lock() const { return tasks_lock_; }
+  Monitor* tasks_lock() const { return &tasks_lock_; }
   intptr_t tasks() const { return tasks_; }
   void set_tasks(intptr_t val) {
     ASSERT(val >= 0);
@@ -510,7 +495,7 @@
   Heap* heap_;
 
   // Use ExclusivePageIterator for safe access to these.
-  Mutex* pages_lock_;
+  mutable Mutex pages_lock_;
   HeapPage* pages_;
   HeapPage* pages_tail_;
   HeapPage* exec_pages_;
@@ -532,7 +517,7 @@
   intptr_t allocated_black_in_words_;
 
   // Keep track of running MarkSweep tasks.
-  Monitor* tasks_lock_;
+  mutable Monitor tasks_lock_;
   intptr_t tasks_;
   intptr_t concurrent_marker_tasks_;
   Phase phase_;
diff --git a/runtime/vm/heap/pointer_block.cc b/runtime/vm/heap/pointer_block.cc
index 52b4563..19428f7 100644
--- a/runtime/vm/heap/pointer_block.cc
+++ b/runtime/vm/heap/pointer_block.cc
@@ -41,17 +41,16 @@
 }
 
 template <int BlockSize>
-BlockStack<BlockSize>::BlockStack() : mutex_(new Mutex()) {}
+BlockStack<BlockSize>::BlockStack() : mutex_() {}
 
 template <int BlockSize>
 BlockStack<BlockSize>::~BlockStack() {
   Reset();
-  delete mutex_;
 }
 
 template <int BlockSize>
 void BlockStack<BlockSize>::Reset() {
-  MutexLocker local_mutex_locker(mutex_);
+  MutexLocker local_mutex_locker(&mutex_);
   {
     // Empty all blocks and move them to the global cache.
     MutexLocker global_mutex_locker(global_mutex_);
@@ -71,7 +70,7 @@
 
 template <int BlockSize>
 typename BlockStack<BlockSize>::Block* BlockStack<BlockSize>::Blocks() {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   while (!partial_.IsEmpty()) {
     full_.Push(partial_.Pop());
   }
@@ -82,14 +81,14 @@
 void BlockStack<BlockSize>::PushBlockImpl(Block* block) {
   ASSERT(block->next() == NULL);  // Should be just a single block.
   if (block->IsFull()) {
-    MutexLocker ml(mutex_);
+    MutexLocker ml(&mutex_);
     full_.Push(block);
   } else if (block->IsEmpty()) {
     MutexLocker ml(global_mutex_);
     global_empty_->Push(block);
     TrimGlobalEmpty();
   } else {
-    MutexLocker ml(mutex_);
+    MutexLocker ml(&mutex_);
     partial_.Push(block);
   }
 }
@@ -104,7 +103,7 @@
 void StoreBuffer::PushBlock(Block* block, ThresholdPolicy policy) {
   BlockStack<Block::kSize>::PushBlockImpl(block);
   if ((policy == kCheckThreshold) && Overflowed()) {
-    MutexLocker ml(mutex_);
+    MutexLocker ml(&mutex_);
     Thread* thread = Thread::Current();
     // Sanity check: it makes no sense to schedule the GC in another isolate.
     // (If Isolate ever gets multiple store buffers, we should avoid this
@@ -118,7 +117,7 @@
 typename BlockStack<BlockSize>::Block*
 BlockStack<BlockSize>::PopNonFullBlock() {
   {
-    MutexLocker ml(mutex_);
+    MutexLocker ml(&mutex_);
     if (!partial_.IsEmpty()) {
       return partial_.Pop();
     }
@@ -140,7 +139,7 @@
 template <int BlockSize>
 typename BlockStack<BlockSize>::Block*
 BlockStack<BlockSize>::PopNonEmptyBlock() {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   if (!full_.IsEmpty()) {
     return full_.Pop();
   } else if (!partial_.IsEmpty()) {
@@ -152,7 +151,7 @@
 
 template <int BlockSize>
 bool BlockStack<BlockSize>::IsEmpty() {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   return full_.IsEmpty() && partial_.IsEmpty();
 }
 
@@ -189,7 +188,7 @@
 }
 
 bool StoreBuffer::Overflowed() {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   return (full_.length() + partial_.length()) > kMaxNonEmpty;
 }
 
diff --git a/runtime/vm/heap/pointer_block.h b/runtime/vm/heap/pointer_block.h
index 609ea97..e9ace07 100644
--- a/runtime/vm/heap/pointer_block.h
+++ b/runtime/vm/heap/pointer_block.h
@@ -7,12 +7,12 @@
 
 #include "platform/assert.h"
 #include "vm/globals.h"
+#include "vm/os_thread.h"
 
 namespace dart {
 
 // Forward declarations.
 class Isolate;
-class Mutex;
 class RawObject;
 class ObjectPointerVisitor;
 
@@ -131,7 +131,7 @@
 
   List full_;
   List partial_;
-  Mutex* mutex_;
+  Mutex mutex_;
 
   // Note: This is shared on the basis of block size.
   static const intptr_t kMaxGlobalEmpty = 100;
diff --git a/runtime/vm/heap/safepoint.cc b/runtime/vm/heap/safepoint.cc
index c231b9c..3888cdf 100644
--- a/runtime/vm/heap/safepoint.cc
+++ b/runtime/vm/heap/safepoint.cc
@@ -39,7 +39,7 @@
 
 SafepointHandler::SafepointHandler(Isolate* isolate)
     : isolate_(isolate),
-      safepoint_lock_(new Monitor()),
+      safepoint_lock_(),
       number_threads_not_at_safepoint_(0),
       safepoint_operation_count_(0),
       owner_(NULL) {}
@@ -47,8 +47,6 @@
 SafepointHandler::~SafepointHandler() {
   ASSERT(owner_ == NULL);
   ASSERT(safepoint_operation_count_ == 0);
-  delete safepoint_lock_;
-  safepoint_lock_ = NULL;
   isolate_ = NULL;
 }
 
@@ -96,7 +94,7 @@
               ASSERT(T->isolate() != NULL);
               current->ScheduleInterruptsLocked(Thread::kVMInterrupt);
             }
-            MonitorLocker sl(safepoint_lock_);
+            MonitorLocker sl(&safepoint_lock_);
             ++number_threads_not_at_safepoint_;
           }
         }
@@ -106,7 +104,7 @@
   }
   // Now wait for all threads that are not already at a safepoint to check-in.
   {
-    MonitorLocker sl(safepoint_lock_);
+    MonitorLocker sl(&safepoint_lock_);
     intptr_t num_attempts = 0;
     while (number_threads_not_at_safepoint_ > 0) {
       Monitor::WaitResult retval = sl.Wait(1000);
@@ -161,7 +159,7 @@
   MonitorLocker tl(T->thread_lock());
   T->SetAtSafepoint(true);
   if (T->IsSafepointRequested()) {
-    MonitorLocker sl(safepoint_lock_);
+    MonitorLocker sl(&safepoint_lock_);
     ASSERT(number_threads_not_at_safepoint_ > 0);
     number_threads_not_at_safepoint_ -= 1;
     sl.Notify();
@@ -185,7 +183,7 @@
   if (T->IsSafepointRequested()) {
     T->SetAtSafepoint(true);
     {
-      MonitorLocker sl(safepoint_lock_);
+      MonitorLocker sl(&safepoint_lock_);
       ASSERT(number_threads_not_at_safepoint_ > 0);
       number_threads_not_at_safepoint_ -= 1;
       sl.Notify();
diff --git a/runtime/vm/heap/safepoint.h b/runtime/vm/heap/safepoint.h
index ce84f85..906933a 100644
--- a/runtime/vm/heap/safepoint.h
+++ b/runtime/vm/heap/safepoint.h
@@ -78,7 +78,7 @@
 
   // Monitor used by thread initiating a safepoint operation to track threads
   // not at a safepoint and wait for these threads to reach a safepoint.
-  Monitor* safepoint_lock_;
+  Monitor safepoint_lock_;
   int32_t number_threads_not_at_safepoint_;
 
   // Count that indicates if a safepoint operation is currently in progress
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 34ede80..fe46279 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -7,6 +7,7 @@
 #include "platform/assert.h"
 #include "vm/compiler/backend/code_statistics.h"
 #include "vm/dwarf.h"
+#include "vm/elf.h"
 #include "vm/hash.h"
 #include "vm/hash_map.h"
 #include "vm/heap/heap.h"
@@ -106,7 +107,7 @@
           RawInstructions* instructions = Code::InstructionsOf(code);
           const intptr_t offset = next_text_offset_;
           instructions_.Add(InstructionsData(instructions, code, offset));
-          next_text_offset_ += instructions->HeapSize();
+          next_text_offset_ += SizeInSnapshot(instructions);
           ASSERT(heap_->GetObjectId(instructions) == 0);
           heap_->SetObjectId(instructions, offset);
           break;
@@ -141,7 +142,7 @@
     pair.object = raw_obj;
     pair.offset = offset;
     map->Insert(pair);
-    obj_addr += raw_obj->HeapSize();
+    obj_addr += SizeInSnapshot(raw_obj);
   }
   ASSERT(obj_addr == end_addr);
 }
@@ -174,13 +175,17 @@
 
   offset = next_text_offset_;
   heap_->SetObjectId(instructions, offset);
-  next_text_offset_ += instructions->HeapSize();
+  next_text_offset_ += SizeInSnapshot(instructions);
   instructions_.Add(InstructionsData(instructions, code, offset));
 
   ASSERT(offset != 0);
   return offset;
 }
 
+intptr_t ImageWriter::SizeInSnapshot(RawObject* raw_object) {
+  return raw_object->HeapSize();
+}
+
 bool ImageWriter::GetSharedDataOffsetFor(RawObject* raw_object,
                                          uint32_t* offset) {
   ObjectOffsetPair* pair = shared_objects_.Lookup(raw_object);
@@ -192,9 +197,9 @@
 }
 
 uint32_t ImageWriter::GetDataOffsetFor(RawObject* raw_object) {
-  intptr_t heap_size = raw_object->HeapSize();
+  intptr_t snap_size = SizeInSnapshot(raw_object);
   intptr_t offset = next_data_offset_;
-  next_data_offset_ += heap_size;
+  next_data_offset_ += snap_size;
   objects_.Add(ObjectData(raw_object));
   return offset;
 }
@@ -237,7 +242,7 @@
       js.PrintPropertyStr("c", name);
     }
     js.PrintProperty("n", data.code_->QualifiedName());
-    js.PrintProperty("s", data.insns_->raw()->HeapSize());
+    js.PrintProperty("s", SizeInSnapshot(data.insns_->raw()));
     js.CloseObject();
   }
   js.CloseArray();
@@ -359,10 +364,10 @@
                                          const void* shared_instructions)
     : ImageWriter(thread->heap(), shared_objects, shared_instructions, nullptr),
       assembly_stream_(512 * KB, callback, callback_data),
-      dwarf_(NULL) {
+      dwarf_(nullptr) {
 #if defined(DART_PRECOMPILER)
   Zone* zone = Thread::Current()->zone();
-  dwarf_ = new (zone) Dwarf(zone, &assembly_stream_);
+  dwarf_ = new (zone) Dwarf(zone, &assembly_stream_, /* elf= */ nullptr);
 #endif
 }
 
@@ -472,7 +477,7 @@
                                             "Instructions",
                                             /*name=*/nullptr);
       profile_writer_->AttributeBytesTo({offset_space_, offset},
-                                        insns.raw()->HeapSize());
+                                        SizeInSnapshot(insns.raw()));
     }
 
     ASSERT(insns.raw()->HeapSize() % sizeof(uint64_t) == 0);
@@ -539,7 +544,7 @@
 
 #ifdef DART_PRECOMPILER
     // Create a label for use by DWARF.
-    if (!code.IsNull()) {
+    if ((dwarf_ != nullptr) && !code.IsNull()) {
       const intptr_t dwarf_index = dwarf_->AddCode(code);
       assembly_stream_.Print(".Lcode%" Pd ":\n", dwarf_index);
     }
@@ -676,12 +681,20 @@
                                  intptr_t initial_size,
                                  const void* shared_objects,
                                  const void* shared_instructions,
-                                 const void* reused_instructions)
+                                 const void* reused_instructions,
+                                 Elf* elf,
+                                 Dwarf* dwarf)
     : ImageWriter(thread->heap(),
                   shared_objects,
                   shared_instructions,
                   reused_instructions),
-      instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size) {
+      instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size),
+      elf_(elf),
+      dwarf_(dwarf) {
+#ifndef DART_PRECOMPILER
+  RELEASE_ASSERT(elf_ == nullptr);
+  RELEASE_ASSERT(dwarf_ == nullptr);
+#endif
 }
 
 intptr_t BlobImageWriter::WriteByteSequence(uword start, uword end) {
@@ -693,6 +706,13 @@
 }
 
 void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
+#ifdef DART_PRECOMPILER
+  intptr_t segment_base = 0;
+  if (elf_ != nullptr) {
+    segment_base = elf_->NextMemoryOffset();
+  }
+#endif
+
   // This header provides the gap to make the instructions snapshot look like a
   // HeapPage.
   intptr_t instructions_length = next_text_offset_;
@@ -733,6 +753,15 @@
     ASSERT(Utils::IsAligned(beginning, sizeof(uword)));
     ASSERT(Utils::IsAligned(entry, sizeof(uword)));
 
+#ifdef DART_PRECOMPILER
+    const Code& code = *instructions_[i].code_;
+    if ((elf_ != nullptr) && (dwarf_ != nullptr) && !code.IsNull()) {
+      intptr_t segment_offset = instructions_blob_stream_.bytes_written() +
+                                Instructions::HeaderSize();
+      dwarf_->AddCode(code, segment_base + segment_offset);
+    }
+#endif
+
     // Write Instructions with the mark and read-only bits set.
     uword marked_tags = insns.raw_ptr()->tags_;
     marked_tags = RawObject::OldBit::update(true, marked_tags);
@@ -750,8 +779,20 @@
     beginning += sizeof(uword);
     text_offset += WriteByteSequence(beginning, end);
 
-    ASSERT((text_offset - instr_start) == insns.raw()->HeapSize());
+    ASSERT((text_offset - instr_start) ==
+           ImageWriter::SizeInSnapshot(insns.raw()));
   }
+
+#ifdef DART_PRECOMPILER
+  if (elf_ != nullptr) {
+    const char* instructions_symbol = vm ? "_kDartVmSnapshotInstructions"
+                                         : "_kDartIsolateSnapshotInstructions";
+    intptr_t segment_base2 =
+        elf_->AddText(instructions_symbol, instructions_blob_stream_.buffer(),
+                      instructions_blob_stream_.bytes_written());
+    ASSERT(segment_base == segment_base2);
+  }
+#endif
 }
 
 ImageReader::ImageReader(const uint8_t* data_image,
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 1bc4260..f59d946 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -23,6 +23,7 @@
 // Forward declarations.
 class Code;
 class Dwarf;
+class Elf;
 class Instructions;
 class Object;
 class RawApiError;
@@ -180,6 +181,8 @@
 
   void TraceInstructions(const Instructions& instructions);
 
+  static intptr_t SizeInSnapshot(RawObject* object);
+
  protected:
   void WriteROData(WriteStream* stream);
   virtual void WriteText(WriteStream* clustered_stream, bool vm) = 0;
@@ -333,7 +336,9 @@
                   intptr_t initial_size,
                   const void* shared_objects,
                   const void* shared_instructions,
-                  const void* reused_instructions);
+                  const void* reused_instructions,
+                  Elf* elf = nullptr,
+                  Dwarf* dwarf = nullptr);
 
   virtual void WriteText(WriteStream* clustered_stream, bool vm);
 
@@ -345,6 +350,8 @@
   intptr_t WriteByteSequence(uword start, uword end);
 
   WriteStream instructions_blob_stream_;
+  Elf* elf_;
+  Dwarf* dwarf_;
 
   DISALLOW_COPY_AND_ASSIGN(BlobImageWriter);
 };
diff --git a/runtime/vm/instructions_arm64.cc b/runtime/vm/instructions_arm64.cc
index d34d7a7..cc29bcd 100644
--- a/runtime/vm/instructions_arm64.cc
+++ b/runtime/vm/instructions_arm64.cc
@@ -390,8 +390,8 @@
 SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code)
     : SwitchableCallPatternBase(code) {
   ASSERT(code.ContainsInstructionAt(pc));
-  // Last instruction: blr ip0.
-  ASSERT(*(reinterpret_cast<uint32_t*>(pc) - 1) == 0xd63f0200);
+  // Last instruction: blr lr.
+  ASSERT(*(reinterpret_cast<uint32_t*>(pc) - 1) == 0xd63f03c0);
 
   Register ic_data_reg, code_reg;
   intptr_t pool_index;
@@ -416,15 +416,15 @@
 BareSwitchableCallPattern::BareSwitchableCallPattern(uword pc, const Code& code)
     : SwitchableCallPatternBase(code) {
   ASSERT(code.ContainsInstructionAt(pc));
-  // Last instruction: blr ip0.
-  ASSERT(*(reinterpret_cast<uint32_t*>(pc) - 1) == 0xd63f0200);
+  // Last instruction: blr lr.
+  ASSERT(*(reinterpret_cast<uint32_t*>(pc) - 1) == 0xd63f03c0);
 
   Register ic_data_reg, code_reg;
   intptr_t pool_index;
   InstructionPattern::DecodeLoadDoubleWordFromPool(
       pc - Instr::kInstrSize, &ic_data_reg, &code_reg, &pool_index);
   ASSERT(ic_data_reg == R5);
-  ASSERT(code_reg == TMP);
+  ASSERT(code_reg == LR);
 
   data_pool_index_ = pool_index;
   target_pool_index_ = pool_index + 1;
@@ -512,10 +512,9 @@
   const uint32_t adr_mask = (3 << 29) | (((1 << 19) - 1) << 5);
   const uint32_t movz_mask = 0xffff << 5;
   uint32_t* pattern = reinterpret_cast<uint32_t*>(pattern_start_);
-  return (pattern[0] & ~adr_mask) == kAdrEncoding &
-             (pattern[1] & ~movz_mask) == kMovzEncoding &
-             pattern[2] == kAddTmpTmp2 &&
-         pattern[3] == kJumpEncoding;
+  return ((pattern[0] & ~adr_mask) == kAdrEncoding) &&
+         ((pattern[1] & ~movz_mask) == kMovzEncoding) &&
+         (pattern[2] == kAddTmpTmp2) && (pattern[3] == kJumpEncoding);
 #else
   UNREACHABLE();
   return false;
diff --git a/runtime/vm/instructions_kbc.cc b/runtime/vm/instructions_kbc.cc
index f6d9f61..a8a3608 100644
--- a/runtime/vm/instructions_kbc.cc
+++ b/runtime/vm/instructions_kbc.cc
@@ -17,11 +17,22 @@
     uword pc,
     const Bytecode& bytecode) {
   ASSERT(bytecode.ContainsInstructionAt(pc));
-  const uword call_pc = pc - sizeof(KBCInstr);
-  KBCInstr call_instr = KernelBytecode::At(call_pc);
-  ASSERT(KernelBytecode::DecodeOpcode(call_instr) ==
-         KernelBytecode::kNativeCall);
-  intptr_t native_entry_data_pool_index = KernelBytecode::DecodeD(call_instr);
+
+  const KBCInstr* return_addr = reinterpret_cast<const KBCInstr*>(pc);
+  const KBCInstr* instr =
+      reinterpret_cast<const KBCInstr*>(bytecode.PayloadStart());
+  ASSERT(instr < return_addr);
+  while (!KernelBytecode::IsNativeCallOpcode(instr)) {
+    instr = KernelBytecode::Next(instr);
+    if (instr >= return_addr) {
+      FATAL1(
+          "Unable to find NativeCall bytecode instruction"
+          " corresponding to PC %" Px,
+          pc);
+    }
+  }
+
+  intptr_t native_entry_data_pool_index = KernelBytecode::DecodeD(instr);
   const ObjectPool& obj_pool = ObjectPool::Handle(bytecode.object_pool());
   TypedData& native_entry_data = TypedData::Handle();
   native_entry_data ^= obj_pool.ObjectAt(native_entry_data_pool_index);
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index c72f6b0..3d9597e 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -12,6 +12,7 @@
 
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/assembler/disassembler_kbc.h"
+#include "vm/compiler/frontend/bytecode_reader.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/cpu.h"
 #include "vm/dart_entry.h"
@@ -229,8 +230,8 @@
   }
 };
 
-DART_FORCE_INLINE static uint32_t* SavedCallerPC(RawObject** FP) {
-  return reinterpret_cast<uint32_t*>(FP[kKBCSavedCallerPcSlotFromFp]);
+DART_FORCE_INLINE static const KBCInstr* SavedCallerPC(RawObject** FP) {
+  return reinterpret_cast<const KBCInstr*>(FP[kKBCSavedCallerPcSlotFromFp]);
 }
 
 DART_FORCE_INLINE static RawFunction* FrameFunction(RawObject** FP) {
@@ -380,7 +381,7 @@
 Interpreter* Interpreter::Current() {
   Thread* thread = Thread::Current();
   Interpreter* interpreter = thread->interpreter();
-  if (interpreter == NULL) {
+  if (interpreter == nullptr) {
     TransitionGeneratedToVM transition(thread);
     interpreter = new Interpreter();
     Thread::Current()->set_interpreter(interpreter);
@@ -396,11 +397,12 @@
 }
 
 // Prints bytecode instruction at given pc for instruction tracing.
-DART_NOINLINE void Interpreter::TraceInstruction(uint32_t* pc) const {
+DART_NOINLINE void Interpreter::TraceInstruction(const KBCInstr* pc) const {
   THR_Print("%" Pu64 " ", icount_);
   if (FLAG_support_disassembler) {
-    KernelBytecodeDisassembler::Disassemble(reinterpret_cast<uword>(pc),
-                                            reinterpret_cast<uword>(pc + 1));
+    KernelBytecodeDisassembler::Disassemble(
+        reinterpret_cast<uword>(pc),
+        reinterpret_cast<uword>(KernelBytecode::Next(pc)));
   } else {
     THR_Print("Disassembler not supported in this mode.\n");
   }
@@ -430,13 +432,15 @@
   trace_buffer_idx_ = 0;
 }
 
-DART_NOINLINE void Interpreter::WriteInstructionToTrace(uint32_t* pc) {
+DART_NOINLINE void Interpreter::WriteInstructionToTrace(const KBCInstr* pc) {
   Dart_FileWriteCallback file_write = Dart::file_write_callback();
   if (file_write == NULL) {
     return;
   }
-  if (trace_buffer_idx_ < kTraceBufferInstrs) {
-    trace_buffer_[trace_buffer_idx_++] = static_cast<KBCInstr>(*pc);
+  const KBCInstr* next = KernelBytecode::Next(pc);
+  while ((trace_buffer_idx_ < kTraceBufferInstrs) && (pc != next)) {
+    trace_buffer_[trace_buffer_idx_++] = *pc;
+    ++pc;
   }
   if (trace_buffer_idx_ == kTraceBufferInstrs) {
     FlushTraceBuffer();
@@ -460,10 +464,10 @@
 void Interpreter::Exit(Thread* thread,
                        RawObject** base,
                        RawObject** frame,
-                       uint32_t* pc) {
+                       const KBCInstr* pc) {
   frame[0] = Function::null();
   frame[1] = Bytecode::null();
-  frame[2] = reinterpret_cast<RawObject*>(pc);
+  frame[2] = reinterpret_cast<RawObject*>(reinterpret_cast<uword>(pc));
   frame[3] = reinterpret_cast<RawObject*>(base);
 
   RawObject** exit_fp = frame + kKBCDartFrameFixedSize;
@@ -534,7 +538,7 @@
                                                RawFunction* function,
                                                RawObject** call_base,
                                                RawObject** call_top,
-                                               uint32_t** pc,
+                                               const KBCInstr** pc,
                                                RawObject*** FP,
                                                RawObject*** SP) {
   ASSERT(Function::HasCode(function));
@@ -615,221 +619,14 @@
   return true;
 }
 
-DART_NOINLINE bool Interpreter::ProcessInvocation(bool* invoked,
-                                                  Thread* thread,
-                                                  RawFunction* function,
-                                                  RawObject** call_base,
-                                                  RawObject** call_top,
-                                                  uint32_t** pc,
-                                                  RawObject*** FP,
-                                                  RawObject*** SP) {
-  ASSERT(!Function::HasCode(function) && !Function::HasBytecode(function));
-  ASSERT(function == call_top[0]);
-  RawFunction::Kind kind = Function::kind(function);
-  switch (kind) {
-    case RawFunction::kImplicitStaticFinalGetter: {
-      // Field object is cached in function's data_.
-      RawField* field = reinterpret_cast<RawField*>(function->ptr()->data_);
-      RawInstance* value = field->ptr()->value_.static_value_;
-      if (value == Object::sentinel().raw() ||
-          value == Object::transition_sentinel().raw()) {
-        call_top[1] = 0;  // Unused result of invoking the initializer.
-        call_top[2] = field;
-        Exit(thread, *FP, call_top + 3, *pc);
-        NativeArguments native_args(thread, 1, call_top + 2, call_top + 1);
-        if (!InvokeRuntime(thread, this, DRT_InitStaticField, native_args)) {
-          *invoked = true;
-          return false;
-        }
-        // Reload objects after the call which may trigger GC.
-        function = reinterpret_cast<RawFunction*>(call_top[0]);
-        field = reinterpret_cast<RawField*>(function->ptr()->data_);
-        pp_ = InterpreterHelpers::FrameBytecode(*FP)->ptr()->object_pool_;
-        // The field is initialized by the runtime call, but not returned.
-        value = field->ptr()->value_.static_value_;
-      }
-      // Field was initialized. Return its value.
-      *SP = call_base;
-      **SP = value;
-      *invoked = true;
-      return true;
-    }
-    case RawFunction::kInvokeFieldDispatcher: {
-      const intptr_t type_args_len =
-          InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
-      const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
-      RawObject* receiver = call_base[receiver_idx];
-      RawObject** callee_fp = call_top + kKBCDartFrameFixedSize;
-      ASSERT(function == FrameFunction(callee_fp));
-      RawFunction* call_function = Function::null();
-      if (function->ptr()->name_ == Symbols::Call().raw()) {
-        RawObject* owner = function->ptr()->owner_;
-        if (owner->GetClassId() == kPatchClassCid) {
-          owner = PatchClass::RawCast(owner)->ptr()->patched_class_;
-        }
-        if (owner == thread->isolate()->object_store()->closure_class()) {
-          // Closure call.
-          call_function = Closure::RawCast(receiver)->ptr()->function_;
-        }
-      }
-      if (call_function == Function::null()) {
-        // Invoke field getter on receiver.
-        call_top[1] = argdesc_;                // Save argdesc_.
-        call_top[2] = 0;                       // Result of runtime call.
-        call_top[3] = receiver;                // Receiver.
-        call_top[4] = function->ptr()->name_;  // Field name.
-        Exit(thread, *FP, call_top + 5, *pc);
-        NativeArguments native_args(thread, 2, call_top + 3, call_top + 2);
-        if (!InvokeRuntime(thread, this, DRT_GetFieldForDispatch,
-                           native_args)) {
-          return false;
-        }
-        argdesc_ = Array::RawCast(call_top[1]);
-
-        // Replace receiver with field value, keep all other arguments, and
-        // invoke 'call' function, or if not found, invoke noSuchMethod.
-        receiver = call_top[2];
-        call_base[receiver_idx] = receiver;
-
-        // If the field value is a closure, no need to resolve 'call' function.
-        // Otherwise, call runtime to resolve 'call' function.
-        if (InterpreterHelpers::GetClassId(receiver) == kClosureCid) {
-          // Closure call.
-          call_function = Closure::RawCast(receiver)->ptr()->function_;
-        } else {
-          // Resolve and invoke the 'call' function.
-          call_top[3] = argdesc_;
-          call_top[4] = 0;  // Result of runtime call.
-          Exit(thread, *FP, call_top + 5, *pc);
-          NativeArguments native_args(thread, 2, call_top + 2, call_top + 4);
-          if (!InvokeRuntime(thread, this, DRT_ResolveCallFunction,
-                             native_args)) {
-            return false;
-          }
-          argdesc_ = Array::RawCast(call_top[1]);
-          call_function = Function::RawCast(call_top[4]);
-          if (call_function == Function::null()) {
-            // Function 'call' could not be resolved for argdesc_.
-            // Invoke noSuchMethod.
-            const intptr_t argc =
-                receiver_idx + InterpreterHelpers::ArgDescArgCount(argdesc_);
-            RawObject* null_value = Object::null();
-            call_top[1] = null_value;
-            call_top[2] = call_base[receiver_idx];
-            call_top[3] = argdesc_;
-            call_top[4] = null_value;  // Array of arguments (will be filled).
-
-            // Allocate array of arguments.
-            {
-              call_top[5] = Smi::New(argc);  // length
-              call_top[6] = null_value;      // type
-              Exit(thread, *FP, call_top + 7, *pc);
-              NativeArguments native_args(thread, 2, call_top + 5,
-                                          call_top + 4);
-              if (!InvokeRuntime(thread, this, DRT_AllocateArray,
-                                 native_args)) {
-                return false;
-              }
-
-              // Copy arguments into the newly allocated array.
-              RawArray* array = static_cast<RawArray*>(call_top[4]);
-              ASSERT(array->GetClassId() == kArrayCid);
-              for (intptr_t i = 0; i < argc; i++) {
-                array->ptr()->data()[i] = call_base[i];
-              }
-            }
-
-            // We failed to resolve 'call' function.
-            call_top[5] = Symbols::Call().raw();
-
-            // Invoke noSuchMethod passing down receiver, argument descriptor,
-            // array of arguments, and target name.
-            {
-              Exit(thread, *FP, call_top + 6, *pc);
-              NativeArguments native_args(thread, 4, call_top + 2,
-                                          call_top + 1);
-              if (!InvokeRuntime(thread, this, DRT_InvokeNoSuchMethod,
-                                 native_args)) {
-                return false;
-              }
-            }
-            *SP = call_base;
-            **SP = call_top[1];
-            *invoked = true;
-            return true;
-          }
-        }
-      }
-      ASSERT(call_function != Function::null());
-      // Patch field dispatcher in callee frame with call function.
-      callee_fp[kKBCFunctionSlotFromFp] = call_function;
-      // Do not compile function if it has code or bytecode.
-      if (Function::HasCode(call_function)) {
-        *invoked = true;
-        return InvokeCompiled(thread, call_function, call_base, call_top, pc,
-                              FP, SP);
-      }
-      if (Function::HasBytecode(call_function)) {
-        *invoked = false;
-        return true;
-      }
-      function = call_function;
-      break;  // Compile and invoke the function.
-    }
-    case RawFunction::kNoSuchMethodDispatcher:
-      // TODO(regis): Implement. For now, use jitted version.
-      break;
-    case RawFunction::kDynamicInvocationForwarder:
-      // TODO(regis): Implement. For now, use jitted version.
-      break;
-    default:
-      break;
-  }
-  // Compile the function to either generate code or load bytecode.
-  call_top[1] = 0;  // Code result.
-  call_top[2] = function;
-  Exit(thread, *FP, call_top + 3, *pc);
-  NativeArguments native_args(thread, 1, call_top + 2, call_top + 1);
-  if (!InvokeRuntime(thread, this, DRT_CompileFunction, native_args)) {
-    return false;
-  }
-  // Reload objects after the call which may trigger GC.
-  function = Function::RawCast(call_top[2]);
-  if (Function::HasCode(function)) {
-    *invoked = true;
-    return InvokeCompiled(thread, function, call_base, call_top, pc, FP, SP);
-  }
+DART_FORCE_INLINE bool Interpreter::InvokeBytecode(Thread* thread,
+                                                   RawFunction* function,
+                                                   RawObject** call_base,
+                                                   RawObject** call_top,
+                                                   const KBCInstr** pc,
+                                                   RawObject*** FP,
+                                                   RawObject*** SP) {
   ASSERT(Function::HasBytecode(function));
-  // Bytecode was loaded in the above compilation step.
-  // The caller will dispatch to the function's bytecode.
-  *invoked = false;
-  ASSERT(thread->vm_tag() == VMTag::kDartInterpretedTagId);
-  ASSERT(thread->top_exit_frame_info() == 0);
-  return true;
-}
-
-DART_FORCE_INLINE bool Interpreter::Invoke(Thread* thread,
-                                           RawObject** call_base,
-                                           RawObject** call_top,
-                                           uint32_t** pc,
-                                           RawObject*** FP,
-                                           RawObject*** SP) {
-  RawObject** callee_fp = call_top + kKBCDartFrameFixedSize;
-
-  RawFunction* function = FrameFunction(callee_fp);
-  if (Function::HasCode(function)) {
-    return InvokeCompiled(thread, function, call_base, call_top, pc, FP, SP);
-  }
-  if (!Function::HasBytecode(function)) {
-    bool invoked = false;
-    bool result = ProcessInvocation(&invoked, thread, function, call_base,
-                                    call_top, pc, FP, SP);
-    if (invoked || !result) {
-      return result;
-    }
-    function = FrameFunction(callee_fp);  // Function may have been patched.
-    ASSERT(Function::HasBytecode(function));
-  }
 #if defined(DEBUG)
   if (IsTracingExecution()) {
     THR_Print("%" Pu64 " ", icount_);
@@ -837,12 +634,15 @@
               Function::Handle(function).ToFullyQualifiedCString());
   }
 #endif
+  RawObject** callee_fp = call_top + kKBCDartFrameFixedSize;
+  ASSERT(function == FrameFunction(callee_fp));
   RawBytecode* bytecode = function->ptr()->bytecode_;
   callee_fp[kKBCPcMarkerSlotFromFp] = bytecode;
-  callee_fp[kKBCSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>(*pc);
+  callee_fp[kKBCSavedCallerPcSlotFromFp] =
+      reinterpret_cast<RawObject*>(reinterpret_cast<uword>(*pc));
   callee_fp[kKBCSavedCallerFpSlotFromFp] = reinterpret_cast<RawObject*>(*FP);
   pp_ = bytecode->ptr()->object_pool_;
-  *pc = reinterpret_cast<uint32_t*>(bytecode->ptr()->instructions_);
+  *pc = reinterpret_cast<const KBCInstr*>(bytecode->ptr()->instructions_);
   NOT_IN_PRODUCT(pc_ = *pc);  // For the profiler.
   *FP = callee_fp;
   NOT_IN_PRODUCT(fp_ = callee_fp);  // For the profiler.
@@ -850,12 +650,44 @@
   return true;
 }
 
+DART_FORCE_INLINE bool Interpreter::Invoke(Thread* thread,
+                                           RawObject** call_base,
+                                           RawObject** call_top,
+                                           const KBCInstr** pc,
+                                           RawObject*** FP,
+                                           RawObject*** SP) {
+  RawObject** callee_fp = call_top + kKBCDartFrameFixedSize;
+  RawFunction* function = FrameFunction(callee_fp);
+
+  for (;;) {
+    if (Function::HasCode(function)) {
+      return InvokeCompiled(thread, function, call_base, call_top, pc, FP, SP);
+    }
+    if (Function::HasBytecode(function)) {
+      return InvokeBytecode(thread, function, call_base, call_top, pc, FP, SP);
+    }
+
+    // Compile the function to either generate code or load bytecode.
+    call_top[1] = 0;  // Code result.
+    call_top[2] = function;
+    Exit(thread, *FP, call_top + 3, *pc);
+    NativeArguments native_args(thread, 1, call_top + 2, call_top + 1);
+    if (!InvokeRuntime(thread, this, DRT_CompileFunction, native_args)) {
+      return false;
+    }
+    // Reload objects after the call which may trigger GC.
+    function = Function::RawCast(call_top[2]);
+
+    ASSERT(Function::HasCode(function) || Function::HasBytecode(function));
+  }
+}
+
 void Interpreter::InlineCacheMiss(int checked_args,
                                   Thread* thread,
                                   RawICData* icdata,
                                   RawObject** args,
                                   RawObject** top,
-                                  uint32_t* pc,
+                                  const KBCInstr* pc,
                                   RawObject** FP,
                                   RawObject** SP) {
   RawObject** result = top;
@@ -898,7 +730,7 @@
                                                   RawString* target_name,
                                                   RawObject** call_base,
                                                   RawObject** top,
-                                                  uint32_t** pc,
+                                                  const KBCInstr** pc,
                                                   RawObject*** FP,
                                                   RawObject*** SP) {
   const intptr_t type_args_len =
@@ -911,6 +743,7 @@
   RawFunction* target;
   if (UNLIKELY(!lookup_cache_.Lookup(receiver_cid, target_name, &target))) {
     // Table lookup miss.
+    top[0] = 0;  // Clean up slot as it may be visited by GC.
     top[1] = call_base[receiver_idx];
     top[2] = target_name;
     top[3] = argdesc_;
@@ -939,7 +772,7 @@
                                                   RawICData* icdata,
                                                   RawObject** call_base,
                                                   RawObject** top,
-                                                  uint32_t** pc,
+                                                  const KBCInstr** pc,
                                                   RawObject*** FP,
                                                   RawObject*** SP,
                                                   bool optimized) {
@@ -960,7 +793,7 @@
   intptr_t i;
   for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
     if (cache->data()[i + 0] == receiver_cid) {
-      top[0] = cache->data()[i + kCheckedArgs];
+      top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)];
       found = true;
       break;
     }
@@ -984,7 +817,7 @@
                                                   RawICData* icdata,
                                                   RawObject** call_base,
                                                   RawObject** top,
-                                                  uint32_t** pc,
+                                                  const KBCInstr** pc,
                                                   RawObject*** FP,
                                                   RawObject*** SP,
                                                   bool optimized) {
@@ -1008,7 +841,7 @@
   for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
     if ((cache->data()[i + 0] == receiver_cid) &&
         (cache->data()[i + 1] == arg0_cid)) {
-      top[0] = cache->data()[i + kCheckedArgs];
+      top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)];
       found = true;
       break;
     }
@@ -1035,10 +868,10 @@
 #if defined(DEBUG)
 #define TRACE_INSTRUCTION                                                      \
   if (IsTracingExecution()) {                                                  \
-    TraceInstruction(pc - 1);                                                  \
+    TraceInstruction(pc);                                                      \
   }                                                                            \
   if (IsWritingTraceFile()) {                                                  \
-    WriteInstructionToTrace(pc - 1);                                           \
+    WriteInstructionToTrace(pc);                                               \
   }                                                                            \
   icount_++;
 #else
@@ -1051,71 +884,207 @@
 #define DISPATCH_OP(val)                                                       \
   do {                                                                         \
     op = (val);                                                                \
-    rA = ((op >> 8) & 0xFF);                                                   \
     TRACE_INSTRUCTION                                                          \
-    goto* dispatch[op & 0xFF];                                                 \
+    goto* dispatch[op];                                                        \
   } while (0)
 #else
 #define DISPATCH_OP(val)                                                       \
   do {                                                                         \
     op = (val);                                                                \
-    rA = ((op >> 8) & 0xFF);                                                   \
     TRACE_INSTRUCTION                                                          \
     goto SwitchDispatch;                                                       \
   } while (0)
 #endif
 
-// Fetch next operation from PC, increment program counter and dispatch.
-#define DISPATCH() DISPATCH_OP(*pc++)
+// Fetch next operation from PC and dispatch.
+#define DISPATCH() DISPATCH_OP(*pc)
 
 // Load target of a jump instruction into PC.
-#define LOAD_JUMP_TARGET() pc += ((static_cast<int32_t>(op) >> 8) - 1)
+#define LOAD_JUMP_TARGET() pc = rT
+
+#define BYTECODE_ENTRY_LABEL(Name) bc##Name:
+#define BYTECODE_WIDE_ENTRY_LABEL(Name) bc##Name##_Wide:
+#define BYTECODE_OLD_ENTRY_LABEL(Name) bc##Name##_Old:
+#define BYTECODE_IMPL_LABEL(Name) bc##Name##Impl:
+#define GOTO_BYTECODE_IMPL(Name) goto bc##Name##Impl;
 
 // Define entry point that handles bytecode Name with the given operand format.
-#define BYTECODE(Name, Operands)                                               \
-  BYTECODE_HEADER(Name, DECLARE_##Operands, DECODE_##Operands)
+#define BYTECODE(Name, Operands) BYTECODE_HEADER_##Operands##_WITH_OLD(Name)
 
-#define BYTECODE_HEADER(Name, Declare, Decode)                                 \
-  Declare;                                                                     \
-  bc##Name : Decode
+// TODO(alexmarkov): switch BYTECODE macro to BYTECODE_NEW implementation
+// and replace BYTECODE_NEW with BYTECODE when old instructions are gone.
+// Cleanup BYTECODE_HEADER_*_WITH_OLD macros and drop _WITH_OLD.
+static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 7,
+              "Cleanup support for old bytecode format versions");
+
+#define BYTECODE_NEW(Name, Operands) BYTECODE_HEADER_##Operands(Name)
 
 // Helpers to decode common instruction formats. Used in conjunction with
 // BYTECODE() macro.
-#define DECLARE_A_B_C                                                          \
-  uint16_t rB, rC;                                                             \
-  USE(rB);                                                                     \
-  USE(rC)
-#define DECODE_A_B_C                                                           \
-  rB = ((op >> KernelBytecode::kBShift) & KernelBytecode::kBMask);             \
-  rC = ((op >> KernelBytecode::kCShift) & KernelBytecode::kCMask);
 
-#define DECLARE_A_B_Y                                                          \
-  uint16_t rB;                                                                 \
-  int8_t rY;                                                                   \
-  USE(rB);                                                                     \
-  USE(rY)
-#define DECODE_A_B_Y                                                           \
-  rB = ((op >> KernelBytecode::kBShift) & KernelBytecode::kBMask);             \
-  rY = ((op >> KernelBytecode::kYShift) & KernelBytecode::kYMask);
+#define BYTECODE_HEADER_0(Name)                                                \
+  BYTECODE_ENTRY_LABEL(Name)                                                   \
+  pc += 1;
 
-#define DECLARE_0
-#define DECODE_0
+#define BYTECODE_HEADER_0_WITH_OLD(Name)                                       \
+  BYTECODE_OLD_ENTRY_LABEL(Name)                                               \
+  pc += 4;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_HEADER_0(Name)                                                      \
+  BYTECODE_IMPL_LABEL(Name)
 
-#define DECLARE_A
-#define DECODE_A
+#define BYTECODE_HEADER_A_WITH_OLD(Name)                                       \
+  uint32_t rA;                                                                 \
+  USE(rA);                                                                     \
+  BYTECODE_OLD_ENTRY_LABEL(Name)                                               \
+  rA = pc[1];                                                                  \
+  pc += 4;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_ENTRY_LABEL(Name)                                                   \
+  rA = pc[1];                                                                  \
+  pc += 2;                                                                     \
+  BYTECODE_IMPL_LABEL(Name)
 
-#define DECLARE___D                                                            \
+#define BYTECODE_HEADER_D_WITH_OLD(Name)                                       \
   uint32_t rD;                                                                 \
-  USE(rD)
-#define DECODE___D rD = (op >> KernelBytecode::kDShift);
+  USE(rD);                                                                     \
+  BYTECODE_OLD_ENTRY_LABEL(Name)                                               \
+  rD = static_cast<uint32_t>(pc[2]) | (static_cast<uint32_t>(pc[3]) << 8);     \
+  pc += 4;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_WIDE_ENTRY_LABEL(Name)                                              \
+  rD = static_cast<uint32_t>(pc[1]) | (static_cast<uint32_t>(pc[2]) << 8) |    \
+       (static_cast<uint32_t>(pc[3]) << 16) |                                  \
+       (static_cast<uint32_t>(pc[4]) << 24);                                   \
+  pc += 5;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_ENTRY_LABEL(Name)                                                   \
+  rD = pc[1];                                                                  \
+  pc += 2;                                                                     \
+  BYTECODE_IMPL_LABEL(Name)
 
-#define DECLARE_A_D DECLARE___D
-#define DECODE_A_D DECODE___D
+#define BYTECODE_HEADER_X_WITH_OLD(Name)                                       \
+  int32_t rX;                                                                  \
+  USE(rX);                                                                     \
+  BYTECODE_OLD_ENTRY_LABEL(Name)                                               \
+  rX = static_cast<int16_t>(static_cast<uint16_t>(pc[2]) |                     \
+                            (static_cast<uint16_t>(pc[3]) << 8));              \
+  pc += 4;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_WIDE_ENTRY_LABEL(Name)                                              \
+  rX = static_cast<int32_t>(static_cast<uint32_t>(pc[1]) |                     \
+                            (static_cast<uint32_t>(pc[2]) << 8) |              \
+                            (static_cast<uint32_t>(pc[3]) << 16) |             \
+                            (static_cast<uint32_t>(pc[4]) << 24));             \
+  pc += 5;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_ENTRY_LABEL(Name)                                                   \
+  rX = static_cast<int8_t>(pc[1]);                                             \
+  pc += 2;                                                                     \
+  BYTECODE_IMPL_LABEL(Name)
 
-#define DECLARE_A_X                                                            \
-  int32_t rD;                                                                  \
-  USE(rD)
-#define DECODE_A_X rD = (static_cast<int32_t>(op) >> KernelBytecode::kDShift);
+#define BYTECODE_HEADER_T_WITH_OLD(Name)                                       \
+  const KBCInstr* rT;                                                          \
+  USE(rT);                                                                     \
+  BYTECODE_OLD_ENTRY_LABEL(Name)                                               \
+  rT = pc + (static_cast<int32_t>((static_cast<uint32_t>(pc[1]) << 8) |        \
+                                  (static_cast<uint32_t>(pc[2]) << 16) |       \
+                                  (static_cast<uint32_t>(pc[3]) << 24)) >>     \
+             (8 - 2));                                                         \
+  pc += 4;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_WIDE_ENTRY_LABEL(Name)                                              \
+  rT = pc + (static_cast<int32_t>((static_cast<uint32_t>(pc[1]) << 8) |        \
+                                  (static_cast<uint32_t>(pc[2]) << 16) |       \
+                                  (static_cast<uint32_t>(pc[3]) << 24)) >>     \
+             8);                                                               \
+  pc += 4;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_ENTRY_LABEL(Name)                                                   \
+  rT = pc + static_cast<int8_t>(pc[1]);                                        \
+  pc += 2;                                                                     \
+  BYTECODE_IMPL_LABEL(Name)
+
+#define BYTECODE_HEADER_A_E_WITH_OLD(Name)                                     \
+  uint32_t rA, rE;                                                             \
+  USE(rA);                                                                     \
+  USE(rE);                                                                     \
+  BYTECODE_OLD_ENTRY_LABEL(Name)                                               \
+  rA = pc[1];                                                                  \
+  rE = static_cast<uint32_t>(pc[2]) | (static_cast<uint32_t>(pc[3]) << 8);     \
+  pc += 4;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_WIDE_ENTRY_LABEL(Name)                                              \
+  rA = pc[1];                                                                  \
+  rE = static_cast<uint32_t>(pc[2]) | (static_cast<uint32_t>(pc[3]) << 8) |    \
+       (static_cast<uint32_t>(pc[4]) << 16) |                                  \
+       (static_cast<uint32_t>(pc[5]) << 24);                                   \
+  pc += 6;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_ENTRY_LABEL(Name)                                                   \
+  rA = pc[1];                                                                  \
+  rE = pc[2];                                                                  \
+  pc += 3;                                                                     \
+  BYTECODE_IMPL_LABEL(Name)
+
+#define BYTECODE_HEADER_A_Y_WITH_OLD(Name)                                     \
+  uint32_t rA;                                                                 \
+  int32_t rY;                                                                  \
+  USE(rA);                                                                     \
+  USE(rY);                                                                     \
+  BYTECODE_OLD_ENTRY_LABEL(Name)                                               \
+  rA = pc[1];                                                                  \
+  rY = static_cast<int16_t>(static_cast<uint16_t>(pc[2]) |                     \
+                            (static_cast<uint16_t>(pc[3]) << 8));              \
+  pc += 4;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_WIDE_ENTRY_LABEL(Name)                                              \
+  rA = pc[1];                                                                  \
+  rY = static_cast<int32_t>(static_cast<uint32_t>(pc[2]) |                     \
+                            (static_cast<uint32_t>(pc[3]) << 8) |              \
+                            (static_cast<uint32_t>(pc[4]) << 16) |             \
+                            (static_cast<uint32_t>(pc[5]) << 24));             \
+  pc += 6;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_ENTRY_LABEL(Name)                                                   \
+  rA = pc[1];                                                                  \
+  rY = static_cast<int8_t>(pc[2]);                                             \
+  pc += 3;                                                                     \
+  BYTECODE_IMPL_LABEL(Name)
+
+#define BYTECODE_HEADER_D_F_WITH_OLD(Name)                                     \
+  uint32_t rD, rF;                                                             \
+  USE(rD);                                                                     \
+  USE(rF);                                                                     \
+  BYTECODE_OLD_ENTRY_LABEL(Name)                                               \
+  rF = pc[1];                                                                  \
+  rD = static_cast<uint32_t>(pc[2]) | (static_cast<uint32_t>(pc[3]) << 8);     \
+  pc += 4;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_WIDE_ENTRY_LABEL(Name)                                              \
+  rD = static_cast<uint32_t>(pc[1]) | (static_cast<uint32_t>(pc[2]) << 8) |    \
+       (static_cast<uint32_t>(pc[3]) << 16) |                                  \
+       (static_cast<uint32_t>(pc[4]) << 24);                                   \
+  rF = pc[5];                                                                  \
+  pc += 6;                                                                     \
+  GOTO_BYTECODE_IMPL(Name);                                                    \
+  BYTECODE_ENTRY_LABEL(Name)                                                   \
+  rD = pc[1];                                                                  \
+  rF = pc[2];                                                                  \
+  pc += 3;                                                                     \
+  BYTECODE_IMPL_LABEL(Name)
+
+#define BYTECODE_HEADER_A_B_C_WITH_OLD(Name)                                   \
+  uint32_t rA, rB, rC;                                                         \
+  USE(rA);                                                                     \
+  USE(rB);                                                                     \
+  USE(rC);                                                                     \
+  BYTECODE_OLD_ENTRY_LABEL(Name)                                               \
+  BYTECODE_ENTRY_LABEL(Name)                                                   \
+  rA = pc[1];                                                                  \
+  rB = pc[2];                                                                  \
+  rC = pc[3];                                                                  \
+  pc += 4;
 
 #define HANDLE_EXCEPTION                                                       \
   do {                                                                         \
@@ -1183,8 +1152,42 @@
   }                                                                            \
   ASSERT(Utils::DoublesBitEqual(Double::RawCast(SP[0])->ptr()->value_, result));
 
+#define BUMP_USAGE_COUNTER_ON_ENTRY(function)                                  \
+  {                                                                            \
+    int32_t counter = ++(function->ptr()->usage_counter_);                     \
+    if (UNLIKELY(FLAG_compilation_counter_threshold >= 0 &&                    \
+                 counter >= FLAG_compilation_counter_threshold &&              \
+                 !Function::HasCode(function))) {                              \
+      SP[1] = 0; /* Unused code result. */                                     \
+      SP[2] = function;                                                        \
+      Exit(thread, FP, SP + 3, pc);                                            \
+      NativeArguments native_args(thread, 1, SP + 2, SP + 1);                  \
+      INVOKE_RUNTIME(DRT_OptimizeInvokedFunction, native_args);                \
+      function = FrameFunction(FP);                                            \
+    }                                                                          \
+  }
+
+#ifdef PRODUCT
+#define DEBUG_CHECK
+#else
+#define DEBUG_CHECK                                                            \
+  if (is_debugging()) {                                                        \
+    /* Check for debug breakpoint or if single stepping. */                    \
+    if (thread->isolate()->debugger()->HasBytecodeBreakpointAt(pc)) {          \
+      SP[1] = null_value;                                                      \
+      Exit(thread, FP, SP + 2, pc);                                            \
+      NativeArguments args(thread, 0, NULL, SP + 1);                           \
+      INVOKE_RUNTIME(DRT_BreakpointRuntimeHandler, args)                       \
+    } else if (thread->isolate()->single_step()) {                             \
+      Exit(thread, FP, SP + 1, pc);                                            \
+      NativeArguments args(thread, 0, NULL, NULL);                             \
+      INVOKE_RUNTIME(DRT_SingleStepHandler, args);                             \
+    }                                                                          \
+  }
+#endif  // PRODUCT
+
 bool Interpreter::AssertAssignable(Thread* thread,
-                                   uint32_t* pc,
+                                   const KBCInstr* pc,
                                    RawObject** FP,
                                    RawObject** call_top,
                                    RawObject** args,
@@ -1278,7 +1281,7 @@
 // Returns false on exception.
 DART_NOINLINE bool Interpreter::AllocateMint(Thread* thread,
                                              int64_t value,
-                                             uint32_t* pc,
+                                             const KBCInstr* pc,
                                              RawObject** FP,
                                              RawObject** SP) {
   ASSERT(!Smi::IsValid(value));
@@ -1309,7 +1312,7 @@
 // Returns false on exception.
 DART_NOINLINE bool Interpreter::AllocateDouble(Thread* thread,
                                                double value,
-                                               uint32_t* pc,
+                                               const KBCInstr* pc,
                                                RawObject** FP,
                                                RawObject** SP) {
   const intptr_t instance_size = Double::InstanceSize();
@@ -1339,7 +1342,7 @@
 // Returns false on exception.
 DART_NOINLINE bool Interpreter::AllocateFloat32x4(Thread* thread,
                                                   simd128_value_t value,
-                                                  uint32_t* pc,
+                                                  const KBCInstr* pc,
                                                   RawObject** FP,
                                                   RawObject** SP) {
   const intptr_t instance_size = Float32x4::InstanceSize();
@@ -1369,7 +1372,7 @@
 // Returns false on exception.
 DART_NOINLINE bool Interpreter::AllocateFloat64x2(Thread* thread,
                                                   simd128_value_t value,
-                                                  uint32_t* pc,
+                                                  const KBCInstr* pc,
                                                   RawObject** FP,
                                                   RawObject** SP) {
   const intptr_t instance_size = Float64x2::InstanceSize();
@@ -1400,12 +1403,12 @@
 bool Interpreter::AllocateArray(Thread* thread,
                                 RawTypeArguments* type_args,
                                 RawObject* length_object,
-                                uint32_t* pc,
+                                const KBCInstr* pc,
                                 RawObject** FP,
                                 RawObject** SP) {
   if (LIKELY(!length_object->IsHeapObject())) {
     const intptr_t length = Smi::Value(Smi::RawCast(length_object));
-    if (LIKELY((0 <= length) && (length <= Array::kMaxElements))) {
+    if (LIKELY(Array::IsValidLength(length))) {
       const intptr_t instance_size = Array::InstanceSize(length);
       const uword start = thread->top();
       if (LIKELY((start + instance_size) < thread->end())) {
@@ -1435,7 +1438,7 @@
 // Returns false on exception.
 bool Interpreter::AllocateContext(Thread* thread,
                                   intptr_t num_context_variables,
-                                  uint32_t* pc,
+                                  const KBCInstr* pc,
                                   RawObject** FP,
                                   RawObject** SP) {
   const intptr_t instance_size = Context::InstanceSize(num_context_variables);
@@ -1466,7 +1469,7 @@
 // Allocate a _Closure and put it into SP[0].
 // Returns false on exception.
 bool Interpreter::AllocateClosure(Thread* thread,
-                                  uint32_t* pc,
+                                  const KBCInstr* pc,
                                   RawObject** FP,
                                   RawObject** SP) {
   const intptr_t instance_size = Closure::InstanceSize();
@@ -1498,12 +1501,11 @@
                              RawObject* const* argv,
                              Thread* thread) {
   // Interpreter state (see constants_kbc.h for high-level overview).
-  uint32_t* pc;    // Program Counter: points to the next op to execute.
+  const KBCInstr* pc;  // Program Counter: points to the next op to execute.
   RawObject** FP;  // Frame Pointer.
   RawObject** SP;  // Stack Pointer.
 
   uint32_t op;  // Currently executing op.
-  uint16_t rA;  // A component of the currently executing op.
 
   bool reentering = fp_ != NULL;
   if (!reentering) {
@@ -1572,7 +1574,7 @@
 
   // Ready to start executing bytecode. Load entry point and corresponding
   // object pool.
-  pc = reinterpret_cast<uint32_t*>(bytecode->ptr()->instructions_);
+  pc = reinterpret_cast<const KBCInstr*>(bytecode->ptr()->instructions_);
   NOT_IN_PRODUCT(pc_ = pc);  // For the profiler.
   NOT_IN_PRODUCT(fp_ = FP);  // For the profiler.
   pp_ = bytecode->ptr()->object_pool_;
@@ -1592,13 +1594,9 @@
   RawBool* false_value = Bool::False().raw();
   RawObject* null_value = Object::null();
 
-#if defined(DEBUG)
-  Function& function_h = Function::Handle();
-#endif
-
 #ifdef DART_HAS_COMPUTED_GOTO
   static const void* dispatch[] = {
-#define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name,
+#define TARGET(name, fmt, kind, fmta, fmtb, fmtc) &&bc##name,
       KERNEL_BYTECODES_LIST(TARGET)
 #undef TARGET
   };
@@ -1607,7 +1605,7 @@
   DISPATCH();  // Enter the dispatch loop.
 SwitchDispatch:
   switch (op & 0xFF) {
-#define TARGET(name, fmt, fmta, fmtb, fmtc)                                    \
+#define TARGET(name, fmt, kind, fmta, fmtb, fmtc)                              \
   case KernelBytecode::k##name:                                                \
     goto bc##name;
     KERNEL_BYTECODES_LIST(TARGET)
@@ -1619,8 +1617,8 @@
 
   // KernelBytecode handlers (see constants_kbc.h for bytecode descriptions).
   {
-    BYTECODE(Entry, A_D);
-    const uint16_t num_locals = rD;
+    BYTECODE(Entry, D);
+    const intptr_t num_locals = rD;
 
     // Initialize locals with null & set SP.
     for (intptr_t i = 0; i < num_locals; i++) {
@@ -1632,14 +1630,14 @@
   }
 
   {
-    BYTECODE(EntryFixed, A_D);
-    const uint16_t num_fixed_params = rA;
-    const uint16_t num_locals = rD;
+    BYTECODE(EntryFixed, A_E);
+    const intptr_t num_fixed_params = rA;
+    const intptr_t num_locals = rE;
 
     const intptr_t arg_count = InterpreterHelpers::ArgDescArgCount(argdesc_);
     const intptr_t pos_count = InterpreterHelpers::ArgDescPosCount(argdesc_);
     if ((arg_count != num_fixed_params) || (pos_count != num_fixed_params)) {
-      goto ClosureNoSuchMethod;
+      goto NoSuchMethodFromPrologue;
     }
 
     // Initialize locals with null & set SP.
@@ -1653,9 +1651,9 @@
 
   {
     BYTECODE(EntryOptional, A_B_C);
-    const uint16_t num_fixed_params = rA;
-    const uint16_t num_opt_pos_params = rB;
-    const uint16_t num_opt_named_params = rC;
+    const intptr_t num_fixed_params = rA;
+    const intptr_t num_opt_pos_params = rB;
+    const intptr_t num_opt_named_params = rC;
     const intptr_t min_num_pos_args = num_fixed_params;
     const intptr_t max_num_pos_args = num_fixed_params + num_opt_pos_params;
 
@@ -1666,7 +1664,7 @@
 
     // Check that got the right number of positional parameters.
     if ((min_num_pos_args > pos_count) || (pos_count > max_num_pos_args)) {
-      goto ClosureNoSuchMethod;
+      goto NoSuchMethodFromPrologue;
     }
 
     // Copy all passed position arguments.
@@ -1681,60 +1679,55 @@
       // descriptor.
       RawObject** argdesc_data = argdesc_->ptr()->data();
 
-      intptr_t i = named_count - 1;           // argument position
-      intptr_t j = num_opt_named_params - 1;  // parameter position
-      while ((j >= 0) && (i >= 0)) {
+      intptr_t i = 0;  // argument position
+      intptr_t j = 0;  // parameter position
+      while ((j < num_opt_named_params) && (i < named_count)) {
         // Fetch formal parameter information: name, default value, target slot.
-        const uint32_t load_name = pc[2 * j];
-        const uint32_t load_value = pc[2 * j + 1];
-        ASSERT(KernelBytecode::DecodeOpcode(load_name) ==
-               KernelBytecode::kLoadConstant);
-        ASSERT(KernelBytecode::DecodeOpcode(load_value) ==
-               KernelBytecode::kLoadConstant);
+        const KBCInstr* load_name = pc;
+        const KBCInstr* load_value = KernelBytecode::Next(load_name);
+        pc = KernelBytecode::Next(load_value);
+        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_name));
+        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value));
         const uint8_t reg = KernelBytecode::DecodeA(load_name);
         ASSERT(reg == KernelBytecode::DecodeA(load_value));
 
         RawString* name = static_cast<RawString*>(
-            LOAD_CONSTANT(KernelBytecode::DecodeD(load_name)));
+            LOAD_CONSTANT(KernelBytecode::DecodeE(load_name)));
         if (name == argdesc_data[ArgumentsDescriptor::name_index(i)]) {
           // Parameter was passed. Fetch passed value.
           const intptr_t arg_index = Smi::Value(static_cast<RawSmi*>(
               argdesc_data[ArgumentsDescriptor::position_index(i)]));
           FP[reg] = first_arg[arg_index];
-          i--;  // Consume passed argument.
+          ++i;  // Consume passed argument.
         } else {
           // Parameter was not passed. Fetch default value.
-          FP[reg] = LOAD_CONSTANT(KernelBytecode::DecodeD(load_value));
+          FP[reg] = LOAD_CONSTANT(KernelBytecode::DecodeE(load_value));
         }
-        j--;  // Next formal parameter.
+        ++j;  // Next formal parameter.
       }
 
       // If we have unprocessed formal parameters then initialize them all
       // using default values.
-      while (j >= 0) {
-        const uint32_t load_name = pc[2 * j];
-        const uint32_t load_value = pc[2 * j + 1];
-        ASSERT(KernelBytecode::DecodeOpcode(load_name) ==
-               KernelBytecode::kLoadConstant);
-        ASSERT(KernelBytecode::DecodeOpcode(load_value) ==
-               KernelBytecode::kLoadConstant);
+      while (j < num_opt_named_params) {
+        const KBCInstr* load_name = pc;
+        const KBCInstr* load_value = KernelBytecode::Next(load_name);
+        pc = KernelBytecode::Next(load_value);
+        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_name));
+        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value));
         const uint8_t reg = KernelBytecode::DecodeA(load_name);
         ASSERT(reg == KernelBytecode::DecodeA(load_value));
 
-        FP[reg] = LOAD_CONSTANT(KernelBytecode::DecodeD(load_value));
-        j--;
+        FP[reg] = LOAD_CONSTANT(KernelBytecode::DecodeE(load_value));
+        ++j;
       }
 
       // If we have unprocessed passed arguments that means we have mismatch
       // between formal parameters and concrete arguments. This can only
       // occur if the current function is a closure.
-      if (i != -1) {
-        goto ClosureNoSuchMethod;
+      if (i < named_count) {
+        goto NoSuchMethodFromPrologue;
       }
 
-      // Skip LoadConstant-s encoding information about named parameters.
-      pc += num_opt_named_params * 2;
-
       // SP points past copied arguments.
       SP = FP + num_fixed_params + num_opt_named_params - 1;
     } else {
@@ -1743,28 +1736,23 @@
         // Function can't have both named and optional positional parameters.
         // This kind of mismatch can only occur if the current function
         // is a closure.
-        goto ClosureNoSuchMethod;
+        goto NoSuchMethodFromPrologue;
       }
 
       // Process the list of default values encoded as a sequence of
       // LoadConstant instructions after EntryOpt bytecode.
       // Execute only those that correspond to parameters that were not passed.
-      for (intptr_t i = pos_count - num_fixed_params; i < num_opt_pos_params;
-           i++) {
-        const uint32_t load_value = pc[i];
-        ASSERT(KernelBytecode::DecodeOpcode(load_value) ==
-               KernelBytecode::kLoadConstant);
-#if defined(DEBUG)
-        const uint8_t reg = KernelBytecode::DecodeA(load_value);
-        ASSERT((num_fixed_params + i) == reg);
-#endif
-        FP[num_fixed_params + i] =
-            LOAD_CONSTANT(KernelBytecode::DecodeD(load_value));
+      for (intptr_t i = num_fixed_params; i < pos_count; ++i) {
+        ASSERT(KernelBytecode::IsLoadConstantOpcode(pc));
+        pc = KernelBytecode::Next(pc);
       }
-
-      // Skip LoadConstant-s encoding default values for optional positional
-      // parameters.
-      pc += num_opt_pos_params;
+      for (intptr_t i = pos_count; i < max_num_pos_args; ++i) {
+        const KBCInstr* load_value = pc;
+        pc = KernelBytecode::Next(load_value);
+        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value));
+        ASSERT(KernelBytecode::DecodeA(load_value) == i);
+        FP[i] = LOAD_CONSTANT(KernelBytecode::DecodeE(load_value));
+      }
 
       // SP points past the last copied parameter.
       SP = FP + max_num_pos_args - 1;
@@ -1774,9 +1762,9 @@
   }
 
   {
-    BYTECODE(Frame, A_D);
+    BYTECODE(Frame, D);
     // Initialize locals with null and increment SP.
-    const uint16_t num_locals = rD;
+    const intptr_t num_locals = rD;
     for (intptr_t i = 1; i <= num_locals; i++) {
       SP[i] = null_value;
     }
@@ -1793,6 +1781,7 @@
 
   {
     BYTECODE(CheckStack, A);
+    DEBUG_CHECK;
     {
       // Check the interpreter's own stack limit for actual interpreter's stack
       // overflows, and also the thread's stack limit for scheduled interrupts.
@@ -1818,15 +1807,15 @@
   }
 
   {
-    BYTECODE(CheckFunctionTypeArgs, A_D);
-    const uint16_t declared_type_args_len = rA;
-    const uint16_t first_stack_local_index = rD;
+    BYTECODE(CheckFunctionTypeArgs, A_E);
+    const intptr_t declared_type_args_len = rA;
+    const intptr_t first_stack_local_index = rE;
 
     // Decode arguments descriptor's type args len.
     const intptr_t type_args_len =
         InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
     if ((type_args_len != declared_type_args_len) && (type_args_len != 0)) {
-      goto ClosureNoSuchMethod;
+      goto NoSuchMethodFromPrologue;
     }
     if (type_args_len > 0) {
       // Decode arguments descriptor's argument count (excluding type args).
@@ -1840,7 +1829,7 @@
   }
 
   {
-    BYTECODE(InstantiateType, A_D);
+    BYTECODE(InstantiateType, D);
     // Stack: instantiator type args, function type args
     RawObject* type = LOAD_CONSTANT(rD);
     SP[1] = type;
@@ -1856,10 +1845,10 @@
   }
 
   {
-    BYTECODE(InstantiateTypeArgumentsTOS, A_D);
+    BYTECODE(InstantiateTypeArgumentsTOS, A_E);
     // Stack: instantiator type args, function type args
     RawTypeArguments* type_arguments =
-        static_cast<RawTypeArguments*>(LOAD_CONSTANT(rD));
+        static_cast<RawTypeArguments*>(LOAD_CONSTANT(rE));
 
     RawObject* instantiator_type_args = SP[-1];
     RawObject* function_type_args = SP[0];
@@ -1919,13 +1908,13 @@
   }
 
   {
-    BYTECODE(LoadConstant, A_D);
-    FP[rA] = LOAD_CONSTANT(rD);
+    BYTECODE(LoadConstant, A_E);
+    FP[rA] = LOAD_CONSTANT(rE);
     DISPATCH();
   }
 
   {
-    BYTECODE(PushConstant, __D);
+    BYTECODE(PushConstant, D);
     *++SP = LOAD_CONSTANT(rD);
     DISPATCH();
   }
@@ -1949,33 +1938,33 @@
   }
 
   {
-    BYTECODE(PushInt, A_X);
-    *++SP = Smi::New(rD);
+    BYTECODE(PushInt, X);
+    *++SP = Smi::New(rX);
     DISPATCH();
   }
 
   {
-    BYTECODE(Push, A_X);
-    *++SP = FP[rD];
+    BYTECODE(Push, X);
+    *++SP = FP[rX];
     DISPATCH();
   }
 
   {
-    BYTECODE(StoreLocal, A_X);
-    FP[rD] = *SP;
+    BYTECODE(StoreLocal, X);
+    FP[rX] = *SP;
     DISPATCH();
   }
 
   {
-    BYTECODE(PopLocal, A_X);
-    FP[rD] = *SP--;
+    BYTECODE(PopLocal, X);
+    FP[rX] = *SP--;
     DISPATCH();
   }
 
   {
-    BYTECODE(MoveSpecial, A_X);
+    BYTECODE(MoveSpecial, A_Y);
     ASSERT(rA < KernelBytecode::kSpecialIndexCount);
-    FP[rD] = special_[rA];
+    FP[rY] = special_[rA];
     DISPATCH();
   }
 
@@ -1986,53 +1975,12 @@
   }
 
   {
-    BYTECODE(IndirectStaticCall, A_D);
-
-#ifndef PRODUCT
-    // Check if single stepping.
-    if (thread->isolate()->single_step()) {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
-    }
-#endif  // !PRODUCT
-
+    BYTECODE(DirectCall, D_F);
+    DEBUG_CHECK;
     // Invoke target function.
     {
-      const uint16_t argc = rA;
-      // Look up the function in the ICData.
-      RawObject* ic_data_obj = SP[0];
-      RawICData* ic_data = RAW_CAST(ICData, ic_data_obj);
-      RawObject** data = ic_data->ptr()->entries_->ptr()->data();
-      InterpreterHelpers::IncrementICUsageCount(data, 0, 0);
-      SP[0] = 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));
-      if (!Invoke(thread, call_base, call_top, &pc, &FP, &SP)) {
-        HANDLE_EXCEPTION;
-      }
-    }
-
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DirectCall, A_D);
-
-#ifndef PRODUCT
-    // Check if single stepping.
-    if (thread->isolate()->single_step()) {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
-    }
-#endif  // !PRODUCT
-
-    // Invoke target function.
-    {
-      const uint16_t argc = rA;
-      const uint16_t kidx = rD;
+      const uint32_t argc = rF;
+      const uint32_t kidx = rD;
 
       InterpreterHelpers::IncrementUsageCounter(FrameFunction(FP));
       *++SP = LOAD_CONSTANT(kidx);
@@ -2048,20 +1996,11 @@
   }
 
   {
-    BYTECODE(InterfaceCall, A_D);
-
-#ifndef PRODUCT
-    // Check if single stepping.
-    if (thread->isolate()->single_step()) {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
-    }
-#endif  // !PRODUCT
-
+    BYTECODE(InterfaceCall, D_F);
+    DEBUG_CHECK;
     {
-      const uint16_t argc = rA;
-      const uint16_t kidx = rD;
+      const uint32_t argc = rF;
+      const uint32_t kidx = rD;
 
       RawObject** call_base = SP - argc + 1;
       RawObject** call_top = SP + 1;
@@ -2080,20 +2019,11 @@
   }
 
   {
-    BYTECODE(UncheckedInterfaceCall, A_D);
-
-#ifndef PRODUCT
-    // Check if single stepping.
-    if (thread->isolate()->single_step()) {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
-    }
-#endif  // !PRODUCT
-
+    BYTECODE(UncheckedInterfaceCall, D_F);
+    DEBUG_CHECK;
     {
-      const uint16_t argc = rA;
-      const uint16_t kidx = rD;
+      const uint32_t argc = rF;
+      const uint32_t kidx = rD;
 
       RawObject** call_base = SP - argc + 1;
       RawObject** call_top = SP + 1;
@@ -2112,20 +2042,11 @@
   }
 
   {
-    BYTECODE(DynamicCall, A_D);
-
-#ifndef PRODUCT
-    // Check if single stepping.
-    if (thread->isolate()->single_step()) {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
-    }
-#endif  // !PRODUCT
-
+    BYTECODE(DynamicCall, D_F);
+    DEBUG_CHECK;
     {
-      const uint16_t argc = rA;
-      const uint16_t kidx = rD;
+      const uint32_t argc = rF;
+      const uint32_t kidx = rD;
 
       RawObject** call_base = SP - argc + 1;
       RawObject** call_top = SP + 1;
@@ -2152,7 +2073,7 @@
   }
 
   {
-    BYTECODE(NativeCall, __D);
+    BYTECODE(NativeCall, D);
     RawTypedData* data = static_cast<RawTypedData*>(LOAD_CONSTANT(rD));
     MethodRecognizer::Kind kind = NativeEntryData::GetKind(data);
     switch (kind) {
@@ -2220,7 +2141,12 @@
           // Change the ArgumentsDescriptor of the call with a new cached one.
           argdesc_ = ArgumentsDescriptor::New(
               0, KernelBytecode::kNativeCallToGrowableListArgc);
-          // Note the special handling of the return of this call in DecodeArgc.
+          if (!thread->isolate()->is_using_old_bytecode_instructions()) {
+            // Replace PC to the return trampoline so ReturnTOS would see
+            // a call bytecode at return address and will be able to get argc
+            // via DecodeArgc.
+            pc = KernelBytecode::GetNativeCallToGrowableListReturnTrampoline();
+          }
           if (!Invoke(thread, SP - 1, SP + 1, &pc, &FP, &SP)) {
             HANDLE_EXCEPTION;
           }
@@ -2333,6 +2259,7 @@
     RawObject* result;  // result to return to the caller.
 
     BYTECODE(ReturnTOS, 0);
+    DEBUG_CHECK;
     result = *SP;
     // Restore caller PC.
     pc = SavedCallerPC(FP);
@@ -2370,7 +2297,9 @@
     }
 
     // Look at the caller to determine how many arguments to pop.
-    const uint8_t argc = KernelBytecode::DecodeArgc(pc[-1]);
+    const uint8_t argc = thread->isolate()->is_using_old_bytecode_instructions()
+                             ? KernelBytecode::DecodeArgc_Old(pc)
+                             : KernelBytecode::DecodeArgc(pc);
 
     // Restore SP, FP and PP. Push result and dispatch.
     SP = FrameArguments(FP, argc);
@@ -2379,11 +2308,19 @@
     NOT_IN_PRODUCT(pc_ = pc);  // For the profiler.
     pp_ = InterpreterHelpers::FrameBytecode(FP)->ptr()->object_pool_;
     *SP = result;
+#if defined(DEBUG)
+    if (IsTracingExecution()) {
+      THR_Print("%" Pu64 " ", icount_);
+      THR_Print("Returning to %s (argc %d)\n",
+                Function::Handle(FrameFunction(FP)).ToFullyQualifiedCString(),
+                static_cast<int>(argc));
+    }
+#endif
     DISPATCH();
   }
 
   {
-    BYTECODE(StoreStaticTOS, A_D);
+    BYTECODE(StoreStaticTOS, D);
     RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
     RawInstance* value = static_cast<RawInstance*>(*SP--);
     field->StorePointer(&field->ptr()->value_.static_value_, value, thread);
@@ -2391,7 +2328,7 @@
   }
 
   {
-    BYTECODE(PushStatic, A_D);
+    BYTECODE(PushStatic, D);
     RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
     // Note: field is also on the stack, hence no increment.
     *SP = field->ptr()->value_.static_value_;
@@ -2399,7 +2336,7 @@
   }
 
   {
-    BYTECODE(StoreFieldTOS, __D);
+    BYTECODE(StoreFieldTOS, D);
     RawField* field = RAW_CAST(Field, LOAD_CONSTANT(rD + 1));
     RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
     RawObject* value = reinterpret_cast<RawObject*>(SP[0]);
@@ -2489,13 +2426,13 @@
   }
 
   {
-    BYTECODE(StoreContextVar, __D);
+    BYTECODE(StoreContextVar, A_E);
     const uword offset_in_words =
-        static_cast<uword>(Context::variable_offset(rD) / kWordSize);
+        static_cast<uword>(Context::variable_offset(rE) / kWordSize);
     RawContext* instance = reinterpret_cast<RawContext*>(SP[-1]);
     RawObject* value = reinterpret_cast<RawContext*>(SP[0]);
     SP -= 2;  // Drop instance and value.
-    ASSERT(rD < static_cast<uint32_t>(instance->ptr()->num_variables_));
+    ASSERT(rE < static_cast<uint32_t>(instance->ptr()->num_variables_));
     instance->StorePointer(
         reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words, value,
         thread);
@@ -2504,7 +2441,7 @@
   }
 
   {
-    BYTECODE(LoadFieldTOS, __D);
+    BYTECODE(LoadFieldTOS, D);
 #if defined(DEBUG)
     // Currently only used to load closure fields, which are not unboxed.
     // If used for general field, code for copying the mutable box must be
@@ -2523,7 +2460,7 @@
   }
 
   {
-    BYTECODE(LoadTypeArgumentsField, __D);
+    BYTECODE(LoadTypeArgumentsField, D);
     const uword offset_in_words =
         static_cast<uword>(Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD))));
     RawInstance* instance = static_cast<RawInstance*>(SP[0]);
@@ -2541,19 +2478,19 @@
   }
 
   {
-    BYTECODE(LoadContextVar, __D);
+    BYTECODE(LoadContextVar, A_E);
     const uword offset_in_words =
-        static_cast<uword>(Context::variable_offset(rD) / kWordSize);
+        static_cast<uword>(Context::variable_offset(rE) / kWordSize);
     RawContext* instance = static_cast<RawContext*>(SP[0]);
-    ASSERT(rD < static_cast<uint32_t>(instance->ptr()->num_variables_));
+    ASSERT(rE < static_cast<uint32_t>(instance->ptr()->num_variables_));
     SP[0] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
     DISPATCH();
   }
 
   {
-    BYTECODE(AllocateContext, A_D);
+    BYTECODE(AllocateContext, A_E);
     ++SP;
-    const uint16_t num_context_variables = rD;
+    const uint32_t num_context_variables = rE;
     if (!AllocateContext(thread, num_context_variables, pc, FP, SP)) {
       HANDLE_EXCEPTION;
     }
@@ -2561,7 +2498,7 @@
   }
 
   {
-    BYTECODE(CloneContext, A);
+    BYTECODE(CloneContext, A_E);
     {
       SP[1] = SP[0];  // Context to clone.
       Exit(thread, FP, SP + 2, pc);
@@ -2572,7 +2509,7 @@
   }
 
   {
-    BYTECODE(Allocate, A_D);
+    BYTECODE(Allocate, D);
     RawClass* cls = Class::RawCast(LOAD_CONSTANT(rD));
     if (LIKELY(InterpreterHelpers::IsFinalized(cls))) {
       const intptr_t class_id = cls->ptr()->id_;
@@ -2646,7 +2583,7 @@
   }
 
   {
-    BYTECODE(AssertAssignable, A_D);
+    BYTECODE(AssertAssignable, A_E);
     // Stack: instance, type, instantiator type args, function type args, name
     RawObject** args = SP - 4;
     const bool may_be_smi = (rA == 1);
@@ -2655,7 +2592,7 @@
     const bool smi_ok = is_smi && may_be_smi;
     if (!smi_ok && (args[0] != null_value)) {
       RawSubtypeTestCache* cache =
-          static_cast<RawSubtypeTestCache*>(LOAD_CONSTANT(rD));
+          static_cast<RawSubtypeTestCache*>(LOAD_CONSTANT(rE));
 
       if (!AssertAssignable(thread, pc, FP, SP, args, cache)) {
         HANDLE_EXCEPTION;
@@ -2667,7 +2604,7 @@
   }
 
   {
-    BYTECODE(AssertSubtype, A);
+    BYTECODE(AssertSubtype, 0);
     RawObject** args = SP - 4;
 
     // TODO(kustermann): Implement fast case for common arguments.
@@ -2720,13 +2657,13 @@
   }
 
   {
-    BYTECODE(Jump, 0);
+    BYTECODE(Jump, T);
     LOAD_JUMP_TARGET();
     DISPATCH();
   }
 
   {
-    BYTECODE(JumpIfNoAsserts, 0);
+    BYTECODE(JumpIfNoAsserts, T);
     if (!thread->isolate()->asserts()) {
       LOAD_JUMP_TARGET();
     }
@@ -2734,7 +2671,7 @@
   }
 
   {
-    BYTECODE(JumpIfNotZeroTypeArgs, 0);
+    BYTECODE(JumpIfNotZeroTypeArgs, T);
     if (InterpreterHelpers::ArgDescTypeArgsLen(argdesc_) != 0) {
       LOAD_JUMP_TARGET();
     }
@@ -2742,7 +2679,7 @@
   }
 
   {
-    BYTECODE(JumpIfEqStrict, 0);
+    BYTECODE(JumpIfEqStrict, T);
     SP -= 2;
     if (SP[1] == SP[2]) {
       LOAD_JUMP_TARGET();
@@ -2751,7 +2688,7 @@
   }
 
   {
-    BYTECODE(JumpIfNeStrict, 0);
+    BYTECODE(JumpIfNeStrict, T);
     SP -= 2;
     if (SP[1] != SP[2]) {
       LOAD_JUMP_TARGET();
@@ -2760,7 +2697,7 @@
   }
 
   {
-    BYTECODE(JumpIfTrue, 0);
+    BYTECODE(JumpIfTrue, T);
     SP -= 1;
     if (SP[1] == true_value) {
       LOAD_JUMP_TARGET();
@@ -2769,7 +2706,7 @@
   }
 
   {
-    BYTECODE(JumpIfFalse, 0);
+    BYTECODE(JumpIfFalse, T);
     SP -= 1;
     if (SP[1] == false_value) {
       LOAD_JUMP_TARGET();
@@ -2778,7 +2715,7 @@
   }
 
   {
-    BYTECODE(JumpIfNull, 0);
+    BYTECODE(JumpIfNull, T);
     SP -= 1;
     if (SP[1] == null_value) {
       LOAD_JUMP_TARGET();
@@ -2787,7 +2724,7 @@
   }
 
   {
-    BYTECODE(JumpIfNotNull, 0);
+    BYTECODE(JumpIfNotNull, T);
     SP -= 1;
     if (SP[1] != null_value) {
       LOAD_JUMP_TARGET();
@@ -3102,7 +3039,7 @@
   }
 
   {
-    BYTECODE(AllocateClosure, A_D);
+    BYTECODE(AllocateClosure, D);
     ++SP;
     if (!AllocateClosure(thread, pc, FP, SP)) {
       HANDLE_EXCEPTION;
@@ -3112,25 +3049,55 @@
 
   {
     BYTECODE(Trap, 0);
+    BYTECODE(Unused00, 0);
+    BYTECODE_NEW(Unused01, 0);
+    BYTECODE_NEW(Unused02, 0);
+    BYTECODE_NEW(Unused03, 0);
+    BYTECODE_NEW(Unused04, 0);
+    BYTECODE_NEW(Unused05, 0);
+    BYTECODE_NEW(Unused06, 0);
+    BYTECODE_NEW(Unused07, 0);
+    BYTECODE_NEW(Unused08, 0);
+    BYTECODE_NEW(Unused09, 0);
+    BYTECODE_NEW(Unused10, 0);
+    BYTECODE_NEW(Unused11, 0);
+    BYTECODE_NEW(Unused12, 0);
+    BYTECODE_NEW(Unused13, 0);
+    BYTECODE_NEW(Unused14, 0);
+    BYTECODE_NEW(Unused15, 0);
+    BYTECODE_NEW(Unused16, 0);
+    BYTECODE_NEW(Unused17, 0);
+    BYTECODE_NEW(Unused18, 0);
+    BYTECODE_NEW(Unused19, 0);
+    BYTECODE_NEW(Unused20, 0);
+    BYTECODE_NEW(Unused21, 0);
+    BYTECODE_NEW(Unused22, 0);
+    BYTECODE_NEW(Unused23, 0);
+    BYTECODE_NEW(Unused24, 0);
+    BYTECODE_NEW(Unused25, 0);
+    BYTECODE_NEW(Unused26, 0);
+    BYTECODE_NEW(Unused27, 0);
+    BYTECODE_NEW(Unused28, 0);
+    BYTECODE_NEW(Unused29, 0);
+    BYTECODE_NEW(Unused30, 0);
+    BYTECODE_NEW(Unused31, 0);
+    BYTECODE_NEW(Unused32, 0);
+    BYTECODE_NEW(Unused33, 0);
+    BYTECODE_NEW(Unused34, 0);
+    BYTECODE_NEW(Unused35, 0);
+    BYTECODE_NEW(Unused36, 0);
+    BYTECODE_NEW(Unused37, 0);
     UNIMPLEMENTED();
     DISPATCH();
   }
 
   {
-    BYTECODE(VMInternal_ImplicitGetter, 0);
+    BYTECODE_NEW(VMInternal_ImplicitGetter, 0);
 
     RawFunction* function = FrameFunction(FP);
-    int32_t counter = ++(function->ptr()->usage_counter_);
-    if (UNLIKELY(FLAG_compilation_counter_threshold >= 0 &&
-                 counter >= FLAG_compilation_counter_threshold &&
-                 !Function::HasCode(function))) {
-      SP[1] = 0;  // Unused code result.
-      SP[2] = function;
-      Exit(thread, FP, SP + 3, pc);
-      NativeArguments native_args(thread, 1, SP + 2, SP + 1);
-      INVOKE_RUNTIME(DRT_OptimizeInvokedFunction, native_args);
-      function = FrameFunction(FP);
-    }
+    ASSERT(Function::kind(function) == RawFunction::kImplicitGetter);
+
+    BUMP_USAGE_COUNTER_ON_ENTRY(function);
 
     // Field object is cached in function's data_.
     RawField* field = reinterpret_cast<RawField*>(function->ptr()->data_);
@@ -3174,20 +3141,12 @@
   }
 
   {
-    BYTECODE(VMInternal_ImplicitSetter, 0);
+    BYTECODE_NEW(VMInternal_ImplicitSetter, 0);
 
     RawFunction* function = FrameFunction(FP);
-    int32_t counter = ++(function->ptr()->usage_counter_);
-    if (UNLIKELY(FLAG_compilation_counter_threshold >= 0 &&
-                 counter >= FLAG_compilation_counter_threshold &&
-                 !Function::HasCode(function))) {
-      SP[1] = 0;  // Unused code result.
-      SP[2] = function;
-      Exit(thread, FP, SP + 3, pc);
-      NativeArguments native_args(thread, 1, SP + 2, SP + 1);
-      INVOKE_RUNTIME(DRT_OptimizeInvokedFunction, native_args);
-      function = FrameFunction(FP);
-    }
+    ASSERT(Function::kind(function) == RawFunction::kImplicitSetter);
+
+    BUMP_USAGE_COUNTER_ON_ENTRY(function);
 
     // Field object is cached in function's data_.
     RawField* field = reinterpret_cast<RawField*>(function->ptr()->data_);
@@ -3262,6 +3221,7 @@
       }
 
       // Reload objects after the call which may trigger GC.
+      field = reinterpret_cast<RawField*>(FrameFunction(FP)->ptr()->data_);
       instance = reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[0]);
       value = FrameArguments(FP, kArgc)[1];
     }
@@ -3302,21 +3262,45 @@
   }
 
   {
-    BYTECODE(VMInternal_MethodExtractor, 0);
+    BYTECODE_NEW(VMInternal_ImplicitStaticGetter, 0);
 
     RawFunction* function = FrameFunction(FP);
-    int32_t counter = ++(function->ptr()->usage_counter_);
-    if (UNLIKELY(FLAG_compilation_counter_threshold >= 0 &&
-                 counter >= FLAG_compilation_counter_threshold &&
-                 !Function::HasCode(function))) {
-      SP[1] = 0;  // Unused code result.
-      SP[2] = function;
+    ASSERT(Function::kind(function) == RawFunction::kImplicitStaticGetter);
+
+    BUMP_USAGE_COUNTER_ON_ENTRY(function);
+
+    // Field object is cached in function's data_.
+    RawField* field = reinterpret_cast<RawField*>(function->ptr()->data_);
+    RawInstance* value = field->ptr()->value_.static_value_;
+    if (value == Object::sentinel().raw() ||
+        value == Object::transition_sentinel().raw()) {
+      SP[1] = 0;  // Unused result of invoking the initializer.
+      SP[2] = field;
       Exit(thread, FP, SP + 3, pc);
       NativeArguments native_args(thread, 1, SP + 2, SP + 1);
-      INVOKE_RUNTIME(DRT_OptimizeInvokedFunction, native_args);
+      INVOKE_RUNTIME(DRT_InitStaticField, native_args);
+
+      // Reload objects after the call which may trigger GC.
       function = FrameFunction(FP);
+      field = reinterpret_cast<RawField*>(function->ptr()->data_);
+      // The field is initialized by the runtime call, but not returned.
+      value = field->ptr()->value_.static_value_;
     }
 
+    // Field was initialized. Return its value.
+    *++SP = value;
+
+    DISPATCH();
+  }
+
+  {
+    BYTECODE_NEW(VMInternal_MethodExtractor, 0);
+
+    RawFunction* function = FrameFunction(FP);
+    ASSERT(Function::kind(function) == RawFunction::kMethodExtractor);
+
+    BUMP_USAGE_COUNTER_ON_ENTRY(function);
+
     ASSERT(InterpreterHelpers::ArgDescTypeArgsLen(argdesc_) == 0);
 
     ++SP;
@@ -3349,64 +3333,264 @@
     DISPATCH();
   }
 
-  // Helper used to handle noSuchMethod on closures.
   {
-  ClosureNoSuchMethod:
-#if defined(DEBUG)
-    function_h ^= FrameFunction(FP);
-    ASSERT(function_h.IsNull() || function_h.IsClosureFunction());
-#endif
+    BYTECODE_NEW(VMInternal_InvokeClosure, 0);
 
-    // Restore caller context as we are going to throw NoSuchMethod.
-    pc = SavedCallerPC(FP);
+    RawFunction* function = FrameFunction(FP);
+    ASSERT(Function::kind(function) == RawFunction::kInvokeFieldDispatcher);
 
-    const bool has_dart_caller = !IsEntryFrameMarker(pc);
+    BUMP_USAGE_COUNTER_ON_ENTRY(function);
+
     const intptr_t type_args_len =
         InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
     const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
     const intptr_t argc =
         InterpreterHelpers::ArgDescArgCount(argdesc_) + receiver_idx;
 
-    SP = FrameArguments(FP, 0);
-    RawObject** args = SP - argc;
-    FP = SavedCallerFP(FP);
-    NOT_IN_PRODUCT(fp_ = FP);  // For the profiler.
-    if (has_dart_caller) {
-      pp_ = InterpreterHelpers::FrameBytecode(FP)->ptr()->object_pool_;
+    RawClosure* receiver =
+        Closure::RawCast(FrameArguments(FP, argc)[receiver_idx]);
+    function = receiver->ptr()->function_;
+
+    SP[1] = function;
+    goto TailCallSP1;
+  }
+
+  {
+    BYTECODE_NEW(VMInternal_InvokeField, 0);
+
+    RawFunction* function = FrameFunction(FP);
+    ASSERT(Function::kind(function) == RawFunction::kInvokeFieldDispatcher);
+
+    BUMP_USAGE_COUNTER_ON_ENTRY(function);
+
+    const intptr_t type_args_len =
+        InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
+    const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
+    const intptr_t argc =
+        InterpreterHelpers::ArgDescArgCount(argdesc_) + receiver_idx;
+
+    RawObject* receiver = FrameArguments(FP, argc)[receiver_idx];
+
+    // Invoke field getter on receiver.
+    {
+      SP[1] = argdesc_;                // Save argdesc_.
+      SP[2] = 0;                       // Result of runtime call.
+      SP[3] = receiver;                // Receiver.
+      SP[4] = function->ptr()->name_;  // Field name.
+      Exit(thread, FP, SP + 5, pc);
+      NativeArguments native_args(thread, 2, SP + 3, SP + 2);
+      if (!InvokeRuntime(thread, this, DRT_GetFieldForDispatch, native_args)) {
+        HANDLE_EXCEPTION;
+      }
+      argdesc_ = Array::RawCast(SP[1]);
     }
 
-    *++SP = null_value;
-    *++SP = args[receiver_idx];  // Closure object.
-    *++SP = argdesc_;
-    *++SP = null_value;  // Array of arguments (will be filled).
+    // Replace receiver with field value, keep all other arguments, and
+    // invoke 'call' function, or if not found, invoke noSuchMethod.
+    FrameArguments(FP, argc)[receiver_idx] = receiver = SP[2];
+
+    // If the field value is a closure, no need to resolve 'call' function.
+    if (InterpreterHelpers::GetClassId(receiver) == kClosureCid) {
+      SP[1] = Closure::RawCast(receiver)->ptr()->function_;
+      goto TailCallSP1;
+    }
+
+    // Otherwise, call runtime to resolve 'call' function.
+    {
+      SP[1] = 0;  // Result slot.
+      SP[2] = receiver;
+      SP[3] = argdesc_;
+      Exit(thread, FP, SP + 4, pc);
+      NativeArguments native_args(thread, 2, SP + 2, SP + 1);
+      if (!InvokeRuntime(thread, this, DRT_ResolveCallFunction, native_args)) {
+        HANDLE_EXCEPTION;
+      }
+      argdesc_ = Array::RawCast(SP[3]);
+      function = Function::RawCast(SP[1]);
+      receiver = SP[2];
+    }
+
+    if (function != Function::null()) {
+      SP[1] = function;
+      goto TailCallSP1;
+    }
+
+    // Function 'call' could not be resolved for argdesc_.
+    // Invoke noSuchMethod.
+    RawObject* null_value = Object::null();
+    SP[1] = null_value;
+    SP[2] = receiver;
+    SP[3] = argdesc_;
+    SP[4] = null_value;  // Array of arguments (will be filled).
 
     // Allocate array of arguments.
     {
-      SP[1] = Smi::New(argc);  // length
-      SP[2] = null_value;      // type
-      Exit(thread, FP, SP + 3, pc);
-      NativeArguments native_args(thread, 2, SP + 1, SP);
+      SP[5] = Smi::New(argc);  // length
+      SP[6] = null_value;      // type
+      Exit(thread, FP, SP + 7, pc);
+      NativeArguments native_args(thread, 2, SP + 5, SP + 4);
       if (!InvokeRuntime(thread, this, DRT_AllocateArray, native_args)) {
         HANDLE_EXCEPTION;
-      } else if (has_dart_caller) {
-        HANDLE_RETURN;
+      }
+    }
+
+    // Copy arguments into the newly allocated array.
+    RawObject** argv = FrameArguments(FP, argc);
+    RawArray* array = static_cast<RawArray*>(SP[4]);
+    ASSERT(array->GetClassId() == kArrayCid);
+    for (intptr_t i = 0; i < argc; i++) {
+      array->ptr()->data()[i] = argv[i];
+    }
+
+    // We failed to resolve 'call' function.
+    SP[5] = Symbols::Call().raw();
+
+    // Invoke noSuchMethod passing down receiver, argument descriptor,
+    // array of arguments, and target name.
+    {
+      Exit(thread, FP, SP + 6, pc);
+      NativeArguments native_args(thread, 4, SP + 2, SP + 1);
+      if (!InvokeRuntime(thread, this, DRT_InvokeNoSuchMethod, native_args)) {
+        HANDLE_EXCEPTION;
+      }
+
+      ++SP;  // Result at SP[0]
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE_NEW(VMInternal_ForwardDynamicInvocation, 0);
+    RawFunction* function = FrameFunction(FP);
+    ASSERT(Function::kind(function) ==
+           RawFunction::kDynamicInvocationForwarder);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE_NEW(VMInternal_NoSuchMethodDispatcher, 0);
+    RawFunction* function = FrameFunction(FP);
+    ASSERT(Function::kind(function) == RawFunction::kNoSuchMethodDispatcher);
+    goto NoSuchMethodFromPrologue;
+  }
+
+  {
+    BYTECODE_NEW(VMInternal_ImplicitStaticClosure, 0);
+    RawFunction* function = FrameFunction(FP);
+    ASSERT(Function::kind(function) == RawFunction::kImplicitClosureFunction);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE_NEW(VMInternal_ImplicitInstanceClosure, 0);
+    RawFunction* function = FrameFunction(FP);
+    ASSERT(Function::kind(function) == RawFunction::kImplicitClosureFunction);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+  TailCallSP1:
+    RawFunction* function = Function::RawCast(SP[1]);
+
+    for (;;) {
+      if (Function::HasBytecode(function)) {
+        ASSERT(function->IsFunction());
+        RawBytecode* bytecode = function->ptr()->bytecode_;
+        ASSERT(bytecode->IsBytecode());
+        FP[kKBCFunctionSlotFromFp] = function;
+        FP[kKBCPcMarkerSlotFromFp] = bytecode;
+        pp_ = bytecode->ptr()->object_pool_;
+        pc = reinterpret_cast<const KBCInstr*>(bytecode->ptr()->instructions_);
+        NOT_IN_PRODUCT(pc_ = pc);  // For the profiler.
+        DISPATCH();
+      }
+
+      if (Function::HasCode(function)) {
+        const intptr_t type_args_len =
+            InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
+        const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
+        const intptr_t argc =
+            InterpreterHelpers::ArgDescArgCount(argdesc_) + receiver_idx;
+        RawObject** argv = FrameArguments(FP, argc);
+        for (intptr_t i = 0; i < argc; i++) {
+          *++SP = argv[i];
+        }
+
+        RawObject** call_base = SP - argc + 1;
+        RawObject** call_top = SP + 1;
+        call_top[0] = function;
+        if (!InvokeCompiled(thread, function, call_base, call_top, &pc, &FP,
+                            &SP)) {
+          HANDLE_EXCEPTION;
+        } else {
+          HANDLE_RETURN;
+        }
+        DISPATCH();
+      }
+
+      // Compile the function to either generate code or load bytecode.
+      SP[1] = argdesc_;
+      SP[2] = 0;  // Code result.
+      SP[3] = function;
+      Exit(thread, FP, SP + 4, pc);
+      NativeArguments native_args(thread, 1, /* argv */ SP + 3,
+                                  /* retval */ SP + 2);
+      if (!InvokeRuntime(thread, this, DRT_CompileFunction, native_args)) {
+        HANDLE_EXCEPTION;
+      }
+      function = Function::RawCast(SP[3]);
+      argdesc_ = Array::RawCast(SP[1]);
+
+      ASSERT(Function::HasCode(function) || Function::HasBytecode(function));
+    }
+  }
+
+  // Helper used to handle noSuchMethod on closures.
+  {
+  NoSuchMethodFromPrologue:
+    RawFunction* function = FrameFunction(FP);
+
+    const intptr_t type_args_len =
+        InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
+    const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
+    const intptr_t argc =
+        InterpreterHelpers::ArgDescArgCount(argdesc_) + receiver_idx;
+    RawObject** args = FrameArguments(FP, argc);
+
+    SP[1] = null_value;
+    SP[2] = args[receiver_idx];
+    SP[3] = function;
+    SP[4] = argdesc_;
+    SP[5] = null_value;  // Array of arguments (will be filled).
+
+    // Allocate array of arguments.
+    {
+      SP[6] = Smi::New(argc);  // length
+      SP[7] = null_value;      // type
+      Exit(thread, FP, SP + 8, pc);
+      NativeArguments native_args(thread, 2, SP + 6, SP + 5);
+      if (!InvokeRuntime(thread, this, DRT_AllocateArray, native_args)) {
+        HANDLE_EXCEPTION;
       }
 
       // Copy arguments into the newly allocated array.
-      RawArray* array = static_cast<RawArray*>(SP[0]);
+      RawArray* array = static_cast<RawArray*>(SP[5]);
       ASSERT(array->GetClassId() == kArrayCid);
       for (intptr_t i = 0; i < argc; i++) {
         array->ptr()->data()[i] = args[i];
       }
     }
 
-    // Invoke noSuchMethod passing down closure, argument descriptor and
-    // array of arguments.
+    // Invoke noSuchMethod passing down receiver, function, argument descriptor
+    // and array of arguments.
     {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments native_args(thread, 3, SP - 2, SP - 3);
-      INVOKE_RUNTIME(DRT_InvokeClosureNoSuchMethod, native_args);
-      UNREACHABLE();
+      Exit(thread, FP, SP + 6, pc);
+      NativeArguments native_args(thread, 4, SP + 2, SP + 1);
+      INVOKE_RUNTIME(DRT_NoSuchMethodFromPrologue, native_args);
+      ++SP;  // Result at SP[0]
     }
 
     DISPATCH();
@@ -3506,9 +3690,9 @@
     thread->set_active_stacktrace(Object::null_object());
     special_[KernelBytecode::kExceptionSpecialIndex] = raw_exception;
     special_[KernelBytecode::kStackTraceSpecialIndex] = raw_stacktrace;
-    pc_ = reinterpret_cast<uint32_t*>(thread->resume_pc());
+    pc_ = reinterpret_cast<const KBCInstr*>(thread->resume_pc());
   } else {
-    pc_ = reinterpret_cast<uint32_t*>(pc);
+    pc_ = reinterpret_cast<const KBCInstr*>(pc);
   }
 
   // Set the tag.
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index e8fe9db..a47eecc 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -96,7 +96,7 @@
   }
 
   // Identify an entry frame by looking at its pc marker value.
-  static bool IsEntryFrameMarker(uint32_t* pc) {
+  static bool IsEntryFrameMarker(const KBCInstr* pc) {
     return reinterpret_cast<word>(pc) == kEntryFramePcMarker;
   }
 
@@ -122,6 +122,11 @@
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
   void MajorGC() { lookup_cache_.Clear(); }
 
+#ifndef PRODUCT
+  void set_is_debugging(bool value) { is_debugging_ = value; }
+  bool is_debugging() const { return is_debugging_; }
+#endif  // !PRODUCT
+
  private:
   uintptr_t* stack_;
   uword stack_base_;
@@ -129,7 +134,7 @@
   uword stack_limit_;
 
   RawObject** volatile fp_;
-  uint32_t* volatile pc_;
+  const KBCInstr* volatile pc_;
   DEBUG_ONLY(uint64_t icount_;)
 
   InterpreterSetjmpBuffer* last_setjmp_buffer_;
@@ -144,29 +149,28 @@
   void Exit(Thread* thread,
             RawObject** base,
             RawObject** exit_frame,
-            uint32_t* pc);
+            const KBCInstr* pc);
 
   bool Invoke(Thread* thread,
               RawObject** call_base,
               RawObject** call_top,
-              uint32_t** pc,
+              const KBCInstr** pc,
               RawObject*** FP,
               RawObject*** SP);
 
-  bool ProcessInvocation(bool* invoked,
-                         Thread* thread,
-                         RawFunction* function,
-                         RawObject** call_base,
-                         RawObject** call_top,
-                         uint32_t** pc,
-                         RawObject*** FP,
-                         RawObject*** SP);
-
   bool InvokeCompiled(Thread* thread,
                       RawFunction* function,
                       RawObject** call_base,
                       RawObject** call_top,
-                      uint32_t** pc,
+                      const KBCInstr** pc,
+                      RawObject*** FP,
+                      RawObject*** SP);
+
+  bool InvokeBytecode(Thread* thread,
+                      RawFunction* function,
+                      RawObject** call_base,
+                      RawObject** call_top,
+                      const KBCInstr** pc,
                       RawObject*** FP,
                       RawObject*** SP);
 
@@ -175,7 +179,7 @@
                        RawICData* icdata,
                        RawObject** call_base,
                        RawObject** top,
-                       uint32_t* pc,
+                       const KBCInstr* pc,
                        RawObject** FP,
                        RawObject** SP);
 
@@ -183,7 +187,7 @@
                      RawString* target_name,
                      RawObject** call_base,
                      RawObject** call_top,
-                     uint32_t** pc,
+                     const KBCInstr** pc,
                      RawObject*** FP,
                      RawObject*** SP);
 
@@ -191,7 +195,7 @@
                      RawICData* icdata,
                      RawObject** call_base,
                      RawObject** call_top,
-                     uint32_t** pc,
+                     const KBCInstr** pc,
                      RawObject*** FP,
                      RawObject*** SP,
                      bool optimized);
@@ -200,13 +204,13 @@
                      RawICData* icdata,
                      RawObject** call_base,
                      RawObject** call_top,
-                     uint32_t** pc,
+                     const KBCInstr** pc,
                      RawObject*** FP,
                      RawObject*** SP,
                      bool optimized);
 
   bool AssertAssignable(Thread* thread,
-                        uint32_t* pc,
+                        const KBCInstr* pc,
                         RawObject** FP,
                         RawObject** call_top,
                         RawObject** args,
@@ -214,37 +218,37 @@
 
   bool AllocateMint(Thread* thread,
                     int64_t value,
-                    uint32_t* pc,
+                    const KBCInstr* pc,
                     RawObject** FP,
                     RawObject** SP);
   bool AllocateDouble(Thread* thread,
                       double value,
-                      uint32_t* pc,
+                      const KBCInstr* pc,
                       RawObject** FP,
                       RawObject** SP);
   bool AllocateFloat32x4(Thread* thread,
                          simd128_value_t value,
-                         uint32_t* pc,
+                         const KBCInstr* pc,
                          RawObject** FP,
                          RawObject** SP);
   bool AllocateFloat64x2(Thread* thread,
                          simd128_value_t value,
-                         uint32_t* pc,
+                         const KBCInstr* pc,
                          RawObject** FP,
                          RawObject** SP);
   bool AllocateArray(Thread* thread,
                      RawTypeArguments* type_args,
                      RawObject* length,
-                     uint32_t* pc,
+                     const KBCInstr* pc,
                      RawObject** FP,
                      RawObject** SP);
   bool AllocateContext(Thread* thread,
                        intptr_t num_variables,
-                       uint32_t* pc,
+                       const KBCInstr* pc,
                        RawObject** FP,
                        RawObject** SP);
   bool AllocateClosure(Thread* thread,
-                       uint32_t* pc,
+                       const KBCInstr* pc,
                        RawObject** FP,
                        RawObject** SP);
 
@@ -253,11 +257,11 @@
   bool IsTracingExecution() const;
 
   // Prints bytecode instruction at given pc for instruction tracing.
-  void TraceInstruction(uint32_t* pc) const;
+  void TraceInstruction(const KBCInstr* pc) const;
 
   bool IsWritingTraceFile() const;
   void FlushTraceBuffer();
-  void WriteInstructionToTrace(uint32_t* pc);
+  void WriteInstructionToTrace(const KBCInstr* pc);
 
   void* trace_file_;
   uint64_t trace_file_bytes_written_;
@@ -275,6 +279,10 @@
     last_setjmp_buffer_ = buffer;
   }
 
+#ifndef PRODUCT
+  bool is_debugging_;
+#endif  // !PRODUCT
+
   friend class InterpreterSetjmpBuffer;
   DISALLOW_COPY_AND_ASSIGN(Interpreter);
 };
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 49caa27..e68d40c 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2,6 +2,8 @@
 // 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 <utility>
+
 #include "vm/isolate.h"
 
 #include "include/dart_api.h"
@@ -69,7 +71,6 @@
 static void DeterministicModeHandler(bool value) {
   if (value) {
     FLAG_background_compilation = false;  // Timing dependent.
-    FLAG_collect_code = false;            // Timing dependent.
     FLAG_concurrent_mark = false;         // Timing dependent.
     FLAG_concurrent_sweep = false;        // Timing dependent.
     FLAG_random_seed = 0x44617274;  // "Dart"
@@ -104,9 +105,10 @@
 };
 #endif
 
-static Message* SerializeMessage(Dart_Port dest_port, const Instance& obj) {
+static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
+                                                 const Instance& obj) {
   if (ApiObjectConverter::CanConvert(obj.raw())) {
-    return new Message(dest_port, obj.raw(), Message::kNormalPriority);
+    return Message::New(dest_port, obj.raw(), Message::kNormalPriority);
   } else {
     MessageWriter writer(false);
     return writer.WriteMessage(obj, dest_port, Message::kNormalPriority);
@@ -239,7 +241,7 @@
 
   const char* name() const;
   void MessageNotify(Message::Priority priority);
-  MessageStatus HandleMessage(Message* message);
+  MessageStatus HandleMessage(std::unique_ptr<Message> message);
 #ifndef PRODUCT
   void NotifyPauseOnStart();
   void NotifyPauseOnExit();
@@ -395,6 +397,31 @@
       I->heap()->NotifyLowMemory();
       break;
     }
+    case Isolate::kDrainServiceExtensionsMsg: {
+#ifndef PRODUCT
+      Object& obj = Object::Handle(zone, message.At(2));
+      if (!obj.IsSmi()) return Error::null();
+      const intptr_t priority = Smi::Cast(obj).Value();
+      if (priority == Isolate::kImmediateAction) {
+        return I->InvokePendingServiceExtensionCalls();
+      } else {
+        ASSERT((priority == Isolate::kBeforeNextEventAction) ||
+               (priority == Isolate::kAsEventAction));
+        // Update the message so that it will be handled immediately when it
+        // is picked up from the message queue the next time.
+        message.SetAt(
+            0, Smi::Handle(zone, Smi::New(Message::kDelayedIsolateLibOOBMsg)));
+        message.SetAt(2,
+                      Smi::Handle(zone, Smi::New(Isolate::kImmediateAction)));
+        this->PostMessage(
+            SerializeMessage(Message::kIllegalPort, message),
+            priority == Isolate::kBeforeNextEventAction /* at_head */);
+      }
+#else
+      UNREACHABLE();
+#endif  // !PRODUCT
+      break;
+    }
 
     case Isolate::kAddExitMsg:
     case Isolate::kDelExitMsg:
@@ -450,7 +477,7 @@
 #if defined(DEBUG)
     // Malformed OOB messages are silently ignored in release builds.
     default:
-      UNREACHABLE();
+      FATAL1("Unknown OOB message type: %" Pd "\n", msg_type);
       break;
 #endif  // defined(DEBUG)
   }
@@ -474,7 +501,7 @@
 }
 
 MessageHandler::MessageStatus IsolateMessageHandler::HandleMessage(
-    Message* message) {
+    std::unique_ptr<Message> message) {
   ASSERT(IsCurrentIsolate());
   Thread* thread = Thread::Current();
   StackZone stack_zone(thread);
@@ -496,16 +523,13 @@
   if (!message->IsOOB() && (message->dest_port() != Message::kIllegalPort)) {
     msg_handler = DartLibraryCalls::LookupHandler(message->dest_port());
     if (msg_handler.IsError()) {
-      delete message;
       return ProcessUnhandledException(Error::Cast(msg_handler));
     }
     if (msg_handler.IsNull()) {
       // If the port has been closed then the message will be dropped at this
       // point. Make sure to post to the delivery failure port in that case.
       if (message->RedirectToDeliveryFailurePort()) {
-        PortMap::PostMessage(message);
-      } else {
-        delete message;
+        PortMap::PostMessage(std::move(message));
       }
       return kOK;
     }
@@ -518,12 +542,11 @@
     // We should only be sending RawObjects that can be converted to CObjects.
     ASSERT(ApiObjectConverter::CanConvert(msg_obj.raw()));
   } else {
-    MessageSnapshotReader reader(message, thread);
+    MessageSnapshotReader reader(message.get(), thread);
     msg_obj = reader.ReadObject();
   }
   if (msg_obj.IsError()) {
     // An error occurred while reading the message.
-    delete message;
     return ProcessUnhandledException(Error::Cast(msg_obj));
   }
   if (!msg_obj.IsNull() && !msg_obj.IsInstance()) {
@@ -615,18 +638,6 @@
       ASSERT(result.IsNull());
     }
   }
-  delete message;
-#ifndef PRODUCT
-  if (status == kOK) {
-    const Object& result =
-        Object::Handle(zone, I->InvokePendingServiceExtensionCalls());
-    if (result.IsError()) {
-      status = ProcessUnhandledException(Error::Cast(result));
-    } else {
-      ASSERT(result.IsNull());
-    }
-  }
-#endif  // !PRODUCT
   return status;
 }
 
@@ -848,95 +859,57 @@
 #define REUSABLE_HANDLE_SCOPE_INIT(object)
 #endif  // defined(DEBUG)
 
-#define REUSABLE_HANDLE_INITIALIZERS(object) object##_handle_(NULL),
+#define REUSABLE_HANDLE_INITIALIZERS(object) object##_handle_(nullptr),
 
 // TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with
 // that shared monitor.
 Isolate::Isolate(const Dart_IsolateFlags& api_flags)
     : BaseIsolate(),
-      user_tag_(0),
       current_tag_(UserTag::null()),
       default_tag_(UserTag::null()),
       ic_miss_code_(Code::null()),
-      object_store_(NULL),
       class_table_(),
-      single_step_(false),
       store_buffer_(new StoreBuffer()),
-      marking_stack_(NULL),
-      heap_(NULL),
-      isolate_flags_(0),
-      background_compiler_(NULL),
-      optimizing_background_compiler_(NULL),
 #if !defined(PRODUCT)
-      debugger_(NULL),
       last_resume_timestamp_(OS::GetCurrentTimeMillis()),
-      last_allocationprofile_accumulator_reset_timestamp_(0),
-      last_allocationprofile_gc_timestamp_(0),
       vm_tag_counters_(),
       pending_service_extension_calls_(GrowableObjectArray::null()),
       registered_service_extension_handlers_(GrowableObjectArray::null()),
-      metrics_list_head_(NULL),
-      pause_loop_monitor_(NULL),
 #define ISOLATE_METRIC_CONSTRUCTORS(type, variable, name, unit)                \
   metric_##variable##_(),
       ISOLATE_METRIC_LIST(ISOLATE_METRIC_CONSTRUCTORS)
 #undef ISOLATE_METRIC_CONSTRUCTORS
-          no_reload_scope_depth_(0),
-      reload_every_n_stack_overflow_checks_(FLAG_reload_every),
-      reload_context_(NULL),
+          reload_every_n_stack_overflow_checks_(FLAG_reload_every),
       last_reload_timestamp_(OS::GetCurrentTimeMillis()),
-      object_id_ring_(NULL),
 #endif  // !defined(PRODUCT)
       start_time_micros_(OS::GetCurrentMonotonicMicros()),
       thread_registry_(new ThreadRegistry()),
       safepoint_handler_(new SafepointHandler(this)),
-      message_notify_callback_(NULL),
-      name_(NULL),
-      main_port_(0),
-      origin_id_(0),
-      pause_capability_(0),
-      terminate_capability_(0),
-      init_callback_data_(NULL),
-      environment_callback_(NULL),
-      library_tag_handler_(NULL),
-      api_state_(NULL),
       random_(),
-      simulator_(NULL),
-      mutex_(new Mutex(NOT_IN_PRODUCT("Isolate::mutex_"))),
-      symbols_mutex_(new Mutex(NOT_IN_PRODUCT("Isolate::symbols_mutex_"))),
+      mutex_(NOT_IN_PRODUCT("Isolate::mutex_")),
+      symbols_mutex_(NOT_IN_PRODUCT("Isolate::symbols_mutex_")),
       type_canonicalization_mutex_(
-          new Mutex(NOT_IN_PRODUCT("Isolate::type_canonicalization_mutex_"))),
-      constant_canonicalization_mutex_(new Mutex(
-          NOT_IN_PRODUCT("Isolate::constant_canonicalization_mutex_"))),
+          NOT_IN_PRODUCT("Isolate::type_canonicalization_mutex_")),
+      constant_canonicalization_mutex_(
+          NOT_IN_PRODUCT("Isolate::constant_canonicalization_mutex_")),
       megamorphic_lookup_mutex_(
-          new Mutex(NOT_IN_PRODUCT("Isolate::megamorphic_lookup_mutex_"))),
+          NOT_IN_PRODUCT("Isolate::megamorphic_lookup_mutex_")),
       kernel_data_lib_cache_mutex_(
-          new Mutex(NOT_IN_PRODUCT("Isolate::kernel_data_lib_cache_mutex_"))),
+          NOT_IN_PRODUCT("Isolate::kernel_data_lib_cache_mutex_")),
       kernel_data_class_cache_mutex_(
-          new Mutex(NOT_IN_PRODUCT("Isolate::kernel_data_class_cache_mutex_"))),
+          NOT_IN_PRODUCT("Isolate::kernel_data_class_cache_mutex_")),
       kernel_constants_mutex_(
-          new Mutex(NOT_IN_PRODUCT("Isolate::kernel_constants_mutex_"))),
-      message_handler_(NULL),
-      spawn_state_(NULL),
-      defer_finalization_count_(0),
+          NOT_IN_PRODUCT("Isolate::kernel_constants_mutex_")),
       pending_deopts_(new MallocGrowableArray<PendingLazyDeopt>()),
-      deopt_context_(NULL),
       tag_table_(GrowableObjectArray::null()),
       deoptimized_code_array_(GrowableObjectArray::null()),
       sticky_error_(Error::null()),
       reloaded_kernel_blobs_(GrowableObjectArray::null()),
-      next_(NULL),
-      loading_invalidation_gen_(kInvalidGen),
-      field_list_mutex_(
-          new Mutex(NOT_IN_PRODUCT("Isolate::field_list_mutex_"))),
+      field_list_mutex_(NOT_IN_PRODUCT("Isolate::field_list_mutex_")),
       boxed_field_list_(GrowableObjectArray::null()),
-      spawn_count_monitor_(new Monitor()),
-      spawn_count_(0),
+      spawn_count_monitor_(),
       handler_info_cache_(),
-      catch_entry_moves_cache_(),
-      embedder_entry_points_(NULL),
-      obfuscation_map_(NULL),
-      reverse_pc_lookup_cache_(nullptr) {
+      catch_entry_moves_cache_() {
   FlagsCopyFrom(api_flags);
   SetErrorsFatal(true);
   set_compilation_allowed(true);
@@ -973,70 +946,54 @@
 
   if (FLAG_enable_interpreter) {
     delete background_compiler_;
-    background_compiler_ = NULL;
+    background_compiler_ = nullptr;
   }
 
   delete optimizing_background_compiler_;
-  optimizing_background_compiler_ = NULL;
+  optimizing_background_compiler_ = nullptr;
 
 #if !defined(PRODUCT)
   delete debugger_;
-  debugger_ = NULL;
+  debugger_ = nullptr;
   if (FLAG_support_service) {
     delete object_id_ring_;
   }
-  object_id_ring_ = NULL;
+  object_id_ring_ = nullptr;
   delete pause_loop_monitor_;
-  pause_loop_monitor_ = NULL;
+  pause_loop_monitor_ = nullptr;
 #endif  // !defined(PRODUCT)
 
   free(name_);
   delete store_buffer_;
   delete heap_;
-  ASSERT(marking_stack_ == NULL);
+  ASSERT(marking_stack_ == nullptr);
   delete object_store_;
   delete api_state_;
 #if defined(USING_SIMULATOR)
   delete simulator_;
 #endif
-  delete mutex_;
-  mutex_ = NULL;  // Fail fast if interrupts are scheduled on a dead isolate.
-  delete symbols_mutex_;
-  symbols_mutex_ = NULL;
-  delete type_canonicalization_mutex_;
-  type_canonicalization_mutex_ = NULL;
-  delete constant_canonicalization_mutex_;
-  constant_canonicalization_mutex_ = NULL;
-  delete megamorphic_lookup_mutex_;
-  megamorphic_lookup_mutex_ = NULL;
-  delete kernel_constants_mutex_;
-  kernel_constants_mutex_ = nullptr;
-  delete kernel_data_lib_cache_mutex_;
-  kernel_data_lib_cache_mutex_ = NULL;
-  delete kernel_data_class_cache_mutex_;
-  kernel_data_class_cache_mutex_ = NULL;
   delete pending_deopts_;
-  pending_deopts_ = NULL;
+  pending_deopts_ = nullptr;
   delete message_handler_;
-  message_handler_ = NULL;  // Fail fast if we send messages to a dead isolate.
-  ASSERT(deopt_context_ == NULL);  // No deopt in progress when isolate deleted.
+  message_handler_ =
+      nullptr;  // Fail fast if we send messages to a dead isolate.
+  ASSERT(deopt_context_ ==
+         nullptr);  // No deopt in progress when isolate deleted.
   delete spawn_state_;
-  delete field_list_mutex_;
-  field_list_mutex_ = NULL;
   ASSERT(spawn_count_ == 0);
-  delete spawn_count_monitor_;
   delete safepoint_handler_;
   delete thread_registry_;
 
-  if (obfuscation_map_ != NULL) {
-    for (intptr_t i = 0; obfuscation_map_[i] != NULL; i++) {
+  if (obfuscation_map_ != nullptr) {
+    for (intptr_t i = 0; obfuscation_map_[i] != nullptr; i++) {
       delete[] obfuscation_map_[i];
     }
     delete[] obfuscation_map_;
   }
 
-  if (embedder_entry_points_ != NULL) {
-    for (intptr_t i = 0; embedder_entry_points_[i].function_name != NULL; i++) {
+  if (embedder_entry_points_ != nullptr) {
+    for (intptr_t i = 0; embedder_entry_points_[i].function_name != nullptr;
+         i++) {
       free(const_cast<char*>(embedder_entry_points_[i].library_uri));
       free(const_cast<char*>(embedder_entry_points_[i].class_name));
       free(const_cast<char*>(embedder_entry_points_[i].function_name));
@@ -1046,11 +1003,11 @@
 }
 
 void Isolate::InitVM() {
-  create_callback_ = NULL;
-  if (isolates_list_monitor_ == NULL) {
+  create_callback_ = nullptr;
+  if (isolates_list_monitor_ == nullptr) {
     isolates_list_monitor_ = new Monitor();
   }
-  ASSERT(isolates_list_monitor_ != NULL);
+  ASSERT(isolates_list_monitor_ != nullptr);
   EnableIsolateCreation();
 }
 
@@ -1058,7 +1015,7 @@
                               const Dart_IsolateFlags& api_flags,
                               bool is_vm_isolate) {
   Isolate* result = new Isolate(api_flags);
-  ASSERT(result != NULL);
+  ASSERT(result != nullptr);
 
 #if !defined(PRODUCT)
 // Initialize metrics.
@@ -1095,23 +1052,23 @@
     // We failed to enter the isolate, it is possible the VM is shutting down,
     // return back a NULL so that CreateIsolate reports back an error.
     if (KernelIsolate::IsKernelIsolate(result)) {
-      KernelIsolate::SetKernelIsolate(NULL);
+      KernelIsolate::SetKernelIsolate(nullptr);
     }
     if (ServiceIsolate::IsServiceIsolate(result)) {
-      ServiceIsolate::SetServiceIsolate(NULL);
+      ServiceIsolate::SetServiceIsolate(nullptr);
     }
     delete result;
-    return NULL;
+    return nullptr;
   }
 
   // Setup the isolate message handler.
   MessageHandler* handler = new IsolateMessageHandler(result);
-  ASSERT(handler != NULL);
+  ASSERT(handler != nullptr);
   result->set_message_handler(handler);
 
   // Setup the Dart API state.
   ApiState* state = new ApiState();
-  ASSERT(state != NULL);
+  ASSERT(state != nullptr);
   result->set_api_state(state);
 
   result->set_main_port(PortMap::CreatePort(result->message_handler()));
@@ -1129,7 +1086,7 @@
   result->debugger_ = new Debugger(result);
 #endif
   if (FLAG_trace_isolates) {
-    if (name_prefix == NULL || strcmp(name_prefix, "vm-isolate") != 0) {
+    if (name_prefix == nullptr || strcmp(name_prefix, "vm-isolate") != 0) {
       OS::PrintErr(
           "[+] Starting isolate:\n"
           "\tisolate:    %s\n",
@@ -1148,13 +1105,13 @@
     result->LowLevelShutdown();
     Thread::ExitIsolate();
     if (KernelIsolate::IsKernelIsolate(result)) {
-      KernelIsolate::SetKernelIsolate(NULL);
+      KernelIsolate::SetKernelIsolate(nullptr);
     }
     if (ServiceIsolate::IsServiceIsolate(result)) {
-      ServiceIsolate::SetServiceIsolate(NULL);
+      ServiceIsolate::SetServiceIsolate(nullptr);
     }
     delete result;
-    return NULL;
+    return nullptr;
   }
 
   return result;
@@ -1169,7 +1126,7 @@
 }
 
 Thread* Isolate::mutator_thread() const {
-  ASSERT(thread_registry() != NULL);
+  ASSERT(thread_registry() != nullptr);
   return thread_registry()->mutator_thread();
 }
 
@@ -1199,7 +1156,7 @@
   // exit the isolate while we are trying to schedule interrupts on it.
   MonitorLocker ml(threads_lock());
   Thread* mthread = mutator_thread();
-  if (mthread != NULL) {
+  if (mthread != nullptr) {
     mthread->ScheduleInterrupts(interrupt_bits);
   }
 }
@@ -1217,13 +1174,13 @@
 #if defined(PRODUCT)
   return false;
 #else
-  return (debugger_ != NULL) && (debugger_->PauseEvent() != NULL);
+  return (debugger_ != nullptr) && (debugger_->PauseEvent() != nullptr);
 #endif  // !defined(PRODUCT)
 }
 
 RawError* Isolate::PausePostRequest() {
 #if !defined(PRODUCT)
-  if (debugger_ == NULL) {
+  if (debugger_ == nullptr) {
     return Error::null();
   }
   ASSERT(!IsPaused());
@@ -1241,9 +1198,9 @@
 }
 
 void Isolate::BuildName(const char* name_prefix) {
-  ASSERT(name_ == NULL);
-  if (name_prefix == NULL) {
-    name_ = OS::SCreate(NULL, "isolate-%" Pd64 "", main_port());
+  ASSERT(name_ == nullptr);
+  if (name_prefix == nullptr) {
+    name_ = OS::SCreate(nullptr, "isolate-%" Pd64 "", main_port());
   } else {
     name_ = strdup(name_prefix);
   }
@@ -1282,7 +1239,7 @@
   SetHasAttemptedReload(true);
   reload_context_ = new IsolateReloadContext(this, js);
   reload_context_->Reload(force_reload, root_script_url, packages_url,
-                          /* kernel_buffer= */ NULL,
+                          /* kernel_buffer= */ nullptr,
                           /* kernel_buffer_size= */ 0);
   bool success = !reload_context_->reload_aborted();
   if (!dont_delete_reload_context) {
@@ -1300,8 +1257,8 @@
   SetHasAttemptedReload(true);
   reload_context_ = new IsolateReloadContext(this, js);
   reload_context_->Reload(force_reload,
-                          /* root_script_url= */ NULL,
-                          /* packages_url= */ NULL, kernel_buffer,
+                          /* root_script_url= */ nullptr,
+                          /* packages_url= */ nullptr, kernel_buffer,
                           kernel_buffer_size);
   bool success = !reload_context_->reload_aborted();
   if (!dont_delete_reload_context) {
@@ -1316,7 +1273,7 @@
   SafepointOperationScope safepoint_scope(thread);
 
   delete reload_context_;
-  reload_context_ = NULL;
+  reload_context_ = nullptr;
 }
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -1329,9 +1286,9 @@
 }
 
 const char* Isolate::MakeRunnable() {
-  ASSERT(Isolate::Current() == NULL);
+  ASSERT(Isolate::Current() == nullptr);
 
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   // Check if we are in a valid state to make the isolate runnable.
   if (is_runnable() == true) {
     return "Isolate is already runnable";
@@ -1349,15 +1306,15 @@
   }
 #endif  // !PRODUCT
   IsolateSpawnState* state = spawn_state();
-  if (state != NULL) {
+  if (state != nullptr) {
     ASSERT(this == state->isolate());
     Run();
   }
 #if defined(SUPPORT_TIMELINE)
   TimelineStream* stream = Timeline::GetIsolateStream();
-  ASSERT(stream != NULL);
+  ASSERT(stream != nullptr);
   TimelineEvent* event = stream->StartEvent();
-  if (event != NULL) {
+  if (event != nullptr) {
     event->Instant("Runnable");
     event->Complete();
   }
@@ -1379,7 +1336,7 @@
     GetRunnableHeapSizeMetric()->set_value(heap_size);
   }
 #endif  // !PRODUCT
-  return NULL;
+  return nullptr;
 }
 
 bool Isolate::VerifyPauseCapability(const Object& capability) const {
@@ -1394,7 +1351,8 @@
 
 bool Isolate::AddResumeCapability(const Capability& capability) {
   // Ensure a limit for the number of resume capabilities remembered.
-  static const intptr_t kMaxResumeCapabilities = kSmiMax / (6 * kWordSize);
+  static const intptr_t kMaxResumeCapabilities =
+      compiler::target::kSmiMax / (6 * kWordSize);
 
   const GrowableObjectArray& caps = GrowableObjectArray::Handle(
       current_zone(), object_store()->resume_capabilities());
@@ -1445,7 +1403,8 @@
 void Isolate::AddExitListener(const SendPort& listener,
                               const Instance& response) {
   // Ensure a limit for the number of listeners remembered.
-  static const intptr_t kMaxListeners = kSmiMax / (12 * kWordSize);
+  static const intptr_t kMaxListeners =
+      compiler::target::kSmiMax / (12 * kWordSize);
 
   const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
       current_zone(), object_store()->exit_listeners());
@@ -1512,7 +1471,8 @@
 
 void Isolate::AddErrorListener(const SendPort& listener) {
   // Ensure a limit for the number of listeners remembered.
-  static const intptr_t kMaxListeners = kSmiMax / (6 * kWordSize);
+  static const intptr_t kMaxListeners =
+      compiler::target::kSmiMax / (6 * kWordSize);
 
   const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
       current_zone(), object_store()->error_listeners());
@@ -1578,7 +1538,7 @@
 
 static MessageHandler::MessageStatus RunIsolate(uword parameter) {
   Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
-  IsolateSpawnState* state = NULL;
+  IsolateSpawnState* state = nullptr;
   {
     // TODO(turnidge): Is this locking required here at all anymore?
     MutexLocker ml(isolate->mutex());
@@ -1790,7 +1750,7 @@
   NoSafepointScope no_safepoint_scope;
 
   // Notify exit listeners that this isolate is shutting down.
-  if (object_store() != NULL) {
+  if (object_store() != nullptr) {
     const Error& error = Error::Handle(thread->sticky_error());
     if (error.IsNull() || !error.IsUnwindError() ||
         UnwindError::Cast(error).is_user_initiated()) {
@@ -1808,7 +1768,7 @@
 
   // Fail fast if anybody tries to post any more messages to this isolate.
   delete message_handler();
-  set_message_handler(NULL);
+  set_message_handler(nullptr);
 #if defined(SUPPORT_TIMELINE)
   // Before analyzing the isolate's timeline blocks- reclaim all cached
   // blocks.
@@ -1874,13 +1834,13 @@
   BackgroundCompiler::Stop(this);
   if (FLAG_enable_interpreter) {
     delete background_compiler_;
-    background_compiler_ = NULL;
+    background_compiler_ = nullptr;
   }
   delete optimizing_background_compiler_;
-  optimizing_background_compiler_ = NULL;
+  optimizing_background_compiler_ = nullptr;
 
 #if defined(DEBUG)
-  if (heap_ != NULL && FLAG_verify_on_transition) {
+  if (heap_ != nullptr && FLAG_verify_on_transition) {
     // The VM isolate keeps all objects marked.
     heap_->Verify(this == Dart::vm_isolate() ? kRequireMarked : kForbidMarked);
   }
@@ -1903,7 +1863,7 @@
     KernelIsolate::NotifyAboutIsolateShutdown(this);
   }
 
-  if (heap_ != NULL) {
+  if (heap_ != nullptr) {
     // Wait for any concurrent GC tasks to finish before shutting down.
     // TODO(rmacnak): Interrupt tasks for faster shutdown.
     PageSpace* old_space = heap_->old_space();
@@ -1933,7 +1893,7 @@
 
 #if defined(DEBUG)
   // No concurrent sweeper tasks should be running at this point.
-  if (heap_ != NULL) {
+  if (heap_ != nullptr) {
     PageSpace* old_space = heap_->old_space();
     MonitorLocker ml(old_space->tasks_lock());
     ASSERT(old_space->tasks() == 0);
@@ -1945,22 +1905,22 @@
   Thread::ExitIsolate();
 
   Dart_IsolateCleanupCallback cleanup = Isolate::CleanupCallback();
-  if (cleanup != NULL) {
+  if (cleanup != nullptr) {
     cleanup(init_callback_data());
   }
 }
 
-Dart_IsolateCreateCallback Isolate::create_callback_ = NULL;
-Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = NULL;
-Dart_IsolateCleanupCallback Isolate::cleanup_callback_ = NULL;
+Dart_IsolateCreateCallback Isolate::create_callback_ = nullptr;
+Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = nullptr;
+Dart_IsolateCleanupCallback Isolate::cleanup_callback_ = nullptr;
 
-Monitor* Isolate::isolates_list_monitor_ = NULL;
-Isolate* Isolate::isolates_list_head_ = NULL;
+Monitor* Isolate::isolates_list_monitor_ = nullptr;
+Isolate* Isolate::isolates_list_head_ = nullptr;
 bool Isolate::creation_enabled_ = false;
 
 void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor,
                                   ValidationPolicy validate_frames) {
-  ASSERT(visitor != NULL);
+  ASSERT(visitor != nullptr);
 
   // Visit objects in the object store.
   object_store()->VisitObjectPointers(visitor);
@@ -1972,7 +1932,7 @@
   StubCode::VisitObjectPointers(visitor);
 
   // Visit the dart api state for all local and persistent handles.
-  if (api_state() != NULL) {
+  if (api_state() != nullptr) {
     api_state()->VisitObjectPointers(visitor);
   }
 
@@ -1997,10 +1957,10 @@
   // when at safepoint or the field_list_mutex_ lock has been taken.
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&boxed_field_list_));
 
-  if (background_compiler() != NULL) {
+  if (background_compiler() != nullptr) {
     background_compiler()->VisitPointers(visitor);
   }
-  if (optimizing_background_compiler() != NULL) {
+  if (optimizing_background_compiler() != nullptr) {
     optimizing_background_compiler()->VisitPointers(visitor);
   }
 
@@ -2009,7 +1969,7 @@
   debugger()->VisitObjectPointers(visitor);
 #if !defined(DART_PRECOMPILED_RUNTIME)
   // Visit objects that are being used for isolate reload.
-  if (reload_context() != NULL) {
+  if (reload_context() != nullptr) {
     reload_context()->VisitObjectPointers(visitor);
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
@@ -2020,13 +1980,13 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   // Visit objects that are being used for deoptimization.
-  if (deopt_context() != NULL) {
+  if (deopt_context() != nullptr) {
     deopt_context()->VisitObjectPointers(visitor);
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 #if defined(TARGET_ARCH_DBC)
-  if (simulator() != NULL) {
+  if (simulator() != nullptr) {
     simulator()->VisitObjectPointers(visitor);
   }
 #endif  // defined(TARGET_ARCH_DBC)
@@ -2041,7 +2001,7 @@
 }
 
 void Isolate::VisitWeakPersistentHandles(HandleVisitor* visitor) {
-  if (api_state() != NULL) {
+  if (api_state() != nullptr) {
     api_state()->VisitWeakHandles(visitor);
   }
 }
@@ -2052,7 +2012,7 @@
 
 void Isolate::EnableIncrementalBarrier(MarkingStack* marking_stack,
                                        MarkingStack* deferred_marking_stack) {
-  ASSERT(marking_stack_ == NULL);
+  ASSERT(marking_stack_ == nullptr);
   marking_stack_ = marking_stack;
   deferred_marking_stack_ = deferred_marking_stack;
   thread_registry()->AcquireMarkingStacks();
@@ -2061,14 +2021,14 @@
 
 void Isolate::DisableIncrementalBarrier() {
   thread_registry()->ReleaseMarkingStacks();
-  ASSERT(marking_stack_ != NULL);
-  marking_stack_ = NULL;
-  deferred_marking_stack_ = NULL;
+  ASSERT(marking_stack_ != nullptr);
+  marking_stack_ = nullptr;
+  deferred_marking_stack_ = nullptr;
   ASSERT(!Thread::Current()->is_marking());
 }
 
 RawClass* Isolate::GetClassForHeapWalkAt(intptr_t cid) {
-  RawClass* raw_class = NULL;
+  RawClass* raw_class = nullptr;
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   if (IsReloading()) {
     raw_class = reload_context()->GetClassForHeapWalkAt(cid);
@@ -2078,7 +2038,7 @@
 #else
   raw_class = class_table()->At(cid);
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
-  ASSERT(raw_class != NULL);
+  ASSERT(raw_class != nullptr);
   ASSERT(remapping_cids() || raw_class->ptr()->id_ == cid);
   return raw_class;
 }
@@ -2142,7 +2102,7 @@
       return "Unhandled";
     default:
       UNIMPLEMENTED();
-      return NULL;
+      return nullptr;
   }
 }
 
@@ -2152,8 +2112,8 @@
   }
   JSONObject jsobj(stream);
   jsobj.AddProperty("type", (ref ? "@Isolate" : "Isolate"));
-  jsobj.AddFixedServiceId(ISOLATE_SERVICE_ID_FORMAT_STRING,
-                          static_cast<int64_t>(main_port()));
+  jsobj.AddServiceId(ISOLATE_SERVICE_ID_FORMAT_STRING,
+                     static_cast<int64_t>(main_port()));
 
   jsobj.AddProperty("name", name());
   jsobj.AddPropertyF("number", "%" Pd64 "", static_cast<int64_t>(main_port()));
@@ -2180,12 +2140,12 @@
 
   if (!is_runnable()) {
     // Isolate is not yet runnable.
-    ASSERT((debugger() == NULL) || (debugger()->PauseEvent() == NULL));
+    ASSERT((debugger() == nullptr) || (debugger()->PauseEvent() == nullptr));
     ServiceEvent pause_event(this, ServiceEvent::kNone);
     jsobj.AddProperty("pauseEvent", &pause_event);
   } else if (message_handler()->should_pause_on_start()) {
     if (message_handler()->is_paused_on_start()) {
-      ASSERT((debugger() == NULL) || (debugger()->PauseEvent() == NULL));
+      ASSERT((debugger() == nullptr) || (debugger()->PauseEvent() == nullptr));
       ServiceEvent pause_event(this, ServiceEvent::kPauseStart);
       jsobj.AddProperty("pauseEvent", &pause_event);
     } else {
@@ -2195,21 +2155,22 @@
       // Treat Runnable+ShouldPauseOnStart as NotRunnable so they see:
       // NonRunnable -> PausedAtStart
       // The should_pause_on_start flag is set to false after resume.
-      ASSERT((debugger() == NULL) || (debugger()->PauseEvent() == NULL));
+      ASSERT((debugger() == nullptr) || (debugger()->PauseEvent() == nullptr));
       ServiceEvent pause_event(this, ServiceEvent::kNone);
       jsobj.AddProperty("pauseEvent", &pause_event);
     }
   } else if (message_handler()->is_paused_on_exit() &&
-             ((debugger() == NULL) || (debugger()->PauseEvent() == NULL))) {
+             ((debugger() == nullptr) ||
+              (debugger()->PauseEvent() == nullptr))) {
     ServiceEvent pause_event(this, ServiceEvent::kPauseExit);
     jsobj.AddProperty("pauseEvent", &pause_event);
-  } else if ((debugger() != NULL) && (debugger()->PauseEvent() != NULL) &&
+  } else if ((debugger() != nullptr) && (debugger()->PauseEvent() != nullptr) &&
              !ResumeRequest()) {
     jsobj.AddProperty("pauseEvent", debugger()->PauseEvent());
   } else {
     ServiceEvent pause_event(this, ServiceEvent::kResume);
 
-    if (debugger() != NULL) {
+    if (debugger() != nullptr) {
       // TODO(turnidge): Don't compute a full stack trace.
       DebuggerStackTrace* stack = debugger()->StackTrace();
       if (stack->Length() > 0) {
@@ -2260,18 +2221,18 @@
 
   {
     JSONArray breakpoints(&jsobj, "breakpoints");
-    if (debugger() != NULL) {
+    if (debugger() != nullptr) {
       debugger()->PrintBreakpointsToJSONArray(&breakpoints);
     }
   }
 
-  Dart_ExceptionPauseInfo pause_info = (debugger() != NULL)
+  Dart_ExceptionPauseInfo pause_info = (debugger() != nullptr)
                                            ? debugger()->GetExceptionPauseInfo()
                                            : kNoPauseOnExceptions;
   jsobj.AddProperty("exceptionPauseMode",
                     ExceptionPauseInfoToServiceEnum(pause_info));
 
-  if (debugger() != NULL) {
+  if (debugger() != nullptr) {
     JSONObject settings(&jsobj, "_debuggerSettings");
     debugger()->PrintSettingsToJSONObject(&settings);
   }
@@ -2362,7 +2323,7 @@
   ASSERT(!field.IsOriginal());
   // The enclosed code allocates objects and can potentially trigger a GC,
   // ensure that we account for safepoints when grabbing the lock.
-  SafepointMutexLocker ml(field_list_mutex_);
+  SafepointMutexLocker ml(&field_list_mutex_);
   if (boxed_field_list_ == GrowableObjectArray::null()) {
     boxed_field_list_ = GrowableObjectArray::New(Heap::kOld);
   }
@@ -2373,7 +2334,7 @@
 
 RawField* Isolate::GetDeoptimizingBoxedField() {
   ASSERT(Thread::Current()->IsMutatorThread());
-  SafepointMutexLocker ml(field_list_mutex_);
+  SafepointMutexLocker ml(&field_list_mutex_);
   if (boxed_field_list_ == GrowableObjectArray::null()) {
     return Field::null();
   }
@@ -2386,14 +2347,14 @@
 }
 
 #ifndef PRODUCT
-RawObject* Isolate::InvokePendingServiceExtensionCalls() {
+RawError* Isolate::InvokePendingServiceExtensionCalls() {
   if (!FLAG_support_service) {
-    return Object::null();
+    return Error::null();
   }
   GrowableObjectArray& calls =
       GrowableObjectArray::Handle(GetAndClearPendingServiceExtensionCalls());
   if (calls.IsNull()) {
-    return Object::null();
+    return Error::null();
   }
   // Grab run function.
   const Library& developer_lib = Library::Handle(Library::DeveloperLibrary());
@@ -2449,17 +2410,17 @@
         Service::PostError(method_name, parameter_keys, parameter_values,
                            reply_port, id, Error::Cast(result));
       }
-      return result.raw();
+      return Error::Cast(result).raw();
     }
     // Drain the microtask queue.
     result = DartLibraryCalls::DrainMicrotaskQueue();
     // Propagate the error.
     if (result.IsError()) {
       // Remaining service extension calls are dropped.
-      return result.raw();
+      return Error::Cast(result).raw();
     }
   }
-  return Object::null();
+  return Error::null();
 }
 
 RawGrowableObjectArray* Isolate::GetAndClearPendingServiceExtensionCalls() {
@@ -2481,10 +2442,12 @@
   }
   GrowableObjectArray& calls =
       GrowableObjectArray::Handle(pending_service_extension_calls());
+  bool schedule_drain = false;
   if (calls.IsNull()) {
-    calls ^= GrowableObjectArray::New();
+    calls = GrowableObjectArray::New();
     ASSERT(!calls.IsNull());
     set_pending_service_extension_calls(calls);
+    schedule_drain = true;
   }
   ASSERT(kPendingHandlerIndex == 0);
   calls.Add(closure);
@@ -2498,6 +2461,22 @@
   calls.Add(reply_port);
   ASSERT(kPendingIdIndex == 5);
   calls.Add(id);
+
+  if (schedule_drain) {
+    const Array& msg = Array::Handle(Array::New(3));
+    Object& element = Object::Handle();
+    element = Smi::New(Message::kIsolateLibOOBMsg);
+    msg.SetAt(0, element);
+    element = Smi::New(Isolate::kDrainServiceExtensionsMsg);
+    msg.SetAt(1, element);
+    element = Smi::New(Isolate::kBeforeNextEventAction);
+    msg.SetAt(2, element);
+    MessageWriter writer(false);
+    std::unique_ptr<Message> message =
+        writer.WriteMessage(msg, main_port(), Message::kOOBPriority);
+    bool posted = PortMap::PostMessage(std::move(message));
+    ASSERT(posted);
+  }
 }
 
 // This function is written in C++ and not Dart because we must do this
@@ -2512,7 +2491,7 @@
   GrowableObjectArray& handlers =
       GrowableObjectArray::Handle(registered_service_extension_handlers());
   if (handlers.IsNull()) {
-    handlers ^= GrowableObjectArray::New(Heap::kOld);
+    handlers = GrowableObjectArray::New(Heap::kOld);
     set_registered_service_extension_handlers(handlers);
   }
 #if defined(DEBUG)
@@ -2571,7 +2550,7 @@
   // could be from our thread pool or it could be a thread from the
   // embedder.  Sit on the current thread handling service events
   // until we are told to resume.
-  if (pause_loop_monitor_ == NULL) {
+  if (pause_loop_monitor_ == nullptr) {
     pause_loop_monitor_ = new Monitor();
   }
   Dart_EnterScope();
@@ -2581,7 +2560,7 @@
   set_message_notify_callback(Isolate::WakePauseEventHandler);
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  const bool had_isolate_reload_context = reload_context() != NULL;
+  const bool had_isolate_reload_context = reload_context() != nullptr;
   const int64_t start_time_micros =
       !had_isolate_reload_context ? 0 : reload_context()->start_time_micros();
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
@@ -2599,7 +2578,7 @@
     }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    if (had_isolate_reload_context && (reload_context() == NULL)) {
+    if (had_isolate_reload_context && (reload_context() == nullptr)) {
       if (FLAG_trace_reload) {
         const int64_t reload_time_micros =
             OS::GetCurrentMonotonicMicros() - start_time_micros;
@@ -2620,7 +2599,7 @@
 #endif  // !PRODUCT
 
 void Isolate::VisitIsolates(IsolateVisitor* visitor) {
-  if (visitor == NULL) {
+  if (visitor == nullptr) {
     return;
   }
   // The visitor could potentially run code that could safepoint so use
@@ -2637,7 +2616,7 @@
   MonitorLocker ml(isolates_list_monitor_);
   intptr_t count = 0;
   Isolate* current = isolates_list_head_;
-  while (current != NULL) {
+  while (current != nullptr) {
     count++;
     current = current->next_;
   }
@@ -2647,13 +2626,13 @@
 Isolate* Isolate::LookupIsolateByPort(Dart_Port port) {
   MonitorLocker ml(isolates_list_monitor_);
   Isolate* current = isolates_list_head_;
-  while (current != NULL) {
+  while (current != nullptr) {
     if (current->main_port() == port) {
       return current;
     }
     current = current->next_;
   }
-  return NULL;
+  return nullptr;
 }
 
 bool Isolate::AddIsolateToList(Isolate* isolate) {
@@ -2661,8 +2640,8 @@
   if (!creation_enabled_) {
     return false;
   }
-  ASSERT(isolate != NULL);
-  ASSERT(isolate->next_ == NULL);
+  ASSERT(isolate != nullptr);
+  ASSERT(isolate->next_ == nullptr);
   isolate->next_ = isolates_list_head_;
   isolates_list_head_ = isolate;
   return true;
@@ -2670,7 +2649,7 @@
 
 void Isolate::RemoveIsolateFromList(Isolate* isolate) {
   MonitorLocker ml(isolates_list_monitor_);
-  ASSERT(isolate != NULL);
+  ASSERT(isolate != nullptr);
   if (isolate == isolates_list_head_) {
     isolates_list_head_ = isolate->next_;
     if (!creation_enabled_) {
@@ -2678,11 +2657,11 @@
     }
     return;
   }
-  Isolate* previous = NULL;
+  Isolate* previous = nullptr;
   Isolate* current = isolates_list_head_;
   while (current) {
     if (current == isolate) {
-      ASSERT(previous != NULL);
+      ASSERT(previous != nullptr);
       previous->next_ = current->next_;
       if (!creation_enabled_) {
         ml.Notify();
@@ -2746,12 +2725,12 @@
 
   {
     ApiMessageWriter writer;
-    Message* message =
+    std::unique_ptr<Message> message =
         writer.WriteCMessage(&kill_msg, main_port(), Message::kOOBPriority);
-    ASSERT(message != NULL);
+    ASSERT(message != nullptr);
 
     // Post the message at the given port.
-    bool success = PortMap::PostMessage(message);
+    bool success = PortMap::PostMessage(std::move(message));
     ASSERT(success);
   }
 }
@@ -2759,7 +2738,7 @@
 class IsolateKillerVisitor : public IsolateVisitor {
  public:
   explicit IsolateKillerVisitor(Isolate::LibMsgId msg_id)
-      : target_(NULL), msg_id_(msg_id) {}
+      : target_(nullptr), msg_id_(msg_id) {}
 
   IsolateKillerVisitor(Isolate* isolate, Isolate::LibMsgId msg_id)
       : target_(isolate), msg_id_(msg_id) {
@@ -2769,7 +2748,7 @@
   virtual ~IsolateKillerVisitor() {}
 
   void VisitIsolate(Isolate* isolate) {
-    ASSERT(isolate != NULL);
+    ASSERT(isolate != nullptr);
     if (ShouldKill(isolate)) {
       isolate->KillLocked(msg_id_);
     }
@@ -2779,8 +2758,8 @@
   bool ShouldKill(Isolate* isolate) {
     // If a target_ is specified, then only kill the target_.
     // Otherwise, don't kill the service isolate or vm isolate.
-    return (((target_ != NULL) && (isolate == target_)) ||
-            ((target_ == NULL) && !IsVMInternalIsolate(isolate)));
+    return (((target_ != nullptr) && (isolate == target_)) ||
+            ((target_ == nullptr) && !IsVMInternalIsolate(isolate)));
   }
 
   Isolate* target_;
@@ -2798,12 +2777,19 @@
 }
 
 void Isolate::IncrementSpawnCount() {
-  MonitorLocker ml(spawn_count_monitor_);
+  MonitorLocker ml(&spawn_count_monitor_);
   spawn_count_++;
 }
 
+void Isolate::DecrementSpawnCount() {
+  MonitorLocker ml(&spawn_count_monitor_);
+  ASSERT(spawn_count_ > 0);
+  spawn_count_--;
+  ml.Notify();
+}
+
 void Isolate::WaitForOutstandingSpawns() {
-  MonitorLocker ml(spawn_count_monitor_);
+  MonitorLocker ml(&spawn_count_monitor_);
   while (spawn_count_ > 0) {
     ml.Wait();
   }
@@ -2817,9 +2803,9 @@
   // Schedule the thread into the isolate by associating
   // a 'Thread' structure with it (this is done while we are holding
   // the thread registry lock).
-  Thread* thread = NULL;
+  Thread* thread = nullptr;
   OSThread* os_thread = OSThread::Current();
-  if (os_thread != NULL) {
+  if (os_thread != nullptr) {
     // We are about to associate the thread with an isolate and it would
     // not be possible to correctly track no_safepoint_scope_depth for the
     // thread in the constructor/destructor of MonitorLocker,
@@ -2828,8 +2814,8 @@
     MonitorLocker ml(threads_lock(), false);
 
     // Check to make sure we don't already have a mutator thread.
-    if (is_mutator && scheduled_mutator_thread_ != NULL) {
-      return NULL;
+    if (is_mutator && scheduled_mutator_thread_ != nullptr) {
+      return nullptr;
     }
 
     // If a safepoint operation is in progress wait for it
@@ -2840,13 +2826,13 @@
 
     // Now get a free Thread structure.
     thread = thread_registry()->GetFreeThreadLocked(this, is_mutator);
-    ASSERT(thread != NULL);
+    ASSERT(thread != nullptr);
 
     thread->ResetHighWatermark();
 
     // Set up other values and set the TLS value.
     thread->isolate_ = this;
-    ASSERT(heap() != NULL);
+    ASSERT(heap() != nullptr);
     thread->heap_ = heap();
     thread->set_os_thread(os_thread);
     ASSERT(thread->execution_state() == Thread::kThreadInNative);
@@ -2882,8 +2868,8 @@
       sticky_error_ = thread->StealStickyError();
     }
   } else {
-    ASSERT(thread->api_top_scope_ == NULL);
-    ASSERT(thread->zone() == NULL);
+    ASSERT(thread->api_top_scope_ == nullptr);
+    ASSERT(thread->zone() == nullptr);
     ASSERT(thread->sticky_error() == Error::null());
   }
   if (!bypass_safepoint) {
@@ -2891,12 +2877,12 @@
     thread->EnterSafepoint();
   }
   OSThread* os_thread = thread->os_thread();
-  ASSERT(os_thread != NULL);
+  ASSERT(os_thread != nullptr);
   os_thread->DisableThreadInterrupts();
-  os_thread->set_thread(NULL);
+  os_thread->set_thread(nullptr);
   OSThread::SetCurrent(os_thread);
   if (is_mutator) {
-    scheduled_mutator_thread_ = NULL;
+    scheduled_mutator_thread_ = nullptr;
   }
   // Even if we unschedule the mutator thread, e.g. via calling
   // `Dart_ExitIsolate()` inside a native, we might still have one or more Dart
@@ -2909,10 +2895,10 @@
   // All other threads are not allowed to unschedule themselves and schedule
   // again later on.
   if (!is_mutator) {
-    thread->isolate_ = NULL;
+    thread->isolate_ = nullptr;
   }
-  thread->heap_ = NULL;
-  thread->set_os_thread(NULL);
+  thread->heap_ = nullptr;
+  thread->set_os_thread(nullptr);
   thread->set_execution_state(Thread::kThreadInNative);
   thread->set_safepoint_state(Thread::SetAtSafepoint(true, 0));
   thread->clear_pending_functions();
@@ -2930,36 +2916,28 @@
 
 IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
                                      Dart_Port origin_id,
-                                     void* init_data,
                                      const char* script_url,
                                      const Function& func,
                                      SerializedObjectBuffer* message_buffer,
-                                     Monitor* spawn_count_monitor,
-                                     intptr_t* spawn_count,
-                                     const char* package_root,
                                      const char* package_config,
                                      bool paused,
                                      bool errors_are_fatal,
                                      Dart_Port on_exit_port,
                                      Dart_Port on_error_port,
                                      const char* debug_name)
-    : isolate_(NULL),
+    : isolate_(nullptr),
       parent_port_(parent_port),
       origin_id_(origin_id),
-      init_data_(init_data),
       on_exit_port_(on_exit_port),
       on_error_port_(on_error_port),
       script_url_(script_url),
-      package_root_(package_root),
       package_config_(package_config),
-      library_url_(NULL),
-      class_name_(NULL),
-      function_name_(NULL),
+      library_url_(nullptr),
+      class_name_(nullptr),
+      function_name_(nullptr),
       debug_name_(debug_name),
-      serialized_args_(NULL),
+      serialized_args_(nullptr),
       serialized_message_(message_buffer->StealMessage()),
-      spawn_count_monitor_(spawn_count_monitor),
-      spawn_count_(spawn_count),
       paused_(paused),
       errors_are_fatal_(errors_are_fatal) {
   const Class& cls = Class::Handle(func.Owner());
@@ -2968,8 +2946,8 @@
   library_url_ = NewConstChar(lib_url.ToCString());
 
   String& func_name = String::Handle();
-  func_name ^= func.name();
-  func_name ^= String::ScrubName(func_name);
+  func_name = func.name();
+  func_name = String::ScrubName(func_name);
   function_name_ = NewConstChar(func_name.ToCString());
   if (!cls.IsTopLevel()) {
     const String& class_name = String::Handle(cls.Name());
@@ -2981,36 +2959,28 @@
 }
 
 IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
-                                     void* init_data,
                                      const char* script_url,
-                                     const char* package_root,
                                      const char* package_config,
                                      SerializedObjectBuffer* args_buffer,
                                      SerializedObjectBuffer* message_buffer,
-                                     Monitor* spawn_count_monitor,
-                                     intptr_t* spawn_count,
                                      bool paused,
                                      bool errors_are_fatal,
                                      Dart_Port on_exit_port,
                                      Dart_Port on_error_port,
                                      const char* debug_name)
-    : isolate_(NULL),
+    : isolate_(nullptr),
       parent_port_(parent_port),
       origin_id_(ILLEGAL_PORT),
-      init_data_(init_data),
       on_exit_port_(on_exit_port),
       on_error_port_(on_error_port),
       script_url_(script_url),
-      package_root_(package_root),
       package_config_(package_config),
-      library_url_(NULL),
-      class_name_(NULL),
-      function_name_(NULL),
+      library_url_(nullptr),
+      class_name_(nullptr),
+      function_name_(nullptr),
       debug_name_(debug_name),
       serialized_args_(args_buffer->StealMessage()),
       serialized_message_(message_buffer->StealMessage()),
-      spawn_count_monitor_(spawn_count_monitor),
-      spawn_count_(spawn_count),
       isolate_flags_(),
       paused_(paused),
       errors_are_fatal_(errors_are_fatal) {
@@ -3023,14 +2993,11 @@
 
 IsolateSpawnState::~IsolateSpawnState() {
   delete[] script_url_;
-  delete[] package_root_;
   delete[] package_config_;
   delete[] library_url_;
   delete[] class_name_;
   delete[] function_name_;
   delete[] debug_name_;
-  delete serialized_args_;
-  delete serialized_message_;
 }
 
 RawObject* IsolateSpawnState::ResolveFunction() {
@@ -3039,7 +3006,7 @@
 
   const String& func_name = String::Handle(zone, String::New(function_name()));
 
-  if (library_url() == NULL) {
+  if (library_url() == nullptr) {
     // Handle spawnUri lookup rules.
     // Check whether the root library defines a main function.
     const Library& lib =
@@ -3075,7 +3042,7 @@
   }
 
   // Resolve the function.
-  if (class_name() == NULL) {
+  if (class_name() == nullptr) {
     const Function& func =
         Function::Handle(zone, lib.LookupLocalFunction(func_name));
     if (func.IsNull()) {
@@ -3094,7 +3061,7 @@
     const String& msg = String::Handle(
         zone, String::NewFormatted(
                   "Unable to resolve class '%s' in library '%s'.", class_name(),
-                  (library_url() != NULL ? library_url() : script_url())));
+                  (library_url() != nullptr ? library_url() : script_url())));
     return LanguageError::New(msg);
   }
   const Function& func =
@@ -3104,27 +3071,18 @@
         zone, String::NewFormatted(
                   "Unable to resolve static method '%s.%s' in library '%s'.",
                   class_name(), function_name(),
-                  (library_url() != NULL ? library_url() : script_url())));
+                  (library_url() != nullptr ? library_url() : script_url())));
     return LanguageError::New(msg);
   }
   return func.raw();
 }
 
 RawInstance* IsolateSpawnState::BuildArgs(Thread* thread) {
-  return DeserializeMessage(thread, serialized_args_);
+  return DeserializeMessage(thread, serialized_args_.get());
 }
 
 RawInstance* IsolateSpawnState::BuildMessage(Thread* thread) {
-  return DeserializeMessage(thread, serialized_message_);
-}
-
-void IsolateSpawnState::DecrementSpawnCount() {
-  ASSERT(spawn_count_monitor_ != NULL);
-  ASSERT(spawn_count_ != NULL);
-  MonitorLocker ml(spawn_count_monitor_);
-  ASSERT(*spawn_count_ > 0);
-  *spawn_count_ = *spawn_count_ - 1;
-  ml.Notify();
+  return DeserializeMessage(thread, serialized_message_.get());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 584eeae..914a40f 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -9,11 +9,14 @@
 #error "Should not include runtime"
 #endif
 
+#include <memory>
+
 #include "include/dart_api.h"
 #include "platform/assert.h"
 #include "platform/atomic.h"
 #include "vm/base_isolate.h"
 #include "vm/class_table.h"
+#include "vm/constants_kbc.h"
 #include "vm/exceptions.h"
 #include "vm/fixed_cache.h"
 #include "vm/growable_array.h"
@@ -170,6 +173,7 @@
     kInterruptMsg = 10,     // Break in the debugger.
     kInternalKillMsg = 11,  // Like kill, but does not run exit listeners, etc.
     kLowMemoryMsg = 12,     // Run compactor, etc.
+    kDrainServiceExtensionsMsg = 13,  // Invoke pending service extensions
   };
   // The different Isolate API message priorities for ping and kill messages.
   enum LibMsgPriority {
@@ -182,7 +186,7 @@
 
   static inline Isolate* Current() {
     Thread* thread = Thread::Current();
-    return thread == NULL ? NULL : thread->isolate();
+    return thread == nullptr ? nullptr : thread->isolate();
   }
 
   // Register a newly introduced class.
@@ -305,14 +309,14 @@
   // the caller to delete is separately if it is still needed.
   bool ReloadSources(JSONStream* js,
                      bool force_reload,
-                     const char* root_script_url = NULL,
-                     const char* packages_url = NULL,
+                     const char* root_script_url = nullptr,
+                     const char* packages_url = nullptr,
                      bool dont_delete_reload_context = false);
 
   // If provided, the VM takes ownership of kernel_buffer.
   bool ReloadKernel(JSONStream* js,
                     bool force_reload,
-                    const uint8_t* kernel_buffer = NULL,
+                    const uint8_t* kernel_buffer = nullptr,
                     intptr_t kernel_buffer_size = 0,
                     bool dont_delete_reload_context = false);
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
@@ -345,30 +349,26 @@
   IsolateSpawnState* spawn_state() const { return spawn_state_; }
   void set_spawn_state(IsolateSpawnState* value) { spawn_state_ = value; }
 
-  Mutex* mutex() const { return mutex_; }
-  Mutex* symbols_mutex() const { return symbols_mutex_; }
-  Mutex* type_canonicalization_mutex() const {
-    return type_canonicalization_mutex_;
+  Mutex* mutex() { return &mutex_; }
+  Mutex* symbols_mutex() { return &symbols_mutex_; }
+  Mutex* type_canonicalization_mutex() { return &type_canonicalization_mutex_; }
+  Mutex* constant_canonicalization_mutex() {
+    return &constant_canonicalization_mutex_;
   }
-  Mutex* constant_canonicalization_mutex() const {
-    return constant_canonicalization_mutex_;
-  }
-  Mutex* megamorphic_lookup_mutex() const { return megamorphic_lookup_mutex_; }
+  Mutex* megamorphic_lookup_mutex() { return &megamorphic_lookup_mutex_; }
 
-  Mutex* kernel_data_lib_cache_mutex() const {
-    return kernel_data_lib_cache_mutex_;
-  }
-  Mutex* kernel_data_class_cache_mutex() const {
-    return kernel_data_class_cache_mutex_;
+  Mutex* kernel_data_lib_cache_mutex() { return &kernel_data_lib_cache_mutex_; }
+  Mutex* kernel_data_class_cache_mutex() {
+    return &kernel_data_class_cache_mutex_;
   }
 
   // Any access to constants arrays must be locked since mutator and
   // background compiler can access the arrays at the same time.
-  Mutex* kernel_constants_mutex() const { return kernel_constants_mutex_; }
+  Mutex* kernel_constants_mutex() { return &kernel_constants_mutex_; }
 
 #if !defined(PRODUCT)
   Debugger* debugger() const {
-    ASSERT(debugger_ != NULL);
+    ASSERT(debugger_ != nullptr);
     return debugger_;
   }
 
@@ -430,10 +430,8 @@
   Simulator* simulator() const { return simulator_; }
   void set_simulator(Simulator* value) { simulator_ = value; }
 
-  Monitor* spawn_count_monitor() const { return spawn_count_monitor_; }
-  intptr_t* spawn_count() { return &spawn_count_; }
-
   void IncrementSpawnCount();
+  void DecrementSpawnCount();
   void WaitForOutstandingSpawns();
 
   static void SetCreateCallback(Dart_IsolateCreateCallback cb) {
@@ -468,10 +466,10 @@
   MallocGrowableArray<PendingLazyDeopt>* pending_deopts() const {
     return pending_deopts_;
   }
-  bool IsDeoptimizing() const { return deopt_context_ != NULL; }
+  bool IsDeoptimizing() const { return deopt_context_ != nullptr; }
   DeoptContext* deopt_context() const { return deopt_context_; }
   void set_deopt_context(DeoptContext* value) {
-    ASSERT(value == NULL || deopt_context_ == NULL);
+    ASSERT(value == nullptr || deopt_context_ == nullptr);
     deopt_context_ = value;
   }
 
@@ -529,7 +527,7 @@
   VMTagCounters* vm_tag_counters() { return &vm_tag_counters_; }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  bool IsReloading() const { return reload_context_ != NULL; }
+  bool IsReloading() const { return reload_context_ != nullptr; }
 
   IsolateReloadContext* reload_context() { return reload_context_; }
 
@@ -658,7 +656,7 @@
   RawField* GetDeoptimizingBoxedField();
 
 #ifndef PRODUCT
-  RawObject* InvokePendingServiceExtensionCalls();
+  RawError* InvokePendingServiceExtensionCalls();
   void AppendServiceExtensionCall(const Instance& closure,
                                   const String& method_name,
                                   const Array& parameter_keys,
@@ -780,11 +778,28 @@
     return !unsafe_trust_strong_mode_types();
   }
 
+  static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 7,
+                "Cleanup support for old bytecode format versions");
+  bool is_using_old_bytecode_instructions() const {
+    return UsingOldBytecodeInstructionsBit::decode(isolate_flags_);
+  }
+  void set_is_using_old_bytecode_instructions(bool value) {
+    isolate_flags_ =
+        UsingOldBytecodeInstructionsBit::update(value, isolate_flags_);
+  }
+  bool is_using_new_bytecode_instructions() const {
+    return UsingNewBytecodeInstructionsBit::decode(isolate_flags_);
+  }
+  void set_is_using_new_bytecode_instructions(bool value) {
+    isolate_flags_ =
+        UsingNewBytecodeInstructionsBit::update(value, isolate_flags_);
+  }
+
   static void KillAllIsolates(LibMsgId msg_id);
   static void KillIfExists(Isolate* isolate, LibMsgId msg_id);
 
-  // Lookup an isolate by its main port. Returns NULL if no matching isolate is
-  // found.
+  // Lookup an isolate by its main port. Returns nullptr if no matching isolate
+  // is found.
   static Isolate* LookupIsolateByPort(Dart_Port port);
 
   static void DisableIsolateCreation();
@@ -870,19 +885,19 @@
   // in SIMARM(IA32) and ARM, and the same offsets in SIMARM64(X64) and ARM64.
   // We use only word-sized fields to avoid differences in struct packing on the
   // different architectures. See also CheckOffsets in dart.cc.
-  uword user_tag_;
+  uword user_tag_ = 0;
   RawUserTag* current_tag_;
   RawUserTag* default_tag_;
   RawCode* ic_miss_code_;
-  ObjectStore* object_store_;
+  ObjectStore* object_store_ = nullptr;
   ClassTable class_table_;
-  bool single_step_;
+  bool single_step_ = false;
   // End accessed from generated code.
 
-  StoreBuffer* store_buffer_;
-  MarkingStack* marking_stack_;
-  MarkingStack* deferred_marking_stack_;
-  Heap* heap_;
+  StoreBuffer* store_buffer_ = nullptr;
+  MarkingStack* marking_stack_ = nullptr;
+  MarkingStack* deferred_marking_stack_ = nullptr;
+  Heap* heap_ = nullptr;
 
 #define ISOLATE_FLAG_BITS(V)                                                   \
   V(ErrorsFatal)                                                               \
@@ -904,7 +919,13 @@
   V(Obfuscate)                                                                 \
   V(CompactionInProgress)                                                      \
   V(ShouldLoadVmService)                                                       \
-  V(UnsafeTrustStrongModeTypes)
+  V(UnsafeTrustStrongModeTypes)                                                \
+  V(UsingOldBytecodeInstructions)                                              \
+  V(UsingNewBytecodeInstructions)
+
+  static_assert(
+      KernelBytecode::kMinSupportedBytecodeFormatVersion < 7,
+      "Cleanup UsingOldBytecodeInstructions and UsingNewBytecodeInstructions");
 
   // Isolate specific flags.
   enum FlagBits {
@@ -918,23 +939,23 @@
   ISOLATE_FLAG_BITS(DECLARE_BITFIELD)
 #undef DECLARE_BITFIELD
 
-  uint32_t isolate_flags_;
+  uint32_t isolate_flags_ = 0;
 
   // Unoptimized background compilation.
-  BackgroundCompiler* background_compiler_;
+  BackgroundCompiler* background_compiler_ = nullptr;
 
   // Optimized background compilation.
-  BackgroundCompiler* optimizing_background_compiler_;
+  BackgroundCompiler* optimizing_background_compiler_ = nullptr;
 
 // Fields that aren't needed in a product build go here with boolean flags at
 // the top.
 #if !defined(PRODUCT)
-  Debugger* debugger_;
+  Debugger* debugger_ = nullptr;
   int64_t last_resume_timestamp_;
 
   // Timestamps of last operation via service.
-  int64_t last_allocationprofile_accumulator_reset_timestamp_;
-  int64_t last_allocationprofile_gc_timestamp_;
+  int64_t last_allocationprofile_accumulator_reset_timestamp_ = 0;
+  int64_t last_allocationprofile_gc_timestamp_ = 0;
 
   VMTagCounters vm_tag_counters_;
 
@@ -958,54 +979,55 @@
   };
   RawGrowableObjectArray* registered_service_extension_handlers_;
 
-  Metric* metrics_list_head_;
+  Metric* metrics_list_head_ = nullptr;
 
   // Used to wake the isolate when it is in the pause event loop.
-  Monitor* pause_loop_monitor_;
+  Monitor* pause_loop_monitor_ = nullptr;
 
 #define ISOLATE_METRIC_VARIABLE(type, variable, name, unit)                    \
   type metric_##variable##_;
   ISOLATE_METRIC_LIST(ISOLATE_METRIC_VARIABLE);
 #undef ISOLATE_METRIC_VARIABLE
 
-  intptr_t no_reload_scope_depth_;  // we can only reload when this is 0.
+  intptr_t no_reload_scope_depth_ = 0;  // 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_;
+  IsolateReloadContext* reload_context_ = nullptr;
   int64_t last_reload_timestamp_;
   // Ring buffer of objects assigned an id.
-  ObjectIdRing* object_id_ring_;
+  ObjectIdRing* object_id_ring_ = nullptr;
 #endif  // !defined(PRODUCT)
 
   // All other fields go here.
   int64_t start_time_micros_;
   ThreadRegistry* thread_registry_;
   SafepointHandler* safepoint_handler_;
-  Dart_MessageNotifyCallback message_notify_callback_;
-  char* name_;
-  Dart_Port main_port_;
-  Dart_Port origin_id_;  // Isolates created by spawnFunc have some origin id.
-  uint64_t pause_capability_;
-  uint64_t terminate_capability_;
-  void* init_callback_data_;
-  Dart_EnvironmentCallback environment_callback_;
-  Dart_LibraryTagHandler library_tag_handler_;
-  ApiState* api_state_;
+  Dart_MessageNotifyCallback message_notify_callback_ = nullptr;
+  char* name_ = nullptr;
+  Dart_Port main_port_ = 0;
+  // Isolates created by Isolate.spawn have the same origin id.
+  Dart_Port origin_id_ = 0;
+  uint64_t pause_capability_ = 0;
+  uint64_t terminate_capability_ = 0;
+  void* init_callback_data_ = nullptr;
+  Dart_EnvironmentCallback environment_callback_ = nullptr;
+  Dart_LibraryTagHandler library_tag_handler_ = nullptr;
+  ApiState* api_state_ = nullptr;
   Random random_;
-  Simulator* simulator_;
-  Mutex* mutex_;          // Protects compiler stats.
-  Mutex* symbols_mutex_;  // Protects concurrent access to the symbol table.
-  Mutex* type_canonicalization_mutex_;      // Protects type canonicalization.
-  Mutex* constant_canonicalization_mutex_;  // Protects const canonicalization.
-  Mutex* megamorphic_lookup_mutex_;  // Protects megamorphic table lookup.
-  Mutex* kernel_data_lib_cache_mutex_;
-  Mutex* kernel_data_class_cache_mutex_;
-  Mutex* kernel_constants_mutex_;
-  MessageHandler* message_handler_;
-  IsolateSpawnState* spawn_state_;
-  intptr_t defer_finalization_count_;
+  Simulator* simulator_ = nullptr;
+  Mutex mutex_;          // Protects compiler stats.
+  Mutex symbols_mutex_;  // Protects concurrent access to the symbol table.
+  Mutex type_canonicalization_mutex_;      // Protects type canonicalization.
+  Mutex constant_canonicalization_mutex_;  // Protects const canonicalization.
+  Mutex megamorphic_lookup_mutex_;         // Protects megamorphic table lookup.
+  Mutex kernel_data_lib_cache_mutex_;
+  Mutex kernel_data_class_cache_mutex_;
+  Mutex kernel_constants_mutex_;
+  MessageHandler* message_handler_ = nullptr;
+  IsolateSpawnState* spawn_state_ = nullptr;
+  intptr_t defer_finalization_count_ = 0;
   MallocGrowableArray<PendingLazyDeopt>* pending_deopts_;
-  DeoptContext* deopt_context_;
+  DeoptContext* deopt_context_ = nullptr;
 
   RawGrowableObjectArray* tag_table_;
 
@@ -1020,30 +1042,30 @@
   RawGrowableObjectArray* reloaded_kernel_blobs_;
 
   // Isolate list next pointer.
-  Isolate* next_;
+  Isolate* next_ = nullptr;
 
   // Invalidation generations; used to track events occurring in parallel
   // to background compilation. The counters may overflow, which is OK
   // since we check for equality to detect if an event occured.
-  intptr_t loading_invalidation_gen_;
+  intptr_t loading_invalidation_gen_ = kInvalidGen;
 
   // Protect access to boxed_field_list_.
-  Mutex* field_list_mutex_;
+  Mutex field_list_mutex_;
   // List of fields that became boxed and that trigger deoptimization.
   RawGrowableObjectArray* boxed_field_list_;
 
   // This guards spawn_count_. An isolate cannot complete shutdown and be
   // destroyed while there are child isolates in the midst of a spawn.
-  Monitor* spawn_count_monitor_;
-  intptr_t spawn_count_;
+  Monitor spawn_count_monitor_;
+  intptr_t spawn_count_ = 0;
 
   HandlerInfoCache handler_info_cache_;
   CatchEntryMovesCache catch_entry_moves_cache_;
 
-  Dart_QualifiedFunctionName* embedder_entry_points_;
-  const char** obfuscation_map_;
+  Dart_QualifiedFunctionName* embedder_entry_points_ = nullptr;
+  const char** obfuscation_map_ = nullptr;
 
-  ReversePcLookupCache* reverse_pc_lookup_cache_;
+  ReversePcLookupCache* reverse_pc_lookup_cache_ = nullptr;
 
   static Dart_IsolateCreateCallback create_callback_;
   static Dart_IsolateShutdownCallback shutdown_callback_;
@@ -1088,14 +1110,13 @@
  public:
   explicit StartIsolateScope(Isolate* new_isolate)
       : new_isolate_(new_isolate), saved_isolate_(Isolate::Current()) {
-    // TODO(koda): Audit users; passing NULL goes against naming of this class.
-    if (new_isolate_ == NULL) {
-      ASSERT(Isolate::Current() == NULL);
+    if (new_isolate_ == nullptr) {
+      ASSERT(Isolate::Current() == nullptr);
       // Do nothing.
       return;
     }
     if (saved_isolate_ != new_isolate_) {
-      ASSERT(Isolate::Current() == NULL);
+      ASSERT(Isolate::Current() == nullptr);
       Thread::EnterIsolate(new_isolate_);
       // Ensure this is not a nested 'isolate enter' with prior state.
       ASSERT(Thread::Current()->saved_stack_limit() == 0);
@@ -1103,13 +1124,13 @@
   }
 
   ~StartIsolateScope() {
-    if (new_isolate_ == NULL) {
-      ASSERT(Isolate::Current() == NULL);
+    if (new_isolate_ == nullptr) {
+      ASSERT(Isolate::Current() == nullptr);
       // Do nothing.
       return;
     }
     if (saved_isolate_ != new_isolate_) {
-      ASSERT(saved_isolate_ == NULL);
+      ASSERT(saved_isolate_ == nullptr);
       // ASSERT that we have bottomed out of all Dart invocations.
       ASSERT(Thread::Current()->saved_stack_limit() == 0);
       Thread::ExitIsolate();
@@ -1127,13 +1148,9 @@
  public:
   IsolateSpawnState(Dart_Port parent_port,
                     Dart_Port origin_id,
-                    void* init_data,
                     const char* script_url,
                     const Function& func,
                     SerializedObjectBuffer* message_buffer,
-                    Monitor* spawn_count_monitor,
-                    intptr_t* spawn_count,
-                    const char* package_root,
                     const char* package_config,
                     bool paused,
                     bool errorsAreFatal,
@@ -1141,14 +1158,10 @@
                     Dart_Port onError,
                     const char* debug_name);
   IsolateSpawnState(Dart_Port parent_port,
-                    void* init_data,
                     const char* script_url,
-                    const char* package_root,
                     const char* package_config,
                     SerializedObjectBuffer* args_buffer,
                     SerializedObjectBuffer* message_buffer,
-                    Monitor* spawn_count_monitor,
-                    intptr_t* spawn_count,
                     bool paused,
                     bool errorsAreFatal,
                     Dart_Port onExit,
@@ -1161,17 +1174,15 @@
 
   Dart_Port parent_port() const { return parent_port_; }
   Dart_Port origin_id() const { return origin_id_; }
-  void* init_data() const { return init_data_; }
   Dart_Port on_exit_port() const { return on_exit_port_; }
   Dart_Port on_error_port() const { return on_error_port_; }
   const char* script_url() const { return script_url_; }
-  const char* package_root() const { return package_root_; }
   const char* package_config() const { return package_config_; }
   const char* library_url() const { return library_url_; }
   const char* class_name() const { return class_name_; }
   const char* function_name() const { return function_name_; }
   const char* debug_name() const { return debug_name_; }
-  bool is_spawn_uri() const { return library_url_ == NULL; }
+  bool is_spawn_uri() const { return library_url_ == nullptr; }
   bool paused() const { return paused_; }
   bool errors_are_fatal() const { return errors_are_fatal_; }
   Dart_IsolateFlags* isolate_flags() { return &isolate_flags_; }
@@ -1180,29 +1191,20 @@
   RawInstance* BuildArgs(Thread* thread);
   RawInstance* BuildMessage(Thread* thread);
 
-  void DecrementSpawnCount();
-
  private:
   Isolate* isolate_;
   Dart_Port parent_port_;
   Dart_Port origin_id_;
-  void* init_data_;
   Dart_Port on_exit_port_;
   Dart_Port on_error_port_;
   const char* script_url_;
-  const char* package_root_;
   const char* package_config_;
   const char* library_url_;
   const char* class_name_;
   const char* function_name_;
   const char* debug_name_;
-  Message* serialized_args_;
-  Message* serialized_message_;
-
-  // This counter tracks the number of outstanding calls to spawn by the parent
-  // isolate.
-  Monitor* spawn_count_monitor_;
-  intptr_t* spawn_count_;
+  std::unique_ptr<Message> serialized_args_;
+  std::unique_ptr<Message> serialized_message_;
 
   Dart_IsolateFlags isolate_flags_;
   bool paused_;
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 76e8e9d..b153644 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -172,7 +172,7 @@
     // Create a function that returns the expression.
     const Field* field = new_fields_->At(i);
     if (field->kernel_offset() > 0) {
-      eval_func ^= kernel::CreateFieldInitializerFunction(thread, zone, *field);
+      eval_func = kernel::CreateFieldInitializerFunction(thread, zone, *field);
     } else {
       UNREACHABLE();
     }
@@ -453,6 +453,7 @@
       error_(Error::null()),
       old_classes_set_storage_(Array::null()),
       class_map_storage_(Array::null()),
+      removed_class_set_storage_(Array::null()),
       old_libraries_set_storage_(Array::null()),
       library_map_storage_(Array::null()),
       become_map_storage_(Array::null()),
@@ -615,7 +616,7 @@
       p_num_received_classes = &num_received_classes_;
       p_num_received_procedures = &num_received_procedures_;
     } else {
-      Dart_KernelCompilationResult retval;
+      Dart_KernelCompilationResult retval = {};
       if (kernel_buffer != NULL && kernel_buffer_size != 0) {
         retval.kernel = const_cast<uint8_t*>(kernel_buffer);
         retval.kernel_size = kernel_buffer_size;
@@ -699,6 +700,8 @@
   old_classes_set_storage_ =
       HashTables::New<UnorderedHashSet<ClassMapTraits> >(4);
   class_map_storage_ = HashTables::New<UnorderedHashMap<ClassMapTraits> >(4);
+  removed_class_set_storage_ =
+      HashTables::New<UnorderedHashSet<ClassMapTraits> >(4);
   old_libraries_set_storage_ =
       HashTables::New<UnorderedHashSet<LibraryMapTraits> >(4);
   library_map_storage_ =
@@ -841,6 +844,8 @@
     return;
   }
   BuildLibraryMapping();
+  BuildRemovedClassesSet();
+
   TIR_Print("---- LOAD SUCCEEDED\n");
   if (ValidateReload()) {
     Commit();
@@ -987,25 +992,40 @@
   ClassAndSize* local_saved_class_table = reinterpret_cast<ClassAndSize*>(
       malloc(sizeof(ClassAndSize) * saved_num_cids_));
 
+  // Copy classes into saved_class_table_ first. Make sure there are no
+  // safepoints until saved_class_table_ is filled up and saved so class raw
+  // pointers in saved_class_table_ are properly visited by GC.
+  {
+    NoSafepointScope no_safepoint_scope(Thread::Current());
+
+    for (intptr_t i = 0; i < saved_num_cids_; i++) {
+      if (class_table->IsValidIndex(i) && class_table->HasValidClassAt(i)) {
+        // Copy the class into the saved class table.
+        local_saved_class_table[i] = class_table->PairAt(i);
+      } else {
+        // No class at this index, mark it as NULL.
+        local_saved_class_table[i] = ClassAndSize(NULL);
+      }
+    }
+
+    // Elements of saved_class_table_ are now visible to GC.
+    saved_class_table_ = local_saved_class_table;
+  }
+
+  // Add classes to the set. Set is stored in the Array, so adding an element
+  // may allocate Dart object on the heap and trigger GC.
   Class& cls = Class::Handle();
   UnorderedHashSet<ClassMapTraits> old_classes_set(old_classes_set_storage_);
   for (intptr_t i = 0; i < saved_num_cids_; i++) {
     if (class_table->IsValidIndex(i) && class_table->HasValidClassAt(i)) {
-      // Copy the class into the saved class table and add it to the set.
-      local_saved_class_table[i] = class_table->PairAt(i);
       if (i != kFreeListElement && i != kForwardingCorpse) {
         cls = class_table->At(i);
         bool already_present = old_classes_set.Insert(cls);
         ASSERT(!already_present);
       }
-    } else {
-      // No class at this index, mark it as NULL.
-      local_saved_class_table[i] = ClassAndSize(NULL);
     }
   }
   old_classes_set_storage_ = old_classes_set.Release().raw();
-  // Assigning the field must be done after saving the class table.
-  saved_class_table_ = local_saved_class_table;
   TIR_Print("---- System had %" Pd " classes\n", saved_num_cids_);
 }
 
@@ -1075,7 +1095,7 @@
     scripts = lib.LoadedScripts();
     for (intptr_t script_idx = 0; script_idx < scripts.Length(); script_idx++) {
       script ^= scripts.At(script_idx);
-      uri ^= script.url();
+      uri = script.url();
       if (ContainsScriptUri(modified_sources_uris, uri.ToCString())) {
         // We've already accounted for this script in a prior library.
         continue;
@@ -1185,7 +1205,7 @@
   if (root_lib_modified) {
     // The root library was either moved or replaced. Mark it as modified to
     // force a reload of the potential root library replacement.
-    lib ^= object_store()->root_library();
+    lib = object_store()->root_library();
     modified_libs->Add(lib.index());
   }
 
@@ -1460,6 +1480,18 @@
     }
 
     class_map.Release();
+
+    {
+      UnorderedHashSet<ClassMapTraits> removed_class_set(
+          removed_class_set_storage_);
+      UnorderedHashSet<ClassMapTraits>::Iterator it(&removed_class_set);
+      while (it.MoveNext()) {
+        const intptr_t entry = it.Current();
+        old_cls ^= removed_class_set.GetKey(entry);
+        old_cls.PatchFieldsAndFunctions();
+      }
+      removed_class_set.Release();
+    }
   }
 
   if (FLAG_identity_reload) {
@@ -1840,8 +1872,10 @@
 void IsolateReloadContext::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   visitor->VisitPointers(from(), to());
   if (saved_class_table_ != NULL) {
-    visitor->VisitPointers(
-        reinterpret_cast<RawObject**>(&saved_class_table_[0]), saved_num_cids_);
+    for (intptr_t i = 0; i < saved_num_cids_; i++) {
+      visitor->VisitPointer(
+          reinterpret_cast<RawObject**>(&(saved_class_table_[i].class_)));
+    }
   }
 }
 
@@ -1941,7 +1975,7 @@
     const KernelProgramInfo& info = *kernel_infos[i];
     // Clear the libraries cache.
     {
-      data ^= info.libraries_cache();
+      data = info.libraries_cache();
       ASSERT(!data.IsNull());
       IntHashMap table(&key, &value, &data);
       table.Clear();
@@ -1949,7 +1983,7 @@
     }
     // Clear the classes cache.
     {
-      data ^= info.classes_cache();
+      data = info.classes_cache();
       ASSERT(!data.IsNull());
       IntHashMap table(&key, &value, &data);
       table.Clear();
@@ -2101,7 +2135,7 @@
     if (!old_url.StartsWith(old_url_prefix)) {
       continue;
     }
-    old_suffix ^= String::SubString(old_url, old_prefix_length);
+    old_suffix = String::SubString(old_url, old_prefix_length);
     if (old_suffix.IsNull()) {
       continue;
     }
@@ -2122,7 +2156,7 @@
   Library& old = Library::Handle();
   for (intptr_t i = num_saved_libs_; i < libs.Length(); i++) {
     replacement_or_new = Library::RawCast(libs.At(i));
-    old ^= OldLibraryOrNull(replacement_or_new);
+    old = OldLibraryOrNull(replacement_or_new);
     if (old.IsNull()) {
       if (FLAG_identity_reload) {
         TIR_Print("Could not find original library for %s\n",
@@ -2141,6 +2175,86 @@
   }
 }
 
+// Find classes that have been removed from the program.
+// Instances of these classes may still be referenced from variables, so the
+// functions of these class may still execute in the future, and they need to
+// be given patch class owners still they correctly reference their (old) kernel
+// data even after the library's kernel data is updated.
+//
+// Note that all such classes must belong to a library that has either been
+// changed or removed.
+void IsolateReloadContext::BuildRemovedClassesSet() {
+  // Find all old classes [mapped_old_classes_set].
+  UnorderedHashMap<ClassMapTraits> class_map(class_map_storage_);
+  UnorderedHashSet<ClassMapTraits> mapped_old_classes_set(
+      HashTables::New<UnorderedHashSet<ClassMapTraits> >(
+          class_map.NumOccupied()));
+  {
+    UnorderedHashMap<ClassMapTraits>::Iterator it(&class_map);
+    Class& cls = Class::Handle();
+    Class& new_cls = Class::Handle();
+    while (it.MoveNext()) {
+      const intptr_t entry = it.Current();
+      new_cls = Class::RawCast(class_map.GetKey(entry));
+      cls = Class::RawCast(class_map.GetPayload(entry, 0));
+      mapped_old_classes_set.InsertOrGet(cls);
+    }
+  }
+  class_map.Release();
+
+  // Find all reloaded libraries [mapped_old_library_set].
+  UnorderedHashMap<LibraryMapTraits> library_map(library_map_storage_);
+  UnorderedHashMap<LibraryMapTraits>::Iterator it_library(&library_map);
+  UnorderedHashSet<LibraryMapTraits> mapped_old_library_set(
+      HashTables::New<UnorderedHashSet<LibraryMapTraits> >(
+          library_map.NumOccupied()));
+  {
+    Library& old_library = Library::Handle();
+    Library& new_library = Library::Handle();
+    while (it_library.MoveNext()) {
+      const intptr_t entry = it_library.Current();
+      new_library ^= library_map.GetKey(entry);
+      old_library ^= library_map.GetPayload(entry, 0);
+      if (new_library.raw() != old_library.raw()) {
+        mapped_old_library_set.InsertOrGet(old_library);
+      }
+    }
+  }
+
+  // For every old class, check if it's library was reloaded and if
+  // the class was mapped. If the class wasn't mapped - add it to
+  // [removed_class_set].
+  UnorderedHashSet<ClassMapTraits> old_classes_set(old_classes_set_storage_);
+  UnorderedHashSet<ClassMapTraits>::Iterator it(&old_classes_set);
+  UnorderedHashSet<ClassMapTraits> removed_class_set(
+      removed_class_set_storage_);
+  Class& old_cls = Class::Handle();
+  Class& new_cls = Class::Handle();
+  Library& old_library = Library::Handle();
+  Library& mapped_old_library = Library::Handle();
+  while (it.MoveNext()) {
+    const intptr_t entry = it.Current();
+    old_cls ^= Class::RawCast(old_classes_set.GetKey(entry));
+    old_library = old_cls.library();
+    if (old_library.IsNull()) {
+      continue;
+    }
+    mapped_old_library ^= mapped_old_library_set.GetOrNull(old_library);
+    if (!mapped_old_library.IsNull()) {
+      new_cls ^= mapped_old_classes_set.GetOrNull(old_cls);
+      if (new_cls.IsNull()) {
+        removed_class_set.InsertOrGet(old_cls);
+      }
+    }
+  }
+  removed_class_set_storage_ = removed_class_set.Release().raw();
+
+  old_classes_set.Release();
+  mapped_old_classes_set.Release();
+  mapped_old_library_set.Release();
+  library_map.Release();
+}
+
 void IsolateReloadContext::AddClassMapping(const Class& replacement_or_new,
                                            const Class& original) {
   UnorderedHashMap<ClassMapTraits> map(class_map_storage_);
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index e8dbfe5..f21c539 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -327,6 +327,7 @@
   RawLibrary* OldLibraryOrNullBaseMoved(const Library& replacement_or_new);
 
   void BuildLibraryMapping();
+  void BuildRemovedClassesSet();
 
   void AddClassMapping(const Class& replacement_or_new, const Class& original);
 
@@ -348,6 +349,7 @@
   RawError* error_;
   RawArray* old_classes_set_storage_;
   RawArray* class_map_storage_;
+  RawArray* removed_class_set_storage_;
   RawArray* old_libraries_set_storage_;
   RawArray* library_map_storage_;
   RawArray* become_map_storage_;
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 8a26648..c331a87 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -578,6 +578,32 @@
   EXPECT_STREQ("hello from A", SimpleInvokeStr(lib, "main"));
 }
 
+TEST_CASE(IsolateReload_ClassRemoved) {
+  const char* kScript =
+      "class A {\n"
+      "  toString() => 'hello from A';\n"
+      "}\n"
+      "List<dynamic> list = <dynamic>[];"
+      "main() {\n"
+      "  list.add(new A());\n"
+      "  return list[0].toString();\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_STREQ("hello from A", SimpleInvokeStr(lib, "main"));
+
+  const char* kReloadScript =
+      "List<dynamic> list = <dynamic>[];\n"
+      "main() {\n"
+      "  return list[0].toString();\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  EXPECT_STREQ("hello from A", SimpleInvokeStr(lib, "main"));
+}
+
 TEST_CASE(IsolateReload_LibraryImportAdded) {
   const char* kScript =
       "main() {\n"
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index c320591..aeaa9d0 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -5,6 +5,7 @@
 #include "platform/assert.h"
 
 #include "include/dart_native_api.h"
+#include "platform/unicode.h"
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
 #include "vm/heap/safepoint.h"
@@ -16,7 +17,6 @@
 #include "vm/service_event.h"
 #include "vm/thread_registry.h"
 #include "vm/timeline.h"
-#include "vm/unicode.h"
 
 namespace dart {
 
@@ -179,7 +179,7 @@
 
 void JSONStream::PostNullReply(Dart_Port port) {
   PortMap::PostMessage(
-      new Message(port, Object::null(), Message::kNormalPriority));
+      Message::New(port, Object::null(), Message::kNormalPriority));
 }
 
 static void Finalizer(void* isolate_callback_data,
@@ -500,6 +500,14 @@
   va_end(args);
 }
 
+void JSONObject::AddServiceId(const char* format, ...) const {
+  // Add the id property.
+  va_list args;
+  va_start(args, format);
+  stream_->VPrintfProperty("id", format, args);
+  va_end(args);
+}
+
 void JSONObject::AddLocation(const Script& script,
                              TokenPosition token_pos,
                              TokenPosition end_token_pos) const {
@@ -516,10 +524,9 @@
   ASSERT(bpt_loc->IsResolved());
 
   Zone* zone = Thread::Current()->zone();
-  Library& library = Library::Handle(zone);
   Script& script = Script::Handle(zone);
   TokenPosition token_pos = TokenPosition::kNoSource;
-  bpt_loc->GetCodeLocation(&library, &script, &token_pos);
+  bpt_loc->GetCodeLocation(&script, &token_pos);
   AddLocation(script, token_pos);
 }
 
@@ -528,10 +535,9 @@
   ASSERT(!bpt_loc->IsResolved());
 
   Zone* zone = Thread::Current()->zone();
-  Library& library = Library::Handle(zone);
   Script& script = Script::Handle(zone);
   TokenPosition token_pos = TokenPosition::kNoSource;
-  bpt_loc->GetCodeLocation(&library, &script, &token_pos);
+  bpt_loc->GetCodeLocation(&script, &token_pos);
 
   JSONObject location(this, "location");
   location.AddProperty("type", "UnresolvedSourceLocation");
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index c44a5f6..98d39f3 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -307,6 +307,7 @@
   void AddServiceId(const Object& o) const { stream_->PrintServiceId(o); }
 
   void AddFixedServiceId(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3);
+  void AddServiceId(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3);
 
   void AddLocation(
       const Script& script,
diff --git a/runtime/vm/json_test.cc b/runtime/vm/json_test.cc
index 1746328..d25d01d 100644
--- a/runtime/vm/json_test.cc
+++ b/runtime/vm/json_test.cc
@@ -61,7 +61,7 @@
       JSONArray jsarr(&js);
       jsarr.AddValue(1.0);
     }
-    EXPECT_STREQ("[1.000000]", js.ToCString());
+    EXPECT_STREQ("[1.0]", js.ToCString());
   }
   {
     JSONStream js;
diff --git a/runtime/vm/json_writer.cc b/runtime/vm/json_writer.cc
index c3760a8..587bf15 100644
--- a/runtime/vm/json_writer.cc
+++ b/runtime/vm/json_writer.cc
@@ -4,9 +4,10 @@
 
 #include "platform/assert.h"
 
+#include "platform/unicode.h"
+#include "vm/double_conversion.h"
 #include "vm/json_writer.h"
 #include "vm/object.h"
-#include "vm/unicode.h"
 
 namespace dart {
 
@@ -117,8 +118,13 @@
 }
 
 void JSONWriter::PrintValue(double d) {
+  // Max length of a double in characters (including \0).
+  // See double_conversion.cc.
+  const size_t kBufferLen = 25;
+  char buffer[kBufferLen];
+  DoubleToCString(d, buffer, kBufferLen);
   PrintCommaIfNeeded();
-  buffer_.Printf("%f", d);
+  buffer_.Printf("%s", buffer);
 }
 
 static const char base64_digits[65] =
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index a4a6eea..ac4a5c7 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -17,25 +17,6 @@
 namespace dart {
 namespace kernel {
 
-bool FieldHasFunctionLiteralInitializer(const Field& field,
-                                        TokenPosition* start,
-                                        TokenPosition* end) {
-  Zone* zone = Thread::Current()->zone();
-  const Script& script = Script::Handle(zone, field.Script());
-
-  TranslationHelper translation_helper(Thread::Current());
-  translation_helper.InitFromScript(script);
-
-  KernelReaderHelper kernel_reader_helper(
-      zone, &translation_helper, Script::Handle(zone, field.Script()),
-      ExternalTypedData::Handle(zone, field.KernelData()),
-      field.KernelDataProgramOffset());
-  kernel_reader_helper.SetOffset(field.kernel_offset());
-  kernel::FieldHelper field_helper(&kernel_reader_helper);
-  field_helper.ReadUntilExcluding(kernel::FieldHelper::kEnd, true);
-  return field_helper.FieldHasFunctionLiteralInitializer(start, end);
-}
-
 KernelLineStartsReader::KernelLineStartsReader(
     const dart::TypedData& line_starts_data,
     dart::Zone* zone)
@@ -256,7 +237,7 @@
   return array_object.raw();
 }
 
-static void ProcessTokenPositionsEntry(
+static void CollectKernelDataTokenPositions(
     const ExternalTypedData& kernel_data,
     const Script& script,
     const Script& entry_script,
@@ -278,6 +259,64 @@
   token_position_collector.CollectTokenPositions(kernel_offset);
 }
 
+static void CollectBytecodeTokenPositions(
+    const Bytecode& bytecode,
+    Zone* zone,
+    GrowableArray<intptr_t>* token_positions,
+    GrowableArray<intptr_t>* yield_positions) {
+  ASSERT(bytecode.HasSourcePositions());
+  BytecodeSourcePositionsIterator iter(zone, bytecode);
+  while (iter.MoveNext()) {
+    const TokenPosition pos = iter.TokenPos();
+    if (pos.IsReal()) {
+      // TODO(alexmarkov): collect yield positions from bytecode.
+      token_positions->Add(pos.value());
+    }
+  }
+}
+
+static void CollectBytecodeFunctionTokenPositions(
+    const Function& function,
+    GrowableArray<intptr_t>* token_positions,
+    GrowableArray<intptr_t>* yield_positions) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  ASSERT(function.is_declared_in_bytecode());
+  if (!function.HasBytecode()) {
+    const Object& result = Object::Handle(
+        zone, BytecodeReader::ReadFunctionBytecode(thread, function));
+    if (!result.IsNull()) {
+      Exceptions::PropagateError(Error::Cast(result));
+    }
+  }
+  Bytecode& bytecode = Bytecode::Handle(zone, function.bytecode());
+  ASSERT(!bytecode.IsNull());
+  if (bytecode.HasSourcePositions()) {
+    CollectBytecodeTokenPositions(bytecode, zone, token_positions,
+                                  yield_positions);
+    // Find closure functions in the object pool.
+    const ObjectPool& pool = ObjectPool::Handle(zone, bytecode.object_pool());
+    Object& object = Object::Handle(zone);
+    Function& closure = Function::Handle(zone);
+    for (intptr_t i = 0; i < pool.Length(); i++) {
+      ObjectPool::EntryType entry_type = pool.TypeAt(i);
+      if (entry_type != ObjectPool::EntryType::kTaggedObject) {
+        continue;
+      }
+      object = pool.ObjectAt(i);
+      if (object.IsFunction()) {
+        closure ^= object.raw();
+        if ((closure.kind() == RawFunction::kClosureFunction) &&
+            (closure.raw() != function.raw())) {
+          bytecode = closure.bytecode();
+          CollectBytecodeTokenPositions(bytecode, zone, token_positions,
+                                        yield_positions);
+        }
+      }
+    }
+  }
+}
+
 void CollectTokenPositionsFor(const Script& interesting_script) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
@@ -325,29 +364,30 @@
               continue;
             }
             data = temp_field.KernelData();
-            ProcessTokenPositionsEntry(data, interesting_script, entry_script,
-                                       temp_field.kernel_offset(),
-                                       temp_field.KernelDataProgramOffset(),
-                                       zone, &helper, &token_positions,
-                                       &yield_positions);
+            CollectKernelDataTokenPositions(
+                data, interesting_script, entry_script,
+                temp_field.kernel_offset(),
+                temp_field.KernelDataProgramOffset(), zone, &helper,
+                &token_positions, &yield_positions);
           }
           temp_array = klass.functions();
           for (intptr_t i = 0; i < temp_array.Length(); ++i) {
             temp_function ^= temp_array.At(i);
             entry_script = temp_function.script();
-            // TODO(alexmarkov): collect token positions from bytecode
-            if (temp_function.is_declared_in_bytecode()) {
-              continue;
-            }
             if (entry_script.raw() != interesting_script.raw()) {
               continue;
             }
-            data = temp_function.KernelData();
-            ProcessTokenPositionsEntry(data, interesting_script, entry_script,
-                                       temp_function.kernel_offset(),
-                                       temp_function.KernelDataProgramOffset(),
-                                       zone, &helper, &token_positions,
-                                       &yield_positions);
+            if (temp_function.is_declared_in_bytecode()) {
+              CollectBytecodeFunctionTokenPositions(
+                  temp_function, &token_positions, &yield_positions);
+            } else {
+              data = temp_function.KernelData();
+              CollectKernelDataTokenPositions(
+                  data, interesting_script, entry_script,
+                  temp_function.kernel_offset(),
+                  temp_function.KernelDataProgramOffset(), zone, &helper,
+                  &token_positions, &yield_positions);
+            }
           }
         } else {
           // Class isn't finalized yet: read the data attached to it.
@@ -362,27 +402,28 @@
           if (entry_script.raw() != interesting_script.raw()) {
             continue;
           }
-          ProcessTokenPositionsEntry(data, interesting_script, entry_script,
-                                     class_offset, library_kernel_offset, zone,
-                                     &helper, &token_positions,
-                                     &yield_positions);
+          CollectKernelDataTokenPositions(data, interesting_script,
+                                          entry_script, class_offset,
+                                          library_kernel_offset, zone, &helper,
+                                          &token_positions, &yield_positions);
         }
       } else if (entry.IsFunction()) {
         temp_function ^= entry.raw();
-        // TODO(alexmarkov): collect token positions from bytecode
-        if (temp_function.is_declared_in_bytecode()) {
-          continue;
-        }
         entry_script = temp_function.script();
         if (entry_script.raw() != interesting_script.raw()) {
           continue;
         }
-        data = temp_function.KernelData();
-        ProcessTokenPositionsEntry(data, interesting_script, entry_script,
-                                   temp_function.kernel_offset(),
-                                   temp_function.KernelDataProgramOffset(),
-                                   zone, &helper, &token_positions,
-                                   &yield_positions);
+        if (temp_function.is_declared_in_bytecode()) {
+          CollectBytecodeFunctionTokenPositions(temp_function, &token_positions,
+                                                &yield_positions);
+        } else {
+          data = temp_function.KernelData();
+          CollectKernelDataTokenPositions(
+              data, interesting_script, entry_script,
+              temp_function.kernel_offset(),
+              temp_function.KernelDataProgramOffset(), zone, &helper,
+              &token_positions, &yield_positions);
+        }
       } else if (entry.IsField()) {
         const Field& field = Field::Cast(entry);
         // TODO(alexmarkov): collect token positions from bytecode
@@ -395,10 +436,10 @@
           continue;
         }
         data = field.KernelData();
-        ProcessTokenPositionsEntry(data, interesting_script, entry_script,
-                                   field.kernel_offset(),
-                                   field.KernelDataProgramOffset(), zone,
-                                   &helper, &token_positions, &yield_positions);
+        CollectKernelDataTokenPositions(
+            data, interesting_script, entry_script, field.kernel_offset(),
+            field.KernelDataProgramOffset(), zone, &helper, &token_positions,
+            &yield_positions);
       }
     }
   }
@@ -612,19 +653,19 @@
   TranslationHelper translation_helper(thread);
   translation_helper.InitFromScript(script);
 
-  KernelReaderHelper reader_helper(
-      zone, &translation_helper, script,
-      ExternalTypedData::Handle(zone, function.KernelData()),
-      function.KernelDataProgramOffset());
-
   if (function.is_declared_in_bytecode()) {
-    BytecodeReaderHelper bytecode_reader_helper(&reader_helper, nullptr,
+    BytecodeReaderHelper bytecode_reader_helper(&translation_helper, nullptr,
                                                 nullptr);
     bytecode_reader_helper.ReadParameterCovariance(function, is_covariant,
                                                    is_generic_covariant_impl);
     return;
   }
 
+  KernelReaderHelper reader_helper(
+      zone, &translation_helper, script,
+      ExternalTypedData::Handle(zone, function.KernelData()),
+      function.KernelDataProgramOffset());
+
   reader_helper.SetOffset(function.kernel_offset());
   reader_helper.ReadUntilFunctionNode();
 
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index 0de9d5d..4e66b89 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -187,10 +187,6 @@
   DISALLOW_COPY_AND_ASSIGN(KernelLineStartsReader);
 };
 
-bool FieldHasFunctionLiteralInitializer(const Field& field,
-                                        TokenPosition* start,
-                                        TokenPosition* end);
-
 void CollectTokenPositionsFor(const Script& script);
 
 RawObject* EvaluateMetadata(const Field& metadata_field,
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 4862219..abf5036 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -102,7 +102,7 @@
                      error);
       }
       free(error);
-      error = NULL;
+      error = nullptr;
       KernelIsolate::SetKernelIsolate(NULL);
       KernelIsolate::InitializingFailed();
       return;
@@ -388,7 +388,7 @@
 class KernelCompilationRequest : public ValueObject {
  public:
   KernelCompilationRequest()
-      : monitor_(new Monitor()),
+      : monitor_(),
         port_(Dart_NewNativePort("kernel-compilation-port",
                                  &HandleResponse,
                                  false)),
@@ -405,7 +405,6 @@
   ~KernelCompilationRequest() {
     UnregisterRequest(this);
     Dart_CloseNativePort(port_);
-    delete monitor_;
   }
 
   Dart_KernelCompilationResult SendAndWaitForResponse(
@@ -527,7 +526,7 @@
 
       // Wait for reply to arrive.
       VMTagScope tagScope(thread, VMTag::kLoadWaitTagId);
-      MonitorLocker ml(monitor_);
+      MonitorLocker ml(&monitor_);
       while (result_.status == Dart_KernelCompilationStatus_Unknown) {
         ml.Wait();
       }
@@ -715,7 +714,7 @@
 
     // Wait for reply to arrive.
     VMTagScope tagScope(Thread::Current(), VMTag::kLoadWaitTagId);
-    MonitorLocker ml(monitor_);
+    MonitorLocker ml(&monitor_);
     while (result_.status == Dart_KernelCompilationStatus_Unknown) {
       ml.Wait();
     }
@@ -756,7 +755,7 @@
 
     Dart_CObject** response = message->value.as_array.values;
 
-    MonitorLocker ml(monitor_);
+    MonitorLocker ml(&monitor_);
 
     ASSERT(response[0]->type == Dart_CObject_kInt32);
     result_.status = static_cast<Dart_KernelCompilationStatus>(
@@ -822,14 +821,14 @@
   // Guarded by requests_monitor_ lock.
   static KernelCompilationRequest* requests_;
 
-  Monitor* monitor_;
+  Monitor monitor_;
   Dart_Port port_;
 
   // Linked list of active requests. Guarded by requests_monitor_ lock.
   KernelCompilationRequest* next_;
   KernelCompilationRequest* prev_;
 
-  Dart_KernelCompilationResult result_;
+  Dart_KernelCompilationResult result_ = {};
 };
 
 Monitor* KernelCompilationRequest::requests_monitor_ = new Monitor();
@@ -849,7 +848,7 @@
   // to finish initialization.
   Dart_Port kernel_port = WaitForKernelPort();
   if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result;
+    Dart_KernelCompilationResult result = {};
     result.status = Dart_KernelCompilationStatus_Unknown;
     result.error = strdup("Error while initializing Kernel isolate");
     return result;
@@ -866,7 +865,7 @@
 Dart_KernelCompilationResult KernelIsolate::ListDependencies() {
   Dart_Port kernel_port = WaitForKernelPort();
   if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result;
+    Dart_KernelCompilationResult result = {};
     result.status = Dart_KernelCompilationStatus_Unknown;
     result.error = strdup("Error while initializing Kernel isolate");
     return result;
@@ -883,7 +882,7 @@
   // to finish initialization.
   Dart_Port kernel_port = WaitForKernelPort();
   if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result;
+    Dart_KernelCompilationResult result = {};
     result.status = Dart_KernelCompilationStatus_Unknown;
     result.error = strdup("Error while initializing Kernel isolate");
     return result;
@@ -904,7 +903,7 @@
     bool is_static) {
   Dart_Port kernel_port = WaitForKernelPort();
   if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result;
+    Dart_KernelCompilationResult result = {};
     result.status = Dart_KernelCompilationStatus_Unknown;
     result.error = strdup("Error while initializing Kernel isolate");
     return result;
@@ -924,7 +923,7 @@
   // to finish initialization.
   Dart_Port kernel_port = WaitForKernelPort();
   if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result;
+    Dart_KernelCompilationResult result = {};
     result.status = Dart_KernelCompilationStatus_Unknown;
     result.error = strdup("Error while initializing Kernel isolate");
     return result;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index b90a609..b5001d1 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -404,6 +404,10 @@
       Z, reader.ExternalDataFromTo(program_->metadata_mappings_offset(),
                                    program_->string_table_offset()));
 
+#if defined(DEBUG)
+  MetadataHelper::VerifyMetadataMappings(metadata_mappings);
+#endif
+
   const Array& libraries_cache =
       Array::Handle(Z, HashTables::New<UnorderedHashMap<SmiTraits>>(
                            program_->library_count(), Heap::kOld));
@@ -961,13 +965,6 @@
       return;
     }
   }
-  if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) {
-    if (bytecode_metadata_helper_.HasBytecode(field.kernel_offset() +
-                                              library_kernel_offset_)) {
-      field.set_has_initializer(true);
-      return;
-    }
-  }
   field.set_has_initializer(false);
 }
 
@@ -1062,8 +1059,8 @@
   Class& toplevel_class =
       Class::Handle(Z, Class::New(library, Symbols::TopLevel(), script,
                                   TokenPosition::kNoSource, register_class));
+  toplevel_class.set_is_declaration_loaded();
   toplevel_class.set_is_type_finalized();
-  toplevel_class.set_is_cycle_free();
   library.set_toplevel_class(toplevel_class);
 
   library_helper.ReadUntilExcluding(LibraryHelper::kDependencies);
@@ -1382,6 +1379,8 @@
   if (class_helper->is_transformed_mixin_application()) {
     klass->set_is_transformed_mixin_application();
   }
+
+  klass->set_is_declaration_loaded();
 }
 
 void KernelLoader::LoadClass(const Library& library,
@@ -1434,10 +1433,9 @@
       helper_.ReadListLength();  // read type_parameters list length.
 
   ActiveClassScope active_class_scope(&active_class_, out_class);
-  if (!out_class->is_cycle_free()) {
+  if (!out_class->is_declaration_loaded()) {
     LoadPreliminaryClass(&class_helper, type_parameter_counts);
   } else {
-    // do not use type parameters with cycle_free
     ASSERT(type_parameter_counts == 0);
     class_helper.SetJustRead(ClassHelper::kTypeParameters);
   }
@@ -1996,14 +1994,14 @@
     wrapper.uri = &uri_string;
     UriToSourceTableEntry* pair = uri_to_source_table->LookupValue(&wrapper);
     if (pair != nullptr) {
-      sources ^= pair->sources->raw();
-      line_starts ^= pair->line_starts->raw();
+      sources = pair->sources->raw();
+      line_starts = pair->line_starts->raw();
     }
   }
 
   if (sources.IsNull() || line_starts.IsNull()) {
     const String& script_source = helper_.GetSourceFor(index);
-    line_starts ^= helper_.GetLineStartsFor(index);
+    line_starts = helper_.GetLineStartsFor(index);
 
     if (script_source.raw() == Symbols::Empty().raw() &&
         line_starts.Length() == 0 && uri_string.Length() > 0) {
@@ -2017,8 +2015,8 @@
         lib ^= libs.At(i);
         script = lib.LookupScript(uri_string, /* useResolvedUri = */ true);
         if (!script.IsNull() && script.kind() == RawScript::kKernelTag) {
-          sources ^= script.Source();
-          line_starts ^= script.line_starts();
+          sources = script.Source();
+          line_starts = script.line_starts();
           break;
         }
       }
@@ -2067,12 +2065,6 @@
   if (field_helper->IsStatic()) {
     bool has_initializer = (tag == kSomething);
 
-    if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) {
-      has_initializer = has_initializer ||
-                        bytecode_metadata_helper_.HasBytecode(
-                            field.kernel_offset() + library_kernel_offset_);
-    }
-
     if (!has_initializer) {
       // Static fields without an initializer are implicitly initialized to
       // null. We do not need a getter.
@@ -2091,7 +2083,7 @@
       Z,
       Function::New(
           getter_name,
-          field_helper->IsStatic() ? RawFunction::kImplicitStaticFinalGetter
+          field_helper->IsStatic() ? RawFunction::kImplicitStaticGetter
                                    : RawFunction::kImplicitGetter,
           field_helper->IsStatic(),
           // The functions created by the parser have is_const for static fields
diff --git a/runtime/vm/libfuzzer/README.md b/runtime/vm/libfuzzer/README.md
new file mode 100644
index 0000000..7820422
--- /dev/null
+++ b/runtime/vm/libfuzzer/README.md
@@ -0,0 +1,64 @@
+DartLibFuzzer
+=============
+
+DartLibFuzzer is a fuzzing tool built with LibFuzzer, which
+is an in-process, coverage-guided, evolutionary fuzzing engine.
+The DartLibFuzzer tool consists of a collection of "target
+functions", each of which stresses a particular part of the
+Dart runtime and compiler.
+
+How to build and run DartLibFuzzer
+==================================
+
+Build the dart_libfuzzer binary as follows (first either export
+DART_USE_ASAN=1 or run ./tools/gn.py --mode=debug --asan):
+
+    ./tools/build.py \
+      -m [all|debug|release|product] \
+      -a [x64|arm64|simarm64] \
+      dart_libfuzzer
+
+Then, to start a blank fuzzing session on a particular target
+function (as defined in dart_libfuzzer.cc), run:
+
+    dart_libfuzzer [--t=<target-function>]
+
+To start a fuzzing session with an initial corpus inside
+the directory CORPUS, run:
+
+    dart_libfuzzer CORPUS
+
+Background
+==========
+
+Although test suites are extremely useful to validate the correctness of a
+system and to ensure that no regressions occur, any test suite is necessarily
+finite in size and scope. Tests typically focus on validating particular
+features by means of code sequences most programmers would expect. Regression
+tests often use slightly less idiomatic code sequences, since they reflect
+problems that were not anticipated originally, but occurred “in the field”.
+Still, any test suite leaves the developer wondering whether undetected bugs
+and flaws still linger in the system.
+
+Over the years, fuzz testing has gained popularity as a testing technique for
+discovering such lingering bugs, including bugs that can bring down a system
+in an unexpected way. Fuzzing refers to feeding a large amount of random data
+as input to a system in an attempt to find bugs or make it crash.
+Generation-based fuzz testing constructs random, but properly formatted input
+data. Mutation-based fuzz testing applies small random changes to existing
+inputs in order to detect shortcomings in a system. Profile-guided or
+coverage-guided fuzz testing adds a direction to the way these random changes
+are applied. Multi-layered approaches generate random inputs that are
+subsequently mutated at various stages of execution.
+
+The randomness of fuzz testing implies that the size and scope of testing is
+no longer bounded. Every new run can potentially discover bugs and crashes
+that were hereto undetected.
+
+Links
+=====
+
+* [Dart bugs found with fuzzing](https://github.com/dart-lang/sdk/issues?utf8=%E2%9C%93&q=label%3Adartfuzz+)
+* [DartFuzz](https://github.com/dart-lang/sdk/tree/master/runtime/tools/dartfuzz)
+* [DartLibFuzzer](https://github.com/dart-lang/sdk/tree/master/runtime/vm/libfuzzer)
+* [LibFuzzer](https://llvm.org/docs/LibFuzzer.html)
diff --git a/runtime/vm/libfuzzer/dart_libfuzzer.cc b/runtime/vm/libfuzzer/dart_libfuzzer.cc
new file mode 100644
index 0000000..5c870ab
--- /dev/null
+++ b/runtime/vm/libfuzzer/dart_libfuzzer.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2019, 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 <stddef.h>
+#include <stdint.h>
+
+#include "bin/dartutils.h"
+#include "platform/text_buffer.h"
+#include "platform/unicode.h"
+#include "platform/utils.h"
+#include "vm/json_writer.h"
+
+// Defines target function.
+static int target = 0;
+
+// Target function that stresses some unicode methods.
+// Found: http://dartbug.com/36235
+static int TestUnicode(const uint8_t* Data, size_t Size) {
+  dart::Utf8::Type type = dart::Utf8::kLatin1;
+  dart::Utf8::CodeUnitCount(Data, Size, &type);
+  dart::Utf8::IsValid(Data, Size);
+  int32_t dst = 0;
+  dart::Utf8::Decode(Data, Size, &dst);
+  uint16_t dst16[1024];
+  dart::Utf8::DecodeToUTF16(Data, Size, dst16, 1024);
+  int32_t dst32[1024];
+  dart::Utf8::DecodeToUTF32(Data, Size, dst32, 1024);
+  dart::Utf8::ReportInvalidByte(Data, Size, 1024);
+  return 0;
+}
+
+// Target function that stresses various utilities.
+// Found: http:/dartbug.com/36818
+static int TestUtilities(const uint8_t* Data, size_t Size) {
+  dart::Utils::StringHash(reinterpret_cast<const char*>(Data), Size);
+  dart::bin::DartUtils::SniffForMagicNumber(Data, Size);
+  // Text buffer.
+  dart::TextBuffer buffer(1);
+  for (size_t i = 0; i < Size; i++) {
+    buffer.AddChar(Data[i]);
+  }
+  if (static_cast<size_t>(buffer.length()) != Size) return 1;
+  buffer.AddRaw(Data, Size);
+  if (static_cast<size_t>(buffer.length()) != 2 * Size) return 1;
+  free(buffer.Steal());
+  buffer.AddRaw(Data, Size);
+  if (static_cast<size_t>(buffer.length()) != Size) return 1;
+  // Json writer.
+  dart::JSONWriter writer(1);
+  writer.OpenObject("object");
+  writer.AppendSerializedObject(Data, Size);
+  writer.CloseObject();
+  for (size_t i = 0; i < Size; i++) {
+    writer.PrintValue(static_cast<intptr_t>(Data[i]));
+  }
+  writer.PrintValueBase64(Data, Size);
+  return 0;
+}
+
+// Dart VM specific initialization.
+static int InitDartVM() {
+  // TODO(ajcbik): one-time setup of Dart VM.
+  return 0;
+}
+
+// Libfuzzer one time initialization.
+extern "C" int LLVMFuzzerInitialize(int* argc_in, char*** argv_in) {
+  // Parse --t=<target> from command line.
+  int argc = *argc_in;
+  char** argv = *argv_in;
+  while (--argc > 0) {
+    char* ptr = *++argv;
+    if (*ptr++ == '-' && *ptr++ == '-' && *ptr++ == 't' && *ptr++ == '=') {
+      target = atoi(ptr);
+    }
+  }
+  // Initialize Dart VM.
+  return InitDartVM();
+}
+
+// Libfuzzer target functions:
+//  0 : unicode
+//  1 : utilies
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
+  switch (target) {
+    case 0:
+      return TestUnicode(Data, Size);
+    case 1:
+      return TestUtilities(Data, Size);
+    default:
+      fprintf(stderr, "dart_libfuzzer: invalid target --t=%d\n", target);
+      return 1;
+  }
+}
diff --git a/runtime/vm/lockers.h b/runtime/vm/lockers.h
index 8cce8c3..de62b6c 100644
--- a/runtime/vm/lockers.h
+++ b/runtime/vm/lockers.h
@@ -46,7 +46,11 @@
 class MutexLocker : public ValueObject {
  public:
   explicit MutexLocker(Mutex* mutex, bool no_safepoint_scope = true)
-      : mutex_(mutex), no_safepoint_scope_(no_safepoint_scope) {
+      :
+#if defined(DEBUG)
+        no_safepoint_scope_(no_safepoint_scope),
+#endif
+        mutex_(mutex) {
     ASSERT(mutex != NULL);
 #if defined(DEBUG)
     if (no_safepoint_scope_) {
@@ -88,8 +92,8 @@
   }
 
  private:
+  DEBUG_ONLY(bool no_safepoint_scope_;)
   Mutex* const mutex_;
-  bool no_safepoint_scope_;
 
   DISALLOW_COPY_AND_ASSIGN(MutexLocker);
 };
diff --git a/runtime/vm/message.cc b/runtime/vm/message.cc
index 985c5b5..0bfca6d 100644
--- a/runtime/vm/message.cc
+++ b/runtime/vm/message.cc
@@ -4,6 +4,8 @@
 
 #include "vm/message.h"
 
+#include <utility>
+
 #include "vm/dart_entry.h"
 #include "vm/json_stream.h"
 #include "vm/object.h"
@@ -11,6 +13,8 @@
 
 namespace dart {
 
+const Dart_Port Message::kIllegalPort = 0;
+
 Message::Message(Dart_Port dest_port,
                  uint8_t* snapshot,
                  intptr_t snapshot_length,
@@ -93,7 +97,10 @@
   ASSERT(head_ == NULL);
 }
 
-void MessageQueue::Enqueue(Message* msg, bool before_events) {
+void MessageQueue::Enqueue(std::unique_ptr<Message> msg0, bool before_events) {
+  // TODO(mdempsky): Use unique_ptr internally?
+  Message* msg = msg0.release();
+
   // Make sure messages are not reused.
   ASSERT(msg->next_ == NULL);
   if (head_ == NULL) {
@@ -134,34 +141,32 @@
   }
 }
 
-Message* MessageQueue::Dequeue() {
+std::unique_ptr<Message> MessageQueue::Dequeue() {
   Message* result = head_;
-  if (result != NULL) {
+  if (result != nullptr) {
     head_ = result->next_;
     // The following update to tail_ is not strictly needed.
-    if (head_ == NULL) {
-      tail_ = NULL;
+    if (head_ == nullptr) {
+      tail_ = nullptr;
     }
 #if defined(DEBUG)
     result->next_ = result;  // Make sure to trigger ASSERT in Enqueue.
 #endif                       // DEBUG
-    return result;
+    return std::unique_ptr<Message>(result);
   }
-  return NULL;
+  return nullptr;
 }
 
 void MessageQueue::Clear() {
-  Message* cur = head_;
-  head_ = NULL;
-  tail_ = NULL;
-  while (cur != NULL) {
-    Message* next = cur->next_;
+  std::unique_ptr<Message> cur(head_);
+  head_ = nullptr;
+  tail_ = nullptr;
+  while (cur != nullptr) {
+    std::unique_ptr<Message> next(cur->next_);
     if (cur->RedirectToDeliveryFailurePort()) {
-      PortMap::PostMessage(cur);
-    } else {
-      delete cur;
+      PortMap::PostMessage(std::move(cur));
     }
-    cur = next;
+    cur = std::move(next);
   }
 }
 
diff --git a/runtime/vm/message.h b/runtime/vm/message.h
index 51ff2551..03f3074 100644
--- a/runtime/vm/message.h
+++ b/runtime/vm/message.h
@@ -5,6 +5,9 @@
 #ifndef RUNTIME_VM_MESSAGE_H_
 #define RUNTIME_VM_MESSAGE_H_
 
+#include <memory>
+#include <utility>
+
 #include "platform/assert.h"
 #include "vm/allocation.h"
 #include "vm/finalizable_data.h"
@@ -40,7 +43,7 @@
   } OOBMsgTag;
 
   // A port number which is never used.
-  static const Dart_Port kIllegalPort = 0;
+  static const Dart_Port kIllegalPort;
 
   // A new message to be sent between two isolates. The data handed to this
   // message will be disposed by calling free() once the message object is
@@ -61,6 +64,11 @@
 
   ~Message();
 
+  template <typename... Args>
+  static std::unique_ptr<Message> New(Args&&... args) {
+    return std::unique_ptr<Message>(new Message(std::forward<Args>(args)...));
+  }
+
   Dart_Port dest_port() const { return dest_port_; }
 
   uint8_t* snapshot() const {
@@ -114,11 +122,11 @@
   MessageQueue();
   ~MessageQueue();
 
-  void Enqueue(Message* msg, bool before_events);
+  void Enqueue(std::unique_ptr<Message> msg, bool before_events);
 
   // Gets the next message from the message queue or NULL if no
   // message is available.  This function will not block.
-  Message* Dequeue();
+  std::unique_ptr<Message> Dequeue();
 
   bool IsEmpty() { return head_ == NULL; }
 
diff --git a/runtime/vm/message_handler.cc b/runtime/vm/message_handler.cc
index c1ae538..da32e9a 100644
--- a/runtime/vm/message_handler.cc
+++ b/runtime/vm/message_handler.cc
@@ -121,7 +121,8 @@
   ASSERT(task_running);
 }
 
-void MessageHandler::PostMessage(Message* message, bool before_events) {
+void MessageHandler::PostMessage(std::unique_ptr<Message> message,
+                                 bool before_events) {
   Message::Priority saved_priority;
   bool task_running = true;
   {
@@ -149,14 +150,13 @@
 
     saved_priority = message->priority();
     if (message->IsOOB()) {
-      oob_queue_->Enqueue(message, before_events);
+      oob_queue_->Enqueue(std::move(message), before_events);
     } else {
-      queue_->Enqueue(message, before_events);
+      queue_->Enqueue(std::move(message), before_events);
     }
     if (paused_for_messages_) {
       ml.Notify();
     }
-    message = NULL;  // Do not access message.  May have been deleted.
 
     if ((pool_ != NULL) && (task_ == NULL)) {
       ASSERT(!delete_me_);
@@ -170,10 +170,11 @@
   MessageNotify(saved_priority);
 }
 
-Message* MessageHandler::DequeueMessage(Message::Priority min_priority) {
+std::unique_ptr<Message> MessageHandler::DequeueMessage(
+    Message::Priority min_priority) {
   // TODO(turnidge): Add assert that monitor_ is held here.
-  Message* message = oob_queue_->Dequeue();
-  if ((message == NULL) && (min_priority < Message::kOOBPriority)) {
+  std::unique_ptr<Message> message = oob_queue_->Dequeue();
+  if ((message == nullptr) && (min_priority < Message::kOOBPriority)) {
     message = queue_->Dequeue();
   }
   return message;
@@ -196,8 +197,8 @@
   Message::Priority min_priority =
       ((allow_normal_messages && !paused()) ? Message::kNormalPriority
                                             : Message::kOOBPriority);
-  Message* message = DequeueMessage(min_priority);
-  while (message != NULL) {
+  std::unique_ptr<Message> message = DequeueMessage(min_priority);
+  while (message != nullptr) {
     intptr_t message_len = message->Size();
     if (FLAG_trace_isolates) {
       OS::PrintErr(
@@ -214,11 +215,10 @@
     ml->Exit();
     Message::Priority saved_priority = message->priority();
     Dart_Port saved_dest_port = message->dest_port();
-    MessageStatus status = HandleMessage(message);
+    MessageStatus status = HandleMessage(std::move(message));
     if (status > max_status) {
       max_status = status;
     }
-    message = NULL;  // May be deleted by now.
     ml->Enter();
     if (FLAG_trace_isolates) {
       OS::PrintErr(
diff --git a/runtime/vm/message_handler.h b/runtime/vm/message_handler.h
index 46dd862..babc541 100644
--- a/runtime/vm/message_handler.h
+++ b/runtime/vm/message_handler.h
@@ -5,6 +5,8 @@
 #ifndef RUNTIME_VM_MESSAGE_HANDLER_H_
 #define RUNTIME_VM_MESSAGE_HANDLER_H_
 
+#include <memory>
+
 #include "vm/isolate.h"
 #include "vm/lockers.h"
 #include "vm/message.h"
@@ -168,7 +170,8 @@
   // Posts a message on this handler's message queue.
   // If before_events is true, then the message is enqueued before any pending
   // events, but after any pending isolate library events.
-  void PostMessage(Message* message, bool before_events = false);
+  void PostMessage(std::unique_ptr<Message> message,
+                   bool before_events = false);
 
   // Notifies this handler that a port is being closed.
   void ClosePort(Dart_Port port);
@@ -195,7 +198,7 @@
   // Handles a single message.  Provided by subclass.
   //
   // Returns true on success.
-  virtual MessageStatus HandleMessage(Message* message) = 0;
+  virtual MessageStatus HandleMessage(std::unique_ptr<Message> message) = 0;
 
   virtual void NotifyPauseOnStart() {}
   virtual void NotifyPauseOnExit() {}
@@ -229,7 +232,7 @@
 
   // Dequeue the next message.  Prefer messages from the oob_queue_ to
   // messages from the queue_.
-  Message* DequeueMessage(Message::Priority min_priority);
+  std::unique_ptr<Message> DequeueMessage(Message::Priority min_priority);
 
   void ClearOOBQueue();
 
diff --git a/runtime/vm/message_handler_test.cc b/runtime/vm/message_handler_test.cc
index 0677178..76c46a1 100644
--- a/runtime/vm/message_handler_test.cc
+++ b/runtime/vm/message_handler_test.cc
@@ -13,7 +13,9 @@
   explicit MessageHandlerTestPeer(MessageHandler* handler)
       : handler_(handler) {}
 
-  void PostMessage(Message* message) { handler_->PostMessage(message); }
+  void PostMessage(std::unique_ptr<Message> message) {
+    handler_->PostMessage(std::move(message));
+  }
   void ClosePort(Dart_Port port) { handler_->ClosePort(port); }
   void CloseAllPorts() { handler_->CloseAllPorts(); }
 
@@ -47,11 +49,10 @@
 
   void MessageNotify(Message::Priority priority) { notify_count_++; }
 
-  MessageStatus HandleMessage(Message* message) {
+  MessageStatus HandleMessage(std::unique_ptr<Message> message) {
     // For testing purposes, keep a list of the ports
     // for all messages we receive.
     AddPortToBuffer(message->dest_port());
-    delete message;
     message_count_++;
     MessageStatus status = kOK;
     if (results_ != NULL) {
@@ -116,9 +117,10 @@
   return (reinterpret_cast<TestMessageHandler*>(data))->End();
 }
 
-static Message* BlankMessage(Dart_Port dest, Message::Priority priority) {
-  return new Message(dest, reinterpret_cast<uint8_t*>(malloc(1)), 1, NULL,
-                     priority);
+static std::unique_ptr<Message> BlankMessage(Dart_Port dest,
+                                             Message::Priority priority) {
+  return Message::New(dest, reinterpret_cast<uint8_t*>(malloc(1)), 1, nullptr,
+                      priority);
 }
 
 VM_UNIT_TEST_CASE(MessageHandler_PostMessage) {
@@ -127,28 +129,28 @@
   EXPECT_EQ(0, handler.notify_count());
 
   // Post a message.
-  Message* message = BlankMessage(1, Message::kNormalPriority);
-  handler_peer.PostMessage(message);
+  std::unique_ptr<Message> message = BlankMessage(1, Message::kNormalPriority);
+  Message* raw_message = message.get();
+  handler_peer.PostMessage(std::move(message));
 
   // The notify callback is called.
   EXPECT_EQ(1, handler.notify_count());
 
   // The message has been added to the correct queue.
-  EXPECT(message == handler_peer.queue()->Dequeue());
-  EXPECT(NULL == handler_peer.oob_queue()->Dequeue());
-  delete message;
+  EXPECT(raw_message == handler_peer.queue()->Dequeue().get());
+  EXPECT(nullptr == handler_peer.oob_queue()->Dequeue());
 
   // Post an oob message.
   message = BlankMessage(1, Message::kOOBPriority);
-  handler_peer.PostMessage(message);
+  raw_message = message.get();
+  handler_peer.PostMessage(std::move(message));
 
   // The notify callback is called.
   EXPECT_EQ(2, handler.notify_count());
 
   // The message has been added to the correct queue.
-  EXPECT(message == handler_peer.oob_queue()->Dequeue());
-  EXPECT(NULL == handler_peer.queue()->Dequeue());
-  delete message;
+  EXPECT(raw_message == handler_peer.oob_queue()->Dequeue().get());
+  EXPECT(nullptr == handler_peer.queue()->Dequeue());
 }
 
 VM_UNIT_TEST_CASE(MessageHandler_HasOOBMessages) {
@@ -158,8 +160,8 @@
   EXPECT(!handler.HasOOBMessages());
 
   // Post a normal message.
-  Message* message = BlankMessage(1, Message::kNormalPriority);
-  handler_peer.PostMessage(message);
+  std::unique_ptr<Message> message = BlankMessage(1, Message::kNormalPriority);
+  handler_peer.PostMessage(std::move(message));
   EXPECT(!handler.HasOOBMessages());
   {
     // Acquire ownership of message handler queues, verify one regular message.
@@ -169,7 +171,7 @@
 
   // Post an oob message.
   message = BlankMessage(1, Message::kOOBPriority);
-  handler_peer.PostMessage(message);
+  handler_peer.PostMessage(std::move(message));
   EXPECT(handler.HasOOBMessages());
   {
     // Acquire ownership of message handler queues, verify one regular and one
@@ -186,32 +188,31 @@
 VM_UNIT_TEST_CASE(MessageHandler_ClosePort) {
   TestMessageHandler handler;
   MessageHandlerTestPeer handler_peer(&handler);
-  Message* message1 = BlankMessage(1, Message::kNormalPriority);
-  handler_peer.PostMessage(message1);
-  Message* message2 = BlankMessage(2, Message::kNormalPriority);
-  handler_peer.PostMessage(message2);
+  std::unique_ptr<Message> message;
+  message = BlankMessage(1, Message::kNormalPriority);
+  Message* raw_message1 = message.get();
+  handler_peer.PostMessage(std::move(message));
+  message = BlankMessage(2, Message::kNormalPriority);
+  Message* raw_message2 = message.get();
+  handler_peer.PostMessage(std::move(message));
 
   handler_peer.ClosePort(1);
 
   // Closing the port does not drop the messages from the queue.
-  EXPECT(message1 == handler_peer.queue()->Dequeue());
-  EXPECT(message2 == handler_peer.queue()->Dequeue());
-  delete message1;
-  delete message2;
+  EXPECT(raw_message1 == handler_peer.queue()->Dequeue().get());
+  EXPECT(raw_message2 == handler_peer.queue()->Dequeue().get());
 }
 
 VM_UNIT_TEST_CASE(MessageHandler_CloseAllPorts) {
   TestMessageHandler handler;
   MessageHandlerTestPeer handler_peer(&handler);
-  Message* message1 = BlankMessage(1, Message::kNormalPriority);
-  handler_peer.PostMessage(message1);
-  Message* message2 = BlankMessage(2, Message::kNormalPriority);
-  handler_peer.PostMessage(message2);
+  handler_peer.PostMessage(BlankMessage(1, Message::kNormalPriority));
+  handler_peer.PostMessage(BlankMessage(2, Message::kNormalPriority));
 
   handler_peer.CloseAllPorts();
 
   // All messages are dropped from the queue.
-  EXPECT(NULL == handler_peer.queue()->Dequeue());
+  EXPECT(nullptr == handler_peer.queue()->Dequeue());
 }
 
 VM_UNIT_TEST_CASE(MessageHandler_HandleNextMessage) {
@@ -220,14 +221,10 @@
   Dart_Port port1 = PortMap::CreatePort(&handler);
   Dart_Port port2 = PortMap::CreatePort(&handler);
   Dart_Port port3 = PortMap::CreatePort(&handler);
-  Message* message1 = BlankMessage(port1, Message::kNormalPriority);
-  handler_peer.PostMessage(message1);
-  Message* oob_message1 = BlankMessage(port2, Message::kOOBPriority);
-  handler_peer.PostMessage(oob_message1);
-  Message* message2 = BlankMessage(port2, Message::kNormalPriority);
-  handler_peer.PostMessage(message2);
-  Message* oob_message2 = BlankMessage(port3, Message::kOOBPriority);
-  handler_peer.PostMessage(oob_message2);
+  handler_peer.PostMessage(BlankMessage(port1, Message::kNormalPriority));
+  handler_peer.PostMessage(BlankMessage(port2, Message::kOOBPriority));
+  handler_peer.PostMessage(BlankMessage(port2, Message::kNormalPriority));
+  handler_peer.PostMessage(BlankMessage(port3, Message::kOOBPriority));
 
   // We handle both oob messages and a single normal message.
   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
@@ -250,12 +247,9 @@
   Dart_Port port1 = PortMap::CreatePort(&handler);
   Dart_Port port2 = PortMap::CreatePort(&handler);
   Dart_Port port3 = PortMap::CreatePort(&handler);
-  Message* message1 = BlankMessage(port1, Message::kNormalPriority);
-  handler_peer.PostMessage(message1);
-  Message* oob_message1 = BlankMessage(port2, Message::kOOBPriority);
-  handler_peer.PostMessage(oob_message1);
-  Message* oob_message2 = BlankMessage(port3, Message::kOOBPriority);
-  handler_peer.PostMessage(oob_message2);
+  handler_peer.PostMessage(BlankMessage(port1, Message::kNormalPriority));
+  handler_peer.PostMessage(BlankMessage(port2, Message::kOOBPriority));
+  handler_peer.PostMessage(BlankMessage(port3, Message::kOOBPriority));
 
   // When we get an error, we continue processing oob messages but
   // stop handling normal messages.
@@ -281,14 +275,10 @@
   Dart_Port port2 = PortMap::CreatePort(&handler);
   Dart_Port port3 = PortMap::CreatePort(&handler);
   Dart_Port port4 = PortMap::CreatePort(&handler);
-  Message* message1 = BlankMessage(port1, Message::kNormalPriority);
-  handler_peer.PostMessage(message1);
-  Message* oob_message1 = BlankMessage(port2, Message::kOOBPriority);
-  handler_peer.PostMessage(oob_message1);
-  Message* oob_message2 = BlankMessage(port3, Message::kOOBPriority);
-  handler_peer.PostMessage(oob_message2);
-  Message* oob_message3 = BlankMessage(port4, Message::kOOBPriority);
-  handler_peer.PostMessage(oob_message3);
+  handler_peer.PostMessage(BlankMessage(port1, Message::kNormalPriority));
+  handler_peer.PostMessage(BlankMessage(port2, Message::kOOBPriority));
+  handler_peer.PostMessage(BlankMessage(port3, Message::kOOBPriority));
+  handler_peer.PostMessage(BlankMessage(port4, Message::kOOBPriority));
 
   // When we get a shutdown message, we stop processing all messages.
   EXPECT_EQ(MessageHandler::kShutdown, handler.HandleNextMessage());
@@ -311,14 +301,10 @@
   Dart_Port port2 = PortMap::CreatePort(&handler);
   Dart_Port port3 = PortMap::CreatePort(&handler);
   Dart_Port port4 = PortMap::CreatePort(&handler);
-  Message* message1 = BlankMessage(port1, Message::kNormalPriority);
-  handler_peer.PostMessage(message1);
-  Message* message2 = BlankMessage(port2, Message::kNormalPriority);
-  handler_peer.PostMessage(message2);
-  Message* oob_message1 = BlankMessage(port3, Message::kOOBPriority);
-  handler_peer.PostMessage(oob_message1);
-  Message* oob_message2 = BlankMessage(port4, Message::kOOBPriority);
-  handler_peer.PostMessage(oob_message2);
+  handler_peer.PostMessage(BlankMessage(port1, Message::kNormalPriority));
+  handler_peer.PostMessage(BlankMessage(port2, Message::kNormalPriority));
+  handler_peer.PostMessage(BlankMessage(port3, Message::kOOBPriority));
+  handler_peer.PostMessage(BlankMessage(port4, Message::kOOBPriority));
 
   // We handle both oob messages but no normal messages.
   EXPECT_EQ(MessageHandler::kOK, handler.HandleOOBMessages());
@@ -340,8 +326,8 @@
   MessageHandler* handler = info->handler;
   MessageHandlerTestPeer handler_peer(handler);
   for (int i = 0; i < info->count; i++) {
-    Message* message = BlankMessage(info->ports[i], Message::kNormalPriority);
-    handler_peer.PostMessage(message);
+    handler_peer.PostMessage(
+        BlankMessage(info->ports[i], Message::kNormalPriority));
   }
 }
 
@@ -358,8 +344,7 @@
   handler.Run(&pool, TestStartFunction, TestEndFunction,
               reinterpret_cast<uword>(&handler));
   Dart_Port port = PortMap::CreatePort(&handler);
-  Message* message = BlankMessage(port, Message::kNormalPriority);
-  handler_peer.PostMessage(message);
+  handler_peer.PostMessage(BlankMessage(port, Message::kNormalPriority));
 
   // Wait for the first message to be handled.
   while (sleep < kMaxSleep && handler.message_count() < 1) {
@@ -373,7 +358,7 @@
   EXPECT_EQ(port, handler_ports[0]);
 
   // Start a thread which sends more messages.
-  Dart_Port* ports = new Dart_Port[10];
+  Dart_Port ports[10];
   for (int i = 0; i < 10; i++) {
     ports[i] = PortMap::CreatePort(&handler);
   }
@@ -396,7 +381,6 @@
   }
   handler_peer.decrement_live_ports();
   EXPECT(!handler.HasLivePorts());
-  delete[] ports;
 }
 
 }  // namespace dart
diff --git a/runtime/vm/message_test.cc b/runtime/vm/message_test.cc
index c07f78c..f580820 100644
--- a/runtime/vm/message_test.cc
+++ b/runtime/vm/message_test.cc
@@ -29,9 +29,11 @@
   const char* str6 = "msg6";
 
   // Add two messages.
-  Message* msg1 = new Message(port, AllocMsg(str1), strlen(str1) + 1, NULL,
-                              Message::kNormalPriority);
-  queue.Enqueue(msg1, false);
+  std::unique_ptr<Message> msg =
+      Message::New(port, AllocMsg(str1), strlen(str1) + 1, nullptr,
+                   Message::kNormalPriority);
+  Message* msg1 = msg.get();
+  queue.Enqueue(std::move(msg), false);
   EXPECT(queue.Length() == 1);
   EXPECT(!queue.IsEmpty());
   it.Reset(&queue);
@@ -39,9 +41,10 @@
   EXPECT(it.Next() == msg1);
   EXPECT(!it.HasNext());
 
-  Message* msg2 = new Message(port, AllocMsg(str2), strlen(str2) + 1, NULL,
-                              Message::kNormalPriority);
-  queue.Enqueue(msg2, false);
+  msg = Message::New(port, AllocMsg(str2), strlen(str2) + 1, nullptr,
+                     Message::kNormalPriority);
+  Message* msg2 = msg.get();
+  queue.Enqueue(std::move(msg), false);
   EXPECT(queue.Length() == 2);
   EXPECT(!queue.IsEmpty());
   it.Reset(&queue);
@@ -59,8 +62,8 @@
   EXPECT(queue.FindMessageById(0x1) == NULL);
 
   // Remove message 1
-  Message* msg = queue.Dequeue();
-  EXPECT(msg != NULL);
+  msg = queue.Dequeue();
+  EXPECT(msg != nullptr);
   EXPECT_STREQ(str1, reinterpret_cast<char*>(msg->snapshot()));
   EXPECT(!queue.IsEmpty());
 
@@ -70,56 +73,49 @@
 
   // Remove message 2
   msg = queue.Dequeue();
-  EXPECT(msg != NULL);
+  EXPECT(msg != nullptr);
   EXPECT_STREQ(str2, reinterpret_cast<char*>(msg->snapshot()));
   EXPECT(queue.IsEmpty());
 
-  Message* msg3 = new Message(Message::kIllegalPort, AllocMsg(str3),
-                              strlen(str3) + 1, NULL, Message::kNormalPriority);
-  queue.Enqueue(msg3, true);
+  msg = Message::New(Message::kIllegalPort, AllocMsg(str3), strlen(str3) + 1,
+                     nullptr, Message::kNormalPriority);
+  queue.Enqueue(std::move(msg), true);
   EXPECT(!queue.IsEmpty());
 
-  Message* msg4 = new Message(Message::kIllegalPort, AllocMsg(str4),
-                              strlen(str4) + 1, NULL, Message::kNormalPriority);
-  queue.Enqueue(msg4, true);
+  msg = Message::New(Message::kIllegalPort, AllocMsg(str4), strlen(str4) + 1,
+                     nullptr, Message::kNormalPriority);
+  queue.Enqueue(std::move(msg), true);
   EXPECT(!queue.IsEmpty());
 
-  Message* msg5 = new Message(port, AllocMsg(str5), strlen(str5) + 1, NULL,
-                              Message::kNormalPriority);
-  queue.Enqueue(msg5, false);
+  msg = Message::New(port, AllocMsg(str5), strlen(str5) + 1, nullptr,
+                     Message::kNormalPriority);
+  queue.Enqueue(std::move(msg), false);
   EXPECT(!queue.IsEmpty());
 
-  Message* msg6 = new Message(Message::kIllegalPort, AllocMsg(str6),
-                              strlen(str6) + 1, NULL, Message::kNormalPriority);
-  queue.Enqueue(msg6, true);
+  msg = Message::New(Message::kIllegalPort, AllocMsg(str6), strlen(str6) + 1,
+                     nullptr, Message::kNormalPriority);
+  queue.Enqueue(std::move(msg), true);
   EXPECT(!queue.IsEmpty());
 
   msg = queue.Dequeue();
-  EXPECT(msg != NULL);
+  EXPECT(msg != nullptr);
   EXPECT_STREQ(str3, reinterpret_cast<char*>(msg->snapshot()));
   EXPECT(!queue.IsEmpty());
 
   msg = queue.Dequeue();
-  EXPECT(msg != NULL);
+  EXPECT(msg != nullptr);
   EXPECT_STREQ(str4, reinterpret_cast<char*>(msg->snapshot()));
   EXPECT(!queue.IsEmpty());
 
   msg = queue.Dequeue();
-  EXPECT(msg != NULL);
+  EXPECT(msg != nullptr);
   EXPECT_STREQ(str6, reinterpret_cast<char*>(msg->snapshot()));
   EXPECT(!queue.IsEmpty());
 
   msg = queue.Dequeue();
-  EXPECT(msg != NULL);
+  EXPECT(msg != nullptr);
   EXPECT_STREQ(str5, reinterpret_cast<char*>(msg->snapshot()));
   EXPECT(queue.IsEmpty());
-
-  delete msg1;
-  delete msg2;
-  delete msg3;
-  delete msg4;
-  delete msg5;
-  delete msg6;
 }
 
 TEST_CASE(MessageQueue_Clear) {
@@ -131,18 +127,17 @@
   const char* str2 = "msg2";
 
   // Add two messages.
-  Message* msg1 = new Message(port1, AllocMsg(str1), strlen(str1) + 1, NULL,
-                              Message::kNormalPriority);
-  queue.Enqueue(msg1, false);
-  Message* msg2 = new Message(port2, AllocMsg(str2), strlen(str2) + 1, NULL,
-                              Message::kNormalPriority);
-  queue.Enqueue(msg2, false);
+  std::unique_ptr<Message> msg;
+  msg = Message::New(port1, AllocMsg(str1), strlen(str1) + 1, nullptr,
+                     Message::kNormalPriority);
+  queue.Enqueue(std::move(msg), false);
+  msg = Message::New(port2, AllocMsg(str2), strlen(str2) + 1, nullptr,
+                     Message::kNormalPriority);
+  queue.Enqueue(std::move(msg), false);
 
   EXPECT(!queue.IsEmpty());
   queue.Clear();
   EXPECT(queue.IsEmpty());
-
-  // msg1 and msg2 already delete by FlushAll.
 }
 
 }  // namespace dart
diff --git a/runtime/vm/metrics_test.cc b/runtime/vm/metrics_test.cc
index 6ca6726..4482a6d 100644
--- a/runtime/vm/metrics_test.cc
+++ b/runtime/vm/metrics_test.cc
@@ -67,7 +67,7 @@
         "{\"type\":\"Counter\",\"name\":\"a.b.c\",\"description\":"
         "\"foobar\",\"unit\":\"byte\","
         "\"fixedId\":true,\"id\":\"metrics\\/native\\/a.b.c\""
-        ",\"value\":99.000000}",
+        ",\"value\":99.0}",
         json);
   }
   Dart_ShutdownIsolate();
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index 92192fd..c225bff 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -41,15 +41,15 @@
 
 static bool PostCObjectHelper(Dart_Port port_id, Dart_CObject* message) {
   ApiMessageWriter writer;
-  Message* msg =
+  std::unique_ptr<Message> msg =
       writer.WriteCMessage(message, port_id, Message::kNormalPriority);
 
-  if (msg == NULL) {
+  if (msg == nullptr) {
     return false;
   }
 
   // Post the message at the given port.
-  return PortMap::PostMessage(msg);
+  return PortMap::PostMessage(std::move(msg));
 }
 
 DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message) {
@@ -59,7 +59,7 @@
 DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message) {
   if (Smi::IsValid(message)) {
     return PortMap::PostMessage(
-        new Message(port_id, Smi::New(message), Message::kNormalPriority));
+        Message::New(port_id, Smi::New(message), Message::kNormalPriority));
   }
   Dart_CObject cobj;
   cobj.type = Dart_CObject_kInt64;
@@ -217,4 +217,37 @@
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
+DART_EXPORT Dart_Handle Dart_FinalizeAllClasses() {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  return Api::NewError("%s: All classes are already finalized in AOT runtime.",
+                       CURRENT_FUNC);
+#else
+  DARTSCOPE(Thread::Current());
+  API_TIMELINE_DURATION(T);
+  Dart_Handle result = Api::CheckAndFinalizePendingClasses(T);
+  if (Api::IsError(result)) {
+    return result;
+  }
+  CHECK_CALLBACK_STATE(T);
+  const Error& error = Error::Handle(T->zone(), Library::FinalizeAllClasses());
+  if (!error.IsNull()) {
+    return Api::NewHandle(T, error.raw());
+  }
+  return Api::Success();
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+}
+
+DART_EXPORT void Dart_ExecuteInternalCommand(const char* command) {
+  if (!FLAG_enable_testing_pragmas) return;
+
+  TransitionNativeToVM _(Thread::Current());
+  if (!strcmp(command, "gc-on-next-allocation")) {
+    Isolate::Current()->heap()->CollectOnNextAllocation();
+  } else if (!strcmp(command, "gc-now")) {
+    Isolate::Current()->heap()->CollectAllGarbage(Heap::kDebugging);
+  } else {
+    UNREACHABLE();
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index 569b402..fbf0c55 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -74,7 +74,7 @@
   Thread* thread = Thread::Current();
   REUSABLE_GROWABLE_OBJECT_ARRAY_HANDLESCOPE(thread);
   GrowableObjectArray& libs = reused_growable_object_array_handle.Handle();
-  libs ^= thread->isolate()->object_store()->libraries();
+  libs = thread->isolate()->object_store()->libraries();
   ASSERT(!libs.IsNull());
   intptr_t num_libs = libs.Length();
   for (intptr_t i = 0; i < num_libs; i++) {
diff --git a/runtime/vm/native_message_handler.cc b/runtime/vm/native_message_handler.cc
index a09d77c..009111c 100644
--- a/runtime/vm/native_message_handler.cc
+++ b/runtime/vm/native_message_handler.cc
@@ -26,7 +26,7 @@
 #endif
 
 MessageHandler::MessageStatus NativeMessageHandler::HandleMessage(
-    Message* message) {
+    std::unique_ptr<Message> message) {
   if (message->IsOOB()) {
     // We currently do not use OOB messages for native ports.
     UNREACHABLE();
@@ -36,10 +36,9 @@
   // zone associated with this scope.
   ApiNativeScope scope;
   Dart_CObject* object;
-  ApiMessageReader reader(message);
+  ApiMessageReader reader(message.get());
   object = reader.ReadMessage();
   (*func())(message->dest_port(), object);
-  delete message;
   return kOK;
 }
 
diff --git a/runtime/vm/native_message_handler.h b/runtime/vm/native_message_handler.h
index 7133662..82a0b98 100644
--- a/runtime/vm/native_message_handler.h
+++ b/runtime/vm/native_message_handler.h
@@ -21,7 +21,7 @@
   const char* name() const { return name_; }
   Dart_NativeMessageHandler func() const { return func_; }
 
-  MessageStatus HandleMessage(Message* message);
+  MessageStatus HandleMessage(std::unique_ptr<Message> message);
 
 #if defined(DEBUG)
   // Check that it is safe to access this handler.
diff --git a/runtime/vm/native_symbol.h b/runtime/vm/native_symbol.h
index 3bc71cd..29dda98 100644
--- a/runtime/vm/native_symbol.h
+++ b/runtime/vm/native_symbol.h
@@ -19,6 +19,7 @@
   static char* LookupSymbolName(uintptr_t pc, uintptr_t* start);
   static bool LookupSharedObject(uword pc, uword* dso_base, char** dso_name);
   static void FreeSymbolName(char* name);
+  static void AddSymbols(const char* dso_name, void* buffer, size_t size);
 };
 
 }  // namespace dart
diff --git a/runtime/vm/native_symbol_android.cc b/runtime/vm/native_symbol_android.cc
index 43df38d..9cfd7cb 100644
--- a/runtime/vm/native_symbol_android.cc
+++ b/runtime/vm/native_symbol_android.cc
@@ -6,6 +6,7 @@
 #if defined(HOST_OS_ANDROID)
 
 #include "vm/native_symbol.h"
+#include "vm/os.h"
 
 #include <cxxabi.h>  // NOLINT
 #include <dlfcn.h>   // NOLINT
@@ -55,6 +56,12 @@
   return true;
 }
 
+void NativeSymbolResolver::AddSymbols(const char* dso_name,
+                                      void* buffer,
+                                      size_t size) {
+  OS::PrintErr("warning: Dart_AddSymbols has no effect on Android\n");
+}
+
 }  // namespace dart
 
 #endif  // defined(HOST_OS_ANDROID)
diff --git a/runtime/vm/native_symbol_fuchsia.cc b/runtime/vm/native_symbol_fuchsia.cc
index f7fdd81..70aa0b5 100644
--- a/runtime/vm/native_symbol_fuchsia.cc
+++ b/runtime/vm/native_symbol_fuchsia.cc
@@ -8,14 +8,97 @@
 #include "platform/memory_sanitizer.h"
 #include "vm/native_symbol.h"
 
-#include <cxxabi.h>  // NOLINT
 #include <dlfcn.h>   // NOLINT
 
 namespace dart {
 
+// On Fuchsia, in lieu of the ELF dynamic symbol table consumed through dladdr,
+// we consumes symbols produced by //topaz/runtime/dart/profiler_symbols and
+// provided to the VM by the embedder through Dart_AddSymbols. They have the
+// format
+//
+// struct {
+//    uint32_t num_entries;
+//    struct {
+//      uint32_t offset;
+//      uint32_t size;
+//      uint32_t string_table_offset;
+//    } entries[num_entries];
+//    const char* string_table;
+// }
+//
+// Entries are sorted by offset. String table entries are NUL-terminated.
+class NativeSymbols {
+ public:
+  NativeSymbols(const char* dso_name, void* buffer, size_t size)
+      : next_(NULL), dso_name_(dso_name) {
+    num_entries_ = *reinterpret_cast<uint32_t*>(buffer);
+    entries_ =
+        reinterpret_cast<Entry*>(reinterpret_cast<uint32_t*>(buffer) + 1);
+    name_table_ = reinterpret_cast<const char*>(entries_ + num_entries_);
+  }
+
+  NativeSymbols* next() const { return next_; }
+  void set_next(NativeSymbols* symbols) { next_ = symbols; }
+
+  bool Lookup(const char* dso_name,
+              uword dso_offset,
+              uword* start_offset,
+              const char** name) {
+    if (strcmp(dso_name, dso_name_) != 0) {
+      return false;
+    }
+
+    intptr_t lo = 0;
+    intptr_t hi = num_entries_ - 1;
+    while (lo <= hi) {
+      intptr_t mid = (hi - lo + 1) / 2 + lo;
+      ASSERT(mid >= lo);
+      ASSERT(mid <= hi);
+      const Entry& entry = entries_[mid];
+      if (dso_offset < entry.offset) {
+        hi = mid - 1;
+      } else if (dso_offset >= (entry.offset + entry.size)) {
+        lo = mid + 1;
+      } else {
+        *start_offset = entry.offset;
+        *name = &name_table_[entry.name_offset];
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+ private:
+  struct Entry {
+    uint32_t offset;
+    uint32_t size;
+    uint32_t name_offset;
+  };
+
+  NativeSymbols* next_;
+  const char* const dso_name_;
+  intptr_t num_entries_;
+  Entry* entries_;
+  const char* name_table_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeSymbols);
+};
+
+static NativeSymbols* symbols_ = NULL;
+
 void NativeSymbolResolver::Init() {}
 
-void NativeSymbolResolver::Cleanup() {}
+void NativeSymbolResolver::Cleanup() {
+  NativeSymbols* symbols = symbols_;
+  symbols_ = NULL;
+  while (symbols != NULL) {
+    NativeSymbols* next = symbols->next();
+    delete symbols;
+    symbols = next;
+  }
+}
 
 char* NativeSymbolResolver::LookupSymbolName(uintptr_t pc, uintptr_t* start) {
   Dl_info info;
@@ -23,20 +106,25 @@
   if (r == 0) {
     return NULL;
   }
-  if (info.dli_sname == NULL) {
-    return NULL;
+
+  const char* dso_name = info.dli_fname;
+  uword dso_base = reinterpret_cast<uword>(info.dli_fbase);
+  uword dso_offset = pc - dso_base;
+
+  for (NativeSymbols* symbols = symbols_; symbols != NULL;
+       symbols = symbols->next()) {
+    uword symbol_start_offset;
+    const char* symbol_name;
+    if (symbols->Lookup(dso_name, dso_offset, &symbol_start_offset,
+                        &symbol_name)) {
+      if (start != NULL) {
+        *start = symbol_start_offset + dso_base;
+      }
+      return strdup(symbol_name);
+    }
   }
-  if (start != NULL) {
-    *start = reinterpret_cast<uintptr_t>(info.dli_saddr);
-  }
-  int status = 0;
-  size_t len = 0;
-  char* demangled = abi::__cxa_demangle(info.dli_sname, NULL, &len, &status);
-  MSAN_UNPOISON(demangled, len);
-  if (status == 0) {
-    return demangled;
-  }
-  return strdup(info.dli_sname);
+
+  return NULL;
 }
 
 void NativeSymbolResolver::FreeSymbolName(char* name) {
@@ -56,6 +144,13 @@
   return true;
 }
 
+void NativeSymbolResolver::AddSymbols(const char* dso_name,
+                                      void* buffer, size_t size) {
+  NativeSymbols* symbols = new NativeSymbols(dso_name, buffer, size);
+  symbols->set_next(symbols_);
+  symbols_ = symbols;
+}
+
 }  // namespace dart
 
 #endif  // defined(HOST_OS_FUCHSIA)
diff --git a/runtime/vm/native_symbol_linux.cc b/runtime/vm/native_symbol_linux.cc
index 135daed..a4af553 100644
--- a/runtime/vm/native_symbol_linux.cc
+++ b/runtime/vm/native_symbol_linux.cc
@@ -7,6 +7,7 @@
 
 #include "platform/memory_sanitizer.h"
 #include "vm/native_symbol.h"
+#include "vm/os.h"
 
 #include <cxxabi.h>  // NOLINT
 #include <dlfcn.h>   // NOLINT
@@ -56,6 +57,12 @@
   return true;
 }
 
+void NativeSymbolResolver::AddSymbols(const char* dso_name,
+                                      void* buffer,
+                                      size_t size) {
+  OS::PrintErr("warning: Dart_AddSymbols has no effect on Linux\n");
+}
+
 }  // namespace dart
 
 #endif  // defined(HOST_OS_LINUX)
diff --git a/runtime/vm/native_symbol_macos.cc b/runtime/vm/native_symbol_macos.cc
index 84d7d7a..d3a6489 100644
--- a/runtime/vm/native_symbol_macos.cc
+++ b/runtime/vm/native_symbol_macos.cc
@@ -6,6 +6,7 @@
 #if defined(HOST_OS_MACOS)
 
 #include "vm/native_symbol.h"
+#include "vm/os.h"
 
 #include <cxxabi.h>  // NOLINT
 #include <dlfcn.h>   // NOLINT
@@ -53,6 +54,12 @@
   return true;
 }
 
+void NativeSymbolResolver::AddSymbols(const char* dso_name,
+                                      void* buffer,
+                                      size_t size) {
+  OS::PrintErr("warning: Dart_AddSymbols has no effect on MacOS\n");
+}
+
 }  // namespace dart
 
 #endif  // defined(HOST_OS_MACOS)
diff --git a/runtime/vm/native_symbol_win.cc b/runtime/vm/native_symbol_win.cc
index e5f8e61..0a26ebd 100644
--- a/runtime/vm/native_symbol_win.cc
+++ b/runtime/vm/native_symbol_win.cc
@@ -7,6 +7,7 @@
 
 #include "vm/lockers.h"
 #include "vm/native_symbol.h"
+#include "vm/os.h"
 #include "vm/os_thread.h"
 
 #include <dbghelp.h>  // NOLINT
@@ -83,6 +84,12 @@
   return false;
 }
 
+void NativeSymbolResolver::AddSymbols(const char* dso_name,
+                                      void* buffer,
+                                      size_t size) {
+  OS::PrintErr("warning: Dart_AddSymbols has no effect on Windows\n");
+}
+
 }  // namespace dart
 
 #endif  // defined(HOST_OS_WINDOWS)
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 7a8b971..f914e28 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -6,6 +6,7 @@
 
 #include "include/dart_api.h"
 #include "platform/assert.h"
+#include "platform/unicode.h"
 #include "vm/bit_vector.h"
 #include "vm/bootstrap.h"
 #include "vm/class_finalizer.h"
@@ -55,7 +56,6 @@
 #include "vm/timeline.h"
 #include "vm/type_table.h"
 #include "vm/type_testing_stubs.h"
-#include "vm/unicode.h"
 #include "vm/zone_text_buffer.h"
 
 namespace dart {
@@ -443,6 +443,21 @@
   return '\0';
 }
 
+static RawBytecode* CreateVMInternalBytecode(KernelBytecode::Opcode opcode) {
+  const KBCInstr* instructions = nullptr;
+  intptr_t instructions_size = 0;
+
+  KernelBytecode::GetVMInternalBytecodeInstructions(opcode, &instructions,
+                                                    &instructions_size);
+
+  const auto& bytecode = Bytecode::Handle(
+      Bytecode::New(reinterpret_cast<uword>(instructions), instructions_size,
+                    -1, Object::empty_object_pool()));
+  bytecode.set_pc_descriptors(Object::empty_descriptors());
+  bytecode.set_exception_handlers(Object::empty_exception_handlers());
+  return bytecode.raw();
+}
+
 void Object::InitNull(Isolate* isolate) {
   // Should only be run by the vm isolate.
   ASSERT(isolate == Dart::vm_isolate());
@@ -518,12 +533,10 @@
     cls.set_id(Class::kClassId);
     cls.set_state_bits(0);
     cls.set_is_finalized();
+    cls.set_is_declaration_loaded();
     cls.set_is_type_finalized();
-    cls.set_is_cycle_free();
     cls.set_type_arguments_field_offset_in_words(Class::kNoTypeArguments);
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
-    cls.set_has_pragma(false);
     cls.set_num_native_fields(0);
     cls.InitEmptyFields();
     isolate->RegisterClass(cls);
@@ -532,24 +545,21 @@
   // Allocate and initialize the null class.
   cls = Class::New<Instance>(kNullCid);
   cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
   isolate->object_store()->set_null_class(cls);
 
   // Allocate and initialize the free list element class.
   cls = Class::New<FreeListElement::FakeInstance>(kFreeListElement);
   cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
   cls.set_is_finalized();
+  cls.set_is_declaration_loaded();
   cls.set_is_type_finalized();
-  cls.set_is_cycle_free();
 
   // Allocate and initialize the forwarding corpse class.
   cls = Class::New<ForwardingCorpse::FakeInstance>(kForwardingCorpse);
   cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
   cls.set_is_finalized();
+  cls.set_is_declaration_loaded();
   cls.set_is_type_finalized();
-  cls.set_is_cycle_free();
 
   // Allocate and initialize the sentinel values of Null class.
   {
@@ -673,12 +683,10 @@
   isolate->object_store()->set_array_class(cls);
   cls.set_type_arguments_field_offset(Array::type_arguments_offset());
   cls.set_num_type_arguments(1);
-  cls.set_num_own_type_arguments(1);
   cls = Class::New<Array>(kImmutableArrayCid);
   isolate->object_store()->set_immutable_array_class(cls);
   cls.set_type_arguments_field_offset(Array::type_arguments_offset());
   cls.set_num_type_arguments(1);
-  cls.set_num_own_type_arguments(1);
   cls = Class::New<GrowableObjectArray>();
   isolate->object_store()->set_growable_object_array_class(cls);
   cls.set_type_arguments_field_offset(
@@ -815,24 +823,22 @@
   cls = Class::New<Instance>(kDynamicCid);
   cls.set_is_abstract();
   cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
   cls.set_is_finalized();
+  cls.set_is_declaration_loaded();
   cls.set_is_type_finalized();
-  cls.set_is_cycle_free();
   dynamic_class_ = cls.raw();
 
   cls = Class::New<Instance>(kVoidCid);
   cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
   cls.set_is_finalized();
+  cls.set_is_declaration_loaded();
   cls.set_is_type_finalized();
-  cls.set_is_cycle_free();
   void_class_ = cls.raw();
 
   cls = Class::New<Type>();
   cls.set_is_finalized();
+  cls.set_is_declaration_loaded();
   cls.set_is_type_finalized();
-  cls.set_is_cycle_free();
 
   cls = dynamic_class_;
   *dynamic_type_ = Type::NewNonParameterizedType(cls);
@@ -880,38 +886,26 @@
   // needs to be created earlier as VM isolate snapshot reader references it
   // before Object::FinalizeVMIsolate.
 
-  static const KBCInstr getter_instr[2] = {
-      KernelBytecode::Encode(KernelBytecode::kVMInternal_ImplicitGetter),
-      KernelBytecode::Encode(KernelBytecode::kReturnTOS),
-  };
   *implicit_getter_bytecode_ =
-      Bytecode::New(reinterpret_cast<uword>(getter_instr), sizeof(getter_instr),
-                    -1, Object::empty_object_pool());
-  implicit_getter_bytecode_->set_pc_descriptors(Object::empty_descriptors());
-  implicit_getter_bytecode_->set_exception_handlers(
-      Object::empty_exception_handlers());
+      CreateVMInternalBytecode(KernelBytecode::kVMInternal_ImplicitGetter);
 
-  static const KBCInstr setter_instr[2] = {
-      KernelBytecode::Encode(KernelBytecode::kVMInternal_ImplicitSetter),
-      KernelBytecode::Encode(KernelBytecode::kReturnTOS),
-  };
   *implicit_setter_bytecode_ =
-      Bytecode::New(reinterpret_cast<uword>(setter_instr), sizeof(setter_instr),
-                    -1, Object::empty_object_pool());
-  implicit_setter_bytecode_->set_pc_descriptors(Object::empty_descriptors());
-  implicit_setter_bytecode_->set_exception_handlers(
-      Object::empty_exception_handlers());
+      CreateVMInternalBytecode(KernelBytecode::kVMInternal_ImplicitSetter);
 
-  static const KBCInstr method_extractor_instr[2] = {
-      KernelBytecode::Encode(KernelBytecode::kVMInternal_MethodExtractor),
-      KernelBytecode::Encode(KernelBytecode::kReturnTOS),
-  };
-  *method_extractor_bytecode_ = Bytecode::New(
-      reinterpret_cast<uword>(method_extractor_instr),
-      sizeof(method_extractor_instr), -1, Object::empty_object_pool());
-  method_extractor_bytecode_->set_pc_descriptors(Object::empty_descriptors());
-  method_extractor_bytecode_->set_exception_handlers(
-      Object::empty_exception_handlers());
+  *implicit_static_getter_bytecode_ = CreateVMInternalBytecode(
+      KernelBytecode::kVMInternal_ImplicitStaticGetter);
+
+  *method_extractor_bytecode_ =
+      CreateVMInternalBytecode(KernelBytecode::kVMInternal_MethodExtractor);
+
+  *invoke_closure_bytecode_ =
+      CreateVMInternalBytecode(KernelBytecode::kVMInternal_InvokeClosure);
+
+  *invoke_field_bytecode_ =
+      CreateVMInternalBytecode(KernelBytecode::kVMInternal_InvokeField);
+
+  *nsm_dispatcher_bytecode_ = CreateVMInternalBytecode(
+      KernelBytecode::kVMInternal_NoSuchMethodDispatcher);
 
   // Some thread fields need to be reinitialized as null constants have not been
   // initialized until now.
@@ -974,8 +968,16 @@
   ASSERT(implicit_getter_bytecode_->IsBytecode());
   ASSERT(!implicit_setter_bytecode_->IsSmi());
   ASSERT(implicit_setter_bytecode_->IsBytecode());
+  ASSERT(!implicit_static_getter_bytecode_->IsSmi());
+  ASSERT(implicit_static_getter_bytecode_->IsBytecode());
   ASSERT(!method_extractor_bytecode_->IsSmi());
   ASSERT(method_extractor_bytecode_->IsBytecode());
+  ASSERT(!invoke_closure_bytecode_->IsSmi());
+  ASSERT(invoke_closure_bytecode_->IsBytecode());
+  ASSERT(!invoke_field_bytecode_->IsSmi());
+  ASSERT(invoke_field_bytecode_->IsBytecode());
+  ASSERT(!nsm_dispatcher_bytecode_->IsSmi());
+  ASSERT(nsm_dispatcher_bytecode_->IsBytecode());
 }
 
 void Object::FinishInit(Isolate* isolate) {
@@ -1453,8 +1455,8 @@
     // declared number of type parameters is still 0. It will become 1 after
     // patching. The array type allocated below represents the raw type _List
     // and not _List<E> as we could expect. Use with caution.
-    type ^= Type::New(Class::Handle(zone, cls.raw()),
-                      TypeArguments::Handle(zone), TokenPosition::kNoSource);
+    type = Type::New(Class::Handle(zone, cls.raw()),
+                     TypeArguments::Handle(zone), TokenPosition::kNoSource);
     type.SetIsFinalized();
     type ^= type.Canonicalize();
     object_store->set_array_type(type);
@@ -1516,6 +1518,11 @@
     RegisterPrivateClass(cls, Symbols::_SendPortImpl(), isolate_lib);
     pending_classes.Add(cls);
 
+    cls = Class::New<TransferableTypedData>();
+    RegisterPrivateClass(cls, Symbols::_TransferableTypedDataImpl(),
+                         isolate_lib);
+    pending_classes.Add(cls);
+
     const Class& stacktrace_cls = Class::Handle(zone, Class::New<StackTrace>());
     RegisterPrivateClass(stacktrace_cls, Symbols::_StackTrace(), core_lib);
     pending_classes.Add(stacktrace_cls);
@@ -1535,7 +1542,6 @@
     object_store->set_object_class(cls);
     cls.set_name(Symbols::Object());
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
     cls.set_is_prefinalized();
     core_lib.AddClass(cls);
     pending_classes.Add(cls);
@@ -1550,7 +1556,6 @@
     cls = Class::New<Instance>(kNullCid);
     object_store->set_null_class(cls);
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
     cls.set_is_prefinalized();
     RegisterClass(cls, Symbols::Null(), core_lib);
     pending_classes.Add(cls);
@@ -1593,7 +1598,6 @@
     // Class that represents the Dart class _Closure and C++ class Closure.
     cls = Class::New<Closure>();
     object_store->set_closure_class(cls);
-    cls.ResetFinalization();  // To calculate field offsets from Dart source.
     RegisterPrivateClass(cls, Symbols::_Closure(), core_lib);
     pending_classes.Add(cls);
 
@@ -1634,7 +1638,6 @@
     object_store->set_linked_hash_map_class(cls);
     cls.set_type_arguments_field_offset(LinkedHashMap::type_arguments_offset());
     cls.set_num_type_arguments(2);
-    cls.set_num_own_type_arguments(0);
     RegisterPrivateClass(cls, Symbols::_LinkedHashMap(), lib);
     pending_classes.Add(cls);
 
@@ -1708,7 +1711,6 @@
     cls = Class::New<Instance>(kIllegalCid);
     RegisterClass(cls, Symbols::Float32x4(), lib);
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
     cls.set_is_prefinalized();
     type = Type::NewNonParameterizedType(cls);
     object_store->set_float32x4_type(type);
@@ -1721,7 +1723,6 @@
     cls = Class::New<Instance>(kIllegalCid);
     RegisterClass(cls, Symbols::Int32x4(), lib);
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
     cls.set_is_prefinalized();
     type = Type::NewNonParameterizedType(cls);
     object_store->set_int32x4_type(type);
@@ -1734,7 +1735,6 @@
     cls = Class::New<Instance>(kIllegalCid);
     RegisterClass(cls, Symbols::Float64x2(), lib);
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
     cls.set_is_prefinalized();
     type = Type::NewNonParameterizedType(cls);
     object_store->set_float64x2_type(type);
@@ -1748,7 +1748,6 @@
     // Note that this class is implemented by Dart class _AbstractType.
     cls = Class::New<Instance>(kIllegalCid);
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
     cls.set_is_prefinalized();
     RegisterClass(cls, Symbols::Type(), core_lib);
     pending_classes.Add(cls);
@@ -1758,7 +1757,6 @@
     // Abstract class that represents the Dart class Function.
     cls = Class::New<Instance>(kIllegalCid);
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
     cls.set_is_prefinalized();
     RegisterClass(cls, Symbols::Function(), core_lib);
     pending_classes.Add(cls);
@@ -1774,7 +1772,6 @@
     cls = Class::New<Instance>(kIllegalCid);
     RegisterClass(cls, Symbols::Int(), core_lib);
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
     cls.set_is_prefinalized();
     pending_classes.Add(cls);
     type = Type::NewNonParameterizedType(cls);
@@ -1783,7 +1780,6 @@
     cls = Class::New<Instance>(kIllegalCid);
     RegisterClass(cls, Symbols::Double(), core_lib);
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
     cls.set_is_prefinalized();
     pending_classes.Add(cls);
     type = Type::NewNonParameterizedType(cls);
@@ -1793,7 +1789,6 @@
     cls = Class::New<Instance>(kIllegalCid);
     RegisterClass(cls, name, core_lib);
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
     cls.set_is_prefinalized();
     pending_classes.Add(cls);
     type = Type::NewNonParameterizedType(cls);
@@ -1869,7 +1864,6 @@
 
     cls = Class::New<Instance>(kFfiNativeTypeCid);
     cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
     cls.set_is_prefinalized();
     pending_classes.Add(cls);
     object_store->set_ffi_native_type_class(cls);
@@ -1878,7 +1872,6 @@
 #define REGISTER_FFI_TYPE_MARKER(clazz)                                        \
   cls = Class::New<Instance>(kFfi##clazz##Cid);                                \
   cls.set_num_type_arguments(0);                                               \
-  cls.set_num_own_type_arguments(0);                                           \
   cls.set_is_prefinalized();                                                   \
   pending_classes.Add(cls);                                                    \
   RegisterClass(cls, Symbols::Ffi##clazz(), lib);
@@ -1888,7 +1881,6 @@
     cls = Class::New<Instance>(kFfiNativeFunctionCid);
     cls.set_type_arguments_field_offset(Pointer::type_arguments_offset());
     cls.set_num_type_arguments(1);
-    cls.set_num_own_type_arguments(1);
     cls.set_is_prefinalized();
     pending_classes.Add(cls);
     RegisterClass(cls, Symbols::FfiNativeFunction(), lib);
@@ -2049,6 +2041,8 @@
 
     cls = Class::New<MirrorReference>();
     cls = Class::New<UserTag>();
+
+    cls = Class::New<TransferableTypedData>();
   }
   return Error::null();
 }
@@ -2290,16 +2284,16 @@
   COMPILE_ASSERT((FakeObject::kClassId != kInstanceCid));
   result.set_id(FakeObject::kClassId);
   result.set_num_type_arguments(0);
-  result.set_num_own_type_arguments(0);
-  result.set_has_pragma(false);
   result.set_num_native_fields(0);
   result.set_state_bits(0);
   if ((FakeObject::kClassId < kInstanceCid) ||
       (FakeObject::kClassId == kTypeArgumentsCid)) {
     // VM internal classes are done. There is no finalization needed or
     // possible in this case.
+    result.set_is_declaration_loaded();
+    result.set_is_type_finalized();
     result.set_is_finalized();
-  } else {
+  } else if (FakeObject::kClassId != kClosureCid) {
     // VM backed classes are almost ready: run checks and resolve class
     // references, but do not recompute size.
     result.set_is_prefinalized();
@@ -2326,25 +2320,8 @@
   StoreNonPointer(&raw_ptr()->num_type_arguments_, value);
 }
 
-void Class::set_num_own_type_arguments(intptr_t value) const {
-  if (!Utils::IsUint(kNumOwnTypeArgumentsSize, value)) {
-    ReportTooManyTypeArguments(*this);
-  }
-  StoreNonPointer(
-      &raw_ptr()->has_pragma_and_num_own_type_arguments_,
-      NumOwnTypeArguments::update(
-          value, raw_ptr()->has_pragma_and_num_own_type_arguments_));
-}
-
-void Class::set_has_pragma_and_num_own_type_arguments(uint16_t value) const {
-  StoreNonPointer(&raw_ptr()->has_pragma_and_num_own_type_arguments_, value);
-}
-
 void Class::set_has_pragma(bool value) const {
-  StoreNonPointer(
-      &raw_ptr()->has_pragma_and_num_own_type_arguments_,
-      HasPragmaBit::update(value,
-                           raw_ptr()->has_pragma_and_num_own_type_arguments_));
+  set_state_bits(HasPragmaBit::update(value, raw_ptr()->state_bits_));
 }
 
 // Initialize class fields of type Array with empty array.
@@ -2528,13 +2505,13 @@
   REUSABLE_FUNCTION_HANDLESCOPE(thread);
   Array& funcs = thread->ArrayHandle();
   Function& function = thread->FunctionHandle();
-  funcs ^= functions();
+  funcs = functions();
   ASSERT(!funcs.IsNull());
   Function& implicit_closure = Function::Handle(thread->zone());
   const intptr_t len = funcs.Length();
   for (intptr_t i = 0; i < len; i++) {
     function ^= funcs.At(i);
-    implicit_closure ^= function.implicit_closure_function();
+    implicit_closure = function.implicit_closure_function();
     if (implicit_closure.IsNull()) {
       // Skip non-implicit closure functions.
       continue;
@@ -2557,7 +2534,7 @@
   REUSABLE_OBJECT_HANDLESCOPE(thread);
   Array& funcs = thread->ArrayHandle();
   Object& object = thread->ObjectHandle();
-  funcs ^= invocation_dispatcher_cache();
+  funcs = invocation_dispatcher_cache();
   ASSERT(!funcs.IsNull());
   const intptr_t len = funcs.Length();
   for (intptr_t i = 0; i < len; i++) {
@@ -2580,7 +2557,7 @@
   REUSABLE_OBJECT_HANDLESCOPE(thread);
   Array& dispatcher_cache = thread->ArrayHandle();
   Object& object = thread->ObjectHandle();
-  dispatcher_cache ^= invocation_dispatcher_cache();
+  dispatcher_cache = invocation_dispatcher_cache();
   object = dispatcher_cache.At(idx);
   if (!object.IsFunction()) {
     return Function::null();
@@ -2594,7 +2571,7 @@
 }
 
 void Class::set_state_bits(intptr_t bits) const {
-  StoreNonPointer(&raw_ptr()->state_bits_, static_cast<uint16_t>(bits));
+  StoreNonPointer(&raw_ptr()->state_bits_, static_cast<uint32_t>(bits));
 }
 
 void Class::set_library(const Library& value) const {
@@ -2602,8 +2579,6 @@
 }
 
 void Class::set_type_parameters(const TypeArguments& value) const {
-  ASSERT((num_own_type_arguments() == kUnknownNumTypeArguments) ||
-         is_prefinalized());
   ASSERT((num_type_arguments() == kUnknownNumTypeArguments) ||
          is_prefinalized());
   StorePointer(&raw_ptr()->type_parameters_, value.raw());
@@ -2624,39 +2599,45 @@
   return type_params.Length();
 }
 
-intptr_t Class::NumOwnTypeArguments() const {
-  // Return cached value if already calculated.
-  if (num_own_type_arguments() != kUnknownNumTypeArguments) {
-    return num_own_type_arguments();
-  }
+intptr_t Class::ComputeNumTypeArguments() const {
+  ASSERT(is_declaration_loaded());
   Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
   Zone* zone = thread->zone();
+  Isolate* isolate = thread->isolate();
   const intptr_t num_type_params = NumTypeParameters();
-  if ((num_type_params == 0) || (super_type() == AbstractType::null()) ||
+
+  if ((super_type() == AbstractType::null()) ||
       (super_type() == isolate->object_store()->object_type())) {
-    set_num_own_type_arguments(num_type_params);
     return num_type_params;
   }
-  const AbstractType& sup_type = AbstractType::Handle(zone, super_type());
-  const TypeArguments& sup_type_args =
-      TypeArguments::Handle(zone, sup_type.arguments());
+
+  const auto& sup_type = AbstractType::Handle(zone, super_type());
+  ASSERT(sup_type.IsType());
+
+  const auto& sup_class = Class::Handle(zone, sup_type.type_class());
+  ASSERT(!sup_class.IsTypedefClass());
+
+  const intptr_t sup_class_num_type_args = sup_class.NumTypeArguments();
+  if (num_type_params == 0) {
+    return sup_class_num_type_args;
+  }
+
+  const auto& sup_type_args = TypeArguments::Handle(zone, sup_type.arguments());
   if (sup_type_args.IsNull()) {
     // The super type is raw or the super class is non generic.
     // In either case, overlapping is not possible.
-    set_num_own_type_arguments(num_type_params);
-    return num_type_params;
+    return sup_class_num_type_args + num_type_params;
   }
-  const intptr_t num_sup_type_args = sup_type_args.Length();
+
+  const intptr_t sup_type_args_length = sup_type_args.Length();
   // At this point, the super type may or may not be finalized. In either case,
   // the result of this function must remain the same.
   // The value of num_sup_type_args may increase when the super type is
-  // finalized, but the last num_sup_type_args type arguments will not be
+  // finalized, but the last [sup_type_args_length] type arguments will not be
   // modified by finalization, only shifted to higher indices in the vector.
   // The super type may not even be resolved yet. This is not necessary, since
   // we only check for matching type parameters, which are resolved by default.
-  const TypeArguments& type_params =
-      TypeArguments::Handle(zone, type_parameters());
+  const auto& type_params = TypeArguments::Handle(zone, type_parameters());
   // Determine the maximum overlap of a prefix of the vector consisting of the
   // type parameters of this class with a suffix of the vector consisting of the
   // type arguments of the super type of this class.
@@ -2665,58 +2646,38 @@
   // Attempt to overlap the whole vector of type parameters; reduce the size
   // of the vector (keeping the first type parameter) until it fits or until
   // its size is zero.
-  TypeParameter& type_param = TypeParameter::Handle(zone);
-  AbstractType& sup_type_arg = AbstractType::Handle(zone);
+  auto& type_param = TypeParameter::Handle(zone);
+  auto& sup_type_arg = AbstractType::Handle(zone);
   for (intptr_t num_overlapping_type_args =
-           (num_type_params < num_sup_type_args) ? num_type_params
-                                                 : num_sup_type_args;
+           (num_type_params < sup_type_args_length) ? num_type_params
+                                                    : sup_type_args_length;
        num_overlapping_type_args > 0; num_overlapping_type_args--) {
     intptr_t i = 0;
     for (; i < num_overlapping_type_args; i++) {
       type_param ^= type_params.TypeAt(i);
-      sup_type_arg = sup_type_args.TypeAt(num_sup_type_args -
+      sup_type_arg = sup_type_args.TypeAt(sup_type_args_length -
                                           num_overlapping_type_args + i);
       if (!type_param.Equals(sup_type_arg)) break;
     }
     if (i == num_overlapping_type_args) {
       // Overlap found.
-      set_num_own_type_arguments(num_type_params - num_overlapping_type_args);
-      return num_type_params - num_overlapping_type_args;
+      return sup_class_num_type_args + num_type_params -
+             num_overlapping_type_args;
     }
   }
   // No overlap found.
-  set_num_own_type_arguments(num_type_params);
-  return num_type_params;
+  return sup_class_num_type_args + num_type_params;
 }
 
 intptr_t Class::NumTypeArguments() const {
   // Return cached value if already calculated.
-  if (num_type_arguments() != kUnknownNumTypeArguments) {
-    return num_type_arguments();
+  intptr_t num_type_args = num_type_arguments();
+  if (num_type_args != kUnknownNumTypeArguments) {
+    return num_type_args;
   }
-  // To work properly, this call requires the super class of this class to be
-  // resolved, which is checked by the type_class() call on the super type.
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  Class& cls = Class::Handle(zone);
-  AbstractType& sup_type = AbstractType::Handle(zone);
-  cls = raw();
-  intptr_t num_type_args = 0;
-  do {
-    num_type_args += cls.NumOwnTypeArguments();
-    // Super type of Object class is null.
-    if ((cls.super_type() == AbstractType::null()) ||
-        (cls.super_type() == isolate->object_store()->object_type())) {
-      break;
-    }
-    sup_type = cls.super_type();
-    // A TypeRef or function type can appear as type argument of
-    // sup_type, but not as sup_type itself.
-    ASSERT(sup_type.IsType());
-    cls = sup_type.type_class();
-    ASSERT(!cls.IsTypedefClass());
-  } while (true);
+
+  num_type_args = ComputeNumTypeArguments();
+  ASSERT(num_type_args != kUnknownNumTypeArguments);
   set_num_type_arguments(num_type_args);
   return num_type_args;
 }
@@ -2756,7 +2717,7 @@
   TypeParameter& type_param = thread->TypeParameterHandle();
   String& type_param_name = thread->StringHandle();
 
-  type_params ^= type_parameters();
+  type_params = type_parameters();
   if (!type_params.IsNull()) {
     const intptr_t num_type_params = type_params.Length();
     for (intptr_t i = 0; i < num_type_params; i++) {
@@ -2834,7 +2795,7 @@
         cache.Length() == 0
             ? static_cast<intptr_t>(Class::kInvocationDispatcherEntrySize)
             : cache.Length() * 2;
-    cache ^= Array::Grow(cache, new_len);
+    cache = Array::Grow(cache, new_len);
     set_invocation_dispatcher_cache(cache);
   }
   auto entry = dispatchers[i];
@@ -2987,19 +2948,21 @@
   const Class& owner = Class::Handle(closure_function.Owner());
   Function& result = Function::Handle(owner.LookupDynamicFunction(getter_name));
   if (result.IsNull()) {
-    result ^= CreateMethodExtractor(getter_name);
+    result = CreateMethodExtractor(getter_name);
   }
   ASSERT(result.kind() == RawFunction::kMethodExtractor);
   return result.raw();
 }
 
 bool Library::FindPragma(Thread* T,
+                         bool only_core,
                          const Object& obj,
                          const String& pragma_name,
-                         Object* options) const {
+                         Object* options) {
   auto I = T->isolate();
   auto Z = T->zone();
   auto& lib = Library::Handle(Z);
+
   if (obj.IsClass()) {
     auto& klass = Class::Cast(obj);
     if (!klass.has_pragma()) return false;
@@ -3016,6 +2979,10 @@
     UNREACHABLE();
   }
 
+  if (only_core && !lib.IsAnyCoreLibrary()) {
+    return false;
+  }
+
   Object& metadata_obj = Object::Handle(Z, lib.GetMetadata(obj));
   if (metadata_obj.IsUnwindError()) {
     Report::LongJump(UnwindError::Cast(metadata_obj));
@@ -3425,7 +3392,7 @@
                                InvocationMirror::kStatic,
                                InvocationMirror::kSetter);
     }
-    parameter_type ^= setter.ParameterTypeAt(0);
+    parameter_type = setter.ParameterTypeAt(0);
     if (!argument_type.IsNullType() && !parameter_type.IsDynamicType() &&
         !value.IsInstanceOf(parameter_type, Object::null_type_arguments(),
                             Object::null_type_arguments())) {
@@ -3448,7 +3415,7 @@
                              InvocationMirror::kSetter);
   }
 
-  parameter_type ^= field.type();
+  parameter_type = field.type();
   if (!argument_type.IsNullType() && !parameter_type.IsDynamicType() &&
       !value.IsInstanceOf(parameter_type, Object::null_type_arguments(),
                           Object::null_type_arguments())) {
@@ -3668,8 +3635,6 @@
   result.set_next_field_offset(FakeInstance::NextFieldOffset());
   result.set_id(index);
   result.set_num_type_arguments(kUnknownNumTypeArguments);
-  result.set_num_own_type_arguments(kUnknownNumTypeArguments);
-  result.set_has_pragma(false);
   result.set_num_native_fields(0);
   result.set_state_bits(0);
   result.InitEmptyFields();
@@ -3722,9 +3687,9 @@
     cls.set_next_field_offset(instance_size);
     cls.set_num_native_fields(field_count);
     cls.set_is_finalized();
+    cls.set_is_declaration_loaded();
     cls.set_is_type_finalized();
     cls.set_is_synthesized_class();
-    cls.set_is_cycle_free();
     cls.set_kernel_offset(-1);
     library.AddClass(cls);
     return cls.raw();
@@ -4052,8 +4017,17 @@
   set_state_bits(AbstractBit::update(true, raw_ptr()->state_bits_));
 }
 
+void Class::set_is_declaration_loaded() const {
+  ASSERT(!is_declaration_loaded());
+  set_state_bits(ClassLoadingBits::update(RawClass::kDeclarationLoaded,
+                                          raw_ptr()->state_bits_));
+}
+
 void Class::set_is_type_finalized() const {
-  set_state_bits(TypeFinalizedBit::update(true, raw_ptr()->state_bits_));
+  ASSERT(is_declaration_loaded());
+  ASSERT(!is_type_finalized());
+  set_state_bits(ClassLoadingBits::update(RawClass::kTypeFinalized,
+                                          raw_ptr()->state_bits_));
 }
 
 void Class::set_is_patch() const {
@@ -4081,11 +4055,6 @@
   set_state_bits(FieldsMarkedNullableBit::update(true, raw_ptr()->state_bits_));
 }
 
-void Class::set_is_cycle_free() const {
-  ASSERT(!is_cycle_free());
-  set_state_bits(CycleFreeBit::update(true, raw_ptr()->state_bits_));
-}
-
 void Class::set_is_allocated(bool value) const {
   set_state_bits(IsAllocatedBit::update(value, raw_ptr()->state_bits_));
 }
@@ -4100,13 +4069,6 @@
       ClassFinalizedBits::update(RawClass::kFinalized, raw_ptr()->state_bits_));
 }
 
-void Class::ResetFinalization() const {
-  ASSERT(IsTopLevel() || IsClosureClass());
-  set_state_bits(
-      ClassFinalizedBits::update(RawClass::kAllocated, raw_ptr()->state_bits_));
-  set_state_bits(TypeFinalizedBit::update(false, raw_ptr()->state_bits_));
-}
-
 void Class::set_is_prefinalized() const {
   ASSERT(!is_finalized());
   set_state_bits(ClassFinalizedBits::update(RawClass::kPreFinalized,
@@ -4502,7 +4464,7 @@
   REUSABLE_ARRAY_HANDLESCOPE(thread);
   REUSABLE_FUNCTION_HANDLESCOPE(thread);
   Array& funcs = thread->ArrayHandle();
-  funcs ^= functions();
+  funcs = functions();
   ASSERT(!funcs.IsNull());
   const intptr_t len = funcs.Length();
   Function& function = thread->FunctionHandle();
@@ -4534,7 +4496,7 @@
     String& function_name = thread->StringHandle();
     for (intptr_t i = 0; i < len; i++) {
       function ^= funcs.At(i);
-      function_name ^= function.name();
+      function_name = function.name();
       if (function_name.Equals(name)) {
         return CheckFunctionType(function, kind);
       }
@@ -4554,14 +4516,14 @@
   REUSABLE_FUNCTION_HANDLESCOPE(thread);
   REUSABLE_STRING_HANDLESCOPE(thread);
   Array& funcs = thread->ArrayHandle();
-  funcs ^= functions();
+  funcs = functions();
   ASSERT(!funcs.IsNull());
   const intptr_t len = funcs.Length();
   Function& function = thread->FunctionHandle();
   String& function_name = thread->StringHandle();
   for (intptr_t i = 0; i < len; i++) {
     function ^= funcs.At(i);
-    function_name ^= function.name();
+    function_name = function.name();
     if (String::EqualsIgnoringPrivateKey(function_name, name)) {
       return CheckFunctionType(function, kind);
     }
@@ -4589,13 +4551,13 @@
   REUSABLE_FUNCTION_HANDLESCOPE(thread);
   REUSABLE_STRING_HANDLESCOPE(thread);
   Array& funcs = thread->ArrayHandle();
-  funcs ^= functions();
+  funcs = functions();
   intptr_t len = funcs.Length();
   Function& function = thread->FunctionHandle();
   String& function_name = thread->StringHandle();
   for (intptr_t i = 0; i < len; i++) {
     function ^= funcs.At(i);
-    function_name ^= function.name();
+    function_name = function.name();
     if (MatchesAccessorName(function_name, prefix, prefix_length, name)) {
       return function.raw();
     }
@@ -4626,7 +4588,7 @@
   REUSABLE_FIELD_HANDLESCOPE(thread);
   REUSABLE_STRING_HANDLESCOPE(thread);
   Array& flds = thread->ArrayHandle();
-  flds ^= fields();
+  flds = fields();
   ASSERT(!flds.IsNull());
   intptr_t len = flds.Length();
   Field& field = thread->FieldHandle();
@@ -4648,7 +4610,7 @@
     String& field_name = thread->StringHandle();
     for (intptr_t i = 0; i < len; i++) {
       field ^= flds.At(i);
-      field_name ^= field.name();
+      field_name = field.name();
       if (name.Equals(field_name)) {
         if (kind == kInstance) {
           return field.is_static() ? Field::null() : field.raw();
@@ -4674,14 +4636,14 @@
   REUSABLE_FIELD_HANDLESCOPE(thread);
   REUSABLE_STRING_HANDLESCOPE(thread);
   Array& flds = thread->ArrayHandle();
-  flds ^= fields();
+  flds = fields();
   ASSERT(!flds.IsNull());
   intptr_t len = flds.Length();
   Field& field = thread->FieldHandle();
   String& field_name = thread->StringHandle();
   for (intptr_t i = 0; i < len; i++) {
     field ^= flds.At(i);
-    field_name ^= field.name();
+    field_name = field.name();
     if (field.is_static() && instance_only) {
       // If we only care about instance fields, skip statics.
       continue;
@@ -5519,7 +5481,7 @@
       if (this->IsNew()) {
         result ^= Object::Clone(*this, Heap::kOld);
       } else {
-        result ^= this->raw();
+        result = this->raw();
       }
       ASSERT(result.IsOld());
       result.SetCanonical();  // Mark object as being canonical.
@@ -5692,15 +5654,11 @@
     }
   }
   switch (kind()) {
-    case RawFunction::kNoSuchMethodDispatcher:
-    case RawFunction::kInvokeFieldDispatcher:
     case RawFunction::kDynamicInvocationForwarder:
     case RawFunction::kImplicitClosureFunction:
     case RawFunction::kIrregexpFunction:
     case RawFunction::kFfiTrampoline:
       return false;
-    case RawFunction::kImplicitStaticFinalGetter:
-      return is_const();
     default:
       return true;
   }
@@ -5717,21 +5675,14 @@
   StorePointer(&raw_ptr()->bytecode_, value.raw());
 
   // We should not have loaded the bytecode if the function had code.
-  ASSERT(!HasCode());
-
-  if (FLAG_enable_interpreter) {
+  // However, we may load the bytecode to access source positions (see
+  // ProcessBytecodeTokenPositionsEntry in kernel.cc).
+  // In that case, do not install InterpretCall stub below.
+  if (FLAG_enable_interpreter && !HasCode()) {
     // Set the code entry_point to InterpretCall stub.
     SetInstructions(StubCode::InterpretCall());
   }
 }
-
-bool Function::HasBytecode() const {
-  return raw_ptr()->bytecode_ != Bytecode::null();
-}
-
-bool Function::HasBytecode(RawFunction* function) {
-  return function->ptr()->bytecode_ != Bytecode::null();
-}
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 bool Function::HasCode(RawFunction* function) {
@@ -5925,7 +5876,7 @@
 RawField* Function::accessor_field() const {
   ASSERT(kind() == RawFunction::kImplicitGetter ||
          kind() == RawFunction::kImplicitSetter ||
-         kind() == RawFunction::kImplicitStaticFinalGetter ||
+         kind() == RawFunction::kImplicitStaticGetter ||
          kind() == RawFunction::kStaticFieldInitializer ||
          kind() == RawFunction::kDynamicInvocationForwarder);
   return Field::RawCast(raw_ptr()->data_);
@@ -5934,7 +5885,7 @@
 void Function::set_accessor_field(const Field& value) const {
   ASSERT(kind() == RawFunction::kImplicitGetter ||
          kind() == RawFunction::kImplicitSetter ||
-         kind() == RawFunction::kImplicitStaticFinalGetter ||
+         kind() == RawFunction::kImplicitStaticGetter ||
          kind() == RawFunction::kStaticFieldInitializer);
   // Top level classes may be finalized multiple times.
   ASSERT(raw_ptr()->data_ == Object::null() || raw_ptr()->data_ == value.raw());
@@ -6060,6 +6011,34 @@
   return FfiTrampolineData::Cast(obj).c_signature();
 }
 
+int32_t Function::FfiCallbackId() const {
+  ASSERT(IsFfiTrampoline());
+  const Object& obj = Object::Handle(raw_ptr()->data_);
+  ASSERT(!obj.IsNull());
+  return FfiTrampolineData::Cast(obj).callback_id();
+}
+
+void Function::SetFfiCallbackId(int32_t value) const {
+  ASSERT(IsFfiTrampoline());
+  const Object& obj = Object::Handle(raw_ptr()->data_);
+  ASSERT(!obj.IsNull());
+  FfiTrampolineData::Cast(obj).set_callback_id(value);
+}
+
+RawFunction* Function::FfiCallbackTarget() const {
+  ASSERT(IsFfiTrampoline());
+  const Object& obj = Object::Handle(raw_ptr()->data_);
+  ASSERT(!obj.IsNull());
+  return FfiTrampolineData::Cast(obj).callback_target();
+}
+
+void Function::SetFfiCallbackTarget(const Function& target) const {
+  ASSERT(IsFfiTrampoline());
+  const Object& obj = Object::Handle(raw_ptr()->data_);
+  ASSERT(!obj.IsNull());
+  FfiTrampolineData::Cast(obj).set_callback_target(target);
+}
+
 RawType* Function::SignatureType() const {
   Type& type = Type::Handle(ExistingSignatureType());
   if (type.IsNull()) {
@@ -6160,8 +6139,8 @@
     case RawFunction::kImplicitSetter:
       return "ImplicitSetter";
       break;
-    case RawFunction::kImplicitStaticFinalGetter:
-      return "ImplicitStaticFinalGetter";
+    case RawFunction::kImplicitStaticGetter:
+      return "ImplicitStaticGetter";
       break;
     case RawFunction::kStaticFieldInitializer:
       return "StaticFieldInitializer";
@@ -6180,10 +6159,18 @@
       break;
     case RawFunction::kDynamicInvocationForwarder:
       return "DynamicInvocationForwarder";
-    default:
-      UNREACHABLE();
-      return NULL;
+      break;
+    case RawFunction::kFfiTrampoline:
+      return "FfiTrampoline";
+      break;
   }
+  // When you add a case to this switch, please also update the observatory.
+  // - runtime/observatory/lib/src/models/objects/function.dart (FunctionKind)
+  // - runtime/observatory/lib/src/elements/function_view.dart
+  //   (_functionKindToString)
+  // - runtime/observatory/lib/src/service/object.dart (stringToFunctionKind)
+  UNREACHABLE();
+  return NULL;
 }
 
 void Function::SetRedirectionType(const Type& type) const {
@@ -6407,7 +6394,7 @@
   while (!parent.IsNull()) {
     num_parent_type_params += parent.NumTypeParameters(thread);
     if (parent.IsImplicitClosureFunction()) break;
-    parent ^= parent.parent_function();
+    parent = parent.parent_function();
   }
   return num_parent_type_params;
 }
@@ -6420,7 +6407,7 @@
     THR_Print("%s%s\n",
               sig_fun.IsImplicitClosureFunction() ? "implicit closure: " : "",
               sig_type.ToCString());
-    sig_fun ^= sig_fun.parent_function();
+    sig_fun = sig_fun.parent_function();
   }
 }
 
@@ -6438,9 +6425,9 @@
   String& type_param_name = thread->StringHandle();
   Function& function = thread->FunctionHandle();
 
-  function ^= this->raw();
+  function = this->raw();
   while (!function.IsNull()) {
-    type_params ^= function.type_parameters();
+    type_params = function.type_parameters();
     if (!type_params.IsNull()) {
       const intptr_t num_type_params = type_params.Length();
       for (intptr_t i = 0; i < num_type_params; i++) {
@@ -6456,7 +6443,7 @@
       // function with identical type parameters.
       break;
     }
-    function ^= function.parent_function();
+    function = function.parent_function();
     if (function_level != NULL) {
       (*function_level)--;
     }
@@ -6714,7 +6701,7 @@
   String& argument_name = String::Handle(zone);
   String& parameter_name = String::Handle(zone);
   for (intptr_t i = 0; i < num_named_arguments; i++) {
-    argument_name ^= args_desc.NameAt(i);
+    argument_name = args_desc.NameAt(i);
     ASSERT(argument_name.IsSymbol());
     bool found = false;
     const intptr_t num_positional_args = num_arguments - num_named_arguments;
@@ -6753,9 +6740,9 @@
   Function& instantiated_func = Function::Handle(zone, raw());
 
   if (!HasInstantiatedSignature()) {
-    instantiated_func ^= InstantiateSignatureFrom(instantiator_type_args,
-                                                  Object::null_type_arguments(),
-                                                  kAllFree, Heap::kOld);
+    instantiated_func = InstantiateSignatureFrom(instantiator_type_args,
+                                                 Object::null_type_arguments(),
+                                                 kAllFree, Heap::kOld);
   }
   AbstractType& argument_type = AbstractType::Handle(zone);
   AbstractType& parameter_type = AbstractType::Handle(zone);
@@ -6765,8 +6752,8 @@
   for (intptr_t i = args_desc.FirstArgIndex(); i < args_desc.PositionalCount();
        ++i) {
     argument ^= args.At(i);
-    argument_type ^= argument.GetType(Heap::kOld);
-    parameter_type ^= instantiated_func.ParameterTypeAt(i);
+    argument_type = argument.GetType(Heap::kOld);
+    parameter_type = instantiated_func.ParameterTypeAt(i);
 
     // If the argument type is dynamic or the parameter is null, move on.
     if (parameter_type.IsDynamicType() || argument_type.IsNullType()) {
@@ -6791,7 +6778,7 @@
 
   // Check types of named arguments against expected parameter type.
   for (intptr_t i = 0; i < num_named_arguments; i++) {
-    argument_name ^= args_desc.NameAt(i);
+    argument_name = args_desc.NameAt(i);
     ASSERT(argument_name.IsSymbol());
     bool found = false;
     const intptr_t num_positional_args = num_arguments - num_named_arguments;
@@ -6805,8 +6792,8 @@
       if (argument_name.Equals(parameter_name)) {
         found = true;
         argument ^= args.At(args_desc.PositionAt(i));
-        argument_type ^= argument.GetType(Heap::kOld);
-        parameter_type ^= instantiated_func.ParameterTypeAt(j);
+        argument_type = argument.GetType(Heap::kOld);
+        parameter_type = instantiated_func.ParameterTypeAt(j);
 
         // If the argument type is dynamic or the parameter is null, move on.
         if (parameter_type.IsDynamicType() || argument_type.IsNullType()) {
@@ -6980,7 +6967,7 @@
           param_name = type_param.name();
           const bool is_generic_covariant = type_param.IsGenericCovariantImpl();
           ASSERT(type_param.IsFinalized());
-          type_param ^=
+          type_param =
               TypeParameter::New(cls, sig, type_param.index(), param_name, type,
                                  is_generic_covariant, type_param.token_pos());
           type_param.SetIsFinalized();
@@ -7272,20 +7259,19 @@
 RawFunction* Function::NewClosureFunctionWithKind(RawFunction::Kind kind,
                                                   const String& name,
                                                   const Function& parent,
-                                                  TokenPosition token_pos) {
+                                                  TokenPosition token_pos,
+                                                  const Object& owner) {
   ASSERT((kind == RawFunction::kClosureFunction) ||
          (kind == RawFunction::kImplicitClosureFunction));
   ASSERT(!parent.IsNull());
-  // Use the owner defining the parent function and not the class containing it.
-  const Object& parent_owner = Object::Handle(parent.raw_ptr()->owner_);
-  ASSERT(!parent_owner.IsNull());
+  ASSERT(!owner.IsNull());
   const Function& result = Function::Handle(
       Function::New(name, kind,
                     /* is_static = */ parent.is_static(),
                     /* is_const = */ false,
                     /* is_abstract = */ false,
                     /* is_external = */ false,
-                    /* is_native = */ false, parent_owner, token_pos));
+                    /* is_native = */ false, owner, token_pos));
   result.set_parent_function(parent);
   return result.raw();
 }
@@ -7293,15 +7279,19 @@
 RawFunction* Function::NewClosureFunction(const String& name,
                                           const Function& parent,
                                           TokenPosition token_pos) {
+  // Use the owner defining the parent function and not the class containing it.
+  const Object& parent_owner = Object::Handle(parent.RawOwner());
   return NewClosureFunctionWithKind(RawFunction::kClosureFunction, name, parent,
-                                    token_pos);
+                                    token_pos, parent_owner);
 }
 
 RawFunction* Function::NewImplicitClosureFunction(const String& name,
                                                   const Function& parent,
                                                   TokenPosition token_pos) {
+  // Use the owner defining the parent function and not the class containing it.
+  const Object& parent_owner = Object::Handle(parent.RawOwner());
   return NewClosureFunctionWithKind(RawFunction::kImplicitClosureFunction, name,
-                                    parent, token_pos);
+                                    parent, token_pos, parent_owner);
 }
 
 RawFunction* Function::NewSignatureFunction(const Object& owner,
@@ -7712,19 +7702,19 @@
       return script.raw();
     }
   }
+  const Object& obj = Object::Handle(raw_ptr()->owner_);
+  if (obj.IsPatchClass()) {
+    return PatchClass::Cast(obj).script();
+  }
   if (IsClosureFunction()) {
     return Function::Handle(parent_function()).script();
   }
-  const Object& obj = Object::Handle(raw_ptr()->owner_);
   if (obj.IsNull()) {
     ASSERT(IsSignatureFunction());
     return Script::null();
   }
-  if (obj.IsClass()) {
-    return Class::Cast(obj).script();
-  }
-  ASSERT(obj.IsPatchClass());
-  return PatchClass::Cast(obj).script();
+  ASSERT(obj.IsClass());
+  return Class::Cast(obj).script();
 }
 
 RawExternalTypedData* Function::KernelData() const {
@@ -7779,7 +7769,8 @@
 
 bool Function::ShouldCompilerOptimize() const {
   return !FLAG_enable_interpreter ||
-         ((unoptimized_code() != Object::null()) && WasCompiled());
+         ((unoptimized_code() != Object::null()) && WasCompiled()) ||
+         ForceOptimize();
 }
 
 RawString* Function::UserVisibleName() const {
@@ -7866,6 +7857,9 @@
       // (3) "var foo = () => null;": End token is `;', but in this case the
       // token semicolon belongs to the assignment so we skip it.
       const String& src = String::Handle(func_script.Source());
+      if (src.IsNull()) {
+        return Symbols::OptimizedOut().raw();
+      }
       uint16_t end_char = src.CharAt(end_token_pos().value());
       if ((end_char == ',') ||  // Case 1.
           (end_char == ')') ||  // Case 2.
@@ -8067,8 +8061,8 @@
     case RawFunction::kImplicitSetter:
       kind_str = " setter";
       break;
-    case RawFunction::kImplicitStaticFinalGetter:
-      kind_str = " static-final-getter";
+    case RawFunction::kImplicitStaticGetter:
+      kind_str = " static-getter";
       break;
     case RawFunction::kStaticFieldInitializer:
       kind_str = " static-field-initializer";
@@ -8210,12 +8204,22 @@
   StorePointer(&raw_ptr()->c_signature_, value.raw());
 }
 
+void FfiTrampolineData::set_callback_target(const Function& value) const {
+  StorePointer(&raw_ptr()->callback_target_, value.raw());
+}
+
+void FfiTrampolineData::set_callback_id(int32_t callback_id) const {
+  StoreNonPointer(&raw_ptr()->callback_id_, callback_id);
+}
+
 RawFfiTrampolineData* FfiTrampolineData::New() {
   ASSERT(Object::ffi_trampoline_data_class() != Class::null());
   RawObject* raw =
       Object::Allocate(FfiTrampolineData::kClassId,
                        FfiTrampolineData::InstanceSize(), Heap::kOld);
-  return reinterpret_cast<RawFfiTrampolineData*>(raw);
+  RawFfiTrampolineData* data = reinterpret_cast<RawFfiTrampolineData*>(raw);
+  data->ptr()->callback_id_ = -1;
+  return data;
 }
 
 const char* FfiTrampolineData::ToCString() const {
@@ -9449,15 +9453,18 @@
     kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
     line_starts_reader.LocationForPosition(token_pos.value(), line, column);
     if (token_len != NULL) {
+      *token_len = 1;
       // We don't explicitly save this data: Load the source
       // and find it from there.
       const String& source = String::Handle(zone, Source());
-      intptr_t offset = token_pos.value();
-      *token_len = 1;
-      if (offset < source.Length() && IsIdentStartChar(source.CharAt(offset))) {
-        for (intptr_t i = offset + 1;
-             i < source.Length() && IsIdentChar(source.CharAt(i)); ++i) {
-          ++*token_len;
+      if (!source.IsNull()) {
+        intptr_t offset = token_pos.value();
+        if (offset < source.Length() &&
+            IsIdentStartChar(source.CharAt(offset))) {
+          for (intptr_t i = offset + 1;
+               i < source.Length() && IsIdentChar(source.CharAt(i)); ++i) {
+            ++*token_len;
+          }
         }
       }
     }
@@ -10349,7 +10356,7 @@
   REUSABLE_OBJECT_HANDLESCOPE(thread);
   REUSABLE_STRING_HANDLESCOPE(thread);
   Array& dict = thread->ArrayHandle();
-  dict ^= dictionary();
+  dict = dictionary();
   intptr_t dict_size = dict.Length() - 1;
   *index = name.Hash() % dict_size;
   Object& entry = thread->ObjectHandle();
@@ -10443,7 +10450,7 @@
       AddScriptIfUnique(scripts, owner_script);
     }
 
-    cls ^= toplevel_class();
+    cls = toplevel_class();
     if (!cls.IsNull()) {
       owner_script = cls.script();
       AddScriptIfUnique(scripts, owner_script);
@@ -10610,7 +10617,7 @@
   String& found_obj_name = String::Handle();
   ASSERT(!ShouldBePrivate(name));
   for (intptr_t i = 0; i < num_imports(); i++) {
-    import ^= ImportAt(i);
+    import = ImportAt(i);
     obj = import.Lookup(name);
     if (!obj.IsNull()) {
       import_lib = import.library();
@@ -11055,7 +11062,7 @@
     if (check_is_entrypoint) {
       CHECK_ERROR(field.VerifyEntryPoint(EntryPointPragma::kSetterOnly));
     }
-    setter_type ^= field.type();
+    setter_type = field.type();
     if (!argument_type.IsNullType() && !setter_type.IsDynamicType() &&
         !value.IsInstanceOf(setter_type, Object::null_type_arguments(),
                             Object::null_type_arguments())) {
@@ -11095,7 +11102,7 @@
         InvocationMirror::kTopLevel, InvocationMirror::kSetter);
   }
 
-  setter_type ^= setter.ParameterTypeAt(0);
+  setter_type = setter.ParameterTypeAt(0);
   if (!argument_type.IsNullType() && !setter_type.IsDynamicType() &&
       !value.IsInstanceOf(setter_type, Object::null_type_arguments(),
                           Object::null_type_arguments())) {
@@ -11366,6 +11373,15 @@
   return private_name;
 }
 
+bool Library::IsPrivateCoreLibName(const String& name, const String& member) {
+  Zone* zone = Thread::Current()->zone();
+  const auto& core_lib = Library::Handle(zone, Library::CoreLibrary());
+  const auto& private_key = String::Handle(zone, core_lib.private_key());
+
+  ASSERT(core_lib.IsPrivate(member));
+  return name.EqualsConcat(member, private_key);
+}
+
 RawClass* Library::LookupCoreClass(const String& class_name) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
@@ -11944,12 +11960,12 @@
   if (!Field::IsGetterName(name) && !Field::IsSetterName(name) &&
       (obj.IsNull() || obj.IsLibraryPrefix())) {
     String& accessor_name = String::Handle(zone);
-    accessor_name ^= Field::LookupGetterSymbol(name);
+    accessor_name = Field::LookupGetterSymbol(name);
     if (!accessor_name.IsNull()) {
       obj = lib.LookupEntry(accessor_name, &ignore);
     }
     if (obj.IsNull()) {
-      accessor_name ^= Field::LookupSetterSymbol(name);
+      accessor_name = Field::LookupSetterSymbol(name);
       if (!accessor_name.IsNull()) {
         obj = lib.LookupEntry(accessor_name, &ignore);
       }
@@ -12080,7 +12096,7 @@
   {
     Isolate* isolate = thread->isolate();
     SafepointMutexLocker ml(isolate->kernel_data_lib_cache_mutex());
-    data ^= libraries_cache();
+    data = libraries_cache();
     ASSERT(!data.IsNull());
     IntHashMap table(&key, &value, &data);
     result ^= table.GetOrNull(name_index);
@@ -12103,7 +12119,7 @@
   {
     Isolate* isolate = thread->isolate();
     SafepointMutexLocker ml(isolate->kernel_data_lib_cache_mutex());
-    data ^= libraries_cache();
+    data = libraries_cache();
     ASSERT(!data.IsNull());
     IntHashMap table(&key, &value, &data);
     result ^= table.InsertOrGetValue(name_index, lib);
@@ -12129,7 +12145,7 @@
   {
     Isolate* isolate = thread->isolate();
     SafepointMutexLocker ml(isolate->kernel_data_class_cache_mutex());
-    data ^= classes_cache();
+    data = classes_cache();
     ASSERT(!data.IsNull());
     IntHashMap table(&key, &value, &data);
     result ^= table.GetOrNull(name_index);
@@ -12152,7 +12168,7 @@
   {
     Isolate* isolate = thread->isolate();
     SafepointMutexLocker ml(isolate->kernel_data_class_cache_mutex());
-    data ^= classes_cache();
+    data = classes_cache();
     ASSERT(!data.IsNull());
     IntHashMap table(&key, &value, &data);
     result ^= table.InsertOrGetValue(name_index, klass);
@@ -12213,6 +12229,39 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
+
+RawError* Library::FinalizeAllClasses() {
+  Thread* thread = Thread::Current();
+  ASSERT(thread->IsMutatorThread());
+  Zone* zone = thread->zone();
+  Error& error = Error::Handle(zone);
+  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      Isolate::Current()->object_store()->libraries());
+  Library& lib = Library::Handle(zone);
+  Class& cls = Class::Handle(zone);
+  for (int i = 0; i < libs.Length(); i++) {
+    lib ^= libs.At(i);
+    if (!lib.Loaded()) {
+      String& uri = String::Handle(zone, lib.url());
+      String& msg = String::Handle(
+          zone,
+          String::NewFormatted("Library '%s' is not loaded. "
+                               "Did you forget to call Dart_FinalizeLoading?",
+                               uri.ToCString()));
+      return ApiError::New(msg);
+    }
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+      error = cls.EnsureIsFinalized(thread);
+      if (!error.IsNull()) {
+        return error.raw();
+      }
+    }
+  }
+  return Error::null();
+}
+
 RawError* Library::ReadAllBytecode() {
   Thread* thread = Thread::Current();
   ASSERT(thread->IsMutatorThread());
@@ -13451,7 +13500,8 @@
   }
   // The final entry is always the sentinel.
   ASSERT(IsSentinelAt(len - 1));
-  if (NumArgsTested() == 0) {
+  const intptr_t num_args_tested = NumArgsTested();
+  if (num_args_tested == 0) {
     // No type feedback is being collected.
     const Array& data = Array::Handle(entries());
     // Static calls with no argument checks hold only one target and the
@@ -13460,11 +13510,11 @@
     // Static calls with no argument checks only need two words.
     ASSERT(TestEntryLength() == 2);
     // Set the target.
-    data.SetAt(0, func);
+    data.SetAt(TargetIndexFor(num_args_tested), func);
     // Set count to 0 as this is called during compilation, before the
     // call has been executed.
     const Smi& value = Smi::Handle(Smi::New(0));
-    data.SetAt(1, value);
+    data.SetAt(CountIndexFor(num_args_tested), value);
   } else {
     // Type feedback on arguments is being collected.
     const Array& data = Array::Handle(entries());
@@ -13478,9 +13528,9 @@
     for (intptr_t i = 0; i < NumArgsTested(); i++) {
       data.SetAt(i, object_cid);
     }
-    data.SetAt(NumArgsTested(), func);
+    data.SetAt(TargetIndexFor(num_args_tested), func);
     const Smi& value = Smi::Handle(Smi::New(0));
-    data.SetAt(NumArgsTested() + 1, value);
+    data.SetAt(CountIndexFor(num_args_tested), value);
   }
 }
 
@@ -13550,11 +13600,11 @@
   WriteSentinel(data, TestEntryLength());
   intptr_t data_pos = old_num * TestEntryLength();
   ASSERT(!target.IsNull());
-  data.SetAt(data_pos++, target);
+  data.SetAt(data_pos + TargetIndexFor(NumArgsTested()), target);
   // Set count to 0 as this is called during compilation, before the
   // call has been executed.
   const Smi& value = Smi::Handle(Smi::New(0));
-  data.SetAt(data_pos, value);
+  data.SetAt(data_pos + CountIndexFor(NumArgsTested()), value);
   // Multithreaded access to ICData requires setting of array to be the last
   // operation.
   set_entries(data);
@@ -13585,7 +13635,8 @@
   ASSERT((target.name() == target_name()) || ValidateInterceptor(target));
   DEBUG_ASSERT(!HasCheck(class_ids));
   ASSERT(NumArgsTested() > 1);  // Otherwise use 'AddReceiverCheck'.
-  ASSERT(class_ids.length() == NumArgsTested());
+  const intptr_t num_args_tested = NumArgsTested();
+  ASSERT(class_ids.length() == num_args_tested);
   const intptr_t old_num = NumberOfChecks();
   Array& data = Array::Handle(entries());
   // ICData of static calls with NumArgsTested() > 0 have initially a
@@ -13593,14 +13644,14 @@
   // overwritten by first real type feedback data.
   if (old_num == 1) {
     bool has_dummy_entry = true;
-    for (intptr_t i = 0; i < NumArgsTested(); i++) {
+    for (intptr_t i = 0; i < num_args_tested; i++) {
       if (Smi::Value(Smi::RawCast(data.At(i))) != kObjectCid) {
         has_dummy_entry = false;
         break;
       }
     }
     if (has_dummy_entry) {
-      ASSERT(target.raw() == data.At(NumArgsTested()));
+      ASSERT(target.raw() == data.At(TargetIndexFor(num_args_tested)));
       // Replace dummy entry.
       Smi& value = Smi::Handle();
       for (intptr_t i = 0; i < NumArgsTested(); i++) {
@@ -13620,12 +13671,12 @@
     // kIllegalCid is used as terminating value, do not add it.
     ASSERT(class_ids[i] != kIllegalCid);
     value = Smi::New(class_ids[i]);
-    data.SetAt(data_pos++, value);
+    data.SetAt(data_pos + i, value);
   }
   ASSERT(!target.IsNull());
-  data.SetAt(data_pos++, target);
+  data.SetAt(data_pos + TargetIndexFor(num_args_tested), target);
   value = Smi::New(count);
-  data.SetAt(data_pos++, value);
+  data.SetAt(data_pos + CountIndexFor(num_args_tested), value);
   // Multithreaded access to ICData requires setting of array to be the last
   // operation.
   set_entries(data);
@@ -13674,7 +13725,8 @@
   ASSERT(!HasCheck(class_ids));
 #endif  // DEBUG
   ASSERT(!target.IsNull());
-  ASSERT(NumArgsTested() == 1);  // Otherwise use 'AddCheck'.
+  const intptr_t kNumArgsTested = 1;
+  ASSERT(NumArgsTested() == kNumArgsTested);  // Otherwise use 'AddCheck'.
   ASSERT(receiver_class_id != kIllegalCid);
 
   intptr_t index = -1;
@@ -13691,10 +13743,12 @@
   }
   data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id)));
   if (Isolate::Current()->compilation_allowed()) {
-    data.SetAt(data_pos + 1, target);
-    data.SetAt(data_pos + 2, Smi::Handle(Smi::New(count)));
+    data.SetAt(data_pos + TargetIndexFor(kNumArgsTested), target);
+    data.SetAt(data_pos + CountIndexFor(kNumArgsTested),
+               Smi::Handle(Smi::New(count)));
     if (is_tracking_exactness()) {
-      data.SetAt(data_pos + 3, Smi::Handle(Smi::New(exactness.Encode())));
+      data.SetAt(data_pos + ExactnessIndexFor(kNumArgsTested),
+                 Smi::Handle(Smi::New(exactness.Encode())));
     }
   } else {
     // Precompilation only, after all functions have been compiled.
@@ -13702,8 +13756,8 @@
     const Code& code = Code::Handle(target.CurrentCode());
     const Smi& entry_point =
         Smi::Handle(Smi::FromAlignedAddress(code.EntryPoint()));
-    data.SetAt(data_pos + 1, code);
-    data.SetAt(data_pos + 2, entry_point);
+    data.SetAt(data_pos + CodeIndexFor(kNumArgsTested), code);
+    data.SetAt(data_pos + EntryPointIndexFor(kNumArgsTested), entry_point);
   }
   // Multithreaded access to ICData requires setting of array to be the last
   // operation.
@@ -13715,9 +13769,10 @@
     return StaticTypeExactnessState::NotTracking();
   }
   const Array& data = Array::Handle(entries());
-  intptr_t data_pos = index * TestEntryLength();
+  intptr_t data_pos =
+      index * TestEntryLength() + ExactnessIndexFor(NumArgsTested());
   return StaticTypeExactnessState::Decode(
-      Smi::Value(Smi::RawCast(data.At(data_pos + NumArgsTested() + 2))));
+      Smi::Value(Smi::RawCast(data.At(data_pos))));
 }
 
 void ICData::GetCheckAt(intptr_t index,
@@ -13730,9 +13785,9 @@
   const Array& data = Array::Handle(entries());
   intptr_t data_pos = index * TestEntryLength();
   for (intptr_t i = 0; i < NumArgsTested(); i++) {
-    class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++))));
+    class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos + i))));
   }
-  (*target) ^= data.At(data_pos++);
+  (*target) ^= data.At(data_pos + TargetIndexFor(NumArgsTested()));
 }
 
 bool ICData::IsSentinelAt(intptr_t index) const {
@@ -13771,7 +13826,7 @@
   const Array& data = Array::Handle(entries());
   const intptr_t data_pos = index * TestEntryLength();
   *class_id = Smi::Value(Smi::RawCast(data.At(data_pos)));
-  *target ^= data.At(data_pos + 1);
+  *target ^= data.At(data_pos + TargetIndexFor(NumArgsTested()));
 }
 
 intptr_t ICData::GetCidAt(intptr_t index) const {
@@ -13798,7 +13853,8 @@
 
 RawFunction* ICData::GetTargetAt(intptr_t index) const {
   ASSERT(Isolate::Current()->compilation_allowed());
-  const intptr_t data_pos = index * TestEntryLength() + NumArgsTested();
+  const intptr_t data_pos =
+      index * TestEntryLength() + TargetIndexFor(NumArgsTested());
   ASSERT(Object::Handle(Array::Handle(entries()).At(data_pos)).IsFunction());
 
   NoSafepointScope no_safepoint;
@@ -13807,7 +13863,8 @@
 }
 
 RawObject* ICData::GetTargetOrCodeAt(intptr_t index) const {
-  const intptr_t data_pos = index * TestEntryLength() + NumArgsTested();
+  const intptr_t data_pos =
+      index * TestEntryLength() + TargetIndexFor(NumArgsTested());
 
   NoSafepointScope no_safepoint;
   RawArray* raw_data = entries();
@@ -13871,18 +13928,6 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-RawFunction* ICData::GetTargetForReceiverClassId(intptr_t class_id,
-                                                 intptr_t* count_return) const {
-  const intptr_t len = NumberOfChecks();
-  for (intptr_t i = 0; i < len; i++) {
-    if (GetReceiverClassIdAt(i) == class_id) {
-      *count_return = GetCountAt(i);
-      return GetTargetAt(i);
-    }
-  }
-  return Function::null();
-}
-
 RawICData* ICData::AsUnaryClassChecksForCid(intptr_t cid,
                                             const Function& target) const {
   ASSERT(!IsNull());
@@ -14820,7 +14865,7 @@
     // Found code in isolate.
     return code.raw();
   }
-  code ^= Code::LookupCodeInVmIsolate(pc);
+  code = Code::LookupCodeInVmIsolate(pc);
   if (!code.IsNull() && (code.compile_timestamp() == timestamp) &&
       (code.PayloadStart() == pc)) {
     // Found code in VM isolate.
@@ -14879,7 +14924,7 @@
     // Regular stub.
     const char* name = StubCode::NameOfStub(EntryPoint());
     if (name == NULL) {
-      return zone->PrintToString("[unknown stub]");  // Not yet recorded.
+      return "[unknown stub]";  // Not yet recorded.
     }
     return zone->PrintToString("[Stub] %s", name);
   } else if (obj.IsClass()) {
@@ -15103,6 +15148,9 @@
     result.set_pc_descriptors(Object::empty_descriptors());
     result.set_instructions_binary_offset(instructions_offset);
     result.set_source_positions_binary_offset(0);
+#if !defined(PRODUCT)
+    result.set_local_variables_binary_offset(0);
+#endif
   }
   return result.raw();
 }
@@ -15141,40 +15189,75 @@
 #endif
 }
 
+intptr_t Bytecode::GetTryIndexAtPc(uword return_address) const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  UNREACHABLE();
+#else
+  intptr_t try_index = -1;
+  const uword pc_offset = return_address - PayloadStart();
+  const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
+  PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
+  while (iter.MoveNext()) {
+    // PC descriptors for try blocks in bytecode are generated in pairs,
+    // marking start and end of a try block.
+    // See BytecodeMetadataHelper::ReadExceptionsTable for details.
+    const intptr_t current_try_index = iter.TryIndex();
+    const uword start_pc = iter.PcOffset();
+    if (pc_offset < start_pc) {
+      break;
+    }
+    const bool has_next = iter.MoveNext();
+    ASSERT(has_next);
+    const uword end_pc = iter.PcOffset();
+    if (start_pc <= pc_offset && pc_offset < end_pc) {
+      ASSERT(try_index < current_try_index);
+      try_index = current_try_index;
+    }
+  }
+  return try_index;
+#endif
+}
+
 const char* Bytecode::ToCString() const {
   return Thread::Current()->zone()->PrintToString("Bytecode(%s)",
                                                   QualifiedName());
 }
 
-const char* Bytecode::Name() const {
-  if (raw() == Object::implicit_getter_bytecode().raw()) {
+static const char* BytecodeStubName(const Bytecode& bytecode) {
+  if (bytecode.raw() == Object::implicit_getter_bytecode().raw()) {
     return "[Bytecode Stub] VMInternal_ImplicitGetter";
-  } else if (raw() == Object::implicit_setter_bytecode().raw()) {
+  } else if (bytecode.raw() == Object::implicit_setter_bytecode().raw()) {
     return "[Bytecode Stub] VMInternal_ImplicitSetter";
-  } else if (raw() == Object::method_extractor_bytecode().raw()) {
+  } else if (bytecode.raw() ==
+             Object::implicit_static_getter_bytecode().raw()) {
+    return "[Bytecode Stub] VMInternal_ImplicitStaticGetter";
+  } else if (bytecode.raw() == Object::method_extractor_bytecode().raw()) {
     return "[Bytecode Stub] VMInternal_MethodExtractor";
+  } else if (bytecode.raw() == Object::invoke_closure_bytecode().raw()) {
+    return "[Bytecode Stub] VMInternal_InvokeClosure";
+  } else if (bytecode.raw() == Object::invoke_field_bytecode().raw()) {
+    return "[Bytecode Stub] VMInternal_InvokeField";
   }
+  return "[unknown stub]";
+}
 
+const char* Bytecode::Name() const {
   Zone* zone = Thread::Current()->zone();
   const Function& fun = Function::Handle(zone, function());
-  ASSERT(!fun.IsNull());
+  if (fun.IsNull()) {
+    return BytecodeStubName(*this);
+  }
   const char* function_name =
       String::Handle(zone, fun.UserVisibleName()).ToCString();
   return zone->PrintToString("[Bytecode] %s", function_name);
 }
 
 const char* Bytecode::QualifiedName() const {
-  if (raw() == Object::implicit_getter_bytecode().raw()) {
-    return "[Bytecode Stub] VMInternal_ImplicitGetter";
-  } else if (raw() == Object::implicit_setter_bytecode().raw()) {
-    return "[Bytecode Stub] VMInternal_ImplicitSetter";
-  } else if (raw() == Object::method_extractor_bytecode().raw()) {
-    return "[Bytecode Stub] VMInternal_MethodExtractor";
-  }
-
   Zone* zone = Thread::Current()->zone();
   const Function& fun = Function::Handle(zone, function());
-  ASSERT(!fun.IsNull());
+  if (fun.IsNull()) {
+    return BytecodeStubName(*this);
+  }
   const char* function_name =
       String::Handle(zone, fun.QualifiedScrubbedName()).ToCString();
   return zone->PrintToString("[Bytecode] %s", function_name);
@@ -15196,11 +15279,30 @@
   return Bytecode::null();
 }
 
+RawLocalVarDescriptors* Bytecode::GetLocalVarDescriptors() const {
+#if defined(PRODUCT) || defined(DART_PRECOMPILED_RUNTIME)
+  UNREACHABLE();
+  return LocalVarDescriptors::null();
+#else
+  Zone* zone = Thread::Current()->zone();
+  auto& var_descs = LocalVarDescriptors::Handle(zone, var_descriptors());
+  if (var_descs.IsNull()) {
+    const auto& func = Function::Handle(zone, function());
+    ASSERT(!func.IsNull());
+    var_descs =
+        kernel::BytecodeReader::ComputeLocalVarDescriptors(zone, func, *this);
+    ASSERT(!var_descs.IsNull());
+    set_var_descriptors(var_descs);
+  }
+  return var_descs.raw();
+#endif
+}
+
 RawContext* Context::New(intptr_t num_variables, Heap::Space space) {
   ASSERT(num_variables >= 0);
   ASSERT(Object::context_class() != Class::null());
 
-  if (num_variables < 0 || num_variables > kMaxElements) {
+  if (!IsValidLength(num_variables)) {
     // This should be caught before we reach here.
     FATAL1("Fatal error in Context::New: invalid num_variables %" Pd "\n",
            num_variables);
@@ -15606,12 +15708,12 @@
   SubtypeTestCacheTable entries(data);
   auto entry = entries[ix];
   *instance_class_id_or_function = entry.Get<kInstanceClassIdOrFunction>();
-  *instance_type_arguments ^= entry.Get<kInstanceTypeArguments>();
-  *instantiator_type_arguments ^= entry.Get<kInstantiatorTypeArguments>();
-  *function_type_arguments ^= entry.Get<kFunctionTypeArguments>();
-  *instance_parent_function_type_arguments ^=
+  *instance_type_arguments = entry.Get<kInstanceTypeArguments>();
+  *instantiator_type_arguments = entry.Get<kInstantiatorTypeArguments>();
+  *function_type_arguments = entry.Get<kFunctionTypeArguments>();
+  *instance_parent_function_type_arguments =
       entry.Get<kInstanceParentFunctionTypeArguments>();
-  *instance_delayed_type_arguments ^=
+  *instance_delayed_type_arguments =
       entry.Get<kInstanceDelayedFunctionTypeArguments>();
   *test_result ^= entry.Get<kTestResult>();
 }
@@ -15915,7 +16017,7 @@
   Class& klass = Class::Handle(zone, clazz());
   TypeArguments& type_args = TypeArguments::Handle(zone);
   if (klass.NumTypeArguments() > 0) {
-    type_args ^= GetTypeArguments();
+    type_args = GetTypeArguments();
   }
 
   const String& internal_getter_name =
@@ -15973,7 +16075,7 @@
   const Class& klass = Class::Handle(zone, clazz());
   TypeArguments& type_args = TypeArguments::Handle(zone);
   if (klass.NumTypeArguments() > 0) {
-    type_args ^= GetTypeArguments();
+    type_args = GetTypeArguments();
   }
 
   const String& internal_setter_name =
@@ -16029,7 +16131,7 @@
 
   TypeArguments& type_args = TypeArguments::Handle(zone);
   if (klass.NumTypeArguments() > 0) {
-    type_args ^= GetTypeArguments();
+    type_args = GetTypeArguments();
   }
 
   if (function.IsNull()) {
@@ -16230,7 +16332,7 @@
   const Class& cls = Class::Handle(zone, this->clazz());
   {
     SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
-    result ^= cls.LookupCanonicalInstance(zone, *this);
+    result = cls.LookupCanonicalInstance(zone, *this);
     if (!result.IsNull()) {
       return result.raw();
     }
@@ -16239,7 +16341,7 @@
       // Create a canonical object in old space.
       result ^= Object::Clone(*this, Heap::kOld);
     } else {
-      result ^= this->raw();
+      result = this->raw();
     }
     ASSERT(result.IsOld());
     result.SetCanonical();
@@ -17239,8 +17341,8 @@
   // yet, so do not call DeclarationType().
   Type& type = Type::Handle(type_class.declaration_type());
   if (type.IsNull()) {
-    type ^= Type::New(Class::Handle(type_class.raw()),
-                      Object::null_type_arguments(), TokenPosition::kNoSource);
+    type = Type::New(Class::Handle(type_class.raw()),
+                     Object::null_type_arguments(), TokenPosition::kNoSource);
     type.SetIsFinalized();
     type ^= type.Canonicalize();
     type_class.set_declaration_type(type);
@@ -17600,7 +17702,7 @@
           if (this->IsNew()) {
             type ^= Object::Clone(*this, Heap::kOld);
           } else {
-            type ^= this->raw();
+            type = this->raw();
           }
           ASSERT(type.IsOld());
           type.ComputeHash();
@@ -17675,7 +17777,7 @@
       if (this->IsNew()) {
         type ^= Object::Clone(*this, Heap::kOld);
       } else {
-        type ^= this->raw();
+        type = this->raw();
       }
       ASSERT(type.IsOld());
       type.SetCanonical();  // Mark object as being canonical.
@@ -18620,7 +18722,7 @@
   Isolate* isolate = thread->isolate();
   const Class& cls = Class::Handle(zone, isolate->object_store()->mint_class());
   Mint& canonical_value = Mint::Handle(zone);
-  canonical_value ^= cls.LookupCanonicalMint(zone, value);
+  canonical_value = cls.LookupCanonicalMint(zone, value);
   if (!canonical_value.IsNull()) {
     return canonical_value.raw();
   }
@@ -18628,7 +18730,7 @@
     SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
     // Retry lookup.
     {
-      canonical_value ^= cls.LookupCanonicalMint(zone, value);
+      canonical_value = cls.LookupCanonicalMint(zone, value);
       if (!canonical_value.IsNull()) {
         return canonical_value.raw();
       }
@@ -18753,7 +18855,7 @@
   // list of canonicalized constants.
   Double& canonical_value = Double::Handle(zone);
 
-  canonical_value ^= cls.LookupCanonicalDouble(zone, value);
+  canonical_value = cls.LookupCanonicalDouble(zone, value);
   if (!canonical_value.IsNull()) {
     return canonical_value.raw();
   }
@@ -18761,7 +18863,7 @@
     SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
     // Retry lookup.
     {
-      canonical_value ^= cls.LookupCanonicalDouble(zone, value);
+      canonical_value = cls.LookupCanonicalDouble(zone, value);
       if (!canonical_value.IsNull()) {
         return canonical_value.raw();
       }
@@ -20395,7 +20497,7 @@
 }
 
 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) {
-  if ((len < 0) || (len > Array::kMaxElements)) {
+  if (!IsValidLength(len)) {
     // This should be caught before we reach here.
     FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len);
   }
@@ -21124,7 +21226,7 @@
   TypeArguments& type_args = TypeArguments::Handle(zone);
   type_args = TypeArguments::New(1);
   type_args.SetTypeAt(Pointer::kNativeTypeArgPos, type_arg);
-  type_args ^= type_args.Canonicalize();
+  type_args = type_args.Canonicalize();
 
   const Class& cls = Class::Handle(Isolate::Current()->class_table()->At(cid));
   cls.EnsureIsFinalized(Thread::Current());
@@ -21170,9 +21272,9 @@
       Isolate::Current()->object_store()->ffi_pointer_class());
   AbstractType& pointer_type =
       AbstractType::Handle(pointer_class.DeclarationType());
-  pointer_type ^= pointer_type.InstantiateFrom(Object::null_type_arguments(),
-                                               Object::null_type_arguments(),
-                                               kNoneFree, NULL, Heap::kNew);
+  pointer_type = pointer_type.InstantiateFrom(Object::null_type_arguments(),
+                                              Object::null_type_arguments(),
+                                              kNoneFree, NULL, Heap::kNew);
   AbstractType& type = AbstractType::Handle(obj.GetType(Heap::kNew));
   return type.IsSubtypeOf(pointer_type, Heap::kNew);
 }
@@ -21255,6 +21357,40 @@
   return "SendPort";
 }
 
+static void TransferableTypedDataFinalizer(void* isolate_callback_data,
+                                           Dart_WeakPersistentHandle handle,
+                                           void* peer) {
+  delete (reinterpret_cast<TransferableTypedDataPeer*>(peer));
+}
+
+RawTransferableTypedData* TransferableTypedData::New(uint8_t* data,
+                                                     intptr_t length,
+                                                     Heap::Space space) {
+  TransferableTypedDataPeer* peer = new TransferableTypedDataPeer(data, length);
+
+  Thread* thread = Thread::Current();
+  TransferableTypedData& result = TransferableTypedData::Handle();
+  {
+    RawObject* raw =
+        Object::Allocate(TransferableTypedData::kClassId,
+                         TransferableTypedData::InstanceSize(), space);
+    NoSafepointScope no_safepoint;
+    thread->heap()->SetPeer(raw, peer);
+    result ^= raw;
+  }
+  // Set up finalizer so it frees allocated memory if handle is
+  // garbage-collected.
+  peer->set_handle(FinalizablePersistentHandle::New(
+      thread->isolate(), result, peer, &TransferableTypedDataFinalizer,
+      length));
+
+  return result.raw();
+}
+
+const char* TransferableTypedData::ToCString() const {
+  return "TransferableTypedData";
+}
+
 const char* Closure::ToCString() const {
   Zone* zone = Thread::Current()->zone();
   const Function& fun = Function::Handle(zone, function());
@@ -21570,7 +21706,7 @@
       }
     }
     // Follow the link.
-    stack_trace ^= stack_trace.async_link();
+    stack_trace = stack_trace.async_link();
   } while (!stack_trace.IsNull());
 
   return buffer.buffer();
@@ -21640,7 +21776,7 @@
       }
     }
     // Follow the link.
-    stack_trace ^= stack_trace.async_link();
+    stack_trace = stack_trace.async_link();
   } while (!stack_trace.IsNull());
 
   return buffer.buffer();
@@ -21703,23 +21839,45 @@
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.set_type(kUninitialized);
-    result.set_flags(0);
-    result.set_num_registers(-1);
+    result.set_flags(RegExpFlags());
+    result.set_num_registers(/*is_one_byte=*/false, -1);
+    result.set_num_registers(/*is_one_byte=*/true, -1);
   }
   return result.raw();
 }
 
-const char* RegExp::Flags() const {
-  switch (flags()) {
-    case kGlobal | kIgnoreCase | kMultiLine:
+const char* RegExpFlags::ToCString() const {
+  switch (value_ & ~kGlobal) {
+    case kIgnoreCase | kMultiLine | kDotAll | kUnicode:
+      return "imsu";
+    case kIgnoreCase | kMultiLine | kDotAll:
+      return "ims";
+    case kIgnoreCase | kMultiLine | kUnicode:
+      return "imu";
+    case kIgnoreCase | kUnicode | kDotAll:
+      return "ius";
+    case kMultiLine | kDotAll | kUnicode:
+      return "msu";
     case kIgnoreCase | kMultiLine:
       return "im";
-    case kGlobal | kIgnoreCase:
+    case kIgnoreCase | kDotAll:
+      return "is";
+    case kIgnoreCase | kUnicode:
+      return "iu";
+    case kMultiLine | kDotAll:
+      return "ms";
+    case kMultiLine | kUnicode:
+      return "mu";
+    case kDotAll | kUnicode:
+      return "su";
     case kIgnoreCase:
       return "i";
-    case kGlobal | kMultiLine:
     case kMultiLine:
       return "m";
+    case kDotAll:
+      return "s";
+    case kUnicode:
+      return "u";
     default:
       break;
   }
@@ -21741,9 +21899,7 @@
     return false;
   }
   // Match the flags.
-  if ((is_global() != other_js.is_global()) ||
-      (is_ignore_case() != other_js.is_ignore_case()) ||
-      (is_multi_line() != other_js.is_multi_line())) {
+  if (flags() != other_js.flags()) {
     return false;
   }
   return true;
@@ -21752,7 +21908,7 @@
 const char* RegExp::ToCString() const {
   const String& str = String::Handle(pattern());
   return OS::SCreate(Thread::Current()->zone(), "RegExp: pattern=%s flags=%s",
-                     str.ToCString(), Flags());
+                     str.ToCString(), flags().ToCString());
 }
 
 RawWeakProperty* WeakProperty::New(Heap::Space space) {
@@ -21879,7 +22035,7 @@
   for (intptr_t i = 0; i < tag_table.Length(); i++) {
     other ^= tag_table.At(i);
     ASSERT(!other.IsNull());
-    tag_label ^= other.label();
+    tag_label = other.label();
     ASSERT(!tag_label.IsNull());
     if (tag_label.Equals(label)) {
       return other.raw();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index b1a0d3b..33261da 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -398,7 +398,11 @@
   V(Array, extractor_parameter_names)                                          \
   V(Bytecode, implicit_getter_bytecode)                                        \
   V(Bytecode, implicit_setter_bytecode)                                        \
+  V(Bytecode, implicit_static_getter_bytecode)                                 \
   V(Bytecode, method_extractor_bytecode)                                       \
+  V(Bytecode, invoke_closure_bytecode)                                         \
+  V(Bytecode, invoke_field_bytecode)                                           \
+  V(Bytecode, nsm_dispatcher_bytecode)                                         \
   V(Instance, sentinel)                                                        \
   V(Instance, transition_sentinel)                                             \
   V(Instance, unknown_constant)                                                \
@@ -912,10 +916,6 @@
   // the super class.
   intptr_t NumTypeArguments() const;
 
-  // Return the number of type arguments that are specific to this class, i.e.
-  // not overlapping with the type arguments of the super class of this class.
-  intptr_t NumOwnTypeArguments() const;
-
   // Return true if this class declares type parameters.
   bool IsGeneric() const { return NumTypeParameters(Thread::Current()) > 0; }
 
@@ -946,7 +946,10 @@
   }
 
   // The super type of this class, Object type if not explicitly specified.
-  RawAbstractType* super_type() const { return raw_ptr()->super_type_; }
+  RawAbstractType* super_type() const {
+    ASSERT(is_declaration_loaded());
+    return raw_ptr()->super_type_;
+  }
   void set_super_type(const AbstractType& value) const;
   static intptr_t super_type_offset() {
     return OFFSET_OF(RawClass, super_type_);
@@ -1113,8 +1116,17 @@
   }
   void set_is_abstract() const;
 
+  RawClass::ClassLoadingState class_loading_state() const {
+    return ClassLoadingBits::decode(raw_ptr()->state_bits_);
+  }
+
+  bool is_declaration_loaded() const {
+    return class_loading_state() >= RawClass::kDeclarationLoaded;
+  }
+  void set_is_declaration_loaded() const;
+
   bool is_type_finalized() const {
-    return TypeFinalizedBit::decode(raw_ptr()->state_bits_);
+    return class_loading_state() >= RawClass::kTypeFinalized;
   }
   void set_is_type_finalized() const;
 
@@ -1142,8 +1154,6 @@
 
   void set_is_prefinalized() const;
 
-  void ResetFinalization() const;
-
   bool is_const() const { return ConstBit::decode(raw_ptr()->state_bits_); }
   void set_is_const() const;
 
@@ -1163,11 +1173,6 @@
   }
   void set_is_fields_marked_nullable() const;
 
-  bool is_cycle_free() const {
-    return CycleFreeBit::decode(raw_ptr()->state_bits_);
-  }
-  void set_is_cycle_free() const;
-
   bool is_allocated() const {
     return IsAllocatedBit::decode(raw_ptr()->state_bits_);
   }
@@ -1330,41 +1335,44 @@
   enum StateBits {
     kConstBit = 0,
     kImplementedBit = 1,
-    kTypeFinalizedBit = 2,
-    kClassFinalizedPos = 3,
+    kClassFinalizedPos = 2,
     kClassFinalizedSize = 2,
-    kAbstractBit = kClassFinalizedPos + kClassFinalizedSize,  // = 5
-    kPatchBit = 6,
+    kClassLoadingPos = kClassFinalizedPos + kClassFinalizedSize,  // = 4
+    kClassLoadingSize = 2,
+    kAbstractBit = kClassLoadingPos + kClassLoadingSize,  // = 6
+    kPatchBit,
     kSynthesizedClassBit,
     kMixinAppAliasBit,
     kMixinTypeAppliedBit,
     kFieldsMarkedNullableBit,
-    kCycleFreeBit,
     kEnumBit,
     kTransformedMixinApplicationBit,
     kIsAllocatedBit,
     kIsLoadedBit,
+    kHasPragmaBit,
   };
-  class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
-  class ImplementedBit : public BitField<uint16_t, bool, kImplementedBit, 1> {};
-  class TypeFinalizedBit
-      : public BitField<uint16_t, bool, kTypeFinalizedBit, 1> {};
-  class ClassFinalizedBits : public BitField<uint16_t,
+  class ConstBit : public BitField<uint32_t, bool, kConstBit, 1> {};
+  class ImplementedBit : public BitField<uint32_t, bool, kImplementedBit, 1> {};
+  class ClassFinalizedBits : public BitField<uint32_t,
                                              RawClass::ClassFinalizedState,
                                              kClassFinalizedPos,
                                              kClassFinalizedSize> {};
-  class AbstractBit : public BitField<uint16_t, bool, kAbstractBit, 1> {};
-  class PatchBit : public BitField<uint16_t, bool, kPatchBit, 1> {};
+  class ClassLoadingBits : public BitField<uint32_t,
+                                           RawClass::ClassLoadingState,
+                                           kClassLoadingPos,
+                                           kClassLoadingSize> {};
+  class AbstractBit : public BitField<uint32_t, bool, kAbstractBit, 1> {};
+  class PatchBit : public BitField<uint32_t, bool, kPatchBit, 1> {};
   class SynthesizedClassBit
-      : public BitField<uint16_t, bool, kSynthesizedClassBit, 1> {};
+      : public BitField<uint32_t, bool, kSynthesizedClassBit, 1> {};
   class FieldsMarkedNullableBit
-      : public BitField<uint16_t, bool, kFieldsMarkedNullableBit, 1> {};
-  class CycleFreeBit : public BitField<uint16_t, bool, kCycleFreeBit, 1> {};
-  class EnumBit : public BitField<uint16_t, bool, kEnumBit, 1> {};
+      : public BitField<uint32_t, bool, kFieldsMarkedNullableBit, 1> {};
+  class EnumBit : public BitField<uint32_t, bool, kEnumBit, 1> {};
   class TransformedMixinApplicationBit
-      : public BitField<uint16_t, bool, kTransformedMixinApplicationBit, 1> {};
-  class IsAllocatedBit : public BitField<uint16_t, bool, kIsAllocatedBit, 1> {};
-  class IsLoadedBit : public BitField<uint16_t, bool, kIsLoadedBit, 1> {};
+      : public BitField<uint32_t, bool, kTransformedMixinApplicationBit, 1> {};
+  class IsAllocatedBit : public BitField<uint32_t, bool, kIsAllocatedBit, 1> {};
+  class IsLoadedBit : public BitField<uint32_t, bool, kIsLoadedBit, 1> {};
+  class HasPragmaBit : public BitField<uint32_t, bool, kHasPragmaBit, 1> {};
 
   void set_name(const String& value) const;
   void set_user_name(const String& value) const;
@@ -1382,40 +1390,23 @@
   // functions_hash_table is in use iff there are at least this many functions.
   static const intptr_t kFunctionLookupHashTreshold = 16;
 
-  enum HasPragmaAndNumOwnTypeArgumentsBits {
-    kHasPragmaBit = 0,
-    kNumOwnTypeArgumentsPos = 1,
-    kNumOwnTypeArgumentsSize = 15
-  };
-
-  class HasPragmaBit : public BitField<uint16_t, bool, kHasPragmaBit, 1> {};
-  class NumOwnTypeArguments : public BitField<uint16_t,
-                                              uint16_t,
-                                              kNumOwnTypeArgumentsPos,
-                                              kNumOwnTypeArgumentsSize> {};
-
   // Initial value for the cached number of type arguments.
-  static const intptr_t kUnknownNumTypeArguments =
-      (1U << kNumOwnTypeArgumentsSize) - 1;
+  static const intptr_t kUnknownNumTypeArguments = -1;
 
   int16_t num_type_arguments() const { return raw_ptr()->num_type_arguments_; }
   void set_num_type_arguments(intptr_t value) const;
 
  public:
   bool has_pragma() const {
-    return HasPragmaBit::decode(
-        raw_ptr()->has_pragma_and_num_own_type_arguments_);
+    return HasPragmaBit::decode(raw_ptr()->state_bits_);
   }
   void set_has_pragma(bool has_pragma) const;
 
  private:
-  uint16_t num_own_type_arguments() const {
-    return NumOwnTypeArguments::decode(
-        raw_ptr()->has_pragma_and_num_own_type_arguments_);
-  }
-  void set_num_own_type_arguments(intptr_t value) const;
-
-  void set_has_pragma_and_num_own_type_arguments(uint16_t value) const;
+  // Calculates number of type arguments of this class.
+  // This includes type arguments of a superclass and takes overlapping
+  // of type arguments into account.
+  intptr_t ComputeNumTypeArguments() const;
 
   // Assigns empty array to all raw class array fields.
   void InitEmptyFields();
@@ -1771,8 +1762,6 @@
   intptr_t GetClassIdAt(intptr_t index, intptr_t arg_nr) const;
 
   RawFunction* GetTargetAt(intptr_t index) const;
-  RawFunction* GetTargetForReceiverClassId(intptr_t class_id,
-                                           intptr_t* count_return) const;
 
   RawObject* GetTargetOrCodeAt(intptr_t index) const;
   void SetCodeAt(intptr_t index, const Code& value) const;
@@ -1825,16 +1814,13 @@
   static intptr_t TestEntryLengthFor(intptr_t num_args,
                                      bool tracking_exactness);
 
-  static intptr_t TargetIndexFor(intptr_t num_args) { return num_args; }
-  static intptr_t CodeIndexFor(intptr_t num_args) { return num_args; }
+  static intptr_t CountIndexFor(intptr_t num_args) { return num_args; }
+  static intptr_t EntryPointIndexFor(intptr_t num_args) { return num_args; }
 
-  static intptr_t CountIndexFor(intptr_t num_args) { return (num_args + 1); }
-  static intptr_t EntryPointIndexFor(intptr_t num_args) {
-    return (num_args + 1);
-  }
-  static intptr_t ExactnessOffsetFor(intptr_t num_args) {
-    return (num_args + 2);
-  }
+  static intptr_t TargetIndexFor(intptr_t num_args) { return num_args + 1; }
+  static intptr_t CodeIndexFor(intptr_t num_args) { return num_args + 1; }
+
+  static intptr_t ExactnessIndexFor(intptr_t num_args) { return num_args + 2; }
 
   bool IsUsedAt(intptr_t i) const;
 
@@ -1969,9 +1955,6 @@
 
 class Function : public Object {
  public:
-  // A value to prevent premature code collection. lg(32) = 5 major GCs.
-  static constexpr intptr_t kGraceUsageCounter = 32;
-
   RawString* name() const { return raw_ptr()->name_; }
   RawString* UserVisibleName() const;  // Same as scrubbed name.
   RawString* QualifiedScrubbedName() const {
@@ -2004,6 +1987,20 @@
   // Can only be used on FFI trampolines.
   RawFunction* FfiCSignature() const;
 
+  // Can only be called on FFI trampolines.
+  // -1 for Dart -> native calls.
+  int32_t FfiCallbackId() const;
+
+  // Can only be called on FFI trampolines.
+  void SetFfiCallbackId(int32_t value) const;
+
+  // Can only be called on FFI trampolines.
+  // Null for Dart -> native calls.
+  RawFunction* FfiCallbackTarget() const;
+
+  // Can only be called on FFI trampolines.
+  void SetFfiCallbackTarget(const Function& target) const;
+
   // Return a new function with instantiated result and parameter types.
   RawFunction* InstantiateSignatureFrom(
       const TypeArguments& instantiator_type_arguments,
@@ -2151,7 +2148,7 @@
   bool HasCode() const;
   static bool HasCode(RawFunction* function);
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  static bool HasBytecode(RawFunction* function);
+  static inline bool HasBytecode(RawFunction* function);
 #endif
 
   static intptr_t code_offset() { return OFFSET_OF(RawFunction, code_); }
@@ -2172,7 +2169,9 @@
   bool IsBytecodeAllowed(Zone* zone) const;
   void AttachBytecode(const Bytecode& bytecode) const;
   RawBytecode* bytecode() const { return raw_ptr()->bytecode_; }
-  bool HasBytecode() const;
+  inline bool HasBytecode() const;
+#else
+  inline bool HasBytecode() const { return false; }
 #endif
 
   virtual intptr_t Hash() const;
@@ -2218,7 +2217,7 @@
   bool IsImplicitGetterOrSetter() const {
     return kind() == RawFunction::kImplicitGetter ||
            kind() == RawFunction::kImplicitSetter ||
-           kind() == RawFunction::kImplicitStaticFinalGetter;
+           kind() == RawFunction::kImplicitStaticGetter;
   }
 
   // Returns true iff an implicit closure function has been created
@@ -2296,7 +2295,7 @@
       case RawFunction::kImplicitClosureFunction:
       case RawFunction::kSignatureFunction:
       case RawFunction::kConstructor:
-      case RawFunction::kImplicitStaticFinalGetter:
+      case RawFunction::kImplicitStaticGetter:
       case RawFunction::kStaticFieldInitializer:
       case RawFunction::kIrregexpFunction:
         return false;
@@ -2315,7 +2314,7 @@
       case RawFunction::kSetterFunction:
       case RawFunction::kImplicitGetter:
       case RawFunction::kImplicitSetter:
-      case RawFunction::kImplicitStaticFinalGetter:
+      case RawFunction::kImplicitStaticGetter:
       case RawFunction::kStaticFieldInitializer:
       case RawFunction::kIrregexpFunction:
         return true;
@@ -2530,13 +2529,17 @@
   // dependencies. It will be compiled into optimized code immediately when it's
   // run.
   bool ForceOptimize() const {
-    return IsFfiTrampoline()
+    if (IsFfiTrampoline()) {
+      return true;
+    }
     // On DBC we use native calls instead of IR for the view factories (see
     // kernel_to_il.cc)
 #if !defined(TARGET_ARCH_DBC)
-           || IsTypedDataViewFactory()
+    if (IsTypedDataViewFactory()) {
+      return true;
+    }
 #endif
-        ;
+    return false;
   }
 
   bool CanBeInlined() const;
@@ -2595,7 +2598,7 @@
     switch (kind()) {
       case RawFunction::kImplicitGetter:
       case RawFunction::kImplicitSetter:
-      case RawFunction::kImplicitStaticFinalGetter:
+      case RawFunction::kImplicitStaticGetter:
       case RawFunction::kNoSuchMethodDispatcher:
       case RawFunction::kInvokeFieldDispatcher:
       case RawFunction::kDynamicInvocationForwarder:
@@ -2757,7 +2760,8 @@
   static RawFunction* NewClosureFunctionWithKind(RawFunction::Kind kind,
                                                  const String& name,
                                                  const Function& parent,
-                                                 TokenPosition token_pos);
+                                                 TokenPosition token_pos,
+                                                 const Object& owner);
 
   // Allocates a new Function object representing a closure function.
   static RawFunction* NewClosureFunction(const String& name,
@@ -3130,6 +3134,12 @@
   RawFunction* c_signature() const { return raw_ptr()->c_signature_; }
   void set_c_signature(const Function& value) const;
 
+  RawFunction* callback_target() const { return raw_ptr()->callback_target_; }
+  void set_callback_target(const Function& value) const;
+
+  int32_t callback_id() const { return raw_ptr()->callback_id_; }
+  void set_callback_id(int32_t value) const;
+
   static RawFfiTrampolineData* New();
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
@@ -3140,8 +3150,15 @@
 
 class Field : public Object {
  public:
+  // The field that this field was cloned from, or this field itself if it isn't
+  // a clone. The purpose of cloning is that the fields the background compiler
+  // sees are consistent.
   RawField* Original() const;
+
+  // Set the original field that this field was cloned from.
   void SetOriginal(const Field& value) const;
+
+  // Returns whether this field is an original or a clone.
   bool IsOriginal() const {
     if (IsNull()) {
       return true;
@@ -3372,17 +3389,23 @@
   // to have or kDynamicCid if such class id is not known.
   // Stores to this field must update this information hence the name.
   intptr_t guarded_cid() const {
-#if defined(DEGUG)
+#if defined(DEBUG)
+    // This assertion ensures that the cid seen by the background compiler is
+    // consistent. So the assertion passes if the field is a clone. It also
+    // passes if the field is static, because we don't use field guards on
+    // static fields.
     Thread* thread = Thread::Current();
-    ASSERT(!IsOriginal() || thread->IsMutator() || thread->IsAtSafepoint());
+    ASSERT(!IsOriginal() || is_static() || thread->IsMutatorThread() ||
+           thread->IsAtSafepoint());
 #endif
     return raw_ptr()->guarded_cid_;
   }
 
   void set_guarded_cid(intptr_t cid) const {
-#if defined(DEGUG)
+#if defined(DEBUG)
     Thread* thread = Thread::Current();
-    ASSERT(!IsOriginal() || thread->IsMutator() || thread->IsAtSafepoint());
+    ASSERT(!IsOriginal() || is_static() || thread->IsMutatorThread() ||
+           thread->IsAtSafepoint());
 #endif
     StoreNonPointer(&raw_ptr()->guarded_cid_, cid);
   }
@@ -3434,7 +3457,18 @@
   // Internally we is_nullable_ field contains either kNullCid (nullable) or
   // kInvalidCid (non-nullable) instead of boolean. This is done to simplify
   // guarding sequence in the generated code.
-  bool is_nullable() const { return raw_ptr()->is_nullable_ == kNullCid; }
+  bool is_nullable(bool silence_assert = false) const {
+#if defined(DEBUG)
+    if (!silence_assert) {
+      // Same assert as guarded_cid(), because is_nullable() also needs to be
+      // consistent for the background compiler.
+      Thread* thread = Thread::Current();
+      ASSERT(!IsOriginal() || is_static() || thread->IsMutatorThread() ||
+             thread->IsAtSafepoint());
+    }
+#endif
+    return raw_ptr()->is_nullable_ == kNullCid;
+  }
   void set_is_nullable(bool val) const {
     ASSERT(Thread::Current()->IsMutatorThread());
     StoreNonPointer(&raw_ptr()->is_nullable_, val ? kNullCid : kIllegalCid);
@@ -3887,12 +3921,16 @@
   // If successful returns `true`. If an error happens during constant
   // evaluation, returns `false.
   //
+  // If [only_core] is true, then the annotations on the object will only
+  // be inspected if it is part of a core library.
+  //
   // WARNING: If the isolate received an [UnwindError] this function will not
   // return and rather unwinds until the enclosing setjmp() handler.
-  bool FindPragma(Thread* T,
-                  const Object& object,
-                  const String& pragma_name,
-                  Object* options) const;
+  static bool FindPragma(Thread* T,
+                         bool only_core,
+                         const Object& object,
+                         const String& pragma_name,
+                         Object* options);
 
   RawClass* toplevel_class() const { return raw_ptr()->toplevel_class_; }
   void set_toplevel_class(const Class& value) const;
@@ -3998,6 +4036,8 @@
   // Eagerly compile all classes and functions in the library.
   static RawError* CompileAll(bool ignore_error = false);
 #if !defined(DART_PRECOMPILED_RUNTIME)
+  // Finalize all classes in all libraries.
+  static RawError* FinalizeAllClasses();
   // Eagerly read all bytecode.
   static RawError* ReadAllBytecode();
 #endif
@@ -4009,8 +4049,13 @@
 #endif  // defined(DART_NO_SNAPSHOT).
 
   static bool IsPrivate(const String& name);
+
   // Construct the full name of a corelib member.
   static const String& PrivateCoreLibName(const String& member);
+
+  // Returns true if [name] matches full name of corelib [member].
+  static bool IsPrivateCoreLibName(const String& name, const String& member);
+
   // Lookup class in the core lib which also contains various VM
   // helper methods and classes. Allow look up of private classes.
   static RawClass* LookupCoreClass(const String& class_name);
@@ -4260,6 +4305,14 @@
            sizeof(RawObjectPool::Entry) * index;
   }
 
+  struct ArrayLayout {
+    static intptr_t elements_start_offset() {
+      return ObjectPool::data_offset();
+    }
+
+    static constexpr intptr_t kElementSize = sizeof(RawObjectPool::Entry);
+  };
+
   EntryType TypeAt(intptr_t index) const {
     return TypeBits::decode(raw_ptr()->entry_bits()[index]);
   }
@@ -4398,8 +4451,8 @@
   static const intptr_t kPolymorphicEntryOffset = 0;
   static const intptr_t kMonomorphicEntryOffset = 0;
 #elif defined(TARGET_ARCH_X64)
-  static const intptr_t kPolymorphicEntryOffset = 16;
-  static const intptr_t kMonomorphicEntryOffset = 36;
+  static const intptr_t kPolymorphicEntryOffset = 8;
+  static const intptr_t kMonomorphicEntryOffset = 32;
 #elif defined(TARGET_ARCH_ARM)
   static const intptr_t kPolymorphicEntryOffset = 0;
   static const intptr_t kMonomorphicEntryOffset = 20;
@@ -4967,7 +5020,7 @@
     return ContainsInstructionAt(raw(), addr);
   }
 
-  static bool ContainsInstructionAt(RawCode* code, uword addr) {
+  static bool ContainsInstructionAt(const RawCode* code, uword addr) {
     return Instructions::ContainsPc(code->ptr()->instructions_, addr);
   }
 
@@ -5167,7 +5220,7 @@
 #endif
   }
 
-  // Will compute local var descriptors is necessary.
+  // Will compute local var descriptors if necessary.
   RawLocalVarDescriptors* GetLocalVarDescriptors() const;
 
   RawExceptionHandlers* exception_handlers() const {
@@ -5191,6 +5244,8 @@
     StorePointer(&raw_ptr()->owner_, owner.raw());
   }
 
+  static intptr_t owner_offset() { return OFFSET_OF(RawCode, owner_); }
+
   // We would have a VisitPointers function here to traverse all the
   // embedded objects in the instructions using pointer_offsets.
 
@@ -5438,6 +5493,7 @@
   RawExternalTypedData* GetBinary(Zone* zone) const;
 
   TokenPosition GetTokenIndexOfPC(uword pc) const;
+  intptr_t GetTryIndexAtPc(uword return_address) const;
 
   intptr_t instructions_binary_offset() const {
     return raw_ptr()->instructions_binary_offset_;
@@ -5456,6 +5512,38 @@
     return (source_positions_binary_offset() != 0);
   }
 
+#if !defined(PRODUCT)
+  intptr_t local_variables_binary_offset() const {
+    return raw_ptr()->local_variables_binary_offset_;
+  }
+  void set_local_variables_binary_offset(intptr_t value) const {
+    StoreNonPointer(&raw_ptr()->local_variables_binary_offset_, value);
+  }
+  bool HasLocalVariablesInfo() const {
+    return (local_variables_binary_offset() != 0);
+  }
+#endif  // !defined(PRODUCT)
+
+  RawLocalVarDescriptors* var_descriptors() const {
+#if defined(PRODUCT)
+    UNREACHABLE();
+    return nullptr;
+#else
+    return raw_ptr()->var_descriptors_;
+#endif
+  }
+  void set_var_descriptors(const LocalVarDescriptors& value) const {
+#if defined(PRODUCT)
+    UNREACHABLE();
+#else
+    ASSERT(value.IsOld());
+    StorePointer(&raw_ptr()->var_descriptors_, value.raw());
+#endif
+  }
+
+  // Will compute local var descriptors if necessary.
+  RawLocalVarDescriptors* GetLocalVarDescriptors() const;
+
   const char* Name() const;
   const char* QualifiedName() const;
 
@@ -5477,8 +5565,6 @@
 
  private:
   void set_instructions(uword instructions) const {
-    // The interpreter requires the instructions to be aligned.
-    ASSERT(Utils::IsAligned(instructions, sizeof(uint32_t)));
     StoreNonPointer(&raw_ptr()->instructions_, instructions);
   }
   void set_instructions_size(intptr_t size) const {
@@ -5528,13 +5614,17 @@
            (kWordSize * context_index);
   }
 
+  static bool IsValidLength(intptr_t len) {
+    return 0 <= len && len <= compiler::target::Array::kMaxElements;
+  }
+
   static intptr_t InstanceSize() {
     ASSERT(sizeof(RawContext) == OFFSET_OF_RETURNED_VALUE(RawContext, data));
     return 0;
   }
 
   static intptr_t InstanceSize(intptr_t len) {
-    ASSERT(0 <= len && len <= kMaxElements);
+    ASSERT(IsValidLength(len));
     return RoundedAllocationSize(sizeof(RawContext) + (len * kBytesPerElement));
   }
 
@@ -6170,6 +6260,14 @@
   }
   void SetTypeAt(intptr_t index, const AbstractType& value) const;
 
+  struct ArrayLayout {
+    static intptr_t elements_start_offset() {
+      return TypeArguments::type_at_offset(0);
+    }
+
+    static constexpr intptr_t kElementSize = kWordSize;
+  };
+
   // The name of this type argument vector, e.g. "<T, dynamic, List<T>, Smi>".
   RawString* Name() const { return SubvectorName(0, Length(), kInternalName); }
 
@@ -7447,8 +7545,6 @@
   friend class TwoByteString;
   friend class ExternalOneByteString;
   friend class ExternalTwoByteString;
-  // So that SkippedCodeFunctions can print a debug string from a NoHandleScope.
-  friend class SkippedCodeFunctions;
   friend class RawOneByteString;
   friend class RODataSerializationCluster;  // SetHash
 };
@@ -7953,6 +8049,12 @@
     return OFFSET_OF_RETURNED_VALUE(RawArray, data) + kWordSize * index;
   }
 
+  struct ArrayLayout {
+    static intptr_t elements_start_offset() { return Array::data_offset(); }
+
+    static constexpr intptr_t kElementSize = kWordSize;
+  };
+
   static bool Equals(RawArray* a, RawArray* b) {
     if (a == b) return true;
     if (a->IsRawNull() || b->IsRawNull()) return false;
@@ -8009,6 +8111,10 @@
     return OFFSET_OF(RawArray, type_arguments_);
   }
 
+  static bool IsValidLength(intptr_t len) {
+    return 0 <= len && len <= kMaxElements;
+  }
+
   static intptr_t InstanceSize() {
     ASSERT(sizeof(RawArray) == OFFSET_OF_RETURNED_VALUE(RawArray, data));
     return 0;
@@ -8017,7 +8123,7 @@
   static intptr_t InstanceSize(intptr_t len) {
     // Ensure that variable length data is not adding to the object length.
     ASSERT(sizeof(RawArray) == (sizeof(RawInstance) + (2 * kWordSize)));
-    ASSERT(0 <= len && len <= kMaxElements);
+    ASSERT(IsValidLength(len));
     return RoundedAllocationSize(sizeof(RawArray) + (len * kBytesPerElement));
   }
 
@@ -8228,6 +8334,14 @@
   static RawGrowableObjectArray* New(const Array& array,
                                      Heap::Space space = Heap::kNew);
 
+  static RawSmi* NoSafepointLength(const RawGrowableObjectArray* array) {
+    return array->ptr()->length_;
+  }
+
+  static RawArray* NoSafepointData(const RawGrowableObjectArray* array) {
+    return array->ptr()->data_;
+  }
+
  private:
   RawArray* DataArray() const { return data()->ptr(); }
   RawObject** ObjectAddr(intptr_t index) const {
@@ -8389,12 +8503,22 @@
     }
   }
 
+  void* DataAddr(intptr_t byte_offset) const {
+    ASSERT((byte_offset == 0) ||
+           ((byte_offset > 0) && (byte_offset < LengthInBytes())));
+    return reinterpret_cast<void*>(Validate(raw_ptr()->data_) + byte_offset);
+  }
+
  protected:
   void SetLength(intptr_t value) const {
     ASSERT(value <= Smi::kMaxValue);
     StoreSmi(&raw_ptr()->length_, Smi::New(value));
   }
 
+  virtual uint8_t* Validate(uint8_t* data) const {
+    return UnsafeMutableNonPointer(data);
+  }
+
  private:
   friend class Class;
 
@@ -8418,13 +8542,6 @@
   // architecture.
   static const intptr_t kHashBits = 30;
 
-  void* DataAddr(intptr_t byte_offset) const {
-    ASSERT((byte_offset == 0) ||
-           ((byte_offset > 0) && (byte_offset < LengthInBytes())));
-    return reinterpret_cast<void*>(UnsafeMutableNonPointer(raw_ptr()->data()) +
-                                   byte_offset);
-  }
-
   virtual bool CanonicalizeEquals(const Instance& other) const;
   virtual uint32_t CanonicalizeHash() const;
 
@@ -8565,12 +8682,6 @@
   // snapshot. Should be independent of word size.
   static const int kDataSerializationAlignment = 8;
 
-  void* DataAddr(intptr_t byte_offset) const {
-    ASSERT((byte_offset == 0) ||
-           ((byte_offset > 0) && (byte_offset < LengthInBytes())));
-    return reinterpret_cast<void*>(raw_ptr()->data_ + byte_offset);
-  }
-
 #define TYPED_GETTER_SETTER(name, type)                                        \
   type Get##name(intptr_t byte_offset) const {                                 \
     return ReadUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset)));      \
@@ -8624,6 +8735,8 @@
   }
 
  protected:
+  virtual uint8_t* Validate(uint8_t* data) const { return data; }
+
   void SetLength(intptr_t value) const {
     ASSERT(value <= Smi::kMaxValue);
     StoreSmi(&raw_ptr()->length_, Smi::New(value));
@@ -8696,6 +8809,9 @@
 
   RawSmi* offset_in_bytes() const { return raw_ptr()->offset_in_bytes_; }
 
+ protected:
+  virtual uint8_t* Validate(uint8_t* data) const { return data; }
+
  private:
   void RecomputeDataField() { raw()->RecomputeDataField(); }
 
@@ -9062,6 +9178,50 @@
   friend class Class;
 };
 
+// This is allocated when new instance of TransferableTypedData is created in
+// [TransferableTypedData::New].
+class TransferableTypedDataPeer {
+ public:
+  // [data] backing store should be malloc'ed, not new'ed.
+  TransferableTypedDataPeer(uint8_t* data, intptr_t length)
+      : data_(data), length_(length), handle_(nullptr) {}
+
+  ~TransferableTypedDataPeer() { free(data_); }
+
+  uint8_t* data() const { return data_; }
+  intptr_t length() const { return length_; }
+  FinalizablePersistentHandle* handle() const { return handle_; }
+  void set_handle(FinalizablePersistentHandle* handle) { handle_ = handle; }
+
+  void ClearData() {
+    data_ = nullptr;
+    length_ = 0;
+    handle_ = nullptr;
+  }
+
+ private:
+  uint8_t* data_;
+  intptr_t length_;
+  FinalizablePersistentHandle* handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(TransferableTypedDataPeer);
+};
+
+class TransferableTypedData : public Instance {
+ public:
+  static RawTransferableTypedData* New(uint8_t* data,
+                                       intptr_t len,
+                                       Heap::Space space = Heap::kNew);
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawTransferableTypedData));
+  }
+
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(TransferableTypedData, Instance);
+  friend class Class;
+};
+
 // Internal stacktrace object used in exceptions for printing stack traces.
 class StackTrace : public Instance {
  public:
@@ -9106,6 +9266,55 @@
   friend class Debugger;
 };
 
+class RegExpFlags {
+ public:
+  // Flags are passed to a regex object as follows:
+  // 'i': ignore case, 'g': do global matches, 'm': pattern is multi line,
+  // 'u': pattern is full Unicode, not just BMP, 's': '.' in pattern matches
+  // all characters including line terminators.
+  enum Flags {
+    kNone = 0,
+    kGlobal = 1,
+    kIgnoreCase = 2,
+    kMultiLine = 4,
+    kUnicode = 8,
+    kDotAll = 16,
+  };
+
+  static const int kDefaultFlags = 0;
+
+  RegExpFlags() : value_(kDefaultFlags) {}
+  explicit RegExpFlags(int value) : value_(value) {}
+
+  inline bool IsGlobal() const { return (value_ & kGlobal) != 0; }
+  inline bool IgnoreCase() const { return (value_ & kIgnoreCase) != 0; }
+  inline bool IsMultiLine() const { return (value_ & kMultiLine) != 0; }
+  inline bool IsUnicode() const { return (value_ & kUnicode) != 0; }
+  inline bool IsDotAll() const { return (value_ & kDotAll) != 0; }
+
+  inline bool NeedsUnicodeCaseEquivalents() {
+    // Both unicode and ignore_case flags are set. We need to use ICU to find
+    // the closure over case equivalents.
+    return IsUnicode() && IgnoreCase();
+  }
+
+  void SetGlobal() { value_ |= kGlobal; }
+  void SetIgnoreCase() { value_ |= kIgnoreCase; }
+  void SetMultiLine() { value_ |= kMultiLine; }
+  void SetUnicode() { value_ |= kUnicode; }
+  void SetDotAll() { value_ |= kDotAll; }
+
+  const char* ToCString() const;
+
+  int value() const { return value_; }
+
+  bool operator==(const RegExpFlags& other) { return value_ == other.value_; }
+  bool operator!=(const RegExpFlags& other) { return value_ != other.value_; }
+
+ private:
+  int value_;
+};
+
 // Internal JavaScript regular expression object.
 class RegExp : public Instance {
  public:
@@ -9119,20 +9328,11 @@
     kComplex = 2,
   };
 
-  // Flags are passed to a regex object as follows:
-  // 'i': ignore case, 'g': do global matches, 'm': pattern is multi line.
-  enum Flags {
-    kNone = 0,
-    kGlobal = 1,
-    kIgnoreCase = 2,
-    kMultiLine = 4,
-  };
-
   enum {
     kTypePos = 0,
     kTypeSize = 2,
     kFlagsPos = 2,
-    kFlagsSize = 4,
+    kFlagsSize = 5,
   };
 
   class TypeBits : public BitField<int8_t, RegExType, kTypePos, kTypeSize> {};
@@ -9142,11 +9342,10 @@
   bool is_simple() const { return (type() == kSimple); }
   bool is_complex() const { return (type() == kComplex); }
 
-  bool is_global() const { return (flags() & kGlobal); }
-  bool is_ignore_case() const { return (flags() & kIgnoreCase); }
-  bool is_multi_line() const { return (flags() & kMultiLine); }
-
-  intptr_t num_registers() const { return raw_ptr()->num_registers_; }
+  intptr_t num_registers(bool is_one_byte) const {
+    return is_one_byte ? raw_ptr()->num_one_byte_registers_
+                       : raw_ptr()->num_two_byte_registers_;
+  }
 
   RawString* pattern() const { return raw_ptr()->pattern_; }
   RawSmi* num_bracket_expressions() const {
@@ -9210,15 +9409,48 @@
 
   void set_num_bracket_expressions(intptr_t value) const;
   void set_capture_name_map(const Array& array) const;
-  void set_is_global() const { set_flags(flags() | kGlobal); }
-  void set_is_ignore_case() const { set_flags(flags() | kIgnoreCase); }
-  void set_is_multi_line() const { set_flags(flags() | kMultiLine); }
+  void set_is_global() const {
+    RegExpFlags f = flags();
+    f.SetGlobal();
+    set_flags(f);
+  }
+  void set_is_ignore_case() const {
+    RegExpFlags f = flags();
+    f.SetIgnoreCase();
+    set_flags(f);
+  }
+  void set_is_multi_line() const {
+    RegExpFlags f = flags();
+    f.SetMultiLine();
+    set_flags(f);
+  }
+  void set_is_unicode() const {
+    RegExpFlags f = flags();
+    f.SetUnicode();
+    set_flags(f);
+  }
+  void set_is_dot_all() const {
+    RegExpFlags f = flags();
+    f.SetDotAll();
+    set_flags(f);
+  }
   void set_is_simple() const { set_type(kSimple); }
   void set_is_complex() const { set_type(kComplex); }
-  void set_num_registers(intptr_t value) const {
-    StoreNonPointer(&raw_ptr()->num_registers_, value);
+  void set_num_registers(bool is_one_byte, intptr_t value) const {
+    if (is_one_byte) {
+      StoreNonPointer(&raw_ptr()->num_one_byte_registers_, value);
+    } else {
+      StoreNonPointer(&raw_ptr()->num_two_byte_registers_, value);
+    }
   }
 
+  RegExpFlags flags() const {
+    return RegExpFlags(FlagsBits::decode(raw_ptr()->type_flags_));
+  }
+  void set_flags(RegExpFlags flags) const {
+    StoreNonPointer(&raw_ptr()->type_flags_,
+                    FlagsBits::update(flags.value(), raw_ptr()->type_flags_));
+  }
   const char* Flags() const;
 
   virtual bool CanonicalizeEquals(const Instance& other) const;
@@ -9234,13 +9466,8 @@
     StoreNonPointer(&raw_ptr()->type_flags_,
                     TypeBits::update(type, raw_ptr()->type_flags_));
   }
-  void set_flags(intptr_t value) const {
-    StoreNonPointer(&raw_ptr()->type_flags_,
-                    FlagsBits::update(value, raw_ptr()->type_flags_));
-  }
 
   RegExType type() const { return TypeBits::decode(raw_ptr()->type_flags_); }
-  intptr_t flags() const { return FlagsBits::decode(raw_ptr()->type_flags_); }
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(RegExp, Instance);
   friend class Class;
@@ -9386,6 +9613,16 @@
 #endif
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+bool Function::HasBytecode() const {
+  return raw_ptr()->bytecode_ != Bytecode::null();
+}
+
+bool Function::HasBytecode(RawFunction* function) {
+  return function->ptr()->bytecode_ != Bytecode::null();
+}
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
 intptr_t Field::Offset() const {
   ASSERT(is_instance());  // Valid only for dart instance fields.
   intptr_t value = Smi::Value(raw_ptr()->value_.offset_);
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 31eb620..f9eb462 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -763,7 +763,7 @@
     } else {
       // Super call.
       Function& caller = Function::Handle(zone);
-      caller ^= Owner();
+      caller = Owner();
       ASSERT(!caller.is_static());
       Class& cls = Class::Handle(zone, caller.Owner());
       cls = cls.SuperClass();
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index e0d65f9..3616d4e 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -273,7 +273,7 @@
   Class& cls = Class::Handle(Owner());
   if (!cls.IsNull()) {
     Error& err = Error::Handle();
-    err ^= cls.EnsureIsFinalized(Thread::Current());
+    err = cls.EnsureIsFinalized(Thread::Current());
     ASSERT(err.IsNull());
   } else {
     ASSERT(IsSignatureFunction());
@@ -332,7 +332,7 @@
                     static_cast<intptr_t>(deoptimization_counter()));
   if ((kind() == RawFunction::kImplicitGetter) ||
       (kind() == RawFunction::kImplicitSetter) ||
-      (kind() == RawFunction::kImplicitStaticFinalGetter) ||
+      (kind() == RawFunction::kImplicitStaticGetter) ||
       (kind() == RawFunction::kStaticFieldInitializer)) {
     const Field& field = Field::Handle(accessor_field());
     if (!field.IsNull()) {
@@ -394,7 +394,7 @@
   } else {
     ClassTable* table = Isolate::Current()->class_table();
     ASSERT(table->IsValidIndex(guarded_cid()));
-    cls ^= table->At(guarded_cid());
+    cls = table->At(guarded_cid());
     jsobj.AddProperty("_guardClass", cls);
   }
   if (guarded_list_length() == kUnknownFixedLength) {
@@ -785,7 +785,7 @@
     intptr_t count = GetCountAt(i);
     if (!is_static_call()) {
       intptr_t cid = GetReceiverClassIdAt(i);
-      cls ^= isolate->class_table()->At(cid);
+      cls = isolate->class_table()->At(cid);
       cache_entry.AddProperty("receiver", cls);
     }
     cache_entry.AddProperty("target", func);
@@ -1455,6 +1455,10 @@
   Instance::PrintJSONImpl(stream, ref);
 }
 
+void TransferableTypedData::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  Instance::PrintJSONImpl(stream, ref);
+}
+
 void ClosureData::PrintJSONImpl(JSONStream* stream, bool ref) const {
   Object::PrintJSONImpl(stream, ref);
 }
@@ -1487,8 +1491,8 @@
     return;
   }
 
-  jsobj.AddProperty("isCaseSensitive", !is_ignore_case());
-  jsobj.AddProperty("isMultiLine", is_multi_line());
+  jsobj.AddProperty("isCaseSensitive", !flags().IgnoreCase());
+  jsobj.AddProperty("isMultiLine", flags().IsMultiLine());
 
   if (!FLAG_interpret_irregexp) {
     Function& func = Function::Handle();
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 2d080e3..47c461e 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -157,35 +157,31 @@
 
   String& function_name = String::Handle(zone);
   Function& function = Function::Handle(zone);
-  function_name ^= async_lib.PrivateName(Symbols::SetAsyncThreadStackTrace());
+  function_name = async_lib.PrivateName(Symbols::SetAsyncThreadStackTrace());
   ASSERT(!function_name.IsNull());
-  function ^=
-      Resolver::ResolveStatic(async_lib, Object::null_string(), function_name,
-                              0, 1, Object::null_array());
+  function = Resolver::ResolveStatic(async_lib, Object::null_string(),
+                                     function_name, 0, 1, Object::null_array());
   ASSERT(!function.IsNull());
   set_async_set_thread_stack_trace(function);
 
-  function_name ^= async_lib.PrivateName(Symbols::ClearAsyncThreadStackTrace());
+  function_name = async_lib.PrivateName(Symbols::ClearAsyncThreadStackTrace());
   ASSERT(!function_name.IsNull());
-  function ^=
-      Resolver::ResolveStatic(async_lib, Object::null_string(), function_name,
-                              0, 0, Object::null_array());
+  function = Resolver::ResolveStatic(async_lib, Object::null_string(),
+                                     function_name, 0, 0, Object::null_array());
   ASSERT(!function.IsNull());
   set_async_clear_thread_stack_trace(function);
 
-  function_name ^= async_lib.PrivateName(Symbols::AsyncStarMoveNextHelper());
+  function_name = async_lib.PrivateName(Symbols::AsyncStarMoveNextHelper());
   ASSERT(!function_name.IsNull());
-  function ^=
-      Resolver::ResolveStatic(async_lib, Object::null_string(), function_name,
-                              0, 1, Object::null_array());
+  function = Resolver::ResolveStatic(async_lib, Object::null_string(),
+                                     function_name, 0, 1, Object::null_array());
   ASSERT(!function.IsNull());
   set_async_star_move_next_helper(function);
 
-  function_name ^= async_lib.PrivateName(Symbols::_CompleteOnAsyncReturn());
+  function_name = async_lib.PrivateName(Symbols::_CompleteOnAsyncReturn());
   ASSERT(!function_name.IsNull());
-  function ^=
-      Resolver::ResolveStatic(async_lib, Object::null_string(), function_name,
-                              0, 2, Object::null_array());
+  function = Resolver::ResolveStatic(async_lib, Object::null_string(),
+                                     function_name, 0, 2, Object::null_array());
   ASSERT(!function.IsNull());
   set_complete_on_async_return(function);
   if (FLAG_async_debugger) {
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 4664ee7..0921cc8 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -31,6 +31,7 @@
   const Class& cls = Class::Handle(Class::New(
       Library::Handle(), class_name, script, TokenPosition::kNoSource));
   cls.set_is_synthesized_class();  // Dummy class for testing.
+  cls.set_is_declaration_loaded();
   return cls.raw();
 }
 
@@ -2488,7 +2489,7 @@
 
 // Test for immutability of generated instructions. The test crashes with a
 // segmentation fault when writing into it.
-ISOLATE_UNIT_TEST_CASE(CodeImmutability) {
+ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(CodeImmutability, "Crash") {
   bool stack_trace_collection_enabled =
       MallocHooks::stack_trace_collection_enabled();
   MallocHooks::set_stack_trace_collection_enabled(false);
@@ -2525,7 +2526,7 @@
 
 // Test for executability of generated instructions. The test crashes with a
 // segmentation fault when executing the writeable view.
-ISOLATE_UNIT_TEST_CASE(CodeExecutability) {
+ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(CodeExecutability, "Crash") {
   bool stack_trace_collection_enabled =
       MallocHooks::stack_trace_collection_enabled();
   MallocHooks::set_stack_trace_collection_enabled(false);
@@ -3113,7 +3114,7 @@
       !String::EqualsIgnoringPrivateKey(ext_mangled_name, ext_bad_bare_name));
 }
 
-ISOLATE_UNIT_TEST_CASE(ArrayNew_Overflow_Crash) {
+ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(ArrayNew_Overflow_Crash, "Crash") {
   Array::Handle(Array::New(Array::kMaxElements + 1));
 }
 
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index df94ba9..869c5b2 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -8,7 +8,9 @@
 #include "vm/os.h"
 
 #include <errno.h>
+#if !defined(FUCHSIA_SDK)
 #include <fuchsia/timezone/cpp/fidl.h>
+#endif  //  !defined(FUCHSIA_SDK)
 #include <lib/sys/cpp/service_directory.h>
 #include <zircon/process.h>
 #include <zircon/syscalls.h>
@@ -37,6 +39,7 @@
   return static_cast<intptr_t>(getpid());
 }
 
+#if !defined(FUCHSIA_SDK)
 // TODO(FL-98): Change this to talk to fuchsia.dart to get timezone service to
 // directly get timezone.
 //
@@ -44,10 +47,12 @@
 // component:ConnectToEnvironmentServices and this is the only thing that is
 // blocking it and FL-98 will take time.
 static fuchsia::timezone::TimezoneSyncPtr tz;
+#endif  //  !defined(FUCHSIA_SDK)
 
 static zx_status_t GetLocalAndDstOffsetInSeconds(int64_t seconds_since_epoch,
                                                  int32_t* local_offset,
                                                  int32_t* dst_offset) {
+#if !defined(FUCHSIA_SDK)
   zx_status_t status = tz->GetTimezoneOffsetMinutes(seconds_since_epoch * 1000,
                                                     local_offset, dst_offset);
   if (status != ZX_OK) {
@@ -56,9 +61,13 @@
   *local_offset *= 60;
   *dst_offset *= 60;
   return ZX_OK;
+#else
+  return ZX_ERR_NOT_SUPPORTED;
+#endif  //  !defined(FUCHSIA_SDK)
 }
 
 const char* OS::GetTimeZoneName(int64_t seconds_since_epoch) {
+#if !defined(FUCHSIA_SDK)
   // TODO(abarth): Handle time zone changes.
   static const auto* tz_name = new std::string([] {
     std::string result;
@@ -66,6 +75,9 @@
     return result;
   }());
   return tz_name->c_str();
+#else
+  return "";
+#endif  //  !defined(FUCHSIA_SDK)}
 }
 
 int OS::GetTimeZoneOffsetInSeconds(int64_t seconds_since_epoch) {
@@ -77,8 +89,10 @@
 
 int OS::GetLocalTimeZoneAdjustmentInSeconds() {
   int32_t local_offset, dst_offset;
+  zx_time_t now = 0;
+  zx_clock_get_new(ZX_CLOCK_UTC, &now);
   zx_status_t status = GetLocalAndDstOffsetInSeconds(
-      zx_clock_get(ZX_CLOCK_UTC) / ZX_SEC(1), &local_offset, &dst_offset);
+      now / ZX_SEC(1), &local_offset, &dst_offset);
   return status == ZX_OK ? local_offset : 0;
 }
 
@@ -87,11 +101,13 @@
 }
 
 int64_t OS::GetCurrentTimeMicros() {
-  return zx_clock_get(ZX_CLOCK_UTC) / kNanosecondsPerMicrosecond;
+  zx_time_t now = 0;
+  zx_clock_get_new(ZX_CLOCK_UTC, &now);
+  return now / kNanosecondsPerMicrosecond;
 }
 
 int64_t OS::GetCurrentMonotonicTicks() {
-  return zx_clock_get(ZX_CLOCK_MONOTONIC);
+  return zx_clock_get_monotonic();
 }
 
 int64_t OS::GetCurrentMonotonicFrequency() {
@@ -105,7 +121,9 @@
 }
 
 int64_t OS::GetCurrentThreadCPUMicros() {
-  return zx_clock_get(ZX_CLOCK_THREAD) / kNanosecondsPerMicrosecond;
+  zx_time_t now = 0;
+  zx_clock_get_new(ZX_CLOCK_THREAD, &now);
+  return now / kNanosecondsPerMicrosecond;
 }
 
 // TODO(5411554):  May need to hoist these architecture dependent code
@@ -252,8 +270,10 @@
 }
 
 void OS::Init() {
+#if !defined(FUCHSIA_SDK)
   auto services = sys::ServiceDirectory::CreateFromNamespace();
   services->Connect(tz.NewRequest());
+#endif  //  !defined(FUCHSIA_SDK)
 }
 
 void OS::Cleanup() {}
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index bc254e4..2ca3bb6 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -37,12 +37,14 @@
 DEFINE_FLAG(bool,
             generate_perf_events_symbols,
             false,
-            "Generate events symbols for profiling with perf");
+            "Generate events symbols for profiling with perf (disables dual "
+            "code mapping)");
 
 DEFINE_FLAG(bool,
             generate_perf_jitdump,
             false,
-            "Generate jitdump file to use with perf-inject");
+            "Generate jitdump file to use with perf-inject (disables dual code "
+            "mapping)");
 
 DECLARE_FLAG(bool, write_protect_code);
 DECLARE_FLAG(bool, write_protect_vm_isolate);
diff --git a/runtime/vm/os_test.cc b/runtime/vm/os_test.cc
index 07b3cd9..406edf6 100644
--- a/runtime/vm/os_test.cc
+++ b/runtime/vm/os_test.cc
@@ -27,7 +27,7 @@
 }
 
 // This test is expected to crash when it runs.
-VM_UNIT_TEST_CASE(SNPrint_BadArgs) {
+VM_UNIT_TEST_CASE_WITH_EXPECTATION(SNPrint_BadArgs, "Crash") {
   int width = kMaxInt32;
   int num = 7;
   Utils::SNPrint(NULL, 0, "%*d%*d", width, num, width, num);
diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc
index 2cfe8fb..e3e9ddf 100644
--- a/runtime/vm/os_thread.cc
+++ b/runtime/vm/os_thread.cc
@@ -33,7 +33,7 @@
       trace_id_(OSThread::GetCurrentThreadTraceId()),
 #endif
       name_(NULL),
-      timeline_block_lock_(new Mutex()),
+      timeline_block_lock_(),
       timeline_block_(NULL),
       thread_list_next_(NULL),
       thread_interrupt_disabled_(1),  // Thread interrupts disabled by default.
@@ -85,7 +85,6 @@
   }
 #endif
   timeline_block_ = NULL;
-  delete timeline_block_lock_;
   free(name_);
 }
 
diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h
index 9a95345..7d27cc8 100644
--- a/runtime/vm/os_thread.h
+++ b/runtime/vm/os_thread.h
@@ -38,6 +38,35 @@
 class ThreadState;
 class TimelineEventBlock;
 
+class Mutex {
+ public:
+  explicit Mutex(NOT_IN_PRODUCT(const char* name = "anonymous mutex"));
+  ~Mutex();
+
+  bool IsOwnedByCurrentThread() const;
+
+ private:
+  void Lock();
+  bool TryLock();  // Returns false if lock is busy and locking failed.
+  void Unlock();
+
+  MutexData data_;
+  NOT_IN_PRODUCT(const char* name_);
+#if defined(DEBUG)
+  ThreadId owner_;
+#endif  // defined(DEBUG)
+
+  friend class MallocLocker;
+  friend class MutexLocker;
+  friend class SafepointMutexLocker;
+  friend class OSThreadIterator;
+  friend class TimelineEventBlockIterator;
+  friend class TimelineEventRecorder;
+  friend class PageSpace;
+  friend void Dart_TestMutex();
+  DISALLOW_COPY_AND_ASSIGN(Mutex);
+};
+
 class BaseThread {
  public:
   bool is_os_thread() const { return is_os_thread_; }
@@ -86,7 +115,7 @@
     name_ = strdup(name);
   }
 
-  Mutex* timeline_block_lock() const { return timeline_block_lock_; }
+  Mutex* timeline_block_lock() const { return &timeline_block_lock_; }
 
   // Only safe to access when holding |timeline_block_lock_|.
   TimelineEventBlock* timeline_block() const { return timeline_block_; }
@@ -259,7 +288,7 @@
 #endif
   char* name_;  // A name for this thread.
 
-  Mutex* timeline_block_lock_;
+  mutable Mutex timeline_block_lock_;
   TimelineEventBlock* timeline_block_;
 
   // All |Thread|s are registered in the thread list.
@@ -308,44 +337,6 @@
   OSThread* next_;
 };
 
-class Mutex {
- public:
-  explicit Mutex(NOT_IN_PRODUCT(const char* name = "anonymous mutex"));
-  ~Mutex();
-
-#if defined(DEBUG)
-  bool IsOwnedByCurrentThread() const {
-    return owner_ == OSThread::GetCurrentThreadId();
-  }
-#else
-  bool IsOwnedByCurrentThread() const {
-    UNREACHABLE();
-    return false;
-  }
-#endif
-
- private:
-  void Lock();
-  bool TryLock();  // Returns false if lock is busy and locking failed.
-  void Unlock();
-
-  MutexData data_;
-  NOT_IN_PRODUCT(const char* name_);
-#if defined(DEBUG)
-  ThreadId owner_;
-#endif  // defined(DEBUG)
-
-  friend class MallocLocker;
-  friend class MutexLocker;
-  friend class SafepointMutexLocker;
-  friend class OSThreadIterator;
-  friend class TimelineEventBlockIterator;
-  friend class TimelineEventRecorder;
-  friend class PageSpace;
-  friend void Dart_TestMutex();
-  DISALLOW_COPY_AND_ASSIGN(Mutex);
-};
-
 class Monitor {
  public:
   enum WaitResult { kNotified, kTimedOut };
@@ -390,6 +381,15 @@
   DISALLOW_COPY_AND_ASSIGN(Monitor);
 };
 
+inline bool Mutex::IsOwnedByCurrentThread() const {
+#if defined(DEBUG)
+  return owner_ == OSThread::GetCurrentThreadId();
+#else
+  UNREACHABLE();
+  return false;
+#endif
+}
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_OS_THREAD_H_
diff --git a/runtime/vm/os_thread_fuchsia.cc b/runtime/vm/os_thread_fuchsia.cc
index d6fd956..01b2fe7 100644
--- a/runtime/vm/os_thread_fuchsia.cc
+++ b/runtime/vm/os_thread_fuchsia.cc
@@ -55,7 +55,7 @@
 
 static void ComputeTimeSpecMicros(struct timespec* ts, int64_t micros) {
   // time in nanoseconds.
-  zx_time_t now = zx_clock_get(ZX_CLOCK_MONOTONIC);
+  zx_time_t now = zx_clock_get_monotonic();
   zx_time_t target = now + (micros * kNanosecondsPerMicrosecond);
   int64_t secs = target / kNanosecondsPerSecond;
   int64_t nanos = target - (secs * kNanosecondsPerSecond);
diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc
index eecfe67..a0d050e 100644
--- a/runtime/vm/os_thread_macos.cc
+++ b/runtime/vm/os_thread_macos.cc
@@ -14,6 +14,7 @@
 #include <mach/task_info.h>    // NOLINT
 #include <mach/thread_act.h>   // NOLINT
 #include <mach/thread_info.h>  // NOLINT
+#include <signal.h>            // NOLINT
 #include <sys/errno.h>         // NOLINT
 #include <sys/sysctl.h>        // NOLINT
 #include <sys/types.h>         // NOLINT
@@ -21,6 +22,7 @@
 #include "platform/address_sanitizer.h"
 #include "platform/assert.h"
 #include "platform/safe_stack.h"
+#include "platform/signal_blocker.h"
 #include "platform/utils.h"
 
 namespace dart {
@@ -105,7 +107,6 @@
   if (thread != NULL) {
     OSThread::SetCurrent(thread);
     thread->set_name(name);
-
     // Call the supplied thread start function handing it its parameters.
     function(parameter);
   }
diff --git a/runtime/vm/port.cc b/runtime/vm/port.cc
index a057379..4ad4340 100644
--- a/runtime/vm/port.cc
+++ b/runtime/vm/port.cc
@@ -236,11 +236,11 @@
   handler->CloseAllPorts();
 }
 
-bool PortMap::PostMessage(Message* message) {
+bool PortMap::PostMessage(std::unique_ptr<Message> message,
+                          bool before_events) {
   MutexLocker ml(mutex_);
   intptr_t index = FindPort(message->dest_port());
   if (index < 0) {
-    delete message;
     return false;
   }
   ASSERT(index >= 0);
@@ -248,7 +248,7 @@
   MessageHandler* handler = map_[index].handler;
   ASSERT(map_[index].port != 0);
   ASSERT((handler != NULL) && (handler != deleted_entry_));
-  handler->PostMessage(message);
+  handler->PostMessage(std::move(message), before_events);
   return true;
 }
 
diff --git a/runtime/vm/port.h b/runtime/vm/port.h
index d307e43..155e3832 100644
--- a/runtime/vm/port.h
+++ b/runtime/vm/port.h
@@ -5,6 +5,8 @@
 #ifndef RUNTIME_VM_PORT_H_
 #define RUNTIME_VM_PORT_H_
 
+#include <memory>
+
 #include "include/dart_api.h"
 #include "vm/allocation.h"
 #include "vm/globals.h"
@@ -46,7 +48,8 @@
   // active any longer.
   //
   // Claims ownership of 'message'.
-  static bool PostMessage(Message* message);
+  static bool PostMessage(std::unique_ptr<Message> message,
+                          bool before_events = false);
 
   // Returns whether a port is local to the current isolate.
   static bool IsLocalPort(Dart_Port id);
diff --git a/runtime/vm/port_test.cc b/runtime/vm/port_test.cc
index ac65fd9..6526471 100644
--- a/runtime/vm/port_test.cc
+++ b/runtime/vm/port_test.cc
@@ -35,7 +35,7 @@
 
   void MessageNotify(Message::Priority priority) { notify_count++; }
 
-  MessageStatus HandleMessage(Message* message) { return kOK; }
+  MessageStatus HandleMessage(std::unique_ptr<Message> message) { return kOK; }
 
   int notify_count;
 };
@@ -133,8 +133,8 @@
   intptr_t message_len = strlen(message) + 1;
 
   EXPECT(PortMap::PostMessage(
-      new Message(port, reinterpret_cast<uint8_t*>(strdup(message)),
-                  message_len, NULL, Message::kNormalPriority)));
+      Message::New(port, reinterpret_cast<uint8_t*>(strdup(message)),
+                   message_len, nullptr, Message::kNormalPriority)));
 
   // Check that the message notify callback was called.
   EXPECT_EQ(1, handler.notify_count);
@@ -147,7 +147,7 @@
   EXPECT_EQ(0, handler.notify_count);
 
   EXPECT(PortMap::PostMessage(
-      new Message(port, Smi::New(42), Message::kNormalPriority)));
+      Message::New(port, Smi::New(42), Message::kNormalPriority)));
 
   // Check that the message notify callback was called.
   EXPECT_EQ(1, handler.notify_count);
@@ -160,7 +160,7 @@
   EXPECT_EQ(0, handler.notify_count);
 
   EXPECT(PortMap::PostMessage(
-      new Message(port, Object::null(), Message::kNormalPriority)));
+      Message::New(port, Object::null(), Message::kNormalPriority)));
 
   // Check that the message notify callback was called.
   EXPECT_EQ(1, handler.notify_count);
@@ -177,8 +177,8 @@
   intptr_t message_len = strlen(message) + 1;
 
   EXPECT(!PortMap::PostMessage(
-      new Message(port, reinterpret_cast<uint8_t*>(strdup(message)),
-                  message_len, NULL, Message::kNormalPriority)));
+      Message::New(port, reinterpret_cast<uint8_t*>(strdup(message)),
+                   message_len, nullptr, Message::kNormalPriority)));
 }
 
 }  // namespace dart
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 7eed0f3..52cbcf5 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -166,14 +166,13 @@
 }
 
 AllocationSampleBuffer::AllocationSampleBuffer(intptr_t capacity)
-    : SampleBuffer(capacity), mutex_(new Mutex()), free_sample_list_(NULL) {}
+    : SampleBuffer(capacity), mutex_(), free_sample_list_(NULL) {}
 
 SampleBuffer::~SampleBuffer() {
   delete memory_;
 }
 
 AllocationSampleBuffer::~AllocationSampleBuffer() {
-  delete mutex_;
 }
 
 Sample* SampleBuffer::At(intptr_t idx) const {
@@ -208,7 +207,7 @@
 }
 
 void AllocationSampleBuffer::FreeAllocationSample(Sample* sample) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   while (sample != NULL) {
     intptr_t continuation_index = -1;
     if (sample->is_continuation_sample()) {
@@ -243,7 +242,7 @@
 }
 
 Sample* AllocationSampleBuffer::ReserveSampleAndLink(Sample* previous) {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   ASSERT(previous != NULL);
   intptr_t next_index = ReserveSampleSlotLocked();
   if (next_index < 0) {
@@ -262,7 +261,7 @@
 }
 
 Sample* AllocationSampleBuffer::ReserveSample() {
-  MutexLocker ml(mutex_);
+  MutexLocker ml(&mutex_);
   intptr_t index = ReserveSampleSlotLocked();
   if (index < 0) {
     return NULL;
@@ -791,7 +790,8 @@
         return;
       }
 
-      if ((pc + 1) < pc) {
+      const uword pc_value = reinterpret_cast<uword>(pc);
+      if ((pc_value + 1) < pc_value) {
         // It is not uncommon to encounter an invalid pc as we
         // traverse a stack frame.  Most of these we can tolerate.  If
         // the pc is so large that adding one to it will cause an
@@ -805,7 +805,7 @@
       // Move the lower bound up.
       lower_bound_ = reinterpret_cast<uword>(fp);
 
-      if (!Append(reinterpret_cast<uword>(pc), reinterpret_cast<uword>(fp))) {
+      if (!Append(pc_value, reinterpret_cast<uword>(fp))) {
         return;
       }
     }
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index d5122fc7d..f0280fc 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -655,7 +655,7 @@
   void FreeAllocationSample(Sample* sample);
 
  private:
-  Mutex* mutex_;
+  Mutex mutex_;
   Sample* free_sample_list_;
 
   DISALLOW_COPY_AND_ASSIGN(AllocationSampleBuffer);
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index a92e31e..97153de 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -133,6 +133,18 @@
   return func_name.ToCString();
 }
 
+const char* ProfileFunction::ResolvedScriptUrl() const {
+  if (function_.IsNull()) {
+    return NULL;
+  }
+  const Script& script = Script::Handle(function_.script());
+  const String& uri = String::Handle(script.resolved_url());
+  if (uri.IsNull()) {
+    return NULL;
+  }
+  return uri.ToCString();
+}
+
 bool ProfileFunction::is_visible() const {
   if (function_.IsNull()) {
     // Some synthetic function.
@@ -2231,6 +2243,7 @@
     }
 
     ASSERT(pc >= native_start);
+    ASSERT(pc < (pc + 1));  // Should not overflow.
     profile_code = new ProfileCode(ProfileCode::kNativeCode, native_start,
                                    pc + 1, 0, null_code_);
     if (native_name != NULL) {
@@ -2427,9 +2440,15 @@
     if (code_trie) {
       ProfileCode* code = GetCode(current->table_index());
       frame.AddProperty("name", code->name());
+      const char* resolved_script_url = NULL;
+      if (code->function() != NULL) {
+        resolved_script_url = code->function()->ResolvedScriptUrl();
+      }
+      frame.AddProperty("resolvedUrl", resolved_script_url);
     } else {
       ProfileFunction* func = GetFunction(current->table_index());
       frame.AddProperty("name", func->Name());
+      frame.AddProperty("resolvedUrl", func->ResolvedScriptUrl());
     }
     if ((parent != NULL) && (parent->frame_id() != kRootFrameId)) {
       ASSERT(parent->frame_id() != -1);
@@ -2467,19 +2486,6 @@
     for (intptr_t sample_index = 0; sample_index < samples_->length();
          sample_index++) {
       ProcessedSample* sample = samples_->At(sample_index);
-      JSONObject event(&events);
-      event.AddProperty("ph", "P");  // kind = sample event
-      // Add a blank name to keep about:tracing happy.
-      event.AddProperty("name", "");
-      event.AddProperty64("pid", pid);
-      event.AddProperty64("tid", OSThread::ThreadIdToIntPtr(sample->tid()));
-      event.AddPropertyTimeMicros("ts", sample->timestamp());
-      event.AddProperty("cat", "Dart");
-      if (!Isolate::IsVMInternalIsolate(isolate_)) {
-        JSONObject args(&event, "args");
-        args.AddProperty("mode", "basic");
-      }
-
       ProfileTrieNode* trie;
       if (code_trie) {
         trie = sample->timeline_code_trie();
@@ -2487,7 +2493,22 @@
         trie = sample->timeline_function_trie();
       }
       ASSERT(trie->frame_id() != -1);
-      event.AddPropertyF("sf", "%" Pd "-%" Pd, isolate_id, trie->frame_id());
+
+      if (trie->frame_id() != kRootFrameId) {
+        JSONObject event(&events);
+        event.AddProperty("ph", "P");  // kind = sample event
+        // Add a blank name to keep about:tracing happy.
+        event.AddProperty("name", "");
+        event.AddProperty64("pid", pid);
+        event.AddProperty64("tid", OSThread::ThreadIdToIntPtr(sample->tid()));
+        event.AddPropertyTimeMicros("ts", sample->timestamp());
+        event.AddProperty("cat", "Dart");
+        if (!Isolate::IsVMInternalIsolate(isolate_)) {
+          JSONObject args(&event, "args");
+          args.AddProperty("mode", "basic");
+        }
+        event.AddPropertyF("sf", "%" Pd "-%" Pd, isolate_id, trie->frame_id());
+      }
     }
   }
 }
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index 55bc101..9328800 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -78,6 +78,9 @@
 
   const Function* function() const { return &function_; }
 
+  // Returns the resolved_url for the script containing this function.
+  const char* ResolvedScriptUrl() const;
+
   bool is_visible() const;
 
   intptr_t table_index() const { return table_index_; }
@@ -208,14 +211,14 @@
 
   void PrintToJSONArray(JSONArray* codes);
 
+  ProfileFunction* function() const { return function_; }
+
  private:
   void Tick(uword pc, bool exclusive, intptr_t serial);
   void TickAddress(uword pc, bool exclusive);
 
   ProfileFunction* SetFunctionAndName(ProfileFunctionTable* table);
 
-  ProfileFunction* function() const { return function_; }
-
   void PrintNativeCode(JSONObject* profile_code_obj);
   void PrintCollectedCode(JSONObject* profile_code_obj);
   void PrintOverwrittenCode(JSONObject* profile_code_obj);
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index bae18f7..42ef355 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -82,7 +82,7 @@
     for (intptr_t j = 0; j < fields_.Length(); j++) {
       field_ ^= fields_.At(j);
       if (field_.is_static() && field_.HasInitializerFunction()) {
-        function_ ^= field_.InitializerFunction();
+        function_ = field_.InitializerFunction();
         visitor_->Visit(function_);
       }
     }
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 78a9445..0658a6d 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -427,6 +427,7 @@
 REGULAR_VISITOR(TypeRef)
 REGULAR_VISITOR(TypeParameter)
 REGULAR_VISITOR(PatchClass)
+REGULAR_VISITOR(Function)
 COMPRESSED_VISITOR(Closure)
 REGULAR_VISITOR(ClosureData)
 REGULAR_VISITOR(SignatureData)
@@ -477,6 +478,7 @@
 NULL_VISITOR(Bool)
 NULL_VISITOR(Capability)
 NULL_VISITOR(SendPort)
+NULL_VISITOR(TransferableTypedData)
 REGULAR_VISITOR(Pointer)
 NULL_VISITOR(DynamicLibrary)
 VARIABLE_NULL_VISITOR(Instructions, Instructions::Size(raw_obj))
@@ -495,73 +497,6 @@
 // Smi has no heap representation.
 UNREACHABLE_VISITOR(Smi)
 
-bool RawFunction::CheckUsageCounter(RawFunction* raw_fun) {
-  // NOTE: This code runs while GC is in progress and runs within
-  // a NoHandleScope block. Hence it is not okay to use regular Zone or
-  // Scope handles. We use direct stack handles, and so the raw pointers in
-  // these handles are not traversed. The use of handles is mainly to
-  // be able to reuse the handle based code and avoid having to add
-  // helper functions to the raw object interface.
-  Function fn;
-  fn = raw_fun;
-
-  // The function may not have code.
-  if (!fn.HasCode()) return false;
-  // These may not increment the usage counter.
-  if (fn.is_intrinsic()) return false;
-
-  if (fn.usage_counter() >= 0) {
-    fn.SetUsageCounter(fn.usage_counter() / 2);
-  }
-  return FLAG_always_drop_code || (fn.usage_counter() == 0);
-}
-
-bool RawFunction::ShouldVisitCode(RawCode* raw_code) {
-  // NOTE: This code runs while GC is in progress and runs within
-  // a NoHandleScope block. Hence it is not okay to use regular Zone or
-  // Scope handles. We use direct stack handles, and so the raw pointers in
-  // these handles are not traversed. The use of handles is mainly to
-  // be able to reuse the handle based code and avoid having to add
-  // helper functions to the raw object interface.
-  Code code;
-  code = raw_code;
-  if (code.IsNull()) return true;
-  if (code.is_optimized()) return true;
-  if (code.HasBreakpoint()) return true;
-  return false;
-}
-
-intptr_t RawFunction::VisitFunctionPointers(RawFunction* raw_obj,
-                                            ObjectPointerVisitor* visitor) {
-  if (visitor->visit_function_code() || !CheckUsageCounter(raw_obj)) {
-    visitor->VisitPointers(raw_obj->from(), raw_obj->to());
-    return Function::InstanceSize();
-  }
-#if defined(DART_PRECOMPILED_RUNTIME)
-  UNREACHABLE();
-#else
-  visitor->VisitPointers(raw_obj->from(), raw_obj->to_no_code());
-
-  visitor->VisitPointer(
-      reinterpret_cast<RawObject**>(&raw_obj->ptr()->bytecode_));
-
-  if (ShouldVisitCode(raw_obj->ptr()->code_)) {
-    visitor->VisitPointer(
-        reinterpret_cast<RawObject**>(&raw_obj->ptr()->code_));
-  } else {
-    visitor->add_skipped_code_function(raw_obj);
-  }
-
-  if (ShouldVisitCode(raw_obj->ptr()->unoptimized_code_)) {
-    visitor->VisitPointer(
-        reinterpret_cast<RawObject**>(&raw_obj->ptr()->unoptimized_code_));
-  } else {
-    visitor->add_skipped_code_function(raw_obj);
-  }
-#endif
-  return Function::InstanceSize();
-}
-
 bool RawCode::ContainsPC(RawObject* raw_obj, uword pc) {
   if (raw_obj->IsCode()) {
     RawCode* raw_code = static_cast<RawCode*>(raw_obj);
@@ -603,7 +538,7 @@
     RawBytecode* raw_bytecode = static_cast<RawBytecode*>(raw_obj);
     uword start = raw_bytecode->ptr()->instructions_;
     uword size = raw_bytecode->ptr()->instructions_size_;
-    return (pc - start) < size;
+    return (pc - start) <= size;  // pc may point past last instruction.
   }
   return false;
 }
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index ffff441..1028af1 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -13,6 +13,7 @@
 #include "platform/atomic.h"
 #include "vm/class_id.h"
 #include "vm/compiler/method_recognizer.h"
+#include "vm/compiler/runtime_api.h"
 #include "vm/exceptions.h"
 #include "vm/globals.h"
 #include "vm/object_graph.h"
@@ -150,8 +151,10 @@
   // Encodes the object size in the tag in units of object alignment.
   class SizeTag {
    public:
-    static const intptr_t kMaxSizeTag = ((1 << RawObject::kSizeTagSize) - 1)
-                                        << kObjectAlignmentLog2;
+    static constexpr intptr_t kMaxSizeTagInUnitsOfAlignment =
+        ((1 << RawObject::kSizeTagSize) - 1);
+    static constexpr intptr_t kMaxSizeTag =
+        kMaxSizeTagInUnitsOfAlignment * kObjectAlignment;
 
     static uword encode(intptr_t size) {
       return SizeBits::encode(SizeToTagValue(size));
@@ -171,11 +174,15 @@
         : public BitField<uint32_t, intptr_t, kSizeTagPos, kSizeTagSize> {};
 
     static intptr_t SizeToTagValue(intptr_t size) {
-      ASSERT(Utils::IsAligned(size, kObjectAlignment));
-      return (size > kMaxSizeTag) ? 0 : (size >> kObjectAlignmentLog2);
+      ASSERT(Utils::IsAligned(
+          size, compiler::target::ObjectAlignment::kObjectAlignment));
+      return (size > kMaxSizeTag)
+                 ? 0
+                 : (size >>
+                    compiler::target::ObjectAlignment::kObjectAlignmentLog2);
     }
     static intptr_t TagValueToSize(intptr_t value) {
-      return value << kObjectAlignmentLog2;
+      return value << compiler::target::ObjectAlignment::kObjectAlignmentLog2;
     }
   };
 
@@ -693,7 +700,6 @@
   friend class SizeExcludingClassVisitor;  // GetClassId
   friend class InstanceAccumulator;        // GetClassId
   friend class RetainingPathVisitor;       // GetClassId
-  friend class SkippedCodeFunctions;       // StorePointer
   friend class ImageReader;                // tags_ check
   friend class ImageWriter;
   friend class AssemblyImageWriter;
@@ -724,6 +730,7 @@
   friend class ObjectOffsetTrait;   // GetClassId
   friend class WriteBarrierUpdateVisitor;  // CheckHeapPointerStore
   friend class OffsetsTable;
+  friend class RawTransferableTypedData;  // GetClassId
 
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(RawObject);
@@ -736,6 +743,19 @@
     kPreFinalized,          // VM classes: size precomputed, but no checks done.
     kFinalized,             // Class parsed, finalized and ready for use.
   };
+  enum ClassLoadingState {
+    // Class object is created, but it is not filled up.
+    // At this state class can only be used as a forward reference during
+    // class loading.
+    kNameOnly = 0,
+    // Class declaration information such as type parameters, supertype and
+    // implemented interfaces are loaded. However, types in the class are
+    // not finalized yet.
+    kDeclarationLoaded,
+    // Types in the class are finalized. At this point, members can be loaded
+    // and class can be finalized.
+    kTypeFinalized,
+  };
 
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(Class);
@@ -785,13 +805,8 @@
   int32_t next_field_offset_in_words_;  // Offset of the next instance field.
   classid_t id_;                // Class Id, also index in the class table.
   int16_t num_type_arguments_;  // Number of type arguments in flattened vector.
-
-  // Bitfields with number of non-overlapping type arguments and 'has_pragma'
-  // bit.
-  uint16_t has_pragma_and_num_own_type_arguments_;
-
   uint16_t num_native_fields_;
-  uint16_t state_bits_;
+  uint32_t state_bits_;
   NOT_IN_PRECOMPILED(intptr_t kernel_offset_);
 
   friend class Instance;
@@ -847,10 +862,10 @@
     kGetterFunction,     // represents getter functions e.g: get foo() { .. }.
     kSetterFunction,     // represents setter functions e.g: set foo(..) { .. }.
     kConstructor,
-    kImplicitGetter,             // represents an implicit getter for fields.
-    kImplicitSetter,             // represents an implicit setter for fields.
-    kImplicitStaticFinalGetter,  // represents an implicit getter for static
-                                 // final fields (incl. static const fields).
+    kImplicitGetter,        // represents an implicit getter for fields.
+    kImplicitSetter,        // represents an implicit setter for fields.
+    kImplicitStaticGetter,  // represents an implicit getter for static
+                            // fields with initializers
     kStaticFieldInitializer,
     kMethodExtractor,  // converts method into implicit closure on the receiver.
     kNoSuchMethodDispatcher,  // invokes noSuchMethod.
@@ -875,15 +890,10 @@
   static constexpr intptr_t kMaxOptionalParametersBits = 14;
 
  private:
-  // So that the SkippedCodeFunctions::DetachCode can null out the code fields.
-  friend class SkippedCodeFunctions;
   friend class Class;
 
   RAW_HEAP_OBJECT_IMPLEMENTATION(Function);
 
-  static bool ShouldVisitCode(RawCode* raw_code);
-  static bool CheckUsageCounter(RawFunction* raw_fun);
-
   uword entry_point_;  // Accessed from generated code.
   uword unchecked_entry_point_;  // Accessed from generated code.
 
@@ -1019,7 +1029,19 @@
   VISIT_FROM(RawObject*, signature_type_);
   RawType* signature_type_;
   RawFunction* c_signature_;
-  VISIT_TO(RawObject*, c_signature_);
+
+  // Target Dart method for callbacks, otherwise null.
+  RawFunction* callback_target_;
+
+  VISIT_TO(RawObject*, callback_target_);
+
+  // Callback id for callbacks, otherwise 0.
+  //
+  // The callbacks ids are used so that native callbacks can lookup their own
+  // code objects, since native code doesn't pass code objects into function
+  // calls. The callback id is also used to for verifying that callbacks are
+  // called on the correct isolate. See DLRT_VerifyCallbackIsolate for details.
+  uint32_t callback_id_;
 };
 
 class RawField : public RawObject {
@@ -1329,7 +1351,6 @@
   friend class Function;
   template <bool>
   friend class MarkingVisitorBase;
-  friend class SkippedCodeFunctions;
   friend class StackFrame;
   friend class Profiler;
   friend class FunctionDeserializationCluster;
@@ -1344,13 +1365,21 @@
   VISIT_FROM(RawObject*, object_pool_);
   RawObjectPool* object_pool_;
   RawFunction* function_;
+  RawArray* closures_;
   RawExceptionHandlers* exception_handlers_;
   RawPcDescriptors* pc_descriptors_;
+  NOT_IN_PRODUCT(RawLocalVarDescriptors* var_descriptors_);
+#if defined(PRODUCT)
   VISIT_TO(RawObject*, pc_descriptors_);
+#else
+  VISIT_TO(RawObject*, var_descriptors_);
+#endif
+
   RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
   int32_t instructions_binary_offset_;
   int32_t source_positions_binary_offset_;
+  NOT_IN_PRODUCT(int32_t local_variables_binary_offset_);
 
   static bool ContainsPC(RawObject* raw_obj, uword pc);
 
@@ -1391,15 +1420,14 @@
   uint32_t size_and_flags_;
   uint32_t unchecked_entrypoint_pc_offset_;
 
-#if defined(DART_PRECOMPILER)
   // There is a gap between size_and_flags_ and the entry point
   // because we align entry point by 4 words on all platforms.
   // This allows us to have a free field here without affecting
   // the aligned size of the Instructions object header.
   // This also means that entry point offset is the same
   // whether this field is included or excluded.
+  // TODO(37103): This field should be removed.
   CodeStatistics* stats_;
-#endif
 
   // Variable length data follows here.
   uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
@@ -1415,7 +1443,6 @@
   friend class StackFrame;
   template <bool>
   friend class MarkingVisitorBase;
-  friend class SkippedCodeFunctions;
   friend class Function;
   friend class ImageReader;
   friend class ImageWriter;
@@ -1439,19 +1466,19 @@
    public:
     // Most of the time try_index will be small and merged field will fit into
     // one byte.
-    static intptr_t Encode(intptr_t kind, intptr_t try_index) {
+    static int32_t Encode(intptr_t kind, intptr_t try_index) {
       intptr_t kind_shift = Utils::ShiftForPowerOfTwo(kind);
       ASSERT(Utils::IsUint(kKindShiftSize, kind_shift));
       ASSERT(Utils::IsInt(kTryIndexSize, try_index));
       return (try_index << kTryIndexPos) | (kind_shift << kKindShiftPos);
     }
 
-    static intptr_t DecodeKind(intptr_t merged_kind_try) {
+    static intptr_t DecodeKind(int32_t merged_kind_try) {
       const intptr_t kKindShiftMask = (1 << kKindShiftSize) - 1;
       return 1 << (merged_kind_try & kKindShiftMask);
     }
 
-    static intptr_t DecodeTryIndex(intptr_t merged_kind_try) {
+    static intptr_t DecodeTryIndex(int32_t merged_kind_try) {
       // Arithmetic shift.
       return merged_kind_try >> kTryIndexPos;
     }
@@ -1463,7 +1490,7 @@
     COMPILE_ASSERT(kLastKind <= 1 << ((1 << kKindShiftSize) - 1));
 
     static const intptr_t kTryIndexPos = kKindShiftSize;
-    static const intptr_t kTryIndexSize = kBitsPerWord - kKindShiftSize;
+    static const intptr_t kTryIndexSize = 32 - kKindShiftSize;
   };
 
  private:
@@ -2387,6 +2414,11 @@
   VISIT_TO(RawObject*, handler_)
 };
 
+class RawTransferableTypedData : public RawInstance {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(TransferableTypedData);
+  VISIT_NOTHING();
+};
+
 // VM type for capturing stacktraces when exceptions are thrown,
 // Currently we don't have any interface that this object is supposed
 // to implement so we just support the 'toString' method which
@@ -2436,11 +2468,17 @@
   VISIT_TO(RawObject*, external_two_byte_sticky_function_)
   RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
-  intptr_t num_registers_;
+  // The same pattern may use different amount of registers if compiled
+  // for a one-byte target than a two-byte target. For example, we do not
+  // need to allocate registers to check whether the current position is within
+  // a surrogate pair when matching a Unicode pattern against a one-byte string.
+  intptr_t num_one_byte_registers_;
+  intptr_t num_two_byte_registers_;
 
   // A bitfield with two fields:
   // type: Uninitialized, simple or complex.
-  // flags: Represents global/local, case insensitive, multiline.
+  // flags: Represents global/local, case insensitive, multiline, unicode,
+  //        dotAll.
   int8_t type_flags_;
 };
 
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index 5728dad..c4aac7c 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -109,6 +109,7 @@
   F(Bytecode, function_)                                                       \
   F(Bytecode, exception_handlers_)                                             \
   F(Bytecode, pc_descriptors_)                                                 \
+  F(Bytecode, closures_)                                                       \
   F(ExceptionHandlers, handled_types_data_)                                    \
   F(Context, parent_)                                                          \
   F(SingleTargetCache, target_)                                                \
@@ -191,7 +192,13 @@
   F(Pointer, type_arguments_)                                                  \
   F(Pointer, c_memory_address_)                                                \
   F(DynamicLibrary, handle_)                                                   \
-  F(FfiTrampolineData, signature_type_)
+  F(FfiTrampolineData, signature_type_)                                        \
+  F(FfiTrampolineData, c_signature_)                                           \
+  F(FfiTrampolineData, callback_target_)                                       \
+  F(TypedDataBase, data_)                                                      \
+  F(TypedDataBase, length_)                                                    \
+  F(TypedDataView, typed_data_)                                                \
+  F(TypedDataView, offset_in_bytes_)
 
 OffsetsTable::OffsetsTable(Zone* zone) : cached_offsets_(zone) {
   for (intptr_t i = 0; offsets_table[i].class_id != -1; ++i) {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 20e3983..d734dbb 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+#include "vm/dart_api_state.h"
 #include "vm/message.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
@@ -42,7 +43,7 @@
   ASSERT(reader != NULL);
 
   Class& cls = Class::ZoneHandle(reader->zone(), Class::null());
-  cls ^= reader->ReadClassId(object_id);
+  cls = reader->ReadClassId(object_id);
   return cls.raw();
 }
 
@@ -316,7 +317,7 @@
 
   // Set the canonical bit.
   if (is_canonical) {
-    type_arguments ^= type_arguments.Canonicalize();
+    type_arguments = type_arguments.Canonicalize();
   }
 
   return type_arguments.raw();
@@ -738,7 +739,7 @@
   Context& context = Context::ZoneHandle(reader->zone());
   reader->AddBackRef(object_id, &context, kIsDeserialized);
   if (num_vars != 0) {
-    context ^= Context::New(num_vars);
+    context = Context::New(num_vars);
 
     // Set all the object fields.
     // TODO(5411462): Need to assert No GC can happen here, even though
@@ -1226,7 +1227,7 @@
     for (intptr_t i = 0; i < len; i++) {
       ptr[i] = reader->Read<CharacterType>();
     }
-    *str_obj ^= (*new_symbol)(reader->thread(), ptr, len);
+    *str_obj = (*new_symbol)(reader->thread(), ptr, len);
   } else {
     // Set up the string object.
     *str_obj = StringType::New(len, Heap::kNew);
@@ -2133,6 +2134,68 @@
   writer->Write<uint64_t>(ptr()->origin_id_);
 }
 
+RawTransferableTypedData* TransferableTypedData::ReadFrom(
+    SnapshotReader* reader,
+    intptr_t object_id,
+    intptr_t tags,
+    Snapshot::Kind kind,
+    bool as_reference) {
+  ASSERT(reader != nullptr);
+
+  ASSERT(!Snapshot::IsFull(kind));
+  const intptr_t length = reader->Read<int32_t>();
+
+  const FinalizableData finalizable_data =
+      static_cast<MessageSnapshotReader*>(reader)->finalizable_data()->Take();
+  uint8_t* data = reinterpret_cast<uint8_t*>(finalizable_data.data);
+  auto& transferableTypedData = TransferableTypedData::ZoneHandle(
+      reader->zone(), TransferableTypedData::New(data, length));
+  reader->AddBackRef(object_id, &transferableTypedData, kIsDeserialized);
+  return transferableTypedData.raw();
+}
+
+void RawTransferableTypedData::WriteTo(SnapshotWriter* writer,
+                                       intptr_t object_id,
+                                       Snapshot::Kind kind,
+                                       bool as_reference) {
+  ASSERT(writer != nullptr);
+  ASSERT(GetClassId() == kTransferableTypedDataCid);
+  void* peer = writer->thread()->heap()->GetPeer(this);
+  // Assume that object's Peer is only used to track transferrability state.
+  ASSERT(peer != nullptr);
+  TransferableTypedDataPeer* tpeer =
+      reinterpret_cast<TransferableTypedDataPeer*>(peer);
+  intptr_t length = tpeer->length();  // In bytes.
+  void* data = tpeer->data();
+  if (data == nullptr) {
+    writer->SetWriteException(
+        Exceptions::kArgument,
+        "Illegal argument in isolate message"
+        " : (TransferableTypedData has been transferred already)");
+    return;
+  }
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+
+  writer->WriteIndexedObject(GetClassId());
+  writer->WriteTags(writer->GetObjectTags(this));
+  writer->Write<int32_t>(length);
+
+  static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
+      length, data, tpeer,
+      // Finalizer does nothing - in case of failure to serialize,
+      // [data] remains wrapped in sender's [TransferableTypedData].
+      [](void* data, Dart_WeakPersistentHandle handle, void* peer) {},
+      // This is invoked on successful serialization of the message
+      [](void* data, Dart_WeakPersistentHandle handle, void* peer) {
+        TransferableTypedDataPeer* tpeer =
+            reinterpret_cast<TransferableTypedDataPeer*>(peer);
+        tpeer->handle()->EnsureFreeExternal(Isolate::Current());
+        tpeer->ClearData();
+      });
+}
+
 RawStackTrace* StackTrace::ReadFrom(SnapshotReader* reader,
                                     intptr_t object_id,
                                     intptr_t tags,
@@ -2172,7 +2235,9 @@
   *reader->StringHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
   regex.set_pattern(*reader->StringHandle());
 
-  regex.StoreNonPointer(&regex.raw_ptr()->num_registers_,
+  regex.StoreNonPointer(&regex.raw_ptr()->num_one_byte_registers_,
+                        reader->Read<int32_t>());
+  regex.StoreNonPointer(&regex.raw_ptr()->num_two_byte_registers_,
                         reader->Read<int32_t>());
   regex.StoreNonPointer(&regex.raw_ptr()->type_flags_, reader->Read<int8_t>());
 
@@ -2202,7 +2267,8 @@
   // Write out all the other fields.
   writer->Write<RawObject*>(ptr()->num_bracket_expressions_);
   writer->WriteObjectImpl(ptr()->pattern_, kAsInlinedObject);
-  writer->Write<int32_t>(ptr()->num_registers_);
+  writer->Write<int32_t>(ptr()->num_one_byte_registers_);
+  writer->Write<int32_t>(ptr()->num_two_byte_registers_);
   writer->Write<int8_t>(ptr()->type_flags_);
 }
 
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index c2b4fe7..12796de 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -4,6 +4,13 @@
 
 #include "vm/regexp.h"
 
+#include <memory>
+
+#include "platform/splay-tree-inl.h"
+#include "platform/unicode.h"
+
+#include "unicode/uniset.h"
+
 #include "vm/dart_entry.h"
 #include "vm/regexp_assembler.h"
 #include "vm/regexp_assembler_bytecode.h"
@@ -12,7 +19,6 @@
 #include "vm/symbols.h"
 #include "vm/thread.h"
 #include "vm/unibrow-inl.h"
-#include "vm/unicode.h"
 
 #define Z (zone())
 
@@ -25,14 +31,14 @@
 static const intptr_t kMaxLookaheadForBoyerMoore = 8;
 
 ContainedInLattice AddRange(ContainedInLattice containment,
-                            const intptr_t* ranges,
+                            const int32_t* ranges,
                             intptr_t ranges_length,
                             Interval new_range) {
   ASSERT((ranges_length & 1) == 1);
-  ASSERT(ranges[ranges_length - 1] == Utf16::kMaxCodeUnit + 1);
+  ASSERT(ranges[ranges_length - 1] == Utf::kMaxCodePoint + 1);
   if (containment == kLatticeUnknown) return containment;
   bool inside = false;
-  intptr_t last = 0;
+  int32_t last = 0;
   for (intptr_t i = 0; i < ranges_length;
        inside = !inside, last = ranges[i], i++) {
     // Consider the range from last to ranges[i].
@@ -282,10 +288,26 @@
 
 class RegExpCompiler : public ValueObject {
  public:
-  RegExpCompiler(intptr_t capture_count, bool ignore_case, bool is_one_byte);
+  RegExpCompiler(intptr_t capture_count, bool is_one_byte);
 
   intptr_t AllocateRegister() { return next_register_++; }
 
+  // Lookarounds to match lone surrogates for unicode character class matches
+  // are never nested. We can therefore reuse registers.
+  intptr_t UnicodeLookaroundStackRegister() {
+    if (unicode_lookaround_stack_register_ == kNoRegister) {
+      unicode_lookaround_stack_register_ = AllocateRegister();
+    }
+    return unicode_lookaround_stack_register_;
+  }
+
+  intptr_t UnicodeLookaroundPositionRegister() {
+    if (unicode_lookaround_position_register_ == kNoRegister) {
+      unicode_lookaround_position_register_ = AllocateRegister();
+    }
+    return unicode_lookaround_position_register_;
+  }
+
 #if !defined(DART_PRECOMPILED_RUNTIME)
   RegExpEngine::CompilationResult Assemble(IRRegExpMacroAssembler* assembler,
                                            RegExpNode* start,
@@ -315,7 +337,6 @@
 
   void SetRegExpTooBig() { reg_exp_too_big_ = true; }
 
-  inline bool ignore_case() { return ignore_case_; }
   inline bool one_byte() const { return is_one_byte_; }
   bool read_backward() { return read_backward_; }
   void set_read_backward(bool value) { read_backward_ = value; }
@@ -333,10 +354,11 @@
  private:
   EndNode* accept_;
   intptr_t next_register_;
+  intptr_t unicode_lookaround_stack_register_;
+  intptr_t unicode_lookaround_position_register_;
   ZoneGrowableArray<RegExpNode*>* work_list_;
   intptr_t recursion_depth_;
   RegExpMacroAssembler* macro_assembler_;
-  bool ignore_case_;
   bool is_one_byte_;
   bool reg_exp_too_big_;
   bool read_backward_;
@@ -362,13 +384,12 @@
 
 // Attempts to compile the regexp using an Irregexp code generator.  Returns
 // a fixed array or a null handle depending on whether it succeeded.
-RegExpCompiler::RegExpCompiler(intptr_t capture_count,
-                               bool ignore_case,
-                               bool is_one_byte)
+RegExpCompiler::RegExpCompiler(intptr_t capture_count, bool is_one_byte)
     : next_register_(2 * (capture_count + 1)),
+      unicode_lookaround_stack_register_(kNoRegister),
+      unicode_lookaround_position_register_(kNoRegister),
       work_list_(NULL),
       recursion_depth_(0),
-      ignore_case_(ignore_case),
       is_one_byte_(is_one_byte),
       reg_exp_too_big_(false),
       read_backward_(false),
@@ -999,7 +1020,7 @@
 }
 
 static void EmitBoundaryTest(RegExpMacroAssembler* masm,
-                             intptr_t border,
+                             uint16_t border,
                              BlockLabel* fall_through,
                              BlockLabel* above_or_equal,
                              BlockLabel* below) {
@@ -1012,8 +1033,8 @@
 }
 
 static void EmitDoubleBoundaryTest(RegExpMacroAssembler* masm,
-                                   intptr_t first,
-                                   intptr_t last,
+                                   uint16_t first,
+                                   uint16_t last,
                                    BlockLabel* fall_through,
                                    BlockLabel* in_range,
                                    BlockLabel* out_of_range) {
@@ -1036,10 +1057,10 @@
 // even_label is for ranges[i] to ranges[i + 1] where i - start_index is even.
 // odd_label is for ranges[i] to ranges[i + 1] where i - start_index is odd.
 static void EmitUseLookupTable(RegExpMacroAssembler* masm,
-                               ZoneGrowableArray<int>* ranges,
+                               ZoneGrowableArray<uint16_t>* ranges,
                                intptr_t start_index,
                                intptr_t end_index,
-                               intptr_t min_char,
+                               uint16_t min_char,
                                BlockLabel* fall_through,
                                BlockLabel* even_label,
                                BlockLabel* odd_label) {
@@ -1093,7 +1114,7 @@
 }
 
 static void CutOutRange(RegExpMacroAssembler* masm,
-                        ZoneGrowableArray<int>* ranges,
+                        ZoneGrowableArray<uint16_t>* ranges,
                         intptr_t start_index,
                         intptr_t end_index,
                         intptr_t cut_index,
@@ -1119,17 +1140,17 @@
 
 // Unicode case.  Split the search space into kSize spaces that are handled
 // with recursion.
-static void SplitSearchSpace(ZoneGrowableArray<int>* ranges,
+static void SplitSearchSpace(ZoneGrowableArray<uint16_t>* ranges,
                              intptr_t start_index,
                              intptr_t end_index,
                              intptr_t* new_start_index,
                              intptr_t* new_end_index,
-                             intptr_t* border) {
+                             uint16_t* border) {
   static const intptr_t kSize = RegExpMacroAssembler::kTableSize;
   static const intptr_t kMask = RegExpMacroAssembler::kTableMask;
 
-  intptr_t first = ranges->At(start_index);
-  intptr_t last = ranges->At(end_index) - 1;
+  uint16_t first = ranges->At(start_index);
+  uint16_t last = ranges->At(end_index) - 1;
 
   *new_start_index = start_index;
   *border = (ranges->At(start_index) & ~kMask) + kSize;
@@ -1189,7 +1210,7 @@
 // Either label can be NULL indicating backtracking.  Either label can also be
 // equal to the fall_through label.
 static void GenerateBranches(RegExpMacroAssembler* masm,
-                             ZoneGrowableArray<int>* ranges,
+                             ZoneGrowableArray<uint16_t>* ranges,
                              intptr_t start_index,
                              intptr_t end_index,
                              uint16_t min_char,
@@ -1197,8 +1218,8 @@
                              BlockLabel* fall_through,
                              BlockLabel* even_label,
                              BlockLabel* odd_label) {
-  intptr_t first = ranges->At(start_index);
-  intptr_t last = ranges->At(end_index) - 1;
+  uint16_t first = ranges->At(start_index);
+  uint16_t last = ranges->At(end_index) - 1;
 
   ASSERT(min_char < first);
 
@@ -1258,7 +1279,7 @@
 
   intptr_t new_start_index = 0;
   intptr_t new_end_index = 0;
-  intptr_t border = 0;
+  uint16_t border = 0;
 
   SplitSearchSpace(ranges, start_index, end_index, &new_start_index,
                    &new_end_index, &border);
@@ -1315,7 +1336,7 @@
     CharacterRange::Canonicalize(ranges);
   }
 
-  intptr_t max_char;
+  uint16_t max_char;
   if (one_byte) {
     max_char = Symbols::kMaxOneCharCodeSymbol;
   } else {
@@ -1326,7 +1347,7 @@
 
   intptr_t last_valid_range = range_count - 1;
   while (last_valid_range >= 0) {
-    CharacterRange& range = (*ranges)[last_valid_range];
+    const CharacterRange& range = ranges->At(last_valid_range);
     if (range.from() <= max_char) {
       break;
     }
@@ -1354,14 +1375,6 @@
     }
     return;
   }
-  if (last_valid_range == 0 && !cc->is_negated() &&
-      ranges->At(0).IsEverything(max_char)) {
-    // This is a common case hit by non-anchored expressions.
-    if (check_offset) {
-      macro_assembler->CheckPosition(cp_offset, on_failure);
-    }
-    return;
-  }
 
   if (!preloaded) {
     macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset);
@@ -1378,25 +1391,24 @@
   // entry at zero which goes to the failure label, but if there
   // was already one there we fall through for success on that entry.
   // Subsequent entries have alternating meaning (success/failure).
-  ZoneGrowableArray<int>* range_boundaries =
-      new (zone) ZoneGrowableArray<int>(last_valid_range);
+  ZoneGrowableArray<uint16_t>* range_boundaries =
+      new (zone) ZoneGrowableArray<uint16_t>(last_valid_range);
 
   bool zeroth_entry_is_failure = !cc->is_negated();
 
   for (intptr_t i = 0; i <= last_valid_range; i++) {
-    CharacterRange& range = (*ranges)[i];
+    const CharacterRange& range = ranges->At(i);
     if (range.from() == 0) {
       ASSERT(i == 0);
       zeroth_entry_is_failure = !zeroth_entry_is_failure;
     } else {
       range_boundaries->Add(range.from());
     }
-    range_boundaries->Add(range.to() + 1);
+    if (range.to() + 1 <= max_char) {
+      range_boundaries->Add(range.to() + 1);
+    }
   }
   intptr_t end_index = range_boundaries->length() - 1;
-  if (range_boundaries->At(end_index) > max_char) {
-    end_index--;
-  }
 
   BlockLabel fall_through;
   GenerateBranches(macro_assembler, range_boundaries,
@@ -1694,7 +1706,7 @@
   if (read_backward()) return;
   ASSERT(characters_filled_in < details->characters());
   intptr_t characters = details->characters();
-  intptr_t char_mask;
+  int32_t char_mask;
   if (compiler->one_byte()) {
     char_mask = Symbols::kMaxOneCharCodeSymbol;
   } else {
@@ -1719,7 +1731,7 @@
           pos->determines_perfectly = false;
           return;
         }
-        if (compiler->ignore_case()) {
+        if (elm.atom()->ignore_case()) {
           int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
           intptr_t length =
               GetCaseIndependentLetters(c, compiler->one_byte(), chars);
@@ -1769,6 +1781,7 @@
           details->positions(characters_filled_in);
       RegExpCharacterClass* tree = elm.char_class();
       ZoneGrowableArray<CharacterRange>* ranges = tree->ranges();
+      ASSERT(!ranges->is_empty());
       if (tree->is_negated()) {
         // A quick check uses multi-character mask and compare.  There is no
         // useful way to incorporate a negative char class into this scheme
@@ -1907,16 +1920,16 @@
   NodeInfo* info_;
 };
 
-RegExpNode* SeqRegExpNode::FilterOneByte(intptr_t depth, bool ignore_case) {
+RegExpNode* SeqRegExpNode::FilterOneByte(intptr_t depth) {
   if (info()->replacement_calculated) return replacement();
   if (depth < 0) return this;
   ASSERT(!info()->visited);
   VisitMarker marker(info());
-  return FilterSuccessor(depth - 1, ignore_case);
+  return FilterSuccessor(depth - 1);
 }
 
-RegExpNode* SeqRegExpNode::FilterSuccessor(intptr_t depth, bool ignore_case) {
-  RegExpNode* next = on_success_->FilterOneByte(depth - 1, ignore_case);
+RegExpNode* SeqRegExpNode::FilterSuccessor(intptr_t depth) {
+  RegExpNode* next = on_success_->FilterOneByte(depth - 1);
   if (next == NULL) return set_replacement(NULL);
   on_success_ = next;
   return set_replacement(this);
@@ -1953,7 +1966,7 @@
   return 0;
 }
 
-RegExpNode* TextNode::FilterOneByte(intptr_t depth, bool ignore_case) {
+RegExpNode* TextNode::FilterOneByte(intptr_t depth) {
   if (info()->replacement_calculated) return replacement();
   if (depth < 0) return this;
   ASSERT(!info()->visited);
@@ -1966,7 +1979,7 @@
       for (intptr_t j = 0; j < quarks->length(); j++) {
         uint16_t c = quarks->At(j);
         if (c <= Symbols::kMaxOneCharCodeSymbol) continue;
-        if (!ignore_case) return set_replacement(NULL);
+        if (!elm.atom()->ignore_case()) return set_replacement(NULL);
         // Here, we need to check for characters whose upper and lower cases
         // are outside the Latin-1 range.
         uint16_t converted = ConvertNonLatin1ToLatin1(c);
@@ -1988,40 +2001,44 @@
         if (range_count != 0 && ranges->At(0).from() == 0 &&
             ranges->At(0).to() >= Symbols::kMaxOneCharCodeSymbol) {
           // This will be handled in a later filter.
-          if (ignore_case && RangesContainLatin1Equivalents(ranges)) continue;
+          if (cc->flags().IgnoreCase() &&
+              RangesContainLatin1Equivalents(ranges)) {
+            continue;
+          }
           return set_replacement(NULL);
         }
       } else {
         if (range_count == 0 ||
             ranges->At(0).from() > Symbols::kMaxOneCharCodeSymbol) {
           // This will be handled in a later filter.
-          if (ignore_case && RangesContainLatin1Equivalents(ranges)) continue;
+          if (cc->flags().IgnoreCase() &&
+              RangesContainLatin1Equivalents(ranges))
+            continue;
           return set_replacement(NULL);
         }
       }
     }
   }
-  return FilterSuccessor(depth - 1, ignore_case);
+  return FilterSuccessor(depth - 1);
 }
 
-RegExpNode* LoopChoiceNode::FilterOneByte(intptr_t depth, bool ignore_case) {
+RegExpNode* LoopChoiceNode::FilterOneByte(intptr_t depth) {
   if (info()->replacement_calculated) return replacement();
   if (depth < 0) return this;
   if (info()->visited) return this;
   {
     VisitMarker marker(info());
 
-    RegExpNode* continue_replacement =
-        continue_node_->FilterOneByte(depth - 1, ignore_case);
+    RegExpNode* continue_replacement = continue_node_->FilterOneByte(depth - 1);
     // If we can't continue after the loop then there is no sense in doing the
     // loop.
     if (continue_replacement == NULL) return set_replacement(NULL);
   }
 
-  return ChoiceNode::FilterOneByte(depth - 1, ignore_case);
+  return ChoiceNode::FilterOneByte(depth - 1);
 }
 
-RegExpNode* ChoiceNode::FilterOneByte(intptr_t depth, bool ignore_case) {
+RegExpNode* ChoiceNode::FilterOneByte(intptr_t depth) {
   if (info()->replacement_calculated) return replacement();
   if (depth < 0) return this;
   if (info()->visited) return this;
@@ -2040,8 +2057,7 @@
   RegExpNode* survivor = NULL;
   for (intptr_t i = 0; i < choice_count; i++) {
     GuardedAlternative alternative = alternatives_->At(i);
-    RegExpNode* replacement =
-        alternative.node()->FilterOneByte(depth - 1, ignore_case);
+    RegExpNode* replacement = alternative.node()->FilterOneByte(depth - 1);
     ASSERT(replacement != this);  // No missing EMPTY_MATCH_CHECK.
     if (replacement != NULL) {
       (*alternatives_)[i].set_node(replacement);
@@ -2061,7 +2077,7 @@
       new (Z) ZoneGrowableArray<GuardedAlternative>(surviving);
   for (intptr_t i = 0; i < choice_count; i++) {
     RegExpNode* replacement =
-        (*alternatives_)[i].node()->FilterOneByte(depth - 1, ignore_case);
+        (*alternatives_)[i].node()->FilterOneByte(depth - 1);
     if (replacement != NULL) {
       (*alternatives_)[i].set_node(replacement);
       new_alternatives->Add((*alternatives_)[i]);
@@ -2071,8 +2087,7 @@
   return this;
 }
 
-RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte(intptr_t depth,
-                                                        bool ignore_case) {
+RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte(intptr_t depth) {
   if (info()->replacement_calculated) return replacement();
   if (depth < 0) return this;
   if (info()->visited) return this;
@@ -2080,12 +2095,12 @@
   // Alternative 0 is the negative lookahead, alternative 1 is what comes
   // afterwards.
   RegExpNode* node = (*alternatives_)[1].node();
-  RegExpNode* replacement = node->FilterOneByte(depth - 1, ignore_case);
+  RegExpNode* replacement = node->FilterOneByte(depth - 1);
   if (replacement == NULL) return set_replacement(NULL);
   (*alternatives_)[1].set_node(replacement);
 
   RegExpNode* neg_node = (*alternatives_)[0].node();
-  RegExpNode* neg_replacement = neg_node->FilterOneByte(depth - 1, ignore_case);
+  RegExpNode* neg_replacement = neg_node->FilterOneByte(depth - 1);
   // If the negative lookahead is always going to fail then
   // we don't need to check it.
   if (neg_replacement == NULL) return set_replacement(replacement);
@@ -2383,13 +2398,21 @@
     if (elm.text_type() == TextElement::ATOM) {
       ZoneGrowableArray<uint16_t>* quarks = elm.atom()->data();
       for (intptr_t j = preloaded ? 0 : quarks->length() - 1; j >= 0; j--) {
+        if (SkipPass(pass, elm.atom()->ignore_case())) continue;
         if (first_element_checked && i == 0 && j == 0) continue;
         if (DeterminedAlready(quick_check, elm.cp_offset() + j)) continue;
         EmitCharacterFunction* emit_function = NULL;
+        uint16_t quark = quarks->At(j);
+        if (elm.atom()->ignore_case()) {
+          // Everywhere else we assume that a non-Latin-1 character cannot match
+          // a Latin-1 character. Avoid the cases where this is assumption is
+          // invalid by using the Latin1 equivalent instead.
+          quark = Latin1::TryConvertToLatin1(quark);
+        }
         switch (pass) {
           case NON_LATIN1_MATCH:
             ASSERT(one_byte);
-            if (quarks->At(j) > Symbols::kMaxOneCharCodeSymbol) {
+            if (quark > Symbols::kMaxOneCharCodeSymbol) {
               assembler->GoTo(backtrack);
               return;
             }
@@ -2445,6 +2468,34 @@
   }
 }
 
+TextNode* TextNode::CreateForCharacterRanges(
+    ZoneGrowableArray<CharacterRange>* ranges,
+    bool read_backward,
+    RegExpNode* on_success,
+    RegExpFlags flags) {
+  ASSERT(ranges != nullptr);
+  ZoneGrowableArray<TextElement>* elms = new ZoneGrowableArray<TextElement>(1);
+  elms->Add(TextElement::CharClass(new RegExpCharacterClass(ranges, flags)));
+  return new TextNode(elms, read_backward, on_success);
+}
+
+TextNode* TextNode::CreateForSurrogatePair(CharacterRange lead,
+                                           CharacterRange trail,
+                                           bool read_backward,
+                                           RegExpNode* on_success,
+                                           RegExpFlags flags) {
+  auto lead_ranges = CharacterRange::List(on_success->zone(), lead);
+  auto trail_ranges = CharacterRange::List(on_success->zone(), trail);
+  auto elms = new ZoneGrowableArray<TextElement>(2);
+
+  elms->Add(
+      TextElement::CharClass(new RegExpCharacterClass(lead_ranges, flags)));
+  elms->Add(
+      TextElement::CharClass(new RegExpCharacterClass(trail_ranges, flags)));
+
+  return new TextNode(elms, read_backward, on_success);
+}
+
 // This generates the code to match a text node.  A text node can contain
 // straight character sequences (possibly to be matched in a case-independent
 // way) and character classes.  For efficiency we do not do this in a single
@@ -2474,19 +2525,15 @@
   // check that now.
   if (trace->characters_preloaded() == 1) {
     for (intptr_t pass = kFirstRealPass; pass <= kLastPass; pass++) {
-      if (!SkipPass(pass, compiler->ignore_case())) {
-        TextEmitPass(compiler, static_cast<TextEmitPassType>(pass), true, trace,
-                     false, &bound_checked_to);
-      }
+      TextEmitPass(compiler, static_cast<TextEmitPassType>(pass), true, trace,
+                   false, &bound_checked_to);
     }
     first_elt_done = true;
   }
 
   for (intptr_t pass = kFirstRealPass; pass <= kLastPass; pass++) {
-    if (!SkipPass(pass, compiler->ignore_case())) {
-      TextEmitPass(compiler, static_cast<TextEmitPassType>(pass), false, trace,
-                   first_elt_done, &bound_checked_to);
-    }
+    TextEmitPass(compiler, static_cast<TextEmitPassType>(pass), false, trace,
+                 first_elt_done, &bound_checked_to);
   }
 
   Trace successor_trace(*trace);
@@ -2528,13 +2575,13 @@
     TextElement elm = elms_->At(i);
     if (elm.text_type() == TextElement::CHAR_CLASS) {
       RegExpCharacterClass* cc = elm.char_class();
-      // None of the standard character classes is different in the case
-      // independent case and it slows us down if we don't know that.
-      if (cc->is_standard()) continue;
-      ZoneGrowableArray<CharacterRange>* ranges = cc->ranges();
-      intptr_t range_count = ranges->length();
-      for (intptr_t j = 0; j < range_count; j++) {
-        (*ranges)[j].AddCaseEquivalents(ranges, is_one_byte, Z);
+      bool case_equivalents_already_added =
+          cc->flags().NeedsUnicodeCaseEquivalents();
+      if (cc->flags().IgnoreCase() && !case_equivalents_already_added) {
+        // None of the standard character classes is different in the case
+        // independent case and it slows us down if we don't know that.
+        if (cc->is_standard()) continue;
+        CharacterRange::AddCaseEquivalents(cc->ranges(), is_one_byte, Z);
       }
     }
   }
@@ -2574,7 +2621,7 @@
 // length nodes or other complications in the way then return a sentinel
 // value indicating that a greedy loop cannot be constructed.
 intptr_t ChoiceNode::GreedyLoopTextLengthForAlternative(
-    GuardedAlternative* alternative) {
+    const GuardedAlternative* alternative) {
   intptr_t length = 0;
   RegExpNode* node = alternative->node();
   // Later we will generate code for all these text nodes using recursion
@@ -2612,7 +2659,7 @@
   if (trace->stop_node() == this) {
     // Back edge of greedy optimized loop node graph.
     intptr_t text_length =
-        GreedyLoopTextLengthForAlternative(&((*alternatives_)[0]));
+        GreedyLoopTextLengthForAlternative(&alternatives_->At(0));
     ASSERT(text_length != kNodeIsTooComplexForGreedyLoops);
     // Update the counter-based backtracking info on the stack.  This is an
     // optimization for greedy loops (see below).
@@ -2668,50 +2715,54 @@
 // size then it is on the stack, otherwise the excess is on the heap.
 class AlternativeGenerationList {
  public:
-  explicit AlternativeGenerationList(intptr_t count) : alt_gens_(count) {
-    for (intptr_t i = 0; i < count && i < kAFew; i++) {
-      alt_gens_.Add(a_few_alt_gens_ + i);
-    }
-    for (intptr_t i = kAFew; i < count; i++) {
-      alt_gens_.Add(new AlternativeGeneration());
-    }
-  }
-  ~AlternativeGenerationList() {
-    for (intptr_t i = kAFew; i < alt_gens_.length(); i++) {
-      delete alt_gens_[i];
-      alt_gens_[i] = NULL;
+  explicit AlternativeGenerationList(intptr_t count) : count_(count) {
+    ASSERT(count >= 0);
+    if (count > kAFew) {
+      excess_alt_gens_.reset(new AlternativeGeneration[count - kAFew]);
     }
   }
 
-  AlternativeGeneration* at(intptr_t i) { return alt_gens_[i]; }
+  AlternativeGeneration* at(intptr_t i) {
+    ASSERT(0 <= i);
+    ASSERT(i < count_);
+    if (i < kAFew) {
+      return &a_few_alt_gens_[i];
+    }
+    return &excess_alt_gens_[i - kAFew];
+  }
 
  private:
   static const intptr_t kAFew = 10;
-  GrowableArray<AlternativeGeneration*> alt_gens_;
+
+  intptr_t count_;
   AlternativeGeneration a_few_alt_gens_[kAFew];
+  std::unique_ptr<AlternativeGeneration[]> excess_alt_gens_;
 
   DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(AlternativeGenerationList);
 };
 
+static const int32_t kRangeEndMarker = Utf::kMaxCodePoint + 1;
+
 // The '2' variant is inclusive from and exclusive to.
 // This covers \s as defined in ECMA-262 5.1, 15.10.2.12,
 // which include WhiteSpace (7.2) or LineTerminator (7.3) values.
 // 0x180E has been removed from Unicode's Zs category and thus
 // from ECMAScript's WhiteSpace category as of Unicode 6.3.
-static const intptr_t kSpaceRanges[] = {
+static const int32_t kSpaceRanges[] = {
     '\t',   '\r' + 1, ' ',    ' ' + 1, 0x00A0, 0x00A1, 0x1680,
     0x1681, 0x2000,   0x200B, 0x2028,  0x202A, 0x202F, 0x2030,
-    0x205F, 0x2060,   0x3000, 0x3001,  0xFEFF, 0xFF00, 0x10000};
+    0x205F, 0x2060,   0x3000, 0x3001,  0xFEFF, 0xFF00, kRangeEndMarker};
 static const intptr_t kSpaceRangeCount = ARRAY_SIZE(kSpaceRanges);
-static const intptr_t kWordRanges[] = {'0',     '9' + 1, 'A',     'Z' + 1, '_',
-                                       '_' + 1, 'a',     'z' + 1, 0x10000};
+static const int32_t kWordRanges[] = {
+    '0', '9' + 1, 'A', 'Z' + 1, '_', '_' + 1, 'a', 'z' + 1, kRangeEndMarker};
 static const intptr_t kWordRangeCount = ARRAY_SIZE(kWordRanges);
-static const intptr_t kDigitRanges[] = {'0', '9' + 1, 0x10000};
+static const int32_t kDigitRanges[] = {'0', '9' + 1, kRangeEndMarker};
 static const intptr_t kDigitRangeCount = ARRAY_SIZE(kDigitRanges);
-static const intptr_t kSurrogateRanges[] = {0xd800, 0xe000, 0x10000};
+static const int32_t kSurrogateRanges[] = {0xd800, 0xe000, kRangeEndMarker};
 static const intptr_t kSurrogateRangeCount = ARRAY_SIZE(kSurrogateRanges);
-static const intptr_t kLineTerminatorRanges[] = {0x000A, 0x000B, 0x000D, 0x000E,
-                                                 0x2028, 0x202A, 0x10000};
+static const int32_t kLineTerminatorRanges[] = {
+    0x000A, 0x000B, 0x000D, 0x000E, 0x2028, 0x202A, kRangeEndMarker};
 static const intptr_t kLineTerminatorRangeCount =
     ARRAY_SIZE(kLineTerminatorRanges);
 
@@ -3057,6 +3108,11 @@
 void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
   intptr_t choice_count = alternatives_->length();
 
+  if (choice_count == 1 && alternatives_->At(0).guards() == nullptr) {
+    alternatives_->At(0).node()->Emit(compiler, trace);
+    return;
+  }
+
   AssertGuardsMentionRegisters(trace);
 
   LimitResult limit_result = LimitVersions(compiler, trace);
@@ -3077,7 +3133,7 @@
   GreedyLoopState greedy_loop_state(not_at_start());
 
   intptr_t text_length =
-      GreedyLoopTextLengthForAlternative(&((*alternatives_)[0]));
+      GreedyLoopTextLengthForAlternative(&alternatives_->At(0));
   AlternativeGenerationList alt_gens(choice_count);
 
   if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) {
@@ -3463,9 +3519,9 @@
   RecursionCheck rc(compiler);
 
   ASSERT(start_reg_ + 1 == end_reg_);
-  if (compiler->ignore_case()) {
-    assembler->CheckNotBackReferenceIgnoreCase(start_reg_, read_backward(),
-                                               trace->backtrack());
+  if (flags_.IgnoreCase()) {
+    assembler->CheckNotBackReferenceIgnoreCase(
+        start_reg_, read_backward(), flags_.IsUnicode(), trace->backtrack());
   } else {
     assembler->CheckNotBackReference(start_reg_, read_backward(),
                                      trace->backtrack());
@@ -3473,6 +3529,11 @@
   // We are going to advance backward, so we may end up at the start.
   if (read_backward()) trace->set_at_start(Trace::UNKNOWN);
 
+  // Check that the back reference does not end inside a surrogate pair.
+  if (flags_.IsUnicode() && !compiler->one_byte()) {
+    assembler->CheckNotInSurrogatePair(trace->cp_offset(), trace->backtrack());
+  }
+
   on_success()->Emit(compiler, trace);
 }
 
@@ -3731,10 +3792,10 @@
 }
 
 static bool CompareInverseRanges(ZoneGrowableArray<CharacterRange>* ranges,
-                                 const intptr_t* special_class,
+                                 const int32_t* special_class,
                                  intptr_t length) {
-  length--;  // Remove final 0x10000.
-  ASSERT(special_class[length] == 0x10000);
+  length--;  // Remove final kRangeEndMarker.
+  ASSERT(special_class[length] == kRangeEndMarker);
   ASSERT(ranges->length() != 0);
   ASSERT(length != 0);
   ASSERT(special_class[0] != 0);
@@ -3754,17 +3815,17 @@
       return false;
     }
   }
-  if (range.to() != 0xffff) {
+  if (range.to() != Utf::kMaxCodePoint) {
     return false;
   }
   return true;
 }
 
 static bool CompareRanges(ZoneGrowableArray<CharacterRange>* ranges,
-                          const intptr_t* special_class,
+                          const int32_t* special_class,
                           intptr_t length) {
-  length--;  // Remove final 0x10000.
-  ASSERT(special_class[length] == 0x10000);
+  length--;  // Remove final kRangeEndMarker.
+  ASSERT(special_class[length] == kRangeEndMarker);
   if (ranges->length() * 2 != length) {
     return false;
   }
@@ -3781,7 +3842,7 @@
 bool RegExpCharacterClass::is_standard() {
   // TODO(lrn): Remove need for this function, by not throwing away information
   // along the way.
-  if (is_negated_) {
+  if (is_negated()) {
     return false;
   }
   if (set_.is_standard()) {
@@ -3816,8 +3877,307 @@
   return false;
 }
 
+UnicodeRangeSplitter::UnicodeRangeSplitter(
+    Zone* zone,
+    ZoneGrowableArray<CharacterRange>* base)
+    : zone_(zone),
+      table_(zone),
+      bmp_(nullptr),
+      lead_surrogates_(nullptr),
+      trail_surrogates_(nullptr),
+      non_bmp_(nullptr) {
+  // The unicode range splitter categorizes given character ranges into:
+  // - Code points from the BMP representable by one code unit.
+  // - Code points outside the BMP that need to be split into surrogate pairs.
+  // - Lone lead surrogates.
+  // - Lone trail surrogates.
+  // Lone surrogates are valid code points, even though no actual characters.
+  // They require special matching to make sure we do not split surrogate pairs.
+  // We use the dispatch table to accomplish this. The base range is split up
+  // by the table by the overlay ranges, and the Call callback is used to
+  // filter and collect ranges for each category.
+  for (intptr_t i = 0; i < base->length(); i++) {
+    table_.AddRange(base->At(i), kBase, zone_);
+  }
+  // Add overlay ranges.
+  table_.AddRange(CharacterRange::Range(0, Utf16::kLeadSurrogateStart - 1),
+                  kBmpCodePoints, zone_);
+  table_.AddRange(CharacterRange::Range(Utf16::kLeadSurrogateStart,
+                                        Utf16::kLeadSurrogateEnd),
+                  kLeadSurrogates, zone_);
+  table_.AddRange(CharacterRange::Range(Utf16::kTrailSurrogateStart,
+                                        Utf16::kTrailSurrogateEnd),
+                  kTrailSurrogates, zone_);
+  table_.AddRange(
+      CharacterRange::Range(Utf16::kTrailSurrogateEnd + 1, Utf16::kMaxCodeUnit),
+      kBmpCodePoints, zone_);
+  table_.AddRange(
+      CharacterRange::Range(Utf16::kMaxCodeUnit + 1, Utf::kMaxCodePoint),
+      kNonBmpCodePoints, zone_);
+  table_.ForEach(this);
+}
+
+void UnicodeRangeSplitter::Call(uint32_t from, DispatchTable::Entry entry) {
+  OutSet* outset = entry.out_set();
+  if (!outset->Get(kBase)) return;
+  ZoneGrowableArray<CharacterRange>** target = nullptr;
+  if (outset->Get(kBmpCodePoints)) {
+    target = &bmp_;
+  } else if (outset->Get(kLeadSurrogates)) {
+    target = &lead_surrogates_;
+  } else if (outset->Get(kTrailSurrogates)) {
+    target = &trail_surrogates_;
+  } else {
+    ASSERT(outset->Get(kNonBmpCodePoints));
+    target = &non_bmp_;
+  }
+  if (*target == nullptr) {
+    *target = new (zone_) ZoneGrowableArray<CharacterRange>(2);
+  }
+  (*target)->Add(CharacterRange::Range(entry.from(), entry.to()));
+}
+
+void AddBmpCharacters(RegExpCompiler* compiler,
+                      ChoiceNode* result,
+                      RegExpNode* on_success,
+                      UnicodeRangeSplitter* splitter) {
+  ZoneGrowableArray<CharacterRange>* bmp = splitter->bmp();
+  if (bmp == nullptr) return;
+  result->AddAlternative(GuardedAlternative(TextNode::CreateForCharacterRanges(
+      bmp, compiler->read_backward(), on_success, RegExpFlags())));
+}
+
+void AddNonBmpSurrogatePairs(RegExpCompiler* compiler,
+                             ChoiceNode* result,
+                             RegExpNode* on_success,
+                             UnicodeRangeSplitter* splitter) {
+  ZoneGrowableArray<CharacterRange>* non_bmp = splitter->non_bmp();
+  if (non_bmp == nullptr) return;
+  ASSERT(!compiler->one_byte());
+  CharacterRange::Canonicalize(non_bmp);
+  for (int i = 0; i < non_bmp->length(); i++) {
+    // Match surrogate pair.
+    // E.g. [\u10005-\u11005] becomes
+    //      \ud800[\udc05-\udfff]|
+    //      [\ud801-\ud803][\udc00-\udfff]|
+    //      \ud804[\udc00-\udc05]
+    uint32_t from = non_bmp->At(i).from();
+    uint32_t to = non_bmp->At(i).to();
+    uint16_t from_points[2];
+    Utf16::Encode(from, from_points);
+    uint16_t to_points[2];
+    Utf16::Encode(to, to_points);
+    if (from_points[0] == to_points[0]) {
+      // The lead surrogate is the same.
+      result->AddAlternative(
+          GuardedAlternative(TextNode::CreateForSurrogatePair(
+              CharacterRange::Singleton(from_points[0]),
+              CharacterRange::Range(from_points[1], to_points[1]),
+              compiler->read_backward(), on_success, RegExpFlags())));
+    } else {
+      if (from_points[1] != Utf16::kTrailSurrogateStart) {
+        // Add [from_l][from_t-\udfff]
+        result->AddAlternative(
+            GuardedAlternative(TextNode::CreateForSurrogatePair(
+                CharacterRange::Singleton(from_points[0]),
+                CharacterRange::Range(from_points[1],
+                                      Utf16::kTrailSurrogateEnd),
+                compiler->read_backward(), on_success, RegExpFlags())));
+        from_points[0]++;
+      }
+      if (to_points[1] != Utf16::kTrailSurrogateEnd) {
+        // Add [to_l][\udc00-to_t]
+        result->AddAlternative(
+            GuardedAlternative(TextNode::CreateForSurrogatePair(
+                CharacterRange::Singleton(to_points[0]),
+                CharacterRange::Range(Utf16::kTrailSurrogateStart,
+                                      to_points[1]),
+                compiler->read_backward(), on_success, RegExpFlags())));
+        to_points[0]--;
+      }
+      if (from_points[0] <= to_points[0]) {
+        // Add [from_l-to_l][\udc00-\udfff]
+        result->AddAlternative(
+            GuardedAlternative(TextNode::CreateForSurrogatePair(
+                CharacterRange::Range(from_points[0], to_points[0]),
+                CharacterRange::Range(Utf16::kTrailSurrogateStart,
+                                      Utf16::kTrailSurrogateEnd),
+                compiler->read_backward(), on_success, RegExpFlags())));
+      }
+    }
+  }
+}
+
+RegExpNode* NegativeLookaroundAgainstReadDirectionAndMatch(
+    RegExpCompiler* compiler,
+    ZoneGrowableArray<CharacterRange>* lookbehind,
+    ZoneGrowableArray<CharacterRange>* match,
+    RegExpNode* on_success,
+    bool read_backward,
+    RegExpFlags flags) {
+  RegExpNode* match_node = TextNode::CreateForCharacterRanges(
+      match, read_backward, on_success, flags);
+  int stack_register = compiler->UnicodeLookaroundStackRegister();
+  int position_register = compiler->UnicodeLookaroundPositionRegister();
+  RegExpLookaround::Builder lookaround(false, match_node, stack_register,
+                                       position_register);
+  RegExpNode* negative_match = TextNode::CreateForCharacterRanges(
+      lookbehind, !read_backward, lookaround.on_match_success(), flags);
+  return lookaround.ForMatch(negative_match);
+}
+
+RegExpNode* MatchAndNegativeLookaroundInReadDirection(
+    RegExpCompiler* compiler,
+    ZoneGrowableArray<CharacterRange>* match,
+    ZoneGrowableArray<CharacterRange>* lookahead,
+    RegExpNode* on_success,
+    bool read_backward,
+    RegExpFlags flags) {
+  int stack_register = compiler->UnicodeLookaroundStackRegister();
+  int position_register = compiler->UnicodeLookaroundPositionRegister();
+  RegExpLookaround::Builder lookaround(false, on_success, stack_register,
+                                       position_register);
+  RegExpNode* negative_match = TextNode::CreateForCharacterRanges(
+      lookahead, read_backward, lookaround.on_match_success(), flags);
+  return TextNode::CreateForCharacterRanges(
+      match, read_backward, lookaround.ForMatch(negative_match), flags);
+}
+
+void AddLoneLeadSurrogates(RegExpCompiler* compiler,
+                           ChoiceNode* result,
+                           RegExpNode* on_success,
+                           UnicodeRangeSplitter* splitter) {
+  auto lead_surrogates = splitter->lead_surrogates();
+  if (lead_surrogates == nullptr) return;
+  // E.g. \ud801 becomes \ud801(?![\udc00-\udfff]).
+  auto trail_surrogates = CharacterRange::List(
+      on_success->zone(), CharacterRange::Range(Utf16::kTrailSurrogateStart,
+                                                Utf16::kTrailSurrogateEnd));
+
+  RegExpNode* match;
+  if (compiler->read_backward()) {
+    // Reading backward. Assert that reading forward, there is no trail
+    // surrogate, and then backward match the lead surrogate.
+    match = NegativeLookaroundAgainstReadDirectionAndMatch(
+        compiler, trail_surrogates, lead_surrogates, on_success, true,
+        RegExpFlags());
+  } else {
+    // Reading forward. Forward match the lead surrogate and assert that
+    // no trail surrogate follows.
+    match = MatchAndNegativeLookaroundInReadDirection(
+        compiler, lead_surrogates, trail_surrogates, on_success, false,
+        RegExpFlags());
+  }
+  result->AddAlternative(GuardedAlternative(match));
+}
+
+void AddLoneTrailSurrogates(RegExpCompiler* compiler,
+                            ChoiceNode* result,
+                            RegExpNode* on_success,
+                            UnicodeRangeSplitter* splitter) {
+  auto trail_surrogates = splitter->trail_surrogates();
+  if (trail_surrogates == nullptr) return;
+  // E.g. \udc01 becomes (?<![\ud800-\udbff])\udc01
+  auto lead_surrogates = CharacterRange::List(
+      on_success->zone(), CharacterRange::Range(Utf16::kLeadSurrogateStart,
+                                                Utf16::kLeadSurrogateEnd));
+
+  RegExpNode* match;
+  if (compiler->read_backward()) {
+    // Reading backward. Backward match the trail surrogate and assert that no
+    // lead surrogate precedes it.
+    match = MatchAndNegativeLookaroundInReadDirection(
+        compiler, trail_surrogates, lead_surrogates, on_success, true,
+        RegExpFlags());
+  } else {
+    // Reading forward. Assert that reading backward, there is no lead
+    // surrogate, and then forward match the trail surrogate.
+    match = NegativeLookaroundAgainstReadDirectionAndMatch(
+        compiler, lead_surrogates, trail_surrogates, on_success, false,
+        RegExpFlags());
+  }
+  result->AddAlternative(GuardedAlternative(match));
+}
+
+RegExpNode* UnanchoredAdvance(RegExpCompiler* compiler,
+                              RegExpNode* on_success) {
+  // This implements ES2015 21.2.5.2.3, AdvanceStringIndex.
+  ASSERT(!compiler->read_backward());
+  // Advance any character. If the character happens to be a lead surrogate and
+  // we advanced into the middle of a surrogate pair, it will work out, as
+  // nothing will match from there. We will have to advance again, consuming
+  // the associated trail surrogate.
+  auto range = CharacterRange::List(
+      on_success->zone(), CharacterRange::Range(0, Utf16::kMaxCodeUnit));
+  return TextNode::CreateForCharacterRanges(range, false, on_success,
+                                            RegExpFlags());
+}
+
+void AddUnicodeCaseEquivalents(ZoneGrowableArray<CharacterRange>* ranges) {
+  ASSERT(CharacterRange::IsCanonical(ranges));
+
+  // Micro-optimization to avoid passing large ranges to UnicodeSet::closeOver.
+  // See also https://crbug.com/v8/6727.
+  // TODO(sstrickl): This only covers the special case of the {0,0x10FFFF}
+  // range, which we use frequently internally. But large ranges can also easily
+  // be created by the user. We might want to have a more general caching
+  // mechanism for such ranges.
+  if (ranges->length() == 1 && ranges->At(0).IsEverything(Utf::kMaxCodePoint)) {
+    return;
+  }
+
+  icu::UnicodeSet set;
+  for (int i = 0; i < ranges->length(); i++) {
+    set.add(ranges->At(i).from(), ranges->At(i).to());
+  }
+  ranges->Clear();
+  set.closeOver(USET_CASE_INSENSITIVE);
+  // Full case mapping map single characters to multiple characters.
+  // Those are represented as strings in the set. Remove them so that
+  // we end up with only simple and common case mappings.
+  set.removeAllStrings();
+  for (int i = 0; i < set.getRangeCount(); i++) {
+    ranges->Add(
+        CharacterRange::Range(set.getRangeStart(i), set.getRangeEnd(i)));
+  }
+  // No errors and everything we collected have been ranges.
+  CharacterRange::Canonicalize(ranges);
+}
+
 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
                                          RegExpNode* on_success) {
+  set_.Canonicalize();
+  ZoneGrowableArray<CharacterRange>* ranges = this->ranges();
+  if (flags_.NeedsUnicodeCaseEquivalents()) {
+    AddUnicodeCaseEquivalents(ranges);
+  }
+  if (flags_.IsUnicode() && !compiler->one_byte() &&
+      !contains_split_surrogate()) {
+    if (is_negated()) {
+      ZoneGrowableArray<CharacterRange>* negated =
+          new ZoneGrowableArray<CharacterRange>(2);
+      CharacterRange::Negate(ranges, negated);
+      ranges = negated;
+    }
+    if (ranges->length() == 0) {
+      RegExpCharacterClass* fail =
+          new RegExpCharacterClass(ranges, RegExpFlags());
+      return new TextNode(fail, compiler->read_backward(), on_success);
+    }
+    if (standard_type() == '*') {
+      return UnanchoredAdvance(compiler, on_success);
+    } else {
+      ChoiceNode* result = new (OZ) ChoiceNode(2, OZ);
+      UnicodeRangeSplitter splitter(OZ, ranges);
+      AddBmpCharacters(compiler, result, on_success, &splitter);
+      AddNonBmpSurrogatePairs(compiler, result, on_success, &splitter);
+      AddLoneLeadSurrogates(compiler, result, on_success, &splitter);
+      AddLoneTrailSurrogates(compiler, result, on_success, &splitter);
+      return result;
+    }
+  } else {
+    return new TextNode(this, compiler->read_backward(), on_success);
+  }
   return new (OZ) TextNode(this, compiler->read_backward(), on_success);
 }
 
@@ -4014,6 +4374,43 @@
   }
 }
 
+namespace {
+// Desugar \b to (?<=\w)(?=\W)|(?<=\W)(?=\w) and
+//         \B to (?<=\w)(?=\w)|(?<=\W)(?=\W)
+RegExpNode* BoundaryAssertionAsLookaround(RegExpCompiler* compiler,
+                                          RegExpNode* on_success,
+                                          RegExpAssertion::AssertionType type,
+                                          RegExpFlags flags) {
+  ASSERT(flags.NeedsUnicodeCaseEquivalents());
+  ZoneGrowableArray<CharacterRange>* word_range =
+      new ZoneGrowableArray<CharacterRange>(2);
+  CharacterRange::AddClassEscape('w', word_range, true);
+  int stack_register = compiler->UnicodeLookaroundStackRegister();
+  int position_register = compiler->UnicodeLookaroundPositionRegister();
+  ChoiceNode* result = new (OZ) ChoiceNode(2, OZ);
+  // Add two choices. The (non-)boundary could start with a word or
+  // a non-word-character.
+  for (int i = 0; i < 2; i++) {
+    bool lookbehind_for_word = i == 0;
+    bool lookahead_for_word =
+        (type == RegExpAssertion::BOUNDARY) ^ lookbehind_for_word;
+    // Look to the left.
+    RegExpLookaround::Builder lookbehind(lookbehind_for_word, on_success,
+                                         stack_register, position_register);
+    RegExpNode* backward = TextNode::CreateForCharacterRanges(
+        word_range, true, lookbehind.on_match_success(), flags);
+    // Look to the right.
+    RegExpLookaround::Builder lookahead(lookahead_for_word,
+                                        lookbehind.ForMatch(backward),
+                                        stack_register, position_register);
+    RegExpNode* forward = TextNode::CreateForCharacterRanges(
+        word_range, false, lookahead.on_match_success(), flags);
+    result->AddAlternative(GuardedAlternative(lookahead.ForMatch(forward)));
+  }
+  return result;
+}
+}  // anonymous namespace
+
 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler,
                                     RegExpNode* on_success) {
   switch (assertion_type()) {
@@ -4022,9 +4419,15 @@
     case START_OF_INPUT:
       return AssertionNode::AtStart(on_success);
     case BOUNDARY:
-      return AssertionNode::AtBoundary(on_success);
+      return flags_.NeedsUnicodeCaseEquivalents()
+                 ? BoundaryAssertionAsLookaround(compiler, on_success, BOUNDARY,
+                                                 flags_)
+                 : AssertionNode::AtBoundary(on_success);
     case NON_BOUNDARY:
-      return AssertionNode::AtNonBoundary(on_success);
+      return flags_.NeedsUnicodeCaseEquivalents()
+                 ? BoundaryAssertionAsLookaround(compiler, on_success,
+                                                 NON_BOUNDARY, flags_)
+                 : AssertionNode::AtNonBoundary(on_success);
     case END_OF_INPUT:
       return AssertionNode::AtEnd(on_success);
     case END_OF_LINE: {
@@ -4039,7 +4442,8 @@
       ZoneGrowableArray<CharacterRange>* newline_ranges =
           new ZoneGrowableArray<CharacterRange>(3);
       CharacterRange::AddClassEscape('n', newline_ranges);
-      RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n');
+      RegExpCharacterClass* newline_atom =
+          new RegExpCharacterClass('n', RegExpFlags());
       TextNode* newline_matcher =
           new TextNode(newline_atom, /*read_backwards=*/false,
                        ActionNode::PositiveSubmatchSuccess(
@@ -4066,7 +4470,7 @@
 RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler,
                                         RegExpNode* on_success) {
   return new (OZ) BackReferenceNode(RegExpCapture::StartRegister(index()),
-                                    RegExpCapture::EndRegister(index()),
+                                    RegExpCapture::EndRegister(index()), flags_,
                                     compiler->read_backward(), on_success);
 }
 
@@ -4174,24 +4578,24 @@
   return current;
 }
 
-static void AddClass(const intptr_t* elmv,
+static void AddClass(const int32_t* elmv,
                      intptr_t elmc,
                      ZoneGrowableArray<CharacterRange>* ranges) {
   elmc--;
-  ASSERT(elmv[elmc] == 0x10000);
+  ASSERT(elmv[elmc] == kRangeEndMarker);
   for (intptr_t i = 0; i < elmc; i += 2) {
     ASSERT(elmv[i] < elmv[i + 1]);
     ranges->Add(CharacterRange(elmv[i], elmv[i + 1] - 1));
   }
 }
 
-static void AddClassNegated(const intptr_t* elmv,
+static void AddClassNegated(const int32_t* elmv,
                             intptr_t elmc,
                             ZoneGrowableArray<CharacterRange>* ranges) {
   elmc--;
-  ASSERT(elmv[elmc] == 0x10000);
+  ASSERT(elmv[elmc] == kRangeEndMarker);
   ASSERT(elmv[0] != 0x0000);
-  ASSERT(elmv[elmc - 1] != Utf16::kMaxCodeUnit);
+  ASSERT(elmv[elmc - 1] != Utf::kMaxCodePoint);
   uint16_t last = 0x0000;
   for (intptr_t i = 0; i < elmc; i += 2) {
     ASSERT(last <= elmv[i] - 1);
@@ -4199,7 +4603,30 @@
     ranges->Add(CharacterRange(last, elmv[i] - 1));
     last = elmv[i + 1];
   }
-  ranges->Add(CharacterRange(last, Utf16::kMaxCodeUnit));
+  ranges->Add(CharacterRange(last, Utf::kMaxCodePoint));
+}
+
+void CharacterRange::AddClassEscape(uint16_t type,
+                                    ZoneGrowableArray<CharacterRange>* ranges,
+                                    bool add_unicode_case_equivalents) {
+  if (add_unicode_case_equivalents && (type == 'w' || type == 'W')) {
+    // See #sec-runtime-semantics-wordcharacters-abstract-operation
+    // In case of unicode and ignore_case, we need to create the closure over
+    // case equivalent characters before negating.
+    ZoneGrowableArray<CharacterRange>* new_ranges =
+        new ZoneGrowableArray<CharacterRange>(2);
+    AddClass(kWordRanges, kWordRangeCount, new_ranges);
+    AddUnicodeCaseEquivalents(new_ranges);
+    if (type == 'W') {
+      ZoneGrowableArray<CharacterRange>* negated =
+          new ZoneGrowableArray<CharacterRange>(2);
+      CharacterRange::Negate(new_ranges, negated);
+      new_ranges = negated;
+    }
+    ranges->AddArray(*new_ranges);
+    return;
+  }
+  AddClassEscape(type, ranges);
 }
 
 void CharacterRange::AddClassEscape(uint16_t type,
@@ -4246,69 +4673,79 @@
     ZoneGrowableArray<CharacterRange>* ranges,
     bool is_one_byte,
     Zone* zone) {
-  uint16_t bottom = from();
-  uint16_t top = to();
-  if (is_one_byte && !RangeContainsLatin1Equivalents(*this)) {
-    if (bottom > Symbols::kMaxOneCharCodeSymbol) return;
-    if (top > Symbols::kMaxOneCharCodeSymbol) {
-      top = Symbols::kMaxOneCharCodeSymbol;
+  CharacterRange::Canonicalize(ranges);
+  int range_count = ranges->length();
+  for (intptr_t i = 0; i < range_count; i++) {
+    CharacterRange range = ranges->At(i);
+    int32_t bottom = range.from();
+    if (bottom > Utf16::kMaxCodeUnit) continue;
+    int32_t top = Utils::Minimum(range.to(), Utf16::kMaxCodeUnit);
+    // Nothing to be done for surrogates
+    if (bottom >= Utf16::kLeadSurrogateStart &&
+        top <= Utf16::kTrailSurrogateEnd) {
+      continue;
     }
-  }
+    if (is_one_byte && !RangeContainsLatin1Equivalents(range)) {
+      if (bottom > Symbols::kMaxOneCharCodeSymbol) continue;
+      if (top > Symbols::kMaxOneCharCodeSymbol) {
+        top = Symbols::kMaxOneCharCodeSymbol;
+      }
+    }
 
-  unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize;
-  unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange;
-  int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
-  if (top == bottom) {
-    // If this is a singleton we just expand the one character.
-    intptr_t length =
-        jsregexp_uncanonicalize.get(bottom, '\0', chars);  // NOLINT
-    for (intptr_t i = 0; i < length; i++) {
-      uint32_t chr = chars[i];
-      if (chr != bottom) {
-        ranges->Add(CharacterRange::Singleton(chars[i]));
-      }
-    }
-  } else {
-    // If this is a range we expand the characters block by block,
-    // expanding contiguous subranges (blocks) one at a time.
-    // The approach is as follows.  For a given start character we
-    // look up the remainder of the block that contains it (represented
-    // by the end point), for instance we find 'z' if the character
-    // is 'c'.  A block is characterized by the property
-    // that all characters uncanonicalize in the same way, except that
-    // each entry in the result is incremented by the distance from the first
-    // element.  So a-z is a block because 'a' uncanonicalizes to ['a', 'A'] and
-    // the k'th letter uncanonicalizes to ['a' + k, 'A' + k].
-    // Once we've found the end point we look up its uncanonicalization
-    // and produce a range for each element.  For instance for [c-f]
-    // we look up ['z', 'Z'] and produce [c-f] and [C-F].  We then only
-    // add a range if it is not already contained in the input, so [c-f]
-    // will be skipped but [C-F] will be added.  If this range is not
-    // completely contained in a block we do this for all the blocks
-    // covered by the range (handling characters that is not in a block
-    // as a "singleton block").
-    int32_t range[unibrow::Ecma262UnCanonicalize::kMaxWidth];
-    intptr_t pos = bottom;
-    while (pos <= top) {
-      intptr_t length = jsregexp_canonrange.get(pos, '\0', range);
-      uint16_t block_end;
-      if (length == 0) {
-        block_end = pos;
-      } else {
-        ASSERT(length == 1);
-        block_end = range[0];
-      }
-      intptr_t end = (block_end > top) ? top : block_end;
-      length = jsregexp_uncanonicalize.get(block_end, '\0', range);  // NOLINT
+    unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize;
+    unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange;
+    int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+    if (top == bottom) {
+      // If this is a singleton we just expand the one character.
+      intptr_t length = jsregexp_uncanonicalize.get(bottom, '\0', chars);
       for (intptr_t i = 0; i < length; i++) {
-        uint32_t c = range[i];
-        uint16_t range_from = c - (block_end - pos);
-        uint16_t range_to = c - (block_end - end);
-        if (!(bottom <= range_from && range_to <= top)) {
-          ranges->Add(CharacterRange(range_from, range_to));
+        int32_t chr = chars[i];
+        if (chr != bottom) {
+          ranges->Add(CharacterRange::Singleton(chars[i]));
         }
       }
-      pos = end + 1;
+    } else {
+      // If this is a range we expand the characters block by block,
+      // expanding contiguous subranges (blocks) one at a time.
+      // The approach is as follows.  For a given start character we
+      // look up the remainder of the block that contains it (represented
+      // by the end point), for instance we find 'z' if the character
+      // is 'c'.  A block is characterized by the property
+      // that all characters uncanonicalize in the same way, except that
+      // each entry in the result is incremented by the distance from the first
+      // element.  So a-z is a block because 'a' uncanonicalizes to ['a', 'A']
+      // and the k'th letter uncanonicalizes to ['a' + k, 'A' + k].
+      // Once we've found the end point we look up its uncanonicalization
+      // and produce a range for each element.  For instance for [c-f]
+      // we look up ['z', 'Z'] and produce [c-f] and [C-F].  We then only
+      // add a range if it is not already contained in the input, so [c-f]
+      // will be skipped but [C-F] will be added.  If this range is not
+      // completely contained in a block we do this for all the blocks
+      // covered by the range (handling characters that is not in a block
+      // as a "singleton block").
+      int32_t range[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+      intptr_t pos = bottom;
+      while (pos <= top) {
+        intptr_t length = jsregexp_canonrange.get(pos, '\0', range);
+        int32_t block_end;
+        if (length == 0) {
+          block_end = pos;
+        } else {
+          ASSERT(length == 1);
+          block_end = range[0];
+        }
+        intptr_t end = (block_end > top) ? top : block_end;
+        length = jsregexp_uncanonicalize.get(block_end, '\0', range);
+        for (intptr_t i = 0; i < length; i++) {
+          int32_t c = range[i];
+          int32_t range_from = c - (block_end - pos);
+          int32_t range_to = c - (block_end - end);
+          if (!(bottom <= range_from && range_to <= top)) {
+            ranges->Add(CharacterRange(range_from, range_to));
+          }
+        }
+        pos = end + 1;
+      }
     }
   }
 }
@@ -4361,8 +4798,8 @@
   // list[0..count] for the result. Returns the number of resulting
   // canonicalized ranges. Inserting a range may collapse existing ranges into
   // fewer ranges, so the return value can be anything in the range 1..count+1.
-  uint16_t from = insert.from();
-  uint16_t to = insert.to();
+  int32_t from = insert.from();
+  int32_t to = insert.to();
   intptr_t start_pos = 0;
   intptr_t end_pos = count;
   for (intptr_t i = count - 1; i >= 0; i--) {
@@ -4458,7 +4895,7 @@
   ASSERT(CharacterRange::IsCanonical(ranges));
   ASSERT(negated_ranges->length() == 0);
   intptr_t range_count = ranges->length();
-  uint16_t from = 0;
+  uint32_t from = 0;
   intptr_t i = 0;
   if (range_count > 0 && ranges->At(0).from() == 0) {
     from = ranges->At(0).to();
@@ -4470,8 +4907,8 @@
     from = range.to();
     i++;
   }
-  if (from < Utf16::kMaxCodeUnit) {
-    negated_ranges->Add(CharacterRange(from + 1, Utf16::kMaxCodeUnit));
+  if (from < Utf::kMaxCodePoint) {
+    negated_ranges->Add(CharacterRange(from + 1, Utf::kMaxCodePoint));
   }
 }
 
@@ -4488,6 +4925,22 @@
   return false;
 }
 
+OutSet* OutSet::Extend(unsigned value, Zone* zone) {
+  if (Get(value)) return this;
+  if (successors() != nullptr) {
+    for (int i = 0; i < successors()->length(); i++) {
+      OutSet* successor = successors()->At(i);
+      if (successor->Get(value)) return successor;
+    }
+  } else {
+    successors_ = new (zone) ZoneGrowableArray<OutSet*>(2);
+  }
+  OutSet* result = new (zone) OutSet(first_, remaining_);
+  result->Set(value, zone);
+  successors()->Add(result);
+  return result;
+}
+
 void OutSet::Set(unsigned value, Zone* zone) {
   if (value < kFirstLimit) {
     first_ |= (1 << value);
@@ -4512,6 +4965,108 @@
   }
 }
 
+const int32_t DispatchTable::Config::kNoKey = Utf::kInvalidChar;
+
+void DispatchTable::AddRange(CharacterRange full_range,
+                             int32_t value,
+                             Zone* zone) {
+  CharacterRange current = full_range;
+  if (tree()->is_empty()) {
+    // If this is the first range we just insert into the table.
+    ZoneSplayTree<Config>::Locator loc;
+    bool inserted = tree()->Insert(current.from(), &loc);
+    ASSERT(inserted);
+    USE(inserted);
+    loc.set_value(
+        Entry(current.from(), current.to(), empty()->Extend(value, zone)));
+    return;
+  }
+  // First see if there is a range to the left of this one that
+  // overlaps.
+  ZoneSplayTree<Config>::Locator loc;
+  if (tree()->FindGreatestLessThan(current.from(), &loc)) {
+    Entry* entry = &loc.value();
+    // If we've found a range that overlaps with this one, and it
+    // starts strictly to the left of this one, we have to fix it
+    // because the following code only handles ranges that start on
+    // or after the start point of the range we're adding.
+    if (entry->from() < current.from() && entry->to() >= current.from()) {
+      // Snap the overlapping range in half around the start point of
+      // the range we're adding.
+      CharacterRange left =
+          CharacterRange::Range(entry->from(), current.from() - 1);
+      CharacterRange right = CharacterRange::Range(current.from(), entry->to());
+      // The left part of the overlapping range doesn't overlap.
+      // Truncate the whole entry to be just the left part.
+      entry->set_to(left.to());
+      // The right part is the one that overlaps.  We add this part
+      // to the map and let the next step deal with merging it with
+      // the range we're adding.
+      ZoneSplayTree<Config>::Locator loc;
+      bool inserted = tree()->Insert(right.from(), &loc);
+      ASSERT(inserted);
+      USE(inserted);
+      loc.set_value(Entry(right.from(), right.to(), entry->out_set()));
+    }
+  }
+  while (current.is_valid()) {
+    if (tree()->FindLeastGreaterThan(current.from(), &loc) &&
+        (loc.value().from() <= current.to()) &&
+        (loc.value().to() >= current.from())) {
+      Entry* entry = &loc.value();
+      // We have overlap.  If there is space between the start point of
+      // the range we're adding and where the overlapping range starts
+      // then we have to add a range covering just that space.
+      if (current.from() < entry->from()) {
+        ZoneSplayTree<Config>::Locator ins;
+        bool inserted = tree()->Insert(current.from(), &ins);
+        ASSERT(inserted);
+        USE(inserted);
+        ins.set_value(Entry(current.from(), entry->from() - 1,
+                            empty()->Extend(value, zone)));
+        current.set_from(entry->from());
+      }
+      ASSERT(current.from() == entry->from());
+      // If the overlapping range extends beyond the one we want to add
+      // we have to snap the right part off and add it separately.
+      if (entry->to() > current.to()) {
+        ZoneSplayTree<Config>::Locator ins;
+        bool inserted = tree()->Insert(current.to() + 1, &ins);
+        ASSERT(inserted);
+        USE(inserted);
+        ins.set_value(Entry(current.to() + 1, entry->to(), entry->out_set()));
+        entry->set_to(current.to());
+      }
+      ASSERT(entry->to() <= current.to());
+      // The overlapping range is now completely contained by the range
+      // we're adding so we can just update it and move the start point
+      // of the range we're adding just past it.
+      entry->AddValue(value, zone);
+      ASSERT(entry->to() + 1 > current.from());
+      current.set_from(entry->to() + 1);
+    } else {
+      // There is no overlap so we can just add the range
+      ZoneSplayTree<Config>::Locator ins;
+      bool inserted = tree()->Insert(current.from(), &ins);
+      ASSERT(inserted);
+      USE(inserted);
+      ins.set_value(
+          Entry(current.from(), current.to(), empty()->Extend(value, zone)));
+      break;
+    }
+  }
+}
+
+OutSet* DispatchTable::Get(int32_t value) {
+  ZoneSplayTree<Config>::Locator loc;
+  if (!tree()->FindGreatestLessThan(value, &loc)) return empty();
+  Entry* entry = &loc.value();
+  if (value <= entry->to())
+    return entry->out_set();
+  else
+    return empty();
+}
+
 // -------------------------------------------------------------------
 // Analysis
 
@@ -4540,9 +5095,7 @@
 }
 
 void Analysis::VisitText(TextNode* that) {
-  if (ignore_case_) {
-    that->MakeCaseIndependent(is_one_byte_);
-  }
+  that->MakeCaseIndependent(is_one_byte_);
   EnsureAnalyzed(that->on_success());
   if (!has_failed()) {
     that->CalculateOffsets();
@@ -4649,7 +5202,7 @@
           return;
         }
         uint16_t character = atom->data()->At(j);
-        if (bm->compiler()->ignore_case()) {
+        if (atom->flags().IgnoreCase()) {
           int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
           intptr_t length = GetCaseIndependentLetters(
               character, bm->max_char() == Symbols::kMaxOneCharCodeSymbol,
@@ -4669,7 +5222,7 @@
         bm->SetAll(offset);
       } else {
         for (intptr_t k = 0; k < ranges->length(); k++) {
-          CharacterRange& range = (*ranges)[k];
+          const CharacterRange& range = ranges->At(k);
           if (range.from() > max_char) continue;
           intptr_t to =
               Utils::Minimum(max_char, static_cast<intptr_t>(range.to()));
@@ -4688,6 +5241,40 @@
   if (initial_offset == 0) set_bm_info(not_at_start, bm);
 }
 
+RegExpNode* OptionallyStepBackToLeadSurrogate(RegExpCompiler* compiler,
+                                              RegExpNode* on_success,
+                                              RegExpFlags flags) {
+  // If the regexp matching starts within a surrogate pair, step back
+  // to the lead surrogate and start matching from there.
+  ASSERT(!compiler->read_backward());
+  Zone* zone = compiler->zone();
+
+  auto lead_surrogates = CharacterRange::List(
+      on_success->zone(), CharacterRange::Range(Utf16::kLeadSurrogateStart,
+                                                Utf16::kLeadSurrogateEnd));
+  auto trail_surrogates = CharacterRange::List(
+      on_success->zone(), CharacterRange::Range(Utf16::kTrailSurrogateStart,
+                                                Utf16::kTrailSurrogateEnd));
+
+  ChoiceNode* optional_step_back = new (zone) ChoiceNode(2, zone);
+
+  int stack_register = compiler->UnicodeLookaroundStackRegister();
+  int position_register = compiler->UnicodeLookaroundPositionRegister();
+  RegExpNode* step_back = TextNode::CreateForCharacterRanges(
+      lead_surrogates, /*read_backward=*/true, on_success, flags);
+  RegExpLookaround::Builder builder(/*is_positive=*/true, step_back,
+                                    stack_register, position_register);
+  RegExpNode* match_trail = TextNode::CreateForCharacterRanges(
+      trail_surrogates, /*read_backward=*/false, builder.on_match_success(),
+      flags);
+
+  optional_step_back->AddAlternative(
+      GuardedAlternative(builder.ForMatch(match_trail)));
+  optional_step_back->AddAlternative(GuardedAlternative(on_success));
+
+  return optional_step_back;
+}
+
 #if !defined(DART_PRECOMPILED_RUNTIME)
 RegExpEngine::CompilationResult RegExpEngine::CompileIR(
     RegExpCompileData* data,
@@ -4708,10 +5295,10 @@
   ASSERT(!regexp.IsNull());
   ASSERT(!pattern.IsNull());
 
-  const bool ignore_case = regexp.is_ignore_case();
-  const bool is_global = regexp.is_global();
+  const bool is_global = regexp.flags().IsGlobal();
+  const bool is_unicode = regexp.flags().IsUnicode();
 
-  RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte);
+  RegExpCompiler compiler(data->capture_count, is_one_byte);
 
   // TODO(zerny): Frequency sampling is currently disabled because of several
   // issues. We do not want to store subject strings in the regexp object since
@@ -4734,34 +5321,37 @@
     // Add a .*? at the beginning, outside the body capture, unless
     // this expression is anchored at the beginning or is sticky.
     RegExpNode* loop_node = RegExpQuantifier::ToNode(
-        0, RegExpTree::kInfinity, false, new (zone) RegExpCharacterClass('*'),
-        &compiler, captured_body, data->contains_anchor);
+        0, RegExpTree::kInfinity, false,
+        new (zone) RegExpCharacterClass('*', RegExpFlags()), &compiler,
+        captured_body, data->contains_anchor);
 
     if (data->contains_anchor) {
       // Unroll loop once, to take care of the case that might start
       // at the start of input.
       ChoiceNode* first_step_node = new (zone) ChoiceNode(2, zone);
       first_step_node->AddAlternative(GuardedAlternative(captured_body));
-      first_step_node->AddAlternative(GuardedAlternative(
-          new (zone) TextNode(new (zone) RegExpCharacterClass('*'),
-                              /*read_backwards=*/false, loop_node)));
+      first_step_node->AddAlternative(GuardedAlternative(new (zone) TextNode(
+          new (zone) RegExpCharacterClass('*', RegExpFlags()),
+          /*read_backwards=*/false, loop_node)));
       node = first_step_node;
     } else {
       node = loop_node;
     }
   }
   if (is_one_byte) {
-    node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
+    node = node->FilterOneByte(RegExpCompiler::kMaxRecursion);
     // Do it again to propagate the new nodes to places where they were not
     // put because they had not been calculated yet.
     if (node != NULL) {
-      node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
+      node = node->FilterOneByte(RegExpCompiler::kMaxRecursion);
     }
+  } else if (is_unicode && (is_global || is_sticky)) {
+    node = OptionallyStepBackToLeadSurrogate(&compiler, node, regexp.flags());
   }
 
   if (node == NULL) node = new (zone) EndNode(EndNode::BACKTRACK, zone);
   data->node = node;
-  Analysis analysis(ignore_case, is_one_byte);
+  Analysis analysis(is_one_byte);
   analysis.EnsureAnalyzed(node);
   if (analysis.has_failed()) {
     const char* error_message = analysis.error_message();
@@ -4783,10 +5373,13 @@
   }
 
   if (is_global) {
-    macro_assembler->set_global_mode(
-        (data->tree->min_match() > 0)
-            ? RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK
-            : RegExpMacroAssembler::GLOBAL);
+    RegExpMacroAssembler::GlobalMode mode = RegExpMacroAssembler::GLOBAL;
+    if (data->tree->min_match() > 0) {
+      mode = RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK;
+    } else if (is_unicode) {
+      mode = RegExpMacroAssembler::GLOBAL_UNICODE;
+    }
+    macro_assembler->set_global_mode(mode);
   }
 
   RegExpEngine::CompilationResult result =
@@ -4812,10 +5405,10 @@
   ASSERT(!regexp.IsNull());
   ASSERT(!pattern.IsNull());
 
-  const bool ignore_case = regexp.is_ignore_case();
-  const bool is_global = regexp.is_global();
+  const bool is_global = regexp.flags().IsGlobal();
+  const bool is_unicode = regexp.flags().IsUnicode();
 
-  RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte);
+  RegExpCompiler compiler(data->capture_count, is_one_byte);
 
   // TODO(zerny): Frequency sampling is currently disabled because of several
   // issues. We do not want to store subject strings in the regexp object since
@@ -4838,34 +5431,37 @@
     // Add a .*? at the beginning, outside the body capture, unless
     // this expression is anchored at the beginning.
     RegExpNode* loop_node = RegExpQuantifier::ToNode(
-        0, RegExpTree::kInfinity, false, new (zone) RegExpCharacterClass('*'),
-        &compiler, captured_body, data->contains_anchor);
+        0, RegExpTree::kInfinity, false,
+        new (zone) RegExpCharacterClass('*', RegExpFlags()), &compiler,
+        captured_body, data->contains_anchor);
 
     if (data->contains_anchor) {
       // Unroll loop once, to take care of the case that might start
       // at the start of input.
       ChoiceNode* first_step_node = new (zone) ChoiceNode(2, zone);
       first_step_node->AddAlternative(GuardedAlternative(captured_body));
-      first_step_node->AddAlternative(GuardedAlternative(
-          new (zone) TextNode(new (zone) RegExpCharacterClass('*'),
-                              /*read_backwards=*/false, loop_node)));
+      first_step_node->AddAlternative(GuardedAlternative(new (zone) TextNode(
+          new (zone) RegExpCharacterClass('*', RegExpFlags()),
+          /*read_backwards=*/false, loop_node)));
       node = first_step_node;
     } else {
       node = loop_node;
     }
   }
   if (is_one_byte) {
-    node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
+    node = node->FilterOneByte(RegExpCompiler::kMaxRecursion);
     // Do it again to propagate the new nodes to places where they were not
     // put because they had not been calculated yet.
     if (node != NULL) {
-      node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
+      node = node->FilterOneByte(RegExpCompiler::kMaxRecursion);
     }
+  } else if (is_unicode && (is_global || is_sticky)) {
+    node = OptionallyStepBackToLeadSurrogate(&compiler, node, regexp.flags());
   }
 
   if (node == NULL) node = new (zone) EndNode(EndNode::BACKTRACK, zone);
   data->node = node;
-  Analysis analysis(ignore_case, is_one_byte);
+  Analysis analysis(is_one_byte);
   analysis.EnsureAnalyzed(node);
   if (analysis.has_failed()) {
     const char* error_message = analysis.error_message();
@@ -4887,10 +5483,13 @@
   }
 
   if (is_global) {
-    macro_assembler->set_global_mode(
-        (data->tree->min_match() > 0)
-            ? RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK
-            : RegExpMacroAssembler::GLOBAL);
+    RegExpMacroAssembler::GlobalMode mode = RegExpMacroAssembler::GLOBAL;
+    if (data->tree->min_match() > 0) {
+      mode = RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK;
+    } else if (is_unicode) {
+      mode = RegExpMacroAssembler::GLOBAL_UNICODE;
+    }
+    macro_assembler->set_global_mode(mode);
   }
 
   RegExpEngine::CompilationResult result =
@@ -4952,19 +5551,12 @@
 
 RawRegExp* RegExpEngine::CreateRegExp(Thread* thread,
                                       const String& pattern,
-                                      bool multi_line,
-                                      bool ignore_case) {
+                                      RegExpFlags flags) {
   Zone* zone = thread->zone();
   const RegExp& regexp = RegExp::Handle(RegExp::New());
 
   regexp.set_pattern(pattern);
-
-  if (multi_line) {
-    regexp.set_is_multi_line();
-  }
-  if (ignore_case) {
-    regexp.set_is_ignore_case();
-  }
+  regexp.set_flags(flags);
 
   // TODO(zerny): We might want to use normal string searching algorithms
   // for simple patterns.
diff --git a/runtime/vm/regexp.h b/runtime/vm/regexp.h
index 092a06a..febcb91 100644
--- a/runtime/vm/regexp.h
+++ b/runtime/vm/regexp.h
@@ -5,11 +5,14 @@
 #ifndef RUNTIME_VM_REGEXP_H_
 #define RUNTIME_VM_REGEXP_H_
 
+#include "platform/unicode.h"
+
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/backend/flow_graph_compiler.h"
 #include "vm/compiler/backend/il.h"
 #include "vm/object.h"
 #include "vm/regexp_assembler.h"
+#include "vm/splay-tree.h"
 
 namespace dart {
 
@@ -25,32 +28,42 @@
 class CharacterRange {
  public:
   CharacterRange() : from_(0), to_(0) {}
-  CharacterRange(uint16_t from, uint16_t to) : from_(from), to_(to) {}
+  CharacterRange(int32_t from, int32_t to) : from_(from), to_(to) {}
 
   static void AddClassEscape(uint16_t type,
                              ZoneGrowableArray<CharacterRange>* ranges);
+  // Add class escapes with case equivalent closure for \w and \W if necessary.
+  static void AddClassEscape(uint16_t type,
+                             ZoneGrowableArray<CharacterRange>* ranges,
+                             bool add_unicode_case_equivalents);
   static GrowableArray<const intptr_t> GetWordBounds();
-  static inline CharacterRange Singleton(uint16_t value) {
+  static inline CharacterRange Singleton(int32_t value) {
     return CharacterRange(value, value);
   }
-  static inline CharacterRange Range(uint16_t from, uint16_t to) {
+  static inline CharacterRange Range(int32_t from, int32_t to) {
     ASSERT(from <= to);
     return CharacterRange(from, to);
   }
   static inline CharacterRange Everything() {
-    return CharacterRange(0, 0xFFFF);
+    return CharacterRange(0, Utf::kMaxCodePoint);
   }
-  bool Contains(uint16_t i) const { return from_ <= i && i <= to_; }
-  uint16_t from() const { return from_; }
-  void set_from(uint16_t value) { from_ = value; }
-  uint16_t to() const { return to_; }
-  void set_to(uint16_t value) { to_ = value; }
+  static inline ZoneGrowableArray<CharacterRange>* List(Zone* zone,
+                                                        CharacterRange range) {
+    auto list = new (zone) ZoneGrowableArray<CharacterRange>(1);
+    list->Add(range);
+    return list;
+  }
+  bool Contains(int32_t i) const { return from_ <= i && i <= to_; }
+  int32_t from() const { return from_; }
+  void set_from(int32_t value) { from_ = value; }
+  int32_t to() const { return to_; }
+  void set_to(int32_t value) { to_ = value; }
   bool is_valid() const { return from_ <= to_; }
-  bool IsEverything(uint16_t max) const { return from_ == 0 && to_ >= max; }
+  bool IsEverything(int32_t max) const { return from_ == 0 && to_ >= max; }
   bool IsSingleton() const { return (from_ == to_); }
-  void AddCaseEquivalents(ZoneGrowableArray<CharacterRange>* ranges,
-                          bool is_one_byte,
-                          Zone* zone);
+  static void AddCaseEquivalents(ZoneGrowableArray<CharacterRange>* ranges,
+                                 bool is_one_byte,
+                                 Zone* zone);
   static void Split(ZoneGrowableArray<CharacterRange>* base,
                     GrowableArray<const intptr_t> overlay,
                     ZoneGrowableArray<CharacterRange>** included,
@@ -71,8 +84,8 @@
   static const intptr_t kPayloadMask = (1 << 24) - 1;
 
  private:
-  uint16_t from_;
-  uint16_t to_;
+  int32_t from_;
+  int32_t to_;
 
   DISALLOW_ALLOCATION();
 };
@@ -105,6 +118,98 @@
   friend class Trace;
 };
 
+// A mapping from integers, specified as ranges, to a set of integers.
+// Used for mapping character ranges to choices.
+class DispatchTable : public ValueObject {
+ public:
+  explicit DispatchTable(Zone* zone) : tree_(zone) {}
+
+  class Entry {
+   public:
+    Entry() : from_(0), to_(0), out_set_(nullptr) {}
+    Entry(int32_t from, int32_t to, OutSet* out_set)
+        : from_(from), to_(to), out_set_(out_set) {
+      ASSERT(from <= to);
+    }
+    int32_t from() { return from_; }
+    int32_t to() { return to_; }
+    void set_to(int32_t value) { to_ = value; }
+    void AddValue(int value, Zone* zone) {
+      out_set_ = out_set_->Extend(value, zone);
+    }
+    OutSet* out_set() { return out_set_; }
+
+   private:
+    int32_t from_;
+    int32_t to_;
+    OutSet* out_set_;
+  };
+
+  class Config {
+   public:
+    typedef int32_t Key;
+    typedef Entry Value;
+    static const int32_t kNoKey;
+    static const Entry NoValue() { return Value(); }
+    static inline int Compare(int32_t a, int32_t b) {
+      if (a == b)
+        return 0;
+      else if (a < b)
+        return -1;
+      else
+        return 1;
+    }
+  };
+
+  void AddRange(CharacterRange range, int32_t value, Zone* zone);
+  OutSet* Get(int32_t value);
+  void Dump();
+
+  template <typename Callback>
+  void ForEach(Callback* callback) {
+    return tree()->ForEach(callback);
+  }
+
+ private:
+  // There can't be a static empty set since it allocates its
+  // successors in a zone and caches them.
+  OutSet* empty() { return &empty_; }
+  OutSet empty_;
+  ZoneSplayTree<Config>* tree() { return &tree_; }
+  ZoneSplayTree<Config> tree_;
+};
+
+// Categorizes character ranges into BMP, non-BMP, lead, and trail surrogates.
+class UnicodeRangeSplitter : public ValueObject {
+ public:
+  UnicodeRangeSplitter(Zone* zone, ZoneGrowableArray<CharacterRange>* base);
+  void Call(uint32_t from, DispatchTable::Entry entry);
+
+  ZoneGrowableArray<CharacterRange>* bmp() { return bmp_; }
+  ZoneGrowableArray<CharacterRange>* lead_surrogates() {
+    return lead_surrogates_;
+  }
+  ZoneGrowableArray<CharacterRange>* trail_surrogates() {
+    return trail_surrogates_;
+  }
+  ZoneGrowableArray<CharacterRange>* non_bmp() const { return non_bmp_; }
+
+ private:
+  static const int kBase = 0;
+  // Separate ranges into
+  static const int kBmpCodePoints = 1;
+  static const int kLeadSurrogates = 2;
+  static const int kTrailSurrogates = 3;
+  static const int kNonBmpCodePoints = 4;
+
+  Zone* zone_;
+  DispatchTable table_;
+  ZoneGrowableArray<CharacterRange>* bmp_;
+  ZoneGrowableArray<CharacterRange>* lead_surrogates_;
+  ZoneGrowableArray<CharacterRange>* trail_surrogates_;
+  ZoneGrowableArray<CharacterRange>* non_bmp_;
+};
+
 #define FOR_EACH_NODE_TYPE(VISIT)                                              \
   VISIT(End)                                                                   \
   VISIT(Action)                                                                \
@@ -344,9 +449,7 @@
   // If we know that the input is one-byte then there are some nodes that can
   // never match.  This method returns a node that can be substituted for
   // itself, or NULL if the node can never match.
-  virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case) {
-    return this;
-  }
+  virtual RegExpNode* FilterOneByte(intptr_t depth) { return this; }
   // Helper for FilterOneByte.
   RegExpNode* replacement() {
     ASSERT(info()->replacement_calculated);
@@ -443,7 +546,7 @@
       : RegExpNode(on_success->zone()), on_success_(on_success) {}
   RegExpNode* on_success() { return on_success_; }
   void set_on_success(RegExpNode* node) { on_success_ = node; }
-  virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case);
+  virtual RegExpNode* FilterOneByte(intptr_t depth);
   virtual void FillInBMInfo(intptr_t offset,
                             intptr_t budget,
                             BoyerMooreLookahead* bm,
@@ -453,7 +556,7 @@
   }
 
  protected:
-  RegExpNode* FilterSuccessor(intptr_t depth, bool ignore_case);
+  RegExpNode* FilterSuccessor(intptr_t depth);
 
  private:
   RegExpNode* on_success_;
@@ -561,6 +664,19 @@
         read_backward_(read_backward) {
     elms_->Add(TextElement::CharClass(that));
   }
+  // Create TextNode for a single character class for the given ranges.
+  static TextNode* CreateForCharacterRanges(
+      ZoneGrowableArray<CharacterRange>* ranges,
+      bool read_backward,
+      RegExpNode* on_success,
+      RegExpFlags flags);
+  // Create TextNode for a surrogate pair with a range given for the
+  // lead and the trail surrogate each.
+  static TextNode* CreateForSurrogatePair(CharacterRange lead,
+                                          CharacterRange trail,
+                                          bool read_backward,
+                                          RegExpNode* on_success,
+                                          RegExpFlags flags);
   virtual void Accept(NodeVisitor* visitor);
   virtual void Emit(RegExpCompiler* compiler, Trace* trace);
   virtual intptr_t EatsAtLeast(intptr_t still_to_find,
@@ -581,7 +697,7 @@
                             BoyerMooreLookahead* bm,
                             bool not_at_start);
   void CalculateOffsets();
-  virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case);
+  virtual RegExpNode* FilterOneByte(intptr_t depth);
 
  private:
   enum TextEmitPassType {
@@ -659,11 +775,13 @@
  public:
   BackReferenceNode(intptr_t start_reg,
                     intptr_t end_reg,
+                    RegExpFlags flags,
                     bool read_backward,
                     RegExpNode* on_success)
       : SeqRegExpNode(on_success),
         start_reg_(start_reg),
         end_reg_(end_reg),
+        flags_(flags),
         read_backward_(read_backward) {}
   virtual void Accept(NodeVisitor* visitor);
   intptr_t start_register() { return start_reg_; }
@@ -687,6 +805,7 @@
  private:
   intptr_t start_reg_;
   intptr_t end_reg_;
+  RegExpFlags flags_;
   bool read_backward_;
 };
 
@@ -761,9 +880,9 @@
  public:
   explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) {}
   void AddGuard(Guard* guard, Zone* zone);
-  RegExpNode* node() { return node_; }
+  RegExpNode* node() const { return node_; }
   void set_node(RegExpNode* node) { node_ = node; }
-  ZoneGrowableArray<Guard*>* guards() { return guards_; }
+  ZoneGrowableArray<Guard*>* guards() const { return guards_; }
 
  private:
   RegExpNode* node_;
@@ -811,11 +930,12 @@
   virtual bool try_to_emit_quick_check_for_alternative(bool is_first) {
     return true;
   }
-  virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case);
+  virtual RegExpNode* FilterOneByte(intptr_t depth);
   virtual bool read_backward() { return false; }
 
  protected:
-  intptr_t GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative);
+  intptr_t GreedyLoopTextLengthForAlternative(
+      const GuardedAlternative* alternative);
   ZoneGrowableArray<GuardedAlternative>* alternatives_;
 
  private:
@@ -886,7 +1006,7 @@
   virtual bool try_to_emit_quick_check_for_alternative(bool is_first) {
     return !is_first;
   }
-  virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case);
+  virtual RegExpNode* FilterOneByte(intptr_t depth);
 };
 
 class LoopChoiceNode : public ChoiceNode {
@@ -918,7 +1038,7 @@
   bool body_can_be_zero_length() { return body_can_be_zero_length_; }
   virtual bool read_backward() { return read_backward_; }
   virtual void Accept(NodeVisitor* visitor);
-  virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case);
+  virtual RegExpNode* FilterOneByte(intptr_t depth);
 
  private:
   // AddAlternative is made private for loop nodes because alternatives
@@ -1286,10 +1406,8 @@
 //   +-------+        +------------+
 class Analysis : public NodeVisitor {
  public:
-  Analysis(bool ignore_case, bool is_one_byte)
-      : ignore_case_(ignore_case),
-        is_one_byte_(is_one_byte),
-        error_message_(NULL) {}
+  explicit Analysis(bool is_one_byte)
+      : is_one_byte_(is_one_byte), error_message_(NULL) {}
   void EnsureAnalyzed(RegExpNode* node);
 
 #define DECLARE_VISIT(Type) virtual void Visit##Type(Type##Node* that);
@@ -1305,7 +1423,6 @@
   void fail(const char* error_message) { error_message_ = error_message; }
 
  private:
-  bool ignore_case_;
   bool is_one_byte_;
   const char* error_message_;
 
@@ -1398,8 +1515,7 @@
 
   static RawRegExp* CreateRegExp(Thread* thread,
                                  const String& pattern,
-                                 bool multi_line,
-                                 bool ignore_case);
+                                 RegExpFlags flags);
 
   static void DotPrint(const char* label, RegExpNode* node, bool ignore_case);
 };
diff --git a/runtime/vm/regexp_assembler.cc b/runtime/vm/regexp_assembler.cc
index fb7dc74..ab242c4 100644
--- a/runtime/vm/regexp_assembler.cc
+++ b/runtime/vm/regexp_assembler.cc
@@ -4,6 +4,10 @@
 
 #include "vm/regexp_assembler.h"
 
+#include "unicode/uchar.h"
+
+#include "platform/unicode.h"
+
 #include "vm/flags.h"
 #include "vm/regexp.h"
 #include "vm/unibrow-inl.h"
@@ -16,11 +20,10 @@
   OS::PrintErr(format, c);
 }
 
-
-static RawBool* CaseInsensitiveCompareUC16(RawString* str_raw,
-                                           RawSmi* lhs_index_raw,
-                                           RawSmi* rhs_index_raw,
-                                           RawSmi* length_raw) {
+RawBool* CaseInsensitiveCompareUCS2(RawString* str_raw,
+                                    RawSmi* lhs_index_raw,
+                                    RawSmi* rhs_index_raw,
+                                    RawSmi* length_raw) {
   const String& str = String::Handle(str_raw);
   const Smi& lhs_index = Smi::Handle(lhs_index_raw);
   const Smi& rhs_index = Smi::Handle(rhs_index_raw);
@@ -48,13 +51,50 @@
   return Bool::True().raw();
 }
 
+RawBool* CaseInsensitiveCompareUTF16(RawString* str_raw,
+                                     RawSmi* lhs_index_raw,
+                                     RawSmi* rhs_index_raw,
+                                     RawSmi* length_raw) {
+  const String& str = String::Handle(str_raw);
+  const Smi& lhs_index = Smi::Handle(lhs_index_raw);
+  const Smi& rhs_index = Smi::Handle(rhs_index_raw);
+  const Smi& length = Smi::Handle(length_raw);
+
+  for (intptr_t i = 0; i < length.Value(); i++) {
+    int32_t c1 = str.CharAt(lhs_index.Value() + i);
+    int32_t c2 = str.CharAt(rhs_index.Value() + i);
+    if (Utf16::IsLeadSurrogate(c1)) {
+      // Non-BMP characters do not have case-equivalents in the BMP.
+      // Both have to be non-BMP for them to be able to match.
+      if (!Utf16::IsLeadSurrogate(c2)) return Bool::False().raw();
+      if (i + 1 < length.Value()) {
+        uint16_t c1t = str.CharAt(lhs_index.Value() + i + 1);
+        uint16_t c2t = str.CharAt(rhs_index.Value() + i + 1);
+        if (Utf16::IsTrailSurrogate(c1t) && Utf16::IsTrailSurrogate(c2t)) {
+          c1 = Utf16::Decode(c1, c1t);
+          c2 = Utf16::Decode(c2, c2t);
+          i++;
+        }
+      }
+    }
+    c1 = u_foldCase(c1, U_FOLD_CASE_DEFAULT);
+    c2 = u_foldCase(c2, U_FOLD_CASE_DEFAULT);
+    if (c1 != c2) return Bool::False().raw();
+  }
+  return Bool::True().raw();
+}
 
 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
-    CaseInsensitiveCompareUC16,
+    CaseInsensitiveCompareUCS2,
     4,
     false /* is_float */,
-    reinterpret_cast<RuntimeFunction>(&CaseInsensitiveCompareUC16));
+    reinterpret_cast<RuntimeFunction>(&CaseInsensitiveCompareUCS2));
 
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(
+    CaseInsensitiveCompareUTF16,
+    4,
+    false /* is_float */,
+    reinterpret_cast<RuntimeFunction>(&CaseInsensitiveCompareUTF16));
 
 BlockLabel::BlockLabel()
     : block_(NULL), is_bound_(false), is_linked_(false), pos_(-1) {
@@ -72,4 +112,18 @@
 
 RegExpMacroAssembler::~RegExpMacroAssembler() {}
 
+void RegExpMacroAssembler::CheckNotInSurrogatePair(intptr_t cp_offset,
+                                                   BlockLabel* on_failure) {
+  BlockLabel ok;
+  // Check that current character is not a trail surrogate.
+  LoadCurrentCharacter(cp_offset, &ok);
+  CheckCharacterNotInRange(Utf16::kTrailSurrogateStart,
+                           Utf16::kTrailSurrogateEnd, &ok);
+  // Check that previous character is not a lead surrogate.
+  LoadCurrentCharacter(cp_offset - 1, &ok);
+  CheckCharacterInRange(Utf16::kLeadSurrogateStart, Utf16::kLeadSurrogateEnd,
+                        on_failure);
+  BindBlock(&ok);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/regexp_assembler.h b/runtime/vm/regexp_assembler.h
index a7b087e..818f573 100644
--- a/runtime/vm/regexp_assembler.h
+++ b/runtime/vm/regexp_assembler.h
@@ -13,6 +13,19 @@
 
 // Utility function for the DotPrinter
 void PrintUtf16(uint16_t c);
+// Compares two-byte strings case insensitively as UCS2.
+// Called from generated RegExp code.
+RawBool* CaseInsensitiveCompareUCS2(RawString* str_raw,
+                                    RawSmi* lhs_index_raw,
+                                    RawSmi* rhs_index_raw,
+                                    RawSmi* length_raw);
+
+// Compares two-byte strings case insensitively as UTF16.
+// Called from generated RegExp code.
+RawBool* CaseInsensitiveCompareUTF16(RawString* str_raw,
+                                     RawSmi* lhs_index_raw,
+                                     RawSmi* rhs_index_raw,
+                                     RawSmi* length_raw);
 
 /// Convenience wrapper around a BlockEntryInstr pointer.
 class BlockLabel : public ValueObject {
@@ -127,6 +140,7 @@
                                      BlockLabel* on_no_match) = 0;
   virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
                                                bool read_backward,
+                                               bool unicode,
                                                BlockLabel* on_no_match) = 0;
   // Check the current character for a match with a literal character.  If we
   // fail to match then goto the on_failure label.  End of input always
@@ -215,22 +229,33 @@
   virtual void ClearRegisters(intptr_t reg_from, intptr_t reg_to) = 0;
   virtual void WriteStackPointerToRegister(intptr_t reg) = 0;
 
+  // Check that we are not in the middle of a surrogate pair.
+  void CheckNotInSurrogatePair(intptr_t cp_offset, BlockLabel* on_failure);
+
   // Controls the generation of large inlined constants in the code.
   void set_slow_safe(bool ssc) { slow_safe_compiler_ = ssc; }
   bool slow_safe() { return slow_safe_compiler_; }
 
-  enum GlobalMode { NOT_GLOBAL, GLOBAL, GLOBAL_NO_ZERO_LENGTH_CHECK };
+  enum GlobalMode {
+    NOT_GLOBAL,
+    GLOBAL,
+    GLOBAL_NO_ZERO_LENGTH_CHECK,
+    GLOBAL_UNICODE
+  };
   // Set whether the regular expression has the global flag.  Exiting due to
   // a failure in a global regexp may still mean success overall.
   inline void set_global_mode(GlobalMode mode) { global_mode_ = mode; }
   inline bool global() { return global_mode_ != NOT_GLOBAL; }
-  inline bool global_with_zero_length_check() { return global_mode_ == GLOBAL; }
+  inline bool global_with_zero_length_check() {
+    return global_mode_ == GLOBAL || global_mode_ == GLOBAL_UNICODE;
+  }
+  inline bool global_unicode() { return global_mode_ == GLOBAL_UNICODE; }
 
   Zone* zone() const { return zone_; }
 
  private:
   bool slow_safe_compiler_;
-  bool global_mode_;
+  GlobalMode global_mode_;
   Zone* zone_;
 };
 
diff --git a/runtime/vm/regexp_assembler_bytecode.cc b/runtime/vm/regexp_assembler_bytecode.cc
index 8288e1b..0318a27 100644
--- a/runtime/vm/regexp_assembler_bytecode.cc
+++ b/runtime/vm/regexp_assembler_bytecode.cc
@@ -349,11 +349,14 @@
 void BytecodeRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(
     intptr_t start_reg,
     bool read_backward,
+    bool unicode,
     BlockLabel* on_not_equal) {
   ASSERT(start_reg >= 0);
   ASSERT(start_reg <= kMaxRegister);
-  Emit(read_backward ? BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD
-                     : BC_CHECK_NOT_BACK_REF_NO_CASE,
+  Emit(read_backward ? (unicode ? BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD
+                                : BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD)
+                     : (unicode ? BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE
+                                : BC_CHECK_NOT_BACK_REF_NO_CASE),
        start_reg);
   EmitOrLink(on_not_equal);
 }
@@ -434,11 +437,10 @@
     }
 #endif  // !defined(PRODUCT)
 
-    const bool multiline = regexp.is_multi_line();
     RegExpCompileData* compile_data = new (zone) RegExpCompileData();
 
     // Parsing failures are handled in the RegExp factory constructor.
-    RegExpParser::ParseRegExp(pattern, multiline, compile_data);
+    RegExpParser::ParseRegExp(pattern, regexp.flags(), compile_data);
 
     regexp.set_num_bracket_expressions(compile_data->capture_count);
     regexp.set_capture_name_map(compile_data->capture_name_map);
@@ -451,15 +453,15 @@
     RegExpEngine::CompilationResult result = RegExpEngine::CompileBytecode(
         compile_data, regexp, is_one_byte, sticky, zone);
     ASSERT(result.bytecode != NULL);
-    ASSERT((regexp.num_registers() == -1) ||
-           (regexp.num_registers() == result.num_registers));
-    regexp.set_num_registers(result.num_registers);
+    ASSERT(regexp.num_registers(is_one_byte) == -1 ||
+           regexp.num_registers(is_one_byte) == result.num_registers);
+    regexp.set_num_registers(is_one_byte, result.num_registers);
     regexp.set_bytecode(is_one_byte, sticky, *(result.bytecode));
   }
 
-  ASSERT(regexp.num_registers() != -1);
+  ASSERT(regexp.num_registers(is_one_byte) != -1);
 
-  return regexp.num_registers() +
+  return regexp.num_registers(is_one_byte) +
          (Smi::Value(regexp.num_bracket_expressions()) + 1) * 2;
 }
 
diff --git a/runtime/vm/regexp_assembler_bytecode.h b/runtime/vm/regexp_assembler_bytecode.h
index 3e17d49..59cf68f 100644
--- a/runtime/vm/regexp_assembler_bytecode.h
+++ b/runtime/vm/regexp_assembler_bytecode.h
@@ -83,6 +83,7 @@
                                      BlockLabel* on_no_match);
   virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
                                                bool read_backward,
+                                               bool unicode,
                                                BlockLabel* on_no_match);
   virtual void IfRegisterLT(intptr_t register_index,
                             intptr_t comparand,
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index f54d840..f7f18ac 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -6,6 +6,7 @@
 
 #include "vm/regexp_assembler_ir.h"
 
+#include "platform/unicode.h"
 #include "vm/bit_vector.h"
 #include "vm/compiler/backend/il_printer.h"
 #include "vm/compiler/frontend/flow_graph_builder.h"
@@ -17,7 +18,6 @@
 #include "vm/resolver.h"
 #include "vm/runtime_entry.h"
 #include "vm/stack_frame.h"
-#include "vm/unicode.h"
 
 #define Z zone()
 
@@ -821,6 +821,7 @@
 void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(
     intptr_t start_reg,
     bool read_backward,
+    bool unicode,
     BlockLabel* on_no_match) {
   TAG();
   ASSERT(start_reg + 1 <= registers_count_);
@@ -967,9 +968,17 @@
     Value* rhs_index_value = Bind(LoadLocal(capture_start_index_));
     Value* length_value = Bind(LoadLocal(capture_length_));
 
-    Definition* is_match_def = new (Z) CaseInsensitiveCompareUC16Instr(
-        string_value, lhs_index_value, rhs_index_value, length_value,
-        specialization_cid_);
+    Definition* is_match_def;
+
+    if (unicode) {
+      is_match_def = new (Z) CaseInsensitiveCompareInstr(
+          string_value, lhs_index_value, rhs_index_value, length_value,
+          kCaseInsensitiveCompareUTF16RuntimeEntry, specialization_cid_);
+    } else {
+      is_match_def = new (Z) CaseInsensitiveCompareInstr(
+          string_value, lhs_index_value, rhs_index_value, length_value,
+          kCaseInsensitiveCompareUCS2RuntimeEntry, specialization_cid_);
+    }
 
     BranchOrBacktrack(Comparison(kNE, is_match_def, BoolConstant(true)),
                       on_no_match);
diff --git a/runtime/vm/regexp_assembler_ir.h b/runtime/vm/regexp_assembler_ir.h
index c4f6e1f..d8c222a 100644
--- a/runtime/vm/regexp_assembler_ir.h
+++ b/runtime/vm/regexp_assembler_ir.h
@@ -67,6 +67,7 @@
                                      BlockLabel* on_no_match);
   virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
                                                bool read_backward,
+                                               bool unicode,
                                                BlockLabel* on_no_match);
   virtual void CheckNotCharacter(uint32_t c, BlockLabel* on_not_equal);
   virtual void CheckNotCharacterAfterAnd(uint32_t c,
diff --git a/runtime/vm/regexp_ast.h b/runtime/vm/regexp_ast.h
index 17a175e..4fb64a3 100644
--- a/runtime/vm/regexp_ast.h
+++ b/runtime/vm/regexp_ast.h
@@ -108,7 +108,8 @@
     BOUNDARY,
     NON_BOUNDARY
   };
-  explicit RegExpAssertion(AssertionType type) : assertion_type_(type) {}
+  RegExpAssertion(AssertionType type, RegExpFlags flags)
+      : assertion_type_(type), flags_(flags) {}
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success);
   virtual RegExpAssertion* AsAssertion();
@@ -121,6 +122,7 @@
 
  private:
   AssertionType assertion_type_;
+  RegExpFlags flags_;
 };
 
 class CharacterSet : public ValueObject {
@@ -150,18 +152,40 @@
 
 class RegExpCharacterClass : public RegExpTree {
  public:
-  RegExpCharacterClass(ZoneGrowableArray<CharacterRange>* ranges,
-                       bool is_negated)
-      : set_(ranges), is_negated_(is_negated) {}
-  explicit RegExpCharacterClass(uint16_t type)
-      : set_(type), is_negated_(false) {}
+  enum Flag {
+    // The character class is negated and should match everything but the
+    // specified ranges.
+    NEGATED = 1 << 0,
+    // The character class contains part of a split surrogate and should not
+    // be unicode-desugared.
+    CONTAINS_SPLIT_SURROGATE = 1 << 1,
+  };
+  using CharacterClassFlags = intptr_t;
+  static inline CharacterClassFlags DefaultFlags() { return 0; }
+
+  RegExpCharacterClass(
+      ZoneGrowableArray<CharacterRange>* ranges,
+      RegExpFlags flags,
+      CharacterClassFlags character_class_flags = DefaultFlags())
+      : set_(ranges),
+        flags_(flags),
+        character_class_flags_(character_class_flags) {
+    // Convert the empty set of ranges to the negated Everything() range.
+    if (ranges->is_empty()) {
+      ranges->Add(CharacterRange::Everything());
+      character_class_flags_ ^= NEGATED;
+    }
+  }
+  RegExpCharacterClass(uint16_t type, RegExpFlags flags)
+      : set_(type), flags_(flags), character_class_flags_(0) {}
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success);
   virtual RegExpCharacterClass* AsCharacterClass();
   virtual bool IsCharacterClass() const;
   virtual bool IsTextElement() const { return true; }
   virtual intptr_t min_match() const { return 1; }
-  virtual intptr_t max_match() const { return 1; }
+  // The character class may match two code units for unicode regexps.
+  virtual intptr_t max_match() const { return 2; }
   virtual void AppendToText(RegExpText* text);
   CharacterSet character_set() const { return set_; }
   // TODO(lrn): Remove need for complex version if is_standard that
@@ -180,16 +204,22 @@
   // * : All characters
   uint16_t standard_type() const { return set_.standard_set_type(); }
   ZoneGrowableArray<CharacterRange>* ranges() { return set_.ranges(); }
-  bool is_negated() const { return is_negated_; }
+  bool is_negated() const { return character_class_flags_ & NEGATED; }
+  RegExpFlags flags() const { return flags_; }
+  bool contains_split_surrogate() const {
+    return character_class_flags_ & CONTAINS_SPLIT_SURROGATE;
+  }
 
  private:
   CharacterSet set_;
-  bool is_negated_;
+  RegExpFlags flags_;
+  CharacterClassFlags character_class_flags_;
 };
 
 class RegExpAtom : public RegExpTree {
  public:
-  explicit RegExpAtom(ZoneGrowableArray<uint16_t>* data) : data_(data) {}
+  RegExpAtom(ZoneGrowableArray<uint16_t>* data, RegExpFlags flags)
+      : data_(data), flags_(flags) {}
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success);
   virtual RegExpAtom* AsAtom();
@@ -200,9 +230,12 @@
   virtual void AppendToText(RegExpText* text);
   ZoneGrowableArray<uint16_t>* data() const { return data_; }
   intptr_t length() const { return data_->length(); }
+  RegExpFlags flags() const { return flags_; }
+  bool ignore_case() const { return flags_.IgnoreCase(); }
 
  private:
   ZoneGrowableArray<uint16_t>* data_;
+  const RegExpFlags flags_;
 };
 
 class RegExpText : public RegExpTree {
@@ -370,9 +403,10 @@
 
 class RegExpBackReference : public RegExpTree {
  public:
-  RegExpBackReference() : capture_(nullptr), name_(nullptr) {}
-  explicit RegExpBackReference(RegExpCapture* capture)
-      : capture_(capture), name_(nullptr) {}
+  explicit RegExpBackReference(RegExpFlags flags)
+      : capture_(nullptr), name_(nullptr), flags_(flags) {}
+  RegExpBackReference(RegExpCapture* capture, RegExpFlags flags)
+      : capture_(capture), name_(nullptr), flags_(flags) {}
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success);
   virtual RegExpBackReference* AsBackReference();
@@ -391,6 +425,7 @@
  private:
   RegExpCapture* capture_;
   const ZoneGrowableArray<uint16_t>* name_;
+  RegExpFlags flags_;
 };
 
 class RegExpEmpty : public RegExpTree {
diff --git a/runtime/vm/regexp_bytecodes.h b/runtime/vm/regexp_bytecodes.h
index 858eef5..178c950 100644
--- a/runtime/vm/regexp_bytecodes.h
+++ b/runtime/vm/regexp_bytecodes.h
@@ -55,17 +55,19 @@
 V(CHECK_GT,          36, 8)   /* bc8 pad8 uc16 addr32                       */ \
 V(CHECK_NOT_BACK_REF, 37, 8)  /* bc8 reg_idx24 addr32                       */ \
 V(CHECK_NOT_BACK_REF_NO_CASE, 38, 8) /* bc8 reg_idx24 addr32                */ \
-V(CHECK_NOT_BACK_REF_BACKWARD, 39, 8) /* bc8 reg_idx24 addr32               */ \
-V(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD, 40, 8) /* bc8 reg_idx24 addr32       */ \
-V(CHECK_NOT_REGS_EQUAL, 41, 12) /* bc8 regidx24 reg_idx32 addr32            */ \
-V(CHECK_REGISTER_LT, 42, 12)  /* bc8 reg_idx24 value32 addr32               */ \
-V(CHECK_REGISTER_GE, 43, 12)  /* bc8 reg_idx24 value32 addr32               */ \
-V(CHECK_REGISTER_EQ_POS, 44, 8) /* bc8 reg_idx24 addr32                     */ \
-V(CHECK_AT_START,    45, 8)   /* bc8 pad24 addr32                           */ \
-V(CHECK_NOT_AT_START, 46, 8)  /* bc8 offset24 addr32                        */ \
-V(CHECK_GREEDY,      47, 8)   /* bc8 pad24 addr32                           */ \
-V(ADVANCE_CP_AND_GOTO, 48, 8) /* bc8 offset24 addr32                        */ \
-V(SET_CURRENT_POSITION_FROM_END, 49, 4) /* bc8 idx24                        */
+V(CHECK_NOT_BACK_REF_NO_CASE_UNICODE, 39, 8) /* bc8 reg_idx24 addr32        */ \
+V(CHECK_NOT_BACK_REF_BACKWARD, 40, 8) /* bc8 reg_idx24 addr32               */ \
+V(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD, 41, 8) /* bc8 reg_idx24 addr32       */ \
+V(CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD, 42, 8) /*bc8 reg_idx24 addr32*/ \
+V(CHECK_NOT_REGS_EQUAL, 43, 12) /* bc8 regidx24 reg_idx32 addr32            */ \
+V(CHECK_REGISTER_LT, 44, 12)  /* bc8 reg_idx24 value32 addr32               */ \
+V(CHECK_REGISTER_GE, 45, 12)  /* bc8 reg_idx24 value32 addr32               */ \
+V(CHECK_REGISTER_EQ_POS, 46, 8) /* bc8 reg_idx24 addr32                     */ \
+V(CHECK_AT_START,    47, 8)   /* bc8 pad24 addr32                           */ \
+V(CHECK_NOT_AT_START, 48, 8)  /* bc8 offset24 addr32                        */ \
+V(CHECK_GREEDY,      49, 8)   /* bc8 pad24 addr32                           */ \
+V(ADVANCE_CP_AND_GOTO, 50, 8) /* bc8 offset24 addr32                        */ \
+V(SET_CURRENT_POSITION_FROM_END, 51, 4) /* bc8 idx24                        */
 
 // clang-format on
 
diff --git a/runtime/vm/regexp_interpreter.cc b/runtime/vm/regexp_interpreter.cc
index ecc7586..2921e3e 100644
--- a/runtime/vm/regexp_interpreter.cc
+++ b/runtime/vm/regexp_interpreter.cc
@@ -6,12 +6,12 @@
 
 #include "vm/regexp_interpreter.h"
 
+#include "platform/unicode.h"
 #include "vm/object.h"
 #include "vm/regexp_assembler.h"
 #include "vm/regexp_bytecodes.h"
 #include "vm/unibrow-inl.h"
 #include "vm/unibrow.h"
-#include "vm/unicode.h"
 
 namespace dart {
 
@@ -24,27 +24,25 @@
                                  intptr_t from,
                                  intptr_t current,
                                  intptr_t len,
-                                 const String& subject);
+                                 const String& subject,
+                                 bool unicode);
 
 template <>
 bool BackRefMatchesNoCase<uint16_t>(Canonicalize* interp_canonicalize,
                                     intptr_t from,
                                     intptr_t current,
                                     intptr_t len,
-                                    const String& subject) {
-  for (int i = 0; i < len; i++) {
-    int32_t old_char = subject.CharAt(from++);
-    int32_t new_char = subject.CharAt(current++);
-    if (old_char == new_char) continue;
-    int32_t old_string[1] = {old_char};
-    int32_t new_string[1] = {new_char};
-    interp_canonicalize->get(old_char, '\0', old_string);
-    interp_canonicalize->get(new_char, '\0', new_string);
-    if (old_string[0] != new_string[0]) {
-      return false;
-    }
+                                    const String& subject,
+                                    bool unicode) {
+  Bool& ret = Bool::Handle();
+  if (unicode) {
+    ret = CaseInsensitiveCompareUTF16(subject.raw(), Smi::New(from),
+                                      Smi::New(current), Smi::New(len));
+  } else {
+    ret = CaseInsensitiveCompareUCS2(subject.raw(), Smi::New(from),
+                                     Smi::New(current), Smi::New(len));
   }
-  return true;
+  return ret.value();
 }
 
 template <>
@@ -52,7 +50,9 @@
                                    intptr_t from,
                                    intptr_t current,
                                    intptr_t len,
-                                   const String& subject) {
+                                   const String& subject,
+                                   bool unicode) {
+  // For Latin1 characters the unicode flag makes no difference.
   for (int i = 0; i < len; i++) {
     unsigned int old_char = subject.CharAt(from++);
     unsigned int new_char = subject.CharAt(current++);
@@ -513,7 +513,11 @@
         pc += BC_CHECK_NOT_BACK_REF_LENGTH;
         break;
       }
+      BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE)
+      FALL_THROUGH;
       BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
+        const bool unicode =
+            (insn & BYTECODE_MASK) == BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE;
         int from = registers[insn >> BYTECODE_SHIFT];
         int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
         if (from < 0 || len <= 0) {
@@ -525,7 +529,7 @@
           break;
         } else {
           if (BackRefMatchesNoCase<Char>(&canonicalize, from, current, len,
-                                         subject)) {
+                                         subject, unicode)) {
             current += len;
             pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
           } else {
@@ -562,7 +566,11 @@
         pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
         break;
       }
+      BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD)
+      FALL_THROUGH;
       BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD) {
+        bool unicode = (insn & BYTECODE_MASK) ==
+                       BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD;
         int from = registers[insn >> BYTECODE_SHIFT];
         int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
         if (from < 0 || len <= 0) {
@@ -574,7 +582,7 @@
           break;
         } else {
           if (BackRefMatchesNoCase<Char>(&canonicalize, from, current - len,
-                                         len, subject)) {
+                                         len, subject, unicode)) {
             current -= len;
             pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
           } else {
diff --git a/runtime/vm/regexp_parser.cc b/runtime/vm/regexp_parser.cc
index b70b945..31aff3f 100644
--- a/runtime/vm/regexp_parser.cc
+++ b/runtime/vm/regexp_parser.cc
@@ -3,6 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/regexp_parser.h"
+
+#include "unicode/uchar.h"
+#include "unicode/uniset.h"
+
+#include "platform/unicode.h"
+
 #include "vm/longjump.h"
 #include "vm/object_store.h"
 
@@ -13,10 +19,12 @@
 // Enables possessive quantifier syntax for testing.
 static const bool FLAG_regexp_possessive_quantifier = false;
 
-RegExpBuilder::RegExpBuilder()
+RegExpBuilder::RegExpBuilder(RegExpFlags flags)
     : zone_(Thread::Current()->zone()),
       pending_empty_(false),
+      flags_(flags),
       characters_(NULL),
+      pending_surrogate_(kNoPendingSurrogate),
       terms_(),
       text_(),
       alternatives_()
@@ -27,10 +35,49 @@
 {
 }
 
+void RegExpBuilder::AddLeadSurrogate(uint16_t lead_surrogate) {
+  ASSERT(Utf16::IsLeadSurrogate(lead_surrogate));
+  FlushPendingSurrogate();
+  // Hold onto the lead surrogate, waiting for a trail surrogate to follow.
+  pending_surrogate_ = lead_surrogate;
+}
+
+void RegExpBuilder::AddTrailSurrogate(uint16_t trail_surrogate) {
+  ASSERT(Utf16::IsTrailSurrogate(trail_surrogate));
+  if (pending_surrogate_ != kNoPendingSurrogate) {
+    uint16_t lead_surrogate = pending_surrogate_;
+    pending_surrogate_ = kNoPendingSurrogate;
+    ASSERT(Utf16::IsLeadSurrogate(lead_surrogate));
+    uint32_t combined = Utf16::Decode(lead_surrogate, trail_surrogate);
+    if (NeedsDesugaringForIgnoreCase(combined)) {
+      AddCharacterClassForDesugaring(combined);
+    } else {
+      auto surrogate_pair = new (Z) ZoneGrowableArray<uint16_t>(2);
+      surrogate_pair->Add(lead_surrogate);
+      surrogate_pair->Add(trail_surrogate);
+      RegExpAtom* atom = new (Z) RegExpAtom(surrogate_pair, flags_);
+      AddAtom(atom);
+    }
+  } else {
+    pending_surrogate_ = trail_surrogate;
+    FlushPendingSurrogate();
+  }
+}
+
+void RegExpBuilder::FlushPendingSurrogate() {
+  if (pending_surrogate_ != kNoPendingSurrogate) {
+    ASSERT(is_unicode());
+    uint32_t c = pending_surrogate_;
+    pending_surrogate_ = kNoPendingSurrogate;
+    AddCharacterClassForDesugaring(c);
+  }
+}
+
 void RegExpBuilder::FlushCharacters() {
+  FlushPendingSurrogate();
   pending_empty_ = false;
   if (characters_ != NULL) {
-    RegExpTree* atom = new (Z) RegExpAtom(characters_);
+    RegExpTree* atom = new (Z) RegExpAtom(characters_, flags_);
     characters_ = NULL;
     text_.Add(atom);
     LAST(ADD_ATOM);
@@ -54,18 +101,62 @@
 }
 
 void RegExpBuilder::AddCharacter(uint16_t c) {
+  FlushPendingSurrogate();
   pending_empty_ = false;
-  if (characters_ == NULL) {
-    characters_ = new (Z) ZoneGrowableArray<uint16_t>(4);
+  if (NeedsDesugaringForIgnoreCase(c)) {
+    AddCharacterClassForDesugaring(c);
+  } else {
+    if (characters_ == NULL) {
+      characters_ = new (Z) ZoneGrowableArray<uint16_t>(4);
+    }
+    characters_->Add(c);
+    LAST(ADD_CHAR);
   }
-  characters_->Add(c);
-  LAST(ADD_CHAR);
+}
+
+void RegExpBuilder::AddUnicodeCharacter(uint32_t c) {
+  if (c > static_cast<uint32_t>(Utf16::kMaxCodeUnit)) {
+    ASSERT(is_unicode());
+    uint16_t surrogates[2];
+    Utf16::Encode(c, surrogates);
+    AddLeadSurrogate(surrogates[0]);
+    AddTrailSurrogate(surrogates[1]);
+  } else if (is_unicode() && Utf16::IsLeadSurrogate(c)) {
+    AddLeadSurrogate(c);
+  } else if (is_unicode() && Utf16::IsTrailSurrogate(c)) {
+    AddTrailSurrogate(c);
+  } else {
+    AddCharacter(static_cast<uint16_t>(c));
+  }
+}
+
+void RegExpBuilder::AddEscapedUnicodeCharacter(uint32_t character) {
+  // A lead or trail surrogate parsed via escape sequence will not
+  // pair up with any preceding lead or following trail surrogate.
+  FlushPendingSurrogate();
+  AddUnicodeCharacter(character);
+  FlushPendingSurrogate();
 }
 
 void RegExpBuilder::AddEmpty() {
   pending_empty_ = true;
 }
 
+void RegExpBuilder::AddCharacterClass(RegExpCharacterClass* cc) {
+  if (NeedsDesugaringForUnicode(cc)) {
+    // With /u, character class needs to be desugared, so it
+    // must be a standalone term instead of being part of a RegExpText.
+    AddTerm(cc);
+  } else {
+    AddAtom(cc);
+  }
+}
+
+void RegExpBuilder::AddCharacterClassForDesugaring(uint32_t c) {
+  auto ranges = CharacterRange::List(Z, CharacterRange::Singleton(c));
+  AddTerm(new (Z) RegExpCharacterClass(ranges, flags_));
+}
+
 void RegExpBuilder::AddAtom(RegExpTree* term) {
   if (term->IsEmpty()) {
     AddEmpty();
@@ -81,6 +172,12 @@
   LAST(ADD_ATOM);
 }
 
+void RegExpBuilder::AddTerm(RegExpTree* term) {
+  FlushText();
+  terms_.Add(term);
+  LAST(ADD_ATOM);
+}
+
 void RegExpBuilder::AddAssertion(RegExpTree* assert) {
   FlushText();
   terms_.Add(assert);
@@ -112,6 +209,37 @@
   LAST(ADD_NONE);
 }
 
+bool RegExpBuilder::NeedsDesugaringForUnicode(RegExpCharacterClass* cc) {
+  if (!is_unicode()) return false;
+  // TODO(yangguo): we could be smarter than this. Case-insensitivity does not
+  // necessarily mean that we need to desugar. It's probably nicer to have a
+  // separate pass to figure out unicode desugarings.
+  if (ignore_case()) return true;
+  ZoneGrowableArray<CharacterRange>* ranges = cc->ranges();
+  CharacterRange::Canonicalize(ranges);
+  for (int i = ranges->length() - 1; i >= 0; i--) {
+    uint32_t from = ranges->At(i).from();
+    uint32_t to = ranges->At(i).to();
+    // Check for non-BMP characters.
+    if (to >= Utf16::kMaxCodeUnit) return true;
+    // Check for lone surrogates.
+    if (from <= Utf16::kTrailSurrogateEnd && to >= Utf16::kLeadSurrogateStart) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool RegExpBuilder::NeedsDesugaringForIgnoreCase(uint32_t c) {
+  if (is_unicode() && ignore_case()) {
+    icu::UnicodeSet set(c, c);
+    set.closeOver(USET_CASE_INSENSITIVE);
+    set.removeAllStrings();
+    return set.size() > 1;
+  }
+  return false;
+}
+
 RegExpTree* RegExpBuilder::ToRegExp() {
   FlushTerms();
   intptr_t num_alternatives = alternatives_.length();
@@ -152,13 +280,13 @@
       for (intptr_t i = 0; i < num_chars - 1; i++) {
         prefix->Add(char_vector->At(i));
       }
-      text_.Add(new (Z) RegExpAtom(prefix));
+      text_.Add(new (Z) RegExpAtom(prefix, flags_));
       ZoneGrowableArray<uint16_t>* tail = new (Z) ZoneGrowableArray<uint16_t>();
       tail->Add(char_vector->At(num_chars - 1));
       char_vector = tail;
     }
     characters_ = NULL;
-    atom = new (Z) RegExpAtom(char_vector);
+    atom = new (Z) RegExpAtom(char_vector, flags_);
     FlushText();
   } else if (text_.length() > 0) {
     DEBUG_ASSERT(last_added_ == ADD_ATOM);
@@ -168,6 +296,8 @@
     DEBUG_ASSERT(last_added_ == ADD_ATOM);
     atom = terms_.RemoveLast();
     if (auto lookaround = atom->AsLookaround()) {
+      // With /u, lookarounds are not quantifiable.
+      if (is_unicode()) return false;
       // Lookbehinds are not quantifiable.
       if (lookaround->type() == RegExpLookaround::LOOKBEHIND) {
         return false;
@@ -194,7 +324,7 @@
 // ----------------------------------------------------------------------------
 // Implementation of Parser
 
-RegExpParser::RegExpParser(const String& in, String* error, bool multiline)
+RegExpParser::RegExpParser(const String& in, String* error, RegExpFlags flags)
     : zone_(Thread::Current()->zone()),
       captures_(nullptr),
       named_captures_(nullptr),
@@ -205,7 +335,7 @@
       captures_started_(0),
       capture_count_(0),
       has_more_(true),
-      multiline_(multiline),
+      top_level_flags_(flags),
       simple_(false),
       contains_anchor_(false),
       is_scanned_for_captures_(false),
@@ -213,20 +343,38 @@
   Advance();
 }
 
+inline uint32_t RegExpParser::ReadNext(bool update_position) {
+  intptr_t position = next_pos_;
+  const uint16_t c0 = in().CharAt(position);
+  uint32_t c = c0;
+  position++;
+  if (is_unicode() && position < in().Length() && Utf16::IsLeadSurrogate(c0)) {
+    const uint16_t c1 = in().CharAt(position);
+    if (Utf16::IsTrailSurrogate(c1)) {
+      c = Utf16::Decode(c0, c1);
+      position++;
+    }
+  }
+  if (update_position) next_pos_ = position;
+  return c;
+}
+
 uint32_t RegExpParser::Next() {
   if (has_next()) {
-    return in().CharAt(next_pos_);
+    return ReadNext(false);
   } else {
     return kEndMarker;
   }
 }
 
 void RegExpParser::Advance() {
-  if (next_pos_ < in().Length()) {
-    current_ = in().CharAt(next_pos_);
-    next_pos_++;
+  if (has_next()) {
+    current_ = ReadNext(true);
   } else {
     current_ = kEndMarker;
+    // Advance so that position() points to 1 after the last character. This is
+    // important so that Reset() to this position works correctly.
+    next_pos_ = in().Length() + 1;
     has_more_ = false;
   }
 }
@@ -246,6 +394,30 @@
   return simple_;
 }
 
+bool RegExpParser::IsSyntaxCharacterOrSlash(uint32_t c) {
+  switch (c) {
+    case '^':
+    case '$':
+    case '\\':
+    case '.':
+    case '*':
+    case '+':
+    case '?':
+    case '(':
+    case ')':
+    case '[':
+    case ']':
+    case '{':
+    case '}':
+    case '|':
+    case '/':
+      return true;
+    default:
+      break;
+  }
+  return false;
+}
+
 void RegExpParser::ReportError(const char* message) {
   // Zip to the end to make sure the no more input is read.
   current_ = kEndMarker;
@@ -274,6 +446,11 @@
   return result;
 }
 
+// Used for error messages where we would have fallen back on treating an
+// escape as the identity escape, but we are in Unicode mode.
+static const char* kUnicodeIdentity =
+    "Invalid identity escape in Unicode pattern";
+
 // Disjunction ::
 //   Alternative
 //   Alternative | Disjunction
@@ -287,7 +464,7 @@
 RegExpTree* RegExpParser::ParseDisjunction() {
   // Used to store current state while parsing subexpressions.
   RegExpParserState initial_state(nullptr, INITIAL, RegExpLookaround::LOOKAHEAD,
-                                  0, nullptr, Z);
+                                  0, nullptr, top_level_flags_, Z);
   RegExpParserState* stored_state = &initial_state;
   // Cache the builder in a local variable for quick access.
   RegExpBuilder* builder = initial_state.builder();
@@ -358,12 +535,12 @@
         UNREACHABLE();
       case '^': {
         Advance();
-        if (multiline_) {
-          builder->AddAssertion(
-              new (Z) RegExpAssertion(RegExpAssertion::START_OF_LINE));
+        if (builder->is_multi_line()) {
+          builder->AddAssertion(new (Z) RegExpAssertion(
+              RegExpAssertion::START_OF_LINE, builder->flags()));
         } else {
-          builder->AddAssertion(
-              new (Z) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
+          builder->AddAssertion(new (Z) RegExpAssertion(
+              RegExpAssertion::START_OF_INPUT, builder->flags()));
           set_contains_anchor();
         }
         continue;
@@ -371,19 +548,29 @@
       case '$': {
         Advance();
         RegExpAssertion::AssertionType assertion_type =
-            multiline_ ? RegExpAssertion::END_OF_LINE
-                       : RegExpAssertion::END_OF_INPUT;
-        builder->AddAssertion(new RegExpAssertion(assertion_type));
+            builder->is_multi_line() ? RegExpAssertion::END_OF_LINE
+                                     : RegExpAssertion::END_OF_INPUT;
+        builder->AddAssertion(
+            new (Z) RegExpAssertion(assertion_type, builder->flags()));
         continue;
       }
       case '.': {
         Advance();
-        // everything except \x0a, \x0d, \u2028 and \u2029
-        ZoneGrowableArray<CharacterRange>* ranges =
-            new ZoneGrowableArray<CharacterRange>(2);
-        CharacterRange::AddClassEscape('.', ranges);
-        RegExpTree* atom = new RegExpCharacterClass(ranges, false);
-        builder->AddAtom(atom);
+        auto ranges = new (Z) ZoneGrowableArray<CharacterRange>(2);
+        if (builder->is_dot_all()) {
+          // Everything.
+          CharacterRange::AddClassEscape(
+              '*', ranges,
+              /*add_unicode_case_equivalents=*/false);
+        } else {
+          // everything except \x0a, \x0d, \u2028 and \u2029
+          CharacterRange::AddClassEscape(
+              '.', ranges,
+              /*add_unicode_case_equivalents=*/false);
+        }
+        RegExpCharacterClass* cc =
+            new (Z) RegExpCharacterClass(ranges, builder->flags());
+        builder->AddCharacterClass(cc);
         break;
       }
       case '(': {
@@ -392,8 +579,8 @@
         continue;
       }
       case '[': {
-        RegExpTree* atom = ParseCharacterClass();
-        builder->AddAtom(atom);
+        RegExpTree* atom = ParseCharacterClass(builder);
+        builder->AddCharacterClass(atom->AsCharacterClass());
         break;
       }
       // Atom ::
@@ -405,13 +592,13 @@
             UNREACHABLE();
           case 'b':
             Advance(2);
-            builder->AddAssertion(
-                new RegExpAssertion(RegExpAssertion::BOUNDARY));
+            builder->AddAssertion(new (Z) RegExpAssertion(
+                RegExpAssertion::BOUNDARY, builder->flags()));
             continue;
           case 'B':
             Advance(2);
-            builder->AddAssertion(
-                new RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
+            builder->AddAssertion(new (Z) RegExpAssertion(
+                RegExpAssertion::NON_BOUNDARY, builder->flags()));
             continue;
           // AtomEscape ::
           //   CharacterClassEscape
@@ -426,11 +613,36 @@
           case 'W': {
             uint32_t c = Next();
             Advance(2);
-            ZoneGrowableArray<CharacterRange>* ranges =
-                new ZoneGrowableArray<CharacterRange>(2);
-            CharacterRange::AddClassEscape(c, ranges);
-            RegExpTree* atom = new RegExpCharacterClass(ranges, false);
-            builder->AddAtom(atom);
+            auto ranges = new (Z) ZoneGrowableArray<CharacterRange>(2);
+            CharacterRange::AddClassEscape(
+                c, ranges, is_unicode() && builder->ignore_case());
+            RegExpCharacterClass* cc =
+                new (Z) RegExpCharacterClass(ranges, builder->flags());
+            builder->AddCharacterClass(cc);
+            break;
+          }
+          case 'p':
+          case 'P': {
+            uint32_t p = Next();
+            Advance(2);
+
+            if (is_unicode()) {
+              auto name_1 = new (Z) ZoneGrowableArray<char>();
+              auto name_2 = new (Z) ZoneGrowableArray<char>();
+              auto ranges = new (Z) ZoneGrowableArray<CharacterRange>(2);
+              if (ParsePropertyClassName(name_1, name_2)) {
+                if (AddPropertyClassRange(ranges, p == 'P', name_1, name_2)) {
+                  RegExpCharacterClass* cc =
+                      new (Z) RegExpCharacterClass(ranges, builder->flags());
+                  builder->AddCharacterClass(cc);
+                  break;
+                }
+              }
+              ReportError("Invalid property name");
+              UNREACHABLE();
+            } else {
+              builder->AddCharacter(p);
+            }
             break;
           }
           case '1':
@@ -453,14 +665,20 @@
                 builder->AddEmpty();
               } else {
                 RegExpCapture* capture = GetCapture(index);
-                RegExpTree* atom = new RegExpBackReference(capture);
+                RegExpTree* atom =
+                    new (Z) RegExpBackReference(capture, builder->flags());
                 builder->AddAtom(atom);
               }
               break;
             }
+            // With /u, no identity escapes except for syntax characters are
+            // allowed. Otherwise, all identity escapes are allowed.
+            if (is_unicode()) {
+              ReportError(kUnicodeIdentity);
+              UNREACHABLE();
+            }
             uint32_t first_digit = Next();
             if (first_digit == '8' || first_digit == '9') {
-              // Treat as identity escape
               builder->AddCharacter(first_digit);
               Advance(2);
               break;
@@ -469,6 +687,11 @@
           }
           case '0': {
             Advance();
+            if (is_unicode() && Next() >= '0' && Next() <= '9') {
+              // With /u, decimal escape with leading 0 are not parsed as octal.
+              ReportError("Invalid decimal escape");
+              UNREACHABLE();
+            }
             uint32_t octal = ParseOctalLiteral();
             builder->AddCharacter(octal);
             break;
@@ -506,6 +729,11 @@
               // This is outside the specification. We match JSC in
               // reading the backslash as a literal character instead
               // of as starting an escape.
+              if (is_unicode()) {
+                // With /u, invalid escapes are not treated as identity escapes.
+                ReportError(kUnicodeIdentity);
+                UNREACHABLE();
+              }
               builder->AddCharacter('\\');
             } else {
               Advance(2);
@@ -518,18 +746,26 @@
             uint32_t value;
             if (ParseHexEscape(2, &value)) {
               builder->AddCharacter(value);
-            } else {
+            } else if (!is_unicode()) {
               builder->AddCharacter('x');
+            } else {
+              // With /u, invalid escapes are not treated as identity escapes.
+              ReportError(kUnicodeIdentity);
+              UNREACHABLE();
             }
             break;
           }
           case 'u': {
             Advance(2);
             uint32_t value;
-            if (ParseHexEscape(4, &value)) {
-              builder->AddCharacter(value);
-            } else {
+            if (ParseUnicodeEscape(&value)) {
+              builder->AddEscapedUnicodeCharacter(value);
+            } else if (!is_unicode()) {
               builder->AddCharacter('u');
+            } else {
+              // With /u, invalid escapes are not treated as identity escapes.
+              ReportError(kUnicodeIdentity);
+              UNREACHABLE();
             }
             break;
           }
@@ -539,16 +775,24 @@
             // an identity escape for non-Unicode patterns without named
             // capture groups, and as the beginning of a named back-reference
             // in all other cases.
-            if (HasNamedCaptures()) {
+            if (is_unicode() || HasNamedCaptures()) {
               Advance(2);
               ParseNamedBackReference(builder, stored_state);
               break;
             }
             FALL_THROUGH;
           default:
-            // Identity escape.
-            builder->AddCharacter(Next());
-            Advance(2);
+            Advance();
+            // With the unicode flag, no identity escapes except for syntax
+            // characters are allowed. Otherwise, all identity escapes are
+            // allowed.
+            if (!is_unicode() || IsSyntaxCharacterOrSlash(current())) {
+              builder->AddCharacter(current());
+              Advance();
+            } else {
+              ReportError(kUnicodeIdentity);
+              UNREACHABLE();
+            }
             break;
         }
         break;
@@ -560,8 +804,15 @@
         }
         FALL_THROUGH;
       }
+      case '}':
+      case ']':
+        if (is_unicode()) {
+          ReportError("Lone quantifier brackets");
+          UNREACHABLE();
+        }
+        FALL_THROUGH;
       default:
-        builder->AddCharacter(current());
+        builder->AddUnicodeCharacter(current());
         Advance();
         break;
     }  // end switch(current())
@@ -693,8 +944,9 @@
     }
   }
   // Store current state and begin new disjunction parsing.
-  return new RegExpParserState(state, subexpr_type, lookaround_type,
-                               captures_started_, capture_name, Z);
+  return new (Z)
+      RegExpParserState(state, subexpr_type, lookaround_type, captures_started_,
+                        capture_name, state->builder()->flags(), Z);
 }
 
 // In order to know whether an escape is a backreference or not we have to scan
@@ -756,10 +1008,6 @@
   Reset(saved_position);
 }
 
-static inline bool IsDecimalDigit(int32_t c) {
-  return '0' <= c && c <= '9';
-}
-
 bool RegExpParser::ParseBackReferenceIndex(intptr_t* index_out) {
   ASSERT('\\' == current());
   ASSERT('1' <= Next() && Next() <= '9');
@@ -770,7 +1018,7 @@
   Advance(2);
   while (true) {
     uint32_t c = current();
-    if (IsDecimalDigit(c)) {
+    if (Utils::IsDecimalDigit(c)) {
       value = 10 * value + (c - '0');
       if (value > kMaxCaptures) {
         Reset(start);
@@ -794,17 +1042,43 @@
 
 namespace {
 
-inline constexpr bool IsIdentifierStart(uint16_t ch) {
-  return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_' ||
-         ch == '$';
+static inline constexpr bool IsAsciiIdentifierPart(uint32_t ch) {
+  return Utils::IsAlphaNumeric(ch) || ch == '_' || ch == '$';
 }
 
-inline constexpr bool IsIdentifierPart(uint16_t ch) {
-  return IsIdentifierStart(ch) || (ch >= '0' && ch <= '9');
+// ES#sec-names-and-keywords Names and Keywords
+// UnicodeIDStart, '$', '_' and '\'
+static bool IsIdentifierStartSlow(uint32_t c) {
+  // cannot use u_isIDStart because it does not work for
+  // Other_ID_Start characters.
+  return u_hasBinaryProperty(c, UCHAR_ID_START) ||
+         (c < 0x60 && (c == '$' || c == '\\' || c == '_'));
 }
 
-bool IsSameName(const RegExpCaptureName* name1,
-                const RegExpCaptureName* name2) {
+// ES#sec-names-and-keywords Names and Keywords
+// UnicodeIDContinue, '$', '_', '\', ZWJ, and ZWNJ
+static bool IsIdentifierPartSlow(uint32_t c) {
+  const uint32_t kZeroWidthNonJoiner = 0x200C;
+  const uint32_t kZeroWidthJoiner = 0x200D;
+  // Can't use u_isIDPart because it does not work for
+  // Other_ID_Continue characters.
+  return u_hasBinaryProperty(c, UCHAR_ID_CONTINUE) ||
+         (c < 0x60 && (c == '$' || c == '\\' || c == '_')) ||
+         c == kZeroWidthNonJoiner || c == kZeroWidthJoiner;
+}
+
+static inline bool IsIdentifierStart(uint32_t c) {
+  if (c > 127) return IsIdentifierStartSlow(c);
+  return IsAsciiIdentifierPart(c) && !Utils::IsDecimalDigit(c);
+}
+
+static inline bool IsIdentifierPart(uint32_t c) {
+  if (c > 127) return IsIdentifierPartSlow(c);
+  return IsAsciiIdentifierPart(c);
+}
+
+static bool IsSameName(const RegExpCaptureName* name1,
+                       const RegExpCaptureName* name2) {
   if (name1->length() != name2->length()) return false;
   for (intptr_t i = 0; i < name1->length(); i++) {
     if (name1->At(i) != name2->At(i)) return false;
@@ -814,14 +1088,34 @@
 
 }  // end namespace
 
+static void PushCodeUnit(RegExpCaptureName* v, uint32_t code_unit) {
+  if (code_unit <= Utf16::kMaxCodeUnit) {
+    v->Add(code_unit);
+  } else {
+    uint16_t units[2];
+    Utf16::Encode(code_unit, units);
+    v->Add(units[0]);
+    v->Add(units[1]);
+  }
+}
+
 const RegExpCaptureName* RegExpParser::ParseCaptureGroupName() {
   auto name = new (Z) RegExpCaptureName();
 
   bool at_start = true;
   while (true) {
-    const uint16_t c = current();
+    uint32_t c = current();
     Advance();
 
+    // Convert unicode escapes.
+    if (c == '\\' && current() == 'u') {
+      Advance();
+      if (!ParseUnicodeEscape(&c)) {
+        ReportError("Invalid Unicode escape sequence");
+        UNREACHABLE();
+      }
+    }
+
     // The backslash char is misclassified as both ID_Start and ID_Continue.
     if (c == '\\') {
       ReportError("Invalid capture group name");
@@ -833,13 +1127,13 @@
         ReportError("Invalid capture group name");
         UNREACHABLE();
       }
-      name->Add(c);
+      PushCodeUnit(name, c);
       at_start = false;
     } else {
       if (c == '>') {
         break;
       } else if (IsIdentifierPart(c)) {
-        name->Add(c);
+        PushCodeUnit(name, c);
       } else {
         ReportError("Invalid capture group name");
         UNREACHABLE();
@@ -896,7 +1190,7 @@
   if (state->IsInsideCaptureGroup(name)) {
     builder->AddEmpty();
   } else {
-    RegExpBackReference* atom = new (Z) RegExpBackReference();
+    RegExpBackReference* atom = new (Z) RegExpBackReference(builder->flags());
     atom->set_name(name);
 
     builder->AddAtom(atom);
@@ -1015,17 +1309,17 @@
   intptr_t start = position();
   Advance();
   intptr_t min = 0;
-  if (!IsDecimalDigit(current())) {
+  if (!Utils::IsDecimalDigit(current())) {
     Reset(start);
     return false;
   }
-  while (IsDecimalDigit(current())) {
+  while (Utils::IsDecimalDigit(current())) {
     intptr_t next = current() - '0';
     if (min > (RegExpTree::kInfinity - next) / 10) {
       // Overflow. Skip past remaining decimal digits and return -1.
       do {
         Advance();
-      } while (IsDecimalDigit(current()));
+      } while (Utils::IsDecimalDigit(current()));
       min = RegExpTree::kInfinity;
       break;
     }
@@ -1042,12 +1336,12 @@
       max = RegExpTree::kInfinity;
       Advance();
     } else {
-      while (IsDecimalDigit(current())) {
+      while (Utils::IsDecimalDigit(current())) {
         intptr_t next = current() - '0';
         if (max > (RegExpTree::kInfinity - next) / 10) {
           do {
             Advance();
-          } while (IsDecimalDigit(current()));
+          } while (Utils::IsDecimalDigit(current()));
           max = RegExpTree::kInfinity;
           break;
         }
@@ -1117,6 +1411,317 @@
   return true;
 }
 
+// This parses RegExpUnicodeEscapeSequence as described in ECMA262.
+bool RegExpParser::ParseUnicodeEscape(uint32_t* value) {
+  // Accept both \uxxxx and \u{xxxxxx} (if harmony unicode escapes are
+  // allowed). In the latter case, the number of hex digits between { } is
+  // arbitrary. \ and u have already been read.
+  if (current() == '{' && is_unicode()) {
+    int start = position();
+    Advance();
+    if (ParseUnlimitedLengthHexNumber(Utf::kMaxCodePoint, value)) {
+      if (current() == '}') {
+        Advance();
+        return true;
+      }
+    }
+    Reset(start);
+    return false;
+  }
+  // \u but no {, or \u{...} escapes not allowed.
+  bool result = ParseHexEscape(4, value);
+  if (result && is_unicode() && Utf16::IsLeadSurrogate(*value) &&
+      current() == '\\') {
+    // Attempt to read trail surrogate.
+    int start = position();
+    if (Next() == 'u') {
+      Advance(2);
+      uint32_t trail;
+      if (ParseHexEscape(4, &trail) && Utf16::IsTrailSurrogate(trail)) {
+        *value = Utf16::Decode(static_cast<uint16_t>(*value),
+                               static_cast<uint16_t>(trail));
+        return true;
+      }
+    }
+    Reset(start);
+  }
+  return result;
+}
+
+namespace {
+
+bool IsExactPropertyAlias(const char* property_name, UProperty property) {
+  const char* short_name = u_getPropertyName(property, U_SHORT_PROPERTY_NAME);
+  if (short_name != nullptr && strcmp(property_name, short_name) == 0) {
+    return true;
+  }
+  for (int i = 0;; i++) {
+    const char* long_name = u_getPropertyName(
+        property, static_cast<UPropertyNameChoice>(U_LONG_PROPERTY_NAME + i));
+    if (long_name == nullptr) break;
+    if (strcmp(property_name, long_name) == 0) return true;
+  }
+  return false;
+}
+
+bool IsExactPropertyValueAlias(const char* property_value_name,
+                               UProperty property,
+                               int32_t property_value) {
+  const char* short_name =
+      u_getPropertyValueName(property, property_value, U_SHORT_PROPERTY_NAME);
+  if (short_name != nullptr && strcmp(property_value_name, short_name) == 0) {
+    return true;
+  }
+  for (int i = 0;; i++) {
+    const char* long_name = u_getPropertyValueName(
+        property, property_value,
+        static_cast<UPropertyNameChoice>(U_LONG_PROPERTY_NAME + i));
+    if (long_name == nullptr) break;
+    if (strcmp(property_value_name, long_name) == 0) return true;
+  }
+  return false;
+}
+
+bool LookupPropertyValueName(UProperty property,
+                             const char* property_value_name,
+                             bool negate,
+                             ZoneGrowableArray<CharacterRange>* result) {
+  UProperty property_for_lookup = property;
+  if (property_for_lookup == UCHAR_SCRIPT_EXTENSIONS) {
+    // For the property Script_Extensions, we have to do the property value
+    // name lookup as if the property is Script.
+    property_for_lookup = UCHAR_SCRIPT;
+  }
+  int32_t property_value =
+      u_getPropertyValueEnum(property_for_lookup, property_value_name);
+  if (property_value == UCHAR_INVALID_CODE) return false;
+
+  // We require the property name to match exactly to one of the property value
+  // aliases. However, u_getPropertyValueEnum uses loose matching.
+  if (!IsExactPropertyValueAlias(property_value_name, property_for_lookup,
+                                 property_value)) {
+    return false;
+  }
+
+  UErrorCode ec = U_ZERO_ERROR;
+  icu::UnicodeSet set;
+  set.applyIntPropertyValue(property, property_value, ec);
+  bool success = ec == U_ZERO_ERROR && !set.isEmpty();
+
+  if (success) {
+    set.removeAllStrings();
+    if (negate) set.complement();
+    for (int i = 0; i < set.getRangeCount(); i++) {
+      result->Add(
+          CharacterRange::Range(set.getRangeStart(i), set.getRangeEnd(i)));
+    }
+  }
+  return success;
+}
+
+template <size_t N>
+inline bool NameEquals(const char* name, const char (&literal)[N]) {
+  return strncmp(name, literal, N + 1) == 0;
+}
+
+bool LookupSpecialPropertyValueName(const char* name,
+                                    ZoneGrowableArray<CharacterRange>* result,
+                                    bool negate) {
+  if (NameEquals(name, "Any")) {
+    if (negate) {
+      // Leave the list of character ranges empty, since the negation of 'Any'
+      // is the empty set.
+    } else {
+      result->Add(CharacterRange::Everything());
+    }
+  } else if (NameEquals(name, "ASCII")) {
+    result->Add(negate ? CharacterRange::Range(0x80, Utf::kMaxCodePoint)
+                       : CharacterRange::Range(0x0, 0x7F));
+  } else if (NameEquals(name, "Assigned")) {
+    return LookupPropertyValueName(UCHAR_GENERAL_CATEGORY, "Unassigned",
+                                   !negate, result);
+  } else {
+    return false;
+  }
+  return true;
+}
+
+// Explicitly whitelist supported binary properties. The spec forbids supporting
+// properties outside of this set to ensure interoperability.
+bool IsSupportedBinaryProperty(UProperty property) {
+  switch (property) {
+    case UCHAR_ALPHABETIC:
+    // 'Any' is not supported by ICU. See LookupSpecialPropertyValueName.
+    // 'ASCII' is not supported by ICU. See LookupSpecialPropertyValueName.
+    case UCHAR_ASCII_HEX_DIGIT:
+    // 'Assigned' is not supported by ICU. See LookupSpecialPropertyValueName.
+    case UCHAR_BIDI_CONTROL:
+    case UCHAR_BIDI_MIRRORED:
+    case UCHAR_CASE_IGNORABLE:
+    case UCHAR_CASED:
+    case UCHAR_CHANGES_WHEN_CASEFOLDED:
+    case UCHAR_CHANGES_WHEN_CASEMAPPED:
+    case UCHAR_CHANGES_WHEN_LOWERCASED:
+    case UCHAR_CHANGES_WHEN_NFKC_CASEFOLDED:
+    case UCHAR_CHANGES_WHEN_TITLECASED:
+    case UCHAR_CHANGES_WHEN_UPPERCASED:
+    case UCHAR_DASH:
+    case UCHAR_DEFAULT_IGNORABLE_CODE_POINT:
+    case UCHAR_DEPRECATED:
+    case UCHAR_DIACRITIC:
+    case UCHAR_EMOJI:
+    case UCHAR_EMOJI_COMPONENT:
+    case UCHAR_EMOJI_MODIFIER_BASE:
+    case UCHAR_EMOJI_MODIFIER:
+    case UCHAR_EMOJI_PRESENTATION:
+    case UCHAR_EXTENDED_PICTOGRAPHIC:
+    case UCHAR_EXTENDER:
+    case UCHAR_GRAPHEME_BASE:
+    case UCHAR_GRAPHEME_EXTEND:
+    case UCHAR_HEX_DIGIT:
+    case UCHAR_ID_CONTINUE:
+    case UCHAR_ID_START:
+    case UCHAR_IDEOGRAPHIC:
+    case UCHAR_IDS_BINARY_OPERATOR:
+    case UCHAR_IDS_TRINARY_OPERATOR:
+    case UCHAR_JOIN_CONTROL:
+    case UCHAR_LOGICAL_ORDER_EXCEPTION:
+    case UCHAR_LOWERCASE:
+    case UCHAR_MATH:
+    case UCHAR_NONCHARACTER_CODE_POINT:
+    case UCHAR_PATTERN_SYNTAX:
+    case UCHAR_PATTERN_WHITE_SPACE:
+    case UCHAR_QUOTATION_MARK:
+    case UCHAR_RADICAL:
+    case UCHAR_REGIONAL_INDICATOR:
+    case UCHAR_S_TERM:
+    case UCHAR_SOFT_DOTTED:
+    case UCHAR_TERMINAL_PUNCTUATION:
+    case UCHAR_UNIFIED_IDEOGRAPH:
+    case UCHAR_UPPERCASE:
+    case UCHAR_VARIATION_SELECTOR:
+    case UCHAR_WHITE_SPACE:
+    case UCHAR_XID_CONTINUE:
+    case UCHAR_XID_START:
+      return true;
+    default:
+      break;
+  }
+  return false;
+}
+
+bool IsUnicodePropertyValueCharacter(char c) {
+  // https://tc39.github.io/proposal-regexp-unicode-property-escapes/
+  //
+  // Note that using this to validate each parsed char is quite conservative.
+  // A possible alternative solution would be to only ensure the parsed
+  // property name/value candidate string does not contain '\0' characters and
+  // let ICU lookups trigger the final failure.
+  if (Utils::IsAlphaNumeric(c)) return true;
+  return (c == '_');
+}
+
+}  // anonymous namespace
+
+bool RegExpParser::ParsePropertyClassName(ZoneGrowableArray<char>* name_1,
+                                          ZoneGrowableArray<char>* name_2) {
+  ASSERT(name_1->is_empty());
+  ASSERT(name_2->is_empty());
+  // Parse the property class as follows:
+  // - In \p{name}, 'name' is interpreted
+  //   - either as a general category property value name.
+  //   - or as a binary property name.
+  // - In \p{name=value}, 'name' is interpreted as an enumerated property name,
+  //   and 'value' is interpreted as one of the available property value names.
+  // - Aliases in PropertyAlias.txt and PropertyValueAlias.txt can be used.
+  // - Loose matching is not applied.
+  if (current() == '{') {
+    // Parse \p{[PropertyName=]PropertyNameValue}
+    for (Advance(); current() != '}' && current() != '='; Advance()) {
+      if (!IsUnicodePropertyValueCharacter(current())) return false;
+      if (!has_next()) return false;
+      name_1->Add(static_cast<char>(current()));
+    }
+    if (current() == '=') {
+      for (Advance(); current() != '}'; Advance()) {
+        if (!IsUnicodePropertyValueCharacter(current())) return false;
+        if (!has_next()) return false;
+        name_2->Add(static_cast<char>(current()));
+      }
+      name_2->Add(0);  // null-terminate string.
+    }
+  } else {
+    return false;
+  }
+  Advance();
+  name_1->Add(0);  // null-terminate string.
+
+  ASSERT(static_cast<size_t>(name_1->length() - 1) == strlen(name_1->data()));
+  ASSERT(name_2->is_empty() ||
+         static_cast<size_t>(name_2->length() - 1) == strlen(name_2->data()));
+  return true;
+}
+
+bool RegExpParser::AddPropertyClassRange(
+    ZoneGrowableArray<CharacterRange>* add_to,
+    bool negate,
+    ZoneGrowableArray<char>* name_1,
+    ZoneGrowableArray<char>* name_2) {
+  ASSERT(name_1->At(name_1->length() - 1) == '\0');
+  ASSERT(name_2->is_empty() || name_2->At(name_2->length() - 1) == '\0');
+  if (name_2->is_empty()) {
+    // First attempt to interpret as general category property value name.
+    const char* name = name_1->data();
+    if (LookupPropertyValueName(UCHAR_GENERAL_CATEGORY_MASK, name, negate,
+                                add_to)) {
+      return true;
+    }
+    // Interpret "Any", "ASCII", and "Assigned".
+    if (LookupSpecialPropertyValueName(name, add_to, negate)) {
+      return true;
+    }
+    // Then attempt to interpret as binary property name with value name 'Y'.
+    UProperty property = u_getPropertyEnum(name);
+    if (!IsSupportedBinaryProperty(property)) return false;
+    if (!IsExactPropertyAlias(name, property)) return false;
+    return LookupPropertyValueName(property, negate ? "N" : "Y", false, add_to);
+  } else {
+    // Both property name and value name are specified. Attempt to interpret
+    // the property name as enumerated property.
+    const char* property_name = name_1->data();
+    const char* value_name = name_2->data();
+    UProperty property = u_getPropertyEnum(property_name);
+    if (!IsExactPropertyAlias(property_name, property)) return false;
+    if (property == UCHAR_GENERAL_CATEGORY) {
+      // We want to allow aggregate value names such as "Letter".
+      property = UCHAR_GENERAL_CATEGORY_MASK;
+    } else if (property != UCHAR_SCRIPT &&
+               property != UCHAR_SCRIPT_EXTENSIONS) {
+      return false;
+    }
+    return LookupPropertyValueName(property, value_name, negate, add_to);
+  }
+}
+
+bool RegExpParser::ParseUnlimitedLengthHexNumber(uint32_t max_value,
+                                                 uint32_t* value) {
+  uint32_t x = 0;
+  int d = HexValue(current());
+  if (d < 0) {
+    return false;
+  }
+  while (d >= 0) {
+    x = x * 16 + d;
+    if (x > max_value) {
+      return false;
+    }
+    Advance();
+    d = HexValue(current());
+  }
+  *value = x;
+  return true;
+}
+
 uint32_t RegExpParser::ParseClassCharacterEscape() {
   ASSERT(current() == '\\');
   DEBUG_ASSERT(has_next() && !IsSpecialClassEscape(Next()));
@@ -1147,35 +1752,47 @@
       uint32_t letter = controlLetter & ~('A' ^ 'a');
       // For compatibility with JSC, inside a character class
       // we also accept digits and underscore as control characters.
-      if ((controlLetter >= '0' && controlLetter <= '9') ||
-          controlLetter == '_' || (letter >= 'A' && letter <= 'Z')) {
+      if (letter >= 'A' && letter <= 'Z') {
         Advance(2);
         // Control letters mapped to ASCII control characters in the range
         // 0x00-0x1f.
         return controlLetter & 0x1f;
       }
+      if (is_unicode()) {
+        // With /u, \c# or \c_ are invalid.
+        ReportError("Invalid class escape");
+        UNREACHABLE();
+      }
+      if (Utils::IsDecimalDigit(controlLetter) || controlLetter == '_') {
+        Advance(2);
+        return controlLetter & 0x1f;
+      }
       // We match JSC in reading the backslash as a literal
       // character instead of as starting an escape.
       return '\\';
     }
     case '0':
+      // With /u, \0 is interpreted as NUL if not followed by another digit.
+      if (is_unicode() && !(Next() >= '0' && Next() <= '9')) {
+        Advance();
+        return 0;
+      }
       FALL_THROUGH;
     case '1':
-      FALL_THROUGH;
     case '2':
-      FALL_THROUGH;
     case '3':
-      FALL_THROUGH;
     case '4':
-      FALL_THROUGH;
     case '5':
-      FALL_THROUGH;
     case '6':
-      FALL_THROUGH;
     case '7':
       // For compatibility, we interpret a decimal escape that isn't
       // a back reference (and therefore either \0 or not valid according
       // to the specification) as a 1..3 digit octal character code.
+      if (is_unicode()) {
+        // With \u, decimal escape is not interpreted as octal character code.
+        ReportError("Invalid class escape");
+        UNREACHABLE();
+      }
       return ParseOctalLiteral();
     case 'x': {
       Advance();
@@ -1183,6 +1800,11 @@
       if (ParseHexEscape(2, &value)) {
         return value;
       }
+      if (is_unicode()) {
+        // With \u, invalid escapes are not treated as identity escapes.
+        ReportError("Invalid escape");
+        UNREACHABLE();
+      }
       // If \x is not followed by a two-digit hexadecimal, treat it
       // as an identity escape.
       return 'x';
@@ -1190,9 +1812,14 @@
     case 'u': {
       Advance();
       uint32_t value;
-      if (ParseHexEscape(4, &value)) {
+      if (ParseUnicodeEscape(&value)) {
         return value;
       }
+      if (is_unicode()) {
+        // With \u, invalid escapes are not treated as identity escapes.
+        ReportError(kUnicodeIdentity);
+        UNREACHABLE();
+      }
       // If \u is not followed by a four-digit hexadecimal, treat it
       // as an identity escape.
       return 'u';
@@ -1202,15 +1829,20 @@
       // been matched by a more specific case, not just the subset required
       // by the ECMAScript specification.
       uint32_t result = current();
-      Advance();
-      return result;
+      if (!is_unicode() || IsSyntaxCharacterOrSlash(result) || result == '-') {
+        Advance();
+        return result;
+      }
+      ReportError(kUnicodeIdentity);
+      UNREACHABLE();
     }
   }
   return 0;
 }
 
-CharacterRange RegExpParser::ParseClassAtom(uint16_t* char_class) {
-  ASSERT(0 == *char_class);
+bool RegExpParser::ParseClassEscape(ZoneGrowableArray<CharacterRange>* ranges,
+                                    bool add_unicode_case_equivalents,
+                                    uint32_t* char_out) {
   uint32_t first = current();
   if (first == '\\') {
     switch (Next()) {
@@ -1220,40 +1852,42 @@
       case 'D':
       case 's':
       case 'S': {
-        *char_class = Next();
+        CharacterRange::AddClassEscape(static_cast<uint16_t>(Next()), ranges,
+                                       add_unicode_case_equivalents);
         Advance(2);
-        return CharacterRange::Singleton(0);  // Return dummy value.
+        return true;
+      }
+      case 'p':
+      case 'P': {
+        if (!is_unicode()) break;
+        bool negate = Next() == 'P';
+        Advance(2);
+        auto name_1 = new (Z) ZoneGrowableArray<char>();
+        auto name_2 = new (Z) ZoneGrowableArray<char>();
+        if (!ParsePropertyClassName(name_1, name_2) ||
+            !AddPropertyClassRange(ranges, negate, name_1, name_2)) {
+          ReportError("Invalid property name in character class");
+          UNREACHABLE();
+        }
+        return true;
       }
       case kEndMarker:
         ReportError("\\ at end of pattern");
         UNREACHABLE();
       default:
-        uint32_t c = ParseClassCharacterEscape();
-        return CharacterRange::Singleton(c);
+        break;
     }
-  } else {
-    Advance();
-    return CharacterRange::Singleton(first);
+    *char_out = ParseClassCharacterEscape();
+    return false;
   }
+  Advance();
+  *char_out = first;
+  return false;
 }
 
-static const uint16_t kNoCharClass = 0;
-
-// Adds range or pre-defined character class to character ranges.
-// If char_class is not kInvalidClass, it's interpreted as a class
-// escape (i.e., 's' means whitespace, from '\s').
-static inline void AddRangeOrEscape(ZoneGrowableArray<CharacterRange>* ranges,
-                                    uint16_t char_class,
-                                    CharacterRange range) {
-  if (char_class != kNoCharClass) {
-    CharacterRange::AddClassEscape(char_class, ranges);
-  } else {
-    ranges->Add(range);
-  }
-}
-
-RegExpTree* RegExpParser::ParseCharacterClass() {
+RegExpTree* RegExpParser::ParseCharacterClass(const RegExpBuilder* builder) {
   static const char* kUnterminated = "Unterminated character class";
+  static const char* kRangeInvalid = "Invalid character class";
   static const char* kRangeOutOfOrder = "Range out of order in character class";
 
   ASSERT(current() == '[');
@@ -1265,9 +1899,11 @@
   }
   ZoneGrowableArray<CharacterRange>* ranges =
       new (Z) ZoneGrowableArray<CharacterRange>(2);
+  bool add_unicode_case_equivalents = is_unicode() && builder->ignore_case();
   while (has_more() && current() != ']') {
-    uint16_t char_class = kNoCharClass;
-    CharacterRange first = ParseClassAtom(&char_class);
+    uint32_t char_1;
+    bool is_class_1 =
+        ParseClassEscape(ranges, add_unicode_case_equivalents, &char_1);
     if (current() == '-') {
       Advance();
       if (current() == kEndMarker) {
@@ -1275,26 +1911,32 @@
         // following code report an error.
         break;
       } else if (current() == ']') {
-        AddRangeOrEscape(ranges, char_class, first);
+        if (!is_class_1) ranges->Add(CharacterRange::Singleton(char_1));
         ranges->Add(CharacterRange::Singleton('-'));
         break;
       }
-      uint16_t char_class_2 = kNoCharClass;
-      CharacterRange next = ParseClassAtom(&char_class_2);
-      if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
+      uint32_t char_2;
+      bool is_class_2 =
+          ParseClassEscape(ranges, add_unicode_case_equivalents, &char_2);
+      if (is_class_1 || is_class_2) {
         // Either end is an escaped character class. Treat the '-' verbatim.
-        AddRangeOrEscape(ranges, char_class, first);
+        if (is_unicode()) {
+          // ES2015 21.2.2.15.1 step 1.
+          ReportError(kRangeInvalid);
+          UNREACHABLE();
+        }
+        if (!is_class_1) ranges->Add(CharacterRange::Singleton(char_1));
         ranges->Add(CharacterRange::Singleton('-'));
-        AddRangeOrEscape(ranges, char_class_2, next);
+        if (!is_class_2) ranges->Add(CharacterRange::Singleton(char_2));
         continue;
       }
-      if (first.from() > next.to()) {
+      if (char_1 > char_2) {
         ReportError(kRangeOutOfOrder);
         UNREACHABLE();
       }
-      ranges->Add(CharacterRange::Range(first.from(), next.to()));
+      ranges->Add(CharacterRange::Range(char_1, char_2));
     } else {
-      AddRangeOrEscape(ranges, char_class, first);
+      if (!is_class_1) ranges->Add(CharacterRange::Singleton(char_1));
     }
   }
   if (!has_more()) {
@@ -1302,21 +1944,21 @@
     UNREACHABLE();
   }
   Advance();
-  if (ranges->length() == 0) {
-    ranges->Add(CharacterRange::Everything());
-    is_negated = !is_negated;
-  }
-  return new (Z) RegExpCharacterClass(ranges, is_negated);
+  RegExpCharacterClass::CharacterClassFlags character_class_flags =
+      RegExpCharacterClass::DefaultFlags();
+  if (is_negated) character_class_flags |= RegExpCharacterClass::NEGATED;
+  return new (Z)
+      RegExpCharacterClass(ranges, builder->flags(), character_class_flags);
 }
 
 // ----------------------------------------------------------------------------
 // The Parser interface.
 
 void RegExpParser::ParseRegExp(const String& input,
-                               bool multiline,
+                               RegExpFlags flags,
                                RegExpCompileData* result) {
   ASSERT(result != NULL);
-  RegExpParser parser(input, &result->error, multiline);
+  RegExpParser parser(input, &result->error, flags);
   // Throws an exception if 'input' is not valid.
   RegExpTree* tree = parser.ParsePattern();
   ASSERT(tree != NULL);
diff --git a/runtime/vm/regexp_parser.h b/runtime/vm/regexp_parser.h
index a2b626b..63c237a 100644
--- a/runtime/vm/regexp_parser.h
+++ b/runtime/vm/regexp_parser.h
@@ -14,13 +14,18 @@
 // Accumulates RegExp atoms and assertions into lists of terms and alternatives.
 class RegExpBuilder : public ZoneAllocated {
  public:
-  RegExpBuilder();
+  explicit RegExpBuilder(RegExpFlags flags);
 
   void AddCharacter(uint16_t character);
+  void AddUnicodeCharacter(uint32_t character);
+  void AddEscapedUnicodeCharacter(uint32_t character);
   // "Adds" an empty expression. Does nothing except consume a
   // following quantifier
   void AddEmpty();
+  void AddCharacterClass(RegExpCharacterClass* cc);
+  void AddCharacterClassForDesugaring(uint32_t c);
   void AddAtom(RegExpTree* tree);
+  void AddTerm(RegExpTree* tree);
   void AddAssertion(RegExpTree* tree);
   void NewAlternative();  // '|'
   // Attempt to add a quantifier to the last atom added. The return value
@@ -30,17 +35,30 @@
                            intptr_t max,
                            RegExpQuantifier::QuantifierType type);
   RegExpTree* ToRegExp();
+  RegExpFlags flags() const { return flags_; }
+  bool ignore_case() const { return flags_.IgnoreCase(); }
+  bool is_multi_line() const { return flags_.IsMultiLine(); }
+  bool is_dot_all() const { return flags_.IsDotAll(); }
 
  private:
+  static const uint16_t kNoPendingSurrogate = 0;
+  void AddLeadSurrogate(uint16_t lead_surrogate);
+  void AddTrailSurrogate(uint16_t trail_surrogate);
+  void FlushPendingSurrogate();
   void FlushCharacters();
   void FlushText();
   void FlushTerms();
+  bool NeedsDesugaringForUnicode(RegExpCharacterClass* cc);
+  bool NeedsDesugaringForIgnoreCase(uint32_t c);
 
   Zone* zone() const { return zone_; }
+  bool is_unicode() const { return flags_.IsUnicode(); }
 
   Zone* zone_;
   bool pending_empty_;
+  RegExpFlags flags_;
   ZoneGrowableArray<uint16_t>* characters_;
+  uint16_t pending_surrogate_;
   GrowableArray<RegExpTree*> terms_;
   GrowableArray<RegExpTree*> text_;
   GrowableArray<RegExpTree*> alternatives_;
@@ -56,16 +74,15 @@
 
 class RegExpParser : public ValueObject {
  public:
-  RegExpParser(const String& in, String* error, bool multiline_mode);
+  RegExpParser(const String& in, String* error, RegExpFlags regexp_flags);
 
   static void ParseRegExp(const String& input,
-                          bool multiline,
+                          RegExpFlags regexp_flags,
                           RegExpCompileData* result);
 
   RegExpTree* ParsePattern();
   RegExpTree* ParseDisjunction();
   RegExpTree* ParseGroup();
-  RegExpTree* ParseCharacterClass();
 
   // Parses a {...,...} quantifier and stores the range in the given
   // out parameters.
@@ -78,6 +95,24 @@
   // Checks whether the following is a length-digit hexadecimal number,
   // and sets the value if it is.
   bool ParseHexEscape(intptr_t length, uint32_t* value);
+  bool ParseUnicodeEscape(uint32_t* value);
+  bool ParseUnlimitedLengthHexNumber(uint32_t max_value, uint32_t* value);
+
+  // Parses either {UNICODE_PROPERTY_NAME=UNICODE_PROPERTY_VALUE} or
+  // the shorthand {UNICODE_PROPERTY_NAME_OR_VALUE} and stores the
+  // result in the given out parameters. If the shorthand is used,
+  // nothing will be added to name_2.
+  bool ParsePropertyClassName(ZoneGrowableArray<char>* name_1,
+                              ZoneGrowableArray<char>* name_2);
+  // Adds the specified unicode property to the provided character range.
+  bool AddPropertyClassRange(ZoneGrowableArray<CharacterRange>* add_to,
+                             bool negate,
+                             ZoneGrowableArray<char>* name_1,
+                             ZoneGrowableArray<char>* name_2);
+  // Returns a regexp node that corresponds to one of these unicode
+  // property sequences: "Any", "ASCII", "Assigned".
+  RegExpTree* GetPropertySequence(ZoneGrowableArray<char>* name_1);
+  RegExpTree* ParseCharacterClass(const RegExpBuilder* builder);
 
   uint32_t ParseOctalLiteral();
 
@@ -87,7 +122,10 @@
   // can be reparsed.
   bool ParseBackReferenceIndex(intptr_t* index_out);
 
-  CharacterRange ParseClassAtom(uint16_t* char_class);
+  // Attempts to parse a possible escape within a character class.
+  bool ParseClassEscape(ZoneGrowableArray<CharacterRange>* ranges,
+                        bool add_unicode_case_equivalents,
+                        uint32_t* char_out);
   void ReportError(const char* message);
   void Advance();
   void Advance(intptr_t dist);
@@ -100,6 +138,9 @@
   void set_contains_anchor() { contains_anchor_ = true; }
   intptr_t captures_started() { return captures_started_; }
   intptr_t position() { return next_pos_ - 1; }
+  bool is_unicode() const { return top_level_flags_.IsUnicode(); }
+
+  static bool IsSyntaxCharacterOrSlash(uint32_t c);
 
   static const intptr_t kMaxCaptures = 1 << 16;
   static const uint32_t kEndMarker = (1 << 21);
@@ -120,9 +161,10 @@
                       RegExpLookaround::Type lookaround_type,
                       intptr_t disjunction_capture_index,
                       const RegExpCaptureName* capture_name,
+                      RegExpFlags flags,
                       Zone* zone)
         : previous_state_(previous_state),
-          builder_(new (zone) RegExpBuilder()),
+          builder_(new (zone) RegExpBuilder(flags)),
           group_type_(group_type),
           lookaround_type_(lookaround_type),
           disjunction_capture_index_(disjunction_capture_index),
@@ -198,6 +240,7 @@
   bool has_more() { return has_more_; }
   bool has_next() { return next_pos_ < in().Length(); }
   uint32_t Next();
+  uint32_t ReadNext(bool update_position);
   const String& in() { return in_; }
   void ScanForCaptures();
 
@@ -212,7 +255,7 @@
   // The capture count is only valid after we have scanned for captures.
   intptr_t capture_count_;
   bool has_more_;
-  bool multiline_;
+  RegExpFlags top_level_flags_;
   bool simple_;
   bool contains_anchor_;
   bool is_scanned_for_captures_;
diff --git a/runtime/vm/regexp_test.cc b/runtime/vm/regexp_test.cc
index 531f12d..f800931 100644
--- a/runtime/vm/regexp_test.cc
+++ b/runtime/vm/regexp_test.cc
@@ -16,7 +16,7 @@
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   const RegExp& regexp =
-      RegExp::Handle(RegExpEngine::CreateRegExp(thread, pat, false, false));
+      RegExp::Handle(RegExpEngine::CreateRegExp(thread, pat, RegExpFlags()));
   const Smi& idx = Smi::Handle(Smi::New(0));
   return IRRegExpMacroAssembler::Execute(regexp, str, idx, /*sticky=*/false,
                                          zone);
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index d7a9fc6..ff9aa15 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -75,12 +75,11 @@
 
   const bool is_getter = Field::IsGetterName(function_name);
   if (is_getter) {
-    demangled ^= Field::NameFromGetter(function_name);
+    demangled = Field::NameFromGetter(function_name);
   }
 
   if (Function::IsDynamicInvocationForwarderName(function_name)) {
-    demangled ^=
-        Function::DemangleDynamicInvocationForwarderName(function_name);
+    demangled = Function::DemangleDynamicInvocationForwarderName(function_name);
 #ifdef DART_PRECOMPILED_RUNTIME
     // In precompiled mode, the non-dynamic version of the function may be
     // tree-shaken away, so can't necessarily resolve the demanged name.
@@ -112,20 +111,20 @@
   // Now look for an instance function whose name matches function_name
   // in the class.
   while (!cls.IsNull()) {
-    function ^= cls.LookupDynamicFunction(function_name);
+    function = cls.LookupDynamicFunction(function_name);
     if (!function.IsNull()) {
       return function.raw();
     }
     // Getter invocation might actually be a method extraction.
     if (FLAG_lazy_dispatchers) {
       if (is_getter && function.IsNull()) {
-        function ^= cls.LookupDynamicFunction(demangled);
+        function = cls.LookupDynamicFunction(demangled);
         if (!function.IsNull() && allow_add) {
           // We were looking for the getter but found a method with the same
           // name. Create a method extractor and return it.
           // The extractor does not exist yet, so using GetMethodExtractor is
           // not necessary here.
-          function ^= function.CreateMethodExtractor(function_name);
+          function = function.CreateMethodExtractor(function_name);
           return function.raw();
         }
       }
diff --git a/runtime/vm/resolver_test.cc b/runtime/vm/resolver_test.cc
deleted file mode 100644
index 6624b49..0000000
--- a/runtime/vm/resolver_test.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// 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.
-
-#include "vm/resolver.h"
-#include "platform/assert.h"
-#include "vm/class_finalizer.h"
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/object.h"
-#include "vm/symbols.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-// Setup function for invocation.
-static void SetupFunction(const char* test_library_name,
-                          const char* test_class_name,
-                          const char* test_static_function_name,
-                          bool is_static) {
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-
-  // Setup a dart class and function.
-  char script_chars[1024];
-  Utils::SNPrint(script_chars, sizeof(script_chars),
-                 "class Base {\n"
-                 "  dynCall() { return 3; }\n"
-                 "  static statCall() { return 4; }\n"
-                 "\n"
-                 "}\n"
-                 "class %s extends Base {\n"
-                 "  %s %s(String s, int i) { return i; }\n"
-                 "}\n",
-                 test_class_name, is_static ? "static" : "",
-                 test_static_function_name);
-
-  String& url = String::Handle(
-      zone, is_static ? String::New("dart-test:DartStaticResolve")
-                      : String::New("dart-test:DartDynamicResolve"));
-  String& source = String::Handle(zone, String::New(script_chars));
-  Script& script =
-      Script::Handle(zone, Script::New(url, source, RawScript::kScriptTag));
-  const String& lib_name = String::Handle(zone, String::New(test_library_name));
-  Library& lib = Library::Handle(zone, Library::New(lib_name));
-  lib.Register(thread);
-  EXPECT(CompilerTest::TestCompileScript(lib, script));
-  EXPECT(ClassFinalizer::ProcessPendingClasses());
-}
-
-// Setup a static function for invocation.
-static void SetupStaticFunction(const char* test_library_name,
-                                const char* test_class_name,
-                                const char* test_static_function_name) {
-  // Setup a static dart class and function.
-  SetupFunction(test_library_name, test_class_name, test_static_function_name,
-                true);
-}
-
-// Setup an instance  function for invocation.
-static void SetupInstanceFunction(const char* test_library_name,
-                                  const char* test_class_name,
-                                  const char* test_function_name) {
-  // Setup a static dart class and function.
-  SetupFunction(test_library_name, test_class_name, test_function_name, false);
-}
-
-ISOLATE_UNIT_TEST_CASE(DartStaticResolve) {
-  const char* test_library_name = "ResolverApp";
-  const char* test_class_name = "A";
-  const char* test_static_function_name = "static_foo";
-  const int kTestValue = 42;
-
-  // Setup a static function which can be invoked.
-  SetupStaticFunction(test_library_name, test_class_name,
-                      test_static_function_name);
-
-  const String& library_name = String::Handle(String::New(test_library_name));
-  const Library& library =
-      Library::Handle(Library::LookupLibrary(thread, library_name));
-  const String& class_name = String::Handle(String::New(test_class_name));
-  const String& static_function_name =
-      String::Handle(String::New(test_static_function_name));
-
-  // Now try to resolve and invoke the static function in this class.
-  {
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 2;
-    const Function& function = Function::Handle(Resolver::ResolveStatic(
-        library, class_name, static_function_name, kTypeArgsLen, kNumArguments,
-        Object::empty_array()));
-    EXPECT(!function.IsNull());  // No ambiguity error expected.
-    const Array& args = Array::Handle(Array::New(kNumArguments));
-    const String& arg0 = String::Handle(String::New("junk"));
-    args.SetAt(0, arg0);
-    const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
-    args.SetAt(1, arg1);
-    const Smi& retval = Smi::Handle(
-        reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
-    EXPECT_EQ(kTestValue, retval.Value());
-  }
-
-  // Now try to resolve a static function with invalid argument count.
-  {
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 1;
-    const Function& bad_function = Function::Handle(Resolver::ResolveStatic(
-        library, class_name, static_function_name, kTypeArgsLen, kNumArguments,
-        Object::empty_array()));
-    EXPECT(bad_function.IsNull());  // No ambiguity error expected.
-  }
-
-  // Hierarchy walking.
-  {
-    const String& super_static_function_name =
-        String::Handle(String::New("statCall"));
-    const String& super_class_name = String::Handle(String::New("Base"));
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 0;
-    const Function& super_function = Function::Handle(Resolver::ResolveStatic(
-        library, super_class_name, super_static_function_name, kTypeArgsLen,
-        kNumArguments, Object::empty_array()));
-    EXPECT(!super_function.IsNull());  // No ambiguity error expected.
-  }
-}
-
-ISOLATE_UNIT_TEST_CASE(DartDynamicResolve) {
-  const char* test_library_name = "ResolverApp";
-  const char* test_class_name = "A";
-  const char* test_function_name = "foo";
-  const int kTestValue = 42;
-
-  // Setup a function which can be invoked.
-  SetupInstanceFunction(test_library_name, test_class_name, test_function_name);
-
-  // Now create an instance object of the class and try to
-  // resolve a function in it.
-  const String& lib_name = String::Handle(String::New(test_library_name));
-  const Library& lib =
-      Library::Handle(Library::LookupLibrary(thread, lib_name));
-  ASSERT(!lib.IsNull());
-  const Class& cls = Class::Handle(
-      lib.LookupClass(String::Handle(Symbols::New(thread, test_class_name))));
-  EXPECT(!cls.IsNull());  // No ambiguity error expected.
-
-  Instance& receiver = Instance::Handle(Instance::New(cls));
-  const String& function_name = String::Handle(String::New(test_function_name));
-
-  // Now try to resolve and invoke the instance function in this class.
-  {
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 3;
-    ArgumentsDescriptor args_desc(
-        Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
-    const Function& function = Function::Handle(
-        Resolver::ResolveDynamic(receiver, function_name, args_desc));
-    EXPECT(!function.IsNull());
-    const Array& args = Array::Handle(Array::New(kNumArguments));
-    args.SetAt(0, receiver);
-    const String& arg0 = String::Handle(String::New("junk"));
-    args.SetAt(1, arg0);
-    const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
-    args.SetAt(2, arg1);
-    const Smi& retval = Smi::Handle(
-        reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
-    EXPECT_EQ(kTestValue, retval.Value());
-  }
-
-  // Now try to resolve an instance function with invalid argument count.
-  {
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 1;
-    ArgumentsDescriptor args_desc(
-        Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
-    const Function& bad_function = Function::Handle(
-        Resolver::ResolveDynamic(receiver, function_name, args_desc));
-    EXPECT(bad_function.IsNull());
-  }
-
-  // Hierarchy walking.
-  {
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 1;
-    ArgumentsDescriptor args_desc(
-        Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
-    const String& super_function_name = String::Handle(String::New("dynCall"));
-    const Function& super_function = Function::Handle(
-        Resolver::ResolveDynamic(receiver, super_function_name, args_desc));
-    EXPECT(!super_function.IsNull());
-  }
-}
-
-}  // namespace dart
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index da70f90..674623b 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -26,6 +26,7 @@
 #include "vm/service_isolate.h"
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
+#include "vm/thread.h"
 #include "vm/thread_registry.h"
 #include "vm/type_testing_stubs.h"
 
@@ -237,7 +238,7 @@
   }
   if (length.IsSmi()) {
     const intptr_t len = Smi::Cast(length).Value();
-    if (len >= 0 && len <= Array::kMaxElements) {
+    if (Array::IsValidLength(len)) {
       const Array& array = Array::Handle(zone, Array::New(len, Heap::kNew));
       arguments.SetReturn(array);
       TypeArguments& element_type =
@@ -975,8 +976,10 @@
                              StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* caller_frame = iterator.NextFrame();
   ASSERT(caller_frame != NULL);
-  const Code& orig_stub = Code::Handle(
-      zone, isolate->debugger()->GetPatchedStubAddress(caller_frame->pc()));
+  Code& orig_stub = Code::Handle(zone);
+  if (!caller_frame->is_interpreted()) {
+    orig_stub = isolate->debugger()->GetPatchedStubAddress(caller_frame->pc());
+  }
   const Error& error =
       Error::Handle(zone, isolate->debugger()->PauseBreakpoint());
   ThrowIfError(error);
@@ -1067,7 +1070,7 @@
     result = target_function.raw();
   }
   // May be null if --no-lazy-dispatchers, in which case dispatch will be
-  // handled by InvokeNoSuchMethodDispatcher.
+  // handled by NoSuchMethodFromCallStub.
   ASSERT(!result.IsNull() || !FLAG_lazy_dispatchers);
   return result.raw();
 }
@@ -1670,7 +1673,7 @@
 // Arg1: ICData or MegamorphicCache
 // Arg2: arguments descriptor array
 // Arg3: arguments array
-DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) {
+DEFINE_RUNTIME_ENTRY(NoSuchMethodFromCallStub, 4) {
   ASSERT(!FLAG_lazy_dispatchers);
   const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
   const Object& ic_data_or_cache = Object::Handle(zone, arguments.ArgAt(1));
@@ -1717,7 +1720,7 @@
     String& field_name =
         String::Handle(zone, Field::NameFromGetter(target_name));
     while (!cls.IsNull()) {
-      function ^= cls.LookupDynamicFunction(field_name);
+      function = cls.LookupDynamicFunction(field_name);
       if (!function.IsNull()) {
         CLOSURIZE(function);
         return;
@@ -1745,12 +1748,12 @@
         String::Handle(zone, Field::GetterName(target_name));
     ArgumentsDescriptor args_desc(orig_arguments_desc);
     while (!cls.IsNull()) {
-      function ^= cls.LookupDynamicFunction(target_name);
+      function = cls.LookupDynamicFunction(target_name);
       if (!function.IsNull()) {
         ASSERT(!function.AreValidArguments(args_desc, NULL));
         break;  // mismatch, invoke noSuchMethod
       }
-      function ^= cls.LookupDynamicFunction(getter_name);
+      function = cls.LookupDynamicFunction(getter_name);
       if (!function.IsNull()) {
         const Array& getter_arguments = Array::Handle(Array::New(1));
         getter_arguments.SetAt(0, receiver);
@@ -1778,24 +1781,31 @@
 }
 
 // Invoke appropriate noSuchMethod function.
-// Arg0: receiver (closure object)
+// Arg0: receiver
+// Arg1: function
 // Arg1: arguments descriptor array.
-// Arg2: arguments array.
-DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) {
-  const Closure& receiver = Closure::CheckedHandle(zone, arguments.ArgAt(0));
+// Arg3: arguments array.
+DEFINE_RUNTIME_ENTRY(NoSuchMethodFromPrologue, 4) {
+  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+  const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(1));
   const Array& orig_arguments_desc =
-      Array::CheckedHandle(zone, arguments.ArgAt(1));
-  const Array& orig_arguments = Array::CheckedHandle(zone, arguments.ArgAt(2));
+      Array::CheckedHandle(zone, arguments.ArgAt(2));
+  const Array& orig_arguments = Array::CheckedHandle(zone, arguments.ArgAt(3));
 
-  // For closure the function name is always 'call'. Replace it with the
-  // name of the closurized function so that exception contains more
-  // relevant information.
-  const Function& function = Function::Handle(receiver.function());
-  ASSERT(!function.IsNull());
-  const String& original_function_name =
-      String::Handle(function.QualifiedUserVisibleName());
-  const Object& result = Object::Handle(DartEntry::InvokeNoSuchMethod(
-      receiver, original_function_name, orig_arguments, orig_arguments_desc));
+  String& orig_function_name = String::Handle(zone);
+  if ((function.kind() == RawFunction::kClosureFunction) ||
+      (function.kind() == RawFunction::kImplicitClosureFunction)) {
+    // For closure the function name is always 'call'. Replace it with the
+    // name of the closurized function so that exception contains more
+    // relevant information.
+    orig_function_name = function.QualifiedUserVisibleName();
+  } else {
+    orig_function_name = function.name();
+  }
+
+  const Object& result = Object::Handle(
+      zone, DartEntry::InvokeNoSuchMethod(receiver, orig_function_name,
+                                          orig_arguments, orig_arguments_desc));
   ThrowIfError(result);
   arguments.SetReturn(result);
 }
@@ -1956,13 +1966,13 @@
     for (intptr_t i = 0; i < num_frames; i++) {
       ActivationFrame* frame = stack->FrameAt(i);
 #ifndef DART_PRECOMPILED_RUNTIME
-      if (!frame->is_interpreted()) {
+      if (!frame->IsInterpreted()) {
         // Ensure that we have unoptimized code.
         frame->function().EnsureHasCompiledUnoptimizedCode();
       }
       // TODO(regis): Provide var descriptors in kernel bytecode.
       const int num_vars =
-          frame->is_interpreted() ? 0 : frame->NumLocalVariables();
+          frame->IsInterpreted() ? 0 : frame->NumLocalVariables();
 #else
       // Variable locations and number are unknown when precompiling.
       const int num_vars = 0;
@@ -2122,8 +2132,14 @@
   ASSERT(FLAG_enable_interpreter || optimizing_compilation);
   ASSERT((!optimizing_compilation) || function.HasCode());
 
-  if ((!optimizing_compilation) ||
+#if defined(PRODUCT)
+  if (!optimizing_compilation ||
       Compiler::CanOptimizeFunction(thread, function)) {
+#else
+  if ((!optimizing_compilation && !Debugger::IsDebugging(thread, function)) ||
+      (optimizing_compilation &&
+       Compiler::CanOptimizeFunction(thread, function))) {
+#endif  // defined(PRODUCT)
     if (FLAG_background_compilation) {
       if (FLAG_enable_inlining_annotations) {
         FATAL("Cannot enable inlining annotations and background compilation");
@@ -2743,6 +2759,7 @@
 }
 
 extern "C" void DFLRT_EnterSafepoint(NativeArguments __unusable_) {
+  CHECK_STACK_ALIGNMENT;
   Thread* thread = Thread::Current();
   ASSERT(thread->top_exit_frame_info() != 0);
   ASSERT(thread->execution_state() == Thread::kThreadInNative);
@@ -2751,6 +2768,7 @@
 DEFINE_RAW_LEAF_RUNTIME_ENTRY(EnterSafepoint, 0, false, &DFLRT_EnterSafepoint);
 
 extern "C" void DFLRT_ExitSafepoint(NativeArguments __unusable_) {
+  CHECK_STACK_ALIGNMENT;
   Thread* thread = Thread::Current();
   ASSERT(thread->top_exit_frame_info() != 0);
   ASSERT(thread->execution_state() == Thread::kThreadInNative);
@@ -2758,4 +2776,29 @@
 }
 DEFINE_RAW_LEAF_RUNTIME_ENTRY(ExitSafepoint, 0, false, &DFLRT_ExitSafepoint);
 
+// Not registered as a runtime entry because we can't use Thread to look it up.
+extern "C" Thread* DLRT_GetThreadForNativeCallback() {
+  Thread* const thread = Thread::Current();
+  if (thread == nullptr) {
+    FATAL("Cannot invoke native callback outside an isolate.");
+  }
+  if (thread->no_callback_scope_depth() != 0) {
+    FATAL("Cannot invoke native callback when API callbacks are prohibited.");
+  }
+  if (!thread->IsMutatorThread()) {
+    FATAL("Native callbacks must be invoked on the mutator thread.");
+  }
+  return thread;
+}
+
+extern "C" void DLRT_VerifyCallbackIsolate(int32_t callback_id,
+                                           uword return_address) {
+  Thread::Current()->VerifyCallbackIsolate(callback_id, return_address);
+}
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(
+    VerifyCallbackIsolate,
+    1,
+    false /* is_float */,
+    reinterpret_cast<RuntimeFunction>(&DLRT_VerifyCallbackIsolate));
+
 }  // namespace dart
diff --git a/runtime/vm/runtime_entry.h b/runtime/vm/runtime_entry.h
index 85e9d7f2..f072c14 100644
--- a/runtime/vm/runtime_entry.h
+++ b/runtime/vm/runtime_entry.h
@@ -145,6 +145,9 @@
 RUNTIME_ENTRY_LIST(DECLARE_RUNTIME_ENTRY)
 LEAF_RUNTIME_ENTRY_LIST(DECLARE_LEAF_RUNTIME_ENTRY)
 
+// Expected to be called inside a safepoint.
+extern "C" Thread* DLRT_GetThreadForNativeCallback();
+
 const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason);
 
 void DeoptimizeAt(const Code& optimized_code, StackFrame* frame);
diff --git a/runtime/vm/runtime_entry_arm.cc b/runtime/vm/runtime_entry_arm.cc
index 7f84226..9c7585e 100644
--- a/runtime/vm/runtime_entry_arm.cc
+++ b/runtime/vm/runtime_entry_arm.cc
@@ -47,17 +47,21 @@
                                 intptr_t argument_count) {
   if (runtime_entry->is_leaf()) {
     ASSERT(argument_count == runtime_entry->argument_count());
-    __ LoadFromOffset(kWord, TMP, THR, Thread::OffsetFromThread(runtime_entry));
-    __ str(TMP, Address(THR, Thread::vm_tag_offset()));
+    __ LoadFromOffset(
+        kWord, TMP, THR,
+        compiler::target::Thread::OffsetFromThread(runtime_entry));
+    __ str(TMP, Address(THR, compiler::target::Thread::vm_tag_offset()));
     __ blx(TMP);
     __ LoadImmediate(TMP, VMTag::kDartCompiledTagId);
-    __ str(TMP, Address(THR, Thread::vm_tag_offset()));
+    __ str(TMP, Address(THR, compiler::target::Thread::vm_tag_offset()));
     ASSERT((kAbiPreservedCpuRegs & (1 << THR)) != 0);
     ASSERT((kAbiPreservedCpuRegs & (1 << PP)) != 0);
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
-    __ LoadFromOffset(kWord, R9, THR, Thread::OffsetFromThread(runtime_entry));
+    __ LoadFromOffset(
+        kWord, R9, THR,
+        compiler::target::Thread::OffsetFromThread(runtime_entry));
     __ LoadImmediate(R4, argument_count);
     __ BranchLinkToRuntime();
   }
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index bb2eca9..b0c241e 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -31,9 +31,9 @@
   V(NonBoolTypeError)                                                          \
   V(InstantiateType)                                                           \
   V(InstantiateTypeArguments)                                                  \
-  V(InvokeClosureNoSuchMethod)                                                 \
+  V(NoSuchMethodFromCallStub)                                                  \
+  V(NoSuchMethodFromPrologue)                                                  \
   V(InvokeNoSuchMethod)                                                        \
-  V(InvokeNoSuchMethodDispatcher)                                              \
   V(MegamorphicCacheMissHandler)                                               \
   V(OptimizeInvokedFunction)                                                   \
   V(TraceICCall)                                                               \
@@ -79,10 +79,13 @@
   V(double, LibcAsin, double)                                                  \
   V(double, LibcAtan, double)                                                  \
   V(double, LibcAtan2, double, double)                                         \
-  V(RawBool*, CaseInsensitiveCompareUC16, RawString*, RawSmi*, RawSmi*,        \
+  V(RawBool*, CaseInsensitiveCompareUCS2, RawString*, RawSmi*, RawSmi*,        \
+    RawSmi*)                                                                   \
+  V(RawBool*, CaseInsensitiveCompareUTF16, RawString*, RawSmi*, RawSmi*,       \
     RawSmi*)                                                                   \
   V(void, EnterSafepoint)                                                      \
-  V(void, ExitSafepoint)
+  V(void, ExitSafepoint)                                                       \
+  V(void, VerifyCallbackIsolate, int32_t, uword)
 
 }  // namespace dart
 
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index e96f9a5..1db81b5 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -8,6 +8,7 @@
 #include "include/dart_native_api.h"
 #include "platform/globals.h"
 
+#include "platform/unicode.h"
 #include "vm/base64.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/cpu.h"
@@ -41,7 +42,6 @@
 #include "vm/symbols.h"
 #include "vm/timeline.h"
 #include "vm/type_table.h"
-#include "vm/unicode.h"
 #include "vm/version.h"
 
 namespace dart {
@@ -117,7 +117,7 @@
 StreamInfo Service::gc_stream("GC");
 StreamInfo Service::echo_stream("_Echo");
 StreamInfo Service::graph_stream("_Graph");
-StreamInfo Service::logging_stream("_Logging");
+StreamInfo Service::logging_stream("Logging");
 StreamInfo Service::extension_stream("Extension");
 StreamInfo Service::timeline_stream("Timeline");
 
@@ -263,6 +263,14 @@
   return false;
 }
 
+static bool CheckProfilerDisabled(Thread* thread, JSONStream* js) {
+  if (Profiler::sample_buffer() == NULL) {
+    js->PrintError(kFeatureDisabled, "Profiler is disabled.");
+    return true;
+  }
+  return false;
+}
+
 static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) {
   if ((s == NULL) || (*s == '\0')) {
     // Empty string.
@@ -1412,7 +1420,7 @@
     for (intptr_t i = 0; i < num_libs; i++) {
       lib ^= libs.At(i);
       ASSERT(!lib.IsNull());
-      scripts ^= lib.LoadedScripts();
+      scripts = lib.LoadedScripts();
       for (intptr_t j = 0; j < scripts.Length(); j++) {
         script ^= scripts.At(j);
         ASSERT(!script.IsNull());
@@ -1671,7 +1679,7 @@
   for (intptr_t i = 0; i < libs.Length(); i++) {
     lib ^= libs.At(i);
     ASSERT(!lib.IsNull());
-    private_key ^= lib.private_key();
+    private_key = lib.private_key();
     if (private_key.Equals(id)) {
       lib_found = true;
       break;
@@ -1707,7 +1715,7 @@
     for (i = 0; i < loaded_scripts.Length(); i++) {
       script ^= loaded_scripts.At(i);
       ASSERT(!script.IsNull());
-      script_url ^= script.url();
+      script_url = script.url();
       if (script_url.Equals(requested_url) &&
           (timestamp == script.load_timestamp())) {
         return script.raw();
@@ -1747,7 +1755,7 @@
       return Object::sentinel().raw();
     }
     Function& func = Function::Handle(zone);
-    func ^= isolate->ClosureFunctionFromIndex(id);
+    func = isolate->ClosureFunctionFromIndex(id);
     if (func.IsNull()) {
       return Object::sentinel().raw();
     }
@@ -1797,7 +1805,7 @@
       return Object::sentinel().raw();
     }
     Function& func = Function::Handle(zone);
-    func ^= cls.ImplicitClosureFunctionFromIndex(id);
+    func = cls.ImplicitClosureFunctionFromIndex(id);
     if (func.IsNull()) {
       return Object::sentinel().raw();
     }
@@ -1813,7 +1821,7 @@
       return Object::sentinel().raw();
     }
     Function& func = Function::Handle(zone);
-    func ^= cls.InvocationDispatcherFunctionFromIndex(id);
+    func = cls.InvocationDispatcherFunctionFromIndex(id);
     if (func.IsNull()) {
       return Object::sentinel().raw();
     }
@@ -2084,7 +2092,7 @@
             slot_offset.Value() - (Array::element_offset(0) >> kWordSizeLog2);
         jselement.AddProperty("parentListIndex", element_index);
       } else if (source.IsInstance()) {
-        source_class ^= source.clazz();
+        source_class = source.clazz();
         parent_field_map = source_class.OffsetToFieldMap();
         intptr_t offset = slot_offset.Value();
         if (offset > 0 && offset < parent_field_map.Length()) {
@@ -2195,7 +2203,7 @@
           }
         }
       } else if (element.IsInstance()) {
-        element_class ^= element.clazz();
+        element_class = element.clazz();
         element_field_map = element_class.OffsetToFieldMap();
         intptr_t offset = slot_offset.Value();
         if (offset > 0 && offset < element_field_map.Length()) {
@@ -2639,14 +2647,14 @@
     if (frame->function().is_static()) {
       const Class& cls = Class::Handle(zone, frame->function().Owner());
       if (!cls.IsTopLevel()) {
-        klass_name ^= cls.UserVisibleName();
+        klass_name = cls.UserVisibleName();
       }
-      library_uri ^= Library::Handle(zone, cls.library()).url();
+      library_uri = Library::Handle(zone, cls.library()).url();
       isStatic = !cls.IsTopLevel();
     } else {
       const Class& method_cls = Class::Handle(zone, frame->function().origin());
-      library_uri ^= Library::Handle(zone, method_cls.library()).url();
-      klass_name ^= method_cls.UserVisibleName();
+      library_uri = Library::Handle(zone, method_cls.library()).url();
+      klass_name = method_cls.UserVisibleName();
     }
   } else {
     // building scope in the context of a given object
@@ -2666,7 +2674,7 @@
     }
     if (obj.IsLibrary()) {
       const Library& lib = Library::Cast(obj);
-      library_uri ^= lib.url();
+      library_uri = lib.url();
     } else if (obj.IsClass() || ((obj.IsInstance() || obj.IsNull()) &&
                                  !ContainsNonInstance(obj))) {
       Class& cls = Class::Handle(zone);
@@ -2675,7 +2683,7 @@
       } else {
         Instance& instance = Instance::Handle(zone);
         instance ^= obj.raw();
-        cls ^= instance.clazz();
+        cls = instance.clazz();
       }
       if (cls.id() < kInstanceCid || cls.id() == kTypeArgumentsCid) {
         js->PrintError(
@@ -2685,9 +2693,9 @@
       }
 
       if (!cls.IsTopLevel()) {
-        klass_name ^= cls.UserVisibleName();
+        klass_name = cls.UserVisibleName();
       }
-      library_uri ^= Library::Handle(zone, cls.library()).url();
+      library_uri = Library::Handle(zone, cls.library()).url();
     } else {
       js->PrintError(kInvalidParams,
                      "%s: invalid 'targetId' parameter: "
@@ -2741,7 +2749,7 @@
       c++;
     }
     if (c > value) {
-      s ^= String::New(zone->MakeCopyOfStringN(value, c - value));
+      s = String::New(zone->MakeCopyOfStringN(value, c - value));
       values.Add(s);
     }
     switch (*c) {
@@ -3815,13 +3823,12 @@
     NULL,
 };
 
-static const MethodParameter* write_cpu_profile_timeline_params[] = {
-    RUNNABLE_ISOLATE_PARAMETER,
-    NULL,
-};
-
 // TODO(johnmccutchan): Rename this to GetCpuSamples.
 static bool GetCpuProfile(Thread* thread, JSONStream* js) {
+  if (CheckProfilerDisabled(thread, js)) {
+    return true;
+  }
+
   Profile::TagOrder tag_order =
       EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
   intptr_t extra_tags = 0;
@@ -3846,6 +3853,10 @@
 };
 
 static bool GetCpuProfileTimeline(Thread* thread, JSONStream* js) {
+  if (CheckProfilerDisabled(thread, js)) {
+    return true;
+  }
+
   Profile::TagOrder tag_order =
       EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
   int64_t time_origin_micros =
@@ -3858,7 +3869,19 @@
   return true;
 }
 
+static const MethodParameter* write_cpu_profile_timeline_params[] = {
+    RUNNABLE_ISOLATE_PARAMETER,
+    new EnumParameter("tags", true, tags_enum_names),
+    new Int64Parameter("timeOriginMicros", false),
+    new Int64Parameter("timeExtentMicros", false),
+    NULL,
+};
+
 static bool WriteCpuProfileTimeline(Thread* thread, JSONStream* js) {
+  if (CheckProfilerDisabled(thread, js)) {
+    return true;
+  }
+
   Profile::TagOrder tag_order =
       EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
   int64_t time_origin_micros =
@@ -3868,6 +3891,7 @@
   bool code_trie = BoolParameter::Parse(js->LookupParam("code"), true);
   ProfilerService::AddToTimeline(tag_order, time_origin_micros,
                                  time_extent_micros, code_trie);
+  PrintSuccess(js);  // The "result" is a side-effect in the timeline.
   return true;
 }
 
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index 4b05099..3d2cb73 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -15,7 +15,7 @@
 namespace dart {
 
 #define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 14
+#define SERVICE_PROTOCOL_MINOR_VERSION 17
 
 class Array;
 class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index e3c2fd1..e993091 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.16
+# Dart VM Service Protocol 3.17
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.16_ of the Dart VM Service Protocol. This
+This document describes of _version 3.17_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -75,6 +75,7 @@
   - [Isolate](#isolate)
   - [Library](#library)
   - [LibraryDependency](#librarydependency)
+  - [LogRecord](#logrecord)
   - [MapAssociation](#mapassociation)
   - [MemoryUsage](#memoryusage)
   - [Message](#message)
@@ -546,7 +547,7 @@
 If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
 result of this evaluation are ignored. Defaults to false if not provided.
 
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
 If an error occurs while evaluating the expression, an [@Error](#error)
@@ -579,7 +580,7 @@
 If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
 result of this evaluation are ignored. Defaults to false if not provided.
 
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
 If an error occurs while evaluating the expression, an [@Error](#error)
@@ -947,6 +948,7 @@
 GC | GC
 Extension | Extension
 Timeline | TimelineEvents
+Logging | Logging
 
 Additionally, some embedders provide the _Stdout_ and _Stderr_
 streams.  These streams allow the client to subscribe to writes to
@@ -1424,6 +1426,11 @@
   //   IsolateReloaded
   //   IsolateSpawn
   string status [optional];
+
+  // LogRecord data.
+  //
+  // This is provided for the Logging event.
+  LogRecord logRecord [optional];
 }
 ```
 
@@ -1506,6 +1513,9 @@
 
   // Event from dart:developer.postEvent.
   Extension
+
+  // Event from dart:developer.log.
+  Logging
 }
 ```
 
@@ -2214,6 +2224,39 @@
 
 A _LibraryDependency_ provides information about an import or export.
 
+### LogRecord
+
+```
+class LogRecord extends Response {
+  // The log message.
+  @Instance message;
+
+  // The timestamp.
+  int time;
+
+  // The severity level (a value between 0 and 2000).
+  //
+  // See the package:logging `Level` class for an overview of the possible
+  // values.
+  int level;
+
+  // A monotonically increasing sequence number.
+  int sequenceNumber;
+
+  // The name of the source of the log message.
+  @Instance loggerName;
+
+  // The zone where the log was emitted.
+  @Instance zone;
+
+  // An error object associated with this log event.
+  @Instance error;
+
+  // A stack trace associated with this log event.
+  @Instance stackTrace;
+}
+```
+
 ### MapAssociation
 
 ```
@@ -2453,6 +2496,10 @@
   // The library which owns this script.
   @Library library;
 
+  int lineOffset [optional];
+
+  int columnOffset [optional];
+
   // The source code for this script. This can be null for certain built-in
   // scripts.
   string source [optional];
@@ -2807,5 +2854,6 @@
 3.14 | Flag 'profile_period' can now be set at runtime, allowing for the profiler sample rate to be changed while the program is running.
 3.15 | Added `disableBreakpoints` parameter to `invoke`, `evaluate`, and `evaluateInFrame`.
 3.16 | Add 'getMemoryUsage' RPC and 'MemoryUsage' object.
+3.17 | Add 'Logging' event kind and the LogRecord class.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service/service_dev.md b/runtime/vm/service/service_dev.md
index dbfa952..5daf941 100644
--- a/runtime/vm/service/service_dev.md
+++ b/runtime/vm/service/service_dev.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.17-dev
+# Dart VM Service Protocol 3.18-dev
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.17-dev_ of the Dart VM Service Protocol. This
+This document describes of _version 3.18-dev_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -75,6 +75,7 @@
   - [Isolate](#isolate)
   - [Library](#library)
   - [LibraryDependency](#librarydependency)
+  - [LogRecord](#logrecord)
   - [MapAssociation](#mapassociation)
   - [MemoryUsage](#memoryusage)
   - [Message](#message)
@@ -546,7 +547,7 @@
 If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
 result of this evaluation are ignored. Defaults to false if not provided.
 
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
 If an error occurs while evaluating the expression, an [@Error](#error)
@@ -579,7 +580,7 @@
 If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
 result of this evaluation are ignored. Defaults to false if not provided.
 
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
 If an error occurs while evaluating the expression, an [@Error](#error)
@@ -947,6 +948,7 @@
 GC | GC
 Extension | Extension
 Timeline | TimelineEvents
+Logging | Logging
 
 Additionally, some embedders provide the _Stdout_ and _Stderr_
 streams.  These streams allow the client to subscribe to writes to
@@ -1424,6 +1426,11 @@
   //   IsolateReloaded
   //   IsolateSpawn
   string status [optional];
+
+  // LogRecord data.
+  //
+  // This is provided for the Logging event.
+  LogRecord logRecord [optional];
 }
 ```
 
@@ -1506,6 +1513,9 @@
 
   // Event from dart:developer.postEvent.
   Extension
+
+  // Event from dart:developer.log.
+  Logging
 }
 ```
 
@@ -2214,6 +2224,39 @@
 
 A _LibraryDependency_ provides information about an import or export.
 
+### LogRecord
+
+```
+class LogRecord extends Response {
+  // The log message.
+  @Instance message;
+
+  // The timestamp.
+  int time;
+
+  // The severity level (a value between 0 and 2000).
+  //
+  // See the package:logging `Level` class for an overview of the possible
+  // values.
+  int level;
+
+  // A monotonically increasing sequence number.
+  int sequenceNumber;
+
+  // The name of the source of the log message.
+  @Instance loggerName;
+
+  // The zone where the log was emitted.
+  @Instance zone;
+
+  // An error object associated with this log event.
+  @Instance error;
+
+  // A stack trace associated with this log event.
+  @Instance stackTrace;
+}
+```
+
 ### MapAssociation
 
 ```
@@ -2453,6 +2496,10 @@
   // The library which owns this script.
   @Library library;
 
+  int lineOffset [optional];
+
+  int columnOffset [optional];
+
   // The source code for this script. This can be null for certain built-in
   // scripts.
   string source [optional];
@@ -2807,5 +2854,6 @@
 3.14 | Flag 'profile_period' can now be set at runtime, allowing for the profiler sample rate to be changed while the program is running.
 3.15 | Added `disableBreakpoints` parameter to `invoke`, `evaluate`, and `evaluateInFrame`.
 3.16 | Add 'getMemoryUsage' RPC and 'MemoryUsage' object.
+3.17 | Add 'Logging' event kind and the LogRecord class.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service/service_evolution.md b/runtime/vm/service/service_evolution.md
new file mode 100644
index 0000000..c2e140a
--- /dev/null
+++ b/runtime/vm/service/service_evolution.md
@@ -0,0 +1,67 @@
+# Evolving the Dart Service Protocol
+
+This document outlines the mindset of the Dart Service Protocol designers and maintainers when it comes to extending or modifying the protocol. Any proposals or requests to update the protocol will be evaluated against the principles described below before being added to the protocol specification.
+
+## Requirements
+
+Any proposed additions to the Dart service protocol should adhere to the following principles.
+
+### Perform Only Simple Operations
+
+The API surface of the service protocol should remain as small and simple as possible. Proposed changes to the protocol will only be accepted if they meet one of the following criteria:
+
+* There is no existing combination of RPCs that achieve the behavior proposed
+* A level of atomicity is required that cannot be achieved by existing RPCs
+* Significant demonstrable performance gains can be made by adding a specialized RPC (e.g., a batch version of an existing RPC)
+
+### Avoid Introducing Side Effects
+
+In general, interacting with the service protocol should avoid changing the state of the Dart instance. Side effects introduced as the result of a service protocol request may be difficult to debug, especially if they change state in a running Dart program. Although exceptions can be made in special circumstances, service protocol APIs should:
+
+* **Be stateless.** Requests should be independent of one another. For example, assuming execution is paused and the Dart instance is effectively idle, invoking the same RPC twice should return the same result.
+* **Be predictable.** If an API must change state, the resulting state change should be obvious and expected. For example, the `SetFlag` RPC allows for specific settings in the Dart instance to be changed but does not introduce any additional side effects.
+
+### Keep Low-Powered Devices in Mind
+
+As the Dart instance may be running on a remote or low-powered device, the service protocol should only provide functionality that doesn't make assumptions about the hardware configuration the Dart instance is running on. In addition, processing should be done on the client whenever possible to maintain reasonable performance in the case where the Dart instance is running on a remote or low-powered device.
+
+Based on the principles above, any changes to the service protocol must satisfy the following:
+
+* **The proposed change must be valid for all types of devices, regardless of their performance.** For example, a request to reduce the minimal sample rate for the profiler from 50us to 10us would be rejected as low-end ARM devices are unable to handle a 10us sample period, often leading to a crash.
+* **Keep as much processing as possible on the client side to avoid slowdowns on low-end devices.** For example, dominator analysis of a heap snapshot is performed on the client side in Observatory.
+
+### Implementation Agnostic
+
+The Dart service protocol is designed to be usable by any implementation of Dart, not just the Dart VM in the official Dart SDK. As a result, the protocol must avoid exposing details of the underlying implementation through its interface. Any exposure of implementation details must only be done through private RPCs and their responses and should only be used within the context of that implementation (e.g., private RPCs provided by the Dart VM are fine to be used within Observatory but are not advertised to, and should not be used by, external clients).
+
+For example, the fact that the Dart VM currently uses a generational garbage collector may not be true in the future, so a response containing information about new and old space should not be exposed through the protocol.
+
+## FAQ
+
+**_Q: I want to get information about system X but there's no way to query for that information over the service protocol. Can we add a new RPC for this?_**
+
+**A:** Maybe! If it's not possible to achieve something through the current service protocol, adding support for that operation can be investigated. However, only RPCs which do not violate the principles stated above will be accepted into the protocol.
+
+**_Q: There's a certain series of RPCs that I invoke frequently. Can we create a single RPC for this operation?_**
+
+**A:** No, unless there is a need for the operations performed by the series of RPCs to be performed atomically or there is a significant performance benefit of performing work in a single RPC.
+
+**_Q: I'd like to do an experiment that requires changes to the service protocol. How can I do this?_**
+
+**A:** Assuming there's no significant performance impact anticipated by an experimental RPC, it's possible to add experimental functionality to the service protocol. Any experimental functionality should either be marked as private or be documented as being experimental and that it may be deprecated without notice. Experimental RPCs should have a short lifespan and be documented with an expected expiration date.
+
+Any experimental changes that are intended to be permanent must adhere to the principles described in the first section of this document.
+
+If you require assistance in adding experimental functionality to the protocol, please reach out to the maintainers at dart-service-protocol@google.com. Changes required to the Dart VM service implementation can also be handled by members of dart-service-protocol@google.com or dart-vm-team@google.com.
+
+**_Q: There's a private RPC that performs functionality that I'm looking for. Can I use it?_**
+
+**A: No, private RPCs and their responses should not be used outside of the Dart SDK.** The implementations of these RPCs and responses are subject to change without warning and unauthorized private RPC requests may be discarded in the future.
+
+**_Q: Can we make a private RPC public?_**
+
+**A:** In general, no. While some private RPCs and responses can be made public without much effort, many expose internal implementation details of the VM itself for use by VM engineers in Observatory. If there is a strong case for exposing functionality provided by a private RPC, a new public RPC will need to be defined in order to keep the protocol from exposing implementation details of the system.
+
+**_Q: I have more questions about the service protocol. Who can I contact?_**
+
+**A:** The Dart VM team is responsible for maintaining the service protocol. The current maintainers can be contacted at dart-service-protocol@google.com.
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 5822378..66ee578 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -95,7 +95,7 @@
     case kEmbedder:
       return embedder_kind();
     case kLogging:
-      return "_Logging";
+      return "Logging";
     case kDebuggerSettingsUpdate:
       return "_DebuggerSettingsUpdate";
     case kIllegal:
@@ -239,6 +239,7 @@
   }
   if (kind() == kLogging) {
     JSONObject logRecord(&jsobj, "logRecord");
+    logRecord.AddProperty("type", "LogRecord");
     logRecord.AddProperty64("sequenceNumber", log_record_.sequence_number);
     logRecord.AddPropertyTimeMillis("time", log_record_.timestamp);
     logRecord.AddProperty64("level", log_record_.level);
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index 085b11a..8a223ee 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -346,6 +346,8 @@
                      ": Isolate creation error: %s\n",
                      error);
       }
+      free(error);
+      error = nullptr;
       ServiceIsolate::SetServiceIsolate(NULL);
       ServiceIsolate::InitializingFailed();
       return;
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index aeb614e..736277a 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -35,7 +35,7 @@
     free(_msg);
   }
 
-  MessageStatus HandleMessage(Message* message) {
+  MessageStatus HandleMessage(std::unique_ptr<Message> message) {
     if (_msg != NULL) {
       free(_msg);
       _msg = NULL;
@@ -47,7 +47,7 @@
       response_obj = message->raw_obj();
     } else {
       Thread* thread = Thread::Current();
-      MessageSnapshotReader reader(message, thread);
+      MessageSnapshotReader reader(message.get(), thread);
       response_obj = reader.ReadObject();
     }
     if (response_obj.IsString()) {
@@ -64,8 +64,6 @@
       _msg = strdup(reinterpret_cast<char*>(response.DataAddr(0)));
     }
 
-    delete message;
-
     return kOK;
   }
 
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 18839b45..99726ee 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -14,13 +14,20 @@
 
 #include "vm/simulator.h"
 
+#include "lib/ffi.h"
+#include "platform/assert.h"
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/assembler/disassembler.h"
+#include "vm/compiler/backend/il.h"
+#include "vm/compiler/backend/locations.h"
+#include "vm/compiler/ffi.h"
+#include "vm/compiler/ffi_dbc_trampoline.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/constants_dbc.h"
 #include "vm/cpu.h"
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
+#include "vm/heap/safepoint.h"
 #include "vm/lockers.h"
 #include "vm/native_arguments.h"
 #include "vm/native_entry.h"
@@ -615,6 +622,7 @@
 // Calls to leaf float Dart runtime functions are based on this interface.
 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1);
 
+// Set up an exit frame for the garbage collector.
 void Simulator::Exit(Thread* thread,
                      RawObject** base,
                      RawObject** frame,
@@ -866,7 +874,7 @@
   intptr_t i;
   for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
     if (cache->data()[i + 0] == receiver_cid) {
-      top[0] = cache->data()[i + kCheckedArgs];
+      top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)];
       found = true;
       break;
     }
@@ -912,7 +920,7 @@
   for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
     if ((cache->data()[i + 0] == receiver_cid) &&
         (cache->data()[i + 1] == arg0_cid)) {
-      top[0] = cache->data()[i + kCheckedArgs];
+      top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)];
       found = true;
       break;
     }
@@ -1860,6 +1868,39 @@
   }
 
   {
+    BYTECODE(FfiCall, __D);
+    {
+      const auto& sig_desc = compiler::ffi::FfiSignatureDescriptor(
+          TypedData::Cast(Object::Handle(LOAD_CONSTANT(rD))));
+
+      // The arguments to this ffi call are on the stack at FP.
+      // kFirstLocalSlotFromFp is 0 in DBC, but the const is -1.
+      uint64_t* arg_values = reinterpret_cast<uint64_t*>(FP);
+
+      uint64_t* marshalled_args_data =
+          FfiMarshalledArguments::New(sig_desc, arg_values);
+      const auto& marshalled_args =
+          FfiMarshalledArguments(marshalled_args_data);
+
+      Exit(thread, FP, SP, pc);
+      {
+        TransitionGeneratedToNative transition(thread);
+        FfiTrampolineCall(marshalled_args_data);
+      }
+
+      const Representation result_rep = sig_desc.ResultRepresentation();
+      intptr_t result;
+      if (result_rep == kUnboxedDouble || result_rep == kUnboxedFloat) {
+        result = marshalled_args.DoubleResult();
+      } else {
+        result = marshalled_args.IntResult();
+      }
+      FP[0] = reinterpret_cast<RawObject*>(result);
+    }
+    DISPATCH();
+  }
+
+  {
     BYTECODE(OneByteStringFromCharCode, A_X);
     const intptr_t char_code = Smi::Value(RAW_CAST(Smi, FP[rD]));
     ASSERT(char_code >= 0);
@@ -2107,6 +2148,35 @@
     DISPATCH();
   }
 
+  {
+    BYTECODE(UnboxedWidthExtender, A_B_C);
+    auto rep = static_cast<SmallRepresentation>(rC);
+    const intptr_t value_32_or_64_bit = reinterpret_cast<intptr_t>(FP[rB]);
+    int32_t value = value_32_or_64_bit & kMaxUint32;  // Prevent overflow.
+    switch (rep) {
+      case kSmallUnboxedInt8:
+        // Sign extend the top 24 bits from the sign bit.
+        value <<= 24;
+        value >>= 24;
+        break;
+      case kSmallUnboxedUint8:
+        value &= 0x000000FF;  // Throw away upper bits.
+        break;
+      case kSmallUnboxedInt16:
+        // Sign extend the top 16 bits from the sign bit.
+        value <<= 16;
+        value >>= 16;
+        break;
+      case kSmallUnboxedUint16:
+        value &= 0x0000FFFF;  // Throw away upper bits.
+        break;
+      default:
+        UNREACHABLE();
+    }
+    FP[rA] = reinterpret_cast<RawObject*>(value);
+    DISPATCH();
+  }
+
 #if defined(ARCH_IS_64_BIT)
   {
     BYTECODE(WriteIntoDouble, A_D);
@@ -2405,6 +2475,43 @@
     FP[rA] = Smi::New(static_cast<intptr_t>(value32));
     DISPATCH();
   }
+
+  {
+    BYTECODE(UnboxInt64, A_D);
+    const intptr_t box_cid = SimulatorHelpers::GetClassId(FP[rD]);
+    if (box_cid == kSmiCid) {
+      const int64_t value = Smi::Value(RAW_CAST(Smi, FP[rD]));
+      FP[rA] = reinterpret_cast<RawObject*>(value);
+    } else if (box_cid == kMintCid) {
+      RawMint* mint = RAW_CAST(Mint, FP[rD]);
+      const int64_t value = mint->ptr()->value_;
+      FP[rA] = reinterpret_cast<RawObject*>(value);
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(BoxInt64, A_D);
+    const int64_t value = reinterpret_cast<int64_t>(FP[rD]);
+    if (Smi::IsValid(value)) {
+      FP[rA] = Smi::New(static_cast<intptr_t>(value));
+    } else {
+      // If the value does not fit into a Smi the following instruction is
+      // skipped. (The following instruction should be a jump to a label after
+      // the slow path allocating a Mint box and writing into the Mint box.)
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(WriteIntoMint, A_D);
+    const int64_t value = bit_cast<int64_t, RawObject*>(FP[rD]);
+    RawMint* box = RAW_CAST(Mint, FP[rA]);
+    box->ptr()->value_ = value;
+    DISPATCH();
+  }
+
 #else   // defined(ARCH_IS_64_BIT)
   {
     BYTECODE(WriteIntoDouble, A_D);
@@ -2609,6 +2716,24 @@
     UNREACHABLE();
     DISPATCH();
   }
+
+  {
+    BYTECODE(UnboxInt64, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(BoxInt64, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(WriteIntoMint, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
 #endif  // defined(ARCH_IS_64_BIT)
 
   // Return and return like instructions (Instrinsic).
@@ -2630,7 +2755,7 @@
 
     BYTECODE(ReturnTOS, 0);
     result = *SP;
-  // Fall through to the ReturnImpl.
+    // Fall through to the ReturnImpl.
 
   ReturnImpl:
     // Restore caller PC.
@@ -3018,7 +3143,7 @@
       NativeArguments native_args(thread, 5, SP + 1, SP - 4);
       INVOKE_RUNTIME(DRT_Instanceof, native_args);
     }
-  // clang-format on
+      // clang-format on
 
   InstanceOfOk:
     SP -= 4;
@@ -3727,7 +3852,7 @@
   {
     BYTECODE(StoreIndexedUint8, A_B_C);
     uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]);
-    *data = Smi::Value(RAW_CAST(Smi, FP[rC]));
+    *data = static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
     DISPATCH();
   }
 
@@ -3735,8 +3860,8 @@
     BYTECODE(StoreIndexedUntaggedUint8, A_B_C);
     uint8_t* array = reinterpret_cast<uint8_t*>(FP[rA]);
     RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    RawSmi* value = RAW_CAST(Smi, FP[rC]);
-    array[Smi::Value(index)] = Smi::Value(value);
+    array[Smi::Value(index)] =
+        static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
     DISPATCH();
   }
 
@@ -3771,9 +3896,9 @@
     BYTECODE(StoreIndexedOneByteString, A_B_C);
     RawOneByteString* array = RAW_CAST(OneByteString, FP[rA]);
     RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    RawSmi* value = RAW_CAST(Smi, FP[rC]);
     ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    array->ptr()->data()[Smi::Value(index)] = Smi::Value(value);
+    array->ptr()->data()[Smi::Value(index)] =
+        static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
     DISPATCH();
   }
 
@@ -3882,14 +4007,15 @@
   {
     BYTECODE(LoadIndexedUint8, A_B_C);
     uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
-    FP[rA] = Smi::New(*data);
+    FP[rA] = reinterpret_cast<RawObject*>(static_cast<word>(*data));
     DISPATCH();
   }
 
   {
     BYTECODE(LoadIndexedInt8, A_B_C);
-    uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
-    FP[rA] = Smi::New(*reinterpret_cast<int8_t*>(data));
+    int8_t* data = reinterpret_cast<int8_t*>(
+        SimulatorHelpers::GetTypedData(FP[rB], FP[rC]));
+    FP[rA] = reinterpret_cast<RawObject*>(static_cast<word>(*data));
     DISPATCH();
   }
 
@@ -3911,9 +4037,10 @@
 
   {
     BYTECODE(LoadIndexedUntaggedInt8, A_B_C);
-    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
+    int8_t* data = reinterpret_cast<int8_t*>(FP[rB]);
     RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    FP[rA] = Smi::New(*reinterpret_cast<int8_t*>(data + Smi::Value(index)));
+    FP[rA] = reinterpret_cast<RawObject*>(
+        static_cast<word>(data[Smi::Value(index)]));
     DISPATCH();
   }
 
@@ -3921,7 +4048,8 @@
     BYTECODE(LoadIndexedUntaggedUint8, A_B_C);
     uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
     RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    FP[rA] = Smi::New(*reinterpret_cast<uint8_t*>(data + Smi::Value(index)));
+    FP[rA] = reinterpret_cast<RawObject*>(
+        static_cast<word>(data[Smi::Value(index)]));
     DISPATCH();
   }
 
@@ -3967,7 +4095,8 @@
     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)]);
+    FP[rA] = reinterpret_cast<RawObject*>(
+        static_cast<word>(array->ptr()->data()[Smi::Value(index)]));
     DISPATCH();
   }
 
@@ -3976,7 +4105,8 @@
     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)]);
+    FP[rA] = reinterpret_cast<RawObject*>(
+        static_cast<word>(array->ptr()->data()[Smi::Value(index)]));
     DISPATCH();
   }
 
@@ -4040,8 +4170,11 @@
       pp_ = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_;
     }
 
+    RawClosure* closure =
+        Closure::RawCast(args[has_function_type_args ? 1 : 0]);
     *++SP = null_value;
-    *++SP = args[has_function_type_args ? 1 : 0];  // Closure object.
+    *++SP = closure;
+    *++SP = closure->ptr()->function_;
     *++SP = argdesc_;
     *++SP = null_value;  // Array of arguments (will be filled).
 
@@ -4069,8 +4202,8 @@
     // array of arguments.
     {
       Exit(thread, FP, SP + 1, pc);
-      NativeArguments native_args(thread, 3, SP - 2, SP - 3);
-      INVOKE_RUNTIME(DRT_InvokeClosureNoSuchMethod, native_args);
+      NativeArguments native_args(thread, 4, SP - 3, SP - 4);
+      INVOKE_RUNTIME(DRT_NoSuchMethodFromPrologue, native_args);
       UNREACHABLE();
     }
 
diff --git a/runtime/vm/simulator_dbc.h b/runtime/vm/simulator_dbc.h
index 8b87a7a..7ed6fce 100644
--- a/runtime/vm/simulator_dbc.h
+++ b/runtime/vm/simulator_dbc.h
@@ -108,6 +108,7 @@
 
   static IntrinsicHandler intrinsics_[kIntrinsicCount];
 
+  // Set up an exit frame for the garbage collector.
   void Exit(Thread* thread,
             RawObject** base,
             RawObject** exit_frame,
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index c676560..3824991 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -45,7 +45,8 @@
           RawObject::IsStringClassId(class_id) ||
           RawObject::IsTypedDataClassId(class_id) ||
           RawObject::IsExternalTypedDataClassId(class_id) ||
-          RawObject::IsTypedDataViewClassId(class_id) || class_id == kNullCid);
+          RawObject::IsTypedDataViewClassId(class_id) || class_id == kNullCid ||
+          class_id == kTransferableTypedDataCid);
 }
 
 static bool IsObjectStoreTypeId(intptr_t index) {
@@ -1461,15 +1462,16 @@
   delete finalizable_data_;
 }
 
-Message* MessageWriter::WriteMessage(const Object& obj,
-                                     Dart_Port dest_port,
-                                     Message::Priority priority) {
+std::unique_ptr<Message> MessageWriter::WriteMessage(
+    const Object& obj,
+    Dart_Port dest_port,
+    Message::Priority priority) {
   ASSERT(kind() == Snapshot::kMessage);
   ASSERT(isolate() != NULL);
 
   // Setup for long jump in case there is an exception while writing
   // the message.
-  bool has_exception = false;
+  volatile bool has_exception = false;
   {
     LongJumpScope jump;
     if (setjmp(*jump.Set()) == 0) {
@@ -1482,12 +1484,14 @@
   }
   if (has_exception) {
     ThrowException(exception_type(), exception_msg());
+  } else {
+    finalizable_data_->SerializationSucceeded();
   }
 
   MessageFinalizableData* finalizable_data = finalizable_data_;
   finalizable_data_ = NULL;
-  return new Message(dest_port, buffer(), BytesWritten(), finalizable_data,
-                     priority);
+  return Message::New(dest_port, buffer(), BytesWritten(), finalizable_data,
+                      priority);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index e4861cb..0939635e 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -442,6 +442,7 @@
   friend class Script;
   friend class SignatureData;
   friend class SubtypeTestCache;
+  friend class TransferableTypedData;
   friend class Type;
   friend class TypedDataView;
   friend class TypeArguments;
@@ -715,6 +716,7 @@
   friend class RawScript;
   friend class RawStackTrace;
   friend class RawSubtypeTestCache;
+  friend class RawTransferableTypedData;
   friend class RawType;
   friend class RawTypedDataView;
   friend class RawTypeRef;
@@ -728,22 +730,17 @@
 
 class SerializedObjectBuffer : public StackResource {
  public:
-  SerializedObjectBuffer() : StackResource(Thread::Current()), message_(NULL) {}
+  SerializedObjectBuffer()
+      : StackResource(Thread::Current()), message_(nullptr) {}
 
-  virtual ~SerializedObjectBuffer() { delete message_; }
-
-  void set_message(Message* message) {
-    ASSERT(message_ == NULL);
-    message_ = message;
+  void set_message(std::unique_ptr<Message> message) {
+    ASSERT(message_ == nullptr);
+    message_ = std::move(message);
   }
-  Message* StealMessage() {
-    Message* result = message_;
-    message_ = NULL;
-    return result;
-  }
+  std::unique_ptr<Message> StealMessage() { return std::move(message_); }
 
  private:
-  Message* message_;
+  std::unique_ptr<Message> message_;
 };
 
 class MessageWriter : public SnapshotWriter {
@@ -752,9 +749,9 @@
   explicit MessageWriter(bool can_send_any_object);
   ~MessageWriter();
 
-  Message* WriteMessage(const Object& obj,
-                        Dart_Port dest_port,
-                        Message::Priority priority);
+  std::unique_ptr<Message> WriteMessage(const Object& obj,
+                                        Dart_Port dest_port,
+                                        Message::Priority priority);
 
   MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
 
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 04f4e6a..e05f475 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -6,6 +6,7 @@
 
 #include "include/dart_tools_api.h"
 #include "platform/assert.h"
+#include "platform/unicode.h"
 #include "vm/class_finalizer.h"
 #include "vm/clustered_snapshot.h"
 #include "vm/dart_api_impl.h"
@@ -17,7 +18,6 @@
 #include "vm/snapshot.h"
 #include "vm/symbols.h"
 #include "vm/timer.h"
-#include "vm/unicode.h"
 #include "vm/unit_test.h"
 
 namespace dart {
@@ -115,12 +115,11 @@
 static void CheckEncodeDecodeMessage(Dart_CObject* root) {
   // Encode and decode the message.
   ApiMessageWriter writer;
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteCMessage(root, ILLEGAL_PORT, Message::kNormalPriority);
 
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* new_root = api_reader.ReadMessage();
-  delete message;
 
   // Check that the two messages are the same.
   CompareDartCObjects(root, new_root);
@@ -128,9 +127,9 @@
 
 static void ExpectEncodeFail(Dart_CObject* root) {
   ApiMessageWriter writer;
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteCMessage(root, ILLEGAL_PORT, Message::kNormalPriority);
-  EXPECT(message == NULL);
+  EXPECT(message == nullptr);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeNull) {
@@ -139,23 +138,21 @@
   // Write snapshot with object content.
   const Object& null_object = Object::Handle();
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(null_object, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   const Object& serialized_object = Object::Handle(reader.ReadObject());
   EXPECT(Equals(null_object, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kNull, root->type);
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeSmi1) {
@@ -164,24 +161,22 @@
   // Write snapshot with object content.
   const Smi& smi = Smi::Handle(Smi::New(124));
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   const Object& serialized_object = Object::Handle(reader.ReadObject());
   EXPECT(Equals(smi, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kInt32, root->type);
   EXPECT_EQ(smi.Value(), root->value.as_int32);
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeSmi2) {
@@ -190,30 +185,28 @@
   // Write snapshot with object content.
   const Smi& smi = Smi::Handle(Smi::New(-1));
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   const Object& serialized_object = Object::Handle(reader.ReadObject());
   EXPECT(Equals(smi, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kInt32, root->type);
   EXPECT_EQ(smi.Value(), root->value.as_int32);
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 Dart_CObject* SerializeAndDeserializeMint(const Mint& mint) {
   // Write snapshot with object content.
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(mint, ILLEGAL_PORT, Message::kNormalPriority);
 
   {
@@ -221,17 +214,16 @@
     Thread* thread = Thread::Current();
     StackZone zone(thread);
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message, thread);
+    MessageSnapshotReader reader(message.get(), thread);
     const Object& serialized_object = Object::Handle(reader.ReadObject());
     EXPECT(serialized_object.IsMint());
   }
 
   // Read object back from the snapshot into a C structure.
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_NOTNULL(root);
   CheckEncodeDecodeMessage(root);
-  delete message;
   return root;
 }
 
@@ -285,24 +277,22 @@
   // Write snapshot with object content.
   const Double& dbl = Double::Handle(Double::New(101.29));
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(dbl, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   const Object& serialized_object = Object::Handle(reader.ReadObject());
   EXPECT(Equals(dbl, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kDouble, root->type);
   EXPECT_EQ(dbl.value(), root->value.as_double);
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeTrue) {
@@ -311,11 +301,11 @@
   // Write snapshot with true object.
   const Bool& bl = Bool::True();
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(bl, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   const Object& serialized_object = Object::Handle(reader.ReadObject());
   fprintf(stderr, "%s / %s\n", bl.ToCString(), serialized_object.ToCString());
 
@@ -323,14 +313,12 @@
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kBool, root->type);
   EXPECT_EQ(true, root->value.as_bool);
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeFalse) {
@@ -339,35 +327,33 @@
   // Write snapshot with false object.
   const Bool& bl = Bool::False();
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(bl, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   const Object& serialized_object = Object::Handle(reader.ReadObject());
   EXPECT(Equals(bl, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kBool, root->type);
   EXPECT_EQ(false, root->value.as_bool);
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeCapability) {
   // Write snapshot with object content.
   const Capability& capability = Capability::Handle(Capability::New(12345));
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(capability, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   Capability& obj = Capability::Handle();
   obj ^= reader.ReadObject();
 
@@ -375,24 +361,22 @@
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kCapability, root->type);
   int64_t id = root->value.as_capability.id;
   EXPECT_EQ(12345, id);
   CheckEncodeDecodeMessage(root);
-  delete message;
 }
 
 #define TEST_ROUND_TRIP_IDENTICAL(object)                                      \
   {                                                                            \
     MessageWriter writer(true);                                                \
-    Message* message = writer.WriteMessage(                                    \
+    std::unique_ptr<Message> message = writer.WriteMessage(                    \
         Object::Handle(object), ILLEGAL_PORT, Message::kNormalPriority);       \
-    MessageSnapshotReader reader(message, thread);                             \
+    MessageSnapshotReader reader(message.get(), thread);                       \
     EXPECT(reader.ReadObject() == object);                                     \
-    delete message;                                                            \
   }
 
 ISOLATE_UNIT_TEST_CASE(SerializeSingletons) {
@@ -417,23 +401,22 @@
   // Write snapshot with object content.
   String& str = String::Handle(String::New(cstr));
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   String& serialized_str = String::Handle();
   serialized_str ^= reader.ReadObject();
   EXPECT(str.Equals(serialized_str));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_EQ(Dart_CObject_kString, root->type);
   EXPECT_STREQ(cstr, root->value.as_string);
   CheckEncodeDecodeMessage(root);
-  delete message;
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeString) {
@@ -461,18 +444,18 @@
     array.SetAt(i, smi);
   }
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   Array& serialized_array = Array::Handle();
   serialized_array ^= reader.ReadObject();
   EXPECT(array.CanonicalizeEquals(serialized_array));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_EQ(Dart_CObject_kArray, root->type);
   EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -482,8 +465,6 @@
     EXPECT_EQ(i, element->value.as_int32);
   }
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeArrayWithTypeArgument) {
@@ -498,18 +479,18 @@
     array.SetAt(i, smi);
   }
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   Array& serialized_array = Array::Handle();
   serialized_array ^= reader.ReadObject();
   EXPECT(array.CanonicalizeEquals(serialized_array));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_EQ(Dart_CObject_kArray, root->type);
   EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -519,8 +500,6 @@
     EXPECT_EQ(i, element->value.as_int32);
   }
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 TEST_CASE(FailSerializeLargeArray) {
@@ -575,25 +554,23 @@
   const int kArrayLength = 0;
   Array& array = Array::Handle(Array::New(kArrayLength));
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   Array& serialized_array = Array::Handle();
   serialized_array ^= reader.ReadObject();
   EXPECT(array.CanonicalizeEquals(serialized_array));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_EQ(Dart_CObject_kArray, root->type);
   EXPECT_EQ(kArrayLength, root->value.as_array.length);
   EXPECT(root->value.as_array.values == NULL);
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeByteArray) {
@@ -605,18 +582,18 @@
     typed_data.SetUint8(i, i);
   }
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(typed_data, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   TypedData& serialized_typed_data = TypedData::Handle();
   serialized_typed_data ^= reader.ReadObject();
   EXPECT(serialized_typed_data.IsTypedData());
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_EQ(Dart_CObject_kTypedData, root->type);
   EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
@@ -624,8 +601,6 @@
     EXPECT(root->value.as_typed_data.values[i] == i);
   }
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 #define TEST_TYPED_ARRAY(darttype, ctype)                                      \
@@ -639,16 +614,15 @@
       array.Set##darttype((i * scale), i);                                     \
     }                                                                          \
     MessageWriter writer(true);                                                \
-    Message* message =                                                         \
+    std::unique_ptr<Message> message =                                         \
         writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);    \
-    MessageSnapshotReader reader(message, thread);                             \
+    MessageSnapshotReader reader(message.get(), thread);                       \
     TypedData& serialized_array = TypedData::Handle();                         \
     serialized_array ^= reader.ReadObject();                                   \
     for (int i = 0; i < kArrayLength; i++) {                                   \
       EXPECT_EQ(static_cast<ctype>(i),                                         \
                 serialized_array.Get##darttype(i* scale));                     \
     }                                                                          \
-    delete message;                                                            \
   }
 
 #define TEST_EXTERNAL_TYPED_ARRAY(darttype, ctype)                             \
@@ -661,16 +635,15 @@
                                reinterpret_cast<uint8_t*>(data), length));     \
     intptr_t scale = array.ElementSizeInBytes();                               \
     MessageWriter writer(true);                                                \
-    Message* message =                                                         \
+    std::unique_ptr<Message> message =                                         \
         writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);    \
-    MessageSnapshotReader reader(message, thread);                             \
+    MessageSnapshotReader reader(message.get(), thread);                       \
     ExternalTypedData& serialized_array = ExternalTypedData::Handle();         \
     serialized_array ^= reader.ReadObject();                                   \
     for (int i = 0; i < length; i++) {                                         \
       EXPECT_EQ(static_cast<ctype>(data[i]),                                   \
                 serialized_array.Get##darttype(i* scale));                     \
     }                                                                          \
-    delete message;                                                            \
   }
 
 ISOLATE_UNIT_TEST_CASE(SerializeTypedArray) {
@@ -705,26 +678,24 @@
   TypedData& typed_data = TypedData::Handle(
       TypedData::New(kTypedDataUint8ArrayCid, kTypedDataLength));
   MessageWriter writer(true);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(typed_data, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message, thread);
+  MessageSnapshotReader reader(message.get(), thread);
   TypedData& serialized_typed_data = TypedData::Handle();
   serialized_typed_data ^= reader.ReadObject();
   EXPECT(serialized_typed_data.IsTypedData());
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_EQ(Dart_CObject_kTypedData, root->type);
   EXPECT_EQ(Dart_TypedData_kUint8, root->value.as_typed_data.type);
   EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
   EXPECT(root->value.as_typed_data.values == NULL);
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 VM_UNIT_TEST_CASE(FullSnapshot) {
@@ -805,7 +776,8 @@
 }
 
 // Helper function to call a top level Dart function and serialize the result.
-static Message* GetSerialized(Dart_Handle lib, const char* dart_function) {
+static std::unique_ptr<Message> GetSerialized(Dart_Handle lib,
+                                              const char* dart_function) {
   Dart_Handle result;
   {
     TransitionVMToNative transition(Thread::Current());
@@ -831,19 +803,17 @@
   String& str = String::Handle();
   str ^= Api::UnwrapHandle(dart_string);
   MessageWriter writer(false);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kString, root->type);
   EXPECT_STREQ(expected, root->value.as_string);
   CheckEncodeDecodeMessage(root);
-
-  delete message;
 }
 
 static void CheckStringInvalid(Dart_Handle dart_string) {
@@ -851,17 +821,15 @@
   String& str = String::Handle();
   str ^= Api::UnwrapHandle(dart_string);
   MessageWriter writer(false);
-  Message* message =
+  std::unique_ptr<Message> message =
       writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message);
+  ApiMessageReader api_reader(message.get());
   Dart_CObject* root = api_reader.ReadMessage();
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kUnsupported, root->type);
-
-  delete message;
 }
 
 VM_UNIT_TEST_CASE(DartGeneratedMessages) {
@@ -958,18 +926,17 @@
       Smi& smi = Smi::Handle();
       smi ^= Api::UnwrapHandle(smi_result);
       MessageWriter writer(false);
-      Message* message =
+      std::unique_ptr<Message> message =
           writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
 
       // Read object back from the snapshot into a C structure.
       ApiNativeScope scope;
-      ApiMessageReader api_reader(message);
+      ApiMessageReader api_reader(message.get());
       Dart_CObject* root = api_reader.ReadMessage();
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kInt32, root->type);
       EXPECT_EQ(42, root->value.as_int32);
       CheckEncodeDecodeMessage(root);
-      delete message;
     }
     CheckString(ascii_string_result, "Hello, world!");
     CheckString(non_ascii_string_result, "Blåbærgrød");
@@ -1028,9 +995,9 @@
     StackZone zone(thread);
     {
       // Generate a list of nulls from Dart code.
-      Message* message = GetSerialized(lib, "getList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1038,13 +1005,12 @@
         EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
       }
       CheckEncodeDecodeMessage(root);
-      delete message;
     }
     {
       // Generate a list of ints from Dart code.
-      Message* message = GetSerialized(lib, "getIntList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1053,13 +1019,12 @@
         EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
       }
       CheckEncodeDecodeMessage(root);
-      delete message;
     }
     {
       // Generate a list of strings from Dart code.
-      Message* message = GetSerialized(lib, "getStringList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1069,13 +1034,12 @@
         snprintf(buffer, sizeof(buffer), "%d", i);
         EXPECT_STREQ(buffer, root->value.as_array.values[i]->value.as_string);
       }
-      delete message;
     }
     {
       // Generate a list of objects of different types from Dart code.
-      Message* message = GetSerialized(lib, "getMixedList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1094,7 +1058,6 @@
           EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
         }
       }
-      delete message;
     }
   }
   Dart_ExitScope();
@@ -1156,9 +1119,9 @@
     StackZone zone(thread);
     {
       // Generate a list of nulls from Dart code.
-      Message* message = GetSerialized(lib, "getList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1166,13 +1129,12 @@
         EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
       }
       CheckEncodeDecodeMessage(root);
-      delete message;
     }
     {
       // Generate a list of ints from Dart code.
-      Message* message = GetSerialized(lib, "getIntList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1181,13 +1143,12 @@
         EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
       }
       CheckEncodeDecodeMessage(root);
-      delete message;
     }
     {
       // Generate a list of strings from Dart code.
-      Message* message = GetSerialized(lib, "getStringList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1197,13 +1158,12 @@
         snprintf(buffer, sizeof(buffer), "%d", i);
         EXPECT_STREQ(buffer, root->value.as_array.values[i]->value.as_string);
       }
-      delete message;
     }
     {
       // Generate a list of lists from Dart code.
-      Message* message = GetSerialized(lib, "getListList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getListList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1217,13 +1177,12 @@
           EXPECT_EQ(j, element->value.as_array.values[j]->value.as_int32);
         }
       }
-      delete message;
     }
     {
       // Generate a list of objects of different types from Dart code.
-      Message* message = GetSerialized(lib, "getMixedList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1319,7 +1278,6 @@
         EXPECT_EQ(Dart_CObject_kInt32, e->type);
         EXPECT_EQ(i + 1, e->value.as_int32);
       }
-      delete message;
     }
   }
   Dart_ExitScope();
@@ -1394,9 +1352,9 @@
     StackZone zone(thread);
     {
       // Generate a list of strings from Dart code.
-      Message* message = GetSerialized(lib, "getStringList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1406,13 +1364,12 @@
         EXPECT_EQ(Dart_CObject_kString, element->type);
         EXPECT_STREQ("Hello, world!", element->value.as_string);
       }
-      delete message;
     }
     {
       // Generate a list of medium ints from Dart code.
-      Message* message = GetSerialized(lib, "getMintList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1422,13 +1379,12 @@
         EXPECT_EQ(Dart_CObject_kInt64, element->type);
         EXPECT_EQ(DART_INT64_C(0x7FFFFFFFFFFFFFFF), element->value.as_int64);
       }
-      delete message;
     }
     {
       // Generate a list of doubles from Dart code.
-      Message* message = GetSerialized(lib, "getDoubleList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1442,13 +1398,12 @@
         EXPECT_EQ(Dart_CObject_kDouble, element->type);
         EXPECT_EQ(3.14, element->value.as_double);
       }
-      delete message;
     }
     {
       // Generate a list of Uint8Lists from Dart code.
-      Message* message = GetSerialized(lib, "getTypedDataList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1459,13 +1414,13 @@
         EXPECT_EQ(Dart_TypedData_kUint8, element->value.as_typed_data.type);
         EXPECT_EQ(256, element->value.as_typed_data.length);
       }
-      delete message;
     }
     {
       // Generate a list of Uint8List views from Dart code.
-      Message* message = GetSerialized(lib, "getTypedDataViewList");
+      std::unique_ptr<Message> message =
+          GetSerialized(lib, "getTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1478,13 +1433,12 @@
         EXPECT_EQ(1, element->value.as_typed_data.values[0]);
         EXPECT_EQ(0, element->value.as_typed_data.values[1]);
       }
-      delete message;
     }
     {
       // Generate a list of objects of different types from Dart code.
-      Message* message = GetSerialized(lib, "getMixedList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1507,13 +1461,12 @@
           EXPECT_STREQ(2.72, element->value.as_double);
         }
       }
-      delete message;
     }
     {
       // Generate a list of objects of different types from Dart code.
-      Message* message = GetSerialized(lib, "getSelfRefList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1522,7 +1475,6 @@
         EXPECT_EQ(Dart_CObject_kArray, element->type);
         EXPECT_EQ(root, element);
       }
-      delete message;
     }
   }
   Dart_ExitScope();
@@ -1603,9 +1555,9 @@
     StackZone zone(thread);
     {
       // Generate a list of strings from Dart code.
-      Message* message = GetSerialized(lib, "getStringList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1615,13 +1567,12 @@
         EXPECT_EQ(Dart_CObject_kString, element->type);
         EXPECT_STREQ("Hello, world!", element->value.as_string);
       }
-      delete message;
     }
     {
       // Generate a list of medium ints from Dart code.
-      Message* message = GetSerialized(lib, "getMintList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1631,13 +1582,12 @@
         EXPECT_EQ(Dart_CObject_kInt64, element->type);
         EXPECT_EQ(DART_INT64_C(0x7FFFFFFFFFFFFFFF), element->value.as_int64);
       }
-      delete message;
     }
     {
       // Generate a list of doubles from Dart code.
-      Message* message = GetSerialized(lib, "getDoubleList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1652,13 +1602,12 @@
         EXPECT_EQ(Dart_CObject_kDouble, element->type);
         EXPECT_EQ(3.14, element->value.as_double);
       }
-      delete message;
     }
     {
       // Generate a list of Uint8Lists from Dart code.
-      Message* message = GetSerialized(lib, "getTypedDataList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1669,13 +1618,13 @@
         EXPECT_EQ(Dart_TypedData_kUint8, element->value.as_typed_data.type);
         EXPECT_EQ(256, element->value.as_typed_data.length);
       }
-      delete message;
     }
     {
       // Generate a list of Uint8List views from Dart code.
-      Message* message = GetSerialized(lib, "getTypedDataViewList");
+      std::unique_ptr<Message> message =
+          GetSerialized(lib, "getTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1688,13 +1637,12 @@
         EXPECT_EQ(1, element->value.as_typed_data.values[0]);
         EXPECT_EQ(0, element->value.as_typed_data.values[1]);
       }
-      delete message;
     }
     {
       // Generate a list of objects of different types from Dart code.
-      Message* message = GetSerialized(lib, "getMixedList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1717,13 +1665,12 @@
           EXPECT_STREQ(2.72, element->value.as_double);
         }
       }
-      delete message;
     }
     {
       // Generate a list of objects of different types from Dart code.
-      Message* message = GetSerialized(lib, "getSelfRefList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1732,7 +1679,6 @@
         EXPECT_EQ(Dart_CObject_kArray, element->type);
         EXPECT_EQ(root, element);
       }
-      delete message;
     }
   }
   Dart_ExitScope();
@@ -1834,9 +1780,9 @@
     StackZone zone(thread);
     {
       // Generate a list of Uint8Lists from Dart code.
-      Message* message = GetSerialized(lib, "getTypedDataList");
+      std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
@@ -1857,13 +1803,13 @@
         i++;
       }
       EXPECT_EQ(i, root->value.as_array.length);
-      delete message;
     }
     {
       // Generate a list of Uint8List views from Dart code.
-      Message* message = GetSerialized(lib, "getTypedDataViewList");
+      std::unique_ptr<Message> message =
+          GetSerialized(lib, "getTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
@@ -1897,13 +1843,13 @@
         i++;
       }
       EXPECT_EQ(i, root->value.as_array.length);
-      delete message;
     }
     {
       // Generate a list of Uint8Lists from Dart code.
-      Message* message = GetSerialized(lib, "getMultipleTypedDataViewList");
+      std::unique_ptr<Message> message =
+          GetSerialized(lib, "getMultipleTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message);
+      Dart_CObject* root = GetDeserialized(message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
@@ -1928,7 +1874,6 @@
         i++;
       }
       EXPECT_EQ(i, root->value.as_array.length);
-      delete message;
     }
   }
   Dart_ExitScope();
@@ -2030,7 +1975,7 @@
   Dart_ExitScope();
 }
 
-TEST_CASE(OmittedObjectEncodingLength) {
+ISOLATE_UNIT_TEST_CASE(OmittedObjectEncodingLength) {
   StackZone zone(Thread::Current());
   MessageWriter writer(true);
   writer.WriteInlinedObjectHeader(kOmittedObjectId);
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 6cf4754..019cb7c 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -92,7 +92,7 @@
     case RawFunction::kRegularFunction:
     case RawFunction::kClosureFunction:
     case RawFunction::kImplicitClosureFunction:
-    case RawFunction::kImplicitStaticFinalGetter:
+    case RawFunction::kImplicitStaticGetter:
     case RawFunction::kStaticFieldInitializer:
     case RawFunction::kGetterFunction:
     case RawFunction::kSetterFunction:
@@ -191,6 +191,10 @@
 void SourceReport::PrintCallSitesData(JSONObject* jsobj,
                                       const Function& function,
                                       const Code& code) {
+  if (code.IsNull()) {
+    // TODO(regis): implement for bytecode.
+    return;
+  }
   const TokenPosition begin_pos = function.token_pos();
   const TokenPosition end_pos = function.end_token_pos();
 
@@ -230,6 +234,10 @@
 void SourceReport::PrintCoverageData(JSONObject* jsobj,
                                      const Function& function,
                                      const Code& code) {
+  if (code.IsNull()) {
+    // TODO(regis): implement for bytecode.
+    return;
+  }
   const TokenPosition begin_pos = function.token_pos();
   const TokenPosition end_pos = function.end_token_pos();
 
@@ -312,15 +320,8 @@
 void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj,
                                                 const Function& func,
                                                 const Code& code) {
-  const uint8_t kSafepointKind =
-      (RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall |
-       RawPcDescriptors::kRuntimeCall);
   const TokenPosition begin_pos = func.token_pos();
   const TokenPosition end_pos = func.end_token_pos();
-
-  const PcDescriptors& descriptors =
-      PcDescriptors::Handle(zone(), code.pc_descriptors());
-
   intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1;
   GrowableArray<char> possible(func_length);
   possible.SetLength(func_length);
@@ -328,15 +329,37 @@
     possible[i] = false;
   }
 
-  PcDescriptors::Iterator iter(descriptors, kSafepointKind);
-  while (iter.MoveNext()) {
-    const TokenPosition token_pos = iter.TokenPos();
-    if ((token_pos < begin_pos) || (token_pos > end_pos)) {
-      // Does not correspond to a valid source position.
-      continue;
+  if (code.IsNull()) {
+    const Bytecode& bytecode = Bytecode::Handle(func.bytecode());
+    ASSERT(!bytecode.IsNull());
+    kernel::BytecodeSourcePositionsIterator iter(zone(), bytecode);
+    while (iter.MoveNext()) {
+      const TokenPosition token_pos = iter.TokenPos();
+      if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+        // Does not correspond to a valid source position.
+        continue;
+      }
+      intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
+      possible[token_offset] = true;
     }
-    intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
-    possible[token_offset] = true;
+  } else {
+    const uint8_t kSafepointKind =
+        (RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall |
+         RawPcDescriptors::kRuntimeCall);
+
+    const PcDescriptors& descriptors =
+        PcDescriptors::Handle(zone(), code.pc_descriptors());
+
+    PcDescriptors::Iterator iter(descriptors, kSafepointKind);
+    while (iter.MoveNext()) {
+      const TokenPosition token_pos = iter.TokenPos();
+      if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+        // Does not correspond to a valid source position.
+        continue;
+      }
+      intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
+      possible[token_offset] = true;
+    }
   }
 
   JSONArray bpts(jsobj, "possibleBreakpoints");
@@ -465,14 +488,8 @@
   range.AddProperty("scriptIndex", GetScriptIndex(script));
   range.AddProperty("startPos", begin_pos);
   range.AddProperty("endPos", end_pos);
-  // TODO(regis): What is the meaning of 'compiled' in the presence of bytecode?
-  // If it means 'called', it should say 'true' if bytecode is present.
-  range.AddProperty("compiled", !code.IsNull());
+  range.AddProperty("compiled", true);  // bytecode or code.
 
-  // TODO(regis): Do we want a report covering interpreted functions too?
-  if (code.IsNull()) {
-    return;
-  }
   if (IsReportRequested(kCallSites)) {
     PrintCallSitesData(&range, func, code);
   }
diff --git a/runtime/vm/splay-tree.h b/runtime/vm/splay-tree.h
new file mode 100644
index 0000000..54c5d9f
--- /dev/null
+++ b/runtime/vm/splay-tree.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_SPLAY_TREE_H_
+#define RUNTIME_VM_SPLAY_TREE_H_
+
+#include "platform/splay-tree.h"
+#include "vm/zone.h"
+
+namespace dart {
+
+// A zone splay tree.  The config type parameter encapsulates the
+// different configurations of a concrete splay tree (see
+// platform/splay-tree.h). The tree itself and all its elements are allocated
+// in the Zone.
+template <typename Config>
+class ZoneSplayTree final : public SplayTree<Config, ZoneAllocated, Zone> {
+ public:
+  explicit ZoneSplayTree(Zone* zone)
+      : SplayTree<Config, ZoneAllocated, Zone>(ASSERT_NOTNULL(zone)) {}
+  ~ZoneSplayTree() {
+    // Reset the root to avoid unneeded iteration over all tree nodes
+    // in the destructor.  For a zone-allocated tree, nodes will be
+    // freed by the Zone.
+    SplayTree<Config, ZoneAllocated, Zone>::ResetRoot();
+  }
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_SPLAY_TREE_H_
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index b1d4b79..4d97d94 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -180,11 +180,9 @@
     if (is_interpreted()) {
       const Bytecode& bytecode = Bytecode::Handle(zone, LookupDartBytecode());
       ASSERT(!bytecode.IsNull());
-      const Function& function = Function::Handle(zone, bytecode.function());
-      ASSERT(!function.IsNull());
-      return zone->PrintToString(
-          "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") bytecode %s ]",
-          GetName(), sp(), fp(), pc(), function.ToFullyQualifiedCString());
+      return zone->PrintToString("[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px
+                                 ") %s ]",
+                                 GetName(), sp(), fp(), pc(), bytecode.Name());
     }
     const Code& code = Code::Handle(zone, LookupDartCode());
     ASSERT(!code.IsNull());
@@ -501,7 +499,6 @@
     ASSERT(!bytecode.IsNull());
     start = bytecode.PayloadStart();
     handlers = bytecode.exception_handlers();
-    descriptors = bytecode.pc_descriptors();
   } else {
     code = LookupDartCode();
     if (code.IsNull()) {
@@ -520,33 +517,17 @@
     *has_catch_all = info->has_catch_all;
     return true;
   }
-  uword pc_offset = pc() - start;
 
   if (handlers.num_entries() == 0) {
     return false;
   }
 
-  PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
   intptr_t try_index = -1;
   if (is_interpreted()) {
-    while (iter.MoveNext()) {
-      // PC descriptors for try blocks in bytecode are generated in pairs,
-      // marking start and end of a try block.
-      // See BytecodeMetadataHelper::ReadExceptionsTable for details.
-      const intptr_t current_try_index = iter.TryIndex();
-      const uword start_pc = iter.PcOffset();
-      if (pc_offset < start_pc) {
-        break;
-      }
-      const bool has_next = iter.MoveNext();
-      ASSERT(has_next);
-      const uword end_pc = iter.PcOffset();
-      if (start_pc <= pc_offset && pc_offset < end_pc) {
-        ASSERT(try_index < current_try_index);
-        try_index = current_try_index;
-      }
-    }
+    try_index = bytecode.GetTryIndexAtPc(pc());
   } else {
+    uword pc_offset = pc() - code.PayloadStart();
+    PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
     while (iter.MoveNext()) {
       const intptr_t current_try_index = iter.TryIndex();
       if ((iter.PcOffset() == pc_offset) && (current_try_index != -1)) {
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index bf67520..7753a4f 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -134,8 +134,7 @@
 
  protected:
   explicit StackFrame(Thread* thread)
-      : fp_(0), sp_(0), pc_(0), thread_(thread), is_interpreted_(false) {
-  }
+      : fp_(0), sp_(0), pc_(0), thread_(thread), is_interpreted_(false) {}
 
   // Name of the frame, used for generic frame printing functionality.
   virtual const char* GetName() const {
diff --git a/runtime/vm/stack_frame_arm.h b/runtime/vm/stack_frame_arm.h
index 2b5dc3e..cf95a67 100644
--- a/runtime/vm/stack_frame_arm.h
+++ b/runtime/vm/stack_frame_arm.h
@@ -55,6 +55,12 @@
 COMPILE_ASSERT(kAbiPreservedFpuRegCount == 4);
 #endif
 
+// For FFI native -> Dart callbacks, the number of stack slots between arguments
+// passed on stack and arguments saved in callback prologue.
+//
+// 2 = return adddress (1) + saved frame pointer (1).
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 2;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_ARM_H_
diff --git a/runtime/vm/stack_frame_arm64.h b/runtime/vm/stack_frame_arm64.h
index 3b8c726..b1b2288 100644
--- a/runtime/vm/stack_frame_arm64.h
+++ b/runtime/vm/stack_frame_arm64.h
@@ -49,6 +49,12 @@
 COMPILE_ASSERT(kAbiPreservedCpuRegCount == 10);
 COMPILE_ASSERT(kAbiPreservedFpuRegCount == 8);
 
+// For FFI native -> Dart callbacks, this is the number of stack slots between
+// arguments passed on stack and arguments saved in callback prologue.
+//
+// 2 = return adddress (1) + saved frame pointer (1).
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 2;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_ARM64_H_
diff --git a/runtime/vm/stack_frame_dbc.h b/runtime/vm/stack_frame_dbc.h
index 632f68c..e3d8395 100644
--- a/runtime/vm/stack_frame_dbc.h
+++ b/runtime/vm/stack_frame_dbc.h
@@ -81,6 +81,10 @@
 // on all other architectures.
 static const uword kInterruptStackLimit = 0;
 
+// TODO(37140): For FFI native -> Dart callbacks, the number of stack slots
+// between arguments passed on stack and arguments saved in callback prologue.
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = -1;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_DBC_H_
diff --git a/runtime/vm/stack_frame_ia32.h b/runtime/vm/stack_frame_ia32.h
index b770cf7..70717c2 100644
--- a/runtime/vm/stack_frame_ia32.h
+++ b/runtime/vm/stack_frame_ia32.h
@@ -46,6 +46,10 @@
 // Entry and exit frame layout.
 static const int kExitLinkSlotFromEntryFp = -7;
 
+// All arguments are passed on the stack, so none need to be saved. Therefore
+// there is no frame for holding the saved arguments.
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 0;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_IA32_H_
diff --git a/runtime/vm/stack_frame_test.cc b/runtime/vm/stack_frame_test.cc
index 9b89101..fa77c7d 100644
--- a/runtime/vm/stack_frame_test.cc
+++ b/runtime/vm/stack_frame_test.cc
@@ -306,7 +306,7 @@
         "     * dart frame corresponding to StackFrame.frameCount"
         "     * dart frame corresponding to StackFrame2Test.noSuchMethod"
         "     * entry frame"
-        "     * exit frame (call to runtime InvokeNoSuchMethodDispatcher)"
+        "     * exit frame (call to runtime NoSuchMethodFromCallStub)"
         "     * IC stub"
         "     * dart frame corresponding to StackFrame2Test.testMain"
         "     * entry frame"
diff --git a/runtime/vm/stack_frame_x64.h b/runtime/vm/stack_frame_x64.h
index 00d0059..193db62 100644
--- a/runtime/vm/stack_frame_x64.h
+++ b/runtime/vm/stack_frame_x64.h
@@ -5,6 +5,8 @@
 #ifndef RUNTIME_VM_STACK_FRAME_X64_H_
 #define RUNTIME_VM_STACK_FRAME_X64_H_
 
+#include "vm/constants_x64.h"
+
 namespace dart {
 
 /* X64 Dart Frame Layout
@@ -52,6 +54,13 @@
 static const int kExitLinkSlotFromEntryFp = -10;
 #endif  // defined(_WIN64)
 
+// For FFI native -> Dart callbacks, the number of stack slots between arguments
+// passed on stack and arguments saved in callback prologue. 2 = return adddress
+// (1) + saved frame pointer (1). Also add slots for the shadow space, if
+// present.
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments =
+    2 + CallingConventions::kShadowSpaceBytes / kWordSize;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_X64_H_
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index 24415e1..b21b28e 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -18,21 +18,32 @@
   StackFrame* frame = frames.NextFrame();
   ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
   Function& function = Function::Handle(zone);
+  Code& code = Code::Handle(zone);
+  Bytecode& bytecode = Bytecode::Handle(zone);
   const bool async_function_is_null = async_function.IsNull();
-  while (frame != NULL) {
-    if (frame->IsDartFrame()) {
-      if (skip_frames > 0) {
-        skip_frames--;
-      } else {
-        function = frame->LookupDartFunction();
-        frame_count++;
-        if (!async_function_is_null &&
-            (async_function.raw() == function.parent_function())) {
-          return frame_count;
-        }
-      }
+  for (; frame != NULL; frame = frames.NextFrame()) {
+    if (!frame->IsDartFrame()) {
+      continue;
     }
-    frame = frames.NextFrame();
+    if (skip_frames > 0) {
+      skip_frames--;
+      continue;
+    }
+    if (frame->is_interpreted()) {
+      bytecode = frame->LookupDartBytecode();
+      function = bytecode.function();
+      if (function.IsNull()) {
+        continue;
+      }
+    } else {
+      code = frame->LookupDartCode();
+      function = code.function();
+    }
+    frame_count++;
+    if (!async_function_is_null &&
+        (async_function.raw() == function.parent_function())) {
+      return frame_count;
+    }
   }
   // We hit the sentinel.
   ASSERT(async_function_is_null);
@@ -55,28 +66,32 @@
   Bytecode& bytecode = Bytecode::Handle(zone);
   Smi& offset = Smi::Handle(zone);
   intptr_t collected_frames_count = 0;
-  while ((frame != NULL) && (collected_frames_count < count)) {
-    if (frame->IsDartFrame()) {
-      if (skip_frames > 0) {
-        skip_frames--;
-      } else {
-        if (frame->is_interpreted()) {
-          bytecode = frame->LookupDartBytecode();
-          function = bytecode.function();
-          offset = Smi::New(frame->pc() - bytecode.PayloadStart());
-          code_array.SetAt(array_offset, bytecode);
-        } else {
-          code = frame->LookupDartCode();
-          function = code.function();
-          offset = Smi::New(frame->pc() - code.PayloadStart());
-          code_array.SetAt(array_offset, code);
-        }
-        pc_offset_array.SetAt(array_offset, offset);
-        array_offset++;
-        collected_frames_count++;
-      }
+  for (; (frame != NULL) && (collected_frames_count < count);
+       frame = frames.NextFrame()) {
+    if (!frame->IsDartFrame()) {
+      continue;
     }
-    frame = frames.NextFrame();
+    if (skip_frames > 0) {
+      skip_frames--;
+      continue;
+    }
+    if (frame->is_interpreted()) {
+      bytecode = frame->LookupDartBytecode();
+      function = bytecode.function();
+      if (function.IsNull()) {
+        continue;
+      }
+      offset = Smi::New(frame->pc() - bytecode.PayloadStart());
+      code_array.SetAt(array_offset, bytecode);
+    } else {
+      code = frame->LookupDartCode();
+      function = code.function();
+      offset = Smi::New(frame->pc() - code.PayloadStart());
+      code_array.SetAt(array_offset, code);
+    }
+    pc_offset_array.SetAt(array_offset, offset);
+    array_offset++;
+    collected_frames_count++;
   }
   return collected_frames_count;
 }
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 637d16f..70d8a43 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -112,7 +112,8 @@
   if (FLAG_enable_interpreter) {
     if (is_interpreted_frame) {
       // Recognize special marker set up by interpreter in entry frame.
-      return Interpreter::IsEntryFrameMarker(reinterpret_cast<uint32_t*>(pc));
+      return Interpreter::IsEntryFrameMarker(
+          reinterpret_cast<const KBCInstr*>(pc));
     }
     {
       uword entry = StubCode::InvokeDartCodeFromBytecode().EntryPoint();
@@ -181,9 +182,9 @@
     compiler::StubCodeCompiler::GenerateAllocationStubForClass(&assembler, cls);
 
     if (thread->IsMutatorThread()) {
-      stub ^= Code::FinalizeCodeAndNotify(name, nullptr, &assembler,
-                                          pool_attachment,
-                                          /*optimized1*/ false);
+      stub = Code::FinalizeCodeAndNotify(name, nullptr, &assembler,
+                                         pool_attachment,
+                                         /*optimized1*/ false);
       // Check if background compilation thread has not already added the stub.
       if (cls.allocation_stub() == Code::null()) {
         stub.set_owner(cls);
@@ -207,8 +208,8 @@
         // Do not Garbage collect during this stage and instead allow the
         // heap to grow.
         NoHeapGrowthControlScope no_growth_control;
-        stub ^= Code::FinalizeCode(nullptr, &assembler, pool_attachment,
-                                   /*optimized=*/false, /*stats=*/nullptr);
+        stub = Code::FinalizeCode(nullptr, &assembler, pool_attachment,
+                                  /*optimized=*/false, /*stats=*/nullptr);
         stub.set_owner(cls);
         cls.set_allocation_stub(stub);
       }
diff --git a/runtime/vm/stub_code_arm64_test.cc b/runtime/vm/stub_code_arm64_test.cc
index 4e69a5a..7471c7d 100644
--- a/runtime/vm/stub_code_arm64_test.cc
+++ b/runtime/vm/stub_code_arm64_test.cc
@@ -83,7 +83,7 @@
   __ LoadObject(R1, lhs_index);
   __ LoadObject(R2, rhs_index);
   __ LoadObject(R3, length);
-  __ CallRuntime(kCaseInsensitiveCompareUC16RuntimeEntry, 4);
+  __ CallRuntime(kCaseInsensitiveCompareUCS2RuntimeEntry, 4);
   __ LeaveDartFrame();
   __ ret();  // Return value is in R0.
 }
diff --git a/runtime/vm/stub_code_arm_test.cc b/runtime/vm/stub_code_arm_test.cc
index 2a66478..d849dc0 100644
--- a/runtime/vm/stub_code_arm_test.cc
+++ b/runtime/vm/stub_code_arm_test.cc
@@ -82,7 +82,7 @@
   __ LoadObject(R1, lhs_index);
   __ LoadObject(R2, rhs_index);
   __ LoadObject(R3, length);
-  __ CallRuntime(kCaseInsensitiveCompareUC16RuntimeEntry, 4);
+  __ CallRuntime(kCaseInsensitiveCompareUCS2RuntimeEntry, 4);
   __ LeaveDartFrameAndReturn();  // Return value is in R0.
 }
 
diff --git a/runtime/vm/stub_code_ia32_test.cc b/runtime/vm/stub_code_ia32_test.cc
index a4f79fc..578afde 100644
--- a/runtime/vm/stub_code_ia32_test.cc
+++ b/runtime/vm/stub_code_ia32_test.cc
@@ -86,7 +86,7 @@
   __ movl(Address(ESP, 2 * kWordSize), EAX);  // Push argument 3.
   __ LoadObject(EAX, length);
   __ movl(Address(ESP, 3 * kWordSize), EAX);  // Push argument 4.
-  __ CallRuntime(kCaseInsensitiveCompareUC16RuntimeEntry, 4);
+  __ CallRuntime(kCaseInsensitiveCompareUCS2RuntimeEntry, 4);
   __ leave();
   __ ret();  // Return value is in EAX.
 }
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index 602ec4d..248c455 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -50,7 +50,7 @@
   V(OneArgCheckInlineCache)                                                    \
   V(TwoArgsCheckInlineCache)                                                   \
   V(SmiAddInlineCache)                                                         \
-  V(SmiSubInlineCache)                                                         \
+  V(SmiLessInlineCache)                                                        \
   V(SmiEqualInlineCache)                                                       \
   V(OneArgOptimizedCheckInlineCache)                                           \
   V(TwoArgsOptimizedCheckInlineCache)                                          \
@@ -77,7 +77,8 @@
   V(OneArgCheckInlineCacheWithExactnessCheck)                                  \
   V(OneArgOptimizedCheckInlineCacheWithExactnessCheck)                         \
   V(EnterSafepoint)                                                            \
-  V(ExitSafepoint)
+  V(ExitSafepoint)                                                             \
+  V(VerifyCallback)
 
 #else
 #define VM_STUB_CODE_LIST(V)                                                   \
diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc
index a71484a..4cdf613 100644
--- a/runtime/vm/stub_code_x64_test.cc
+++ b/runtime/vm/stub_code_x64_test.cc
@@ -83,7 +83,7 @@
   __ LoadObject(CallingConventions::kArg2Reg, lhs_index);
   __ LoadObject(CallingConventions::kArg3Reg, rhs_index);
   __ LoadObject(CallingConventions::kArg4Reg, length);
-  __ CallRuntime(kCaseInsensitiveCompareUC16RuntimeEntry, 4);
+  __ CallRuntime(kCaseInsensitiveCompareUCS2RuntimeEntry, 4);
   __ LeaveStubFrame();
   __ ret();  // Return value is in RAX.
 }
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 3a80632..3333c03 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -4,6 +4,7 @@
 
 #include "vm/symbols.h"
 
+#include "platform/unicode.h"
 #include "vm/handles.h"
 #include "vm/hash_table.h"
 #include "vm/isolate.h"
@@ -13,7 +14,6 @@
 #include "vm/reusable_handles.h"
 #include "vm/snapshot_ids.h"
 #include "vm/type_table.h"
-#include "vm/unicode.h"
 #include "vm/visitor.h"
 
 namespace dart {
@@ -573,7 +573,7 @@
   Array& data = thread->ArrayHandle();
   {
     Isolate* vm_isolate = Dart::vm_isolate();
-    data ^= vm_isolate->object_store()->symbol_table();
+    data = vm_isolate->object_store()->symbol_table();
     SymbolTable table(&key, &value, &data);
     symbol ^= table.GetOrNull(str);
     table.Release();
@@ -581,7 +581,7 @@
   if (symbol.IsNull()) {
     Isolate* isolate = thread->isolate();
     SafepointMutexLocker ml(isolate->symbols_mutex());
-    data ^= isolate->object_store()->symbol_table();
+    data = isolate->object_store()->symbol_table();
     SymbolTable table(&key, &value, &data);
     symbol ^= table.InsertNewOrGet(str);
     isolate->object_store()->set_symbol_table(table.Release());
@@ -602,7 +602,7 @@
   Array& data = thread->ArrayHandle();
   {
     Isolate* vm_isolate = Dart::vm_isolate();
-    data ^= vm_isolate->object_store()->symbol_table();
+    data = vm_isolate->object_store()->symbol_table();
     SymbolTable table(&key, &value, &data);
     symbol ^= table.GetOrNull(str);
     table.Release();
@@ -610,7 +610,7 @@
   if (symbol.IsNull()) {
     Isolate* isolate = thread->isolate();
     SafepointMutexLocker ml(isolate->symbols_mutex());
-    data ^= isolate->object_store()->symbol_table();
+    data = isolate->object_store()->symbol_table();
     SymbolTable table(&key, &value, &data);
     symbol ^= table.GetOrNull(str);
     table.Release();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 845d780..5454049 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -179,6 +179,7 @@
   V(GetterPrefix, "get:")                                                      \
   V(GreaterEqualOperator, ">=")                                                \
   V(GrowRegExpStack, "_growRegExpStack")                                       \
+  V(HandleExposedException, "_handleExposedException")                         \
   V(HaveSameRuntimeType, "_haveSameRuntimeType")                               \
   V(Hide, "hide")                                                              \
   V(ICData, "ICData")                                                          \
@@ -286,6 +287,7 @@
   V(ThrowNewInvocation, "_throwNewInvocation")                                 \
   V(TopLevel, "::")                                                            \
   V(TruncDivOperator, "~/")                                                    \
+  V(TransferableTypedData, "TransferableTypedData")                            \
   V(TryFinallyReturnValue, ":try_finally_return_value")                        \
   V(TwoByteString, "_TwoByteString")                                           \
   V(TwoNewlines, "\n\n")                                                       \
@@ -402,6 +404,7 @@
   V(_RawReceivePortImpl, "_RawReceivePortImpl")                                \
   V(_RegExp, "_RegExp")                                                        \
   V(_SendPortImpl, "_SendPortImpl")                                            \
+  V(_TransferableTypedDataImpl, "_TransferableTypedDataImpl")                  \
   V(_Smi, "_Smi")                                                              \
   V(_SourceLocation, "_SourceLocation")                                        \
   V(_SpecialTypeMirror, "_SpecialTypeMirror")                                  \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index e4b6658..71a9b2d 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -6,6 +6,7 @@
 
 #include "vm/dart_api_state.h"
 #include "vm/growable_array.h"
+#include "vm/heap/safepoint.h"
 #include "vm/isolate.h"
 #include "vm/json_stream.h"
 #include "vm/lockers.h"
@@ -44,8 +45,6 @@
     delete api_reusable_scope_;
     api_reusable_scope_ = NULL;
   }
-  delete thread_lock_;
-  thread_lock_ = NULL;
 }
 
 #if defined(DEBUG)
@@ -78,9 +77,10 @@
       resume_pc_(0),
       execution_state_(kThreadInNative),
       safepoint_state_(0),
+      ffi_callback_code_(GrowableObjectArray::null()),
       task_kind_(kUnknownTask),
       dart_stream_(NULL),
-      thread_lock_(new Monitor()),
+      thread_lock_(),
       api_reusable_scope_(NULL),
       api_top_scope_(NULL),
       no_callback_scope_depth_(0),
@@ -406,7 +406,7 @@
 void Thread::SetStackLimit(uword limit) {
   // The thread setting the stack limit is not necessarily the thread which
   // the stack limit is being set on.
-  MonitorLocker ml(thread_lock_);
+  MonitorLocker ml(&thread_lock_);
   if (!HasScheduledInterrupts()) {
     // No interrupt pending, set stack_limit_ too.
     stack_limit_ = limit;
@@ -419,12 +419,12 @@
 }
 
 void Thread::ScheduleInterrupts(uword interrupt_bits) {
-  MonitorLocker ml(thread_lock_);
+  MonitorLocker ml(&thread_lock_);
   ScheduleInterruptsLocked(interrupt_bits);
 }
 
 void Thread::ScheduleInterruptsLocked(uword interrupt_bits) {
-  ASSERT(thread_lock_->IsOwnedByCurrentThread());
+  ASSERT(thread_lock_.IsOwnedByCurrentThread());
   ASSERT((interrupt_bits & ~kInterruptsMask) == 0);  // Must fit in mask.
 
   // Check to see if any of the requested interrupts should be deferred.
@@ -444,7 +444,7 @@
 }
 
 uword Thread::GetAndClearInterrupts() {
-  MonitorLocker ml(thread_lock_);
+  MonitorLocker ml(&thread_lock_);
   if (stack_limit_ == saved_stack_limit_) {
     return 0;  // No interrupt was requested.
   }
@@ -454,7 +454,7 @@
 }
 
 void Thread::DeferOOBMessageInterrupts() {
-  MonitorLocker ml(thread_lock_);
+  MonitorLocker ml(&thread_lock_);
   defer_oob_messages_count_++;
   if (defer_oob_messages_count_ > 1) {
     // OOB message interrupts are already deferred.
@@ -482,7 +482,7 @@
 }
 
 void Thread::RestoreOOBMessageInterrupts() {
-  MonitorLocker ml(thread_lock_);
+  MonitorLocker ml(&thread_lock_);
   defer_oob_messages_count_--;
   if (defer_oob_messages_count_ > 0) {
     return;
@@ -670,6 +670,7 @@
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&active_stacktrace_));
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&sticky_error_));
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&async_stack_trace_));
+  visitor->VisitPointer(reinterpret_cast<RawObject**>(&ffi_callback_code_));
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (interpreter() != NULL) {
@@ -938,4 +939,45 @@
   }
 }
 
+const intptr_t kInitialCallbackIdsReserved = 1024;
+int32_t Thread::AllocateFfiCallbackId() {
+  Zone* Z = isolate()->current_zone();
+  if (ffi_callback_code_ == GrowableObjectArray::null()) {
+    ffi_callback_code_ = GrowableObjectArray::New(kInitialCallbackIdsReserved);
+  }
+  const auto& array = GrowableObjectArray::Handle(Z, ffi_callback_code_);
+  array.Add(Code::Handle(Z, Code::null()));
+  return array.Length() - 1;
+}
+
+void Thread::SetFfiCallbackCode(int32_t callback_id, const Code& code) {
+  Zone* Z = isolate()->current_zone();
+  const auto& array = GrowableObjectArray::Handle(Z, ffi_callback_code_);
+  array.SetAt(callback_id, code);
+}
+
+void Thread::VerifyCallbackIsolate(int32_t callback_id, uword entry) {
+  NoSafepointScope _;
+
+  const RawGrowableObjectArray* const array = ffi_callback_code_;
+  if (array == GrowableObjectArray::null()) {
+    FATAL("Cannot invoke callback on incorrect isolate.");
+  }
+
+  const RawSmi* const length_smi =
+      GrowableObjectArray::NoSafepointLength(array);
+  const intptr_t length = Smi::Value(length_smi);
+
+  if (callback_id < 0 || callback_id >= length) {
+    FATAL("Cannot invoke callback on incorrect isolate.");
+  }
+
+  RawObject** const code_array =
+      Array::DataOf(GrowableObjectArray::NoSafepointData(array));
+  const RawCode* const code = Code::RawCast(code_array[callback_id]);
+  if (!Code::ContainsInstructionAt(code, entry)) {
+    FATAL("Cannot invoke callback on incorrect isolate.");
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index f5b7c97..44bb9e6 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -114,6 +114,7 @@
   V(RawCode*, monomorphic_miss_stub_, StubCode::MonomorphicMiss().raw(), NULL) \
   V(RawCode*, ic_lookup_through_code_stub_,                                    \
     StubCode::ICCallThroughCode().raw(), NULL)                                 \
+  V(RawCode*, optimize_stub_, StubCode::OptimizeFunction().raw(), NULL)        \
   V(RawCode*, deoptimize_stub_, StubCode::Deoptimize().raw(), NULL)            \
   V(RawCode*, lazy_deopt_from_return_stub_,                                    \
     StubCode::DeoptimizeLazyFromReturn().raw(), NULL)                          \
@@ -166,8 +167,9 @@
     StubCode::MegamorphicCall().EntryPoint(), 0)                               \
   V(uword, monomorphic_miss_entry_, StubCode::MonomorphicMiss().EntryPoint(),  \
     0)                                                                         \
-  V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0)
-
+  V(uword, optimize_entry_, StubCode::OptimizeFunction().EntryPoint(), 0)      \
+  V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0)          \
+  V(uword, verify_callback_entry_, StubCode::VerifyCallback().EntryPoint(), 0)
 #endif
 
 #define CACHED_ADDRESSES_LIST(V)                                               \
@@ -313,6 +315,10 @@
     return OFFSET_OF(Thread, safepoint_state_);
   }
 
+  static intptr_t callback_code_offset() {
+    return OFFSET_OF(Thread, ffi_callback_code_);
+  }
+
   TaskKind task_kind() const { return task_kind_; }
 
   // Retrieves and clears the stack overflow flags.  These are set by
@@ -337,7 +343,7 @@
   }
 
   // Monitor corresponding to this thread.
-  Monitor* thread_lock() const { return thread_lock_; }
+  Monitor* thread_lock() const { return &thread_lock_; }
 
   // The reusable api local scope for this thread.
   ApiLocalScope* api_reusable_scope() const { return api_reusable_scope_; }
@@ -450,12 +456,8 @@
   Heap* heap() const { return heap_; }
   static intptr_t heap_offset() { return OFFSET_OF(Thread, heap_); }
 
-  void set_top(uword value) {
-    top_ = value;
-  }
-  void set_end(uword value) {
-    end_ = value;
-  }
+  void set_top(uword value) { top_ = value; }
+  void set_end(uword value) { end_ = value; }
 
   uword top() { return top_; }
   uword end() { return end_; }
@@ -770,6 +772,13 @@
     }
   }
 
+  int32_t AllocateFfiCallbackId();
+  void SetFfiCallbackCode(int32_t callback_id, const Code& code);
+
+  // Ensure that 'entry' points within the code of the callback identified by
+  // 'callback_id'. Aborts otherwise.
+  void VerifyCallbackIsolate(int32_t callback_id, uword entry);
+
   Thread* next() const { return next_; }
 
   // Visit all object pointers.
@@ -786,6 +795,17 @@
 
   uint64_t GetRandomUInt64() { return thread_random_.NextUInt64(); }
 
+  uint64_t* GetFfiMarshalledArguments(intptr_t size) {
+    if (ffi_marshalled_arguments_size_ < size) {
+      if (ffi_marshalled_arguments_size_ > 0) {
+        free(ffi_marshalled_arguments_);
+      }
+      ffi_marshalled_arguments_ =
+          reinterpret_cast<uint64_t*>(malloc(size * sizeof(uint64_t)));
+    }
+    return ffi_marshalled_arguments_;
+  }
+
 #ifndef PRODUCT
   void PrintJSON(JSONStream* stream) const;
 #endif
@@ -852,6 +872,7 @@
   uword resume_pc_;
   uword execution_state_;
   uword safepoint_state_;
+  RawGrowableObjectArray* ffi_callback_code_;
 
   // ---- End accessed from generated code. ----
 
@@ -862,7 +883,7 @@
 
   TaskKind task_kind_;
   TimelineStream* dart_stream_;
-  Monitor* thread_lock_;
+  mutable Monitor thread_lock_;
   ApiLocalScope* api_reusable_scope_;
   ApiLocalScope* api_top_scope_;
   int32_t no_callback_scope_depth_;
@@ -887,6 +908,9 @@
 
   Random thread_random_;
 
+  intptr_t ffi_marshalled_arguments_size_ = 0;
+  uint64_t* ffi_marshalled_arguments_;
+
 // Reusable handles support.
 #define REUSABLE_HANDLE_FIELDS(object) object* object##_handle_;
   REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_FIELDS)
diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc
index 2052d4a..2dcabf8 100644
--- a/runtime/vm/thread_registry.cc
+++ b/runtime/vm/thread_registry.cc
@@ -30,9 +30,6 @@
       delete thread;
     }
   }
-
-  // Delete monitor.
-  delete threads_lock_;
 }
 
 // Gets a free Thread structure, we special case the mutator thread
diff --git a/runtime/vm/thread_registry.h b/runtime/vm/thread_registry.h
index fda9474..b6c0ec5 100644
--- a/runtime/vm/thread_registry.h
+++ b/runtime/vm/thread_registry.h
@@ -23,7 +23,7 @@
 class ThreadRegistry {
  public:
   ThreadRegistry()
-      : threads_lock_(new Monitor()),
+      : threads_lock_(),
         active_list_(NULL),
         free_list_(NULL),
         mutator_thread_(NULL) {}
@@ -50,7 +50,7 @@
 
  private:
   Thread* active_list() const { return active_list_; }
-  Monitor* threads_lock() const { return threads_lock_; }
+  Monitor* threads_lock() const { return &threads_lock_; }
 
   Thread* GetFreeThreadLocked(Isolate* isolate, bool is_mutator);
   void ReturnThreadLocked(bool is_mutator, Thread* thread);
@@ -61,7 +61,7 @@
 
   // This monitor protects the threads list for an isolate, it is used whenever
   // we need to iterate over threads (both active and free) in an isolate.
-  Monitor* threads_lock_;
+  mutable Monitor threads_lock_;
   Thread* active_list_;  // List of active threads in the isolate.
   Thread* free_list_;    // Free list of Thread objects that can be reused.
 
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 9a42800..1030795 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -376,6 +376,7 @@
   TestCase::CreateTestIsolate();
   {
     // Create a stack resource this time, and exercise it.
+    TransitionNativeToVM transition(Thread::Current());
     StackZone stack_zone(Thread::Current());
     Zone* zone1 = Thread::Current()->zone();
     EXPECT(zone1 != zone0);
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 158c1c3..329f488 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -115,7 +115,7 @@
 
 #if defined(HOST_OS_LINUX) || defined(HOST_OS_ANDROID)
       return new TimelineEventSystraceRecorder();
-#elif defined(HOST_OS_FUCHSIA)
+#elif defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
       return new TimelineEventFuchsiaRecorder();
 #else
       OS::PrintErr(
@@ -1108,7 +1108,7 @@
 
 int64_t TimelineEventRecorder::GetNextAsyncId() {
   // TODO(johnmccutchan): Gracefully handle wrap around.
-#if defined(HOST_OS_FUCHSIA)
+#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
   return trace_generate_nonce();
 #else
   uint32_t next =
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index 37e5af9..9d43824 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -14,7 +14,7 @@
 #include "vm/os.h"
 #include "vm/os_thread.h"
 
-#if defined(HOST_OS_FUCHSIA)
+#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
 #include <trace-engine/context.h>
 #include <trace-engine/instrumentation.h>
 #endif
@@ -59,11 +59,15 @@
   const char* fuchsia_name() const { return fuchsia_name_; }
 
   bool enabled() {
-#if defined(HOST_OS_FUCHSIA)
+#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
+#ifdef PRODUCT
     return trace_is_category_enabled(fuchsia_name_);
 #else
+    return trace_is_category_enabled(fuchsia_name_) || enabled_ != 0;
+#endif  // PRODUCT
+#else
     return enabled_ != 0;
-#endif
+#endif  // defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
   }
 
   void set_enabled(bool enabled) { enabled_ = enabled ? 1 : 0; }
@@ -78,7 +82,7 @@
     return OFFSET_OF(TimelineStream, enabled_);
   }
 
-#if defined(HOST_OS_FUCHSIA)
+#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
   trace_site_t* trace_site() { return &trace_site_; }
 #endif
 
@@ -90,7 +94,7 @@
   // 0 or 1. If this becomes a BitField, the generated code must be updated.
   uintptr_t enabled_;
 
-#if defined(HOST_OS_FUCHSIA)
+#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
   trace_site_t trace_site_ = {};
 #endif
 };
@@ -907,7 +911,7 @@
   void CompleteEvent(TimelineEvent* event);
 };
 
-#if defined(HOST_OS_FUCHSIA)
+#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
 // A recorder that sends events to Fuchsia's tracing app. See:
 // https://fuchsia.googlesource.com/garnet/+/master/docs/tracing_usage_guide.md
 class TimelineEventFuchsiaRecorder : public TimelineEventPlatformRecorder {
diff --git a/runtime/vm/timeline_fuchsia.cc b/runtime/vm/timeline_fuchsia.cc
index 0110166..fde26e5 100644
--- a/runtime/vm/timeline_fuchsia.cc
+++ b/runtime/vm/timeline_fuchsia.cc
@@ -3,7 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/globals.h"
-#if defined(HOST_OS_FUCHSIA) && defined(SUPPORT_TIMELINE)
+#if defined(HOST_OS_FUCHSIA) && defined(SUPPORT_TIMELINE) &&                   \
+    !defined(FUCHSIA_SDK)
 
 #include <trace-engine/context.h>
 #include <trace-engine/instrumentation.h>
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index f55e2d9..90dc754 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -322,9 +322,10 @@
   // fall through to continue
 
   // b) Then we'll load the values for the type parameters.
-  __ LoadField(
-      instance_type_args_reg,
-      FieldAddress(instance_reg, type_class.type_arguments_field_offset()));
+  __ LoadField(instance_type_args_reg,
+               FieldAddress(instance_reg,
+                            compiler::target::Class::TypeArgumentsFieldOffset(
+                                type_class)));
 
   // The kernel frontend should fill in any non-assigned type parameters on
   // construction with dynamic/Object, so we should never get the null type
@@ -391,24 +392,27 @@
     // TODO(kustermann): Even though it should be safe to use TMP here, we
     // should avoid using TMP outside the assembler.  Try to find a free
     // register to use here!
+    __ LoadField(TMP,
+                 FieldAddress(instance_type_args_reg,
+                              compiler::target::TypeArguments::type_at_offset(
+                                  type_param_value_offset_i)));
     __ LoadField(
-        TMP,
-        FieldAddress(instance_type_args_reg,
-                     TypeArguments::type_at_offset(type_param_value_offset_i)));
-    __ LoadField(class_id_reg, FieldAddress(TMP, Type::type_class_id_offset()));
+        class_id_reg,
+        FieldAddress(TMP, compiler::target::Type::type_class_id_offset()));
 
     if (type_arg.IsTypeParameter()) {
       const TypeParameter& type_param = TypeParameter::Cast(type_arg);
       const Register kTypeArgumentsReg = type_param.IsClassTypeParameter()
                                              ? instantiator_type_args_reg
                                              : function_type_args_reg;
-      __ LoadField(
-          own_type_arg_reg,
-          FieldAddress(kTypeArgumentsReg,
-                       TypeArguments::type_at_offset(type_param.index())));
+      __ LoadField(own_type_arg_reg,
+                   FieldAddress(kTypeArgumentsReg,
+                                compiler::target::TypeArguments::type_at_offset(
+                                    type_param.index())));
       __ CompareWithFieldValue(
           class_id_reg,
-          FieldAddress(own_type_arg_reg, Type::type_class_id_offset()));
+          FieldAddress(own_type_arg_reg,
+                       compiler::target::Type::type_class_id_offset()));
       __ BranchIf(NOT_EQUAL, check_failed);
     } else {
       const Class& type_class = Class::Handle(type_arg.type_class());
@@ -483,7 +487,7 @@
       const Class& instance_klass =
           Class::Handle(Isolate::Current()->class_table()->At(cid));
       if (load_field->slot().IsTypeArguments() && instance_klass.IsGeneric() &&
-          instance_klass.type_arguments_field_offset() ==
+          compiler::target::Class::TypeArgumentsFieldOffset(instance_klass) ==
               load_field->slot().offset_in_bytes()) {
         // This is a subset of Case c) above, namely forwarding the type
         // argument vector.
@@ -814,7 +818,7 @@
           // We only add instantiated types to the set (and dynamic/Object were
           // already handled above).
           if (!(*ta)->IsNull()) {
-            type ^= (*ta)->TypeAt(i);
+            type = (*ta)->TypeAt(i);
             if (type.IsInstantiated()) {
               UseTypeInAssertAssignable(type);
             }
diff --git a/runtime/vm/type_testing_stubs_arm.cc b/runtime/vm/type_testing_stubs_arm.cc
index 30f1de07..28d8c7c 100644
--- a/runtime/vm/type_testing_stubs_arm.cc
+++ b/runtime/vm/type_testing_stubs_arm.cc
@@ -23,8 +23,10 @@
   BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class,
                                       kInstanceReg, kClassIdReg);
 
-  __ ldr(CODE_REG, Address(THR, Thread::slow_type_test_stub_offset()));
-  __ Branch(FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, compiler::target::Thread::slow_type_test_stub_offset()));
+  __ Branch(
+      FieldAddress(CODE_REG, compiler::target::Code::entry_point_offset()));
 }
 
 void TypeTestingStubGenerator::
diff --git a/runtime/vm/unicode.cc b/runtime/vm/unicode.cc
index 90379d1..0ecb72c 100644
--- a/runtime/vm/unicode.cc
+++ b/runtime/vm/unicode.cc
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#include "vm/unicode.h"
+#include "platform/unicode.h"
 
 #include "vm/allocation.h"
 #include "vm/globals.h"
@@ -10,103 +10,6 @@
 
 namespace dart {
 
-// clang-format off
-const int8_t Utf8::kTrailBytes[256] = {
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-  4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0
-};
-// clang-format on
-
-const uint32_t Utf8::kMagicBits[7] = {0,  // Padding.
-                                      0x00000000, 0x00003080, 0x000E2080,
-                                      0x03C82080, 0xFA082080, 0x82082080};
-
-// Minimum values of code points used to check shortest form.
-const uint32_t Utf8::kOverlongMinimum[7] = {0,  // Padding.
-                                            0x0,     0x80,       0x800,
-                                            0x10000, 0xFFFFFFFF, 0xFFFFFFFF};
-
-// Returns the most restricted coding form in which the sequence of utf8
-// characters in 'utf8_array' can be represented in, and the number of
-// code units needed in that form.
-intptr_t Utf8::CodeUnitCount(const uint8_t* utf8_array,
-                             intptr_t array_len,
-                             Type* type) {
-  intptr_t len = 0;
-  Type char_type = kLatin1;
-  for (intptr_t i = 0; i < array_len; i++) {
-    uint8_t code_unit = utf8_array[i];
-    if (!IsTrailByte(code_unit)) {
-      ++len;
-      if (!IsLatin1SequenceStart(code_unit)) {          // > U+00FF
-        if (IsSupplementarySequenceStart(code_unit)) {  // >= U+10000
-          char_type = kSupplementary;
-          ++len;
-        } else if (char_type == kLatin1) {
-          char_type = kBMP;
-        }
-      }
-    }
-  }
-  *type = char_type;
-  return len;
-}
-
-// Returns true if str is a valid NUL-terminated UTF-8 string.
-bool Utf8::IsValid(const uint8_t* utf8_array, intptr_t array_len) {
-  intptr_t i = 0;
-  while (i < array_len) {
-    uint32_t ch = utf8_array[i] & 0xFF;
-    intptr_t j = 1;
-    if (ch >= 0x80) {
-      int8_t num_trail_bytes = kTrailBytes[ch];
-      bool is_malformed = false;
-      for (; j < num_trail_bytes; ++j) {
-        if ((i + j) < array_len) {
-          uint8_t code_unit = utf8_array[i + j];
-          is_malformed |= !IsTrailByte(code_unit);
-          ch = (ch << 6) + code_unit;
-        } else {
-          return false;
-        }
-      }
-      ch -= kMagicBits[num_trail_bytes];
-      if (!((is_malformed == false) && (j == num_trail_bytes) &&
-            !Utf::IsOutOfRange(ch) && !IsNonShortestForm(ch, j))) {
-        return false;
-      }
-    }
-    i += j;
-  }
-  return true;
-}
-
-intptr_t Utf8::Length(int32_t ch) {
-  if (ch <= kMaxOneByteChar) {
-    return 1;
-  } else if (ch <= kMaxTwoByteChar) {
-    return 2;
-  } else if (ch <= kMaxThreeByteChar) {
-    return 3;
-  }
-  ASSERT(ch <= kMaxFourByteChar);
-  return 4;
-}
-
 // A constant mask that can be 'and'ed with a word of data to determine if it
 // is all ASCII (with no Latin1 characters).
 #if defined(ARCH_IS_64_BIT)
@@ -164,31 +67,6 @@
   return length;
 }
 
-intptr_t Utf8::Encode(int32_t ch, char* dst) {
-  static const int kMask = ~(1 << 6);
-  if (ch <= kMaxOneByteChar) {
-    dst[0] = ch;
-    return 1;
-  }
-  if (ch <= kMaxTwoByteChar) {
-    dst[0] = 0xC0 | (ch >> 6);
-    dst[1] = 0x80 | (ch & kMask);
-    return 2;
-  }
-  if (ch <= kMaxThreeByteChar) {
-    dst[0] = 0xE0 | (ch >> 12);
-    dst[1] = 0x80 | ((ch >> 6) & kMask);
-    dst[2] = 0x80 | (ch & kMask);
-    return 3;
-  }
-  ASSERT(ch <= kMaxFourByteChar);
-  dst[0] = 0xF0 | (ch >> 18);
-  dst[1] = 0x80 | ((ch >> 12) & kMask);
-  dst[2] = 0x80 | ((ch >> 6) & kMask);
-  dst[3] = 0x80 | (ch & kMask);
-  return 4;
-}
-
 intptr_t Utf8::Encode(const String& src, char* dst, intptr_t len) {
   uintptr_t array_len = len;
   intptr_t pos = 0;
@@ -252,144 +130,4 @@
   return pos;
 }
 
-intptr_t Utf8::Decode(const uint8_t* utf8_array,
-                      intptr_t array_len,
-                      int32_t* dst) {
-  uint32_t ch = utf8_array[0] & 0xFF;
-  intptr_t i = 1;
-  if (ch >= 0x80) {
-    intptr_t num_trail_bytes = kTrailBytes[ch];
-    bool is_malformed = false;
-    for (; i < num_trail_bytes; ++i) {
-      if (i < array_len) {
-        uint8_t code_unit = utf8_array[i];
-        is_malformed |= !IsTrailByte(code_unit);
-        ch = (ch << 6) + code_unit;
-      } else {
-        *dst = -1;
-        return 0;
-      }
-    }
-    ch -= kMagicBits[num_trail_bytes];
-    if (!((is_malformed == false) && (i == num_trail_bytes) &&
-          !Utf::IsOutOfRange(ch) && !IsNonShortestForm(ch, i))) {
-      *dst = -1;
-      return 0;
-    }
-  }
-  *dst = ch;
-  return i;
-}
-intptr_t Utf8::ReportInvalidByte(const uint8_t* utf8_array,
-                                 intptr_t array_len,
-                                 intptr_t len) {
-  intptr_t i = 0;
-  intptr_t j = 0;
-  intptr_t num_bytes;
-  for (; (i < array_len) && (j < len); i += num_bytes, ++j) {
-    int32_t ch;
-    bool is_supplementary = IsSupplementarySequenceStart(utf8_array[i]);
-    num_bytes = Utf8::Decode(&utf8_array[i], (array_len - i), &ch);
-    if (ch == -1) {
-      break;  // Invalid input.
-    }
-    if (is_supplementary) {
-      j = j + 1;
-    }
-  }
-  OS::PrintErr("Invalid UTF8 sequence encountered, ");
-  for (intptr_t idx = 0; idx < 10 && (i + idx) < array_len; idx++) {
-    OS::PrintErr("(Error Code: %X + idx: %" Pd " )", utf8_array[idx + i],
-                 (idx + i));
-  }
-  OS::PrintErr("\n");
-  return i;
-}
-
-bool Utf8::DecodeToLatin1(const uint8_t* utf8_array,
-                          intptr_t array_len,
-                          uint8_t* dst,
-                          intptr_t len) {
-  intptr_t i = 0;
-  intptr_t j = 0;
-  intptr_t num_bytes;
-  for (; (i < array_len) && (j < len); i += num_bytes, ++j) {
-    int32_t ch;
-    ASSERT(IsLatin1SequenceStart(utf8_array[i]));
-    num_bytes = Utf8::Decode(&utf8_array[i], (array_len - i), &ch);
-    if (ch == -1) {
-      return false;  // Invalid input.
-    }
-    ASSERT(Utf::IsLatin1(ch));
-    dst[j] = ch;
-  }
-  if ((i < array_len) && (j == len)) {
-    return false;  // Output overflow.
-  }
-  return true;  // Success.
-}
-
-bool Utf8::DecodeToUTF16(const uint8_t* utf8_array,
-                         intptr_t array_len,
-                         uint16_t* dst,
-                         intptr_t len) {
-  intptr_t i = 0;
-  intptr_t j = 0;
-  intptr_t num_bytes;
-  for (; (i < array_len) && (j < len); i += num_bytes, ++j) {
-    int32_t ch;
-    bool is_supplementary = IsSupplementarySequenceStart(utf8_array[i]);
-    num_bytes = Utf8::Decode(&utf8_array[i], (array_len - i), &ch);
-    if (ch == -1) {
-      return false;  // Invalid input.
-    }
-    if (is_supplementary) {
-      if (j == (len - 1)) return false;  // Output overflow.
-      Utf16::Encode(ch, &dst[j]);
-      j = j + 1;
-    } else {
-      dst[j] = ch;
-    }
-  }
-  if ((i < array_len) && (j == len)) {
-    return false;  // Output overflow.
-  }
-  return true;  // Success.
-}
-
-bool Utf8::DecodeToUTF32(const uint8_t* utf8_array,
-                         intptr_t array_len,
-                         int32_t* dst,
-                         intptr_t len) {
-  intptr_t i = 0;
-  intptr_t j = 0;
-  intptr_t num_bytes;
-  for (; (i < array_len) && (j < len); i += num_bytes, ++j) {
-    int32_t ch;
-    num_bytes = Utf8::Decode(&utf8_array[i], (array_len - i), &ch);
-    if (ch == -1) {
-      return false;  // Invalid input.
-    }
-    dst[j] = ch;
-  }
-  if ((i < array_len) && (j == len)) {
-    return false;  // Output overflow.
-  }
-  return true;  // Success.
-}
-
-bool Utf8::DecodeCStringToUTF32(const char* str, int32_t* dst, intptr_t len) {
-  ASSERT(str != NULL);
-  intptr_t array_len = strlen(str);
-  const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(str);
-  return Utf8::DecodeToUTF32(utf8_array, array_len, dst, len);
-}
-
-void Utf16::Encode(int32_t codepoint, uint16_t* dst) {
-  ASSERT(codepoint > Utf16::kMaxCodeUnit);
-  ASSERT(dst != NULL);
-  dst[0] = (Utf16::kLeadSurrogateOffset + (codepoint >> 10));
-  dst[1] = (0xDC00 + (codepoint & 0x3FF));
-}
-
 }  // namespace dart
diff --git a/runtime/vm/unicode.h b/runtime/vm/unicode.h
deleted file mode 100644
index d2050be..0000000
--- a/runtime/vm/unicode.h
+++ /dev/null
@@ -1,227 +0,0 @@
-// 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.
-
-#ifndef RUNTIME_VM_UNICODE_H_
-#define RUNTIME_VM_UNICODE_H_
-
-#include "vm/allocation.h"
-#include "vm/globals.h"
-
-namespace dart {
-
-class String;
-
-class Utf : AllStatic {
- public:
-  static const int32_t kMaxCodePoint = 0x10FFFF;
-
-  static bool IsLatin1(int32_t code_point) {
-    return (code_point >= 0) && (code_point <= 0xFF);
-  }
-
-  static bool IsBmp(int32_t code_point) {
-    return (code_point >= 0) && (code_point <= 0xFFFF);
-  }
-
-  static bool IsSupplementary(int32_t code_point) {
-    return (code_point > 0xFFFF) && (code_point <= kMaxCodePoint);
-  }
-
-  // Returns true if the code point value is above Plane 17.
-  static bool IsOutOfRange(intptr_t code_point) {
-    return (code_point < 0) || (code_point > kMaxCodePoint);
-  }
-};
-
-class Utf8 : AllStatic {
- public:
-  enum Type {
-    kLatin1 = 0,     // Latin-1 code point [U+0000, U+00FF].
-    kBMP,            // Basic Multilingual Plane code point [U+0000, U+FFFF].
-    kSupplementary,  // Supplementary code point [U+010000, U+10FFFF].
-  };
-
-  // Returns the most restricted coding form in which the sequence of utf8
-  // characters in 'utf8_array' can be represented in, and the number of
-  // code units needed in that form.
-  static intptr_t CodeUnitCount(const uint8_t* utf8_array,
-                                intptr_t array_len,
-                                Type* type);
-
-  // Returns true if 'utf8_array' is a valid UTF-8 string.
-  static bool IsValid(const uint8_t* utf8_array, intptr_t array_len);
-
-  static intptr_t Length(int32_t ch);
-  static intptr_t Length(const String& str);
-
-  static intptr_t Encode(int32_t ch, char* dst);
-  static intptr_t Encode(const String& src, char* dst, intptr_t len);
-
-  static intptr_t Decode(const uint8_t* utf8_array,
-                         intptr_t array_len,
-                         int32_t* ch);
-
-  static bool DecodeToLatin1(const uint8_t* utf8_array,
-                             intptr_t array_len,
-                             uint8_t* dst,
-                             intptr_t len);
-  static bool DecodeToUTF16(const uint8_t* utf8_array,
-                            intptr_t array_len,
-                            uint16_t* dst,
-                            intptr_t len);
-  static bool DecodeToUTF32(const uint8_t* utf8_array,
-                            intptr_t array_len,
-                            int32_t* dst,
-                            intptr_t len);
-  static intptr_t ReportInvalidByte(const uint8_t* utf8_array,
-                                    intptr_t array_len,
-                                    intptr_t len);
-  static bool DecodeCStringToUTF32(const char* str, int32_t* dst, intptr_t len);
-
-  static const int32_t kMaxOneByteChar = 0x7F;
-  static const int32_t kMaxTwoByteChar = 0x7FF;
-  static const int32_t kMaxThreeByteChar = 0xFFFF;
-  static const int32_t kMaxFourByteChar = Utf::kMaxCodePoint;
-
- private:
-  static bool IsTrailByte(uint8_t code_unit) {
-    return (code_unit & 0xC0) == 0x80;
-  }
-
-  static bool IsNonShortestForm(uint32_t code_point, size_t num_code_units) {
-    return code_point < kOverlongMinimum[num_code_units];
-  }
-
-  static bool IsLatin1SequenceStart(uint8_t code_unit) {
-    // Check if utf8 sequence is the start of a codepoint <= U+00FF
-    return (code_unit <= 0xC3);
-  }
-
-  static bool IsSupplementarySequenceStart(uint8_t code_unit) {
-    // Check if utf8 sequence is the start of a codepoint >= U+10000.
-    return (code_unit >= 0xF0);
-  }
-
-  static const int8_t kTrailBytes[];
-  static const uint32_t kMagicBits[];
-  static const uint32_t kOverlongMinimum[];
-};
-
-class Utf16 : AllStatic {
- public:
-  // Returns the length of the code point in UTF-16 code units.
-  static intptr_t Length(int32_t ch) {
-    return (ch <= Utf16::kMaxCodeUnit) ? 1 : 2;
-  }
-
-  // Returns true if ch is a lead or trail surrogate.
-  static bool IsSurrogate(uint32_t ch) { return (ch & 0xFFFFF800) == 0xD800; }
-
-  // Returns true if ch is a lead surrogate.
-  static bool IsLeadSurrogate(uint32_t ch) {
-    return (ch & 0xFFFFFC00) == 0xD800;
-  }
-
-  // Returns true if ch is a low surrogate.
-  static bool IsTrailSurrogate(uint32_t ch) {
-    return (ch & 0xFFFFFC00) == 0xDC00;
-  }
-
-  // Returns the character at i and advances i to the next character
-  // boundary.
-  static int32_t Next(const uint16_t* characters, intptr_t* i, intptr_t len) {
-    int32_t ch = characters[*i];
-    if (Utf16::IsLeadSurrogate(ch) && (*i < (len - 1))) {
-      int32_t ch2 = characters[*i + 1];
-      if (Utf16::IsTrailSurrogate(ch2)) {
-        ch = Utf16::Decode(ch, ch2);
-        *i += 1;
-      }
-    }
-    *i += 1;
-    return ch;
-  }
-
-  // Decodes a surrogate pair into a supplementary code point.
-  static int32_t Decode(uint16_t lead, uint16_t trail) {
-    return 0x10000 + ((lead & 0x000003FF) << 10) + (trail & 0x3FF);
-  }
-
-  // Encodes a single code point.
-  static void Encode(int32_t codepoint, uint16_t* dst);
-
-  static const int32_t kMaxCodeUnit = 0xFFFF;
-
- private:
-  static const int32_t kLeadSurrogateOffset = (0xD800 - (0x10000 >> 10));
-
-  static const int32_t kSurrogateOffset = (0x10000 - (0xD800 << 10) - 0xDC00);
-};
-
-class CaseMapping : AllStatic {
- public:
-  // Maps a code point to uppercase.
-  static int32_t ToUpper(int32_t code_point) {
-    return Convert(code_point, kUppercase);
-  }
-
-  // Maps a code point to lowercase.
-  static int32_t ToLower(int32_t code_point) {
-    return Convert(code_point, kLowercase);
-  }
-
- private:
-  // Property is a delta to the uppercase mapping.
-  static const int32_t kUppercase = 1;
-
-  // Property is a delta to the uppercase mapping.
-  static const int32_t kLowercase = 2;
-
-  // Property is an index into the exception table.
-  static const int32_t kException = 3;
-
-  // Type bit-field parameters
-  static const int32_t kTypeShift = 2;
-  static const int32_t kTypeMask = 3;
-
-  // The size of the stage 1 index.
-  // TODO(cshapiro): improve indexing so this value is unnecessary.
-  static const int kStage1Size = 261;
-
-  // The size of a stage 2 block in bytes.
-  static const int kBlockSizeLog2 = 8;
-  static const int kBlockSize = 1 << kBlockSizeLog2;
-
-  static int32_t Convert(int32_t ch, int32_t mapping) {
-    if (Utf::IsLatin1(ch)) {
-      int32_t info = stage2_[ch];
-      if ((info & kTypeMask) == mapping) {
-        ch += info >> kTypeShift;
-      }
-    } else if (ch <= (kStage1Size << kBlockSizeLog2)) {
-      int16_t offset = stage1_[ch >> kBlockSizeLog2] << kBlockSizeLog2;
-      int32_t info = stage2_[offset + (ch & (kBlockSize - 1))];
-      int32_t type = info & kTypeMask;
-      if (type == mapping) {
-        ch += (info >> kTypeShift);
-      } else if (type == kException) {
-        ch += stage2_exception_[info >> kTypeShift][mapping - 1];
-      }
-    }
-    return ch;
-  }
-
-  // Index into the data array.
-  static const uint8_t stage1_[];
-
-  // Data for small code points with one mapping
-  static const int16_t stage2_[];
-
-  // Data for large code points or code points with both mappings.
-  static const int32_t stage2_exception_[][2];
-};
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_UNICODE_H_
diff --git a/runtime/vm/unicode_data.cc b/runtime/vm/unicode_data.cc
index d8fed1e..08ab595 100644
--- a/runtime/vm/unicode_data.cc
+++ b/runtime/vm/unicode_data.cc
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#include "vm/unicode.h"
+#include "platform/unicode.h"
 
 namespace dart {
 
diff --git a/runtime/vm/unicode_test.cc b/runtime/vm/unicode_test.cc
index bfd4f0a..700ce53 100644
--- a/runtime/vm/unicode_test.cc
+++ b/runtime/vm/unicode_test.cc
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#include "vm/unicode.h"
+#include "platform/unicode.h"
 #include "vm/globals.h"
 #include "vm/unit_test.h"
 
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 23b42ee..880a945 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -52,8 +52,11 @@
 TestCaseBase* TestCaseBase::tail_ = NULL;
 KernelBufferList* TestCaseBase::current_kernel_buffers_ = NULL;
 
-TestCaseBase::TestCaseBase(const char* name)
-    : raw_test_(false), next_(NULL), name_(name) {
+TestCaseBase::TestCaseBase(const char* name, const char* expectation)
+    : raw_test_(false),
+      next_(NULL),
+      name_(name),
+      expectation_(strlen(expectation) > 0 ? expectation : "Pass") {
   if (first_ == NULL) {
     first_ = this;
   } else {
@@ -682,7 +685,6 @@
     val = lib.EvaluateCompiledExpression(kernel_bytes, kernel_length,
                                          Array::empty_array(), param_values,
                                          TypeArguments::null_type_arguments());
-
     free(const_cast<uint8_t*>(kernel_bytes));
   }
   return Api::NewHandle(thread, val.raw());
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index c4855d2..bbdfea4 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -23,27 +23,33 @@
 
 // The VM_UNIT_TEST_CASE macro is used for tests that do not need any
 // default isolate or zone functionality.
-#define VM_UNIT_TEST_CASE(name)                                                \
+#define VM_UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation)                  \
   void Dart_Test##name();                                                      \
-  static const dart::TestCase kRegister##name(Dart_Test##name, #name);         \
+  static const dart::TestCase kRegister##name(Dart_Test##name, #name,          \
+                                              expectation);                    \
   void Dart_Test##name()
 
+#define VM_UNIT_TEST_CASE(name) VM_UNIT_TEST_CASE_WITH_EXPECTATION(name, "Pass")
+
 // The UNIT_TEST_CASE macro is used for tests that do not require any
 // functionality provided by the VM. Tests declared using this macro will be run
 // after the VM is cleaned up.
-#define UNIT_TEST_CASE(name)                                                   \
+#define UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation)                     \
   void Dart_Test##name();                                                      \
-  static const dart::RawTestCase kRegister##name(Dart_Test##name, #name);      \
+  static const dart::RawTestCase kRegister##name(Dart_Test##name, #name,       \
+                                                 expectation);                 \
   void Dart_Test##name()
 
+#define UNIT_TEST_CASE(name) UNIT_TEST_CASE_WITH_EXPECTATION(name, "Pass")
+
 // The ISOLATE_UNIT_TEST_CASE macro is used for tests that need an isolate and
 // zone in order to test its functionality. This macro is used for tests that
 // are implemented using the VM code directly and do not use the Dart API
 // for calling into the VM. The safepoint execution state of threads using
 // this macro is transitioned from kThreadInNative to kThreadInVM.
-#define ISOLATE_UNIT_TEST_CASE(name)                                           \
+#define ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation)             \
   static void Dart_TestHelper##name(Thread* thread);                           \
-  VM_UNIT_TEST_CASE(name) {                                                    \
+  VM_UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation) {                      \
     TestIsolateScope __test_isolate__;                                         \
     Thread* __thread__ = Thread::Current();                                    \
     ASSERT(__thread__->isolate() == __test_isolate__.isolate());               \
@@ -54,13 +60,16 @@
   }                                                                            \
   static void Dart_TestHelper##name(Thread* thread)
 
+#define ISOLATE_UNIT_TEST_CASE(name)                                           \
+  ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(name, "Pass")
+
 // The TEST_CASE macro is used for tests that need an isolate and zone
 // in order to test its functionality. This macro is used for tests that
 // are implemented using the Dart API for calling into the VM. The safepoint
 // execution state of threads using this macro remains kThreadNative.
-#define TEST_CASE(name)                                                        \
+#define TEST_CASE_WITH_EXPECTATION(name, expectation)                          \
   static void Dart_TestHelper##name(Thread* thread);                           \
-  VM_UNIT_TEST_CASE(name) {                                                    \
+  VM_UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation) {                      \
     TestIsolateScope __test_isolate__;                                         \
     Thread* __thread__ = Thread::Current();                                    \
     ASSERT(__thread__->isolate() == __test_isolate__.isolate());               \
@@ -72,6 +81,8 @@
   }                                                                            \
   static void Dart_TestHelper##name(Thread* thread)
 
+#define TEST_CASE(name) TEST_CASE_WITH_EXPECTATION(name, "Pass")
+
 // The ASSEMBLER_TEST_GENERATE macro is used to generate a unit test
 // for the assembler.
 #define ASSEMBLER_TEST_GENERATE(name, assembler)                               \
@@ -85,9 +96,9 @@
 // The ASSEMBLER_TEST_RUN macro is used to execute the assembler unit
 // test generated using the ASSEMBLER_TEST_GENERATE macro.
 // C++ callee-saved registers are not preserved. Arguments may be passed in.
-#define ASSEMBLER_TEST_RUN(name, test)                                         \
+#define ASSEMBLER_TEST_RUN_WITH_EXPECTATION(name, test, expectation)           \
   static void AssemblerTestRun##name(AssemblerTest* test);                     \
-  ISOLATE_UNIT_TEST_CASE(name) {                                               \
+  ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation) {                 \
     {                                                                          \
       bool use_far_branches = false;                                           \
       LongJumpScope jump;                                                      \
@@ -117,6 +128,9 @@
   }                                                                            \
   static void AssemblerTestRun##name(AssemblerTest* test)
 
+#define ASSEMBLER_TEST_RUN(name, test)                                         \
+  ASSEMBLER_TEST_RUN_WITH_EXPECTATION(name, test, "Pass")
+
 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
 #if defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
 // Running on actual ARM hardware, execute code natively.
@@ -249,10 +263,11 @@
 
 class TestCaseBase {
  public:
-  explicit TestCaseBase(const char* name);
+  explicit TestCaseBase(const char* name, const char* expectation);
   virtual ~TestCaseBase() {}
 
   const char* name() const { return name_; }
+  const char* expectation() const { return expectation_; }
 
   virtual void Run() = 0;
   void RunTest();
@@ -272,6 +287,7 @@
 
   TestCaseBase* next_;
   const char* name_;
+  const char* expectation_;
 
   DISALLOW_COPY_AND_ASSIGN(TestCaseBase);
 };
@@ -284,7 +300,8 @@
  public:
   typedef void(RunEntry)();
 
-  TestCase(RunEntry* run, const char* name) : TestCaseBase(name), run_(run) {}
+  TestCase(RunEntry* run, const char* name, const char* expectation)
+      : TestCaseBase(name, expectation), run_(run) {}
 
   static char* CompileTestScriptWithDFE(const char* url,
                                         const char* source,
@@ -391,7 +408,8 @@
  public:
   typedef void(RunEntry)();
 
-  RawTestCase(RunEntry* run, const char* name) : TestCaseBase(name), run_(run) {
+  RawTestCase(RunEntry* run, const char* name, const char* expectation)
+      : TestCaseBase(name, expectation), run_(run) {
     raw_test_ = true;
   }
   virtual void Run();
diff --git a/runtime/vm/v8_snapshot_writer.cc b/runtime/vm/v8_snapshot_writer.cc
index 2ddd3e0..b8ef328 100644
--- a/runtime/vm/v8_snapshot_writer.cc
+++ b/runtime/vm/v8_snapshot_writer.cc
@@ -23,7 +23,7 @@
       node_types_(zone_),
       edge_types_(zone_),
       strings_(zone),
-      roots_(zone_, 100) {
+      roots_(zone_) {
   node_types_.Insert({"Unknown", kUnknown});
   node_types_.Insert({"ArtificialRoot", kArtificialRoot});
 
@@ -128,7 +128,7 @@
   // The artificial root has 'nullptr' edges, it actually points to all the
   // roots.
   writer->PrintValue64(info.edges != nullptr ? info.edges->length()
-                                             : roots_.length());
+                                             : roots_.Size());
   writer->PrintNewline();
 }
 
@@ -142,7 +142,15 @@
 
 void V8SnapshotProfileWriter::AddRoot(ObjectId object_id) {
   EnsureId(object_id);
-  roots_.Add(object_id);
+  // HeapSnapshotWorker.HeapSnapshot.calculateDistances (from HeapSnapshot.js)
+  // assumes that the root does not have more than one edge to any other node
+  // (most likely an oversight).
+  if (roots_.HasKey(object_id)) return;
+
+  ObjectIdToNodeInfoTraits::Pair pair;
+  pair.key = object_id;
+  pair.value = NodeInfo{0, 0, object_id, 0, nullptr, 0};
+  roots_.Insert(pair);
 }
 
 void V8SnapshotProfileWriter::WriteStringsTable(
@@ -210,7 +218,7 @@
 
     writer->PrintProperty64("node_count",
                             nodes_.Size() + 1 /* artificial root */);
-    writer->PrintProperty64("edge_count", edge_count_ + roots_.length());
+    writer->PrintProperty64("edge_count", edge_count_ + roots_.Size());
   }
   writer->CloseObject();
 
@@ -234,13 +242,14 @@
     writer->OpenArray("edges");
 
     // Write references from the artificial root to the actual roots.
-    for (intptr_t i = 0; i < roots_.length(); ++i) {
-      WriteEdgeInfo(writer, {kElement, i, roots_[i]});
+    ObjectIdToNodeInfoTraits::Pair* entry = nullptr;
+    auto roots_it = roots_.GetIterator();
+    for (int i = 0; (entry = roots_it.Next()) != nullptr; ++i) {
+      WriteEdgeInfo(writer, {kElement, i, entry->key});
     }
 
-    ObjectIdToNodeInfoTraits::Pair* entry = nullptr;
-    auto it = nodes_.GetIterator();
-    while ((entry = it.Next()) != nullptr) {
+    auto nodes_it = nodes_.GetIterator();
+    while ((entry = nodes_it.Next()) != nullptr) {
       for (intptr_t i = 0; i < entry->value.edges->length(); ++i) {
         WriteEdgeInfo(writer, entry->value.edges->At(i));
       }
diff --git a/runtime/vm/v8_snapshot_writer.h b/runtime/vm/v8_snapshot_writer.h
index fa9ee85..63d0617 100644
--- a/runtime/vm/v8_snapshot_writer.h
+++ b/runtime/vm/v8_snapshot_writer.h
@@ -10,6 +10,7 @@
 #include "platform/assert.h"
 #include "vm/allocation.h"
 #include "vm/hash_map.h"
+#include "vm/hash_table.h"
 #include "vm/json_writer.h"
 #include "vm/object.h"
 
@@ -201,7 +202,12 @@
   DirectChainedHashMap<StringToIntMapTraits> node_types_;
   DirectChainedHashMap<StringToIntMapTraits> edge_types_;
   DirectChainedHashMap<StringToIntMapTraits> strings_;
-  ZoneGrowableArray<ObjectId> roots_;
+
+  // We don't have a zone-allocated hash set, so we just re-use the type for
+  // nodes_ even though we don't need to access the node info (and fill it with
+  // dummy values).
+  DirectChainedHashMap<ObjectIdToNodeInfoTraits> roots_;
+
   size_t edge_count_ = 0;
 #endif
 };
diff --git a/runtime/vm/virtual_memory_posix.cc b/runtime/vm/virtual_memory_posix.cc
index fb1fff2..bf9833f 100644
--- a/runtime/vm/virtual_memory_posix.cc
+++ b/runtime/vm/virtual_memory_posix.cc
@@ -35,12 +35,29 @@
 DECLARE_FLAG(bool, dual_map_code);
 DECLARE_FLAG(bool, write_protect_code);
 
+#if defined(TARGET_OS_LINUX)
+DECLARE_FLAG(bool, generate_perf_events_symbols);
+DECLARE_FLAG(bool, generate_perf_jitdump);
+#endif
+
 uword VirtualMemory::page_size_ = 0;
 
 void VirtualMemory::Init() {
   page_size_ = getpagesize();
 
 #if defined(DUAL_MAPPING_SUPPORTED)
+// Perf is Linux-specific and the flags aren't defined in Product.
+#if defined(TARGET_OS_LINUX) && !defined(PRODUCT)
+  // Perf interacts strangely with memfds, leading it to sometimes collect
+  // garbled return addresses.
+  if (FLAG_generate_perf_events_symbols || FLAG_generate_perf_jitdump) {
+    LOG_INFO(
+        "Dual code mapping disabled to generate perf events or jitdump.\n");
+    FLAG_dual_map_code = false;
+    return;
+  }
+#endif
+
   // Detect dual mapping exec permission limitation on some platforms,
   // such as on docker containers, and disable dual mapping in this case.
   // Also detect for missing support of memfd_create syscall.
diff --git a/runtime/vm/visitor.h b/runtime/vm/visitor.h
index 4eac814..165aa3e 100644
--- a/runtime/vm/visitor.h
+++ b/runtime/vm/visitor.h
@@ -37,8 +37,6 @@
   // Range of pointers to visit 'first' <= pointer <= 'last'.
   virtual void VisitPointers(RawObject** first, RawObject** last) = 0;
 
-  virtual bool visit_function_code() const { return true; }
-  virtual void add_skipped_code_function(RawFunction* funct) { UNREACHABLE(); }
   // len argument is the number of pointers to visit starting from 'p'.
   void VisitPointers(RawObject** p, intptr_t len) {
     VisitPointers(p, (p + len - 1));
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 586cc38..a1f20bf 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -46,9 +46,11 @@
   "constants_arm.h",
   "constants_arm64.cc",
   "constants_arm64.h",
+  "constants_dbc.cc",
   "constants_dbc.h",
   "constants_ia32.cc",
   "constants_ia32.h",
+  "constants_kbc.cc",
   "constants_kbc.h",
   "constants_x64.cc",
   "constants_x64.h",
@@ -83,6 +85,7 @@
   "debugger_arm64.cc",
   "debugger_dbc.cc",
   "debugger_ia32.cc",
+  "debugger_kbc.cc",
   "debugger_x64.cc",
   "deferred_objects.cc",
   "deferred_objects.h",
@@ -93,6 +96,8 @@
   "double_internals.h",
   "dwarf.cc",
   "dwarf.h",
+  "elf.cc",
+  "elf.h",
   "exceptions.cc",
   "exceptions.h",
   "finalizable_data.h",
@@ -345,7 +350,6 @@
   "unibrow.cc",
   "unibrow.h",
   "unicode.cc",
-  "unicode.h",
   "unicode_data.cc",
   "uri.cc",
   "uri.h",
@@ -387,10 +391,8 @@
   "cpuinfo_test.cc",
   "custom_isolate_test.cc",
   "dart_api_impl_test.cc",
-  "dart_entry_test.cc",
   "debugger_api_impl_test.cc",
   "exceptions_test.cc",
-  "find_code_object_test.cc",
   "fixed_cache_test.cc",
   "flags_test.cc",
   "growable_array_test.cc",
@@ -429,7 +431,6 @@
   "port_test.cc",
   "profiler_test.cc",
   "regexp_test.cc",
-  "resolver_test.cc",
   "ring_buffer_test.cc",
   "scopes_test.cc",
   "service_test.cc",
diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc
index 2d95479..cdb8ba4 100644
--- a/runtime/vm/zone.cc
+++ b/runtime/vm/zone.cc
@@ -331,24 +331,36 @@
   return OS::VSCreate(this, format, args);
 }
 
-StackZone::StackZone(ThreadState* thread) : StackResource(thread), zone_() {
+StackZone::StackZone(ThreadState* thread)
+    : StackResource(thread), zone_(new Zone()) {
   if (FLAG_trace_zones) {
     OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n",
                  reinterpret_cast<intptr_t>(this),
-                 reinterpret_cast<intptr_t>(&zone_));
+                 reinterpret_cast<intptr_t>(zone_));
   }
-  zone_.Link(thread->zone());
-  thread->set_zone(&zone_);
+
+  // This thread must be preventing safepoints or the GC could be visiting the
+  // chain of handle blocks we're about the mutate.
+  ASSERT(Thread::Current()->MayAllocateHandles());
+
+  zone_->Link(thread->zone());
+  thread->set_zone(zone_);
 }
 
 StackZone::~StackZone() {
-  ASSERT(thread()->zone() == &zone_);
-  thread()->set_zone(zone_.previous_);
+  // This thread must be preventing safepoints or the GC could be visiting the
+  // chain of handle blocks we're about the mutate.
+  ASSERT(Thread::Current()->MayAllocateHandles());
+
+  ASSERT(thread()->zone() == zone_);
+  thread()->set_zone(zone_->previous_);
   if (FLAG_trace_zones) {
     OS::PrintErr("*** Deleting Stack zone 0x%" Px "(0x%" Px ")\n",
                  reinterpret_cast<intptr_t>(this),
-                 reinterpret_cast<intptr_t>(&zone_));
+                 reinterpret_cast<intptr_t>(zone_));
   }
+
+  delete zone_;
 }
 
 }  // namespace dart
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index b4aba7f..88e1ef9 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -177,19 +177,19 @@
   explicit StackZone(ThreadState* thread);
 
   // Delete all memory associated with the zone.
-  ~StackZone();
+  virtual ~StackZone();
 
   // Compute the total size of this zone. This includes wasted space that is
   // due to internal fragmentation in the segments.
-  uintptr_t SizeInBytes() const { return zone_.SizeInBytes(); }
+  uintptr_t SizeInBytes() const { return zone_->SizeInBytes(); }
 
   // Computes the used space in the zone.
-  intptr_t CapacityInBytes() const { return zone_.CapacityInBytes(); }
+  intptr_t CapacityInBytes() const { return zone_->CapacityInBytes(); }
 
-  Zone* GetZone() { return &zone_; }
+  Zone* GetZone() { return zone_; }
 
  private:
-  Zone zone_;
+  Zone* zone_;
 
   template <typename T>
   friend class GrowableArray;
diff --git a/runtime/vm/zone_test.cc b/runtime/vm/zone_test.cc
index a12b5ff..e52b940 100644
--- a/runtime/vm/zone_test.cc
+++ b/runtime/vm/zone_test.cc
@@ -18,6 +18,7 @@
   Thread* thread = Thread::Current();
   EXPECT(thread->zone() == NULL);
   {
+    TransitionNativeToVM transition(thread);
     StackZone stack_zone(thread);
     EXPECT(thread->zone() != NULL);
     Zone* zone = stack_zone.GetZone();
@@ -78,6 +79,7 @@
   Thread* thread = Thread::Current();
   EXPECT(thread->zone() == NULL);
   {
+    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     EXPECT(thread->zone() != NULL);
     uintptr_t allocated_size = 0;
@@ -92,7 +94,7 @@
 }
 
 // This test is expected to crash.
-VM_UNIT_TEST_CASE(AllocGeneric_Overflow) {
+VM_UNIT_TEST_CASE_WITH_EXPECTATION(AllocGeneric_Overflow, "Crash") {
 #if defined(DEBUG)
   FLAG_trace_zones = true;
 #endif
@@ -131,6 +133,7 @@
 
   // Create a few zone allocated objects.
   {
+    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     EXPECT_EQ(0UL, zone.SizeInBytes());
     SimpleZoneObject* first = new SimpleZoneObject();
@@ -156,6 +159,7 @@
 }
 
 TEST_CASE(PrintToString) {
+  TransitionNativeToVM transition(Thread::Current());
   StackZone zone(Thread::Current());
   const char* result = zone.GetZone()->PrintToString("Hello %s!", "World");
   EXPECT_STREQ("Hello World!", result);
@@ -219,7 +223,7 @@
 #endif  // !defined(PRODUCT)
 }
 
-TEST_CASE(StressMallocThroughZones) {
+ISOLATE_UNIT_TEST_CASE(StressMallocThroughZones) {
 #if !defined(PRODUCT)
   int64_t start_rss = Service::CurrentRSS();
 #endif  // !defined(PRODUCT)
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart b/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart
index 122b225..d7b3194 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart
@@ -218,7 +218,7 @@
     _currentScrollStartMouse = coordinate;
   }
 
-  void _onEnd(UIEvent e) {
+  void _onEnd(Event e) {
     _scrollBarDragInProgress = false;
     // TODO(jacobr): make scrollbar less tightly coupled to the scroller.
     _scroller._onScrollerDragEnd.add(new Event(ScrollerEventType.DRAG_END));
diff --git a/samples/ffi/sqlite/docs/sqlite-tutorial.md b/samples/ffi/sqlite/docs/sqlite-tutorial.md
index 7f7aa22..c38170c 100644
--- a/samples/ffi/sqlite/docs/sqlite-tutorial.md
+++ b/samples/ffi/sqlite/docs/sqlite-tutorial.md
@@ -71,19 +71,19 @@
 Strings in C are pointers to character arrays.
 
 ```dart
-class CString extends Pointer<Int8> {}
+class CString extends Pointer<Uint8> {}
 ```
 
 Pointers to C integers, floats, an doubles can be read from and written through to `dart:ffi`.
 However, before we can write to C memory from dart, we need to `allocate` some memory.
 
 ```dart
-Pointer<Int8> p = allocate(); // Infers type argument allocate<Int8>(), and allocates 1 byte.
-p.store(123);                 // Stores a Dart int into this C int8.
-int v = p.load();             // Infers type argument p.load<int>(), and loads a value from C memory.
+Pointer<Uint8> p = allocate(); // Infers type argument allocate<Uint8>(), and allocates 1 byte.
+p.store(123);                  // Stores a Dart int into this C int8.
+int v = p.load();              // Infers type argument p.load<int>(), and loads a value from C memory.
 ```
 
-Note that you can only load a Dart `int` from a C `Int8`.
+Note that you can only load a Dart `int` from a C `Uint8`.
 Trying to load a Dart `double` will result in a runtime exception.
 
 We've almost modeled C Strings.
diff --git a/samples/ffi/sqlite/lib/src/ffi/cstring.dart b/samples/ffi/sqlite/lib/src/ffi/cstring.dart
index 5b07085..da095e4 100644
--- a/samples/ffi/sqlite/lib/src/ffi/cstring.dart
+++ b/samples/ffi/sqlite/lib/src/ffi/cstring.dart
@@ -8,7 +8,7 @@
 import "arena.dart";
 
 /// Represents a String in C memory, managed by an [Arena].
-class CString extends Pointer<Int8> {
+class CString extends Pointer<Uint8> {
   /// Allocates a [CString] in the current [Arena] and populates it with
   /// [dartStr].
   factory CString(String dartStr) => CString.inArena(Arena.current(), dartStr);
@@ -23,7 +23,7 @@
   /// memory manually!
   factory CString.allocate(String dartStr) {
     List<int> units = Utf8Encoder().convert(dartStr);
-    Pointer<Int8> str = allocate(count: units.length + 1);
+    Pointer<Uint8> str = allocate(count: units.length + 1);
     for (int i = 0; i < units.length; ++i) {
       str.elementAt(i).store(units[i]);
     }
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 78cd365..52a35d5 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -571,7 +571,7 @@
 }
 
 copy("copy_abi_dill_files") {
-  visibility = [ ":create_common_sdk" ]
+  visibility = [ ":create_sdk_with_abi_versions" ]
   sources = [
     "../tools/abiversions",
   ]
@@ -668,23 +668,6 @@
   ]
 }
 
-# This rule copies DDC's JS SDK and dart_library.js to lib/dev_compiler/legacy.
-copy("copy_dev_compiler_js_legacy") {
-  visibility = [ ":copy_dev_compiler_js" ]
-  deps = [
-    "../utils/dartdevc:dartdevc_sdk",
-  ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk", "target_gen_dir")
-  sources = [
-    "$gen_dir/js/legacy/dart_sdk.js",
-    "$gen_dir/js/legacy/dart_sdk.js.map",
-    "../pkg/dev_compiler/lib/js/legacy/dart_library.js",
-  ]
-  outputs = [
-    "$root_out_dir/dart-sdk/lib/dev_compiler/legacy/{{source_file_part}}",
-  ]
-}
-
 # This rule copies DDK's JS SDK and require.js to lib/dev_compiler/kernel/amd.
 copy("copy_dev_compiler_js_amd_kernel") {
   visibility = [ ":copy_dev_compiler_js" ]
@@ -738,24 +721,6 @@
   ]
 }
 
-# This rule copies DDK's JS SDK to lib/dev_compiler/kernel/legacy.
-copy("copy_dev_compiler_js_legacy_kernel") {
-  visibility = [ ":copy_dev_compiler_js" ]
-  deps = [
-    "../utils/dartdevc:dartdevc_kernel_sdk",
-  ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_kernel_sdk",
-                           "target_gen_dir")
-  sources = [
-    "$gen_dir/kernel/legacy/dart_sdk.js",
-    "$gen_dir/kernel/legacy/dart_sdk.js.map",
-    "../pkg/dev_compiler/lib/js/legacy/dart_library.js",
-  ]
-  outputs = [
-    "$root_out_dir/dart-sdk/lib/dev_compiler/kernel/legacy/{{source_file_part}}",
-  ]
-}
-
 # Copies all of the JS artifacts needed by DDC.
 group("copy_dev_compiler_js") {
   visibility = [
@@ -769,8 +734,6 @@
     ":copy_dev_compiler_js_common_kernel",
     ":copy_dev_compiler_js_es6",
     ":copy_dev_compiler_js_es6_kernel",
-    ":copy_dev_compiler_js_legacy",
-    ":copy_dev_compiler_js_legacy_kernel",
   ]
 }
 
@@ -974,7 +937,6 @@
 group("create_common_sdk") {
   visibility = [ ":create_sdk" ]
   public_deps = [
-    ":copy_abi_dill_files",
     ":copy_analysis_summaries",
     ":copy_api_readme",
     ":copy_dart",
@@ -1028,3 +990,11 @@
     public_deps += [ ":create_full_sdk" ]
   }
 }
+
+# Same as create_sdk, but with abi version files.
+group("create_sdk_with_abi_versions") {
+  public_deps = [
+    ":copy_abi_dill_files",
+    ":create_sdk",
+  ]
+}
diff --git a/sdk/api_readme.md b/sdk/api_readme.md
index 3e5990dd..2f51f7e 100644
--- a/sdk/api_readme.md
+++ b/sdk/api_readme.md
@@ -16,15 +16,15 @@
 ```
 
 You can install more libraries using the
-[pub package manager](https://www.dartlang.org/tools/pub).
+[pub package manager](https://dart.dev/guides/packages).
   
 The main site for learning and using Dart is
-[www.dartlang.org](https://www.dartlang.org). Check out these pages:
+[dart.dev](https://dart.dev). Check out these pages:
   
-  * [Get started](https://www.dartlang.org/guides/get-started)
-  * [Language tour](https://www.dartlang.org/guides/language/language-tour)
-  * [Library tour](https://www.dartlang.org/guides/libraries/library-tour)
-  * [Sample code](https://www.dartlang.org/samples)
+  * [Platforms](https://dart.dev/platforms)
+  * [Language tour](https://dart.dev/guides/language/language-tour)
+  * [Library tour](https://dart.dev/guides/libraries/library-tour)
+  * [Sample code](https://dart.dev/samples)
   
 This API reference is automatically generated from source code in the [Dart
 SDK project](https://github.com/dart-lang/sdk).
diff --git a/sdk/lib/_http/http.dart b/sdk/lib/_http/http.dart
index f1e72be..1e2560f 100644
--- a/sdk/lib/_http/http.dart
+++ b/sdk/lib/_http/http.dart
@@ -1958,6 +1958,14 @@
    */
   int get contentLength;
 
+  /// The compression state of the response.
+  ///
+  /// This specifies whether the response bytes were compressed when they were
+  /// received across the wire and whether callers will receive compressed
+  /// or uncompressed bytes when they listed to this response's byte stream.
+  @Since("2.4")
+  HttpClientResponseCompressionState get compressionState;
+
   /**
    * Gets the persistent connection state returned by the server.
    *
@@ -2037,6 +2045,49 @@
   HttpConnectionInfo get connectionInfo;
 }
 
+/// Enum that specifies the compression state of the byte stream of an
+/// [HttpClientResponse].
+///
+/// The values herein allow callers to answer the following questions as they
+/// pertain to an [HttpClientResponse]:
+///
+///  * Can the value of the response's `Content-Length` HTTP header be trusted?
+///  * Does the caller need to manually decompress the response's byte stream?
+///
+/// This enum is accessed via the [HttpClientResponse.compressionState] value.
+@Since("2.4")
+enum HttpClientResponseCompressionState {
+  /// The body of the HTTP response was received and remains in an uncompressed
+  /// state.
+  ///
+  /// In this state, the value of the `Content-Length` HTTP header, if
+  /// specified (non-negative), should match the number of bytes produced by
+  /// the response's byte stream.
+  notCompressed,
+
+  /// The body of the HTTP response was originally compressed, but by virtue of
+  /// the [HttpClient.autoUncompress] configuration option, it has been
+  /// automatically uncompressed.
+  ///
+  /// HTTP headers are not modified, so when a response has been uncompressed
+  /// in this way, the value of the `Content-Length` HTTP header cannot be
+  /// trusted, as it will contain the compressed content length, whereas the
+  /// stream of bytes produced by the response will contain uncompressed bytes.
+  decompressed,
+
+  /// The body of the HTTP response contains compressed bytes.
+  ///
+  /// In this state, the value of the `Content-Length` HTTP header, if
+  /// specified (non-negative), should match the number of bytes produced by
+  /// the response's byte stream.
+  ///
+  /// If the caller wishes to manually uncompress the body of the response,
+  /// it should consult the value of the `Content-Encoding` HTTP header to see
+  /// what type of compression has been applied. See
+  /// <https://tools.ietf.org/html/rfc2616#section-14.11> for more information.
+  compressed,
+}
+
 abstract class HttpClientCredentials {}
 
 /**
diff --git a/sdk/lib/_http/http_headers.dart b/sdk/lib/_http/http_headers.dart
index ea5eaff..dc9ff84 100644
--- a/sdk/lib/_http/http_headers.dart
+++ b/sdk/lib/_http/http_headers.dart
@@ -982,14 +982,24 @@
           codeUnit >= 127 ||
           separators.indexOf(name[i]) >= 0) {
         throw new FormatException(
-            "Invalid character in cookie name, code unit: '$codeUnit'");
+            "Invalid character in cookie name, code unit: '$codeUnit'",
+            name,
+            i);
       }
     }
 
-    if (value[0] == '"' && value[value.length - 1] == '"') {
-      value = value.substring(1, value.length - 1);
+    // Per RFC 6265, consider surrounding "" as part of the value, but otherwise
+    // double quotes are not allowed.
+    int start = 0;
+    int end = value.length;
+    if (2 <= value.length &&
+        value.codeUnits[start] == 0x22 &&
+        value.codeUnits[end - 1] == 0x22) {
+      start++;
+      end--;
     }
-    for (int i = 0; i < value.length; i++) {
+
+    for (int i = start; i < end; i++) {
       int codeUnit = value.codeUnits[i];
       if (!(codeUnit == 0x21 ||
           (codeUnit >= 0x23 && codeUnit <= 0x2B) ||
@@ -997,7 +1007,9 @@
           (codeUnit >= 0x3C && codeUnit <= 0x5B) ||
           (codeUnit >= 0x5D && codeUnit <= 0x7E))) {
         throw new FormatException(
-            "Invalid character in cookie value, code unit: '$codeUnit'");
+            "Invalid character in cookie value, code unit: '$codeUnit'",
+            value,
+            i);
       }
     }
   }
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index f0e365d..497516c 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -292,20 +292,35 @@
   // The HttpClientRequest of this response.
   final _HttpClientRequest _httpRequest;
 
+  // The compression state of this response.
+  final HttpClientResponseCompressionState compressionState;
+
   _HttpClientResponse(
       _HttpIncoming _incoming, this._httpRequest, this._httpClient)
-      : super(_incoming) {
+      : compressionState = _getCompressionState(_httpClient, _incoming.headers),
+        super(_incoming) {
     // Set uri for potential exceptions.
     _incoming.uri = _httpRequest.uri;
   }
 
+  static HttpClientResponseCompressionState _getCompressionState(
+      _HttpClient httpClient, _HttpHeaders headers) {
+    if (headers.value(HttpHeaders.contentEncodingHeader) == "gzip") {
+      return httpClient.autoUncompress
+          ? HttpClientResponseCompressionState.decompressed
+          : HttpClientResponseCompressionState.compressed;
+    } else {
+      return HttpClientResponseCompressionState.notCompressed;
+    }
+  }
+
   int get statusCode => _incoming.statusCode;
   String get reasonPhrase => _incoming.reasonPhrase;
 
   X509Certificate get certificate {
     var socket = _httpRequest._httpClientConnection._socket;
     if (socket is SecureSocket) return socket.peerCertificate;
-    throw new UnsupportedError("Socket is not a SecureSocket");
+    return null;
   }
 
   List<Cookie> get cookies {
@@ -377,8 +392,7 @@
       return new Stream<List<int>>.empty().listen(null, onDone: onDone);
     }
     Stream<List<int>> stream = _incoming;
-    if (_httpClient.autoUncompress &&
-        headers.value(HttpHeaders.contentEncodingHeader) == "gzip") {
+    if (compressionState == HttpClientResponseCompressionState.decompressed) {
       stream = stream.transform(gzip.decoder);
     }
     return stream.listen(onData,
diff --git a/sdk/lib/_http/websocket.dart b/sdk/lib/_http/websocket.dart
index 64dbeb1..5a949af 100644
--- a/sdk/lib/_http/websocket.dart
+++ b/sdk/lib/_http/websocket.dart
@@ -50,51 +50,78 @@
   static const int RESERVED_1015 = reserved1015;
 }
 
-/**
- * The [CompressionOptions] class allows you to control
- * the options of WebSocket compression.
- */
+/// Options controlling compression in a [WebSocket].
+///
+/// A [CompressionOptions] instance can be passed to [WebSocket.connect], or
+/// used in other similar places where [WebSocket] compression is configured.
+///
+/// In most cases the default [compressionDefault] is sufficient, but in some
+/// situations, it might be desirable to use different compression parameters,
+/// for example to preserve memory on small devices.
 class CompressionOptions {
-  /// Default WebSocket Compression options.
+  /// Default [WebSocket] compression configuration.
   ///
-  /// Compression will be enabled with the following options:
+  /// Enables compression with default window sizes and no reuse. This is the
+  /// default options used by [WebSocket.connect] if no [CompressionOptions] is
+  /// supplied.
   ///
   /// * `clientNoContextTakeover`: false
   /// * `serverNoContextTakeover`: false
-  /// * `clientMaxWindowBits`: 15
-  /// * `serverMaxWindowBits`: 15
+  /// * `clientMaxWindowBits`: null (default maximal window size of 15 bits)
+  /// * `serverMaxWindowBits`: null (default maximal window size of 15 bits)
   static const CompressionOptions compressionDefault =
       const CompressionOptions();
   @Deprecated("Use compressionDefault instead")
   static const CompressionOptions DEFAULT = compressionDefault;
 
-  /// Disables WebSocket Compression.
+  /// No-compression configuration.
+  ///
+  /// Disables compression when used as compression configuration for a
+  /// [WebSocket].
   static const CompressionOptions compressionOff =
       const CompressionOptions(enabled: false);
   @Deprecated("Use compressionOff instead")
   static const CompressionOptions OFF = compressionOff;
 
-  /// Controls whether the client will reuse its compression instances.
+  /// Whether the client will reuse its compression instances.
   final bool clientNoContextTakeover;
 
-  /// Controls whether the server will reuse its compression instances.
+  /// Whether the server will reuse its compression instances.
   final bool serverNoContextTakeover;
 
-  /// Determines the max window bits for the client.
+  /// The maximal window size bit count requested by the client.
+  ///
+  /// The windows size for the compression is always a power of two, so the
+  /// number of bits precisely determines the window size.
+  ///
+  /// If set to `null`, the client has no preference, and the compression can
+  /// use up to its default maximum window size of 15 bits depending on the
+  /// server's preference.
   final int clientMaxWindowBits;
 
-  /// Determines the max window bits for the server.
+  /// The maximal window size bit count requested by the server.
+  ///
+  /// The windows size for the compression is always a power of two, so the
+  /// number of bits precisely determines the window size.
+  ///
+  /// If set to `null`, the server has no preference, and the compression can
+  /// use up to its default maximum window size of 15 bits depending on the
+  /// client's preference.
   final int serverMaxWindowBits;
 
-  /// Enables or disables WebSocket compression.
+  /// Whether WebSocket compression is enabled.
+  ///
+  /// If not enabled, the remaining fields have no effect, and the
+  /// [compressionOff] instance can, and should, be reused instead of creating a
+  /// new instance with compression disabled.
   final bool enabled;
 
   const CompressionOptions(
-      {this.clientNoContextTakeover: false,
-      this.serverNoContextTakeover: false,
+      {this.clientNoContextTakeover = false,
+      this.serverNoContextTakeover = false,
       this.clientMaxWindowBits,
       this.serverMaxWindowBits,
-      this.enabled: true});
+      this.enabled = true});
 
   /// Parses list of requested server headers to return server compression
   /// response headers.
diff --git a/sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart b/sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart
new file mode 100644
index 0000000..b16c43e
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart
@@ -0,0 +1,584 @@
+// 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.
+
+/**
+ * Support for interoperating with JavaScript.
+ *
+ * This library provides access to JavaScript objects from Dart, allowing
+ * Dart code to get and set properties, and call methods of JavaScript objects
+ * and invoke JavaScript functions. The library takes care of converting
+ * between Dart and JavaScript objects where possible, or providing proxies if
+ * conversion isn't possible.
+ *
+ * This library does not yet make Dart objects usable from JavaScript, their
+ * methods and proeprties are not accessible, though it does allow Dart
+ * functions to be passed into and called from JavaScript.
+ *
+ * [JsObject] is the core type and represents a proxy of a JavaScript object.
+ * JsObject gives access to the underlying JavaScript objects properties and
+ * methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
+ * created from proxies to JavaScript constructors.
+ *
+ * The top-level getter [context] provides a [JsObject] that represents the
+ * global object in JavaScript, usually `window`.
+ *
+ * The following example shows an alert dialog via a JavaScript call to the
+ * global function `alert()`:
+ *
+ *     import 'dart:js';
+ *
+ *     main() => context.callMethod('alert', ['Hello from Dart!']);
+ *
+ * This example shows how to create a [JsObject] from a JavaScript constructor
+ * and access its properties:
+ *
+ *     import 'dart:js';
+ *
+ *     main() {
+ *       var object = new JsObject(context['Object']);
+ *       object['greeting'] = 'Hello';
+ *       object['greet'] = (name) => "${object['greeting']} $name";
+ *       var message = object.callMethod('greet', ['JavaScript']);
+ *       context['console'].callMethod('log', [message]);
+ *     }
+ *
+ * ## Proxying and automatic conversion
+ *
+ * When setting properties on a JsObject or passing arguments to a Javascript
+ * method or function, Dart objects are automatically converted or proxied to
+ * JavaScript objects. When accessing JavaScript properties, or when a Dart
+ * closure is invoked from JavaScript, the JavaScript objects are also
+ * converted to Dart.
+ *
+ * Functions and closures are proxied in such a way that they are callable. A
+ * Dart closure assigned to a JavaScript property is proxied by a function in
+ * JavaScript. A JavaScript function accessed from Dart is proxied by a
+ * [JsFunction], which has a [apply] method to invoke it.
+ *
+ * The following types are transferred directly and not proxied:
+ *
+ * * "Basic" types: `null`, `bool`, `num`, `String`, `DateTime`
+ * * `Blob`
+ * * `Event`
+ * * `HtmlCollection`
+ * * `ImageData`
+ * * `KeyRange`
+ * * `Node`
+ * * `NodeList`
+ * * `TypedData`, including its subclasses like `Int32List`, but _not_
+ *   `ByteBuffer`
+ * * `Window`
+ *
+ * ## Converting collections with JsObject.jsify()
+ *
+ * To create a JavaScript collection from a Dart collection use the
+ * [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
+ * into JavaScript Objects and Arrays.
+ *
+ * The following expression creates a new JavaScript object with the properties
+ * `a` and `b` defined:
+ *
+ *     var jsMap = new JsObject.jsify({'a': 1, 'b': 2});
+ *
+ * This expression creates a JavaScript array:
+ *
+ *     var jsArray = new JsObject.jsify([1, 2, 3]);
+ */
+library dart.js;
+
+import 'dart:collection' show HashMap, ListMixin;
+
+import 'dart:_js_helper' show Primitives;
+import 'dart:_foreign_helper' show JS;
+import 'dart:_runtime' as dart;
+
+final JsObject context = _wrapToDart(dart.global_);
+
+/**
+ * Proxies a JavaScript object to Dart.
+ *
+ * The properties of the JavaScript object are accessible via the `[]` and
+ * `[]=` operators. Methods are callable via [callMethod].
+ */
+class JsObject {
+  // The wrapped JS object.
+  final dynamic _jsObject;
+
+  // This should only be called from _wrapToDart
+  JsObject._fromJs(this._jsObject) {
+    assert(_jsObject != null);
+  }
+
+  /**
+   * Constructs a new JavaScript object from [constructor] and returns a proxy
+   * to it.
+   */
+  factory JsObject(JsFunction constructor, [List arguments]) {
+    var ctor = constructor._jsObject;
+    if (arguments == null) {
+      return _wrapToDart(JS('', 'new #()', ctor));
+    }
+    var unwrapped = List.from(arguments.map(_convertToJS));
+    return _wrapToDart(JS('', 'new #(...#)', ctor, unwrapped));
+  }
+
+  /**
+   * Constructs a [JsObject] that proxies a native Dart object; _for expert use
+   * only_.
+   *
+   * Use this constructor only if you wish to get access to JavaScript
+   * properties attached to a browser host object, such as a Node or Blob, that
+   * is normally automatically converted into a native Dart object.
+   *
+   * An exception will be thrown if [object] either is `null` or has the type
+   * `bool`, `num`, or `String`.
+   */
+  factory JsObject.fromBrowserObject(object) {
+    if (object is num || object is String || object is bool || object == null) {
+      throw ArgumentError("object cannot be a num, string, bool, or null");
+    }
+    return _wrapToDart(_convertToJS(object));
+  }
+
+  /**
+   * 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 transferable values are directly converted to their
+   * JavaScript type, and all other objects are proxied.
+   */
+  factory JsObject.jsify(object) {
+    if ((object is! Map) && (object is! Iterable)) {
+      throw ArgumentError("object must be a Map or Iterable");
+    }
+    return _wrapToDart(_convertDataTree(object));
+  }
+
+  static _convertDataTree(data) {
+    var _convertedObjects = HashMap.identity();
+
+    _convert(o) {
+      if (_convertedObjects.containsKey(o)) {
+        return _convertedObjects[o];
+      }
+      if (o is Map) {
+        final convertedMap = JS('', '{}');
+        _convertedObjects[o] = convertedMap;
+        for (var key in o.keys) {
+          JS('', '#[#] = #', 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 _convertToJS(o);
+      }
+    }
+
+    return _convert(data);
+  }
+
+  /**
+   * Returns the value associated with [property] from the proxied JavaScript
+   * object.
+   *
+   * The type of [property] must be either [String] or [num].
+   */
+  dynamic operator [](Object property) {
+    if (property is! String && property is! num) {
+      throw ArgumentError("property is not a String or num");
+    }
+    return _convertToDart(JS('', '#[#]', _jsObject, property));
+  }
+
+  /**
+   * Sets the value associated with [property] on the proxied JavaScript
+   * object.
+   *
+   * The type of [property] must be either [String] or [num].
+   */
+  void operator []=(Object property, value) {
+    if (property is! String && property is! num) {
+      throw ArgumentError("property is not a String or num");
+    }
+    JS('', '#[#] = #', _jsObject, property, _convertToJS(value));
+  }
+
+  int get hashCode => 0;
+
+  bool operator ==(other) =>
+      other is JsObject && JS('bool', '# === #', _jsObject, other._jsObject);
+
+  /**
+   * Returns `true` if the JavaScript object contains the specified property
+   * either directly or though its prototype chain.
+   *
+   * This is the equivalent of the `in` operator in JavaScript.
+   */
+  bool hasProperty(property) {
+    if (property is! String && property is! num) {
+      throw ArgumentError("property is not a String or num");
+    }
+    return JS('bool', '# in #', property, _jsObject);
+  }
+
+  /**
+   * Removes [property] from the JavaScript object.
+   *
+   * This is the equivalent of the `delete` operator in JavaScript.
+   */
+  void deleteProperty(property) {
+    if (property is! String && property is! num) {
+      throw ArgumentError("property is not a String or num");
+    }
+    JS('bool', 'delete #[#]', _jsObject, property);
+  }
+
+  /**
+   * Returns `true` if the JavaScript object has [type] in its prototype chain.
+   *
+   * This is the equivalent of the `instanceof` operator in JavaScript.
+   */
+  bool instanceof(JsFunction type) {
+    return JS('bool', '# instanceof #', _jsObject, _convertToJS(type));
+  }
+
+  /**
+   * Returns the result of the JavaScript objects `toString` method.
+   */
+  String toString() {
+    try {
+      return JS('String', 'String(#)', _jsObject);
+    } catch (e) {
+      return super.toString();
+    }
+  }
+
+  /**
+   * Calls [method] on the JavaScript object with the arguments [args] and
+   * returns the result.
+   *
+   * The type of [method] must be either [String] or [num].
+   */
+  dynamic callMethod(method, [List args]) {
+    if (method is! String && method is! num) {
+      throw ArgumentError("method is not a String or num");
+    }
+    if (args != null) args = List.from(args.map(_convertToJS));
+    var fn = JS('', '#[#]', _jsObject, method);
+    if (JS('bool', 'typeof(#) !== "function"', fn)) {
+      throw NoSuchMethodError(_jsObject, Symbol(method), args, {});
+    }
+    return _convertToDart(JS('', '#.apply(#, #)', fn, _jsObject, args));
+  }
+}
+
+/**
+ * Proxies a JavaScript Function object.
+ */
+class JsFunction extends JsObject {
+  /**
+   * Returns a [JsFunction] that captures its 'this' binding and calls [f]
+   * with the value of this passed as the first argument.
+   */
+  factory JsFunction.withThis(Function f) {
+    return JsFunction._fromJs(JS(
+        '',
+        'function(/*...arguments*/) {'
+            '  let args = [#(this)];'
+            '  for (let arg of arguments) {'
+            '    args.push(#(arg));'
+            '  }'
+            '  return #(#(...args));'
+            '}',
+        _convertToDart,
+        _convertToDart,
+        _convertToJS,
+        f));
+  }
+
+  JsFunction._fromJs(jsObject) : super._fromJs(jsObject);
+
+  /**
+   * 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}) => _convertToDart(JS(
+      '',
+      '#.apply(#, #)',
+      _jsObject,
+      _convertToJS(thisArg),
+      args == null ? null : List.from(args.map(_convertToJS))));
+}
+
+// TODO(jmesserly): this is totally unnecessary in dev_compiler.
+/** A [List] that proxies a JavaScript array. */
+class JsArray<E> extends JsObject with ListMixin<E> {
+  /**
+   * Creates a new JavaScript array.
+   */
+  JsArray() : super._fromJs([]);
+
+  /**
+   * Creates a new JavaScript array and initializes it to the contents of
+   * [other].
+   */
+  JsArray.from(Iterable<E> other)
+      : super._fromJs([]..addAll(other.map(_convertToJS)));
+
+  JsArray._fromJs(jsObject) : super._fromJs(jsObject);
+
+  _checkIndex(int index) {
+    if (index is int && (index < 0 || index >= length)) {
+      throw RangeError.range(index, 0, length);
+    }
+  }
+
+  _checkInsertIndex(int index) {
+    if (index is int && (index < 0 || index >= length + 1)) {
+      throw RangeError.range(index, 0, length);
+    }
+  }
+
+  static _checkRange(int start, int end, int length) {
+    if (start < 0 || start > length) {
+      throw RangeError.range(start, 0, length);
+    }
+    if (end < start || end > length) {
+      throw RangeError.range(end, start, length);
+    }
+  }
+
+  // Methods required by ListMixin
+
+  E operator [](Object index) {
+    // TODO(justinfagnani): fix the semantics for non-ints
+    // dartbug.com/14605
+    if (index is num && index == index.toInt()) {
+      _checkIndex(index);
+    }
+    return super[index] as E;
+  }
+
+  void operator []=(Object index, value) {
+    // TODO(justinfagnani): fix the semantics for non-ints
+    // dartbug.com/14605
+    if (index is num && index == index.toInt()) {
+      _checkIndex(index);
+    }
+    super[index] = value;
+  }
+
+  int get length {
+    // Check the length honours the List contract.
+    var len = JS('', '#.length', _jsObject);
+    // JavaScript arrays have lengths which are unsigned 32-bit integers.
+    if (JS('bool', 'typeof # === "number" && (# >>> 0) === #', len, len, len)) {
+      return JS('int', '#', len);
+    }
+    throw StateError('Bad JsArray length');
+  }
+
+  void set length(int length) {
+    super['length'] = length;
+  }
+
+  // Methods overridden for better performance
+
+  void add(E value) {
+    callMethod('push', [value]);
+  }
+
+  void addAll(Iterable<E> iterable) {
+    var list = (JS('bool', '# instanceof Array', iterable))
+        ? iterable
+        : List.from(iterable);
+    callMethod('push', list);
+  }
+
+  void insert(int index, E element) {
+    _checkInsertIndex(index);
+    callMethod('splice', [index, 0, element]);
+  }
+
+  E removeAt(int index) {
+    _checkIndex(index);
+    return callMethod('splice', [index, 1])[0] as E;
+  }
+
+  E removeLast() {
+    if (length == 0) throw RangeError(-1);
+    return callMethod('pop') as E;
+  }
+
+  void removeRange(int start, int end) {
+    _checkRange(start, end, length);
+    callMethod('splice', [start, end - start]);
+  }
+
+  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
+    _checkRange(start, end, this.length);
+    int length = end - start;
+    if (length == 0) return;
+    if (skipCount < 0) throw ArgumentError(skipCount);
+    var args = <Object>[start, length]
+      ..addAll(iterable.skip(skipCount).take(length));
+    callMethod('splice', args);
+  }
+
+  void sort([int compare(E a, E b)]) {
+    // Note: arr.sort(null) is a type error in FF
+    callMethod('sort', compare == null ? [] : [compare]);
+  }
+}
+
+// Cross frame objects should not be considered browser types.
+// We include the instanceof Object test to filter out cross frame objects
+// on FireFox. Surprisingly on FireFox the instanceof Window test succeeds for
+// cross frame windows while the instanceof Object test fails.
+bool _isBrowserType(o) => JS(
+    'bool',
+    '# instanceof Object && ('
+        '# instanceof Blob || '
+        '# instanceof Event || '
+        '(window.KeyRange && # instanceof KeyRange) || '
+        '(window.IDBKeyRange && # instanceof IDBKeyRange) || '
+        '# instanceof ImageData || '
+        '# instanceof Node || '
+        // Int8Array.__proto__ is TypedArray.
+        '(window.Int8Array && # instanceof Int8Array.__proto__) || '
+        '# instanceof Window)',
+    o,
+    o,
+    o,
+    o,
+    o,
+    o,
+    o,
+    o,
+    o);
+
+class _DartObject {
+  final _dartObj;
+  _DartObject(this._dartObj);
+}
+
+dynamic _convertToJS(dynamic o) {
+  if (o == null || o is String || o is num || o is bool || _isBrowserType(o)) {
+    return o;
+  } else if (o is DateTime) {
+    return Primitives.lazyAsJsDate(o);
+  } else if (o is JsObject) {
+    return o._jsObject;
+  } else if (o is Function) {
+    return _putIfAbsent(_jsProxies, o, _wrapDartFunction);
+  } else {
+    // TODO(jmesserly): for now, we wrap other objects, to keep compatibility
+    // with the original dart:js behavior.
+    return _putIfAbsent(_jsProxies, o, (o) => _DartObject(o));
+  }
+}
+
+dynamic _wrapDartFunction(f) {
+  var wrapper = JS(
+      '',
+      'function(/*...arguments*/) {'
+          '  let args = Array.prototype.map.call(arguments, #);'
+          '  return #(#(...args));'
+          '}',
+      _convertToDart,
+      _convertToJS,
+      f);
+  JS('', '#.set(#, #)', _dartProxies, wrapper, f);
+
+  return wrapper;
+}
+
+// converts a Dart object to a reference to a native JS object
+// which might be a DartObject JS->Dart proxy
+Object _convertToDart(o) {
+  if (o == null || o is String || o is num || o is bool || _isBrowserType(o)) {
+    return o;
+  } else if (JS('!', '# instanceof Date', o)) {
+    num ms = JS('!', '#.getTime()', o);
+    return DateTime.fromMillisecondsSinceEpoch(ms);
+  } else if (o is _DartObject &&
+      !identical(dart.getReifiedType(o), dart.jsobject)) {
+    return o._dartObj;
+  } else {
+    return _wrapToDart(o);
+  }
+}
+
+Object _wrapToDart(o) => _putIfAbsent(_dartProxies, o, _wrapToDartHelper);
+
+Object _wrapToDartHelper(o) {
+  if (JS('bool', 'typeof # == "function"', o)) {
+    return JsFunction._fromJs(o);
+  }
+  if (JS('bool', '# instanceof Array', o)) {
+    return JsArray._fromJs(o);
+  }
+  return JsObject._fromJs(o);
+}
+
+final _dartProxies = JS('', 'new WeakMap()');
+final _jsProxies = JS('', 'new WeakMap()');
+
+Object _putIfAbsent(weakMap, o, getValue(o)) {
+  var value = JS('', '#.get(#)', weakMap, o);
+  if (value == null) {
+    value = getValue(o);
+    JS('', '#.set(#, #)', weakMap, o, value);
+  }
+  return value;
+}
+
+// The allowInterop method is a no-op in Dart Dev Compiler.
+// TODO(jacobr): tag methods so we can throw if a Dart method is passed to
+// JavaScript using the new interop without calling allowInterop.
+
+/// Returns a wrapper around function [f] that can be called from JavaScript
+/// using the package:js Dart-JavaScript interop.
+///
+/// For performance reasons in Dart2Js, by default Dart functions cannot be
+/// passed directly to JavaScript unless this method is called to create
+/// a Function compatible with both Dart and JavaScript.
+/// Calling this method repeatedly on a function will return the same function.
+/// The [Function] returned by this method can be used from both Dart and
+/// 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.
+F allowInterop<F extends Function>(F f) => f;
+
+Expando<Function> _interopCaptureThisExpando = Expando<Function>();
+
+/// Returns a [Function] that when called from JavaScript captures its 'this'
+/// binding and calls [f] with the value of this passed as the first argument.
+/// When called from Dart, [null] will be passed as the first argument.
+///
+/// See the documentation for [allowInterop]. This method should only be used
+/// with package:js Dart-JavaScript interop.
+Function allowInteropCaptureThis(Function f) {
+  var ret = _interopCaptureThisExpando[f];
+  if (ret == null) {
+    ret = JS(
+        '',
+        'function(/*...arguments*/) {'
+            '  let args = [this];'
+            '  for (let arg of arguments) {'
+            '    args.push(arg);'
+            '  }'
+            '  return #(...args);'
+            '}',
+        f);
+    _interopCaptureThisExpando[f] = ret;
+  }
+  return ret;
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/lib/js_util/dart2js/js_util_dart2js.dart b/sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/lib/js_util/dart2js/js_util_dart2js.dart
rename to sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
diff --git a/sdk/lib/_internal/js_dev_runtime/libraries.dart b/sdk/lib/_internal/js_dev_runtime/libraries.dart
new file mode 100644
index 0000000..d5cffa2
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/libraries.dart
@@ -0,0 +1,310 @@
+// 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.
+
+library libraries;
+
+/**
+ * A bit flag used by [LibraryInfo] indicating that a library is used by dart2js
+ */
+const int DART2JS_PLATFORM = 1;
+
+/**
+ * A bit flag used by [LibraryInfo] indicating that a library is used by the VM
+ */
+const int VM_PLATFORM = 2;
+
+/// The contexts that a library can be used from.
+enum Category {
+  /// Indicates that a library can be used in a browser context.
+  client,
+
+  /// Indicates that a library can be used in a command line context.
+  server,
+
+  /// Indicates that a library can be used from embedded devices.
+  embedded
+}
+
+Category parseCategory(String name) {
+  switch (name) {
+    case "Client":
+      return Category.client;
+    case "Server":
+      return Category.server;
+    case "Embedded":
+      return Category.embedded;
+  }
+  return null;
+}
+
+/// Mapping of "dart:" library name (e.g. "core") to information about that
+/// library.
+const Map<String, LibraryInfo> libraries = const {
+  "async": const LibraryInfo("async/async.dart",
+      categories: "Client,Server",
+      maturity: Maturity.STABLE,
+      dart2jsPatchPath: "_internal/js_runtime/lib/async_patch.dart"),
+  "collection": const LibraryInfo("collection/collection.dart",
+      categories: "Client,Server,Embedded",
+      maturity: Maturity.STABLE,
+      dart2jsPatchPath: "_internal/js_runtime/lib/collection_patch.dart"),
+  "convert": const LibraryInfo("convert/convert.dart",
+      categories: "Client,Server",
+      maturity: Maturity.STABLE,
+      dart2jsPatchPath: "_internal/js_runtime/lib/convert_patch.dart"),
+  "core": const LibraryInfo("core/core.dart",
+      categories: "Client,Server,Embedded",
+      maturity: Maturity.STABLE,
+      dart2jsPatchPath: "_internal/js_runtime/lib/core_patch.dart"),
+  "developer": const LibraryInfo("developer/developer.dart",
+      categories: "Client,Server,Embedded",
+      maturity: Maturity.UNSTABLE,
+      dart2jsPatchPath: "_internal/js_runtime/lib/developer_patch.dart"),
+  "html": const LibraryInfo("html/dart2js/html_dart2js.dart",
+      categories: "Client",
+      maturity: Maturity.WEB_STABLE,
+      platforms: DART2JS_PLATFORM),
+  "html_common": const LibraryInfo("html/html_common/html_common.dart",
+      categories: "Client",
+      maturity: Maturity.WEB_STABLE,
+      dart2jsPath: "html/html_common/html_common_dart2js.dart",
+      documented: false,
+      implementation: true),
+  "indexed_db": const LibraryInfo("indexed_db/dart2js/indexed_db_dart2js.dart",
+      categories: "Client",
+      maturity: Maturity.WEB_STABLE,
+      platforms: DART2JS_PLATFORM),
+  "_http":
+      const LibraryInfo("_http/http.dart", categories: "", documented: false),
+  "io": const LibraryInfo("io/io.dart",
+      categories: "Server",
+      dart2jsPatchPath: "_internal/js_runtime/lib/io_patch.dart"),
+  "isolate": const LibraryInfo("isolate/isolate.dart",
+      categories: "Client,Server",
+      maturity: Maturity.STABLE,
+      dart2jsPatchPath: "_internal/js_runtime/lib/isolate_patch.dart"),
+  "js": const LibraryInfo("js/dart2js/js_dart2js.dart",
+      categories: "Client",
+      maturity: Maturity.STABLE,
+      platforms: DART2JS_PLATFORM),
+  "js_util": const LibraryInfo("js_util/dart2js/js_util_dart2js.dart",
+      categories: "Client",
+      maturity: Maturity.STABLE,
+      platforms: DART2JS_PLATFORM),
+  "math": const LibraryInfo("math/math.dart",
+      categories: "Client,Server,Embedded",
+      maturity: Maturity.STABLE,
+      dart2jsPatchPath: "_internal/js_runtime/lib/math_patch.dart"),
+  "mirrors": const LibraryInfo("mirrors/mirrors.dart",
+      categories: "Client,Server",
+      maturity: Maturity.UNSTABLE,
+      dart2jsPatchPath: "_internal/js_runtime/lib/mirrors_patch.dart"),
+  "nativewrappers": const LibraryInfo("html/dartium/nativewrappers.dart",
+      categories: "Client",
+      implementation: true,
+      documented: false,
+      platforms: DART2JS_PLATFORM),
+  "typed_data": const LibraryInfo("typed_data/typed_data.dart",
+      categories: "Client,Server,Embedded",
+      maturity: Maturity.STABLE,
+      dart2jsPatchPath: "_internal/js_runtime/lib/typed_data_patch.dart"),
+  "_native_typed_data": const LibraryInfo(
+      "_internal/js_runtime/lib/native_typed_data.dart",
+      categories: "",
+      implementation: true,
+      documented: false,
+      platforms: DART2JS_PLATFORM),
+  "cli": const LibraryInfo("cli/cli.dart",
+      categories: "Server",
+      dart2jsPatchPath: "_internal/js_runtime/lib/cli_patch.dart"),
+  "svg": const LibraryInfo("svg/dart2js/svg_dart2js.dart",
+      categories: "Client",
+      maturity: Maturity.WEB_STABLE,
+      platforms: DART2JS_PLATFORM),
+  "web_audio": const LibraryInfo("web_audio/dart2js/web_audio_dart2js.dart",
+      categories: "Client",
+      maturity: Maturity.WEB_STABLE,
+      platforms: DART2JS_PLATFORM),
+  "web_gl": const LibraryInfo("web_gl/dart2js/web_gl_dart2js.dart",
+      categories: "Client",
+      maturity: Maturity.WEB_STABLE,
+      platforms: DART2JS_PLATFORM),
+  "web_sql": const LibraryInfo("web_sql/dart2js/web_sql_dart2js.dart",
+      categories: "Client",
+      maturity: Maturity.WEB_STABLE,
+      platforms: DART2JS_PLATFORM),
+  "_internal": const LibraryInfo("internal/internal.dart",
+      categories: "",
+      documented: false,
+      dart2jsPatchPath: "_internal/js_runtime/lib/internal_patch.dart"),
+  "_js_helper": const LibraryInfo("_internal/js_runtime/lib/js_helper.dart",
+      categories: "", documented: false, platforms: DART2JS_PLATFORM),
+  "_interceptors": const LibraryInfo(
+      "_internal/js_runtime/lib/interceptors.dart",
+      categories: "",
+      documented: false,
+      platforms: DART2JS_PLATFORM),
+  "_foreign_helper": const LibraryInfo(
+      "_internal/js_runtime/lib/foreign_helper.dart",
+      categories: "",
+      documented: false,
+      platforms: DART2JS_PLATFORM),
+  "_isolate_helper": const LibraryInfo(
+      "_internal/js_runtime/lib/isolate_helper.dart",
+      categories: "",
+      documented: false,
+      platforms: DART2JS_PLATFORM),
+  "_js_mirrors": const LibraryInfo("_internal/js_runtime/lib/js_mirrors.dart",
+      categories: "", documented: false, platforms: DART2JS_PLATFORM),
+  "_js_primitives": const LibraryInfo(
+      "_internal/js_runtime/lib/js_primitives.dart",
+      categories: "",
+      documented: false,
+      platforms: DART2JS_PLATFORM),
+  "_metadata": const LibraryInfo("html/html_common/metadata.dart",
+      categories: "", documented: false, platforms: DART2JS_PLATFORM),
+  "_debugger": const LibraryInfo("_internal/js_runtime/lib/debugger.dart",
+      category: "", documented: false, platforms: DART2JS_PLATFORM),
+  "_runtime": const LibraryInfo(
+      "_internal/js_runtime/lib/ddc_runtime/runtime.dart",
+      category: "",
+      documented: false,
+      platforms: DART2JS_PLATFORM),
+};
+
+/**
+ * Information about a "dart:" library.
+ */
+class LibraryInfo {
+  /**
+   * Path to the library's *.dart file relative to this file.
+   */
+  final String path;
+
+  /**
+   * The categories in which the library can be used encoded as a
+   * comma-separated String.
+   */
+  final String _categories;
+
+  /**
+   * Path to the dart2js library's *.dart file relative to this file
+   * or null if dart2js uses the common library path defined above.
+   * Access using the [#getDart2JsPath()] method.
+   */
+  final String dart2jsPath;
+
+  /**
+   * Path to the dart2js library's patch file relative to this file
+   * or null if no dart2js patch file associated with this library.
+   * Access using the [#getDart2JsPatchPath()] method.
+   */
+  final String dart2jsPatchPath;
+
+  /**
+   * True if this library is documented and should be shown to the user.
+   */
+  final bool documented;
+
+  /**
+   * Bit flags indicating which platforms consume this library.
+   * See [DART2JS_LIBRARY] and [VM_LIBRARY].
+   */
+  final int platforms;
+
+  /**
+   * True if the library contains implementation details for another library.
+   * The implication is that these libraries are less commonly used
+   * and that tools like Dart Editor should not show these libraries
+   * in a list of all libraries unless the user specifically asks the tool to
+   * do so.
+   */
+  final bool implementation;
+
+  /**
+   * States the current maturity of this library.
+   */
+  final Maturity maturity;
+
+  const LibraryInfo(this.path,
+      {String categories: "",
+      this.dart2jsPath,
+      this.dart2jsPatchPath,
+      this.implementation: false,
+      this.documented: true,
+      this.maturity: Maturity.UNSPECIFIED,
+      this.platforms: DART2JS_PLATFORM | VM_PLATFORM})
+      : _categories = categories;
+
+  bool get isDart2jsLibrary => (platforms & DART2JS_PLATFORM) != 0;
+  bool get isVmLibrary => (platforms & VM_PLATFORM) != 0;
+
+  /**
+   * The categories in which the library can be used.
+   *
+   * If no categories are specified, the library is internal and can not be
+   * loaded by user code.
+   */
+  List<Category> get categories {
+    // `"".split(,)` returns [""] not [], so we handle that case separately.
+    if (_categories == "") return const <Category>[];
+    return _categories.split(",").map(parseCategory).toList();
+  }
+
+  bool get isInternal => categories.isEmpty;
+
+  /// The original "categories" String that was passed to the constructor.
+  ///
+  /// Can be used to construct a slightly modified copy of this LibraryInfo.
+  String get categoriesString {
+    return _categories;
+  }
+}
+
+/**
+ * Abstraction to capture the maturity of a library.
+ */
+class Maturity {
+  final int level;
+  final String name;
+  final String description;
+
+  const Maturity(this.level, this.name, this.description);
+
+  String toString() => "$name: $level\n$description\n";
+
+  static const Maturity DEPRECATED = const Maturity(0, "Deprecated",
+      "This library will be remove before next major release.");
+
+  static const Maturity EXPERIMENTAL = const Maturity(
+      1,
+      "Experimental",
+      "This library is experimental and will likely change or be removed\n"
+          "in future versions.");
+
+  static const Maturity UNSTABLE = const Maturity(
+      2,
+      "Unstable",
+      "This library is in still changing and have not yet endured\n"
+          "sufficient real-world testing.\n"
+          "Backwards-compatibility is NOT guaranteed.");
+
+  static const Maturity WEB_STABLE = const Maturity(
+      3,
+      "Web Stable",
+      "This library is tracking the DOM evolution as defined by WC3.\n"
+          "Backwards-compatibility is NOT guaranteed.");
+
+  static const Maturity STABLE = const Maturity(
+      4,
+      "Stable",
+      "The library is stable. API backwards-compatibility is guaranteed.\n"
+          "However implementation details might change.");
+
+  static const Maturity LOCKED = const Maturity(5, "Locked",
+      "This library will not change except when serious bugs are encountered.");
+
+  static const Maturity UNSPECIFIED = const Maturity(-1, "Unspecified",
+      "The maturity for this library has not been specified.");
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart
rename to sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/cli_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/cli_patch.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/patch/cli_patch.dart
rename to sdk/lib/_internal/js_dev_runtime/patch/cli_patch.dart
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart
new file mode 100644
index 0000000..d0bbcd8
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart
@@ -0,0 +1,602 @@
+// 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.
+
+// Patch file for dart:collection classes.
+import 'dart:_foreign_helper' show JS, JSExportName;
+import 'dart:_runtime' as dart;
+import 'dart:_interceptors' show JSArray;
+import 'dart:_js_helper'
+    show
+        NoInline,
+        NoSideEffects,
+        NoThrows,
+        patch,
+        LinkedMap,
+        IdentityMap,
+        CustomHashMap,
+        CustomKeyHashMap,
+        DartIterator,
+        notNull,
+        putLinkedMapKey;
+
+@patch
+class HashMap<K, V> {
+  @patch
+  factory HashMap(
+      {bool equals(K key1, K key2),
+      int hashCode(K key),
+      bool isValidKey(Object potentialKey)}) {
+    if (isValidKey == null) {
+      if (hashCode == null) {
+        if (equals == null) {
+          if (identical(K, String) || identical(K, int)) {
+            return IdentityMap<K, V>();
+          }
+          return LinkedMap<K, V>();
+        }
+        hashCode = dart.hashCode;
+      } else if (identical(identityHashCode, hashCode) &&
+          identical(identical, equals)) {
+        return IdentityMap<K, V>();
+      }
+      return CustomHashMap<K, V>(equals ?? dart.equals, hashCode);
+    }
+    return CustomKeyHashMap<K, V>(
+        equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey);
+  }
+
+  @patch
+  factory HashMap.identity() = IdentityMap<K, V>;
+}
+
+@patch
+class LinkedHashMap<K, V> {
+  @patch
+  factory LinkedHashMap(
+      {bool equals(K key1, K key2),
+      int hashCode(K key),
+      bool isValidKey(Object potentialKey)}) {
+    if (isValidKey == null) {
+      if (hashCode == null) {
+        if (equals == null) {
+          if (identical(K, String) || identical(K, int)) {
+            return IdentityMap<K, V>();
+          }
+          return LinkedMap<K, V>();
+        }
+        hashCode = dart.hashCode;
+      } else if (identical(identityHashCode, hashCode) &&
+          identical(identical, equals)) {
+        return IdentityMap<K, V>();
+      }
+      return CustomHashMap<K, V>(equals ?? dart.equals, hashCode);
+    }
+    return CustomKeyHashMap<K, V>(
+        equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey);
+  }
+
+  @patch
+  factory LinkedHashMap.identity() = IdentityMap<K, V>;
+}
+
+@patch
+class HashSet<E> {
+  @patch
+  factory HashSet(
+      {bool equals(E e1, E e2),
+      int hashCode(E e),
+      bool isValidKey(Object potentialKey)}) {
+    if (isValidKey == null) {
+      if (hashCode == null) {
+        if (equals == null) {
+          if (identical(E, String) || identical(E, int)) {
+            return _IdentityHashSet<E>();
+          }
+          return _HashSet<E>();
+        }
+        hashCode = dart.hashCode;
+      } else if (identical(identityHashCode, hashCode) &&
+          identical(identical, equals)) {
+        return _IdentityHashSet<E>();
+      }
+      return _CustomHashSet<E>(
+          equals ?? dart.equals, hashCode ?? dart.hashCode);
+    }
+    return _CustomKeyHashSet<E>(
+        equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey);
+  }
+
+  @patch
+  factory HashSet.identity() = _IdentityHashSet<E>;
+}
+
+@patch
+class LinkedHashSet<E> {
+  @patch
+  factory LinkedHashSet(
+      {bool equals(E e1, E e2),
+      int hashCode(E e),
+      bool isValidKey(Object potentialKey)}) {
+    if (isValidKey == null) {
+      if (hashCode == null) {
+        if (equals == null) {
+          if (identical(E, String) || identical(E, int)) {
+            return _IdentityHashSet<E>();
+          }
+          return _HashSet<E>();
+        }
+        hashCode = dart.hashCode;
+      } else if (identical(identityHashCode, hashCode) &&
+          identical(identical, equals)) {
+        return _IdentityHashSet<E>();
+      }
+      return _CustomHashSet<E>(
+          equals ?? dart.equals, hashCode ?? dart.hashCode);
+    }
+    return _CustomKeyHashSet<E>(
+        equals ?? dart.equals, hashCode ?? dart.hashCode, isValidKey);
+  }
+
+  @patch
+  factory LinkedHashSet.identity() = _IdentityHashSet<E>;
+}
+
+class _HashSet<E> extends _InternalSet<E>
+    implements HashSet<E>, LinkedHashSet<E> {
+  /// The backing store for this set.
+  ///
+  /// Keys that use identity equality are stored directly. For other types of
+  /// keys, we first look them up (by hashCode) in the [_keyMap] map, then
+  /// we lookup the key in this map.
+  @notNull
+  final _map = JS('', 'new Set()');
+
+  /// Items that use custom equality semantics.
+  ///
+  /// This maps from the item's hashCode to the canonical key, which is then
+  /// used to lookup the item in [_map]. Keeping the data in our primary backing
+  /// map gives us the ordering semantics requred by [LinkedHashMap], while
+  /// also providing convenient access to keys/values.
+  @notNull
+  final _keyMap = JS('', 'new Map()');
+
+  // We track the number of modifications done to the key set of the
+  // hash map to be able to throw when the map is modified while being
+  // iterated over.
+  //
+  // Value cycles after 2^30 modifications so that modification counts are
+  // always unboxed (Smi) values. Modification detection will be missed if you
+  // make exactly some multiple of 2^30 modifications between advances of an
+  // iterator.
+  @notNull
+  int _modifications = 0;
+
+  _HashSet();
+
+  Set<E> _newSet() => _HashSet<E>();
+
+  Set<R> _newSimilarSet<R>() => _HashSet<R>();
+
+  bool contains(Object key) {
+    if (key == null) {
+      key = null;
+    } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
+        dart.identityEquals)) {
+      @notNull
+      var k = key;
+      var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, k.hashCode);
+      if (buckets != null) {
+        for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
+          k = JS('', '#[#]', buckets, i);
+          if (k == key) return true;
+        }
+      }
+      return false;
+    }
+    return JS('bool', '#.has(#)', _map, key);
+  }
+
+  E lookup(Object key) {
+    if (key == null) return null;
+    if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
+        dart.identityEquals)) {
+      @notNull
+      var k = key;
+      var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, k.hashCode);
+      if (buckets != null) {
+        for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
+          k = JS('', '#[#]', buckets, i);
+          if (k == key) return JS('', '#', k);
+        }
+      }
+      return null;
+    }
+    return JS('', '#.has(#) ? # : null', _map, key, key);
+  }
+
+  bool add(E key) {
+    var map = _map;
+    if (key == null) {
+      if (JS('', '#.has(null)', map)) return false;
+      key = null;
+    } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
+        dart.identityEquals)) {
+      var keyMap = _keyMap;
+      @notNull
+      var k = key;
+      int hash = JS('!', '# & 0x3ffffff', k.hashCode);
+      var buckets = JS('', '#.get(#)', keyMap, hash);
+      if (buckets == null) {
+        JS('', '#.set(#, [#])', keyMap, hash, key);
+      } else {
+        for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
+          k = JS('', '#[#]', buckets, i);
+          if (k == key) return false;
+        }
+        JS('', '#.push(#)', buckets, key);
+      }
+    } else if (JS('', '#.has(#)', map, key)) {
+      return false;
+    }
+    JS('', '#.add(#)', map, key);
+    _modifications = (_modifications + 1) & 0x3ffffff;
+    return true;
+  }
+
+  void addAll(Iterable<E> objects) {
+    var map = _map;
+    int length = JS('', '#.size', map);
+    for (E key in objects) {
+      if (key == null) {
+        key = null; // converts undefined to null, if needed.
+      } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
+          dart.identityEquals)) {
+        key = putLinkedMapKey(key, _keyMap);
+      }
+      JS('', '#.add(#)', map, key);
+    }
+    if (length != JS<int>('!', '#.size', map)) {
+      _modifications = (_modifications + 1) & 0x3ffffff;
+    }
+  }
+
+  bool remove(Object key) {
+    if (key == null) {
+      key = null;
+    } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
+        dart.identityEquals)) {
+      @notNull
+      var k = key;
+      int hash = JS('!', '# & 0x3ffffff', k.hashCode);
+      var buckets = JS('', '#.get(#)', _keyMap, hash);
+      if (buckets == null) return false; // not found
+      for (int i = 0, n = JS('!', '#.length', buckets);;) {
+        k = JS('', '#[#]', buckets, i);
+        if (k == key) {
+          key = k;
+          if (n == 1) {
+            JS('', '#.delete(#)', _keyMap, hash);
+          } else {
+            JS('', '#.splice(#, 1)', buckets, i);
+          }
+          break;
+        }
+        if (++i >= n) return false; // not found
+      }
+    }
+    var map = _map;
+    if (JS('bool', '#.delete(#)', map, key)) {
+      _modifications = (_modifications + 1) & 0x3ffffff;
+      return true;
+    }
+    return false;
+  }
+
+  void clear() {
+    var map = _map;
+    if (JS<int>('!', '#.size', map) > 0) {
+      JS('', '#.clear()', map);
+      JS('', '#.clear()', _keyMap);
+      _modifications = (_modifications + 1) & 0x3ffffff;
+    }
+  }
+}
+
+// Used for DDC const sets.
+class _ImmutableSet<E> extends _HashSet<E> {
+  _ImmutableSet.from(JSArray entries) {
+    var map = _map;
+    for (Object key in entries) {
+      if (key == null) {
+        key = null; // converts undefined to null, if needed.
+      } else if (JS('bool', '#[#] !== #', key, dart.extensionSymbol('_equals'),
+          dart.identityEquals)) {
+        key = putLinkedMapKey(key, _keyMap);
+      }
+      JS('', '#.add(#)', map, key);
+    }
+  }
+
+  bool add(Object other) => throw _unsupported();
+  void addAll(Object other) => throw _unsupported();
+  void clear() => throw _unsupported();
+  bool remove(Object key) => throw _unsupported();
+
+  static Error _unsupported() =>
+      UnsupportedError("Cannot modify unmodifiable set");
+}
+
+class _IdentityHashSet<E> extends _InternalSet<E>
+    implements HashSet<E>, LinkedHashSet<E> {
+  /// The backing store for this set.
+  @notNull
+  final _map = JS('', 'new Set()');
+
+  @notNull
+  int _modifications = 0;
+
+  _IdentityHashSet();
+
+  Set<E> _newSet() => _IdentityHashSet<E>();
+
+  Set<R> _newSimilarSet<R>() => _IdentityHashSet<R>();
+
+  bool contains(Object element) {
+    return JS('', '#.has(#)', _map, element);
+  }
+
+  E lookup(Object element) {
+    return JS('', '#.has(#)', _map, element) ? element : null;
+  }
+
+  bool add(E element) {
+    var map = _map;
+    if (JS('bool', '#.has(#)', map, element)) return false;
+    JS('', '#.add(#)', map, element);
+    _modifications = (_modifications + 1) & 0x3ffffff;
+    return true;
+  }
+
+  void addAll(Iterable<E> objects) {
+    var map = _map;
+    int length = JS('', '#.size', map);
+    for (E key in objects) {
+      JS('', '#.add(#)', map, key);
+    }
+    if (length != JS<int>('!', '#.size', map)) {
+      _modifications = (_modifications + 1) & 0x3ffffff;
+    }
+  }
+
+  bool remove(Object element) {
+    if (JS('bool', '#.delete(#)', _map, element)) {
+      _modifications = (_modifications + 1) & 0x3ffffff;
+      return true;
+    }
+    return false;
+  }
+
+  void clear() {
+    var map = _map;
+    if (JS<int>('!', '#.size', map) > 0) {
+      JS('', '#.clear()', map);
+      _modifications = (_modifications + 1) & 0x3ffffff;
+    }
+  }
+}
+
+class _CustomKeyHashSet<E> extends _CustomHashSet<E> {
+  _Predicate<Object> _validKey;
+  _CustomKeyHashSet(_Equality<E> equals, _Hasher<E> hashCode, this._validKey)
+      : super(equals, hashCode);
+
+  Set<E> _newSet() => _CustomKeyHashSet<E>(_equals, _hashCode, _validKey);
+
+  Set<R> _newSimilarSet<R>() => _HashSet<R>();
+
+  bool contains(Object element) {
+    // TODO(jmesserly): there is a subtle difference here compared to Dart 1.
+    // See the comment on CustomKeyHashMap.containsKey for more information.
+    // Treatment of `null` is different due to strong mode's requirement to
+    // perform an `element is E` check before calling equals/hashCode.
+    if (!_validKey(element)) return false;
+    return super.contains(element);
+  }
+
+  E lookup(Object element) {
+    if (!_validKey(element)) return null;
+    return super.lookup(element);
+  }
+
+  bool remove(Object element) {
+    if (!_validKey(element)) return false;
+    return super.remove(element);
+  }
+}
+
+class _CustomHashSet<E> extends _InternalSet<E>
+    implements HashSet<E>, LinkedHashSet<E> {
+  _Equality<E> _equals;
+  _Hasher<E> _hashCode;
+
+  // We track the number of modifications done to the key set of the
+  // hash map to be able to throw when the map is modified while being
+  // iterated over.
+  //
+  // Value cycles after 2^30 modifications so that modification counts are
+  // always unboxed (Smi) values. Modification detection will be missed if you
+  // make exactly some multiple of 2^30 modifications between advances of an
+  // iterator.
+  @notNull
+  int _modifications = 0;
+
+  /// The backing store for this set, used to handle ordering.
+  // TODO(jmesserly): a non-linked custom hash set could skip this.
+  @notNull
+  final _map = JS('', 'new Set()');
+
+  /// Our map used to map keys onto the canonical key that is stored in [_map].
+  @notNull
+  final _keyMap = JS('', 'new Map()');
+
+  _CustomHashSet(this._equals, this._hashCode);
+
+  Set<E> _newSet() => _CustomHashSet<E>(_equals, _hashCode);
+  Set<R> _newSimilarSet<R>() => _HashSet<R>();
+
+  bool contains(Object key) {
+    if (key is E) {
+      var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, _hashCode(key));
+      if (buckets != null) {
+        var equals = _equals;
+        for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
+          E k = JS('', '#[#]', buckets, i);
+          if (equals(k, key)) return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  E lookup(Object key) {
+    if (key is E) {
+      var buckets = JS('', '#.get(# & 0x3ffffff)', _keyMap, _hashCode(key));
+      if (buckets != null) {
+        var equals = _equals;
+        for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
+          E k = JS('', '#[#]', buckets, i);
+          if (equals(k, key)) return k;
+        }
+      }
+    }
+    return null;
+  }
+
+  bool add(E key) {
+    var keyMap = _keyMap;
+    var hash = JS<int>('!', '# & 0x3ffffff', _hashCode(key));
+    var buckets = JS('', '#.get(#)', keyMap, hash);
+    if (buckets == null) {
+      JS('', '#.set(#, [#])', keyMap, hash, key);
+    } else {
+      var equals = _equals;
+      for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
+        E k = JS('', '#[#]', buckets, i);
+        if (equals(k, key)) return false;
+      }
+      JS('', '#.push(#)', buckets, key);
+    }
+    JS('', '#.add(#)', _map, key);
+    _modifications = (_modifications + 1) & 0x3ffffff;
+    return true;
+  }
+
+  void addAll(Iterable<E> objects) {
+    // TODO(jmesserly): it'd be nice to skip the covariance check here.
+    for (E element in objects) add(element);
+  }
+
+  bool remove(Object key) {
+    if (key is E) {
+      var hash = JS<int>('!', '# & 0x3ffffff', _hashCode(key));
+      var keyMap = _keyMap;
+      var buckets = JS('', '#.get(#)', keyMap, hash);
+      if (buckets == null) return false; // not found
+      var equals = _equals;
+      for (int i = 0, n = JS('!', '#.length', buckets); i < n; i++) {
+        E k = JS('', '#[#]', buckets, i);
+        if (equals(k, key)) {
+          if (n == 1) {
+            JS('', '#.delete(#)', keyMap, hash);
+          } else {
+            JS('', '#.splice(#, 1)', buckets, i);
+          }
+          JS('', '#.delete(#)', _map, k);
+          _modifications = (_modifications + 1) & 0x3ffffff;
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  void clear() {
+    var map = _map;
+    if (JS<int>('!', '#.size', map) > 0) {
+      JS('', '#.clear()', map);
+      JS('', '#.clear()', _keyMap);
+      _modifications = (_modifications + 1) & 0x3ffffff;
+    }
+  }
+}
+
+/// Base class for our internal [LinkedHashSet]/[HashSet] implementations.
+///
+/// This implements the common functionality.
+abstract class _InternalSet<E> extends _SetBase<E> {
+  @notNull
+  get _map;
+
+  @notNull
+  int get _modifications;
+
+  @notNull
+  int get length => JS<int>('!', '#.size', _map);
+
+  @notNull
+  bool get isEmpty => JS('bool', '#.size == 0', _map);
+
+  @notNull
+  bool get isNotEmpty => JS('bool', '#.size != 0', _map);
+
+  Iterator<E> get iterator => DartIterator<E>(_jsIterator());
+
+  @JSExportName('Symbol.iterator')
+  _jsIterator() {
+    var self = this;
+    var iterator = JS('', '#.values()', self._map);
+    int modifications = self._modifications;
+    return JS(
+        '',
+        '''{
+      next() {
+        if (# != #) {
+          throw #;
+        }
+        return #.next();
+      }
+    }''',
+        modifications,
+        self._modifications,
+        ConcurrentModificationError(self),
+        iterator);
+  }
+}
+
+@patch
+abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
+  @patch
+  Node _splayMin(Node node) {
+    Node current = node;
+    while (current.left != null) {
+      Node left = current.left;
+      current.left = left.right;
+      left.right = current;
+      current = left;
+    }
+    return current;
+  }
+
+  @patch
+  Node _splayMax(Node node) {
+    Node current = node;
+    while (current.right != null) {
+      Node right = current.right;
+      current.right = right.left;
+      right.left = current;
+      current = right;
+    }
+    return current;
+  }
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/convert_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/convert_patch.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/patch/convert_patch.dart
rename to sdk/lib/_internal/js_dev_runtime/patch/convert_patch.dart
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
new file mode 100644
index 0000000..1c742e1
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
@@ -0,0 +1,2910 @@
+// 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.
+
+// Patch file for dart:core classes.
+import "dart:_internal" as _symbol_dev;
+import 'dart:_interceptors';
+import 'dart:_js_helper'
+    show
+        patch,
+        checkInt,
+        getRuntimeType,
+        LinkedMap,
+        JSSyntaxRegExp,
+        NoInline,
+        notNull,
+        nullCheck,
+        Primitives,
+        PrivateSymbol,
+        quoteStringForRegExp,
+        undefined;
+import 'dart:_runtime' as dart;
+import 'dart:_foreign_helper' show JS;
+import 'dart:_native_typed_data' show NativeUint8List;
+import 'dart:collection' show UnmodifiableMapView;
+import 'dart:convert' show Encoding, utf8;
+import 'dart:typed_data' show Endian, Uint8List, Uint16List;
+
+String _symbolToString(Symbol symbol) => symbol is PrivateSymbol
+    ? PrivateSymbol.getName(symbol)
+    : _symbol_dev.Symbol.getName(symbol);
+
+@patch
+int identityHashCode(Object object) {
+  if (object == null) return 0;
+  // Note: this works for primitives because we define the `identityHashCode`
+  // for them to be equivalent to their computed hashCode function.
+  int hash = JS('int|Null', r'#[#]', object, dart.identityHashCode_);
+  if (hash == null) {
+    hash = JS('int', '(Math.random() * 0x3fffffff) | 0');
+    JS('void', r'#[#] = #', object, dart.identityHashCode_, hash);
+  }
+  return JS('int', '#', hash);
+}
+
+// Patch for Object implementation.
+@patch
+class Object {
+  @patch
+  bool operator ==(other) => identical(this, other);
+
+  @patch
+  int get hashCode => identityHashCode(this);
+
+  @patch
+  String toString() =>
+      "Instance of '${dart.typeName(dart.getReifiedType(this))}'";
+
+  @patch
+  noSuchMethod(Invocation invocation) {
+    return dart.defaultNoSuchMethod(this, invocation);
+  }
+
+  @patch
+  Type get runtimeType => dart.wrapType(dart.getReifiedType(this));
+}
+
+@patch
+class Null {
+  @patch
+  int get hashCode => super.hashCode;
+}
+
+// Patch for Function implementation.
+@patch
+class Function {
+  @patch
+  static apply(Function f, List positionalArguments,
+      [Map<Symbol, dynamic> namedArguments]) {
+    positionalArguments ??= [];
+    // dcall expects the namedArguments as a JS map in the last slot.
+    if (namedArguments != null && namedArguments.isNotEmpty) {
+      var map = JS('', '{}');
+      namedArguments.forEach((symbol, arg) {
+        JS('', '#[#] = #', map, _symbolToString(symbol), arg);
+      });
+      return dart.dcall(f, positionalArguments, map);
+    }
+    return dart.dcall(f, positionalArguments);
+  }
+
+  static Map<String, dynamic> _toMangledNames(
+      Map<Symbol, dynamic> namedArguments) {
+    Map<String, dynamic> result = {};
+    namedArguments.forEach((symbol, value) {
+      result[_symbolToString(symbol)] = value;
+    });
+    return result;
+  }
+}
+
+// TODO(jmesserly): switch to WeakMap
+// Patch for Expando implementation.
+@patch
+class Expando<T> {
+  @patch
+  Expando([String name]) : this.name = name;
+
+  @patch
+  T operator [](Object object) {
+    var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME);
+    return (values == null) ? null : Primitives.getProperty(values, _getKey());
+  }
+
+  @patch
+  void operator []=(Object object, T value) {
+    var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME);
+    if (values == null) {
+      values = Object();
+      Primitives.setProperty(object, _EXPANDO_PROPERTY_NAME, values);
+    }
+    Primitives.setProperty(values, _getKey(), value);
+  }
+
+  String _getKey() {
+    String key = Primitives.getProperty(this, _KEY_PROPERTY_NAME);
+    if (key == null) {
+      key = "expando\$key\$${_keyCount++}";
+      Primitives.setProperty(this, _KEY_PROPERTY_NAME, key);
+    }
+    return key;
+  }
+
+  static const String _KEY_PROPERTY_NAME = 'expando\$key';
+  static const String _EXPANDO_PROPERTY_NAME = 'expando\$values';
+  static int _keyCount = 0;
+}
+
+Null _kNull(_) => null;
+
+@patch
+class int {
+  @patch
+  static int parse(String source,
+      {int radix, @deprecated int onError(String source)}) {
+    return Primitives.parseInt(source, radix, onError);
+  }
+
+  @patch
+  static int tryParse(String source, {int radix}) {
+    return Primitives.parseInt(source, radix, _kNull);
+  }
+
+  @patch
+  factory int.fromEnvironment(String name, {int defaultValue}) {
+    // ignore: const_constructor_throws_exception
+    throw UnsupportedError(
+        'int.fromEnvironment can only be used as a const constructor');
+  }
+}
+
+@patch
+class double {
+  @patch
+  static double parse(String source,
+      [@deprecated double onError(String source)]) {
+    return Primitives.parseDouble(source, onError);
+  }
+
+  @patch
+  static double tryParse(String source) {
+    return Primitives.parseDouble(source, _kNull);
+  }
+}
+
+@patch
+class BigInt implements Comparable<BigInt> {
+  @patch
+  static BigInt get zero => _BigIntImpl.zero;
+  @patch
+  static BigInt get one => _BigIntImpl.one;
+  @patch
+  static BigInt get two => _BigIntImpl.two;
+
+  @patch
+  static BigInt parse(String source, {int radix}) =>
+      _BigIntImpl.parse(source, radix: radix);
+
+  @patch
+  static BigInt tryParse(String source, {int radix}) =>
+      _BigIntImpl._tryParse(source, radix: radix);
+
+  @patch
+  factory BigInt.from(num value) = _BigIntImpl.from;
+}
+
+@patch
+class Error {
+  @patch
+  static String _objectToString(Object object) {
+    return "Instance of '${dart.typeName(dart.getReifiedType(object))}'";
+  }
+
+  @patch
+  static String _stringToSafeString(String string) {
+    return JS("String", "JSON.stringify(#)", string);
+  }
+
+  @patch
+  StackTrace get stackTrace => dart.stackTraceForError(this);
+}
+
+@patch
+class FallThroughError {
+  @patch
+  FallThroughError._create(String url, int line);
+
+  @patch
+  String toString() => super.toString();
+}
+
+@patch
+class AbstractClassInstantiationError {
+  @patch
+  String toString() => "Cannot instantiate abstract class: '$_className'";
+}
+
+// Patch for DateTime implementation.
+@patch
+class DateTime {
+  @patch
+  DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
+      {bool isUtc = false})
+      : this._withValue(millisecondsSinceEpoch, isUtc: isUtc);
+
+  @patch
+  DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
+      {bool isUtc = false})
+      : this._withValue(
+            _microsecondInRoundedMilliseconds(microsecondsSinceEpoch),
+            isUtc: isUtc);
+
+  @patch
+  DateTime._internal(int year, int month, int day, int hour, int minute,
+      int second, int millisecond, int microsecond, bool isUtc)
+      // checkBool is manually inlined here because dart2js doesn't inline it
+      // and [isUtc] is usually a constant.
+      : this.isUtc =
+            isUtc is bool ? isUtc : throw ArgumentError.value(isUtc, 'isUtc'),
+        _value = checkInt(Primitives.valueFromDecomposedDate(
+            year,
+            month,
+            day,
+            hour,
+            minute,
+            second,
+            millisecond + _microsecondInRoundedMilliseconds(microsecond),
+            isUtc));
+
+  @patch
+  DateTime._now()
+      : isUtc = false,
+        _value = Primitives.dateNow();
+
+  /// Rounds the given [microsecond] to the nearest milliseconds value.
+  ///
+  /// For example, invoked with argument `2600` returns `3`.
+  static int _microsecondInRoundedMilliseconds(int microsecond) {
+    return (microsecond / 1000).round();
+  }
+
+  @patch
+  static int _brokenDownDateToValue(int year, int month, int day, int hour,
+      int minute, int second, int millisecond, int microsecond, bool isUtc) {
+    return Primitives.valueFromDecomposedDate(
+        year,
+        month,
+        day,
+        hour,
+        minute,
+        second,
+        millisecond + _microsecondInRoundedMilliseconds(microsecond),
+        isUtc);
+  }
+
+  @patch
+  String get timeZoneName {
+    if (isUtc) return "UTC";
+    return Primitives.getTimeZoneName(this);
+  }
+
+  @patch
+  Duration get timeZoneOffset {
+    if (isUtc) return Duration();
+    return Duration(minutes: Primitives.getTimeZoneOffsetInMinutes(this));
+  }
+
+  @patch
+  DateTime add(Duration duration) {
+    return DateTime._withValue(_value + duration.inMilliseconds, isUtc: isUtc);
+  }
+
+  @patch
+  DateTime subtract(Duration duration) {
+    return DateTime._withValue(_value - duration.inMilliseconds, isUtc: isUtc);
+  }
+
+  @patch
+  Duration difference(DateTime other) {
+    return Duration(milliseconds: _value - other._value);
+  }
+
+  @patch
+  int get millisecondsSinceEpoch => _value;
+
+  @patch
+  int get microsecondsSinceEpoch => _value * 1000;
+
+  @patch
+  int get year => Primitives.getYear(this);
+
+  @patch
+  int get month => Primitives.getMonth(this);
+
+  @patch
+  int get day => Primitives.getDay(this);
+
+  @patch
+  int get hour => Primitives.getHours(this);
+
+  @patch
+  int get minute => Primitives.getMinutes(this);
+
+  @patch
+  int get second => Primitives.getSeconds(this);
+
+  @patch
+  int get millisecond => Primitives.getMilliseconds(this);
+
+  @patch
+  int get microsecond => 0;
+
+  @patch
+  int get weekday => Primitives.getWeekday(this);
+
+  @patch
+  bool operator ==(dynamic other) =>
+      other is DateTime &&
+      _value == other.millisecondsSinceEpoch &&
+      isUtc == other.isUtc;
+
+  @patch
+  bool isBefore(DateTime other) => _value < other.millisecondsSinceEpoch;
+
+  @patch
+  bool isAfter(DateTime other) => _value > other.millisecondsSinceEpoch;
+
+  @patch
+  bool isAtSameMomentAs(DateTime other) =>
+      _value == other.millisecondsSinceEpoch;
+
+  @patch
+  int compareTo(DateTime other) =>
+      _value.compareTo(other.millisecondsSinceEpoch);
+}
+
+// Patch for Stopwatch implementation.
+@patch
+class Stopwatch {
+  @patch
+  static void _initTicker() {
+    Primitives.initTicker();
+    _frequency = Primitives.timerFrequency;
+  }
+
+  @patch
+  static int _now() => Primitives.timerTicks();
+
+  @patch
+  int get elapsedMicroseconds {
+    int ticks = elapsedTicks;
+    if (_frequency == 1000000) return ticks;
+    assert(_frequency == 1000);
+    return ticks * 1000;
+  }
+
+  @patch
+  int get elapsedMilliseconds {
+    int ticks = elapsedTicks;
+    if (_frequency == 1000) return ticks;
+    assert(_frequency == 1000000);
+    return ticks ~/ 1000;
+  }
+}
+
+// Patch for List implementation.
+@patch
+class List<E> {
+  @patch
+  factory List([@undefined int _length]) {
+    dynamic list;
+    if (JS('bool', '# === void 0', _length)) {
+      list = JS('', '[]');
+    } else {
+      int length = JS('!', '#', _length);
+      if (_length == null || length < 0) {
+        throw ArgumentError("Length must be a non-negative integer: $_length");
+      }
+      list = JS('', 'new Array(#)', length);
+      JS('', '#.fill(null)', list);
+      JSArray.markFixedList(list);
+    }
+    return JSArray<E>.of(list);
+  }
+
+  @patch
+  factory List.filled(@nullCheck int length, E fill, {bool growable = false}) {
+    var list = JSArray<E>.of(JS('', 'new Array(#)', length));
+    JS('', '#.fill(#)', list, fill);
+    if (!growable) JSArray.markFixedList(list);
+    return list;
+  }
+
+  @patch
+  factory List.from(Iterable elements, {bool growable = true}) {
+    var list = JSArray<E>.of(JS('', '[]'));
+    // Specialize the copy loop for the case that doesn't need a
+    // runtime check.
+    if (elements is Iterable<E>) {
+      for (var e in elements) {
+        list.add(e);
+      }
+    } else {
+      for (var e in elements) {
+        list.add(e as E);
+      }
+    }
+    if (!growable) JSArray.markFixedList(list);
+    return list;
+  }
+
+  @patch
+  factory List.unmodifiable(Iterable elements) {
+    var list = List<E>.from(elements);
+    JSArray.markUnmodifiableList(list);
+    return list;
+  }
+}
+
+@patch
+class Map<K, V> {
+  @patch
+  factory Map.unmodifiable(Map other) {
+    return UnmodifiableMapView<K, V>(Map<K, V>.from(other));
+  }
+
+  @patch
+  factory Map() = LinkedMap<K, V>;
+}
+
+@patch
+class String {
+  @patch
+  factory String.fromCharCodes(Iterable<int> charCodes,
+      [int start = 0, int end]) {
+    if (charCodes is JSArray) {
+      return _stringFromJSArray(charCodes, start, end);
+    }
+    if (charCodes is NativeUint8List) {
+      return _stringFromUint8List(charCodes, start, end);
+    }
+    return _stringFromIterable(charCodes, start, end);
+  }
+
+  @patch
+  factory String.fromCharCode(int charCode) {
+    return Primitives.stringFromCharCode(charCode);
+  }
+
+  @patch
+  factory String.fromEnvironment(String name, {String defaultValue}) {
+    // ignore: const_constructor_throws_exception
+    throw UnsupportedError(
+        'String.fromEnvironment can only be used as a const constructor');
+  }
+
+  static String _stringFromJSArray(
+      /*=JSArray<int>*/ list,
+      int start,
+      int endOrNull) {
+    int len = list.length;
+    int end = RangeError.checkValidRange(start, endOrNull, len);
+    if (start > 0 || end < len) {
+      list = list.sublist(start, end);
+    }
+    return Primitives.stringFromCharCodes(list);
+  }
+
+  static String _stringFromUint8List(
+      NativeUint8List charCodes, int start, int endOrNull) {
+    int len = charCodes.length;
+    int end = RangeError.checkValidRange(start, endOrNull, len);
+    return Primitives.stringFromNativeUint8List(charCodes, start, end);
+  }
+
+  static String _stringFromIterable(
+      Iterable<int> charCodes, int start, int end) {
+    if (start < 0) throw RangeError.range(start, 0, charCodes.length);
+    if (end != null && end < start) {
+      throw RangeError.range(end, start, charCodes.length);
+    }
+    var it = charCodes.iterator;
+    for (int i = 0; i < start; i++) {
+      if (!it.moveNext()) {
+        throw RangeError.range(start, 0, i);
+      }
+    }
+    var list = <int>[];
+    if (end == null) {
+      while (it.moveNext()) list.add(it.current);
+    } else {
+      for (int i = start; i < end; i++) {
+        if (!it.moveNext()) {
+          throw RangeError.range(end, start, i);
+        }
+        list.add(it.current);
+      }
+    }
+    return Primitives.stringFromCharCodes(list);
+  }
+}
+
+@patch
+class bool {
+  @patch
+  factory bool.fromEnvironment(String name, {bool defaultValue = false}) {
+    // ignore: const_constructor_throws_exception
+    throw UnsupportedError(
+        'bool.fromEnvironment can only be used as a const constructor');
+  }
+
+  @patch
+  int get hashCode => super.hashCode;
+}
+
+@patch
+class RegExp {
+  @patch
+  factory RegExp(String source,
+          {bool multiLine = false,
+          bool caseSensitive = true,
+          bool unicode = false,
+          bool dotAll = false}) =>
+      JSSyntaxRegExp(source,
+          multiLine: multiLine,
+          caseSensitive: caseSensitive,
+          unicode: unicode,
+          dotAll: dotAll);
+
+  @patch
+  static String escape(String text) => quoteStringForRegExp(text);
+}
+
+// Patch for 'identical' function.
+@patch
+bool identical(Object a, Object b) {
+  return JS('bool', '(# == null ? # == null : # === #)', a, b, a, b);
+}
+
+@patch
+class StringBuffer {
+  String _contents;
+
+  @patch
+  StringBuffer([Object content = ""]) : _contents = '$content';
+
+  @patch
+  int get length => _contents.length;
+
+  @patch
+  void write(Object obj) {
+    _writeString('$obj');
+  }
+
+  @patch
+  void writeCharCode(int charCode) {
+    _writeString(String.fromCharCode(charCode));
+  }
+
+  @patch
+  void writeAll(Iterable objects, [String separator = ""]) {
+    _contents = _writeAll(_contents, objects, separator);
+  }
+
+  @patch
+  void writeln([Object obj = ""]) {
+    _writeString('$obj\n');
+  }
+
+  @patch
+  void clear() {
+    _contents = "";
+  }
+
+  @patch
+  String toString() => Primitives.flattenString(_contents);
+
+  void _writeString(str) {
+    _contents = Primitives.stringConcatUnchecked(_contents, str);
+  }
+
+  static String _writeAll(String string, Iterable objects, String separator) {
+    Iterator iterator = objects.iterator;
+    if (!iterator.moveNext()) return string;
+    if (separator.isEmpty) {
+      do {
+        string = _writeOne(string, iterator.current);
+      } while (iterator.moveNext());
+    } else {
+      string = _writeOne(string, iterator.current);
+      while (iterator.moveNext()) {
+        string = _writeOne(string, separator);
+        string = _writeOne(string, iterator.current);
+      }
+    }
+    return string;
+  }
+
+  static String _writeOne(String string, Object obj) {
+    return Primitives.stringConcatUnchecked(string, '$obj');
+  }
+}
+
+// TODO(jmesserly): kernel expects to find this in our SDK.
+class _CompileTimeError extends Error {
+  final String _errorMsg;
+  _CompileTimeError(this._errorMsg);
+  String toString() => _errorMsg;
+}
+
+@patch
+class NoSuchMethodError {
+  final Object _receiver;
+  final Symbol _memberName;
+  final List _arguments;
+  final Map<Symbol, dynamic> _namedArguments;
+  final List _existingArgumentNames;
+  final Invocation _invocation;
+
+  @patch
+  NoSuchMethodError(Object receiver, Symbol memberName,
+      List positionalArguments, Map<Symbol, dynamic> namedArguments,
+      [List existingArgumentNames = null])
+      : _receiver = receiver,
+        _memberName = memberName,
+        _arguments = positionalArguments,
+        _namedArguments = namedArguments,
+        _existingArgumentNames = existingArgumentNames,
+        _invocation = null;
+
+  @patch
+  NoSuchMethodError.withInvocation(Object receiver, Invocation invocation)
+      : _receiver = receiver,
+        _memberName = invocation.memberName,
+        _arguments = invocation.positionalArguments,
+        _namedArguments = invocation.namedArguments,
+        _existingArgumentNames = null,
+        _invocation = invocation;
+
+  @patch
+  String toString() {
+    StringBuffer sb = StringBuffer('');
+    String comma = '';
+    if (_arguments != null) {
+      for (var argument in _arguments) {
+        sb.write(comma);
+        sb.write(Error.safeToString(argument));
+        comma = ', ';
+      }
+    }
+    if (_namedArguments != null) {
+      _namedArguments.forEach((Symbol key, var value) {
+        sb.write(comma);
+        sb.write(_symbolToString(key));
+        sb.write(": ");
+        sb.write(Error.safeToString(value));
+        comma = ', ';
+      });
+    }
+    String memberName = _symbolToString(_memberName);
+    String receiverText = Error.safeToString(_receiver);
+    String actualParameters = '$sb';
+    var failureMessage = (_invocation is dart.InvocationImpl)
+        ? (_invocation as dart.InvocationImpl).failureMessage
+        : 'method not found';
+    if (_existingArgumentNames == null) {
+      return "NoSuchMethodError: '$memberName'\n"
+          "$failureMessage\n"
+          "Receiver: ${receiverText}\n"
+          "Arguments: [$actualParameters]";
+    } else {
+      String formalParameters = _existingArgumentNames.join(', ');
+      return "NoSuchMethodError: incorrect number of arguments passed to "
+          "method named '$memberName'\n"
+          "Receiver: ${receiverText}\n"
+          "Tried calling: $memberName($actualParameters)\n"
+          "Found: $memberName($formalParameters)";
+    }
+  }
+}
+
+@patch
+class Uri {
+  @patch
+  static Uri get base {
+    String uri = Primitives.currentUri();
+    if (uri != null) return Uri.parse(uri);
+    throw UnsupportedError("'Uri.base' is not supported");
+  }
+}
+
+@patch
+class _Uri {
+  @patch
+  static bool get _isWindows => _isWindowsCached;
+
+  static final bool _isWindowsCached = JS(
+      'bool',
+      'typeof process != "undefined" && '
+          'Object.prototype.toString.call(process) == "[object process]" && '
+          'process.platform == "win32"');
+
+  // Matches a String that _uriEncodes to itself regardless of the kind of
+  // component.  This corresponds to [_unreservedTable], i.e. characters that
+  // are not encoded by any encoding table.
+  static final RegExp _needsNoEncoding = RegExp(r'^[\-\.0-9A-Z_a-z~]*$');
+
+  /**
+   * This is the internal implementation of JavaScript's encodeURI function.
+   * It encodes all characters in the string [text] except for those
+   * that appear in [canonicalTable], and returns the escaped string.
+   */
+  @patch
+  static String _uriEncode(List<int> canonicalTable, String text,
+      Encoding encoding, bool spaceToPlus) {
+    if (identical(encoding, utf8) && _needsNoEncoding.hasMatch(text)) {
+      return text;
+    }
+
+    // Encode the string into bytes then generate an ASCII only string
+    // by percent encoding selected bytes.
+    StringBuffer result = StringBuffer('');
+    var bytes = encoding.encode(text);
+    for (int i = 0; i < bytes.length; i++) {
+      int byte = bytes[i];
+      if (byte < 128 &&
+          ((canonicalTable[byte >> 4] & (1 << (byte & 0x0f))) != 0)) {
+        result.writeCharCode(byte);
+      } else if (spaceToPlus && byte == _SPACE) {
+        result.write('+');
+      } else {
+        const String hexDigits = '0123456789ABCDEF';
+        result.write('%');
+        result.write(hexDigits[(byte >> 4) & 0x0f]);
+        result.write(hexDigits[byte & 0x0f]);
+      }
+    }
+    return result.toString();
+  }
+}
+
+@patch
+class StackTrace {
+  @patch
+  @NoInline()
+  static StackTrace get current {
+    return dart.stackTrace(JS('', 'Error()'));
+  }
+}
+
+// TODO(jmesserly): this class is supposed to be obsolete in Strong Mode, but
+// the front-end crashes without it
+class _DuplicatedFieldInitializerError {
+  final String _name;
+
+  _DuplicatedFieldInitializerError(this._name);
+
+  toString() => "Error: field '$_name' is already initialized.";
+}
+
+// TODO(jmesserly): The rest of this core_patch.dart source should reside in an
+// included part file instead of being inlined. However, part files are not
+// properly supported here.
+
+// Copyright (c) 2017, 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 dart.core;
+
+int _max(int a, int b) => a > b ? a : b;
+int _min(int a, int b) => a < b ? a : b;
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+ * Copyright (c) 2003-2005  Tom Wu
+ * Copyright (c) 2012 Adam Singer (adam@solvr.io)
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following condition applies:
+ *
+ * All redistributions must retain an intact copy of this copyright notice
+ * and disclaimer.
+ */
+
+/**
+ * An implementation for the arbitrarily large integer.
+ *
+ * The integer number is represented by a sign, an array of 16-bit unsigned
+ * integers in little endian format, and a number of used digits in that array.
+ */
+class _BigIntImpl implements BigInt {
+  // Bits per digit.
+  static const int _digitBits = 16;
+  static const int _digitBase = 1 << _digitBits;
+  static const int _digitMask = (1 << _digitBits) - 1;
+
+  static final _BigIntImpl zero = _BigIntImpl._fromInt(0);
+  static final _BigIntImpl one = _BigIntImpl._fromInt(1);
+  static final _BigIntImpl two = _BigIntImpl._fromInt(2);
+
+  static final _BigIntImpl _minusOne = -one;
+  static final _BigIntImpl _bigInt10000 = _BigIntImpl._fromInt(10000);
+
+  // Result cache for last _divRem call.
+  // Result cache for last _divRem call.
+  static Uint16List _lastDividendDigits;
+  static int _lastDividendUsed;
+  static Uint16List _lastDivisorDigits;
+  static int _lastDivisorUsed;
+  static Uint16List _lastQuoRemDigits;
+  static int _lastQuoRemUsed;
+  static int _lastRemUsed;
+  static int _lastRem_nsh;
+
+  /// Whether this bigint is negative.
+  final bool _isNegative;
+
+  /// The unsigned digits of this bigint.
+  ///
+  /// The least significant digit is in slot 0.
+  /// The list may have more digits than needed. That is, `_digits.length` may
+  /// be strictly greater than `_used`.
+  final Uint16List _digits;
+
+  /// The number of used entries in [_digits].
+  ///
+  /// To avoid reallocating [Uint16List]s, lists that are too big are not
+  /// replaced.
+  final int _used;
+
+  /**
+   * Parses [source] as a, possibly signed, integer literal and returns its
+   * value.
+   *
+   * The [source] must be a non-empty sequence of base-[radix] digits,
+   * optionally prefixed with a minus or plus sign ('-' or '+').
+   *
+   * The [radix] must be in the range 2..36. The digits used are
+   * first the decimal digits 0..9, and then the letters 'a'..'z' with
+   * values 10 through 35. Also accepts upper-case letters with the same
+   * values as the lower-case ones.
+   *
+   * If no [radix] is given then it defaults to 10. In this case, the [source]
+   * digits may also start with `0x`, in which case the number is interpreted
+   * as a hexadecimal literal, which effectively means that the `0x` is ignored
+   * and the radix is instead set to 16.
+   *
+   * For any int `n` and radix `r`, it is guaranteed that
+   * `n == int.parse(n.toRadixString(r), radix: r)`.
+   *
+   * Throws a [FormatException] if the [source] is not a valid integer literal,
+   * optionally prefixed by a sign.
+   */
+  static _BigIntImpl parse(String source, {int radix}) {
+    var result = _tryParse(source, radix: radix);
+    if (result == null) {
+      throw FormatException("Could not parse BigInt", source);
+    }
+    return result;
+  }
+
+  /// Parses a decimal bigint literal.
+  ///
+  /// The [source] must not contain leading or trailing whitespace.
+  static _BigIntImpl _parseDecimal(String source, bool isNegative) {
+    const _0 = 48;
+
+    int part = 0;
+    _BigIntImpl result = zero;
+    // Read in the source 4 digits at a time.
+    // The first part may have a few leading virtual '0's to make the remaining
+    // parts all have exactly 4 digits.
+    int digitInPartCount = 4 - source.length.remainder(4);
+    if (digitInPartCount == 4) digitInPartCount = 0;
+    for (int i = 0; i < source.length; i++) {
+      part = part * 10 + source.codeUnitAt(i) - _0;
+      if (++digitInPartCount == 4) {
+        result = result * _bigInt10000 + _BigIntImpl._fromInt(part);
+        part = 0;
+        digitInPartCount = 0;
+      }
+    }
+    if (isNegative) return -result;
+    return result;
+  }
+
+  /// Returns the value of a given source digit.
+  ///
+  /// Source digits between "0" and "9" (inclusive) return their decimal value.
+  ///
+  /// Source digits between "a" and "z", or "A" and "Z" (inclusive) return
+  /// 10 + their position in the ASCII alphabet.
+  ///
+  /// The incoming [codeUnit] must be an ASCII code-unit.
+  static int _codeUnitToRadixValue(int codeUnit) {
+    // We know that the characters must be ASCII as otherwise the
+    // regexp wouldn't have matched. Lowercasing by doing `| 0x20` is thus
+    // guaranteed to be a safe operation, since it preserves digits
+    // and lower-cases ASCII letters.
+    const int _0 = 48;
+    const int _9 = 57;
+    const int _a = 97;
+    if (_0 <= codeUnit && codeUnit <= _9) return codeUnit - _0;
+    codeUnit |= 0x20;
+    var result = codeUnit - _a + 10;
+    return result;
+  }
+
+  /// Parses the given [source] string, starting at [startPos], as a hex
+  /// literal.
+  ///
+  /// If [isNegative] is true, negates the result before returning it.
+  ///
+  /// The [source] (substring) must be a valid hex literal.
+  static _BigIntImpl _parseHex(String source, int startPos, bool isNegative) {
+    int hexDigitsPerChunk = _digitBits ~/ 4;
+    int sourceLength = source.length - startPos;
+    int chunkCount = (sourceLength / hexDigitsPerChunk).ceil();
+    var digits = Uint16List(chunkCount);
+
+    int lastDigitLength = sourceLength - (chunkCount - 1) * hexDigitsPerChunk;
+    int digitIndex = digits.length - 1;
+    int i = startPos;
+    int chunk = 0;
+    for (int j = 0; j < lastDigitLength; j++) {
+      var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i++));
+      if (digitValue >= 16) return null;
+      chunk = chunk * 16 + digitValue;
+    }
+    digits[digitIndex--] = chunk;
+
+    while (i < source.length) {
+      chunk = 0;
+      for (int j = 0; j < hexDigitsPerChunk; j++) {
+        var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i++));
+        if (digitValue >= 16) return null;
+        chunk = chunk * 16 + digitValue;
+      }
+      digits[digitIndex--] = chunk;
+    }
+    if (digits.length == 1 && digits[0] == 0) return zero;
+    return _BigIntImpl._(isNegative, digits.length, digits);
+  }
+
+  /// Parses the given [source] as a [radix] literal.
+  ///
+  /// The [source] will be checked for invalid characters. If it is invalid,
+  /// this function returns `null`.
+  static _BigIntImpl _parseRadix(String source, int radix, bool isNegative) {
+    var result = zero;
+    var base = _BigIntImpl._fromInt(radix);
+    for (int i = 0; i < source.length; i++) {
+      var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i));
+      if (digitValue >= radix) return null;
+      result = result * base + _BigIntImpl._fromInt(digitValue);
+    }
+    if (isNegative) return -result;
+    return result;
+  }
+
+  /// Tries to parse the given [source] as a [radix] literal.
+  ///
+  /// Returns the parsed big integer, or `null` if it failed.
+  ///
+  /// If the [radix] is `null` accepts decimal literals or `0x` hex literals.
+  static _BigIntImpl _tryParse(String source, {int radix}) {
+    if (source == "") return null;
+
+    var re = RegExp(r'^\s*([+-]?)((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$',
+        caseSensitive: false);
+    var match = re.firstMatch(source);
+    int signIndex = 1;
+    int hexIndex = 3;
+    int decimalIndex = 4;
+    int nonDecimalHexIndex = 5;
+    if (match == null) return null;
+
+    bool isNegative = match[signIndex] == "-";
+
+    String decimalMatch = match[decimalIndex];
+    String hexMatch = match[hexIndex];
+    String nonDecimalMatch = match[nonDecimalHexIndex];
+
+    if (radix == null) {
+      if (decimalMatch != null) {
+        // Cannot fail because we know that the digits are all decimal.
+        return _parseDecimal(decimalMatch, isNegative);
+      }
+      if (hexMatch != null) {
+        // Cannot fail because we know that the digits are all hex.
+        return _parseHex(hexMatch, 2, isNegative);
+      }
+      return null;
+    }
+
+    if (radix is! int) {
+      throw ArgumentError.value(radix, 'radix', 'is not an integer');
+    }
+    if (radix < 2 || radix > 36) {
+      throw RangeError.range(radix, 2, 36, 'radix');
+    }
+    if (radix == 10 && decimalMatch != null) {
+      return _parseDecimal(decimalMatch, isNegative);
+    }
+    if (radix == 16 && (decimalMatch != null || nonDecimalMatch != null)) {
+      return _parseHex(decimalMatch ?? nonDecimalMatch, 0, isNegative);
+    }
+
+    return _parseRadix(
+        decimalMatch ?? nonDecimalMatch ?? hexMatch, radix, isNegative);
+  }
+
+  /// Finds the amount significant digits in the provided [digits] array.
+  static int _normalize(int used, Uint16List digits) {
+    while (used > 0 && digits[used - 1] == 0) used--;
+    return used;
+  }
+
+  /// Factory returning an instance initialized with the given field values.
+  /// If the [digits] array contains leading 0s, the [used] value is adjusted
+  /// accordingly. The [digits] array is not modified.
+  _BigIntImpl._(bool isNegative, int used, Uint16List digits)
+      : this._normalized(isNegative, _normalize(used, digits), digits);
+
+  _BigIntImpl._normalized(bool isNegative, this._used, this._digits)
+      : _isNegative = _used == 0 ? false : isNegative;
+
+  /// Whether this big integer is zero.
+  bool get _isZero => _used == 0;
+
+  /// Allocates an array of the given [length] and copies the [digits] in the
+  /// range [from] to [to-1], starting at index 0, followed by leading zero
+  /// digits.
+  static Uint16List _cloneDigits(
+      Uint16List digits, int from, int to, int length) {
+    var resultDigits = Uint16List(length);
+    var n = to - from;
+    for (var i = 0; i < n; i++) {
+      resultDigits[i] = digits[from + i];
+    }
+    return resultDigits;
+  }
+
+  /// Allocates a big integer from the provided [value] number.
+  factory _BigIntImpl.from(num value) {
+    if (value == 0) return zero;
+    if (value == 1) return one;
+    if (value == 2) return two;
+
+    // Given this order dart2js will use the `_fromInt` for smaller value and
+    // then use the bit-manipulating `_fromDouble` for all other values.
+    if (value.abs() < 0x100000000) return _BigIntImpl._fromInt(value.toInt());
+    if (value is double) return _BigIntImpl._fromDouble(value);
+    return _BigIntImpl._fromInt(value);
+  }
+
+  factory _BigIntImpl._fromInt(int value) {
+    bool isNegative = value < 0;
+    assert(_digitBits == 16);
+    if (isNegative) {
+      // Handle the min 64-bit value differently, since its negation is not
+      // positive.
+      const int minInt64 = -0x80000000 * 0x100000000;
+      if (value == minInt64) {
+        var digits = Uint16List(4);
+        digits[3] = 0x8000;
+        return _BigIntImpl._(true, 4, digits);
+      }
+      value = -value;
+    }
+    if (value < _digitBase) {
+      var digits = Uint16List(1);
+      digits[0] = value;
+      return _BigIntImpl._(isNegative, 1, digits);
+    }
+    if (value <= 0xFFFFFFFF) {
+      var digits = Uint16List(2);
+      digits[0] = value & _digitMask;
+      digits[1] = value >> _digitBits;
+      return _BigIntImpl._(isNegative, 2, digits);
+    }
+
+    var bits = value.bitLength;
+    var digits = Uint16List((bits - 1) ~/ _digitBits + 1);
+    var i = 0;
+    while (value != 0) {
+      digits[i++] = value & _digitMask;
+      value = value ~/ _digitBase;
+    }
+    return _BigIntImpl._(isNegative, digits.length, digits);
+  }
+
+  /// An 8-byte Uint8List we can reuse for [_fromDouble] to avoid generating
+  /// garbage.
+  static final Uint8List _bitsForFromDouble = Uint8List(8);
+
+  factory _BigIntImpl._fromDouble(double value) {
+    const int exponentBias = 1075;
+
+    if (value.isNaN || value.isInfinite) {
+      throw ArgumentError("Value must be finite: $value");
+    }
+    bool isNegative = value < 0;
+    if (isNegative) value = -value;
+
+    value = value.floorToDouble();
+    if (value == 0) return zero;
+
+    var bits = _bitsForFromDouble;
+    for (int i = 0; i < 8; i++) {
+      bits[i] = 0;
+    }
+    bits.buffer.asByteData().setFloat64(0, value, Endian.little);
+    // The exponent is in bits 53..63.
+    var biasedExponent = (bits[7] << 4) + (bits[6] >> 4);
+    var exponent = biasedExponent - exponentBias;
+
+    assert(_digitBits == 16);
+    // The significant bits are in 0 .. 52.
+    var unshiftedDigits = Uint16List(4);
+    unshiftedDigits[0] = (bits[1] << 8) + bits[0];
+    unshiftedDigits[1] = (bits[3] << 8) + bits[2];
+    unshiftedDigits[2] = (bits[5] << 8) + bits[4];
+    // Don't forget to add the hidden bit.
+    unshiftedDigits[3] = 0x10 | (bits[6] & 0xF);
+
+    var unshiftedBig = _BigIntImpl._normalized(false, 4, unshiftedDigits);
+    _BigIntImpl absResult = unshiftedBig;
+    if (exponent < 0) {
+      absResult = unshiftedBig >> -exponent;
+    } else if (exponent > 0) {
+      absResult = unshiftedBig << exponent;
+    }
+    if (isNegative) return -absResult;
+    return absResult;
+  }
+
+  /**
+   * Return the negative value of this integer.
+   *
+   * The result of negating an integer always has the opposite sign, except
+   * for zero, which is its own negation.
+   */
+  _BigIntImpl operator -() {
+    if (_used == 0) return this;
+    return _BigIntImpl._(!_isNegative, _used, _digits);
+  }
+
+  /**
+   * Returns the absolute value of this integer.
+   *
+   * For any integer `x`, the result is the same as `x < 0 ? -x : x`.
+   */
+  _BigIntImpl abs() => _isNegative ? -this : this;
+
+  /// Returns this << n *_DIGIT_BITS.
+  _BigIntImpl _dlShift(int n) {
+    final used = _used;
+    if (used == 0) {
+      return zero;
+    }
+    final resultUsed = used + n;
+    final digits = _digits;
+    final resultDigits = Uint16List(resultUsed);
+    for (int i = used - 1; i >= 0; i--) {
+      resultDigits[i + n] = digits[i];
+    }
+    return _BigIntImpl._(_isNegative, resultUsed, resultDigits);
+  }
+
+  /// Same as [_dlShift] but works on the decomposed big integers.
+  ///
+  /// Returns `resultUsed`.
+  ///
+  /// `resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n*_DIGIT_BITS`.
+  static int _dlShiftDigits(
+      Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+    if (xUsed == 0) {
+      return 0;
+    }
+    if (n == 0 && identical(resultDigits, xDigits)) {
+      return xUsed;
+    }
+    final resultUsed = xUsed + n;
+    for (int i = xUsed - 1; i >= 0; i--) {
+      resultDigits[i + n] = xDigits[i];
+    }
+    for (int i = n - 1; i >= 0; i--) {
+      resultDigits[i] = 0;
+    }
+    return resultUsed;
+  }
+
+  /// Returns `this >> n*_DIGIT_BITS`.
+  _BigIntImpl _drShift(int n) {
+    final used = _used;
+    if (used == 0) {
+      return zero;
+    }
+    final resultUsed = used - n;
+    if (resultUsed <= 0) {
+      return _isNegative ? _minusOne : zero;
+    }
+    final digits = _digits;
+    final resultDigits = Uint16List(resultUsed);
+    for (var i = n; i < used; i++) {
+      resultDigits[i - n] = digits[i];
+    }
+    final result = _BigIntImpl._(_isNegative, resultUsed, resultDigits);
+    if (_isNegative) {
+      // Round down if any bit was shifted out.
+      for (var i = 0; i < n; i++) {
+        if (digits[i] != 0) {
+          return result - one;
+        }
+      }
+    }
+    return result;
+  }
+
+  /// Shifts the digits of [xDigits] into the right place in [resultDigits].
+  ///
+  /// `resultDigits[ds..xUsed+ds] = xDigits[0..xUsed-1] << (n % _DIGIT_BITS)`
+  ///   where `ds = n ~/ _DIGIT_BITS`
+  ///
+  /// Does *not* clear digits below ds.
+  static void _lsh(
+      Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+    assert(xUsed > 0);
+    final digitShift = n ~/ _digitBits;
+    final bitShift = n % _digitBits;
+    final carryBitShift = _digitBits - bitShift;
+    final bitMask = (1 << carryBitShift) - 1;
+    var carry = 0;
+    for (int i = xUsed - 1; i >= 0; i--) {
+      final digit = xDigits[i];
+      resultDigits[i + digitShift + 1] = (digit >> carryBitShift) | carry;
+      carry = (digit & bitMask) << bitShift;
+    }
+    resultDigits[digitShift] = carry;
+  }
+
+  /**
+   * Shift the bits of this integer to the left by [shiftAmount].
+   *
+   * Shifting to the left makes the number larger, effectively multiplying
+   * the number by `pow(2, shiftIndex)`.
+   *
+   * There is no limit on the size of the result. It may be relevant to
+   * limit intermediate values by using the "and" operator with a suitable
+   * mask.
+   *
+   * It is an error if [shiftAmount] is negative.
+   */
+  _BigIntImpl operator <<(int shiftAmount) {
+    if (shiftAmount < 0) {
+      throw ArgumentError("shift-amount must be posititve $shiftAmount");
+    }
+    if (_isZero) return this;
+    final digitShift = shiftAmount ~/ _digitBits;
+    final bitShift = shiftAmount % _digitBits;
+    if (bitShift == 0) {
+      return _dlShift(digitShift);
+    }
+    var resultUsed = _used + digitShift + 1;
+    var resultDigits = Uint16List(resultUsed);
+    _lsh(_digits, _used, shiftAmount, resultDigits);
+    return _BigIntImpl._(_isNegative, resultUsed, resultDigits);
+  }
+
+  // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n.
+  // Returns resultUsed.
+  static int _lShiftDigits(
+      Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+    final digitsShift = n ~/ _digitBits;
+    final bitShift = n % _digitBits;
+    if (bitShift == 0) {
+      return _dlShiftDigits(xDigits, xUsed, digitsShift, resultDigits);
+    }
+    var resultUsed = xUsed + digitsShift + 1;
+    _lsh(xDigits, xUsed, n, resultDigits);
+    var i = digitsShift;
+    while (--i >= 0) {
+      resultDigits[i] = 0;
+    }
+    if (resultDigits[resultUsed - 1] == 0) {
+      resultUsed--; // Clamp result.
+    }
+    return resultUsed;
+  }
+
+  // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
+  static void _rsh(
+      Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+    assert(xUsed > 0);
+    final digitsShift = n ~/ _digitBits;
+    final bitShift = n % _digitBits;
+    final carryBitShift = _digitBits - bitShift;
+    final bitMask = (1 << bitShift) - 1;
+    var carry = xDigits[digitsShift] >> bitShift;
+    final last = xUsed - digitsShift - 1;
+    for (var i = 0; i < last; i++) {
+      final digit = xDigits[i + digitsShift + 1];
+      resultDigits[i] = ((digit & bitMask) << carryBitShift) | carry;
+      carry = digit >> bitShift;
+    }
+    resultDigits[last] = carry;
+  }
+
+  /**
+   * Shift the bits of this integer to the right by [shiftAmount].
+   *
+   * Shifting to the right makes the number smaller and drops the least
+   * significant bits, effectively doing an integer division by
+   *`pow(2, shiftIndex)`.
+   *
+   * It is an error if [shiftAmount] is negative.
+   */
+  _BigIntImpl operator >>(int shiftAmount) {
+    if (shiftAmount < 0) {
+      throw ArgumentError("shift-amount must be posititve $shiftAmount");
+    }
+    if (_isZero) return this;
+    final digitShift = shiftAmount ~/ _digitBits;
+    final bitShift = shiftAmount % _digitBits;
+    if (bitShift == 0) {
+      return _drShift(digitShift);
+    }
+    final used = _used;
+    final resultUsed = used - digitShift;
+    if (resultUsed <= 0) {
+      return _isNegative ? _minusOne : zero;
+    }
+    final digits = _digits;
+    final resultDigits = Uint16List(resultUsed);
+    _rsh(digits, used, shiftAmount, resultDigits);
+    final result = _BigIntImpl._(_isNegative, resultUsed, resultDigits);
+    if (_isNegative) {
+      // Round down if any bit was shifted out.
+      if ((digits[digitShift] & ((1 << bitShift) - 1)) != 0) {
+        return result - one;
+      }
+      for (var i = 0; i < digitShift; i++) {
+        if (digits[i] != 0) {
+          return result - one;
+        }
+      }
+    }
+    return result;
+  }
+
+  /// Compares this to [other] taking the absolute value of both operands.
+  ///
+  /// Returns 0 if abs(this) == abs(other); a positive number if
+  /// abs(this) > abs(other); and a negative number if abs(this) < abs(other).
+  int _absCompare(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    return _compareDigits(_digits, _used, other._digits, other._used);
+  }
+
+  /**
+   * Compares this to `other`.
+   *
+   * Returns a negative number if `this` is less than `other`, zero if they are
+   * equal, and a positive number if `this` is greater than `other`.
+   */
+  int compareTo(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isNegative == other._isNegative) {
+      var result = _absCompare(other);
+      // Use 0 - result to avoid negative zero in JavaScript.
+      return _isNegative ? 0 - result : result;
+    }
+    return _isNegative ? -1 : 1;
+  }
+
+  /// Compares `digits[0..used-1]` with `otherDigits[0..otherUsed-1]`.
+  ///
+  /// Returns 0 if equal; a positive number if larger;
+  /// and a negative number if smaller.
+  static int _compareDigits(
+      Uint16List digits, int used, Uint16List otherDigits, int otherUsed) {
+    var result = used - otherUsed;
+    if (result == 0) {
+      for (int i = used - 1; i >= 0; i--) {
+        result = digits[i] - otherDigits[i];
+        if (result != 0) return result;
+      }
+    }
+    return result;
+  }
+
+  // resultDigits[0..used] = digits[0..used-1] + otherDigits[0..otherUsed-1].
+  // used >= otherUsed > 0.
+  static void _absAdd(Uint16List digits, int used, Uint16List otherDigits,
+      int otherUsed, Uint16List resultDigits) {
+    assert(used >= otherUsed && otherUsed > 0);
+    var carry = 0;
+    for (var i = 0; i < otherUsed; i++) {
+      carry += digits[i] + otherDigits[i];
+      resultDigits[i] = carry & _digitMask;
+      carry >>= _digitBits;
+    }
+    for (var i = otherUsed; i < used; i++) {
+      carry += digits[i];
+      resultDigits[i] = carry & _digitMask;
+      carry >>= _digitBits;
+    }
+    resultDigits[used] = carry;
+  }
+
+  // resultDigits[0..used-1] = digits[0..used-1] - otherDigits[0..otherUsed-1].
+  // used >= otherUsed > 0.
+  static void _absSub(Uint16List digits, int used, Uint16List otherDigits,
+      int otherUsed, Uint16List resultDigits) {
+    assert(used >= otherUsed && otherUsed > 0);
+
+    var carry = 0;
+    for (var i = 0; i < otherUsed; i++) {
+      carry += digits[i] - otherDigits[i];
+      resultDigits[i] = carry & _digitMask;
+      // Dart2js only supports unsigned shifts.
+      // Since the carry can only be -1 or 0 use this hack.
+      carry = 0 - ((carry >> _digitBits) & 1);
+    }
+    for (var i = otherUsed; i < used; i++) {
+      carry += digits[i];
+      resultDigits[i] = carry & _digitMask;
+      // Dart2js only supports unsigned shifts.
+      // Since the carry can only be -1 or 0 use this hack.
+      carry = 0 - ((carry >> _digitBits) & 1);
+    }
+  }
+
+  /// Returns `abs(this) + abs(other)` with sign set according to [isNegative].
+  _BigIntImpl _absAddSetSign(_BigIntImpl other, bool isNegative) {
+    var used = _used;
+    var otherUsed = other._used;
+    if (used < otherUsed) {
+      return other._absAddSetSign(this, isNegative);
+    }
+    if (used == 0) {
+      assert(!isNegative);
+      return zero;
+    }
+    if (otherUsed == 0) {
+      return _isNegative == isNegative ? this : -this;
+    }
+    var resultUsed = used + 1;
+    var resultDigits = Uint16List(resultUsed);
+    _absAdd(_digits, used, other._digits, otherUsed, resultDigits);
+    return _BigIntImpl._(isNegative, resultUsed, resultDigits);
+  }
+
+  /// Returns `abs(this) - abs(other)` with sign set according to [isNegative].
+  ///
+  /// Requirement: `abs(this) >= abs(other)`.
+  _BigIntImpl _absSubSetSign(_BigIntImpl other, bool isNegative) {
+    assert(_absCompare(other) >= 0);
+    var used = _used;
+    if (used == 0) {
+      assert(!isNegative);
+      return zero;
+    }
+    var otherUsed = other._used;
+    if (otherUsed == 0) {
+      return _isNegative == isNegative ? this : -this;
+    }
+    var resultDigits = Uint16List(used);
+    _absSub(_digits, used, other._digits, otherUsed, resultDigits);
+    return _BigIntImpl._(isNegative, used, resultDigits);
+  }
+
+  /// Returns `abs(this) & abs(other)` with sign set according to [isNegative].
+  _BigIntImpl _absAndSetSign(_BigIntImpl other, bool isNegative) {
+    var resultUsed = _min(_used, other._used);
+    var digits = _digits;
+    var otherDigits = other._digits;
+    var resultDigits = Uint16List(resultUsed);
+    for (var i = 0; i < resultUsed; i++) {
+      resultDigits[i] = digits[i] & otherDigits[i];
+    }
+    return _BigIntImpl._(isNegative, resultUsed, resultDigits);
+  }
+
+  /// Returns `abs(this) &~ abs(other)` with sign set according to [isNegative].
+  _BigIntImpl _absAndNotSetSign(_BigIntImpl other, bool isNegative) {
+    var resultUsed = _used;
+    var digits = _digits;
+    var otherDigits = other._digits;
+    var resultDigits = Uint16List(resultUsed);
+    var m = _min(resultUsed, other._used);
+    for (var i = 0; i < m; i++) {
+      resultDigits[i] = digits[i] & ~otherDigits[i];
+    }
+    for (var i = m; i < resultUsed; i++) {
+      resultDigits[i] = digits[i];
+    }
+    return _BigIntImpl._(isNegative, resultUsed, resultDigits);
+  }
+
+  /// Returns `abs(this) | abs(other)` with sign set according to [isNegative].
+  _BigIntImpl _absOrSetSign(_BigIntImpl other, bool isNegative) {
+    var used = _used;
+    var otherUsed = other._used;
+    var resultUsed = _max(used, otherUsed);
+    var digits = _digits;
+    var otherDigits = other._digits;
+    var resultDigits = Uint16List(resultUsed);
+    var l, m;
+    if (used < otherUsed) {
+      l = other;
+      m = used;
+    } else {
+      l = this;
+      m = otherUsed;
+    }
+    for (var i = 0; i < m; i++) {
+      resultDigits[i] = digits[i] | otherDigits[i];
+    }
+    var lDigits = l._digits;
+    for (var i = m; i < resultUsed; i++) {
+      resultDigits[i] = lDigits[i];
+    }
+    return _BigIntImpl._(isNegative, resultUsed, resultDigits);
+  }
+
+  /// Returns `abs(this) ^ abs(other)` with sign set according to [isNegative].
+  _BigIntImpl _absXorSetSign(_BigIntImpl other, bool isNegative) {
+    var used = _used;
+    var otherUsed = other._used;
+    var resultUsed = _max(used, otherUsed);
+    var digits = _digits;
+    var otherDigits = other._digits;
+    var resultDigits = Uint16List(resultUsed);
+    var l, m;
+    if (used < otherUsed) {
+      l = other;
+      m = used;
+    } else {
+      l = this;
+      m = otherUsed;
+    }
+    for (var i = 0; i < m; i++) {
+      resultDigits[i] = digits[i] ^ otherDigits[i];
+    }
+    var lDigits = l._digits;
+    for (var i = m; i < resultUsed; i++) {
+      resultDigits[i] = lDigits[i];
+    }
+    return _BigIntImpl._(isNegative, resultUsed, resultDigits);
+  }
+
+  /**
+   * Bit-wise and operator.
+   *
+   * Treating both `this` and [other] as sufficiently large two's component
+   * integers, the result is a number with only the bits set that are set in
+   * both `this` and [other]
+   *
+   * Of both operands are negative, the result is negative, otherwise
+   * the result is non-negative.
+   */
+  _BigIntImpl operator &(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero || other._isZero) return zero;
+    if (_isNegative == other._isNegative) {
+      if (_isNegative) {
+        // (-this) & (-other) == ~(this-1) & ~(other-1)
+        //                    == ~((this-1) | (other-1))
+        //                    == -(((this-1) | (other-1)) + 1)
+        _BigIntImpl this1 = _absSubSetSign(one, true);
+        _BigIntImpl other1 = other._absSubSetSign(one, true);
+        // Result cannot be zero if this and other are negative.
+        return this1._absOrSetSign(other1, true)._absAddSetSign(one, true);
+      }
+      return _absAndSetSign(other, false);
+    }
+    // _isNegative != other._isNegative
+    var p, n;
+    if (_isNegative) {
+      p = other;
+      n = this;
+    } else {
+      // & is symmetric.
+      p = this;
+      n = other;
+    }
+    // p & (-n) == p & ~(n-1) == p &~ (n-1)
+    var n1 = n._absSubSetSign(one, false);
+    return p._absAndNotSetSign(n1, false);
+  }
+
+  /**
+   * Bit-wise or operator.
+   *
+   * Treating both `this` and [other] as sufficiently large two's component
+   * integers, the result is a number with the bits set that are set in either
+   * of `this` and [other]
+   *
+   * If both operands are non-negative, the result is non-negative,
+   * otherwise the result us negative.
+   */
+  _BigIntImpl operator |(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
+    if (_isNegative == other._isNegative) {
+      if (_isNegative) {
+        // (-this) | (-other) == ~(this-1) | ~(other-1)
+        //                    == ~((this-1) & (other-1))
+        //                    == -(((this-1) & (other-1)) + 1)
+        var this1 = _absSubSetSign(one, true);
+        var other1 = other._absSubSetSign(one, true);
+        // Result cannot be zero if this and a are negative.
+        return this1._absAndSetSign(other1, true)._absAddSetSign(one, true);
+      }
+      return _absOrSetSign(other, false);
+    }
+    // _neg != a._neg
+    var p, n;
+    if (_isNegative) {
+      p = other;
+      n = this;
+    } else {
+      // | is symmetric.
+      p = this;
+      n = other;
+    }
+    // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1)
+    var n1 = n._absSubSetSign(one, true);
+    // Result cannot be zero if only one of this or a is negative.
+    return n1._absAndNotSetSign(p, true)._absAddSetSign(one, true);
+  }
+
+  /**
+   * Bit-wise exclusive-or operator.
+   *
+   * Treating both `this` and [other] as sufficiently large two's component
+   * integers, the result is a number with the bits set that are set in one,
+   * but not both, of `this` and [other]
+   *
+   * If the operands have the same sign, the result is non-negative,
+   * otherwise the result is negative.
+   */
+  _BigIntImpl operator ^(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
+    if (_isNegative == other._isNegative) {
+      if (_isNegative) {
+        // (-this) ^ (-other) == ~(this-1) ^ ~(other-1) == (this-1) ^ (other-1)
+        var this1 = _absSubSetSign(one, true);
+        var other1 = other._absSubSetSign(one, true);
+        return this1._absXorSetSign(other1, false);
+      }
+      return _absXorSetSign(other, false);
+    }
+    // _isNegative != a._isNegative
+    var p, n;
+    if (_isNegative) {
+      p = other;
+      n = this;
+    } else {
+      // ^ is symmetric.
+      p = this;
+      n = other;
+    }
+    // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1)
+    var n1 = n._absSubSetSign(one, true);
+    // Result cannot be zero if only one of this or a is negative.
+    return p._absXorSetSign(n1, true)._absAddSetSign(one, true);
+  }
+
+  /**
+   * The bit-wise negate operator.
+   *
+   * Treating `this` as a sufficiently large two's component integer,
+   * the result is a number with the opposite bits set.
+   *
+   * This maps any integer `x` to `-x - 1`.
+   */
+  _BigIntImpl operator ~() {
+    if (_isZero) return _minusOne;
+    if (_isNegative) {
+      // ~(-this) == ~(~(this-1)) == this-1
+      return _absSubSetSign(one, false);
+    }
+    // ~this == -this-1 == -(this+1)
+    // Result cannot be zero if this is positive.
+    return _absAddSetSign(one, true);
+  }
+
+  /// Addition operator.
+  _BigIntImpl operator +(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
+    var isNegative = _isNegative;
+    if (isNegative == other._isNegative) {
+      // this + other == this + other
+      // (-this) + (-other) == -(this + other)
+      return _absAddSetSign(other, isNegative);
+    }
+    // this + (-other) == this - other == -(this - other)
+    // (-this) + other == other - this == -(this - other)
+    if (_absCompare(other) >= 0) {
+      return _absSubSetSign(other, isNegative);
+    }
+    return other._absSubSetSign(this, !isNegative);
+  }
+
+  /// Subtraction operator.
+  _BigIntImpl operator -(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero) return -other;
+    if (other._isZero) return this;
+    var isNegative = _isNegative;
+    if (isNegative != other._isNegative) {
+      // this - (-other) == this + other
+      // (-this) - other == -(this + other)
+      return _absAddSetSign(other, isNegative);
+    }
+    // this - other == this - a == -(this - other)
+    // (-this) - (-other) == other - this == -(this - other)
+    if (_absCompare(other) >= 0) {
+      return _absSubSetSign(other, isNegative);
+    }
+    return other._absSubSetSign(this, !isNegative);
+  }
+
+  /// Multiplies [x] with [multiplicandDigits] and adds the result to
+  /// [accumulatorDigits].
+  ///
+  /// The [multiplicandDigits] in the range [i] to [i]+[n]-1 are the
+  /// multiplicand digits.
+  ///
+  /// The [acculumatorDigits] in the range [j] to [j]+[n]-1 are the accumulator
+  /// digits.
+  ///
+  /// Adds the result of the multiplicand-digits * [x] to the accumulator.
+  ///
+  /// Concretely: `accumulatorDigits[j..j+n] += x * m_digits[i..i+n-1]`.
+  static void _mulAdd(int x, Uint16List multiplicandDigits, int i,
+      Uint16List accumulatorDigits, int j, int n) {
+    if (x == 0) {
+      // No-op if x is 0.
+      return;
+    }
+    int c = 0;
+    while (--n >= 0) {
+      int product = x * multiplicandDigits[i++];
+      int combined = product + accumulatorDigits[j] + c;
+      accumulatorDigits[j++] = combined & _digitMask;
+      // Note that this works with 53 bits, as the division will not lose
+      // bits.
+      c = combined ~/ _digitBase;
+    }
+    while (c != 0) {
+      int l = accumulatorDigits[j] + c;
+      accumulatorDigits[j++] = l & _digitMask;
+      c = l ~/ _digitBase;
+    }
+  }
+
+  /// Multiplication operator.
+  _BigIntImpl operator *(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    var used = _used;
+    var otherUsed = other._used;
+    if (used == 0 || otherUsed == 0) {
+      return zero;
+    }
+    var resultUsed = used + otherUsed;
+    var digits = _digits;
+    var otherDigits = other._digits;
+    var resultDigits = Uint16List(resultUsed);
+    var i = 0;
+    while (i < otherUsed) {
+      _mulAdd(otherDigits[i], digits, 0, resultDigits, i, used);
+      i++;
+    }
+    return _BigIntImpl._(
+        _isNegative != other._isNegative, resultUsed, resultDigits);
+  }
+
+  // r_digits[0..rUsed-1] = xDigits[0..xUsed-1]*otherDigits[0..otherUsed-1].
+  // Return resultUsed = xUsed + otherUsed.
+  static int _mulDigits(Uint16List xDigits, int xUsed, Uint16List otherDigits,
+      int otherUsed, Uint16List resultDigits) {
+    var resultUsed = xUsed + otherUsed;
+    var i = resultUsed;
+    assert(resultDigits.length >= i);
+    while (--i >= 0) {
+      resultDigits[i] = 0;
+    }
+    i = 0;
+    while (i < otherUsed) {
+      _mulAdd(otherDigits[i], xDigits, 0, resultDigits, i, xUsed);
+      i++;
+    }
+    return resultUsed;
+  }
+
+  /// Returns an estimate of `digits[i-1..i] ~/ topDigitDivisor`.
+  static int _estimateQuotientDigit(
+      int topDigitDivisor, Uint16List digits, int i) {
+    if (digits[i] == topDigitDivisor) return _digitMask;
+    var quotientDigit =
+        (digits[i] << _digitBits | digits[i - 1]) ~/ topDigitDivisor;
+    if (quotientDigit > _digitMask) return _digitMask;
+    return quotientDigit;
+  }
+
+  /// Returns `trunc(this / other)`, with `other != 0`.
+  _BigIntImpl _div(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    assert(other._used > 0);
+    if (_used < other._used) {
+      return zero;
+    }
+    _divRem(other);
+    // Return quotient, i.e.
+    // _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign.
+    var lastQuo_used = _lastQuoRemUsed - _lastRemUsed;
+    var quo_digits = _cloneDigits(
+        _lastQuoRemDigits, _lastRemUsed, _lastQuoRemUsed, lastQuo_used);
+    var quo = _BigIntImpl._(false, lastQuo_used, quo_digits);
+    if ((_isNegative != other._isNegative) && (quo._used > 0)) {
+      quo = -quo;
+    }
+    return quo;
+  }
+
+  /// Returns `this - other * trunc(this / other)`, with `other != 0`.
+  _BigIntImpl _rem(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    assert(other._used > 0);
+    if (_used < other._used) {
+      return this;
+    }
+    _divRem(other);
+    // Return remainder, i.e.
+    // denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign.
+    var remDigits =
+        _cloneDigits(_lastQuoRemDigits, 0, _lastRemUsed, _lastRemUsed);
+    var rem = _BigIntImpl._(false, _lastRemUsed, remDigits);
+    if (_lastRem_nsh > 0) {
+      rem = rem >> _lastRem_nsh; // Denormalize remainder.
+    }
+    if (_isNegative && (rem._used > 0)) {
+      rem = -rem;
+    }
+    return rem;
+  }
+
+  /// Computes this ~/ other and this.remainder(other).
+  ///
+  /// Stores the result in [_lastQuoRemDigits], [_lastQuoRemUsed] and
+  /// [_lastRemUsed]. The [_lastQuoRemDigits] contains the digits of *both*, the
+  /// quotient and the remainder.
+  ///
+  /// Caches the input to avoid doing the work again when users write
+  /// `a ~/ b` followed by a `a % b`.
+  void _divRem(_BigIntImpl other) {
+    // Check if result is already cached.
+    if ((this._used == _lastDividendUsed) &&
+        (other._used == _lastDivisorUsed) &&
+        identical(this._digits, _lastDividendDigits) &&
+        identical(other._digits, _lastDivisorDigits)) {
+      return;
+    }
+    assert(_used >= other._used);
+
+    var nsh = _digitBits - other._digits[other._used - 1].bitLength;
+    // Concatenated positive quotient and normalized positive remainder.
+    // The resultDigits can have at most one more digit than the dividend.
+    Uint16List resultDigits;
+    int resultUsed;
+    // Normalized positive divisor.
+    // The normalized divisor has the most-significant bit of its most
+    // significant digit set.
+    // This makes estimating the quotient easier.
+    Uint16List yDigits;
+    int yUsed;
+    if (nsh > 0) {
+      yDigits = Uint16List(other._used + 5);
+      yUsed = _lShiftDigits(other._digits, other._used, nsh, yDigits);
+      resultDigits = Uint16List(_used + 5);
+      resultUsed = _lShiftDigits(_digits, _used, nsh, resultDigits);
+    } else {
+      yDigits = other._digits;
+      yUsed = other._used;
+      resultDigits = _cloneDigits(_digits, 0, _used, _used + 2);
+      resultUsed = _used;
+    }
+    var topDigitDivisor = yDigits[yUsed - 1];
+    var i = resultUsed;
+    var j = i - yUsed;
+    // tmpDigits is a temporary array of i (resultUsed) digits.
+    var tmpDigits = Uint16List(i);
+    var tmpUsed = _dlShiftDigits(yDigits, yUsed, j, tmpDigits);
+    // Explicit first division step in case normalized dividend is larger or
+    // equal to shifted normalized divisor.
+    if (_compareDigits(resultDigits, resultUsed, tmpDigits, tmpUsed) >= 0) {
+      assert(i == resultUsed);
+      resultDigits[resultUsed++] = 1; // Quotient = 1.
+      // Subtract divisor from remainder.
+      _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+    } else {
+      // Account for possible carry in _mulAdd step.
+      resultDigits[resultUsed++] = 0;
+    }
+
+    // Negate y so we can later use _mulAdd instead of non-existent _mulSub.
+    var nyDigits = Uint16List(yUsed + 2);
+    nyDigits[yUsed] = 1;
+    _absSub(nyDigits, yUsed + 1, yDigits, yUsed, nyDigits);
+    // nyDigits is read-only and has yUsed digits (possibly including several
+    // leading zeros).
+    // resultDigits is modified during iteration.
+    // resultDigits[0..yUsed-1] is the current remainder.
+    // resultDigits[yUsed..resultUsed-1] is the current quotient.
+    --i;
+
+    while (j > 0) {
+      var estimatedQuotientDigit =
+          _estimateQuotientDigit(topDigitDivisor, resultDigits, i);
+      j--;
+      _mulAdd(estimatedQuotientDigit, nyDigits, 0, resultDigits, j, yUsed);
+      if (resultDigits[i] < estimatedQuotientDigit) {
+        // Reusing the already existing tmpDigits array.
+        var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
+        _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+        while (resultDigits[i] < --estimatedQuotientDigit) {
+          _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+        }
+      }
+      i--;
+    }
+    // Cache result.
+    _lastDividendDigits = _digits;
+    _lastDividendUsed = _used;
+    _lastDivisorDigits = other._digits;
+    _lastDivisorUsed = other._used;
+    _lastQuoRemDigits = resultDigits;
+    _lastQuoRemUsed = resultUsed;
+    _lastRemUsed = yUsed;
+    _lastRem_nsh = nsh;
+  }
+
+  int get hashCode {
+    // This is the [Jenkins hash function][1] but using masking to keep
+    // values in SMI range.
+    //
+    // [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
+
+    int combine(int hash, int value) {
+      hash = 0x1fffffff & (hash + value);
+      hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
+      return hash ^ (hash >> 6);
+    }
+
+    int finish(int hash) {
+      hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
+      hash = hash ^ (hash >> 11);
+      return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
+    }
+
+    if (_isZero) return 6707; // Just a random number.
+    var hash = _isNegative ? 83585 : 429689; // Also random.
+    for (int i = 0; i < _used; i++) {
+      hash = combine(hash, _digits[i]);
+    }
+    return finish(hash);
+  }
+
+  /**
+   * Test whether this value is numerically equal to `other`.
+   *
+   * If [other] is a [_BigIntImpl] returns whether the two operands have the same
+   * value.
+   *
+   * Returns false if `other` is not a [_BigIntImpl].
+   */
+  bool operator ==(Object other) =>
+      other is _BigIntImpl && compareTo(other) == 0;
+
+  /**
+   * Returns the minimum number of bits required to store this big integer.
+   *
+   * The number of bits excludes the sign bit, which gives the natural length
+   * for non-negative (unsigned) values.  Negative values are complemented to
+   * return the bit position of the first bit that differs from the sign bit.
+   *
+   * To find the number of bits needed to store the value as a signed value,
+   * add one, i.e. use `x.bitLength + 1`.
+   *
+   * ```
+   * x.bitLength == (-x-1).bitLength
+   *
+   * new BigInt.from(3).bitLength == 2;   // 00000011
+   * new BigInt.from(2).bitLength == 2;   // 00000010
+   * new BigInt.from(1).bitLength == 1;   // 00000001
+   * new BigInt.from(0).bitLength == 0;   // 00000000
+   * new BigInt.from(-1).bitLength == 0;  // 11111111
+   * new BigInt.from(-2).bitLength == 1;  // 11111110
+   * new BigInt.from(-3).bitLength == 2;  // 11111101
+   * new BigInt.from(-4).bitLength == 2;  // 11111100
+   * ```
+   */
+  int get bitLength {
+    if (_used == 0) return 0;
+    if (_isNegative) return (~this).bitLength;
+    return _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
+  }
+
+  /**
+   * Truncating division operator.
+   *
+   * Performs a truncating integer division, where the remainder is discarded.
+   *
+   * The remainder can be computed using the [remainder] method.
+   *
+   * Examples:
+   * ```
+   * var seven = new BigInt.from(7);
+   * var three = new BigInt.from(3);
+   * seven ~/ three;    // => 2
+   * (-seven) ~/ three; // => -2
+   * seven ~/ -three;   // => -2
+   * seven.remainder(three);    // => 1
+   * (-seven).remainder(three); // => -1
+   * seven.remainder(-three);   // => 1
+   * ```
+   */
+  _BigIntImpl operator ~/(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (other._used == 0) {
+      throw const IntegerDivisionByZeroException();
+    }
+    return _div(other);
+  }
+
+  /**
+   * Returns the remainder of the truncating division of `this` by [other].
+   *
+   * The result `r` of this operation satisfies:
+   * `this == (this ~/ other) * other + r`.
+   * As a consequence the remainder `r` has the same sign as the divider `this`.
+   */
+  _BigIntImpl remainder(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (other._used == 0) {
+      throw const IntegerDivisionByZeroException();
+    }
+    return _rem(other);
+  }
+
+  /// Division operator.
+  double operator /(BigInt other) => this.toDouble() / other.toDouble();
+
+  /** Relational less than operator. */
+  bool operator <(BigInt other) => compareTo(other) < 0;
+
+  /** Relational less than or equal operator. */
+  bool operator <=(BigInt other) => compareTo(other) <= 0;
+
+  /** Relational greater than operator. */
+  bool operator >(BigInt other) => compareTo(other) > 0;
+
+  /** Relational greater than or equal operator. */
+  bool operator >=(BigInt other) => compareTo(other) >= 0;
+
+  /**
+   * Euclidean modulo operator.
+   *
+   * Returns the remainder of the Euclidean division. The Euclidean division of
+   * two integers `a` and `b` yields two integers `q` and `r` such that
+   * `a == b * q + r` and `0 <= r < b.abs()`.
+   *
+   * The sign of the returned value `r` is always positive.
+   *
+   * See [remainder] for the remainder of the truncating division.
+   */
+  _BigIntImpl operator %(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (other._used == 0) {
+      throw const IntegerDivisionByZeroException();
+    }
+    var result = _rem(other);
+    if (result._isNegative) {
+      if (other._isNegative) {
+        result = result - other;
+      } else {
+        result = result + other;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Returns the sign of this big integer.
+   *
+   * Returns 0 for zero, -1 for values less than zero and
+   * +1 for values greater than zero.
+   */
+  int get sign {
+    if (_used == 0) return 0;
+    return _isNegative ? -1 : 1;
+  }
+
+  /// Whether this big integer is even.
+  bool get isEven => _used == 0 || (_digits[0] & 1) == 0;
+
+  /// Whether this big integer is odd.
+  bool get isOdd => !isEven;
+
+  /// Whether this number is negative.
+  bool get isNegative => _isNegative;
+
+  _BigIntImpl pow(int exponent) {
+    if (exponent < 0) {
+      throw ArgumentError("Exponent must not be negative: $exponent");
+    }
+    if (exponent == 0) return one;
+
+    // Exponentiation by squaring.
+    var result = one;
+    var base = this;
+    while (exponent != 0) {
+      if ((exponent & 1) == 1) {
+        result *= base;
+      }
+      exponent >>= 1;
+      // Skip unnecessary operation.
+      if (exponent != 0) {
+        base *= base;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Returns this integer to the power of [exponent] modulo [modulus].
+   *
+   * The [exponent] must be non-negative and [modulus] must be
+   * positive.
+   */
+  _BigIntImpl modPow(BigInt bigExponent, BigInt bigModulus) {
+    _BigIntImpl exponent = bigExponent;
+    _BigIntImpl modulus = bigModulus;
+    if (exponent._isNegative) {
+      throw ArgumentError("exponent must be positive: $exponent");
+    }
+    if (modulus <= zero) {
+      throw ArgumentError("modulus must be strictly positive: $modulus");
+    }
+    if (exponent._isZero) return one;
+
+    final modulusUsed = modulus._used;
+    final modulusUsed2p4 = 2 * modulusUsed + 4;
+    final exponentBitlen = exponent.bitLength;
+    if (exponentBitlen <= 0) return one;
+    _BigIntReduction z = _BigIntClassic(modulus);
+    var resultDigits = Uint16List(modulusUsed2p4);
+    var result2Digits = Uint16List(modulusUsed2p4);
+    var gDigits = Uint16List(modulusUsed);
+    var gUsed = z.convert(this, gDigits);
+    // Initialize result with g.
+    // Copy leading zero if any.
+    for (int j = gUsed - 1; j >= 0; j--) {
+      resultDigits[j] = gDigits[j];
+    }
+    var resultUsed = gUsed;
+    var result2Used;
+    for (int i = exponentBitlen - 2; i >= 0; i--) {
+      result2Used = z.sqr(resultDigits, resultUsed, result2Digits);
+      if (!(exponent & (one << i))._isZero) {
+        resultUsed =
+            z.mul(result2Digits, result2Used, gDigits, gUsed, resultDigits);
+      } else {
+        // Swap result and result2.
+        var tmpDigits = resultDigits;
+        var tmpUsed = resultUsed;
+        resultDigits = result2Digits;
+        resultUsed = result2Used;
+        result2Digits = tmpDigits;
+        result2Used = tmpUsed;
+      }
+    }
+    return z.revert(resultDigits, resultUsed);
+  }
+
+  // If inv is false, returns gcd(x, y).
+  // If inv is true and gcd(x, y) = 1, returns d, so that c*x + d*y = 1.
+  // If inv is true and gcd(x, y) != 1, throws Exception("Not coprime").
+  static _BigIntImpl _binaryGcd(_BigIntImpl x, _BigIntImpl y, bool inv) {
+    var xDigits = x._digits;
+    var yDigits = y._digits;
+    var xUsed = x._used;
+    var yUsed = y._used;
+    var maxUsed = xUsed > yUsed ? xUsed : yUsed;
+    var unshiftedMaxUsed = maxUsed; // Keep
+    xDigits = _cloneDigits(xDigits, 0, xUsed, maxUsed);
+    yDigits = _cloneDigits(yDigits, 0, yUsed, maxUsed);
+    int shiftAmount = 0;
+    if (inv) {
+      if ((yUsed == 1) && (yDigits[0] == 1)) return one;
+      if ((yUsed == 0) || (yDigits[0].isEven && xDigits[0].isEven)) {
+        throw Exception("Not coprime");
+      }
+    } else {
+      if (x._isZero) {
+        throw ArgumentError.value(0, "this", "must not be zero");
+      }
+      if (y._isZero) {
+        throw ArgumentError.value(0, "other", "must not be zero");
+      }
+      if (((xUsed == 1) && (xDigits[0] == 1)) ||
+          ((yUsed == 1) && (yDigits[0] == 1))) return one;
+      while (((xDigits[0] & 1) == 0) && ((yDigits[0] & 1) == 0)) {
+        _rsh(xDigits, xUsed, 1, xDigits);
+        _rsh(yDigits, yUsed, 1, yDigits);
+        shiftAmount++;
+      }
+      if (shiftAmount >= _digitBits) {
+        var digitShiftAmount = shiftAmount ~/ _digitBits;
+        xUsed -= digitShiftAmount;
+        yUsed -= digitShiftAmount;
+        maxUsed -= digitShiftAmount;
+      }
+      if ((yDigits[0] & 1) == 1) {
+        // Swap x and y.
+        var tmpDigits = xDigits;
+        var tmpUsed = xUsed;
+        xDigits = yDigits;
+        xUsed = yUsed;
+        yDigits = tmpDigits;
+        yUsed = tmpUsed;
+      }
+    }
+    var uDigits = _cloneDigits(xDigits, 0, xUsed, unshiftedMaxUsed);
+    var vDigits =
+        _cloneDigits(yDigits, 0, yUsed, unshiftedMaxUsed + 2); // +2 for lsh.
+    final bool ac = (xDigits[0] & 1) == 0;
+
+    // Variables a, b, c, and d require one more digit.
+    final abcdUsed = maxUsed + 1;
+    final abcdLen = abcdUsed + 2; // +2 to satisfy _absAdd.
+    var aDigits, bDigits, cDigits, dDigits;
+    bool aIsNegative, bIsNegative, cIsNegative, dIsNegative;
+    if (ac) {
+      aDigits = Uint16List(abcdLen);
+      aIsNegative = false;
+      aDigits[0] = 1;
+      cDigits = Uint16List(abcdLen);
+      cIsNegative = false;
+    }
+    bDigits = Uint16List(abcdLen);
+    bIsNegative = false;
+    dDigits = Uint16List(abcdLen);
+    dIsNegative = false;
+    dDigits[0] = 1;
+
+    while (true) {
+      while ((uDigits[0] & 1) == 0) {
+        _rsh(uDigits, maxUsed, 1, uDigits);
+        if (ac) {
+          if (((aDigits[0] & 1) == 1) || ((bDigits[0] & 1) == 1)) {
+            // a += y
+            if (aIsNegative) {
+              if ((aDigits[maxUsed] != 0) ||
+                  (_compareDigits(aDigits, maxUsed, yDigits, maxUsed)) > 0) {
+                _absSub(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
+              } else {
+                _absSub(yDigits, maxUsed, aDigits, maxUsed, aDigits);
+                aIsNegative = false;
+              }
+            } else {
+              _absAdd(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
+            }
+            // b -= x
+            if (bIsNegative) {
+              _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
+            } else if ((bDigits[maxUsed] != 0) ||
+                (_compareDigits(bDigits, maxUsed, xDigits, maxUsed) > 0)) {
+              _absSub(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
+            } else {
+              _absSub(xDigits, maxUsed, bDigits, maxUsed, bDigits);
+              bIsNegative = true;
+            }
+          }
+          _rsh(aDigits, abcdUsed, 1, aDigits);
+        } else if ((bDigits[0] & 1) == 1) {
+          // b -= x
+          if (bIsNegative) {
+            _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
+          } else if ((bDigits[maxUsed] != 0) ||
+              (_compareDigits(bDigits, maxUsed, xDigits, maxUsed) > 0)) {
+            _absSub(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
+          } else {
+            _absSub(xDigits, maxUsed, bDigits, maxUsed, bDigits);
+            bIsNegative = true;
+          }
+        }
+        _rsh(bDigits, abcdUsed, 1, bDigits);
+      }
+      while ((vDigits[0] & 1) == 0) {
+        _rsh(vDigits, maxUsed, 1, vDigits);
+        if (ac) {
+          if (((cDigits[0] & 1) == 1) || ((dDigits[0] & 1) == 1)) {
+            // c += y
+            if (cIsNegative) {
+              if ((cDigits[maxUsed] != 0) ||
+                  (_compareDigits(cDigits, maxUsed, yDigits, maxUsed) > 0)) {
+                _absSub(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
+              } else {
+                _absSub(yDigits, maxUsed, cDigits, maxUsed, cDigits);
+                cIsNegative = false;
+              }
+            } else {
+              _absAdd(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
+            }
+            // d -= x
+            if (dIsNegative) {
+              _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+            } else if ((dDigits[maxUsed] != 0) ||
+                (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+              _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+            } else {
+              _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+              dIsNegative = true;
+            }
+          }
+          _rsh(cDigits, abcdUsed, 1, cDigits);
+        } else if ((dDigits[0] & 1) == 1) {
+          // d -= x
+          if (dIsNegative) {
+            _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+          } else if ((dDigits[maxUsed] != 0) ||
+              (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+            _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+          } else {
+            _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+            dIsNegative = true;
+          }
+        }
+        _rsh(dDigits, abcdUsed, 1, dDigits);
+      }
+      if (_compareDigits(uDigits, maxUsed, vDigits, maxUsed) >= 0) {
+        // u -= v
+        _absSub(uDigits, maxUsed, vDigits, maxUsed, uDigits);
+        if (ac) {
+          // a -= c
+          if (aIsNegative == cIsNegative) {
+            var a_cmp_c = _compareDigits(aDigits, abcdUsed, cDigits, abcdUsed);
+            if (a_cmp_c > 0) {
+              _absSub(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
+            } else {
+              _absSub(cDigits, abcdUsed, aDigits, abcdUsed, aDigits);
+              aIsNegative = !aIsNegative && (a_cmp_c != 0);
+            }
+          } else {
+            _absAdd(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
+          }
+        }
+        // b -= d
+        if (bIsNegative == dIsNegative) {
+          var b_cmp_d = _compareDigits(bDigits, abcdUsed, dDigits, abcdUsed);
+          if (b_cmp_d > 0) {
+            _absSub(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
+          } else {
+            _absSub(dDigits, abcdUsed, bDigits, abcdUsed, bDigits);
+            bIsNegative = !bIsNegative && (b_cmp_d != 0);
+          }
+        } else {
+          _absAdd(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
+        }
+      } else {
+        // v -= u
+        _absSub(vDigits, maxUsed, uDigits, maxUsed, vDigits);
+        if (ac) {
+          // c -= a
+          if (cIsNegative == aIsNegative) {
+            var c_cmp_a = _compareDigits(cDigits, abcdUsed, aDigits, abcdUsed);
+            if (c_cmp_a > 0) {
+              _absSub(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
+            } else {
+              _absSub(aDigits, abcdUsed, cDigits, abcdUsed, cDigits);
+              cIsNegative = !cIsNegative && (c_cmp_a != 0);
+            }
+          } else {
+            _absAdd(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
+          }
+        }
+        // d -= b
+        if (dIsNegative == bIsNegative) {
+          var d_cmp_b = _compareDigits(dDigits, abcdUsed, bDigits, abcdUsed);
+          if (d_cmp_b > 0) {
+            _absSub(dDigits, abcdUsed, bDigits, abcdUsed, dDigits);
+          } else {
+            _absSub(bDigits, abcdUsed, dDigits, abcdUsed, dDigits);
+            dIsNegative = !dIsNegative && (d_cmp_b != 0);
+          }
+        } else {
+          _absAdd(dDigits, abcdUsed, bDigits, abcdUsed, dDigits);
+        }
+      }
+      // Exit loop if u == 0.
+      var i = maxUsed;
+      while ((i > 0) && (uDigits[i - 1] == 0)) --i;
+      if (i == 0) break;
+    }
+    if (!inv) {
+      if (shiftAmount > 0) {
+        maxUsed = _lShiftDigits(vDigits, maxUsed, shiftAmount, vDigits);
+      }
+      return _BigIntImpl._(false, maxUsed, vDigits);
+    }
+    // No inverse if v != 1.
+    var i = maxUsed - 1;
+    while ((i > 0) && (vDigits[i] == 0)) --i;
+    if ((i != 0) || (vDigits[0] != 1)) {
+      throw Exception("Not coprime");
+    }
+
+    if (dIsNegative) {
+      while ((dDigits[maxUsed] != 0) ||
+          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+        // d += x, d still negative
+        _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+      }
+      // d += x
+      _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+      dIsNegative = false;
+    } else {
+      while ((dDigits[maxUsed] != 0) ||
+          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) >= 0)) {
+        // d -= x
+        _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+      }
+    }
+    return _BigIntImpl._(false, maxUsed, dDigits);
+  }
+
+  /**
+   * Returns the modular multiplicative inverse of this big integer
+   * modulo [modulus].
+   *
+   * The [modulus] must be positive.
+   *
+   * It is an error if no modular inverse exists.
+   */
+  // Returns 1/this % modulus, with modulus > 0.
+  _BigIntImpl modInverse(BigInt bigInt) {
+    _BigIntImpl modulus = bigInt;
+    if (modulus <= zero) {
+      throw ArgumentError("Modulus must be strictly positive: $modulus");
+    }
+    if (modulus == one) return zero;
+    var tmp = this;
+    if (tmp._isNegative || (tmp._absCompare(modulus) >= 0)) {
+      tmp %= modulus;
+    }
+    return _binaryGcd(modulus, tmp, true);
+  }
+
+  /**
+   * Returns the greatest common divisor of this big integer and [other].
+   *
+   * If either number is non-zero, the result is the numerically greatest
+   * integer dividing both `this` and `other`.
+   *
+   * The greatest common divisor is independent of the order,
+   * so `x.gcd(y)` is  always the same as `y.gcd(x)`.
+   *
+   * For any integer `x`, `x.gcd(x)` is `x.abs()`.
+   *
+   * If both `this` and `other` is zero, the result is also zero.
+   */
+  _BigIntImpl gcd(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero) return other.abs();
+    if (other._isZero) return this.abs();
+    return _binaryGcd(this, other, false);
+  }
+
+  /**
+   * Returns the least significant [width] bits of this big integer as a
+   * non-negative number (i.e. unsigned representation).  The returned value has
+   * zeros in all bit positions higher than [width].
+   *
+   * ```
+   * new BigInt.from(-1).toUnsigned(5) == 31   // 11111111  ->  00011111
+   * ```
+   *
+   * This operation can be used to simulate arithmetic from low level languages.
+   * For example, to increment an 8 bit quantity:
+   *
+   * ```
+   * q = (q + 1).toUnsigned(8);
+   * ```
+   *
+   * `q` will count from `0` up to `255` and then wrap around to `0`.
+   *
+   * If the input fits in [width] bits without truncation, the result is the
+   * same as the input.  The minimum width needed to avoid truncation of `x` is
+   * given by `x.bitLength`, i.e.
+   *
+   * ```
+   * x == x.toUnsigned(x.bitLength);
+   * ```
+   */
+  _BigIntImpl toUnsigned(int width) {
+    return this & ((one << width) - one);
+  }
+
+  /**
+   * Returns the least significant [width] bits of this integer, extending the
+   * highest retained bit to the sign.  This is the same as truncating the value
+   * to fit in [width] bits using an signed 2-s complement representation.  The
+   * returned value has the same bit value in all positions higher than [width].
+   *
+   * ```
+   * var big15 = new BigInt.from(15);
+   * var big16 = new BigInt.from(16);
+   * var big239 = new BigInt.from(239);
+   *                                      V--sign bit-V
+   * big16.toSigned(5) == -big16   //  00010000 -> 11110000
+   * big239.toSigned(5) == big15   //  11101111 -> 00001111
+   *                                      ^           ^
+   * ```
+   *
+   * This operation can be used to simulate arithmetic from low level languages.
+   * For example, to increment an 8 bit signed quantity:
+   *
+   * ```
+   * q = (q + 1).toSigned(8);
+   * ```
+   *
+   * `q` will count from `0` up to `127`, wrap to `-128` and count back up to
+   * `127`.
+   *
+   * If the input value fits in [width] bits without truncation, the result is
+   * the same as the input.  The minimum width needed to avoid truncation of `x`
+   * is `x.bitLength + 1`, i.e.
+   *
+   * ```
+   * x == x.toSigned(x.bitLength + 1);
+   * ```
+   */
+  _BigIntImpl toSigned(int width) {
+    // The value of binary number weights each bit by a power of two.  The
+    // twos-complement value weights the sign bit negatively.  We compute the
+    // value of the negative weighting by isolating the sign bit with the
+    // correct power of two weighting and subtracting it from the value of the
+    // lower bits.
+    var signMask = one << (width - 1);
+    return (this & (signMask - one)) - (this & signMask);
+  }
+
+  // Maximum number of digits that always fit in mantissa.
+  static const _simpleValidIntDigits = 53 ~/ _digitBits;
+
+  bool get isValidInt {
+    if (_used <= _simpleValidIntDigits) return true;
+    var asInt = toInt();
+    if (!asInt.toDouble().isFinite) return false;
+    return this == _BigIntImpl._fromInt(asInt);
+  }
+
+  int toInt() {
+    var result = 0;
+    for (int i = _used - 1; i >= 0; i--) {
+      result = result * _digitBase + _digits[i];
+    }
+    return _isNegative ? -result : result;
+  }
+
+  /**
+   * Returns this [_BigIntImpl] as a [double].
+   *
+   * If the number is not representable as a [double], an
+   * approximation is returned. For numerically large integers, the
+   * approximation may be infinite.
+   */
+  double toDouble() {
+    const int exponentBias = 1075;
+    // There are 11 bits for the exponent.
+    // 2047 (all bits set to 1) is reserved for infinity and NaN.
+    // When storing the exponent in the 11 bits, it is biased by exponentBias
+    // to support negative exponents.
+    const int maxDoubleExponent = 2046 - exponentBias;
+    if (_isZero) return 0.0;
+
+    // We fill the 53 bits little-endian.
+    var resultBits = Uint8List(8);
+
+    var length = _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
+    if (length > maxDoubleExponent + 53) {
+      return _isNegative ? double.negativeInfinity : double.infinity;
+    }
+
+    // The most significant bit is for the sign.
+    if (_isNegative) resultBits[7] = 0x80;
+
+    // Write the exponent into bits 1..12:
+    var biasedExponent = length - 53 + exponentBias;
+    resultBits[6] = (biasedExponent & 0xF) << 4;
+    resultBits[7] |= biasedExponent >> 4;
+
+    int cachedBits = 0;
+    int cachedBitsLength = 0;
+    int digitIndex = _used - 1;
+    int readBits(int n) {
+      // Ensure that we have enough bits in [cachedBits].
+      while (cachedBitsLength < n) {
+        int nextDigit;
+        int nextDigitLength = _digitBits; // May get updated.
+        if (digitIndex < 0) {
+          nextDigit = 0;
+          digitIndex--;
+        } else {
+          nextDigit = _digits[digitIndex];
+          if (digitIndex == _used - 1) nextDigitLength = nextDigit.bitLength;
+          digitIndex--;
+        }
+        cachedBits = (cachedBits << nextDigitLength) + nextDigit;
+        cachedBitsLength += nextDigitLength;
+      }
+      // Read the top [n] bits.
+      var result = cachedBits >> (cachedBitsLength - n);
+      // Remove the bits from the cache.
+      cachedBits -= result << (cachedBitsLength - n);
+      cachedBitsLength -= n;
+      return result;
+    }
+
+    // The first leading 1 bit is implicit in the double-representation and can
+    // be discarded.
+    var leadingBits = readBits(5) & 0xF;
+    resultBits[6] |= leadingBits;
+
+    for (int i = 5; i >= 0; i--) {
+      // Get the remaining 48 bits.
+      resultBits[i] = readBits(8);
+    }
+
+    void roundUp() {
+      // Simply consists of adding 1 to the whole 64 bit "number".
+      // It will update the exponent, if necessary.
+      // It might even round up to infinity (which is what we want).
+      var carry = 1;
+      for (int i = 0; i < 8; i++) {
+        if (carry == 0) break;
+        var sum = resultBits[i] + carry;
+        resultBits[i] = sum & 0xFF;
+        carry = sum >> 8;
+      }
+    }
+
+    if (readBits(1) == 1) {
+      if (resultBits[0].isOdd) {
+        // Rounds to even all the time.
+        roundUp();
+      } else {
+        // Round up, if there is at least one other digit that is not 0.
+        if (cachedBits != 0) {
+          // There is already one in the cachedBits.
+          roundUp();
+        } else {
+          for (int i = digitIndex; digitIndex >= 0; i--) {
+            if (_digits[i] != 0) {
+              roundUp();
+              break;
+            }
+          }
+        }
+      }
+    }
+    return resultBits.buffer.asByteData().getFloat64(0, Endian.little);
+  }
+
+  /**
+   * Returns a String-representation of this integer.
+   *
+   * The returned string is parsable by [parse].
+   * For any `_BigIntImpl` `i`, it is guaranteed that
+   * `i == _BigIntImpl.parse(i.toString())`.
+   */
+  String toString() {
+    if (_used == 0) return "0";
+    if (_used == 1) {
+      if (_isNegative) return (-_digits[0]).toString();
+      return _digits[0].toString();
+    }
+
+    // Generate in chunks of 4 digits.
+    // The chunks are in reversed order.
+    var decimalDigitChunks = <String>[];
+    var rest = isNegative ? -this : this;
+    while (rest._used > 1) {
+      var digits4 = rest.remainder(_bigInt10000).toString();
+      decimalDigitChunks.add(digits4);
+      if (digits4.length == 1) decimalDigitChunks.add("000");
+      if (digits4.length == 2) decimalDigitChunks.add("00");
+      if (digits4.length == 3) decimalDigitChunks.add("0");
+      rest = rest ~/ _bigInt10000;
+    }
+    decimalDigitChunks.add(rest._digits[0].toString());
+    if (_isNegative) decimalDigitChunks.add("-");
+    return decimalDigitChunks.reversed.join();
+  }
+
+  int _toRadixCodeUnit(int digit) {
+    const int _0 = 48;
+    const int _a = 97;
+    if (digit < 10) return _0 + digit;
+    return _a + digit - 10;
+  }
+
+  /**
+   * Converts [this] to a string representation in the given [radix].
+   *
+   * In the string representation, lower-case letters are used for digits above
+   * '9', with 'a' being 10 an 'z' being 35.
+   *
+   * The [radix] argument must be an integer in the range 2 to 36.
+   */
+  String toRadixString(int radix) {
+    if (radix > 36) throw RangeError.range(radix, 2, 36);
+
+    if (_used == 0) return "0";
+
+    if (_used == 1) {
+      var digitString = _digits[0].toRadixString(radix);
+      if (_isNegative) return "-" + digitString;
+      return digitString;
+    }
+
+    if (radix == 16) return _toHexString();
+
+    var base = _BigIntImpl._fromInt(radix);
+    var reversedDigitCodeUnits = <int>[];
+    var rest = this.abs();
+    while (!rest._isZero) {
+      var digit = rest.remainder(base).toInt();
+      rest = rest ~/ base;
+      reversedDigitCodeUnits.add(_toRadixCodeUnit(digit));
+    }
+    var digitString = String.fromCharCodes(reversedDigitCodeUnits.reversed);
+    if (_isNegative) return "-" + digitString;
+    return digitString;
+  }
+
+  String _toHexString() {
+    var chars = <int>[];
+    for (int i = 0; i < _used - 1; i++) {
+      int chunk = _digits[i];
+      for (int j = 0; j < (_digitBits ~/ 4); j++) {
+        chars.add(_toRadixCodeUnit(chunk & 0xF));
+        chunk >>= 4;
+      }
+    }
+    var msbChunk = _digits[_used - 1];
+    while (msbChunk != 0) {
+      chars.add(_toRadixCodeUnit(msbChunk & 0xF));
+      msbChunk >>= 4;
+    }
+    if (_isNegative) {
+      const _dash = 45;
+      chars.add(_dash);
+    }
+    return String.fromCharCodes(chars.reversed);
+  }
+}
+
+// Interface for modular reduction.
+abstract class _BigIntReduction {
+  // Return the number of digits used by r_digits.
+  int convert(_BigIntImpl x, Uint16List r_digits);
+  int mul(Uint16List xDigits, int xUsed, Uint16List yDigits, int yUsed,
+      Uint16List resultDigits);
+  int sqr(Uint16List xDigits, int xUsed, Uint16List resultDigits);
+
+  // Return x reverted to _BigIntImpl.
+  _BigIntImpl revert(Uint16List xDigits, int xUsed);
+}
+
+// Modular reduction using "classic" algorithm.
+class _BigIntClassic implements _BigIntReduction {
+  final _BigIntImpl _modulus; // Modulus.
+  final _BigIntImpl _normalizedModulus; // Normalized _modulus.
+
+  _BigIntClassic(this._modulus)
+      : _normalizedModulus = _modulus <<
+            (_BigIntImpl._digitBits -
+                _modulus._digits[_modulus._used - 1].bitLength);
+
+  int convert(_BigIntImpl x, Uint16List resultDigits) {
+    var digits;
+    var used;
+    if (x._isNegative || x._absCompare(_modulus) >= 0) {
+      var remainder = x._rem(_modulus);
+      if (x._isNegative && remainder._used > 0) {
+        assert(remainder._isNegative);
+        remainder += _modulus;
+      }
+      assert(!remainder._isNegative);
+      used = remainder._used;
+      digits = remainder._digits;
+    } else {
+      used = x._used;
+      digits = x._digits;
+    }
+    var i = used; // Copy leading zero if any.
+    while (--i >= 0) {
+      resultDigits[i] = digits[i];
+    }
+    return used;
+  }
+
+  _BigIntImpl revert(Uint16List xDigits, int xUsed) {
+    return _BigIntImpl._(false, xUsed, xDigits);
+  }
+
+  int _reduce(Uint16List xDigits, int xUsed) {
+    if (xUsed < _modulus._used) {
+      return xUsed;
+    }
+    var reverted = revert(xDigits, xUsed);
+    var rem = reverted._rem(_normalizedModulus);
+    return convert(rem, xDigits);
+  }
+
+  int sqr(Uint16List xDigits, int xUsed, Uint16List resultDigits) {
+    var b = _BigIntImpl._(false, xUsed, xDigits);
+    var b2 = b * b;
+    for (int i = 0; i < b2._used; i++) {
+      resultDigits[i] = b2._digits[i];
+    }
+    for (int i = b2._used; i < 2 * xUsed; i++) {
+      resultDigits[i] = 0;
+    }
+    return _reduce(resultDigits, 2 * xUsed);
+  }
+
+  int mul(Uint16List xDigits, int xUsed, Uint16List yDigits, int yUsed,
+      Uint16List resultDigits) {
+    var resultUsed =
+        _BigIntImpl._mulDigits(xDigits, xUsed, yDigits, yUsed, resultDigits);
+    return _reduce(resultDigits, resultUsed);
+  }
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/developer_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/patch/developer_patch.dart
rename to sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/internal_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/patch/internal_patch.dart
rename to sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart
rename to sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/isolate_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/isolate_patch.dart
new file mode 100644
index 0000000..f6aa73bb
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/patch/isolate_patch.dart
@@ -0,0 +1,125 @@
+// 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.
+
+// Patch file for the dart:isolate library.
+
+import 'dart:_js_helper' show patch, NoReifyGeneric;
+import 'dart:async';
+import "dart:typed_data" show TypedData;
+
+@patch
+class Isolate {
+  // `current` must be a getter, not just a final field,
+  // to match the external declaration.
+  @patch
+  static Isolate get current => _unsupported();
+
+  @patch
+  String get debugName => _unsupported();
+
+  @patch
+  static Future<Uri> get packageRoot => _unsupported();
+
+  @patch
+  static Future<Uri> get packageConfig => _unsupported();
+
+  @patch
+  static Future<Uri> resolvePackageUri(Uri packageUri) => _unsupported();
+
+  @patch
+  static Future<Isolate> spawn<T>(void entryPoint(T message), T message,
+          {bool paused = false,
+          bool errorsAreFatal,
+          SendPort onExit,
+          SendPort onError}) =>
+      _unsupported();
+
+  @patch
+  static Future<Isolate> spawnUri(Uri uri, List<String> args, var message,
+          {bool paused = false,
+          SendPort onExit,
+          SendPort onError,
+          bool errorsAreFatal,
+          bool checked,
+          Map<String, String> environment,
+          Uri packageRoot,
+          Uri packageConfig,
+          bool automaticPackageResolution = false}) =>
+      _unsupported();
+
+  @patch
+  void _pause(Capability resumeCapability) => _unsupported();
+
+  @patch
+  void resume(Capability resumeCapability) => _unsupported();
+
+  @patch
+  void addOnExitListener(SendPort responsePort, {Object response}) =>
+      _unsupported();
+
+  @patch
+  void removeOnExitListener(SendPort responsePort) => _unsupported();
+
+  @patch
+  void setErrorsFatal(bool errorsAreFatal) => _unsupported();
+
+  @patch
+  void kill({int priority = beforeNextEvent}) => _unsupported();
+  @patch
+  void ping(SendPort responsePort,
+          {Object response, int priority = immediate}) =>
+      _unsupported();
+
+  @patch
+  void addErrorListener(SendPort port) => _unsupported();
+
+  @patch
+  void removeErrorListener(SendPort port) => _unsupported();
+}
+
+/** Default factory for receive ports. */
+@patch
+class ReceivePort {
+  @patch
+  factory ReceivePort() = _ReceivePort;
+
+  @patch
+  factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) =>
+      _unsupported();
+}
+
+/// ReceivePort is supported by dev_compiler because async test packages
+/// (async_helper, unittest) create a dummy receive port to keep the Dart VM
+/// alive.
+class _ReceivePort extends Stream implements ReceivePort {
+  close() {}
+
+  get sendPort => _unsupported();
+
+  listen(onData, {onError, onDone, cancelOnError}) => _unsupported();
+}
+
+@patch
+class RawReceivePort {
+  @patch
+  factory RawReceivePort([void handler(event)]) => _unsupported();
+}
+
+@patch
+class Capability {
+  @patch
+  factory Capability() => _unsupported();
+}
+
+@patch
+abstract class TransferableTypedData {
+  @patch
+  factory TransferableTypedData.fromList(List<TypedData> list) =>
+      _unsupported();
+}
+
+@NoReifyGeneric()
+T _unsupported<T>() {
+  throw UnsupportedError('dart:isolate is not supported on dart4web');
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/math_patch.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart
rename to sdk/lib/_internal/js_dev_runtime/patch/math_patch.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/mirrors_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/patch/mirrors_patch.dart
rename to sdk/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/typed_data_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/patch/typed_data_patch.dart
rename to sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/annotations.dart b/sdk/lib/_internal/js_dev_runtime/private/annotations.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/annotations.dart
rename to sdk/lib/_internal/js_dev_runtime/private/annotations.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/custom_hash_map.dart b/sdk/lib/_internal/js_dev_runtime/private/custom_hash_map.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/custom_hash_map.dart
rename to sdk/lib/_internal/js_dev_runtime/private/custom_hash_map.dart
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
new file mode 100644
index 0000000..704b856
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
@@ -0,0 +1,530 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library defines the operations that define and manipulate Dart
+/// classes.  Included in this are:
+///   - Generics
+///   - Class metadata
+///   - Extension methods
+///
+
+// TODO(leafp): Consider splitting some of this out.
+part of dart._runtime;
+
+/// Returns a new type that mixes members from base and the mixin.
+void applyMixin(to, from) {
+  JS('', '#[#] = #', to, _mixin, from);
+  var toProto = JS('', '#.prototype', to);
+  var fromProto = JS('', '#.prototype', from);
+  _copyMembers(toProto, fromProto);
+  _mixinSignature(to, from, _methodSig);
+  _mixinSignature(to, from, _fieldSig);
+  _mixinSignature(to, from, _getterSig);
+  _mixinSignature(to, from, _setterSig);
+  var mixinOnFn = JS('', '#[#]', from, mixinOn);
+  if (mixinOnFn != null) {
+    var proto = JS('', '#(#.__proto__).prototype', mixinOnFn, to);
+    _copyMembers(toProto, proto);
+  }
+}
+
+void _copyMembers(to, from) {
+  var names = getOwnNamesAndSymbols(from);
+  for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) {
+    String name = JS('', '#[#]', names, i);
+    if (name == 'constructor') continue;
+    _copyMember(to, from, name);
+  }
+  return to;
+}
+
+void _copyMember(to, from, name) {
+  var desc = getOwnPropertyDescriptor(from, name);
+  if (JS('!', '# == Symbol.iterator', name)) {
+    // On native types, Symbol.iterator may already be present.
+    // TODO(jmesserly): investigate if we still need this.
+    // If so, we need to find a better solution.
+    // See https://github.com/dart-lang/sdk/issues/28324
+    var existing = getOwnPropertyDescriptor(to, name);
+    if (existing != null) {
+      if (JS('!', '#.writable', existing)) {
+        JS('', '#[#] = #.value', to, name, desc);
+      }
+      return;
+    }
+  }
+  var getter = JS('', '#.get', desc);
+  var setter = JS('', '#.set', desc);
+  if (getter != null) {
+    if (setter == null) {
+      var obj = JS(
+          '',
+          '#.set = { __proto__: #.__proto__, '
+              'set [#](x) { return super[#] = x; } }',
+          desc,
+          to,
+          name,
+          name);
+      JS('', '#.set = #.set', desc, getOwnPropertyDescriptor(obj, name));
+    }
+  } else if (setter != null) {
+    if (getter == null) {
+      var obj = JS(
+          '',
+          '#.get = { __proto__: #.__proto__, '
+              'get [#]() { return super[#]; } }',
+          desc,
+          to,
+          name,
+          name);
+      JS('', '#.get = #.get', desc, getOwnPropertyDescriptor(obj, name));
+    }
+  }
+  defineProperty(to, name, desc);
+}
+
+void _mixinSignature(to, from, kind) {
+  JS('', '#[#] = #', to, kind, () {
+    var baseMembers = _getMembers(JS('', '#.__proto__', to), kind);
+    var fromMembers = _getMembers(from, kind);
+    if (fromMembers == null) return baseMembers;
+    var toSignature = JS('', '{ __proto__: # }', baseMembers);
+    copyProperties(toSignature, fromMembers);
+    return toSignature;
+  });
+}
+
+final _mixin = JS('', 'Symbol("mixin")');
+
+getMixin(clazz) => JS('', 'Object.hasOwnProperty.call(#, #) ? #[#] : null',
+    clazz, _mixin, clazz, _mixin);
+
+final mixinOn = JS('', 'Symbol("mixinOn")');
+
+@JSExportName('implements')
+final implements_ = JS('', 'Symbol("implements")');
+
+List Function() getImplements(clazz) => JS(
+    '',
+    'Object.hasOwnProperty.call(#, #) ? #[#] : null',
+    clazz,
+    implements_,
+    clazz,
+    implements_);
+
+/// The Symbol for storing type arguments on a specialized generic type.
+final _typeArguments = JS('', 'Symbol("typeArguments")');
+
+final _originalDeclaration = JS('', 'Symbol("originalDeclaration")');
+
+final mixinNew = JS('', 'Symbol("dart.mixinNew")');
+
+/// Memoize a generic type constructor function.
+generic(typeConstructor, setBaseClass) => JS('', '''(() => {
+  let length = $typeConstructor.length;
+  if (length < 1) {
+    $throwInternalError('must have at least one generic type argument');
+  }
+  let resultMap = new Map();
+  $_cacheMaps.push(resultMap);
+  function makeGenericType(...args) {
+    if (args.length != length && args.length != 0) {
+      $throwInternalError('requires ' + length + ' or 0 type arguments');
+    }
+    while (args.length < length) args.push($dynamic);
+
+    let value = resultMap;
+    for (let i = 0; i < length; i++) {
+      let arg = args[i];
+      if (arg == null) {
+        $throwInternalError('type arguments should not be null: '
+                          + $typeConstructor);
+      }
+      let map = value;
+      value = map.get(arg);
+      if (value === void 0) {
+        if (i + 1 == length) {
+          value = $typeConstructor.apply(null, args);
+          // Save the type constructor and arguments for reflection.
+          if (value) {
+            value[$_typeArguments] = args;
+            value[$_originalDeclaration] = makeGenericType;
+          }
+          map.set(arg, value);
+          if ($setBaseClass != null) $setBaseClass.apply(null, args);
+        } else {
+          value = new Map();
+          map.set(arg, value);
+        }
+      }
+    }
+    return value;
+  }
+  makeGenericType[$_genericTypeCtor] = $typeConstructor;
+  return makeGenericType;
+})()''');
+
+getGenericClass(type) => safeGetOwnProperty(type, _originalDeclaration);
+
+List getGenericArgs(type) =>
+    JS('List', '#', safeGetOwnProperty(type, _typeArguments));
+
+List<TypeVariable> getGenericTypeFormals(genericClass) {
+  return _typeFormalsFromFunction(getGenericTypeCtor(genericClass));
+}
+
+Object instantiateClass(Object genericClass, List<Object> typeArgs) {
+  return JS('', '#.apply(null, #)', genericClass, typeArgs);
+}
+
+final _constructorSig = JS('', 'Symbol("sigCtor")');
+final _methodSig = JS('', 'Symbol("sigMethod")');
+final _fieldSig = JS('', 'Symbol("sigField")');
+final _getterSig = JS('', 'Symbol("sigGetter")');
+final _setterSig = JS('', 'Symbol("sigSetter")');
+final _staticMethodSig = JS('', 'Symbol("sigStaticMethod")');
+final _staticFieldSig = JS('', 'Symbol("sigStaticField")');
+final _staticGetterSig = JS('', 'Symbol("sigStaticGetter")');
+final _staticSetterSig = JS('', 'Symbol("sigStaticSetter")');
+final _genericTypeCtor = JS('', 'Symbol("genericType")');
+final _libraryUri = JS('', 'Symbol("libraryUri")');
+
+getConstructors(value) => _getMembers(value, _constructorSig);
+getMethods(value) => _getMembers(value, _methodSig);
+getFields(value) => _getMembers(value, _fieldSig);
+getGetters(value) => _getMembers(value, _getterSig);
+getSetters(value) => _getMembers(value, _setterSig);
+getStaticMethods(value) => _getMembers(value, _staticMethodSig);
+getStaticFields(value) => _getMembers(value, _staticFieldSig);
+getStaticGetters(value) => _getMembers(value, _staticGetterSig);
+getStaticSetters(value) => _getMembers(value, _staticSetterSig);
+
+getGenericTypeCtor(value) => JS('', '#[#]', value, _genericTypeCtor);
+
+/// Get the type of a method from an object using the stored signature
+getType(obj) =>
+    JS('', '# == null ? # : #.__proto__.constructor', obj, Object, obj);
+
+getLibraryUri(value) => JS('', '#[#]', value, _libraryUri);
+setLibraryUri(f, uri) => JS('', '#[#] = #', f, _libraryUri, uri);
+
+bool isJsInterop(obj) {
+  if (obj == null) return false;
+  if (JS('!', 'typeof # === "function"', obj)) {
+    // A function is a Dart function if it has runtime type information.
+    return JS('!', '#[#] == null', obj, _runtimeType);
+  }
+  // Primitive types are not JS interop types.
+  if (JS('!', 'typeof # !== "object"', obj)) return false;
+
+  // Extension types are not considered JS interop types.
+  // Note that it is still possible to call typed JS interop methods on
+  // extension types but the calls must be statically typed.
+  if (JS('!', '#[#] != null', obj, _extensionType)) return false;
+  return JS('!', '!($obj instanceof $Object)');
+}
+
+/// Get the type of a method from a type using the stored signature
+getMethodType(type, name) {
+  var m = getMethods(type);
+  return m != null ? JS('', '#[#]', m, name) : null;
+}
+
+/// Gets the type of the corresponding setter (this includes writable fields).
+getSetterType(type, name) {
+  var setters = getSetters(type);
+  if (setters != null) {
+    var type = JS('', '#[#]', setters, name);
+    if (type != null) {
+      if (JS('!', '# instanceof Array', type)) {
+        // The type has metadata attached.  Pull out just the type.
+        // TODO(jmesserly): remove when we remove mirrors
+        return JS('', '#[0]', type);
+      }
+      return type;
+    }
+  }
+  var fields = getFields(type);
+  if (fields != null) {
+    var fieldInfo = JS('', '#[#]', fields, name);
+    if (fieldInfo != null && JS<bool>('!', '!#.isFinal', fieldInfo)) {
+      return JS('', '#.type', fieldInfo);
+    }
+  }
+  return null;
+}
+
+finalFieldType(type, metadata) =>
+    JS('', '{ type: #, isFinal: true, metadata: # }', type, metadata);
+
+fieldType(type, metadata) =>
+    JS('', '{ type: #, isFinal: false, metadata: # }', type, metadata);
+
+/// Get the type of a constructor from a class using the stored signature
+/// If name is undefined, returns the type of the default constructor
+/// Returns undefined if the constructor is not found.
+classGetConstructorType(cls, name) {
+  if (cls == null) return null;
+  if (name == null) name = 'new';
+  var ctors = getConstructors(cls);
+  return ctors != null ? JS('', '#[#]', ctors, name) : null;
+}
+
+void setMethodSignature(f, sigF) => JS('', '#[#] = #', f, _methodSig, sigF);
+void setFieldSignature(f, sigF) => JS('', '#[#] = #', f, _fieldSig, sigF);
+void setGetterSignature(f, sigF) => JS('', '#[#] = #', f, _getterSig, sigF);
+void setSetterSignature(f, sigF) => JS('', '#[#] = #', f, _setterSig, sigF);
+
+// Set up the constructor signature field on the constructor
+void setConstructorSignature(f, sigF) =>
+    JS('', '#[#] = #', f, _constructorSig, sigF);
+
+// Set up the static signature field on the constructor
+void setStaticMethodSignature(f, sigF) =>
+    JS('', '#[#] = #', f, _staticMethodSig, sigF);
+
+void setStaticFieldSignature(f, sigF) =>
+    JS('', '#[#] = #', f, _staticFieldSig, sigF);
+
+void setStaticGetterSignature(f, sigF) =>
+    JS('', '#[#] = #', f, _staticGetterSig, sigF);
+
+void setStaticSetterSignature(f, sigF) =>
+    JS('', '#[#] = #', f, _staticSetterSig, sigF);
+
+_getMembers(type, kind) {
+  var sig = JS('', '#[#]', type, kind);
+  return JS<bool>('!', 'typeof # == "function"', sig)
+      ? JS('', '#[#] = #()', type, kind, sig)
+      : sig;
+}
+
+bool _hasMember(type, kind, name) {
+  var sig = _getMembers(type, kind);
+  return sig != null && JS<bool>('!', '# in #', name, sig);
+}
+
+bool hasMethod(type, name) => _hasMember(type, _methodSig, name);
+bool hasGetter(type, name) => _hasMember(type, _getterSig, name);
+bool hasSetter(type, name) => _hasMember(type, _setterSig, name);
+bool hasField(type, name) => _hasMember(type, _fieldSig, name);
+
+final _extensionType = JS('', 'Symbol("extensionType")');
+
+final dartx = JS('', 'dartx');
+
+/// Install properties in prototype-first order.  Properties / descriptors from
+/// more specific types should overwrite ones from less specific types.
+void _installProperties(jsProto, dartType, installedParent) {
+  if (JS('!', '# === #', dartType, Object)) {
+    _installPropertiesForObject(jsProto);
+    return;
+  }
+  // If the extension methods of the parent have been installed on the parent
+  // of [jsProto], the methods will be available via prototype inheritance.
+  var dartSupertype = JS('', '#.__proto__', dartType);
+  if (JS('!', '# !== #', dartSupertype, installedParent)) {
+    _installProperties(jsProto, dartSupertype, installedParent);
+  }
+
+  var dartProto = JS('', '#.prototype', dartType);
+  copyTheseProperties(jsProto, dartProto, getOwnPropertySymbols(dartProto));
+}
+
+void _installPropertiesForObject(jsProto) {
+  // core.Object members need to be copied from the non-symbol name to the
+  // symbol name.
+  var coreObjProto = JS('', '#.prototype', Object);
+  var names = getOwnPropertyNames(coreObjProto);
+  for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) {
+    var name = JS<String>('!', '#[#]', names, i);
+    if (name == 'constructor') continue;
+    var desc = getOwnPropertyDescriptor(coreObjProto, name);
+    defineProperty(jsProto, JS('', '#.#', dartx, name), desc);
+  }
+}
+
+void _installPropertiesForGlobalObject(jsProto) {
+  _installPropertiesForObject(jsProto);
+  // Use JS toString for JS objects, rather than the Dart one.
+  JS('', '#[dartx.toString] = function() { return this.toString(); }', jsProto);
+  identityEquals ??= JS('', '#[dartx._equals]', jsProto);
+}
+
+final _extensionMap = JS('', 'new Map()');
+
+_applyExtension(jsType, dartExtType) {
+  // TODO(vsm): Not all registered js types are real.
+  if (jsType == null) return;
+  var jsProto = JS('', '#.prototype', jsType);
+  if (jsProto == null) return;
+
+  if (JS('!', '# === #', dartExtType, Object)) {
+    _installPropertiesForGlobalObject(jsProto);
+    return;
+  }
+
+  _installProperties(
+      jsProto, dartExtType, JS('', '#[#]', jsProto, _extensionType));
+
+  // Mark the JS type's instances so we can easily check for extensions.
+  if (JS('!', '# !== #', dartExtType, JSFunction)) {
+    JS('', '#[#] = #', jsProto, _extensionType, dartExtType);
+  }
+  JS('', '#[#] = #[#]', jsType, _methodSig, dartExtType, _methodSig);
+  JS('', '#[#] = #[#]', jsType, _fieldSig, dartExtType, _fieldSig);
+  JS('', '#[#] = #[#]', jsType, _getterSig, dartExtType, _getterSig);
+  JS('', '#[#] = #[#]', jsType, _setterSig, dartExtType, _setterSig);
+}
+
+/// Apply the previously registered extension to the type of [nativeObject].
+/// This is intended for types that are not available to polyfill at startup.
+applyExtension(name, nativeObject) {
+  var dartExtType = JS('', '#.get(#)', _extensionMap, name);
+  var jsType = JS('', '#.constructor', nativeObject);
+  _applyExtension(jsType, dartExtType);
+}
+
+/// Apply all registered extensions to a window.  This is intended for
+/// different frames, where registrations need to be reapplied.
+applyAllExtensions(global) {
+  JS('', '#.forEach((dartExtType, name) => #(#[name], dartExtType))',
+      _extensionMap, _applyExtension, global);
+}
+
+/// Copy symbols from the prototype of the source to destination.
+/// These are the only properties safe to copy onto an existing public
+/// JavaScript class.
+registerExtension(name, dartExtType) {
+  JS('', '#.set(#, #)', _extensionMap, name, dartExtType);
+  var jsType = JS('', '#[#]', global_, name);
+  _applyExtension(jsType, dartExtType);
+}
+
+///
+/// Mark a concrete type as implementing extension methods.
+/// For example: `class MyIter implements Iterable`.
+///
+/// This takes a list of names, which are the extension methods implemented.
+/// It will add a forwarder, so the extension method name redirects to the
+/// normal Dart method name. For example:
+///
+///     defineExtensionMembers(MyType, ['add', 'remove']);
+///
+/// Results in:
+///
+///     MyType.prototype[dartx.add] = MyType.prototype.add;
+///     MyType.prototype[dartx.remove] = MyType.prototype.remove;
+///
+// TODO(jmesserly): essentially this gives two names to the same method.
+// This benefit is roughly equivalent call performance either way, but the
+// cost is we need to call defineExtensionMembers any time a subclass
+// overrides one of these methods.
+defineExtensionMethods(type, Iterable memberNames) {
+  var proto = JS('', '#.prototype', type);
+  for (var name in memberNames) {
+    JS('', '#[dartx.#] = #[#]', proto, name, proto, name);
+  }
+}
+
+/// Like [defineExtensionMethods], but for getter/setter pairs.
+defineExtensionAccessors(type, Iterable memberNames) {
+  var proto = JS('', '#.prototype', type);
+  for (var name in memberNames) {
+    // Find the member. It should always exist (or we have a compiler bug).
+    var member;
+    var p = proto;
+    for (;; p = JS('', '#.__proto__', p)) {
+      member = getOwnPropertyDescriptor(p, name);
+      if (member != null) break;
+    }
+    defineProperty(proto, JS('', 'dartx[#]', name), member);
+  }
+}
+
+definePrimitiveHashCode(proto) {
+  defineProperty(proto, identityHashCode_,
+      getOwnPropertyDescriptor(proto, extensionSymbol('hashCode')));
+}
+
+/// Link the extension to the type it's extending as a base class.
+setBaseClass(derived, base) {
+  JS('', '#.prototype.__proto__ = #.prototype', derived, base);
+  // We use __proto__ to track the superclass hierarchy (see isSubtypeOf).
+  JS('', '#.__proto__ = #', derived, base);
+}
+
+/// Like [setBaseClass], but for generic extension types such as `JSArray<E>`.
+setExtensionBaseClass(dartType, jsType) {
+  // Mark the generic type as an extension type and link the prototype objects.
+  var dartProto = JS('', '#.prototype', dartType);
+  JS('', '#[#] = #', dartProto, _extensionType, dartType);
+  JS('', '#.__proto__ = #.prototype', dartProto, jsType);
+}
+
+/// Adds type test predicates to a class/interface type [ctor], using the
+/// provided [isClass] JS Symbol.
+///
+/// This will operate quickly for non-generic types, native extension types,
+/// as well as matching exact generic type arguments:
+///
+///     class C<T> {}
+///     class D extends C<int> {}
+///     main() { dynamic d = new D(); d as C<int>; }
+///
+addTypeTests(ctor, isClass) {
+  if (isClass == null) isClass = JS('', 'Symbol("_is_" + ctor.name)');
+  // TODO(jmesserly): since we know we're dealing with class/interface types,
+  // we can optimize this rather than go through the generic `dart.is` helpers.
+  JS('', '#.prototype[#] = true', ctor, isClass);
+  JS(
+      '',
+      '''#.is = function is_C(obj) {
+    return obj != null && (obj[#] || #(obj, this));
+  }''',
+      ctor,
+      isClass,
+      instanceOf);
+  JS(
+      '',
+      '''#.as = function as_C(obj) {
+    if (obj == null || obj[#]) return obj;
+    return #(obj, this, false);
+  }''',
+      ctor,
+      isClass,
+      cast);
+  JS(
+      '',
+      '''#._check = function check_C(obj) {
+    if (obj == null || obj[#]) return obj;
+    return #(obj, this, true);
+  }''',
+      ctor,
+      isClass,
+      cast);
+}
+
+// TODO(jmesserly): should we do this for all interfaces?
+
+/// The well known symbol for testing `is Future`
+final isFuture = JS('', 'Symbol("_is_Future")');
+
+/// The well known symbol for testing `is Iterable`
+final isIterable = JS('', 'Symbol("_is_Iterable")');
+
+/// The well known symbol for testing `is List`
+final isList = JS('', 'Symbol("_is_List")');
+
+/// The well known symbol for testing `is Map`
+final isMap = JS('', 'Symbol("_is_Map")');
+
+/// The well known symbol for testing `is Stream`
+final isStream = JS('', 'Symbol("_is_Stream")');
+
+/// The well known symbol for testing `is StreamSubscription`
+final isStreamSubscription = JS('', 'Symbol("_is_StreamSubscription")');
+
+/// The default `operator ==` that calls [identical].
+var identityEquals;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
new file mode 100644
index 0000000..d4cec70
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
@@ -0,0 +1,296 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart._runtime;
+
+// We need to set these properties while the sdk is only partially initialized
+// so we cannot use regular Dart fields.
+// The default values for these properties are set when the global_ final field
+// in runtime.dart is initialized.
+
+// Override, e.g., for testing
+void trapRuntimeErrors(bool flag) {
+  JS('', 'dart.__trapRuntimeErrors = #', flag);
+}
+
+void ignoreWhitelistedErrors(bool flag) {
+  JS('', 'dart.__ignoreWhitelistedErrors = #', flag);
+}
+
+// TODO(jmesserly): remove this?
+void ignoreAllErrors(bool flag) {
+  JS('', 'dart.__ignoreAllErrors = #', flag);
+}
+
+argumentError(value) {
+  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+  throw ArgumentError.value(value);
+}
+
+throwUnimplementedError(String message) {
+  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+  throw UnimplementedError(message);
+}
+
+// TODO(nshahan) Cleanup embeded strings and extract file location at runtime
+// from the stacktrace.
+assertFailed(String message,
+    [String fileUri, int line, int column, String conditionSource]) {
+  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+
+  throw AssertionErrorImpl(message, fileUri, line, column, conditionSource);
+}
+
+throwCyclicInitializationError([Object field]) {
+  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+  throw CyclicInitializationError(field);
+}
+
+throwNullValueError() {
+  // TODO(vsm): Per spec, we should throw an NSM here.  Technically, we ought
+  // to thread through method info, but that uglifies the code and can't
+  // actually be queried ... it only affects how the error is printed.
+  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+  throw NoSuchMethodError(
+      null, Symbol('<Unexpected Null Value>'), null, null, null);
+}
+
+castError(obj, expectedType, [@notNull bool isImplicit = false]) {
+  var actualType = getReifiedType(obj);
+  var message = _castErrorMessage(actualType, expectedType);
+  if (JS('!', 'dart.__ignoreAllErrors')) {
+    JS('', 'console.error(#)', message);
+    return obj;
+  }
+  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+  var error = isImplicit ? TypeErrorImpl(message) : CastErrorImpl(message);
+  throw error;
+}
+
+String _castErrorMessage(from, to) {
+  // If both types are generic classes, see if we can infer generic type
+  // arguments for `from` that would allow the subtype relation to work.
+  var fromClass = getGenericClass(from);
+  if (fromClass != null) {
+    var fromTypeFormals = getGenericTypeFormals(fromClass);
+    var fromType = instantiateClass(fromClass, fromTypeFormals);
+    var inferrer = _TypeInferrer(fromTypeFormals);
+    if (inferrer.trySubtypeMatch(fromType, to)) {
+      var inferredTypes = inferrer.getInferredTypes();
+      if (inferredTypes != null) {
+        var inferred = instantiateClass(fromClass, inferredTypes);
+        return "Type '${typeName(from)}' should be '${typeName(inferred)}' "
+            "to implement expected type '${typeName(to)}'.";
+      }
+    }
+  }
+  return "Expected a value of type '${typeName(to)}', "
+      "but got one of type '${typeName(from)}'";
+}
+
+/// The symbol that references the thrown Dart Object (typically but not
+/// necessarily an [Error] or [Exception]), used by the [exception] function.
+final Object _thrownValue = JS('', 'Symbol("_thrownValue")');
+
+/// For a Dart [Error], this provides access to the JS Error object that
+/// contains the stack trace if the error was thrown.
+final Object _jsError = JS('', 'Symbol("_jsError")');
+
+/// Gets the thrown Dart Object from an [error] caught by a JS catch.
+///
+/// If the throw originated in Dart, the result will typically be an [Error]
+/// or [Exception], but it could be any Dart object.
+///
+/// If the throw originated in JavaScript, then there is not a corresponding
+/// Dart value, so we just return the error object.
+Object getThrown(Object error) {
+  if (error != null) {
+    // Get the Dart thrown value, if any.
+    var value = JS('', '#[#]', error, _thrownValue);
+    if (value != null) return value;
+  }
+  // Otherwise return the original object.
+  return error;
+}
+
+final _stackTrace = JS('', 'Symbol("_stackTrace")');
+
+/// Returns the stack trace from an [error] caught by a JS catch.
+///
+/// If the throw originated in Dart, we should always have JS Error
+/// (see [throw_]) so we can create a Dart [StackTrace] from that (or return a
+/// previously created instance).
+///
+/// If the throw originated in JavaScript and was an `Error`, then we can get
+/// the corresponding stack trace the same way we do for Dart throws. If the
+/// throw object was not an Error, then we don't have a JS trace, so we create
+/// one here.
+StackTrace stackTrace(Object error) {
+  if (JS<bool>('!', '!(# instanceof Error)', error)) {
+    // We caught something that isn't a JS Error.
+    //
+    // We should only hit this path when a non-Error was thrown from JS. In
+    // case, there is no stack trace available, so create one here.
+    return _StackTrace.missing(error);
+  }
+
+  // If we've already created the Dart stack trace object, return it.
+  StackTrace trace = JS('', '#[#]', error, _stackTrace);
+  if (trace != null) return trace;
+
+  // Otherwise create the Dart stack trace (by parsing the JS stack), and
+  // cache it so we don't repeat the parsing/allocation.
+  return JS('', '#[#] = #', error, _stackTrace, _StackTrace(error));
+}
+
+StackTrace stackTraceForError(Error error) {
+  return stackTrace(JS('', '#[#]', error, _jsError));
+}
+
+/// Implements `rethrow` of [error], allowing rethrow in an expression context.
+///
+/// Note: [error] must be the raw JS error caught in the JS catch, not the
+/// unwrapped value returned by [getThrown].
+@JSExportName('rethrow')
+void rethrow_(Object error) {
+  JS('', 'throw #', error);
+}
+
+/// Subclass of JS `Error` that wraps a thrown Dart object, and evaluates the
+/// message lazily by calling `toString()` on the wrapped Dart object.
+///
+/// Also creates a pointer from the thrown Dart object to the JS Error
+/// (via [_jsError]). This is used to implement [Error.stackTrace], but also
+/// provides a way to recover the stack trace if we lose track of it.
+/// [Error] requires preserving the original stack trace if an error is
+/// rethrown, so we only update the pointer if it wasn't already set.
+///
+/// TODO(jmesserly): Dart Errors should simply be JS Errors.
+final Object DartError = JS(
+    '!',
+    '''class DartError extends Error {
+      constructor(error) {
+        super();
+        if (error == null) error = #;
+        this[#] = error;
+        if (error != null && typeof error == "object" && error[#] == null) {
+          error[#] = this;
+        }
+      }
+      get message() {
+        return #(this[#]);
+      }
+    }''',
+    NullThrownError(),
+    _thrownValue,
+    _jsError,
+    _jsError,
+    _toString,
+    _thrownValue);
+
+/// Subclass of [DartError] for cases where we're rethrowing with a different,
+/// original Dart StackTrace object.
+///
+/// This includes the original stack trace in the JS Error message so it doesn't
+/// get lost if the exception reaches JS.
+final Object RethrownDartError = JS(
+    '!',
+    '''class RethrownDartError extends # {
+      constructor(error, stackTrace) {
+        super(error);
+        this[#] = stackTrace;
+      }
+      get message() {
+        return super.message + "\\n    " + #(this[#]) + "\\n";
+      }
+    }''',
+    DartError,
+    _stackTrace,
+    _toString,
+    _stackTrace);
+
+/// Implements `throw` of [exception], allowing for throw in an expression
+/// context, and capturing the current stack trace.
+@JSExportName('throw')
+void throw_(Object exception) {
+  /// Wrap the object so we capture a new stack trace, and so it will print
+  /// nicely from JS, as if it were a normal JS error.
+  JS('', 'throw new #(#)', DartError, exception);
+}
+
+/// Returns a JS error for throwing the Dart [exception] Object and using the
+/// provided stack [trace].
+///
+/// This is used by dart:async to rethrow unhandled errors in [Zone]s, and by
+/// `async`/`async*` to rethrow errors from Futures/Streams into the generator
+/// (so a try/catch in there can catch it).
+///
+/// If the exception and trace originated from the same Dart throw, then we can
+/// simply return the original JS Error. Otherwise, we have to create a new JS
+/// Error. The new error will have the correct Dart trace, but it will not have
+/// the correct JS stack trace (visible if JavaScript ends up handling it). To
+/// fix that, we use [RethrownDartError] to preserve the Dart trace and make
+/// sure it gets displayed in the JS error message.
+///
+/// If the stack trace is null, this will preserve the original stack trace
+/// on the exception, if available, otherwise it will capture the current stack
+/// trace.
+Object createErrorWithStack(Object exception, StackTrace trace) {
+  if (trace == null) {
+    var error = JS('', '#[#]', exception, _jsError);
+    return error != null ? error : JS('', 'new #(#)', DartError, exception);
+  }
+  if (trace is _StackTrace) {
+    /// Optimization: if this stack trace and exception already have a matching
+    /// Error, we can just rethrow it.
+    var originalError = trace._jsError;
+    if (identical(exception, getThrown(originalError))) {
+      return originalError;
+    }
+  }
+  return JS('', 'new #(#, #)', RethrownDartError, exception, trace);
+}
+
+// This is a utility function: it is only intended to be called from dev
+// tools.
+void stackPrint(Object error) {
+  JS('', 'console.log(#.stack ? #.stack : "No stack trace for: " + #)', error,
+      error, error);
+}
+
+class _StackTrace implements StackTrace {
+  final Object _jsError;
+  final Object _jsObjectMissingTrace;
+  String _trace;
+
+  _StackTrace(this._jsError) : _jsObjectMissingTrace = null;
+
+  _StackTrace.missing(Object caughtObj)
+      : _jsObjectMissingTrace = caughtObj != null ? caughtObj : 'null',
+        _jsError = JS('', 'Error()');
+
+  String toString() {
+    if (_trace != null) return _trace;
+
+    var e = _jsError;
+    String trace = '';
+    if (e != null && JS('bool', 'typeof # === "object"', e)) {
+      trace = e is NativeError ? e.dartStack() : JS<String>('', '#.stack', e);
+      if (trace != null && stackTraceMapper != null) {
+        trace = stackTraceMapper(trace);
+      }
+    }
+    if (trace.isEmpty || _jsObjectMissingTrace != null) {
+      String jsToString;
+      try {
+        jsToString = JS('', '"" + #', _jsObjectMissingTrace);
+      } catch (_) {
+        jsToString = '<error converting JS object to string>';
+      }
+      trace = 'Non-error `$jsToString` thrown by JS does not have stack trace.'
+          '\nCaught in Dart at:\n\n$trace';
+    }
+    return _trace = trace;
+  }
+}
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
new file mode 100644
index 0000000..0c287ae
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
@@ -0,0 +1,782 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library defines runtime operations on objects used by the code
+/// generator.
+part of dart._runtime;
+
+// TODO(jmesserly): remove this in favor of _Invocation.
+class InvocationImpl extends Invocation {
+  final Symbol memberName;
+  final List positionalArguments;
+  final Map<Symbol, dynamic> namedArguments;
+  final List<Type> typeArguments;
+  final bool isMethod;
+  final bool isGetter;
+  final bool isSetter;
+  final String failureMessage;
+
+  InvocationImpl(memberName, List<Object> positionalArguments,
+      {namedArguments,
+      List typeArguments,
+      this.isMethod = false,
+      this.isGetter = false,
+      this.isSetter = false,
+      this.failureMessage = 'method not found'})
+      : memberName =
+            isSetter ? _setterSymbol(memberName) : _dartSymbol(memberName),
+        positionalArguments = List.unmodifiable(positionalArguments),
+        namedArguments = _namedArgsToSymbols(namedArguments),
+        typeArguments = typeArguments == null
+            ? const []
+            : List.unmodifiable(typeArguments.map(wrapType));
+
+  static Map<Symbol, dynamic> _namedArgsToSymbols(namedArgs) {
+    if (namedArgs == null) return const {};
+    return Map.unmodifiable(Map.fromIterable(getOwnPropertyNames(namedArgs),
+        key: _dartSymbol, value: (k) => JS('', '#[#]', namedArgs, k)));
+  }
+}
+
+/// Given an object and a method name, tear off the method.
+/// Sets the runtime type of the torn off method appropriately,
+/// and also binds the object.
+///
+/// If the optional `f` argument is passed in, it will be used as the method.
+/// This supports cases like `super.foo` where we need to tear off the method
+/// from the superclass, not from the `obj` directly.
+// TODO(leafp): Consider caching the tearoff on the object?
+bind(obj, name, method) {
+  if (obj == null) obj = jsNull;
+  if (method == null) method = JS('', '#[#]', obj, name);
+  var f = JS('', '#.bind(#)', method, obj);
+  // TODO(jmesserly): canonicalize tearoffs.
+  JS('', '#._boundObject = #', f, obj);
+  JS('', '#._boundMethod = #', f, method);
+  JS('', '#[#] = #', f, _runtimeType, getMethodType(getType(obj), name));
+  return f;
+}
+
+/// Binds the `call` method of an interface type, handling null.
+///
+/// Essentially this works like `obj?.call`. It also handles the needs of
+/// [dsend]/[dcall], returning `null` if no method was found with the given
+/// canonical member [name].
+///
+/// [name] is typically `"call"` but it could be the [extensionSymbol] for
+/// `call`, if we define it on a native type, and [obj] is known statially to be
+/// a native type/interface with `call`.
+bindCall(obj, name) {
+  if (obj == null) return null;
+  var ftype = getMethodType(getType(obj), name);
+  if (ftype == null) return null;
+  var method = JS('', '#[#]', obj, name);
+  var f = JS('', '#.bind(#)', method, obj);
+  // TODO(jmesserly): canonicalize tearoffs.
+  JS('', '#._boundObject = #', f, obj);
+  JS('', '#._boundMethod = #', f, method);
+  JS('', '#[#] = #', f, _runtimeType, ftype);
+  return f;
+}
+
+/// Instantiate a generic method.
+///
+/// We need to apply the type arguments both to the function, as well as its
+/// associated function type.
+gbind(f, @rest List typeArgs) {
+  GenericFunctionType type = JS('!', '#[#]', f, _runtimeType);
+  type.checkBounds(typeArgs);
+  // Create a JS wrapper function that will also pass the type arguments, and
+  // tag it with the instantiated function type.
+  var result =
+      JS('', '(...args) => #.apply(null, #.concat(args))', f, typeArgs);
+  return fn(result, type.instantiate(typeArgs));
+}
+
+dloadRepl(obj, field) => dload(obj, replNameLookup(obj, field), false);
+
+// Warning: dload, dput, and dsend assume they are never called on methods
+// implemented by the Object base class as those methods can always be
+// statically resolved.
+dload(obj, field, [@undefined mirrors]) {
+  if (JS('!', 'typeof # == "function" && # == "call"', obj, field)) {
+    return obj;
+  }
+  var f = _canonicalMember(obj, field);
+
+  trackCall(obj);
+  if (f != null) {
+    var type = getType(obj);
+
+    if (hasField(type, f) || hasGetter(type, f)) return JS('', '#[#]', obj, f);
+    if (hasMethod(type, f)) return bind(obj, f, null);
+
+    // Always allow for JS interop objects.
+    if (!JS<bool>('!', '#', mirrors) && isJsInterop(obj)) {
+      return JS('', '#[#]', obj, f);
+    }
+  }
+  return noSuchMethod(obj, InvocationImpl(field, JS('', '[]'), isGetter: true));
+}
+
+// Version of dload that matches legacy mirrors behavior for JS types.
+dloadMirror(obj, field) => dload(obj, field, true);
+
+_stripGenericArguments(type) {
+  var genericClass = getGenericClass(type);
+  if (genericClass != null) return JS('', '#()', genericClass);
+  return type;
+}
+
+// Version of dput that matches legacy Dart 1 type check rules and mirrors
+// behavior for JS types.
+// TODO(jacobr): remove the type checking rules workaround when mirrors based
+// PageLoader code can generate the correct reified generic types.
+dputMirror(obj, field, value) => dput(obj, field, value, true);
+
+dputRepl(obj, field, value) =>
+    dput(obj, replNameLookup(obj, field), value, false);
+
+dput(obj, field, value, [@undefined mirrors]) {
+  var f = _canonicalMember(obj, field);
+  trackCall(obj);
+  if (f != null) {
+    var setterType = getSetterType(getType(obj), f);
+    if (setterType != null) {
+      if (JS('!', '#', mirrors))
+        setterType = _stripGenericArguments(setterType);
+      return JS('', '#[#] = #._check(#)', obj, f, setterType, value);
+    }
+    // Always allow for JS interop objects.
+    if (!JS<bool>('!', '#', mirrors) && isJsInterop(obj)) {
+      return JS('', '#[#] = #', obj, f, value);
+    }
+  }
+  noSuchMethod(
+      obj, InvocationImpl(field, JS('', '[#]', value), isSetter: true));
+  return value;
+}
+
+/// Returns an error message if function of a given [type] can't be applied to
+/// [actuals] and [namedActuals].
+///
+/// Returns `null` if all checks pass.
+String _argumentErrors(FunctionType type, List actuals, namedActuals) {
+  // Check for too few required arguments.
+  int actualsCount = JS('!', '#.length', actuals);
+  var required = type.args;
+  int requiredCount = JS('!', '#.length', required);
+  if (actualsCount < requiredCount) {
+    return 'Dynamic call with too few arguments. '
+        'Expected: $requiredCount Actual: $actualsCount';
+  }
+
+  // Check for too many postional arguments.
+  var extras = actualsCount - requiredCount;
+  var optionals = type.optionals;
+  if (extras > JS<int>('!', '#.length', optionals)) {
+    return 'Dynamic call with too many arguments. '
+        'Expected: $requiredCount Actual: $actualsCount';
+  }
+
+  // Check if we have invalid named arguments.
+  Iterable names;
+  var named = type.named;
+  if (namedActuals != null) {
+    names = getOwnPropertyNames(namedActuals);
+    for (var name in names) {
+      if (!JS('!', '#.hasOwnProperty(#)', named, name)) {
+        return "Dynamic call with unexpected named argument '$name'.";
+      }
+    }
+  }
+  // Now that we know the signature matches, we can perform type checks.
+  for (var i = 0; i < requiredCount; ++i) {
+    JS('', '#[#]._check(#[#])', required, i, actuals, i);
+  }
+  for (var i = 0; i < extras; ++i) {
+    JS('', '#[#]._check(#[#])', optionals, i, actuals, i + requiredCount);
+  }
+  if (names != null) {
+    for (var name in names) {
+      JS('', '#[#]._check(#[#])', named, name, namedActuals, name);
+    }
+  }
+  return null;
+}
+
+_toSymbolName(symbol) => JS('', '''(() => {
+        let str = $symbol.toString();
+        // Strip leading 'Symbol(' and trailing ')'
+        return str.substring(7, str.length-1);
+    })()''');
+
+_toDisplayName(name) => JS('', '''(() => {
+      // Names starting with _ are escaped names used to disambiguate Dart and
+      // JS names.
+      if ($name[0] === '_') {
+        // Inverse of
+        switch($name) {
+          case '_get':
+            return '[]';
+          case '_set':
+            return '[]=';
+          case '_negate':
+            return 'unary-';
+          case '_constructor':
+          case '_prototype':
+            return $name.substring(1);
+        }
+      }
+      return $name;
+  })()''');
+
+Symbol _dartSymbol(name) {
+  return (JS<bool>('!', 'typeof # === "symbol"', name))
+      ? JS('Symbol', '#(new #.new(#, #))', const_, PrivateSymbol,
+          _toSymbolName(name), name)
+      : JS('Symbol', '#(new #.new(#))', const_, internal.Symbol,
+          _toDisplayName(name));
+}
+
+Symbol _setterSymbol(name) {
+  return (JS<bool>('!', 'typeof # === "symbol"', name))
+      ? JS('Symbol', '#(new #.new(# + "=", #))', const_, PrivateSymbol,
+          _toSymbolName(name), name)
+      : JS('Symbol', '#(new #.new(# + "="))', const_, internal.Symbol,
+          _toDisplayName(name));
+}
+
+_checkAndCall(f, ftype, obj, typeArgs, args, named, displayName) =>
+    JS('', '''(() => {
+  $trackCall($obj);
+
+  let originalTarget = obj === void 0 ? f : obj;
+
+  function callNSM(errorMessage) {
+    return $noSuchMethod(originalTarget, new $InvocationImpl.new(
+        $displayName, $args, {
+          namedArguments: $named,
+          typeArguments: $typeArgs,
+          isMethod: true,
+          failureMessage: errorMessage
+        }));
+  }
+  if ($f == null) return callNSM('Dynamic call of null.');
+  if (!($f instanceof Function)) {
+    // We're not a function (and hence not a method either)
+    // Grab the `call` method if it's not a function.
+    if ($f != null) {
+      // Getting the member succeeded, so update the originalTarget.
+      // (we're now trying `call()` on `f`, so we want to call its nSM rather
+      // than the original target's nSM).
+      originalTarget = f;
+      $f = ${bindCall(f, _canonicalMember(f, 'call'))};
+      $ftype = null;
+    }
+    if ($f == null) return callNSM(
+        "Dynamic call of object has no instance method 'call'.");
+  }
+  // If f is a function, but not a method (no method type)
+  // then it should have been a function valued field, so
+  // get the type from the function.
+  if ($ftype == null) $ftype = $f[$_runtimeType];
+
+  if ($ftype == null) {
+    // TODO(leafp): Allow JS objects to go through?
+    if ($typeArgs != null) {
+      // TODO(jmesserly): is there a sensible way to handle these?
+      $throwTypeError('call to JS object `' + $obj +
+          '` with type arguments <' + $typeArgs + '> is not supported.');
+    }
+
+    if ($named != null) $args.push($named);
+    return $f.apply($obj, $args);
+  }
+
+  // TODO(vsm): Remove when we no longer need mirrors metadata.
+  // An array is used to encode annotations attached to the type.
+  if ($ftype instanceof Array) $ftype = $ftype[0];
+
+  // Apply type arguments
+  if ($ftype instanceof $GenericFunctionType) {
+    let formalCount = $ftype.formalCount;
+
+    if ($typeArgs == null) {
+      $typeArgs = $ftype.instantiateDefaultBounds();
+    } else if ($typeArgs.length != formalCount) {
+      return callNSM('Dynamic call with incorrect number of type arguments. ' +
+          'Expected: ' + formalCount + ' Actual: ' + $typeArgs.length);
+    } else {
+      $ftype.checkBounds($typeArgs);
+    }
+    $ftype = $ftype.instantiate($typeArgs);
+  } else if ($typeArgs != null) {
+    return callNSM('Dynamic call with unexpected type arguments. ' +
+        'Expected: 0 Actual: ' + $typeArgs.length);
+  }
+  let errorMessage = $_argumentErrors($ftype, $args, $named);
+  if (errorMessage == null) {
+    if ($typeArgs != null) $args = $typeArgs.concat($args);
+    if ($named != null) $args.push($named);
+    return $f.apply($obj, $args);
+  }
+  return callNSM(errorMessage);
+})()''');
+
+dcall(f, args, [@undefined named]) =>
+    _checkAndCall(f, null, JS('', 'void 0'), null, args, named, 'call');
+
+dgcall(f, typeArgs, args, [@undefined named]) =>
+    _checkAndCall(f, null, JS('', 'void 0'), typeArgs, args, named, 'call');
+
+/// Helper for REPL dynamic invocation variants that make a best effort to
+/// enable accessing private members across library boundaries.
+replNameLookup(object, field) => JS('', '''(() => {
+  let rawField = $field;
+  if (typeof(field) == 'symbol') {
+    // test if the specified field exists in which case it is safe to use it.
+    if ($field in $object) return $field;
+
+    // Symbol is from a different library. Make a best effort to
+    $field = $field.toString();
+    $field = $field.substring('Symbol('.length, field.length - 1);
+
+  } else if ($field.charAt(0) != '_') {
+    // Not a private member so default call path is safe.
+    return $field;
+  }
+
+  // If the exact field name is present, invoke callback with it.
+  if ($field in $object) return $field;
+
+  // TODO(jacobr): warn if there are multiple private members with the same
+  // name which could happen if super classes in different libraries have
+  // the same private member name.
+  let proto = $object;
+  while (proto !== null) {
+    // Private field (indicated with "_").
+    let symbols = Object.getOwnPropertySymbols(proto);
+    let target = 'Symbol(' + $field + ')';
+
+    for (let s = 0; s < symbols.length; s++) {
+      let sym = symbols[s];
+      if (target == sym.toString()) return sym;
+    }
+    proto = proto.__proto__;
+  }
+  // We didn't find a plausible alternate private symbol so just fall back
+  // to the regular field.
+  return rawField;
+})()''');
+
+// TODO(jmesserly): the debugger extension hardcodes a call to this private
+// function. Fix that.
+@Deprecated('use replNameLookup')
+_dhelperRepl(obj, field, Function(Object) callback) {
+  return callback(replNameLookup(obj, field));
+}
+
+/// Shared code for dsend, dindex, and dsetindex.
+callMethod(obj, name, typeArgs, args, named, displayName) {
+  if (JS('!', 'typeof # == "function" && # == "call"', obj, name)) {
+    return dgcall(obj, typeArgs, args, named);
+  }
+  var symbol = _canonicalMember(obj, name);
+  if (symbol == null) {
+    return noSuchMethod(obj, InvocationImpl(displayName, args, isMethod: true));
+  }
+  var f = obj != null ? JS('', '#[#]', obj, symbol) : null;
+  var type = getType(obj);
+  var ftype = getMethodType(type, symbol);
+  // No such method if dart object and ftype is missing.
+  return _checkAndCall(f, ftype, obj, typeArgs, args, named, displayName);
+}
+
+dsend(obj, method, args, [@undefined named]) =>
+    callMethod(obj, method, null, args, named, method);
+
+dgsend(obj, typeArgs, method, args, [@undefined named]) =>
+    callMethod(obj, method, typeArgs, args, named, method);
+
+dsendRepl(obj, method, args, [@undefined named]) =>
+    callMethod(obj, replNameLookup(obj, method), null, args, named, method);
+
+dgsendRepl(obj, typeArgs, method, args, [@undefined named]) =>
+    callMethod(obj, replNameLookup(obj, method), typeArgs, args, named, method);
+
+dindex(obj, index) => callMethod(obj, '_get', null, [index], null, '[]');
+
+dsetindex(obj, index, value) =>
+    callMethod(obj, '_set', null, [index, value], null, '[]=');
+
+final _ignoreSubtypeCache = JS('', 'new Map()');
+
+/// Whether [t1] <: [t2], or if [isImplicit] is set and we should ignore the
+/// cast failure from t1 to t2.
+///
+/// See [_isSubtypeOrLegacySubtype] and [ignoreWhitelistedErrors].
+@notNull
+bool _isSubtypeOrIgnorableCastFailure(
+    Object t1, Object t2, @notNull bool isImplicit) {
+  var result = _isSubtypeOrLegacySubtype(t1, t2);
+  return result == true ||
+      result == null &&
+          isImplicit &&
+          JS<bool>('!', 'dart.__ignoreWhitelistedErrors') &&
+          _ignoreTypeFailure(t1, t2);
+}
+
+@notNull
+bool _ignoreTypeFailure(Object t1, Object t2) {
+  var map = JS('', '#.get(#)', _ignoreSubtypeCache, t1);
+  if (map != null) {
+    bool result = JS('', '#.get(#)', map, t2);
+    if (JS('!', '# !== void 0', result)) return result;
+  } else {
+    map = JS('', 'new Map()');
+    JS('', '#.set(#, #)', _ignoreSubtypeCache, t1, map);
+  }
+
+  // TODO(vsm): Remove this hack ...
+  // This is primarily due to the lack of generic methods,
+  // but we need to triage all the types.
+  @notNull
+  bool result;
+  if (_isFutureOr(t2)) {
+    // Ignore if we would ignore either side of union.
+    var typeArg = getGenericArgs(t2)[0];
+    var typeFuture = JS('', '#(#)', getGenericClass(Future), typeArg);
+    result =
+        _ignoreTypeFailure(t1, typeFuture) || _ignoreTypeFailure(t1, typeArg);
+  } else {
+    result = isSubtypeOf(t2, unwrapType(Iterable)) &&
+        isSubtypeOf(t1, unwrapType(Iterable));
+    if (result) {
+      _warn('Ignoring cast fail from ${typeName(t1)} to ${typeName(t2)}');
+    }
+  }
+  JS('', '#.set(#, #)', map, t2, result);
+  return result;
+}
+
+@notNull
+@JSExportName('is')
+bool instanceOf(obj, type) {
+  if (obj == null) {
+    return identical(type, unwrapType(Null)) || _isTop(type);
+  }
+  return isSubtypeOf(getReifiedType(obj), type);
+}
+
+@JSExportName('as')
+cast(obj, type, @notNull bool isImplicit) {
+  if (obj == null) return obj;
+  var actual = getReifiedType(obj);
+  if (_isSubtypeOrIgnorableCastFailure(actual, type, isImplicit)) {
+    return obj;
+  }
+  return castError(obj, type, isImplicit);
+}
+
+bool test(bool obj) {
+  if (obj == null) _throwBooleanConversionError();
+  return obj;
+}
+
+bool dtest(obj) {
+  if (obj is! bool) booleanConversionFailed(obj);
+  return obj;
+}
+
+void _throwBooleanConversionError() => throw BooleanConversionAssertionError();
+
+void booleanConversionFailed(obj) {
+  var actual = typeName(getReifiedType(test(obj)));
+  throw TypeErrorImpl("type '$actual' is not a 'bool' in boolean expression");
+}
+
+asInt(obj) {
+  if (obj == null) return null;
+
+  if (JS('!', 'Math.floor(#) != #', obj, obj)) {
+    castError(obj, JS('', '#', int), false);
+  }
+  return obj;
+}
+
+/// Checks that `x` is not null or undefined.
+//
+// TODO(jmesserly): inline this, either by generating it as a function into
+// the module, or via some other pattern such as:
+//
+//     <expr> || nullErr()
+//     (t0 = <expr>) != null ? t0 : nullErr()
+@JSExportName('notNull')
+_notNull(x) {
+  if (x == null) throwNullValueError();
+  return x;
+}
+
+/// The global constant map table.
+final constantMaps = JS('', 'new Map()');
+
+// TODO(leafp): This table gets quite large in apps.
+// Keeping the paths is probably expensive.  It would probably
+// be more space efficient to just use a direct hash table with
+// an appropriately defined structural equality function.
+Object _lookupNonTerminal(Object map, Object key) {
+  var result = JS('', '#.get(#)', map, key);
+  if (result != null) return result;
+  JS('', '#.set(#, # = new Map())', map, key, result);
+  return result;
+}
+
+Map<K, V> constMap<K, V>(JSArray elements) {
+  var count = elements.length;
+  var map = _lookupNonTerminal(constantMaps, count);
+  for (var i = 0; i < count; i++) {
+    map = _lookupNonTerminal(map, JS('', '#[#]', elements, i));
+  }
+  map = _lookupNonTerminal(map, K);
+  var result = JS('', '#.get(#)', map, V);
+  if (result != null) return result;
+  result = ImmutableMap<K, V>.from(elements);
+  JS('', '#.set(#, #)', map, V, result);
+  return result;
+}
+
+final constantSets = JS('', 'new Map()');
+var _immutableSetConstructor;
+
+// We cannot invoke private class constructors directly in Dart.
+Set<E> _createImmutableSet<E>(JSArray<E> elements) {
+  _immutableSetConstructor ??=
+      JS('', '#.#', getLibrary('dart:collection'), '_ImmutableSet\$');
+  return JS('', 'new (#(#)).from(#)', _immutableSetConstructor, E, elements);
+}
+
+Set<E> constSet<E>(JSArray<E> elements) {
+  var count = elements.length;
+  var map = _lookupNonTerminal(constantSets, count);
+  for (var i = 0; i < count; i++) {
+    map = _lookupNonTerminal(map, JS('', '#[#]', elements, i));
+  }
+  var result = JS('', '#.get(#)', map, E);
+  if (result != null) return result;
+  result = _createImmutableSet<E>(elements);
+  JS('', '#.set(#, #)', map, E, result);
+  return result;
+}
+
+bool dassert(value) {
+  if (JS('!', '# != null && #[#] instanceof #', value, value, _runtimeType,
+      AbstractFunctionType)) {
+    value = dcall(value, []);
+  }
+  return dtest(value);
+}
+
+final _value = JS('', 'Symbol("_value")');
+
+///
+/// Looks up a sequence of [keys] in [map], recursively, and
+/// returns the result. If the value is not found, [valueFn] will be called to
+/// add it. For example:
+///
+///     let map = new Map();
+///     putIfAbsent(map, [1, 2, 'hi ', 'there '], () => 'world');
+///
+/// ... will create a Map with a structure like:
+///
+///     { 1: { 2: { 'hi ': { 'there ': 'world' } } } }
+///
+multiKeyPutIfAbsent(map, keys, valueFn) => JS('', '''(() => {
+  for (let k of $keys) {
+    let value = $map.get(k);
+    if (!value) {
+      // TODO(jmesserly): most of these maps are very small (e.g. 1 item),
+      // so it may be worth optimizing for that.
+      $map.set(k, value = new Map());
+    }
+    $map = value;
+  }
+  if ($map.has($_value)) return $map.get($_value);
+  let value = $valueFn();
+  $map.set($_value, value);
+  return value;
+})()''');
+
+/// The global constant table.
+/// This maps the number of names in the object (n)
+/// to a path of length 2*n of maps indexed by the name and
+/// and value of the field.  The final map is
+/// indexed by runtime type, and contains the canonical
+/// version of the object.
+final constants = JS('', 'new Map()');
+
+///
+/// Canonicalize a constant object.
+///
+/// Preconditions:
+/// - `obj` is an objects or array, not a primitive.
+/// - nested values of the object are themselves already canonicalized.
+///
+@JSExportName('const')
+const_(obj) => JS('', '''(() => {  
+  let names = $getOwnNamesAndSymbols($obj);
+  let count = names.length;
+  // Index by count.  All of the paths through this map
+  // will have 2*count length.
+  let map = $_lookupNonTerminal($constants, count);
+  // TODO(jmesserly): there's no guarantee in JS that names/symbols are
+  // returned in the same order.
+  //
+  // We could probably get the same order if we're judicious about
+  // initializing fields in a consistent order across all const constructors.
+  // Alternatively we need a way to sort them to make consistent.
+  //
+  // Right now we use the (name,value) pairs in sequence, which prevents
+  // an object with incorrect field values being returned, but won't
+  // canonicalize correctly if key order is different.
+  //
+  // See issue https://github.com/dart-lang/sdk/issues/30876
+  for (let i = 0; i < count; i++) {
+    let name = names[i];
+    map = $_lookupNonTerminal(map, name);
+    map = $_lookupNonTerminal(map, $obj[name]);
+  }
+  // TODO(leafp): It may be the case that the reified type
+  // is always one of the keys already used above?
+  let type = $getReifiedType($obj);
+  let value = map.get(type);
+  if (value) return value;
+  map.set(type, $obj);
+  return $obj;
+})()''');
+
+/// The global constant list table.
+/// This maps the number of elements in the list (n)
+/// to a path of length n of maps indexed by the value
+/// of the field.  The final map is indexed by the element
+/// type and contains the canonical version of the list.
+final constantLists = JS('', 'new Map()');
+
+/// Canonicalize a constant list
+constList(elements, elementType) => JS('', '''(() => {
+  let count = $elements.length;
+  let map = $_lookupNonTerminal($constantLists, count);
+  for (let i = 0; i < count; i++) {
+    map = $_lookupNonTerminal(map, elements[i]);
+  }
+  let value = map.get($elementType);
+  if (value) return value;
+
+  ${getGenericClass(JSArray)}($elementType).unmodifiable($elements);
+  map.set($elementType, elements);
+  return elements;
+})()''');
+
+constFn(x) => JS('', '() => x');
+
+/// Gets the extension symbol given a member [name].
+///
+/// This is inlined by the compiler when used with a literal string.
+extensionSymbol(String name) => JS('', 'dartx[#]', name);
+
+// The following are helpers for Object methods when the receiver
+// may be null. These should only be generated by the compiler.
+bool equals(x, y) {
+  // We handle `y == null` inside our generated operator methods, to keep this
+  // function minimal.
+  // This pattern resulted from performance testing; it found that dispatching
+  // was the fastest solution, even for primitive types.
+  return JS('!', '# == null ? # == null : #[#](#)', x, y, x,
+      extensionSymbol('_equals'), y);
+}
+
+int hashCode(obj) {
+  return obj == null ? 0 : JS('!', '#[#]', obj, extensionSymbol('hashCode'));
+}
+
+@JSExportName('toString')
+String _toString(obj) {
+  if (obj == null) return "null";
+  if (obj is String) return obj;
+  return JS('!', '#[#]()', obj, extensionSymbol('toString'));
+}
+
+/// Converts to a non-null [String], equivalent to
+/// `dart.notNull(dart.toString(obj))`.
+///
+/// This is commonly used in string interpolation.
+@notNull
+String str(obj) {
+  if (obj == null) return "null";
+  if (obj is String) return obj;
+  return _notNull(JS('!', '#[#]()', obj, extensionSymbol('toString')));
+}
+
+// TODO(jmesserly): is the argument type verified statically?
+noSuchMethod(obj, Invocation invocation) {
+  if (obj == null) defaultNoSuchMethod(obj, invocation);
+  return JS('', '#[#](#)', obj, extensionSymbol('noSuchMethod'), invocation);
+}
+
+/// The default implementation of `noSuchMethod` to match `Object.noSuchMethod`.
+defaultNoSuchMethod(obj, Invocation i) {
+  if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+  throw NoSuchMethodError.withInvocation(obj, i);
+}
+
+runtimeType(obj) {
+  return obj == null ? Null : JS('', '#[dartx.runtimeType]', obj);
+}
+
+final identityHashCode_ = JS('', 'Symbol("_identityHashCode")');
+
+/// Adapts a Dart `get iterator` into a JS `[Symbol.iterator]`.
+// TODO(jmesserly): instead of an adaptor, we could compile Dart iterators
+// natively implementing the JS iterator protocol. This would allow us to
+// optimize them a bit.
+final JsIterator = JS('', '''
+  class JsIterator {
+    constructor(dartIterator) {
+      this.dartIterator = dartIterator;
+    }
+    next() {
+      let i = this.dartIterator;
+      let done = !i.moveNext();
+      return { done: done, value: done ? void 0 : i.current };
+    }
+  }
+''');
+
+_canonicalMember(obj, name) {
+  // Private names are symbols and are already canonical.
+  if (JS('!', 'typeof # === "symbol"', name)) return name;
+
+  if (obj != null && JS<bool>('!', '#[#] != null', obj, _extensionType)) {
+    return JS('', 'dartx.#', name);
+  }
+
+  // Check for certain names that we can't use in JS
+  if (JS('!', '# == "constructor" || # == "prototype"', name, name)) {
+    JS('', '# = "+" + #', name, name);
+  }
+  return name;
+}
+
+/// Emulates the implicit "loadLibrary" function provided by a deferred library.
+///
+/// Libraries are not actually deferred in DDC, so this just returns a future
+/// that completes immediately.
+Future loadLibrary() => Future.value();
+
+/// Defines lazy statics.
+void defineLazy(to, from) {
+  for (var name in getOwnNamesAndSymbols(from)) {
+    defineLazyField(to, name, getOwnPropertyDescriptor(from, name));
+  }
+}
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
new file mode 100644
index 0000000..11ea1ae
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
@@ -0,0 +1,222 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library defines the association between runtime objects and
+/// runtime types.
+part of dart._runtime;
+
+/// Runtime type information.  This module defines the mapping from
+/// runtime objects to their runtime type information.  See the types
+/// module for the definition of how type information is represented.
+///
+/// There are two kinds of objects that represent "types" at runtime. A
+/// "runtime type" contains all of the data needed to implement the runtime
+/// type checking inserted by the compiler. These objects fall into four
+/// categories:
+///
+///   - Things represented by javascript primitives, such as
+///     null, numbers, booleans, strings, and symbols.  For these
+///     we map directly from the javascript type (given by typeof)
+///     to the appropriate class type from core, which serves as their
+///     rtti.
+///
+///   - Functions, which are represented by javascript functions.
+///     Representations of Dart functions always have a
+///     _runtimeType property attached to them with the appropriate
+///     rtti.
+///
+///   - Objects (instances) which are represented by instances of
+///     javascript (ES6) classes.  Their types are given by their
+///     classes, and the rtti is accessed by projecting out their
+///     constructor field.
+///
+///   - Types objects, which are represented as described in the types
+///     module.  Types always have a _runtimeType property attached to
+///     them with the appropriate rtti.  The rtti for these is always
+///     core.Type.  TODO(leafp): consider the possibility that we can
+///     reliably recognize type objects and map directly to core.Type
+///     rather than attaching this property everywhere.
+///
+/// The other kind of object representing a "type" is the instances of the
+/// dart:core Type class. These are the user visible objects you get by calling
+/// "runtimeType" on an object or using a class literal expression. These are
+/// different from the above objects, and are created by calling `wrapType()`
+/// on a runtime type.
+
+/// Tag a closure with a type.
+///
+/// `dart.fn(closure, type)` marks [closure] with the provided runtime [type].
+fn(closure, type) {
+  JS('', '#[#] = #', closure, _runtimeType, type);
+  return closure;
+}
+
+/// Tag a closure with a type that's computed lazily.
+///
+/// `dart.fn(closure, type)` marks [closure] with a getter that uses
+/// [computeType] to return the runtime type.
+///
+/// The getter/setter replaces the property with a value property, so the
+/// resulting function is compatible with [fn] and the type can be set again
+/// safely.
+lazyFn(closure, Object Function() computeType) {
+  defineAccessor(closure, _runtimeType,
+      get: () => defineValue(closure, _runtimeType, computeType()),
+      set: (value) => defineValue(closure, _runtimeType, value),
+      configurable: true);
+  return closure;
+}
+
+// TODO(vsm): How should we encode the runtime type?
+final _runtimeType = JS('', 'Symbol("_runtimeType")');
+
+final _moduleName = JS('', 'Symbol("_moduleName")');
+
+getFunctionType(obj) {
+  // TODO(vsm): Encode this properly on the function for Dart-generated code.
+  var args = JS<List>('!', 'Array(#.length).fill(#)', obj, dynamic);
+  return fnType(bottom, args, JS('', 'void 0'));
+}
+
+/// Returns the runtime representation of the type of obj.
+///
+/// The resulting object is used internally for runtime type checking. This is
+/// different from the user-visible Type object returned by calling
+/// `runtimeType` on some Dart object.
+getReifiedType(obj) {
+  switch (JS<String>('!', 'typeof #', obj)) {
+    case "object":
+      if (obj == null) return JS('', '#', Null);
+      if (JS('!', '# instanceof #', obj, Object)) {
+        return JS('', '#.constructor', obj);
+      }
+      var result = JS('', '#[#]', obj, _extensionType);
+      if (result == null) return JS('', '#', jsobject);
+      return result;
+    case "function":
+      // All Dart functions and callable classes must set _runtimeType
+      var result = JS('', '#[#]', obj, _runtimeType);
+      if (result != null) return result;
+      return JS('', '#', jsobject);
+    case "undefined":
+      return JS('', '#', Null);
+    case "number":
+      return JS('', 'Math.floor(#) == # ? # : #', obj, obj, int, double);
+    case "boolean":
+      return JS('', '#', bool);
+    case "string":
+      return JS('', '#', String);
+    case "symbol":
+    default:
+      return JS('', '#', jsobject);
+  }
+}
+
+/// Return the module name for a raw library object.
+String getModuleName(Object module) => JS('', '#[#]', module, _moduleName);
+
+final _loadedModules = JS('', 'new Map()');
+final _loadedPartMaps = JS('', 'new Map()');
+final _loadedSourceMaps = JS('', 'new Map()');
+
+List<String> getModuleNames() {
+  return JSArray<String>.of(JS('', 'Array.from(#.keys())', _loadedModules));
+}
+
+String getSourceMap(String moduleName) {
+  return JS('!', '#.get(#)', _loadedSourceMaps, moduleName);
+}
+
+/// Return all library objects in the specified module.
+getModuleLibraries(String name) {
+  var module = JS('', '#.get(#)', _loadedModules, name);
+  if (module == null) return null;
+  JS('', '#[#] = #', module, _moduleName, name);
+  return module;
+}
+
+/// Return the part map for a specific module.
+getModulePartMap(String name) => JS('', '#.get(#)', _loadedPartMaps, name);
+
+/// Track all libraries
+void trackLibraries(
+    String moduleName, Object libraries, Object parts, String sourceMap) {
+  if (parts is String) {
+    // Added for backwards compatibility.
+    // package:build_web_compilers currently invokes this without [parts]
+    // in its bootstrap code.
+    sourceMap = parts as String;
+    parts = JS('', '{}');
+  }
+  JS('', '#.set(#, #)', _loadedSourceMaps, moduleName, sourceMap);
+  JS('', '#.set(#, #)', _loadedModules, moduleName, libraries);
+  JS('', '#.set(#, #)', _loadedPartMaps, moduleName, parts);
+}
+
+List<String> _libraries;
+Map<String, Object> _libraryObjects;
+Map<String, List<String>> _parts;
+
+_computeLibraryMetadata() {
+  _libraries = [];
+  _libraryObjects = {};
+  _parts = {};
+  var modules = getModuleNames();
+  for (var name in modules) {
+    // Add libraries from each module.
+    var module = getModuleLibraries(name);
+    var libraries = getOwnPropertyNames(module).cast<String>();
+    _libraries.addAll(libraries);
+    for (var library in libraries) {
+      _libraryObjects[library] = JS('', '#.#', module, library);
+    }
+
+    // Add parts from each module.
+    var partMap = getModulePartMap(name);
+    libraries = getOwnPropertyNames(partMap).cast<String>();
+    for (var library in libraries) {
+      _parts[library] = List.from(JS('List', '#.#', partMap, library));
+    }
+  }
+}
+
+/// Returns the JS library object for a given library [uri] or
+/// undefined / null if it isn't loaded.  Top-level types and
+/// methods are available on this object.
+Object getLibrary(String uri) {
+  if (_libraryObjects == null) {
+    _computeLibraryMetadata();
+  }
+  return _libraryObjects[uri];
+}
+
+/// Returns a JSArray of library uris (e.g,
+/// ['dart:core', 'dart:_internal', ..., 'package:foo/bar.dart', ... 'main.dart'])
+/// loaded in this application.
+List<String> getLibraries() {
+  if (_libraries == null) {
+    _computeLibraryMetadata();
+  }
+  return _libraries;
+}
+
+/// Returns a JSArray of part uris for a given [libraryUri].
+/// The part uris will be relative to the [libraryUri].
+///
+/// E.g., invoking `getParts('package:intl/intl.dart')` returns (as of this
+/// writing): ```
+/// ["src/intl/bidi_formatter.dart", "src/intl/bidi_utils.dart",
+///  "src/intl/compact_number_format.dart", "src/intl/date_format.dart",
+///  "src/intl/date_format_field.dart", "src/intl/date_format_helpers.dart",
+///  "src/intl/number_format.dart"]
+/// ```
+///
+/// If [libraryUri] doesn't map to a library or maps to a library with no
+/// parts, an empty list is returned.
+List<String> getParts(String libraryUri) {
+  if (_parts == null) {
+    _computeLibraryMetadata();
+  }
+  return _parts[libraryUri] ?? [];
+}
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
new file mode 100644
index 0000000..3ec16c9
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
@@ -0,0 +1,219 @@
+// 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.
+
+@ReifyFunctionTypes(false)
+library dart._runtime;
+
+import 'dart:async';
+import 'dart:collection';
+
+import 'dart:_debugger' show stackTraceMapper, trackCall;
+import 'dart:_foreign_helper' show JS, JSExportName, rest, spread;
+import 'dart:_interceptors' show JSArray, jsNull, JSFunction, NativeError;
+import 'dart:_internal' as internal show Symbol;
+import 'dart:_js_helper'
+    show
+        AssertionErrorImpl,
+        BooleanConversionAssertionError,
+        CastErrorImpl,
+        DartIterator,
+        TypeErrorImpl,
+        JsLinkedHashMap,
+        ImmutableMap,
+        PrivateSymbol,
+        ReifyFunctionTypes,
+        NoReifyGeneric,
+        notNull,
+        undefined;
+
+export 'dart:_debugger' show getDynamicStats, clearDynamicStats, trackCall;
+
+part 'utils.dart';
+part 'classes.dart';
+part 'rtti.dart';
+part 'types.dart';
+part 'errors.dart';
+part 'operations.dart';
+
+// TODO(vsm): Move polyfill code to dart:html.
+// Note, native extensions are registered onto types in dart.global.
+// This polyfill needs to run before the corresponding dart:html code is run.
+final _polyfilled = JS('', 'Symbol("_polyfilled")');
+
+bool polyfill(window) => JS('', '''(() => {
+  if ($window[$_polyfilled]) return false;
+  $window[$_polyfilled] = true;
+
+  if (typeof $window.NodeList !== "undefined") {
+    // TODO(vsm): Do we still need these?
+    $window.NodeList.prototype.get = function(i) { return this[i]; };
+    $window.NamedNodeMap.prototype.get = function(i) { return this[i]; };
+    $window.DOMTokenList.prototype.get = function(i) { return this[i]; };
+    $window.HTMLCollection.prototype.get = function(i) { return this[i]; };
+
+    // Expose constructors for DOM types dart:html needs to assume are
+    // available on window.
+    if (typeof $window.PannerNode == "undefined") {
+      let audioContext;
+      if (typeof $window.AudioContext == "undefined" &&
+          (typeof $window.webkitAudioContext != "undefined")) {
+        audioContext = new $window.webkitAudioContext();
+      } else {
+        audioContext = new $window.AudioContext();
+        $window.StereoPannerNode =
+            audioContext.createStereoPanner().constructor;
+      }
+      $window.PannerNode = audioContext.createPanner().constructor;
+    }
+    if (typeof $window.AudioSourceNode == "undefined") {
+      $window.AudioSourceNode = MediaElementAudioSourceNode.__proto__;
+    }
+    if (typeof $window.FontFaceSet == "undefined") {
+      // CSS Font Loading is not supported on Edge.
+      if (typeof $window.document.fonts != "undefined") {
+        $window.FontFaceSet = $window.document.fonts.__proto__.constructor;
+      }
+    }
+    if (typeof $window.MemoryInfo == "undefined") {
+      if (typeof $window.performance.memory != "undefined") {
+        $window.MemoryInfo = $window.performance.memory.constructor;
+      }
+    }
+    if (typeof $window.Geolocation == "undefined") {
+      $window.Geolocation == $window.navigator.geolocation.constructor;
+    }
+    if (typeof $window.Animation == "undefined") {
+      let d = $window.document.createElement('div');
+      if (typeof d.animate != "undefined") {
+        $window.Animation = d.animate(d).constructor;
+      }
+    }
+    if (typeof $window.SourceBufferList == "undefined") {
+      if ('MediaSource' in $window) {
+        $window.SourceBufferList =
+          new $window.MediaSource().sourceBuffers.constructor; 
+      }
+    }
+    if (typeof $window.SpeechRecognition == "undefined") {
+      $window.SpeechRecognition = $window.webkitSpeechRecognition;
+      $window.SpeechRecognitionError = $window.webkitSpeechRecognitionError;
+      $window.SpeechRecognitionEvent = $window.webkitSpeechRecognitionEvent;
+    }
+  }
+  return true;
+})()''');
+
+@JSExportName('global')
+final global_ = JS('', '''
+  function () {
+    // Find global object.
+    var globalState = (typeof window != "undefined") ? window
+      : (typeof global != "undefined") ? global
+      : (typeof self != "undefined") ? self : null;
+    if (!globalState) {
+      // Some platforms (e.g., d8) do not define any of the above.  The
+      // following is a non-CSP safe way to access the global object:
+      globalState = new Function('return this;')();
+    }
+
+    $polyfill(globalState);
+
+    // By default, stack traces cutoff at 10.  Set the limit to Infinity for
+    // better debugging.
+    if (globalState.Error) {
+      globalState.Error.stackTraceLimit = Infinity;
+    }
+
+    // These settings must be configured before the application starts so that
+    // user code runs with the correct configuration.
+    let settings = 'ddcSettings' in globalState ? globalState.ddcSettings : {};
+    $trapRuntimeErrors(
+        'trapRuntimeErrors' in settings ? settings.trapRuntimeErrors : false);
+    $ignoreWhitelistedErrors(
+        'ignoreWhitelistedErrors' in settings ?
+            settings.ignoreWhitelistedErrors : false);
+
+    $ignoreAllErrors(
+        'ignoreAllErrors' in settings ? settings.ignoreAllErrors : false);
+
+    $trackProfile(
+        'trackProfile' in settings ? settings.trackProfile : false);
+
+    return globalState;
+  }()
+''');
+
+void trackProfile(bool flag) {
+  JS('', 'dart.__trackProfile = #', flag);
+}
+
+final JsSymbol = JS('', 'Symbol');
+
+/// The prototype used for all Dart libraries.
+///
+/// This makes it easy to identify Dart library objects, and also improves
+/// performance (JS engines such as V8 tend to assume `Object.create(null)` is
+/// used for a Map, so they don't optimize it as they normally would for
+/// class-like objects).
+///
+/// The `dart.library` field is set by the compiler during SDK bootstrapping
+/// (because it is needed for dart:_runtime itself), so we don't need to
+/// initialize it here. The name `dart.library` is used because it reads nicely,
+/// for example:
+///
+///     const my_library = Object.create(dart.library);
+///
+Object libraryPrototype = JS('', 'dart.library');
+
+// TODO(vsm): Remove once this flag we've removed the ability to
+// whitelist / fallback on the old behavior.
+bool startAsyncSynchronously = true;
+void setStartAsyncSynchronously([bool value = true]) {
+  startAsyncSynchronously = value;
+}
+
+/// A list of all JS Maps used for caching results, such as by [isSubtypeOf] and
+/// [generic].
+///
+/// This is used by [hotRestart] to ensure we don't leak types from previous
+/// libraries.
+@notNull
+final List<Object> _cacheMaps = JS('!', '[]');
+
+/// A list of functions to reset static fields back to their uninitialized
+/// state.
+///
+/// This is populated by [defineLazyField], and only contains the list of fields
+/// that have actually been initialized.
+@notNull
+final List<void Function()> _resetFields = JS('', '[]');
+
+/// Clears out runtime state in `dartdevc` so we can hot-restart.
+///
+/// This should be called when the user requests a hot-restart, when the UI is
+/// handling that user action.
+void hotRestart() {
+  // TODO(jmesserly): we need to prevent all pending callbacks from firing.
+  for (var f in _resetFields) f();
+  _resetFields.clear();
+  for (var m in _cacheMaps) JS('', '#.clear()', m);
+  _cacheMaps.clear();
+  JS('', '#.clear()', constantMaps);
+  JS('', '#.clear()', _ignoreSubtypeCache);
+}
+
+/// Marks enqueuing an async operation.
+///
+/// This will be called by library code when enqueuing an async operation
+/// controlled by the JavaScript event handler.
+///
+/// It will also call [removeAsyncCallback] when Dart callback is about to be
+/// executed (note this is called *before* the callback executes, so more
+/// async operations could be added from that).
+void Function() addAsyncCallback = JS('', 'function() {}');
+
+/// Marks leaving a javascript async operation.
+///
+/// See [addAsyncCallback].
+void Function() removeAsyncCallback = JS('', 'function() {}');
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
new file mode 100644
index 0000000..41c3de7
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -0,0 +1,1450 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library defines the representation of runtime types.
+part of dart._runtime;
+
+final metadata = JS('', 'Symbol("metadata")');
+
+/// Types in dart are represented internally at runtime as follows.
+///
+///   - Normal nominal types, produced from classes, are represented
+///     at runtime by the JS class of which they are an instance.
+///     If the type is the result of instantiating a generic class,
+///     then the "classes" module manages the association between the
+///     instantiated class and the original class declaration
+///     and the type arguments with which it was instantiated.  This
+///     association can be queried via the "classes" module".
+///
+///   - All other types are represented as instances of class [DartType],
+///     defined in this module.
+///     - Dynamic, Void, and Bottom are singleton instances of sentinal
+///       classes.
+///     - Function types are instances of subclasses of AbstractFunctionType.
+///
+/// Function types are represented in one of two ways:
+///   - As an instance of FunctionType.  These are eagerly computed.
+///   - As an instance of TypeDef.  The TypeDef representation lazily
+///     computes an instance of FunctionType, and delegates to that instance.
+///
+/// These above "runtime types" are what is used for implementing DDC's
+/// internal type checks. These objects are distinct from the objects exposed
+/// to user code by class literals and calling `Object.runtimeType`. In DDC,
+/// the latter are represented by instances of WrappedType which contain a
+/// real runtime type internally. This ensures that the returned object only
+/// exposes the API that Type defines:
+///
+///     get String name;
+///     String toString();
+///
+/// These "runtime types" have methods for performing type checks. The methods
+/// have the following JavaScript names which are designed to not collide with
+/// static methods, which are also placed 'on' the class constructor function.
+///
+///     T.is(o): Implements 'o is T'.
+///     T.as(o): Implements 'o as T'.
+///     T._check(o): Implements the type assertion of 'T x = o;'
+///
+/// By convention, we used named JavaScript functions for these methods with the
+/// name 'is_X', 'as_X' and 'check_X' for various X to indicate the type or the
+/// implementation strategy for the test (e.g 'is_String', 'is_G' for generic
+/// types, etc.)
+// TODO(jmesserly): we shouldn't implement Type here. It should be moved down
+// to AbstractFunctionType.
+class DartType implements Type {
+  String get name => this.toString();
+
+  // TODO(jmesserly): these should never be reached, can be make them abstract?
+  @notNull
+  @JSExportName('is')
+  bool is_T(object) => instanceOf(object, this);
+
+  @JSExportName('as')
+  as_T(object) => cast(object, this, false);
+
+  @JSExportName('_check')
+  check_T(object) => cast(object, this, true);
+}
+
+class DynamicType extends DartType {
+  toString() => 'dynamic';
+
+  @JSExportName('is')
+  bool is_T(object) => true;
+
+  @JSExportName('as')
+  as_T(object) => object;
+
+  @JSExportName('_check')
+  check_T(object) => object;
+}
+
+@notNull
+bool _isJsObject(obj) => JS('!', '# === #', getReifiedType(obj), jsobject);
+
+/// The Dart type that represents a JavaScript class(/constructor) type.
+///
+/// The JavaScript type may not exist, either because it's not loaded yet, or
+/// because it's not available (such as with mocks). To handle this gracefully,
+/// we disable type checks for in these cases, and allow any JS object to work
+/// as if it were an instance of this JS type.
+class LazyJSType extends DartType {
+  Function() _getRawJSTypeFn;
+  @notNull
+  final String _dartName;
+  Object _rawJSType;
+
+  LazyJSType(this._getRawJSTypeFn, this._dartName);
+
+  toString() {
+    var raw = _getRawJSType();
+    return raw != null ? typeName(raw) : "JSObject<$_dartName>";
+  }
+
+  Object _getRawJSType() {
+    var raw = _rawJSType;
+    if (raw != null) return raw;
+
+    // Try to evaluate the JS type. If this fails for any reason, we'll try
+    // again next time.
+    // TODO(jmesserly): is it worth trying again? It may create unnecessary
+    // overhead, especially if exceptions are being thrown. Also it means the
+    // behavior of a given type check can change later on.
+    try {
+      raw = _getRawJSTypeFn();
+    } catch (e) {}
+
+    if (raw == null) {
+      _warn('Cannot find native JavaScript type ($_dartName) for type check');
+    } else {
+      _rawJSType = raw;
+      _getRawJSTypeFn = null; // Free the function that computes the JS type.
+    }
+    return raw;
+  }
+
+  Object rawJSTypeForCheck() => _getRawJSType() ?? jsobject;
+
+  @notNull
+  bool isRawJSType(obj) {
+    var raw = _getRawJSType();
+    if (raw != null) return JS('!', '# instanceof #', obj, raw);
+    return _isJsObject(obj);
+  }
+
+  @notNull
+  @JSExportName('is')
+  bool is_T(obj) => isRawJSType(obj) || instanceOf(obj, this);
+
+  @JSExportName('as')
+  as_T(obj) => obj == null || is_T(obj) ? obj : castError(obj, this, false);
+
+  @JSExportName('_check')
+  check_T(obj) => obj == null || is_T(obj) ? obj : castError(obj, this, true);
+}
+
+/// An anonymous JS type
+///
+/// For the purposes of subtype checks, these match any JS type.
+class AnonymousJSType extends DartType {
+  final String _dartName;
+  AnonymousJSType(this._dartName);
+  toString() => _dartName;
+
+  @JSExportName('is')
+  bool is_T(obj) => _isJsObject(obj) || instanceOf(obj, this);
+
+  @JSExportName('as')
+  as_T(obj) => obj == null || _isJsObject(obj) ? obj : cast(obj, this, false);
+
+  @JSExportName('_check')
+  check_T(obj) => obj == null || _isJsObject(obj) ? obj : cast(obj, this, true);
+}
+
+void _warn(arg) {
+  JS('void', 'console.warn(#)', arg);
+}
+
+var _lazyJSTypes = JS('', 'new Map()');
+var _anonymousJSTypes = JS('', 'new Map()');
+
+lazyJSType(Function() getJSTypeCallback, String name) {
+  var ret = JS('', '#.get(#)', _lazyJSTypes, name);
+  if (ret == null) {
+    ret = LazyJSType(getJSTypeCallback, name);
+    JS('', '#.set(#, #)', _lazyJSTypes, name, ret);
+  }
+  return ret;
+}
+
+anonymousJSType(String name) {
+  var ret = JS('', '#.get(#)', _anonymousJSTypes, name);
+  if (ret == null) {
+    ret = AnonymousJSType(name);
+    JS('', '#.set(#, #)', _anonymousJSTypes, name, ret);
+  }
+  return ret;
+}
+
+@JSExportName('dynamic')
+final _dynamic = DynamicType();
+
+class VoidType extends DartType {
+  toString() => 'void';
+}
+
+@JSExportName('void')
+final void_ = VoidType();
+
+class BottomType extends DartType {
+  toString() => 'bottom';
+}
+
+// TODO(vsm): We reify bottom as Null.  We will revisit this with
+// non-nullable types.
+final bottom = unwrapType(Null);
+
+class JSObjectType extends DartType {
+  toString() => 'NativeJavaScriptObject';
+}
+
+final jsobject = JSObjectType();
+
+/// Dev Compiler's implementation of Type, wrapping its internal [_type].
+class _Type extends Type {
+  /// The internal type representation, either a [DartType] or class constructor
+  /// function.
+  // TODO(jmesserly): introduce InterfaceType so we don't have to special case
+  // classes
+  @notNull
+  final Object _type;
+
+  _Type(this._type);
+
+  toString() => typeName(_type);
+
+  Type get runtimeType => Type;
+}
+
+/// Given an internal runtime type object, wraps it in a `_Type` object
+/// that implements the dart:core Type interface.
+Type wrapType(type) {
+  // If we've already wrapped this type once, use the previous wrapper. This
+  // way, multiple references to the same type return an identical Type.
+  if (JS('!', '#.hasOwnProperty(#)', type, _typeObject)) {
+    return JS('', '#[#]', type, _typeObject);
+  }
+  var result = _Type(type);
+  JS('', '#[#] = #', type, _typeObject, result);
+  return result;
+}
+
+/// The symbol used to store the cached `Type` object associated with a class.
+final _typeObject = JS('', 'Symbol("typeObject")');
+
+/// Given a WrappedType, return the internal runtime type object.
+Object unwrapType(Type obj) => JS<_Type>('', '#', obj)._type;
+
+// Marker class for generic functions, typedefs, and non-generic functions.
+abstract class AbstractFunctionType extends DartType {}
+
+/// Memo table for named argument groups. A named argument packet
+/// {name1 : type1, ..., namen : typen} corresponds to the path
+/// n, name1, type1, ...., namen, typen.  The element of the map
+/// reached via this path (if any) is the canonical representative
+/// for this packet.
+final _fnTypeNamedArgMap = JS('', 'new Map()');
+
+/// Memo table for positional argument groups. A positional argument
+/// packet [type1, ..., typen] (required or optional) corresponds to
+/// the path n, type1, ...., typen.  The element reached via
+/// this path (if any) is the canonical representative for this
+/// packet. Note that required and optional parameters packages
+/// may have the same canonical representation.
+final _fnTypeArrayArgMap = JS('', 'new Map()');
+
+/// Memo table for function types. The index path consists of the
+/// path length - 1, the returnType, the canonical positional argument
+/// packet, and if present, the canonical optional or named argument
+/// packet.  A level of indirection could be avoided here if desired.
+final _fnTypeTypeMap = JS('', 'new Map()');
+
+/// Memo table for small function types with no optional or named
+/// arguments and less than a fixed n (currently 3) number of
+/// required arguments.  Indexing into this table by the number
+/// of required arguments yields a map which is indexed by the
+/// argument types themselves.  The element reached via this
+/// index path (if present) is the canonical function type.
+final List _fnTypeSmallMap = JS('', '[new Map(), new Map(), new Map()]');
+
+@NoReifyGeneric()
+T _memoizeArray<T>(map, arr, T create()) => JS('', '''(() => {
+  let len = $arr.length;
+  $map = $_lookupNonTerminal($map, len);
+  for (var i = 0; i < len-1; ++i) {
+    $map = $_lookupNonTerminal($map, $arr[i]);
+  }
+  let result = $map.get($arr[len-1]);
+  if (result !== void 0) return result;
+  $map.set($arr[len-1], result = $create());
+  return result;
+})()''');
+
+List _canonicalizeArray(List array, map) =>
+    _memoizeArray(map, array, () => array);
+
+// TODO(leafp): This only canonicalizes of the names are
+// emitted in a consistent order.
+_canonicalizeNamed(named, map) => JS('', '''(() => {
+  let key = [];
+  let names = $getOwnPropertyNames($named);
+  for (var i = 0; i < names.length; ++i) {
+    let name = names[i];
+    let type = $named[name];
+    key.push(name);
+    key.push(type);
+  }
+  return $_memoizeArray($map, key, () => $named);
+})()''');
+
+// TODO(leafp): This handles some low hanging fruit, but
+// really we should make all of this faster, and also
+// handle more cases here.
+FunctionType _createSmall(returnType, List required) => JS('', '''(() => {
+  let count = $required.length;
+  let map = $_fnTypeSmallMap[count];
+  for (var i = 0; i < count; ++i) {
+    map = $_lookupNonTerminal(map, $required[i]);
+ }
+ let result = map.get($returnType);
+ if (result !== void 0) return result;
+ result = ${new FunctionType(returnType, required, [], JS('', '{}'))};
+ map.set($returnType, result);
+ return result;
+})()''');
+
+class FunctionType extends AbstractFunctionType {
+  final returnType;
+  List args;
+  List optionals;
+  final named;
+  // TODO(vsm): This is just parameter metadata for now.
+  List metadata = [];
+  String _stringValue;
+
+  /**
+   * Construct a function type.
+   *
+   * We eagerly normalize the argument types to avoid having to deal with
+   * this logic in multiple places.
+   *
+   * This code does best effort canonicalization.  It does not guarantee
+   * that all instances will share.
+   *
+   */
+  static FunctionType create(returnType, List args, extra) {
+    // Note that if extra is ever passed as an empty array
+    // or an empty map, we can end up with semantically
+    // identical function types that don't canonicalize
+    // to the same object since we won't fall into this
+    // fast path.
+    if (extra == null && JS<bool>('!', '#.length < 3', args)) {
+      return _createSmall(returnType, args);
+    }
+    args = _canonicalizeArray(args, _fnTypeArrayArgMap);
+    var keys;
+    FunctionType Function() create;
+    if (extra == null) {
+      keys = [returnType, args];
+      create = () => FunctionType(returnType, args, [], JS('', '{}'));
+    } else if (JS('!', '# instanceof Array', extra)) {
+      var optionals =
+          _canonicalizeArray(JS('', '#', extra), _fnTypeArrayArgMap);
+      keys = [returnType, args, optionals];
+      create = () => FunctionType(returnType, args, optionals, JS('', '{}'));
+    } else {
+      var named = _canonicalizeNamed(extra, _fnTypeNamedArgMap);
+      keys = [returnType, args, named];
+      create = () => FunctionType(returnType, args, [], named);
+    }
+    return _memoizeArray(_fnTypeTypeMap, keys, create);
+  }
+
+  List _process(List array) {
+    var result = [];
+    for (var i = 0; JS<bool>('!', '# < #.length', i, array); ++i) {
+      var arg = JS('', '#[#]', array, i);
+      if (JS('!', '# instanceof Array', arg)) {
+        JS('', '#.push(#.slice(1))', metadata, arg);
+        JS('', '#.push(#[0])', result, arg);
+      } else {
+        JS('', '#.push([])', metadata);
+        JS('', '#.push(#)', result, arg);
+      }
+    }
+    return result;
+  }
+
+  FunctionType(this.returnType, this.args, this.optionals, this.named) {
+    this.args = _process(this.args);
+    this.optionals = _process(this.optionals);
+    // TODO(vsm): Add named arguments.
+  }
+
+  toString() => name;
+
+  int get requiredParameterCount => args.length;
+  int get positionalParameterCount => args.length + optionals.length;
+
+  getPositionalParameter(int i) {
+    int n = args.length;
+    return i < n ? args[i] : optionals[i + n];
+  }
+
+  Map<String, Object> getNamedParameters() {
+    var result = <String, Object>{};
+    var names = getOwnPropertyNames(named);
+    JS('', '#.sort()', names);
+    for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
+      String name = JS('!', '#[#]', names, i);
+      result[name] = JS('', '#[#]', named, name);
+    }
+    return result;
+  }
+
+  get name {
+    if (_stringValue != null) return _stringValue;
+
+    var buffer = '(';
+    for (var i = 0; JS<bool>('!', '# < #.length', i, args); ++i) {
+      if (i > 0) {
+        buffer += ', ';
+      }
+      buffer += typeName(JS('', '#[#]', args, i));
+    }
+    if (JS('!', '#.length > 0', optionals)) {
+      if (JS('!', '#.length > 0', args)) buffer += ', ';
+      buffer += '[';
+      for (var i = 0; JS<bool>('!', '# < #.length', i, optionals); ++i) {
+        if (i > 0) {
+          buffer += ', ';
+        }
+        buffer += typeName(JS('', '#[#]', optionals, i));
+      }
+      buffer += ']';
+    } else if (JS('!', 'Object.keys(#).length > 0', named)) {
+      if (JS('!', '#.length > 0', args)) buffer += ', ';
+      buffer += '{';
+      var names = getOwnPropertyNames(named);
+      JS('', '#.sort()', names);
+      for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
+        if (i > 0) {
+          buffer += ', ';
+        }
+        var typeNameString = typeName(JS('', '#[#[#]]', named, names, i));
+        buffer += '$typeNameString ${JS('', '#[#]', names, i)}';
+      }
+      buffer += '}';
+    }
+
+    var returnTypeName = typeName(returnType);
+    buffer += ') => $returnTypeName';
+    _stringValue = buffer;
+    return buffer;
+  }
+
+  @JSExportName('is')
+  bool is_T(obj) {
+    if (JS('!', 'typeof # == "function"', obj)) {
+      var actual = JS('', '#[#]', obj, _runtimeType);
+      // If there's no actual type, it's a JS function.
+      // Allow them to subtype all Dart function types.
+      return actual == null || isSubtypeOf(actual, this);
+    }
+    return false;
+  }
+
+  @JSExportName('as')
+  as_T(obj, [@notNull bool isImplicit = false]) {
+    if (obj == null) return obj;
+    if (JS('!', 'typeof # == "function"', obj)) {
+      var actual = JS('', '#[#]', obj, _runtimeType);
+      // If there's no actual type, it's a JS function.
+      // Allow them to subtype all Dart function types.
+      if (actual == null ||
+          _isSubtypeOrIgnorableCastFailure(actual, this, isImplicit)) {
+        return obj;
+      }
+    }
+    return castError(obj, this, isImplicit);
+  }
+
+  @JSExportName('_check')
+  check_T(obj) => as_T(obj, true);
+}
+
+/// A type variable, used by [GenericFunctionType] to represent a type formal.
+class TypeVariable extends DartType {
+  final String name;
+
+  TypeVariable(this.name);
+
+  toString() => name;
+}
+
+class GenericFunctionType extends AbstractFunctionType {
+  final _instantiateTypeParts;
+  final int formalCount;
+  final _instantiateTypeBounds;
+  List<TypeVariable> _typeFormals;
+
+  GenericFunctionType(instantiateTypeParts, this._instantiateTypeBounds)
+      : _instantiateTypeParts = instantiateTypeParts,
+        formalCount = JS('!', '#.length', instantiateTypeParts);
+
+  List<TypeVariable> get typeFormals {
+    if (_typeFormals != null) return _typeFormals;
+    return _typeFormals = _typeFormalsFromFunction(_instantiateTypeParts);
+  }
+
+  /// Checks that [typeArgs] satisfies the upper bounds of the [typeFormals],
+  /// and throws a [TypeError] if they do not.
+  void checkBounds(List typeArgs) {
+    // If we don't have explicit type parameter bounds, the bounds default to
+    // a top type, so there's nothing to check here.
+    if (_instantiateTypeBounds == null) return;
+
+    var bounds = instantiateTypeBounds(typeArgs);
+    var typeFormals = this.typeFormals;
+    for (var i = 0; i < typeArgs.length; i++) {
+      checkTypeBound(typeArgs[i], bounds[i], typeFormals[i].name);
+    }
+  }
+
+  FunctionType instantiate(typeArgs) {
+    var parts = JS('', '#.apply(null, #)', _instantiateTypeParts, typeArgs);
+    return FunctionType.create(
+        JS('', '#[0]', parts), JS('', '#[1]', parts), JS('', '#[2]', parts));
+  }
+
+  List instantiateTypeBounds(List typeArgs) {
+    var boundsFn = _instantiateTypeBounds;
+    if (boundsFn == null) {
+      // The Dart 1 spec says omitted type parameters have an upper bound of
+      // Object. However Dart 2 uses `dynamic` for the purpose of instantiate to
+      // bounds, so we use that here.
+      return List.filled(formalCount, _dynamic);
+    }
+    // Bounds can be recursive or depend on other type parameters, so we need to
+    // apply type arguments and return the resulting bounds.
+    return JS('List', '#.apply(null, #)', boundsFn, typeArgs);
+  }
+
+  toString() {
+    String s = "<";
+    var typeFormals = this.typeFormals;
+    var typeBounds = instantiateTypeBounds(typeFormals);
+    for (int i = 0, n = typeFormals.length; i < n; i++) {
+      if (i != 0) s += ", ";
+      s += JS<String>('!', '#[#].name', typeFormals, i);
+      var bound = typeBounds[i];
+      if (JS('!', '# !== # && # !== #', bound, dynamic, bound, Object)) {
+        s += " extends $bound";
+      }
+    }
+    s += ">" + instantiate(typeFormals).toString();
+    return s;
+  }
+
+  /// Given a [DartType] [type], if [type] is an uninstantiated
+  /// parameterized type then instantiate the parameters to their
+  /// bounds and return those type arguments.
+  ///
+  /// See the issue for the algorithm description:
+  /// <https://github.com/dart-lang/sdk/issues/27526#issuecomment-260021397>
+  List instantiateDefaultBounds() {
+    var typeFormals = this.typeFormals;
+
+    // All type formals
+    var all = HashMap<Object, int>.identity();
+    // ground types, by index.
+    //
+    // For each index, this will be a ground type for the corresponding type
+    // formal if known, or it will be the original TypeVariable if we are still
+    // solving for it. This array is passed to `instantiateToBounds` as we are
+    // progressively solving for type variables.
+    var defaults = List<Object>(typeFormals.length);
+    // not ground
+    var partials = Map<TypeVariable, Object>.identity();
+
+    var typeBounds = this.instantiateTypeBounds(typeFormals);
+    for (var i = 0; i < typeFormals.length; i++) {
+      var typeFormal = typeFormals[i];
+      var bound = typeBounds[i];
+      all[typeFormal] = i;
+      if (identical(bound, _dynamic)) {
+        defaults[i] = bound;
+      } else {
+        defaults[i] = typeFormal;
+        partials[typeFormal] = bound;
+      }
+    }
+
+    bool hasFreeFormal(Object t) {
+      if (partials.containsKey(t)) return true;
+
+      // Generic classes and typedefs.
+      var typeArgs = getGenericArgs(t);
+      if (typeArgs != null) return typeArgs.any(hasFreeFormal);
+
+      if (t is GenericFunctionType) {
+        return hasFreeFormal(t.instantiate(t.typeFormals));
+      }
+
+      if (t is FunctionType) {
+        return hasFreeFormal(t.returnType) || t.args.any(hasFreeFormal);
+      }
+
+      return false;
+    }
+
+    var hasProgress = true;
+    while (hasProgress) {
+      hasProgress = false;
+      for (var typeFormal in partials.keys) {
+        var partialBound = partials[typeFormal];
+        if (!hasFreeFormal(partialBound)) {
+          int index = all[typeFormal];
+          defaults[index] = instantiateTypeBounds(defaults)[index];
+          partials.remove(typeFormal);
+          hasProgress = true;
+          break;
+        }
+      }
+    }
+
+    // If we stopped making progress, and not all types are ground,
+    // then the whole type is malbounded and an error should be reported
+    // if errors are requested, and a partially completed type should
+    // be returned.
+    if (partials.isNotEmpty) {
+      throwTypeError('Instantiate to bounds failed for type with '
+          'recursive generic bounds: ${typeName(this)}. '
+          'Try passing explicit type arguments.');
+    }
+    return defaults;
+  }
+
+  @notNull
+  @JSExportName('is')
+  bool is_T(obj) {
+    if (JS('!', 'typeof # == "function"', obj)) {
+      var actual = JS('', '#[#]', obj, _runtimeType);
+      return actual != null && isSubtypeOf(actual, this);
+    }
+    return false;
+  }
+
+  @JSExportName('as')
+  as_T(obj) {
+    if (obj == null || is_T(obj)) return obj;
+    return castError(obj, this, false);
+  }
+
+  @JSExportName('_check')
+  check_T(obj) {
+    if (obj == null || is_T(obj)) return obj;
+    return castError(obj, this, true);
+  }
+}
+
+List<TypeVariable> _typeFormalsFromFunction(Object typeConstructor) {
+  // Extract parameter names from the function parameters.
+  //
+  // This is not robust in general for user-defined JS functions, but it
+  // should handle the functions generated by our compiler.
+  //
+  // TODO(jmesserly): names of TypeVariables are only used for display
+  // purposes, such as when an error happens or if someone calls
+  // `Type.toString()`. So we could recover them lazily rather than eagerly.
+  // Alternatively we could synthesize new names.
+  String str = JS('!', '#.toString()', typeConstructor);
+  var hasParens = str[0] == '(';
+  var end = str.indexOf(hasParens ? ')' : '=>');
+  if (hasParens) {
+    return str
+        .substring(1, end)
+        .split(',')
+        .map((n) => TypeVariable(n.trim()))
+        .toList();
+  } else {
+    return [TypeVariable(str.substring(0, end).trim())];
+  }
+}
+
+/// Create a function type.
+FunctionType fnType(returnType, List args, [@undefined extra]) =>
+    FunctionType.create(returnType, args, extra);
+
+/// Creates a generic function type.
+///
+/// A function type consists of two things: an instantiate function, and an
+/// function that returns a list of upper bound constraints for each
+/// the type formals. Both functions accept the type parameters, allowing us
+/// to substitute values. The upper bound constraints can be omitted if all
+/// of the type parameters use the default upper bound.
+///
+/// For example given the type <T extends Iterable<T>>(T) -> T, we can declare
+/// this type with `gFnType(T => [T, [T]], T => [Iterable$(T)])`.\
+gFnType(instantiateFn, typeBounds) =>
+    GenericFunctionType(instantiateFn, typeBounds);
+
+/// TODO(vsm): Remove when mirrors is deprecated.
+/// This is a temporary workaround to support dart:mirrors, which doesn't
+/// understand generic methods.
+getFunctionTypeMirror(AbstractFunctionType type) {
+  if (type is GenericFunctionType) {
+    var typeArgs = List.filled(type.formalCount, dynamic);
+    return type.instantiate(typeArgs);
+  }
+  return type;
+}
+
+/// Whether the given JS constructor [obj] is a Dart class type.
+@notNull
+bool isType(obj) => JS('', '#[#] === #', obj, _runtimeType, Type);
+
+void checkTypeBound(
+    @notNull Object type, @notNull Object bound, @notNull String name) {
+  if (!isSubtypeOf(type, bound)) {
+    throwTypeError('type `$type` does not extend `$bound` of `$name`.');
+  }
+}
+
+@notNull
+String typeName(type) => JS('', '''(() => {
+  if ($type === void 0) return "undefined type";
+  if ($type === null) return "null type";
+  // Non-instance types
+  if ($type instanceof $DartType) {
+    return $type.toString();
+  }
+
+  // Instance types
+  let tag = $type[$_runtimeType];
+  if (tag === $Type) {
+    let name = $type.name;
+    let args = ${getGenericArgs(type)};
+    if (args == null) return name;
+
+    if (${getGenericClass(type)} == ${getGenericClass(JSArray)}) name = 'List';
+
+    let result = name;
+    result += '<';
+    for (let i = 0; i < args.length; ++i) {
+      if (i > 0) result += ', ';
+      result += $typeName(args[i]);
+    }
+    result += '>';
+    return result;
+  }
+  if (tag) return "Not a type: " + tag.name;
+  return "JSObject<" + $type.name + ">";
+})()''');
+
+/// Returns true if [ft1] <: [ft2].
+/// Returns false if [ft1] </: [ft2] in both spec and strong mode
+/// Returns null if [ft1] </: [ft2] in strong mode, but spec mode
+/// may differ
+/// If [isCovariant] is true, then we are checking subtyping in a covariant
+/// position, and hence the direction of the check for function types
+/// corresponds to the direction of the check according to the Dart spec.
+_isFunctionSubtype(ft1, ft2, isCovariant) => JS('', '''(() => {
+  let ret1 = $ft1.returnType;
+  let ret2 = $ft2.returnType;
+
+  let args1 = $ft1.args;
+  let args2 = $ft2.args;
+
+  if (args1.length > args2.length) {
+    // If we're in a covariant position, then Dart's arity rules
+    // agree with strong mode, otherwise we can't be sure.
+    return ($isCovariant) ? false : null;
+  }
+
+  for (let i = 0; i < args1.length; ++i) {
+    if (!$_isSubtype(args2[i], args1[i], !$isCovariant)) {
+      // Even if isSubtypeOf returns false, assignability
+      // means that we can't be definitive
+      return null;
+    }
+  }
+
+  let optionals1 = $ft1.optionals;
+  let optionals2 = $ft2.optionals;
+
+  if (args1.length + optionals1.length < args2.length + optionals2.length) {
+    return ($isCovariant) ? false : null;
+  }
+
+  let j = 0;
+  for (let i = args1.length; i < args2.length; ++i, ++j) {
+    if (!$_isSubtype(args2[i], optionals1[j], !$isCovariant)) {
+      return null;
+    }
+  }
+
+  for (let i = 0; i < optionals2.length; ++i, ++j) {
+    if (!$_isSubtype(optionals2[i], optionals1[j], !$isCovariant)) {
+      return null;
+    }
+  }
+
+  let named1 = $ft1.named;
+  let named2 = $ft2.named;
+
+  let names = $getOwnPropertyNames(named2);
+  for (let i = 0; i < names.length; ++i) {
+    let name = names[i];
+    let n1 = named1[name];
+    let n2 = named2[name];
+    if (n1 === void 0) {
+      return ($isCovariant) ? false : null;
+    }
+    if (!$_isSubtype(n2, n1, !$isCovariant)) {
+      return null;
+    }
+  }
+
+  // Check return type last, so that arity mismatched functions can be
+  // definitively rejected.
+
+  // For `void` we will give the same answer as the VM, so don't return null.
+  if (ret1 === $void_) return $_isTop(ret2);
+
+  if (!$_isSubtype(ret1, ret2, $isCovariant)) return null;
+  return true;
+})()''');
+
+/// Whether [t1] <: [t2].
+@notNull
+bool isSubtypeOf(Object t1, Object t2) {
+  // TODO(jmesserly): we've optimized `is`/`as`/implicit type checks, so they're
+  // dispatched on the type. Can we optimize the subtype relation too?
+  return JS('!', '!!#', _isSubtypeOrLegacySubtype(t1, t2));
+}
+
+/// Returns true if [t1] <: [t2].
+/// Returns false if [t1] </: [t2] and we should not ignore this cast failure.
+/// Returns null if [t1] </: [t2] and we should ignore this cast failure when
+/// the appropriate flags are set.
+bool _isSubtypeOrLegacySubtype(Object t1, Object t2) {
+  Object map;
+  if (JS('!', '!#.hasOwnProperty(#)', t1, _subtypeCache)) {
+    JS('', '#[#] = # = new Map()', t1, _subtypeCache, map);
+    _cacheMaps.add(map);
+  } else {
+    map = JS('', '#[#]', t1, _subtypeCache);
+    bool result = JS('', '#.get(#)', map, t2);
+    if (JS('!', '# !== void 0', result)) return result;
+  }
+  var result = _isSubtype(t1, t2, true);
+  JS('', '#.set(#, #)', map, t2, result);
+  return result;
+}
+
+final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
+
+@notNull
+bool _isBottom(type) => JS('!', '# == # || # == #', type, bottom, type, Null);
+
+@notNull
+bool _isTop(type) {
+  if (_isFutureOr(type)) {
+    return _isTop(JS('', '#[0]', getGenericArgs(type)));
+  }
+  return JS('!', '# == # || # == # || # == #', type, Object, type, dynamic,
+      type, void_);
+}
+
+@notNull
+bool _isFutureOr(type) =>
+    identical(getGenericClass(type), getGenericClass(FutureOr));
+
+bool _isSubtype(t1, t2, isCovariant) => JS('', '''(() => {
+  if ($t1 === $t2) return true;
+
+  // Trivially true.
+  if (${_isTop(t2)} || ${_isBottom(t1)}) {
+    return true;
+  }
+
+  // Trivially false.
+  if (${_isBottom(t2)}) return null;
+  if (${_isTop(t1)}) {
+    if ($t1 === $dynamic) return null;
+    return false;
+  }
+
+  // Handle FutureOr<T> union type.
+  if (${_isFutureOr(t1)}) {
+    let t1TypeArg = ${getGenericArgs(t1)}[0];
+    if (${_isFutureOr(t2)}) {
+      let t2TypeArg = ${getGenericArgs(t2)}[0];
+      // FutureOr<A> <: FutureOr<B> iff A <: B
+      return $_isSubtype(t1TypeArg, t2TypeArg, $isCovariant);
+    }
+
+    // given t1 is Future<A> | A, then:
+    // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
+    let t1Future = ${getGenericClass(Future)}(t1TypeArg);
+    return $_isSubtype(t1Future, $t2, $isCovariant) &&
+        $_isSubtype(t1TypeArg, $t2, $isCovariant);
+  }
+
+  if ($_isFutureOr($t2)) {
+    // given t2 is Future<A> | A, then:
+    // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
+    let t2TypeArg = ${getGenericArgs(t2)}[0];
+    let t2Future = ${getGenericClass(Future)}(t2TypeArg);
+    let s1 = $_isSubtype($t1, t2Future, $isCovariant);
+    let s2 = $_isSubtype($t1, t2TypeArg, $isCovariant);
+    if (s1 === true || s2 === true) return true;
+    if (s1 === null || s2 === null) return null;
+    return false;
+  }
+
+  // "Traditional" name-based subtype check.  Avoid passing
+  // function types to the class subtype checks, since we don't
+  // currently distinguish between generic typedefs and classes.
+  if (!($t2 instanceof $AbstractFunctionType)) {
+    // t2 is an interface type.
+
+    if ($t1 instanceof $AbstractFunctionType) {
+      // Function types are only subtypes of interface types `Function` (and top
+      // types, handled already above).
+      return $t2 === $Function;
+    }
+
+    // All JS types are subtypes of anonymous JS types.
+    if ($t1 === $jsobject && $t2 instanceof $AnonymousJSType) return true;
+
+    // Compare two interface types:
+    return ${_isInterfaceSubtype(t1, t2, isCovariant)};
+  }
+
+  // Function subtyping.
+  if (!($t1 instanceof $AbstractFunctionType)) return false;
+
+  // Handle generic functions.
+  if ($t1 instanceof $GenericFunctionType) {
+    if (!($t2 instanceof $GenericFunctionType)) return false;
+
+    // Given generic functions g1 and g2, g1 <: g2 iff:
+    //
+    //     g1<TFresh> <: g2<TFresh>
+    //
+    // where TFresh is a list of fresh type variables that both g1 and g2 will
+    // be instantiated with.
+    let formalCount = $t1.formalCount;
+    if (formalCount !== $t2.formalCount) return false;
+
+    // Using either function's type formals will work as long as they're both
+    // instantiated with the same ones. The instantiate operation is guaranteed
+    // to avoid capture because it does not depend on its TypeVariable objects,
+    // rather it uses JS function parameters to ensure correct binding.
+    let fresh = $t2.typeFormals;
+
+    // Check the bounds of the type parameters of g1 and g2.
+    // given a type parameter `T1 extends U1` from g1, and a type parameter
+    // `T2 extends U2` from g2, we must ensure that:
+    //
+    //      U2 <: U1
+    //
+    // (Note the reversal of direction -- type formal bounds are contravariant,
+    // similar to the function's formal parameter types).
+    //
+    let t1Bounds = $t1.instantiateTypeBounds(fresh);
+    let t2Bounds = $t2.instantiateTypeBounds(fresh);
+    // TODO(jmesserly): we could optimize for the common case of no bounds.
+    for (let i = 0; i < formalCount; i++) {
+      if (!$_isSubtype(t2Bounds[i], t1Bounds[i], !$isCovariant)) {
+        return false;
+      }
+    }
+
+    $t1 = $t1.instantiate(fresh);
+    $t2 = $t2.instantiate(fresh);
+  } else if ($t2 instanceof $GenericFunctionType) {
+    return false;
+  }
+
+  // Handle non-generic functions.
+  return ${_isFunctionSubtype(t1, t2, isCovariant)};
+})()''');
+
+bool _isInterfaceSubtype(t1, t2, isCovariant) => JS('', '''(() => {
+  // We support Dart's covariant generics with the caveat that we do not
+  // substitute bottom for dynamic in subtyping rules.
+  // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow:
+  // - S !<: S<T1, ..., Tn>
+  // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn>
+  
+  // If we have lazy JS types, unwrap them.  This will effectively
+  // reduce to a prototype check below.
+  if ($t1 instanceof $LazyJSType) $t1 = $t1.rawJSTypeForCheck();
+  if ($t2 instanceof $LazyJSType) $t2 = $t2.rawJSTypeForCheck();
+
+  if ($t1 === $t2) return true;
+  if ($t1 === $Object) return false;
+
+  // Classes cannot subtype `Function` or vice versa.
+  if ($t1 === $Function || $t2 === $Function) return false;
+
+  // If t1 is a JS Object, we may not hit core.Object.
+  if ($t1 == null) return $t2 == $Object || $t2 == $dynamic;
+
+  // Check if t1 and t2 have the same raw type.  If so, check covariance on
+  // type parameters.
+  let raw1 = $getGenericClass($t1);
+  let raw2 = $getGenericClass($t2);
+  if (raw1 != null && raw1 == raw2) {
+    let typeArguments1 = $getGenericArgs($t1);
+    let typeArguments2 = $getGenericArgs($t2);
+    let length = typeArguments1.length;
+    if (typeArguments2.length == 0) {
+      // t2 is the raw form of t1
+      return true;
+    } else if (length == 0) {
+      // t1 is raw, but t2 is not
+      if (typeArguments2.every($_isTop)) return true;
+      return null;
+    }
+    if (length != typeArguments2.length) $assertFailed();
+    for (let i = 0; i < length; ++i) {
+      let result =
+          $_isSubtype(typeArguments1[i], typeArguments2[i], $isCovariant);
+      if (!result) {
+        return result;
+      }
+    }
+    return true;
+  }
+
+  let indefinite = false;
+  function definitive(t1, t2) {
+    let result = $_isInterfaceSubtype(t1, t2, $isCovariant);
+    if (result == null) {
+      indefinite = true;
+      return false;
+    }
+    return result;
+  }
+
+  if (definitive($t1.__proto__, $t2)) return true;
+
+  // Check mixin.
+  let m1 = $getMixin($t1);
+  if (m1 != null) {
+    if (definitive(m1, $t2)) return true;
+  }
+
+  // Check interfaces.
+  let getInterfaces = $getImplements($t1);
+  if (getInterfaces) {
+    for (let i1 of getInterfaces()) {
+      if (definitive(i1, $t2)) return true;
+    }
+  }
+
+  // We found no definite supertypes, and at least one indefinite supertype
+  // so the answer is indefinite.
+  if (indefinite) return null;
+  // We found no definite supertypes and no indefinite supertypes, so we
+  // can return false.
+  return false;
+})()''');
+
+Object extractTypeArguments<T>(T instance, Function f) {
+  if (instance == null) {
+    throw ArgumentError('Cannot extract type of null instance.');
+  }
+  var type = unwrapType(T);
+  if (type is AbstractFunctionType || _isFutureOr(type)) {
+    throw ArgumentError('Cannot extract from non-class type ($type).');
+  }
+  var typeArguments = getGenericArgs(type);
+  if (typeArguments.isEmpty) {
+    throw ArgumentError('Cannot extract from non-generic type ($type).');
+  }
+  var supertype = _getMatchingSupertype(getReifiedType(instance), type);
+  // The signature of this method guarantees that instance is a T, so we
+  // should have a valid non-empty list at this point.
+  assert(supertype != null);
+  var typeArgs = getGenericArgs(supertype);
+  assert(typeArgs != null && typeArgs.isNotEmpty);
+  return dgcall(f, typeArgs, []);
+}
+
+/// Infers type variables based on a series of [trySubtypeMatch] calls, followed
+/// by [getInferredTypes] to return the type.
+class _TypeInferrer {
+  final Map<TypeVariable, TypeConstraint> _typeVariables;
+
+  /// Creates a [TypeConstraintGatherer] which is prepared to gather type
+  /// constraints for the given type parameters.
+  _TypeInferrer(Iterable<TypeVariable> typeVariables)
+      : _typeVariables = Map.fromIterables(
+            typeVariables, typeVariables.map((_) => TypeConstraint()));
+
+  /// Returns the inferred types based on the current constraints.
+  List<Object> getInferredTypes() {
+    var result = List<Object>();
+    for (var constraint in _typeVariables.values) {
+      // Prefer the known bound, if any.
+      if (constraint.lower != null) {
+        result.add(constraint.lower);
+      } else if (constraint.upper != null) {
+        result.add(constraint.upper);
+      } else {
+        return null;
+      }
+    }
+    return result;
+  }
+
+  /// Tries to match [subtype] against [supertype].
+  ///
+  /// If the match succeeds, the resulting type constraints are recorded for
+  /// later use by [computeConstraints].  If the match fails, the set of type
+  /// constraints is unchanged.
+  bool trySubtypeMatch(Object subtype, Object supertype) =>
+      _isSubtypeMatch(subtype, supertype);
+
+  void _constrainLower(TypeVariable parameter, Object lower) {
+    _typeVariables[parameter]._constrainLower(lower);
+  }
+
+  void _constrainUpper(TypeVariable parameter, Object upper) {
+    _typeVariables[parameter]._constrainUpper(upper);
+  }
+
+  bool _isFunctionSubtypeMatch(FunctionType subtype, FunctionType supertype) {
+    // A function type `(M0,..., Mn, [M{n+1}, ..., Mm]) -> R0` is a subtype
+    // match for a function type `(N0,..., Nk, [N{k+1}, ..., Nr]) -> R1` with
+    // respect to `L` under constraints `C0 + ... + Cr + C`
+    // - If `R0` is a subtype match for a type `R1` with respect to `L` under
+    //   constraints `C`:
+    // - If `n <= k` and `r <= m`.
+    // - And for `i` in `0...r`, `Ni` is a subtype match for `Mi` with respect
+    //   to `L` under constraints `Ci`.
+    // Function types with named parameters are treated analogously to the
+    // positional parameter case above.
+    // A generic function type `<T0 extends B0, ..., Tn extends Bn>F0` is a
+    // subtype match for a generic function type `<S0 extends B0, ..., Sn
+    // extends Bn>F1` with respect to `L` under constraints `Cl`:
+    // - If `F0[Z0/T0, ..., Zn/Tn]` is a subtype match for `F0[Z0/S0, ...,
+    //   Zn/Sn]` with respect to `L` under constraints `C`, where each `Zi` is a
+    //   fresh type variable with bound `Bi`.
+    // - And `Cl` is `C` with each constraint replaced with its closure with
+    //   respect to `[Z0, ..., Zn]`.
+    if (subtype.requiredParameterCount > supertype.requiredParameterCount) {
+      return false;
+    }
+    if (subtype.positionalParameterCount < supertype.positionalParameterCount) {
+      return false;
+    }
+    // Test the return types.
+    if (supertype.returnType is! VoidType &&
+        !_isSubtypeMatch(subtype.returnType, supertype.returnType)) {
+      return false;
+    }
+
+    // Test the parameter types.
+    for (int i = 0, n = supertype.positionalParameterCount; i < n; ++i) {
+      if (!_isSubtypeMatch(supertype.getPositionalParameter(i),
+          subtype.getPositionalParameter(i))) {
+        return false;
+      }
+    }
+    var supertypeNamed = supertype.getNamedParameters();
+    var subtypeNamed = supertype.getNamedParameters();
+    for (var name in supertypeNamed.keys) {
+      var subtypeParamType = subtypeNamed[name];
+      if (subtypeParamType == null) return false;
+      if (!_isSubtypeMatch(supertypeNamed[name], subtypeParamType)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  bool _isInterfaceSubtypeMatch(Object subtype, Object supertype) {
+    // A type `P<M0, ..., Mk>` is a subtype match for `P<N0, ..., Nk>` with
+    // respect to `L` under constraints `C0 + ... + Ck`:
+    // - If `Mi` is a subtype match for `Ni` with respect to `L` under
+    //   constraints `Ci`.
+    // A type `P<M0, ..., Mk>` is a subtype match for `Q<N0, ..., Nj>` with
+    // respect to `L` under constraints `C`:
+    // - If `R<B0, ..., Bj>` is the superclass of `P<M0, ..., Mk>` and `R<B0,
+    //   ..., Bj>` is a subtype match for `Q<N0, ..., Nj>` with respect to `L`
+    //   under constraints `C`.
+    // - Or `R<B0, ..., Bj>` is one of the interfaces implemented by `P<M0, ...,
+    //   Mk>` (considered in lexical order) and `R<B0, ..., Bj>` is a subtype
+    //   match for `Q<N0, ..., Nj>` with respect to `L` under constraints `C`.
+    // - Or `R<B0, ..., Bj>` is a mixin into `P<M0, ..., Mk>` (considered in
+    //   lexical order) and `R<B0, ..., Bj>` is a subtype match for `Q<N0, ...,
+    //   Nj>` with respect to `L` under constraints `C`.
+
+    // Note that since kernel requires that no class may only appear in the set
+    // of supertypes of a given type more than once, the order of the checks
+    // above is irrelevant; we just need to find the matched superclass,
+    // substitute, and then iterate through type variables.
+    var matchingSupertype = _getMatchingSupertype(subtype, supertype);
+    if (matchingSupertype == null) return false;
+
+    var matchingTypeArgs = getGenericArgs(matchingSupertype);
+    var supertypeTypeArgs = getGenericArgs(supertype);
+    for (int i = 0; i < supertypeTypeArgs.length; i++) {
+      if (!_isSubtypeMatch(matchingTypeArgs[i], supertypeTypeArgs[i])) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  bool _isNull(Object type) => identical(type, unwrapType(Null));
+
+  /// Attempts to match [subtype] as a subtype of [supertype], gathering any
+  /// constraints discovered in the process.
+  ///
+  /// If a set of constraints was found, `true` is returned and the caller
+  /// may proceed to call [computeConstraints].  Otherwise, `false` is returned.
+  ///
+  /// In the case where `false` is returned, some bogus constraints may have
+  /// been added to [_protoConstraints].  It is the caller's responsibility to
+  /// discard them if necessary.
+  bool _isSubtypeMatch(Object subtype, Object supertype) {
+    // A type variable `T` in `L` is a subtype match for any type schema `Q`:
+    // - Under constraint `T <: Q`.
+    if (subtype is TypeVariable && _typeVariables.containsKey(subtype)) {
+      _constrainUpper(subtype, supertype);
+      return true;
+    }
+    // A type schema `Q` is a subtype match for a type variable `T` in `L`:
+    // - Under constraint `Q <: T`.
+    if (supertype is TypeVariable && _typeVariables.containsKey(supertype)) {
+      _constrainLower(supertype, subtype);
+      return true;
+    }
+    // Any two equal types `P` and `Q` are subtype matches under no constraints.
+    // Note: to avoid making the algorithm quadratic, we just check for
+    // identical().  If P and Q are equal but not identical, recursing through
+    // the types will give the proper result.
+    if (identical(subtype, supertype)) return true;
+    // Any type `P` is a subtype match for `dynamic`, `Object`, or `void` under
+    // no constraints.
+    if (_isTop(supertype)) return true;
+    // `Null` is a subtype match for any type `Q` under no constraints.
+    // Note that nullable types will change this.
+    if (_isNull(subtype)) return true;
+
+    // Handle FutureOr<T> union type.
+    if (_isFutureOr(subtype)) {
+      var subtypeArg = getGenericArgs(subtype)[0];
+      if (_isFutureOr(supertype)) {
+        // `FutureOr<P>` is a subtype match for `FutureOr<Q>` with respect to `L`
+        // under constraints `C`:
+        // - If `P` is a subtype match for `Q` with respect to `L` under constraints
+        //   `C`.
+        var supertypeArg = getGenericArgs(supertype)[0];
+        return _isSubtypeMatch(subtypeArg, supertypeArg);
+      }
+
+      // `FutureOr<P>` is a subtype match for `Q` with respect to `L` under
+      // constraints `C0 + C1`:
+      // - If `Future<P>` is a subtype match for `Q` with respect to `L` under
+      //   constraints `C0`.
+      // - And `P` is a subtype match for `Q` with respect to `L` under
+      //   constraints `C1`.
+      var subtypeFuture = JS('!', '#(#)', getGenericClass(Future), subtypeArg);
+      return _isSubtypeMatch(subtypeFuture, supertype) &&
+          _isSubtypeMatch(subtypeArg, supertype);
+    }
+
+    if (_isFutureOr(supertype)) {
+      // `P` is a subtype match for `FutureOr<Q>` with respect to `L` under
+      // constraints `C`:
+      // - If `P` is a subtype match for `Future<Q>` with respect to `L` under
+      //   constraints `C`.
+      // - Or `P` is not a subtype match for `Future<Q>` with respect to `L` under
+      //   constraints `C`
+      //   - And `P` is a subtype match for `Q` with respect to `L` under
+      //     constraints `C`
+      var supertypeArg = getGenericArgs(supertype)[0];
+      var supertypeFuture =
+          JS('!', '#(#)', getGenericClass(Future), supertypeArg);
+      return _isSubtypeMatch(subtype, supertypeFuture) ||
+          _isSubtypeMatch(subtype, supertypeArg);
+    }
+
+    // A type variable `T` not in `L` with bound `P` is a subtype match for the
+    // same type variable `T` with bound `Q` with respect to `L` under
+    // constraints `C`:
+    // - If `P` is a subtype match for `Q` with respect to `L` under constraints
+    //   `C`.
+    if (subtype is TypeVariable) {
+      return supertype is TypeVariable && identical(subtype, supertype);
+    }
+    if (subtype is GenericFunctionType) {
+      if (supertype is GenericFunctionType) {
+        // Given generic functions g1 and g2, g1 <: g2 iff:
+        //
+        //     g1<TFresh> <: g2<TFresh>
+        //
+        // where TFresh is a list of fresh type variables that both g1 and g2 will
+        // be instantiated with.
+        var formalCount = subtype.formalCount;
+        if (formalCount != supertype.formalCount) return false;
+
+        // Using either function's type formals will work as long as they're
+        // both instantiated with the same ones. The instantiate operation is
+        // guaranteed to avoid capture because it does not depend on its
+        // TypeVariable objects, rather it uses JS function parameters to ensure
+        // correct binding.
+        var fresh = supertype.typeFormals;
+
+        // Check the bounds of the type parameters of g1 and g2.
+        // given a type parameter `T1 extends U1` from g1, and a type parameter
+        // `T2 extends U2` from g2, we must ensure that:
+        //
+        //      U2 <: U1
+        //
+        // (Note the reversal of direction -- type formal bounds are
+        // contravariant, similar to the function's formal parameter types).
+        //
+        var t1Bounds = subtype.instantiateTypeBounds(fresh);
+        var t2Bounds = supertype.instantiateTypeBounds(fresh);
+        // TODO(jmesserly): we could optimize for the common case of no bounds.
+        for (var i = 0; i < formalCount; i++) {
+          if (!_isSubtypeMatch(t2Bounds[i], t1Bounds[i])) {
+            return false;
+          }
+        }
+        return _isFunctionSubtypeMatch(
+            subtype.instantiate(fresh), supertype.instantiate(fresh));
+      } else {
+        return false;
+      }
+    } else if (supertype is GenericFunctionType) {
+      return false;
+    }
+
+    // A type `P` is a subtype match for `Function` with respect to `L` under no
+    // constraints:
+    // - If `P` implements a call method.
+    // - Or if `P` is a function type.
+    // TODO(paulberry): implement this case.
+    // A type `P` is a subtype match for a type `Q` with respect to `L` under
+    // constraints `C`:
+    // - If `P` is an interface type which implements a call method of type `F`,
+    //   and `F` is a subtype match for a type `Q` with respect to `L` under
+    //   constraints `C`.
+    // TODO(paulberry): implement this case.
+    if (subtype is FunctionType) {
+      if (supertype is! FunctionType) {
+        if (identical(supertype, unwrapType(Function)) ||
+            identical(supertype, unwrapType(Object))) {
+          return true;
+        } else {
+          return false;
+        }
+      }
+      if (supertype is FunctionType) {
+        return _isFunctionSubtypeMatch(subtype, supertype);
+      }
+    }
+    return _isInterfaceSubtypeMatch(subtype, supertype);
+  }
+
+  bool _isTop(Object type) =>
+      identical(type, _dynamic) ||
+      identical(type, void_) ||
+      identical(type, unwrapType(Object));
+}
+
+/// A constraint on a type parameter that we're inferring.
+class TypeConstraint {
+  /// The lower bound of the type being constrained.  This bound must be a
+  /// subtype of the type being constrained.
+  Object lower;
+
+  /// The upper bound of the type being constrained.  The type being constrained
+  /// must be a subtype of this bound.
+  Object upper;
+
+  void _constrainLower(Object type) {
+    if (lower != null) {
+      if (isSubtypeOf(lower, type)) {
+        // nothing to do, existing lower bound is lower than the new one.
+        return;
+      }
+      if (!isSubtypeOf(type, lower)) {
+        // Neither bound is lower and we don't have GLB, so use bottom type.
+        type = unwrapType(Null);
+      }
+    }
+    lower = type;
+  }
+
+  void _constrainUpper(Object type) {
+    if (upper != null) {
+      if (isSubtypeOf(type, upper)) {
+        // nothing to do, existing upper bound is higher than the new one.
+        return;
+      }
+      if (!isSubtypeOf(upper, type)) {
+        // Neither bound is higher and we don't have LUB, so use top type.
+        type = unwrapType(Object);
+      }
+    }
+    upper = type;
+  }
+
+  String toString() => '${typeName(lower)} <: <type> <: ${typeName(upper)}';
+}
+
+/// Finds a supertype of [subtype] that matches the class [supertype], but may
+/// contain different generic type arguments.
+Object _getMatchingSupertype(Object subtype, Object supertype) {
+  if (identical(subtype, supertype)) return supertype;
+  if (subtype == null || subtype == unwrapType(Object)) return null;
+
+  var subclass = getGenericClass(subtype);
+  var superclass = getGenericClass(supertype);
+  if (subclass != null && identical(subclass, superclass)) {
+    return subtype; // matching supertype found!
+  }
+
+  var result = _getMatchingSupertype(JS('', '#.__proto__', subtype), supertype);
+  if (result != null) return result;
+
+  // Check mixin.
+  var mixin = getMixin(subtype);
+  if (mixin != null) {
+    result = _getMatchingSupertype(mixin, supertype);
+    if (result != null) return result;
+  }
+
+  // Check interfaces.
+  var getInterfaces = getImplements(subtype);
+  if (getInterfaces != null) {
+    for (var iface in getInterfaces()) {
+      result = _getMatchingSupertype(iface, supertype);
+      if (result != null) return result;
+    }
+  }
+
+  return null;
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/utils.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/utils.dart
rename to sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart
diff --git a/sdk/lib/_internal/js_dev_runtime/private/debugger.dart b/sdk/lib/_internal/js_dev_runtime/private/debugger.dart
new file mode 100644
index 0000000..69016fd
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/private/debugger.dart
@@ -0,0 +1,1016 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart._debugger;
+
+import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show JSArray;
+import 'dart:_js_helper' show InternalMap;
+import 'dart:_runtime' as dart;
+import 'dart:core';
+import 'dart:collection';
+import 'dart:html' as html;
+import 'dart:math';
+
+part 'profile.dart';
+
+/// JsonMLConfig object to pass to devtools to specify how an Object should
+/// be displayed. skipDart signals that an object should not be formatted
+/// by the Dart formatter. This is used to specify that an Object
+/// should just be displayed using the regular JavaScript view instead of a
+/// custom Dart view. For example, this is used to display the JavaScript view
+/// of a Dart Function as a child of the regular Function object. keyToString
+/// signals that a map key object should have its toString() displayed by
+/// the Dart formatter.
+///
+/// We'd like this to be an enum, but we can't because it's a dev_compiler bug.
+class JsonMLConfig {
+  const JsonMLConfig(this.name);
+
+  final String name;
+  static const none = JsonMLConfig("none");
+  static const skipDart = JsonMLConfig("skipDart");
+  static const keyToString = JsonMLConfig("keyToString");
+  static const asClass = JsonMLConfig("asClass");
+  static const asObject = JsonMLConfig("asObject");
+  static const asMap = JsonMLConfig("asMap");
+  toString() => "JsonMLConfig($name)";
+}
+
+int _maxSpanLength = 100;
+var _devtoolsFormatter = JsonMLFormatter(DartFormatter());
+
+/// We truncate a toString() longer than [maxStringLength].
+int maxFormatterStringLength = 100;
+
+String _typeof(object) => JS('String', 'typeof #', object);
+
+List<String> getOwnPropertyNames(object) =>
+    JSArray<String>.of(dart.getOwnPropertyNames(object));
+
+List getOwnPropertySymbols(object) =>
+    JS('List', 'Object.getOwnPropertySymbols(#)', object);
+
+// TODO(jacobr): move this to dart:js and fully implement.
+class JSNative {
+  // Name may be a String or a Symbol.
+  static getProperty(object, name) => JS('', '#[#]', object, name);
+  // Name may be a String or a Symbol.
+  static setProperty(object, name, value) =>
+      JS('', '#[#]=#', object, name, value);
+}
+
+void addMetadataChildren(object, Set<NameValuePair> ret) {
+  ret.add(NameValuePair(
+      name: "[[class]]",
+      value: dart.getReifiedType(object),
+      config: JsonMLConfig.asClass));
+}
+
+/// Add properties from a signature definition [sig] for [object].
+/// Walk the prototype chain if [walkProtypeChain] is set.
+/// Tag types on function typed properties of [object] if [tagTypes] is set.
+///
+void addPropertiesFromSignature(
+    sig, Set<NameValuePair> properties, object, bool walkPrototypeChain,
+    {tagTypes = false}) {
+  // Including these property names doesn't add any value and just clutters
+  // the debugger output.
+  // TODO(jacobr): consider adding runtimeType to this list.
+  var skippedNames = Set()..add('hashCode');
+  var objectPrototype = JS('', 'Object.prototype');
+  while (sig != null && !identical(sig, objectPrototype)) {
+    for (var symbol in getOwnPropertySymbols(sig)) {
+      var dartName = symbolName(symbol);
+      String dartXPrefix = 'dartx.';
+      if (dartName.startsWith(dartXPrefix)) {
+        dartName = dartName.substring(dartXPrefix.length);
+      }
+      if (skippedNames.contains(dartName)) continue;
+      var value = safeGetProperty(object, symbol);
+      // Tag the function with its runtime type.
+      if (tagTypes && _typeof(value) == 'function') {
+        dart.fn(value, JS('', '#[#]', sig, symbol));
+      }
+      properties.add(NameValuePair(name: dartName, value: value));
+    }
+
+    for (var name in getOwnPropertyNames(sig)) {
+      var value = safeGetProperty(object, name);
+      if (skippedNames.contains(name)) continue;
+      // Tag the function with its runtime type.
+      if (tagTypes && _typeof(value) == 'function') {
+        dart.fn(value, JS('', '#[#]', sig, name));
+      }
+      properties.add(NameValuePair(name: name, value: value));
+    }
+
+    if (!walkPrototypeChain) break;
+
+    sig = dart.getPrototypeOf(sig);
+  }
+}
+
+/// Sort properties sorting public names before private names.
+List<NameValuePair> sortProperties(Iterable<NameValuePair> properties) {
+  var sortedProperties = properties.toList();
+
+  sortedProperties.sort((a, b) {
+    var aPrivate = a.name.startsWith('_');
+    var bPrivate = b.name.startsWith('_');
+    if (aPrivate != bPrivate) return aPrivate ? 1 : -1;
+    return a.name.compareTo(b.name);
+  });
+  return sortedProperties;
+}
+
+String getObjectTypeName(object) {
+  var reifiedType = dart.getReifiedType(object);
+  if (reifiedType == null) {
+    if (_typeof(object) == 'function') {
+      return '[[Raw JavaScript Function]]';
+    }
+    return '<Error getting type name>';
+  }
+  return getTypeName(reifiedType);
+}
+
+String getTypeName(type) {
+  // TODO(jacobr): it would be nice if there was a way we could distinguish
+  // between a List<dynamic> created from Dart and an Array passed in from
+  // JavaScript.
+  return dart.typeName(type);
+}
+
+String safePreview(object, config) {
+  try {
+    var preview = _devtoolsFormatter._simpleFormatter.preview(object, config);
+    if (preview != null) return preview;
+    return object.toString();
+  } catch (e) {
+    return '<Exception thrown> $e';
+  }
+}
+
+String symbolName(symbol) {
+  var name = symbol.toString();
+  assert(name.startsWith('Symbol('));
+  return name.substring('Symbol('.length, name.length - 1);
+}
+
+bool hasMethod(object, String name) {
+  try {
+    return dart.hasMethod(object, name);
+  } catch (e) {
+    return false;
+  }
+}
+
+/// [JsonMLFormatter] consumes [NameValuePair] objects and
+class NameValuePair {
+  NameValuePair(
+      {this.name,
+      this.value,
+      this.config = JsonMLConfig.none,
+      this.hideName = false});
+
+  // Define equality and hashCode so that NameValuePair can be used
+  // in a Set to dedupe entries with duplicate names.
+  bool operator ==(other) {
+    if (other is! NameValuePair) return false;
+    if (this.hideName || other.hideName) return identical(this, other);
+    return other.name == name;
+  }
+
+  int get hashCode => name.hashCode;
+
+  final String name;
+  final Object value;
+  final JsonMLConfig config;
+  final bool hideName;
+
+  String get displayName => hideName ? '' : name;
+}
+
+class MapEntry {
+  MapEntry({this.key, this.value});
+
+  final Object key;
+  final Object value;
+}
+
+class IterableSpan {
+  IterableSpan(this.start, this.end, this.iterable);
+
+  final int start;
+  final int end;
+  final Iterable iterable;
+  int get length => end - start;
+
+  /// Using length - .5, a list of length 10000 results in a
+  /// maxPowerOfSubsetSize of 1, so the list will be broken up into 100,
+  /// 100-length subsets. A list of length 10001 results in a
+  /// maxPowerOfSubsetSize of 2, so the list will be broken up into 1
+  /// 10000-length subset and 1 1-length subset.
+  int get maxPowerOfSubsetSize =>
+      (log(length - .5) / log(_maxSpanLength)).truncate();
+  int get subsetSize => pow(_maxSpanLength, maxPowerOfSubsetSize);
+
+  Map<int, dynamic> asMap() =>
+      iterable.skip(start).take(length).toList().asMap();
+
+  List<NameValuePair> children() {
+    var children = <NameValuePair>[];
+    if (length <= _maxSpanLength) {
+      asMap().forEach((i, element) {
+        children
+            .add(NameValuePair(name: (i + start).toString(), value: element));
+      });
+    } else {
+      for (var i = start; i < end; i += subsetSize) {
+        var subSpan = IterableSpan(i, min(end, subsetSize + i), iterable);
+        if (subSpan.length == 1) {
+          children.add(
+              NameValuePair(name: i.toString(), value: iterable.elementAt(i)));
+        } else {
+          children.add(NameValuePair(
+              name: '[${i}...${subSpan.end - 1}]',
+              value: subSpan,
+              hideName: true));
+        }
+      }
+    }
+    return children;
+  }
+}
+
+class Library {
+  Library(this.name, this.object);
+
+  final String name;
+  final Object object;
+}
+
+class NamedConstructor {
+  NamedConstructor(this.object);
+
+  final Object object;
+}
+
+class HeritageClause {
+  HeritageClause(this.name, this.types);
+
+  final String name;
+  final List types;
+}
+
+Object safeGetProperty(Object protoChain, Object name) {
+  try {
+    return JSNative.getProperty(protoChain, name);
+  } catch (e) {
+    return '<Exception thrown> $e';
+  }
+}
+
+safeProperties(object) => Map.fromIterable(
+    getOwnPropertyNames(object)
+        .where((each) => safeGetProperty(object, each) != null),
+    key: (name) => name,
+    value: (name) => safeGetProperty(object, name));
+
+/// Class to simplify building the JsonML objects expected by the
+/// Devtools Formatter API.
+class JsonMLElement {
+  dynamic _attributes;
+  List _jsonML;
+
+  JsonMLElement(tagName) {
+    _attributes = JS('', '{}');
+    _jsonML = [tagName, _attributes];
+  }
+
+  appendChild(element) {
+    _jsonML.add(element.toJsonML());
+  }
+
+  JsonMLElement createChild(String tagName) {
+    var c = JsonMLElement(tagName);
+    _jsonML.add(c.toJsonML());
+    return c;
+  }
+
+  JsonMLElement createObjectTag(object) =>
+      createChild('object')..addAttribute('object', object);
+
+  void setStyle(String style) {
+    _attributes.style = style;
+  }
+
+  addStyle(String style) {
+    if (_attributes.style == null) {
+      _attributes.style = style;
+    } else {
+      _attributes.style += style;
+    }
+  }
+
+  addAttribute(key, value) {
+    JSNative.setProperty(_attributes, key, value);
+  }
+
+  createTextChild(String text) {
+    _jsonML.add(text);
+  }
+
+  toJsonML() => _jsonML;
+}
+
+/// Whether an object is a native JavaScript type where we should display the
+/// JavaScript view of the object instead of the custom Dart specific render
+/// of properties.
+bool isNativeJavaScriptObject(object) {
+  var type = _typeof(object);
+  if (type != 'object' && type != 'function') return true;
+
+  // Consider all regular JS objects that do not represent Dart modules native
+  // JavaScript objects.
+  if (dart.isJsInterop(object) && dart.getModuleName(object) == null) {
+    return true;
+  }
+
+  // Treat Node objects as a native JavaScript type as the regular DOM render
+  // in devtools is superior to the dart specific view.
+  return object is html.Node;
+}
+
+/// Class implementing the Devtools Formatter API described by:
+/// https://docs.google.com/document/d/1FTascZXT9cxfetuPRT2eXPQKXui4nWFivUnS_335T3U
+/// Specifically, a formatter implements a header, hasBody, and body method.
+/// This class renders the simple structured format objects [_simpleFormatter]
+/// provides as JsonML.
+class JsonMLFormatter {
+  // TODO(jacobr): define a SimpleFormatter base class that DartFormatter
+  // implements if we decide to use this class elsewhere. We specify that the
+  // type is DartFormatter here purely to get type checking benefits not because
+  // this class is really intended to only support instances of type
+  // DartFormatter.
+  DartFormatter _simpleFormatter;
+
+  bool customFormattersOn = false;
+
+  JsonMLFormatter(this._simpleFormatter);
+
+  void setMaxSpanLengthForTestingOnly(int spanLength) {
+    _maxSpanLength = spanLength;
+  }
+
+  header(object, config) {
+    customFormattersOn = true;
+    if (config == JsonMLConfig.skipDart || isNativeJavaScriptObject(object)) {
+      return null;
+    }
+    var c = _simpleFormatter.preview(object, config);
+    if (c == null) return null;
+
+    if (config == JsonMLConfig.keyToString) {
+      c = object.toString();
+    }
+
+    // Indicate this is a Dart Object by using a Dart background color.
+    // This is stylistically a bit ugly but it eases distinguishing Dart and
+    // JS objects.
+    var element = JsonMLElement('span')
+      ..setStyle('background-color: #d9edf7;color: black')
+      ..createTextChild(c);
+    return element.toJsonML();
+  }
+
+  bool hasBody(object, config) => _simpleFormatter.hasChildren(object, config);
+
+  body(object, config) {
+    var body = JsonMLElement('ol')
+      ..setStyle('list-style-type: none;'
+          'padding-left: 0px;'
+          'margin-top: 0px;'
+          'margin-bottom: 0px;'
+          'margin-left: 12px;');
+    if (object is StackTrace) {
+      body.addStyle('background-color: thistle;color: rgb(196, 26, 22);');
+    }
+    var children = _simpleFormatter.children(object, config);
+    if (children == null) return body.toJsonML();
+    for (NameValuePair child in children) {
+      var li = body.createChild('li');
+      li.setStyle("padding-left: 13px;");
+
+      // The value is indented when it is on a different line from the name
+      // by setting right padding of the name to -13px and the padding of the
+      // value to 13px.
+      JsonMLElement nameSpan;
+      var valueStyle = '';
+      if (!child.hideName) {
+        nameSpan = JsonMLElement('span')
+          ..createTextChild(
+              child.displayName.isNotEmpty ? '${child.displayName}: ' : '')
+          ..setStyle(
+              'background-color: thistle; color: rgb(136, 19, 145); margin-right: -13px');
+        valueStyle = 'margin-left: 13px';
+      }
+
+      if (_typeof(child.value) == 'object' ||
+          _typeof(child.value) == 'function') {
+        var valueSpan = JsonMLElement('span')..setStyle(valueStyle);
+        valueSpan.createObjectTag(child.value)
+          ..addAttribute('config', child.config);
+        if (nameSpan != null) {
+          li.appendChild(nameSpan);
+        }
+        li.appendChild(valueSpan);
+      } else {
+        var line = li.createChild('span');
+        if (nameSpan != null) {
+          line.appendChild(nameSpan);
+        }
+        line.appendChild(JsonMLElement('span')
+          ..createTextChild(safePreview(child.value, child.config))
+          ..setStyle(valueStyle));
+      }
+    }
+    return body.toJsonML();
+  }
+}
+
+abstract class Formatter {
+  bool accept(object, config);
+  String preview(object);
+  bool hasChildren(object);
+  List<NameValuePair> children(object);
+}
+
+class DartFormatter {
+  List<Formatter> _formatters;
+
+  DartFormatter() {
+    // The order of formatters matters as formatters earlier in the list take
+    // precedence.
+    _formatters = [
+      ObjectInternalsFormatter(),
+      ClassFormatter(),
+      TypeFormatter(),
+      NamedConstructorFormatter(),
+      MapFormatter(),
+      MapOverviewFormatter(),
+      IterableFormatter(),
+      IterableSpanFormatter(),
+      MapEntryFormatter(),
+      StackTraceFormatter(),
+      ErrorAndExceptionFormatter(),
+      FunctionFormatter(),
+      HeritageClauseFormatter(),
+      LibraryModuleFormatter(),
+      LibraryFormatter(),
+      ObjectFormatter(),
+    ];
+  }
+
+  String preview(object, config) {
+    try {
+      if (object == null ||
+          object is num ||
+          object is String ||
+          isNativeJavaScriptObject(object)) {
+        return object.toString();
+      }
+      for (var formatter in _formatters) {
+        if (formatter.accept(object, config)) return formatter.preview(object);
+      }
+    } catch (e, trace) {
+      // Log formatter internal errors as unfortunately the devtools cannot
+      // be used to debug formatter errors.
+      html.window.console.error("Caught exception $e\n trace:\n$trace");
+    }
+
+    return null;
+  }
+
+  bool hasChildren(object, config) {
+    if (object == null) return false;
+    try {
+      for (var formatter in _formatters) {
+        if (formatter.accept(object, config))
+          return formatter.hasChildren(object);
+      }
+    } catch (e, trace) {
+      // See comment for preview.
+      html.window.console
+          .error("[hasChildren] Caught exception $e\n trace:\n$trace");
+    }
+    return false;
+  }
+
+  List<NameValuePair> children(object, config) {
+    try {
+      if (object != null) {
+        for (var formatter in _formatters) {
+          if (formatter.accept(object, config))
+            return formatter.children(object);
+        }
+      }
+    } catch (e, trace) {
+      // See comment for preview.
+      html.window.console.error("Caught exception $e\n trace:\n$trace");
+    }
+    return <NameValuePair>[];
+  }
+}
+
+/// Default formatter for Dart Objects.
+class ObjectFormatter extends Formatter {
+  bool accept(object, config) => !isNativeJavaScriptObject(object);
+
+  String preview(object) {
+    var typeName = getObjectTypeName(object);
+    try {
+      // An explicit toString() call might not actually be a string. This way
+      // we're sure.
+      var toString = "$object";
+      if (toString.length > maxFormatterStringLength) {
+        toString = toString.substring(0, maxFormatterStringLength - 3) + "...";
+      }
+      // The default toString() will be "Instance of 'Foo'", in which case we
+      // don't need any further indication of the class.
+      if (toString.contains(typeName)) {
+        return toString;
+      } else {
+        // If there's no class indication, e.g. an Int64 that just prints as a
+        // number, then add the class name.
+        return "$toString ($typeName)";
+      }
+    } catch (e) {}
+    // We will only get here if there was an error getting the toString, in
+    // which case we just use the type name.
+    return typeName;
+  }
+
+  bool hasChildren(object) => true;
+
+  List<NameValuePair> children(object) {
+    var type = dart.getType(object);
+    var ret = LinkedHashSet<NameValuePair>();
+    // We use a Set rather than a List to avoid duplicates.
+    var fields = Set<NameValuePair>();
+    addPropertiesFromSignature(dart.getFields(type), fields, object, true);
+    var getters = Set<NameValuePair>();
+    addPropertiesFromSignature(dart.getGetters(type), getters, object, true);
+    ret.addAll(sortProperties(fields));
+    ret.addAll(sortProperties(getters));
+    addMetadataChildren(object, ret);
+    return ret.toList();
+  }
+}
+
+/// Show the object instance members and a reduced preview.
+///
+/// Used as a sub-entry to show the internals of objects that have a different
+/// primary format. For example, a Map shows the key-value pairs, but this makes
+/// the internals of the map visible for debugging.
+class ObjectInternalsFormatter extends ObjectFormatter {
+  bool accept(object, config) =>
+      super.accept(object, config) && config == JsonMLConfig.asObject;
+
+  // A minimal preview because we expect a full preview is already shown in a
+  // parent formatter.
+  String preview(object) {
+    return getObjectTypeName(object);
+  }
+}
+
+/// Formatter for module Dart Library objects.
+class LibraryModuleFormatter implements Formatter {
+  accept(object, config) => dart.getModuleName(object) != null;
+
+  bool hasChildren(object) => true;
+
+  String preview(object) {
+    var libraryNames = dart.getModuleName(object).split('/');
+    // Library names are received with a repeat directory name, so strip the
+    // last directory entry here to make the path cleaner. For example, the
+    // library "third_party/dart/utf/utf" shoud display as
+    // "third_party/dart/utf/".
+    if (libraryNames.length > 1 &&
+        libraryNames.last == libraryNames[libraryNames.length - 2]) {
+      libraryNames[libraryNames.length - 1] = '';
+    }
+    return 'Library Module: ${libraryNames.join('/')}';
+  }
+
+  List<NameValuePair> children(object) {
+    var children = LinkedHashSet<NameValuePair>();
+    for (var name in getOwnPropertyNames(object)) {
+      var value = safeGetProperty(object, name);
+      children.add(NameValuePair(
+          name: name, value: Library(name, value), hideName: true));
+    }
+    return children.toList();
+  }
+}
+
+class LibraryFormatter implements Formatter {
+  var genericParameters = HashMap<String, String>();
+
+  accept(object, config) => object is Library;
+
+  bool hasChildren(object) => true;
+
+  String preview(object) => object.name;
+
+  List<NameValuePair> children(object) {
+    // Maintain library member order rather than sorting members as is the
+    // case for class members.
+    var children = LinkedHashSet<NameValuePair>();
+    var objectProperties = safeProperties(object.object);
+    objectProperties.forEach((name, value) {
+      // Skip the generic constructors for each class as users are only
+      // interested in seeing the actual classes.
+      if (dart.getGenericTypeCtor(value) != null) return;
+
+      children.add(dart.isType(value)
+          ? classChild(name, value)
+          : NameValuePair(name: name, value: value));
+    });
+    return children.toList();
+  }
+
+  classChild(String name, Object child) {
+    var typeName = getTypeName(child);
+    return NameValuePair(
+        name: typeName, value: child, config: JsonMLConfig.asClass);
+  }
+}
+
+/// Formatter for Dart Function objects.
+/// Dart functions happen to be regular JavaScript Function objects but
+/// we can distinguish them based on whether they have been tagged with
+/// runtime type information.
+class FunctionFormatter implements Formatter {
+  accept(object, config) {
+    if (_typeof(object) != 'function') return false;
+    return dart.getReifiedType(object) != null;
+  }
+
+  bool hasChildren(object) => true;
+
+  String preview(object) {
+    // The debugger can createa a preview of a FunctionType while it's being
+    // constructed (before argument types exist), so we need to catch errors.
+    try {
+      return dart.typeName(dart.getReifiedType(object));
+    } catch (e) {
+      return safePreview(object, JsonMLConfig.none);
+    }
+  }
+
+  List<NameValuePair> children(object) => <NameValuePair>[
+        NameValuePair(name: 'signature', value: preview(object)),
+        NameValuePair(
+            name: 'JavaScript Function',
+            value: object,
+            config: JsonMLConfig.skipDart)
+      ];
+}
+
+/// Formatter for Objects that implement Map but are not system Maps.
+///
+/// This shows two sub-views, one for instance fields and one for
+/// Map key/value pairs.
+class MapOverviewFormatter implements Formatter {
+  // Because this comes after MapFormatter in the list, internal
+  // maps will be picked up by that formatter.
+  accept(object, config) => object is Map;
+
+  bool hasChildren(object) => true;
+
+  String preview(object) {
+    Map map = object;
+    try {
+      return '${getObjectTypeName(map)}';
+    } catch (e) {
+      return safePreview(object, JsonMLConfig.none);
+    }
+  }
+
+  List<NameValuePair> children(object) => [
+        NameValuePair(
+            name: "[[instance view]]",
+            value: object,
+            config: JsonMLConfig.asObject),
+        NameValuePair(
+            name: "[[entries]]", value: object, config: JsonMLConfig.asMap)
+      ];
+}
+
+/// Formatter for Dart Map objects.
+///
+/// This is only used for internal maps, or when shown as [[entries]]
+/// from MapOverViewFormatter.
+class MapFormatter implements Formatter {
+  accept(object, config) =>
+      object is InternalMap || config == JsonMLConfig.asMap;
+
+  bool hasChildren(object) => true;
+
+  String preview(object) {
+    Map map = object;
+    try {
+      return '${getObjectTypeName(map)} length ${map.length}';
+    } catch (e) {
+      return safePreview(object, JsonMLConfig.none);
+    }
+  }
+
+  List<NameValuePair> children(object) {
+    // TODO(jacobr): be lazier about enumerating contents of Maps that are not
+    // the build in LinkedHashMap class.
+    // TODO(jacobr): handle large Maps better.
+    Map map = object;
+    var entries = LinkedHashSet<NameValuePair>();
+    map.forEach((key, value) {
+      var entryWrapper = MapEntry(key: key, value: value);
+      entries.add(
+          NameValuePair(name: entries.length.toString(), value: entryWrapper));
+    });
+    addMetadataChildren(object, entries);
+    return entries.toList();
+  }
+}
+
+/// Formatter for Dart Iterable objects including List and Set.
+class IterableFormatter implements Formatter {
+  bool accept(object, config) => object is Iterable;
+
+  String preview(object) {
+    Iterable iterable = object;
+    try {
+      var length = iterable.length;
+      return '${getObjectTypeName(iterable)} length $length';
+    } catch (_) {
+      return '${getObjectTypeName(iterable)}';
+    }
+  }
+
+  bool hasChildren(object) => true;
+
+  List<NameValuePair> children(object) {
+    // TODO(jacobr): be lazier about enumerating contents of Iterables that
+    // are not the built in Set or List types.
+    // TODO(jacobr): handle large Iterables better.
+    // TODO(jacobr): consider only using numeric indices
+    var children = LinkedHashSet<NameValuePair>();
+    children.addAll(IterableSpan(0, object.length, object).children());
+    // TODO(jacobr): provide a link to show regular class properties here.
+    // required for subclasses of iterable, etc.
+    addMetadataChildren(object, children);
+    return children.toList();
+  }
+}
+
+class NamedConstructorFormatter implements Formatter {
+  accept(object, config) => object is NamedConstructor;
+
+  // TODO(bmilligan): Display the signature of the named constructor as the
+  // preview.
+  String preview(object) => 'Named Constructor';
+
+  bool hasChildren(object) => true;
+
+  List<NameValuePair> children(object) => <NameValuePair>[
+        NameValuePair(
+            name: 'JavaScript Function',
+            value: object,
+            config: JsonMLConfig.skipDart)
+      ];
+}
+
+/// Formatter for synthetic MapEntry objects used to display contents of a Map
+/// cleanly.
+class MapEntryFormatter implements Formatter {
+  accept(object, config) => object is MapEntry;
+
+  String preview(object) {
+    MapEntry entry = object;
+    return '${safePreview(entry.key, JsonMLConfig.none)} => ${safePreview(entry.value, JsonMLConfig.none)}';
+  }
+
+  bool hasChildren(object) => true;
+
+  List<NameValuePair> children(object) => <NameValuePair>[
+        NameValuePair(
+            name: 'key', value: object.key, config: JsonMLConfig.keyToString),
+        NameValuePair(name: 'value', value: object.value)
+      ];
+}
+
+/// Formatter for Dart Iterable objects including List and Set.
+class HeritageClauseFormatter implements Formatter {
+  bool accept(object, config) => object is HeritageClause;
+
+  String preview(object) {
+    HeritageClause clause = object;
+    var typeNames = clause.types.map(getTypeName);
+    return '${clause.name} ${typeNames.join(", ")}';
+  }
+
+  bool hasChildren(object) => true;
+
+  List<NameValuePair> children(object) {
+    HeritageClause clause = object;
+    var children = <NameValuePair>[];
+    for (var type in clause.types) {
+      children.add(NameValuePair(value: type, config: JsonMLConfig.asClass));
+    }
+    return children;
+  }
+}
+
+/// Formatter for synthetic IterableSpan objects used to display contents of
+/// an Iterable cleanly.
+class IterableSpanFormatter implements Formatter {
+  accept(object, config) => object is IterableSpan;
+
+  String preview(object) {
+    return '[${object.start}...${object.end - 1}]';
+  }
+
+  bool hasChildren(object) => true;
+
+  List<NameValuePair> children(object) => object.children();
+}
+
+/// Formatter for Dart Errors and Exceptions.
+class ErrorAndExceptionFormatter extends ObjectFormatter {
+  static final RegExp _pattern = RegExp(r'\d+\:\d+');
+
+  accept(object, config) => object is Error || object is Exception;
+
+  bool hasChildren(object) => true;
+
+  String preview(object) {
+    var trace = dart.stackTrace(object);
+    // TODO(vsm): Pull our stack mapping logic here.  We should aim to
+    // provide the first meaningful stack frame.
+    var line = '$trace'.split('\n').firstWhere(
+        (l) =>
+            l.contains(_pattern) &&
+            !l.contains('dart:sdk') &&
+            !l.contains('dart_sdk'),
+        orElse: () => null);
+    return line != null ? '${object} at ${line}' : '${object}';
+  }
+
+  List<NameValuePair> children(object) {
+    var trace = dart.stackTrace(object);
+    var entries = LinkedHashSet<NameValuePair>();
+    entries.add(NameValuePair(name: 'stackTrace', value: trace));
+    addInstanceMembers(object, entries);
+    addMetadataChildren(object, entries);
+    return entries.toList();
+  }
+
+  // Add an ObjectFormatter view underneath.
+  void addInstanceMembers(object, Set<NameValuePair> ret) {
+    ret.add(NameValuePair(
+        name: "[[instance members]]",
+        value: object,
+        config: JsonMLConfig.asObject));
+  }
+}
+
+class StackTraceFormatter implements Formatter {
+  accept(object, config) => object is StackTrace;
+
+  String preview(object) => 'StackTrace';
+
+  bool hasChildren(object) => true;
+
+  // Using the stack_trace formatting would be ideal, but adding the
+  // dependency or re-writing the code is too messy, so each line of the
+  // StackTrace will be added as its own child.
+  List<NameValuePair> children(object) => object
+      .toString()
+      .split('\n')
+      .map((line) => NameValuePair(
+          value: line.replaceFirst(RegExp(r'^\s+at\s'), ''), hideName: true))
+      .toList();
+}
+
+class ClassFormatter implements Formatter {
+  accept(object, config) => config == JsonMLConfig.asClass;
+
+  String preview(type) {
+    var implements = dart.getImplements(type);
+    var typeName = getTypeName(type);
+    if (implements != null) {
+      var typeNames = implements().map(getTypeName);
+      return '${typeName} implements ${typeNames.join(", ")}';
+    } else {
+      return typeName;
+    }
+  }
+
+  bool hasChildren(object) => true;
+
+  List<NameValuePair> children(type) {
+    // TODO(jacobr): add other entries describing the class such as
+    // implemented interfaces, and methods.
+    var ret = LinkedHashSet<NameValuePair>();
+
+    var staticProperties = Set<NameValuePair>();
+    var staticMethods = Set<NameValuePair>();
+    // Static fields and properties.
+    addPropertiesFromSignature(
+        dart.getStaticFields(type), staticProperties, type, false);
+    addPropertiesFromSignature(
+        dart.getStaticGetters(type), staticProperties, type, false);
+    // static methods.
+    addPropertiesFromSignature(
+        dart.getStaticMethods(type), staticMethods, type, false);
+
+    if (staticProperties.isNotEmpty || staticMethods.isNotEmpty) {
+      ret
+        ..add(NameValuePair(value: '[[Static members]]', hideName: true))
+        ..addAll(sortProperties(staticProperties))
+        ..addAll(sortProperties(staticMethods));
+    }
+
+    // instance methods.
+    var instanceMethods = Set<NameValuePair>();
+    // Instance methods are defined on the prototype not the constructor object.
+    addPropertiesFromSignature(dart.getMethods(type), instanceMethods,
+        JS('', '#.prototype', type), false,
+        tagTypes: true);
+    if (instanceMethods.isNotEmpty) {
+      ret
+        ..add(NameValuePair(value: '[[Instance Methods]]', hideName: true))
+        ..addAll(sortProperties(instanceMethods));
+    }
+
+    var mixin = dart.getMixin(type);
+    if (mixin != null) {
+      // TODO(jmesserly): this can only be one value.
+      ret.add(NameValuePair(
+          name: '[[Mixins]]', value: HeritageClause('mixins', [mixin])));
+    }
+
+    var baseProto = JS('', '#.__proto__', type);
+    if (baseProto != null && !dart.isJsInterop(baseProto)) {
+      ret.add(NameValuePair(
+          name: "[[base class]]",
+          value: baseProto,
+          config: JsonMLConfig.asClass));
+    }
+
+    // TODO(jacobr): add back fields for named constructors.
+    return ret.toList();
+  }
+}
+
+class TypeFormatter implements Formatter {
+  accept(object, config) => object is Type;
+
+  String preview(object) => object.toString();
+
+  bool hasChildren(object) => false;
+
+  List<NameValuePair> children(object) => [];
+}
+
+typedef String StackTraceMapper(String stackTrace);
+
+/// Hook for other parts of the SDK To use to map JS stack traces to Dart
+/// stack traces.
+///
+/// Raw JS stack traces are used if $dartStackTraceUtility has not been
+/// specified.
+StackTraceMapper get stackTraceMapper {
+  var _util = JS('', r'#.$dartStackTraceUtility', dart.global_);
+  return _util != null ? JS('!', '#.mapper', _util) : null;
+}
+
+/// This entry point is automatically invoked by the code generated by
+/// Dart Dev Compiler
+registerDevtoolsFormatter() {
+  JS('', '#.devtoolsFormatters = [#]', dart.global_, _devtoolsFormatter);
+}
+
+// These methods are exposed here for debugger tests.
+//
+// TODO(jmesserly): these are not exports because there is existing code that
+// calls into them from JS. Currently `dartdevc` always resolves exports at
+// compile time, so there is no need to make exports available at runtime by
+// copying properties. For that reason we cannot use re-export.
+//
+// If these methods are only for tests, we should move them here, or change the
+// tests to call the methods directly on dart:_runtime.
+List<String> getModuleNames() => dart.getModuleNames();
+getModuleLibraries(String name) => dart.getModuleLibraries(name);
diff --git a/pkg/dev_compiler/tool/input_sdk/private/foreign_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/foreign_helper.dart
rename to sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/identity_hash_map.dart b/sdk/lib/_internal/js_dev_runtime/private/identity_hash_map.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/identity_hash_map.dart
rename to sdk/lib/_internal/js_dev_runtime/private/identity_hash_map.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/interceptors.dart b/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/interceptors.dart
rename to sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart
rename to sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_array.dart b/sdk/lib/_internal/js_dev_runtime/private/js_array.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/js_array.dart
rename to sdk/lib/_internal/js_dev_runtime/private/js_array.dart
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
new file mode 100644
index 0000000..2f6750e
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
@@ -0,0 +1,826 @@
+// 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 dart._js_helper;
+
+import 'dart:collection';
+
+import 'dart:_foreign_helper' show JS, JS_STRING_CONCAT, JSExportName;
+
+import 'dart:_interceptors';
+import 'dart:_internal'
+    show
+        EfficientLengthIterable,
+        MappedIterable,
+        IterableElementError,
+        SubListIterable;
+
+import 'dart:_native_typed_data';
+import 'dart:_runtime' as dart;
+
+part 'annotations.dart';
+part 'linked_hash_map.dart';
+part 'identity_hash_map.dart';
+part 'custom_hash_map.dart';
+part 'native_helper.dart';
+part 'regexp_helper.dart';
+part 'string_helper.dart';
+part 'js_rti.dart';
+
+class _Patch {
+  const _Patch();
+}
+
+const _Patch patch = _Patch();
+
+/// Adapts a JS `[Symbol.iterator]` to a Dart `get iterator`.
+///
+/// This is the inverse of `JsIterator`, for classes where we can more
+/// efficiently obtain a JS iterator instead of a Dart one.
+///
+// TODO(jmesserly): this adapter is to work around
+// https://github.com/dart-lang/sdk/issues/28320
+class DartIterator<E> implements Iterator<E> {
+  final _jsIterator;
+  E _current;
+
+  DartIterator(this._jsIterator);
+
+  E get current => _current;
+
+  bool moveNext() {
+    final ret = JS('', '#.next()', _jsIterator);
+    _current = JS('', '#.value', ret);
+    return JS('bool', '!#.done', ret);
+  }
+}
+
+/// Used to compile `sync*`.
+class SyncIterable<E> extends IterableBase<E> {
+  final Function() _initGenerator;
+  SyncIterable(this._initGenerator);
+
+  @JSExportName('Symbol.iterator')
+  _jsIterator() => _initGenerator();
+
+  get iterator => DartIterator(_initGenerator());
+}
+
+class Primitives {
+  @NoInline()
+  static int _parseIntError(String source, int handleError(String source)) {
+    if (handleError == null) throw FormatException(source);
+    return handleError(source);
+  }
+
+  static int parseInt(
+      @nullCheck String source, int _radix, int handleError(String source)) {
+    var re = JS('', r'/^\s*[+-]?((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$/i');
+    // TODO(jmesserly): this isn't reified List<String>, but it's safe to use as
+    // long as we use it locally and don't expose it to user code.
+    List<String> match = JS('', '#.exec(#)', re, source);
+    int digitsIndex = 1;
+    int hexIndex = 2;
+    int decimalIndex = 3;
+    if (match == null) {
+      // TODO(sra): It might be that the match failed due to unrecognized U+0085
+      // spaces.  We could replace them with U+0020 spaces and try matching
+      // again.
+      return _parseIntError(source, handleError);
+    }
+    String decimalMatch = match[decimalIndex];
+    if (_radix == null) {
+      if (decimalMatch != null) {
+        // Cannot fail because we know that the digits are all decimal.
+        return JS('int', r'parseInt(#, 10)', source);
+      }
+      if (match[hexIndex] != null) {
+        // Cannot fail because we know that the digits are all hex.
+        return JS('int', r'parseInt(#, 16)', source);
+      }
+      return _parseIntError(source, handleError);
+    }
+    @notNull
+    var radix = _radix;
+    if (radix < 2 || radix > 36) {
+      throw RangeError.range(radix, 2, 36, 'radix');
+    }
+    if (radix == 10 && decimalMatch != null) {
+      // Cannot fail because we know that the digits are all decimal.
+      return JS('int', r'parseInt(#, 10)', source);
+    }
+    // If radix >= 10 and we have only decimal digits the string is safe.
+    // Otherwise we need to check the digits.
+    if (radix < 10 || decimalMatch == null) {
+      // We know that the characters must be ASCII as otherwise the
+      // regexp wouldn't have matched. Lowercasing by doing `| 0x20` is thus
+      // guaranteed to be a safe operation, since it preserves digits
+      // and lower-cases ASCII letters.
+      int maxCharCode;
+      if (radix <= 10) {
+        // Allow all digits less than the radix. For example 0, 1, 2 for
+        // radix 3.
+        // "0".codeUnitAt(0) + radix - 1;
+        maxCharCode = (0x30 - 1) + radix;
+      } else {
+        // Letters are located after the digits in ASCII. Therefore we
+        // only check for the character code. The regexp above made already
+        // sure that the string does not contain anything but digits or
+        // letters.
+        // "a".codeUnitAt(0) + (radix - 10) - 1;
+        maxCharCode = (0x61 - 10 - 1) + radix;
+      }
+      assert(match[digitsIndex] is String);
+      String digitsPart = JS('String', '#[#]', match, digitsIndex);
+      for (int i = 0; i < digitsPart.length; i++) {
+        int characterCode = digitsPart.codeUnitAt(i) | 0x20;
+        if (characterCode > maxCharCode) {
+          return _parseIntError(source, handleError);
+        }
+      }
+    }
+    // The above matching and checks ensures the source has at least one digits
+    // and all digits are suitable for the radix, so parseInt cannot return NaN.
+    return JS('int', r'parseInt(#, #)', source, radix);
+  }
+
+  @NoInline()
+  static double _parseDoubleError(
+      String source, double handleError(String source)) {
+    if (handleError == null) {
+      throw FormatException('Invalid double', source);
+    }
+    return handleError(source);
+  }
+
+  static double parseDouble(
+      @nullCheck String source, double handleError(String source)) {
+    // Notice that JS parseFloat accepts garbage at the end of the string.
+    // Accept only:
+    // - [+/-]NaN
+    // - [+/-]Infinity
+    // - a Dart double literal
+    // We do allow leading or trailing whitespace.
+    if (!JS(
+        'bool',
+        r'/^\s*[+-]?(?:Infinity|NaN|'
+            r'(?:\.\d+|\d+(?:\.\d*)?)(?:[eE][+-]?\d+)?)\s*$/.test(#)',
+        source)) {
+      return _parseDoubleError(source, handleError);
+    }
+    num result = JS('!', r'parseFloat(#)', source);
+    if (result.isNaN) {
+      var trimmed = source.trim();
+      if (trimmed == 'NaN' || trimmed == '+NaN' || trimmed == '-NaN') {
+        return result;
+      }
+      return _parseDoubleError(source, handleError);
+    }
+    return result;
+  }
+
+  /** `r"$".codeUnitAt(0)` */
+  static const int DOLLAR_CHAR_VALUE = 36;
+
+  static int dateNow() => JS('int', r'Date.now()');
+
+  static void initTicker() {
+    if (timerFrequency != null) return;
+    // Start with low-resolution. We overwrite the fields if we find better.
+    timerFrequency = 1000;
+    timerTicks = dateNow;
+    if (JS('bool', 'typeof window == "undefined"')) return;
+    var jsWindow = JS('var', 'window');
+    if (jsWindow == null) return;
+    var performance = JS('var', '#.performance', jsWindow);
+    if (performance == null) return;
+    if (JS('bool', 'typeof #.now != "function"', performance)) return;
+    timerFrequency = 1000000;
+    timerTicks = () => (1000 * JS<num>('!', '#.now()', performance)).floor();
+  }
+
+  static int timerFrequency;
+  static num Function() timerTicks;
+
+  static bool get isD8 {
+    return JS(
+        'bool',
+        'typeof version == "function"'
+            ' && typeof os == "object" && "system" in os');
+  }
+
+  static bool get isJsshell {
+    return JS(
+        'bool', 'typeof version == "function" && typeof system == "function"');
+  }
+
+  static String currentUri() {
+    // In a browser return self.location.href.
+    if (JS('bool', '!!#.location', dart.global_)) {
+      return JS('String', '#.location.href', dart.global_);
+    }
+
+    // TODO(vsm): Consider supporting properly in non-browser settings.
+    return '';
+  }
+
+  // This is to avoid stack overflows due to very large argument arrays in
+  // apply().  It fixes http://dartbug.com/6919
+  @notNull
+  static String _fromCharCodeApply(List<int> array) {
+    const kMaxApply = 500;
+    @nullCheck
+    int end = array.length;
+    if (end <= kMaxApply) {
+      return JS('String', r'String.fromCharCode.apply(null, #)', array);
+    }
+    String result = '';
+    for (int i = 0; i < end; i += kMaxApply) {
+      int chunkEnd = (i + kMaxApply < end) ? i + kMaxApply : end;
+      result = JS(
+          'String',
+          r'# + String.fromCharCode.apply(null, #.slice(#, #))',
+          result,
+          array,
+          i,
+          chunkEnd);
+    }
+    return result;
+  }
+
+  @notNull
+  static String stringFromCodePoints(JSArray<int> codePoints) {
+    List<int> a = <int>[];
+    for (@nullCheck var i in codePoints) {
+      if (i <= 0xffff) {
+        a.add(i);
+      } else if (i <= 0x10ffff) {
+        a.add(0xd800 + ((((i - 0x10000) >> 10) & 0x3ff)));
+        a.add(0xdc00 + (i & 0x3ff));
+      } else {
+        throw argumentErrorValue(i);
+      }
+    }
+    return _fromCharCodeApply(a);
+  }
+
+  @notNull
+  static String stringFromCharCodes(JSArray<int> charCodes) {
+    for (@nullCheck var i in charCodes) {
+      if (i < 0) throw argumentErrorValue(i);
+      if (i > 0xffff) return stringFromCodePoints(charCodes);
+    }
+    return _fromCharCodeApply(charCodes);
+  }
+
+  // [start] and [end] are validated.
+  @notNull
+  static String stringFromNativeUint8List(
+      NativeUint8List charCodes, @nullCheck int start, @nullCheck int end) {
+    const kMaxApply = 500;
+    if (end <= kMaxApply && start == 0 && end == charCodes.length) {
+      return JS('String', r'String.fromCharCode.apply(null, #)', charCodes);
+    }
+    String result = '';
+    for (int i = start; i < end; i += kMaxApply) {
+      int chunkEnd = (i + kMaxApply < end) ? i + kMaxApply : end;
+      result = JS(
+          'String',
+          r'# + String.fromCharCode.apply(null, #.subarray(#, #))',
+          result,
+          charCodes,
+          i,
+          chunkEnd);
+    }
+    return result;
+  }
+
+  @notNull
+  static String stringFromCharCode(@nullCheck int charCode) {
+    if (0 <= charCode) {
+      if (charCode <= 0xffff) {
+        return JS('String', 'String.fromCharCode(#)', charCode);
+      }
+      if (charCode <= 0x10ffff) {
+        var bits = charCode - 0x10000;
+        var low = 0xDC00 | (bits & 0x3ff);
+        var high = 0xD800 | (bits >> 10);
+        return JS('String', 'String.fromCharCode(#, #)', high, low);
+      }
+    }
+    throw RangeError.range(charCode, 0, 0x10ffff);
+  }
+
+  static String stringConcatUnchecked(String string1, String string2) {
+    return JS_STRING_CONCAT(string1, string2);
+  }
+
+  static String flattenString(String str) {
+    return JS('String', "#.charCodeAt(0) == 0 ? # : #", str, str, str);
+  }
+
+  static String getTimeZoneName(DateTime receiver) {
+    // Firefox and Chrome emit the timezone in parenthesis.
+    // Example: "Wed May 16 2012 21:13:00 GMT+0200 (CEST)".
+    // We extract this name using a regexp.
+    var d = lazyAsJsDate(receiver);
+    List match = JS('JSArray|Null', r'/\((.*)\)/.exec(#.toString())', d);
+    if (match != null) return match[1];
+
+    // Internet Explorer 10+ emits the zone name without parenthesis:
+    // Example: Thu Oct 31 14:07:44 PDT 2013
+    match = JS(
+        'JSArray|Null',
+        // Thu followed by a space.
+        r'/^[A-Z,a-z]{3}\s'
+            // Oct 31 followed by space.
+            r'[A-Z,a-z]{3}\s\d+\s'
+            // Time followed by a space.
+            r'\d{2}:\d{2}:\d{2}\s'
+            // The time zone name followed by a space.
+            r'([A-Z]{3,5})\s'
+            // The year.
+            r'\d{4}$/'
+            '.exec(#.toString())',
+        d);
+    if (match != null) return match[1];
+
+    // IE 9 and Opera don't provide the zone name. We fall back to emitting the
+    // UTC/GMT offset.
+    // Example (IE9): Wed Nov 20 09:51:00 UTC+0100 2013
+    //       (Opera): Wed Nov 20 2013 11:03:38 GMT+0100
+    match = JS('JSArray|Null', r'/(?:GMT|UTC)[+-]\d{4}/.exec(#.toString())', d);
+    if (match != null) return match[0];
+    return "";
+  }
+
+  static int getTimeZoneOffsetInMinutes(DateTime receiver) {
+    // Note that JS and Dart disagree on the sign of the offset.
+    return -JS('int', r'#.getTimezoneOffset()', lazyAsJsDate(receiver));
+  }
+
+  static num valueFromDecomposedDate(
+      @nullCheck int years,
+      @nullCheck int month,
+      @nullCheck int day,
+      @nullCheck int hours,
+      @nullCheck int minutes,
+      @nullCheck int seconds,
+      @nullCheck int milliseconds,
+      @nullCheck bool isUtc) {
+    final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000;
+    var jsMonth = month - 1;
+    num value;
+    if (isUtc) {
+      value = JS('!', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth, day,
+          hours, minutes, seconds, milliseconds);
+    } else {
+      value = JS('!', r'new Date(#, #, #, #, #, #, #).valueOf()', years,
+          jsMonth, day, hours, minutes, seconds, milliseconds);
+    }
+    if (value.isNaN ||
+        value < -MAX_MILLISECONDS_SINCE_EPOCH ||
+        value > MAX_MILLISECONDS_SINCE_EPOCH) {
+      return null;
+    }
+    if (years <= 0 || years < 100) return patchUpY2K(value, years, isUtc);
+    return value;
+  }
+
+  static num patchUpY2K(value, years, isUtc) {
+    var date = JS('', r'new Date(#)', value);
+    if (isUtc) {
+      JS('', r'#.setUTCFullYear(#)', date, years);
+    } else {
+      JS('', r'#.setFullYear(#)', date, years);
+    }
+    return JS('!', r'#.valueOf()', date);
+  }
+
+  // Lazily keep a JS Date stored in the JS object.
+  static lazyAsJsDate(DateTime receiver) {
+    if (JS('bool', r'#.date === (void 0)', receiver)) {
+      JS('void', r'#.date = new Date(#)', receiver,
+          receiver.millisecondsSinceEpoch);
+    }
+    return JS('var', r'#.date', receiver);
+  }
+
+  // The getters for date and time parts below add a positive integer to ensure
+  // that the result is really an integer, because the JavaScript implementation
+  // may return -0.0 instead of 0.
+
+  static int getYear(DateTime receiver) {
+    return (receiver.isUtc)
+        ? JS('int', r'(#.getUTCFullYear() + 0)', lazyAsJsDate(receiver))
+        : JS('int', r'(#.getFullYear() + 0)', lazyAsJsDate(receiver));
+  }
+
+  static int getMonth(DateTime receiver) {
+    return (receiver.isUtc)
+        ? JS('int', r'#.getUTCMonth() + 1', lazyAsJsDate(receiver))
+        : JS('int', r'#.getMonth() + 1', lazyAsJsDate(receiver));
+  }
+
+  static int getDay(DateTime receiver) {
+    return (receiver.isUtc)
+        ? JS('int', r'(#.getUTCDate() + 0)', lazyAsJsDate(receiver))
+        : JS('int', r'(#.getDate() + 0)', lazyAsJsDate(receiver));
+  }
+
+  static int getHours(DateTime receiver) {
+    return (receiver.isUtc)
+        ? JS('int', r'(#.getUTCHours() + 0)', lazyAsJsDate(receiver))
+        : JS('int', r'(#.getHours() + 0)', lazyAsJsDate(receiver));
+  }
+
+  static int getMinutes(DateTime receiver) {
+    return (receiver.isUtc)
+        ? JS('int', r'(#.getUTCMinutes() + 0)', lazyAsJsDate(receiver))
+        : JS('int', r'(#.getMinutes() + 0)', lazyAsJsDate(receiver));
+  }
+
+  static int getSeconds(DateTime receiver) {
+    return (receiver.isUtc)
+        ? JS('int', r'(#.getUTCSeconds() + 0)', lazyAsJsDate(receiver))
+        : JS('int', r'(#.getSeconds() + 0)', lazyAsJsDate(receiver));
+  }
+
+  static int getMilliseconds(DateTime receiver) {
+    return (receiver.isUtc)
+        ? JS('int', r'(#.getUTCMilliseconds() + 0)', lazyAsJsDate(receiver))
+        : JS('int', r'(#.getMilliseconds() + 0)', lazyAsJsDate(receiver));
+  }
+
+  static int getWeekday(DateTime receiver) {
+    int weekday = (receiver.isUtc)
+        ? JS('int', r'#.getUTCDay() + 0', lazyAsJsDate(receiver))
+        : JS('int', r'#.getDay() + 0', lazyAsJsDate(receiver));
+    // Adjust by one because JS weeks start on Sunday.
+    return (weekday + 6) % 7 + 1;
+  }
+
+  static num valueFromDateString(str) {
+    if (str is! String) throw argumentErrorValue(str);
+    num value = JS('!', r'Date.parse(#)', str);
+    if (value.isNaN) throw argumentErrorValue(str);
+    return value;
+  }
+
+  static getProperty(object, key) {
+    if (object == null || object is bool || object is num || object is String) {
+      throw argumentErrorValue(object);
+    }
+    return JS('var', '#[#]', object, key);
+  }
+
+  static void setProperty(object, key, value) {
+    if (object == null || object is bool || object is num || object is String) {
+      throw argumentErrorValue(object);
+    }
+    JS('void', '#[#] = #', object, key, value);
+  }
+}
+
+/**
+ * Diagnoses an indexing error. Returns the ArgumentError or RangeError that
+ * describes the problem.
+ */
+@NoInline()
+Error diagnoseIndexError(indexable, int index) {
+  int length = indexable.length;
+  // The following returns the same error that would be thrown by calling
+  // [RangeError.checkValidIndex] with no optional parameters provided.
+  if (index < 0 || index >= length) {
+    return RangeError.index(index, indexable, 'index', null, length);
+  }
+  // The above should always match, but if it does not, use the following.
+  return RangeError.value(index, 'index');
+}
+
+/**
+ * Diagnoses a range error. Returns the ArgumentError or RangeError that
+ * describes the problem.
+ */
+@NoInline()
+Error diagnoseRangeError(int start, int end, int length) {
+  if (start == null) {
+    return ArgumentError.value(start, 'start');
+  }
+  if (start < 0 || start > length) {
+    return RangeError.range(start, 0, length, 'start');
+  }
+  if (end != null) {
+    if (end < start || end > length) {
+      return RangeError.range(end, start, length, 'end');
+    }
+  }
+  // The above should always match, but if it does not, use the following.
+  return ArgumentError.value(end, "end");
+}
+
+@notNull
+int stringLastIndexOfUnchecked(receiver, element, start) =>
+    JS('int', r'#.lastIndexOf(#, #)', receiver, element, start);
+
+/// 'factory' for constructing ArgumentError.value to keep the call sites small.
+@NoInline()
+ArgumentError argumentErrorValue(object) {
+  return ArgumentError.value(object);
+}
+
+void throwArgumentErrorValue(value) {
+  throw argumentErrorValue(value);
+}
+
+checkInt(value) {
+  if (value is! int) throw argumentErrorValue(value);
+  return value;
+}
+
+throwRuntimeError(message) {
+  throw RuntimeError(message);
+}
+
+throwAbstractClassInstantiationError(className) {
+  throw AbstractClassInstantiationError(className);
+}
+
+@NoInline()
+throwConcurrentModificationError(collection) {
+  throw ConcurrentModificationError(collection);
+}
+
+class JsNoSuchMethodError extends Error implements NoSuchMethodError {
+  final String _message;
+  final String _method;
+  final String _receiver;
+
+  JsNoSuchMethodError(this._message, match)
+      : _method = match == null ? null : JS('String|Null', '#.method', match),
+        _receiver =
+            match == null ? null : JS('String|Null', '#.receiver', match);
+
+  String toString() {
+    if (_method == null) return 'NoSuchMethodError: $_message';
+    if (_receiver == null) {
+      return "NoSuchMethodError: method not found: '$_method' ($_message)";
+    }
+    return "NoSuchMethodError: "
+        "method not found: '$_method' on '$_receiver' ($_message)";
+  }
+}
+
+class UnknownJsTypeError extends Error {
+  final String _message;
+
+  UnknownJsTypeError(this._message);
+
+  String toString() => _message.isEmpty ? 'Error' : 'Error: $_message';
+}
+
+/**
+ * Called by generated code to build a map literal. [keyValuePairs] is
+ * a list of key, value, key, value, ..., etc.
+ */
+fillLiteralMap(keyValuePairs, Map result) {
+  // TODO(johnniwinther): Use JSArray to optimize this code instead of calling
+  // [getLength] and [getIndex].
+  int index = 0;
+  int length = getLength(keyValuePairs);
+  while (index < length) {
+    var key = getIndex(keyValuePairs, index++);
+    var value = getIndex(keyValuePairs, index++);
+    result[key] = value;
+  }
+  return result;
+}
+
+bool jsHasOwnProperty(var jsObject, String property) {
+  return JS('bool', r'#.hasOwnProperty(#)', jsObject, property);
+}
+
+jsPropertyAccess(var jsObject, String property) {
+  return JS('var', r'#[#]', jsObject, property);
+}
+
+/**
+ * Called at the end of unaborted switch cases to get the singleton
+ * FallThroughError exception that will be thrown.
+ */
+getFallThroughError() => FallThroughErrorImplementation();
+
+/**
+ * A metadata annotation describing the types instantiated by a native element.
+ *
+ * The annotation is valid on a native method and a field of a native class.
+ *
+ * By default, a field of a native class is seen as an instantiation point for
+ * all native classes that are a subtype of the field's type, and a native
+ * method is seen as an instantiation point fo all native classes that are a
+ * subtype of the method's return type, or the argument types of the declared
+ * type of the method's callback parameter.
+ *
+ * An @[Creates] annotation overrides the default set of instantiated types.  If
+ * one or more @[Creates] annotations are present, the type of the native
+ * element is ignored, and the union of @[Creates] annotations is used instead.
+ * The names in the strings are resolved and the program will fail to compile
+ * with dart2js if they do not name types.
+ *
+ * The argument to [Creates] is a string.  The string is parsed as the names of
+ * one or more types, separated by vertical bars `|`.  There are some special
+ * names:
+ *
+ * * `=Object`. This means 'exactly Object', which is a plain JavaScript object
+ *   with properties and none of the subtypes of Object.
+ *
+ * Example: we may know that a method always returns a specific implementation:
+ *
+ *     @Creates('_NodeList')
+ *     List<Node> getElementsByTagName(String tag) native;
+ *
+ * Useful trick: A method can be marked as not instantiating any native classes
+ * with the annotation `@Creates('Null')`.  This is useful for fields on native
+ * classes that are used only in Dart code.
+ *
+ *     @Creates('Null')
+ *     var _cachedFoo;
+ */
+class Creates {
+  final String types;
+  const Creates(this.types);
+}
+
+/**
+ * A metadata annotation describing the types returned or yielded by a native
+ * element.
+ *
+ * The annotation is valid on a native method and a field of a native class.
+ *
+ * By default, a native method or field is seen as returning or yielding all
+ * subtypes if the method return type or field type.  This annotation allows a
+ * more precise set of types to be specified.
+ *
+ * See [Creates] for the syntax of the argument.
+ *
+ * Example: IndexedDB keys are numbers, strings and JavaScript Arrays of keys.
+ *
+ *     @Returns('String|num|JSExtendableArray')
+ *     dynamic key;
+ *
+ *     // Equivalent:
+ *     @Returns('String') @Returns('num') @Returns('JSExtendableArray')
+ *     dynamic key;
+ */
+class Returns {
+  final String types;
+  const Returns(this.types);
+}
+
+/**
+ * A metadata annotation placed on native methods and fields of native classes
+ * to specify the JavaScript name.
+ *
+ * This example declares a Dart field + getter + setter called `$dom_title` that
+ * corresponds to the JavaScript property `title`.
+ *
+ *     class Document native "*Foo" {
+ *       @JSName('title')
+ *       String $dom_title;
+ *     }
+ */
+class JSName {
+  final String name;
+  const JSName(this.name);
+}
+
+/**
+ * Special interface recognized by the compiler and implemented by DOM
+ * objects that support integer indexing. This interface is not
+ * visible to anyone, and is only injected into special libraries.
+ */
+abstract class JavaScriptIndexingBehavior<E> {}
+
+// TODO(lrn): These exceptions should be implemented in core.
+// When they are, remove the 'Implementation' here.
+
+/// Thrown by type assertions that fail.
+class TypeErrorImpl extends Error implements TypeError {
+  final String message;
+
+  TypeErrorImpl(this.message);
+
+  String toString() => message;
+}
+
+/// Thrown by the 'as' operator if the cast isn't valid.
+class CastErrorImpl extends Error implements CastError {
+  final String message;
+
+  CastErrorImpl(this.message);
+
+  String toString() => message;
+}
+
+class FallThroughErrorImplementation extends FallThroughError {
+  String toString() => "Switch case fall-through.";
+}
+
+/**
+ * Error thrown when a runtime error occurs.
+ */
+class RuntimeError extends Error {
+  final message;
+  RuntimeError(this.message);
+  String toString() => "RuntimeError: $message";
+}
+
+/// Error thrown by DDC when an `assert()` fails (with or without a message).
+class AssertionErrorImpl extends AssertionError {
+  final String _fileUri;
+  final int _line;
+  final int _column;
+  final String _conditionSource;
+
+  AssertionErrorImpl(Object message,
+      [this._fileUri, this._line, this._column, this._conditionSource])
+      : super(message);
+
+  String toString() {
+    var failureMessage = "";
+    if (_fileUri != null &&
+        _line != null &&
+        _column != null &&
+        _conditionSource != null) {
+      failureMessage += "$_fileUri:${_line}:${_column}\n$_conditionSource\n";
+    }
+    failureMessage +=
+        message != null ? Error.safeToString(message) : "is not true";
+
+    return "Assertion failed: $failureMessage";
+  }
+}
+
+/**
+ * Creates a random number with 64 bits of randomness.
+ *
+ * This will be truncated to the 53 bits available in a double.
+ */
+int random64() {
+  // TODO(lrn): Use a secure random source.
+  int int32a = JS("int", "(Math.random() * 0x100000000) >>> 0");
+  int int32b = JS("int", "(Math.random() * 0x100000000) >>> 0");
+  return int32a + int32b * 0x100000000;
+}
+
+class BooleanConversionAssertionError extends AssertionError {
+  toString() => 'Failed assertion: boolean expression must not be null';
+}
+
+// Hook to register new global object.  This is invoked from dart:html
+// whenever a new window is accessed for the first time.
+void registerGlobalObject(object) {
+  try {
+    if (dart.polyfill(object)) {
+      dart.applyAllExtensions(object);
+    }
+  } catch (e) {
+    // This may fail due to cross-origin errors.  In that case, we shouldn't
+    // need to polyfill as we can't get objects from that frame.
+
+    // TODO(vsm): Detect this more robustly - ideally before we try to polyfill.
+  }
+}
+
+/// Expose browser JS classes.
+void applyExtension(name, nativeObject) {
+  dart.applyExtension(name, nativeObject);
+}
+
+/// Used internally by DDC to map ES6 symbols to Dart.
+class PrivateSymbol implements Symbol {
+  // TODO(jmesserly): could also get this off the native symbol instead of
+  // storing it. Mirrors already does this conversion.
+  final String _name;
+  final Object _nativeSymbol;
+
+  const PrivateSymbol(this._name, this._nativeSymbol);
+
+  static String getName(Symbol symbol) => (symbol as PrivateSymbol)._name;
+
+  static Object getNativeSymbol(Symbol symbol) {
+    if (symbol is PrivateSymbol) return symbol._nativeSymbol;
+    return null;
+  }
+
+  bool operator ==(other) =>
+      other is PrivateSymbol &&
+      _name == other._name &&
+      identical(_nativeSymbol, other._nativeSymbol);
+
+  get hashCode => _name.hashCode;
+
+  // TODO(jmesserly): is this equivalent to _nativeSymbol toString?
+  toString() => 'Symbol("$_name")';
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dart b/sdk/lib/_internal/js_dev_runtime/private/js_mirrors.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dart
rename to sdk/lib/_internal/js_dev_runtime/private/js_mirrors.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_number.dart b/sdk/lib/_internal/js_dev_runtime/private/js_number.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/js_number.dart
rename to sdk/lib/_internal/js_dev_runtime/private/js_number.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_primitives.dart b/sdk/lib/_internal/js_dev_runtime/private/js_primitives.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/js_primitives.dart
rename to sdk/lib/_internal/js_dev_runtime/private/js_primitives.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_rti.dart b/sdk/lib/_internal/js_dev_runtime/private/js_rti.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/js_rti.dart
rename to sdk/lib/_internal/js_dev_runtime/private/js_rti.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_string.dart b/sdk/lib/_internal/js_dev_runtime/private/js_string.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/js_string.dart
rename to sdk/lib/_internal/js_dev_runtime/private/js_string.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/linked_hash_map.dart b/sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/linked_hash_map.dart
rename to sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/mirror_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/mirror_helper.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/mirror_helper.dart
rename to sdk/lib/_internal/js_dev_runtime/private/mirror_helper.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/native_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/native_helper.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/native_helper.dart
rename to sdk/lib/_internal/js_dev_runtime/private/native_helper.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/native_typed_data.dart b/sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/native_typed_data.dart
rename to sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/preambles/README b/sdk/lib/_internal/js_dev_runtime/private/preambles/README
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/preambles/README
rename to sdk/lib/_internal/js_dev_runtime/private/preambles/README
diff --git a/pkg/dev_compiler/tool/input_sdk/private/preambles/d8.js b/sdk/lib/_internal/js_dev_runtime/private/preambles/d8.js
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/preambles/d8.js
rename to sdk/lib/_internal/js_dev_runtime/private/preambles/d8.js
diff --git a/pkg/dev_compiler/tool/input_sdk/private/preambles/jsshell.js b/sdk/lib/_internal/js_dev_runtime/private/preambles/jsshell.js
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/preambles/jsshell.js
rename to sdk/lib/_internal/js_dev_runtime/private/preambles/jsshell.js
diff --git a/pkg/dev_compiler/tool/input_sdk/private/profile.dart b/sdk/lib/_internal/js_dev_runtime/private/profile.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/profile.dart
rename to sdk/lib/_internal/js_dev_runtime/private/profile.dart
diff --git a/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
new file mode 100644
index 0000000..1c31a09
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
@@ -0,0 +1,283 @@
+// 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.
+
+part of dart._js_helper;
+
+// Helper method used by internal libraries.
+regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp;
+
+/**
+ * Returns a native version of the RegExp with the global flag set.
+ *
+ * The RegExp's `lastIndex` property is zero when it is returned.
+ *
+ * The returned regexp is shared, and its `lastIndex` property may be
+ * modified by other uses, so the returned regexp must be used immediately
+ * when it's returned, with no user-provided code run in between.
+ */
+regExpGetGlobalNative(JSSyntaxRegExp regexp) {
+  var nativeRegexp = regexp._nativeGlobalVersion;
+  JS("void", "#.lastIndex = 0", nativeRegexp);
+  return nativeRegexp;
+}
+
+/**
+ * Computes the number of captures in a regexp.
+ *
+ * This currently involves creating a new RegExp object with a different
+ * source and running it against the empty string (the last part is usually
+ * fast).
+ *
+ * The JSSyntaxRegExp could cache the result, and set the cache any time
+ * it finds a match.
+ */
+int regExpCaptureCount(JSSyntaxRegExp regexp) {
+  var nativeAnchoredRegExp = regexp._nativeAnchoredVersion;
+  JSExtendableArray match =
+      JS('JSExtendableArray', "#.exec('')", nativeAnchoredRegExp);
+  // The native-anchored regexp always have one capture more than the original,
+  // and always matches the empty string.
+  return match.length - 2;
+}
+
+class JSSyntaxRegExp implements RegExp {
+  final String pattern;
+  final _nativeRegExp;
+  var _nativeGlobalRegExp;
+  var _nativeAnchoredRegExp;
+
+  String toString() =>
+      'RegExp/$pattern/' + JS('String', '#.flags', _nativeRegExp);
+
+  JSSyntaxRegExp(String source,
+      {bool multiLine = false,
+      bool caseSensitive = true,
+      bool unicode = false,
+      bool dotAll = false})
+      : this.pattern = source,
+        this._nativeRegExp = makeNative(
+            source, multiLine, caseSensitive, unicode, dotAll, false);
+
+  get _nativeGlobalVersion {
+    if (_nativeGlobalRegExp != null) return _nativeGlobalRegExp;
+    return _nativeGlobalRegExp = makeNative(
+        pattern, _isMultiLine, _isCaseSensitive, _isUnicode, _isDotAll, true);
+  }
+
+  get _nativeAnchoredVersion {
+    if (_nativeAnchoredRegExp != null) return _nativeAnchoredRegExp;
+    // An "anchored version" of a regexp is created by adding "|()" to the
+    // source. This means that the regexp always matches at the first position
+    // that it tries, and you can see if the original regexp matched, or it
+    // was the added zero-width match that matched, by looking at the last
+    // capture. If it is a String, the match participated, otherwise it didn't.
+    return _nativeAnchoredRegExp = makeNative("$pattern|()", _isMultiLine,
+        _isCaseSensitive, _isUnicode, _isDotAll, true);
+  }
+
+  bool get _isMultiLine => JS("bool", "#.multiline", _nativeRegExp);
+  bool get _isCaseSensitive => JS("bool", "!#.ignoreCase", _nativeRegExp);
+  bool get _isUnicode => JS("bool", "#.unicode", _nativeRegExp);
+  bool get _isDotAll => JS("bool", "#.dotAll", _nativeRegExp);
+
+  static makeNative(@nullCheck String source, bool multiLine,
+      bool caseSensitive, bool unicode, bool dotAll, bool global) {
+    String m = multiLine ? 'm' : '';
+    String i = caseSensitive ? '' : 'i';
+    String u = unicode ? 'u' : '';
+    String s = dotAll ? 's' : '';
+    String g = global ? 'g' : '';
+    // We're using the JavaScript's try catch instead of the Dart one
+    // to avoid dragging in Dart runtime support just because of using
+    // RegExp.
+    var regexp = JS(
+        '',
+        '(function() {'
+            'try {'
+            'return new RegExp(#, # + # + # + # + #);'
+            '} catch (e) {'
+            'return e;'
+            '}'
+            '})()',
+        source,
+        m,
+        i,
+        u,
+        s,
+        g);
+    if (JS('bool', '# instanceof RegExp', regexp)) return regexp;
+    // The returned value is the JavaScript exception. Turn it into a
+    // Dart exception.
+    String errorMessage = JS('String', r'String(#)', regexp);
+    throw FormatException("Illegal RegExp pattern: $source, $errorMessage");
+  }
+
+  RegExpMatch firstMatch(@nullCheck String string) {
+    List m = JS('JSExtendableArray|Null', r'#.exec(#)', _nativeRegExp, string);
+    if (m == null) return null;
+    return _MatchImplementation(this, JSArray<String>.of(m));
+  }
+
+  @notNull
+  bool hasMatch(@nullCheck String string) {
+    return JS('bool', r'#.test(#)', _nativeRegExp, string);
+  }
+
+  String stringMatch(String string) {
+    var match = firstMatch(string);
+    if (match != null) return match.group(0);
+    return null;
+  }
+
+  Iterable<RegExpMatch> allMatches(@nullCheck String string,
+      [@nullCheck int start = 0]) {
+    if (start < 0 || start > string.length) {
+      throw RangeError.range(start, 0, string.length);
+    }
+    return _AllMatchesIterable(this, string, start);
+  }
+
+  RegExpMatch _execGlobal(String string, int start) {
+    Object regexp = _nativeGlobalVersion;
+    JS("void", "#.lastIndex = #", regexp, start);
+    List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string);
+    if (match == null) return null;
+    return _MatchImplementation(this, JSArray<String>.of(match));
+  }
+
+  RegExpMatch _execAnchored(String string, int start) {
+    Object regexp = _nativeAnchoredVersion;
+    JS("void", "#.lastIndex = #", regexp, start);
+    List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string);
+    if (match == null) return null;
+    // If the last capture group participated, the original regexp did not
+    // match at the start position.
+    if (match[match.length - 1] != null) return null;
+    match.length -= 1;
+    return _MatchImplementation(this, JSArray<String>.of(match));
+  }
+
+  RegExpMatch matchAsPrefix(String string, [int start = 0]) {
+    if (start < 0 || start > string.length) {
+      throw RangeError.range(start, 0, string.length);
+    }
+    return _execAnchored(string, start);
+  }
+
+  bool get isMultiLine => _isMultiLine;
+  bool get isCaseSensitive => _isCaseSensitive;
+  bool get isUnicode => _isUnicode;
+  bool get isDotAll => _isDotAll;
+}
+
+class _MatchImplementation implements RegExpMatch {
+  final Pattern pattern;
+  // Contains a JS RegExp match object.
+  // It is an Array of String values with extra "index" and "input" properties.
+  final List<String> _match;
+
+  _MatchImplementation(this.pattern, this._match) {
+    assert(JS("var", "#.input", _match) is String);
+    assert(JS("var", "#.index", _match) is int);
+  }
+
+  String get input => JS("String", "#.input", _match);
+  int get start => JS("int", "#.index", _match);
+  int get end => start + _match[0].length;
+
+  String group(int index) => _match[index];
+  String operator [](int index) => group(index);
+  int get groupCount => _match.length - 1;
+
+  List<String> groups(List<int> groups) {
+    List<String> out = [];
+    for (int i in groups) {
+      out.add(group(i));
+    }
+    return out;
+  }
+
+  String namedGroup(String name) {
+    var groups = JS('Object', '#.groups', _match);
+    if (groups != null) {
+      var result = JS('String|Null', '#[#]', groups, name);
+      if (result != null || JS('bool', '# in #', name, groups)) {
+        return result;
+      }
+    }
+    throw ArgumentError.value(name, "name", "Not a capture group name");
+  }
+
+  Iterable<String> get groupNames {
+    var groups = JS('Object', '#.groups', _match);
+    if (groups != null) {
+      var keys = JSArray<String>.of(JS('', 'Object.keys(#)', groups));
+      return SubListIterable(keys, 0, null);
+    }
+    return Iterable.empty();
+  }
+}
+
+class _AllMatchesIterable extends IterableBase<RegExpMatch> {
+  final JSSyntaxRegExp _re;
+  final String _string;
+  final int _start;
+
+  _AllMatchesIterable(this._re, this._string, this._start);
+
+  Iterator<RegExpMatch> get iterator =>
+      _AllMatchesIterator(_re, _string, _start);
+}
+
+class _AllMatchesIterator implements Iterator<RegExpMatch> {
+  final JSSyntaxRegExp _regExp;
+  String _string;
+  int _nextIndex;
+  RegExpMatch _current;
+
+  _AllMatchesIterator(this._regExp, this._string, this._nextIndex);
+
+  RegExpMatch get current => _current;
+
+  static bool _isLeadSurrogate(int c) {
+    return c >= 0xd800 && c <= 0xdbff;
+  }
+
+  static bool _isTrailSurrogate(int c) {
+    return c >= 0xdc00 && c <= 0xdfff;
+  }
+
+  bool moveNext() {
+    if (_string == null) return false;
+    if (_nextIndex <= _string.length) {
+      var match = _regExp._execGlobal(_string, _nextIndex);
+      if (match != null) {
+        _current = match;
+        int nextIndex = match.end;
+        if (match.start == nextIndex) {
+          // Zero-width match. Advance by one more, unless the regexp
+          // is in unicode mode and it would put us within a surrogate
+          // pair. In that case, advance past the code point as a whole.
+          if (_regExp.isUnicode &&
+              _nextIndex + 1 < _string.length &&
+              _isLeadSurrogate(_string.codeUnitAt(_nextIndex)) &&
+              _isTrailSurrogate(_string.codeUnitAt(_nextIndex + 1))) {
+            nextIndex++;
+          }
+          nextIndex++;
+        }
+        _nextIndex = nextIndex;
+        return true;
+      }
+    }
+    _current = null;
+    _string = null; // Marks iteration as ended.
+    return false;
+  }
+}
+
+/** Find the first match of [regExp] in [string] at or after [start]. */
+RegExpMatch firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) {
+  return regExp._execGlobal(string, start);
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/string_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/string_helper.dart
similarity index 100%
rename from pkg/dev_compiler/tool/input_sdk/private/string_helper.dart
rename to sdk/lib/_internal/js_dev_runtime/private/string_helper.dart
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index e31fe29..5fc220c 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -528,9 +528,15 @@
   @pragma('dart2js:noInline')
   @patch
   factory RegExp(String source,
-          {bool multiLine: false, bool caseSensitive: true}) =>
+          {bool multiLine: false,
+          bool caseSensitive: true,
+          bool unicode: false,
+          bool dotAll: false}) =>
       new JSSyntaxRegExp(source,
-          multiLine: multiLine, caseSensitive: caseSensitive);
+          multiLine: multiLine,
+          caseSensitive: caseSensitive,
+          unicode: unicode,
+          dotAll: dotAll);
 
   @patch
   static String escape(String text) => quoteStringForRegExp(text);
@@ -734,15 +740,6 @@
   }
 }
 
-Uri _resolvePackageUri(Uri packageUri) {
-  assert(packageUri.scheme == "package");
-  if (packageUri.hasAuthority) {
-    throw new ArgumentError("Package-URI must not have a host: $packageUri");
-  }
-  var resolved = Uri.base.resolve("packages/${packageUri.path}");
-  return resolved;
-}
-
 bool _hasErrorStackProperty = JS('bool', 'new Error().stack != void 0');
 
 @patch
@@ -2346,6 +2343,7 @@
         _rsh(uDigits, maxUsed, 1, uDigits);
         if (ac) {
           if (((aDigits[0] & 1) == 1) || ((bDigits[0] & 1) == 1)) {
+            // a += y
             if (aIsNegative) {
               if ((aDigits[maxUsed] != 0) ||
                   (_compareDigits(aDigits, maxUsed, yDigits, maxUsed)) > 0) {
@@ -2357,6 +2355,7 @@
             } else {
               _absAdd(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
             }
+            // b -= x
             if (bIsNegative) {
               _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
             } else if ((bDigits[maxUsed] != 0) ||
@@ -2369,6 +2368,7 @@
           }
           _rsh(aDigits, abcdUsed, 1, aDigits);
         } else if ((bDigits[0] & 1) == 1) {
+          // b -= x
           if (bIsNegative) {
             _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
           } else if ((bDigits[maxUsed] != 0) ||
@@ -2385,6 +2385,7 @@
         _rsh(vDigits, maxUsed, 1, vDigits);
         if (ac) {
           if (((cDigits[0] & 1) == 1) || ((dDigits[0] & 1) == 1)) {
+            // c += y
             if (cIsNegative) {
               if ((cDigits[maxUsed] != 0) ||
                   (_compareDigits(cDigits, maxUsed, yDigits, maxUsed) > 0)) {
@@ -2396,6 +2397,7 @@
             } else {
               _absAdd(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
             }
+            // d -= x
             if (dIsNegative) {
               _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
             } else if ((dDigits[maxUsed] != 0) ||
@@ -2408,6 +2410,7 @@
           }
           _rsh(cDigits, abcdUsed, 1, cDigits);
         } else if ((dDigits[0] & 1) == 1) {
+          // d -= x
           if (dIsNegative) {
             _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
           } else if ((dDigits[maxUsed] != 0) ||
@@ -2421,8 +2424,10 @@
         _rsh(dDigits, abcdUsed, 1, dDigits);
       }
       if (_compareDigits(uDigits, maxUsed, vDigits, maxUsed) >= 0) {
+        // u -= v
         _absSub(uDigits, maxUsed, vDigits, maxUsed, uDigits);
         if (ac) {
+          // a -= c
           if (aIsNegative == cIsNegative) {
             var a_cmp_c = _compareDigits(aDigits, abcdUsed, cDigits, abcdUsed);
             if (a_cmp_c > 0) {
@@ -2435,6 +2440,7 @@
             _absAdd(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
           }
         }
+        // b -= d
         if (bIsNegative == dIsNegative) {
           var b_cmp_d = _compareDigits(bDigits, abcdUsed, dDigits, abcdUsed);
           if (b_cmp_d > 0) {
@@ -2447,8 +2453,10 @@
           _absAdd(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
         }
       } else {
+        // v -= u
         _absSub(vDigits, maxUsed, uDigits, maxUsed, vDigits);
         if (ac) {
+          // c -= a
           if (cIsNegative == aIsNegative) {
             var c_cmp_a = _compareDigits(cDigits, abcdUsed, aDigits, abcdUsed);
             if (c_cmp_a > 0) {
@@ -2461,6 +2469,7 @@
             _absAdd(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
           }
         }
+        // d -= b
         if (dIsNegative == bIsNegative) {
           var d_cmp_b = _compareDigits(dDigits, abcdUsed, bDigits, abcdUsed);
           if (d_cmp_b > 0) {
@@ -2492,25 +2501,18 @@
     }
 
     if (dIsNegative) {
-      if ((dDigits[maxUsed] != 0) ||
+      while ((dDigits[maxUsed] != 0) ||
           (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+        // d += x, d still negative
         _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        if ((dDigits[maxUsed] != 0) ||
-            (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-          _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        } else {
-          _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-          dIsNegative = false;
-        }
-      } else {
-        _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-        dIsNegative = false;
       }
-    } else if ((dDigits[maxUsed] != 0) ||
-        (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-      _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-      if ((dDigits[maxUsed] != 0) ||
-          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+      // d += x
+      _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+      dIsNegative = false;
+    } else {
+      while ((dDigits[maxUsed] != 0) ||
+        (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) >= 0)) {
+        // d -= x
         _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
       }
     }
diff --git a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart b/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
index 56bab4c..d781e7a 100644
--- a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
@@ -7,6 +7,7 @@
 import "dart:async";
 import 'dart:_foreign_helper' show JS;
 import 'dart:_js_helper' show patch;
+import "dart:typed_data" show ByteData, TypedData, Uint8List;
 
 @patch
 class Isolate {
@@ -32,11 +33,7 @@
 
   @patch
   static Future<Uri> resolvePackageUri(Uri packageUri) {
-    if (packageUri.scheme != 'package') {
-      return new Future<Uri>.value(packageUri);
-    }
-    return new Future<Uri>.value(
-        _packagesBase.resolveUri(packageUri.replace(scheme: '')));
+    throw new UnsupportedError("Isolate.resolvePackageUri");
   }
 
   @patch
@@ -146,9 +143,10 @@
   }
 }
 
-/// Returns the base path added to Uri.base to resolve `package:` Uris.
-///
-/// This is used by `Isolate.resolvePackageUri` to load resources. The default
-/// value is `packages/` but users can override this by using the
-/// `defaultPackagesBase` hook.
-Uri _packagesBase = Uri.base.resolve(JS('String', r'self.defaultPackagesBase'));
+@patch
+abstract class TransferableTypedData {
+  @patch
+  factory TransferableTypedData.fromList(List<TypedData> list) {
+    throw new UnsupportedError('TransferableTypedData.fromList');
+  }
+}
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 7205568..beee35b 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -59,6 +59,8 @@
         unmangleGlobalNameIfPreservedAnyways,
         unmangleAllIdentifiersIfPreservedAnyways;
 
+import 'dart:_rti' as newRti show getRuntimeType;
+
 part 'annotations.dart';
 part 'constant_map.dart';
 part 'instantiation.dart';
diff --git a/sdk/lib/_internal/js_runtime/lib/js_rti.dart b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
index e4b0f9d..6250aa0 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
@@ -391,6 +391,7 @@
 }
 
 Type getRuntimeType(var object) {
+  if (JS_GET_FLAG('USE_NEW_RTI')) return newRti.getRuntimeType(object);
   return new TypeImpl(getRti(object));
 }
 
diff --git a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
index 51b4bfb..3dacc06 100644
--- a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
@@ -42,18 +42,22 @@
   var _nativeGlobalRegExp;
   var _nativeAnchoredRegExp;
 
-  String toString() => 'RegExp/$pattern/';
+  String toString() =>
+      'RegExp/$pattern/' + JS('String', '#.flags', _nativeRegExp);
 
   JSSyntaxRegExp(String source,
-      {bool multiLine: false, bool caseSensitive: true})
+      {bool multiLine: false,
+      bool caseSensitive: true,
+      bool unicode: false,
+      bool dotAll: false})
       : this.pattern = source,
-        this._nativeRegExp =
-            makeNative(source, multiLine, caseSensitive, false);
+        this._nativeRegExp = makeNative(
+            source, multiLine, caseSensitive, unicode, dotAll, false);
 
   get _nativeGlobalVersion {
     if (_nativeGlobalRegExp != null) return _nativeGlobalRegExp;
-    return _nativeGlobalRegExp =
-        makeNative(pattern, _isMultiLine, _isCaseSensitive, true);
+    return _nativeGlobalRegExp = makeNative(
+        pattern, _isMultiLine, _isCaseSensitive, _isUnicode, _isDotAll, true);
   }
 
   get _nativeAnchoredVersion {
@@ -63,18 +67,22 @@
     // that it tries, and you can see if the original regexp matched, or it
     // was the added zero-width match that matched, by looking at the last
     // capture. If it is a String, the match participated, otherwise it didn't.
-    return _nativeAnchoredRegExp =
-        makeNative('$pattern|()', _isMultiLine, _isCaseSensitive, true);
+    return _nativeAnchoredRegExp = makeNative('$pattern|()', _isMultiLine,
+        _isCaseSensitive, _isUnicode, _isDotAll, true);
   }
 
   bool get _isMultiLine => JS('bool', '#.multiline', _nativeRegExp);
   bool get _isCaseSensitive => JS('bool', '!#.ignoreCase', _nativeRegExp);
+  bool get _isUnicode => JS('bool', '#.unicode', _nativeRegExp);
+  bool get _isDotAll => JS('bool', '#.dotAll', _nativeRegExp);
 
-  static makeNative(
-      String source, bool multiLine, bool caseSensitive, bool global) {
+  static makeNative(String source, bool multiLine, bool caseSensitive,
+      bool unicode, bool dotAll, bool global) {
     checkString(source);
     String m = multiLine == true ? 'm' : '';
     String i = caseSensitive == true ? '' : 'i';
+    String u = unicode ? 'u' : '';
+    String s = dotAll ? 's' : '';
     String g = global ? 'g' : '';
     // We're using the JavaScript's try catch instead of the Dart one to avoid
     // dragging in Dart runtime support just because of using RegExp.
@@ -87,10 +95,12 @@
             } catch (e) {
               return e;
             }
-          })(#, # + # + #)''',
+          })(#, # + # + # + # + #)''',
         source,
         m,
         i,
+        u,
+        s,
         g);
     if (JS('bool', '# instanceof RegExp', regexp)) return regexp;
     // The returned value is the JavaScript exception. Turn it into a
@@ -99,7 +109,7 @@
     throw new FormatException('Illegal RegExp pattern ($errorMessage)', source);
   }
 
-  Match firstMatch(String string) {
+  RegExpMatch firstMatch(String string) {
     List m = JS('JSExtendableArray|Null', r'#.exec(#)', _nativeRegExp,
         checkString(string));
     if (m == null) return null;
@@ -116,7 +126,7 @@
     return null;
   }
 
-  Iterable<Match> allMatches(String string, [int start = 0]) {
+  Iterable<RegExpMatch> allMatches(String string, [int start = 0]) {
     checkString(string);
     checkInt(start);
     if (start < 0 || start > string.length) {
@@ -125,7 +135,7 @@
     return new _AllMatchesIterable(this, string, start);
   }
 
-  Match _execGlobal(String string, int start) {
+  RegExpMatch _execGlobal(String string, int start) {
     Object regexp = _nativeGlobalVersion;
     JS('void', '#.lastIndex = #', regexp, start);
     List match = JS('JSExtendableArray|Null', '#.exec(#)', regexp, string);
@@ -133,7 +143,7 @@
     return new _MatchImplementation(this, match);
   }
 
-  Match _execAnchored(String string, int start) {
+  RegExpMatch _execAnchored(String string, int start) {
     Object regexp = _nativeAnchoredVersion;
     JS('void', '#.lastIndex = #', regexp, start);
     List match = JS('JSExtendableArray|Null', '#.exec(#)', regexp, string);
@@ -144,7 +154,7 @@
     return new _MatchImplementation(this, match);
   }
 
-  Match matchAsPrefix(String string, [int start = 0]) {
+  RegExpMatch matchAsPrefix(String string, [int start = 0]) {
     if (start < 0 || start > string.length) {
       throw new RangeError.range(start, 0, string.length);
     }
@@ -153,6 +163,8 @@
 
   bool get isMultiLine => _isMultiLine;
   bool get isCaseSensitive => _isCaseSensitive;
+  bool get isUnicode => _isUnicode;
+  bool get isDotAll => _isDotAll;
 }
 
 class _MatchImplementation implements RegExpMatch {
@@ -219,25 +231,34 @@
   }
 }
 
-class _AllMatchesIterable extends IterableBase<Match> {
+class _AllMatchesIterable extends IterableBase<RegExpMatch> {
   final JSSyntaxRegExp _re;
   final String _string;
   final int _start;
 
   _AllMatchesIterable(this._re, this._string, this._start);
 
-  Iterator<Match> get iterator => new _AllMatchesIterator(_re, _string, _start);
+  Iterator<RegExpMatch> get iterator =>
+      new _AllMatchesIterator(_re, _string, _start);
 }
 
-class _AllMatchesIterator implements Iterator<Match> {
+class _AllMatchesIterator implements Iterator<RegExpMatch> {
   final JSSyntaxRegExp _regExp;
   String _string;
   int _nextIndex;
-  Match _current;
+  RegExpMatch _current;
 
   _AllMatchesIterator(this._regExp, this._string, this._nextIndex);
 
-  Match get current => _current;
+  RegExpMatch get current => _current;
+
+  static bool _isLeadSurrogate(int c) {
+    return c >= 0xd800 && c <= 0xdbff;
+  }
+
+  static bool _isTrailSurrogate(int c) {
+    return c >= 0xdc00 && c <= 0xdfff;
+  }
 
   bool moveNext() {
     if (_string == null) return false;
@@ -247,6 +268,15 @@
         _current = match;
         int nextIndex = match.end;
         if (match.start == nextIndex) {
+          // Zero-width match. Advance by one more, unless the regexp
+          // is in unicode mode and it would put us within a surrogate
+          // pair. In that case, advance past the code point as a whole.
+          if (_regExp.isUnicode &&
+              _nextIndex + 1 < _string.length &&
+              _isLeadSurrogate(_string.codeUnitAt(_nextIndex)) &&
+              _isTrailSurrogate(_string.codeUnitAt(_nextIndex + 1))) {
+            nextIndex++;
+          }
           nextIndex++;
         }
         _nextIndex = nextIndex;
@@ -260,6 +290,6 @@
 }
 
 /// Find the first match of [regExp] in [string] at or after [start].
-Match firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) {
+RegExpMatch firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) {
   return regExp._execGlobal(string, start);
 }
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
new file mode 100644
index 0000000..574cd52
--- /dev/null
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -0,0 +1,660 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library contains support for runtime type information.
+library rti;
+
+import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show JSArray, JSUnmodifiableArray;
+
+/// An Rti object represents both a type (e.g `Map<int, String>`) and a type
+/// environment (`Map<int, String>` binds `Map.K=int` and `Map.V=String`).
+///
+/// There is a single [Rti] class to help reduce polymorphism in the JavaScript
+/// runtime. The class has a default constructor and no final fields so it can
+/// be created before much of the runtime exists.
+///
+/// The fields are declared in an order that gets shorter minified names for the
+/// more commonly used fields. (TODO: we should exploit the fact that an Rti
+/// instance never appears in a dynamic context, so does not need field names to
+/// be distinct from dynamic selectors).
+///
+class Rti {
+  /// JavaScript method for 'as' check. The method is called from generated code,
+  /// e.g. `o as T` generates something like `rtiForT._as(o)`.
+  @pragma('dart2js:noElision')
+  dynamic _as;
+
+  /// JavaScript method for type check.  The method is called from generated
+  /// code, e.g. parameter check for `T param` generates something like
+  /// `rtiForT._check(param)`.
+  @pragma('dart2js:noElision')
+  dynamic _check;
+
+  /// JavaScript method for 'is' test.  The method is called from generated
+  /// code, e.g. `o is T` generates something like `rtiForT._is(o)`.
+  @pragma('dart2js:noElision')
+  dynamic _is;
+
+  static void _setAsCheckFunction(Rti rti, fn) {
+    rti._as = fn;
+  }
+
+  static void _setTypeCheckFunction(Rti rti, fn) {
+    rti._check = fn;
+  }
+
+  static void _setIsTestFunction(Rti rti, fn) {
+    rti._is = fn;
+  }
+
+  /// Method called from generated code to evaluate a type environment recipe in
+  /// `this` type environment.
+  Rti _eval(String recipe) => _rtiEval(this, recipe);
+
+  /// Method called from generated code to extend `this` type environment with a
+  /// function type parameter.
+  Rti _bind1(Rti type) => _rtiBind1(this, type);
+
+  /// Method called from generated code to extend `this` type environment with a
+  /// tuple of function type parameters.
+  Rti _bind(Rti typeTuple) => _rtiBind(this, typeTuple);
+
+  // Precomputed derived types. These fields are used to hold derived types that
+  // are computed eagerly.
+  // TODO(sra): Implement precomputed type optimizations.
+  dynamic _precomputed1;
+  dynamic _precomputed2;
+  dynamic _precomputed3;
+  dynamic _precomputed4;
+
+  // The Type object corresponding to this Rti.
+  Type _typeCache;
+
+  /// The kind of Rti `this` is, one of the kindXXX constants below.
+  ///
+  /// We don't use an enum since we need to create Rti objects very early.
+  ///
+  /// The zero initializer ensures dart2js type analysis considers [_kind] is
+  /// non-nullable.
+  int _kind = 0;
+
+  static int _getKind(Rti rti) => rti._kind;
+  static void _setKind(Rti rti, int kind) {
+    rti._kind = kind;
+  }
+
+  // Terminal terms.
+  static const kindNever = 1;
+  static const kindDynamic = 2;
+  static const kindVoid = 3; // TODO(sra): Use `dynamic` instead?
+  static const kindAny = 4; // Dart1-style 'dynamic' for JS-interop.
+  // Unary terms.
+  static const kindStar = 5;
+  static const kindQuestion = 6;
+  static const kindFutureOr = 7;
+  // More complex terms.
+  static const kindInterface = 8;
+  // A vector of type parameters from enclosing functions and closures.
+  static const kindBinding = 9;
+  static const kindFunction = 10;
+  static const kindGenericFunction = 11;
+
+  /// Primary data associated with type.
+  ///
+  /// - Minified name of interface for interface types.
+  /// - Underlying type for unary terms.
+  /// - Class part of a type environment inside a generic class, or `null` for
+  ///   type tuple.
+  /// - Return type of function types.
+  dynamic _primary;
+
+  static Object _getPrimary(Rti rti) => rti._primary;
+  static void _setPrimary(Rti rti, value) {
+    rti._primary = value;
+  }
+
+  /// Additional data associated with type.
+  ///
+  /// - The type arguments of an interface type.
+  /// - The type arguments from enclosing functions and closures for a
+  ///   kindBinding.
+  /// - TBD for kindFunction and kindGenericFunction.
+  dynamic _rest;
+
+  static Object _getRest(Rti rti) => rti._rest;
+  static void _setRest(Rti rti, value) {
+    rti._rest = value;
+  }
+
+  static String _getInterfaceName(Rti rti) {
+    assert(_getKind(rti) == kindInterface);
+    return _Utils.asString(_getPrimary(rti));
+  }
+
+  static JSArray _getInterfaceTypeArguments(rti) {
+    // The array is a plain JavaScript Array, otherwise we would need the type
+    // `JSArray<Rti>` to exist before we could create the type `JSArray<Rti>`.
+    assert(_getKind(rti) == kindInterface);
+    return JS('JSUnmodifiableArray', '#', _getRest(rti));
+  }
+
+  /// On [Rti]s that are type environments, derived types are cached on the
+  /// environment to ensure fast canonicalization. Ground-term types (i.e. not
+  /// dependent on class or function type parameters) are cached in the
+  /// universe. This field starts as `null` and the cache is created on demand.
+  Object _evalCache;
+
+  static Object _getEvalCache(Rti rti) => rti._evalCache;
+  static void _setEvalCache(Rti rti, value) {
+    rti._evalCache = value;
+  }
+
+  static Rti allocate() {
+    return new Rti();
+  }
+
+  String _canonicalRecipe;
+
+  static String _getCanonicalRecipe(Rti rti) {
+    var s = rti._canonicalRecipe;
+    assert(_Utils.isString(s), 'Missing canonical recipe');
+    return _Utils.asString(s);
+  }
+
+  static void _setCanonicalRecipe(Rti rti, String s) {
+    rti._canonicalRecipe = s;
+  }
+}
+
+Rti _rtiEval(Rti environment, String recipe) {
+  throw UnimplementedError('_rtiEval');
+}
+
+Rti _rtiBind1(Rti environment, Rti type) {
+  throw UnimplementedError('_rtiBind1');
+}
+
+Rti _rtiBind(Rti environment, Rti typeTuple) {
+  throw UnimplementedError('_rtiBind');
+}
+
+Type getRuntimeType(object) {
+  throw UnimplementedError('getRuntimeType');
+}
+
+String _rtiToString(Rti rti, List<String> genericContext) {
+  int kind = Rti._getKind(rti);
+  if (kind == Rti.kindDynamic) return 'dynamic';
+  if (kind == Rti.kindInterface) {
+    String name = Rti._getInterfaceName(rti);
+    var arguments = Rti._getInterfaceTypeArguments(rti);
+    if (arguments.length != 0) {
+      name += '<';
+      for (int i = 0; i < arguments.length; i++) {
+        if (i > 0) name += ', ';
+        name += _rtiToString(_castToRti(arguments[i]), genericContext);
+      }
+      name += '>';
+    }
+    return name;
+  }
+  return '?';
+}
+
+/// Class of static methods for the universe of Rti objects.
+///
+/// The universe is the manager object for the Rti instances.
+///
+/// The universe itself is allocated at startup before any types or Dart objects
+/// can be created, so it does not have a Dart type.
+class _Universe {
+  _Universe._() {
+    throw UnimplementedError('_Universe is static methods only');
+  }
+
+  @pragma('dart2js:noInline')
+  static Object create() {
+    // TODO(sra): For consistency, this expression should be a JS_BUILTIN that
+    // uses the same template as emitted by the emitter.
+    return JS(
+        '',
+        '{'
+            'evalCache: new Map(),'
+            'unprocessedRules:[],'
+            'a0:[],' // shared empty array.
+            '}');
+  }
+
+  // Field accessors.
+
+  static evalCache(universe) => JS('', '#.evalCache', universe);
+
+  static void addRules(universe, String rules) {
+    JS('', '#.unprocessedRules.push(#)', universe, rules);
+  }
+
+  static Object sharedEmptyArray(universe) => JS('JSArray', '#.a0', universe);
+
+  /// Evaluates [recipe] in the global environment.
+  static Rti eval(Object universe, String recipe) {
+    var cache = evalCache(universe);
+    var probe = _cacheGet(cache, recipe);
+    if (probe != null) return _castToRti(probe);
+    var rti = _parseRecipe(universe, null, recipe);
+    _cacheSet(cache, recipe, rti);
+    return rti;
+  }
+
+  static Rti evalInEnvironment(
+      Object universe, Rti environment, String recipe) {
+    var cache = Rti._getEvalCache(environment);
+    if (cache == null) {
+      cache = JS('', 'new Map()');
+      Rti._setEvalCache(environment, cache);
+    }
+    var probe = _cacheGet(cache, recipe);
+    if (probe != null) return _castToRti(probe);
+    var rti = _parseRecipe(universe, environment, recipe);
+    _cacheSet(cache, recipe, rti);
+    return rti;
+  }
+
+  static Rti evalTypeVariable(Object universe, Rti environment, String name) {
+    throw UnimplementedError('_Universe.evalTypeVariable("$name")');
+  }
+
+  static _cacheGet(cache, key) => JS('', '#.get(#)', cache, key);
+  static void _cacheSet(cache, key, value) {
+    JS('', '#.set(#, #)', cache, key, value);
+  }
+
+  static Rti _parseRecipe(Object universe, Object environment, String recipe) {
+    var parser = _Parser.create(universe, environment, recipe);
+    Rti rti = _Parser.parse(parser);
+    if (rti != null) return rti;
+    throw UnimplementedError('_Universe._parseRecipe("$recipe")');
+  }
+
+  static Rti _finishRti(Object universe, Rti rti) {
+    // Enter fresh Rti in global table under it's canonical recipe.
+    String key = Rti._getCanonicalRecipe(rti);
+    _cacheSet(evalCache(universe), key, rti);
+
+    // Set up methods to type tests.
+    // TODO(sra): These are for `dynamic`. Install general functions and
+    // specializations.
+    var alwaysPasses = JS('', 'function(o) { return o; }');
+    Rti._setAsCheckFunction(rti, alwaysPasses);
+    Rti._setTypeCheckFunction(rti, alwaysPasses);
+    Rti._setIsTestFunction(rti, JS('', 'function(o) { return true; }'));
+
+    return rti;
+  }
+
+  // For each kind of Rti there are three methods:
+  //
+  // * `lookupXXX` which takes the component parts and returns an existing Rti
+  //   object if it exists.
+  // * `canonicalRecipeOfXXX` that returns the compositional canonical recipe
+  //   for the proposed type.
+  // * `createXXX` to create the type if it does not exist.
+
+  static String _canonicalRecipeOfDynamic() => '@';
+
+  static Rti _lookupDynamicRti(universe) {
+    var cache = evalCache(universe);
+    var probe = _cacheGet(cache, _canonicalRecipeOfDynamic());
+    if (probe != null) return _castToRti(probe);
+    return _createDynamicRti(universe);
+  }
+
+  static Rti _createDynamicRti(Object universe) {
+    var rti = Rti.allocate();
+    Rti._setKind(rti, Rti.kindDynamic);
+    Rti._setCanonicalRecipe(rti, _canonicalRecipeOfDynamic());
+    return _finishRti(universe, rti);
+  }
+
+  static String _canonicalRecipeOfInterface(String name, Object arguments) {
+    assert(_Utils.isString(name));
+    String s = _Utils.asString(name);
+    int length = _Utils.arrayLength(arguments);
+    if (length != 0) {
+      s += '<';
+      for (int i = 0; i < length; i++) {
+        if (i > 0) s += ',';
+        Rti argument = _castToRti(_Utils.arrayAt(arguments, i));
+        String subrecipe = Rti._getCanonicalRecipe(argument);
+        s += subrecipe;
+      }
+      s += '>';
+    }
+    return s;
+  }
+
+  static Rti _lookupInterfaceRti(
+      Object universe, String name, Object arguments) {
+    String key = _canonicalRecipeOfInterface(name, arguments);
+    var cache = evalCache(universe);
+    var probe = _cacheGet(cache, key);
+    if (probe != null) return _castToRti(probe);
+    return _createInterfaceRti(universe, name, arguments, key);
+  }
+
+  static Rti _createInterfaceRti(
+      Object universe, String name, Object typeArguments, String key) {
+    var rti = Rti.allocate();
+    Rti._setKind(rti, Rti.kindInterface);
+    Rti._setPrimary(rti, name);
+    Rti._setRest(rti, typeArguments);
+    Rti._setCanonicalRecipe(rti, key);
+    return _finishRti(universe, rti);
+  }
+}
+
+/// Class of static methods implementing recipe parser.
+///
+/// The recipe is a sequence of operations on a stack machine. The operations
+/// are described below using the format
+///
+///      operation: stack elements before --- stack elements after
+///
+/// integer:  --- integer-value
+///
+/// identifier:  --- string-value
+///
+/// identifier-with-one-period:  --- type-variable-value
+///
+///   Period may be in any position, including first and last e.g. `.x`.
+///
+/// ',': ignored
+///
+///   Used to separate elements.
+///
+/// '@': --- dynamicType
+///
+/// '?':  type  ---  type?
+///
+/// '<':  --- position
+///
+///   Saves (pushes) position register, sets position register to end of stack.
+///
+/// '>':  name saved-position type ... type  ---  name<type, ..., type>
+///
+///   Creates interface type from name types pushed since the position register
+///   was last set. Restores position register to previous saved value.
+///
+class _Parser {
+  _Parser._() {
+    throw UnimplementedError('_Parser is static methods only');
+  }
+
+  /// Creates a parser object for parsing a recipe against an environment in a
+  /// universe.
+  ///
+  /// Marked as no-inline so the object literal is not cloned by inlining.
+  @pragma('dart2js:noInline')
+  static Object create(Object universe, Object environment, String recipe) {
+    return JS(
+        '',
+        '{'
+            'u:#,' // universe
+            'e:#,' // environment
+            'r:#,' // recipe
+            's:[],' // stack
+            'p:0,' // position of sequence start.
+            '}',
+        universe,
+        environment,
+        recipe);
+  }
+
+  // Field accessors for the parser.
+  static Object universe(Object parser) => JS('String', '#.u', parser);
+  static Rti environment(Object parser) => JS('Rti', '#.e', parser);
+  static String recipe(Object parser) => JS('String', '#.r', parser);
+  static Object stack(Object parser) => JS('', '#.s', parser);
+  static Object position(Object parser) => JS('int', '#.p', parser);
+  static void setPosition(Object parser, int p) {
+    JS('', '#.p = #', parser, p);
+  }
+
+  static int charCodeAt(String s, int i) => JS('int', '#.charCodeAt(#)', s, i);
+  static void push(Object stack, Object value) {
+    JS('', '#.push(#)', stack, value);
+  }
+
+  static Object pop(Object stack) => JS('', '#.pop()', stack);
+
+  static Rti parse(Object parser) {
+    String source = _Parser.recipe(parser);
+    var stack = _Parser.stack(parser);
+    int i = 0;
+    while (i < source.length) {
+      int ch = charCodeAt(source, i);
+      if (isDigit(ch)) {
+        i = handleDigit(i + 1, ch, source, stack);
+      } else if (isIdentifierStart(ch)) {
+        i = handleIdentifer(parser, i, source, stack, false);
+      } else if (ch == $PERIOD) {
+        i = handleIdentifer(parser, i, source, stack, true);
+      } else {
+        i++;
+        switch (ch) {
+          case $COMMA:
+            // ignored
+            break;
+
+          case $AT:
+            push(stack, _Universe._lookupDynamicRti(universe(parser)));
+            break;
+
+          case $LT:
+            push(stack, position(parser));
+            setPosition(parser, _Utils.arrayLength(stack));
+            break;
+
+          case $GT:
+            handleGenericInterfaceType(parser, stack);
+            break;
+
+          default:
+            JS('', 'throw "Bad character " + #', ch);
+        }
+      }
+    }
+    Object item = pop(stack);
+    return toType(universe(parser), environment(parser), item);
+  }
+
+  static int handleDigit(int i, int digit, String source, Object stack) {
+    int value = digit - $0;
+    for (; i < source.length; i++) {
+      int ch = charCodeAt(source, i);
+      if (!isDigit(ch)) break;
+      value = value * 10 + ch - $0;
+    }
+    push(stack, value);
+    return i;
+  }
+
+  static int handleIdentifer(
+      Object parser, int start, String source, Object stack, bool hasPeriod) {
+    int i = start + 1;
+    for (; i < source.length; i++) {
+      int ch = charCodeAt(source, i);
+      if (ch == $PERIOD) {
+        if (hasPeriod) break;
+        hasPeriod = true;
+      } else if (isIdentifierStart(ch) || isDigit(ch)) {
+        // Accept.
+      } else {
+        break;
+      }
+    }
+    String string = _Utils.substring(source, start, i);
+    if (hasPeriod) {
+      push(
+          stack,
+          _Universe.evalTypeVariable(
+              universe(parser), environment(parser), string));
+    } else {
+      push(stack, string);
+    }
+    return i;
+  }
+
+  static void handleGenericInterfaceType(Object parser, Object stack) {
+    var universe = _Parser.universe(parser);
+    var arguments = _Utils.arraySplice(stack, position(parser));
+    toTypes(universe, environment(parser), arguments);
+    setPosition(parser, _Utils.asInt(pop(stack)));
+    String name = _Utils.asString(pop(stack));
+    push(stack, _Universe._lookupInterfaceRti(universe, name, arguments));
+  }
+
+  /// Coerce a stack item into an Rti object. Strings are converted to interface
+  /// types, integers are looked up in the type environment.
+  static Rti toType(Object universe, Rti environment, Object item) {
+    if (_Utils.isString(item)) {
+      String name = _Utils.asString(item);
+      // TODO(sra): Compile this out for minified code.
+      if ('dynamic' == name) {
+        return _Universe._lookupDynamicRti(universe);
+      }
+      return _Universe._lookupInterfaceRti(
+          universe, name, _Universe.sharedEmptyArray(universe));
+    } else if (_Utils.isNum(item)) {
+      return _Parser._indexToType(universe, environment, _Utils.asInt(item));
+    } else {
+      return _castToRti(item);
+    }
+  }
+
+  static void toTypes(Object universe, Rti environment, Object items) {
+    int length = _Utils.arrayLength(items);
+    for (int i = 0; i < length; i++) {
+      var item = _Utils.arrayAt(items, i);
+      var type = toType(universe, environment, item);
+      _Utils.arraySetAt(items, i, type);
+    }
+  }
+
+  static Rti _indexToType(Object universe, Rti environment, int index) {
+    while (true) {
+      int kind = Rti._getKind(environment);
+      if (kind == Rti.kindInterface) {
+        var typeArguments = Rti._getInterfaceTypeArguments(environment);
+        int len = _Utils.arrayLength(typeArguments);
+        if (index < len) {
+          return _castToRti(_Utils.arrayAt(typeArguments, index));
+        }
+        throw AssertionError('Bad index $index for $environment');
+      }
+      // TODO(sra): Binding environment.
+      throw AssertionError('Recipe cannot index Rti kind $kind');
+    }
+  }
+
+  static bool isDigit(int ch) => ch >= $0 && ch <= $9;
+  static bool isIdentifierStart(int ch) =>
+      (ch >= $A && ch <= $Z) ||
+      (ch >= $a && ch <= $z) ||
+      (ch == $_) ||
+      (ch == $$);
+
+  static const int $$ = 0x24;
+  static const int $COMMA = 0x2C;
+  static const int $PERIOD = 0x2E;
+  static const int $0 = 0x30;
+  static const int $9 = 0x39;
+  static const int $LT = 0x3C;
+  static const int $GT = 0x3E;
+  static const int $A = 0x41;
+  static const int $AT = 0x40;
+  static const int $Z = $A + 26 - 1;
+  static const int $a = $A + 32;
+  static const int $z = $Z + 32;
+  static const int $_ = 0x5F;
+}
+
+// -------- Subtype tests ------------------------------------------------------
+
+// Future entry point from compiled code.
+bool isSubtype(Rti s, Rti t) {
+  return _isSubtype(s, null, t, null);
+}
+
+bool _isSubtype(Rti s, var sEnv, Rti t, var tEnv) {
+  if (_Utils.isIdentical(s, t)) return true;
+  int tKind = Rti._getKind(t);
+  if (tKind == Rti.kindDynamic) return true;
+  if (tKind == Rti.kindNever) return false;
+  return false;
+}
+
+/// Unchecked cast to Rti.
+Rti _castToRti(s) => JS('Rti', '#', s);
+
+///
+class _Utils {
+  static int asInt(Object o) => JS('int', '#', o);
+  static String asString(Object o) => JS('String', '#', o);
+
+  static bool isString(Object o) => JS('bool', 'typeof # == "string"', o);
+  static bool isNum(Object o) => JS('bool', 'typeof # == "number"', o);
+
+  static bool isIdentical(s, t) => JS('bool', '# === #', s, t);
+
+  static int arrayLength(Object array) => JS('int', '#.length', array);
+
+  static Object arrayAt(Object array, int i) => JS('', '#[#]', array, i);
+
+  static Object arraySetAt(Object array, int i, Object value) {
+    JS('', '#[#] = #', array, i, value);
+  }
+
+  static JSArray arraySplice(Object array, int position) =>
+      JS('JSArray', '#.splice(#)', array, position);
+
+  static String substring(String s, int start, int end) =>
+      JS('String', '#.substring(#, #)', s, start, end);
+
+  static mapGet(cache, key) => JS('', '#.get(#)', cache, key);
+
+  static void mapSet(cache, key, value) {
+    JS('', '#.set(#, #)', cache, key, value);
+  }
+}
+// -------- Entry points for testing -------------------------------------------
+
+String testingRtiToString(rti) {
+  return _rtiToString(_castToRti(rti), null);
+}
+
+String testingRtiToDebugString(rti) {
+  // TODO(sra): Create entty point for structural formatting of Rti tree.
+  return 'Rti';
+}
+
+Object testingCreateUniverse() {
+  return _Universe.create();
+}
+
+Object testingAddRules(universe, String rules) {
+  _Universe.addRules(universe, rules);
+}
+
+bool testingIsSubtype(rti1, rti2) {
+  return isSubtype(_castToRti(rti1), _castToRti(rti2));
+}
+
+Object testingUniverseEval(universe, String recipe) {
+  return _Universe.eval(universe, recipe);
+}
+
+Object testingEnvironmentEval(universe, environment, String recipe) {
+  return _Universe.evalInEnvironment(universe, _castToRti(environment), recipe);
+}
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index 58a9e90..f848a09 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -152,6 +152,8 @@
       dart2jsPatchPath: "_internal/js_runtime/lib/internal_patch.dart"),
   "_js_helper": const LibraryInfo("_internal/js_runtime/lib/js_helper.dart",
       categories: "", documented: false, platforms: DART2JS_PLATFORM),
+  "_rti": const LibraryInfo("_internal/js_runtime/lib/rti.dart",
+      categories: "", documented: false, platforms: DART2JS_PLATFORM),
   "_interceptors": const LibraryInfo(
       "_internal/js_runtime/lib/interceptors.dart",
       categories: "",
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index c29609d..82b88ee 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -410,6 +410,14 @@
    * The [convert] function is called once per data event per listener.
    * If a broadcast stream is listened to more than once, each subscription
    * will individually call [convert] on each data event.
+   *
+   * Unlike [transform], this method does not treat the stream as
+   * chunks of a single value. Instead each event is converted independently
+   * of the previous and following events, which may not always be correct.
+   * For example, UTF-8 encoding, or decoding, will give wrong results
+   * if a surrogate pair, or a multibyte UTF-8 encoding, is split into
+   * separate events, and those events are attempted encoded or decoded
+   * independently.
    */
   Stream<S> map<S>(S convert(T event)) {
     return new _MapStream<T, S>(this, convert);
@@ -633,6 +641,16 @@
    * Whether the returned stream is a broadcast stream or not,
    * and which elements it will contain,
    * is entirely up to the transformation.
+   *
+   * This method should always be used for transformations which treat
+   * the entire stream as representing a single value
+   * which has perhaps been split into several parts for transport,
+   * like a file being read from disk or being fetched over a network.
+   * The transformation will then produce a new stream which
+   * transforms the stream's value incrementally (perhaps using
+   * [Converter.startChunkedConversion]). The resulting stream
+   * may again be chunks of the result, but does not have to
+   * correspond to specific events from the source string.
    */
   Stream<S> transform<S>(StreamTransformer<T, S> streamTransformer) {
     return streamTransformer.bind(this);
@@ -1892,6 +1910,14 @@
    * receives the input stream (the one passed to [bind]) and a
    * boolean flag `cancelOnError` to create a [StreamSubscription].
    *
+   * If the transformed stream is a broadcast stream, so is the stream
+   * returned by the [StreamTransformer.bind] method by this transformer.
+   *
+   * If the transformed stream is listened to multiple times, the [onListen]
+   * callback is called again for each new [Stream.listen] call.
+   * This happens whether the stream is a broadcast stream or not,
+   * but the call will usually fail for non-broadcast streams.
+   *
    * The [onListen] callback does *not* receive the handlers that were passed
    * to [Stream.listen]. These are automatically set after the call to the
    * [onListen] callback (using [StreamSubscription.onData],
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 51497e0..14c84a5 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -967,7 +967,8 @@
   /// completed.
   bool _isPaused = false;
 
-  _StreamIterator(final Stream<T> stream) : _stateData = stream;
+  _StreamIterator(final Stream<T> stream)
+      : _stateData = stream ?? (throw ArgumentError.notNull("stream"));
 
   T get current {
     if (_subscription != null && _isPaused) {
diff --git a/sdk/lib/async/stream_transformers.dart b/sdk/lib/async/stream_transformers.dart
index b656dea..9ec13bd 100644
--- a/sdk/lib/async/stream_transformers.dart
+++ b/sdk/lib/async/stream_transformers.dart
@@ -320,6 +320,8 @@
   final _SubscriptionTransformer<S, T> _onListen;
   final Stream<S> _stream;
 
+  bool get isBroadcast => _stream.isBroadcast;
+
   _BoundSubscriptionStream(this._stream, this._onListen);
 
   StreamSubscription<T> listen(void onData(T event),
diff --git a/sdk/lib/core/regexp.dart b/sdk/lib/core/regexp.dart
index c0bd153..748933d 100644
--- a/sdk/lib/core/regexp.dart
+++ b/sdk/lib/core/regexp.dart
@@ -16,7 +16,7 @@
  * for the specification of JavaScript regular expressions.
  *
  * [firstMatch] is the main implementation method that applies a regular
- * expression to a string and returns the first [Match]. All
+ * expression to a string and returns the first [RegExpMatch]. All
  * other methods in [RegExp] can build on it.
  *
  * Use [allMatches] to look for all matches of a regular expression in
@@ -27,7 +27,7 @@
  * ```dart
  * RegExp exp = new RegExp(r"(\w+)");
  * String str = "Parse my string";
- * Iterable<Match> matches = exp.allMatches(str);
+ * Iterable<RegExpMatch> matches = exp.allMatches(str);
  * ```
  *
  * Note the use of a _raw string_ (a string prefixed with `r`)
@@ -47,6 +47,12 @@
    *
    * If `caseSensitive` is disabled, then case is ignored.
    *
+   * If `unicode` is enabled, then the pattern is treated as a Unicode
+   * pattern as described by the ECMAScript standard.
+   *
+   * If `dotAll` is enabled, then the `.` pattern will match _all_ characters,
+   * including line terminators.
+   *
    * Example:
    *
    * ```dart
@@ -60,7 +66,10 @@
    * interpolation is required.
    */
   external factory RegExp(String source,
-      {bool multiLine = false, bool caseSensitive = true});
+      {bool multiLine = false,
+      bool caseSensitive = true,
+      @Since("2.4") bool unicode = false,
+      @Since("2.4") bool dotAll = false});
 
   /**
    * Returns a regular expression that matches [text].
@@ -79,14 +88,14 @@
    * Searches for the first match of the regular expression
    * in the string [input]. Returns `null` if there is no match.
    */
-  Match firstMatch(String input);
+  RegExpMatch firstMatch(String input);
 
   /**
    * Returns an iterable of the matches of the regular expression on [input].
    *
    * If [start] is provided, only start looking for matches at `start`.
    */
-  Iterable<Match> allMatches(String input, [int start = 0]);
+  Iterable<RegExpMatch> allMatches(String input, [int start = 0]);
 
   /**
    * Returns whether the regular expression has a match in the string [input].
@@ -120,6 +129,35 @@
    * versions of the same letter.
    */
   bool get isCaseSensitive;
+
+  /**
+   * Whether this regular expression is in Unicode mode.
+   *
+   * In Unicode mode, UTF-16 surrogate pairs in the original string will be
+   * treated as a single code point and will not match separately. Otherwise,
+   * the target string will be treated purely as a sequence of individual code
+   * units and surrogates will not be treated specially.
+   *
+   * In Unicode mode, the syntax of the RegExp pattern is more restricted, but
+   * some pattern features, like Unicode property escapes, are only available in
+   * this mode.
+   */
+  @Since("2.4")
+  bool get isUnicode;
+
+  /**
+   * Whether "." in this regular expression matches line terminators.
+   *
+   * When false, the "." character matches a single character, unless that
+   * character is a line terminator. When true, then the "." character will
+   * match any single character including line terminators.
+   *
+   * This feature is distinct from [isMultiline], as they affect the behavior
+   * of different pattern characters, and so they can be used together or
+   * separately.
+   */
+  @Since("2.4")
+  bool get isDotAll;
 }
 
 /**
@@ -129,6 +167,7 @@
  * to retrieve the names for any named capture groups and to retrieve
  * matches for named capture groups by name instead of their index.
  */
+@Since("2.3")
 abstract class RegExpMatch implements Match {
   /**
    * The string matched by the group named [name].
diff --git a/sdk/lib/developer/extension.dart b/sdk/lib/developer/extension.dart
index c6f4cce..3cc4ede 100644
--- a/sdk/lib/developer/extension.dart
+++ b/sdk/lib/developer/extension.dart
@@ -9,19 +9,24 @@
 /// If the RPC was successful, use [ServiceExtensionResponse.result], otherwise
 /// use [ServiceExtensionResponse.error].
 class ServiceExtensionResponse {
-  final String _result;
-  final int _errorCode;
-  final String _errorDetail;
+  /// The result of a successful service protocol extension RPC.
+  final String result;
+
+  /// The error code associated with a failed service protocol extension RPC.
+  final int errorCode;
+
+  /// The details of a failed service protocol extension RPC.
+  final String errorDetail;
 
   /// Creates a successful response to a service protocol extension RPC.
   ///
   /// Requires [result] to be a JSON object encoded as a string. When forming
   /// the JSON-RPC message [result] will be inlined directly.
   ServiceExtensionResponse.result(String result)
-      : _result = result,
-        _errorCode = null,
-        _errorDetail = null {
-    ArgumentError.checkNotNull(_result, "result");
+      : result = result,
+        errorCode = null,
+        errorDetail = null {
+    ArgumentError.checkNotNull(result, "result");
   }
 
   /// Creates an error response to a service protocol extension RPC.
@@ -31,11 +36,11 @@
   /// encoded as a string. When forming the JSON-RPC message [errorDetail] will
   /// be inlined directly.
   ServiceExtensionResponse.error(int errorCode, String errorDetail)
-      : _result = null,
-        _errorCode = errorCode,
-        _errorDetail = errorDetail {
-    _validateErrorCode(_errorCode);
-    ArgumentError.checkNotNull(_errorDetail, "errorDetail");
+      : result = null,
+        errorCode = errorCode,
+        errorDetail = errorDetail {
+    _validateErrorCode(errorCode);
+    ArgumentError.checkNotNull(errorDetail, "errorDetail");
   }
 
   /// Invalid method parameter(s) error code.
@@ -83,20 +88,20 @@
     throw new ArgumentError.value(errorCode, "errorCode", "Out of range");
   }
 
-  // ignore: unused_element, called from runtime/lib/developer.dart
-  bool _isError() => (_errorCode != null) && (_errorDetail != null);
+  /// Determines if this response represents an error.
+  bool isError() => (errorCode != null) && (errorDetail != null);
 
   // ignore: unused_element, called from runtime/lib/developer.dart
   String _toString() {
-    if (_result != null) {
-      return _result;
+    if (result != null) {
+      return result;
     } else {
-      assert(_errorCode != null);
-      assert(_errorDetail != null);
+      assert(errorCode != null);
+      assert(errorDetail != null);
       return json.encode({
-        'code': _errorCode,
-        'message': _errorCodeMessage(_errorCode),
-        'data': {'details': _errorDetail}
+        'code': errorCode,
+        'message': _errorCodeMessage(errorCode),
+        'data': {'details': errorDetail}
       });
     }
   }
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 656fa6b..eb75be5 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -13944,6 +13944,8 @@
   @JSName('innerHTML')
   String _innerHtml;
 
+  String innerText;
+
   @JSName('localName')
   final String _localName;
 
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index 02fb46a..fdf6bbd 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -413,6 +413,7 @@
 /// It allows for fine grained control of the socket options, and its values will
 /// be passed to the underlying platform's implementation of setsockopt and
 /// getsockopt.
+@Since("2.2")
 class RawSocketOption {
   /// Creates a RawSocketOption for getRawOption andSetRawOption.
   ///
@@ -556,8 +557,13 @@
 }
 
 /**
- * The [RawSocket] is a low-level interface to a socket, exposing the raw
- * events signaled by the system. It's a [Stream] of [RawSocketEvent]s.
+ * A [RawSocket] is an unbuffered interface to a TCP socket.
+ *
+ * The raw socket delivers the data stream in the same chunks as the underlying
+ * operating system.
+ *
+ * It is not the same as a
+ * [POSIX raw socket](http://man7.org/linux/man-pages/man7/raw.7.html).
  */
 abstract class RawSocket implements Stream<RawSocketEvent> {
   /**
@@ -685,6 +691,7 @@
    *
    * Throws an [OSError] on failure.
    */
+  @Since("2.2")
   Uint8List getRawOption(RawSocketOption option);
 
   /**
@@ -693,6 +700,7 @@
    *
    * Throws an [OSError] on failure.
    */
+  @Since("2.2")
   void setRawOption(RawSocketOption option);
 }
 
@@ -830,12 +838,16 @@
 }
 
 /**
- * The [RawDatagramSocket] is a low-level interface to an UDP socket,
- * exposing the raw events signaled by the system. It's a [Stream] of
- * [RawSocketEvent]s.
+ * A [RawDatagramSocket] is an unbuffered interface to a UDP socket.
+ *
+ * The raw datagram socket delivers the datagrams in the same chunks as the
+ * underlying operating system. It's a [Stream] of [RawSocketEvent]s.
  *
  * Note that the event [RawSocketEvent.readClosed] will never be
  * received as an UDP socket cannot be closed by a remote peer.
+ *
+ * It is not the same as a
+ * [POSIX raw socket](http://man7.org/linux/man-pages/man7/raw.7.html).
  */
 abstract class RawDatagramSocket extends Stream<RawSocketEvent> {
   /**
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 5c5883d..e786e16 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -17,6 +17,8 @@
 library dart.isolate;
 
 import "dart:async";
+import "dart:_internal" show Since;
+import "dart:typed_data" show ByteBuffer, TypedData, Uint8List;
 
 part "capability.dart";
 
@@ -123,6 +125,7 @@
    * `Dart_DebugName` in the C embedding API and the `debugName` property in
    * [IsolateMirror].
    */
+  @Since("2.3")
   external String get debugName;
 
   /**
@@ -249,7 +252,7 @@
       bool errorsAreFatal,
       SendPort onExit,
       SendPort onError,
-      String debugName});
+      @Since("2.3") String debugName});
 
   /**
    * Creates and spawns an isolate that runs the code from the library with
@@ -337,7 +340,8 @@
           Uri packageRoot,
       Uri packageConfig,
       bool automaticPackageResolution: false,
-      String debugName});
+      @Since("2.3")
+          String debugName});
 
   /**
    * Requests the isolate to pause.
@@ -750,3 +754,36 @@
         stackTrace = new StackTrace.fromString(stackDescription);
   String toString() => _description;
 }
+
+/*
+ * An efficiently transferable sequence of byte values.
+ *
+ * A [TransferableTypedData] is created from a number of bytes.
+ * This will take time proportional to the number of bytes.
+ *
+ * The [TransferableTypedData] can be moved between isolates, so
+ * sending it through a send port will only take constant time.
+ *
+ * When sent this way, the local transferable can no longer be materialized,
+ * and the received object is now the only way to materialize the data.
+ */
+@Since("2.3.2")
+abstract class TransferableTypedData {
+  /**
+   * Creates a new [TransferableTypedData] containing the bytes of [list].
+   *
+   * It must be possible to create a single [Uint8List] containing the
+   * bytes, so if there are more bytes than what the platform allows in
+   * a single [Uint8List], then creation fails.
+   */
+  external factory TransferableTypedData.fromList(List<TypedData> list);
+
+  /**
+   * Creates a new [ByteBuffer] containing the bytes stored in this [TransferableTypedData].
+   *
+   * The [TransferableTypedData] is a cross-isolate single-use resource.
+   * This method must not be called more than once on the same underlying
+   * transferable bytes, even if the calls occur in different isolates.
+   */
+  ByteBuffer materialize();
+}
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 9b239ff..4a0f788 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -265,6 +265,9 @@
       "web_sql": {
         "uri": "web_sql/dart2js/web_sql_dart2js.dart"
       },
+      "_rti": {
+        "uri": "_internal/js_runtime/lib/rti.dart"
+      },
       "svg": {
         "uri": "svg/dart2js/svg_dart2js.dart"
       }
@@ -273,30 +276,30 @@
   "dartdevc": {
     "libraries": {
       "async": {
-        "patches": "../../pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart",
+        "patches": "_internal/js_dev_runtime/patch/async_patch.dart",
         "uri": "async/async.dart"
       },
       "_runtime": {
-        "uri": "../../pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart"
+        "uri": "_internal/js_dev_runtime/private/ddc_runtime/runtime.dart"
       },
       "_interceptors": {
-        "uri": "../../pkg/dev_compiler/tool/input_sdk/private/interceptors.dart"
+        "uri": "_internal/js_dev_runtime/private/interceptors.dart"
       },
       "mirrors": {
-        "patches": "../../pkg/dev_compiler/tool/input_sdk/patch/mirrors_patch.dart",
+        "patches": "_internal/js_dev_runtime/patch/mirrors_patch.dart",
         "supported": false,
         "uri": "mirrors/mirrors.dart"
       },
       "_debugger": {
-        "uri": "../../pkg/dev_compiler/tool/input_sdk/private/debugger.dart"
+        "uri": "_internal/js_dev_runtime/private/debugger.dart"
       },
       "io": {
-        "patches": "../../pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart",
+        "patches": "_internal/js_dev_runtime/patch/io_patch.dart",
         "supported": false,
         "uri": "io/io.dart"
       },
       "_internal": {
-        "patches": "../../pkg/dev_compiler/tool/input_sdk/patch/internal_patch.dart",
+        "patches": "_internal/js_dev_runtime/patch/internal_patch.dart",
         "uri": "internal/internal.dart"
       },
       "_metadata": {
@@ -306,36 +309,36 @@
         "uri": "_http/http.dart"
       },
       "_js_primitives": {
-        "uri": "../../pkg/dev_compiler/tool/input_sdk/private/js_primitives.dart"
+        "uri": "_internal/js_dev_runtime/private/js_primitives.dart"
       },
       "_js_helper": {
-        "uri": "../../pkg/dev_compiler/tool/input_sdk/private/js_helper.dart"
+        "uri": "_internal/js_dev_runtime/private/js_helper.dart"
       },
       "js": {
-        "uri": "../../pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart"
+        "uri": "_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart"
       },
       "_js_mirrors": {
-        "uri": "../../pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dart"
+        "uri": "_internal/js_dev_runtime/private/js_mirrors.dart"
       },
       "html_common": {
         "uri": "html/html_common/html_common_dart2js.dart"
       },
       "_native_typed_data": {
-        "uri": "../../pkg/dev_compiler/tool/input_sdk/private/native_typed_data.dart"
+        "uri": "_internal/js_dev_runtime/private/native_typed_data.dart"
       },
       "core": {
-        "patches": "../../pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart",
+        "patches": "_internal/js_dev_runtime/patch/core_patch.dart",
         "uri": "core/core.dart"
       },
       "js_util": {
-        "uri": "../../pkg/dev_compiler/tool/input_sdk/lib/js_util/dart2js/js_util_dart2js.dart"
+        "uri": "_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart"
       },
       "collection": {
-        "patches": "../../pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart",
+        "patches": "_internal/js_dev_runtime/patch/collection_patch.dart",
         "uri": "collection/collection.dart"
       },
       "typed_data": {
-        "patches": "../../pkg/dev_compiler/tool/input_sdk/patch/typed_data_patch.dart",
+        "patches": "_internal/js_dev_runtime/patch/typed_data_patch.dart",
         "uri": "typed_data/typed_data.dart"
       },
       "web_audio": {
@@ -345,11 +348,11 @@
         "uri": "html/dart2js/html_dart2js.dart"
       },
       "developer": {
-        "patches": "../../pkg/dev_compiler/tool/input_sdk/patch/developer_patch.dart",
+        "patches": "_internal/js_dev_runtime/patch/developer_patch.dart",
         "uri": "developer/developer.dart"
       },
       "isolate": {
-        "patches": "../../pkg/dev_compiler/tool/input_sdk/patch/isolate_patch.dart",
+        "patches": "_internal/js_dev_runtime/patch/isolate_patch.dart",
         "supported": false,
         "uri": "isolate/isolate.dart"
       },
@@ -360,18 +363,18 @@
         "uri": "indexed_db/dart2js/indexed_db_dart2js.dart"
       },
       "convert": {
-        "patches": "../../pkg/dev_compiler/tool/input_sdk/patch/convert_patch.dart",
+        "patches": "_internal/js_dev_runtime/patch/convert_patch.dart",
         "uri": "convert/convert.dart"
       },
       "_isolate_helper": {
-        "uri": "../../pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart"
+        "uri": "_internal/js_dev_runtime/private/isolate_helper.dart"
       },
       "math": {
-        "patches": "../../pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart",
+        "patches": "_internal/js_dev_runtime/patch/math_patch.dart",
         "uri": "math/math.dart"
       },
       "_foreign_helper": {
-        "uri": "../../pkg/dev_compiler/tool/input_sdk/private/foreign_helper.dart"
+        "uri": "_internal/js_dev_runtime/private/foreign_helper.dart"
       },
       "web_sql": {
         "uri": "web_sql/dart2js/web_sql_dart2js.dart"
@@ -464,9 +467,12 @@
       "_js_helper": {
         "uri": "_internal/js_runtime/lib/js_helper.dart"
       },
+      "_rti": {
+        "uri": "_internal/js_runtime/lib/rti.dart"
+      },
       "js": {
         "uri": "js/dart2js/js_dart2js.dart"
       }
     }
   }
-}
\ No newline at end of file
+}
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index a53b69a..7a5520c 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -245,6 +245,9 @@
     _js_helper:
       uri: "_internal/js_runtime/lib/js_helper.dart"
 
+    _rti:
+      uri: "_internal/js_runtime/lib/rti.dart"
+
     _interceptors:
       uri: "_internal/js_runtime/lib/interceptors.dart"
 
@@ -334,6 +337,9 @@
     _js_helper:
       uri: "_internal/js_runtime/lib/js_helper.dart"
 
+    _rti:
+      uri: "_internal/js_runtime/lib/rti.dart"
+
     _interceptors:
       uri: "_internal/js_runtime/lib/interceptors.dart"
 
@@ -351,87 +357,88 @@
 
     _async_await_error_codes:
       uri: "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+
 dartdevc:
     libraries:
       _runtime:
-        uri: "../../pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart"
+        uri: "_internal/js_dev_runtime/private/ddc_runtime/runtime.dart"
 
       _debugger:
-        uri: "../../pkg/dev_compiler/tool/input_sdk/private/debugger.dart"
+        uri: "_internal/js_dev_runtime/private/debugger.dart"
 
       _foreign_helper:
-        uri: "../../pkg/dev_compiler/tool/input_sdk/private/foreign_helper.dart"
+        uri: "_internal/js_dev_runtime/private/foreign_helper.dart"
 
       _http:
         uri: "_http/http.dart"
 
       _interceptors:
-        uri: "../../pkg/dev_compiler/tool/input_sdk/private/interceptors.dart"
+        uri: "_internal/js_dev_runtime/private/interceptors.dart"
 
       _internal:
         uri: "internal/internal.dart"
-        patches: "../../pkg/dev_compiler/tool/input_sdk/patch/internal_patch.dart"
+        patches: "_internal/js_dev_runtime/patch/internal_patch.dart"
 
       _isolate_helper:
-        uri: "../../pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart"
+        uri: "_internal/js_dev_runtime/private/isolate_helper.dart"
 
       _js_helper:
-        uri: "../../pkg/dev_compiler/tool/input_sdk/private/js_helper.dart"
+        uri: "_internal/js_dev_runtime/private/js_helper.dart"
 
       _js_mirrors:
-        uri: "../../pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dart"
+        uri: "_internal/js_dev_runtime/private/js_mirrors.dart"
 
       _js_primitives:
-        uri: "../../pkg/dev_compiler/tool/input_sdk/private/js_primitives.dart"
+        uri: "_internal/js_dev_runtime/private/js_primitives.dart"
 
       _metadata:
         uri: "html/html_common/metadata.dart"
 
       _native_typed_data:
-        uri: "../../pkg/dev_compiler/tool/input_sdk/private/native_typed_data.dart"
+        uri: "_internal/js_dev_runtime/private/native_typed_data.dart"
 
       async:
         uri: "async/async.dart"
-        patches: "../../pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart"
+        patches: "_internal/js_dev_runtime/patch/async_patch.dart"
 
       collection:
         uri: "collection/collection.dart"
-        patches: "../../pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart"
+        patches: "_internal/js_dev_runtime/patch/collection_patch.dart"
 
       convert:
         uri: "convert/convert.dart"
-        patches: "../../pkg/dev_compiler/tool/input_sdk/patch/convert_patch.dart"
+        patches: "_internal/js_dev_runtime/patch/convert_patch.dart"
 
       core:
         uri: "core/core.dart"
-        patches: "../../pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart"
+        patches: "_internal/js_dev_runtime/patch/core_patch.dart"
 
       developer:
         uri: "developer/developer.dart"
-        patches: "../../pkg/dev_compiler/tool/input_sdk/patch/developer_patch.dart"
+        patches: "_internal/js_dev_runtime/patch/developer_patch.dart"
 
       io:
         uri: "io/io.dart"
-        patches: "../../pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart"
+        patches: "_internal/js_dev_runtime/patch/io_patch.dart"
         supported: false
 
       isolate:
         uri: "isolate/isolate.dart"
-        patches: "../../pkg/dev_compiler/tool/input_sdk/patch/isolate_patch.dart"
+        patches: "_internal/js_dev_runtime/patch/isolate_patch.dart"
         supported: false
 
       mirrors:
         uri: "mirrors/mirrors.dart"
-        patches: "../../pkg/dev_compiler/tool/input_sdk/patch/mirrors_patch.dart"
+        patches: "_internal/js_dev_runtime/patch/mirrors_patch.dart"
         supported: false
 
       math:
         uri: "math/math.dart"
-        patches: "../../pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart"
+        patches: "_internal/js_dev_runtime/patch/math_patch.dart"
 
       typed_data:
         uri: "typed_data/typed_data.dart"
-        patches: "../../pkg/dev_compiler/tool/input_sdk/patch/typed_data_patch.dart"
+        patches: "_internal/js_dev_runtime/patch/typed_data_patch.dart"
 
       html:
         uri: "html/dart2js/html_dart2js.dart"
@@ -443,10 +450,10 @@
         uri: "indexed_db/dart2js/indexed_db_dart2js.dart"
 
       js:
-        uri: "../../pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart"
+        uri: "_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart"
 
       js_util:
-        uri: "../../pkg/dev_compiler/tool/input_sdk/lib/js_util/dart2js/js_util_dart2js.dart"
+        uri: "_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart"
 
       svg:
         uri: "svg/dart2js/svg_dart2js.dart"
diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status
index c4f2692..5321ddf 100644
--- a/tests/co19_2/co19_2-dart2js.status
+++ b/tests/co19_2/co19_2-dart2js.status
@@ -10,6 +10,17 @@
 LibTest/html/*: SkipByDesign # d8 is not a browser
 WebPlatformTest/*: SkipByDesign # d8 is not a browser
 
+[ $compiler == dart2js && $runtime == ie11 ]
+LibTest/collection/ListBase/ListBase_class_A01_t04: SkipSlow # slow babeljs transformation
+LibTest/collection/ListBase/ListBase_class_A01_t05: SkipSlow # slow babeljs transformation
+LibTest/collection/ListBase/ListBase_class_A01_t06: SkipSlow # slow babeljs transformation
+LibTest/collection/ListMixin/ListMixin_class_A01_t04: SkipSlow # slow babeljs transformation
+LibTest/collection/ListMixin/ListMixin_class_A01_t05: SkipSlow # slow babeljs transformation
+LibTest/collection/ListMixin/ListMixin_class_A01_t06: SkipSlow # slow babeljs transformation
+LibTest/core/List/List_class_A01_t04: SkipSlow # slow babeljs transformation
+LibTest/core/List/List_class_A01_t05: SkipSlow # slow babeljs transformation
+LibTest/core/List/List_class_A01_t06: SkipSlow # slow babeljs transformation
+
 [ $compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk ]
 Language/Expressions/Spawning_an_Isolate/new_isolate_t01: SkipByDesign
 LibTest/io/*: SkipByDesign # dart:io not supported.
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index e637ca2..48b24cc 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -101,12 +101,27 @@
 Language/Classes/Setters/same_name_getter_different_type_t01: MissingCompileTimeError
 Language/Classes/Setters/syntax_t04: MissingCompileTimeError
 Language/Classes/Setters/syntax_t05: MissingCompileTimeError
+Language/Classes/Setters/syntax_t06: CompileTimeError
+Language/Classes/Static_Methods/declaration_t04: CompileTimeError
 Language/Classes/Static_Methods/same_name_method_and_setter_t01: CompileTimeError
+Language/Classes/Static_Variables/type_alias_t01: CompileTimeError
+Language/Classes/Superclasses/Inheritance_and_Overriding/inheritance_t07: CompileTimeError
+Language/Classes/Superclasses/Inheritance_and_Overriding/inheritance_t08: CompileTimeError
+Language/Classes/Superclasses/Inheritance_and_Overriding/inheritance_t09: CompileTimeError
+Language/Classes/Superclasses/Inheritance_and_Overriding/overriding_t06: CompileTimeError
+Language/Classes/Superclasses/Inheritance_and_Overriding/overriding_t07: CompileTimeError
+Language/Classes/Superclasses/Inheritance_and_Overriding/overriding_t08: CompileTimeError
+Language/Classes/Superclasses/extends_clause_t02: CompileTimeError
+Language/Classes/Superclasses/transition_t02: CompileTimeError
 Language/Classes/Superclasses/wrong_superclass_t08: MissingCompileTimeError # Issue 30273
+Language/Classes/Superinterfaces/no_member_t07: CompileTimeError
+Language/Classes/Superinterfaces/syntax_t03: CompileTimeError
 Language/Classes/Superinterfaces/wrong_type_t05: MissingCompileTimeError # Issue 30273
 Language/Classes/method_definition_t06: MissingCompileTimeError # Legal
+Language/Enums/restrictions_t10: Crash
 Language/Enums/syntax_t08: CompileTimeError
 Language/Enums/syntax_t09: CompileTimeError
+Language/Enums/syntax_t10: CompileTimeError
 Language/Expressions/Assignable_Expressions/syntax_t01: CompileTimeError
 Language/Expressions/Assignment/Compound_Assignment/expression_assignment_t12: Skip # triple-shift flag
 Language/Expressions/Assignment/Compound_Assignment/indexed_expression_assignment_t12: Skip # triple-shift flag
@@ -128,8 +143,6 @@
 Language/Expressions/Constants/bitwise_operators_t08: Skip # triple-shift flag
 Language/Expressions/Constants/constant_list_t02: MissingCompileTimeError # Legal because of implicit const
 Language/Expressions/Constants/constant_map_t02: MissingCompileTimeError # Legal because of implicit const
-Language/Expressions/Constants/depending_on_itself_t03: MissingCompileTimeError # Issue 34189
-Language/Expressions/Constants/equals_expression_t03: MissingCompileTimeError # Issue 34192
 Language/Expressions/Equality/syntax_t01: Skip # triple-shift flag
 Language/Expressions/Function_Expressions/syntax_t05: CompileTimeError
 Language/Expressions/Function_Invocation/async_cleanup_t01: CompileTimeError
@@ -150,8 +163,6 @@
 Language/Expressions/Lists/syntax_t01: Skip # triple-shift flag
 Language/Expressions/Maps/constant_map_t02: MissingCompileTimeError
 Language/Expressions/Maps/constant_map_type_t01: CompileTimeError
-Language/Expressions/Maps/equal_keys_t01/01: MissingCompileTimeError
-Language/Expressions/Maps/equal_keys_t01/02: MissingCompileTimeError
 Language/Expressions/Maps/key_value_equals_operator_t01: MissingCompileTimeError # Issue 32557
 Language/Expressions/Maps/syntax_t01: Skip # triple-shift flag
 Language/Expressions/Method_Invocation/Ordinary_Invocation/accessible_instance_member_t04: CompileTimeError
@@ -207,6 +218,15 @@
 Language/Generics/typedef_A01_t07: CompileTimeError
 Language/Generics/typedef_A01_t08: CompileTimeError
 Language/Generics/typedef_A01_t10: CompileTimeError
+Language/Generics/typedef_A04_t01: CompileTimeError
+Language/Generics/typedef_A04_t02: CompileTimeError
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/inheritance_t13: CompileTimeError
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/inheritance_t14: CompileTimeError
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/not_overriden_members_t03: CompileTimeError
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_getters_t03: CompileTimeError
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_getters_t04: CompileTimeError
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_getters_type_t10: CompileTimeError
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_getters_type_t11: CompileTimeError
 Language/Libraries_and_Scripts/Imports/library_name_t01: MissingCompileTimeError # Expects an error, but this is a warning in Dart 2
 Language/Mixins/Mixin_Application/abstract_t09: Crash
 Language/Mixins/Mixin_Application/abstract_t10: Crash
@@ -231,8 +251,11 @@
 Language/Mixins/Mixin_Application/superinterfaces_t14: Crash
 Language/Mixins/Mixin_Application/syntax_t26: Crash
 Language/Mixins/Mixin_Application/warning_t04: Crash
+Language/Mixins/Mixin_Application/wrong_mixin_type_t09: Crash
+Language/Mixins/Mixin_Composition/order_t02: Crash
 Language/Mixins/declaring_constructor_t05: MissingCompileTimeError # Mixin constructor
 Language/Mixins/declaring_constructor_t06: MissingCompileTimeError # Mixin constructor
+Language/Mixins/declaring_constructor_t11: Crash
 Language/Overview/Privacy/private_and_public_t11: CompileTimeError
 Language/Reference/Operator_Precedence/precedence_01_assignment_t14: Skip # triple-shift experimental flag
 Language/Reference/Operator_Precedence/precedence_12_Shift_t04: Skip # triple-shift experimental flag
@@ -274,6 +297,7 @@
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t03/05: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t03/06: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t03/none: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t04: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t04/01: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t04/02: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t04/03: Crash
@@ -291,6 +315,8 @@
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t06/03: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t06/04: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t06/05: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t06/06: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t07: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t07/01: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t07/02: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t07/03: Crash
@@ -304,6 +330,21 @@
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t08/04: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t08/05: Crash
 LanguageFeatures/Constant-update-2018/NewOperators_A01_t08/none: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t09: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t10/01: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t10/02: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t10/03: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t10/04: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t10/05: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t10/06: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t10/none: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t11: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t12/01: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t12/02: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t12/03: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t12/04: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t12/05: Crash
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t12/none: Crash
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t01: Crash
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t02: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t03: Crash
@@ -556,13 +597,6 @@
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_typedef_l1_t17/01: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_typedef_l1_t18/01: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_typedef_l1_t19/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t02/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t02/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t02/03: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t02/04: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t03/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t03/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t03/03: MissingCompileTimeError
 LanguageFeatures/Set-literals/disambiguating_A02_t02: CompileTimeError
 LanguageFeatures/Set-literals/disambiguating_A02_t03: Crash
 LanguageFeatures/Set-literals/exact_types_of_literals_A01_t03: RuntimeError
@@ -579,8 +613,6 @@
 LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t04/01: MissingCompileTimeError
 LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t04/02: MissingCompileTimeError
 LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t10: CompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A09_t09/04: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A10_t09/04: MissingCompileTimeError
 LanguageFeatures/Spread-collections/TypeInference_A01_t03/06: MissingCompileTimeError
 LanguageFeatures/Spread-collections/TypeInference_A01_t03/07: MissingCompileTimeError
 LanguageFeatures/Spread-collections/TypeInference_A01_t03/08: MissingCompileTimeError
@@ -687,36 +719,13 @@
 
 [ $compiler != dart2js && $runtime != vm && $fasta ]
 Language/Classes/Constructors/Constant_Constructors/invalid_constant_initializer_t02: MissingCompileTimeError # Issue 34192
-Language/Expressions/Constants/exception_t01: MissingCompileTimeError # Issue 31936
-Language/Expressions/Constants/exception_t03: MissingCompileTimeError # Issue 31936
-Language/Expressions/Constants/exception_t04: MissingCompileTimeError # Issue 31936
-Language/Expressions/Constants/no_other_constant_expressions_t11: MissingCompileTimeError # Issue 34192
-Language/Expressions/Constants/ternary_operator_t02: MissingCompileTimeError # Issue 34192
 Language/Expressions/Instance_Creation/Const/exception_t01: MissingCompileTimeError # Issue 31936
 Language/Metadata/compilation_t03: MissingCompileTimeError # Issue 34205
 
 [ $compiler != dart2js && $fasta ]
-Language/Expressions/Constants/literal_string_t02: MissingCompileTimeError # Issue 34192
 Language/Statements/Switch/equal_operator_t01: MissingCompileTimeError # Issue 32557
 Language/Statements/Switch/equal_operator_t02: MissingCompileTimeError # Issue 32557
 
-[ $compiler != dartkp && $fasta ]
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/03: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/04: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/05: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/06: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/03: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/04: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/05: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/06: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/07: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/08: MissingCompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/09: MissingCompileTimeError
-
 [ $mode == debug && $runtime == vm && $system == linux && ($compiler == dartk || $compiler == dartkb) ]
 LibTest/io/Stdin/readByteSync_A02_t01: RuntimeError, Pass
 LibTest/io/WebSocket/pingInterval_A01_t01: RuntimeError, Pass
@@ -1165,10 +1174,9 @@
 LibTest/typed_data/Uint8List/first_A01_t02: RuntimeError
 LibTest/typed_data/Uint8List/last_A01_t02: RuntimeError
 
-[ $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk || $compiler == dartkb ]
 Language/Expressions/Additive_Expressions/syntax_t01: RuntimeError
 Language/Expressions/Assignment/null_aware_assignment_static_type_t01: RuntimeError
-Language/Expressions/Constants/depending_on_itself_t03: Crash
 Language/Expressions/Function_Invocation/async_generator_invokation_t08: Fail
 Language/Expressions/Function_Invocation/async_generator_invokation_t10: Fail
 Language/Expressions/Instance_Creation/Const/canonicalized_t05: RuntimeError
diff --git a/tests/compiler/dart2js/analyses/api_allowed.json b/tests/compiler/dart2js/analyses/api_allowed.json
index a7a08a3..cec99f0 100644
--- a/tests/compiler/dart2js/analyses/api_allowed.json
+++ b/tests/compiler/dart2js/analyses/api_allowed.json
@@ -28,10 +28,10 @@
     "Dynamic invocation of '_js_helper::_execGlobal'.": 1,
     "Dynamic access of 'start'.": 1,
     "Dynamic access of 'end'.": 1,
-    "Dynamic access of 'length'.": 3,
-    "Dynamic invocation of '[]'.": 1,
     "Dynamic invocation of 'call'.": 13,
+    "Dynamic access of 'length'.": 3,
     "Dynamic invocation of 'codeUnitAt'.": 2,
+    "Dynamic invocation of '[]'.": 1,
     "Dynamic access of 'iterator'.": 2,
     "Dynamic invocation of 'replaceRange'.": 2
   },
@@ -184,7 +184,7 @@
   "org-dartlang-sdk:///sdk/lib/_internal/js_runtime/lib/core_patch.dart": {
     "Dynamic access of 'dart.core::_digits'.": 2,
     "Dynamic invocation of '<'.": 2,
-    "Dynamic invocation of '[]'.": 19,
+    "Dynamic invocation of '[]'.": 17,
     "Dynamic invocation of '+'.": 2,
     "Dynamic invocation of 'dart.core::_absSubSetSign'.": 3,
     "Dynamic invocation of 'dart.core::_absAndNotSetSign'.": 2,
@@ -244,4 +244,4 @@
     "Dynamic access of 'port'.": 1,
     "Dynamic invocation of 'dart._http::_toJSON'.": 1
   }
-}
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/analyses/dart2js_allowed.json b/tests/compiler/dart2js/analyses/dart2js_allowed.json
index de743f0..0b70e2e 100644
--- a/tests/compiler/dart2js/analyses/dart2js_allowed.json
+++ b/tests/compiler/dart2js/analyses/dart2js_allowed.json
@@ -143,8 +143,8 @@
     "Dynamic invocation of 'toSet'.": 1
   },
   "pkg/compiler/lib/src/helpers/track_map.dart": {
-    "Dynamic invocation of '+'.": 2,
-    "Dynamic invocation of '-'.": 1
+    "Dynamic invocation of '-'.": 1,
+    "Dynamic invocation of '+'.": 1
   },
   "pkg/compiler/lib/src/constants/constant_system.dart": {
     "Dynamic invocation of '&'.": 1,
@@ -250,6 +250,12 @@
     "Dynamic access of 'named'.": 2,
     "Dynamic invocation of '[]'.": 2
   },
+  "pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart": {
+    "Dynamic access of 'keys'.": 1,
+    "Dynamic invocation of 'toSet'.": 1,
+    "Dynamic invocation of '[]='.": 1,
+    "Dynamic invocation of 'add'.": 1
+  },
   "pkg/compiler/lib/src/universe/function_set.dart": {
     "Dynamic access of 'selector'.": 1,
     "Dynamic access of 'receiver'.": 1
@@ -270,16 +276,6 @@
   "pkg/compiler/lib/src/ssa/value_set.dart": {
     "Dynamic invocation of 'add'.": 2
   },
-  "pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart": {
-    "Dynamic access of 'keys'.": 1,
-    "Dynamic invocation of 'toSet'.": 1,
-    "Dynamic invocation of '[]='.": 1,
-    "Dynamic invocation of 'add'.": 1
-  },
-  "pkg/compiler/lib/src/util/features.dart": {
-    "Dynamic invocation of 'sort'.": 1,
-    "Dynamic invocation of 'join'.": 1
-  },
   "pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart": {
     "Dynamic access of 'superclass'.": 1,
     "Dynamic access of 'needsTearOff'.": 1
diff --git a/tests/compiler/dart2js/closure/closure_test.dart b/tests/compiler/dart2js/closure/closure_test.dart
index da6b882..941efb5 100644
--- a/tests/compiler/dart2js/closure/closure_test.dart
+++ b/tests/compiler/dart2js/closure/closure_test.dart
@@ -12,8 +12,8 @@
 import 'package:compiler/src/js_model/element_map.dart';
 import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/js_model/locals.dart';
-import 'package:compiler/src/universe/codegen_world_builder.dart';
 import 'package:compiler/src/util/features.dart';
+import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
 import '../equivalence/id_equivalence.dart';
 import '../equivalence/id_equivalence_helper.dart';
@@ -43,14 +43,8 @@
         definition.kind == MemberKind.regular ||
             definition.kind == MemberKind.constructor,
         failedAt(member, "Unexpected member definition $definition"));
-    new ClosureIrChecker(
-            compiler.reporter,
-            actualMap,
-            elementMap,
-            member,
-            localsMap.getLocalsMap(member),
-            closureDataLookup,
-            compiler.codegenWorldBuilder,
+    new ClosureIrChecker(compiler.reporter, actualMap, elementMap, member,
+            localsMap.getLocalsMap(member), closureDataLookup, closedWorld,
             verbose: verbose)
         .run(definition.node);
   }
@@ -63,7 +57,7 @@
 class ClosureIrChecker extends IrDataExtractor<String> {
   final MemberEntity member;
   final ClosureData closureDataLookup;
-  final CodegenWorldBuilder codegenWorldBuilder;
+  final JClosedWorld _closedWorld;
   final KernelToLocalsMap _localsMap;
   final bool verbose;
 
@@ -81,7 +75,7 @@
       this.member,
       this._localsMap,
       this.closureDataLookup,
-      this.codegenWorldBuilder,
+      this._closedWorld,
       {this.verbose: false})
       : super(reporter, actualMap) {
     pushMember(member);
@@ -276,10 +270,10 @@
       addLocals('free', closureRepresentationInfo.forEachFreeVariable);
       if (closureRepresentationInfo.closureClassEntity != null) {
         addLocals('fields', (f(Local local, _)) {
-          codegenWorldBuilder.forEachInstanceField(
+          _closedWorld.elementEnvironment.forEachInstanceField(
               closureRepresentationInfo.closureClassEntity,
-              (_, FieldEntity field, {bool isElided}) {
-            if (isElided) return;
+              (_, FieldEntity field) {
+            if (_closedWorld.fieldAnalysis.getFieldData(field).isElided) return;
             f(closureRepresentationInfo.getLocalForField(field), field);
           });
         });
diff --git a/tests/compiler/dart2js/codegen/expect_annotations_test.dart b/tests/compiler/dart2js/codegen/expect_annotations_test.dart
index d38eba7..8775d9c 100644
--- a/tests/compiler/dart2js/codegen/expect_annotations_test.dart
+++ b/tests/compiler/dart2js/codegen/expect_annotations_test.dart
@@ -48,8 +48,8 @@
 
   void testTypeMatch(FunctionEntity function, TypeMask expectedParameterType,
       TypeMask expectedReturnType, GlobalTypeInferenceResults results) {
-    compiler.codegenWorldBuilder.forEachParameterAsLocal(function,
-        (Local parameter) {
+    closedWorld.elementEnvironment.forEachParameterAsLocal(
+        closedWorld.globalLocalsMap, function, (Local parameter) {
       TypeMask type = results.resultOfParameter(parameter);
       Expect.equals(
           expectedParameterType, simplify(type, closedWorld), "$parameter");
diff --git a/tests/compiler/dart2js/codegen/is_function_test.dart b/tests/compiler/dart2js/codegen/is_function_test.dart
index 53cbaf3..9965040 100644
--- a/tests/compiler/dart2js/codegen/is_function_test.dart
+++ b/tests/compiler/dart2js/codegen/is_function_test.dart
@@ -24,8 +24,8 @@
         memorySourceFiles: {'main.dart': SOURCE}, options: options);
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    Program program = compiler.backend.emitter.emitter.programForTesting;
-    var name = compiler.backend.namer.operatorIs(
+    Program program = compiler.backend.emitterTask.emitter.programForTesting;
+    var name = compiler.backend.namerForTesting.operatorIs(
         compiler.backendClosedWorldForTesting.commonElements.functionClass);
     for (Fragment fragment in program.fragments) {
       for (Library library in fragment.libraries) {
diff --git a/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart b/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart
index 8b98f7d..d5df20f 100644
--- a/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart
+++ b/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart
@@ -51,7 +51,7 @@
 
   Selector getLengthSelector = new Selector.getter(const PublicName('length'));
   js.Name getLengthName =
-      compiler.backend.namer.invocationName(getLengthSelector);
+      compiler.backend.namerForTesting.invocationName(getLengthSelector);
 
   Method method = programLookup.getMethod(jsArrayIndexOf);
   int lengthCount = 0;
diff --git a/tests/compiler/dart2js/codegen/model_data/constant_folding.dart b/tests/compiler/dart2js/codegen/model_data/constant_folding.dart
index e93751d..6ca83c8 100644
--- a/tests/compiler/dart2js/codegen/model_data/constant_folding.dart
+++ b/tests/compiler/dart2js/codegen/model_data/constant_folding.dart
@@ -31,7 +31,7 @@
         actual.isNegative,
         (reason == null ? "" : "$reason ") +
             "${expected.toString()} and "
-            "${actual.toString()} have different signs.");
+                "${actual.toString()} have different signs.");
   }
 }
 
diff --git a/tests/compiler/dart2js/codegen/model_data/dynamic_get.dart b/tests/compiler/dart2js/codegen/model_data/dynamic_get.dart
index 81c7601..e7f67fb 100644
--- a/tests/compiler/dart2js/codegen/model_data/dynamic_get.dart
+++ b/tests/compiler/dart2js/codegen/model_data/dynamic_get.dart
@@ -63,6 +63,7 @@
 class Class4b implements Class4a {
   /*element: Class4b.field4:emitted,get=simple*/
   @pragma('dart2js:noElision')
+  @override
   int field4;
 }
 
diff --git a/tests/compiler/dart2js/codegen/model_test.dart b/tests/compiler/dart2js/codegen/model_test.dart
index 61f5c27..47d0c5c 100644
--- a/tests/compiler/dart2js/codegen/model_test.dart
+++ b/tests/compiler/dart2js/codegen/model_test.dart
@@ -6,6 +6,7 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/closure.dart';
 import 'package:compiler/src/common.dart';
+import 'package:compiler/src/common/codegen.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/elements/entities.dart';
@@ -89,9 +90,9 @@
   void registerCalls(Features features, String tag, js.Node node,
       {String prefix = '', Set<js.PropertyAccess> handledAccesses}) {
     forEachNode(node, onCall: (js.Call node) {
-      js.Node target = node.target;
+      js.Node target = undefer(node.target);
       if (target is js.PropertyAccess) {
-        js.Node selector = target.selector;
+        js.Node selector = undefer(target.selector);
         bool fixedNameCall = false;
         String name;
         if (selector is js.Name) {
@@ -125,7 +126,7 @@
         return;
       }
 
-      js.Node receiver = node.receiver;
+      js.Node receiver = undefer(node.receiver);
       String receiverName;
       if (receiver is js.VariableUse) {
         receiverName = receiver.name;
@@ -138,7 +139,7 @@
         receiverName = 'this';
       }
 
-      js.Node selector = node.selector;
+      js.Node selector = undefer(node.selector);
       String name;
       if (selector is js.Name) {
         name = selector.key;
@@ -229,9 +230,9 @@
         }
 
         forEachNode(code, onAssignment: (js.Assignment node) {
-          js.Expression leftHandSide = node.leftHandSide;
+          js.Expression leftHandSide = undefer(node.leftHandSide);
           if (leftHandSide is js.PropertyAccess) {
-            js.Node selector = leftHandSide.selector;
+            js.Node selector = undefer(leftHandSide.selector);
             String name;
             if (selector is js.Name) {
               name = selector.key;
@@ -272,3 +273,9 @@
     return null;
   }
 }
+
+js.Node undefer(js.Node node) {
+  if (node is js.DeferredExpression) return undefer(node.value);
+  if (node is ModularName) return undefer(node.value);
+  return node;
+}
diff --git a/tests/compiler/dart2js/codegen/type_inference8_test.dart b/tests/compiler/dart2js/codegen/type_inference8_test.dart
index 865f73e..7cb7040 100644
--- a/tests/compiler/dart2js/codegen/type_inference8_test.dart
+++ b/tests/compiler/dart2js/codegen/type_inference8_test.dart
@@ -6,8 +6,14 @@
 
 import "package:async_helper/async_helper.dart";
 import "package:compiler/src/commandline_options.dart";
+import "package:compiler/src/common_elements.dart";
+import "package:compiler/src/compiler.dart";
 import "package:compiler/src/constants/values.dart";
+import "package:compiler/src/elements/entities.dart";
+import "package:compiler/src/inferrer/abstract_value_domain.dart";
+import "package:compiler/src/inferrer/types.dart";
 import 'package:compiler/src/inferrer/typemasks/masks.dart';
+import "package:compiler/src/world.dart";
 import "package:expect/expect.dart";
 import '../helpers/memory_compiler.dart';
 
@@ -33,29 +39,31 @@
 """;
 
 Future runTest1() async {
-  var result = await runCompiler(
+  CompilationResult result = await runCompiler(
       memorySourceFiles: {'main.dart': TEST1},
       options: [Flags.disableInlining]);
-  var compiler = result.compiler;
-  var results = compiler.globalInference.resultsForTesting;
-  var closedWorld = results.closedWorld;
-  var elementEnvironment = closedWorld.elementEnvironment;
-  var commonMasks = closedWorld.abstractValueDomain;
-  var element = elementEnvironment.lookupLibraryMember(
+  Compiler compiler = result.compiler;
+  GlobalTypeInferenceResults results =
+      compiler.globalInference.resultsForTesting;
+  JClosedWorld closedWorld = results.closedWorld;
+  JElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
+  AbstractValueDomain commonMasks = closedWorld.abstractValueDomain;
+  MemberEntity element = elementEnvironment.lookupLibraryMember(
       elementEnvironment.mainLibrary, 'foo');
-  var mask = results.resultOfMember(element).returnType;
-  var falseType =
+  AbstractValue mask = results.resultOfMember(element).returnType;
+  AbstractValue falseType =
       new ValueTypeMask(commonMasks.boolType, new FalseConstantValue());
   // 'foo' should always return false
   Expect.equals(falseType, mask);
   // the argument to 'bar' is always false
-  dynamic bar = elementEnvironment.lookupLibraryMember(
+  MemberEntity bar = elementEnvironment.lookupLibraryMember(
       elementEnvironment.mainLibrary, 'bar');
-  compiler.codegenWorldBuilder.forEachParameterAsLocal(bar, (barArg) {
-    var barArgMask = results.resultOfParameter(barArg);
+  elementEnvironment.forEachParameterAsLocal(closedWorld.globalLocalsMap, bar,
+      (barArg) {
+    AbstractValue barArgMask = results.resultOfParameter(barArg);
     Expect.equals(falseType, barArgMask);
   });
-  var barCode = compiler.backend.getGeneratedCode(bar);
+  String barCode = compiler.backend.getGeneratedCode(bar);
   Expect.isTrue(barCode.contains('"bbb"'));
   Expect.isFalse(barCode.contains('"aaa"'));
 }
@@ -81,35 +89,38 @@
 """;
 
 Future runTest2() async {
-  var result = await runCompiler(
+  CompilationResult result = await runCompiler(
       memorySourceFiles: {'main.dart': TEST2},
       options: [Flags.disableInlining]);
-  var compiler = result.compiler;
-  var results = compiler.globalInference.resultsForTesting;
-  var closedWorld = results.closedWorld;
-  var commonMasks = closedWorld.abstractValueDomain;
-  var elementEnvironment = closedWorld.elementEnvironment;
-  var element = elementEnvironment.lookupLibraryMember(
+  Compiler compiler = result.compiler;
+  GlobalTypeInferenceResults results =
+      compiler.globalInference.resultsForTesting;
+  JClosedWorld closedWorld = results.closedWorld;
+  AbstractValueDomain commonMasks = closedWorld.abstractValueDomain;
+  JElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
+  MemberEntity element = elementEnvironment.lookupLibraryMember(
       elementEnvironment.mainLibrary, 'foo');
-  var mask = results.resultOfMember(element).returnType;
+  AbstractValue mask = results.resultOfMember(element).returnType;
   // Can't infer value for foo's return type, it could be either true or false
   Expect.identical(commonMasks.boolType, mask);
-  dynamic bar = elementEnvironment.lookupLibraryMember(
+  MemberEntity bar = elementEnvironment.lookupLibraryMember(
       elementEnvironment.mainLibrary, 'bar');
-  compiler.codegenWorldBuilder.forEachParameterAsLocal(bar, (barArg) {
-    var barArgMask = results.resultOfParameter(barArg);
+  elementEnvironment.forEachParameterAsLocal(closedWorld.globalLocalsMap, bar,
+      (barArg) {
+    AbstractValue barArgMask = results.resultOfParameter(barArg);
     // The argument to bar should have the same type as the return type of foo
     Expect.identical(commonMasks.boolType, barArgMask);
   });
-  var barCode = compiler.backend.getGeneratedCode(bar);
+  String barCode = compiler.backend.getGeneratedCode(bar);
   Expect.isTrue(barCode.contains('"bbb"'));
   // Still must output the print for "aaa"
   Expect.isTrue(barCode.contains('"aaa"'));
 }
 
 main() {
-  asyncStart();
-  runTest1().then((_) {
-    return runTest2();
-  }).whenComplete(asyncEnd);
+  asyncTest(() async {
+    ;
+    await runTest1();
+    await runTest2();
+  });
 }
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 3df3488..84af435 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -30,6 +30,7 @@
 model/native_test: Pass, Slow
 model/no_such_method_enabled_test: Pass, Slow
 model/subtype_test: Pass, Slow
+modular/*: Slow, Pass
 packages/*: Skip # Skip packages folder
 rti/rti_emission_test: Pass, Slow
 rti/rti_need0_test: Pass, Slow
diff --git a/tests/compiler/dart2js/deferred/emit_type_checks_test.dart b/tests/compiler/dart2js/deferred/emit_type_checks_test.dart
index a6cf80c..2aea089 100644
--- a/tests/compiler/dart2js/deferred/emit_type_checks_test.dart
+++ b/tests/compiler/dart2js/deferred/emit_type_checks_test.dart
@@ -22,7 +22,7 @@
     String mainOutput = collector.getOutput('', OutputType.js);
     String deferredOutput = collector.getOutput('out_1', OutputType.jsPart);
     JavaScriptBackend backend = compiler.backend;
-    String isPrefix = backend.namer.operatorIsPrefix;
+    String isPrefix = backend.namerForTesting.fixedNames.operatorIsPrefix;
     Expect.isTrue(
         deferredOutput.contains('${isPrefix}A: 1'),
         "Deferred output doesn't contain '${isPrefix}A: 1':\n"
diff --git a/tests/compiler/dart2js/deferred/follow_constant_dependencies_test.dart b/tests/compiler/dart2js/deferred/follow_constant_dependencies_test.dart
index 21bb4bc..9da9d81 100644
--- a/tests/compiler/dart2js/deferred/follow_constant_dependencies_test.dart
+++ b/tests/compiler/dart2js/deferred/follow_constant_dependencies_test.dart
@@ -32,7 +32,7 @@
     }
 
     dynamic codegenWorldBuilder = compiler.codegenWorldBuilder;
-    codegenWorldBuilder.compiledConstants
+    codegenWorldBuilder.compiledConstantsForTesting
         .forEach(addConstantWithDependendencies);
     for (String stringValue in ["cA", "cB", "cC"]) {
       StringConstantValue constant =
diff --git a/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
index e79c1f8..45bd24b 100644
--- a/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
@@ -29,7 +29,7 @@
 
     var mainOutputUnit = closedWorld.outputUnitData.mainOutputUnit;
     var backend = compiler.backend;
-    var classes = backend.emitter.neededClasses;
+    var classes = backend.emitterTask.neededClasses;
     var inputElement = classes.where((e) => e.name == 'InputElement').single;
     dynamic lib1 = lookupLibrary("memory:lib1.dart");
     var foo1 = env.lookupLibraryMember(lib1, "foo1");
diff --git a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
index e79853c..b23c178 100644
--- a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
+++ b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
@@ -105,7 +105,7 @@
       {bool verbose: false}) {
     JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     OutputUnitData data = closedWorld.outputUnitData;
-    String value = outputUnitString(data.outputUnitForClass(cls));
+    String value = outputUnitString(data.outputUnitForClassForTesting(cls));
 
     JsToElementMap elementMap = closedWorld.elementMap;
     ClassDefinition definition = elementMap.getClassDefinition(cls);
@@ -141,7 +141,7 @@
 
   String getMemberValue(MemberEntity member, Set<String> constants) {
     StringBuffer sb = new StringBuffer();
-    sb.write(outputUnitString(_data.outputUnitForMember(member)));
+    sb.write(outputUnitString(_data.outputUnitForMemberForTesting(member)));
     if (constants.isNotEmpty) {
       List<String> text = constants.toList()..sort();
       sb.write(',constants=[${text.join(',')}]');
@@ -166,7 +166,7 @@
         }
         _registerValue(
             new NodeId(span.begin, IdKind.node),
-            outputUnitString(_data.outputUnitForConstant(constant)),
+            outputUnitString(_data.outputUnitForConstantForTesting(constant)),
             node,
             span,
             actualMap,
diff --git a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
index 545c685..a207e12 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
@@ -17,7 +17,7 @@
 /*strong.element: C2b:OutputUnit(1, {lib1})*/
 const C2b = /*strong.OutputUnit(1, {lib1})*/ const C(1010);
 
-/*class: D:OutputUnit(main, {})*/
+/*class: D:null*/
 class D {
   /*strong.element: D.C3:OutputUnit(1, {lib1})*/
   static const C3 = "string2";
diff --git a/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart
index 18f9ec3..4707d65 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart
@@ -38,7 +38,7 @@
   }
 }
 
-/*class: C1:OutputUnit(main, {})*/
+/*class: C1:null*/
 class C1 {
   /*strong.element: C1.foo:OutputUnit(3, {lib2})*/
   /*strongConst.element: C1.foo:
diff --git a/tests/compiler/dart2js/end_to_end/command_line_test.dart b/tests/compiler/dart2js/end_to_end/command_line_test.dart
index 88fb3e8..076b918 100644
--- a/tests/compiler/dart2js/end_to_end/command_line_test.dart
+++ b/tests/compiler/dart2js/end_to_end/command_line_test.dart
@@ -10,6 +10,7 @@
 import 'package:expect/expect.dart';
 
 import 'package:compiler/compiler_new.dart' as api;
+import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/dart2js.dart' as entry;
 import 'package:compiler/src/options.dart' show CompilerOptions;
 
@@ -17,11 +18,191 @@
   entry.enableWriteString = false;
   asyncTest(() async {
     await test([], exitCode: 1);
-    await test(['foo.dart']);
+    await test(['foo.dart'], out: 'out.js');
+    await test(['foo.dart', '-ofoo.js'], out: 'foo.js');
+    await test(['foo.dart', '--out=foo.js'], out: 'foo.js');
+
+    await test([Flags.cfeOnly], exitCode: 1);
+    await test([Flags.cfeOnly, 'foo.dart'], out: 'out.dill');
+    await test([Flags.cfeOnly, 'foo.dart', '--out=out.dill'], out: 'out.dill');
+    await test([Flags.cfeOnly, 'foo.dart', Flags.readData], exitCode: 1);
+    await test(['foo.dart', Flags.readData, Flags.cfeOnly], exitCode: 1);
+    await test([Flags.cfeOnly, 'foo.dart', Flags.readCodegen], exitCode: 1);
+    await test(['foo.dart', Flags.readCodegen, Flags.cfeOnly], exitCode: 1);
+    await test([Flags.cfeOnly, 'foo.dart', Flags.writeData], exitCode: 1);
+    await test(['foo.dart', Flags.writeData, Flags.cfeOnly], exitCode: 1);
+    await test([Flags.cfeOnly, 'foo.dart', Flags.writeCodegen], exitCode: 1);
+    await test(['foo.dart', Flags.writeCodegen, Flags.cfeOnly], exitCode: 1);
+
+    await test([Flags.writeData, 'foo.dart'],
+        out: 'out.dill', writeData: 'out.dill.data');
+    await test(['${Flags.writeData}=foo.data', 'foo.dart', '--out=foo.dill'],
+        out: 'foo.dill', writeData: 'foo.data');
+    await test([Flags.readData, Flags.writeData, 'foo.dart'], exitCode: 1);
+    await test([Flags.writeData, Flags.readData, 'foo.dart'], exitCode: 1);
+    await test([Flags.readCodegen, Flags.writeData, 'foo.dart'], exitCode: 1);
+    await test([Flags.writeData, Flags.readCodegen, 'foo.dart'], exitCode: 1);
+
+    await test([Flags.readData, 'foo.dill'],
+        out: 'out.js', readData: 'foo.dill.data');
+    await test([Flags.readData, 'foo.dill', '--out=foo.js'],
+        out: 'foo.js', readData: 'foo.dill.data');
+    await test(['${Flags.readData}=out.data', 'foo.dill'],
+        out: 'out.js', readData: 'out.data');
+    await test(['${Flags.readData}=out.data', 'foo.dill', '--out=foo.js'],
+        out: 'foo.js', readData: 'out.data');
+
+    await test([
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShard}=0',
+      '${Flags.codegenShards}=2'
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShard}=0',
+      '${Flags.codegenShards}=2'
+    ],
+        out: 'out',
+        readData: 'foo.dill.data',
+        writeCodegen: 'out.code',
+        codegenShard: 0,
+        codegenShards: 2);
+    await test([
+      Flags.writeCodegen,
+      Flags.readData,
+      'foo.dill',
+      '${Flags.codegenShard}=1',
+      '${Flags.codegenShards}=2'
+    ],
+        out: 'out',
+        readData: 'foo.dill.data',
+        writeCodegen: 'out.code',
+        codegenShard: 1,
+        codegenShards: 2);
+    await test([
+      '${Flags.readData}=foo.data',
+      '${Flags.writeCodegen}=foo.code',
+      'foo.dill',
+      '${Flags.codegenShard}=0',
+      '${Flags.codegenShards}=3'
+    ],
+        out: 'out',
+        readData: 'foo.data',
+        writeCodegen: 'foo.code',
+        codegenShard: 0,
+        codegenShards: 3);
+    await test([
+      '${Flags.readData}=foo.data',
+      '${Flags.writeCodegen}',
+      'foo.dill',
+      '--out=foo.js',
+      '${Flags.codegenShard}=0',
+      '${Flags.codegenShards}=2'
+    ],
+        out: 'foo.js',
+        readData: 'foo.data',
+        writeCodegen: 'foo.js.code',
+        codegenShard: 0,
+        codegenShards: 2);
+    await test([Flags.writeCodegen, 'foo.dill', Flags.readCodegen],
+        exitCode: 1);
+    await test([Flags.readCodegen, Flags.writeCodegen, 'foo.dill'],
+        exitCode: 1);
+    await test(
+        [Flags.readData, Flags.writeCodegen, 'foo.dill', Flags.readCodegen],
+        exitCode: 1);
+    await test(
+        [Flags.readCodegen, Flags.readData, Flags.writeCodegen, 'foo.dill'],
+        exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShard}=0'
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShards}=2'
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShards}=0'
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShard}=-1',
+      '${Flags.codegenShards}=2'
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShard}=2',
+      '${Flags.codegenShards}=2'
+    ], exitCode: 1);
+
+    await test([Flags.readCodegen, 'foo.dill', '${Flags.codegenShards}=2'],
+        out: 'out.js',
+        readData: 'foo.dill.data',
+        readCodegen: 'foo.dill.code',
+        codegenShards: 2);
+    await test([
+      '${Flags.readCodegen}=foo.code',
+      'foo.dill',
+      '${Flags.codegenShards}=3'
+    ],
+        out: 'out.js',
+        readData: 'foo.dill.data',
+        readCodegen: 'foo.code',
+        codegenShards: 3);
+
+    await test([
+      Flags.readData,
+      Flags.readCodegen,
+      'foo.dill',
+      '${Flags.codegenShards}=2'
+    ],
+        out: 'out.js',
+        readData: 'foo.dill.data',
+        readCodegen: 'foo.dill.code',
+        codegenShards: 2);
+    await test([
+      '${Flags.readData}=foo.data',
+      '${Flags.readCodegen}=foo.code',
+      'foo.dill',
+      '${Flags.codegenShards}=3',
+      '-v'
+    ],
+        out: 'out.js',
+        readData: 'foo.data',
+        readCodegen: 'foo.code',
+        codegenShards: 3);
   });
 }
 
-Future test(List<String> arguments, {int exitCode}) async {
+Future test(List<String> arguments,
+    {int exitCode,
+    String out,
+    String readData,
+    String writeData,
+    String readCodegen,
+    String writeCodegen,
+    int codegenShard,
+    int codegenShards}) async {
   print('--------------------------------------------------------------------');
   print('dart2js ${arguments.join(' ')}');
   print('--------------------------------------------------------------------');
@@ -47,8 +228,23 @@
   Expect.equals(exitCode, actualExitCode, "Unexpected exit code");
   if (actualExitCode == null) {
     Expect.isNotNull(options, "Missing options object");
+    Expect.equals(toUri(out), options.outputUri, "Unexpected output uri.");
+    Expect.equals(
+        toUri(readData), options.readDataUri, "Unexpected readData uri");
+    Expect.equals(
+        toUri(writeData), options.writeDataUri, "Unexpected writeData uri");
+    Expect.equals(toUri(readCodegen), options.readCodegenUri,
+        "Unexpected readCodegen uri");
+    Expect.equals(toUri(writeCodegen), options.writeCodegenUri,
+        "Unexpected writeCodegen uri");
+    Expect.equals(
+        codegenShard, options.codegenShard, "Unexpected codegenShard uri");
+    Expect.equals(
+        codegenShards, options.codegenShards, "Unexpected codegenShards uri");
   }
 
   entry.compileFunc = oldCompileFunc;
   entry.exitFunc = oldExitFunc;
 }
+
+Uri toUri(String path) => path != null ? Uri.base.resolve(path) : null;
diff --git a/tests/compiler/dart2js/end_to_end/exit_code_test.dart b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
index aea5404..3397753 100644
--- a/tests/compiler/dart2js/end_to_end/exit_code_test.dart
+++ b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
@@ -12,6 +12,7 @@
 import 'package:compiler/compiler_new.dart' as api;
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/common/codegen.dart';
+import 'package:compiler/src/common/work.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/dart2js.dart' as entry;
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
@@ -20,9 +21,9 @@
 import 'package:compiler/src/diagnostics/spannable.dart';
 import 'package:compiler/src/apiimpl.dart' as apiimpl;
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/inferrer/types.dart';
 import 'package:compiler/src/js_backend/js_backend.dart';
 import 'package:compiler/src/null_compiler_output.dart';
+import 'package:compiler/src/serialization/serialization.dart';
 import 'package:compiler/src/options.dart' show CompilerOptions;
 import 'package:compiler/src/universe/world_impact.dart';
 import 'package:compiler/src/world.dart';
@@ -110,10 +111,15 @@
             useNewSourceInfo: compiler.options.useNewSourceInfo);
 
   @override
-  WorldImpact codegen(CodegenWorkItem work, JClosedWorld closedWorld,
-      GlobalTypeInferenceResults results) {
+  WorldImpact generateCode(
+      WorkItem work,
+      JClosedWorld closedWorld,
+      CodegenResults codegenResults,
+      EntityLookup entityLookup,
+      ComponentLookup componentLookup) {
     compiler.test('Compiler.codegen');
-    return super.codegen(work, closedWorld, results);
+    return super.generateCode(
+        work, closedWorld, codegenResults, entityLookup, componentLookup);
   }
 }
 
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index 75f2163..799be65 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -109,6 +109,9 @@
   /// Returns `true` if [computeClassData] is supported.
   bool get computesClassData => false;
 
+  /// Returns `true` if frontend member should be tested.
+  bool get testFrontend => false;
+
   /// Function that computes a data mapping for [cls].
   ///
   /// Fills [actualMap] with the data and [sourceSpanMap] with the source spans
@@ -525,7 +528,6 @@
     List<String> options: const <String>[],
     List<String> args: const <String>[],
     Directory libDirectory: null,
-    bool testFrontend: false,
     bool forUserLibrariesOnly: true,
     Callback setUpFunction,
     int shards: 1,
@@ -632,7 +634,7 @@
             options: options,
             verbose: verbose,
             printCode: printCode,
-            testFrontend: testFrontend,
+            testFrontend: dataComputer.testFrontend,
             forUserLibrariesOnly: forUserLibrariesOnly,
             globalIds: annotations.globalData.keys);
         if (await checkCode(strongName, entity.uri, code, annotations,
@@ -667,7 +669,7 @@
               entryPoint, memorySourceFiles, dataComputer,
               options: options,
               verbose: verbose,
-              testFrontend: testFrontend,
+              testFrontend: dataComputer.testFrontend,
               forUserLibrariesOnly: forUserLibrariesOnly,
               globalIds: annotations.globalData.keys);
           if (await checkCode(omitName, entity.uri, code, annotations,
diff --git a/tests/compiler/dart2js/equivalence/show_helper.dart b/tests/compiler/dart2js/equivalence/show_helper.dart
index c1bbe3f..8b8d4bc 100644
--- a/tests/compiler/dart2js/equivalence/show_helper.dart
+++ b/tests/compiler/dart2js/equivalence/show_helper.dart
@@ -24,7 +24,7 @@
 }
 
 show<T>(ArgResults argResults, DataComputer<T> dataComputer,
-    {bool testFrontend: false, List<String> options: const <String>[]}) async {
+    {List<String> options: const <String>[]}) async {
   dataComputer.setup();
 
   if (argResults.wasParsed('colors')) {
@@ -51,7 +51,7 @@
   CompiledData<T> data = await computeData<T>(
       entryPoint, const {}, dataComputer,
       options: options,
-      testFrontend: testFrontend,
+      testFrontend: dataComputer.testFrontend,
       forUserLibrariesOnly: false,
       skipUnprocessedMembers: true,
       skipFailedCompilations: true,
diff --git a/tests/compiler/dart2js/field_analysis/kfield_analysis_test.dart b/tests/compiler/dart2js/field_analysis/kfield_analysis_test.dart
index 559810d..72b427c 100644
--- a/tests/compiler/dart2js/field_analysis/kfield_analysis_test.dart
+++ b/tests/compiler/dart2js/field_analysis/kfield_analysis_test.dart
@@ -18,10 +18,7 @@
   asyncTest(() async {
     Directory dataDir = new Directory.fromUri(Platform.script.resolve('kdata'));
     await checkTests(dataDir, const KAllocatorAnalysisDataComputer(),
-        args: args,
-        testOmit: false,
-        testFrontend: true,
-        testCFEConstants: true);
+        args: args, testOmit: false, testCFEConstants: true);
   });
 }
 
@@ -71,6 +68,9 @@
   }
 
   @override
+  bool get testFrontend => true;
+
+  @override
   DataInterpreter<Features> get dataValidator =>
       const FeaturesDataInterpreter();
 }
diff --git a/tests/compiler/dart2js/generic_methods/world_test.dart b/tests/compiler/dart2js/generic_methods/world_test.dart
index dc793c1..d0edbe1 100644
--- a/tests/compiler/dart2js/generic_methods/world_test.dart
+++ b/tests/compiler/dart2js/generic_methods/world_test.dart
@@ -86,13 +86,13 @@
         await runCompiler(memorySourceFiles: {'main.dart': code});
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    CodegenWorldBuilder worldBuilder = compiler.codegenWorldBuilder;
+    CodegenWorld codegenWorld = compiler.codegenWorldForTesting;
 
     CallStructure noTypeArguments = new CallStructure(0, [], 0);
     CallStructure oneTypeArgument = new CallStructure(0, [], 1);
 
     Iterable<CallStructure> getCallStructures(String name) {
-      return worldBuilder
+      return codegenWorld
               .invocationsByName(name)
               ?.keys
               ?.map((s) => s.callStructure) ??
diff --git a/tests/compiler/dart2js/helpers/ir_types.dart b/tests/compiler/dart2js/helpers/ir_types.dart
index 280ae12..cd18f77 100644
--- a/tests/compiler/dart2js/helpers/ir_types.dart
+++ b/tests/compiler/dart2js/helpers/ir_types.dart
@@ -20,7 +20,7 @@
     type.accept1(this, sb);
   }
 
-  void _writeTypes(List<ir.DartType> types, StringBuffer sb) {
+  void _writeTypes(Iterable<ir.DartType> types, StringBuffer sb) {
     String comma = '';
     for (ir.DartType type in types) {
       sb.write(comma);
@@ -29,7 +29,8 @@
     }
   }
 
-  void _writeTypeArguments(List<ir.DartType> typeArguments, StringBuffer sb) {
+  void _writeTypeArguments(
+      Iterable<ir.DartType> typeArguments, StringBuffer sb) {
     if (typeArguments.isNotEmpty) {
       sb.write('<');
       _writeTypes(typeArguments, sb);
diff --git a/tests/compiler/dart2js/helpers/program_lookup.dart b/tests/compiler/dart2js/helpers/program_lookup.dart
index f4ce6d9e..4f4d052 100644
--- a/tests/compiler/dart2js/helpers/program_lookup.dart
+++ b/tests/compiler/dart2js/helpers/program_lookup.dart
@@ -43,8 +43,8 @@
   final Namer namer;
 
   ProgramLookup(Compiler compiler)
-      : this.program = compiler.backend.emitter.emitter.programForTesting,
-        this.namer = compiler.backend.namer;
+      : this.program = compiler.backend.emitterTask.emitter.programForTesting,
+        this.namer = compiler.backend.namerForTesting;
 
   Fragment getFragment(OutputUnit outputUnit) {
     for (Fragment fragment in program.fragments) {
diff --git a/tests/compiler/dart2js/helpers/type_test_helper.dart b/tests/compiler/dart2js/helpers/type_test_helper.dart
index cda6070..f95e6bb 100644
--- a/tests/compiler/dart2js/helpers/type_test_helper.dart
+++ b/tests/compiler/dart2js/helpers/type_test_helper.dart
@@ -12,6 +12,7 @@
 import 'package:compiler/src/elements/types.dart';
 import 'package:compiler/src/compiler.dart' show Compiler;
 import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/kernel/kelements.dart';
 import 'package:compiler/src/kernel/kernel_strategy.dart';
 import 'package:compiler/src/world.dart' show JClosedWorld, KClosedWorld;
 import 'memory_compiler.dart' as memory;
@@ -145,12 +146,13 @@
     }
     MemberEntity member = _getMember(name, cls);
     DartType type;
-    compiler.resolutionWorldBuilder
-        .forEachLocalFunction((MemberEntity m, Local local) {
-      if (member == m) {
+
+    for (KLocalFunction local in compiler
+        .resolutionWorldBuilder.closedWorldForTesting.localFunctions) {
+      if (local.memberContext == member) {
         type ??= elementEnvironment.getLocalFunctionType(local);
       }
-    });
+    }
     return type;
   }
 
diff --git a/tests/compiler/dart2js/impact/data/async.dart b/tests/compiler/dart2js/impact/data/async.dart
index 69792ef..bde8eb7 100644
--- a/tests/compiler/dart2js/impact/data/async.dart
+++ b/tests/compiler/dart2js/impact/data/async.dart
@@ -219,9 +219,9 @@
 
 /*element: testAsyncForIn:
  dynamic=[
-  cancel(0),
-  current,
-  moveNext(0)],
+  _StreamIterator.cancel(0),
+  _StreamIterator.current,
+  _StreamIterator.moveNext(0)],
  static=[
   StreamIterator.(1),
   _asyncAwait(2),
@@ -243,9 +243,9 @@
 
 /*element: testAsyncForInTyped:
  dynamic=[
-  cancel(0),
-  current,
-  moveNext(0)],
+  _StreamIterator.cancel(0),
+  _StreamIterator.current,
+  _StreamIterator.moveNext(0)],
  static=[
   StreamIterator.(1),
   _asyncAwait(2),
diff --git a/tests/compiler/dart2js/impact/data/statements.dart b/tests/compiler/dart2js/impact/data/statements.dart
index 3b5e240..7a89d28 100644
--- a/tests/compiler/dart2js/impact/data/statements.dart
+++ b/tests/compiler/dart2js/impact/data/statements.dart
@@ -67,9 +67,9 @@
 
 /*element: testForIn:
  dynamic=[
-  current,
-  iterator,
-  moveNext(0)],
+  Iterator.current,
+  Iterator.iterator,
+  Iterator.moveNext(0)],
  static=[checkConcurrentModificationError(2)],
  type=[
   impl:Iterable<dynamic>,
@@ -84,9 +84,9 @@
 
 /*element: testForInTyped:
  dynamic=[
-  current,
-  iterator,
-  moveNext(0)],
+  Iterator.current,
+  Iterator.iterator,
+  Iterator.moveNext(0)],
  static=[checkConcurrentModificationError(2)],
  type=[
   impl:Iterable<dynamic>,
diff --git a/tests/compiler/dart2js/impact/impact_test.dart b/tests/compiler/dart2js/impact/impact_test.dart
index 27f2ea9..38bfe17 100644
--- a/tests/compiler/dart2js/impact/impact_test.dart
+++ b/tests/compiler/dart2js/impact/impact_test.dart
@@ -26,10 +26,7 @@
     print('==================================================================');
     useImpactDataForTesting = false;
     await checkTests(dataDir, const ImpactDataComputer(),
-        libDirectory: libDirectory,
-        args: args,
-        testOmit: false,
-        testFrontend: true);
+        libDirectory: libDirectory, args: args, testOmit: false);
 
     print('Testing computation of ResolutionImpact through ImpactData');
     print('==================================================================');
@@ -38,7 +35,6 @@
         libDirectory: libDirectory,
         args: args,
         testOmit: false,
-        testFrontend: true,
         testCFEConstants: true);
   });
 }
@@ -95,6 +91,9 @@
   }
 
   @override
+  bool get testFrontend => true;
+
+  @override
   DataInterpreter<Features> get dataValidator =>
       const FeaturesDataInterpreter();
 }
diff --git a/tests/compiler/dart2js/inference/data/field_type.dart b/tests/compiler/dart2js/inference/data/field_type.dart
index 4f499a9..d97d431 100644
--- a/tests/compiler/dart2js/inference/data/field_type.dart
+++ b/tests/compiler/dart2js/inference/data/field_type.dart
@@ -24,7 +24,9 @@
   test18();
   test19();
   test20();
+  test20b();
   test21();
+  test21b();
   test22();
   test23();
   test24();
@@ -460,26 +462,22 @@
 }
 
 class A20 {
-  /*element: A20.f20:[null|exact=JSUInt31]*/
+  /*element: A20.f20:[null]*/
   var f20;
 
   /*element: A20.:[exact=A20]*/
   A20() {
     dynamic a = this;
-    // TODO(johnniwinther): Fix ast equivalence on instance fields in for.
     /*iterator: [exact=A20]*/
-    /*current: [exact=A20]*/
-    /*moveNext: [exact=A20]*/
+    /*current: [empty]*/
+    /*moveNext: [empty]*/
     for (/*update: [exact=A20]*/ f20 in a) {}
   }
 
-  /*element: A20.iterator:[exact=A20]*/
   get iterator => this;
 
-  /*element: A20.current:[exact=JSUInt31]*/
   get current => 42;
 
-  /*element: A20.moveNext:Value([exact=JSBool], value: false)*/
   bool moveNext() => false;
 }
 
@@ -488,6 +486,37 @@
   new A20();
 }
 
+class A20b extends Iterable implements Iterator {
+  /*element: A20b.f20b:[null|exact=JSUInt31]*/
+  var f20b;
+
+  /*element: A20b.:[exact=A20b]*/
+  A20b() {
+    dynamic a = this;
+    /*iterator: [exact=A20b]*/
+    /*current: [exact=A20b]*/
+    /*moveNext: [exact=A20b]*/
+    for (/*update: [exact=A20b]*/ f20b in a) {}
+  }
+
+  /*element: A20b.iterator:[exact=A20b]*/
+  @override
+  get iterator => this;
+
+  /*element: A20b.current:[exact=JSUInt31]*/
+  @override
+  get current => 42;
+
+  /*element: A20b.moveNext:Value([exact=JSBool], value: false)*/
+  @override
+  bool moveNext() => false;
+}
+
+/*element: test20b:[null]*/
+test20b() {
+  new A20b();
+}
+
 class A21 {
   /*element: A21.f21:[null|exact=JSUInt31]*/
   var f21;
@@ -496,14 +525,14 @@
   A21() {
     dynamic a = this;
     /*iterator: [exact=A21]*/
-    /*current: [null]*/
-    /*moveNext: [null]*/
+    /*current: [empty]*/
+    /*moveNext: [empty]*/
     for (
         // ignore: unused_local_variable
         var i in a) {}
     /*update: [exact=A21]*/ f21 = 42;
   }
-  /*element: A21.iterator:[null]*/
+
   get iterator => null;
 }
 
@@ -512,6 +541,32 @@
   new A21();
 }
 
+class A21b extends Iterable {
+  /*element: A21b.f21:[null|exact=JSUInt31]*/
+  var f21;
+
+  /*element: A21b.:[exact=A21b]*/
+  A21b() {
+    dynamic a = this;
+    /*iterator: [exact=A21b]*/
+    /*current: [null]*/
+    /*moveNext: [null]*/
+    for (
+        // ignore: unused_local_variable
+        var i in a) {}
+    /*update: [exact=A21b]*/ f21 = 42;
+  }
+
+  /*element: A21b.iterator:[null]*/
+  @override
+  get iterator => null;
+}
+
+/*element: test21b:[null]*/
+test21b() {
+  new A21b();
+}
+
 class A22 {
   /*element: A22.f22a:[exact=JSUInt31]*/
   var f22a;
@@ -617,6 +672,7 @@
 /*element: B24.:[exact=B24]*/
 class B24 extends A24 {
   /*element: B24.bar24:[exact=JSUInt31]*/
+  @override
   bar24() => 42;
 }
 
@@ -683,6 +739,7 @@
 
 /*element: B27.:[exact=B27]*/
 class B27 extends A27 {
+  @override
   set f27b(/*[exact=JSUInt31]*/ value) {}
 }
 
diff --git a/tests/compiler/dart2js/inlining/inlining_test.dart b/tests/compiler/dart2js/inlining/inlining_test.dart
index c6a8b92..8e73762 100644
--- a/tests/compiler/dart2js/inlining/inlining_test.dart
+++ b/tests/compiler/dart2js/inlining/inlining_test.dart
@@ -12,7 +12,7 @@
 import 'package:compiler/src/js_backend/backend.dart';
 import 'package:compiler/src/js_model/element_map.dart';
 import 'package:compiler/src/js_model/js_world.dart';
-import 'package:compiler/src/ssa/builder_kernel.dart' as kernel;
+import 'package:compiler/src/ssa/builder_kernel.dart';
 import 'package:compiler/src/universe/world_impact.dart';
 import 'package:compiler/src/universe/use.dart';
 import 'package:kernel/ast.dart' as ir;
@@ -53,6 +53,7 @@
   final JavaScriptBackend backend;
   final JsToElementMap _elementMap;
   final ClosureData _closureDataLookup;
+  final InlineDataCache _inlineDataCache;
 
   InliningIrComputer(
       DiagnosticReporter reporter,
@@ -61,7 +62,8 @@
       MemberEntity member,
       this.backend,
       this._closureDataLookup)
-      : super(reporter, actualMap);
+      : this._inlineDataCache = new InlineDataCache(enableUserAssertions: true),
+        super(reporter, actualMap);
 
   String getMemberValue(MemberEntity member) {
     if (member is FunctionEntity) {
@@ -125,14 +127,16 @@
 
   String getTooDifficultReasonForbidLoops(MemberEntity member) {
     if (member is! FunctionEntity) return null;
-    return kernel.InlineWeeder.cannotBeInlinedReason(_elementMap, member, null,
-        enableUserAssertions: true);
+    return _inlineDataCache
+        .getInlineData(_elementMap, member)
+        .cannotBeInlinedReason();
   }
 
   String getTooDifficultReasonAllowLoops(MemberEntity member) {
     if (member is! FunctionEntity) return null;
-    return kernel.InlineWeeder.cannotBeInlinedReason(_elementMap, member, null,
-        allowLoops: true, enableUserAssertions: true);
+    return _inlineDataCache
+        .getInlineData(_elementMap, member)
+        .cannotBeInlinedReason(allowLoops: true);
   }
 
   @override
diff --git a/tests/compiler/dart2js/js/js_parser_statements_test.dart b/tests/compiler/dart2js/js/js_parser_statements_test.dart
index d5d1de7..cc8c378 100644
--- a/tests/compiler/dart2js/js/js_parser_statements_test.dart
+++ b/tests/compiler/dart2js/js/js_parser_statements_test.dart
@@ -351,8 +351,8 @@
         'fieldName'
       ],
       'className.prototype.getterName = function(r, y) {\n'
-      '  return r.fieldName;\n'
-      '};');
+          '  return r.fieldName;\n'
+          '};');
   testStatement(
       '#a.prototype.#b = function(#c) { return #d.#e };',
       {
@@ -363,8 +363,8 @@
         'e': 'fieldName'
       },
       'className.prototype.getterName = function(r, y) {\n'
-      '  return r.fieldName;\n'
-      '};');
+          '  return r.fieldName;\n'
+          '};');
 
   testStatement(
       'function foo(r, #) { return #[r](#) }',
@@ -406,8 +406,8 @@
         'c': 'name4_5'
       },
       'name1_2.prototype.name1_2 = function(r, y) {\n'
-      '  return name4_5.name4_5;\n'
-      '};');
+          '  return name4_5.name4_5;\n'
+          '};');
 
   testStatement('label: while (a) { label2: break label;}', [],
       'label:\n  while (a)\n    label2:\n      break label;\n  ');
diff --git a/tests/compiler/dart2js/jsinterop/declaration_test.dart b/tests/compiler/dart2js/jsinterop/declaration_test.dart
index 92e8054..2239c40 100644
--- a/tests/compiler/dart2js/jsinterop/declaration_test.dart
+++ b/tests/compiler/dart2js/jsinterop/declaration_test.dart
@@ -65,7 +65,7 @@
 '''),
   const Test(
       'Js-interop class with external method with optional parameters '
-      'with default values.',
+          'with default values.',
       '''
 @JS()
 library test;
@@ -172,7 +172,7 @@
 '''),
   const Test(
       'Js-interop class that extends a js-interop class, '
-      'reversed declaration order.',
+          'reversed declaration order.',
       '''
 @JS()
 library test;
@@ -353,7 +353,7 @@
 '''),
   const Test(
       'External factory constructor with named parameters '
-      'with default parameters.',
+          'with default parameters.',
       '''
 @JS()
 library test;
diff --git a/tests/compiler/dart2js/member_usage/data/constant_folding.dart b/tests/compiler/dart2js/member_usage/data/constant_folding.dart
index 4fa09bb..0225146 100644
--- a/tests/compiler/dart2js/member_usage/data/constant_folding.dart
+++ b/tests/compiler/dart2js/member_usage/data/constant_folding.dart
@@ -31,7 +31,7 @@
         actual.isNegative,
         (reason == null ? "" : "$reason ") +
             "${expected.toString()} and "
-            "${actual.toString()} have different signs.");
+                "${actual.toString()} have different signs.");
   }
 }
 
diff --git a/tests/compiler/dart2js/member_usage/data/fields.dart b/tests/compiler/dart2js/member_usage/data/fields.dart
index 5d95285..6b40661 100644
--- a/tests/compiler/dart2js/member_usage/data/fields.dart
+++ b/tests/compiler/dart2js/member_usage/data/fields.dart
@@ -11,6 +11,12 @@
 /*element: field1c:init,read,write*/
 var field1c;
 
+// Invocations of static/top level fields are converted into 'field1d.call(...)`
+// so we don't have an invocation of the field but instead an additional dynamic
+// call to 'call'.
+/*element: field1d:init,read*/
+var field1d;
+
 /*element: field2a:read*/
 get field2a => 42;
 
@@ -27,6 +33,14 @@
 /*element: field2c=:write*/
 set field2c(_) {}
 
+// Invocations of static/top level getters are converted into
+// 'field2d.call(...)` so we don't have an invocation of the field but instead
+// an additional dynamic call to 'call'.
+/*element: field2d:read*/
+get field2d => 42;
+
+set field2d(_) {}
+
 class Class {
   /*element: Class.field1a:init,read*/
   var field1a;
@@ -37,6 +51,9 @@
   /*element: Class.field1c:init,read,write*/
   var field1c;
 
+  /*element: Class.field1d:init,invoke,read=static*/
+  var field1d;
+
   /*element: Class.field2a:read*/
   get field2a => 42;
 
@@ -53,6 +70,11 @@
   /*element: Class.field2c=:write*/
   set field2c(_) {}
 
+  /*element: Class.field2d:invoke,read=static*/
+  get field2d => null;
+
+  set field2d(_) {}
+
   /*element: Class.field3a:init*/
   var field3a = 0;
 
@@ -67,10 +89,12 @@
     field1a;
     field1b = 42;
     field1c = field1c;
+    field1d();
 
     field2a;
     field2b = 42;
     field2c = field2c;
+    field2d();
   }
 }
 
@@ -79,10 +103,12 @@
   field1a;
   field1b = 42;
   field1c = field1c;
+  field1d();
 
   field2a;
   field2b = 42;
   field2c = field2c;
+  field2d();
 
   new Class().test();
 }
diff --git a/tests/compiler/dart2js/member_usage/data/general.dart b/tests/compiler/dart2js/member_usage/data/general.dart
index ffab22b..9954b67 100644
--- a/tests/compiler/dart2js/member_usage/data/general.dart
+++ b/tests/compiler/dart2js/member_usage/data/general.dart
@@ -34,43 +34,75 @@
 /*element: C.:invoke*/
 class C extends A {
   /*element: C.method1:invoke*/
+  @override
   method1() {}
 
   /*element: B.method2:invoke*/
+  @override
   method2() {}
+
+  @override
   method4() {}
 
   /*element: C.getter:read*/
+  @override
   get getter => 42;
+
+  @override
   set setter(_) {}
 }
 
 /*element: D.:invoke*/
 class D implements B {
+  @override
   method1() {}
 
   /*element: D.method2:invoke*/
+  @override
   method2() {}
+
+  @override
   method5() {}
+
+  @override
   get getter => 42;
 
   /*element: D.setter=:write*/
+  @override
   set setter(_) {}
 }
 
 class E implements A {
+  @override
   method1() {}
+
+  @override
   method2() {}
+
+  @override
   method4() {}
+
+  @override
   get getter => 42;
+
+  @override
   set setter(_) {}
 }
 
 class F extends B {
+  @override
   method1() {}
+
+  @override
   method2() {}
+
+  @override
   method5() {}
+
+  @override
   get getter => 42;
+
+  @override
   set setter(_) {}
 }
 
@@ -134,12 +166,15 @@
 /*element: P.:invoke*/
 class P implements O {
   /*element: P.method1:invoke*/
+  @override
   method1() {}
 
   /*element: P.getter:read*/
+  @override
   get getter => 42;
 
   /*element: P.setter=:write*/
+  @override
   set setter(_) {}
 }
 
@@ -165,7 +200,7 @@
 
 /*element: Class2.:invoke*/
 class Class2 {
-  /*element: Class2.c:init,read*/
+  /*element: Class2.c:init,invoke,read=static*/
   Class1a c;
 }
 
diff --git a/tests/compiler/dart2js/member_usage/data/super.dart b/tests/compiler/dart2js/member_usage/data/super.dart
new file mode 100644
index 0000000..5b3b775
--- /dev/null
+++ b/tests/compiler/dart2js/member_usage/data/super.dart
@@ -0,0 +1,122 @@
+// Copyright (c) 2019, 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.
+
+class Super {
+  /*element: Super.field1:init,read=super*/
+  var field1;
+
+  /*element: Super.field2:init,write=super*/
+  var field2;
+
+  /*element: Super.field3:init,read=super*/
+  var field3;
+
+  /*element: Super.field4:init,read=super*/
+  final field4;
+
+  /*element: Super.field5:init,read=super*/
+  final field5;
+
+  /*element: Super.constructor1:invoke*/
+  Super.constructor1(this.field4, this.field5);
+
+  /*element: Super.constructor2:invoke=(0)*/
+  Super.constructor2([this.field4, this.field5]);
+
+  /*element: Super.constructor3:invoke=(1)*/
+  Super.constructor3([this.field4, this.field5]);
+
+  /*element: Super.method1:invoke=(1):super*/
+  method1([a, b]) {}
+
+  /*element: Super.method2:invoke,read=super*/
+  method2([a, b]) {}
+
+  /*element: Super.getter1:read=super*/
+  get getter1 => null;
+
+  /*element: Super.getter2:read=super*/
+  get getter2 => null;
+
+  /*element: Super.setter1=:write=super*/
+  set setter1(_) {}
+
+  /*element: Super.call:invoke=(0,a,b,c)*/
+  void call({a, b, c, d}) {}
+}
+
+class Sub extends Super {
+  /*element: Sub.constructor1:invoke=(1)*/
+  Sub.constructor1([field4, field5]) : super.constructor1(field4, field5);
+
+  /*element: Sub.constructor2:invoke*/
+  Sub.constructor2() : super.constructor2();
+
+  /*element: Sub.readSuperField:invoke*/
+  readSuperField() {
+    return super.field1;
+  }
+
+  /*element: Sub.writeSuperField:invoke*/
+  writeSuperField() {
+    super.field2 = null;
+  }
+
+  /*element: Sub.invokeSuperField:invoke*/
+  invokeSuperField() {
+    super.field3(a: 0);
+  }
+
+  /*element: Sub.readSuperFinalField:invoke*/
+  readSuperFinalField() {
+    return super.field4;
+  }
+
+  /*element: Sub.invokeSuperFinalField:invoke*/
+  invokeSuperFinalField() {
+    super.field5(b: 0);
+  }
+
+  /*element: Sub.invokeSuperMethod:invoke*/
+  invokeSuperMethod() {
+    super.method1(0);
+  }
+
+  /*element: Sub.readSuperMethod:invoke*/
+  readSuperMethod() {
+    return super.method2;
+  }
+
+  /*element: Sub.readSuperGetter:invoke*/
+  readSuperGetter() {
+    return super.getter1;
+  }
+
+  /*element: Sub.invokeSuperGetter:invoke*/
+  invokeSuperGetter() {
+    return super.getter2(c: 0);
+  }
+
+  /*element: Sub.writeSuperSetter:invoke*/
+  writeSuperSetter() {
+    super.setter1 = null;
+  }
+}
+
+/*element: main:invoke*/
+void main() {
+  new Super.constructor3(null);
+  new Sub.constructor1(null);
+  new Sub.constructor2()
+    ..readSuperField()
+    ..writeSuperField()
+    ..invokeSuperField()
+    ..readSuperFinalField()
+    ..invokeSuperFinalField()
+    ..invokeSuperMethod()
+    ..readSuperMethod()
+    ..readSuperGetter()
+    ..invokeSuperGetter()
+    ..writeSuperSetter();
+}
diff --git a/tests/compiler/dart2js/member_usage/member_usage_test.dart b/tests/compiler/dart2js/member_usage/member_usage_test.dart
index 9767dc5..4e5a2c0 100644
--- a/tests/compiler/dart2js/member_usage/member_usage_test.dart
+++ b/tests/compiler/dart2js/member_usage/member_usage_test.dart
@@ -11,6 +11,7 @@
 import 'package:compiler/src/kernel/kernel_strategy.dart';
 import 'package:compiler/src/universe/member_usage.dart';
 import 'package:compiler/src/universe/resolution_world_builder.dart';
+import 'package:compiler/src/util/enumset.dart';
 import 'package:compiler/src/util/features.dart';
 import 'package:kernel/ast.dart' as ir;
 import '../equivalence/id_equivalence.dart';
@@ -23,18 +24,12 @@
     print(' Test with enqueuer checks');
     print('------------------------------------------------------------------');
     await checkTests(dataDir, const ClosedWorldDataComputer(false),
-        args: args,
-        testOmit: false,
-        testFrontend: true,
-        testCFEConstants: true);
+        args: args, testOmit: false, testCFEConstants: true);
     print('------------------------------------------------------------------');
     print(' Test without enqueuer checks');
     print('------------------------------------------------------------------');
     await checkTests(dataDir, const ClosedWorldDataComputer(true),
-        args: args,
-        testOmit: false,
-        testFrontend: true,
-        testCFEConstants: true);
+        args: args, testOmit: false, testCFEConstants: true);
   });
 }
 
@@ -55,6 +50,31 @@
     Enqueuer.skipEnqueuerCheckForTesting = skipEnqueuerCheck;
   }
 
+  /// Compute a short textual representation of [access] on member.
+  ///
+  /// Dynamic access on instance members and static access on non-instance
+  /// members is implicit, so we only annotate super access and static access
+  /// not implied by dynamic or super access.
+  String computeAccessText(MemberEntity member, EnumSet<Access> access,
+      [String prefix]) {
+    StringBuffer sb = new StringBuffer();
+    String delimiter = '';
+    if (prefix != null) {
+      sb.write(prefix);
+      delimiter = ':';
+    }
+    if (access.contains(Access.superAccess)) {
+      sb.write(delimiter);
+      sb.write('super');
+    } else if (member.isInstanceMember &&
+        access.contains(Access.staticAccess) &&
+        !access.contains(Access.dynamicAccess)) {
+      sb.write(delimiter);
+      sb.write('static');
+    }
+    return sb.toString();
+  }
+
   @override
   void computeMemberData(Compiler compiler, MemberEntity member,
       Map<Id, ActualData<Features>> actualMap,
@@ -71,15 +91,20 @@
         features.add(Tags.init);
       }
       if (memberUsage.hasRead) {
-        features.add(Tags.read);
+        features[Tags.read] = computeAccessText(member, memberUsage.reads);
       }
       if (memberUsage.hasWrite) {
-        features.add(Tags.write);
+        features[Tags.write] = computeAccessText(member, memberUsage.writes);
       }
-      if (memberUsage.isFullyInvoked) {
-        features.add(Tags.invoke);
-      } else if (memberUsage.hasInvoke) {
-        features[Tags.invoke] = memberUsage.invokedParameters.shortText;
+      if (memberUsage.hasInvoke) {
+        if (memberUsage is MethodUsage &&
+            !memberUsage.parameterUsage.isFullyUsed) {
+          features[Tags.invoke] = computeAccessText(member, memberUsage.invokes,
+              memberUsage.invokedParameters.shortText);
+        } else {
+          features[Tags.invoke] =
+              computeAccessText(member, memberUsage.invokes);
+        }
       }
     }
     Id id = computeEntityId(node);
@@ -88,6 +113,9 @@
   }
 
   @override
+  bool get testFrontend => true;
+
+  @override
   DataInterpreter<Features> get dataValidator =>
       const FeaturesDataInterpreter();
 }
diff --git a/tests/compiler/dart2js/model/cfe_annotations_test.dart b/tests/compiler/dart2js/model/cfe_annotations_test.dart
index d1ea655..d5b0e0f 100644
--- a/tests/compiler/dart2js/model/cfe_annotations_test.dart
+++ b/tests/compiler/dart2js/model/cfe_annotations_test.dart
@@ -36,7 +36,7 @@
 @noInline
 method2() {}
 
-@pragma('dart2js:tryInline')
+@pragma(const String.fromEnvironment('foo', defaultValue: 'dart2js:tryInline'))
 method3() {}
 
 @tryInline
diff --git a/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart b/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart
index 52f93c0..e75c916 100644
--- a/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart
+++ b/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart
@@ -470,6 +470,30 @@
     const ConstantData(
         'const Class9()', 'ConstructedConstant(Class9(field=IntConstant(0)))'),
   ]),
+  const TestData('type-variables', '''
+class A {
+  const A();
+}
+
+class C1<T> {
+  final T a;
+  const C1(dynamic t) : a = t; // adds implicit cast `as T`
+}
+
+T id<T>(T t) => t;
+
+class C2<T> {
+  final T Function(T) a;
+  const C2(dynamic t) : a = id; // implicit partial instantiation
+}
+''', const <ConstantData>[
+    const ConstantData('const C1<A>(const A())',
+        'ConstructedConstant(C1<A>(a=ConstructedConstant(A())))'),
+    const ConstantData(
+        'const C2<A>(id)',
+        'ConstructedConstant(C2<A>(a='
+            'InstantiationConstant([A],FunctionConstant(id))))'),
+  ])
 ];
 
 main(List<String> args) {
@@ -509,6 +533,7 @@
       'main.dart': source
     }, options: [
       Flags.enableAsserts,
+      '${Flags.enableLanguageExperiments}=constant-update-2018',
     ]);
     Compiler compiler = result.compiler;
     KernelFrontEndStrategy frontEndStrategy = compiler.frontendStrategy;
diff --git a/tests/compiler/dart2js/model/class_set_test.dart b/tests/compiler/dart2js/model/class_set_test.dart
index 5ceb1e8..ea78222 100644
--- a/tests/compiler/dart2js/model/class_set_test.dart
+++ b/tests/compiler/dart2js/model/class_set_test.dart
@@ -344,6 +344,7 @@
     List<ClassEntity> visited = <ClassEntity>[];
     classSet.forEachSubclass((cls) {
       visited.add(cls);
+      return IterationStep.CONTINUE;
     }, ClassHierarchyNode.ALL);
 
     Expect.listEquals(
@@ -381,6 +382,7 @@
     List<ClassEntity> visited = <ClassEntity>[];
     classSet.forEachSubtype((cls) {
       visited.add(cls);
+      return IterationStep.CONTINUE;
     }, ClassHierarchyNode.ALL);
 
     Expect.listEquals(
diff --git a/tests/compiler/dart2js/model/enqueuer_test.dart b/tests/compiler/dart2js/model/enqueuer_test.dart
index 3417206..e792a10 100644
--- a/tests/compiler/dart2js/model/enqueuer_test.dart
+++ b/tests/compiler/dart2js/model/enqueuer_test.dart
@@ -195,8 +195,8 @@
         new Name(methodName, elementEnvironment.mainLibrary),
         CallStructure.NO_ARGS);
     WorldImpact impact = new WorldImpactBuilderImpl()
-      ..registerDynamicUse(new ConstrainedDynamicUse(
-          selector, createConstraint(cls), const <DartType>[]));
+      ..registerDynamicUse(
+          new DynamicUse(selector, createConstraint(cls), const <DartType>[]));
     enqueuer.applyImpact(impact);
   }
 
diff --git a/tests/compiler/dart2js/model/future_or_test.dart b/tests/compiler/dart2js/model/future_or_test.dart
index cbb513c..3e9573c 100644
--- a/tests/compiler/dart2js/model/future_or_test.dart
+++ b/tests/compiler/dart2js/model/future_or_test.dart
@@ -59,7 +59,7 @@
           expectedType,
           '${type}',
           "Unexpected type for $name"
-          "${cls != null ? ' in class $cls' : ''}.");
+              "${cls != null ? ' in class $cls' : ''}.");
       return type;
     }
 
@@ -73,7 +73,7 @@
           expectedType,
           '${returnType}',
           "Unexpected return type for $name"
-          "${cls != null ? ' in class $cls' : ''}.");
+              "${cls != null ? ' in class $cls' : ''}.");
       return returnType;
     }
 
diff --git a/tests/compiler/dart2js/model/receiver_type_test.dart b/tests/compiler/dart2js/model/receiver_type_test.dart
index 663c6e3..3ad5042 100644
--- a/tests/compiler/dart2js/model/receiver_type_test.dart
+++ b/tests/compiler/dart2js/model/receiver_type_test.dart
@@ -6,6 +6,7 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/inferrer/typemasks/masks.dart';
+import 'package:compiler/src/universe/class_set.dart';
 import 'package:compiler/src/universe/selector.dart';
 import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
@@ -49,7 +50,8 @@
   Selector callSelector = new Selector.callClosure(0);
   closedWorld.classHierarchy.forEachStrictSubclassOf(
       closedWorld.commonElements.objectClass, (ClassEntity cls) {
-    if (cls.library.canonicalUri.scheme != 'memory') return;
+    if (cls.library.canonicalUri.scheme != 'memory')
+      return IterationStep.CONTINUE;
 
     TypeMask mask = new TypeMask.nonNullSubclass(cls, closedWorld);
     TypeMask receiverType = closedWorld.computeReceiverType(callSelector, mask);
@@ -65,6 +67,7 @@
       Expect.equals(expected, '$receiverType',
           "Unexpected receiver type for $callSelector on $mask");
     }
+    return IterationStep.CONTINUE;
   });
 
   Expect.equals(2, closureCount);
diff --git a/tests/compiler/dart2js/model/uri_extras_test.dart b/tests/compiler/dart2js/model/uri_extras_test.dart
index b53db4b..7a500f1 100644
--- a/tests/compiler/dart2js/model/uri_extras_test.dart
+++ b/tests/compiler/dart2js/model/uri_extras_test.dart
@@ -51,7 +51,7 @@
       '../sdk/lib/_internal/compiler/implementation/dart2js.dart',
       '///C:/Users/person/dart_checkout_for_stuff/dart/ReleaseIA32/dart.exe',
       '///c:/Users/person/dart_checkout_for_stuff/dart/sdk/lib/_internal/compiler/'
-      'implementation/dart2js.dart',
+          'implementation/dart2js.dart',
       true);
 
   c('/Users/person/file.dart', '/users/person/', '/Users/person/file.dart',
diff --git a/tests/compiler/dart2js/model/world_test.dart b/tests/compiler/dart2js/model/world_test.dart
index c49ff3d..b2106a8 100644
--- a/tests/compiler/dart2js/model/world_test.dart
+++ b/tests/compiler/dart2js/model/world_test.dart
@@ -99,6 +99,7 @@
       List<ClassEntity> visited = <ClassEntity>[];
       forEach(cls, (ClassEntity c) {
         visited.add(c);
+        return IterationStep.CONTINUE;
       });
       checkClasses('forEach($property)', cls, visited, expectedClasses,
           exact: exact);
@@ -424,6 +425,7 @@
       if (allClasses.contains(other)) {
         strictSubclasses.add(other);
       }
+      return IterationStep.CONTINUE;
     });
     Expect.setEquals(subclasses, strictSubclasses,
         "Unexpected strict subclasses of $cls: ${strictSubclasses}.");
@@ -433,6 +435,7 @@
       if (allClasses.contains(other)) {
         strictSubtypes.add(other);
       }
+      return IterationStep.CONTINUE;
     });
     Expect.setEquals(subtypes, strictSubtypes,
         "Unexpected strict subtypes of $cls: $strictSubtypes.");
diff --git a/tests/compiler/dart2js/optimization/data/arithmetic.dart b/tests/compiler/dart2js/optimization/data/arithmetic.dart
index f8aad1b..3ec5b39 100644
--- a/tests/compiler/dart2js/optimization/data/arithmetic.dart
+++ b/tests/compiler/dart2js/optimization/data/arithmetic.dart
@@ -118,19 +118,19 @@
 // Negation
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: negate:Specializer=[Negate],TypeConversion=[]*/
+/*element: negate:Specializer=[Negate],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 negate(o) {
   return -o;
 }
 
-/*element: negateNum:Specializer=[Negate],TypeConversion=[]*/
+/*element: negateNum:Specializer=[Negate],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 negateNum(o) {
   return -o;
 }
 
-/*element: negateNull:Specializer=[Negate],TypeConversion=[kind=receiver&type=num]*/
+/*element: negateNull:Specializer=[Negate],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 negateNull(o) {
   return -o;
@@ -146,37 +146,37 @@
 // Addition
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: add:Specializer=[Add],TypeConversion=[]*/
+/*element: add:Specializer=[Add],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 add(a, b) {
   return a + b;
 }
 
-/*element: addNumInt:Specializer=[Add],TypeConversion=[]*/
+/*element: addNumInt:Specializer=[Add],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 addNumInt(a, b) {
   return a + b;
 }
 
-/*element: addIntNum:Specializer=[Add],TypeConversion=[]*/
+/*element: addIntNum:Specializer=[Add],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 addIntNum(a, b) {
   return a + b;
 }
 
-/*element: addNumNum:Specializer=[Add],TypeConversion=[]*/
+/*element: addNumNum:Specializer=[Add],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 addNumNum(a, b) {
   return a + b;
 }
 
-/*element: addNullInt:Specializer=[Add],TypeConversion=[kind=receiver&type=num]*/
+/*element: addNullInt:Specializer=[Add],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 addNullInt(a, b) {
   return a + b;
 }
 
-/*element: addIntNull:Specializer=[Add],TypeConversion=[kind=argument&type=num]*/
+/*element: addIntNull:Specializer=[Add],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 addIntNull(a, b) {
   return a + b;
@@ -188,7 +188,7 @@
   return a + b;
 }
 
-/*element: addIntString:Specializer=[Add],TypeConversion=[kind=argument&type=num]*/
+/*element: addIntString:Specializer=[Add],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 addIntString(a, b) {
   return a + b;
@@ -198,49 +198,49 @@
 // Subtraction
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: subtract:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtract:Specializer=[Subtract],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 subtract(a, b) {
   return a - b;
 }
 
-/*element: subtractNumInt:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtractNumInt:Specializer=[Subtract],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 subtractNumInt(a, b) {
   return a - b;
 }
 
-/*element: subtractIntNum:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtractIntNum:Specializer=[Subtract],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 subtractIntNum(a, b) {
   return a - b;
 }
 
-/*element: subtractNumNum:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtractNumNum:Specializer=[Subtract],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 subtractNumNum(a, b) {
   return a - b;
 }
 
-/*element: subtractNullInt:Specializer=[Subtract],TypeConversion=[kind=receiver&type=num]*/
+/*element: subtractNullInt:Specializer=[Subtract],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 subtractNullInt(a, b) {
   return a - b;
 }
 
-/*element: subtractIntNull:Specializer=[Subtract],TypeConversion=[kind=argument&type=num]*/
+/*element: subtractIntNull:Specializer=[Subtract],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 subtractIntNull(a, b) {
   return a - b;
 }
 
-/*element: subtractStringInt:Specializer=[Subtract],TypeConversion=[kind=receiver&type=num]*/
+/*element: subtractStringInt:Specializer=[Subtract],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 subtractStringInt(a, b) {
   return a - b;
 }
 
-/*element: subtractIntString:Specializer=[Subtract],TypeConversion=[kind=argument&type=num]*/
+/*element: subtractIntString:Specializer=[Subtract],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 subtractIntString(a, b) {
   return a - b;
@@ -250,37 +250,37 @@
 // Multiplication
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: multiply:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiply:Specializer=[Multiply],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 multiply(a, b) {
   return a * b;
 }
 
-/*element: multiplyNumInt:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiplyNumInt:Specializer=[Multiply],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 multiplyNumInt(a, b) {
   return a * b;
 }
 
-/*element: multiplyIntNum:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiplyIntNum:Specializer=[Multiply],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 multiplyIntNum(a, b) {
   return a * b;
 }
 
-/*element: multiplyNumNum:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiplyNumNum:Specializer=[Multiply],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 multiplyNumNum(a, b) {
   return a * b;
 }
 
-/*element: multiplyNullInt:Specializer=[Multiply],TypeConversion=[kind=receiver&type=num]*/
+/*element: multiplyNullInt:Specializer=[Multiply],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 multiplyNullInt(a, b) {
   return a * b;
 }
 
-/*element: multiplyIntNull:Specializer=[Multiply],TypeConversion=[kind=argument&type=num]*/
+/*element: multiplyIntNull:Specializer=[Multiply],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 multiplyIntNull(a, b) {
   return a * b;
@@ -292,7 +292,7 @@
   return a * b;
 }
 
-/*element: multiplyIntString:Specializer=[Multiply],TypeConversion=[kind=argument&type=num]*/
+/*element: multiplyIntString:Specializer=[Multiply],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 multiplyIntString(a, b) {
   return a * b;
@@ -302,55 +302,55 @@
 // Division
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: divide:Specializer=[Divide],TypeConversion=[]*/
+/*element: divide:Specializer=[Divide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 divide(a, b) {
   return a / b;
 }
 
-/*element: divideZero:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideZero:Specializer=[Divide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 divideZero(a) {
   return a / 0;
 }
 
-/*element: divideNumInt:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideNumInt:Specializer=[Divide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 divideNumInt(a, b) {
   return a / b;
 }
 
-/*element: divideIntNum:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideIntNum:Specializer=[Divide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 divideIntNum(a, b) {
   return a / b;
 }
 
-/*element: divideNumNum:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideNumNum:Specializer=[Divide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 divideNumNum(a, b) {
   return a / b;
 }
 
-/*element: divideNullInt:Specializer=[Divide],TypeConversion=[kind=receiver&type=num]*/
+/*element: divideNullInt:Specializer=[Divide],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 divideNullInt(a, b) {
   return a / b;
 }
 
-/*element: divideIntNull:Specializer=[Divide],TypeConversion=[kind=argument&type=num]*/
+/*element: divideIntNull:Specializer=[Divide],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 divideIntNull(a, b) {
   return a / b;
 }
 
-/*element: divideStringInt:Specializer=[Divide],TypeConversion=[kind=receiver&type=num]*/
+/*element: divideStringInt:Specializer=[Divide],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 divideStringInt(a, b) {
   return a / b;
 }
 
-/*element: divideIntString:Specializer=[Divide],TypeConversion=[kind=argument&type=num]*/
+/*element: divideIntString:Specializer=[Divide],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 divideIntString(a, b) {
   return a / b;
@@ -360,7 +360,7 @@
 // Truncating division
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: truncatingDivide:Specializer=[TruncatingDivide],TypeConversion=[]*/
+/*element: truncatingDivide:Specializer=[TruncatingDivide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 truncatingDivide(a, b) {
   return a ~/ 2;
@@ -372,13 +372,13 @@
   return a ~/ 0;
 }
 
-/*element: truncatingDivideIntNonZero1:Specializer=[TruncatingDivide],TypeConversion=[]*/
+/*element: truncatingDivideIntNonZero1:Specializer=[TruncatingDivide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 truncatingDivideIntNonZero1(a) {
   return a ~/ 1;
 }
 
-/*element: truncatingDivideIntNonZero2:Specializer=[TruncatingDivide],TypeConversion=[]*/
+/*element: truncatingDivideIntNonZero2:Specializer=[TruncatingDivide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 truncatingDivideIntNonZero2(a) {
   return a ~/ 2;
@@ -390,7 +390,7 @@
   return a ~/ b;
 }
 
-/*element: truncatingDivideNumNonZero:Specializer=[TruncatingDivide._tdivFast],TypeConversion=[]*/
+/*element: truncatingDivideNumNonZero:Specializer=[TruncatingDivide._tdivFast],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 truncatingDivideNumNonZero(a) {
   return a ~/ 2;
@@ -408,25 +408,25 @@
   return a ~/ b;
 }
 
-/*element: truncatingDivideNullInt:Specializer=[!TruncatingDivide],TypeConversion=[kind=receiver&type=num]*/
+/*element: truncatingDivideNullInt:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 truncatingDivideNullInt(a, b) {
   return a ~/ b;
 }
 
-/*element: truncatingDivideIntNull:Specializer=[!TruncatingDivide],TypeConversion=[kind=argument&type=num]*/
+/*element: truncatingDivideIntNull:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 truncatingDivideIntNull(a, b) {
   return a ~/ b;
 }
 
-/*element: truncatingDivideStringInt:Specializer=[!TruncatingDivide],TypeConversion=[kind=receiver&type=num]*/
+/*element: truncatingDivideStringInt:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 truncatingDivideStringInt(a, b) {
   return a ~/ b;
 }
 
-/*element: truncatingDivideIntString:Specializer=[!TruncatingDivide],TypeConversion=[kind=argument&type=num]*/
+/*element: truncatingDivideIntString:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 truncatingDivideIntString(a, b) {
   return a ~/ b;
diff --git a/tests/compiler/dart2js/optimization/data/bit.dart b/tests/compiler/dart2js/optimization/data/bit.dart
index 51e3741..543a87d 100644
--- a/tests/compiler/dart2js/optimization/data/bit.dart
+++ b/tests/compiler/dart2js/optimization/data/bit.dart
@@ -92,49 +92,49 @@
 // Bitwise and
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: bitAnd:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAnd:Specializer=[BitAnd],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitAnd(a, b) {
   return a & b;
 }
 
-/*element: bitAndNumInt:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAndNumInt:Specializer=[BitAnd],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitAndNumInt(a, b) {
   return a & b;
 }
 
-/*element: bitAndIntNum:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAndIntNum:Specializer=[BitAnd],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitAndIntNum(a, b) {
   return a & b;
 }
 
-/*element: bitAndNumNum:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAndNumNum:Specializer=[BitAnd],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitAndNumNum(a, b) {
   return a & b;
 }
 
-/*element: bitAndNullInt:Specializer=[BitAnd],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitAndNullInt:Specializer=[BitAnd],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitAndNullInt(a, b) {
   return a & b;
 }
 
-/*element: bitAndIntNull:Specializer=[BitAnd],TypeConversion=[kind=argument&type=num]*/
+/*element: bitAndIntNull:Specializer=[BitAnd],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitAndIntNull(a, b) {
   return a & b;
 }
 
-/*element: bitAndStringInt:Specializer=[BitAnd],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitAndStringInt:Specializer=[BitAnd],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitAndStringInt(a, b) {
   return a & b;
 }
 
-/*element: bitAndIntString:Specializer=[BitAnd],TypeConversion=[kind=argument&type=num]*/
+/*element: bitAndIntString:Specializer=[BitAnd],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitAndIntString(a, b) {
   return a & b;
@@ -144,49 +144,49 @@
 // Bitwise or
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: bitOr:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOr:Specializer=[BitOr],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitOr(a, b) {
   return a | b;
 }
 
-/*element: bitOrNumInt:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOrNumInt:Specializer=[BitOr],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitOrNumInt(a, b) {
   return a | b;
 }
 
-/*element: bitOrIntNum:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOrIntNum:Specializer=[BitOr],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitOrIntNum(a, b) {
   return a | b;
 }
 
-/*element: bitOrNumNum:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOrNumNum:Specializer=[BitOr],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitOrNumNum(a, b) {
   return a | b;
 }
 
-/*element: bitOrNullInt:Specializer=[BitOr],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitOrNullInt:Specializer=[BitOr],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitOrNullInt(a, b) {
   return a | b;
 }
 
-/*element: bitOrIntNull:Specializer=[BitOr],TypeConversion=[kind=argument&type=num]*/
+/*element: bitOrIntNull:Specializer=[BitOr],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitOrIntNull(a, b) {
   return a | b;
 }
 
-/*element: bitOrStringInt:Specializer=[BitOr],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitOrStringInt:Specializer=[BitOr],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitOrStringInt(a, b) {
   return a | b;
 }
 
-/*element: bitOrIntString:Specializer=[BitOr],TypeConversion=[kind=argument&type=num]*/
+/*element: bitOrIntString:Specializer=[BitOr],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitOrIntString(a, b) {
   return a | b;
@@ -196,49 +196,49 @@
 // Bitwise xor
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: bitXor:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXor:Specializer=[BitXor],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitXor(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorNumInt:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXorNumInt:Specializer=[BitXor],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitXorNumInt(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorIntNum:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXorIntNum:Specializer=[BitXor],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitXorIntNum(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorNumNum:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXorNumNum:Specializer=[BitXor],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitXorNumNum(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorNullInt:Specializer=[BitXor],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitXorNullInt:Specializer=[BitXor],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitXorNullInt(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorIntNull:Specializer=[BitXor],TypeConversion=[kind=argument&type=num]*/
+/*element: bitXorIntNull:Specializer=[BitXor],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitXorIntNull(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorStringInt:Specializer=[BitXor],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitXorStringInt:Specializer=[BitXor],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitXorStringInt(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorIntString:Specializer=[BitXor],TypeConversion=[kind=argument&type=num]*/
+/*element: bitXorIntString:Specializer=[BitXor],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitXorIntString(a, b) {
   return a ^ b;
diff --git a/tests/compiler/dart2js/rti/data/generic_methods_dynamic_05.dart b/tests/compiler/dart2js/rti/data/generic_methods_dynamic_05.dart
index dcd1539..142ac30 100644
--- a/tests/compiler/dart2js/rti/data/generic_methods_dynamic_05.dart
+++ b/tests/compiler/dart2js/rti/data/generic_methods_dynamic_05.dart
@@ -5,7 +5,7 @@
 // Test derived from language_2/generic_methods_dynamic_test/05
 
 /*omit.class: global#JSArray:deps=[List],explicit=[JSArray],needsArgs*/
-/*strong.class: global#JSArray:deps=[ArrayIterator,List],direct,explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],needsArgs*/
+/*strong.class: global#JSArray:deps=[ArrayIterator,List],explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],indirect,needsArgs*/
 
 /*omit.class: global#List:deps=[C.bar],explicit=[List,List<B>],needsArgs*/
 /*strong.class: global#List:deps=[C.bar],explicit=[List,List<B>,List<String>],indirect,needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/local_function_list_literal.dart b/tests/compiler/dart2js/rti/data/local_function_list_literal.dart
index 7cbb508..aa06e82 100644
--- a/tests/compiler/dart2js/rti/data/local_function_list_literal.dart
+++ b/tests/compiler/dart2js/rti/data/local_function_list_literal.dart
@@ -4,7 +4,7 @@
 
 import 'package:expect/expect.dart';
 
-/*strong.class: global#JSArray:deps=[ArrayIterator,List],direct,explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],needsArgs*/
+/*strong.class: global#JSArray:deps=[ArrayIterator,List],explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],indirect,needsArgs*/
 /*omit.class: global#JSArray:deps=[List],explicit=[JSArray],needsArgs*/
 
 /*strong.element: method:implicit=[method.T],indirect,needsArgs*/
diff --git a/tests/compiler/dart2js/rti/factory_call_test.dart b/tests/compiler/dart2js/rti/factory_call_test.dart
index 5526cc0..392c989 100644
--- a/tests/compiler/dart2js/rti/factory_call_test.dart
+++ b/tests/compiler/dart2js/rti/factory_call_test.dart
@@ -46,7 +46,7 @@
     ProgramLookup programLookup = new ProgramLookup(compiler);
 
     js.Name getName(String name) {
-      return compiler.backend.namer
+      return compiler.backend.namerForTesting
           .globalPropertyNameForMember(lookupMember(elementEnvironment, name));
     }
 
@@ -81,14 +81,17 @@
       js.Name selector = getName(targetName);
       bool callFound = false;
       forEachNode(fun, onCall: (js.Call node) {
-        js.Expression target = node.target;
-        if (target is js.PropertyAccess && target.selector == selector) {
-          callFound = true;
-          Expect.equals(
-              expectedTypeArguments,
-              node.arguments.length,
-              "Unexpected argument count in $function call to $targetName: "
-              "${js.nodeToString(fun)}");
+        js.Expression target = js.undefer(node.target);
+        if (target is js.PropertyAccess) {
+          js.Node targetSelector = js.undefer(target.selector);
+          if (targetSelector is js.Name && targetSelector.key == selector.key) {
+            callFound = true;
+            Expect.equals(
+                expectedTypeArguments,
+                node.arguments.length,
+                "Unexpected argument count in $function call to $targetName: "
+                "${js.nodeToString(fun)}");
+          }
         }
       });
       Expect.isTrue(
diff --git a/tests/compiler/dart2js/rti/instance_call_test.dart b/tests/compiler/dart2js/rti/instance_call_test.dart
index 3b0c102..cdbbf3e 100644
--- a/tests/compiler/dart2js/rti/instance_call_test.dart
+++ b/tests/compiler/dart2js/rti/instance_call_test.dart
@@ -107,7 +107,7 @@
     ProgramLookup programLookup = new ProgramLookup(compiler);
 
     js.Name getName(String name, int typeArguments) {
-      return compiler.backend.namer.invocationName(new Selector.call(
+      return compiler.backend.namerForTesting.invocationName(new Selector.call(
           new PublicName(name),
           new CallStructure(1, const <String>[], typeArguments)));
     }
@@ -151,14 +151,17 @@
       js.Name selector = getName(targetName, expectedTypeArguments);
       bool callFound = false;
       forEachNode(fun, onCall: (js.Call node) {
-        js.Expression target = node.target;
-        if (target is js.PropertyAccess && target.selector == selector) {
-          callFound = true;
-          Expect.equals(
-              1 + expectedTypeArguments,
-              node.arguments.length,
-              "Unexpected argument count in $function call to $targetName: "
-              "${js.nodeToString(fun)}");
+        js.Expression target = js.undefer(node.target);
+        if (target is js.PropertyAccess) {
+          js.Node targetSelector = js.undefer(target.selector);
+          if (targetSelector is js.Name && targetSelector.key == selector.key) {
+            callFound = true;
+            Expect.equals(
+                1 + expectedTypeArguments,
+                node.arguments.length,
+                "Unexpected argument count in $function call to $targetName: "
+                "${js.nodeToString(fun)}");
+          }
         }
       });
       Expect.isTrue(callFound,
diff --git a/tests/compiler/dart2js/rti/type_representation_test.dart b/tests/compiler/dart2js/rti/type_representation_test.dart
index d93fab1..0729ef9 100644
--- a/tests/compiler/dart2js/rti/type_representation_test.dart
+++ b/tests/compiler/dart2js/rti/type_representation_test.dart
@@ -14,7 +14,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_backend/backend.dart' show JavaScriptBackend;
 import 'package:compiler/src/js_backend/runtime_types.dart'
-    show TypeRepresentationGenerator;
+    show RuntimeTypeTags, TypeRepresentationGenerator;
 import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
 import '../helpers/element_lookup.dart';
@@ -67,9 +67,10 @@
   Compiler compiler = result.compiler;
   JavaScriptBackend backend = compiler.backend;
 
+  RuntimeTypeTags rtiTags = const RuntimeTypeTags();
   TypeRepresentationGenerator typeRepresentation =
       new TypeRepresentationGenerator(
-          backend.namer, compiler.backendClosedWorldForTesting.nativeData);
+          rtiTags, compiler.backendClosedWorldForTesting.nativeData);
 
   Expression onVariable(TypeVariableType _variable) {
     TypeVariableType variable = _variable;
@@ -85,12 +86,18 @@
       [String expectedTypedefRepresentation]) {
     bool encodeTypedefName = false;
     Expression expression = typeRepresentation.getTypeRepresentation(
-        backend.emitter.emitter, type, onVariable, (x) => encodeTypedefName);
+        backend.emitterTask.emitter,
+        type,
+        onVariable,
+        (x) => encodeTypedefName);
     Expect.stringEquals(expectedRepresentation, stringify(expression));
 
     encodeTypedefName = true;
     expression = typeRepresentation.getTypeRepresentation(
-        backend.emitter.emitter, type, onVariable, (x) => encodeTypedefName);
+        backend.emitterTask.emitter,
+        type,
+        onVariable,
+        (x) => encodeTypedefName);
     if (expectedTypedefRepresentation == null) {
       expectedTypedefRepresentation = expectedRepresentation;
     }
@@ -98,22 +105,22 @@
   }
 
   String getJsName(Entity cls) {
-    Expression name =
-        typeRepresentation.getJavaScriptClassName(cls, backend.emitter.emitter);
+    Expression name = typeRepresentation.getJavaScriptClassName(
+        cls, backend.emitterTask.emitter);
     return stringify(name);
   }
 
   JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
-  String func = backend.namer.functionTypeTag;
-  String ret = backend.namer.functionTypeReturnTypeTag;
+  String func = rtiTags.functionTypeTag;
+  String ret = rtiTags.functionTypeReturnTypeTag;
   String retvoid = '$ret: -1';
-  String args = backend.namer.functionTypeRequiredParametersTag;
-  String opt = backend.namer.functionTypeOptionalParametersTag;
-  String named = backend.namer.functionTypeNamedParametersTag;
-  String bounds = backend.namer.functionTypeGenericBoundsTag;
-  String futureOr = backend.namer.futureOrTag;
-  String futureOrType = backend.namer.futureOrTypeTag;
+  String args = rtiTags.functionTypeRequiredParametersTag;
+  String opt = rtiTags.functionTypeOptionalParametersTag;
+  String named = rtiTags.functionTypeNamedParametersTag;
+  String bounds = rtiTags.functionTypeGenericBoundsTag;
+  String futureOr = rtiTags.futureOrTag;
+  String futureOrType = rtiTags.futureOrTypeTag;
 
   ClassEntity List_ = findClass(closedWorld, 'List');
   TypeVariableType List_E =
@@ -199,44 +206,44 @@
   expect(
       instantiate(List_, [Typedef5_]),
       '[$List_rep, {$func: 1,'
-      ' $args: [$int_rep, $String_rep]}]',
+          ' $args: [$int_rep, $String_rep]}]',
       '[$List_rep, {$func: 1,'
-      ' $args: [$int_rep, $String_rep]$Typedef5_tag}]');
+          ' $args: [$int_rep, $String_rep]$Typedef5_tag}]');
   expect(
       instantiate(List_, [Typedef6_]),
       '[$List_rep, {$func: 1,'
-      ' $args: [$int_rep], $opt: [$String_rep]}]',
+          ' $args: [$int_rep], $opt: [$String_rep]}]',
       '[$List_rep, {$func: 1,'
-      ' $args: [$int_rep], $opt: [$String_rep]$Typedef6_tag}]');
+          ' $args: [$int_rep], $opt: [$String_rep]$Typedef6_tag}]');
   expect(
       instantiate(List_, [Typedef7_]),
       '[$List_rep, {$func: 1, $args: '
-      '[$int_rep, $String_rep], $opt: [[$List_rep, $int_rep],,]}]',
+          '[$int_rep, $String_rep], $opt: [[$List_rep, $int_rep],,]}]',
       '[$List_rep, {$func: 1, $args: '
-      '[$int_rep, $String_rep], $opt: [[$List_rep, $int_rep],,]'
-      '$Typedef7_tag}]');
+          '[$int_rep, $String_rep], $opt: [[$List_rep, $int_rep],,]'
+          '$Typedef7_tag}]');
   expect(
       instantiate(List_, [Typedef8_]),
       '[$List_rep, {$func: 1, $args: [$int_rep],'
-      ' $named: {b: $String_rep}}]',
+          ' $named: {b: $String_rep}}]',
       '[$List_rep, {$func: 1, $args: [$int_rep],'
-      ' $named: {b: $String_rep}$Typedef8_tag}]');
+          ' $named: {b: $String_rep}$Typedef8_tag}]');
   expect(
       instantiate(List_, [Typedef9_]),
       '[$List_rep, {$func: 1, '
-      '$args: [$int_rep, $String_rep], $named: '
-      '{c: [$List_rep, $int_rep], d: null}}]',
+          '$args: [$int_rep, $String_rep], $named: '
+          '{c: [$List_rep, $int_rep], d: null}}]',
       '[$List_rep, {$func: 1, '
-      '$args: [$int_rep, $String_rep], $named: {c: [$List_rep, $int_rep],'
-      ' d: null}$Typedef9_tag}]');
+          '$args: [$int_rep, $String_rep], $named: {c: [$List_rep, $int_rep],'
+          ' d: null}$Typedef9_tag}]');
   expect(
       instantiate(List_, [Typedef10_]),
       '[$List_rep, {$func: 1, '
-      '$args: [{$func: 1, $retvoid, '
-      '$args: [$int_rep], $opt: [,]}]}]',
+          '$args: [{$func: 1, $retvoid, '
+          '$args: [$int_rep], $opt: [,]}]}]',
       '[$List_rep, {$func: 1, '
-      '$args: [{$func: 1, $retvoid, '
-      '$args: [$int_rep], $opt: [,]}]$Typedef10_tag}]');
+          '$args: [{$func: 1, $retvoid, '
+          '$args: [$int_rep], $opt: [,]}]$Typedef10_tag}]');
 
   expect(
       instantiate(List_, [Typedef11_]),
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
index f38c7a6..9e4273d 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
@@ -262,6 +262,7 @@
         }
         return null;
       }
+      return null;
     });
   }
 }
diff --git a/tests/compiler/dart2js/static_type/data/assert.dart b/tests/compiler/dart2js/static_type/data/assert.dart
index 0f0057e..54f2a34 100644
--- a/tests/compiler/dart2js/static_type/data/assert.dart
+++ b/tests/compiler/dart2js/static_type/data/assert.dart
@@ -18,25 +18,25 @@
 }
 
 assert1(Class c) {
-  assert(/*Class*/ c /*invoke: bool*/ != null);
+  assert(/*Class*/ c /*invoke: [Class]->bool*/ != null);
   /*Class*/ c.next;
 }
 
 assert2(Class c) {
-  assert(/*Class*/ c /*invoke: bool*/ == null);
+  assert(/*Class*/ c /*invoke: [Class]->bool*/ == null);
   /*Class*/ c.next;
 }
 
 assert3(Class c) {
   bool b;
-  assert(/*Class*/ c /*invoke: bool*/ != null);
+  assert(/*Class*/ c /*invoke: [Class]->bool*/ != null);
   if (/*bool*/ b) return;
   /*Class*/ c.next;
 }
 
 assert4(Class c) {
   bool b;
-  assert(/*Class*/ c /*invoke: bool*/ == null);
+  assert(/*Class*/ c /*invoke: [Class]->bool*/ == null);
   if (/*bool*/ b) return;
   /*Class*/ c.next;
 }
diff --git a/tests/compiler/dart2js/static_type/data/assert_ea.dart b/tests/compiler/dart2js/static_type/data/assert_ea.dart
index 9e6edbd..c28215d 100644
--- a/tests/compiler/dart2js/static_type/data/assert_ea.dart
+++ b/tests/compiler/dart2js/static_type/data/assert_ea.dart
@@ -18,25 +18,25 @@
 }
 
 assert1(Class c) {
-  assert(/*Class*/ c /*invoke: bool*/ != null);
+  assert(/*Class*/ c /*invoke: [Class]->bool*/ != null);
   /*Class*/ c.next;
 }
 
 assert2(Class c) {
-  assert(/*Class*/ c /*invoke: bool*/ == null);
+  assert(/*Class*/ c /*invoke: [Class]->bool*/ == null);
   /*Null*/ c.next;
 }
 
 assert3(Class c) {
   bool b;
-  assert(/*Class*/ c /*invoke: bool*/ != null);
+  assert(/*Class*/ c /*invoke: [Class]->bool*/ != null);
   if (/*bool*/ b) return;
   /*Class*/ c.next;
 }
 
 assert4(Class c) {
   bool b;
-  assert(/*Class*/ c /*invoke: bool*/ == null);
+  assert(/*Class*/ c /*invoke: [Class]->bool*/ == null);
   if (/*bool*/ b) return;
   /*Null*/ c.next;
 }
diff --git a/tests/compiler/dart2js/static_type/data/cascade.dart b/tests/compiler/dart2js/static_type/data/cascade.dart
new file mode 100644
index 0000000..4f2f6a5
--- /dev/null
+++ b/tests/compiler/dart2js/static_type/data/cascade.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2018, 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() {
+  promotedCascade(null);
+}
+
+promotedCascade(dynamic value) {
+  if (/*dynamic*/ value is List<String>) {
+    value = '[${(
+        /*List<String>*/ value.. /*invoke: [List<String>]->void*/ sort()). /*invoke: [List<String>]->String*/ join(',')}]';
+  }
+  return /*dynamic*/ value;
+}
diff --git a/tests/compiler/dart2js/static_type/data/closure.dart b/tests/compiler/dart2js/static_type/data/closure.dart
index b8768de..f24f209 100644
--- a/tests/compiler/dart2js/static_type/data/closure.dart
+++ b/tests/compiler/dart2js/static_type/data/closure.dart
@@ -11,7 +11,10 @@
   closure2(null);
   closure3(null);
   closure4(null);
+  closure4a(null);
   closure5(null);
+  closure6(null);
+  closure7();
 }
 
 closure1(dynamic c) {
@@ -26,7 +29,7 @@
     }
 
     /*dynamic*/ c.next;
-    /*invoke: Null*/ local();
+    /*invoke: [Null Function()]->Null*/ local();
     /*dynamic*/ c.next;
   }
 }
@@ -39,7 +42,7 @@
     }
 
     /*Class*/ c.next;
-    /*invoke: Null*/ local();
+    /*invoke: [Null Function()]->Null*/ local();
     /*Class*/ c.next;
   }
 }
@@ -53,7 +56,7 @@
 
     c = 0;
     /*dynamic*/ c.next;
-    /*invoke: Null*/ local();
+    /*invoke: [Null Function()]->Null*/ local();
     /*dynamic*/ c.next;
   }
 }
@@ -65,8 +68,24 @@
       /*dynamic*/ c.next;
     }
 
+    /*Class*/ c.next;
+    /*invoke: [Null Function()]->Null*/ local();
+    /*Class*/ c.next;
+    c = 0;
     /*dynamic*/ c.next;
-    /*invoke: Null*/ local();
+  }
+}
+
+closure4a(dynamic c) {
+  if (/*dynamic*/ c is Class) {
+    /*Class*/ c.next;
+    local() {
+      /*dynamic*/ c.next;
+      c = 0;
+    }
+
+    /*dynamic*/ c.next;
+    /*invoke: [Null Function()]->Null*/ local();
     /*dynamic*/ c.next;
     c = 0;
     /*dynamic*/ c.next;
@@ -82,8 +101,61 @@
   }
 
   /*dynamic*/ c.next;
-  /*invoke: Null*/ local();
+  /*invoke: [Null Function()]->Null*/ local();
   /*dynamic*/ c.next;
   c = 0;
   /*dynamic*/ c.next;
 }
+
+_returnTrue(_) => true;
+
+class A {}
+
+class B extends A {
+  f() {}
+}
+
+closure6(var x) {
+  var closure;
+  /*dynamic*/ x is B &&
+      _returnTrue(
+          closure = () => /*dynamic*/ x. /*invoke: [dynamic]->dynamic*/ f());
+  /*dynamic*/ x;
+  x = new A();
+  /*dynamic*/ closure. /*invoke: [dynamic]->dynamic*/ call();
+  /*dynamic*/ x;
+}
+
+class C {}
+
+class D extends C {
+  f() {}
+}
+
+class E extends D {
+  g() {}
+}
+
+_closure7(C x) {
+  /*C*/ x is D && _returnTrue((() => /*C*/ x))
+      ? /*D*/ x. /*invoke: [D]->dynamic*/ f()
+      : x = new C();
+  _returnTrue((() => /*C*/ x)) && /*C*/ x is D
+      ? /*D*/ x. /*invoke: [D]->dynamic*/ f()
+      : x = new C();
+
+  (/*C*/ x is D && _returnTrue((() => /*C*/ x))) &&
+          (/*D*/ x is E && _returnTrue((() => /*C*/ x)))
+      ? /*E*/ x. /*invoke: [E]->dynamic*/ g()
+      : x = new C();
+
+  (_returnTrue((() => /*C*/ x)) && /*C*/ x is E) &&
+          (_returnTrue((() => /*C*/ x)) && /*E*/ x is D)
+      ? /*E*/ x. /*invoke: [E]->dynamic*/ g()
+      : x = new C();
+}
+
+closure7() {
+  _closure7(new D());
+  _closure7(new E());
+}
diff --git a/tests/compiler/dart2js/static_type/data/do.dart b/tests/compiler/dart2js/static_type/data/do.dart
index 205480d..0d0952b 100644
--- a/tests/compiler/dart2js/static_type/data/do.dart
+++ b/tests/compiler/dart2js/static_type/data/do.dart
@@ -20,7 +20,7 @@
         /*Class*/ c.next;
       }
       c = 0;
-    } while (/*dynamic*/ c /*invoke: bool*/ != null);
+    } while (/*dynamic*/ c /*invoke: [dynamic]->bool*/ != null);
     /*dynamic*/ c.next;
   }
 }
@@ -30,7 +30,7 @@
     /*Class*/ c.next;
     do {
       /*Class*/ c.next;
-    } while (/*Class*/ c /*invoke: bool*/ != null);
+    } while (/*Class*/ c /*invoke: [Class]->bool*/ != null);
     /*Class*/ c.next;
   }
 }
diff --git a/tests/compiler/dart2js/static_type/data/effectively_final.dart b/tests/compiler/dart2js/static_type/data/effectively_final.dart
index 58bd022..a50cdaf 100644
--- a/tests/compiler/dart2js/static_type/data/effectively_final.dart
+++ b/tests/compiler/dart2js/static_type/data/effectively_final.dart
@@ -11,14 +11,14 @@
 
 effectivelyFinalList() {
   dynamic c = [];
-  /*List<dynamic>*/ c. /*invoke: void*/ add(null);
-  /*List<dynamic>*/ c.length /*invoke: int*/ + 1;
+  /*List<dynamic>*/ c. /*invoke: [List<dynamic>]->void*/ add(null);
+  /*List<dynamic>*/ c.length /*invoke: [int]->int*/ + 1;
 }
 
 notEffectivelyFinalList() {
   dynamic c = [];
-  /*dynamic*/ c. /*invoke: dynamic*/ add(null);
-  /*dynamic*/ c.length /*invoke: dynamic*/ + 1;
+  /*dynamic*/ c. /*invoke: [dynamic]->dynamic*/ add(null);
+  /*dynamic*/ c.length /*invoke: [dynamic]->dynamic*/ + 1;
   c = null;
 }
 
@@ -26,9 +26,9 @@
 
 effectivelyFinalPromoted() {
   dynamic c = _method1();
-  /*num*/ c /*invoke: num*/ + 0;
+  /*num*/ c /*invoke: [num]->num*/ + 0;
   if (/*num*/ c is int) {
-    /*int*/ c /*invoke: int*/ + 1;
+    /*int*/ c /*invoke: [int]->int*/ + 1;
   }
 }
 
@@ -36,8 +36,8 @@
 
 effectivelyFinalPromotedInvalid() {
   dynamic c = _method2();
-  /*String*/ c /*invoke: String*/ + '';
+  /*String*/ c /*invoke: [String]->String*/ + '';
   if (/*String*/ c is int) {
-    /*int*/ c /*invoke: int*/ + 1;
+    /*int*/ c /*invoke: [int]->int*/ + 1;
   }
 }
diff --git a/tests/compiler/dart2js/static_type/data/for.dart b/tests/compiler/dart2js/static_type/data/for.dart
index d755de9..3d4bb82 100644
--- a/tests/compiler/dart2js/static_type/data/for.dart
+++ b/tests/compiler/dart2js/static_type/data/for.dart
@@ -17,7 +17,7 @@
   if (/*dynamic*/ c is Class) {
     /*Class*/ c.next;
     for (/*Class*/ c.next;
-        /*dynamic*/ c /*invoke: bool*/ != null;
+        /*dynamic*/ c /*invoke: [dynamic]->bool*/ != null;
         /*dynamic*/ c.next) {
       /*dynamic*/ c.next;
       if (/*dynamic*/ c is Class) {
@@ -33,7 +33,7 @@
   if (/*dynamic*/ c is Class) {
     /*Class*/ c.next;
     for (/*Class*/ c.next;
-        /*Class*/ c /*invoke: bool*/ != null;
+        /*Class*/ c /*invoke: [Class]->bool*/ != null;
         /*Class*/ c.next) {
       /*Class*/ c.next;
     }
diff --git a/tests/compiler/dart2js/static_type/data/for_in.dart b/tests/compiler/dart2js/static_type/data/for_in.dart
index 3168538..a97c74b 100644
--- a/tests/compiler/dart2js/static_type/data/for_in.dart
+++ b/tests/compiler/dart2js/static_type/data/for_in.dart
@@ -6,9 +6,17 @@
   Iterable<Class> next;
 }
 
+abstract class Class2<E> implements Iterable<E> {
+  @override
+  Iterator<E> iterator;
+}
+
 main() {
   forIn1(null);
   forIn2(null);
+  forIn3(null);
+  forIn4(null);
+  forIn5(null);
 }
 
 forIn1(dynamic c) {
@@ -36,3 +44,30 @@
     /*Class*/ c.next;
   }
 }
+
+forIn3(o) {
+  /*dynamic*/ o;
+  for (var e in /*dynamic*/ o) {
+    /*dynamic*/ e;
+    /*dynamic*/ o;
+  }
+  /*dynamic*/ o;
+}
+
+forIn4(o) {
+  /*dynamic*/ o;
+  for (int e in /*dynamic*/ o) {
+    /*int*/ e;
+    /*dynamic*/ o;
+  }
+  /*dynamic*/ o;
+}
+
+forIn5(Class2<int> o) {
+  /*Class2<int>*/ o;
+  for (var e in /*Class2<int>*/ o) {
+    /*int*/ e;
+    /*Class2<int>*/ o;
+  }
+  /*Class2<int>*/ o;
+}
diff --git a/tests/compiler/dart2js/static_type/data/generic_method.dart b/tests/compiler/dart2js/static_type/data/generic_method.dart
index 99a2f17..8026b3c 100644
--- a/tests/compiler/dart2js/static_type/data/generic_method.dart
+++ b/tests/compiler/dart2js/static_type/data/generic_method.dart
@@ -19,16 +19,16 @@
 
 genericMethod1(c) {
   if (/*dynamic*/ c is Class1) {
-    /*Class1*/ c. /*invoke: String*/ method('').length;
+    /*Class1*/ c. /*invoke: [Class1]->String*/ method('').length;
   }
 }
 
 genericMethod2(c) {
   if (/*dynamic*/ c is! Class1) return;
-  /*Class1*/ c. /*invoke: dynamic*/ method('').length;
+  /*Class1*/ c. /*invoke: [Class1]->dynamic*/ method('').length;
 }
 
 genericMethod3() {
   dynamic c = new Class2<int>();
-  /*Class2<int>*/ c. /*invoke: int*/ method();
+  /*Class2<int>*/ c. /*invoke: [Class2<int>]->int*/ method();
 }
diff --git a/tests/compiler/dart2js/static_type/data/null.dart b/tests/compiler/dart2js/static_type/data/null.dart
index c0b9386..dcbe522 100644
--- a/tests/compiler/dart2js/static_type/data/null.dart
+++ b/tests/compiler/dart2js/static_type/data/null.dart
@@ -19,46 +19,46 @@
 
 null1(dynamic c) {
   /*dynamic*/ c.next;
-  /*dynamic*/ c /*invoke: bool*/ != null;
+  /*dynamic*/ c /*invoke: [dynamic]->bool*/ != null;
   /*dynamic*/ c.next;
 }
 
 null2(dynamic c) {
   /*dynamic*/ c.next;
-  /*dynamic*/ c /*invoke: bool*/ == null;
+  /*dynamic*/ c /*invoke: [dynamic]->bool*/ == null;
   /*dynamic*/ c.next;
 }
 
 null3(dynamic c) {
-  if (/*dynamic*/ c /*invoke: bool*/ == null) return;
+  if (/*dynamic*/ c /*invoke: [dynamic]->bool*/ == null) return;
   /*dynamic*/ c.next;
 }
 
 null4(dynamic c) {
-  if (/*dynamic*/ c /*invoke: bool*/ != null) return;
+  if (/*dynamic*/ c /*invoke: [dynamic]->bool*/ != null) return;
   /*Null*/ c.next;
 }
 
 null5(dynamic c) {
-  if (/*dynamic*/ c /*invoke: bool*/ != null) {
+  if (/*dynamic*/ c /*invoke: [dynamic]->bool*/ != null) {
     /*dynamic*/ c.next;
   }
 }
 
 null6(dynamic c) {
-  if (/*dynamic*/ c /*invoke: bool*/ == null) {
+  if (/*dynamic*/ c /*invoke: [dynamic]->bool*/ == null) {
     /*Null*/ c.next;
   }
 }
 
 null7(dynamic c) {
-  while (/*dynamic*/ c /*invoke: bool*/ != null) {
+  while (/*dynamic*/ c /*invoke: [dynamic]->bool*/ != null) {
     /*dynamic*/ c.next;
   }
 }
 
 null8(dynamic c) {
-  while (/*dynamic*/ c /*invoke: bool*/ == null) {
+  while (/*dynamic*/ c /*invoke: [dynamic]->bool*/ == null) {
     /*Null*/ c.next;
   }
 }
diff --git a/tests/compiler/dart2js/static_type/data/null_access.dart b/tests/compiler/dart2js/static_type/data/null_access.dart
index de65e93..4c7735a 100644
--- a/tests/compiler/dart2js/static_type/data/null_access.dart
+++ b/tests/compiler/dart2js/static_type/data/null_access.dart
@@ -16,7 +16,7 @@
 
 test1() {
   const Class1 c = null;
-  return /*Null*/ c. /*invoke: void*/ method1();
+  return /*Null*/ c. /*invoke: [Null]->void*/ method1();
 }
 
 class Class2<T> {
@@ -28,7 +28,7 @@
 test2() {
   const Class2<int> c = null;
   // TODO(johnniwinther): Track the unreachable code properly.
-  return /*Null*/ c. /*invoke: <bottom>*/ method2();
+  return /*Null*/ c. /*invoke: [Null]-><bottom>*/ method2();
 }
 
 class Class3<T> {
@@ -40,5 +40,5 @@
 test3() {
   const Class3<int> c = null;
   // TODO(johnniwinther): Track the unreachable code properly.
-  return /*Null*/ c. /*invoke: Class3<<bottom>>*/ method3();
+  return /*Null*/ c. /*invoke: [Null]->Class3<<bottom>>*/ method3();
 }
diff --git a/tests/compiler/dart2js/static_type/data/while.dart b/tests/compiler/dart2js/static_type/data/while.dart
index e646074..b21dee0 100644
--- a/tests/compiler/dart2js/static_type/data/while.dart
+++ b/tests/compiler/dart2js/static_type/data/while.dart
@@ -16,15 +16,15 @@
   whileNext(null);
   whileNextGeneric(null);
   new Class1<int>()
-    .. /*invoke: dynamic*/ whileNext1()
-    .. /*invoke: dynamic*/ whileNext2()
-    .. /*invoke: dynamic*/ whileNext3();
+    .. /*invoke: [Class1<int>]->dynamic*/ whileNext1()
+    .. /*invoke: [Class1<int>]->dynamic*/ whileNext2()
+    .. /*invoke: [Class1<int>]->dynamic*/ whileNext3();
 }
 
 while1(dynamic c) {
   if (/*dynamic*/ c is Class) {
     /*Class*/ c.next;
-    while (/*dynamic*/ c /*invoke: bool*/ != null) {
+    while (/*dynamic*/ c /*invoke: [dynamic]->bool*/ != null) {
       /*dynamic*/ c.next;
       if (/*dynamic*/ c is Class) {
         /*Class*/ c.next;
@@ -38,7 +38,7 @@
 while2(dynamic c) {
   if (/*dynamic*/ c is Class) {
     /*Class*/ c.next;
-    while (/*Class*/ c /*invoke: bool*/ != null) {
+    while (/*Class*/ c /*invoke: [Class]->bool*/ != null) {
       /*Class*/ c.next;
     }
     /*Class*/ c.next;
@@ -46,14 +46,15 @@
 }
 
 whileNext(Class c) {
-  while (/*Class*/ c /*invoke: bool*/ != null) {
+  while (/*Class*/ c /*invoke: [Class]->bool*/ != null) {
     c = /*Class*/ c.next;
   }
   return /*Class*/ c;
 }
 
 whileNextGeneric(GenericClass<int> c) {
-  while (/*GenericClass<int>*/ c /*invoke: bool*/ != null) {
+  while (
+      /*GenericClass<int>*/ c /*invoke: [GenericClass<int>]->bool*/ != null) {
     c = /*GenericClass<int>*/ c.next;
   }
   return /*GenericClass<int>*/ c;
@@ -77,7 +78,7 @@
   whileNext2() {
     bool b;
     GenericClass<T> c;
-    while (/*GenericClass<T>*/ c /*invoke: bool*/ != null) {
+    while (/*GenericClass<T>*/ c /*invoke: [GenericClass<T>]->bool*/ != null) {
       if (/*bool*/ b) {
         GenericClass<T> next = /*GenericClass<T>*/ c.next;
         c = /*GenericClass<T>*/ next;
@@ -91,7 +92,7 @@
   whileNext3() {
     bool b;
     GenericClass<T> c;
-    while (/*GenericClass<T>*/ c /*invoke: bool*/ == null) {
+    while (/*GenericClass<T>*/ c /*invoke: [GenericClass<T>]->bool*/ == null) {
       if (/*bool*/ b) {
         GenericClass<T> next = /*Null*/ c.next;
         c = /*GenericClass<T>*/ next;
diff --git a/tests/compiler/dart2js/static_type/show.dart b/tests/compiler/dart2js/static_type/show.dart
new file mode 100644
index 0000000..59f85ee
--- /dev/null
+++ b/tests/compiler/dart2js/static_type/show.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2019, 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.
+
+/// Helper program that shows the static type data on a dart program.
+
+import 'package:args/args.dart';
+import '../equivalence/show_helper.dart';
+import 'type_promotion_test.dart';
+import 'static_type_test.dart';
+
+main(List<String> args) async {
+  ArgParser argParser = createArgParser();
+  argParser.addFlag('type-promotion', defaultsTo: false);
+  ArgResults results = argParser.parse(args);
+
+  bool showTypePromotion = results['type-promotion'];
+
+  await show(
+      results,
+      showTypePromotion
+          ? new TypePromotionDataComputer()
+          : new StaticTypeDataComputer());
+}
diff --git a/tests/compiler/dart2js/static_type/static_type_test.dart b/tests/compiler/dart2js/static_type/static_type_test.dart
index 1f935d8..369d14c 100644
--- a/tests/compiler/dart2js/static_type/static_type_test.dart
+++ b/tests/compiler/dart2js/static_type/static_type_test.dart
@@ -9,6 +9,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/ir/cached_static_type.dart';
 import 'package:compiler/src/ir/static_type_base.dart';
+import 'package:compiler/src/ir/static_type_cache.dart';
 import 'package:compiler/src/kernel/element_map_impl.dart';
 import 'package:compiler/src/kernel/kernel_strategy.dart';
 import 'package:kernel/ast.dart' as ir;
@@ -24,7 +25,7 @@
   asyncTest(() async {
     Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
     await checkTests(dataDir, new StaticTypeDataComputer(),
-        args: args, testOmit: false, testFrontend: true);
+        args: args, testOmit: false);
   });
 }
 
@@ -49,8 +50,7 @@
       {bool verbose: false}) {
     KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
     KernelToElementMapImpl elementMap = frontendStrategy.elementMap;
-    Map<ir.TreeNode, ir.DartType> staticTypeCache =
-        elementMap.getCachedStaticTypes(member);
+    StaticTypeCache staticTypeCache = elementMap.getCachedStaticTypes(member);
     ir.Member node = elementMap.getMemberNode(member);
     new StaticTypeIrComputer(
             compiler.reporter,
@@ -63,6 +63,9 @@
   }
 
   @override
+  bool get testFrontend => true;
+
+  @override
   DataInterpreter<String> get dataValidator => const StringDataInterpreter();
 }
 
@@ -81,8 +84,11 @@
 
   @override
   String computeNodeValue(Id id, ir.TreeNode node) {
-    if (node is ir.VariableGet || node is ir.MethodInvocation) {
+    if (node is ir.VariableGet) {
       return typeToText(node.accept(staticTypeCache));
+    } else if (node is ir.MethodInvocation) {
+      return '[${typeToText(node.receiver.accept(staticTypeCache))}]->'
+          '${typeToText(node.accept(staticTypeCache))}';
     }
     return null;
   }
diff --git a/tests/compiler/dart2js/static_type/type_promotion_data/closure.dart b/tests/compiler/dart2js/static_type/type_promotion_data/closure.dart
new file mode 100644
index 0000000..f50db9d
--- /dev/null
+++ b/tests/compiler/dart2js/static_type/type_promotion_data/closure.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2019, 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() {
+  closure6(null);
+  closure7();
+}
+
+class A {}
+
+class B extends A {
+  f() {}
+}
+
+_returnTrue(_) => true;
+
+closure6(var x) {
+  var closure;
+  /*{}*/ x is B && _returnTrue(closure = () => /*{}*/ x.f());
+  /*{}*/ x;
+  x = new A();
+  /*{}*/ closure();
+  /*{}*/ x;
+}
+
+class C {}
+
+class D extends C {
+  f() {}
+}
+
+class E extends D {
+  g() {}
+}
+
+_closure7(C x) {
+  /*{}*/ x is D && _returnTrue((() => /*{}*/ x)())
+      ? /*{x:[{true:D}|D]}*/ x.f()
+      : x = new C();
+  _returnTrue((() => /*{}*/ x)()) && /*{}*/ x is D
+      ? /*{x:[{true:D}|D]}*/ x.f()
+      : x = new C();
+
+  (/*{}*/ x is D && _returnTrue((() => /*{}*/ x)())) &&
+          (/*{x:[{true:D}|D]}*/ x is E && _returnTrue((() => /*{}*/ x)()))
+      ? /*{x:[{true:D,E}|D,E]}*/ x.g()
+      : x = new C();
+
+  (_returnTrue((() => /*{}*/ x)()) && /*{}*/ x is E) &&
+          (_returnTrue((() => /*{}*/ x)()) && /*{x:[{true:E}|E]}*/ x is D)
+      ? /*{x:[{true:E,D}|E,D]}*/ x.g()
+      : x = new C();
+}
+
+closure7() {
+  _closure7(new D());
+  _closure7(new E());
+}
diff --git a/tests/compiler/dart2js/static_type/type_promotion_test.dart b/tests/compiler/dart2js/static_type/type_promotion_test.dart
index 76f448f..ca9dfd4 100644
--- a/tests/compiler/dart2js/static_type/type_promotion_test.dart
+++ b/tests/compiler/dart2js/static_type/type_promotion_test.dart
@@ -23,8 +23,7 @@
   asyncTest(() async {
     Directory dataDir =
         new Directory.fromUri(Platform.script.resolve('type_promotion_data'));
-    await checkTests(dataDir, new TypePromotionDataComputer(),
-        args: args, testFrontend: true);
+    await checkTests(dataDir, new TypePromotionDataComputer(), args: args);
   });
 }
 
@@ -57,6 +56,9 @@
   }
 
   @override
+  bool get testFrontend => true;
+
+  @override
   DataInterpreter<String> get dataValidator => const StringDataInterpreter();
 }
 
diff --git a/tests/compiler/dart2js_extra/boolean_conversion_test.dart b/tests/compiler/dart2js_extra/boolean_conversion_test.dart
index 46a8994..64cd441 100644
--- a/tests/compiler/dart2js_extra/boolean_conversion_test.dart
+++ b/tests/compiler/dart2js_extra/boolean_conversion_test.dart
@@ -2,7 +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.
 
-// SharedOptions=--enable-experiment=control-flow-collections
 // dart2jsOptions=--omit-implicit-checks
 
 // Note: --omit-implicit-checks causes Expect.isNull to misbehave, so we use
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 4facaed..b1acb29 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -4,6 +4,7 @@
 
 [ $compiler == dart2js ]
 23264_test: RuntimeError
+bound_closure_interceptor_type_test: RuntimeError
 bounds_check4a_test: RuntimeError # Issue 32741
 bounds_check4b_test: RuntimeError # Issue 32741
 class_test: Fail
@@ -126,21 +127,6 @@
 type_literal_test: Fail, OK # Tests expected output of Type.toString().
 typevariable_typedef_test: Fail, OK # Tests expected output of Type.toString().
 
-[ $compiler == dart2js && $strong ]
-bound_closure_interceptor_type_test: RuntimeError
-
-[ $compiler == dart2js && !$strong ]
-extract_type_arguments_1_test: RuntimeError # Uses function type variables
-extract_type_arguments_2_test: RuntimeError # Uses function type variables
-extract_type_arguments_3_test: RuntimeError # Uses function type variables
-generic_method_dynamic_is_test: RuntimeError # Test against function type variables is only supported in strong mode.
-generic_method_dynamic_type_test: SkipByDesign # Requires strong mode support for function type variables.
-generic_method_static_is_test: RuntimeError # Test against function type variables is only supported in strong mode.
-int_index_test/01: MissingCompileTimeError
-int_index_test/02: MissingCompileTimeError
-local_signature_test: RuntimeError # Test against function type variables is only supported in strong mode.
-switch_test/00: MissingCompileTimeError
-
 [ $compiler == dart2js && ($runtime == chrome || $runtime == chromeOnAndroid || $runtime == ff || $runtime == safari) ]
 isolate2_test/01: Fail # Issue 14458.
 
diff --git a/tests/compiler/dart2js_extra/field_access_test.dart b/tests/compiler/dart2js_extra/field_access_test.dart
new file mode 100644
index 0000000..044baf4
--- /dev/null
+++ b/tests/compiler/dart2js_extra/field_access_test.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test the all variants of field/property access/update are emitted.
+//
+// This is needed because getter/setters are now registered as read from and
+// written to, respectively, instead of being invoked.
+
+var field1a;
+
+var field1b;
+
+var field1c;
+
+@pragma('dart2js:noInline')
+get field2a => 42;
+
+@pragma('dart2js:noInline')
+set field2a(_) {}
+
+@pragma('dart2js:noInline')
+get field2b => 42;
+
+@pragma('dart2js:noInline')
+set field2b(_) {}
+
+@pragma('dart2js:noInline')
+get field2c => 42;
+
+@pragma('dart2js:noInline')
+set field2c(_) {}
+
+class Class {
+  @pragma('dart2js:noElision')
+  var field1a;
+
+  var field1b;
+
+  var field1c;
+
+  @pragma('dart2js:noInline')
+  get field2a => 42;
+
+  @pragma('dart2js:noInline')
+  set field2a(_) {}
+
+  @pragma('dart2js:noInline')
+  get field2b => 42;
+
+  @pragma('dart2js:noInline')
+  set field2b(_) {}
+
+  @pragma('dart2js:noInline')
+  get field2c => 42;
+
+  set field2c(_) {}
+
+  var field3a = 0;
+
+  var field3b;
+
+  @pragma('dart2js:noInline')
+  Class([this.field3b]);
+
+  @pragma('dart2js:noInline')
+  test() {
+    field1a;
+    field1b = 42;
+    field1c = field1c;
+
+    field2a;
+    field2b = 42;
+    field2c = field2c;
+  }
+}
+
+main() {
+  field1a;
+  field1b = 42;
+  field1c = field1c;
+
+  field2a;
+  field2b = 42;
+  field2c = field2c;
+
+  new Class().test();
+}
diff --git a/tests/compiler/dart2js_extra/rti/class_environment_test.dart b/tests/compiler/dart2js_extra/rti/class_environment_test.dart
new file mode 100644
index 0000000..0cad566
--- /dev/null
+++ b/tests/compiler/dart2js_extra/rti/class_environment_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2019, 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:_rti' as rti;
+import "package:expect/expect.dart";
+
+void checkRtiIdentical(Object rti1, Object rti2) {
+  var format = rti.testingRtiToString;
+  Expect.isTrue(
+      identical(rti1, rti2), 'identical(${format(rti1)}, ${format(rti2)}');
+}
+
+testInterface1() {
+  var universe = rti.testingCreateUniverse();
+
+  var env = rti.testingUniverseEval(universe, 'Foo<int>');
+  var rti1 = rti.testingUniverseEval(universe, 'int');
+  var rti2 = rti.testingEnvironmentEval(universe, env, '0');
+
+  Expect.equals('int', rti.testingRtiToString(rti1));
+  Expect.equals('int', rti.testingRtiToString(rti2));
+  checkRtiIdentical(rti1, rti2);
+}
+
+testInterface2() {
+  var universe = rti.testingCreateUniverse();
+
+  var env = rti.testingUniverseEval(universe, 'Foo<int,List<int>>');
+  var rti1 = rti.testingUniverseEval(universe, 'List<int>');
+  var rti2 = rti.testingEnvironmentEval(universe, env, '1');
+  var rti3 = rti.testingEnvironmentEval(universe, env, 'List<0>');
+
+  Expect.equals('List<int>', rti.testingRtiToString(rti1));
+  Expect.equals('List<int>', rti.testingRtiToString(rti2));
+  Expect.equals('List<int>', rti.testingRtiToString(rti3));
+  checkRtiIdentical(rti1, rti2);
+  checkRtiIdentical(rti1, rti3);
+}
+
+main() {
+  testInterface1();
+  testInterface2();
+}
diff --git a/tests/compiler/dart2js_extra/rti/simple_2_test.dart b/tests/compiler/dart2js_extra/rti/simple_2_test.dart
new file mode 100644
index 0000000..ce81c7b
--- /dev/null
+++ b/tests/compiler/dart2js_extra/rti/simple_2_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2019, 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:_rti' as rti;
+import "package:expect/expect.dart";
+
+testDynamic1() {
+  var universe = rti.testingCreateUniverse();
+
+  var dynamicRti1 = rti.testingUniverseEval(universe, 'dynamic');
+  var dynamicRti2 = rti.testingUniverseEval(universe, ',,dynamic,,');
+
+  Expect.isTrue(
+      identical(dynamicRti1, dynamicRti2), 'dynamic should be identical');
+  Expect.isFalse(dynamicRti1 is String);
+  Expect.equals('dynamic', rti.testingRtiToString(dynamicRti1));
+}
+
+testDynamic2() {
+  var universe = rti.testingCreateUniverse();
+
+  var dynamicRti1 = rti.testingUniverseEval(universe, 'dynamic');
+  var dynamicRti2 = rti.testingUniverseEval(universe, ',,@,,');
+
+  Expect.isTrue(
+      identical(dynamicRti1, dynamicRti2), 'dynamic should be identical');
+  Expect.isFalse(dynamicRti1 is String);
+  Expect.equals('dynamic', rti.testingRtiToString(dynamicRti1));
+}
+
+testInterface1() {
+  var universe = rti.testingCreateUniverse();
+
+  var rti1 = rti.testingUniverseEval(universe, 'int');
+  var rti2 = rti.testingUniverseEval(universe, ',,int,,');
+
+  Expect.isTrue(identical(rti1, rti2));
+  Expect.isFalse(rti1 is String);
+  Expect.equals('int', rti.testingRtiToString(rti1));
+}
+
+testInterface2() {
+  var universe = rti.testingCreateUniverse();
+
+  var rti1 = rti.testingUniverseEval(universe, 'Foo<int,bool>');
+  var rti2 = rti.testingUniverseEval(universe, 'Foo<int,bool>');
+
+  Expect.isTrue(identical(rti1, rti2));
+  Expect.isFalse(rti1 is String);
+  Expect.equals('Foo<int, bool>', rti.testingRtiToString(rti1));
+}
+
+testInterface3() {
+  var universe = rti.testingCreateUniverse();
+
+  var rti1 = rti.testingUniverseEval(universe, 'Foo<Bar<int>,Bar<bool>>');
+  var rti2 = rti.testingUniverseEval(universe, 'Foo<Bar<int>,Bar<bool>>');
+
+  Expect.isTrue(identical(rti1, rti2));
+  Expect.isFalse(rti1 is String);
+  Expect.equals('Foo<Bar<int>, Bar<bool>>', rti.testingRtiToString(rti1));
+}
+
+testInterface4() {
+  var universe = rti.testingCreateUniverse();
+
+  var rti1 = rti.testingUniverseEval(universe, 'Foo<Foo<Foo<Foo<int>>>>');
+  var rti2 = rti.testingUniverseEval(universe, 'Foo<Foo<Foo<Foo<int>>>>');
+
+  Expect.isTrue(identical(rti1, rti2));
+  Expect.isFalse(rti1 is String);
+  Expect.equals('Foo<Foo<Foo<Foo<int>>>>', rti.testingRtiToString(rti1));
+}
+
+main() {
+  testDynamic1();
+  testDynamic2();
+  testInterface1();
+  testInterface2();
+  testInterface3();
+  testInterface4();
+}
diff --git a/tests/compiler/dart2js_extra/rti/simple_test.dart b/tests/compiler/dart2js_extra/rti/simple_test.dart
new file mode 100644
index 0000000..88ccf9f
--- /dev/null
+++ b/tests/compiler/dart2js_extra/rti/simple_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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:_rti' as rti;
+import "package:expect/expect.dart";
+
+main() {
+  var universe = rti.testingCreateUniverse();
+
+  // TODO(sra): Add call: rti.testingAddRules(universe, ???);
+
+  var dynamicRti1 = rti.testingUniverseEval(universe, 'dynamic');
+  var dynamicRti2 = rti.testingUniverseEval(universe, 'dynamic');
+
+  Expect.isTrue(identical(dynamicRti1, dynamicRti2));
+  Expect.isFalse(dynamicRti1 is String);
+  Expect.equals('dynamic', rti.testingRtiToString(dynamicRti1));
+}
diff --git a/tests/compiler/dart2js_native/compute_this_script_test.dart b/tests/compiler/dart2js_native/compute_this_script_test.dart
index 8519bc4..ee5c855 100644
--- a/tests/compiler/dart2js_native/compute_this_script_test.dart
+++ b/tests/compiler/dart2js_native/compute_this_script_test.dart
@@ -10,7 +10,7 @@
   // This is somewhat brittle and relies on an implementation detail
   // of our test runner, but I can think of no other way to test this.
   // -- ahe
-  if (!thisScript.endsWith('/out.js')) {
+  if (!thisScript.endsWith('/compute_this_script_test.js')) {
     throw 'Unexpected script: "$thisScript"';
   }
 }
diff --git a/tests/compiler/dartdevc_native/const_test.dart b/tests/compiler/dartdevc_native/const_test.dart
new file mode 100644
index 0000000..b2dbf27
--- /dev/null
+++ b/tests/compiler/dartdevc_native/const_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2019, 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";
+import 'dart:_foreign_helper' show JS;
+import 'dart:_runtime' as dart;
+
+void main() {
+  var data = JS('', '[1, 2, 3, 4]');
+  Expect.isFalse(data is List<int>);
+
+  var list = dart.constList(data, dart.unwrapType(int));
+  Expect.isTrue(list is List<int>);
+  Expect.throws(() {
+    list[0] = 0;
+  });
+
+  var set = dart.constSet<int>(data);
+  Expect.isTrue(set is Set<int>);
+  Expect.isTrue(set.contains(3));
+  Expect.throws(() => set.clear());
+
+  var map = dart.constMap<int, int>(data);
+  Expect.isTrue(map is Map<int, int>);
+  Expect.equals(map[1], 2);
+  Expect.throws(() {
+    map[1] = 42;
+  });
+}
diff --git a/tests/compiler/dartdevc_native/libraries_part.dart b/tests/compiler/dartdevc_native/libraries_part.dart
new file mode 100644
index 0000000..d5ac766
--- /dev/null
+++ b/tests/compiler/dartdevc_native/libraries_part.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2019, 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 'libraries_test.dart';
diff --git a/tests/compiler/dartdevc_native/libraries_test.dart b/tests/compiler/dartdevc_native/libraries_test.dart
new file mode 100644
index 0000000..533eb5d
--- /dev/null
+++ b/tests/compiler/dartdevc_native/libraries_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, 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';
+import 'dart:_foreign_helper' show JS;
+import 'dart:_runtime' as dart;
+
+part 'libraries_part.dart';
+
+void main() {
+  // Test getLibraries()
+  var libraries = dart.getLibraries();
+  Expect.isTrue(libraries.contains('dart:core'));
+  Expect.isTrue(libraries.contains('package:expect/expect.dart'));
+
+  // Test getParts(...)
+  var expectParts = dart.getParts('package:expect/expect.dart');
+  Expect.isTrue(expectParts.isEmpty);
+
+  var testLibraries =
+      libraries.where((l) => l.endsWith('libraries_test.dart')).toList();
+  Expect.isTrue(testLibraries.length == 1);
+  var testParts = dart.getParts(testLibraries.first);
+  Expect.isTrue(testParts.length == 1);
+  Expect.isTrue(testParts.first.endsWith('libraries_part.dart'));
+
+  // Test getLibrary(...)
+  var core = dart.getLibrary('dart:core');
+  var stackTraceType = dart.wrapType(JS('', '#.StackTrace', core));
+  Expect.equals(StackTrace, stackTraceType);
+}
diff --git a/tests/corelib_2/bigint_test.dart b/tests/corelib_2/bigint_test.dart
index 01dea1f..0b5b8c5 100644
--- a/tests/corelib_2/bigint_test.dart
+++ b/tests/corelib_2/bigint_test.dart
@@ -222,6 +222,15 @@
   test(mediumNumber, new BigInt.from(137), new BigInt.from(77));
   test(new BigInt.from(137), mediumNumber, new BigInt.from(540686667207353));
   test(bigNumber, new BigInt.from(137), new BigInt.from(128));
+  var x = BigInt.parse(
+      "28ea16430c1f1072754aa5ebbfda0d790605a507c6c9758e88697b0b5dd9e74c",
+      radix: 16);
+  var m = BigInt.parse(
+      "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
+      radix: 16);
+  var r = BigInt.parse("95929095851002583825372225918533539673793386278"
+                       "360575987103577151530201707061", radix: 10);
+  test(x, m, r);
 }
 
 testGcd() {
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 45e2873..b196c6f 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -26,7 +26,9 @@
 double_floor_test/int64: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 double_round_test/int64: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 double_truncate_test/int64: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+error_stack_trace1_test: RuntimeError # Issue 12399
 growable_list_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+growable_list_test: RuntimeError # Concurrent modifications test always runs
 int_ceil_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 int_ceil_to_double_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 int_floor_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
@@ -43,7 +45,12 @@
 int_truncate_to_double_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 integer_arith_vm_test/modPow: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 integer_arith_vm_test/none: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+integer_to_radix_string_test/01: RuntimeError
+integer_to_radix_string_test/02: RuntimeError
+integer_to_radix_string_test/none: RuntimeError
+integer_to_string_test/01: RuntimeError
 integer_to_string_test/01: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+iterable_return_type_test/02: RuntimeError # Dart2js does not support Uint64*.
 list_unmodifiable_test: Pass, RuntimeError # Issue 28712
 num_parse_test/01: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 num_parse_test/none: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
@@ -88,12 +95,6 @@
 symbol_reserved_word_test/04: MissingCompileTimeError
 symbol_reserved_word_test/07: MissingCompileTimeError
 
-[ !$strong ]
-cast_test: SkipByDesign # Uses generic method parameters.
-iterable_where_type_test: SkipByDesign
-map_test: SkipByDesign
-regress_33166_test: SkipByDesign # Not a Dart 1 test
-
 [ $arch == simarmv5te && ($runtime == dart_precompiled || $runtime == vm) ]
 int_parse_radix_test/*: Pass, Slow
 integer_parsed_mul_div_vm_test: Pass, Slow
@@ -111,8 +112,9 @@
 error_stack_trace1_test: SkipByDesign # Expects unobfuscated stack trace
 
 # All static_tests have expected compile-time errors.
-[ $compiler != app_jitk && $compiler != dart2analyzer && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $compiler != fasta && $strong ]
+[ $compiler != app_jitk && $compiler != dart2analyzer && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $compiler != fasta ]
 core_runtime_types_static_test: MissingCompileTimeError
+iterable_mapping_test/01: MissingCompileTimeError
 splay_tree_test/01: MissingCompileTimeError
 splay_tree_test/02: MissingCompileTimeError
 string_base_vm_static_test: MissingCompileTimeError
@@ -122,9 +124,6 @@
 [ $compiler != app_jitk && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $compiler != fasta ]
 iterable_element_at_test/static: MissingCompileTimeError
 
-[ $compiler != app_jitk && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $compiler != fasta && ($compiler != dart2analyzer || !$strong) ]
-iterable_mapping_test/01: MissingCompileTimeError
-
 [ $compiler != app_jitk && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $runtime != none ]
 map_keys2_test: RuntimeError # needs Dart 2 is checks
 
@@ -141,22 +140,16 @@
 [ $compiler == dart2js && $runtime != none ]
 regexp/pcre_test: Pass, Slow # Issue 21593
 
-[ $compiler == dart2js && $runtime != none && !$strong ]
-collection_of_test: RuntimeError # Strong mode test
-map_of_test: RuntimeError # Strong mode test
-
 [ $compiler == dart2js && $runtime == safari ]
 regexp/lookahead_test: RuntimeError
 regexp/no-extensions_test: RuntimeError
-regexp/overflow_test: RuntimeError
-
-[ $compiler == dart2js && $runtime == safari && $strong ]
 regexp/no-extensions_test: Pass, RuntimeError
+regexp/overflow_test: RuntimeError
 
 [ $compiler == dart2js && !$browser ]
 package_resource_test: RuntimeError # Issue 26842
 
-[ $compiler == dart2js && $checked && $strong ]
+[ $compiler == dart2js && $checked ]
 apply3_test: RuntimeError
 collection_of_test: RuntimeError
 error_stack_trace1_test: RuntimeError # Issue 12399
@@ -188,7 +181,7 @@
 map_test: Crash # tests/corelib_2/map_test.dart:903:7: Internal problem: Unhandled Null in installDefaultConstructor.
 symbol_reserved_word_test/03: RuntimeError # Issue 19972, new Symbol('void') should be allowed.
 
-[ $compiler == dart2js && $minified && $strong ]
+[ $compiler == dart2js && $minified ]
 dynamic_nosuchmethod_test: RuntimeError
 error_stack_trace1_test: RuntimeError # Issue 12399
 growable_list_test: RuntimeError # Concurrent modifications test always runs
@@ -208,30 +201,10 @@
 symbol_operator_test/none: RuntimeError
 symbol_reserved_word_test/03: RuntimeError # Issue 19972, new Symbol('void') should be allowed.
 
-[ $compiler == dart2js && $strong ]
-error_stack_trace1_test: RuntimeError # Issue 12399
-growable_list_test: RuntimeError # Concurrent modifications test always runs
-integer_to_radix_string_test/01: RuntimeError
-integer_to_radix_string_test/02: RuntimeError
-integer_to_radix_string_test/none: RuntimeError
-integer_to_string_test/01: RuntimeError
-iterable_return_type_test/02: RuntimeError # Dart2js does not support Uint64*.
-
-[ $compiler == dart2js && !$strong ]
-*: SkipByDesign
-
 [ $compiler == dartdevc && $runtime != none ]
 compare_to2_test: CompileTimeError # invalid test
 symbol_operator_test: RuntimeError # Issue 29921
 
-[ $compiler != dartdevc && $compiler != dartdevk && $checked && !$strong ]
-core_runtime_types_static_test: MissingCompileTimeError
-splay_tree_test/01: MissingCompileTimeError
-splay_tree_test/02: MissingCompileTimeError
-string_base_vm_static_test: MissingCompileTimeError
-string_replace_static_test: MissingCompileTimeError
-string_static_test: MissingCompileTimeError
-
 [ $compiler != dartk && $runtime == vm && $checked ]
 apply_test/01: RuntimeError
 
@@ -240,7 +213,7 @@
 symbol_test/02: MissingCompileTimeError
 symbol_test/03: MissingCompileTimeError
 
-[ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
+[ $compiler == dartkp && $runtime == dart_precompiled ]
 iterable_fold_test/02: RuntimeError
 iterable_reduce_test/01: CompileTimeError # Issue 31533
 iterable_reduce_test/none: RuntimeError
@@ -252,9 +225,6 @@
 symbol_test/none: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
 unicode_test: RuntimeError # Issue 18061: German double S.
 
-[ $compiler != fasta && !$strong ]
-core_runtime_types_test: SkipByDesign
-
 [ $compiler == none && $runtime == vm ]
 from_environment_const_type_undefined_test/09: MissingCompileTimeError
 from_environment_const_type_undefined_test/11: MissingCompileTimeError
@@ -290,7 +260,7 @@
 typed_data_with_limited_ints_test: Skip # Requires fixed-size int64 support.
 
 # ===== dartk + vm status lines =====
-[ $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
 iterable_fold_test/02: RuntimeError
 iterable_reduce_test/01: CompileTimeError # Issue 31533
 iterable_reduce_test/none: RuntimeError
@@ -301,71 +271,15 @@
 symbol_test/none: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
 unicode_test: RuntimeError # Issue 18061: German double S.
 
-[ $runtime == vm && !$strong ]
-collection_of_test: RuntimeError
-
-[ !$checked && !$strong ]
-core_runtime_types_static_test: MissingCompileTimeError
-splay_tree_test/01: MissingCompileTimeError
-splay_tree_test/02: MissingCompileTimeError
-string_base_vm_static_test: MissingCompileTimeError
-string_replace_static_test: MissingCompileTimeError
-string_static_test: MissingCompileTimeError
-
 # We no longer expect Dart2 tests to run with the standalone VM without the new
 # common front end, but for now we get better coverage by still running them in
 # checked mode, which is mostly Dart2-compatible.
 [ !$checked && ($compiler == app_jit || $compiler == none || $compiler == precompiler) && ($runtime == dart_precompiled || $runtime == vm) ]
 *: SkipByDesign
 
-[ $fasta && !$strong ]
-bool_from_environment2_test/01: MissingCompileTimeError
-bool_from_environment2_test/02: MissingCompileTimeError
-bool_from_environment2_test/04: MissingCompileTimeError
-bool_from_environment2_test/05: MissingCompileTimeError
-from_environment_const_type_test/02: MissingCompileTimeError
-from_environment_const_type_test/03: MissingCompileTimeError
-from_environment_const_type_test/04: MissingCompileTimeError
-from_environment_const_type_test/06: MissingCompileTimeError
-from_environment_const_type_test/07: MissingCompileTimeError
-from_environment_const_type_test/08: MissingCompileTimeError
-from_environment_const_type_test/09: MissingCompileTimeError
-from_environment_const_type_test/11: MissingCompileTimeError
-from_environment_const_type_test/12: MissingCompileTimeError
-from_environment_const_type_test/13: MissingCompileTimeError
-from_environment_const_type_test/14: MissingCompileTimeError
-from_environment_const_type_test/16: MissingCompileTimeError
-from_environment_const_type_undefined_test/02: MissingCompileTimeError
-from_environment_const_type_undefined_test/03: MissingCompileTimeError
-from_environment_const_type_undefined_test/04: MissingCompileTimeError
-from_environment_const_type_undefined_test/06: MissingCompileTimeError
-from_environment_const_type_undefined_test/07: MissingCompileTimeError
-from_environment_const_type_undefined_test/08: MissingCompileTimeError
-from_environment_const_type_undefined_test/09: MissingCompileTimeError
-from_environment_const_type_undefined_test/11: MissingCompileTimeError
-from_environment_const_type_undefined_test/12: MissingCompileTimeError
-from_environment_const_type_undefined_test/13: MissingCompileTimeError
-from_environment_const_type_undefined_test/14: MissingCompileTimeError
-from_environment_const_type_undefined_test/16: MissingCompileTimeError
-int_parse_radix_bad_handler_test: MissingCompileTimeError
-iterable_element_at_test/static: MissingCompileTimeError
-iterable_mapping_test/01: MissingCompileTimeError
-string_from_environment3_test/01: MissingCompileTimeError
-string_from_environment3_test/02: MissingCompileTimeError
-string_from_environment3_test/04: MissingCompileTimeError
-string_from_environment3_test/05: MissingCompileTimeError
-symbol_reserved_word_test/05: MissingCompileTimeError
-symbol_test/01: MissingCompileTimeError
-
 [ !$preview_dart_2 && ($runtime == dart_precompiled || $runtime == vm) ]
 *: SkipByDesign # Deprecating all Dart1 modes of execution
 
-[ !$strong && ($compiler == dartk || $compiler == dartkb || $compiler == dartkp) ]
-*: SkipByDesign
-
-[ !$strong && ($runtime == dart_precompiled || $runtime == vm) ]
-list_test/*: RuntimeError # VM doesn't implement strong mode covariance checks
-
 [ ($arch == simdbc || $arch == simdbc64) && ($hot_reload || $hot_reload_rollback) ]
 uri_parse_test: SkipSlow
 
@@ -521,12 +435,6 @@
 bigint_test/03: SkipSlow # --no_intrinsify
 bigint_test/15: SkipSlow # --no_intrinsify
 
-[ $compiler == precompiler || $runtime == vm && !$checked && !$strong ]
-int_parse_radix_test/badTypes: RuntimeError # wrong exception returned
-
-[ $compiler == precompiler || $runtime == vm && !$strong ]
-apply3_test: RuntimeError
-
 [ $runtime == dart_precompiled || $runtime == vm ]
 regexp/global_test: Skip # Issue 21709
 regexp/pcre_test: Pass, Slow, Timeout
diff --git a/tests/corelib_2/regexp/dot-all_test.dart b/tests/corelib_2/regexp/dot-all_test.dart
new file mode 100644
index 0000000..5610e7f
--- /dev/null
+++ b/tests/corelib_2/regexp/dot-all_test.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2017 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  // The flags accessors.
+  var re = new RegExp(r".", dotAll: true);
+  assertTrue(re.isCaseSensitive);
+  assertFalse(re.isMultiLine);
+  assertFalse(re.isUnicode);
+  assertTrue(re.isDotAll);
+
+  re = new RegExp(r".",
+      caseSensitive: false, multiLine: true, unicode: true, dotAll: true);
+  assertFalse(re.isCaseSensitive);
+  assertTrue(re.isMultiLine);
+  assertTrue(re.isUnicode);
+  assertTrue(re.isDotAll);
+
+  re = new RegExp(r".", caseSensitive: false, multiLine: true, unicode: true);
+  assertFalse(re.isCaseSensitive);
+  assertTrue(re.isMultiLine);
+  assertTrue(re.isUnicode);
+  assertFalse(re.isDotAll);
+
+  // Default '.' behavior.
+  re = new RegExp(r"^.$");
+  assertTrue(re.hasMatch("a"));
+  assertTrue(re.hasMatch("3"));
+  assertTrue(re.hasMatch("π"));
+  assertTrue(re.hasMatch("\u2027"));
+  assertTrue(re.hasMatch("\u0085"));
+  assertTrue(re.hasMatch("\v"));
+  assertTrue(re.hasMatch("\f"));
+  assertTrue(re.hasMatch("\u180E"));
+  assertFalse(re.hasMatch("\u{10300}")); // Supplementary plane.
+  assertFalse(re.hasMatch("\n"));
+  assertFalse(re.hasMatch("\r"));
+  assertFalse(re.hasMatch("\u2028"));
+  assertFalse(re.hasMatch("\u2029"));
+
+  // Default '.' behavior (unicode).
+  re = new RegExp(r"^.$", unicode: true);
+  assertTrue(re.hasMatch("a"));
+  assertTrue(re.hasMatch("3"));
+  assertTrue(re.hasMatch("π"));
+  assertTrue(re.hasMatch("\u2027"));
+  assertTrue(re.hasMatch("\u0085"));
+  assertTrue(re.hasMatch("\v"));
+  assertTrue(re.hasMatch("\f"));
+  assertTrue(re.hasMatch("\u180E"));
+  assertTrue(re.hasMatch("\u{10300}")); // Supplementary plane.
+  assertFalse(re.hasMatch("\n"));
+  assertFalse(re.hasMatch("\r"));
+  assertFalse(re.hasMatch("\u2028"));
+  assertFalse(re.hasMatch("\u2029"));
+
+  // DotAll '.' behavior.
+  re = new RegExp(r"^.$", dotAll: true);
+  assertTrue(re.hasMatch("a"));
+  assertTrue(re.hasMatch("3"));
+  assertTrue(re.hasMatch("π"));
+  assertTrue(re.hasMatch("\u2027"));
+  assertTrue(re.hasMatch("\u0085"));
+  assertTrue(re.hasMatch("\v"));
+  assertTrue(re.hasMatch("\f"));
+  assertTrue(re.hasMatch("\u180E"));
+  assertFalse(re.hasMatch("\u{10300}")); // Supplementary plane.
+  assertTrue(re.hasMatch("\n"));
+  assertTrue(re.hasMatch("\r"));
+  assertTrue(re.hasMatch("\u2028"));
+  assertTrue(re.hasMatch("\u2029"));
+
+  // DotAll '.' behavior (unicode).
+  re = new RegExp(r"^.$", unicode: true, dotAll: true);
+  assertTrue(re.hasMatch("a"));
+  assertTrue(re.hasMatch("3"));
+  assertTrue(re.hasMatch("π"));
+  assertTrue(re.hasMatch("\u2027"));
+  assertTrue(re.hasMatch("\u0085"));
+  assertTrue(re.hasMatch("\v"));
+  assertTrue(re.hasMatch("\f"));
+  assertTrue(re.hasMatch("\u180E"));
+  assertTrue(re.hasMatch("\u{10300}")); // Supplementary plane.
+  assertTrue(re.hasMatch("\n"));
+  assertTrue(re.hasMatch("\r"));
+  assertTrue(re.hasMatch("\u2028"));
+  assertTrue(re.hasMatch("\u2029"));
+}
diff --git a/tests/corelib_2/regexp/lookbehind_test.dart b/tests/corelib_2/regexp/lookbehind_test.dart
index 5ccdcdb..3fd11af 100644
--- a/tests/corelib_2/regexp/lookbehind_test.dart
+++ b/tests/corelib_2/regexp/lookbehind_test.dart
@@ -433,8 +433,6 @@
   assertThrows(() => new RegExp(r"(?<=.)?")); //# 01: ok
   assertThrows(() => new RegExp(r"(?<=.)+")); //# 01: ok
 
-  // No unicode flag (yet), so can't test these.
-  // See https://github.com/dart-lang/sdk/issues/36170.
-  // assertThrows("/(?<=.)*/u", SyntaxError);
-  // assertThrows("/(?<=.){1,2}/u", SyntaxError);
+  assertThrows(() => new RegExp(r"(?<=.)*", unicode: true)); //# 01: ok
+  assertThrows(() => new RegExp(r"(?<=.){1,2}", unicode: true)); //# 01: ok
 }
diff --git a/tests/corelib_2/regexp/named-captures_test.dart b/tests/corelib_2/regexp/named-captures_test.dart
index aff61b8..ee2d843 100644
--- a/tests/corelib_2/regexp/named-captures_test.dart
+++ b/tests/corelib_2/regexp/named-captures_test.dart
@@ -31,35 +31,90 @@
 import 'v8_regexp_utils.dart';
 
 void main() {
-  void testRE(RegExp re, String input, bool expectedResult) {
-    if (expectedResult) {
-      assertTrue(re.hasMatch(input));
-    } else {
-      assertFalse(re.hasMatch(input));
-    }
-  }
-
   void execRE(RegExp re, String input, List<String> expectedResult) {
     assertTrue(re.hasMatch(input));
     shouldBe(re.firstMatch(input), expectedResult);
   }
 
+  void execString(String pattern, String input, List<String> expectedResult,
+      {bool unicode = true, bool caseSensitive: false}) {
+    execRE(RegExp(pattern, unicode: unicode, caseSensitive: caseSensitive),
+        input, expectedResult);
+  }
+
   void namedRE(RegExp re, String input, Map<String, String> expectedResults) {
     assertTrue(re.hasMatch(input));
-    var match = re.firstMatch(input) as RegExpMatch;
+    var match = re.firstMatch(input);
     for (var s in expectedResults.keys) {
       assertEquals(match.namedGroup(s), expectedResults[s]);
     }
   }
 
+  void execStringGroups(
+      String pattern, String input, Map<String, String> expectedResults,
+      {bool unicode = true, bool caseSensitive: false}) {
+    namedRE(RegExp(pattern, unicode: unicode, caseSensitive: caseSensitive),
+        input, expectedResults);
+  }
+
   void hasNames(RegExp re, String input, List<String> expectedResults) {
     assertTrue(re.hasMatch(input));
-    var match = re.firstMatch(input) as RegExpMatch;
+    var match = re.firstMatch(input);
     for (var s in match.groupNames) {
       assertTrue(expectedResults.contains(s));
     }
   }
 
+  void matchesIndexEqual(String input, RegExp re1, RegExp re2) {
+    var m1 = re1.firstMatch(input);
+    var m2 = re2.firstMatch(input);
+    if (m2 == null) {
+      assertNull(m1);
+    } else {
+      assertTrue(m1 != null);
+      assertEquals(m1.groupCount, m2.groupCount);
+      for (int i = 0; i < m1.groupCount; i++) {
+        assertEquals(m1.group(i), m2.group(i));
+      }
+    }
+  }
+
+  // Malformed named captures.
+  // Empty name.
+  assertThrows(() => RegExp(r"(?<>a)", unicode: true));
+  // Unterminated name.
+  assertThrows(() => RegExp(r"(?<aa)", unicode: true));
+  // Name starting with digits.
+  assertThrows(() => RegExp(r"(?<42a>a)", unicode: true));
+  // Name starting with invalid char.
+  assertThrows(() => RegExp(r"(?<:a>a)", unicode: true));
+  // Name containing invalid char.
+  assertThrows(() => RegExp(r"(?<a:>a)", unicode: true));
+  // Duplicate name.
+  assertThrows(() => RegExp(r"(?<a>a)(?<a>a)", unicode: true));
+  // Duplicate name.
+  assertThrows(() => RegExp(r"(?<a>a)(?<b>b)(?<a>a)", unicode: true));
+  // Invalid reference.
+  assertThrows(() => RegExp(r"\k<a>", unicode: true));
+  // Unterminated reference.
+  assertThrows(() => RegExp(r"\k<a", unicode: true));
+  // Lone \k.
+  assertThrows(() => RegExp(r"\k", unicode: true));
+  // Lone \k.
+  assertThrows(() => RegExp(r"(?<a>.)\k", unicode: true));
+  // Unterminated reference.
+  assertThrows(() => RegExp(r"(?<a>.)\k<a", unicode: true));
+  // Invalid reference.
+  assertThrows(() => RegExp(r"(?<a>.)\k<b>", unicode: true));
+  // Invalid reference.
+  assertThrows(() => RegExp(r"(?<a>a)\k<ab>", unicode: true));
+  // Invalid reference.
+  assertThrows(() => RegExp(r"(?<ab>a)\k<a>", unicode: true));
+  // Invalid reference.
+  assertThrows(() => RegExp(r"\k<a>(?<ab>a)", unicode: true));
+  // Identity escape in capture.
+  assertThrows(() => RegExp(r"(?<a>\a)", unicode: true));
+
   // Behavior in non-unicode mode.
   assertThrows(() => RegExp(r"(?<>a)"));
   assertThrows(() => RegExp(r"(?<aa)"));
@@ -102,6 +157,182 @@
   assertThrows(() => RegExp(r"\k<a(?<a>.)"));
   assertThrows(() => RegExp(r"\k(?<a>.)"));
 
-  // TODO(sstrickl): Add more tests when unicode flag support is in.
-  // https://github.com/dart-lang/sdk/issues/36170
+  // Basic named groups.
+  execString(r"(?<a>a)", "bab", ["a", "a"]);
+  execString(r"(?<a42>a)", "bab", ["a", "a"]);
+  execString(r"(?<_>a)", "bab", ["a", "a"]);
+  execString(r"(?<$>a)", "bab", ["a", "a"]);
+  execString(r".(?<$>a).", "bab", ["bab", "a"]);
+  execString(r".(?<a>a)(.)", "bab", ["bab", "a", "b"]);
+  execString(r".(?<a>a)(?<b>.)", "bab", ["bab", "a", "b"]);
+  execString(r".(?<a>\w\w)", "bab", ["bab", "ab"]);
+  execString(r"(?<a>\w\w\w)", "bab", ["bab", "bab"]);
+  execString(r"(?<a>\w\w)(?<b>\w)", "bab", ["bab", "ba", "b"]);
+
+  execString(r"(?<a>a)", "bab", ["a", "a"], unicode: false);
+  execString(r"(?<a42>a)", "bab", ["a", "a"], unicode: false);
+  execString(r"(?<_>a)", "bab", ["a", "a"], unicode: false);
+  execString(r"(?<$>a)", "bab", ["a", "a"], unicode: false);
+  execString(r".(?<$>a).", "bab", ["bab", "a"], unicode: false);
+  execString(r".(?<a>a)(.)", "bab", ["bab", "a", "b"], unicode: false);
+  execString(r".(?<a>a)(?<b>.)", "bab", ["bab", "a", "b"], unicode: false);
+  execString(r".(?<a>\w\w)", "bab", ["bab", "ab"], unicode: false);
+  execString(r"(?<a>\w\w\w)", "bab", ["bab", "bab"], unicode: false);
+  execString(r"(?<a>\w\w)(?<b>\w)", "bab", ["bab", "ba", "b"], unicode: false);
+
+  matchesIndexEqual(
+      "bab", RegExp(r"(?<a>a)", unicode: true), RegExp(r"(a)", unicode: true));
+  matchesIndexEqual("bab", RegExp(r"(?<a42>a)", unicode: true),
+      RegExp(r"(a)", unicode: true));
+  matchesIndexEqual(
+      "bab", RegExp(r"(?<_>a)", unicode: true), RegExp(r"(a)", unicode: true));
+  matchesIndexEqual(
+      "bab", RegExp(r"(?<$>a)", unicode: true), RegExp(r"(a)", unicode: true));
+  matchesIndexEqual("bab", RegExp(r".(?<$>a).", unicode: true),
+      RegExp(r".(a).", unicode: true));
+  matchesIndexEqual("bab", RegExp(r".(?<a>a)(.)", unicode: true),
+      RegExp(r".(a)(.)", unicode: true));
+  matchesIndexEqual("bab", RegExp(r".(?<a>a)(?<b>.)", unicode: true),
+      RegExp(r".(a)(.)", unicode: true));
+  matchesIndexEqual("bab", RegExp(r".(?<a>\w\w)", unicode: true),
+      RegExp(r".(\w\w)", unicode: true));
+  matchesIndexEqual("bab", RegExp(r"(?<a>\w\w\w)", unicode: true),
+      RegExp(r"(\w\w\w)", unicode: true));
+  matchesIndexEqual("bab", RegExp(r"(?<a>\w\w)(?<b>\w)", unicode: true),
+      RegExp(r"(\w\w)(\w)", unicode: true));
+
+  execString(r"(?<b>b).\1", "bab", ["bab", "b"]);
+  execString(r"(.)(?<a>a)\1\2", "baba", ["baba", "b", "a"]);
+  execString(r"(.)(?<a>a)(?<b>\1)(\2)", "baba", ["baba", "b", "a", "b", "a"]);
+  execString(r"(?<lt><)a", "<a", ["<a", "<"]);
+  execString(r"(?<gt>>)a", ">a", [">a", ">"]);
+
+  // Named references.
+  var pattern = r"(?<b>.).\k<b>";
+  execString(pattern, "bab", ["bab", "b"]);
+  assertFalse(RegExp(pattern, unicode: true).hasMatch("baa"));
+
+  // Nested groups.
+  pattern = r"(?<a>.(?<b>.(?<c>.)))";
+  execString(pattern, "bab", ["bab", "bab", "ab", "b"]);
+  execStringGroups(pattern, "bab", {"a": "bab", "b": "ab", "c": "b"});
+
+  // Reference inside group.
+  pattern = r"(?<a>\k<a>\w)..";
+  execString(pattern, "bab", ["bab", "b"]);
+  execStringGroups(pattern, "bab", {"a": "b"});
+
+  // Reference before group.
+  pattern = r"\k<a>(?<a>b)\w\k<a>";
+  execString(pattern, "bab", ["bab", "b"], unicode: false);
+  execString(pattern, "bab", ["bab", "b"]);
+  execStringGroups(pattern, "bab", {"a": "b"});
+
+  pattern = r"(?<b>b)\k<a>(?<a>a)\k<b>";
+  execString(pattern, "bab", ["bab", "b", "a"], unicode: false);
+  execString(pattern, "bab", ["bab", "b", "a"]);
+  execStringGroups(pattern, "bab", {"a": "a", "b": "b"});
+
+  // Reference named groups.
+  var match = RegExp(r"(?<a>a)(?<b>b)\k<a>", unicode: true).firstMatch("aba");
+  assertEquals("a", match.namedGroup("a"));
+  assertEquals("b", match.namedGroup("b"));
+  assertFalse(match.groupNames.contains("c"));
+
+  match =
+      RegExp(r"(?<a>a)(?<b>b)\k<a>|(?<c>c)", unicode: true).firstMatch("aba");
+  assertNull(match.namedGroup("c"));
+
+  // Unicode names.
+  execStringGroups(r"(?<π>a)", "bab", {"π": "a"});
+  execStringGroups(r"(?<\u{03C0}>a)", "bab", {"π": "a"});
+  execStringGroups(r"(?<π>a)", "bab", {"\u03C0": "a"});
+  execStringGroups(r"(?<\u{03C0}>a)", "bab", {"\u03C0": "a"});
+  execStringGroups(r"(?<$>a)", "bab", {"\$": "a"});
+  execStringGroups(r"(?<_>a)", "bab", {"_": "a"});
+  execStringGroups(r"(?<$𐒤>a)", "bab", {"\$𐒤": "a"});
+  execStringGroups(r"(?<_\u200C>a)", "bab", {"_\u200C": "a"});
+  execStringGroups(r"(?<_\u200D>a)", "bab", {"_\u200D": "a"});
+  execStringGroups(r"(?<ಠ_ಠ>a)", "bab", {"ಠ_ಠ": "a"});
+  // ID_Continue but not ID_Start.
+  assertThrows(() => RegExp(r"/(?<❤>a)", unicode: true));
+  assertThrows(() => RegExp(r"/(?<𐒤>a)", unicode: true));
+
+  execStringGroups(r"(?<π>a)", "bab", {"π": "a"}, unicode: false);
+  execStringGroups(r"(?<$>a)", "bab", {"\$": "a"}, unicode: false);
+  execStringGroups(r"(?<_>a)", "bab", {"_": "a"}, unicode: false);
+  assertThrows(() => RegExp(r"(?<$𐒤>a)"));
+  execStringGroups(r"(?<ಠ_ಠ>a)", "bab", {"ಠ_ಠ": "a"}, unicode: false);
+  // ID_Continue but not ID_Start.
+  assertThrows(() => RegExp(r"/(?<❤>a)"));
+  assertThrows(() => RegExp(r"/(?<𐒤>a)"));
+
+  // Interaction with lookbehind assertions.
+  pattern = r"(?<=(?<a>\w){3})f";
+  execString(pattern, "abcdef", ["f", "c"]);
+  execStringGroups(pattern, "abcdef", {"a": "c"});
+
+  execStringGroups(r"(?<=(?<a>\w){4})f", "abcdef", {"a": "b"});
+  execStringGroups(r"(?<=(?<a>\w)+)f", "abcdef", {"a": "a"});
+  assertFalse(RegExp(r"(?<=(?<a>\w){6})f", unicode: true).hasMatch("abcdef"));
+
+  execString(r"((?<=\w{3}))f", "abcdef", ["f", ""]);
+  execString(r"(?<a>(?<=\w{3}))f", "abcdef", ["f", ""]);
+
+  execString(r"(?<!(?<a>\d){3})f", "abcdef", ["f", null]);
+  assertFalse(RegExp(r"(?<!(?<a>\D){3})f", unicode: true).hasMatch("abcdef"));
+
+  execString(r"(?<!(?<a>\D){3})f|f", "abcdef", ["f", null]);
+  execString(r"(?<a>(?<!\D{3}))f|f", "abcdef", ["f", null]);
+
+  // Matches contain the names of named captures
+  match = RegExp(r"(?<fst>.)|(?<snd>.)", unicode: true).firstMatch("abcd");
+  Expect.setEquals(["fst", "snd"], match.groupNames);
+
+  // Backslash as ID_Start and ID_Continue (v8:5868).
+  assertThrows(() => RegExp("(?<\\>.)")); // '\' misclassified as ID_Start.
+  assertThrows(() => RegExp("(?<a\\>.)")); // '\' misclassified as ID_Continue.
+
+  // Backreference before the group (exercises the capture mini-parser).
+  assertThrows(() => RegExp(r"/\1(?:.)", unicode: true));
+  assertThrows(() => RegExp(r"/\1(?<=a).", unicode: true));
+  assertThrows(() => RegExp(r"/\1(?<!a).", unicode: true));
+  execString(r"\1(?<a>.)", "abcd", ["a", "a"]);
+
+  // Unicode escapes in capture names. (Testing both unicode interpreted by
+  // Dart string handling and also escaped unicode making it to RegExp parser.)
+
+  // \u Lead \u Trail
+  assertTrue(RegExp("(?<a\uD801\uDCA4>.)", unicode: true).hasMatch("a"));
+  assertTrue(RegExp(r"(?<a\uD801\uDCA4>.)", unicode: true).hasMatch("a"));
+  assertThrows(() => RegExp("(?<a\uD801>.)", unicode: true)); // \u Lead
+  assertThrows(() => RegExp(r"(?<a\uD801>.)", unicode: true)); // \u Lead
+  assertThrows(() => RegExp("(?<a\uDCA4>.)", unicode: true)); // \u Trail
+  assertThrows(() => RegExp(r"(?<a\uDCA4>.)", unicode: true)); // \u Trail
+  // \u NonSurrogate
+  assertTrue(RegExp("(?<\u0041>.)", unicode: true).hasMatch("a"));
+  assertTrue(RegExp(r"(?<\u0041>.)", unicode: true).hasMatch("a"));
+  // \u{ Surrogate, ID_Continue }
+  assertTrue(RegExp("(?<a\u{104A4}>.)", unicode: true).hasMatch("a"));
+  assertTrue(RegExp(r"(?<a\u{104A4}>.)", unicode: true).hasMatch("a"));
+
+  // \u{ Out-of-bounds } -- only need to test RegExp parser for this.
+  assertThrows(() => RegExp(r"(?<a\\u{110000}>.)", unicode: true));
+
+  // Also checking non-unicode patterns, where surrogate pairs will not
+  // be combined (so only \u0041 will have any success).
+
+  assertThrows(() => RegExp("(?<a\uD801\uDCA4>.)"));
+  assertThrows(() => RegExp(r"(?<a\uD801\uDCA4>.)"));
+  assertThrows(() => RegExp("(?<a\uD801>.)"));
+  assertThrows(() => RegExp(r"(?<a\uD801>.)"));
+  assertThrows(() => RegExp("(?<a\uDCA4>.)"));
+  assertThrows(() => RegExp(r"(?<a\uDCA4>.)"));
+  assertTrue(RegExp("(?<\u0041>.)").hasMatch("a"));
+  assertTrue(RegExp(r"(?<\u0041>.)").hasMatch("a"));
+  assertThrows(() => RegExp("(?<a\u{104A4}>.)"));
+  assertThrows(() => RegExp(r"(?<a\u{104A4}>.)"));
+  assertThrows(() => RegExp("(?<a\u{10FFFF}>.)"));
+  assertThrows(() => RegExp(r"(?<a\u{10FFFF}>.)"));
+  assertThrows(() => RegExp(r"(?<a\\u{110000}>.)"));
 }
diff --git a/tests/corelib_2/regexp/unicode-character-ranges_test.dart b/tests/corelib_2/regexp/unicode-character-ranges_test.dart
new file mode 100644
index 0000000..7154d0f
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-character-ranges_test.dart
@@ -0,0 +1,160 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1.  Redistributions of source code must retain the above copyright
+//     notice, this list of conditions and the following disclaimer.
+// 2.  Redistributions in binary form must reproduce the above copyright
+//     notice, this list of conditions and the following disclaimer in the
+//     documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void execl(List<String> expectation, RegExp re, String subject) {
+  shouldBe(re.firstMatch(subject), expectation);
+}
+
+void execs(List<String> expectation, String pattern, String subject) {
+  final re = RegExp(pattern, unicode: true);
+  shouldBe(re.firstMatch(subject), expectation);
+}
+
+void main() {
+  // Character ranges.
+  execs(["A"], r"[A-D]", "A");
+  execs(["ABCD"], r"[A-D]+", "ZABCDEF");
+
+  execs(["\u{12345}"], r"[\u1234-\u{12345}]", "\u{12345}");
+  execs(null, r"[^\u1234-\u{12345}]", "\u{12345}");
+
+  execs(["\u{1234}"], r"[\u1234-\u{12345}]", "\u{1234}");
+  execs(null, r"[^\u1234-\u{12345}]", "\u{1234}");
+
+  execs(null, r"[\u1234-\u{12345}]", "\u{1233}");
+  execs(["\u{1233}"], r"[^\u1234-\u{12345}]", "\u{1233}");
+
+  execs(["\u{12346}"], r"[^\u1234-\u{12345}]", "\u{12346}");
+  execs(null, r"[\u1234-\u{12345}]", "\u{12346}");
+
+  execs(["\u{12342}"], r"[\u{12340}-\u{12345}]", "\u{12342}");
+  execs(["\u{12342}"], r"[\ud808\udf40-\ud808\udf45]", "\u{12342}");
+  execs(null, r"[^\u{12340}-\u{12345}]", "\u{12342}");
+  execs(null, r"[^\ud808\udf40-\ud808\udf45]", "\u{12342}");
+
+  execs(["\u{ffff}"], r"[\u{ff80}-\u{12345}]", "\u{ffff}");
+  execs(["\u{ffff}"], r"[\u{ff80}-\ud808\udf45]", "\u{ffff}");
+  execs(null, r"[^\u{ff80}-\u{12345}]", "\u{ffff}");
+  execs(null, r"[^\u{ff80}-\ud808\udf45]", "\u{ffff}");
+
+  // Lone surrogate
+  execs(["\udc00"], r"[^\u{ff80}-\u{12345}]", "\uff99\u{dc00}A");
+  execs(["\udc01"], r"[\u0100-\u{10ffff}]", "A\udc01");
+  execs(["\udc03"], r"[\udc01-\udc03]", "\ud801\udc02\udc03");
+  execs(["\ud801"], r"[\ud801-\ud803]", "\ud802\udc01\ud801");
+
+  // Paired surrogate.
+  execs(null, r"[^\u{ff80}-\u{12345}]", "\u{d800}\u{dc00}");
+  execs(["\ud800\udc00"], r"[\u{ff80}-\u{12345}]", "\u{d800}\u{dc00}");
+  execs(["foo\u{10e6d}bar"], r"foo\ud803\ude6dbar", "foo\u{10e6d}bar");
+
+  // Lone surrogates
+  execs(["\ud801\ud801"], r"\ud801+", "\ud801\udc01\ud801\ud801");
+  execs(["\udc01\udc01"], r"\udc01+", "\ud801\ud801\udc01\udc01\udc01");
+
+  execs(["\udc02\udc03A"], r"\W\WA", "\ud801\udc01A\udc02\udc03A");
+  execs(["\ud801\ud802"], r"\ud801.", "\ud801\udc01\ud801\ud802");
+  execs(["\udc02\udc03A"], r"[\ud800-\udfff][\ud800-\udfff]A",
+      "\ud801\udc01A\udc02\udc03A");
+
+  // Character classes
+  execs(null, r"\w", "\ud801\udc01");
+  execl(["\ud801"], RegExp(r"[^\w]"), "\ud801\udc01");
+  execs(["\ud801\udc01"], r"[^\w]", "\ud801\udc01");
+  execl(["\ud801"], RegExp(r"\W"), "\ud801\udc01");
+  execs(["\ud801\udc01"], r"\W", "\ud801\udc01");
+
+  execs(["\ud800X"], r".X", "\ud800XaX");
+  execs(["aX"], r".(?<!\ud800)X", "\ud800XaX");
+  execs(["aX"], r".(?<![\ud800-\ud900])X", "\ud800XaX");
+
+  execs(null, r"[]", "\u1234");
+  execs(["0abc"], r"[^]abc", "0abc");
+  execs(["\u1234abc"], r"[^]abc", "\u1234abc");
+  execs(["\u{12345}abc"], r"[^]abc", "\u{12345}abc");
+
+  execs(null, r"[\u{0}-\u{1F444}]", "\ud83d\udfff");
+
+  // Backward matches of lone surrogates.
+  execs(["B", "\ud803A"], r"(?<=([\ud800-\ud900]A))B",
+      "\ud801\udc00AB\udc00AB\ud802\ud803AB");
+  execs(["B", "\udc00A"], r"(?<=([\ud800-\u{10300}]A))B",
+      "\ud801\udc00AB\udc00AB\ud802\ud803AB");
+  execs(["B", "\udc11A"], r"(?<=([\udc00-\udd00]A))B",
+      "\ud801\udc00AB\udc11AB\ud802\ud803AB");
+  execs(["X", "\ud800C"], r"(?<=(\ud800\w))X",
+      "\ud800\udc00AX\udc11BX\ud800\ud800CX");
+  execs(["C", "\ud800\ud800"], r"(?<=(\ud800.))\w",
+      "\ud800\udc00AX\udc11BX\ud800\ud800CX");
+  execs(["X", "\udc01C"], r"(?<=(\udc01\w))X",
+      "\ud800\udc01AX\udc11BX\udc01\udc01CX");
+  execs(["C", "\udc01\udc01"], r"(?<=(\udc01.)).",
+      "\ud800\udc01AX\udc11BX\udc01\udc01CX");
+
+  const L = "\ud800";
+  const T = "\udc00";
+  const X = "X";
+
+  // Test string contains only match.
+  void testw(bool expect, String src, String subject) {
+    var re = RegExp(r"^" + src + r"$", unicode: true);
+    assertEquals(expect, re.hasMatch(subject));
+  }
+
+  // Test string starts with match.
+  void tests(bool expect, String src, String subject) {
+    var re = RegExp(r"^" + src, unicode: true);
+    assertEquals(expect, re.hasMatch(subject));
+  }
+
+  testw(true, X, X);
+  testw(true, L, L);
+  testw(true, T, T);
+  testw(true, L + T, L + T);
+  testw(true, T + L, T + L);
+  testw(false, T, L + T);
+  testw(false, L, L + T);
+  testw(true, r".(?<=" + L + r")", L);
+  testw(true, r".(?<=" + T + r")", T);
+  testw(true, r".(?<=" + L + T + r")", L + T);
+  testw(true, r".(?<=" + L + T + r")", L + T);
+  tests(true, r".(?<=" + T + r")", T + L);
+  tests(false, r".(?<=" + L + r")", L + T);
+  tests(false, r".(?<=" + T + r")", L + T);
+  tests(true, r"..(?<=" + T + r")", T + T + L);
+  tests(true, r"..(?<=" + T + r")", X + T + L);
+  tests(true, r"...(?<=" + L + r")", X + T + L);
+  tests(false, r"...(?<=" + T + r")", X + L + T);
+  tests(true, r"..(?<=" + L + T + r")", X + L + T);
+  tests(true, r"..(?<=" + L + T + r"(?<=" + L + T + r"))", X + L + T);
+  tests(false, r"..(?<=" + L + r"(" + T + r"))", X + L + T);
+  tests(false, r".*" + L, X + L + T);
+  tests(true, r".*" + L, X + L + L + T);
+  tests(false, r".*" + L, X + L + T + L + T);
+  tests(false, r".*" + T, X + L + T + L + T);
+  tests(true, r".*" + T, X + L + T + T + L + T);
+}
diff --git a/tests/corelib_2/regexp/unicode-escapes-in-regexps_test.dart b/tests/corelib_2/regexp/unicode-escapes-in-regexps_test.dart
new file mode 100644
index 0000000..7cb0894
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-escapes-in-regexps_test.dart
@@ -0,0 +1,307 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ES6 extends the \uxxxx escape and also allows \u{xxxxx}.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void testRegExpHelper(RegExp r) {
+  assertTrue(r.hasMatch("foo"));
+  assertTrue(r.hasMatch("boo"));
+  assertFalse(r.hasMatch("moo"));
+}
+
+void TestUnicodeEscapes() {
+  testRegExpHelper(RegExp(r"(\u0066|\u0062)oo"));
+  testRegExpHelper(RegExp(r"(\u0066|\u0062)oo", unicode: true));
+  testRegExpHelper(RegExp(r"(\u{0066}|\u{0062})oo", unicode: true));
+  testRegExpHelper(RegExp(r"(\u{66}|\u{000062})oo", unicode: true));
+
+  // Note that we need \\ inside a string, otherwise it's interpreted as a
+  // unicode escape inside a string.
+  testRegExpHelper(RegExp("(\\u0066|\\u0062)oo"));
+  testRegExpHelper(RegExp("(\\u0066|\\u0062)oo", unicode: true));
+  testRegExpHelper(RegExp("(\\u{0066}|\\u{0062})oo", unicode: true));
+  testRegExpHelper(RegExp("(\\u{66}|\\u{000062})oo", unicode: true));
+
+  // Though, unicode escapes via strings should work too.
+  testRegExpHelper(RegExp("(\u0066|\u0062)oo"));
+  testRegExpHelper(RegExp("(\u0066|\u0062)oo", unicode: true));
+  testRegExpHelper(RegExp("(\u{0066}|\u{0062})oo", unicode: true));
+  testRegExpHelper(RegExp("(\u{66}|\u{000062})oo", unicode: true));
+}
+
+void TestUnicodeEscapesInCharacterClasses() {
+  testRegExpHelper(RegExp(r"[\u0062-\u0066]oo"));
+  testRegExpHelper(RegExp(r"[\u0062-\u0066]oo", unicode: true));
+  testRegExpHelper(RegExp(r"[\u{0062}-\u{0066}]oo", unicode: true));
+  testRegExpHelper(RegExp(r"[\u{62}-\u{000066}]oo", unicode: true));
+
+  // Note that we need \\ inside a string, otherwise it's interpreted as a
+  // unicode escape inside a string.
+  testRegExpHelper(RegExp("[\\u0062-\\u0066]oo"));
+  testRegExpHelper(RegExp("[\\u0062-\\u0066]oo", unicode: true));
+  testRegExpHelper(RegExp("[\\u{0062}-\\u{0066}]oo", unicode: true));
+  testRegExpHelper(RegExp("[\\u{62}-\\u{000066}]oo", unicode: true));
+
+  // Though, unicode escapes via strings should work too.
+  testRegExpHelper(RegExp("[\u0062-\u0066]oo"));
+  testRegExpHelper(RegExp("[\u0062-\u0066]oo", unicode: true));
+  testRegExpHelper(RegExp("[\u{0062}-\u{0066}]oo", unicode: true));
+  testRegExpHelper(RegExp("[\u{62}-\u{000066}]oo", unicode: true));
+}
+
+void TestBraceEscapesWithoutUnicodeFlag() {
+  // \u followed by illegal escape will be parsed as u. {x} will be the
+  // character count.
+  void helper1(RegExp r) {
+    assertFalse(r.hasMatch("fbar"));
+    assertFalse(r.hasMatch("fubar"));
+    assertTrue(r.hasMatch("fuubar"));
+    assertFalse(r.hasMatch("fuuubar"));
+  }
+
+  helper1(RegExp(r"f\u{2}bar"));
+  helper1(RegExp("f\\u{2}bar"));
+
+  void helper2(RegExp r) {
+    assertFalse(r.hasMatch("fbar"));
+    assertTrue(r.hasMatch("fubar"));
+    assertTrue(r.hasMatch("fuubar"));
+    assertFalse(r.hasMatch("fuuubar"));
+  }
+
+  helper2(RegExp(r"f\u{1,2}bar"));
+  helper2(RegExp("f\\u{1,2}bar"));
+
+  void helper3(RegExp r) {
+    assertTrue(r.hasMatch("u"));
+    assertTrue(r.hasMatch("{"));
+    assertTrue(r.hasMatch("2"));
+    assertTrue(r.hasMatch("}"));
+    assertFalse(r.hasMatch("q"));
+    assertFalse(r.hasMatch("("));
+    assertFalse(r.hasMatch(")"));
+  }
+
+  helper3(RegExp(r"[\u{2}]"));
+  helper3(RegExp("[\\u{2}]"));
+}
+
+void TestInvalidEscapes() {
+  // Without the u flag, invalid unicode escapes and other invalid escapes are
+  // treated as identity escapes.
+  void helper1(RegExp r) {
+    assertTrue(r.hasMatch("firstuxz89second"));
+  }
+
+  helper1(RegExp(r"first\u\x\z\8\9second"));
+  helper1(RegExp("first\\u\\x\\z\\8\\9second"));
+
+  void helper2(RegExp r) {
+    assertTrue(r.hasMatch("u"));
+    assertTrue(r.hasMatch("x"));
+    assertTrue(r.hasMatch("z"));
+    assertTrue(r.hasMatch("8"));
+    assertTrue(r.hasMatch("9"));
+    assertFalse(r.hasMatch("q"));
+    assertFalse(r.hasMatch("7"));
+  }
+
+  helper2(RegExp(r"[\u\x\z\8\9]"));
+  helper2(RegExp("[\\u\\x\\z\\8\\9]"));
+
+  // However, with the u flag, these are treated as invalid escapes.
+  assertThrows(() => RegExp(r"\u", unicode: true));
+  assertThrows(() => RegExp(r"\u12", unicode: true));
+  assertThrows(() => RegExp(r"\ufoo", unicode: true));
+  assertThrows(() => RegExp(r"\x", unicode: true));
+  assertThrows(() => RegExp(r"\xfoo", unicode: true));
+  assertThrows(() => RegExp(r"\z", unicode: true));
+  assertThrows(() => RegExp(r"\8", unicode: true));
+  assertThrows(() => RegExp(r"\9", unicode: true));
+
+  assertThrows(() => RegExp("\\u", unicode: true));
+  assertThrows(() => RegExp("\\u12", unicode: true));
+  assertThrows(() => RegExp("\\ufoo", unicode: true));
+  assertThrows(() => RegExp("\\x", unicode: true));
+  assertThrows(() => RegExp("\\xfoo", unicode: true));
+  assertThrows(() => RegExp("\\z", unicode: true));
+  assertThrows(() => RegExp("\\8", unicode: true));
+  assertThrows(() => RegExp("\\9", unicode: true));
+}
+
+void TestTooBigHexEscape() {
+  // The hex number inside \u{} has a maximum value.
+  RegExp(r"\u{10ffff}", unicode: true);
+  RegExp("\\u{10ffff}", unicode: true);
+  assertThrows(() => RegExp(r"\u{110000}", unicode: true));
+  assertThrows(() => RegExp("\\u{110000}", unicode: true));
+
+  // Without the u flag, they're of course fine ({x} is the count).
+  RegExp(r"\u{110000}");
+  RegExp("\\u{110000}");
+}
+
+void TestSyntaxEscapes() {
+  // Syntax escapes work the same with or without the u flag.
+  void helper(RegExp r) {
+    assertTrue(r.hasMatch("foo[bar"));
+    assertFalse(r.hasMatch("foo]bar"));
+  }
+
+  helper(RegExp(r"foo\[bar"));
+  helper(RegExp("foo\\[bar"));
+  helper(RegExp(r"foo\[bar", unicode: true));
+  helper(RegExp("foo\\[bar", unicode: true));
+}
+
+void TestUnicodeSurrogates() {
+  // U+10E6D corresponds to the surrogate pair [U+D803, U+DE6D].
+  void helper(RegExp r) {
+    assertTrue(r.hasMatch("foo\u{10e6d}bar"));
+  }
+
+  helper(RegExp(r"foo\ud803\ude6dbar", unicode: true));
+  helper(RegExp("foo\\ud803\\ude6dbar", unicode: true));
+}
+
+void main() {
+  TestUnicodeEscapes();
+  TestUnicodeEscapesInCharacterClasses();
+  TestBraceEscapesWithoutUnicodeFlag();
+  TestInvalidEscapes();
+  TestTooBigHexEscape();
+  TestSyntaxEscapes();
+  TestUnicodeSurrogates();
+
+  // Non-BMP patterns.
+  // Single character atom.
+  assertTrue(RegExp("\u{12345}", unicode: true).hasMatch("\u{12345}"));
+  assertTrue(RegExp(r"\u{12345}", unicode: true).hasMatch("\u{12345}"));
+  assertTrue(RegExp(r"\u{12345}", unicode: true).hasMatch("\ud808\udf45"));
+  assertTrue(RegExp(r"\u{12345}", unicode: true).hasMatch("\ud808\udf45"));
+  assertFalse(RegExp(r"\u{12345}", unicode: true).hasMatch("\udf45"));
+  assertFalse(RegExp(r"\u{12345}", unicode: true).hasMatch("\udf45"));
+
+  // Multi-character atom.
+  assertTrue(RegExp(r"\u{12345}\u{23456}", unicode: true)
+      .hasMatch("a\u{12345}\u{23456}b"));
+  assertTrue(RegExp(r"\u{12345}\u{23456}", unicode: true)
+      .hasMatch("b\u{12345}\u{23456}c"));
+  assertFalse(RegExp(r"\u{12345}\u{23456}", unicode: true)
+      .hasMatch("a\udf45\u{23456}b"));
+  assertFalse(RegExp(r"\u{12345}\u{23456}", unicode: true)
+      .hasMatch("b\udf45\u{23456}c"));
+
+  // Disjunction.
+  assertTrue(RegExp(r"\u{12345}(?:\u{23456})", unicode: true)
+      .hasMatch("a\u{12345}\u{23456}b"));
+  assertTrue(RegExp(r"\u{12345}(?:\u{23456})", unicode: true)
+      .hasMatch("b\u{12345}\u{23456}c"));
+  assertFalse(RegExp(r"\u{12345}(?:\u{23456})", unicode: true)
+      .hasMatch("a\udf45\u{23456}b"));
+  assertFalse(RegExp(r"\u{12345}(?:\u{23456})", unicode: true)
+      .hasMatch("b\udf45\u{23456}c"));
+
+  // Alternative.
+  assertTrue(
+      RegExp(r"\u{12345}|\u{23456}", unicode: true).hasMatch("a\u{12345}b"));
+  assertTrue(
+      RegExp(r"\u{12345}|\u{23456}", unicode: true).hasMatch("b\u{23456}c"));
+  assertFalse(
+      RegExp(r"\u{12345}|\u{23456}", unicode: true).hasMatch("a\udf45\ud84db"));
+  assertFalse(
+      RegExp(r"\u{12345}|\u{23456}", unicode: true).hasMatch("b\udf45\ud808c"));
+
+  // Capture.
+  assertTrue(RegExp("(\u{12345}|\u{23456}).\\1", unicode: true)
+      .hasMatch("\u{12345}b\u{12345}"));
+  assertTrue(RegExp(r"(\u{12345}|\u{23456}).\1", unicode: true)
+      .hasMatch("\u{12345}b\u{12345}"));
+  assertFalse(RegExp("(\u{12345}|\u{23456}).\\1", unicode: true)
+      .hasMatch("\u{12345}b\u{23456}"));
+  assertFalse(RegExp(r"(\u{12345}|\u{23456}).\1", unicode: true)
+      .hasMatch("\u{12345}b\u{23456}"));
+
+  // Quantifier.
+  assertTrue(RegExp("\u{12345}{3}", unicode: true)
+      .hasMatch("\u{12345}\u{12345}\u{12345}"));
+  assertTrue(RegExp(r"\u{12345}{3}", unicode: true)
+      .hasMatch("\u{12345}\u{12345}\u{12345}"));
+  assertTrue(RegExp("\u{12345}{3}").hasMatch("\u{12345}\udf45\udf45"));
+  assertFalse(RegExp(r"\ud808\udf45{3}", unicode: true)
+      .hasMatch("\u{12345}\udf45\udf45"));
+  assertTrue(RegExp(r"\ud808\udf45{3}", unicode: true)
+      .hasMatch("\u{12345}\u{12345}\u{12345}"));
+  assertFalse(
+      RegExp("\u{12345}{3}", unicode: true).hasMatch("\u{12345}\udf45\udf45"));
+  assertFalse(
+      RegExp(r"\u{12345}{3}", unicode: true).hasMatch("\u{12345}\udf45\udf45"));
+
+  // Literal surrogates.
+  shouldBe(
+      RegExp("\ud800\udc00+", unicode: true).firstMatch("\u{10000}\u{10000}"),
+      ["\u{10000}\u{10000}"]);
+  shouldBe(
+      RegExp("\\ud800\\udc00+", unicode: true).firstMatch("\u{10000}\u{10000}"),
+      ["\u{10000}\u{10000}"]);
+
+  shouldBe(
+      RegExp("[\\ud800\\udc03-\\ud900\\udc01\]+", unicode: true)
+          .firstMatch("\u{10003}\u{50001}"),
+      ["\u{10003}\u{50001}"]);
+  shouldBe(
+      RegExp("[\ud800\udc03-\u{50001}\]+", unicode: true)
+          .firstMatch("\u{10003}\u{50001}"),
+      ["\u{10003}\u{50001}"]);
+
+  // Unicode escape sequences to represent a non-BMP character cannot have
+  // mixed notation, and must follow the rules for RegExpUnicodeEscapeSequence.
+  assertThrows(() => RegExp("[\\ud800\udc03-\ud900\\udc01\]+", unicode: true));
+  assertNull(
+      RegExp("\\ud800\udc00+", unicode: true).firstMatch("\u{10000}\u{10000}"));
+  assertNull(
+      RegExp("\ud800\\udc00+", unicode: true).firstMatch("\u{10000}\u{10000}"));
+
+  assertNull(RegExp("[\\ud800\udc00]", unicode: true).firstMatch("\u{10000}"));
+  assertNull(
+      RegExp("[\\{ud800}\udc00]", unicode: true).firstMatch("\u{10000}"));
+  assertNull(RegExp("[\ud800\\udc00]", unicode: true).firstMatch("\u{10000}"));
+  assertNull(
+      RegExp("[\ud800\\{udc00}]", unicode: true).firstMatch("\u{10000}"));
+
+  assertNull(RegExp(r"\u{d800}\u{dc00}+", unicode: true)
+      .firstMatch("\ud800\udc00\udc00"));
+  assertNull(RegExp(r"\ud800\u{dc00}+", unicode: true)
+      .firstMatch("\ud800\udc00\udc00"));
+  assertNull(RegExp(r"\u{d800}\udc00+", unicode: true)
+      .firstMatch("\ud800\udc00\udc00"));
+}
diff --git a/tests/corelib_2/regexp/unicode-property-binary_test.dart b/tests/corelib_2/regexp/unicode-property-binary_test.dart
new file mode 100644
index 0000000..b8981a7
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-property-binary_test.dart
@@ -0,0 +1,201 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  void t(RegExp re, String s) {
+    assertTrue(re.hasMatch(s));
+  }
+
+  void f(RegExp re, String s) {
+    assertFalse(re.hasMatch(s));
+  }
+
+  assertThrows(() => RegExp("\\p{Hiragana}", unicode: true));
+  assertThrows(() => RegExp("\\p{Bidi_Class}", unicode: true));
+  assertThrows(() => RegExp("\\p{Bidi_C=False}", unicode: true));
+  assertThrows(() => RegExp("\\P{Bidi_Control=Y}", unicode: true));
+  assertThrows(() => RegExp("\\p{AHex=Yes}", unicode: true));
+
+  assertThrows(() => RegExp("\\p{Composition_Exclusion}", unicode: true));
+  assertThrows(() => RegExp("\\p{CE}", unicode: true));
+  assertThrows(() => RegExp("\\p{Full_Composition_Exclusion}", unicode: true));
+  assertThrows(() => RegExp("\\p{Comp_Ex}", unicode: true));
+  assertThrows(() => RegExp("\\p{Grapheme_Link}", unicode: true));
+  assertThrows(() => RegExp("\\p{Gr_Link}", unicode: true));
+  assertThrows(() => RegExp("\\p{Hyphen}", unicode: true));
+  assertThrows(() => RegExp("\\p{NFD_Inert}", unicode: true));
+  assertThrows(() => RegExp("\\p{NFDK_Inert}", unicode: true));
+  assertThrows(() => RegExp("\\p{NFC_Inert}", unicode: true));
+  assertThrows(() => RegExp("\\p{NFKC_Inert}", unicode: true));
+  assertThrows(() => RegExp("\\p{Segment_Starter}", unicode: true));
+
+  t(RegExp(r"\p{Alphabetic}", unicode: true), "æ");
+  f(RegExp(r"\p{Alpha}", unicode: true), "1");
+
+  t(RegExp(r"\p{ASCII_Hex_Digit}", unicode: true), "f");
+  f(RegExp(r"\p{AHex}", unicode: true), "g");
+
+  t(RegExp(r"\p{Bidi_Control}", unicode: true), "\u200e");
+  f(RegExp(r"\p{Bidi_C}", unicode: true), "g");
+
+  t(RegExp(r"\p{Bidi_Mirrored}", unicode: true), "(");
+  f(RegExp(r"\p{Bidi_M}", unicode: true), "-");
+
+  t(RegExp(r"\p{Case_Ignorable}", unicode: true), "\u02b0");
+  f(RegExp(r"\p{CI}", unicode: true), "a");
+
+  t(RegExp(r"\p{Changes_When_Casefolded}", unicode: true), "B");
+  f(RegExp(r"\p{CWCF}", unicode: true), "1");
+
+  t(RegExp(r"\p{Changes_When_Casemapped}", unicode: true), "b");
+  f(RegExp(r"\p{CWCM}", unicode: true), "1");
+
+  t(RegExp(r"\p{Changes_When_Lowercased}", unicode: true), "B");
+  f(RegExp(r"\p{CWL}", unicode: true), "1");
+
+  t(RegExp(r"\p{Changes_When_Titlecased}", unicode: true), "b");
+  f(RegExp(r"\p{CWT}", unicode: true), "1");
+
+  t(RegExp(r"\p{Changes_When_Uppercased}", unicode: true), "b");
+  f(RegExp(r"\p{CWU}", unicode: true), "1");
+
+  t(RegExp(r"\p{Dash}", unicode: true), "-");
+  f(RegExp(r"\p{Dash}", unicode: true), "1");
+
+  t(RegExp(r"\p{Default_Ignorable_Code_Point}", unicode: true), "\u00ad");
+  f(RegExp(r"\p{DI}", unicode: true), "1");
+
+  t(RegExp(r"\p{Deprecated}", unicode: true), "\u17a3");
+  f(RegExp(r"\p{Dep}", unicode: true), "1");
+
+  t(RegExp(r"\p{Diacritic}", unicode: true), "\u0301");
+  f(RegExp(r"\p{Dia}", unicode: true), "1");
+
+  t(RegExp(r"\p{Emoji}", unicode: true), "\u2603");
+  f(RegExp(r"\p{Emoji}", unicode: true), "x");
+
+  t(RegExp(r"\p{Emoji_Component}", unicode: true), "\u{1F1E6}");
+  f(RegExp(r"\p{Emoji_Component}", unicode: true), "x");
+
+  t(RegExp(r"\p{Emoji_Modifier_Base}", unicode: true), "\u{1F6CC}");
+  f(RegExp(r"\p{Emoji_Modifier_Base}", unicode: true), "x");
+
+  t(RegExp(r"\p{Emoji_Modifier}", unicode: true), "\u{1F3FE}");
+  f(RegExp(r"\p{Emoji_Modifier}", unicode: true), "x");
+
+  t(RegExp(r"\p{Emoji_Presentation}", unicode: true), "\u{1F308}");
+  f(RegExp(r"\p{Emoji_Presentation}", unicode: true), "x");
+
+  t(RegExp(r"\p{Extender}", unicode: true), "\u3005");
+  f(RegExp(r"\p{Ext}", unicode: true), "x");
+
+  t(RegExp(r"\p{Grapheme_Base}", unicode: true), " ");
+  f(RegExp(r"\p{Gr_Base}", unicode: true), "\u0010");
+
+  t(RegExp(r"\p{Grapheme_Extend}", unicode: true), "\u0300");
+  f(RegExp(r"\p{Gr_Ext}", unicode: true), "x");
+
+  t(RegExp(r"\p{Hex_Digit}", unicode: true), "a");
+  f(RegExp(r"\p{Hex}", unicode: true), "g");
+
+  t(RegExp(r"\p{ID_Continue}", unicode: true), "1");
+  f(RegExp(r"\p{IDC}", unicode: true), ".");
+
+  t(RegExp(r"\p{ID_Start}", unicode: true), "a");
+  f(RegExp(r"\p{IDS}", unicode: true), "1");
+
+  t(RegExp(r"\p{Ideographic}", unicode: true), "漢");
+  f(RegExp(r"\p{Ideo}", unicode: true), "H");
+
+  t(RegExp(r"\p{IDS_Binary_Operator}", unicode: true), "\u2FF0");
+  f(RegExp(r"\p{IDSB}", unicode: true), "a");
+
+  t(RegExp(r"\p{IDS_Trinary_Operator}", unicode: true), "\u2FF2");
+  f(RegExp(r"\p{IDST}", unicode: true), "a");
+
+  t(RegExp(r"\p{Join_Control}", unicode: true), "\u200c");
+  f(RegExp(r"\p{Join_C}", unicode: true), "a");
+
+  t(RegExp(r"\p{Logical_Order_Exception}", unicode: true), "\u0e40");
+  f(RegExp(r"\p{LOE}", unicode: true), "a");
+
+  t(RegExp(r"\p{Lowercase}", unicode: true), "a");
+  f(RegExp(r"\p{Lower}", unicode: true), "A");
+
+  t(RegExp(r"\p{Math}", unicode: true), "=");
+  f(RegExp(r"\p{Math}", unicode: true), "A");
+
+  t(RegExp(r"\p{Noncharacter_Code_Point}", unicode: true), "\uFDD0");
+  f(RegExp(r"\p{NChar}", unicode: true), "A");
+
+  t(RegExp(r"\p{Pattern_Syntax}", unicode: true), "\u0021");
+  f(RegExp(r"\p{NChar}", unicode: true), "A");
+
+  t(RegExp(r"\p{Pattern_White_Space}", unicode: true), "\u0009");
+  f(RegExp(r"\p{Pat_Syn}", unicode: true), "A");
+
+  t(RegExp(r"\p{Quotation_Mark}", unicode: true), "'");
+  f(RegExp(r"\p{QMark}", unicode: true), "A");
+
+  t(RegExp(r"\p{Radical}", unicode: true), "\u2FAD");
+  f(RegExp(r"\p{Radical}", unicode: true), "A");
+
+  t(RegExp(r"\p{Regional_Indicator}", unicode: true), "\u{1F1E6}");
+  f(RegExp(r"\p{Regional_Indicator}", unicode: true), "A");
+
+  t(RegExp(r"\p{Sentence_Terminal}", unicode: true), "!");
+  f(RegExp(r"\p{STerm}", unicode: true), "A");
+
+  t(RegExp(r"\p{Soft_Dotted}", unicode: true), "i");
+  f(RegExp(r"\p{SD}", unicode: true), "A");
+
+  t(RegExp(r"\p{Terminal_Punctuation}", unicode: true), ".");
+  f(RegExp(r"\p{Term}", unicode: true), "A");
+
+  t(RegExp(r"\p{Unified_Ideograph}", unicode: true), "\u4e00");
+  f(RegExp(r"\p{UIdeo}", unicode: true), "A");
+
+  t(RegExp(r"\p{Uppercase}", unicode: true), "A");
+  f(RegExp(r"\p{Upper}", unicode: true), "a");
+
+  t(RegExp(r"\p{Variation_Selector}", unicode: true), "\uFE00");
+  f(RegExp(r"\p{VS}", unicode: true), "A");
+
+  t(RegExp(r"\p{White_Space}", unicode: true), " ");
+  f(RegExp(r"\p{WSpace}", unicode: true), "A");
+
+  t(RegExp(r"\p{XID_Continue}", unicode: true), "1");
+  f(RegExp(r"\p{XIDC}", unicode: true), " ");
+
+  t(RegExp(r"\p{XID_Start}", unicode: true), "A");
+  f(RegExp(r"\p{XIDS}", unicode: true), " ");
+}
diff --git a/tests/corelib_2/regexp/unicode-property-char-class_test.dart b/tests/corelib_2/regexp/unicode-property-char-class_test.dart
new file mode 100644
index 0000000..db87fad
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-property-char-class_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  assertThrows(() => RegExp("[\\p]", unicode: true));
+  assertThrows(() => RegExp("[\\p{garbage}]", unicode: true));
+  assertThrows(() => RegExp("[\\p{}]", unicode: true));
+  assertThrows(() => RegExp("[\\p{]", unicode: true));
+  assertThrows(() => RegExp("[\\p}]", unicode: true));
+  assertThrows(() => RegExp("^[\\p{Lu}-\\p{Ll}]+\$", unicode: true));
+
+  assertTrue(RegExp(r"^[\p{Lu}\p{Ll}]+$", unicode: true).hasMatch("ABCabc"));
+  assertTrue(RegExp(r"^[\p{Lu}-]+$", unicode: true).hasMatch("ABC-"));
+  assertFalse(RegExp(r"^[\P{Lu}\p{Ll}]+$", unicode: true).hasMatch("ABCabc"));
+  assertTrue(RegExp(r"^[\P{Lu}\p{Ll}]+$", unicode: true).hasMatch("abc"));
+  assertTrue(RegExp(r"^[\P{Lu}]+$", unicode: true).hasMatch("abc123"));
+  assertFalse(RegExp(r"^[\P{Lu}]+$", unicode: true).hasMatch("XYZ"));
+  assertTrue(RegExp(r"[\p{Math}]", unicode: true).hasMatch("+"));
+  assertTrue(RegExp(r"[\P{Bidi_M}]", unicode: true).hasMatch(" "));
+  assertTrue(RegExp(r"[\p{Hex}]", unicode: true).hasMatch("A"));
+
+  assertTrue(RegExp(r"^[^\P{Lu}]+$", unicode: true).hasMatch("XYZ"));
+  assertFalse(RegExp(r"^[^\p{Lu}\p{Ll}]+$", unicode: true).hasMatch("abc"));
+  assertFalse(RegExp(r"^[^\p{Lu}\p{Ll}]+$", unicode: true).hasMatch("ABC"));
+  assertTrue(RegExp(r"^[^\p{Lu}\p{Ll}]+$", unicode: true).hasMatch("123"));
+  assertTrue(RegExp(r"^[^\p{Lu}\P{Ll}]+$", unicode: true).hasMatch("abc"));
+}
diff --git a/tests/corelib_2/regexp/unicode-property-enumerated_test.dart b/tests/corelib_2/regexp/unicode-property-enumerated_test.dart
new file mode 100644
index 0000000..cfb3e02
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-property-enumerated_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  assertThrows(() => RegExp("\\p{Bidi_Class=L}+", unicode: true));
+  assertThrows(() => RegExp("\\p{bc=Left_To_Right}+", unicode: true));
+  assertThrows(() => RegExp("\\p{bc=AL}+", unicode: true));
+  assertThrows(() => RegExp("\\p{bc=Arabic_Letter}+", unicode: true));
+
+  assertThrows(() => RegExp("\\p{Line_Break=Glue}", unicode: true));
+  assertThrows(() => RegExp("\\p{lb=AL}", unicode: true));
+
+  assertThrows(() => RegExp("\\p{Block=}", unicode: true));
+  assertThrows(() => RegExp("\\p{=}", unicode: true));
+  assertThrows(() => RegExp("\\p{=L}", unicode: true));
+  assertThrows(() => RegExp("\\p{=Hiragana}", unicode: true));
+  assertThrows(() => RegExp("\\p{Block=CJK=}", unicode: true));
+
+  assertThrows(() => RegExp("\\p{Age=V8_0}", unicode: true));
+  assertDoesNotThrow(
+      () => RegExp("\\p{General_Category=Letter}", unicode: true));
+  assertDoesNotThrow(() => RegExp("\\p{gc=L}", unicode: true));
+  assertThrows(
+      () => RegExp("\\p{General_Category_Mask=Letter}", unicode: true));
+  assertThrows(() => RegExp("\\p{gcm=L}", unicode: true));
+}
diff --git a/tests/corelib_2/regexp/unicode-property-exact-match_test.dart b/tests/corelib_2/regexp/unicode-property-exact-match_test.dart
new file mode 100644
index 0000000..bbf99d0
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-property-exact-match_test.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  assertThrows(() => RegExp("\\p{In CJK}", unicode: true));
+  assertThrows(() => RegExp("\\p{InCJKUnifiedIdeographs}", unicode: true));
+  assertThrows(() => RegExp("\\p{InCJK}", unicode: true));
+  assertThrows(() => RegExp("\\p{InCJK_Unified_Ideographs}", unicode: true));
+
+  assertThrows(() => RegExp("\\p{InCyrillic_Sup}", unicode: true));
+  assertThrows(() => RegExp("\\p{InCyrillic_Supplement}", unicode: true));
+  assertThrows(() => RegExp("\\p{InCyrillic_Supplementary}", unicode: true));
+  assertThrows(() => RegExp("\\p{InCyrillicSupplementary}", unicode: true));
+  assertThrows(() => RegExp("\\p{InCyrillic_supplementary}", unicode: true));
+
+  assertDoesNotThrow(() => RegExp("\\p{C}", unicode: true));
+  assertDoesNotThrow(() => RegExp("\\p{Other}", unicode: true));
+  assertDoesNotThrow(() => RegExp("\\p{Cc}", unicode: true));
+  assertDoesNotThrow(() => RegExp("\\p{Control}", unicode: true));
+  assertDoesNotThrow(() => RegExp("\\p{cntrl}", unicode: true));
+  assertDoesNotThrow(() => RegExp("\\p{M}", unicode: true));
+  assertDoesNotThrow(() => RegExp("\\p{Mark}", unicode: true));
+  assertDoesNotThrow(() => RegExp("\\p{Combining_Mark}", unicode: true));
+  assertThrows(() => RegExp("\\p{Combining Mark}", unicode: true));
+
+  assertDoesNotThrow(() => RegExp("\\p{Script=Copt}", unicode: true));
+  assertThrows(() => RegExp("\\p{Coptic}", unicode: true));
+  assertThrows(() => RegExp("\\p{Qaac}", unicode: true));
+  assertThrows(() => RegExp("\\p{Egyp}", unicode: true));
+  assertDoesNotThrow(
+      () => RegExp("\\p{Script=Egyptian_Hieroglyphs}", unicode: true));
+  assertThrows(() => RegExp("\\p{EgyptianHieroglyphs}", unicode: true));
+
+  assertThrows(() => RegExp("\\p{BidiClass=LeftToRight}", unicode: true));
+  assertThrows(() => RegExp("\\p{BidiC=LeftToRight}", unicode: true));
+  assertThrows(() => RegExp("\\p{bidi_c=Left_To_Right}", unicode: true));
+
+  assertThrows(() => RegExp("\\p{Block=CJK}", unicode: true));
+  assertThrows(() => RegExp("\\p{Block = CJK}", unicode: true));
+  assertThrows(() => RegExp("\\p{Block=cjk}", unicode: true));
+  assertThrows(() => RegExp("\\p{BLK=CJK}", unicode: true));
+}
diff --git a/tests/corelib_2/regexp/unicode-property-general-category_test.dart b/tests/corelib_2/regexp/unicode-property-general-category_test.dart
new file mode 100644
index 0000000..cb94cac
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-property-general-category_test.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  assertThrows(() => RegExp("\\p", unicode: true));
+  assertThrows(() => RegExp("\\p{garbage}", unicode: true));
+  assertThrows(() => RegExp("\\p{}", unicode: true));
+  assertThrows(() => RegExp("\\p{", unicode: true));
+  assertThrows(() => RegExp("\\p}", unicode: true));
+  assertThrows(() => RegExp("\\pL", unicode: true));
+  assertThrows(() => RegExp("\\P", unicode: true));
+  assertThrows(() => RegExp("\\P{garbage}", unicode: true));
+  assertThrows(() => RegExp("\\P{}", unicode: true));
+  assertThrows(() => RegExp("\\P{", unicode: true));
+  assertThrows(() => RegExp("\\P}", unicode: true));
+  assertThrows(() => RegExp("\\PL", unicode: true));
+
+  assertTrue(RegExp(r"\p{Ll}", unicode: true).hasMatch("a"));
+  assertFalse(RegExp(r"\P{Ll}", unicode: true).hasMatch("a"));
+  assertTrue(RegExp(r"\P{Ll}", unicode: true).hasMatch("A"));
+  assertFalse(RegExp(r"\p{Ll}", unicode: true).hasMatch("A"));
+  assertTrue(RegExp(r"\p{Ll}", unicode: true).hasMatch("\u{1D7BE}"));
+  assertFalse(RegExp(r"\P{Ll}", unicode: true).hasMatch("\u{1D7BE}"));
+  assertFalse(RegExp(r"\p{Ll}", unicode: true).hasMatch("\u{1D5E3}"));
+  assertTrue(RegExp(r"\P{Ll}", unicode: true).hasMatch("\u{1D5E3}"));
+
+  assertTrue(
+      RegExp(r"\p{Ll}", caseSensitive: false, unicode: true).hasMatch("a"));
+  assertTrue(RegExp(r"\p{Ll}", caseSensitive: false, unicode: true)
+      .hasMatch("\u{118D4}"));
+  assertTrue(
+      RegExp(r"\p{Ll}", caseSensitive: false, unicode: true).hasMatch("A"));
+  assertTrue(RegExp(r"\p{Ll}", caseSensitive: false, unicode: true)
+      .hasMatch("\u{118B4}"));
+  assertTrue(
+      RegExp(r"\P{Ll}", caseSensitive: false, unicode: true).hasMatch("a"));
+  assertTrue(RegExp(r"\P{Ll}", caseSensitive: false, unicode: true)
+      .hasMatch("\u{118D4}"));
+  assertTrue(
+      RegExp(r"\P{Ll}", caseSensitive: false, unicode: true).hasMatch("A"));
+  assertTrue(RegExp(r"\P{Ll}", caseSensitive: false, unicode: true)
+      .hasMatch("\u{118B4}"));
+
+  assertTrue(RegExp(r"\p{Lu}", unicode: true).hasMatch("A"));
+  assertFalse(RegExp(r"\P{Lu}", unicode: true).hasMatch("A"));
+  assertTrue(RegExp(r"\P{Lu}", unicode: true).hasMatch("a"));
+  assertFalse(RegExp(r"\p{Lu}", unicode: true).hasMatch("a"));
+  assertTrue(RegExp(r"\p{Lu}", unicode: true).hasMatch("\u{1D5E3}"));
+  assertFalse(RegExp(r"\P{Lu}", unicode: true).hasMatch("\u{1D5E3}"));
+  assertFalse(RegExp(r"\p{Lu}", unicode: true).hasMatch("\u{1D7BE}"));
+  assertTrue(RegExp(r"\P{Lu}", unicode: true).hasMatch("\u{1D7BE}"));
+
+  assertTrue(
+      RegExp(r"\p{Lu}", caseSensitive: false, unicode: true).hasMatch("a"));
+  assertTrue(RegExp(r"\p{Lu}", caseSensitive: false, unicode: true)
+      .hasMatch("\u{118D4}"));
+  assertTrue(
+      RegExp(r"\p{Lu}", caseSensitive: false, unicode: true).hasMatch("A"));
+  assertTrue(RegExp(r"\p{Lu}", caseSensitive: false, unicode: true)
+      .hasMatch("\u{118B4}"));
+  assertTrue(
+      RegExp(r"\P{Lu}", caseSensitive: false, unicode: true).hasMatch("a"));
+  assertTrue(RegExp(r"\P{Lu}", caseSensitive: false, unicode: true)
+      .hasMatch("\u{118D4}"));
+  assertTrue(
+      RegExp(r"\P{Lu}", caseSensitive: false, unicode: true).hasMatch("A"));
+  assertTrue(RegExp(r"\P{Lu}", caseSensitive: false, unicode: true)
+      .hasMatch("\u{118B4}"));
+
+  assertTrue(RegExp(r"\p{Sm}", unicode: true).hasMatch("+"));
+  assertFalse(RegExp(r"\P{Sm}", unicode: true).hasMatch("+"));
+  assertTrue(RegExp(r"\p{Sm}", unicode: true).hasMatch("\u{1D6C1}"));
+  assertFalse(RegExp(r"\P{Sm}", unicode: true).hasMatch("\u{1D6C1}"));
+
+  assertFalse(RegExp(r"\p{L}", unicode: true).hasMatch("\uA6EE"));
+  assertTrue(RegExp(r"\P{L}", unicode: true).hasMatch("\uA6EE"));
+
+  assertTrue(RegExp(r"\p{Lowercase_Letter}", unicode: true).hasMatch("a"));
+  assertTrue(RegExp(r"\p{Math_Symbol}", unicode: true).hasMatch("+"));
+
+  assertTrue(RegExp(r"\p{gc=Ll}", unicode: true).hasMatch("a"));
+  assertTrue(
+      RegExp(r"\p{General_Category=Math_Symbol}", unicode: true).hasMatch("+"));
+  assertTrue(RegExp(r"\p{General_Category=L}", unicode: true).hasMatch("X"));
+}
diff --git a/tests/corelib_2/regexp/unicode-property-invalid_test.dart b/tests/corelib_2/regexp/unicode-property-invalid_test.dart
new file mode 100644
index 0000000..8dddbc1
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-property-invalid_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  assertThrows(() => RegExp("\p{Block=ASCII}+", unicode: true));
+  assertThrows(() => RegExp("\p{Block=ASCII}+", unicode: true));
+  assertThrows(() => RegExp("\p{Block=Basic_Latin}+", unicode: true));
+  assertThrows(() => RegExp("\p{Block=Basic_Latin}+", unicode: true));
+
+  assertThrows(() => RegExp("\p{blk=CJK}+", unicode: true));
+  assertThrows(() => RegExp("\p{blk=CJK_Unified_Ideographs}+", unicode: true));
+  assertThrows(() => RegExp("\p{blk=CJK}+", unicode: true));
+  assertThrows(() => RegExp("\p{blk=CJK_Unified_Ideographs}+", unicode: true));
+
+  assertThrows(() => RegExp("\p{Block=ASCII}+", unicode: true));
+  assertThrows(() => RegExp("\p{Block=ASCII}+", unicode: true));
+  assertThrows(() => RegExp("\p{Block=Basic_Latin}+", unicode: true));
+  assertThrows(() => RegExp("\p{Block=Basic_Latin}+", unicode: true));
+
+  assertThrows(() => RegExp("\p{NFKD_Quick_Check=Y}+", unicode: true));
+  assertThrows(() => RegExp("\p{NFKD_QC=Yes}+", unicode: true));
+
+  assertThrows(() => RegExp("\p{Numeric_Type=Decimal}+", unicode: true));
+  assertThrows(() => RegExp("\p{nt=De}+", unicode: true));
+
+  assertThrows(() => RegExp("\p{Bidi_Class=Arabic_Letter}+", unicode: true));
+  assertThrows(() => RegExp("\p{Bidi_Class=AN}+", unicode: true));
+
+  assertThrows(() => RegExp("\p{ccc=OV}+", unicode: true));
+
+  assertThrows(() => RegExp("\p{Sentence_Break=Format}+", unicode: true));
+
+  assertThrows(() => RegExp("\\p{In}", unicode: true));
+  assertThrows(() => RegExp("\\pI", unicode: true));
+  assertThrows(() => RegExp("\\p{I}", unicode: true));
+  assertThrows(() => RegExp("\\p{CJK}", unicode: true));
+
+  assertThrows(() => RegExp("\\p{}", unicode: true));
+}
diff --git a/tests/corelib_2/regexp/unicode-property-scripts_test.dart b/tests/corelib_2/regexp/unicode-property-scripts_test.dart
new file mode 100644
index 0000000..5adec29
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-property-scripts_test.dart
@@ -0,0 +1,77 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  void t(RegExp re, String s) {
+    assertTrue(re.hasMatch(s));
+  }
+
+  void f(RegExp re, String s) {
+    assertFalse(re.hasMatch(s));
+  }
+
+  t(RegExp(r"\p{Script=Common}+", unicode: true), ".");
+  f(RegExp(r"\p{Script=Common}+", unicode: true),
+      "supercalifragilisticexpialidocious");
+
+  t(RegExp(r"\p{Script=Han}+", unicode: true), "话说天下大势,分久必合,合久必分");
+  t(RegExp(r"\p{Script=Hani}+", unicode: true), "吾庄后有一桃园,花开正盛");
+  f(RegExp(r"\p{Script=Han}+", unicode: true), "おはようございます");
+  f(RegExp(r"\p{Script=Hani}+", unicode: true),
+      "Something is rotten in the state of Denmark");
+
+  t(RegExp(r"\p{Script=Latin}+", unicode: true),
+      "Wie froh bin ich, daß ich weg bin!");
+  t(RegExp(r"\p{Script=Latn}+", unicode: true),
+      "It was a bright day in April, and the clocks were striking thirteen");
+  f(RegExp(r"\p{Script=Latin}+", unicode: true), "奔腾千里荡尘埃,渡水登山紫雾开");
+  f(RegExp(r"\p{Script=Latn}+", unicode: true), "いただきます");
+
+  t(RegExp(r"\p{sc=Hiragana}", unicode: true), "いただきます");
+  t(RegExp(r"\p{sc=Hira}", unicode: true), "ありがとうございました");
+  f(RegExp(r"\p{sc=Hiragana}", unicode: true),
+      "Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte");
+  f(RegExp(r"\p{sc=Hira}", unicode: true), "Call me Ishmael");
+
+  t(RegExp(r"\p{sc=Phoenician}", unicode: true), "\u{10900}\u{1091a}");
+  t(RegExp(r"\p{sc=Phnx}", unicode: true), "\u{1091f}\u{10916}");
+  f(RegExp(r"\p{sc=Phoenician}", unicode: true), "Arthur est un perroquet");
+  f(RegExp(r"\p{sc=Phnx}", unicode: true), "设心狠毒非良士,操卓原来一路人");
+
+  t(RegExp(r"\p{sc=Grek}", unicode: true),
+      "ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ");
+  t(RegExp(r"\p{sc=Greek}", unicode: true),
+      "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος");
+  f(RegExp(r"\p{sc=Greek}", unicode: true), "高贤未服英雄志,屈节偏生杰士疑");
+  f(RegExp(r"\p{sc=Greek}", unicode: true),
+      "Mr. Jones, of the Manor Farm, had locked the hen-houses for the night");
+}
diff --git a/tests/corelib_2/regexp/unicode-property-special_test.dart b/tests/corelib_2/regexp/unicode-property-special_test.dart
new file mode 100644
index 0000000..1e0d2c1
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-property-special_test.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  void t(RegExp re, String s) {
+    assertTrue(re.hasMatch(s));
+  }
+
+  void f(RegExp re, String s) {
+    assertFalse(re.hasMatch(s));
+  }
+
+  t(RegExp(r"\p{ASCII}+", unicode: true), "abc123");
+  f(RegExp(r"\p{ASCII}+", unicode: true), "ⓐⓑⓒ①②③");
+  f(RegExp(r"\p{ASCII}+", unicode: true), "🄰🄱🄲①②③");
+  f(RegExp(r"\P{ASCII}+", unicode: true), "abcd123");
+  t(RegExp(r"\P{ASCII}+", unicode: true), "ⓐⓑⓒ①②③");
+  t(RegExp(r"\P{ASCII}+", unicode: true), "🄰🄱🄲①②③");
+
+  f(RegExp(r"[^\p{ASCII}]+", unicode: true), "abc123");
+  f(RegExp(r"[\p{ASCII}]+", unicode: true), "ⓐⓑⓒ①②③");
+  f(RegExp(r"[\p{ASCII}]+", unicode: true), "🄰🄱🄲①②③");
+  t(RegExp(r"[^\P{ASCII}]+", unicode: true), "abcd123");
+  t(RegExp(r"[\P{ASCII}]+", unicode: true), "ⓐⓑⓒ①②③");
+  f(RegExp(r"[^\P{ASCII}]+", unicode: true), "🄰🄱🄲①②③");
+
+  t(RegExp(r"\p{Any}+", unicode: true), "🄰🄱🄲①②③");
+
+  shouldBe(
+      RegExp(r"\p{Any}", unicode: true).firstMatch("\ud800\ud801"), ["\ud800"]);
+  shouldBe(
+      RegExp(r"\p{Any}", unicode: true).firstMatch("\udc00\udc01"), ["\udc00"]);
+  shouldBe(RegExp(r"\p{Any}", unicode: true).firstMatch("\ud800\udc01"),
+      ["\ud800\udc01"]);
+  shouldBe(RegExp(r"\p{Any}", unicode: true).firstMatch("\udc01"), ["\udc01"]);
+
+  f(RegExp(r"\P{Any}+", unicode: true), "123");
+  f(RegExp(r"[\P{Any}]+", unicode: true), "123");
+  t(RegExp(r"[\P{Any}\d]+", unicode: true), "123");
+  t(RegExp(r"[^\P{Any}]+", unicode: true), "123");
+
+  t(RegExp(r"\p{Assigned}+", unicode: true), "123");
+  t(RegExp(r"\p{Assigned}+", unicode: true), "🄰🄱🄲");
+  f(RegExp(r"\p{Assigned}+", unicode: true), "\ufdd0");
+  f(RegExp(r"\p{Assigned}+", unicode: true), "\u{fffff}");
+
+  f(RegExp(r"\P{Assigned}+", unicode: true), "123");
+  f(RegExp(r"\P{Assigned}+", unicode: true), "🄰🄱🄲");
+  t(RegExp(r"\P{Assigned}+", unicode: true), "\ufdd0");
+  t(RegExp(r"\P{Assigned}+", unicode: true), "\u{fffff}");
+  f(RegExp(r"\P{Assigned}", unicode: true), "");
+
+  t(RegExp(r"[^\P{Assigned}]+", unicode: true), "123");
+  f(RegExp(r"[\P{Assigned}]+", unicode: true), "🄰🄱🄲");
+  f(RegExp(r"[^\P{Assigned}]+", unicode: true), "\ufdd0");
+  t(RegExp(r"[\P{Assigned}]+", unicode: true), "\u{fffff}");
+  f(RegExp(r"[\P{Assigned}]", unicode: true), "");
+
+  f(RegExp(r"[^\u1234\p{ASCII}]+", unicode: true), "\u1234");
+  t(RegExp(r"[x\P{ASCII}]+", unicode: true), "x");
+  t(RegExp(r"[\u1234\p{ASCII}]+", unicode: true), "\u1234");
+
+// Contributory binary properties are not supported.
+  assertThrows(() => RegExp("\\p{Other_Alphabetic}", unicode: true));
+  assertThrows(() => RegExp("\\P{OAlpha}", unicode: true));
+  assertThrows(
+      () => RegExp("\\p{Other_Default_Ignorable_Code_Point}", unicode: true));
+  assertThrows(() => RegExp("\\P{ODI}", unicode: true));
+  assertThrows(() => RegExp("\\p{Other_Grapheme_Extend}", unicode: true));
+  assertThrows(() => RegExp("\\P{OGr_Ext}", unicode: true));
+  assertThrows(() => RegExp("\\p{Other_ID_Continue}", unicode: true));
+  assertThrows(() => RegExp("\\P{OIDC}", unicode: true));
+  assertThrows(() => RegExp("\\p{Other_ID_Start}", unicode: true));
+  assertThrows(() => RegExp("\\P{OIDS}", unicode: true));
+  assertThrows(() => RegExp("\\p{Other_Lowercase}", unicode: true));
+  assertThrows(() => RegExp("\\P{OLower}", unicode: true));
+  assertThrows(() => RegExp("\\p{Other_Math}", unicode: true));
+  assertThrows(() => RegExp("\\P{OMath}", unicode: true));
+  assertThrows(() => RegExp("\\p{Other_Uppercase}", unicode: true));
+  assertThrows(() => RegExp("\\P{OUpper}", unicode: true));
+}
diff --git a/tests/corelib_2/regexp/unicode-regexp-backrefs_test.dart b/tests/corelib_2/regexp/unicode-regexp-backrefs_test.dart
new file mode 100644
index 0000000..2fcb7c1
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-regexp-backrefs_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+String replace(String string) {
+  return string
+      .replaceAll("L", "\ud800")
+      .replaceAll("l", "\ud801")
+      .replaceAll("T", "\udc00")
+      .replaceAll(".", "[^]");
+}
+
+void test(List<String> expectation, String regexp_source, String subject) {
+  if (expectation != null) expectation = expectation.map(replace).toList();
+  subject = replace(subject);
+  regexp_source = replace(regexp_source);
+  shouldBe(new RegExp(regexp_source, unicode: true).firstMatch(subject),
+      expectation);
+}
+
+void main() {
+  // Back reference does not end in the middle of a surrogate pair.
+  test(null, "(L)\\1", "LLT");
+  test(["LLTLl", "L", "l"], "(L).*\\1(.)", "LLTLl");
+  test(null, "(aL).*\\1", "aLaLT");
+  test(["aLaLTaLl", "aL", "l"], "(aL).*\\1(.)", "aLaLTaLl");
+
+  var s = "TabcLxLTabcLxTabcLTyTabcLz";
+  test([s, "TabcL", "z"], "([^x]+).*\\1(.)", s);
+
+  // Back reference does not start in the middle of a surrogate pair.
+  test(["TLTabTc", "T", "c"], "(T).*\\1(.)", "TLTabTc");
+
+  // Lookbehinds.
+  test(null, "(?<=\\1(T)x)", "LTTx");
+  test(["", "b", "T"], "(?<=(.)\\2.*(T)x)", "bTaLTTx");
+  test(null, "(?<=\\1.*(L)x)", "LTLx");
+  test(["", "b", "L"], "(?<=(.)\\2.*(L)x)", "bLaLTLx");
+
+  test(null, "([^x]+)x*\\1", "LxLT");
+  test(null, "([^x]+)x*\\1", "TxLT");
+  test(null, "([^x]+)x*\\1", "LTxL");
+  test(null, "([^x]+)x*\\1", "LTxT");
+  test(null, "([^x]+)x*\\1", "xLxLT");
+  test(null, "([^x]+)x*\\1", "xTxLT");
+  test(null, "([^x]+)x*\\1", "xLTxL");
+  test(null, "([^x]+)x*\\1", "xLTxT");
+  test(null, "([^x]+)x*\\1", "xxxLxxLTxx");
+  test(null, "([^x]+)x*\\1", "xxxTxxLTxx");
+  test(null, "([^x]+)x*\\1", "xxxLTxxLxx");
+  test(null, "([^x]+)x*\\1", "xxxLTxxTxx");
+  test(["LTTxxLTT", "LTT"], "([^x]+)x*\\1", "xxxLTTxxLTTxx");
+}
diff --git a/tests/corelib_2/regexp/unicode-regexp-ignore-case_test.dart b/tests/corelib_2/regexp/unicode-regexp-ignore-case_test.dart
new file mode 100644
index 0000000..c87047c
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-regexp-ignore-case_test.dart
@@ -0,0 +1,135 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  // Non-unicode use toUpperCase mappings.
+  assertFalse(RegExp(r"[\u00e5]", caseSensitive: false).hasMatch("\u212b"));
+  assertFalse(
+      RegExp(r"[\u212b]", caseSensitive: false).hasMatch("\u00e5\u1234"));
+  assertFalse(RegExp(r"[\u212b]", caseSensitive: false).hasMatch("\u00e5"));
+
+  assertTrue("\u212b".toLowerCase() == "\u00e5");
+  assertTrue("\u00c5".toLowerCase() == "\u00e5");
+  assertTrue("\u00e5".toUpperCase() == "\u00c5");
+
+  // Unicode uses case folding mappings.
+  assertTrue(RegExp(r"\u00e5", caseSensitive: false, unicode: true)
+      .hasMatch("\u212b"));
+  assertTrue(RegExp(r"\u00e5", caseSensitive: false, unicode: true)
+      .hasMatch("\u00c5"));
+  assertTrue(RegExp(r"\u00e5", caseSensitive: false, unicode: true)
+      .hasMatch("\u00e5"));
+  assertTrue(RegExp(r"\u00e5", caseSensitive: false, unicode: true)
+      .hasMatch("\u212b"));
+  assertTrue(RegExp(r"\u00c5", caseSensitive: false, unicode: true)
+      .hasMatch("\u00e5"));
+  assertTrue(RegExp(r"\u00c5", caseSensitive: false, unicode: true)
+      .hasMatch("\u212b"));
+  assertTrue(RegExp(r"\u00c5", caseSensitive: false, unicode: true)
+      .hasMatch("\u00c5"));
+  assertTrue(RegExp(r"\u212b", caseSensitive: false, unicode: true)
+      .hasMatch("\u00c5"));
+  assertTrue(RegExp(r"\u212b", caseSensitive: false, unicode: true)
+      .hasMatch("\u00e5"));
+  assertTrue(RegExp(r"\u212b", caseSensitive: false, unicode: true)
+      .hasMatch("\u212b"));
+
+  // Non-BMP.
+  assertFalse(RegExp(r"\u{10400}", caseSensitive: false).hasMatch("\u{10428}"));
+  assertTrue(RegExp(r"\u{10400}", caseSensitive: false, unicode: true)
+      .hasMatch("\u{10428}"));
+  assertTrue(RegExp(r"\ud801\udc00", caseSensitive: false, unicode: true)
+      .hasMatch("\u{10428}"));
+  assertTrue(RegExp(r"[\u{10428}]", caseSensitive: false, unicode: true)
+      .hasMatch("\u{10400}"));
+  assertTrue(RegExp(r"[\ud801\udc28]", caseSensitive: false, unicode: true)
+      .hasMatch("\u{10400}"));
+  shouldBe(
+      RegExp(r"[\uff40-\u{10428}]+", caseSensitive: false, unicode: true)
+          .firstMatch("\uff21\u{10400}abc"),
+      ["\uff21\u{10400}"]);
+  shouldBe(
+      RegExp(r"[^\uff40-\u{10428}]+", caseSensitive: false, unicode: true)
+          .firstMatch("\uff21\u{10400}abc\uff23"),
+      ["abc"]);
+  shouldBe(
+      RegExp(r"[\u24d5-\uff33]+", caseSensitive: false, unicode: true)
+          .firstMatch("\uff54\uff53\u24bb\u24ba"),
+      ["\uff53\u24bb"]);
+
+  // Full mappings are ignored.
+  assertFalse(
+      RegExp(r"\u00df", caseSensitive: false, unicode: true).hasMatch("SS"));
+  assertFalse(RegExp(r"\u1f8d", caseSensitive: false, unicode: true)
+      .hasMatch("\u1f05\u03b9"));
+
+  // Simple mappings work.
+  assertTrue(RegExp(r"\u1f8d", caseSensitive: false, unicode: true)
+      .hasMatch("\u1f85"));
+
+  // Common mappings work.
+  assertTrue(RegExp(r"\u1f6b", caseSensitive: false, unicode: true)
+      .hasMatch("\u1f63"));
+
+  // Back references.
+  shouldBe(
+      RegExp(r"(.)\1\1", caseSensitive: false, unicode: true)
+          .firstMatch("\u00e5\u212b\u00c5"),
+      ["\u00e5\u212b\u00c5", "\u00e5"]);
+  shouldBe(
+      RegExp(r"(.)\1", caseSensitive: false, unicode: true)
+          .firstMatch("\u{118aa}\u{118ca}"),
+      ["\u{118aa}\u{118ca}", "\u{118aa}"]);
+
+  // Misc.
+  assertTrue(RegExp(r"\u00e5\u00e5\u00e5", caseSensitive: false, unicode: true)
+      .hasMatch("\u212b\u00e5\u00c5"));
+  assertTrue(RegExp(r"AB\u{10400}", caseSensitive: false, unicode: true)
+      .hasMatch("ab\u{10428}"));
+
+  // Non-Latin1 maps to Latin1.
+  shouldBe(
+      RegExp(r"^\u017F", caseSensitive: false, unicode: true).firstMatch("s"),
+      ["s"]);
+  shouldBe(
+      RegExp(r"^\u017F", caseSensitive: false, unicode: true)
+          .firstMatch("s\u1234"),
+      ["s"]);
+  shouldBe(
+      RegExp(r"^a[\u017F]", caseSensitive: false, unicode: true)
+          .firstMatch("as"),
+      ["as"]);
+  shouldBe(
+      RegExp(r"^a[\u017F]", caseSensitive: false, unicode: true)
+          .firstMatch("as\u1234"),
+      ["as"]);
+}
diff --git a/tests/corelib_2/regexp/unicode-regexp-match-index_test.dart b/tests/corelib_2/regexp/unicode-regexp-match-index_test.dart
new file mode 100644
index 0000000..3e69658
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-regexp-match-index_test.dart
@@ -0,0 +1,155 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  // Testing handling of paired and non-paired surrogates in unicode mode
+  var r = new RegExp(r".", unicode: true);
+
+  var m = r.matchAsPrefix("\ud800\udc00\ud801\udc01");
+  shouldBe(m, ["\ud800\udc00"]);
+  assertEquals(m.end, 2);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 1);
+  shouldBe(m, ["\ud800\udc00"]);
+  assertEquals(m.end, 2);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 2);
+  shouldBe(m, ["\ud801\udc01"]);
+  assertEquals(m.end, 4);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 3);
+  shouldBe(m, ["\ud801\udc01"]);
+  assertEquals(m.end, 4);
+
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\udc01", 4));
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\ud802", 3);
+  shouldBe(m, ["\ud802"]);
+
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\ud802", 4));
+
+  // Testing handling of paired and non-paired surrogates in non-unicode mode
+  r = new RegExp(r".");
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01");
+  shouldBe(m, ["\ud800"]);
+  assertEquals(m.end, 1);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 1);
+  shouldBe(m, ["\udc00"]);
+  assertEquals(m.end, 2);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 2);
+  shouldBe(m, ["\ud801"]);
+  assertEquals(m.end, 3);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 3);
+  shouldBe(m, ["\udc01"]);
+  assertEquals(m.end, 4);
+
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\udc01", 4));
+
+  // Testing same with start anchor, unicode mode.
+  r = new RegExp("^.", unicode: true);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01");
+  shouldBe(m, ["\ud800\udc00"]);
+  assertEquals(2, m.end);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 1);
+  shouldBe(m, ["\ud800\udc00"]);
+  assertEquals(2, m.end);
+
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\udc01", 2));
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\udc01", 3));
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\udc01", 4));
+
+  // Testing same with start anchor, non-unicode mode.
+  r = new RegExp("^.");
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01");
+  shouldBe(m, ["\ud800"]);
+  assertEquals(1, m.end);
+
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\udc01", 1));
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\udc01", 2));
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\udc01", 3));
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\udc01", 4));
+
+  // Now with both anchored and not as alternatives (with the anchored
+  // version as a captured group), unicode mode.
+  r = new RegExp(r"(?:(^.)|.)", unicode: true);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01");
+  shouldBe(m, ["\ud800\udc00", "\ud800\udc00"]);
+  assertEquals(m.end, 2);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 1);
+  shouldBe(m, ["\ud800\udc00", "\ud800\udc00"]);
+  assertEquals(m.end, 2);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 2);
+  shouldBe(m, ["\ud801\udc01", null]);
+  assertEquals(m.end, 4);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 3);
+  shouldBe(m, ["\ud801\udc01", null]);
+  assertEquals(m.end, 4);
+
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\udc01", 4));
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\ud802", 3);
+  shouldBe(m, ["\ud802", null]);
+
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\ud802", 4));
+
+  // Now with both anchored and not as alternatives (with the anchored
+  // version as a captured group), non-unicode mode.
+  r = new RegExp(r"(?:(^.)|.)");
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01");
+  shouldBe(m, ["\ud800", "\ud800"]);
+  assertEquals(m.end, 1);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 1);
+  shouldBe(m, ["\udc00", null]);
+  assertEquals(m.end, 2);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 2);
+  shouldBe(m, ["\ud801", null]);
+  assertEquals(m.end, 3);
+
+  m = r.matchAsPrefix("\ud800\udc00\ud801\udc01", 3);
+  shouldBe(m, ["\udc01", null]);
+  assertEquals(m.end, 4);
+
+  assertNull(r.matchAsPrefix("\ud800\udc00\ud801\udc01", 4));
+}
diff --git a/tests/corelib_2/regexp/unicode-regexp-restricted-syntax_test.dart b/tests/corelib_2/regexp/unicode-regexp-restricted-syntax_test.dart
new file mode 100644
index 0000000..d894c7b
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-regexp-restricted-syntax_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  // test262/data/test/language/literals/regexp/u-dec-esc
+  assertThrows(() => RegExp(r"\1", unicode: true));
+  // test262/language/literals/regexp/u-invalid-char-range-a
+  assertThrows(() => RegExp(r"[\w-a]", unicode: true));
+  // test262/language/literals/regexp/u-invalid-char-range-b
+  assertThrows(() => RegExp(r"[a-\w]", unicode: true));
+  // test262/language/literals/regexp/u-invalid-char-esc
+  assertThrows(() => RegExp(r"\c", unicode: true));
+  assertThrows(() => RegExp(r"\c0", unicode: true));
+  // test262/built-ins/RegExp/unicode_restricted_quantifiable_assertion
+  assertThrows(() => RegExp(r"(?=.)*", unicode: true));
+  assertThrows(() => RegExp(r"(?=.){1,2}", unicode: true));
+  // test262/built-ins/RegExp/unicode_restricted_octal_escape
+  assertThrows(() => RegExp(r"[\1]", unicode: true));
+  assertThrows(() => RegExp(r"\00", unicode: true));
+  assertThrows(() => RegExp(r"\09", unicode: true));
+  // test262/built-ins/RegExp/unicode_restricted_identity_escape_alpha
+  assertThrows(() => RegExp(r"[\c]", unicode: true));
+  // test262/built-ins/RegExp/unicode_restricted_identity_escape_c
+  assertThrows(() => RegExp(r"[\c0]", unicode: true));
+  // test262/built-ins/RegExp/unicode_restricted_incomple_quantifier
+  assertThrows(() => RegExp(r"a{", unicode: true));
+  assertThrows(() => RegExp(r"a{1,", unicode: true));
+  assertThrows(() => RegExp(r"{", unicode: true));
+  assertThrows(() => RegExp(r"}", unicode: true));
+  // test262/data/test/built-ins/RegExp/unicode_restricted_brackets
+  assertThrows(() => RegExp(r"]", unicode: true));
+  // test262/built-ins/RegExp/unicode_identity_escape
+  assertDoesNotThrow(() => RegExp(r"\/", unicode: true));
+
+  // escaped \0 (as NUL) is allowed inside a character class.
+  shouldBe(RegExp(r"[\0]", unicode: true).firstMatch("\u0000"), ["\u0000"]);
+  // unless it is followed by another digit.
+  assertThrows(() => RegExp(r"[\00]", unicode: true));
+  assertThrows(() => RegExp(r"[\01]", unicode: true));
+  assertThrows(() => RegExp(r"[\09]", unicode: true));
+  shouldBe(RegExp(r"[1\0a]+", unicode: true).firstMatch("b\u{0}1\u{0}a\u{0}2"),
+      ["\u{0}1\u{0}a\u{0}"]);
+  // escaped \- is allowed inside a character class.
+  shouldBe(RegExp(r"[a\-z]", unicode: true).firstMatch("12-34"), ["-"]);
+}
diff --git a/tests/corelib_2/regexp/unicode-regexp-unanchored-advance_test.dart b/tests/corelib_2/regexp/unicode-regexp-unanchored-advance_test.dart
new file mode 100644
index 0000000..e57d810
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-regexp-unanchored-advance_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 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';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  final s = "a" * 10000000 + "\u1234";
+  shouldBe(
+      RegExp(r"(\u1234)", unicode: true).firstMatch(s), ["\u1234", "\u1234"]);
+}
diff --git a/tests/corelib_2/regexp/unicode-regexp-zero-length_test.dart b/tests/corelib_2/regexp/unicode-regexp-zero-length_test.dart
new file mode 100644
index 0000000..e1dd330
--- /dev/null
+++ b/tests/corelib_2/regexp/unicode-regexp-zero-length_test.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  const L = "\ud800";
+  const T = "\udc00";
+  const x = "x";
+
+  var r = RegExp(r"()"); // Not unicode.
+  // Zero-length matches do not advance lastIndex.
+  var m = r.matchAsPrefix(L + T + L + T);
+  shouldBe(m, ["", ""]);
+  assertEquals(0, m.end);
+
+  m = r.matchAsPrefix(L + T + L + T, 1);
+  shouldBe(m, ["", ""]);
+  assertEquals(1, m.end);
+
+  var u = RegExp(r"()", unicode: true);
+
+  // Zero-length matches do not advance lastIndex (but do respect paired
+  // surrogates).
+  m = u.matchAsPrefix(L + T + L + T);
+  shouldBe(m, ["", ""]);
+  assertEquals(0, m.end);
+
+  m = u.matchAsPrefix(L + T + L + T, 1);
+  shouldBe(m, ["", ""]);
+  assertEquals(0, m.end);
+
+  // However, with repeating matches, we do advance from match to match.
+  var ms = r.allMatches(L + T + L + T);
+  assertEquals(5, ms.length);
+  for (var i = 0; i < ms.length; i++) {
+    shouldBe(ms.elementAt(i), ["", ""]);
+  }
+
+  // With unicode flag, we advance code point by code point.
+  ms = u.allMatches(L + T + L + T);
+  assertEquals(3, ms.length);
+  for (var i = 0; i < ms.length; i++) {
+    shouldBe(ms.elementAt(i), ["", ""]);
+  }
+
+  // Test with a lot of copies.
+  const c = 100;
+  ms = u.allMatches((L + T) * c);
+  assertEquals(c + 1, ms.length);
+  for (var i = 0; i < ms.length; i++) {
+    shouldBe(ms.elementAt(i), ["", ""]);
+  }
+
+  // Same with replaceAll().
+  assertEquals(
+      x + L + x + T + x + L + x + T + x, (L + T + L + T).replaceAll(r, "x"));
+
+  assertEquals(x + L + T + x + L + T + x, (L + T + L + T).replaceAll(u, "x"));
+
+  assertEquals((x + L + T) * c + x, ((L + T) * c).replaceAll(u, "x"));
+
+  // Also test String#split.
+  Expect.deepEquals(
+      ["\u{12345}"], "\u{12345}".split(RegExp(r"(?:)", unicode: true)));
+}
diff --git a/tests/corelib_2/regexp/v8_regexp_utils.dart b/tests/corelib_2/regexp/v8_regexp_utils.dart
index cde750a..111ab90 100644
--- a/tests/corelib_2/regexp/v8_regexp_utils.dart
+++ b/tests/corelib_2/regexp/v8_regexp_utils.dart
@@ -22,6 +22,10 @@
   Expect.throws(fn, null, "Test $testid");
 }
 
+void assertDoesNotThrow(fn, [num testid = null]) {
+  fn();
+}
+
 void assertNull(actual, [num testid = null]) {
   Expect.isNull(actual, "Test $testid");
 }
diff --git a/tests/corelib_2/unsigned_shift_test.dart b/tests/corelib_2/unsigned_shift_test.dart
new file mode 100644
index 0000000..09687f8
--- /dev/null
+++ b/tests/corelib_2/unsigned_shift_test.dart
@@ -0,0 +1,115 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=triple-shift
+
+import "package:expect/expect.dart";
+
+// The >>> operator is (again) supported by Dart, and used on `int`.
+
+// This test assumes that the JS implementation of `>>>` uses the JS `>>>`
+// operator directly (that is, convert the value to Uint32, shift right,)
+
+main() {
+  testIntegerShifts();
+  testNonDoubleShifts();
+  testConstantShifts();
+}
+
+void testIntegerShifts() {
+  for (int i = -1; i <= 65; i++) {
+    testShift(0, i);
+    testShift(1, i);
+    testShift(2, i);
+    testShift(3, i);
+    testShift(-1, i);
+    testShift(-5, i);
+    //         .   .   .
+    testShift(0x7fffffff, i);
+    testShift(0x55555555, i);
+    testShift(0xaaaaaaaa, i);
+    testShift(0x80000000, i);
+    //         .   .   .   .   .
+    testShift(0x7fffffffffffffff, i);
+    testShift(0xffffffffffffffff, i);
+  }
+
+  // JavaScript numbers may consider Infinity as an integer.
+  // If so, it is zero when converted to a fixed precision.
+  if (double.infinity is int) {
+    int number = (double.infinity as int);
+    Expect.equals(0, number >> 1);
+    Expect.throws(() => 1 >>> number); // infinity > 64.
+  }
+}
+
+void testNonDoublesShift() {
+  double n = 0.0;
+  n >>> 1; //# 01: compile-time error
+  for (dynamic number in [0.0, 1.0, 2.4, -2.4, double.infinity, double.nan]) {
+    if (number is! int) {
+      Expect.throws(() => number >>> 1);
+      Expect.throws(() => 1 >>> number);
+    }
+  }
+}
+
+int testConstantShifts() {
+  const c = C();
+  // >>> is a constant operation on integers.
+  const c1 = 2 >>> 1;
+  const c2 = (1 >>> 0) >>> 0;
+  // >> is a potentially constant operation independent of type.
+  // The type must still type-check.
+  const c3 = false ? 1 : c >>> c;
+  const c4 = true || c >>> c;
+
+  // It's an error if it doesn't type-check.
+  const c5 = true || "string" >>> 1;  //# 02: compile-time error
+
+  // Or if the shift isn't on integers and it is evaluated.
+  const c6 = c >>> c; //# 03: compile-time error
+
+  // Or if shifting throws
+  const c7 = 1 >>> -1; //# 04: compile-time error
+  const c8 = 1 >>> 65; //# 05: compile-time error
+
+  Expect.notNull(c1 + c2 + c3 + c4);  // Avoid "unused variable" warnings.
+}
+
+const bool isJSBitOps => (-1 | 0) > 0;
+const String jsFlag = isJSBitOps ? " (JS)" : "";
+
+void testShift(int value, int shift) {
+  var title = "0x${value.toRadixString(16)} >>> $shift$jsFlag";
+  if (shift < 0) {
+    // No platform allows shifting a negative.
+    Expect.throws(() => value >>> shift, "$title: shift < 0");
+    return;
+  }
+  if (!isJSBitOps && shift > 64) {
+    // Native 64-bit integers do not allow shifts above 64.
+    Expect.throws(() => value >>> shift, "$title: shift > 64");
+    return;
+  }
+  var expected;
+  if (isJsBitOps) {
+    // TODO: Check that this is the desired behavior for JS >>>.
+    expected = value.toUnsigned(32) >> shift;
+  } else if (value < 0) {
+    if (shift > 0) {
+      expected = (value >> shift).toUnsigned(64 - shift);
+    } else {
+      expected = value;
+    }
+  } else {
+    expected = value >> shift;
+  }
+  Expect.equals(expected, value >>> shift, title);
+}
+
+class C {
+  const C();
+  C operator >>>(C other) => other;
+}
diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status
index 5b0ab46..0e982e4 100644
--- a/tests/ffi/ffi.status
+++ b/tests/ffi/ffi.status
@@ -9,9 +9,8 @@
 data_not_asan_test: SkipByDesign # This test tries to allocate too much memory on purpose.
 
 # dartbug.com/35768: Structs not supported on 32-bit.
-[ $arch == ia32 || $arch == arm ]
+[ $arch == ia32 || $arch == arm || $arch == simdbc ]
 function_structs_test: Skip
-function_callbacks_test: Skip
 structs_test: Skip
 
 # dartbug.com/35934
@@ -22,17 +21,26 @@
 function_test: Skip
 negative_function_test: Skip
 
-[ $arch == x64 || $arch == arm64 ]
+[ $arch == x64 || $arch == arm64 || $arch == simdbc64 ]
 enable_structs_test: SkipByDesign  # Tests that structs don't work on 32-bit systems.
 
 [ $runtime == dart_precompiled ]
 *: Skip # AOT is not yet supported: dartbug.com/35765
 
-[ $arch == simdbc64 || $arch == simarm || $arch == simarm64 ]
-*: Skip # FFI not yet supported on DBC or other simulated architectures.
+[ $arch == simarm || $arch == simarm64 ]
+*: Skip # FFI not yet supported on the arm simulator.
+
+[ $arch == simdbc ]
+*: Skip # FFI not yet supported on SimDBC32: dartbug.com/36809
+
+[ $arch == simdbc64 && $system != linux && $system != macos ]
+*: Skip # FFI not yet supported outside x64 Linux: dartbug.com/36809
 
 [ $system != android && $system != linux && $system != macos && $system != windows ]
 *: Skip # FFI not yet supported on other OSes.
 
 [ $system != android && $arch == arm ]
 *: Skip # "hardfp" calling convention is not yet supported (iOS is also supported but not tested): dartbug.com/36309
+
+[ $arch == simdbc64 ]
+function_callbacks_test: Skip  # Issue 37140
diff --git a/tests/ffi/function_callbacks_test.dart b/tests/ffi/function_callbacks_test.dart
index 0ad50a9..fc2e46c 100644
--- a/tests/ffi/function_callbacks_test.dart
+++ b/tests/ffi/function_callbacks_test.dart
@@ -8,71 +8,192 @@
 
 library FfiTest;
 
-import 'dart:ffi' as ffi;
-
+import 'dart:io';
+import 'dart:ffi';
+import 'dart:isolate';
 import 'dylib_utils.dart';
 
 import "package:expect/expect.dart";
 
-import 'coordinate.dart';
+typedef NativeCallbackTest = Int32 Function(Pointer);
+typedef NativeCallbackTestFn = int Function(Pointer);
 
-typedef NativeCoordinateOp = Coordinate Function(Coordinate);
+final DynamicLibrary testLibrary = dlopenPlatformSpecific("ffi_test_functions");
 
-typedef CoordinateTrice = Coordinate Function(
-    ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>, Coordinate);
+class Test {
+  final String name;
+  final Pointer callback;
+  final bool skip;
 
-void main() {
-  testFunctionWithFunctionPointer();
-  testNativeFunctionWithFunctionPointer();
+  Test(this.name, this.callback, {bool skipIf: false}) : skip = skipIf {}
+
+  void run() {
+    if (skip) return;
+
+    final NativeCallbackTestFn tester = testLibrary
+        .lookupFunction<NativeCallbackTest, NativeCallbackTestFn>("Test$name");
+    final int testCode = tester(callback);
+    if (testCode != 0) {
+      Expect.fail("Test $name failed.");
+    }
+  }
 }
 
-ffi.DynamicLibrary ffiTestFunctions =
-    dlopenPlatformSpecific("ffi_test_functions");
+typedef SimpleAdditionType = Int32 Function(Int32, Int32);
+int simpleAddition(int x, int y) => x + y;
 
-/// pass a pointer to a c function as an argument to a c function
-void testFunctionWithFunctionPointer() {
-  ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>
-      transposeCoordinatePointer =
-      ffiTestFunctions.lookup("TransposeCoordinate");
+typedef IntComputationType = Int64 Function(Int8, Int16, Int32, Int64);
+int intComputation(int a, int b, int c, int d) => d - c + b - a;
 
-  ffi.Pointer<ffi.NativeFunction<CoordinateTrice>> p2 =
-      ffiTestFunctions.lookup("CoordinateUnOpTrice");
-  CoordinateTrice coordinateUnOpTrice = p2.asFunction();
+typedef UintComputationType = Uint64 Function(Uint8, Uint16, Uint32, Uint64);
+int uintComputation(int a, int b, int c, int d) => d - c + b - a;
 
-  Coordinate c1 = Coordinate(10.0, 20.0, null);
-  c1.next = c1;
+typedef SimpleMultiplyType = Double Function(Double);
+double simpleMultiply(double x) => x * 1.337;
 
-  Coordinate result = coordinateUnOpTrice(transposeCoordinatePointer, c1);
+typedef SimpleMultiplyFloatType = Float Function(Float);
+double simpleMultiplyFloat(double x) => x * 1.337;
 
-  print(result.runtimeType);
-  print(result.x);
-  print(result.y);
-
-  c1.free();
+typedef ManyIntsType = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr, IntPtr,
+    IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
+int manyInts(
+    int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
+  return a + b + c + d + e + f + g + h + i + j;
 }
 
-typedef BinaryOp = int Function(int, int);
-
-typedef NativeIntptrBinOp = ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr);
-
-typedef NativeIntptrBinOpLookup
-    = ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> Function();
-
-void testNativeFunctionWithFunctionPointer() {
-  ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOpLookup>> p1 =
-      ffiTestFunctions.lookup("IntptrAdditionClosure");
-  NativeIntptrBinOpLookup intptrAdditionClosure = p1.asFunction();
-
-  ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> intptrAdditionPointer =
-      intptrAdditionClosure();
-  BinaryOp intptrAddition = intptrAdditionPointer.asFunction();
-  Expect.equals(37, intptrAddition(10, 27));
+typedef ManyDoublesType = Double Function(Double, Double, Double, Double,
+    Double, Double, Double, Double, Double, Double);
+double manyDoubles(double a, double b, double c, double d, double e, double f,
+    double g, double h, double i, double j) {
+  return a + b + c + d + e + f + g + h + i + j;
 }
 
-int myPlus(int a, int b) => a + b;
+typedef ManyArgsType = Double Function(
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double);
+double manyArgs(
+    int _1,
+    double _2,
+    int _3,
+    double _4,
+    int _5,
+    double _6,
+    int _7,
+    double _8,
+    int _9,
+    double _10,
+    int _11,
+    double _12,
+    int _13,
+    double _14,
+    int _15,
+    double _16,
+    int _17,
+    double _18,
+    int _19,
+    double _20) {
+  return _1 +
+      _2 +
+      _3 +
+      _4 +
+      _5 +
+      _6 +
+      _7 +
+      _8 +
+      _9 +
+      _10 +
+      _11 +
+      _12 +
+      _13 +
+      _14 +
+      _15 +
+      _16 +
+      _17 +
+      _18 +
+      _19 +
+      _20;
+}
 
-typedef NativeApplyTo42And74Type = ffi.IntPtr Function(
-    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+typedef StoreType = Pointer<Int64> Function(Pointer<Int64>);
+Pointer<Int64> store(Pointer<Int64> ptr) => ptr.elementAt(1)..store(1337);
 
-typedef ApplyTo42And74Type = int Function(
-    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+typedef NullPointersType = Pointer<Int64> Function(Pointer<Int64>);
+Pointer<Int64> nullPointers(Pointer<Int64> ptr) => ptr?.elementAt(1);
+
+typedef ReturnNullType = Int32 Function();
+int returnNull() {
+  print('Expect "unhandled exception" error message to follow.');
+  return null;
+}
+
+typedef ReturnVoid = Void Function();
+void returnVoid() {}
+
+final List<Test> testcases = [
+  Test("SimpleAddition", fromFunction<SimpleAdditionType>(simpleAddition)),
+  Test("IntComputation", fromFunction<IntComputationType>(intComputation)),
+  Test("UintComputation", fromFunction<UintComputationType>(uintComputation)),
+  Test("SimpleMultiply", fromFunction<SimpleMultiplyType>(simpleMultiply)),
+  Test("SimpleMultiplyFloat",
+      fromFunction<SimpleMultiplyFloatType>(simpleMultiplyFloat)),
+  Test("ManyInts", fromFunction<ManyIntsType>(manyInts)),
+  Test("ManyDoubles", fromFunction<ManyDoublesType>(manyDoubles)),
+  Test("ManyArgs", fromFunction<ManyArgsType>(manyArgs)),
+  Test("Store", fromFunction<StoreType>(store)),
+  Test("NullPointers", fromFunction<NullPointersType>(nullPointers)),
+  Test("ReturnNull", fromFunction<ReturnNullType>(returnNull)),
+];
+
+testCallbackWrongThread() =>
+    Test("CallbackWrongThread", fromFunction<ReturnVoid>(returnVoid)).run();
+
+testCallbackOutsideIsolate() =>
+    Test("CallbackOutsideIsolate", fromFunction<ReturnVoid>(returnVoid)).run();
+
+isolateHelper(int callbackPointer) {
+  final Pointer<Void> ptr = fromAddress(callbackPointer);
+  final NativeCallbackTestFn tester =
+      testLibrary.lookupFunction<NativeCallbackTest, NativeCallbackTestFn>(
+          "TestCallbackWrongIsolate");
+  Expect.equals(0, tester(ptr));
+}
+
+testCallbackWrongIsolate() async {
+  final int callbackPointer = fromFunction<ReturnVoid>(returnVoid).address;
+  final ReceivePort exitPort = ReceivePort();
+  await Isolate.spawn(isolateHelper, callbackPointer,
+      errorsAreFatal: true, onExit: exitPort.sendPort);
+  await exitPort.first;
+}
+
+void main() async {
+  testcases.forEach((t) => t.run()); //# 00: ok
+
+  // These tests terminate the process after successful completion, so we have
+  // to run them separately.
+  //
+  // Since they use signal handlers they only run on Linux.
+  if (Platform.isLinux && !const bool.fromEnvironment("dart.vm.product")) {
+    testCallbackWrongThread(); //# 01: ok
+    testCallbackOutsideIsolate(); //# 02: ok
+    await testCallbackWrongIsolate(); //# 03: ok
+  }
+}
diff --git a/tests/ffi/function_gc_test.dart b/tests/ffi/function_gc_test.dart
new file mode 100644
index 0000000..1799ce1
--- /dev/null
+++ b/tests/ffi/function_gc_test.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2019, 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=--deterministic --optimization-counter-threshold=500 --enable-testing-pragmas
+// VMOptions=--deterministic --optimization-counter-threshold=-1 --enable-testing-pragmas
+//
+// Dart test program for stress-testing boxing and GC in return paths from FFI
+// trampolines.
+//
+// NOTE: This test does not produce useful stderr when it fails because the
+// stderr is redirected to a file for reflection.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi' as ffi;
+import 'dylib_utils.dart';
+import "package:expect/expect.dart";
+
+main() async {
+  testBoxInt64();
+  testBoxInt32();
+  testBoxDouble();
+  testBoxPointer();
+  testAllocateInNative();
+  testAllocateInDart();
+}
+
+ffi.DynamicLibrary ffiTestFunctions =
+    dlopenPlatformSpecific("ffi_test_functions");
+
+typedef NativeNullaryOp64 = ffi.Int64 Function();
+typedef NativeNullaryOp32 = ffi.Int32 Function();
+typedef NativeNullaryOpDouble = ffi.Double Function();
+typedef NativeNullaryOpPtr = ffi.Pointer<ffi.Void> Function();
+typedef NativeNullaryOp = ffi.Void Function();
+typedef NativeUnaryOp = ffi.Void Function(ffi.Uint64);
+typedef NullaryOp = int Function();
+typedef NullaryOpDbl = double Function();
+typedef NullaryOpPtr = ffi.Pointer<ffi.Void> Function();
+typedef UnaryOp = void Function(int);
+typedef NullaryOpVoid = void Function();
+
+//// These functions return values that require boxing into different types.
+
+final minInt64 =
+    ffiTestFunctions.lookupFunction<NativeNullaryOp64, NullaryOp>("MinInt64");
+
+// Forces boxing into Mint on all platforms.
+void testBoxInt64() {
+  Expect.equals(0x8000000000000000, minInt64());
+}
+
+NullaryOp minInt32 =
+    ffiTestFunctions.lookupFunction<NativeNullaryOp32, NullaryOp>("MinInt32");
+
+// Forces boxing into Mint on 32-bit platforms only.
+void testBoxInt32() {
+  Expect.equals(-0x80000000, minInt32());
+}
+
+final smallDouble = ffiTestFunctions
+    .lookupFunction<NativeNullaryOpDouble, NullaryOpDbl>("SmallDouble");
+
+// Forces boxing into Double.
+void testBoxDouble() {
+  Expect.equals(0x80000000 * -1.0, smallDouble());
+}
+
+final largePointer = ffiTestFunctions
+    .lookupFunction<NativeNullaryOpPtr, NullaryOpPtr>("LargePointer");
+
+// Forces boxing into ffi.Pointer and ffi.Mint.
+void testBoxPointer() {
+  ffi.Pointer pointer = largePointer();
+  if (pointer != null) {
+    if (ffi.sizeOf<ffi.Pointer>() == 4) {
+      Expect.equals(0x82000000, pointer.address);
+    } else {
+      Expect.equals(0x8100000082000000, pointer.address);
+    }
+  }
+}
+
+final triggerGc = ffiTestFunctions
+    .lookupFunction<NativeNullaryOp, NullaryOpVoid>("TriggerGC");
+
+// Test GC in the FFI call path by calling a C function which triggers GC
+// directly.
+void testAllocateInNative() => triggerGc();
+
+@pragma("vm:entry-point", "call")
+void testAllocationsInDartHelper() => triggerGc();
+
+final allocateThroughDart = ffiTestFunctions
+    .lookupFunction<NativeNullaryOp, NullaryOpVoid>("AllocateThroughDart");
+
+// Test GC in the FFI call path by calling a C function which allocates by
+// calling back into Dart ('testAllocationsInDartHelper').
+void testAllocateInDart() => allocateThroughDart();
diff --git a/tests/ffi/function_stress_test.dart b/tests/ffi/function_stress_test.dart
deleted file mode 100644
index 92e807c..0000000
--- a/tests/ffi/function_stress_test.dart
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) 2019, 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=--deterministic --optimization-counter-threshold=500 --verbose-gc
-// VMOptions=--deterministic --optimization-counter-threshold=-1 --verbose-gc
-//
-// Dart test program for stress-testing boxing and GC in return paths from FFI
-// trampolines.
-//
-// NOTE: This test does not produce useful stderr when it fails because the
-// stderr is redirected to a file for reflection.
-//
-// SharedObjects=ffi_test_functions
-
-import 'dart:ffi' as ffi;
-import 'dylib_utils.dart';
-import "package:expect/expect.dart";
-import 'gc_helper.dart';
-
-test(GCWatcher watcher, Function testee,
-    {bool mustTriggerGC: true, bool batched: false}) async {
-  // Warmup.
-  for (int i = 0; i < 1000; ++i) {
-    batched ? testee(1) : testee();
-  }
-  int size = await watcher.size();
-  for (int i = 0; i < 1000000;) {
-    if (batched) {
-      testee(1000);
-      i += 1000;
-    } else {
-      testee();
-      i++;
-    }
-  }
-  int new_size = await watcher.size();
-  if (mustTriggerGC) {
-    print("Expect $new_size > $size.");
-    Expect.isTrue(new_size > size);
-  }
-}
-
-main() async {
-  final watcher = GCWatcher.ifAvailable();
-  try {
-    await test(watcher, testBoxInt64);
-    // On 64-bit platforms this won't trigger GC because the result fits into a
-    // Smi.
-    await test(watcher, testBoxInt32, mustTriggerGC: false);
-    await test(watcher, testBoxDouble);
-    await test(watcher, testBoxPointer);
-    await test(watcher, testAllocateMints, batched: true);
-    await test(watcher, testAllocationsInDart, batched: true);
-  } finally {
-    watcher.dispose();
-  }
-}
-
-ffi.DynamicLibrary ffiTestFunctions =
-    dlopenPlatformSpecific("ffi_test_functions");
-
-typedef NativeNullaryOp64 = ffi.Int64 Function();
-typedef NativeNullaryOp32 = ffi.Int32 Function();
-typedef NativeNullaryOpDouble = ffi.Double Function();
-typedef NativeNullaryOpPtr = ffi.Pointer<ffi.Void> Function();
-typedef NativeUnaryOp = ffi.Void Function(ffi.Uint64);
-typedef NullaryOp = int Function();
-typedef NullaryOpDbl = double Function();
-typedef NullaryOpPtr = ffi.Pointer<ffi.Void> Function();
-typedef UnaryOp = void Function(int);
-
-//// These functions return values that require boxing into different types.
-
-final minInt64 =
-    ffiTestFunctions.lookupFunction<NativeNullaryOp64, NullaryOp>("MinInt64");
-
-// Forces boxing into Mint on all platforms.
-void testBoxInt64() {
-  Expect.equals(0x8000000000000000, minInt64());
-}
-
-NullaryOp minInt32 =
-    ffiTestFunctions.lookupFunction<NativeNullaryOp32, NullaryOp>("MinInt32");
-
-// Forces boxing into Mint on 32-bit platforms only.
-void testBoxInt32() {
-  Expect.equals(-0x80000000, minInt32());
-}
-
-final smallDouble = ffiTestFunctions
-    .lookupFunction<NativeNullaryOpDouble, NullaryOpDbl>("SmallDouble");
-
-// Forces boxing into Double.
-void testBoxDouble() {
-  Expect.equals(0x80000000 * -1.0, smallDouble());
-}
-
-final largePointer = ffiTestFunctions
-    .lookupFunction<NativeNullaryOpPtr, NullaryOpPtr>("LargePointer");
-
-// Forces boxing into ffi.Pointer and ffi.Mint.
-void testBoxPointer() {
-  ffi.Pointer pointer = largePointer();
-  if (pointer != null) {
-    if (ffi.sizeOf<ffi.Pointer>() == 4) {
-      Expect.equals(0x82000000, pointer.address);
-    } else {
-      Expect.equals(0x8100000082000000, pointer.address);
-    }
-  }
-}
-
-final allocateMint =
-    ffiTestFunctions.lookupFunction<NativeUnaryOp, UnaryOp>("AllocateMints");
-
-// Test GC in the FFI call path by calling a C function which allocates through
-// the Dart API.
-void testAllocateMints(int batchSize) {
-  allocateMint(batchSize);
-}
-
-class C {
-  final int i;
-  C(this.i);
-}
-
-C c = null;
-@pragma("vm:entry-point", "call")
-void testAllocationsInDartHelper(int count) {
-  for (int i = 0; i < count; ++i) {
-    c = C(i);
-  }
-}
-
-final allocateThroughDart = ffiTestFunctions
-    .lookupFunction<NativeUnaryOp, UnaryOp>("AllocateThroughDart");
-
-// Test GC in the FFI call path by calling a C function which allocates by
-// calling back into Dart ('testAllocationsInDartHelper').
-void testAllocationsInDart(int batchSize) {
-  allocateThroughDart(batchSize * 10);
-}
diff --git a/tests/ffi/function_test.dart b/tests/ffi/function_test.dart
index 07f8fc2..014c66e 100644
--- a/tests/ffi/function_test.dart
+++ b/tests/ffi/function_test.dart
@@ -6,6 +6,7 @@
 //
 // VMOptions=
 // VMOptions=--deterministic --optimization-counter-threshold=10
+// VMOptions=--use-slow-path
 // SharedObjects=ffi_test_functions
 
 library FfiTest;
diff --git a/tests/ffi/gc_helper.dart b/tests/ffi/gc_helper.dart
deleted file mode 100644
index abe0454..0000000
--- a/tests/ffi/gc_helper.dart
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2019, 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:io';
-import 'dylib_utils.dart';
-import 'dart:ffi';
-import 'dart:io' show Platform;
-
-DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
-
-const bool isProduct = const bool.fromEnvironment("dart.vm.product");
-
-abstract class GCWatcher {
-  factory GCWatcher() => _GCWatcherImpl();
-  factory GCWatcher.dummy() => _MockGCWatcher();
-  factory GCWatcher.ifAvailable() =>
-      (Platform.isWindows || Platform.isAndroid || isProduct)
-          ? GCWatcher.dummy()
-          : GCWatcher();
-
-  Future<int> size();
-  void dispose();
-}
-
-// Requires --verbose-gc.
-class _GCWatcherImpl implements GCWatcher {
-  int _suffix;
-
-  Future<int> size() async {
-    return await File("/tmp/captured_stderr_$_suffix").length();
-  }
-
-  _GCWatcherImpl() {
-    print("Starting...");
-    _suffix = ffiTestFunctions
-        .lookupFunction<Int32 Function(), int Function()>("RedirectStderr")();
-  }
-
-  dispose() {
-    try {
-      File("/tmp/captured_stderr_$_suffix").deleteSync();
-    } catch (e) {
-      print("deleting file failed");
-    }
-  }
-}
-
-class _MockGCWatcher implements GCWatcher {
-  int _ctr = 0;
-
-  Future<int> size() async => ++_ctr;
-  dispose() {}
-}
diff --git a/tests/ffi/regress_37100_test.dart b/tests/ffi/regress_37100_test.dart
new file mode 100644
index 0000000..7281042
--- /dev/null
+++ b/tests/ffi/regress_37100_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, 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.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+
+import 'dylib_utils.dart';
+
+class EVP_MD extends Pointer<Void> {}
+
+DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+
+final EVP_sha1 = ffiTestFunctions
+    .lookupFunction<EVP_MD Function(), EVP_MD Function()>('LargePointer');
+
+main() {
+  int result = EVP_sha1().address;
+  // On 32 bit only the lowest 32 bits are returned, so only test those.
+  result &= 0x00000000FFFFFFFF;
+  Expect.equals(0x0000000082000000, result);
+}
diff --git a/tests/ffi/subtype_test.dart b/tests/ffi/subtype_test.dart
index 22dbe13..54977b5 100644
--- a/tests/ffi/subtype_test.dart
+++ b/tests/ffi/subtype_test.dart
@@ -4,6 +4,7 @@
 //
 // Dart test program for testing dart:ffi Pointer subtypes.
 //
+// SharedObjects=ffi_test_functions
 // VMOptions=--verbose-gc
 
 library FfiTest;
@@ -12,21 +13,21 @@
 
 import "package:expect/expect.dart";
 
-import 'gc_helper.dart';
 import 'cstring.dart';
+import 'dylib_utils.dart';
+
+ffi.DynamicLibrary ffiTestFunctions =
+    dlopenPlatformSpecific("ffi_test_functions");
+
+final triggerGc = ffiTestFunctions
+    .lookupFunction<ffi.Void Function(), void Function()>("TriggerGC");
 
 void main() async {
   testAllocate();
   testSizeOf();
-  await testGC();
+  testGC();
 }
 
-class X {
-  X(this.i);
-  int i;
-}
-
-dynamic foo;
 dynamic bar;
 
 void testAllocate() {
@@ -36,15 +37,10 @@
 }
 
 Future<void> testGC() async {
-  CString cs = ffi.fromAddress<CString>(11);
-  bar = cs;
-  foo = "";
-  final watcher = GCWatcher.ifAvailable();
-  int counts = await watcher.size();
-  for (int i = 0; i < 1000000; ++i) {
-    foo = new X(i);
-  }
-  Expect.isTrue(await watcher.size() > counts);
+  bar = ffi.fromAddress<CString>(11);
+  // Verify that the objects manufactured by 'fromAddress' can be scanned by the
+  // GC.
+  triggerGc();
 }
 
 void testSizeOf() {
diff --git a/tests/kernel/kernel.status b/tests/kernel/kernel.status
index 8c659a4..a75323a 100644
--- a/tests/kernel/kernel.status
+++ b/tests/kernel/kernel.status
@@ -23,11 +23,5 @@
 [ $compiler == dart2js && $host_checked ]
 unsorted/super_mixin_test: Crash
 
-[ $compiler == dart2js && !$strong ]
-unsorted/types_test: RuntimeError
-
-[ $compiler != dartk && $compiler != dartkb && $compiler != dartkp && !$strong ]
-unsorted/invocation_errors_test/00: MissingCompileTimeError # This test has been tuned for dart 2.
-
 [ !$preview_dart_2 && ($runtime == dart_precompiled || $runtime == vm) ]
 *: SkipByDesign # Deprecating all Dart1 modes of execution
diff --git a/tests/language_2/assertion_initializer_const_error2_test.dart b/tests/language_2/assertion_initializer_const_error2_test.dart
index dd152a3..02372d5 100644
--- a/tests/language_2/assertion_initializer_const_error2_test.dart
+++ b/tests/language_2/assertion_initializer_const_error2_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, 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=--assert_initializer
+// VMOptions=--enable-asserts
 // dart2jsOptions=--enable-asserts
 //
 // Test of asserts in initializer lists.
diff --git a/tests/language_2/assertion_test.dart b/tests/language_2/assertion_test.dart
index d14c513..2f1efee 100644
--- a/tests/language_2/assertion_test.dart
+++ b/tests/language_2/assertion_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--enable_type_checks --enable_asserts
+// VMOptions=--enable-asserts
 // dart2jsOptions=--enable-asserts
 
 // Dart test program testing assert statements.
diff --git a/tests/language_2/async_identifier_test.dart b/tests/language_2/async_identifier_test.dart
new file mode 100644
index 0000000..5af2722
--- /dev/null
+++ b/tests/language_2/async_identifier_test.dart
@@ -0,0 +1,209 @@
+// Copyright (c) 2019, 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' as async;
+import 'async_lib.dart' as l; // Minimal library containing "int async;".
+
+// Adapted from Analyzer test testing where `async` was not previously allowed.
+
+// Helpers
+void ignore(argument) {}
+
+class GNamed {
+  void g({Object async = null}) {}
+}
+
+class AGet {
+  int get async => 1;
+  set async(int i) {}
+}
+
+class ACall {
+  int async() => 1;
+}
+
+main() {
+  // Each test declares a spearate async function, tests that `async`
+  // can occur in it, and makes sure the function is run.
+  {
+    const int async = 0;
+    f() async {
+      g(@async x) {}
+      g(0);
+    }
+
+    f();
+  }
+  {
+    f(c) async {
+      c.g(async: 0);
+    }
+
+    f(GNamed());
+  }
+  {
+    f() async {
+      var async = 1;
+      ignore(async);
+    }
+
+    f();
+  }
+  {
+    f() async* {
+      var async = 1;
+      ignore(async);
+    }
+
+    f().forEach(ignore);
+  }
+  {
+    f() async {
+      async:
+      while (true) {
+        break async;
+      }
+    }
+
+    f();
+  }
+  {
+    g() {}
+    f() async {
+      try {
+        g();
+      } catch (async) {}
+    }
+
+    f();
+  }
+  {
+    g() {}
+    f() async {
+      try {
+        g();
+      } catch (e, async) {}
+    }
+
+    f();
+  }
+  {
+    f() async {
+      async:
+      while (true) {
+        if (false) continue async;
+        break;
+      }
+    }
+
+    f();
+  }
+  {
+    var async;
+    f() async {
+      for (async in []) {}
+    }
+
+    f();
+  }
+  {
+    f() async {
+      g(int async) {}
+      g(0);
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new AGet().async;
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new ACall().async();
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new ACall()..async();
+    }
+
+    f();
+  }
+  {
+    g() {}
+    f() async {
+      async:
+      g();
+    }
+
+    f();
+  }
+  {
+    f() async {
+      int async() => null;
+      async();
+    }
+  }
+  {
+    f() async {
+      return async.Future.value(0);
+    }
+
+    f();
+  }
+  {
+    f() async {
+      new AGet().async = 1;
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new AGet()..async = 1;
+    }
+
+    f();
+  }
+  {
+    int async = 1;
+    f() async {
+      return "$async";
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return l.async;
+    }
+
+    f();
+  }
+  {
+    f() async {
+      switch (0) {
+        async:
+        case 0:
+          break;
+      }
+    }
+
+    f();
+  }
+  {
+    f() sync* {
+      var async = 1;
+      ignore(async);
+    }
+
+    f();
+  }
+}
diff --git a/tests/language_2/async_lib.dart b/tests/language_2/async_lib.dart
new file mode 100644
index 0000000..a6be037
--- /dev/null
+++ b/tests/language_2/async_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, 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.
+
+// Helper library for async_identifier_test.dart
+
+int async;
diff --git a/tests/language_2/async_star_error_test.dart b/tests/language_2/async_star_error_test.dart
index 4bf2433..dc06e5a 100644
--- a/tests/language_2/async_star_error_test.dart
+++ b/tests/language_2/async_star_error_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "dart:async";
-import "package:expect/async_minitest.dart";
+import "package:async_helper/async_minitest.dart";
 
 /// Tests for exceptions raised in async*
 main() {
diff --git a/tests/language_2/async_star_test.dart b/tests/language_2/async_star_test.dart
index 4828485..72d772e 100644
--- a/tests/language_2/async_star_test.dart
+++ b/tests/language_2/async_star_test.dart
@@ -6,7 +6,7 @@
 
 import "dart:async";
 
-import "package:expect/async_minitest.dart";
+import "package:async_helper/async_minitest.dart";
 
 main() {
   group("basic", () {
diff --git a/tests/language_2/bottom_test.dart b/tests/language_2/bottom_test.dart
new file mode 100644
index 0000000..38ac721
--- /dev/null
+++ b/tests/language_2/bottom_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, 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";
+
+void main() {
+  final f1 = () => throw null;
+  final f2 = () => null;
+  Expect.equals(f1.runtimeType, f2.runtimeType);
+
+  final Bottom = (<F>(F Function() f) => F)(() => throw null);
+  Expect.equals(Null, Bottom);
+}
diff --git a/tests/language_2/constants_2018/constant_type_literal_test.dart b/tests/language_2/constants_2018/constant_type_literal_test.dart
index 33cf4a9..a644ff0 100644
--- a/tests/language_2/constants_2018/constant_type_literal_test.dart
+++ b/tests/language_2/constants_2018/constant_type_literal_test.dart
@@ -9,15 +9,16 @@
 import "dart:core";
 import "dart:core" as core;
 // No reloading support for deferred loading.
-// See https://github.com/dart-lang/sdk/issues/33118,
-import "dart:core" deferred as dcore; //# 01: crash on reload
+// See https://github.com/dart-lang/sdk/issues/33118.
+import "dart:core" deferred as dcore; //# 01: compile-time error
 
 // Declares F function type alias, M mixin and C class.
 import "constant_type_literal_types.dart";
 import "constant_type_literal_types.dart" as p;
 // No reloading support for deferred loading.
-// See https://github.com/dart-lang/sdk/issues/33118,
-import "constant_type_literal_types.dart" deferred as d; //# 02: crash on reload
+// See https://github.com/dart-lang/sdk/issues/33118.
+import "constant_type_literal_types.dart" //# 02: compile-time error
+    deferred as d; //# 02: continued
 
 main() {
   const Test(int, core.int);
@@ -25,11 +26,11 @@
   const Test(M, p.M);
   const Test(F, p.F);
   const c1 = //
-      dcore. //# 01: compile-time error
+      dcore. //# 01: continued
           int;
   const Test(c1, int);
   const c2 = //
-      d. //# 02: compile-time error
+      d. //# 02: continued
           C;
   const Test(c2, C);
 }
diff --git a/tests/language_2/control_flow_collections/await_for_inference_test.dart b/tests/language_2/control_flow_collections/await_for_inference_test.dart
index 6987f58..e0c1df8 100644
--- a/tests/language_2/control_flow_collections/await_for_inference_test.dart
+++ b/tests/language_2/control_flow_collections/await_for_inference_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 // Test how await for interacts with inference.
 import "package:async_helper/async_helper.dart";
 import 'package:expect/expect.dart';
diff --git a/tests/language_2/control_flow_collections/await_for_null_test.dart b/tests/language_2/control_flow_collections/await_for_null_test.dart
index 7e2fc5e..f1c1460 100644
--- a/tests/language_2/control_flow_collections/await_for_null_test.dart
+++ b/tests/language_2/control_flow_collections/await_for_null_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 // Test that a null stream expression procudes a runtime error.
 import 'package:async_helper/async_helper.dart';
 
@@ -11,11 +9,11 @@
   asyncTest(() async {
     // Null stream.
     Stream<int> nullStream = null;
-    asyncExpectThrows<NoSuchMethodError>(
+    asyncExpectThrows<Error>(
         () async => <int>[await for (var i in nullStream) 1]);
-    asyncExpectThrows<NoSuchMethodError>(
+    asyncExpectThrows<Error>(
         () async => <int, int>{await for (var i in nullStream) 1: 1});
-    asyncExpectThrows<NoSuchMethodError>(
+    asyncExpectThrows<Error>(
         () async => <int>{await for (var i in nullStream) 1});
   });
 }
diff --git a/tests/language_2/control_flow_collections/await_for_syntax_error_test.dart b/tests/language_2/control_flow_collections/await_for_syntax_error_test.dart
index f5e30ce..d64303a 100644
--- a/tests/language_2/control_flow_collections/await_for_syntax_error_test.dart
+++ b/tests/language_2/control_flow_collections/await_for_syntax_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections
-
 void main() {
   // Use await for in non-async function.
   var _ = [await for (var i in Stream<int>.empty()) i]; //# 01: compile-time error
diff --git a/tests/language_2/control_flow_collections/await_for_test.dart b/tests/language_2/control_flow_collections/await_for_test.dart
index c838c49..9faee4a 100644
--- a/tests/language_2/control_flow_collections/await_for_test.dart
+++ b/tests/language_2/control_flow_collections/await_for_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
 
diff --git a/tests/language_2/control_flow_collections/await_for_type_error_test.dart b/tests/language_2/control_flow_collections/await_for_type_error_test.dart
index 8cc87da..e63a52e 100644
--- a/tests/language_2/control_flow_collections/await_for_type_error_test.dart
+++ b/tests/language_2/control_flow_collections/await_for_type_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections
-
 void main() {
   () async {
     // Non-Stream type.
diff --git a/tests/language_2/control_flow_collections/for_await_test.dart b/tests/language_2/control_flow_collections/for_await_test.dart
index 55d24ae..2baeefc 100644
--- a/tests/language_2/control_flow_collections/for_await_test.dart
+++ b/tests/language_2/control_flow_collections/for_await_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections
-
 import "package:async_helper/async_helper.dart";
 import 'package:expect/expect.dart';
 
diff --git a/tests/language_2/control_flow_collections/for_const_error_test.dart b/tests/language_2/control_flow_collections/for_const_error_test.dart
index 626c7a8..3348639 100644
--- a/tests/language_2/control_flow_collections/for_const_error_test.dart
+++ b/tests/language_2/control_flow_collections/for_const_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections
-
 void main() {
   // For cannot be used in a const collection.
   const _ = [for (var i in []) 1]; //# 00: compile-time error
diff --git a/tests/language_2/control_flow_collections/for_inference_test.dart b/tests/language_2/control_flow_collections/for_inference_test.dart
index 9479dd6..4e022e0 100644
--- a/tests/language_2/control_flow_collections/for_inference_test.dart
+++ b/tests/language_2/control_flow_collections/for_inference_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 // Test how control flow interacts with inference.
 import 'package:expect/expect.dart';
 
diff --git a/tests/language_2/control_flow_collections/for_non_bool_condition_test.dart b/tests/language_2/control_flow_collections/for_non_bool_condition_test.dart
index 74b00df..a808e9c 100644
--- a/tests/language_2/control_flow_collections/for_non_bool_condition_test.dart
+++ b/tests/language_2/control_flow_collections/for_non_bool_condition_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 import 'package:expect/expect.dart';
 
 void main() {
diff --git a/tests/language_2/control_flow_collections/for_null_condition_test.dart b/tests/language_2/control_flow_collections/for_null_condition_test.dart
index 2f9a6c0..8233c10 100644
--- a/tests/language_2/control_flow_collections/for_null_condition_test.dart
+++ b/tests/language_2/control_flow_collections/for_null_condition_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 import 'package:expect/expect.dart';
 
 void main() {
diff --git a/tests/language_2/control_flow_collections/for_runtime_error_test.dart b/tests/language_2/control_flow_collections/for_runtime_error_test.dart
index b8fa267..ea5cfe4 100644
--- a/tests/language_2/control_flow_collections/for_runtime_error_test.dart
+++ b/tests/language_2/control_flow_collections/for_runtime_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 import 'package:expect/expect.dart';
 
 void main() {
diff --git a/tests/language_2/control_flow_collections/for_test.dart b/tests/language_2/control_flow_collections/for_test.dart
index a264cb6..16026a6 100644
--- a/tests/language_2/control_flow_collections/for_test.dart
+++ b/tests/language_2/control_flow_collections/for_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 import 'package:expect/expect.dart';
 
 import 'utils.dart';
diff --git a/tests/language_2/control_flow_collections/for_variable_test.dart b/tests/language_2/control_flow_collections/for_variable_test.dart
index f866daf..47ab2e7 100644
--- a/tests/language_2/control_flow_collections/for_variable_test.dart
+++ b/tests/language_2/control_flow_collections/for_variable_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 /// Tests for how variables and scoping work with for elements.
 import 'package:expect/expect.dart';
 
diff --git a/tests/language_2/control_flow_collections/if_await_test.dart b/tests/language_2/control_flow_collections/if_await_test.dart
index 2db3f62..08d0c60 100644
--- a/tests/language_2/control_flow_collections/if_await_test.dart
+++ b/tests/language_2/control_flow_collections/if_await_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections
-
 import "package:async_helper/async_helper.dart";
 import 'package:expect/expect.dart';
 
diff --git a/tests/language_2/control_flow_collections/if_const_error_test.dart b/tests/language_2/control_flow_collections/if_const_error_test.dart
index f3645f2..87cd501 100644
--- a/tests/language_2/control_flow_collections/if_const_error_test.dart
+++ b/tests/language_2/control_flow_collections/if_const_error_test.dart
@@ -2,14 +2,138 @@
 // 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.
 
-// SharedOptions=--enable-experiment=control-flow-collections
+// SharedOptions=--enable-experiment=constant-update-2018
+
+import 'dart:collection';
+
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+final nonConstBool = true;
+final nonConstInt = 3;
+
+const dynamic nonBool = 3;
+const dynamic nonInt = "s";
 
 void main() {
-  // If cannot be used in a const collection.
-  const _ = [if (true) 1]; //# 00: compile-time error
-  const _ = [if (false) 1 else 2]; //# 01: compile-time error
-  const _ = {if (true) 1}; //# 02: compile-time error
-  const _ = {if (false) 1 else 2}; //# 03: compile-time error
-  const _ = {if (true) 1: 1}; //# 04: compile-time error
-  const _ = {if (false) 1: 1 else 2: 2}; //# 05: compile-time error
+  testList();
+  testMap();
+  testSet();
+  testShortCircuit();
+}
+
+void testList() {
+  // Condition must be constant.
+  const _ = <int>[if (nonConstBool) 1]; //# 01: compile-time error
+
+  // Condition must be Boolean.
+  const _ = <int>[if (nonBool) 1]; //# 02: compile-time error
+
+  // Then element must be constant, whether or not branch is taken.
+  const _ = <int>[if (true) nonConstInt]; //# 03: compile-time error
+  const _ = <int>[if (false) nonConstInt]; //# 04: compile-time error
+
+  // Else element must be constant, whether or not branch is taken.
+  const _ = <int>[if (true) 1 else nonConstInt]; //# 05: compile-time error
+  const _ = <int>[if (false) 1 else nonConstInt]; //# 06: compile-time error
+
+  // Then element must have right type if branch is chosen.
+  const _ = <int>[if (true) nonInt]; //# 07: compile-time error
+
+  // Else element must have right type if branch is chosen.
+  const _ = <int>[if (false) 9 else nonInt]; //# 08: compile-time error
+}
+
+void testMap() {
+  // Condition must be constant.
+  const _ = <int, int>{if (nonConstBool) 1: 1}; //# 09: compile-time error
+
+  // Condition must be Boolean.
+  const _ = <int, int>{if (nonBool) 1: 1}; //# 10: compile-time error
+
+  // Then key element must be constant, whether or not branch is taken.
+  const _ = <int, int>{if (true) nonConstInt: 1}; //# 11: compile-time error
+  const _ = <int, int>{if (false) nonConstInt: 1}; //# 12: compile-time error
+
+  // Then value element must be constant, whether or not branch is taken.
+  const _ = <int, int>{if (true) 1: nonConstInt}; //# 13: compile-time error
+  const _ = <int, int>{if (false) 1: nonConstInt}; //# 14: compile-time error
+
+  // Else key element must be constant, whether or not branch is taken.
+  const _ = <int, int>{if (true) 1 else nonConstInt: 1}; //# 15: compile-time error
+  const _ = <int, int>{if (false) 1 else nonConstInt: 1}; //# 16: compile-time error
+
+  // Else value element must be constant, whether or not branch is taken.
+  const _ = <int, int>{if (true) 1 else 1: nonConstInt}; //# 17: compile-time error
+  const _ = <int, int>{if (false) 1 else 1: nonConstInt}; //# 18: compile-time error
+
+  // Then key element must have right type if branch is chosen.
+  const _ = <int, int>{if (true) nonInt: 1}; //# 19: compile-time error
+
+  // Then value element must have right type if branch is chosen.
+  const _ = <int, int>{if (true) 1: nonInt}; //# 20: compile-time error
+
+  // Else key element must have right type if branch is chosen.
+  const _ = <int, int>{if (false) 9 else nonInt: 1}; //# 21: compile-time error
+
+  // Else value element must have right type if branch is chosen.
+  const _ = <int, int>{if (false) 9 else 1: nonInt}; //# 22: compile-time error
+
+  // Key cannot override operator.==().
+  const obj = 0.1;
+  const _ = {if (true) 0.1: 1}; //# 23: compile-time error
+  const _ = {if (true) Duration(seconds: 0): 1}; //# 24: compile-time error
+  const _ = {if (true) obj: 1}; //# 25: compile-time error
+
+  // Cannot have key collision when branch is chosen.
+  const _ = <int, int>{1: 1, if (true) 1: 1}; //# 25: compile-time error
+  const _ = <int, int>{if (true) 1: 1, if (true) 1: 1}; //# 26: compile-time error
+}
+
+void testSet() {
+  // Condition must be constant.
+  const _ = <int>{if (nonConstBool) 1}; //# 27: compile-time error
+
+  // Condition must be Boolean.
+  const _ = <int>{if (nonBool) 1}; //# 28: compile-time error
+
+  // Then element must be constant, whether or not branch is taken.
+  const _ = <int>{if (true) nonConstInt}; //# 29: compile-time error
+  const _ = <int>{if (false) nonConstInt}; //# 30: compile-time error
+
+  // Else element must be constant, whether or not branch is taken.
+  const _ = <int>{if (true) 1 else nonConstInt}; //# 31: compile-time error
+  const _ = <int>{if (false) 1 else nonConstInt}; //# 32: compile-time error
+
+  // Then element must have right type if branch is chosen.
+  const _ = <int>{if (true) nonInt}; //# 33: compile-time error
+
+  // Else element must have right type if branch is chosen.
+  const _ = <int>{if (false) 9 else nonInt}; //# 34: compile-time error
+
+  // Cannot override operator.==().
+  const obj = 0.1;
+  const _ = {if (true) 0.1}; //# 35: compile-time error
+  const _ = {if (true) Duration(seconds: 0)}; //# 36: compile-time error
+  const _ = {if (true) obj}; //# 37: compile-time error
+
+  // Cannot have collision when branch is chosen.
+  const _ = <int>{1, if (true) 1}; //# 38: compile-time error
+  const _ = <int>{if (true) 1, if (true) 1}; //# 39: compile-time error
+}
+
+void testShortCircuit() {
+  // A const expression that throws causes a compile error if it occurs inside
+  // the chosen branch of an if.
+
+  // Store null in a dynamically-typed constant to avoid the type error on "+".
+  const dynamic nil = null;
+
+  // With no else.
+  const _ = [if (true) nil + 1]; //# 40: compile-time error
+
+  // With else.
+  const _ = [if (true) nil + 1 else 1]; //# 41: compile-time error
+  const _ = [if (false) 1 else nil + 1]; //# 42: compile-time error
 }
diff --git a/tests/language_2/control_flow_collections/if_const_syntax_error_test.dart b/tests/language_2/control_flow_collections/if_const_syntax_error_test.dart
new file mode 100644
index 0000000..86cb887
--- /dev/null
+++ b/tests/language_2/control_flow_collections/if_const_syntax_error_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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 'if' in const collections is not enabled without the experimental
+// constant-update-2018 flag.
+
+// SharedOptions=--enable-experiment=no-constant-update-2018
+
+void main() {
+  // If cannot be used in a const collection.
+  const _ = [if (true) 1]; //# 00: compile-time error
+  const _ = [if (false) 1 else 2]; //# 01: compile-time error
+  const _ = {if (true) 1}; //# 02: compile-time error
+  const _ = {if (false) 1 else 2}; //# 03: compile-time error
+  const _ = {if (true) 1: 1}; //# 04: compile-time error
+  const _ = {if (false) 1: 1 else 2: 2}; //# 05: compile-time error
+}
diff --git a/tests/language_2/control_flow_collections/if_const_test.dart b/tests/language_2/control_flow_collections/if_const_test.dart
new file mode 100644
index 0000000..8eba551
--- /dev/null
+++ b/tests/language_2/control_flow_collections/if_const_test.dart
@@ -0,0 +1,244 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=constant-update-2018
+
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+// Typed as dynamic to also test spreading a value of type dynamic.
+const dynamic list = [1, 2, 3];
+const dynamic map = {1: 1, 2: 2, 3: 3};
+const dynamic set = {1, 2, 3};
+
+const dynamic dynamicTrue = true;
+const Object objectTrue = true;
+
+void main() {
+  testList();
+  testMap();
+  testSet();
+  testShortCircuit();
+  testDuplicateKeys();
+  testKeyOrder();
+}
+
+void testList() {
+  // Then if true.
+  Expect.identical(list, const <int>[1, if (true) 2, 3]);
+
+  // Nothing if false and no else.
+  Expect.identical(list, const <int>[1, if (false) 9, 2, 3]);
+
+  // Else if false.
+  Expect.identical(list, const <int>[1, if (false) 9 else 2, 3]);
+
+  // Only if.
+  Expect.identical(const [1], const <int>[if (true) 1]);
+
+  // If at beginning.
+  Expect.identical(list, const <int>[if (true) 1, 2, 3]);
+
+  // If in middle.
+  Expect.identical(list, const <int>[1, if (true) 2, 3]);
+
+  // If at end.
+  Expect.identical(list, const <int>[1, 2, if (true) 3]);
+
+  // Multiple ifs.
+  Expect.identical(list,
+      const <int>[if (true) 1, if (false) 9, 2, if (true) 3]);
+
+  // Cast condition.
+  Expect.identical(const [1], const <int>[if (dynamicTrue) 1]);
+  Expect.identical(const [1], const <int>[if (objectTrue) 1]);
+
+  // Does not flatten nested collection literal.
+  Expect.identical(const [1], const [if (true) [1]].first);
+  Expect.identical(const {1: 1}, const [if (true) {1: 1}].first);
+  Expect.identical(const {1}, const [if (true) {1}].first);
+
+  // Nested spread.
+  Expect.identical(list,
+      const <int>[if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]]);
+
+  // Nested if in then.
+  Expect.identical(const [1],
+      const <int>[if (true) if (true) 1, if (true) if (false) 9]);
+
+  // Nested if in else.
+  Expect.identical(const [1], const <int>[if (false) 9 else if (true) 1]);
+}
+
+void testMap() {
+  // Then if true.
+  Expect.identical(map, const <int, int>{1: 1, if (true) 2: 2, 3: 3});
+
+  // Nothing if false and no else.
+  Expect.identical(map, const <int, int>{1: 1, if (false) 9: 9, 2: 2, 3: 3});
+
+  // Else if false.
+  Expect.identical(map,
+      const <int, int>{1: 1, if (false) 9: 9 else 2: 2, 3: 3});
+
+  // Only if.
+  Expect.identical(const {1: 1}, const <int, int>{if (true) 1: 1});
+
+  // If at beginning.
+  Expect.identical(map, const <int, int>{if (true) 1: 1, 2: 2, 3: 3});
+
+  // If in middle.
+  Expect.identical(map, const <int, int>{1: 1, if (true) 2: 2, 3: 3});
+
+  // If at end.
+  Expect.identical(map, const <int, int>{1: 1, 2: 2, if (true) 3: 3});
+
+  // Multiple ifs.
+  Expect.identical(map,
+      const <int, int>{if (true) 1: 1, if (false) 9: 9, 2: 2, if (true) 3: 3});
+
+  // Cast condition.
+  Expect.identical(const {1: 1}, const <int, int>{if (dynamicTrue) 1: 1});
+  Expect.identical(const {1: 1}, const <int, int>{if (objectTrue) 1: 1});
+
+  // Nested spread.
+  Expect.identical(map, const <int, int>{
+    if (true) ...<int, int>{1: 1, 2: 2},
+    if (false) 9: 9 else ...<int, int>{3: 3}
+  });
+
+  // Nested if in then.
+  Expect.identical(const {1: 1},
+      const <int, int>{if (true) if (true) 1: 1, if (true) if (false) 9: 9});
+
+  // Nested if in else.
+  Expect.identical(const {1: 1},
+      const <int, int>{if (false) 9: 9 else if (true) 1: 1});
+}
+
+void testSet() {
+  // Then if true.
+  Expect.identical(set, const <int>{1, if (true) 2, 3});
+
+  // Nothing if false and no else.
+  Expect.identical(set, const <int>{1, if (false) 9, 2, 3});
+
+  // Else if false.
+  Expect.identical(set, const <int>{1, if (false) 9 else 2, 3});
+
+  // Only if.
+  Expect.identical(const <int>{1}, const <int>{if (true) 1});
+
+  // If at beginning.
+  Expect.identical(set, const <int>{if (true) 1, 2, 3});
+
+  // If in middle.
+  Expect.identical(set, const <int>{1, if (true) 2, 3});
+
+  // If at end.
+  Expect.identical(set, const <int>{1, 2, if (true) 3});
+
+  // Multiple ifs.
+  Expect.identical(set,
+      const <int>{if (true) 1, if (false) 9, 2, if (true) 3});
+
+  // Cast condition.
+  Expect.identical(const <int>{1}, const <int>{if (dynamicTrue) 1});
+  Expect.identical(const <int>{1}, const <int>{if (objectTrue) 1});
+
+  // Does not flatten nested collection literal.
+  Expect.identical(const <int>[1], const <List<int>>{if (true) [1]}.first);
+  Expect.identical(
+      const <int, int>{1: 1}, const <Map<int, int>>{if (true) {1: 1}}.first);
+  Expect.identical(const <int>{1}, const <Set<int>>{if (true) {1}}.first);
+
+  // Nested spread.
+  Expect.identical(set,
+      const <int>{if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]});
+
+  // Nested if in then.
+  Expect.identical(const <int>{1},
+      const <int>{if (true) if (true) 1, if (true) if (false) 9});
+
+  // Nested if in else.
+  Expect.identical(const <int>{1}, const <int>{if (false) 9 else if (true) 1});
+}
+
+void testShortCircuit() {
+  // A const expression that throws does not cause a compile error if it occurs
+  // inside an unchosen branch of an if.
+
+  // Store null in a dynamically-typed constant to avoid the type error on "+".
+  const dynamic nil = null;
+
+  Expect.identical(const <int>[1],
+      const <int>[if (true) 1, if (false) nil + 1]);
+  Expect.identical(const <int>[1, 2],
+      const <int>[if (true) 1 else nil + 1, if (false) nil + 1 else 2]);
+
+  Expect.identical(const <int, int>{1: 1}, const <int, int>{
+    if (true) 1: 1,
+    if (false) nil + 1: 9,
+    if (false) 9: nil + 1
+  });
+  Expect.identical(const <int, int>{1: 1, 2: 2}, const <int, int>{
+    if (true) 1: 1 else nil + 1: 9,
+    if (false) 9: nil + 1 else 2: 2
+  });
+
+  Expect.identical(const <int>{1},
+      const <int>{if (true) 1, if (false) nil + 1});
+  Expect.identical(const <int>{1, 2},
+      const <int>{if (true) 1 else nil + 1, if (false) nil + 1 else 2});
+
+  // A const expression whose value isn't the right type does not cause a
+  // compile error if it occurs inside an unchosen branch.
+  const dynamic nonInt = "s";
+
+  Expect.identical(const <int>[1], const <int>[if (true) 1, if (false) nonInt]);
+  Expect.identical(const <int>[1, 2],
+      const <int>[if (true) 1 else nonInt, if (false) nonInt else 2]);
+
+  Expect.identical(const <int, int>{1: 1}, const <int, int>{
+    if (true) 1: 1,
+    if (false) nonInt: 9,
+    if (false) 9: nonInt
+  });
+  Expect.identical(const <int, int>{1: 1, 2: 2}, const <int, int>{
+    if (true) 1: 1 else nonInt: 9,
+    if (false) 9: nonInt else 2: 2
+  });
+
+  Expect.identical(const <int>{1}, const <int>{if (true) 1, if (false) nonInt});
+  Expect.identical(const <int>{1, 2},
+      const <int>{if (true) 1 else nonInt, if (false) nonInt else 2});
+}
+
+void testDuplicateKeys() {
+  // Duplicate keys from unchosen branches are not an error.
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    if (false) 1: 1,
+    if (true) 2: 2 else 3: 3,
+    3: 3
+  });
+
+  Expect.setEquals(set, const <int>{1, if (false) 1, if (true) 2 else 3, 3});
+}
+
+void testKeyOrder() {
+  // Canonicalization isn't affected by which elements are conditional.
+  Expect.identical(map,
+      const <int, int>{1: 1, if (true) 2: 2, if (false) 9: 9, 3: 3});
+  Expect.identical(map,
+      const <int, int>{if (false) 9: 9 else 1: 1, 2: 2, if (true) 3: 3});
+
+  Expect.identical(set, const <int>{1, if (true) 2, if (false) 9, 3});
+  Expect.identical(set, const <int>{if (false) 9 else 1, 2, if (true) 3});
+
+  // Ordering does affect canonicalization.
+  Expect.notIdentical(map, const <int, int>{1: 1, if (true) 3: 3, 2: 2});
+  Expect.notIdentical(set, const <int>{1, if (true) 3, 2});
+}
diff --git a/tests/language_2/control_flow_collections/if_inference_test.dart b/tests/language_2/control_flow_collections/if_inference_test.dart
index 0c73618..11c7b95 100644
--- a/tests/language_2/control_flow_collections/if_inference_test.dart
+++ b/tests/language_2/control_flow_collections/if_inference_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 // Test how control flow interacts with inference.
 import 'package:expect/expect.dart';
 
diff --git a/tests/language_2/control_flow_collections/if_null_condition_test.dart b/tests/language_2/control_flow_collections/if_null_condition_test.dart
index c5a1e96..fbfe3b9 100644
--- a/tests/language_2/control_flow_collections/if_null_condition_test.dart
+++ b/tests/language_2/control_flow_collections/if_null_condition_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections
-
 import 'package:expect/expect.dart';
 
 void main() {
diff --git a/tests/language_2/control_flow_collections/if_promotion_test.dart b/tests/language_2/control_flow_collections/if_promotion_test.dart
index 5622a47..382db01 100644
--- a/tests/language_2/control_flow_collections/if_promotion_test.dart
+++ b/tests/language_2/control_flow_collections/if_promotion_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections
-
 class A {
   var a = "a";
 }
diff --git a/tests/language_2/control_flow_collections/if_runtime_error_test.dart b/tests/language_2/control_flow_collections/if_runtime_error_test.dart
index 8e48bea..1dba5b8 100644
--- a/tests/language_2/control_flow_collections/if_runtime_error_test.dart
+++ b/tests/language_2/control_flow_collections/if_runtime_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 import 'package:expect/expect.dart';
 
 void main() {
diff --git a/tests/language_2/control_flow_collections/if_test.dart b/tests/language_2/control_flow_collections/if_test.dart
index c835dd6..9338987 100644
--- a/tests/language_2/control_flow_collections/if_test.dart
+++ b/tests/language_2/control_flow_collections/if_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 import 'package:expect/expect.dart';
 
 import 'utils.dart';
diff --git a/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart b/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart
index 452ac9b..ae4fee4 100644
--- a/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart
+++ b/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 // Test cases where the syntax is ambiguous between maps and sets when control
 // flow elements contain spreads.
 import 'dart:collection';
diff --git a/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart b/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart
index 6ce77de..bf5f685 100644
--- a/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart
+++ b/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 // Test cases where the syntax is ambiguous between maps and sets because of
 // spreads inside control flow.
 import 'dart:collection';
diff --git a/tests/language_2/control_flow_collections/syntax_error_test.dart b/tests/language_2/control_flow_collections/syntax_error_test.dart
index e0f0ba8..8b9fa65 100644
--- a/tests/language_2/control_flow_collections/syntax_error_test.dart
+++ b/tests/language_2/control_flow_collections/syntax_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
-
 void main() {
   // No then element.
   var _ = [if (true)]; //# 00: syntax error
diff --git a/tests/language_2/control_flow_collections/syntax_test.dart b/tests/language_2/control_flow_collections/syntax_test.dart
index 0810aec..0ed9829 100644
--- a/tests/language_2/control_flow_collections/syntax_test.dart
+++ b/tests/language_2/control_flow_collections/syntax_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections
-
 // Tests syntax edge cases.
 import 'package:expect/expect.dart';
 
diff --git a/tests/language_2/control_flow_collections/type_error_test.dart b/tests/language_2/control_flow_collections/type_error_test.dart
index 91e0ebb..63f6706 100644
--- a/tests/language_2/control_flow_collections/type_error_test.dart
+++ b/tests/language_2/control_flow_collections/type_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=control-flow-collections
-
 void main() {
   // Non-Boolean if condition.
   var _ = <int>[if (1) 2]; //# 00: compile-time error
diff --git a/tests/language_2/covariant_subtyping_with_substitution_test.dart b/tests/language_2/covariant_subtyping_with_substitution_test.dart
deleted file mode 100644
index 7cf2b52..0000000
--- a/tests/language_2/covariant_subtyping_with_substitution_test.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2017, 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';
-
-typedef F<T>(T x);
-
-class B<T> {
-  void f(F<T> x) {}
-}
-
-abstract class I<U> {
-  void f(U x);
-}
-
-class C<V> extends B<V> implements I<F<V>> {}
-
-void acceptsObject(Object o) {}
-
-void acceptsNum(num n) {}
-
-void g(I<F<num>> i) {
-  i.f(acceptsObject);
-  // i.f has static type (F<num>)->void, or ((num)->void)->void.  Which means we
-  // are statically allowed to pass acceptsNum to it.  However, if i's runtime
-  // type is C<Object>, then it extends B<Object>, so its f function requires
-  // its argument to be F<Object>.  This means that passing acceptsNum to f
-  // would violate soundness (since acceptsNum has type F<num>, and F<num> is a
-  // supertype of F<Object>).  So we expect a type error here.
-  Expect.throwsTypeError(() => i.f(acceptsNum));
-}
-
-void main() {
-  g(new C<Object>());
-}
diff --git a/tests/language_2/example_constructor_test.dart b/tests/language_2/example_constructor_test.dart
index df2565a..f015b07 100644
--- a/tests/language_2/example_constructor_test.dart
+++ b/tests/language_2/example_constructor_test.dart
@@ -13,9 +13,9 @@
 }
 
 class A {
-  A(int x) : x = rec(2) {
-    Expect.equals(1, x); // Parameter x
-    Expect.equals(2, this.x);
+  A(int x) : x = rec(4) {
+    Expect.equals(3, x); // Parameter x
+    Expect.equals(4, this.x);
     rec(5);
   }
   final int x;
@@ -23,9 +23,9 @@
 
 class B extends A {
   B(this.a, int y, int z)
-      : z = rec(3),
-        y = rec(4),
-        super(rec(1)) {
+      : z = rec(1),
+        y = rec(2),
+        super(rec(3)) {
     rec(6);
   }
   int a;
@@ -36,8 +36,8 @@
 main() {
   var test = new B(rec(0), 0, 0);
   Expect.equals(0, test.a);
-  Expect.equals(2, test.x);
-  Expect.equals(4, test.y);
-  Expect.equals(3, test.z);
+  Expect.equals(4, test.x);
+  Expect.equals(2, test.y);
+  Expect.equals(1, test.z);
   Expect.equals("0 1 2 3 4 5 6 ", trace);
 }
diff --git a/tests/language_2/extension_methods/syntax/extension_methods.dart b/tests/language_2/extension_methods/syntax/extension_methods.dart
new file mode 100644
index 0000000..51013db
--- /dev/null
+++ b/tests/language_2/extension_methods/syntax/extension_methods.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=extension-methods
+
+import 'package:expect/expect.dart';
+
+class C {
+  int get one => 1;
+}
+
+extension E on C {
+  int get two => 2;
+}
+
+main() {
+  C c = C();
+  var result = c.one + c.two;
+  Expect.equals(result, 3);
+}
diff --git a/tests/language_2/generic_is_check_test.dart b/tests/language_2/generic_is_check_test.dart
index 810964c..5cfa38a 100644
--- a/tests/language_2/generic_is_check_test.dart
+++ b/tests/language_2/generic_is_check_test.dart
@@ -9,7 +9,7 @@
 }
 
 main() {
-  Expect.isTrue(new A().foo());
+  Expect.isFalse(new A().foo());
   Expect.isTrue(new A<int>().foo());
   Expect.isFalse(new A<String>().foo());
 }
diff --git a/tests/language_2/initializer_super_last_test.dart b/tests/language_2/initializer_super_last_test.dart
index 73f18d0d..19ad3fa 100644
--- a/tests/language_2/initializer_super_last_test.dart
+++ b/tests/language_2/initializer_super_last_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 201, 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=--assert_initializer
+// VMOptions=--enable-asserts
 //
 // Dart test program testing assert statements.
 
diff --git a/tests/language_2/known_identifier_usage_error_test.dart b/tests/language_2/known_identifier_usage_error_test.dart
index 9c96dc1..0d56f26 100644
--- a/tests/language_2/known_identifier_usage_error_test.dart
+++ b/tests/language_2/known_identifier_usage_error_test.dart
@@ -21,7 +21,7 @@
 import 'dart:async';
 
 Future<int> f1() async {
-  int async = 1; //# 01: syntax error
+  int async = 1;
   int await = 1; //# 02: syntax error
   int yield = 1; //# 03: syntax error
 
@@ -32,7 +32,7 @@
 }
 
 Stream<int> f2() async* {
-  int async = 1; //# 04: syntax error
+  int async = 1;
   int await = 1; //# 05: syntax error
   int yield = 1; //# 06: syntax error
 
@@ -43,7 +43,7 @@
 }
 
 Iterable<int> f3() sync* {
-  int async = 1; //# 07: syntax error
+  int async = 1;
   int await = 1; //# 08: syntax error
   int yield = 1; //# 09: syntax error
 
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 2f8711e..921c002 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -67,7 +67,7 @@
 [ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $mode == debug && $runtime == vm ]
 built_in_identifier_type_annotation_test/set: Crash # Not supported by legacy VM front-end.
 
-[ $compiler != compare_analyzer_cfe && $compiler != dart2js && $compiler != spec_parser && !$fasta && $strong ]
+[ $compiler != compare_analyzer_cfe && $compiler != dart2js && $compiler != spec_parser && !$fasta ]
 compile_time_constant_static5_test/11: CompileTimeError # Issue 30546
 compile_time_constant_static5_test/16: CompileTimeError # Issue 30546
 compile_time_constant_static5_test/21: CompileTimeError # Issue 30546
@@ -93,140 +93,6 @@
 [ $compiler != dart2js && $compiler != dartdevc && !$checked ]
 function_type/*: Skip # Needs checked mode.
 
-[ $compiler != dart2js && !$fasta && !$strong ]
-implicit_creation/implicit_new_constructor_generic_test: Fail # No support for implicit creation.
-implicit_creation/implicit_new_constructor_test: Fail # No support for implicit creation.
-implicit_creation/implicit_new_prefix_constructor_generic_test: Fail # No support for implicit creation.
-implicit_creation/implicit_new_prefix_constructor_test: Fail # No support for implicit creation.
-
-[ $compiler != spec_parser && $runtime != none && !$checked && !$strong ]
-closure_type_test: RuntimeError
-map_literal1_test/01: MissingCompileTimeError
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/02: RuntimeError # Requires type check.
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError # Issue #31426
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue #31426
-
-[ $compiler != spec_parser && !$strong ]
-class_literal_static_test: MissingCompileTimeError # Requires strong mode
-class_literal_static_test/none: Pass
-class_override_test: MissingCompileTimeError # Requires strong mode
-closure_internals_test/01: MissingCompileTimeError # Requires strong mode
-closure_internals_test/02: MissingCompileTimeError # Requires strong mode
-closure_internals_test/03: MissingCompileTimeError # Requires strong mode
-compile_time_constant_k_test/01: MissingCompileTimeError # Requires strong mode
-compile_time_constant_k_test/02: MissingCompileTimeError # Requires strong mode
-compile_time_constant_k_test/03: MissingCompileTimeError # Requires strong mode
-compile_time_constant_static2_test: Skip # Requires strong mode
-compile_time_constant_static3_test: Skip # Requires strong mode
-compile_time_constant_static4_test: Skip # Requires strong mode
-compile_time_constant_static5_test: Skip # Requires strong mode
-compile_time_constant_static_test: Skip # Requires strong mode
-crash_6725_test/01: MissingCompileTimeError # Requires strong mode
-deferred_super_dependency_test/01: MissingCompileTimeError # Requires strong mode
-double_to_string_as_exponential2_test/*: MissingCompileTimeError
-double_to_string_as_exponential2_test/none: Pass
-double_to_string_as_fixed2_test/*: MissingCompileTimeError
-double_to_string_as_fixed2_test/none: Pass
-double_to_string_as_precision2_test/*: MissingCompileTimeError
-double_to_string_as_precision2_test/none: Pass
-initializing_formal_type_annotation_test/01: MissingCompileTimeError # Requires strong mode
-initializing_formal_type_annotation_test/02: MissingCompileTimeError # Requires strong mode
-is_malformed_type_test/94: MissingCompileTimeError # Requires strong mode
-is_malformed_type_test/95: MissingCompileTimeError # Requires strong mode
-is_malformed_type_test/96: MissingCompileTimeError # Requires strong mode
-is_malformed_type_test/97: MissingCompileTimeError # Requires strong mode
-is_malformed_type_test/98: MissingCompileTimeError # Requires strong mode
-is_malformed_type_test/99: MissingCompileTimeError # Requires strong mode
-is_not_class2_test/01: MissingCompileTimeError # Requires strong mode
-is_not_class2_test/none: Skip # No interesting functionality in this configuration.
-isnot_malformed_type_test/01: MissingCompileTimeError
-issue11724_test/01: MissingCompileTimeError
-issue1363_test/01: MissingCompileTimeError # Requires strong mode
-issue15606_test/01: MissingCompileTimeError # Requires strong mode
-issue18628_1_test/01: MissingCompileTimeError # Requires strong mode
-issue18628_2_test/01: MissingCompileTimeError # Requires strong mode
-known_identifier_prefix_error_test/*: MissingCompileTimeError # Requires strong mode
-known_identifier_prefix_error_test/none: Pass
-map_literal3_test/01: MissingCompileTimeError
-map_literal3_test/02: MissingCompileTimeError
-map_literal3_test/03: MissingCompileTimeError
-map_literal3_test/04: MissingCompileTimeError
-map_literal4_test/01: MissingCompileTimeError
-map_literal4_test/02: MissingCompileTimeError
-map_literal4_test/03: MissingCompileTimeError
-map_literal4_test/04: MissingCompileTimeError
-map_literal4_test/05: MissingCompileTimeError
-map_literal4_test/06: MissingCompileTimeError
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/03: MissingCompileTimeError # Issue #31426
-number_identifier_test/05: MissingCompileTimeError
-number_identifier_test/08: MissingCompileTimeError
-number_identifier_test/09: MissingCompileTimeError
-on_catch_malformed_type_test: MissingCompileTimeError
-operator5_test: MissingCompileTimeError
-operator_equals_test: MissingCompileTimeError
-optimized_constant_array_string_access_test: MissingCompileTimeError
-redirecting_factory_default_values_test/03: MissingCompileTimeError
-redirecting_factory_incompatible_signature_test/01: MissingCompileTimeError
-redirecting_factory_infinite_steps_test/01: MissingCompileTimeError
-redirecting_factory_malbounded_test/01: MissingCompileTimeError
-type_literal_prefix_call_test/00: MissingCompileTimeError
-type_parameter_test/*: MissingCompileTimeError
-type_parameter_test/none: Pass
-type_promotion_assign_test/*: MissingCompileTimeError
-type_promotion_assign_test/none: Pass
-type_promotion_closure_test/*: MissingCompileTimeError
-type_promotion_closure_test/05: Pass
-type_promotion_closure_test/08: Pass
-type_promotion_closure_test/none: Pass
-type_promotion_local_test/*: MissingCompileTimeError
-type_promotion_local_test/none: Pass
-type_promotion_logical_and_test/01: MissingCompileTimeError
-type_promotion_logical_and_test/02: MissingCompileTimeError
-type_promotion_logical_and_test/03: MissingCompileTimeError
-type_promotion_more_specific_test/02: MissingCompileTimeError
-type_promotion_more_specific_test/06: MissingCompileTimeError
-type_promotion_more_specific_test/07: MissingCompileTimeError
-type_promotion_more_specific_test/09: MissingCompileTimeError
-type_promotion_more_specific_test/10: MissingCompileTimeError
-type_promotion_more_specific_test/11: MissingCompileTimeError
-type_promotion_multiple_test/*: MissingCompileTimeError
-type_promotion_multiple_test/none: Pass
-vm/type_vm_test/01: MissingCompileTimeError
-vm/type_vm_test/02: MissingCompileTimeError
-vm/type_vm_test/03: MissingCompileTimeError
-vm/type_vm_test/04: MissingCompileTimeError
-vm/type_vm_test/05: MissingCompileTimeError
-vm/type_vm_test/06: MissingCompileTimeError
-vm/type_vm_test/08: MissingCompileTimeError
-vm/type_vm_test/09: MissingCompileTimeError
-vm/type_vm_test/10: MissingCompileTimeError
-vm/type_vm_test/11: MissingCompileTimeError
-vm/type_vm_test/12: MissingCompileTimeError
-vm/type_vm_test/13: MissingCompileTimeError
-vm/type_vm_test/14: MissingCompileTimeError
-vm/type_vm_test/15: MissingCompileTimeError
-vm/type_vm_test/16: MissingCompileTimeError
-vm/type_vm_test/22: MissingCompileTimeError
-vm/type_vm_test/24: MissingCompileTimeError
-vm/type_vm_test/25: MissingCompileTimeError
-vm/type_vm_test/26: MissingCompileTimeError
-vm/type_vm_test/27: MissingCompileTimeError
-void/return_future_future_or_void_sync_error1_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
-void/void_block_return_test/00: MissingCompileTimeError # Requires strong mode
-void/void_type_callbacks_test: Skip # Requires strong mode
-void/void_type_function_types_test: Skip # Requires strong mode
-void/void_type_override_test: Skip # Requires strong mode
-void/void_type_usage_test: Skip # Requires strong mode
-wrong_number_type_arguments_test/*: MissingCompileTimeError # Requires strong mode
-wrong_number_type_arguments_test/none: Pass
-
-[ $runtime != none && !$strong ]
-map_literal11_test/none: MissingRuntimeError
-map_literal7_test: RuntimeError # Requires strong mode
-
-[ $checked && !$strong ]
-type_parameter_test/05: Pass
-
 [ !$preview_dart_2 && ($runtime == dart_precompiled || $runtime == vm) ]
 *: SkipByDesign # Deprecating all Dart1 modes of execution
 
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 7f34dad..6c03694 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -5,32 +5,91 @@
 
 [ $compiler == dart2js ]
 arithmetic_int64_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+async_await_test/02: RuntimeError
+async_await_test/03: RuntimeError
+async_await_test/none: RuntimeError
 async_star/async_star_await_for_test: RuntimeError
 async_star/async_star_cancel_test: RuntimeError
 async_star_cancel_while_paused_test: RuntimeError # Issue 22853
+async_star_test/02: RuntimeError
 bit_operations_test: RuntimeError, OK # non JS number semantics
+bit_operations_test: RuntimeError
 bit_operations_test/03: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 bit_operations_test/04: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 bit_operations_test/none: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+branch_canonicalization_test: RuntimeError
 call_method_as_cast_test/06: RuntimeError
 call_method_implicit_tear_off_implements_function_test/05: RuntimeError
 call_method_implicit_tear_off_implements_function_test/06: RuntimeError
 call_method_is_check_test/06: RuntimeError
 call_method_must_not_be_field_test/03: RuntimeError # Issue 32155
 call_method_must_not_be_getter_test/03: RuntimeError # Issue 32155
+canonical_const2_test: RuntimeError, OK # non JS number semantics
+closure_type_arguments_test: Crash # Issue 34272
+compile_time_constant_static5_test/11: CompileTimeError
+compile_time_constant_static5_test/16: CompileTimeError
+compile_time_constant_static5_test/21: CompileTimeError
+compile_time_constant_static5_test/23: CompileTimeError
+conditional_rewrite_test: RuntimeError
 config_import_corelib_test: CompileTimeError # we need a special platform.dill file for categories=all. Once we fix that, all dart:* are supported when using '--categories=all' so this will become a RuntimeError, OK.
 config_import_test: RuntimeError # Test flag is not passed to the compiler.
+const_constructor3_test/04: MissingCompileTimeError # OK - Subtype check uses JS number semantics.
 const_constructor_nonconst_param_test/01: MissingCompileTimeError
 const_dynamic_type_literal_test/03: Pass # but it shouldn't until we fix issue 17207
+const_evaluation_test/01: RuntimeError
+const_list_test: RuntimeError
+const_map2_test/00: MissingCompileTimeError
+const_map3_test/00: MissingCompileTimeError
+const_map4_test: RuntimeError
+const_switch_test/02: RuntimeError, OK # constant identity based on JS constants
+const_switch_test/04: RuntimeError, OK # constant identity based on JS constants
+constructor12_test: RuntimeError
+constructor_named_arguments_test/none: RuntimeError
+covariant_subtyping_test: Crash # Unsupported operation: Unsupported type parameter type node E.
+ct_const_test: RuntimeError
+deferred_load_library_wrong_args_test/01: CompileTimeError
+deferred_not_loaded_check_test: RuntimeError # Test out of date. Issue 31933
+deferred_redirecting_factory_test: RuntimeError
 deopt_inlined_function_lazy_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 deopt_smi_op_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in dart2js; bug #11551.
+double_int_to_string_test: RuntimeError, OK # non JS number semantics
+dynamic_prefix_core_test/none: CompileTimeError
+enum_mirror_test: RuntimeError
+example_constructor_test: RuntimeError
+expect_test: RuntimeError, OK # Issue 13080
 external_test/10: CompileTimeError # External non-js-interop function are treated as compile-time errors.
+external_test/10: MissingRuntimeError
 external_test/13: CompileTimeError # External non-js-interop function are treated as compile-time errors.
+external_test/13: MissingRuntimeError
 external_test/20: CompileTimeError # External non-js-interop function are treated as compile-time errors.
+external_test/20: MissingRuntimeError
+external_test/21: CompileTimeError
+external_test/24: CompileTimeError
+flatten_test/05: MissingRuntimeError
+flatten_test/08: MissingRuntimeError
+flatten_test/09: MissingRuntimeError
+flatten_test/12: MissingRuntimeError
+full_stacktrace1_test: RuntimeError # Issue 12698
+full_stacktrace2_test: RuntimeError # Issue 12698
+full_stacktrace3_test: RuntimeError # Issue 12698
 function_propagation_test: RuntimeError
+function_subtype_inline2_test: RuntimeError
+generic_function_bounds_test: RuntimeError
+generic_function_dcall_test/01: RuntimeError
+generic_instanceof2_test: RuntimeError
+generic_is_check_test: RuntimeError
+generic_methods_bounds_test/02: MissingRuntimeError
+generic_no_such_method_dispatcher_simple_test: CompileTimeError
+generic_no_such_method_dispatcher_test: CompileTimeError
+generic_tearoff_test: CompileTimeError
 guess_cid_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+identical_closure2_test: RuntimeError # non JS number semantics
 identical_closure2_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+if_null_precedence_test/none: RuntimeError
+infinity_test: RuntimeError # non JS number semantics - Issue 4984
+instance_creation_in_function_annotation_test: RuntimeError
+instantiate_tearoff_of_call_test: CompileTimeError
 instantiate_tearoff_of_call_test: RuntimeError
 int2_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 int64_literal_test/01: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
@@ -45,23 +104,105 @@
 int64_literal_test/17: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 int64_literal_test/19: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 int64_literal_test/none: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+integer_division_by_zero_test: RuntimeError # Issue 8301
+internal_library_test/02: Crash
+invocation_mirror_invoke_on2_test: RuntimeError
+invocation_mirror_invoke_on_test: RuntimeError
+issue21079_test: RuntimeError
 issue23244_test: RuntimeError # Isolates - enum canonicalization - Issue 23244
+issue31596_super_test/01: CompileTimeError
+issue31596_super_test/03: CompileTimeError
+left_shift_test: RuntimeError # non JS number semantics
 library_env_test/has_io_support: RuntimeError, OK # dart2js doesn't support io when compiling on --categories=Client
 library_env_test/has_mirror_support: Fail # mirrors not supported on web
+library_env_test/has_mirror_support: RuntimeError
 library_env_test/has_no_html_support: RuntimeError, OK
 library_env_test/has_no_mirror_support: Pass # fails for the wrong reason.
 list_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+local_function2_test/none: RuntimeError
+local_function3_test/none: RuntimeError
+local_function_test/none: RuntimeError
+minify_closure_variable_collision_test: CompileTimeError
 mint_arithmetic_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+mint_arithmetic_test: RuntimeError # non JS number semantics
 mint_compares_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 mint_identical_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+mixin_illegal_super_use_test/01: MissingCompileTimeError
+mixin_illegal_super_use_test/04: MissingCompileTimeError
+mixin_illegal_super_use_test/07: MissingCompileTimeError
+mixin_illegal_super_use_test/10: MissingCompileTimeError
+mixin_illegal_super_use_test/11: MissingCompileTimeError
+mixin_illegal_superclass_test/01: MissingCompileTimeError
+mixin_illegal_superclass_test/02: MissingCompileTimeError
+mixin_illegal_superclass_test/03: MissingCompileTimeError
+mixin_illegal_superclass_test/04: MissingCompileTimeError
+mixin_illegal_superclass_test/05: MissingCompileTimeError
+mixin_illegal_superclass_test/06: MissingCompileTimeError
+mixin_illegal_superclass_test/07: MissingCompileTimeError
+mixin_illegal_superclass_test/08: MissingCompileTimeError
+mixin_illegal_superclass_test/09: MissingCompileTimeError
+mixin_illegal_superclass_test/10: MissingCompileTimeError
+mixin_illegal_superclass_test/11: MissingCompileTimeError
+mixin_illegal_superclass_test/12: MissingCompileTimeError
+mixin_illegal_superclass_test/13: MissingCompileTimeError
+mixin_illegal_superclass_test/14: MissingCompileTimeError
+mixin_illegal_superclass_test/15: MissingCompileTimeError
+mixin_illegal_superclass_test/16: MissingCompileTimeError
+mixin_illegal_superclass_test/17: MissingCompileTimeError
+mixin_illegal_superclass_test/18: MissingCompileTimeError
+mixin_illegal_superclass_test/19: MissingCompileTimeError
+mixin_illegal_superclass_test/20: MissingCompileTimeError
+mixin_illegal_superclass_test/21: MissingCompileTimeError
+mixin_illegal_superclass_test/22: MissingCompileTimeError
+mixin_illegal_superclass_test/23: MissingCompileTimeError
+mixin_illegal_superclass_test/24: MissingCompileTimeError
+mixin_illegal_superclass_test/25: MissingCompileTimeError
+mixin_illegal_superclass_test/26: MissingCompileTimeError
+mixin_illegal_superclass_test/27: MissingCompileTimeError
+mixin_illegal_superclass_test/28: MissingCompileTimeError
+mixin_illegal_superclass_test/29: MissingCompileTimeError
+mixin_illegal_superclass_test/30: MissingCompileTimeError
+mixin_method_override_test/G5: Skip # Issue 34354
+mock_writable_final_field_test: RuntimeError # Issue 30847
+mock_writable_final_private_field_test: RuntimeError # Issue 17526, 30847
+modulo_test: RuntimeError # non JS number semantics
+named_parameters_default_eq_test/none: RuntimeError
+nan_identical_test: RuntimeError # Issue 11551
+nested_generic_closure_test: RuntimeError
+no_main_test/01: CompileTimeError
+no_such_method_mock_test: RuntimeError
+null_no_such_method_test: CompileTimeError
+number_identity2_test: RuntimeError
 number_identity_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+numbers_test: RuntimeError, OK # non JS number semantics
+parser_quirks_test: CompileTimeError
 partial_instantiation_eager_bounds_check_test: RuntimeError # Issue #34295
 partial_tearoff_instantiation_test/05: Pass # for the wrong reason.
 partial_tearoff_instantiation_test/06: Pass # for the wrong reason.
 partial_tearoff_instantiation_test/07: Pass # for the wrong reason.
 partial_tearoff_instantiation_test/08: Pass # for the wrong reason.
 private_method_tearoff_test: RuntimeError
+redirecting_factory_reflection_test: RuntimeError
+regress_23408_test: CompileTimeError
+regress_24283_test: RuntimeError, OK # non JS number semantics
+regress_28255_test: RuntimeError
+regress_29025_test: CompileTimeError
+regress_29405_test: CompileTimeError
+regress_30339_test: CompileTimeError
+setter_no_getter_test/01: CompileTimeError
+stacktrace_demangle_ctors_test: RuntimeError # Issue 12698
+stacktrace_rethrow_error_test/none: RuntimeError # Issue 12698
+stacktrace_rethrow_error_test/withtraceparameter: RuntimeError # Issue 12698
+stacktrace_rethrow_nonerror_test: RuntimeError # Issue 12698
+super_bound_closure_test/none: CompileTimeError
+super_call4_test/01: MissingCompileTimeError
+super_test: RuntimeError
+tearoff_dynamic_test: RuntimeError
+truncdiv_test: RuntimeError # non JS number semantics - Issue 15246
 type_constants_test/none: RuntimeError # Issue 35052
+type_error_test: RuntimeError
+type_literal_test: RuntimeError
+type_promotion_more_specific_test/04: CompileTimeError
 vm/*: SkipByDesign # Tests for the VM.
 
 [ $compiler != dart2js ]
@@ -72,13 +213,11 @@
 
 [ $compiler == dart2js && $runtime == chrome ]
 field_override_optimization_test: RuntimeError
+stacktrace_test: RuntimeError
 
 [ $compiler == dart2js && $runtime == chrome && $system == macos ]
 await_future_test: Pass, Timeout # Issue 26735
 
-[ $compiler == dart2js && $runtime == chrome && $strong ]
-stacktrace_test: RuntimeError
-
 [ $compiler == dart2js && $runtime == chromeOnAndroid ]
 override_field_test/02: Pass, Slow # TODO(kasperl): Please triage.
 
@@ -86,13 +225,11 @@
 conditional_import_string_test: SkipByDesign # No XHR in d8
 conditional_import_test: SkipByDesign # No XHR in d8
 implicit_creation/implicit_new_constructor_generic_test: Pass
+stacktrace_test: RuntimeError
 
 [ $compiler == dart2js && $runtime == d8 && !$checked ]
 field_override_optimization_test: RuntimeError
 
-[ $compiler == dart2js && $runtime == d8 && $strong ]
-stacktrace_test: RuntimeError
-
 [ $compiler == dart2js && $runtime == ff ]
 field_override_optimization_test: RuntimeError
 round_test: Pass, Fail, OK # Fixed in ff 35. Common JavaScript engine Math.round bug.
@@ -113,24 +250,15 @@
 syncstar_dcall_type_test: RuntimeError # dart2js misplaces check in Iterator, not Iterable.
 
 [ $compiler == dart2js && $runtime == safari ]
+async_throw_in_catch_test/none: Pass, RuntimeError
 field_override_optimization_test: RuntimeError
 round_test: Fail, OK # Common JavaScript engine Math.round bug.
-
-[ $compiler == dart2js && $runtime == safari && $strong ]
-async_throw_in_catch_test/none: Pass, RuntimeError
 stacktrace_test: RuntimeError
 
 [ $compiler == dart2js && $system == windows ]
 string_literals_test: Pass, RuntimeError # Failures on dart2js-win7-chrome-4-4-be and dart2js-win7-ie11ff-4-4-be
 
 [ $compiler == dart2js && $checked ]
-covariant_subtyping_test: CompileTimeError
-
-[ $compiler == dart2js && $checked && $minified && $strong ]
-inline_super_field_test: Crash
-typedef_is_test: Crash
-
-[ $compiler == dart2js && $checked && $strong ]
 assign_instance_method_test: RuntimeError
 async_await_foreign_test: RuntimeError
 async_star_cancel_while_paused_test: RuntimeError
@@ -222,6 +350,7 @@
 constructor_named_arguments_test/01: MissingCompileTimeError
 constructor_named_arguments_test/none: RuntimeError
 covariant_override/runtime_check_test: RuntimeError
+covariant_subtyping_test: CompileTimeError
 covariant_subtyping_test: RuntimeError
 deferred_constraints_type_annotation_test/as_operation: MissingCompileTimeError
 deferred_constraints_type_annotation_test/catch_check: MissingCompileTimeError
@@ -374,12 +503,16 @@
 type_parameter_test/09: Crash # Internal Error: Unexpected type variable in static context.
 type_variable_scope_test/03: Crash # Internal Error: Unexpected type variable in static context.
 
+[ $compiler == dart2js && $checked && $minified ]
+inline_super_field_test: Crash
+typedef_is_test: Crash
+
 [ $compiler == dart2js && !$checked ]
 bool_check_test: RuntimeError
 bool_condition_check_test: RuntimeError
 issue31596_super_test/05: RuntimeError
 
-[ $compiler == dart2js && $host_checked && $strong ]
+[ $compiler == dart2js && $host_checked ]
 async_return_types_test/nestedFuture: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
 async_star_cancel_while_paused_test: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
 await_not_started_immediately_test: Crash # Assertion failure: Runtime type information not available for type_variable_local(bindCallback.R) in (local(_RootZone.bindCallback#)) for j:closure_call(_RootZone_bindCallback_closure.call).
@@ -402,22 +535,6 @@
 type_promotion_logical_and_test/01: MissingCompileTimeError
 
 [ $compiler == dart2js && $minified ]
-cyclic_type2_test: RuntimeError # Issue 31054
-cyclic_type_test/0*: RuntimeError # Issue 31054
-f_bounded_quantification4_test: RuntimeError # Issue 31054
-f_bounded_quantification5_test: RuntimeError # Issue 31054
-generic_closure_test/01: RuntimeError # Uses runtimeType.toString()
-mixin_mixin2_test: RuntimeError # Issue 31054
-mixin_mixin3_test: RuntimeError # Issue 31054
-mixin_mixin4_test: RuntimeError # Issue 31054
-mixin_mixin5_test: RuntimeError # Issue 31054
-mixin_mixin6_test: RuntimeError # Issue 31054
-mixin_mixin_bound2_test: RuntimeError # Issue 31054
-mixin_mixin_bound_test: RuntimeError # Issue 31054
-mixin_mixin_type_arguments_test: RuntimeError # Issue 31054
-runtime_type_function_test: RuntimeError # Uses runtimeType.toString()
-
-[ $compiler == dart2js && $minified && $strong ]
 async_return_types_test/nestedFuture: Crash # Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]
 async_star_cancel_while_paused_test: Crash # Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]
 await_not_started_immediately_test: Crash # Assertion failure: Runtime type information not available for type_variable_local(bindCallback.R) in (local(_RootZone.bindCallback#)) for j:closure_call(_RootZone_bindCallback_closure.call).
@@ -427,6 +544,11 @@
 class_literal_static_test/07: MissingCompileTimeError
 config_import_corelib_test: CompileTimeError
 covariant_subtyping_test: RuntimeError
+cyclic_type2_test: RuntimeError # Issue 31054
+cyclic_type_test/0*: RuntimeError # Issue 31054
+f_bounded_quantification4_test: RuntimeError # Issue 31054
+f_bounded_quantification5_test: RuntimeError # Issue 31054
+generic_closure_test/01: RuntimeError # Uses runtimeType.toString()
 invocation_mirror2_test: RuntimeError # mirrors not supported
 invocation_mirror_test: RuntimeError
 issue23244_test: Crash # Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]
@@ -434,7 +556,14 @@
 many_overridden_no_such_method_test: RuntimeError
 map_literal3_test/03: MissingCompileTimeError
 mixin_generic_test: RuntimeError # Issue 12605
-mixin_mixin_type_arguments_test: RuntimeError
+mixin_mixin2_test: RuntimeError # Issue 31054
+mixin_mixin3_test: RuntimeError # Issue 31054
+mixin_mixin4_test: RuntimeError # Issue 31054
+mixin_mixin5_test: RuntimeError # Issue 31054
+mixin_mixin6_test: RuntimeError # Issue 31054
+mixin_mixin_bound2_test: RuntimeError # Issue 31054
+mixin_mixin_bound_test: RuntimeError # Issue 31054
+mixin_mixin_type_arguments_test: RuntimeError # Issue 31054
 no_such_method_native_test: RuntimeError
 no_such_method_test: RuntimeError
 overridden_no_such_method_test: RuntimeError
@@ -442,156 +571,8 @@
 regress_13462_1_test: RuntimeError
 regress_18535_test: RuntimeError
 regress_21795_test: RuntimeError # Issue 12605
+runtime_type_function_test: RuntimeError # Uses runtimeType.toString()
 stack_trace_test: RuntimeError, OK # Stack trace not preserved in minified code.
 symbol_conflict_test: RuntimeError # Issue 23857
 type_literal_prefix_call_test/00: MissingCompileTimeError
 type_promotion_logical_and_test/01: MissingCompileTimeError
-
-[ $compiler == dart2js && $strong ]
-async_await_test/02: RuntimeError
-async_await_test/03: RuntimeError
-async_await_test/none: RuntimeError
-async_star_cancel_while_paused_test: RuntimeError
-async_star_test/02: RuntimeError
-bit_operations_test: RuntimeError
-branch_canonicalization_test: RuntimeError
-canonical_const2_test: RuntimeError, OK # non JS number semantics
-closure_type_arguments_test: Crash # Issue 34272
-compile_time_constant_static5_test/11: CompileTimeError
-compile_time_constant_static5_test/16: CompileTimeError
-compile_time_constant_static5_test/21: CompileTimeError
-compile_time_constant_static5_test/23: CompileTimeError
-conditional_rewrite_test: RuntimeError
-config_import_test: RuntimeError
-const_constructor3_test/04: MissingCompileTimeError # OK - Subtype check uses JS number semantics.
-const_evaluation_test/01: RuntimeError
-const_list_test: RuntimeError
-const_map2_test/00: MissingCompileTimeError
-const_map3_test/00: MissingCompileTimeError
-const_map4_test: RuntimeError
-const_switch_test/02: RuntimeError, OK # constant identity based on JS constants
-const_switch_test/04: RuntimeError, OK # constant identity based on JS constants
-constructor12_test: RuntimeError
-constructor_named_arguments_test/none: RuntimeError
-covariant_subtyping_test: Crash # Unsupported operation: Unsupported type parameter type node E.
-ct_const_test: RuntimeError
-deferred_load_library_wrong_args_test/01: CompileTimeError
-deferred_not_loaded_check_test: RuntimeError # Test out of date. Issue 31933
-deferred_redirecting_factory_test: RuntimeError
-double_int_to_string_test: RuntimeError, OK # non JS number semantics
-dynamic_prefix_core_test/none: CompileTimeError
-enum_mirror_test: RuntimeError
-example_constructor_test: RuntimeError
-expect_test: RuntimeError, OK # Issue 13080
-external_test/10: MissingRuntimeError
-external_test/13: MissingRuntimeError
-external_test/20: MissingRuntimeError
-external_test/21: CompileTimeError
-external_test/24: CompileTimeError
-flatten_test/05: MissingRuntimeError
-flatten_test/08: MissingRuntimeError
-flatten_test/09: MissingRuntimeError
-flatten_test/12: MissingRuntimeError
-full_stacktrace1_test: RuntimeError # Issue 12698
-full_stacktrace2_test: RuntimeError # Issue 12698
-full_stacktrace3_test: RuntimeError # Issue 12698
-function_subtype_inline2_test: RuntimeError
-generic_function_bounds_test: RuntimeError
-generic_function_dcall_test/01: RuntimeError
-generic_instanceof2_test: RuntimeError
-generic_is_check_test: RuntimeError
-generic_methods_bounds_test/02: MissingRuntimeError
-generic_no_such_method_dispatcher_simple_test: CompileTimeError
-generic_no_such_method_dispatcher_test: CompileTimeError
-generic_tearoff_test: CompileTimeError
-identical_closure2_test: RuntimeError # non JS number semantics
-if_null_precedence_test/none: RuntimeError
-infinity_test: RuntimeError # non JS number semantics - Issue 4984
-instance_creation_in_function_annotation_test: RuntimeError
-instantiate_tearoff_of_call_test: CompileTimeError
-integer_division_by_zero_test: RuntimeError # Issue 8301
-internal_library_test/02: Crash
-invocation_mirror_invoke_on2_test: RuntimeError
-invocation_mirror_invoke_on_test: RuntimeError
-issue21079_test: RuntimeError
-issue23244_test: RuntimeError
-issue31596_super_test/01: CompileTimeError
-issue31596_super_test/03: CompileTimeError
-left_shift_test: RuntimeError # non JS number semantics
-library_env_test/has_mirror_support: RuntimeError
-local_function2_test/none: RuntimeError
-local_function3_test/none: RuntimeError
-local_function_test/none: RuntimeError
-minify_closure_variable_collision_test: CompileTimeError
-mint_arithmetic_test: RuntimeError # non JS number semantics
-mixin_illegal_super_use_test/01: MissingCompileTimeError
-mixin_illegal_super_use_test/04: MissingCompileTimeError
-mixin_illegal_super_use_test/07: MissingCompileTimeError
-mixin_illegal_super_use_test/10: MissingCompileTimeError
-mixin_illegal_super_use_test/11: MissingCompileTimeError
-mixin_illegal_superclass_test/01: MissingCompileTimeError
-mixin_illegal_superclass_test/02: MissingCompileTimeError
-mixin_illegal_superclass_test/03: MissingCompileTimeError
-mixin_illegal_superclass_test/04: MissingCompileTimeError
-mixin_illegal_superclass_test/05: MissingCompileTimeError
-mixin_illegal_superclass_test/06: MissingCompileTimeError
-mixin_illegal_superclass_test/07: MissingCompileTimeError
-mixin_illegal_superclass_test/08: MissingCompileTimeError
-mixin_illegal_superclass_test/09: MissingCompileTimeError
-mixin_illegal_superclass_test/10: MissingCompileTimeError
-mixin_illegal_superclass_test/11: MissingCompileTimeError
-mixin_illegal_superclass_test/12: MissingCompileTimeError
-mixin_illegal_superclass_test/13: MissingCompileTimeError
-mixin_illegal_superclass_test/14: MissingCompileTimeError
-mixin_illegal_superclass_test/15: MissingCompileTimeError
-mixin_illegal_superclass_test/16: MissingCompileTimeError
-mixin_illegal_superclass_test/17: MissingCompileTimeError
-mixin_illegal_superclass_test/18: MissingCompileTimeError
-mixin_illegal_superclass_test/19: MissingCompileTimeError
-mixin_illegal_superclass_test/20: MissingCompileTimeError
-mixin_illegal_superclass_test/21: MissingCompileTimeError
-mixin_illegal_superclass_test/22: MissingCompileTimeError
-mixin_illegal_superclass_test/23: MissingCompileTimeError
-mixin_illegal_superclass_test/24: MissingCompileTimeError
-mixin_illegal_superclass_test/25: MissingCompileTimeError
-mixin_illegal_superclass_test/26: MissingCompileTimeError
-mixin_illegal_superclass_test/27: MissingCompileTimeError
-mixin_illegal_superclass_test/28: MissingCompileTimeError
-mixin_illegal_superclass_test/29: MissingCompileTimeError
-mixin_illegal_superclass_test/30: MissingCompileTimeError
-mixin_method_override_test/G5: Skip # Issue 34354
-mock_writable_final_field_test: RuntimeError # Issue 30847
-mock_writable_final_private_field_test: RuntimeError # Issue 17526, 30847
-modulo_test: RuntimeError # non JS number semantics
-named_parameters_default_eq_test/none: RuntimeError
-nan_identical_test: RuntimeError # Issue 11551
-nested_generic_closure_test: RuntimeError
-no_main_test/01: CompileTimeError
-no_such_method_mock_test: RuntimeError
-null_no_such_method_test: CompileTimeError
-number_identity2_test: RuntimeError
-numbers_test: RuntimeError, OK # non JS number semantics
-parser_quirks_test: CompileTimeError
-redirecting_factory_reflection_test: RuntimeError
-regress_23408_test: CompileTimeError
-regress_24283_test: RuntimeError, OK # non JS number semantics
-regress_28255_test: RuntimeError
-regress_29025_test: CompileTimeError
-regress_29405_test: CompileTimeError
-regress_30339_test: CompileTimeError
-setter_no_getter_test/01: CompileTimeError
-stacktrace_demangle_ctors_test: RuntimeError # Issue 12698
-stacktrace_rethrow_error_test/none: RuntimeError # Issue 12698
-stacktrace_rethrow_error_test/withtraceparameter: RuntimeError # Issue 12698
-stacktrace_rethrow_nonerror_test: RuntimeError # Issue 12698
-super_bound_closure_test/none: CompileTimeError
-super_call4_test/01: MissingCompileTimeError
-super_test: RuntimeError
-tearoff_dynamic_test: RuntimeError
-truncdiv_test: RuntimeError # non JS number semantics - Issue 15246
-type_error_test: RuntimeError
-type_literal_test: RuntimeError
-type_promotion_more_specific_test/04: CompileTimeError
-
-[ $compiler == dart2js && !$strong ]
-*: SkipByDesign
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index f5b2b09..1a54ab1 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -156,10 +156,28 @@
 assertion_initializer_const_error2_test/cc10: MissingCompileTimeError
 async_await_syntax_test/e5: Crash # Assertion error: continuation.dart: Failed assertion: 'node.expression == null || node.expression is NullLiteral': is not true.
 async_await_syntax_test/e6: Crash # Assertion error: continuation.dart: Failed assertion: 'node.expression == null || node.expression is NullLiteral': is not true.
+compile_time_constant_static4_test/02: MissingCompileTimeError
+compile_time_constant_static4_test/03: MissingCompileTimeError
+compile_time_constant_static5_test/11: CompileTimeError
+compile_time_constant_static5_test/16: CompileTimeError
+compile_time_constant_static5_test/21: CompileTimeError
+compile_time_constant_static5_test/23: CompileTimeError
+conditional_import_string_test: CompileTimeError
+conditional_import_test: CompileTimeError
+config_import_corelib_test: CompileTimeError
 const_cast1_test/02: MissingCompileTimeError
+const_constructor3_test/04: MissingCompileTimeError
 const_constructor_nonconst_param_test/01: MissingCompileTimeError
+constants_test/05: MissingCompileTimeError
 constructor5_test: CompileTimeError # Verification error
 constructor6_test: CompileTimeError # Verification error
+deferred_load_library_wrong_args_test/01: CompileTimeError
+dynamic_prefix_core_test/none: CompileTimeError
+external_test/21: CompileTimeError
+external_test/24: CompileTimeError
+generic_no_such_method_dispatcher_simple_test: CompileTimeError
+generic_no_such_method_dispatcher_test: CompileTimeError
+generic_tearoff_test: CompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e1: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e10: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e11: MissingCompileTimeError
@@ -180,7 +198,61 @@
 implicit_creation/implicit_const_not_default_values_test/e5: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e7: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e8: MissingCompileTimeError
+instantiate_tearoff_of_call_test: CompileTimeError
+issue31596_super_test/01: CompileTimeError
+issue31596_super_test/03: CompileTimeError
+mixin_illegal_super_use_test/01: MissingCompileTimeError
+mixin_illegal_super_use_test/04: MissingCompileTimeError
+mixin_illegal_super_use_test/07: MissingCompileTimeError
+mixin_illegal_super_use_test/10: MissingCompileTimeError
+mixin_illegal_super_use_test/11: MissingCompileTimeError
+mixin_illegal_superclass_test/01: MissingCompileTimeError
+mixin_illegal_superclass_test/02: MissingCompileTimeError
+mixin_illegal_superclass_test/03: MissingCompileTimeError
+mixin_illegal_superclass_test/04: MissingCompileTimeError
+mixin_illegal_superclass_test/05: MissingCompileTimeError
+mixin_illegal_superclass_test/06: MissingCompileTimeError
+mixin_illegal_superclass_test/07: MissingCompileTimeError
+mixin_illegal_superclass_test/08: MissingCompileTimeError
+mixin_illegal_superclass_test/09: MissingCompileTimeError
+mixin_illegal_superclass_test/10: MissingCompileTimeError
+mixin_illegal_superclass_test/11: MissingCompileTimeError
+mixin_illegal_superclass_test/12: MissingCompileTimeError
+mixin_illegal_superclass_test/13: MissingCompileTimeError
+mixin_illegal_superclass_test/14: MissingCompileTimeError
+mixin_illegal_superclass_test/15: MissingCompileTimeError
+mixin_illegal_superclass_test/16: MissingCompileTimeError
+mixin_illegal_superclass_test/17: MissingCompileTimeError
+mixin_illegal_superclass_test/18: MissingCompileTimeError
+mixin_illegal_superclass_test/19: MissingCompileTimeError
+mixin_illegal_superclass_test/20: MissingCompileTimeError
+mixin_illegal_superclass_test/21: MissingCompileTimeError
+mixin_illegal_superclass_test/22: MissingCompileTimeError
+mixin_illegal_superclass_test/23: MissingCompileTimeError
+mixin_illegal_superclass_test/24: MissingCompileTimeError
+mixin_illegal_superclass_test/25: MissingCompileTimeError
+mixin_illegal_superclass_test/26: MissingCompileTimeError
+mixin_illegal_superclass_test/27: MissingCompileTimeError
+mixin_illegal_superclass_test/28: MissingCompileTimeError
+mixin_illegal_superclass_test/29: MissingCompileTimeError
+mixin_illegal_superclass_test/30: MissingCompileTimeError
 mixin_method_override_test/G4: Crash # Assertion error: mixin_full_resolution.dart': 'src.typeParameters.length == dst.typeParameters.length': is not true.
+multiline_newline_test/04: MissingCompileTimeError
+multiline_newline_test/04r: MissingCompileTimeError
+multiline_newline_test/05: MissingCompileTimeError
+multiline_newline_test/05r: MissingCompileTimeError
+multiline_newline_test/06: MissingCompileTimeError
+multiline_newline_test/06r: MissingCompileTimeError
+null_no_such_method_test: CompileTimeError
+parser_quirks_test: CompileTimeError
+regress_23408_test: CompileTimeError
+regress_29025_test: CompileTimeError
+regress_29405_test: CompileTimeError
+regress_30339_test: CompileTimeError
+setter_no_getter_test/01: CompileTimeError
+super_bound_closure_test/none: CompileTimeError
+try_catch_test/01: MissingCompileTimeError
+type_promotion_more_specific_test/04: CompileTimeError
 vm/regress_33469_test/01: MissingCompileTimeError
 vm/regress_33469_test/02: MissingCompileTimeError
 vm/regress_33469_test/03: MissingCompileTimeError
@@ -387,6 +459,7 @@
 syntax_test/60: MissingCompileTimeError # Issue 30470
 syntax_test/61: MissingCompileTimeError # Issue 30470
 type_constants_test/04: MissingCompileTimeError # Issue 32557
+type_promotion_logical_and_test/01: MissingCompileTimeError
 vm/debug_break_enabled_vm_test/01: CompileTimeError # KernelVM bug: Bad test using extended break syntax.
 vm/debug_break_enabled_vm_test/none: CompileTimeError # KernelVM bug: Bad test using extended break syntax.
 vm/regress_27201_test: CompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
@@ -418,11 +491,14 @@
 [ $compiler != app_jitk && $compiler != dart2analyzer && $compiler != dart2js && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $fasta ]
 const_optional_args_test/01: MissingCompileTimeError
 
-# The precomilation configuration uses a kernel2kernel constants evaluator
+# The precompilation and bytecode configurations use a kernel2kernel constants evaluator
 # which is is more correct than fasta/vm in JIT mode (i.e. it catches more
 # compile-time errors).
 [ $compiler != dart2analyzer && $compiler != dart2js && $compiler != dartkb && $compiler != dartkp && $fasta ]
 compile_time_constant_c_test/02: MissingCompileTimeError
+compile_time_constant_k_test/01: MissingCompileTimeError
+compile_time_constant_k_test/02: MissingCompileTimeError
+compile_time_constant_k_test/03: MissingCompileTimeError
 compile_time_constant_o_test/01: MissingCompileTimeError # Issue 32983
 compile_time_constant_o_test/02: MissingCompileTimeError # Issue 32983
 const_dynamic_type_literal_test/02: MissingCompileTimeError # Issue 32983
@@ -431,37 +507,22 @@
 identical_const_test/02: MissingCompileTimeError # Issue 32983
 identical_const_test/03: MissingCompileTimeError # Issue 32983
 identical_const_test/04: MissingCompileTimeError # Issue 32983
-
-# The precomilation and bytecode configurations use a kernel2kernel constants evaluator
-# which is is more correct than fasta/vm in JIT mode (i.e. it catches more
-# compile-time errors).
-[ $compiler != dart2analyzer && $compiler != dart2js && $compiler != dartkb && $compiler != dartkp && $fasta && $strong ]
-compile_time_constant_k_test/01: MissingCompileTimeError
-compile_time_constant_k_test/02: MissingCompileTimeError
-compile_time_constant_k_test/03: MissingCompileTimeError
 map_literal3_test/01: MissingCompileTimeError
 map_literal3_test/02: MissingCompileTimeError
 
 [ $compiler != dart2analyzer && $compiler != dart2js && $fasta ]
+super_call4_test/01: MissingCompileTimeError
 switch_bad_case_test/01: MissingCompileTimeError # KernelVM bug: Constant evaluation.
 switch_bad_case_test/02: MissingCompileTimeError # KernelVM bug: Constant evaluation.
 switch_case_test/00: MissingCompileTimeError # KernelVM bug: Constant evaluation.
 switch_case_test/01: MissingCompileTimeError # KernelVM bug: Constant evaluation.
 switch_case_test/02: MissingCompileTimeError # KernelVM bug: Constant evaluation.
 
-[ $compiler != dart2analyzer && $compiler != dart2js && $fasta && $strong ]
-super_call4_test/01: MissingCompileTimeError
-
 [ $compiler != dart2analyzer && $fasta ]
 const_map2_test/00: MissingCompileTimeError # KernelVM bug: Constant evaluation.
 const_map3_test/00: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-
-[ $compiler != dart2analyzer && $fasta && $strong ]
 map_literal3_test/03: MissingCompileTimeError
 
-[ $compiler != dart2analyzer && $fasta && !$strong ]
-super_call4_test/01: MissingCompileTimeError
-
 [ $compiler != dart2js && $compiler != dartdevk && $fasta ]
 const_native_factory_test: MissingCompileTimeError # Issue 29763
 
@@ -471,7 +532,7 @@
 [ $compiler == dartk && $mode == debug && ($hot_reload || $hot_reload_rollback) ]
 inference_enum_list_test: Skip # Issue 35885
 
-[ $compiler == dartk && $runtime == vm && !$checked && $strong ]
+[ $compiler == dartk && $runtime == vm && !$checked ]
 assertion_initializer_const_error2_test/cc01: MissingCompileTimeError # Not reporting failed assert() at compile time.
 assertion_initializer_const_error2_test/cc02: MissingCompileTimeError # Not reporting failed assert() at compile time.
 assertion_initializer_const_error2_test/cc03: MissingCompileTimeError # Not reporting failed assert() at compile time.
@@ -483,7 +544,7 @@
 assertion_initializer_const_error2_test/cc09: MissingCompileTimeError # Not reporting failed assert() at compile time.
 assertion_initializer_const_error2_test/cc10: MissingCompileTimeError # Not reporting failed assert() at compile time.
 
-[ $compiler == dartkb && $runtime == vm && $strong ]
+[ $compiler == dartkb && $runtime == vm ]
 async_star_test/03: Pass, RuntimeError # Please triage
 async_star_test/04: Pass, RuntimeError # Please triage
 compile_time_constant_o_test/01: Pass
@@ -499,11 +560,11 @@
 vm/symbols_test/01: MissingCompileTimeError
 vm/symbols_test/03: MissingCompileTimeError
 
-[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
+[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
 external_test/13: Crash
 vm/precompiled_static_initializer_test: Pass, Slow
 
-[ $compiler == dartkp && $mode == product && $runtime == dart_precompiled && $strong ]
+[ $compiler == dartkp && $mode == product && $runtime == dart_precompiled ]
 vm/type_vm_test/28: MissingRuntimeError
 vm/type_vm_test/29: MissingRuntimeError
 vm/type_vm_test/30: MissingRuntimeError
@@ -514,106 +575,8 @@
 vm/type_vm_test/35: MissingRuntimeError
 vm/type_vm_test/36: MissingRuntimeError
 
-[ $compiler == dartkp && $runtime == dart_precompiled ]
-type_alias_equality_test/03: RuntimeError # Issue 32783
-type_alias_equality_test/04: RuntimeError # Issue 32783
-vm/bool_check_stack_traces_test/01: RuntimeError # Issue 33584
-vm/bool_check_stack_traces_test/02: RuntimeError # Issue 33584
-
-[ $compiler == dartkp && $runtime == dart_precompiled && $checked && $strong ]
-assert_initializer_test/31: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/32: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/33: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/34: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/35: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/36: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/37: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/38: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/41: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/42: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/43: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/44: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/45: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/46: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/47: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/48: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-assert_initializer_test/none: RuntimeError # KernelVM bug: Constant evaluation.
-assertion_initializer_const_error2_test/cc01: Crash
-assertion_initializer_const_error2_test/cc02: Crash
-assertion_initializer_const_error2_test/cc03: Crash
-assertion_initializer_const_error2_test/cc04: Crash
-assertion_initializer_const_error2_test/cc05: Crash
-assertion_initializer_const_error2_test/cc06: Crash
-assertion_initializer_const_error2_test/cc07: Crash
-assertion_initializer_const_error2_test/cc08: Crash
-assertion_initializer_const_error2_test/cc09: Crash
-assertion_initializer_const_error2_test/cc10: Crash
-assertion_initializer_const_error2_test/cc11: Crash
-async_await_test: RuntimeError
-async_return_types_test/nestedFuture: Fail
-async_star/async_star_cancel_test: DartkCrash
-async_star/async_star_invalid_test/01: DartkCrash
-async_star/async_star_invalid_test/02: DartkCrash
-async_star/async_star_invalid_test/03: DartkCrash
-async_star/async_star_invalid_test/04: DartkCrash
-async_star/async_star_invalid_test/none: DartkCrash
-async_star/async_star_test: DartkCrash
-compile_time_constant_checked_test/02: MissingCompileTimeError
-covariance_type_parameter_test/01: RuntimeError
-covariance_type_parameter_test/02: RuntimeError
-covariance_type_parameter_test/03: RuntimeError
-covariance_type_parameter_test/none: RuntimeError
-default_factory2_test/01: Fail
-function_subtype_checked0_test: Pass
-function_subtype_closure0_test: Pass
-function_subtype_closure1_test: Pass
-function_subtype_factory1_test: Pass
-function_subtype_inline1_test: Pass
-function_subtype_inline2_test: Pass
-generic_functions_test: Pass # Issue 25869
-generic_local_functions_test: Pass # Issue 25869
-generic_methods_function_type_test: Pass # Issue 25869
-generic_methods_generic_function_parameter_test: Pass # Issue 25869
-generic_methods_new_test: Pass # Issue 25869
-generic_methods_test: Pass # Issue 25869
-known_identifier_usage_error_test/none: RuntimeError # Issue 28814
-malbounded_type_test_test/03: Fail
-malbounded_type_test_test/04: Fail
-recursive_inheritance_test: RuntimeError
-redirecting_factory_infinite_steps_test/01: Fail
-redirecting_factory_malbounded_test/01: Fail
-regress_22728_test: Fail # Dartk Issue 28498
-regress_22728_test: RuntimeError
-
-[ $compiler == dartkp && $runtime == dart_precompiled && !$checked && $strong ]
-assertion_initializer_const_error_test/01: MissingCompileTimeError
-assertion_initializer_const_function_error_test/01: MissingCompileTimeError
-conditional_rewrite_test: RuntimeError # Issue 31402 (Not)
-implicit_downcast_during_combiner_test: RuntimeError
-implicit_downcast_during_compound_assignment_test: RuntimeError
-implicit_downcast_during_conditional_expression_test: RuntimeError
-implicit_downcast_during_do_test: RuntimeError
-implicit_downcast_during_for_condition_test: RuntimeError
-implicit_downcast_during_for_initializer_expression_test: RuntimeError
-implicit_downcast_during_for_initializer_var_test: RuntimeError
-implicit_downcast_during_if_null_assignment_test: RuntimeError
-implicit_downcast_during_if_statement_test: RuntimeError
-implicit_downcast_during_list_literal_test: RuntimeError
-implicit_downcast_during_logical_expression_test: RuntimeError
-implicit_downcast_during_map_literal_test: RuntimeError
-implicit_downcast_during_not_test: RuntimeError
-implicit_downcast_during_return_async_test: RuntimeError
-implicit_downcast_during_return_test: RuntimeError
-implicit_downcast_during_variable_declaration_test: RuntimeError
-implicit_downcast_during_while_statement_test: RuntimeError
-implicit_downcast_during_yield_star_test: RuntimeError
-implicit_downcast_during_yield_test: RuntimeError
-regress_30339_test: RuntimeError
-type_error_test: RuntimeError # Issue 31402 (Variable declaration)
-vm/causal_async_exception_stack_test: RuntimeError
-
 # ==== dartkp + dart_precompiled status lines ====
-[ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
+[ $compiler == dartkp && $runtime == dart_precompiled ]
 assert_with_type_test_or_cast_test: Pass, Crash
 assertion_initializer_const_error_test/01: Pass
 async_star_cancel_while_paused_test: RuntimeError
@@ -758,8 +721,12 @@
 super_bound_closure_test/none: CompileTimeError # Issue 31533
 super_test: Fail, OK
 syntax_test/00: MissingCompileTimeError
+type_alias_equality_test/03: RuntimeError # Issue 32783
+type_alias_equality_test/04: RuntimeError # Issue 32783
 type_promotion_logical_and_test/01: MissingCompileTimeError
 type_promotion_more_specific_test/04: CompileTimeError # Issue 31533
+vm/bool_check_stack_traces_test/01: RuntimeError # Issue 33584
+vm/bool_check_stack_traces_test/02: RuntimeError # Issue 33584
 vm/causal_async_exception_stack2_test: SkipByDesign
 vm/causal_async_exception_stack_test: SkipByDesign
 vm/closure_memory_retention_test: Skip # KernelVM bug: Hits OOM
@@ -792,323 +759,102 @@
 vm/type_vm_test/31: MissingRuntimeError
 vm/type_vm_test/32: MissingRuntimeError
 
+[ $compiler == dartkp && $runtime == dart_precompiled && $checked ]
+assert_initializer_test/31: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/32: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/33: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/34: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/35: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/36: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/37: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/38: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/41: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/42: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/43: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/44: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/45: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/46: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/47: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/48: MissingCompileTimeError # KernelVM bug: Constant evaluation.
+assert_initializer_test/none: RuntimeError # KernelVM bug: Constant evaluation.
+assertion_initializer_const_error2_test/cc01: Crash
+assertion_initializer_const_error2_test/cc02: Crash
+assertion_initializer_const_error2_test/cc03: Crash
+assertion_initializer_const_error2_test/cc04: Crash
+assertion_initializer_const_error2_test/cc05: Crash
+assertion_initializer_const_error2_test/cc06: Crash
+assertion_initializer_const_error2_test/cc07: Crash
+assertion_initializer_const_error2_test/cc08: Crash
+assertion_initializer_const_error2_test/cc09: Crash
+assertion_initializer_const_error2_test/cc10: Crash
+assertion_initializer_const_error2_test/cc11: Crash
+async_await_test: RuntimeError
+async_return_types_test/nestedFuture: Fail
+async_star/async_star_cancel_test: DartkCrash
+async_star/async_star_invalid_test/01: DartkCrash
+async_star/async_star_invalid_test/02: DartkCrash
+async_star/async_star_invalid_test/03: DartkCrash
+async_star/async_star_invalid_test/04: DartkCrash
+async_star/async_star_invalid_test/none: DartkCrash
+async_star/async_star_test: DartkCrash
+compile_time_constant_checked_test/02: MissingCompileTimeError
+covariance_type_parameter_test/01: RuntimeError
+covariance_type_parameter_test/02: RuntimeError
+covariance_type_parameter_test/03: RuntimeError
+covariance_type_parameter_test/none: RuntimeError
+default_factory2_test/01: Fail
+function_subtype_checked0_test: Pass
+function_subtype_closure0_test: Pass
+function_subtype_closure1_test: Pass
+function_subtype_factory1_test: Pass
+function_subtype_inline1_test: Pass
+function_subtype_inline2_test: Pass
+generic_functions_test: Pass # Issue 25869
+generic_local_functions_test: Pass # Issue 25869
+generic_methods_function_type_test: Pass # Issue 25869
+generic_methods_generic_function_parameter_test: Pass # Issue 25869
+generic_methods_new_test: Pass # Issue 25869
+generic_methods_test: Pass # Issue 25869
+known_identifier_usage_error_test/none: RuntimeError # Issue 28814
+malbounded_type_test_test/03: Fail
+malbounded_type_test_test/04: Fail
+recursive_inheritance_test: RuntimeError
+redirecting_factory_infinite_steps_test/01: Fail
+redirecting_factory_malbounded_test/01: Fail
+regress_22728_test: Fail # Dartk Issue 28498
+regress_22728_test: RuntimeError
+
+[ $compiler == dartkp && $runtime == dart_precompiled && !$checked ]
+assertion_initializer_const_error_test/01: MissingCompileTimeError
+assertion_initializer_const_function_error_test/01: MissingCompileTimeError
+conditional_rewrite_test: RuntimeError # Issue 31402 (Not)
+implicit_downcast_during_combiner_test: RuntimeError
+implicit_downcast_during_compound_assignment_test: RuntimeError
+implicit_downcast_during_conditional_expression_test: RuntimeError
+implicit_downcast_during_do_test: RuntimeError
+implicit_downcast_during_for_condition_test: RuntimeError
+implicit_downcast_during_for_initializer_expression_test: RuntimeError
+implicit_downcast_during_for_initializer_var_test: RuntimeError
+implicit_downcast_during_if_null_assignment_test: RuntimeError
+implicit_downcast_during_if_statement_test: RuntimeError
+implicit_downcast_during_list_literal_test: RuntimeError
+implicit_downcast_during_logical_expression_test: RuntimeError
+implicit_downcast_during_map_literal_test: RuntimeError
+implicit_downcast_during_not_test: RuntimeError
+implicit_downcast_during_return_async_test: RuntimeError
+implicit_downcast_during_return_test: RuntimeError
+implicit_downcast_during_variable_declaration_test: RuntimeError
+implicit_downcast_during_while_statement_test: RuntimeError
+implicit_downcast_during_yield_star_test: RuntimeError
+implicit_downcast_during_yield_test: RuntimeError
+regress_30339_test: RuntimeError
+type_error_test: RuntimeError # Issue 31402 (Variable declaration)
+vm/causal_async_exception_stack_test: RuntimeError
+
 [ $compiler == dartkp && $system == windows ]
 disassemble_test: Pass, Slow
 
-[ $compiler == fasta && $strong ]
-compile_time_constant_static4_test/02: MissingCompileTimeError
-compile_time_constant_static4_test/03: MissingCompileTimeError
-compile_time_constant_static5_test/11: CompileTimeError
-compile_time_constant_static5_test/16: CompileTimeError
-compile_time_constant_static5_test/21: CompileTimeError
-compile_time_constant_static5_test/23: CompileTimeError
-conditional_import_string_test: CompileTimeError
-conditional_import_test: CompileTimeError
-config_import_corelib_test: CompileTimeError
-const_constructor3_test/04: MissingCompileTimeError
-constants_test/05: MissingCompileTimeError
-deferred_load_library_wrong_args_test/01: CompileTimeError
-dynamic_prefix_core_test/none: CompileTimeError
-external_test/21: CompileTimeError
-external_test/24: CompileTimeError
-generic_no_such_method_dispatcher_simple_test: CompileTimeError
-generic_no_such_method_dispatcher_test: CompileTimeError
-generic_tearoff_test: CompileTimeError
-instantiate_tearoff_of_call_test: CompileTimeError
-issue31596_super_test/01: CompileTimeError
-issue31596_super_test/03: CompileTimeError
-mixin_illegal_super_use_test/01: MissingCompileTimeError
-mixin_illegal_super_use_test/04: MissingCompileTimeError
-mixin_illegal_super_use_test/07: MissingCompileTimeError
-mixin_illegal_super_use_test/10: MissingCompileTimeError
-mixin_illegal_super_use_test/11: MissingCompileTimeError
-mixin_illegal_superclass_test/01: MissingCompileTimeError
-mixin_illegal_superclass_test/02: MissingCompileTimeError
-mixin_illegal_superclass_test/03: MissingCompileTimeError
-mixin_illegal_superclass_test/04: MissingCompileTimeError
-mixin_illegal_superclass_test/05: MissingCompileTimeError
-mixin_illegal_superclass_test/06: MissingCompileTimeError
-mixin_illegal_superclass_test/07: MissingCompileTimeError
-mixin_illegal_superclass_test/08: MissingCompileTimeError
-mixin_illegal_superclass_test/09: MissingCompileTimeError
-mixin_illegal_superclass_test/10: MissingCompileTimeError
-mixin_illegal_superclass_test/11: MissingCompileTimeError
-mixin_illegal_superclass_test/12: MissingCompileTimeError
-mixin_illegal_superclass_test/13: MissingCompileTimeError
-mixin_illegal_superclass_test/14: MissingCompileTimeError
-mixin_illegal_superclass_test/15: MissingCompileTimeError
-mixin_illegal_superclass_test/16: MissingCompileTimeError
-mixin_illegal_superclass_test/17: MissingCompileTimeError
-mixin_illegal_superclass_test/18: MissingCompileTimeError
-mixin_illegal_superclass_test/19: MissingCompileTimeError
-mixin_illegal_superclass_test/20: MissingCompileTimeError
-mixin_illegal_superclass_test/21: MissingCompileTimeError
-mixin_illegal_superclass_test/22: MissingCompileTimeError
-mixin_illegal_superclass_test/23: MissingCompileTimeError
-mixin_illegal_superclass_test/24: MissingCompileTimeError
-mixin_illegal_superclass_test/25: MissingCompileTimeError
-mixin_illegal_superclass_test/26: MissingCompileTimeError
-mixin_illegal_superclass_test/27: MissingCompileTimeError
-mixin_illegal_superclass_test/28: MissingCompileTimeError
-mixin_illegal_superclass_test/29: MissingCompileTimeError
-mixin_illegal_superclass_test/30: MissingCompileTimeError
-multiline_newline_test/04: MissingCompileTimeError
-multiline_newline_test/04r: MissingCompileTimeError
-multiline_newline_test/05: MissingCompileTimeError
-multiline_newline_test/05r: MissingCompileTimeError
-multiline_newline_test/06: MissingCompileTimeError
-multiline_newline_test/06r: MissingCompileTimeError
-null_no_such_method_test: CompileTimeError
-parser_quirks_test: CompileTimeError
-regress_23408_test: CompileTimeError
-regress_29025_test: CompileTimeError
-regress_29405_test: CompileTimeError
-regress_30339_test: CompileTimeError
-setter_no_getter_test/01: CompileTimeError
-super_bound_closure_test/none: CompileTimeError
-try_catch_test/01: MissingCompileTimeError
-type_promotion_more_specific_test/04: CompileTimeError
-
-[ $compiler == fasta && !$strong ]
-abstract_factory_constructor_test/00: MissingCompileTimeError
-abstract_getter_test/01: MissingCompileTimeError
-abstract_syntax_test/00: MissingCompileTimeError
-bad_override_test/04: MissingCompileTimeError
-bad_override_test/05: MissingCompileTimeError
-bug32305_test: MissingCompileTimeError
-call_method_implicit_invoke_local_test/05: MissingCompileTimeError
-closure_invoked_through_interface_target_field_test: MissingCompileTimeError
-closure_invoked_through_interface_target_getter_test: MissingCompileTimeError
-factory2_test/03: MissingCompileTimeError
-field_override4_test/02: MissingCompileTimeError
-field_override_test/00: MissingCompileTimeError # Override checks are performed differently in strong mode.
-field_override_test/01: MissingCompileTimeError # Override checks are performed differently in strong mode.
-generic_methods_overriding_test/01: MissingCompileTimeError # Override checks are performed differently in strong mode.
-getter_override2_test/02: MissingCompileTimeError
-implicit_this_test/01: MissingCompileTimeError
-implicit_this_test/04: MissingCompileTimeError
-invalid_override_in_mixin_test/01: MissingCompileTimeError
-issue31596_override_test/07: MissingCompileTimeError # Override checks are performed differently in strong mode.
-issue31596_override_test/08: MissingCompileTimeError # Override checks are performed differently in strong mode.
-map_literal1_test/01: MissingCompileTimeError
-method_override8_test/00: MissingCompileTimeError
-method_override8_test/01: MissingCompileTimeError
-method_override8_test/03: MissingCompileTimeError
-mixin_of_mixin_test/01: MissingCompileTimeError
-mixin_of_mixin_test/02: MissingCompileTimeError
-mixin_of_mixin_test/03: MissingCompileTimeError
-mixin_of_mixin_test/04: MissingCompileTimeError
-mixin_of_mixin_test/05: MissingCompileTimeError
-mixin_of_mixin_test/06: MissingCompileTimeError
-nsm5_test: MissingCompileTimeError
-override_field_method1_negative_test: Fail
-override_field_method2_negative_test: Fail
-override_field_method4_negative_test: Fail
-override_field_method5_negative_test: Fail
-override_inheritance_field_test/43: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_field_test/44: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_field_test/45: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_field_test/47: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_field_test/48: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_field_test/49: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_field_test/50: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_field_test/53: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_field_test/54: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/012: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/016: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/020: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/024: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/026: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/027: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/030: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/031: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/044: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/048: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/052: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/056: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/058: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/059: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/062: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/063: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/068: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/072: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/076: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/080: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/084: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/088: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/089: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/093: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/097: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/101: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/105: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/109: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/113: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/114: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/118: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/122: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/126: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/130: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/134: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/138: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/139: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/143: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/147: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/151: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/155: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/159: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/163: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/164: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/166: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/167: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/170: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/171: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/173: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/174: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/176: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/177: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/180: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/181: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/184: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/185: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/188: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/189: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/191: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/192: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/194: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/195: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/198: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/199: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/212: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/216: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/220: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/224: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/226: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/227: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/230: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/231: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/238: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/239: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/240: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/241: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/242: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/243: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/247: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/251: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/255: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/259: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/263: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/267: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/268: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/272: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/274: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/275: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/276: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/280: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/283: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/284: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/285: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/286: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/290: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/294: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/298: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/302: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/306: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/310: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/311: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/315: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/317: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/318: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/319: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/323: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/326: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/327: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/331: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/335: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/336: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/338: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/339: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/342: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/343: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/345: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/346: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/348: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/349: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/352: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/353: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/356: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/357: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/360: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/361: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/362: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/363: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/364: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/366: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/367: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/370: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_method2_test/371: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_mixed_test/01: MissingCompileTimeError
-override_inheritance_mixed_test/02: MissingCompileTimeError
-override_inheritance_mixed_test/03: MissingCompileTimeError
-override_inheritance_mixed_test/04: MissingCompileTimeError
-override_inheritance_mixed_test/06: MissingCompileTimeError
-override_inheritance_mixed_test/07: MissingCompileTimeError
-override_inheritance_mixed_test/08: MissingCompileTimeError
-override_inheritance_mixed_test/09: MissingCompileTimeError
-override_inheritance_no_such_method_test/01: MissingCompileTimeError
-override_inheritance_no_such_method_test/05: MissingCompileTimeError
-override_inheritance_no_such_method_test/06: MissingCompileTimeError
-override_inheritance_no_such_method_test/07: MissingCompileTimeError
-override_inheritance_no_such_method_test/09: MissingCompileTimeError
-override_inheritance_no_such_method_test/10: MissingCompileTimeError
-override_inheritance_no_such_method_test/12: MissingCompileTimeError
-override_inheritance_setter_test/001: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_setter_test/002: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_setter_test/004: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_inheritance_setter_test/006: MissingCompileTimeError # Override checks are performed differently in strong mode.
-override_method_with_field_test/01: MissingCompileTimeError
-prefix_import_collision_test/01: MissingCompileTimeError
-prefix_shadow_test/01: MissingCompileTimeError
-prefix_shadow_test/02: MissingCompileTimeError
-prefix_transitive_import_prefix_test/01: MissingCompileTimeError
-prefix_transitive_import_prefix_test/02: MissingCompileTimeError
-prefix_transitive_import_prefix_test/03: MissingCompileTimeError
-prefix_transitive_import_test/01: MissingCompileTimeError
-prefix_transitive_import_test/02: MissingCompileTimeError
-regress_23089_test: MissingCompileTimeError
-regress_33235_05_test/02: MissingCompileTimeError
-regress_33235_05_test/03: MissingCompileTimeError
-regress_33235_06_test/02: MissingCompileTimeError
-regress_33235_06_test/03: MissingCompileTimeError
-regress_33235_07_test/01: MissingCompileTimeError
-regress_33235_07_test/02: MissingCompileTimeError
-regress_33235_07_test/03: MissingCompileTimeError
-regress_33235_08_test/02: MissingCompileTimeError
-regress_33235_08_test/03: MissingCompileTimeError
-regress_33235_09_test/02: MissingCompileTimeError
-regress_33235_09_test/03: MissingCompileTimeError
-regress_33235_10_test/01: MissingCompileTimeError
-regress_33235_10_test/02: MissingCompileTimeError
-regress_33235_10_test/03: MissingCompileTimeError
-regress_33235_12_test/01: MissingCompileTimeError
-regress_33235_12_test/02: MissingCompileTimeError
-regress_33235_12_test/03: MissingCompileTimeError
-regress_33235_13_test/01: MissingCompileTimeError
-regress_33235_13_test/02: MissingCompileTimeError
-regress_33235_13_test/03: MissingCompileTimeError
-regress_33235_14_test/02: MissingCompileTimeError
-regress_33235_14_test/03: MissingCompileTimeError
-regress_33235_15_test/02: MissingCompileTimeError
-regress_33235_15_test/03: MissingCompileTimeError
-regress_33235_16_test/01: MissingCompileTimeError
-regress_33235_16_test/02: MissingCompileTimeError
-regress_33235_16_test/03: MissingCompileTimeError
-setter4_test: MissingCompileTimeError
-setter_override2_test/02: MissingCompileTimeError
-super_no_such_method4_test/01: MissingCompileTimeError # Requires Dart 2 semantics. See http://dartbug.com/33380.
-super_no_such_method5_test/01: MissingCompileTimeError # Requires Dart 2 semantics. See http://dartbug.com/33380.
-variable_shadow_class_test/01: MissingCompileTimeError
-
-[ $mode == debug && $runtime == vm && $strong && ($compiler == app_jitk || $compiler == dartk || $compiler == dartkb) ]
+[ $mode == debug && $runtime == vm && ($compiler == app_jitk || $compiler == dartk || $compiler == dartkb) ]
 deopt_inlined_function_lazy_test: Skip
 
 [ $mode == debug && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
@@ -1127,7 +873,7 @@
 vm/causal_async_exception_stack_test: SkipByDesign
 vm/type_vm_test/29: MissingRuntimeError
 
-[ $runtime == vm && $checked && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $runtime == vm && $checked && ($compiler == dartk || $compiler == dartkb) ]
 assert_initializer_test/31: MissingCompileTimeError # KernelVM bug: Constant evaluation.
 assert_initializer_test/32: MissingCompileTimeError # KernelVM bug: Constant evaluation.
 assert_initializer_test/33: MissingCompileTimeError # KernelVM bug: Constant evaluation.
@@ -1151,12 +897,12 @@
 malbounded_type_test_test/04: Fail
 regress_30339_test: RuntimeError
 
-[ $runtime == vm && !$checked && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $runtime == vm && !$checked && ($compiler == dartk || $compiler == dartkb) ]
 conditional_rewrite_test: RuntimeError # Issue 31402 (Not)
 type_error_test: RuntimeError # Issue 31402 (Variable declaration)
 
 # ===== dartk + vm status lines =====
-[ $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
 arithmetic2_test: RuntimeError # Throws CastError instead of TypeError
 async_star_cancel_while_paused_test: RuntimeError
 async_star_pause_test: Fail, OK
@@ -1265,7 +1011,7 @@
 vm/type_cast_vm_test: RuntimeError
 web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
 
-[ $system == windows && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $system == windows && ($compiler == dartk || $compiler == dartkb) ]
 ct_const2_test: Fail
 
 [ $checked && ($compiler == dartk || $compiler == dartkb) ]
@@ -1280,807 +1026,15 @@
 assertion_initializer_const_error2_test/cc09: Pass # Works in --checked mode but not in --strong mode.
 assertion_initializer_const_error2_test/cc10: Pass # Works in --checked mode but not in --strong mode.
 
-[ $fasta && $strong ]
-type_promotion_logical_and_test/01: MissingCompileTimeError
-
-[ $fasta && !$strong ]
-abstract_beats_arguments_test: MissingCompileTimeError
-abstract_exact_selector_test/01: MissingCompileTimeError
-abstract_override_adds_optional_args_supercall_test: MissingCompileTimeError
-additional_interface_adds_optional_args_supercall_test: MissingCompileTimeError
-argument_assignability_function_typed_test/01: MissingCompileTimeError
-argument_assignability_function_typed_test/02: MissingCompileTimeError
-assertion_initializer_const_function_test/01: MissingCompileTimeError
-assign_static_type_test/01: MissingCompileTimeError
-assign_static_type_test/02: MissingCompileTimeError
-assign_static_type_test/03: MissingCompileTimeError
-assign_static_type_test/04: MissingCompileTimeError
-assign_static_type_test/05: MissingCompileTimeError
-assign_static_type_test/06: MissingCompileTimeError
-assign_to_type_test/01: MissingCompileTimeError
-assign_to_type_test/02: MissingCompileTimeError
-assign_to_type_test/03: MissingCompileTimeError
-assign_to_type_test/04: MissingCompileTimeError
-assign_top_method_test: MissingCompileTimeError
-async_await_syntax_test/a10a: MissingCompileTimeError
-async_await_syntax_test/b10a: MissingCompileTimeError
-async_await_syntax_test/c10a: MissingCompileTimeError
-async_await_syntax_test/d08b: MissingCompileTimeError
-async_await_syntax_test/d10a: MissingCompileTimeError
-async_congruence_local_test/01: MissingCompileTimeError
-async_congruence_local_test/02: MissingCompileTimeError
-async_congruence_method_test/01: MissingCompileTimeError
-async_congruence_unnamed_test/01: MissingCompileTimeError
-async_congruence_unnamed_test/02: MissingCompileTimeError
-async_or_generator_return_type_stacktrace_test/01: MissingCompileTimeError
-async_return_types_test/tooManyTypeParameters: MissingCompileTimeError
-async_return_types_test/wrongReturnType: MissingCompileTimeError
-async_return_types_test/wrongTypeParameter: MissingCompileTimeError
-bad_named_parameters2_test/01: MissingCompileTimeError
-bad_named_parameters_test/01: MissingCompileTimeError
-bad_named_parameters_test/02: MissingCompileTimeError
-bad_named_parameters_test/03: MissingCompileTimeError
-bad_named_parameters_test/04: MissingCompileTimeError
-bad_named_parameters_test/05: MissingCompileTimeError
-bad_override_test/01: MissingCompileTimeError
-bad_override_test/02: MissingCompileTimeError
-bad_override_test/03: MissingCompileTimeError
-bad_override_test/06: MissingCompileTimeError
-built_in_identifier_type_annotation_test/dynamic-gen: MissingCompileTimeError
-call_constructor_on_unresolvable_class_test/01: MissingCompileTimeError
-call_constructor_on_unresolvable_class_test/02: MissingCompileTimeError
-call_constructor_on_unresolvable_class_test/03: MissingCompileTimeError
-call_method_must_not_be_field_test/01: MissingCompileTimeError
-call_method_must_not_be_field_test/02: MissingCompileTimeError
-call_method_must_not_be_getter_test/01: MissingCompileTimeError
-call_method_must_not_be_getter_test/02: MissingCompileTimeError
-call_method_override_test/01: MissingCompileTimeError
-call_method_override_test/02: MissingCompileTimeError
-call_nonexistent_constructor_test/01: MissingCompileTimeError
-call_nonexistent_constructor_test/02: MissingCompileTimeError
-call_nonexistent_static_test/01: MissingCompileTimeError
-call_nonexistent_static_test/02: MissingCompileTimeError
-call_nonexistent_static_test/03: MissingCompileTimeError
-call_nonexistent_static_test/04: MissingCompileTimeError
-call_nonexistent_static_test/05: MissingCompileTimeError
-call_nonexistent_static_test/06: MissingCompileTimeError
-call_nonexistent_static_test/07: MissingCompileTimeError
-call_nonexistent_static_test/08: MissingCompileTimeError
-call_nonexistent_static_test/09: MissingCompileTimeError
-call_nonexistent_static_test/10: MissingCompileTimeError
-call_through_getter_test/01: MissingCompileTimeError
-call_through_getter_test/02: MissingCompileTimeError
-callable_test/00: MissingCompileTimeError
-callable_test/01: MissingCompileTimeError
-cast_test/04: MissingCompileTimeError
-cast_test/05: MissingCompileTimeError
-check_member_static_test/02: MissingCompileTimeError
-check_method_override_test/01: MissingCompileTimeError
-check_method_override_test/02: MissingCompileTimeError
-checked_null_test/01: MissingCompileTimeError
-class_cycle_test/02: MissingCompileTimeError
-class_cycle_test/03: MissingCompileTimeError
-class_literal_test/02: MissingCompileTimeError
-class_literal_test/04: MissingCompileTimeError
-class_literal_test/05: MissingCompileTimeError
-class_literal_test/06: MissingCompileTimeError
-class_literal_test/08: MissingCompileTimeError
-class_literal_test/09: MissingCompileTimeError
-class_literal_test/10: MissingCompileTimeError
-class_literal_test/11: MissingCompileTimeError
-class_literal_test/12: MissingCompileTimeError
-class_literal_test/13: MissingCompileTimeError
-class_literal_test/14: MissingCompileTimeError
-class_literal_test/15: MissingCompileTimeError
-class_literal_test/16: MissingCompileTimeError
-class_literal_test/17: MissingCompileTimeError
-class_literal_test/18: MissingCompileTimeError
-class_literal_test/19: MissingCompileTimeError
-class_literal_test/20: MissingCompileTimeError
-class_literal_test/21: MissingCompileTimeError
-class_literal_test/22: MissingCompileTimeError
-class_literal_test/23: MissingCompileTimeError
-class_literal_test/24: MissingCompileTimeError
-class_literal_test/25: MissingCompileTimeError
-conditional_method_invocation_test/05: MissingCompileTimeError
-conditional_method_invocation_test/06: MissingCompileTimeError
-conditional_method_invocation_test/07: MissingCompileTimeError
-conditional_method_invocation_test/08: MissingCompileTimeError
-conditional_method_invocation_test/12: MissingCompileTimeError
-conditional_method_invocation_test/13: MissingCompileTimeError
-conditional_method_invocation_test/18: MissingCompileTimeError
-conditional_method_invocation_test/19: MissingCompileTimeError
-conditional_property_access_test/04: MissingCompileTimeError
-conditional_property_access_test/05: MissingCompileTimeError
-conditional_property_access_test/06: MissingCompileTimeError
-conditional_property_access_test/10: MissingCompileTimeError
-conditional_property_access_test/11: MissingCompileTimeError
-conditional_property_access_test/16: MissingCompileTimeError
-conditional_property_access_test/17: MissingCompileTimeError
-conditional_property_assignment_test/04: MissingCompileTimeError
-conditional_property_assignment_test/05: MissingCompileTimeError
-conditional_property_assignment_test/06: MissingCompileTimeError
-conditional_property_assignment_test/10: MissingCompileTimeError
-conditional_property_assignment_test/11: MissingCompileTimeError
-conditional_property_assignment_test/12: MissingCompileTimeError
-conditional_property_assignment_test/13: MissingCompileTimeError
-conditional_property_assignment_test/27: MissingCompileTimeError
-conditional_property_assignment_test/28: MissingCompileTimeError
-conditional_property_assignment_test/32: MissingCompileTimeError
-conditional_property_assignment_test/33: MissingCompileTimeError
-conditional_property_assignment_test/34: MissingCompileTimeError
-conditional_property_assignment_test/35: MissingCompileTimeError
-conditional_property_increment_decrement_test/04: MissingCompileTimeError
-conditional_property_increment_decrement_test/08: MissingCompileTimeError
-conditional_property_increment_decrement_test/12: MissingCompileTimeError
-conditional_property_increment_decrement_test/16: MissingCompileTimeError
-conditional_property_increment_decrement_test/21: MissingCompileTimeError
-conditional_property_increment_decrement_test/22: MissingCompileTimeError
-conditional_property_increment_decrement_test/27: MissingCompileTimeError
-conditional_property_increment_decrement_test/28: MissingCompileTimeError
-conditional_property_increment_decrement_test/33: MissingCompileTimeError
-conditional_property_increment_decrement_test/34: MissingCompileTimeError
-conditional_property_increment_decrement_test/39: MissingCompileTimeError
-conditional_property_increment_decrement_test/40: MissingCompileTimeError
-const_conditional_test/08: MissingCompileTimeError
-const_constructor2_test/05: MissingCompileTimeError
-const_constructor2_test/06: MissingCompileTimeError
-const_constructor2_test/13: MissingCompileTimeError
-const_constructor2_test/14: MissingCompileTimeError
-const_constructor2_test/15: MissingCompileTimeError
-const_constructor2_test/16: MissingCompileTimeError
-const_constructor2_test/17: MissingCompileTimeError
-const_constructor2_test/18: MissingCompileTimeError
-const_constructor2_test/20: MissingCompileTimeError
-const_constructor2_test/22: MissingCompileTimeError
-const_constructor2_test/24: MissingCompileTimeError
-const_constructor3_test/02: MissingCompileTimeError
-const_constructor3_test/04: MissingCompileTimeError
-const_init2_test/02: MissingCompileTimeError
-const_syntax_test/08: MissingCompileTimeError
-const_syntax_test/10: MissingCompileTimeError
-const_types_test/01: MissingCompileTimeError
-const_types_test/02: MissingCompileTimeError
-const_types_test/03: MissingCompileTimeError
-const_types_test/04: MissingCompileTimeError
-const_types_test/05: MissingCompileTimeError
-const_types_test/06: MissingCompileTimeError
-const_types_test/13: MissingCompileTimeError
-const_types_test/35: MissingCompileTimeError
-const_types_test/40: MissingCompileTimeError
-constants_test/05: MissingCompileTimeError
-constructor13_test/01: MissingCompileTimeError
-constructor13_test/02: MissingCompileTimeError
-constructor_call_wrong_argument_count_test/01: MissingCompileTimeError
-constructor_duplicate_final_test/01: MissingCompileTimeError
-constructor_duplicate_final_test/02: MissingCompileTimeError
-constructor_named_arguments_test/01: MissingCompileTimeError
-create_unresolved_type_test/01: MissingCompileTimeError
-cyclic_typedef_test/13: MissingCompileTimeError
-deferred_constraints_type_annotation_test/as_operation: MissingCompileTimeError
-deferred_constraints_type_annotation_test/catch_check: MissingCompileTimeError
-deferred_constraints_type_annotation_test/is_check: MissingCompileTimeError
-deferred_constraints_type_annotation_test/new_before_load: MissingCompileTimeError
-deferred_constraints_type_annotation_test/new_generic2: MissingCompileTimeError
-deferred_constraints_type_annotation_test/new_generic3: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation1: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_generic1: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_generic2: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_generic3: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_generic4: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_null: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_top_level: MissingCompileTimeError
-duplicate_implements_test/03: MissingCompileTimeError
-duplicate_implements_test/04: MissingCompileTimeError
-dynamic_field_test/01: MissingCompileTimeError
-dynamic_field_test/02: MissingCompileTimeError
-dynamic_prefix_core_test/01: MissingCompileTimeError
-empty_block_case_test: MissingCompileTimeError
-enum_private_test/02: MissingCompileTimeError
-error_stacktrace_test/00: MissingCompileTimeError
-external_test/21: CompileTimeError
-external_test/24: CompileTimeError
-factory1_test/00: MissingCompileTimeError
-factory1_test/01: MissingCompileTimeError
-factory2_test/none: MissingCompileTimeError
-factory3_test/none: MissingCompileTimeError
-factory5_test/00: MissingCompileTimeError
-factory6_test/00: MissingCompileTimeError
-factory_redirection_test/01: MissingCompileTimeError
-factory_redirection_test/02: MissingCompileTimeError
-factory_redirection_test/03: MissingCompileTimeError
-factory_redirection_test/05: MissingCompileTimeError
-factory_redirection_test/06: MissingCompileTimeError
-factory_redirection_test/07: MissingCompileTimeError
-factory_redirection_test/08: MissingCompileTimeError
-factory_redirection_test/09: MissingCompileTimeError
-factory_redirection_test/10: MissingCompileTimeError
-factory_redirection_test/11: MissingCompileTimeError
-factory_redirection_test/12: MissingCompileTimeError
-factory_redirection_test/13: MissingCompileTimeError
-factory_redirection_test/14: MissingCompileTimeError
-factory_redirection_test/none: MissingCompileTimeError
-factory_return_type_checked_test/00: MissingCompileTimeError
-fauxverride_test/03: MissingCompileTimeError
-fauxverride_test/05: MissingCompileTimeError
-field_method4_test: MissingCompileTimeError
-field_override2_test: MissingCompileTimeError
-field_override3_test/00: MissingCompileTimeError
-field_override3_test/01: MissingCompileTimeError
-field_override3_test/02: MissingCompileTimeError
-field_override3_test/03: MissingCompileTimeError
-field_override_test/02: MissingCompileTimeError
-field_override_test/none: MissingCompileTimeError
-field_type_check_test/01: MissingCompileTimeError
-final_attempt_reinitialization_test/01: MissingCompileTimeError
-final_attempt_reinitialization_test/02: MissingCompileTimeError
-final_for_in_variable_test: MissingCompileTimeError
-final_param_test: MissingCompileTimeError
-final_super_field_set_test: MissingCompileTimeError
-final_syntax_test/10: MissingCompileTimeError
-final_variable_assignment_test/01: MissingCompileTimeError
-final_variable_assignment_test/02: MissingCompileTimeError
-final_variable_assignment_test/03: MissingCompileTimeError
-final_variable_assignment_test/04: MissingCompileTimeError
-first_class_types_literals_test/03: MissingCompileTimeError
-first_class_types_literals_test/04: MissingCompileTimeError
-first_class_types_literals_test/05: MissingCompileTimeError
-first_class_types_literals_test/06: MissingCompileTimeError
-first_class_types_literals_test/07: MissingCompileTimeError
-first_class_types_literals_test/08: MissingCompileTimeError
-first_class_types_literals_test/09: MissingCompileTimeError
-first_class_types_literals_test/10: MissingCompileTimeError
-first_class_types_literals_test/11: MissingCompileTimeError
-first_class_types_literals_test/12: MissingCompileTimeError
-for_in3_test: MissingCompileTimeError
-function_malformed_result_type_test/00: MissingCompileTimeError
-function_type_call_getter2_test/00: MissingCompileTimeError
-function_type_call_getter2_test/01: MissingCompileTimeError
-function_type_call_getter2_test/02: MissingCompileTimeError
-function_type_call_getter2_test/03: MissingCompileTimeError
-function_type_call_getter2_test/04: MissingCompileTimeError
-function_type_call_getter2_test/05: MissingCompileTimeError
-fuzzy_arrows_test/01: MissingCompileTimeError
-generic_constructor_mixin2_test/01: MissingCompileTimeError
-generic_constructor_mixin3_test/01: MissingCompileTimeError
-generic_constructor_mixin_test/01: MissingCompileTimeError
-generic_field_mixin6_test/01: MissingCompileTimeError
-generic_function_typedef2_test/04: MissingCompileTimeError
-generic_methods_dynamic_test/01: MissingCompileTimeError
-generic_methods_dynamic_test/03: MissingCompileTimeError
-generic_methods_generic_function_result_test/01: MissingCompileTimeError
-generic_methods_overriding_test/03: MissingCompileTimeError
-getter_no_setter2_test/00: MissingCompileTimeError
-getter_no_setter2_test/01: MissingCompileTimeError
-getter_no_setter2_test/03: MissingCompileTimeError
-getter_no_setter_test/00: MissingCompileTimeError
-getter_no_setter_test/01: MissingCompileTimeError
-getter_no_setter_test/03: MissingCompileTimeError
-getter_override_test/00: MissingCompileTimeError
-getter_override_test/01: MissingCompileTimeError
-getter_override_test/02: MissingCompileTimeError
-getter_override_test/03: MissingCompileTimeError
-getters_setters2_test/02: MissingCompileTimeError
-if_null_assignment_behavior_test/03: MissingCompileTimeError
-if_null_assignment_behavior_test/13: MissingCompileTimeError
-if_null_assignment_behavior_test/15: MissingCompileTimeError
-if_null_assignment_static_test/02: MissingCompileTimeError
-if_null_assignment_static_test/04: MissingCompileTimeError
-if_null_assignment_static_test/06: MissingCompileTimeError
-if_null_assignment_static_test/07: MissingCompileTimeError
-if_null_assignment_static_test/09: MissingCompileTimeError
-if_null_assignment_static_test/11: MissingCompileTimeError
-if_null_assignment_static_test/13: MissingCompileTimeError
-if_null_assignment_static_test/14: MissingCompileTimeError
-if_null_assignment_static_test/16: MissingCompileTimeError
-if_null_assignment_static_test/18: MissingCompileTimeError
-if_null_assignment_static_test/20: MissingCompileTimeError
-if_null_assignment_static_test/21: MissingCompileTimeError
-if_null_assignment_static_test/23: MissingCompileTimeError
-if_null_assignment_static_test/25: MissingCompileTimeError
-if_null_assignment_static_test/27: MissingCompileTimeError
-if_null_assignment_static_test/28: MissingCompileTimeError
-if_null_assignment_static_test/30: MissingCompileTimeError
-if_null_assignment_static_test/32: MissingCompileTimeError
-if_null_assignment_static_test/34: MissingCompileTimeError
-if_null_assignment_static_test/35: MissingCompileTimeError
-if_null_assignment_static_test/37: MissingCompileTimeError
-if_null_assignment_static_test/39: MissingCompileTimeError
-if_null_assignment_static_test/41: MissingCompileTimeError
-if_null_assignment_static_test/42: MissingCompileTimeError
-if_null_precedence_test/06: MissingCompileTimeError
-if_null_precedence_test/07: MissingCompileTimeError
-implicit_this_test/02: MissingCompileTimeError
-import_combinators2_test/00: MissingCompileTimeError
-import_self_test/01: MissingCompileTimeError
-inferrer_constructor5_test/01: MissingCompileTimeError
-initializing_formal_final_test: MissingCompileTimeError
-initializing_formal_type_test: MissingCompileTimeError
-instance_call_wrong_argument_count_negative_test: Fail
-instance_method2_negative_test: Fail
-instance_method_negative_test: Fail
-instantiate_type_variable_test/01: MissingCompileTimeError
-interface_static_non_final_fields_negative_test: Fail
-interface_test/00: MissingCompileTimeError
-invalid_cast_test/01: MissingCompileTimeError
-invalid_cast_test/02: MissingCompileTimeError
-invalid_cast_test/03: MissingCompileTimeError
-invalid_cast_test/04: MissingCompileTimeError
-invalid_cast_test/07: MissingCompileTimeError
-invalid_cast_test/08: MissingCompileTimeError
-invalid_cast_test/09: MissingCompileTimeError
-invalid_cast_test/10: MissingCompileTimeError
-invalid_cast_test/11: MissingCompileTimeError
-invalid_type_argument_count_test/01: MissingCompileTimeError
-invalid_type_argument_count_test/02: MissingCompileTimeError
-invalid_type_argument_count_test/03: MissingCompileTimeError
-invalid_type_argument_count_test/04: MissingCompileTimeError
-issue31596_override_test/05: MissingCompileTimeError
-issue31596_override_test/06: MissingCompileTimeError
-least_upper_bound_expansive_test/01: MissingCompileTimeError
-least_upper_bound_expansive_test/02: MissingCompileTimeError
-least_upper_bound_expansive_test/03: MissingCompileTimeError
-least_upper_bound_expansive_test/04: MissingCompileTimeError
-least_upper_bound_expansive_test/05: MissingCompileTimeError
-least_upper_bound_expansive_test/06: MissingCompileTimeError
-least_upper_bound_expansive_test/07: MissingCompileTimeError
-least_upper_bound_expansive_test/08: MissingCompileTimeError
-least_upper_bound_expansive_test/09: MissingCompileTimeError
-least_upper_bound_expansive_test/10: MissingCompileTimeError
-least_upper_bound_expansive_test/11: MissingCompileTimeError
-least_upper_bound_expansive_test/12: MissingCompileTimeError
-least_upper_bound_test/03: MissingCompileTimeError
-least_upper_bound_test/04: MissingCompileTimeError
-least_upper_bound_test/10: MissingCompileTimeError
-least_upper_bound_test/19: MissingCompileTimeError
-least_upper_bound_test/20: MissingCompileTimeError
-least_upper_bound_test/23: MissingCompileTimeError
-least_upper_bound_test/24: MissingCompileTimeError
-least_upper_bound_test/29: MissingCompileTimeError
-least_upper_bound_test/30: MissingCompileTimeError
-least_upper_bound_test/32: MissingCompileTimeError
-library_ambiguous_test/00: MissingCompileTimeError
-library_ambiguous_test/01: MissingCompileTimeError
-library_ambiguous_test/02: MissingCompileTimeError
-library_ambiguous_test/03: MissingCompileTimeError
-library_ambiguous_test/04: MissingCompileTimeError
-list_literal1_test/01: MissingCompileTimeError
-list_literal4_test/00: MissingCompileTimeError
-list_literal4_test/01: MissingCompileTimeError
-list_literal4_test/03: MissingCompileTimeError
-list_literal4_test/04: MissingCompileTimeError
-list_literal4_test/05: MissingCompileTimeError
-list_literal_syntax_test/01: MissingCompileTimeError
-list_literal_syntax_test/02: MissingCompileTimeError
-list_literal_syntax_test/03: MissingCompileTimeError
-local_function2_test/01: MissingCompileTimeError
-local_function2_test/02: MissingCompileTimeError
-local_function3_test/01: MissingCompileTimeError
-local_function_test/01: MissingCompileTimeError
-local_function_test/02: MissingCompileTimeError
-local_function_test/03: MissingCompileTimeError
-local_function_test/04: MissingCompileTimeError
-logical_expression3_test: MissingCompileTimeError
-malformed2_test/00: MissingCompileTimeError
-malformed2_test/01: MissingCompileTimeError
-malformed2_test/02: MissingCompileTimeError
-malformed2_test/03: MissingCompileTimeError
-malformed2_test/04: MissingCompileTimeError
-malformed2_test/05: MissingCompileTimeError
-malformed2_test/06: MissingCompileTimeError
-malformed2_test/07: MissingCompileTimeError
-malformed2_test/08: MissingCompileTimeError
-malformed2_test/09: MissingCompileTimeError
-malformed2_test/10: MissingCompileTimeError
-malformed2_test/11: MissingCompileTimeError
-malformed2_test/12: MissingCompileTimeError
-malformed2_test/13: MissingCompileTimeError
-malformed_bound_test/00: MissingCompileTimeError
-malformed_bound_test/01: MissingCompileTimeError
-malformed_inheritance_test/01: MissingCompileTimeError
-malformed_inheritance_test/03: MissingCompileTimeError
-malformed_inheritance_test/05: MissingCompileTimeError
-malformed_test/00: MissingCompileTimeError
-malformed_test/01: MissingCompileTimeError
-malformed_test/02: MissingCompileTimeError
-malformed_test/03: MissingCompileTimeError
-malformed_test/04: MissingCompileTimeError
-malformed_test/05: MissingCompileTimeError
-malformed_test/06: MissingCompileTimeError
-malformed_test/07: MissingCompileTimeError
-malformed_test/08: MissingCompileTimeError
-malformed_test/09: MissingCompileTimeError
-malformed_test/10: MissingCompileTimeError
-malformed_test/11: MissingCompileTimeError
-malformed_test/12: MissingCompileTimeError
-malformed_test/13: MissingCompileTimeError
-malformed_test/14: MissingCompileTimeError
-malformed_test/15: MissingCompileTimeError
-malformed_test/16: MissingCompileTimeError
-malformed_test/17: MissingCompileTimeError
-malformed_test/18: MissingCompileTimeError
-malformed_test/19: MissingCompileTimeError
-malformed_test/20: MissingCompileTimeError
-malformed_test/21: MissingCompileTimeError
-malformed_test/22: MissingCompileTimeError
-malformed_test/23: MissingCompileTimeError
-malformed_test/24: MissingCompileTimeError
-malformed_type_test: MissingCompileTimeError
-method_override2_test/00: MissingCompileTimeError
-method_override2_test/01: MissingCompileTimeError
-method_override2_test/02: MissingCompileTimeError
-method_override2_test/03: MissingCompileTimeError
-method_override3_test/00: MissingCompileTimeError
-method_override3_test/01: MissingCompileTimeError
-method_override3_test/02: MissingCompileTimeError
-method_override7_test/00: MissingCompileTimeError
-method_override7_test/01: MissingCompileTimeError
-method_override7_test/02: MissingCompileTimeError
-method_override7_test/03: MissingCompileTimeError
-mixin_illegal_constructor_test/13: MissingCompileTimeError
-mixin_illegal_constructor_test/14: MissingCompileTimeError
-mixin_illegal_constructor_test/15: MissingCompileTimeError
-mixin_illegal_constructor_test/16: MissingCompileTimeError
-mixin_illegal_static_access_test/01: MissingCompileTimeError
-mixin_illegal_static_access_test/02: MissingCompileTimeError
-mixin_illegal_super_use_test/01: MissingCompileTimeError
-mixin_illegal_super_use_test/02: MissingCompileTimeError
-mixin_illegal_super_use_test/03: MissingCompileTimeError
-mixin_illegal_super_use_test/04: MissingCompileTimeError
-mixin_illegal_super_use_test/05: MissingCompileTimeError
-mixin_illegal_super_use_test/06: MissingCompileTimeError
-mixin_illegal_super_use_test/07: MissingCompileTimeError
-mixin_illegal_super_use_test/08: MissingCompileTimeError
-mixin_illegal_super_use_test/09: MissingCompileTimeError
-mixin_illegal_super_use_test/10: MissingCompileTimeError
-mixin_illegal_super_use_test/11: MissingCompileTimeError
-mixin_illegal_superclass_test/01: MissingCompileTimeError
-mixin_illegal_superclass_test/02: MissingCompileTimeError
-mixin_illegal_superclass_test/03: MissingCompileTimeError
-mixin_illegal_superclass_test/04: MissingCompileTimeError
-mixin_illegal_superclass_test/05: MissingCompileTimeError
-mixin_illegal_superclass_test/06: MissingCompileTimeError
-mixin_illegal_superclass_test/07: MissingCompileTimeError
-mixin_illegal_superclass_test/08: MissingCompileTimeError
-mixin_illegal_superclass_test/09: MissingCompileTimeError
-mixin_illegal_superclass_test/10: MissingCompileTimeError
-mixin_illegal_superclass_test/11: MissingCompileTimeError
-mixin_illegal_superclass_test/12: MissingCompileTimeError
-mixin_illegal_superclass_test/13: MissingCompileTimeError
-mixin_illegal_superclass_test/14: MissingCompileTimeError
-mixin_illegal_superclass_test/15: MissingCompileTimeError
-mixin_illegal_superclass_test/16: MissingCompileTimeError
-mixin_illegal_superclass_test/17: MissingCompileTimeError
-mixin_illegal_superclass_test/18: MissingCompileTimeError
-mixin_illegal_superclass_test/19: MissingCompileTimeError
-mixin_illegal_superclass_test/20: MissingCompileTimeError
-mixin_illegal_superclass_test/21: MissingCompileTimeError
-mixin_illegal_superclass_test/22: MissingCompileTimeError
-mixin_illegal_superclass_test/23: MissingCompileTimeError
-mixin_illegal_superclass_test/24: MissingCompileTimeError
-mixin_illegal_superclass_test/25: MissingCompileTimeError
-mixin_illegal_superclass_test/26: MissingCompileTimeError
-mixin_illegal_superclass_test/27: MissingCompileTimeError
-mixin_illegal_superclass_test/28: MissingCompileTimeError
-mixin_illegal_superclass_test/29: MissingCompileTimeError
-mixin_illegal_superclass_test/30: MissingCompileTimeError
-mixin_illegal_syntax_test/13: MissingCompileTimeError
-mixin_type_parameter_inference_error_test/01: MissingCompileTimeError
-mixin_type_parameter_inference_error_test/02: MissingCompileTimeError
-mixin_type_parameter_inference_previous_mixin_test/03: MissingCompileTimeError
-mixin_type_parameter_inference_previous_mixin_test/04: MissingCompileTimeError
-mixin_type_parameter_inference_test/04: MissingCompileTimeError
-mixin_type_parameter_inference_test/05: MissingCompileTimeError
-mixin_type_parameter_inference_test/06: MissingCompileTimeError
-mixin_type_parameter_inference_test/07: MissingCompileTimeError
-mixin_type_parameter_inference_test/11: MissingCompileTimeError
-mixin_type_parameter_inference_test/14: MissingCompileTimeError
-mixin_type_parameter_inference_test/15: MissingCompileTimeError
-mixin_type_parameters_errors_test/01: MissingCompileTimeError
-mixin_type_parameters_errors_test/02: MissingCompileTimeError
-mixin_type_parameters_errors_test/05: MissingCompileTimeError
-mixin_with_two_implicit_constructors_test: MissingCompileTimeError
-multiline_newline_test/04: MissingCompileTimeError
-multiline_newline_test/04r: MissingCompileTimeError
-multiline_newline_test/05: MissingCompileTimeError
-multiline_newline_test/05r: MissingCompileTimeError
-multiline_newline_test/06: MissingCompileTimeError
-multiline_newline_test/06r: MissingCompileTimeError
-named_constructor_test/03: MissingCompileTimeError
-named_parameters2_test: MissingCompileTimeError
-named_parameters3_test: MissingCompileTimeError
-named_parameters4_test: MissingCompileTimeError
-named_parameters_aggregated_test/05: MissingCompileTimeError
-named_parameters_test/01: MissingCompileTimeError
-named_parameters_test/02: MissingCompileTimeError
-named_parameters_test/03: MissingCompileTimeError
-named_parameters_test/04: MissingCompileTimeError
-named_parameters_test/05: MissingCompileTimeError
-named_parameters_test/06: MissingCompileTimeError
-named_parameters_test/07: MissingCompileTimeError
-named_parameters_test/08: MissingCompileTimeError
-named_parameters_test/09: MissingCompileTimeError
-named_parameters_test/10: MissingCompileTimeError
-named_parameters_type_test/01: MissingCompileTimeError
-named_parameters_type_test/02: MissingCompileTimeError
-named_parameters_type_test/03: MissingCompileTimeError
-new_expression_type_args_test/00: MissingCompileTimeError
-new_expression_type_args_test/01: MissingCompileTimeError
-new_expression_type_args_test/02: MissingCompileTimeError
-new_prefix_test/01: MissingCompileTimeError
-no_such_constructor_test/01: MissingCompileTimeError
-no_such_method_negative_test: Fail
-not_enough_positional_arguments_test/00: MissingCompileTimeError
-not_enough_positional_arguments_test/01: MissingCompileTimeError
-not_enough_positional_arguments_test/02: MissingCompileTimeError
-not_enough_positional_arguments_test/03: MissingCompileTimeError
-not_enough_positional_arguments_test/05: MissingCompileTimeError
-not_enough_positional_arguments_test/06: MissingCompileTimeError
-not_enough_positional_arguments_test/07: MissingCompileTimeError
-object_has_no_call_method_test/02: MissingCompileTimeError
-object_has_no_call_method_test/05: MissingCompileTimeError
-object_has_no_call_method_test/08: MissingCompileTimeError
-optional_named_parameters_test/01: MissingCompileTimeError
-optional_named_parameters_test/02: MissingCompileTimeError
-optional_named_parameters_test/03: MissingCompileTimeError
-optional_named_parameters_test/04: MissingCompileTimeError
-optional_named_parameters_test/05: MissingCompileTimeError
-optional_named_parameters_test/06: MissingCompileTimeError
-optional_named_parameters_test/07: MissingCompileTimeError
-optional_named_parameters_test/08: MissingCompileTimeError
-optional_named_parameters_test/09: MissingCompileTimeError
-override_field_test/01: MissingCompileTimeError
-override_inheritance_abstract_test/*: Skip # Tests Dart 2 semantics
-override_inheritance_field_test/04: MissingCompileTimeError
-override_inheritance_field_test/05: MissingCompileTimeError
-override_inheritance_field_test/06: MissingCompileTimeError
-override_inheritance_field_test/07: MissingCompileTimeError
-override_inheritance_field_test/08: MissingCompileTimeError
-override_inheritance_field_test/09: MissingCompileTimeError
-override_inheritance_field_test/10: MissingCompileTimeError
-override_inheritance_field_test/11: MissingCompileTimeError
-override_inheritance_field_test/26: MissingCompileTimeError
-override_inheritance_field_test/28: MissingCompileTimeError
-override_inheritance_field_test/29: MissingCompileTimeError
-override_inheritance_field_test/30: MissingCompileTimeError
-override_inheritance_field_test/31: MissingCompileTimeError
-override_inheritance_field_test/32: MissingCompileTimeError
-override_inheritance_field_test/33: MissingCompileTimeError
-override_inheritance_field_test/33a: MissingCompileTimeError
-override_inheritance_field_test/34: MissingCompileTimeError
-override_inheritance_generic_test/02: MissingCompileTimeError
-override_inheritance_generic_test/04: MissingCompileTimeError
-override_inheritance_generic_test/06: MissingCompileTimeError
-override_inheritance_generic_test/07: MissingCompileTimeError
-override_inheritance_generic_test/08: MissingCompileTimeError
-override_inheritance_generic_test/09: MissingCompileTimeError
-override_inheritance_generic_test/10: MissingCompileTimeError
-override_inheritance_method_test/04: MissingCompileTimeError
-override_inheritance_method_test/05: MissingCompileTimeError
-override_inheritance_method_test/06: MissingCompileTimeError
-override_inheritance_method_test/11: MissingCompileTimeError
-override_inheritance_method_test/12: MissingCompileTimeError
-override_inheritance_method_test/13: MissingCompileTimeError
-override_inheritance_method_test/14: MissingCompileTimeError
-override_inheritance_method_test/19: MissingCompileTimeError
-override_inheritance_method_test/20: MissingCompileTimeError
-override_inheritance_method_test/21: MissingCompileTimeError
-override_inheritance_method_test/27: MissingCompileTimeError
-override_inheritance_method_test/28: MissingCompileTimeError
-override_inheritance_method_test/29: MissingCompileTimeError
-override_inheritance_method_test/30: MissingCompileTimeError
-override_inheritance_method_test/31: MissingCompileTimeError
-override_inheritance_method_test/32: MissingCompileTimeError
-override_inheritance_method_test/33: MissingCompileTimeError
-override_inheritance_method_test/36: MissingCompileTimeError
-override_inheritance_method_test/39: MissingCompileTimeError
-override_method_with_field_test/02: MissingCompileTimeError
-part2_test/01: MissingCompileTimeError
-partial_tearoff_instantiation_test/01: MissingCompileTimeError
-partial_tearoff_instantiation_test/03: MissingCompileTimeError
-positional_parameters_type_test/01: MissingCompileTimeError
-positional_parameters_type_test/02: MissingCompileTimeError
-prefix16_test/00: MissingCompileTimeError
-prefix16_test/01: MissingCompileTimeError
-prefix22_test/00: MissingCompileTimeError
-prefix23_test/00: MissingCompileTimeError
-private_access_test/01: MissingCompileTimeError
-private_access_test/02: MissingCompileTimeError
-private_access_test/03: MissingCompileTimeError
-private_access_test/04: MissingCompileTimeError
-private_access_test/05: MissingCompileTimeError
-private_access_test/06: MissingCompileTimeError
-private_member1_negative_test: Fail
-private_member2_negative_test: Fail
-private_member3_negative_test: Fail
-private_super_constructor_test/01: MissingCompileTimeError
-regress_12561_test: MissingCompileTimeError
-regress_13494_test: MissingCompileTimeError
-regress_17382_test: MissingCompileTimeError
-regress_19413_test: MissingCompileTimeError
-regress_19728_test: MissingCompileTimeError
-regress_20394_test/01: MissingCompileTimeError
-regress_21793_test/01: MissingCompileTimeError
-regress_21912_test/01: MissingCompileTimeError
-regress_21912_test/02: MissingCompileTimeError
-regress_22438_test: MissingCompileTimeError
-regress_22936_test: MissingCompileTimeError
-regress_26133_test: MissingCompileTimeError
-regress_27572_test: MissingCompileTimeError
-regress_28217_test/01: MissingCompileTimeError
-regress_28217_test/none: MissingCompileTimeError
-return_type_test: MissingCompileTimeError
-rewrite_implicit_this_test/01: MissingCompileTimeError
-setter_no_getter_call_test/01: MissingCompileTimeError
-setter_override2_test/02: MissingCompileTimeError
-setter_override_test/00: MissingCompileTimeError
-setter_override_test/01: MissingCompileTimeError
-setter_override_test/02: MissingCompileTimeError
-setter_override_test/03: MissingCompileTimeError
-static_call_wrong_argument_count_negative_test: Fail
-static_field1_test/01: MissingCompileTimeError
-static_field1a_test/01: MissingCompileTimeError
-static_field3_test/01: MissingCompileTimeError
-static_field3_test/02: MissingCompileTimeError
-static_field3_test/03: MissingCompileTimeError
-static_field3_test/04: MissingCompileTimeError
-static_field_test/01: MissingCompileTimeError
-static_field_test/02: MissingCompileTimeError
-static_field_test/03: MissingCompileTimeError
-static_field_test/04: MissingCompileTimeError
-static_final_field2_test/01: MissingCompileTimeError
-static_getter_no_setter1_test/01: MissingCompileTimeError
-static_getter_no_setter2_test/01: MissingCompileTimeError
-static_initializer_type_error_test: MissingCompileTimeError
-static_setter_conflicts_test/01: MissingCompileTimeError
-static_setter_conflicts_test/03: MissingCompileTimeError
-static_setter_conflicts_test/04: MissingCompileTimeError
-static_setter_conflicts_test/07: MissingCompileTimeError
-static_setter_get_test/01: MissingCompileTimeError
-string_interpolation_test/01: MissingCompileTimeError
-string_no_operator_test/01: MissingCompileTimeError
-string_no_operator_test/02: MissingCompileTimeError
-string_no_operator_test/03: MissingCompileTimeError
-string_no_operator_test/04: MissingCompileTimeError
-string_no_operator_test/05: MissingCompileTimeError
-string_no_operator_test/06: MissingCompileTimeError
-string_no_operator_test/07: MissingCompileTimeError
-string_no_operator_test/08: MissingCompileTimeError
-string_no_operator_test/09: MissingCompileTimeError
-string_no_operator_test/10: MissingCompileTimeError
-string_no_operator_test/11: MissingCompileTimeError
-string_no_operator_test/12: MissingCompileTimeError
-string_no_operator_test/13: MissingCompileTimeError
-string_no_operator_test/14: MissingCompileTimeError
-string_no_operator_test/15: MissingCompileTimeError
-string_no_operator_test/16: MissingCompileTimeError
-string_test/01: MissingCompileTimeError
-substring_test/01: MissingCompileTimeError
-super_assign_test/01: MissingCompileTimeError
-super_bound_closure_test/01: MissingCompileTimeError
-super_operator_index_test/01: MissingCompileTimeError
-super_operator_index_test/02: MissingCompileTimeError
-super_operator_index_test/03: MissingCompileTimeError
-super_operator_index_test/04: MissingCompileTimeError
-super_operator_index_test/05: MissingCompileTimeError
-super_operator_index_test/06: MissingCompileTimeError
-super_operator_index_test/07: MissingCompileTimeError
-switch_fallthru_test/01: MissingCompileTimeError
-symbol_literal_test/01: MissingCompileTimeError
-sync_generator1_test/01: MissingCompileTimeError
-syntax_test/59: MissingCompileTimeError
-top_level_getter_no_setter1_test: MissingCompileTimeError
-top_level_getter_no_setter2_test: MissingCompileTimeError
-transitive_private_library_access_test: MissingCompileTimeError
-try_catch_on_syntax_test/07: MissingCompileTimeError
-try_catch_on_syntax_test/10: MissingCompileTimeError
-try_catch_on_syntax_test/11: MissingCompileTimeError
-try_catch_syntax_test/08: MissingCompileTimeError
-try_catch_test/01: MissingCompileTimeError
-type_check_const_function_typedef2_test: MissingCompileTimeError
-type_checks_in_factory_method_test/01: MissingCompileTimeError
-type_inference_accessor_ref_test/03: MissingCompileTimeError
-type_inference_accessor_ref_test/06: MissingCompileTimeError
-type_inference_circularity_test: MissingCompileTimeError
-type_inference_inconsistent_inheritance_test: MissingCompileTimeError
-type_promotion_parameter_test/01: MissingCompileTimeError
-type_promotion_parameter_test/02: MissingCompileTimeError
-type_promotion_parameter_test/03: MissingCompileTimeError
-type_promotion_parameter_test/04: MissingCompileTimeError
-type_promotion_parameter_test/05: MissingCompileTimeError
-type_promotion_parameter_test/06: MissingCompileTimeError
-type_promotion_parameter_test/07: MissingCompileTimeError
-type_promotion_parameter_test/08: MissingCompileTimeError
-type_promotion_parameter_test/09: MissingCompileTimeError
-type_promotion_parameter_test/10: MissingCompileTimeError
-type_promotion_parameter_test/11: MissingCompileTimeError
-type_promotion_parameter_test/12: MissingCompileTimeError
-type_promotion_parameter_test/13: MissingCompileTimeError
-type_promotion_parameter_test/14: MissingCompileTimeError
-type_promotion_parameter_test/15: MissingCompileTimeError
-type_promotion_parameter_test/16: MissingCompileTimeError
-type_promotion_parameter_test/17: MissingCompileTimeError
-type_promotion_parameter_test/18: MissingCompileTimeError
-type_promotion_parameter_test/19: MissingCompileTimeError
-type_promotion_parameter_test/20: MissingCompileTimeError
-type_promotion_parameter_test/21: MissingCompileTimeError
-type_promotion_parameter_test/22: MissingCompileTimeError
-type_promotion_parameter_test/23: MissingCompileTimeError
-type_promotion_parameter_test/24: MissingCompileTimeError
-type_promotion_parameter_test/25: MissingCompileTimeError
-type_promotion_parameter_test/26: MissingCompileTimeError
-type_promotion_parameter_test/27: MissingCompileTimeError
-type_promotion_parameter_test/28: MissingCompileTimeError
-type_promotion_parameter_test/29: MissingCompileTimeError
-type_promotion_parameter_test/30: MissingCompileTimeError
-type_promotion_parameter_test/31: MissingCompileTimeError
-type_promotion_parameter_test/32: MissingCompileTimeError
-type_promotion_parameter_test/33: MissingCompileTimeError
-type_promotion_parameter_test/34: MissingCompileTimeError
-type_promotion_parameter_test/35: MissingCompileTimeError
-type_promotion_parameter_test/36: MissingCompileTimeError
-type_promotion_parameter_test/37: MissingCompileTimeError
-type_promotion_parameter_test/38: MissingCompileTimeError
-type_promotion_parameter_test/39: MissingCompileTimeError
-type_promotion_parameter_test/40: MissingCompileTimeError
-type_promotion_parameter_test/41: MissingCompileTimeError
-type_promotion_parameter_test/42: MissingCompileTimeError
-type_promotion_parameter_test/43: MissingCompileTimeError
-type_promotion_parameter_test/44: MissingCompileTimeError
-type_promotion_parameter_test/45: MissingCompileTimeError
-type_promotion_parameter_test/46: MissingCompileTimeError
-type_promotion_parameter_test/47: MissingCompileTimeError
-type_promotion_parameter_test/48: MissingCompileTimeError
-type_promotion_parameter_test/49: MissingCompileTimeError
-type_promotion_parameter_test/50: MissingCompileTimeError
-type_promotion_parameter_test/51: MissingCompileTimeError
-type_promotion_parameter_test/52: MissingCompileTimeError
-type_promotion_parameter_test/54: MissingCompileTimeError
-type_promotion_parameter_test/55: MissingCompileTimeError
-type_promotion_parameter_test/56: MissingCompileTimeError
-type_variable_bounds_test/00: MissingCompileTimeError
-type_variable_bounds_test/07: MissingCompileTimeError
-type_variable_bounds_test/09: MissingCompileTimeError
-type_variable_bounds_test/10: MissingCompileTimeError
-type_variable_conflict2_test/01: MissingCompileTimeError
-type_variable_conflict2_test/02: MissingCompileTimeError
-type_variable_conflict2_test/03: MissingCompileTimeError
-type_variable_conflict2_test/04: MissingCompileTimeError
-type_variable_conflict2_test/05: MissingCompileTimeError
-type_variable_conflict2_test/07: MissingCompileTimeError
-type_variable_conflict2_test/09: MissingCompileTimeError
-type_variable_identifier_expression_test: MissingCompileTimeError
-type_variable_scope2_test: MissingCompileTimeError
-type_variable_scope_test/00: MissingCompileTimeError
-type_variable_scope_test/01: MissingCompileTimeError
-type_variable_scope_test/02: MissingCompileTimeError
-type_variable_scope_test/03: MissingCompileTimeError
-type_variable_scope_test/04: MissingCompileTimeError
-type_variable_scope_test/05: MissingCompileTimeError
-type_variable_static_context_test: MissingCompileTimeError
-typed_selector2_test: MissingCompileTimeError
-unbound_getter_test: MissingCompileTimeError
-unresolved_default_constructor_test/01: MissingCompileTimeError
-unresolved_in_factory_test: MissingCompileTimeError
-unresolved_top_level_method_test: MissingCompileTimeError
-unresolved_top_level_var_test: MissingCompileTimeError
-
 [ $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
 symbol_conflict_test: Pass, Slow
 
 # Enabling of dartk for sim{arm,arm64,dbc64} revealed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
 # batch mode.
-[ $strong && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ]
+[ ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ]
 least_upper_bound_expansive_test/none: RuntimeError # Please triage.
 
-[ $strong && ($compiler == dartk || $compiler == dartkb) ]
-covariant_subtyping_test: RuntimeError
-redirecting_factory_reflection_test: RuntimeError
-
-[ !$strong && ($compiler == dartk || $compiler == dartkb || $compiler == dartkp || $runtime == dart_precompiled || $runtime == vm) ]
-*: SkipByDesign # language_2 is only supported in strong mode.
-
 [ ($compiler == app_jitk || $compiler == dartk || $compiler == dartkp) && ($runtime == dart_precompiled || $runtime == vm) ]
 covariant_subtyping_with_mixin_test: RuntimeError # Issue 34321
 type_alias_equality_test/03: RuntimeError # Issue 32783
@@ -2095,6 +1049,10 @@
 async_star_test/none: Skip # Timeout
 type_constants_test/none: Skip # Deferred libraries and hot reload.
 
+[ $compiler == dartk || $compiler == dartkb ]
+covariant_subtyping_test: RuntimeError
+redirecting_factory_reflection_test: RuntimeError
+
 [ $compiler == dartk || $compiler == dartkb || $compiler == dartkp ]
 generic_function_bounds_test: RuntimeError # Issue 32076
 
diff --git a/tests/language_2/language_2_spec_parser.status b/tests/language_2/language_2_spec_parser.status
index c8867ce..1c7952a 100644
--- a/tests/language_2/language_2_spec_parser.status
+++ b/tests/language_2/language_2_spec_parser.status
@@ -34,6 +34,7 @@
 new_expression1_negative_test: Fail # Negative, uses `new id`.
 new_expression2_negative_test: Fail # Negative, uses `new id(`.
 new_expression3_negative_test: Fail # Negative, uses `new id(...`.
+nnbd/*: Skip # Not yet included.
 no_such_method_negative_test: Skip # Negative, not syntax.
 non_const_super_negative_test: Skip # Negative, not syntax.
 operator1_negative_test: Fail # Negative, declares static operator.
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index fef4d22..ceb8ec6 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -28,8 +28,5 @@
 [ $arch == ia32 && $mode == release && $runtime == vm ]
 deep_nesting_expression_test/01: Crash, Pass # Issue 31496
 
-[ !$strong && ($runtime == dart_precompiled || $runtime == vm) ]
-*: SkipByDesign # tests/language has the non-strong mode versions of these tests.
-
 [ $runtime == dart_precompiled || $runtime == vm ]
 superinterface_variance/*: Skip # Issue dart-lang/language#113
diff --git a/tests/language_2/lazy_spread_test.dart b/tests/language_2/lazy_spread_test.dart
new file mode 100644
index 0000000..eedb957
--- /dev/null
+++ b/tests/language_2/lazy_spread_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that the body of an if element with unevaluated condition can
+// contain a spread.
+// Regression test for https://github.com/dart-lang/sdk/issues/36812
+
+// SharedOptions=--enable-experiment=constant-update-2018
+
+const b = bool.fromEnvironment("foo");
+
+main() {
+  const l1 = [1, 2, 3];
+  const l2 = [if (b) ...l1];
+  print(l2);
+}
diff --git a/tests/language_2/local_function2_test.dart b/tests/language_2/local_function2_test.dart
index c9b3bb4..44d2ef9 100644
--- a/tests/language_2/local_function2_test.dart
+++ b/tests/language_2/local_function2_test.dart
@@ -10,12 +10,12 @@
 class Parameterized<T> {
   Parameterized() {}
   T mul3(F<T> f, T t) {
-    return 3 * f(t); //# 01: compile-time error
+    return (3 as dynamic) * f(t);
   }
 
   T test(T t) {
     return mul3((T t) {
-      return 3 * t; //# 02: compile-time error
+      return (3 as dynamic) * t;
     }, t);
   }
 }
diff --git a/tests/language_2/local_function3_test.dart b/tests/language_2/local_function3_test.dart
index d6f59d2..0fc44b0 100644
--- a/tests/language_2/local_function3_test.dart
+++ b/tests/language_2/local_function3_test.dart
@@ -7,13 +7,13 @@
 
 class LocalFunction3Test {
   static testExceptions() {
-    var f = (int n) {
+    dynamic f = (int n) {
       return n + 1;
     };
     Expect.equals(true, f is Object);
     bool exception_caught = false;
     try {
-      f.xyz(0); //# 01: compile-time error
+      f.xyz(0);
     } on NoSuchMethodError {
       exception_caught = true;
     }
diff --git a/tests/language_2/local_function_test.dart b/tests/language_2/local_function_test.dart
index ceb7ef9..100b7c4 100644
--- a/tests/language_2/local_function_test.dart
+++ b/tests/language_2/local_function_test.dart
@@ -161,35 +161,35 @@
   }
 
   static testExceptions() {
-    var f = (int n) => n + 1;
+    dynamic f = (int n) => n + 1;
     Expect.equals(2, f(1));
     Expect.equals(true, f is Function);
     Expect.equals(true, f is Object);
     Expect.equals(true, f.toString().startsWith("Closure"));
     bool exception_caught = false;
     try {
-      f(1, 2); //# 01: compile-time error
+      f(1, 2);
     } on NoSuchMethodError catch (e) {
       exception_caught = true;
     }
     Expect.equals(true, exception_caught);
     exception_caught = false;
     try {
-      f(); //# 02: compile-time error
+      f();
     } on NoSuchMethodError catch (e) {
       exception_caught = true;
     }
     Expect.equals(true, exception_caught);
     exception_caught = false;
     try {
-      f.xyz(0); //# 03: compile-time error
+      f.xyz(0);
     } on NoSuchMethodError catch (e) {
       exception_caught = true;
     }
     Expect.equals(true, exception_caught);
 
     // Overwrite closure value.
-    f = 3; //# 04: compile-time error
+    f = 3;
     exception_caught = false;
     try {
       f(1);
diff --git a/tests/language_2/local_var_in_annotation_test.dart b/tests/language_2/local_var_in_annotation_test.dart
new file mode 100644
index 0000000..f6474f8
--- /dev/null
+++ b/tests/language_2/local_var_in_annotation_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/37065
+
+const x = 0;
+main(@x args) {
+  const z = 0;
+  foo(@z args) {}
+  bar(@x args) {}
+}
diff --git a/tests/language_2/mixin_implicit_covariance_test.dart b/tests/language_2/mixin_implicit_covariance_test.dart
new file mode 100644
index 0000000..5606bd7
--- /dev/null
+++ b/tests/language_2/mixin_implicit_covariance_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, 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 A<T> {
+  foo(T x);
+}
+
+abstract class B<T> implements A<T> {}
+
+class C {
+  foo(num x) {
+    if (x is! num) {
+      throw "Soudness issue: expected x to be num, got ${x.runtimeType}.";
+    }
+  }
+}
+
+class D<T extends num> extends C with B<T> {}
+
+class E<T extends num> = C with B<T>;
+
+test(B<dynamic> b) {
+  b.foo("bar");
+}
+
+main() {
+  Expect.throws<TypeError>(() => test(new D<int>()));
+  Expect.throws<TypeError>(() => test(new E<int>()));
+}
diff --git a/tests/language_2/named_parameters_default_eq_test.dart b/tests/language_2/named_parameters_default_eq_test.dart
index 9a02777..17ee092 100644
--- a/tests/language_2/named_parameters_default_eq_test.dart
+++ b/tests/language_2/named_parameters_default_eq_test.dart
@@ -7,9 +7,9 @@
 import "package:expect/expect.dart";
 
 // Default values are not allowed on typedefs.
-typedef int F1({x = 3, y}); //# 01: compile-time error
+typedef F1({x = 3, y}); //# 01: compile-time error
 
-typedef int functype({x, y, z});
+typedef functype({x, y, z});
 
 int topF({x = 3, y: 5, z}) => x * y * (z ?? 2);
 
@@ -35,7 +35,7 @@
 
 main() {
   // Reference the type, or dart2js won't see that the declaration is invalid
-  F1 _ = null; // //# 01: continued
+  F1 _ = null; //# 01: continued
 
   var a = new A();
 
diff --git a/tests/language_2/nnbd/resolution/null_assertion_null_type_test.dart b/tests/language_2/nnbd/resolution/null_assertion_null_type_test.dart
new file mode 100644
index 0000000..159731d
--- /dev/null
+++ b/tests/language_2/nnbd/resolution/null_assertion_null_type_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that the trailing "!" properly promotes the type `Null` to `Never`, by
+// verifying that it's statically ok to pass it to a function expecting a
+// non-null parameter.
+import 'package:expect/expect.dart';
+
+void f(int i) {}
+
+void g(Null n) {
+   // Statically ok because `Never <: int`.  Throws at runtime.
+  f(n!);
+}
+
+main() {
+  Expect.throws(() => g(null));
+}
diff --git a/tests/language_2/nnbd/resolution/question_dot_produces_nullable_type_test.dart b/tests/language_2/nnbd/resolution/question_dot_produces_nullable_type_test.dart
new file mode 100644
index 0000000..bfb9388
--- /dev/null
+++ b/tests/language_2/nnbd/resolution/question_dot_produces_nullable_type_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+bool c = false;
+
+// Test that the type produced from expression `x?.y` is nullable.
+void main() {
+  int? x;
+  x?.bitLength + 1; //# 01: compile-time error
+  x?.round(2) + 1; //# 02: compile-time error
+}
+
+// Ensure it works correctly on type parameters
+void f<T extends num>(Generic<T>? generic, Generic<T?> nullableGeneric) {
+  generic?.getter + 1; //# 03: compile-time error
+  generic?.method() + 1; //# 04: compile-time error
+  generic?.nullableGetter + 1; //# 05: compile-time error
+  generic?.nullableMethod() + 1; //# 06: compile-time error
+  nullableGeneric?.getter + 1; //# 07: compile-time error
+  nullableGeneric?.method() + 1; //# 08: compile-time error
+  nullableGeneric?.nullableGetter + 1; //# 09: compile-time error
+  nullableGeneric?.nullableMethod() + 1; //# 10: compile-time error
+}
+
+class Generic<T> {
+  T get getter => throw Exception('unreachable');
+  T method() => throw Exception('unreachable');
+  T? nullableGetter = null;
+  T? nullableMethod() => null;
+}
diff --git a/tests/language_2/nnbd/resolution/question_question_lub_test.dart b/tests/language_2/nnbd/resolution/question_question_lub_test.dart
new file mode 100644
index 0000000..1606441
--- /dev/null
+++ b/tests/language_2/nnbd/resolution/question_question_lub_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that `x ?? y` results in type LUB(x!, y)
+void main() {
+  f1(null, 2);
+}
+
+void f1(
+    int? nullableInt,
+    int nonNullInt,
+) {
+  (nullableInt ?? nonNullInt) + 1; //# 00: ok
+  (nullableInt ?? nullableInt) + 1; //# 01: compile-time error
+  (nonNullInt ?? nullableInt) + 1; //# 02: compile-time error
+  (nonNullInt ?? nonNullInt) + 1; //# 03: ok
+}
+
+// TODO(mfairhurst) add cases with type parameter types
diff --git a/tests/language_2/nnbd/static_errors/default_list_constructor_test.dart b/tests/language_2/nnbd/static_errors/default_list_constructor_test.dart
new file mode 100644
index 0000000..7263438
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/default_list_constructor_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+import 'opted_out_library.dart';
+
+// Test that it is an error to call the default List constructor with a length
+// argument and a type argument which is potentially non-nullable.
+main() {
+  var a = new List<int>(3); //# 01: compile-time error
+  var b = new List<String?>(3);
+  List<C> c = List(5); //# 02: compile-time error
+  consumeListOfStringStar(new List(3)); //# 03: compile-time error
+}
+
+class A<T> {
+  var l = new List<T>(3); //# 04: compile-time error
+}
+
+class C {}
diff --git a/tests/language_2/nnbd/static_errors/default_value_on_required_parameter_test.dart b/tests/language_2/nnbd/static_errors/default_value_on_required_parameter_test.dart
new file mode 100644
index 0000000..7303897
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/default_value_on_required_parameter_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is an error if a required named parameter has a default value.
+main() {}
+
+void log1({String message: 'no message'}) {}
+void log2({String? message}) {}
+void log3({required String? message: 'no message'}) {} //# 01: compile-time error
+void log4({required String message}) {}
diff --git a/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart b/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
new file mode 100644
index 0000000..35e756e
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2019, 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';
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that Object.operator==(Object o) is the signature of ==, but that we can
+// still compare nullable values to Object.
+//
+// This is because a == b is essentially sugar for
+//
+// ```
+// identical(a, null) || identical (b, null)
+//   ? identical(a, b)
+//   : a.operator==(b);
+// ```
+//
+// It should not be required to handle `null` inside the implementation of
+// operator==, but it should not be an error to "assign null" to the parameter
+// of the comparison operator.
+main() {
+  Object o;
+  // Valid comparison.
+  o == null;
+
+  // Caveat: it is NOT that the argument is promoted to non-null. Otherwise,
+  // types which we can't cleanly promote, such as FutureOr<int?>, would not be
+  // assignable in comparisons.
+  FutureOr<int?> foInt;
+
+  // Valid comparison.
+  o == foInt;
+}
+
+class C {
+  // Valid override
+  @override
+  bool operator==(Object other) => identical(other, this);
+}
diff --git a/tests/language_2/nnbd/static_errors/implicit_downcasts.dart b/tests/language_2/nnbd/static_errors/implicit_downcasts.dart
new file mode 100644
index 0000000..6d8b7b4
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/implicit_downcasts.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is an error to do what was once allowed as an "implicit
+// downcast."
+main() {
+  num asNum = 1;
+  Object asObject = 1;
+  dynamic asDynamic = 1;
+  int asInt1 = asNum; //# 01: compile-time error
+  double asDouble1 = asNum; //# 02: compile-time error
+  int asInt2 = asObject; //# 03: compile-time error
+  double asDouble2 = asObject; //# 04: compile-time error
+  String asString1 = asObject; //# 05: compile-time error
+  int asInt3 = asDynamic; //# 06: ok
+}
diff --git a/tests/language_2/nnbd/static_errors/late_final_without_initializer.dart b/tests/language_2/nnbd/static_errors/late_final_without_initializer.dart
new file mode 100644
index 0000000..8386210
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/late_final_without_initializer.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is not a compile time error for a `final` variable to not have
+// an initializer if that variable is declared as `late`.
+import 'package:expect/expect.dart';
+import 'dart:core';
+
+main() {
+  late final a;
+  late final b = 0;
+}
+
+class C {
+  late final a;
+  late final b = 0;
+}
diff --git a/tests/language_2/nnbd/static_errors/missing_default_value_for_parameter_test.dart b/tests/language_2/nnbd/static_errors/missing_default_value_for_parameter_test.dart
new file mode 100644
index 0000000..ff664b7
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/missing_default_value_for_parameter_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is an error if an optional parameter (named or otherwise) with
+// no default value has a potentially non-nullable type.
+main() {}
+
+// Non-nullable types
+void f01({int a = 0}) {}
+void f02({int a}) {} //# 01: compile-time error
+void f03({required int a}) {}
+void f04([int a = 0]) {}
+void f05([int a]) {} //# 02: compile-time error
+void f06(int a) {}
+
+// Nullable types
+void f07({int? a = 0}) {}
+void f08({int? a}) {}
+void f09({required int? a}) {}
+void f10([int? a = 0]) {}
+void f11([int? a]) {}
+void f12(int? a) {}
+
+class A {
+  final f;
+  A(void this.f({String s})) {}
+}
+typedef void f13({String});
+void printToLog(void f({String})) {}
+void Function({String s}) f14;
+
+class B<T extends Object?> {
+  // Potentially non-nullable types
+  void f15({T a = null}) {} //# 03: compile-time error
+  void f16({T a}) {} //# 04: compile-time error
+  void f17({required T a}) {}
+  void f18([T a = null]) {} //# 05: compile-time error
+  void f19([T a]) {} //# 06: compile-time error
+  void f20(T a) {}
+
+  // Nullable types
+  void f21({T? a = null}) {}
+  void f22({T? a}) {}
+  void f23({required T? a}) {}
+  void f24([T? a = null]) {}
+  void f25([T? a]) {}
+  void f26(T? a) {}
+}
+
+class C<T extends Object> {
+  // Non-nullable types
+  void f27({T a = null}) {} //# 07: compile-time error
+  void f28({T a}) {} //# 08: compile-time error
+  void f29({required T a}) {}
+  void f30([T a = null]) {} //# 09: compile-time error
+  void f31([T a]) {} //# 10: compile-time error
+  void f32(T a) {}
+
+  // Nullable types
+  void f33({T? a = null}) {}
+  void f34({T? a}) {}
+  void f35({required T? a}) {}
+  void f36([T? a = null]) {}
+  void f37([T? a]) {}
+  void f38(T? a) {}
+}
diff --git a/tests/language_2/nnbd/static_errors/missing_required_argument_test.dart b/tests/language_2/nnbd/static_errors/missing_required_argument_test.dart
new file mode 100644
index 0000000..630c53d
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/missing_required_argument_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is an error if a named parameter that is part of a required
+// group is not bound to an argument at a call site.
+typedef String F({required String x});
+
+class A {
+  A({required int a}) {}
+  A.named() : this(); //# 01: compile-time error
+  void m1({required int a}) {}
+  F m2() => ({required String x}) => '';
+}
+
+class B extends A { B() : super(); } //# 02: compile-time error
+
+void f({required int a}) {}
+
+void Function({required int a}) g() => throw '';
+
+main() {
+  A a = new A(); //# 03: compile-time error
+  A a = A(); //# 04: compile-time error
+  f(); //# 05: compile-time error
+  g()(); //# 06: compile-time error
+  new A(a: 0).m1(); //# 07: compile-time error
+  new A(a: 0).m2()(); //# 08: compile-time error
+}
diff --git a/tests/language_2/nnbd/static_errors/nullable_function_types_test.dart b/tests/language_2/nnbd/static_errors/nullable_function_types_test.dart
new file mode 100644
index 0000000..714ecb8
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/nullable_function_types_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+class C {
+  call() {}
+}
+
+// Test calling various nullable functions produces errors.
+void main() {
+  Function()? nf1;
+  Function? nf2;
+  C c1 = new C();
+  C? nc1;
+  var nf3 = c1?.call;
+  Object? object;
+
+
+  nf1(); //# 00: compile-time error
+  nf2(); //# 01: compile-time error
+  nf3(); //# 02: compile-time error
+  c1(); //# 03: ok
+  nc1(); //# 04: compile-time error
+  object(); //# 05: compile-time error
+}
diff --git a/tests/language_2/nnbd/static_errors/nullable_in_on_clause_test.dart b/tests/language_2/nnbd/static_errors/nullable_in_on_clause_test.dart
new file mode 100644
index 0000000..ac7db83
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/nullable_in_on_clause_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is an error if the type `T` in the on-catch clause `on T catch`
+// is potentially nullable.
+import 'package:expect/expect.dart';
+import 'dart:core';
+import 'dart:core' as core;
+
+main() {
+  try {} catch (e) {}
+  try {} on A catch (e) {}
+  try {} on A? {} //# 01: compile-time error
+}
+
+class A {}
+
+class B<C> {
+  m() {
+    try {} on C {} //# 02: compile-time error
+  }
+}
+
+class D<E extends Object> {
+  m() {
+    try {} on E {}
+  }
+}
\ No newline at end of file
diff --git a/tests/language_2/nnbd/static_errors/opted_out_library.dart b/tests/language_2/nnbd/static_errors/opted_out_library.dart
new file mode 100644
index 0000000..fefacf5
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/opted_out_library.dart
@@ -0,0 +1,3 @@
+// @dart=2.3
+
+void consumeListOfStringStar(List<String> l) {}
diff --git a/tests/language_2/nnbd/static_errors/subtype_of_never_test.dart b/tests/language_2/nnbd/static_errors/subtype_of_never_test.dart
new file mode 100644
index 0000000..a19197c
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/subtype_of_never_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is an error for a class to extend, implement, or mixin the type
+// Never.
+class A extends Never {} //# 01: compile-time error
+
+class A implements Never {} //# 02: compile-time error
+
+class A with Never {} //# 03: compile-time error
+
+mixin M on Never {} //# 04: compile-time error
+
+main() {}
diff --git a/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart b/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart
new file mode 100644
index 0000000..a73735c
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart
@@ -0,0 +1,206 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is an error to use nullable types in unsound ways.
+void main() async {
+  int? x;
+  bool? cond;
+  List? list;
+  Function? func;
+  List<Function?> funcList;
+  Stream? stream;
+  x.isEven; //# 00: compile-time error
+  x.round(); //# 01: compile-time error
+  x.toString(); //# 02: ok
+  x.hashCode; //# 03: ok
+  x.runtimeType; //# 04: ok
+  x.noSuchMethod(Invocation.method(#toString, [])); //# 05: ok
+  x + 1; //# 06: compile-time error
+  -x; //# 06: compile-time error
+  x++; //# 07: compile-time error
+  ++x; //# 08: compile-time error
+  x..isEven; //# 09: compile-time error
+  list[0]; //# 10: compile-time error
+  list[0] = 0; //# 10: compile-time error
+  x += 1; //# 11: compile-time error
+  x ??= 1; //# 12: ok
+  x.round; //# 13: compile-time error
+  x.toString; //# 14: ok
+  x.noSuchMethod; //# 15: ok
+  func(); //# 16: compile-time error
+  funcList[0](); //# 17: compile-time error
+  funcList.single(); //# 18: compile-time error
+  throw x; //# 19: compile-time error
+  cond || true; //# 20: compile-time error
+  true || cond; //# 21: compile-time error
+  cond && true; //# 22: compile-time error
+  true && cond; //# 23: compile-time error
+  !cond; //# 24: compile-time error
+  cond ? null : null; //# 25: compile-time error
+  if (cond) {} //# 26: compile-time error
+  while (cond) {} //# 27: compile-time error
+  for (;cond;) {} //# 28: compile-time error
+  do {} while (cond); //# 29: compile-time error
+  cond!; //# 30: ok
+  cond ?? null; //# 31: ok
+  cond == null; //# 32: ok
+  cond != null; //# 33: ok
+  x?.isEven; //# 34: ok
+  x?.round(); //# 35: ok
+  for(var i in list) {}; //# 36: compile-time error
+  await for(var i in stream) {}; //# 37: compile-time error
+  assert(cond); //# 38: compile-time error
+}
+
+generator() sync* {
+  Iterable? iter;
+  yield* iter; //# 39: compile-time error
+}
+
+void typeParametersNullableBounds<IQ extends int?, BQ extends bool?, LQ extends List?, FQ extends Function?, SQ extends Stream?>(
+    IQ x,
+    BQ cond,
+    LQ list,
+    FQ func,
+    List<FQ> funcList,
+    SQ stream,
+    ) async {
+  x.isEven; //# 40: compile-time error
+  x.round(); //# 41: compile-time error
+  x.toString(); //# 42: ok
+  x.hashCode; //# 43: ok
+  x.runtimeType; //# 44: ok
+  x.noSuchMethod(Invocation.method(#toString, [])); //# 45: ok
+  x + 1; //# 46: compile-time error
+  -x; //# 47: compile-time error
+  x++; //# 48: compile-time error
+  ++x; //# 49: compile-time error
+  x..isEven; //# 50: compile-time error
+  list[0]; //# 51: compile-time error
+  list[0] = 0; //# 52: compile-time error
+  x += 1; //# 53: compile-time error
+  x ??= x; //# 54: ok
+  x.round; //# 55: compile-time error
+  x.toString; //# 56: ok
+  x.noSuchMethod; //# 57: ok
+  func(); //# 58: compile-time error
+  funcList[0](); //# 59: compile-time error
+  funcList.single(); //# 60: compile-time error
+  throw x; //# 61: compile-time error
+  cond || true; //# 62: compile-time error
+  true || cond; //# 63: compile-time error
+  cond && true; //# 64: compile-time error
+  true && cond; //# 65: compile-time error
+  !cond; //# 66: compile-time error
+  cond ? null : null; //# 67: compile-time error
+  if (cond) {} //# 68: compile-time error
+  while (cond) {} //# 69: compile-time error
+  for (;cond;){} //# 70: compile-time error
+  do {} while (cond); //# 71: compile-time error
+  cond!; //# 72: ok
+  cond ?? null; //# 73: ok
+  cond == null; //# 74: ok
+  cond != null; //# 75: ok
+  x?.isEven; //# 76: ok
+  x?.round(); //# 77: ok
+  for(var i in list) {}; //# 78: compile-time error
+  await for(var i in stream) {}; //# 79: compile-time error
+  assert(cond); //# 39: compile-time error
+}
+
+void typeParametersNullableUses<I extends int, B extends bool, L extends List, F extends Function, S extends Stream>(
+    I? x,
+    B? cond,
+    L? list,
+    F? func,
+    List<F?> funcList,
+    S? stream,
+    ) async {
+  x.isEven; //# 80: compile-time error
+  x.round(); //# 81: compile-time error
+  x.toString(); //# 82: ok
+  x.hashCode; //# 83: ok
+  x.runtimeType; //# 84: ok
+  x.noSuchMethod(Invocation.method(#toString, [])); //# 85: ok
+  x + 1; //# 86: compile-time error
+  -x; //# 87: compile-time error
+  x++; //# 88: compile-time error
+  ++x; //# 89: compile-time error
+  x..isEven; //# 90: compile-time error
+  list[0]; //# 91: compile-time error
+  list[0] = 0; //# 92: compile-time error
+  x += 1; //# 93: compile-time error
+  x ??= null; //# 94: ok
+  x.round; //# 95: compile-time error
+  x.toString; //# 96: ok
+  x.noSuchMethod; //# 97: ok
+  func(); //# 98: compile-time error
+  funcList[0](); //# 99: compile-time error
+  funcList.single(); //# 100: compile-time error
+  throw x; //# 101: compile-time error
+  cond || true; //# 102: compile-time error
+  true || cond; //# 103: compile-time error
+  cond && true; //# 104: compile-time error
+  true && cond; //# 105: compile-time error
+  !cond; //# 106: compile-time error
+  cond ? null : null; //# 107: compile-time error
+  if (cond) {} //# 108: compile-time error
+  while (cond) {} //# 109: compile-time error
+  for (;cond;) {} //# 110: compile-time error
+  do {} while (cond); //# 111: compile-time error
+  cond!; //# 112: ok
+  cond ?? null; //# 113: ok
+  cond == null; //# 114: ok
+  cond != null; //# 115: ok
+  x?.isEven; //# 116: ok
+  x?.round(); //# 117: ok
+  for(var i in list) {}; //# 118: compile-time error
+  await for(var i in stream) {}; //# 119: compile-time error
+}
+
+void dynamicUses() async {
+  dynamic dyn;
+  dyn.isEven; //# 120: ok
+  dyn.round(); //# 121: ok
+  dyn.toString(); //# 122: ok
+  dyn.hashCode; //# 123: ok
+  dyn.runtimeType; //# 124: ok
+  dyn.noSuchMethod(null); //# 125: ok
+  dyn + 1; //# 126: ok
+  -dyn; //# 127: ok
+  dyn++; //# 128: ok
+  ++dyn; //# 129: ok
+  dyn..isEven; //# 130: ok
+  dyn[0]; //# 131: ok
+  dyn[0] = 0; //# 132: ok
+  dyn += 1; //# 133: ok
+  dyn ??= null; //# 134: ok
+  dyn.round; //# 135: ok
+  dyn.toString; //# 136: ok
+  dyn.noSuchMethod; //# 137: ok
+  dyn(); //# 138: ok
+  dyn[0](); //# 139: ok
+  dyn.single(); //# 140: ok
+  throw dyn; //# 141: ok
+  dyn || true; //# 142: ok
+  true || dyn; //# 143: ok
+  dyn && true; //# 144: ok
+  true && dyn; //# 145: ok
+  !dyn; //# 146: ok
+  dyn ? null : null; //# 147: ok
+  if (dyn) {} //# 148: ok
+  while (dyn) {} //# 149: ok
+  for (;dyn;) {} //# 150: ok
+  do {} while (dyn); //# 151: ok
+  dyn!; //# 152: ok
+  dyn ?? null; //# 153: ok
+  dyn == null; //# 154: ok
+  dyn != null; //# 155: ok
+  dyn?.isEven; //# 156: ok
+  dyn?.round(); //# 157: ok
+  for(var i in dyn) {}; //# 158: ok
+  await for(var i in dyn) {}; //# 159: ok
+}
diff --git a/tests/language_2/nnbd/syntax/late_modifier_error_test.dart b/tests/language_2/nnbd/syntax/late_modifier_error_test.dart
new file mode 100644
index 0000000..5fd1289
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/late_modifier_error_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Invalid uses of "late" modifier
+
+late //# 01: compile-time error
+int f1(
+  late //# 02: compile-time error
+  int x
+) {}
+
+late //# 03: compile-time error
+class C1 {
+  late //# 04: compile-time error
+  int m() {}
+}
+
+main() {
+}
diff --git a/tests/language_2/nnbd/syntax/late_modifier_test.dart b/tests/language_2/nnbd/syntax/late_modifier_test.dart
new file mode 100644
index 0000000..bcd4385
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/late_modifier_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+import 'package:expect/expect.dart';
+
+late final int d = d_init();
+int d_init() => 5;
+
+class C {
+  static late final int e = e_init();
+  static int e_init() => 6;
+
+  late final int f;
+  C() { f = 7; }
+
+  int get g {
+    late final int x;
+    x = 8;
+    return x;
+  }
+}
+
+main() {
+  Expect.equals(d, 5);
+  Expect.equals(C.e, 6);
+  Expect.equals(C().f, 7);
+  Expect.equals(C().g, 8);
+}
diff --git a/tests/language_2/nnbd/syntax/null_assertion_ambiguous_test.dart b/tests/language_2/nnbd/syntax/null_assertion_ambiguous_test.dart
index b2955e9..29200e7 100644
--- a/tests/language_2/nnbd/syntax/null_assertion_ambiguous_test.dart
+++ b/tests/language_2/nnbd/syntax/null_assertion_ambiguous_test.dart
@@ -18,11 +18,11 @@
   // `throw a!` means `throw (a!)`, not `(throw a)!`.  Since it's a compile-time
   // error for a thrown expression to be potentially nullable, this is
   // sufficient to verify that the compiler has resolved the ambiguity
-  // correctly.  Unforunately there's no good way to test the runtime behavior
-  // because `throw a` wouldn't complete anyway.
+  // correctly.  We check the runtime behavior by verifying that the error that
+  // is thrown is not `NullThrownError`.
   Expect.throws(() {
       throw a!;
-  });
+    }, (error) => error is! NullThrownError);
 
   // `() => a!` means `() => (a!)`, not `(() => a)!`.  We check the compile-time
   // behavior by trying to assign to a function returning non-null.  We check
@@ -64,6 +64,7 @@
   int? i = 2;
   x6 * i!;
   var x7 = new C();
+  i = null;
   Expect.throws(() {
       x7 * i!;
   });
diff --git a/tests/language_2/nnbd/syntax/nullable_type_ambiguous_test.dart b/tests/language_2/nnbd/syntax/nullable_type_ambiguous_test.dart
index e6f6ad6..3e5a718 100644
--- a/tests/language_2/nnbd/syntax/nullable_type_ambiguous_test.dart
+++ b/tests/language_2/nnbd/syntax/nullable_type_ambiguous_test.dart
@@ -13,18 +13,30 @@
   // { a as bool ? - 3 : 3 } is parsed as a set literal { (a as bool) ? - 3 : 3 }.
   dynamic a = true;
   var x1 = {a as bool ? -3 : 3};
-  Expect.isTrue(x1 is Set<dynamic>);
+  Expect.type<Set<dynamic>>(x1);
   Set<dynamic> y1 = x1;
 
   // { a is int ? -3 : 3 } is parsed as a set literal { (a is int) ? -3 : 3 }.
   a = 0;
   var x2 = {a is int ? -3 : 3};
-  Expect.isTrue(x2 is Set<dynamic>);
+  Expect.type<Set<dynamic>>(x2);
   Set<dynamic> y2 = x2;
 
   // { a * int ? -3 : 3 } is parsed as a set literal { (a * int) ? -3 : 3 }.
   a = C();
   var x3 = {a * int ? -3 : 3};
-  Expect.isTrue(x3 is Set<dynamic>);
+  Expect.type<Set<dynamic>>(x3);
   Set<dynamic> y3 = x3;
+
+  // { a is bool ? ? - 3 : 3 } is parsed as a set literal { (a is bool?) ? - 3 : 3 }.
+  a = true;
+  var x4 = {a is bool ? ? -3 : 3};
+  Expect.type<Set<dynamic>>(x4);
+  Set<dynamic> y4 = x4;
+
+  // { a is bool ?? true : 3 } is parsed as a map literal { ((a is bool) ?? true) : 3 }.
+  a = true;
+  var x5 = {a is bool ?? true : 3};
+  Expect.type<Map<dynamic, dynamic>>(x5);
+  Map<dynamic, dynamic> y5 = x5;
 }
diff --git a/tests/language_2/nnbd/syntax/opt_out_nnbd_modifiers_test.dart b/tests/language_2/nnbd/syntax/opt_out_nnbd_modifiers_test.dart
new file mode 100644
index 0000000..59d55da
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/opt_out_nnbd_modifiers_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+// @dart = 2.2
+import 'package:expect/expect.dart';
+
+class late {
+  int get g => 1;
+}
+
+class required {
+  int get g => 2;
+}
+
+class C {
+  late l = late();
+  required r = required();
+}
+
+main() {
+  Expect.equals(C().l.g, 1);
+  Expect.equals(C().r.g, 2);
+}
diff --git a/tests/language_2/nnbd/syntax/pre_nnbd_modifiers_test.dart b/tests/language_2/nnbd/syntax/pre_nnbd_modifiers_test.dart
new file mode 100644
index 0000000..a8ae465
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/pre_nnbd_modifiers_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test ensures that the modifiers added as part of NNBD are not enabled
+// until NNBD is enabled by default. At that time, this test should be removed.
+
+import 'package:expect/expect.dart';
+
+class late {
+  int get g => 1;
+}
+
+class required {
+  int get g => 2;
+}
+
+class C {
+  late l = late();
+  required r = required();
+}
+
+main() {
+  Expect.equals(C().l.g, 1);
+  Expect.equals(C().r.g, 2);
+}
diff --git a/tests/language_2/nnbd/syntax/required_modifier_error_test.dart b/tests/language_2/nnbd/syntax/required_modifier_error_test.dart
new file mode 100644
index 0000000..b8265e3
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/required_modifier_error_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Invalid uses of "required" modifier
+
+required //# 01: compile-time error
+int f1(
+  required //# 02: compile-time error
+  int x
+) {}
+
+required //# 03: compile-time error
+class C1 {
+  required //# 04: compile-time error
+  int f2;
+}
+
+// Duplicate modifier
+void f2({
+  required
+  required //# 05: compile-time error
+  int i,
+}){
+}
+
+// Out of order modifiers
+class C2 {
+  void m({
+    covariant
+    required //# 07: compile-time error
+    int i2,
+    final
+    required //# 08: compile-time error
+    int i3,
+  }) {
+  }
+}
+
+main() {
+}
diff --git a/tests/language_2/nnbd/syntax/required_modifier_test.dart b/tests/language_2/nnbd/syntax/required_modifier_test.dart
new file mode 100644
index 0000000..423f22e
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/required_modifier_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+import 'package:expect/expect.dart';
+
+int f({required int i}) => i + 1;
+
+class C {
+  m(int a, {required int i}) => a + i;
+}
+
+main() {
+  Expect.equals(f(i: 2), 3);
+  Expect.equals(C().m(4, i: 5), 9);
+}
diff --git a/tests/language_2/regress_28268_test.dart b/tests/language_2/regress_28268_test.dart
new file mode 100644
index 0000000..a2a0bd5
--- /dev/null
+++ b/tests/language_2/regress_28268_test.dart
@@ -0,0 +1,159 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+class E {
+  static final String a = "get a";
+  static void set a(String o) {
+    printx("set a: $o");
+  }
+
+  static const String b = "get b";
+  static void set b(String o) {
+    printx("set b: $o");
+  }
+
+  static void set c(String o) {
+    printx("set c: $o");
+  }
+
+  final String d = "get d";
+  void set d(String o) {
+    printx("set d: $o");
+  }
+
+  final String e = "get e";
+
+  static const String f = "get f";
+
+  set g(v) {
+    printx("set g: $v");
+  }
+
+  set h(v) {
+    printx("set h: $v");
+  }
+
+  foo() {
+    printx(e);
+    e = "set e"; // //# 01: compile-time error
+    printx(e);
+
+    printx(f);
+    f = "set f"; // //# 02: compile-time error
+    printx(f);
+
+    printx(g); //   //# 03: compile-time error
+    g = "set g";
+    printx(g); //   //# 04: compile-time error
+
+    printx(h); //   //# 05: compile-time error
+    h = "set h";
+    printx(h); //   //# 06: compile-time error
+  }
+}
+
+set e(v) {
+  printx("Setting top-level e: $v");
+}
+
+set f(v) {
+  printx("Setting top-level f: $v");
+}
+
+final String g = "get g";
+
+const String h = "get h";
+
+const x = 42;
+final y = 42;
+
+set x(v) {
+  printx("Setting top-level x: $v");
+}
+
+set y(v) {
+  printx("Setting top-level y: $v");
+}
+
+main() {
+  printx(E.a);
+  E.a = "set E";
+  printx(E.a);
+
+  printx(E.b);
+  E.b = "set E";
+  printx(E.b);
+
+  E.c = "set E";
+
+  E eInstance = new E();
+  printx(eInstance.d);
+  eInstance.d = "set eInstance";
+  printx(eInstance.d);
+  eInstance.foo();
+
+  printx(e); //     //# 07: compile-time error
+  e = "set e";
+  printx(e); //     //# 08: compile-time error
+
+  printx(f); //     //# 09: compile-time error
+  f = "set f";
+  printx(f); //     //# 10: compile-time error
+
+  printx(g);
+  g = "set g"; //   //# 11: compile-time error
+  printx(g);
+
+  printx(h);
+  h = "set h"; //   //# 12: compile-time error
+  printx(h);
+
+  printx(x);
+  x = "Hello world!";
+  printx(x);
+
+  printx(y);
+  y = "Hello world!";
+  printx(y);
+
+  Expect.listEquals(expected, actual);
+}
+
+List<String> actual = <String>[];
+void printx(Object x) {
+  actual.add(x.toString());
+}
+
+List<String> expected = <String>[
+  "get a",
+  "set a: set E",
+  "get a",
+  "get b",
+  "set b: set E",
+  "get b",
+  "set c: set E",
+  "get d",
+  "set d: set eInstance",
+  "get d",
+  "get e",
+  "get e",
+  "get f",
+  "get f",
+  "set g: set g",
+  "set h: set h",
+  "Setting top-level e: set e",
+  "Setting top-level f: set f",
+  "get g",
+  "get g",
+  "get h",
+  "get h",
+  "42",
+  "Setting top-level x: Hello world!",
+  "42",
+  "42",
+  "Setting top-level y: Hello world!",
+  "42",
+];
diff --git a/tests/language_2/spread_collections/await_test.dart b/tests/language_2/spread_collections/await_test.dart
index 886a94a..866e1c4 100644
--- a/tests/language_2/spread_collections/await_test.dart
+++ b/tests/language_2/spread_collections/await_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=spread-collections
-
 import "package:async_helper/async_helper.dart";
 import 'package:expect/expect.dart';
 
diff --git a/tests/language_2/spread_collections/const_error_test.dart b/tests/language_2/spread_collections/const_error_test.dart
index c186f13..348c4c8 100644
--- a/tests/language_2/spread_collections/const_error_test.dart
+++ b/tests/language_2/spread_collections/const_error_test.dart
@@ -2,24 +2,66 @@
 // 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.
 
-// SharedOptions=--enable-experiment=spread-collections
+// SharedOptions=--enable-experiment=constant-update-2018
 
-import 'package:expect/expect.dart';
+import 'dart:collection';
 
-const constList = [1, 2, 3, 4];
-const constSet = {1, 2, 3, 4};
-const constMap = {1: 1, 2: 2, 3: 3, 4: 4};
+import 'helper_classes.dart';
+
+var nonConstList = <int>[];
+var nonConstMap = <int, String>{};
+const dynamic nonIterable = 3;
+const dynamic nonMap = 3;
 
 void main() {
-  var list = [1, 2, 3];
-  var set = {1, 2, 3};
-  var map = {1:1, 2:2, 3:3};
+  testList();
+  testMap();
+  testSet();
+}
 
-  // Spread cannot be used in a const collection.
-  const _ = [...list]; //# 00: compile-time error
-  const _ = [...constList]; //# 01: compile-time error
-  const _ = {...set}; //# 02: compile-time error
-  const _ = {...constSet}; //# 03: compile-time error
-  const _ = {...map}; //# 04: compile-time error
-  const _ = {...constMap}; //# 05: compile-time error
+void testList() {
+  // Must be constant.
+  const _ = <int>[...nonConstList]; //# 01: compile-time error
+
+  // Must be iterable.
+  const _ = <int>[...nonIterable]; //# 02: compile-time error
+
+  // Cannot be custom iterable type.
+  const _ = <int>[...ConstIterable()]; //# 03: compile-time error
+}
+
+void testMap() {
+  // Must be constant.
+  const _ = <int, String>{...nonConstMap}; //# 04: compile-time error
+
+  // Must be map.
+  const _ = <int, String>{...nonMap}; //# 05: compile-time error
+
+  // Cannot be custom map type.
+  const _ = <int, String>{...ConstMap()}; //# 06: compile-time error
+
+  // Cannot have key collision.
+  const _ = <int, String>{1: "s", ...{1: "t"}}; //# 07: compile-time error
+  const _ = <int, String>{...{1: "s"}, ...{1: "t"}}; //# 08: compile-time error
+}
+
+void testSet() {
+  // Must be constant.
+  const _ = <int>{...nonConstList}; //# 09: compile-time error
+
+  // Must be iterable.
+  const _ = <int>{...nonIterable}; //# 10: compile-time error
+
+  // Cannot be custom iterable type.
+  const _ = <int>{...ConstIterable()}; //# 11: compile-time error
+
+  // Cannot override operator.==().
+  const obj = 0.1;
+  const _ = {...[0.1]}; //# 12: compile-time error
+  const _ = {...[Duration(seconds: 0)]}; //# 13: compile-time error
+  const _ = {...[obj]}; //# 14: compile-time error
+
+  // Cannot have collision.
+  const _ = {1, ...[1]}; //# 15: compile-time error
+  const _ = {...[1], ...[1]}; //# 16: compile-time error
 }
diff --git a/tests/language_2/spread_collections/const_syntax_error_test.dart b/tests/language_2/spread_collections/const_syntax_error_test.dart
new file mode 100644
index 0000000..6684548
--- /dev/null
+++ b/tests/language_2/spread_collections/const_syntax_error_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2019, 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 'spread' in const collections is not enabled without the
+// experimental constant-update-2018 flag.
+
+// SharedOptions=--enable-experiment=no-constant-update-2018
+
+const constList = [1, 2, 3, 4];
+const constSet = {1, 2, 3, 4};
+const constMap = {1: 1, 2: 2, 3: 3, 4: 4};
+
+void main() {
+  var list = [1, 2, 3];
+  var set = {1, 2, 3};
+  var map = {1:1, 2:2, 3:3};
+
+  // Spread cannot be used in a const collection.
+  const _ = [...list]; //# 00: compile-time error
+  const _ = [...constList]; //# 01: compile-time error
+  const _ = {...set}; //# 02: compile-time error
+  const _ = {...constSet}; //# 03: compile-time error
+  const _ = {...map}; //# 04: compile-time error
+  const _ = {...constMap}; //# 05: compile-time error
+}
diff --git a/tests/language_2/spread_collections/const_test.dart b/tests/language_2/spread_collections/const_test.dart
new file mode 100644
index 0000000..9f09c54
--- /dev/null
+++ b/tests/language_2/spread_collections/const_test.dart
@@ -0,0 +1,182 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=constant-update-2018
+
+import 'package:expect/expect.dart';
+
+// Typed as dynamic to also test spreading a value of type dynamic.
+const dynamic list = [1, 2, 3, 4];
+const dynamic map = {1: 1, 2: 2, 3: 3, 4: 4};
+const dynamic set = {1, 2, 3, 4};
+
+void main() {
+  testList();
+  testMap();
+  testSet();
+  testKeyOrder();
+}
+
+void testList() {
+  // Only spread.
+  Expect.identical(list, const <int>[...list]);
+  Expect.identical(list, const <int>[...set]);
+
+  // Spread at beginning.
+  Expect.identical(list, const <int>[...<int>[1, 2], 3, 4]);
+
+  // Spread in middle.
+  Expect.identical(list, const <int>[1, ...<int>[2, 3], 4]);
+
+  // Spread at end.
+  Expect.identical(list, const <int>[1, 2, ...<int>[3, 4]]);
+
+  // Empty spreads.
+  Expect.identical(list,
+      const <int>[...<int>[], 1, 2, ...<int>[], 3, 4, ...<int>[]]);
+
+  // Multiple spreads.
+  Expect.identical(list,
+      const <int>[...<int>[1], 2, ...<int>[3, 4]]);
+
+  // Nested spreads.
+  Expect.identical(list,
+      const <int>[...<int>[...<int>[1, 2], ...<int>[3, 4]]]);
+
+  // Null-aware.
+  Expect.identical(list,
+      const <int>[1, ...?<int>[2, 3], ...?(null), ...?<int>[4]]);
+
+  // Does not deep flatten.
+  Expect.identical(
+      const <Object>[1, 2, <int>[3], 4],
+      const <Object>[1, ...<Object>[2, <int>[3], 4]]);
+
+  // Establishes const context.
+  Expect.identical(const <Symbol>[Symbol("sym")],
+      const <Symbol>[...<Symbol>[Symbol("sym")]]);
+}
+
+void testMap() {
+  // Only spread.
+  Expect.identical(map, const <int, int>{...map});
+
+  // Spread at beginning.
+  Expect.identical(map,
+      const <int, int>{...<int, int>{1: 1, 2: 2}, 3: 3, 4: 4});
+
+  // Spread in middle.
+  Expect.identical(map,
+      const <int, int>{1: 1, ...<int, int>{2: 2, 3: 3}, 4: 4});
+
+  // Spread at end.
+  Expect.identical(map,
+      const <int, int>{1: 1, 2: 2, ...<int, int>{3: 3, 4: 4}});
+
+  // Empty spreads.
+  Expect.identical(map, const <int, int>{
+    ...<int, int>{},
+    1: 1,
+    2: 2,
+    ...<int, int>{},
+    3: 3,
+    4: 4,
+    ...<int, int>{}
+  });
+
+  // Multiple spreads.
+  Expect.identical(map,
+      const <int, int>{...<int, int>{1: 1}, 2: 2, ...<int, int>{3: 3, 4: 4}});
+
+  // Nested spreads.
+  Expect.identical(map, const <int, int>{
+    ...<int, int>{
+      ...<int, int>{1: 1, 2: 2},
+      ...<int, int>{3: 3, 4: 4}
+    }
+  });
+
+  // Null-aware.
+  Expect.identical(map, const <int, int>{
+    1: 1,
+    ...?<int, int>{2: 2, 3: 3},
+    ...?(null),
+    ...?<int, int>{4: 4}
+  });
+
+  // Does not deep flatten.
+  Expect.identical(const <int, Object>{
+    1: 1,
+    2: 2,
+    3: <int, int>{3: 3},
+    4: 4
+  }, const <int, Object>{
+    1: 1,
+    ...<int, Object>{
+      2: 2,
+      3: <int, int>{3: 3},
+      4: 4
+    }
+  });
+
+  // Establishes const context.
+  Expect.identical(const <Symbol, Symbol>{
+    Symbol("sym"): Symbol("bol")
+  }, const <Symbol, Symbol>{
+    ...<Symbol, Symbol>{Symbol("sym"): Symbol("bol")}
+  });
+}
+
+void testSet() {
+  // Only spread.
+  Expect.identical(set, const <int>{...set});
+  Expect.identical(set, const <int>{...list});
+
+  // Spread at beginning.
+  Expect.identical(set, const <int>{...<int>[1, 2], 3, 4});
+
+  // Spread in middle.
+  Expect.identical(set, const <int>{1, ...<int>[2, 3], 4});
+
+  // Spread at end.
+  Expect.identical(set, const <int>{1, 2, ...<int>[3, 4]});
+
+  // Empty spreads.
+  Expect.identical(set,
+      const <int>{...<int>[], 1, 2, ...<int>[], 3, 4, ...<int>[]});
+
+  // Multiple spreads.
+  Expect.identical(set, const <int>{...<int>[1], 2, ...<int>[3, 4]});
+
+  // Nested spreads.
+  Expect.identical(set, const <int>{...<int>{...<int>[1, 2], ...<int>[3, 4]}});
+
+  // Null-aware.
+  Expect.identical(set,
+      const <int>{1, ...?<int>[2, 3], ...?(null), ...?<int>[4]});
+
+  // Does not deep flatten.
+  Expect.identical(const <Object>{1, 2, <int>{3}, 4},
+      const <Object>{1, ...<Object>{2, <int>{3}, 4}});
+
+  // Establishes const context.
+  Expect.identical(const <Symbol>{Symbol("sym")},
+      const <Symbol>{...<Symbol>{Symbol("sym")}});
+}
+
+void testKeyOrder() {
+  // Canonicalization isn't affected by which elements are spread.
+  Expect.identical(map,
+      const <int, int>{1: 1, ...<int, int>{2: 2, 3: 3}, 4: 4});
+  Expect.identical(map,
+      const <int, int>{1: 1, ...<int, int>{2: 2}, 3: 3, ...<int, int>{4: 4}});
+
+  Expect.identical(set, const <int>{1, ...<int>{2, 3}, 4});
+  Expect.identical(set, const <int>{1, ...<int>{2}, 3, ...<int>{4}});
+
+  // Ordering does affect canonicalization.
+  Expect.notIdentical(const <int, int>{1: 1, 2: 2, 3: 3},
+      const <int, int>{1: 1, ...<int, int>{3: 3, 2: 2}});
+  Expect.notIdentical(const <int>{1, 2, 3}, const <int>{1, ...<int>{3, 2}});
+}
diff --git a/tests/language_2/spread_collections/inference_test.dart b/tests/language_2/spread_collections/inference_test.dart
index e3c429f..c0dff36 100644
--- a/tests/language_2/spread_collections/inference_test.dart
+++ b/tests/language_2/spread_collections/inference_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=spread-collections
-
 // Test how spread interacts with inference.
 import 'package:expect/expect.dart';
 
diff --git a/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart b/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart
index 5f6576d..00f40a8 100644
--- a/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart
+++ b/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=spread-collections
-
 // Test cases where the syntax is ambiguous between maps and sets.
 import 'dart:collection';
 
diff --git a/tests/language_2/spread_collections/map_set_ambiguity_test.dart b/tests/language_2/spread_collections/map_set_ambiguity_test.dart
index 9b3d537..11345ea 100644
--- a/tests/language_2/spread_collections/map_set_ambiguity_test.dart
+++ b/tests/language_2/spread_collections/map_set_ambiguity_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=spread-collections
-
 // Test cases where the syntax is ambiguous between maps and sets.
 import 'dart:collection';
 
diff --git a/tests/language_2/spread_collections/runtime_error_test.dart b/tests/language_2/spread_collections/runtime_error_test.dart
index ad74289..d133b04 100644
--- a/tests/language_2/spread_collections/runtime_error_test.dart
+++ b/tests/language_2/spread_collections/runtime_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=spread-collections
-
 import 'package:expect/expect.dart';
 
 // Typed as dynamic to also test spreading a value of type dynamic.
diff --git a/tests/language_2/spread_collections/spread_test.dart b/tests/language_2/spread_collections/spread_test.dart
index 7bc721d..1be7185 100644
--- a/tests/language_2/spread_collections/spread_test.dart
+++ b/tests/language_2/spread_collections/spread_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=spread-collections
-
 import 'package:expect/expect.dart';
 
 import 'helper_classes.dart';
diff --git a/tests/language_2/spread_collections/syntax_error_test.dart b/tests/language_2/spread_collections/syntax_error_test.dart
index 05261cd..825e5dd2 100644
--- a/tests/language_2/spread_collections/syntax_error_test.dart
+++ b/tests/language_2/spread_collections/syntax_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=spread-collections
-
 void main() {
   // Spread nothing.
   var _ = [...]; //# 00: syntax error
diff --git a/tests/language_2/spread_collections/syntax_test.dart b/tests/language_2/spread_collections/syntax_test.dart
index 7100394..376db0d 100644
--- a/tests/language_2/spread_collections/syntax_test.dart
+++ b/tests/language_2/spread_collections/syntax_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=spread-collections
-
 // Tests syntax edge cases.
 import 'package:expect/expect.dart';
 
diff --git a/tests/language_2/spread_collections/type_error_test.dart b/tests/language_2/spread_collections/type_error_test.dart
index 68cf98c..05e9e5b 100644
--- a/tests/language_2/spread_collections/type_error_test.dart
+++ b/tests/language_2/spread_collections/type_error_test.dart
@@ -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.
 
-// SharedOptions=--enable-experiment=spread-collections
-
 void main() {
   // Spread non-iterable or non-map.
   var _ = [...(3)]; //# 00: compile-time error
diff --git a/tests/language_2/stacktrace_test.dart b/tests/language_2/stacktrace_test.dart
index 20ddcb0..ecbf6d38 100644
--- a/tests/language_2/stacktrace_test.dart
+++ b/tests/language_2/stacktrace_test.dart
@@ -12,6 +12,6 @@
     throw ex;
   } on Exception catch (e, st) {
     Expect.equals(ex, e);
-    Expect.isTrue(st.toString().endsWith("\n"));
+    Expect.isTrue(st.toString().length > 0);
   }
 }
diff --git a/tests/language_2/sync_generator2_test.dart b/tests/language_2/sync_generator2_test.dart
index 9e33f0c..feaee63 100644
--- a/tests/language_2/sync_generator2_test.dart
+++ b/tests/language_2/sync_generator2_test.dart
@@ -15,13 +15,10 @@
 test01() sync* {
   var yield = 0; // //# 01: syntax error
   var await = 0; // //# 02: syntax error
-  var async = 0; // //# 03: syntax error
   bool yield() => false; //# 04: syntax error
   bool await() => false; //# 05: syntax error
-  bool async() => false; //# 06: syntax error
 
   var x1 = sync;
-  var x2 = async; // //# 07: syntax error
   var x3 = await; // //# 08: syntax error
   var x4 = await 55; // //# 09: compile-time error
   var x4 = yield; // //# 10: syntax error
diff --git a/tests/language_2/unsigned_right_shift_test.dart b/tests/language_2/unsigned_right_shift_test.dart
index 64d46d0..bcedfd3 100644
--- a/tests/language_2/unsigned_right_shift_test.dart
+++ b/tests/language_2/unsigned_right_shift_test.dart
@@ -1,12 +1,197 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2019, 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.
 
-// The >>> operator is not supported in Dart
+// SharedOptions=--enable-experiment=triple-shift
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+// The >>> operator is (again) supported by Dart
+// (This test does not test int.operator>>>, such a test belongs in the corelib
+// test collection. Const uses of int.operator>>> is tested elsewhere as well).
+
+/// Syntactically tricky coincidences containing >>> and >>>=.
+/// DO NOT FORMAT THIS FILE. There should not be a space between >>> and =.
+typedef F3<T extends List<List<int>>>= T Function();
+typedef F4<T extends List<List<List<int>>>>= T Function();
+typedef F5<T extends List<List<List<List<int>>>>>= T Function();
+typedef F6<T extends List<List<List<List<List<int>>>>>>= T Function();
+class E3<T extends List<List<int>>> {}
+class E4<T extends List<List<List<int>>>> {}
+class E5<T extends List<List<List<List<int>>>>> {}
+class E6<T extends List<List<List<List<List<int>>>>>> {}
 
 main() {
-  var foo = -10
-    >>> 1 //# 01: syntax error
-      ;
-  foo >>>= 1; //# 02: syntax error
+  // >>> is an overridable operator.
+  const c1 = C(1);
+  const c2 = C(2);
+  Expect.identical(c2, c1 >>> c2);
+
+  /// It combines to an assignment operator.
+  C c = c1;
+  c >>>= c2;
+  Expect.identical(c2, c);
+
+  // Operand needs to have correct type for typed invocation.
+  c1 //
+     >>> 4 //# 01: compile-time error
+     >>> "string" //# 02: compile-time error
+  ;
+  c //
+     >>>= 4 //# 03: compile-time error
+  ;
+
+  // Dynamic invocations are allowed, and check types at run-time.
+  dynamic d = c1;
+  Expect.identical(c2, d >>> c2);
+  Expect.throws(() => d >>> 4);
+
+  // There is a symbol for >>>, both as constructed and literal.
+  Expect.identical(const Symbol(">>>"), #>>>);
+
+  // No such method can catch dynamic invocations of >>>:
+  dynamic nsm = NSM();
+  Invocation invocation = nsm >>> c2;
+  Expect.isTrue(invocation.isMethod);
+  Expect.isFalse(invocation.isAccessor);
+  Expect.equals(#>>>, invocation.memberName);
+  Expect.equals(1, invocation.positionalArguments.length);
+  Expect.identical(c2, invocation.positionalArguments[1]);
+  Expect.equals(0, invocation.namedArguments.length);
+
+  invocation = (nsm >>>= c2);
+  Expect.isTrue(invocation.isMethod);
+  Expect.isFalse(invocation.isAccessor);
+  Expect.equals(#>>>, invocation.memberName);
+  Expect.equals(1, invocation.positionalArguments.length);
+  Expect.identical(c2, invocation.positionalArguments[1]);
+  Expect.equals(0, invocation.namedArguments.length);
+
+  // And unimplemented interface methods.
+  ShiftNSM shnsm = ShiftNSM();
+  invocation = shnsm >>> c2;
+  Expect.isTrue(invocation.isMethod);
+  Expect.isFalse(invocation.isAccessor);
+  Expect.equals(#>>>, invocation.memberName);
+  Expect.equals(1, invocation.positionalArguments.length);
+  Expect.identical(c2, invocation.positionalArguments[1]);
+  Expect.equals(0, invocation.namedArguments.length);
+
+  // If there is an interface, we must match it, even if the call
+  // otherwise goes to noSuchMethod.
+  shnsm //
+      >>> 4 //# 04: compile-time error
+  ;
+
+  /// A type error in the nSM return value is caught.
+  dynamic badNSM = BadNSM();
+  Expect.throws(() => badNSM >>> "not an int", (e) => e != "Unreachable");
+  Expect.throws(() => badNSM >>> 4, (e) => e != "Unreachable");
+
+  asyncStart();
+  () async {
+    // Operands can be asynchronous.
+    var fc1 = Future.value(c1);
+    var fc2 = Future.value(c2);
+    Expect.identical(c2, (await fc1) >>> (await fc2));
+    /// The operator itself can be async.
+    var async = Async();
+    Expect.identical(c1, await (async >>> c2));
+    asyncEnd();
+  }();
+
+  // >>> has same precedence as >> (and <<), is left associative.
+  // Binds weaker than addition/multiplication, stronger than other bitwise
+  // operators and comparisons.
+  final a = Assoc("*");
+  Expect.equals("((~*)>>>(~*))", "${~a >>> ~a}");
+  Expect.equals("((*+*)>>>(*+*))", "${a + a >>> a + a}");
+  Expect.equals("((*/*)>>>(*/*))", "${a / a >>> a / a}");
+  Expect.equals("((*>>*)>>>*)>>*)", "${a >> a >>> a >> a}");
+  Expect.equals("((*&(*>>>*))&*)", "${a & a >>> a & a}");
+  Expect.equals("((*|(*>>>*)|)*)", "${a | a >>> a | a}");
+  Expect.equals("((*^(*>>>*)^)*)", "${a ^ a >>> a ^ a}");
+  Expect.equals("(*<(*>>>*))", "${a < a >>> a}");
+  Expect.equals("((*>>>*)<*)", "${a >>> a < a}");
+
+  var res = a;
+  res >>>= a;
+  res >>>= a;
+  Expect.equals("((*>>>*)>>>*)", "$res");
+
+  // Exercise the type declarations below.
+  E3<List<List<int>>>();
+  E4<List<List<List<int>>>>();
+  E5<List<List<List<List<int>>>>>();
+  E6<List<List<List<List<List<int>>>>>>();
+  Expect.type<F3<Null>>(() => null);
+  Expect.type<F4<Null>>(() => null);
+  Expect.type<F5<Null>>(() => null);
+  Expect.type<F6<Null>>(() => null);
+}
+
+/// Class with a simple overridden `operator>>>`.
+class C {
+  final int id;
+  const C(this. id);
+  C operator >>>(C other) => other;
+  String toString() => "C($id)";
+}
+
+/// Invalid declarations of `>>>` operator.
+class Invalid {
+  // Overridable operator must have exactly one required parameter.
+  Object operator>>>() => null;  //# arg0: compile-time error
+  Object operator>>>(v1, v2) => null;  //# arg2: compile-time error
+  Object operator>>>([v1]) => null;  //# argOpt: compile-time error
+  Object operator>>>({v1}) => null;  //# argNam: compile-time error
+  // The operator must not be async* or sync*.
+  Stream<Object> operator>>>(v) async* {}  //# asyncstar: compile-time error
+  Iterable<Object> operator>>>(v) sync* {}  //# syncstar: compile-time error
+}
+
+/// Class with noSuchMethod and no `>>>` operator.
+class NSM {
+  dynamic noSuchMethod(Invocation i) {
+    return invocation;
+  }
+}
+
+/// Class with nSM and abstract `>>>` (implicit typed forwarder).
+class ShiftNSM extends NSM {
+  dynamic operator>>>(C o);
+}
+
+/// Class with nSM and abstract `>>>` where nSM returns wrong type.
+class BadNSM {
+  int operator>>>(int n);
+  dynamic noSuchMethod(Invocation i) {
+    if (i.memberName == #>>>) {
+      if (i.positionalArguments.first is! int) throw "Unreachable";
+      return "notAnInt";
+    }
+    return super.noSuchMethod(i);
+  }
+}
+
+/// Class with an `async` implementation of `operator >>>`
+class Async {
+  Future<C> operator>>>(C other) async => other;
+}
+
+/// Helper class to record precedence and associativity of operators.
+class Assoc {
+  final String ops;
+  Assoc(this.ops);
+  Assoc operator~() => Assoc("(~${this}}");
+  Assoc operator+(Assoc other) => Assoc("(${this}+$other)");
+  Assoc operator/(Assoc other) => Assoc("(${this}/$other)");
+  Assoc operator&(Assoc other) => Assoc("(${this}&$other)");
+  Assoc operator|(Assoc other) => Assoc("(${this}|$other)");
+  Assoc operator^(Assoc other) => Assoc("(${this}^$other)");
+  Assoc operator>(Assoc other) => Assoc("(${this}>$other)");
+  Assoc operator>>(Assoc other) => Assoc("(${this}>>$other)");
+  Assoc operator>>>(Assoc other) => Assoc("(${this}>>>$other)");
+  String toString() => ops;
 }
diff --git a/tests/language_2/vm/causal_async_exception_stack2_test.dart b/tests/language_2/vm/causal_async_exception_stack2_test.dart
index a92ab7f..94dda4b 100644
--- a/tests/language_2/vm/causal_async_exception_stack2_test.dart
+++ b/tests/language_2/vm/causal_async_exception_stack2_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'causal_async_exception_stack_helper.dart' as h;
 
diff --git a/tests/language_2/vm/causal_async_exception_stack_test.dart b/tests/language_2/vm/causal_async_exception_stack_test.dart
index 3500fac..b4059e9 100644
--- a/tests/language_2/vm/causal_async_exception_stack_test.dart
+++ b/tests/language_2/vm/causal_async_exception_stack_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'causal_async_exception_stack_helper.dart' as h;
 
diff --git a/tests/language_2/vm/load_to_load_forwarding_cutdown_vm_test.dart b/tests/language_2/vm/load_to_load_forwarding_cutdown_vm_test.dart
new file mode 100644
index 0000000..ed81342
--- /dev/null
+++ b/tests/language_2/vm/load_to_load_forwarding_cutdown_vm_test.dart
@@ -0,0 +1,27 @@
+// 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.
+
+// Test correctness of side effects tracking used by load to load forwarding.
+// In this cutdown version of the load_to_load_forwarding_vm test, the function
+// being compiled ends up in a single basic block, which tests load
+// elimination when generating the initial sets.
+
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+import "package:expect/expect.dart";
+import "dart:typed_data";
+
+testViewAliasing1() {
+  final f64 = new Float64List(1);
+  final f32 = new Float32List.view(f64.buffer);
+  f64[0] = 1.0; // Should not be forwarded.
+  f32[1] = 2.0; // upper 32bits for 2.0f and 2.0 are the same
+  return f64[0];
+}
+
+main() {
+  for (var i = 0; i < 20; i++) {
+    Expect.equals(2.0, testViewAliasing1());
+  }
+}
diff --git a/tests/language_2/vm/osr_nonempty_stack_test.dart b/tests/language_2/vm/osr_nonempty_stack_test.dart
index 20af5d6..f003579 100644
--- a/tests/language_2/vm/osr_nonempty_stack_test.dart
+++ b/tests/language_2/vm/osr_nonempty_stack_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// SharedOptions=--enable-experiment=spread-collections,control-flow-collections,constant-update-2018
+// SharedOptions=--enable-experiment=constant-update-2018
 
 // Test with OSR on non-empty stack (block expression).
 
@@ -98,7 +98,7 @@
 }
 
 main() {
-  int n = 100000;
+  int n = 20000;
   int g = 457;
 
   var a = test1(n);
diff --git a/tests/language_2/vm/regress_36589_test.dart b/tests/language_2/vm/regress_36589_test.dart
new file mode 100644
index 0000000..dc64419
--- /dev/null
+++ b/tests/language_2/vm/regress_36589_test.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2019, 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.
+
+// Non-smi constant indices for load and store indexed (dartbug.com/36589).
+//
+// VMOptions=--deterministic --optimization_counter_threshold=5
+
+import "package:expect/expect.dart";
+
+const String NeverInline = 'NeverInline';
+
+List<int> mX = new List(1);
+
+@NeverInline
+int foo() {
+  return mX[8589934591];
+}
+
+@NeverInline
+foo_store() {
+  mX[8589934591] = 0;
+}
+
+@NeverInline
+int bar() {
+  List<int> x = new List(1);
+  return x[8589934591];
+}
+
+@NeverInline
+bar_store() {
+  List<int> x = new List(1);
+  x[8589934591] = 0;
+}
+
+main() {
+  int i = 0;
+  for (int j = 0; j < 10; j++) {
+    try {
+      i = foo();
+    } catch (e, s) {
+      i++;
+    }
+  }
+  Expect.equals(10, i);
+  for (int j = 0; j < 10; j++) {
+    try {
+      foo_store();
+    } catch (e, s) {
+      i++;
+    }
+  }
+  Expect.equals(20, i);
+  for (int j = 0; j < 10; j++) {
+    try {
+      i = bar();
+    } catch (e, s) {
+      i++;
+    }
+  }
+  Expect.equals(30, i);
+  for (int j = 0; j < 10; j++) {
+    try {
+      bar_store();
+    } catch (e, s) {
+      i++;
+    }
+  }
+  Expect.equals(40, i);
+}
diff --git a/tests/language_2/vm/regress_36681_test.dart b/tests/language_2/vm/regress_36681_test.dart
new file mode 100644
index 0000000..8dbe171
--- /dev/null
+++ b/tests/language_2/vm/regress_36681_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2019, 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.
+
+// Enforce proper S-overlapping register for temp (dartbug.com/36681).
+//
+// VMOptions=--deterministic --optimization_counter_threshold=5
+
+import "package:expect/expect.dart";
+
+const String NeverInline = 'NeverInline';
+
+double v = 0;
+
+@NeverInline
+int foo(int a, int p, int q) {
+  double p1 = 0;
+  double p2 = 0;
+  double p3 = 0;
+  double p4 = 0;
+  double p5 = 0;
+  double p6 = 0;
+  double p7 = 0;
+  double p8 = 0;
+  for (int z = 0; z < 8; z++) {
+    a += (p ~/ q);
+    a += (p % q);
+    p += 3;
+    q += 2;
+    p1 += 1;
+    p2 += 2;
+    p3 += 3;
+    p4 += 4;
+    p5 += 1;
+    p6 += 2;
+    p7 += 3;
+    p8 += 4;
+  }
+  v = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8;
+  return a;
+}
+
+main() {
+  for (int j = 0; j < 10; j++) {
+    int i = foo(1, 1, 1);
+    Expect.equals(37, i);
+    Expect.equals(160, v);
+  }
+}
diff --git a/tests/language_2/vm/regress_36778_test.dart b/tests/language_2/vm/regress_36778_test.dart
new file mode 100644
index 0000000..b3a95d5
--- /dev/null
+++ b/tests/language_2/vm/regress_36778_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2019, 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 for length overflow when eliminating write barriers for variable-length
+// objects.
+//
+// VMOptions=--deterministic --optimization_counter_threshold=5 --optimization_level=3
+
+import "package:expect/expect.dart";
+
+List foo(int a) {
+  if (a >= 100) {
+    return List.filled(2305843009213693951, 1);
+  }
+  return null;
+}
+
+main() {
+  for (int i = 0; i < 100; i++) {
+    List x = foo(i);
+    Expect.equals(null, x);
+  }
+}
diff --git a/tests/language_2/vm/regress_36803_test.dart b/tests/language_2/vm/regress_36803_test.dart
new file mode 100755
index 0000000..62ca189
--- /dev/null
+++ b/tests/language_2/vm/regress_36803_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2019, 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.
+
+// Don't LICM AOT's generic bounds check reference beyond other exception.
+// (dartbug.com/36803).
+//
+// VMOptions=--deterministic --optimization_level=3 --enable-inlining-annotations
+
+import "package:expect/expect.dart";
+
+const String NeverInline = 'NeverInline';
+
+String var1 = 'Hdi\u{1f600}T';
+
+@NeverInline
+int foo() {
+  List<int> a = [1, 2, 3, 4];
+  int x = 0;
+  do {
+    Uri.decodeQueryComponent(var1);
+    x = x + a[1000];
+  } while (x < 1);
+  return x;
+}
+
+main() {
+  int x = 0;
+  try {
+    x = foo();
+  } on RangeError catch (e) {
+    x = -2;
+  } on ArgumentError catch (e) {
+    x = -1;
+  }
+  Expect.equals(-1, x);
+}
diff --git a/tests/language_2/vm/regress_b131091988_test.dart b/tests/language_2/vm/regress_b131091988_test.dart
new file mode 100644
index 0000000..359b4fe
--- /dev/null
+++ b/tests/language_2/vm/regress_b131091988_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2019, 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 await from a call-via-field expression works.
+
+import 'package:expect/expect.dart';
+
+abstract class A<T> {
+  T Function(List<int> raw) get decode;
+}
+
+class B extends A<int> {
+  int Function(List<int> raw) get decode => (List<int> raw) => raw.first;
+}
+
+class C<T> {
+  final A<T> aa;
+  C(this.aa);
+}
+
+class D {
+  final C<int> cc;
+  D(this.cc);
+
+  Future<int> read() async {
+    return cc.aa.decode(await getList());
+  }
+
+  Future<List<int>> getList() async => <int>[42];
+}
+
+main() async {
+  D dd = new D(new C<int>(new B()));
+  Expect.equals(42, await dd.read());
+}
diff --git a/tests/lib_2/async/stream_controller_async_test.dart b/tests/lib_2/async/stream_controller_async_test.dart
index 3ee1725..a079250 100644
--- a/tests/lib_2/async/stream_controller_async_test.dart
+++ b/tests/lib_2/async/stream_controller_async_test.dart
@@ -8,7 +8,7 @@
 import 'dart:async';
 
 import 'package:expect/expect.dart';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'event_helper.dart';
 import 'stream_state_helper.dart';
diff --git a/tests/lib_2/async/stream_from_iterable_test.dart b/tests/lib_2/async/stream_from_iterable_test.dart
index b8317f0..d80d989 100644
--- a/tests/lib_2/async/stream_from_iterable_test.dart
+++ b/tests/lib_2/async/stream_from_iterable_test.dart
@@ -8,7 +8,7 @@
 
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'event_helper.dart';
 
diff --git a/tests/lib_2/async/stream_iterator_test.dart b/tests/lib_2/async/stream_iterator_test.dart
index b4a6596..c50f53e 100644
--- a/tests/lib_2/async/stream_iterator_test.dart
+++ b/tests/lib_2/async/stream_iterator_test.dart
@@ -4,7 +4,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test("stream iterator basic", () async {
diff --git a/tests/lib_2/async/stream_join_test.dart b/tests/lib_2/async/stream_join_test.dart
index aeac53c..6e3a98b 100644
--- a/tests/lib_2/async/stream_join_test.dart
+++ b/tests/lib_2/async/stream_join_test.dart
@@ -8,7 +8,7 @@
 import 'dart:async';
 
 import 'package:expect/expect.dart';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'event_helper.dart';
 
diff --git a/tests/lib_2/async/stream_periodic2_test.dart b/tests/lib_2/async/stream_periodic2_test.dart
index a69568d..1250131 100644
--- a/tests/lib_2/async/stream_periodic2_test.dart
+++ b/tests/lib_2/async/stream_periodic2_test.dart
@@ -7,7 +7,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test("stream-periodic2", () {
diff --git a/tests/lib_2/async/stream_periodic3_test.dart b/tests/lib_2/async/stream_periodic3_test.dart
index ab1adc2..a1fbbd0 100644
--- a/tests/lib_2/async/stream_periodic3_test.dart
+++ b/tests/lib_2/async/stream_periodic3_test.dart
@@ -7,7 +7,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 // The stopwatch is more precise than the Timer.
 // Some browsers (Firefox and IE so far) can trigger too early. So we add more
diff --git a/tests/lib_2/async/stream_periodic4_test.dart b/tests/lib_2/async/stream_periodic4_test.dart
index cbdc780..e687786 100644
--- a/tests/lib_2/async/stream_periodic4_test.dart
+++ b/tests/lib_2/async/stream_periodic4_test.dart
@@ -7,7 +7,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 void runTest(period, maxElapsed, pauseDuration) {
   Function done = expectAsync(() {});
diff --git a/tests/lib_2/async/stream_periodic5_test.dart b/tests/lib_2/async/stream_periodic5_test.dart
index 2a2f900..2be1c96 100644
--- a/tests/lib_2/async/stream_periodic5_test.dart
+++ b/tests/lib_2/async/stream_periodic5_test.dart
@@ -7,7 +7,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 watchMs(Stopwatch watch) {
   int microsecs = watch.elapsedMicroseconds;
diff --git a/tests/lib_2/async/stream_periodic6_test.dart b/tests/lib_2/async/stream_periodic6_test.dart
index 8b51ca8..0ef154e 100644
--- a/tests/lib_2/async/stream_periodic6_test.dart
+++ b/tests/lib_2/async/stream_periodic6_test.dart
@@ -7,7 +7,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test("stream-periodic1", () {
diff --git a/tests/lib_2/async/stream_periodic_test.dart b/tests/lib_2/async/stream_periodic_test.dart
index c8ea5a7..43a06d0 100644
--- a/tests/lib_2/async/stream_periodic_test.dart
+++ b/tests/lib_2/async/stream_periodic_test.dart
@@ -7,7 +7,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test("stream-periodic1", () {
diff --git a/tests/lib_2/async/stream_single_test.dart b/tests/lib_2/async/stream_single_test.dart
index 57bf54c..0156d71 100644
--- a/tests/lib_2/async/stream_single_test.dart
+++ b/tests/lib_2/async/stream_single_test.dart
@@ -8,7 +8,7 @@
 import 'dart:async';
 
 import 'package:expect/expect.dart';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'event_helper.dart';
 
diff --git a/tests/lib_2/async/stream_single_to_multi_subscriber_test.dart b/tests/lib_2/async/stream_single_to_multi_subscriber_test.dart
index 9cedef0..e422a8d 100644
--- a/tests/lib_2/async/stream_single_to_multi_subscriber_test.dart
+++ b/tests/lib_2/async/stream_single_to_multi_subscriber_test.dart
@@ -8,7 +8,7 @@
 import 'dart:async';
 
 import 'package:expect/expect.dart';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'event_helper.dart';
 
diff --git a/tests/lib_2/async/stream_state_helper.dart b/tests/lib_2/async/stream_state_helper.dart
index 2bd412f..6178495 100644
--- a/tests/lib_2/async/stream_state_helper.dart
+++ b/tests/lib_2/async/stream_state_helper.dart
@@ -7,7 +7,7 @@
 import 'dart:async';
 import 'dart:collection';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 class SubscriptionProtocolTest {
   final StreamProtocolTest _streamTest;
diff --git a/tests/lib_2/async/stream_state_nonzero_timer_test.dart b/tests/lib_2/async/stream_state_nonzero_timer_test.dart
index ff6cebb..8c7c115 100644
--- a/tests/lib_2/async/stream_state_nonzero_timer_test.dart
+++ b/tests/lib_2/async/stream_state_nonzero_timer_test.dart
@@ -9,7 +9,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'stream_state_helper.dart';
 
diff --git a/tests/lib_2/async/stream_state_test.dart b/tests/lib_2/async/stream_state_test.dart
index b56f37f..651f74d 100644
--- a/tests/lib_2/async/stream_state_test.dart
+++ b/tests/lib_2/async/stream_state_test.dart
@@ -5,7 +5,7 @@
 // Test the event/callback protocol of the stream implementations.
 library stream_state_test;
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'stream_state_helper.dart';
 
diff --git a/tests/lib_2/async/stream_subscription_as_future_test.dart b/tests/lib_2/async/stream_subscription_as_future_test.dart
index 5dc109d..5be5c91 100644
--- a/tests/lib_2/async/stream_subscription_as_future_test.dart
+++ b/tests/lib_2/async/stream_subscription_as_future_test.dart
@@ -8,7 +8,7 @@
 import 'dart:async';
 
 import 'package:expect/expect.dart';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test("subscription.asFuture success", () {
diff --git a/tests/lib_2/async/stream_subscription_cancel_test.dart b/tests/lib_2/async/stream_subscription_cancel_test.dart
index 6ad6b56..017bac5 100644
--- a/tests/lib_2/async/stream_subscription_cancel_test.dart
+++ b/tests/lib_2/async/stream_subscription_cancel_test.dart
@@ -7,7 +7,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 void main() {
   test('subscription.cancel', () {
diff --git a/tests/lib_2/async/stream_timeout_test.dart b/tests/lib_2/async/stream_timeout_test.dart
index 876a767..eb33ad2 100644
--- a/tests/lib_2/async/stream_timeout_test.dart
+++ b/tests/lib_2/async/stream_timeout_test.dart
@@ -4,7 +4,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   const ms5 = const Duration(milliseconds: 5);
diff --git a/tests/lib_2/async/stream_transform_test.dart b/tests/lib_2/async/stream_transform_test.dart
index f08f037..e8ac505 100644
--- a/tests/lib_2/async/stream_transform_test.dart
+++ b/tests/lib_2/async/stream_transform_test.dart
@@ -7,7 +7,7 @@
 import 'dart:async';
 
 import 'package:expect/expect.dart';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'event_helper.dart';
 
diff --git a/tests/lib_2/async/stream_transformation_broadcast_test.dart b/tests/lib_2/async/stream_transformation_broadcast_test.dart
index 3bb9667..839933f 100644
--- a/tests/lib_2/async/stream_transformation_broadcast_test.dart
+++ b/tests/lib_2/async/stream_transformation_broadcast_test.dart
@@ -8,7 +8,7 @@
 import 'dart:async';
 
 import 'package:expect/expect.dart';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'event_helper.dart';
 
diff --git a/tests/lib_2/async/stream_transformer_test.dart b/tests/lib_2/async/stream_transformer_test.dart
index f1b850d..9f89f6a 100644
--- a/tests/lib_2/async/stream_transformer_test.dart
+++ b/tests/lib_2/async/stream_transformer_test.dart
@@ -48,6 +48,8 @@
   var stream = controller.stream;
   var transformed = stream.transform(transformer);
 
+  Expect.isFalse(transformed.isBroadcast);
+
   var handleData = (String _) => 499;
   var handleError = (e, st) => 42;
   var handleDone = () => 99;
@@ -85,4 +87,17 @@
   Expect.identical(_defaultData, subscription.handleData);
   Expect.identical(_defaultError, subscription.handleError);
   Expect.identical(handleDone, subscription.handleDone);
+
+  controller = new StreamController.broadcast(sync: true);
+  stream = controller.stream;
+  transformed = stream.transform(transformer);
+  Expect.isTrue(transformed.isBroadcast);
+  subscription =
+      transformed.listen(null, onDone: handleDone, cancelOnError: true);
+
+  Expect.identical(stream, subscription.stream);
+  Expect.equals(true, subscription.cancelOnError);
+  Expect.identical(_defaultData, subscription.handleData);
+  Expect.identical(_defaultError, subscription.handleError);
+  Expect.identical(handleDone, subscription.handleDone);
 }
diff --git a/tests/lib_2/async/timer_cancel1_test.dart b/tests/lib_2/async/timer_cancel1_test.dart
index 49fb647..1295e96 100644
--- a/tests/lib_2/async/timer_cancel1_test.dart
+++ b/tests/lib_2/async/timer_cancel1_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   // Test that a timeout handler can cancel another.
diff --git a/tests/lib_2/async/timer_isActive_test.dart b/tests/lib_2/async/timer_isActive_test.dart
index 84f872f..b688b21 100644
--- a/tests/lib_2/async/timer_isActive_test.dart
+++ b/tests/lib_2/async/timer_isActive_test.dart
@@ -4,7 +4,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test("timer isActive test", () {
diff --git a/tests/lib_2/async/timer_test.dart b/tests/lib_2/async/timer_test.dart
index 052ff63..220ac05 100644
--- a/tests/lib_2/async/timer_test.dart
+++ b/tests/lib_2/async/timer_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 const int STARTTIMEOUT = 1050;
 const int DECREASE = 200;
diff --git a/tests/lib_2/html/async_spawnuri_test.dart b/tests/lib_2/html/async_spawnuri_test.dart
deleted file mode 100644
index 1175a3e..0000000
--- a/tests/lib_2/html/async_spawnuri_test.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-library async_spawnuri_test;
-
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
-
-import 'dart:async';
-import 'dart:isolate';
-import 'dart:html';
-
-// OtherScripts=async_oneshot.dart async_periodictimer.dart async_cancellingisolate.dart
-main() {
-  useHtmlConfiguration();
-
-  test('one shot timer in pure isolate', () {
-    var response = new ReceivePort();
-    var remote = Isolate.spawnUri(
-        Uri.parse('async_oneshot.dart'), ['START'], response.sendPort);
-    remote.catchError((x) => expect("Error in oneshot isolate", x));
-    expect(remote.then((_) => response.first), completion('DONE'));
-  });
-
-  test('periodic timer in pure isolate', () {
-    var response = new ReceivePort();
-    var remote = Isolate.spawnUri(
-        Uri.parse('async_periodictimer.dart'), ['START'], response.sendPort);
-    remote.catchError((x) => expect("Error in periodic timer isolate", x));
-    expect(remote.then((_) => response.first), completion('DONE'));
-  });
-
-  test('cancellation in pure isolate', () {
-    var response = new ReceivePort();
-    var remote = Isolate.spawnUri(Uri.parse('async_cancellingisolate.dart'),
-        ['START'], response.sendPort);
-    remote.catchError((x) => expect("Error in cancelling isolate", x));
-    expect(remote.then((_) => response.first), completion('DONE'));
-  });
-}
diff --git a/tests/lib_2/html/debugger_test_golden.txt b/tests/lib_2/html/debugger_test_golden.txt
index 1c9ec45..b18cfc5 100644
--- a/tests/lib_2/html/debugger_test_golden.txt
+++ b/tests/lib_2/html/debugger_test_golden.txt
@@ -4234,34 +4234,6 @@
             {
                 "style": "background-color: thistle; color: rgb(136, 19, 145); margin-right: -13px"
             },
-            "[[instance members]]: "
-        ],
-        [
-            "span",
-            {
-                "style": "margin-left: 13px"
-            },
-            [
-                "object",
-                {
-                    "object": "<OBJECT>",
-                    "config": {
-                        "name": "asObject"
-                    }
-                }
-            ]
-        ]
-    ],
-    [
-        "li",
-        {
-            "style": "padding-left: 13px;"
-        },
-        [
-            "span",
-            {
-                "style": "background-color: thistle; color: rgb(136, 19, 145); margin-right: -13px"
-            },
             "[[class]]: "
         ],
         [
@@ -4393,34 +4365,6 @@
             {
                 "style": "background-color: thistle; color: rgb(136, 19, 145); margin-right: -13px"
             },
-            "[[instance members]]: "
-        ],
-        [
-            "span",
-            {
-                "style": "margin-left: 13px"
-            },
-            [
-                "object",
-                {
-                    "object": "<OBJECT>",
-                    "config": {
-                        "name": "asObject"
-                    }
-                }
-            ]
-        ]
-    ],
-    [
-        "li",
-        {
-            "style": "padding-left: 13px;"
-        },
-        [
-            "span",
-            {
-                "style": "background-color: thistle; color: rgb(136, 19, 145); margin-right: -13px"
-            },
             "[[class]]: "
         ],
         [
@@ -7308,4 +7252,4 @@
         ]
     ]
 ]
------------------------------------
\ No newline at end of file
+-----------------------------------
diff --git a/tests/lib_2/html/websql_test.dart b/tests/lib_2/html/websql_test.dart
index 07f9ff2..4c1e34d 100644
--- a/tests/lib_2/html/websql_test.dart
+++ b/tests/lib_2/html/websql_test.dart
@@ -4,7 +4,7 @@
 import 'dart:html';
 import 'dart:web_sql';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 Future<SqlResultSet> createTable(
     SqlTransaction transaction, String tableName, String columnName) async {
diff --git a/tests/lib_2/isolate/browser/compute_this_script_browser_test.dart b/tests/lib_2/isolate/browser/compute_this_script_browser_test.dart
deleted file mode 100644
index b7464fc..0000000
--- a/tests/lib_2/isolate/browser/compute_this_script_browser_test.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.
-
-// Test that spawn works even when there are many script files in the page.
-// This requires computing correctly the URL to the orignal script, so we can
-// pass it to the web worker APIs.
-library compute_this_script;
-
-import 'dart:html';
-import 'dart:isolate';
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
-import "../remote_unittest_helper.dart";
-
-child(var message) {
-  var data = message[0];
-  var reply = message[1];
-  reply.send('re: $data');
-}
-
-void main([args, port]) {
-  if (testRemote(main, port)) return;
-  useHtmlConfiguration();
-  var script = new ScriptElement();
-  document.body.append(script);
-  test('spawn with other script tags in page', () {
-    ReceivePort port = new ReceivePort();
-    port.listen(expectAsync((msg) {
-      expect(msg, equals('re: hi'));
-      port.close();
-    }));
-
-    Isolate.spawn(child, ['hi', port.sendPort]);
-  });
-}
diff --git a/tests/lib_2/isolate/browser/issue_12474_child.dart b/tests/lib_2/isolate/browser/issue_12474_child.dart
deleted file mode 100644
index 510fdbb..0000000
--- a/tests/lib_2/isolate/browser/issue_12474_child.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// 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:isolate';
-import 'package:issue_12474_lib.dart';
-
-void main([args, port]) {
-  testPackageRoot(args);
-}
diff --git a/tests/lib_2/isolate/browser/issue_12474_test.dart b/tests/lib_2/isolate/browser/issue_12474_test.dart
deleted file mode 100644
index aca9741..0000000
--- a/tests/lib_2/isolate/browser/issue_12474_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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.
-
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_12474_child.dart
-// OtherScripts=package/issue_12474_lib.dart
-
-import 'dart:isolate';
-
-final SPAWN_PACKAGE_ROOT = Uri.parse(".");
-
-void main([args, port]) {
-  var p = new ReceivePort();
-  Isolate.spawnUri(
-      Uri.parse("issue_12474_child.dart"), [p.sendPort as dynamic], {},
-      packageRoot: SPAWN_PACKAGE_ROOT);
-  p.listen((msg) {
-    print("Received message");
-    p.close();
-  });
-}
diff --git a/tests/lib_2/isolate/browser/package/issue_12474_lib.dart b/tests/lib_2/isolate/browser/package/issue_12474_lib.dart
deleted file mode 100644
index f9beb27..0000000
--- a/tests/lib_2/isolate/browser/package/issue_12474_lib.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// 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.
-
-void testPackageRoot(args) {
-  args[0].send(null);
-}
diff --git a/tests/lib_2/isolate/browser/package_resolve_browser_hook2_test.dart b/tests/lib_2/isolate/browser/package_resolve_browser_hook2_test.dart
deleted file mode 100644
index f87a9d8..0000000
--- a/tests/lib_2/isolate/browser/package_resolve_browser_hook2_test.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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:js';
-import 'dart:isolate';
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
-
-main() async {
-  useHtmlConfiguration();
-
-  setUp(() {
-    context['defaultPackagesBase'] = 'path1/';
-  });
-
-  test('hook overrides package-uri resolution', () async {
-    var uri = await Isolate.resolvePackageUri(Uri.parse('package:foo/bar.txt'));
-    expect(uri, Uri.base.resolve('path1/foo/bar.txt'));
-  });
-
-  test('hook is read once, on the first use of resolvePackageUri', () async {
-    await Isolate.resolvePackageUri(Uri.parse('package:foo/bar.txt'));
-    context['defaultPackagesBase'] = 'path2/';
-    var uri = await Isolate.resolvePackageUri(Uri.parse('package:foo/bar.txt'));
-    expect(uri, Uri.base.resolve('path1/foo/bar.txt'));
-  });
-}
diff --git a/tests/lib_2/isolate/browser/package_resolve_browser_hook_test.dart b/tests/lib_2/isolate/browser/package_resolve_browser_hook_test.dart
deleted file mode 100644
index 5c90474..0000000
--- a/tests/lib_2/isolate/browser/package_resolve_browser_hook_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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:isolate';
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
-
-main() async {
-  useHtmlConfiguration();
-
-  test('defaultPackagesBase hook overrides package-uri resolution', () async {
-    var uri = await Isolate.resolvePackageUri(Uri.parse('package:foo/bar.txt'));
-    expect(uri, Uri.base.resolve('path/set/from/hook/foo/bar.txt'));
-  });
-}
diff --git a/tests/lib_2/isolate/browser/package_resolve_browser_hook_test.html b/tests/lib_2/isolate/browser/package_resolve_browser_hook_test.html
deleted file mode 100644
index a3b67b6..0000000
--- a/tests/lib_2/isolate/browser/package_resolve_browser_hook_test.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="dart.unittest" content="full-stack-traces">
-  <title> mirrors_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 mirrors_test </h1>
-  <script type="text/javascript"
-      src="/root_dart/tools/testing/dart/test_controller.js"></script>
-  <script>
-  // Dart2js exposes this hook to override the default base path where resource
-  // package uris are resolved from.
-  defaultPackagesBase = 'path/set/from/hook/';
-  </script>
-  %TEST_SCRIPTS%
-</body>
-</html>
diff --git a/tests/lib_2/isolate/browser/package_resolve_browser_test.dart b/tests/lib_2/isolate/browser/package_resolve_browser_test.dart
deleted file mode 100644
index 49ced93..0000000
--- a/tests/lib_2/isolate/browser/package_resolve_browser_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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:isolate';
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
-
-main() {
-  useHtmlConfiguration();
-
-  test('by default package-uri resolve under base/packages/', () async {
-    var uri = await Isolate.resolvePackageUri(Uri.parse('package:foo/bar.txt'));
-    expect(uri, Uri.base.resolve('packages/foo/bar.txt'));
-  });
-}
diff --git a/tests/lib_2/isolate/browser/typed_data_message_test.dart b/tests/lib_2/isolate/browser/typed_data_message_test.dart
deleted file mode 100644
index 3070fc0..0000000
--- a/tests/lib_2/isolate/browser/typed_data_message_test.dart
+++ /dev/null
@@ -1,115 +0,0 @@
-// 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.
-
-// Dart test program for testing serialization of messages.
-// VMOptions=--enable_type_checks --enable_asserts
-
-library TypedDataMessageTest;
-
-import 'dart:async';
-import 'dart:isolate';
-import 'dart:typed_data';
-import 'package:unittest/unittest.dart';
-import "../remote_unittest_helper.dart";
-
-// ---------------------------------------------------------------------------
-// Message passing test.
-// ---------------------------------------------------------------------------
-
-List elements;
-
-void initializeList() {
-  elements = new List(3);
-  elements[0] = new Int8List(10);
-  for (int j = 0; j < 10; j++) {
-    elements[0][j] = j;
-  }
-  elements[1] = new ByteData.view(elements[0].buffer, 0, 10);
-  for (int j = 0; j < 10; j++) {
-    elements[1].setInt8(j, j + 100);
-  }
-  elements[2] = new Int8List.view(new Int8List(100).buffer, 50, 10);
-  for (int j = 0; j < 10; j++) {
-    elements[2][j] = j + 250;
-  }
-}
-
-void VerifyList(List expected, List actual) {
-  for (int i = 0; i < expected.length; i++) {
-    expect(actual[i], expected[i]);
-  }
-}
-
-void VerifyBytedata(ByteData expected, ByteData actual) {
-  for (int i = 0; i < expected.lengthInBytes; i++) {
-    expect(actual.getInt8(i), expected.getInt8(i));
-  }
-}
-
-void VerifyObject(int index, var actual) {
-  var expected = elements[index];
-  if (expected is List) {
-    expect(actual, isList);
-    VerifyList(expected, actual);
-  } else {
-    expect(true, actual is ByteData);
-    VerifyBytedata(expected, actual);
-  }
-  expect(actual.length, expected.length);
-}
-
-pingPong(SendPort initialReplyTo) {
-  var port = new ReceivePort();
-  initialReplyTo.send(port.sendPort);
-  initializeList();
-  int count = 0;
-  port.listen((var message) {
-    var data = message[0];
-    SendPort replyTo = message[1];
-    if (data == -1) {
-      port.close();
-      replyTo.send(count);
-    } else {
-      // Check if the received object is correct.
-      if (count < elements.length) {
-        VerifyObject(count, data);
-      }
-      // Bounce the received object back so that the sender
-      // can make sure that the object matches.
-      replyTo.send(data);
-      count++;
-    }
-  });
-}
-
-Future sendReceive(SendPort port, msg) {
-  ReceivePort response = new ReceivePort();
-  port.send([msg, response.sendPort]);
-  return response.first;
-}
-
-void main([args, port]) {
-  if (testRemote(main, port)) return;
-  initializeList();
-  test("send objects and receive them back", () {
-    ReceivePort response = new ReceivePort();
-    Isolate.spawn(pingPong, response.sendPort);
-    response.first.then((_remote) {
-      SendPort remote = _remote;
-      // Send objects and receive them back.
-      for (int i = 0; i < elements.length; i++) {
-        var sentObject = elements[i];
-        var idx = i;
-        sendReceive(remote, sentObject).then(expectAsync((var receivedObject) {
-          VerifyObject(idx, receivedObject);
-        }));
-      }
-
-      // Shutdown the MessageServer.
-      sendReceive(remote, -1).then(expectAsync((int message) {
-        expect(message, elements.length);
-      }));
-    });
-  });
-}
diff --git a/tests/lib_2/isolate/deferred_in_isolate2_test.dart b/tests/lib_2/isolate/deferred_in_isolate2_test.dart
index 636eb73..47d401a 100644
--- a/tests/lib_2/isolate/deferred_in_isolate2_test.dart
+++ b/tests/lib_2/isolate/deferred_in_isolate2_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:isolate';
 import 'dart:async';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'deferred_in_isolate2_lib.dart' deferred as lib;
 
diff --git a/tests/lib_2/isolate/error_at_spawnuri_test.dart b/tests/lib_2/isolate/error_at_spawnuri_test.dart
index d33ac09..5c428b9 100644
--- a/tests/lib_2/isolate/error_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/error_at_spawnuri_test.dart
@@ -1,8 +1,6 @@
 // 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.
-//
-// OtherScripts=error_at_spawnuri_iso.dart
 
 library error_at_spawnuri;
 
diff --git a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
index 9643770..6e9a5a8 100644
--- a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
@@ -1,8 +1,6 @@
 // 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.
-//
-// OtherScripts=error_exit_at_spawning_shared.dart
 
 library error_exit_at_spawnuri;
 
diff --git a/tests/lib_2/isolate/exit_at_spawnuri_test.dart b/tests/lib_2/isolate/exit_at_spawnuri_test.dart
index fd2287b..f415c66 100644
--- a/tests/lib_2/isolate/exit_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/exit_at_spawnuri_test.dart
@@ -1,8 +1,6 @@
 // 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.
-//
-// OtherScripts=exit_at_spawnuri_iso.dart
 
 library exit_at_spawn;
 
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
index 9da9678..74b6cc6 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
@@ -2,13 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_21398_child_isolate1.dart
-// OtherScripts=issue_21398_child_isolate11.dart
-
 import 'dart:isolate';
-import 'dart:async';
 import "package:expect/expect.dart";
 import 'package:async_helper/async_helper.dart';
 
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
index 27d49b9..0fe1043 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
@@ -2,12 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=deferred_loaded_lib.dart
-
 import 'dart:isolate';
-import 'dart:async';
 import "package:expect/expect.dart";
 import 'package:async_helper/async_helper.dart';
 
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
index 967d25f..ab413e9 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
@@ -2,12 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_21398_child_isolate.dart
-
 import 'dart:isolate';
-import 'dart:async';
 import "package:expect/expect.dart";
 import 'package:async_helper/async_helper.dart';
 
diff --git a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
index 6294767..2c1dc54 100644
--- a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
+++ b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
@@ -2,12 +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.
 
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_24243_child1_isolate.dart
-// OtherScripts=issue_24243_child2_isolate.dart
-// OtherScripts=issue_24243_child3_isolate.dart
-
 import 'dart:collection';
 import 'dart:isolate';
 
diff --git a/tests/lib_2/isolate/spawn_uri_multi_test.dart b/tests/lib_2/isolate/spawn_uri_multi_test.dart
index c74c517..2984fca 100644
--- a/tests/lib_2/isolate/spawn_uri_multi_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_multi_test.dart
@@ -3,13 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Negative test to make sure that we are reaching all assertions.
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_child_isolate.dart
 library spawn_tests;
 
 import 'dart:isolate';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 /* Dummy import so multi-test copies the file.
 import 'spawn_uri_child_isolate.dart';
diff --git a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
index b13aff1..f558df5 100644
--- a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
@@ -3,13 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Example of nested spawning of isolates from a URI
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_nested_child1_vm_isolate.dart spawn_uri_nested_child2_vm_isolate.dart
 library NestedSpawnUriLibrary;
 
 import 'dart:isolate';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test('isolate fromUri - nested send and reply', () {
diff --git a/tests/lib_2/isolate/spawn_uri_test.dart b/tests/lib_2/isolate/spawn_uri_test.dart
index a4d89c3..e71fed7 100644
--- a/tests/lib_2/isolate/spawn_uri_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_test.dart
@@ -3,13 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Example of spawning an isolate from a URI
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_child_isolate.dart
 library spawn_tests;
 
 import 'dart:isolate';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test('isolate fromUri - send and reply', () async {
diff --git a/tests/lib_2/isolate/spawn_uri_vm_test.dart b/tests/lib_2/isolate/spawn_uri_vm_test.dart
index a61c2f9..a3b8f61 100644
--- a/tests/lib_2/isolate/spawn_uri_vm_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_vm_test.dart
@@ -3,13 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Example of spawning an isolate from a URI
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_child_isolate.dart
 library spawn_tests;
 
 import 'dart:isolate';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test('isolate fromUri - send and reply', () {
diff --git a/tests/lib_2/isolate/timer_isolate_test.dart b/tests/lib_2/isolate/timer_isolate_test.dart
index cf7fb26..a34005a 100644
--- a/tests/lib_2/isolate/timer_isolate_test.dart
+++ b/tests/lib_2/isolate/timer_isolate_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:isolate';
 import 'dart:async';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 const Duration TIMEOUT = const Duration(milliseconds: 100);
 
diff --git a/tests/lib_2/isolate/transferable_failed_to_send_test.dart b/tests/lib_2/isolate/transferable_failed_to_send_test.dart
new file mode 100644
index 0000000..1bca938
--- /dev/null
+++ b/tests/lib_2/isolate/transferable_failed_to_send_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2019, 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:io" show ServerSocket;
+import "dart:isolate";
+import "dart:typed_data" show ByteData;
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+void main() async {
+  final port = new ReceivePort();
+
+  // Sending a socket object will result in an error.
+  final socket = await ServerSocket.bind('localhost', 0);
+
+  final x = new ByteData(4);
+  for (int i = 0; i < 4; i++) {
+    x.setUint8(i, i);
+  }
+  {
+    final transferableFirst = TransferableTypedData.fromList([x]);
+    Expect.throwsArgumentError(
+        () => port.sendPort.send(<dynamic>[transferableFirst, socket]));
+    // Once TransferableTypedData was sent even if attempt failed, it can't be
+    // materialized.
+    // This need to be changed so that on failed send we should not detach the
+    // buffer form the transferrable. The order should not matter (i.e. if the
+    // error happens before or after the serializer hits a transferrable object)
+
+    final data1 = transferableFirst.materialize().asUint8List();
+    Expect.equals(x.lengthInBytes, data1.length);
+    for (int i = 0; i < data1.length; i++) {
+      Expect.equals(i, data1[i]);
+    }
+  }
+  {
+    final transferableFirst = TransferableTypedData.fromList([x]);
+    Expect.throwsArgumentError(() => port.sendPort
+        .send(<dynamic>[transferableFirst, transferableFirst, socket]));
+    // Once TransferableTypedData was sent even if attempt failed, it can't be
+    // materialized.
+    // This need to be changed so that on failed send we should not detach the
+    // buffer form the transferrable. The order should not matter (i.e. if the
+    // error happens before or after the serializer hits a transferrable object)
+
+    final data1 = transferableFirst.materialize().asUint8List();
+    Expect.equals(x.lengthInBytes, data1.length);
+    for (int i = 0; i < data1.length; i++) {
+      Expect.equals(i, data1[i]);
+    }
+  }
+
+  {
+    final transferableSecond = TransferableTypedData.fromList([x]);
+    Expect.throwsArgumentError(
+        () => port.sendPort.send(<dynamic>[socket, transferableSecond]));
+    // Once TransferableTypedData was sent even if attempt failed, it can't be
+    // materialized.
+    final data2 = transferableSecond.materialize().asUint8List();
+    Expect.equals(x.lengthInBytes, data2.length);
+    for (int i = 0; i < data2.length; i++) {
+      Expect.equals(i, data2[i]);
+    }
+  }
+
+  {
+    final transferableSecond = TransferableTypedData.fromList([x]);
+    Expect.throwsArgumentError(() => port.sendPort
+        .send(<dynamic>[socket, transferableSecond, transferableSecond]));
+    // Once TransferableTypedData was sent even if attempt failed, it can't be
+    // materialized.
+    final data2 = transferableSecond.materialize().asUint8List();
+    Expect.equals(x.lengthInBytes, data2.length);
+    for (int i = 0; i < data2.length; i++) {
+      Expect.equals(i, data2[i]);
+    }
+  }
+
+  socket.close();
+  port.close();
+}
diff --git a/tests/lib_2/isolate/transferable_test.dart b/tests/lib_2/isolate/transferable_test.dart
new file mode 100644
index 0000000..df28bab
--- /dev/null
+++ b/tests/lib_2/isolate/transferable_test.dart
@@ -0,0 +1,284 @@
+// Copyright (c) 2019, 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:collection";
+import "dart:isolate";
+import "dart:typed_data";
+import "package:expect/expect.dart";
+
+const large = 2 * 1024 * 1024;
+
+void child(replyPort) {
+  print("Child start");
+
+  print("Child ByteData");
+  dynamic x = new ByteData(large);
+  for (int i = 0; i < 4; i++) {
+    x.setInt8(i, i);
+  }
+  replyPort.send(TransferableTypedData.fromList([x.buffer.asUint8List()]));
+
+  print("Child Uint8List");
+  x = new Uint8List(large);
+  for (int i = 0; i < 4; i++) {
+    x[i] = i;
+  }
+  replyPort.send(TransferableTypedData.fromList([x]));
+
+  print("Child Uint8List.view");
+  x = new Uint8List.view(x.buffer, 1, 2);
+  replyPort.send(TransferableTypedData.fromList([x]));
+
+  print("Child Int8List");
+  x = new Int8List(large);
+  for (int i = 0; i < 4; i++) {
+    x[i] = i;
+  }
+  replyPort.send(TransferableTypedData.fromList([x]));
+
+  print("Child Uint16List");
+  x = new Uint16List(large);
+  for (int i = 0; i < 4; i++) {
+    x[i] = i;
+  }
+  replyPort.send(TransferableTypedData.fromList([x]));
+
+  print("Child Int16List");
+  x = new Int16List(large);
+  for (int i = 0; i < 4; i++) {
+    x[i] = i;
+  }
+  replyPort.send(TransferableTypedData.fromList([x]));
+
+  print("Child Uint32List");
+  x = new Uint32List(large);
+  for (int i = 0; i < 4; i++) {
+    x[i] = i;
+  }
+  replyPort.send(TransferableTypedData.fromList([x]));
+
+  print("Child Int32List");
+  x = new Int32List(large);
+  for (int i = 0; i < 4; i++) {
+    x[i] = i;
+  }
+  replyPort.send(TransferableTypedData.fromList([x]));
+
+  print("Child Uint64List");
+  x = new Uint64List(large);
+  for (int i = 0; i < 4; i++) {
+    x[i] = i;
+  }
+  replyPort.send(TransferableTypedData.fromList([x]));
+
+  print("Child Int64List");
+  x = new Int64List(large);
+  for (int i = 0; i < 4; i++) {
+    x[i] = i;
+  }
+  replyPort.send(TransferableTypedData.fromList([x]));
+
+  print("Child two Uint8Lists");
+  x = new Uint8List(large);
+  for (int i = 0; i < 4; i++) {
+    x[i] = i;
+  }
+  replyPort.send([
+    TransferableTypedData.fromList([x]),
+    TransferableTypedData.fromList([x])
+  ]);
+
+  print("Child same Uint8List twice - materialize first");
+  x = new Uint8List(large);
+  for (int i = 0; i < 4; i++) {
+    x[i] = i;
+  }
+  var tr = TransferableTypedData.fromList([x]);
+  replyPort.send([tr, tr]);
+
+  print("Child same Uint8List twice - materialize second");
+  x = new Uint8List(large);
+  for (int i = 0; i < 4; i++) {
+    x[i] = i;
+  }
+  tr = TransferableTypedData.fromList([x]);
+  replyPort.send([tr, tr]);
+
+  print("Child done");
+}
+
+Future<void> main(List<String> args) async {
+  print("Parent start");
+
+  ReceivePort port = new ReceivePort();
+  Isolate.spawn(child, port.sendPort);
+  StreamIterator<dynamic> incoming = new StreamIterator<dynamic>(port);
+
+  print("Parent ByteData");
+  Expect.isTrue(await incoming.moveNext());
+  dynamic x = incoming.current.materialize().asByteData();
+  Expect.isTrue(x is ByteData);
+  Expect.equals(large, x.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, x.getUint8(i));
+  }
+
+  print("Parent Uint8List");
+  Expect.isTrue(await incoming.moveNext());
+  x = incoming.current.materialize();
+  Expect.isTrue(x is ByteBuffer);
+  x = x.asUint8List();
+  Expect.equals(large, x.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, x[i]);
+  }
+
+  print("Parent Uint8List view");
+  Expect.isTrue(await incoming.moveNext());
+  x = incoming.current.materialize().asUint8List();
+  Expect.equals(1, x[0]);
+  Expect.equals(2, x[1]);
+
+  print("Parent Int8");
+  Expect.isTrue(await incoming.moveNext());
+  x = incoming.current.materialize().asInt8List();
+  Expect.equals(large, x.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, x[i]);
+  }
+
+  print("Parent Uint16");
+  Expect.isTrue(await incoming.moveNext());
+  x = incoming.current.materialize().asUint16List();
+  Expect.equals(large, x.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, x[i]);
+  }
+
+  print("Parent Int16");
+  Expect.isTrue(await incoming.moveNext());
+  x = incoming.current.materialize().asInt16List();
+  Expect.equals(large, x.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, x[i]);
+  }
+
+  print("Parent Uint32");
+  Expect.isTrue(await incoming.moveNext());
+  x = incoming.current.materialize().asUint32List();
+  Expect.equals(large, x.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, x[i]);
+  }
+
+  print("Parent Int32");
+  Expect.isTrue(await incoming.moveNext());
+  x = incoming.current.materialize().asInt32List();
+  Expect.equals(large, x.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, x[i]);
+  }
+
+  print("Parent Uint64");
+  Expect.isTrue(await incoming.moveNext());
+  x = incoming.current.materialize().asUint64List();
+  Expect.equals(large, x.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, x[i]);
+  }
+
+  print("Parent Int64");
+  Expect.isTrue(await incoming.moveNext());
+  x = incoming.current.materialize().asInt64List();
+  Expect.equals(large, x.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, x[i]);
+  }
+
+  print("Parent two Uint8Lists");
+  Expect.isTrue(await incoming.moveNext());
+  final x1 = incoming.current[0].materialize().asUint8List();
+  final x2 = incoming.current[1].materialize().asUint8List();
+  Expect.equals(large, x1.length);
+  Expect.equals(large, x2.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, x1[i]);
+    Expect.equals(i, x2[i]);
+  }
+
+  print("Parent same Uint8Lists twice, materialize first");
+  Expect.isTrue(await incoming.moveNext());
+  final tr0 = incoming.current[0].materialize().asUint8List();
+  Expect.throwsArgumentError(() => incoming.current[1].materialize());
+  Expect.equals(large, tr0.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, tr0[i]);
+  }
+
+  print("Parent same Uint8Lists twice, materialize second");
+  Expect.isTrue(await incoming.moveNext());
+  final tr1 = incoming.current[1].materialize().asUint8List();
+  Expect.throwsArgumentError(() => incoming.current[0].materialize());
+  Expect.equals(large, tr1.length);
+  for (int i = 0; i < 4; i++) {
+    Expect.equals(i, tr1[i]);
+  }
+
+  port.close();
+  print("Parent done");
+
+  testCreateMaterializeInSameIsolate();
+  testIterableToList();
+  testUserExtendedList();
+}
+
+testCreateMaterializeInSameIsolate() {
+  // Test same-isolate operation of TransferableTypedData.
+  final Uint8List bytes = new Uint8List(large);
+  for (int i = 0; i < bytes.length; ++i) {
+    bytes[i] = i % 256;
+  }
+  final tr = TransferableTypedData.fromList([bytes]);
+  Expect.listEquals(bytes, tr.materialize().asUint8List());
+}
+
+testIterableToList() {
+  // Test that iterable.toList() can be used as an argument.
+  final list1 = Uint8List(10);
+  for (int i = 0; i < list1.length; i++) {
+    list1[i] = i;
+  }
+  final list2 = Uint8List(20);
+  for (int i = 0; i < list2.length; i++) {
+    list2[i] = i + list1.length;
+  }
+  final map = {list1: true, list2: true};
+  Iterable<Uint8List> iterable = map.keys;
+  final result = TransferableTypedData.fromList(iterable.toList())
+      .materialize()
+      .asUint8List();
+  for (int i = 0; i < result.length; i++) {
+    Expect.equals(i, result[i]);
+  }
+}
+
+class MyList<E> extends ListBase<E> {
+  List<E> _source;
+  MyList(this._source);
+  int get length => _source.length;
+  void set length(int length) {
+    _source.length = length;
+  }
+
+  E operator [](int index) => _source[index];
+  void operator []=(int index, E value) {
+    _source[index] = value;
+  }
+}
+
+testUserExtendedList() {
+  final list = MyList<TypedData>([Uint8List(10)]);
+  TransferableTypedData.fromList(list);
+}
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 3a5dc80..1e56403 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -139,7 +139,6 @@
 async/periodic_timer4_test: Pass, RuntimeError # Flaky. Issue 32094
 
 [ $csp ]
-isolate/browser/package_resolve_browser_hook_test: SkipByDesign # Test written in a way that violates CSP.
 isolate/deferred_in_isolate2_test: Skip # Issue 16898. Deferred loading does not work from an isolate in CSP-mode
 
 [ $hot_reload ]
@@ -149,24 +148,11 @@
 [ $jscl ]
 isolate/spawn_uri_multi_test/none: RuntimeError # Issue 13544
 
-[ !$strong ]
-async/future_test: SkipByDesign # Uses Dart 2 syntax.
-async/stream_first_where_test/badType: MissingCompileTimeError
-async/stream_from_iterable_test: SkipByDesign # Uses Dart 2 syntax.
-async/stream_last_where_test/badType: MissingCompileTimeError
-mirrors/redirecting_factory_different_type_test/02: MissingCompileTimeError
-
 [ $builder_tag == mac10_7 && $runtime == safari ]
 typed_data/setRange_2_test: Fail # Safari doesn't fully implement spec for TypedArray.set
 typed_data/setRange_3_test: Fail # Safari doesn't fully implement spec for TypedArray.set
 typed_data/setRange_4_test: Fail # Safari doesn't fully implement spec for TypedArray.set
 
-[ $compiler != dart2analyzer && $compiler != fasta && !$strong ]
-async/future_or_type_test: Fail # Strong mode implements FutureOr, non-strong treats it as dynamic.
-
-[ $compiler != dartdevc && $checked && !$strong ]
-async/future_or_only_in_async_test/00: MissingCompileTimeError
-
 [ $compiler == dartk && $system == macos && $hot_reload && ($arch == simdbc || $arch == simdbc64) ]
 isolate/unresolved_ports_test: Pass, RuntimeError #  Issue 35410
 
@@ -198,18 +184,6 @@
 html/request_animation_frame_test: Skip # Times out. Issue 22167
 html/transition_event_test: Skip # Times out. Issue 22167
 
-[ !$checked && !$strong ]
-async/future_or_only_in_async_test/00: MissingCompileTimeError
-async/multiple_timer_test: Pass, Fail # Timing related
-isolate/issue_24243_parent_isolate_test: SkipByDesign # Requires type checks.
-
-[ !$fasta && !$strong ]
-isolate/isolate_import_test/01: MissingCompileTimeError
-mirrors/top_level_accessors_test/01: MissingCompileTimeError
-typed_data/float32x4_static_test: MissingCompileTimeError
-typed_data/int32x4_static_test/01: MissingCompileTimeError
-typed_data/int32x4_static_test/02: MissingCompileTimeError
-
 [ !$preview_dart_2 && ($runtime == dart_precompiled || $runtime == vm) ]
 *: SkipByDesign # Deprecating all Dart1 modes of execution
 
@@ -240,7 +214,6 @@
 async/stream_timeout_test: SkipSlow # Times out. Issue 22050
 
 [ $runtime == dart_precompiled || $runtime == vm ]
-isolate/browser/*: SkipByDesign # Browser specific tests
 isolate/isolate_stress_test: Skip # Issue 12588: Uses dart:html. This should be able to pass when we have wrapper-less tests.
 isolate/stacktrace_message_test: RuntimeError # Fails to send stacktrace object.
 
diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status
index 705ddba..b96429f 100644
--- a/tests/lib_2/lib_2_dart2js.status
+++ b/tests/lib_2/lib_2_dart2js.status
@@ -3,10 +3,13 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dart2js ]
+async/future_or_type_test: RuntimeError
+async/slow_consumer2_test: RuntimeError
+async/stream_distinct_test: RuntimeError
+collection/list_test: RuntimeError
 convert/chunked_conversion_utf88_test: Slow
 convert/utf85_test: Slow
 developer/timeline_test: Skip # Not supported
-html/async_spawnuri_test: SkipByDesign
 html/async_test: SkipByDesign
 html/custom/document_register_basic_test: Slow
 html/custom/document_register_type_extensions_test/construction: Slow
@@ -16,6 +19,7 @@
 html/custom/mirrors_2_test: Skip # mirrors not supported, delete this test.
 html/custom/mirrors_test: Skip # mirrors not supported, delete this test.
 html/custom_elements_test: Slow # Issue 26789
+html/element_classes_test: RuntimeError
 html/isolates_test: SkipByDesign
 html/mirrors_js_typed_interop_test: Skip # mirrors not supported, delete this test.
 html/worker_api_test: SkipByDesign
@@ -36,6 +40,7 @@
 html/element_types_keygen_test: RuntimeError # Issue 29055
 html/file_sample_test: Pass, RuntimeError
 html/fileapi_entry_test: Pass, RuntimeError
+html/interactive_media_test: RuntimeError
 html/media_stream_test: RuntimeError # Please triage.
 html/speechrecognition_test: RuntimeError # Please triage.
 
@@ -57,9 +62,6 @@
 html/js_typed_interop_rename_static_test: RuntimeError
 html/worker_test/functional: RuntimeError # Issue 32261
 
-[ $compiler == dart2js && $runtime == chrome && $strong ]
-html/interactive_media_test: RuntimeError
-
 [ $compiler == dart2js && $runtime == chromeOnAndroid ]
 html/audiobuffersourcenode_test/supported: Fail # TODO(dart2js-team): Please triage this failure.
 html/audiocontext_test/supported: RuntimeError # TODO(dart2js-team): Please triage this failure.
@@ -79,7 +81,6 @@
 
 [ $compiler == dart2js && $runtime == d8 ]
 async/dart2js_uncaught_error_test: RuntimeError
-html/async_spawnuri_test: RuntimeError
 html/async_test: RuntimeError
 html/audiobuffersourcenode_test: RuntimeError
 html/audiocontext_test: RuntimeError
@@ -316,9 +317,6 @@
 html/input_element_attributes_test: RuntimeError
 html/js_extend_class_test: RuntimeError
 
-[ $compiler == dart2js && $runtime != d8 && !$strong ]
-html/js_dart_functions_test: RuntimeError # does not implement Dart 2 implicit `.call` tearoff
-
 [ $compiler == dart2js && $runtime == ff ]
 async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
 convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Times out. Issue 22050
@@ -340,6 +338,7 @@
 html/fileapi_supported_test: Skip # FileSystem not supported on FireFox.
 html/fileapi_supported_throws_test: Skip # FileSystem not supported on FireFox.
 html/fontface_test: Fail # Fontface not supported on ff
+html/gamepad_test: RuntimeError
 html/history_test/history: Skip # Issue 22050
 html/input_element_datetime_test: Fail
 html/input_element_month_test: Fail
@@ -354,10 +353,6 @@
 html/text_event_test: Fail # Issue 17893
 html/webgl_1_test: Pass, Fail # Issue 8219
 
-[ $compiler == dart2js && $runtime == ff && $strong ]
-html/gamepad_test: RuntimeError
-html/interactive_media_test: RuntimeError
-
 [ $compiler == dart2js && $runtime == ie11 ]
 html/element_types_content_test: RuntimeError # Issue 29922
 html/element_types_datalist_test: RuntimeError # Issue 29922
@@ -428,7 +423,12 @@
 
 [ $compiler == dart2js && $runtime == safari ]
 html/audiobuffersourcenode_test: RuntimeError
+html/audiobuffersourcenode_test: Pass, RuntimeError
 html/callback_list_test: SkipByDesign # FileSystem not supported in Safari.
+html/canvasrenderingcontext2d_test/arc: Pass, RuntimeError
+html/canvasrenderingcontext2d_test/drawImage_canvas_element: Pass, RuntimeError
+html/canvasrenderingcontext2d_test/drawImage_image_element: Pass, RuntimeError
+html/canvasrenderingcontext2d_test/fillText: Pass, RuntimeError
 html/css_test/functional/functional: RuntimeError # Issue 32576
 html/custom/attribute_changed_callback_test: RuntimeError, Timeout
 html/custom/constructor_calls_created_synchronously_test: Pass, Timeout
@@ -439,26 +439,10 @@
 html/element_types_shadow_test: RuntimeError # Issue 29922
 html/file_sample_test: Skip # FileSystem not supported on Safari.
 html/fileapi_supported_throws_test: Skip # FileSystem not supported on Safari
-html/storage_promise_test: RuntimeError # Not supported on Safari
-html/xhr_test: RuntimeError
-
-[ $compiler == dart2js && $runtime == safari && $strong ]
-html/audiobuffersourcenode_test: Pass, RuntimeError
-html/canvasrenderingcontext2d_test/arc: Pass, RuntimeError
-html/canvasrenderingcontext2d_test/drawImage_canvas_element: Pass, RuntimeError
-html/canvasrenderingcontext2d_test/drawImage_image_element: Pass, RuntimeError
-html/canvasrenderingcontext2d_test/fillText: Pass, RuntimeError
 html/interactive_media_test: SkipSlow
 html/notification_test: Pass, RuntimeError # Safari doesn't let us access the fields of the Notification to verify them.
-
-[ $compiler == dart2js && $runtime == safari && !$strong ]
-convert/json_test: Fail # https://bugs.webkit.org/show_bug.cgi?id=134920
-html/fontface_loaded_test: RuntimeError # FontFace polyfill?
-html/fontface_test: Fail # FontFace polyfill?
-html/notification_test: Fail # Safari doesn't let us access the fields of the Notification to verify them.
-
-[ $compiler == dart2js && $runtime != safari && !$strong ]
-html/element_classes_test: RuntimeError
+html/storage_promise_test: RuntimeError # Not supported on Safari
+html/xhr_test: RuntimeError
 
 [ $compiler == dart2js && $system == linux ]
 html/interactive_geolocation_test: Skip # Requires allowing geo location.
@@ -468,20 +452,18 @@
 
 [ $compiler == dart2js && $browser ]
 html/custom/created_callback_test: RuntimeError
+html/element_classes_svg_test: RuntimeError
+html/js_array_test: RuntimeError
 html/js_typed_interop_lazy_test/01: RuntimeError
 html/notification_permission_test: Timeout, Pass # Issue 32002
 html/private_extension_member_test: RuntimeError
+html/typed_arrays_range_checks_test: RuntimeError
 js/null_test: RuntimeError # Issue 30652
 
 [ $compiler == dart2js && $browser && $csp ]
 html/custom/element_upgrade_test: Fail # Issue 17298
 html/custom/js_custom_test: Fail # Issue 14643
 
-[ $compiler == dart2js && $browser && $strong ]
-html/element_classes_svg_test: RuntimeError
-html/js_array_test: RuntimeError
-html/typed_arrays_range_checks_test: RuntimeError
-
 [ $compiler == dart2js && $checked ]
 async/stream_listen_zone_test: RuntimeError
 convert/utf85_test: Pass, Slow # Issue 12029.
@@ -510,7 +492,6 @@
 html/postmessage_structured_test: SkipByDesign
 
 [ $compiler == dart2js && !$csp && $minified ]
-html/async_spawnuri_test: RuntimeError
 html/async_test: RuntimeError
 html/audiobuffersourcenode_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
 html/audiocontext_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
@@ -671,8 +652,6 @@
 [ $compiler == dart2js && $ie ]
 html/fontface_loaded_test: RuntimeError # FontFace polyfill?
 html/fontface_test: Fail # Fontface not supported on ie
-
-[ $compiler == dart2js && $ie && $strong ]
 html/interactive_media_test: RuntimeError
 
 [ $compiler == dart2js && $minified ]
@@ -752,17 +731,6 @@
 html/typed_arrays_1_test/supported: RuntimeError
 html/webgl_1_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
 
-[ $compiler == dart2js && $strong ]
-async/future_or_type_test: RuntimeError
-async/slow_consumer2_test: RuntimeError
-async/stream_distinct_test: RuntimeError
-collection/list_test: RuntimeError
-html/element_classes_test: RuntimeError
-
-[ $compiler == dart2js && !$strong ]
-html/custom/element_upgrade_failure_test: MissingCompileTimeError
-html/element_classes_svg_test: RuntimeError # Expected runtime type check only in strong mode.
-
 [ $compiler == dart2js && ($runtime == chrome || $runtime == ff) ]
 async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
 convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Times out. Issue 22050
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index 0532e64..4b47ff6 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -41,7 +41,6 @@
 convert/streamed_conversion_json_utf8_encode_test: Pass, Timeout # Issue 29922
 convert/streamed_conversion_utf8_decode_test: Slow, Pass, Timeout # Issue 29922
 convert/utf85_test: Slow, Pass
-html/async_spawnuri_test: RuntimeError # Issue 29922
 html/async_test: RuntimeError # Issue 29922
 html/callback_list_test: Skip # Test requires user interaction to accept permissions.
 html/custom/attribute_changed_callback_test: Skip # Issue 31577
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index 04313d4..c52f96f 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -17,12 +17,28 @@
 isolate/ping_pause_test: Skip # Timeout
 
 [ $compiler == dartkb ]
+convert/streamed_conversion_json_utf8_decode_test: Pass, Timeout # Please triage.
+isolate/isolate_complex_messages_test: Pass, Crash # runtime/vm/object.cc: 17395: error: expected: type_arguments.IsNull() || type_arguments.IsCanonical()
+isolate/mandel_isolate_test: Pass, Timeout # Please triage.
+isolate/spawn_uri_exported_main_test: Pass, RuntimeError # Please triage: Expect.fail('Isolate was not spawned successfully.')
 mirrors/*: Skip # Mirrors are not yet supported in bytecode modes.
+mirrors/invocation_fuzz_test/emptyarray: Skip # Times out, issue 32232
+mirrors/invocation_fuzz_test/false: Skip # Times out, issue 32232
+mirrors/library_uri_io_test: RuntimeError # Platform.script points to dill file.
+mirrors/method_mirror_location_test: Crash # runtime/lib/mirrors.cc: 1634: error: expected: token_pos != TokenPosition::kNoSource
 
 [ $compiler == fasta ]
 html/*: Skip # TODO(ahe): Make dart:html available.
-isolate/browser/*: Skip # TODO(ahe): Make dart:html available.
+isolate/isolate_stress_test: CompileTimeError
 js/*: Skip # TODO(ahe): Make dart:js available.
+mirrors/deferred_type_test: CompileTimeError
+mirrors/metadata_allowed_values_test/02: MissingCompileTimeError
+mirrors/metadata_allowed_values_test/27: MissingCompileTimeError
+mirrors/metadata_constructor_arguments_test/04: MissingCompileTimeError
+mirrors/mirrors_nsm_mismatch_test: CompileTimeError
+mirrors/mirrors_nsm_test/dart2js: CompileTimeError
+mirrors/mirrors_nsm_test/none: CompileTimeError
+mirrors/native_class_test: CompileTimeError
 
 [ $fasta ]
 async/future_or_type_test: CompileTimeError # Issue 34626
@@ -32,19 +48,19 @@
 mirrors/redirecting_factory_test/01: CompileTimeError # Issue 34714
 mirrors/redirecting_factory_test/none: CompileTimeError # Issue 34714
 
-[ $arch == simdbc64 && $mode == debug && $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $arch == simdbc64 && $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
 isolate/isolate_complex_messages_test: Crash # http://dartbug.com/33128
 
 [ $arch == simdbc64 && $hot_reload_rollback ]
 convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Uses --verify_before_gc --verify_after_gc --old_gen_growth_rate=1 flags
 
-[ $arch == simdbc64 && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $arch == simdbc64 && ($compiler == dartk || $compiler == dartkb) ]
 isolate/issue_24243_parent_isolate_test: RuntimeError # dartbug.com/35373
 
 [ $arch == x64 && $builder_tag == asan && $compiler == dartk ]
 mirrors/dynamic_load_test: Fail # Memory leak (issue 34724)
 
-[ $arch == x64 && $mode == debug && $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $arch == x64 && $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
 mirrors/invocation_fuzz_test: Skip # Because it times out, issue 29439.
 
 [ $arch == x64 && ($hot_reload || $hot_reload_rollback) ]
@@ -65,28 +81,11 @@
 [ $compiler == app_jitk && ($mode == product || $mode == release) ]
 isolate/spawn_uri_nested_vm_test: Skip # Timeout, Issue 33385
 
-[ $compiler != dart2js && $fasta && !$strong ]
-isolate/browser/compute_this_script_browser_test: CompileTimeError
-isolate/browser/package_resolve_browser_hook2_test: CompileTimeError
-isolate/browser/package_resolve_browser_hook_test: CompileTimeError
-isolate/browser/package_resolve_browser_test: CompileTimeError
-
-# The failures below still need to be investigated and possibly fixed, or marked as skipped.
-[ $compiler == dartkb && $strong ]
-convert/streamed_conversion_json_utf8_decode_test: Pass, Timeout # Please triage.
-isolate/isolate_complex_messages_test: Pass, Crash # runtime/vm/object.cc: 17395: error: expected: type_arguments.IsNull() || type_arguments.IsCanonical()
-isolate/mandel_isolate_test: Pass, Timeout # Please triage.
-isolate/spawn_uri_exported_main_test: Pass, RuntimeError # Please triage: Expect.fail('Isolate was not spawned successfully.')
-mirrors/invocation_fuzz_test/emptyarray: Skip # Times out, issue 32232
-mirrors/invocation_fuzz_test/false: Skip # Times out, issue 32232
-mirrors/library_uri_io_test: RuntimeError # Platform.script points to dill file.
-mirrors/method_mirror_location_test: Crash # runtime/lib/mirrors.cc: 1634: error: expected: token_pos != TokenPosition::kNoSource
-
-[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
+[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
 isolate/static_function_test: Skip # Flaky (https://github.com/dart-lang/sdk/issues/30063).
 
 # ===== dartkp + dart_precompiled status lines =====
-[ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
+[ $compiler == dartkp && $runtime == dart_precompiled ]
 async/slow_consumer2_test: RuntimeError # Issue 31402 (Invocation arguments)
 async/stream_distinct_test: RuntimeError
 async/timer_not_available_test: RuntimeError
@@ -98,32 +97,18 @@
 isolate/spawn_uri_nested_vm_test: Pass, Timeout
 mirrors/*: SkipByDesign # Mirrors are not supported in AOT mode.
 
-[ $compiler == dartkp && !$strong ]
-*: SkipByDesign
-
-[ $compiler == fasta && $strong ]
-isolate/isolate_stress_test: CompileTimeError
-mirrors/deferred_type_test: CompileTimeError
-mirrors/metadata_allowed_values_test/02: MissingCompileTimeError
-mirrors/metadata_allowed_values_test/27: MissingCompileTimeError
-mirrors/metadata_constructor_arguments_test/04: MissingCompileTimeError
-mirrors/mirrors_nsm_mismatch_test: CompileTimeError
-mirrors/mirrors_nsm_test/dart2js: CompileTimeError
-mirrors/mirrors_nsm_test/none: CompileTimeError
-mirrors/native_class_test: CompileTimeError
-
-[ $mode == debug && $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
 mirrors/other_declarations_location_test: Crash # Issue 33325 (assertion error, TypeParameter not having position).
 
 [ $mode == debug && $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
 isolate/message3_test/constList_identical: Skip # Timeout
 
-[ $runtime == vm && $checked && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $runtime == vm && $checked && ($compiler == dartk || $compiler == dartkb) ]
 mirrors/redirecting_factory_different_type_test/none: RuntimeError # Issue 28424
 mirrors/reflected_type_generics_test/02: Pass
 
 # ===== dartk + vm status lines =====
-[ $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
 async/slow_consumer2_test: CompileTimeError # Issue 31402 (Invocation arguments)
 async/timer_not_available_test: RuntimeError
 html/*: SkipByDesign # dart:html not supported on VM.
@@ -172,7 +157,6 @@
 mirrors/mirrors_nsm_mismatch_test: CompileTimeError # Issue 31533
 mirrors/mirrors_nsm_test/dart2js: CompileTimeError # Issue 31533
 mirrors/mirrors_nsm_test/none: CompileTimeError # Issue 31533
-mirrors/mirrors_reader_test: Crash
 mirrors/mirrors_test: RuntimeError
 mirrors/mirrors_used*: SkipByDesign # Invalid tests. MirrorsUsed does not have a specification, and dart:mirrors is not required to hide declarations that are not covered by any MirrorsUsed annotation.
 mirrors/mirrors_used_inheritance_test: RuntimeError
@@ -215,25 +199,6 @@
 mirrors/typedef_test: RuntimeError
 mirrors/typevariable_mirror_metadata_test: RuntimeError
 
-[ $fasta && !$strong ]
-isolate/isolate_import_test/01: MissingCompileTimeError
-isolate/isolate_stress_test: CompileTimeError
-mirrors/generics_test/01: MissingCompileTimeError
-mirrors/metadata_allowed_values_test/02: MissingCompileTimeError
-mirrors/metadata_allowed_values_test/27: MissingCompileTimeError
-mirrors/metadata_constructor_arguments_test/04: MissingCompileTimeError
-mirrors/native_class_test: CompileTimeError
-mirrors/redirecting_factory_different_type_test/01: MissingCompileTimeError
-mirrors/reflect_class_test/01: MissingCompileTimeError
-mirrors/reflect_class_test/02: MissingCompileTimeError
-mirrors/reflected_type_classes_test/01: MissingCompileTimeError
-mirrors/reflected_type_test/01: MissingCompileTimeError
-mirrors/regress_16321_test/01: MissingCompileTimeError
-mirrors/top_level_accessors_test/01: MissingCompileTimeError
-typed_data/float32x4_static_test: MissingCompileTimeError
-typed_data/int32x4_static_test/01: MissingCompileTimeError
-typed_data/int32x4_static_test/02: MissingCompileTimeError
-
 [ $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
 isolate/illegal_msg_function_test: Skip # Timeout
 isolate/pause_test: Skip # Timeout
@@ -241,15 +206,27 @@
 # Enabling of dartk for sim{arm,arm64,dbc64} revealed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
 # batch mode.
-[ $strong && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ]
+[ ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ]
 isolate/mandel_isolate_test: Pass, Timeout
 isolate/nested_spawn2_test: Pass, RuntimeError # RuntimeError caused by timeout
 mirrors/library_uri_io_test: RuntimeError # Please triage.
 
-[ $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
+isolate/mandel_isolate_test: Pass, Timeout, RuntimeError # Test can time out which results in runtime error
+isolate/message4_test: Pass, Timeout, Crash # Timeout and sporadic crash (issue 33824)
+mirrors/dynamic_load_test: Crash
+mirrors/library_uri_io_test: Skip # Timeout
+mirrors/library_uri_package_test: Skip # Timeout
+
+[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkb || $compiler == dartkp ]
+html/*: SkipByDesign
+js/*: SkipByDesign
+
+[ $compiler == dartk || $compiler == dartkb ]
 async/slow_consumer2_test: RuntimeError # Issue 31402 (Invocation arguments)
 async/stream_distinct_test: RuntimeError
 isolate/ping_pause_test: RuntimeError
+isolate/ping_pause_test: Skip # Issues 32137 and 32138
 isolate/request_reply_test: Pass, Timeout
 isolate/stacktrace_message_test: RuntimeError
 mirrors/constructor_optional_args_test: RuntimeError
@@ -265,24 +242,5 @@
 mirrors/redirecting_factory_different_type_test/none: RuntimeError
 mirrors/redirecting_factory_reflection_test: RuntimeError
 
-# ===== Skip dartk and darkp in !$strong mode ====
-[ !$strong && ($compiler == dartk || $compiler == dartkb) ]
-*: SkipByDesign
-
-[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
-isolate/mandel_isolate_test: Pass, Timeout, RuntimeError # Test can time out which results in runtime error
-isolate/message4_test: Pass, Timeout, Crash # Timeout and sporadic crash (issue 33824)
-mirrors/dynamic_load_test: Crash
-mirrors/library_uri_io_test: Skip # Timeout
-mirrors/library_uri_package_test: Skip # Timeout
-
-[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkb || $compiler == dartkp ]
-html/*: SkipByDesign
-isolate/browser/*: SkipByDesign
-js/*: SkipByDesign
-
-[ $compiler == dartk || $compiler == dartkb ]
-isolate/ping_pause_test: Skip # Issues 32137 and 32138
-
 [ $hot_reload || $hot_reload_rollback ]
 isolate/issue_6610_test: Skip # Sources are looked up on every reload request.
diff --git a/tests/lib_2/lib_2_vm.status b/tests/lib_2/lib_2_vm.status
index a652e636..869e7c8 100644
--- a/tests/lib_2/lib_2_vm.status
+++ b/tests/lib_2/lib_2_vm.status
@@ -18,6 +18,7 @@
 convert/utf85_test: Skip # Pass, Slow Issue 20111.
 
 [ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $runtime == vm ]
+async/future_or_only_in_async_test/00: MissingCompileTimeError
 convert/streamed_conversion_json_utf8_decode_test: Pass, Slow # Infrequent timeouts.
 html/*: SkipByDesign # dart:html not supported on VM.
 js/datetime_roundtrip_test: CompileTimeError
@@ -40,24 +41,6 @@
 [ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $runtime == vm && !$checked ]
 mirrors/inference_and_no_such_method_test: RuntimeError
 
-[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $runtime == vm && $strong ]
-async/future_or_only_in_async_test/00: MissingCompileTimeError
-
-[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $runtime == vm && !$strong ]
-mirrors/redirecting_factory_test/02: MissingCompileTimeError
-mirrors/redirecting_factory_test/03: MissingCompileTimeError
-mirrors/redirecting_factory_test/04: MissingCompileTimeError
-
-[ $compiler != dartk && $compiler != dartkb && $runtime == vm && !$strong ]
-mirrors/reflect_class_test/01: MissingCompileTimeError
-mirrors/reflect_class_test/02: MissingCompileTimeError
-mirrors/reflected_type_classes_test/01: MissingCompileTimeError
-mirrors/reflected_type_classes_test/02: MissingCompileTimeError
-mirrors/reflected_type_classes_test/03: MissingCompileTimeError
-mirrors/reflected_type_test/01: MissingCompileTimeError
-mirrors/reflected_type_test/02: MissingCompileTimeError
-mirrors/reflected_type_test/03: MissingCompileTimeError
-
 [ $runtime == vm && $system == fuchsia ]
 async/first_regression_test: RuntimeError
 async/future_timeout_test: RuntimeError
@@ -96,9 +79,6 @@
 mirrors/library_uri_io_test: RuntimeError
 mirrors/library_uri_package_test: RuntimeError
 
-[ $runtime == vm && !$checked && !$strong ]
-mirrors/regress_16321_test/01: MissingCompileTimeError
-
 [ $runtime == vm && $no_preview_dart_2 ]
 async/async_no_await_zones_test: RuntimeError # not supported in Dart 1 mode.
 
diff --git a/tests/lib_2/mirrors/library_uri_io_test.dart b/tests/lib_2/mirrors/library_uri_io_test.dart
index 74553b4..e072a83 100644
--- a/tests/lib_2/mirrors/library_uri_io_test.dart
+++ b/tests/lib_2/mirrors/library_uri_io_test.dart
@@ -9,7 +9,7 @@
 import 'dart:io';
 import 'dart:mirrors';
 
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 class Class {}
 
diff --git a/tests/lib_2/mirrors/library_uri_package_test.dart b/tests/lib_2/mirrors/library_uri_package_test.dart
index f9db81d..a8be56d 100644
--- a/tests/lib_2/mirrors/library_uri_package_test.dart
+++ b/tests/lib_2/mirrors/library_uri_package_test.dart
@@ -8,7 +8,7 @@
 
 import 'dart:mirrors';
 import 'package:args/args.dart';
-import 'package:expect/async_minitest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 testLibraryUri(var value, Uri expectedUri) {
   var valueMirror = reflect(value);
diff --git a/tests/modular/int_js_number/def.dart b/tests/modular/int_js_number/def.dart
new file mode 100644
index 0000000..0fd7377
--- /dev/null
+++ b/tests/modular/int_js_number/def.dart
@@ -0,0 +1,4 @@
+// Copyright (c) 2019, 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.
+const int foo = 331;
diff --git a/tests/modular/int_js_number/main.dart b/tests/modular/int_js_number/main.dart
new file mode 100644
index 0000000..6352c3d
--- /dev/null
+++ b/tests/modular/int_js_number/main.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2019, 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 'def.dart';
+
+main() {
+  print(const <int>[foo]);
+}
diff --git a/tests/modular/int_js_number/modules.yaml b/tests/modular/int_js_number/modules.yaml
new file mode 100644
index 0000000..e8cdeea
--- /dev/null
+++ b/tests/modular/int_js_number/modules.yaml
@@ -0,0 +1,10 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+#
+# Regression test: integral numbers should be treated as int and not double
+# after serialization across modules.
+dependencies:
+  main: def
+flags:
+  - constant-update-2018
diff --git a/tests/modular/js_interop/.packages b/tests/modular/js_interop/.packages
new file mode 100644
index 0000000..fce126f
--- /dev/null
+++ b/tests/modular/js_interop/.packages
@@ -0,0 +1 @@
+js:../../../pkg/js/lib
diff --git a/tests/modular/js_interop/log.dart b/tests/modular/js_interop/log.dart
new file mode 100644
index 0000000..f69bf62
--- /dev/null
+++ b/tests/modular/js_interop/log.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+
+/// Calls to [console.log] and to [log] from other modules don't work if the
+/// js-interop annotations are not preserved. However, calls via [log2] and
+/// [log3] do work because the annotation is available when compiling this
+/// module.
+@JS()
+library log;
+
+import 'package:js/js.dart';
+
+@JS()
+class Console {
+  @JS()
+  external void log(arg);
+}
+
+@JS('console')
+external Console get console;
+
+@JS('console.log')
+external void log(String s);
+
+void log2(String s) => log(s);
+void log3(String s) => console.log(s);
diff --git a/tests/modular/js_interop/main.dart b/tests/modular/js_interop/main.dart
new file mode 100644
index 0000000..f0d26c2
--- /dev/null
+++ b/tests/modular/js_interop/main.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2019, 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 'log.dart';
+
+void main() {
+  log2('A');
+  log3('B');
+  log('C');
+  console.log('D');
+}
diff --git a/tests/modular/js_interop/modules.yaml b/tests/modular/js_interop/modules.yaml
new file mode 100644
index 0000000..021eddc
--- /dev/null
+++ b/tests/modular/js_interop/modules.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+#
+# Regression test: js-interop annotations need to be preserved in outline files.
+dependencies:
+  main: log
+  log: js
diff --git a/tests/modular/package_imports/.packages b/tests/modular/package_imports/.packages
new file mode 100644
index 0000000..3da0bf2
--- /dev/null
+++ b/tests/modular/package_imports/.packages
@@ -0,0 +1,6 @@
+# Copyright (c) 2019, 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.
+f0:.
+f1:.
+a:a
diff --git a/tests/modular/package_imports/a/a.dart b/tests/modular/package_imports/a/a.dart
new file mode 100644
index 0000000..3a62c13
--- /dev/null
+++ b/tests/modular/package_imports/a/a.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2019, 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:f1/f1.dart';
+
+int z = y + 100;
diff --git a/tests/modular/package_imports/f0.dart b/tests/modular/package_imports/f0.dart
new file mode 100644
index 0000000..27b7873
--- /dev/null
+++ b/tests/modular/package_imports/f0.dart
@@ -0,0 +1,4 @@
+// Copyright (c) 2019, 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.
+int x = 1;
diff --git a/tests/modular/package_imports/f1.dart b/tests/modular/package_imports/f1.dart
new file mode 100644
index 0000000..0eeb9f8
--- /dev/null
+++ b/tests/modular/package_imports/f1.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2019, 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:f0/f0.dart';
+
+int y = x + 10;
diff --git a/tests/modular/package_imports/f3.dart b/tests/modular/package_imports/f3.dart
new file mode 100644
index 0000000..72965f8
--- /dev/null
+++ b/tests/modular/package_imports/f3.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2019, 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:a/a.dart';
+
+int w = z + 1000;
diff --git a/tests/modular/package_imports/main.dart b/tests/modular/package_imports/main.dart
new file mode 100644
index 0000000..7dcee7a
--- /dev/null
+++ b/tests/modular/package_imports/main.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2019, 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 'f3.dart';
+import 'package:expect/expect.dart';
+
+main() {
+  print(w);
+  Expect.isTrue(w == 1111);
+}
diff --git a/tests/modular/package_imports/modules.yaml b/tests/modular/package_imports/modules.yaml
new file mode 100644
index 0000000..a8731e9
--- /dev/null
+++ b/tests/modular/package_imports/modules.yaml
@@ -0,0 +1,13 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+#
+# Test ensuring that the modular compiler works properly with `package:`
+# imports. This test also ensures that the dart2js implementation of the modular
+# test pipeline works as intended. The test is not designed to cover any
+# compiler or language feature explicitly.
+dependencies:
+  main: [f3, expect]
+  f3: a
+  a: f1
+  f1: f0
diff --git a/tests/modular/subclass/a/a.dart b/tests/modular/subclass/a/a.dart
new file mode 100644
index 0000000..e393550
--- /dev/null
+++ b/tests/modular/subclass/a/a.dart
@@ -0,0 +1,4 @@
+// Copyright (c) 2019, 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.
+const x = 1;
diff --git a/tests/modular/subclass/f0.dart b/tests/modular/subclass/f0.dart
new file mode 100644
index 0000000..113a6ff
--- /dev/null
+++ b/tests/modular/subclass/f0.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2019, 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.
+class A0 {
+  StringBuffer buffer = new StringBuffer()..write("hello ");
+}
diff --git a/tests/modular/subclass/f1.dart b/tests/modular/subclass/f1.dart
new file mode 100644
index 0000000..00f7709
--- /dev/null
+++ b/tests/modular/subclass/f1.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2019, 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 'f0.dart';
+
+class B1 extends A0 {
+  A0 get foo => null;
+}
+
+A0 createA0() => new A0();
diff --git a/tests/modular/subclass/main.dart b/tests/modular/subclass/main.dart
new file mode 100644
index 0000000..090de94
--- /dev/null
+++ b/tests/modular/subclass/main.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, 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 'f1.dart';
+import 'a/a.dart';
+
+class C2 extends B1 {
+  final foo = createA0();
+}
+
+main() {
+  var buffer = new C2().foo.buffer;
+
+  buffer.write('world! $x');
+  print(buffer.toString());
+}
diff --git a/tests/modular/subclass/modules.yaml b/tests/modular/subclass/modules.yaml
new file mode 100644
index 0000000..70606e9
--- /dev/null
+++ b/tests/modular/subclass/modules.yaml
@@ -0,0 +1,9 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+#
+# Test illustrating how the modular pipeline works. This test is not designed to
+# stress any specific feature of the compiler.
+dependencies:
+  f1: f0
+  main: [f1, a]
diff --git a/tests/standalone_2/io/code_collection_test.dart b/tests/standalone_2/io/code_collection_test.dart
deleted file mode 100644
index 71f36b6..0000000
--- a/tests/standalone_2/io/code_collection_test.dart
+++ /dev/null
@@ -1,103 +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.
-
-// Dart test program testing code GC.
-
-import "package:expect/expect.dart";
-import "dart:async";
-import "dart:io";
-
-int foo(int x) {
-  x = x + 1;
-  // Print marker message while foo is on the stack so the code cannot be
-  // collected.
-  stderr.write("foo=$x\n");
-  return x;
-}
-
-List<int> bar() {
-  // A couple of big allocations trigger GC.
-  var l = new List.filled(700000, 7);
-  return l;
-}
-
-doTest() {
-  var i = 0;
-  var ret = foo(1); // Initial call to compile.
-  // Time passes, GC runs, foo's code is dropped.
-  var ms = const Duration(milliseconds: 100);
-  var t = new Timer.periodic(ms, (timer) {
-    i++;
-    // Calling bar will trigger GC without foo being on the stack. This way
-    // the method can be collected.
-    bar();
-    if (i > 1) {
-      timer.cancel();
-      // foo is called again to make sure we can still run it even after
-      // its code has been detached.
-      var ret = foo(2);
-      // GC after here may collect the second compilation of foo.
-    }
-  });
-}
-
-List<String> packageOptions() {
-  if (Platform.packageRoot != null) {
-    return <String>['--package-root=${Platform.packageRoot}'];
-  } else if (Platform.packageConfig != null) {
-    return <String>['--packages=${Platform.packageConfig}'];
-  } else {
-    return <String>[];
-  }
-}
-
-main(List<String> arguments) {
-  if (arguments.contains("--run")) {
-    doTest();
-  } else {
-    // Run the test and capture stderr.
-    var args = packageOptions();
-    args.addAll([
-      "--verbose-gc",
-      "--collect-code",
-      "--code-collection-interval-in-us=0",
-      "--old_gen_growth_rate=10",
-      "--log-code-drop",
-      "--optimization-counter-threshold=-1",
-      Platform.script.toFilePath(),
-      "--run"
-    ]);
-    print("+ ${Platform.executable} ${args.join(' ')}");
-    var pr = Process.runSync(Platform.executable, args);
-
-    print(pr.stderr);
-    Expect.equals(0, pr.exitCode);
-
-    // Code drops are logged with --log-code-drop. Look through stderr for the
-    // message that foo's code was dropped.
-    bool saw_foo2 = false;
-    bool saw_detaching_foo = false;
-    bool saw_foo3 = false;
-    pr.stderr.split("\n").forEach((line) {
-      if (line.contains("foo=2")) {
-        Expect.isFalse(saw_foo2, "foo=2 ran twice");
-        saw_foo2 = true;
-      }
-      if (line.contains("Detaching code") && line.contains("foo")) {
-        Expect.isTrue(saw_foo2, "foo detached before running");
-        // May detach twice.
-        saw_detaching_foo = true;
-      }
-      if (line.contains("foo=3")) {
-        Expect.isFalse(saw_foo3, "foo=3 ran twice");
-        Expect.isTrue(saw_detaching_foo, "foo should have been collected");
-        saw_foo3 = true;
-      }
-    });
-
-    Expect.isTrue(saw_foo2, "Missing foo=2");
-    Expect.isTrue(saw_detaching_foo, "Missing code collection for foo");
-    Expect.isTrue(saw_foo3, "Missing foo=3");
-  }
-}
diff --git a/tests/standalone_2/io/http_cookie_date_test.dart b/tests/standalone_2/io/http_cookie_date_test.dart
index 112d700..621d9e5 100644
--- a/tests/standalone_2/io/http_cookie_date_test.dart
+++ b/tests/standalone_2/io/http_cookie_date_test.dart
@@ -2,14 +2,12 @@
 // 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 dart.http;
+library dart._http;
 
 import "dart:async";
 import "dart:collection";
 import "dart:convert";
-import "dart:developer";
 import "dart:io";
-import "dart:isolate";
 import "dart:math";
 import "dart:typed_data";
 import "package:expect/expect.dart";
diff --git a/tests/standalone_2/io/http_cookie_test.dart b/tests/standalone_2/io/http_cookie_test.dart
index 50cad66..bfe9302 100644
--- a/tests/standalone_2/io/http_cookie_test.dart
+++ b/tests/standalone_2/io/http_cookie_test.dart
@@ -2,8 +2,8 @@
 // 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:io";
+
 import "package:expect/expect.dart";
 
 void testCookies() {
@@ -59,12 +59,28 @@
 }
 
 void testValidateCookieWithDoubleQuotes() {
-  try {
-    Cookie cookie = Cookie('key', '"double-quoted-value"');
-  } catch (e) {
-    Expect.fail("Unexpected error $e.\n"
-        "Unable to parse cookie with value in double-quote characters.");
-  }
+  Expect.equals(Cookie('key', 'value').toString(), 'key=value; HttpOnly');
+  Expect.equals(Cookie('key', '').toString(), 'key=; HttpOnly');
+  Expect.equals(Cookie('key', '""').toString(), 'key=""; HttpOnly');
+  Expect.equals(Cookie('key', '"value"').toString(), 'key="value"; HttpOnly');
+  Expect.equals(Cookie.fromSetCookieValue('key=value; HttpOnly').toString(),
+      'key=value; HttpOnly');
+  Expect.equals(
+      Cookie.fromSetCookieValue('key=; HttpOnly').toString(), 'key=; HttpOnly');
+  Expect.equals(Cookie.fromSetCookieValue('key=""; HttpOnly').toString(),
+      'key=""; HttpOnly');
+  Expect.equals(Cookie.fromSetCookieValue('key="value"; HttpOnly').toString(),
+      'key="value"; HttpOnly');
+  Expect.throwsFormatException(() => Cookie('key', '"'));
+  Expect.throwsFormatException(() => Cookie('key', '"""'));
+  Expect.throwsFormatException(() => Cookie('key', '"x""'));
+  Expect.throwsFormatException(() => Cookie('key', '"x"y"'));
+  Expect.throwsFormatException(
+      () => Cookie.fromSetCookieValue('key="; HttpOnly'));
+  Expect.throwsFormatException(
+      () => Cookie.fromSetCookieValue('key="""; HttpOnly'));
+  Expect.throwsFormatException(
+      () => Cookie.fromSetCookieValue('key="x""; HttpOnly'));
 }
 
 void main() {
diff --git a/tests/standalone_2/io/raw_socket_test.dart b/tests/standalone_2/io/raw_socket_test.dart
index d46d1d6..cf8087d 100644
--- a/tests/standalone_2/io/raw_socket_test.dart
+++ b/tests/standalone_2/io/raw_socket_test.dart
@@ -79,13 +79,14 @@
   RawSocket.startConnect(InternetAddress.loopbackIPv4, 0)
       .then((ConnectionTask<RawSocket> task) {
     task.cancel();
-    task.socket.catchError((error) {
-      Expect.isTrue(error is SocketException);
-      asyncEnd();
-    });
     task.socket.then((s) {
       Expect.fail("Unreachable");
+    }, onError: (e) {
+      Expect.isTrue(e is SocketException);
+      asyncEnd();
     });
+  }, onError: (e) {
+    Expect.fail("Unreachable");
   });
 }
 
@@ -474,6 +475,21 @@
   });
 }
 
+void testClosedServer() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    int port = server.port;
+    server.close().then((_) {
+      RawSocket.connect(InternetAddress.loopbackIPv4, server.port).then((_) {
+        Expect.fail('Connecting to the closed server socket should fail');
+      }, onError: (e) {
+        Expect.isTrue(e is SocketException);
+        asyncEnd();
+      });
+    });
+  });
+}
+
 main() {
   asyncStart();
   testArguments();
@@ -491,5 +507,6 @@
   testSocketZone();
   testSocketZoneError();
   testClosedError();
+  testClosedServer();
   asyncEnd();
 }
diff --git a/tests/standalone_2/standalone_2.status b/tests/standalone_2/standalone_2.status
index 74d303c..10647f5 100644
--- a/tests/standalone_2/standalone_2.status
+++ b/tests/standalone_2/standalone_2.status
@@ -68,14 +68,11 @@
 io/wait_for_event_zone_test: SkipByDesign # Uses mirrors.
 io/wait_for_test: SkipByDesign # Uses mirrors.
 
-[ !$strong ]
-float_array_static_test: MissingCompileTimeError
-
 [ $builder_tag == swarming && $system == macos ]
 io/*: Skip # Issue 30618
 
 # All static_tests have expected compile-time errors.
-[ $compiler != app_jitk && $compiler != dart2analyzer && $compiler != dartdevc && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $runtime != none && $strong ]
+[ $compiler != app_jitk && $compiler != dart2analyzer && $compiler != dartdevc && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $runtime != none ]
 float_array_static_test: MissingCompileTimeError
 
 [ $compiler == none && $runtime == vm && $system == fuchsia ]
@@ -91,9 +88,6 @@
 [ $mode == release && $runtime == vm && $system == macos ]
 io/named_pipe_script_test: Pass, RuntimeError # Issue 28737
 
-[ $runtime == none && !$strong ]
-io/process_exit_negative_test: Fail, OK # Must be run to exit with non-zero exit code.
-
 [ $runtime == vm && $system == linux ]
 io/http_basic_test: Pass, Slow, Timeout # Issue 28046, These tests might be slow on an opt counter threshold bot. They also time out on the bot occasionally => flaky test issue 28046
 io/http_launch_test: Pass, Slow, Timeout # Issue 28046, These tests might be slow on an opt counter threshold bot. They also time out on the bot occasionally => flaky test issue 28046
@@ -108,7 +102,13 @@
 [ !$preview_dart_2 && ($runtime == dart_precompiled || $runtime == vm) ]
 *: SkipByDesign # Deprecating all Dart1 modes of execution
 
-[ $strong && ($compiler == dartk || $compiler == dartkb || $compiler == dartkp) ]
+[ $arch == arm || $arch == arm64 || $runtime != vm || $mode == debug && $system == windows ]
+fragmentation_test: Skip
+
+[ $compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk ]
+*: SkipByDesign
+
+[ $compiler == dartk || $compiler == dartkb || $compiler == dartkp ]
 io/file_error_test: RuntimeError
 io/file_test: RuntimeError
 io/http_auth_digest_test: RuntimeError
@@ -125,37 +125,6 @@
 io/web_socket_protocol_processor_test: CompileTimeError
 io/zlib_test: RuntimeError
 
-[ !$strong && ($compiler == dartk || $compiler == dartkb || $compiler == dartkp) ]
-io/compile_all_test: Skip # Crashes
-io/http_client_connect_test: Skip # Flaky.
-io/http_content_length_test: Skip # Flaky.
-io/http_proxy_test: Skip # Flaky.
-io/http_response_deadline_test: Skip # Flaky.
-io/http_reuse_server_port_test: Skip # Flaky.
-io/http_server_close_response_after_error_test: Skip # Flaky.
-io/http_shutdown_test: Skip # Flaky.
-io/raw_secure_server_closing_test: Skip # Flaky.
-io/secure_multiple_client_server_test: Skip # Flaky.
-io/secure_server_closing_test: Skip # Flaky.
-io/secure_server_socket_test: Skip # Flaky.
-io/web_socket_error_test: Skip # Flaky
-io/web_socket_ping_test: Skip # Flaky.
-io/web_socket_test: Skip # Flaky.
-map_insert_remove_oom_test: Skip # Heap limit too low.
-no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
-package/package1_test: CompileTimeError
-package/package_test: CompileTimeError
-package/scenarios/invalid/invalid_utf8_test: CompileTimeError
-package/scenarios/invalid/non_existent_packages_file_test: CompileTimeError
-package/scenarios/invalid/same_package_twice_test: CompileTimeError
-regress_29350_test: MissingCompileTimeError
-
-[ $arch == arm || $arch == arm64 || $runtime != vm || $mode == debug && $system == windows ]
-fragmentation_test: Skip
-
-[ $compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk ]
-*: SkipByDesign
-
 [ $mode == product || $runtime == dart_precompiled ]
 no_assert_test: SkipByDesign
 
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index ceb859a..1441048 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -35,19 +35,36 @@
 io/zlib_test: RuntimeError
 
 [ $compiler == dartkb ]
+io/dart_std_io_pipe_test: Pass, Timeout # Please triage
+io/platform_resolved_executable_test/00: RuntimeError # Reruns the same script (dill file without AST) without passing --enable-interpreter or --use-bytecode-compiler.
+io/platform_resolved_executable_test/01: RuntimeError # Reruns the same script (dill file without AST) without passing --enable-interpreter or --use-bytecode-compiler.
+io/platform_resolved_executable_test/02: RuntimeError # Reruns the same script (dill file without AST) without passing --enable-interpreter or --use-bytecode-compiler.
 io/platform_resolved_executable_test/03: RuntimeError
 io/platform_resolved_executable_test/04: RuntimeError
+io/platform_resolved_executable_test/05: RuntimeError # Reruns the same script (dill file without AST) without passing --enable-interpreter or --use-bytecode-compiler.
+io/platform_test: RuntimeError # Platform.script points to dill file.
+io/test_extension_fail_test: RuntimeError # Platform.script points to dill file.
+io/test_extension_test: RuntimeError # Platform.script points to dill file.
+no_lazy_dispatchers_test: SkipByDesign # KBC interpreter doesn't support --no_lazy_dispatchers
 
 [ $compiler == dartkp ]
 io/arguments_test: Fail # Test harness passes runtime arguments to the compiler
 io/test_runner_test: SkipByDesign # Is not relevant for AOT.
 
+[ $compiler == fasta ]
+io/http_cookie_date_test: CompileTimeError
+io/http_headers_test: CompileTimeError
+io/http_parser_test: CompileTimeError
+io/secure_socket_argument_test: CompileTimeError
+io/web_socket_protocol_processor_test: CompileTimeError
+
 [ $system == android ]
 entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
 
 [ $fasta ]
 deferred_transitive_import_error_test: CompileTimeError
 package/package1_test: CompileTimeError
+package/package_isolate_test: CompileTimeError
 package/package_test: CompileTimeError
 package/scenarios/invalid/invalid_utf8_test: CompileTimeError
 package/scenarios/invalid/non_existent_packages_file_test: CompileTimeError
@@ -56,10 +73,10 @@
 [ $arch == ia32 && $builder_tag == optimization_counter_threshold ]
 io/file_lock_test: SkipSlow # Timeout
 
-[ $arch == ia32 && $compiler == dartk && $strong ]
+[ $arch == ia32 && $compiler == dartk ]
 io/dart_std_io_pipe_test: Timeout, Pass # Issue 34723
 
-[ $arch == simarm64 && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $arch == simarm64 && ($compiler == dartk || $compiler == dartkb) ]
 io/http_bind_test: Pass, Slow
 
 [ $arch == x64 && $builder_tag == asan && $compiler == dartk ]
@@ -71,20 +88,7 @@
 [ $builder_tag == optimization_counter_threshold && ($compiler == dartk || $compiler == dartkb) ]
 map_insert_remove_oom_test: Skip # Heap limit too low.
 
-# The failures below still need to be investigated and possibly fixed, or marked as skipped.
-[ $compiler == dartkb && $strong ]
-io/code_collection_test: RuntimeError # Reruns the same script (dill file without AST) without passing --enable-interpreter or --use-bytecode-compiler.
-io/dart_std_io_pipe_test: Pass, Timeout # Please triage
-io/platform_resolved_executable_test/00: RuntimeError # Reruns the same script (dill file without AST) without passing --enable-interpreter or --use-bytecode-compiler.
-io/platform_resolved_executable_test/01: RuntimeError # Reruns the same script (dill file without AST) without passing --enable-interpreter or --use-bytecode-compiler.
-io/platform_resolved_executable_test/02: RuntimeError # Reruns the same script (dill file without AST) without passing --enable-interpreter or --use-bytecode-compiler.
-io/platform_resolved_executable_test/05: RuntimeError # Reruns the same script (dill file without AST) without passing --enable-interpreter or --use-bytecode-compiler.
-io/platform_test: RuntimeError # Platform.script points to dill file.
-io/test_extension_fail_test: RuntimeError # Platform.script points to dill file.
-io/test_extension_test: RuntimeError # Platform.script points to dill file.
-no_lazy_dispatchers_test: SkipByDesign # KBC interpreter doesn't support --no_lazy_dispatchers
-
-[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
+[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
 io/raw_socket_test: Crash
 io/skipping_dart2js_compilations_test: Crash
 io/socket_exception_test: Pass, Crash
@@ -93,20 +97,15 @@
 io/socket_info_ipv6_test: Pass, Crash
 io/socket_port_test: Pass, Crash
 
-[ $compiler == dartkp && $mode == product && $runtime == dart_precompiled && $strong ]
+[ $compiler == dartkp && $mode == product && $runtime == dart_precompiled ]
 io/compile_all_test: Pass
 
-# ===== dartkp + dart_precompiled status lines =====
-[ $compiler == dartkp && $runtime == dart_precompiled && $system != windows && $strong ]
-io/namespace_test: RuntimeError
-
-[ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
+[ $compiler == dartkp && $runtime == dart_precompiled ]
 io/compile_all_test: Skip # We do not support --compile-all for precompilation
 io/file_fuzz_test: RuntimeError, Pass
 io/http_client_connect_test: Skip # Flaky.
 io/http_close_test: Crash
 io/http_content_length_test: Skip # Flaky.
-io/http_cookie_test: Skip # Flaky
 io/http_proxy_advanced_test: Skip # Flaky
 io/http_proxy_test: Skip # Flaky.
 io/http_response_deadline_test: Skip # Flaky.
@@ -132,20 +131,14 @@
 regress_29350_test: MissingCompileTimeError
 regress_29350_test/none: Pass # Issue 31537
 
+# ===== dartkp + dart_precompiled status lines =====
+[ $compiler == dartkp && $runtime == dart_precompiled && $system != windows ]
+io/namespace_test: RuntimeError
+
 [ $compiler == dartkp && $system == android ]
 io/http_close_test: Timeout # Issue 28380
 
-[ $compiler == dartkp && !$strong ]
-*: SkipByDesign
-
-[ $compiler == fasta && $strong ]
-io/http_cookie_date_test: CompileTimeError
-io/http_headers_test: CompileTimeError
-io/http_parser_test: CompileTimeError
-io/secure_socket_argument_test: CompileTimeError
-io/web_socket_protocol_processor_test: CompileTimeError
-
-[ $mode == debug && $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
 io/file_lock_test: Slow, Pass
 io/raw_socket_test: Crash
 io/socket_exception_test: Pass, Crash
@@ -157,7 +150,7 @@
 [ $mode == debug && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
 io/web_socket_ping_test: Crash, Pass
 
-[ $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
+[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
 io/http_client_request_test: Pass, Timeout
 io/secure_builtin_roots_test: Pass, Timeout
 io/socket_finalizer_test: Pass, Timeout
@@ -165,22 +158,14 @@
 regress_29350_test: MissingCompileTimeError
 regress_29350_test/none: Pass # Issue 31537
 
-[ $system == windows && $strong && ($compiler == dartk || $compiler == dartkb) ]
-io/compile_all_test: Pass, Fail # Possibly related to issue 32373
-map_insert_remove_oom_test: Skip # Heap limit too low.
-
 [ $system == windows && ($compiler == dartk || $compiler == dartkb) ]
+io/compile_all_test: Pass, Fail # Possibly related to issue 32373
 io/dart_std_io_pipe_test: Pass, Slow
 io/secure_builtin_roots_test: Skip # Issues 32137 and 32138.
 io/test_extension_fail_test: RuntimeError, Pass # Issue 32137.
 io/test_extension_test: RuntimeError, Pass # Issue 32137.
 io/wait_for_event_isolate_test: Skip # Issues 32137 and 32138.
-
-[ $fasta && $strong ]
-package/package_isolate_test: CompileTimeError
-
-[ $fasta && !$strong ]
-regress_29350_test/none: MissingCompileTimeError
+map_insert_remove_oom_test: Skip # Heap limit too low.
 
 [ $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
 io/http_no_reason_phrase_test: Pass, Crash
@@ -193,7 +178,7 @@
 # Enabling of dartk for sim{arm,arm64,dbc64} revealed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
 # batch mode.
-[ $strong && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ]
+[ ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ]
 fragmentation_test: Timeout, Pass
 io/dart_std_io_pipe_test: Timeout, Pass
 io/directory_list_sync_test: Timeout, Pass # Please triage.
@@ -205,13 +190,6 @@
 io/test_extension_test: RuntimeError # Platform.script points to dill file.
 map_insert_remove_oom_test: Skip # Heap limit too low.
 
-# ===== Skip dartk and darkp in !$strong mode ====
-[ !$strong && ($compiler == dartk || $compiler == dartkb) ]
-*: SkipByDesign
-
-[ !$strong && ($compiler == dartk || $compiler == dartkb || $compiler == dartkp || $runtime == dart_precompiled || $runtime == vm) ]
-*: SkipByDesign # standalone_2 is only supported in strong mode.
-
 [ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
 io/addlatexhash_test: Skip # Timeout
 io/http_advanced_test: Skip # Timeout
@@ -229,6 +207,5 @@
 io/web_socket_compression_test: Skip # Timeout
 io/web_socket_test: Skip # Timeout
 
-
 [ $compiler != dartk && $compiler != dartkb && $compiler != dartkp || $compiler == dartkp && $system == windows ]
 entrypoints_verification_test: SkipByDesign # Requires VM to run. Cannot run in precompiled Windows because the DLL is linked against dart.exe instead of dart_precompiled_runtime.exe.
diff --git a/tests/standalone_2/standalone_2_precompiled.status b/tests/standalone_2/standalone_2_precompiled.status
index 64e4609..e17acac 100644
--- a/tests/standalone_2/standalone_2_precompiled.status
+++ b/tests/standalone_2/standalone_2_precompiled.status
@@ -62,9 +62,6 @@
 io/namespace_test: RuntimeError
 io/test_runner_test: RuntimeError
 
-[ $runtime == dart_precompiled && !$checked && !$strong ]
-io/file_constructor_test: RuntimeError
-
 [ $compiler == app_jit || $compiler == precompiler ]
 io/compile_all_test: Skip # Incompatible flag --compile_all
 
@@ -79,5 +76,4 @@
 package/scenarios/packages_option_only/packages_option_only_test: Skip
 
 [ $mode == product || $runtime == dart_precompiled ]
-io/code_collection_test: Skip # Incompatible flags
 no_assert_test: SkipByDesign # Requires checked mode.
diff --git a/tests/standalone_2/standalone_2_vm.status b/tests/standalone_2/standalone_2_vm.status
index bc23a30..ee8622a 100644
--- a/tests/standalone_2/standalone_2_vm.status
+++ b/tests/standalone_2/standalone_2_vm.status
@@ -8,7 +8,6 @@
 
 [ $compiler == app_jit ]
 full_coverage_test: Skip # Platform.executable
-io/code_collection_test: Skip # Platform.executable
 io/namespace_test: RuntimeError # Issue 33168
 io/platform_resolved_executable_test/00: RuntimeError # Issue 33168
 io/platform_resolved_executable_test/01: RuntimeError # Issue 33168
@@ -89,11 +88,7 @@
 [ $runtime == dart_precompiled && $system == linux && ($arch == simarm || $arch == simarm64 || $arch == x64) ]
 io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
 
-[ $runtime == vm && !$checked && !$strong ]
-io/file_constructor_test: RuntimeError
-
 [ $runtime == vm && ($arch == arm || $arch == arm64) ]
-io/code_collection_test: Timeout, Pass
 io/dart_std_io_pipe_test: Timeout, Pass
 io/file_input_stream_test: Skip # Issue 26109
 io/file_stream_test: Skip # Issue 26109
@@ -101,7 +96,6 @@
 io/process_sync_test: Timeout, Pass
 
 [ $runtime == vm && ($arch == simarm || $arch == simarm64) ]
-io/code_collection_test: Timeout, Pass
 io/dart_std_io_pipe_test: Timeout, Pass
 io/http_client_stays_alive_test: Skip # Spawns process in Dart2 mode.
 io/process_sync_test: Timeout, Pass
diff --git a/third_party/babel/update.sh b/third_party/babel/update.sh
new file mode 100755
index 0000000..6b9ca5a
--- /dev/null
+++ b/third_party/babel/update.sh
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+# Uploads a new version of d8 CIPD package
+set -e
+set -x
+
+if [ -z "$1" ]; then
+  echo "Usage: update.sh version"
+  exit 1
+fi
+
+version=$1
+
+tmpdir=$(mktemp -d)
+cleanup() {
+  rm -rf "$tmpdir"
+}
+trap cleanup EXIT HUP INT QUIT TERM PIPE
+cd "$tmpdir"
+
+for file in "babel.js" "babel.min.js" "LICENSE"
+do
+  curl -o $file "https://unpkg.com/@babel/standalone@$version/$file"
+done
+
+cipd create \
+  -name dart/third_party/babel \
+  -in . \
+  -install-mode copy \
+  -tag version:$version
diff --git a/tools/VERSION b/tools/VERSION
index e9acdfb..5912f77 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -31,9 +31,9 @@
 #
 CHANNEL stable
 MAJOR 2
-MINOR 3
-PATCH 2
+MINOR 4
+PATCH 0
 PRERELEASE 0
 PRERELEASE_PATCH 0
-ABI_VERSION 4
-OLDEST_SUPPORTED_ABI_VERSION 1
+ABI_VERSION 5
+OLDEST_SUPPORTED_ABI_VERSION 3
diff --git a/tools/bots/aot_smoke_tests.dart b/tools/bots/aot_smoke_tests.dart
new file mode 100755
index 0000000..bb92379
--- /dev/null
+++ b/tools/bots/aot_smoke_tests.dart
@@ -0,0 +1,69 @@
+#!/usr/bin/env dart
+// Copyright (c) 2019, 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.
+
+// Smoke test runner for Dart AOT (dart2aot, dartaotruntime).
+// aot_smoke_tests.dart and dart_aot_test.dart together form the test that the
+// AOT toolchain is compiled and included correctly in the SDK.
+// This tests that the AOT tools can both successfully compile Dart -> AOT and
+// run the resulting AOT blob with the AOT runtime.
+
+import 'dart:io';
+import 'dart:convert';
+
+import 'package:args/args.dart';
+
+get_dart2aot() {
+  if (Platform.isLinux) {
+    return 'out/ReleaseX64/dart-sdk/bin/dart2aot';
+  } else if (Platform.isMacOS) {
+    return 'xcodebuild/ReleaseX64/dart-sdk/bin/dart2aot';
+  } else if (Platform.isWindows) {
+    return 'out\\ReleaseX64\\dart-sdk\\bin\\dart2aot.bat';
+  } else {
+    throw 'Unsupported host platform!';
+  }
+}
+
+get_dartaotruntime() {
+  if (Platform.isLinux) {
+    return 'out/ReleaseX64/dart-sdk/bin/dartaotruntime';
+  } else if (Platform.isMacOS) {
+    return 'xcodebuild/ReleaseX64/dart-sdk/bin/dartaotruntime';
+  } else if (Platform.isWindows) {
+    return 'out\\ReleaseX64\\dart-sdk\\bin\\dartaotruntime.exe';
+  } else {
+    throw 'Unsupported host platform!';
+  }
+}
+
+assert_equals(var expected, var actual) {
+  if (expected != actual) {
+    print('Test failed! Expected \'$expected\', got \'$actual\'');
+    exit(1);
+  }
+}
+
+main(List<String> args) async {
+  ProcessResult result;
+
+  result = Process.runSync(get_dart2aot(),
+      ['tools/bots/dart_aot_test.dart', 'tools/bots/dart_aot_test.dart.aot'],
+      stdoutEncoding: utf8, stderrEncoding: utf8);
+  stdout.write(result.stdout);
+  if (result.exitCode != 0 || result.stderr != '') {
+    stderr.write(result.stderr);
+    exit(1);
+  }
+
+  result = Process.runSync(
+      get_dartaotruntime(), ['tools/bots/dart_aot_test.dart.aot'],
+      stdoutEncoding: utf8, stderrEncoding: utf8);
+  if (result.exitCode != 0 || result.stderr != '') {
+    stderr.write(result.stderr);
+    exit(1);
+  }
+
+  assert_equals('Hello, 世界.', result.stdout.trim());
+}
diff --git a/tools/bots/dart_aot_test.dart b/tools/bots/dart_aot_test.dart
new file mode 100755
index 0000000..0a626f4
--- /dev/null
+++ b/tools/bots/dart_aot_test.dart
@@ -0,0 +1,10 @@
+#!/usr/bin/env dart
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test program for Dart AOT (dart2aot, dartaotruntime).
+
+main(List<String> args) async {
+  print('Hello, 世界.');
+}
diff --git a/tools/bots/dart_sdk.py b/tools/bots/dart_sdk.py
index 301f269..48564d8 100755
--- a/tools/bots/dart_sdk.py
+++ b/tools/bots/dart_sdk.py
@@ -27,11 +27,12 @@
  else:
    return ['ia32', 'x64']
 
+def BuildRootPath(path, arch=BUILD_ARCHITECTURE, build_mode='release'):
+  return os.path.join(bot_utils.DART_DIR,
+                      utils.GetBuildRoot(BUILD_OS, build_mode, arch), path)
+
 def BuildDartdocAPIDocs(dirname):
-  dart_sdk = os.path.join(bot_utils.DART_DIR,
-                          utils.GetBuildRoot(BUILD_OS, 'release',
-                                             BUILD_ARCHITECTURE),
-                          'dart-sdk')
+  dart_sdk = BuildRootPath('dart-sdk')
   dart_exe =  os.path.join(dart_sdk, 'bin', 'dart')
   dartdoc_dart = os.path.join(bot_utils.DART_DIR,
                               'third_party', 'pkg', 'dartdoc', 'bin',
@@ -45,10 +46,7 @@
                   '--rel-canonical-prefix=' + url])
 
 def CreateUploadVersionFile():
-  file_path = os.path.join(bot_utils.DART_DIR,
-                           utils.GetBuildRoot(BUILD_OS, 'release',
-                                              BUILD_ARCHITECTURE),
-                           'VERSION')
+  file_path = BuildRootPath('VERSION')
   with open(file_path, 'w') as fd:
     fd.write(utils.GetVersionFileContent())
   DartArchiveUploadVersionFile(file_path)
@@ -60,27 +58,19 @@
     destination = namer.version_filepath(revision)
     DartArchiveFile(version_file, destination, checksum_files=False)
 
-def CreateUploadSDKZips():
-  with bot.BuildStep('Create and upload sdk zips'):
-    for arch in BuildArchitectures():
-      sdk_path = os.path.join(bot_utils.DART_DIR,
-                              utils.GetBuildRoot(BUILD_OS, 'release', arch),
-                              'dart-sdk')
-      product_sdk_path = os.path.join(bot_utils.DART_DIR,
-                              utils.GetBuildRoot(BUILD_OS, 'product', arch),
-                              'dart-sdk')
-      sdk_zip = os.path.join(bot_utils.DART_DIR,
-                             utils.GetBuildRoot(BUILD_OS, 'release', arch),
-                             'dartsdk-%s-%s.zip' % (BUILD_OS, arch))
-      FileDelete(sdk_zip)
-      # We don't support precompilation on ia32.
-      if arch != 'ia32':
-        # Patch in all the PRODUCT built AOT binaries.
-        CopyBetween(product_sdk_path, sdk_path, 'bin', 'utils', GuessExtension('gen_snapshot'))
-        CopyBetween(product_sdk_path, sdk_path, 'bin', GuessExtension('dartaotruntime'))
-      # Zip it up.
-      CreateZip(sdk_path, sdk_zip)
-      DartArchiveUploadSDKs(BUILD_OS, arch, sdk_zip)
+def CreateAndUploadSDKZip(arch, sdk_path):
+  sdk_zip = BuildRootPath('dartsdk-%s-%s.zip' % (BUILD_OS, arch), arch=arch)
+  FileDelete(sdk_zip)
+  CreateZip(sdk_path, sdk_zip)
+  DartArchiveUploadSDKs(BUILD_OS, arch, sdk_zip)
+
+def CopyAotBinaries(arch, sdk_path):
+  product_sdk_path = BuildRootPath('dart-sdk', arch=arch, build_mode='product')
+  # We don't support precompilation on ia32.
+  if arch != 'ia32':
+    with bot.BuildStep('Patching in PRODUCT built AOT binaries'):
+      CopyBetween(product_sdk_path, sdk_path, 'bin', 'utils', GuessExtension('gen_snapshot'))
+      CopyBetween(product_sdk_path, sdk_path, 'bin', GuessExtension('dartaotruntime'))
 
 def DartArchiveUploadSDKs(system, arch, sdk_zip):
   namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW)
@@ -95,21 +85,13 @@
   revision = utils.GetArchiveVersion()
   binary = namer.unstripped_filename(BUILD_OS)
   for arch in BuildArchitectures():
-    binary = os.path.join(bot_utils.DART_DIR,
-                          utils.GetBuildRoot(BUILD_OS, 'release', arch),
-                          binary)
+    binary = BuildRootPath(binary, arch=arch)
     gs_path = namer.unstripped_filepath(revision, BUILD_OS, arch)
     DartArchiveFile(binary, gs_path)
 
 def CreateUploadAPIDocs():
-  dartdoc_dir = os.path.join(bot_utils.DART_DIR,
-                             utils.GetBuildRoot(BUILD_OS, 'release',
-                                                BUILD_ARCHITECTURE),
-                             'gen-dartdocs')
-  dartdoc_zip = os.path.join(bot_utils.DART_DIR,
-                             utils.GetBuildRoot(BUILD_OS, 'release',
-                                                BUILD_ARCHITECTURE),
-                             'dartdocs-api.zip')
+  dartdoc_dir = BuildRootPath('gen-dartdocs')
+  dartdoc_zip = BuildRootPath('dartdocs-api.zip')
   if CHANNEL == bot_utils.Channel.TRY:
     BuildDartdocAPIDocs(dartdoc_dir)
   else:
@@ -236,7 +218,17 @@
     if BUILD_OS == 'linux':
       CreateUploadAPIDocs()
   elif CHANNEL != bot_utils.Channel.TRY:
-    CreateUploadSDKZips()
+    for arch in BuildArchitectures():
+      sdk_path = BuildRootPath('dart-sdk', arch=arch)
+      # Patch in all the PRODUCT built AOT binaries.
+      CopyAotBinaries(arch, sdk_path)
+      with bot.BuildStep('Create and upload sdk zip for ' + arch):
+        CreateAndUploadSDKZip(arch, sdk_path)
     DartArchiveUnstrippedBinaries()
     if BUILD_OS == 'linux':
       CreateUploadVersionFile()
+  else:  # CHANNEL == bot_utils.Channel.TRY
+    # Patch in all the PRODUCT built AOT binaries.
+    for arch in BuildArchitectures():
+      sdk_path = BuildRootPath('dart-sdk', arch=arch)
+      CopyAotBinaries(arch, sdk_path)
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 3cd4ed0..9eb3373 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -43,6 +43,7 @@
       "tests/standalone/",
       "tests/standalone_2/",
       "tests/ffi/",
+      "third_party/babel/babel.min.js",
       "third_party/d8/",
       "third_party/observatory_pub_packages/packages/web_components/",
       "third_party/pkg/",
@@ -245,7 +246,12 @@
       "options": {
         "use-sdk": true
     }},
-    "dart2js-win-(ie11|edge)": {
+    "dart2js-win-ie11": {
+      "options": {
+        "use-sdk": true,
+        "babel": "{\"presets\":[\"es2015\"]}"
+    }},
+    "dart2js-win-edge": {
       "options": {
         "use-sdk": true
     }},
@@ -274,9 +280,9 @@
       "options": {
         "host-checked": true
     }},
-    "dartkp-android-(debug|product|release)-arm": {
+    "dartkp-android-(debug|product|release)-(arm|arm64)": {
       "options": {
-        "use-blobs": true
+        "use-elf": true
     }},
     "dartk-android-(debug|product|release)-(arm|arm64)": {},
     "dartkp-linux-(debug|product|release)-(simarm|simarm64)": {
@@ -318,7 +324,7 @@
     "dartk-(linux|mac|win)-(debug|product|release)-(ia32|x64)": { },
     "dartk-checked-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
-	"enable-asserts": true
+        "enable-asserts": true
     }},
     "dartk-(linux|mac|win)-(debug|product|release)-(arm64|simarm|simarm64|simdbc64)": { },
     "dartk-optcounter-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
@@ -392,6 +398,7 @@
         },
         {
           "name": "unit tests",
+          "script": "tools/disguised_test.py",
           "arguments": [
             "-nunittest-asserts-${mode}-${system}",
              "pkg/(kernel|front_end|fasta)"
@@ -554,7 +561,6 @@
     },
     {
       "builders": [
-        "vm-kernel-precomp-linux-debug-x64",
         "vm-kernel-precomp-linux-product-x64",
         "vm-kernel-precomp-linux-release-simarm",
         "vm-kernel-precomp-linux-release-simarm64",
@@ -587,6 +593,32 @@
     },
     {
       "builders": [
+        "vm-kernel-precomp-linux-debug-x64"
+      ],
+      "meta": {
+        "description": "This configuration is used by the vm kernel precomp debug builders. It uses 15 shards for testing to avoid 1 hour shard timeouts."
+      },
+      "steps": [
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": [
+            "runtime_kernel",
+            "dart_precompiled_runtime"
+          ]
+        },
+        {
+          "name": "vm tests",
+          "arguments": [
+            "-ndartkp-${system}-${mode}-${arch}"
+          ],
+          "fileset": "vm-kernel",
+          "shards": 15
+        }
+      ]
+    },
+    {
+      "builders": [
         "vm-kernel-precomp-bare-linux-release-x64",
         "vm-kernel-precomp-bare-linux-release-simarm",
         "vm-kernel-precomp-bare-linux-release-simarm64"
@@ -842,7 +874,8 @@
             "-ndartdevc-checked-${system}-release-chrome",
             "language_2",
             "corelib_2",
-            "lib_2"
+            "lib_2",
+            "dartdevc_native"
           ]
         },
         {
@@ -851,7 +884,20 @@
             "-ndartdevk-checked-${system}-release-chrome",
             "language_2",
             "corelib_2",
-            "lib_2"
+            "lib_2",
+            "dartdevc_native"
+          ]
+        },
+        {
+          "name": "ddc kernel modular tests",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "testRunner": true,
+          "arguments": [
+            "pkg/dev_compiler/test/modular_suite.dart",
+            "--configuration-name",
+            "dartdevk-${system}-release",
+            "--verbose",
+            "--use-sdk"
           ]
         },
         {
@@ -893,6 +939,27 @@
             "pkg/dev_compiler/test/worker/worker_test.dart",
             "-rnone"
           ]
+        },
+        {
+          "name": "ddc self host test",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "arguments": [
+            "--enable-asserts",
+            "pkg/dev_compiler/bin/dartdevc.dart",
+            "-o=out/ReleaseX64/dartdevc.js",
+            "pkg/dev_compiler/bin/dartdevc.dart"
+          ]
+        },
+        {
+          "name": "ddk self host test",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "arguments": [
+            "--enable-asserts",
+            "pkg/dev_compiler/bin/dartdevc.dart",
+            "-k",
+            "-o=out/ReleaseX64/dartdevk.js",
+            "pkg/dev_compiler/bin/dartdevc.dart"
+          ]
         }
       ]
     },
@@ -915,7 +982,8 @@
             "-ndartdevc-checked-mac-release-chrome",
             "language_2",
             "corelib_2",
-            "lib_2"
+            "lib_2",
+            "dartdevc_native"
           ]
         },
         {
@@ -924,7 +992,20 @@
             "-ndartdevk-checked-mac-release-chrome",
             "language_2",
             "corelib_2",
-            "lib_2"
+            "lib_2",
+            "dartdevc_native"
+          ]
+        },
+        {
+          "name": "ddc kernel modular tests",
+          "script": "xcodebuild/ReleaseX64/dart-sdk/bin/dart",
+          "testRunner": true,
+          "arguments": [
+            "pkg/dev_compiler/test/modular_suite.dart",
+            "--configuration-name",
+            "dartdevk-${system}-release",
+            "--verbose",
+            "--use-sdk"
           ]
         },
         {
@@ -966,6 +1047,27 @@
             "pkg/dev_compiler/test/worker/worker_test.dart",
             "-rnone"
           ]
+        },
+        {
+          "name": "ddc self host test",
+          "script": "xcodebuild/ReleaseX64/dart-sdk/bin/dart",
+          "arguments": [
+            "--enable-asserts",
+            "pkg/dev_compiler/bin/dartdevc.dart",
+            "-o=xcodebuild/ReleaseX64/dartdevc.js",
+            "pkg/dev_compiler/bin/dartdevc.dart"
+          ]
+        },
+        {
+          "name": "ddk self host test",
+          "script": "xcodebuild/ReleaseX64/dart-sdk/bin/dart",
+          "arguments": [
+            "--enable-asserts",
+            "pkg/dev_compiler/bin/dartdevc.dart",
+            "-k",
+            "-o=xcodebuild/ReleaseX64/dartdevk.js",
+            "pkg/dev_compiler/bin/dartdevc.dart"
+          ]
         }
       ]
     },
@@ -1056,6 +1158,18 @@
           "arguments": ["create_sdk"]
         },
         {
+          "name": "dart2js modular tests",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "testRunner": true,
+          "arguments": [
+            "pkg/compiler/tool/modular_test_suite.dart",
+            "--configuration-name",
+            "dart2js-${system}-release-d8",
+            "--verbose",
+            "--use-sdk"
+          ]
+        },
+        {
           "name": "dart2js unit tests",
           "arguments": [
             "-nunittest-asserts-no-sdk-linux",
@@ -1346,6 +1460,13 @@
           "script": "tools/bots/dart_sdk.py"
         },
         {
+          "name": "run smoke tests",
+          "script": "out/ReleaseX64/dart",
+          "arguments": [
+            "tools/bots/aot_smoke_tests.dart"
+          ]
+        },
+        {
           "name": "build api docs",
           "script": "tools/bots/dart_sdk.py",
           "arguments": [ "api_docs" ]
@@ -1361,10 +1482,9 @@
       ]
     },
     {
-      "builders": ["dart-sdk-mac",
-                   "dart-sdk-win"],
+      "builders": ["dart-sdk-mac"],
       "meta": {
-        "description": "This configuration is used by the sdk-builders for MacOS and Windows."
+        "description": "This configuration is used by the sdk-builders for MacOS."
       },
       "steps": [
         {
@@ -1388,6 +1508,50 @@
         {
           "name": "upload sdk",
           "script": "tools/bots/dart_sdk.py"
+        },
+        {
+          "name": "run smoke tests",
+          "script": "xcodebuild/ReleaseX64/dart",
+          "arguments": [
+            "tools/bots/aot_smoke_tests.dart"
+          ]
+        }
+      ]
+    },
+    {
+      "builders": ["dart-sdk-win"],
+      "meta": {
+        "description": "This configuration is used by the sdk-builders for Windows."
+      },
+      "steps": [
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": ["--arch=ia32,x64",
+                        "--mode=release", "create_sdk"]
+        },
+        {
+          "name": "build gen_kernel.dart.snapshot and dart2aot",
+          "script": "tools/build.py",
+          "arguments": ["--arch=x64", "--mode=release",
+                        "copy_gen_kernel_snapshot", "copy_dart2aot"]
+        },
+        {
+          "name": "build gen_snapshot and dartaotruntime",
+          "script": "tools/build.py",
+          "arguments": ["--arch=x64", "--mode=product",
+                        "copy_gen_snapshot", "copy_dartaotruntime"]
+        },
+        {
+          "name": "upload sdk",
+          "script": "tools/bots/dart_sdk.py"
+        },
+        {
+          "name": "run smoke tests",
+          "script": "out/ReleaseX64/dart.exe",
+          "arguments": [
+            "tools/bots/aot_smoke_tests.dart"
+          ]
         }
       ]
     },
@@ -1561,7 +1725,7 @@
         {
           "name": "analyze pkg/dev_compiler",
           "script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
-          "arguments": ["--fatal-warnings", "pkg/dev_compiler"]
+          "arguments": ["--fatal-warnings", "--fatal-lints", "pkg/dev_compiler"]
         },
         {
           "name": "analyze pkg/expect",
@@ -1674,7 +1838,7 @@
           "name": "package unit tests",
           "arguments": [
             "-nunittest-asserts-${mode}-${system}",
-            "pkg/pkg/(?!front_end/|kernel/)"
+            "pkg/pkg/(?!(analyzer*|analysis_server|front_end|kernel)/)"
           ]
         },
         {
@@ -1708,7 +1872,7 @@
           "name": "package unit tests",
           "arguments": [
             "-nunittest-asserts-${mode}-${system}",
-            "pkg/pkg/(?!front_end/|kernel/)"
+            "pkg/pkg/(?!(analyzer*|analysis_server|front_end|kernel)/)"
           ]
         },
         {
@@ -1918,6 +2082,38 @@
           "fileset": "fuzzer"
         }
       ]
+    },
+    {
+      "builders": [
+        "vm-dartkb-linux-release-x64-abi"
+      ],
+      "meta": {
+        "description": "This configuration runs tests for each supported ABI version."
+      },
+      "steps": [
+        {
+          "name": "configure dart",
+          "script": "tools/gn.py",
+          "arguments": [
+            "--mode=release",
+            "--arch=x64",
+            "--bytecode"
+          ]
+        },
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": [
+            "--mode=release",
+            "--arch=x64",
+            "create_sdk"
+          ]
+        },
+        {
+          "name": "run tests",
+          "script": "tools/run_abi_tests.py"
+        }
+      ]
     }
   ]
 }
diff --git a/tools/build.py b/tools/build.py
index 237c486..1782f2b 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -18,7 +18,7 @@
 DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
 AVAILABLE_ARCHS = ['ia32', 'x64', 'simarm', 'arm', 'simarmv6', 'armv6',
     'simarmv5te', 'armv5te', 'simarm64', 'arm64',
-    'simdbc', 'simdbc64', 'armsimdbc', 'armsimdbc64']
+    'simdbc', 'simdbc64', 'armsimdbc', 'armsimdbc64', 'simarm_x64']
 
 
 usage = """\
@@ -82,20 +82,20 @@
   options.os = options.os.split(',')
   for mode in options.mode:
     if not mode in ['debug', 'release', 'product']:
-      print "Unknown mode %s" % mode
+      print ("Unknown mode %s" % mode)
       return False
   for arch in options.arch:
     if not arch in AVAILABLE_ARCHS:
-      print "Unknown arch %s" % arch
+      print ("Unknown arch %s" % arch)
       return False
   options.os = [ProcessOsOption(os_name) for os_name in options.os]
   for os_name in options.os:
     if not os_name in ['android', 'freebsd', 'linux', 'macos', 'win32']:
-      print "Unknown os %s" % os_name
+      print ("Unknown os %s" % os_name)
       return False
     if os_name != HOST_OS:
       if os_name != 'android':
-        print "Unsupported target os %s" % os_name
+        print ("Unsupported target os %s" % os_name)
         return False
       if not HOST_OS in ['linux', 'macos']:
         print ("Cross-compilation to %s is not supported on host os %s."
@@ -109,14 +109,14 @@
       # We have not yet tweaked the v8 dart build to work with the Android
       # NDK/SDK, so don't try to build it.
       if not args:
-        print "For android builds you must specify a target, such as 'runtime'."
+        print ("For android builds you must specify a target, such as 'runtime'.")
         return False
   return True
 
 
 def NotifyBuildDone(build_config, success, start):
   if not success:
-    print "BUILD FAILED"
+    print ("BUILD FAILED")
 
   sys.stdout.flush()
 
@@ -223,10 +223,10 @@
         words = line.split()
         goma_dir = words[2][1:-1]  # goma_dir = "/path/to/goma"
   if not goma_dir:
-    print 'Could not find goma for ' + out_dir
+    print ('Could not find goma for ' + out_dir)
     return False
   if not os.path.exists(goma_dir) or not os.path.isdir(goma_dir):
-    print 'Could not find goma at ' + goma_dir
+    print ('Could not find goma at ' + goma_dir)
     return False
   goma_ctl = os.path.join(goma_dir, 'goma_ctl.py')
   goma_ctl_command = [
@@ -270,7 +270,7 @@
 
 def RunOneBuildCommand(build_config, args):
   start_time = time.time()
-  print ' '.join(args)
+  print (' '.join(args))
   process = subprocess.Popen(args, stdin=None)
   process.wait()
   if process.returncode != 0:
@@ -284,7 +284,7 @@
 
 def RunOneGomaBuildCommand(args):
   try:
-    print ' '.join(args)
+    print (' '.join(args))
     process = subprocess.Popen(args, stdin=None)
     process.wait()
     print (' '.join(args) + " done.")
diff --git a/tools/copy_tree.py b/tools/copy_tree.py
index 5d72750..d175b14 100755
--- a/tools/copy_tree.py
+++ b/tools/copy_tree.py
@@ -43,17 +43,17 @@
 def ValidateArgs(args):
   if args.gn:
     if args.exclude_patterns or args.copy_from or args.to:
-      print "--gn mode does not accept other switches"
+      print ("--gn mode does not accept other switches")
       return False
     if not args.gn_paths:
-      print "--gn mode requires a list of source specifications"
+      print ("--gn mode requires a list of source specifications")
       return False
     return True
   if not args.copy_from or not os.path.isdir(args.copy_from):
-    print "--from argument must refer to a directory"
+    print ("--from argument must refer to a directory")
     return False
   if not args.to:
-    print "--to is required"
+    print ("--to is required")
     return False
   return True
 
@@ -118,10 +118,10 @@
 # directory, and source_dirs[n+1] is a list of ignore patterns.
 def SourcesToGN(source_dirs):
   if len(source_dirs) % 2 != 0:
-    print "--gn list length should be a multiple of 2."
+    print ("--gn list length should be a multiple of 2.")
     return False
   data = []
-  for i in xrange(0, len(source_dirs), 2):
+  for i in range(0, len(source_dirs), 2):
     path = source_dirs[i]
     ignores = source_dirs[i + 1]
     if ignores in ["{}"]:
@@ -131,7 +131,7 @@
       sources = ListTree(path, ignore=shutil.ignore_patterns(*patterns))
     data.append(sources)
   scope_data = {"sources": data}
-  print gn_helpers.ToGNString(scope_data)
+  print (gn_helpers.ToGNString(scope_data))
   return True
 
 
diff --git a/tools/disguised_test.py b/tools/disguised_test.py
new file mode 100755
index 0000000..40e8a0c
--- /dev/null
+++ b/tools/disguised_test.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# This script disguises test.py so it doesn't look like test.py to the testing
+# infrastructure, which handles test.py specially. Any testing done through
+# this script will not show up on testing dashboards and in the test results
+# database.
+
+# The front-end-* builders are currently using this script to run their unit
+# tests, which must always pass and should not be approvable through the status
+# file free workflow.
+
+import os
+import subprocess
+import sys
+
+exit(subprocess.call([sys.executable,
+                      os.path.join(os.path.dirname(os.path.abspath(__file__)),
+                                   "test.py")] +
+                      sys.argv[1:]))
diff --git a/tools/download_abi_dills.py b/tools/download_abi_dills.py
index 51dd8c1..5de464b 100644
--- a/tools/download_abi_dills.py
+++ b/tools/download_abi_dills.py
@@ -28,7 +28,7 @@
   oldest_abi_version = int(utils.GetOldestSupportedAbiVersion())
   cmd = ['cipd', 'ensure', '-root', 'tools/abiversions', '-ensure-file', '-']
   ensure_file = ''
-  for i in xrange(oldest_abi_version, abi_version + 1):
+  for i in range(oldest_abi_version, abi_version + 1):
     if findAbiVersion(i):
       ensure_file += '@Subdir %d\ndart/abiversions/%d latest\n\n' % (i, i)
   if not ensure_file:
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
new file mode 100644
index 0000000..0fa456c
--- /dev/null
+++ b/tools/experimental_features.yaml
@@ -0,0 +1,91 @@
+# Copyright (c) 2019, 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.
+
+# Experimental features are described in docs/process/experimental-flags.md
+# (Despite the name, they are not really intended for experiments.)
+# They are intended to enable new features or enhancements that are being
+# developed and are not yet shipped. Experimental feature flags are expected
+# to be relatively short-lived.
+#
+# Each entry in this map corresponds to an experiment,
+# and contains the following parts:
+#
+# 1. help: (required text)
+#    A human readable description of the experiment.
+#
+# 2. enabledIn: (optional #.#)
+#    The Dart SDK version (<major>.<minor>) in which the experiment is shipping.
+#
+#    If this field is specified, then the experiment is enabled regardless of
+#    the actual version of the SDK. If this field is omitted, then the
+#    experiment is disabled by default, but may be enabled by specifying the
+#    flag on the command line. (e.g. --enable-experiment=non-nullable)
+#
+#    A version less than than this version may be specified in a .packages file
+#    or in a library language version override (e.g. // @dart = 2.1)
+#    to disable this feature. For more on library language version override, see
+#    https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/language-versioning.md
+#
+# 3. expired: (optional boolean)
+#    If true, then the experiment can no longer be enabled by specifying the
+#    flag on the command line, and the corresponding entry is slated for
+#    eventual removal from this file. If this field is omitted, then 'expired'
+#    is considered to be false.
+#
+# Using the above fields, experiments pass through several states:
+#
+# Disabled:
+#    When an experiment is first added to this file, the 'enabledIn' and
+# 'expired' fields are omitted and the experiment is disabled by default,
+# but may be enabled by specifying the flag on the command line.
+# The implementation teams begin building support for the feature,
+# guarded by the flag.  Users can enable the flag and begin to try out
+# the feature as it is being developed.
+#
+# Shipped:
+#    When an experiment is shipped, then the 'enabledIn' field is added
+# indicating which version of the SDK contains this new language feature.
+# At this point, specifying the flag on the command line has no effect because
+# the experiment is enabled by default and cannot be disabled.
+#
+# Retired or Rejected:
+#    At some point, the 'expired' field is added to the experiment indicating
+# that the flag is to be retired if the experiment has shipped or that the
+# entire experiment was rejected if the experiment has not shipped. It also
+# indicates that the corresponding entry is slated for eventual removal
+# from this file. Users specifying this flag on the command line should receive
+# a warning that the experiment has been retired or rejected, but the tool
+# should continue to run.
+
+constant-update-2018:
+  help: "Enhanced constant expressions"
+
+extension-methods:
+  help: "Extension Methods"
+
+non-nullable:
+  help: "Non Nullable by default"
+
+triple-shift:
+  help: "Triple-shift operator"
+
+#
+# Flags below this line are either retired or rejected, cannot be specified
+# on the command line, and will eventually be removed.
+#
+
+control-flow-collections:
+  help: "Control Flow Collections"
+  enabledIn: '2.2.2'
+  expired: true
+
+set-literals:
+  help: "Set Literals"
+  enabledIn: 2.2
+  expired: true
+
+spread-collections:
+  help: "Spread Collections"
+  enabledIn: '2.2.2'
+  expired: true
\ No newline at end of file
diff --git a/tools/generate_buildfiles.py b/tools/generate_buildfiles.py
index 6118957..201c666 100755
--- a/tools/generate_buildfiles.py
+++ b/tools/generate_buildfiles.py
@@ -37,7 +37,7 @@
   ]
   if options.verbose:
     gn_command.append('-v')
-    print ' '.join(gn_command)
+    print (' '.join(gn_command))
   return Execute(gn_command)
 
 
@@ -52,7 +52,7 @@
   ]
   if options.verbose:
     gn_command.append('-v')
-    print ' '.join(gn_command)
+    print (' '.join(gn_command))
   return Execute(gn_command)
 
 
@@ -65,7 +65,7 @@
   ]
   if options.verbose:
     gn_command.append('-v')
-    print ' '.join(gn_command)
+    print (' '.join(gn_command))
   return Execute(gn_command)
 
 
diff --git a/tools/generate_idefiles.py b/tools/generate_idefiles.py
index 900c25c..728fdbb 100755
--- a/tools/generate_idefiles.py
+++ b/tools/generate_idefiles.py
@@ -50,7 +50,8 @@
   if gn_result != 0:
     return gn_result
 
-  out_folder = utils.GetBuildRoot(HOST_OS, mode="debug", arch=options.arch)
+  out_folder = utils.GetBuildRoot(
+      HOST_OS, mode="debug", arch=options.arch, target_os=options.os)
 
   if not os.path.isdir(out_folder):
     return 1
@@ -140,6 +141,10 @@
                       help="Target architecture for runtime sources.",
                       default="x64")
 
+  parser.add_argument("-s", "--os",
+                      help="Target operating system for runtime sources.",
+                      default=HOST_OS)
+
   options = parser.parse_args(argv[1:])
 
   return GenerateIdeFiles(options)
diff --git a/tools/gn.py b/tools/gn.py
index fbd1814..18725d2 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -82,7 +82,7 @@
 def HostCpuForArch(arch):
   if arch in ['ia32', 'arm', 'armv6', 'armv5te',
               'simarm', 'simarmv6', 'simarmv5te', 'simdbc',
-              'armsimdbc']:
+              'armsimdbc', 'simarm_x64']:
     return 'x86'
   if arch in ['x64', 'arm64', 'simarm64', 'simdbc64', 'armsimdbc64']:
     return 'x64'
@@ -92,7 +92,7 @@
 def TargetCpuForArch(arch, target_os):
   if arch in ['ia32', 'simarm', 'simarmv6', 'simarmv5te']:
     return 'x86'
-  if arch in ['x64', 'simarm64']:
+  if arch in ['x64', 'simarm64', 'simarm_x64']:
     return 'x64'
   if arch == 'simdbc':
     return 'arm' if target_os == 'android' else 'x86'
@@ -111,7 +111,7 @@
     return 'ia32'
   if arch in ['x64']:
     return 'x64'
-  if arch in ['arm', 'simarm']:
+  if arch in ['arm', 'simarm', 'simarm_x64']:
     return 'arm'
   if arch in ['armv6', 'simarmv6']:
     return 'armv6'
@@ -301,23 +301,23 @@
   args.os = args.os.split(',')
   for mode in args.mode:
     if not mode in ['debug', 'release', 'product']:
-      print "Unknown mode %s" % mode
+      print ("Unknown mode %s" % mode)
       return False
   for arch in args.arch:
     archs = ['ia32', 'x64', 'simarm', 'arm', 'simarmv6', 'armv6',
              'simarmv5te', 'armv5te', 'simarm64', 'arm64',
-             'simdbc', 'simdbc64', 'armsimdbc', 'armsimdbc64']
+             'simdbc', 'simdbc64', 'armsimdbc', 'armsimdbc64','simarm_x64']
     if not arch in archs:
-      print "Unknown arch %s" % arch
+      print ("Unknown arch %s" % arch)
       return False
   oses = [ProcessOsOption(os_name) for os_name in args.os]
   for os_name in oses:
     if not os_name in ['android', 'freebsd', 'linux', 'macos', 'win32']:
-      print "Unknown os %s" % os_name
+      print ("Unknown os %s" % os_name)
       return False
     if os_name != HOST_OS:
       if os_name != 'android':
-        print "Unsupported target os %s" % os_name
+        print ("Unsupported target os %s" % os_name)
         return False
       if not HOST_OS in ['linux', 'macos']:
         print ("Cross-compilation to %s is not supported on host os %s."
@@ -329,7 +329,7 @@
                % (os_name, arch))
         return False
   if HOST_OS != 'win' and args.use_crashpad:
-    print "Crashpad is only supported on Windows"
+    print ("Crashpad is only supported on Windows")
     return False
   return True
 
@@ -359,7 +359,7 @@
       type=str,
       help='Target architectures (comma-separated).',
       metavar='[all,ia32,x64,simarm,arm,simarmv6,armv6,simarmv5te,armv5te,'
-              'simarm64,arm64,simdbc,armsimdbc]',
+              'simarm64,arm64,simdbc,armsimdbc,simarm_x64]',
       default='x64')
   common_group.add_argument('--mode', '-m',
       type=str,
@@ -501,7 +501,7 @@
   gn = os.path.join(DART_ROOT, 'buildtools',
       'gn.exe' if utils.IsWindows() else 'gn')
   if not os.path.isfile(gn):
-    print "Couldn't find the gn binary at path: " + gn
+    print ("Couldn't find the gn binary at path: " + gn)
     return 1
 
   commands = []
@@ -516,7 +516,7 @@
         gn_args = ToCommandLine(ToGnArgs(args, mode, arch, target_os))
         gn_args += GetGNArgs(args)
         if args.verbose:
-          print "gn gen --check in %s" % out_dir
+          print ("gn gen --check in %s" % out_dir)
         if args.ide:
           command.append(ide_switch(HOST_OS))
         command.append('--args=%s' % ' '.join(gn_args))
@@ -526,7 +526,7 @@
   results = pool.map(RunCommand, commands, chunksize=1)
   for r in results:
     if r != 0:
-      print r.strip()
+      print (r.strip())
       return 1
 
   endtime = time.time()
diff --git a/tools/linux_dist_support/debian/rules b/tools/linux_dist_support/debian/rules
index 8c0665b..2ec324f 100755
--- a/tools/linux_dist_support/debian/rules
+++ b/tools/linux_dist_support/debian/rules
@@ -1,6 +1,8 @@
 #!/usr/bin/make -f
 export DH_VERBOSE = 1
 
+AOT_SUPPORTED_ARCHS := amd64 arm
+
 # Use DEB_BUILD_OPTIONS's parallel=n option (see Policy 4.9.1)
 ifneq (,$(findstring parallel,$(DEB_BUILD_OPTIONS)))
 PARALLEL_JOBS := $(shell echo $(DEB_BUILD_OPTIONS) | \
@@ -11,17 +13,21 @@
 
 ifeq (amd64,$(DEB_HOST_ARCH_CPU))
 BUILD_TYPE += ReleaseX64
+BUILD_TYPE_PRODUCT += ProductX64
 ARCH += x64
 else
 ifeq (i386,$(DEB_HOST_ARCH_CPU))
 BUILD_TYPE += ReleaseIA32
+BUILD_TYPE_PRODUCT += ProductIA32
 ARCH += ia32
 else
 ifeq (arm,$(DEB_HOST_ARCH_CPU))
 ifeq ($(DEB_BUILD_ARCH_CPU),$(DEB_HOST_ARCH_CPU))
 BUILD_TYPE += ReleaseARM
+BUILD_TYPE_PRODUCT += ProductARM
 else
 BUILD_TYPE += ReleaseXARM
+BUILD_TYPE_PRODUCT += ProductXARM
 endif
 ARCH += arm
 else
@@ -30,6 +36,22 @@
 endif
 endif
 
+# Only run AOT builds for supported archs.
+ifneq (,$(findstring $(DEB_HOST_ARCH_CPU),$(AOT_SUPPORTED_ARCHS)))
+AOT_BUILD_CMD := \
+python tools/build.py -v -m release -a $(ARCH) $(TOOLCHAIN) \
+		copy_gen_kernel_snapshot copy_dart2aot; \
+python tools/build.py -v -m product -a $(ARCH) $(TOOLCHAIN) \
+		copy_gen_snapshot copy_dartaotruntime; \
+mkdir -p out/$(BUILD_TYPE)/dart-sdk/bin/utils; \
+cp out/$(BUILD_TYPE_PRODUCT)/dart-sdk/bin/utils/gen_snapshot \
+		out/$(BUILD_TYPE)/dart-sdk/bin/utils/gen_snapshot; \
+cp out/$(BUILD_TYPE_PRODUCT)/dart-sdk/bin/dartaotruntime \
+		out/$(BUILD_TYPE)/dart-sdk/bin/dartaotruntime
+else
+AOT_BUILD_CMD := # empty
+endif
+
 # Verbose?
 ifeq (1,$(DH_VERBOSE))
 BUILD_ARGS += V=1
@@ -52,6 +74,7 @@
 override_dh_auto_build:
 	cd dart; \
 	python tools/build.py -v -m release -a $(ARCH) $(TOOLCHAIN) create_sdk; \
+	$(AOT_BUILD_CMD); \
 	cd ..
 
 # Building the Dart SDK will already strip all binaries.
diff --git a/tools/make_version.py b/tools/make_version.py
index d63dfa8..05f72e8 100755
--- a/tools/make_version.py
+++ b/tools/make_version.py
@@ -41,7 +41,8 @@
 ]
 
 def MakeVersionString(quiet, no_git_hash, custom_for_pub=None):
-  if custom_for_pub:
+  channel = utils.GetChannel()
+  if custom_for_pub and channel == 'be':
     latest = utils.GetLatestDevTag()
     if not latest:
       # If grabbing the dev tag fails, then fall back on the VERSION file.
@@ -67,9 +68,13 @@
   return vmhash.hexdigest()
 
 
-def MakeFile(quiet, output_file, input_file, no_git_hash, custom_for_pub):
+def MakeFile(quiet, output_file, input_file, no_git_hash, custom_for_pub, version_file=None):
+  if version_file:
+    version_string = utils.GetVersion(no_git_hash, version_file)
+  else:
+    version_string = MakeVersionString(quiet, no_git_hash, custom_for_pub)
+
   version_cc_text = open(input_file).read()
-  version_string = MakeVersionString(quiet, no_git_hash, custom_for_pub)
   version_cc_text = version_cc_text.replace("{{VERSION_STR}}",
                                             version_string)
   version_time = utils.GetGitTimestamp()
@@ -77,9 +82,9 @@
     version_time = "Unknown timestamp"
   version_cc_text = version_cc_text.replace("{{COMMIT_TIME}}",
                                             version_time)
-  abi_version = utils.GetAbiVersion()
+  abi_version = utils.GetAbiVersion(version_file)
   version_cc_text = version_cc_text.replace("{{ABI_VERSION}}", abi_version)
-  oldest_supported_abi_version = utils.GetOldestSupportedAbiVersion()
+  oldest_supported_abi_version = utils.GetOldestSupportedAbiVersion(version_file)
   version_cc_text = version_cc_text.replace("{{OLDEST_SUPPORTED_ABI_VERSION}}",
                                             oldest_supported_abi_version)
   snapshot_hash = MakeSnapshotHashString()
@@ -97,7 +102,8 @@
         action="store",
         type="string",
         help=("Generates a version string that works with pub that includes"
-              "the given string"))
+              "the given string. This is silently ignored on channels other"
+              "than be"))
     parser.add_option("--input",
         action="store",
         type="string",
@@ -114,6 +120,11 @@
         action="store_true",
         default=False,
         help="disable console output")
+    parser.add_option("--version-file",
+        action="store",
+        type="string",
+        default=None,
+        help="Version file")
 
     (options, args) = parser.parse_args()
 
@@ -126,7 +137,7 @@
       if options.output:
         open(options.output, 'w').write(version_string)
       else:
-        print version_string
+        print (version_string)
       return 0
 
     if not options.output:
@@ -141,11 +152,11 @@
       files.append(arg)
 
     if not MakeFile(options.quiet, options.output, options.input,
-                    options.no_git_hash, options.custom_for_pub):
+                    options.no_git_hash, options.custom_for_pub, options.version_file):
       return -1
 
     return 0
-  except Exception, inst:
+  except Exception as inst:
     sys.stderr.write('make_version.py exception\n')
     sys.stderr.write(str(inst))
     sys.stderr.write('\n')
diff --git a/tools/minidump.py b/tools/minidump.py
index 2f382e4..e74be94 100644
--- a/tools/minidump.py
+++ b/tools/minidump.py
@@ -158,7 +158,7 @@
       raise Exception('Unsupported minidump header magic')
     self.directories = []
     offset = self.header.stream_directories_rva
-    for _ in xrange(self.header.stream_count):
+    for _ in range(self.header.stream_count):
       self.directories.append(self.Read(MINIDUMP_DIRECTORY, offset))
       offset += MINIDUMP_DIRECTORY.size
 
diff --git a/tools/patches/flutter-engine/apply.sh b/tools/patches/flutter-engine/apply.sh
index 9c2bd33..06811d4 100755
--- a/tools/patches/flutter-engine/apply.sh
+++ b/tools/patches/flutter-engine/apply.sh
@@ -53,7 +53,7 @@
   # DEPS file might have been patched with new version of packages that
   # Dart SDK depends on. Get information about dependencies from the
   # DEPS file and forcefully update checkouts of those dependencies.
-  gclient.py revinfo | grep 'src/third_party/dart/' | while read -r line; do
+  gclient.py revinfo | grep 'src/third_party/dart/third_party' | while read -r line; do
     # revinfo would produce lines in the following format:
     #     path: git-url@tag-or-hash
     # Where no spaces occur inside path, git-url or tag-or-hash.
diff --git a/tools/patches/flutter-engine/b48c8b1d1c9050734c0491f4e36b7d61ef005233.patch b/tools/patches/flutter-engine/b48c8b1d1c9050734c0491f4e36b7d61ef005233.patch
new file mode 100644
index 0000000..1e357de
--- /dev/null
+++ b/tools/patches/flutter-engine/b48c8b1d1c9050734c0491f4e36b7d61ef005233.patch
@@ -0,0 +1,16 @@
+diff --git a/frontend_server/lib/server.dart b/frontend_server/lib/server.dart
+index 44a3d69b9..9620a5de0 100644
+--- a/frontend_server/lib/server.dart
++++ b/frontend_server/lib/server.dart
+@@ -85,11 +85,6 @@ Future<int> starter(
+       StringSink output,
+     }) async {
+   ArgResults options;
+-  frontend.argParser
+-    ..addFlag('track-widget-creation',
+-      help: 'Run a kernel transformer to track creation locations for widgets.',
+-      defaultsTo: false);
+-
+   try {
+     options = frontend.argParser.parse(args);
+   } catch (error) {
diff --git a/tools/patches/flutter-engine/cc63d6e647df1cfd34a54adb63aba7f937ce6f6b.patch b/tools/patches/flutter-engine/cc63d6e647df1cfd34a54adb63aba7f937ce6f6b.patch
deleted file mode 100644
index 5e81c49..0000000
--- a/tools/patches/flutter-engine/cc63d6e647df1cfd34a54adb63aba7f937ce6f6b.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-diff --git a/DEPS b/DEPS
-index d7973695e..1113c3101 100644
---- a/DEPS
-+++ b/DEPS
-@@ -52,7 +52,7 @@ vars = {
-   'dart_dartdoc_tag': 'v0.28.2',
-   'dart_fixnum_tag': '0.10.9',
-   'dart_glob_tag': '1.1.7',
--  'dart_html_tag': '0.13.4+1',
-+  'dart_html_tag': '0.14.0',
-   'dart_http_multi_server_tag': '2.0.5',
-   'dart_http_parser_tag': '3.1.3',
-   'dart_http_retry_tag': '0.1.1',
-@@ -94,7 +94,6 @@ vars = {
-   'dart_test_tag': '1.3.4',
-   'dart_typed_data_tag': '1.1.6',
-   'dart_usage_tag': '3.4.0',
--  'dart_utf_tag': '0.9.0+5',
-   'dart_watcher_rev': '0.9.7+12',
-   'dart_web_socket_channel_tag': '1.0.9',
-   'dart_yaml_tag': '2.1.15',
-@@ -341,9 +340,6 @@ deps = {
-   'src/third_party/dart/third_party/pkg/test':
-    Var('dart_git') + '/test.git' + '@' + Var('dart_test_tag'),
- 
--  'src/third_party/dart/third_party/pkg/utf':
--   Var('dart_git') + '/utf.git' + '@' + Var('dart_utf_tag'),
--
-   'src/third_party/dart/third_party/pkg/usage':
-    Var('dart_git') + '/usage.git' + '@' + Var('dart_usage_tag'),
- 
diff --git a/tools/patches/flutter-flutter/445a23a9bc14a57ea6275e5d4da179f7cb0bbdb6.patch b/tools/patches/flutter-flutter/445a23a9bc14a57ea6275e5d4da179f7cb0bbdb6.patch
new file mode 100644
index 0000000..ec58158
--- /dev/null
+++ b/tools/patches/flutter-flutter/445a23a9bc14a57ea6275e5d4da179f7cb0bbdb6.patch
@@ -0,0 +1,46 @@
+diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart
+index 7d450be42..e158e33af 100644
+--- a/packages/flutter_test/lib/src/binding.dart
++++ b/packages/flutter_test/lib/src/binding.dart
+@@ -1763,9 +1763,10 @@ class _MockHttpResponse extends Stream<List<int>> implements HttpClientResponse
+   @override
+   int get contentLength => -1;
+ 
+-  // @override
+-  // TODO(tvolkert): Uncomment @override annotation once SDK change lands.
+-  bool get autoUncompress => true;
++  @override
++  HttpClientResponseCompressionState get compressionState {
++    return HttpClientResponseCompressionState.decompressed;
++  }
+ 
+   @override
+   List<Cookie> get cookies => null;
+diff --git a/packages/flutter_tools/lib/src/base/io.dart b/packages/flutter_tools/lib/src/base/io.dart
+index 4c9d2250b..8b3535d54 100644
+--- a/packages/flutter_tools/lib/src/base/io.dart
++++ b/packages/flutter_tools/lib/src/base/io.dart
+@@ -47,6 +47,7 @@ export 'dart:io'
+         HttpClient,
+         HttpClientRequest,
+         HttpClientResponse,
++        HttpClientResponseCompressionState,
+         HttpHeaders,
+         HttpRequest,
+         HttpServer,
+diff --git a/packages/flutter_tools/test/commands/create_test.dart b/packages/flutter_tools/test/commands/create_test.dart
+index b5453cbb1..f7cdf6164 100644
+--- a/packages/flutter_tools/test/commands/create_test.dart
++++ b/packages/flutter_tools/test/commands/create_test.dart
+@@ -1172,6 +1172,11 @@ class MockHttpClientResponse extends Stream<List<int>> implements HttpClientResp
+   @override
+   String get reasonPhrase => '<reason phrase>';
+ 
++  @override
++  HttpClientResponseCompressionState get compressionState {
++    return HttpClientResponseCompressionState.decompressed;
++  }
++
+   @override
+   StreamSubscription<List<int>> listen(
+     void onData(List<int> event), {
diff --git a/tools/patches/flutter-flutter/apply.sh b/tools/patches/flutter-flutter/apply.sh
index 47043f0..2b3a280 100755
--- a/tools/patches/flutter-flutter/apply.sh
+++ b/tools/patches/flutter-flutter/apply.sh
@@ -23,3 +23,9 @@
 if [ -e "$patch" ]; then
   (cd flutter && git apply ../$patch)
 fi
+
+pinned_dart_sdk=$(get_pinned_dart_version)
+patch=src/third_party/dart/tools/patches/flutter-flutter/${pinned_dart_sdk}.patch
+if [ -e "$patch" ]; then
+  (cd flutter && git apply ../$patch)
+fi
diff --git a/tools/run_abi_tests.py b/tools/run_abi_tests.py
new file mode 100644
index 0000000..7bb4919
--- /dev/null
+++ b/tools/run_abi_tests.py
@@ -0,0 +1,177 @@
+# Copyright (c) 2019, 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.
+
+# Runs tests with old ABI versions and check if the results differ from the
+# current results.
+
+import json
+import os
+import subprocess
+import sys
+import time
+import utils
+
+
+scriptDir = os.path.dirname(os.path.realpath(__file__))
+outDir = os.path.join(scriptDir, '..', 'out', 'ReleaseX64')
+
+
+# Info about a running test.
+class Test:
+  def __init__(self, cmd, resultFile, logFile, version):
+    self.cmd = cmd  # The test command.
+    self.resultFile = resultFile  # The expected location of the result file.
+    self.logFile = logFile  # The expected location of the log file.
+    self.version = version  # The ABI version, or None.
+
+
+# Recursively make directories for the path.
+def makeDirs(path):
+  try:
+    os.makedirs(path)
+  except OSError:
+    pass
+
+
+# Build a Test object for the given version (or None).
+def buildTest(version):
+  testDir = os.path.join(
+    outDir, 'test%s' % ('' if version is None else str(version)))
+  logDir = os.path.join(testDir, 'logs')
+  makeDirs(logDir)
+
+  vm_options = ['--enable-interpreter']
+  if version is not None:
+    vm_options += ['--use-abi-version=%d' % version]
+  cmd = [
+      'python',
+      os.path.join(scriptDir, 'test.py'),
+      '--compiler=dartkb',
+      '--mode=release',
+      '--write-results',
+      '--write-logs',
+      '--output_directory=%s' % logDir,
+      '--vm-options=%s' % ' '.join(vm_options),
+      'lib_2',
+  ]
+
+  resultFile = os.path.join(logDir, 'results.json')
+  logFile = os.path.join(logDir, 'logs.json')
+  return Test(cmd, resultFile, logFile, version)
+
+
+# Build tests for every supported version, and return a list of Test objects.
+def buildAllTests():
+  abi_version = int(utils.GetAbiVersion())
+  oldest_abi_version = int(utils.GetOldestSupportedAbiVersion())
+  tests = [buildTest(None)]
+  for version in xrange(oldest_abi_version, abi_version + 1):
+    tests.append(buildTest(version))
+  return tests
+
+
+# Run all tests, one by one, and wait for them all to complete.
+def runAllTests(tests):
+  for test in tests:
+    print('\n\n\n=== Running tests %s ===' % (
+        ('for ABI version %d' % test.version) if test.version is not None else
+        ('without an ABI version')))
+    print(subprocess.list2cmdline(test.cmd) + '\n\n')
+    proc = subprocess.Popen(test.cmd)
+    while proc.returncode is None:
+      time.sleep(1)
+      proc.communicate()
+      proc.poll()
+
+
+# Read a test result file or log file and convert JSON lines to a dictionary of
+# JSON records indexed by name. Assumes result and log files both use name key.
+def readTestFile(fileName):
+  with open(fileName, 'r') as f:
+    return { r['name']: r for r in [json.loads(line) for line in f]}
+
+
+# Read the test result or log files for every version and return a dict like:
+# {name: {version: resultJson, ...}, ...}
+def readAllTestFiles(tests, nameGetter):
+  allRecords = {}
+  for test in tests:
+    records = readTestFile(nameGetter(test))
+    for name, result in records.items():
+      if name not in allRecords:
+        allRecords[name] = {}
+      allRecords[name][test.version] = result
+  return allRecords
+
+
+# Pick any element of the dictionary, favoring the None key if it exists.
+def pickOne(d):
+  if None in d:
+    return d[None]
+  for v in d.values():
+    return v
+  return None
+
+
+# Diff the results of a test for each version and construct a new test result
+# that reports whether the test results match for each version.
+def diffResults(results):
+  outResult = pickOne(results)
+  exp = results[None]['result'] if None in results else None
+  outResult['expected'] = exp
+  outResult['result'] = exp
+  outResult['matches'] = True
+  diffs = []
+  for version, result in results.items():
+    if version is not None:
+      act = result['result']
+      if exp != act:
+        diffs.append(version)
+        outResult['result'] = act  # May be overwritten by other versions.
+        outResult['matches'] = False
+  return outResult, diffs
+
+
+# Create a log entry for a test that has diffs. Concatenate all the log records
+# and include which tests failed.
+def makeLog(diffs, results, logRecords):
+  result = pickOne(results)
+  logs = ["%s: %s" % (str(v), l['log']) for v, l in logRecords.items()]
+  return {
+    'name': result['name'],
+    'configuration': result['configuration'],
+    'result': result['result'],
+    'log': '\n\n\n'.join([repr(diffs)] + logs),
+  }
+
+
+# Diff the results of all the tests and create the merged result and log files.
+def diffAllResults(tests):
+  allResults = readAllTestFiles(tests, lambda test: test.resultFile)
+  allLogs = readAllTestFiles(tests, lambda test: test.logFile)
+  anyDiff = False
+  logDir = os.path.join(outDir, 'logs')
+  makeDirs(logDir)
+  resultFileName = os.path.join(logDir, 'results.json')
+  logFileName = os.path.join(logDir, 'logs.json')
+  with open(resultFileName, 'w') as resultFile:
+    with open(logFileName, 'w') as logFile:
+      for name, results in allResults.items():
+        outResult, diffs = diffResults(results)
+        resultFile.write(json.dumps(outResult) + '\n')
+        if diffs:
+          logRecords = allLogs[name] if name in allLogs else []
+          logFile.write(json.dumps(makeLog(diffs, results, logRecords)) + '\n')
+          anyDiff = True
+  return anyDiff
+
+
+def main():
+  tests = buildAllTests()
+  runAllTests(tests)
+  return 1 if diffAllResults(tests) else 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/tools/run_offsets_extractor.sh b/tools/run_offsets_extractor.sh
new file mode 100755
index 0000000..4e1a5ad
--- /dev/null
+++ b/tools/run_offsets_extractor.sh
@@ -0,0 +1,42 @@
+#!/usr/bin/env bash
+# Copyright (c) 2019, 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.
+
+set -e
+
+FILE="runtime/vm/compiler/runtime_offsets_extracted.h"
+
+# Make sure we're running in the SDK directory.
+if ! test -f "$FILE"; then
+  echo "Couldn't find $FILE"
+  echo "Make sure to run this script from the Dart SDK directory."
+  exit 1
+fi
+
+# We're regenerating the file, but we want to keep all the comments etc at the
+# top of the file. So just delete everything after the first "#if defined".
+LINE=$(grep "#if defined" "$FILE" -n | head -n 1 | sed "s/^\([0-9]*\):.*/\1/")
+TEMP="${FILE}.temp"
+head -n $(expr $LINE - 1) "$FILE" >"$TEMP"
+
+# Run offsets_extractor for every architecture and append the results.
+run() {
+  echo "" >>"$TEMP"
+  tools/gn.py --mode=release --arch=$1
+  tools/build.py --mode=release --arch=$1 offsets_extractor
+  out/$2/offsets_extractor >>"$TEMP"
+}
+run simarm ReleaseSIMARM
+run x64 ReleaseX64
+run ia32 ReleaseIA32
+run simarm64 ReleaseSIMARM64
+run simdbc64 ReleaseSIMDBC64
+run simdbc ReleaseSIMDBC
+
+# Cleanup.
+echo "" >>"$TEMP"
+echo "#endif  // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_" >>"$TEMP"
+mv "$TEMP" "$FILE"
+git cl format "$FILE"
+echo -e "\n\nSuccessfully generated $FILE :)"
diff --git a/tools/spec_parser/Dart.g b/tools/spec_parser/Dart.g
index 0a95229..dd71d27 100644
--- a/tools/spec_parser/Dart.g
+++ b/tools/spec_parser/Dart.g
@@ -46,7 +46,7 @@
     return !errorHasOccurred;
   }
 
-  // Enable the parser to treat ASYNC/AWAIT/YIELD as keywords in the body of an
+  // Enable the parser to treat AWAIT/YIELD as keywords in the body of an
   // `async`, `async*`, or `sync*` function. Access via methods below.
   private Stack<Boolean> asyncEtcAreKeywords = new Stack<Boolean>();
   { asyncEtcAreKeywords.push(false); }
@@ -62,9 +62,9 @@
   // Use this to indicate that we are now leaving any funciton.
   void endFunction() { asyncEtcAreKeywords.pop(); }
 
-  // Whether we can recognize ASYNC/AWAIT/YIELD as an identifier/typeIdentifier.
+  // Whether we can recognize AWAIT/YIELD as an identifier/typeIdentifier.
   boolean asyncEtcPredicate(int tokenId) {
-    if (tokenId == ASYNC || tokenId == AWAIT || tokenId == YIELD) {
+    if (tokenId == AWAIT || tokenId == YIELD) {
       return !asyncEtcAreKeywords.peek();
     }
     return false;
@@ -261,12 +261,12 @@
     :    normalFormalParameter ((':' | '=') expression)?
     ;
 
-typeApplication
+typeWithParameters
     :    typeIdentifier typeParameters?
     ;
 
 classDeclaration
-    :    ABSTRACT? CLASS typeApplication (superclass mixins?)? interfaces?
+    :    ABSTRACT? CLASS typeWithParameters superclass? mixins? interfaces?
          LBRACE (metadata classMemberDefinition)* RBRACE
     |    ABSTRACT? CLASS mixinApplicationClass
     ;
@@ -419,7 +419,7 @@
     ;
 
 mixinApplicationClass
-    :    typeApplication '=' mixinApplication ';'
+    :    typeWithParameters '=' mixinApplication ';'
     ;
 
 mixinApplication
@@ -545,7 +545,7 @@
     ;
 
 ifElement
-    : IF '(' expression ')' element ('else' element)?
+    : IF '(' expression ')' element (ELSE element)?
     ;
 
 forElement
@@ -648,6 +648,7 @@
     |    '+='
     |    '-='
     |    '<<='
+    |    '>' '>' '>' '='
     |    '>' '>' '='
     |    '&='
     |    '^='
@@ -723,6 +724,7 @@
 
 shiftOperator
     :    '<<'
+    |    '>' '>' '>'
     |    '>' '>'
     ;
 
@@ -778,10 +780,6 @@
     :    AWAIT unaryExpression
     ;
 
-// The `(selector)` predicate ensures that the parser commits to the longest
-// possible chain of selectors, e.g., `a<b,c>(d)` as a call rather than as a
-// sequence of two relational expressions.
-
 postfixExpression
     :    assignableExpression postfixOperator
     |    constructorInvocation selector*
@@ -810,17 +808,9 @@
     |    '--'
     ;
 
-// The `(assignableSelectorPart)` predicate ensures that the parser
-// commits to the longest possible chain, e.g., `a<b,c>(d).e` as one rather
-// than two expressions. The first `identifier` alternative handles all
-// the simple cases; the final `identifier` alternative at the end catches
-// the case where we have `identifier '<'` and the '<' is used as a
-// relationalOperator, not the beginning of typeArguments.
-
 assignableExpression
     :    SUPER unconditionalAssignableSelector
     |    constructorInvocation assignableSelectorPart+
-    |    identifier
     |    primary assignableSelectorPart+
     |    identifier
     ;
@@ -860,12 +850,13 @@
     |    SET // Built-in identifier.
     |    STATIC // Built-in identifier.
     |    TYPEDEF // Built-in identifier.
+    |    ASYNC // Not a built-in identifier.
     |    HIDE // Not a built-in identifier.
     |    OF // Not a built-in identifier.
     |    ON // Not a built-in identifier.
     |    SHOW // Not a built-in identifier.
     |    SYNC // Not a built-in identifier.
-    |    { asyncEtcPredicate(getCurrentToken().getType()) }? (ASYNC|AWAIT|YIELD)
+    |    { asyncEtcPredicate(getCurrentToken().getType()) }? (AWAIT|YIELD)
     ;
 
 identifier
@@ -882,12 +873,13 @@
 typeIdentifier
     :    IDENTIFIER
     |    DYNAMIC // Built-in identifier that can be used as a type.
+    |    ASYNC // Not a built-in identifier.
     |    HIDE // Not a built-in identifier.
     |    OF // Not a built-in identifier.
     |    ON // Not a built-in identifier.
     |    SHOW // Not a built-in identifier.
     |    SYNC // Not a built-in identifier.
-    |    { asyncEtcPredicate(getCurrentToken().getType()) }? (ASYNC|AWAIT|YIELD)
+    |    { asyncEtcPredicate(getCurrentToken().getType()) }? (AWAIT|YIELD)
     ;
 
 typeTest
diff --git a/tools/test.dart b/tools/test.dart
index ae5213c..edb0f8c 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -3,7 +3,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Run tests like on the given builder.
+// Run tests like on the given builder and/or named configuration.
 
 import 'dart:async';
 import 'dart:collection';
@@ -55,7 +55,7 @@
       await Process.run(executable, arguments, runInShell: runInShell);
   if (processResult.exitCode != 0) {
     final command =
-        ([executable]..addAll(arguments)).map(simpleShellSingleQuote).join(" ");
+        [executable, ...arguments].map(simpleShellSingleQuote).join(" ");
     throw new Exception("Command exited ${processResult.exitCode}: $command\n"
         "${processResult.stdout}\n${processResult.stderr}");
   }
@@ -73,7 +73,7 @@
   final processResult = new ProcessResult(process.pid, exitCode, "", "");
   if (processResult.exitCode != 0) {
     final command =
-        ([executable]..addAll(arguments)).map(simpleShellSingleQuote).join(" ");
+        [executable, ...arguments].map(simpleShellSingleQuote).join(" ");
     throw new Exception("Command exited ${processResult.exitCode}: $command");
   }
   return processResult;
@@ -319,12 +319,18 @@
 void main(List<String> args) async {
   final parser = new ArgParser();
   parser.addOption("builder",
-      abbr: "b", help: "Run tests like on the given buider");
+      abbr: "b", help: "Run tests like on the given builder");
   parser.addOption("branch",
       abbr: "B",
       help: "Select the builders building this branch",
       defaultsTo: "master");
   parser.addOption("commit", abbr: "C", help: "Compare with this commit");
+  parser.addFlag("deflake",
+      help: "Re-run failing newly tests $deflakingCount times.");
+  parser.addFlag("report-flakes",
+      help: "Report test failures for tests known to be flaky.\n"
+          "This ignores all flakiness data from CI but flakes\n"
+          "detected by --deflake will remain hidden");
   parser.addFlag("list-configurations",
       help: "Output list of configurations.", negatable: false);
   parser.addOption("named-configuration",
@@ -354,8 +360,8 @@
 
 Run tests and compare with the results on the given builder. Either the -n or
 the -b option, or both, must be used. Any options following -- and non-option
-arguments will be forwarded to test.py invocations. The results for the specified
-named configuration will be downloaded from the specified builder. If only a
+arguments will be forwarded to test.py invocations. The specified named
+configuration's results will be downloaded from the specified builder. If only a
 named configuration is specified, the results are downloaded from the
 appropriate builders. If only a builder is specified, the default named
 configuration is used if the builder only has a single named configuration.
@@ -404,7 +410,7 @@
     exitCode = 1;
     return;
   }
-  if (2 <= namedConfigurations.length) {
+  if (namedConfigurations.length > 1) {
     final builder = builders.single;
     stderr.writeln(
         "error: The builder $builder is testing multiple named configurations");
@@ -418,7 +424,7 @@
   }
   final namedConfiguration = namedConfigurations.single;
   final localConfiguration =
-      options["local-configuration"] ?? namedConfiguration;
+      options["local-configuration"] as String ?? namedConfiguration;
   for (final builder in builders) {
     if (localConfiguration != namedConfiguration) {
       print("Testing the named configuration $localConfiguration "
@@ -452,28 +458,34 @@
             "as baseline instead of $commit for $builder");
         inexactBuilds[builder] = buildSearchResult.commit;
       }
-      final buildNumber = buildSearchResult.build;
+      final buildNumber = buildSearchResult.build.toString();
       print("Downloading results from builder $builder build $buildNumber...");
-      await cpGsutil(
-          buildFileCloudPath(builder, buildNumber.toString(), "results.json"),
+      await cpGsutil(buildFileCloudPath(builder, buildNumber, "results.json"),
           "${outDirectory.path}/previous.json");
-      await cpGsutil(
-          buildFileCloudPath(builder, buildNumber.toString(), "flaky.json"),
-          "${outDirectory.path}/flaky.json");
+      if (!options["report-flakes"]) {
+        await cpGsutil(buildFileCloudPath(builder, buildNumber, "flaky.json"),
+            "${outDirectory.path}/flaky.json");
+      }
       print("Downloaded baseline results from builder $builder");
       // Merge the results for the builders.
-      if (2 <= builders.length) {
+      if (builders.length > 1) {
         mergedResults
             .addAll(await loadResultsMap("${outDirectory.path}/previous.json"));
-        mergedFlaky
-            .addAll(await loadResultsMap("${outDirectory.path}/flaky.json"));
+        if (!options["report-flakes"]) {
+          mergedFlaky
+              .addAll(await loadResultsMap("${outDirectory.path}/flaky.json"));
+        }
       }
     }
 
     // Write out the merged results for the builders.
-    if (2 <= builders.length) {
+    if (builders.length > 1) {
       await new File("${outDirectory.path}/previous.json").writeAsString(
           mergedResults.values.map((data) => jsonEncode(data) + "\n").join(""));
+    }
+
+    // Ensure that there is a flaky.json even if it wasn't downloaded.
+    if (builders.length > 1 || options["report-flakes"]) {
       await new File("${outDirectory.path}/flaky.json").writeAsString(
           mergedFlaky.values.map((data) => jsonEncode(data) + "\n").join(""));
     }
@@ -502,62 +514,18 @@
       "--silent-failures",
       "--write-results",
       "--write-logs",
-    ]..addAll(options.rest);
+      ...options.rest,
+    ];
     print("".padLeft(80, "="));
     print("Running tests");
     print("".padLeft(80, "="));
-    await runProcessInheritStdio("python", ["tools/test.py"]..addAll(arguments),
+    await runProcessInheritStdio("python", ["tools/test.py", ...arguments],
         runInShell: Platform.isWindows);
 
-    // Find the list of tests to deflake.
-    final deflakeListOutput = await runProcess(Platform.resolvedExecutable, [
-      "tools/bots/compare_results.dart",
-      "--changed",
-      "--failing",
-      "--passing",
-      "--flakiness-data=${outDirectory.path}/flaky.json",
-      "${outDirectory.path}/previous.json",
-      "${outDirectory.path}/results.json",
-    ]);
-    final deflakeListPath = "${outDirectory.path}/deflake.list";
-    final deflakeListFile = new File(deflakeListPath);
-    await deflakeListFile.writeAsString(deflakeListOutput.stdout);
-
-    // Deflake the changed tests.
-    final deflakingResultsPaths = <String>[];
-    for (int i = 1;
-        deflakeListOutput.stdout != "" && i <= deflakingCount;
-        i++) {
-      print("".padLeft(80, "="));
-      print("Running deflaking iteration $i");
-      print("".padLeft(80, "="));
-      final deflakeDirectory = new Directory("${outDirectory.path}/$i");
-      await deflakeDirectory.create();
-      final deflakeArguments = <String>[
-        "--named-configuration=$localConfiguration",
-        "--output-directory=${deflakeDirectory.path}",
-        "--clean-exit",
-        "--silent-failures",
-        "--write-results",
-        "--test-list=$deflakeListPath",
-      ]..addAll(options.rest);
-      await runProcessInheritStdio(
-          "python", ["tools/test.py"]..addAll(deflakeArguments),
-          runInShell: Platform.isWindows);
-      deflakingResultsPaths.add("${deflakeDirectory.path}/results.json");
+    if (options["deflake"]) {
+      await deflake(outDirectory, localConfiguration, options.rest);
     }
 
-    // Update the flakiness information based on what we've learned.
-    print("Updating flakiness information...");
-    await runProcess(
-        Platform.resolvedExecutable,
-        [
-          "tools/bots/update_flakiness.dart",
-          "--input=${outDirectory.path}/flaky.json",
-          "--output=${outDirectory.path}/flaky.json",
-          "${outDirectory.path}/results.json",
-        ]..addAll(deflakingResultsPaths));
-
     // Write out the final comparison.
     print("".padLeft(80, "="));
     print("Test Results");
@@ -589,3 +557,53 @@
     await outDirectory.delete(recursive: true);
   }
 }
+
+void deflake(Directory outDirectory, String localConfiguration,
+    List<String> testPyArgs) async {
+  // Find the list of tests to deflake.
+  final deflakeListOutput = await runProcess(Platform.resolvedExecutable, [
+    "tools/bots/compare_results.dart",
+    "--changed",
+    "--failing",
+    "--passing",
+    "--flakiness-data=${outDirectory.path}/flaky.json",
+    "${outDirectory.path}/previous.json",
+    "${outDirectory.path}/results.json",
+  ]);
+  final deflakeListPath = "${outDirectory.path}/deflake.list";
+  final deflakeListFile = new File(deflakeListPath);
+  await deflakeListFile.writeAsString(deflakeListOutput.stdout);
+
+  // Deflake the changed tests.
+  final deflakingResultsPaths = <String>[];
+  for (int i = 1; deflakeListOutput.stdout != "" && i <= deflakingCount; i++) {
+    print("".padLeft(80, "="));
+    print("Running deflaking iteration $i");
+    print("".padLeft(80, "="));
+    final deflakeDirectory = new Directory("${outDirectory.path}/$i");
+    await deflakeDirectory.create();
+    final deflakeArguments = <String>[
+      "--named-configuration=$localConfiguration",
+      "--output-directory=${deflakeDirectory.path}",
+      "--clean-exit",
+      "--silent-failures",
+      "--write-results",
+      "--test-list=$deflakeListPath",
+      ...testPyArgs,
+    ];
+    await runProcessInheritStdio(
+        "python", ["tools/test.py", ...deflakeArguments],
+        runInShell: Platform.isWindows);
+    deflakingResultsPaths.add("${deflakeDirectory.path}/results.json");
+  }
+
+  // Update the flakiness information based on what we've learned.
+  print("Updating flakiness information...");
+  await runProcess(Platform.resolvedExecutable, [
+    "tools/bots/update_flakiness.dart",
+    "--input=${outDirectory.path}/flaky.json",
+    "--output=${outDirectory.path}/flaky.json",
+    "${outDirectory.path}/results.json",
+    ...deflakingResultsPaths,
+  ]);
+}
diff --git a/tools/testing/dart/babel_transform.js b/tools/testing/dart/babel_transform.js
new file mode 100644
index 0000000..5229e8a
--- /dev/null
+++ b/tools/testing/dart/babel_transform.js
@@ -0,0 +1,12 @@
+// Copyright (c) 2019, 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.
+
+
+const babelStandalonePath = arguments[0];
+load(babelStandalonePath);
+const inputFilePath = arguments[2];
+const input = read(inputFilePath);
+const options = JSON.parse(arguments[1]);
+const output = Babel.transform(input, options).code;
+console.log(output);
diff --git a/tools/testing/dart/command.dart b/tools/testing/dart/command.dart
index d89b964..2eb7648 100644
--- a/tools/testing/dart/command.dart
+++ b/tools/testing/dart/command.dart
@@ -76,10 +76,15 @@
         checked: checked);
   }
 
-  static Command adbPrecompiled(String precompiledRunner, String processTest,
-      String testDirectory, List<String> arguments, bool useBlobs) {
-    return new AdbPrecompilationCommand._(
-        precompiledRunner, processTest, testDirectory, arguments, useBlobs);
+  static Command adbPrecompiled(
+      String precompiledRunner,
+      String processTest,
+      String testDirectory,
+      List<String> arguments,
+      bool useBlobs,
+      bool useElf) {
+    return new AdbPrecompilationCommand._(precompiledRunner, processTest,
+        testDirectory, arguments, useBlobs, useElf);
   }
 
   static Command adbDartk(String precompiledRunner, String processTest,
@@ -252,7 +257,8 @@
 }
 
 class CompilationCommand extends ProcessCommand {
-  final String _outputFile;
+  /// The primary output file that will be created by this command.
+  final String outputFile;
 
   /// If true, then the compilation is run even if the input files are older
   /// than the output file.
@@ -261,7 +267,7 @@
 
   CompilationCommand._(
       String displayName,
-      this._outputFile,
+      this.outputFile,
       this._alwaysCompile,
       this._bootstrapDependencies,
       String executable,
@@ -274,7 +280,7 @@
 
   CompilationCommand indexedCopy(int index) => CompilationCommand._(
       displayName,
-      _outputFile,
+      outputFile,
       _alwaysCompile,
       _bootstrapDependencies,
       executable,
@@ -286,7 +292,7 @@
   bool get outputIsUpToDate {
     if (_alwaysCompile) return false;
 
-    var file = new io.File(new Path("$_outputFile.deps").toNativePath());
+    var file = new io.File(new Path("$outputFile.deps").toNativePath());
     if (!file.existsSync()) return false;
 
     var lines = file.readAsLinesSync();
@@ -300,7 +306,7 @@
 
     dependencies.addAll(_bootstrapDependencies);
     var jsOutputLastModified = TestUtils.lastModifiedCache
-        .getLastModified(new Uri(scheme: 'file', path: _outputFile));
+        .getLastModified(new Uri(scheme: 'file', path: outputFile));
     if (jsOutputLastModified == null) return false;
 
     for (var dependency in dependencies) {
@@ -316,14 +322,14 @@
 
   void _buildHashCode(HashCodeBuilder builder) {
     super._buildHashCode(builder);
-    builder.addJson(_outputFile);
+    builder.addJson(outputFile);
     builder.addJson(_alwaysCompile);
     builder.addJson(_bootstrapDependencies);
   }
 
   bool _equal(CompilationCommand other) =>
       super._equal(other) &&
-      _outputFile == other._outputFile &&
+      outputFile == other.outputFile &&
       _alwaysCompile == other._alwaysCompile &&
       deepJsonCompare(_bootstrapDependencies, other._bootstrapDependencies);
 }
@@ -347,7 +353,7 @@
   @override
   FastaCompilationCommand indexedCopy(int index) => FastaCompilationCommand._(
       _compilerLocation,
-      _outputFile,
+      outputFile,
       _bootstrapDependencies,
       executable,
       arguments,
@@ -437,7 +443,7 @@
 
   VMKernelCompilationCommand indexedCopy(int index) =>
       VMKernelCompilationCommand._(
-          _outputFile,
+          outputFile,
           _alwaysCompile,
           _bootstrapDependencies,
           executable,
@@ -589,6 +595,7 @@
   final String precompiledTestDirectory;
   final List<String> arguments;
   final bool useBlobs;
+  final bool useElf;
 
   AdbPrecompilationCommand._(
       this.precompiledRunnerFilename,
@@ -596,6 +603,7 @@
       this.precompiledTestDirectory,
       this.arguments,
       this.useBlobs,
+      this.useElf,
       {int index = 0})
       : super._("adb_precompilation", index: index);
 
@@ -605,6 +613,7 @@
       precompiledTestDirectory,
       arguments,
       useBlobs,
+      useElf,
       index: index);
   _buildHashCode(HashCodeBuilder builder) {
     super._buildHashCode(builder);
@@ -612,12 +621,14 @@
     builder.add(precompiledTestDirectory);
     builder.add(arguments);
     builder.add(useBlobs);
+    builder.add(useElf);
   }
 
   bool _equal(AdbPrecompilationCommand other) =>
       super._equal(other) &&
       precompiledRunnerFilename == other.precompiledRunnerFilename &&
       useBlobs == other.useBlobs &&
+      useElf == other.useElf &&
       arguments == other.arguments &&
       precompiledTestDirectory == other.precompiledTestDirectory;
 
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 9edb9fb..c67ae47 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -118,8 +118,6 @@
     }
   }
 
-  // TODO(ahe): It shouldn't be necessary to pass [buildDir] to any of these
-  // functions. It is fixed for a given configuration.
   String computeCompilerPath() {
     throw "Unknown compiler for: $runtimeType";
   }
@@ -130,15 +128,6 @@
 
   List<Uri> bootstrapDependencies() => const <Uri>[];
 
-  /// Creates a [Command] to compile [inputFile] to [outputFile].
-  Command createCommand(String inputFile, String outputFile,
-      List<String> sharedOptions, Map<String, String> environment) {
-    // TODO(rnystrom): See if this method can be unified with
-    // computeCompilationArtifact() and/or computeCompilerArguments() for the
-    // other compilers.
-    throw new UnsupportedError("$this does not support createCommand().");
-  }
-
   CommandArtifact computeCompilationArtifact(
 
       /// Each test has its own temporary directory to avoid name collisions.
@@ -486,10 +475,26 @@
       List<String> arguments, Map<String, String> environmentOverrides) {
     var compilerArguments = arguments.toList()
       ..addAll(_configuration.dart2jsOptions);
-    return new CommandArtifact([
-      computeCompilationCommand(
-          '$tempDir/out.js', compilerArguments, environmentOverrides)
-    ], '$tempDir/out.js', 'application/javascript');
+
+    var commands = <Command>[];
+    // TODO(athom): input filename extraction is copied from DDC. Maybe this
+    // should be passed to computeCompilationArtifact, instead?
+    var inputFile = arguments.last;
+    var inputFilename = (new Uri.file(inputFile)).pathSegments.last;
+    var out = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}";
+    var babel = _configuration.babel;
+    var babelOut = out;
+    if (babel != null && babel.isNotEmpty) {
+      out = out.replaceAll('.js', '.raw.js');
+    }
+    commands.add(computeCompilationCommand(
+        out, compilerArguments, environmentOverrides));
+
+    if (babel != null && babel.isNotEmpty) {
+      commands.add(computeBabelCommand(out, babelOut, babel));
+    }
+
+    return new CommandArtifact(commands, babelOut, 'application/javascript');
   }
 
   List<String> computeRuntimeArguments(
@@ -507,6 +512,22 @@
     return runtimeConfiguration.dart2jsPreambles(preambleDir)
       ..add(artifact.filename);
   }
+
+  Command computeBabelCommand(String input, String output, String options) {
+    var uri = Repository.uri;
+    var babelTransform =
+        uri.resolve('tools/testing/dart/babel_transform.js').toFilePath();
+    var babelStandalone =
+        uri.resolve('third_party/babel/babel.min.js').toFilePath();
+    return Command.compilation(
+        'babel',
+        output,
+        [],
+        _configuration.runtimeConfiguration.d8FileName,
+        [babelTransform, "--", babelStandalone, options, input],
+        {},
+        alwaysCompile: true); // TODO(athom): ensure dependency tracking works.
+  }
 }
 
 /// Configuration for `dartdevc` and `dartdevk` (DDC with Kernel)
@@ -537,7 +558,7 @@
     return result;
   }
 
-  Command createCommand(String inputFile, String outputFile,
+  Command _createCommand(String inputFile, String outputFile,
       List<String> sharedOptions, Map<String, String> environment) {
     /// This can be disabled to test DDC's hybrid mode (automatically converting
     /// Analyzer summaries to Kernel files).
@@ -629,7 +650,7 @@
     var outputFile = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}";
 
     return new CommandArtifact(
-        [createCommand(inputFile, outputFile, sharedOptions, environment)],
+        [_createCommand(inputFile, outputFile, sharedOptions, environment)],
         outputFile,
         "application/javascript");
   }
@@ -673,7 +694,7 @@
           tempDir, arguments, environmentOverrides));
     }
 
-    if (!_configuration.useBlobs) {
+    if (!_configuration.useBlobs && !_configuration.useElf) {
       commands.add(
           computeAssembleCommand(tempDir, arguments, environmentOverrides));
       if (!_configuration.keepGeneratedFiles) {
@@ -712,21 +733,26 @@
   Command computeDartBootstrapCommand(String tempDir, List<String> arguments,
       Map<String, String> environmentOverrides) {
     var buildDir = _configuration.buildDirectory;
-    String exec;
-    if (_isAndroid) {
-      if (_isArm) {
-        exec = "$buildDir/clang_x86/gen_snapshot";
-      } else if (_configuration.architecture == Architecture.arm64) {
-        exec = "$buildDir/clang_x64/gen_snapshot";
+    String exec = _configuration.genSnapshotPath;
+    if (exec == null) {
+      if (_isAndroid) {
+        if (_isArm) {
+          exec = "$buildDir/clang_x86/gen_snapshot";
+        } else if (_configuration.architecture == Architecture.arm64) {
+          exec = "$buildDir/clang_x64/gen_snapshot";
+        }
+      } else {
+        exec = "$buildDir/gen_snapshot";
       }
-    } else {
-      exec = "$buildDir/gen_snapshot";
     }
 
     final args = <String>[];
     if (_configuration.useBlobs) {
       args.add("--snapshot-kind=app-aot-blobs");
       args.add("--blobs_container_filename=$tempDir/out.aotsnapshot");
+    } else if (_configuration.useElf) {
+      args.add("--snapshot-kind=app-aot-elf");
+      args.add("--elf=$tempDir/out.aotsnapshot");
     } else {
       args.add("--snapshot-kind=app-aot-assembly");
       args.add("--assembly=$tempDir/out.S");
@@ -1146,14 +1172,17 @@
         !arguments.any((String arg) => noCausalAsyncStacksRegExp.hasMatch(arg));
     args.add('-Ddart.developer.causal_async_stacks=$causalAsyncStacks');
 
-    if (_useEnableAsserts) {
-      args.add('--enable_asserts');
+    if (_useEnableAsserts ||
+        arguments.contains('--enable-asserts') ||
+        arguments.contains('--enable_asserts')) {
+      args.add('--enable-asserts');
     }
 
     if (_configuration.useKernelBytecode) {
       args.add('--gen-bytecode');
       args.add('--drop-ast');
       args.add('--emit-bytecode-source-positions');
+      args.add('--emit-bytecode-local-var-info');
     }
 
     return Command.vmKernelCompilation(dillFile, true, bootstrapDependencies(),
@@ -1200,12 +1229,6 @@
   List<Uri> bootstrapDependencies() => [_platformDill];
 
   @override
-  Command createCommand(String inputFile, String outputFile,
-      List<String> sharedOptions, Map<String, String> environment) {
-    throw new UnimplementedError();
-  }
-
-  @override
   CommandArtifact computeCompilationArtifact(String tempDir,
       List<String> arguments, Map<String, String> environmentOverrides) {
     var output =
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index 85a0433..da990fb9 100644
--- a/tools/testing/dart/configuration.dart
+++ b/tools/testing/dart/configuration.dart
@@ -50,6 +50,7 @@
       this.firefoxPath,
       this.dartPath,
       this.dartPrecompiledPath,
+      this.genSnapshotPath,
       this.taskCount,
       this.shardCount,
       this.shard,
@@ -114,6 +115,7 @@
   bool get useAnalyzerCfe => configuration.useAnalyzerCfe;
   bool get useAnalyzerFastaParser => configuration.useAnalyzerFastaParser;
   bool get useBlobs => configuration.useBlobs;
+  bool get useElf => configuration.useElf;
   bool get useSdk => configuration.useSdk;
   bool get useEnableAsserts => configuration.enableAsserts;
 
@@ -125,6 +127,7 @@
   final String firefoxPath;
   final String dartPath;
   final String dartPrecompiledPath;
+  final String genSnapshotPath;
   final List<String> testList;
 
   final int taskCount;
@@ -162,6 +165,7 @@
   final String outputDirectory;
   final String packageRoot;
   final String suiteDirectory;
+  String get babel => configuration.babel;
   String get builderTag => configuration.builderTag;
   final List<String> reproducingArguments;
 
@@ -208,24 +212,30 @@
   ///     build/none_vm_release_x64
   String get buildDirectory => system.outputDirectory + configurationDirectory;
 
+  int _timeout;
+
   // TODO(whesse): Put non-default timeouts explicitly in configs, not this.
   /// Calculates a default timeout based on the compiler and runtime used,
   /// and the mode, architecture, etc.
   int get timeout {
-    if (configuration.timeout == null) {
-      var isReload = hotReload || hotReloadRollback;
+    if (_timeout == null) {
+      if (configuration.timeout > 0) {
+        _timeout = configuration.timeout;
+      } else {
+        var isReload = hotReload || hotReloadRollback;
 
-      var compilerMulitiplier = compilerConfiguration.timeoutMultiplier;
-      var runtimeMultiplier = runtimeConfiguration.timeoutMultiplier(
-          mode: mode,
-          isChecked: isChecked,
-          isReload: isReload,
-          arch: architecture);
+        var compilerMulitiplier = compilerConfiguration.timeoutMultiplier;
+        var runtimeMultiplier = runtimeConfiguration.timeoutMultiplier(
+            mode: mode,
+            isChecked: isChecked,
+            isReload: isReload,
+            arch: architecture);
 
-      configuration.timeout = 60 * compilerMulitiplier * runtimeMultiplier;
+        _timeout = 60 * compilerMulitiplier * runtimeMultiplier;
+      }
     }
 
-    return configuration.timeout;
+    return _timeout;
   }
 
   List<String> get standardOptions {
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index 67f5b27..9519f1c 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -181,6 +181,9 @@
     new _Option.bool(
         'use_blobs', 'Use mmap instead of shared libraries for precompilation.',
         hide: true),
+    new _Option.bool(
+        'use_elf', 'Directly generate an ELF shared libraries for precompilation.',
+        hide: true),
     new _Option.bool('keep_generated_files', 'Keep any generated files.',
         abbr: 'k'),
     new _Option.int('timeout', 'Timeout in seconds.', abbr: 't'),
@@ -222,13 +225,14 @@
     new _Option.bool(
         'silent_failures',
         "Don't complain about failing tests. This is useful when in "
-        "combination with --write-results.",
+            "combination with --write-results.",
         hide: true),
     new _Option.bool('report_in_json',
         'When listing with --list, output result summary in JSON.',
         hide: true),
     new _Option.bool('time', 'Print timing information after running tests.'),
     new _Option('dart', 'Path to dart executable.', hide: true),
+    new _Option('gen-snapshot', 'Path to gen_snapshot executable.', hide: true),
     new _Option('firefox', 'Path to firefox browser executable.', hide: true),
     new _Option('chrome', 'Path to chrome browser executable.', hide: true),
     new _Option('safari', 'Path to safari browser executable.', hide: true),
@@ -249,12 +253,12 @@
     new _Option.bool(
         'write_results',
         'Write results to a "${TestUtils.resultsFileName}" json file '
-        'located at the debug_output_directory.',
+            'located at the debug_output_directory.',
         hide: true),
     new _Option.bool(
         'write_logs',
         'Include the stdout and stderr of tests that don\'t match expectations '
-        'in the "${TestUtils.logsFileName}" file',
+            'in the "${TestUtils.logsFileName}" file',
         hide: true),
     new _Option.bool(
         'reset_browser_configuration',
@@ -299,6 +303,11 @@
         hide: true),
     new _Option('shared_options', 'Extra shared options.', hide: true),
     new _Option(
+        'babel',
+        '''Transforms dart2js output with Babel. The value must be
+Babel options JSON.''',
+        hide: true),
+    new _Option(
         'suite_dir', 'Additional directory to add to the testing matrix.',
         hide: true),
     new _Option('package_root', 'The package root to use for testing.',
@@ -687,6 +696,7 @@
                     useAnalyzerFastaParser:
                         data["analyzer_use_fasta_parser"] as bool,
                     useBlobs: data["use_blobs"] as bool,
+                    useElf: data["use_elf"] as bool,
                     useSdk: data["use_sdk"] as bool,
                     useHotReload: data["hot_reload"] as bool,
                     useHotReloadRollback: data["hot_reload_rollback"] as bool,
@@ -695,6 +705,7 @@
                     isMinified: data["minified"] as bool,
                     vmOptions: vmOptions,
                     dart2jsOptions: dart2jsOptions,
+                    babel: data['babel'] as String,
                     builderTag: data["builder_tag"] as String,
                     previewDart2: true);
             var configuration = new TestConfiguration(
@@ -727,6 +738,7 @@
                 firefoxPath: data["firefox"] as String,
                 dartPath: data["dart"] as String,
                 dartPrecompiledPath: data["dart_precompiled"] as String,
+                genSnapshotPath: data["gen-snapshot"] as String,
                 keepGeneratedFiles: data["keep_generated_files"] as bool,
                 taskCount: data["tasks"] as int,
                 shardCount: data["shards"] as int,
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index c523839..38c10b1 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -8,9 +8,7 @@
 import 'compiler_configuration.dart';
 import 'configuration.dart';
 import 'repository.dart';
-// TODO(ahe): Remove this import, we can precompute all the values required
-// from TestSuite once the refactoring is complete.
-import 'test_suite.dart';
+import 'utils.dart';
 
 /// Describes the commands to run a given test case or its compiled output.
 ///
@@ -50,10 +48,14 @@
       case Runtime.dartPrecompiled:
         if (configuration.system == System.android) {
           return new DartPrecompiledAdbRuntimeConfiguration(
-              useBlobs: configuration.useBlobs);
+            useBlobs: configuration.useBlobs,
+            useElf: configuration.useElf,
+          );
         } else {
           return new DartPrecompiledRuntimeConfiguration(
-              useBlobs: configuration.useBlobs);
+            useBlobs: configuration.useBlobs,
+            useElf: configuration.useElf,
+          );
         }
         break;
 
@@ -78,7 +80,6 @@
   }
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -88,9 +89,74 @@
     throw "Unimplemented runtime '$runtimeType'";
   }
 
+  /**
+   * The output directory for this suite's configuration.
+   */
+  String get buildDir => _configuration.buildDirectory;
+
   List<String> dart2jsPreambles(Uri preambleDir) => [];
 
   bool get shouldSkipNegativeTests => false;
+
+  /// Returns the path to the Dart VM executable.
+  String get dartVmBinaryFileName {
+    // Controlled by user with the option "--dart".
+    var dartExecutable = _configuration.dartPath;
+
+    if (dartExecutable == null) {
+      dartExecutable = dartVmExecutableFileName;
+    }
+
+    TestUtils.ensureExists(dartExecutable, _configuration);
+    return dartExecutable;
+  }
+
+  String get dartVmExecutableFileName {
+    return _configuration.useSdk
+        ? '$buildDir/dart-sdk/bin/dart$executableBinarySuffix'
+        : '$buildDir/dart$executableBinarySuffix';
+  }
+
+  String get dartPrecompiledBinaryFileName {
+    // Controlled by user with the option "--dart_precompiled".
+    var dartExecutable = _configuration.dartPrecompiledPath;
+
+    if (dartExecutable == null || dartExecutable == '') {
+      var suffix = executableBinarySuffix;
+      dartExecutable = '$buildDir/dart_precompiled_runtime$suffix';
+    }
+
+    TestUtils.ensureExists(dartExecutable, _configuration);
+    return dartExecutable;
+  }
+
+  String get processTestBinaryFileName {
+    var suffix = executableBinarySuffix;
+    var processTestExecutable = '$buildDir/process_test$suffix';
+    TestUtils.ensureExists(processTestExecutable, _configuration);
+    return processTestExecutable;
+  }
+
+  String get d8FileName {
+    var suffix = executableBinarySuffix;
+    var d8Dir = Repository.dir.append('third_party/d8');
+    var d8Path = d8Dir.append('${Platform.operatingSystem}/d8$suffix');
+    var d8 = d8Path.toNativePath();
+    TestUtils.ensureExists(d8, _configuration);
+    return d8;
+  }
+
+  String get jsShellFileName {
+    var executableSuffix = executableBinarySuffix;
+    var executable = 'jsshell$executableSuffix';
+    var jsshellDir = Repository.uri.resolve("tools/testing/bin").path;
+    var jsshell = '$jsshellDir/$executable';
+    TestUtils.ensureExists(jsshell, _configuration);
+    return jsshell;
+  }
+
+  String get executableBinarySuffix => Platform.isWindows ? '.exe' : '';
+  String get executableScriptSuffix => Platform.isWindows ? '.bat' : '';
 }
 
 /// The 'none' runtime configuration.
@@ -98,7 +164,6 @@
   NoneRuntimeConfiguration() : super._subclass();
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -126,7 +191,6 @@
   D8RuntimeConfiguration() : super('d8');
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -136,7 +200,7 @@
     checkArtifact(artifact);
     return [
       Command.jsCommandLine(
-          moniker, suite.d8FileName, arguments, environmentOverrides)
+          moniker, d8FileName, arguments, environmentOverrides)
     ];
   }
 
@@ -150,7 +214,6 @@
   JsshellRuntimeConfiguration() : super('jsshell');
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -159,7 +222,7 @@
     checkArtifact(artifact);
     return [
       Command.jsCommandLine(
-          moniker, suite.jsShellFileName, arguments, environmentOverrides)
+          moniker, jsShellFileName, arguments, environmentOverrides)
     ];
   }
 
@@ -210,7 +273,6 @@
 //// The standalone Dart VM binary, "dart" or "dart.exe".
 class StandaloneDartRuntimeConfiguration extends DartVmRuntimeConfiguration {
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -228,9 +290,9 @@
     if (isCrashExpected) {
       arguments.insert(0, '--suppress-core-dump');
     }
-    String executable = suite.dartVmBinaryFileName;
+    String executable = dartVmBinaryFileName;
     if (type == 'application/kernel-ir-fully-linked') {
-      executable = suite.dartVmExecutableFileName;
+      executable = dartVmExecutableFileName;
     }
     return [Command.vm(executable, arguments, environmentOverrides)];
   }
@@ -238,10 +300,12 @@
 
 class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration {
   final bool useBlobs;
-  DartPrecompiledRuntimeConfiguration({bool useBlobs}) : useBlobs = useBlobs;
+  final bool useElf;
+  DartPrecompiledRuntimeConfiguration({bool useBlobs, bool useElf})
+      : useBlobs = useBlobs,
+        useElf = useElf;
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -254,8 +318,7 @@
     }
 
     return [
-      Command.vm(
-          suite.dartPrecompiledBinaryFileName, arguments, environmentOverrides)
+      Command.vm(dartPrecompiledBinaryFileName, arguments, environmentOverrides)
     ];
   }
 }
@@ -265,7 +328,6 @@
   static const String DeviceTestDir = '/data/local/tmp/testing/test';
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -277,8 +339,8 @@
       throw "dart cannot run files of type '$type'.";
     }
 
-    final String buildPath = suite.buildDir;
-    final String processTest = suite.processTestBinaryFileName;
+    final String buildPath = buildDir;
+    final String processTest = processTestBinaryFileName;
     return [
       Command.adbDartk(buildPath, processTest, script, arguments, extraLibs)
     ];
@@ -292,10 +354,12 @@
       '/data/local/tmp/precompilation-testing/test';
 
   final bool useBlobs;
-  DartPrecompiledAdbRuntimeConfiguration({bool useBlobs}) : useBlobs = useBlobs;
+  final bool useElf;
+  DartPrecompiledAdbRuntimeConfiguration({bool useBlobs, bool useElf})
+      : useBlobs = useBlobs,
+        useElf = useElf;
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -307,11 +371,11 @@
       throw "dart_precompiled cannot run files of type '$type'.";
     }
 
-    String precompiledRunner = suite.dartPrecompiledBinaryFileName;
-    String processTest = suite.processTestBinaryFileName;
+    String precompiledRunner = dartPrecompiledBinaryFileName;
+    String processTest = processTestBinaryFileName;
     return [
       Command.adbPrecompiled(
-          precompiledRunner, processTest, script, arguments, useBlobs)
+          precompiledRunner, processTest, script, arguments, useBlobs, useElf)
     ];
   }
 }
@@ -333,17 +397,16 @@
   }
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
       bool isCrashExpected) {
-    String executable = suite.dartVmBinaryFileName;
+    String executable = dartVmBinaryFileName;
     return selfCheckers
         .map((String tester) => Command.vmBatch(
             executable, tester, arguments, environmentOverrides,
-            checked: suite.configuration.isChecked))
+            checked: _configuration.isChecked))
         .toList();
   }
 
@@ -356,7 +419,6 @@
 // TODO(ahe): Remove this class.
 class DummyRuntimeConfiguration extends DartVmRuntimeConfiguration {
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
diff --git a/tools/testing/dart/test_configurations.dart b/tools/testing/dart/test_configurations.dart
index 32b9559..68f97a4 100644
--- a/tools/testing/dart/test_configurations.dart
+++ b/tools/testing/dart/test_configurations.dart
@@ -35,6 +35,7 @@
   new Path('tests/compiler/dart2js'),
   new Path('tests/compiler/dart2js_extra'),
   new Path('tests/compiler/dart2js_native'),
+  new Path('tests/compiler/dartdevc_native'),
   new Path('tests/corelib_2'),
   new Path('tests/kernel'),
   new Path('tests/language_2'),
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 6deb34a..bbe9a68 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -80,6 +80,7 @@
   static final int HAS_SYNTAX_ERROR = 1 << 1;
   static final int HAS_COMPILE_ERROR = 1 << 2;
   static final int HAS_STATIC_WARNING = 1 << 3;
+  static final int HAS_CRASH = 1 << 4;
   /**
    * A list of commands to execute. Most test cases have a single command.
    * Dart2js tests have two commands, one to compile the source and another
@@ -104,7 +105,8 @@
 
     if (info != null) {
       _setExpectations(info);
-      hash = info.originTestPath.relativeTo(Repository.dir).toString().hashCode;
+      hash = (info?.originTestPath?.relativeTo(Repository.dir)?.toString())
+          .hashCode;
     }
   }
 
@@ -113,6 +115,7 @@
     // so we copy the needed bools into flags set in a single integer.
     if (info.hasRuntimeError) _expectations |= HAS_RUNTIME_ERROR;
     if (info.hasSyntaxError) _expectations |= HAS_SYNTAX_ERROR;
+    if (info.hasCrash) _expectations |= HAS_CRASH;
     if (info.hasCompileError || info.hasSyntaxError) {
       _expectations |= HAS_COMPILE_ERROR;
     }
@@ -131,6 +134,7 @@
   bool get hasStaticWarning => _expectations & HAS_STATIC_WARNING != 0;
   bool get hasSyntaxError => _expectations & HAS_SYNTAX_ERROR != 0;
   bool get hasCompileError => _expectations & HAS_COMPILE_ERROR != 0;
+  bool get hasCrash => _expectations & HAS_CRASH != 0;
   bool get isNegative =>
       hasCompileError ||
       hasRuntimeError && configuration.runtime != Runtime.none ||
@@ -146,6 +150,9 @@
   Expectation get result => lastCommandOutput.result(this);
   Expectation get realResult => lastCommandOutput.realResult(this);
   Expectation get realExpected {
+    if (hasCrash) {
+      return Expectation.crash;
+    }
     if (configuration.compiler == Compiler.specParser) {
       if (hasSyntaxError) {
         return Expectation.syntaxError;
@@ -237,7 +244,7 @@
  * it is longer than MAX_HEAD characters, and just keeps the head and
  * the last TAIL_LENGTH characters of the output.
  */
-class OutputLog {
+class OutputLog implements StreamConsumer<List<int>> {
   static const int MAX_HEAD = 500 * 1024;
   static const int TAIL_LENGTH = 10 * 1024;
   List<int> head = <int>[];
@@ -245,6 +252,7 @@
   List<int> complete;
   bool dataDropped = false;
   bool hasNonUtf8 = false;
+  StreamSubscription _subscription;
 
   OutputLog();
 
@@ -318,6 +326,53 @@
     }
     return complete;
   }
+
+  @override
+  Future addStream(Stream<List<int>> stream) {
+    _subscription = stream.listen(this.add);
+    return _subscription.asFuture();
+  }
+
+  @override
+  Future close() {
+    toList();
+    return _subscription?.cancel();
+  }
+
+  Future cancel() {
+    return _subscription?.cancel();
+  }
+}
+
+// An [OutputLog] that tees the output to a file as well.
+class FileOutputLog extends OutputLog {
+  io.File _outputFile;
+  io.IOSink _sink;
+
+  FileOutputLog(this._outputFile);
+
+  @override
+  void add(List<int> data) {
+    super.add(data);
+    _sink ??= _outputFile.openWrite();
+    _sink.add(data);
+  }
+
+  @override
+  Future close() {
+    return Future.wait([
+      super.close(),
+      if (_sink != null) _sink.flush().whenComplete(_sink.close)
+    ]);
+  }
+
+  @override
+  Future cancel() {
+    return Future.wait([
+      super.cancel(),
+      if (_sink != null) _sink.flush().whenComplete(_sink.close)
+    ]);
+  }
 }
 
 // Helper to get a list of all child pids for a parent process.
@@ -374,16 +429,18 @@
   int timeout;
   bool timedOut = false;
   DateTime startTime;
-  Timer timeoutTimer;
   int pid;
-  OutputLog stdout = new OutputLog();
-  OutputLog stderr = new OutputLog();
+  OutputLog stdout;
+  OutputLog stderr = OutputLog();
   List<String> diagnostics = <String>[];
   bool compilationSkipped = false;
   Completer<CommandOutput> completer;
   TestConfiguration configuration;
 
-  RunningProcess(this.command, this.timeout, {this.configuration});
+  RunningProcess(this.command, this.timeout,
+      {this.configuration, io.File outputFile}) {
+    stdout = outputFile != null ? FileOutputLog(outputFile) : OutputLog();
+  }
 
   Future<CommandOutput> run() {
     completer = new Completer<CommandOutput>();
@@ -403,44 +460,10 @@
           environment: processEnvironment,
           workingDirectory: command.workingDirectory);
       processFuture.then((io.Process process) {
-        StreamSubscription stdoutSubscription =
-            _drainStream(process.stdout, stdout);
-        StreamSubscription stderrSubscription =
-            _drainStream(process.stderr, stderr);
-
-        var stdoutCompleter = new Completer<Null>();
-        var stderrCompleter = new Completer<Null>();
-
-        bool stdoutDone = false;
-        bool stderrDone = false;
+        var stdoutFuture = process.stdout.pipe(stdout);
+        var stderrFuture = process.stderr.pipe(stderr);
         pid = process.pid;
 
-        // This timer is used to close stdio to the subprocess once we got
-        // the exitCode. Sometimes descendants of the subprocess keep stdio
-        // handles alive even though the direct subprocess is dead.
-        Timer watchdogTimer;
-
-        closeStdout([_]) {
-          if (!stdoutDone) {
-            stdoutCompleter.complete();
-            stdoutDone = true;
-            if (stderrDone && watchdogTimer != null) {
-              watchdogTimer.cancel();
-            }
-          }
-        }
-
-        closeStderr([_]) {
-          if (!stderrDone) {
-            stderrCompleter.complete();
-            stderrDone = true;
-
-            if (stdoutDone && watchdogTimer != null) {
-              watchdogTimer.cancel();
-            }
-          }
-        }
-
         // Close stdin so that tests that try to block on input will fail.
         process.stdin.close();
         timeoutHandler() async {
@@ -500,30 +523,31 @@
           }
         }
 
-        stdoutSubscription.asFuture().then(closeStdout);
-        stderrSubscription.asFuture().then(closeStderr);
-
-        process.exitCode.then((exitCode) {
-          if (!stdoutDone || !stderrDone) {
-            watchdogTimer = new Timer(MAX_STDIO_DELAY, () {
-              DebugLogger.warning(
-                  "$MAX_STDIO_DELAY_PASSED_MESSAGE (command: $command)");
-              watchdogTimer = null;
-              stdoutSubscription.cancel();
-              stderrSubscription.cancel();
-              closeStdout();
-              closeStderr();
-            });
-          }
-
-          Future.wait([stdoutCompleter.future, stderrCompleter.future])
-              .then((_) {
+        // Wait for the process to finish or timeout
+        process.exitCode
+            .timeout(Duration(seconds: timeout), onTimeout: timeoutHandler)
+            .then((exitCode) {
+          // This timeout is used to close stdio to the subprocess once we got
+          // the exitCode. Sometimes descendants of the subprocess keep stdio
+          // handles alive even though the direct subprocess is dead.
+          Future.wait([stdoutFuture, stderrFuture]).timeout(MAX_STDIO_DELAY,
+              onTimeout: () async {
+            DebugLogger.warning(
+                "$MAX_STDIO_DELAY_PASSED_MESSAGE (command: $command)");
+            await stdout.cancel();
+            await stderr.cancel();
+            _commandComplete(exitCode);
+            return null;
+          }).then((_) {
+            if (stdout is FileOutputLog) {
+              // Prevent logging data that has already been written to a file
+              // and is unlikely too add value in the logs because the command
+              // succeeded.
+              stdout.complete = <int>[];
+            }
             _commandComplete(exitCode);
           });
         });
-
-        timeoutTimer =
-            new Timer(new Duration(seconds: timeout), timeoutHandler);
       }).catchError((e) {
         // TODO(floitsch): should we try to report the stacktrace?
         print("Process error:");
@@ -536,9 +560,6 @@
   }
 
   void _commandComplete(int exitCode) {
-    if (timeoutTimer != null) {
-      timeoutTimer.cancel();
-    }
     var commandOutput = _createCommandOutput(command, exitCode);
     completer.complete(commandOutput);
   }
@@ -566,11 +587,6 @@
     return commandOutput;
   }
 
-  StreamSubscription _drainStream(
-      Stream<List<int>> source, OutputLog destination) {
-    return source.listen(destination.add);
-  }
-
   Map<String, String> _createProcessEnvironment() {
     var environment = new Map<String, String>.from(io.Platform.environment);
 
@@ -1202,7 +1218,8 @@
       return _getBatchRunner(name)
           .runCommand(name, command, timeout, command.arguments);
     } else if (command is CompilationCommand &&
-        globalConfiguration.batchDart2JS) {
+        globalConfiguration.batchDart2JS &&
+        command.displayName == 'dart2js') {
       return _getBatchRunner("dart2js")
           .runCommand("dart2js", command, timeout, command.arguments);
     } else if (command is AnalysisCommand && globalConfiguration.batch) {
@@ -1236,6 +1253,12 @@
       var name = command.displayName;
       return _getBatchRunner(command.displayName + command.dartFile)
           .runCommand(name, command, timeout, command.arguments);
+    } else if (command is CompilationCommand &&
+        command.displayName == 'babel') {
+      return new RunningProcess(command, timeout,
+              configuration: globalConfiguration,
+              outputFile: io.File(command.outputFile))
+          .run();
     } else if (command is ProcessCommand) {
       return new RunningProcess(command, timeout,
               configuration: globalConfiguration)
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index b3ad21d..f00c75d 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -141,12 +141,6 @@
   Map<String, String> get environmentOverrides => _environmentOverrides;
 
   /**
-   * Whether or not binaries should be found in the root build directory or
-   * in the built SDK.
-   */
-  bool get useSdk => configuration.useSdk;
-
-  /**
    * The output directory for this suite's configuration.
    */
   String get buildDir => configuration.buildDirectory;
@@ -165,80 +159,6 @@
     return name;
   }
 
-  /// Returns the name of the Dart VM executable.
-  String get dartVmBinaryFileName {
-    // Controlled by user with the option "--dart".
-    var dartExecutable = configuration.dartPath;
-
-    if (dartExecutable == null) {
-      dartExecutable = dartVmExecutableFileName;
-    }
-
-    TestUtils.ensureExists(dartExecutable, configuration);
-    return dartExecutable;
-  }
-
-  String get dartVmExecutableFileName {
-    return useSdk
-        ? '$buildDir/dart-sdk/bin/dart$executableBinarySuffix'
-        : '$buildDir/dart$executableBinarySuffix';
-  }
-
-  String get dartPrecompiledBinaryFileName {
-    // Controlled by user with the option "--dart_precompiled".
-    var dartExecutable = configuration.dartPrecompiledPath;
-
-    if (dartExecutable == null || dartExecutable == '') {
-      var suffix = executableBinarySuffix;
-      dartExecutable = '$buildDir/dart_precompiled_runtime$suffix';
-    }
-
-    TestUtils.ensureExists(dartExecutable, configuration);
-    return dartExecutable;
-  }
-
-  String get processTestBinaryFileName {
-    var suffix = executableBinarySuffix;
-    var processTestExecutable = '$buildDir/process_test$suffix';
-    TestUtils.ensureExists(processTestExecutable, configuration);
-    return processTestExecutable;
-  }
-
-  String get d8FileName {
-    var suffix = getExecutableSuffix('d8');
-    var d8Dir = Repository.dir.append('third_party/d8');
-    var d8Path = d8Dir.append('${Platform.operatingSystem}/d8$suffix');
-    var d8 = d8Path.toNativePath();
-    TestUtils.ensureExists(d8, configuration);
-    return d8;
-  }
-
-  String get jsShellFileName {
-    var executableSuffix = getExecutableSuffix('jsshell');
-    var executable = 'jsshell$executableSuffix';
-    var jsshellDir = '${Repository.dir.toNativePath()}/tools/testing/bin';
-    return '$jsshellDir/$executable';
-  }
-
-  /**
-   * The file extension (if any) that should be added to the given executable
-   * name for the current platform.
-   */
-  // TODO(ahe): Get rid of this. Use executableBinarySuffix instead.
-  String getExecutableSuffix(String executable) {
-    if (Platform.operatingSystem == 'windows') {
-      if (executable == 'd8' || executable == 'vm' || executable == 'none') {
-        return '.exe';
-      } else {
-        return '.bat';
-      }
-    }
-    return '';
-  }
-
-  String get executableBinarySuffix => Platform.isWindows ? '.exe' : '';
-  String get executableScriptSuffix => Platform.isWindows ? '.bat' : '';
-
   /**
    * Call the callback function onTest with a [TestCase] argument for each
    * test in the suite.  When all tests have been processed, call [onDone].
@@ -451,22 +371,46 @@
     var expectations = new ExpectationSet.read(statusFiles, configuration);
 
     try {
-      for (var name in await _listTests(hostRunnerPath)) {
-        _addTest(expectations, name);
+      for (VmUnitTest test in await _listTests(hostRunnerPath)) {
+        _addTest(expectations, test);
       }
 
       doTest = null;
       if (onDone != null) onDone();
-    } catch (error) {
+    } catch (error, s) {
       print("Fatal error occured: $error");
+      print(s);
       exit(1);
     }
   }
 
-  void _addTest(ExpectationSet testExpectations, String testName) {
-    var fullName = 'cc/$testName';
+  void _addTest(ExpectationSet testExpectations, VmUnitTest test) {
+    final fullName = 'cc/${test.name}';
     var expectations = testExpectations.expectations(fullName);
 
+    // Get the expectation from the cc/ test itself.
+    final Expectation testExpectation = Expectation.find(test.expectation);
+
+    // Update the legacy status-file based expectations to include
+    // [testExpectation].
+    if (testExpectation != Expectation.pass) {
+      expectations = Set<Expectation>.from(expectations)..add(testExpectation);
+      expectations.removeWhere((e) => e == Expectation.pass);
+    }
+
+    // Update the new workflow based expectations to include [testExpectation].
+    final Path filePath = null;
+    final Path originTestPath = null;
+    final hasSyntaxError = false;
+    final hasStaticWarning = false;
+    final hasCompileTimeError = testExpectation == Expectation.compileTimeError;
+    final hasRuntimeError = testExpectation == Expectation.runtimeError;
+    final hasCrash = testExpectation == Expectation.crash;
+    final optionsFromFile = const <String, dynamic>{};
+    final testInfo = TestInformation(filePath, originTestPath, optionsFromFile,
+        hasSyntaxError, hasCompileTimeError, hasRuntimeError, hasStaticWarning,
+        hasCrash: hasCrash);
+
     var args = configuration.standardOptions.toList();
     if (configuration.compilerConfiguration.previewDart2) {
       final filename = configuration.architecture == Architecture.x64
@@ -480,14 +424,14 @@
       args.insert(0, '--suppress-core-dump');
     }
 
-    args.add(testName);
+    args.add(test.name);
 
-    var command = Command.process(
+    final command = Command.process(
         'run_vm_unittest', targetRunnerPath, args, environmentOverrides);
-    enqueueNewTestCase(fullName, [command], expectations);
+    enqueueNewTestCase(fullName, [command], expectations, testInfo);
   }
 
-  Future<Iterable<String>> _listTests(String runnerPath) async {
+  Future<Iterable<VmUnitTest>> _listTests(String runnerPath) async {
     var result = await Process.run(runnerPath, ["--list"]);
     if (result.exitCode != 0) {
       throw "Failed to list tests: '$runnerPath --list'. "
@@ -497,10 +441,21 @@
     return (result.stdout as String)
         .split('\n')
         .map((line) => line.trim())
-        .where((name) => name.isNotEmpty);
+        .where((name) => name.isNotEmpty)
+        .map((String line) {
+      final parts = line.split(' ');
+      return VmUnitTest(parts[0].trim(), parts.skip(1).single);
+    });
   }
 }
 
+class VmUnitTest {
+  final String name;
+  final String expectation;
+
+  VmUnitTest(this.name, this.expectation);
+}
+
 class TestInformation {
   Path filePath;
   Path originTestPath;
@@ -509,6 +464,7 @@
   bool hasCompileError;
   bool hasRuntimeError;
   bool hasStaticWarning;
+  bool hasCrash;
   String multitestKey;
 
   TestInformation(
@@ -519,7 +475,8 @@
       this.hasCompileError,
       this.hasRuntimeError,
       this.hasStaticWarning,
-      {this.multitestKey: ''}) {
+      {this.multitestKey: '',
+      this.hasCrash: false}) {
     assert(filePath.isAbsolute);
   }
 }
@@ -548,7 +505,7 @@
         extraVmOptions = configuration.vmOptions,
         super(configuration, suiteName, statusFilePaths) {
     // Initialize _dart2JsBootstrapDependencies
-    if (!useSdk) {
+    if (!configuration.useSdk) {
       _dart2JsBootstrapDependencies = [];
     } else {
       _dart2JsBootstrapDependencies = [
@@ -896,7 +853,6 @@
 
     return commands
       ..addAll(configuration.runtimeConfiguration.computeRuntimeCommands(
-          this,
           compilationArtifact,
           runtimeArguments,
           environment,
@@ -991,30 +947,28 @@
     var fileName = info.filePath.toNativePath();
     var optionsFromFile = info.optionsFromFile;
     var compilationTempDir = createCompilationOutputDirectory(info.filePath);
-    var jsWrapperFileName = '$compilationTempDir/test.js';
     var nameNoExt = info.filePath.filenameWithoutExtension;
+    var outputDir = compilationTempDir;
+    var commonArguments =
+        commonArgumentsFromFile(info.filePath, optionsFromFile);
 
     // Use existing HTML document if available.
     String content;
     var customHtml = new File(
         info.filePath.directoryPath.append('$nameNoExt.html').toNativePath());
     if (customHtml.existsSync()) {
-      jsWrapperFileName = '$tempDir/$nameNoExt.js';
+      outputDir = tempDir;
       content = customHtml.readAsStringSync().replaceAll(
           '%TEST_SCRIPTS%', '<script src="$nameNoExt.js"></script>');
     } else {
       // Synthesize an HTML file for the test.
       if (configuration.compiler == Compiler.dart2js) {
-        var scriptPath = _createUrlPathFromFile(new Path(jsWrapperFileName));
+        var scriptPath = _createUrlPathFromFile(
+            new Path('$compilationTempDir/$nameNoExt.js'));
         content = dart2jsHtml(fileName, scriptPath);
       } else {
         var jsDir =
             new Path(compilationTempDir).relativeTo(Repository.dir).toString();
-        jsWrapperFileName =
-            new Path('$compilationTempDir/$nameNoExt.js').toNativePath();
-        // Always run with synchronous starts of `async` functions.
-        // If we want to make this dependent on other parameters or flags,
-        // this flag could be become conditional.
         content = dartdevcHtml(nameNoExt, jsDir, configuration.compiler);
       }
     }
@@ -1025,36 +979,21 @@
     // Construct the command(s) that compile all the inputs needed by the
     // browser test.
     var commands = <Command>[];
+    const supportedCompilers = {
+      Compiler.dart2js,
+      Compiler.dartdevc,
+      Compiler.dartdevk
+    };
+    assert(supportedCompilers.contains(configuration.compiler));
+    var sharedOptions = optionsFromFile["sharedOptions"] as List<String>;
+    var dart2jsOptions = optionsFromFile["dart2jsOptions"] as List<String>;
+    var ddcOptions = optionsFromFile["ddcOptions"] as List<String>;
 
-    void addCompileCommand(String fileName, String toPath) {
-      switch (configuration.compiler) {
-        case Compiler.dart2js:
-          commands.add(_dart2jsCompileCommand(
-              fileName, toPath, tempDir, optionsFromFile));
-          break;
-
-        case Compiler.dartdevc:
-        case Compiler.dartdevk:
-          var ddcOptions = optionsFromFile["sharedOptions"] as List<String>;
-          ddcOptions.addAll(optionsFromFile["ddcOptions"] as List<String>);
-          commands.add(configuration.compilerConfiguration.createCommand(
-              fileName, toPath, ddcOptions, environmentOverrides));
-          break;
-
-        default:
-          assert(false);
-      }
-    }
-
-    addCompileCommand(fileName, jsWrapperFileName);
-
-    // Some tests require compiling multiple input scripts.
-    for (var name in optionsFromFile['otherScripts'] as List<String>) {
-      var namePath = new Path(name);
-      var fromPath = info.filePath.directoryPath.join(namePath).toNativePath();
-      var toPath = new Path('$tempDir/${namePath.filename}.js').toNativePath();
-      addCompileCommand(fromPath, toPath);
-    }
+    var args = configuration.compilerConfiguration.computeCompilerArguments(
+        null, sharedOptions, null, dart2jsOptions, ddcOptions, commonArguments);
+    var compilation = configuration.compilerConfiguration
+        .computeCompilationArtifact(outputDir, args, environmentOverrides);
+    commands.addAll(compilation.commands);
 
     if (info.optionsFromFile['isMultiHtmlTest'] as bool) {
       // Variables for browser multi-tests.
@@ -1091,43 +1030,6 @@
     enqueueNewTestCase(fullName, commands, expectations, info);
   }
 
-  /// Creates a [Command] to compile a single .dart file using dart2js.
-  Command _dart2jsCompileCommand(String inputFile, String outputFile,
-      String dir, Map<String, dynamic> optionsFromFile) {
-    var args = <String>[];
-
-    if (compilerPath.endsWith('.dart')) {
-      // Run the compiler script via the Dart VM.
-      args.add(compilerPath);
-    }
-
-    args.addAll(configuration.standardOptions);
-    args.addAll(configuration.dart2jsOptions);
-
-    var packages = packagesArgument(optionsFromFile['packageRoot'] as String,
-        optionsFromFile['packages'] as String);
-    if (packages != null) args.add(packages);
-
-    args.add('--out=$outputFile');
-    args.add(inputFile);
-
-    var options = optionsFromFile['sharedOptions'] as List<String>;
-    if (options != null) args.addAll(options);
-    options = optionsFromFile['dart2jsOptions'] as List<String>;
-    if (options != null) args.addAll(options);
-    if (configuration.compiler == Compiler.dart2js) {
-      if (configuration.noPreviewDart2) {
-        args.add("--no-preview-dart-2");
-      } else {
-        args.add("--preview-dart-2");
-      }
-    }
-
-    return Command.compilation(Compiler.dart2js.name, outputFile,
-        dart2JsBootstrapDependencies, compilerPath, args, environmentOverrides,
-        alwaysCompile: !useSdk);
-  }
-
   List<String> commonArgumentsFromFile(
       Path filePath, Map<String, dynamic> optionsFromFile) {
     var args = configuration.standardOptions.toList();
@@ -1148,14 +1050,6 @@
       }
     }
 
-    if (configuration.compiler == Compiler.dart2js) {
-      if (configuration.noPreviewDart2) {
-        args.add("--no-preview-dart-2");
-      } else {
-        args.add("--preview-dart-2");
-      }
-    }
-
     args.add(filePath.toNativePath());
 
     return args;
@@ -1204,12 +1098,6 @@
    *     // Environment=ENV_VAR1=foo bar
    *     // Environment=ENV_VAR2=bazz
    *
-   *   - For tests that depend on compiling other files with dart2js (e.g.
-   *   isolate tests that use multiple source scripts), you can specify
-   *   additional files to compile using a comment too, as follows:
-   *
-   *     // OtherScripts=file1.dart file2.dart
-   *
    *   - Most tests are not web tests, but can (and will be) wrapped within
    *   an HTML file and another script file to test them also on browser
    *   environments (e.g. language and corelib tests are run this way).
@@ -1235,7 +1123,6 @@
     }
     RegExp testOptionsRegExp = new RegExp(r"// VMOptions=(.*)");
     RegExp environmentRegExp = new RegExp(r"// Environment=(.*)");
-    RegExp otherScriptsRegExp = new RegExp(r"// OtherScripts=(.*)");
     RegExp otherResourcesRegExp = new RegExp(r"// OtherResources=(.*)");
     RegExp sharedObjectsRegExp = new RegExp(r"// SharedObjects=(.*)");
     RegExp packageRootRegExp = new RegExp(r"// PackageRoot=(.*)");
@@ -1328,12 +1215,6 @@
       }
     }
 
-    var otherScripts = <String>[];
-    matches = otherScriptsRegExp.allMatches(contents);
-    for (var match in matches) {
-      otherScripts.addAll(wordSplit(match[1]));
-    }
-
     var otherResources = <String>[];
     matches = otherResourcesRegExp.allMatches(contents);
     for (var match in matches) {
@@ -1401,7 +1282,6 @@
       "hasCompileError": hasCompileError,
       "hasRuntimeError": hasRuntimeError,
       "hasStaticWarning": hasStaticWarning,
-      "otherScripts": otherScripts,
       "otherResources": otherResources,
       "sharedObjects": sharedObjects,
       "isMultitest": isMultitest,
@@ -1424,7 +1304,6 @@
       "hasCompileError": false,
       "hasRuntimeError": false,
       "hasStaticWarning": false,
-      "otherScripts": const [],
       "isMultitest": false,
       "isMultiHtmlTest": false,
       "subtestNames": const [],
diff --git a/tools/utils.py b/tools/utils.py
index 32d843e..a8f96f6 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -5,7 +5,6 @@
 # This file contains a set of utilities functions used by other Python-based
 # scripts.
 
-import commands
 import contextlib
 import datetime
 import glob
@@ -94,8 +93,8 @@
     return 'ia32'
   else:
     guess_os = GuessOS()
-    print "Warning: Guessing architecture %s based on os %s\n"\
-          % (os_id, guess_os)
+    print ("Warning: Guessing architecture %s based on os %s\n"\
+          % (os_id, guess_os))
     if guess_os == 'win32':
       return 'ia32'
     return None
@@ -106,11 +105,11 @@
   if os.getenv("DART_NUMBER_OF_CORES") is not None:
     return int(os.getenv("DART_NUMBER_OF_CORES"))
   if os.path.exists("/proc/cpuinfo"):
-    return int(commands.getoutput("grep -E '^processor' /proc/cpuinfo | wc -l"))
+    return int(subprocess.check_output("grep -E '^processor' /proc/cpuinfo | wc -l", shell=True))
   if os.path.exists("/usr/bin/hostinfo"):
-    return int(commands.getoutput('/usr/bin/hostinfo |'
+    return int(subprocess.check_output('/usr/bin/hostinfo |'
         ' grep "processors are logically available." |'
-        ' awk "{ print \$1 }"'))
+        ' awk "{ print \$1 }"', shell=True))
   win_cpu_count = os.getenv("NUMBER_OF_PROCESSORS")
   if win_cpu_count:
     return int(win_cpu_count)
@@ -271,6 +270,7 @@
   'simdbc64': 'ia32',
   'armsimdbc': 'arm',
   'armsimdbc64': 'arm',
+  'simarm_x64': 'ia32',
 }
 
 ARCH_GUESS = GuessArchitecture()
@@ -340,8 +340,8 @@
       version.prerelease_patch))
 
 
-def GetSemanticSDKVersion(no_git_hash=False):
-  version = ReadVersionFile()
+def GetSemanticSDKVersion(no_git_hash=False, version_file=None):
+  version = ReadVersionFile(version_file)
   if not version:
     return None
 
@@ -356,8 +356,8 @@
   return '%s.%s.%s%s' % (version.major, version.minor, version.patch, postfix)
 
 
-def GetVersion(no_git_hash=False):
-  return GetSemanticSDKVersion(no_git_hash)
+def GetVersion(no_git_hash=False, version_file=None):
+  return GetSemanticSDKVersion(no_git_hash, version_file)
 
 
 # The editor used to produce the VERSION file put on gcs. We now produce this
@@ -387,29 +387,32 @@
   return os.environ.get(key, '')
 
 
-def GetAbiVersion():
-  version = ReadVersionFile()
+def GetAbiVersion(version_file=None):
+  version = ReadVersionFile(version_file)
   return version.abi_version
 
 
-def GetOldestSupportedAbiVersion():
-  version = ReadVersionFile()
+def GetOldestSupportedAbiVersion(version_file=None):
+  version = ReadVersionFile(version_file)
   return version.oldest_supported_abi_version
 
 
-def ReadVersionFile():
+def ReadVersionFile(version_file=None):
   def match_against(pattern, file_content):
     match = re.search(pattern, file_content, flags=re.MULTILINE)
     if match:
       return match.group(1)
     return None
 
+  if version_file == None:
+    version_file = VERSION_FILE
+
   try:
-    fd = open(VERSION_FILE)
+    fd = open(version_file)
     content = fd.read()
     fd.close()
   except:
-    print "Warning: Couldn't read VERSION file (%s)" % VERSION_FILE
+    print ("Warning: Couldn't read VERSION file (%s)" % version_file)
     return None
 
   channel = match_against('^CHANNEL ([A-Za-z0-9]+)$', content)
@@ -428,7 +431,7 @@
         channel, major, minor, patch, prerelease, prerelease_patch, abi_version,
         oldest_supported_abi_version)
   else:
-    print "Warning: VERSION file (%s) has wrong format" % VERSION_FILE
+    print ("Warning: VERSION file (%s) has wrong format" % version_file)
     return None
 
 
@@ -466,7 +469,7 @@
   output = output.strip()
   # We expect a full git hash
   if len(output) != 40:
-    print "Warning: could not parse git commit, output was %s" % output
+    print ("Warning: could not parse git commit, output was %s" % output)
     return None
   return output
 
@@ -498,7 +501,7 @@
                        cwd = DART_DIR)
   output, _ = p.communicate()
   if p.wait() != 0:
-    print "Warning: Could not get the most recent dev branch tag %s" % output
+    print ("Warning: Could not get the most recent dev branch tag %s" % output)
     return None
   return output.strip()
 
@@ -528,7 +531,7 @@
     number = int(output)
     return number + GIT_NUMBER_BASE
   except:
-    print "Warning: could not parse git count, output was %s" % output
+    print ("Warning: could not parse git count, output was %s" % output)
   return None
 
 
@@ -610,20 +613,20 @@
   """Unlink a file without throwing an exception."""
   try:
     os.unlink(name)
-  except OSError, e:
+  except OSError as e:
     PrintError("os.unlink() " + str(e))
 
 
 def Main():
-  print "GuessOS() -> ", GuessOS()
-  print "GuessArchitecture() -> ", GuessArchitecture()
-  print "GuessCpus() -> ", GuessCpus()
-  print "IsWindows() -> ", IsWindows()
-  print "GuessVisualStudioPath() -> ", GuessVisualStudioPath()
-  print "GetGitRevision() -> ", GetGitRevision()
-  print "GetGitTimestamp() -> ", GetGitTimestamp()
-  print "GetVersionFileContent() -> ", GetVersionFileContent()
-  print "GetGitNumber() -> ", GetGitNumber()
+  print ("GuessOS() -> ", GuessOS())
+  print ("GuessArchitecture() -> ", GuessArchitecture())
+  print ("GuessCpus() -> ", GuessCpus())
+  print ("IsWindows() -> ", IsWindows())
+  print ("GuessVisualStudioPath() -> ", GuessVisualStudioPath())
+  print ("GetGitRevision() -> ", GetGitRevision())
+  print ("GetGitTimestamp() -> ", GetGitTimestamp())
+  print ("GetVersionFileContent() -> ", GetVersionFileContent())
+  print ("GetGitNumber() -> ", GetGitNumber())
 
 
 class Error(Exception):
@@ -660,7 +663,7 @@
 
 def ExecuteCommand(cmd):
   """Execute a command in a subprocess."""
-  print 'Executing: ' + ' '.join(cmd)
+  print ('Executing: ' + ' '.join(cmd))
   pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
       shell=IsWindows())
   output = pipe.communicate()
@@ -679,7 +682,7 @@
   try:
     osname = osdict[system]
   except KeyError:
-    print >>sys.stderr, ('WARNING: platform "%s" not supported') % (system)
+    sys.stderr.write('WARNING: platform "%s" not supported\n' % system)
     return None
   tools_dir = os.path.dirname(os.path.realpath(__file__))
   return os.path.join(tools_dir,
@@ -719,7 +722,7 @@
     if fatal:
       raise Exception(message)
     else:
-      print message
+      print (message)
       return False
   return True
 
@@ -743,11 +746,11 @@
 
   def __enter__(self):
     self._old_cwd = os.getcwd()
-    print "Enter directory = ", self._working_directory
+    print ("Enter directory = ", self._working_directory)
     os.chdir(self._working_directory)
 
   def __exit__(self, *_):
-    print "Enter directory = ", self._old_cwd
+    print ("Enter directory = ", self._old_cwd)
     os.chdir(self._old_cwd)
 
 
@@ -797,7 +800,7 @@
     pass
 
   def __enter__(self):
-    print "INFO: Enabling coredump archiving into %s" % (WindowsCoreDumpEnabler.CRASHPAD_DB_FOLDER)
+    print ("INFO: Enabling coredump archiving into %s" % (WindowsCoreDumpEnabler.CRASHPAD_DB_FOLDER))
     os.environ['DART_CRASHPAD_CRASHES_DIR'] = WindowsCoreDumpEnabler.CRASHPAD_DB_FOLDER
 
   def __exit__(self, *_):
@@ -808,7 +811,7 @@
   try:
     os.unlink(file)
   except Exception as error:
-    print "ERROR: Failed to remove %s: %s" % (file, error)
+    print ("ERROR: Failed to remove %s: %s" % (file, error))
 
 
 class BaseCoreDumpArchiver(object):
@@ -830,15 +833,15 @@
     try:
       return self._cleanup();
     except Exception as error:
-      print "ERROR: Failure during cleanup: %s" % error
+      print ("ERROR: Failure during cleanup: %s" % error)
       return False
 
   def __enter__(self):
-    print "INFO: Core dump archiving is activated"
+    print ("INFO: Core dump archiving is activated")
 
     # Cleanup any stale files
     if self._safe_cleanup():
-      print "WARNING: Found and removed stale coredumps"
+      print ("WARNING: Found and removed stale coredumps")
 
   def __exit__(self, *_):
     try:
@@ -846,23 +849,23 @@
       if crashes:
         # If we get a ton of crashes, only archive 10 dumps.
         archive_crashes = crashes[:10]
-        print 'Archiving coredumps for crash (if possible):'
+        print ('Archiving coredumps for crash (if possible):')
         for crash in archive_crashes:
-          print '----> %s' % crash
+          print ('----> %s' % crash)
 
         sys.stdout.flush()
 
         self._archive(archive_crashes)
       else:
-        print "INFO: No unexpected crashes recorded"
+        print ("INFO: No unexpected crashes recorded")
         dumps = self._find_all_coredumps()
         if dumps:
-          print "INFO: However there are %d core dumps found" % len(dumps)
+          print ("INFO: However there are %d core dumps found" % len(dumps))
           for dump in dumps:
-            print "INFO:        -> %s" % dump
-          print
+            print ("INFO:        -> %s" % dump)
+          print ()
     except Exception as error:
-      print "ERROR: Failed to archive crashes: %s" % error
+      print ("ERROR: Failed to archive crashes: %s" % error)
       raise
 
     finally:
@@ -902,10 +905,10 @@
   def _report_missing_crashes(self, missing, throw=True):
     missing_as_string = ', '.join([str(c) for c in missing])
     other_files = list(glob.glob(os.path.join(self._search_dir, '*')))
-    print >> sys.stderr, (
+    sys.stderr.write(
         "Could not find crash dumps for '%s' in search directory '%s'.\n"
         "Existing files which *did not* match the pattern inside the search "
-        "directory are are:\n  %s"
+        "directory are are:\n  %s\n"
         % (missing_as_string, self._search_dir, '\n  '.join(other_files)))
     # TODO: Figure out why windows coredump generation does not work.
     # See http://dartbug.com/36469
@@ -927,7 +930,7 @@
 
   def _move(self, files):
     for file in files:
-      print '+++ Moving %s to output_directory (%s)' % (file, self._output_directory)
+      print ('+++ Moving %s to output_directory (%s)' % (file, self._output_directory))
       (name, is_binary) = self._get_file_name(file)
       destination = os.path.join(self._output_directory, name)
       shutil.move(file, destination)
@@ -956,7 +959,7 @@
     gs_prefix = 'gs://%s' % storage_path
     http_prefix = 'https://storage.cloud.google.com/%s' % storage_path
 
-    print '\n--- Uploading into %s (%s) ---' % (gs_prefix, http_prefix)
+    print ('\n--- Uploading into %s (%s) ---' % (gs_prefix, http_prefix))
     for file in files:
       tarname = self._tar(file)
 
@@ -966,13 +969,13 @@
 
       try:
         gsutil.upload(tarname, gs_url)
-        print '+++ Uploaded %s (%s)' % (gs_url, http_url)
+        print ('+++ Uploaded %s (%s)' % (gs_url, http_url))
       except Exception as error:
-        print '!!! Failed to upload %s, error: %s' % (tarname, error)
+        print ('!!! Failed to upload %s, error: %s' % (tarname, error))
 
       TryUnlink(tarname)
 
-    print '--- Done ---\n'
+    print ('--- Done ---\n')
 
   def _find_all_coredumps(self):
     """Return coredumps that were recorded (if supported by the platform).
@@ -1069,10 +1072,10 @@
     if not dumps:
       return
 
-    print "### Collected %d crash dumps" % len(dumps)
+    print ("### Collected %d crash dumps" % len(dumps))
     for dump in dumps:
-      print
-      print "### Dumping stacks from %s using CDB" % dump
+      print ()
+      print ("### Dumping stacks from %s using CDB" % dump)
       cdb_output = subprocess.check_output(
           '"%s" -z "%s" -kqm -c "!uniqstack -b -v -p;qd"' % (cdb_path, dump),
           stderr=subprocess.STDOUT)
@@ -1084,17 +1087,17 @@
         elif line.startswith("quit:"):
           break
         elif output:
-          print line
-    print
-    print "#############################################"
-    print
+          print (line)
+    print ()
+    print ("#############################################")
+    print ()
 
 
   def __exit__(self, *args):
     try:
       self._dump_all_stacks()
     except Exception as error:
-      print "ERROR: Unable to dump stacks from dumps: %s" % error
+      print ("ERROR: Unable to dump stacks from dumps: %s" % error)
 
     super(WindowsCoreDumpArchiver, self).__exit__(*args)
 
diff --git a/utils/application_snapshot.gni b/utils/application_snapshot.gni
index e577331..2c257a2 100644
--- a/utils/application_snapshot.gni
+++ b/utils/application_snapshot.gni
@@ -176,49 +176,3 @@
     forward_variables_from(invoker, "*")
   }
 }
-
-template("aot_assembly") {
-  assert(defined(invoker.main_dart), "Must specify 'main_dart'")
-  aot_vm_args = []
-  if (defined(invoker.vm_args)) {
-    aot_vm_args = invoker.vm_args
-  }
-  main_dart = invoker.main_dart
-  aot_vm_args = aot_vm_args + [ rebase_path("$main_dart") ]
-  name = target_name
-  if (defined(invoker.name)) {
-    name = invoker.name
-  }
-  extra_deps = []
-  if (defined(invoker.deps)) {
-    extra_deps += invoker.deps
-  }
-  extra_inputs = [ main_dart ]
-  if (defined(invoker.inputs)) {
-    extra_inputs += invoker.inputs
-  }
-  output = "$root_gen_dir/$name.dart.S"
-  if (defined(invoker.output)) {
-    output = invoker.output
-  }
-  gen_snapshot_action(target_name) {
-    deps = extra_deps
-    depfile = "$output.d"
-
-    inputs = extra_inputs
-
-    outputs = [
-      output,
-    ]
-
-    abs_output = rebase_path(output, root_build_dir)
-
-    vm_args = [
-      "--deterministic",
-      "--snapshot-kind=app-aot-assembly",
-      "--assembly=$abs_output",
-    ] + aot_vm_args
-
-    args = []
-  }
-}
diff --git a/utils/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index 53cf818..5cd62a0 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -20,6 +20,8 @@
 import 'package:kernel/ast.dart' show Component, Library;
 import 'package:kernel/target/targets.dart';
 import 'package:vm/target/vm.dart';
+import 'package:vm/target/flutter.dart';
+import 'package:vm/target/flutter_runner.dart';
 import 'package:compiler/src/kernel/dart2js_target.dart';
 
 main(List<String> args) async {
@@ -53,24 +55,11 @@
       } else {
         previousState = null;
       }
-      ComputeKernelResult result;
-      // TODO(vsm): See https://github.com/dart-lang/sdk/issues/36644.
-      // If the CFE is crashing with previous state, then clear compilation
-      // state and try again.
-      try {
-        result = await computeKernel(request.arguments,
-            isWorker: true,
-            outputBuffer: outputBuffer,
-            inputs: request.inputs,
-            previousState: previousStateToPass);
-      } catch (_) {
-        outputBuffer.clear();
-        result = await computeKernel(request.arguments,
-            isWorker: true,
-            outputBuffer: outputBuffer,
-            inputs: request.inputs,
-            previousState: null);
-      }
+      var result = await computeKernel(request.arguments,
+          isWorker: true,
+          outputBuffer: outputBuffer,
+          inputs: request.inputs,
+          previousState: previousStateToPass);
       previousState = result.previousState;
       if (!result.succeeded) {
         response.exitCode = 15;
@@ -120,8 +109,14 @@
       negatable: true,
       help: 'Whether to only build summary files.')
   ..addOption('target',
-      allowed: const ['vm', 'dart2js', 'ddc'],
-      help: 'Build kernel for the vm, dart2js, or ddc')
+      allowed: const [
+        'vm',
+        'flutter',
+        'flutter_runner',
+        'dart2js',
+        'ddc',
+      ],
+      help: 'Build kernel for the vm, flutter, flutter_runner, dart2js or ddc')
   ..addOption('dart-sdk-summary')
   ..addMultiOption('input-summary')
   ..addMultiOption('input-linked')
@@ -132,7 +127,10 @@
   ..addMultiOption('source')
   ..addOption('output')
   ..addFlag('reuse-compiler-result', defaultsTo: false)
-  ..addFlag('use-incremental-compiler', defaultsTo: false);
+  ..addFlag('use-incremental-compiler', defaultsTo: false)
+  ..addFlag('track-widget-creation', defaultsTo: false)
+  ..addMultiOption('enable-experiment',
+      help: 'Enable a language experiment when invoking the CFE.');
 
 class ComputeKernelResult {
   final bool succeeded;
@@ -171,16 +169,17 @@
   if (multiRoots.isEmpty) multiRoots.add(Uri.base);
   var fileSystem = new MultiRootFileSystem(parsedArgs['multi-root-scheme'],
       multiRoots, fe.StandardFileSystem.instance);
-  var sources =
-      (parsedArgs['source'] as List<String>).map(Uri.base.resolve).toList();
+  var sources = (parsedArgs['source'] as List<String>).map(_toUri).toList();
   var excludeNonSources = parsedArgs['exclude-non-sources'] as bool;
 
   var summaryOnly = parsedArgs['summary-only'] as bool;
+  var trackWidgetCreation = parsedArgs['track-widget-creation'] as bool;
+
   // TODO(sigmund,jakemac): make target mandatory. We allow null to be backwards
   // compatible while we migrate existing clients of this tool.
   var targetName =
       (parsedArgs['target'] as String) ?? (summaryOnly ? 'ddc' : 'vm');
-  var targetFlags = new TargetFlags();
+  var targetFlags = new TargetFlags(trackWidgetCreation: trackWidgetCreation);
   Target target;
   switch (targetName) {
     case 'vm':
@@ -189,6 +188,20 @@
         out.writeln('error: --summary-only not supported for the vm target');
       }
       break;
+    case 'flutter':
+      target = new FlutterTarget(targetFlags);
+      if (summaryOnly) {
+        throw new ArgumentError(
+            'error: --summary-only not supported for the flutter target');
+      }
+      break;
+    case 'flutter_runner':
+      target = new FlutterRunnerTarget(targetFlags);
+      if (summaryOnly) {
+        throw new ArgumentError('error: --summary-only not supported for the '
+            'flutter_runner target');
+      }
+      break;
     case 'dart2js':
       target = new Dart2jsTarget('dart2js', targetFlags);
       if (summaryOnly) {
@@ -199,7 +212,8 @@
     case 'ddc':
       // TODO(jakemac):If `generateKernel` changes to return a summary
       // component, process the component instead.
-      target = new DevCompilerSummaryTarget(sources, excludeNonSources);
+      target =
+          new DevCompilerSummaryTarget(sources, excludeNonSources, targetFlags);
       if (!summaryOnly) {
         out.writeln('error: --no-summary-only not supported for the '
             'ddc target');
@@ -209,23 +223,17 @@
       out.writeln('error: unsupported target: $targetName');
   }
 
-  // TODO(sigmund,jakemac): make it mandatory. We allow null while we migrate
-  // existing clients of this tool.
-  var librariesSpec = parsedArgs['libraries-file'] == null
-      ? null
-      : Uri.base.resolve(parsedArgs['libraries-file']);
+  List<Uri> linkedInputs =
+      (parsedArgs['input-linked'] as List<String>).map(_toUri).toList();
 
-  List<Uri> linkedInputs = (parsedArgs['input-linked'] as List<String>)
-      .map(Uri.base.resolve)
-      .toList();
-
-  List<Uri> summaryInputs = (parsedArgs['input-summary'] as List<String>)
-      .map(Uri.base.resolve)
-      .toList();
+  List<Uri> summaryInputs =
+      (parsedArgs['input-summary'] as List<String>).map(_toUri).toList();
 
   fe.InitializedCompilerState state;
   bool usingIncrementalCompiler = false;
-  if (parsedArgs['use-incremental-compiler'] && linkedInputs.isEmpty) {
+  if (parsedArgs['use-incremental-compiler'] &&
+      linkedInputs.isEmpty &&
+      isWorker) {
     usingIncrementalCompiler = true;
 
     /// Build a map of uris to digests.
@@ -238,27 +246,30 @@
       inputDigests[uri] = input.digest;
     }
 
+    // TODO(sigmund): add support for experiments with the incremental compiler.
     state = await fe.initializeIncrementalCompiler(
         previousState,
-        Uri.base.resolve(parsedArgs['dart-sdk-summary']),
-        Uri.base.resolve(parsedArgs['packages-file']),
-        librariesSpec,
+        _toUri(parsedArgs['dart-sdk-summary']),
+        _toUri(parsedArgs['packages-file']),
+        _toUri(parsedArgs['libraries-file']),
         summaryInputs,
         inputDigests,
         target,
         fileSystem,
+        (parsedArgs['enable-experiment'] as List<String>),
         summaryOnly);
   } else {
     state = await fe.initializeCompiler(
         // TODO(sigmund): pass an old state once we can make use of it.
         null,
-        Uri.base.resolve(parsedArgs['dart-sdk-summary']),
-        librariesSpec,
-        Uri.base.resolve(parsedArgs['packages-file']),
+        _toUri(parsedArgs['dart-sdk-summary']),
+        _toUri(parsedArgs['libraries-file']),
+        _toUri(parsedArgs['packages-file']),
         summaryInputs,
         linkedInputs,
         target,
-        fileSystem);
+        fileSystem,
+        (parsedArgs['enable-experiment'] as List<String>));
   }
 
   void onDiagnostic(fe.DiagnosticMessage message) {
@@ -278,14 +289,25 @@
         incrementalComponent.problemsAsJson = null;
         incrementalComponent.mainMethod = null;
         target.performOutlineTransformations(incrementalComponent);
+        return Future.value(fe.serializeComponent(incrementalComponent,
+            includeSources: false, includeOffsets: false));
       }
 
       return Future.value(fe.serializeComponent(incrementalComponent));
     });
+  } else if (summaryOnly) {
+    kernel = await fe.compileSummary(state, sources, onDiagnostic,
+        includeOffsets: false);
   } else {
-    kernel = await fe.compile(state, sources, onDiagnostic,
-        summaryOnly: summaryOnly);
+    Component component =
+        await fe.compileComponent(state, sources, onDiagnostic);
+    kernel = fe.serializeComponent(component,
+        filter: excludeNonSources
+            ? (library) => sources.contains(library.importUri)
+            : null,
+        includeOffsets: true);
   }
+  state.options.onDiagnostic = null; // See http://dartbug.com/36983.
 
   if (kernel != null) {
     var outputFile = new File(parsedArgs['output']);
@@ -314,7 +336,9 @@
   final List<Uri> sources;
   final bool excludeNonSources;
 
-  DevCompilerSummaryTarget(this.sources, this.excludeNonSources);
+  DevCompilerSummaryTarget(
+      this.sources, this.excludeNonSources, TargetFlags targetFlags)
+      : super(targetFlags);
 
   @override
   void performOutlineTransformations(Component component) {
@@ -338,3 +362,8 @@
     }
   }
 }
+
+Uri _toUri(String uriString) {
+  if (uriString == null) return null;
+  return Uri.base.resolve(uriString);
+}
diff --git a/utils/dartanalyzer/BUILD.gn b/utils/dartanalyzer/BUILD.gn
index ad45cf1..7665d74 100644
--- a/utils/dartanalyzer/BUILD.gn
+++ b/utils/dartanalyzer/BUILD.gn
@@ -31,65 +31,6 @@
   name = "dartanalyzer"
 }
 
-if (current_os == "linux") {
-  prebuilt_dart_action("dart_analyzer_dill") {
-    deps = [
-      "../../runtime/vm:vm_platform",
-      "../../runtime/vm:kernel_platform_files($dart_host_toolchain)",
-    ]
-    dart_analyzer_script = "../../pkg/vm/bin/kernel_service.dart"
-    gen_kernel_script = "../../pkg/vm/bin/gen_kernel.dart"
-
-    inputs = [
-      gen_kernel_script,
-      dart_analyzer_script,
-      "$root_out_dir/vm_platform_strong.dill",
-    ]
-    output = "$root_gen_dir/dart_analyzer.dill"
-    outputs = [
-      output,
-    ]
-
-    depfile = "$root_gen_dir/dart_analyzer_dill.d"
-    abs_depfile = rebase_path(depfile)
-    rebased_output = rebase_path(output, root_out_dir)
-    vm_args = [
-      "--depfile=$abs_depfile",
-      "--depfile_output_filename=$rebased_output",
-    ]
-
-    script = gen_kernel_script
-
-    args = [
-      "--packages=" + rebase_path("../../.packages"),
-      "--platform=" + rebase_path("$root_out_dir/vm_platform_strong.dill"),
-      "--aot",
-      "--no-embed-sources",
-      "--output=" + rebase_path("$root_gen_dir/dart_analyzer.dill"),
-      rebase_path(dart_analyzer_script),
-    ]
-  }
-
-  aot_assembly("dartanalyzer_aot_assembly") {
-    main_dart = "$root_gen_dir/dart_analyzer.dill"
-    name = "dartanalyzer"
-    deps = [
-      ":dart_analyzer_dill"
-    ]
-  }
-
-  # This target is for Goma. It should not be used in the SDK.
-  executable("dartanalyzer_aot") {
-    deps = [
-      "../../runtime/bin:dart_precompiled_runtime_for_linking",
-      ":dartanalyzer_aot_assembly",
-    ]
-    sources = [
-      "$root_gen_dir/dartanalyzer.dart.S"
-    ]
-  }
-}
-
 sdk_lib_files = exec_script("../../tools/list_dart_files.py",
                             [
                               "absolute",
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index 767bdb9..e56bbfd 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -18,7 +18,7 @@
     "--dart-sdk",
     rebase_path("../../sdk"),
     "--dart-sdk-summary",
-    rebase_path(sdk_summary),
+    rebase_path(sdk_dill),
     "-k",
     "-o",
     "dartdevc.js",
@@ -124,7 +124,7 @@
   inputs += exec_script("../../tools/list_dart_files.py",
                         [
                           "absolute",
-                          rebase_path("../../pkg/dev_compiler/tool/input_sdk"),
+                          rebase_path("../../sdk/lib/_internal/js_dev_runtime"),
                         ],
                         "list lines")
 
@@ -137,7 +137,7 @@
 
   args = [
     rebase_path("../../"),
-    rebase_path("../../pkg/dev_compiler/tool/input_sdk"),
+    rebase_path("../../sdk/lib/_internal/js_dev_runtime"),
     rebase_path(patched_sdk_dir),
   ]
 }
@@ -233,7 +233,7 @@
 }
 
 create_timestamp_file("dartdevc_sdk_patch_stamp") {
-  path = rebase_path("../../pkg/dev_compiler/tool/input_sdk")
+  path = rebase_path("../../sdk/lib/_internal/js_dev_runtime")
   output = "$target_gen_dir/dartdevc_sdk_patch_stamp.stamp"
 }